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