]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.21 1.3.21
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:11 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:11 +0000 (15:10 -0500)
71 files changed:
CREDITS
Makefile
Rules.make
arch/i386/config.in
arch/i386/kernel/entry.S
arch/i386/kernel/setup.c
drivers/block/Makefile
drivers/block/README.ide
drivers/block/README.optcd
drivers/block/blk.h
drivers/block/ide-cd.c
drivers/block/ide.c
drivers/block/ide.h
drivers/block/optcd.c
drivers/block/triton.c [new file with mode: 0644]
drivers/char/lp.c
drivers/char/serial.c
drivers/net/Makefile
drivers/net/net_init.c
drivers/net/ppp.c
drivers/pci/pci.c
drivers/scsi/Makefile
drivers/scsi/scsi.c
drivers/scsi/sd_ioctl.c
drivers/sound/ad1848.c
drivers/sound/sound_switch.c
fs/binfmt_elf.c
fs/buffer.c
fs/msdos/namei.c
fs/nfs/inode.c
fs/proc/net.c
fs/proc/root.c
fs/proc/scsi.c
fs/smbfs/README
fs/smbfs/dir.c
fs/smbfs/file.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/smbfs/sock.c
include/asm-i386/string.h
include/asm-i386/unistd.h
include/linux/hdreg.h
include/linux/if_arp.h
include/linux/if_ether.h
include/linux/in.h
include/linux/mm.h
include/linux/skbuff.h
include/linux/smb_fs.h
include/linux/socket.h
include/net/netrom.h
kernel/Makefile
mm/filemap.c
mm/swap.c
net/Changes
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/core/Makefile
net/core/datagram.c
net/core/iovec.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/icmp.c
net/ipv4/ip.c
net/ipv4/ip_fw.c
net/ipv4/tcp.c
net/ipv4/udp.c
net/netrom/af_netrom.c
net/netrom/nr_dev.c
net/unix/af_unix.c
scripts/depend.awk
versions.mk

diff --git a/CREDITS b/CREDITS
index decee3859b9acf86a0d7d4fbc35e6415d3645ee2..69bf9accae28015f642674da8843b44e3ab0ad8a 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -962,12 +962,14 @@ D: The Linux Support Team Erlangen
 N: Matt Welsh
 E: mdw@sunsite.unc.edu
 D: Linux Documentation Project coordinator
-D: Author, Linux Installation and Getting Started
-D: HOWTO coordinator and writer
-D: Maintainer of sunsite.unc.edu Linux doc archives
-D: Moderator, comp.os.linux.announce
-S: 205 Gray Street NE
-S: Wilson, North Carolina 27893
+D: Author, _Running_Linux_ and I&GS guide
+D: Linuxdoc-SGML formatting system
+D: Keithley DAS1200 device driver
+D: Maintainer of sunsite WWW and FTP, moderator c.o.l.answers
+S: Cornell University Computer Science Department
+S: Robotics and Vision Laboratory
+S: 4130 Upson Hall
+S: Ithaca NY 14850
 S: USA
 
 N: Marco van Wieringen
index 0cc3d59cf60d2693f6c04e05678f61b9157f76bb..421cc33d3a7b55e3b967c972d516a7e0c36b123d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 20
+SUBLEVEL = 21
 
 ARCH = i386
 
index d7686e5ad3fbfa4e42c2f85995289450a6a3d86a..95dbbded2fc64b923f4b8c2cf7a8e5428020b1d5 100644 (file)
@@ -45,7 +45,8 @@ first_rule: sub_dirs $(O_TARGET) $(L_TARGET)
 # Rule to compile a set of .o files into one .o file
 #
 ifdef O_TARGET
-$(O_TARGET): $(O_OBJS)
+$(O_TARGET): $(O_OBJS) $(TOPDIR)/include/linux/config.h
+       rm -f $@
 ifdef O_OBJS
        $(LD) $(EXTRA_LDFLAGS) -r -o $@ $(O_OBJS)
 else
@@ -57,7 +58,7 @@ endif
 # Rule to compile a set of .o files into one .a file
 #
 ifdef L_TARGET
-$(L_TARGET): $(L_OBJS)
+$(L_TARGET): $(L_OBJS) $(TOPDIR)/include/linux/config.h
        rm -f $@
        $(AR) $(EXTRA_ARFLAGS) rcs $@ $(L_OBJS)
 endif
index ca82d156d67a3fb2ae6bde16bf936a54510398f5..9bae0d8e61b659251178faa82403feac37c09d7f 100644 (file)
@@ -26,7 +26,10 @@ bool 'Networking support' CONFIG_NET y
 bool 'Limit memory to low 16MB' CONFIG_MAX_16M n
 bool 'PCI bios support' CONFIG_PCI y
 if [ "$CONFIG_PCI" = "y" ]; then
- bool '   PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE y
+  bool '   PCI bridge optimisation (experimental)' CONFIG_PCI_OPTIMIZE y
+  if [ "$CONFIG_BLK_DEV_IDE" = "y" ]; then
+    bool '   PCI Triton IDE Bus Master DMA support' CONFIG_BLK_DEV_TRITON y
+  fi
 fi
 bool 'System V IPC' CONFIG_SYSVIPC y
 bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF y
index bd64d74ba9b968e321d7abcf6f8b2ddd6dad0140..f09a507d288c9496efb6badfac67c3a9bb5779c0 100644 (file)
@@ -517,4 +517,5 @@ ENTRY(sys_call_table)
        .long SYMBOL_NAME(sys_getdents)
        .long SYMBOL_NAME(sys_select)
        .long SYMBOL_NAME(sys_flock)
