diff -ur --new-file old/atm/.kernel new/atm/.kernel
--- old/atm/.kernel	Fri Jan 21 05:40:56 2000
+++ new/atm/.kernel	Mon Jan 31 11:34:39 2000
@@ -1,2 +1,2 @@
 # this file is used to control automated generation of differences
-2.3.40
+2.3.41
diff -ur --new-file old/atm/CHANGES new/atm/CHANGES
--- old/atm/CHANGES	Fri Jan 21 19:27:12 2000
+++ new/atm/CHANGES	Mon Jan 31 15:58:28 2000
@@ -1,3 +1,41 @@
+Version 0.65 to 0.66 (31-JAN-2000)
+====================
+
+Bug fixes
+---------
+
+ - atmsigd crashed on reception of as_accept, etc., because of inverted NULL
+   pointer test (reported by Kevin Vargo, Rui Prior, fixed by Julian Cable)
+ - fixed various SPARC build problems (by Christophe Lizzi)
+ - atmsigd insisted that calling party number is local in switch mode
+ - debug switch didn't initialize any ports
+ - net/atm/signaling.c:sigd_enq didn't properly zero the message, yielding
+   kernel pointers partially containing junk
+ - accept(2) didn't copy local ATM address to VCC descriptor (reported by
+   Pedro Brandao)
+ - ilmid/io.c didn't compile on SPARC (reported by Christophe Lizzi)
+ - usage.txt didn't define the %: macro, leaving garbage in usage.txt
+
+New features
+------------
+
+ - upgraded to 2.3.41
+ - Fore 200E driver now also works for SBA-200E (by Christophe Lizzi)
+
+Other changes
+-------------
+
+ - added various CREDITS entries
+ - changed TIOC{IN,OUT}Q to SIOC{IN,OUT}Q (no user space rebuild required;
+   the values are identical)
+ - added script atm/switch/tcp/mkfiles for automatic extraction of
+   configuration files
+ - atmsigd called ATM_GETLINKRATE "ATM_GETLINERATE" in complaints
+ - atmsigd tried to obtain link speed in switch mode, although it's not used
+ - Ambassador NIC: various files still had the wrong copyright/licensing text
+   (patch by Giuliano Procida)
+
+
 Version 0.64 to 0.65 (21-JAN-2000)
 ====================
 
diff -ur --new-file old/atm/README new/atm/README
--- old/atm/README	Fri Jan 21 05:41:15 2000
+++ new/atm/README	Mon Jan 31 14:55:27 2000
@@ -1,4 +1,4 @@
-ATM on Linux, release 0.65 (beta)         by Werner Almesberger, EPFL ICA
+ATM on Linux, release 0.66 (beta)         by Werner Almesberger, EPFL ICA
 ============================================== Werner.Almesberger@epfl.ch
 
 This is experimental software. There are known bugs and certainly even
@@ -9,7 +9,7 @@
 device drivers, source for demons, management and test tools, and some
 documentation.
 
-The kernel patch is relative to the 2.3.40 kernel.
+The kernel patch is relative to the 2.3.41 kernel.
 
 Please see  http://icawww1.epfl.ch/linux-atm/info.html  for a list of
 features supported by ATM on Linux.
diff -ur --new-file old/atm/USAGE new/atm/USAGE
--- old/atm/USAGE	Fri Jan 21 09:17:27 2000
+++ new/atm/USAGE	Mon Jan 31 14:57:14 2000
@@ -1,13 +1,10 @@
-%:Usage instructions  -  ATM on Linux, release 0.65
-%:-------------------------------------------------
-%:
-%:
+Usage instructions  -  ATM on Linux, release 0.66
+-------------------------------------------------
 
 For updates of ATM on Linux, please check the Web page at  
 http://ica1www.epfl.ch/linux-atm/ 
 
-%:         WARNING
-%:
+         WARNING
 
 This is experimental software. There are known major bugs and certainly 
 even many more yet unknown problems. Internal and external interfaces are 
@@ -20,9 +17,9 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://icaftp.epfl.ch/pub/linux/atm/dist/atm-0.65.tar.gz  
-  - the Linux kernel, version 2.3.40, e.g. from  
-    ftp://ftp.kernel.org/pub/linux/kernel/v2.3/linux-2.3.40.tar.gz  
+    ftp://icaftp.epfl.ch/pub/linux/atm/dist/atm-0.66.tar.gz  
+  - the Linux kernel, version 2.3.41, e.g. from  
+    ftp://ftp.kernel.org/pub/linux/kernel/v2.3/linux-2.3.41.tar.gz  
   - Perl, version 4 or 5 
   - if you want memory debugging: MPR version 1.6, e.g. from  
     ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz  
@@ -36,11 +33,11 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.65.tar.gz
+tar xfz atm-0.66.tar.gz
 
 and the kernel source:
 
-tar xfz linux-2.3.40.tar.gz
+tar xfz linux-2.3.41.tar.gz
 
 Finally, you can extract the ATM-related patches:
 
diff -ur --new-file old/atm/VERSION new/atm/VERSION
--- old/atm/VERSION	Fri Jan 21 19:29:10 2000
+++ new/atm/VERSION	Mon Jan 31 11:34:43 2000
@@ -1 +1 @@
-0.65
+0.66
diff -ur --new-file old/atm/atm.patch new/atm/atm.patch
--- old/atm/atm.patch	Fri Jan 21 19:37:28 2000
+++ new/atm/atm.patch	Mon Jan 31 14:53:55 2000
@@ -1,6 +1,19 @@
---- ref/CREDITS	Tue Jan 18 07:19:08 2000
-+++ work/CREDITS	Fri Jan 21 16:01:02 2000
-@@ -38,11 +38,11 @@
+--- ref/CREDITS	Tue Jan 25 20:17:07 2000
++++ work/CREDITS	Mon Jan 31 11:38:23 2000
+@@ -24,6 +24,12 @@
+ S: Iasi 6600
+ S: Romania
+ 
++N: Monalisa Agrawal
++E: magrawal@nortelnetworks.com
++D: Basic Interphase 5575 driver with UBR and ABR support.
++S: 75 Donald St, Apt 42
++S: Weymouth, MA 02188
++
+ N: Dave Airlie
+ E: airlied@linux.ie
+ W: http://www.csn.ul.ie/~airlied
+@@ -38,11 +44,11 @@
  S: United Kingdom
  
  N: Werner Almesberger
@@ -16,7 +29,7 @@
  S: CH-1015 Lausanne
  S: Switzerland
  
-@@ -155,6 +155,14 @@
+@@ -155,6 +161,14 @@
  S: Notre Dame, Indiana
  S: USA
  
@@ -31,19 +44,63 @@
  N: James Banks
  E: james@sovereign.org
  D: TLAN network driver
-@@ -1735,6 +1743,10 @@
- N: Frederic Potter 
+@@ -1116,6 +1130,13 @@
+ S: TW9 1AE
+ S: United Kingdom
+ 
++N: Marko Kiiskila
++E: marko@iprg.nokia.com
++D: Author of ATM Lan Emulation
++S: 660 Harvard Ave. #7
++S: Santa Clara, CA 95051
++S: USA
++
+ N: Russell King
+ E: rmk@arm.uk.linux.org
+ D: Linux/arm integrator, maintainer & hacker
+@@ -1306,6 +1327,15 @@
+ S: North Little Rock, Arkansas 72115
+ S: USA
+ 
++N: Christophe Lizzi
++E: lizzi@cnam.fr
++W: http://cedric.cnam.fr/personne/lizzi
++D: FORE Systems 200E-series ATM network driver, sparc64 port of ATM
++S: CNAM, Laboratoire CEDRIC
++S: 292, rue St-Martin
++S: 75141 Paris Cedex 03
++S: France
++
+ N: Siegfried "Frieder" Loeffler (dg1sek)
+ E: floeff@tunix.mathematik.uni-stuttgart.de, fl@LF.net
+ W: http://www.mathematik.uni-stuttgart.de/~floeff
+@@ -1744,6 +1774,10 @@
  E: Frederic.Potter@masi.ibp.fr 
  D: Some PCI kernel support
-+
+ 
 +N: Rui Prior
 +E: rprior@inescn.pt
 +D: ATM device driver for NICStAR based cards
- 
++
  N: Stefan Probst
  E: sp@caldera.de
---- ref/Documentation/Configure.help	Fri Jan 21 00:00:16 2000
-+++ work/Documentation/Configure.help	Fri Jan 21 16:01:02 2000
+ D: The Linux Support Team Erlangen, 1993-97
+@@ -2311,6 +2345,13 @@
+ S: UC Berkeley
+ S: Berkeley, CA 94720-1776
+ S: USA
++
++N: Mike Westall
++D: IBM Turboways 25 ATM Device Driver
++E: westall@cs.clemson.edu
++S: Department of Computer Science
++S: Clemson University
++S: Clemson SC 29634 USA
+ 
+ N: Greg Wettstein
+ E: greg@wind.rmcc.com
+--- ref/Documentation/Configure.help	Thu Jan 27 16:40:16 2000
++++ work/Documentation/Configure.help	Mon Jan 31 11:38:23 2000
 @@ -3839,7 +3839,8 @@
    of your ATM card below.
  
@@ -197,7 +254,7 @@
    When active, these messages can have a significant impact on the
    speed of the driver, and the size of your syslog files! When
 --- ref/Documentation/atm.txt	Wed Sep  8 20:14:31 1999
-+++ work/Documentation/atm.txt	Fri Jan 21 16:01:02 2000
++++ work/Documentation/atm.txt	Mon Jan 31 11:38:23 2000
 @@ -1,8 +0,0 @@
 -In order to use anything but the most primitive functions of ATM,
 -several user-mode programs are required to assist the kernel. These
@@ -208,7 +265,7 @@
 -on Linux mailing list. Subscription information, archives, etc.,
 -can be found on http://icawww1.epfl.ch/linux-atm/
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/Documentation/networking/atm.txt	Fri Jan 21 16:01:02 2000
++++ work/Documentation/networking/atm.txt	Mon Jan 31 11:38:23 2000
 @@ -0,0 +1,8 @@
 +In order to use anything but the most primitive functions of ATM,
 +several user-mode programs are required to assist the kernel. These
@@ -219,7 +276,7 @@
 +on Linux mailing list. Subscription information, archives, etc.,
 +can be found on http://icawww1.epfl.ch/linux-atm/
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/Documentation/networking/fore200e.txt	Fri Jan 21 16:01:02 2000
++++ work/Documentation/networking/fore200e.txt	Mon Jan 31 11:38:23 2000
 @@ -0,0 +1,47 @@
 +Fore PCA-200E/SBA-200E ATM NIC Firmware
 +---------------------------------------
@@ -269,7 +326,7 @@
 +patches/improvement/comments/flames to <lizzi@cnam.fr>.
 +
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/Documentation/networking/iphase.txt	Fri Jan 21 16:01:02 2000
++++ work/Documentation/networking/iphase.txt	Mon Jan 31 11:38:23 2000
 @@ -0,0 +1,158 @@
 +
 +                              READ ME FISRT
@@ -429,8 +486,8 @@
 +			Fax:		33 (0)1 41 15 12 13
 +     World Wide Web:	http://www.iphase.com
 +     Anonymous FTP:	ftp.iphase.com
---- ref/arch/sparc64/config.in	Fri Jan 14 09:50:53 2000
-+++ work/arch/sparc64/config.in	Fri Jan 21 16:01:03 2000
+--- ref/arch/sparc64/config.in	Sat Jan 22 03:22:54 2000
++++ work/arch/sparc64/config.in	Mon Jan 31 11:38:23 2000
 @@ -216,6 +216,9 @@
  #      bool '  FDDI driver support' CONFIG_FDDI
  #      if [ "$CONFIG_FDDI" = "y" ]; then
@@ -441,9 +498,9 @@
     fi
  endmenu
  fi
---- ref/arch/sparc64/kernel/ioctl32.c	Thu Jan 13 21:03:00 2000
-+++ work/arch/sparc64/kernel/ioctl32.c	Fri Jan 21 16:01:03 2000
-@@ -60,6 +60,18 @@
+--- ref/arch/sparc64/kernel/ioctl32.c	Sat Jan 22 03:22:54 2000
++++ work/arch/sparc64/kernel/ioctl32.c	Mon Jan 31 11:38:23 2000
+@@ -61,6 +61,18 @@
  
  #include <linux/soundcard.h>
  
@@ -462,8 +519,8 @@
  /* Use this to get at 32-bit user passed pointers. 
     See sys_sparc32.c for description about these. */
  #define A(__x) ((unsigned long)(__x))
-@@ -1734,6 +1746,214 @@
- 	return 0;
+@@ -1753,6 +1765,217 @@
+ 	return err;
  }
  
 +struct atmif_sioc32 {
@@ -478,7 +535,7 @@
 +};
 +
 +#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
-+#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atmif_iobuf32)
++#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
 +#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
 +#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
 +#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
@@ -514,6 +571,7 @@
 +
 +#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
 +
