Subject: patches you might be interested in
To: None <port-i386@netbsd.org>
From: T. William Wells <bill@twwells.com>
List: port-i386
Date: 09/19/1994 01:48:20
I finished porting my serial driver and I figured this was a good time to
post the patches that I've made to my copy of NetBSD. These are based,
roughly, on a set of sources from the first or second week of August.

What's in here?

      o Configuration changes for my serial driver.

	These let me bring up my serial driver. At the moment, I would call it
	"pre-beta". It works well; however, I haven't updated the docs from
	the pre-NetBSD days, so they're out of date. Also, I haven't verified
	any of the support programs that go with the serial driver. On the
	other hand, this driver supports my PPP link at 115200 and I haven't
	managed to get it to overflow the 16550A's FIFO yet....

      o An implementation of fast interrupts sufficient to make my driver
	happy. The word for this is "quick and dirty". NB: my driver doesn't
	*require* fast interrupts; however, without them it's no better at
	grabbing data off the UARTs than the com driver. On the other hand, it
	is a bidirectional driver, and designed that way from the start, and
	is just plain better in a host of ways that you'd have to read the
	documentation to check out.

      o The current PPP implementation does not do priority queuing correctly;
	I put in the fix for that.

      o Both SLIP and PPP will bomb if t_oproc is zeroed. The previous
	version of my sio driver didn't do this (instead, using a dummy
	routine); however, I decided that, as these were a bug (try doing
	SLIP or PPP over a pty), it was better to fix the bug and then take
	advantage of the fix in my driver.

Not included in this set of patches, because I haven't actually made the
patch, is a fix for a problem that occured in FreeBSD. The problem was that if
you changed the controlling terminal when you already had one, you lost a
vnode. The routine is vn_ioctl, and the code is:

	case VFIFO:
	case VCHR:
	case VBLK:
		error = VOP_IOCTL(vp, com, data, fp->f_flag, p->p_ucred, p);
		if (error == 0 && com == TIOCSCTTY) {
			p->p_session->s_ttyvp = vp;
			VREF(vp);
		}
		return (error);
	}

The fix is to change the if as follows:

		if (error == 0 && com == TIOCSCTTY
		    && (p->p_session->s_ttyvp != vp))

As I said, my serial driver is pre-beta. If someone desperately needs a
working serial driver, I suppose I could send mine out, but I'd prefer to wait
until it is properly integrated into NetBSD, meaning something more than
hackery for fast interrupts, its configuration and ioctl numbers being made
standard, and the documentation brought up to date, before handing it out.

Following are the patches. NB: my editor loses on spacing, so don't apply
these patches blindly, unless you don't care about the appearance afterwards.

	@@@@@ sio configuration change @@@@@

+ diff -bu sys/arch/i386/conf/files.i386.base sys/arch/i386/conf/files.i386
--- sys/arch/i386/conf/files.i386.base  Sat Jul  2 06:52:11 1994
+++ sys/arch/i386/conf/files.i386       Thu Sep 15 08:13:54 1994
@@ -54,6 +54,7 @@
 arch/i386/isa/pms.c            optional pms device-driver requires isa
 arch/i386/isa/sb.c             optional sb device-driver requires isa
 arch/i386/isa/seagate.c                optional sea requires isa scsi
+arch/i386/isa/sio/sio.c         optional sio device-driver requires isa
 arch/i386/isa/spkr.c           optional speaker device-driver requires isa
 arch/i386/isa/ultra14f.c       optional uha requires isa scsi
 arch/i386/isa/wd.c             optional wd device-driver requires isa

	@@@@@ sio configuration change @@@@@

+ diff -bu sys/arch/i386/i386/conf.c.base sys/arch/i386/i386/conf.c
--- sys/arch/i386/i386/conf.c.base      Wed Jun 15 06:24:23 1994
+++ sys/arch/i386/i386/conf.c   Wed Sep 14 17:29:09 1994
@@ -173,6 +173,13 @@
	(dev_type_reset((*))) nullop, dev_tty_init(c,n), ttselect, \
	(dev_type_mmap((*))) enodev, 0 }

+/* open, close, read, write, ioctl, stop, tty, select */
+#define cdev_sio_init(c,n) { \
+       dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
+       dev_init(c,n,write), dev_init(c,n,ioctl), dev_init(c,n,stop), \
+       (dev_type_reset((*))) nullop, dev_tty_init(c,n), dev_init(c,n,select), \
+       (dev_type_mmap((*))) enodev, 0 }
+
 /* open, close, read, ioctl, select */
 #define        cdev_mouse_init(c,n) { \
	dev_init(c,n,open), dev_init(c,n,close), dev_init(c,n,read), \
@@ -350,12 +357,14 @@
 #include "mms.h"
 #include "lms.h"
 #include "pms.h"
