diff -u --recursive --new-file v2.0.15/linux/Documentation/Changes linux/Documentation/Changes
--- v2.0.15/linux/Documentation/Changes	Wed Aug 21 09:18:07 1996
+++ linux/Documentation/Changes	Sat Aug 31 19:39:10 1996
@@ -20,20 +20,21 @@
 
    Para aquellos que prefieran una version en castellano de este
 documento, consultad la traduccion de Alfredo Sanjuan en
-http://slug.ctv.es/~alfredo/Cambios.html.
+http://slug.ctv.es/~alfredo/Cambios.html (Spanish translation).
 
    Akik magyarul szeretnenek olvasni az uj kernellel kapcsolatos
 valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
-http://www.datanet.hu/generations/linux/newkernel.html.
+http://www.datanet.hu/generations/linux/newkernel.html (Hungarian
+translation).
 
-   Tamas also maintains a version of this file in English at
-http://www.datanet.hu/generations/linux/Changes.html.
+   Tamas also maintains a version of this file at
+http://www.datanet.hu/generations/linux/Changes.html (English).
 
    For people who prefer Japanese (thanks to Mitsuhiro Kojima): Kono
 bunshou no nihongo ban wa
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
-Last updated: August 18, 1996.
+Last updated: August 29, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -152,7 +153,7 @@
 
    On the other hand, if you're using a gcc patched for Pentium
 optimization and are getting these errors, downgrade to a standard GNU
-gcc before assuming your hardware (or the kernel) is to blame..
+gcc before assuming your hardware (or the kernel) is to blame.
 
    On a related note, if you get random OOPses that don't seem to be
 related to anything and you have a motherboard with APM support, try
@@ -678,11 +679,14 @@
 ftp://ftp.redhat.com/pub/current/i386/updates/2.0-kernel/ and its
 mirrors.
 
-   For others, especially those of you running Slackware 3.0, David
-Bourgin has put together a Slackware-compatible package of everything
+   For others, David Bourgin has put together a package of everything
 necessary to quickly and easily upgrade to 2.0.x.  See
 ftp://ftp.wsc.com/pub/freeware/linux/update.linux/ for more information
-and the files.
+and the files.  This package also includes many bug-fixes, including
+one for a recently discovered bug in sendmail-8.7.5 (just look at
+/pub/freeware/linux/update.linux/updat2-0.addon1/sendmail-8.7.5a.tar.gz
+if you only need the bug fix).  There's also an alternate lightweight
+termcap in the same directory that works well for many people.
 
 Please send info about any other packages that 2.0.x "broke" or about
 any new features of 2.0.x that require extra or new packages for use to
diff -u --recursive --new-file v2.0.15/linux/Makefile linux/Makefile
--- v2.0.15/linux/Makefile	Thu Aug 29 19:15:13 1996
+++ linux/Makefile	Thu Aug 29 19:31:46 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 15
+SUBLEVEL = 16
 
 ARCH = i386
 
diff -u --recursive --new-file v2.0.15/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.0.15/linux/drivers/block/floppy.c	Thu Aug 29 19:15:14 1996
+++ linux/drivers/block/floppy.c	Thu Aug 29 19:12:01 1996
@@ -966,7 +966,7 @@
 		return 1;
 	}
 
-	if (jiffies - delay < 0){
+	if ((signed) (jiffies - delay) < 0){
 		del_timer(&fd_timer);
 		fd_timer.function = function;
 		fd_timer.expires = delay;
@@ -1415,7 +1415,7 @@
 		 * again just before spinup completion. Beware that
 		 * after scandrives, we must again wait for selection.
 		 */
-		if (ready_date - jiffies > DP->select_delay){
+		if ((signed) (ready_date - jiffies) > DP->select_delay){
 			ready_date -= DP->select_delay;
 			function = (timeout_fn) floppy_start;
 		} else
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.0.15/linux/drivers/isdn/icn/icn.c	Thu Aug 29 19:15:14 1996
+++ linux/drivers/isdn/icn/icn.c	Sat Aug 31 19:01:48 1996
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.28 1996/06/28 17:02:53 fritz Exp $
+/* $Id: icn.c,v 1.29 1996/08/29 20:34:54 fritz Exp $
  *
  * ISDN low-level module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,11 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: icn.c,v $
+ * Revision 1.29  1996/08/29 20:34:54  fritz
+ * Bugfix in send queue management:
+ * sndcount was not updated correctly.
+ * Minor Bugfixes.
+ *
  * Revision 1.28  1996/06/28 17:02:53  fritz
  * replaced memcpy_fromfs_toio.
  *
@@ -136,7 +141,7 @@
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.28 $";
+*revision = "$Revision: 1.29 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -675,9 +680,7 @@
 /* Append a packet to the transmit buffer-queue.
  * Parameters:
  *   channel = Number of B-channel
- *   buffer  = pointer to packet
- *   len     = size of packet (max 4000)
- *   user    = 1 = call from userproc, 0 = call from kernel
+ *   skb     = pointer to sk_buff
  *   card    = pointer to card-struct
  * Return:
  *   Number of bytes transferred, -E??? on error
@@ -701,19 +704,25 @@
                         return 0;
                 save_flags(flags);
                 cli();
-                card->sndcount[channel] += len;
                 nskb = skb_clone(skb, GFP_ATOMIC);
                 if (nskb) {
-                   skb_queue_tail(&card->spqueue[channel], nskb);
-                   dev_kfree_skb(skb, FREE_WRITE);
-                }
+                        skb_queue_tail(&card->spqueue[channel], nskb);
+                        dev_kfree_skb(skb, FREE_WRITE);
+                } else
+                        len = 0;
+                card->sndcount[channel] += len;
                 restore_flags(flags);
-                if (!nskb) 
-                   return 0;
         }
         return len;
 }
 
+/*
+ * Check card's status after starting the bootstrap loader.
+ * On entry, the card's shared memory has already to be mapped.
+ * Return:
+ *   0 on success (Boot loader ready)
+ *   -EIO on failure (timeout)
+ */
 static int icn_check_loader(int cardnumber)
 {
         int timer = 0;
@@ -1162,7 +1171,19 @@
                         case ICN_IOCTL_GETDOUBLE:
                                 return (int) card->doubleS0;
                         case ICN_IOCTL_DEBUGVAR:
-                                return (ulong) card;
+				if ((i = verify_area(VERIFY_WRITE,
+                                                    (void *) a,
+                                                    sizeof(ulong) * 2)))
+                                        return i;
+                                memcpy_tofs((char *)a,
+                                            (char *)&card, sizeof(ulong));
+				a += sizeof(ulong);
+				{
+                                        ulong l = (ulong)&dev;
+                                        memcpy_tofs((char *)a,
+                                                    (char *)&l, sizeof(ulong));
+                                }
+                                return 0;
                         case ICN_IOCTL_LOADBOOT:
                                 icn_stopcard(card);
                                 return (icn_loadboot((u_char *) a, card));
@@ -1630,7 +1651,7 @@
                 }
                 card = card->next;
         }
-        card = card;
+        card = cards;
         while (card) {
                 last = card;
                 card = card->next;
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h
--- v2.0.15/linux/drivers/isdn/icn/icn.h	Sat Jun 29 20:36:22 1996
+++ linux/drivers/isdn/icn/icn.h	Sat Aug 31 19:01:48 1996
@@ -1,4 +1,4 @@
-/* $Id: icn.h,v 1.20 1996/06/24 17:20:37 fritz Exp $
+/* $Id: icn.h,v 1.21 1996/08/29 20:35:57 fritz Exp $
  *
  * ISDN lowlevel-module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: icn.h,v $
+ * Revision 1.21  1996/08/29 20:35:57  fritz
+ * Speed up B-Channel polling interval.
+ *
  * Revision 1.20  1996/06/24 17:20:37  fritz
  * Bugfixes in pollbchan_send():
  *   - Using lock field of skbuff breaks networking.
@@ -156,7 +159,7 @@
 #define ICN_BOOT_TIMEOUT1  100   /* Delay for Boot-download (jiffies)       */
 #define ICN_CHANLOCK_DELAY  10   /* Delay for Channel-mapping (jiffies)     */
 
-#define ICN_TIMER_BCREAD 3       /* B-Channel poll-cycle                    */
+#define ICN_TIMER_BCREAD 1       /* B-Channel poll-cycle                    */
 #define ICN_TIMER_DCREAD 50      /* D-Channel poll-cycle                    */
 
 #define ICN_CODE_STAGE1 4096     /* Size of bootcode                        */
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.0.15/linux/drivers/isdn/isdn_net.c	Wed Jul 17 11:55:48 1996
+++ linux/drivers/isdn/isdn_net.c	Sat Aug 31 19:13:03 1996
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.18 1996/07/03 13:48:51 hipp Exp $
+/* $Id: isdn_net.c,v 1.20 1996/08/29 20:06:03 fritz Exp $
  *
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -21,6 +21,12 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.20  1996/08/29 20:06:03  fritz
+ * Bugfix: Transmission timeout had been much to low.
+ *
+ * Revision 1.19  1996/08/12 16:24:32  hipp
+ * removed some (now) obsolete functions for syncPPP in rebuild_header etc.
+ *
  * Revision 1.18  1996/07/03 13:48:51  hipp
  * bugfix: Call dev_purge_queues() only for master device
  *
@@ -124,7 +130,7 @@
  
 extern void dev_purge_queues(struct device *dev);	/* move this to net/core/dev.c */
 
-char *isdn_net_revision = "$Revision: 1.18 $";
+char *isdn_net_revision = "$Revision: 1.20 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -369,6 +375,10 @@
                                                  */
                                                 lp->chargetime = jiffies;
                                                 /* Immediately send first skb to speed up arp */
+#ifdef CONFIG_ISDN_PPP
+						if(lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+							isdn_ppp_wakeup_daemon(lp);
+#endif
                                                 if (lp->first_skb) {
                                                         if (!(isdn_net_xmit(&p->dev,lp,lp->first_skb)))
                                                                 lp->first_skb = NULL;
@@ -658,7 +668,6 @@
         u_char *p = buf;
 	unsigned short proto = ETH_P_IP;
         int data_ofs;
-        int len;
 	ip_ports *ipp;
 	char addinfo[100];
 
@@ -676,22 +685,6 @@
                         proto = ntohs(*(unsigned short *)&buf[2]);
                         p = &buf[4];
                         break;
-                case ISDN_NET_ENCAP_SYNCPPP:
-                        len = 4;
-#ifdef CONFIG_ISDN_MPP
-                        if (lp->ppp_minor!=-1) {
-                                if (ippp_table[lp->ppp_minor]->mpppcfg &
-                                    SC_MP_PROT) {
-                                        if (ippp_table[lp->ppp_minor]->mpppcfg &
-                                            SC_OUT_SHORT_SEQ)
-                                                len = 7;
-                                        else
-                                                len = 9;
-                                }
-                        }
-#endif
-                        p = &buf[len];
-                        break;
         }
 	data_ofs = ((p[0] & 15) * 4);
         switch (proto) {
@@ -851,7 +844,7 @@
 	isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 
 	if (ndev->tbusy) {
-		if (jiffies - ndev->trans_start < 20)
+		if (jiffies - ndev->trans_start < (2 * HZ))
 			return 1;
                 if (!lp->dialstate)
                         lp->stats.tx_errors++;
@@ -1248,29 +1241,6 @@
                         *((ushort*)&skb->data[2]) = htons(type);
                         len = 4;
                         break;
-#ifdef CONFIG_ISDN_PPP
-                case ISDN_NET_ENCAP_SYNCPPP:
-                        /* reserve space to be filled in isdn_ppp_xmit */
-                        len = 4;
-#ifdef CONFIG_ISDN_MPP
-                        if (lp->ppp_minor!=-1) {
-                                if (ippp_table[lp->ppp_minor]->mpppcfg &
-                                    SC_MP_PROT) {
-                                        if (ippp_table[lp->ppp_minor]->mpppcfg &
-                                            SC_OUT_SHORT_SEQ)
-                                                len = 7;
-                                        else
-                                                len = 9;
-                                }
-                        }
-#endif
-                        /* Initialize first 4 bytes to a value, which is
-                         * guaranteed to be invalid. Need that to check
-                         * for already compressed packets in isdn_ppp_xmit().
-                         */
-                        *((u32 *)skb_push(skb, len)) = 0;
-                        break;
-#endif
 	}
 	return len;
 }
@@ -1756,7 +1726,7 @@
                                         dev->st_netdev[idx] = lp->netdev;
 					p->local.isdn_device = di;
 					p->local.isdn_channel = ch;
-					p->local.ppp_minor = -1;
+					p->local.ppp_slot = -1;
 					p->local.pppbind = -1;
 					p->local.flags |= ISDN_NET_CONNECTED;
 					p->local.dialstate = 7;
@@ -1927,7 +1897,7 @@
 	netdev->local.pre_device = -1;
 	netdev->local.pre_channel = -1;
 	netdev->local.exclusive = -1;
-	netdev->local.ppp_minor = -1;
+	netdev->local.ppp_slot = -1;
 	netdev->local.pppbind = -1;
 	netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
 	netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
@@ -2443,8 +2413,7 @@
 	for(i=0;i<DEV_NUMBUFFS;i++) {
 		struct sk_buff *skb;
 		while((skb=skb_dequeue(&dev->buffs[i])))
-			if(skb->free)
-				kfree_skb(skb,FREE_WRITE);
+				dev_kfree_skb(skb,FREE_WRITE);
         }
 	
 }
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.0.15/linux/drivers/isdn/isdn_ppp.c	Wed Jul 17 11:55:48 1996
+++ linux/drivers/isdn/isdn_ppp.c	Sat Aug 31 19:13:03 1996
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.13 1996/07/01 19:47:24 hipp Exp $
+/* $Id: isdn_ppp.c,v 1.14 1996/08/12 16:26:47 hipp Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -19,6 +19,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.14  1996/08/12 16:26:47  hipp
+ * code cleanup
+ * changed connection management from minors to slots
+ *
  * Revision 1.13  1996/07/01 19:47:24  hipp
  * Fixed memory leak in VJ handling and more VJ changes
  *
@@ -82,21 +86,21 @@
 #endif
  
 /* Prototypes */
-static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int minor);
-static int isdn_ppp_closewait(int);
+static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot);
+static int isdn_ppp_closewait(int slot);
 static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
 			struct sk_buff *skb, int proto);
-static int isdn_ppp_if_get_unit(char **namebuf);
+static int isdn_ppp_if_get_unit(char *namebuf);
 
 #ifdef CONFIG_ISDN_MPP
-static int isdn_ppp_bundle(int, int);
+static int isdn_ppp_bundle(struct ippp_struct *, int unit);
 static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
 static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min);
 static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
 		int BEbyte, int *sqno, int min_sqno);
 #endif
 
