156819Sralph /*- 263205Sbostic * Copyright (c) 1992, 1993 363205Sbostic * The Regents of the University of California. All rights reserved. 452130Smckusick * 552130Smckusick * This code is derived from software contributed to Berkeley by 656819Sralph * Ralph Campbell and Rick Macklem. 756819Sralph * 856819Sralph * %sccs.include.redist.c% 956819Sralph * 10*67477Smckusick * @(#)dc.c 8.3 (Berkeley) 07/03/94 1152693Sralph */ 1252693Sralph 1352693Sralph /* 1452130Smckusick * devDC7085.c -- 1552130Smckusick * 1652130Smckusick * This file contains machine-dependent routines that handle the 1752130Smckusick * output queue for the serial lines. 1852130Smckusick * 1952130Smckusick * Copyright (C) 1989 Digital Equipment Corporation. 2052130Smckusick * Permission to use, copy, modify, and distribute this software and 2152130Smckusick * its documentation for any purpose and without fee is hereby granted, 2252130Smckusick * provided that the above copyright notice appears in all copies. 2352130Smckusick * Digital Equipment Corporation makes no representations about the 2452130Smckusick * suitability of this software for any purpose. It is provided "as is" 2552130Smckusick * without express or implied warranty. 2652130Smckusick * 2752130Smckusick * from: $Header: /sprite/src/kernel/dev/ds3100.md/RCS/devDC7085.c, 2852130Smckusick * v 1.4 89/08/29 11:55:30 nelson Exp $ SPRITE (DECWRL)"; 2952130Smckusick */ 3052130Smckusick 3156819Sralph #include <dc.h> 3252130Smckusick #if NDC > 0 3352130Smckusick /* 3452130Smckusick * DC7085 (DZ-11 look alike) Driver 3552130Smckusick */ 3656522Sbostic #include <sys/param.h> 3756522Sbostic #include <sys/systm.h> 3856522Sbostic #include <sys/ioctl.h> 3956522Sbostic #include <sys/tty.h> 4056522Sbostic #include <sys/proc.h> 4156522Sbostic #include <sys/map.h> 4256522Sbostic #include <sys/buf.h> 4356522Sbostic #include <sys/conf.h> 4456522Sbostic #include <sys/file.h> 4556522Sbostic #include <sys/uio.h> 4656522Sbostic #include <sys/kernel.h> 4756522Sbostic #include <sys/syslog.h> 4852130Smckusick 4956522Sbostic #include <machine/dc7085cons.h> 5056819Sralph #include <machine/pmioctl.h> 5152130Smckusick 5256819Sralph #include <pmax/pmax/pmaxtype.h> 5356819Sralph #include <pmax/pmax/cons.h> 5456819Sralph 5556525Sbostic #include <pmax/dev/device.h> 5656525Sbostic #include <pmax/dev/pdma.h> 5756819Sralph #include <pmax/dev/fbreg.h> 5852130Smckusick 5956819Sralph extern int pmax_boardtype; 6056819Sralph extern struct consdev cn_tab; 6156819Sralph 6252130Smckusick /* 6352130Smckusick * Driver information for auto-configuration stuff. 6452130Smckusick */ 6552130Smckusick int dcprobe(); 6652693Sralph void dcintr(); 6752130Smckusick struct driver dcdriver = { 6852693Sralph "dc", dcprobe, 0, 0, dcintr, 6952130Smckusick }; 7052130Smckusick 7152130Smckusick #define NDCLINE (NDC*4) 7252130Smckusick 7356819Sralph void dcstart __P((struct tty *)); 7456819Sralph void dcxint __P((struct tty *)); 7556819Sralph void dcPutc __P((dev_t, int)); 7656819Sralph void dcscan __P((void *)); 7756226Sralph extern void ttrstrt __P((void *)); 7856819Sralph int dcGetc __P((dev_t)); 7956819Sralph int dcparam __P((struct tty *, struct termios *)); 8052130Smckusick 8152130Smckusick struct tty dc_tty[NDCLINE]; 8252130Smckusick int dc_cnt = NDCLINE; 8352863Sralph void (*dcDivertXInput)(); /* X windows keyboard input routine */ 8452863Sralph void (*dcMouseEvent)(); /* X windows mouse motion event routine */ 8552863Sralph void (*dcMouseButtons)(); /* X windows mouse buttons event routine */ 8652130Smckusick #ifdef DEBUG 8752130Smckusick int debugChar; 8852130Smckusick #endif 8952130Smckusick 9052130Smckusick /* 9152130Smckusick * Software copy of brk register since it isn't readable 9252130Smckusick */ 9352130Smckusick int dc_brk[NDC]; 9452130Smckusick char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ 9552130Smckusick 9652130Smckusick /* 9752130Smckusick * The DC7085 doesn't interrupt on carrier transitions, so 9852130Smckusick * we have to use a timer to watch it. 9952130Smckusick */ 10052130Smckusick int dc_timer; /* true if timer started */ 10152130Smckusick 10252130Smckusick /* 10352130Smckusick * Pdma structures for fast output code 10452130Smckusick */ 10552130Smckusick struct pdma dcpdma[NDCLINE]; 10652130Smckusick 10752130Smckusick struct speedtab dcspeedtab[] = { 10852130Smckusick 0, 0, 10952130Smckusick 50, LPR_B50, 11052130Smckusick 75, LPR_B75, 11152130Smckusick 110, LPR_B110, 11252130Smckusick 134, LPR_B134, 11352130Smckusick 150, LPR_B150, 11452130Smckusick 300, LPR_B300, 11552130Smckusick 600, LPR_B600, 11652130Smckusick 1200, LPR_B1200, 11752130Smckusick 1800, LPR_B1800, 11852130Smckusick 2400, LPR_B2400, 11952130Smckusick 4800, LPR_B4800, 12052130Smckusick 9600, LPR_B9600, 12152693Sralph 19200, LPR_B19200, 12252130Smckusick -1, -1 12352130Smckusick }; 12452130Smckusick 12552130Smckusick #ifndef PORTSELECTOR 12652130Smckusick #define ISPEED TTYDEF_SPEED 12752130Smckusick #define LFLAG TTYDEF_LFLAG 12852130Smckusick #else 12952130Smckusick #define ISPEED B4800 13052130Smckusick #define LFLAG (TTYDEF_LFLAG & ~ECHO) 13152130Smckusick #endif 13252130Smckusick 13352130Smckusick /* 13452130Smckusick * Test to see if device is present. 13552130Smckusick * Return true if found and initialized ok. 13652130Smckusick */ 13752130Smckusick dcprobe(cp) 13852130Smckusick register struct pmax_ctlr *cp; 13952130Smckusick { 14052130Smckusick register dcregs *dcaddr; 14152130Smckusick register struct pdma *pdp; 14252130Smckusick register struct tty *tp; 14352130Smckusick register int cntr; 14456819Sralph int s; 14552130Smckusick 14652130Smckusick if (cp->pmax_unit >= NDC) 14752130Smckusick return (0); 14852130Smckusick if (badaddr(cp->pmax_addr, 2)) 14952130Smckusick return (0); 15052130Smckusick 15157234Sralph /* 15257234Sralph * For a remote console, wait a while for previous output to 15357234Sralph * complete. 15457234Sralph */ 15557234Sralph if (major(cn_tab.cn_dev) == DCDEV && cp->pmax_unit == 0 && 15657234Sralph cn_tab.cn_screen == 0) 15757234Sralph DELAY(10000); 15857234Sralph 15952130Smckusick /* reset chip */ 16052130Smckusick dcaddr = (dcregs *)cp->pmax_addr; 16152130Smckusick dcaddr->dc_csr = CSR_CLR; 16252130Smckusick MachEmptyWriteBuffer(); 16352130Smckusick while (dcaddr->dc_csr & CSR_CLR) 16452130Smckusick ; 16552130Smckusick dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; 16652130Smckusick 16752130Smckusick /* init pseudo DMA structures */ 16852130Smckusick pdp = &dcpdma[cp->pmax_unit * 4]; 16952130Smckusick tp = &dc_tty[cp->pmax_unit * 4]; 17052130Smckusick for (cntr = 0; cntr < 4; cntr++) { 17156819Sralph pdp->p_addr = (void *)dcaddr; 17252130Smckusick pdp->p_arg = (int)tp; 17352130Smckusick pdp->p_fcn = dcxint; 17452130Smckusick pdp++, tp++; 17552130Smckusick } 17652130Smckusick dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB; 17752130Smckusick 17852130Smckusick if (dc_timer == 0) { 17952130Smckusick dc_timer = 1; 18055744Sralph timeout(dcscan, (void *)0, hz); 18152130Smckusick } 18256819Sralph 18356819Sralph /* 18456819Sralph * Special handling for consoles. 18556819Sralph */ 18652130Smckusick if (cp->pmax_unit == 0) { 18756819Sralph if (cn_tab.cn_screen) { 18856819Sralph s = spltty(); 18956819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 19056819Sralph LPR_B4800 | DCKBD_PORT; 19158975Sralph MachEmptyWriteBuffer(); 19256819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 19356819Sralph LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; 19456819Sralph MachEmptyWriteBuffer(); 19557234Sralph DELAY(1000); 19656819Sralph KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc); 19756819Sralph MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc); 19856819Sralph splx(s); 19956819Sralph } else if (major(cn_tab.cn_dev) == DCDEV) { 20056819Sralph s = spltty(); 20156819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 20256819Sralph LPR_B9600 | minor(cn_tab.cn_dev); 20356819Sralph MachEmptyWriteBuffer(); 20457234Sralph DELAY(1000); 20556819Sralph cn_tab.cn_disabled = 0; 20656819Sralph splx(s); 20756819Sralph } 20852130Smckusick } 20957234Sralph printf("dc%d at nexus0 csr 0x%x priority %d\n", 21057234Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 21152130Smckusick return (1); 21252130Smckusick } 21352130Smckusick 21454146Sralph dcopen(dev, flag, mode, p) 21552130Smckusick dev_t dev; 21654146Sralph int flag, mode; 21754146Sralph struct proc *p; 21852130Smckusick { 21952130Smckusick register struct tty *tp; 22052130Smckusick register int unit; 22152130Smckusick int s, error = 0; 22252130Smckusick 22352130Smckusick unit = minor(dev); 22456819Sralph if (unit >= dc_cnt || dcpdma[unit].p_addr == (void *)0) 22552130Smckusick return (ENXIO); 22652130Smckusick tp = &dc_tty[unit]; 22752130Smckusick tp->t_oproc = dcstart; 22852130Smckusick tp->t_param = dcparam; 22952130Smckusick tp->t_dev = dev; 23052130Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 23152130Smckusick tp->t_state |= TS_WOPEN; 23252130Smckusick ttychars(tp); 23352130Smckusick #ifndef PORTSELECTOR 23452130Smckusick if (tp->t_ispeed == 0) { 23552130Smckusick #endif 23652130Smckusick tp->t_iflag = TTYDEF_IFLAG; 23752130Smckusick tp->t_oflag = TTYDEF_OFLAG; 23852130Smckusick tp->t_cflag = TTYDEF_CFLAG; 23952130Smckusick tp->t_lflag = LFLAG; 24052130Smckusick tp->t_ispeed = tp->t_ospeed = ISPEED; 24152130Smckusick #ifdef PORTSELECTOR 24252130Smckusick tp->t_cflag |= HUPCL; 24352130Smckusick #else 24452130Smckusick } 24552130Smckusick #endif 24652130Smckusick (void) dcparam(tp, &tp->t_termios); 24752130Smckusick ttsetwater(tp); 24852130Smckusick } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 24952130Smckusick return (EBUSY); 250*67477Smckusick (void) dcmctl(dev, DML_DTR | DML_RTS, DMSET); 25152130Smckusick s = spltty(); 25252130Smckusick while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 25352130Smckusick !(tp->t_state & TS_CARR_ON)) { 25452130Smckusick tp->t_state |= TS_WOPEN; 25552130Smckusick if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 25652130Smckusick ttopen, 0)) 25752130Smckusick break; 25852130Smckusick } 25952130Smckusick splx(s); 26052130Smckusick if (error) 26152130Smckusick return (error); 26252130Smckusick return ((*linesw[tp->t_line].l_open)(dev, tp)); 26352130Smckusick } 26452130Smckusick 26552130Smckusick /*ARGSUSED*/ 26654146Sralph dcclose(dev, flag, mode, p) 26752130Smckusick dev_t dev; 26854146Sralph int flag, mode; 26954146Sralph struct proc *p; 27052130Smckusick { 27152130Smckusick register struct tty *tp; 27252130Smckusick register int unit, bit; 27352130Smckusick 27452130Smckusick unit = minor(dev); 27552130Smckusick tp = &dc_tty[unit]; 27652130Smckusick bit = 1 << ((unit & 03) + 8); 27752130Smckusick if (dc_brk[unit >> 2] & bit) { 27852130Smckusick dc_brk[unit >> 2] &= ~bit; 27952130Smckusick ttyoutput(0, tp); 28052130Smckusick } 28154146Sralph (*linesw[tp->t_line].l_close)(tp, flag); 28252130Smckusick if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 28352130Smckusick !(tp->t_state & TS_ISOPEN)) 28452130Smckusick (void) dcmctl(dev, 0, DMSET); 28552130Smckusick return (ttyclose(tp)); 28652130Smckusick } 28752130Smckusick 28852130Smckusick dcread(dev, uio, flag) 28952130Smckusick dev_t dev; 29052130Smckusick struct uio *uio; 29152130Smckusick { 29252130Smckusick register struct tty *tp; 29352130Smckusick 29452130Smckusick tp = &dc_tty[minor(dev)]; 295*67477Smckusick if ((tp->t_cflag & CRTS_IFLOW) && (tp->t_state & TS_TBLOCK) && 296*67477Smckusick tp->t_rawq.c_cc < TTYHOG/5) { 297*67477Smckusick tp->t_state &= ~TS_TBLOCK; 298*67477Smckusick (void) dcmctl(dev, DML_RTS, DMBIS); 299*67477Smckusick } 30052130Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 30152130Smckusick } 30252130Smckusick 30352130Smckusick dcwrite(dev, uio, flag) 30452130Smckusick dev_t dev; 30552130Smckusick struct uio *uio; 30652130Smckusick { 30752130Smckusick register struct tty *tp; 30852130Smckusick 30952130Smckusick tp = &dc_tty[minor(dev)]; 31052130Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 31152130Smckusick } 31252130Smckusick 31352130Smckusick /*ARGSUSED*/ 31454146Sralph dcioctl(dev, cmd, data, flag, p) 31552130Smckusick dev_t dev; 31656819Sralph int cmd; 31752130Smckusick caddr_t data; 31854146Sralph int flag; 31954146Sralph struct proc *p; 32052130Smckusick { 32152130Smckusick register struct tty *tp; 32252130Smckusick register int unit = minor(dev); 32352130Smckusick register int dc = unit >> 2; 32452130Smckusick int error; 32552130Smckusick 32652130Smckusick tp = &dc_tty[unit]; 32754146Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 32852130Smckusick if (error >= 0) 32952130Smckusick return (error); 33052130Smckusick error = ttioctl(tp, cmd, data, flag); 33152130Smckusick if (error >= 0) 33252130Smckusick return (error); 33352130Smckusick 33452130Smckusick switch (cmd) { 33552130Smckusick 33652130Smckusick case TIOCSBRK: 33752130Smckusick dc_brk[dc] |= 1 << ((unit & 03) + 8); 33852130Smckusick ttyoutput(0, tp); 33952130Smckusick break; 34052130Smckusick 34152130Smckusick case TIOCCBRK: 34252130Smckusick dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); 34352130Smckusick ttyoutput(0, tp); 34452130Smckusick break; 34552130Smckusick 34652130Smckusick case TIOCSDTR: 347*67477Smckusick (void) dcmctl(dev, DML_DTR | DML_RTS, DMBIS); 34852130Smckusick break; 34952130Smckusick 35052130Smckusick case TIOCCDTR: 351*67477Smckusick (void) dcmctl(dev, DML_DTR | DML_RTS, DMBIC); 35252130Smckusick break; 35352130Smckusick 35452130Smckusick case TIOCMSET: 35552130Smckusick (void) dcmctl(dev, *(int *)data, DMSET); 35652130Smckusick break; 35752130Smckusick 35852130Smckusick case TIOCMBIS: 35952130Smckusick (void) dcmctl(dev, *(int *)data, DMBIS); 36052130Smckusick break; 36152130Smckusick 36252130Smckusick case TIOCMBIC: 36352130Smckusick (void) dcmctl(dev, *(int *)data, DMBIC); 36452130Smckusick break; 36552130Smckusick 36652130Smckusick case TIOCMGET: 36752130Smckusick *(int *)data = dcmctl(dev, 0, DMGET); 36852130Smckusick break; 36952130Smckusick 37052130Smckusick default: 37152130Smckusick return (ENOTTY); 37252130Smckusick } 37352130Smckusick return (0); 37452130Smckusick } 37552130Smckusick 37652130Smckusick dcparam(tp, t) 37752130Smckusick register struct tty *tp; 37852130Smckusick register struct termios *t; 37952130Smckusick { 38052130Smckusick register dcregs *dcaddr; 38152130Smckusick register int lpr; 38252130Smckusick register int cflag = t->c_cflag; 38352130Smckusick int unit = minor(tp->t_dev); 38452130Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); 38552130Smckusick 38652130Smckusick /* check requested parameters */ 38752130Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 38856819Sralph (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 || 38956819Sralph (pmax_boardtype == DS_PMAX && t->c_ospeed == 19200)) 39052130Smckusick return (EINVAL); 39152130Smckusick /* and copy to tty */ 39252130Smckusick tp->t_ispeed = t->c_ispeed; 39352130Smckusick tp->t_ospeed = t->c_ospeed; 39452130Smckusick tp->t_cflag = cflag; 39552130Smckusick 39656819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 39756819Sralph 39856819Sralph /* 39956819Sralph * Handle console cases specially. 40056819Sralph */ 40156819Sralph if (cn_tab.cn_screen) { 40256819Sralph if (unit == DCKBD_PORT) { 40356819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 40456819Sralph LPR_B4800 | DCKBD_PORT; 40556819Sralph MachEmptyWriteBuffer(); 40656819Sralph return (0); 40756819Sralph } else if (unit == DCMOUSE_PORT) { 40856819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 40956819Sralph LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; 41056819Sralph MachEmptyWriteBuffer(); 41156819Sralph return (0); 41256819Sralph } 41356819Sralph } else if (tp->t_dev == cn_tab.cn_dev) { 41456819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 41556819Sralph LPR_B9600 | unit; 41652130Smckusick MachEmptyWriteBuffer(); 41752130Smckusick return (0); 41852130Smckusick } 41952130Smckusick if (ospeed == 0) { 42052130Smckusick (void) dcmctl(unit, 0, DMSET); /* hang up line */ 42152130Smckusick return (0); 42252130Smckusick } 42352130Smckusick lpr = LPR_RXENAB | ospeed | (unit & 03); 42452130Smckusick if ((cflag & CSIZE) == CS7) 42552130Smckusick lpr |= LPR_7_BIT_CHAR; 42652130Smckusick else 42752130Smckusick lpr |= LPR_8_BIT_CHAR; 42852130Smckusick if (cflag & PARENB) 42952130Smckusick lpr |= LPR_PARENB; 43052130Smckusick if (cflag & PARODD) 43152130Smckusick lpr |= LPR_OPAR; 43252130Smckusick if (cflag & CSTOPB) 43352130Smckusick lpr |= LPR_2_STOP; 43452130Smckusick dcaddr->dc_lpr = lpr; 43552130Smckusick MachEmptyWriteBuffer(); 43658975Sralph DELAY(10); 43752130Smckusick return (0); 43852130Smckusick } 43952130Smckusick 44052693Sralph /* 44152693Sralph * Check for interrupts from all devices. 44252693Sralph */ 44352693Sralph void 44452693Sralph dcintr(unit) 44552693Sralph register int unit; 44652693Sralph { 44752693Sralph register dcregs *dcaddr; 44852693Sralph register unsigned csr; 44952693Sralph 45052693Sralph unit <<= 2; 45156819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 45252693Sralph while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { 45352693Sralph if (csr & CSR_RDONE) 45452693Sralph dcrint(unit); 45552693Sralph if (csr & CSR_TRDY) 45652693Sralph dcxint(&dc_tty[unit + ((csr >> 8) & 03)]); 45752693Sralph } 45852693Sralph } 45952693Sralph 46052693Sralph dcrint(unit) 46152693Sralph register int unit; 46252693Sralph { 46352693Sralph register dcregs *dcaddr; 46452693Sralph register struct tty *tp; 46552693Sralph register int c, cc; 46652693Sralph register struct tty *tp0; 46752693Sralph int overrun = 0; 46852693Sralph 46956819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 47052693Sralph tp0 = &dc_tty[unit]; 47152693Sralph while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ 47252693Sralph cc = c & 0xff; 47352693Sralph tp = tp0 + ((c >> 8) & 03); 47452693Sralph if ((c & RBUF_OERR) && overrun == 0) { 47552693Sralph log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, 47652693Sralph (c >> 8) & 03); 47752693Sralph overrun = 1; 47852693Sralph } 47952693Sralph /* the keyboard requires special translation */ 48056819Sralph if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { 48152693Sralph #ifdef KADB 48252693Sralph if (cc == LK_DO) { 48352693Sralph spl0(); 48452693Sralph kdbpanic(); 48552693Sralph return; 48652693Sralph } 48752693Sralph #endif 48852693Sralph #ifdef DEBUG 48952693Sralph debugChar = cc; 49052693Sralph #endif 49152693Sralph if (dcDivertXInput) { 49252863Sralph (*dcDivertXInput)(cc); 49352693Sralph return; 49452693Sralph } 49556819Sralph if ((cc = kbdMapChar(cc)) < 0) 49652693Sralph return; 49756819Sralph } else if (tp == &dc_tty[DCMOUSE_PORT] && dcMouseButtons) { 49852863Sralph register MouseReport *mrp; 49952693Sralph static MouseReport currentRep; 50052693Sralph 50152863Sralph mrp = ¤tRep; 50252863Sralph mrp->byteCount++; 50352693Sralph if (cc & MOUSE_START_FRAME) { 50452693Sralph /* 50552693Sralph * The first mouse report byte (button state). 50652693Sralph */ 50752863Sralph mrp->state = cc; 50852863Sralph if (mrp->byteCount > 1) 50952863Sralph mrp->byteCount = 1; 51052863Sralph } else if (mrp->byteCount == 2) { 51152693Sralph /* 51252693Sralph * The second mouse report byte (delta x). 51352693Sralph */ 51452863Sralph mrp->dx = cc; 51552863Sralph } else if (mrp->byteCount == 3) { 51652693Sralph /* 51752693Sralph * The final mouse report byte (delta y). 51852693Sralph */ 51952863Sralph mrp->dy = cc; 52052863Sralph mrp->byteCount = 0; 52152863Sralph if (mrp->dx != 0 || mrp->dy != 0) { 52252693Sralph /* 52352693Sralph * If the mouse moved, 52452693Sralph * post a motion event. 52552693Sralph */ 52652863Sralph (*dcMouseEvent)(mrp); 52752693Sralph } 52852863Sralph (*dcMouseButtons)(mrp); 52952693Sralph } 53052693Sralph return; 53152693Sralph } 53252693Sralph if (!(tp->t_state & TS_ISOPEN)) { 53352693Sralph wakeup((caddr_t)&tp->t_rawq); 53452693Sralph #ifdef PORTSELECTOR 53552693Sralph if (!(tp->t_state & TS_WOPEN)) 53652693Sralph #endif 53752693Sralph return; 53852693Sralph } 53952693Sralph if (c & RBUF_FERR) 54052693Sralph cc |= TTY_FE; 54152693Sralph if (c & RBUF_PERR) 54252693Sralph cc |= TTY_PE; 543*67477Smckusick if ((tp->t_cflag & CRTS_IFLOW) && !(tp->t_state & TS_TBLOCK) && 544*67477Smckusick tp->t_rawq.c_cc + tp->t_canq.c_cc >= TTYHOG) { 545*67477Smckusick tp->t_state &= ~TS_TBLOCK; 546*67477Smckusick (void) dcmctl(tp->t_dev, DML_RTS, DMBIC); 547*67477Smckusick } 54852693Sralph (*linesw[tp->t_line].l_rint)(cc, tp); 54952693Sralph } 55052693Sralph DELAY(10); 55152693Sralph } 55252693Sralph 55352755Sralph void 55452130Smckusick dcxint(tp) 55552130Smckusick register struct tty *tp; 55652130Smckusick { 55752130Smckusick register struct pdma *dp; 55852130Smckusick register dcregs *dcaddr; 559*67477Smckusick int unit; 56052130Smckusick 561*67477Smckusick dp = &dcpdma[unit = minor(tp->t_dev)]; 56252130Smckusick if (dp->p_mem < dp->p_end) { 56356819Sralph dcaddr = (dcregs *)dp->p_addr; 564*67477Smckusick /* check for hardware flow control of output */ 565*67477Smckusick if ((tp->t_cflag & CCTS_OFLOW) && pmax_boardtype != DS_PMAX) { 566*67477Smckusick switch (unit) { 567*67477Smckusick case DCCOMM_PORT: 568*67477Smckusick if (dcaddr->dc_msr & MSR_CTS2) 569*67477Smckusick break; 570*67477Smckusick goto stop; 571*67477Smckusick 572*67477Smckusick case DCPRINTER_PORT: 573*67477Smckusick if (dcaddr->dc_msr & MSR_CTS3) 574*67477Smckusick break; 575*67477Smckusick stop: 576*67477Smckusick tp->t_state &= ~TS_BUSY; 577*67477Smckusick tp->t_state |= TS_TTSTOP; 578*67477Smckusick ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 579*67477Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 580*67477Smckusick dcaddr->dc_tcr &= ~(1 << unit); 581*67477Smckusick MachEmptyWriteBuffer(); 582*67477Smckusick DELAY(10); 583*67477Smckusick return; 584*67477Smckusick } 585*67477Smckusick } 586*67477Smckusick dcaddr->dc_tdr = dc_brk[unit >> 2] | *dp->p_mem++; 58752130Smckusick MachEmptyWriteBuffer(); 58852130Smckusick DELAY(10); 58952130Smckusick return; 59052130Smckusick } 59152130Smckusick tp->t_state &= ~TS_BUSY; 59252130Smckusick if (tp->t_state & TS_FLUSH) 59352130Smckusick tp->t_state &= ~TS_FLUSH; 59452130Smckusick else { 595*67477Smckusick ndflush(&tp->t_outq, dp->p_mem - tp->t_outq.c_cf); 59652130Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 59752130Smckusick } 59852130Smckusick if (tp->t_line) 59952130Smckusick (*linesw[tp->t_line].l_start)(tp); 60052130Smckusick else 60152130Smckusick dcstart(tp); 60252130Smckusick if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 60358975Sralph dcaddr = (dcregs *)dp->p_addr; 604*67477Smckusick dcaddr->dc_tcr &= ~(1 << (unit & 03)); 60552130Smckusick MachEmptyWriteBuffer(); 60652130Smckusick DELAY(10); 60752130Smckusick } 60852130Smckusick } 60952130Smckusick 61052755Sralph void 61152130Smckusick dcstart(tp) 61252130Smckusick register struct tty *tp; 61352130Smckusick { 61452130Smckusick register struct pdma *dp; 61552130Smckusick register dcregs *dcaddr; 61652130Smckusick register int cc; 617*67477Smckusick int unit, s; 61852130Smckusick 619*67477Smckusick dp = &dcpdma[unit = minor(tp->t_dev)]; 62056819Sralph dcaddr = (dcregs *)dp->p_addr; 62152130Smckusick s = spltty(); 62252130Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 62352130Smckusick goto out; 62452130Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 62552130Smckusick if (tp->t_state & TS_ASLEEP) { 62652130Smckusick tp->t_state &= ~TS_ASLEEP; 62752130Smckusick wakeup((caddr_t)&tp->t_outq); 62852130Smckusick } 62952674Smckusick selwakeup(&tp->t_wsel); 63052130Smckusick } 63152130Smckusick if (tp->t_outq.c_cc == 0) 63252130Smckusick goto out; 63352130Smckusick /* handle console specially */ 63456819Sralph if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { 63552130Smckusick while (tp->t_outq.c_cc > 0) { 63652130Smckusick cc = getc(&tp->t_outq) & 0x7f; 63752863Sralph cnputc(cc); 63852130Smckusick } 63952130Smckusick /* 64052130Smckusick * After we flush the output queue we may need to wake 64152130Smckusick * up the process that made the output. 64252130Smckusick */ 64352130Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 64452130Smckusick if (tp->t_state & TS_ASLEEP) { 64552130Smckusick tp->t_state &= ~TS_ASLEEP; 64652130Smckusick wakeup((caddr_t)&tp->t_outq); 64752130Smckusick } 64852674Smckusick selwakeup(&tp->t_wsel); 64952130Smckusick } 65052130Smckusick goto out; 65152130Smckusick } 652*67477Smckusick cc = ndqb(&tp->t_outq, 0); 65352130Smckusick tp->t_state |= TS_BUSY; 65452130Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 65552130Smckusick dp->p_end += cc; 656*67477Smckusick dcaddr->dc_tcr |= 1 << (unit & 03); 65752130Smckusick MachEmptyWriteBuffer(); 65852130Smckusick out: 65952130Smckusick splx(s); 66052130Smckusick } 66152130Smckusick 66252130Smckusick /* 66352130Smckusick * Stop output on a line. 66452130Smckusick */ 66552130Smckusick /*ARGSUSED*/ 66652130Smckusick dcstop(tp, flag) 66752130Smckusick register struct tty *tp; 66852130Smckusick { 66952130Smckusick register struct pdma *dp; 67052130Smckusick register int s; 67152130Smckusick 67264978Smckusick dp = &dcpdma[minor(tp->t_dev)]; 67352130Smckusick s = spltty(); 67452130Smckusick if (tp->t_state & TS_BUSY) { 67552130Smckusick dp->p_end = dp->p_mem; 67652130Smckusick if (!(tp->t_state & TS_TTSTOP)) 67752130Smckusick tp->t_state |= TS_FLUSH; 67852130Smckusick } 67952130Smckusick splx(s); 68052130Smckusick } 68152130Smckusick 68252130Smckusick dcmctl(dev, bits, how) 68352130Smckusick dev_t dev; 68452130Smckusick int bits, how; 68552130Smckusick { 68652130Smckusick register dcregs *dcaddr; 68752130Smckusick register int unit, mbits; 68852130Smckusick int b, s; 689*67477Smckusick register int tcr, msr; 69052130Smckusick 69152130Smckusick unit = minor(dev); 69252130Smckusick b = 1 << (unit & 03); 69356819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 69452130Smckusick s = spltty(); 695*67477Smckusick /* only channel 2 has modem control on a DECstation 2100/3100 */ 696*67477Smckusick mbits = DML_DTR | DML_RTS | DML_DSR | DML_CAR; 69752693Sralph switch (unit & 03) { 69852693Sralph case 2: 69952130Smckusick mbits = 0; 700*67477Smckusick tcr = dcaddr->dc_tcr; 701*67477Smckusick if (tcr & TCR_DTR2) 70252130Smckusick mbits |= DML_DTR; 703*67477Smckusick if (pmax_boardtype != DS_PMAX && (tcr & TCR_RTS2)) 704*67477Smckusick mbits |= DML_RTS; 70552693Sralph msr = dcaddr->dc_msr; 70652693Sralph if (msr & MSR_CD2) 70752693Sralph mbits |= DML_CAR; 70856819Sralph if (msr & MSR_DSR2) { 70956819Sralph if (pmax_boardtype == DS_PMAX) 71056819Sralph mbits |= DML_CAR | DML_DSR; 71156819Sralph else 71256819Sralph mbits |= DML_DSR; 71356819Sralph } 71452693Sralph break; 71552693Sralph 71652693Sralph case 3: 71756819Sralph if (pmax_boardtype != DS_PMAX) { 71856819Sralph mbits = 0; 719*67477Smckusick tcr = dcaddr->dc_tcr; 720*67477Smckusick if (tcr & TCR_DTR3) 72156819Sralph mbits |= DML_DTR; 722*67477Smckusick if (tcr & TCR_RTS3) 723*67477Smckusick mbits |= DML_RTS; 72456819Sralph msr = dcaddr->dc_msr; 72556819Sralph if (msr & MSR_CD3) 72656819Sralph mbits |= DML_CAR; 72756819Sralph if (msr & MSR_DSR3) 72856819Sralph mbits |= DML_DSR; 72956819Sralph } 73052693Sralph } 73152130Smckusick switch (how) { 73252130Smckusick case DMSET: 73352130Smckusick mbits = bits; 73452130Smckusick break; 73552130Smckusick 73652130Smckusick case DMBIS: 73752130Smckusick mbits |= bits; 73852130Smckusick break; 73952130Smckusick 74052130Smckusick case DMBIC: 74152130Smckusick mbits &= ~bits; 74252130Smckusick break; 74352130Smckusick 74452130Smckusick case DMGET: 74552130Smckusick (void) splx(s); 74652130Smckusick return (mbits); 74752130Smckusick } 74852693Sralph switch (unit & 03) { 74952693Sralph case 2: 750*67477Smckusick tcr = dcaddr->dc_tcr; 75152130Smckusick if (mbits & DML_DTR) 752*67477Smckusick tcr |= TCR_DTR2; 75352130Smckusick else 754*67477Smckusick tcr &= ~TCR_DTR2; 755*67477Smckusick if (pmax_boardtype != DS_PMAX) { 756*67477Smckusick if (mbits & DML_RTS) 757*67477Smckusick tcr |= TCR_RTS2; 758*67477Smckusick else 759*67477Smckusick tcr &= ~TCR_RTS2; 760*67477Smckusick } 761*67477Smckusick dcaddr->dc_tcr = tcr; 76252693Sralph break; 76352693Sralph 76452693Sralph case 3: 76556819Sralph if (pmax_boardtype != DS_PMAX) { 766*67477Smckusick tcr = dcaddr->dc_tcr; 76756819Sralph if (mbits & DML_DTR) 768*67477Smckusick tcr |= TCR_DTR3; 76956819Sralph else 770*67477Smckusick tcr &= ~TCR_DTR3; 771*67477Smckusick if (mbits & DML_RTS) 772*67477Smckusick tcr |= TCR_RTS3; 773*67477Smckusick else 774*67477Smckusick tcr &= ~TCR_RTS3; 775*67477Smckusick dcaddr->dc_tcr = tcr; 77656819Sralph } 77752130Smckusick } 77852130Smckusick if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) 77952130Smckusick dc_tty[unit].t_state |= TS_CARR_ON; 78052130Smckusick (void) splx(s); 78152130Smckusick return (mbits); 78252130Smckusick } 78352130Smckusick 78452130Smckusick /* 78552130Smckusick * This is called by timeout() periodically. 78652130Smckusick * Check to see if modem status bits have changed. 78752130Smckusick */ 78856819Sralph void 78955744Sralph dcscan(arg) 79055744Sralph void *arg; 79152130Smckusick { 79252130Smckusick register dcregs *dcaddr; 79352130Smckusick register struct tty *tp; 794*67477Smckusick register int unit, limit, dtr, dsr; 79552130Smckusick int s; 79652130Smckusick 797*67477Smckusick /* only channel 2 has modem control on a DECstation 2100/3100 */ 798*67477Smckusick dtr = TCR_DTR2; 799*67477Smckusick dsr = MSR_DSR2; 800*67477Smckusick limit = (pmax_boardtype == DS_PMAX) ? 2 : 3; 80152130Smckusick s = spltty(); 802*67477Smckusick for (unit = 2; unit <= limit; unit++, dtr >>= 2, dsr >>= 8) { 803*67477Smckusick tp = &dc_tty[unit]; 804*67477Smckusick dcaddr = (dcregs *)dcpdma[unit].p_addr; 805*67477Smckusick if (dcaddr->dc_msr & dsr) { 806*67477Smckusick /* carrier present */ 807*67477Smckusick if (!(tp->t_state & TS_CARR_ON)) 808*67477Smckusick (void)(*linesw[tp->t_line].l_modem)(tp, 1); 809*67477Smckusick } else if ((tp->t_state & TS_CARR_ON) && 810*67477Smckusick (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 811*67477Smckusick dcaddr->dc_tcr &= ~dtr; 812*67477Smckusick /* 813*67477Smckusick * If we are using hardware flow control and output is stopped, 814*67477Smckusick * then resume transmit. 815*67477Smckusick */ 816*67477Smckusick if ((tp->t_cflag & CCTS_OFLOW) && (tp->t_state & TS_TTSTOP) && 817*67477Smckusick pmax_boardtype != DS_PMAX) { 818*67477Smckusick switch (unit) { 819*67477Smckusick case DCCOMM_PORT: 820*67477Smckusick if (dcaddr->dc_msr & MSR_CTS2) 821*67477Smckusick break; 822*67477Smckusick continue; 823*67477Smckusick 824*67477Smckusick case DCPRINTER_PORT: 825*67477Smckusick if (dcaddr->dc_msr & MSR_CTS3) 826*67477Smckusick break; 827*67477Smckusick continue; 828*67477Smckusick } 829*67477Smckusick tp->t_state &= ~TS_TTSTOP; 830*67477Smckusick dcstart(tp); 831*67477Smckusick } 832*67477Smckusick } 83352130Smckusick splx(s); 83455744Sralph timeout(dcscan, (void *)0, hz); 83552130Smckusick } 83652130Smckusick 83752130Smckusick /* 83852130Smckusick * ---------------------------------------------------------------------------- 83952130Smckusick * 84056819Sralph * dcGetc -- 84152130Smckusick * 84256819Sralph * Read a character from a serial line. 84352130Smckusick * 84452130Smckusick * Results: 84556819Sralph * A character read from the serial port. 84652130Smckusick * 84752130Smckusick * Side effects: 84852130Smckusick * None. 84952130Smckusick * 85052130Smckusick * ---------------------------------------------------------------------------- 85152130Smckusick */ 85252130Smckusick int 85356819Sralph dcGetc(dev) 85456819Sralph dev_t dev; 85552130Smckusick { 85652130Smckusick register dcregs *dcaddr; 85752130Smckusick register int c; 85854146Sralph int s; 85952130Smckusick 86056819Sralph dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; 86152130Smckusick if (!dcaddr) 86252130Smckusick return (0); 86354146Sralph s = spltty(); 86452693Sralph for (;;) { 86552693Sralph if (!(dcaddr->dc_csr & CSR_RDONE)) 86652693Sralph continue; 86752693Sralph c = dcaddr->dc_rbuf; 86852693Sralph DELAY(10); 86956819Sralph if (((c >> 8) & 03) == (minor(dev) & 03)) 87052693Sralph break; 87152693Sralph } 87252693Sralph splx(s); 87356819Sralph return (c & 0xff); 87452693Sralph } 87552693Sralph 87652693Sralph /* 87756819Sralph * Send a char on a port, non interrupt driven. 87852693Sralph */ 87952130Smckusick void 88056819Sralph dcPutc(dev, c) 88156819Sralph dev_t dev; 88252130Smckusick int c; 88352130Smckusick { 88452130Smckusick register dcregs *dcaddr; 88552130Smckusick register u_short tcr; 88652130Smckusick register int timeout; 88756819Sralph int s, line; 88852130Smckusick 88956819Sralph s = spltty(); 89056819Sralph 89156819Sralph dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; 89252130Smckusick tcr = dcaddr->dc_tcr; 89356819Sralph dcaddr->dc_tcr = tcr | (1 << minor(dev)); 89452130Smckusick MachEmptyWriteBuffer(); 89552130Smckusick DELAY(10); 89652130Smckusick while (1) { 89752130Smckusick /* 89852130Smckusick * Wait for transmitter to be not busy. 89952130Smckusick */ 90052130Smckusick timeout = 1000000; 90152130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 90252130Smckusick timeout--; 90352130Smckusick if (timeout == 0) { 90456819Sralph printf("dcPutc: timeout waiting for CSR_TRDY\n"); 90552130Smckusick break; 90652130Smckusick } 90752130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 90852130Smckusick /* 90952130Smckusick * Check to be sure its the right port. 91052130Smckusick */ 91156819Sralph if (line != minor(dev)) { 91252130Smckusick tcr |= 1 << line; 91352130Smckusick dcaddr->dc_tcr &= ~(1 << line); 91452130Smckusick MachEmptyWriteBuffer(); 91552130Smckusick DELAY(10); 91652130Smckusick continue; 91752130Smckusick } 91852130Smckusick /* 91952130Smckusick * Start sending the character. 92052130Smckusick */ 92152130Smckusick dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 92252130Smckusick MachEmptyWriteBuffer(); 92352130Smckusick DELAY(10); 92452130Smckusick /* 92552130Smckusick * Wait for character to be sent. 92652130Smckusick */ 92752130Smckusick while (1) { 92852130Smckusick /* 92952130Smckusick * cc -O bug: this code produces and infinite loop! 93052130Smckusick * while (!(dcaddr->dc_csr & CSR_TRDY)) 93152130Smckusick * ; 93252130Smckusick */ 93352130Smckusick timeout = 1000000; 93452130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 93552130Smckusick timeout--; 93652130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 93756819Sralph if (line != minor(dev)) { 93852130Smckusick tcr |= 1 << line; 93952130Smckusick dcaddr->dc_tcr &= ~(1 << line); 94052130Smckusick MachEmptyWriteBuffer(); 94152130Smckusick DELAY(10); 94252130Smckusick continue; 94352130Smckusick } 94456819Sralph dcaddr->dc_tcr &= ~(1 << minor(dev)); 94552130Smckusick MachEmptyWriteBuffer(); 94652130Smckusick DELAY(10); 94752130Smckusick break; 94852130Smckusick } 94952130Smckusick break; 95052130Smckusick } 95152130Smckusick /* 95252130Smckusick * Enable interrupts for other lines which became ready. 95352130Smckusick */ 95452130Smckusick if (tcr & 0xF) { 95552130Smckusick dcaddr->dc_tcr = tcr; 95652130Smckusick MachEmptyWriteBuffer(); 95752130Smckusick DELAY(10); 95852130Smckusick } 95952130Smckusick 96056819Sralph splx(s); 96152130Smckusick } 96252130Smckusick #endif /* NDC */ 963