+#include "sio.h"

 cdev_decl(com);
 cdev_decl(cy);
 cdev_decl(mms);
 cdev_decl(lms);
 cdev_decl(pms);
+cdev_decl(sio);

 struct cdevsw  cdevsw[] =
 {
@@ -404,6 +413,7 @@
	cdev_tun_init(NTUN,tun),        /* 40: network tunnel */
	cdev_disk_init(NVN,vn),         /* 41: vnode disk driver */
	cdev_audio_init(NSB,audio),     /* 42: generic audio I/O */
+       cdev_sio_init(NSIO,sio),        /* 43: serial port */
 };
 int    nchrdev = sizeof(cdevsw) / sizeof(cdevsw[0]);

@@ -554,6 +564,9 @@
 #if NCOM > 0
 int comcnprobe(), comcninit(), comcngetc(), comcnputc();
 #endif
+#if NSIO > 0
+int siocnprobe(), siocninit(), siocngetc(), siocnputc();
+#endif

 struct consdev constab[] = {
 #if NPC > 0 || NVT > 0
@@ -561,6 +574,9 @@
 #endif
 #if NCOM > 0
	{ comcnprobe,   comcninit,      comcngetc,      comcnputc },
+#endif
+#if NSIO > 0
+       { siocnprobe,   siocninit,      siocngetc,      siocnputc },
 #endif
	{ 0 },
 };

	@@@@@ twiddly improvement, to shut up cc -Wall @@@@@

+ diff -bu sys/arch/i386/include/psl.h.base sys/arch/i386/include/psl.h
--- sys/arch/i386/include/psl.h.base    Thu May  5 07:10:50 1994
+++ sys/arch/i386/include/psl.h Sat Sep 17 11:30:04 1994
@@ -108,6 +108,8 @@
 #define        splnet()        splsoftnet()
 SPL(softtty, cpl |= SIR_TTYMASK)

+extern void spllower(void);
+
 static __inline void
 spl0()
 {

	@@@@@ fast interrupt change @@@@@

+ diff -bu sys/arch/i386/isa/intr.c.base sys/arch/i386/isa/intr.c
--- sys/arch/i386/isa/intr.c.base       Fri May  6 06:14:39 1994
+++ sys/arch/i386/isa/intr.c    Sat Sep 17 09:05:48 1994
@@ -148,9 +148,9 @@
	}
 }

-int fastvec;
 int intrmask[ICU_LEN], intrlevel[ICU_LEN];
 struct intrhand *intrhand[ICU_LEN];
+struct intrhand *fasthand[ICU_LEN];

 /*
  * Recalculate the interrupt masks from scratch.
@@ -170,6 +170,9 @@
		for (q = intrhand[irq]; q; q = q->ih_next)
			if (q->ih_level != IPL_NONE)
				levels |= 1 << q->ih_level;
+               for (q = fasthand[irq]; q; q = q->ih_next)
+                       if (q->ih_level != IPL_NONE)
+                               levels |= 1 << q->ih_level;
		intrlevel[irq] = levels;
	}

@@ -196,6 +199,9 @@
		for (q = intrhand[irq]; q; q = q->ih_next)
			if (q->ih_level != IPL_NONE)
				irqs |= imask[q->ih_level];
+               for (q = fasthand[irq]; q; q = q->ih_next)
+                       if (q->ih_level != IPL_NONE)
+                               irqs |= imask[q->ih_level];
		intrmask[irq] = irqs;
	}

@@ -205,6 +211,8 @@
		for (irq = 0; irq < ICU_LEN; irq++)
			if (intrhand[irq])
				irqs |= 1 << irq;
+                       if (fasthand[irq])
+                               irqs |= 1 << irq;
		if (irqs >= 0x100) /* any IRQs >= 8 in use */
			irqs |= IRQ_SLAVE;
		imen = ~irqs;
@@ -236,8 +244,6 @@

	if (irq < 0 || irq > ICU_LEN)
		panic("intr_establish: bogus irq");
