138627Smarc /*
238627Smarc * Copyright (c) 1982, 1986 Regents of the University of California.
338627Smarc * All rights reserved. The Berkeley software License Agreement
438627Smarc * specifies the terms and conditions for redistribution.
538627Smarc *
6*49759Smarc * @(#)dmx.c 7.7 (Berkeley) 05/16/91
738627Smarc */
838627Smarc
938627Smarc /*
1038627Smarc * Common code for DMF32 and DMZ32 drivers
1138627Smarc */
1238627Smarc #include "dmf.h"
1338627Smarc #include "dmz.h"
1438627Smarc #if NDMF + NDMZ > 0
1538627Smarc
1645804Sbostic #include "../include/pte.h"
1738627Smarc
1845804Sbostic #include "sys/param.h"
1938627Smarc #include "uba.h"
2045804Sbostic #include "sys/conf.h"
2145804Sbostic #include "sys/user.h"
2245804Sbostic #include "sys/proc.h"
2345804Sbostic #include "sys/ioctl.h"
2445804Sbostic #include "sys/tty.h"
2545804Sbostic #include "sys/map.h"
2645804Sbostic #include "sys/buf.h"
2745804Sbostic #include "sys/vm.h"
2845804Sbostic #include "sys/clist.h"
2945804Sbostic #include "sys/file.h"
3045804Sbostic #include "sys/uio.h"
3145804Sbostic #include "sys/kernel.h"
3245804Sbostic #include "sys/syslog.h"
3338627Smarc
3438627Smarc #include "dmx.h"
3538627Smarc #include "ubareg.h"
3638627Smarc #include "ubavar.h"
3738627Smarc #include "dmxreg.h"
3838627Smarc #include "dmreg.h"
3938627Smarc
4038627Smarc #ifndef PORTSELECTOR
4139061Smarc #define ISPEED TTYDEF_SPEED
4239061Smarc #define LFLAG TTYDEF_LFLAG
4338627Smarc #else
4438627Smarc #define ISPEED B4800
4539061Smarc #define IFLAGS (TTYDEF_LFLAG&~ECHO)
4638627Smarc #endif
4738627Smarc
4838627Smarc #ifndef DMX_TIMEOUT
4938627Smarc #define DMX_TIMEOUT 10
5038627Smarc #endif
5138627Smarc int dmx_timeout = DMX_TIMEOUT; /* silo timeout, in ms */
5238627Smarc int dmx_mindma = 4; /* don't dma below this point */
5338627Smarc
5438627Smarc struct speedtab dmxspeedtab[] = {
5538627Smarc 0, 0,
5638627Smarc 75, 1,
5738627Smarc 110, 2,
5838627Smarc 134, 3,
5938627Smarc 150, 4,
6038627Smarc 300, 5,
6138627Smarc 600, 6,
6238627Smarc 1200, 7,
6338627Smarc 1800, 010,
6438627Smarc 2400, 012,
6538627Smarc 4800, 014,
6638627Smarc 9600, 016,
6738627Smarc 19200, 017,
6838627Smarc EXTA, 017,
6938627Smarc -1, -1
7038627Smarc };
7138627Smarc /*
7238627Smarc * The clist space is mapped by the drivers onto each UNIBUS.
7338627Smarc * The UBACVT macro converts a clist space address for unibus uban
7438627Smarc * into an I/O space address for the DMA routine.
7538627Smarc */
7638627Smarc int cbase[NUBA]; /* base address in unibus map */
7738627Smarc #define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
7838627Smarc
7938627Smarc int ttrstrt();
8038627Smarc
8138627Smarc /*
8238627Smarc * DMF/DMZ open common code
8338627Smarc */
dmxopen(tp,sc,flag)8439061Smarc dmxopen(tp, sc, flag)
8538627Smarc register struct tty *tp;
8638627Smarc register struct dmx_softc *sc;
8738627Smarc {
8840731Skarels int s, unit, error = 0;
8938627Smarc int dmxparam();
9038627Smarc
9138627Smarc s = spltty();
9238627Smarc if ((sc->dmx_flags & DMX_ACTIVE) == 0) {
9338627Smarc sc->dmx_octet->csr |= DMF_IE;
9438627Smarc sc->dmx_flags |= DMX_ACTIVE;
9538627Smarc sc->dmx_octet->rsp = dmx_timeout;
9638627Smarc }
9738627Smarc splx(s);
9838627Smarc if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
9938627Smarc return (EBUSY);
10038627Smarc /*
10138627Smarc * If this is first open, initialize tty state to default.
10238627Smarc */
10338627Smarc if ((tp->t_state&TS_ISOPEN) == 0) {
10444393Smarc tp->t_state |= TS_WOPEN;
10538627Smarc ttychars(tp);
10638627Smarc #ifndef PORTSELECTOR
10738627Smarc if (tp->t_ispeed == 0) {
10839061Smarc #endif
10939061Smarc tp->t_iflag = TTYDEF_IFLAG;
11039061Smarc tp->t_oflag = TTYDEF_OFLAG;
11139061Smarc tp->t_cflag = TTYDEF_CFLAG;
11239061Smarc tp->t_lflag = LFLAG;
11339061Smarc tp->t_ispeed = tp->t_ospeed = ISPEED;
11439061Smarc #ifdef PORTSELECTOR
11539061Smarc tp->t_cflag |= HUPCL;
11638627Smarc #else
11738627Smarc }
11839061Smarc #endif
11938627Smarc }
12039061Smarc dmxparam(tp, &tp->t_termios);
12138627Smarc
12238627Smarc unit = minor(tp->t_dev) & 07;
12338627Smarc /*
12438627Smarc * Wait for carrier, then process line discipline specific open.
12538627Smarc */
12638627Smarc s = spltty();
12738627Smarc for (;;) {
12838627Smarc if ((dmxmctl(tp, DMF_ON, DMSET) & DMF_CAR) ||
12938627Smarc (sc->dmx_softCAR & (1 << unit)))
13038627Smarc tp->t_state |= TS_CARR_ON;
13139061Smarc if (tp->t_state&TS_CARR_ON || flag&O_NONBLOCK ||
13239061Smarc tp->t_cflag&CLOCAL)
13338627Smarc break;
13438627Smarc tp->t_state |= TS_WOPEN;
13544393Smarc if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
13644393Smarc ttopen, 0))
13740731Skarels break;
13838627Smarc }
13938627Smarc splx(s);
14040731Skarels if (error)
14140731Skarels return (error);
14238627Smarc return ((*linesw[tp->t_line].l_open)(tp->t_dev, tp));
14338627Smarc }
14438627Smarc
145*49759Smarc dmxclose(tp, flag)
146*49759Smarc struct tty *tp;
147*49759Smarc int flag;
14838627Smarc {
14938627Smarc
150*49759Smarc (*linesw[tp->t_line].l_close)(tp, flag);
15138627Smarc (void) dmxmctl(tp, DMF_BRK, DMBIC);
15239061Smarc if (tp->t_cflag & HUPCL || (tp->t_state & TS_ISOPEN) == 0)
15338627Smarc (void) dmxmctl(tp, DMF_OFF, DMSET);
15440731Skarels return (ttyclose(tp));
15538627Smarc }
15638627Smarc
dmxrint(sc)15738627Smarc dmxrint(sc)
15838627Smarc register struct dmx_softc *sc;
15938627Smarc {
16039061Smarc register c, cc;
16138627Smarc register struct tty *tp;
16238627Smarc register struct dmx_octet *addr;
16338627Smarc int unit;
16438627Smarc int overrun = 0;
16538627Smarc
16638627Smarc addr = (struct dmx_octet *)sc->dmx_octet;
16738627Smarc /*
16838627Smarc * Loop fetching characters from the silo for this
16938627Smarc * octet until there are no more in the silo.
17038627Smarc */
17138627Smarc while ((c = addr->rbuf) < 0) {
17239061Smarc cc = c&0xff;
17338627Smarc unit = (c >> 8) & 07;
17438627Smarc tp = sc->dmx_tty + unit;
17538627Smarc if (c & DMF_DSC) {
17638627Smarc addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
17738627Smarc if (addr->rmstsc & DMF_CAR)
17838627Smarc (void)(*linesw[tp->t_line].l_modem)(tp, 1);
17938627Smarc else if ((sc->dmx_softCAR & (1 << unit)) == 0 &&
18038627Smarc (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
18138627Smarc addr->csr = DMF_IE | DMFIR_LCR | unit;
18238627Smarc addr->lctms = DMF_ENA;
18338627Smarc }
18438627Smarc continue;
18538627Smarc }
18638627Smarc if ((tp->t_state&TS_ISOPEN) == 0) {
18738627Smarc wakeup((caddr_t)&tp->t_rawq);
18838627Smarc #ifdef PORTSELECTOR
18938627Smarc if ((tp->t_state & TS_WOPEN) == 0)
19038627Smarc #endif
19138627Smarc continue;
19238627Smarc }
19338627Smarc if (c & (DMF_PE|DMF_DO|DMF_FE)) {
19438627Smarc if (c & DMF_PE)
19539061Smarc cc |= TTY_PE;
19638627Smarc if ((c & DMF_DO) && overrun == 0) {
19738627Smarc log(LOG_WARNING,
19838627Smarc "dm%c%d: silo overflow, line %d\n",
19938627Smarc sc->dmx_type, sc->dmx_unit,
20038627Smarc sc->dmx_unit0 + unit);
20138627Smarc overrun = 1;
20238627Smarc }
20338627Smarc if (c & DMF_FE)
20439061Smarc cc |= TTY_FE;
20538627Smarc }
20639061Smarc (*linesw[tp->t_line].l_rint)(cc, tp);
20738627Smarc }
20838627Smarc }
20938627Smarc
dmxioctl(tp,cmd,data,flag)21038627Smarc dmxioctl(tp, cmd, data, flag)
21138627Smarc register struct tty *tp;
21238627Smarc caddr_t data;
21338627Smarc {
21438627Smarc int error;
21538627Smarc
21638627Smarc error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
21738627Smarc if (error >= 0)
21838627Smarc return (error);
21938627Smarc error = ttioctl(tp, cmd, data, flag);
22039061Smarc if (error >= 0)
22138627Smarc return (error);
22239061Smarc
22338627Smarc switch (cmd) {
22438627Smarc
22538627Smarc case TIOCSBRK:
22638627Smarc (void) dmxmctl(tp, DMF_BRK, DMBIS);
22738627Smarc break;
22838627Smarc
22938627Smarc case TIOCCBRK:
23038627Smarc (void) dmxmctl(tp, DMF_BRK, DMBIC);
23138627Smarc break;
23238627Smarc
23338627Smarc case TIOCSDTR:
23438627Smarc (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIS);
23538627Smarc break;
23638627Smarc
23738627Smarc case TIOCCDTR:
23838627Smarc (void) dmxmctl(tp, DMF_DTR|DMF_RTS, DMBIC);
23938627Smarc break;
24038627Smarc
24138627Smarc case TIOCMSET:
24238627Smarc (void) dmxmctl(tp, dmtodmx(*(int *)data), DMSET);
24338627Smarc break;
24438627Smarc
24538627Smarc case TIOCMBIS:
24638627Smarc (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIS);
24738627Smarc break;
24838627Smarc
24938627Smarc case TIOCMBIC:
25038627Smarc (void) dmxmctl(tp, dmtodmx(*(int *)data), DMBIC);
25138627Smarc break;
25238627Smarc
25338627Smarc case TIOCMGET:
25438627Smarc *(int *)data = dmxmctl(tp, 0, DMGET);
25538627Smarc break;
25638627Smarc
25738627Smarc default:
25838627Smarc return (ENOTTY);
25938627Smarc }
26038627Smarc return (0);
26138627Smarc }
26238627Smarc
26338627Smarc /*
26438627Smarc * modem control
26538627Smarc * "bits" are dmf/dmz lcr format;
26638627Smarc * return of DMGET is DM11 format.
26738627Smarc */
26838627Smarc dmxmctl(tp, bits, how)
26938627Smarc struct tty *tp;
27038627Smarc int bits, how;
27138627Smarc {
27238627Smarc register struct dmx_octet *addr;
27338627Smarc register int unit, mbits, lcr;
27438627Smarc int s;
27538627Smarc
27638627Smarc unit = minor(tp->t_dev) & 07;
27738627Smarc addr = (struct dmx_octet *)(tp->t_addr);
27838627Smarc
27938627Smarc s = spltty();
28038627Smarc addr->csr = DMF_IE | DMFIR_RMSTSC | unit;
28138627Smarc mbits = addr->rmstsc & 0xff00;
28238627Smarc addr->csr = DMF_IE | DMFIR_LCR | unit;
28338627Smarc lcr = addr->lctms;
28438627Smarc
28538627Smarc switch (how) {
28638627Smarc case DMSET:
28738627Smarc lcr = bits;
28838627Smarc break;
28938627Smarc
29038627Smarc case DMBIS:
29138627Smarc lcr |= bits;
29238627Smarc break;
29338627Smarc
29438627Smarc case DMBIC:
29538627Smarc lcr &= ~bits;
29638627Smarc break;
29738627Smarc
29838627Smarc case DMGET:
29938627Smarc splx(s);
30038627Smarc return (dmxtodm(mbits, lcr));
30138627Smarc }
30238627Smarc addr->lctms = lcr;
30338627Smarc (void) splx(s);
30438627Smarc return (mbits);
30538627Smarc }
30638627Smarc
30738627Smarc /*
30838627Smarc * Routine to convert modem status from dm to dmf/dmz lctmr format.
30938627Smarc */
dmtodmx(bits)31038627Smarc dmtodmx(bits)
31138627Smarc register int bits;
31238627Smarc {
31338627Smarc register int lcr = DMF_ENA;
31438627Smarc
31538627Smarc if (bits & DML_DTR)
31638627Smarc lcr |= DMF_DTR;
31738627Smarc if (bits & DML_RTS)
31838627Smarc lcr |= DMF_RTS;
31938627Smarc if (bits & DML_ST)
32038627Smarc lcr |= DMF_SRTS;
32138627Smarc if (bits & DML_USR)
32238627Smarc lcr |= DMF_USRW;
32338627Smarc return (lcr);
32438627Smarc }
32538627Smarc
32638627Smarc /*
32738627Smarc * Routine to convert modem status from dmf/dmz receive modem status
32838627Smarc * and line control register to dm format.
32938627Smarc * If dmf/dmz user modem read bit set, set DML_USR.
33038627Smarc */
dmxtodm(mstat,lcr)33138627Smarc dmxtodm(mstat, lcr)
33238627Smarc register int mstat, lcr;
33338627Smarc {
33438627Smarc
33538627Smarc mstat = ((mstat & (DMF_DSR|DMF_RNG|DMF_CAR|DMF_CTS|DMF_SR)) >> 7) |
33638627Smarc ((mstat & DMF_USRR) >> 1) | DML_LE;
33738627Smarc if (lcr & DMF_DTR)
33838627Smarc mstat |= DML_DTR;
33938627Smarc if (lcr & DMF_SRTS)
34038627Smarc mstat |= DML_ST;
34138627Smarc if (lcr & DMF_RTS)
34238627Smarc mstat |= DML_RTS;
34338627Smarc return (mstat);
34438627Smarc }
34538627Smarc
34638627Smarc
34738627Smarc /*
34838627Smarc * Set parameters from open or ioctl into the hardware registers.
34938627Smarc */
dmxparam(tp,t)35039061Smarc dmxparam(tp, t)
35138627Smarc register struct tty *tp;
35239061Smarc register struct termios *t;
35338627Smarc {
35438627Smarc register struct dmx_octet *addr;
35538627Smarc register int lpar, lcr;
35639061Smarc register int cflag = t->c_cflag;
35738627Smarc int s, unit;
35839061Smarc int ispeed = ttspeedtab(t->c_ispeed, dmxspeedtab);
35939061Smarc int ospeed = ttspeedtab(t->c_ospeed, dmxspeedtab);
36038627Smarc
36139061Smarc /* check requested parameters */
36239061Smarc if (ospeed < 0 || ispeed < 0 || (cflag&CSIZE) == CS5)
36339061Smarc return(EINVAL);
36439061Smarc if (ispeed == 0)
36539061Smarc ispeed = ospeed;
36639061Smarc /* and copy to tty */
36739061Smarc tp->t_ispeed = t->c_ispeed;
36839061Smarc tp->t_ospeed = t->c_ospeed;
36939061Smarc tp->t_cflag = cflag;
37039061Smarc
37138627Smarc addr = (struct dmx_octet *)tp->t_addr;
37238627Smarc unit = minor(tp->t_dev) & 07;
37338627Smarc /*
37438627Smarc * Block interrupts so parameters will be set
37538627Smarc * before the line interrupts.
37638627Smarc */
37738627Smarc s = spltty();
37838627Smarc addr->csr = unit | DMFIR_LCR | DMF_IE;
37939061Smarc if (ospeed == 0) {
38039061Smarc tp->t_cflag |= HUPCL;
38138627Smarc (void) dmxmctl(tp, DMF_OFF, DMSET);
38238627Smarc splx(s);
38338627Smarc return;
38438627Smarc }
38539061Smarc lpar = (ospeed<<12) | (ispeed<<8);
38638627Smarc lcr = DMF_ENA;
38739061Smarc switch (cflag&CSIZE) {
38839061Smarc case CS6: lpar |= BITS6; break;
38939061Smarc case CS7: lpar |= BITS7; break;
39039061Smarc case CS8: lpar |= BITS8; break;
39139061Smarc }
39239061Smarc if (cflag&PARENB)
39339061Smarc lpar |= PENABLE;
39439061Smarc if (!(cflag&PARODD))
39539061Smarc lpar |= EPAR;
39639061Smarc if (cflag&CSTOPB)
39739061Smarc lpar |= TWOSB;
39839061Smarc
39938627Smarc lpar |= (unit&07);
40038627Smarc addr->lpr = lpar;
40138627Smarc addr->lctms = (addr->lctms &~ 0xff) | lcr;
40238627Smarc splx(s);
40339061Smarc return 0;
40438627Smarc }
40538627Smarc
40638627Smarc /*
40738627Smarc * Process a transmit interrupt on an octet.
40838627Smarc */
dmxxint(sc)40938627Smarc dmxxint(sc)
41038627Smarc register struct dmx_softc *sc;
41138627Smarc {
41238627Smarc register struct tty *tp;
41338627Smarc register struct dmx_octet *addr;
41438627Smarc register int t;
41538627Smarc
41638627Smarc addr = (struct dmx_octet *)sc->dmx_octet;
41738627Smarc while ((t = addr->csr) & DMF_TI) {
41838627Smarc if (t & DMF_NXM)
41938627Smarc /* SHOULD RESTART OR SOMETHING... */
42038627Smarc printf("dm%c%d: NXM line %d\n", sc->dmx_type,
42138627Smarc sc->dmx_unit, sc->dmx_unit0 + (t >> 8 & 7));
42238627Smarc t = t >> 8 & 7;
42338627Smarc tp = sc->dmx_tty + t;
42438627Smarc tp->t_state &= ~TS_BUSY;
42538627Smarc if (tp->t_state & TS_FLUSH)
42638627Smarc tp->t_state &= ~TS_FLUSH;
42738627Smarc #define new
42838627Smarc #ifndef new
42938627Smarc else if (sc->dmx_dmacount[t]) {
43038627Smarc short cntr;
43138627Smarc
43238627Smarc /*
43338627Smarc * Do arithmetic in a short to make up
43438627Smarc * for lost 16&17 bits.
43538627Smarc */
43638627Smarc addr->csr = DMFIR_TBA | DMF_IE | t;
43738627Smarc cntr = addr->tba -
43838627Smarc UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
43938627Smarc ndflush(&tp->t_outq, (int)cntr);
44038627Smarc }
44138627Smarc #else
44238627Smarc else if (sc->dmx_dmacount[t])
44338627Smarc ndflush(&tp->t_outq, sc->dmx_dmacount[t]);
44438627Smarc sc->dmx_dmacount[t] = 0;
44538627Smarc #endif
44638627Smarc (*linesw[tp->t_line].l_start)(tp);
44738627Smarc }
44838627Smarc }
44938627Smarc
dmxstart(tp,sc)45038627Smarc dmxstart(tp, sc)
45138627Smarc register struct tty *tp;
45238627Smarc struct dmx_softc *sc;
45338627Smarc {
45438627Smarc register struct dmx_octet *addr;
45538627Smarc register int unit, nch;
45638627Smarc int s;
45738627Smarc
45838627Smarc unit = minor(tp->t_dev) & 07;
45938627Smarc addr = (struct dmx_octet *)tp->t_addr;
46038627Smarc
46138627Smarc /*
46238627Smarc * Must hold interrupts in following code to prevent
46338627Smarc * state of the tp from changing.
46438627Smarc */
46538627Smarc s = spltty();
46638627Smarc /*
46738627Smarc * If it's currently active, or delaying, no need to do anything.
46838627Smarc */
46938627Smarc if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
47038627Smarc goto out;
47138627Smarc /*
47238627Smarc * If there are still characters to dma or in the silo,
47338627Smarc * just reenable the transmitter.
47438627Smarc */
47538627Smarc addr->csr = DMF_IE | DMFIR_TBUF | unit;
47638627Smarc #ifdef new
47738627Smarc if (addr->tsc || sc->dmx_dmacount[unit]) {
47838627Smarc #else
47938627Smarc if (addr->tsc) {
48038627Smarc #endif
48138627Smarc addr->csr = DMF_IE | DMFIR_LCR | unit;
48238627Smarc addr->lctms = addr->lctms | DMF_TE;
48338627Smarc tp->t_state |= TS_BUSY;
48438627Smarc goto out;
48538627Smarc }
48638627Smarc /*
48738627Smarc * If there are sleepers, and output has drained below low
48838627Smarc * water mark, wake up the sleepers.
48938627Smarc */
49039061Smarc if (tp->t_outq.c_cc <= tp->t_lowat) {
49138627Smarc if (tp->t_state & TS_ASLEEP) {
49238627Smarc tp->t_state &= ~TS_ASLEEP;
49338627Smarc wakeup((caddr_t)&tp->t_outq);
49438627Smarc }
49538627Smarc if (tp->t_wsel) {
49638627Smarc selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
49738627Smarc tp->t_wsel = 0;
49838627Smarc tp->t_state &= ~TS_WCOLL;
49938627Smarc }
50038627Smarc }
50138627Smarc /*
50238627Smarc * Now restart transmission unless the output queue is
50338627Smarc * empty.
50438627Smarc */
50538627Smarc if (tp->t_outq.c_cc == 0)
50638627Smarc goto out;
50739061Smarc if (1 || !(tp->t_oflag&OPOST)) /*XXX*/
50838627Smarc nch = ndqb(&tp->t_outq, 0);
50938627Smarc else {
51038627Smarc if ((nch = ndqb(&tp->t_outq, 0200)) == 0) {
51138627Smarc /*
51238627Smarc * If first thing on queue is a delay process it.
51338627Smarc */
51438627Smarc nch = getc(&tp->t_outq);
51538627Smarc timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
51638627Smarc tp->t_state |= TS_TIMEOUT;
51738627Smarc goto out;
51838627Smarc }
51938627Smarc }
52038627Smarc /*
52138627Smarc * If characters to transmit, restart transmission.
52238627Smarc */
52338627Smarc if (nch >= dmx_mindma) {
52438627Smarc register car;
52538627Smarc
52638627Smarc sc->dmx_dmacount[unit] = nch;
52738627Smarc addr->csr = DMF_IE | DMFIR_LCR | unit;
52838627Smarc addr->lctms = addr->lctms | DMF_TE;
52938627Smarc car = UBACVT(tp->t_outq.c_cf, sc->dmx_ubanum);
53038627Smarc addr->csr = DMF_IE | DMFIR_TBA | unit;
53138627Smarc addr->tba = car;
53238627Smarc addr->tcc = ((car >> 2) & 0xc000) | nch;
53338627Smarc tp->t_state |= TS_BUSY;
53438627Smarc } else if (nch) {
53538627Smarc register char *cp = tp->t_outq.c_cf;
53638627Smarc register int i;
53738627Smarc
53838627Smarc #ifndef new
53938627Smarc sc->dmx_dmacount[unit] = 0;
54038627Smarc #endif
54138627Smarc nch = MIN(nch, DMF_SILOCNT);
54238627Smarc addr->csr = DMF_IE | DMFIR_LCR | unit;
54338627Smarc addr->lctms = addr->lctms | DMF_TE;
54438627Smarc addr->csr = DMF_IE | DMFIR_TBUF | unit;
54538627Smarc for (i = 0; i < nch; i++)
54638627Smarc addr->tbuf = *cp++;
54738627Smarc ndflush(&tp->t_outq, nch);
54838627Smarc tp->t_state |= TS_BUSY;
54938627Smarc }
55038627Smarc out:
55138627Smarc splx(s);
55238627Smarc }
55338627Smarc
dmxstop(tp,sc,flag)55438627Smarc dmxstop(tp, sc, flag)
55538627Smarc register struct tty *tp;
55638627Smarc struct dmx_softc *sc;
55738627Smarc {
55838627Smarc register struct dmx_octet *addr;
55938627Smarc register unit = minor(tp->t_dev) & 7;
56038627Smarc int s;
56138627Smarc
56238627Smarc addr = (struct dmx_octet *)tp->t_addr;
56338627Smarc /*
56438627Smarc * Block input/output interrupts while messing with state.
56538627Smarc */
56638627Smarc s = spltty();
56738627Smarc if (flag) {
56838627Smarc addr->csr = DMF_IE | DMFIR_TBUF | unit;
56938627Smarc if (addr->tsc) {
57038627Smarc /*
57138627Smarc * Flush regardless of whether we're transmitting
57238627Smarc * (TS_BUSY), if the silo contains untransmitted
57338627Smarc * characters.
57438627Smarc */
57538627Smarc addr->csr = DMFIR_LCR | unit | DMF_IE;
57638627Smarc addr->lctms = addr->lctms | DMF_TE | DMF_FLUSH;
57738627Smarc /* this will interrupt so let dmxxint handle the rest */
57838627Smarc tp->t_state |= TS_FLUSH|TS_BUSY;
57938627Smarc }
58038627Smarc /*#ifdef new*/
58138627Smarc sc->dmx_dmacount[unit] = 0;
58238627Smarc /*#endif*/
58338627Smarc } else {
58438627Smarc /*
58538627Smarc * Stop transmission by disabling
58638627Smarc * the transmitter. We'll pick up where we
58738627Smarc * left off by reenabling in dmxstart.
58838627Smarc */
58938627Smarc addr->csr = DMFIR_LCR | unit | DMF_IE;
59038627Smarc addr->lctms = addr->lctms &~ DMF_TE;
59138627Smarc /* no interrupt here */
59238627Smarc tp->t_state &= ~TS_BUSY;
59338627Smarc }
59438627Smarc splx(s);
59538627Smarc }
59638627Smarc #endif NDMF + NDMZ
597