++
 +static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
 +{
 +	struct atm_iobuf32 iobuf32;
@@ -547,10 +605,10 @@
 +	old_fs = get_fs(); set_fs (KERNEL_DS);
 +	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
 +	set_fs (old_fs);
-+	if (err)
++        if(err)
 +		goto out;
 +
-+	if (iobuf.buffer && iobuf.length > 0) {
++        if(iobuf.buffer && iobuf.length > 0) {
 +		err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length);
 +		if (err) {
 +			err = -EFAULT;
@@ -559,8 +617,8 @@
 +	}
 +	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
 +
-+out:
-+	if (iobuf32.buffer && iobuf32.length > 0)
++ out:
++        if(iobuf32.buffer && iobuf32.length > 0)
 +		kfree(iobuf.buffer);
 +
 +	return err;
@@ -601,10 +659,11 @@
 +        old_fs = get_fs(); set_fs (KERNEL_DS);
 +        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
 +        set_fs (old_fs);
-+        if (err)
++        if(err) {
 +                goto out;
++	}
 +        
-+        if (sioc.arg && sioc.length > 0) {
++        if(sioc.arg && sioc.length > 0) {
 +                err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length);
 +                if (err) {
 +                        err = -EFAULT;
@@ -614,7 +673,7 @@
 +        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
 +        
 + out:
-+	if (sioc32.arg && sioc32_length > 0)
++        if(sioc32.arg && sioc32.length > 0)
 +		kfree(sioc.arg);
 +        
 +	return err;
@@ -647,14 +706,15 @@
 +				break;
 +			}
 +		}
++	        if (i == NR_ATM_IOCTL) {
++	        return -EINVAL;
++	        }
 +	}
-+
-+        if (i == NR_ATM_IOCTL)
-+	        return -ENOIOCTLCMD;
 +        
 +        switch (cmd) {
 +	case ATM_GETNAMES:
 +		return do_atm_iobuf(fd, cmd, arg);
++	    
 +	case ATM_GETLINKRATE:
 +        case ATM_GETTYPE:
 +        case ATM_GETESI:
@@ -671,14 +731,14 @@
 +                return do_atmif_sioc(fd, cmd, arg);
 +        }
 +
-+	return -ENOIOCTLCMD;
++        return -EINVAL;
 +}
 +
  asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
  {
  	struct file * filp;
-@@ -1921,6 +2141,33 @@
- 		error = do_video_ioctl(fd, cmd, arg);
+@@ -1945,6 +2168,33 @@
+ 		error = do_smb_getmountuid(fd, cmd, arg);
  		goto out;
  
 +	case ATM_GETLINKRATE32:
@@ -711,9 +771,9 @@
  	/* List here exlicitly which ioctl's are known to have
  	 * compatable types passed or none at all...
  	 */
-@@ -2427,6 +2674,24 @@
- 	case RAW_SETBIND:
- 	case RAW_GETBIND:
+@@ -2454,6 +2704,23 @@
+ 	/* SMB ioctls which do not need any translations */
+ 	case SMB_IOC_NEWCONN:
  
 +	/* Little a */
 +	case ATMSIGD_CTRL:
@@ -722,7 +782,6 @@
 +	case ATMLEC_MCAST:
 +	case ATMLEC_DATA:
 +	case ATM_SETSC:
-+	case ATM_CREATE_LEAF:
 +        case SIOCSIFATMTCP:
 +	case SIOCMKCLIP:
 +        case ATMARP_MKIP:
@@ -737,7 +796,7 @@
  		goto out;
  
 --- ref/drivers/atm/Config.in	Thu Oct  7 19:17:09 1999
-+++ work/drivers/atm/Config.in	Fri Jan 21 16:01:03 2000
++++ work/drivers/atm/Config.in	Mon Jan 31 11:38:23 2000
 @@ -8,7 +8,7 @@
  fi
  if [ "$CONFIG_PCI" = "y" ]; then
@@ -772,7 +831,7 @@
     fi
     tristate 'Madge Ambassador (Collage PCI 155 Server)' CONFIG_ATM_AMBASSADOR
     if [ "$CONFIG_ATM_AMBASSADOR" != "n" ]; then
-@@ -43,5 +46,35 @@
+@@ -43,5 +46,34 @@
     if [ "$CONFIG_ATM_HORIZON" != "n" ]; then
        bool '  Enable debugging messages' CONFIG_ATM_HORIZON_DEBUG
     fi
@@ -781,8 +840,7 @@
 +      bool '  Enable debugging messages' CONFIG_ATM_IA_DEBUG
 +    fi
 +fi
-+#if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
-+if [ "$CONFIG_PCI" = "y" ]; then
++if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
 +  tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E
 +  if [ "$CONFIG_ATM_FORE200E" != "n" ]; then
 +    if [ "$CONFIG_PCI" = "y" ]; then
@@ -794,22 +852,22 @@
 +        fi
 +      fi
 +    fi
-+#    if [ "$CONFIG_SBUS" = "y" ]; then
-+#      bool '  SBA-200E support' CONFIG_ATM_FORE200E_SBA y
-+#      if [ "$CONFIG_ATM_FORE200E_SBA" = "y" ]; then
-+#        bool '   Use default SBA-200E firmware (normally enabled)' CONFIG_ATM_FORE200E_SBA_DEFAULT_FW
-+#        if [ "$CONFIG_ATM_FORE200E_SBA_DEFAULT_FW" = "n" ]; then
-+#          string '   Pathname of user-supplied binary firmware' CONFIG_ATM_FORE200E_SBA_FW ""
-+#        fi
-+#      fi
-+#    fi
++    if [ "$CONFIG_SBUS" = "y" ]; then
++      bool '  SBA-200E support' CONFIG_ATM_FORE200E_SBA y
++      if [ "$CONFIG_ATM_FORE200E_SBA" = "y" ]; then
++        bool '   Use default SBA-200E firmware (normally enabled)' CONFIG_ATM_FORE200E_SBA_DEFAULT_FW
++        if [ "$CONFIG_ATM_FORE200E_SBA_DEFAULT_FW" = "n" ]; then
++          string '   Pathname of user-supplied binary firmware' CONFIG_ATM_FORE200E_SBA_FW ""
++        fi
++      fi
++    fi
 +    int  '  Maximum number of tx retries' CONFIG_ATM_FORE200E_TX_RETRY 16
 +    int  '  Debugging level (0-3)' CONFIG_ATM_FORE200E_DEBUG 0
 +  fi
  fi
  endmenu
 --- ref/drivers/atm/Makefile	Wed Sep  8 20:14:31 1999
-+++ work/drivers/atm/Makefile	Fri Jan 21 16:01:03 2000
++++ work/drivers/atm/Makefile	Mon Jan 31 11:38:23 2000
 @@ -43,12 +43,18 @@
    ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
    NEED_SUNI_LX = suni.o
@@ -924,7 +982,7 @@
 +fore_200e.o: fore200e.o $(FORE200E_FW_OBJS)
 +	$(LD) -r -o $@ $< $(FORE200E_FW_OBJS)
 --- ref/drivers/atm/ambassador.c	Wed Sep 29 23:02:59 1999
-+++ work/drivers/atm/ambassador.c	Fri Jan 21 16:01:03 2000
++++ work/drivers/atm/ambassador.c	Mon Jan 31 11:38:23 2000
 @@ -1405,7 +1405,7 @@
      dont_panic (dev);
    } else {
@@ -962,7 +1020,7 @@
  
  /********** housekeeping **********/
 --- ref/drivers/atm/atmdev_init.c	Thu Aug 26 21:42:33 1999
-+++ work/drivers/atm/atmdev_init.c	Fri Jan 21 16:01:03 2000
++++ work/drivers/atm/atmdev_init.c	Mon Jan 31 11:38:23 2000
 @@ -28,6 +28,12 @@
  #ifdef CONFIG_ATM_HORIZON
  extern int hrz_detect(void);
@@ -989,8 +1047,44 @@
  #endif
  	return devs;
  }
+--- ref/drivers/atm/atmsar11.data	Mon Aug 23 18:56:31 1999
++++ work/drivers/atm/atmsar11.data	Mon Jan 31 11:38:23 2000
+@@ -2,12 +2,12 @@
+   Madge Ambassador ATM Adapter microcode.
+   Copyright (C) 1995-1999  Madge Networks Ltd.
+   
+-  This is provided here for your convenience only.
++  This microcode data is placed under the terms of the GNU General
++  Public License. The GPL is contained in /usr/doc/copyright/GPL on a
++  Debian system and in the file COPYING in the Linux kernel source.
+   
+-  No restrictions are placed on its use, so long as this file remains
+-  unchanged.
+-  
+-  You may not make, use or re-distribute modified versions of this code.
++  We would prefer you not to distribute modified versions without
++  consultation and not to ask for assembly/other microcode source.
+ */
+ 
+   0x401a6800,
+--- ref/drivers/atm/atmsar11.regions	Mon Aug 23 18:56:31 1999
++++ work/drivers/atm/atmsar11.regions	Mon Jan 31 11:38:23 2000
+@@ -1,3 +1,6 @@
++/*
++  See copyright and licensing conditions in ambassador.* files.
++*/
+   { 0x00000080,  993, },
+   { 0xa0d0d500,   80, },
+   { 0xa0d0f000,  978, },
+--- ref/drivers/atm/atmsar11.start	Mon Aug 23 18:56:31 1999
++++ work/drivers/atm/atmsar11.start	Mon Jan 31 11:38:23 2000
+@@ -1 +1,4 @@
++/*
++  See copyright and licensing conditions in ambassador.* files.
++*/
+   0xa0d0f000
 --- ref/drivers/atm/atmtcp.c	Wed Sep  8 20:14:31 1999
-+++ work/drivers/atm/atmtcp.c	Fri Jan 21 16:01:03 2000
++++ work/drivers/atm/atmtcp.c	Mon Jan 31 11:38:23 2000
 @@ -1,6 +1,6 @@
  /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
  
@@ -1109,7 +1203,7 @@
  
  
 --- ref/drivers/atm/eni.c	Wed Sep  8 20:14:31 1999
-+++ work/drivers/atm/eni.c	Fri Jan 21 17:27:47 2000
++++ work/drivers/atm/eni.c	Mon Jan 31 11:38:23 2000
 @@ -1,6 +1,6 @@
  /* drivers/atm/eni.c - Efficient Networks ENI155P device driver */
   
@@ -1370,7 +1464,7 @@
  
  
 --- ref/drivers/atm/eni.h	Mon Aug 23 18:56:31 1999
-+++ work/drivers/atm/eni.h	Fri Jan 21 16:47:37 2000
++++ work/drivers/atm/eni.h	Mon Jan 31 11:46:05 2000
 @@ -1,6 +1,6 @@
  /* drivers/atm/eni.h - Efficient Networks ENI155P device driver declarations */
   
@@ -1432,20 +1526,18 @@
  };
  
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/fore200e.c	Fri Jan 21 16:01:04 2000
-@@ -0,0 +1,2921 @@
++++ work/drivers/atm/fore200e.c	Mon Jan 31 11:38:24 2000
+@@ -0,0 +1,2958 @@
 +/*
 +  $Id: $
 +
 +  A FORE Systems 200E-series driver for ATM on Linux.
-+  Christophe Lizzi (lizzi@cnam.fr), October-December 1999.
++  Christophe Lizzi (lizzi@cnam.fr), October 1999-January 2000.
 +
 +  Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de).
 +
 +  This driver simultaneously supports PCA-200E and SBA-200E adapters
-+  on i386, alpha (untested), powerpc, sparc and sparc64 (with additional
-+  64 bit fixes to the linux-atm core) hosts.
-+
++  on i386, alpha (untested), powerpc, sparc and sparc64 architectures.
 +
 +  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
@@ -1504,7 +1596,7 @@
 +#define FORE200E_52BYTE_AAL0_SDU
 +#endif
 +
-+#define FORE200E_VERSION "0.1e"
++#define FORE200E_VERSION "0.2"
 +
 +
 +#define FORE200E         "fore200e: "
@@ -1517,17 +1609,12 @@
 +#endif
 +
 +
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18))  /* XXX 2.3.x? */
-+#define FORE200E_PCI_BASE_ADDR   base_address[0]
-+#else
-+#define FORE200E_PCI_BASE_ADDR   resource[0].start
-+#endif
-+
-+
 +#define FORE200E_ALIGN(addr, alignment) \
 +        ((((unsigned long)(addr) + (alignment - 1)) & ~(alignment - 1)) - (unsigned long)(addr))
 +
-+#define FORE200E_DMA_INDEX(dma, type, index)  ((dma) + (index) * sizeof(type))
++#define FORE200E_DMA_INDEX(dma_addr, type, index)  ((dma_addr) + (index) * sizeof(type))
++
++#define FORE200E_INDEX(virt_addr, type, index)     (&((type *)(virt_addr))[ index ])
 +
 +#define FORE200E_NEXT_ENTRY(index, modulo)    (index = ++(index) % (modulo))
 +
@@ -1607,8 +1694,6 @@
 +}
 +
 +
-+/* allocate and initialize a chunk of memory */
-+
 +static void*
 +fore200e_kmalloc(int size, int flags)
 +{
@@ -1623,51 +1708,54 @@
 +}
 +
 +
-+/* free a chunk of memory */
-+
 +static void
-+fore200e_kfree(void** chunk)
++fore200e_kfree(void* chunk)
 +{
-+    if (chunk && *chunk) {
-+	void* tmp = *chunk;
-+	*chunk = (void*) 0xDEADDEAD; /* XXX for debugging purposes */
-+	kfree(tmp);
-+    }
++    kfree(chunk);
 +}
 +
 +
-+/* allocate and align a chunk of memory */
++/* allocate and align a chunk of memory intended to hold the data behing exchanged
++   between the driver and the adapter (using streaming DVMA on SBUS hosts) */
 +
 +static int
-+fore200e_align_alloc(void** aligned, void** raw, int size, int alignment)
++fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int alignment)
 +{
 +    unsigned long offset = 0;
 +
 +    if (alignment <= sizeof(int))
 +	alignment = 0;
 +
-+    *raw = fore200e_kmalloc(size + alignment, GFP_KERNEL | GFP_DMA);
-+    if (*raw == NULL)
++    chunk->alloc_size = size + alignment;
++    chunk->align_size = size;
++
++    chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);
++    if (chunk->alloc_addr == NULL)
 +	return -ENOMEM;
 +
 +    if (alignment > 0)
-+	offset = FORE200E_ALIGN(*raw, alignment); 
++	offset = FORE200E_ALIGN(chunk->alloc_addr, alignment); 
 +    
-+    *aligned = *raw + offset;
++    chunk->align_addr = chunk->alloc_addr + offset;
++
++    chunk->dma_addr = fore200e->bus->dma_map(fore200e, chunk->align_addr, chunk->align_size);
 +    
 +    return 0;
 +}
 +
 +
-+/* free and aligned chunk of memory */
++/* free a chunk of memory */
 +
 +static void
-+fore200e_align_free(void** raw)
++fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
 +{
-+    fore200e_kfree(raw);
++    fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size);
++
++    fore200e_kfree(chunk->alloc_addr);
 +}
 +
 +
++
 +#if 0 /* currently unused */
 +static int
 +fore200e_checkup(struct fore200e* fore200e)
@@ -1704,8 +1792,9 @@
 +    unsigned long timeout = jiffies + MSECS(msecs);
 +    int           ok;
 +
++    mb();
 +    do {
-+	if ((ok = (fore200e->bus->read(addr) == val)))
++	if ((ok = (*addr == val)) || (*addr & STATUS_ERROR))
 +	    break;
 +
 +    } while (jiffies < timeout);
@@ -1721,6 +1810,29 @@
 +}
 +
 +
++static int
++fore200e_io_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
++{
++    unsigned long timeout = jiffies + MSECS(msecs);
++    int           ok;
++
++    do {
++	if ((ok = (fore200e->bus->read(addr) == val)))
++	    break;
++
++    } while (jiffies < timeout);
++
++#if 1
++    if (!ok) {
++	printk(FORE200E "I/O polling failed, got status 0x%x, expected 0x%x\n",
++	       fore200e->bus->read(addr), val);
++    }
++#endif
++
++    return ok;
++}
++
++
 +static void
 +fore200e_free_rx_buf(struct fore200e* fore200e)
 +{
@@ -1733,8 +1845,11 @@
 +	    if ((buffer = fore200e->host_bsq[ scheme ][ magn ].buffer) != NULL) {
 +
 +		for (nbr = 0; nbr < fore200e_rx_buf_nbr[ scheme ][ magn ]; nbr++) {
-+		    if (buffer[ nbr ].data_raw != NULL)
-+			fore200e_align_free((void**)&buffer[ nbr ].data_raw);
++
++		    struct chunk* data = &buffer[ nbr ].data;
++
++		    if (data->alloc_addr != NULL)
++			fore200e_chunk_free(fore200e, data);
 +		}
 +	    }
 +	}
@@ -1746,16 +1861,18 @@
 +fore200e_uninit_bs_queue(struct fore200e* fore200e)
 +{
 +    int scheme, magn;
-+    void *addr;
 +    
 +    for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
 +	for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
 +
-+	    if ((addr = fore200e->host_bsq[ scheme ][ magn ].status_raw))
-+		fore200e->bus->dma_free((void**)&addr);
++	    struct chunk* status    = &fore200e->host_bsq[ scheme ][ magn ].status;
++	    struct chunk* rbd_block = &fore200e->host_bsq[ scheme ][ magn ].rbd_block;
++	    
++	    if (status->alloc_addr)
++		fore200e->bus->dma_chunk_free(fore200e, status);
 +	    
-+	    if ((addr = fore200e->host_bsq[ scheme ][ magn ].rbd_block_raw))
-+		fore200e->bus->dma_free((void**)&addr);
++	    if (rbd_block->alloc_addr)
++		fore200e->bus->dma_chunk_free(fore200e, rbd_block);
 +	}
 +    }
 +}
@@ -1773,7 +1890,7 @@
 +    fore200e->bus->reset(fore200e);
 +
 +    if (diag) {
-+	ok = fore200e_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_SELFTEST_OK, 1000);
++	ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_SELFTEST_OK, 1000);
 +	if (ok == 0) {
 +	    
 +	    printk(FORE200E "device %s self-test failed\n", fore200e->name);
@@ -1805,8 +1922,9 @@
 +    switch(fore200e->state) {
 +
 +    case FORE200E_STATE_COMPLETE:
-+	if (fore200e->stats)
++	if (fore200e->stats) {
 +	    kfree(fore200e->stats);
++	}
 +
 +    case FORE200E_STATE_IRQ:
 +	free_irq(fore200e->irq, fore200e->atm_dev);
@@ -1818,15 +1936,15 @@
 +	fore200e_uninit_bs_queue(fore200e);
 +
 +    case FORE200E_STATE_INIT_RXQ:
-+	fore200e->bus->dma_free((void**)&fore200e->host_rxq.status_raw);
-+	fore200e->bus->dma_free((void**)&fore200e->host_rxq.rpd_raw);
++	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.status);
++	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_rxq.rpd);
 +
 +    case FORE200E_STATE_INIT_TXQ:
-+	fore200e->bus->dma_free((void**)&fore200e->host_txq.status_raw);
-+	fore200e->bus->dma_free((void**)&fore200e->host_txq.tpd_raw);
++	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.status);
++	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_txq.tpd);
 +
 +    case FORE200E_STATE_INIT_CMDQ:
-+	fore200e->bus->dma_free((void**)&fore200e->host_cmdq.status_raw);
++	fore200e->bus->dma_chunk_free(fore200e, &fore200e->host_cmdq.status);
 +
 +    case FORE200E_STATE_INITIALIZE:
 +	/* nothing to do for that state */
