]> git.neil.brown.name Git - history.git/commitdiff
[tytso] include/asm-i386/posix_types.h 2.1.104
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:38 +0000 (15:15 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:15:38 +0000 (15:15 -0500)
This quick fix eliminates a lot of warning messages when
compiling e2fsprogs under glibc.  This is because the glibc header files
defines its own version of FD_SET, FD_ZERO, etc., and so if you need to
#include the kernel include files, you get a lot of duplicate defined
macro warning messages.  This patch simply #ifdef's out the kernel
versions of these function if the kernel is not being compiled and the
glibc header files are in use.

58 files changed:
CREDITS
Documentation/00-INDEX
Documentation/cdrom/00-INDEX
Documentation/filesystems/00-INDEX
Documentation/initrd.txt
Documentation/m68k/framebuffer.txt
Documentation/networking/filter.txt
Documentation/networking/multicast.txt
Documentation/rtc.txt
Documentation/smart-config.txt
Documentation/sysrq.txt
MAINTAINERS
arch/i386/kernel/process.c
arch/i386/kernel/smp.c
drivers/char/cyclades.c
drivers/char/lp.c
drivers/char/random.c
drivers/char/serial.c
drivers/char/tty_io.c
drivers/scsi/BusLogic.c
drivers/scsi/README.aic7xxx
drivers/scsi/aha1542.c
drivers/scsi/aic7xxx.c
drivers/scsi/aic7xxx_proc.c
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/fdomain.c
drivers/scsi/fdomain.h
drivers/scsi/scsi_ioctl.c
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
fs/buffer.c
fs/coda/cache.c
fs/coda/cnode.c
fs/coda/coda_linux.c
fs/coda/dir.c
fs/coda/file.c
fs/coda/inode.c
fs/coda/psdev.c
fs/coda/stats.c
fs/coda/upcall.c
fs/proc/procfs_syms.c
fs/stat.c
include/asm-i386/posix_types.h
include/asm-i386/spinlock.h
include/asm-i386/user.h
include/linux/coda.h
include/linux/coda_linux.h
include/linux/cyclades.h
include/linux/sched.h
include/linux/serial_reg.h
include/linux/socket.h
include/linux/stat.h
kernel/sched.c
kernel/sys.c
net/ipv4/syncookies.c
net/ipx/af_spx.c
scripts/ksymoops.cc

diff --git a/CREDITS b/CREDITS
index 0d9b63fedfe1a96d2b7c9cee467afe55dd518562..43d2fded33d9a2c895dddb3e9499e38c15dcfb70 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -467,7 +467,7 @@ S: Italy
 
 N: Rik Faith
 E: faith@cs.unc.edu
-E: r.faith@ieee.org
+E: faith@acm.org
 D: Author: Future Domain TMC-16x0 SCSI driver
 D: Debugging: SCSI code; Cyclades serial driver; APM driver
 D: Debugging: XFree86 Mach 32 server, accelerated server code
index fd986e95ca93fd4d2598ff65e2989287e86f19f5..18ec845df83901dbf52e50d5bd337338a76f50bb 100644 (file)
@@ -1,7 +1,8 @@
 This is a brief list of all the files in ./linux/Documentation and what
 they contain. If you add a documentation file, please list it here in 
 alphabetical order as well, or risk being hunted down like a rabid dog. 
-Note that subdirectories have their own index files too.
+Note that subdirectories have their own index files too. Please try and
+keep the descriptions small enough to fit on one line.
                                                         Thanks -- Paul G.
 
 00-INDEX
@@ -56,6 +57,8 @@ java.txt
        - info on the in-kernel binary support for Java(tm)
 joystick.txt
        - info on using joystick devices (and driver) with linux.
+kmod.txt
+       - - info on the kernel module loader/unloader (kerneld replacement)
 locks.txt
        - info on file locking implementations, flock() vs. fcntl(), etc.
 logo.gif
@@ -76,6 +79,8 @@ memory.txt
        - info on typical Linux memory problems.
 modules.txt
        - short guide on how to make kernel parts into loadable modules
+mtrr.txt
+       - how to use PPro Memory Type Range Registers to increase performance
 nbd.txt
        - info on a TCP implementation of a network block device.
 networking/
index c8b428bf19171724cf081fed3731a249ec1e8771..eae6896676f2079266003d1edcc7930dc155b5eb 100644 (file)
@@ -1,8 +1,9 @@
 00-INDEX
        - this file (info on CD-ROMs and Linux)
+Makefile
+       - only used to generate TeX output from the documentation.
 aztcd
        - info on Aztech/Orchid/Okano/Wearnes/Conrad/CyCDROM driver.
-
 cdrom-standard.tex
        - LaTeX document on standardizing the CD-ROM programming interface.
 cdu31a
index 679904d0b8d16c562a9881ba0540740919ef39b3..0b88a67556d5c6711acb0178696a4717b74e4063 100644 (file)
@@ -5,8 +5,7 @@ affs.txt
 coda.txt
        - description of the CODA filesystem.
 fat_cvf.txt
-       - Description of the Compressed Volume Files extension to the FAT
-         filesystem
+       - info on the Compressed Volume Files extension to the FAT filesystem
 hpfs.txt
        - info and mount options for the OS/2 HPFS.
 isofs.txt
index 220fcb150f3a3451e2bbb17fe778d06b44ac32a0..d5680b389775482b3ceb9717abcf2fb0f8cd17e6 100644 (file)
@@ -93,7 +93,7 @@ Installation
 
 First, the "normal" root file system has to be prepared as follows:
 
-# mknod /dev/initrd b 0 250 
+# mknod /dev/initrd b 1 250 
 # chmod 400 /dev/initrd
 # mkdir /initrd
 
index c5b77d077339151842074d7ed7414cc299f7c009..858fdd211e62ff30f497874f52be4488af242f8e 100644 (file)
@@ -315,7 +315,7 @@ applications, please refer to the following documentation:
 
 All necessary files can be found at
 
-    ftp://ftp.uni-erlangen.de/pub/Linux/LOCAL/680x0/
+    ftp://ftp.uni-erlangen.de/pub/Linux/680x0/
 
 and on its mirrors.
 
index 370cb92f866a8625bc4c48c7437312e14b1fa28c..be865f352f1c4893e74982c4744ff04f39a47c56 100644 (file)
@@ -15,7 +15,7 @@ the same filter code structure as the BSD Berkeley Packet Filter
 (BPF), so refering to the BSD bpf.4 manpage is very helpful in
 creating filters.
 
-LSF is much simpler that BPF. One does not have to worry about
+LSF is much simpler than BPF. One does not have to worry about
 devices or anything like that. You simply create your filter
 code, send it to the kernel via the SO_ATTACH_FILTER ioctl and
 if your filter code passes the kernel check on it, you then
index a8539007aaa0b9fc63ffb854d21e07c4f19e9038..2bd6fd9ba7a7f4cbe8b6817fcafd1a3f75bb5b91 100644 (file)
@@ -1,6 +1,5 @@
 Behaviour of cards under Multicast. This is how they currently 
-behave not what the hardware can do. In particular all the 8390 based
-cards don't use the onboard hash filter, and the lance driver doesn't
+behave not what the hardware can do - i.e. the lance driver doesn't
 use its filter, even though the code for loading it is in the DEC
 lance based driver.
 
index e290b4177750eeba9a6562b11bd2c529b8461ac0..7718228ba5519563409c50702d070b9ea3d3e1b1 100644 (file)
@@ -129,7 +129,7 @@ fprintf(stderr, "\nAgain, from using select(2) on /dev/rtc:");
 fflush(stderr);
 for (i=1; i<6; i++) {
        struct timeval tv = {5, 0};     /* 5 second timeout on select */
-       struct fd_set readfds;
+       fd_set readfds;
 
        FD_ZERO(&readfds);
        FD_SET(fd, &readfds);
index eda5c3dfaa001f2650fcd1466196db83adaff7e2..b31d252fa5077d58f56182c8f30eb8944d4b3af6 100644 (file)
@@ -72,14 +72,12 @@ Flag Dependencies
     modular, 'make' will notice that the foo.o was not compiled
     with -DMODULE and will recompile foo.c.
 
-    Flag dependencies also work with per-source-file flags such
-    as those in drivers/net/CONFIG.
-
     All .a and .o files made from C source or with 'ld' or 'ar'
     have flag dependencies.  .S files do not have flag dependencies.
 
 Per-source-file Flags
 
+    Flag dependencies also work with per-source-file flags.
     You can specify compilation flags for individual source files
     like this:
 
index 44e0f47578874572c9dbb9eb28bf507cc14bff13..78ab20c4b568a46680697c8b510f2b0aa480e9fb 100644 (file)
@@ -46,7 +46,7 @@ On other - If you know of the key combos for other architectures, please
 
 'm'     - Will dump current memory info to your console.
 
-'0'-'8' - Sets the console log level, controlling which kernel messages
+'0'-'9' - Sets the console log level, controlling which kernel messages
           will be printed to your console. ('0', for example would make
           it so that only emergency messages like PANICs or OOPSes would
           make it to your console.)
@@ -69,12 +69,17 @@ re'B'oot is good when you're unable to shut down. But you should also 'S'ync
 and 'U'mount first.
 
 'S'ync is great when your system is locked up, it allows you to sync your
-disks and will certainly lessen the chance of data loss and fscking.
+disks and will certainly lessen the chance of data loss and fscking. Note
+that the sync hasn't taken place until you see the "OK" and "Done" appear 
+on the screen. (If the kernel is really in strife, you may not ever get the
+OK or Done message...)
 
 'U'mount is basically useful in the same ways as 'S'ync. I generally 'S'ync,
 'U'mount, then re'B'oot when my system locks. It's saved me many a fsck.
+Again, the unmount (remount read-only) hasn't taken place until you see the
+"OK" and "Done" message appear on the screen.
 
-The loglevel'0'-'8' is useful when your console is being flooded with
+The loglevel'0'-'9' is useful when your console is being flooded with
 kernel messages you do not want to see. Setting '0' will prevent all but
 the most urgent kernel messages from reaching your console. (They will
 still be logged if syslogd/klogd are alive, though.)
@@ -87,7 +92,8 @@ processes.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 That happens to me, also. I've found that tapping shift, alt, and control
 on both sides of the keyboard, and hitting an invalid sysrq sequence again
-will fix the problem. (ie, something like alt-sysrq-z).
+will fix the problem. (ie, something like alt-sysrq-z). Switching to another
+virtual console (ALT+Fn) and then back again should also help.
 
 *  I hit SysRQ, but nothing seems to happen, what's wrong?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index ce385f558ad267c30c68c14c0a726ab4be9f62ca..f12bade7752bc81d34931d3196e3f411cd931b58 100644 (file)
@@ -107,8 +107,8 @@ L:  linux-scsi@vger.rutgers.edu
 S:     Maintained
 
 APM DRIVER
-P:     Rik Faith & Stephen Rothwell
-M:     faith@cs.unc.edu, Stephen.Rothwell@canb.auug.org.au
+P:     Stephen Rothwell
+M:     Stephen.Rothwell@canb.auug.org.au
 L:     linux-laptop@vger.rutgers.edu
 S:     Maintained
 
index afcd8f3ec92c13fc433dd4a3612603da99179ad8..2c5de4f2a44b8ee90c2054d3b4ac203c451778d5 100644 (file)
@@ -46,6 +46,8 @@
 #endif
 #include "irq.h"
 
+spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
+
 struct task_struct *last_task_used_math = NULL;
 
 #ifdef __SMP__
index dc6b2144acf2faf141b20308d84fe48bcffa3113..2403da1727c2eecfe966273c4c0d163d8c33db5a 100644 (file)
@@ -57,8 +57,6 @@
 
 #include "irq.h"
 
-spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
-
 extern unsigned long start_kernel, _etext;
 extern void update_one_process( struct task_struct *p,
                                unsigned long ticks, unsigned long user,
index c7440eb91971aedf6d75ad134ea450b2bd33ca4c..2e0172bbe7538da0ff1cefa015846ca5b8d1d1e6 100644 (file)
@@ -1,9 +1,7 @@
 #define BLOCKMOVE
-#define        NEW_INTR_FLOW
 #define        Z_WAKE
-#define        NEW_PCI
 static char rcsid[] =
-"$Revision: 2.2.1.1 $$Date: 1998/03/19 16:43:12 $";
+"$Revision: 2.2.1.3 $$Date: 1998/06/01 12:09:10 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -33,6 +31,13 @@ static char rcsid[] =
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.2.1.3  1998/06/01 12:09:10 ivan
+ * General code review in order to comply with 2.1 kernel standards;
+ * data loss prevention for slow devices revisited (cy_wait_until_sent
+ * was created);
+ * removed conditional compilation for new/old PCI structure support 
+ * (now the driver only supports the new PCI structure).
+ *
  * Revision 2.2.1.1  1998/03/19 16:43:12 ivan
  * added conditional compilation for new/old PCI structure support;
  * removed kernel series (2.0.x / 2.1.x) conditional compilation.
@@ -40,7 +45,7 @@ static char rcsid[] =
  * Revision 2.1.1.3  1998/03/16 18:01:12 ivan
  * cleaned up the data loss fix;
  * fixed XON/XOFF handling once more (Cyclades-Z);
- * general revision in the driver routines;
+ * general review of the driver routines;
  * introduction of a mechanism to prevent data loss with slow 
  * printers, by forcing a delay before closing the port.
  *
@@ -482,14 +487,15 @@ static char rcsid[] =
 #define ZE_V1  2
 
 #define        SERIAL_PARANOIA_CHECK
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_THROTTLE
-#undef SERIAL_DEBUG_OTHER
-#undef SERIAL_DEBUG_IO
-#undef SERIAL_DEBUG_COUNT
-#undef SERIAL_DEBUG_DTR
-#undef CYCLOM_16Y_HACK
-#undef CYCLOM_ENABLE_MONITORING
+#undef CY_DEBUG_OPEN
+#undef CY_DEBUG_THROTTLE
+#undef CY_DEBUG_OTHER
+#undef CY_DEBUG_IO
+#undef CY_DEBUG_COUNT
+#undef CY_DEBUG_DTR
+#undef CY_DEBUG_WAIT_UNTIL_SENT
+#undef CY_16Y_HACK
+#undef CY_ENABLE_MONITORING
 #undef CY_PCI_DEBUG
 
 #if 0
@@ -519,40 +525,38 @@ static char rcsid[] =
                  (cy_readl(&buf_ctrl->tx_bufsize) - 1))
 #endif
 
+/*
+ * Include section 
+ */
+#include <linux/config.h>
 #include <linux/module.h>
-
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/serial.h>
-#include <linux/interrupt.h>
+#include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/cyclades.h>
-#include <linux/delay.h>
-#include <linux/major.h>
 #include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/segment.h>
+#include <asm/irq.h>
+#include <asm/uaccess.h>
 #include <asm/bitops.h>
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#ifndef NEW_PCI
-#include <linux/bios32.h>
-#endif
 #include <linux/pci.h>
-
 #include <linux/version.h>
 
-#include <asm/uaccess.h>
-#include <linux/init.h>
 
 #define cy_put_user    put_user
 
@@ -585,19 +589,16 @@ static unsigned long cy_get_user(unsigned long *addr)
 
 #define STD_COM_FLAGS (0)
 
-#define SERIAL_TYPE_NORMAL  1
-#define SERIAL_TYPE_CALLOUT 2
-
 static DECLARE_TASK_QUEUE(tq_cyclades);
 
 static struct tty_driver cy_serial_driver, cy_callout_driver;
+static int serial_refcount;
 
 static volatile int cy_irq_triggered;
 static volatile int cy_triggered;
 static int cy_wild_int_mask;
 static volatile ucchar *intr_base_addr;
 
-
 /* This is the address lookup table. The driver will probe for
    Cyclom-Y/ISA boards at all addresses in here. If you want the
    driver to probe addresses at a different address, add it to
@@ -632,8 +633,6 @@ static struct cyclades_port cy_port[NR_PORTS];
 
 static int cy_next_channel = 0; /* next minor available */
 
-static int serial_refcount;
-
 static struct tty_struct *serial_table[NR_PORTS];
 static struct termios *serial_termios[NR_PORTS];
 static struct termios *serial_termios_locked[NR_PORTS];
@@ -641,8 +640,7 @@ static struct termios *serial_termios_locked[NR_PORTS];
 /* This is the per-irq data structure,
    it maps an irq to the corresponding card */
 
-static struct cyclades_card     *IRQ_cards[16];
-
+static struct cyclades_card     *IRQ_cards[NR_IRQS];
 
 /*
  * tmp_buf is used as a temporary buffer by serial_write.  We need to
@@ -654,7 +652,7 @@ static struct cyclades_card     *IRQ_cards[16];
  * memory if large numbers of serial ports are open.  This buffer is
  * allocated when the first cy_open occurs.
  */
-static unsigned char *tmp_buf = 0;
+static unsigned char *tmp_buf;
 static struct semaphore tmp_buf_sem = MUTEX;
 
 /*
@@ -799,41 +797,6 @@ serial_paranoia_check(struct cyclades_port *info,
         return 0;
 } /* serial_paranoia_check */
 
-
-/* The following diagnostic routines allow the driver to spew
-   information on the screen, even (especially!) during interrupts.
- */
-static void
-SP(char *data){
-  unsigned long flags;
-    save_flags(flags); cli();
-        console_print(data);
-    restore_flags(flags);
-}/* SP */
-
-static void
-CP(char data){
-  unsigned long flags;
-  char scrn[2];
-    save_flags(flags); cli();
-        scrn[0] = data;
-        scrn[1] = '\0';
-        console_print(scrn);
-    restore_flags(flags);
-}/* CP */
-
-static void CP4(int data)
-    { (data<10)?  CP(data+'0'): CP(data+'A'-10); }/* CP4 */
-static void CP8(int data)
-    { CP4((data>>4) & 0x0f); CP4( data & 0x0f); }/* CP8 */
-#if 0
-static void CP16(int data)
-    { CP8((data>>8) & 0xff); CP8(data & 0xff); }/* CP16 */
-static void CP32(long data)
-    { CP16((data>>16) & 0xffff); CP16(data & 0xffff); }/* CP32 */
-#endif
-
-
 /*
  * This routine is used by the interrupt handler to schedule
  * processing in the software interrupt portion of the driver
@@ -1125,11 +1088,6 @@ cy_probe(int irq, void *dev_id, struct pt_regs *regs)
         if(cy_readb(intr_base_addr+(CySVRR<<index)) != 0) {
             save_xir = (u_char) cy_readb(intr_base_addr+(CyTIR<<index));
             save_car = cy_readb(intr_base_addr+(CyCAR<<index));
-            if ((save_xir & 0x3) != 0){
-                SP("channel ");
-                CP8(save_xir);
-                SP(" requesting unexpected interrupt\n");
-            }
             cy_writeb((u_long)intr_base_addr+(CyCAR<<index), (save_xir & 0x3));
             cy_writeb((u_long)intr_base_addr+(CySRER<<index),
                 cy_readb(intr_base_addr+(CySRER<<index)) & ~CyTxMpty);
@@ -1286,7 +1244,7 @@ printk("cy_interrupt: rcvd intr, chip %d\n\r", chip);
                             /* load # chars available from the chip */
                             char_count = cy_readb(base_addr+(CyRDCR<<index));
 
-#ifdef CYCLOM_ENABLE_MONITORING
+#ifdef CY_ENABLE_MONITORING
                             ++info->mon.int_count;
                             info->mon.char_count += char_count;
                             if (char_count > info->mon.char_max)
@@ -1301,7 +1259,7 @@ printk("cy_interrupt: rcvd intr, chip %d\n\r", chip);
                                 data = cy_readb(base_addr+(CyRDSR<<index));
                                 *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
                                 *tty->flip.char_buf_ptr++ = data;
-#ifdef CYCLOM_16Y_HACK
+#ifdef CY_16Y_HACK
                                 udelay(10L);
 #endif
                             }
@@ -1387,11 +1345,9 @@ printk("cy_interrupt: xmit intr, chip %d\n\r", chip);
                         info->x_break = 0;
                     }
 
-#ifdef NEW_INTR_FLOW
                     if (!info->xmit_cnt){
                         cy_writeb((u_long)base_addr+(CySRER<<index),
                            cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-                        cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
                         goto txdone;
                     }
                     if (info->xmit_buf == 0){
@@ -1404,28 +1360,10 @@ printk("cy_interrupt: xmit intr, chip %d\n\r", chip);
                            cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
                         goto txdone;
                     }
-#endif
                     while (char_count-- > 0){
-#ifdef NEW_INTR_FLOW
                         if (!info->xmit_cnt){
                             goto txdone;
                         }
-#else
-                        if (!info->xmit_cnt){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
-                               cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-                            goto txdone;
-                        }
-                        if (info->xmit_buf == 0){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
-                               cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-                            goto txdone;
-                        }
-                        if (info->tty->stopped || info->tty->hw_stopped){
-                            cy_writeb((u_long)base_addr+(CySRER<<index),
-                               cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty);
-                       }
-#endif
                         /* Because the Embedded Transmit Commands have
                            been enabled, we must check to see if the
                           escape character, NULL, is being sent.  If it
@@ -1725,14 +1663,12 @@ cyz_poll(unsigned long arg)
                    if ((fw_ver > 241 ? 
                           ((u_long)param) : 
                           cy_readl(&ch_ctrl[channel].rs_status)) & C_RS_DCD) {
-                       /* SP("Open Wakeup\n"); */
                        cy_sched_event(info,
                            Cy_EVENT_OPEN_WAKEUP);
                    }else if(!((info->flags
                                & ASYNC_CALLOUT_ACTIVE)
                         &&(info->flags
                            & ASYNC_CALLOUT_NOHUP))){
-                       /* SP("Hangup\n"); */
                        cy_sched_event(info,
                            Cy_EVENT_HANGUP);
                    }
@@ -1744,7 +1680,6 @@ cyz_poll(unsigned long arg)
                        if( cy_readl(&ch_ctrl[channel].rs_status) & C_RS_DCD){
                            /* cy_start isn't used because... 
                               HW flow is handled by the board */
-                           /* SP("Write Wakeup\n"); */
                            cy_sched_event(info,
                                Cy_EVENT_WRITE_WAKEUP);
                        }
@@ -1752,7 +1687,6 @@ cyz_poll(unsigned long arg)
                        if(!(cy_readl(&ch_ctrl[channel].rs_status) & C_RS_CTS)){
                            /* cy_stop isn't used because 
                               HW flow is handled by the board */
-                           /* SP("Write stop\n"); */
                        }
                    }
                }
@@ -1796,7 +1730,7 @@ cyz_poll(unsigned long arg)
                info->last_active = jiffies;
                info->jiffies[1] = jiffies;
 
-#ifdef CYCLOM_ENABLE_MONITORING
+#ifdef CY_ENABLE_MONITORING
                info->mon.int_count++;
                info->mon.char_count += char_count;
                if (char_count > info->mon.char_max)
@@ -1806,7 +1740,6 @@ cyz_poll(unsigned long arg)
                if( tty == 0){
                    /* flush received characters */
                    rx_get = (rx_get + char_count) & (rx_bufsize - 1);
-                   /* SP("-"); */
                    info->rflush_count++;
                }else{
 #ifdef BLOCKMOVE
@@ -1986,7 +1919,7 @@ startup(struct cyclades_port * info)
        base_addr = (unsigned char*)
                   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
        printk("cyc startup card %d, chip %d, channel %d, base_addr %lx\n",
             card, chip, channel, (long)base_addr);/**/
 #endif
@@ -2004,7 +1937,7 @@ startup(struct cyclades_port * info)
            cy_writeb((ulong)base_addr+(CyMSVR1<<index), CyRTS);
            cy_writeb((ulong)base_addr+(CyMSVR2<<index), CyDTR);
 
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
            printk("cyc:startup raising DTR\n");
            printk("     status: 0x%x, 0x%x\n",
                   cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -2040,7 +1973,7 @@ startup(struct cyclades_port * info)
        board_ctrl = &zfw_ctrl->board_ctrl;
        ch_ctrl = zfw_ctrl->ch_ctrl;
 
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
        printk("cyc startup Z card %d, channel %d, base_addr %lx\n",
             card, channel, (long)base_addr);/**/
 #endif
@@ -2068,7 +2001,7 @@ startup(struct cyclades_port * info)
        if (retval != 0){
            printk("cyc:startup(2) retval was %x\n", retval);
        }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
            printk("cyc:startup raising Z DTR\n");
 #endif
 
@@ -2082,7 +2015,7 @@ startup(struct cyclades_port * info)
 
     }
 
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
        printk(" cyc startup done\n");
 #endif
        return 0;
@@ -2142,7 +2075,7 @@ shutdown(struct cyclades_port * info)
                       (cy_card[card].base_addr
                       + (cy_chip_offset[chip]<<index));
 
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk("cyc shutdown Y card %d, chip %d, channel %d, base_addr %lx\n",
                card, chip, channel, (long)base_addr);
 #endif
@@ -2159,7 +2092,7 @@ shutdown(struct cyclades_port * info)
            if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
                cy_writeb((u_long)base_addr+(CyMSVR1<<index), ~CyRTS);
                cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc shutdown dropping DTR\n");
                printk("     status: 0x%x, 0x%x\n",
                    cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -2183,7 +2116,7 @@ shutdown(struct cyclades_port * info)
       int retval;
 
        base_addr = (unsigned char*) (cy_card[card].base_addr);
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk("cyc shutdown Z card %d, channel %d, base_addr %lx\n",
                card, channel, (long)base_addr);
 #endif
@@ -2217,7 +2150,7 @@ shutdown(struct cyclades_port * info)
                if (retval != 0){
                    printk("cyc:shutdown retval (2) was %x\n", retval);
                }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:shutdown dropping Z DTR\n");
 #endif
            }
@@ -2230,7 +2163,7 @@ shutdown(struct cyclades_port * info)
        restore_flags(flags);
     }
 
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk(" cyc shutdown done\n");
 #endif
     return;
@@ -2262,11 +2195,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
        if (info->flags & ASYNC_CLOSING) {
             interruptible_sleep_on(&info->close_wait);
        }
-        if (info->flags & ASYNC_HUP_NOTIFY){
-            return -EAGAIN;
-        }else{
-            return -ERESTARTSYS;
-        }
+        return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
     }
 
     /*
@@ -2313,7 +2242,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
      */
     retval = 0;
     add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk("cyc block_til_ready before block: ttyC%d, count = %d\n",
            info->line, info->count);/**/
 #endif
@@ -2321,7 +2250,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
     if (!tty_hung_up_p(filp))
        info->count--;
     restore_flags(flags);
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
     printk("cyc block_til_ready: (%d): decrementing count to %d\n",
         current->pid, info->count);
 #endif
