Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Aug 2008 12:55:25 GMT
From:      Ed Schouten <ed@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 146518 for review
Message-ID:  <200808031255.m73CtPLP025876@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=146518

Change 146518 by ed@ed_flippo on 2008/08/03 12:54:42

	Very first cut to get nmdm(4) working.
	
	Does not compile, but I'd better check it in to make sure it
	doesn't get lost.

Affected files ...

.. //depot/projects/mpsafetty/sys/dev/nmdm/nmdm.c#2 edit

Differences ...

==== //depot/projects/mpsafetty/sys/dev/nmdm/nmdm.c#2 (text+ko) ====

@@ -48,154 +48,158 @@
 #include <sys/fcntl.h>
 #include <sys/poll.h>
 #include <sys/kernel.h>
+#include <sys/limits.h>
 #include <sys/module.h>
 #include <sys/serial.h>
 #include <sys/signalvar.h>
 #include <sys/malloc.h>
 #include <sys/taskqueue.h>
 
-MALLOC_DEFINE(M_NLMDM, "nullmodem", "nullmodem data structures");
+MALLOC_DEFINE(M_NMDM, "nullmodem", "nullmodem data structures");
 
-static d_close_t	nmdmclose;
-static t_modem_t	nmdmmodem;
-static d_open_t		nmdmopen;
-static t_oproc_t	nmdmoproc;
-static t_param_t	nmdmparam;
-static t_stop_t		nmdmstop;
+static tsw_outwakeup_t	nmdm_outwakeup;
+static tsw_param_t	nmdm_param;
+static tsw_modem_t	nmdm_modem;
 