@@ -1861,12 +1979,9 @@
 +static u32 fore200e_pca_read(volatile u32* addr)
 +{
 +#if defined(__BIG_ENDIAN)
-+    /* on big-endian hosts, the board is configured to convert the endianess of
-+       slave RAM accesses, so we do not use the regular readl()/writel() primitives */
-+#if defined(__powerpc__)
-+    eieio();    /* enforce in-order execution of I/O */
-+#endif
-+    return *addr;
++    /* on big-endian hosts, the board is configured to convert
++       the endianess of slave RAM accesses  */
++    return swab32(readl(addr));
 +#elif defined(__LITTLE_ENDIAN)
 +    return readl(addr);
 +#else
@@ -1878,11 +1993,9 @@
 +static void fore200e_pca_write(u32 val, volatile u32* addr)
 +{
 +#if defined(__BIG_ENDIAN)
-+    /* same comment as above */
-+#if defined(__powerpc__)
-+    eieio();    /* enforce in-order execution of I/O */
-+#endif
-+    *addr = val;
++    /* on big-endian hosts, the board is configured to convert
++       the endianess of slave RAM accesses  */
++    writel(swab32(val), addr);
 +#elif defined(__LITTLE_ENDIAN)
 +    writel(val, addr);
 +#else
@@ -1891,31 +2004,55 @@
 +}
 +
 +
++/* make DMA mapping */
++
 +static u32
-+fore200e_pca_virt_to_dma(void* addr)
++fore200e_pca_dma_map(struct fore200e* fore200e, void* virt_addr, int size)
 +{
-+    return (u32) virt_to_bus(addr);
++    u32 dma_addr = (u32) virt_to_bus(virt_addr);
++
++    DPRINTK(3, "PCI DMA mapping: virt_addr = 0x%p, size = %d --> dma_addr = 0x%08x\n",
++	    virt_addr, size, dma_addr);
++    
++    return dma_addr;
 +}
 +
 +
++/* remove DMA mapping */
++
++static void
++fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size)
++{
++    DPRINTK(3, "PCI DMA unmapping: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
++
++    return;
++}
++
++
++/* allocate a DMA consistant chunk of memory intended to act as a communication mechanism
++   (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
 +
 +static int
-+fore200e_pca_dma_alloc(void** aligned, void** raw, u32* dma, int size, int nbr, int alignment)
++fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
++			     int size, int nbr, int alignment)
 +{
-+    if (fore200e_align_alloc(aligned, raw, size * nbr, alignment) < 0)
++    if (fore200e_chunk_alloc(fore200e, chunk, size * nbr, alignment) < 0)
 +	return -ENOMEM;
 +
-+    *dma = fore200e_pca_virt_to_dma(*aligned);
++    chunk->dma_addr = fore200e_pca_dma_map(fore200e, chunk->align_addr, chunk->align_size);
 +    
 +    return 0;
 +}
 +
 +
++/* free a DMA consistant chunk of memory */
 +
 +static void
-+fore200e_pca_dma_free(void** raw)
++fore200e_pca_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
 +{
-+    fore200e_align_free(raw);
++    fore200e_pca_dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size);
++
++    fore200e_chunk_free(fore200e, chunk);
 +}
 +
 +
@@ -1948,11 +2085,7 @@
 +{
 +    DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);
 +
-+#if !defined(__sparc_v9__)
 +    fore200e->virt_base = ioremap(fore200e->phys_base, PCA200E_IOSPACE_LENGTH);
-+#else
-+    fore200e->virt_base = (void*)fore200e->phys_base;
-+#endif
 +    
 +    if (fore200e->virt_base == NULL) {
 +	printk(FORE200E "can't map device %s\n", fore200e->name);
@@ -1976,8 +2109,8 @@
 +{
 +    DPRINTK(2, "device %s being unmapped from memory\n", fore200e->name);
 +
-+    /* XXX iounmap() is empty on powerpc (at least in 2.2.12 and 2.3.18), so
-+       we get a kernel panic if the module is loaded and unloaded several times */
++    /* XXX iounmap() does nothing on powerpc (at least in 2.2.12 and 2.3.18),
++       this leads to a kernel panic if the module is loaded and unloaded several times */
 +    if (fore200e->virt_base != NULL)
 +	iounmap(fore200e->virt_base);
 +}
@@ -1992,21 +2125,10 @@
 +
 +    DPRINTK(2, "device %s being configured\n", fore200e->name);
 +
-+#if 0 && defined(__powerpc__) || defined(__sparc_v9__)    /* XXX really required? */
-+    {
-+	u16 command;
-+	pci_read_config_word(pci_dev, PCI_COMMAND, &command);
-+	command = PCI_COMMAND_MEMORY |
-+	          PCI_COMMAND_MASTER |
-+	          PCI_COMMAND_PARITY |
-+	          PCI_COMMAND_SERR;
-+	pci_write_config_word(pci_dev, PCI_COMMAND, command);
-+    }
-+#endif
-+
 +#if defined(__powerpc__)
 +    if (pci_dev->irq == 0) {
 +	u8 intr_line;
++
 +	pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &intr_line);
 +	
 +	/* pci_dev->irq is not set on my Motorola MTX (PReP PowerPC) running a 2.2.7 kernel */
@@ -2021,7 +2143,9 @@
 +#if defined(__BIG_ENDIAN)
 +    {
 +	u8 master_ctrl;
++
 +	pci_read_config_byte(pci_dev, PCA200E_PCI_MASTER_CTRL, &master_ctrl);
++
 +	/* request the PCA board to convert the endianess of slave RAM accesses */
 +	master_ctrl = PCA200E_CTRL_DIS_CACHE_RD     |
 +                      PCA200E_CTRL_DIS_WRT_INVAL    |
@@ -2061,7 +2185,7 @@
 +    fore200e->bus       = bus;
 +    fore200e->bus_dev   = pci_dev;    
 +    fore200e->irq       = pci_dev->irq;
-+    fore200e->phys_base = (pci_dev->FORE200E_PCI_BASE_ADDR & PCI_BASE_ADDRESS_MEM_MASK);
++    fore200e->phys_base = (pci_dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK);
 +
 +#if defined(__powerpc__)
 +    fore200e->phys_base += KERNELBASE;
@@ -2082,13 +2206,16 @@
 +    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
 +    struct prom_opcode      opcode;
 +    int                     ok;
++    u32                     prom_dma;
 +
 +    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 +
 +    opcode.opcode = OPCODE_GET_PROM;
 +    opcode.pad    = 0;
 +
-+    fore200e->bus->write(fore200e->bus->virt_to_dma((void*) prom), &entry->cp_entry->cmd.prom_block.prom_haddr);
++    prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data));
++
++    fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr);
 +    
 +    *entry->status = STATUS_PENDING;
 +
@@ -2098,6 +2225,8 @@
 +
 +    *entry->status = STATUS_FREE;
 +
++    fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data));
++
 +    if (ok == 0) {
 +	printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name);
 +	return -EIO;
@@ -2119,7 +2248,7 @@
 +static int
 +fore200e_pca_proc_read(struct fore200e* fore200e, char *page)
 +{
-+    struct pci_dev* pci_dev = fore200e->bus_dev;
++    struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;
 +
 +    return sprintf(page, "   PCI bus/slot/function:\t%d/%d/%d\n",
 +		   pci_dev->bus->number, PCI_SLOT(pci_dev->devfn), PCI_FUNC(pci_dev->devfn));
@@ -2135,47 +2264,79 @@
 +static u32
 +fore200e_sba_read(volatile u32* addr)
 +{
-+    return *addr;
++    return sbus_readl(addr);
 +}
 +
 +
 +static void
 +fore200e_sba_write(u32 val, volatile u32* addr)
 +{
-+    *addr = val;
++    sbus_writel(val, addr);
 +}
 +
 +
 +static u32
-+fore200e_sba_virt_to_dma(void* addr)
++fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size)
++{
++    u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size);
++
++    DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d --> dma_addr = 0x%08x\n", virt_addr, size, dma_addr);
++    
++    return dma_addr;
++}
++
++
++static void
++fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size)
++{
++    DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
++
++    sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size);
++    
++    return;
++}
++
++
++static void
++fore200e_sba_dma_sync(struct fore200e* fore200e, u32 dma_addr, int size)
 +{
-+    return sbus_dvma_addr(addr);
++    DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d\n", dma_addr, size);
++    
++    sbus_dma_sync_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size);
 +}
 +
 +
-+/* allocate a DMA'able consistent chunk of memory */
++/* allocate a DVMA consistant chunk of memory intended to act as a communication mechanism
++   (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
 +
 +static int
-+fore200e_sba_dma_alloc(void** aligned, void** raw, u32* dma, int size, int nbr, int alignment)
++fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int nbr, int alignment)
 +{
++    chunk->alloc_size = chunk->align_size = size * nbr;
++
 +    /* returned chunks are page-aligned */
-+    *aligned = sparc_dvma_malloc(size * nbr, "", dma);
++    chunk->alloc_addr = sbus_alloc_consistant((struct sbus_dev*)fore200e->bus_dev,
++					      chunk->alloc_size,
++					      &chunk->dma_addr);
 +
-+    if (*aligned == NULL || *dma == 0)
++    if (chunk->alloc_addr == NULL || chunk->dma_addr == 0)
 +	return -ENOMEM;
 +
-+    *raw = (void*)(unsigned long) *dma;    /* XXX there is no sparc_dvma_free() anyway */
++    chunk->align_addr = chunk->alloc_addr;
 +    
 +    return 0;
 +}
 +
 +
-+/* free a DMA'able chunk of memory */
++/* free a DVMA consistant chunk of memory */
 +
 +static void
-+fore200e_sba_dma_free(void** raw)
++fore200e_sba_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
 +{
-+    /* XXX there is no sparc_dvma_free() */
++    sbus_free_consistant((struct sbus_dev*)fore200e->bus_dev,
++			 chunk->alloc_size,
++			 chunk->alloc_addr,
++			 chunk->dma_addr);
 +}
 +
 +
@@ -2203,15 +2364,6 @@
 +
 +
 +static void
-+fore200e_sba_dma_sync(struct fore200e* fore200e, u32 haddr, int len)
-+{
-+#ifdef NEED_DMA_SYNCHRONIZATION
-+    mmu_sync_dma(haddr, len, ((struct linux_sbus_device*)fore200e->bus_dev)->my_bus);
-+#endif
-+}
-+
-+
-+static void
 +fore200e_sba_reset(struct fore200e* fore200e)
 +{
 +    fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr);
@@ -2223,48 +2375,17 @@
 +static int __init
 +fore200e_sba_map(struct fore200e* fore200e)
 +{
-+    struct linux_sbus_device* sbus_dev = (struct linux_sbus_device*)fore200e->bus_dev;
++    struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;
 +
 +    /* gain access to the SBA-200E specific registers  */
 +    
-+    prom_apply_sbus_ranges(sbus_dev->my_bus, &sbus_dev->reg_addrs[0], sbus_dev->num_registers, sbus_dev);
-+    fore200e->regs.sba.hcr = (u32*)sparc_alloc_io(sbus_dev->reg_addrs[0].phys_addr, 0,
-+						  sbus_dev->reg_addrs[0].reg_size,
-+						  "SBA HCR",
-+						  sbus_dev->reg_addrs[0].which_io, 0);
-+    if (fore200e->regs.sba.hcr == NULL) {
-+	printk(FORE200E "unable to map HCR register of device %s\n", fore200e->name);
-+	return -EFAULT;
-+    }
-+    
-+    prom_apply_sbus_ranges(sbus_dev->my_bus, &sbus_dev->reg_addrs[1], sbus_dev->num_registers, sbus_dev);
-+    fore200e->regs.sba.bsr = (u32*)sparc_alloc_io(sbus_dev->reg_addrs[1].phys_addr, 0,
-+						  sbus_dev->reg_addrs[1].reg_size,
-+						  "SBA BSR",
-+						  sbus_dev->reg_addrs[1].which_io, 0);
-+    if (fore200e->regs.sba.bsr == NULL) {
-+	printk(FORE200E "unable to map BSR register of device %s\n", fore200e->name);
-+	return -EFAULT;
-+    }
-+    
-+    prom_apply_sbus_ranges(sbus_dev->my_bus, &sbus_dev->reg_addrs[2], sbus_dev->num_registers, sbus_dev);
-+    fore200e->regs.sba.isr = (u32*)sparc_alloc_io(sbus_dev->reg_addrs[2].phys_addr, 0,
-+						  sbus_dev->reg_addrs[2].reg_size,
-+						  "SBA ISR",
-+						  sbus_dev->reg_addrs[2].which_io, 0);
-+    if (fore200e->regs.sba.isr == NULL) {
-+	printk(FORE200E "unable to map ISR register of device %s\n", fore200e->name);
-+	return -EFAULT;
-+    }
++    fore200e->regs.sba.hcr = (u32*)sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
++    fore200e->regs.sba.bsr = (u32*)sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
++    fore200e->regs.sba.isr = (u32*)sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
++    fore200e->virt_base    = (u32*)sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
 +
 +    fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */
 +
-+    
-+    prom_apply_sbus_ranges(sbus_dev->my_bus, &sbus_dev->reg_addrs[3], sbus_dev->num_registers, sbus_dev);
-+    fore200e->virt_base = (u32*)sparc_alloc_io(sbus_dev->reg_addrs[3].phys_addr, 0,
-+					       sbus_dev->reg_addrs[3].reg_size,
-+					       "SBA RAM",
-+					       sbus_dev->reg_addrs[3].which_io, 0);
 +    if (fore200e->virt_base == NULL) {
 +	printk(FORE200E "unable to map RAM of device %s\n", fore200e->name);
 +	return -EFAULT;
@@ -2280,12 +2401,10 @@
 +static void
 +fore200e_sba_unmap(struct fore200e* fore200e)
 +{
-+    struct linux_sbus_device* sbus_dev = (struct linux_sbus_device*)fore200e->bus_dev;
-+
-+    sparc_free_io((void*)fore200e->regs.sba.hcr, sbus_dev->reg_addrs[0].reg_size);
-+    sparc_free_io((void*)fore200e->regs.sba.bsr, sbus_dev->reg_addrs[1].reg_size);
-+    sparc_free_io((void*)fore200e->regs.sba.isr, sbus_dev->reg_addrs[2].reg_size);
-+    sparc_free_io((void*)fore200e->virt_base,    sbus_dev->reg_addrs[3].reg_size);
++    sbus_iounmap((ulong)fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
++    sbus_iounmap((ulong)fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
++    sbus_iounmap((ulong)fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
++    sbus_iounmap((ulong)fore200e->virt_base,    SBA200E_RAM_LENGTH);
 +}
 +
 +
@@ -2301,16 +2420,17 @@
 +fore200e_sba_detect(const struct fore200e_bus* bus, int index)
 +{
 +    struct fore200e*          fore200e;
-+    struct linux_sbus*        sbus;
-+    struct linux_sbus_device* sbus_dev = 0;
-+    unsigned int              curr = 0;
++    struct sbus_bus* sbus_bus;
++    struct sbus_dev* sbus_dev = NULL;
++    
++    unsigned int     count = 0;
 +    
-+    for_each_sbus (sbus) {
-+	for_each_sbusdev (sbus_dev, sbus) {
++    for_each_sbus (sbus_bus) {
++	for_each_sbusdev (sbus_dev, sbus_bus) {
 +	    if (strcmp(sbus_dev->prom_name, SBA200E_PROM_NAME) == 0) {
-+		if (curr >= index)
++		if (count >= index)
 +		    goto found;
-+		curr++;
++		count++;
 +	    }
 +	}
 +    }
@@ -2344,11 +2464,9 @@
 +static int __init
 +fore200e_sba_prom_read(struct fore200e* fore200e, struct prom_data* prom)
 +{
-+    struct linux_sbus_device* sbus_dev;
++    struct sbus_dev* sbus_dev = (struct sbus_dev*) fore200e->bus_dev;
 +    int                       len;
 +
-+    sbus_dev = fore200e->bus_dev;
-+    
 +    len = prom_getproperty(sbus_dev->prom_node, "macaddrlo2", &prom->mac_addr[ 4 ], 4);
 +    if (len < 0)
 +	return -EBUSY;
@@ -2370,7 +2488,7 @@
 +static int
 +fore200e_sba_proc_read(struct fore200e* fore200e, char *page)
 +{
-+    struct linux_sbus_device* sbus_dev = (struct linux_sbus_device*)fore200e->bus_dev;
++    struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev;
 +
 +    return sprintf(page, "   SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name);
 +}
@@ -2395,6 +2513,9 @@
 +	    if (entry->data)
 +		kfree(entry->data);
 +
++	    /* remove DMA mapping */
++	    fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length);
++
 +	    /* notify tx completion */
 +	    if (entry->vcc->pop)
 +		entry->vcc->pop(entry->vcc, entry->skb);
@@ -2445,7 +2566,7 @@
 +		    
 +		    FORE200E_NEXT_ENTRY(bsq->free, fore200e_rx_buf_nbr[ scheme ][ magn ]);
 +		    
-+		    entry->rbd_block->rbd[ i ].buffer_haddr = buffer->data_dma;
++		    entry->rbd_block->rbd[ i ].buffer_haddr = buffer->data.dma_addr;
 +		    entry->rbd_block->rbd[ i ].handle       = FORE200E_BUF2HDL(buffer);
 +		}
 +
@@ -2538,9 +2659,9 @@
 +	
 +	/* ensure DMA synchronisation */
 +	if (fore200e->bus->dma_sync)
-+	    fore200e->bus->dma_sync(fore200e, buffer->data_dma, rpd->rsd[ i ].length);
++	    fore200e->bus->dma_sync(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length);
 +	
-+	memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data_align, rpd->rsd[ i ].length);
++	memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length);
 +    }
 +    
 +    DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize);
@@ -2984,11 +3105,11 @@
 +	if (skb_len < tx_len)
 +	    memset(entry->data + skb_len, 0x00, tx_len - skb_len);
 +	
-+	tpd->tsd[ 0 ].buffer = fore200e->bus->virt_to_dma(entry->data);
++	tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, entry->data, tx_len);
 +    }
 +    else {
 +	entry->data = NULL;
-+	tpd->tsd[ 0 ].buffer = fore200e->bus->virt_to_dma(skb_data);
++	tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, skb_data, tx_len);
 +    }
 +
 +    tpd->tsd[ 0 ].length = tx_len;
@@ -3055,6 +3176,8 @@
 +    {
 +	int ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 10);
 +
++	fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length);
++	
 +	if (ok == 0) {
 +	    printk(FORE200E "synchronous tx on %d:%d:%d failed\n", vcc->itf, vcc->vpi, vcc->vci);
 +
@@ -3088,6 +3211,7 @@
 +    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
 +    struct stats_opcode     opcode;
 +    int                     ok;
++    u32                     stats_dma_addr;
 +
 +    if (fore200e->stats == NULL) {
 +	fore200e->stats = fore200e_kmalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA);
@@ -3095,13 +3219,14 @@
 +	    return -ENOMEM;
 +    }
 +    
