From owner-p4-projects@FreeBSD.ORG Sun Aug 3 12:55:26 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id E512E106567A; Sun, 3 Aug 2008 12:55:25 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A6FB51065673 for ; Sun, 3 Aug 2008 12:55:25 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 94B9A8FC08 for ; Sun, 3 Aug 2008 12:55:25 +0000 (UTC) (envelope-from ed@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.2/8.14.2) with ESMTP id m73CtPsv025878 for ; Sun, 3 Aug 2008 12:55:25 GMT (envelope-from ed@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m73CtPLP025876 for perforce@freebsd.org; Sun, 3 Aug 2008 12:55:25 GMT (envelope-from ed@FreeBSD.org) Date: Sun, 3 Aug 2008 12:55:25 GMT Message-Id: <200808031255.m73CtPLP025876@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to ed@FreeBSD.org using -f From: Ed Schouten To: Perforce Change Reviews Cc: Subject: PERFORCE change 146518 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Aug 2008 12:55:26 -0000 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 #include #include +#include #include #include #include #include #include -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);