@@ -2338,11 +2267,12 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
 
        while (1) {
            save_flags(flags); cli();
-               if (!(info->flags & ASYNC_CALLOUT_ACTIVE)){
+               if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+                   (tty->termios->c_cflag & CBAUD)){
                    cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)channel);
                    cy_writeb((u_long)base_addr+(CyMSVR1<<index), CyRTS);
                    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                    printk("cyc:block_til_ready raising DTR\n");
                    printk("     status: 0x%x, 0x%x\n",
                        cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -2353,11 +2283,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
            current->state = TASK_INTERRUPTIBLE;
            if (tty_hung_up_p(filp)
            || !(info->flags & ASYNC_INITIALIZED) ){
-               if (info->flags & ASYNC_HUP_NOTIFY) {
-                   retval = -EAGAIN;
-               }else{
-                   retval = -ERESTARTSYS;
-               }
+               return ((info->flags & ASYNC_HUP_NOTIFY) ? 
+                   -EAGAIN : -ERESTARTSYS);
                break;
            }
            save_flags(flags); cli();
@@ -2374,7 +2301,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
                retval = -ERESTARTSYS;
                break;
            }
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
            printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
                   info->line, info->count);/**/
 #endif
@@ -2408,18 +2335,15 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
            if (retval != 0){
                printk("cyc:block_til_ready retval was %x\n", retval);
            }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                    printk("cyc:block_til_ready raising Z DTR\n");
 #endif
 
            current->state = TASK_INTERRUPTIBLE;
            if (tty_hung_up_p(filp)
            || !(info->flags & ASYNC_INITIALIZED) ){
-               if (info->flags & ASYNC_HUP_NOTIFY) {
-                   retval = -EAGAIN;
-               }else{
-                   retval = -ERESTARTSYS;
-               }
+               return ((info->flags & ASYNC_HUP_NOTIFY) ?
+                   -EAGAIN : -ERESTARTSYS);
                break;
            }
            if (!(info->flags & ASYNC_CALLOUT_ACTIVE)
@@ -2432,7 +2356,7 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
                retval = -ERESTARTSYS;
                break;
            }
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
            printk("cyc block_til_ready blocking: ttyC%d, count = %d\n",
                   info->line, info->count);/**/
 #endif
@@ -2443,13 +2367,13 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
     remove_wait_queue(&info->open_wait, &wait);
     if (!tty_hung_up_p(filp)){
        info->count++;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
        printk("cyc:block_til_ready (%d): incrementing count to %d\n",
            current->pid, info->count);
 #endif
     }
     info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk("cyc:block_til_ready after blocking: ttyC%d, count = %d\n",
           info->line, info->count);/**/
 #endif
@@ -2464,11 +2388,12 @@ block_til_ready(struct tty_struct *tty, struct file * filp,
  * This routine is called whenever a serial port is opened.  It
  * performs the serial-specific initialization for the tty structure.
  */
-int
+static int
 cy_open(struct tty_struct *tty, struct file * filp)
 {
   struct cyclades_port  *info;
   int retval, line;
+  unsigned long page;
 
     line = MINOR(tty->device) - tty->driver.minor_start;
     if ((line < 0) || (NR_PORTS <= line)){
@@ -2491,46 +2416,50 @@ cy_open(struct tty_struct *tty, struct file * filp)
                (ZFIRM_HLT==cy_readl(&((struct FIRM_ID *)
                ((cy_card[info->card]).base_addr+ID_ADDRESS))->signature)))
            {
-               printk ("Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n");
+               printk ("cyc:Cyclades-Z Error: you need an external power supply for this number of ports.\n\rFirmware halted.\r\n");
            } else {
-               printk("Cyclades-Z firmware not yet loaded\n");
+               printk("cyc:Cyclades-Z firmware not yet loaded\n");
            }
            return -ENODEV;
        }
     }
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_open ttyC%d\n", info->line); /* */
 #endif
     if (serial_paranoia_check(info, tty->device, "cy_open")){
         return -ENODEV;
     }
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk("cyc:cy_open ttyC%d, count = %d\n",
         info->line, info->count);/**/
 #endif
     info->count++;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
     printk("cyc:cy_open (%d): incrementing count to %d\n",
         current->pid, info->count);
 #endif
     tty->driver_data = info;
     info->tty = tty;
 
-    /* Some drivers have (incorrect/incomplete) code to test
-       against a race condition.  Should add good code here!!! */
     if (!tmp_buf) {
-        tmp_buf = (unsigned char *) get_free_page(GFP_KERNEL);
-        if (!tmp_buf){
-            return -ENOMEM;
-        }
+       page = get_free_page(GFP_KERNEL);
+       if (!page)
+           return -ENOMEM;
+       if (tmp_buf)
+           free_page(page);
+       else
+           tmp_buf = (unsigned char *) page;
     }
 
-    if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
-        if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
-            *tty->termios = info->normal_termios;
-        else 
-            *tty->termios = info->callout_termios;
+    /*
+     * If the port is the middle of closing, bail out now
+     */
+    if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
+       if (info->flags & ASYNC_CLOSING)
+           interruptible_sleep_on(&info->close_wait);
+       return ((info->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
     }
+
     /*
      * Start up serial port
      */
@@ -2543,17 +2472,24 @@ cy_open(struct tty_struct *tty, struct file * filp)
 
     retval = block_til_ready(tty, filp, info);
     if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
         printk("cyc:cy_open returning after block_til_ready with %d\n",
                retval);
 #endif
         return retval;
     }
 
+    if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+        if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+            *tty->termios = info->normal_termios;
+        else 
+            *tty->termios = info->callout_termios;
+    }
+
     info->session = current->session;
     info->pgrp = current->pgrp;
 
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk(" cyc:cy_open done\n");/**/
 #endif
 
@@ -2561,6 +2497,76 @@ cy_open(struct tty_struct *tty, struct file * filp)
 } /* cy_open */
 
 
+/*
+ * cy_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+  struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
+  unsigned char *base_addr;
+  int card,chip,channel,index;
+  unsigned long orig_jiffies, char_time;
+       
+    if (serial_paranoia_check(info, tty->device, "cy_wait_until_sent"))
+       return;
+
+    orig_jiffies = jiffies;
+    /*
+     * Set the check interval to be 1/5 of the estimated time to
+     * send a single character, and make it at least 1.  The check
+     * interval should also be less than the timeout.
+     * 
+     * Note: we have to use pretty tight timings here to satisfy
+     * the NIST-PCTS.
+     */
+    char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
+    char_time = char_time / 5;
+    if (char_time == 0)
+       char_time = 1;
+    if (timeout < 0)
+       timeout = 0;
+    if (timeout)
+       char_time = MIN(char_time, timeout);
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+    printk("In cy_wait_until_sent(%d) check=%lu...", timeout, char_time);
+    printk("jiff=%lu...", jiffies);
+#endif
+    card = info->card;
+    channel = (info->line) - (cy_card[card].first_line);
+    if (!IS_CYC_Z(cy_card[card])) {
+       chip = channel>>2;
+       channel &= 0x03;
+       index = cy_card[card].bus_index;
+       base_addr = (unsigned char *)
+               (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
+       while (cy_readb(base_addr+(CySRER<<index)) & CyTxMpty) {
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+           printk("Not clean (jiff=%lu)...", jiffies);
+#endif
+           current->state = TASK_INTERRUPTIBLE;
+           current->counter = 0;       /* make us low-priority */
+           current->timeout = jiffies + char_time;
+           schedule();
+           if (signal_pending(current))
+               break;
+           if (timeout && ((orig_jiffies + timeout) < jiffies))
+               break;
+       }
+       current->state = TASK_RUNNING;
+    } else {
+       // Nothing to do!
+    }
+    /* Run one more char cycle */
+    current->state = TASK_INTERRUPTIBLE;
+    current->counter = 0;      /* make us low-priority */
+    current->timeout = jiffies + (char_time * 5);
+    schedule();
+    current->state = TASK_RUNNING;
+#ifdef CY_DEBUG_WAIT_UNTIL_SENT
+    printk("Clean (jiff=%lu)...done\n", jiffies);
+#endif
+}
+
 /*
  * This routine is called when a particular tty device is closed.
  */
@@ -2570,7 +2576,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
 
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_close ttyC%d\n", info->line);
 #endif
 
@@ -2578,7 +2584,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
     || serial_paranoia_check(info, tty->device, "cy_close")){
         return;
     }
-#ifdef SERIAL_DEBUG_OPEN
+#ifdef CY_DEBUG_OPEN
     printk("cyc:cy_close ttyC%d, count = %d\n", info->line, info->count);
 #endif
 
@@ -2586,6 +2592,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
 
     /* If the TTY is being hung up, nothing to do */
     if (tty_hung_up_p(filp)) {
+       MOD_DEC_USE_COUNT;
         restore_flags(flags);
         return;
     }
@@ -2602,18 +2609,18 @@ cy_close(struct tty_struct * tty, struct file * filp)
            "info->count is %d\n", info->count);
         info->count = 1;
     }
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
     printk("cyc:cy_close at (%d): decrementing count to %d\n",
         current->pid, info->count - 1);
 #endif
     if (--info->count < 0) {
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
     printk("cyc:cyc_close setting count to 0\n");
 #endif
         info->count = 0;
     }
     if (info->count) {
-        MOD_DEC_USE_COUNT;
+       MOD_DEC_USE_COUNT;
         restore_flags(flags);
         return;
     }
@@ -2632,28 +2639,25 @@ cy_close(struct tty_struct * tty, struct file * filp)
     * the line discipline to only process XON/XOFF characters.
     */
     tty->closing = 1;
-    if (info->closing_wait2 != 0) { /* The port's being forced to wait, 
-                                      independent on the port settings */
-       tty_wait_until_sent(tty, info->closing_wait2*HZ);
-    } else {
-       if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-           tty_wait_until_sent(tty, info->closing_wait*HZ);
+    if (info->closing_wait != CY_CLOSING_WAIT_NONE) {
+       tty_wait_until_sent(tty, info->closing_wait);
     }
 
-    /* Waiting for on-board buffers to be empty before closing the port */
     if (!IS_CYC_Z(cy_card[info->card])) {
-#ifdef NEW_INTR_FLOW
        unsigned char *base_addr = (unsigned char *) 
                                        cy_card[info->card].base_addr;
        int index = cy_card[info->card].bus_index;
-
-       if (cy_readb(base_addr+(CySRER<<index)) & CyTxMpty) {
-           /* Interrupts are enabled, so go to sleep */
-            interruptible_sleep_on(&info->shutdown_wait);
+       /* Stop accepting input */
+       cy_writeb((u_long)base_addr+(CySRER<<index),
+                       cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
+       if (info->flags & ASYNC_INITIALIZED) {
+           /* Waiting for on-board buffers to be empty before closing 
+              the port */
+           cy_wait_until_sent(tty, info->timeout);
        }
-#endif
     } else {
 #ifdef Z_WAKE
+       /* Waiting for on-board buffers to be empty before closing the port */
        unsigned char *base_addr = (unsigned char *) 
                                        cy_card[info->card].base_addr;
        struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS);
@@ -2693,7 +2697,7 @@ cy_close(struct tty_struct * tty, struct file * filp)
                      ASYNC_CLOSING);
     wake_up_interruptible(&info->close_wait);
 
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk(" cyc:cy_close done\n");
 #endif
 
@@ -2722,9 +2726,9 @@ cy_write(struct tty_struct * tty, int from_user,
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
-  int c, total = 0;
+  int c, ret = 0;
 
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
     printk("cyc:cy_write ttyC%d\n", info->line); /* */
 #endif
 
@@ -2736,42 +2740,57 @@ cy_write(struct tty_struct * tty, int from_user,
         return 0;
     }
 
-    if (from_user)
-       down(&tmp_buf_sem);
     save_flags(flags);               
-    while (1) {
-        cli();               
-        c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                           SERIAL_XMIT_SIZE - info->xmit_head));
-        if (c <= 0)
-            break;
 
-        if (from_user) {
-            copy_from_user(tmp_buf, buf, c);
-            c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                       SERIAL_XMIT_SIZE - info->xmit_head));
-            memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-        } else
-            memcpy(info->xmit_buf + info->xmit_head, buf, c);
-        info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-        info->xmit_cnt += c;
-        restore_flags(flags);
-        buf += c;
-        count -= c;
-        total += c;
-#if 0
-        SP("CW");
-       CP16(c);
-       SP(" ");
-#endif
-    }
-    if (from_user)
+    if (from_user) {
+       down(&tmp_buf_sem);
+       while (1) {
+           c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                               SERIAL_XMIT_SIZE - info->xmit_head));
+           if (c <= 0)
+               break;
+
+           c -= copy_from_user(tmp_buf, buf, c);
+           if (!c) {
+               if (!ret) {
+                   ret = -EFAULT;
+               }
+               break;
+           }
+           cli();               
+           c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                       SERIAL_XMIT_SIZE - info->xmit_head));
+           memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+           info->xmit_head = ((info->xmit_head + c) & (SERIAL_XMIT_SIZE-1));
+           info->xmit_cnt += c;
+           restore_flags(flags);
+           buf += c;
+           count -= c;
+           ret += c;
+       }
        up(&tmp_buf_sem);
+    } else {
+       while (1) {
+           cli();
+           c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, 
+                       SERIAL_XMIT_SIZE - info->xmit_head));
+           if (c <= 0) {
+               restore_flags(flags);
+               break;
+           }
+           memcpy(info->xmit_buf + info->xmit_head, buf, c);
+           info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+           info->xmit_cnt += c;
+           restore_flags(flags);
+           buf += c;
+           count -= c;
+           ret += c;
+       }
+    }
     if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
         start_xmit(info);
     }
-    restore_flags(flags);
-    return total;
+    return ret;
 } /* cy_write */
 
 
@@ -2788,7 +2807,7 @@ cy_put_char(struct tty_struct *tty, unsigned char ch)
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   unsigned long flags;
 
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
     printk("cyc:cy_put_char ttyC%d\n", info->line);
 #endif
 
@@ -2808,9 +2827,6 @@ cy_put_char(struct tty_struct *tty, unsigned char ch)
         info->xmit_head &= SERIAL_XMIT_SIZE - 1;
         info->xmit_cnt++;
     restore_flags(flags);
-#if 0
-       SP("+");
-#endif
 } /* cy_put_char */
 
 
@@ -2826,7 +2842,7 @@ cy_flush_chars(struct tty_struct *tty)
   unsigned char *base_addr;
   int card,chip,channel,index;
                                 
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
     printk("cyc:cy_flush_chars ttyC%d\n", info->line); /* */
 #endif
 
@@ -2871,7 +2887,7 @@ cy_write_room(struct tty_struct *tty)
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
   int   ret;
                                 
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
     printk("cyc:cy_write_room ttyC%d\n", info->line); /* */
 #endif
 
@@ -2897,7 +2913,7 @@ cy_chars_in_buffer(struct tty_struct *tty)
     channel = (info->line) - (cy_card[card].first_line);
 
     if (!IS_CYC_Z(cy_card[card])) {
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
        printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
                info->line, info->xmit_cnt); /* */
 #endif
@@ -2923,7 +2939,7 @@ cy_chars_in_buffer(struct tty_struct *tty)
            char_count = tx_put - tx_get;
        else
            char_count = tx_put - tx_get + tx_bufsize;
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
        printk("cyc:cy_chars_in_buffer ttyC%d %d\n",
                info->line, info->xmit_cnt + char_count); /* */
 #endif
@@ -2951,6 +2967,7 @@ set_line_char(struct cyclades_port * info)
   int card,chip,channel,index;
   unsigned cflag, iflag;
   unsigned short chip_number;
+  int baud;
   int   i;
 
 
@@ -2972,47 +2989,21 @@ set_line_char(struct cyclades_port * info)
        index = cy_card[card].bus_index;
 
        /* baud rate */
-       i = cflag & CBAUD;
-     
-       if (i & CBAUDEX) {
-           if (i == B57600)
-               i = 16;
-#ifdef B76800
-           else if(i == B76800) 
-               i = 17;
-#endif
-           else if(i == B115200) 
-               i = 18;
-           else if(i == B230400 && (info->chip_rev >= CD1400_REV_J)) {
-               /* It is a CD1400 rev. J or later */
-               i = 20;
+       baud = tty_get_baud_rate(info->tty);
+       if (baud > CD1400_MAX_SPEED) {
+           baud = CD1400_MAX_SPEED;
+       }
+       /* find the baud index */
+       for (i = 0; i < 20; i++) {
+           if (baud == baud_table[i]) {
+               break;
            }
-           else
-               info->tty->termios->c_cflag &= ~CBAUDEX;
        }
+       if (i == 20) {
+           i = 19; /* CD1400_MAX_SPEED */
+       } 
+
 
-       if (i == 15) {
-           if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-               i += 1;
-           if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-               i += 3;
-                   if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST){
-                switch(info->baud) {
-                   case 57600:
-                       i += 1; break;
-#ifdef B76800
-                   case 76800: 
-                       i += 2; break;
-#endif
-                   case 115200:
-                       i += 3; break;
-                   case 230400:
-                       i += 5; break;
-                   default:
-                       break;
-               }
-            }
-       }
        if(info->chip_rev >= CD1400_REV_J) {
            /* It is a CD1400 rev. J or later */
            info->tbpr = baud_bpr_60[i]; /* Tx BPR */
@@ -3026,7 +3017,7 @@ set_line_char(struct cyclades_port * info)
            info->rco = baud_co_25[i]; /* Rx CO */
        }
        if (baud_table[i] == 134) {
-           info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
+           info->timeout = (info->xmit_fifo_size*HZ*15/269) + 2;
            /* get it right for 134.5 baud */
        } else if (baud_table[i]) {
            info->timeout = (info->xmit_fifo_size*HZ*15/baud_table[i]) + 2;
@@ -3168,7 +3159,7 @@ set_line_char(struct cyclades_port * info)
                } else {
                         cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
                }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:set_line_char dropping DTR\n");
                printk("     status: 0x%x,
                    0x%x\n", cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3180,7 +3171,7 @@ set_line_char(struct cyclades_port * info)
                 } else {
                        cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
                 }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:set_line_char raising DTR\n");
                printk("     status: 0x%x, 0x%x\n",
                    cy_readb(base_addr+(CyMSVR1<<index)),
@@ -3214,49 +3205,17 @@ set_line_char(struct cyclades_port * info)
        buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
 
        /* baud rate */
-       switch(i = cflag & CBAUD){
-       /*
-        case B0: cy_writel(&ch_ctrl->comm_baud , 0); break;
-       */
-        case B50: cy_writel(&ch_ctrl->comm_baud , 50); break;
-        case B75: cy_writel(&ch_ctrl->comm_baud , 75); break;
-        case B110: cy_writel(&ch_ctrl->comm_baud , 110); break;
-        case B134: cy_writel(&ch_ctrl->comm_baud , 134); break;
-        case B150: cy_writel(&ch_ctrl->comm_baud , 150); break;
-        case B200: cy_writel(&ch_ctrl->comm_baud , 200); break;
-        case B300: cy_writel(&ch_ctrl->comm_baud , 300); break;
-        case B600: cy_writel(&ch_ctrl->comm_baud , 600); break;
-        case B1200: cy_writel(&ch_ctrl->comm_baud , 1200); break;
-        case B1800: cy_writel(&ch_ctrl->comm_baud , 1800); break;
-        case B2400: cy_writel(&ch_ctrl->comm_baud , 2400); break;
-        case B4800: cy_writel(&ch_ctrl->comm_baud , 4800); break;
-        case B9600: cy_writel(&ch_ctrl->comm_baud , 9600); break;
-        case B19200: cy_writel(&ch_ctrl->comm_baud , 19200); break;
-        case B38400:
-            if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI){
-                cy_writel(&ch_ctrl->comm_baud , 57600);
-            }else if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI){
-                cy_writel(&ch_ctrl->comm_baud , 115200);
-            }else if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST){
-                cy_writel(&ch_ctrl->comm_baud , info->baud);
-            }else{
-                cy_writel(&ch_ctrl->comm_baud , 38400);
-            }
-            break;
-        case B57600: cy_writel(&ch_ctrl->comm_baud , 57600); break;
-#ifdef B76800
-        case B76800: cy_writel(&ch_ctrl->comm_baud , 76800); break;
-#endif
-        case B115200: cy_writel(&ch_ctrl->comm_baud , 115200); break;
-        case B230400: cy_writel(&ch_ctrl->comm_baud , 230400); break;
-        case B460800: cy_writel(&ch_ctrl->comm_baud , 460800); break;
+       baud = tty_get_baud_rate(info->tty);
+       if (baud > CD1400_MAX_SPEED) {
+           baud = CD1400_MAX_SPEED;
        }
+       cy_writel(&ch_ctrl->comm_baud , baud);
 
-       if ((i = cy_readl(&ch_ctrl->comm_baud)) == 134) {
+       if (baud == 134) {
            info->timeout = (info->xmit_fifo_size*HZ*30/269) + 2;
            /* get it right for 134.5 baud */
-       } else if (i) {
-           info->timeout = (info->xmit_fifo_size*HZ*15/i) + 2;
+       } else if (baud) {
+           info->timeout = (info->xmit_fifo_size*HZ*15/baud) + 2;
            /* this needs to be propagated into the card info */
        } else {
            info->timeout = 0;
@@ -3318,16 +3277,16 @@ set_line_char(struct cyclades_port * info)
                cy_readl(&ch_ctrl->sw_flow) & ~C_FL_OXX);
        }
 
-       if(i == 0){ /* baud rate is zero, turn off line */
+       if(baud == 0){ /* baud rate is zero, turn off line */
            cy_writel(&ch_ctrl->rs_control,
                cy_readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
            printk("cyc:set_line_char dropping Z DTR\n");
 #endif
        }else{
            cy_writel(&ch_ctrl->rs_control,
                cy_readl(&ch_ctrl->rs_control) | C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
            printk("cyc:set_line_char raising Z DTR\n");
 #endif
        }
@@ -3343,6 +3302,21 @@ set_line_char(struct cyclades_port * info)
        }
     }
 
+    /*
+     * Set up the tty->alt_speed kludge
+     */
+    if (info->tty) {
+       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+           info->tty->alt_speed = 57600;
+       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+           info->tty->alt_speed = 115200;
+       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+           info->tty->alt_speed = 230400;
+       if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+           info->tty->alt_speed = 460800;
+    }
+
+
 } /* set_line_char */
 
 
@@ -3377,9 +3351,8 @@ set_serial_info(struct cyclades_port * info,
   struct serial_struct new_serial;
   struct cyclades_port old_info;
 
-    if (!new_info)
-            return -EFAULT;
-    copy_from_user(&new_serial,new_info,sizeof(new_serial));
+    if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+       return -EFAULT;
     old_info = *info;
 
     if (!capable(CAP_SYS_ADMIN)) {
@@ -3405,7 +3378,6 @@ set_serial_info(struct cyclades_port * info,
                     (new_serial.flags & ASYNC_FLAGS));
     info->close_delay = new_serial.close_delay * HZ/100;
     info->closing_wait = new_serial.closing_wait * HZ/100;
 
 check_and_exit:
     if (info->flags & ASYNC_INITIALIZED){
@@ -3486,8 +3458,7 @@ get_modem_info(struct cyclades_port * info, unsigned int *value)
        }
 
     }
-    cy_put_user(result,(unsigned long *) value);
-    return 0;
+    return cy_put_user(result,(unsigned long *) value);
 } /* get_modem_info */
 
 
@@ -3535,7 +3506,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                 } else {
                    cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
                 }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:set_modem_info raising DTR\n");
                printk("     status: 0x%x, 0x%x\n",
                    cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -3564,7 +3535,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                 } else {
                        cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
                 }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:set_modem_info dropping DTR\n");
                printk("     status: 0x%x, 0x%x\n",
                    cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -3601,7 +3572,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                 } else {
                        cy_writeb((u_long)base_addr+(CyMSVR2<<index), CyDTR);
                 }
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:set_modem_info raising DTR\n");
                printk("     status: 0x%x, 0x%x\n",
                    cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -3617,7 +3588,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                        cy_writeb((u_long)base_addr+(CyMSVR2<<index), ~CyDTR);
                 }
 
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                printk("cyc:set_modem_info dropping DTR\n");
                printk("     status: 0x%x, 0x%x\n",
                    cy_readb(base_addr+(CyMSVR1<<index)), 
@@ -3649,7 +3620,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                if (arg & TIOCM_DTR){
                    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                    printk("cyc:set_modem_info raising Z DTR\n");
 #endif
                }
@@ -3662,7 +3633,7 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                if (arg & TIOCM_DTR){
                    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                    printk("cyc:set_modem_info clearing Z DTR\n");
 #endif
                }
@@ -3678,13 +3649,13 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
                if (arg & TIOCM_DTR){
                    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) | C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                    printk("cyc:set_modem_info raising Z DTR\n");
 #endif
                }else{
                    cy_writel(&ch_ctrl[channel].rs_control,
                        cy_readl(&ch_ctrl[channel].rs_control) & ~C_RS_DTR);
-#ifdef SERIAL_DEBUG_DTR
+#ifdef CY_DEBUG_DTR
                    printk("cyc:set_modem_info clearing Z DTR\n");
 #endif
                }
@@ -3705,7 +3676,6 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
     return 0;
 } /* set_modem_info */
 
-
 static void
 send_break( struct cyclades_port * info, int duration)
 {
@@ -3737,7 +3707,6 @@ int retval;
     }
 } /* send_break */
 
-
 static int
 get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
 {
@@ -3796,11 +3765,11 @@ get_threshold(struct cyclades_port * info, unsigned long *value)
                       + (cy_chip_offset[chip]<<index));
 
        tmp = cy_readb(base_addr+(CyCOR3<<index)) & CyREC_FIFO;
-       cy_put_user(tmp,value);
+       return cy_put_user(tmp,value);
     } else {
        // Nothing to do!
+       return 0;
     }
-    return 0;
 }/* get_threshold */
 
 
@@ -3815,8 +3784,7 @@ set_default_threshold(struct cyclades_port * info, unsigned long value)
 static int
 get_default_threshold(struct cyclades_port * info, unsigned long *value)
 {
-    cy_put_user(info->default_threshold,value);
-    return 0;
+    return cy_put_user(info->default_threshold,value);
 }/* get_default_threshold */
 
 
@@ -3862,11 +3830,11 @@ get_timeout(struct cyclades_port * info, unsigned long *value)
                       + (cy_chip_offset[chip]<<index));
 
        tmp = cy_readb(base_addr+(CyRTPR<<index));
-       cy_put_user(tmp,value);
+       return cy_put_user(tmp,value);
     } else {
        // Nothing to do!
+       return 0;
     }
