1*56819Sralph /*- 2*56819Sralph * Copyright (c) 1992 The Regents of the University of California. 352130Smckusick * All rights reserved. 452130Smckusick * 552130Smckusick * This code is derived from software contributed to Berkeley by 6*56819Sralph * Ralph Campbell and Rick Macklem. 7*56819Sralph * 8*56819Sralph * %sccs.include.redist.c% 9*56819Sralph * 10*56819Sralph * @(#)dc.c 7.11 (Berkeley) 11/15/92 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 31*56819Sralph #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> 50*56819Sralph #include <machine/pmioctl.h> 5152130Smckusick 52*56819Sralph #include <pmax/pmax/pmaxtype.h> 53*56819Sralph #include <pmax/pmax/cons.h> 54*56819Sralph 5556525Sbostic #include <pmax/dev/device.h> 5656525Sbostic #include <pmax/dev/pdma.h> 57*56819Sralph #include <pmax/dev/fbreg.h> 5852130Smckusick 59*56819Sralph extern int pmax_boardtype; 60*56819Sralph extern struct consdev cn_tab; 61*56819Sralph 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 73*56819Sralph void dcstart __P((struct tty *)); 74*56819Sralph void dcxint __P((struct tty *)); 75*56819Sralph void dcPutc __P((dev_t, int)); 76*56819Sralph void dcscan __P((void *)); 7756226Sralph extern void ttrstrt __P((void *)); 78*56819Sralph int dcGetc __P((dev_t)); 79*56819Sralph int dcparam __P((struct tty *, struct termios *)); 80*56819Sralph extern void KBDReset __P((dev_t, void (*)())); 81*56819Sralph extern void MouseInit __P((dev_t, void (*)(), int (*)())); 8252130Smckusick 8352130Smckusick struct tty dc_tty[NDCLINE]; 8452130Smckusick int dc_cnt = NDCLINE; 8552863Sralph void (*dcDivertXInput)(); /* X windows keyboard input routine */ 8652863Sralph void (*dcMouseEvent)(); /* X windows mouse motion event routine */ 8752863Sralph void (*dcMouseButtons)(); /* X windows mouse buttons event routine */ 8852130Smckusick #ifdef DEBUG 8952130Smckusick int debugChar; 9052130Smckusick #endif 9152130Smckusick 9252130Smckusick /* 9352130Smckusick * Software copy of brk register since it isn't readable 9452130Smckusick */ 9552130Smckusick int dc_brk[NDC]; 9652130Smckusick char dcsoftCAR[NDC]; /* mask of dc's with carrier on (DSR) */ 9752130Smckusick 9852130Smckusick /* 9952130Smckusick * The DC7085 doesn't interrupt on carrier transitions, so 10052130Smckusick * we have to use a timer to watch it. 10152130Smckusick */ 10252130Smckusick int dc_timer; /* true if timer started */ 10352130Smckusick 10452130Smckusick /* 10552130Smckusick * Pdma structures for fast output code 10652130Smckusick */ 10752130Smckusick struct pdma dcpdma[NDCLINE]; 10852130Smckusick 10952130Smckusick struct speedtab dcspeedtab[] = { 11052130Smckusick 0, 0, 11152130Smckusick 50, LPR_B50, 11252130Smckusick 75, LPR_B75, 11352130Smckusick 110, LPR_B110, 11452130Smckusick 134, LPR_B134, 11552130Smckusick 150, LPR_B150, 11652130Smckusick 300, LPR_B300, 11752130Smckusick 600, LPR_B600, 11852130Smckusick 1200, LPR_B1200, 11952130Smckusick 1800, LPR_B1800, 12052130Smckusick 2400, LPR_B2400, 12152130Smckusick 4800, LPR_B4800, 12252130Smckusick 9600, LPR_B9600, 12352693Sralph 19200, LPR_B19200, 12452130Smckusick -1, -1 12552130Smckusick }; 12652130Smckusick 12752130Smckusick #ifndef PORTSELECTOR 12852130Smckusick #define ISPEED TTYDEF_SPEED 12952130Smckusick #define LFLAG TTYDEF_LFLAG 13052130Smckusick #else 13152130Smckusick #define ISPEED B4800 13252130Smckusick #define LFLAG (TTYDEF_LFLAG & ~ECHO) 13352130Smckusick #endif 13452130Smckusick 13552130Smckusick /* 13652130Smckusick * Test to see if device is present. 13752130Smckusick * Return true if found and initialized ok. 13852130Smckusick */ 13952130Smckusick dcprobe(cp) 14052130Smckusick register struct pmax_ctlr *cp; 14152130Smckusick { 14252130Smckusick register dcregs *dcaddr; 14352130Smckusick register struct pdma *pdp; 14452130Smckusick register struct tty *tp; 14552130Smckusick register int cntr; 146*56819Sralph int s; 14752130Smckusick 14852130Smckusick if (cp->pmax_unit >= NDC) 14952130Smckusick return (0); 15052130Smckusick if (badaddr(cp->pmax_addr, 2)) 15152130Smckusick return (0); 15252130Smckusick 15352130Smckusick /* reset chip */ 15452130Smckusick dcaddr = (dcregs *)cp->pmax_addr; 15552130Smckusick dcaddr->dc_csr = CSR_CLR; 15652130Smckusick MachEmptyWriteBuffer(); 15752130Smckusick while (dcaddr->dc_csr & CSR_CLR) 15852130Smckusick ; 15952130Smckusick dcaddr->dc_csr = CSR_MSE | CSR_TIE | CSR_RIE; 16052130Smckusick 16152130Smckusick /* init pseudo DMA structures */ 16252130Smckusick pdp = &dcpdma[cp->pmax_unit * 4]; 16352130Smckusick tp = &dc_tty[cp->pmax_unit * 4]; 16452130Smckusick for (cntr = 0; cntr < 4; cntr++) { 165*56819Sralph pdp->p_addr = (void *)dcaddr; 16652130Smckusick pdp->p_arg = (int)tp; 16752130Smckusick pdp->p_fcn = dcxint; 16852130Smckusick tp->t_addr = (caddr_t)pdp; 16952130Smckusick pdp++, tp++; 17052130Smckusick } 17152130Smckusick dcsoftCAR[cp->pmax_unit] = cp->pmax_flags | 0xB; 17252130Smckusick 17352130Smckusick if (dc_timer == 0) { 17452130Smckusick dc_timer = 1; 17555744Sralph timeout(dcscan, (void *)0, hz); 17652130Smckusick } 17752693Sralph printf("dc%d at nexus0 csr 0x%x priority %d\n", 17852693Sralph cp->pmax_unit, cp->pmax_addr, cp->pmax_pri); 179*56819Sralph 180*56819Sralph /* 181*56819Sralph * Special handling for consoles. 182*56819Sralph */ 18352130Smckusick if (cp->pmax_unit == 0) { 184*56819Sralph if (cn_tab.cn_screen) { 185*56819Sralph s = spltty(); 186*56819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 187*56819Sralph LPR_B4800 | DCKBD_PORT; 188*56819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 189*56819Sralph LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; 190*56819Sralph MachEmptyWriteBuffer(); 191*56819Sralph KBDReset(makedev(DCDEV, DCKBD_PORT), dcPutc); 192*56819Sralph MouseInit(makedev(DCDEV, DCMOUSE_PORT), dcPutc, dcGetc); 193*56819Sralph splx(s); 194*56819Sralph } else if (major(cn_tab.cn_dev) == DCDEV) { 195*56819Sralph s = spltty(); 196*56819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 197*56819Sralph LPR_B9600 | minor(cn_tab.cn_dev); 198*56819Sralph MachEmptyWriteBuffer(); 199*56819Sralph cn_tab.cn_disabled = 0; 200*56819Sralph splx(s); 201*56819Sralph } 20252130Smckusick } 20352130Smckusick return (1); 20452130Smckusick } 20552130Smckusick 20654146Sralph dcopen(dev, flag, mode, p) 20752130Smckusick dev_t dev; 20854146Sralph int flag, mode; 20954146Sralph struct proc *p; 21052130Smckusick { 21152130Smckusick register struct tty *tp; 21252130Smckusick register int unit; 21352130Smckusick int s, error = 0; 21452130Smckusick 21552130Smckusick unit = minor(dev); 216*56819Sralph if (unit >= dc_cnt || dcpdma[unit].p_addr == (void *)0) 21752130Smckusick return (ENXIO); 21852130Smckusick tp = &dc_tty[unit]; 21952130Smckusick tp->t_addr = (caddr_t)&dcpdma[unit]; 22052130Smckusick tp->t_oproc = dcstart; 22152130Smckusick tp->t_param = dcparam; 22252130Smckusick tp->t_dev = dev; 22352130Smckusick if ((tp->t_state & TS_ISOPEN) == 0) { 22452130Smckusick tp->t_state |= TS_WOPEN; 22552130Smckusick ttychars(tp); 22652130Smckusick #ifndef PORTSELECTOR 22752130Smckusick if (tp->t_ispeed == 0) { 22852130Smckusick #endif 22952130Smckusick tp->t_iflag = TTYDEF_IFLAG; 23052130Smckusick tp->t_oflag = TTYDEF_OFLAG; 23152130Smckusick tp->t_cflag = TTYDEF_CFLAG; 23252130Smckusick tp->t_lflag = LFLAG; 23352130Smckusick tp->t_ispeed = tp->t_ospeed = ISPEED; 23452130Smckusick #ifdef PORTSELECTOR 23552130Smckusick tp->t_cflag |= HUPCL; 23652130Smckusick #else 23752130Smckusick } 23852130Smckusick #endif 23952130Smckusick (void) dcparam(tp, &tp->t_termios); 24052130Smckusick ttsetwater(tp); 24152130Smckusick } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0) 24252130Smckusick return (EBUSY); 24352130Smckusick (void) dcmctl(dev, DML_DTR, DMSET); 24452130Smckusick s = spltty(); 24552130Smckusick while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) && 24652130Smckusick !(tp->t_state & TS_CARR_ON)) { 24752130Smckusick tp->t_state |= TS_WOPEN; 24852130Smckusick if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, 24952130Smckusick ttopen, 0)) 25052130Smckusick break; 25152130Smckusick } 25252130Smckusick splx(s); 25352130Smckusick if (error) 25452130Smckusick return (error); 25552130Smckusick return ((*linesw[tp->t_line].l_open)(dev, tp)); 25652130Smckusick } 25752130Smckusick 25852130Smckusick /*ARGSUSED*/ 25954146Sralph dcclose(dev, flag, mode, p) 26052130Smckusick dev_t dev; 26154146Sralph int flag, mode; 26254146Sralph struct proc *p; 26352130Smckusick { 26452130Smckusick register struct tty *tp; 26552130Smckusick register int unit, bit; 26652130Smckusick 26752130Smckusick unit = minor(dev); 26852130Smckusick tp = &dc_tty[unit]; 26952130Smckusick bit = 1 << ((unit & 03) + 8); 27052130Smckusick if (dc_brk[unit >> 2] & bit) { 27152130Smckusick dc_brk[unit >> 2] &= ~bit; 27252130Smckusick ttyoutput(0, tp); 27352130Smckusick } 27454146Sralph (*linesw[tp->t_line].l_close)(tp, flag); 27552130Smckusick if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) || 27652130Smckusick !(tp->t_state & TS_ISOPEN)) 27752130Smckusick (void) dcmctl(dev, 0, DMSET); 27852130Smckusick return (ttyclose(tp)); 27952130Smckusick } 28052130Smckusick 28152130Smckusick dcread(dev, uio, flag) 28252130Smckusick dev_t dev; 28352130Smckusick struct uio *uio; 28452130Smckusick { 28552130Smckusick register struct tty *tp; 28652130Smckusick 28752130Smckusick tp = &dc_tty[minor(dev)]; 28852130Smckusick return ((*linesw[tp->t_line].l_read)(tp, uio, flag)); 28952130Smckusick } 29052130Smckusick 29152130Smckusick dcwrite(dev, uio, flag) 29252130Smckusick dev_t dev; 29352130Smckusick struct uio *uio; 29452130Smckusick { 29552130Smckusick register struct tty *tp; 29652130Smckusick 29752130Smckusick tp = &dc_tty[minor(dev)]; 29852130Smckusick return ((*linesw[tp->t_line].l_write)(tp, uio, flag)); 29952130Smckusick } 30052130Smckusick 30152130Smckusick /*ARGSUSED*/ 30254146Sralph dcioctl(dev, cmd, data, flag, p) 30352130Smckusick dev_t dev; 304*56819Sralph int cmd; 30552130Smckusick caddr_t data; 30654146Sralph int flag; 30754146Sralph struct proc *p; 30852130Smckusick { 30952130Smckusick register struct tty *tp; 31052130Smckusick register int unit = minor(dev); 31152130Smckusick register int dc = unit >> 2; 31252130Smckusick int error; 31352130Smckusick 31452130Smckusick tp = &dc_tty[unit]; 31554146Sralph error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p); 31652130Smckusick if (error >= 0) 31752130Smckusick return (error); 31852130Smckusick error = ttioctl(tp, cmd, data, flag); 31952130Smckusick if (error >= 0) 32052130Smckusick return (error); 32152130Smckusick 32252130Smckusick switch (cmd) { 32352130Smckusick 32452130Smckusick case TIOCSBRK: 32552130Smckusick dc_brk[dc] |= 1 << ((unit & 03) + 8); 32652130Smckusick ttyoutput(0, tp); 32752130Smckusick break; 32852130Smckusick 32952130Smckusick case TIOCCBRK: 33052130Smckusick dc_brk[dc] &= ~(1 << ((unit & 03) + 8)); 33152130Smckusick ttyoutput(0, tp); 33252130Smckusick break; 33352130Smckusick 33452130Smckusick case TIOCSDTR: 33552130Smckusick (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIS); 33652130Smckusick break; 33752130Smckusick 33852130Smckusick case TIOCCDTR: 33952130Smckusick (void) dcmctl(dev, DML_DTR|DML_RTS, DMBIC); 34052130Smckusick break; 34152130Smckusick 34252130Smckusick case TIOCMSET: 34352130Smckusick (void) dcmctl(dev, *(int *)data, DMSET); 34452130Smckusick break; 34552130Smckusick 34652130Smckusick case TIOCMBIS: 34752130Smckusick (void) dcmctl(dev, *(int *)data, DMBIS); 34852130Smckusick break; 34952130Smckusick 35052130Smckusick case TIOCMBIC: 35152130Smckusick (void) dcmctl(dev, *(int *)data, DMBIC); 35252130Smckusick break; 35352130Smckusick 35452130Smckusick case TIOCMGET: 35552130Smckusick *(int *)data = dcmctl(dev, 0, DMGET); 35652130Smckusick break; 35752130Smckusick 35852130Smckusick default: 35952130Smckusick return (ENOTTY); 36052130Smckusick } 36152130Smckusick return (0); 36252130Smckusick } 36352130Smckusick 36452130Smckusick dcparam(tp, t) 36552130Smckusick register struct tty *tp; 36652130Smckusick register struct termios *t; 36752130Smckusick { 36852130Smckusick register dcregs *dcaddr; 36952130Smckusick register int lpr; 37052130Smckusick register int cflag = t->c_cflag; 37152130Smckusick int unit = minor(tp->t_dev); 37252130Smckusick int ospeed = ttspeedtab(t->c_ospeed, dcspeedtab); 37352130Smckusick 37452130Smckusick /* check requested parameters */ 37552130Smckusick if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed) || 376*56819Sralph (cflag & CSIZE) == CS5 || (cflag & CSIZE) == CS6 || 377*56819Sralph (pmax_boardtype == DS_PMAX && t->c_ospeed == 19200)) 37852130Smckusick return (EINVAL); 37952130Smckusick /* and copy to tty */ 38052130Smckusick tp->t_ispeed = t->c_ispeed; 38152130Smckusick tp->t_ospeed = t->c_ospeed; 38252130Smckusick tp->t_cflag = cflag; 38352130Smckusick 384*56819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 385*56819Sralph 386*56819Sralph /* 387*56819Sralph * Handle console cases specially. 388*56819Sralph */ 389*56819Sralph if (cn_tab.cn_screen) { 390*56819Sralph if (unit == DCKBD_PORT) { 391*56819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 392*56819Sralph LPR_B4800 | DCKBD_PORT; 393*56819Sralph MachEmptyWriteBuffer(); 394*56819Sralph return (0); 395*56819Sralph } else if (unit == DCMOUSE_PORT) { 396*56819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_B4800 | LPR_OPAR | 397*56819Sralph LPR_PARENB | LPR_8_BIT_CHAR | DCMOUSE_PORT; 398*56819Sralph MachEmptyWriteBuffer(); 399*56819Sralph return (0); 400*56819Sralph } 401*56819Sralph } else if (tp->t_dev == cn_tab.cn_dev) { 402*56819Sralph dcaddr->dc_lpr = LPR_RXENAB | LPR_8_BIT_CHAR | 403*56819Sralph LPR_B9600 | unit; 40452130Smckusick MachEmptyWriteBuffer(); 40552130Smckusick return (0); 40652130Smckusick } 40752130Smckusick if (ospeed == 0) { 40852130Smckusick (void) dcmctl(unit, 0, DMSET); /* hang up line */ 40952130Smckusick return (0); 41052130Smckusick } 41152130Smckusick lpr = LPR_RXENAB | ospeed | (unit & 03); 41252130Smckusick if ((cflag & CSIZE) == CS7) 41352130Smckusick lpr |= LPR_7_BIT_CHAR; 41452130Smckusick else 41552130Smckusick lpr |= LPR_8_BIT_CHAR; 41652130Smckusick if (cflag & PARENB) 41752130Smckusick lpr |= LPR_PARENB; 41852130Smckusick if (cflag & PARODD) 41952130Smckusick lpr |= LPR_OPAR; 42052130Smckusick if (cflag & CSTOPB) 42152130Smckusick lpr |= LPR_2_STOP; 42252130Smckusick dcaddr->dc_lpr = lpr; 42352130Smckusick MachEmptyWriteBuffer(); 42452130Smckusick return (0); 42552130Smckusick } 42652130Smckusick 42752693Sralph /* 42852693Sralph * Check for interrupts from all devices. 42952693Sralph */ 43052693Sralph void 43152693Sralph dcintr(unit) 43252693Sralph register int unit; 43352693Sralph { 43452693Sralph register dcregs *dcaddr; 43552693Sralph register unsigned csr; 43652693Sralph 43752693Sralph unit <<= 2; 438*56819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 43952693Sralph while ((csr = dcaddr->dc_csr) & (CSR_RDONE | CSR_TRDY)) { 44052693Sralph if (csr & CSR_RDONE) 44152693Sralph dcrint(unit); 44252693Sralph if (csr & CSR_TRDY) 44352693Sralph dcxint(&dc_tty[unit + ((csr >> 8) & 03)]); 44452693Sralph } 44552693Sralph } 44652693Sralph 44752693Sralph dcrint(unit) 44852693Sralph register int unit; 44952693Sralph { 45052693Sralph register dcregs *dcaddr; 45152693Sralph register struct tty *tp; 45252693Sralph register int c, cc; 45352693Sralph register struct tty *tp0; 45452693Sralph int overrun = 0; 45552693Sralph 456*56819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 45752693Sralph tp0 = &dc_tty[unit]; 45852693Sralph while ((c = dcaddr->dc_rbuf) < 0) { /* char present */ 45952693Sralph cc = c & 0xff; 46052693Sralph tp = tp0 + ((c >> 8) & 03); 46152693Sralph if ((c & RBUF_OERR) && overrun == 0) { 46252693Sralph log(LOG_WARNING, "dc%d,%d: silo overflow\n", unit >> 2, 46352693Sralph (c >> 8) & 03); 46452693Sralph overrun = 1; 46552693Sralph } 46652693Sralph /* the keyboard requires special translation */ 467*56819Sralph if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { 46852693Sralph #ifdef KADB 46952693Sralph if (cc == LK_DO) { 47052693Sralph spl0(); 47152693Sralph kdbpanic(); 47252693Sralph return; 47352693Sralph } 47452693Sralph #endif 47552693Sralph #ifdef DEBUG 47652693Sralph debugChar = cc; 47752693Sralph #endif 47852693Sralph if (dcDivertXInput) { 47952863Sralph (*dcDivertXInput)(cc); 48052693Sralph return; 48152693Sralph } 482*56819Sralph if ((cc = kbdMapChar(cc)) < 0) 48352693Sralph return; 484*56819Sralph } else if (tp == &dc_tty[DCMOUSE_PORT] && dcMouseButtons) { 48552863Sralph register MouseReport *mrp; 48652693Sralph static MouseReport currentRep; 48752693Sralph 48852863Sralph mrp = ¤tRep; 48952863Sralph mrp->byteCount++; 49052693Sralph if (cc & MOUSE_START_FRAME) { 49152693Sralph /* 49252693Sralph * The first mouse report byte (button state). 49352693Sralph */ 49452863Sralph mrp->state = cc; 49552863Sralph if (mrp->byteCount > 1) 49652863Sralph mrp->byteCount = 1; 49752863Sralph } else if (mrp->byteCount == 2) { 49852693Sralph /* 49952693Sralph * The second mouse report byte (delta x). 50052693Sralph */ 50152863Sralph mrp->dx = cc; 50252863Sralph } else if (mrp->byteCount == 3) { 50352693Sralph /* 50452693Sralph * The final mouse report byte (delta y). 50552693Sralph */ 50652863Sralph mrp->dy = cc; 50752863Sralph mrp->byteCount = 0; 50852863Sralph if (mrp->dx != 0 || mrp->dy != 0) { 50952693Sralph /* 51052693Sralph * If the mouse moved, 51152693Sralph * post a motion event. 51252693Sralph */ 51352863Sralph (*dcMouseEvent)(mrp); 51452693Sralph } 51552863Sralph (*dcMouseButtons)(mrp); 51652693Sralph } 51752693Sralph return; 51852693Sralph } 51952693Sralph if (!(tp->t_state & TS_ISOPEN)) { 52052693Sralph wakeup((caddr_t)&tp->t_rawq); 52152693Sralph #ifdef PORTSELECTOR 52252693Sralph if (!(tp->t_state & TS_WOPEN)) 52352693Sralph #endif 52452693Sralph return; 52552693Sralph } 52652693Sralph if (c & RBUF_FERR) 52752693Sralph cc |= TTY_FE; 52852693Sralph if (c & RBUF_PERR) 52952693Sralph cc |= TTY_PE; 53052693Sralph (*linesw[tp->t_line].l_rint)(cc, tp); 53152693Sralph } 53252693Sralph DELAY(10); 53352693Sralph } 53452693Sralph 53552755Sralph void 53652130Smckusick dcxint(tp) 53752130Smckusick register struct tty *tp; 53852130Smckusick { 53952130Smckusick register struct pdma *dp; 54052130Smckusick register dcregs *dcaddr; 54152130Smckusick 54252130Smckusick dp = (struct pdma *)tp->t_addr; 54352130Smckusick if (dp->p_mem < dp->p_end) { 544*56819Sralph dcaddr = (dcregs *)dp->p_addr; 54552130Smckusick dcaddr->dc_tdr = dc_brk[(tp - dc_tty) >> 2] | *dp->p_mem++; 54652130Smckusick MachEmptyWriteBuffer(); 54752130Smckusick DELAY(10); 54852130Smckusick return; 54952130Smckusick } 55052130Smckusick tp->t_state &= ~TS_BUSY; 55152130Smckusick if (tp->t_state & TS_FLUSH) 55252130Smckusick tp->t_state &= ~TS_FLUSH; 55352130Smckusick else { 55452130Smckusick ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf); 55552130Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 55652130Smckusick } 55752130Smckusick if (tp->t_line) 55852130Smckusick (*linesw[tp->t_line].l_start)(tp); 55952130Smckusick else 56052130Smckusick dcstart(tp); 56152130Smckusick if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) { 562*56819Sralph ((dcregs *)dp->p_addr)->dc_tcr &= ~(1 << (minor(tp->t_dev) & 03)); 56352130Smckusick MachEmptyWriteBuffer(); 56452130Smckusick DELAY(10); 56552130Smckusick } 56652130Smckusick } 56752130Smckusick 56852755Sralph void 56952130Smckusick dcstart(tp) 57052130Smckusick register struct tty *tp; 57152130Smckusick { 57252130Smckusick register struct pdma *dp; 57352130Smckusick register dcregs *dcaddr; 57452130Smckusick register int cc; 57552130Smckusick int s; 57652130Smckusick 57752130Smckusick dp = (struct pdma *)tp->t_addr; 578*56819Sralph dcaddr = (dcregs *)dp->p_addr; 57952130Smckusick s = spltty(); 58052130Smckusick if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) 58152130Smckusick goto out; 58252130Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 58352130Smckusick if (tp->t_state & TS_ASLEEP) { 58452130Smckusick tp->t_state &= ~TS_ASLEEP; 58552130Smckusick wakeup((caddr_t)&tp->t_outq); 58652130Smckusick } 58752674Smckusick selwakeup(&tp->t_wsel); 58852130Smckusick } 58952130Smckusick if (tp->t_outq.c_cc == 0) 59052130Smckusick goto out; 59152130Smckusick /* handle console specially */ 592*56819Sralph if (tp == &dc_tty[DCKBD_PORT] && cn_tab.cn_screen) { 59352130Smckusick while (tp->t_outq.c_cc > 0) { 59452130Smckusick cc = getc(&tp->t_outq) & 0x7f; 59552863Sralph cnputc(cc); 59652130Smckusick } 59752130Smckusick /* 59852130Smckusick * After we flush the output queue we may need to wake 59952130Smckusick * up the process that made the output. 60052130Smckusick */ 60152130Smckusick if (tp->t_outq.c_cc <= tp->t_lowat) { 60252130Smckusick if (tp->t_state & TS_ASLEEP) { 60352130Smckusick tp->t_state &= ~TS_ASLEEP; 60452130Smckusick wakeup((caddr_t)&tp->t_outq); 60552130Smckusick } 60652674Smckusick selwakeup(&tp->t_wsel); 60752130Smckusick } 60852130Smckusick goto out; 60952130Smckusick } 61052130Smckusick if (tp->t_flags & (RAW|LITOUT)) 61152130Smckusick cc = ndqb(&tp->t_outq, 0); 61252130Smckusick else { 61352130Smckusick cc = ndqb(&tp->t_outq, 0200); 61452130Smckusick if (cc == 0) { 61552130Smckusick cc = getc(&tp->t_outq); 61655744Sralph timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6); 61752130Smckusick tp->t_state |= TS_TIMEOUT; 61852130Smckusick goto out; 61952130Smckusick } 62052130Smckusick } 62152130Smckusick tp->t_state |= TS_BUSY; 62252130Smckusick dp->p_end = dp->p_mem = tp->t_outq.c_cf; 62352130Smckusick dp->p_end += cc; 62452130Smckusick dcaddr->dc_tcr |= 1 << (minor(tp->t_dev) & 03); 62552130Smckusick MachEmptyWriteBuffer(); 62652130Smckusick out: 62752130Smckusick splx(s); 62852130Smckusick } 62952130Smckusick 63052130Smckusick /* 63152130Smckusick * Stop output on a line. 63252130Smckusick */ 63352130Smckusick /*ARGSUSED*/ 63452130Smckusick dcstop(tp, flag) 63552130Smckusick register struct tty *tp; 63652130Smckusick { 63752130Smckusick register struct pdma *dp; 63852130Smckusick register int s; 63952130Smckusick 64052130Smckusick dp = (struct pdma *)tp->t_addr; 64152130Smckusick s = spltty(); 64252130Smckusick if (tp->t_state & TS_BUSY) { 64352130Smckusick dp->p_end = dp->p_mem; 64452130Smckusick if (!(tp->t_state & TS_TTSTOP)) 64552130Smckusick tp->t_state |= TS_FLUSH; 64652130Smckusick } 64752130Smckusick splx(s); 64852130Smckusick } 64952130Smckusick 65052130Smckusick dcmctl(dev, bits, how) 65152130Smckusick dev_t dev; 65252130Smckusick int bits, how; 65352130Smckusick { 65452130Smckusick register dcregs *dcaddr; 65552130Smckusick register int unit, mbits; 65652130Smckusick int b, s; 65752693Sralph register int msr; 65852130Smckusick 65952130Smckusick unit = minor(dev); 66052130Smckusick b = 1 << (unit & 03); 661*56819Sralph dcaddr = (dcregs *)dcpdma[unit].p_addr; 66252130Smckusick s = spltty(); 66352130Smckusick /* only channel 2 has modem control (what about line 3?) */ 664*56819Sralph mbits = DML_DTR | DML_DSR | DML_CAR; 66552693Sralph switch (unit & 03) { 66652693Sralph case 2: 66752130Smckusick mbits = 0; 66852130Smckusick if (dcaddr->dc_tcr & TCR_DTR2) 66952130Smckusick mbits |= DML_DTR; 67052693Sralph msr = dcaddr->dc_msr; 67152693Sralph if (msr & MSR_CD2) 67252693Sralph mbits |= DML_CAR; 673*56819Sralph if (msr & MSR_DSR2) { 674*56819Sralph if (pmax_boardtype == DS_PMAX) 675*56819Sralph mbits |= DML_CAR | DML_DSR; 676*56819Sralph else 677*56819Sralph mbits |= DML_DSR; 678*56819Sralph } 67952693Sralph break; 68052693Sralph 68152693Sralph case 3: 682*56819Sralph if (pmax_boardtype != DS_PMAX) { 683*56819Sralph mbits = 0; 684*56819Sralph if (dcaddr->dc_tcr & TCR_DTR3) 685*56819Sralph mbits |= DML_DTR; 686*56819Sralph msr = dcaddr->dc_msr; 687*56819Sralph if (msr & MSR_CD3) 688*56819Sralph mbits |= DML_CAR; 689*56819Sralph if (msr & MSR_DSR3) 690*56819Sralph mbits |= DML_DSR; 691*56819Sralph } 69252693Sralph } 69352130Smckusick switch (how) { 69452130Smckusick case DMSET: 69552130Smckusick mbits = bits; 69652130Smckusick break; 69752130Smckusick 69852130Smckusick case DMBIS: 69952130Smckusick mbits |= bits; 70052130Smckusick break; 70152130Smckusick 70252130Smckusick case DMBIC: 70352130Smckusick mbits &= ~bits; 70452130Smckusick break; 70552130Smckusick 70652130Smckusick case DMGET: 70752130Smckusick (void) splx(s); 70852130Smckusick return (mbits); 70952130Smckusick } 71052693Sralph switch (unit & 03) { 71152693Sralph case 2: 71252130Smckusick if (mbits & DML_DTR) 71352130Smckusick dcaddr->dc_tcr |= TCR_DTR2; 71452130Smckusick else 71552130Smckusick dcaddr->dc_tcr &= ~TCR_DTR2; 71652693Sralph break; 71752693Sralph 71852693Sralph case 3: 719*56819Sralph if (pmax_boardtype != DS_PMAX) { 720*56819Sralph if (mbits & DML_DTR) 721*56819Sralph dcaddr->dc_tcr |= TCR_DTR3; 722*56819Sralph else 723*56819Sralph dcaddr->dc_tcr &= ~TCR_DTR3; 724*56819Sralph } 72552130Smckusick } 72652130Smckusick if ((mbits & DML_DTR) && (dcsoftCAR[unit >> 2] & b)) 72752130Smckusick dc_tty[unit].t_state |= TS_CARR_ON; 72852130Smckusick (void) splx(s); 72952130Smckusick return (mbits); 73052130Smckusick } 73152130Smckusick 73252130Smckusick /* 73352130Smckusick * This is called by timeout() periodically. 73452130Smckusick * Check to see if modem status bits have changed. 73552130Smckusick */ 736*56819Sralph void 73755744Sralph dcscan(arg) 73855744Sralph void *arg; 73952130Smckusick { 74052130Smckusick register dcregs *dcaddr; 74152130Smckusick register struct tty *tp; 74252130Smckusick register int i, bit, car; 74352130Smckusick int s; 74452130Smckusick 74552130Smckusick s = spltty(); 74652130Smckusick /* only channel 2 has modem control (what about line 3?) */ 747*56819Sralph dcaddr = (dcregs *)dcpdma[i = 2].p_addr; 74852130Smckusick tp = &dc_tty[i]; 74952130Smckusick bit = TCR_DTR2; 75052130Smckusick if (dcsoftCAR[i >> 2] & bit) 75152130Smckusick car = 1; 75252130Smckusick else 75352130Smckusick car = dcaddr->dc_msr & MSR_DSR2; 75452130Smckusick if (car) { 75552130Smckusick /* carrier present */ 75652130Smckusick if (!(tp->t_state & TS_CARR_ON)) 75752130Smckusick (void)(*linesw[tp->t_line].l_modem)(tp, 1); 75852130Smckusick } else if ((tp->t_state & TS_CARR_ON) && 75952130Smckusick (*linesw[tp->t_line].l_modem)(tp, 0) == 0) 76052130Smckusick dcaddr->dc_tcr &= ~bit; 76152130Smckusick splx(s); 76255744Sralph timeout(dcscan, (void *)0, hz); 76352130Smckusick } 76452130Smckusick 76552130Smckusick /* 76652130Smckusick * ---------------------------------------------------------------------------- 76752130Smckusick * 768*56819Sralph * dcGetc -- 76952130Smckusick * 770*56819Sralph * Read a character from a serial line. 77152130Smckusick * 77252130Smckusick * Results: 773*56819Sralph * A character read from the serial port. 77452130Smckusick * 77552130Smckusick * Side effects: 77652130Smckusick * None. 77752130Smckusick * 77852130Smckusick * ---------------------------------------------------------------------------- 77952130Smckusick */ 78052130Smckusick int 781*56819Sralph dcGetc(dev) 782*56819Sralph dev_t dev; 78352130Smckusick { 78452130Smckusick register dcregs *dcaddr; 78552130Smckusick register int c; 78654146Sralph int s; 78752130Smckusick 788*56819Sralph dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; 78952130Smckusick if (!dcaddr) 79052130Smckusick return (0); 79154146Sralph s = spltty(); 79252693Sralph for (;;) { 79352693Sralph if (!(dcaddr->dc_csr & CSR_RDONE)) 79452693Sralph continue; 79552693Sralph c = dcaddr->dc_rbuf; 79652693Sralph DELAY(10); 797*56819Sralph if (((c >> 8) & 03) == (minor(dev) & 03)) 79852693Sralph break; 79952693Sralph } 80052693Sralph splx(s); 801*56819Sralph return (c & 0xff); 80252693Sralph } 80352693Sralph 80452693Sralph /* 805*56819Sralph * Send a char on a port, non interrupt driven. 80652693Sralph */ 80752130Smckusick void 808*56819Sralph dcPutc(dev, c) 809*56819Sralph dev_t dev; 81052130Smckusick int c; 81152130Smckusick { 81252130Smckusick register dcregs *dcaddr; 81352130Smckusick register u_short tcr; 81452130Smckusick register int timeout; 815*56819Sralph int s, line; 81652130Smckusick 817*56819Sralph s = spltty(); 818*56819Sralph 819*56819Sralph dcaddr = (dcregs *)dcpdma[minor(dev)].p_addr; 82052130Smckusick tcr = dcaddr->dc_tcr; 821*56819Sralph dcaddr->dc_tcr = tcr | (1 << minor(dev)); 82252130Smckusick MachEmptyWriteBuffer(); 82352130Smckusick DELAY(10); 82452130Smckusick while (1) { 82552130Smckusick /* 82652130Smckusick * Wait for transmitter to be not busy. 82752130Smckusick */ 82852130Smckusick timeout = 1000000; 82952130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 83052130Smckusick timeout--; 83152130Smckusick if (timeout == 0) { 832*56819Sralph printf("dcPutc: timeout waiting for CSR_TRDY\n"); 83352130Smckusick break; 83452130Smckusick } 83552130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 83652130Smckusick /* 83752130Smckusick * Check to be sure its the right port. 83852130Smckusick */ 839*56819Sralph if (line != minor(dev)) { 84052130Smckusick tcr |= 1 << line; 84152130Smckusick dcaddr->dc_tcr &= ~(1 << line); 84252130Smckusick MachEmptyWriteBuffer(); 84352130Smckusick DELAY(10); 84452130Smckusick continue; 84552130Smckusick } 84652130Smckusick /* 84752130Smckusick * Start sending the character. 84852130Smckusick */ 84952130Smckusick dcaddr->dc_tdr = dc_brk[0] | (c & 0xff); 85052130Smckusick MachEmptyWriteBuffer(); 85152130Smckusick DELAY(10); 85252130Smckusick /* 85352130Smckusick * Wait for character to be sent. 85452130Smckusick */ 85552130Smckusick while (1) { 85652130Smckusick /* 85752130Smckusick * cc -O bug: this code produces and infinite loop! 85852130Smckusick * while (!(dcaddr->dc_csr & CSR_TRDY)) 85952130Smckusick * ; 86052130Smckusick */ 86152130Smckusick timeout = 1000000; 86252130Smckusick while (!(dcaddr->dc_csr & CSR_TRDY) && timeout > 0) 86352130Smckusick timeout--; 86452130Smckusick line = (dcaddr->dc_csr >> 8) & 3; 865*56819Sralph if (line != minor(dev)) { 86652130Smckusick tcr |= 1 << line; 86752130Smckusick dcaddr->dc_tcr &= ~(1 << line); 86852130Smckusick MachEmptyWriteBuffer(); 86952130Smckusick DELAY(10); 87052130Smckusick continue; 87152130Smckusick } 872*56819Sralph dcaddr->dc_tcr &= ~(1 << minor(dev)); 87352130Smckusick MachEmptyWriteBuffer(); 87452130Smckusick DELAY(10); 87552130Smckusick break; 87652130Smckusick } 87752130Smckusick break; 87852130Smckusick } 87952130Smckusick /* 88052130Smckusick * Enable interrupts for other lines which became ready. 88152130Smckusick */ 88252130Smckusick if (tcr & 0xF) { 88352130Smckusick dcaddr->dc_tcr = tcr; 88452130Smckusick MachEmptyWriteBuffer(); 88552130Smckusick DELAY(10); 88652130Smckusick } 88752130Smckusick 888*56819Sralph splx(s); 88952130Smckusick } 89052130Smckusick #endif /* NDC */ 891