diff -ur --new-file old/linux/arch/ppc/config.in new/linux/arch/ppc/config.in
--- old/linux/arch/ppc/config.in	Tue May 11 17:24:32 1999
+++ new/linux/arch/ppc/config.in	Fri Jun 11 22:57:21 1999
@@ -141,6 +141,9 @@
   bool 'Network device support' CONFIG_NETDEVICES
   if [ "$CONFIG_NETDEVICES" = "y" ]; then
     source drivers/net/Config.in
+    if [ "$CONFIG_ATM" = "y" ]; then
+      source drivers/atm/Config.in
+    fi
   fi
   endmenu
 fi
diff -ur --new-file old/linux/drivers/atm/Makefile new/linux/drivers/atm/Makefile
--- old/linux/drivers/atm/Makefile	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/Makefile	Fri Jun 11 22:57:21 1999
@@ -24,7 +24,8 @@
 L_OBJS += zatm.o uPD98402.o
 else
   ifeq ($(CONFIG_ATM_ZATM),m)
-  M_OBJS += zatm.o uPD98402.o
+  M_OBJS += zatm.o
+  MX_OBJS += uPD98402.o
   endif
 endif
 
diff -ur --new-file old/linux/drivers/atm/ambassador.c new/linux/drivers/atm/ambassador.c
--- old/linux/drivers/atm/ambassador.c	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/ambassador.c	Fri Jun 11 22:57:21 1999
@@ -44,7 +44,7 @@
 
 #define maintainer_string "Giuliano Procida at Madge Networks <gprocida@madge.com>"
 #define description_string "Madge ATM Ambassador driver"