-char *isdn_ppp_revision              = "$Revision: 1.13 $";
+char *isdn_ppp_revision              = "$Revision: 1.14 $";
 struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
 extern int isdn_net_force_dial_lp(isdn_net_local *);
@@ -109,10 +113,13 @@
 {
 	isdn_net_local *master_lp=lp;
 	unsigned long flags;
+	struct ippp_struct *is;
 
-	if (lp->ppp_minor < 0)
+	if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS)
 		return 0;
 
+	is = ippp_table[lp->ppp_slot];
+
 	save_flags(flags);
 	cli();
 #ifdef CONFIG_ISDN_MPP
@@ -132,13 +139,13 @@
 	lp->next = lp->last = lp;	/* (re)set own pointers */
 #endif
 
-	isdn_ppp_closewait(lp->ppp_minor);	/* force wakeup on ippp device */
+	isdn_ppp_closewait(lp->ppp_slot);	/* force wakeup on ippp device */
 
-	if(ippp_table[lp->ppp_minor]->debug & 0x1)
-		printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_minor, (long) lp,(long) ippp_table[lp->ppp_minor]->lp);
+	if(is->debug & 0x1)
+		printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp,(long) is->lp);
 
-	ippp_table[lp->ppp_minor]->lp = NULL;	/* link is down .. set lp to NULL */
-	lp->ppp_minor = -1;			/* is this OK ?? */
+	is->lp = NULL;	/* link is down .. set lp to NULL */
+	lp->ppp_slot = -1;			/* is this OK ?? */
 	restore_flags(flags);
 
 	return 0;
@@ -151,11 +158,11 @@
 {
 	int i;
 	int unit = 0;
-	char *name;
 	long flags;
+	struct ippp_struct *is;
 
 	if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
-		return 0;
+		return -1;
 
 	save_flags(flags);
 	cli();
@@ -172,19 +179,18 @@
 			net_dev = net_dev->next;
 		}
 		/*
-		 * search a free device 
+		 * search a free device / slot
 		 */
 		for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-			if (ippp_table[i]->state == IPPP_OPEN && !exclusive[i]) { /* OPEN, but not connected! */
+			if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) { /* OPEN, but not connected! */
 				break;
 			}
 		}
 	}
 	else {
-		if (ippp_table[lp->pppbind]->state == IPPP_OPEN) /* OPEN, but not connected! */
-			i = lp->pppbind;
-		else
-			i = ISDN_MAX_CHANNELS;	/* trigger error */
+		for(i=0;i<ISDN_MAX_CHANNELS;i++)
+			if(ippp_table[i]->minor == lp->pppbind && ippp_table[i]->state == IPPP_OPEN)
+				break;
 	}
 
 	if (i >= ISDN_MAX_CHANNELS) {
@@ -192,24 +198,33 @@
 		printk(KERN_WARNING "isdn_ppp_bind: Can't find usable ippp device.\n");
 		return -1;
 	}
-	lp->ppp_minor = i;
-	ippp_table[lp->ppp_minor]->lp = lp;
 
-	name = lp->name;
-	unit = isdn_ppp_if_get_unit(&name); /* get unit number from interface name .. ugly! */
-	ippp_table[lp->ppp_minor]->unit = unit;
+	unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */
+	if(unit < 0) {
+		printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n",lp->name);
+		return -1;
+	}
 
-	ippp_table[lp->ppp_minor]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+	lp->ppp_slot = i;
+	is = ippp_table[i];
+	is->lp = lp;
+	is->unit = unit;
+	is->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
 
 	restore_flags(flags);
 
-        /*
-         * kick the ipppd on the new device 
-         */
-	if (ippp_table[lp->ppp_minor]->wq)
-		wake_up_interruptible(&ippp_table[lp->ppp_minor]->wq);
+	return lp->ppp_slot;
+}
 
-	return lp->ppp_minor;
+/*
+ * kick the ipppd on the device
+ * (wakes up daemon after B-channel connect)
+ */
+
+void isdn_ppp_wakeup_daemon(isdn_net_local *lp)
+{
+	if (ippp_table[lp->ppp_slot]->wq)
+		wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
 }
 
 /*
@@ -217,51 +232,76 @@
  * force wakeup of the ippp device 
  * go into 'device waits for release' state
  */
-static int isdn_ppp_closewait(int minor)
+static int isdn_ppp_closewait(int slot)
 {
-	if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
+	struct ippp_struct *is;
+
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS)
 		return 0;
+	is = ippp_table[slot];
 
-	if (ippp_table[minor]->state && ippp_table[minor]->wq)
-		wake_up_interruptible(&ippp_table[minor]->wq);
+	if (is->state && is->wq)
+		wake_up_interruptible(&is->wq);
 
-	ippp_table[minor]->state = IPPP_CLOSEWAIT;
+	is->state = IPPP_CLOSEWAIT;
 	return 1;
 }
 
 /*
+ * isdn_ppp_find_slot / isdn_ppp_free_slot
+ */
+
+static int isdn_ppp_get_slot(void)
+{
+	int i;
+	for(i=0;i<ISDN_MAX_CHANNELS;i++) {
+		if(!ippp_table[i]->state)
+			return i;
+	}
+	return -1;
+}
+
+/*
  * isdn_ppp_open 
  */
 
-int isdn_ppp_open(int minor, struct file *file)
+int isdn_ppp_open(int min, struct file *file)
 {
-	if(ippp_table[minor]->debug & 0x1)
-		printk(KERN_DEBUG "ippp, open, minor: %d state: %04x\n", minor,ippp_table[minor]->state);
-	if (ippp_table[minor]->state)
+	int slot;
+	struct ippp_struct *is;
+
+	slot = isdn_ppp_get_slot();
+	if(slot < 0) {
 		return -EBUSY;
+	}
+	is = file->private_data = ippp_table[slot];
 
-	ippp_table[minor]->lp = 0;
-	ippp_table[minor]->mp_seqno = 0;  /* MP sequence number */
-	ippp_table[minor]->pppcfg = 0;    /* ppp configuration */
-	ippp_table[minor]->mpppcfg = 0;   /* mppp configuration */
-	ippp_table[minor]->range = 0x1000000;	/* MP: 24 bit range */
-	ippp_table[minor]->last_link_seqno = -1;	/* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
-	ippp_table[minor]->unit = -1;	/* set, when we have our interface */
-	ippp_table[minor]->mru = 1524;	/* MRU, default 1524 */
-	ippp_table[minor]->maxcid = 16;	/* VJ: maxcid */
-	ippp_table[minor]->tk = current;
-	ippp_table[minor]->wq = NULL;    /* read() wait queue */
-	ippp_table[minor]->wq1 = NULL;   /* select() wait queue */
-	ippp_table[minor]->first = ippp_table[minor]->rq + NUM_RCV_BUFFS - 1; /* receive queue */
-	ippp_table[minor]->last = ippp_table[minor]->rq;
+	if(is->debug & 0x1)
+		printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",slot, min,is->state);
+
+	is->lp = 0;
+	is->mp_seqno = 0;  /* MP sequence number */
+	is->pppcfg = 0;    /* ppp configuration */
+	is->mpppcfg = 0;   /* mppp configuration */
+	is->range = 0x1000000;	/* MP: 24 bit range */
+	is->last_link_seqno = -1;	/* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
+	is->unit = -1;	/* set, when we have our interface */
+	is->mru = 1524;	/* MRU, default 1524 */
+	is->maxcid = 16;	/* VJ: maxcid */
+	is->tk = current;
+	is->wq = NULL;    /* read() wait queue */
+	is->wq1 = NULL;   /* select() wait queue */
+	is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
+	is->last = is->rq;
+	is->minor = min;
 #ifdef CONFIG_ISDN_PPP_VJ
         /*
          * VJ header compression init
          */
-	ippp_table[minor]->slcomp = slhc_init(16, 16);	/* not necessary for 2. link in bundle */
+	is->slcomp = slhc_init(16, 16);	/* not necessary for 2. link in bundle */
 #endif
 
-	ippp_table[minor]->state = IPPP_OPEN;
+	is->state = IPPP_OPEN;
 
 	return 0;
 }
@@ -269,38 +309,40 @@
 /*
  * release ippp device
  */
-void isdn_ppp_release(int minor, struct file *file)
+void isdn_ppp_release(int min, struct file *file)
 {
 	int i;
+	struct ippp_struct *is;
 
-	if (minor < 0 || minor >= ISDN_MAX_CHANNELS)
+	if (min < 0 || min >= ISDN_MAX_CHANNELS)
 		return;
+	is = file->private_data;
 
-	if(ippp_table[minor]->debug & 0x1)
-		printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", minor, (long) ippp_table[minor]->lp);
+	if(is->debug & 0x1)
+		printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
 
-	if (ippp_table[minor]->lp) {	/* a lp address says: this link is still up */
+	if (is->lp) {	/* a lp address says: this link is still up */
 		isdn_net_dev *p = dev->netdev;
-		p = ippp_table[minor]->lp->netdev;
-		ippp_table[minor]->lp->ppp_minor = -1;
-		isdn_net_hangup(&p->dev); /* lp->ppp_minor==-1 => no calling of isdn_ppp_closewait() */
-		ippp_table[minor]->lp = NULL;
+		p = is->lp->netdev;
+		is->lp->ppp_slot = -1;
+		isdn_net_hangup(&p->dev); /* lp->ppp_slot==-1 => no calling of isdn_ppp_closewait() */
+		is->lp = NULL;
 	}
 	for (i = 0; i < NUM_RCV_BUFFS; i++) {
-		if (ippp_table[minor]->rq[i].buf) {
-			kfree(ippp_table[minor]->rq[i].buf);
-			ippp_table[minor]->rq[i].buf = NULL;
+		if (is->rq[i].buf) {
+			kfree(is->rq[i].buf);
+			is->rq[i].buf = NULL;
 		}
 	}
-        ippp_table[minor]->first = ippp_table[minor]->rq + NUM_RCV_BUFFS - 1; /* receive queue */
-        ippp_table[minor]->last = ippp_table[minor]->rq;
+        is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
+        is->last = is->rq;
 
 #ifdef CONFIG_ISDN_PPP_VJ
-	slhc_free(ippp_table[minor]->slcomp);
-	ippp_table[minor]->slcomp = NULL;
+	slhc_free(is->slcomp);
+	is->slcomp = NULL;
 #endif
 
-	ippp_table[minor]->state = 0;
+	is->state = 0;
 }
 
 /*
@@ -330,62 +372,59 @@
 /*
  * ippp device ioctl 
  */
-int isdn_ppp_ioctl(int minor, struct file *file, unsigned int cmd, unsigned long arg)
+int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	unsigned long val;
 	int r;
+	struct ippp_struct *is;
+
+	is = file->private_data;
 
-	if(ippp_table[minor]->debug & 0x1)
-		printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n",
-			minor,cmd,ippp_table[minor]->state);
+	if(is->debug & 0x1)
+		printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n",min,cmd,is->state);
 
-	if (!(ippp_table[minor]->state & IPPP_OPEN))
+	if (!(is->state & IPPP_OPEN))
 		return -EINVAL;
 
 	switch (cmd) {
-#if 0
-	case PPPIOCSINPSIG:	/* obsolete: set input ready signal */
-		/* usual: sig = SIGIO *//* we always deliver a SIGIO */
-		break;
-#endif
 	case PPPIOCBUNDLE:
 #ifdef CONFIG_ISDN_MPP
 		if ((r = get_arg((void *) arg, &val)))
 			return r;
 		printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
-                        (int) minor, (int) ippp_table[minor]->unit, (int) val);
-		return isdn_ppp_bundle(minor, val);
+                        (int) min, (int) is->unit, (int) val);
+		return isdn_ppp_bundle(is, val);
 #else
 		return -1;
 #endif
 		break;
 	case PPPIOCGUNIT:	/* get ppp/isdn unit number */
-		if ((r = set_arg((void *) arg, ippp_table[minor]->unit)))
+		if ((r = set_arg((void *) arg, is->unit)))
 			return r;
 		break;
 	case PPPIOCGMPFLAGS:	/* get configuration flags */
-		if ((r = set_arg((void *) arg, ippp_table[minor]->mpppcfg)))
+		if ((r = set_arg((void *) arg, is->mpppcfg)))
 			return r;
 		break;
 	case PPPIOCSMPFLAGS:	/* set configuration flags */
 		if ((r = get_arg((void *) arg, &val)))
 			return r;
-		ippp_table[minor]->mpppcfg = val;
+		is->mpppcfg = val;
 		break;
 	case PPPIOCGFLAGS:	/* get configuration flags */
-		if ((r = set_arg((void *) arg, ippp_table[minor]->pppcfg)))
+		if ((r = set_arg((void *) arg, is->pppcfg)))
 			return r;
 		break;
 	case PPPIOCSFLAGS:	/* set configuration flags */
 		if ((r = get_arg((void *) arg, &val))) {
 			return r;
 		}
-		if (val & SC_ENABLE_IP && !(ippp_table[minor]->pppcfg & SC_ENABLE_IP)) {
-			isdn_net_local *lp = ippp_table[minor]->lp;
+		if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) {
+			isdn_net_local *lp = is->lp;
 			lp->netdev->dev.tbusy = 0;
 			mark_bh(NET_BH); /* OK .. we are ready to send buffers */
 		}
-		ippp_table[minor]->pppcfg = val;
+		is->pppcfg = val;
 		break;
 #if 0
 	case PPPIOCGSTAT:	/* read PPP statistic information */
@@ -396,7 +435,7 @@
 	case PPPIOCSMRU:	/* set receive unit size for PPP */
 		if ((r = get_arg((void *) arg, &val)))
 			return r;
-		ippp_table[minor]->mru = val;
+		is->mru = val;
 		break;
 	case PPPIOCSMPMRU:
 		break;
@@ -406,33 +445,33 @@
 		if ((r = get_arg((void *) arg, &val)))
 			return r;
 		val++;
-		if(ippp_table[minor]->maxcid != val) {
+		if(is->maxcid != val) {
 #ifdef CONFIG_ISDN_PPP_VJ
 			struct slcompress *sltmp;
 #endif
-			if(ippp_table[minor]->debug & 0x1)
+			if(is->debug & 0x1)
 				printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n",val);
-			ippp_table[minor]->maxcid = val;
+			is->maxcid = val;
 #ifdef CONFIG_ISDN_PPP_VJ
 			sltmp = slhc_init(16,val);
 			if(!sltmp) {
 				printk(KERN_ERR "ippp, can't realloc slhc struct\n");
 				return -ENOMEM;
 			}	
-			if(ippp_table[minor]->slcomp)
-				slhc_free(ippp_table[minor]->slcomp);
-			ippp_table[minor]->slcomp = sltmp;
+			if(is->slcomp)
+				slhc_free(is->slcomp);
+			is->slcomp = sltmp;
 #endif
 		}
 		break;
 	case PPPIOCGDEBUG:
-		if ((r = set_arg((void *) arg, ippp_table[minor]->debug)))
+		if ((r = set_arg((void *) arg, is->debug)))
 			return r;
 		break;
 	case PPPIOCSDEBUG:
 		if ((r = get_arg((void *) arg, &val)))
 			return r;
-		ippp_table[minor]->debug = val;
+		is->debug = val;
 		break;
 	default:
 		break;
@@ -440,39 +479,42 @@
 	return 0;
 }
 
