static int nmdmclose(struct dev_close_args *ap) { cdev_t dev = ap->a_head.a_dev; struct tty *tp, *tp2; int err; struct softpart *ourpart, *otherpart; /* * let the other end know that the game is up */ tp = dev->si_tty; lwkt_gettoken(&tp->t_token); GETPARTS(tp, ourpart, otherpart); tp2 = &otherpart->nm_tty; lwkt_gettoken(&tp2->t_token); (void)(*linesw[tp2->t_line].l_modem)(tp2, 0); /* * XXX MDMBUF makes no sense for nmdms but would inhibit the above * l_modem(). CLOCAL makes sense but isn't supported. Special * l_modem()s that ignore carrier drop make no sense for nmdms but * may be in use because other parts of the line discipline make * sense for nmdms. Recover by doing everything that a normal * ttymodem() would have done except for sending a SIGHUP. */ if (tp2->t_state & TS_ISOPEN) { tp2->t_state &= ~(TS_CARR_ON | TS_CONNECTED); tp2->t_state |= TS_ZOMBIE; ttyflush(tp2, FREAD | FWRITE); } err = (*linesw[tp->t_line].l_close)(tp, ap->a_fflag); ourpart->modemsignals &= ~TIOCM_DTR; nmdm_crossover(dev->si_drv1, ourpart, otherpart); nmdmstop(tp, FREAD|FWRITE); ttyclose(tp); lwkt_reltoken(&tp2->t_token); lwkt_reltoken(&tp->t_token); return (err); }
/*ARGSUSED*/ static int nmdmopen(struct dev_open_args *ap) { cdev_t dev = ap->a_head.a_dev; struct tty *tp, *tp2; int error; int minr; #if 0 cdev_t nextdev; #endif struct nm_softc *pti; int is_b; int pair; struct softpart *ourpart, *otherpart; minr = lminor(dev); pair = minr >> 1; is_b = minr & 1; #if 0 /* * XXX: Gross hack for DEVFS: * If we openned this device, ensure we have the * next one too, so people can open it. */ if (pair < 127) { nextdev = makedev(major(dev), (pair+pair) + 1); if (!nextdev->si_drv1) { nmdminit(pair + 1); } } #endif if (!dev->si_drv1) nmdminit(pair); if (!dev->si_drv1) return(ENXIO); lwkt_gettoken(&tty_token); pti = dev->si_drv1; if (is_b) tp = &pti->part2.nm_tty; else tp = &pti->part1.nm_tty; GETPARTS(tp, ourpart, otherpart); tp2 = &otherpart->nm_tty; ourpart->modemsignals |= TIOCM_LE; if ((tp->t_state & TS_ISOPEN) == 0) { ttychars(tp); /* Set up default chars */ tp->t_iflag = TTYDEF_IFLAG; tp->t_oflag = TTYDEF_OFLAG; tp->t_lflag = TTYDEF_LFLAG; tp->t_cflag = TTYDEF_CFLAG; tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; } else if (tp->t_state & TS_XCLUDE && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) { lwkt_reltoken(&tty_token); return (EBUSY); } else if (pti->pt_prison != ap->a_cred->cr_prison) { lwkt_reltoken(&tty_token); return (EBUSY); } /* * If the other side is open we have carrier */ if (tp2->t_state & TS_ISOPEN) { (void)(*linesw[tp->t_line].l_modem)(tp, 1); } /* * And the other side gets carrier as we are now open. */ (void)(*linesw[tp2->t_line].l_modem)(tp2, 1); /* External processing makes no sense here */ tp->t_lflag &= ~EXTPROC; /* * Wait here if we don't have carrier. */ #if 0 while ((tp->t_state & TS_CARR_ON) == 0) { if (flag & FNONBLOCK) break; error = ttysleep(tp, TSA_CARR_ON(tp), PCATCH, "nmdopn", 0); if (error) { lwkt_reltoken(&tty_token); return (error); } } #endif /* * Give the line disciplin a chance to set this end up. */ error = (*linesw[tp->t_line].l_open)(dev, tp); /* * Wake up the other side. * Theoretically not needed. */ ourpart->modemsignals |= TIOCM_DTR; nmdm_crossover(pti, ourpart, otherpart); if (error == 0) wakeup_other(tp, FREAD|FWRITE); /* XXX */ lwkt_reltoken(&tty_token); return (error); }