-    return 0;
 }/* get_timeout */
 
 
@@ -3881,8 +3849,7 @@ set_default_timeout(struct cyclades_port * info, unsigned long value)
 static int
 get_default_timeout(struct cyclades_port * info, unsigned long *value)
 {
-    cy_put_user(info->default_timeout,value);
-    return 0;
+    return cy_put_user(info->default_timeout,value);
 }/* get_default_timeout */
 
 /*
@@ -3894,68 +3861,40 @@ static int
 cy_ioctl(struct tty_struct *tty, struct file * file,
             unsigned int cmd, unsigned long arg)
 {
-  int error;
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int ret_val = 0;
 
-#ifdef SERIAL_DEBUG_OTHER
+    if (serial_paranoia_check(info, tty->device, "cy_ioctl"))
+       return -ENODEV;
+
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
         info->line, cmd, arg); /* */
 #endif
 
     switch (cmd) {
         case CYGETMON:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(struct cyclades_monitor));
-            if (error){
-                ret_val = error;
-                break;
-            }
             ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
             break;
         case CYGETTHRESH:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(unsigned long));
-            if (error){
-                ret_val = error;
-                break;
-            }
             ret_val = get_threshold(info, (unsigned long *)arg);
             break;
         case CYSETTHRESH:
             ret_val = set_threshold(info, (unsigned long)arg);
             break;
         case CYGETDEFTHRESH:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(unsigned long));
-            if (error){
-                ret_val = error;
-                break;
-            }
             ret_val = get_default_threshold(info, (unsigned long *)arg);
             break;
         case CYSETDEFTHRESH:
             ret_val = set_default_threshold(info, (unsigned long)arg);
             break;
         case CYGETTIMEOUT:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(unsigned long));
-            if (error){
-                ret_val = error;
-                break;
-            }
             ret_val = get_timeout(info, (unsigned long *)arg);
             break;
         case CYSETTIMEOUT:
             ret_val = set_timeout(info, (unsigned long)arg);
             break;
         case CYGETDEFTIMEOUT:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(unsigned long));
-            if (error){
-                ret_val = error;
-                break;
-            }
             ret_val = get_default_timeout(info, (unsigned long *)arg);
             break;
         case CYSETDEFTIMEOUT:
@@ -3976,14 +3915,10 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
            ret_val = info->rtsdtr_inv;
            break;
        case CYGETCARDINFO:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(struct cyclades_card));
-            if (error){
-                ret_val = error;
-                break;
-            }
-            copy_to_user((void *)arg, (void *)&cy_card[info->card], 
-                        sizeof (struct cyclades_card));
+            if (copy_to_user((void *)arg, (void *)&cy_card[info->card], 
+                       sizeof (struct cyclades_card))) {
+               ret_val = -EFAULT;
+           }
            ret_val = 0;
             break;
        case CYGETCD1400VER:
@@ -3994,91 +3929,46 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
            ret_val = 0;
            break;
        case CYSETWAIT:
-           info->closing_wait2 = (unsigned short)arg;
+           info->closing_wait = (unsigned short)arg * HZ/100;
            ret_val = 0;
            break;
        case CYGETWAIT:
-           ret_val = info->closing_wait2;
+           ret_val = info->closing_wait / (HZ/100);
            break;
-        case TCSBRK:    /* SVID version: non-zero arg --> no break */
-            ret_val = tty_check_change(tty);
-            if (ret_val)
-                return ret_val;
-            tty_wait_until_sent(tty,0);
-            if (!arg)
-                send_break(info, HZ/4); /* 1/4 second */
-            break;
-        case TCSBRKP:   /* support for POSIX tcsendbreak() */
-            ret_val = tty_check_change(tty);
-            if (ret_val)
-                return ret_val;
-            tty_wait_until_sent(tty,0);
-            send_break(info, arg ? arg*(HZ/10) : HZ/4);
+       case TCSBRK:    /* SVID version: non-zero arg --> no break */
+           ret_val = tty_check_change(tty);
+           if (ret_val)
+               return ret_val;
+           tty_wait_until_sent(tty,0);
+           if (!arg)
+               send_break(info, HZ/4); /* 1/4 second */
+           break;
+       case TCSBRKP:   /* support for POSIX tcsendbreak() */
+           ret_val = tty_check_change(tty);
+           if (ret_val)
+               return ret_val;
+           tty_wait_until_sent(tty,0);
+           send_break(info, arg ? arg*(HZ/10) : HZ/4);
+           break;
+        case TIOCMGET:
+            ret_val = get_modem_info(info, (unsigned int *) arg);
             break;
         case TIOCMBIS:
         case TIOCMBIC:
         case TIOCMSET:
             ret_val = set_modem_info(info, cmd, (unsigned int *) arg);
             break;
-
-/* The following commands are incompletely implemented!!! */
-        case TIOCGSOFTCAR:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(unsigned int *));
-            if (error){
-                ret_val = error;
-                break;
-            }
-            cy_put_user(C_CLOCAL(tty) ? 1 : 0,
-                        (unsigned long *) arg);
-            break;
-        case TIOCSSOFTCAR:
-           error = verify_area(VERIFY_READ, (void *) arg
-                                ,sizeof(unsigned long *));
-           if (error) {
-                ret_val = error;
-                break;
-           }
-
-            arg = cy_get_user((unsigned long *) arg);
-            tty->termios->c_cflag =
-                    ((tty->termios->c_cflag & ~CLOCAL) |
-                     (arg ? CLOCAL : 0));
-            break;
-        case TIOCMGET:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(unsigned int *));
-            if (error){
-                ret_val = error;
-                break;
-            }
-            ret_val = get_modem_info(info, (unsigned int *) arg);
-            break;
         case TIOCGSERIAL:
-            error = verify_area(VERIFY_WRITE, (void *) arg
-                                ,sizeof(struct serial_struct));
-            if (error){
-                ret_val = error;
-                break;
-            }
-            ret_val = get_serial_info(info,
-                                   (struct serial_struct *) arg);
+            ret_val = get_serial_info(info, (struct serial_struct *) arg);
             break;
         case TIOCSSERIAL:
-            error = verify_area(VERIFY_READ, (void *) arg
-                                ,sizeof(struct serial_struct));
-            if (error){
-                ret_val = error;
-                break;
-            }
-            ret_val = set_serial_info(info,
-                                   (struct serial_struct *) arg);
+            ret_val = set_serial_info(info, (struct serial_struct *) arg);
             break;
         default:
             ret_val = -ENOIOCTLCMD;
     }
 
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk(" cyc:cy_ioctl done\n");
 #endif
 
@@ -4097,7 +3987,7 @@ cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_set_termios ttyC%d\n", info->line);
 #endif
 
@@ -4141,7 +4031,7 @@ cy_throttle(struct tty_struct * tty)
   unsigned char *base_addr;
   int card,chip,channel,index;
 
-#ifdef SERIAL_DEBUG_THROTTLE
+#ifdef CY_DEBUG_THROTTLE
   char buf[64];
 
     printk("cyc:throttle %s: %d....ttyC%d\n", 
@@ -4197,7 +4087,7 @@ cy_unthrottle(struct tty_struct * tty)
   unsigned char *base_addr;
   int card,chip,channel,index;
 
-#ifdef SERIAL_DEBUG_THROTTLE
+#ifdef CY_DEBUG_THROTTLE
   char buf[64];
         
     printk("cyc:unthrottle %s: %d....ttyC%d\n", 
@@ -4255,7 +4145,7 @@ cy_stop(struct tty_struct *tty)
   int chip,channel,index;
   unsigned long flags;
 
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_stop ttyC%d\n", info->line); /* */
 #endif
 
@@ -4295,7 +4185,7 @@ cy_start(struct tty_struct *tty)
   int chip,channel,index;
   unsigned long flags;
 
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_start ttyC%d\n", info->line); /* */
 #endif
 
@@ -4333,7 +4223,7 @@ cy_flush_buffer(struct tty_struct *tty)
   int card, channel;
   unsigned long flags;
                                 
-#ifdef SERIAL_DEBUG_IO
+#ifdef CY_DEBUG_IO
     printk("cyc:cy_flush_buffer ttyC%d\n", info->line); /* */
 #endif
 
@@ -4377,7 +4267,7 @@ cy_hangup(struct tty_struct *tty)
 {
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
         
-#ifdef SERIAL_DEBUG_OTHER
+#ifdef CY_DEBUG_OTHER
     printk("cyc:cy_hangup ttyC%d\n", info->line); /* */
 #endif
 
@@ -4388,7 +4278,7 @@ cy_hangup(struct tty_struct *tty)
     shutdown(info);
     info->event = 0;
     info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
     printk("cyc:cy_hangup (%d): setting count to 0\n", current->pid);
 #endif
     info->tty = 0;
@@ -4593,88 +4483,45 @@ cy_detect_pci(void))
 {
 #ifdef CONFIG_PCI
 
-#ifdef NEW_PCI
   struct pci_dev       *pdev = NULL;
   unsigned char                cyy_rev_id;
-#else
-  unsigned char         cyy_bus, cyy_dev_fn, cyy_rev_id;
-#endif
   unsigned long         pci_intr_ctrl;
-  unsigned char         cy_pci_irq;
+  unsigned char         cy_pci_irq = 0;
   uclong                cy_pci_addr0, cy_pci_addr1, cy_pci_addr2;
   unsigned short        i,j,cy_pci_nchan;
   unsigned short        device_id,dev_index = 0;
-#ifndef NEW_PCI
-  unsigned short       board_index = 0;
-#endif
   uclong               mailbox;
   uclong               Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
 
-#ifdef NEW_PCI
         if(pci_present() == 0) {    /* PCI bus not present */
-#else
-        if(pcibios_present() == 0) {    /* PCI bus not present */
-#endif
                 return(0);
         }
         for (i = 0; i < NR_CARDS; i++) {
                 /* look for a Cyclades card by vendor and device id */
                 while((device_id = cy_pci_dev_id[dev_index]) != 0) {
-#ifdef NEW_PCI
                         if((pdev = pci_find_device(PCI_VENDOR_ID_CYCLADES,
                                         device_id, pdev)) == NULL) {
                                 dev_index++;    /* try next device id */
                         } else {
                                 break;          /* found a board */
                         }
-#else
-                        if(pcibios_find_device(PCI_VENDOR_ID_CYCLADES,
-                                        device_id,board_index,
-                                        &cyy_bus, &cyy_dev_fn) != 0) {
-                                dev_index++;    /* try next device id */
-                                board_index = 0;
-                        } else {
-                                board_index++;
-                                break;          /* found a board */
-                        }
-#endif
                 }
 
                if (device_id == 0)
                    break;
 
                 /* read PCI configuration area */
-#ifdef NEW_PCI
                cy_pci_irq = pdev->irq;
                cy_pci_addr0 = pdev->base_address[0];
                cy_pci_addr1 = pdev->base_address[1]; 
                cy_pci_addr2 = pdev->base_address[2]; 
                 pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id);
-#else
-                pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
-                                 PCI_INTERRUPT_LINE, &cy_pci_irq);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_0, 
-                                 (unsigned int *) &cy_pci_addr0);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_1, 
-                                 (unsigned int *) &cy_pci_addr1);
-                pcibios_read_config_dword(cyy_bus, cyy_dev_fn,
-                                  PCI_BASE_ADDRESS_2, 
-                                 (unsigned int *) &cy_pci_addr2);
-                pcibios_read_config_byte(cyy_bus, cyy_dev_fn,
-                                  PCI_REVISION_ID, &cyy_rev_id);
-#endif
 
     if ((device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo)
           || (device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi)){
 #ifdef CY_PCI_DEBUG
             printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
                pdev->bus->number, pdev->devfn);
-#else
-               cyy_bus, cyy_dev_fn);
-#endif
             printk("rev_id=%d) IRQ%d\n",
                cyy_rev_id, (int)cy_pci_irq);
             printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
@@ -4686,11 +4533,7 @@ cy_detect_pci(void))
 #if defined(__alpha__)
                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
                    printk("Cyclom-Y/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
                        pdev->bus->number, pdev->devfn);
-#else
-                       cyy_bus, cyy_dev_fn);
-#endif
                    printk("rev_id=%d) IRQ%d\n",
                        cyy_rev_id, (int)cy_pci_irq);
                     printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
@@ -4775,11 +4618,7 @@ cy_detect_pci(void))
     }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo){
            /* print message */
                printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
                    pdev->bus->number, pdev->devfn);
-#else
-                   cyy_bus, cyy_dev_fn);
-#endif
                printk("rev_id=%d) IRQ%d\n",
                    cyy_rev_id, (int)cy_pci_irq);
                printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
@@ -4789,11 +4628,7 @@ cy_detect_pci(void))
     }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){
 #ifdef CY_PCI_DEBUG
             printk("Cyclades-Z/PCI (bus=0x0%x, pci_id=0x%x, ",
-#ifdef NEW_PCI
                pdev->bus->number, pdev->devfn);
-#else
-               cyy_bus, cyy_dev_fn);
-#endif
             printk("rev_id=%d) IRQ%d\n",
                cyy_rev_id, (int)cy_pci_irq);
             printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n",
@@ -5077,6 +4912,7 @@ cy_init(void))
     
     memset(&cy_serial_driver, 0, sizeof(struct tty_driver));
     cy_serial_driver.magic = TTY_DRIVER_MAGIC;
+    cy_serial_driver.name = "cyclades";
     cy_serial_driver.name = "ttyC";
     cy_serial_driver.major = CYCLADES_MAJOR;
     cy_serial_driver.minor_start = 0;
@@ -5106,6 +4942,7 @@ cy_init(void))
     cy_serial_driver.stop = cy_stop;
     cy_serial_driver.start = cy_start;
     cy_serial_driver.hangup = cy_hangup;
+    cy_serial_driver.wait_until_sent = cy_wait_until_sent;
 
     /*
      * The callout device is just like normal device except for
@@ -5115,6 +4952,9 @@ cy_init(void))
     cy_callout_driver.name = "cub";
     cy_callout_driver.major = CYCLADESAUX_MAJOR;
     cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+    cy_callout_driver.read_proc = 0;
+    cy_callout_driver.proc_entry = 0;
+
 
     if (tty_register_driver(&cy_serial_driver))
             panic("Couldn't register Cyclades serial driver\n");
@@ -5123,7 +4963,7 @@ cy_init(void))
 
     init_bh(CYCLADES_BH, do_cyclades_bh);
 
-    for (i = 0; i < 16; i++) {
+    for (i = 0; i < NR_IRQS; i++) {
             IRQ_cards[i] = 0;
     }
 
@@ -5199,11 +5039,10 @@ cy_init(void))
                     info->rco = 0;
                     info->close_delay = 5*HZ/10;
                    info->closing_wait = CLOSING_WAIT_DELAY;
-                   info->closing_wait2 = 0;
                     info->x_char = 0;
                     info->event = 0;
                     info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
 //        printk("cyc:cy_init(1) setting Z count to 0\n");
 #endif
                     info->blocked_open = 0;
@@ -5250,7 +5089,6 @@ cy_init(void))
                     info->cor5 = 0;
                     info->close_delay = 5*HZ/10;
                    info->closing_wait = CLOSING_WAIT_DELAY;
-                   info->closing_wait2 = 0;
                    chip_number = (port - cinfo->first_line) / 4;
                     if ((info->chip_rev = cy_readb(cinfo->base_addr +
                                 (cy_chip_offset[chip_number]<<index) +
@@ -5273,7 +5111,7 @@ cy_init(void))
                     info->x_char = 0;
                     info->event = 0;
                     info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
+#ifdef CY_DEBUG_COUNT
 //        printk("cyc:cy_init(2) setting Y count to 0\n");
 #endif
                     info->blocked_open = 0;
index d6e4601839b440f0a0b41ec4a8677064541a4b62..74f1f737ae6887c68ea93bc1315cd817bd747a19 100644 (file)
@@ -168,6 +168,7 @@ static __inline__ void lp_schedule(int minor)
        register unsigned long int timeslip = (jiffies - dev->time);
        if ((timeslip > dev->timeslice) && (dev->port->waithead != NULL)) {
                lp_parport_release(minor);
+               lp_table[minor].irq_missed = 1;
                schedule ();
                lp_parport_claim(minor);
        } else
index 13d5d6d36de1ed6909ae6bba84adf9d72a1f08c5..e7fbc2efd2eea6e83d682b0287ddbb22ad127bf7 100644 (file)
@@ -1,9 +1,10 @@
 /*
  * random.c -- A strong random number generator
  *
- * Version 1.03, last modified 26-Apr-97
+ * Version 1.04, last modified 26-Apr-98
  * 
- * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997.  All rights reserved.
+ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998.  All rights
+ * reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * an *estimate* of how many bits of randomness have been stored into
  * the random number generator's internal state.
  * 
- * When random bytes are desired, they are obtained by taking the MD5
- * hash of the contents of the "entropy pool".  The MD5 hash avoids
+ * When random bytes are desired, they are obtained by taking the SHA
+ * hash of the contents of the "entropy pool".  The SHA hash avoids
  * exposing the internal state of the entropy pool.  It is believed to
  * be computationally infeasible to derive any useful information
- * about the input of MD5 from its output.  Even if it is possible to
- * analyze MD5 in some clever way, as long as the amount of data
+ * about the input of SHA from its output.  Even if it is possible to
+ * analyze SHA in some clever way, as long as the amount of data
  * returned from the generator is less than the inherent entropy in
  * the pool, the output data is totally unpredictable.  For this
  * reason, the routine decreases its internal estimate of how many
@@ -88,7 +89,7 @@
  * If this estimate goes to zero, the routine can still generate
  * random numbers; however, an attacker may (at least in theory) be
  * able to infer the future output of the generator from prior
- * outputs.  This requires successful cryptanalysis of MD5, which is
+ * outputs.  This requires successful cryptanalysis of SHA, which is
  * not believed to be feasible, but there is a remote possibility.
  * Nonetheless, these numbers should be useful for the vast majority
  * of purposes.
  * sequence: 
  *
  *     echo "Initializing random number generator..."
+ *     random_seed=/var/run/random-seed
  *     # Carry a random seed from start-up to start-up
  *     # Load and then save 512 bytes, which is the size of the entropy pool
- *     if [ -f /etc/random-seed ]; then
- *             cat /etc/random-seed >/dev/urandom
+ *     if [ -f $random_seed ]; then
+ *             cat $random_seed >/dev/urandom
  *     fi
- *     dd if=/dev/urandom of=/etc/random-seed count=1
+ *     dd if=/dev/urandom of=$random_seed count=1
+ *     chmod 600 $random_seed
  *
  * and the following lines in an appropriate script which is run as
  * the system is shutdown:
  *     # Carry a random seed from shut-down to start-up
  *     # Save 512 bytes, which is the size of the entropy pool
  *     echo "Saving random seed..."
- *     dd if=/dev/urandom of=/etc/random-seed count=1
+ *     random_seed=/var/run/random-seed
+ *     dd if=/dev/urandom of=$random_seed count=1
+ *     chmod 600 $random_seed
  * 
- * For example, on many Linux systems, the appropriate scripts are
- * usually /etc/rc.d/rc.local and /etc/rc.d/rc.0, respectively.
+ * For example, on most modern systems using the System V init
+ * scripts, such code fragments would be found in
+ * /etc/rc.d/init.d/random.  On older Linux systems, the correct script
+ * location might be in /etc/rcb.d/rc.local or /etc/rc.d/rc.0.
  * 
  * Effectively, these commands cause the contents of the entropy pool
  * to be saved at shut-down time and reloaded into the entropy pool at
  * =================
  *
  * Ideas for constructing this random number generator were derived
- * from the Pretty Good Privacy's random number generator, and from
- * private discussions with Phil Karn.  Colin Plumb provided a faster
- * random number generator, which speed up the mixing function of the
- * entropy pool, taken from PGP 3.0 (under development).  It has since
- * been modified by myself to provide better mixing in the case where
- * the input values to add_entropy_word() are mostly small numbers.
- * Dale Worley has also contributed many useful ideas and suggestions
- * to improve this driver.
+ * from Pretty Good Privacy's random number generator, and from private
+ * discussions with Phil Karn.  Colin Plumb provided a faster random
+ * number generator, which speed up the mixing function of the entropy
+ * pool, taken from PGPfone.  Dale Worley has also contributed many
+ * useful ideas and suggestions to improve this driver.
  * 
  * Any flaws in the design are solely my responsibility, and should
  * not be attributed to the Phil, Colin, or any of authors of PGP.
  * 
+ * The code for SHA transform was taken from Peter Gutmann's
+ * implementation, which has been placed in the public domain.
  * The code for MD5 transform was taken from Colin Plumb's
  * implementation, which has been placed in the public domain.  The
  * MD5 cryptographic checksum was devised by Ronald Rivest, and is
  */
 #undef RANDOM_BENCHMARK
 #undef BENCHMARK_NOINT
+#define ROTATE_PARANOIA
 
-/*
- * The pool is stirred with a primitive polynomial of degree 128
- * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1.
- * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
- */
 #define POOLWORDS 128    /* Power of 2 - note that this is 32-bit words */
 #define POOLBITS (POOLWORDS*32)
-#if POOLWORDS == 128
-#define TAP1    99     /* The polynomial taps */
-#define TAP2    59
-#define TAP3    31
-#define TAP4    9
-#define TAP5    7
-#elif POOLWORDS == 64
-#define TAP1    62      /* The polynomial taps */
-#define TAP2    38
-#define TAP3    10
-#define TAP4    6
-#define TAP5    1
+/*
+ * The pool is stirred with a primitive polynomial of degree POOLWORDS
+ * over GF(2).  The taps for various sizes are defined below.  They are
+ * chosen to be evenly spaced (minimum RMS distance from evenly spaced;
+ * the numbers in the comments are a scaled squared error sum) except
+ * for the last tap, which is 1 to get the twisting happening as fast
+ * as possible.
+ */
+#if POOLWORDS == 2048  /* 115 x^2048+x^1638+x^1231+x^819+x^411+x^1+1 */
+#define TAP1   1638
+#define TAP2   1231
+#define TAP3   819
+#define TAP4   411
+#define TAP5   1
+#elif POOLWORDS == 1024        /* 290 x^1024+x^817+x^615+x^412+x^204+x^1+1 */
+/* Alt: 115 x^1024+x^819+x^616+x^410+x^207+x^2+1 */
+#define TAP1   817
+#define TAP2   615
+#define TAP3   412
+#define TAP4   204
+#define TAP5   1
+#elif POOLWORDS == 512 /* 225 x^512+x^411+x^308+x^208+x^104+x+1 */
+/* Alt: 95 x^512+x^409+x^307+x^206+x^102+x^2+1
+ *      95 x^512+x^409+x^309+x^205+x^103+x^2+1 */
+#define TAP1   411
+#define TAP2   308
+#define TAP3   208
+#define TAP4   104
+#define TAP5   1
+#elif POOLWORDS == 256 /* 125 x^256+x^205+x^155+x^101+x^52+x+1 */
+#define TAP1   205
+#define TAP2   155
+#define TAP3   101
+#define TAP4   52
+#define TAP5   1
+#elif POOLWORDS == 128 /* 105 x^128+x^103+x^76+x^51+x^25+x+1 */
+/* Alt: 70 x^128+x^103+x^78+x^51+x^27+x^2+1 */
+#define TAP1   103
+#define TAP2   76
+#define TAP3   51
+#define TAP4   25
+#define TAP5   1
+#elif POOLWORDS == 64  /* 15 x^64+x^52+x^39+x^26+x^14+x+1 */
+#define TAP1   52
+#define TAP2   39
+#define TAP3   26
+#define TAP4   14
+#define TAP5   1
+#elif POOLWORDS == 32  /* 15 x^32+x^26+x^20+x^14+x^7+x^1+1 */
+#define TAP1   26
+#define TAP2   20
+#define TAP3   14
+#define TAP4   7
+#define TAP5   1
+#elif POOLWORDS & (POOLWORDS-1)
+#error POOLWORDS must be a power of 2
 #else
 #error No primitive polynomial available for chosen POOLWORDS
 #endif
  * Also see M. Matsumoto & Y. Kurita, 1994.  Twisted GFSR generators
  * II.  ACM Transactions on Mdeling and Computer Simulation 4:254-266)
  *
- * Thanks to Colin Plumb for suggesting this.  (Note that the behavior
- * of the 1.0 version of the driver was equivalent to using a second
- * element of 0x80000000).
+ * Thanks to Colin Plumb for suggesting this.
+ * We have not analyzed the resultant polynomial to prove it primitive;
+ * in fact it almost certainly isn't.  Nonetheless, the irreducible factors
+ * of a random large-degree polynomial over GF(2) are more than large enough
+ * that periodicity is not a concern.
+ *
+ * The input hash is much less sensitive than the output hash.  All that
+ * we want of it is that it be a good non-cryptographic hash; i.e. it
+ * not produce collisions when fed "random" data of the sort we expect
+ * to see.  As long as the pool state differs for different inputs, we
+ * have preserved the input entropy and done a good job.  The fact that an
+ * intelligent attacker can construct inputs that will produce controlled
+ * alterations to the pool's state is not important because we don't
+ * consider such inputs to contribute any randomness.
+ * The only property we need with respect to them is
+ * that the attacker can't increase his/her knowledge of the pool's state.
+ * Since all additions are reversible (knowing the final state and the
+ * input, you can reconstruct the initial state), if an attacker has
+ * any uncertainty about the initial state, he/she can only shuffle that
+ * uncertainty about, but never cause any collisions (which would
+ * decrease the uncertainty).
+ *
+ * The chosen system lets the state of the pool be (essentially) the input
+ * modulo the generator polymnomial.  Now, for random primitive polynomials,
+ * this is a universal class of hash functions, meaning that the chance
+ * of a collision is limited by the attacker's knowledge of the generator
+ * polynomail, so if it is chosen at random, an attacker can never force
+ * a collision.  Here, we use a fixed polynomial, but we *can* assume that
+ * ###--> it is unknown to the processes generating the input entropy. <-###
+ * Because of this important property, this is a good, collision-resistant
+ * hash; hash collisions will occur no more often than chance.
  */
-static __u32 twist_table[2] = { 0, 0xEDB88320 };
 
 /*
  * The minimum number of bits to release a "wait on input".  Should
@@ -303,7 +376,9 @@ static __u32 twist_table[2] = { 0, 0xEDB88320 };
 struct random_bucket {
        unsigned add_ptr;
        unsigned entropy_count;
+#ifdef ROTATE_PARANOIA 
        int input_rotate;
+#endif
        __u32 pool[POOLWORDS];
 };
 
@@ -332,8 +407,8 @@ struct random_benchmark timer_benchmark;
 
 /* There is one of these per entropy source */
 struct timer_rand_state {
-       unsigned long   last_time;
-       int             last_delta,last_delta2;
+       __u32           last_time;
+       __s32           last_delta,last_delta2;
        int             dont_count_entropy:1;
 };
 