++    stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats, sizeof(struct stats));
++    
 +    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 +
 +    opcode.opcode = OPCODE_GET_STATS;
 +    opcode.pad    = 0;
 +
-+    fore200e->bus->write(fore200e->bus->virt_to_dma((void*) fore200e->stats),
-+			 &entry->cp_entry->cmd.stats_block.stats_haddr);
++    fore200e->bus->write(stats_dma_addr, &entry->cp_entry->cmd.stats_block.stats_haddr);
 +    
 +    *entry->status = STATUS_PENDING;
 +
@@ -3111,6 +3236,8 @@
 +
 +    *entry->status = STATUS_FREE;
 +
++    fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats));
++    
 +    if (ok == 0) {
 +	printk(FORE200E "unable to get statistics from device %s\n", fore200e->name);
 +	return -EIO;
@@ -3152,6 +3279,9 @@
 +    struct host_cmdq_entry* entry = &cmdq->host_entry[ cmdq->head ];
 +    struct oc3_opcode       opcode;
 +    int                     ok;
++    u32                     oc3_regs_dma_addr;
++
++    oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs));
 +
 +    FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 +
@@ -3160,8 +3290,7 @@
 +    opcode.value  = 0;
 +    opcode.mask   = 0;
 +
-+    fore200e->bus->write(fore200e->bus->virt_to_dma((void*) regs),
-+			 &entry->cp_entry->cmd.oc3_block.regs_haddr);
++    fore200e->bus->write(oc3_regs_dma_addr, &entry->cp_entry->cmd.oc3_block.regs_haddr);
 +    
 +    *entry->status = STATUS_PENDING;
 +
@@ -3171,6 +3300,8 @@
 +
 +    *entry->status = STATUS_FREE;
 +
++    fore200e->bus_dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs));
++    
 +    if (ok == 0) {
 +	printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name);
 +	return -EIO;
@@ -3252,9 +3383,9 @@
 +
 +
 +static inline unsigned int
-+fore200e_dma_swap(unsigned int in)
++fore200e_swap(unsigned int in)
 +{
-+#if defined(__i386__)
++#if defined(__LITTLE_ENDIAN)
 +    return swab32(in);
 +#else
 +    return in;
@@ -3270,19 +3401,19 @@
 +    if (fore200e_getstats(fore200e) < 0)
 +	return -EIO;
 +
-+    tmp.section_bip = fore200e_dma_swap(fore200e->stats->oc3.section_bip8_errors);
-+    tmp.line_bip    = fore200e_dma_swap(fore200e->stats->oc3.line_bip24_errors);
-+    tmp.path_bip    = fore200e_dma_swap(fore200e->stats->oc3.path_bip8_errors);
-+    tmp.line_febe   = fore200e_dma_swap(fore200e->stats->oc3.line_febe_errors);
-+    tmp.path_febe   = fore200e_dma_swap(fore200e->stats->oc3.path_febe_errors);
-+    tmp.corr_hcs    = fore200e_dma_swap(fore200e->stats->oc3.corr_hcs_errors);
-+    tmp.uncorr_hcs  = fore200e_dma_swap(fore200e->stats->oc3.ucorr_hcs_errors);
-+    tmp.tx_cells    = fore200e_dma_swap(fore200e->stats->aal0.cells_transmitted)  +
-+	              fore200e_dma_swap(fore200e->stats->aal34.cells_transmitted) +
-+	              fore200e_dma_swap(fore200e->stats->aal5.cells_transmitted);
-+    tmp.rx_cells    = fore200e_dma_swap(fore200e->stats->aal0.cells_received)     +
-+	              fore200e_dma_swap(fore200e->stats->aal34.cells_received)    +
-+	              fore200e_dma_swap(fore200e->stats->aal5.cells_received);
++    tmp.section_bip = fore200e_swap(fore200e->stats->oc3.section_bip8_errors);
++    tmp.line_bip    = fore200e_swap(fore200e->stats->oc3.line_bip24_errors);
++    tmp.path_bip    = fore200e_swap(fore200e->stats->oc3.path_bip8_errors);
++    tmp.line_febe   = fore200e_swap(fore200e->stats->oc3.line_febe_errors);
++    tmp.path_febe   = fore200e_swap(fore200e->stats->oc3.path_febe_errors);
++    tmp.corr_hcs    = fore200e_swap(fore200e->stats->oc3.corr_hcs_errors);
++    tmp.uncorr_hcs  = fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors);
++    tmp.tx_cells    = fore200e_swap(fore200e->stats->aal0.cells_transmitted)  +
++	              fore200e_swap(fore200e->stats->aal34.cells_transmitted) +
++	              fore200e_swap(fore200e->stats->aal5.cells_transmitted);
++    tmp.rx_cells    = fore200e_swap(fore200e->stats->aal0.cells_received)     +
++	              fore200e_swap(fore200e->stats->aal34.cells_received)    +
++	              fore200e_swap(fore200e->stats->aal5.cells_received);
 +
 +    if (arg)
 +	return copy_to_user(arg, &tmp, sizeof(struct sonet_stats)) ? -EFAULT : 0;	
@@ -3398,7 +3529,7 @@
 +	fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ];
 +    }
 +    
-+    fore200e_kfree((void**)&prom);
++    fore200e_kfree(prom);
 +
 +    return 0;
 +}
@@ -3433,23 +3564,17 @@
 +		buffer[ i ].scheme = scheme;
 +		buffer[ i ].magn   = magn;
 +
-+		/* allocate and align the receive buffer body */
-+		if (fore200e_align_alloc((void**) &buffer[ i ].data_align, 
-+					 (void**) &buffer[ i ].data_raw, 
-+					 size,
-+					 fore200e->bus->buffer_alignment) < 0) {
++		/* allocate the receive buffer body */
++		if (fore200e_chunk_alloc(fore200e,
++					 &buffer[ i ].data, size, fore200e->bus->buffer_alignment) < 0) {
 +		    
 +		    while (i > 0)
-+			fore200e_align_free((void**)&buffer[ --i ].data_raw);
-+		    fore200e_kfree((void**)&buffer);
++			fore200e_chunk_free(fore200e, &buffer[ --i ].data);
++		    fore200e_kfree(buffer);
 +		    
 +		    return -ENOMEM;
 +		}
-+
-+		/* finally get the physical base address of the buffer body */
-+		buffer[ i ].data_dma = fore200e->bus->virt_to_dma(buffer[ i ].data_align);
 +	    }
-+
 +	    /* set next free buffer index */
 +	    bsq->free = 0;
 +	}
@@ -3467,8 +3592,6 @@
 +
 +    struct host_bsq*     bsq;
 +    struct cp_bsq_entry* cp_entry;
-+    u32                  status_dma;
-+    u32                  rbd_block_dma;
 +
 +    for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
 +	for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
@@ -3478,9 +3601,8 @@
 +	    bsq = &fore200e->host_bsq[ scheme ][ magn ];
 +
 +	    /* allocate and align the array of status words */
