[comp.os.minix] Generating SIGHUP on loss of carrier, for PC Minix 1.5

jds@cs.umd.edu (James da Silva) (07/01/91)

Archive-name: sighup.shar

I have added support for the generation of SIGHUP on loss of carrier to the
Minix 1.5 tty driver.  I desperately needed this change for operating my
BBS under Minix.  The Mars Hotel (301-277-9408), has been around since
1987, but was running under MS-DOS until last month when I finally upgraded
it to Minix/386.

The tty driver is also missing full handling of DTR.  This requires action
on open/close so would be a bit more involved to add to the 1.5 driver.
Minix 1.6 has more thorough support for device open/close, so it might be
better just to add that to 1.6 instead of mucking any more with 1.5.  This
is still on the TODO list.

I understand that Fred van K. has already done all this for his Advanced
Minix, but I have yet to see his bits on this side of The Pond.

Details of the changes I made are included in the shar file below.  Caveat
Hacker: These changes work for me, but I have not tested them on a wide
range of systems, so approach them with caution.  I would appreciate any
bug reports, constructive comments and/or criticism.  I don't mind flames
either; but if you dish it out, I hope you can take it too.

Jaime
...........................................................................
: domain: jds@cs.umd.edu				     James da Silva
: path:   uunet!mimsy!jds		    Systems Design & Analysis Group


p.s. Please accept my apologies for posting a text-only file to
comp.os.minix.  Next time I will try to post a tarred, featherred,
compressed, encoded and zipped file, or maybe even a raw binary, as has
become fashionable these days. :-)

........ cut here .......
: Run this shell script with "sh" not "csh"
PATH=/bin:/usr/bin:/usr/ucb:/etc:$PATH
export PATH
all=false
if [ x$1 = x-a ]; then
	all=true
fi
echo Extracting CHANGES.SIGHUP
sed 's/^X//' <<'//go.sysin dd *' >CHANGES.SIGHUP
XThe Following changes were made to support the generation of SIGHUP on
Xloss of carrier.
X
XAn ODEVHUP flag was added to the device state word used in rs232.c.  It is
Xset by the interrupt routines and checked by tty.c when it is looking for
Xtty events.  The interrupt routine increments tty_events to let the tty
Xtask know that something is pending, but makes no effort to actually wake
Xup the tty task.  That will be done by the clock task or at the next tty i/o
Xinterrupt.  The placement of the hangup check in the tty event loop insures
Xthat SIGHUP is processed before any more i/o is handled for that device.
X
Xkernel/rs232.c	- added rs_hangup(), which checks the ODEVHUP state for tty.c
X		- added code to modem_int() to set ODEVHUP and inc tty_events.
Xkernel/rs2.x    - asm version of modem_int(); set ODEVHUP and inc tty_events.
Xkernel/tty.c	- added check for hangup to event loop in do_int.
Xmm/signal.c	- add SIGHUP to signals sent to whole process group, like
X		  SIGINT and SIGQUIT.
X
XThese changes were tested under Minix/386 on a 486/25 with an internal
Xmodem card (with an 8250 on it), and on a 386/16 with a NS16450-based
Xserial port card.  I have not tested it under 16-bit Minix, but there
Xshould not be any 32-bit dependencies.
X
XTo apply the patches, (cd kernel; patch <kernel.diffs), then
X(cd mm; patch <mm.diffs).  You get the idea.
X
XPlease send me any fixes, comments or criticisms.
X
XThanks,
XJaime
X...........................................................................
X: domain: jds@cs.umd.edu				     James da Silva
X: path:   uunet!mimsy!jds		    Systems Design & Analysis Group
//go.sysin dd *
if [ `wc -c < CHANGES.SIGHUP` != 1596 ]; then
	made=false
	echo error transmitting CHANGES.SIGHUP --
	echo length should be 1596, not `wc -c < CHANGES.SIGHUP`
else
	made=true
fi
if $made; then
	chmod 644 CHANGES.SIGHUP
	echo -n '	'; ls -ld CHANGES.SIGHUP