-       .space (NR_syscalls-143)*4
+       .long SYMBOL_NAME(sys_msync)
+       .space (NR_syscalls-144)*4
index 45097c79ee0027fb5a29e8ba02d6c1130cd4b626..f7cb717f70acdfece7ea1126a81f1b69c75c6bcf 100644 (file)
@@ -103,14 +103,24 @@ void setup_arch(char **cmdline_p,
        init_task.mm->brk = TASK_SIZE + (unsigned long) &_end;
 
        for (;;) {
+               /*
+                * "mem=nopentium" disables the 4MB page tables.
+                * "mem=XXX[kKmM]" overrides the BIOS-reported
+                * memory size
+                */
                if (c == ' ' && *(const unsigned long *)from == *(const unsigned long *)"mem=") {
-                       memory_end = simple_strtoul(from+4, &from, 0);
-                       if ( *from == 'K' || *from == 'k' ) {
-                               memory_end = memory_end << 10;
-                               from++;
-                       } else if ( *from == 'M' || *from == 'm' ) {
-                               memory_end = memory_end << 20;
-                               from++;
+                       if (!memcmp(from+4, "nopentium", 9)) {
+                               from += 9+4;
+                               x86_capability &= ~8;
+                       } else {
+                               memory_end = simple_strtoul(from+4, &from, 0);
+                               if ( *from == 'K' || *from == 'k' ) {
+                                       memory_end = memory_end << 10;
+                                       from++;
+                               } else if ( *from == 'M' || *from == 'm' ) {
+                                       memory_end = memory_end << 20;
+                                       from++;
+                               }
                        }
                }
                c = *(from++);
index 6fbd176283bf982ec1ef1cb7581d94e888b01084..d5984bddf6c1bc906d233e9f3188686f66a572a0 100644 (file)
@@ -106,6 +106,10 @@ ifdef CONFIG_BLK_DEV_IDE
 L_OBJS += ide.o
 endif
 
+ifdef CONFIG_BLK_DEV_TRITON
+L_OBJS += triton.o
+endif
+
 ifdef CONFIG_BLK_DEV_IDECD
 L_OBJS += ide-cd.o
 endif
index ad92b88cf8b77b496dff7a19c3f6b32b70d74e32..efbb1e4fe207e3e1a555938daadbd3244c572e74 100644 (file)
@@ -3,7 +3,12 @@ README.ide -- Information regarding ide.c and ide-cd.c (IDE driver in 1.3.x)
 Supported by:  mlord@bnr.ca           -- disks, interfaces, probing
                snyder@fnald0.fnal.gov -- cdroms, ATAPI, audio
 
-(see description later on below for handling BIG IDE drives with >1024 cyls).
+   +-----------------------------------------------------------------+
+   |  The hdparm utility for controlling various IDE features is     |
+   |  packaged separately.  Look for it on popular linux FTP sites.  |
+   +-----------------------------------------------------------------+
+
+See description later on below for handling BIG IDE drives with >1024 cyls.
 
 Major features of ide.c & ide-cd.c:
 
@@ -35,16 +40,29 @@ NEW!        - transparent support for DiskManager 6.0x and "Dynamic Disk Overlay"
 NEW!           - should work for for EZ-Drive disks as well (not verified)
                - works with Linux fdisk, LILO, loadlin, bootln, etc..
 NEW!   - ide-cd.c now compiles separate from ide.c
+NEW!   - Bus-Master DMA support for Intel PCI Triton chipset IDE interfaces
+               - for details, see comments at top of triton.c
 
-For a list of work underway, see the comments near the top of ide.c and ide-cd.c
+For work in progress, see the comments in ide.c, ide-cd.c, and triton.c.
 
 ***
-
-IMPORTANT NOTICE:  "CMD" EIDE Interfaces will not (by default) work *reliably*
-when drives are attached to the second interface.  To "fix" this, supply the
-special kernel "command line" parameter to LILO:    ide1=serialize
-Failure to do so can cause severe data corruption!
-
+***  IMPORTANT NOTICES:
+***  ==================
+***
+***  "CMD" EIDE Interfaces will not (by default) work *reliably* when drives
+***  are attached to the second interface.  This is due to a flaw in the
+***  hardware.  To "fix" this, supply the special kernel "command line"
+***  parameter to LILO or LOADLIN:    ide1=serialize
+***
+***  "CMD 640B" EIDE Interfaces will not work *reliably* when "hdparm -u1"
+***  (interrupt unmasking) is used.  This is due to a flaw in the hardware,
+***  and is only a problem when "hdparm -u1" is used after booting.
+***
+***  "RZ1000" EIDE Interfaces will also not work *reliably* when "hdparm -u1"
+***  (interrupt unmasking) is used.  This is due to a flaw in the hardware,
+***  and is only a problem when "hdparm -u1" is used after booting.
+***
+***  Failure to abide by these restrictions can cause severe data corruption!
 ***
 
 To access devices on the 2nd/3rd/4th interfaces, device entries must first be
@@ -76,7 +94,7 @@ seldom occurs.  Be careful, and if in doubt, don't do it!
 
 Drives are normally found by auto-probing and/or examining the CMOS/BIOS data.
 For really weird situations, the apparent (fdisk) geometry can also be specified
-on the kernel "command line" using LILO.  The format of such lines is:   
+on the kernel "command line" using LILO.  The format of such lines is:
 
        hdx=cyls,heads,sects,wpcom,irq
 or     hdx=cdrom
@@ -139,9 +157,6 @@ and still allows newer hardware to run on the 2nd/3rd/4th IDE ports
 under control of ide.c.   To have ide.c also "take over" the primary
 IDE port in this situation, use the "command line" parameter:  ide0=0x1f0
 
-The hdparm.c program for controlling various IDE features is now packaged
-separately.  Look for it on popular linux FTP sites.
-
 mlord@bnr.ca
 snyder@fnald0.fnal.gov
 ================================================================================
@@ -151,7 +166,7 @@ Summary of ide driver parameters for kernel "command line":
 
   "hdx="  is recognized for all "x" from "a" to "h", such as "hdc".
   "idex=" is recognized for all "x" from "0" to "3", such as "ide1".
+
   "hdx=noprobe"                : drive may be present, but do not probe for it
   "hdx=nowerr"         : ignore the WRERR_STAT bit on this drive
   "hdx=cdrom"          : drive is present, and is a cdrom drive
@@ -300,7 +315,7 @@ by doing the following after installing slackware (or whatever):
        0. Boot from the "boot floppy" created during the installation
         1. Mount your DOS partition as /dos (and stick it in /etc/fstab)
         2. Move your kernel (/vmlinuz) to /dos/vmlinuz with:  mv /vmlinuz /dos
-        3. Edit /etc/lilo.conf to change /vmlinuz to /dos/vmlinuz 
+        3. Edit /etc/lilo.conf to change /vmlinuz to /dos/vmlinuz
         4. Move /boot to /dos/boot with:  cp -a /boot /dos ; rm -r /boot
         5. Create a symlink for LILO to use with:  ln -s /dos/boot /boot
         6. Re-run LILO with:  lilo
index 63c8d29b09b974c2344bfc2138d93e9f146cefc5..514c9d9ccb126a2200b4966e1429d7187728cf38 100644 (file)
@@ -1,9 +1,14 @@
 This is the README file for the Optics Storage 8000 AT CDROM device driver.
 
-The driver contains code to enable an ISP16 interface if it finds one, so if
-you have that, you're lucky.
-
-My configuration code for the ISP-16 card can get found at
+The driver contains code to enable an ISP16 interface if it finds one.  It
+didn't originally (although this README erroneously said so), because I think
+this kind of code should go into its own module. But having to use a hack all
+the time in order to use a part of the standard kernel started to annoy me, so
+I copied the ISP16 code by Eric van der Maarel (maarel@marin.nl) from Vadim
+Model's Sanyo sjcd driver. I'll remove it again from this driver when we have
+some common way to talk to ISP16 interfaces.
+
+My original configuration code for the ISP-16 card can get found at
       dutette.et.tudelft.nl:/pub/linux/
 and at Eberhard's mirror
       ftp.gwdg.de:/pub/linux/cdrom/drivers/optics/
@@ -32,7 +37,10 @@ or
 with the matching address value of your interface card.
 
 I have tried the module with several 1.2.x kernel versions, and it seems to
-work, as far as I tested. If you use it, I'd appreciate success/failure
-reports.
+work, as far as I tested. It also seems to work for several 1.3.x versions.
+If you use it, I'd appreciate success/failure reports. If you find a bug,
+try recompiling the driver with some strategically chosen #undef DEBUG_...'s
+changed into #defines (you'll find them in .../include/linux/optcd.h) and
+include the messages generated in your bug report. Good luck.
 
 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
index 0395968461fe3be4a29e49dc39144ff48ed423b4..d8d936fe36705826bb3619caecbf4a68204e9966 100644 (file)
@@ -336,7 +336,7 @@ static void (DEVICE_REQUEST)(void);
 
 #if ! SCSI_MAJOR(MAJOR_NR)
 
-#ifdef _IDE_CD_C       /* ide-cd.c uses copy from ide.c */
+#if defined(_IDE_CD_C) || defined(_TRITON_C) /* shares copy with ide.c */
 void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup);
 #else
 
index 69039bfb9552101758f5a8af46c4d9974e2cfebb..722d0fa42a5970b9894355bb8c3c84da7489b259 100644 (file)
 #define PACKET_COMMAND 4315
 #define REQUEST_SENSE_COMMAND 4316
 
-#define WIN_PACKETCMD 0xa0  /* Send a packet command. */
-
 /* Some ATAPI command opcodes (just like SCSI).
    (Some other cdrom-specific codes are in cdrom.h.) */
 #define TEST_UNIT_READY         0x00
index 57214551a0731184b3d4ac8184606fa4295eb02f..9ff7285cdf0ddd5e90d21fec32e998533a167756 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/ide.c  Version 5.03  Aug 13, 1995
+ *  linux/drivers/block/ide.c  Version 5.10  Aug 26, 1995
  *
  *  Copyright (C) 1994, 1995  Linus Torvalds & authors (see below)
  */
  *  Version 5.03       tune-ups, comments, remove "busy wait" from drive resets
  *                     removed PROBE_FOR_IRQS option -- no longer needed
  *                     OOOPS!  fixed "bad access" bug for 2nd drive on an i/f
+ *  Version 5.04       changed "ira %d" to "irq %d" in DEBUG message
+ *                     added more comments, cleaned up unexpected_intr()
+ *                     OOOPS!  fixed null pointer problem in ide reset code
+ *                     added autodetect for Triton chipset -- no effect yet
+ *  Version 5.05       OOOPS!  fixed bug in revalidate_disk()
+ *                     OOOPS!  fixed bug in ide_do_request()
+ *                     added ATAPI reset sequence for cdroms
+ *  Version 5.10       added Bus-Mastered DMA support for Triton Chipset
+ *                     some (mostly) cosmetic changes
  *
  *  Driver compile-time options are in ide.h
  *
  *  To do, in likely order of completion:
  *     - add in several updates from my email collection (soon folks!)
- *     - add full support for Intel Triton chipset, including bus-mastered DMA
  *     - improved CMD support:  handing this off to someone else
  *     - find someone to work on IDE *tape drive* support
  */
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 
+#ifdef CONFIG_PCI
+#include <linux/bios32.h>
+#endif /* CONFIG_PCI */
+
 #include "ide.h"
 
 static ide_hwif_t      ide_hwifs[MAX_HWIFS];           /* hwif info */
@@ -196,50 +208,46 @@ void ide_set_recovery_timer (ide_hwif_t *hwif)
  * ide_drive_t structs as needed, rather than always consuming memory
  * for the max possible number (MAX_HWIFS * MAX_DRIVES) of them.
  */
+#define MAGIC_COOKIE 0x12345678
 static void init_ide_data (void)
 {
+       byte *p;
        unsigned int h, unit;
-       static unsigned long magic_cookie = 0x12345678;
+       static unsigned long magic_cookie = MAGIC_COOKIE;
 
-       if (magic_cookie != 0x12345678)
+       if (magic_cookie != MAGIC_COOKIE)
                return;         /* already initialized */
        magic_cookie = 0;
 
        for (h = 0; h < 16; ++h)
                 irq_to_hwgroup[h] = NULL;
 
+       /* bulk initialize hwif & drive info with zeros */
+       p = ((byte *) ide_hwifs) + sizeof(ide_hwifs);
+       do {
+               *--p = 0;
+       } while (p > (byte *) ide_hwifs);
+
        for (h = 0; h < MAX_HWIFS; ++h) {
                ide_hwif_t *hwif = &ide_hwifs[h];
 
+               /* fill in any non-zero initial values */
                hwif->noprobe   = (h > 1);
-               hwif->hwgroup   = NULL;
                hwif->io_base   = default_io_base[h];
                hwif->ctl_port  = hwif->io_base ? hwif->io_base + 0x206 : 0x000;
 #ifdef CONFIG_BLK_DEV_HD
                if (hwif->io_base == HD_DATA)
                        hwif->noprobe = 1; /* may be overriden by ide_setup() */
 #endif /* CONFIG_BLK_DEV_HD */
-               hwif->gd        = NULL;
-               hwif->irq       = 0;  /* default_irqs[h] used when probe fails */
                hwif->major     = ide_hwif_to_major[h];
                hwif->name[0]   = 'i';
                hwif->name[1]   = 'd';
                hwif->name[2]   = 'e';
                hwif->name[3]   = '0' + h;
-               hwif->name[4]   = '\0';
-               hwif->present   = 0;
-               hwif->next      = NULL;
-               hwif->reset_timeout = 0;
 
                for (unit = 0; unit < MAX_DRIVES; ++unit) {
                        ide_drive_t *drive = &hwif->drives[unit];
 
-                       /* bulk initialize drive info with zeros */
-                       byte *p = ((byte *) drive) + sizeof(ide_drive_t);
-                       do {
-                               *--p = 0;
-                       } while (p > (byte *) drive);
-
                        /* fill in any non-zero initial values */
                        drive->select.all               = (unit<<4)|0xa0;
                        drive->hwif                     = hwif;
@@ -257,7 +265,13 @@ static void init_ide_data (void)
 
 #ifdef __i386__
 #define VLB_SYNC 1
-
+/*
+ * Some localbus EIDE interfaces require a special access sequence
+ * when using 32-bit I/O instructions to transfer data.  We call this
+ * the "vlb_sync" sequence, which consists of three successive reads
+ * of the sector count register location, with interrupts disabled
+ * to ensure that the reads all happen together.
+ */
 static inline void do_vlb_sync (unsigned short port) {
        unsigned int _v;
        __asm__ __volatile__    (
@@ -404,16 +418,30 @@ static void ide_geninit (struct gendisk *gd)
 }
 
 /*
- * ide_alloc(): memory allocation for using during driver initialization.
+ * ide_alloc(): memory allocation for use *only* during driver initialization.
+ * If "within_area" is non-zero, the memory will be allocated such that
+ * it lies entirely within a "within_area" sized area (eg. 4096).  This is
+ * needed for DMA stuff.  "within_area" must be a power of two (not validated).
+ * All allocations are longword aligned.
  */
-static unsigned long init_mem_start = 0uL;     /* used by init routines */
+static unsigned long ide_mem_start = 0uL;      /* used by ide_alloc() */
 
-static inline void *ide_alloc (unsigned long bytecount)
+void *ide_alloc (unsigned long bytecount, unsigned long within_area)
 {
-       unsigned long p = init_mem_start;
-       if (!p) panic("ide: ide_alloc() not valid now\n");
-       init_mem_start += (bytecount + 3uL) & ~3uL;
-       return (void *) p;
+       const unsigned long longsize_m1 = (sizeof(long) - 1);
+       void *p;
+
+       if (!ide_mem_start)
+               panic("ide: ide_alloc() not valid now\n");
+       ide_mem_start = (ide_mem_start + longsize_m1) & ~longsize_m1;
+       if (within_area) {
+               unsigned long fraction = within_area - (ide_mem_start & (within_area - 1));
+               if (fraction < bytecount)
+                       ide_mem_start += fraction; /* realign to a new page */
+       }
+       p = (void *) ide_mem_start;
+       ide_mem_start += (bytecount + longsize_m1) & ~longsize_m1;
+       return p;
 }
 
 /*
@@ -434,10 +462,10 @@ static void init_gendisk (ide_hwif_t *hwif)
                        break;
        }
        minors    = units * (1<<PARTN_BITS);
-       gd        = ide_alloc(sizeof(struct gendisk));
-       gd->sizes = ide_alloc(minors * sizeof(int));
-       gd->part  = ide_alloc(minors * sizeof(struct hd_struct));
-       bs        = ide_alloc(minors*sizeof(int));
+       gd        = ide_alloc (sizeof(struct gendisk), 0);
+       gd->sizes = ide_alloc (minors * sizeof(int), 0);
+       gd->part  = ide_alloc (minors * sizeof(struct hd_struct), 0);
+       bs        = ide_alloc (minors*sizeof(int), 0);
 
        /* cdroms and msdos f/s are examples of non-1024 blocksizes */
        blksize_size[hwif->major] = bs;
@@ -470,7 +498,12 @@ static void unexpected_intr (int, ide_hwgroup_t *);
  */
 static void reset_ihandler (ide_drive_t *drive)
 {
+       unsigned long flags;
+
+       save_flags(flags);
+       cli();
        unexpected_intr (HWIF(drive)->irq, HWGROUP(drive));
+       restore_flags(flags);
 }
 
 /*
@@ -481,15 +514,49 @@ static void start_reset_timer (ide_hwif_t *hwif)
 {
        ide_hwgroup_t *hwgroup = hwif->hwgroup;
 
-       hwif->reset_timeout = jiffies + WAIT_WORSTCASE; /* max waiting time */
+       hwgroup->reset_timeout = jiffies + WAIT_WORSTCASE; /* max waiting time */
        hwgroup->handler = &reset_ihandler;             /* dummy irq handler */
        hwgroup->timer.expires = jiffies + (HZ/20);     /* polling interval */
        add_timer(&(hwgroup->timer));
 }
 
+#ifdef CONFIG_BLK_DEV_IDECD
+/*
+ * atapi_reset_handler() gets invoked to poll the interface for completion every 50ms
+ * during an atapi drive reset operation. If the drive has not yet responded,
+ * and we have not yet hit our maximum waiting time, then the timer is restarted
+ * for another 50ms.
+ *
+ * Returns 1 if waiting for another 50ms, returns 0 otherwise.
+ */
+static int atapi_reset_handler (ide_hwgroup_t *hwgroup)
+{
+       ide_hwif_t *hwif = hwgroup->hwif;
+       ide_drive_t *drive = hwgroup->drive;
+       byte stat;
+
+       OUT_BYTE (drive->select.all, IDE_SELECT_REG);
+       udelay (10);
+
+       if (!OK_STAT(stat=GET_STAT(), 0, BUSY_STAT)) {
+               if (jiffies < hwgroup->reset_timeout) {
+                       start_reset_timer (hwif);
+                       return 1;
+               }
+               printk("%s: ATAPI reset timed-out, status=0x%02x\n", drive->name, stat);
+               return ide_do_reset (drive);    /* do it the old fashioned way */
+       }
+       hwgroup->doing_atapi_reset = 0;
+       hwgroup->handler = NULL;        /* allow new requests to be processed */
+       hwgroup->reset_timeout = 0;     /* signal end of ide reset operation */
+       printk("%s: ATAPI reset complete\n", drive->name);
+       return 0;
+}
+#endif /* CONFIG_BLK_DEV_IDECD */
+
 /*
  * reset_handler() gets invoked to poll the interface for completion every 50ms
- * during an ide reset operation. If the drives have not not responded,
+ * during an ide reset operation. If the drives have not yet responded,
  * and we have not yet hit our maximum waiting time, then the timer is restarted
  * for another 50ms.
  *
@@ -501,8 +568,13 @@ static int reset_handler (ide_hwgroup_t *hwgroup)
        ide_drive_t *drive = hwgroup->drive;
        byte tmp;
 
+#ifdef CONFIG_BLK_DEV_IDECD
+       if (hwgroup->doing_atapi_reset)
+               return atapi_reset_handler(hwgroup);
+#endif /* CONFIG_BLK_DEV_IDECD */
+
        if (!OK_STAT(tmp=GET_STAT(), 0, BUSY_STAT)) {
-               if (jiffies < hwif->reset_timeout) {
+               if (jiffies < hwgroup->reset_timeout) {
                        start_reset_timer (hwif);
                        return 1;
                }
@@ -532,7 +604,7 @@ static int reset_handler (ide_hwgroup_t *hwgroup)
                }
        }
        hwgroup->handler = NULL;        /* allow new requests to be processed */
-       hwif->reset_timeout = 0;        /* signal end of ide reset operation */
+       hwgroup->reset_timeout = 0;     /* signal end of ide reset operation */
        return 0;
 }
 
@@ -542,9 +614,8 @@ static int reset_handler (ide_hwgroup_t *hwgroup)
  * the same interface, so it can really be thought of as resetting the
  * interface rather than resetting the drive.
  *
- * ATAPI devices have their own reset mechanism (not handled here),
- * which allows them to be individually reset without clobbering other
- * devices on the same interface.  ide-cd.c will handle those separately.
+ * ATAPI devices have their own reset mechanism which allows them to be
+ * individually reset without clobbering other devices on the same interface.
  *
  * Unfortunately, the IDE interface does not generate an interrupt to let
  * us know when the reset operation has finished, so we must poll for this.
@@ -552,15 +623,35 @@ static int reset_handler (ide_hwgroup_t *hwgroup)
  * (up to 30 seconds worstcase).  So, instead of busy-waiting here for it,
  * we set a timer to poll at 50ms intervals.
  */
-static int ide_do_reset (ide_drive_t *drive)
+int ide_do_reset (ide_drive_t *drive)
 {
        unsigned int unit;
        unsigned long flags;
        ide_hwif_t *hwif = HWIF(drive);
+       ide_hwgroup_t *hwgroup = HWGROUP(drive);
 
        save_flags(flags);
        cli();          /* Why ? */
 
+#ifdef CONFIG_BLK_DEV_IDECD
+       /* For an ATAPI device, first try an ATAPI SRST. */
+       if (drive->media == cdrom) {
+               if (!hwgroup->doing_atapi_reset) {
+                       hwgroup->doing_atapi_reset = 1;
+                       if (!drive->keep_settings)
+                               drive->unmask = 0;
+                       OUT_BYTE (drive->select.all, IDE_SELECT_REG);
+                       OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
+                       udelay (10);
+                       hwgroup->reset_timeout = jiffies + WAIT_WORSTCASE;
+                       start_reset_timer (hwif); /* begin periodic polling */
+                       restore_flags (flags);
+                       return 1;
+               }
+       }
+       hwgroup->doing_atapi_reset = 0;
+#endif /* CONFIG_BLK_DEV_IDECD */
+
        /*
         * First, reset any device state data we were maintaining
         * for any of the drives on this interface.
@@ -589,10 +680,10 @@ static int ide_do_reset (ide_drive_t *drive)
         * This single interrupt gives us a "fast poll" for drives that
         * recover from reset very quickly, saving us the first 50ms wait time.
         */
-       OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set nIEN and SRST */
+       OUT_BYTE(drive->ctl|6,IDE_CONTROL_REG); /* set SRST and nIEN */
        udelay(5);                      /* more than enough time */
        OUT_BYTE(drive->ctl|2,IDE_CONTROL_REG); /* clear SRST, leave nIEN */
-       hwif->reset_timeout = jiffies + WAIT_WORSTCASE;
+       hwgroup->reset_timeout = jiffies + WAIT_WORSTCASE;
        start_reset_timer (hwif);       /* begin periodic polling */
 #endif /* OK_TO_RESET_CONTROLLER */
 
@@ -640,7 +731,7 @@ byte ide_dump_status (ide_drive_t *drive, const char *msg, byte stat)
                        printk("Busy ");
                else {
                        if (stat & READY_STAT)  printk("DriveReady ");
-                       if (stat & WRERR_STAT)  printk("WriteFault ");
+                       if (stat & WRERR_STAT)  printk("DeviceFault ");
                        if (stat & SEEK_STAT)   printk("SeekComplete ");
                        if (stat & DRQ_STAT)    printk("DataRequest ");
                        if (stat & ECC_STAT)    printk("CorrectedError ");
@@ -746,6 +837,12 @@ int ide_error (ide_drive_t *drive, const char *msg, byte stat)
        if (GET_STAT() & (BUSY_STAT|DRQ_STAT))
                rq->errors |= ERROR_RESET;      /* Mmmm.. timing problem */
 
+       if (rq->errors > 3 && drive->using_dma) {       /* DMA troubles? */
+               drive->using_dma = 0;
+               printk("%s: DMA disabled\n", drive->name);
+               --rq->errors;
+               return 0;
+       }
        if (rq->errors >= ERROR_MAX)
                ide_end_request(0, HWGROUP(drive));
        else {
@@ -916,7 +1013,7 @@ static void multwrite_intr (ide_drive_t *drive)
  * Issue a simple drive command
  * The drive must be selected beforehand.
  */
-static inline void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
+static void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
 {
        ide_set_handler (drive, handler);
        OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
@@ -924,6 +1021,9 @@ static inline void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler
        OUT_BYTE(cmd,IDE_COMMAND_REG);
 }
 
+/*
+ * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
+ */
 static void set_multmode_intr (ide_drive_t *drive)
 {
        byte stat = GET_STAT();
@@ -939,6 +1039,9 @@ static void set_multmode_intr (ide_drive_t *drive)
        IDE_DO_REQUEST;
 }
 
+/*
+ * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
+ */
 static void set_geometry_intr (ide_drive_t *drive)
 {
        byte stat = GET_STAT();
@@ -950,6 +1053,9 @@ static void set_geometry_intr (ide_drive_t *drive)
        IDE_DO_REQUEST;
 }
 
+/*
+ * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
+ */
 static void recal_intr (ide_drive_t *drive)
 {
        byte stat = GET_STAT();
@@ -961,6 +1067,10 @@ static void recal_intr (ide_drive_t *drive)
        IDE_DO_REQUEST;
 }
 
+#ifdef IDE_DRIVE_CMD
+/*
+ * drive_cmd_intr() is invoked on completion of a special DRIVE_CMD.
+ */
 static void drive_cmd_intr (ide_drive_t *drive)
 {
        byte stat = GET_STAT();
@@ -972,8 +1082,14 @@ static void drive_cmd_intr (ide_drive_t *drive)
                return;
        IDE_DO_REQUEST;
 }
+#endif /* IDE_DRIVE_CMD */
 
-static void do_special (ide_drive_t *drive)
+/*
+ * do_special() is used to issue WIN_SPECIFY, WIN_RESTORE, and WIN_SETMULT
+ * commands to a drive.  It used to do much more, but has been scaled back
+ * in recent updates, and could be completely eliminated with a bit more effort.
+ */
+static inline void do_special (ide_drive_t *drive)
 {
        special_t *s = &drive->special;
 #ifdef DEBUG
@@ -1044,6 +1160,11 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
        return 1;
 }
 
+/*
+ * do_rw_disk() issues WIN_{MULT}READ and WIN_{MULT}WRITE commands to a disk,
+ * using LBA if supported, or CHS otherwise, to address sectors.  It also takes
+ * care of issuing special DRIVE_CMDs.
+ */
 static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
 {
        OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
@@ -1075,11 +1196,15 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
 #endif
        }
        if (rq->cmd == READ) {
+               if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_read, drive)))
+                       return;
                ide_set_handler(drive, &read_intr);
                OUT_BYTE(drive->mult_count ? WIN_MULTREAD : WIN_READ, IDE_COMMAND_REG);
                return;
        }
        if (rq->cmd == WRITE) {
+               if (drive->using_dma && !(HWIF(drive)->dmaproc(ide_dma_write, drive)))
+                       return;
                OUT_BYTE(drive->mult_count ? WIN_MULTWRITE : WIN_WRITE, IDE_COMMAND_REG);
                if (ide_wait_stat(drive, DATA_READY, drive->bad_wstat, WAIT_DRQ)) {
                        printk("%s: no DRQ after issuing %s\n", drive->name,
@@ -1108,6 +1233,10 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
                        ide_cmd(drive, args[0], args[1], &drive_cmd_intr);
                        return;
                } else {
+                       /*
+                        * NULL is actually a valid way of waiting for
+                        * all current requests to be flushed from the queue.
+                        */
 #ifdef DEBUG
                        printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
@@ -1120,6 +1249,9 @@ static inline void do_rw_disk (ide_drive_t *drive, struct request *rq, unsigned
        ide_end_request(0, HWGROUP(drive));
 }
 
+/*
+ * do_request() initiates handling of a new I/O request
+ */
 static inline void do_request (ide_hwif_t *hwif, struct request *rq)
 {
        unsigned int minor, unit;
@@ -1137,18 +1269,21 @@ static inline void do_request (ide_hwif_t *hwif, struct request *rq)
                goto kill_rq;
        }
        drive = &hwif->drives[unit];
+#ifdef DEBUG
        if (rq->bh && !rq->bh->b_lock) {
                printk("%s: block not locked\n", drive->name);
                goto kill_rq;
        }
+#endif
        block    = rq->sector;
        blockend = block + rq->nr_sectors;
        if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) {
-               printk("%s: bad access: block=%ld, count=%ld\n",
-                       drive->name, block, rq->nr_sectors);
+               printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name,
+                (minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors);
                goto kill_rq;
        }
        block += drive->part[minor&PARTN_MASK].start_sect + drive->sect0;
+       ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
 #if (DISK_RECOVERY_TIME > 0)
        while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
 #endif
@@ -1158,7 +1293,6 @@ static inline void do_request (ide_hwif_t *hwif, struct request *rq)
                return;
 
        }
-       ((ide_hwgroup_t *)hwif->hwgroup)->drive = drive;
        if (!drive->special.all) {
 #ifdef CONFIG_BLK_DEV_IDECD
                switch (drive->media) {
@@ -1202,7 +1336,6 @@ kill_rq:
 void ide_do_request (ide_hwgroup_t *hwgroup)
 {
        cli();  /* paranoia */
-
        if (hwgroup->handler != NULL) {
                printk("%s: EEeekk!! handler not NULL in ide_do_request()\n", hwgroup->hwif->name);
                return;
@@ -1218,14 +1351,25 @@ void ide_do_request (ide_hwgroup_t *hwgroup)
                                        goto got_rq;
                        } while ((hwif = hwif->next) != hwgroup->hwif);
                        return;         /* no work left for this hwgroup */
+               got_rq:
+                       blk_dev[hwif->major].current_request = rq->next;
                }
-       got_rq:
-               blk_dev[hwif->major].current_request = rq->next;
                do_request(hwgroup->hwif = hwif, hwgroup->rq = rq);
                cli();
        } while (hwgroup->handler == NULL);
 }
 
+/*
+ * do_hwgroup_request() invokes ide_do_request() after first masking
+ * all possible interrupts for the current hwgroup.  This prevents race
+ * conditions in the event that an unexpected interrupt occurs while
+ * we are in the driver.
+ *
+ * Note that when an interrupt is used to reenter the driver, the first level
+ * handler will already have masked the irq that triggered, but any other ones
+ * for the hwgroup will still be unmasked.  The driver tries to be careful
+ * about such things.
+ */
 static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
 {
        if (hwgroup->handler == NULL) {
@@ -1270,7 +1414,7 @@ static void timer_expiry (unsigned long data)
        save_flags(flags);
        cli();
 
-       if (hwgroup->hwif->reset_timeout != 0) { /* ide reset in progress? */
+       if (hwgroup->reset_timeout != 0) { /* ide reset in progress? */
                if (!reset_handler(hwgroup))
                        do_hwgroup_request (hwgroup);
        } else if (hwgroup->handler == NULL) {   /* not waiting for anything? */
@@ -1278,6 +1422,8 @@ static void timer_expiry (unsigned long data)
                printk("%s: marginal timeout\n", drive->name);
        } else {                                 /* drive not responding */
                hwgroup->handler = NULL;
+               if (hwgroup->hwif->dmaproc) 
+                       (void) hwgroup->hwif->dmaproc (ide_dma_abort, drive);
                if (!ide_error(drive, "irq timeout", GET_STAT()))
                        do_hwgroup_request (hwgroup);
        }
@@ -1293,24 +1439,32 @@ static void timer_expiry (unsigned long data)
  * On laptops (and "green" PCs), an unexpected interrupt occurs whenever the
  * drive enters "idle", "standby", or "sleep" mode, so if the status looks
  * "good", we just ignore the interrupt completely.
+ *
+ * This routine assumes cli() is in effect when called.
+ *
+ * If an unexpected interrupt happens on irq15 while we are handling irq14
+ * and if the two interfaces are "serialized" (CMD640B), then it looks like
+ * we could screw up by interfering with a new request being set up for irq15.
+ *
+ * In reality, this is a non-issue.  The new command is not sent unless the
+ * drive is ready to accept one, in which case we know the drive is not
+ * trying to interrupt us.  And ide_set_handler() is always invoked before
+ * completing the issuance of any new drive command, so we will not be 
+ * accidently invoked as a result of any valid command completion interrupt.
+ *
  */
 static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
 {
        byte stat;
        unsigned int unit;
        ide_hwif_t *hwif = hwgroup->hwif;
-       unsigned long flags;
-
-       save_flags(flags);
-       cli();
 
        /*
         * check for ide reset in progress
         */
-       if (hwif->reset_timeout != 0) {
+       if (hwgroup->reset_timeout != 0) {
                if (!reset_handler(hwgroup))
                        do_hwgroup_request (hwgroup);
-               restore_flags(flags);
                return;
        }
 
@@ -1330,7 +1484,6 @@ static void unexpected_intr (int irq, ide_hwgroup_t *hwgroup)
                        }
                }
        } while ((hwif = hwif->next) != hwgroup->hwif);
-       restore_flags(flags);
 }
 
 /*
@@ -1340,13 +1493,8 @@ static void ide_intr (int irq, struct pt_regs *regs)
 {
        ide_hwgroup_t  *hwgroup = irq_to_hwgroup[irq];
        ide_handler_t  *handler;
-       if (irq != hwgroup->hwif->irq) {
-#ifdef DEBUG
-               printk("ide_intr: expected ira %d, got irq %d instead\n",
-                       hwgroup->hwif->irq, irq);
-#endif
-               unexpected_intr(irq, hwgroup);
-       } else if ((handler = hwgroup->handler) != NULL) {
+
+       if (irq == hwgroup->hwif->irq && (handler = hwgroup->handler) != NULL) {
                ide_drive_t *drive = hwgroup->drive;
                hwgroup->handler = NULL;
                del_timer(&(hwgroup->timer));
@@ -1354,12 +1502,15 @@ static void ide_intr (int irq, struct pt_regs *regs)
                        sti();
                handler(drive);
        } else {
-               sti();
                unexpected_intr(irq, hwgroup);
        }
        cli();
 }
 
+/*
+ * get_info_ptr() returns the (ide_drive_t *) for a given device number.
+ * It returns NULL if the given device number does not match any present drives.
+ */
 static ide_drive_t *get_info_ptr (int i_rdev)
 {
        int             major = MAJOR(i_rdev);
@@ -1381,18 +1532,6 @@ static ide_drive_t *get_info_ptr (int i_rdev)
 }
 
 #ifdef IDE_DRIVE_CMD
-static int write_fs_long (unsigned long useraddr, long value)
-{
-       int err;
-
-       if (NULL == (long *)useraddr)
-               return -EINVAL;
-       if ((err = verify_area(VERIFY_WRITE, (long *)useraddr, sizeof(long))))
-               return err;
-       put_user((unsigned)value, (long *) useraddr);
-       return 0;
-}
-
 /*
  * This function issues a specific IDE drive command onto the
  * tail of the request queue, and waits for it to be completed.
@@ -1513,7 +1652,7 @@ static int revalidate_disk(dev_t  i_rdev)
        if ((drive = get_info_ptr(i_rdev)) == NULL)
                return -ENODEV;
 
-       major = MAJOR(i_rdev);
+       major = MAJOR(i_rdev) << 8;
        minor = drive->select.b.unit << PARTN_BITS;
        save_flags(flags);
        cli();
@@ -1540,6 +1679,18 @@ static int revalidate_disk(dev_t  i_rdev)
        return 0;
 }
 
+static int write_fs_long (unsigned long useraddr, long value)
+{
+       int err;
+
+       if (NULL == (long *)useraddr)
+               return -EINVAL;
+       if ((err = verify_area(VERIFY_WRITE, (long *)useraddr, sizeof(long))))
+               return err;
+       put_user((unsigned)value, (long *) useraddr);
+       return 0;
+}
+
 static int ide_ioctl (struct inode *inode, struct file *file,
                        unsigned int cmd, unsigned long arg)
 {
@@ -1590,6 +1741,9 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                 case HDIO_GET_UNMASKINTR:
                        return write_fs_long(arg, drive->unmask);
 
+                case HDIO_GET_DMA:
+                       return write_fs_long(arg, drive->using_dma);
+
                 case HDIO_GET_CHIPSET:
                        return write_fs_long(arg, drive->chipset);
 
@@ -1602,13 +1756,18 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        if (drive->id == NULL)
                                return -ENOMSG;
                        err = verify_area(VERIFY_WRITE, (char *)arg, sizeof(*drive->id));
-                       if (err) return err;
-                       memcpy_tofs((char *)arg, (char *)drive->id, sizeof(*drive->id));
-                       return 0;
+                       if (!err)
+                               memcpy_tofs((char *)arg, (char *)drive->id, sizeof(*drive->id));
+                       return err;
 
                        case HDIO_GET_NOWERR:
                        return write_fs_long(arg, drive->bad_wstat == BAD_R_STAT);
 
+               case HDIO_SET_DMA:
+                       if (drive->media != disk)
+                               return -EPERM;
+                       if (!drive->id || !(drive->id->capability & 1) || !HWIF(drive)->dmaproc)
+                               return -EPERM;
                case HDIO_SET_KEEPSETTINGS:
                case HDIO_SET_UNMASKINTR:
                case HDIO_SET_NOWERR:
@@ -1622,6 +1781,9 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        save_flags(flags);
                        cli();
                        switch (cmd) {
+                               case HDIO_SET_DMA:
+                                       drive->using_dma = arg;
+                                       break;
                                case HDIO_SET_KEEPSETTINGS:
                                        drive->keep_settings = arg;
                                        break;
@@ -1645,7 +1807,8 @@ static int ide_ioctl (struct inode *inode, struct file *file,
                        return 0;
 
                case HDIO_SET_MULTCOUNT:
-                       if (!suser()) return -EACCES;
+                       if (!suser())
+                               return -EACCES;
                        if (inode->i_rdev & PARTN_MASK)
                                return -EINVAL;
                        if ((drive->id != NULL) && (arg > drive->id->max_multsect))
@@ -1738,13 +1901,13 @@ static void fixstring (byte *s, const int bytecount, const int byteswap)
                *p++ = '\0';
 }
 
-static void do_identify (ide_drive_t *drive, byte cmd)
+static inline void do_identify (ide_drive_t *drive, byte cmd)
 {
        int bswap;
        struct hd_driveid *id;
        unsigned long capacity, check;
 
-       id = drive->id = ide_alloc(SECTOR_WORDS*4);
+       id = drive->id = ide_alloc (SECTOR_WORDS*4, 0);
        ide_input_data(drive, id, SECTOR_WORDS);        /* read 512 bytes of id info */
        sti();
 
@@ -1764,11 +1927,11 @@ static void do_identify (ide_drive_t *drive, byte cmd)
         */
        bswap = 1;
        if (cmd == WIN_PIDENTIFY) {
-               if ((id->model[0] == 'N' && id->model[1] == 'E')
-                || (id->model[0] == 'F' && id->model[1] == 'X')
-                || (id->model[0] == 'P' && id->model[1] == 'i'))
-                       bswap = 0;      /* NEC, Pioneer and *some* Mitsumi units */
-       }                               /* Vertos drives may still be weird */
+               if ((id->model[0] == 'N' && id->model[1] == 'E') /* NEC */
+                || (id->model[0] == 'F' && id->model[1] == 'X') /* Mitsumi */
+                || (id->model[0] == 'P' && id->model[1] == 'i'))/* Pioneer */
+                       bswap = 0;      /* Vertos drives may still be weird */
+       }
        fixstring (id->model,     sizeof(id->model),     bswap);
        fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
        fixstring (id->serial_no, sizeof(id->serial_no), bswap);
@@ -1862,7 +2025,10 @@ static void do_identify (ide_drive_t *drive, byte cmd)
                        drive->mult_req = id->max_multsect;
                if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
                        drive->special.b.set_multmode = 1;
-               printk(", MaxMult=%d", id->max_multsect);
+       }
+       if (HWIF(drive)->dmaproc != NULL) {     /* hwif supports DMA? */
+               if (!(HWIF(drive)->dmaproc(ide_dma_check, drive)))
+                       printk(", DMA");
        }
        printk("\n");
 }
@@ -1998,7 +2164,7 @@ static int do_probe (ide_drive_t *drive, byte cmd)
  * Returns:    0  no device was found
  *             1  device was found (note: drive->present might still be 0)
  */
-static byte probe_for_drive (ide_drive_t *drive)
+static inline byte probe_for_drive (ide_drive_t *drive)
 {
        if (drive->noprobe)                     /* skip probing? */
                return drive->present;
@@ -2306,6 +2472,7 @@ int ide_xlate_1024 (dev_t i_rdev, int need_offset, const char *msg)
  * 0x19 for an 8 bit type, drive 1, 0x1a for drive 2 in CMOS.  A non-zero value 
  * means we have an AT controller hard disk for that drive.
  */
+
 static void probe_cmos_for_drives (ide_hwif_t *hwif)
 {
 #ifdef __i386__
@@ -2320,11 +2487,9 @@ static void probe_cmos_for_drives (ide_hwif_t *hwif)
                ide_drive_t *drive = &hwif->drives[unit];
                if ((cmos_disks & (0xf0 >> (unit*4))) && !drive->present) {
                        drive->cyl   = drive->bios_cyl  = *(unsigned short *)BIOS;
-                       drive->head  = drive->bios_head = * (BIOS+2);
-                       drive->sect  = drive->bios_sect = * (BIOS+14);
-                       drive->wpcom = (*(unsigned short *)(BIOS+5))>>2;
+                       drive->head  = drive->bios_head = *(BIOS+2);
+                       drive->sect  = drive->bios_sect = *(BIOS+14);
                        drive->ctl   = *(BIOS+8);
-                       drive->wpcom = 0;
                        drive->media = disk;
                        drive->present = 1;
                }
@@ -2362,12 +2527,16 @@ static int init_irq (ide_hwif_t *hwif)
         * Got the irq,  now set everything else up
         */
        if ((hwgroup = irq_to_hwgroup[hwif->irq]) == NULL) {
-               hwgroup = ide_alloc(sizeof(ide_hwgroup_t));
+               hwgroup = ide_alloc (sizeof(ide_hwgroup_t), 0);
                irq_to_hwgroup[hwif->irq] = hwgroup;
                hwgroup->hwif    = hwif->next = hwif;
                hwgroup->rq      = NULL;
                hwgroup->handler = NULL;
                hwgroup->drive   = NULL;
+               hwgroup->reset_timeout = 0;
+#ifdef CONFIG_BLK_DEV_IDECD
+               hwgroup->doing_atapi_reset = 0;
+#endif /* CONFIG_BLK_DEV_IDECD */
                init_timer(&hwgroup->timer);
                hwgroup->timer.function = &timer_expiry;
                hwgroup->timer.data = (unsigned long) hwgroup;
@@ -2456,6 +2625,7 @@ static void try_to_init_dtc2278 (void)
 }
 #endif /* SUPPORT_DTC2278 */
 
+
 /*
  * This is gets invoked once during initialization, to set *everything* up
  */
@@ -2463,7 +2633,7 @@ unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
 {
        int h;
 
-       init_mem_start = (mem_start + 3uL) & ~3uL;      /* for ide_alloc() */
+       ide_mem_start = mem_start;      /* for ide_alloc () */
        init_ide_data ();
        /*
         * First, we determine what hardware is present
@@ -2472,6 +2642,20 @@ unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
        if (probe_dtc2278)
                try_to_init_dtc2278();
 #endif /* SUPPORT_DTC2278 */
+#ifdef CONFIG_PCI
+       /*
+        * Look for pci disk interfaces.
+        */
+       if (pcibios_present()) {
+#ifdef CONFIG_BLK_DEV_TRITON
+               ide_init_triton (ide_hwifs);
+#endif /* CONFIG_BLK_DEV_TRITON */
+       }
+#endif /* CONFIG_PCI */
+
+       /*
+        * Probe for drives in the usual way.. CMOS/BIOS, then poke at ports
+        */
        for (h = 0; h < MAX_HWIFS; ++h) {
                ide_hwif_t *hwif = &ide_hwifs[h];
                if (!hwif->noprobe) {
@@ -2491,6 +2675,7 @@ unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
                        if (hwif->irq == HD_IRQ && hwif->io_base != HD_DATA) {
                                printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", hwif->name);
                                hwif->present = 0;
+B
                        }
 #endif /* CONFIG_BLK_DEV_HD */
                }
@@ -2535,7 +2720,7 @@ unsigned long ide_init (unsigned long mem_start, unsigned long mem_end)
                        hwif->present = 1;      /* success */
                }
        }
-       mem_start = init_mem_start;
-       init_mem_start = 0uL;   /* prevent further use of ide_alloc() */
+       mem_start = ide_mem_start;
+       ide_mem_start = 0uL;    /* prevent further use of ide_alloc() */
        return mem_start;
 }
index bff63d62e52fc6d3a5c377c74fa767faf5afa37f..f22803bf62e0e0d819c14f572257f7b4acb0a0fc 100644 (file)
@@ -21,7 +21,7 @@
 #undef REALLY_SLOW_IO                  /* most systems can safely undef this */
 #include <asm/io.h>
 
-#define        REALLY_FAST_IO                  /* define if ide ports are perfect */
+#undef         REALLY_FAST_IO                  /* define if ide ports are perfect */
 #define INITIAL_MULT_COUNT     0       /* off=0; on=2,4,8,16,32, etc.. */
 
 #ifndef DISK_RECOVERY_TIME             /* off=0; on=access_delay_time */
@@ -121,14 +121,6 @@ typedef unsigned char      byte;   /* used everywhere */
 
 #ifdef CONFIG_BLK_DEV_IDECD
 
-struct packet_command {
-  char *buffer;
-  int buflen;
-  int stat;
-  unsigned char c[12];
-};
-
-
 struct atapi_request_sense {
   unsigned char error_code : 7;
   unsigned char valid      : 1;
@@ -146,6 +138,14 @@ struct atapi_request_sense {
   byte sense_key_specific[3];
 };
 
+struct packet_command {
+  char *buffer;
+  int buflen;
+  int stat;
+  struct atapi_request_sense *sense_data;
+  unsigned char c[12];
+};
+
 /* Space to hold the disk TOC. */
 
 #define MAX_TRACKS 99
@@ -165,6 +165,9 @@ struct atapi_toc_entry {
 };
 
 struct atapi_toc {
+  int    last_session_lba;
+  int    xa_flag;
+  unsigned capacity;
   struct atapi_toc_header hdr;
   struct atapi_toc_entry  ent[MAX_TRACKS+1];  /* One extra for the leadout. */
 };
@@ -230,14 +233,13 @@ typedef struct ide_drive_s {
        unsigned vlb_32bit      : 1;    /* use 32bit in/out for data */
        unsigned vlb_sync       : 1;    /* needed for some 32bit chip sets */
        unsigned removeable     : 1;    /* 1 if need to do check_media_change */
-       unsigned dma_capable    : 1;    /* for Intel Triton chipset, others.. */
+       unsigned using_dma      : 1;    /* disk is using dma for read/write */
+       unsigned unmask         : 1;    /* flag: okay to unmask other irqs */
+       media_t         media;          /* disk, cdrom, tape */
        select_t        select;         /* basic drive/head select reg value */
-       byte            unmask;         /* flag: okay to unmask other irqs */
        void            *hwif;          /* actually (ide_hwif_t *) */
        byte            ctl;            /* "normal" value for IDE_CONTROL_REG */
        byte            ready_stat;     /* min status value for drive ready */
-       byte            wpcom;          /* ignored by all IDE drives */
-       media_t         media;          /* disk, cdrom, tape */
        byte            mult_count;     /* current multiple sector setting */
        byte            mult_req;       /* requested multiple sector setting */
        byte            chipset;        /* interface chipset access method */
@@ -259,22 +261,38 @@ typedef struct ide_drive_s {
 #endif /* CONFIG_BLK_DEV_IDECD */
        } ide_drive_t;
 
+/*
+ * An ide_dmaproc_t() initiates/aborts DMA read/write operations on a drive.
+ *
+ * The caller is assumed to have selected the drive and programmed the drive's
+ * sector address using CHS or LBA.  All that remains is to prepare for DMA
+ * and then issue the actual read/write DMA/PIO command to the drive.
+ *
+ * Returns 0 if all went well.
+ * Returns 1 if DMA read/write could not be started, in which case the caller
+ * should either try again later, or revert to PIO for the current request.
+ */
+typedef enum {ide_dma_read = 0, ide_dma_write = 1, ide_dma_abort = 2, ide_dma_check = 3} ide_dma_action_t;
+typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
+
 typedef struct hwif_s {
        struct hwif_s   *next;          /* for linked-list in ide_hwgroup_t */
        void            *hwgroup;       /* actually (ide_hwgroup_t *) */
        unsigned short  io_base;        /* base io port addr */
        unsigned short  ctl_port;       /* usually io_base+0x206 */
-       ide_drive_t             drives[MAX_DRIVES];     /* drive info */
+       ide_drive_t     drives[MAX_DRIVES];     /* drive info */
        struct gendisk  *gd;            /* gendisk structure */
+       ide_dmaproc_t   *dmaproc;       /* dma read/write/abort routine */
+       unsigned long   *dmatable;      /* dma physical region descriptor table */
+       unsigned short  dma_base;       /* base addr for dma ports (triton) */
        byte            irq;            /* our irq number */
        byte            major;          /* our major number */
        byte            drivecount;     /* how many drives attached */
        char            name[5];        /* name of interface, eg. "ide0" */
        unsigned        noprobe : 1;    /* don't probe for this interface */
        unsigned        present : 1;    /* this interface exists */
-       unsigned long   reset_timeout;  /* timeout value during ide resets */
 #if (DISK_RECOVERY_TIME > 0)
-       unsigned long   last_timer;     /* time when previous rq was done */
+       unsigned long   last_time     /* time when previous rq was done */
 #endif
 #ifdef CONFIG_BLK_DEV_IDECD
        struct request request_sense_request;   /* from ide-cd.c */
@@ -283,7 +301,7 @@ typedef struct hwif_s {
        } ide_hwif_t;
 
 /*
- *  our internal interrupt handler type
+ *  internal ide interrupt handler type
  */
 typedef void (ide_handler_t)(ide_drive_t *);
 
@@ -294,6 +312,10 @@ typedef struct hwgroup_s {
        struct request          *rq;    /* current request */
        struct timer_list       timer;  /* failsafe timer */
        struct request          wrq;    /* local copy of current write rq */
+       unsigned long   reset_timeout;  /* timeout value during ide resets */
+#ifdef CONFIG_BLK_DEV_IDECD
+       int                     doing_atapi_reset;
+#endif /* CONFIG_BLK_DEV_IDECD */
        } ide_hwgroup_t;
 
 /*
@@ -363,6 +385,23 @@ int ide_wait_stat (ide_drive_t *drive, byte good, byte bad, unsigned long timeou
  */
 int ide_xlate_1024(dev_t, int, const char *);
 
+/*
+ * Start a reset operation for an IDE interface.
+ * Returns 0 if the reset operation is still in progress,
+ *  in which case the drive MUST return, to await completion.
+ * Returns 1 if the reset is complete (success or failure).
+ */
+int ide_do_reset (ide_drive_t *);
+
+/*
+ * ide_alloc(): memory allocation for use *only* during driver initialization.
+ * If "within_area" is non-zero, the memory will be allocated such that
+ * it lies entirely within a "within_area" sized area (eg. 4096).  This is
+ * needed for DMA stuff.  "within_area" must be a power of two (not validated).
+ * All allocations are longword aligned.
+ */
+void *ide_alloc (unsigned long bytecount, unsigned long within_area);
+
 #ifdef CONFIG_BLK_DEV_IDECD
 /*
  * These are routines in ide-cd.c invoked from ide.c
@@ -374,3 +413,8 @@ int ide_cdrom_open (struct inode *, struct file *, ide_drive_t *);
 void ide_cdrom_release (struct inode *, struct file *, ide_drive_t *);
 void ide_cdrom_setup (ide_drive_t *);
 #endif /* CONFIG_BLK_DEV_IDECD */
+
+#ifdef CONFIG_BLK_DEV_TRITON
+void ide_init_triton (ide_hwif_t *);
+#endif /* CONFIG_BLK_DEV_TRITON */
+
index c22efad2b03057b8f96178bf2ae34215b966776d..c844aed9daa7ce5fdc0a66c1279408d7a0377cd2 100644 (file)
@@ -1,10 +1,12 @@
-/*     $Id: optcd.c,v 1.7 1995/06/28 20:20:13 root Exp $
+/*     $Id: optcd.c,v 1.3 1995/08/24 19:54:27 root Exp root $
        linux/drivers/block/optcd.c - Optics Storage 8000 AT CDROM driver
 
        Copyright (C) 1995 Leo Spiekman (spiekman@dutette.et.tudelft.nl)
 
        Based on Aztech CD268 CDROM driver by Werner Zimmermann and preworks
-       by Eberhard Moenkeberg.
+       by Eberhard Moenkeberg (emoenke@gwdg.de). ISP16 detection and
+       configuration by Eric van der Maarel (maarel@marin.nl), with some data
+       communicated by Vadim V. Model (vadim@rbrf.msk.su).
 
        This program is free software; you can redistribute it and/or modify
        it under the terms of the GNU General Public License as published by
                                should go into its own driver. The driver now
                                has its own major nr.
                                Disk change detection now seems to work, too.
+                               This version became part of the standard
+                               kernel as of version 1.3.7
+       24-9-95         v0.4    Re-inserted ISP-16 interface code which I
+                               copied from sjcd.c, with a few changes.
+                               Updated README.optcd. Submitted for
+                               inclusion in 1.3.21
 */
 
 #include <linux/major.h>
 #define optcd_port optcd       /* Needed for the modutils. */
 # include <linux/optcd.h>
 
+
+/* Some (Media)Magic */
+/* define types of drive the interface on an ISP16 card may be looking at */
+#define ISP16_DRIVE_X 0x00
+#define ISP16_SONY  0x02
+#define ISP16_PANASONIC0 0x02
+#define ISP16_SANYO0 0x02
+#define ISP16_MITSUMI  0x04
+#define ISP16_PANASONIC1 0x06
+#define ISP16_SANYO1 0x06
+#define ISP16_DRIVE_NOT_USED 0x08  /* not used */
+#define ISP16_DRIVE_SET_MASK 0xF1  /* don't change 0-bit or 4-7-bits*/
+/* ...for port */
+#define ISP16_DRIVE_SET_PORT 0xF8D
+/* set io parameters */
+#define ISP16_BASE_340  0x00
+#define ISP16_BASE_330  0x40
+#define ISP16_BASE_360  0x80
+#define ISP16_BASE_320  0xC0
+#define ISP16_IRQ_X  0x00
+#define ISP16_IRQ_5  0x04  /* shouldn't be used due to soundcard conflicts */
+#define ISP16_IRQ_7  0x08  /* shouldn't be used due to soundcard conflicts */
+#define ISP16_IRQ_3  0x0C
+#define ISP16_IRQ_9  0x10
+#define ISP16_IRQ_10  0x14
+#define ISP16_IRQ_11  0x18
+#define ISP16_DMA_X  0x03
+#define ISP16_DMA_3  0x00
+#define ISP16_DMA_5  0x00
+#define ISP16_DMA_6  0x01
+#define ISP16_DMA_7  0x02
+#define ISP16_IO_SET_MASK  0x20  /* don't change 5-bit */
+/* ...for port */
+#define ISP16_IO_SET_PORT  0xF8E
+/* enable the drive */
+#define ISP16_NO_IDE__ENABLE_CDROM_PORT  0xF90  /* ISP16 without IDE interface */
+#define ISP16_IDE__ENABLE_CDROM_PORT  0xF91  /* ISP16 with IDE interface */
+#define ISP16_ENABLE_CDROM  0x80  /* seven bit */
+
+/* the magic stuff */
+#define ISP16_CTRL_PORT  0xF8F
+#define ISP16_NO_IDE__CTRL  0xE2  /* ISP16 without IDE interface */
+#define ISP16_IDE__CTRL  0xE3  /* ISP16 with IDE interface */
+
+static short isp16_detect(void);
+static short isp16_no_ide__detect(void);
+static short isp16_with_ide__detect(void);
+static short isp16_config( int base, u_char drive_type, int irq, int dma );
+static short isp16_type; /* dependent on type of interface card */
+static u_char isp16_ctrl;
+static u_short isp16_enable_cdrom_port;
+
+
 static short optcd_port = OPTCD_PORTBASE;
 
 /* Read current status/data availability flags */
@@ -1363,6 +1424,29 @@ int init_module(void) {
                        optcd_port);
                RETURN_EIO;
        }
+
+       if (!check_region(ISP16_DRIVE_SET_PORT, 5)) {
+       /* If someone else has'nt already reserved these ports,
+          probe for an ISP16 interface card, and enable SONY mode
+          with no interrupts and no DMA. (As far as I know, all optics
+          drives come with a SONY interface.) */
+  if ( (isp16_type=isp16_detect()) < 0 )
+    printk( "No ISP16 cdrom interface found.\n" );
+  else {
+    u_char expected_drive;
+
+    printk( "ISP16 cdrom interface (%s optional IDE) detected.\n",
+      (isp16_type==2)?"with":"without" );
+
+    expected_drive = (isp16_type?ISP16_SANYO1:ISP16_SANYO0);
+
+    if ( isp16_config( optcd_port, ISP16_SONY, 0, 0 ) < 0 ) {
+      printk( "ISP16 cdrom interface has not been properly configured.\n" );
+      return(mem_start);
+    }
+  }
+       }
+
        if (!optResetDrive()) {
                printk("optcd: drive at 0x%x not ready\n", optcd_port);
                RETURN_EIO;
@@ -1406,3 +1490,191 @@ void cleanup_module(void) {
        printk("optcd: module released.\n");
 }
 #endif MODULE
+
+
+/*
+ * -- ISP16 detection and configuration
+ *
+ *    Copyright (c) 1995, Eric van der Maarel <maarel@marin.nl>
+ *
+ *    Version 0.5
+ *
+ *    Detect cdrom interface on ISP16 soundcard.
+ *    Configure cdrom interface.
+ *
+ *    Algorithm for the card with no IDE support option taken
+ *    from the CDSETUP.SYS driver for MSDOS,
+ *    by OPTi Computers, version 2.03.
+ *    Algorithm for the IDE supporting ISP16 as communicated
+ *    to me by Vadim Model and Leo Spiekman.
+ *
+ *    Use, modifification or redistribution of this software is
+ *    allowed under the terms of the GPL.
+ *
+ */
+
+
+#define ISP16_IN(p) (outb(isp16_ctrl,ISP16_CTRL_PORT), inb(p))
+#define ISP16_OUT(p,b) (outb(isp16_ctrl,ISP16_CTRL_PORT), outb(b,p))
+
+static short
+isp16_detect(void)
+{
+
+  if ( !( isp16_with_ide__detect() < 0 ) )
+    return(2);
+  else
+    return( isp16_no_ide__detect() );
+}
+
+static short
+isp16_no_ide__detect(void)
+{
+  u_char ctrl;
+  u_char enable_cdrom;
+  u_char io;
+  short i = -1;
+
+  isp16_ctrl = ISP16_NO_IDE__CTRL;
+  isp16_enable_cdrom_port = ISP16_NO_IDE__ENABLE_CDROM_PORT;
+
+  /* read' and write' are a special read and write, respectively */
+
+  /* read' ISP16_CTRL_PORT, clear last two bits and write' back the result */
+  ctrl = ISP16_IN( ISP16_CTRL_PORT ) & 0xFC;
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+
+  /* read' 3,4 and 5-bit from the cdrom enable port */
+  enable_cdrom = ISP16_IN( ISP16_NO_IDE__ENABLE_CDROM_PORT ) & 0x38;
+
+  if ( !(enable_cdrom & 0x20) ) {  /* 5-bit not set */
+    /* read' last 2 bits of ISP16_IO_SET_PORT */
+    io = ISP16_IN( ISP16_IO_SET_PORT ) & 0x03;
+    if ( ((io&0x01)<<1) == (io&0x02) ) {  /* bits are the same */
+      if ( io == 0 ) {  /* ...the same and 0 */
+        i = 0;
+        enable_cdrom |= 0x20;
+      }
+      else {  /* ...the same and 1 */  /* my card, first time 'round */
+        i = 1;
+        enable_cdrom |= 0x28;
+      }
+      ISP16_OUT( ISP16_NO_IDE__ENABLE_CDROM_PORT, enable_cdrom );
+    }
+    else {  /* bits are not the same */
+      ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+      return(i); /* -> not detected: possibly incorrect conclusion */
+    }
+  }
+  else if ( enable_cdrom == 0x20 )
+    i = 0;
+  else if ( enable_cdrom == 0x28 )  /* my card, already initialised */
+    i = 1;
+
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+
+  return(i);
+}
+
+static short
+isp16_with_ide__detect(void)
+{
+  u_char ctrl;
+  u_char tmp;
+
+  isp16_ctrl = ISP16_IDE__CTRL;
+  isp16_enable_cdrom_port = ISP16_IDE__ENABLE_CDROM_PORT;
+
+  /* read' and write' are a special read and write, respectively */
+
+  /* read' ISP16_CTRL_PORT and save */
+  ctrl = ISP16_IN( ISP16_CTRL_PORT );
+
+  /* write' zero to the ctrl port and get response */
+  ISP16_OUT( ISP16_CTRL_PORT, 0 );
+  tmp = ISP16_IN( ISP16_CTRL_PORT );
+
+  if ( tmp != 2 )  /* isp16 with ide option not detected */
+    return(-1);
+
+  /* restore ctrl port value */
+  ISP16_OUT( ISP16_CTRL_PORT, ctrl );
+  
+  return(2);
+}
+
+static short
+isp16_config( int base, u_char drive_type, int irq, int dma )
+{
+  u_char base_code;
+  u_char irq_code;
+  u_char dma_code;
+  u_char i;
+
+  if ( (drive_type == ISP16_MITSUMI) && (dma != 0) )
+    printk( "Mitsumi cdrom drive has no dma support.\n" );
+
+  switch (base) {
+  case 0x340: base_code = ISP16_BASE_340; break;
+  case 0x330: base_code = ISP16_BASE_330; break;
+  case 0x360: base_code = ISP16_BASE_360; break;
+  case 0x320: base_code = ISP16_BASE_320; break;
+  default:
+    printk( "Base address 0x%03X not supported by cdrom interface on ISP16.\n", base );
+    return(-1);
+  }
+  switch (irq) {
+  case 0: irq_code = ISP16_IRQ_X; break; /* disable irq */
+  case 5: irq_code = ISP16_IRQ_5;
+          printk( "Irq 5 shouldn't be used by cdrom interface on ISP16,"
+            " due to possible conflicts with the soundcard.\n");
+          break;
+  case 7: irq_code = ISP16_IRQ_7;
+          printk( "Irq 7 shouldn't be used by cdrom interface on ISP16,"
+            " due to possible conflicts with the soundcard.\n");
+          break;
+  case 3: irq_code = ISP16_IRQ_3; break;
+  case 9: irq_code = ISP16_IRQ_9; break;
+  case 10: irq_code = ISP16_IRQ_10; break;
+  case 11: irq_code = ISP16_IRQ_11; break;
+  default:
+    printk( "Irq %d not supported by cdrom interface on ISP16.\n", irq );
+    return(-1);
+  }
+  switch (dma) {
+  case 0: dma_code = ISP16_DMA_X; break;  /* disable dma */
+  case 1: printk( "Dma 1 cannot be used by cdrom interface on ISP16,"
+            " due to conflict with the soundcard.\n");
+          return(-1); break;
+  case 3: dma_code = ISP16_DMA_3; break;
+  case 5: dma_code = ISP16_DMA_5; break;
+  case 6: dma_code = ISP16_DMA_6; break;
+  case 7: dma_code = ISP16_DMA_7; break;
+  default:
+    printk( "Dma %d not supported by cdrom interface on ISP16.\n", dma );
+    return(-1);
+  }
+
+  if ( drive_type != ISP16_SONY && drive_type != ISP16_PANASONIC0 &&
+    drive_type != ISP16_PANASONIC1 && drive_type != ISP16_SANYO0 &&
+    drive_type != ISP16_SANYO1 && drive_type != ISP16_MITSUMI &&
+    drive_type != ISP16_DRIVE_X ) {
+    printk( "Drive type (code 0x%02X) not supported by cdrom"
+     " interface on ISP16.\n", drive_type );
+    return(-1);
+  }
+
+  /* set type of interface */
+  i = ISP16_IN(ISP16_DRIVE_SET_PORT) & ISP16_DRIVE_SET_MASK;  /* clear some bits */
+  ISP16_OUT( ISP16_DRIVE_SET_PORT, i|drive_type );
+
+  /* enable cdrom on interface with ide support */
+  if ( isp16_type > 1 )
+    ISP16_OUT( isp16_enable_cdrom_port, ISP16_ENABLE_CDROM );
+
+  /* set base address, irq and dma */
+  i = ISP16_IN(ISP16_IO_SET_PORT) & ISP16_IO_SET_MASK;  /* keep some bits */
+  ISP16_OUT( ISP16_IO_SET_PORT, i|base_code|irq_code|dma_code );
+
+  return(0);
+}
diff --git a/drivers/block/triton.c b/drivers/block/triton.c
new file mode 100644 (file)
index 0000000..75cbd21
--- /dev/null
@@ -0,0 +1,352 @@
+/*
+ *  linux/drivers/block/triton.c       Version 1.00  Aug 26, 1995
+ *
+ *  Copyright (c) 1995  Mark Lord
+ *  May be copied or modified under the terms of the GNU General Public License
+ */
+
+/*
+ * This module provides support for the Bus Master IDE DMA function
+ * of the Intel PCI Triton chipset (82371FB).
+ *
+ * DMA is currently supported only for hard disk drives (not cdroms).
+ *
+ * Support for cdroms will likely be added at a later date,
+ * after broader experience has been obtained with hard disks.
+ *
+ * Up to four drives may be enabled for DMA, and the Triton chipset will
+ * (hopefully) arbitrate the PCI bus among them.  Note that the 82371FB chip
+ * provides a single "line buffer" for the BM IDE function, so performance of
+ * multiple (two) drives doing DMA simultaneously will suffer somewhat,
+ * as they contest for that resource bottleneck.  This is handled transparently
+ * inside the 82371FB chip.
+ *
+ * By default, DMA support is prepared for use, but is currently enabled only
+ * for drives which support multi-word DMA mode2 (mword2), or which are
+ * recognized as "good" (see table below).  Drives with only mode0 or mode1
+ * (single or multi) DMA should also work with this chipset/driver (eg. MC2112A)
+ * but are not enabled by default.  Use "hdparm -i" to view supported modes
+ * for a given drive.
+ *
+ * The hdparm-2.4 (or later) utility can be used for manually enabling/disabling
+ * DMA support, but must be (re-)compiled against this kernel version or later.
+ *
+ * To enable DMA, use "hdparm -d1 /dev/hd?" on a per-drive basis after booting.
+ * If problems arise, ide.c will disable DMA operation after a few retries.
+ * This error recovery mechanism works and has been extremely well exercised.
+ *
+ * IDE drives, depending on their vintage, may support several different modes
+ * of DMA operation.  The boot-time modes are indicated with a "*" in
+ * the "hdparm -i" listing, and can be changed with *knowledgeable* use of
+ * the "hdparm -X" feature.  There is seldom a need to do this, as drives
+ * normally power-up with their "best" PIO/DMA modes enabled.
+ *
+ * Testing was done with an ASUS P55TP4XE/100 system and the following drives:
+ *
+ *   Quantum Fireball 1080A (1Gig w/83kB buffer), DMA mode2, PIO mode4.
+ *     - DMA mode2 works fine (7.4MB/sec), despite the tiny on-drive buffer.
+ *     - This drive also does PIO mode4, slightly slower than DMA mode2.
+ *
+ *   Micropolis MC2112A (1Gig w/512kB buffer), drive pre-dates EIDE, ATA2.
+ *     - DMA works fine (2.2MB/sec), probably due to the large on-drive buffer.
+ *     - This older drive can also be tweaked for fastPIO (3,7MB/sec) by using
+ *       maximum clock settings (5,4) and setting all flags except prefetch.
+ *
+ *   Western Digital AC31000H (1Gig w/128kB buffer), DMA mode1, PIO mode3.
+ *     - DMA does not work reliably.  The drive appears to be somewhat tardy
+ *       in deasserting DMARQ at the end of a sector.  This is evident in
+ *       the observation that WRITEs work most of the time, depending on
+ *       cache-buffer occupancy, but multi-sector reads seldom work.
+ *
+ * Drives like the AC31000H could likely be made to work if all DMA were done
+ * one sector at a time, but that would likely negate any advantage over PIO.
+ *
+ * If you have any drive models add, email your results to:  mlord@bnr.ca
+ * Keep an eye on your /var/adm/messages for "DMA disabled" messages.
+ */
+#define _TRITON_C
+#include <linux/config.h>
+#ifndef CONFIG_BLK_DEV_TRITON
+#define CONFIG_BLK_DEV_TRITON y
+#endif
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <asm/io.h>
+
+#include "ide.h"
+
+/*
+ * good_dma_drives() lists the model names (from "hdparm -i")
+ * of drives which do not support mword2 DMA but which are
+ * known to work fine with this interface under Linux.
+ */
+const char *good_dma_drives[] = {"Micropolis 2112A"};
+
+/*
+ * Our Physical Region Descriptor (PRD) table should be large enough
+ * to handle the biggest I/O request we are likely to see.  Since requests
+ * can have no more than 256 sectors, and since the typical blocksize is
+ * two sectors, we can get by with a limit of 128 entries here for the
+ * usual worst case.  Most requests seem to include some contiguous blocks,
+ * further reducing the number of table entries required.
+ *
+ * Note that the driver reverts to PIO mode for individual requests that exceed
+ * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
+ * 100% of all crazy scenarios here is not necessary.
+ */
+#define PRD_ENTRIES    128     /* max memory area count per DMA */
+
+/*
+ * dma_intr() is the handler for disk read/write DMA interrupts
+ */
+static void dma_intr (ide_drive_t *drive)
+{
+       byte stat, dma_stat;
+       int i;
+       struct request *rq = HWGROUP(drive)->rq;
+       unsigned short dma_base = HWIF(drive)->dma_base;
+
+       dma_stat = inb(dma_base+2);     /* get DMA status */
+       outb(inb(dma_base)&~1, dma_base);       /* stop DMA operation */
+       stat = GET_STAT();
+       if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+               if ((dma_stat & 7) == 4) {      /* verify good DMA status */
+                       rq = HWGROUP(drive)->rq;
+                       for (i = rq->nr_sectors; i > 0;) {
+                               i -= rq->current_nr_sectors;
+                               ide_end_request(1, HWGROUP(drive));
+                       }
+                       IDE_DO_REQUEST;
+                       return;
+               }
+               printk("%s: bad DMA status: 0x%02x\n", drive->name, dma_stat);
+       }
+       sti();
+       if (!ide_error(drive, "dma_intr", stat))
+               IDE_DO_REQUEST;
+}
+
+/*
+ * build_dmatable() prepares a dma request.
+ * Returns 0 if all went okay, returns 1 otherwise.
+ */
+static int build_dmatable (ide_drive_t *drive)
+{
+       struct request *rq = HWGROUP(drive)->rq;
+       struct buffer_head *bh = rq->bh;
+       unsigned long size, addr, *table = HWIF(drive)->dmatable;
+       unsigned int count = 0;
+
+       do {
+               /*
+                * Determine addr and size of next buffer area.  We assume that
+                * individual virtual buffers are always composed linearly in
+                * physical memory.  For example, we assume that any 8kB buffer
+                * is always composed of two adjacent physical 4kB pages rather
+                * than two possibly non-adjacent physical 4kB pages.
+                */
+               if (bh == NULL) {  /* paging requests have (rq->bh == NULL) */
+                       addr = virt_to_bus (rq->buffer);
+                       size = rq->nr_sectors << 9;
+               } else {
+                       /* group sequential buffers into one large buffer */
+                       addr = virt_to_bus (bh->b_data);
+                       size = bh->b_size;
+                       while ((bh = bh->b_reqnext) != NULL) {
+                               if ((addr + size) != virt_to_bus (bh->b_data))
+                                       break;
+                               size += bh->b_size;
+                       }
+               }
+
+               /*
+                * Fill in the dma table, without crossing any 64kB boundaries.
+                * We assume 16-bit alignment of all blocks.
+                */
+               while (size) {
+                       if (++count >= PRD_ENTRIES) {
+                               printk("%s: DMA table too small\n", drive->name);
+                               return 1; /* revert to PIO for this request */
+                       } else {
+                               unsigned long bcount = 0x10000 - (addr & 0xffff);
+                               if (bcount > size)
+                                       bcount = size;
+                               *table++ = addr;
+                               *table++ = bcount;
+                               addr += bcount;
+                               size -= bcount;
+                       }
+               }
+       } while (bh != NULL);
+       if (count) {
+               *--table |= 0x80000000; /* set End-Of-Table (EOT) bit */
+               return 0;
+       }
+       printk("%s: empty DMA table?\n", drive->name);
+       return 1;       /* let the PIO routines handle this weirdness */
+}
+
+/*
+ * triton_dmaproc() initiates/aborts DMA read/write operations on a drive.
+ *
+ * The caller is assumed to have selected the drive and programmed the drive's
+ * sector address using CHS or LBA.  All that remains is to prepare for DMA
+ * and then issue the actual read/write DMA/PIO command to the drive.
+ *
+ * Returns 0 if all went well.
+ * Returns 1 if DMA read/write could not be started, in which case
+ * the caller should revert to PIO for the current request.
+ */
+static int triton_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+       const char **list;
+       unsigned long dma_base = HWIF(drive)->dma_base;
+
+       if (func == ide_dma_abort) {
+               outb(inb(dma_base)&~1, dma_base);       /* stop DMA */
+               return 0;
+       }
+       if (func == ide_dma_check) {
+               struct hd_driveid *id = drive->id;
+               if (id && (id->capability & 1)) {
+                       /* Enable DMA on any drive that supports mword2 DMA */
+                       if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) {
+                               drive->using_dma = 1;
+                               return 0;               /* DMA enabled */
+                       }
+                       /* Consult the list of known "good" drives */
+                       list = good_dma_drives;
+                       while (*list) {
+                               if (!strcmp(*list++,id->model)) {
+                                       drive->using_dma = 1;
+                                       return 0;       /* DMA enabled */
+                               }
+                       }
+               }
+               return 1;       /* DMA not enabled */
+       }
+       if (build_dmatable (drive))
+               return 1;
+       outl(virt_to_bus (HWIF(drive)->dmatable), dma_base + 4); /* PRD table */
+       outb((!func) << 3, dma_base);                   /* specify r/w */
+       outb(0x26, dma_base+2);                         /* clear status bits */
+       ide_set_handler (drive, &dma_intr);             /* issue cmd to drive */
+       OUT_BYTE(func ? WIN_WRITEDMA : WIN_READDMA, IDE_COMMAND_REG);
+       outb(inb(dma_base)|1, dma_base);                        /* begin DMA */
+       return 0;
+}
+
+/*
+ * print_triton_drive_flags() displays the currently programmed options
+ * in the Triton chipset for a given drive.
+ *
+ *     If fastDMA  is "no", then slow ISA timings are used for DMA data xfers.
+ *     If fastPIO  is "no", then slow ISA timings are used for PIO data xfers.
+ *     If IORDY    is "no", then IORDY is assumed to always be asserted.
+ *     If PreFetch is "no", then data pre-fetch/post are not used.
+ *
+ * When "fastPIO" and/or "fastDMA" are "yes", then faster PCI timings and
+ * back-to-back 16-bit data transfers are enabled, using the sample_CLKs
+ * and recovery_CLKs (PCI clock cycles) timing parameters for that interface.
+ */
+static void print_triton_drive_flags (unsigned int unit, byte flags)
+{
+       printk("         %s ", unit ? "slave :" : "master:");
+       printk( "fastDMA=%s",   (flags&9)       ? "on " : "off");
+       printk(" PreFetch=%s",  (flags&4)       ? "on " : "off");
+       printk(" IORDY=%s",     (flags&2)       ? "on " : "off");
+       printk(" fastPIO=%s\n", ((flags&9)==1)  ? "on " : "off");
+}
+
+/*
+ * ide_init_triton() uses the PCI BIOS to scan for a Triton i82371FB chip,
+ * and prepares the IDE driver for DMA operation if one is found.
+ * This routine is called from ide.c during driver initialization.
+ */
+void ide_init_triton (ide_hwif_t  hwifs[])
+{
+       int rc = 0, h;
+       unsigned short bmiba, pcicmd;
+       unsigned int timings;
+       unsigned char bus, fn;
+
+       if (pcibios_find_device (PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371, 0, &bus, &fn))
+               goto quit;
+       ++fn;   /* IDE is second function on this chip */
+
+       /*
+        * See if IDE and BM-DMA features are enabled:
+        */
+       if ((rc = pcibios_read_config_word(bus, fn, 0x04, &pcicmd)))
+               goto quit;
+       if ((pcicmd & 5) != 5) {
+               if ((pcicmd & 1) == 0)
+                       printk("ide: Triton IDE ports are not enabled\n");
+               else
+                       printk("ide: Triton BM-DMA feature is not enabled\n");
+               goto quit;
+       }
+#if 0
+       (void) pcibios_write_config_word(bus, fn, 0x42, 0x8037); /* for my MC2112A */
+#endif
+       /*
+        * See if ide port(s) are enabled
+        */
+       if ((rc = pcibios_read_config_dword(bus, fn, 0x40, &timings)))
+               goto quit;
+       if (!(timings & 0x80008000)) {
+               printk("ide: Triton IDE ports are not enabled\n");
+               goto quit;
+       }
+       printk("ide: Triton BM-IDE on PCI bus %d function %d\n", bus, fn);
+
+       /*
+        * Get the bmiba base address
+        */
+       if ((rc = pcibios_read_config_word(bus, fn, 0x20, &bmiba)))
+               goto quit;
+       bmiba &= 0xfff0;        /* extract port base address */
+
+       /*
+        * Save the dma_base port addr for each interface
+        */
+       for (h = 0; h < MAX_HWIFS; ++h) {
+               ide_hwif_t *hwif = &hwifs[h];
+               unsigned short base, time;
+               if (hwif->io_base == 0x1f0 && (timings & 0x8000)) {
+                       time = timings & 0xffff;
+                       base = bmiba;
+               } else if (hwif->io_base == 0x170 && (timings & 0x80000000)) {
+                       time = timings >> 16;
+                       base = bmiba + 8;
+               } else
+                       continue;
+               printk("    %s: BusMaster DMA at 0x%04x-0x%04x", hwif->name, base, base+5);
+               if (check_region(base, 6)) {
+                       printk(" -- ERROR, PORTS ALREADY IN USE");
+               } else {
+                       unsigned long *table;
+                       request_region(base, 8, hwif->name);
+                       hwif->dma_base  = base;
+                       table = ide_alloc(2 * PRD_ENTRIES * sizeof(long), 4096);
+                       hwif->dmatable = table;
+                       outl((unsigned long) table, base + 4);
+                       hwif->dmaproc  = &triton_dmaproc;
+               }
+               printk("\n    %s timing: (0x%04x) sample_CLKs=%d, recovery_CLKs=%d\n",
+                hwif->name, time, ((~time>>12)&3)+2, ((~time>>8)&3)+1);
+               print_triton_drive_flags (0, time & 0xf);
+               print_triton_drive_flags (1, (time >> 4) & 0xf);
+       }
+
+quit: if (rc) printk("ide: pcibios access failed - %s\n", pcibios_strerror(rc));
+}
+
index d42bafab66babf0c9e0e69f6cb3976d5a6f74bf1..89047db2137ad8ad813f3216427540c57e1e2c8f 100644 (file)
@@ -33,7 +33,7 @@
 
 /* the BIOS manuals say there can be up to 4 lpt devices
  * but I have not seen a board where the 4th address is listed
- * if you have different hardware change the table below 
+ * if you have different hardware change the table below
  * please let me know if you have different equipment
  * if you have more than 3 printers, remember to increase LP_NO
  */
@@ -41,7 +41,7 @@ struct lp_struct lp_table[] = {
        { 0x3bc, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
        { 0x378, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
        { 0x278, 0, 0, LP_INIT_CHAR, LP_INIT_TIME, LP_INIT_WAIT, NULL, NULL, 0, 0, 0, {0} },
-}; 
+};
 #define LP_NO 3
 
 /* Test if printer is ready (and optionally has no error conditions) */
@@ -51,9 +51,9 @@ struct lp_struct lp_table[] = {
   ((LP_F(minor) & LP_CAREFUL) ? _LP_CAREFUL_READY(status) : 1)
 #define _LP_CAREFUL_READY(status) \
    (status & (LP_PBUSY|LP_POUTPA|LP_PSELECD|LP_PERRORP)) == \
-      (LP_PBUSY|LP_PSELECD|LP_PERRORP) 
+      (LP_PBUSY|LP_PSELECD|LP_PERRORP)
 
-/* 
+/*
  * All my debugging code assumes that you debug with only one printer at
  * a time. RWWH
  * Debug info moved into stats area, so this is no longer true (Rob Janssen)
@@ -72,7 +72,7 @@ static int lp_reset(int minor)
 static inline int lp_char_polled(char lpchar, int minor)
 {
        int status, wait = 0;
-       unsigned long count  = 0; 
+       unsigned long count  = 0;
        struct lp_stats *stats;
 
        do {
@@ -92,10 +92,10 @@ static inline int lp_char_polled(char lpchar, int minor)
        /* must wait before taking strobe high, and after taking strobe
           low, according spec.  Some printers need it, others don't. */
        while(wait != LP_WAIT(minor)) wait++;
-        /* control port takes strobe high */
+       /* control port takes strobe high */
        outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
        while(wait) wait--;
-        /* take strobe low */
+       /* take strobe low */
        outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
        /* update waittime statistics */
        if (count > stats->maxwait) {
@@ -116,7 +116,7 @@ static inline int lp_char_polled(char lpchar, int minor)
 static inline int lp_char_interrupt(char lpchar, int minor)
 {
        int wait;
-       unsigned long count = 0; 
+       unsigned long count = 0;
        unsigned char status;
        struct lp_stats *stats;
 
@@ -269,7 +269,7 @@ static inline int lp_write_polled(unsigned int minor, const char * buf, int coun
                                current->timeout = jiffies + LP_TIMEOUT_POLLED;
                                schedule();
                        } else
-                       /* not offline or out of paper. on fire? */
+                       /* not offline or out of paper. on fire? */
                        if (!(status & LP_PERRORP)) {
                                printk(KERN_ERR "lp%d reported invalid error status (on fire, eh?)\n", minor);
                                if(LP_F(minor) & LP_ABORT)
@@ -340,7 +340,7 @@ static int lp_open(struct inode * inode, struct file * file)
           have commandeered O_NONBLOCK, even though it is being used in
           a non-standard manner.  This is strictly a Linux hack, and
           should most likely only ever be used by the tunelp application. */
-        if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
+       if ((LP_F(minor) & LP_ABORTOPEN) && !(file->f_flags & O_NONBLOCK)) {
                int status = LP_S(minor);
                if (status & LP_POUTPA) {
                        printk(KERN_INFO "lp%d out of paper\n", minor);
@@ -545,7 +545,7 @@ long lp_init(long kmem_start)
                printk("lp: unable to get major %d\n", LP_MAJOR);
 #ifdef MODULE
                return -EIO;
-#else          
+#else
                return kmem_start;
 #endif
        }
@@ -577,7 +577,7 @@ long lp_init(long kmem_start)
 
 #ifdef MODULE
        return 0;
-#else  
+#else
        return kmem_start;
 #endif
 }
@@ -586,14 +586,19 @@ long lp_init(long kmem_start)
 #ifdef MODULE
 void cleanup_module(void)
 {
-        int offset;
-       if(MOD_IN_USE)
-               printk("lp: busy - remove delayed\n");
-        else {
-               unregister_chrdev(LP_MAJOR,"lp");
-              for (offset = 0; offset < LP_NO; offset++) 
-                       if (LP_F(offset) & LP_EXIST) 
-                               release_region(LP_B(offset),3);
+       int offset;
+
+       if(MOD_IN_USE) {
+              printk("lp: busy - remove delayed\n");
+              return;
+       }
+       unregister_chrdev(LP_MAJOR,"lp");
+       for (offset = 0; offset < LP_NO; offset++) {
+               int base, size;
+               base = LP_B(offset);
+               size = (base == 0x3bc)? 3 : 8;
+               if (LP_F(offset) & LP_EXIST)
+                       release_region(LP_B(offset),size);
        }
 }
 
index 21fc8c73cb8320ba4916560a66a78823e397482b..c9f18a3ce71a92af37747c9f1609ea525c120f28 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/string.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
-#include <linux/major.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
 
index a8fb24e701a388a4a4f65f2b7a5bf6ab02fb8e57..0b04ee879db4382e1b4d89e9e8c74c5246468c0b 100644 (file)
@@ -298,7 +298,8 @@ ewrk3.o: ewrk3.c CONFIG
 depca.o: depca.c CONFIG
        $(CC) $(CPPFLAGS) $(CFLAGS) $(DEPCA_OPTS) -c $<
 
-Space.o: ../../include/linux/autoconf.h
+Space.o: Space.c ../../include/linux/autoconf.h CONFIG
+       $(CC) $(CPPFLAGS) $(CFLAGS) $(OPTS) -c $<
 
 net_init.o: ../../include/linux/autoconf.h
 
index 82fe4dbe8b6bf624768299c558aebadd4c935e31..5e77af0d0c97ade72d8bf4aa5f5168cb9691c3dd 100644 (file)
@@ -341,13 +341,13 @@ void unregister_netdev(struct device *dev)
                        restore_flags(flags);
                        return;
                }
-               for (i = 0; i < MAX_ETH_CARDS; ++i) 
+       }
+       for (i = 0; i < MAX_ETH_CARDS; ++i) 
+       {
+               if (ethdev_index[i] == dev) 
                {
-                       if (ethdev_index[i] == dev) 
-                       {
-                               ethdev_index[i] = NULL;
-                               break;
-                       }
+                       ethdev_index[i] = NULL;
+                       break;
                }
        }
        restore_flags(flags);
index c42d640bdecaf96605e91c0dcedaaf7b05fc3237..6f85d9a83d7d9acb5705a68c69131a5a98b8cdd2 100644 (file)
@@ -1775,7 +1775,7 @@ ppp_xmit(struct sk_buff *skb, struct device *dev)
 
   /* If doing demand dial then divert the first frame to pppd. */
   if (ppp->flags & SC_IP_DOWN) {
-    if (ppp->flags & SC_IP_FLUSH == 0) {
+    if ((ppp->flags & SC_IP_FLUSH) == 0) {
       if (ppp_us_queue (ppp, proto, p, len))
        ppp->flags |= SC_IP_FLUSH;
     }
index b384941b41a6fb8015a6db4e877719a1f178ccb9..56fa844217f1306317392136886951825b2c7130 100644 (file)
@@ -73,7 +73,7 @@ struct pci_dev_info dev_info[] = {
        BRIDGE( INTEL,          INTEL_82434,    "82434LX Mercury/Neptune", 0x00),
        DEVICE( INTEL,          INTEL_82430,    "82430ZX Aries"),
        DEVICE( INTEL,          INTEL_82437,    "82437 Triton"),
-       DEVICE( INTEL,          INTEL_82371,    "82471 Triton"),
+       DEVICE( INTEL,          INTEL_82371,    "82371 Triton"),
        DEVICE( INTEL,          INTEL_82438,    "82438"),
        DEVICE( INTEL,          INTEL_7116,     "SAA7116"),
        DEVICE( INTEL,          INTEL_82865,    "82865"),
@@ -261,7 +261,7 @@ const char *pci_strclass (unsigned int class)
              case PCI_CLASS_NOT_DEFINED_VGA:           return "VGA compatible device";
 
              case PCI_CLASS_STORAGE_SCSI:              return "SCSI storage controller";
-             case PCI_CLASS_STORAGE_IDE:               return "IDE controller";
+             case PCI_CLASS_STORAGE_IDE:               return "IDE interface";
              case PCI_CLASS_STORAGE_FLOPPY:            return "Floppy disk controller";
              case PCI_CLASS_STORAGE_IPI:               return "IPI bus controller";
              case PCI_CLASS_STORAGE_RAID:              return "RAID bus controller";
index 9eb054afb86ecf4b1683f99eeb6a1e8b85cd0946..a503efdf4be5c90c306e9c8b95f979ed5f13c8e9 100644 (file)
@@ -191,7 +191,7 @@ aha152x.o: aha152x.c
        $(CC) $(CFLAGS) $(AHA152X) -c aha152x.c 
 
 aic7xxx_asm:   aic7xxx_asm.c
-       $(CC) $(CFLAGS) -o $@ aic7xxx_asm.c
+       $(HOSTCC) -o $@ aic7xxx_asm.c
 
 aic7xxx.c: aic7xxx_seq.h
 aic7xxx_seq.h: aic7xxx_asm aic7xxx.seq
index 0a63c63c43f95f84cf6f8a030d8cb18dd4cd238a..c735a41fb76de0ee5aa6864229955241f5bf499a 100644 (file)
@@ -107,9 +107,9 @@ Scsi_Cmnd * last_cmnd = NULL;
  * It is only initialized to !=0 if the scsi code is present 
  */ 
 extern int (* dispatch_scsi_info_ptr)(int ino, char *buffer, char **start, 
-                                      off_t offset, int length, int inout); 
+                                     off_t offset, int length, int inout); 
 extern int dispatch_scsi_info(int ino, char *buffer, char **start, 
-                              off_t offset, int length, int inout); 
+                             off_t offset, int length, int inout); 
 
 
 /*
@@ -202,19 +202,19 @@ static struct dev_info device_list[] =
 {"NEC","CD-ROM DRIVE:841","1.0", BLIST_NOLUN},  /* Locks-up when LUN>0 polled. */
 {"RODIME","RO3000S","2.33", BLIST_NOLUN},       /* Locks up if polled for lun != 0 */
 {"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN},   /* causes failed REQUEST SENSE on lun 1 
-                                                 * for aha152x controller, which causes 
-                                                 * SCSI code to reset bus.*/
+                                                * for aha152x controller, which causes 
+                                                * SCSI code to reset bus.*/
 {"SEAGATE", "ST296","921", BLIST_NOLUN},        /* Responds to all lun */
 {"SONY","CD-ROM CDU-541","4.3d", BLIST_NOLUN},
 {"SONY","CD-ROM CDU-55S","1.0i", BLIST_NOLUN},
 {"SONY","CD-ROM CDU-561","1.7x", BLIST_NOLUN},
 {"TANDBERG","TDC 3600","U07", BLIST_NOLUN},     /* Locks up if polled for lun != 0 */
 {"TEAC","CD-ROM","1.06", BLIST_NOLUN},          /* causes failed REQUEST SENSE on lun 1 
-                                                 * for seagate controller, which causes 
-                                                 * SCSI code to reset bus.*/
+                                                * for seagate controller, which causes 
+                                                * SCSI code to reset bus.*/
 {"TEXEL","CD-ROM","1.06", BLIST_NOLUN},         /* causes failed REQUEST SENSE on lun 1 
-                                                 * for seagate controller, which causes 
-                                                 * SCSI code to reset bus.*/
+                                                * for seagate controller, which causes 
+                                                * SCSI code to reset bus.*/
 {"QUANTUM","LPS525S","3110", BLIST_NOLUN},      /* Locks sometimes if polled for lun != 0 */
 {"QUANTUM","PD1225S","3110", BLIST_NOLUN},      /* Locks sometimes if polled for lun != 0 */
 {"MEDIAVIS","CDR-H93MV","1.31", BLIST_NOLUN},   /* Locks up if polled for lun != 0 */
@@ -407,12 +407,12 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
                
                /*
                 * We need the for so our continue, etc. work fine.
-                 * We put this in a variable so that we can override
-                 * it during the scan if we detect a device *KNOWN*
-                 * to have multiple logical units.
+                * We put this in a variable so that we can override
+                * it during the scan if we detect a device *KNOWN*
+                * to have multiple logical units.
                 */
-                max_dev_lun = (max_scsi_luns < shpnt->max_lun ? 
-                               max_scsi_luns : shpnt->max_lun);
+               max_dev_lun = (max_scsi_luns < shpnt->max_lun ? 
+                              max_scsi_luns : shpnt->max_lun);
 
                for (lun = 0; lun < max_dev_lun; ++lun)
                {
@@ -555,8 +555,8 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
                                SDpnt->manufacturer = SCSI_MAN_NEC;
                        } else if (!strncmp(scsi_result+8,"TOSHIBA",7))
                            SDpnt->manufacturer = SCSI_MAN_TOSHIBA;
-                        else if (!strncmp(scsi_result+8,"SONY",4))
-                            SDpnt->manufacturer = SCSI_MAN_SONY;
+                       else if (!strncmp(scsi_result+8,"SONY",4))
+                           SDpnt->manufacturer = SCSI_MAN_SONY;
                        else
                            SDpnt->manufacturer = SCSI_MAN_UNKNOWN;
                        
@@ -569,7 +569,7 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
                        SDpnt->changed = 0;
                        SDpnt->access_count = 0;
                        SDpnt->busy = 0;
-                        SDpnt->has_cmdblocks = 0;
+                       SDpnt->has_cmdblocks = 0;
                        /*
                         * Currently, all sequential devices are assumed to be
                         * tapes, all random devices disk, with the appropriate
@@ -599,7 +599,7 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
 #endif
                        }
                        
-                        SDpnt->single_lun = 0;
+                       SDpnt->single_lun = 0;
                        SDpnt->soft_reset =
                            (scsi_result[7] & 1) && ((scsi_result[3] &7) == 2);
                        SDpnt->random = (type == TYPE_TAPE) ? 0 : 1;
@@ -640,10 +640,10 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
 
                            SDpnt->disconnect = 0;
 
-                            /*
-                             * Get any flags for this device.
-                             */
-                            bflags = get_device_flags(scsi_result);
+                           /*
+                            * Get any flags for this device.
+                            */
+                           bflags = get_device_flags(scsi_result);
 
                            
                            /*
@@ -654,16 +654,16 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
                             * change it here if it turns out that it isn't
                             * a TEXEL drive.
                             */
-                            if( (bflags & BLIST_BORKEN) == 0 )
-                            {
+                           if( (bflags & BLIST_BORKEN) == 0 )
+                           {
                                SDpnt->borken = 0;
-                            }
+                           }
                            
                            
                            /* These devices need this "key" to unlock the
                             * devices so we can use it 
                             */
-                            if( (bflags & BLIST_KEY) != 0 ) {
+                           if( (bflags & BLIST_KEY) != 0 ) {
                                printk("Unlocked floptical drive.\n");
                                SDpnt->lockable = 0;
                                scsi_cmd[0] = MODE_SENSE;
@@ -706,28 +706,28 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
                             */
                            if(bflags & BLIST_NOLUN) break;
 
-                            /*
-                             * If we want to only allow I/O to one of the luns
-                             * attached to this device at a time, then we set this
-                             * flag.
-                             */
-                            if(bflags & BLIST_SINGLELUN)
-                            {
-                                SDpnt->single_lun = 1;
-                            }
-
-                            /*
-                             * If this device is known to support multiple units, override
-                             * the other settings, and scan all of them.
-                             */
-                            if(bflags & BLIST_FORCELUN)
-                            {
-                                /*
-                                 * We probably want to make this a variable, but this
-                                 * will do for now.
-                                 */
-                                max_dev_lun = 8;
-                            }
+                           /*
+                            * If we want to only allow I/O to one of the luns
+                            * attached to this device at a time, then we set this
+                            * flag.
+                            */
+                           if(bflags & BLIST_SINGLELUN)
+                           {
+                               SDpnt->single_lun = 1;
+                           }
+
+                           /*
+                            * If this device is known to support multiple units, override
+                            * the other settings, and scan all of them.
+                            */
+                           if(bflags & BLIST_FORCELUN)
+                           {
+                               /*
+                                * We probably want to make this a variable, but this
+                                * will do for now.
+                                */
+                               max_dev_lun = 8;
+                           }
  
 
                            /* Old drives like the MAXTOR XT-3280 say vers=0 */
@@ -741,10 +741,10 @@ void scan_scsis (struct Scsi_Host * shpnt, unchar hardcoded,
                        }
                    }       /* if result == DID_OK ends */
 
-                    /*
-                     * This might screw us up with multi-lun devices, but the user can
-                     * scan for them too.
-                     */
+                   /*
+                    * This might screw us up with multi-lun devices, but the user can
+                    * scan for them too.
+                    */
                    if(hardcoded == 1)
                        goto leave;
                } /* for lun ends */
@@ -850,35 +850,35 @@ Scsi_Cmnd * request_queueable (struct request * req, Scsi_Device * device)
       
     SCpnt = device->host->host_queue;
     if (!device->single_lun) {
-        while(SCpnt){
-            if(SCpnt->target == device->id &&
-               SCpnt->lun == device->lun) {
-                if(SCpnt->request.dev < 0) break;
-            }
-            SCpnt = SCpnt->next;
-        }
+       while(SCpnt){
+           if(SCpnt->target == device->id &&
+              SCpnt->lun == device->lun) {
+               if(SCpnt->request.dev < 0) break;
+           }
+           SCpnt = SCpnt->next;
+       }
     } else {
-        while(SCpnt){
-            if(SCpnt->target == device->id) {
-                if (SCpnt->lun == device->lun) {
-                    if(found == NULL 
-                       && SCpnt->request.dev < 0) 
-                    {
-                        found=SCpnt;
-                    }
-                
-                if(SCpnt->request.dev >= 0) {
-                    /*
-                     * I think that we should really limit things to one
-                     * outstanding command per device - this is what tends to trip
-                     * up buggy firmware.
-                     */
-                    return NULL;
-                }
-            }
-            SCpnt = SCpnt->next;
-        }
-        SCpnt = found;
+       while(SCpnt){
+           if(SCpnt->target == device->id) {
+               if (SCpnt->lun == device->lun) {
+                   if(found == NULL 
+                      && SCpnt->request.dev < 0) 
+                   {
+                       found=SCpnt;
+                   }
+               } 
+               if(SCpnt->request.dev >= 0) {
+                   /*
+                    * I think that we should really limit things to one
+                    * outstanding command per device - this is what tends to trip
+                    * up buggy firmware.
+                    */
+                   return NULL;
+               }
+           }
+           SCpnt = SCpnt->next;
+       }
+       SCpnt = found;
     }
     
     if (!SCpnt) return NULL;
@@ -975,41 +975,41 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device,
     if (intr_count && SCSI_BLOCK(host)) return NULL;
     
     while (1==1){
-        SCpnt = device->host->host_queue;
-        if (!device->single_lun) {
-            while(SCpnt){
-                if(SCpnt->target == device->id &&
-                   SCpnt->lun == device->lun) {
-                   SCwait = SCpnt;
-                    if(SCpnt->request.dev < 0) break;
-                }
-                SCpnt = SCpnt->next;
-            }
-        } else {
-            while(SCpnt){
-                if(SCpnt->target == device->id) {
-                    if (SCpnt->lun == device->lun) {
-                        SCwait = SCpnt;
-                        if(found == NULL 
-                           && SCpnt->request.dev < 0) 
-                        {
-                            found=SCpnt;
-                        }
-                    
-                    if(SCpnt->request.dev >= 0) {
-                        /*
-                         * I think that we should really limit things to one
-                         * outstanding command per device - this is what tends to trip
-                         * up buggy firmware.
-                         */
-                        found = NULL;
-                        break;
-                    }
-                }
-                SCpnt = SCpnt->next;
-            }
-            SCpnt = found;
-        }
+       SCpnt = device->host->host_queue;
+       if (!device->single_lun) {
+           while(SCpnt){
+               if(SCpnt->target == device->id &&
+                  SCpnt->lun == device->lun) {
+                  SCwait = SCpnt;
+                   if(SCpnt->request.dev < 0) break;
+               }
+               SCpnt = SCpnt->next;
+           }
+       } else {
+           while(SCpnt){
+               if(SCpnt->target == device->id) {
+                   if (SCpnt->lun == device->lun) {
+                       SCwait = SCpnt;
+                       if(found == NULL 
+                          && SCpnt->request.dev < 0) 
+                       {
+                           found=SCpnt;
+                       }
+                   } 
+                   if(SCpnt->request.dev >= 0) {
+                       /*
+                        * I think that we should really limit things to one
+                        * outstanding command per device - this is what tends to trip
+                        * up buggy firmware.
+                        */
+                       found = NULL;
+                       break;
+                   }
+               }
+               SCpnt = SCpnt->next;
+           }
+           SCpnt = found;
+       }
 
        save_flags(flags);
        cli();
@@ -2198,7 +2198,8 @@ void * scsi_init_malloc(unsigned int size, int priority)
                scsi_init_memory_start += size;
            }
        }
-    memset((void *) retval, 0, size);
+    if (retval)
+       memset((void *) retval, 0, size);
     return (void *) retval;
 }
 
@@ -2341,19 +2342,22 @@ unsigned long scsi_dev_init (unsigned long memory_start, unsigned long memory_en
     
     dma_sectors = (dma_sectors + 15) & 0xfff0;
     dma_free_sectors = dma_sectors;  /* This must be a multiple of 16 */
+
+    if (dma_sectors)
+    {
+       dma_malloc_freelist = (unsigned char *)
+           scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC);
+       memset(dma_malloc_freelist, 0, dma_sectors >> 3);
+
+       dma_malloc_pages = (unsigned char **)
+           scsi_init_malloc(dma_sectors >> 1, GFP_ATOMIC);
+       memset(dma_malloc_pages, 0, dma_sectors >> 1);
+
+       for(i=0; i< dma_sectors >> 3; i++)
+           dma_malloc_pages[i] = (unsigned char *)
+               scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
     
-    dma_malloc_freelist = (unsigned char *)
-       scsi_init_malloc(dma_sectors >> 3, GFP_ATOMIC);
-    memset(dma_malloc_freelist, 0, dma_sectors >> 3);
-    
-    dma_malloc_pages = (unsigned char **)
-       scsi_init_malloc(dma_sectors >> 1, GFP_ATOMIC);
-    memset(dma_malloc_pages, 0, dma_sectors >> 1);
-    
-    for(i=0; i< dma_sectors >> 3; i++)
-       dma_malloc_pages[i] = (unsigned char *)
-           scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
-    
+    }
     /* OK, now we finish the initialization by doing spin-up, read
      * capacity, etc, etc 
      */
@@ -2440,40 +2444,40 @@ int scsi_proc_info(char *buffer, char **start, off_t offset, int length,
     HBA_ptr = scsi_hostlist;
 
     if(inout == 0) { 
-        size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none");
-        len += size; 
-        pos = begin + len;
-        while (HBA_ptr) {
+       size = sprintf(buffer+len,"Attached devices: %s\n", (scd)?"":"none");
+       len += size; 
+       pos = begin + len;
+       while (HBA_ptr) {
 #if 0
-            size += sprintf(buffer+len,"scsi%2d: %s\n", (int) HBA_ptr->host_no, HBA_ptr->hostt->procname);
-            len += size; 
-            pos = begin + len;
+           size += sprintf(buffer+len,"scsi%2d: %s\n", (int) HBA_ptr->host_no, HBA_ptr->hostt->procname);
+           len += size; 
+           pos = begin + len;
 #endif
-            scd = scsi_devices;
-            while (scd) {
-                if (scd->host == HBA_ptr) {
-                    proc_print_scsidevice(scd, buffer, &size, len);
-                    len += size; 
-                    pos = begin + len;
-                    
-                    if (pos < offset) {
-                        len = 0;
-                        begin = pos;
-                    }
-                    if (pos > offset + length)
-                        goto stop_output;
-                }
-                scd = scd->next;
-            }
+           scd = scsi_devices;
+           while (scd) {
+               if (scd->host == HBA_ptr) {
+                   proc_print_scsidevice(scd, buffer, &size, len);
+                   len += size; 
+                   pos = begin + len;
+                   
+                   if (pos < offset) {
+                       len = 0;
+                       begin = pos;
+                   }
+                   if (pos > offset + length)
+                       goto stop_output;
+               }
+               scd = scd->next;
+           }
            HBA_ptr = HBA_ptr->next;
-        }
-        
+       }
+       
     stop_output:
-        *start=buffer+(offset-begin);   /* Start of wanted data */
-        len-=(offset-begin);       /* Start slop */
-        if(len>length)
-            len = length;                  /* Ending slop */
-        return (len);     
+       *start=buffer+(offset-begin);   /* Start of wanted data */
+       len-=(offset-begin);        /* Start slop */
+       if(len>length)
+           len = length;                   /* Ending slop */
+       return (len);     
     }
 
     if(!buffer || length < 25 || strncmp("scsi", buffer, 4))
@@ -2623,15 +2627,18 @@ static int scsi_register_host(Scsi_Host_Template * tpnt)
         */
        if( new_dma_sectors < dma_sectors )
            new_dma_sectors = dma_sectors;
-       
-       new_dma_malloc_freelist = (unsigned char *)
-           scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
-       memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
-       
-       new_dma_malloc_pages = (unsigned char **)
-           scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
-       memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
-       
+
+       if (new_dma_sectors)
+       {
+           new_dma_malloc_freelist = (unsigned char *)
+               scsi_init_malloc(new_dma_sectors >> 3, GFP_ATOMIC);
+           memset(new_dma_malloc_freelist, 0, new_dma_sectors >> 3);
+
+           new_dma_malloc_pages = (unsigned char **)
+               scsi_init_malloc(new_dma_sectors >> 1, GFP_ATOMIC);
+           memset(new_dma_malloc_pages, 0, new_dma_sectors >> 1);
+       }
+
        /*
         * If we need more buffers, expand the list.
         */
@@ -2646,13 +2653,19 @@ static int scsi_register_host(Scsi_Host_Template * tpnt)
         */
        save_flags(flags);
        cli();
-       memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
-       scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+       if (dma_malloc_freelist)
+       {
+           memcpy(new_dma_malloc_freelist, dma_malloc_freelist, dma_sectors >> 3);
+           scsi_init_free(dma_malloc_freelist, dma_sectors>>3);
+       }
        dma_malloc_freelist = new_dma_malloc_freelist;
        
-       memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
-       scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
-       
+       if (dma_malloc_pages)
+       {
+           memcpy(new_dma_malloc_pages, dma_malloc_pages, dma_sectors >> 1);
+           scsi_init_free((char *) dma_malloc_pages, dma_sectors>>1);
+       }
+
        dma_free_sectors += new_dma_sectors - dma_sectors;
        dma_malloc_pages = new_dma_malloc_pages;
        dma_sectors = new_dma_sectors;
@@ -2739,7 +2752,7 @@ static void scsi_unregister_host(Scsi_Host_Template * tpnt)
                scsi_init_free((char *) sdpnt->host->host_queue, sizeof(Scsi_Cmnd));
                sdpnt->host->host_queue = SCpnt;
                if (SCpnt) SCpnt->prev = NULL;
-                sdpnt->has_cmdblocks = 0;
+               sdpnt->has_cmdblocks = 0;
            }
     
     /* Next free up the Scsi_Device structures for this host */
@@ -2904,7 +2917,7 @@ static int scsi_unregister_device(struct Scsi_Device_Template * tpnt)
                    scsi_init_free((char *) SCpnt, sizeof(*SCpnt));
                }
            }
-            SDpnt->has_cmdblocks = 0;
+           SDpnt->has_cmdblocks = 0;
        }
     }
     /*
index fcc61dcfb022997d6743510efb2efb24c4034fbe..1f4c33bcd9e5656260d1cb5a2be320390a5b2a6c 100644 (file)
@@ -30,7 +30,7 @@ int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigne
     struct hd_geometry *loc = (struct hd_geometry *) arg;
     
     switch (cmd) {
-    case HDIO_REQ:   /* Return BIOS disk parameters */
+    case HDIO_GETGEO:   /* Return BIOS disk parameters */
        if (!loc)  return -EINVAL;
        error = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
        if (error)
index 9a6a355e02d1557672efef1f3e9861f7c68393af..5e4b3ed27178da83a8578083a66db04c1c9f6083 100644 (file)
@@ -252,7 +252,7 @@ ad_leave_MCE (ad1848_info * devc)
   prev = INB (io_Index_Addr (devc));
   OUTB (0x00, io_Index_Addr (devc));   /* Clear the MCE bit */
 
-  if (prev & 0x40 == 0)                /* Not in MCE mode */
+  if ((prev & 0x40) == 0)              /* Not in MCE mode */
     {
       RESTORE_INTR (flags);
       return;
index 1d1b8599d797929d1f17bcf3a797489f53fac420..aa85c2a2c8ff4c6be376e0450f2e0b041701931c 100644 (file)
@@ -479,7 +479,7 @@ sound_ioctl_sw (int dev, struct fileinfo *file,
 {
   DEB (printk ("sound_ioctl_sw(dev=%d, cmd=0x%x, arg=0x%x)\n", dev, cmd, arg));
 
-  if ((cmd >> 8) & 0xff == 'M' && num_mixers > 0)      /* Mixer ioctl */
+  if (((cmd >> 8) & 0xff) == 'M' && num_mixers > 0)    /* Mixer ioctl */
     if ((dev & 0x0f) != SND_DEV_CTL)
       {
        int             dtype = dev & 0x0f;
index b7326613a86b6d4fca7731919ceb189d43e120e7..01db8a604a30fad0d7cca6c89c277cd76c8fc749 100644 (file)
@@ -172,7 +172,7 @@ unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exe
 static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
                             struct inode * interpreter_inode, unsigned int *interp_load_addr)
 {
-        struct file * file;
+       struct file * file;
        struct elf_phdr *elf_phdata  =  NULL;
        struct elf_phdr *eppnt;
        unsigned int len;
@@ -258,7 +258,7 @@ static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
 
        SYS(close)(elf_exec_fileno);
        if(error < 0 && error > -1024) {
-               kfree(elf_phdata);
+               kfree(elf_phdata);
                return 0xffffffff;
        }
 
@@ -386,7 +386,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
                           elf_ex.e_phentsize * elf_ex.e_phnum, 1);
        if (retval < 0) {
-               kfree (elf_phdata);
+               kfree (elf_phdata);
                MOD_DEC_USE_COUNT;
                return retval;
        }
@@ -399,7 +399,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
 
        if (elf_exec_fileno < 0) {
-               kfree (elf_phdata);
+               kfree (elf_phdata);
                MOD_DEC_USE_COUNT;
                return elf_exec_fileno;
        }
@@ -458,7 +458,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
        
        /* Some simple consistency checks for the interpreter */
        if(elf_interpreter){
-               interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
+               interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
                if(retval < 0) {
                        kfree(elf_interpreter);
                        kfree(elf_phdata);
@@ -500,10 +500,10 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                  }
                }
                if (!bprm->p) {
-                       if(elf_interpreter) {
+                       if(elf_interpreter) {
                              kfree(elf_interpreter);
                        }
-                       kfree (elf_phdata);
+                       kfree (elf_phdata);
                        MOD_DEC_USE_COUNT;
                        return -E2BIG;
                }
@@ -662,6 +662,15 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
                                MAP_FIXED | MAP_PRIVATE, 0);
        }
 
+       /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
+          starts %edx contains a pointer to a function which might be
+          registered using `atexit'.  This provides a mean for the
+          dynamic linker to call DT_FINI functions for shared libraries
+          that have been loaded before the code runs.
+
+          A value of 0 tells we have no such handler.  */
+       regs->edx = 0;
+
        start_thread(regs, elf_entry, bprm->p);
        if (current->flags & PF_PTRACED)
                send_sig(SIGTRAP, current, 0);
@@ -674,7 +683,7 @@ load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 
 static int
 load_elf_library(int fd){
-        struct file * file;
+       struct file * file;
        struct elfhdr elf_ex;
        struct elf_phdr *elf_phdata  =  NULL;
        struct  inode * inode;
@@ -751,7 +760,7 @@ load_elf_library(int fd){
        
        SYS(close)(fd);
        if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
-               kfree(elf_phdata);
+               kfree(elf_phdata);
                MOD_DEC_USE_COUNT;
                return error;
        }
index 10937274aa4eac9b3edc6f8888e20c4fb6094b0a..a175baaabdeb1b712d1bfb4f3c28a2a0adc2607b 100644 (file)
@@ -1171,6 +1171,7 @@ unsigned long bread_page(unsigned long address, dev_t dev, int b[], int size, in
        return address;
 }
 
+#if 0
 /*
  * bwrite_page writes a page out to the buffer cache and/or the physical device.
  * It's used for mmap writes (the same way bread_page() is used for mmap reads).
@@ -1192,9 +1193,10 @@ void bwrite_page(unsigned long address, dev_t dev, int b[], int size)
                        mark_buffer_dirty(bh[i], 0);
                        brelse(bh[i]);
                } else
-                       memset((void *) address, 0, size);
+                       memset((void *) address, 0, size); /* ???!?!! */
        }       
 }
+#endif
 
 /*
  * Try to increase the number of buffers available: the size argument
index aef8fcc2b4e37e0f0754dc6acaea9492993c3a3c..bcad000df70101e7c6680d00a4a6fb2d334a5536 100644 (file)
@@ -105,8 +105,9 @@ static int msdos_find(struct inode *dir,const char *name,int len,
        char msdos_name[MSDOS_NAME];
        int res;
 
-       if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
-           msdos_name,1)) < 0) return res;
+       res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, msdos_name,1);
+       if (res < 0)
+               return -ENOENT;
        return msdos_scan(dir,msdos_name,bh,de,ino);
 }
 
index 2982179c0679c53ebbbf0291abf754c22700c075..258637cf2a11911ceccc3001ded2fa6486855ce5 100644 (file)
@@ -143,6 +143,7 @@ struct super_block *nfs_read_super(struct super_block *sb, void *raw_data,
        if (data->addr.sin_addr.s_addr == INADDR_ANY) {  /* No address passed */
          if (((struct sockaddr_in *)(&server->toaddr))->sin_addr.s_addr == INADDR_ANY) {
            printk("NFS: Error passed unconnected socket and no address\n") ;
+           MOD_DEC_USE_COUNT;
            return NULL ;
          } else {
            /* Need access to socket internals  JSP */
index 0284098abeefe8b6bc0120dc35a0dfd908fbbf51..5e0eae3bc32f7d5cf8e738681853194632755ac1 100644 (file)
 #include <linux/config.h>
 #include <linux/mm.h>
 
-static struct file_operations proc_netdir_operations = {
-       NULL,                   /* lseek - default */
-       NULL,                   /* read - bad */
-       NULL,                   /* write - bad */
-       proc_readdir,           /* readdir */
-       NULL,                   /* select - default */
-       NULL,                   /* ioctl - default */
-       NULL,                   /* mmap */
-       NULL,                   /* no special open code */
-       NULL,                   /* no special release code */
-       NULL                    /* can't fsync */
-};
-
-/*
- * proc directories can do almost nothing..
- */
-static struct inode_operations proc_netdir_inode_operations = {
-       &proc_netdir_operations,        /* default net directory file-ops */
-       NULL,                   /* create */
-       proc_lookup,            /* lookup */
-       NULL,                   /* link */
-       NULL,                   /* unlink */
-       NULL,                   /* symlink */
-       NULL,                   /* mkdir */
-       NULL,                   /* rmdir */
-       NULL,                   /* mknod */
-       NULL,                   /* rename */
-       NULL,                   /* readlink */
-       NULL,                   /* follow_link */
-       NULL,                   /* bmap */
-       NULL,                   /* truncate */
-       NULL                    /* permission */
-};
-
-struct proc_dir_entry proc_net = {
-       PROC_NET, 3, "net",
-       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-       0, &proc_netdir_inode_operations,
-       NULL, NULL,
-       NULL,
-       NULL, NULL      
-};
-
 #define PROC_BLOCK_SIZE        (3*1024)                /* 4K page size but our output routines use some slack for overruns */
 
 static int proc_readnet(struct inode * inode, struct file * file,
index 7b457709b3902fd6cd41bc128ecc0bbefa897fdf..e51f222df45a7bbf31208d5abc8fc1b62325f8e9 100644 (file)
 static int proc_root_readdir(struct inode *, struct file *, void *, filldir_t);
 static int proc_root_lookup(struct inode *,const char *,int,struct inode **);
 
+/*
+ * These are the generic /proc directory operations. They
+ * use the in-memory "struct proc_dir_entry" tree to parse
+ * the /proc directory.
+ *
+ * NOTE! The /proc/scsi directory currently does not correctly
+ * build up the proc_dir_entry tree, and will show up empty.
+ */
+static struct file_operations proc_dir_operations = {
+       NULL,                   /* lseek - default */
+       NULL,                   /* read - bad */
+       NULL,                   /* write - bad */
+       proc_readdir,           /* readdir */
+       NULL,                   /* select - default */
+       NULL,                   /* ioctl - default */
+       NULL,                   /* mmap */
+       NULL,                   /* no special open code */
+       NULL,                   /* no special release code */
+       NULL                    /* can't fsync */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+static struct inode_operations proc_dir_inode_operations = {
+       &proc_dir_operations,   /* default net directory file-ops */
+       NULL,                   /* create */
+       proc_lookup,            /* lookup */
+       NULL,                   /* link */
+       NULL,                   /* unlink */
+       NULL,                   /* symlink */
+       NULL,                   /* mkdir */
+       NULL,                   /* rmdir */
+       NULL,                   /* mknod */
+       NULL,                   /* rename */
+       NULL,                   /* readlink */
+       NULL,                   /* follow_link */
+       NULL,                   /* bmap */
+       NULL,                   /* truncate */
+       NULL                    /* permission */
+};
+
+/*
+ * The root /proc directory is special, as it has the
+ * <pid> directories. Thus we don't use the generic
+ * directory handling functions for that..
+ */
 static struct file_operations proc_root_operations = {
        NULL,                   /* lseek - default */
        NULL,                   /* read - bad */
@@ -36,7 +83,7 @@ static struct file_operations proc_root_operations = {
 };
 
 /*
- * proc directories can do almost nothing..
+ * proc root can do almost nothing..
  */
 static struct inode_operations proc_root_inode_operations = {
        &proc_root_operations,  /* default base directory file-ops */
@@ -61,13 +108,31 @@ static struct inode_operations proc_root_inode_operations = {
  */
 struct proc_dir_entry proc_root = {
        PROC_ROOT_INO, 5, "/proc",
-       S_IFDIR | S_IRUGO | S_IXUGO, 3, 0, 0,
+       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
        0, &proc_root_inode_operations,
        NULL, NULL,
        NULL,
        &proc_root, NULL
 };
 
+struct proc_dir_entry proc_net = {
+       PROC_NET, 3, "net",
+       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+       0, &proc_dir_inode_operations,
+       NULL, NULL,
+       NULL,
+       NULL, NULL      
+};
+
+struct proc_dir_entry proc_scsi = {
+       PROC_SCSI, 4, "scsi",
+       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+       0, &proc_dir_inode_operations,
+       NULL, NULL,
+       NULL,
+       &proc_root, NULL
+};
+
 int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
        dp->next = dir->subdir;
index 608f7c06e99c4299ce7f9c8c697f27714dea2d86..8f3d0f529f7db8cb46d5a8c81f7af5b4437e2e09 100644 (file)
@@ -34,8 +34,6 @@ static int proc_readscsi(struct inode * inode, struct file * file,
                         char * buf, int count);
 static int proc_writescsi(struct inode * inode, struct file * file,
                         const char * buf, int count);
-static int proc_readscsidir(struct inode *, struct file *, 
-                           void *, filldir_t filldir);
 static int proc_lookupscsi(struct inode *,const char *,int,struct inode **);
 static int proc_scsilseek(struct inode *, struct file *, off_t, int);
 
@@ -50,7 +48,7 @@ static struct file_operations proc_scsi_operations = {
     proc_scsilseek,    /* lseek   */
     proc_readscsi,     /* read    */
     proc_writescsi,    /* write   */
-    proc_readscsidir,  /* readdir */
+    NULL,              /* readdir */
     NULL,              /* select  */
     NULL,              /* ioctl   */
     NULL,              /* mmap    */
@@ -80,15 +78,6 @@ struct inode_operations proc_scsi_inode_operations = {
     NULL           /* permission  */
 };
 
-struct proc_dir_entry proc_scsi = {
-       PROC_SCSI, 4, "scsi",
-       S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-       0, &proc_scsi_inode_operations,
-       NULL, NULL,
-       NULL,
-       &proc_root, NULL
-};
-
 struct proc_dir_entry scsi_dir[PROC_SCSI_FILE - PROC_SCSI_SCSI + 3]; 
 struct proc_dir_entry scsi_hba_dir[(PROC_SCSI_LAST - PROC_SCSI_FILE) * 4]; 
 
@@ -177,36 +166,6 @@ static int proc_lookupscsi(struct inode * dir, const char * name, int len,
     return(-ENOENT);
 }
 
-static int proc_readscsidir(struct inode * inode, struct file * filp,
-                           void * dirent, filldir_t filldir)
-{
-    struct proc_dir_entry * de;
-    uint index, num;
-    num = 0;
-
-    if (!inode || !S_ISDIR(inode->i_mode))
-       return(-EBADF);
-
-    index = count_dir_entries(inode->i_ino, &num);
-
-    while (((unsigned) filp->f_pos + index) < index + num) {
-       if (dispatch_scsi_info_ptr) {
-           if (inode->i_ino <= PROC_SCSI_SCSI)
-               de = scsi_dir + filp->f_pos;
-           else
-               de = scsi_hba_dir + filp->f_pos + index;
-        }
-       else {
-           de = scsi_dir2 + filp->f_pos;
-        }
-       if (filldir(dirent, de->name, de->namelen, filp->f_pos, de->low_ino)<0)
-           break;
-       filp->f_pos++;
-    }
-    return(0);
-}
-
 int get_not_present_info(char *buffer, char **start, off_t offset, int length)
 {
     int len, pos, begin;
index 00707f6f875b748cdcb451e4e75b638c62da553b..937262dacfd437d5c7427e97bc0342f47e3d2663 100644 (file)
@@ -1,7 +1,7 @@
 smbfs is a filesystem which understands the SMB protocol. This is the
 protocol Windows for Workgroups, Windows NT or Lan Manager use to talk
-to each other. It was inspired by samba, the program by Andrew
-Tridgell that turns any unix site into a file server for DOS or
+to each other. smbfs was inspired by samba, the program written by
+Andrew Tridgell that turns any unix host into a file server for DOS or
 Windows clients.  See ftp://nimbus.anu.edu.au/pub/tridge/samba/ for
 this interesting program suite and lots of more information on SMB and
 NetBIOS over TCP/IP. There you also find explanation for conceps like
index 5be44babbd0838e1729c69d686b168814d991c21..9802e3958aa4964a2c76c620ed8724ffb3926ff9 100644 (file)
@@ -159,10 +159,11 @@ static int                c_last_returned_index;
 static struct smb_dirent* c_entry = NULL;
 
 static int
-smb_readdir1(struct inode *inode, const struct file *filp,
-            struct smb_dirent *ret,ino_t *ino)
+smb_readdir(struct inode *inode, struct file *filp,
+            void *dirent, filldir_t filldir)
 {
        int result, i = 0;
+        int index = 0;
        struct smb_dirent *entry = NULL;
         struct smb_server *server = SMB_SERVER(inode);
 
@@ -198,6 +199,7 @@ smb_readdir1(struct inode *inode, const struct file *filp,
                        if (filp->f_pos == c_entry[i].f_pos) {
                                 entry = &c_entry[i];
                                 c_last_returned_index = i;
+                                index = i;
                                 break;
                        }
                }
@@ -222,6 +224,7 @@ smb_readdir1(struct inode *inode, const struct file *filp,
                        c_size = result;
                        entry = c_entry;
                         c_last_returned_index = 0;
+                        index = 0;
                         for (i = 0; i < c_size; i++) {
 
                                 switch (server->case_handling) 
@@ -236,22 +239,26 @@ smb_readdir1(struct inode *inode, const struct file *filp,
                         }
                }
        }
-       
-       if (entry) {
+
+        if (entry == NULL) {
+                /* Nothing found, even from a smb call */
+                return 0;
+        }
+
+        while (index < c_size) {
 
                 /* We found it.  For getwd(), we have to return the
                    correct inode in d_ino if the inode is currently in
                    use. Otherwise the inode number does not
-                   matter. */ 
+                   matter. (You can argue a lot about this..) */ 
 
-                int  path_len;
+                int path_len;
+                int len;
                 struct smb_inode_info *ino_info;
                 char complete_path[SMB_MAXPATHLEN];
 
-                
-
-               i = strlen(entry->path);
-                if ((result = get_pname_static(inode, entry->path, i,
+               len = strlen(entry->path);
+                if ((result = get_pname_static(inode, entry->path, len,
                                                complete_path,
                                                &path_len)) < 0)
                         return result;
@@ -268,30 +275,20 @@ smb_readdir1(struct inode *inode, const struct file *filp,
                DDPRINTK("smb_readdir: entry->path = %s\n", entry->path);
                DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);
 
-               *ino = (ino_t)ino_info; /* use the pointer as the
-                                         inode - dangerous if we have
-                                         64 bit pointers! FIXME */
-
-               *ret = *entry;
-               return 1;
-       }
-
-       return 0;
-}
-
-static int 
-smb_readdir(struct inode *inode, struct file *filp,
-            void *dirent, filldir_t filldir)
-{
-       struct smb_dirent d;
-       ino_t ino;
+                if (filldir(dirent, entry->path, len,
+                            entry->f_pos, (ino_t)ino_info) < 0) {
+                        break;
+                }
 
-       while (smb_readdir1(inode,filp,&d,&ino) == 1) {         
-               if (filldir(dirent,d.path,strlen(d.path)+1,
-                           filp->f_pos,ino) < 0) {
-                       return 0;
-               }
-               filp->f_pos++;
+                if (   (inode->i_ino != c_ino)
+                    || (entry->f_pos != filp->f_pos)) {
+                        /* Someone has destroyed the cache while we slept
+                           in filldir */
+                        break;
+                }
+                filp->f_pos += 1;
+                index += 1;
+                entry += 1;
        }
        return 0;
 }
@@ -716,13 +713,9 @@ smb_lookup(struct inode *dir, const char *__name, int len,
         found_in_cache = 0;
         
         if (dir->i_ino == c_ino) {
-                int first = c_last_returned_index - 1;
+                int first = c_last_returned_index;
                 int i;
 
-                if (first < 0) {
-                        first = c_size - 1;
-                }
-
                 i = first;
                 do {
                         DDPRINTK("smb_lookup: trying index: %d, name: %s\n",
@@ -735,7 +728,8 @@ smb_lookup(struct inode *dir, const char *__name, int len,
                                 break;
                         }
                         i = (i + 1) % c_size;
-
+                        DDPRINTK("smb_lookup: index %d, name %s failed\n",
+                                 i, c_entry[i].path);
                 } while (i != first);
         }
 
@@ -920,10 +914,19 @@ smb_rename(struct inode *old_dir, const char *old_name, int old_len,
        res = smb_proc_mv(SMB_SERVER(old_dir), old_path, old_len,
                           new_path, new_len);
 
+       if (res == -EEXIST) {
+               int res1;
+               res1 = smb_proc_unlink(SMB_SERVER(old_dir), new_path, new_len);
+               if (res1 == 0) {
+                       res = smb_proc_mv(SMB_SERVER(old_dir), old_path,
+                                         old_len, new_path, new_len);
+               }
+       }
+
         if (res == 0) {
                 smb_invalid_dir_cache(old_dir->i_ino);
                 smb_invalid_dir_cache(new_dir->i_ino);
-        }
+        }              
        
  finished:
        iput(old_dir); 
index c170965d6116938db682a54b9289eb68a4dc83ed..bcc543613ca27200df3224e1192c950e4ff5be89 100644 (file)
@@ -102,10 +102,25 @@ smb_file_read(struct inode *inode, struct file *file, char *buf, int count)
        /* First read in as much as possible for each bufsize. */
         while (already_read < count) {
 
-                to_read = min(bufsize, count - already_read);
+                result = 0;
+                to_read = 0;
+                
+                if ((SMB_SERVER(inode)->blkmode & 1) != 0) {
+                        to_read = min(65535, count - already_read);
+                        DPRINTK("smb_file_read: Raw %d bytes\n", to_read);
+                        result = smb_proc_read_raw(SMB_SERVER(inode),
+                                                   SMB_FINFO(inode),
+                                                   pos, to_read, buf);
+                        DPRINTK("smb_file_read: returned %d\n", result);
+                }
+
+                if (result <= 0) {
+                        to_read = min(bufsize, count - already_read);
+                        result = smb_proc_read(SMB_SERVER(inode),
+                                               SMB_FINFO(inode),
+                                               pos, to_read, buf, 1);
+                }
 
-               result = smb_proc_read(SMB_SERVER(inode), SMB_FINFO(inode),
-                                       pos, to_read, buf, 1);
                if (result < 0)
                        return result;
                pos += result;
@@ -162,12 +177,30 @@ smb_file_write(struct inode *inode, struct file *file, const char *buf, int coun
 
         already_written = 0;
 
+        DPRINTK("smb_write_file: blkmode = %d, blkmode & 2 = %d\n",
+                SMB_SERVER(inode)->blkmode,
+                SMB_SERVER(inode)->blkmode & 2);
+        
         while (already_written < count) {
 
-                to_write = min(bufsize, count - already_written);
-
-               result = smb_proc_write(SMB_SERVER(inode), SMB_FINFO(inode), 
-                                       pos, to_write, buf);
+                result = 0;
+                to_write = 0;
+
+                if ((SMB_SERVER(inode)->blkmode & 2) != 0) {
+                        to_write = min(65535, count - already_written);
+                        DPRINTK("smb_file_write: Raw %d bytes\n", to_write);
+                        result = smb_proc_write_raw(SMB_SERVER(inode),
+                                                    SMB_FINFO(inode), 
+                                                    pos, to_write, buf);
+                        DPRINTK("smb_file_write: returned %d\n", result);
+                }
+
+                if (result <= 0) {
+                        to_write = min(bufsize, count - already_written);
+                        result = smb_proc_write(SMB_SERVER(inode),
+                                                SMB_FINFO(inode), 
+                                                pos, to_write, buf);
+                }
 
                if (result < 0)
                        return result;
index 90e6f696863a4ec504eba3d1e4f683c7f8c78b37..2352f677c7e113b5aaf499892bead3e186fc2f34 100644 (file)
@@ -345,13 +345,18 @@ smb_notify_change(struct inode *inode, struct iattr *attr)
        if ((error = inode_change_ok(inode, attr)) < 0)
                return error;
 
-        if (!S_ISREG(inode->i_mode))
-                return -EPERM;
+       if (((attr->ia_valid & ATTR_UID) && 
+            (attr->ia_uid != SMB_SERVER(inode)->m.uid)))
+               return -EPERM;
 
-        if ((attr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) != 0) {
+       if (((attr->ia_valid & ATTR_GID) && 
+            (attr->ia_uid != SMB_SERVER(inode)->m.gid)))
                 return -EPERM;
-        }
-        
+
+       if (((attr->ia_valid & ATTR_MODE) &&
+            (attr->ia_mode & ~(S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO))))
+               return -EPERM;
+
         if ((attr->ia_valid & ATTR_SIZE) != 0) {
 
                 if ((error = smb_make_open(inode, O_WRONLY)) < 0)
index 708bd3784ce413e2271e98c45cdbc2ccd3c31627..a45423009ea3fd110ffd0856c798c0c933412fce 100644 (file)
@@ -69,18 +69,7 @@ smb_decode_word(byte *p, word *data)
        return &p[2];
 }
 
-static byte *
-smb_decode_dword(byte *p, dword *data)
-{
-#if (ARCH == i386)
-       *data = *((dword *)p);
-#else
-       *data = (dword)p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
-#endif
-       return &p[4];
-}
-
-static byte *
+byte *
 smb_encode_smb_length(byte *p, dword len)
 {
        p[0] = p[1] = 0;
@@ -320,6 +309,9 @@ smb_errno(int errcls, int error)
                        case ERRlock:       return EDEADLOCK;
                        case ERRfilexists:  return EEXIST;
                        case 87:            return 0; /* Unknown error!! */
+                       /* This next error seems to occur on an mv when
+                        * the destination exists */
+                       case 183:           return EEXIST;
                        default:            return EIO;
                }
        else if (errcls == ERRSRV) 
@@ -655,6 +647,33 @@ smb_proc_read(struct smb_server *server, struct smb_dirent *finfo,
         return data_len;
 }
 
+/* count must be <= 65535. No error number is returned.  A result of 0
+   indicates an error, which has to be investigated by a normal read
+   call. */
+int
+smb_proc_read_raw(struct smb_server *server, struct smb_dirent *finfo, 
+                  off_t offset, long count, char *data)
+{
+        char *buf = server->packet;
+        int result;
+
+        if ((count <= 0) || (count > 65535)) {
+                return -EINVAL;
+        }
+
+       smb_setup_header_exclusive(server, SMBreadbraw, 8, 0);
+
+        WSET(buf, smb_vwv0, finfo->fileid);
+        DSET(buf, smb_vwv1, offset);
+        WSET(buf, smb_vwv3, count);
+        WSET(buf, smb_vwv4, 0);
+        DSET(buf, smb_vwv5, 0);
+
+        result = smb_request_read_raw(server, data, count);
+        smb_unlock_server(server);
+        return result;
+}
+
 int
 smb_proc_write(struct smb_server *server, struct smb_dirent *finfo,
                off_t offset, int count, const char *data)
@@ -682,6 +701,61 @@ smb_proc_write(struct smb_server *server, struct smb_dirent *finfo,
        return res;
 }
 
+/* count must be <= 65535 */
+int
+smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, 
+                   off_t offset, long count, const char *data)
+{
+        char *buf = server->packet;
+        int result;
+
+        if ((count <= 0) || (count > 65535)) {
+                return -EINVAL;
+        }
+
+       smb_setup_header_exclusive(server, SMBwritebraw, 11, 0);
+
+        WSET(buf, smb_vwv0, finfo->fileid);
+        WSET(buf, smb_vwv1, count);
+        WSET(buf, smb_vwv2, 0); /* reserved */
+        DSET(buf, smb_vwv3, offset);
+        DSET(buf, smb_vwv5, 0); /* timeout */
+        WSET(buf, smb_vwv7, 1); /* send final result response */
+        DSET(buf, smb_vwv8, 0); /* reserved */
+        WSET(buf, smb_vwv10, 0); /* no data in this buf */
+        WSET(buf, smb_vwv11, 0); /* no data in this buf */
+
+        result = smb_request_ok(server, SMBwritebraw, 1, 0);
+
+        DPRINTK("smb_proc_write_raw: first request returned %d\n", result);
+        
+        if (result < 0) {
+                smb_unlock_server(server);
+                return result;
+        }
+        
+        result = smb_request_write_raw(server, data, count);
+
+        DPRINTK("smb_proc_write_raw: raw request returned %d\n", result);
+        
+        if (result > 0) {
+                /* We have to do the checks of smb_request_ok here as well */
+                if (smb_valid_packet(server->packet) != 0) {
+                        DPRINTK("not a valid packet!\n");
+                        result = -EIO;
+                } else if (server->rcls != 0) {
+                        result = -smb_errno(server->rcls, server->err);
+                } else if (smb_verify(server->packet, SMBwritec,1,0) != 0) {
+                        DPRINTK("smb_verify failed\n");
+                        result = -EIO;
+                }
+        }
+
+        smb_unlock_server(server);
+        return result;
+}
+
+
 /* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
 
 static int
@@ -1642,12 +1716,14 @@ smb_proc_reconnect(struct smb_server *server)
                         server->m.password);
                 DPRINTK("smb_proc_connect: usernam = %s\n",
                         server->m.username);
+                DPRINTK("smb_proc_connect: blkmode = %d\n",
+                        WVAL(server->packet, smb_vwv5));
 
-                p = smb_decode_word(p, &(server->maxxmt));
-                p = smb_decode_word(p, &(server->maxmux));
-                p = smb_decode_word(p, &(server->maxvcs));
-                p = smb_decode_word(p, &(server->blkmode));
-                p = smb_decode_dword(p, &(server->sesskey));
+                server->maxxmt = WVAL(server->packet, smb_vwv2);
+                server->maxmux = WVAL(server->packet, smb_vwv3);
+                server->maxvcs = WVAL(server->packet, smb_vwv4);
+                server->blkmode= WVAL(server->packet, smb_vwv5);
+                server->sesskey= DVAL(server->packet, smb_vwv6);
 
                 smb_setup_header(server, SMBsesssetupX, 10,
                                  2 + userlen + passlen);
@@ -1674,6 +1750,15 @@ smb_proc_reconnect(struct smb_server *server)
                 }
                 smb_decode_word(server->packet+32, &(server->server_uid));
         }
+        else
+
+        {
+                server->maxxmt = 0;
+                server->maxmux = 0;
+                server->maxvcs = 0;
+                server->blkmode = 0;
+                server->sesskey = 0;
+        }
 
        /* Fine! We have a connection, send a tcon message. */
 
index fbea9cfb9f655e2fb00f03afd3147a9ad891958b..20a7b8105bc2662a9b797d3efc18d467351b026b 100644 (file)
@@ -175,27 +175,36 @@ smb_dont_catch_keepalive(struct smb_server *server)
 }
 
 /*
- * smb_receive
- * fs points to the correct segment, server != NULL, sock!=NULL
+ * smb_receive_raw
+ * fs points to the correct segment, sock != NULL, target != NULL
+ * The smb header is only stored if want_header != 0.
  */
 static int
-smb_receive(struct smb_server *server, struct socket *sock)
+smb_receive_raw(struct socket *sock, unsigned char *target,
+                int max_raw_length, int want_header)
 {
         int len, result;
+        int already_read;
         unsigned char peek_buf[4];
+        unsigned short fs;      /* We fool the kernel to believe
+                                   we call from user space. */
+
 
  re_recv:
 
+       fs = get_fs();
+       set_fs(get_ds());
         result = sock->ops->recvfrom(sock, (void *)peek_buf, 4, 0,
-                                     MSG_PEEK, NULL, NULL);
+                                     0, NULL, NULL);
+        set_fs(fs);
 
         if (result < 0) {
-                DPRINTK("smb_receive: recv error = %d\n", -result);
+                DPRINTK("smb_receive_raw: recv error = %d\n", -result);
                 return result;
         }
 
-        if (result == 0) {
-                DPRINTK("smb_receive: got 0 bytes\n");
+        if (result < 4) {
+                DPRINTK("smb_receive_raw: got less than 4 bytes\n");
                 return -EIO;
         }
 
@@ -206,51 +215,72 @@ smb_receive(struct smb_server *server, struct socket *sock)
                 break;
 
         case 0x85:
-                DPRINTK("smb_receive: Got SESSION KEEP ALIVE\n");
-                sock->ops->recvfrom(sock, (void *)peek_buf, 4, 1,
-                                    0, NULL, NULL);
+                DPRINTK("smb_receive_raw: Got SESSION KEEP ALIVE\n");
                 goto re_recv;
                 
         default:
-                printk("smb_receive: Invalid packet\n");
+                printk("smb_receive_raw: Invalid packet\n");
                 return -EIO;
         }
 
-        /* Length not including first four bytes. */
-       len = smb_len(peek_buf) + 4
-        if (len > server->max_xmit) { 
-                printk("smb_receive: Received length (%d) > max_xmit (%d)!\n", 
-                      len, server->max_xmit);
+        /* The length in the RFC NB header is the raw data length */
+       len = smb_len(peek_buf); 
+        if (len > max_raw_length) { 
+                printk("smb_receive_raw: Received length (%d) > max_xmit (%d)!\n", 
+                      len, max_raw_length);
                 return -EIO;
        }
-        else
-        {
-                int already_read = 0;
 
-                while (already_read < len) {
+        if (want_header != 0) {
+                memcpy_tofs(target, peek_buf, 4);
+                target += 4;
+        }
+
+        already_read = 0;
+
+        while (already_read < len) {
                 
-                        result = sock->ops->
-                                recvfrom(sock,
-                                         (void *)(server->packet+already_read),
-                                         len - already_read, 0, 0,
-                                         NULL, NULL);
+                result = sock->ops->
+                        recvfrom(sock,
+                                 (void *)(target+already_read),
+                                 len - already_read, 0, 0,
+                                 NULL, NULL);
    
-                        if (result < 0) {
-                                printk("SMB: notice message: error = %d\n",
-                                       -result);
-                                return result;
-                        }
-
-                        already_read += result;
+                if (result < 0) {
+                        printk("smb_receive_raw: recvfrom error = %d\n",
+                               -result);
+                        return result;
                 }
-                result = already_read;
+
+                already_read += result;
+        }
+        return already_read;
+}
+
+/*
+ * smb_receive
+ * fs points to the correct segment, server != NULL, sock!=NULL
+ */
+static int
+smb_receive(struct smb_server *server, struct socket *sock)
+{
+        int result;
+
+        result = smb_receive_raw(sock, server->packet,
+                                 server->max_xmit - 4, /* max_xmit in server
+                                                          includes NB header */
+                                 1); /* We want the header */
+
+        if (result < 0) {
+                printk("smb_receive: receive error: %d\n", result);
+                return result;
         }
 
         server->rcls = *((unsigned char *)(server->packet+9));
         server->err  = *((unsigned short *)(server->packet+11));
 
         if (server->rcls != 0) {
-                DPRINTK("smb_response: rcls=%d, err=%d\n",
+                DPRINTK("smb_receive: rcls=%d, err=%d\n",
                         server->rcls, server->err);
         }
 
@@ -447,12 +477,6 @@ smb_request(struct smb_server *server)
         if (server->state != CONN_VALID)
                 return -EIO;
                
-#if 0
-       while (server->lock)
-               sleep_on(&server->wait);
-       server->lock = 1;
-#endif
-
         if ((result = smb_dont_catch_keepalive(server)) != 0) {
                 server->state = CONN_INVALID;
                 smb_invalidate_all_inodes(server);
@@ -486,11 +510,6 @@ smb_request(struct smb_server *server)
                 result = result2;
         }
 
-#if 0
-       server->lock = 0;
-       wake_up(&server->wait);
-#endif
-
         if (result < 0) {
                 server->state = CONN_INVALID;
                 smb_invalidate_all_inodes(server);
@@ -526,12 +545,6 @@ smb_trans2_request(struct smb_server *server,
         if (server->state != CONN_VALID)
                 return -EIO;
                
-#if 0
-       while (server->lock)
-               sleep_on(&server->wait);
-       server->lock = 1;
-#endif
-
         if ((result = smb_dont_catch_keepalive(server)) != 0) {
                 server->state = CONN_INVALID;
                 smb_invalidate_all_inodes(server);
@@ -540,13 +553,13 @@ smb_trans2_request(struct smb_server *server,
 
         len = smb_len(buffer) + 4;
 
-        DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
-
        old_mask = current->blocked;
        current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
        fs = get_fs();
        set_fs(get_ds());
 
+        DDPRINTK("smb_request: len = %d cmd = 0x%X\n", len, buffer[8]);
+
         result = sock->ops->send(sock, (void *)buffer, len, 0, 0);
         if (result < 0) {
                 printk("smb_trans2_request: send error = %d\n", result);
@@ -567,11 +580,6 @@ smb_trans2_request(struct smb_server *server,
                 result = result2;
         }
 
-#if 0
-       server->lock = 0;
-       wake_up(&server->wait);
-#endif
-
         if (result < 0) {
                 server->state = CONN_INVALID;
                 smb_invalidate_all_inodes(server);
@@ -582,6 +590,156 @@ smb_trans2_request(struct smb_server *server,
        return result;
 }
 
+/* target must be in user space */
+int
+smb_request_read_raw(struct smb_server *server,
+                     unsigned char *target, int max_len)
+{
+       unsigned long old_mask;
+       int len, result, result2;
+       unsigned short fs;      /* We fool the kernel to believe
+                                   we call from user space. */
+
+       struct socket *sock = server_sock(server);
+       unsigned char *buffer = (server == NULL) ? NULL : server->packet;
+
+       if ((sock == NULL) || (buffer == NULL)) {
+               printk("smb_request_read_raw: Bad server!\n");
+               return -EBADF;
+       }
+
+        if (server->state != CONN_VALID)
+                return -EIO;
+               
+        if ((result = smb_dont_catch_keepalive(server)) != 0) {
+                server->state = CONN_INVALID;
+                smb_invalidate_all_inodes(server);
+                return result;
+        }
+
+        len = smb_len(buffer) + 4;
+
+       old_mask = current->blocked;
+       current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
+       fs = get_fs();
+       set_fs(get_ds());
+
+        DPRINTK("smb_request_read_raw: len = %d cmd = 0x%X\n",
+                len, buffer[8]);
+        DPRINTK("smb_request_read_raw: target=%X, max_len=%d\n",
+                (unsigned int)target, max_len);
+        DPRINTK("smb_request_read_raw: buffer=%X, sock=%X\n",
+                (unsigned int)buffer, (unsigned int)sock);
+
+        result = sock->ops->send(sock, (void *)buffer, len, 0, 0);
+
+        DPRINTK("smb_request_read_raw: send returned %d\n", result);
+
+       set_fs(fs);             /* We recv into user space */
+
+        if (result < 0) {
+                printk("smb_request_read_raw: send error = %d\n", result);
+        }
+        else {
+                result = smb_receive_raw(sock, target, max_len, 0);
+        }
+
+        /* read/write errors are handled by errno */
+        current->signal &= ~_S(SIGPIPE);
+       current->blocked = old_mask;
+
+        if ((result2 = smb_catch_keepalive(server)) < 0) {
+                result = result2;
+        }
+
+        if (result < 0) {
+                server->state = CONN_INVALID;
+                smb_invalidate_all_inodes(server);
+        }
+        
+        DPRINTK("smb_request_read_raw: result = %d\n", result);
+
+       return result;
+}
+
+/* Source must be in user space. smb_request_write_raw assumes that
+ * the request SMBwriteBraw has been completed successfully, so that
+ * we can send the raw data now.  */
+int
+smb_request_write_raw(struct smb_server *server,
+                      unsigned const char *source, int length)
+{
+       unsigned long old_mask;
+       int result, result2;
+       unsigned short fs;      /* We fool the kernel to believe
+                                   we call from user space. */
+        byte nb_header[4];
+
+       struct socket *sock = server_sock(server);
+       unsigned char *buffer = (server == NULL) ? NULL : server->packet;
+
+       if ((sock == NULL) || (buffer == NULL)) {
+                printk("smb_request_write_raw: Bad server!\n");
+               return -EBADF;
+       }
+
+        if (server->state != CONN_VALID)
+                return -EIO;
+               
+        if ((result = smb_dont_catch_keepalive(server)) != 0) {
+                server->state = CONN_INVALID;
+                smb_invalidate_all_inodes(server);
+                return result;
+        }
+
+       old_mask = current->blocked;
+       current->blocked |= ~(_S(SIGKILL) | _S(SIGSTOP));
+       fs = get_fs();
+       set_fs(get_ds());
+
+        smb_encode_smb_length(nb_header, length);
+
+        result = sock->ops->send(sock, (void *)nb_header, 4, 0, 0);
+
+        if (result == 4) {
+                set_fs(fs);     /* source is in user-land */
+                result = sock->ops->send(sock, (void *)source, length, 0, 0);
+                set_fs(get_ds());
+        } else {
+                result = -EIO;
+        }
+
+        DPRINTK("smb_request_write_raw: send returned %d\n", result);
+
+        if (result == length) {
+                result = smb_receive(server, sock);
+        } else {
+                result = -EIO;
+        }
+
+        /* read/write errors are handled by errno */
+        current->signal &= ~_S(SIGPIPE);
+       current->blocked = old_mask;
+       set_fs(fs);
+
+        if ((result2 = smb_catch_keepalive(server)) < 0) {
+                result = result2;
+        }
+
+        if (result < 0) {
+                server->state = CONN_INVALID;
+                smb_invalidate_all_inodes(server);
+        }
+
+        if (result > 0) {
+                result = length;
+        }
+        
+        DPRINTK("smb_request_write_raw: result = %d\n", result);
+
+       return result;
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index 8170facfea50bc1214d178d1797b53fd4444ec98..d93a2a773226b2795e47adeb93b4a85b21ce9441 100644 (file)
@@ -496,6 +496,25 @@ __asm__ __volatile__(
 return (s);    
 }
 
+/* Added by Gertjan van Wingerde to make minix and sysv module work */
+#define __HAVE_ARCH_STRNLEN
+extern inline size_t strnlen(const char * s, size_t count)
+{
+register int __res;
+__asm__ __volatile__(
+       "movl %1,%0\n\t"
+       "jmp 2f\n"
+       "1:\tcmpb $0,(%0)\n\t"
+       "je 3f\n\t"
+       "incl %0\n"
+       "2:\tdecl %2\n\t"
+       "cmpl $-1,%2\n\t"
+       "jne 1b\n"
+       "3:\tsubl %1,%0"
+       :"=a" (__res):"c" (s),"d" (count));
+return __res;
+}
+/* end of additional stuff */
 
 /*
  * This looks horribly ugly, but the compiler can optimize it totally,
index 6f293d9f37f173a737b19a311cf9ca084d7b5958..06f83388196cc41d9f902b1ba3ab61a455d31e6a 100644 (file)
 #define __NR_getdents          141
 #define __NR__newselect                142
 #define __NR_flock             143
+#define __NR_msync             144
 
 /* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
 #define _syscall0(type,name) \
index 7abd7d14fc532e10a026ef0e8992b45c0676bcef..d6b0b5967cf51b9ed92a58e9e63bfb88ef8dbc88 100644 (file)
 #define WIN_DOORLOCK           0xde    /* lock door on removeable drives */
 #define WIN_DOORUNLOCK         0xdf    /* unlock door on removeable drives */
 
-#define WIN_PIDENTIFY          0xA1    /* identify ATA-PI device       */
-#define WIN_MULTREAD           0xC4    /* read multiple sectors        */
-#define WIN_MULTWRITE          0xC5    /* write multiple sectors       */
-#define WIN_SETMULT            0xC6    /* enable read multiple         */
+#define WIN_MULTREAD           0xC4    /* read sectors using multiple mode */
+#define WIN_MULTWRITE          0xC5    /* write sectors using multiple mode */
+#define WIN_SETMULT            0xC6    /* enable/disable multiple mode */
 #define WIN_IDENTIFY           0xEC    /* ask drive to identify itself */
-#define WIN_SETFEATURES                0xEF    /* set special drive features   */
+#define WIN_SETFEATURES                0xEF    /* set special drive features */
+#define WIN_READDMA            0xc8    /* read sectors using DMA transfers */
+#define WIN_WRITEDMA           0xca    /* write sectors using DMA transfers */
+
+/* Additional drive command codes used by ATAPI devices. */
+#define WIN_PIDENTIFY          0xA1    /* identify ATAPI device        */
+#define WIN_SRST               0x08    /* ATAPI soft reset command */
+#define WIN_PACKETCMD          0xa0    /* Send a packet command. */
 
 /* Bits for HD_ERROR */
 #define MARK_ERR       0x01    /* Bad address mark */
@@ -80,13 +86,13 @@ struct hd_geometry {
 
 /* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x30n/0x31n */
 #define HDIO_GETGEO            0x301   /* get device geometry */
-#define HDIO_REQ               HDIO_GETGEO     /* obsolete, use HDIO_GETGEO */
 #define HDIO_GET_UNMASKINTR    0x302   /* get current unmask setting */
 #define HDIO_GET_MULTCOUNT     0x304   /* get current IDE blockmode setting */
 #define HDIO_GET_IDENTITY      0x307   /* get IDE identification info */
 #define HDIO_GET_KEEPSETTINGS  0x308   /* get keep-settings-on-reset flag */
 #define HDIO_GET_CHIPSET       0x309   /* get current interface type setting */
-#define HDIO_GET_NOWERR        0x30a   /* get ignore-write-error flag */
+#define HDIO_GET_NOWERR                0x30a   /* get ignore-write-error flag */
+#define HDIO_GET_DMA           0x30b   /* get use-dma flag */
 #define HDIO_DRIVE_CMD         0x31f   /* execute a special drive command */
 
 /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x32n/0x33n */
@@ -94,7 +100,8 @@ struct hd_geometry {
 #define HDIO_SET_UNMASKINTR    0x322   /* permit other irqs during I/O */
 #define HDIO_SET_KEEPSETTINGS  0x323   /* keep ioctl settings on reset */
 #define HDIO_SET_CHIPSET       0x324   /* optimise driver for interface type */
-#define HDIO_SET_NOWERR        0x325   /* set ignore-write-error flag */
+#define HDIO_SET_NOWERR                0x325   /* set ignore-write-error flag */
+#define HDIO_SET_DMA           0x326   /* set use-dma flag */
 
 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
 struct hd_driveid {
index 75f86b6163007ffc992530cb18822ca22ce56450..0b7dd484214d3b80998355399763b7dd2496472d 100644 (file)
@@ -28,7 +28,7 @@
 #define        ARPHRD_AX25     3               /* AX.25 Level 2                */
 #define        ARPHRD_PRONET   4               /* PROnet token ring            */
 #define        ARPHRD_CHAOS    5               /* Chaosnet                     */
-#define        ARPHRD_IEEE802  6               /* IEEE 802.2 Ethernet- huh?    */
+#define        ARPHRD_IEEE802  6               /* IEEE 802.2 Ethernet/TR/TB    */
 #define        ARPHRD_ARCNET   7               /* ARCnet                       */
 #define        ARPHRD_APPLETLK 8               /* APPLEtalk                    */
 /* Dummy types for non ARP hardware */
@@ -40,6 +40,7 @@
 #define ARPHRD_ADAPT   264
 #define ARPHRD_PPP     512
 #define ARPHRD_TUNNEL  768             /* IPIP tunnel                  */
+#define ARPHRD_TUNNEL6 769             /* IPIP6 tunnel                 */
 
 /* ARP protocol opcodes. */
 #define        ARPOP_REQUEST   1               /* ARP request                  */
index f4511f2c1326a9ce9c9cf2590ec7b286c7b24891..305556b0a96a82a809016ce1869f6991aac0776a 100644 (file)
@@ -49,6 +49,7 @@
 #define ETH_P_ATALK    0x809B          /* Appletalk DDP                */
 #define ETH_P_AARP     0x80F3          /* Appletalk AARP               */
 #define ETH_P_IPX      0x8137          /* IPX over DIX                 */
+#define ETH_P_IPV6     0x86DD          /* IPv6 over bluebook           */
 #define ETH_P_802_3    0x0001          /* Dummy type for 802.3 frames  */
 #define ETH_P_AX25     0x0002          /* Dummy protocol id for AX.25  */
 #define ETH_P_ALL      0x0003          /* Every packet (be careful!!!) */
index 499a9c8046e1492ce4371831e400cb7951e633fd..c8e156e878cf0b2c37e190a25e031a8c5aeb7534 100644 (file)
@@ -127,4 +127,23 @@ struct sockaddr_in {
 
 #endif
 
+/*
+ *     IPv6 definitions as we start to include them. This is just
+ *     a beginning dont get excited 8)
+ */
+struct in_addr6
+{
+       unsigned char s6_addr[16];
+};
+
+struct sockaddr_in6
+{
+       unsigned short sin6_family;
+       unsigned short sin6_port;
+       unsigned long sin6_flowinfo;
+       struct in_addr6 sin6_addr;
+};
+
+
 #endif /* _LINUX_IN_H */
index 24ae6f4ed974945f0fc300ffcb8d5b818d9f06b4..3f7e00f95e84521a4107c0669a7a46872f8a3e62 100644 (file)
@@ -95,13 +95,13 @@ struct vm_operations_struct {
        void (*close)(struct vm_area_struct * area);
        void (*unmap)(struct vm_area_struct *area, unsigned long, size_t);
        void (*protect)(struct vm_area_struct *area, unsigned long, size_t, unsigned int newprot);
-       void (*sync)(struct vm_area_struct *area, unsigned long, size_t, unsigned int flags);
+       int (*sync)(struct vm_area_struct *area, unsigned long, size_t, unsigned int flags);
        void (*advise)(struct vm_area_struct *area, unsigned long, size_t, unsigned int advise);
        unsigned long (*nopage)(struct vm_area_struct * area, unsigned long address,
                unsigned long page, int write_access);
        unsigned long (*wppage)(struct vm_area_struct * area, unsigned long address,
                unsigned long page);
-       void (*swapout)(struct vm_area_struct *,  unsigned long, pte_t *);
+       int (*swapout)(struct vm_area_struct *,  unsigned long, pte_t *);
        pte_t (*swapin)(struct vm_area_struct *, unsigned long, unsigned long);
 };
 
index a36bf866bfd141f598d70d2e39ebe5cda1876877..be1e6505f814a3f6e8d53eb45ecd3e326f17cced 100644 (file)
@@ -363,6 +363,7 @@ extern __inline__ void skb_trim(struct sk_buff *skb, int len)
 extern struct sk_buff *                skb_recv_datagram(struct sock *sk,unsigned flags,int noblock, int *err);
 extern int                     datagram_select(struct sock *sk, int sel_type, select_table *wait);
 extern void                    skb_copy_datagram(struct sk_buff *from, int offset, char *to,int size);
+extern void                    skb_copy_datagram_iovec(struct sk_buff *from, int offset, struct iovec *to,int size);
 extern void                    skb_free_datagram(struct sk_buff *skb);
 
 #endif /* __KERNEL__ */
index 822dc674ce62024f7d8558def89fc396ea59b76d..382ae83d3bd320ab9be9249ba529c3ba2cd30d39 100644 (file)
@@ -124,13 +124,18 @@ int smb_conn_is_valid(struct smb_server *server);
 
 /* linux/fs/smbfs/proc.c */
 dword smb_len(unsigned char *packet);
+byte *smb_encode_smb_length(byte *p, dword len);
 int smb_proc_open(struct smb_server *server, const char *pathname,
                   int len, struct smb_dirent *entry);
 int smb_proc_close(struct smb_server *server, struct smb_dirent *finfo);
 int smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, 
                  off_t offset, long count, char *data, int fs);
+int smb_proc_read_raw(struct smb_server *server, struct smb_dirent *finfo, 
+                      off_t offset, long count, char *data);
 int smb_proc_write(struct smb_server *server, struct smb_dirent *finfo,
                   off_t offset, int count, const char *data);
+int smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, 
+                       off_t offset, long count, const char *data);
 int smb_proc_create(struct smb_server *server, const char *path,
                     int len, struct smb_dirent *entry);
 int smb_proc_mknew(struct smb_server *server, const char *path, int len,
@@ -161,6 +166,10 @@ int smb_proc_trunc(struct smb_server *server, word fid, dword length);
 int smb_release(struct smb_server *server);
 int smb_connect(struct smb_server *server);
 int smb_request(struct smb_server *server);
+int smb_request_read_raw(struct smb_server *server,
+                         unsigned char *target, int max_len);
+int smb_request_write_raw(struct smb_server *server,
+                          unsigned const char *source, int length);
 int smb_catch_keepalive(struct smb_server *server);
 int smb_dont_catch_keepalive(struct smb_server *server);
 int smb_trans2_request(struct smb_server *server,
index a0efebca6736344012ec12762eae2181fa52909d..d98bf6981c01b927d4cd1e0b77b894425a55f9b2 100644 (file)
@@ -48,6 +48,7 @@ struct msghdr
 #define AF_BRIDGE      7       /* Multiprotocol bridge         */
 #define AF_AAL5                8       /* Reserved for Werner's ATM    */
 #define AF_X25         9       /* Reserved for X.25 project    */
+#define AF_INET6       10      /* IP version 6                 */
 #define AF_MAX         12      /* For now.. */
 
 /* Protocol families, same as address families. */
@@ -61,6 +62,7 @@ struct msghdr
 #define PF_BRIDGE      AF_BRIDGE
 #define PF_AAL5                AF_AAL5
 #define PF_X25         AF_X25
+#define PF_INET6       AF_INET6
 
 #define PF_MAX         AF_MAX
 
index 8f93519fcdf8551bf85f158ab80f6c4672d2ece8..1870011754273ffdcbb220a4578278b3f537d7b5 100644 (file)
@@ -90,7 +90,7 @@ struct nr_neigh {
 extern struct nr_parms_struct nr_default;
 extern int  nr_rx_frame(struct sk_buff *, struct device *);
 extern void nr_destroy_socket(struct sock *);
-extern int  nr_get_info(char *, char **, off_t, int, int);
+/*extern int  nr_get_info(char *, char **, off_t, int, int);*/
 
 /* nr_dev.c */
 extern int  nr_rx_ip(struct sk_buff *, struct device *);
index 059b1ee5d9a3b1fffa4ee15ae9f5ad4b29d50f83..3b08522090e7ab38826d1ab8e563b8b4641fc20c 100644 (file)
@@ -20,6 +20,8 @@ O_OBJS     += $(SYMTAB_OBJS)
 
 ifdef CONFIG_MODVERSIONS
 $(O_TARGET): $(SYMTAB_OBJS:.o=.ver)
+dep: $(SYMTAB_OBJS:.o=.ver)
+fastdep: $(SYMTAB_OBJS:.o=.ver)
 endif
 
 include $(TOPDIR)/Rules.make
index 9ec211cf74f8ab373418f3aeab388d2af877b08f..04134503f654b99a148d4bcfa85f809e6f0003ab 100644 (file)
@@ -1,7 +1,7 @@
 /*
- *     linux/mm/filemmap.c
+ *     linux/mm/filemap.c
  *
- * Copyright (C) 1994 Linus Torvalds
+ * Copyright (C) 1994, 1995  Linus Torvalds
  */
 
 /*
@@ -18,6 +18,8 @@
 #include <linux/mman.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
+#include <linux/fs.h>
+#include <linux/locks.h>
 
 #include <asm/segment.h>
 #include <asm/system.h>
 /*
  * Shared mappings implemented 30.11.1994. It's not fully working yet,
  * though.
+ *
+ * Shared mappings now work. 15.8.1995  Bruno.
  */
 
-static inline void multi_bmap(struct inode * inode, unsigned int block, unsigned int * nr, int shift)
+/*
+ * Simple routines for both non-shared and shared mappings.
+ */
+
+static inline void multi_bmap(struct inode * inode, unsigned long block, unsigned int * nr, int shift)
 {
        int i = PAGE_SIZE >> shift;
        block >>= shift;
@@ -51,23 +59,19 @@ static unsigned long filemap_nopage(struct vm_area_struct * area, unsigned long
        return bread_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize, no_share);
 }
 
+
 /*
- * NOTE! mmap sync doesn't really work yet. This is mainly a stub for it,
- * which only works if the buffers and the page were already sharing the
- * same physical page (that's actually pretty common, especially if the
- * file has been mmap'ed before being read the normal way).
- *
- * Todo:
- * - non-shared pages also need to be synced with the buffers.
- * - the "swapout()" function needs to swap out the page to
- *   the shared file instead of using the swap device.
+ * Tries to write a shared mapped page to its backing store. May return -EIO
+ * if the disk is full.
  */
-static void filemap_sync_page(struct vm_area_struct * vma,
+static int filemap_write_page(struct vm_area_struct * vma,
        unsigned long offset,
        unsigned long page)
 {
+       int old_fs;
+       unsigned long size, result;
+       struct file file;
        struct inode * inode;
-       int nr[PAGE_SIZE/512];
        struct buffer_head * bh;
 
        bh = buffer_pages[MAP_NR(page)];
@@ -78,14 +82,39 @@ static void filemap_sync_page(struct vm_area_struct * vma,
                        mark_buffer_dirty(tmp, 0);
                        tmp = tmp->b_this_page;
                } while (tmp != bh);
-               return;
+               return 0;
        }
+
        inode = vma->vm_inode;
-       offset += vma->vm_offset;
-       multi_bmap(inode, offset, nr, inode->i_sb->s_blocksize_bits);
-       bwrite_page(page, inode->i_dev, nr, inode->i_sb->s_blocksize);
+       file.f_op = inode->i_op->default_file_ops;
+       if (!file.f_op->write)
+               return -EIO;
+       size = offset + PAGE_SIZE;
+       /* refuse to extend file size.. */
+       if (S_ISREG(inode->i_mode)) {
+               if (size > inode->i_size)
+                       size = inode->i_size;
+               /* Ho humm.. We should have tested for this earlier */
+               if (size < offset)
+                       return -EIO;
+       }
+       size -= offset;
+       file.f_mode = 3;
+       file.f_flags = 0;
+       file.f_count = 1;
+       file.f_inode = inode;
+       file.f_pos = offset;
+       file.f_reada = 0;
+       old_fs = get_fs();
+       set_fs(KERNEL_DS);
+       result = file.f_op->write(inode, &file, (const char *) page, size);
+       set_fs(old_fs);
+       if (result != size)
+               return -EIO;
+       return 0;
 }
 
+
 /*
  * Swapping to a shared file: while we're busy writing out the page
  * (and the page still exists in memory), we save the page information
@@ -94,20 +123,22 @@ static void filemap_sync_page(struct vm_area_struct * vma,
  *
  * Once we've written it all out, we mark the page entry "empty", which
  * will result in a normal page-in (instead of a swap-in) from the now
- * up-to-date shared file mapping.
+ * up-to-date disk file.
  */
-void filemap_swapout(struct vm_area_struct * vma,
+int filemap_swapout(struct vm_area_struct * vma,
        unsigned long offset,
        pte_t *page_table)
 {
+       int error;
        unsigned long page = pte_page(*page_table);
        unsigned long entry = SWP_ENTRY(SHM_SWP_TYPE, MAP_NR(page));
 
        pte_val(*page_table) = entry;
        invalidate();
-       filemap_sync_page(vma, offset, page);
+       error = filemap_write_page(vma, offset, page);
        if (pte_val(*page_table) == entry)
                pte_clear(page_table);
+       return error;
 }
 
 /*
@@ -124,41 +155,58 @@ static pte_t filemap_swapin(struct vm_area_struct * vma,
 
        mem_map[page]++;
        page = (page << PAGE_SHIFT) + PAGE_OFFSET;
-       return pte_mkdirty(mk_pte(page,vma->vm_page_prot));
+       return mk_pte(page,vma->vm_page_prot);
 }
 
-static inline void filemap_sync_pte(pte_t * pte, struct vm_area_struct *vma,
+
+static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
        unsigned long address, unsigned int flags)
 {
-       pte_t page = *pte;
-
-       if (!pte_present(page))
-               return;
-       if (!pte_dirty(page))
-               return;
-       if (flags & MS_INVALIDATE) {
-               pte_clear(pte);
+       pte_t pte = *ptep;
+       unsigned long page;
+       int error;
+
+       if (!(flags & MS_INVALIDATE)) {
+               if (!pte_present(pte))
+                       return 0;
+               if (!pte_dirty(pte))
+                       return 0;
+               *ptep = pte_mkclean(pte);
+               page = pte_page(pte);
+               mem_map[MAP_NR(page)]++;
        } else {
-               mem_map[MAP_NR(pte_page(page))]++;
-               *pte = pte_mkclean(page);
+               if (pte_none(pte))
+                       return 0;
+               pte_clear(ptep);
+               if (!pte_present(pte)) {
+                       swap_free(pte_val(pte));
+                       return 0;
+               }
+               page = pte_page(pte);
+               if (!pte_dirty(pte) || flags == MS_INVALIDATE) {
+                       free_page(page);
+                       return 0;
+               }
        }
-       filemap_sync_page(vma, address - vma->vm_start, pte_page(page));
-       free_page(pte_page(page));
+       error = filemap_write_page(vma, address - vma->vm_start + vma->vm_offset, page);
+       free_page(page);
+       return error;
 }
 
-static inline void filemap_sync_pte_range(pmd_t * pmd,
+static inline int filemap_sync_pte_range(pmd_t * pmd,
        unsigned long address, unsigned long size, 
        struct vm_area_struct *vma, unsigned long offset, unsigned int flags)
 {
        pte_t * pte;
        unsigned long end;
+       int error;
 
        if (pmd_none(*pmd))
-               return;
+               return 0;
        if (pmd_bad(*pmd)) {
                printk("filemap_sync_pte_range: bad pmd (%08lx)\n", pmd_val(*pmd));
                pmd_clear(pmd);
-               return;
+               return 0;
        }
        pte = pte_offset(pmd, address);
        offset += address & PMD_MASK;
@@ -166,26 +214,29 @@ static inline void filemap_sync_pte_range(pmd_t * pmd,
        end = address + size;
        if (end > PMD_SIZE)
                end = PMD_SIZE;
+       error = 0;
        do {
-               filemap_sync_pte(pte, vma, address + offset, flags);
+               error |= filemap_sync_pte(pte, vma, address + offset, flags);
                address += PAGE_SIZE;
                pte++;
        } while (address < end);
+       return error;
 }
 
-static inline void filemap_sync_pmd_range(pgd_t * pgd,
+static inline int filemap_sync_pmd_range(pgd_t * pgd,
        unsigned long address, unsigned long size, 
        struct vm_area_struct *vma, unsigned int flags)
 {
        pmd_t * pmd;
        unsigned long offset, end;
+       int error;
 
        if (pgd_none(*pgd))
-               return;
+               return 0;
        if (pgd_bad(*pgd)) {
                printk("filemap_sync_pmd_range: bad pgd (%08lx)\n", pgd_val(*pgd));
                pgd_clear(pgd);
-               return;
+               return 0;
        }
        pmd = pmd_offset(pgd, address);
        offset = address & PMD_MASK;
@@ -193,31 +244,34 @@ static inline void filemap_sync_pmd_range(pgd_t * pgd,
        end = address + size;
        if (end > PGDIR_SIZE)
                end = PGDIR_SIZE;
+       error = 0;
        do {
-               filemap_sync_pte_range(pmd, address, end - address, vma, offset, flags);
+               error |= filemap_sync_pte_range(pmd, address, end - address, vma, offset, flags);
                address = (address + PMD_SIZE) & PMD_MASK;
                pmd++;
        } while (address < end);
+       return error;
 }
 
-static void filemap_sync(struct vm_area_struct * vma, unsigned long address,
+static int filemap_sync(struct vm_area_struct * vma, unsigned long address,
        size_t size, unsigned int flags)
 {
        pgd_t * dir;
        unsigned long end = address + size;
+       int error = 0;
 
        dir = pgd_offset(current, address);
        while (address < end) {
-               filemap_sync_pmd_range(dir, address, end - address, vma, flags);
+               error |= filemap_sync_pmd_range(dir, address, end - address, vma, flags);
                address = (address + PGDIR_SIZE) & PGDIR_MASK;
                dir++;
        }
        invalidate();
-       return;
+       return error;
 }
 
 /*
- * This handles area unmaps..
+ * This handles partial area unmaps..
  */
 static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
 {
@@ -251,9 +305,9 @@ static struct vm_operations_struct file_shared_mmap = {
 };
 
 /*
- * Private mappings just need to be able to load in the map
+ * Private mappings just need to be able to load in the map.
  *
- * (this is actually used for shared mappings as well, if we
+ * (This is actually used for shared mappings as well, if we
  * know they can't ever get write permissions..)
  */
 static struct vm_operations_struct file_private_mmap = {
@@ -274,17 +328,21 @@ int generic_mmap(struct inode * inode, struct file * file, struct vm_area_struct
 {
        struct vm_operations_struct * ops;
 
-       if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
-               return -EINVAL;
+       if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE)) {
+               ops = &file_shared_mmap;
+               /* share_page() can only guarantee proper page sharing if
+                * the offsets are all page aligned. */
+               if (vma->vm_offset & (PAGE_SIZE - 1))
+                       return -EINVAL;
+       } else {
+               ops = &file_private_mmap;
+               if (vma->vm_offset & (inode->i_sb->s_blocksize - 1))
+                       return -EINVAL;
+       }
        if (!inode->i_sb || !S_ISREG(inode->i_mode))
                return -EACCES;
        if (!inode->i_op || !inode->i_op->bmap)
                return -ENOEXEC;
-       ops = &file_private_mmap;
-       if (vma->vm_flags & VM_SHARED) {
-               if (vma->vm_flags & (VM_WRITE | VM_MAYWRITE))
-                       ops = &file_shared_mmap;
-       }
        if (!IS_RDONLY(inode)) {
                inode->i_atime = CURRENT_TIME;
                inode->i_dirt = 1;
@@ -294,3 +352,74 @@ int generic_mmap(struct inode * inode, struct file * file, struct vm_area_struct
        vma->vm_ops = ops;
        return 0;
 }
+
+
+/*
+ * The msync() system call.
+ */
+
+static int msync_interval(struct vm_area_struct * vma,
+       unsigned long start, unsigned long end, int flags)
+{
+       if (!vma->vm_inode)
+               return 0;
+       if (vma->vm_ops->sync) {
+               int error;
+               error = vma->vm_ops->sync(vma, start, end-start, flags);
+               if (error)
+                       return error;
+               if (flags & MS_SYNC)
+                       return file_fsync(vma->vm_inode, NULL);
+               return 0;
+       }
+       return 0;
+}
+
+asmlinkage int sys_msync(unsigned long start, size_t len, int flags)
+{
+       unsigned long end;
+       struct vm_area_struct * vma;
+       int unmapped_error, error;
+
+       if (start & ~PAGE_MASK)
+               return -EINVAL;
+       len = (len + ~PAGE_MASK) & PAGE_MASK;
+       end = start + len;
+       if (end < start)
+               return -EINVAL;
+       if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
+               return -EINVAL;
+       if (end == start)
+               return 0;
+       /*
+        * If the interval [start,end) covers some unmapped address ranges,
+        * just ignore them, but return -EFAULT at the end.
+        */
+       vma = find_vma(current, start);
+       unmapped_error = 0;
+       for (;;) {
+               /* Still start < end. */
+               if (!vma)
+                       return -EFAULT;
+               /* Here start < vma->vm_end. */
+               if (start < vma->vm_start) {
+                       unmapped_error = -EFAULT;
+                       start = vma->vm_start;
+               }
+               /* Here vma->vm_start <= start < vma->vm_end. */
+               if (end <= vma->vm_end) {
+                       if (start < end) {
+                               error = msync_interval(vma, start, end, flags);
+                               if (error)
+                                       return error;
+                       }
+                       return unmapped_error;
+               }
+               /* Here vma->vm_start <= start < vma->vm_end < end. */
+               error = msync_interval(vma, start, vma->vm_end, flags);
+               if (error)
+                       return error;
+               start = vma->vm_end;
+               vma = vma->vm_next;
+       }
+}
index 32f0b38cb483a0096ea5def5a11a50e2c54cfef5..0c6a82bc14d85477f9f180e9d6dd90547b5149ea 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -55,6 +55,13 @@ static struct swap_info_struct {
 
 extern int shm_swap (int, unsigned long);
 
+/*
+ * To save us from swapping out pages which have just been swapped in and
+ * have not been modified since then, we keep in swap_cache[page>>PAGE_SHIFT]
+ * the swap entry which was last used to fill the page, or zero if the
+ * page does not currently correspond to a page in swap. PAGE_DIRTY makes
+ * this info useless.
+ */
 unsigned long *swap_cache;
 
 #ifdef SWAP_CACHE_INFO
@@ -366,12 +373,14 @@ static inline int try_to_swap_out(struct vm_area_struct* vma, unsigned long addr
                return 0;
        }       
        if (pte_dirty(pte)) {
-               if (mem_map[MAP_NR(page)] != 1)
-                       return 0;
                if (vma->vm_ops && vma->vm_ops->swapout) {
+                       pid_t pid = vma->vm_task->pid;
                        vma->vm_task->mm->rss--;
-                       vma->vm_ops->swapout(vma, address-vma->vm_start, page_table);
+                       if (vma->vm_ops->swapout(vma, address - vma->vm_start + vma->vm_offset, page_table))
+                               kill_proc(pid, SIGBUS, 1);
                } else {
+                       if (mem_map[MAP_NR(page)] != 1)
+                               return 0;
                        if (!(entry = get_swap_page()))
                                return 0;
                        vma->vm_task->mm->rss--;
index 61c42830b20e2edbfa9262a9657c025f4fb9b842..adb4fc5edd027c8190379ce50439fb907add9f7d 100644 (file)
@@ -140,9 +140,9 @@ o   TCP does rerouting for most cases               [TESTED]
 
 ------->>>>>    1.3.14  <<<<<----------
 
-o      IPX works                                       [IN]
-o      NetROM works                                    [IN]
-o      AX.25 works                                     [IN]
+o      IPX works                                       [TESTED]
+o      NetROM works                                    [TESTED]
+o      AX.25 works                                     [TESTED]
 o      Most modules need recompiling even though they
        load OK                                         [BLAME LINUS]
 o      Appletalk works nicely                          [CHECKED]
@@ -150,14 +150,14 @@ o Fast IP forwarding part 1 works                 [CHECKED]
 
 ------->>>>>   1.3.15  <<<<<---------
 o      Mike Shaver has started RFC1122 verification    [IN PROGRESS]
-o      Minor bug fixes                                 [IN]
+o      Minor bug fixes                                 [TESTED]
 
 ------->>>> 1.3.16 <<<--------
 
 o      Missing patches for device change in TCP        [TESTED]
 o      Device locking                                  [TESTED]
-o      Infinite slip devices                           [IN]
-o      New AF_UNIX sockets                             [IN]
+o      Infinite slip devices                           [IN - BUG]
+o      New AF_UNIX sockets                             [TESTED]
 o      Sendmsg/recvmsg (for some stuff only)           [IN]
 o      Device unload loopholes fixed                   [TESTED]
 o      Extra firewall abilities                        [IN]
@@ -165,11 +165,17 @@ o Appletalk node probe bug fix                    [TESTED]
 
 ------->>>> 1.3.18 <<<<---------
 
-o      AF_UNIX debugging                               [IN]
-o      TCP explode on SWS bug fix                      [IN]
-o      John Naylor's ARP hwtype fix                    [IN]
-o      Datagram select matches BSD semantics           [IN]
+o      AF_UNIX debugging                               [TESTED]
+o      TCP explode on SWS bug fix                      [TESTED]
+o      John Naylor's ARP hwtype fix                    [TESTED]
+o      Datagram select matches BSD semantics           [TESTED]
 
+-------->>>>> 1.3.21 <<<<<---------
+
+o      AF_UNIX fixes and 4K limiter                    [IN]
+o      Sendmsg/recvmsg for AX.25/Appletalk             [IN]
+o      Datagram generic iovec support                  [IN]
+o      Misc minor bug fixes                            [IN]
 
 o      Finish merging the bridge code
 o      SIOCSLEEPRT patch
@@ -177,7 +183,7 @@ o   Options support in ip_build_xmit                [PENDING]
 o      Fast checksum/copy on outgoing TCP
 o      Fast dev_grab_next() transmit reload function
        and dev_push_failed() ??
-o      Faster ip_forward last hit cache                [PENDING]
+o      Faster ip_forward last hit cache                [PENDING(GuruA0)]
 o      Forwarding queue control (+ fairness algorithms ??)
 o      IP forward flow control.
 o      Infinite PPP devices.
@@ -186,6 +192,10 @@ o  Clean up RAW AX.25 sockets.
 o      Finish 802.2 Class I code to be compliant to the oddities of 802.2
 o      Full variable length AX.25 support              [JSN doing]
 o      Tidy BPQ support
+o      Strange eth0-eth3 bug 
+o      Finish IPIP bug fixes
+o      Why doesnt the PROTO_UNREACH get sent ?
+
 
 0.2
 ---
@@ -282,9 +292,10 @@ their hands. [Provisionally taken]
 17.    PPP multilink. Another nasty job.
 
 18.    Implement swIPe under Linux.
-[In progress]
+[Reportedly in progress]
 
 19.    IPv4 IP-AH and IP-ESP.
+[Taken]
 
 BTW: Don't let the magic words 'kernel programming' worry you. Its like DOS
 - you make a mistake you have to reboot. You do at least get dumps and a
index 6449de7d49ace3ac302f8a6524c1b1191719e767..5822d72d5ca19c36f0670b8244ab0e6fed0a88cc 100644 (file)
@@ -13,6 +13,7 @@
  *             Michael Callahan        :       Made routing work
  *             Wesley Craig            :       Fix probing to listen to a
  *                                             passed node id.
+ *             Alan Cox                :       Added send/recvmsg support
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -1466,11 +1467,10 @@ int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        return(0);
 }
 
-static int atalk_sendto(struct socket *sock, const void *ubuf, int len, int noblock,
-       unsigned flags, struct sockaddr *sat, int addr_len)
+static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
 {
        atalk_socket *sk=(atalk_socket *)sock->data;
-       struct sockaddr_at *usat=(struct sockaddr_at *)sat;
+       struct sockaddr_at *usat=(struct sockaddr_at *)msg->msg_name;
        struct sockaddr_at local_satalk, gsat;
        struct sk_buff *skb;
        struct device *dev;
@@ -1495,7 +1495,7 @@ static int atalk_sendto(struct socket *sock, const void *ubuf, int len, int nobl
                                return -EBUSY;
                }
 
-               if(addr_len <sizeof(*usat))
+               if(msg->msg_namelen <sizeof(*usat))
                        return(-EINVAL);
                if(usat->sat_family != AF_APPLETALK)
                        return -EINVAL;
@@ -1581,7 +1581,7 @@ static int atalk_sendto(struct socket *sock, const void *ubuf, int len, int nobl
        if(sk->debug)
                printk("SK %p: Copy user data (%d bytes).\n", sk, len);
                
-       memcpy_fromfs(skb_put(skb,len),ubuf,len);
+       memcpy_fromiovec(skb_put(skb,len),msg->msg_iov,len);
 
        if(sk->no_check==1)
                ddp->deh_sum=0;
@@ -1643,16 +1643,32 @@ static int atalk_sendto(struct socket *sock, const void *ubuf, int len, int nobl
        return len;
 }
 
+
+static int atalk_sendto(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags,
+               struct sockaddr *sa, int addr_len)
+{
+       struct iovec iov;
+       struct msghdr msg;
+       iov.iov_base=(void *)ubuf;
+       iov.iov_len=size;
+       msg.msg_name=(void *)sa;
+       msg.msg_namelen=addr_len;
+       msg.msg_accrights=NULL;
+       msg.msg_iov=&iov;
+       msg.msg_iovlen=1;
+       return atalk_sendmsg(sock,&msg,size,noblock,flags);     
+}
+
+
 static int atalk_send(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags)
 {
        return atalk_sendto(sock,ubuf,size,noblock,flags,NULL,0);
 }
 
-static int atalk_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
-                  unsigned flags, struct sockaddr *sip, int *addr_len)
+static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
 {
        atalk_socket *sk=(atalk_socket *)sock->data;
-       struct sockaddr_at *sat=(struct sockaddr_at *)sip;
+       struct sockaddr_at *sat=(struct sockaddr_at *)msg->msg_name;
        struct ddpehdr  *ddp = NULL;
        int copied = 0;
        struct sk_buff *skb;
@@ -1678,14 +1694,14 @@ static int atalk_recvfrom(struct socket *sock, void *ubuf, int size, int noblock
                copied=ddp->deh_len;
                if(copied > size)
                        copied=size;
-               skb_copy_datagram(skb,0,ubuf,copied);
+               skb_copy_datagram_iovec(skb,0,msg->msg_iov,copied);
        }
        else
        {
                copied=ddp->deh_len - sizeof(*ddp);
                if (copied > size)
                        copied = size;
-               skb_copy_datagram(skb,sizeof(*ddp),ubuf,copied);
+               skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
        }
        if(sat)
        {
@@ -1705,6 +1721,23 @@ static int atalk_write(struct socket *sock, const char *ubuf, int size, int nobl
 }
 
 
+static int atalk_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags,
+               struct sockaddr *sa, int *addr_len)
+{
+       struct iovec iov;
+       struct msghdr msg;
+       iov.iov_base=ubuf;
+       iov.iov_len=size;
+       msg.msg_name=(void *)sa;
+       msg.msg_namelen=0;
+       if (addr_len)
+               msg.msg_namelen = *addr_len;
+       msg.msg_accrights=NULL;
+       msg.msg_iov=&iov;
+       msg.msg_iovlen=1;
+       return atalk_recvmsg(sock,&msg,size,noblock,flags,addr_len);    
+}
+
 static int atalk_recv(struct socket *sock, void *ubuf, int size , int noblock,
        unsigned flags)
 {
@@ -1848,6 +1881,8 @@ static struct proto_ops atalk_proto_ops = {
        atalk_setsockopt,
        atalk_getsockopt,
        atalk_fcntl,
+       atalk_sendmsg,
+       atalk_recvmsg
 };
 
 static struct notifier_block ddp_notifier={
@@ -1886,6 +1921,6 @@ void atalk_proto_init(struct net_proto *pro)
                atalk_if_get_info
        });
 
-       printk("Appletalk BETA 0.11 for Linux NET3.030\n");
+       printk("Appletalk BETA 0.12 for Linux NET3.030\n");
 }
 #endif
index 11a1448ab9db9c0e7f2e6f771832c4f8bb931954..942bb62ccbd953eb6d175b94a0dd026d23c9f76c 100644 (file)
@@ -1630,12 +1630,11 @@ static int bpq_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *
        return ax25_rcv(skb, dev, &port_call, ptype);
 }
 
-static int ax25_sendto(struct socket *sock, const void *ubuf, int len, int noblock,
-       unsigned flags, struct sockaddr *usip, int addr_len)
+static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int noblock, int flags)
 {
        struct sock *sk = (struct sock *)sock->data;
-       struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)usip;
-       unsigned char *uaddr = (unsigned char *)usip;
+       struct sockaddr_ax25 *usax = (struct sockaddr_ax25 *)msg->msg_name;
+       unsigned char *uaddr = (unsigned char *)msg->msg_name;
        int err;
        struct sockaddr_ax25 sax;
        struct sk_buff *skb;
@@ -1644,14 +1643,17 @@ static int ax25_sendto(struct socket *sock, const void *ubuf, int len, int noblo
        ax25_digi *dp;
        ax25_digi dtmp;
        int lv;
+       int addr_len=msg->msg_namelen;
        
        if (sk->err) {
+               cli();
                err     = sk->err;
                sk->err = 0;
+               sti();
                return -err;
        }
 
-       if (flags)
+       if (flags|| msg->msg_accrights)
                return -EINVAL;
 
        if (sk->zapped)
@@ -1731,7 +1733,7 @@ static int ax25_sendto(struct socket *sock, const void *ubuf, int len, int noblo
                printk("AX.25: Appending user data\n");
 
        /* User data follows immediately after the AX.25 data */
-       memcpy_fromfs(skb_put(skb, len), ubuf, len);
+       memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
 
        /* Add the PID, usually AX25_TEXT */
        asmptr  = skb_push(skb, 1);
@@ -1780,6 +1782,22 @@ static int ax25_sendto(struct socket *sock, const void *ubuf, int len, int noblo
                
 }
 
+static int ax25_sendto(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags,
+               struct sockaddr *sa, int addr_len)
+{
+       struct iovec iov;
+       struct msghdr msg;
+       iov.iov_base=(void *)ubuf;
+       iov.iov_len=size;
+       msg.msg_name=(void *)sa;
+       msg.msg_namelen=addr_len;
+       msg.msg_accrights=NULL;
+       msg.msg_iov=&iov;
+       msg.msg_iovlen=1;
+       return ax25_sendmsg(sock,&msg,size,noblock,flags);      
+}
+
+
 static int ax25_send(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags)
 {
        return ax25_sendto(sock, ubuf, size, noblock, flags, NULL, 0);
@@ -1787,22 +1805,23 @@ static int ax25_send(struct socket *sock, const void *ubuf, int size, int nobloc
 
 static int ax25_write(struct socket *sock, const char *ubuf, int size, int noblock)
 {
-       return ax25_send(sock, ubuf, size, noblock, 0);
+       return ax25_sendto(sock, ubuf, size, noblock, 0, NULL, 0);
 }
 
-static int ax25_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
-                  unsigned flags, struct sockaddr *sip, int *addr_len)
+static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
 {
        struct sock *sk = (struct sock *)sock->data;
-       struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)sip;
-       char *addrptr = (char *)sip;
+       struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
+       char *addrptr = (char *)msg->msg_name;
        int copied, length;
        struct sk_buff *skb;
        int er;
 
        if (sk->err) {
+               cli();
                er      = -sk->err;
                sk->err = 0;
+               sti();
                return er;
        }
        
@@ -1830,7 +1849,7 @@ static int ax25_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
        }
 
        copied = (size < length) ? size : length;
-       skb_copy_datagram(skb, 0, ubuf, copied);
+       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
        
        if (sax) {
                struct sockaddr_ax25 addr;
@@ -1859,6 +1878,23 @@ static int ax25_recvfrom(struct socket *sock, void *ubuf, int size, int noblock,
        return copied;
 }              
 
+static int ax25_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags,
+               struct sockaddr *sa, int *addr_len)
+{
+       struct iovec iov;
+       struct msghdr msg;
+       iov.iov_base=ubuf;
+       iov.iov_len=size;
+       msg.msg_name=(void *)sa;
+       msg.msg_namelen=0;
+       if (addr_len)
+               msg.msg_namelen = *addr_len;
+       msg.msg_accrights=NULL;
+       msg.msg_iov=&iov;
+       msg.msg_iovlen=1;
+       return ax25_recvmsg(sock,&msg,size,noblock,flags,addr_len);     
+}
+
 static int ax25_recv(struct socket *sock, void *ubuf, int size , int noblock,
        unsigned flags)
 {
@@ -2076,6 +2112,8 @@ static struct proto_ops ax25_proto_ops = {
        ax25_setsockopt,
        ax25_getsockopt,
        ax25_fcntl,
+       ax25_sendmsg,
+       ax25_recvmsg
 };
 
 /* Called by socket.c on kernel start up */
index 3570be78edf885a46b4c1e06edb1f7e548ec5744..7c98519f886a2d757a9a5e02a7571c13398a601d 100644 (file)
@@ -9,10 +9,10 @@
 
 O_TARGET := core.o
 
-O_OBJS :=
+O_OBJS := sock.o skbuff.o iovec.o datagram.o
 
 ifdef CONFIG_NET
-O_OBJS += sock.o dev.o dev_mcast.o iovec.o skbuff.o datagram.o
+O_OBJS += dev.o dev_mcast.o
 endif
 
 include $(TOPDIR)/Rules.make
index b61e0efd59a9940b5e799f30b81efbc11cbac57c..4dc47269eab9121cfcd899c217caa23c191ff097 100644 (file)
@@ -17,6 +17,7 @@
  *             Florian  La Roche:      Changed for my new skbuff handling.
  *             Darryl Miles    :       Fixed non-blocking SOCK_SEQPACKET.
  *             Linus Torvalds  :       BSD semantic fixes.
+ *             Alan Cox        :       Datagram iovec handling
  *
  *     Note:
  *             A lot of this will change when the protocol/socket separation
@@ -164,11 +165,25 @@ void skb_free_datagram(struct sk_buff *skb)
        restore_flags(flags);
 }
 
+/*
+ *     Copy a datagram to a linear buffer.
+ */
+
 void skb_copy_datagram(struct sk_buff *skb, int offset, char *to, int size)
 {
        memcpy_tofs(to,skb->h.raw+offset,size);
 }
 
+
+/*
+ *     Copy a datagram to an iovec.
+ */
+void skb_copy_datagram_iovec(struct sk_buff *skb, int offset, struct iovec *to, int size)
+{
+       memcpy_toiovec(to,skb->h.raw+offset,size);
+}
+
 /*
  *     Datagram select: Again totally generic. Moved from udp.c
  *     Now does seqpacket.
index c5c3c3ade971d68ff9446d3ebd19ee605ac2f2fe..225e1f09f50f5434f6757c38ad16ae6e9024aa30 100644 (file)
@@ -64,9 +64,10 @@ void memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
 {
        while(len>0)
        {
-               memcpy_tofs(iov->iov_base, kdata,iov->iov_len);
-               kdata+=iov->iov_len;
-               len-=iov->iov_len;
+               int copy = min(iov->iov_len,len);
+               memcpy_tofs(iov->iov_base,kdata,copy);
+               kdata+=copy;
+               len-=copy;
                iov++;
        }
 }
index 30a2bba551b379ae0f31b41c60ce63e27ea73e21..4a9c16a1c5db9fe680355d2fe903221f7557e191 100644 (file)
@@ -95,7 +95,7 @@ extern int afinet_get_info(char *, char **, off_t, int, int);
 extern int tcp_get_info(char *, char **, off_t, int, int);
 extern int udp_get_info(char *, char **, off_t, int, int);
 
-int (*rarp_ioctl_hook)(int,void*) = NULL;
+int (*rarp_ioctl_hook)(unsigned int,void*) = NULL;
 
 /*
  *     See if a socket number is in use.
index 4b63a900901237e3eb8bec21cbcd6c6811d58e3d..7ddbc46837e3f51d162b2830ff4a63483bff0da5 100644 (file)
@@ -691,7 +691,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
  *     Check for bad requests for 127.x.x.x and requests for multicast
  *     addresses.  If this is one such, delete it.
  */
-       if (IN_LOOPBACK(tip) || IN_MULTICAST(tip))
+       if (LOOPBACK(tip) || MULTICAST(tip))
        {
                kfree_skb(skb, FREE_READ);
                return 0;
index 11bc14f30bfb13cf646b20ae3191a80e90e3a8a7..d5364dde7373b517eb39f605c7be4e6570f500b8 100644 (file)
      (OK... we don't use it)
    MUST discard received REPLYs if not using this system (OK)
    MUST NOT send replies unless specifically made agent for this sort
-     of thing. (NOT YET)
+     of thing. (OK)
 */
 
 #include <linux/types.h>
index a2398e32e44fa7f8e06b4262b0580705a019b129..6deb43646a7fe0a931e211dce2a27876a3cce5d5 100644 (file)
@@ -205,6 +205,26 @@ static int ip_send(struct sk_buff *skb, unsigned long daddr, int len, struct dev
        return mac;
 }
 
+static int ip_send_room(struct sk_buff *skb, unsigned long daddr, int len, struct device *dev, unsigned long saddr)
+{
+       int mac = 0;
+
+       skb->dev = dev;
+       skb->arp = 1;
+       if (dev->hard_header)
+       {
+               skb_reserve(skb,MAX_HEADER);
+               mac = dev->hard_header(skb, dev, ETH_P_IP, NULL, NULL, len);
+               if (mac < 0)
+               {
+                       mac = -mac;
+                       skb->arp = 0;
+                       skb->raddr = daddr;     /* next routing address */
+               }
+       }
+       return mac;
+}
+
 int ip_id_count = 0;
 
 /*
@@ -287,7 +307,10 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
         *      Now build the MAC header.
         */
 
-       tmp = ip_send(skb, raddr, len, *dev, saddr);
+       if(type==IPPROTO_TCP)
+               tmp = ip_send_room(skb, raddr, len, *dev, saddr);
+       else
+               tmp = ip_send(skb, raddr, len, *dev, saddr);
 
        /*
         *      Book keeping
@@ -1300,6 +1323,15 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
        int err;
 #endif 
 
+#ifdef CONFIG_NET_IPV6
+       /* 
+        *      Intercept IPv6 frames. We dump ST-II and invalid types just below..
+        */
+        
+       if(iph->version == 6)
+               return ipv6_rcv(skb,dev,pt);
+#endif         
+
        ip_statistics.IpInReceives++;
 
        /*
@@ -1571,13 +1603,13 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
                {
                        struct sock *sknext=NULL;
                        struct sk_buff *skb1;
-                       raw_sk=get_sock_raw(raw_sk, hash,  iph->saddr, iph->daddr);
+                       raw_sk=get_sock_raw(raw_sk, iph->protocol,  iph->saddr, iph->daddr);
                        if(raw_sk)      /* Any raw sockets */
                        {
                                do
                                {
                                        /* Find the next */
-                                       sknext=get_sock_raw(raw_sk->next, hash, iph->saddr, iph->daddr);
+                                       sknext=get_sock_raw(raw_sk->next, iph->protocol, iph->saddr, iph->daddr);
                                        if(sknext)
                                                skb1=skb_clone(skb, GFP_ATOMIC);
                                        else
index 5ec5daef8d1b62a8829301c0866682044b45ba26..d960f2869baec349e6010689de7c1db62d99b2c1 100644 (file)
@@ -1502,7 +1502,7 @@ static int ip_fw_fwd_procinfo(char *buffer, char **start, off_t offset,
 #ifdef CONFIG_IP_MASQUERADE
 
 static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
-                             int length)
+                             int length, int unused)
 {
        off_t pos=0, begin=0;
        struct ip_masq *ms;
index 02ce3082715f3798660ffc7b846f15cc13c55f08..3a5aea847832618c2a37e9306a786de2b8040dfb 100644 (file)
@@ -886,7 +886,7 @@ void tcp_err(int err, unsigned char *header, unsigned long daddr,
         * until we time out, or the user gives up.
         */
 
-       if (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT) 
+       if (err < 13 && (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT))
        {
                if (sk->state == TCP_SYN_SENT) 
                {
index 826e44c7ffac5ea1fa51542e7173e46fd3ffe5f1..9dfb716a30e0d1d68e9167e5095db1f6f6b332f2 100644 (file)
@@ -189,7 +189,7 @@ void udp_err(int err, unsigned char *header, unsigned long daddr,
        /* 4.1.3.3. */
        /* After the comment above, that should be no surprise. */
 
-       if (icmp_err_convert[err & 0xff].fatal)
+       if (err < 13 && icmp_err_convert[err & 0xff].fatal)
        {
                sk->err = icmp_err_convert[err & 0xff].errno;
                sk->error_report(sk);
index fa7b098327aad1d0be6e017b6077e2e1aa9f7278..a8c57cdbccc06afd7b20dcb6f116fe7b1e00c36f 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/string.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
+#include <linux/stat.h>
 #include <net/ax25.h>
 #include <linux/inet.h>
 #include <linux/netdevice.h>
@@ -53,7 +54,7 @@
 #include <linux/proc_fs.h>
 #include <net/ip.h>
 #include <net/arp.h>
-
+#include <linux/if_arp.h>
 #include <linux/proc_fs.h>
 
 /************************************************************************\
@@ -1411,16 +1412,19 @@ void nr_proto_init(struct net_proto *pro)
        proc_net_register(&(struct proc_dir_entry) {
                PROC_NET_NR, 2, "nr",
                S_IFREG | S_IRUGO, 1, 0, 0,
+               0, &proc_net_inode_operations, 
                nr_get_info
        });
        proc_net_register(&(struct proc_dir_entry) {
                PROC_NET_NR_NEIGH, 8, "nr_neigh",
                S_IFREG | S_IRUGO, 1, 0, 0,
+               0, &proc_net_inode_operations, 
                nr_neigh_get_info
        });
        proc_net_register(&(struct proc_dir_entry) {
                PROC_NET_NR_NODES, 8, "nr_nodes",
                S_IFREG | S_IRUGO, 1, 0, 0,
+               0, &proc_net_inode_operations, 
                nr_nodes_get_info
        });
 }
index f1854739d8dc78a2924a4bde719b24f9ba05589f..683c39d8264dcb6b1b97c54fc0a8a79a5e794161 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <net/ip.h>
 #include <net/arp.h>
+#include <linux/if_arp.h>
 
 #include <net/ax25.h>
 #include <net/netrom.h>
index 1a1865d5e0faea0732e93f8fb99532022af7e391..37f3c4edce34a25441b632cbf1f10a7b4a995d3a 100644 (file)
@@ -5,8 +5,8 @@
  *
  *             Currently this contains all but the file descriptor passing code.
  *             Before that goes in the odd bugs in the iovec handlers need 
- *             fixing, and this bit testing. BSD fd passing is a trivial part
- *             of the exercise.
+ *             fixing, and this bit testing. BSD fd passing is not a trivial part
+ *             of the exercise it turns out. Anyone like writing garbage collectors.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -15,8 +15,9 @@
  *
  * Fixes:
  *             Linus Torvalds  :       Assorted bug cures.
- *             Niibe Yutaka    :       async I/O support
+ *             Niibe Yutaka    :       async I/O support.
  *             Carsten Paeth   :       PF_UNIX check, address fixes.
+ *             Alan Cox        :       Limit size of allocated blocks.
  */
 
 #include <linux/config.h>
@@ -681,7 +682,7 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
        if(sun==NULL)
        {
                if(sk->protinfo.af_unix.other==NULL)
-                       return -EINVAL;
+                       return -ENOTCONN;
        }
 
        /*
@@ -694,6 +695,13 @@ static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                if(sock->type==SOCK_DGRAM)
                        return -EMSGSIZE;
                len=(sk->sndbuf-sizeof(struct sk_buff))/2;
+               /*
+                *      Keep to page sized kmalloc()'s as various people
+                *      have suggested. Big mallocs stress the vm too
+                *      much.
+                */
+               if(len > 4000 && sock->type!=SOCK_DGRAM)
+                       len = 4000;
        }
         
        size=/*protocol_size(&proto_unix)+*/len;
@@ -1044,7 +1052,7 @@ static struct proto_ops unix_proto_ops = {
 
 void unix_proto_init(struct net_proto *pro)
 {
-       printk("NET3: Unix domain sockets 0.07 BETA for Linux NET3.030.\n");
+       printk("NET3: Unix domain sockets 0.09 BETA for Linux NET3.030.\n");
        sock_register(unix_proto_ops.family, &unix_proto_ops);
        proc_net_register(&(struct proc_dir_entry) {
                PROC_NET_UNIX,  4, "unix",
index 630d90444c4cbd24b9a483fb25d52f21d738bd73..a08dc29879b3ff0a94ceef6e9899f4bee4bdce87 100644 (file)
@@ -14,9 +14,8 @@ function fileExists(f,    TMP, dummy, result) {
                        return "Yes"
                } else {return ""}
        }
-       ERRNO=""
-       getline dummy < f
-       if(!length(ERRNO)) {
+       ERRNO = getline dummy < f
+       if(ERRNO >= 0) {
                close(f)
                return FILEHASH[f]="Yes"
        } else {
index 3c71e9a377f012401a2d17ba7f9893e193b1d39c..41aadcd6bc1eb1c591c0dca1ee0d12620eab4f37 100644 (file)
@@ -26,6 +26,6 @@ $(TOPINCL)/modversions.h: $(SYMTAB_OBJS:.o=.ver)
        do echo "#include <linux/modules/$${f}>"; done) \
        > $(TOPINCL)/modversions.h
 
-dep: $(TOPINCL)/modversions.h
+fastdep: $(TOPINCL)/modversions.h
 
 endif