-       if (fastvec & mask)
-               panic("intr_establish: irq is already fast vector");

	/*
	 * Figure out where to put the handler.
@@ -280,8 +286,6 @@

	if (irq < 0 || irq > ICU_LEN)
		panic("intr_disestablish: bogus irq");
-       if (fastvec & mask)
-               fastvec &= ~mask;

	/*
	 * Remove the handler from the chain.
@@ -294,5 +298,51 @@
	else
		panic("intr_disestablish: handler not registered");

+       intr_calculatemasks();
+}
+
+
+void
+intr_fast_establish(mask, ih)
+       int mask;
+       struct intrhand *ih;
+{
+       int irq;
+
+       irq = ffs(mask) - 1;
+       if (irq < 0 || irq > ICU_LEN) {
+               panic("intr_fast_establish: bogus irq");
+       }
+       if (fasthand[irq]) {
+               panic("intr_fast_establish: fast handler already installed");
+       }
+       ih->ih_count = 0;
+       ih->ih_next = NULL;
+       fasthand[irq] = ih;
+       disable_intr();
+       setidt(ICU_OFFSET + irq, IDTVEC(fast)[irq],  SDT_SYS386IGT, SEL_KPL);
+       enable_intr();
+       intr_calculatemasks();
+}
+
+void
+intr_fast_disestablish(mask, ih)
+       int mask;
+       struct intrhand *ih;
+{
+       int irq;
+       struct intrhand **p, *q;
+
+       irq = ffs(mask) - 1;
+       if (irq < 0 || irq > ICU_LEN) {
+               panic("intr_fast_disestablish: bogus irq");
+       }
+       if (fasthand[irq] != ih) {
+               panic("intr_fast_disestablish: handler not registered");
+       }
+       disable_intr();
+       fasthand[irq] = 0;
+       setidt(ICU_OFFSET + irq, IDTVEC(intr)[irq],  SDT_SYS386IGT, SEL_KPL);
+       enable_intr();
	intr_calculatemasks();
 }

	@@@@@ fast interrupt change @@@@@

+ diff -bu sys/arch/i386/isa/isavar.h.base sys/arch/i386/isa/isavar.h
--- sys/arch/i386/isa/isavar.h.base     Sat Jul 30 14:54:46 1994
+++ sys/arch/i386/isa/isavar.h  Sat Sep 17 11:25:05 1994
@@ -93,6 +93,9 @@
 void intr_disestablish __P((int intr, struct intrhand *));
 void isa_establish __P((struct isadev *, struct device *));

+void intr_fast_establish __P((int intr, struct intrhand *));
+void intr_fast_disestablish __P((int intr, struct intrhand *));
+
 /*
  * software conventions
  */

	@@@@@ fast interrupt change @@@@@

