Subject: Re: dialin/dialout crapola
To: None <tech-kern@NetBSD.ORG>
From: Charles M. Hannum <mycroft@mit.edu>
List: tech-kern
Date: 03/21/1998 09:12:07
Just for the sake of completeness, here's a complete set of diffs to
put dialout handling in tty.c, and modify the com driver to use it.
This has not been extensively tested.
Index: dev/ic/com.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/com.c,v
retrieving revision 1.142
diff -c -2 -r1.142 com.c
*** com.c 1998/03/21 04:27:58 1.142
--- com.c 1998/03/21 14:12:33
***************
*** 199,203 ****
#endif /* KGDB */
! #define COMUNIT(x) (minor(x))
int
--- 199,204 ----
#endif /* KGDB */
! #define COMUNIT(x) (minor(x) & 0x7ffff)
! #define COMFLAG(x) (minor(x) >> 19)
int
***************
*** 743,764 ****
splx(s2);
}
!
! /* If we're doing a blocking open... */
! if (!ISSET(flag, O_NONBLOCK))
! /* ...then wait for carrier. */
! while (!ISSET(tp->t_state, TS_CARR_ON) &&
! !ISSET(tp->t_cflag, CLOCAL | MDMBUF)) {
! tp->t_wopen++;
! error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
! ttopen, 0);
! tp->t_wopen--;
! if (error) {
! splx(s);
! goto bad;
! }
! }
!
splx(s);
error = (*linesw[tp->t_line].l_open)(dev, tp);
if (error)
--- 744,754 ----
splx(s2);
}
!
splx(s);
+ error = ttyopen(tp, COMFLAG(dev), ISSET(flag, O_NONBLOCK));
+ if (error)
+ goto bad;
+
error = (*linesw[tp->t_line].l_open)(dev, tp);
if (error)
***************
*** 795,799 ****
ttyclose(tp);
! com_shutdown(sc);
return (0);
--- 785,796 ----
ttyclose(tp);
! if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
! /*
! * Although we got a last close, the device may still be in
! * use; e.g. if this was the dialout node, and there are still
! * processes waiting for carrier on the non-dialout node.
! */
! com_shutdown(sc);
! }
return (0);
Index: kern/tty.c
===================================================================
RCS file: /cvsroot/src/sys/kern/tty.c,v
retrieving revision 1.106
diff -c -2 -r1.106 tty.c
*** tty.c 1998/03/21 04:02:47 1.106
--- tty.c 1998/03/21 14:12:33
***************
*** 171,179 ****
int tty_count;
/*
* Initial open of tty, or (re)entry to standard tty line discipline.
*/
int
! ttyopen(device, tp)
dev_t device;
register struct tty *tp;
--- 171,242 ----
int tty_count;
+ int
+ ttyopen(tp, dialout, nonblock)
+ struct tty *tp;
+ int dialout, nonblock;
+ {
+ int s;
+ int error;
+
+ s = spltty();
+
+ if (dialout) {
+ /*
+ * If the device is already open for non-dialout, fail.
+ * Otherwise, set TS_DIALOUT here so that a dialout open always
+ * has precedence, even if we have to wait for carrier.
+ */
+ if (ISSET(tp->t_state, TS_ISOPEN)) {
+ if (!ISSET(tp->t_state, TS_DIALOUT)) {
+ splx(s);
+ return (EBUSY);
+ }
+ } else
+ SET(tp->t_state, TS_DIALOUT);
+ }
+
+ if (!nonblock) {
+ /*
+ * Wait for carrier. If this is a non-dialout open, also wait
+ * for any dialout processes to close the tty first.
+ */
+ while ((!dialout && ISSET(tp->t_state, TS_DIALOUT)) ||
+ (!ISSET(tp->t_state, TS_CARR_ON) &&
+ !ISSET(tp->t_cflag, CLOCAL | MDMBUF))) {
+ tp->t_wopen++;
+ error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
+ ttopen, 0);
+ tp->t_wopen--;
+ if (error) {
+ /*
+ * If there are no other dialout users, clean
+ * up.
+ */
+ if (dialout && !ISSET(tp->t_state, TS_ISOPEN))
+ CLR(tp->t_state, TS_DIALOUT);
+ splx(s);
+ return (error);
+ }
+ }
+ } else {
+ /*
+ * Don't allow a non-blocking non-dialout open if the device is
+ * already open for dialout.
+ */
+ if (!dialout && ISSET(tp->t_state, TS_DIALOUT)) {
+ splx(s);
+ return (EBUSY);
+ }
+ }
+
+ splx(s);
+ return (0);
+ }
+
/*
* Initial open of tty, or (re)entry to standard tty line discipline.
*/
int
! ttylopen(device, tp)
dev_t device;
register struct tty *tp;
Index: kern/tty_conf.c
===================================================================
RCS file: /cvsroot/src/sys/kern/tty_conf.c,v
retrieving revision 1.20
diff -c -2 -r1.20 tty_conf.c
*** tty_conf.c 1998/03/01 02:22:32 1.20
--- tty_conf.c 1998/03/21 14:12:33
***************
*** 101,105 ****
struct linesw linesw[] =
{
! { ttyopen, ttylclose, ttread, ttwrite, nullioctl,
ttyinput, ttstart, ttymodem }, /* 0- termios */
--- 101,105 ----
struct linesw linesw[] =
{
! { ttylopen, ttylclose, ttread, ttwrite, nullioctl,
ttyinput, ttstart, ttymodem }, /* 0- termios */
***************
*** 108,112 ****
#if defined(COMPAT_43) || defined(COMPAT_FREEBSD)
! { ttyopen, ttylclose, ttread, ttwrite, nullioctl,
ttyinput, ttstart, ttymodem }, /* 2- old NTTYDISC */
#else
--- 108,112 ----
#if defined(COMPAT_43) || defined(COMPAT_FREEBSD)
! { ttylopen, ttylclose, ttread, ttwrite, nullioctl,
ttyinput, ttstart, ttymodem }, /* 2- old NTTYDISC */
#else
Index: sys/tty.h
===================================================================
RCS file: /cvsroot/src/sys/sys/tty.h,v
retrieving revision 1.40
diff -c -2 -r1.40 tty.h
*** tty.h 1998/03/21 04:02:47 1.40
--- tty.h 1998/03/21 14:12:33
***************
*** 145,153 ****
#define TS_BUSY 0x00004 /* Draining output. */
#define TS_CARR_ON 0x00008 /* Carrier is present. */
! #define TS_FLUSH 0x00010 /* Outq has been flushed during DMA. */
! #define TS_ISOPEN 0x00020 /* Open has completed. */
! #define TS_TBLOCK 0x00040 /* Further input blocked. */
! #define TS_TIMEOUT 0x00080 /* Wait for output char processing. */
! #define TS_TTSTOP 0x00100 /* Output paused. */
#define TS_XCLUDE 0x00400 /* Tty requires exclusivity. */
--- 145,154 ----
#define TS_BUSY 0x00004 /* Draining output. */
#define TS_CARR_ON 0x00008 /* Carrier is present. */
! #define TS_DIALOUT 0x00010 /* Tty used for dialout. */
! #define TS_FLUSH 0x00020 /* Outq has been flushed during DMA. */
! #define TS_ISOPEN 0x00040 /* Open has completed. */
! #define TS_TBLOCK 0x00080 /* Further input blocked. */
! #define TS_TIMEOUT 0x00100 /* Wait for output char processing. */
! #define TS_TTSTOP 0x00200 /* Output paused. */
#define TS_XCLUDE 0x00400 /* Tty requires exclusivity. */
***************
*** 238,243 ****
int ttyinput __P((int c, struct tty *tp));
int ttylclose __P((struct tty *tp, int flag));
int ttymodem __P((struct tty *tp, int flag));
! int ttyopen __P((dev_t device, struct tty *tp));
int ttyoutput __P((int c, struct tty *tp));
void ttypend __P((struct tty *tp));
--- 239,245 ----
int ttyinput __P((int c, struct tty *tp));
int ttylclose __P((struct tty *tp, int flag));
+ int ttylopen __P((dev_t device, struct tty *tp));
int ttymodem __P((struct tty *tp, int flag));
! int ttyopen __P((struct tty *tp, int dialout, int nonblock));
int ttyoutput __P((int c, struct tty *tp));
void ttypend __P((struct tty *tp));