-int isdn_ppp_select(int minor, struct file *file, int type, select_table * st)
+int isdn_ppp_select(int min, struct file *file, int type, select_table * st)
 {
 	struct ippp_buf_queue *bf, *bl;
 	unsigned long flags;
+	struct ippp_struct *is;
 
-	if(ippp_table[minor]->debug & 0x2)
-		printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",minor,type);
+	is = file->private_data;
 
-	if (!(ippp_table[minor]->state & IPPP_OPEN))
+	if(is->debug & 0x2)
+		printk(KERN_DEBUG "isdn_ppp_select: minor: %d, type: %d \n",min,type);
+
+	if (!(is->state & IPPP_OPEN))
 		return -EINVAL;
 
 	switch (type) {
 	case SEL_IN:
 		save_flags(flags);
 		cli();
-		bl = ippp_table[minor]->last;
-		bf = ippp_table[minor]->first;
+		bl = is->last;
+		bf = is->first;
 		/* 
 		 * if IPPP_NOBLOCK is set we return even if we have nothing to read 
 		 */
-		if (bf->next == bl && !(ippp_table[minor]->state & IPPP_NOBLOCK)) {
-			select_wait(&ippp_table[minor]->wq, st);
+		if (bf->next == bl && !(is->state & IPPP_NOBLOCK)) {
+			select_wait(&is->wq, st);
 			restore_flags(flags);
 			return 0;
 		}
-		ippp_table[minor]->state &= ~IPPP_NOBLOCK;
+		is->state &= ~IPPP_NOBLOCK;
 		restore_flags(flags);
 		return 1;
 	case SEL_OUT:
                 /* we're always ready to send .. */
 		return 1;
 	case SEL_EX:
-		select_wait(&ippp_table[minor]->wq1, st);
+		select_wait(&is->wq1, st);
 		return 0;
 	}
 	return 1;
@@ -482,17 +524,20 @@
  *  fill up isdn_ppp_read() queue ..
  */
 
-static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int minor)
+static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot)
 {
 	struct ippp_buf_queue *bf, *bl;
 	unsigned long flags;
 	unsigned char *nbuf;
+	struct ippp_struct *is;
 
-	if (minor < 0 || minor >= ISDN_MAX_CHANNELS) {
-		printk(KERN_WARNING "ippp: illegal minor.\n");
+	if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+		printk(KERN_WARNING "ippp: illegal slot.\n");
 		return 0;
 	}
-	if (!(ippp_table[minor]->state & IPPP_CONNECT)) {
+	is = ippp_table[slot];
+
+	if (!(is->state & IPPP_CONNECT)) {
 		printk(KERN_DEBUG "ippp: device not activated.\n");
 		return 0;
 	}
@@ -511,23 +556,23 @@
 	save_flags(flags);
 	cli();
 
-	bf = ippp_table[minor]->first;
-	bl = ippp_table[minor]->last;
+	bf = is->first;
+	bl = is->last;
 
 	if (bf == bl) {
 		printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
 		bf = bf->next;
 		kfree(bf->buf);
-		ippp_table[minor]->first = bf;
+		is->first = bf;
 	}
 	bl->buf = (char *) nbuf;
 	bl->len = len+4;
 
-	ippp_table[minor]->last = bl->next;
+	is->last = bl->next;
 	restore_flags(flags);
 
-	if (ippp_table[minor]->wq)
-		wake_up_interruptible(&ippp_table[minor]->wq);
+	if (is->wq)
+		wake_up_interruptible(&is->wq);
 
 	return len;
 }
@@ -537,14 +582,16 @@
  *           reports, that there is data
  */
 
-int isdn_ppp_read(int minor, struct file *file, char *buf, int count)
+int isdn_ppp_read(int min, struct file *file, char *buf, int count)
 {
-	struct ippp_struct *c = ippp_table[minor];
+	struct ippp_struct *is;
 	struct ippp_buf_queue *b;
 	int r;
 	unsigned long flags;
 
-	if (!(ippp_table[minor]->state & IPPP_OPEN))
+	is = file->private_data;
+
+	if (!(is->state & IPPP_OPEN))
 		return 0;
 
 	if ((r = verify_area(VERIFY_WRITE, (void *) buf, count)))
@@ -553,7 +600,7 @@
 	save_flags(flags);
 	cli();
 
-	b = c->first->next;
+	b = is->first->next;
 	if (!b->buf) {
 		restore_flags(flags);
 		return -EAGAIN;
@@ -563,7 +610,7 @@
 	memcpy_tofs(buf, b->buf, count);
 	kfree(b->buf);
 	b->buf = NULL;
-	c->first = b;
+	is->first = b;
 	restore_flags(flags);
 
 	return count;
@@ -573,14 +620,17 @@
  * ipppd wanna write a packet to the card .. non-blocking
  */
  
-int isdn_ppp_write(int minor, struct file *file,  const char *buf, int count)
+int isdn_ppp_write(int min, struct file *file,  const char *buf, int count)
 {
 	isdn_net_local *lp;
+	struct ippp_struct *is;
+
+	is = file->private_data;
 
-	if (!(ippp_table[minor]->state & IPPP_CONNECT))
+	if (!(is->state & IPPP_CONNECT))
 		return 0;
 
-	lp = ippp_table[minor]->lp;
+	lp = is->lp;
 
 	/* -> push it directly to the lowlevel interface */
 
@@ -659,7 +709,10 @@
 
 void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
 {
-	if(ippp_table[lp->ppp_minor]->debug & 0x4)
+	struct ippp_struct *is;
+	is = ippp_table[lp->ppp_slot];
+
+	if(is->debug & 0x4)
 		printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len);
 
 	if(net_dev->local.master) {
@@ -669,14 +722,14 @@
 
 	if(skb->data[0] == 0xff && skb->data[1] == 0x03)
 		skb_pull(skb,2);
-	else if (ippp_table[lp->ppp_minor]->pppcfg & SC_REJ_COMP_AC) {
+	else if (is->pppcfg & SC_REJ_COMP_AC) {
 		skb->free = 1;
 		dev_kfree_skb(skb,0 /* FREE_READ */ );
 		return;		/* discard it silently */
 	}
 
 #ifdef CONFIG_ISDN_MPP
-	if (!(ippp_table[lp->ppp_minor]->mpppcfg & SC_REJ_MP_PROT)) {
+	if (!(is->mpppcfg & SC_REJ_MP_PROT)) {
 		int proto;
 		int sqno_end;
 		if (skb->data[0] & 0x1) {
@@ -690,11 +743,11 @@
 			isdn_net_local *lpq;
 			int sqno, min_sqno, tseq;
 			u_char BEbyte = skb->data[0];
-			if(ippp_table[lp->ppp_minor]->debug & 0x8)
-	 			printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_minor, proto ,
+			if(is->debug & 0x8)
+	 			printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto ,
 					(int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2], 
 					(int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
-			if (!(ippp_table[lp->ppp_minor]->mpppcfg & SC_IN_SHORT_SEQ)) {
+			if (!(is->mpppcfg & SC_IN_SHORT_SEQ)) {
 				sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3];
 				skb_pull(skb,4);
 			} else {
@@ -702,26 +755,26 @@
 				skb_pull(skb,2);
 			}
 
-			if ((tseq = ippp_table[lp->ppp_minor]->last_link_seqno) >= sqno) {
-				int range = ippp_table[lp->ppp_minor]->range;
+			if ((tseq = is->last_link_seqno) >= sqno) {
+				int range = is->range;
 				if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
 					printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %d, last: %d !!!\n", sqno, tseq);
 				else {
 					sqno += range;
-					ippp_table[lp->ppp_minor]->last_link_seqno = sqno;
+					is->last_link_seqno = sqno;
 				}
 			} else
-				ippp_table[lp->ppp_minor]->last_link_seqno = sqno;
+				is->last_link_seqno = sqno;
 
 			for (min_sqno = 0, lpq = net_dev->queue;;) {
-				if (ippp_table[lpq->ppp_minor]->last_link_seqno > min_sqno)
-					min_sqno = ippp_table[lpq->ppp_minor]->last_link_seqno;
+				if (ippp_table[lpq->ppp_slot]->last_link_seqno > min_sqno)
+					min_sqno = ippp_table[lpq->ppp_slot]->last_link_seqno;
 				lpq = lpq->next;
 				if (lpq == net_dev->queue)
 					break;
 			}
-			if (min_sqno >= ippp_table[lpq->ppp_minor]->range) {	/* OK, every link overflowed */
-				int mask = ippp_table[lpq->ppp_minor]->range - 1;	/* range is a power of 2 */
+			if (min_sqno >= ippp_table[lpq->ppp_slot]->range) {	/* OK, every link overflowed */
+				int mask = ippp_table[lpq->ppp_slot]->range - 1;	/* range is a power of 2 */
 				isdn_ppp_cleanup_queue(net_dev, min_sqno);
 				isdn_ppp_mask_queue(net_dev, mask);
 				net_dev->ib.next_num &= mask;
@@ -734,14 +787,14 @@
 				}
 				min_sqno &= mask;
 				for (lpq = net_dev->queue;;) {
-					ippp_table[lpq->ppp_minor]->last_link_seqno &= mask;
+					ippp_table[lpq->ppp_slot]->last_link_seqno &= mask;
 					lpq = lpq->next;
 					if (lpq == net_dev->queue)
 						break;
 				}
 			}
 			if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
-				printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_minor);
+				printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot);
 				if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0)
 					return;		/* no packet complete */
 			} else
@@ -820,9 +873,14 @@
 }
 
 
+/*
+ * push frame to higher layers
+ * note: net_dev has to be master net_dev
+ */
 static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb,int proto)
 {
 	struct device *dev = &net_dev->dev;
+	struct ippp_struct *is = ippp_table[lp->ppp_slot];
 
 	if (proto < 0) {	/* MP, oder normales Paket bei REJ_MP, MP Pakete gehen bei REJ zum pppd */
 		if (skb->data[0] & 0x01) {	/* is it odd? */
@@ -834,12 +892,12 @@
 		}
 	}
 
-	if(ippp_table[lp->ppp_minor]->debug & 0x10)
+	if(is->debug & 0x10)
 		printk(KERN_DEBUG "push, skb %ld %04x\n",skb->len,proto);
 
 	switch (proto) {
 	case PPP_IPX: /* untested */
-		if(ippp_table[lp->ppp_minor]->debug & 0x20)
+		if(is->debug & 0x20)
 			printk(KERN_DEBUG "isdn_ppp: _IPX\n");
 		skb->dev = dev;
 		skb->mac.raw = skb->data;
@@ -847,9 +905,9 @@
 		break;
 #ifdef CONFIG_ISDN_PPP_VJ
 	case PPP_VJC_UNCOMP:
-		if(ippp_table[lp->ppp_minor]->debug & 0x20)
+		if(is->debug & 0x20)
 			printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
-		if(slhc_remember(ippp_table[net_dev->local.ppp_minor]->slcomp, skb->data, skb->len) <= 0) {
+		if(slhc_remember(ippp_table[net_dev->local.ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
 			printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
 			net_dev->local.stats.rx_dropped++;
 			skb->free = 1;
@@ -858,14 +916,14 @@
 		}
 #endif
 	case PPP_IP:
-		if(ippp_table[lp->ppp_minor]->debug & 0x20)
+		if(is->debug & 0x20)
 			printk(KERN_DEBUG "isdn_ppp: IP\n");
 		skb->dev = dev;
 		skb->mac.raw = skb->data;
 		skb->protocol = htons(ETH_P_IP);
 		break;
 	case PPP_VJC_COMP:
-                if(ippp_table[lp->ppp_minor]->debug & 0x20)
+                if(is->debug & 0x20)
                         printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
 #ifdef CONFIG_ISDN_PPP_VJ
 		{
@@ -885,7 +943,7 @@
 			skb_put(skb,skb_old->len + 40);
 			memcpy(skb->data, skb_old->data, skb_old->len);
 			skb->mac.raw = skb->data;
-			pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_minor]->slcomp,
+			pkt_len = slhc_uncompress(ippp_table[net_dev->local.ppp_slot]->slcomp,
 						  skb->data, skb_old->len);
 			dev_kfree_skb(skb_old,0 /* FREE_READ */ );
 			if(pkt_len < 0) {
@@ -906,7 +964,7 @@
 #endif
 		break;
 	default:
-		isdn_ppp_fill_rq(skb->data, skb->len,proto, lp->ppp_minor);	/* push data to pppd device */
+		isdn_ppp_fill_rq(skb->data, skb->len,proto, lp->ppp_slot);	/* push data to pppd device */
 		skb->free = 1;
 		dev_kfree_skb(skb,0 /* FREE_READ */ );
 		return;
@@ -928,6 +986,19 @@
  * skb isn't allowed!! 
  */
 
+static void isdn_ppp_skb_destructor(struct sk_buff *skb)
+{
+	char outstr[80],*outpnt=outstr;
+	int i;
+
+	*outpnt = 0;
+	for(i=0;i<24 && i<skb->len;i++) {
+		sprintf(outpnt,"%02x ",skb->data[i]);
+		outpnt += 3;
+	}
+	printk(KERN_DEBUG "ippp_dstrct: %s\n",outstr);
+}
+
 int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
 {
 	struct device *mdev = ((isdn_net_local *) (dev->priv) )->master;	/* get master (for redundancy) */
@@ -941,13 +1012,18 @@
 	else
 		mlp = (isdn_net_local *) (dev->priv);
 	nd = mlp->netdev;	/* get master lp */
-	ipts = ippp_table[mlp->ppp_minor];
+	ipts = ippp_table[mlp->ppp_slot];
 
 	if (!(ipts->pppcfg & SC_ENABLE_IP)) {    /* PPP connected ? */
-		printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
-		return 1;
+		if(ipts->debug & 0x1) {
+			printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
+			skb->destructor = isdn_ppp_skb_destructor;
+		}
+ 		return 1;
         }
 
+	skb->destructor = NULL;
+
 	lp = nd->queue;		/* get lp on top of queue */
 	if(lp->sav_skb) {	/* find a non-busy device */
 		isdn_net_local *nlp = lp->next;
@@ -958,35 +1034,21 @@
 		}
 		lp = nlp;
 	}
-	ipt = ippp_table[lp->ppp_minor];
+	ipt = ippp_table[lp->ppp_slot];
 
         lp->huptimer = 0;
- 
-        /* If packet is to be resent, it has already been processed and
-         * therefore its first bytes are already initialized. In this case
-         * send it immediately ...
-         */
-        if (*((u32 *)skb->data) != 0) {
-	  printk(KERN_ERR "%s: Whoops .. packet resend should no longer happen!\n",dev->name);
-          return (isdn_net_send_skb(dev , lp , skb));
-        }
 
-        /* ... else packet needs processing. */
+	/*
+	 * after this line .. requeueing in the device queue is no longer allowed!!! 
+	 */
 
-	if(ippp_table[lp->ppp_minor]->debug & 0x4)
+	if(ipt->debug & 0x4)
 		printk(KERN_DEBUG  "xmit skb, len %ld\n",skb->len);
 
 #ifdef CONFIG_ISDN_PPP_VJ
-	if (ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes .. but check again */
+	if (ipts->pppcfg & SC_COMP_TCP) {	/* ipts here? probably yes .. but this check again */
 		struct sk_buff *new_skb;
-		int len = 4;
-#ifdef CONFIG_ISDN_MPP
-		if (ipt->mpppcfg & SC_MP_PROT) /* sigh */ 	/* ipt or ipts ?? */
-			if (ipt->mpppcfg & SC_OUT_SHORT_SEQ)
-				len += 3;
-			else
-				len += 5;
-#endif
+
 		new_skb = dev_alloc_skb(skb->len);
 		if(new_skb) {
 			u_char *buf;
@@ -995,8 +1057,6 @@
 			new_skb->dev = skb->dev;
 			new_skb->free = 1;
 			skb_put(new_skb,skb->len);
-			skb_pull(skb,len);	/* pull PPP header */
-			skb_pull(new_skb,len);	/* pull PPP header */
 			buf = skb->data;
 
 			pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
@@ -1021,12 +1081,11 @@
 					proto = PPP_VJC_UNCOMP;
 				skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
 			}
-			skb_push(skb,len);
 		}
 	}
 #endif
 
-        if(ippp_table[lp->ppp_minor]->debug & 0x24)
+        if(ipt->debug & 0x24)
  		printk(KERN_DEBUG  "xmit2 skb, len %ld, proto %04x\n",skb->len,proto);
 
 #ifdef CONFIG_ISDN_MPP
@@ -1036,22 +1095,23 @@
 		ipts->mp_seqno++;
 		nd->queue = nd->queue->next;
 		if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
-			/* skb_push(skb, 3); Done in isdn_net_header() */
+			skb_push(skb, 3);
 			mp_seqno &= 0xfff;
-			skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8);	/* (B)egin & (E)ndbit .. */
-			skb->data[5] = mp_seqno & 0xff;
-			skb->data[6] = proto;	/* PID compression */
+			skb->data[0] = MP_BEGIN_FRAG | MP_END_FRAG | (mp_seqno >> 8);	/* (B)egin & (E)ndbit .. */
+			skb->data[1] = mp_seqno & 0xff;
+			skb->data[2] = proto;	/* PID compression */
 		} else {
-			/* skb_push(skb, 5); Done in isdn_net_header () */
-			skb->data[4] = MP_BEGIN_FRAG | MP_END_FRAG;	/* (B)egin & (E)ndbit .. */
-			skb->data[5] = (mp_seqno >> 16) & 0xff;	/* sequence number: 24bit */
-			skb->data[6] = (mp_seqno >> 8) & 0xff;
-			skb->data[7] = (mp_seqno >> 0) & 0xff;
-			skb->data[8] = proto;	/* PID compression */
+			skb_push(skb, 5);
+			skb->data[0] = MP_BEGIN_FRAG | MP_END_FRAG;	/* (B)egin & (E)ndbit .. */
+			skb->data[1] = (mp_seqno >> 16) & 0xff;	/* sequence number: 24bit */
+			skb->data[2] = (mp_seqno >> 8) & 0xff;
+			skb->data[3] = (mp_seqno >> 0) & 0xff;
+			skb->data[4] = proto;	/* PID compression */
 		}
 		proto = PPP_MP; /* MP Protocol, 0x003d */
 	}
 #endif
+	skb_push(skb,4);
 	skb->data[0] = 0xff;        /* All Stations */
 	skb->data[1] = 0x03;        /* Unnumbered information */
 	skb->data[2] = proto >> 8;
@@ -1100,7 +1160,7 @@
 
 #ifdef CONFIG_ISDN_MPP
 
-static int isdn_ppp_bundle(int minor, int unit)
+static int isdn_ppp_bundle(struct ippp_struct *is, int unit)
 {
 	char ifn[IFNAMSIZ + 1];
 	long flags;
@@ -1117,7 +1177,7 @@
 	save_flags(flags);
 	cli();
 
-	nlp = ippp_table[minor]->lp;
+	nlp = is->lp;
 
 	lp = p->queue;
 	p->ib.bundled = 1;
@@ -1127,17 +1187,17 @@
 	nlp->next = lp;
 	p->queue = nlp;
 
-	ippp_table[nlp->ppp_minor]->unit = ippp_table[lp->ppp_minor]->unit;
+	ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
 /* maybe also SC_CCP stuff */
-	ippp_table[nlp->ppp_minor]->pppcfg |= ippp_table[lp->ppp_minor]->pppcfg &
+	ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
 	    (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
 
-	ippp_table[nlp->ppp_minor]->mpppcfg |= ippp_table[lp->ppp_minor]->mpppcfg &
+	ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
 	    (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
 #if 0
-	if (ippp_table[nlp->ppp_minor]->mpppcfg != ippp_table[lp->ppp_minor]->mpppcfg) {
+	if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) {
 		printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n",
-		       ippp_table[nlp->ppp_minor]->mpppcfg, ippp_table[lp->ppp_minor]->mpppcfg);
+		       ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg);
 	}
 #endif
 
@@ -1325,7 +1385,7 @@
 #ifdef CONFIG_ISDN_PPP_VJ
 	/* did we free a stale frame ? */
 	if(toss)
-		slhc_toss(ippp_table[dev->local.ppp_minor]->slcomp);
+		slhc_toss(ippp_table[dev->local.ppp_slot]->slcomp);
 #endif
 }
 
@@ -1355,7 +1415,7 @@
 #ifdef CONFIG_ISDN_PPP_VJ
 				/* did we step over a missing frame ? */
 				if(q->sqno_start != net_dev->ib.next_num)
-					slhc_toss(ippp_table[lp->ppp_minor]->slcomp);
+					slhc_toss(ippp_table[lp->ppp_slot]->slcomp);
 #endif
 
 				ql = net_dev->ib.sq;
@@ -1381,7 +1441,7 @@
  * network device ioctl handlers
  */
 
-static int isdn_ppp_dev_ioctl_stats(int minor,struct ifreq *ifr,struct device *dev)
+static int isdn_ppp_dev_ioctl_stats(int slot,struct ifreq *ifr,struct device *dev)
 {
 	struct ppp_stats *res, t;
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -1402,8 +1462,8 @@
 		t.p.ppp_opackets = lp->stats.tx_packets;
 		t.p.ppp_oerrors = lp->stats.tx_errors;
 #ifdef CONFIG_ISDN_PPP_VJ
-		if(minor >= 0 && ippp_table[minor]->slcomp) {
-			struct slcompress *slcomp = ippp_table[minor]->slcomp;
+		if(slot >= 0 && ippp_table[slot]->slcomp) {
+			struct slcompress *slcomp = ippp_table[slot]->slcomp;
 			t.vj.vjs_packets  = slcomp->sls_o_compressed+slcomp->sls_o_uncompressed;
 			t.vj.vjs_compressed = slcomp->sls_o_compressed;
 			t.vj.vjs_searches = slcomp->sls_o_searches;
@@ -1428,7 +1488,7 @@
 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
 
 #if 0
-	printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n",cmd,lp->ppp_minor);
+	printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n",cmd,lp->ppp_slot);
 #endif
 
 	if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
@@ -1443,7 +1503,7 @@
 				memcpy_tofs(r, PPP_VERSION, len);
 			break;
 		case SIOCGPPPSTATS:
-			error = isdn_ppp_dev_ioctl_stats (lp->ppp_minor, ifr, dev);
+			error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
 			break;
 		default:
 			error = -EINVAL;
@@ -1452,24 +1512,26 @@
 	return error;
 }
 
-static int isdn_ppp_if_get_unit(char **namebuf)
+static int isdn_ppp_if_get_unit(char *name)
 {
-	char *name = *namebuf;
 	int len, i, unit = 0, deci;
 
 	len = strlen(name);
+
+	if(strncmp("ippp",name,4) || len > 8)
+		return -1;
+
 	for (i = 0, deci = 1; i < len; i++, deci *= 10) {
-		if (name[len - 1 - i] >= '0' && name[len - 1 - i] <= '9')
-			unit += (name[len - 1 - i] - '0') * deci;
+		char a = name[len-i-1];
+		if (a >= '0' && a <= '9')
+			unit += (a - '0') * deci;
 		else
 			break;
 	}
-	if (!i)
+	if (!i || len-i != 4)
 		unit = -1;
 
-	*namebuf = name + len - 1 - i;
 	return unit;
-
 }
 
 
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/isdn_ppp.h linux/drivers/isdn/isdn_ppp.h
--- v2.0.15/linux/drivers/isdn/isdn_ppp.h	Sun May 19 15:29:29 1996
+++ linux/drivers/isdn/isdn_ppp.h	Sat Aug 31 19:13:03 1996
@@ -51,5 +51,6 @@
 extern int  isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
 extern void isdn_ppp_release(int, struct file *);
 extern int  isdn_ppp_dial_slave(char *);
+extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
 
 extern struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
diff -u --recursive --new-file v2.0.15/linux/drivers/isdn/teles/card.c linux/drivers/isdn/teles/card.c
--- v2.0.15/linux/drivers/isdn/teles/card.c	Sat Jun 29 20:36:23 1996
+++ linux/drivers/isdn/teles/card.c	Sat Aug 31 19:01:49 1996
@@ -1,4 +1,4 @@
-/* $Id: card.c,v 1.12 1996/06/24 17:16:52 fritz Exp $
+/* $Id: card.c,v 1.13 1996/07/18 11:21:24 jdenoud Exp $
  *
  * card.c     low level stuff for the Teles S0 isdn card
  * 
@@ -7,6 +7,9 @@
  * Beat Doebeli         log all D channel traffic
  * 
  * $Log: card.c,v $
+ * Revision 1.13  1996/07/18 11:21:24  jdenoud
+ * Use small buffers for incoming audio data
+ *
  * Revision 1.12  1996/06/24 17:16:52  fritz
  * Added check for misconfigured membase.
  *
@@ -424,7 +427,7 @@
 {
 	byte             r;
 	struct HscxState *hsp = sp->hs + hscx;
-	int              count;
+	int              count, err;
 
 	if (!hsp->init)
 		return;
@@ -471,9 +474,15 @@
 	}
       afterRME:
 	if (val & 0x40) {	/* RPF */
-		if (!hsp->rcvibh)
-			if (BufPoolGet(&hsp->rcvibh, &hsp->rbufpool,
-				       GFP_ATOMIC, (void *) 1, 2)) {
+		if (!hsp->rcvibh) {
+			if (hsp->mode == 1)
+				err=BufPoolGet(&hsp->rcvibh, &hsp->smallpool,
+					GFP_ATOMIC, (void *)1, 2);
+			else
+				err=BufPoolGet(&hsp->rcvibh, &hsp->rbufpool,
+					GFP_ATOMIC, (void *)1, 2);
+			
+			if (err) {
 				printk(KERN_WARNING
                                        "HSCX RPF out of buffers at %ld\n",
                                        jiffies);
@@ -482,7 +491,8 @@
 				goto afterRPF;
 			} else
 				hsp->rcvptr = 0;
-
+		}
+		
 		hscx_empty_fifo(hsp, 32);
                 if (hsp->mode == 1) {
                         /* receive audio data */
diff -u --recursive --new-file v2.0.15/linux/drivers/scsi/ChangeLog.ncr53c8xx linux/drivers/scsi/ChangeLog.ncr53c8xx
--- v2.0.15/linux/drivers/scsi/ChangeLog.ncr53c8xx	Tue Jul 23 10:26:41 1996
+++ linux/drivers/scsi/ChangeLog.ncr53c8xx	Sat Aug 31 19:39:10 1996
@@ -1,3 +1,10 @@
+Fri Aug 30  10:00 1996 Gerard Roudier (groudier@club-internet.fr)
+	* ncr53c8xx.c - Version 1.12c
+	Incorporate the changes of FreeBSD/ncr.c revision 1.76.
+	The changes add support for the 53c860 and 53c875, 
+	but without taking advantage of the new features.
+	Those chips are used exactly as the old 53c810.
+
 Sun Jul 21  00:00 1996 Gerard Roudier (groudier@club-internet.fr)
 	* ncr53c8xx.c, README.ncr53c8xx
 	Add the ncr53c8xx_select_queue_depths() function.
diff -u --recursive --new-file v2.0.15/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.0.15/linux/drivers/scsi/ncr53c8xx.c	Sat Aug 17 21:19:27 1996
+++ linux/drivers/scsi/ncr53c8xx.c	Sat Aug 31 19:39:11 1996
@@ -40,7 +40,7 @@
 */
 
 /*
-**	21 July 1996, version 1.12b
+**	30 August 1996, version 1.12c
 **
 **	Supported SCSI-II features:
 **	    Synchronous negotiation
@@ -55,6 +55,8 @@
 **		53C815		(~53C810 with on board rom BIOS)
 **		53C820		(Wide, NCR BIOS in flash bios required)
 **		53C825		(Wide, ~53C820 with on board rom BIOS)
+**		53C860		(not yet tested)
+**		53C875		(not yet tested)
 **
 **	Other features:
 **		Memory mapped IO (linux-1.3.X only)
@@ -1492,7 +1494,7 @@
 static	void	ncr_complete	(ncb_p np, ccb_p cp);
 static	void	ncr_exception	(ncb_p np);
 static	void	ncr_free_ccb	(ncb_p np, ccb_p cp);
-static	void	ncr_getclock	(ncb_p np);
+static	void	ncr_getclock	(ncb_p np, u_char scntl3);
 static	ccb_p	ncr_get_ccb	(ncb_p np, u_long t,u_long l);
 static	void	ncr_init	(ncb_p np, char * msg, u_long code);
 static	int	ncr_intr	(ncb_p np);
@@ -3540,7 +3542,7 @@
 	**	Find the right value for scntl3.
 	*/
 
-	ncr_getclock (np);
+	ncr_getclock (np, INB(nc_scntl3));
 
 	/*
 	**	Reset chip.
@@ -4816,8 +4818,8 @@
 	if ((ChipDevice == PCI_DEVICE_ID_NCR_53C825 && ChipVersion >= 0x10) ||
 	    ChipDevice == PCI_DEVICE_ID_NCR_53C875) {
 		OUTB(nc_dmode, 0xc0);	/* Set 16-transfer burst */
-		OUTB(nc_ctest5, 0x04);	/* Set DMA FIFO to 88 */
 #if 0
+		OUTB(nc_ctest5, 0x04);	/* Set DMA FIFO to 88 */
 		OUTB(nc_ctest5, 0x24);	/* Set DMA FIFO to 536 */
 		OUTB(nc_dmode, 0x40);	/* Set 64-transfer burst */
 		OUTB(nc_ctest3, 0x01);	/* Set write and invalidate */
@@ -6278,9 +6280,18 @@
 		/*
 		**	Check against controller limits.
 		*/
-		fak = (4ul * per - 1) / np->ns_sync - 3;
-		if (ofs && (fak>7))   {chg = 1; ofs = 0;}
-		if (!ofs) fak=7;
+		if (ofs != 0) {
+			fak = (4ul * per - 1) / np->ns_sync - 3;
+			if (fak>7) {
+				chg = 1;
+				ofs = 0;
+			}
+		}
+		if (ofs == 0) {
+			fak = 7;
+			per = 0;
+			tp->minsync = 0;
+		}
 
 		if (DEBUG_FLAGS & DEBUG_NEGO) {
 			PRINT_ADDR(cp->cmd);
@@ -7311,8 +7322,9 @@
 #endif /* NCR_CLOCK */
 
 
-static void ncr_getclock (ncb_p np)
+static void ncr_getclock (ncb_p np, u_char scntl3)
 {
+#if 0
 	u_char	tbl[5] = {6,2,3,4,6};
 	u_char	f;
 	u_char	ns_clock = (1000/NCR_CLOCK);
@@ -7335,6 +7347,25 @@
 	if (DEBUG_FLAGS & DEBUG_TIMING)
 		printf ("%s: sclk=%d async=%d sync=%d (ns) scntl3=0x%x\n",
 		ncr_name (np), ns_clock, np->ns_async, np->ns_sync, np->rv_scntl3);
+#else
+	/*
+	 *	For now just preserve the BIOS setting ...
+	 */
+
+	if ((scntl3 & 7) < 3) {
+		printf ("%s: assuming 40MHz clock", ncr_name(np));
+		scntl3 = 3; /* assume 40MHz if no value supplied by BIOS */
+	}
+
+	np->ns_sync   = 25;
+	np->ns_async  = 50;
+	np->rv_scntl3 = ((scntl3 & 0x7) << 4) -0x20 + (scntl3 & 0x7);
+
+	if (bootverbose) {
+		printf ("%s: initial value of SCNTL3 = %02x, final = %02x\n",
+			ncr_name(np), scntl3, np->rv_scntl3);
+	}
+#endif
 }
 
 /*===================== LINUX ENTRY POINTS SECTION ==========================*/
diff -u --recursive --new-file v2.0.15/linux/drivers/scsi/ncr53c8xx.h linux/drivers/scsi/ncr53c8xx.h
--- v2.0.15/linux/drivers/scsi/ncr53c8xx.h	Tue Jul 23 10:26:41 1996
+++ linux/drivers/scsi/ncr53c8xx.h	Sat Aug 31 19:39:11 1996
@@ -196,7 +196,7 @@
 
 #if	LINUX_VERSION_CODE >= LinuxVersionCode(1,3,0)
 
-#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12b)", ncr53c8xx_detect,\
+#define NCR53C8XX {NULL,NULL,NULL,NULL,"ncr53c8xx (rel 1.12c)", ncr53c8xx_detect,\
     	ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset,	\
         NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
@@ -207,7 +207,7 @@
 #else
 
 
-#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12b)", ncr53c8xx_detect,\
+#define NCR53C8XX {NULL, NULL, "ncr53c8xx (rel 1.12c)", ncr53c8xx_detect,\
     	ncr53c8xx_release, /* info */ NULL, /* command, deprecated */ NULL, 		\
 	ncr53c8xx_queue_command, ncr53c8xx_abort, ncr53c8xx_reset,	\
         NULL /* slave attach */, scsicam_bios_param, /* can queue */ SCSI_NCR_CAN_QUEUE,\
diff -u --recursive --new-file v2.0.15/linux/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- v2.0.15/linux/drivers/scsi/sg.c	Mon Aug  5 10:13:53 1996
+++ linux/drivers/scsi/sg.c	Sat Aug 31 20:52:43 1996
@@ -275,8 +275,39 @@
      * See if the command completed normally, or whether something went
      * wrong.
      */
-    memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
-    device->header.result = (SCpnt->sense_buffer[0] == 0 ? 0 : EIO);
+    memcpy(device->header.sense_buffer, SCpnt->sense_buffer,
+	   sizeof(SCpnt->sense_buffer));
+    switch (host_byte(SCpnt->result)) {
+    case DID_OK:
+      device->header.result = 0;
+      break;
+    case DID_NO_CONNECT:
+    case DID_BUS_BUSY:
+    case DID_TIME_OUT: 
+      device->header.result = EBUSY;
+      break;
+    case DID_BAD_TARGET: 
+    case DID_ABORT: 
+    case DID_PARITY: 
+    case DID_RESET:
+    case DID_BAD_INTR: 
+      device->header.result = EIO;
+      break;
+    case DID_ERROR:
+      /*
+       * There really should be DID_UNDERRUN and DID_OVERRUN error values,
+       * and a means for callers of scsi_do_cmd to indicate whether an
+       * underrun or overrun should signal an error.  Until that can be
+       * implemented, this kludge allows for returning useful error values
+       * except in cases that return DID_ERROR that might be due to an
+       * underrun.
+       */
+      if (SCpnt->sense_buffer[0] == 0 &&
+	  status_byte(SCpnt->result) == GOOD)
+	device->header.result = 0;
+      else device->header.result = EIO;
+      break;
+    }
 
     /*
      * Now wake up the process that is waiting for the
diff -u --recursive --new-file v2.0.15/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- v2.0.15/linux/drivers/scsi/wd7000.c	Fri Mar  1 07:50:54 1996
+++ linux/drivers/scsi/wd7000.c	Sat Aug 31 20:52:44 1996
@@ -98,6 +98,23 @@
  *  one of the FD boards, it would be nice to come up with a signature
  *  for it.
  *                                                           J.B. Jan 1994.
+ *
+ *
+ *  Revision: 08/24/1996. by Miroslav Zagorac <zaga@fly.cc.fer.hr>
+ *
+ *  Enhancement for wd7000_detect function has been made, so you don't have
+ *  to enter BIOS ROM adress and IO port in initialisation data (see struct
+ *  Config). We cannot detect IRQ and DMA for now, so we have to enter them
+ *  as arguments while wd_7000 is detected. If someone has IRQ and DMA set
+ *  to some other value, he can enter them in configuration without any
+ *  problem. Also I wrote a function wd7000_setup, so now you can enter
+ *  WD-7000 definition as kernel arguments, as in lilo.conf:
+ *
+ *     append="wd7000=IRQ,DMA"
+ *
+ *  PS: If card BIOS ROM is disabled, function wd7000_detect now will recognize
+ *      adapter, unlike the old one. Anyway, BIOS ROM from WD7000 adapter is
+ *      worthless for Linux. :)
  */
 
 #ifdef MODULE
@@ -121,7 +138,7 @@
 #include "hosts.h"
 #include "sd.h"
 
-#define ANY2SCSI_INLINE    /* undef this to use old macros */
+#define ANY2SCSI_INLINE		/* undef this to use old macros */
 #undef DEBUG
 
 #include "wd7000.h"
@@ -158,7 +175,7 @@
  */
 typedef volatile struct mailbox{
   unchar status;
-  unchar scbptr[3];             /* SCSI-style - MSB first (big endian) */
+  unchar scbptr[3];		/* SCSI-style - MSB first (big endian) */
 } Mailbox;
 
 /*
@@ -167,17 +184,17 @@
  *
  */
 typedef struct adapter {
-  struct Scsi_Host *sh;             /* Pointer to Scsi_Host structure */
-  int iobase;                       /* This adapter's I/O base address */
-  int irq;                          /* This adapter's IRQ level */
-  int dma;                          /* This adapter's DMA channel */
-  struct {                          /* This adapter's mailboxes */
-    Mailbox ogmb[OGMB_CNT];             /* Outgoing mailboxes */
-    Mailbox icmb[ICMB_CNT];             /* Incoming mailboxes */
+  struct Scsi_Host *sh;		/* Pointer to Scsi_Host structure */
+  int iobase;			/* This adapter's I/O base address */
+  int irq;			/* This adapter's IRQ level */
+  int dma;			/* This adapter's DMA channel */
+  struct {			/* This adapter's mailboxes */
+    Mailbox ogmb[OGMB_CNT];	/* Outgoing mailboxes */
+    Mailbox icmb[ICMB_CNT];	/* Incoming mailboxes */
   } mb;
-  int next_ogmb;                    /* to reduce contention at mailboxes */
-  unchar control;                   /* shadows CONTROL port value */
-  unchar rev1, rev2;                /* filled in by wd7000_revision */
+  int next_ogmb;		/* to reduce contention at mailboxes */
+  unchar control;		/* shadows CONTROL port value */
+  unchar rev1, rev2;		/* filled in by wd7000_revision */
 } Adapter;
 
 /*
@@ -186,22 +203,47 @@
  * Note that if SA_INTERRUPT is not used, wd7000_intr_handle must be
  * changed to pick up the IRQ level correctly.
  */
-Adapter *irq2host[16] = {NULL};  /* Possible IRQs are 0-15 */
+Adapter *irq2host[16] = {NULL};	/* Possible IRQs are 0-15 */
+
+/*
+ * (linear) base address for ROM BIOS
+ */
+static const long wd7000_biosaddr[] = {
+  0xc0000, 0xc2000, 0xc4000, 0xc6000, 0xc8000, 0xca000, 0xcc000, 0xce000,
+  0xd0000, 0xd2000, 0xd4000, 0xd6000, 0xd8000, 0xda000, 0xdc000, 0xde000
+};
+#define NUM_ADDRS (sizeof(wd7000_biosaddr)/sizeof(long))
+
+static const unsigned short wd7000_iobase[] = {
+  0x0300, 0x0308, 0x0310, 0x0318, 0x0320, 0x0328, 0x0330, 0x0338,
+  0x0340, 0x0348, 0x0350, 0x0358, 0x0360, 0x0368, 0x0370, 0x0378,
+  0x0380, 0x0388, 0x0390, 0x0398, 0x03a0, 0x03a8, 0x03b0, 0x03b8,
+  0x03c0, 0x03c8, 0x03d0, 0x03d8, 0x03e0, 0x03e8, 0x03f0, 0x03f8
+};
+#define NUM_IOPORTS (sizeof(wd7000_iobase)/sizeof(unsigned short))
+
+static const short wd7000_irq[] = { 3, 4, 5, 7, 9, 10, 11, 12, 14, 15 };
+#define NUM_IRQS (sizeof(wd7000_irq)/sizeof(short))
 
+static const short wd7000_dma[] = { 5, 6, 7 };
+#define NUM_DMAS (sizeof(wd7000_dma)/sizeof(short))
+  
 /*
  *  Standard Adapter Configurations - used by wd7000_detect
  */
 typedef struct {
-  const void *bios;             /* (linear) base address for ROM BIOS */
-  int iobase;                   /* I/O ports base address */
-  int irq;                      /* IRQ level */
-  int dma;                      /* DMA channel */
+  int irq;			/* IRQ level */
+  int dma;			/* DMA channel */
 } Config;
 
+/*
+ * Add here your configuration...
+ */
 static const Config configs[] = {
-  {(void *) 0xce000, 0x350, 15, 6},  /* defaults for single adapter */
-  {(void *) 0xc8000, 0x330, 11, 5},  /* defaults for second adapter */
-  {(void *) 0xd8000, 0x350, 15, 6},  /* Arghhh.... who added this ? */
+  { 15,  6 },			/* defaults for single adapter */
+  { 11,  5 },			/* defaults for second adapter */
+  {  9,  6 },			/* My configuretion (Zaga)     */
+  { -1, -1 }                    /* Empty slot                  */
 };
 #define NUM_CONFIGS (sizeof(configs)/sizeof(Config))
 
@@ -211,13 +253,13 @@
  *  added for the Future Domain version.
  */
 typedef struct signature {
-    const void *sig;           /* String to look for */
-    unsigned    ofs;           /* offset from BIOS base address */
-    unsigned    len;           /* length of string */
+    const void *sig;		/* String to look for */
+    unsigned    ofs;		/* offset from BIOS base address */
+    unsigned    len;		/* length of string */
 } Signature;
 
 static const Signature signatures[] = {
-  {"SSTBIOS",0x0000d,7}                  /* "SSTBIOS" @ offset 0x0000d */
+  { "SSTBIOS", 0x0000d, 7 }	/* "SSTBIOS" @ offset 0x0000d */
 };
 #define NUM_SIGNATURES (sizeof(signatures)/sizeof(Signature))
 
@@ -226,19 +268,20 @@
  *  I/O Port Offsets and Bit Definitions
  *  4 addresses are used.  Those not defined here are reserved.
  */
-#define ASC_STAT        0       /* Status,  Read */
-#define ASC_COMMAND     0       /* Command, Write */
-#define ASC_INTR_STAT   1       /* Interrupt Status, Read */
-#define ASC_INTR_ACK    1       /* Acknowledge, Write */
-#define ASC_CONTROL     2       /* Control, Write */
-
-/* ASC Status Port
- */
-#define INT_IM		0x80		/* Interrupt Image Flag */
-#define CMD_RDY		0x40		/* Command Port Ready */
-#define CMD_REJ		0x20		/* Command Port Byte Rejected */
-#define ASC_INIT        0x10		/* ASC Initialized Flag */
-#define ASC_STATMASK    0xf0		/* The lower 4 Bytes are reserved */
+#define ASC_STAT        0	/* Status,  Read */
+#define ASC_COMMAND     0	/* Command, Write */
+#define ASC_INTR_STAT   1	/* Interrupt Status, Read */
+#define ASC_INTR_ACK    1	/* Acknowledge, Write */
+#define ASC_CONTROL     2	/* Control, Write */
+
+/*
+ * ASC Status Port
+ */
+#define INT_IM		0x80	/* Interrupt Image Flag */
+#define CMD_RDY		0x40	/* Command Port Ready */
+#define CMD_REJ		0x20	/* Command Port Byte Rejected */
+#define ASC_INIT        0x10	/* ASC Initialized Flag */
+#define ASC_STATMASK    0xf0	/* The lower 4 Bytes are reserved */
 
 /* COMMAND opcodes
  *
@@ -248,31 +291,31 @@
  *  discernible effect whatsoever.  I think they may be related to certain
  *  ICB commands, but again, the OEM manual doesn't make that clear.
  */
-#define NO_OP             0     /* NO-OP toggles CMD_RDY bit in ASC_STAT */
-#define INITIALIZATION    1     /* initialization (10 bytes) */
-#define DISABLE_UNS_INTR  2     /* disable unsolicited interrupts */
-#define ENABLE_UNS_INTR   3     /* enable unsolicited interrupts */
-#define INTR_ON_FREE_OGMB 4     /* interrupt on free OGMB */
-#define SOFT_RESET        5     /* SCSI bus soft reset */
-#define HARD_RESET_ACK    6     /* SCSI bus hard reset acknowledge */
-#define START_OGMB        0x80  /* start command in OGMB (n) */
-#define SCAN_OGMBS        0xc0  /* start multiple commands, signature (n) */
+#define NO_OP             0	/* NO-OP toggles CMD_RDY bit in ASC_STAT */
+#define INITIALIZATION    1	/* initialization (10 bytes) */
+#define DISABLE_UNS_INTR  2	/* disable unsolicited interrupts */
+#define ENABLE_UNS_INTR   3	/* enable unsolicited interrupts */
+#define INTR_ON_FREE_OGMB 4	/* interrupt on free OGMB */
+#define SOFT_RESET        5	/* SCSI bus soft reset */
+#define HARD_RESET_ACK    6	/* SCSI bus hard reset acknowledge */
+#define START_OGMB        0x80	/* start command in OGMB (n) */
+#define SCAN_OGMBS        0xc0	/* start multiple commands, signature (n) */
 				/*    where (n) = lower 6 bits */
 /* For INITIALIZATION:
  */
 typedef struct initCmd {
-  unchar op;                   /* command opcode (= 1) */
-  unchar ID;                   /* Adapter's SCSI ID */
-  unchar bus_on;               /* Bus on time, x 125ns (see below) */
-  unchar bus_off;              /* Bus off time, ""         ""      */
-  unchar rsvd;                 /* Reserved */
-  unchar mailboxes[3];         /* Address of Mailboxes, MSB first  */
-  unchar ogmbs;                /* Number of outgoing MBs, max 64, 0,1 = 1 */
-  unchar icmbs;                /* Number of incoming MBs,   ""       ""   */
+  unchar op;			/* command opcode (= 1) */
+  unchar ID;			/* Adapter's SCSI ID */
+  unchar bus_on;		/* Bus on time, x 125ns (see below) */
+  unchar bus_off;		/* Bus off time, ""         ""      */
+  unchar rsvd;			/* Reserved */
+  unchar mailboxes[3];		/* Address of Mailboxes, MSB first  */
+  unchar ogmbs;			/* Number of outgoing MBs, max 64, 0,1 = 1 */
+  unchar icmbs;			/* Number of incoming MBs,   ""       ""   */
 } InitCmd;
 
-#define BUS_ON            64    /* x 125ns = 8000ns (BIOS default) */
-#define BUS_OFF           15    /* x 125ns = 1875ns (BIOS default) */
+#define BUS_ON            64	/* x 125ns = 8000ns (BIOS default) */
+#define BUS_OFF           15	/* x 125ns = 1875ns (BIOS default) */
  
 /* Interrupt Status Port - also returns diagnostic codes at ASC reset
  *
@@ -301,29 +344,29 @@
 #define ASC_RES		0x01	/* ASC Reset		*/
 
 /*
-   Driver data structures:
-   - mb and scbs are required for interfacing with the host adapter.
-     An SCB has extra fields not visible to the adapter; mb's
-     _cannot_ do this, since the adapter assumes they are contiguous in
-     memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
-     to access them.
-   - An icb is for host-only (non-SCSI) commands.  ICBs are 16 bytes each;
-     the additional bytes are used only by the driver.
-   - For now, a pool of SCBs are kept in global storage by this driver,
-     and are allocated and freed as needed.
-
-  The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
-  not when it has finished.  Since the SCB must be around for completion,
-  problems arise when SCBs correspond to OGMBs, which may be reallocated
-  earlier (or delayed unnecessarily until a command completes).
-  Mailboxes are used as transient data structures, simply for
-  carrying SCB addresses to/from the 7000-FASST2.
-
-  Note also since SCBs are not "permanently" associated with mailboxes,
-  there is no need to keep a global list of Scsi_Cmnd pointers indexed
-  by OGMB.   Again, SCBs reference their Scsi_Cmnds directly, so mailbox
-  indices need not be involved.
-*/
+ *   Driver data structures:
+ *   - mb and scbs are required for interfacing with the host adapter.
+ *     An SCB has extra fields not visible to the adapter; mb's
+ *     _cannot_ do this, since the adapter assumes they are contiguous in
+ *     memory, 4 bytes each, with ICMBs following OGMBs, and uses this fact
+ *     to access them.
+ *   - An icb is for host-only (non-SCSI) commands.  ICBs are 16 bytes each;
+ *     the additional bytes are used only by the driver.
+ *   - For now, a pool of SCBs are kept in global storage by this driver,
+ *     and are allocated and freed as needed.
+ *
+ *  The 7000-FASST2 marks OGMBs empty as soon as it has _started_ a command,
+ *  not when it has finished.  Since the SCB must be around for completion,
+ *  problems arise when SCBs correspond to OGMBs, which may be reallocated
+ *  earlier (or delayed unnecessarily until a command completes).
+ *  Mailboxes are used as transient data structures, simply for
+ *  carrying SCB addresses to/from the 7000-FASST2.
+ *
+ *  Note also since SCBs are not "permanently" associated with mailboxes,
+ *  there is no need to keep a global list of Scsi_Cmnd pointers indexed
+ *  by OGMB.   Again, SCBs reference their Scsi_Cmnds directly, so mailbox
+ *  indices need not be involved.
+ */
 
 /*
  *  WD7000-specific scatter/gather element structure
@@ -483,10 +526,87 @@
 static int freescbs = MAX_SCBS;  /* free list counter */
 
 /*
+ *
+ */
+static short wd7000_setupIRQ[NUM_CONFIGS];
+static short wd7000_setupDMA[NUM_CONFIGS];
+static short wd7000_card_num = 0;
+
+/*
  *  END of data/declarations - code follows.
  */
 
 
+/*
+ * Note: You can now set these options from the kernel's "command line".
+ * The syntax is:
+ *
+ *     wd7000=IRQ,DMA
+ * eg:
+ *     wd7000=15,6
+ *
+ * will configure the driver for a WD-7000 controller
+ * using IRQ 15 with a DMA channel 6.
+ */
+void wd7000_setup (char *str, int *ints) {
+    short i, j;
+
+    if (wd7000_card_num >= NUM_CONFIGS) {
+        printk ("wd7000_setup: Too many \"wd7000=\" configurations in "
+	        "command line!\n");
+
+        return;
+    }
+
+    if (ints[0] != 2)
+	printk ("wd7000_setup: Error in command line!  "
+	        "Usage: wd7000=IRQ,DMA\n");
+    else {
+	for (i = 0; i < NUM_IRQS; i++)
+	    if (ints[1] == wd7000_irq[i])
+		break;
+
+	if (i == NUM_IRQS) {
+	    printk ("wd7000_setup: invalid IRQ.\n");
+	    return;
+	}
+	else
+ 	    wd7000_setupIRQ[wd7000_card_num] = ints[1];
+
+	for (i = 0; i < NUM_DMAS; i++)
+	    if (ints[2] == wd7000_dma[i])
+		break;
+
+	if (i == NUM_IRQS) {
+	    printk ("wd7000_setup: invalid DMA channel.\n");
+	    return;
+	}
+	else
+	    wd7000_setupDMA[wd7000_card_num] = ints[2];
+
+	if (wd7000_card_num)
+	    for (i = 0; i < (wd7000_card_num - 1); i++)
+	        for (j = i + 1; j < wd7000_card_num; j++)
+	            if (wd7000_setupIRQ[i] == wd7000_setupIRQ[j]) {
+	                printk ("wd7000_setup: duplicated IRQ!\n");
+		        return;
+	            }
+	            else if (wd7000_setupDMA[i] == wd7000_setupDMA[j]) {
+	                printk ("wd7000_setup: duplicated DMA channel!\n");
+		        return;
+	            }
+
+#ifdef DEBUG
+	printk ("wd7000_setup: IRQ=%d, DMA=%d\n",
+	        wd7000_setupIRQ[wd7000_card_num],
+		wd7000_setupDMA[wd7000_card_num]);
+#endif
+
+	wd7000_card_num++;
+    }
+}
+
+
 #ifdef ANY2SCSI_INLINE
 /*
    Since they're used a lot, I've redone the following from the macros
@@ -627,7 +747,8 @@
 	timeout = jiffies + WAITnexttimeout;
 	do {
 	    sti();	/* Yes this is really needed here */
-	    now = jiffies;   while (jiffies == now) /* wait a jiffy */;
+	    now = jiffies;
+	    while (jiffies == now); /* wait a jiffy */
 	    cli();
 	}  while (freescbs < needed && jiffies <= timeout);
 	/*
@@ -699,7 +820,7 @@
     Mailbox *ogmbs = host->mb.ogmb;
     int *next_ogmb = &(host->next_ogmb);
 #ifdef DEBUG
-    printk("wd7000 mail_out: %06x",(unsigned int) scbptr);
+    printk("wd7000 mail_out: 0x%06lx",(long) scbptr);
 #endif
     /* We first look for a free outgoing mailbox */
     save_flags(flags);
@@ -708,7 +829,7 @@
     for (i = 0; i < OGMB_CNT; i++) {
 	if (ogmbs[ogmb].status == 0)  {
 #ifdef DEBUG
-	    printk(" using OGMB %x",ogmb);
+	    printk(" using OGMB 0x%x",ogmb);
 #endif
 	    ogmbs[ogmb].status = 1;
 	    any2scsi((unchar *) ogmbs[ogmb].scbptr, (int) scbptr);
@@ -720,7 +841,7 @@
     }
     restore_flags(flags);
 #ifdef DEBUG
-    printk(", scb is %x",(unsigned int) scbptr);
+    printk(", scb is 0x%06lx",(long) scbptr);
 #endif
     if (i >= OGMB_CNT) {
 	/*
@@ -790,7 +911,7 @@
 	}
 #ifdef DEBUG
     if (scsierr||hosterr)
-	printk("\nSCSI command error: SCSI %02x host %04x return %d",
+	printk("\nSCSI command error: SCSI 0x%02x host 0x%04x return %d\n",
 	       scsierr,in_error,hosterr);
 #endif
     return scsierr | (hosterr << 16);
@@ -800,7 +921,7 @@
 static void wd7000_scsi_done(Scsi_Cmnd * SCpnt)
 {
 #ifdef DEBUG
-    printk("wd7000_scsi_done: %06x\n",(unsigned int) SCpnt);
+    printk("wd7000_scsi_done: 0x%06x\n",(long) SCpnt);
 #endif
     SCpnt->SCp.phase = 0;
 }
@@ -819,12 +940,12 @@
     Mailbox *icmbs = host->mb.icmb;
 
 #ifdef DEBUG
-    printk("wd7000_intr_handle: irq = %d, host = %06x\n", irq, host);
+    printk("wd7000_intr_handle: irq = %d, host = 0x%06lx\n", irq, (long) host);
 #endif
 
     flag = inb(host->iobase+ASC_INTR_STAT);
 #ifdef DEBUG
-    printk("wd7000_intr_handle: intr stat = %02x\n",flag);
+    printk("wd7000_intr_handle: intr stat = 0x%02x\n",flag);
 #endif
 
     if (!(inb(host->iobase+ASC_STAT) & INT_IM))  {
@@ -847,7 +968,7 @@
 	/* The interrupt is for a mailbox */
 	if (!(flag & IMB_INTR)) {
 #ifdef DEBUG
-	    printk("wd7000_intr_handle: free outgoing mailbox");
+	    printk("wd7000_intr_handle: free outgoing mailbox\n");
 #endif
 	    /*
 	     * If sleep_on() and the "interrupt on free OGMB" command are
@@ -862,7 +983,7 @@
 	    icmb_status = icmbs[icmb].status;
 	    if (icmb_status & 0x80)  {  /* unsolicited - result in ICMB */
 #ifdef DEBUG
- 		printk("wd7000_intr_handle: unsolicited interrupt %02xh\n",
+ 		printk("wd7000_intr_handle: unsolicited interrupt 0x%02xh\n",
 		       icmb_status);
 #endif
 		wd7000_intr_ack(host);
@@ -983,7 +1104,7 @@
 	return 0;
     }
     if (make_code(icb.vue|(icb.status << 8),0))  {
-	printk("wd7000_diagnostics: failed (%02x,%02x)\n",
+	printk("wd7000_diagnostics: failed (0x%02x,0x%02x)\n",
 	       icb.vue, icb.status);
 	return 0;
     }
@@ -1011,6 +1132,7 @@
 
     if ((diag = inb(host->iobase+ASC_INTR_STAT)) != 1)  {
 	printk("wd7000_init: ");
+
 	switch (diag)  {
 	case 2:
 	  printk("RAM failure.\n");
@@ -1031,8 +1153,7 @@
 	  printk("ROM checksum error.\n");
 	  break;
 	default:
-	  printk("diagnostic code %02Xh received.\n", diag);
-	  break;
+	  printk("diagnostic code 0x%02Xh received.\n", diag);
 	}
 	return 0;
     }
@@ -1093,8 +1214,7 @@
 }
 
 
-int wd7000_detect(Scsi_Host_Template * tpnt)
-/* 
+/*
  *  Returns the number of adapters this driver is supporting.
  *
  *  The source for hosts.c says to wait to call scsi_register until 100%
@@ -1104,87 +1224,139 @@
  *  calling scsi_unregister.
  *
  */
+int wd7000_detect (Scsi_Host_Template *tpnt)
 {
-    int i,j, present = 0;
-    const Config *cfg;
-    const Signature *sig;
+    short present = 0, biosaddr_ptr, iobase_ptr, cfg_ptr, sig_ptr, i;
+    short biosptr[NUM_CONFIGS];
     Adapter *host = NULL;
     struct Scsi_Host *sh;
 
+    for (i = 0; i < NUM_CONFIGS; biosptr[i++] = -1);
+
     tpnt->proc_dir = &proc_scsi_wd7000;
 
-    /* Set up SCB free list, which is shared by all adapters */
-    init_scbs();
+    /*
+     * Set up SCB free list, which is shared by all adapters
+     */
+    init_scbs ();
+
+    for (cfg_ptr = 0; cfg_ptr < NUM_CONFIGS; cfg_ptr++) {
+        for (biosaddr_ptr = 0; biosaddr_ptr < NUM_ADDRS; biosaddr_ptr++)
+	    for (sig_ptr = 0; sig_ptr < NUM_SIGNATURES; sig_ptr++) {
+	        for (i = 0; i < cfg_ptr; i++)
+	            if (biosptr[i] == biosaddr_ptr)
+		        break;
+
+		if ((i == cfg_ptr) &&
+		    !memcmp ((void *) (wd7000_biosaddr[biosaddr_ptr] +
+		             signatures[sig_ptr].ofs), signatures[sig_ptr].sig,
+		             signatures[sig_ptr].len))
+		    goto bios_matched;
+	    }
+
+bios_matched:
 
-    cfg = configs;
-    for (i = 0; i < NUM_CONFIGS; i++)  {
-	sig = signatures;
-	for (j = 0; j < NUM_SIGNATURES; j++)  {
-	    if (!memcmp(cfg->bios+sig->ofs, sig->sig, sig->len))  {
-		/* matched this one */
 #ifdef DEBUG
-		printk("WD-7000 SST BIOS detected at %04X: checking...\n",
-		       (int) cfg->bios);
+	printk ("wd7000_detect: pass %d\n", cfg_ptr + 1);
+
+        if (biosaddr_ptr == NUM_ADDRS)
+	    printk ("WD-7000 SST BIOS not detected...\n");
+	else
+	    printk ("WD-7000 SST BIOS detected at 0x%lx: checking...\n",
+	            wd7000_biosaddr[biosaddr_ptr]);
 #endif
-		/*
-		 *  We won't explicitly test the configuration (in this
-		 *  version); instead, we'll just see if it works to
-		 *  setup the adapter; if it does, we'll use it.
-		 */
-		if (check_region(cfg->iobase, 4))  {  /* ports in use */
-		    printk("IO %xh already in use.\n", host->iobase);
-		    continue;
-		}
-		/*
-		 *  We register here, to get a pointer to the extra space,
-		 *  which we'll use as the Adapter structure (host) for
-		 *  this adapter.  It is located just after the registered
-		 *  Scsi_Host structure (sh), and is located by the empty
-		 *  array hostdata.
+
+	for (iobase_ptr = 0; iobase_ptr < NUM_IOPORTS; iobase_ptr++)
+	    if (! check_region (wd7000_iobase[iobase_ptr], 4)) {
+	        /*
+		 * ASC reset...
 		 */
-		sh = scsi_register(tpnt, sizeof(Adapter) );
-		host = (Adapter *) sh->hostdata;
+ 	        outb (ASC_RES, wd7000_iobase[iobase_ptr] + ASC_CONTROL);
+	        delay (1);
+	        outb (0, wd7000_iobase[iobase_ptr] + ASC_CONTROL);
+	        WAIT (wd7000_iobase[iobase_ptr] + ASC_STAT, ASC_STATMASK,
+		      CMD_RDY, 0);
+
+		if (inb (wd7000_iobase[iobase_ptr] + ASC_INTR_STAT) == 1) {
+		   /*
+		    *  We register here, to get a pointer to the extra space,
+		    *  which we'll use as the Adapter structure (host) for
+		    *  this adapter.  It is located just after the registered
+		    *  Scsi_Host structure (sh), and is located by the empty
+		    *  array hostdata.
+		    */
+	    	    sh = scsi_register (tpnt, sizeof (Adapter));
+	    	    host = (Adapter *) sh->hostdata;
+
 #ifdef DEBUG
-		printk("wd7000_detect: adapter allocated at %06x\n",
-		       (int)host);
+	    	    printk ("wd7000_detect: adapter allocated at 0x%x\n",
+	    		    (int) host);
 #endif
-		memset( host, 0, sizeof(Adapter) );
-		host->sh = sh;
-		host->irq = cfg->irq;
-		host->iobase = cfg->iobase;
-		host->dma = cfg->dma;
-		irq2host[host->irq] = host;
-
-		if (!wd7000_init(host))  {  /* Initialization failed */
-		    scsi_unregister (sh);
-		    continue;
-		}
 
-		/*
-		 *  OK from here - we'll use this adapter/configuration.
-		 */
-		wd7000_revision(host);   /* important for scatter/gather */
+	    	    memset (host, 0, sizeof (Adapter));
 
-		printk("Western Digital WD-7000 (%d.%d) ",
-		       host->rev1, host->rev2);
-		printk("using IO %xh IRQ %d DMA %d.\n",
-		       host->iobase, host->irq, host->dma);
-
-		request_region(host->iobase, 4,"wd7000"); /* Register our ports */
-		/*
-		 *  For boards before rev 6.0, scatter/gather isn't supported.
-		 */
-		if (host->rev1 < 6)  sh->sg_tablesize = SG_NONE;
+		    if (wd7000_card_num) {
+	    	        host->irq = wd7000_setupIRQ[--wd7000_card_num];
+	    	        host->dma = wd7000_setupDMA[wd7000_card_num];
+		    }
+		    else {
+	    	        host->irq = configs[cfg_ptr].irq;
+	    	        host->dma = configs[cfg_ptr].dma;
+		    }
+
+	    	    host->sh = sh;
+	    	    host->iobase = wd7000_iobase[iobase_ptr];
+	    	    irq2host[host->irq] = host;
 
-		present++;                      /* count it */
-		break;                          /* don't try any more sigs */
+#ifdef DEBUG
+		    printk ("wd7000_detect: Trying init WD-7000 card at IO "
+			    "0x%x, IRQ %d, DMA %d...\n",
+			    host->iobase, host->irq, host->dma);
+#endif
+
+	    	    if (! wd7000_init (host)) {  /* Initialization failed */
+	    		scsi_unregister (sh);
+
+	    		continue;
+	    	    }
+
+		    /*
+		     *  OK from here - we'll use this adapter/configuration.
+		     */
+		    wd7000_revision (host);   /* important for scatter/gather */
+
+                    /*
+		     * Register our ports.
+		     */
+    		    request_region (host->iobase, 4, "wd7000");
+
+    		    /*
+    		     *  For boards before rev 6.0, scatter/gather
+		     *  isn't supported.
+    		     */
+    		    if (host->rev1 < 6)
+   		       sh->sg_tablesize = SG_NONE;
+
+    		    present++;		/* count it */
+
+		    if (biosaddr_ptr != NUM_ADDRS)
+                        biosptr[cfg_ptr] = biosaddr_ptr;
+
+                    printk ("Western Digital WD-7000 (rev %d.%d) ",
+			    host->rev1, host->rev2);
+                    printk ("using IO 0x%xh, IRQ %d, DMA %d.\n", 
+	                    host->iobase, host->irq, host->dma);
+
+	    	    break;
+		}
+fail:
 	    }
-	    sig++;  /* try next signature with this configuration */
-	}
-	cfg++;      /* try next configuration */
     }
 
-    return present;
+    if (! present)
+       printk ("Failed initialization of WD-7000 SCSI card!\n");
+
+    return (present);
 }
 
 
diff -u --recursive --new-file v2.0.15/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v2.0.15/linux/drivers/sound/dmabuf.c	Wed Aug 21 09:18:09 1996
+++ linux/drivers/sound/dmabuf.c	Sat Aug 31 19:39:10 1996
@@ -1182,7 +1182,7 @@
       if (!audio_devs[dev]->go)
 	tmout = 0;
       else
-	tmout = 2 * HZ;
+	tmout = 10 * HZ;
 
 
       {
diff -u --recursive --new-file v2.0.15/linux/fs/buffer.c linux/fs/buffer.c
--- v2.0.15/linux/fs/buffer.c	Sat Aug 10 10:03:15 1996
+++ linux/fs/buffer.c	Sat Aug 31 16:43:52 1996
@@ -968,11 +968,6 @@
  */
 static void put_unused_buffer_head(struct buffer_head * bh)
 {
-	struct wait_queue * wait;
-
-	wait = ((volatile struct buffer_head *) bh)->b_wait;
-	memset(bh,0,sizeof(*bh));
-	((volatile struct buffer_head *) bh)->b_wait = wait;
 	bh->b_next_free = unused_list;
 	unused_list = bh;
 	wake_up(&buffer_wait);
@@ -1402,6 +1397,11 @@
 
 /* =========== Reduce the buffer memory ============= */
 
+static inline int buffer_waiting(struct buffer_head * bh)
+{
+	return waitqueue_active(&bh->b_wait);
+}
+
 /*
  * try_to_free_buffer() checks if all the buffers on this particular page
  * are unused, and free's the page if so.
@@ -1421,7 +1421,8 @@
 		if (!tmp)
 			return 0;
 		if (tmp->b_count || buffer_protected(tmp) ||
-		    buffer_dirty(tmp) || buffer_locked(tmp) || tmp->b_wait)
+		    buffer_dirty(tmp) || buffer_locked(tmp) ||
+		    buffer_waiting(bh))
 			return 0;
 		if (priority && buffer_touched(tmp))
 			return 0;
diff -u --recursive --new-file v2.0.15/linux/fs/locks.c linux/fs/locks.c
--- v2.0.15/linux/fs/locks.c	Tue Jul  2 19:08:42 1996
+++ linux/fs/locks.c	Thu Aug 29 19:07:37 1996
@@ -132,6 +132,15 @@
 /* Free lock not inserted in any queue */
 static inline void locks_free_lock(struct file_lock *fl)
 {
+	/*
+	 * CAREFUL! We can't free it until everybody waiting for
+	 * this block have removed themselves from the wait queue
+	 */
+	if (fl->fl_wait) {
+		struct wait_queue *head = WAIT_QUEUE_HEAD(&fl->fl_wait);
+		while (fl->fl_wait != head)
+			schedule();
+	}
 	kfree(fl);
 	return;
 }
@@ -636,10 +645,12 @@
 	if (my_task == blocked_task)
 		return (1);
 	for (fl = file_lock_table; fl != NULL; fl = fl->fl_nextlink) {
+		struct wait_queue *head;
 		if (fl->fl_owner == NULL || fl->fl_wait == NULL)
 			continue;
+		head = WAIT_QUEUE_HEAD(&fl->fl_wait);
 		dlock_wait = fl->fl_wait;
-		do {
+		while (dlock_wait != head) {
 			if (dlock_wait->task == blocked_task) {
 				if (fl->fl_owner == my_task) {
 					return (1);
@@ -648,7 +659,7 @@
 				goto next_task;
 			}
 			dlock_wait = dlock_wait->next;
-		} while (dlock_wait != fl->fl_wait);
+		}
 	}
 	return (0);
 }
@@ -979,7 +990,7 @@
 	}
 
 	wake_up(&fl->fl_wait);
-	kfree(fl);
+	locks_free_lock(fl);
 
 	return;
 }
@@ -1014,10 +1025,11 @@
 		     (long)fl, (long)fl->fl_prevlink, (long)fl->fl_nextlink,
 		     (long)fl->fl_next, (long)fl->fl_block, id, pfx);
 	if ((wt = fl->fl_wait) != NULL) {
-		do {
+		struct wait_queue *head = WAIT_QUEUE_HEAD(&fl->fl_wait);
+		while (wt != head) {
 			p += sprintf(p, " %d", wt->task->pid);
 			wt = wt->next;
-		} while (wt != fl->fl_wait);
+		}
 	}
 	p += sprintf(p, "\n");
 	return (p);
diff -u --recursive --new-file v2.0.15/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.0.15/linux/include/linux/isdn.h	Sat Jun 29 20:36:23 1996
+++ linux/include/linux/isdn.h	Sat Aug 31 19:01:49 1996
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.15 1996/06/15 14:56:57 fritz Exp $
+/* $Id: isdn.h,v 1.16 1996/08/12 16:20:56 hipp Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -21,6 +21,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.16  1996/08/12 16:20:56  hipp
+ * renamed ppp_minor to ppp_slot
+ *
  * Revision 1.15  1996/06/15 14:56:57  fritz
  * Added version signatures for data structures used
  * by userlevel programs.
@@ -319,7 +322,7 @@
   struct enet_statistics stats;        /* Ethernet Statistics              */
   int                    isdn_device;  /* Index to isdn-device             */
   int                    isdn_channel; /* Index to isdn-channel            */
-  int			 ppp_minor;    /* PPPD device minor number         */
+  int			 ppp_slot;     /* PPPD device slot number          */
   int                    pre_device;   /* Preselected isdn-device          */
   int                    pre_channel;  /* Preselected isdn-channel         */
   int                    exclusive;    /* If non-zero idx to reserved chan.*/
@@ -549,6 +552,7 @@
   unsigned int maxcid;
   isdn_net_local *lp;
   int unit; 
+  int minor;
   long last_link_seqno;
   long mp_seqno;
   long range;
diff -u --recursive --new-file v2.0.15/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.0.15/linux/include/linux/sched.h	Thu Aug 29 19:15:14 1996
+++ linux/include/linux/sched.h	Sat Aug 31 20:09:22 1996
@@ -401,12 +401,10 @@
 extern inline void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 {
 	struct wait_queue *head = *p;
-	struct wait_queue *next = wait;
+	struct wait_queue *next = WAIT_QUEUE_HEAD(p);
 
-	if (head) {
-		next = head->next;
-		p = &head->next;
-	}
+	if (head)
+		next = head;
 	*p = wait;
 	wait->next = next;
 }
@@ -424,22 +422,15 @@
 extern inline void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
 {
 	struct wait_queue * next = wait->next;
+	struct wait_queue * head = next;
 
-	if (wait == next) {
-		*p = NULL;
-	} else {
-		struct wait_queue *head = *p;
-		if (head == wait)
-			*p = next;
-		for (;;) {
-			struct wait_queue *nextlist = head->next;
-			if (nextlist == wait)
-				break;
-			head = nextlist;
-		}
-		head->next = next;
+	for (;;) {
+		struct wait_queue * nextlist = head->next;
+		if (nextlist == wait)
+			break;
+		head = nextlist;
 	}
-	wait->next = NULL;
+	head->next = next;
 }
 
 extern inline void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)
diff -u --recursive --new-file v2.0.15/linux/include/linux/soundcard.h linux/include/linux/soundcard.h
--- v2.0.15/linux/include/linux/soundcard.h	Sun Jun 30 12:25:28 1996
+++ linux/include/linux/soundcard.h	Sat Aug 31 19:39:10 1996
@@ -742,15 +742,13 @@
 /* Note!	Number 31 cannot be used since the sign bit is reserved */
 
 
-#ifdef NO_LONGER_AVAILABLE
 /*
- * The following unsupported macros will be removed from the API in near
- * future.
+ * The following unsupported macros are no longer functional.
+ * Use SOUND_MIXER_PRIVATE# macros in future.
  */
-#define SOUND_MIXER_ENHANCE	29	/* Enhanced stereo (0, 40, 60 or 80) */
-#define SOUND_MIXER_MUTE	28	/* 0 or 1 */
-#define SOUND_MIXER_LOUD	30	/* 0 or 1 */
-#endif
+#define SOUND_MIXER_ENHANCE	31
+#define SOUND_MIXER_MUTE	31
+#define SOUND_MIXER_LOUD	31
 
 
 #define SOUND_DEVICE_LABELS	{"Vol  ", "Bass ", "Trebl", "Synth", "Pcm  ", "Spkr ", "Line ", \
@@ -790,11 +788,10 @@
 #define SOUND_MASK_LINE2	(1 << SOUND_MIXER_LINE2)
 #define SOUND_MASK_LINE3	(1 << SOUND_MIXER_LINE3)
 
-#ifdef NO_LONGER_AVAILABLE
+/* Obsolete macros */
 #define SOUND_MASK_MUTE		(1 << SOUND_MIXER_MUTE)
 #define SOUND_MASK_ENHANCE	(1 << SOUND_MIXER_ENHANCE)
 #define SOUND_MASK_LOUD		(1 << SOUND_MIXER_LOUD)
-#endif
 
 #define MIXER_READ(dev)		_IOR('M', dev, int)
 #define SOUND_MIXER_READ_VOLUME		MIXER_READ(SOUND_MIXER_VOLUME)
@@ -814,11 +811,11 @@
 #define SOUND_MIXER_READ_LINE1		MIXER_READ(SOUND_MIXER_LINE1)
 #define SOUND_MIXER_READ_LINE2		MIXER_READ(SOUND_MIXER_LINE2)
 #define SOUND_MIXER_READ_LINE3		MIXER_READ(SOUND_MIXER_LINE3)
-#ifdef NO_LONGER_AVAILABLE
+
+/* Obsolete macros */
 #define SOUND_MIXER_READ_MUTE		MIXER_READ(SOUND_MIXER_MUTE)
 #define SOUND_MIXER_READ_ENHANCE	MIXER_READ(SOUND_MIXER_ENHANCE)
 #define SOUND_MIXER_READ_LOUD		MIXER_READ(SOUND_MIXER_LOUD)
-#endif
 
 #define SOUND_MIXER_READ_RECSRC		MIXER_READ(SOUND_MIXER_RECSRC)
 #define SOUND_MIXER_READ_DEVMASK	MIXER_READ(SOUND_MIXER_DEVMASK)
@@ -844,11 +841,11 @@
 #define SOUND_MIXER_WRITE_LINE1		MIXER_WRITE(SOUND_MIXER_LINE1)
 #define SOUND_MIXER_WRITE_LINE2		MIXER_WRITE(SOUND_MIXER_LINE2)
 #define SOUND_MIXER_WRITE_LINE3		MIXER_WRITE(SOUND_MIXER_LINE3)
-#ifdef NO_LONGER_AVAILABLE
+
+/* Obsolete macros */
 #define SOUND_MIXER_WRITE_MUTE		MIXER_WRITE(SOUND_MIXER_MUTE)
 #define SOUND_MIXER_WRITE_ENHANCE	MIXER_WRITE(SOUND_MIXER_ENHANCE)
 #define SOUND_MIXER_WRITE_LOUD		MIXER_WRITE(SOUND_MIXER_LOUD)
-#endif
 
 #define SOUND_MIXER_WRITE_RECSRC	MIXER_WRITE(SOUND_MIXER_RECSRC)
 
diff -u --recursive --new-file v2.0.15/linux/include/linux/wait.h linux/include/linux/wait.h
--- v2.0.15/linux/include/linux/wait.h	Tue Jul 19 13:10:15 1994
+++ linux/include/linux/wait.h	Sat Aug 31 16:38:17 1996
@@ -13,6 +13,19 @@
 	struct wait_queue * next;
 };
 
+#define WAIT_QUEUE_HEAD(x) ((struct wait_queue *)((x)-1))
+
+static inline void init_waitqueue(struct wait_queue **q)
+{
+	*q = WAIT_QUEUE_HEAD(q);
+}
+
+static inline int waitqueue_active(struct wait_queue **q)
+{
+	struct wait_queue *head = *q;
+	return head && head != WAIT_QUEUE_HEAD(q);
+}
+
 struct semaphore {
 	int count;
 	struct wait_queue * wait;
diff -u --recursive --new-file v2.0.15/linux/init/main.c linux/init/main.c
--- v2.0.15/linux/init/main.c	Mon May 20 20:33:57 1996
+++ linux/init/main.c	Sat Aug 31 20:52:44 1996
@@ -94,6 +94,7 @@
 extern void fdomain_setup(char *str, int *ints);
 extern void in2000_setup(char *str, int *ints);
 extern void NCR53c406a_setup(char *str, int *ints);
+extern void wd7000_setup(char *str, int *ints);
 extern void ppa_setup(char *str, int *ints);
 extern void scsi_luns_setup(char *str, int *ints);
 extern void sound_setup(char *str, int *ints);
@@ -329,6 +330,9 @@
 #endif
 #ifdef CONFIG_SCSI_IN2000
 	{ "in2000=", in2000_setup},
+#endif
+#ifdef CONFIG_SCSI_7000FASST
+	{ "wd7000=", wd7000_setup},
 #endif
 #ifdef CONFIG_SCSI_PPA
         { "ppa=", ppa_setup },
diff -u --recursive --new-file v2.0.15/linux/ipc/msg.c linux/ipc/msg.c
--- v2.0.15/linux/ipc/msg.c	Wed Jul 17 15:10:03 1996
+++ linux/ipc/msg.c	Sat Aug 31 16:49:04 1996
@@ -193,8 +193,7 @@
 	msq->msg_lspid = current->pid;
 	msq->msg_stime = CURRENT_TIME;
 	restore_flags(flags);
-	if (msq->rwait)
-		wake_up (&msq->rwait);
+	wake_up (&msq->rwait);
 	return 0;
 }
 
@@ -350,8 +349,7 @@
 			msghdrs--; 
 			msq->msg_cbytes -= nmsg->msg_ts;
 			restore_flags(flags);
-			if (msq->wwait)
-				wake_up (&msq->wwait);
+			wake_up (&msq->wwait);
 			/*
 			 * Calls from kernel level (IPC_KERNELD set)
 			 * wants the message copied to kernel space!
@@ -438,8 +436,7 @@
 	msq = (struct msqid_ds *) kmalloc (sizeof (*msq), GFP_KERNEL);
 	if (!msq) {
 		msgque[id] = (struct msqid_ds *) IPC_UNUSED;
-		if (msg_lock)
-			wake_up (&msg_lock);
+		wake_up (&msg_lock);
 		return -ENOMEM;
 	}
 	ipcp = &msq->msg_perm;
@@ -459,8 +456,7 @@
 		max_msqid = id;
 	msgque[id] = msq;
 	used_queues++;
-	if (msg_lock)
-		wake_up (&msg_lock);
+	wake_up (&msg_lock);
 	return (unsigned int) msq->msg_perm.seq * MSGMNI + id;
 }
 
@@ -525,11 +521,9 @@
 		while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED));
 	msgque[id] = (struct msqid_ds *) IPC_UNUSED;
 	used_queues--;
-	while (msq->rwait || msq->wwait) {
-		if (msq->rwait)
-			wake_up (&msq->rwait); 
-		if (msq->wwait)
-			wake_up (&msq->wwait);
+	while (waitqueue_active(&msq->rwait) || waitqueue_active(&msq->wwait)) {
+		wake_up (&msq->rwait); 
+		wake_up (&msq->wwait);
 		schedule(); 
 	}
 	for (msgp = msq->msg_first; msgp; msgp = msgh ) {
diff -u --recursive --new-file v2.0.15/linux/ipc/sem.c linux/ipc/sem.c
--- v2.0.15/linux/ipc/sem.c	Fri Jun 16 20:03:03 1995
+++ linux/ipc/sem.c	Sat Aug 31 16:49:47 1996
@@ -103,8 +103,7 @@
 	if (!sma) {
 		semary[id] = (struct semid_ds *) IPC_UNUSED;
 		used_sems -= nsems;
-		if (sem_lock)
-			wake_up (&sem_lock);
+		wake_up (&sem_lock);
 		return -ENOMEM;
 	}
 	memset (sma, 0, size);
@@ -124,8 +123,7 @@
 		max_semid = id;
 	used_semids++;
 	semary[id] = sma;
-	if (sem_lock)
-		wake_up (&sem_lock);
+	wake_up (&sem_lock);
 	return (unsigned int) sma->sem_perm.seq * SEMMNI + id;
 }
 
diff -u --recursive --new-file v2.0.15/linux/ipc/shm.c linux/ipc/shm.c
--- v2.0.15/linux/ipc/shm.c	Tue Jul 23 10:26:53 1996
+++ linux/ipc/shm.c	Sat Aug 31 16:50:16 1996
@@ -92,16 +92,14 @@
 	shp = (struct shmid_ds *) kmalloc (sizeof (*shp), GFP_KERNEL);
 	if (!shp) {
 		shm_segs[id] = (struct shmid_ds *) IPC_UNUSED;
-		if (shm_lock)
-			wake_up (&shm_lock);
+		wake_up (&shm_lock);
 		return -ENOMEM;
 	}
 
 	shp->shm_pages = (ulong *) kmalloc (numpages*sizeof(ulong),GFP_KERNEL);
 	if (!shp->shm_pages) {
 		shm_segs[id] = (struct shmid_ds *) IPC_UNUSED;
-		if (shm_lock)
-			wake_up (&shm_lock);
+		wake_up (&shm_lock);
 		kfree(shp);
 		return -ENOMEM;
 	}
@@ -125,8 +123,7 @@
 		max_shmid = id;
 	shm_segs[id] = shp;
 	used_segs++;
-	if (shm_lock)
-		wake_up (&shm_lock);
+	wake_up (&shm_lock);
 	return (unsigned int) shp->shm_perm.seq * SHMMNI + id;
 }
 
diff -u --recursive --new-file v2.0.15/linux/kernel/fork.c linux/kernel/fork.c
--- v2.0.15/linux/kernel/fork.c	Thu Jul  4 20:09:41 1996
+++ linux/kernel/fork.c	Thu Aug 29 19:07:37 1996
@@ -247,6 +247,7 @@
 	p->prev_run = NULL;
 	p->p_pptr = p->p_opptr = current;
 	p->p_cptr = NULL;
+	init_waitqueue(&p->wait_chldexit);
 	p->signal = 0;
 	p->it_real_value = p->it_virt_value = p->it_prof_value = 0;
 	p->it_real_incr = p->it_virt_incr = p->it_prof_incr = 0;
diff -u --recursive --new-file v2.0.15/linux/kernel/sched.c linux/kernel/sched.c
--- v2.0.15/linux/kernel/sched.c	Thu Aug 29 19:15:15 1996
+++ linux/kernel/sched.c	Thu Aug 29 19:07:37 1996
@@ -431,51 +431,55 @@
  */
 void wake_up(struct wait_queue **q)
 {
-	struct wait_queue *tmp;
-	struct task_struct * p;
+	struct wait_queue *next;
+	struct wait_queue *head;
 
-	if (!q || !(tmp = *q))
+	if (!q || !(next = *q))
 		return;
-	do {
-		if ((p = tmp->task) != NULL) {
+	head = WAIT_QUEUE_HEAD(q);
+	while (next != head) {
+		struct task_struct *p = next->task;
+		next = next->next;
+		if (p != NULL) {
 			if ((p->state == TASK_UNINTERRUPTIBLE) ||
 			    (p->state == TASK_INTERRUPTIBLE))
 				wake_up_process(p);
 		}
-		if (!tmp->next) {
-			printk("wait_queue is bad (eip = %p)\n",
-				__builtin_return_address(0));
-			printk("        q = %p\n",q);
-			printk("       *q = %p\n",*q);
-			printk("      tmp = %p\n",tmp);
-			break;
-		}
-		tmp = tmp->next;
-	} while (tmp != *q);
+		if (!next)
+			goto bad;
+	}
+	return;
+bad:
+	printk("wait_queue is bad (eip = %p)\n",
+		__builtin_return_address(0));
+	printk("        q = %p\n",q);
+	printk("       *q = %p\n",*q);
 }
 
 void wake_up_interruptible(struct wait_queue **q)
 {
-	struct wait_queue *tmp;
-	struct task_struct * p;
+	struct wait_queue *next;
+	struct wait_queue *head;
 
-	if (!q || !(tmp = *q))
+	if (!q || !(next = *q))
 		return;
-	do {
-		if ((p = tmp->task) != NULL) {
+	head = WAIT_QUEUE_HEAD(q);
+	while (next != head) {
+		struct task_struct *p = next->task;
+		next = next->next;
+		if (p != NULL) {
 			if (p->state == TASK_INTERRUPTIBLE)
 				wake_up_process(p);
 		}
-		if (!tmp->next) {
-			printk("wait_queue is bad (eip = %p)\n",
-				__builtin_return_address(0));
-			printk("        q = %p\n",q);
-			printk("       *q = %p\n",*q);
-			printk("      tmp = %p\n",tmp);
-			break;
-		}
-		tmp = tmp->next;
-	} while (tmp != *q);
+		if (!next)
+			goto bad;
+	}
+	return;
+bad:
+	printk("wait_queue is bad (eip = %p)\n",
+		__builtin_return_address(0));
+	printk("        q = %p\n",q);
+	printk("       *q = %p\n",*q);
 }
 
 void __down(struct semaphore * sem)
diff -u --recursive --new-file v2.0.15/linux/net/core/net_alias.c linux/net/core/net_alias.c
--- v2.0.15/linux/net/core/net_alias.c	Sat May 18 20:16:23 1996
+++ linux/net/core/net_alias.c	Sat Aug 31 19:39:10 1996
@@ -1298,6 +1298,7 @@
    */
   
 #ifndef ALIAS_USER_LAND_DEBUG
+#ifdef CONFIG_PROC_FS
   proc_net_register(&(struct proc_dir_entry) {
     PROC_NET_ALIAS_TYPES, 11, "alias_types",
     S_IFREG | S_IRUGO, 1, 0, 0,
@@ -1310,6 +1311,7 @@
     0, &proc_net_inode_operations,
     net_alias_getinfo
   });
+#endif
 #endif
   
 }
diff -u --recursive --new-file v2.0.15/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.0.15/linux/net/ipv4/tcp_output.c	Sat Aug 10 10:03:16 1996
+++ linux/net/ipv4/tcp_output.c	Sun Aug 25 17:59:16 1996
@@ -966,8 +966,10 @@
 		sock_wfree(sk, buff);
 		return;
 	}
+#if 0	/* why does this result in problems? */
 #ifndef CONFIG_NO_PATH_MTU_DISCOVERY
 	buff->ip_hdr->frag_off |= htons(IP_DF);
+#endif
 #endif
 
 	t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