@@ -356,11 +431,10 @@ static ssize_t random_write(struct file * file, const char * buffer,
 static int random_ioctl(struct inode * inode, struct file * file,
                        unsigned int cmd, unsigned long arg);
 
-static inline void fast_add_entropy_word(struct random_bucket *r,
-                                        const __u32 input);
+static inline void fast_add_entropy_words(struct random_bucket *r,
+                                        __u32 x, __u32 y);
 
-static void add_entropy_word(struct random_bucket *r,
-                                   const __u32 input);
+static void add_entropy_words(struct random_bucket *r, __u32 x, __u32 y);
 
 #ifndef MIN
 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
@@ -391,33 +465,36 @@ extern inline __u32 rotate_left(int i, __u32 word)
  * More asm magic....
  * 
  * For entropy estimation, we need to do an integral base 2
- * logarithm.  By default, use an open-coded C version, although we do
- * have a version which takes advantage of the Intel's x86's "bsr"
- * instruction.
+ * logarithm.  
+ *
+ * Note the "12bits" suffix - this is used for numbers between
+ * 0 and 4095 only.  This allows a few shortcuts.
  */
-#if (!defined (__i386__))
-static inline __u32 int_ln(__u32 word)
+#if 0  /* Slow but clear version */
+static inline __u32 int_ln_12bits(__u32 word)
 {
        __u32 nbits = 0;
        
-       while (1) {
-               word >>= 1;
-               if (!word)
-                       break;
+       while (word >>= 1)
                nbits++;
-       }
        return nbits;
 }
-#else
-static inline __u32 int_ln(__u32 word)
+#else  /* Faster (more clever) version, courtesy Colin Plumb */
+static inline __u32 int_ln_12bits(__u32 word)
 {
-       __asm__("bsrl %1,%0\n\t"
-               "jnz 1f\n\t"
-               "movl $0,%0\n"
-               "1:"
-               :"=r" (word)
-               :"r" (word));
-       return word;
+       /* Smear msbit right to make an n-bit mask */
+       word |= word >> 8;
+       word |= word >> 4;
+       word |= word >> 2;
+       word |= word >> 1;
+       /* Remove one bit to make this a logarithm */
+       word >>= 1;
+       /* Count the bits set in the word */
+       word -= (word >> 1) & 0x555;
+       word = (word & 0x333) + ((word >> 2) & 0x333);
+       word += (word >> 4);
+       word += (word >> 8);
+       return word & 15;
 }
 #endif
 
@@ -429,19 +506,18 @@ static inline __u32 int_ln(__u32 word)
  */
 static void init_std_data(struct random_bucket *r)
 {
-       __u32 word, *p;
+       __u32 words[2], *p;
        int i;
        struct timeval  tv;
 
        do_gettimeofday(&tv);
-       add_entropy_word(r, tv.tv_sec);
-       add_entropy_word(r, tv.tv_usec);
-
-       for (p = (__u32 *) &system_utsname,
-            i = sizeof(system_utsname) / sizeof(__u32);
-            i ; i--, p++) {
-               memcpy(&word, p, sizeof(__u32));
-               add_entropy_word(r, word);
+       add_entropy_words(r, tv.tv_sec, tv.tv_usec);
+
+       p = (__u32 *)&system_utsname;
+       for (i = sizeof(system_utsname) / sizeof(words); i; i--) {
+               memcpy(words, p, sizeof(words));
+               add_entropy_words(r, words[0], words[1]);
+               p += sizeof(words)/sizeof(*words);
        }
        
 }
@@ -513,54 +589,90 @@ void rand_initialize_blkdev(int major, int mode)
  * This function adds a byte into the entropy "pool".  It does not
  * update the entropy estimate.  The caller must do this if appropriate.
  *
- * The pool is stirred with a primitive polynomial of degree 128
- * over GF(2), namely x^128 + x^99 + x^59 + x^31 + x^9 + x^7 + 1.
- * For a pool of size 64, try x^64+x^62+x^38+x^10+x^6+x+1.
- * 
- * We rotate the input word by a changing number of bits, to help
- * assure that all bits in the entropy get toggled.  Otherwise, if we
- * consistently feed the entropy pool small numbers (like jiffies and
- * scancodes, for example), the upper bits of the entropy pool don't
- * get affected. --- TYT, 10/11/95
+ * This function is tuned for speed above most other considerations.
+ *
+ * The pool is stirred with a primitive polynomial of the appropriate degree,
+ * and then twisted.  We twist by three bits at a time because it's
+ * cheap to do so and helps slightly in the expected case where the
+ * entropy is concentrated in the low-order bits.
  */
-static inline void fast_add_entropy_word(struct random_bucket *r,
-                                        const __u32 input)
+#define MASK(x) ((x) & (POOLWORDS-1))  /* Convenient abreviation */
+static inline void fast_add_entropy_words(struct random_bucket *r,
+                                        __u32 x, __u32 y)
 {
-       unsigned i;
-       int new_rotate;
-       __u32 w;
+       static __u32 const twist_table[8] = {
+                        0, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
+               0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
+       unsigned i, j;
+
+       i = MASK(r->add_ptr - 2);       /* i is always even */
+       r->add_ptr = i;
+
+#ifdef ROTATE_PARANOIA
+       j = r->input_rotate + 14;
+       if (i)
+               j -= 7;
+       r->input_rotate = j & 31;
+
+       x = rotate_left(r->input_rotate, x);
+       y = rotate_left(r->input_rotate, y);
+#endif
 
        /*
-        * Normally, we add 7 bits of rotation to the pool.  At the
-        * beginning of the pool, add an extra 7 bits rotation, so
-        * that successive passes spread the input bits across the
-        * pool evenly.
+        * XOR in the various taps.  Even though logically, we compute
+        * x and then compute y, we read in y then x order because most
+        * caches work slightly better with increasing read addresses.
+        * If a tap is even then we can use the fact that i is even to
+        * avoid a masking operation.  Every polynomial has at least one
+        * even tap, so j is always used.
+        * (Is there a nicer way to arrange this code?)
         */
-       new_rotate = r->input_rotate + 14;
-       if ((i = r->add_ptr--))
-               new_rotate -= 7;
-       r->input_rotate = new_rotate & 31;
-
-       w = rotate_left(r->input_rotate, input);
-       
-       /* XOR in the various taps */
-       w ^= r->pool[(i+TAP1)&(POOLWORDS-1)];
-       w ^= r->pool[(i+TAP2)&(POOLWORDS-1)];
-       w ^= r->pool[(i+TAP3)&(POOLWORDS-1)];
-       w ^= r->pool[(i+TAP4)&(POOLWORDS-1)];
-       w ^= r->pool[(i+TAP5)&(POOLWORDS-1)];
-       w ^= r->pool[i&(POOLWORDS-1)];
-       /* Use a twisted GFSR for the mixing operation */
-       r->pool[i&(POOLWORDS-1)] = (w >> 1) ^ twist_table[w & 1];
+#if TAP1 & 1
+       y ^= r->pool[MASK(i+TAP1)];     x ^= r->pool[MASK(i+TAP1+1)];
+#else
+       j = MASK(i+TAP1);       y ^= r->pool[j];        x ^= r->pool[j+1];
+#endif
+#if TAP2 & 1
+       y ^= r->pool[MASK(i+TAP2)];     x ^= r->pool[MASK(i+TAP2+1)];
+#else
+       j = MASK(i+TAP2);       y ^= r->pool[j];        x ^= r->pool[j+1];
+#endif
+#if TAP3 & 1
+       y ^= r->pool[MASK(i+TAP3)];     x ^= r->pool[MASK(i+TAP3+1)];
+#else
+       j = MASK(i+TAP3);       y ^= r->pool[j];        x ^= r->pool[j+1];
+#endif
+#if TAP4 & 1
+       y ^= r->pool[MASK(i+TAP4)];     x ^= r->pool[MASK(i+TAP4+1)];
+#else
+       j = MASK(i+TAP4);       y ^= r->pool[j];        x ^= r->pool[j+1];
+#endif
+#if TAP5 == 1
+       /* We need to pretend to write pool[i+1] before computing y */
+       y ^= r->pool[i];
+       x ^= r->pool[i+1];
+       x ^= r->pool[MASK(i+TAP5+1)];
+       y ^= r->pool[i+1] = x = (x >> 3) ^ twist_table[x & 7];
+       r->pool[i] = (y >> 3) ^ twist_table[y & 7];
+#else
+# if TAP5 & 1
+       y ^= r->pool[MASK(i+TAP5)];     x ^= r->pool[MASK(i+TAP5+1)];
+# else
+       j = MASK(i+TAP5);       y ^= r->pool[j];        x ^= r->pool[j+1];
+# endif
+       y ^= r->pool[i];
+       x ^= r->pool[i+1];
+       r->pool[i] = (y >> 3) ^ twist_table[y & 7];
+       r->pool[i+1] = (x >> 3) ^ twist_table[x & 7];
+#endif
 }
 
 /*
  * For places where we don't need the inlined version
  */
-static void add_entropy_word(struct random_bucket *r,
-                                   const __u32 input)
+static void add_entropy_words(struct random_bucket *r, __u32 x, __u32 y)
 {
-       fast_add_entropy_word(r, input);
+       fast_add_entropy_words(r, x, y);
 }
 
 /*
@@ -578,19 +690,18 @@ static void add_entropy_word(struct random_bucket *r,
 static void add_timer_randomness(struct random_bucket *r,
                                 struct timer_rand_state *state, unsigned num)
 {
-       int     delta, delta2, delta3;
        __u32           time;
+       __s32           delta, delta2, delta3;
 
 #ifdef RANDOM_BENCHMARK
        begin_benchmark(&timer_benchmark);
 #endif
 #if defined (__i386__)
        if (boot_cpu_data.x86_capability & 16) {
-               unsigned long low, high;
+               __u32 high;
                __asm__(".byte 0x0f,0x31"
-                       :"=a" (low), "=d" (high));
-               time = (__u32) low;
-               num ^= (__u32) high;
+                       :"=a" (time), "=d" (high));
+               num ^= high;
        } else {
                time = jiffies;
        }
@@ -598,42 +709,53 @@ static void add_timer_randomness(struct random_bucket *r,
        time = jiffies;
 #endif
 
-       fast_add_entropy_word(r, (__u32) num);
-       fast_add_entropy_word(r, time);
+       fast_add_entropy_words(r, (__u32)num, time);
        
        /*
-        * Calculate number of bits of randomness we probably
-        * added.  We take into account the first and second order
-        * deltas in order to make our estimate.
+        * Calculate number of bits of randomness we probably added.
+        * We take into account the first, second and third-order deltas
+        * in order to make our estimate.
         */
-       if (!state->dont_count_entropy &&
-           (r->entropy_count < POOLBITS)) {
+       if ((r->entropy_count < POOLBITS) && !state->dont_count_entropy) {
                delta = time - state->last_time;
                state->last_time = time;
-               if (delta < 0) delta = -delta;
 
                delta2 = delta - state->last_delta;
                state->last_delta = delta;
-               if (delta2 < 0) delta2 = -delta2;
 
                delta3 = delta2 - state->last_delta2;
                state->last_delta2 = delta2;
-               if (delta3 < 0) delta3 = -delta3;
 
-               delta = MIN(MIN(delta, delta2), delta3) >> 1;
-               /* Limit entropy estimate to 12 bits */
+               if (delta < 0)
+                       delta = -delta;
+               if (delta2 < 0)
+                       delta2 = -delta2;
+               if (delta3 < 0)
+                       delta3 = -delta3;
+               if (delta > delta2)
+                       delta = delta2;
+               if (delta > delta3)
+                       delta = delta3;
+
+               /*
+                * delta is now minimum absolute delta.
+                * Round down by 1 bit on general principles,
+                * and limit entropy entimate to 12 bits.
+                */
+               delta >>= 1;
                delta &= (1 << 12) - 1;
 
-               r->entropy_count += int_ln(delta);
+               r->entropy_count += int_ln_12bits(delta);
 
                /* Prevent overflow */
                if (r->entropy_count > POOLBITS)
                        r->entropy_count = POOLBITS;
+
+               /* Wake up waiting processes, if we have enough entropy. */
+               if (r->entropy_count >= WAIT_INPUT_BITS)
+                       wake_up_interruptible(&random_read_wait);
        }
                
-       /* Wake up waiting processes, if we have enough entropy. */
-       if (r->entropy_count >= WAIT_INPUT_BITS)
-               wake_up_interruptible(&random_read_wait);
 #ifdef RANDOM_BENCHMARK
        end_benchmark(&timer_benchmark);
 #endif
@@ -672,52 +794,84 @@ void add_blkdev_randomness(int major)
                             0x200+major);
 }
 
+/*
+ * This chunk of code defines a function
+ * void HASH_TRANSFORM(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
+ *             __u32 const data[16])
+ * 
+ * The function hashes the input data to produce a digest in the first
+ * HASH_BUFFER_SIZE words of the digest[] array, and uses HASH_EXTRA_SIZE
+ * more words for internal purposes.  (This buffer is exported so the
+ * caller can wipe it once rather than this code doing it each call,
+ * and tacking it onto the end of the digest[] array is the quick and
+ * dirty way of doing it.)
+ *
+ * It so happens that MD5 and SHA share most of the initial vector
+ * used to initialize the digest[] array before the first call:
+ * 1) 0x67452301
+ * 2) 0xefcdab89
+ * 3) 0x98badcfe
+ * 4) 0x10325476
+ * 5) 0xc3d2e1f0 (SHA only)
+ *
+ * For /dev/random purposes, the length of the data being hashed is
+ * fixed in length (at POOLWORDS words), so appending a bit count in
+ * the usual way is not cryptographically necessary.
+ */
 #define USE_SHA
 
 #ifdef USE_SHA
 
-#define SMALL_VERSION          /* Optimize for space over time */
-
 #define HASH_BUFFER_SIZE 5
+#define HASH_EXTRA_SIZE 80
 #define HASH_TRANSFORM SHATransform
 
+/* Various size/speed tradeoffs are available.  Choose 0..3. */
+#define SHA_CODE_SIZE 0
+
 /*
- * SHA transform algorithm, taken from code written by Peter Gutman,
- * and apparently in the public domain.
+ * SHA transform algorithm, taken from code written by Peter Gutmann,
+ * and placed in the public domain.
  */
 
 /* The SHA f()-functions.  */
 
-#define f1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )           /* Rounds  0-19 */
-#define f2(x,y,z)   ( x ^ y ^ z )                       /* Rounds 20-39 */
-#define f3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )   /* Rounds 40-59 */
-#define f4(x,y,z)   ( x ^ y ^ z )                       /* Rounds 60-79 */
+#define f1(x,y,z)   ( z ^ (x & (y^z)) )                /* Rounds  0-19: x ? y : z */
+#define f2(x,y,z)   (x ^ y ^ z)                        /* Rounds 20-39: XOR */
+#define f3(x,y,z)   ( (x & y) + (z & (x ^ y)) )        /* Rounds 40-59: majority */
+#define f4(x,y,z)   (x ^ y ^ z)                        /* Rounds 60-79: XOR */
 
 /* The SHA Mysterious Constants */
 
-#define K1  0x5A827999L                                 /* Rounds  0-19 */
-#define K2  0x6ED9EBA1L                                 /* Rounds 20-39 */
-#define K3  0x8F1BBCDCL                                 /* Rounds 40-59 */
-#define K4  0xCA62C1D6L                                 /* Rounds 60-79 */
+#define K1  0x5A827999L                        /* Rounds  0-19: sqrt(2) * 2^30 */
+#define K2  0x6ED9EBA1L                        /* Rounds 20-39: sqrt(3) * 2^30 */
+#define K3  0x8F1BBCDCL                        /* Rounds 40-59: sqrt(5) * 2^30 */
+#define K4  0xCA62C1D6L                        /* Rounds 60-79: sqrt(10) * 2^30 */
 
 #define ROTL(n,X)  ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
 
-#define expand(W,i) ( W[ i & 15 ] = \
-                    ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \
-                               W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) )
-
 #define subRound(a, b, c, d, e, f, k, data) \
     ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) )
 
 