-+	    if (fore200e->bus->dma_alloc((void**) &bsq->status_align, 
-+					 (void**) &bsq->status_raw,
-+					 &status_dma,
++	    if (fore200e->bus->dma_chunk_alloc(fore200e,
++					       &bsq->status,
 +					 sizeof(enum status), 
 +					 QUEUE_SIZE_BS,
 +					 fore200e->bus->status_alignment) < 0) {
@@ -3488,14 +3610,13 @@
 +	    }
 +
 +	    /* allocate and align the array of receive buffer descriptors */
-+	    if (fore200e->bus->dma_alloc((void**) &bsq->rbd_block_align, 
-+					 (void**) &bsq->rbd_block_raw,
-+					 &rbd_block_dma,
++	    if (fore200e->bus->dma_chunk_alloc(fore200e,
++					       &bsq->rbd_block,
 +					 sizeof(struct rbd_block),
 +					 QUEUE_SIZE_BS,
 +					 fore200e->bus->descr_alignment) < 0) {
 +		
-+		fore200e->bus->dma_free((void**)&bsq->status_raw);
++		fore200e->bus->dma_chunk_free(fore200e, &bsq->status);
 +		return -ENOMEM;
 +	    }
 +	    
@@ -3506,14 +3627,18 @@
 +	    /* fill the host resident and cp resident buffer supply queue entries */
 +	    for (i = 0; i < QUEUE_SIZE_BS; i++) {
 +		
-+		bsq->host_entry[ i ].status        = &bsq->status_align[ i ];
-+	        bsq->host_entry[ i ].rbd_block     = &bsq->rbd_block_align[i];
-+		bsq->host_entry[ i ].rbd_block_dma = FORE200E_DMA_INDEX(rbd_block_dma, struct rbd, i);
++		bsq->host_entry[ i ].status = 
++		                     FORE200E_INDEX(bsq->status.align_addr, enum status, i);
++	        bsq->host_entry[ i ].rbd_block =
++		                     FORE200E_INDEX(bsq->rbd_block.align_addr, struct rbd_block, i);
++		bsq->host_entry[ i ].rbd_block_dma =
++		                     FORE200E_DMA_INDEX(bsq->rbd_block.dma_addr, struct rbd_block, i);
 +		bsq->host_entry[ i ].cp_entry      = &cp_entry[ i ];
 +		
 +		*bsq->host_entry[ i ].status   = STATUS_FREE;
 +		
-+		fore200e->bus->write(FORE200E_DMA_INDEX(status_dma, enum status, i), &cp_entry[ i ].status_haddr);
++		fore200e->bus->write(FORE200E_DMA_INDEX(bsq->status.dma_addr, enum status, i), 
++				     &cp_entry[ i ].status_haddr);
 +	    }
 +	}
 +    }
@@ -3528,16 +3653,13 @@
 +{
 +    struct host_rxq*     rxq =  &fore200e->host_rxq;
 +    struct cp_rxq_entry* cp_entry;
-+    u32                  status_dma;
-+    u32                  rpd_dma;
 +    int i;
 +
 +    DPRINTK(2, "receive queue is being initialized\n");
 +
 +    /* allocate and align the array of status words */
-+    if (fore200e->bus->dma_alloc((void**) &rxq->status_align, 
-+				 (void**) &rxq->status_raw,
-+				 &status_dma,
++    if (fore200e->bus->dma_chunk_alloc(fore200e,
++				       &rxq->status,
 +				 sizeof(enum status), 
 +				 QUEUE_SIZE_RX,
 +				 fore200e->bus->status_alignment) < 0) {
@@ -3545,14 +3667,13 @@
 +    }
 +
 +    /* allocate and align the array of receive PDU descriptors */
-+    if (fore200e->bus->dma_alloc((void**) &rxq->rpd_align, 
-+				 (void**) &rxq->rpd_raw,
-+				 &rpd_dma,
++    if (fore200e->bus->dma_chunk_alloc(fore200e,
++				       &rxq->rpd,
 +				 sizeof(struct rpd), 
 +				 QUEUE_SIZE_RX,
 +				 fore200e->bus->descr_alignment) < 0) {
 +	
-+	fore200e->bus->dma_free((void**)&rxq->status_raw);
++	fore200e->bus->dma_chunk_free(fore200e, &rxq->status);
 +	return -ENOMEM;
 +    }
 +
@@ -3563,15 +3684,21 @@
 +    /* fill the host resident and cp resident rx entries */
 +    for (i=0; i < QUEUE_SIZE_RX; i++) {
 +	
-+	rxq->host_entry[ i ].status   = &rxq->status_align[ i ];
-+	rxq->host_entry[ i ].rpd      = &rxq->rpd_align[ i ];
-+	rxq->host_entry[ i ].rpd_dma  = FORE200E_DMA_INDEX(rpd_dma, struct rpd, i);
++	rxq->host_entry[ i ].status = 
++	                     FORE200E_INDEX(rxq->status.align_addr, enum status, i);
++	rxq->host_entry[ i ].rpd = 
++	                     FORE200E_INDEX(rxq->rpd.align_addr, struct rpd, i);
++	rxq->host_entry[ i ].rpd_dma = 
++	                     FORE200E_DMA_INDEX(rxq->rpd.dma_addr, struct rpd, i);
 +	rxq->host_entry[ i ].cp_entry = &cp_entry[ i ];
 +
 +	*rxq->host_entry[ i ].status = STATUS_FREE;
 +
-+	fore200e->bus->write(FORE200E_DMA_INDEX(status_dma, enum status, i), &cp_entry[ i ].status_haddr);
-+	fore200e->bus->write(FORE200E_DMA_INDEX(rpd_dma,    struct rpd,  i), &cp_entry[ i ].rpd_haddr);
++	fore200e->bus->write(FORE200E_DMA_INDEX(rxq->status.dma_addr, enum status, i), 
++			     &cp_entry[ i ].status_haddr);
++
++	fore200e->bus->write(FORE200E_DMA_INDEX(rxq->rpd.dma_addr, struct rpd, i),
++			     &cp_entry[ i ].rpd_haddr);
 +    }
 +
 +    /* set the head entry of the queue */
@@ -3587,16 +3714,13 @@
 +{
 +    struct host_txq*     txq =  &fore200e->host_txq;
 +    struct cp_txq_entry* cp_entry;
-+    u32                  status_dma;
-+    u32                  tpd_dma;
 +    int i;
 +
 +    DPRINTK(2, "transmit queue is being initialized\n");
 +
 +    /* allocate and align the array of status words */
-+    if (fore200e->bus->dma_alloc((void**) &txq->status_align, 
-+				 (void**) &txq->status_raw,
-+				 &status_dma,
++    if (fore200e->bus->dma_chunk_alloc(fore200e,
++				       &txq->status,
 +				 sizeof(enum status), 
 +				 QUEUE_SIZE_TX,
 +				 fore200e->bus->status_alignment) < 0) {
@@ -3604,14 +3728,13 @@
 +    }
 +
 +    /* allocate and align the array of transmit PDU descriptors */
-+    if (fore200e->bus->dma_alloc((void**) &txq->tpd_align, 
-+				 (void**) &txq->tpd_raw,
-+				 &tpd_dma,
++    if (fore200e->bus->dma_chunk_alloc(fore200e,
++				       &txq->tpd,
 +				 sizeof(struct tpd), 
 +				 QUEUE_SIZE_TX,
 +				 fore200e->bus->descr_alignment) < 0) {
 +	
-+	fore200e->bus->dma_free((void**)&txq->status_raw);
++	fore200e->bus->dma_chunk_free(fore200e, &txq->status);
 +	return -ENOMEM;
 +    }
 +
@@ -3622,20 +3745,24 @@
 +    /* fill the host resident and cp resident tx entries */
 +    for (i=0; i < QUEUE_SIZE_TX; i++) {
 +	
-+	txq->host_entry[ i ].status   = &txq->status_align[ i ];
-+	txq->host_entry[ i ].tpd      = &txq->tpd_align[ i ];
-+	txq->host_entry[ i ].tpd_dma  = FORE200E_DMA_INDEX(tpd_dma, struct tpd, i);
++	txq->host_entry[ i ].status = 
++	                     FORE200E_INDEX(txq->status.align_addr, enum status, i);
++	txq->host_entry[ i ].tpd = 
++	                     FORE200E_INDEX(txq->tpd.align_addr, struct tpd, i);
++	txq->host_entry[ i ].tpd_dma  = 
++                             FORE200E_DMA_INDEX(txq->tpd.dma_addr, struct tpd, i);
 +	txq->host_entry[ i ].cp_entry = &cp_entry[ i ];
 +
 +	*txq->host_entry[ i ].status = STATUS_FREE;
 +	
-+	fore200e->bus->write(FORE200E_DMA_INDEX(status_dma, enum status, i), &cp_entry[ i ].status_haddr);
++	fore200e->bus->write(FORE200E_DMA_INDEX(txq->status.dma_addr, enum status, i), 
++			     &cp_entry[ i ].status_haddr);
 +	
 +        /* although there is a one-to-one mapping of tx queue entries and tpds,
-+	   we do not write here the DMA (physical) base address of each tpd into the related
-+	   cp resident entry, because the cp relies on this write to detect that a new pdu
-+	   has been submitted for tx */
-+    }
++	   we do not write here the DMA (physical) base address of each tpd into
++	   the related cp resident entry, because the cp relies on this write
++	   operation to detect that a new pdu has been submitted for tx */
++}
 +
 +    /* set the head entry of the queue */
 +    txq->head = 0;
@@ -3650,15 +3777,13 @@
 +{
 +    struct host_cmdq*     cmdq =  &fore200e->host_cmdq;
 +    struct cp_cmdq_entry* cp_entry;
-+    u32                   status_dma;
 +    int i;
 +
 +    DPRINTK(2, "command queue is being initialized\n");
 +
 +    /* allocate and align the array of status words */
-+    if (fore200e->bus->dma_alloc((void**) &cmdq->status_align, 
-+				 (void**) &cmdq->status_raw,
-+				 &status_dma,
++    if (fore200e->bus->dma_chunk_alloc(fore200e,
++				       &cmdq->status,
 +				 sizeof(enum status), 
 +				 QUEUE_SIZE_CMD,
 +				 fore200e->bus->status_alignment) < 0) {
@@ -3672,12 +3797,14 @@
 +    /* fill the host resident and cp resident cmd entries */
 +    for (i=0; i < QUEUE_SIZE_CMD; i++) {
 +	
-+	cmdq->host_entry[ i ].status   = &cmdq->status_align[ i ];
++	cmdq->host_entry[ i ].status   = 
++                              FORE200E_INDEX(cmdq->status.align_addr, enum status, i);
 +	cmdq->host_entry[ i ].cp_entry = &cp_entry[ i ];
 +
 +	*cmdq->host_entry[ i ].status = STATUS_FREE;
 +
-+	fore200e->bus->write(FORE200E_DMA_INDEX(status_dma, enum status, i), &cp_entry[ i ].status_haddr);
++	fore200e->bus->write(FORE200E_DMA_INDEX(cmdq->status.dma_addr, enum status, i), 
++                             &cp_entry[ i ].status_haddr);
 +    }
 +
 +    /* set the head entry of the queue */
@@ -3717,12 +3844,7 @@
 +    DPRINTK(2, "device %s being initialized\n", fore200e->name);
 +
 +    spin_lock_init(&fore200e->tx_lock);
-+    
-+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1))
-+    fore200e->rate_sf = MUTEX;
-+#else
 +    init_MUTEX(&fore200e->rate_sf);
-+#endif
 +    
 +    cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
 +
@@ -3752,7 +3874,7 @@
 +    fore200e->bus->write(STATUS_PENDING,    &cpq->init.status);
 +    fore200e->bus->write(OPCODE_INITIALIZE, &cpq->init.opcode);
 +
-+    ok = fore200e_poll(fore200e, &cpq->init.status, STATUS_COMPLETE, 3000);
++    ok = fore200e_io_poll(fore200e, &cpq->init.status, STATUS_COMPLETE, 3000);
 +    if (ok == 0) {
 +	printk(FORE200E "device %s initialization failed\n", fore200e->name);
 +	return -ENODEV;
@@ -3830,7 +3952,7 @@
 +
 +    fore200e_monitor_puts(fore200e, cmd);
 +
-+    ok = fore200e_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_CP_RUNNING, 1000);
++    ok = fore200e_io_poll(fore200e, &fore200e->cp_monitor->bstat, BSTAT_CP_RUNNING, 1000);
 +    if (ok == 0) {
 +	printk(FORE200E "device %s firmware didn't start\n", fore200e->name);
 +	return -ENODEV;
@@ -4126,8 +4248,8 @@
 +		       "  4b5b:\n"
 +		       "     crc_header_errors:\t\t%10u\n"
 +		       "     framing_errors:\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->phy.crc_header_errors),
-+		       fore200e_dma_swap(fore200e->stats->phy.framing_errors));
++		       fore200e_swap(fore200e->stats->phy.crc_header_errors),
++		       fore200e_swap(fore200e->stats->phy.framing_errors));
 +    
 +    if (!left--)
 +	return sprintf(page, "\n"
@@ -4139,13 +4261,13 @@
 +		       "     path_febe_errors:\t\t%10u\n"
 +		       "     corr_hcs_errors:\t\t%10u\n"
 +		       "     ucorr_hcs_errors:\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->oc3.section_bip8_errors),
-+		       fore200e_dma_swap(fore200e->stats->oc3.path_bip8_errors),
-+		       fore200e_dma_swap(fore200e->stats->oc3.line_bip24_errors),
-+		       fore200e_dma_swap(fore200e->stats->oc3.line_febe_errors),
-+		       fore200e_dma_swap(fore200e->stats->oc3.path_febe_errors),
-+		       fore200e_dma_swap(fore200e->stats->oc3.corr_hcs_errors),
-+		       fore200e_dma_swap(fore200e->stats->oc3.ucorr_hcs_errors));
++		       fore200e_swap(fore200e->stats->oc3.section_bip8_errors),
++		       fore200e_swap(fore200e->stats->oc3.path_bip8_errors),
++		       fore200e_swap(fore200e->stats->oc3.line_bip24_errors),
++		       fore200e_swap(fore200e->stats->oc3.line_febe_errors),
++		       fore200e_swap(fore200e->stats->oc3.path_febe_errors),
++		       fore200e_swap(fore200e->stats->oc3.corr_hcs_errors),
++		       fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors));
 +
 +    if (!left--)
 +	return sprintf(page,"\n"
@@ -4156,12 +4278,12 @@
 +		       "     vpi no conn:\t\t%10u\n"
 +		       "     vci out of range:\t\t%10u\n"
 +		       "     vci no conn:\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->atm.cells_transmitted),
-+		       fore200e_dma_swap(fore200e->stats->atm.cells_received),
-+		       fore200e_dma_swap(fore200e->stats->atm.vpi_bad_range),
-+		       fore200e_dma_swap(fore200e->stats->atm.vpi_no_conn),
-+		       fore200e_dma_swap(fore200e->stats->atm.vci_bad_range),
-+		       fore200e_dma_swap(fore200e->stats->atm.vci_no_conn));
++		       fore200e_swap(fore200e->stats->atm.cells_transmitted),
++		       fore200e_swap(fore200e->stats->atm.cells_received),
++		       fore200e_swap(fore200e->stats->atm.vpi_bad_range),
++		       fore200e_swap(fore200e->stats->atm.vpi_no_conn),
++		       fore200e_swap(fore200e->stats->atm.vci_bad_range),
++		       fore200e_swap(fore200e->stats->atm.vci_no_conn));
 +    
 +    if (!left--)
 +	return sprintf(page,"\n"
@@ -4169,9 +4291,9 @@
 +		       "     TX:\t\t\t%10u\n"
 +		       "     RX:\t\t\t%10u\n"
 +		       "     dropped:\t\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->aal0.cells_transmitted),
-+		       fore200e_dma_swap(fore200e->stats->aal0.cells_received),
-+		       fore200e_dma_swap(fore200e->stats->aal0.cells_dropped));
++		       fore200e_swap(fore200e->stats->aal0.cells_transmitted),
++		       fore200e_swap(fore200e->stats->aal0.cells_received),
++		       fore200e_swap(fore200e->stats->aal0.cells_dropped));
 +    
 +    if (!left--)
 +	return sprintf(page,"\n"
@@ -4187,15 +4309,15 @@
 +		       "       RX:\t\t\t%10u\n"
 +		       "       dropped:\t\t\t%10u\n"
 +		       "       protocol errors:\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->aal34.cells_transmitted),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cells_received),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cells_dropped),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cells_crc_errors),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cells_protocol_errors),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cspdus_transmitted),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cspdus_received),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cspdus_dropped),
-+		       fore200e_dma_swap(fore200e->stats->aal34.cspdus_protocol_errors));
++		       fore200e_swap(fore200e->stats->aal34.cells_transmitted),
++		       fore200e_swap(fore200e->stats->aal34.cells_received),
++		       fore200e_swap(fore200e->stats->aal34.cells_dropped),
++		       fore200e_swap(fore200e->stats->aal34.cells_crc_errors),
++		       fore200e_swap(fore200e->stats->aal34.cells_protocol_errors),
++		       fore200e_swap(fore200e->stats->aal34.cspdus_transmitted),
++		       fore200e_swap(fore200e->stats->aal34.cspdus_received),
++		       fore200e_swap(fore200e->stats->aal34.cspdus_dropped),
++		       fore200e_swap(fore200e->stats->aal34.cspdus_protocol_errors));
 +    
 +    if (!left--)
 +	return sprintf(page,"\n"
@@ -4211,15 +4333,15 @@
 +		       "       dropped:\t\t\t%10u\n"
 +		       "       CRC errors:\t\t%10u\n"
 +		       "       protocol errors:\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->aal5.cells_transmitted),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cells_received),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cells_dropped),
-+		       fore200e_dma_swap(fore200e->stats->aal5.congestion_experienced),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cspdus_transmitted),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cspdus_received),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cspdus_dropped),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cspdus_crc_errors),
-+		       fore200e_dma_swap(fore200e->stats->aal5.cspdus_protocol_errors));
++		       fore200e_swap(fore200e->stats->aal5.cells_transmitted),
++		       fore200e_swap(fore200e->stats->aal5.cells_received),
++		       fore200e_swap(fore200e->stats->aal5.cells_dropped),
++		       fore200e_swap(fore200e->stats->aal5.congestion_experienced),
++		       fore200e_swap(fore200e->stats->aal5.cspdus_transmitted),
++		       fore200e_swap(fore200e->stats->aal5.cspdus_received),
++		       fore200e_swap(fore200e->stats->aal5.cspdus_dropped),
++		       fore200e_swap(fore200e->stats->aal5.cspdus_crc_errors),
++		       fore200e_swap(fore200e->stats->aal5.cspdus_protocol_errors));
 +    
 +    if (!left--)
 +	return sprintf(page,"\n"
@@ -4229,11 +4351,11 @@
 +		       "     small b2:\t\t\t%10u\n"
 +		       "     large b2:\t\t\t%10u\n"
 +		       "     RX PDUs:\t\t\t%10u\n",
-+		       fore200e_dma_swap(fore200e->stats->aux.small_b1_failed),
-+		       fore200e_dma_swap(fore200e->stats->aux.large_b1_failed),
-+		       fore200e_dma_swap(fore200e->stats->aux.small_b2_failed),
-+		       fore200e_dma_swap(fore200e->stats->aux.large_b2_failed),
-+		       fore200e_dma_swap(fore200e->stats->aux.rpd_alloc_failed));
++		       fore200e_swap(fore200e->stats->aux.small_b1_failed),
++		       fore200e_swap(fore200e->stats->aux.large_b1_failed),
++		       fore200e_swap(fore200e->stats->aux.small_b2_failed),
++		       fore200e_swap(fore200e->stats->aux.large_b2_failed),
++		       fore200e_swap(fore200e->stats->aux.rpd_alloc_failed));
 +    
 +    if (!left--)
 +	return sprintf(page,"\n"
@@ -4290,14 +4412,21 @@
 +
 +static const struct atmdev_ops fore200e_ops =
 +{
-+    open:	fore200e_open,
-+    close:	fore200e_close,
-+    ioctl:	fore200e_ioctl,
-+    getsockopt:	fore200e_getsockopt,
-+    setsockopt:	fore200e_setsockopt,
-+    send:	fore200e_send,
-+    change_qos:	fore200e_change_qos,
-+    proc_read:	fore200e_proc_read
++    NULL, /* fore200e_dev_close   */
++    fore200e_open,
++    fore200e_close,
++    fore200e_ioctl,
++    fore200e_getsockopt,
++    fore200e_setsockopt,
++    fore200e_send,
++    NULL, /* fore200e_sg_send,    */
++    NULL, /* fore200e_send_oam,   */
++    NULL, /* fore200e_phy_put,    */
++    NULL, /* fore200e_phy_get,    */
++    NULL, /* fore200e_feedback,   */
++    fore200e_change_qos,
++    NULL, /* free_rx_skb          */
++    fore200e_proc_read
 +};
 +
 +
@@ -4316,9 +4445,11 @@
 +      _fore200e_pca_fw_data, &_fore200e_pca_fw_size,
 +      fore200e_pca_read,
 +      fore200e_pca_write,
-+      fore200e_pca_virt_to_dma,
-+      fore200e_pca_dma_alloc,
-+      fore200e_pca_dma_free,
++      fore200e_pca_dma_map,
++      fore200e_pca_dma_unmap,
++      NULL,
++      fore200e_pca_dma_chunk_alloc,
++      fore200e_pca_dma_chunk_free,
 +      fore200e_pca_detect,
 +      fore200e_pca_configure,
 +      fore200e_pca_map,
@@ -4328,7 +4459,6 @@
 +      NULL,
 +      fore200e_pca_irq_check,
 +      fore200e_pca_irq_ack,
-+      NULL,
 +      fore200e_pca_proc_read,
 +    },
 +#endif
@@ -4337,9 +4467,11 @@
 +      _fore200e_sba_fw_data, &_fore200e_sba_fw_size,
 +      fore200e_sba_read,
 +      fore200e_sba_write,
-+      fore200e_sba_virt_to_dma,
-+      fore200e_sba_dma_alloc,
-+      fore200e_sba_dma_free,
++      fore200e_sba_dma_map,
++      fore200e_sba_dma_unmap,
++      fore200e_sba_dma_sync,
++      fore200e_sba_dma_chunk_alloc,
++      fore200e_sba_dma_chunk_free,
 +      fore200e_sba_detect, 
 +      fore200e_sba_configure,
 +      fore200e_sba_map,
@@ -4349,15 +4481,14 @@
 +      fore200e_sba_irq_enable,
 +      fore200e_sba_irq_check,
 +      fore200e_sba_irq_ack,
-+      fore200e_sba_dma_sync,
 +      fore200e_sba_proc_read,
 +    },
 +#endif
 +    {}
 +};
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/fore200e.h	Fri Jan 21 16:01:04 2000
-@@ -0,0 +1,932 @@
++++ work/drivers/atm/fore200e.h	Mon Jan 31 11:38:24 2000
+@@ -0,0 +1,945 @@
 +#ifndef _FORE200E_H
 +#define _FORE200E_H
 +
@@ -4913,15 +5044,26 @@
 +} host_cmdq_entry_t;
 +
 +
++/* chunk of memory */
++
++typedef struct chunk {
++    void* alloc_addr;    /* base address of allocated chunk */
++    void* align_addr;    /* base address of aligned chunk   */
++    u32   dma_addr;      /* DMA address of aligned chunk    */
++    u32   alloc_size;    /* length of allocated chunk       */
++    u32   align_size;    /* length of aligned chunk         */
++} chunk_t;
++
++#define dma_size align_size             /* DMA useable size */
++
++
 +/* host resident receive buffer */
 +
 +typedef struct buffer {
 +    struct buffer*       next;        /* next receive buffer     */
 +    enum   buffer_scheme scheme;      /* buffer scheme           */
 +    enum   buffer_magn   magn;        /* buffer magnitude        */
-+    void*                data_raw;    /* raw buffer data         */
-+    void*                data_align;  /* DMA aligned buffer data */
-+    u32                  data_dma;    /* DMA address of data     */
++    struct chunk         data;        /* data buffer             */
 +} buffer_t;
 +
 +
