xref: /original-bsd/sys/pmax/dev/scc.c (revision 3b43aa51)
1 /*-
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Ralph Campbell and Rick Macklem.
7  *
8  * %sccs.include.redist.c%
9  *
10  *	@(#)scc.c	7.2 (Berkeley) 12/20/92
11  */
12 
13 /*
14  * Mach Operating System
15  * Copyright (c) 1991,1990,1989 Carnegie Mellon University
16  * All Rights Reserved.
17  *
18  * Permission to use, copy, modify and distribute this software and its
19  * documentation is hereby granted, provided that both the copyright
20  * notice and this permission notice appear in all copies of the
21  * software, derivative works or modified versions, and any portions
22  * thereof, and that both notices appear in supporting documentation.
23  *
24  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
25  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
26  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
27  *
28  * Carnegie Mellon requests users of this software to return to
29  *
30  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
31  *  School of Computer Science
32  *  Carnegie Mellon University
33  *  Pittsburgh PA 15213-3890
34  *
35  * any improvements or extensions that they make and grant Carnegie the
36  * rights to redistribute these changes.
37  */
38 
39 #include <scc.h>
40 #if NSCC > 0
41 /*
42  * Intel 82530 dual usart chip driver. Supports the serial port(s) on the
43  * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard
44  * and mouse on the 5000/1xx. (Don't ask me where the A channel signals
45  * are on the 5000/xx.)
46  *
47  * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992.
48  */
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/ioctl.h>
52 #include <sys/tty.h>
53 #include <sys/proc.h>
54 #include <sys/map.h>
55 #include <sys/buf.h>
56 #include <sys/conf.h>
57 #include <sys/file.h>
58 #include <sys/uio.h>
59 #include <sys/kernel.h>
60 #include <sys/syslog.h>
61 
62 #include <machine/pmioctl.h>
63 
64 #include <pmax/dev/device.h>
65 #include <pmax/dev/pdma.h>
66 #include <pmax/dev/sccreg.h>
67 #include <pmax/dev/fbreg.h>
68 
69 #include <pmax/pmax/cons.h>
70 #include <pmax/pmax/pmaxtype.h>
71 
72 extern int pmax_boardtype;
73 extern struct consdev cn_tab;
74 extern void ttrstrt	__P((void *));
75 extern void KBDReset	__P((dev_t, void (*)()));
76 extern void MouseInit	__P((dev_t, void (*)(), int (*)()));
77 
78 /*
79  * Driver information for auto-configuration stuff.
80  */
81 int	sccprobe(), sccopen(), sccparam(), sccGetc();
82 void	sccintr(), sccstart(), sccPutc();
83 struct	driver sccdriver = {
84 	"scc", sccprobe, 0, 0, sccintr,
85 };
86 
87 #define	NSCCLINE 	(NSCC*2)
88 #define	SCCUNIT(dev)	(minor(dev) >> 1)
89 #define	SCCLINE(dev)	(minor(dev) & 0x1)
90 
91 struct	tty scc_tty[NSCCLINE];
92 void	(*sccDivertXInput)();	/* X windows keyboard input routine */
93 void	(*sccMouseEvent)();	/* X windows mouse motion event routine */
94 void	(*sccMouseButtons)();	/* X windows mouse buttons event routine */
95 #ifdef DEBUG
96 int	debugChar;
97 #endif
98 static void scc_modem_intr(), sccreset();
99 
100 struct scc_softc {
101 	struct pdma scc_pdma[2];
102 	struct {
103 		u_char	wr1;
104 		u_char	wr3;
105 		u_char	wr4;
106 		u_char	wr5;
107 		u_char	wr14;
108 	} scc_wreg[2];
109 	int	scc_softCAR;
110 } scc_softc[NSCC];
111 
112 struct speedtab sccspeedtab[] = {
113 	0,	0,
114 	50,	4606,
115 	75,	3070,
116 	110,	2093,
117 	134,	1711,
118 	150,	1534,
119 	300,	766,
120 	600,	382,
121 	1200,	190,
122 	1800,	126,
123 	2400,	94,
124 	4800,	46,
125 	9600,	22,
126 	19200,	10,
127 	38400,	4,
128 	-1,	-1
129 };
130 
131 #ifndef	PORTSELECTOR
132 #define	ISPEED	TTYDEF_SPEED
133 #define	LFLAG	TTYDEF_LFLAG
134 #else
135 #define	ISPEED	B4800
136 #define	LFLAG	(TTYDEF_LFLAG & ~ECHO)
137 #endif
138 
139 /*
140  * Test to see if device is present.
141  * Return true if found and initialized ok.
142  */
143 sccprobe(cp)
144 	register struct pmax_ctlr *cp;
145 {
146 	register struct scc_softc *sc;
147 	register struct pdma *pdp;
148 	register struct tty *tp;
149 	register int cntr;
150 	struct tty ctty;
151 	struct termios cterm;
152 	int s;
153 
154 	if (cp->pmax_unit >= NSCC)
155 		return (0);
156 	if (badaddr(cp->pmax_addr, 2))
157 		return (0);
158 
159 	/*
160 	 * For a remote console, wait a while for previous output to
161 	 * complete.
162 	 */
163 	if (major(cn_tab.cn_dev) == SCCDEV && cn_tab.cn_screen == 0 &&
164 		SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit)
165 		DELAY(10000);
166 
167 	sc = &scc_softc[cp->pmax_unit];
168 	pdp = &sc->scc_pdma[0];
169 
170 	/* init pseudo DMA structures */
171 	tp = &scc_tty[cp->pmax_unit * 2];
172 	for (cntr = 0; cntr < 2; cntr++) {
173 		pdp->p_addr = (void *)cp->pmax_addr;
174 		pdp->p_arg = (int)tp;
175 		pdp->p_fcn = (void (*)())0;
176 		tp->t_addr = (caddr_t)pdp;
177 		tp->t_dev = (dev_t)((cp->pmax_unit << 1) | cntr);
178 		pdp++, tp++;
179 	}
180 	sc->scc_softCAR = cp->pmax_flags | 0x2;
181 
182 	/* reset chip */
183 	sccreset(sc);
184 
185 	/*
186 	 * Special handling for consoles.
187 	 */
188 	if (cn_tab.cn_screen) {
189 		if (cn_tab.cn_kbdgetc == sccGetc) {
190 			if (cp->pmax_unit == 0) {
191 				s = spltty();
192 				ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT);
193 				cterm.c_cflag = CS8;
194 				cterm.c_ospeed = cterm.c_ispeed = 4800;
195 				(void) sccparam(&ctty, &cterm);
196 				DELAY(1000);
197 				KBDReset(ctty.t_dev, sccPutc);
198 				splx(s);
199 			} else if (cp->pmax_unit == 1) {
200 				s = spltty();
201 				ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT);
202 				cterm.c_cflag = CS8 | PARENB | PARODD;
203 				cterm.c_ospeed = cterm.c_ispeed = 4800;
204 				(void) sccparam(&ctty, &cterm);
205 				DELAY(1000);
206 				MouseInit(ctty.t_dev, sccPutc, sccGetc);
207 				splx(s);
208 			}
209 		}
210 	} else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) {
211 		s = spltty();
212 		ctty.t_dev = cn_tab.cn_dev;
213 		cterm.c_cflag = CS8;
214 		cterm.c_ospeed = cterm.c_ispeed = 9600;
215 		(void) sccparam(&ctty, &cterm);
216 		DELAY(1000);
217 		cn_tab.cn_disabled = 0;
218 		splx(s);
219 	}
220 	printf("scc%d at nexus0 csr 0x%x priority %d\n",
221 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
222 	return (1);
223 }
224 
225 /*
226  * Reset the chip.
227  */
228 static void
229 sccreset(sc)
230 	register struct scc_softc *sc;
231 {
232 	register scc_regmap_t *regs;
233 	register u_char val;
234 
235 	regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
236 	/*
237 	 * Chip once-only initialization
238 	 *
239 	 * NOTE: The wiring we assume is the one on the 3min:
240 	 *
241 	 *	out	A-TxD	-->	TxD	keybd or mouse
242 	 *	in	A-RxD	-->	RxD	keybd or mouse
243 	 *	out	A-DTR~	-->	DTR	comm
244 	 *	out	A-RTS~	-->	RTS	comm
245 	 *	in	A-CTS~	-->	SI	comm
246 	 *	in	A-DCD~	-->	RI	comm
247 	 *	in	A-SYNCH~-->	DSR	comm
248 	 *	out	B-TxD	-->	TxD	comm
249 	 *	in	B-RxD	-->	RxD	comm
250 	 *	in	B-RxC	-->	TRxCB	comm
251 	 *	in	B-TxC	-->	RTxCB	comm
252 	 *	out	B-RTS~	-->	SS	comm
253 	 *	in	B-CTS~	-->	CTS	comm
254 	 *	in	B-DCD~	-->	CD	comm
255 	 */
256 	SCC_INIT_REG(regs, SCC_CHANNEL_A);
257 	SCC_INIT_REG(regs, SCC_CHANNEL_B);
258 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);
259 	DELAY(50000);	/*enough ? */
260 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0);
261 
262 	/* program the interrupt vector */
263 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);
264 	SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);
265 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);
266 
267 	/* timing base defaults */
268 	sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;
269 	sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;
270 
271 	/* enable DTR, RTS and SS */
272 	sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;
273 	sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;
274 
275 	/* baud rates */
276 	val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;
277 	sc->scc_wreg[SCC_CHANNEL_B].wr14 = val;
278 	sc->scc_wreg[SCC_CHANNEL_A].wr14 = val;
279 
280 	/* interrupt conditions */
281 	val =	SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |
282 		SCC_WR1_EXT_IE;
283 	sc->scc_wreg[SCC_CHANNEL_A].wr1 = val;
284 	sc->scc_wreg[SCC_CHANNEL_B].wr1 = val;
285 }
286 
287 sccopen(dev, flag, mode, p)
288 	dev_t dev;
289 	int flag, mode;
290 	struct proc *p;
291 {
292 	register struct scc_softc *sc;
293 	register struct tty *tp;
294 	register int unit, line;
295 	int s, error = 0;
296 
297 	unit = SCCUNIT(dev);
298 	if (unit >= NSCC)
299 		return (ENXIO);
300 	line = SCCLINE(dev);
301 	sc = &scc_softc[unit];
302 	if (sc->scc_pdma[line].p_addr == (void *)0)
303 		return (ENXIO);
304 	tp = &scc_tty[minor(dev)];
305 	tp->t_addr = (caddr_t)&sc->scc_pdma[line];
306 	tp->t_oproc = sccstart;
307 	tp->t_param = sccparam;
308 	tp->t_dev = dev;
309 	if ((tp->t_state & TS_ISOPEN) == 0) {
310 		tp->t_state |= TS_WOPEN;
311 		ttychars(tp);
312 #ifndef PORTSELECTOR
313 		if (tp->t_ispeed == 0) {
314 #endif
315 			tp->t_iflag = TTYDEF_IFLAG;
316 			tp->t_oflag = TTYDEF_OFLAG;
317 			tp->t_cflag = TTYDEF_CFLAG;
318 			tp->t_lflag = LFLAG;
319 			tp->t_ispeed = tp->t_ospeed = ISPEED;
320 #ifdef PORTSELECTOR
321 			tp->t_cflag |= HUPCL;
322 #else
323 		}
324 #endif
325 		(void) sccparam(tp, &tp->t_termios);
326 		ttsetwater(tp);
327 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
328 		return (EBUSY);
329 	(void) sccmctl(dev, DML_DTR, DMSET);
330 	s = spltty();
331 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
332 	       !(tp->t_state & TS_CARR_ON)) {
333 		tp->t_state |= TS_WOPEN;
334 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
335 		    ttopen, 0))
336 			break;
337 	}
338 	splx(s);
339 	if (error)
340 		return (error);
341 	return ((*linesw[tp->t_line].l_open)(dev, tp));
342 }
343 
344 /*ARGSUSED*/
345 sccclose(dev, flag, mode, p)
346 	dev_t dev;
347 	int flag, mode;
348 	struct proc *p;
349 {
350 	register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)];
351 	register struct tty *tp;
352 	register int bit, line;
353 
354 	tp = &scc_tty[minor(dev)];
355 	line = SCCLINE(dev);
356 	if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) {
357 		sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK;
358 		ttyoutput(0, tp);
359 	}
360 	(*linesw[tp->t_line].l_close)(tp, flag);
361 	if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
362 	    !(tp->t_state & TS_ISOPEN))
363 		(void) sccmctl(dev, 0, DMSET);
364 	return (ttyclose(tp));
365 }
366 
367 sccread(dev, uio, flag)
368 	dev_t dev;
369 	struct uio *uio;
370 {
371 	register struct tty *tp;
372 
373 	tp = &scc_tty[minor(dev)];
374 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
375 }
376 
377 sccwrite(dev, uio, flag)
378 	dev_t dev;
379 	struct uio *uio;
380 {
381 	register struct tty *tp;
382 
383 	tp = &scc_tty[minor(dev)];
384 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
385 }
386 
387 /*ARGSUSED*/
388 sccioctl(dev, cmd, data, flag, p)
389 	dev_t dev;
390 	int cmd;
391 	caddr_t data;
392 	int flag;
393 	struct proc *p;
394 {
395 	register struct scc_softc *sc;
396 	register struct tty *tp;
397 	int error, line;
398 
399 	tp = &scc_tty[minor(dev)];
400 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
401 	if (error >= 0)
402 		return (error);
403 	error = ttioctl(tp, cmd, data, flag);
404 	if (error >= 0)
405 		return (error);
406 
407 	line = SCCLINE(dev);
408 	sc = &scc_softc[SCCUNIT(dev)];
409 	switch (cmd) {
410 
411 	case TIOCSBRK:
412 		sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK;
413 		ttyoutput(0, tp);
414 		break;
415 
416 	case TIOCCBRK:
417 		sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK;
418 		ttyoutput(0, tp);
419 		break;
420 
421 	case TIOCSDTR:
422 		(void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS);
423 		break;
424 
425 	case TIOCCDTR:
426 		(void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC);
427 		break;
428 
429 	case TIOCMSET:
430 		(void) sccmctl(dev, *(int *)data, DMSET);
431 		break;
432 
433 	case TIOCMBIS:
434 		(void) sccmctl(dev, *(int *)data, DMBIS);
435 		break;
436 
437 	case TIOCMBIC:
438 		(void) sccmctl(dev, *(int *)data, DMBIC);
439 		break;
440 
441 	case TIOCMGET:
442 		*(int *)data = sccmctl(dev, 0, DMGET);
443 		break;
444 
445 	default:
446 		return (ENOTTY);
447 	}
448 	return (0);
449 }
450 
451 sccparam(tp, t)
452 	register struct tty *tp;
453 	register struct termios *t;
454 {
455 	register struct scc_softc *sc;
456 	register scc_regmap_t *regs;
457 	register int line;
458 	register u_char value, wvalue;
459 	register int cflag = t->c_cflag;
460 	int ospeed;
461 
462         if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
463                 return (EINVAL);
464 	sc = &scc_softc[SCCUNIT(tp->t_dev)];
465 	line = SCCLINE(tp->t_dev);
466 	regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
467 	ospeed = ttspeedtab(t->c_ospeed, sccspeedtab);
468         if (ospeed < 0)
469                 return (EINVAL);
470         /* and copy to tty */
471         tp->t_ispeed = t->c_ispeed;
472         tp->t_ospeed = t->c_ospeed;
473         tp->t_cflag = cflag;
474 
475 	/*
476 	 * Handle console specially.
477 	 */
478 	if (cn_tab.cn_screen) {
479 		if (minor(tp->t_dev) == SCCKBD_PORT) {
480 			cflag = CS8;
481 			ospeed = ttspeedtab(4800, sccspeedtab);
482 		} else if (minor(tp->t_dev) == SCCMOUSE_PORT) {
483 			cflag = CS8 | PARENB | PARODD;
484 			ospeed = ttspeedtab(4800, sccspeedtab);
485 		}
486 	} else if (tp->t_dev == cn_tab.cn_dev) {
487 		cflag = CS8;
488 		ospeed = ttspeedtab(9600, sccspeedtab);
489 	}
490 	if (ospeed == 0) {
491 		(void) sccmctl(tp->t_dev, 0, DMSET);	/* hang up line */
492 		return (0);
493 	}
494 
495 	/* reset line */
496 	if (line == SCC_CHANNEL_A)
497 		value = SCC_WR9_RESET_CHA_A;
498 	else
499 		value = SCC_WR9_RESET_CHA_B;
500 	SCC_WRITE_REG(regs, line, SCC_WR9, value);
501 	DELAY(25);
502 
503 	/* stop bits, normally 1 */
504 	value = sc->scc_wreg[line].wr4 & 0xf0;
505 	if (cflag & CSTOPB)
506 		value |= SCC_WR4_2_STOP;
507 	else
508 		value |= SCC_WR4_1_STOP;
509 	if ((cflag & PARODD) == 0)
510 		value |= SCC_WR4_EVEN_PARITY;
511 	if (cflag & PARENB)
512 		value |= SCC_WR4_PARITY_ENABLE;
513 
514 	/* set it now, remember it must be first after reset */
515 	sc->scc_wreg[line].wr4 = value;
516 	SCC_WRITE_REG(regs, line, SCC_WR4, value);
517 
518 	/* vector again */
519 	SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0);
520 
521 	/* clear break, keep rts dtr */
522 	wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS);
523 	switch (cflag & CSIZE) {
524 	case CS5:
525 		value = SCC_WR3_RX_5_BITS;
526 		wvalue |= SCC_WR5_TX_5_BITS;
527 		break;
528 	case CS6:
529 		value = SCC_WR3_RX_6_BITS;
530 		wvalue |= SCC_WR5_TX_6_BITS;
531 		break;
532 	case CS7:
533 		value = SCC_WR3_RX_7_BITS;
534 		wvalue |= SCC_WR5_TX_7_BITS;
535 		break;
536 	case CS8:
537 	default:
538 		value = SCC_WR3_RX_8_BITS;
539 		wvalue |= SCC_WR5_TX_8_BITS;
540 	};
541 	sc->scc_wreg[line].wr3 = value;
542 	SCC_WRITE_REG(regs, line, SCC_WR3, value);
543 	sc->scc_wreg[line].wr5 = wvalue;
544 	SCC_WRITE_REG(regs, line, SCC_WR5, wvalue);
545 	SCC_WRITE_REG(regs, line, SCC_WR6, 0);
546 	SCC_WRITE_REG(regs, line, SCC_WR7, 0);
547 	SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS);
548 	SCC_WRITE_REG(regs, line, SCC_WR10, 0);
549 	value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR |
550 		SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR;
551 	SCC_WRITE_REG(regs, line, SCC_WR11, value);
552 	SCC_SET_TIMING_BASE(regs, line, ospeed);
553 	value = sc->scc_wreg[line].wr14;
554 	SCC_WRITE_REG(regs, line, SCC_WR14, value);
555 	value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE;
556 	SCC_WRITE_REG(regs, line, SCC_WR15, value);
557 
558 	/* and now the enables */
559 	value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE;
560 	SCC_WRITE_REG(regs, line, SCC_WR3, value);
561 	value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE;
562 	sc->scc_wreg[line].wr5 = value;
563 	SCC_WRITE_REG(regs, line, SCC_WR5, value);
564 
565 	/* master inter enable */
566 	value = SCC_WR9_MASTER_IE | SCC_WR9_VIS;
567 	SCC_WRITE_REG(regs, line, SCC_WR9, value);
568 	SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1);
569 	MachEmptyWriteBuffer();
570 	return (0);
571 }
572 
573 /*
574  * Check for interrupts from all devices.
575  */
576 void
577 sccintr(unit)
578 	register int unit;
579 {
580 	register scc_regmap_t *regs;
581 	register struct tty *tp;
582 	register struct pdma *dp;
583 	register struct scc_softc *sc;
584 	register int cc, chan, rr1, rr2, rr3;
585 	int overrun = 0;
586 
587 	sc = &scc_softc[unit];
588 	regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
589 	unit <<= 1;
590 	for (;;) {
591 	    SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
592 	    rr2 = SCC_RR2_STATUS(rr2);
593 	    /* are we done yet ? */
594 	    if (rr2 == 6) {	/* strange, distinguished value */
595 		SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3);
596 		if (rr3 == 0)
597 			return;
598 	    }
599 
600 	    SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
601 	    if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
602 		chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
603 			SCC_CHANNEL_A : SCC_CHANNEL_B;
604 		tp = &scc_tty[unit | chan];
605 		dp = (struct pdma *)tp->t_addr;
606 		if (dp->p_mem < dp->p_end) {
607 			SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
608 			MachEmptyWriteBuffer();
609 		} else {
610 			tp->t_state &= ~TS_BUSY;
611 			if (tp->t_state & TS_FLUSH)
612 				tp->t_state &= ~TS_FLUSH;
613 			else {
614 				ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
615 				dp->p_end = dp->p_mem = tp->t_outq.c_cf;
616 			}
617 			if (tp->t_line)
618 				(*linesw[tp->t_line].l_start)(tp);
619 			else
620 				sccstart(tp);
621 			if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
622 				SCC_READ_REG(regs, chan, SCC_RR15, cc);
623 				cc &= ~SCC_WR15_TX_UNDERRUN_IE;
624 				SCC_WRITE_REG(regs, chan, SCC_WR15, cc);
625 				cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE;
626 				SCC_WRITE_REG(regs, chan, SCC_WR1, cc);
627 				sc->scc_wreg[chan].wr1 = cc;
628 				MachEmptyWriteBuffer();
629 			}
630 		}
631 	    } else if (rr2 == SCC_RR2_A_RECV_DONE ||
632 		rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL ||
633 		rr2 == SCC_RR2_B_RECV_SPECIAL) {
634 		if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL)
635 			chan = SCC_CHANNEL_A;
636 		else
637 			chan = SCC_CHANNEL_B;
638 		tp = &scc_tty[unit | chan];
639 		SCC_READ_DATA(regs, chan, cc);
640 		if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
641 			rr2 == SCC_RR2_B_RECV_SPECIAL) {
642 			SCC_READ_REG(regs, chan, SCC_RR1, rr1);
643 			SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR);
644 			if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) {
645 				log(LOG_WARNING, "scc%d,%d: silo overflow\n",
646 					unit >> 1, chan);
647 				overrun = 1;
648 			}
649 		}
650 
651 		/*
652 		 * Keyboard needs special treatment.
653 		 */
654 		if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) {
655 #ifdef KADB
656 			if (cc == LK_DO) {
657 				spl0();
658 				kdbpanic();
659 				return;
660 			}
661 #endif
662 #ifdef DEBUG
663 			debugChar = cc;
664 #endif
665 			if (sccDivertXInput) {
666 				(*sccDivertXInput)(cc);
667 				continue;
668 			}
669 			if ((cc = kbdMapChar(cc)) < 0)
670 				continue;
671 		/*
672 		 * Now for mousey
673 		 */
674 		} else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) {
675 			register MouseReport *mrp;
676 			static MouseReport currentRep;
677 
678 			mrp = &currentRep;
679 			mrp->byteCount++;
680 			if (cc & MOUSE_START_FRAME) {
681 				/*
682 				 * The first mouse report byte (button state).
683 				 */
684 				mrp->state = cc;
685 				if (mrp->byteCount > 1)
686 					mrp->byteCount = 1;
687 			} else if (mrp->byteCount == 2) {
688 				/*
689 				 * The second mouse report byte (delta x).
690 				 */
691 				mrp->dx = cc;
692 			} else if (mrp->byteCount == 3) {
693 				/*
694 				 * The final mouse report byte (delta y).
695 				 */
696 				mrp->dy = cc;
697 				mrp->byteCount = 0;
698 				if (mrp->dx != 0 || mrp->dy != 0) {
699 					/*
700 					 * If the mouse moved,
701 					 * post a motion event.
702 					 */
703 					(*sccMouseEvent)(mrp);
704 				}
705 				(*sccMouseButtons)(mrp);
706 			}
707 			continue;
708 		}
709 		if (!(tp->t_state & TS_ISOPEN)) {
710 			wakeup((caddr_t)&tp->t_rawq);
711 #ifdef PORTSELECTOR
712 			if (!(tp->t_state & TS_WOPEN))
713 #endif
714 				continue;
715 		}
716 		if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
717 			rr2 == SCC_RR2_B_RECV_SPECIAL) {
718 			if (rr1 & SCC_RR1_PARITY_ERR)
719 				cc |= TTY_PE;
720 			if (rr1 & SCC_RR1_FRAME_ERR)
721 				cc |= TTY_FE;
722 		}
723 		(*linesw[tp->t_line].l_rint)(cc, tp);
724 	    } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
725 		chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
726 			SCC_CHANNEL_A : SCC_CHANNEL_B;
727 		SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
728 		scc_modem_intr(unit | chan);
729 	    }
730 	}
731 }
732 
733 void
734 sccstart(tp)
735 	register struct tty *tp;
736 {
737 	register struct pdma *dp;
738 	register scc_regmap_t *regs;
739 	register struct scc_softc *sc;
740 	register int cc, chan;
741 	u_char temp;
742 	int s, sendone;
743 
744 	dp = (struct pdma *)tp->t_addr;
745 	regs = (scc_regmap_t *)dp->p_addr;
746 	sc = &scc_softc[SCCUNIT(tp->t_dev)];
747 	s = spltty();
748 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
749 		goto out;
750 	if (tp->t_outq.c_cc <= tp->t_lowat) {
751 		if (tp->t_state & TS_ASLEEP) {
752 			tp->t_state &= ~TS_ASLEEP;
753 			wakeup((caddr_t)&tp->t_outq);
754 		}
755 		selwakeup(&tp->t_wsel);
756 	}
757 	if (tp->t_outq.c_cc == 0)
758 		goto out;
759 	/* handle console specially */
760 	if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) {
761 		while (tp->t_outq.c_cc > 0) {
762 			cc = getc(&tp->t_outq) & 0x7f;
763 			cnputc(cc);
764 		}
765 		/*
766 		 * After we flush the output queue we may need to wake
767 		 * up the process that made the output.
768 		 */
769 		if (tp->t_outq.c_cc <= tp->t_lowat) {
770 			if (tp->t_state & TS_ASLEEP) {
771 				tp->t_state &= ~TS_ASLEEP;
772 				wakeup((caddr_t)&tp->t_outq);
773 			}
774 			selwakeup(&tp->t_wsel);
775 		}
776 		goto out;
777 	}
778 	if (tp->t_flags & (RAW|LITOUT))
779 		cc = ndqb(&tp->t_outq, 0);
780 	else {
781 		cc = ndqb(&tp->t_outq, 0200);
782 		if (cc == 0) {
783 			cc = getc(&tp->t_outq);
784 			timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6);
785 			tp->t_state |= TS_TIMEOUT;
786 			goto out;
787 		}
788 	}
789 	tp->t_state |= TS_BUSY;
790 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
791 	dp->p_end += cc;
792 
793 	/*
794 	 * Enable transmission and send the first char, as required.
795 	 */
796 	chan = SCCLINE(tp->t_dev);
797 	SCC_READ_REG(regs, chan, SCC_RR0, temp);
798 	sendone = (temp & SCC_RR0_TX_EMPTY);
799 	SCC_READ_REG(regs, chan, SCC_RR15, temp);
800 	temp |= SCC_WR15_TX_UNDERRUN_IE;
801 	SCC_WRITE_REG(regs, chan, SCC_WR15, temp);
802 	temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE;
803 	SCC_WRITE_REG(regs, chan, SCC_WR1, temp);
804 	sc->scc_wreg[chan].wr1 = temp;
805 	if (sendone) {
806 #ifdef DIAGNOSTIC
807 		if (cc == 0)
808 			panic("sccstart: No chars");
809 #endif
810 		SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
811 	}
812 	MachEmptyWriteBuffer();
813 out:
814 	splx(s);
815 }
816 
817 /*
818  * Stop output on a line.
819  */
820 /*ARGSUSED*/
821 sccstop(tp, flag)
822 	register struct tty *tp;
823 {
824 	register struct pdma *dp;
825 	register int s;
826 
827 	dp = (struct pdma *)tp->t_addr;
828 	s = spltty();
829 	if (tp->t_state & TS_BUSY) {
830 		dp->p_end = dp->p_mem;
831 		if (!(tp->t_state & TS_TTSTOP))
832 			tp->t_state |= TS_FLUSH;
833 	}
834 	splx(s);
835 }
836 
837 sccmctl(dev, bits, how)
838 	dev_t dev;
839 	int bits, how;
840 {
841 	register struct scc_softc *sc;
842 	register scc_regmap_t *regs;
843 	register int line, mbits;
844 	register u_char value;
845 	int s;
846 
847 	sc = &scc_softc[SCCUNIT(dev)];
848 	line = SCCLINE(dev);
849 	regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
850 	s = spltty();
851 	/*
852 	 * only channel B has modem control, however the DTR and RTS
853 	 * pins on the comm port are wired to the DTR and RTS A channel
854 	 * signals.
855 	 */
856 	mbits = DML_DTR | DML_DSR | DML_CAR;
857 	if (line == SCC_CHANNEL_B) {
858 		if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & SCC_WR5_DTR)
859 			mbits = DML_DTR | DML_DSR;
860 		else
861 			mbits = 0;
862 		SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value);
863 		if (value & SCC_RR0_DCD)
864 			mbits |= DML_CAR;
865 	}
866 	switch (how) {
867 	case DMSET:
868 		mbits = bits;
869 		break;
870 
871 	case DMBIS:
872 		mbits |= bits;
873 		break;
874 
875 	case DMBIC:
876 		mbits &= ~bits;
877 		break;
878 
879 	case DMGET:
880 		(void) splx(s);
881 		return (mbits);
882 	}
883 	if (line == SCC_CHANNEL_B) {
884 		if (mbits & DML_DTR)
885 			sc->scc_wreg[SCC_CHANNEL_A].wr5 |= SCC_WR5_DTR;
886 		else
887 			sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~SCC_WR5_DTR;
888 		SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5,
889 			sc->scc_wreg[SCC_CHANNEL_A].wr5);
890 	}
891 	if ((mbits & DML_DTR) && (sc->scc_softCAR & (1 << line)))
892 		scc_tty[minor(dev)].t_state |= TS_CARR_ON;
893 	(void) splx(s);
894 	return (mbits);
895 }
896 
897 /*
898  * Check for carrier transition.
899  */
900 static void
901 scc_modem_intr(dev)
902 	dev_t dev;
903 {
904 	register scc_regmap_t *regs;
905 	register struct scc_softc *sc;
906 	register struct tty *tp;
907 	register int car, chan;
908 	register u_char value;
909 	int s;
910 
911 	sc = &scc_softc[SCCUNIT(dev)];
912 	tp = &scc_tty[minor(dev)];
913 	regs = (scc_regmap_t *)((struct pdma *)tp->t_addr)->p_addr;
914 	chan = SCCLINE(dev);
915 	if (chan == SCC_CHANNEL_A)
916 		return;
917 	s = spltty();
918 	if (sc->scc_softCAR & (1 << chan))
919 		car = 1;
920 	else {
921 		SCC_READ_REG_ZERO(regs, chan, value);
922 		car = value & SCC_RR0_DCD;
923 	}
924 	if (car) {
925 		/* carrier present */
926 		if (!(tp->t_state & TS_CARR_ON))
927 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
928 	} else if (tp->t_state & TS_CARR_ON)
929 		(void)(*linesw[tp->t_line].l_modem)(tp, 0);
930 	splx(s);
931 }
932 
933 /*
934  * Get a char off the appropriate line via. a busy wait loop.
935  */
936 int
937 sccGetc(dev)
938 	dev_t dev;
939 {
940 	register scc_regmap_t *regs;
941 	register int c, line;
942 	register u_char value;
943 	int s;
944 
945 	line = SCCLINE(dev);
946 	regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr;
947 	if (!regs)
948 		return (0);
949 	s = spltty();
950 	for (;;) {
951 		SCC_READ_REG(regs, line, SCC_RR0, value);
952 		if (value & SCC_RR0_RX_AVAIL) {
953 			SCC_READ_REG(regs, line, SCC_RR1, value);
954 			if (value & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN |
955 				SCC_RR1_FRAME_ERR)) {
956 				SCC_WRITE_REG(regs, line, SCC_WR0, SCC_RESET_ERROR);
957 				SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
958 					SCC_RESET_HIGHEST_IUS);
959 			} else {
960 				SCC_READ_DATA(regs, line, c);
961 				SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
962 					SCC_RESET_HIGHEST_IUS);
963 				splx(s);
964 				return (c & 0xff);
965 			}
966 		} else
967 			DELAY(10);
968 	}
969 }
970 
971 /*
972  * Send a char on a port, via a busy wait loop.
973  */
974 void
975 sccPutc(dev, c)
976 	dev_t dev;
977 	int c;
978 {
979 	register scc_regmap_t *regs;
980 	register int line;
981 	register u_char value;
982 	int s;
983 
984 	s = spltty();
985 	line = SCCLINE(dev);
986 	regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr;
987 
988 	/*
989 	 * Wait for transmitter to be not busy.
990 	 */
991 	do {
992 		SCC_READ_REG(regs, line, SCC_RR0, value);
993 		if (value & SCC_RR0_TX_EMPTY)
994 			break;
995 		DELAY(100);
996 	} while (1);
997 
998 	/*
999 	 * Send the char.
1000 	 */
1001 	SCC_WRITE_DATA(regs, line, c);
1002 	MachEmptyWriteBuffer();
1003 	splx(s);
1004 }
1005 #endif /* NSCC */
1006