-static void SHATransform(__u32 *digest, __u32 *data)
-    {
+static void SHATransform(__u32 digest[85], __u32 const data[16])
+{
     __u32 A, B, C, D, E;     /* Local vars */
-    __u32 eData[ 16 ];       /* Expanded data */
-#ifdef SMALL_VERSION
-    int        i;
     __u32 TEMP;
-#endif
+    int        i;
+#define W (digest + HASH_BUFFER_SIZE)  /* Expanded data array */
+
+    /*
+     * Do the preliminary expansion of 16 to 80 words.  Doing it
+     * out-of-line line this is faster than doing it in-line on
+     * register-starved machines like the x86, and not really any
+     * slower on real processors.
+     */
+    memcpy(W, data, 16*sizeof(__u32));
+    for (i = 0; i < 64; i++) {
+           TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
+           W[i+16] = ROTL(1, TEMP);
+    }
 
     /* Set up first buffer and local data buffer */
     A = digest[ 0 ];
@@ -725,112 +879,161 @@ static void SHATransform(__u32 *digest, __u32 *data)
     C = digest[ 2 ];
     D = digest[ 3 ];
     E = digest[ 4 ];
-    memcpy( eData, data, 16*sizeof(__u32));
 
-#ifdef SMALL_VERSION
+    /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
+#if SHA_CODE_SIZE == 0
     /*
-     * Approximately 50% of the speed of the optimized version, but
+     * Approximately 50% of the speed of the largest version, but
      * takes up 1/16 the space.  Saves about 6k on an i386 kernel.
      */
-    for (i=0; i < 80; i++) {
+    for (i = 0; i < 80; i++) {
+       if (i < 40) {
            if (i < 20)
-                   TEMP = f1(B, C, D) + K1;
-           else if (i < 40)
-                   TEMP = f2(B, C, D) + K2;
-           else if (i < 60)
-                   TEMP = f3(B, C, D) + K3;
+               TEMP = f1(B, C, D) + K1;
            else
-                   TEMP = f4(B, C, D) + K4;
-           TEMP += ROTL (5, A) + E +
-                   ((i > 15) ? expand(eData, i) : eData[i]);
-           E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+               TEMP = f2(B, C, D) + K2;
+       } else {
+           if (i < 60)
+               TEMP = f3(B, C, D) + K3;
+           else
+               TEMP = f4(B, C, D) + K4;
+       }
+       TEMP += ROTL(5, A) + E + W[i];
+       E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+    }
+#elif SHA_CODE_SIZE == 1
+    for (i = 0; i < 20; i++) {
+       TEMP = f1(B, C, D) + K1 + ROTL(5, A) + E + W[i];
+       E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
     }
+    for (; i < 40; i++) {
+       TEMP = f2(B, C, D) + K2 + ROTL(5, A) + E + W[i];
+       E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+    }
+    for (; i < 60; i++) {
+       TEMP = f3(B, C, D) + K3 + ROTL(5, A) + E + W[i];
+       E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+    }
+    for (; i < 80; i++) {
+       TEMP = f4(B, C, D) + K4 + ROTL(5, A) + E + W[i];
+       E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
+    }
+#elif SHA_CODE_SIZE == 2
+    for (i = 0; i < 20; i += 5) {
+       subRound( A, B, C, D, E, f1, K1, W[ i   ] );
+       subRound( E, A, B, C, D, f1, K1, W[ i+1 ] );
+       subRound( D, E, A, B, C, f1, K1, W[ i+2 ] );
+       subRound( C, D, E, A, B, f1, K1, W[ i+3 ] );
+       subRound( B, C, D, E, A, f1, K1, W[ i+4 ] );
+    }
+    for (; i < 40; i += 5) {
+       subRound( A, B, C, D, E, f2, K2, W[ i   ] );
+       subRound( E, A, B, C, D, f2, K2, W[ i+1 ] );
+       subRound( D, E, A, B, C, f2, K2, W[ i+2 ] );
+       subRound( C, D, E, A, B, f2, K2, W[ i+3 ] );
+       subRound( B, C, D, E, A, f2, K2, W[ i+4 ] );
+    }
+    for (; i < 60; i += 5) {
+       subRound( A, B, C, D, E, f3, K3, W[ i   ] );
+       subRound( E, A, B, C, D, f3, K3, W[ i+1 ] );
+       subRound( D, E, A, B, C, f3, K3, W[ i+2 ] );
+       subRound( C, D, E, A, B, f3, K3, W[ i+3 ] );
+       subRound( B, C, D, E, A, f3, K3, W[ i+4 ] );
+    }
+    for (; i < 80; i += 5) {
+       subRound( A, B, C, D, E, f4, K4, W[ i   ] );
+       subRound( E, A, B, C, D, f4, K4, W[ i+1 ] );
+       subRound( D, E, A, B, C, f4, K4, W[ i+2 ] );
+       subRound( C, D, E, A, B, f4, K4, W[ i+3 ] );
+       subRound( B, C, D, E, A, f4, K4, W[ i+4 ] );
+    }
+#elif SHA_CODE_SIZE == 3 /* Really large version */
+    subRound( A, B, C, D, E, f1, K1, W[  0 ] );
+    subRound( E, A, B, C, D, f1, K1, W[  1 ] );
+    subRound( D, E, A, B, C, f1, K1, W[  2 ] );
+    subRound( C, D, E, A, B, f1, K1, W[  3 ] );
+    subRound( B, C, D, E, A, f1, K1, W[  4 ] );
+    subRound( A, B, C, D, E, f1, K1, W[  5 ] );
+    subRound( E, A, B, C, D, f1, K1, W[  6 ] );
+    subRound( D, E, A, B, C, f1, K1, W[  7 ] );
+    subRound( C, D, E, A, B, f1, K1, W[  8 ] );
+    subRound( B, C, D, E, A, f1, K1, W[  9 ] );
+    subRound( A, B, C, D, E, f1, K1, W[ 10 ] );
+    subRound( E, A, B, C, D, f1, K1, W[ 11 ] );
+    subRound( D, E, A, B, C, f1, K1, W[ 12 ] );
+    subRound( C, D, E, A, B, f1, K1, W[ 13 ] );
+    subRound( B, C, D, E, A, f1, K1, W[ 14 ] );
+    subRound( A, B, C, D, E, f1, K1, W[ 15 ] );
+    subRound( E, A, B, C, D, f1, K1, W[ 16 ] );
+    subRound( D, E, A, B, C, f1, K1, W[ 17 ] );
+    subRound( C, D, E, A, B, f1, K1, W[ 18 ] );
+    subRound( B, C, D, E, A, f1, K1, W[ 19 ] );
+
+    subRound( A, B, C, D, E, f2, K2, W[ 20 ] );
+    subRound( E, A, B, C, D, f2, K2, W[ 21 ] );
+    subRound( D, E, A, B, C, f2, K2, W[ 22 ] );
+    subRound( C, D, E, A, B, f2, K2, W[ 23 ] );
+    subRound( B, C, D, E, A, f2, K2, W[ 24 ] );
+    subRound( A, B, C, D, E, f2, K2, W[ 25 ] );
+    subRound( E, A, B, C, D, f2, K2, W[ 26 ] );
+    subRound( D, E, A, B, C, f2, K2, W[ 27 ] );
+    subRound( C, D, E, A, B, f2, K2, W[ 28 ] );
+    subRound( B, C, D, E, A, f2, K2, W[ 29 ] );
+    subRound( A, B, C, D, E, f2, K2, W[ 30 ] );
+    subRound( E, A, B, C, D, f2, K2, W[ 31 ] );
+    subRound( D, E, A, B, C, f2, K2, W[ 32 ] );
+    subRound( C, D, E, A, B, f2, K2, W[ 33 ] );
+    subRound( B, C, D, E, A, f2, K2, W[ 34 ] );
+    subRound( A, B, C, D, E, f2, K2, W[ 35 ] );
+    subRound( E, A, B, C, D, f2, K2, W[ 36 ] );
+    subRound( D, E, A, B, C, f2, K2, W[ 37 ] );
+    subRound( C, D, E, A, B, f2, K2, W[ 38 ] );
+    subRound( B, C, D, E, A, f2, K2, W[ 39 ] );
+    
+    subRound( A, B, C, D, E, f3, K3, W[ 40 ] );
+    subRound( E, A, B, C, D, f3, K3, W[ 41 ] );
+    subRound( D, E, A, B, C, f3, K3, W[ 42 ] );
+    subRound( C, D, E, A, B, f3, K3, W[ 43 ] );
+    subRound( B, C, D, E, A, f3, K3, W[ 44 ] );
+    subRound( A, B, C, D, E, f3, K3, W[ 45 ] );
+    subRound( E, A, B, C, D, f3, K3, W[ 46 ] );
+    subRound( D, E, A, B, C, f3, K3, W[ 47 ] );
+    subRound( C, D, E, A, B, f3, K3, W[ 48 ] );
+    subRound( B, C, D, E, A, f3, K3, W[ 49 ] );
+    subRound( A, B, C, D, E, f3, K3, W[ 50 ] );
+    subRound( E, A, B, C, D, f3, K3, W[ 51 ] );
+    subRound( D, E, A, B, C, f3, K3, W[ 52 ] );
+    subRound( C, D, E, A, B, f3, K3, W[ 53 ] );
+    subRound( B, C, D, E, A, f3, K3, W[ 54 ] );
+    subRound( A, B, C, D, E, f3, K3, W[ 55 ] );
+    subRound( E, A, B, C, D, f3, K3, W[ 56 ] );
+    subRound( D, E, A, B, C, f3, K3, W[ 57 ] );
+    subRound( C, D, E, A, B, f3, K3, W[ 58 ] );
+    subRound( B, C, D, E, A, f3, K3, W[ 59 ] );
+
+    subRound( A, B, C, D, E, f4, K4, W[ 60 ] );
+    subRound( E, A, B, C, D, f4, K4, W[ 61 ] );
+    subRound( D, E, A, B, C, f4, K4, W[ 62 ] );
+    subRound( C, D, E, A, B, f4, K4, W[ 63 ] );
+    subRound( B, C, D, E, A, f4, K4, W[ 64 ] );
+    subRound( A, B, C, D, E, f4, K4, W[ 65 ] );
+    subRound( E, A, B, C, D, f4, K4, W[ 66 ] );
+    subRound( D, E, A, B, C, f4, K4, W[ 67 ] );
+    subRound( C, D, E, A, B, f4, K4, W[ 68 ] );
+    subRound( B, C, D, E, A, f4, K4, W[ 69 ] );
+    subRound( A, B, C, D, E, f4, K4, W[ 70 ] );
+    subRound( E, A, B, C, D, f4, K4, W[ 71 ] );
+    subRound( D, E, A, B, C, f4, K4, W[ 72 ] );
+    subRound( C, D, E, A, B, f4, K4, W[ 73 ] );
+    subRound( B, C, D, E, A, f4, K4, W[ 74 ] );
+    subRound( A, B, C, D, E, f4, K4, W[ 75 ] );
+    subRound( E, A, B, C, D, f4, K4, W[ 76 ] );
+    subRound( D, E, A, B, C, f4, K4, W[ 77 ] );
+    subRound( C, D, E, A, B, f4, K4, W[ 78 ] );
+    subRound( B, C, D, E, A, f4, K4, W[ 79 ] );
 #else
-    /* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
-    subRound( A, B, C, D, E, f1, K1, eData[  0 ] );
-    subRound( E, A, B, C, D, f1, K1, eData[  1 ] );
-    subRound( D, E, A, B, C, f1, K1, eData[  2 ] );
-    subRound( C, D, E, A, B, f1, K1, eData[  3 ] );
-    subRound( B, C, D, E, A, f1, K1, eData[  4 ] );
-    subRound( A, B, C, D, E, f1, K1, eData[  5 ] );
-    subRound( E, A, B, C, D, f1, K1, eData[  6 ] );
-    subRound( D, E, A, B, C, f1, K1, eData[  7 ] );
-    subRound( C, D, E, A, B, f1, K1, eData[  8 ] );
-    subRound( B, C, D, E, A, f1, K1, eData[  9 ] );
-    subRound( A, B, C, D, E, f1, K1, eData[ 10 ] );
-    subRound( E, A, B, C, D, f1, K1, eData[ 11 ] );
-    subRound( D, E, A, B, C, f1, K1, eData[ 12 ] );
-    subRound( C, D, E, A, B, f1, K1, eData[ 13 ] );
-    subRound( B, C, D, E, A, f1, K1, eData[ 14 ] );
-    subRound( A, B, C, D, E, f1, K1, eData[ 15 ] );
-    subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) );
-    subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) );
-    subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) );
-    subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) );
-
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) );
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) );
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) );
-    subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) );
-    subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) );
-    subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) );
-    subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) );
-    subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) );
-
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) );
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) );
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) );
-    subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) );
-    subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) );
-    subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) );
-    subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) );
-    subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) );
-
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) );
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) );
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) );
-    subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) );
-    subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) );
-    subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) );
-    subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) );
-    subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) );
-#endif /* SMALL_VERSION */
+#error Illegal SHA_CODE_SIZE
+#endif
 
     /* Build message digest */
     digest[ 0 ] += A;
@@ -838,7 +1041,10 @@ static void SHATransform(__u32 *digest, __u32 *data)
     digest[ 2 ] += C;
     digest[ 3 ] += D;
     digest[ 4 ] += E;
-    }
+
+       /* W is wiped by the caller */
+#undef W
+}
 
 #undef ROTL
 #undef f1
@@ -849,11 +1055,12 @@ static void SHATransform(__u32 *digest, __u32 *data)
 #undef K2
 #undef K3      
 #undef K4      
-#undef expand
 #undef subRound
        
-#else
+#else /* !USE_SHA - Use MD5 */
+
 #define HASH_BUFFER_SIZE 4
+#define HASH_EXTRA_SIZE 0
 #define HASH_TRANSFORM MD5Transform
        
 /*
@@ -881,8 +1088,7 @@ static void SHATransform(__u32 *digest, __u32 *data)
  * reflect the addition of 16 longwords of new data.  MD5Update blocks
  * the data and converts bytes into longwords for this routine.
  */
-static void MD5Transform(__u32 buf[4],
-                        __u32 const in[16])
+static void MD5Transform(__u32 buf[HASH_BUFFER_SIZE], __u32 const in[16])
 {
        __u32 a, b, c, d;
 
@@ -971,10 +1177,10 @@ static void MD5Transform(__u32 buf[4],
 #undef F4
 #undef MD5STEP
 
-#endif
+#endif /* !USE_SHA */
 
 
-#if POOLWORDS % 16
+#if POOLWORDS % 16 != 0
 #error extract_entropy() assumes that POOLWORDS is a multiple of 16 words.
 #endif
 /*
@@ -987,8 +1193,8 @@ static ssize_t extract_entropy(struct random_bucket *r, char * buf,
                               size_t nbytes, int to_user)
 {
        ssize_t ret, i;
-       __u32 tmp[HASH_BUFFER_SIZE];
-       char *cp,*dp;
+       __u32 tmp[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
+       __u32 x;
 
        add_timer_randomness(r, &extract_timer_state, nbytes);
        
@@ -1016,31 +1222,33 @@ static ssize_t extract_entropy(struct random_bucket *r, char * buf,
 #endif
                for (i = 0; i < POOLWORDS; i += 16)
                        HASH_TRANSFORM(tmp, r->pool+i);
-               /* Modify pool so next hash will produce different results */
-               add_entropy_word(r, tmp[0]);
-               add_entropy_word(r, tmp[1]);
-               add_entropy_word(r, tmp[2]);
-               add_entropy_word(r, tmp[3]);
-#ifdef USE_SHA
-               add_entropy_word(r, tmp[4]);
-#endif
-               /*
-                * Run the hash transform one more time, since we want
-                * to add at least minimal obscuring of the inputs to
-                * add_entropy_word().
-                */
-               HASH_TRANSFORM(tmp, r->pool);
 
                /*
-                * In case the hash function has some recognizable
-                * output pattern, we fold it in half.
+                * The following code does two separate things that happen
+                * to both work two words at a time, so are convenient
+                * to do together.
+                *
+                * First, this feeds the output back into the pool so
+                * that the next call will return different results.
+                * Any perturbation of the pool's state would do, even
+                * changing one bit, but this mixes the pool nicely.
+                *
+                * Second, this folds the output in half to hide the data
+                * fed back into the pool from the user and further mask
+                * any patterns in the hash output.  (The exact folding
+                * pattern is not important; the one used here is quick.)
                 */
-               cp = (char *) tmp;
-               dp = cp + (HASH_BUFFER_SIZE*sizeof(__u32)) - 1;
-               for (i=0; i <  HASH_BUFFER_SIZE*sizeof(__u32)/2; i++) {
-                       *cp ^= *dp;
-                       cp++;  dp--;
+               for (i = 0; i <  HASH_BUFFER_SIZE/2; i++) {
+                       x = tmp[i + (HASH_BUFFER_SIZE+1)/2];
+                       add_entropy_words(r, tmp[i], x);
+                       tmp[i] ^= x;
                }
+#if HASH_BUFFER_SIZE & 1       /* There's a middle word to deal with */
+               x = tmp[HASH_BUFFER_SIZE/2];
+               add_entropy_words(r, x, (__u32)buf);
+               x ^= (x >> 16);         /* Fold it in half */
+               ((__u16 *)tmp)[HASH_BUFFER_SIZE-1] = (__u16)x;
+#endif
                
                /* Copy data to destination buffer */
                i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
@@ -1059,7 +1267,7 @@ static ssize_t extract_entropy(struct random_bucket *r, char * buf,
                        schedule();
        }
 
-       /* Wipe data from memory */
+       /* Wipe data just returned from memory */
        memset(tmp, 0, sizeof(tmp));
        
        return ret;
@@ -1105,8 +1313,7 @@ random_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos)
                }
                n = extract_entropy(&random_state, buf, n, 1);
                if (n < 0) {
-                       if (count == 0)
-                               retval = n;
+                       retval = n;
                        break;
                }
                count += n;
@@ -1154,33 +1361,36 @@ static ssize_t
 random_write(struct file * file, const char * buffer,
             size_t count, loff_t *ppos)
 {
-       ssize_t         i, bytes, ret = 0;
+       int             ret = 0;
+       size_t          bytes;
+       unsigned        i;
        __u32           buf[16];
        const char      *p = buffer;
-       ssize_t         c = count;
+       size_t          c = count;
 
        while (c > 0) {
                bytes = MIN(c, sizeof(buf));
 
                bytes -= copy_from_user(&buf, p, bytes);
                if (!bytes) {
-                       if (!ret)
-                               ret = -EFAULT;
+                       ret = -EFAULT;
                        break;
                }
                c -= bytes;
                p += bytes;
-               ret += bytes;
                
-               i = (bytes+sizeof(__u32)-1) / sizeof(__u32);
-               while (i--)
-                       add_entropy_word(&random_state, buf[i]);
+               i = (unsigned)((bytes-1) / (2 * sizeof(__u32)));
+               do {
+                       add_entropy_words(&random_state, buf[2*i], buf[2*i+1]);
+               } while (i--);
        }
-       if (ret > 0) {
+       if (p == buffer) {
+               return (ssize_t)ret;
+       } else {
                file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
                mark_inode_dirty(file->f_dentry->d_inode);
+               return (ssize_t)(p - buffer);
        }
-       return ret;
 }
 
 static int
@@ -1344,19 +1554,17 @@ struct file_operations urandom_fops = {
 #define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
 #define H(x, y, z) ((x) ^ (y) ^ (z))
 
-#define ROTL(n,X)  ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) )
-
-/* FF, GG and HH are MD4 transformations for rounds 1, 2 and 3 */
-/* Rotation is separate from addition to prevent recomputation */
-#define FF(a, b, c, d, x, s) \
-  {(a) += F ((b), (c), (d)) + (x); \
-   (a) = ROTL ((s), (a));}
-#define GG(a, b, c, d, x, s) \
-  {(a) += G ((b), (c), (d)) + (x) + 013240474631UL; \
-   (a) = ROTL ((s), (a));}
-#define HH(a, b, c, d, x, s) \
-  {(a) += H ((b), (c), (d)) + (x) + 015666365641UL; \
-   (a) = ROTL ((s), (a));}
+/*
+ * The generic round function.  The application is so specific that
+ * we don't bother protecting all the arguments with parens, as is generally
+ * good macro practice, in favor of extra legibility.
+ * Rotation is separate from addition to prevent recomputation
+ */
+#define ROUND(f, a, b, c, d, x, s)     \
+       (a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
+#define K1 0
+#define K2 013240474631UL
+#define K3 015666365641UL
 
 /*
  * Basic cut-down MD4 transform.  Returns only 32 bits of result.
@@ -1366,38 +1574,99 @@ static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
        __u32   a = buf[0], b = buf[1], c = buf[2], d = buf[3];
 
        /* Round 1 */
-       FF (a, b, c, d, in[ 0],  3);
-       FF (d, a, b, c, in[ 1],  7);
-       FF (c, d, a, b, in[ 2], 11);
-       FF (b, c, d, a, in[ 3], 19);
-       FF (a, b, c, d, in[ 4],  3);
-       FF (d, a, b, c, in[ 5],  7);
-       FF (c, d, a, b, in[ 6], 11);
-       FF (b, c, d, a, in[ 7], 19);
+       ROUND(F, a, b, c, d, in[0] + K1,  3);
+       ROUND(F, d, a, b, c, in[1] + K1,  7);
+       ROUND(F, c, d, a, b, in[2] + K1, 11);
+       ROUND(F, b, c, d, a, in[3] + K1, 19);
+       ROUND(F, a, b, c, d, in[4] + K1,  3);
+       ROUND(F, d, a, b, c, in[5] + K1,  7);
+       ROUND(F, c, d, a, b, in[6] + K1, 11);
+       ROUND(F, b, c, d, a, in[7] + K1, 19);
+
+       /* Round 2 */
+       ROUND(G, a, b, c, d, in[1] + K2,  3);
+       ROUND(G, d, a, b, c, in[3] + K2,  5);
+       ROUND(G, c, d, a, b, in[5] + K2,  9);
+       ROUND(G, b, c, d, a, in[7] + K2, 13);
+       ROUND(G, a, b, c, d, in[0] + K2,  3);
+       ROUND(G, d, a, b, c, in[2] + K2,  5);
+       ROUND(G, c, d, a, b, in[4] + K2,  9);
+       ROUND(G, b, c, d, a, in[6] + K2, 13);
+
+       /* Round 3 */
+       ROUND(H, a, b, c, d, in[3] + K3,  3);
+       ROUND(H, d, a, b, c, in[7] + K3,  9);
+       ROUND(H, c, d, a, b, in[2] + K3, 11);
+       ROUND(H, b, c, d, a, in[6] + K3, 15);
+       ROUND(H, a, b, c, d, in[1] + K3,  3);
+       ROUND(H, d, a, b, c, in[5] + K3,  9);
+       ROUND(H, c, d, a, b, in[0] + K3, 11);
+       ROUND(H, b, c, d, a, in[4] + K3, 15);
+
+       return buf[1] + b;      /* "most hashed" word */
+       /* Alternative: return sum of all words? */
+}
+
+#if 0  /* May be needed for IPv6 */
+
+static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
+{
+       __u32   a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+       /* Round 1 */
+       ROUND(F, a, b, c, d, in[ 0] + K1,  3);
+       ROUND(F, d, a, b, c, in[ 1] + K1,  7);
+       ROUND(F, c, d, a, b, in[ 2] + K1, 11);
+       ROUND(F, b, c, d, a, in[ 3] + K1, 19);
+       ROUND(F, a, b, c, d, in[ 4] + K1,  3);
+       ROUND(F, d, a, b, c, in[ 5] + K1,  7);
+       ROUND(F, c, d, a, b, in[ 6] + K1, 11);
+       ROUND(F, b, c, d, a, in[ 7] + K1, 19);
+       ROUND(F, a, b, c, d, in[ 8] + K1,  3);
+       ROUND(F, d, a, b, c, in[ 9] + K1,  7);
+       ROUND(F, c, d, a, b, in[10] + K1, 11);
+       ROUND(F, b, c, d, a, in[11] + K1, 19);
 
        /* Round 2 */
-       GG (a, b, c, d, in[ 0],  3);
-       GG (d, a, b, c, in[ 4],  5);
-       GG (c, d, a, b, in[ 1],  9);
-       GG (b, c, d, a, in[ 5], 13);
-       GG (a, b, c, d, in[ 2],  3);
-       GG (d, a, b, c, in[ 6],  5);
-       GG (c, d, a, b, in[ 3],  9);
-       GG (b, c, d, a, in[ 7], 13);
+       ROUND(G, a, b, c, d, in[ 1] + K2,  3);
+       ROUND(G, d, a, b, c, in[ 3] + K2,  5);
+       ROUND(G, c, d, a, b, in[ 5] + K2,  9);
+       ROUND(G, b, c, d, a, in[ 7] + K2, 13);
+       ROUND(G, a, b, c, d, in[ 9] + K2,  3);
+       ROUND(G, d, a, b, c, in[11] + K2,  5);
+       ROUND(G, c, d, a, b, in[ 0] + K2,  9);
+       ROUND(G, b, c, d, a, in[ 2] + K2, 13);
+       ROUND(G, a, b, c, d, in[ 4] + K2,  3);
+       ROUND(G, d, a, b, c, in[ 6] + K2,  5);
+       ROUND(G, c, d, a, b, in[ 8] + K2,  9);
+       ROUND(G, b, c, d, a, in[10] + K2, 13);
 
        /* Round 3 */
-       HH (a, b, c, d, in[ 0],  3);
-       HH (d, a, b, c, in[ 4],  9);
-       HH (c, d, a, b, in[ 2], 11);
-       HH (b, c, d, a, in[ 6], 15);
-       HH (a, b, c, d, in[ 1],  3);
-       HH (d, a, b, c, in[ 5],  9);
-       HH (c, d, a, b, in[ 3], 11);
-       HH (b, c, d, a, in[ 7], 15);
+       ROUND(H, a, b, c, d, in[ 3] + K3,  3);
+       ROUND(H, d, a, b, c, in[ 7] + K3,  9);
+       ROUND(H, c, d, a, b, in[11] + K3, 11);
+       ROUND(H, b, c, d, a, in[ 2] + K3, 15);
+       ROUND(H, a, b, c, d, in[ 6] + K3,  3);
+       ROUND(H, d, a, b, c, in[10] + K3,  9);
+       ROUND(H, c, d, a, b, in[ 1] + K3, 11);
+       ROUND(H, b, c, d, a, in[ 5] + K3, 15);
+       ROUND(H, a, b, c, d, in[ 9] + K3,  3);
+       ROUND(H, d, a, b, c, in[ 0] + K3,  9);
+       ROUND(H, c, d, a, b, in[ 4] + K3, 11);
+       ROUND(H, b, c, d, a, in[ 8] + K3, 15);
 
        return buf[1] + b;      /* "most hashed" word */
        /* Alternative: return sum of all words? */
 }
+#endif
+
+#undef ROUND
+#undef F
+#undef G
+#undef H
+#undef K1
+#undef K2
+#undef K3
 
 /* This should not be decreased so low that ISNs wrap too fast. */
 #define REKEY_INTERVAL 300
@@ -1417,8 +1686,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
         */
        do_gettimeofday(&tv);   /* We need the usecs below... */
 
-       if (!rekey_time ||
-           (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
+       if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {
                rekey_time = tv.tv_sec;
                /* First three words are overwritten below. */
                get_random_bytes(&secret+3, sizeof(secret)-12);
@@ -1439,7 +1707,7 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
        secret[2]=(sport << 16) + dport;
 
        seq = (halfMD4Transform(secret+8, secret) &
-              ((1<<HASH_BITS)-1)) + (count << HASH_BITS);
+              ((1<<HASH_BITS)-1)) + count;
 
        /*
         *      As close as possible to RFC 793, which
@@ -1463,53 +1731,97 @@ __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
  * Dan Bernstein and Eric Schenk.
  *
  * For linux I implement the 1 minute counter by looking at the jiffies clock.
- * The count is passed in as a parameter;
- *
+ * The count is passed in as a parameter, so this code doesn't much care.
  */
-__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
-                __u16 sport, __u16 dport, __u32 sseq, __u32 count)
+
+#define COOKIEBITS 24  /* Upper bits store count */
+#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+
+static int     syncookie_init = 0;
+static __u32   syncookie_secret[2][16-3+HASH_BUFFER_SIZE];
+
+__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
+               __u16 dport, __u32 sseq, __u32 count, __u32 data)
 {
-       static int      is_init = 0;
-       static __u32    secret[2][16];
-       __u32           tmp[16];
-       __u32           seq;
+       __u32   tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
+       __u32   seq;
 
        /*
-        * Pick two random secret the first time we open a TCP connection.
+        * Pick two random secrets the first time we need a cookie.
         */
-       if (is_init == 0) {
-               get_random_bytes(&secret[0], sizeof(secret[0]));
-               get_random_bytes(&secret[1], sizeof(secret[1]));
-               is_init = 1;
+       if (syncookie_init == 0) {
+               get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
+               syncookie_init = 1;
        }
 
        /*
         * Compute the secure sequence number.
         * The output should be:
-        *   MD5(sec1,saddr,sport,daddr,dport,sec1) + their sequence number
-         *      + (count * 2^24)
-        *      + (MD5(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
-        * Where count increases every minute by 1.
+        *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
+        *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
+        * Where sseq is their sequence number and count increases every
+        * minute by 1.
+        * As an extra hack, we add a small "data" value that encodes the
+        * MSS into the second hash value.
         */
 
-       memcpy(tmp, secret[0], sizeof(tmp));
-       tmp[8]=saddr;
-       tmp[9]=daddr;
-       tmp[10]=(sport << 16) + dport;
-       HASH_TRANSFORM(tmp, tmp);
-       seq = tmp[1];
-
-       memcpy(tmp, secret[1], sizeof(tmp));
-       tmp[8]=saddr;
-       tmp[9]=daddr;
-       tmp[10]=(sport << 16) + dport;
-       tmp[11]=count;  /* minute counter */
-       HASH_TRANSFORM(tmp, tmp);
-
-       seq += sseq + (count << 24) + (tmp[1] & 0x00ffffff);
+       memcpy(tmp+3, syncookie_secret[0], sizeof(syncookie_secret[0]));
+       tmp[0]=saddr;
+       tmp[1]=daddr;
+       tmp[2]=(sport << 16) + dport;
+       HASH_TRANSFORM(tmp+16, tmp);
+       seq = tmp[17] + sseq + (count << COOKIEBITS);
+
+       memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));
+       tmp[0]=saddr;
+       tmp[1]=daddr;
+       tmp[2]=(sport << 16) + dport;
+       tmp[3] = count; /* minute counter */
+       HASH_TRANSFORM(tmp+16, tmp);
+
+       /* Add in the second hash and the data */
+       return seq + ((tmp[17] + data) & COOKIEMASK);
+}
 
-       /* Zap lower 3 bits to leave room for the MSS representation */
-       return (seq & 0xfffff8);
+/*
+ * This retrieves the small "data" value from the syncookie.
+ * If the syncookie is bad, the data returned will be out of
+ * range.  This must be checked by the caller.
+ *
+ * The count value used to generate the cookie must be within
+ * "maxdiff" if the current (passed-in) "count".  The return value
+ * is (__u32)-1 if this test fails.
+ */
+__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
+               __u16 dport, __u32 sseq, __u32 count, __u32 maxdiff)
+{
+       __u32   tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
+       __u32   diff;
+
+       if (syncookie_init == 0)
+               return (__u32)-1;       /* Well, duh! */
+
+       /* Strip away the layers from the cookie */
+       memcpy(tmp+3, syncookie_secret[0], sizeof(syncookie_secret[0]));
+       tmp[0]=saddr;
+       tmp[1]=daddr;
+       tmp[2]=(sport << 16) + dport;
+       HASH_TRANSFORM(tmp+16, tmp);
+       cookie -= tmp[17] + sseq;
+       /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
+
+       diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);
+       if (diff >= maxdiff)
+               return (__u32)-1;
+
+       memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));
+       tmp[0] = saddr;
+       tmp[1] = daddr;
+       tmp[2] = (sport << 16) + dport;
+       tmp[3] = count - diff;  /* minute counter */
+       HASH_TRANSFORM(tmp+16, tmp);
+
+       return (cookie - tmp[17]) & COOKIEMASK; /* Leaving the data behind */
 }
 #endif
 
@@ -1532,7 +1844,7 @@ static inline unsigned long long get_clock_cnt(void)
 {
        unsigned long low, high;
        __asm__(".byte 0x0f,0x31" :"=a" (low), "=d" (high));
-       return (((unsigned long long) high << 31) | low); 
+       return (((unsigned long long) high << 32) | low); 
 }
 
 __initfunc(static void
index 5ac51c5c6243403f2fb6d899455a83a1cec4adbe..69216bb98edb8a1ae2872612097772b9d9ce78ce 100644 (file)
 #endif
        
 static char *serial_name = "Serial driver";
-static char *serial_version = "4.25";
+static char *serial_version = "4.26";
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
@@ -830,13 +830,14 @@ static void rs_timer(void)
        static unsigned long last_strobe = 0;
        struct async_struct *info;
        unsigned int    i;
+       unsigned long flags;
 
        if ((jiffies - last_strobe) >= RS_STROBE_TIME) {
                for (i=1; i < NR_IRQS; i++) {
                        info = IRQ_ports[i];
                        if (!info)
                                continue;
-                       cli();
+                       save_flags(flags); cli();
 #ifdef CONFIG_SERIAL_SHARE_IRQ
                        if (info->next_port) {
                                do {
@@ -854,7 +855,7 @@ static void rs_timer(void)
                        } else
 #endif /* CONFIG_SERIAL_SHARE_IRQ */
                                rs_interrupt_single(i, NULL, NULL);
-                       sti();
+                       restore_flags(flags);
                }
        }
        last_strobe = jiffies;
@@ -862,13 +863,13 @@ static void rs_timer(void)
        timer_active |= 1 << RS_TIMER;
 
        if (IRQ_ports[0]) {
-               cli();
+               save_flags(flags); cli();
 #ifdef CONFIG_SERIAL_SHARE_IRQ
                rs_interrupt(0, NULL, NULL);
 #else
                rs_interrupt_single(0, NULL, NULL);
 #endif
-               sti();
+               restore_flags(flags);
 
                timer_table[RS_TIMER].expires = jiffies + IRQ_timeout[0] - 2;
        }
@@ -1501,12 +1502,13 @@ static int rs_chars_in_buffer(struct tty_struct *tty)
 static void rs_flush_buffer(struct tty_struct *tty)
 {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
-                               
+       unsigned long flags;
+       
        if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
                return;
-       cli();
+       save_flags(flags); cli();
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       sti();
+       restore_flags(flags);
        wake_up_interruptible(&tty->write_wait);
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
            tty->ldisc.write_wakeup)
@@ -1543,6 +1545,7 @@ static void rs_send_xchar(struct tty_struct *tty, char ch)
 static void rs_throttle(struct tty_struct * tty)
 {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
        
@@ -1559,14 +1562,15 @@ static void rs_throttle(struct tty_struct * tty)
        if (tty->termios->c_cflag & CRTSCTS)
                info->MCR &= ~UART_MCR_RTS;
 
-       cli();
+       save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
-       sti();
+       restore_flags(flags);
 }
 
 static void rs_unthrottle(struct tty_struct * tty)
 {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
+       unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
        char    buf[64];
        
@@ -1585,9 +1589,9 @@ static void rs_unthrottle(struct tty_struct * tty)
        }
        if (tty->termios->c_cflag & CRTSCTS)
                info->MCR |= UART_MCR_RTS;
-       cli();
+       save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
-       sti();
+       restore_flags(flags);
 }
 
 /*
@@ -1656,7 +1660,9 @@ static int set_serial_info(struct async_struct * info,
        new_serial.irq = irq_cannonicalize(new_serial.irq);
 
        if ((new_serial.irq >= NR_IRQS) || (new_serial.port > 0xffff) ||
-           (new_serial.type < PORT_UNKNOWN) || (new_serial.type > PORT_MAX)) {
+           (new_serial.type < PORT_UNKNOWN) ||
+           (new_serial.type > PORT_MAX) ||
+           (new_serial.xmit_fifo_size == 0)) {
                return -EINVAL;
        }
 
@@ -1745,10 +1751,11 @@ static int get_lsr_info(struct async_struct * info, unsigned int *value)
 {
        unsigned char status;
        unsigned int result;
+       unsigned long flags;
 
-       cli();
+       save_flags(flags); cli();
        status = serial_in(info, UART_LSR);
-       sti();
+       restore_flags(flags);
        result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
        return put_user(result,value);
 }
@@ -1758,11 +1765,12 @@ static int get_modem_info(struct async_struct * info, unsigned int *value)
 {
        unsigned char control, status;
        unsigned int result;
+       unsigned long flags;
 
        control = info->MCR;
-       cli();
+       save_flags(flags); cli();
        status = serial_in(info, UART_MSR);
-       sti();
+       restore_flags(flags);
        result =  ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
                | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
 #ifdef TIOCM_OUT1
@@ -1781,6 +1789,7 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd,
 {
        int error;
        unsigned int arg;
+       unsigned long flags;
 
        error = get_user(arg, value);
        if (error)
@@ -1827,9 +1836,9 @@ static int set_modem_info(struct async_struct * info, unsigned int cmd,
        default:
                return -EINVAL;
        }
-       cli();
+       save_flags(flags); cli();
        serial_out(info, UART_MCR, info->MCR);
-       sti();
+       restore_flags(flags);
        return 0;
 }
 
@@ -1846,7 +1855,9 @@ static int do_autoconfig(struct async_struct * info)
        shutdown(info);
 
        autoconfig(info->state);
-       if ((info->state->flags & ASYNC_AUTO_IRQ) && (info->state->port != 0))
+       if ((info->state->flags & ASYNC_AUTO_IRQ) &&
+           (info->state->port != 0) &&
+           (info->state->type != PORT_UNKNOWN))
                info->state->irq = detect_uart_irq(info->state);
 
        retval = startup(info);
@@ -2000,7 +2011,8 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
        struct async_struct * info = (struct async_struct *)tty->driver_data;
        struct async_icount cprev, cnow;        /* kernel counter temps */
        struct serial_icounter_struct *p_cuser; /* user space */
-
+       unsigned long flags;
+       
        if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
                return -ENODEV;
 
@@ -2052,18 +2064,18 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                 * Caller should use TIOCGICOUNT to see which one it was
                 */
                case TIOCMIWAIT:
-                       cli();
+                       save_flags(flags); cli();
                        /* note the counters on entry */
                        cprev = info->state->icount;
-                       sti();
+                       restore_flags(flags);
                        while (1) {
                                interruptible_sleep_on(&info->delta_msr_wait);
                                /* see if a signal did it */
                                if (signal_pending(current))
                                        return -ERESTARTSYS;
-                               cli();
+                               save_flags(flags); cli();
                                cnow = info->state->icount; /* atomic copy */
-                               sti();
+                               restore_flags(flags);
                                if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
                                    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
                                        return -EIO; /* no change => error */
@@ -2084,9 +2096,9 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                 *     RI where only 0->1 is counted.
                 */
                case TIOCGICOUNT:
-                       cli();
+                       save_flags(flags); cli();
                        cnow = info->state->icount;
-                       sti();
+                       restore_flags(flags);
                        p_cuser = (struct serial_icounter_struct *) arg;
                        error = put_user(cnow.cts, &p_cuser->cts);
                        if (error) return error;
@@ -2096,6 +2108,26 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        if (error) return error;
                        error = put_user(cnow.dcd, &p_cuser->dcd);
                        if (error) return error;
+                       error = put_user(cnow.rx, &p_cuser->rx);
+                       if (error) return error;
+                       error = put_user(cnow.tx, &p_cuser->tx);
+                       if (error) return error;
+                       error = put_user(cnow.frame, &p_cuser->frame);
+                       if (error) return error;
+                       error = put_user(cnow.overrun, &p_cuser->overrun);
+                       if (error) return error;
+                       error = put_user(cnow.parity, &p_cuser->parity);
+                       if (error) return error;
+                       error = put_user(cnow.brk, &p_cuser->brk);
+                       if (error) return error;
+                       error = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
+                       if (error) return error;                        
+                       return 0;
+
+               case TIOCSERGWILD:
+               case TIOCSERSWILD:
+                       /* "setserial -W" is called in Debian boot */
+                       printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
                        return 0;
 
                default:
@@ -2107,7 +2139,8 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
 static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
 {
        struct async_struct *info = (struct async_struct *)tty->driver_data;
-
+       unsigned long flags;
+       
        if (   (tty->termios->c_cflag == old_termios->c_cflag)
            && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
                == RELEVANT_IFLAG(old_termios->c_iflag)))
@@ -2119,9 +2152,9 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
        if ((old_termios->c_cflag & CBAUD) &&
            !(tty->termios->c_cflag & CBAUD)) {
                info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-               cli();
+               save_flags(flags); cli();
                serial_out(info, UART_MCR, info->MCR);
-               sti();
+               restore_flags(flags);
        }
        
        /* Handle transition away from B0 status */
@@ -2132,9 +2165,9 @@ static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
                    !test_bit(TTY_THROTTLED, &tty->flags)) {
                        info->MCR |= UART_MCR_RTS;
                }
-               cli();
+               save_flags(flags); cli();
                serial_out(info, UART_MCR, info->MCR);
-               sti();
+               restore_flags(flags);
        }
        
        /* Handle turning off CRTSCTS */
