From freefall.cdrom.com!owner-freebsd-hackers Sun Aug  7 16:41:33 1994
Return-Path: <owner-freebsd-hackers@freefall.cdrom.com>
Received: from freefall.cdrom.com by tfs.com (smail3.1.28.1) with SMTP
	id m0qXHqJ-0003wNa; Sun, 7 Aug 94 16:41 PDT
Received: (from root@localhost) by freefall.cdrom.com (8.6.8/8.6.6) id QAA16872 for freebsd-hackers-outgoing; Sun, 7 Aug 1994 16:36:08 -0700
Received: from warrane.connect.com.au (warrane.connect.com.au [192.189.54.33]) by freefall.cdrom.com (8.6.8/8.6.6) with SMTP id QAA16866 for <freebsd-hackers@freefall.cdrom.com>; Sun, 7 Aug 1994 16:36:04 -0700
Received: from kralizec.zeta.org.au by warrane.connect.com.au with SMTP id AA05791
  (5.67b8/IDA-1.5 for <freebsd-hackers@freefall.cdrom.com>); Mon, 8 Aug 1994 09:35:48 +1000
Received: (from bde@localhost) by kralizec.zeta.org.au (8.6.9/8.6.9) id JAA27407; Mon, 8 Aug 1994 09:35:20 +1000
Date: Mon, 8 Aug 1994 09:35:20 +1000
From: Bruce Evans <bde@kralizec.zeta.org.au>
Message-Id: <199408072335.JAA27407@kralizec.zeta.org.au>
To: jhay@mikom.csir.co.za
Subject: Re:  COMCONSOLE fixed
Cc: freebsd-hackers@freefall.cdrom.com
Sender: freebsd-hackers-owner@freefall.cdrom.com
Precedence: bulk
Status: RO

> I finaly got the comconsole stuff working with the following patch. It seems
> that during the probes the interrupt gets set and after the splnone() when it
> go into siointr1() it does not know what to do because the interrupt was
> cleared by the console output.

Here is the official fix.

The polled i/o routines for the serial console were causing an
interrupt by turning off the MCR_IENABLE bit and floating the IRQ.  The
interrupt handler checks for all events so it notices ones whose
interrupt is disabled and increments the event counter.  The timeout
routine doesn't handle such events in all cases since they "can't
happen".  When they happen, it loops forever.  It used to handle them
in all cases but the dynamic allocation of com->tp broke the case where
com->tp is not allocated.

Your fix works by not calling the interrupt handler for spurious
interrupts.  The COM_MULTIPORT handler happens to do that naturally,
and I didn't notice the problem the previous time I checked for it
since I have COM_MULTIPORT defined.

My fix avoids the spurious interrupts for the serial console and
handles spurious events in the timeout routine in case there are
other bugs.

Bruce

---
*** src/sysc/i386/isa/sio.c	Thu Jun 16 18:08:26 1994
--- src/sys/i386/isa/sio.c	Mon Aug  8 08:20:34 1994
***************
*** 1305,1310 ****
  			continue;
  		tp = com->tp;
! 		if (tp == NULL)
  			continue;
  
  		/* switch the role of the low-level input buffers */
--- 1305,1329 ----
  			continue;
  		tp = com->tp;
! 		if (tp == NULL) {
! 			/*
! 			 * XXX forget any events related to closed devices
! 			 * (actually never opened devices) so that we don't
! 			 * loop.
! 			 */
! 			disable_intr();
! 			incc = com->iptr - com->ibuf;
! 			com->iptr = com->ibuf;
! 			if (com->state & CS_CHECKMSR) {
! 				incc += LOTS_OF_EVENTS;
! 				com->state &= ~CS_CHECKMSR;
! 			}
! 			com_events -= incc;
! 			enable_intr();
! 			if (incc != 0)
! 				log(LOG_DEBUG,
! 				    "sio%d: %d events for device with no tp\n",
! 				    unit, incc);
  			continue;
+ 		}
  
  		/* switch the role of the low-level input buffers */
***************
*** 1828,1832 ****
  	outb(iobase + com_cfcr, CFCR_8BITS);
  	sp->mcr = inb(iobase + com_mcr);
! 	outb(iobase + com_mcr, MCR_DTR | MCR_RTS);
  }
  
--- 1849,1858 ----
  	outb(iobase + com_cfcr, CFCR_8BITS);
  	sp->mcr = inb(iobase + com_mcr);
! 	/*
! 	 * We don't want interrupts, but must be careful not to "disable"
! 	 * them by clearing the MCR_IENABLE bit, since that might cause
! 	 * an interrupt by floating the IRQ line.
! 	 */
! 	outb(iobase + com_mcr, (sp->mcr & MCR_IENABLE) | MCR_DTR | MCR_RTS);
  }
  
