xref: /original-bsd/sys/pmax/dev/scc.c (revision e49f9654)
1 /*-
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  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	8.3 (Berkeley) 06/02/95
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_dev = (dev_t)((cp->pmax_unit << 1) | cntr);
177 		pdp++, tp++;
178 	}
179 	sc->scc_softCAR = cp->pmax_flags | 0x2;
180 
181 	/* reset chip */
182 	sccreset(sc);
183 
184 	/*
185 	 * Special handling for consoles.
186 	 */
187 	if (cn_tab.cn_screen) {
188 		if (cn_tab.cn_kbdgetc == sccGetc) {
189 			if (cp->pmax_unit == 1) {
190 				s = spltty();
191 				ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT);
192 				cterm.c_cflag = CS8;
193 				cterm.c_ospeed = cterm.c_ispeed = 4800;
194 				(void) sccparam(&ctty, &cterm);
195 				DELAY(10000);
196 #ifdef notyet
197 				/*
198 				 * For some reason doing this hangs the 3min
199 				 * during booting. Fortunately the keyboard
200 				 * works ok without it.
201 				 */
202 				KBDReset(ctty.t_dev, sccPutc);
203 #endif
204 				DELAY(10000);
205 				splx(s);
206 			} else if (cp->pmax_unit == 0) {
207 				s = spltty();
208 				ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT);
209 				cterm.c_cflag = CS8 | PARENB | PARODD;
210 				cterm.c_ospeed = cterm.c_ispeed = 4800;
211 				(void) sccparam(&ctty, &cterm);
212 				DELAY(10000);
213 				MouseInit(ctty.t_dev, sccPutc, sccGetc);
214 				DELAY(10000);
215 				splx(s);
216 			}
217 		}
218 	} else if (SCCUNIT(cn_tab.cn_dev) == cp->pmax_unit) {
219 		s = spltty();
220 		ctty.t_dev = cn_tab.cn_dev;
221 		cterm.c_cflag = CS8;
222 		cterm.c_ospeed = cterm.c_ispeed = 9600;
223 		(void) sccparam(&ctty, &cterm);
224 		DELAY(1000);
225 		cn_tab.cn_disabled = 0;
226 		splx(s);
227 	}
228 	printf("scc%d at nexus0 csr 0x%x priority %d\n",
229 		cp->pmax_unit, cp->pmax_addr, cp->pmax_pri);
230 	return (1);
231 }
232 
233 /*
234  * Reset the chip.
235  */
236 static void
237 sccreset(sc)
238 	register struct scc_softc *sc;
239 {
240 	register scc_regmap_t *regs;
241 	register u_char val;
242 
243 	regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
244 	/*
245 	 * Chip once-only initialization
246 	 *
247 	 * NOTE: The wiring we assume is the one on the 3min:
248 	 *
249 	 *	out	A-TxD	-->	TxD	keybd or mouse
250 	 *	in	A-RxD	-->	RxD	keybd or mouse
251 	 *	out	A-DTR~	-->	DTR	comm
252 	 *	out	A-RTS~	-->	RTS	comm
253 	 *	in	A-CTS~	-->	SI	comm
254 	 *	in	A-DCD~	-->	RI	comm
255 	 *	in	A-SYNCH~-->	DSR	comm
256 	 *	out	B-TxD	-->	TxD	comm
257 	 *	in	B-RxD	-->	RxD	comm
258 	 *	in	B-RxC	-->	TRxCB	comm
259 	 *	in	B-TxC	-->	RTxCB	comm
260 	 *	out	B-RTS~	-->	SS	comm
261 	 *	in	B-CTS~	-->	CTS	comm
262 	 *	in	B-DCD~	-->	CD	comm
263 	 */
264 	SCC_INIT_REG(regs, SCC_CHANNEL_A);
265 	SCC_INIT_REG(regs, SCC_CHANNEL_B);
266 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_HW_RESET);
267 	DELAY(50000);	/*enough ? */
268 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0);
269 
270 	/* program the interrupt vector */
271 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR2, 0xf0);
272 	SCC_WRITE_REG(regs, SCC_CHANNEL_B, SCC_WR2, 0xf0);
273 	SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, SCC_WR9_VIS);
274 
275 	/* timing base defaults */
276 	sc->scc_wreg[SCC_CHANNEL_A].wr4 = SCC_WR4_CLK_x16;
277 	sc->scc_wreg[SCC_CHANNEL_B].wr4 = SCC_WR4_CLK_x16;
278 
279 	/* enable DTR, RTS and SS */
280 	sc->scc_wreg[SCC_CHANNEL_B].wr5 = SCC_WR5_RTS;
281 	sc->scc_wreg[SCC_CHANNEL_A].wr5 = SCC_WR5_RTS | SCC_WR5_DTR;
282 
283 	/* baud rates */
284 	val = SCC_WR14_BAUDR_ENABLE|SCC_WR14_BAUDR_SRC;
285 	sc->scc_wreg[SCC_CHANNEL_B].wr14 = val;
286 	sc->scc_wreg[SCC_CHANNEL_A].wr14 = val;
287 
288 	/* interrupt conditions */
289 	val =	SCC_WR1_RXI_ALL_CHAR | SCC_WR1_PARITY_IE |
290 		SCC_WR1_EXT_IE;
291 	sc->scc_wreg[SCC_CHANNEL_A].wr1 = val;
292 	sc->scc_wreg[SCC_CHANNEL_B].wr1 = val;
293 }
294 
295 sccopen(dev, flag, mode, p)
296 	dev_t dev;
297 	int flag, mode;
298 	struct proc *p;
299 {
300 	register struct scc_softc *sc;
301 	register struct tty *tp;
302 	register int unit, line;
303 	int s, error = 0;
304 
305 	unit = SCCUNIT(dev);
306 	if (unit >= NSCC)
307 		return (ENXIO);
308 	line = SCCLINE(dev);
309 	sc = &scc_softc[unit];
310 	if (sc->scc_pdma[line].p_addr == (void *)0)
311 		return (ENXIO);
312 	tp = &scc_tty[minor(dev)];
313 	tp->t_oproc = sccstart;
314 	tp->t_param = sccparam;
315 	tp->t_dev = dev;
316 	if ((tp->t_state & TS_ISOPEN) == 0) {
317 		tp->t_state |= TS_WOPEN;
318 		ttychars(tp);
319 #ifndef PORTSELECTOR
320 		if (tp->t_ispeed == 0) {
321 #endif
322 			tp->t_iflag = TTYDEF_IFLAG;
323 			tp->t_oflag = TTYDEF_OFLAG;
324 			tp->t_cflag = TTYDEF_CFLAG;
325 			tp->t_lflag = LFLAG;
326 			tp->t_ispeed = tp->t_ospeed = ISPEED;
327 #ifdef PORTSELECTOR
328 			tp->t_cflag |= HUPCL;
329 #else
330 		}
331 #endif
332 		(void) sccparam(tp, &tp->t_termios);
333 		ttsetwater(tp);
334 	} else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
335 		return (EBUSY);
336 	(void) sccmctl(dev, DML_DTR, DMSET);
337 	s = spltty();
338 	while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
339 	       !(tp->t_state & TS_CARR_ON)) {
340 		tp->t_state |= TS_WOPEN;
341 		if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
342 		    ttopen, 0))
343 			break;
344 	}
345 	splx(s);
346 	if (error)
347 		return (error);
348 	return ((*linesw[tp->t_line].l_open)(dev, tp));
349 }
350 
351 /*ARGSUSED*/
352 sccclose(dev, flag, mode, p)
353 	dev_t dev;
354 	int flag, mode;
355 	struct proc *p;
356 {
357 	register struct scc_softc *sc = &scc_softc[SCCUNIT(dev)];
358 	register struct tty *tp;
359 	register int bit, line;
360 
361 	tp = &scc_tty[minor(dev)];
362 	line = SCCLINE(dev);
363 	if (sc->scc_wreg[line].wr5 & SCC_WR5_SEND_BREAK) {
364 		sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK;
365 		ttyoutput(0, tp);
366 	}
367 	(*linesw[tp->t_line].l_close)(tp, flag);
368 	if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
369 	    !(tp->t_state & TS_ISOPEN))
370 		(void) sccmctl(dev, 0, DMSET);
371 	return (ttyclose(tp));
372 }
373 
374 sccread(dev, uio, flag)
375 	dev_t dev;
376 	struct uio *uio;
377 {
378 	register struct tty *tp;
379 
380 	tp = &scc_tty[minor(dev)];
381 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
382 }
383 
384 sccwrite(dev, uio, flag)
385 	dev_t dev;
386 	struct uio *uio;
387 {
388 	register struct tty *tp;
389 
390 	tp = &scc_tty[minor(dev)];
391 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
392 }
393 
394 /*ARGSUSED*/
395 sccioctl(dev, cmd, data, flag, p)
396 	dev_t dev;
397 	u_long cmd;
398 	caddr_t data;
399 	int flag;
400 	struct proc *p;
401 {
402 	register struct scc_softc *sc;
403 	register struct tty *tp;
404 	int error, line;
405 
406 	tp = &scc_tty[minor(dev)];
407 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
408 	if (error >= 0)
409 		return (error);
410 	error = ttioctl(tp, cmd, data, flag);
411 	if (error >= 0)
412 		return (error);
413 
414 	line = SCCLINE(dev);
415 	sc = &scc_softc[SCCUNIT(dev)];
416 	switch (cmd) {
417 
418 	case TIOCSBRK:
419 		sc->scc_wreg[line].wr5 |= SCC_WR5_SEND_BREAK;
420 		ttyoutput(0, tp);
421 		break;
422 
423 	case TIOCCBRK:
424 		sc->scc_wreg[line].wr5 &= ~SCC_WR5_SEND_BREAK;
425 		ttyoutput(0, tp);
426 		break;
427 
428 	case TIOCSDTR:
429 		(void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS);
430 		break;
431 
432 	case TIOCCDTR:
433 		(void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC);
434 		break;
435 
436 	case TIOCMSET:
437 		(void) sccmctl(dev, *(int *)data, DMSET);
438 		break;
439 
440 	case TIOCMBIS:
441 		(void) sccmctl(dev, *(int *)data, DMBIS);
442 		break;
443 
444 	case TIOCMBIC:
445 		(void) sccmctl(dev, *(int *)data, DMBIC);
446 		break;
447 
448 	case TIOCMGET:
449 		*(int *)data = sccmctl(dev, 0, DMGET);
450 		break;
451 
452 	default:
453 		return (ENOTTY);
454 	}
455 	return (0);
456 }
457 
458 sccparam(tp, t)
459 	register struct tty *tp;
460 	register struct termios *t;
461 {
462 	register struct scc_softc *sc;
463 	register scc_regmap_t *regs;
464 	register int line;
465 	register u_char value, wvalue;
466 	register int cflag = t->c_cflag;
467 	int ospeed;
468 
469         if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
470                 return (EINVAL);
471 	sc = &scc_softc[SCCUNIT(tp->t_dev)];
472 	line = SCCLINE(tp->t_dev);
473 	regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
474 	ospeed = ttspeedtab(t->c_ospeed, sccspeedtab);
475         if (ospeed < 0)
476                 return (EINVAL);
477         /* and copy to tty */
478         tp->t_ispeed = t->c_ispeed;
479         tp->t_ospeed = t->c_ospeed;
480         tp->t_cflag = cflag;
481 
482 	/*
483 	 * Handle console specially.
484 	 */
485 	if (cn_tab.cn_screen) {
486 		if (minor(tp->t_dev) == SCCKBD_PORT) {
487 			cflag = CS8;
488 			ospeed = ttspeedtab(4800, sccspeedtab);
489 		} else if (minor(tp->t_dev) == SCCMOUSE_PORT) {
490 			cflag = CS8 | PARENB | PARODD;
491 			ospeed = ttspeedtab(4800, sccspeedtab);
492 		}
493 	} else if (tp->t_dev == cn_tab.cn_dev) {
494 		cflag = CS8;
495 		ospeed = ttspeedtab(9600, sccspeedtab);
496 	}
497 	if (ospeed == 0) {
498 		(void) sccmctl(tp->t_dev, 0, DMSET);	/* hang up line */
499 		return (0);
500 	}
501 
502 	/* reset line */
503 	if (line == SCC_CHANNEL_A)
504 		value = SCC_WR9_RESET_CHA_A;
505 	else
506 		value = SCC_WR9_RESET_CHA_B;
507 	SCC_WRITE_REG(regs, line, SCC_WR9, value);
508 	DELAY(25);
509 
510 	/* stop bits, normally 1 */
511 	value = sc->scc_wreg[line].wr4 & 0xf0;
512 	if (cflag & CSTOPB)
513 		value |= SCC_WR4_2_STOP;
514 	else
515 		value |= SCC_WR4_1_STOP;
516 	if ((cflag & PARODD) == 0)
517 		value |= SCC_WR4_EVEN_PARITY;
518 	if (cflag & PARENB)
519 		value |= SCC_WR4_PARITY_ENABLE;
520 
521 	/* set it now, remember it must be first after reset */
522 	sc->scc_wreg[line].wr4 = value;
523 	SCC_WRITE_REG(regs, line, SCC_WR4, value);
524 
525 	/* vector again */
526 	SCC_WRITE_REG(regs, line, SCC_WR2, 0xf0);
527 
528 	/* clear break, keep rts dtr */
529 	wvalue = sc->scc_wreg[line].wr5 & (SCC_WR5_DTR|SCC_WR5_RTS);
530 	switch (cflag & CSIZE) {
531 	case CS5:
532 		value = SCC_WR3_RX_5_BITS;
533 		wvalue |= SCC_WR5_TX_5_BITS;
534 		break;
535 	case CS6:
536 		value = SCC_WR3_RX_6_BITS;
537 		wvalue |= SCC_WR5_TX_6_BITS;
538 		break;
539 	case CS7:
540 		value = SCC_WR3_RX_7_BITS;
541 		wvalue |= SCC_WR5_TX_7_BITS;
542 		break;
543 	case CS8:
544 	default:
545 		value = SCC_WR3_RX_8_BITS;
546 		wvalue |= SCC_WR5_TX_8_BITS;
547 	};
548 	sc->scc_wreg[line].wr3 = value;
549 	SCC_WRITE_REG(regs, line, SCC_WR3, value);
550 	sc->scc_wreg[line].wr5 = wvalue;
551 	SCC_WRITE_REG(regs, line, SCC_WR5, wvalue);
552 	SCC_WRITE_REG(regs, line, SCC_WR6, 0);
553 	SCC_WRITE_REG(regs, line, SCC_WR7, 0);
554 	SCC_WRITE_REG(regs, line, SCC_WR9, SCC_WR9_VIS);
555 	SCC_WRITE_REG(regs, line, SCC_WR10, 0);
556 	value = SCC_WR11_RCLK_BAUDR | SCC_WR11_XTLK_BAUDR |
557 		SCC_WR11_TRc_OUT | SCC_WR11_TRcOUT_BAUDR;
558 	SCC_WRITE_REG(regs, line, SCC_WR11, value);
559 	SCC_SET_TIMING_BASE(regs, line, ospeed);
560 	value = sc->scc_wreg[line].wr14;
561 	SCC_WRITE_REG(regs, line, SCC_WR14, value);
562 	value = SCC_WR15_BREAK_IE | SCC_WR15_CTS_IE | SCC_WR15_DCD_IE;
563 	SCC_WRITE_REG(regs, line, SCC_WR15, value);
564 
565 	/* and now the enables */
566 	value = sc->scc_wreg[line].wr3 | SCC_WR3_RX_ENABLE;
567 	SCC_WRITE_REG(regs, line, SCC_WR3, value);
568 	value = sc->scc_wreg[line].wr5 | SCC_WR5_TX_ENABLE;
569 	sc->scc_wreg[line].wr5 = value;
570 	SCC_WRITE_REG(regs, line, SCC_WR5, value);
571 
572 	/* master inter enable */
573 	value = SCC_WR9_MASTER_IE | SCC_WR9_VIS;
574 	SCC_WRITE_REG(regs, line, SCC_WR9, value);
575 	SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1);
576 	MachEmptyWriteBuffer();
577 	return (0);
578 }
579 
580 /*
581  * Check for interrupts from all devices.
582  */
583 void
584 sccintr(unit)
585 	register int unit;
586 {
587 	register scc_regmap_t *regs;
588 	register struct tty *tp;
589 	register struct pdma *dp;
590 	register struct scc_softc *sc;
591 	register int cc, chan, rr1, rr2, rr3;
592 	int overrun = 0;
593 
594 	sc = &scc_softc[unit];
595 	regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
596 	unit <<= 1;
597 	for (;;) {
598 	    SCC_READ_REG(regs, SCC_CHANNEL_B, SCC_RR2, rr2);
599 	    rr2 = SCC_RR2_STATUS(rr2);
600 	    /* are we done yet ? */
601 	    if (rr2 == 6) {	/* strange, distinguished value */
602 		SCC_READ_REG(regs, SCC_CHANNEL_A, SCC_RR3, rr3);
603 		if (rr3 == 0)
604 			return;
605 	    }
606 
607 	    SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, SCC_RESET_HIGHEST_IUS);
608 	    if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
609 		chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
610 			SCC_CHANNEL_A : SCC_CHANNEL_B;
611 		tp = &scc_tty[unit | chan];
612 		dp = &sc->scc_pdma[chan];
613 		if (dp->p_mem < dp->p_end) {
614 			SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
615 			MachEmptyWriteBuffer();
616 		} else {
617 			tp->t_state &= ~TS_BUSY;
618 			if (tp->t_state & TS_FLUSH)
619 				tp->t_state &= ~TS_FLUSH;
620 			else {
621 				ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
622 				dp->p_end = dp->p_mem = tp->t_outq.c_cf;
623 			}
624 			if (tp->t_line)
625 				(*linesw[tp->t_line].l_start)(tp);
626 			else
627 				sccstart(tp);
628 			if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
629 				SCC_READ_REG(regs, chan, SCC_RR15, cc);
630 				cc &= ~SCC_WR15_TX_UNDERRUN_IE;
631 				SCC_WRITE_REG(regs, chan, SCC_WR15, cc);
632 				cc = sc->scc_wreg[chan].wr1 & ~SCC_WR1_TX_IE;
633 				SCC_WRITE_REG(regs, chan, SCC_WR1, cc);
634 				sc->scc_wreg[chan].wr1 = cc;
635 				MachEmptyWriteBuffer();
636 			}
637 		}
638 	    } else if (rr2 == SCC_RR2_A_RECV_DONE ||
639 		rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL ||
640 		rr2 == SCC_RR2_B_RECV_SPECIAL) {
641 		if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL)
642 			chan = SCC_CHANNEL_A;
643 		else
644 			chan = SCC_CHANNEL_B;
645 		tp = &scc_tty[unit | chan];
646 		SCC_READ_DATA(regs, chan, cc);
647 		if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
648 			rr2 == SCC_RR2_B_RECV_SPECIAL) {
649 			SCC_READ_REG(regs, chan, SCC_RR1, rr1);
650 			SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_ERROR);
651 			if ((rr1 & SCC_RR1_RX_OVERRUN) && overrun == 0) {
652 				log(LOG_WARNING, "scc%d,%d: silo overflow\n",
653 					unit >> 1, chan);
654 				overrun = 1;
655 			}
656 		}
657 
658 		/*
659 		 * Keyboard needs special treatment.
660 		 */
661 		if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) {
662 #ifdef KADB
663 			if (cc == LK_DO) {
664 				spl0();
665 				kdbpanic();
666 				return;
667 			}
668 #endif
669 #ifdef DEBUG
670 			debugChar = cc;
671 #endif
672 			if (sccDivertXInput) {
673 				(*sccDivertXInput)(cc);
674 				continue;
675 			}
676 			if ((cc = kbdMapChar(cc)) < 0)
677 				continue;
678 		/*
679 		 * Now for mousey
680 		 */
681 		} else if (tp == &scc_tty[SCCMOUSE_PORT] && sccMouseButtons) {
682 			register MouseReport *mrp;
683 			static MouseReport currentRep;
684 
685 			mrp = &currentRep;
686 			mrp->byteCount++;
687 			if (cc & MOUSE_START_FRAME) {
688 				/*
689 				 * The first mouse report byte (button state).
690 				 */
691 				mrp->state = cc;
692 				if (mrp->byteCount > 1)
693 					mrp->byteCount = 1;
694 			} else if (mrp->byteCount == 2) {
695 				/*
696 				 * The second mouse report byte (delta x).
697 				 */
698 				mrp->dx = cc;
699 			} else if (mrp->byteCount == 3) {
700 				/*
701 				 * The final mouse report byte (delta y).
702 				 */
703 				mrp->dy = cc;
704 				mrp->byteCount = 0;
705 				if (mrp->dx != 0 || mrp->dy != 0) {
706 					/*
707 					 * If the mouse moved,
708 					 * post a motion event.
709 					 */
710 					(*sccMouseEvent)(mrp);
711 				}
712 				(*sccMouseButtons)(mrp);
713 			}
714 			continue;
715 		}
716 		if (!(tp->t_state & TS_ISOPEN)) {
717 			wakeup((caddr_t)&tp->t_rawq);
718 #ifdef PORTSELECTOR
719 			if (!(tp->t_state & TS_WOPEN))
720 #endif
721 				continue;
722 		}
723 		if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
724 			rr2 == SCC_RR2_B_RECV_SPECIAL) {
725 			if (rr1 & SCC_RR1_PARITY_ERR)
726 				cc |= TTY_PE;
727 			if (rr1 & SCC_RR1_FRAME_ERR)
728 				cc |= TTY_FE;
729 		}
730 		(*linesw[tp->t_line].l_rint)(cc, tp);
731 	    } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
732 		chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
733 			SCC_CHANNEL_A : SCC_CHANNEL_B;
734 		SCC_WRITE_REG(regs, chan, SCC_RR0, SCC_RESET_EXT_IP);
735 		scc_modem_intr(unit | chan);
736 	    }
737 	}
738 }
739 
740 void
741 sccstart(tp)
742 	register struct tty *tp;
743 {
744 	register struct pdma *dp;
745 	register scc_regmap_t *regs;
746 	register struct scc_softc *sc;
747 	register int cc, chan;
748 	u_char temp;
749 	int s, sendone;
750 
751 	sc = &scc_softc[SCCUNIT(tp->t_dev)];
752 	dp = &sc->scc_pdma[SCCLINE(tp->t_dev)];
753 	regs = (scc_regmap_t *)dp->p_addr;
754 	s = spltty();
755 	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
756 		goto out;
757 	if (tp->t_outq.c_cc <= tp->t_lowat) {
758 		if (tp->t_state & TS_ASLEEP) {
759 			tp->t_state &= ~TS_ASLEEP;
760 			wakeup((caddr_t)&tp->t_outq);
761 		}
762 		selwakeup(&tp->t_wsel);
763 	}
764 	if (tp->t_outq.c_cc == 0)
765 		goto out;
766 	/* handle console specially */
767 	if (tp == &scc_tty[SCCKBD_PORT] && cn_tab.cn_screen) {
768 		while (tp->t_outq.c_cc > 0) {
769 			cc = getc(&tp->t_outq) & 0x7f;
770 			cnputc(cc);
771 		}
772 		/*
773 		 * After we flush the output queue we may need to wake
774 		 * up the process that made the output.
775 		 */
776 		if (tp->t_outq.c_cc <= tp->t_lowat) {
777 			if (tp->t_state & TS_ASLEEP) {
778 				tp->t_state &= ~TS_ASLEEP;
779 				wakeup((caddr_t)&tp->t_outq);
780 			}
781 			selwakeup(&tp->t_wsel);
782 		}
783 		goto out;
784 	}
785 	if (tp->t_flags & (RAW|LITOUT))
786 		cc = ndqb(&tp->t_outq, 0);
787 	else {
788 		cc = ndqb(&tp->t_outq, 0200);
789 		if (cc == 0) {
790 			cc = getc(&tp->t_outq);
791 			timeout(ttrstrt, (void *)tp, (cc & 0x7f) + 6);
792 			tp->t_state |= TS_TIMEOUT;
793 			goto out;
794 		}
795 	}
796 	tp->t_state |= TS_BUSY;
797 	dp->p_end = dp->p_mem = tp->t_outq.c_cf;
798 	dp->p_end += cc;
799 
800 	/*
801 	 * Enable transmission and send the first char, as required.
802 	 */
803 	chan = SCCLINE(tp->t_dev);
804 	SCC_READ_REG(regs, chan, SCC_RR0, temp);
805 	sendone = (temp & SCC_RR0_TX_EMPTY);
806 	SCC_READ_REG(regs, chan, SCC_RR15, temp);
807 	temp |= SCC_WR15_TX_UNDERRUN_IE;
808 	SCC_WRITE_REG(regs, chan, SCC_WR15, temp);
809 	temp = sc->scc_wreg[chan].wr1 | SCC_WR1_TX_IE;
810 	SCC_WRITE_REG(regs, chan, SCC_WR1, temp);
811 	sc->scc_wreg[chan].wr1 = temp;
812 	if (sendone) {
813 #ifdef DIAGNOSTIC
814 		if (cc == 0)
815 			panic("sccstart: No chars");
816 #endif
817 		SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
818 	}
819 	MachEmptyWriteBuffer();
820 out:
821 	splx(s);
822 }
823 
824 /*
825  * Stop output on a line.
826  */
827 /*ARGSUSED*/
828 sccstop(tp, flag)
829 	register struct tty *tp;
830 {
831 	register struct pdma *dp;
832 	register struct scc_softc *sc;
833 	register int s;
834 
835 	sc = &scc_softc[SCCUNIT(tp->t_dev)];
836 	dp = &sc->scc_pdma[SCCLINE(tp->t_dev)];
837 	s = spltty();
838 	if (tp->t_state & TS_BUSY) {
839 		dp->p_end = dp->p_mem;
840 		if (!(tp->t_state & TS_TTSTOP))
841 			tp->t_state |= TS_FLUSH;
842 	}
843 	splx(s);
844 }
845 
846 sccmctl(dev, bits, how)
847 	dev_t dev;
848 	int bits, how;
849 {
850 	register struct scc_softc *sc;
851 	register scc_regmap_t *regs;
852 	register int line, mbits;
853 	register u_char value;
854 	int s;
855 
856 	sc = &scc_softc[SCCUNIT(dev)];
857 	line = SCCLINE(dev);
858 	regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
859 	s = spltty();
860 	/*
861 	 * only channel B has modem control, however the DTR and RTS
862 	 * pins on the comm port are wired to the DTR and RTS A channel
863 	 * signals.
864 	 */
865 	mbits = DML_DTR | DML_DSR | DML_CAR;
866 	if (line == SCC_CHANNEL_B) {
867 		if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & SCC_WR5_DTR)
868 			mbits = DML_DTR | DML_DSR;
869 		else
870 			mbits = 0;
871 		SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value);
872 		if (value & SCC_RR0_DCD)
873 			mbits |= DML_CAR;
874 	}
875 	switch (how) {
876 	case DMSET:
877 		mbits = bits;
878 		break;
879 
880 	case DMBIS:
881 		mbits |= bits;
882 		break;
883 
884 	case DMBIC:
885 		mbits &= ~bits;
886 		break;
887 
888 	case DMGET:
889 		(void) splx(s);
890 		return (mbits);
891 	}
892 	if (line == SCC_CHANNEL_B) {
893 		if (mbits & DML_DTR)
894 			sc->scc_wreg[SCC_CHANNEL_A].wr5 |= SCC_WR5_DTR;
895 		else
896 			sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~SCC_WR5_DTR;
897 		SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5,
898 			sc->scc_wreg[SCC_CHANNEL_A].wr5);
899 	}
900 	if ((mbits & DML_DTR) && (sc->scc_softCAR & (1 << line)))
901 		scc_tty[minor(dev)].t_state |= TS_CARR_ON;
902 	(void) splx(s);
903 	return (mbits);
904 }
905 
906 /*
907  * Check for carrier transition.
908  */
909 static void
910 scc_modem_intr(dev)
911 	dev_t dev;
912 {
913 	register scc_regmap_t *regs;
914 	register struct scc_softc *sc;
915 	register struct tty *tp;
916 	register int car, chan;
917 	register u_char value;
918 	int s;
919 
920 	sc = &scc_softc[SCCUNIT(dev)];
921 	tp = &scc_tty[minor(dev)];
922 	chan = SCCLINE(dev);
923 	regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr;
924 	if (chan == SCC_CHANNEL_A)
925 		return;
926 	s = spltty();
927 	if (sc->scc_softCAR & (1 << chan))
928 		car = 1;
929 	else {
930 		SCC_READ_REG_ZERO(regs, chan, value);
931 		car = value & SCC_RR0_DCD;
932 	}
933 	if (car) {
934 		/* carrier present */
935 		if (!(tp->t_state & TS_CARR_ON))
936 			(void)(*linesw[tp->t_line].l_modem)(tp, 1);
937 	} else if (tp->t_state & TS_CARR_ON)
938 		(void)(*linesw[tp->t_line].l_modem)(tp, 0);
939 	splx(s);
940 }
941 
942 /*
943  * Get a char off the appropriate line via. a busy wait loop.
944  */
945 int
946 sccGetc(dev)
947 	dev_t dev;
948 {
949 	register scc_regmap_t *regs;
950 	register int c, line;
951 	register u_char value;
952 	int s;
953 
954 	line = SCCLINE(dev);
955 	regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr;
956 	if (!regs)
957 		return (0);
958 	s = spltty();
959 	for (;;) {
960 		SCC_READ_REG(regs, line, SCC_RR0, value);
961 		if (value & SCC_RR0_RX_AVAIL) {
962 			SCC_READ_REG(regs, line, SCC_RR1, value);
963 			SCC_READ_DATA(regs, line, c);
964 			if (value & (SCC_RR1_PARITY_ERR | SCC_RR1_RX_OVERRUN |
965 				SCC_RR1_FRAME_ERR)) {
966 				SCC_WRITE_REG(regs, line, SCC_WR0, SCC_RESET_ERROR);
967 				SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
968 					SCC_RESET_HIGHEST_IUS);
969 			} else {
970 				SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
971 					SCC_RESET_HIGHEST_IUS);
972 				splx(s);
973 				return (c & 0xff);
974 			}
975 		} else
976 			DELAY(10);
977 	}
978 }
979 
980 /*
981  * Send a char on a port, via a busy wait loop.
982  */
983 void
984 sccPutc(dev, c)
985 	dev_t dev;
986 	int c;
987 {
988 	register scc_regmap_t *regs;
989 	register int line;
990 	register u_char value;
991 	int s;
992 
993 	s = spltty();
994 	line = SCCLINE(dev);
995 	regs = (scc_regmap_t *)scc_softc[SCCUNIT(dev)].scc_pdma[line].p_addr;
996 
997 	/*
998 	 * Wait for transmitter to be not busy.
999 	 */
1000 	do {
1001 		SCC_READ_REG(regs, line, SCC_RR0, value);
1002 		if (value & SCC_RR0_TX_EMPTY)
1003 			break;
1004 		DELAY(100);
1005 	} while (1);
1006 
1007 	/*
1008 	 * Send the char.
1009 	 */
1010 	SCC_WRITE_DATA(regs, line, c);
1011 	MachEmptyWriteBuffer();
1012 	splx(s);
1013 }
1014 #endif /* NSCC */
1015