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