diff -urP linux-2.2.6-clean/drivers/net/acenic.c linux-2.2.6/drivers/net/acenic.c
--- linux-2.2.6-clean/drivers/net/acenic.c	Mon Mar 22 16:08:12 1999
+++ linux-2.2.6/drivers/net/acenic.c	Mon May  3 12:02:17 1999
@@ -20,6 +20,10 @@
  * Additional work by Pete Wyckoff <wyckoff@ca.sandia.gov> for initial
  * Alpha and trace dump support.
  */
+/* 
+ * Alterations made for use with the Great User-Safe Device project
+ * by Tim Deegan <tjd21@cl.cam.ac.uk> starting in April 1999
+ */
 
 #define PKT_COPY_THRESHOLD 300
 
@@ -241,6 +245,9 @@
 #if 0
 		dev->do_ioctl = &ace_ioctl;
 #endif
+#ifdef DEBUGGING_IOCTLS
+                dev->do_ioctl = &ace_do_ioctl;
+#endif
 		dev->set_mac_address = &ace_set_mac_addr;
 		dev->change_mtu = &ace_change_mtu;
 
@@ -1873,6 +1880,76 @@
 	return result;
 }
 
+
+#ifdef DEBUGGING_IOCTLS
+
+/*
+ *  I/F for debugging firmware through ioctls. We provide 2
+ *  ioctls, to read and write 32-bit values from the shared memory
+ */
+
+static int ace_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
+{
+    struct ace_private *ap;
+    struct acenic_ioc_req rq;
+    __volatile__ u32 *ptr;
+    unsigned long flags;
+
+    /* The Alteon card has a DMA engine on it -- allowing unprivileged
+     * users to monkey with it would be foolish :)
+     */
+    if (current->euid != 0)
+        return -EPERM;
+    
+    ap = (struct ace_private *)dev->priv;
+    if (!ap) return -ENODEV;
+    
+    /* Go get the arguments */
+    if (copy_from_user(&rq, ifr->ifr_data, sizeof(rq)))
+        return -EFAULT;
+
+    /* Check the arguments */
+    if (((rq.cardoffset & 0x3)
+        /* Not 32-bit aligned */
+        || (rq.cardoffset > 0x3FFc)))   
+        /* Larger than shared address space */
+        return -EINVAL;
+
+    /* Work out where in our memory that offset is */
+    ptr  = ((u32 *)ap->regs);
+    ptr += (rq.cardoffset / 4);
+        
+    switch(cmd) 
+    {
+    case ACENIC_IOCTL_READ_SMEM:
+        /* Read data from the card. */
+        spin_lock_irqsave(&ap->lock, flags);       
+        rq.data = *ptr;
+        spin_unlock_irqrestore(&ap->lock, flags);
+        /* Send it back to the user */
+        if (copy_to_user(ifr->ifr_data, &rq, sizeof(rq)))
+            return -EFAULT;
+        break;
+
+    case ACENIC_IOCTL_WRITE_SMEM: 
+        /* Send data to the card */
+        spin_lock_irqsave(&ap->lock, flags);
+        *ptr = rq.data;
+        rq.data = *ptr;
+        spin_unlock_irqrestore(&ap->lock, flags);       
+        /* Send it back to the user */
+        if (copy_to_user(ifr->ifr_data, &rq, sizeof(rq)))
+            return -EFAULT;
+        break;
+
+    default:
+        return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+#endif
 
 /*
  * Local variables:
diff -urP linux-2.2.6-clean/drivers/net/acenic.h linux-2.2.6/drivers/net/acenic.h
--- linux-2.2.6-clean/drivers/net/acenic.h	Mon Mar 22 16:08:12 1999
+++ linux-2.2.6/drivers/net/acenic.h	Wed Apr 28 17:38:14 1999
@@ -1,6 +1,12 @@
 #ifndef _ACENIC_H_
 #define _ACENIC_H_
 
+/* 
+ *  TJD April 1999: Debugging ioctls...
+ */
+
+#define DEBUGGING_IOCTLS
+
 /*
  * Addressing:
  *
@@ -670,5 +676,13 @@
 static int ace_set_mac_addr(struct device *dev, void *p);
 static struct net_device_stats *ace_get_stats(struct device *dev);
 static u8 read_eeprom_byte(struct ace_regs *regs, unsigned long offset);
+
+#ifdef DEBUGGING_IOCTLS
+
+#define MIN(_x, _y) (((_x) <= (_y)) ? (_x) : (_y))
+#include "acenic_ioctls.h"
+static int ace_do_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+
+#endif
 
 #endif /* _ACENIC_H_ */
diff -urP linux-2.2.6-clean/drivers/net/acenic_ioctls.h linux-2.2.6/drivers/net/acenic_ioctls.h
--- linux-2.2.6-clean/drivers/net/acenic_ioctls.h	Thu Jan  1 01:00:00 1970
+++ linux-2.2.6/drivers/net/acenic_ioctls.h	Fri Apr 16 10:56:39 1999
@@ -0,0 +1,32 @@
+/*
+ *  acenic_ioctls.h
+ *  ---------------
+ *
+ *  tjd 25.03.99
+ *
+ *  Definitions for using the SIOCDEVPRIVATE ioctls to debug the firmware in
+ *  Alteon's Tigon II chipset Gigabit Ethernet cards.
+ *
+ */
+
+#include <asm/types.h>
+
+/* 
+ * If we provide methods to read & write data to and from the card, 
+ * we can do anything we want on top of that.
+ */
+
+#define ACENIC_IOCTL_READ_SMEM  SIOCDEVPRIVATE
+#define ACENIC_IOCTL_WRITE_SMEM (SIOCDEVPRIVATE + 1)
+
+/* The structures we pass in as the arguments */
+struct acenic_ioc_req {
+    unsigned long int cardoffset; 
+    /* Where on the card - must be a multiple of 4 and < 0x3FFc */
+    __u32  data;  
+    /* What to put there (read ioctl puts return val here) */
+};
+
+/*
+ *  EOF
+ */