-#define version_string "1.1"
+#define version_string "1.1.3"
 
 static inline void __init show_version (void) {
   printk ("%s version %s\n", description_string, version_string);
@@ -122,11 +122,11 @@
   
   The queue pairs work as follows: one queue is for supply to the
   adapter, items in it are pending and are owned by the adapter; the
-  other is the for return from the adapter, items in it have been
-  dealt with by the adapter. The host adds items to the supply (TX
-  descriptors and free RX buffer descriptors) and removes items from
-  the return (TX and RX completions). The adapter deals with out of
-  order completions.
+  other is the queue for return from the adapter, items in it have
+  been dealt with by the adapter. The host adds items to the supply
+  (TX descriptors and free RX buffer descriptors) and removes items
+  from the return (TX and RX completions). The adapter deals with out
+  of order completions.
   
   Interrupts (card to host) and the doorbell (host to card) are used
   for signalling.
@@ -170,25 +170,26 @@
 
     delay/spacing = latency = (20+2)/3 = 7 (buffers)  (rounding up)
     
-  The 20us delay assumes that there is no need to touch disk; if we
-  need touch disk to get buffers we are going to drop frames anyway.
-   
+  The 20us delay assumes that there is no need to sleep; if we need to
+  sleep to get buffers we are going to drop frames anyway.
+  
   In fact, each pool should have enough buffers to support the
   simultaneous reassembly of a separate frame on each VC and cope with
-  the case in which large frames arrive with round robin cell arrivals
-  on each VC.
-   
+  the case in which frames complete in round robin cell fashion on
+  each VC.
+  
   Only one frame can complete at each cell arrival, so if "n" VCs are
   open, the worst case is to have them all complete frames together
   followed by all starting new frames together.
   
-    min number of buffers = n + delay/spacing
+    desired number of buffers = n + delay/spacing
     
   These are the extreme requirements, however, they are "n+k" for some
   "k" so we have only the constant to choose. This is the argument
-  rx_lats which current defaults at 3.
+  rx_lats which current defaults to 7.
   
-  Actually, "n ? n+k : 0" is better and this is what is implemented.
+  Actually, "n ? n+k : 0" is better and this is what is implemented,
+  subject to the limit given by the pool size.
   
   4. Driver locking
   
@@ -202,7 +203,7 @@
   and close functions. There are three reasons for a lock: 1. we need
   to do atomic rate reservation and release (not used yet), 2. Opening
   sometimes involves two adapter commands which must not be separated
-  by another command on the same VC, 3. the changes in RX pool size
+  by another command on the same VC, 3. the changes to RX pool size
   must be atomic. The lock needs to work over context switches, so we
   use a semaphore.
   
@@ -233,8 +234,8 @@
   
   Now we:
   . Note that skb_alloc rounds up size to a 16byte boundary.  
-  . Ensure all areas must not traverse 4MB boundaries.
-  . Ensure all areas must not start at a E00000xx bus address.
+  . Ensure all areas do not traverse 4MB boundaries.
+  . Ensure all areas do not start at a E00000xx bus address.
   (I cannot be certain, but this may always hold with Linux)
   . Make all failures cause a loud message.
   . Discard non-conforming SKBs (causes TX failure or RX fill delay).
@@ -880,11 +881,9 @@
   
   while (irq_ok_old != irq_ok && irq_ok < 100) {
     unsigned char pool;
-#ifdef DEBUG_AMBASSADOR
-    u32 ints = rd_mem (dev, &mem->interrupt);
-#endif
+    PRINTD (DBG_IRQ, "FYI: interrupt was %08x, work %u",
+	    rd_mem (dev, &mem->interrupt), irq_ok);
     wr_mem (dev, &mem->interrupt, -1);
-    PRINTD (DBG_IRQ, "FYI: interrupt was %08x, work %u", ints, irq_ok);
     irq_ok_old = irq_ok;
     for (pool = 0; pool < NUM_RX_POOLS; ++pool)
       while (!rx_take (dev, pool))
@@ -970,9 +969,9 @@
 /********** make rate (not quite as much fun as Horizon) **********/
 
 static unsigned int make_rate (unsigned int rate, rounding r,
-			u16 * bits, unsigned int * actual) {
-  unsigned char exp = 0; /* silence gcc */
-  unsigned int man = 0;
+			       u16 * bits, unsigned int * actual) {
+  unsigned char exp = -1; // hush gcc
+  unsigned int man = -1;  // hush gcc
   
   PRINTD (DBG_FLOW|DBG_QOS, "make_rate %u", rate);
   
@@ -987,12 +986,20 @@
   // find position of top bit, this gives e
   // remove top bit and shift (rounding if feeling clever) by 9-e
   
-  // XXX fix me to work with larger ints
-  
   // ucode bug: please don't set bit 14! 0 not representable
   
-  if (rate) {
-    // non-zero rate
+  if (rate > 0xffc00000U) {
+    // larger than largest representable rate
+    
+    if (r == round_up) {
+	return -EINVAL;
+    } else {
+      exp = 31;
+      man = 511;
+    }
+    
+  } else if (rate) {
+    // representable rate
     
     exp = 31;
     man = rate;
@@ -1007,13 +1014,14 @@
     // rate = (2^31+(man-2^31))*2^(exp-31)
     // rate = (1+(man-2^31)/2^31)*2^exp
     man = man<<1;
+    man &= 0xffffffffU; // a nop on 32-bit systems
     // rate = (1+man/2^32)*2^exp
     
     // exp is in the range 0 to 31, man is in the range 0 to 2^32-1
     // time to lose significance... we want m in the range 0 to 2^9-1
     // rounding presents a minor problem... we first decide which way
-    // we are rounding (based on given rounding direction and the bits
-    // of the mantissa that are to be discarded).
+    // we are rounding (based on given rounding direction and possibly
+    // the bits of the mantissa that are to be discarded).
     
     switch (r) {
       case round_down: {
@@ -1026,13 +1034,9 @@
 	if (man & (-1>>9)) {
 	  man = (man>>(32-9)) + 1;
 	  if (man == (1<<9)) {
-	    // check for round up outside of range
-	    if (exp == 31) {
-	      return -EINVAL;
-	    } else {
-	      man = 0;
-	      exp += 1;
-	    }
+	    // no need to check for round up outside of range
+	    man = 0;
+	    exp += 1;
 	  }
 	} else {
 	  man = (man>>(32-9));
@@ -1043,14 +1047,10 @@
 	// check msb that we are discarding
 	if (man & (1<<(32-9-1))) {
 	  man = (man>>(32-9)) + 1;
-	  // if rounding up would go out of range, just stay at top
 	  if (man == (1<<9)) {
-	    if (exp == 31) {
-	      man -= 1;
-	    } else {
-	      man = 0;
-	      exp += 1;
-	    }
+	    // no need to check for round up outside of range
+	    man = 0;
+	    exp += 1;
 	  }
 	} else {
 	  man = (man>>(32-9));
@@ -1060,19 +1060,13 @@
     }
     
   } else {
-    // zero rate
+    // zero rate - not representable
     
-    switch (r) {
-      case round_up: {
-	break;
-      }
-      case round_down: {
-	return -EINVAL;
-	break;
-      }
-      case round_nearest: {
-	break;
-      }
+    if (r == round_down) {
+      return -EINVAL;
+    } else {
+      exp = 0;
+      man = 0;
     }
     
   }
@@ -1104,18 +1098,17 @@
   struct atm_trafprm * txtp;
   struct atm_trafprm * rxtp;
   u16 tx_rate_bits;
-  u16 tx_vc_bits = 0; /* silence gcc */
-  u16 tx_frame_bits = 0;
-  // int pcr;
+  u16 tx_vc_bits = -1; // hush gcc
+  u16 tx_frame_bits = -1; // hush gcc
   
   amb_dev * dev = AMB_DEV(atm_vcc->dev);
   amb_vcc * vcc;
-  unsigned char pool = -1; // compiler warning
+  unsigned char pool = -1; // hush gcc
   
   PRINTD (DBG_FLOW|DBG_VCC, "amb_open %x %x", vpi, vci);
   
+#ifdef ATM_VPI_UNSPEC
   // UNSPEC is deprecated, remove this code eventually
-#if defined ATM_VPI_UNSPEC
   if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) {
     PRINTK (KERN_WARNING, "rejecting open with unspecified VPI/VCI (deprecated)");
     return -EINVAL;
@@ -1282,7 +1275,6 @@
     vcc->rx_info.pool = pool;
     
     down (&dev->vcc_sf); 
-    
     /* grow RX buffer pool */
     if (!dev->rxq[pool].buffers_wanted)
       dev->rxq[pool].buffers_wanted = rx_lats;
@@ -1392,7 +1384,6 @@
       dev->rxq[pool].buffers_wanted = 0;
       drain_rx_pool (dev, pool);
     }
-
     up (&dev->vcc_sf);
   }
   
@@ -1674,8 +1665,8 @@
   amb_open,
   amb_close,
   NULL,          // no amb_ioctl,
-  NULL, // amb_getsockopt,
-  NULL, // amb_setsockopt,
+  NULL,          // no amb_getsockopt,
+  NULL,          // no amb_setsockopt,
   amb_send,
   amb_sg_send,
   NULL,          // no send_oam    - not in fact used yet
@@ -1718,8 +1709,9 @@
 
 /********** creation of communication queues **********/
 
-static int create_queues (amb_dev * dev, unsigned int cmds, unsigned int txs,
-			  unsigned int * rxs, unsigned int * rx_buffer_sizes) {
+static int __init create_queues (amb_dev * dev, unsigned int cmds,
+				 unsigned int txs, unsigned int * rxs,
+				 unsigned int * rx_buffer_sizes) {
   unsigned char pool;
   size_t total = 0;
   void * memory;
@@ -1848,8 +1840,8 @@
 
 /********** basic loader commands and error handling **********/
 
-static int do_loader_command (const amb_dev * dev, loader_command cmd,
-			      volatile loader_block * lb) {
+static int __init do_loader_command (const amb_dev * dev, loader_command cmd,
+				     volatile loader_block * lb) {
   
   // centisecond timeouts - guessing away here
   unsigned int command_timeouts [] = {
@@ -1865,8 +1857,7 @@
     [adap_run_in_iram]     = 1,
     [adap_end_download]    = 1
   };
-
-#if 0 /* unused */
+  
   unsigned int command_successes [] = {
     [host_memory_test]     = COMMAND_PASSED_TEST,
     [read_adapter_memory]  = COMMAND_READ_DATA_OK,
@@ -1880,11 +1871,14 @@
     [adap_run_in_iram]     = COMMAND_COMPLETE,
     [adap_end_download]    = COMMAND_COMPLETE
   };
-#endif
   
-  int decode_loader_error (u32 result) {
+  int decode_loader_result (loader_command cmd, u32 result) {
     int res;
     const char * msg;
+    
+    if (result == command_successes[cmd])
+      return 0;
+    
     switch (result) {
       case BAD_COMMAND:
 	res = -EINVAL;
@@ -1937,12 +1931,12 @@
       default:
 	res = -EINVAL;
 	msg = "unknown error";
-	PRINTD (DBG_LOAD|DBG_ERR, "decode_loader_error got %d=%x !",
+	PRINTD (DBG_LOAD|DBG_ERR, "decode_loader_result got %d=%x !",
 		result, result);
 	break;
     }
-    if (res)
-      PRINTK (KERN_ERR, "%s", msg);
+    
+    PRINTK (KERN_ERR, "%s", msg);
     return res;
   }
   
@@ -1991,25 +1985,14 @@
       }
     return 0;
   } else {
-    return decode_loader_error (be32_to_cpu (lb->result));
+    return decode_loader_result (cmd, be32_to_cpu (lb->result));
   }
   
-#if 0
-  if ((res != COMMAND_PASSED_TEST) &&
-      (res != COMMAND_READ_DATA_OK) &&
-      (res != COMMAND_WRITE_DATA_OK) &&
-      (res != COMMAND_COMPLETE)) {
-    PRINTD (DBG_LOAD|DBG_ERR"startup cmd %d failed with error %08x",
-	    cmd, res);
-    dump_registers (dev);
-    return -EIO;
-  }
-#endif
 }
 
 /* loader: determine loader version */
 
-static int get_loader_version (const amb_dev * dev, u32 * version) {
+static int __init get_loader_version (const amb_dev * dev, u32 * version) {
   loader_block lb;
   int res;
   
@@ -2025,8 +2008,8 @@
 
 /* loader: read or verify memory data blocks */
 
-static int loader_write (const amb_dev * dev, const u32 * data,
-		  u32 address, unsigned int count) {
+static int __init loader_write (const amb_dev * dev, const u32 * data,
+				u32 address, unsigned int count) {
   unsigned int i;
   loader_block lb;
   transfer_block * tb = &lb.payload.transfer;
@@ -2042,8 +2025,8 @@
   return do_loader_command (dev, write_adapter_memory, &lb);
 }
 
-static int loader_verify (const amb_dev * dev, const u32 * data,
-		   u32 address, unsigned int count) {
+static int __init loader_verify (const amb_dev * dev, const u32 * data,
+				 u32 address, unsigned int count) {
   unsigned int i;
   loader_block lb;
   transfer_block * tb = &lb.payload.transfer;
@@ -2065,7 +2048,7 @@
   return res;
 }
 
-static int loader_start (const amb_dev * dev, u32 address) {
+static int __init loader_start (const amb_dev * dev, u32 address) {
   loader_block lb;
   
   PRINTD (DBG_FLOW|DBG_LOAD, "loader_start");
@@ -2139,7 +2122,7 @@
 
 /********** transfer and start the microcode **********/
 
-static int ucode_init (amb_dev * dev) {
+static int __init ucode_init (amb_dev * dev) {
   unsigned int i = 0;
   unsigned int total = 0;
   const u32 * pointer = ucode_data;
@@ -2185,7 +2168,7 @@
 
 /********** give adapter parameters **********/
 
-static int amb_talk (amb_dev * dev) {
+static int __init amb_talk (amb_dev * dev) {
   adap_talk_block a;
   unsigned char pool;
   unsigned long timeout;
@@ -2238,7 +2221,7 @@
 }
 
 // get microcode version
-static void amb_ucode_version (amb_dev * dev) {
+static void __init amb_ucode_version (amb_dev * dev) {
   u32 major;
   u32 minor;
   command cmd;
@@ -2251,7 +2234,7 @@
 }
 
 // get end station address
-static void amb_esi (amb_dev * dev, u8 * esi) {
+static void __init amb_esi (amb_dev * dev, u8 * esi) {
   u32 lower4;
   u16 upper2;
   command cmd;
@@ -2292,7 +2275,7 @@
   return;
 }
 
-static int amb_init (amb_dev * dev) {
+static int __init amb_init (amb_dev * dev) {
   u32 version;
   
   /* enable adapter doorbell */
@@ -2618,8 +2601,6 @@
 
 int __init amb_detect (void) {
   int devs;
-  
-  PRINTD (DBG_FLOW|DBG_INIT, "init_module");
   
   // sanity check - cast needed as printk does not support %Zu
   if (sizeof(amb_mem) != 4*16 + 4*12) {
diff -ur --new-file old/linux/drivers/atm/atmsar11.data new/linux/drivers/atm/atmsar11.data
--- old/linux/drivers/atm/atmsar11.data	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/atmsar11.data	Fri Jun 11 22:57:21 1999
@@ -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,
diff -ur --new-file old/linux/drivers/atm/atmsar11.regions new/linux/drivers/atm/atmsar11.regions
--- old/linux/drivers/atm/atmsar11.regions	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/atmsar11.regions	Fri Jun 11 22:57:21 1999
@@ -1,3 +1,6 @@
+/*
+  See copyright and licensing conditions in ambassador.* files.
+*/
   { 0x00000080,  993, },
   { 0xa0d0d500,   80, },
   { 0xa0d0f000,  978, },
diff -ur --new-file old/linux/drivers/atm/atmsar11.start new/linux/drivers/atm/atmsar11.start
--- old/linux/drivers/atm/atmsar11.start	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/atmsar11.start	Fri Jun 11 22:57:21 1999
@@ -1 +1,4 @@
+/*
+  See copyright and licensing conditions in ambassador.* files.
+*/
   0xa0d0f000
diff -ur --new-file old/linux/drivers/atm/atmtcp.c new/linux/drivers/atm/atmtcp.c
--- old/linux/drivers/atm/atmtcp.c	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/atmtcp.c	Fri Jun 11 22:57:21 1999
@@ -1,6 +1,6 @@
 /* drivers/atm/atmtcp.c - ATM over TCP "device" driver */
 
-/* Written 1997,1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1997-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/module.h>
@@ -323,8 +323,12 @@
 	return 0;
 }
 
+
 void cleanup_module(void)
 {
+	atm_tcp_ops.attach = NULL;
+	atm_tcp_ops.create_persistent = NULL;
+	atm_tcp_ops.remove_persistent = NULL;
 }
 
 #else
@@ -336,4 +340,3 @@
 };
 
 #endif
-    
diff -ur --new-file old/linux/drivers/atm/horizon.c new/linux/drivers/atm/horizon.c
--- old/linux/drivers/atm/horizon.c	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/horizon.c	Fri Jun 11 22:57:21 1999
@@ -51,9 +51,9 @@
 
 #define maintainer_string "Giuliano Procida at Madge Networks <gprocida@madge.com>"
 #define description_string "Madge ATM Horizon [Ultra] driver"
-#define version_string "1.1"
+#define version_string "1.1.3"
 
-static void __init show_version (void) {
+static inline void __init show_version (void) {
   printk ("%s version %s\n", description_string, version_string);
 }
 
@@ -87,7 +87,7 @@
   
   The driver is only known to work with SONET and UTP Horizon Ultra
   cards at 155Mb/s. However, code is in place to deal with both the
-  original Horizon and 35Mb/s.
+  original Horizon and 25Mb/s operation.
   
   There are two revisions of the Horizon ASIC: the original and the
   Ultra. Details of hardware bugs are in section III.
@@ -128,15 +128,15 @@
   
   3. Initialisation
   
-  The card is reset and then put into a know state. The physical layer
-  is configured for normal operation at the appropriate speed; in the
-  case of the 155 cards, the framer is initialised with line-based
-  timing; the internal RAM is zeroed and the allocation of buffers for
-  RX and TX is made; the Burnt In Address is read and copied to the
-  ATM ESI; various policy settings for RX (VPI bits, unknown VCs, oam
-  cells) are made. Ideally all policy items should be configurable at
-  module load (if not actually on-demand), however, only the vpi vs
-  vci bit allocation can be specified at insmod.
+  The card is reset and then put into a known state. The physical
+  layer is configured for normal operation at the appropriate speed;
+  in the case of the 155 cards, the framer is initialised with
+  line-based timing; the internal RAM is zeroed and the allocation of
+  buffers for RX and TX is made; the Burnt In Address is read and
+  copied to the ATM ESI; various policy settings for RX (VPI bits,
+  unknown VCs, oam cells) are made. Ideally all policy items should be
+  configurable at module load (if not actually on-demand), however,
+  only the vpi vs vci bit allocation can be specified at insmod.
   
   4. Shutdown
   
@@ -220,17 +220,18 @@
   "raw cell" to ATM Linux's (48 bytes vs. 52 bytes) so neither are
   supported by this driver.
   
-  The Horizon has (TX) support for ABR (including UBR), VBR and CBR.
-  Each TX channel has a bucket (containing up to 31 cell units) and
-  two timers (PCR and SCR) associated with it that can be used to
-  govern cell emissions and host notification (in the case of
-  ABR). The timers may either be disabled or may be set to any of 240
-  values (determined by the clock crystal, a fixed (?) per-device
-  divider, a configurable divider and a configurable timer preload
-  value).
-  
-  At the moment only UBR and CBR are supported by the driver. This is
-  due to my not understanding ATM Linux VBR or Horizon's VBR support.
+  The Horizon has limited support for ABR (including UBR), VBR and
+  CBR. Each TX channel has a bucket (containing up to 31 cell units)
+  and two timers (PCR and SCR) associated with it that can be used to
+  govern cell emissions and host notification (in the case of ABR this
+  is presumably so that RM cells may be emitted at appropriate times).
+  The timers may either be disabled or may be set to any of 240 values
+  (determined by the clock crystal, a fixed (?) per-device divider, a
+  configurable divider and a configurable timer preload value).
+  
+  At the moment only UBR and CBR are supported by the driver. VBR will
+  be supported as soon as ATM for Linux supports it. ABR support is
+  very unlikely as RM cell handling is completely up to the driver.
   
   1. TX (TX channel setup and TX transfer)
   
@@ -306,7 +307,7 @@
   in the TX direction on the original Horizon. More complicated
   solutions are likely to hurt my brain.
   
-  3. Loss of buffer on close VC
+  2. Loss of buffer on close VC
   
   When a VC is being closed, the buffer associated with it is not
   returned to the pool. The host must store the reference to this
@@ -315,7 +316,7 @@
   The host intervention currently consists of stacking such a buffer
   pointer at VC close and checking the stack at VC open.
   
-  4. Failure to close a VC
+  3. Failure to close a VC
   
   If a VC is currently receiving a frame then closing the VC may fail
   and the frame continues to be received.
@@ -323,7 +324,7 @@
   The solution is to make sure any received frames are flushed when
   ready. This is currently done just before the solution to 3.
   
-  5. PCI bus (original Horizon only, fixed in Ultra)
+  4. PCI bus (original Horizon only, fixed in Ultra)
   
   Reading from the data port prior to initialisation will hang the PCI
   bus. Just don't do that then! We don't.
@@ -402,7 +403,7 @@
 static inline u32 rd_mem (const hrz_dev * dev, HDW * addr) {
   // wr_regl (dev, MEM_RD_ADDR_REG_OFF, (u32) addr);
   wr_regl (dev, MEM_RD_ADDR_REG_OFF, (addr - (HDW *) 0) * sizeof(HDW));
-  return rd_regl(dev, MEMORY_PORT_OFF);
+  return rd_regl (dev, MEMORY_PORT_OFF);
 }
 
 static inline void wr_framer (const hrz_dev * dev, u32 addr, u32 data) {
@@ -512,7 +513,7 @@
 
 /* RX channels are 10 bit integers, these fns are quite paranoid */
 
-static inline int channel_to_vpci (const u16 channel, short * vpi, int * vci) {
+static inline int channel_to_vpivci (const u16 channel, short * vpi, int * vci) {
   unsigned short vci_bits = 10 - vpi_bits;
   if ((channel & RX_CHANNEL_MASK) == channel) {
     *vci = channel & ((~0)<<vci_bits);
@@ -522,7 +523,7 @@
   return -EINVAL;
 }
 
-static inline int vpci_to_channel (u16 * channel, const short vpi, const int vci) {
+static inline int vpivci_to_channel (u16 * channel, const short vpi, const int vci) {
   unsigned short vci_bits = 10 - vpi_bits;
   if (0 <= vpi && vpi < 1<<vpi_bits && 0 <= vci && vci < 1<<vci_bits) {
     *channel = vpi<<vci_bits | vci;
@@ -1574,7 +1575,7 @@
 			      vcc->tx_pcr_bits);
 
 #if 0
-    if (a vbr channel) {
+    if (vcc->tx_xbr_bits == VBR_RATE_TYPE) {
       // SCR timer
       update_tx_channel_config (dev, tx_channel, SCR_TIMER_ACCESS,
 				vcc->tx_scr_bits);
@@ -1585,7 +1586,7 @@
       
       // ... and fullness
       update_tx_channel_config (dev, tx_channel, BUCKET_FULLNESS_ACCESS,
-			      vcc->tx_bucket_bits);
+				vcc->tx_bucket_bits);
     }
 #endif    
 
@@ -1803,7 +1804,7 @@
 
 /********** reset a card **********/
 
-static void __init hrz_reset_card (const hrz_dev * dev) {
+static void __init hrz_reset (const hrz_dev * dev) {
   u32 control_0_reg = rd_regl (dev, CONTROL_0_REG);
   
   // why not set RESET_HORIZON to one and wait for the card to
@@ -1822,18 +1823,6 @@
   wr_regl (dev, CONTROL_0_REG, control_0_reg);
 }
 
-/********** shutdown a card **********/
-
-#ifdef MODULE
-
-static void hrz_shutdown (const hrz_dev * dev) {
-  hrz_reset_card (dev);
-  
-  GREEN_LED_OFF(dev);
-}
-
-#endif
-
 /********** read the burnt in address **********/
 
 static u16 __init read_bia (const hrz_dev * dev, u16 addr) {
@@ -1932,7 +1921,7 @@
   // Reset the card to get everything in a known state
   
   printk (" reset");
-  hrz_reset_card (dev);
+  hrz_reset (dev);
   
   // Clear all the buffer memory
   
@@ -2200,8 +2189,8 @@
   hrz_vcc * vccp; // allocated late
   PRINTD (DBG_FLOW|DBG_VCC, "hrz_open %x %x", vpi, vci);
   
+#ifdef ATM_VPI_UNSPEC
   // UNSPEC is deprecated, remove this code eventually
-#if defined ATM_VPI_UNSPEC
   if (vpi == ATM_VPI_UNSPEC || vci == ATM_VCI_UNSPEC) {
     PRINTK (KERN_WARNING, "rejecting open with unspecified VPI/VCI (deprecated)");
     return -EINVAL;
@@ -2216,7 +2205,7 @@
   }
   PRINTD (DBG_VCC, "atm_find_ci gives %x %x", vpi, vci);
   
-  error = vpci_to_channel (&channel, vpi, vci);
+  error = vpivci_to_channel (&channel, vpi, vci);
   if (error) {
     PRINTD (DBG_WARN|DBG_VCC, "VPI/VCI out of range: %hd/%d", vpi, vci);
     return error;
@@ -2460,7 +2449,7 @@
 	  // slight race (no locking) here so we may get -EAGAIN
 	  // later; the greedy bastards would deserve it :)
 	  PRINTD (DBG_QOS, "snatching all remaining RX bandwidth");
-	  pcr = dev->tx_avail;
+	  pcr = dev->rx_avail;
 	} else if (pcr < 0) {
 	  pcr = -pcr;
 	}
@@ -2473,14 +2462,15 @@
 	}
 	break;
       }
+#if 0
       case ATM_VBR: {
-	// int scr = atm_scr_goal (txtp);
+	// int scr = atm_scr_goal (rxtp);
 	int scr = 1<<16; // just for fun
 	if (!scr) {
 	  // slight race (no locking) here so we may get -EAGAIN
 	  // later; the greedy bastards would deserve it :)
 	  PRINTD (DBG_QOS, "snatching all remaining RX bandwidth");
-	  scr = dev->tx_avail;
+	  scr = dev->rx_avail;
 	} else if (scr < 0) {
 	  scr = -scr;
 	}
@@ -2493,6 +2483,7 @@
 	}
 	break;
       }
+#endif
       default: {
 	PRINTD (DBG_QOS, "unsupported RX traffic class");
 	return -EINVAL;
@@ -2633,8 +2624,10 @@
   MOD_DEC_USE_COUNT;
 }
 
+#if 0
 static int hrz_getsockopt (struct atm_vcc * atm_vcc, int level, int optname,
 			   void *optval, int optlen) {
+  hrz_dev * dev = HRZ_DEV(atm_vcc->dev);
   PRINTD (DBG_FLOW|DBG_VCC, "hrz_getsockopt");
   switch (level) {
     case SOL_SOCKET:
@@ -2656,6 +2649,7 @@
 
 static int hrz_setsockopt (struct atm_vcc * atm_vcc, int level, int optname,
 			   void *optval, int optlen) {
+  hrz_dev * dev = HRZ_DEV(atm_vcc->dev);
   PRINTD (DBG_FLOW|DBG_VCC, "hrz_setsockopt");
   switch (level) {
     case SOL_SOCKET:
@@ -2674,6 +2668,7 @@
   }
   return -EINVAL;
 }
+#endif
 
 static int hrz_sg_send (struct atm_vcc * atm_vcc,
 			unsigned long start,
@@ -2725,13 +2720,16 @@
 #if 0
   {
     // VBR temporary diags
+    unsigned int count = sprintf (page, "buckets:");
     unsigned int i;
     for (i = 0; i < TX_CHANS; ++i) {
       if (!left--)
-	return sprintf (page, "bucket %u: %u/%u\n", i, 
-			query_tx_channel_config (dev, i, BUCKET_FULLNESS_ACCESS),
-			query_tx_channel_config (dev, i, BUCKET_CAPACITY_ACCESS));
+	count += sprintf (page, " %u/%u",
+			  query_tx_channel_config (dev, i, BUCKET_FULLNESS_ACCESS),
+			  query_tx_channel_config (dev, i, BUCKET_CAPACITY_ACCESS));
     }
+    count += sprintf (page+count, ".\n");
+    return count;
   }
 #endif
   
@@ -2761,8 +2759,8 @@
   hrz_open,
   hrz_close,
   NULL,          // no hrz_ioctl
-  hrz_getsockopt,
-  hrz_setsockopt,
+  NULL,          // hrz_getsockopt,
+  NULL,          // hrz_setsockopt,
   hrz_send,
   hrz_sg_send,
   NULL,          // no send_oam    - not in fact used yet
@@ -2908,7 +2906,7 @@
 	// writes to adapter memory (handles IRQ and SMP)
 	spin_lock_init (&dev->mem_lock);
 	
-	init_waitqueue_head(&dev->tx_queue);
+	init_waitqueue_head (&dev->tx_queue);
         
         // vpi in 0..4, vci in 6..10
         dev->atm_dev->ci_range.vpi_bits = vpi_bits;
@@ -3018,7 +3016,7 @@
     hrz_devs = dev->prev;
     
     PRINTD (DBG_INFO, "closing %p (atm_dev = %p)", dev, dev->atm_dev);
-    hrz_shutdown (dev);
+    hrz_reset (dev);
     atm_dev_deregister (dev->atm_dev);
     free_irq (dev->irq, dev);
     release_region (dev->iobase, HRZ_IO_EXTENT);
diff -ur --new-file old/linux/drivers/atm/horizon.h new/linux/drivers/atm/horizon.h
--- old/linux/drivers/atm/horizon.h	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/horizon.h	Fri Jun 11 22:57:21 1999
@@ -39,7 +39,7 @@
 #ifndef PCI_VENDOR_ID_MADGE
 #define PCI_VENDOR_ID_MADGE               0x10B6
 #endif
-#ifndef PCI_VENDOR_ID_MADGE_HORIZON
+#ifndef PCI_DEVICE_ID_MADGE_HORIZON
 #define PCI_DEVICE_ID_MADGE_HORIZON       0x1000
 #endif
 
@@ -373,8 +373,6 @@
 
 #define memmap ((MEMMAP *)0)
 
-#define BUF_PTR(cbptr) ((cbptr) - (cell_buf *) 0)
-
 /* end horizon specific bits */
 
 typedef enum {
@@ -463,6 +461,8 @@
 typedef struct hrz_dev hrz_dev;
 
 /* macros for use later */
+
+#define BUF_PTR(cbptr) ((cbptr) - (cell_buf *) 0)
 
 #define INTERESTING_INTERRUPTS \
   (RX_DATA_AV | RX_DISABLED | TX_BUS_MASTER_COMPLETE | RX_BUS_MASTER_COMPLETE)
diff -ur --new-file old/linux/drivers/atm/nicstar.c new/linux/drivers/atm/nicstar.c
--- old/linux/drivers/atm/nicstar.c	Fri Jun 11 22:55:59 1999
+++ new/linux/drivers/atm/nicstar.c	Fri Jun 11 22:57:21 1999
@@ -884,6 +884,7 @@
    card->atmdev->ci_range.vci_bits = card->vcibits;
    card->atmdev->link_rate = card->max_pcr;
 
+   card->atmdev->phy = NULL;
 #ifdef CONFIG_ATM_NICSTAR_USE_SUNI
    if (card->max_pcr == ATM_OC3_PCR) {
       suni_init(card->atmdev);
diff -ur --new-file old/linux/net/atm/Makefile new/linux/net/atm/Makefile
--- old/linux/net/atm/Makefile	Fri Jun 11 22:56:00 1999
+++ new/linux/net/atm/Makefile	Fri Jun 11 22:57:22 1999
@@ -15,8 +15,8 @@
 
 ifeq ($(CONFIG_ATM),y)
 
-O_OBJS	= addr.o pvc.o raw.o signaling.o svc.o # party.o
-OX_OBJS = common.o atm_misc.o resources.o
+O_OBJS	= addr.o pvc.o signaling.o svc.o # party.o
+OX_OBJS = common.o atm_misc.o raw.o resources.o
 
 ifeq ($(CONFIG_MMU_HACKS),y)
 O_OBJS += mmuio.o
diff -ur --new-file old/linux/net/atm/raw.c new/linux/net/atm/raw.c
--- old/linux/net/atm/raw.c	Fri Jun 11 22:56:00 1999
+++ new/linux/net/atm/raw.c	Fri Jun 11 22:57:22 1999
@@ -1,9 +1,10 @@
 /* net/atm/raw.c - Raw AAL0 and AAL5 transports */
 
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC */
+/* Written 1995-1999 by Werner Almesberger, EPFL LRC/ICA */
 
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/atmdev.h>
 #include <linux/kernel.h>
@@ -78,3 +79,6 @@
 	vcc->push_oam = NULL;
 	return 0;
 }
+
+
+EXPORT_SYMBOL(atm_init_aal5);