@@ -2284,6 +2317,9 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
        if (info->state->type == PORT_UNKNOWN)
                return;
 
+       if (info->xmit_fifo_size == 0)
+               return; /* Just in case.... */
+
        orig_jiffies = jiffies;
        /*
         * Set the check interval to be 1/5 of the estimated time to
@@ -2355,7 +2391,8 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        struct wait_queue wait = { current, NULL };
        struct serial_state *state = info->state;
        int             retval;
-       int             do_clocal = 0;
+       int             do_clocal = 0, extra_count = 0;
+       unsigned long   flags;
 
        /*
         * If the device is in the middle of being closed, then block
@@ -2425,19 +2462,21 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        printk("block_til_ready before block: ttys%d, count = %d\n",
               state->line, state->count);
 #endif
-       cli();
-       if (!tty_hung_up_p(filp)) 
+       save_flags(flags); cli();
+       if (!tty_hung_up_p(filp)) {
+               extra_count = 1;
                state->count--;
-       sti();
+       }
+       restore_flags(flags);
        info->blocked_open++;
        while (1) {
-               cli();
+               save_flags(flags); cli();
                if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
                    (tty->termios->c_cflag & CBAUD))
                        serial_out(info, UART_MCR,
                                   serial_inp(info, UART_MCR) |
                                   (UART_MCR_DTR | UART_MCR_RTS));
-               sti();
+               restore_flags(flags);
                current->state = TASK_INTERRUPTIBLE;
                if (tty_hung_up_p(filp) ||
                    !(info->flags & ASYNC_INITIALIZED)) {
@@ -2468,7 +2507,7 @@ static int block_til_ready(struct tty_struct *tty, struct file * filp,
        }
        current->state = TASK_RUNNING;
        remove_wait_queue(&info->open_wait, &wait);
-       if (!tty_hung_up_p(filp))
+       if (extra_count)
                state->count++;
        info->blocked_open--;
 #ifdef SERIAL_DEBUG_OPEN
@@ -2619,6 +2658,7 @@ static inline int line_info(char *buf, struct serial_state *state)
        struct async_struct *info = state->info, scr_info;
        char    stat_buf[30], control, status;
        int     ret;
+       unsigned long flags;
 
        ret = sprintf(buf, "%d: uart:%s port:%X irq:%d",
                      state->line, uart_config[state->type].name, 
@@ -2641,10 +2681,10 @@ static inline int line_info(char *buf, struct serial_state *state)
                info->quot = 0;
                info->tty = 0;
        }
-       cli();
+       save_flags(flags); cli();
        status = serial_in(info, UART_MSR);
        control = info ? info->MCR : serial_in(info, UART_MCR);
-       sti();
+       restore_flags(flags); 
        
        stat_buf[0] = 0;
        stat_buf[1] = 0;
@@ -2691,12 +2731,13 @@ static inline int line_info(char *buf, struct serial_state *state)
 int rs_read_proc(char *page, char **start, off_t off, int count,
                 int *eof, void *data)
 {
-       int i, len = 0;
+       int i, len = 0, l;
        off_t   begin = 0;
 
        len += sprintf(page, "serinfo:1.0 driver:%s\n", serial_version);
        for (i = 0; i < NR_PORTS && len < 4000; i++) {
-               len += line_info(page + len, &rs_table[i]);
+               l = line_info(page + len, &rs_table[i]);
+               len += l;
                if (len+begin > off+count)
                        goto done;
                if (len+begin < off) {
@@ -2742,10 +2783,11 @@ static _INLINE_ void show_serial_version(void)
 #endif
 #ifdef CONFIG_SERIAL_SHARE_IRQ
        printk(" SHARE_IRQ");
-#endif
 #define SERIAL_OPT
+#endif
 #ifdef CONFIG_SERIAL_DETECT_IRQ
        printk(" DETECT_IRQ");
+#define SERIAL_OPT
 #endif
 #ifdef SERIAL_OPT
        printk(" enabled\n");
@@ -2766,7 +2808,7 @@ static unsigned detect_uart_irq (struct serial_state * state)
 {
        int irq;
        unsigned long irqs;
-       unsigned char save_mcr;
+       unsigned char save_mcr, save_ier;
        struct async_struct scr_info; /* serial_{in,out} because HUB6 */
 
 #ifdef CONFIG_SERIAL_MANY_PORTS
@@ -2790,15 +2832,30 @@ static unsigned detect_uart_irq (struct serial_state * state)
        /* forget possible initially masked and pending IRQ */
        probe_irq_off(probe_irq_on());
        save_mcr = serial_inp(&scr_info, UART_MCR);