@@ -4939,9 +5081,7 @@
 +typedef struct host_cmdq {
 +    struct host_cmdq_entry host_entry[ QUEUE_SIZE_CMD ];    /* host resident cmd queue entries        */
 +    int                    head;                            /* head of cmd queue                      */
-+    enum   status*         status_raw;                      /* raw array of completion status         */
-+    enum   status*         status_align;                    /* DMA aligned array of completion status */
-+
++    struct chunk           status;                          /* array of completion status      */
 +} host_cmdq_t;
 +
 +
@@ -4950,10 +5090,8 @@
 +typedef struct host_txq {
 +    struct host_txq_entry host_entry[ QUEUE_SIZE_TX ];    /* host resident tx queue entries         */
 +    int                   head;                           /* head of tx queue                       */
-+    struct tpd*           tpd_raw;                        /* raw array of tpds                      */
-+    struct tpd*           tpd_align;                      /* DMA aligned array of tpds              */
-+    enum   status*        status_raw;                     /* raw array of completion status         */
-+    enum   status*        status_align;                   /* DMA aligned array of completion status */
++    struct chunk          tpd;                            /* array of tpds                          */
++    struct chunk          status;                         /* arry of completion status              */
 +    int                   txing;                          /* number of pending PDUs in tx queue     */
 +} host_txq_t;
 +
@@ -4963,10 +5101,8 @@
 +typedef struct host_rxq {
 +    struct host_rxq_entry  host_entry[ QUEUE_SIZE_RX ];    /* host resident rx queue entries         */
 +    int                    head;                           /* head of rx queue                       */
-+    struct rpd*            rpd_raw;                        /* raw array of rpds                      */
-+    struct rpd*            rpd_align;                      /* DMA aligned  array of rpds             */
-+    enum   status*         status_raw;                     /* raw array of completion status         */
-+    enum   status*         status_align;                   /* DMA aligned array of completion status */
++    struct chunk           rpd;                            /* array of rpds                          */
++    struct chunk           status;                         /* array of completion status             */
 +} host_rxq_t;
 +
 +
@@ -4975,10 +5111,8 @@
 +typedef struct host_bsq {
 +    struct host_bsq_entry host_entry[ QUEUE_SIZE_BS ];    /* host resident buffer supply queue entries */
 +    int                   head;                           /* head of buffer supply queue               */
-+    struct rbd_block*     rbd_block_raw;                  /* raw array of rbds                         */
-+    struct rbd_block*     rbd_block_align;                /* DMA aligned array fo rbds                 */
-+    enum   status*        status_raw;                     /* raw array of completion status            */
-+    enum   status*        status_align;                   /* DMA aligned array of completion status    */
++    struct chunk          rbd_block;                      /* array of rbds                             */
++    struct chunk          status;                         /* array of completion status                */
 +    struct buffer*        buffer;                         /* array of rx buffers                       */
 +    int                   free;                           /* index of first free rx buffer             */
 +    volatile int          count;                          /* count of supplied rx buffers              */
@@ -5153,9 +5287,11 @@
 +    const unsigned int*  fw_size;             /* address of firmware data size          */
 +    u32                  (*read)(volatile u32*);
 +    void                 (*write)(u32, volatile u32*);
-+    u32                  (*virt_to_dma)(void*);
-+    int                  (*dma_alloc)(void**, void**, u32*, int, int, int);
-+    void                 (*dma_free)(void**);
++    u32                  (*dma_map)(struct fore200e*, void*, int);
++    void                 (*dma_unmap)(struct fore200e*, u32, int);
++    void                 (*dma_sync)(struct fore200e*, u32, int);
++    int                  (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int);
++    void                 (*dma_chunk_free)(struct fore200e*, struct chunk*);
 +    struct fore200e*     (*detect)(const struct fore200e_bus*, int);
 +    int                  (*configure)(struct fore200e*); 
 +    int                  (*map)(struct fore200e*); 
@@ -5165,7 +5301,6 @@
 +    void                 (*irq_enable)(struct fore200e*);
 +    int                  (*irq_check)(struct fore200e*);
 +    void                 (*irq_ack)(struct fore200e*);
-+    void                 (*dma_sync)(struct fore200e*, u32, int);
 +    int                  (*proc_read)(struct fore200e*, char*);
 +} fore200e_bus_t;
 +
@@ -5271,6 +5406,15 @@
 +
 +#define SBA200E_PROM_NAME  "FORE,sba-200e"    /* device name in openprom tree */
 +
++
++/* size of SBA-200E registers */
++
++#define SBA200E_HCR_LENGTH        4
++#define SBA200E_BSR_LENGTH        4
++#define SBA200E_ISR_LENGTH        4
++#define SBA200E_RAM_LENGTH  0x40000
++
++
 +/* SBA-200E host control register */
 +
 +#define SBA200E_HCR_RESET        (1<<0)    /* read / write (sticky) */
@@ -5291,7 +5435,7 @@
 +#endif /* __KERNEL__ */
 +#endif /* _FORE200E_H */
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/fore200e_mkfirm.c	Fri Jan 21 16:01:04 2000
++++ work/drivers/atm/fore200e_mkfirm.c	Mon Jan 31 11:38:24 2000
 @@ -0,0 +1,155 @@
 +/*
 +  $Id: $
@@ -5449,7 +5593,7 @@
 +    exit(0);
 +}
 --- ref/drivers/atm/horizon.c	Wed Sep  8 20:14:31 1999
-+++ work/drivers/atm/horizon.c	Fri Jan 21 16:01:04 2000
++++ work/drivers/atm/horizon.c	Mon Jan 31 11:38:24 2000
 @@ -2623,12 +2623,10 @@
    switch (level) {
      case SOL_SOCKET:
@@ -5512,7 +5656,7 @@
  
  static int __init hrz_probe (void) {
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/idt77105.c	Fri Jan 21 16:01:04 2000
++++ work/drivers/atm/idt77105.c	Mon Jan 31 11:38:24 2000
 @@ -0,0 +1,385 @@
 +/* drivers/atm/idt77105.c - IDT77105 (PHY) driver */
 + 
@@ -5900,7 +6044,7 @@
 +
 +#endif
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/idt77105.h	Fri Jan 21 16:47:47 2000
++++ work/drivers/atm/idt77105.h	Mon Jan 31 11:46:16 2000
 @@ -0,0 +1,92 @@
 +/* drivers/atm/idt77105.h - IDT77105 (PHY) declarations */
 + 
@@ -5995,7 +6139,7 @@
 +
 +#endif
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/iphase.c	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/iphase.c	Mon Jan 31 11:38:24 2000
 @@ -0,0 +1,3315 @@
 +/******************************************************************************
 +         iphase.c: Device driver for Interphase ATM PCI adapter cards 
@@ -9313,7 +9457,7 @@
 +#endif  
 +  
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/iphase.h	Fri Jan 21 16:48:16 2000
++++ work/drivers/atm/iphase.h	Mon Jan 31 11:46:43 2000
 @@ -0,0 +1,1465 @@
 +/******************************************************************************
 +             Device driver for Interphase ATM PCI adapter cards 
@@ -10781,7 +10925,7 @@
 +
 +#endif /* IPHASE_H */
 --- ref/drivers/atm/nicstar.c	Mon Jan 10 23:05:32 2000
-+++ work/drivers/atm/nicstar.c	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/nicstar.c	Mon Jan 31 11:38:24 2000
 @@ -44,6 +44,9 @@
  #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
  #include "suni.h"
@@ -10968,7 +11112,7 @@
     }
  }
 --- ref/drivers/atm/nicstar.h	Mon Aug 23 18:56:31 1999
-+++ work/drivers/atm/nicstar.h	Fri Jan 21 16:47:47 2000
++++ work/drivers/atm/nicstar.h	Mon Jan 31 11:46:16 2000
 @@ -51,7 +51,7 @@
  				   128K x 32bit SRAM will limit the maximum
  				   VCI. */
@@ -11184,7 +11328,7 @@
     int rct_size;			/* Number of entries */
     int vpibits;
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/pca200e.data	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/pca200e.data	Mon Jan 31 11:38:24 2000
 @@ -0,0 +1,850 @@
 +:150000001F8B0808AB5A10380203706361323030652E62696E4D
 +:150015007D00E43A0D7014D7796FA5BDE84EC86211A7333020EE
@@ -12037,7 +12181,7 @@
 +:06459000C0E6B892000035
 +:00000001FF
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/pca200e_ecd.data	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/pca200e_ecd.data	Mon Jan 31 11:38:24 2000
 @@ -0,0 +1,906 @@
 +:150000001F8B0808AC5A10380203706361323030655F65636428
 +:150015002E62696E327D00DC3A0D7054459AFD261333136278A4
@@ -12946,7 +13090,7 @@
 +:104A2800FEFE99F5D6F2FF06E2E5D1A4A89C0000A7
 +:00000001FF
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/drivers/atm/sba200e_ecd.data	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/sba200e_ecd.data	Mon Jan 31 11:38:24 2000
 @@ -0,0 +1,928 @@
 +:150000001F8B0808AC5A10380203736261323030655F65636426
 +:150015002E62696E327D00DC3A0D6C14D7996FD7B3F5AE71CCD4
@@ -13877,7 +14021,7 @@
 +:014BF60000BE
 +:00000001FF
 --- ref/drivers/atm/suni.c	Wed Sep  8 20:14:32 1999
-+++ work/drivers/atm/suni.c	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/suni.c	Mon Jan 31 11:38:24 2000
 @@ -1,6 +1,6 @@
  /* drivers/atm/suni.c - PMC SUNI (PHY) driver */
   
@@ -13921,7 +14065,7 @@
  }
  
 --- ref/drivers/atm/uPD98402.c	Thu Aug 26 21:42:33 1999
-+++ work/drivers/atm/uPD98402.c	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/uPD98402.c	Mon Jan 31 11:38:24 2000
 @@ -1,6 +1,6 @@
  /* drivers/atm/uPD98402.c - NEC uPD98402 (PHY) declarations */
   
@@ -13940,7 +14084,7 @@
  }
  
 --- ref/drivers/atm/zatm.c	Wed Sep  8 20:14:32 1999
-+++ work/drivers/atm/zatm.c	Fri Jan 21 16:01:05 2000
++++ work/drivers/atm/zatm.c	Mon Jan 31 11:38:24 2000
 @@ -1,6 +1,6 @@
  /* drivers/atm/zatm.c - ZeitNet ZN122x device driver */
   
@@ -14023,8 +14167,8 @@
  };
  
  
---- ref/include/linux/atm.h	Fri Jan 21 01:06:57 2000
-+++ work/include/linux/atm.h	Fri Jan 21 16:47:33 2000
+--- ref/include/linux/atm.h	Fri Jan 28 17:03:35 2000
++++ work/include/linux/atm.h	Mon Jan 31 11:46:01 2000
 @@ -1,6 +1,6 @@
  /* atm.h - general ATM declarations */
   
@@ -14126,7 +14270,7 @@
  
  #ifdef __KERNEL__
 --- ref/include/linux/atm_eni.h	Mon Aug 23 18:56:31 1999
-+++ work/include/linux/atm_eni.h	Fri Jan 21 16:47:37 2000
++++ work/include/linux/atm_eni.h	Mon Jan 31 11:38:25 2000
 @@ -1,7 +1,7 @@
  /* atm_eni.h - Driver-specific declarations of the ENI driver (for use by
  	       driver-specific utilities) */
@@ -14153,7 +14297,7 @@
  
  #endif
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/include/linux/atm_idt77105.h	Fri Jan 21 16:01:06 2000
++++ work/include/linux/atm_idt77105.h	Mon Jan 31 11:38:25 2000
 @@ -0,0 +1,40 @@
 +/* atm_idt77105.h - Driver-specific declarations of the IDT77105 driver (for
 + * use by driver-specific utilities) */
@@ -14196,7 +14340,7 @@
 +
 +#endif
 --- ref/include/linux/atm_nicstar.h	Mon Aug 23 18:56:31 1999
-+++ work/include/linux/atm_nicstar.h	Fri Jan 21 16:47:47 2000
++++ work/include/linux/atm_nicstar.h	Mon Jan 31 11:38:25 2000
 @@ -18,6 +18,7 @@
   * sys/types.h for struct timeval
   */
@@ -14215,7 +14359,7 @@
  
  typedef struct pool_levels
 --- ref/include/linux/atm_tcp.h	Wed Sep  8 20:14:32 1999
-+++ work/include/linux/atm_tcp.h	Fri Jan 21 16:48:05 2000
++++ work/include/linux/atm_tcp.h	Mon Jan 31 11:46:33 2000
 @@ -1,12 +1,14 @@
  /* atm_tcp.h - Driver-specific declarations of the ATMTCP driver (for use by
  	       driver-specific utilities) */
@@ -14249,7 +14393,7 @@
  /*
   * Field usage:
 --- ref/include/linux/atm_zatm.h	Mon Aug 23 18:56:31 1999
-+++ work/include/linux/atm_zatm.h	Fri Jan 21 16:47:42 2000
++++ work/include/linux/atm_zatm.h	Mon Jan 31 11:38:25 2000
 @@ -1,7 +1,7 @@
  /* atm_zatm.h - Driver-specific declarations of the ZATM driver (for use by
  		driver-specific utilities) */
@@ -14268,7 +14412,7 @@
  
  #define ZATM_GETPOOL	_IOW('a',ATMIOC_SARPRV+1,struct atmif_sioc)
 --- /dev/null	Tue May  5 22:32:27 1998
-+++ work/include/linux/atmapi.h	Fri Jan 21 16:01:06 2000
++++ work/include/linux/atmapi.h	Mon Jan 31 11:38:25 2000
 @@ -0,0 +1,29 @@
 +/* atmapi.h - ATM API user space/kernel compatibility */
 + 
@@ -14299,8 +14443,8 @@
 +typedef struct { unsigned char _[8]; } atm_kptr_t;
 +
 +#endif
---- ref/include/linux/atmarp.h	Fri Jan 21 01:07:54 2000
-+++ work/include/linux/atmarp.h	Fri Jan 21 16:53:11 2000
+--- ref/include/linux/atmarp.h	Fri Jan 28 17:03:35 2000
++++ work/include/linux/atmarp.h	Mon Jan 31 11:51:38 2000
 @@ -1,6 +1,6 @@
  /* atmarp.h - ATM ARP protocol and kernel-demon interface definitions */
   
@@ -14317,8 +14461,8 @@
  #include <linux/atmioc.h>
  
  
---- ref/include/linux/atmdev.h	Fri Jan 21 01:07:08 2000
-+++ work/include/linux/atmdev.h	Fri Jan 21 16:47:33 2000
+--- ref/include/linux/atmdev.h	Fri Jan 28 17:04:09 2000
++++ work/include/linux/atmdev.h	Mon Jan 31 11:46:01 2000
 @@ -8,6 +8,8 @@
  
  
@@ -14427,7 +14571,7 @@
  
  
 --- ref/include/linux/atmioc.h	Mon Aug 23 18:56:31 1999
-+++ work/include/linux/atmioc.h	Fri Jan 21 16:01:07 2000
++++ work/include/linux/atmioc.h	Mon Jan 31 11:38:25 2000
 @@ -1,10 +1,10 @@
  /* atmioc.h - ranges for ATM-related ioctl numbers */
   
@@ -14442,7 +14586,7 @@
   */
  
 --- ref/include/linux/atmlec.h	Mon Aug 23 18:56:31 1999
-+++ work/include/linux/atmlec.h	Fri Jan 21 16:54:11 2000
++++ work/include/linux/atmlec.h	Mon Jan 31 11:52:37 2000
 @@ -9,6 +9,7 @@
  #ifndef _ATMLEC_H_
  #define _ATMLEC_H_
