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 */
sccprobe(cp)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
sccreset(sc)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
sccopen(dev,flag,mode,p)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*/
sccclose(dev,flag,mode,p)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
sccread(dev,uio,flag)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
sccwrite(dev,uio,flag)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*/
sccioctl(dev,cmd,data,flag,p)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
sccparam(tp,t)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
sccintr(unit)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 = ¤tRep;
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
sccstart(tp)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*/
sccstop(tp,flag)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
sccmctl(dev,bits,how)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
scc_modem_intr(dev)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
sccGetc(dev)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
sccPutc(dev,c)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