/* * SCCS id @(#)dc.c 2.1 (Berkeley) 8/5/83 */ #include "dc.h" #if NDC > 0 #include "param.h" #include #include #include #include #include struct tty dc11[NDC]; extern struct dcdevice *DCADDR; /* * Input-side speed and control bit table. * Each DC11 has 4 speeds which correspond to the 4 non-zero entries. * The table index is the same as the speed-selector * number for the DH11. * Attempts to set the speed to a zero entry are ignored. */ short dcrstab[] = { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ DC_7BITS | DC_IE | DC_SPEED0 | DC_DTR, /* 134.5 baud */ DC_8BITS | DC_IE | DC_SPEED1 | DC_DTR, /* 150 baud */ 0, /* 200 baud */ DC_8BITS | DC_IE | DC_SPEED2 | DC_DTR, /* 300 baud */ 0, /* 600 baud */ DC_8BITS | DC_IE | DC_SPEED3 | DC_DTR, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0 /* X1 */ }; /* * Transmitter speed and control bit table */ short dctstab[] = { 0, /* 0 baud */ 0, /* 50 baud */ 0, /* 75 baud */ 0, /* 110 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED0 | DCTCSR_RTS, /* 134.5 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED1 | DCTCSR_RTS, /* 150 baud */ 0, /* 200 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED2 | DCTCSR_RTS, /* 300 baud */ 0, /* 600 baud */ DCTCSR_STOP1 | DCTCSR_TIE | DC_SPEED3 | DCTCSR_RTS, /* 1200 baud */ 0, /* 1800 baud */ 0, /* 2400 baud */ 0, /* 4800 baud */ 0, /* 9600 baud */ 0, /* X0 */ 0 /* X1 */ }; /* * Open a DC11, waiting until carrier is established. * Default initial conditions are set up on the first open. * T_state's CARR_ON bit is a pure copy of the hardware * DC_CAR bit, and is only used to regularize * carrier tests in general tty routines. */ /*ARGSUSED*/ dcopen(dev, flag) register dev_t dev; { register struct tty *tp; register struct dcdevice *dcaddr; extern klstart(); int s; if (minor(dev) >= NDC) { u.u_error = ENXIO; return; } tp = &dc11[minor(dev)]; dcaddr = DCADDR + minor(dev); tp->t_addr = (caddr_t)dcaddr; tp->t_state |= WOPEN; s = spl5(); dcaddr->dcrcsr |= DC_IE | DC_DTR; if ((tp->t_state & ISOPEN) == 0) { tp->t_iproc = NULL; tp->t_oproc = klstart; /* Yes, I know, but it works. */ ttychars(tp); tp->t_ispeed = B300; tp->t_ospeed = B300; tp->t_flags = ODDP | EVENP | ECHO; dcaddr->dcrcsr = dcrstab[B300]; dcaddr->dctcsr = dctstab[B300]; } if (dcaddr->dcrcsr & DC_CAR) tp->t_state |= CARR_ON; splx(s); while ((tp->t_state & CARR_ON) == 0) sleep((caddr_t)&tp->t_rawq, TTIPRI); ttyopen(dev, tp); } /* * Close a DC11 */ dcclose(dev) dev_t dev; { register struct tty *tp; tp = &dc11[minor(dev)]; if (tp->t_state & HUPCLS) ((struct dcdevice *) (tp->t_addr))->dcrcsr & = ~DC_DTR; ttyclose(tp); } /* * Read a DC11 */ dcread(dev) dev_t dev; { register struct tty *tp; tp = &dc11[minor(dev)]; (*linesw[tp->t_line].l_read)(tp); } /* * Write a DC11 */ dcwrite(dev) dev_t dev; { register struct tty *tp; tp = &dc11[minor(dev)]; (*linesw[tp->t_line].l_write)(tp); } /* * DC11 transmitter interrupt. */ dcxint(dev) dev_t dev; { register struct tty *tp; register struct clist *cp; tp = &dc11[minor(dev)]; cp = &(tp->t_outq); ttstart(tp); if ((cp->c_cc == 0) || (cp->c_cc == TTLOWAT(tp))) wakeup((caddr_t) cp); } /* * DC11 receiver interrupt. */ dcrint(dev) dev_t dev; { register struct tty *tp; register int c, csr; tp = &dc11[minor(dev)]; c = ((struct dcdevice *) (tp->t_addr))->dcrbuf; /* * If carrier is off, and an open is not in progress, * knock down the CD lead to hang up the local dataset * and signal a hangup. */ if (((csr = ((struct dcdevice *)(tp->t_addr))->dcrcsr) & DC_CAR) == 0) { if ((tp->t_state & WOPEN) == 0) { ((struct dcdevice *) (tp->t_addr))->dcrcsr &= ~DC_DTR; if (tp->t_state & CARR_ON) signal(tp->t_pgrp, SIGHUP); flushtty(tp, FREAD|FWRITE); } tp->t_state &= ~CARR_ON; return; } if ((tp->t_state & ISOPEN) == 0) { if ((tp->t_state & WOPEN) && (csr & DC_CAR)) tp->t_state |= CARR_ON; wakeup((caddr_t) tp); return; } if (csr & DC_BRK) if (tp->t_flags & RAW) c = 0; else c = 0177; csr &= DC_PCHK; if ((csr && ((tp->t_flags & (EVENP | ODDP)) == ODDP)) || (!csr && ((tp->t_flags & (EVENP | ODDP)) == EVENP))) (*linesw[tp->t_line].l_input)(c, tp); } /* * DC11 stty/gtty. * Perform general functions and set speeds. */ dcioctl(dev, cmd, addr, flag) dev_t dev; caddr_t addr; { register struct tty *tp; register r; tp = &dc11[minor(dev)]; if (ttioctl(cmd, tp, addr, dev, flag) == 0) { u.u_error = ENOTTY; return; } if (cmd == TIOCSETP) { r = dcrstab[tp->t_ispeed]; if (r) ((struct dcdevice *) (tp->t_addr))->dcrcsr = r; else ((struct dcdevice *) (tp->t_addr))->dcrcsr &= ~DC_DTR; r = dctstab[tp->t_ospeed]; ((struct dcdevice *) (tp->t_addr))->dctcsr = r; } else u.u_error = ENOTTY; } #endif NDC