Annotation of src/sys/arch/pmax/tc/scc.c, Revision 1.30
1.30 ! jonathan 1: /* $NetBSD: scc.c,v 1.29 1997/11/08 21:55:08 jonathan Exp $ */
1.1 jonathan 2:
3: /*
1.18 jonathan 4: * Copyright (c) 1991,1990,1989,1994,1995,1996 Carnegie Mellon University
1.1 jonathan 5: * All rights reserved.
6: *
7: * Author: Chris G. Demetriou and Jonathan Stone
8: *
9: * Permission to use, copy, modify and distribute this software and its
10: * documentation is hereby granted, provided that both the copyright
11: * notice and this permission notice appear in all copies of the
12: * software, derivative works or modified versions, and any portions
13: * thereof, and that both notices appear in supporting documentation.
14: *
15: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
16: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
17: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
18: *
19: * Carnegie Mellon requests users of this software to return to
20: *
21: * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
22: * School of Computer Science
23: * Carnegie Mellon University
24: * Pittsburgh PA 15213-3890
25: *
26: * any improvements or extensions that they make and grant Carnegie the
27: * rights to redistribute these changes.
28: */
29:
30: /*-
31: * Copyright (c) 1992, 1993
32: * The Regents of the University of California. All rights reserved.
33: *
34: * This code is derived from software contributed to Berkeley by
35: * Ralph Campbell and Rick Macklem.
36: *
37: * Redistribution and use in source and binary forms, with or without
38: * modification, are permitted provided that the following conditions
39: * are met:
40: * 1. Redistributions of source code must retain the above copyright
41: * notice, this list of conditions and the following disclaimer.
42: * 2. Redistributions in binary form must reproduce the above copyright
43: * notice, this list of conditions and the following disclaimer in the
44: * documentation and/or other materials provided with the distribution.
45: * 3. All advertising materials mentioning features or use of this software
46: * must display the following acknowledgement:
47: * This product includes software developed by the University of
48: * California, Berkeley and its contributors.
49: * 4. Neither the name of the University nor the names of its contributors
50: * may be used to endorse or promote products derived from this software
51: * without specific prior written permission.
52: *
53: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63: * SUCH DAMAGE.
64: *
1.18 jonathan 65: * @(#)scc.c 8.2 (Berkeley) 11/30/93
1.1 jonathan 66: */
67:
1.29 jonathan 68: #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
1.30 ! jonathan 69: __KERNEL_RCSID(0, "$NetBSD: scc.c,v 1.29 1997/11/08 21:55:08 jonathan Exp $");
1.1 jonathan 70:
71: /*
72: * Intel 82530 dual usart chip driver. Supports the serial port(s) on the
73: * Personal DECstation 5000/xx and DECstation 5000/1xx, plus the keyboard
74: * and mouse on the 5000/1xx. (Don't ask me where the A channel signals
75: * are on the 5000/xx.)
76: *
77: * See: Intel MicroCommunications Handbook, Section 2, pg. 155-173, 1992.
78: */
79: #include <sys/param.h>
80: #include <sys/systm.h>
81: #include <sys/ioctl.h>
82: #include <sys/tty.h>
83: #include <sys/proc.h>
84: #include <sys/map.h>
85: #include <sys/buf.h>
86: #include <sys/conf.h>
87: #include <sys/file.h>
88: #include <sys/uio.h>
89: #include <sys/kernel.h>
90: #include <sys/syslog.h>
91: #include <sys/device.h>
92:
1.18 jonathan 93: #ifndef pmax
1.1 jonathan 94: #include <dev/cons.h>
95: #endif
96:
97: #include <pmax/include/pmioctl.h>
98:
99: #include <pmax/dev/pdma.h>
100: #include <dev/ic/z8530reg.h>
1.2 jonathan 101: #include <pmax/dev/lk201.h>
1.18 jonathan 102: #include <pmax/dev/lk201var.h>
1.1 jonathan 103:
104: #ifdef pmax
1.18 jonathan 105: #include <mips/cpuregs.h> /* phys to uncached */
1.1 jonathan 106: #include <pmax/pmax/cons.h>
107: #include <pmax/pmax/pmaxtype.h>
108: #include <pmax/pmax/maxine.h>
109: #include <pmax/pmax/asic.h>
110: #include <pmax/dev/sccreg.h>
1.12 mhitch 111: #include <pmax/tc/sccvar.h> /* XXX */
1.1 jonathan 112: #endif
113:
114: #ifdef alpha
115: #include <alpha/tc/sccreg.h>
116: #include <alpha/tc/sccvar.h>
117: #include <machine/rpb.h>
1.6 jonathan 118: #include <alpha/tc/ioasicreg.h>
1.1 jonathan 119: #endif
120:
1.6 jonathan 121: #include <machine/autoconf.h>
1.24 jonathan 122: #include <machine/bus.h>
123: #include <machine/conf.h>
124:
1.6 jonathan 125: #include <dev/tc/tcvar.h>
126: #include <dev/tc/ioasicvar.h>
127:
1.18 jonathan 128:
1.21 mellon 129: #include "rasterconsole.h"
130:
1.1 jonathan 131: extern void ttrstrt __P((void *));
132:
133: #ifdef alpha
134: #undef SCCDEV
135: #define SCCDEV 15 /* XXX */
136: #endif
137:
138: /*
1.18 jonathan 139: * rcons glass-tty console (as used on pmax) needs lk-201 ASCII input
140: * support from the tty drivers. This is ugly and broken and won't
141: * compile on Alphas.
1.1 jonathan 142: */
1.21 mellon 143: #if defined (pmax)
144: #if NRASTERCONSOLE > 0
1.6 jonathan 145: #define HAVE_RCONS
1.21 mellon 146: #endif
1.9 jonathan 147: extern int pending_remcons;
1.6 jonathan 148: #endif
1.2 jonathan 149:
150: /*
151: * True iff the console unit is diverted throught this SCC device.
152: * (used to just test if cn_tab->cn_getc was sccGetc, but that
153: * breaks with the new-style glass-tty framebuffer console input.
154: */
155:
156: #define CONSOLE_ON_UNIT(unit) \
157: (major(cn_tab->cn_dev) == SCCDEV && SCCUNIT(cn_tab->cn_dev) == (unit))
1.1 jonathan 158:
159: #ifdef alpha
1.2 jonathan 160: #define RASTER_CONSOLE() 1 /* Treat test for cn_screen as true */
1.1 jonathan 161: #endif
162:
1.2 jonathan 163: /*
164: * Is there a framebuffer console device using this serial driver?
165: * XXX used for ugly special-cased console input that should be redone
166: * more cleanly.
167: */
168:
169: static inline int
1.18 jonathan 170: raster_console(void)
1.2 jonathan 171: {
172: return (cn_tab->cn_pri == CN_NORMAL || cn_tab->cn_pri == CN_INTERNAL);
173: }
174:
1.1 jonathan 175:
176: #define SCCUNIT(dev) (minor(dev) >> 1)
177: #define SCCLINE(dev) (minor(dev) & 0x1)
178:
1.18 jonathan 179: /* QVSS-compatible in-kernel X input event parser, pointer tracker */
180: void (*sccDivertXInput) __P((int cc)); /* X windows keyboard input routine */
181: void (*sccMouseEvent) __P((int)); /* X windows mouse motion event routine */
182: void (*sccMouseButtons) __P((int)); /* X windows mouse buttons event routine */
183:
1.1 jonathan 184: #ifdef DEBUG
185: int debugChar;
186: #endif
187:
188: struct scc_softc {
189: struct device sc_dv;
190: struct pdma scc_pdma[2];
191: struct {
192: u_char wr1;
193: u_char wr3;
194: u_char wr4;
195: u_char wr5;
196: u_char wr14;
197: } scc_wreg[2];
1.18 jonathan 198: struct tty *scc_tty[2];
1.1 jonathan 199: int scc_softCAR;
1.18 jonathan 200: int scc_flags[2];
201: #define SCC_CHAN_NEEDSDELAY 0x01 /* sw must delay 1.6us between output*/
202: #define SCC_CHAN_NOMODEM 0x02 /* don't touch modem ctl lines (may
203: be left floating or x-wired */
204: #define SCC_CHAN_MODEM_CROSSED 0x04 /* modem lines wired to other channel*/
205: #define SCC_CHAN_KBDLINE 0x08 /* XXX special-case keyboard lines */
206: int scc_unitflags; /* flags for both channels, e.g. */
207: #define SCC_PREFERRED_CONSOLE 0x01
1.1 jonathan 208: };
209:
210: /*
211: * BRG formula is:
212: * ClockFrequency
213: * BRGconstant = --------------------------- - 2
214: * 2 * BaudRate * ClockDivider
215: *
216: * Speed selections with Pclk=7.3728Mhz, clock x16
217: */
218: struct speedtab sccspeedtab[] = {
219: { 0, 0, },
220: { 50, 4606, },
221: { 75, 3070, },
222: { 110, 2093, },
223: { 134.5, 1711, },
224: { 150, 1534, },
225: { 200, 1150, },
226: { 300, 766, },
227: { 600, 382, },
228: { 1200, 190, },
229: { 1800, 126, },
230: { 2400, 94, },
231: { 4800, 46, },
1.18 jonathan 232: { 7200, 30, }, /* non-POSIX */
1.1 jonathan 233: { 9600, 22, },
1.5 jonathan 234: { 14400, 14, }, /* non-POSIX */
1.1 jonathan 235: { 19200, 10, },
1.5 jonathan 236: { 28800, 6, }, /* non-POSIX */
1.18 jonathan 237: { 38400, 4, }, /* non-POSIX */
238: { 57600, 2, }, /* non-POSIX */
239: { 76800, 1, }, /* non-POSIX, doesn't work reliably */
240: { 115200, 0 }, /* non-POSIX doesn't work reliably */
1.1 jonathan 241: { -1, -1, },
242: };
243:
1.5 jonathan 244: #if 0
245: /* speed selections with clock x1 */
246: {
247: { 0, 0 },
248: { 300, 24574 },
249: { 300, 12286 },
250: { 600, 6142 },
251: { 1200, 3070 },
252: { 2400, 1534 },
253: { 4800, 766 },
254: { 7200, 510 },
255: { 9600, 382 },
256: { 14400, 254 },
257: { 19200, 190 },
258: { 28800, 126 },
259: { 38400, 94 },
260: { 57600, 62, },
261: { 76800, 46, },
262: { 115200, 30 },
263: { 204800, 16 },
264: { 230400, 14 },
265: }
266: #endif
267:
1.1 jonathan 268: #ifndef PORTSELECTOR
269: #define ISPEED TTYDEF_SPEED
270: #define LFLAG TTYDEF_LFLAG
271: #else
272: #define ISPEED B4800
273: #define LFLAG (TTYDEF_LFLAG & ~ECHO)
274: #endif
275:
276: /* Definition of the driver for autoconfig. */
1.28 jonathan 277: static int sccmatch __P((struct device *parent, struct cfdata *cf,
1.18 jonathan 278: void *aux));
279: static void sccattach __P((struct device *parent, struct device *self,
280: void *aux));
1.10 thorpej 281:
282: struct cfattach scc_ca = {
1.18 jonathan 283: sizeof (struct scc_softc), sccmatch, sccattach,
1.10 thorpej 284: };
285:
286: struct cfdriver scc_cd = {
1.18 jonathan 287: NULL, "scc", DV_TTY,
1.1 jonathan 288: };
289:
290: int sccGetc __P((dev_t));
291: void sccPutc __P((dev_t, int));
292: void sccPollc __P((dev_t, int));
293: int sccparam __P((struct tty *, struct termios *));
294: void sccstart __P((struct tty *));
295: int sccmctl __P((dev_t, int, int));
1.18 jonathan 296: static int cold_sccparam __P((struct tty *, struct termios *,
297: struct scc_softc *sc));
1.1 jonathan 298:
299:
1.18 jonathan 300: #ifdef SCC_DEBUG
301: static void rr __P((char *, scc_regmap_t *));
302: #endif
303:
1.1 jonathan 304: static void scc_modem_intr __P((dev_t));
305: static void sccreset __P((struct scc_softc *));
306:
1.2 jonathan 307: int sccintr __P((void *));
1.18 jonathan 308: #ifdef alpha
309: void scc_alphaintr __P((int));
310: #endif
1.9 jonathan 311:
312:
1.18 jonathan 313: /*
314: * console variables, for using serial console while still cold and
315: * autoconfig has not attached the scc device.
316: */
317: extern int cold;
318: scc_regmap_t *scc_cons_addr = 0;
319: static struct scc_softc coldcons_softc;
320: static struct consdev scccons = {
321: NULL, NULL, sccGetc, sccPutc, sccPollc, NODEV, 0
322: };
323: void scc_consinit __P((dev_t dev, scc_regmap_t *sccaddr));
1.22 jonathan 324: void scc_oconsinit __P((struct scc_softc *sc, dev_t dev));
1.18 jonathan 325:
326:
327: /*
328: * Set up a given unit as a serial console device.
329: * We need console output when cold, and before any device is configured.
330: * Should be callable when cold, to reset the chip and set parameters
331: * for a remote (serial) console or kgdb line.
332: * XXX
333: * As most DECstations only bring out one rs-232 lead from an SCC
334: * to the bulkhead, and use the other for mouse and keyboard, we
335: * only allow one unit per SCC to be console.
336: */
337: void
338: scc_consinit(dev, sccaddr)
339: dev_t dev;
340: scc_regmap_t *sccaddr;
341: {
342: struct scc_softc *sc;
343: struct termios cterm;
344: struct tty ctty;
345: int s;
346:
347: /* Save address in case we're cold. */
348: if (cold && scc_cons_addr == 0) {
349: scc_cons_addr = sccaddr;
350: sc = &coldcons_softc;
351: coldcons_softc.scc_pdma[0].p_addr = sccaddr;
352: coldcons_softc.scc_pdma[1].p_addr = sccaddr;
353: } else {
354: /* being called from sccattach() to reset console */
355: sc = scc_cd.cd_devs[SCCUNIT(dev)];
356: }
357:
358: /* Reset chip. */
359: sccreset(sc);
360: /* XXX make sure sccreset() called only once for this chip? */
1.9 jonathan 361:
1.18 jonathan 362: /* set console-line parameters */
363: s = spltty();
364: ctty.t_dev = dev;
365: scccons.cn_dev = dev;
366: cterm.c_cflag = CS8;
367: #ifdef pmax
368: /* XXX -- why on pmax, not on Alpha? */
369: cterm.c_cflag |= CLOCAL;
370: #endif
371: cterm.c_ospeed = cterm.c_ispeed = 9600;
372: (void) cold_sccparam(&ctty, &cterm, sc);
373: *cn_tab = scccons;
374: DELAY(1000);
375: splx(s);
376: }
377:
378: void
379: scc_oconsinit(sc, dev)
380: struct scc_softc *sc;
381: dev_t dev;
382: {
383: struct termios cterm;
384: struct tty ctty;
385: int s;
386:
387: s = spltty();
388: ctty.t_dev = dev;
389: cterm.c_cflag = CS8;
390: #ifdef pmax
391: /* XXX -- why on pmax, not on Alpha? */
392: cterm.c_cflag |= CLOCAL;
1.1 jonathan 393: #endif
1.18 jonathan 394: cterm.c_ospeed = cterm.c_ispeed = 9600;
395: (void) sccparam(&ctty, &cterm);
396: DELAY(1000);
397: splx(s);
398: }
1.1 jonathan 399:
400: /*
401: * Test to see if device is present.
402: * Return true if found.
403: */
404: int
1.28 jonathan 405: sccmatch(parent, cf, aux)
1.1 jonathan 406: struct device *parent;
1.28 jonathan 407: struct cfdata *cf;
1.1 jonathan 408: void *aux;
409: {
1.12 mhitch 410: struct ioasicdev_attach_args *d = aux;
1.1 jonathan 411: void *sccaddr;
412:
1.18 jonathan 413: if (parent->dv_cfdata->cf_driver != &ioasic_cd) {
1.1 jonathan 414: #ifdef DIAGNOSTIC
1.17 christos 415: printf("Cannot attach scc on %s\n", parent->dv_xname);
1.1 jonathan 416: #endif
1.18 jonathan 417: return (0);
1.1 jonathan 418: }
419:
1.18 jonathan 420: /* Make sure that we're looking for this type of device. */
421: if ((strncmp(d->iada_modname, "z8530 ", TC_ROM_LLEN) != 0) &&
422: (strncmp(d->iada_modname, "scc", TC_ROM_LLEN)!= 0))
423: return (0);
424:
1.20 jonathan 425: /*
426: * Check user-specified offset against the ioasic offset.
427: * Allow it to be wildcarded.
428: */
1.27 jtk 429: if (cf->cf_loc[IOASICCF_OFFSET] != IOASICCF_OFFSET_DEFAULT &&
430: cf->cf_loc[IOASICCF_OFFSET] != d->iada_offset)
1.1 jonathan 431: return (0);
432:
433: /* Get the address, and check it for validity. */
1.18 jonathan 434: sccaddr = (void *)d->iada_addr;
435: #ifdef SPARSE
436: sccaddr = (void *)TC_DENSE_TO_SPARSE((tc_addr_t)sccaddr);
437: #endif
1.1 jonathan 438:
439: if (badaddr(sccaddr, 2))
440: return (0);
441:
442: return (1);
443: }
444:
445: #ifdef alpha
1.18 jonathan 446: /*
447: * Enable ioasic SCC interrupts and scc DMA engine interrupts.
448: * XXX does not really belong here.
449: */
1.1 jonathan 450: void
451: scc_alphaintr(onoff)
452: int onoff;
453: {
454: if (onoff) {
1.6 jonathan 455: *(volatile u_int *)IOASIC_REG_IMSK(ioasic_base) |=
456: IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0;
1.1 jonathan 457: #if !defined(DEC_3000_300) && defined(SCC_DMA)
1.6 jonathan 458: *(volatile u_int *)IOASIC_REG_CSR(ioasic_base) |=
459: IOASIC_CSR_DMAEN_T1 | IOASIC_CSR_DMAEN_R1 |
460: IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2;
1.1 jonathan 461: #endif
462: } else {
1.6 jonathan 463: *(volatile u_int *)IOASIC_REG_IMSK(ioasic_base) &=
464: ~(IOASIC_INTR_SCC_1 | IOASIC_INTR_SCC_0);
1.1 jonathan 465: #if !defined(DEC_3000_300) && defined(SCC_DMA)
1.6 jonathan 466: *(volatile u_int *)IOASIC_REG_CSR(ioasic_base) &=
467: ~(IOASIC_CSR_DMAEN_T1 | IOASIC_CSR_DMAEN_R1 |
468: IOASIC_CSR_DMAEN_T2 | IOASIC_CSR_DMAEN_R2);
1.1 jonathan 469: #endif
470: }
1.18 jonathan 471: alpha_mb();
1.1 jonathan 472: }
473: #endif /*alpha*/
474:
475: void
476: sccattach(parent, self, aux)
477: struct device *parent;
478: struct device *self;
479: void *aux;
480: {
481: struct scc_softc *sc = (struct scc_softc *)self;
1.12 mhitch 482: struct ioasicdev_attach_args *d = aux;
1.1 jonathan 483: struct pdma *pdp;
484: struct tty *tp;
485: void *sccaddr;
486: int cntr;
487: struct termios cterm;
488: struct tty ctty;
489: int s;
490: extern int cputype;
491: int unit, flags;
492:
493: unit = sc->sc_dv.dv_unit;
494: flags = sc->sc_dv.dv_cfdata->cf_flags;
495:
1.6 jonathan 496: /* serial console debugging */
497: #if defined(DEBUG) && defined(HAVE_RCONS) && 0
498: if (CONSOLE_ON_UNIT(unit) && (cn_tab->cn_pri == CN_REMOTE))
1.17 christos 499: printf("\nattaching scc%d, currently PROM console\n", unit);
1.6 jonathan 500: #endif /* defined(DEBUG) && defined(HAVE_RCONS)*/
501:
1.25 jonathan 502: sccaddr = (void*)MIPS_PHYS_TO_KSEG1(d->iada_addr);
1.18 jonathan 503: #ifdef SPARSE
504: sccaddr = (void *)TC_DENSE_TO_SPARSE((tc_addr_t)sccaddr);
505: #endif
1.1 jonathan 506:
507: /* Register the interrupt handler. */
1.12 mhitch 508: ioasic_intr_establish(parent, d->iada_cookie, TC_IPL_TTY,
1.6 jonathan 509: sccintr, (void *)sc);
510:
511: /* serial console debugging */
512: #if defined(DEBUG) && defined(HAVE_RCONS) && 0 /*XXX*/
513: if (CONSOLE_ON_UNIT(unit) && (cn_tab->cn_pri == CN_REMOTE)) {
514: DELAY(10000);
1.17 christos 515: printf("(attached interrupt, delaying)\n");
1.6 jonathan 516: }
517: #endif /* defined(DEBUG) && defined(HAVE_RCONS)*/
1.1 jonathan 518:
519: /*
520: * For a remote console, wait a while for previous output to
521: * complete.
522: */
1.21 mellon 523: #ifdef pmax
1.2 jonathan 524: if (CONSOLE_ON_UNIT(unit) && (cn_tab->cn_pri == CN_REMOTE))
1.1 jonathan 525: DELAY(10000);
1.21 mellon 526: #endif
527:
528: #ifdef alpha
1.1 jonathan 529: if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) ||
530: (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0))
531: DELAY(10000);
532: #endif
533:
534: pdp = &sc->scc_pdma[0];
535:
536: /* init pseudo DMA structures */
537: for (cntr = 0; cntr < 2; cntr++) {
538: pdp->p_addr = (void *)sccaddr;
1.18 jonathan 539: tp = sc->scc_tty[cntr] = ttymalloc();
1.13 mhitch 540: if (cputype == DS_MAXINE || cntr == 0)
541: tty_attach(tp); /* XXX */
1.1 jonathan 542: pdp->p_arg = (long)tp;
1.18 jonathan 543: pdp->p_fcn = (void (*)__P((struct tty*)))0;
1.1 jonathan 544: tp->t_dev = (dev_t)((unit << 1) | cntr);
545: pdp++;
546: }
547: /* What's the warning here? Defaulting to softCAR on line 2? */
1.18 jonathan 548: sc->scc_softCAR = flags | 0x2; /* XXX */
1.1 jonathan 549:
1.18 jonathan 550: /* reset chip, initialize register-copies in softc */
1.1 jonathan 551: sccreset(sc);
552:
553: /*
554: * Special handling for consoles.
555: */
1.9 jonathan 556: #ifdef pmax
557: if (pending_remcons) {
558: /*
559: * We were using PROM callbacks for console I/O,
560: * and we just reset the chip under the console.
561: * wire up this driver as console ASAP.
562: */
563:
564: /*XXX*/ /* test for correct unit */
565: DELAY(10000);
566:
567: /*
568: * XXX PROM and NetBSD unit numbers swapped
569: * on kn03, maybe kmin?
1.15 mhitch 570: * And what about maxine?
1.9 jonathan 571: */
1.21 mellon 572: if (cn_tab->cn_dev == unit && cputype != DS_MAXINE) {
573: printf ("\n");
1.9 jonathan 574: return;
1.21 mellon 575: }
1.9 jonathan 576:
577: /*
578: * If we are using the PROM serial-console routines
579: * as console, now is the time to set up the scc
580: * driver as console.
581: */
582: cn_tab = &scccons;
583: cn_tab->cn_dev = makedev(SCCDEV,
584: sc->sc_dv.dv_unit == 0 ? SCCCOMM2_PORT : SCCCOMM3_PORT);
1.18 jonathan 585: #ifdef notyet
586: scc_consinit(cn_tab->cn_dev, sccaddr);
587: #else
588: scc_oconsinit(sc, cn_tab->cn_dev);
589: #endif
590:
1.17 christos 591: printf(" (In sccattach: cn_dev = 0x%x)", cn_tab->cn_dev);
592: printf(" (Unit = %d)", unit);
1.21 mellon 593: printf(": console\n");
1.9 jonathan 594: pending_remcons = 0;
595: /*
596: * XXX We should support configurations where the PROM
597: * console device is a serial console, and a
598: * framebuffer, keyboard, and mouse are present.
599: */
600: return;
601: }
602: #endif /* pmax */
1.6 jonathan 603: #ifdef HAVE_RCONS
1.2 jonathan 604: if ((cn_tab->cn_getc == LKgetc)) {
605: /* XXX test below may be too inclusive ? */
1.7 jonathan 606: /*(1)*/ /*(CONSOLE_ON_UNIT(unit))*/
607: if (major(cn_tab->cn_dev) == SCCDEV) {
1.1 jonathan 608: if (unit == 1) {
609: s = spltty();
610: ctty.t_dev = makedev(SCCDEV, SCCKBD_PORT);
611: cterm.c_cflag = CS8;
612: #ifdef pmax
613: /* XXX -- why on pmax, not on Alpha? */
614: cterm.c_cflag |= CLOCAL;
1.6 jonathan 615: #endif /* pmax */
1.1 jonathan 616: cterm.c_ospeed = cterm.c_ispeed = 4800;
617: (void) sccparam(&ctty, &cterm);
618: DELAY(10000);
619: #ifdef notyet
620: /*
621: * For some reason doing this hangs the 3min
622: * during booting. Fortunately the keyboard
623: * works ok without it.
624: */
625: KBDReset(ctty.t_dev, sccPutc);
1.6 jonathan 626: #endif /* notyet */
1.1 jonathan 627: DELAY(10000);
628: splx(s);
629: } else if (unit == 0) {
630: s = spltty();
631: ctty.t_dev = makedev(SCCDEV, SCCMOUSE_PORT);
632: cterm.c_cflag = CS8 | PARENB | PARODD;
633: cterm.c_ospeed = cterm.c_ispeed = 4800;
634: (void) sccparam(&ctty, &cterm);
1.6 jonathan 635: #ifdef HAVE_RCONS
1.1 jonathan 636: DELAY(10000);
637: MouseInit(ctty.t_dev, sccPutc, sccGetc);
638: DELAY(10000);
639: #endif
640: splx(s);
641: }
642: }
1.2 jonathan 643: } else
1.6 jonathan 644: #endif /* HAVE_RCONS */
1.9 jonathan 645: if (SCCUNIT(cn_tab->cn_dev) == unit)
646: {
647: /*XXX console initialization used to go here */
1.1 jonathan 648: }
649:
650: #ifdef alpha
651: /*
652: * XXX
653: * Unit 1 is the remote console, wire it up now.
654: */
655: if ((cputype == ST_DEC_3000_500 && sc->sc_dv.dv_unit == 1) ||
1.3 jonathan 656: (cputype == ST_DEC_3000_300 && sc->sc_dv.dv_unit == 0))
657: {
1.1 jonathan 658: cn_tab = &scccons;
659: cn_tab->cn_dev = makedev(SCCDEV, sc->sc_dv.dv_unit * 2);
660:
1.17 christos 661: printf(": console\n");
1.1 jonathan 662:
663: /* wire carrier for console. */
664: sc->scc_softCAR |= SCCLINE(cn_tab->cn_dev);
665: } else
1.17 christos 666: printf("\n");
1.9 jonathan 667: #endif /* !alpha */
1.17 christos 668: printf("\n");
1.9 jonathan 669: }
670:
1.1 jonathan 671:
672: /*
1.18 jonathan 673: * Reset the chip and the softc state.
674: * Resetting clobbers chip state and copies of registers for both channels.
675: * The driver assumes this is only ever called once per unit.
1.1 jonathan 676: */
677: static void
678: sccreset(sc)
679: register struct scc_softc *sc;
680: {
681: register scc_regmap_t *regs;
682: register u_char val;
683:
684: regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
685: /*
686: * Chip once-only initialization
687: *
688: * NOTE: The wiring we assume is the one on the 3min:
689: *
690: * out A-TxD --> TxD keybd or mouse
691: * in A-RxD --> RxD keybd or mouse
692: * out A-DTR~ --> DTR comm
693: * out A-RTS~ --> RTS comm
694: * in A-CTS~ --> SI comm
695: * in A-DCD~ --> RI comm
696: * in A-SYNCH~--> DSR comm
697: * out B-TxD --> TxD comm
698: * in B-RxD --> RxD comm
699: * in B-RxC --> TRxCB comm
700: * in B-TxC --> RTxCB comm
701: * out B-RTS~ --> SS comm
702: * in B-CTS~ --> CTS comm
703: * in B-DCD~ --> CD comm
704: */
705: SCC_INIT_REG(regs, SCC_CHANNEL_A);
706: SCC_INIT_REG(regs, SCC_CHANNEL_B);
707:
708: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, ZSWR9_HARD_RESET);
709: DELAY(50000); /*enough ? */
710: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, 0);
711:
712: /* program the interrupt vector */
713: SCC_WRITE_REG(regs, SCC_CHANNEL_A, ZSWR_IVEC, 0xf0);
714: SCC_WRITE_REG(regs, SCC_CHANNEL_B, ZSWR_IVEC, 0xf0);
715: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR9, ZSWR9_VECTOR_INCL_STAT);
716:
1.18 jonathan 717: /*
718: * Set softc copies of writable (write-only?) registers.
719: */
720:
1.1 jonathan 721: /* receive parameters and control */
722: sc->scc_wreg[SCC_CHANNEL_A].wr3 = 0;
723: sc->scc_wreg[SCC_CHANNEL_B].wr3 = 0;
724:
725: /* timing base defaults */
726: sc->scc_wreg[SCC_CHANNEL_A].wr4 = ZSWR4_CLK_X16;
727: sc->scc_wreg[SCC_CHANNEL_B].wr4 = ZSWR4_CLK_X16 ;
728:
729: /* enable DTR, RTS and SS */
730: #ifdef alpha
731: /* XXX -- who changed the alpha driver to do this, and why? */
732: sc->scc_wreg[SCC_CHANNEL_B].wr5 = 0;
733: #else
734: sc->scc_wreg[SCC_CHANNEL_B].wr5 = ZSWR5_RTS;
735: #endif
736: sc->scc_wreg[SCC_CHANNEL_A].wr5 = ZSWR5_RTS | ZSWR5_DTR;
737:
738: /* baud rates */
739: val = ZSWR14_BAUD_ENA | ZSWR14_BAUD_FROM_PCLK;
740: sc->scc_wreg[SCC_CHANNEL_B].wr14 = val;
741: sc->scc_wreg[SCC_CHANNEL_A].wr14 = val;
742:
743: /* interrupt conditions */
744: val = ZSWR1_RIE | ZSWR1_PE_SC | ZSWR1_SIE | ZSWR1_TIE;
745: sc->scc_wreg[SCC_CHANNEL_A].wr1 = val;
746: sc->scc_wreg[SCC_CHANNEL_B].wr1 = val;
747: }
748:
749: int
750: sccopen(dev, flag, mode, p)
751: dev_t dev;
752: int flag, mode;
753: struct proc *p;
754: {
755: register struct scc_softc *sc;
756: register struct tty *tp;
757: register int unit, line;
758: int s, error = 0;
1.29 jonathan 759: int firstopen = 0;
1.1 jonathan 760:
761: unit = SCCUNIT(dev);
1.10 thorpej 762: if (unit >= scc_cd.cd_ndevs)
1.1 jonathan 763: return (ENXIO);
1.10 thorpej 764: sc = scc_cd.cd_devs[unit];
1.1 jonathan 765: if (!sc)
766: return (ENXIO);
767:
768: line = SCCLINE(dev);
769: if (sc->scc_pdma[line].p_addr == NULL)
770: return (ENXIO);
1.18 jonathan 771: tp = sc->scc_tty[line];
1.13 mhitch 772: if (tp == NULL) {
1.18 jonathan 773: tp = sc->scc_tty[line] = ttymalloc();
1.13 mhitch 774: tty_attach(tp);
775: }
1.1 jonathan 776: tp->t_oproc = sccstart;
777: tp->t_param = sccparam;
778: tp->t_dev = dev;
779: if ((tp->t_state & TS_ISOPEN) == 0) {
780: tp->t_state |= TS_WOPEN;
1.29 jonathan 781: firstopen = 1;
1.1 jonathan 782: ttychars(tp);
783: #ifndef PORTSELECTOR
784: if (tp->t_ispeed == 0) {
785: #endif
786: tp->t_iflag = TTYDEF_IFLAG;
787: tp->t_oflag = TTYDEF_OFLAG;
788: tp->t_cflag = TTYDEF_CFLAG;
789: tp->t_lflag = LFLAG;
790: tp->t_ispeed = tp->t_ospeed = ISPEED;
791: #ifdef PORTSELECTOR
792: tp->t_cflag |= HUPCL;
793: #else
794: }
795: #endif
796: (void) sccparam(tp, &tp->t_termios);
797: ttsetwater(tp);
1.29 jonathan 798:
1.1 jonathan 799: } else if ((tp->t_state & TS_XCLUDE) && curproc->p_ucred->cr_uid != 0)
800: return (EBUSY);
801: (void) sccmctl(dev, DML_DTR, DMSET);
802: s = spltty();
803: while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
804: !(tp->t_state & TS_CARR_ON)) {
805: tp->t_state |= TS_WOPEN;
806: if ((error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
807: ttopen, 0)) != 0)
808: break;
809: }
810: splx(s);
811: if (error)
812: return (error);
1.29 jonathan 813: error = (*linesw[tp->t_line].l_open)(dev, tp);
814:
815: #ifdef HAVE_RCONS
816: /* handle raster console specially */
817: if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) &&
818: raster_console() && firstopen) {
819: extern struct tty *fbconstty;
820: tp->t_winsize = fbconstty->t_winsize;
821: }
822: #endif /* HAVE_RCONS */
823: return (error);
1.1 jonathan 824: }
825:
826: /*ARGSUSED*/
827: int
828: sccclose(dev, flag, mode, p)
829: dev_t dev;
830: int flag, mode;
831: struct proc *p;
832: {
1.18 jonathan 833: register struct scc_softc *sc = scc_cd.cd_devs[SCCUNIT(dev)];
1.1 jonathan 834: register struct tty *tp;
1.6 jonathan 835: register int line;
1.1 jonathan 836:
837: line = SCCLINE(dev);
1.18 jonathan 838: tp = sc->scc_tty[line];
1.1 jonathan 839: if (sc->scc_wreg[line].wr5 & ZSWR5_BREAK) {
840: sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK;
841: ttyoutput(0, tp);
842: }
843: (*linesw[tp->t_line].l_close)(tp, flag);
844: if ((tp->t_cflag & HUPCL) || (tp->t_state & TS_WOPEN) ||
845: !(tp->t_state & TS_ISOPEN))
846: (void) sccmctl(dev, 0, DMSET);
847: return (ttyclose(tp));
848: }
849:
850: int
851: sccread(dev, uio, flag)
852: dev_t dev;
853: struct uio *uio;
854: int flag;
855: {
1.18 jonathan 856: register struct scc_softc *sc;
1.1 jonathan 857: register struct tty *tp;
858:
1.18 jonathan 859: sc = scc_cd.cd_devs[SCCUNIT(dev)]; /* XXX*/
860: tp = sc->scc_tty[SCCLINE(dev)];
1.1 jonathan 861: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
862: }
863:
864: int
865: sccwrite(dev, uio, flag)
866: dev_t dev;
867: struct uio *uio;
868: int flag;
869: {
1.18 jonathan 870: register struct scc_softc *sc;
1.1 jonathan 871: register struct tty *tp;
872:
1.18 jonathan 873: sc = scc_cd.cd_devs[SCCUNIT(dev)]; /* XXX*/
874: tp = sc->scc_tty[SCCLINE(dev)];
1.1 jonathan 875: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
876: }
877:
878: struct tty *
879: scctty(dev)
880: dev_t dev;
881: {
1.18 jonathan 882: register struct scc_softc *sc;
883: register struct tty *tp;
884: register int unit = SCCUNIT(dev);
1.1 jonathan 885:
1.18 jonathan 886: if ((unit >= scc_cd.cd_ndevs) || (sc = scc_cd.cd_devs[unit]) == 0)
887: return (0);
888: tp = sc->scc_tty[SCCLINE(dev)];
1.1 jonathan 889: return (tp);
890: }
891:
892: /*ARGSUSED*/
893: int
894: sccioctl(dev, cmd, data, flag, p)
895: dev_t dev;
896: u_long cmd;
897: caddr_t data;
898: int flag;
899: struct proc *p;
900: {
901: register struct scc_softc *sc;
902: register struct tty *tp;
903: int error, line;
904:
1.18 jonathan 905: line = SCCLINE(dev);
906: sc = scc_cd.cd_devs[SCCUNIT(dev)];
907: tp = sc->scc_tty[line];
1.1 jonathan 908: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
909: if (error >= 0)
910: return (error);
911: error = ttioctl(tp, cmd, data, flag, p);
912: if (error >= 0)
913: return (error);
914:
915: switch (cmd) {
916:
917: case TIOCSBRK:
918: sc->scc_wreg[line].wr5 |= ZSWR5_BREAK;
919: ttyoutput(0, tp);
920: break;
921:
922: case TIOCCBRK:
923: sc->scc_wreg[line].wr5 &= ~ZSWR5_BREAK;
924: ttyoutput(0, tp);
925: break;
926:
927: case TIOCSDTR:
928: (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIS);
929: break;
930:
931: case TIOCCDTR:
932: (void) sccmctl(dev, DML_DTR|DML_RTS, DMBIC);
933: break;
934:
935: case TIOCMSET:
936: (void) sccmctl(dev, *(int *)data, DMSET);
937: break;
938:
939: case TIOCMBIS:
940: (void) sccmctl(dev, *(int *)data, DMBIS);
941: break;
942:
943: case TIOCMBIC:
944: (void) sccmctl(dev, *(int *)data, DMBIC);
945: break;
946:
947: case TIOCMGET:
948: *(int *)data = sccmctl(dev, 0, DMGET);
949: break;
950:
951: default:
952: return (ENOTTY);
953: }
954: return (0);
955: }
956:
1.18 jonathan 957: /*
958: * Set line parameters -- tty t_param entry point.
959: */
1.1 jonathan 960: int
961: sccparam(tp, t)
962: register struct tty *tp;
963: register struct termios *t;
964: {
965: register struct scc_softc *sc;
1.18 jonathan 966:
967: /* Extract the softc and call cold_sccparam to do all the work. */
968: sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
969: return cold_sccparam(tp, t, sc);
970: }
971:
972:
973: /*
974: * Do what sccparam() (t_param entry point) does, but callable when cold.
975: */
976: static int
977: cold_sccparam(tp, t, sc)
978: register struct tty *tp;
979: register struct termios *t;
980: register struct scc_softc *sc;
981: {
1.1 jonathan 982: register scc_regmap_t *regs;
983: register int line;
984: register u_char value, wvalue;
985: register int cflag = t->c_cflag;
986: int ospeed;
987:
1.18 jonathan 988: /* Check arguments */
989: if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
1.1 jonathan 990: return (EINVAL);
991: ospeed = ttspeedtab(t->c_ospeed, sccspeedtab);
992: if (ospeed < 0)
993: return (EINVAL);
994: /* and copy to tty */
995: tp->t_ispeed = t->c_ispeed;
996: tp->t_ospeed = t->c_ospeed;
997: tp->t_cflag = cflag;
998:
999: /*
1000: * Handle console specially.
1001: */
1.6 jonathan 1002: #ifdef HAVE_RCONS
1.2 jonathan 1003: if (cn_tab->cn_getc == LKgetc) {
1.1 jonathan 1004: if (minor(tp->t_dev) == SCCKBD_PORT) {
1005: cflag = CS8;
1006: ospeed = ttspeedtab(4800, sccspeedtab);
1007: } else if (minor(tp->t_dev) == SCCMOUSE_PORT) {
1008: cflag = CS8 | PARENB | PARODD;
1009: ospeed = ttspeedtab(4800, sccspeedtab);
1010: }
1.2 jonathan 1011: } else if (tp->t_dev == cn_tab->cn_dev)
1.6 jonathan 1012: #endif /*HAVE_RCONS*/
1.1 jonathan 1013: {
1014: cflag = CS8;
1015: ospeed = ttspeedtab(9600, sccspeedtab);
1016: }
1017: if (ospeed == 0) {
1018: (void) sccmctl(tp->t_dev, 0, DMSET); /* hang up line */
1019: return (0);
1020: }
1021:
1022: line = SCCLINE(tp->t_dev);
1023: regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
1024:
1025: /*
1026: * pmax driver used to reset the SCC here. That reset causes the
1027: * other channel on the SCC to drop outpur chars: at least that's
1028: * what CGD reports for the Alpha. It's a bug.
1029: */
1030: #if 0
1031: /* reset line */
1032: if (line == SCC_CHANNEL_A)
1033: value = ZSWR9_A_RESET;
1034: else
1035: value = ZSWR9_B_RESET;
1036: SCC_WRITE_REG(regs, line, SCC_WR9, value);
1037: DELAY(25);
1038: #endif
1039:
1040: /* stop bits, normally 1 */
1041: value = sc->scc_wreg[line].wr4 & 0xf0;
1042: if (cflag & CSTOPB)
1043: value |= ZSWR4_TWOSB;
1044: else
1045: value |= ZSWR4_ONESB;
1046: if ((cflag & PARODD) == 0)
1047: value |= ZSWR4_EVENP;
1048: if (cflag & PARENB)
1049: value |= ZSWR4_PARENB;
1050:
1051: /* set it now, remember it must be first after reset */
1052: sc->scc_wreg[line].wr4 = value;
1053: SCC_WRITE_REG(regs, line, SCC_WR4, value);
1054:
1055: /* vector again */
1056: SCC_WRITE_REG(regs, line, ZSWR_IVEC, 0xf0);
1057:
1058: /* clear break, keep rts dtr */
1059: wvalue = sc->scc_wreg[line].wr5 & (ZSWR5_DTR|ZSWR5_RTS);
1060: switch (cflag & CSIZE) {
1061: case CS5:
1062: value = ZSWR3_RX_5;
1063: wvalue |= ZSWR5_TX_5;
1064: break;
1065: case CS6:
1066: value = ZSWR3_RX_6;
1067: wvalue |= ZSWR5_TX_6;
1068: break;
1069: case CS7:
1070: value = ZSWR3_RX_7;
1071: wvalue |= ZSWR5_TX_7;
1072: break;
1073: case CS8:
1074: default:
1075: value = ZSWR3_RX_8;
1076: wvalue |= ZSWR5_TX_8;
1077: };
1078: sc->scc_wreg[line].wr3 = value;
1079: SCC_WRITE_REG(regs, line, SCC_WR3, value);
1080:
1081: sc->scc_wreg[line].wr5 = wvalue;
1082: SCC_WRITE_REG(regs, line, SCC_WR5, wvalue);
1083:
1084: /*
1085: * XXX Does the SCC chip require us to refresh the WR5 register
1086: * for the other channel after writing the other, or not?
1087: */
1088: #ifdef notdef
1089: /* XXX */
1090: {
1091: int otherline = (line + 1) & 1;
1092: SCC_WRITE_REG(regs, otherline, SCC_WR5, sc->scc_wreg[otherline].wr5);
1093: }
1094: #endif
1095:
1096: SCC_WRITE_REG(regs, line, ZSWR_SYNCLO, 0);
1097: SCC_WRITE_REG(regs, line, ZSWR_SYNCHI, 0);
1098: SCC_WRITE_REG(regs, line, SCC_WR9, ZSWR9_VECTOR_INCL_STAT);
1099: SCC_WRITE_REG(regs, line, SCC_WR10, 0);
1100: value = ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD |
1101: ZSWR11_TRXC_OUT_ENA | ZSWR11_TRXC_BAUD;
1102: SCC_WRITE_REG(regs, line, SCC_WR11, value);
1103: SCC_SET_TIMING_BASE(regs, line, ospeed);
1104: value = sc->scc_wreg[line].wr14;
1105: SCC_WRITE_REG(regs, line, SCC_WR14, value);
1106:
1107: #ifdef alpha
1108: if (SCCUNIT(tp->t_dev) == 1) {
1109: /* On unit one, on the flamingo, modem control is floating! */
1110: value = ZSWR15_BREAK_IE;
1111: } else
1112: #endif
1113: {
1114: value = ZSWR15_BREAK_IE | ZSWR15_CTS_IE | ZSWR15_DCD_IE;
1115: }
1116: SCC_WRITE_REG(regs, line, SCC_WR15, value);
1117:
1118: /* and now the enables */
1119: value = sc->scc_wreg[line].wr3 | ZSWR3_RX_ENABLE;
1120: SCC_WRITE_REG(regs, line, SCC_WR3, value);
1121: value = sc->scc_wreg[line].wr5 | ZSWR5_TX_ENABLE;
1122: sc->scc_wreg[line].wr5 = value;
1123: SCC_WRITE_REG(regs, line, SCC_WR5, value);
1124:
1125: /* master inter enable */
1126: value = ZSWR9_MASTER_IE | ZSWR9_VECTOR_INCL_STAT;
1127: SCC_WRITE_REG(regs, line, SCC_WR9, value);
1128: SCC_WRITE_REG(regs, line, SCC_WR1, sc->scc_wreg[line].wr1);
1.18 jonathan 1129: tc_mb();
1.1 jonathan 1130:
1131: #ifdef alpha
1.18 jonathan 1132: scc_alphaintr(1); /* XXX XXX XXX */
1.1 jonathan 1133: #endif /*alpha*/
1134:
1135: return (0);
1136: }
1137:
1.18 jonathan 1138:
1.1 jonathan 1139: /*
1140: * Check for interrupts from all devices.
1141: */
1.2 jonathan 1142: int
1143: sccintr(xxxsc)
1.18 jonathan 1144: void *xxxsc;
1.1 jonathan 1145: {
1.2 jonathan 1146: register struct scc_softc *sc = (struct scc_softc *)xxxsc;
1.18 jonathan 1147: register int unit = (long)sc->sc_dv.dv_unit;
1.1 jonathan 1148: register scc_regmap_t *regs;
1149: register struct tty *tp;
1150: register struct pdma *dp;
1151: register int cc, chan, rr1, rr2, rr3;
1152: int overrun = 0;
1153:
1.18 jonathan 1154: rr1 = 0; /* shut up gcc -Wall */
1.1 jonathan 1155: regs = (scc_regmap_t *)sc->scc_pdma[0].p_addr;
1156: unit <<= 1;
1157: for (;;) {
1158: SCC_READ_REG(regs, SCC_CHANNEL_B, ZSRR_IVEC, rr2);
1159: rr2 = SCC_RR2_STATUS(rr2);
1160: /* are we done yet ? */
1161: if (rr2 == 6) { /* strange, distinguished value */
1162: SCC_READ_REG(regs, SCC_CHANNEL_A, ZSRR_IPEND, rr3);
1163: if (rr3 == 0)
1.2 jonathan 1164: return 0 ;/* XXX FIXME why ? */
1.1 jonathan 1165: }
1166:
1167: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_RR0, ZSWR0_CLR_INTR);
1168: if ((rr2 == SCC_RR2_A_XMIT_DONE) || (rr2 == SCC_RR2_B_XMIT_DONE)) {
1169: chan = (rr2 == SCC_RR2_A_XMIT_DONE) ?
1170: SCC_CHANNEL_A : SCC_CHANNEL_B;
1.18 jonathan 1171: tp = sc->scc_tty[chan];
1.1 jonathan 1172: dp = &sc->scc_pdma[chan];
1173: if (dp->p_mem < dp->p_end) {
1174: SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
1.3 jonathan 1175: #ifdef pmax /* Alpha handles the 1.6 msec settle time in hardware */
1176: DELAY(2);
1177: #endif
1.18 jonathan 1178: tc_mb();
1.1 jonathan 1179: } else {
1180: tp->t_state &= ~TS_BUSY;
1181: if (tp->t_state & TS_FLUSH)
1182: tp->t_state &= ~TS_FLUSH;
1183: else {
1184: ndflush(&tp->t_outq, dp->p_mem -
1185: (caddr_t) tp->t_outq.c_cf);
1186: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
1187: }
1188: if (tp->t_line)
1189: (*linesw[tp->t_line].l_start)(tp);
1190: else
1191: sccstart(tp);
1192: if (tp->t_outq.c_cc == 0 || !(tp->t_state & TS_BUSY)) {
1193: SCC_READ_REG(regs, chan, SCC_RR15, cc);
1194: cc &= ~ZSWR15_TXUEOM_IE;
1195: SCC_WRITE_REG(regs, chan, SCC_WR15, cc);
1196: cc = sc->scc_wreg[chan].wr1 & ~ZSWR1_TIE;
1197: SCC_WRITE_REG(regs, chan, SCC_WR1, cc);
1198: sc->scc_wreg[chan].wr1 = cc;
1.18 jonathan 1199: tc_mb();
1.1 jonathan 1200: }
1201: }
1202: } else if (rr2 == SCC_RR2_A_RECV_DONE ||
1203: rr2 == SCC_RR2_B_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL ||
1204: rr2 == SCC_RR2_B_RECV_SPECIAL) {
1205: if (rr2 == SCC_RR2_A_RECV_DONE || rr2 == SCC_RR2_A_RECV_SPECIAL)
1206: chan = SCC_CHANNEL_A;
1207: else
1208: chan = SCC_CHANNEL_B;
1.18 jonathan 1209: tp = sc->scc_tty[chan];
1.1 jonathan 1210: SCC_READ_DATA(regs, chan, cc);
1211: if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
1212: rr2 == SCC_RR2_B_RECV_SPECIAL) {
1213: SCC_READ_REG(regs, chan, SCC_RR1, rr1);
1214: SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_ERRORS);
1215: if ((rr1 & ZSRR1_DO) && overrun == 0) {
1216: log(LOG_WARNING, "scc%d,%d: silo overflow\n",
1217: unit >> 1, chan);
1218: overrun = 1;
1219: }
1220: }
1221:
1222: /*
1223: * Keyboard needs special treatment.
1224: */
1.18 jonathan 1225: if (tp == scctty(makedev(SCCDEV, SCCKBD_PORT)) &&
1226: raster_console()) {
1.26 jonathan 1227: #ifdef DDB
1.1 jonathan 1228: if (cc == LK_DO) {
1229: spl0();
1.26 jonathan 1230: Debugger();
1.2 jonathan 1231: return -1;
1.1 jonathan 1232: }
1233: #endif
1.26 jonathan 1234:
1.1 jonathan 1235: #ifdef DEBUG
1236: debugChar = cc;
1237: #endif
1238: if (sccDivertXInput) {
1239: (*sccDivertXInput)(cc);
1240: continue;
1241: }
1.6 jonathan 1242: #ifdef HAVE_RCONS
1.1 jonathan 1243: if ((cc = kbdMapChar(cc)) < 0)
1244: continue;
1245: #endif
1246: /*
1247: * Now for mousey
1248: */
1.18 jonathan 1249: } else if (tp == scctty(makedev(SCCDEV, SCCMOUSE_PORT)) &&
1250: sccMouseButtons) {
1251: #ifdef HAVE_RCONS
1.2 jonathan 1252: /*XXX*/
1253: mouseInput(cc);
1.1 jonathan 1254: continue;
1.18 jonathan 1255: #endif
1.1 jonathan 1256: }
1257: if (!(tp->t_state & TS_ISOPEN)) {
1258: wakeup((caddr_t)&tp->t_rawq);
1259: #ifdef PORTSELECTOR
1260: if (!(tp->t_state & TS_WOPEN))
1261: #endif
1262: continue;
1263: }
1264: if (rr2 == SCC_RR2_A_RECV_SPECIAL ||
1265: rr2 == SCC_RR2_B_RECV_SPECIAL) {
1266: if (rr1 & ZSRR1_PE)
1267: cc |= TTY_PE;
1268: if (rr1 & ZSRR1_FE)
1269: cc |= TTY_FE;
1270: }
1271: (*linesw[tp->t_line].l_rint)(cc, tp);
1272: } else if ((rr2 == SCC_RR2_A_EXT_STATUS) || (rr2 == SCC_RR2_B_EXT_STATUS)) {
1273: chan = (rr2 == SCC_RR2_A_EXT_STATUS) ?
1274: SCC_CHANNEL_A : SCC_CHANNEL_B;
1275: SCC_WRITE_REG(regs, chan, SCC_RR0, ZSWR0_RESET_STATUS);
1276: scc_modem_intr(unit | chan);
1277: }
1278: }
1279: }
1280:
1281: void
1282: sccstart(tp)
1283: register struct tty *tp;
1284: {
1285: register struct pdma *dp;
1286: register scc_regmap_t *regs;
1287: register struct scc_softc *sc;
1288: register int cc, chan;
1289: u_char temp;
1290: int s, sendone;
1291:
1.10 thorpej 1292: sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
1.1 jonathan 1293: dp = &sc->scc_pdma[SCCLINE(tp->t_dev)];
1294: regs = (scc_regmap_t *)dp->p_addr;
1295: s = spltty();
1296: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1297: goto out;
1298: if (tp->t_outq.c_cc <= tp->t_lowat) {
1299: if (tp->t_state & TS_ASLEEP) {
1300: tp->t_state &= ~TS_ASLEEP;
1301: wakeup((caddr_t)&tp->t_outq);
1302: }
1303: selwakeup(&tp->t_wsel);
1304: }
1305: if (tp->t_outq.c_cc == 0)
1306: goto out;
1307: /* handle console specially */
1.18 jonathan 1308: if (tp == scctty(makedev(SCCDEV,SCCKBD_PORT)) && raster_console()) {
1.1 jonathan 1309: while (tp->t_outq.c_cc > 0) {
1310: cc = getc(&tp->t_outq) & 0x7f;
1311: cnputc(cc);
1312: }
1313: /*
1314: * After we flush the output queue we may need to wake
1315: * up the process that made the output.
1316: */
1317: if (tp->t_outq.c_cc <= tp->t_lowat) {
1318: if (tp->t_state & TS_ASLEEP) {
1319: tp->t_state &= ~TS_ASLEEP;
1320: wakeup((caddr_t)&tp->t_outq);
1321: }
1322: selwakeup(&tp->t_wsel);
1323: }
1324: goto out;
1325: }
1.4 jonathan 1326: cc = ndqb(&tp->t_outq, 0);
1327:
1.1 jonathan 1328: tp->t_state |= TS_BUSY;
1329: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
1330: dp->p_end += cc;
1331:
1332: /*
1333: * Enable transmission and send the first char, as required.
1334: */
1335: chan = SCCLINE(tp->t_dev);
1336: SCC_READ_REG(regs, chan, SCC_RR0, temp);
1337: sendone = (temp & ZSRR0_TX_READY);
1338: SCC_READ_REG(regs, chan, SCC_RR15, temp);
1339: temp |= ZSWR15_TXUEOM_IE;
1340: SCC_WRITE_REG(regs, chan, SCC_WR15, temp);
1341: temp = sc->scc_wreg[chan].wr1 | ZSWR1_TIE;
1342: SCC_WRITE_REG(regs, chan, SCC_WR1, temp);
1343: sc->scc_wreg[chan].wr1 = temp;
1344: if (sendone) {
1345: #ifdef DIAGNOSTIC
1346: if (cc == 0)
1347: panic("sccstart: No chars");
1.18 jonathan 1348: #endif
1.1 jonathan 1349: SCC_WRITE_DATA(regs, chan, *dp->p_mem++);
1.3 jonathan 1350: #ifdef pmax /* Alpha handles the 1.6 msec settle time in hardware */
1351: DELAY(2);
1352: #endif
1.1 jonathan 1353: }
1.18 jonathan 1354: tc_mb();
1.1 jonathan 1355: out:
1356: splx(s);
1357: }
1358:
1359: /*
1360: * Stop output on a line.
1361: */
1362: /*ARGSUSED*/
1.14 mycroft 1363: void
1.1 jonathan 1364: sccstop(tp, flag)
1365: register struct tty *tp;
1366: int flag;
1367: {
1368: register struct pdma *dp;
1369: register struct scc_softc *sc;
1370: register int s;
1371:
1.10 thorpej 1372: sc = scc_cd.cd_devs[SCCUNIT(tp->t_dev)];
1.1 jonathan 1373: dp = &sc->scc_pdma[SCCLINE(tp->t_dev)];
1374: s = spltty();
1375: if (tp->t_state & TS_BUSY) {
1376: dp->p_end = dp->p_mem;
1377: if (!(tp->t_state & TS_TTSTOP))
1378: tp->t_state |= TS_FLUSH;
1379: }
1380: splx(s);
1381: }
1382:
1383: int
1384: sccmctl(dev, bits, how)
1385: dev_t dev;
1386: int bits, how;
1387: {
1388: register struct scc_softc *sc;
1389: register scc_regmap_t *regs;
1390: register int line, mbits;
1391: register u_char value;
1392: int s;
1393:
1.10 thorpej 1394: sc = scc_cd.cd_devs[SCCUNIT(dev)];
1.1 jonathan 1395: line = SCCLINE(dev);
1396: regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
1397: s = spltty();
1398: /*
1399: * only channel B has modem control, however the DTR and RTS
1400: * pins on the comm port are wired to the DTR and RTS A channel
1401: * signals.
1402: */
1403: mbits = DML_DTR | DML_DSR | DML_CAR;
1404: if (line == SCC_CHANNEL_B) {
1405: if (sc->scc_wreg[SCC_CHANNEL_A].wr5 & ZSWR5_DTR)
1406: mbits = DML_DTR | DML_DSR;
1407: else
1408: mbits = 0;
1409: SCC_READ_REG_ZERO(regs, SCC_CHANNEL_B, value);
1410: if (value & ZSRR0_DCD)
1411: mbits |= DML_CAR;
1412: }
1413: switch (how) {
1414: case DMSET:
1415: mbits = bits;
1416: break;
1417:
1418: case DMBIS:
1419: mbits |= bits;
1420: break;
1421:
1422: case DMBIC:
1423: mbits &= ~bits;
1424: break;
1425:
1426: case DMGET:
1427: (void) splx(s);
1428: return (mbits);
1429: }
1430: if (line == SCC_CHANNEL_B) {
1431: if (mbits & DML_DTR)
1432: sc->scc_wreg[SCC_CHANNEL_A].wr5 |= ZSWR5_DTR;
1433: else
1434: sc->scc_wreg[SCC_CHANNEL_A].wr5 &= ~ZSWR5_DTR;
1435: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR5,
1436: sc->scc_wreg[SCC_CHANNEL_A].wr5);
1437: }
1438: if ((mbits & DML_DTR) || (sc->scc_softCAR & (1 << line)))
1.18 jonathan 1439: sc->scc_tty[line]->t_state |= TS_CARR_ON;
1.1 jonathan 1440: (void) splx(s);
1441: return (mbits);
1442: }
1443:
1444: /*
1445: * Check for carrier transition.
1446: */
1447: static void
1448: scc_modem_intr(dev)
1449: dev_t dev;
1450: {
1451: register scc_regmap_t *regs;
1452: register struct scc_softc *sc;
1453: register struct tty *tp;
1454: register int car, chan;
1455: register u_char value;
1456: int s;
1457:
1.18 jonathan 1458: chan = SCCLINE(dev);
1.10 thorpej 1459: sc = scc_cd.cd_devs[SCCUNIT(dev)];
1.18 jonathan 1460: tp = sc->scc_tty[chan];
1.1 jonathan 1461: regs = (scc_regmap_t *)sc->scc_pdma[chan].p_addr;
1462: if (chan == SCC_CHANNEL_A)
1463: return;
1464: s = spltty();
1.26 jonathan 1465:
1466: SCC_READ_REG_ZERO(regs, chan, value);
1.1 jonathan 1467: if (sc->scc_softCAR & (1 << chan))
1468: car = 1;
1469: else {
1470: car = value & ZSRR0_DCD;
1471: }
1472:
1.26 jonathan 1473:
1474: /* Break on serial console drops into the dbeugger */
1475: if ((value & ZSRR0_BREAK) && CONSOLE_ON_UNIT(sc->sc_dv.dv_unit)) {
1476: #ifdef DDB
1477: splx(s); /* spl0()? */
1478: Debugger();
1479: return;
1480: #else
1481: /* XXX maybe fall back to PROM? */
1482: #endif
1483: }
1484:
1.1 jonathan 1485: /*
1.18 jonathan 1486: * The pmax driver follows carrier-detect. The Alpha does not.
1487: * XXX Why doesn't the Alpha driver follow carrier-detect?
1.1 jonathan 1488: * (in the Alpha driver, this is an "#ifdef notdef").
1489: * Is it related to console handling?
1.26 jonathan 1490: *
1491: * Ignore hups on a console tty.
1.1 jonathan 1492: */
1493: #ifndef alpha
1.26 jonathan 1494: if (!CONSOLE_ON_UNIT(sc->sc_dv.dv_unit)) {
1495: if (car) {
1496: /* carrier present */
1497: if (!(tp->t_state & TS_CARR_ON))
1498: (void)(*linesw[tp->t_line].l_modem)(tp, 1);
1499: } else if (tp->t_state & TS_CARR_ON)
1500: (void)(*linesw[tp->t_line].l_modem)(tp, 0);
1501: }
1502: #endif
1.1 jonathan 1503: splx(s);
1504: }
1505:
1506: /*
1507: * Get a char off the appropriate line via. a busy wait loop.
1508: */
1509: int
1510: sccGetc(dev)
1511: dev_t dev;
1512: {
1513: register scc_regmap_t *regs;
1514: register int c, line;
1515: register u_char value;
1516: int s;
1517:
1518: line = SCCLINE(dev);
1.18 jonathan 1519: if (cold && scc_cons_addr) {
1520: regs = scc_cons_addr;
1521: } else {
1522: register struct scc_softc *sc;
1523: sc = scc_cd.cd_devs[SCCUNIT(dev)];
1524: regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
1525: }
1526:
1.1 jonathan 1527: if (!regs)
1528: return (0);
1529: #ifdef pmax
1.2 jonathan 1530: /*s = spltty(); */ /* XXX why different spls? */
1531: s = splhigh();
1.1 jonathan 1532: #else
1533: s = splhigh();
1534: #endif
1535: for (;;) {
1536: SCC_READ_REG(regs, line, SCC_RR0, value);
1537: if (value & ZSRR0_RX_READY) {
1538: SCC_READ_REG(regs, line, SCC_RR1, value);
1539: SCC_READ_DATA(regs, line, c);
1540: if (value & (ZSRR1_PE | ZSRR1_DO | ZSRR1_FE)) {
1541: SCC_WRITE_REG(regs, line, SCC_WR0,
1542: ZSWR0_RESET_ERRORS);
1543: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
1544: ZSWR0_CLR_INTR);
1545: } else {
1546: SCC_WRITE_REG(regs, SCC_CHANNEL_A, SCC_WR0,
1547: ZSWR0_CLR_INTR);
1548: splx(s);
1549: return (c & 0xff);
1550: }
1551: } else
1552: DELAY(10);
1553: }
1554: }
1555:
1556: /*
1557: * Send a char on a port, via a busy wait loop.
1558: */
1559: void
1560: sccPutc(dev, c)
1561: dev_t dev;
1562: int c;
1563: {
1564: register scc_regmap_t *regs;
1565: register int line;
1566: register u_char value;
1567: int s;
1568:
1569: #ifdef pmax
1570: s = spltty(); /* XXX why different spls? */
1571: #else
1572: s = splhigh();
1573: #endif
1574: line = SCCLINE(dev);
1.18 jonathan 1575: if (cold && scc_cons_addr) {
1576: regs = scc_cons_addr;
1577: } else {
1578: register struct scc_softc *sc;
1579: sc = scc_cd.cd_devs[SCCUNIT(dev)];
1580: regs = (scc_regmap_t *)sc->scc_pdma[line].p_addr;
1581: }
1.1 jonathan 1582:
1583: /*
1584: * Wait for transmitter to be not busy.
1585: */
1586: do {
1587: SCC_READ_REG(regs, line, SCC_RR0, value);
1588: if (value & ZSRR0_TX_READY)
1589: break;
1590: DELAY(100);
1591: } while (1);
1592:
1593: /*
1594: * Send the char.
1595: */
1596: SCC_WRITE_DATA(regs, line, c);
1.18 jonathan 1597: tc_mb();
1.1 jonathan 1598: splx(s);
1599:
1600: return;
1601: }
1602:
1603: /*
1604: * Enable/disable polling mode
1605: */
1606: void
1607: sccPollc(dev, on)
1608: dev_t dev;
1609: int on;
1610: {
1611: }
1612:
1613: #ifdef SCC_DEBUG
1614: static void
1615: rr(msg, regs)
1616: char *msg;
1617: scc_regmap_t *regs;
1618: {
1619: u_char value;
1620: int r0, r1, r2, r3, r10, r15;
1621:
1.17 christos 1622: printf("%s: register: %lx\n", msg, regs);
1.1 jonathan 1623: #define L(reg, r) { \
1624: SCC_READ_REG(regs, SCC_CHANNEL_A, reg, value); \
1625: r = value; \
1626: }
1627: L(SCC_RR0, r0);
1628: L(SCC_RR1, r1);
1629: L(ZSRR_IVEC, r2);
1630: L(ZSRR_IPEND, r3);
1631: L(SCC_RR10, r10);
1632: L(SCC_RR15, r15);
1.17 christos 1633: printf("A: 0: %x 1: %x 2(vec): %x 3: %x 10: %x 15: %x\n",
1.1 jonathan 1634: r0, r1, r2, r3, r10, r15);
1635: #undef L
1636: #define L(reg, r) { \
1637: SCC_READ_REG(regs, SCC_CHANNEL_B, reg, value); \
1638: r = value; \
1639: }
1640: L(SCC_RR0, r0);
1641: L(SCC_RR1, r1);
1642: L(ZSRR_IVEC, r2);
1643: L(SCC_RR10, r10);
1644: L(SCC_RR15, r15);
1.17 christos 1645: printf("B: 0: %x 1: %x 2(state): %x 10: %x 15: %x\n",
1.1 jonathan 1646: r0, r1, r2, r10, r15);
1647: }
1.2 jonathan 1648: #endif /* SCC_DEBUG */
CVSweb <webmaster@jp.NetBSD.org>