-static struct cdevsw nmdm_cdevsw = {
-	.d_version =	D_VERSION,
-	.d_open =	nmdmopen,
-	.d_close =	nmdmclose,
-	.d_name =	"nmdn",
-	.d_flags =	D_TTY | D_PSEUDO | D_NEEDGIANT | D_NEEDMINOR,
+static struct ttydevsw nmdm_class = {
+	.tsw_flags	= TF_NOPREFIX,
+	.tsw_outwakeup	= nmdm_outwakeup,
+	.tsw_param	= nmdm_param,
+	.tsw_modem	= nmdm_modem,
 };
 
-#define BUFSIZ 		100		/* Chunk size iomoved to/from user */
-#define NMDM_MAX_NUM	128		/* Artificially limit # devices. */
-#define	PF_STOPPED	0x10		/* user told stopped */
-#define BFLAG		CLONE_FLAG0
+static void nmdm_task_tty(void *, int);
+
+struct nmdmsoftc;
 
-struct softpart {
-	struct tty		*nm_tty;
-	struct cdev 		*dev;
-	int			nm_dcd;
-	struct task		pt_task;
-	struct softpart		*other;
-	struct callout		co;
-	u_long			quota;
-	u_long			accumulator;
-	int			rate;
-	int			credits;
+struct nmdmpart {
+	struct tty		*np_tty;
+	int			 np_dcd;
+	struct task		 np_task;
+	struct nmdmpart		*np_other;
+	struct nmdmsoftc	*np_pair;
+	struct callout		 np_callout;
+	u_long			 np_quota;
+	u_long			 np_accumulator;
+	int			 np_rate;
+	int			 np_credits;
 
 #define QS 8	/* Quota shift */
 };
 
-struct	nm_softc {
-	TAILQ_ENTRY(nm_softc)	pt_list;
-	int			pt_flags;
-	struct softpart 	part1, part2;
-	struct	prison 		*pt_prison;
+struct nmdmsoftc {
+	struct nmdmpart	ns_part1;
+	struct nmdmpart	ns_part2;
+	struct mtx	ns_mtx;
 };
 
-static struct clonedevs *nmdmclones;
-static TAILQ_HEAD(,nm_softc) nmdmhead = TAILQ_HEAD_INITIALIZER(nmdmhead);
+static struct nmdmsoftc *
+nmdm_alloc(unsigned long unit, struct ucred *cr)
+{
+	struct nmdmsoftc *ns;
+	struct tty *tp;
+
+	ns = malloc(sizeof(*ns), M_NMDM, M_WAITOK|M_ZERO);
+	mtx_init(&ns->ns_mtx, "nmdm", NULL, MTX_DEF);
+
+	/* Hook the pairs together */
+	ns->ns_part1.np_pair = ns;
+	ns->ns_part1.np_other = &ns->ns_part2;
+	TASK_INIT(&ns->ns_part1.np_task, 0, nmdm_task_tty, &ns->ns_part1);
+	callout_init(&ns->ns_part1.np_callout, 0);
+
+	ns->ns_part2.np_pair = ns;
+	ns->ns_part2.np_other = &ns->ns_part1;
+	TASK_INIT(&ns->ns_part2.np_task, 0, nmdm_task_tty, &ns->ns_part2);
+	callout_init(&ns->ns_part2.np_callout, 0);
+
+	/* Create device nodes */
+	tp = ns->ns_part1.np_tty = tty_alloc(&nmdm_class, &ns->ns_part1,
+	    &ns->ns_mtx);
+	tty_makedev(tp, cr, "nmdm%luA", unit);
+
+	tp = ns->ns_part2.np_tty = tty_alloc(&nmdm_class, &ns->ns_part2,
+	    &ns->ns_mtx);
+	tty_makedev(tp, cr, "nmdm%luB", unit);
+
+	return (ns);
+}
 
 static void
 nmdm_clone(void *arg, struct ucred *cred, char *name, int nameen,
     struct cdev **dev)
 {
-	int i, unit;
-	char *p;
-	struct cdev *d1, *d2;
+	unsigned long unit;
+	char *end;
+	struct nmdmsoftc *ns;
 
 	if (*dev != NULL)
 		return;
-	if (strcmp(name, "nmdm") == 0) {
-		p = NULL;
-		unit = -1;
-	} else {
-		i = dev_stdclone(name, &p, "nmdm", &unit);
-		if (i == 0)
-			return;
-		if (p[0] != '\0' && p[0] != 'A' && p[0] != 'B')
-			return;
-		else if (p[0] != '\0' && p[1] != '\0')
-			return;
-	}
-	i = clone_create(&nmdmclones, &nmdm_cdevsw, &unit, &d1, 0);
-	if (i) {
-		d1 = make_dev(&nmdm_cdevsw, unit2minor(unit),
-		     0, 0, 0666, "nmdm%dA", unit);
-		if (d1 == NULL)
-			return;
-		d2 = make_dev(&nmdm_cdevsw, unit2minor(unit) | BFLAG,
-		     0, 0, 0666, "nmdm%dB", unit);
-		if (d2 == NULL) {
-			destroy_dev(d1);
-			return;
-		}
-		d2->si_drv2 = d1;
-		d1->si_drv2 = d2;
-		dev_depends(d1, d2);
-		dev_depends(d2, d1);
-		d1->si_flags |= SI_CHEAPCLONE;
-		d2->si_flags |= SI_CHEAPCLONE;
-	}
-	if (p != NULL && p[0] == 'B')
-		*dev = d1->si_drv2;
+	if (strncmp(name, "nmdm", 4) != 0)
+		return;
+
+	/* Device name must be "nmdm%lu%c", where %c is 'A' or 'B' */
+	name += 4;
+	unit = strtoul(name, &end, 10);
+	if (unit == ULONG_MAX || name == end)
+		return;
+	if ((end[0] != 'A' && end[0] != 'B') || end[1] != '\0')
+		return;
+
+	ns = nmdm_alloc(unit, cred);
+
+	if (end[1] == 'A')
+		*dev = ns->ns_part1.np_tty->t_dev;
 	else
-		*dev = d1;
-	dev_ref(*dev);
+		*dev = ns->ns_part2.np_tty->t_dev;
 }
 
 static void
 nmdm_timeout(void *arg)
 {
-	struct softpart *sp;
+	struct nmdmpart *np = arg;
 
-	sp = arg;
-
-	if (sp->rate == 0)
+	if (np->np_rate == 0)
 		return;
 
 	/*
 	 * Do a simple Floyd-Steinberg dither here to avoid FP math.
 	 * Wipe out unused quota from last tick.
 	 */
-	sp->accumulator += sp->credits;
-	sp->quota = sp->accumulator >> QS;
-	sp->accumulator &= ((1 << QS) - 1);
+	np->np_accumulator += np->np_credits;
+	np->np_quota = np->np_accumulator >> QS;
+	np->np_accumulator &= ((1 << QS) - 1);
 
-	taskqueue_enqueue(taskqueue_swi_giant, &sp->pt_task);
-	callout_reset(&sp->co, sp->rate, nmdm_timeout, arg);
+	taskqueue_enqueue(taskqueue_swi, &np->np_task);
+	callout_reset(&np->np_callout, np->np_rate, nmdm_timeout, np);
 }
 
 static void
 nmdm_task_tty(void *arg, int pending __unused)
 {
 	struct tty *tp, *otp;
-	struct softpart *sp;
+	struct nmdmpart *np = tty_softc(tp);
+#if 0
 	int c;
+#endif
 
 	tp = arg;
-	sp = tp->t_sc;
-	otp = sp->other->nm_tty;
+	otp = np->np_other->np_tty;
 	KASSERT(otp != NULL, ("NULL otp in nmdmstart"));
 	KASSERT(otp != tp, ("NULL otp == tp nmdmstart"));
-	if (sp->other->nm_dcd) {
-		if (!(tp->t_state & TS_ISOPEN)) {
-			sp->other->nm_dcd = 0;
-			(void)ttyld_modem(otp, 0);
+	if (np->np_other->np_dcd) {
+		if (!tty_opened(tp)) {
+			np->np_other->np_dcd = 0;
+			(void)ttydisc_modem(otp, 0);
 		}
 	} else {
-		if (tp->t_state & TS_ISOPEN) {
-			sp->other->nm_dcd = 1;
-			(void)ttyld_modem(otp, 1);
+		if (tty_opened(tp)) {
+			np->np_other->np_dcd = 1;
+			(void)ttydisc_modem(otp, 1);
 		}
 	}
-	if (tp->t_state & TS_TTSTOP)
-		return;
+
+#if 0
 	while (tp->t_outq.c_cc != 0) {
 		if (sp->rate && !sp->quota)
 			return;
@@ -208,92 +212,7 @@
 	}
 	if (tp->t_outq.c_cc == 0)
 		ttwwakeup(tp);
-
-}
-
-/*
- * This function creates and initializes a pair of ttys.
- */
-static void
-nmdminit(struct cdev *dev1)
-{
-	struct cdev *dev2;
-	struct nm_softc *pt;
-
-	dev2 = dev1->si_drv2;
-
-	dev1->si_flags &= ~SI_CHEAPCLONE;
-	dev2->si_flags &= ~SI_CHEAPCLONE;
-
-	pt = malloc(sizeof(*pt), M_NLMDM, M_WAITOK | M_ZERO);
-	TAILQ_INSERT_TAIL(&nmdmhead, pt, pt_list);
-
-	dev1->si_drv1 = dev2->si_drv1 = pt;
-
-	pt->part1.dev = dev1;
-	pt->part2.dev = dev2;
-
-	pt->part1.nm_tty = ttyalloc();
-	pt->part1.nm_tty->t_oproc = nmdmoproc;
-	pt->part1.nm_tty->t_stop = nmdmstop;
-	pt->part1.nm_tty->t_modem = nmdmmodem;
-	pt->part1.nm_tty->t_param = nmdmparam;
-	pt->part1.nm_tty->t_dev = dev1;
-	pt->part1.nm_tty->t_sc = &pt->part1;
-	TASK_INIT(&pt->part1.pt_task, 0, nmdm_task_tty, pt->part1.nm_tty);
-	callout_init(&pt->part1.co, 0);
-
-	pt->part2.nm_tty = ttyalloc();
-	pt->part2.nm_tty->t_oproc = nmdmoproc;
-	pt->part2.nm_tty->t_stop = nmdmstop;
-	pt->part2.nm_tty->t_modem = nmdmmodem;
-	pt->part2.nm_tty->t_param = nmdmparam;
-	pt->part2.nm_tty->t_dev = dev2;
-	pt->part2.nm_tty->t_sc = &pt->part2;
-	TASK_INIT(&pt->part2.pt_task, 0, nmdm_task_tty, pt->part2.nm_tty);
-	callout_init(&pt->part2.co, 0);
-
-	pt->part1.other = &pt->part2;
-	pt->part2.other = &pt->part1;
-
-	dev1->si_tty = pt->part1.nm_tty;
-	dev1->si_drv1 = pt;
-
-	dev2->si_tty = pt->part2.nm_tty;
-	dev2->si_drv1 = pt;
-}
-
-/*
- * Device opened from userland
- */
-static	int
-nmdmopen(struct cdev *dev, int flag, int devtype, struct thread *td)
-{
-	struct tty *tp, *tp2;
-	int error;
-	struct nm_softc *pti;
-	struct softpart *sp;
-
-	if (dev->si_drv1 == NULL)
-		nmdminit(dev);
-	pti = dev->si_drv1;
-	if (pti->pt_prison != td->td_ucred->cr_prison)
-		return (EBUSY);
-
-	tp = dev->si_tty;
-	sp = tp->t_sc;
-	tp2 = sp->other->nm_tty;
-
-	if ((tp->t_state & TS_ISOPEN) == 0) {
-		ttyinitmode(tp, 0, 0);
-		ttsetwater(tp); /* XXX ? */
-	} else if (tp->t_state & TS_XCLUDE &&
-	    priv_check(td, PRIV_TTY_EXCLUSIVE)) {
-		return (EBUSY);
-	}
-
-	error = ttyld_open(tp, dev);
-	return (error);
+#endif
 }
 
 static int
@@ -319,16 +238,15 @@
 static int
 nmdmparam(struct tty *tp, struct termios *t)
 {
-	struct softpart *sp;
+	struct nmdmpart *np = tty_softc(tp);
 	struct tty *tp2;
 	int bpc, rate, speed, i;
 
-	sp = tp->t_sc;
-	tp2 = sp->other->nm_tty;
+	tp2 = np->np_other->np_tty;
 
 	if (!((t->c_cflag | tp2->t_cflag) & CDSR_OFLOW)) {
-		sp->rate = 0;
-		sp->other->rate = 0;
+		np->np_rate = 0;
+		np->np_other->np_rate = 0;
 		return (0);
 	}
 
@@ -345,8 +263,8 @@
 		/* Use the slower of our receive and their transmit rate */
 		speed = imin(tp2->t_ospeed, t->c_ispeed);
 		if (speed == 0) {
-			sp->rate = 0;
-			sp->other->rate = 0;
+			np->np_rate = 0;
+			np->np_other->np_rate = 0;
 			return (0);
 		}
 
@@ -359,28 +277,29 @@
 		speed *= rate;
 		speed /= hz;			/* [(char/sec)/tick, scaled */
 
-		sp->credits = speed;
-		sp->rate = rate;
-		callout_reset(&sp->co, rate, nmdm_timeout, sp);
+		np->np_credits = speed;
+		np->np_rate = rate;
+		callout_reset(&np->np_callout, rate, nmdm_timeout, np);
 
 		/*
 		 * swap pointers for second pass so the other end gets
 		 * updated as well.
 		 */
-		sp = sp->other;
+		np = np->np_other;
 		t = &tp2->t_termios;
 		tp2 = tp;
 	}
 	return (0);
 }
 
+#if 0
 static int
 nmdmmodem(struct tty *tp, int sigon, int sigoff)
 {
 	struct softpart *sp;
 	int i;
 
-	sp = tp->t_sc;
+	sp = tty_softc(tp);
 	if (sigon || sigoff) {
 		if (sigon & SER_DTR)
 			sp->other->nm_dcd = 1;
@@ -397,35 +316,15 @@
 		return (i);
 	}
 }
-
-static int
-nmdmclose(struct cdev *dev, int flag, int mode, struct thread *td)
-{
-	struct tty *tp = dev->si_tty;
-	int error;
-
-	error = ttyld_close(tp, flag);
-	(void) tty_close(dev->si_tty);
+#endif
 
-	return (error);
-}
-
 static void
-nmdmoproc(struct tty *tp)
+nmdm_outwakeup(struct tty *tp)
 {
-	struct softpart *pt;
+	struct nmdmpart *np = tty_softc(tp);
 
-	pt = tp->t_sc;
-	taskqueue_enqueue(taskqueue_swi_giant, &pt->pt_task);
-}
-
-static void
-nmdmstop(struct tty *tp, int flush)
-{
-	struct softpart *pt;
-
-	pt = tp->t_sc;
-	taskqueue_enqueue(taskqueue_swi_giant, &pt->pt_task);
+	np = tty_softc(tp);
+	taskqueue_enqueue(taskqueue_swi, &np->np_task);
 }
 
 /*
@@ -435,32 +334,27 @@
 nmdm_modevent(module_t mod, int type, void *data)
 {
 	static eventhandler_tag tag;
-	struct nm_softc *pt, *tpt;
-        int error = 0;
 
         switch(type) {
         case MOD_LOAD: 
-		clone_setup(&nmdmclones);
 		tag = EVENTHANDLER_REGISTER(dev_clone, nmdm_clone, 0, 1000);
 		if (tag == NULL)
 			return (ENOMEM);
 		break;
 
 	case MOD_SHUTDOWN:
-		/* FALLTHROUGH */
+		break;
+
 	case MOD_UNLOAD:
 		EVENTHANDLER_DEREGISTER(dev_clone, tag);
-		TAILQ_FOREACH_SAFE(pt, &nmdmhead, pt_list, tpt) {
-			destroy_dev(pt->part1.dev);
-			TAILQ_REMOVE(&nmdmhead, pt, pt_list);
-			free(pt, M_NLMDM);
-		}
-		clone_cleanup(&nmdmclones);
+		/* XXX: track counter! */
 		break;
+
 	default:
-		error = EOPNOTSUPP;
+		return (EOPNOTSUPP);
 	}
-	return (error);
+
+	return (0);
 }
 
 DEV_MODULE(nmdm, nmdm_modevent, NULL);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200808031255.m73CtPLP025876>