-
+       save_ier = serial_inp(&scr_info, UART_IER);
        serial_outp(&scr_info, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+       
        irqs = probe_irq_on();
        serial_outp(&scr_info, UART_MCR, 0);
-       udelay (1);
+       udelay (10);
+       if (state->flags & ASYNC_FOURPORT)  {
+               serial_outp(&scr_info, UART_MCR,
+                           UART_MCR_DTR | UART_MCR_RTS);
+       } else {
+               serial_outp(&scr_info, UART_MCR,
+                           UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+       }
+       serial_outp(&scr_info, UART_IER, 0x0f); /* enable all intrs */
+       (void)serial_inp(&scr_info, UART_LSR);
+       (void)serial_inp(&scr_info, UART_RX);
+       (void)serial_inp(&scr_info, UART_IIR);
+       (void)serial_inp(&scr_info, UART_MSR);
+       serial_outp(&scr_info, UART_TX, 0xFF);
+       udelay (20);
        irq = probe_irq_off(irqs);
 
        serial_outp(&scr_info, UART_MCR, save_mcr);
-
+       serial_outp(&scr_info, UART_IER, save_ier);
 #ifdef CONFIG_SERIAL_MANY_PORTS
        if (state->flags & ASYNC_FOURPORT)
                outb_p(save_ICP, ICP);
@@ -2866,11 +2923,9 @@ static void autoconfig(struct serial_state * state)
        if (!(state->flags & ASYNC_SKIP_TEST)) {
                scratch = serial_inp(info, UART_MCR);
                serial_outp(info, UART_MCR, UART_MCR_LOOP | scratch);
-               scratch2 = serial_inp(info, UART_MSR);
                serial_outp(info, UART_MCR, UART_MCR_LOOP | 0x0A);
                status1 = serial_inp(info, UART_MSR) & 0xF0;
                serial_outp(info, UART_MCR, scratch);
-               serial_outp(info, UART_MSR, scratch2);
                if (status1 != 0x90) {
                        restore_flags(flags);
                        return;
@@ -3083,12 +3138,9 @@ __initfunc(int rs_init(void))
                state->icount.frame = state->icount.parity = 0;
                state->icount.overrun = state->icount.brk = 0;
                state->irq = irq_cannonicalize(state->irq);
-               if (check_region(state->port,8)) {
-                       state->type = PORT_UNKNOWN;
+               if (check_region(state->port,8))
                        continue;
-               }
-               if (   (state->type == PORT_UNKNOWN)
-                   && (state->flags & ASYNC_BOOT_AUTOCONF))
+               if (state->flags & ASYNC_BOOT_AUTOCONF)
                        autoconfig(state);
        }
        /*
index bf2e642c4dec9dc5eb03d5881f2897a7777e669f..0f50d34db9bcf4625eddd247dedcb98418a188c6 100644 (file)
@@ -1022,6 +1022,10 @@ static void release_dev(struct file * filp)
                }
        }
 #endif
+
+       if (tty->driver.close)
+               tty->driver.close(tty, filp);
+
        /*
         * Sanity check: if tty->count is going to zero, there shouldn't be
         * any waiters on tty->read_wait or tty->write_wait.  We test the
@@ -1079,9 +1083,6 @@ static void release_dev(struct file * filp)
         * block, so it's safe to proceed with closing.
         */
 
-       if (tty->driver.close)
-               tty->driver.close(tty, filp);
-
        if (pty_master) {
                if (--o_tty->count < 0) {
                        printk("release_dev: bad pty slave count (%d) for %s\n",
index 2b63631eb53a2d1d656487afc9dbc6703dca8e1f..28f18d7ddae92ce67ddb04f9949184dc39620246 100644 (file)
@@ -595,7 +595,7 @@ static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
        performed, so there should be no Host Adapter state lost by a
        Soft Reset in response to a Command Invalid condition.
       */
-      mdelay(1);
+      udelay(1000);
       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
       if (StatusRegister.Bits.CommandInvalid ||
          StatusRegister.Bits.Reserved ||
@@ -607,7 +607,7 @@ static int BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
          StatusRegister.Bits.DiagnosticFailure)
        {
          BusLogic_SoftReset(HostAdapter);
-         mdelay(1);
+         udelay(1000);
        }
       BusLogic_CommandFailureReason = "Command Invalid";
       Result = -1;
index 783a21ba0b0250324c893571768d68e64212c25f..9707e7f08df6ce096035a40905ea30ff84d85923 100644 (file)
@@ -100,8 +100,6 @@ linux-1.1.x and fairly stable since linux-1.2.x, and are also in FreeBSD
     
   Boot Command line options
   ------------------------------
-    "aic7xxx=no_reset" -  Eliminate the SCSI reset delay during startup.
-        Some SCSI devices need some extra time to reset.
     "aic7xxx=reverse_scan" - Have the driver register the SCSI cards in the
         reverse of the normal order.  This may help those people who have more
         than one PCI Adaptec controller force the correct controller to be
index 4d6830b2c15bd0f2792942fb0416759eed552ae3..6807f488e3fd68eba9c9acb6247a0cdde412fc6a 100644 (file)
@@ -319,8 +319,7 @@ static int aha1542_test_port(int bse, struct Scsi_Host * shpnt)
 
     outb(SRST|IRST/*|SCRST*/, CONTROL(bse));
 
-    i = jiffies + 2;
-    while (i>jiffies); /* Wait a little bit for things to settle down. */
+    mdelay(20);        /* Wait a little bit for things to settle down. */
     
     debug = 1;
     /* Expect INIT and IDLE, any of the others are bad */
index 8950149ff56ac79855df655ed095ec8734f7c6ac..f4e39ef8da24d117869112b42294fa6e5fdf3483 100644 (file)
@@ -209,7 +209,7 @@ struct proc_dir_entry proc_scsi_aic7xxx = {
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.0.17"
+#define AIC7XXX_C_VERSION  "5.0.18"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -874,9 +874,10 @@ struct aic7xxx_host {
   unsigned char            dev_commands_sent[MAX_TARGETS];
 
   /*
-   * The next 64 (or 128 on 64 bit machines)....
+   * The next 128 (or 256 on 64 bit machines)....
    */
-  Scsi_Cmnd               *dev_negotiation_cmnd[MAX_TARGETS];
+  Scsi_Cmnd               *dev_wdtr_cmnd[MAX_TARGETS];
+  Scsi_Cmnd               *dev_sdtr_cmnd[MAX_TARGETS];
 
   /*
    * The next 64.... 
@@ -1050,7 +1051,6 @@ static int aic7xxx_7895_irq_hack = -1;       /* This enables a hack to fix
                                               *   1 == Use the Channel B IRQ
                                               */
 static unsigned int aic7xxx_extended = 0;    /* extended translation on? */
-static unsigned int aic7xxx_no_reset = 0;    /* no resetting of SCSI bus */
 static int aic7xxx_irq_trigger = -1;         /*
                                               * -1 use board setting
                                               *  0 use edge triggered
@@ -1222,7 +1222,6 @@ aic7xxx_setup(char *s, int *dummy)
     unsigned int *flag;
   } options[] = {
     { "extended",    &aic7xxx_extended },
-    { "no_reset",    &aic7xxx_no_reset },
     { "irq_trigger", &aic7xxx_irq_trigger },
     { "verbose",     &aic7xxx_verbose },
     { "reverse_scan",&aic7xxx_reverse_scan },
@@ -6408,7 +6407,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
       scsi_conf |= p->scsi_id_b;
       aic_outb(p, scsi_conf | (term) ? TERM_ENB : 0, SCSICONF + 1);
     }
-    if ((scsi_conf & RESET_SCSI) && (aic7xxx_no_reset == 0))
+    if (scsi_conf & RESET_SCSI)
     {
       /* Reset SCSI bus B. */
       if (aic7xxx_verbose & VERBOSE_PROBE)
@@ -6444,7 +6443,7 @@ aic7xxx_register(Scsi_Host_Template *template, struct aic7xxx_host *p,
   }
 
 
-  if ((scsi_conf & RESET_SCSI) && (aic7xxx_no_reset == 0))
+  if (scsi_conf & RESET_SCSI)
   {
     /* Reset SCSI bus A. */
     if (aic7xxx_verbose & VERBOSE_PROBE)
@@ -6843,8 +6842,10 @@ aic7xxx_free(struct aic7xxx_host *p)
    */
   for (i = 0; i < MAX_TARGETS; i++)
   {
-    if(p->dev_negotiation_cmnd[i])
-      kfree(p->dev_negotiation_cmnd[i]);
+    if(p->dev_wdtr_cmnd[i])
+      kfree(p->dev_wdtr_cmnd[i]);
+    if(p->dev_sdtr_cmnd[i])
+      kfree(p->dev_sdtr_cmnd[i]);
   }
 
   /*
@@ -8165,31 +8166,60 @@ aic7xxx_build_negotiation_cmnd(struct aic7xxx_host *p, Scsi_Cmnd *old_cmd,
   int tindex)
 {
 
-  if(p->dev_negotiation_cmnd[tindex] == NULL)
+  if ( (p->needwdtr & (1<<tindex)) && !(p->wdtr_pending & (1<<tindex)) )
   {
-    Scsi_Cmnd *cmd;
-
-    if (!(p->dev_negotiation_cmnd[tindex] =
-          kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+    if(p->dev_wdtr_cmnd[tindex] == NULL)
     {
-      return;
-    }
-    cmd = p->dev_negotiation_cmnd[tindex];
-    memset(cmd, 0, sizeof(Scsi_Cmnd));
-    memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
-    memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
-    memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
-    cmd->lun = 0;
-    cmd->request_bufflen = 0;
-    cmd->request_buffer = NULL;
-    cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
-    cmd->bufflen = 0;
-    cmd->buffer = NULL;
-    cmd->underflow = 0;
-    cmd->cmd_len = 6;
-  }
-  aic7xxx_queue(p->dev_negotiation_cmnd[tindex], 
-                aic7xxx_negotiation_complete);
+      Scsi_Cmnd *cmd;
+
+      if (!(p->dev_wdtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+      {
+        return;
+      }
+      cmd = p->dev_wdtr_cmnd[tindex];
+      memset(cmd, 0, sizeof(Scsi_Cmnd));
+      memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
+      memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
+      memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
+      cmd->lun = 0;
+      cmd->request_bufflen = 0;
+      cmd->request_buffer = NULL;
+      cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
+      cmd->bufflen = 0;
+      cmd->buffer = NULL;
+      cmd->underflow = 0;
+      cmd->cmd_len = 6;
+    }
+    aic7xxx_queue(p->dev_wdtr_cmnd[tindex], 
+                  aic7xxx_negotiation_complete);
+  }
+  else if ( (p->needsdtr & (1<<tindex)) && !(p->sdtr_pending & (1<<tindex)) )
+  {
+    if(p->dev_sdtr_cmnd[tindex] == NULL)
+    {
+      Scsi_Cmnd *cmd;
+
+      if (!(p->dev_sdtr_cmnd[tindex] = kmalloc(sizeof(Scsi_Cmnd), GFP_ATOMIC)) )
+      {
+        return;
+      }
+      cmd = p->dev_sdtr_cmnd[tindex];
+      memset(cmd, 0, sizeof(Scsi_Cmnd));
+      memcpy(cmd, old_cmd, sizeof(Scsi_Cmnd));
+      memset(&cmd->cmnd[0], 0, sizeof(cmd->cmnd));
+      memset(&cmd->data_cmnd[0], 0, sizeof(cmd->data_cmnd));
+      cmd->lun = 0;
+      cmd->request_bufflen = 0;
+      cmd->request_buffer = NULL;
+      cmd->use_sg = cmd->old_use_sg = cmd->sglist_len = 0;
+      cmd->bufflen = 0;
+      cmd->buffer = NULL;
+      cmd->underflow = 0;
+      cmd->cmd_len = 6;
+    }
+    aic7xxx_queue(p->dev_sdtr_cmnd[tindex], 
+                  aic7xxx_negotiation_complete);
+  }
 }
 
 /*+F*************************************************************************
@@ -8245,21 +8275,12 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
   }
   if (p->dev_flags[TARGET_INDEX(cmd)] & DEVICE_SCANNED)
   {
-    if ( ((p->needwdtr & mask) || (p->needsdtr & mask)) &&
-        !((p->wdtr_pending & mask) || (p->sdtr_pending & mask)) )
+    if ( (p->needwdtr & mask) && !(p->wdtr_pending & mask) )
     {
-      if (cmd == p->dev_negotiation_cmnd[TARGET_INDEX(cmd)])
+      if (cmd == p->dev_wdtr_cmnd[TARGET_INDEX(cmd)])
       {
-        if (p->needwdtr & mask)
-        {
-          p->wdtr_pending |= mask;
-          scb->flags |= SCB_MSGOUT_WDTR_16BIT;
-        }
-        else
-        {
-          p->sdtr_pending |= mask;
-          scb->flags |= SCB_MSGOUT_SDTR;
-        }
+        p->wdtr_pending |= mask;
+        scb->flags |= SCB_MSGOUT_WDTR_16BIT;
         hscb->control &= DISCENB;
         hscb->control |= MK_MESSAGE;
         scb->tag_action = 0;
@@ -8269,6 +8290,21 @@ aic7xxx_buildscb(struct aic7xxx_host *p, Scsi_Cmnd *cmd,
         aic7xxx_build_negotiation_cmnd(p, cmd, TARGET_INDEX(cmd));
       }
     }
+    if ( (p->needsdtr & mask) && !(p->sdtr_pending & mask) )
+    {
+      if (cmd == p->dev_sdtr_cmnd[TARGET_INDEX(cmd)])
+      {
+        p->sdtr_pending |= mask;
+        scb->flags |= SCB_MSGOUT_SDTR;
+        hscb->control &= DISCENB;
+        hscb->control |= MK_MESSAGE;
+        scb->tag_action = 0;
+      }
+      else if (cmd != p->dev_wdtr_cmnd[TARGET_INDEX(cmd)])
+      {
+        aic7xxx_build_negotiation_cmnd(p, cmd, TARGET_INDEX(cmd));
+      }
+    }
   }
   hscb->target_channel_lun = ((cmd->target << 4) & 0xF0) |
         ((cmd->channel & 0x01) << 3) | (cmd->lun & 0x07);
index c923cecec2fb942171b988267496de420cf406e1..44ac9d5f9c8961d181defb5d028b51ffb77a6c59 100644 (file)
@@ -243,8 +243,6 @@ aic7xxx_proc_info ( char *buffer, char **start, off_t offset, int length,
             p->adapter_control);
   size += sprintf(BLS, "   Extended Translation: %sabled\n",
       (p->flags & AHC_EXTEND_TRANS_A) ? "En" : "Dis");
-  size += sprintf(BLS, "         SCSI Bus Reset: %sabled\n",
-      aic7xxx_no_reset ? "Dis" : "En");
   size += sprintf(BLS, "Disconnect Enable Flags: 0x%04x\n", p->discenable);
   if (p->type & AHC_ULTRA)
   {
index 09f301cef6a551c3cb53115dc14d38cca912fd37..a3d3ea51647f2e73225aad392e5ce8438f4fe3f3 100644 (file)
@@ -1,6 +1,10 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      28 May 1998 Rev. 4.32 for linux 2.0.33 and 2.1.104
+ *          Increased busy timeout from 10 msec. to 200 msec. while
+ *          processing interrupts.
+ *
  *      16 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102
  *          Improved abort handling during the eh recovery process.
  *
@@ -9,7 +13,7 @@
  *          abort and reset routines.
  *          Added command line options (eh:[y|n]) to choose between
  *          new_eh_code and the old scsi code.
- *          If linux verion >= 2.1.101 the default is eh:y, while the eh
+ *          If linux version >= 2.1.101 the default is eh:y, while the eh
  *          option is ignored for previous releases and the old scsi code
  *          is used.
  *
@@ -2020,7 +2024,7 @@ static inline void ihdlr(int irq, unsigned int j) {
                         HD(j)->iocount);
 
    /* Check if this board is still busy */
-   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+   if (wait_on_busy(sh[j]->io_port, 20 * MAXLOOP)) {
       reg = inb(sh[j]->io_port + REG_STATUS);
       printk("%s: ihdlr, busy timeout error,  irq %d, reg 0x%x, count %d.\n",
              BN(j), irq, reg, HD(j)->iocount);
index e495b2d14343895f9a48a2c671bfd574e9b73ed5..c45169f65af75d33765eaad9fe980a68530fc802 100644 (file)
@@ -15,7 +15,7 @@ int eata2x_old_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *);
 int eata2x_old_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "4.31.00"
+#define EATA_VERSION "4.32.00"
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
index e0d7ec2c95daebd8ff643442190efa47550f6e52..ae00f3714dbe54f8737338d8e9e6efbb5ad92937 100644 (file)
@@ -1,6 +1,6 @@
 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Wed Oct  2 11:10:55 1996 by r.faith@ieee.org
+ * Revised: Wed Oct  2 11:10:55 1996 by faith@acm.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
  *
@@ -956,14 +956,14 @@ int fdomain_16x0_detect( Scsi_Host_Template *tpnt )
         if (retcode == -EINVAL) {
            printk( "fdomain: IRQ %d is bad!\n", interrupt_level );
            printk( "         This shouldn't happen!\n" );
-           printk( "         Send mail to faith@cs.unc.edu\n" );
+           printk( "         Send mail to faith@acm.org\n" );
         } else if (retcode == -EBUSY) {
            printk( "fdomain: IRQ %d is already in use!\n", interrupt_level );
            printk( "         Please use another IRQ!\n" );
         } else {
            printk( "fdomain: Error getting IRQ %d\n", interrupt_level );
            printk( "         This shouldn't happen!\n" );
-           printk( "         Send mail to faith@cs.unc.edu\n" );
+           printk( "         Send mail to faith@acm.org\n" );
         }
         panic( "fdomain: Driver requires interruptions\n" );
       }
index 0983e5383439b3fd7fb0c5430825b5213fce0b94..3ac53365f9b0556c701d0e59516652c2121c2f16 100644 (file)
@@ -1,6 +1,6 @@
 /* fdomain.h -- Header for Future Domain TMC-16x0 driver
  * Created: Sun May  3 18:47:33 1992 by faith@cs.unc.edu
- * Revised: Thu Oct 12 13:21:35 1995 by r.faith@ieee.org
+ * Revised: Thu Oct 12 13:21:35 1995 by faith@acm.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994, 1995 Rickard E. Faith
  *
index b5692acd1a0f767d9b00018f00e359719ef17f57..876d0a007a47c7889f4235d7a65d7559d0d48058 100644 (file)
@@ -6,6 +6,7 @@
 #include <asm/system.h>
 #include <asm/page.h>
 
+#include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -107,15 +108,17 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd,
     Scsi_Cmnd * SCpnt;
     Scsi_Device * SDpnt;
 
+    spin_lock_irqsave(&io_request_lock, flags);
+
     SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0]));
     SCpnt = scsi_allocate_device(NULL, dev, 1);
     {
        struct semaphore sem = MUTEX_LOCKED;
        SCpnt->request.sem = &sem;
-       spin_lock_irqsave(&io_request_lock, flags);
        scsi_do_cmd(SCpnt,  cmd, NULL,  0, scsi_ioctl_done,  timeout, retries);
        spin_unlock_irqrestore(&io_request_lock, flags);
        down(&sem);
+        spin_lock_irqsave(&io_request_lock, flags);
         SCpnt->request.sem = NULL;
     }
     
@@ -163,6 +166,7 @@ static int ioctl_internal_command(Scsi_Device *dev, char * cmd,
        (*SDpnt->scsi_request_fn)();
 
     wake_up(&SDpnt->device_wait);
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return result;
 }
 
@@ -276,13 +280,14 @@ int scsi_ioctl_send_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
       }
 
 #ifndef DEBUG_NO_CMD
+
+    spin_lock_irqsave(&io_request_lock, flags);
     
     SCpnt = scsi_allocate_device(NULL, dev, 1);
 
     {
        struct semaphore sem = MUTEX_LOCKED;
        SCpnt->request.sem = &sem;
-       spin_lock_irqsave(&io_request_lock, flags);
        scsi_do_cmd(SCpnt,  cmd,  buf, needed,  scsi_ioctl_done,
                    timeout, retries);
        spin_unlock_irqrestore(&io_request_lock, flags);
@@ -308,6 +313,8 @@ int scsi_ioctl_send_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
     }
     result = SCpnt->result;
 
+    spin_lock_irqsave(&io_request_lock, flags);
+
     wake_up(&SCpnt->device->device_wait);
     SDpnt = SCpnt->device;
     scsi_release_command(SCpnt);
@@ -318,6 +325,7 @@ int scsi_ioctl_send_command(Scsi_Device *dev, Scsi_Ioctl_Command *sic)
     if(SDpnt->scsi_request_fn)
        (*SDpnt->scsi_request_fn)();
     
+    spin_unlock_irqrestore(&io_request_lock, flags);
     return result;
 #else
     {
index 5dd63f0d3ecae86975ac668188514ab46c6a91fa..0ebd939576104d48040c73eab5200c9a10126c7b 100644 (file)
@@ -1,6 +1,10 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      28 May 1998 Rev. 4.32 for linux 2.0.33 and 2.1.104
+ *          Increased busy timeout from 10 msec. to 200 msec. while
+ *          processing interrupts.
+ *
  *      18 May 1998 Rev. 4.31 for linux 2.0.33 and 2.1.102
  *          Improved abort handling during the eh recovery process.
  *
@@ -9,7 +13,7 @@
  *          abort and reset routines.
  *          Added command line options (eh:[y|n]) to choose between
  *          new_eh_code and the old scsi code.
- *          If linux verion >= 2.1.101 the default is eh:y, while the eh
+ *          If linux version >= 2.1.101 the default is eh:y, while the eh
  *          option is ignored for previous releases and the old scsi code
  *          is used.
  *
@@ -1733,7 +1737,7 @@ static inline void ihdlr(int irq, unsigned int j) {
                         HD(j)->iocount);
 
    /* Check if this board is still busy */
-   if (wait_on_busy(sh[j]->io_port, MAXLOOP)) {
+   if (wait_on_busy(sh[j]->io_port, 20 * MAXLOOP)) {
       outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
       printk("%s: ihdlr, busy timeout error,  irq %d, reg 0x%x, count %d.\n",
              BN(j), irq, reg, HD(j)->iocount);
index 47029641948823612e9137f6dad1dc9dc6c25f3c..f21aa63faf4dec6504537c2b9db1f04361a6bf22 100644 (file)
@@ -15,7 +15,7 @@ int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_old_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "4.31.00"
+#define U14_34F_VERSION "4.32.00"
 
 #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
 
index f63b43cb0796bdd453b7df25713be48c023ec23b..824d1daad23fbe5a3dcc688ac5860d24da466631 100644 (file)
@@ -10,7 +10,6 @@
  * data, of course), but instead letting the caller do it.
  */
 
-/* Some bdflush() changes for the dynamic ramdisk - Paul Gortmaker, 12/94 */
 /* Start bdflush() with kernel_thread not syscall - Paul Gortmaker, 12/95 */
 
 /* Removed a lot of unnecessary code and simplified things now that
  * hash table, use SLAB cache for buffer heads. -DaveM
  */
 
+/* Added 32k buffer block sizes - these are required older ARM systems.
+ * - RMK
+ */
+
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-#define NR_SIZES 5
-static char buffersize_index[17] =
-{-1,  0,  1, -1,  2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4};
+#define NR_SIZES 7
+static char buffersize_index[65] =
+{-1,  0,  1, -1,  2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
+  4, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1,
+  5, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1,-1, -1, -1, -1, -1, -1, -1,
+  6};
 
 #define BUFSIZE_INDEX(X) ((int) buffersize_index[(X)>>9])
 #define MAX_BUF_PER_PAGE (PAGE_SIZE / 512)
@@ -637,13 +644,9 @@ void set_blocksize(kdev_t dev, int size)
        if (!blksize_size[MAJOR(dev)])
                return;
 
-       if (size > PAGE_SIZE)
-               size = 0;
-
-       switch (size) {
-               default: panic("Invalid blocksize passed to set_blocksize");
-               case 512: case 1024: case 2048: case 4096: case 8192: ;
-       }
+       /* Size must be a power of two, and between 512 and PAGE_SIZE */
+       if (size > PAGE_SIZE || size < 512 || (size & (size-1)))
+               panic("Invalid blocksize passed to set_blocksize");
 
        if (blksize_size[MAJOR(dev)][MINOR(dev)] == 0 && size == BLOCK_SIZE) {
                blksize_size[MAJOR(dev)][MINOR(dev)] = size;
index 1285ac7573f7eb9cc3a9baece2249ce3eea87602..c8025416f20c05bb12a94a3d18822a2cb1cb1a92 100644 (file)
@@ -267,8 +267,7 @@ void coda_flag_alias_children(struct inode *inode, int flag)
        while ( alias != &inode->i_dentry ) {
                alias_de = list_entry(alias, struct dentry, d_alias);
                if ( !alias_de ) {
-                       printk("Corrupt alias list for %*s\n",
-                              alias_de->d_name.len, alias_de->d_name.name);
+                       printk("Null alias list for inode %ld\n", inode->i_ino);
                        return;
                }
                coda_flag_children(alias_de, flag);
index aa67a22e4b3fe9ac2bb5678d1291fdfda58e70ba..7bd0e30e0ead1976afc51a3b1ebf0c0b4d871609 100644 (file)
@@ -15,7 +15,7 @@ extern int coda_print_entry;
 
 /* cnode.c */
 
-static void coda_fill_inode (struct inode *inode, struct coda_vattr *attr)
+static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
 {
         CDEBUG(D_SUPER, "ino: %ld\n", inode->i_ino);
 
@@ -54,8 +54,8 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
         ENTRY;
 
         /* 
-        * We get inode numbers from Venus -- see venus source
-       */
+        * We get inode numbers from Venus -- see venus source
+        */
 
        error = venus_getattr(sb, fid, &attr);
        if ( error ) {
@@ -82,16 +82,26 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
                INIT_LIST_HEAD(&(cnp->c_cnhead));
                INIT_LIST_HEAD(&(cnp->c_volrootlist));
        } else {
-               printk("coda_cnode make on initialized inode %ld, %s!\n",
+               cnp->c_flags = 0;
+               CDEBUG(D_CNODE, "coda_cnode make on initialized"
+                      "inode %ld, %s!\n",
                       (*inode)->i_ino, coda_f2s(&cnp->c_fid));
        }
 
        /* fill in the inode attributes */
-       if ( coda_fid_is_volroot(fid) ) 
+       if ( coda_f2i(fid) != ino ) {
+               if ( !coda_fid_is_weird(fid) ) 
+                       printk("Coda: unknown weird fid: ino %ld, fid %s."
+                              "Tell Peter.", ino, coda_f2s(&cnp->c_fid));
                list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead);
+               CDEBUG(D_CNODE, "Added %ld ,%s to volroothead\n",
+                      ino, coda_f2s(&cnp->c_fid));
+       }
 
         coda_fill_inode(*inode, &attr);
-       CDEBUG(D_CNODE, "Done linking: ino %ld,  at 0x%x with cnp 0x%x, cnp->c_vnode 0x%x\n", (*inode)->i_ino, (int) (*inode), (int) cnp, (int)cnp->c_vnode);
+       CDEBUG(D_CNODE, "Done linking: ino %ld,  at 0x%x with cnp 0x%x,"
+              "cnp->c_vnode 0x%x\n", (*inode)->i_ino, (int) (*inode), 
+              (int) cnp, (int)cnp->c_vnode);
 
         EXIT;
         return 0;
@@ -132,7 +142,7 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
        }
 
 
-       if ( coda_fid_is_volroot(fid) ) {
+       if ( coda_fid_is_weird(fid) ) {
                struct coda_inode_info *cii;
                struct list_head *lh, *le;
                struct coda_sb_info *sbi = coda_sbp(sb);
@@ -141,7 +151,7 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
                while ( (le = le->next) != lh ) {
                        cii = list_entry(le, struct coda_inode_info, 
                                         c_volrootlist);
-                       if ( cii->c_fid.Volume == fid->Volume) {
+                       if ( coda_fideq(&cii->c_fid, fid) ) {
                                inode = cii->c_vnode;
                                CDEBUG(D_INODE, "volume root, found %ld\n", cii->c_vnode->i_ino);
                                return cii->c_vnode;
@@ -151,7 +161,7 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
                return NULL;
        }
 
-       /* fid is not volume root, hence ino is computable */
+       /* fid is not weird: ino should be computable */
        nr = coda_f2i(fid);
        inode = iget(sb, nr);
        if ( !inode ) {
@@ -173,9 +183,9 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
           These have the same inode as the root of the volume they
           mount, but the fid will be wrong. 
        */
-       if ( !coda_fideq(fid, &(cnp->c_fid)) && 
-            !coda_fid_is_volroot(&(cnp->c_fid))) {
-               printk("coda_fid2inode: bad cnode! Tell Peter.\n");
+       if ( !coda_fideq(fid, &(cnp->c_fid)) ) {
+               printk("coda_fid2inode: bad cnode (ino %ld, fid %s)"
+                      "Tell Peter.\n", nr, coda_f2s(fid));
                iput(inode);
                return NULL;
        }
index 322b764a9a2a6d502cb2d634c4dea20eb554e6ce..05e38331978c2ec3f4792ebc99cb275f0c49ead1 100644 (file)
@@ -65,6 +65,36 @@ int coda_fid_is_volroot(struct ViceFid *fid)
 {
        return ( (fid->Vnode == 1) && (fid->Unique == 1 ) );
 }
+  
+int coda_fid_is_weird(struct ViceFid *fid)
+{
+        /* volume roots */
+        if ( (fid->Vnode == 1) && (fid->Unique == 1 ) )
+               return 1;
+        /* tmpfid unique (simulate.cc) */
+       if ( fid->Unique == 0xffffffff )
+               return 1;
+       /* LocalFakeVnode (local.h)  */
+       if ( fid->Vnode == 0xfffffffd )
+               return 1;
+       /* LocalFileVnode (venus.private.h) */
+       if ( fid->Vnode == 0xfffffffe )
+               return 1;
+       /* local fake vid (local.h) */
+       if ( fid->Volume == 0xffffffff )
+               return 1;
+       /* local DirVnode (venus.private.h) */
+       if ( fid->Vnode == 0xffffffff )
+               return 1;
+       /* FakeVnode (venus.private.h) */
+       if ( fid->Vnode == 0xfffffffc )
+               return 1;
+
+       return 0;
+
+}
+
+
 
 /* put the current process credentials in the cred */
 void coda_load_creds(struct coda_cred *cred)
@@ -94,14 +124,23 @@ unsigned short coda_flags_to_cflags(unsigned short flags)
 {
        unsigned short coda_flags = 0;
 
-       if ( flags & (O_RDONLY | O_RDWR) )
+       if ( (flags & 0xf) == O_RDONLY )
+               coda_flags |= C_O_READ;
+
+       if ( flags &  O_RDWR )
                coda_flags |= C_O_READ;
 
        if ( flags & (O_WRONLY | O_RDWR) )
                coda_flags |= C_O_WRITE;
 
-       if ( flags & O_TRUNC ) 
+       if ( flags & O_TRUNC )  { 
+               CDEBUG(D_FILE, "--> C_O_TRUNC added\n");
                coda_flags |= C_O_TRUNC;
+       }
+       if ( flags & O_EXCL ) {
+               coda_flags |= C_O_EXCL;
+               CDEBUG(D_FILE, "--> C_O_EXCL added\n");
+       }
 
        return coda_flags;
 }
index ba0ec6e2f1f23efe5ccdff48c93a79275872da2b..564484dd0f15aee996766470ba2449533acced93 100644 (file)
@@ -167,8 +167,10 @@ exit:
        entry->d_time = 0;
        entry->d_op = &coda_dentry_operations;
        d_add(entry, res_inode);
-       if ( dropme ) 
+       if ( dropme ) {
                d_drop(entry);
+               ITOC(res_inode)->c_flags |= C_VATTR;
+       }
         EXIT;
         return 0;
 }
@@ -264,7 +266,7 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode)
        }
 
        /* invalidate the directory cnode's attributes */
-       dircnp->c_flags &= ~C_VATTR;
+       dircnp->c_flags |= C_VATTR;
        d_instantiate(de, result);
         return 0;
 }                           
@@ -320,7 +322,7 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
        }
        
        /* invalidate the directory cnode's attributes */
-       dircnp->c_flags &= ~C_VATTR;
+       dircnp->c_flags |= C_VATTR;
        dir->i_nlink++;
        d_instantiate(de, inode);
         return 0;
@@ -359,7 +361,7 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
                           (const char *)name, len);
 
        if (  ! error ) { 
-               dir_cnp->c_flags &= ~C_VATTR;
+               dir_cnp->c_flags |= C_VATTR;
                inode->i_nlink++;
                d_instantiate(de, inode);
        } else {
@@ -442,7 +444,7 @@ int coda_unlink(struct inode *dir, struct dentry *de)
         }
 
         /* cache management */
-       dircnp->c_flags &= ~C_VATTR;
+       dircnp->c_flags |= C_VATTR;
        
        de->d_inode->i_nlink--;
        d_delete(de);
@@ -814,7 +816,7 @@ int coda_dentry_revalidate(struct dentry *de)
                if (is_bad_inode(inode))
                        return 0;
                cii = ITOC(de->d_inode);
-               if (cii->c_flags & C_PURGE
+               if (cii->c_flags & (C_PURGE | C_VATTR)
                        valid = 0;
        }
        return valid ||  coda_isroot(de->d_inode);
@@ -838,7 +840,7 @@ static int coda_refresh_inode(struct dentry *dentry)
        }
 
        /* this baby may be lost if:
-          - it's type changed
+            - it's type changed
             - it's ino changed 
        */
        old_mode = inode->i_mode;
@@ -852,7 +854,7 @@ static int coda_refresh_inode(struct dentry *dentry)
                return -EIO;
        }
        
-       cii->c_flags &= ~C_VATTR;
+       cii->c_flags &= ~(C_VATTR | C_PURGE);
        return 0;
 }
 
index c92aeeb275000623b5bf221e4378d1ce62e50ee4..949d9ce00e9f2dfb3f835a504213f4b9ab1f3e6d 100644 (file)
@@ -192,13 +192,14 @@ static ssize_t coda_file_write(struct file *coda_file, const char *buff,
                 return -1;
         }
 
-        cnp->c_flags &= ~C_VATTR;
-
        down(&cont_inode->i_sem);
         result = cont_file.f_op->write(&cont_file , buff, count, 
                                       &(cont_file.f_pos));
        up(&cont_inode->i_sem);
         coda_restore_codafile(coda_inode, coda_file, cont_inode, &cont_file);
+       
+       if (result)
+               cnp->c_flags |= C_VATTR;
 
         return result;
 }
index 92543a15c280ad8eebdf7bdcc4eab3ae1ba972f9..6a4d52acd9ed0e67badaa94984db6c1750f33335 100644 (file)
@@ -161,6 +161,8 @@ static void coda_put_super(struct super_block *sb)
 
         ENTRY;
 
+
+        sb->s_dev = 0;
        coda_cache_clear_all(sb);
        sb_info = coda_sbp(sb);
        sb_info->sbi_vcomm->vc_inuse = 0;
index 799b1e38d3668cb1a94b123e2a4b938088362861..063f8b50682c263afe5c615c84834a09d5953dcb 100644 (file)
@@ -401,10 +401,18 @@ static struct file_operations coda_psdev_fops = {
 
 #ifdef CONFIG_PROC_FS
 
-extern struct proc_dir_entry proc_sys_root;
+struct proc_dir_entry proc_sys_root = {
+        PROC_SYS, 3, "sys",                     /* inode, name */
+        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,   /* mode, nlink, uid, gid */
+        0, &proc_dir_inode_operations,          /* size, ops */
+        NULL, NULL,                             /* get_info, fill_inode */
+        NULL,                                   /* next */
+        NULL, NULL                              /* parent, subdir */
+};
 
-struct proc_dir_entry proc_fs_coda = {
-        PROC_FS_CODA, 4, "coda",
+
+struct proc_dir_entry proc_sys_coda = {
+        0, 4, "coda",
         S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
         0, &proc_dir_inode_operations,
        NULL, NULL,
@@ -412,8 +420,8 @@ struct proc_dir_entry proc_fs_coda = {
        NULL, NULL
 };
 
-struct proc_dir_entry proc_sys_coda = {
-        0, 4, "coda",
+struct proc_dir_entry proc_fs = {
+        PROC_FS, 2, "fs",
         S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
         0, &proc_dir_inode_operations,
        NULL, NULL,
@@ -421,8 +429,17 @@ struct proc_dir_entry proc_sys_coda = {
        NULL, NULL
 };
 
-struct proc_dir_entry proc_fs = {
-        PROC_FS, 2, "fs",
+/*
+ * target directory structure:
+   /proc/fs/
+   /proc/fs/coda
+   /proc/fs/coda/{vfs_stats,
+
+*/
+
+
+struct proc_dir_entry proc_fs_coda = {
+        PROC_FS_CODA, 4, "coda",
         S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
         0, &proc_dir_inode_operations,
        NULL, NULL,
@@ -430,15 +447,6 @@ struct proc_dir_entry proc_fs = {
        NULL, NULL
 };
 
-#if 0
-struct proc_dir_entry proc_coda_ncstats =  {
-                0 , 12, "coda-ncstats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                cfsnc_nc_info
-        };
-#endif
-
 struct proc_dir_entry proc_coda_vfs =  {
                 PROC_VFS_STATS , 9, "vfs_stats",
                 S_IFREG | S_IRUGO, 1, 0, 0,
@@ -521,9 +529,7 @@ int init_coda_psdev(void)
        proc_register(&proc_fs_coda,&proc_coda_upcall);
        proc_register(&proc_fs_coda,&proc_coda_permission);
        proc_register(&proc_fs_coda,&proc_coda_cache_inv);
-#if 0
-       proc_register(&proc_fs_coda, &proc_coda_ncstats);
-#endif
+
        proc_register(&proc_sys_root,&proc_sys_coda);
        proc_register(&proc_sys_coda,&proc_coda_vfs_control);
        proc_register(&proc_sys_coda,&proc_coda_upcall_control);
@@ -578,12 +584,9 @@ void cleanup_module(void)
         proc_unregister(&proc_sys_coda, proc_coda_cache_inv_control.low_ino);
         proc_unregister(&proc_sys_coda, proc_coda_permission_control.low_ino);
         proc_unregister(&proc_sys_coda, proc_coda_upcall_control.low_ino);
-       proc_unregister(&proc_sys_coda,proc_coda_vfs_control.low_ino);
+       proc_unregister(&proc_sys_coda, proc_coda_vfs_control.low_ino);
        proc_unregister(&proc_sys_root, proc_sys_coda.low_ino);
 
-#if 0
-       proc_unregister(&proc_fs_coda, proc_coda_ncstats.low_ino);
-#endif
         proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino);
         proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino);
         proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino);
index 1b55b8ea7f9a915b7737f12e6fb1fbfe134b3898..20c2b13cab9f06b7b4ac207eb0d393643bb191c6 100644 (file)
@@ -7,6 +7,7 @@
  *
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
index 0e3ba95d157be8dbe4c7f7ea770c235738a7f269..d5ffe783d0bcb90afa9d0e4ec74c2592b8815782 100644 (file)
@@ -777,8 +777,6 @@ ENTRY;
  *                  force a new lookup for all the children
                     of this dir.
 
- * CFS_ZAPVNODE  -- intended to be a zapfile for just one cred. 
-                    Not used?
  *
  * The next is a result of Venus detecting an inconsistent file.
  * CFS_PURGEFID  -- flush the attribute for the file
@@ -792,81 +790,85 @@ ENTRY;
 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 {
 
-    /* Handle invalidate requests. */
-    switch (opcode) {
-    case CFS_FLUSH : {
-           clstats(CFS_FLUSH);
-           CDEBUG(D_DOWNCALL, "CFS_FLUSH\n");
-           coda_cache_clear_all(sb);
-           shrink_dcache_sb(sb);
-           return(0);
-    }
-    case CFS_PURGEUSER : {
-           struct coda_cred *cred = &out->cfs_purgeuser.cred;
-           CDEBUG(D_DOWNCALL, "CFS_PURGEUSER\n");
-           if ( !cred ) {
-                   printk("PURGEUSER: null cred!\n");
-                   return 0;
-           }
-           clstats(CFS_PURGEUSER);
-           coda_cache_clear_cred(sb, cred);
-           return(0);
-    }
-    case CFS_ZAPDIR : {
-           struct inode *inode;
-           ViceFid *fid = &out->cfs_zapdir.CodaFid;
-           if ( !fid ) {
-                   printk("ZAPDIR: Null fid\n");
-                   return 0;
-           }
-           CDEBUG(D_DOWNCALL, "zapdir: fid = %s\n", coda_f2s(fid));
-           clstats(CFS_ZAPDIR);
-           inode = coda_fid_to_inode(fid, sb);
-           coda_flag_inode(inode, C_VATTR);
-           coda_cache_clear_inode(inode);
-           coda_flag_alias_children(inode, C_PURGE);
-           return(0);
-    }
-
-    case CFS_ZAPVNODE : 
-    case CFS_ZAPFILE : {
-           struct inode *inode;
-           struct ViceFid *fid = &out->cfs_zapfile.CodaFid;
-           clstats(CFS_ZAPFILE);
-           if ( !fid ) {
-                   printk("ZAPFILE: Null fid\n");
-                   return 0;
-           }
-           CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
-           inode = coda_fid_to_inode(fid, sb);
-           coda_flag_inode(inode, C_VATTR);
-           coda_cache_clear_inode(inode);
-           return 0;
-    }
-    case CFS_PURGEFID : {
-           struct inode *inode;
-           ViceFid *fid = &out->cfs_purgefid.CodaFid;
-           if ( !fid ) {
-                   printk("PURGEFID: Null fid\n");
-                   return 0;
-           }
-           CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
-           clstats(CFS_PURGEFID);
-           inode = coda_fid_to_inode(fid, sb);
-           coda_flag_inode(inode, C_PURGE);
-           coda_cache_clear_inode(inode);
-           return 0;
-    }
-    case CFS_REPLACE : {
-           printk("CFS_REPLACCE\n");
-           clstats(CFS_REPLACE);
-           CDEBUG(D_DOWNCALL, "CFS_REPLACE\n");
-           coda_cache_clear_all(sb);
-           shrink_dcache_sb(sb);
-           return (0);
-    }                     
-    }
-      return 0;
+    /* Handle invalidation requests. */
+          if ( !sb ) { 
+                 printk("coda_downcall: opcode %d, no sb!\n", opcode);
+                 return 0; 
+         }
+
+         switch (opcode) {
+
+         case CFS_FLUSH : {
+                  clstats(CFS_FLUSH);
+                  CDEBUG(D_DOWNCALL, "CFS_FLUSH\n");
+                  coda_cache_clear_all(sb);
+                  shrink_dcache_sb(sb);
+                  return(0);
+         }
+
+         case CFS_PURGEUSER : {
+                  struct coda_cred *cred = &out->cfs_purgeuser.cred;
+                  CDEBUG(D_DOWNCALL, "CFS_PURGEUSER\n");
+                  if ( !cred ) {
+                          printk("PURGEUSER: null cred!\n");
+                          return 0;
+                  }
+                  clstats(CFS_PURGEUSER);
+                  coda_cache_clear_cred(sb, cred);
+                  return(0);
+         }
+
+         case CFS_ZAPDIR : {
+                 struct inode *inode;
+                 ViceFid *fid = &out->cfs_zapdir.CodaFid;
+                 CDEBUG(D_DOWNCALL, "zapdir: fid = %s\n", coda_f2s(fid));
+                 clstats(CFS_ZAPDIR);
+
+                 inode = coda_fid_to_inode(fid, sb);
+                 if ( inode ) {
+                         coda_flag_inode(inode, C_VATTR);
+                         coda_cache_clear_inode(inode);
+                         coda_flag_alias_children(inode, C_PURGE);
+                 }
+                 return(0);
+         }
+
+         case CFS_ZAPFILE : {
+                 struct inode *inode;
+                 struct ViceFid *fid = &out->cfs_zapfile.CodaFid;
+                 clstats(CFS_ZAPFILE);
+                 CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
+                 inode = coda_fid_to_inode(fid, sb);
+                 if ( inode ) {
+                         coda_flag_inode(inode, C_VATTR);
+                         coda_cache_clear_inode(inode);
+                 }
+                 return 0;
+         }
+
+         case CFS_PURGEFID : {
+                 struct inode *inode;
+                 ViceFid *fid = &out->cfs_purgefid.CodaFid;
+                 CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
+                 clstats(CFS_PURGEFID);
+                 inode = coda_fid_to_inode(fid, sb);
+                 if ( inode ) { 
+                          coda_flag_inode(inode, C_PURGE);
+                         coda_cache_clear_inode(inode);
+                 }
+                 return 0;
+         }
+
+         case CFS_REPLACE : {
+                 printk("CFS_REPLACCE\n");
+                 clstats(CFS_REPLACE);
+                 CDEBUG(D_DOWNCALL, "CFS_REPLACE\n");
+                 coda_cache_clear_all(sb);
+                 shrink_dcache_sb(sb);
+                 return (0);
+         }                        
+         }
+         return 0;
 }
 
 
index d3077ea79bebeb77f572ee5505482c282a5e2d9c..60c459a9592c73b08cba96177b5b78713b0810ae 100644 (file)
@@ -22,6 +22,7 @@ EXPORT_SYMBOL(in_group_p);
 EXPORT_SYMBOL(proc_dir_inode_operations);
 EXPORT_SYMBOL(proc_net_inode_operations);
 EXPORT_SYMBOL(proc_net);
+EXPORT_SYMBOL(proc_bus);
 
 /*
  * This is required so that if we load scsi later, that the
index edc22b27f2b6f4d6edae65b43a19cf6a904f745a..94b07c1aa4e43b6108580538bdebfd196cd2a854 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -38,10 +38,15 @@ do_revalidate(struct dentry *dentry)
  */
 static int cp_old_stat(struct inode * inode, struct __old_kernel_stat * statbuf)
 {
+       static int warncount = 5;
        struct __old_kernel_stat tmp;
 
-       printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
-               current->comm);
+       if (warncount) {
+               warncount--;
+               printk("VFS: Warning: %s using old stat() call. Recompile your binary.\n",
+                       current->comm);
+       }
+
        tmp.st_dev = kdev_t_to_nr(inode->i_dev);
        tmp.st_ino = inode->i_ino;
        tmp.st_mode = inode->i_mode;
index aed0fd6fde307a79bf830499554e95eb9f8f5476..6413683c20cc48065f39a8e6cc1bfb9ad91d722f 100644 (file)
@@ -37,6 +37,8 @@ typedef struct {
 #endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
 } __kernel_fsid_t;
 
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
 #undef __FD_SET
 #define __FD_SET(fd,fdsetp) \
                __asm__ __volatile__("btsl %1,%0": \
@@ -62,4 +64,6 @@ typedef struct {
                        :"a" (0), "c" (__FDSET_LONGS), \
                        "D" ((__kernel_fd_set *) (fdsetp)) :"cx","di")
 
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
 #endif
index e6a42b2279441e3c9e84a1343ee6a2d20a6dd910..cd5bdd8e642d0138419619a5da93bf3050e11638 100644 (file)
@@ -61,14 +61,14 @@ typedef struct {
 #define spin_lock_init(x)      do { (x)->lock = 0; } while (0)
 #define spin_trylock(lock)     (!test_and_set_bit(0,(lock)))
 
-#define spin_lock(x)           do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
-#define spin_unlock_wait(x)    do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
-#define spin_unlock(x)         do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s: spin_unlock(%s:%p) not locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
-#define spin_lock_irq(x)       do {cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
-#define spin_unlock_irq(x)     do {cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; sti();} while (0)
-
-#define spin_lock_irqsave(x,flags)      do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
-#define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
+#define spin_lock(x)           do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
+#define spin_unlock_wait(x)    do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
+#define spin_unlock(x)         do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
+#define spin_lock_irq(x)       do {cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
+#define spin_unlock_irq(x)     do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_lock(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; sti();} while (0)
+
+#define spin_lock_irqsave(x,flags)      do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s:%d: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
+#define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s:%d: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__,__LINE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
 
 #endif /* DEBUG_SPINLOCKS */
 
index b5acf0e745c7af24bb25675376f33d68f9b0d318..b0d067e7af1342acfe04ba5ae147350ec672f11e 100644 (file)
@@ -79,7 +79,7 @@ struct user{
                                   esp register.  */
   long int signal;                     /* Signal that caused the core dump. */
   int reserved;                        /* No longer used */
-  struct pt_regs * u_ar0;      /* Used by gdb to help find the values for */
+  struct user_pt_regs * u_ar0; /* Used by gdb to help find the values for */
                                /* the registers. */
   struct user_i387_struct* u_fpstate;  /* Math Co-processor pointer. */
   unsigned long magic;         /* To uniquely identify a core file */
index 5c3cb563e1fcda10bec278cad6a8b67d8673372f..9cdf0d04b8cbdbf84152631f2d7d22ae0252e256 100644 (file)
@@ -148,8 +148,8 @@ static inline ino_t coda_f2i(struct ViceFid *fid)
 
 #ifndef _VUID_T_
 #define _VUID_T_
-typedef u_long vuid_t;
-typedef u_long vgid_t;
+typedef unsigned int vuid_t;
+typedef unsigned int vgid_t;
 #endif /*_VUID_T_ */
 
 #ifndef _CODACRED_T_
@@ -223,7 +223,7 @@ struct coda_vattr {
 #define CFS_PURGEUSER   ((u_long) 26)
 #define CFS_ZAPFILE     ((u_long) 27)
 #define CFS_ZAPDIR      ((u_long) 28)
-#define CFS_ZAPVNODE    ((u_long) 29)
+/* #define CFS_ZAPVNODE    ((u_long) 29)   obsolete */ 
 #define CFS_PURGEFID    ((u_long) 30)
 #define CFS_OPEN_BY_PATH ((u_long) 31)
 #define CFS_NCALLS 32
index 9dd30eaeb3ea2cf4a5f5cb124bcf3ec876ef21b7..e867226ec50ba23ee2783bcf207087cff3d640ba 100644 (file)
@@ -48,6 +48,7 @@ static __inline__ struct ViceFid *coda_i2f(struct inode *);
 char *coda_f2s(ViceFid *f);
 int coda_isroot(struct inode *i);
 int coda_fid_is_volroot(struct ViceFid *);
+int coda_fid_is_weird(struct ViceFid *fid);
 int coda_iscontrol(const char *name, size_t length);
 
 
index f5ef3f250bacbaf33aecfe9a6dfff9dfc476ca4e..9828ac5e2d16e48bf5e30c287728d71854e1f3d8 100644 (file)
@@ -1,4 +1,4 @@
-/* $Revision: 2.3 $$Date: 1998/03/16 18:01:12 $
+/* $Revision: 2.4 $$Date: 1998/06/01 12:09:53 $
  * linux/include/linux/cyclades.h
  *
  * This file is maintained by Ivan Passos <ivan@cyclades.com>, 
@@ -7,10 +7,14 @@
  *
  * This file contains the general definitions for the cyclades.c driver
  *$Log: cyclades.h,v $
+ *Revision 2.4  1998/06/01 12:09:53  ivan
+ *removed closing_wait2 from cyclades_port structure;
+ *
  *Revision 2.3  1998/03/16 18:01:12  ivan
  *changes in the cyclades_port structure to get it closer to the 
  *standard serial port structure;
  *added constants for new ioctls;
+ *
  *Revision 2.2  1998/02/17 16:50:00  ivan
  *changes in the cyclades_port structure (addition of shutdown_wait and 
  *chip_rev variables);
@@ -89,8 +93,8 @@ struct cyclades_monitor {
 #define CZ_DEF_POLL    (HZ/25)
 
 #define MAX_BOARD       4       /* Max number of boards */
-#define MAX_PORT        128     /* Max number of ports per board */
 #define MAX_DEV         256     /* Max number of ports total */
+#define        CYZ_MAX_SPEED   921600
 
 #define        CYZ_FIFO_SIZE   16
 
@@ -508,7 +512,6 @@ struct cyclades_port {
        int                     x_char; /* to be pushed out ASAP */
        int                     close_delay;
        unsigned short          closing_wait;
-       unsigned short          closing_wait2;
        unsigned long           event;
        unsigned long           last_active;
        int                     count;  /* # of fd on device */
@@ -544,11 +547,15 @@ struct cyclades_port {
 #define Cy_EVENT_OPEN_WAKEUP           4
 #define Cy_EVENT_SHUTDOWN_WAKEUP       5
 
-#define        CLOSING_WAIT_DELAY      30
+#define        CLOSING_WAIT_DELAY      30*HZ
+#define CY_CLOSING_WAIT_NONE   65535
+#define CY_CLOSING_WAIT_INF    0
+
 
 #define CyMAX_CHIPS_PER_CARD   8
 #define CyMAX_CHAR_FIFO                12
 #define CyPORTS_PER_CHIP       4
+#define        CD1400_MAX_SPEED        115200
 
 #define        CyISA_Ywin      0x2000
 
index 1347d59077317aebb586ae9e7eb1c55c0c86eb16..c5df0d7990cfd71cab53e67be2157cebd4972b93 100644 (file)
@@ -565,7 +565,7 @@ extern inline int fsuser(void)
 
 extern inline int capable(int cap)
 {
-#if 0 /* not yet */
+#if 1 /* ok now */
        if (cap_raised(current->cap_effective, cap))
 #else
        if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
index c982ae28b4560ced7fa27d4b57b1059a93b18460..713227a56e56219b3f47c317cdf3b214c30158bf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * include/linux/serial.h
+ * include/linux/serial_reg.h
  *
  * Copyright (C) 1992, 1994 by Theodore Ts'o.
  * 
index 08f0d281401c21966d1c9334a0682fc85b9f9790..35a7629b6b7015dfd1bfc7442ea1ab6eded744b6 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _LINUX_SOCKET_H
 #define _LINUX_SOCKET_H
 
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
 #include <asm/socket.h>                        /* arch-dependent defines       */
 #include <linux/sockios.h>             /* the SIOCxxx I/O controls     */
 #include <linux/uio.h>                 /* iovec support                */
@@ -256,4 +258,5 @@ extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
 extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
 #endif
+#endif /* not kernel and not glibc */
 #endif /* _LINUX_SOCKET_H */
index d86b1646f1c68d92c89f28af6543ce16ecf29e41..e43e241f31cbf6ea502959f5d2d07993931512f4 100644 (file)
@@ -7,6 +7,8 @@
 
 #endif
 
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
 #define S_IFMT  00170000
 #define S_IFSOCK 0140000
 #define S_IFLNK         0120000
@@ -42,6 +44,8 @@
 #define S_IWOTH 00002
 #define S_IXOTH 00001
 
+#endif
+
 #ifdef __KERNEL__
 #define S_IRWXUGO      (S_IRWXU|S_IRWXG|S_IRWXO)
 #define S_IALLUGO      (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
index eb6d020b42e0f9327b34337938c1b9fa95a06318..e8baf6ded55191d62a74f5b64267c3e19db9372f 100644 (file)
@@ -142,6 +142,22 @@ static inline void move_last_runqueue(struct task_struct * p)
        prev->next_run = p;
 }
 
+static inline void move_first_runqueue(struct task_struct * p)
+{
+       struct task_struct *next = p->next_run;
+       struct task_struct *prev = p->prev_run;
+
+       /* remove from list */
+       next->prev_run = prev;
+       prev->next_run = next;
+       /* add back to list */
+       p->prev_run = &init_task;
+       next = init_task.next_run;
+       init_task.next_run = p;
+       p->next_run = next;
+       next->prev_run = p;
+}
+
 /*
  * The tasklist_lock protects the linked list of processes.
  *
@@ -1329,7 +1345,7 @@ static int setscheduler(pid_t pid, int policy,
        p->policy = policy;
        p->rt_priority = lp.sched_priority;
        if (p->next_run)
-               move_last_runqueue(p);
+               move_first_runqueue(p);
 
        need_resched = 1;
 
index 1496b701b49a60ec6a19c8bdc6be7fb4bf23dc2f..e50c82c355c8ea70aad8df68da4f37ecce57c3ce 100644 (file)
@@ -448,7 +448,7 @@ asmlinkage int sys_setuid(uid_t uid)
        if (current->euid != old_euid)
                current->dumpable = 0;
 
-       if(new_ruid != old_ruid) {
+       if (new_ruid != old_ruid) {
                /* See comment above about NPROC rlimit issues... */
                charge_uid(current, -1);
                current->uid = new_ruid;
@@ -473,7 +473,7 @@ asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
        int old_ruid = current->uid;
        int old_euid = current->euid;
        int old_suid = current->suid;
-       if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+       if (!capable(CAP_SETUID)) {
                if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
                    (ruid != current->euid) && (ruid != current->suid))
                        return -EPERM;
@@ -523,7 +523,7 @@ asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
  */
 asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 {
-       if (current->uid != 0 && current->euid != 0 && current->suid != 0) {
+       if (!capable(CAP_SETGID)) {
                if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
                    (rgid != current->egid) && (rgid != current->sgid))
                        return -EPERM;
@@ -578,13 +578,13 @@ asmlinkage int sys_setfsuid(uid_t uid)
                current->dumpable = 0;
 
        /* We emulate fsuid by essentially doing a scaled-down version
-         * of what we did in setresuid and friends. However, we only
-         * operate on the fs-specific bits of the process' effective
-         * capabilities 
-         *
-         * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
-         *          if not, we might be a bit too harsh here.
-         */
+        * of what we did in setresuid and friends. However, we only
+        * operate on the fs-specific bits of the process' effective
+        * capabilities 
+        *
+        * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
+        *          if not, we might be a bit too harsh here.
+        */
        
        if (!issecure(SECURE_NO_SETUID_FIXUP)) {
                if (old_fsuid == 0 && current->fsuid != 0) {
@@ -749,7 +749,7 @@ asmlinkage int sys_setsid(void)
        read_lock(&tasklist_lock);
        for_each_task(p) {
                if (p->pgrp == current->pid)
-                       goto out;
+                       goto out;
        }
 
        current->leader = 1;
@@ -779,7 +779,7 @@ asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
        i = current->ngroups;
        if (gidsetsize) {
                if (i > gidsetsize)
-                       return -EINVAL;
+                       return -EINVAL;
                if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
                        return -EFAULT;
        }
@@ -994,7 +994,7 @@ asmlinkage int sys_umask(int mask)
 }
     
 asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
-                         unsigned long arg4, unsigned long arg5)
+                        unsigned long arg4, unsigned long arg5)
 {
        int error = 0;
        int sig;
@@ -1003,15 +1003,15 @@ asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
                case PR_SET_PDEATHSIG:
                        sig = arg2;
                        if (sig > _NSIG) {
-                               error = -EINVAL;
-                                break;
-                        }
-                        current->pdeath_signal = sig;
-                        break;
+                               error = -EINVAL;
+                               break;
+                       }
+                       current->pdeath_signal = sig;
+                       break;
                default:
                        error = -EINVAL;
                        break;
-        }
-        return error;
+       }
+       return error;
 }
 
index a3e3be0f16ff369df09a8db26d4a259568fb0186..e9465004350b083caac69577b848500c9b0532cd 100644 (file)
@@ -26,104 +26,74 @@ extern int sysctl_tcp_syncookies;
 static unsigned long tcp_lastsynq_overflow;
 
 /* 
- * This table has to be sorted. Only 8 entries are allowed and the
- * last entry has to be duplicated.
+ * This table has to be sorted and terminated with (__u16)-1.
  * XXX generate a better table.
  * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
  */
 static __u16 const msstab[] = {
-       64,
-       256,    
-       512,    
-       536,
-       1024,   
-       1440,   
-       1460,   
-       4312,
-       4312 
+       64-1,
+       256-1,  
+       512-1,
+       536-1,
+       1024-1, 
+       1440-1,
+       1460-1,
+       4312-1,
+       (__u16)-1
 };
-
-static __u32 make_syncookie(struct sk_buff *skb,  __u32 counter, __u32 seq)
-{
-       __u32 z;
-
-       z = secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
-                                 skb->h.th->source, skb->h.th->dest,
-                                 seq, 
-                                 counter);
-
-#if 0
-       printk(KERN_DEBUG 
-              "msc: z=%u,cnt=%u,seq=%u,sadr=%u,dadr=%u,sp=%u,dp=%u\n",
-              z,counter,seq,
-              skb->nh.iph->saddr,skb->nh.iph->daddr,
-              ntohs(skb->h.th->source), ntohs(skb->h.th->dest));
-#endif
-
-       return z;
-}
+/* The number doesn't include the -1 terminator */
+#define NUM_MSS (sizeof(msstab)/sizeof(msstab[0]) - 1)
 
 /*
- * Generate a syncookie. 
+ * Generate a syncookie.  mssp points to the mss, which is returned
+ * rounded down to the value encoded in the cookie.
  */
 __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
                              __u16 *mssp)
 {
-       int i; 
-       __u32 isn; 
-       const __u16 mss = *mssp, *w; 
+       int mssind;
+       const __u16 mss = *mssp;
 
        tcp_lastsynq_overflow = jiffies;
-
-       isn = make_syncookie(skb, (jiffies/HZ) >> 6, ntohl(skb->h.th->seq));
-       
-       /* XXX sort msstab[] by probability? */
-       w = msstab;
-       for (i = 0; i < 8; i++) 
-               if (mss >= *w && mss < *++w)
-                       goto found;
-       i--;
-found:
-       *mssp = w[-1]; 
+       /* XXX sort msstab[] by probability?  Binary search? */
+       for (mssind = 0; mss > msstab[mssind+1]; mssind++)
+               ;
+       *mssp = msstab[mssind]+1;
 
        net_statistics.SyncookiesSent++;
 
-       isn |= i; 
-       return isn; 
+       return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
+                                    skb->h.th->source, skb->h.th->dest,
+                                    ntohl(skb->h.th->seq),
+                                    jiffies / (HZ*60), mssind);
 }
 
-/* This value should be dependent on TCP_TIMEOUT_INIT and 
- * sysctl_tcp_retries1. It's a rather complicated formula 
- * (exponential backoff) to compute at runtime so it's currently hardcoded
- * here.
+/* 
+ * This (misnamed) value is the age of syncookie which is permitted.
+ * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
+ * sysctl_tcp_retries1. It's a rather complicated formula (exponential
+ * backoff) to compute at runtime so it's currently hardcoded here.
  */
 #define COUNTER_TRIES 4
-
 /*  
  * Check if a ack sequence number is a valid syncookie. 
+ * Return the decoded mss if it is, or 0 if not.
  */
 static inline int cookie_check(struct sk_buff *skb, __u32 cookie) 
 {
-       int mssind; 
-       int i; 
-       __u32 counter; 
        __u32 seq; 
+       __u32 mssind;
 
-       if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT
-           && tcp_lastsynq_overflow) {
+       if ((jiffies - tcp_lastsynq_overflow) > TCP_TIMEOUT_INIT)
                return 0; 
-       }
-
-       mssind = cookie & 7;
-       cookie &= ~7;
 
-       counter = (jiffies/HZ)>>6; 
        seq = ntohl(skb->h.th->seq)-1; 
-       for (i = 0; i < COUNTER_TRIES; i++)
-           if (make_syncookie(skb, counter-i, seq) == cookie)
-                   return msstab[mssind];      
+       mssind = check_tcp_syn_cookie(cookie,
+                                     skb->nh.iph->saddr, skb->nh.iph->daddr,
+                                     skb->h.th->source, skb->h.th->dest,
+                                     seq, jiffies/(HZ*60), COUNTER_TRIES);
 
-       return 0;
+       return mssind < NUM_MSS ? msstab[mssind]+1 : 0;
 }
 
 extern struct or_calltable or_ipv4;
index 56f5f74846bab28922d5b0f65c5a1aa9b2bba0d5..fb2cffeabebe61efdb24e1cdf577fb5e76e04c4d 100644 (file)
@@ -630,7 +630,7 @@ void spx_rcv(struct sock *sk, int bytes)
                                 && (pdata->state != SPX_CONNECTED))
                         {
                                 pdata->state = SPX_CONNECTED;
-                               pdatat->dest_connid = ipxh->spx.sconn;
+                               pdata->dest_connid = ipxh->spx.sconn;
 
                                if(spx_retransmit_chk(pdata, 0, CONACK) < 0)
                                        goto toss_skb;
index b0aa76c82940be440f65d4caca85d28f8750b94a..13fb4518d1f2bdf8614071170295768276a3725f 100644 (file)
@@ -26,6 +26,9 @@
 // command-line argument, and redirect the oops-log into stdin.  Out
 // will come the EIP and call-trace in symbolic form.
 
+// Changed by Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
+// adapted to Linux/m68k
+
 //////////////////////////////////////////////////////////////////////////////
 
 // BUGS:
@@ -39,8 +42,9 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <ctype.h>
+#include <a.out.h>
 
-inline int strnequ(char const* x, char const* y, size_t n) { return (::strncmp(x, y, n) == 0); }
+inline int strnequ(char const* x, char const* y, size_t n) { return (strncmp(x, y, n) == 0); }
 
 const int code_size = 20;
 
@@ -149,32 +153,34 @@ NameList::decode(unsigned char* code, long eip_addr)
     /* This is a hack to avoid using gcc.  We create an object file by
        concatenating objfile_head, the twenty bytes of code, and
        objfile_tail.  */
-    unsigned char objfile_head[] = {
-       0x07, 0x01, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    static struct exec objfile_head = {
+       OMAGIC, code_size + 4, 0, 0, sizeof (struct nlist) * 3, 0, 0, 0
     };
-    unsigned char objfile_tail[] = {
-       0x00, 0x90, 0x90, 0x90,
-       0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00,
-       0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x25, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
-       'g',  'c',  'c',  '2',  '_',  'c',  'o',  'm',  
-       'p',  'i',  'l',  'e',  'd',  '.',  '\0', '_',  
-       'E',  'I',  'P',  '\0', '\0', '\0', '\0', '\0',
-       '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
-       '\0', '\0', '\0', '\0', '\0', '\0'
+    static struct {
+       unsigned char tail[4];
+       struct nlist syms[3];
+       unsigned long strsize;
+       char strings[42];
+    } objfile_tail = {
+#ifdef i386
+       { 0x00, 0x90, 0x90, 0x90 },
+#endif
+#ifdef mc68000
+       { 0x00, 0x00, 0x00, 0x00 },
+#endif
+       { { (char *) 4, N_TEXT, 0, 0, 0 },
+         { (char *) 19, N_TEXT, 0, 0, 0 },
+         { (char *) 37, N_TEXT | N_EXT, 0, 0, 0 } },
+       42,
+       "gcc2_compiled.\0___gnu_compiled_c\0_EIP\0"
     };
     char const* objdump_command = "objdump -d oops_decode.o";
     char const* objfile_name = &objdump_command[11];
     ofstream objfile_stream(objfile_name);
 
-    objfile_stream.write(objfile_head, sizeof(objfile_head));
+    objfile_stream.write((char *) &objfile_head, sizeof(objfile_head));
     objfile_stream.write(code, code_size);
-    objfile_stream.write(objfile_tail, sizeof(objfile_tail));
+    objfile_stream.write((char *) &objfile_tail, sizeof(objfile_tail));
     objfile_stream.close();
     
     FILE* objdump_FILE = popen(objdump_command, "r");
@@ -197,8 +203,8 @@ NameList::decode(unsigned char* code, long eip_addr)
            memset(newbuf, '\0', sizeof(newbuf));
            ostrstream ost(newbuf, sizeof(newbuf));
            ost.width(8);
-           ost << offset;
-           ost << " <_EIP+" << offset << ">: " << &buf[6] << ends;
+           ost << hex << offset;
+           ost << " <_EIP+" << hex << offset << ">: " << &buf[6] << ends;
            strcpy(buf, newbuf);
        }
        if (!strnequ(&buf[9], "<_EIP", 5))
@@ -233,6 +239,7 @@ NameList::decode(unsigned char* code, long eip_addr)
            bp++;
        if (!isxdigit(*bp)) {
            cout << bp_0;
+#ifdef i386
        } else if (*bp_1 == 'j' || strnequ(bp_1, "call", 4)) { // a jump or call insn
            long rel_addr = strtol(bp, 0, 16);
            ksym = find(eip_addr + rel_addr);
@@ -241,6 +248,21 @@ NameList::decode(unsigned char* code, long eip_addr)
                cout << bp_0 << *ksym << endl;
            } else
                cout << bp_0;
+#endif
+#ifdef mc68000
+       } else if ((bp_1[0] == 'b' && bp_1[4] == ' ' && strchr("swl", bp_1[3]))
+                  || (bp_1[0] == 'd' && bp_1[1] == 'b')) {
+           // a branch or decr-and-branch insn
+           if (bp_1[0] == 'd') // skip register
+               while (*bp && *bp++ != ',');
+           long rel_addr = strtoul(bp, 0, 16);
+           ksym = find(eip_addr + rel_addr);
+           if (ksym) {
+               *bp++ = '\0';
+               cout << bp_0 << *ksym << endl;
+           } else
+             cout << bp_0;
+#endif
        } else {
            cout << bp_0;
        }
@@ -308,6 +330,7 @@ main(int argc, char** argv)
        if (cin.eof())
            break;
        cin.get(c);     /* swallow newline */
+#ifdef i386
        if (strstr(buffer, "EIP:") && names.valid()) {
            oops_column =  strstr(buffer, "EIP:");
            if (sscanf(oops_column+13, "[<%x>]", &eip_addr) != 1) {
@@ -321,6 +344,22 @@ main(int argc, char** argv)
            else
                cout << ::hex << eip_addr << " cannot be resolved" << endl;
        }
+#endif
+#ifdef mc68000
+       if (strstr(buffer, "PC:") && names.valid()) {
+           oops_column =  strstr(buffer, "PC:");
+           if (sscanf(oops_column+4, "[<%x>]", &eip_addr) != 1) {
+               cout << "Cannot read pc address from PC: line.  Is this a valid oops file?" << endl;
+               exit(1);
+           }
+           cout << ">>PC: ";
+           KSym* ksym = names.find(eip_addr);
+           if (ksym)
+               cout << *ksym << endl;
+           else
+               cout << ::hex << eip_addr << " cannot be resolved" << endl;
+       }
+#endif
        else if (oops_column && strstr(oops_column, "[<") && names.valid()) {
            unsigned long address;
            while (strstr(oops_column, "[<")) {
@@ -356,6 +395,9 @@ main(int argc, char** argv)
                    ++p;
                if (sscanf(p, "%x", &c) != 1)
                    break;
+#ifdef mc68000
+               *cp++ = c >> 8;
+#endif
                *cp++ = c;
                while (*p && *p++ != ' ')
                    ;