@@ -14497,7 +14641,7 @@
  struct atmlec_ioc {
          int dev_num;
 --- ref/include/linux/atmmpc.h	Mon Aug 23 18:56:31 1999
-+++ work/include/linux/atmmpc.h	Fri Jan 21 16:54:11 2000
++++ work/include/linux/atmmpc.h	Mon Jan 31 11:52:37 2000
 @@ -1,6 +1,7 @@
  #ifndef _ATMMPC_H_
  #define _ATMMPC_H_
@@ -14545,7 +14689,7 @@
  #endif /* _ATMMPC_H_ */
 -
 --- ref/include/linux/atmsap.h	Mon Aug 23 18:56:32 1999
-+++ work/include/linux/atmsap.h	Fri Jan 21 16:01:07 2000
++++ work/include/linux/atmsap.h	Mon Jan 31 11:38:25 2000
 @@ -1,11 +1,13 @@
  /* atmsap.h - ATM Service Access Point addressing definitions */
  
@@ -14603,7 +14747,7 @@
  
  
 --- ref/include/linux/atmsvc.h	Mon Aug 23 18:56:32 1999
-+++ work/include/linux/atmsvc.h	Fri Jan 21 16:54:11 2000
++++ work/include/linux/atmsvc.h	Mon Jan 31 11:52:37 2000
 @@ -1,11 +1,12 @@
  /* atmsvc.h - ATM signaling kernel-demon interface definitions */
   
@@ -14646,7 +14790,7 @@
  
  /*
 --- ref/include/linux/sonet.h	Mon Aug 23 18:56:32 1999
-+++ work/include/linux/sonet.h	Fri Jan 21 16:01:07 2000
++++ work/include/linux/sonet.h	Mon Jan 31 11:38:25 2000
 @@ -1,22 +1,22 @@
  /* sonet.h - SONET/SHD physical layer control */
   
@@ -14681,8 +14825,8 @@
  
  #define SONET_GETSTAT	_IOR('a',ATMIOC_PHYTYP,struct sonet_stats)
  					/* get statistics */
---- ref/include/net/atmclip.h	Fri Jan 21 01:08:33 2000
-+++ work/include/net/atmclip.h	Fri Jan 21 16:53:11 2000
+--- ref/include/net/atmclip.h	Fri Jan 28 17:04:09 2000
++++ work/include/net/atmclip.h	Mon Jan 31 11:51:38 2000
 @@ -1,6 +1,6 @@
  /* net/atm/atmarp.h - RFC1577 ATM ARP */
   
@@ -14703,7 +14847,7 @@
  };
  
 --- ref/net/sched/sch_atm.c	Wed Sep  8 20:14:32 1999
-+++ work/net/sched/sch_atm.c	Fri Jan 21 16:01:07 2000
++++ work/net/sched/sch_atm.c	Mon Jan 31 11:38:26 2000
 @@ -56,12 +56,14 @@
  
  
@@ -14796,7 +14940,7 @@
  
  	atm_tc_init,			/* init */
 --- ref/net/atm/atm_misc.c	Wed Sep  8 20:14:32 1999
-+++ work/net/atm/atm_misc.c	Fri Jan 21 16:01:07 2000
++++ work/net/atm/atm_misc.c	Mon Jan 31 11:38:26 2000
 @@ -10,13 +10,11 @@
  #include <asm/atomic.h>
  #include <asm/errno.h>