fi
echo Extracting kernel.diffs
sed 's/^X//' <<'//go.sysin dd *' >kernel.diffs
X*** 1.5	1991/06/15 15:50:16
X--- tty.c	1991/06/30 11:51:26
X***************
X*** 169,174 ****
X--- 169,178 ----
X    do {
X  	if (++tp >= END_TTY) tp = FIRST_TTY;
X  
X+ 	/* Check for hangup from rs232 devices */
X+ 	if (isrs232(tp) && rs_hangup(tp->tty_line))  
X+ 		sigchar(tp, SIGHUP);
X+ 
X  	/* Transfer any fresh input to TTY's buffer, and test output done. */
X  	remaining = (*tp->tty_devread)(tp->tty_line, &buf, &odone);
X  	if (remaining == 0)
X*** 1.5	1991/06/30 11:52:46
X--- rs232.c	1991/06/30 12:02:35
X***************
X*** 51,56 ****
X--- 51,58 ----
X  
X  /* Modem status bits. */
X  #define MS_CTS               0x10
X+ #define MS_RLSD		     0x80	/* Received Line Signal Detect */
X+ #define MS_DRLSD	     0x08	/* Delta RLSD */
X  
X  /* Input buffer watermarks.
X   * The external device is asked to stop sending when the buffer
X***************
X*** 97,102 ****
X--- 99,114 ----
X  /* Macro to tell if transmitter is ready. */
X  #define txready(rs) (in_byte(rs->line_status_port) & LS_TRANSMITTER_READY)
X  
X+ /* Macro to tell if carrier has dropped.
X+  * The RS232 Carrier Detect (CD) line is usually connected to the 8250
X+  * Received Line Signal Detect pin, reflected by bit MS_RLSD in the Modem
X+  * Status Register.  The MS_DRLSD bit tells if MS_RLSD has just changed state.
X+  * So if MS_DRLSD is set and MS_RLSD cleared, we know that carrier has just
X+  * dropped.
X+  */
X+ #define devhup(rs) (in_byte(rs->modem_status_port) & (MS_RLSD|MS_DRLSD) \
X+ 		    == MS_DRLSD)
X+ 
X  /* Types. */
X  typedef char bool_t;		/* boolean */
X  typedef unsigned port_t;	/* hardware port */
X***************
X*** 114,125 ****
X  
X    unsigned char ostate;		/* combination of flags: */
X  #define ODEVREADY MS_CTS	/* external device hardware ready (CTS) */
X  #define ODONE          1	/* output completed (< output enable bits) */
X  #define OQUEUED     0x20	/* output buffer not empty */
X  #define ORAW           2	/* raw mode for xoff disable (< enab. bits) */
X  #define OSWREADY    0x40	/* external device software ready (no xoff) */
X  #define OWAKEUP        4	/* tty_wakeup() pending (asm code only) */
X! #if (ODEVREADY | 0x63) == 0x63
X  #error				/* bits are not unique */
X  #endif
X    unsigned char oxoff;		/* char to stop output */
X--- 126,139 ----
X  
X    unsigned char ostate;		/* combination of flags: */
X  #define ODEVREADY MS_CTS	/* external device hardware ready (CTS) */
X+ #define ODEVHUP  MS_RLSD	/* external device has dropped carrier */
X  #define ODONE          1	/* output completed (< output enable bits) */
X  #define OQUEUED     0x20	/* output buffer not empty */
X  #define ORAW           2	/* raw mode for xoff disable (< enab. bits) */
X  #define OSWREADY    0x40	/* external device software ready (no xoff) */
X  #define OWAKEUP        4	/* tty_wakeup() pending (asm code only) */
X! #define OSOFTBITS  (ODONE|OQUEUED|ORAW|OSWREADY|OWAKEUP) /* user-defined bits */
X! #if (ODEVREADY | ODEVHUP | OSOFTBITS) == OSOFTBITS  /* a weak sanity check */
X  #error				/* bits are not unique */
X  #endif
X    unsigned char oxoff;		/* char to stop output */
X***************
X*** 171,176 ****
X--- 185,191 ----
X  #endif
X  FORWARD void out_int();
X  FORWARD int rs_config();
X+ FORWARD int rs_hangup();
X  
X  
X  /* High level routines (should only be called by TTY). */
X***************
X*** 484,489 ****
X--- 499,526 ----
X    unlock();
X  }
X  
X+ /*==========================================================================*
X+  *				rs_hangup				    *
X+  *==========================================================================*/
X+ PUBLIC int rs_hangup(minor)
X+ int minor;			/* which rs line */
X+ {
X+ /* Tell TTY whether a hangup has occured, and if so, clear ODEVHUP state. */
X+ 
X+   register struct rs232_s *rs;
X+ 
X+   rs = rs_addr(minor);
X+   if (rs->ostate & ODEVHUP) {
X+   	lock();
X+   	rs->ostate &= ~ODEVHUP;
X+ 	--tty_events;
X+   	unlock();
X+ 	return 1;
X+   }
X+   else
X+ 	return 0;
X+ }
X+ 
X  
X  /* Low level (interrupt) routines. */
X  
X***************
X*** 615,620 ****
X--- 652,661 ----
X   * If the device just became ready, restart output.
X   */
X  
X+   if (devhup(rs)) {
X+ 	rs->ostate |= ODEVHUP;
X+ 	++tty_events;
X+   }
X    if (!devready(rs))
X  	rs->ostate &= ~ODEVREADY;
X    else if (!(rs->ostate & ODEVREADY)) {
X*** 1.5	1991/06/23 21:23:00
X--- rs2.x	1991/06/30 11:55:04
X***************
X*** 68,74 ****
X--- 68,77 ----
X  MC_DTR			=	1
X  MC_OUT2			=	8
X  MS_CTS			=	0x10
X+ MS_RLSD			=	0x80
X+ MS_DRLSD		=	0x08
X  ODEVREADY		=	MS_CTS
X+ ODEVHUP			=	MS_RLSD
X  ODONE			=	1
X  OQUEUED			=	0x20
X  ORAW			=	2
X***************
X*** 272,277 ****
X--- 275,290 ----
X  modemint:
X  	addb	dl,#MODEM_STATUS_OFFSET-INT_ID_OFFSET
X  	in
X+ 
X+ 	testb	al,#MS_RLSD	| hungup = !MS_RLSD && MS_DRLSD
X+ 	jne	m_handshake
X+ 	testb   al,#MS_DRLSD
X+ 	je	m_handshake
X+ 
X+ 	orb	ah,#ODEVHUP
X+ 	inc	_tty_events
X+ 
X+ m_handshake:
X  #if NO_HANDSHAKE
X  	orb	al,#MS_CTS
X  #endif
//go.sysin dd *
if [ `wc -c < kernel.diffs` != 4803 ]; then
	made=false
	echo error transmitting kernel.diffs --
	echo length should be 4803, not `wc -c < kernel.diffs`
else
	made=true
fi
if $made; then
	chmod 644 kernel.diffs
	echo -n '	'; ls -ld kernel.diffs
fi
echo Extracting mm.diffs
sed 's/^X//' <<'//go.sysin dd *' >mm.diffs
X*** 1.5	1991/06/15 17:36:10
X--- signal.c	1991/06/30 11:34:06
X***************
X*** 121,127 ****
X     * and SIGQUIT, use proc_id 0, since multiple processes may have to signaled.
X     */
X    for (i = 0, j = 1; i < _NSIG - 1; i++, j++) {
X! 	id = (j == SIGINT || j == SIGQUIT) ? 0 : proc_id;
X  	if (j == SIGKILL) id = -1;	/* simulate kill -1 9 */
X  	if ( (sig_map >> i) & 1) {
X  		check_sig(id, j, SUPER_USER);
X--- 121,127 ----
X     * and SIGQUIT, use proc_id 0, since multiple processes may have to signaled.
X     */
X    for (i = 0, j = 1; i < _NSIG - 1; i++, j++) {
X! 	id = (j == SIGINT || j == SIGQUIT || j == SIGHUP) ? 0 : proc_id;
X  	if (j == SIGKILL) id = -1;	/* simulate kill -1 9 */
X  	if ( (sig_map >> i) & 1) {
X  		check_sig(id, j, SUPER_USER);
//go.sysin dd *
if [ `wc -c < mm.diffs` != 750 ]; then
	made=false
	echo error transmitting mm.diffs --
	echo length should be 750, not `wc -c < mm.diffs`
else
	made=true
fi
if $made; then
	chmod 644 mm.diffs
	echo -n '	'; ls -ld mm.diffs
fi