+ diff -bu sys/arch/i386/isa/vector.s.base sys/arch/i386/isa/vector.s
--- sys/arch/i386/isa/vector.s.base     Mon May 23 06:32:29 1994
+++ sys/arch/i386/isa/vector.s  Sun Sep 18 18:53:03 1994
@@ -133,62 +133,6 @@
	INTRFASTEXIT

 /*
- * Fast vectors.
- *
- * Like a normal vector, but run with all interrupts off.  The handler is
- * expected to be as fast as possible, and is expected to not change the
- * interrupt flag.  We pass an argument in like normal vectors, but we assume
- * that a pointer to the frame is never required.  There can be only one
- * handler on a fast vector.
- *
- * XXX
- * Note that we assume fast vectors don't do anything that would cause an AST
- * or softintr; if so, it will be deferred until the next clock tick (or
- * possibly sooner).
- */
-#define        FAST(irq_num, icu, enable_icus) \
-IDTVEC(fast/**/irq_num)                                                        ;\
-       pushl   %eax                    /* save call-used registers */  ;\
-       pushl   %ecx                                                    ;\
-       pushl   %edx                                                    ;\
-       pushl   %ds                                                     ;\
-       pushl   %es                                                     ;\
-       movl    $KDSEL,%eax                                             ;\
-       movl    %ax,%ds                                                 ;\
-       movl    %ax,%es                                                 ;\
-       /* have to do this here because %eax is lost on call */         ;\
-       movl    _intrhand + (irq_num) * 4,%eax                          ;\
-       incl    IH_COUNT(%eax)                                          ;\
-       pushl   IH_ARG(%eax)                                            ;\
-       call    IH_FUN(%eax)                                            ;\
-       enable_icus(irq_num)                                            ;\
-       addl    $4,%esp                                                 ;\
-       incl    _cnt+V_INTR             /* statistical info */          ;\
-       popl    %es                                                     ;\
-       popl    %ds                                                     ;\
-       popl    %edx                                                    ;\
-       popl    %ecx                                                    ;\
-       popl    %eax                                                    ;\
-       iret
-
-FAST(0, IO_ICU1, ENABLE_ICU1)
-FAST(1, IO_ICU1, ENABLE_ICU1)
-FAST(2, IO_ICU1, ENABLE_ICU1)
-FAST(3, IO_ICU1, ENABLE_ICU1)
-FAST(4, IO_ICU1, ENABLE_ICU1)
-FAST(5, IO_ICU1, ENABLE_ICU1)
-FAST(6, IO_ICU1, ENABLE_ICU1)
-FAST(7, IO_ICU1, ENABLE_ICU1)
-FAST(8, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(9, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(10, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(11, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(12, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(13, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(14, IO_ICU2, ENABLE_ICU1_AND_2)
-FAST(15, IO_ICU2, ENABLE_ICU1_AND_2)
-
-/*
  * Normal vectors.
  *
  * We cdr down the intrhand chain, calling each handler with its appropriate
@@ -209,7 +153,6 @@
	pushl   $0                      /* dummy error code */          ;\
	pushl   $T_ASTFLT               /* trap # for doing ASTs */     ;\
	INTRENTRY                                                       ;\
-       MASK(irq_num, icu)              /* mask it in hardware */       ;\
	enable_icus(irq_num)            /* and allow other intrs */     ;\
	testb   $IRQ_BIT(irq_num),_cpl + IRQ_BYTE(irq_num)              ;\
	jnz     _Xhold/**/irq_num       /* currently masked; hold it */ ;\
@@ -236,8 +179,7 @@
	testl   %ebx,%ebx                                               ;\
	jnz     7b                                                      ;\
	STRAY_TEST                                                      ;\
-5:     UNMASK(irq_num, icu)            /* unmask it in hardware */     ;\
-       INTREXIT                        /* lower spl and do ASTs */     ;\
+5:      INTREXIT                        /* lower spl and do ASTs */     ;\
 IDTVEC(stray/**/irq_num)                                               ;\
	pushl   $irq_num                                                ;\
	call    _isa_strayintr                                          ;\
@@ -245,7 +187,39 @@
	jmp     5b                                                      ;\
 IDTVEC(hold/**/irq_num)                                                        ;\
	orb     $IRQ_BIT(irq_num),_ipending + IRQ_BYTE(irq_num)         ;\
-       INTRFASTEXIT
+       INTRFASTEXIT                                                    ;\
+IDTVEC(fast/**/irq_num)                                                 ;\
+       pushl   %eax                    /* save call-used registers */  ;\
+       pushl   %ecx                                                    ;\
+       pushl   %edx                                                    ;\
+       pushl   %ds                                                     ;\
+       pushl   %es                                                     ;\
+       movl    $KDSEL,%eax                                             ;\
+       movl    %ax,%ds                                                 ;\
+       movl    %ax,%es                                                 ;\
+       movl    _fasthand + (irq_num) * 4,%eax                          ;\
+       incl    IH_COUNT(%eax)                                          ;\
+       pushl   IH_ARG(%eax)                                            ;\
+       call    IH_FUN(%eax)                                            ;\
+       testl   %eax,%eax                                               ;\
+       jnz     6f                                                      ;\
+       enable_icus(irq_num)                                            ;\
+       addl    $4,%esp                                                 ;\
+       incl    _cnt+V_INTR             /* statistical info */          ;\
+       popl    %es                                                     ;\
+       popl    %ds                                                     ;\
+       popl    %edx                                                    ;\
+       popl    %ecx                                                    ;\
+       popl    %eax                                                    ;\
+       iret                                                            ;\
+6:      addl    $4,%esp                                                 ;\
+       incl    _cnt+V_INTR             /* statistical info */          ;\
+       popl    %es                                                     ;\
+       popl    %ds                                                     ;\
+       popl    %edx                                                    ;\
+       popl    %ecx                                                    ;\
+       popl    %eax                                                    ;\
+       jmp     _Xintr/**/irq_num

 #if defined(DEBUG) && defined(notdef)
 #define        STRAY_INITIALIZE \

	@@@@@ priority queuing fix @@@@@
	@@@@@ t_oproc fix @@@@@

+ diff -bu sys/net/if_ppp.c.base sys/net/if_ppp.c
--- sys/net/if_ppp.c.base       Sat Jul 30 14:58:27 1994
+++ sys/net/if_ppp.c    Wed Sep 14 09:39:36 1994
@@ -648,7 +648,7 @@
	 */
	if ((ip = mtod(m0, struct ip *))->ip_p == IPPROTO_TCP) {
	    register int p = ntohl(((int *)ip)[ip->ip_hl]);
-           if (INTERACTIVE(p & 0xffff) || INTERACTIVE(p >> 16))
+           if (INTERACTIVE(ntohs(p & 0xffff)) || INTERACTIVE(ntohs(p >> 16)))
		ifq = &sc->sc_fastq;
	}
	break;
@@ -854,7 +854,9 @@
	return;
     }
     if (sc == NULL || tp != (struct tty *) sc->sc_devp) {
+       if (tp->t_oproc) {
	(*tp->t_oproc)(tp);
+       }
	return;
     }


	@@@@@ t_oproc fix @@@@@

+ diff -bu sys/net/if_sl.c.base sys/net/if_sl.c
--- sys/net/if_sl.c.base        Sat Jul 16 06:37:22 1994
+++ sys/net/if_sl.c     Wed Sep 14 09:35:29 1994
@@ -461,7 +461,9 @@
		 * it would.
		 */
		if (tp->t_outq.c_cc != 0) {
+                       if (tp->t_oproc) {
			(*tp->t_oproc)(tp);
+                       }
			if (tp->t_outq.c_cc > SLIP_HIWAT)
				return;
		}