@@ -14822,7 +14966,7 @@
  
  		if (skb) {
 --- ref/net/atm/clip.c	Wed Sep  8 20:14:32 1999
-+++ work/net/atm/clip.c	Fri Jan 21 16:01:07 2000
++++ work/net/atm/clip.c	Mon Jan 31 11:38:26 2000
 @@ -1,6 +1,6 @@
  /* net/atm/clip.c - RFC1577 Classical IP over ATM */
  
@@ -14948,7 +15092,7 @@
  
  
 --- ref/net/atm/common.c	Wed Sep  8 20:14:32 1999
-+++ work/net/atm/common.c	Fri Jan 21 16:53:57 2000
++++ work/net/atm/common.c	Mon Jan 31 11:38:26 2000
 @@ -1,6 +1,6 @@
  /* net/atm/common.c - ATM sockets (common part for PVC and SVC) */
  
@@ -15088,15 +15232,23 @@
  			mask |= POLLOUT | POLLWRNORM;
  	}
  	else if (vcc->reply != WAITING) {
-@@ -530,7 +479,7 @@
- 		case TIOCOUTQ:
+@@ -527,13 +476,13 @@
+ 
+ 	vcc = ATM_SD(sock);
+ 	switch (cmd) {
+-		case TIOCOUTQ:
++		case SIOCOUTQ:
  			if (sock->state != SS_CONNECTED ||
  			    !(vcc->flags & ATM_VF_READY)) return -EINVAL;
 -			return put_user(vcc->tx_quota-
 +			return put_user(vcc->sk->sndbuf-
  			    atomic_read(&vcc->tx_inuse)-ATM_PDU_OVHD,
  			    (int *) arg) ? -EFAULT : 0;
- 		case TIOCINQ:
+-		case TIOCINQ:
++		case SIOCINQ:
+ 			{
+ 				struct sk_buff *skb;
+ 
 @@ -569,30 +518,13 @@
  			return copy_to_user((void *) arg,&vcc->timestamp,
  			    sizeof(struct timeval)) ? -EFAULT : 0;
@@ -15182,7 +15334,7 @@
  			if (!(vcc->flags & ATM_VF_HASQOS)) return -EINVAL;
  			return copy_to_user(optval,&vcc->qos,sizeof(vcc->qos)) ?
 --- ref/net/atm/lec.c	Wed Sep  8 20:14:32 1999
-+++ work/net/atm/lec.c	Fri Jan 21 16:01:07 2000
++++ work/net/atm/lec.c	Mon Jan 31 11:38:26 2000
 @@ -39,7 +39,6 @@
  
  #include "lec.h"
@@ -15417,7 +15569,7 @@
          kfree(to_remove);
  }
 --- ref/net/atm/mpc.c	Mon Aug 23 18:56:32 1999
-+++ work/net/atm/mpc.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/mpc.c	Mon Jan 31 11:38:26 2000
 @@ -27,7 +27,6 @@
  
  #include "lec.h"
@@ -15479,7 +15631,7 @@
  	eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client);
  	if(eg_entry && eg_entry->shortcut){
 --- ref/net/atm/mpoa_caches.c	Mon Aug 23 18:56:32 1999
-+++ work/net/atm/mpoa_caches.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/mpoa_caches.c	Mon Jan 31 11:38:26 2000
 @@ -87,7 +87,7 @@
  					  struct mpoa_client *client)
  {
@@ -15500,7 +15652,7 @@
  		dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
                  entry->entry_state = INGRESS_RESOLVING;
 --- ref/net/atm/mpoa_proc.c	Fri Nov 19 05:02:02 1999
-+++ work/net/atm/mpoa_proc.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/mpoa_proc.c	Mon Jan 31 11:38:26 2000
 @@ -143,7 +143,7 @@
  		while(eg_entry != NULL){
  		  for(i=0;i<ATM_ESA_LEN;i++){
@@ -15511,7 +15663,7 @@
  			/* latest IP address */
  			temp = (unsigned char *)&eg_entry->latest_ip_addr;
 --- ref/net/atm/proc.c	Sun Nov 28 00:27:49 1999
-+++ work/net/atm/proc.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/proc.c	Mon Jan 31 11:38:26 2000
 @@ -1,6 +1,6 @@
  /* net/atm/proc.c - ATM /proc interface */
  
@@ -15743,7 +15895,7 @@
  	return -ENOMEM;
  }
 --- ref/net/atm/raw.c	Wed Sep  8 20:14:32 1999
-+++ work/net/atm/raw.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/raw.c	Mon Jan 31 11:38:26 2000
 @@ -11,14 +11,8 @@
  #include <linux/skbuff.h>
  #include <linux/mm.h>
@@ -15771,7 +15923,7 @@
  	atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
  	dev_kfree_skb(skb);
 --- ref/net/atm/resources.c	Mon Aug 23 18:56:32 1999
-+++ work/net/atm/resources.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/resources.c	Mon Jan 31 11:38:26 2000
 @@ -145,8 +145,10 @@
  		sk_free(sk);
  		return NULL;
@@ -15784,7 +15936,7 @@
  	vcc->prev = NULL;
  	vcc->next = nodev_vccs;
 --- ref/net/atm/signaling.c	Mon Aug 23 18:56:32 1999
-+++ work/net/atm/signaling.c	Fri Jan 21 16:01:08 2000
++++ work/net/atm/signaling.c	Mon Jan 31 11:38:26 2000
 @@ -1,6 +1,6 @@
  /* net/atm/signaling.c - ATM signaling */
  
@@ -15835,7 +15987,7 @@
  	while (!(skb = alloc_skb(sizeof(struct atmsvc_msg),GFP_KERNEL)))
  		schedule();
  	msg = (struct atmsvc_msg *) skb_put(skb,sizeof(struct atmsvc_msg));
-+	memset(msg,0,sizeof(msg));
++	memset(msg,0,sizeof(*msg));
  	msg->type = type;
 -	msg->vcc = (unsigned long) vcc;
 -	msg->listen_vcc = (unsigned long) listen_vcc;
@@ -15868,7 +16020,7 @@
  
  
 --- ref/net/atm/signaling.h	Mon Aug 23 18:56:32 1999
-+++ work/net/atm/signaling.h	Fri Jan 21 16:54:11 2000
++++ work/net/atm/signaling.h	Mon Jan 31 11:52:37 2000
 @@ -1,6 +1,6 @@
  /* net/atm/signaling.h - ATM signaling */
   
@@ -15886,8 +16038,26 @@
      const struct sockaddr_atmsvc *svc);
  int sigd_attach(struct atm_vcc *vcc);
  void signaling_init(void);
+--- ref/net/atm/svc.c	Wed Sep  8 20:14:32 1999
++++ work/net/atm/svc.c	Mon Jan 31 11:38:26 2000
+@@ -1,6 +1,6 @@
+ /* net/atm/svc.c - ATM SVC sockets */
+ 
+-/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
++/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
+ 
+ 
+ #include <linux/string.h>
+@@ -253,6 +253,7 @@
+ 		new_vcc->qos = msg->qos;
+ 		new_vcc->flags |= ATM_VF_HASQOS;
+ 		new_vcc->remote = msg->svc;
++		new_vcc->local = msg->local;
+ 		new_vcc->sap = msg->sap;
+ 		error = atm_connect(newsock,msg->pvc.sap_addr.itf,
+ 		    msg->pvc.sap_addr.vpi,msg->pvc.sap_addr.vci);
 --- ref/net/atm/tunable.h	Wed Sep  8 20:14:32 1999
-+++ work/net/atm/tunable.h	Fri Jan 21 16:01:08 2000
++++ work/net/atm/tunable.h	Mon Jan 31 11:38:26 2000
 @@ -1,16 +0,0 @@
 -/* net/atm/tunable.h - Tunable parameters of ATM support */
 -
diff -ur --new-file old/atm/doc/t2a.pl new/atm/doc/t2a.pl
--- old/atm/doc/t2a.pl	Tue Nov 12 19:12:49 1996
+++ new/atm/doc/t2a.pl	Mon Jan 31 11:00:50 2000
@@ -1,6 +1,6 @@
 #!/usr/bin/perl
 #
-# Copyright 1994-1996 Werner Almesberger.
+# Copyright 1994-2000 Werner Almesberger.
 # All rights reserved.
 #
 # See file COPYING for details.
diff -ur --new-file old/atm/doc/usage.tex new/atm/doc/usage.tex
--- old/atm/doc/usage.tex	Fri Jan 21 07:04:44 2000
+++ new/atm/doc/usage.tex	Mon Jan 31 14:55:14 2000
@@ -1,7 +1,7 @@
-%def%:=
+%%def%:=
 
 %:\begin{verbatim}
-%:Usage instructions  -  ATM on Linux, release 0.65
+%:Usage instructions  -  ATM on Linux, release 0.66
 %:-------------------------------------------------
 %:
 %:\end{verbatim}
@@ -38,14 +38,14 @@
 
 \title{ATM on Linux \\
   User's guide \\
-  Release 0.65 (beta)}
+  Release 0.66 (beta)}
 \author{Werner Almesberger \\
   {\tt Werner.Almesberger@epfl.ch} \\
   \\
   Institute for computer Communications and Applications (ICA) \\
   EPFL, CH-1015 Lausanne, Switzerland}
  
-\date{January 21, 2000}
+\date{January 31, 2000}
 
 \begin{document}
 \maketitle
@@ -82,9 +82,9 @@
 In order to install this package, you need
 \begin{itemize}
   \item the package itself
-    \url{ftp://icaftp.epfl.ch/pub/linux/atm/dist/atm-0.65.tar.gz}
-  \item the Linux kernel, version 2.3.40, e.g. from
-    \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.3/linux-2.3.40.tar.gz}
+    \url{ftp://icaftp.epfl.ch/pub/linux/atm/dist/atm-0.66.tar.gz}
+  \item the Linux kernel, version 2.3.41, e.g. from
+    \url{ftp://ftp.kernel.org/pub/linux/kernel/v2.3/linux-2.3.41.tar.gz}
   \item Perl, version 4 or 5
   \item if you want memory debugging: MPR version 1.6, e.g. from
     \url{ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz}
@@ -99,13 +99,13 @@
 distribution:
 
 \begin{verbatim}
-tar xfz atm-0.65.tar.gz
+tar xfz atm-0.66.tar.gz
 \end{verbatim}
 
 and the kernel source:
 
 \begin{verbatim}
-tar xfz linux-2.3.40.tar.gz
+tar xfz linux-2.3.41.tar.gz
 \end{verbatim}
 
 Finally, you can extract the ATM-related patches:
diff -ur --new-file old/atm/doc/usage.txt new/atm/doc/usage.txt
--- old/atm/doc/usage.txt	Fri Jan 21 09:17:27 2000
+++ new/atm/doc/usage.txt	Mon Jan 31 14:57:14 2000
@@ -1,13 +1,10 @@
-%:Usage instructions  -  ATM on Linux, release 0.65
-%:-------------------------------------------------
-%:
-%:
+Usage instructions  -  ATM on Linux, release 0.66
+-------------------------------------------------
 
 For updates of ATM on Linux, please check the Web page at  
 http://ica1www.epfl.ch/linux-atm/ 
 
-%:         WARNING
-%:
+         WARNING
 
 This is experimental software. There are known major bugs and certainly 
 even many more yet unknown problems. Internal and external interfaces are 
@@ -20,9 +17,9 @@
 In order to install this package, you need 
 
   - the package itself  
-    ftp://icaftp.epfl.ch/pub/linux/atm/dist/atm-0.65.tar.gz  
-  - the Linux kernel, version 2.3.40, e.g. from  
-    ftp://ftp.kernel.org/pub/linux/kernel/v2.3/linux-2.3.40.tar.gz  
+    ftp://icaftp.epfl.ch/pub/linux/atm/dist/atm-0.66.tar.gz  
+  - the Linux kernel, version 2.3.41, e.g. from  
+    ftp://ftp.kernel.org/pub/linux/kernel/v2.3/linux-2.3.41.tar.gz  
   - Perl, version 4 or 5 
   - if you want memory debugging: MPR version 1.6, e.g. from  
     ftp://sunsite.unc.edu/pub/Linux/devel/lang/c/mpr-1.6.tar.gz  
@@ -36,11 +33,11 @@
 all the files listed above there. Then extract the ATM on Linux 
 distribution:
 
-tar xfz atm-0.65.tar.gz
+tar xfz atm-0.66.tar.gz
 
 and the kernel source:
 
-tar xfz linux-2.3.40.tar.gz
+tar xfz linux-2.3.41.tar.gz
 
 Finally, you can extract the ATM-related patches:
 
diff -ur --new-file old/atm/ilmid/io.c new/atm/ilmid/io.c
--- old/atm/ilmid/io.c	Thu Nov 18 19:36:48 1999
+++ new/atm/ilmid/io.c	Fri Jan 28 15:11:08 2000
@@ -26,10 +26,10 @@
 #include <sys/ioctl.h>
 #include <errno.h>
 #include <net/if.h>
+#include <atm.h>
 #include <linux/atmdev.h>
 #include "io.h"
 #include "atmd.h"
-#include "atm.h"
 #include "atmf_uni.h"
 
 #define SNMP_VCI 16
diff -ur --new-file old/atm/ilmid/io.h new/atm/ilmid/io.h
--- old/atm/ilmid/io.h	Sat Oct 10 11:16:13 1998
+++ new/atm/ilmid/io.h	Fri Jan 28 15:11:18 2000
@@ -25,6 +25,7 @@
 #define IO_H
 
 #include <sys/time.h>
+#include <atm.h>
 #include <linux/atmdev.h>
 #include "asn_incl.h"
 #include "rfc1155_smi.h"
diff -ur --new-file old/atm/maint/atmaddr.c new/atm/maint/atmaddr.c
--- old/atm/maint/atmaddr.c	Tue Jan 18 10:11:24 2000
+++ new/atm/maint/atmaddr.c	Fri Jan 28 09:31:18 2000
@@ -9,7 +9,7 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 
-#include "atm.h"
+#include <atm.h>
 #include <linux/atmdev.h>
 
 
diff -ur --new-file old/atm/mkdist new/atm/mkdist
--- old/atm/mkdist	Fri Jan 21 09:16:41 2000
+++ new/atm/mkdist	Fri Jan 28 12:45:41 2000
@@ -123,7 +123,8 @@
     atm/switch/swc.h atm/switch/swc.c atm/switch/README \
     atm/switch/debug/README atm/switch/debug/Makefile atm/switch/debug/debug.c \
     atm/switch/debug/demo \
-    atm/switch/tcp/README atm/switch/tcp/Makefile atm/switch/tcp/tcpsw.c \
+    atm/switch/tcp/README atm/switch/tcp/Makefile atm/switch/tcp/mkfiles \
+    atm/switch/tcp/tcpsw.c \
   atm/extra/extra.html atm/extra/Makefile \
     atm/extra/tcpdump-3.4.patch atm/extra/tcpdump-3.4.patch.sunrpc \
     atm/extra/bind-4.9.5-REL.patch atm/extra/hosts2ans.pl \
diff -ur --new-file old/atm/sigd/io.c new/atm/sigd/io.c
--- old/atm/sigd/io.c	Fri Jan 21 08:28:39 2000
+++ new/atm/sigd/io.c	Fri Jan 28 12:54:57 2000
@@ -14,7 +14,7 @@
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 
-#include "atm.h"
+#include <atm.h>
 #include <linux/atmdev.h>
 #include <linux/atmsvc.h>
 
@@ -373,7 +373,7 @@
     req.arg = &rate;
     req.length = sizeof(rate);
     if (ioctl(entities->signaling,ATM_GETLINKRATE,&req) < 0)
-	diag(COMPONENT,DIAG_FATAL,"ioctl ATM_GETLINERATE yields \"%s\"",
+	diag(COMPONENT,DIAG_FATAL,"ioctl ATM_GETLINKRATE yields \"%s\"",
 	  strerror(errno));
     return rate;
 }
diff -ur --new-file old/atm/sigd/kernel.c new/atm/sigd/kernel.c
--- old/atm/sigd/kernel.c	Fri Jan 21 08:39:30 2000
+++ new/atm/sigd/kernel.c	Fri Jan 28 11:59:57 2000
@@ -8,7 +8,7 @@
 #include <errno.h>
 #include <assert.h>
 
-#include "atm.h"
+#include <atm.h>
 #include <linux/atmsvc.h>
 #include <linux/atmdev.h>
 
@@ -45,7 +45,9 @@
     q_create(&dsc,q_buffer,MAX_Q_MSG);
     local = NULL;
     error = 0;
-    if (atmsvc_addr_in_use(sock->local)) {
+    sock->sig = route_remote(&sock->remote);
+    if (sock->sig && sock->sig->mode == sm_switch) local = &sock->local;
+    if (atmsvc_addr_in_use(sock->local) && !local) {
 	sock->sig = route_local(&sock->local);
 	if (sock->sig) local = &sock->local;
 	else {
@@ -54,10 +56,9 @@
 	}
     }
     else {
-	sock->sig = route_remote(&sock->remote);
 	if (!sock->sig) error = -EHOSTUNREACH;
 	else {
-	    local = get_local(sock->sig);
+	    if (!local) local = get_local(sock->sig);
 	    if (!local) local = get_local(NULL);
 	    if (local) sock->local = *local;
 	    else {
@@ -561,7 +562,7 @@
 	 */
 	return;
     }
-    if (kptr_eq(&msg->listen_vcc,&kptr_null) && (msg->type == as_accept ||
+    if (!kptr_eq(&msg->listen_vcc,&kptr_null) && (msg->type == as_accept ||
       msg->type == as_reject || msg->type == as_identify)) {
 	dispatcher = dispatch_listen;
 	for (curr = sockets; curr; curr = curr->next)
diff -ur --new-file old/atm/sigd/proto.c new/atm/sigd/proto.c
--- old/atm/sigd/proto.c	Fri Jan 21 08:39:55 2000
+++ new/atm/sigd/proto.c	Fri Jan 28 13:03:14 2000
@@ -527,6 +527,7 @@
     VPCI *vpci;
     int max;
 
+    if (sig->mode == sm_switch) return 0; /* switches don't use ATM_MAX_PCR */
     max = 0;
     for (vpci = sig->vpcis; vpci; vpci = vpci->next) {
 	int curr;
diff -ur --new-file old/atm/sigd/sap.c new/atm/sigd/sap.c
--- old/atm/sigd/sap.c	Tue Nov 30 22:38:51 1999
+++ new/atm/sigd/sap.c	Fri Jan 28 09:32:41 2000
@@ -1,16 +1,15 @@
 /* sap.c - SAP manipulations */
  
-/* Written 1996-1999 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */
  
 
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <stdint.h> /* linux/atmdev and linux/atmsvc.h include linux/atm.h */
+#include <atm.h>
 #include <linux/atmdev.h>
 #include <linux/atmsvc.h>
 
-#include "atm.h"
 #include "atmd.h"
 #include "uni.h"
 #include "qlib.h"
diff -ur --new-file old/atm/sigd/sap.h new/atm/sigd/sap.h
--- old/atm/sigd/sap.h	Thu Mar 25 16:56:25 1999
+++ new/atm/sigd/sap.h	Fri Jan 28 09:32:55 2000
@@ -1,11 +1,12 @@
 /* sap.h - SAP manipulations */
 
-/* Written 1996-1999 by Werner Almesberger, EPFL-LRC/ICA */
+/* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */
 
 
 #ifndef SAP_H
 #define SAP_H
 
+#include <linux/atm.h>
 #include <linux/atmsvc.h>
 
 #include "atmsap.h"
diff -ur --new-file old/atm/sigd/timeout.c new/atm/sigd/timeout.c
--- old/atm/sigd/timeout.c	Fri Jan 21 16:32:10 2000
+++ new/atm/sigd/timeout.c	Fri Jan 28 09:32:59 2000
@@ -7,7 +7,7 @@
 #include <errno.h>
 #include <assert.h>
 
-#include "atm.h"
+#include <atm.h>
 #include <linux/atmdev.h>
 
 #include "atmd.h"
diff -ur --new-file old/atm/sigd/uni.c new/atm/sigd/uni.c
--- old/atm/sigd/uni.c	Fri Jan 21 08:40:11 2000
+++ new/atm/sigd/uni.c	Fri Jan 28 09:33:04 2000
@@ -10,7 +10,7 @@
 #include <errno.h>
 #include <assert.h>
 
-#include "atm.h"
+#include <atm.h>
 #include <linux/atmdev.h>
 
 #include "atmd.h"
diff -ur --new-file old/atm/switch/debug/README new/atm/switch/debug/README
--- old/atm/switch/debug/README	Fri Jan 21 18:39:06 2000
+++ new/atm/switch/debug/README	Fri Jan 28 12:11:14 2000
@@ -17,17 +17,17 @@
 
 Preparation (only once):
 
-  # atmtcp -b virtual 1 listen 8412 &
-  # atmtcp -b virtual 2 connect localhost 8412
-  # atmtcp -b virtual 3 listen 8434 &
-  # atmtcp -b virtual 4 connect localhost 8434
+  # atmtcp virtual 1 listen-bg 8412
+  # atmtcp virtual 2 connect localhost 8412 bg
+  # atmtcp virtual 3 listen-bg 8434
+  # atmtcp virtual 4 connect localhost 8434 bg
   # atmaddr -a 1 +123
 
 Start the "network" (no privileges required):
 
   % atmsigd -b 1.0.105 /tmp/1
-  % atmsigd -b -N -A 2.0.105 /tmp/2
-  % atmsigd -b -N -A 3.0.105 /tmp/3
+  % atmsigd -b -m switch 2.0.105 /tmp/2
+  % atmsigd -b -m switch 3.0.105 /tmp/3
   % atmsigd -b 4.0.105 /tmp/4
   % ./sw_debug -d
   % isp /tmp/4 <4.isp
@@ -43,23 +43,23 @@
 		   |			                 |
 		 /tmp/2			               /tmp/3
 		   |			                 |
-    +------------------------------+	  +------------------------------+
-    | atmsigd -N -A 2.0.105 /tmp/2 |	  | atmsigd -N -A 3.0.105 /tmp/3 |
-    +------------------------------+	  +------------------------------+
+  +----------------------------------+ +----------------------------------+
+  | atmsigd -m switch 2.0.105 /tmp/2 | | atmsigd -m switch 3.0.105 /tmp/3 |
+  +----------------------------------+ +----------------------------------+
 		   |			                 |
 		 itf 2			                 |
 	           |					 |
-+-----------------------------------------+              |
-| atmtcp virtual 2 connect localhost 8412 |              |
-+-----------------------------------------+              |
-|      atmtcp virtual 1 listen 8412       |              |
-+-----------------------------------------+            itf 3
++--------------------------------------------+           |
+| atmtcp virtual 2 connect localhost 8412 bg |           |
++--------------------------------------------+           |
+|      atmtcp virtual 1 listen-bg 8412       |           |
++--------------------------------------------+         itf 3
 	           |					 |
-                 itf 1             +-----------------------------------------+
-                   |               |      atmtcp virtual 3 listen 8434       |
-                   |               +-----------------------------------------+
-                   |               | atmtcp virtual 4 connect localhost 8434 |
-                   |               +-----------------------------------------+
+                 itf 1          +--------------------------------------------+
+                   |            |      atmtcp virtual 3 listen-bg 8434       |
+                   |            +--------------------------------------------+
+                   |            | atmtcp virtual 4 connect localhost 8434 bg |
+                   |            +--------------------------------------------+
 	           |					 |
 		   |				       itf 4
 		   |					 |
@@ -83,11 +83,11 @@
 --- switch.conf --------------------------------------------------------------
 
 socket /tmp/2 {
-    itf 2
+    itf 2 2.0.5
     route +1
 }
 socket /tmp/3 {
-    itf 3
+    itf 3 2.0.5
     default
 }
 
diff -ur --new-file old/atm/switch/debug/debug.c new/atm/switch/debug/debug.c
--- old/atm/switch/debug/debug.c	Wed Sep  9 19:46:55 1998
+++ new/atm/switch/debug/debug.c	Fri Jan 28 10:48:04 2000
@@ -1,6 +1,6 @@
 /* debug.c - Simple debugging "switch" */
 
-/* Written 1998 by Werner Almesberger, EPFL DI-ICA */
+/* Written 1998-2000 by Werner Almesberger, EPFL DI-ICA */
 
 
 #include <stdlib.h>
@@ -34,6 +34,7 @@
 
 void fab_start(void (*port_notify)(int number,int up))
 {
+    sig_start_all(port_notify);
 }
 
 
diff -ur --new-file old/atm/switch/relay.c new/atm/switch/relay.c
--- old/atm/switch/relay.c	Thu Oct  1 19:42:03 1998
+++ new/atm/switch/relay.c	Fri Jan 28 13:17:29 2000
@@ -1,7 +1,7 @@
 /* switch.c - Handles signaling an ATM switch */
 
 /* Written 1997-1998 by Roman Pletka, EPFL SSC */
-/* Modified 1998 by Werner Almesberger, EPFL ICA */
+/* Modified 1998-2000 by Werner Almesberger, EPFL ICA */
 
 
 #include <stdio.h>
@@ -140,7 +140,7 @@
 		    /* save msg content in call */
 		    call->out.qos = msg->qos;
 		    new_state(call,cs_called_accepted);
-		    fab_op(call,RM_CLAIM(_RM_ANY),NULL,from_fab,NULL);
+		    fab_op(call,RM_CLAIM(_RM_ANY),&msg->qos,from_fab,NULL);
 		    return;
 		case as_error:
 		    send_reject(call,msg->reply);
diff -ur --new-file old/atm/switch/sig.c new/atm/switch/sig.c
--- old/atm/switch/sig.c	Wed Aug 12 12:41:30 1998
+++ new/atm/switch/sig.c	Fri Jan 28 11:34:54 2000
@@ -149,6 +149,16 @@
 	remove_entity(sig);
 	fab_op(sig->call,RM_FREE,NULL,down_callback,NULL);
 	free_call(sig->call);
-	
+    }
+}
+
+
+void sig_start_all(void (*port_notify)(int number,int up))
+{
+    SIGNALING_ENTITY *sig;
+
+    for (sig = entities; sig; sig = sig->next) {
+	sig->call = NULL;
+	up_callback(NULL,0,NULL,sig);
     }
 }
diff -ur --new-file old/atm/switch/sig.h new/atm/switch/sig.h
--- old/atm/switch/sig.h	Wed Jun 24 13:20:07 1998
+++ new/atm/switch/sig.h	Fri Jan 28 10:47:49 2000
@@ -1,15 +1,14 @@
 /* sig.h - signaling entity handling */
 
-/* Written 1998 by Werner Almesberger, EPFL ICA */
+/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
 
 
 #ifndef SIG_H
 #define SIG_H
 
+#include <atm.h>
 #include <linux/atmsvc.h>
 
-#include "atm.h"
-
 
 typedef struct _signaling_entity {
     int s;			/* socket */
@@ -25,5 +24,12 @@
 SIGNALING_ENTITY *sig_vc(const char *command,const char *path,int itf);
 void sig_send(SIGNALING_ENTITY *sig,struct atmsvc_msg *msg);
 void sig_notify(int itf,int up);
+
+/*
+ * sig_start can be called by fab_start if fab_start has no knowledge of
+ * ports, e.g. if ports are virtual and pre-configured.
+ */
+
+void sig_start_all(void (*port_notify)(int number,int up));
 
 #endif
diff -ur --new-file old/atm/switch/tcp/README new/atm/switch/tcp/README
--- old/atm/switch/tcp/README	Fri Jan 21 06:09:28 2000
+++ new/atm/switch/tcp/README	Fri Jan 28 15:10:27 2000
@@ -4,11 +4,11 @@
 Commands:
 
 lrcpc4:~/w/atm/switch/tcp# ./sw_tcp -b -d
-lrcpc4:~# atmtcp -b virtual 1 switch localhost 1
-lrcpc4:~# atmtcp -b virtual 2 switch localhost 2
+lrcpc4:~# atmtcp virtual 1 switch localhost 1 bg
+lrcpc4:~# atmtcp virtual 2 switch localhost 2 bg
 lrcpc4:~# atmaddr -a 2 +1
 lrcpc4:~/w/atm/switch/tcp# atmsigd -b -c 2.conf
-lrcpc15:~# atmtcp -b virtual 1 switch lrcpc4 3
+lrcpc15:~# atmtcp virtual 1 switch lrcpc4 3 bg
 lrcpc15:~# atmaddr -a 1 +2
 lrcpc15:~/w/atm/switch/tcp# atmsigd -b -c 1.conf
 lrcpc15:~$ ttcp_atm -r -a
@@ -55,7 +55,7 @@
 io vc 2.0.5
 sig vpci 0 itf 2
 
-
+--- -
 
 The following picture shows a simplified view of the configuration. Note
 that the command-line options have been choosen for clarity (and minor
@@ -91,13 +91,13 @@
 +-----------------------------------+ | +-----------------------------------+
 |atmtcp virtual 2 switch localhost 2| | |atmtcp virtual 1 switch localhost 1|
 +-----------------------------------+ | +-----------------------------------+
-                   |                 |
-	       itf 2 (+1)	     +----- - - - - - -----+
-		   |					   |
-           +---------------+        |  on lrcpc15:	   |
-           | atmsigd 2.0.5 |				   |
-           +---------------+	    |		           |
-							   |
+                   |                  |
+	       itf 2 (+1)	      +---- - - - - - ----+
+		   |					  |
+           +---------------+        |  on lrcpc15:	  |
+           | atmsigd 2.0.5 |				  |
+           +---------------+	    |		          |
+							  |
 				    |   +--------------------------------+
                                     |   |atmtcp virtual 1 switch lrcpc4 3|
                                     |   +--------------------------------+
diff -ur --new-file old/atm/switch/tcp/mkfiles new/atm/switch/tcp/mkfiles
--- old/atm/switch/tcp/mkfiles	Thu Jan  1 01:00:00 1970
+++ new/atm/switch/tcp/mkfiles	Fri Jan 28 13:53:55 2000
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+open(IN,"README") || die "open README: $!";
+while (<IN>) {
+    if (/^---\s*(\S+)\s*/) {
+	if ($writing) {
+	    close OUT || die "close: $!";
+	    $writing = 0;
+	}
+	next if $1 eq "-";
+	open(OUT,">$1") || die "create $1: $!";
+	$writing = 1;
+	next;
+    }
+    print OUT $_ || die "write: $!" if $writing;
+}
+close OUT || die "close: $!" if $writing;
+for (@do) {
+    print "$_\n";
+    system($_);
+    sleep(1);
+}