zs.c revision 1.2 1 1.2 thorpej i* $NetBSD: zs.c,v 1.2 1996/03/17 01:35:05 thorpej Exp $ */
2 1.1 chuck
3 1.1 chuck /*
4 1.1 chuck * Copyright (c) 1993 Paul Mackerras.
5 1.1 chuck * All rights reserved.
6 1.1 chuck *
7 1.1 chuck * Redistribution and use in source and binary forms, with or without
8 1.1 chuck * modification, are permitted provided that the following conditions
9 1.1 chuck * are met:
10 1.1 chuck * 1. Redistributions of source code must retain the above copyright
11 1.1 chuck * notice, this list of conditions and the following disclaimer.
12 1.1 chuck * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 chuck * notice, this list of conditions and the following disclaimer in the
14 1.1 chuck * documentation and/or other materials provided with the distribution.
15 1.1 chuck * 3. The name of the author may not be used to endorse or promote products
16 1.1 chuck * derived from this software withough specific prior written permission
17 1.1 chuck *
18 1.1 chuck * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 1.1 chuck * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 1.1 chuck * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 1.1 chuck * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 1.1 chuck * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 1.1 chuck * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 1.1 chuck * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 1.1 chuck * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 1.1 chuck * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 1.1 chuck * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 1.1 chuck */
29 1.1 chuck /*
30 1.1 chuck * Serial I/O via an SCC,
31 1.1 chuck */
32 1.1 chuck #include <sys/param.h>
33 1.1 chuck #include <sys/conf.h>
34 1.1 chuck #include <sys/ioctl.h>
35 1.1 chuck #include <sys/proc.h>
36 1.1 chuck #include <sys/user.h>
37 1.1 chuck #include <sys/tty.h>
38 1.1 chuck #include <sys/uio.h>
39 1.1 chuck #include <sys/callout.h>
40 1.1 chuck #include <sys/systm.h>
41 1.1 chuck #include <sys/kernel.h>
42 1.1 chuck #include <sys/syslog.h>
43 1.1 chuck #include <sys/fcntl.h>
44 1.1 chuck #include <sys/device.h>
45 1.1 chuck #include <machine/cpu.h>
46 1.1 chuck #include <dev/cons.h>
47 1.1 chuck #include <mvme68k/dev/iio.h>
48 1.1 chuck #include <mvme68k/dev/scc.h>
49 1.1 chuck #include <mvme68k/dev/pccreg.h>
50 1.1 chuck
51 1.1 chuck #include "zs.h"
52 1.1 chuck #if NZS > 0
53 1.1 chuck
54 1.1 chuck /*#define PCLK_FREQ 8333333*/
55 1.1 chuck #undef PCLK_FREQ /* XXXCDC */
56 1.1 chuck #define PCLK_FREQ 5000000
57 1.1 chuck #define NZSLINE (NZS*2)
58 1.1 chuck
59 1.1 chuck #define RECV_BUF 512
60 1.1 chuck #define ERROR_DET 0xed
61 1.1 chuck
62 1.1 chuck #define TS_DRAIN TS_FLUSH/* waiting for output to drain */
63 1.1 chuck
64 1.1 chuck #define splzs() spl4()
65 1.1 chuck
66 1.1 chuck struct zs {
67 1.1 chuck short flags; /* see below */
68 1.1 chuck char rr0; /* holds previous CTS, DCD state */
69 1.1 chuck unsigned char imask; /* mask for input chars */
70 1.1 chuck int nzs_open; /* # opens as /dev/zsn */
71 1.1 chuck int nkbd_open; /* # opens as a keyboard */
72 1.1 chuck int gsp_unit; /* unit to send kbd chars to */
73 1.1 chuck struct tty *tty; /* link to tty structure */
74 1.1 chuck struct sccregs scc; /* SCC shadow registers */
75 1.1 chuck u_char *rcv_get;
76 1.1 chuck u_char *rcv_put;
77 1.1 chuck u_char *rcv_end;
78 1.1 chuck volatile int rcv_count;
79 1.1 chuck int rcv_len;
80 1.1 chuck char *send_ptr;
81 1.1 chuck int send_count;
82 1.1 chuck int sent_count;
83 1.1 chuck volatile char modem_state;
84 1.1 chuck volatile char modem_change;
85 1.1 chuck volatile short hflags;
86 1.1 chuck char rcv_buf[RECV_BUF];
87 1.1 chuck };
88 1.1 chuck
89 1.1 chuck /* Bits in flags */
90 1.1 chuck #define ZS_SIDEA 1
91 1.1 chuck #define ZS_INITED 2
92 1.1 chuck #define ZS_INTEN 4
93 1.1 chuck #define ZS_RESET 8
94 1.1 chuck #define ZS_CONSOLE 0x20
95 1.1 chuck
96 1.1 chuck /* Bits in hflags */
97 1.1 chuck #define ZH_OBLOCK 1 /* output blocked by CTS */
98 1.1 chuck #define ZH_SIRQ 2 /* soft interrupt request */
99 1.1 chuck #define ZH_TXING 4 /* transmitter active */
100 1.1 chuck #define ZH_RXOVF 8 /* receiver buffer overflow */
101 1.1 chuck
102 1.1 chuck struct zssoftc {
103 1.1 chuck struct device dev;
104 1.1 chuck struct zs zs[2];
105 1.1 chuck };
106 1.1 chuck
107 1.1 chuck struct tty *zs_tty[NZSLINE];
108 1.1 chuck
109 1.1 chuck struct termios zs_cons_termios;
110 1.1 chuck int zs_cons_unit = 0;
111 1.1 chuck int zs_is_console = 0;
112 1.1 chuck struct sccregs *zs_cons_scc;
113 1.1 chuck
114 1.1 chuck int zsopen __P((dev_t, int, int, struct proc *));
115 1.1 chuck void zsstart __P((struct tty *));
116 1.1 chuck int zsparam __P((struct tty *, struct termios *));
117 1.1 chuck int zsirq __P((int unit));
118 1.1 chuck void zs_softint __P((void));
119 1.1 chuck
120 1.1 chuck unsigned long sir_zs;
121 1.1 chuck void zs_softint();
122 1.1 chuck
123 1.1 chuck #define zsunit(dev) (minor(dev) >> 1)
124 1.1 chuck #define zsside(dev) (minor(dev) & 1)
125 1.1 chuck
126 1.1 chuck /*
127 1.1 chuck * Autoconfiguration stuff.
128 1.1 chuck */
129 1.1 chuck void zsattach __P((struct device *, struct device *, void *));
130 1.1 chuck int zsmatch __P((struct device *, void *, void *));
131 1.1 chuck
132 1.2 thorpej struct cfattach zs_ca = {
133 1.2 thorpej sizeof(struct zssoftc), zsmatch, zsattach
134 1.2 thorpej };
135 1.2 thorpej
136 1.2 thorpej struct cfdriver zs_cd = {
137 1.2 thorpej NULL, "zs", DV_TTY, 0
138 1.1 chuck };
139 1.1 chuck
140 1.1 chuck int
141 1.1 chuck zsmatch(parent, vcf, args)
142 1.1 chuck struct device *parent;
143 1.1 chuck void *vcf, *args;
144 1.1 chuck {
145 1.1 chuck struct cfdata *cf = vcf;
146 1.1 chuck
147 1.1 chuck return !badbaddr((caddr_t) IIO_CFLOC_ADDR(cf));
148 1.1 chuck }
149 1.1 chuck
150 1.1 chuck void
151 1.1 chuck zsattach(parent, self, args)
152 1.1 chuck struct device *parent, *self;
153 1.1 chuck void *args;
154 1.1 chuck {
155 1.1 chuck struct zssoftc *dv;
156 1.1 chuck struct zs *zp, *zc;
157 1.1 chuck u_char ir;
158 1.1 chuck volatile struct scc *scc;
159 1.1 chuck int zs_level = IIO_CFLOC_LEVEL(self->dv_cfdata);
160 1.1 chuck
161 1.1 chuck iio_print(self->dv_cfdata);
162 1.1 chuck
163 1.1 chuck /* connect the interrupt */
164 1.1 chuck dv = (struct zssoftc *) self;
165 1.1 chuck pccintr_establish(PCCV_ZS, zsirq, zs_level, self->dv_unit);
166 1.1 chuck /* XXXCDC: needs some work to handle zs1 */
167 1.1 chuck
168 1.1 chuck zp = &dv->zs[0];
169 1.1 chuck scc = (volatile struct scc *) IIO_CFLOC_ADDR(self->dv_cfdata);
170 1.1 chuck
171 1.1 chuck if (zs_is_console && self->dv_unit == zsunit(zs_cons_unit)) {
172 1.1 chuck /* SCC is the console - it's already reset */
173 1.1 chuck zc = zp + zsside(zs_cons_unit);
174 1.1 chuck zc->scc = *zs_cons_scc;
175 1.1 chuck zs_cons_scc = &zc->scc;
176 1.1 chuck zc->flags |= ZS_CONSOLE;
177 1.1 chuck } else {
178 1.1 chuck /* reset the SCC */
179 1.1 chuck scc->cr = 0;
180 1.1 chuck scc->cr = 9;
181 1.1 chuck scc->cr = 0xC0; /* hardware reset of SCC, both sides */
182 1.1 chuck }
183 1.1 chuck
184 1.1 chuck /* side A */
185 1.1 chuck zp->scc.s_adr = scc + 1;
186 1.1 chuck zp->flags |= ZS_SIDEA | ZS_RESET;
187 1.1 chuck
188 1.1 chuck /* side B */
189 1.1 chuck ++zp;
190 1.1 chuck zp->scc.s_adr = scc;
191 1.1 chuck zp->flags |= ZS_RESET;
192 1.1 chuck
193 1.1 chuck if (sir_zs == 0)
194 1.1 chuck sir_zs = allocate_sir(zs_softint, 0);
195 1.1 chuck printf("\n");
196 1.1 chuck
197 1.1 chuck ir = sys_pcc->zs_int;
198 1.1 chuck if ((ir & PCC_IMASK) != 0 && (ir & PCC_IMASK) != zs_level)
199 1.1 chuck panic("zs configured at different IPLs");
200 1.1 chuck sys_pcc->zs_int = zs_level | PCC_IENABLE | PCC_ZSEXTERN;
201 1.1 chuck }
202 1.1 chuck
203 1.1 chuck zs_ttydef(struct zs *zp)
204 1.1 chuck {
205 1.1 chuck struct tty *tp = zp->tty;
206 1.1 chuck
207 1.1 chuck if ((zp->flags & ZS_CONSOLE) == 0) {
208 1.1 chuck tp->t_iflag = TTYDEF_IFLAG;
209 1.1 chuck tp->t_oflag = TTYDEF_OFLAG;
210 1.1 chuck tp->t_cflag = TTYDEF_CFLAG;
211 1.1 chuck tp->t_lflag = TTYDEF_LFLAG;
212 1.1 chuck tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
213 1.1 chuck } else
214 1.1 chuck tp->t_termios = zs_cons_termios;
215 1.1 chuck ttychars(tp);
216 1.1 chuck ttsetwater(tp);
217 1.1 chuck tp->t_oproc = zsstart;
218 1.1 chuck tp->t_param = zsparam;
219 1.1 chuck
220 1.1 chuck zp->rcv_get = zp->rcv_buf;
221 1.1 chuck zp->rcv_put = zp->rcv_buf;
222 1.1 chuck zp->rcv_end = zp->rcv_buf + sizeof(zp->rcv_buf);
223 1.1 chuck zp->rcv_len = sizeof(zp->rcv_buf) / 2;
224 1.1 chuck }
225 1.1 chuck
226 1.1 chuck struct tty *
227 1.1 chuck zstty(dev)
228 1.1 chuck dev_t dev;
229 1.1 chuck {
230 1.1 chuck
231 1.1 chuck if (minor(dev) < NZSLINE)
232 1.1 chuck return (zs_tty[minor(dev)]);
233 1.1 chuck
234 1.1 chuck return (NULL);
235 1.1 chuck }
236 1.1 chuck
237 1.1 chuck /* ARGSUSED */
238 1.1 chuck zsopen(dev_t dev, int flag, int mode, struct proc * p)
239 1.1 chuck {
240 1.1 chuck register struct tty *tp;
241 1.1 chuck int error;
242 1.1 chuck struct zs *zp;
243 1.1 chuck struct zssoftc *dv;
244 1.1 chuck
245 1.2 thorpej if (zsunit(dev) > zs_cd.cd_ndevs
246 1.2 thorpej || (dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)]) == NULL)
247 1.1 chuck return ENODEV;
248 1.1 chuck
249 1.1 chuck zp = &dv->zs[zsside(dev)];
250 1.1 chuck if (zp->tty == NULL) {
251 1.1 chuck zp->tty = ttymalloc();
252 1.1 chuck zs_ttydef(zp);
253 1.1 chuck if (minor(dev) < NZSLINE)
254 1.1 chuck zs_tty[minor(dev)] = zp->tty;
255 1.1 chuck }
256 1.1 chuck tp = zp->tty;
257 1.1 chuck tp->t_dev = dev;
258 1.1 chuck
259 1.1 chuck if ((tp->t_state & TS_ISOPEN) == 0) {
260 1.1 chuck tp->t_state |= TS_WOPEN;
261 1.1 chuck zs_init(zp);
262 1.1 chuck if ((zp->modem_state & SCC_DCD) != 0)
263 1.1 chuck tp->t_state |= TS_CARR_ON;
264 1.1 chuck } else
265 1.1 chuck if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
266 1.1 chuck return (EBUSY);
267 1.1 chuck
268 1.1 chuck error = ((*linesw[tp->t_line].l_open) (dev, tp));
269 1.1 chuck
270 1.1 chuck if (error == 0)
271 1.1 chuck ++zp->nzs_open;
272 1.1 chuck return error;
273 1.1 chuck }
274 1.1 chuck
275 1.1 chuck int
276 1.1 chuck zsclose(dev, flag, mode, p)
277 1.1 chuck dev_t dev;
278 1.1 chuck int flag, mode;
279 1.1 chuck struct proc *p;
280 1.1 chuck {
281 1.1 chuck struct zs *zp;
282 1.1 chuck struct tty *tp;
283 1.1 chuck struct zssoftc *dv;
284 1.1 chuck int s;
285 1.1 chuck
286 1.2 thorpej if (zsunit(dev) > zs_cd.cd_ndevs
287 1.2 thorpej || (dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)]) == NULL)
288 1.1 chuck return ENODEV;
289 1.1 chuck zp = &dv->zs[zsside(dev)];
290 1.1 chuck tp = zp->tty;
291 1.1 chuck
292 1.1 chuck if (zp->nkbd_open == 0) {
293 1.1 chuck (*linesw[tp->t_line].l_close) (tp, flag);
294 1.1 chuck s = splzs();
295 1.1 chuck if ((zp->flags & ZS_CONSOLE) == 0 && (tp->t_cflag & HUPCL) != 0)
296 1.1 chuck ZBIC(&zp->scc, 5, 0x82); /* drop DTR, RTS */
297 1.1 chuck ZBIC(&zp->scc, 3, 1); /* disable receiver */
298 1.1 chuck splx(s);
299 1.1 chuck ttyclose(tp);
300 1.1 chuck }
301 1.1 chuck zp->nzs_open = 0;
302 1.1 chuck return (0);
303 1.1 chuck }
304 1.1 chuck
305 1.1 chuck /*ARGSUSED*/
306 1.1 chuck zsread(dev, uio, flag)
307 1.1 chuck dev_t dev;
308 1.1 chuck struct uio *uio;
309 1.1 chuck int flag;
310 1.1 chuck {
311 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
312 1.1 chuck struct zs *zp = &dv->zs[zsside(dev)];
313 1.1 chuck struct tty *tp = zp->tty;
314 1.1 chuck
315 1.1 chuck return ((*linesw[tp->t_line].l_read) (tp, uio, flag));
316 1.1 chuck }
317 1.1 chuck
318 1.1 chuck /*ARGSUSED*/
319 1.1 chuck zswrite(dev, uio, flag)
320 1.1 chuck dev_t dev;
321 1.1 chuck struct uio *uio;
322 1.1 chuck int flag;
323 1.1 chuck {
324 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
325 1.1 chuck struct zs *zp = &dv->zs[zsside(dev)];
326 1.1 chuck struct tty *tp = zp->tty;
327 1.1 chuck
328 1.1 chuck return ((*linesw[tp->t_line].l_write) (tp, uio, flag));
329 1.1 chuck }
330 1.1 chuck
331 1.1 chuck zsioctl(dev, cmd, data, flag, p)
332 1.1 chuck dev_t dev;
333 1.1 chuck caddr_t data;
334 1.1 chuck int cmd, flag;
335 1.1 chuck struct proc *p;
336 1.1 chuck {
337 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(dev)];
338 1.1 chuck struct zs *zp = &dv->zs[zsside(dev)];
339 1.1 chuck struct tty *tp = zp->tty;
340 1.1 chuck register struct sccregs *scc = &zp->scc;
341 1.1 chuck register int error, s;
342 1.1 chuck
343 1.1 chuck error = (*linesw[tp->t_line].l_ioctl) (tp, cmd, data, flag, p);
344 1.1 chuck if (error >= 0)
345 1.1 chuck return (error);
346 1.1 chuck error = ttioctl(tp, cmd, data, flag, p);
347 1.1 chuck if (error >= 0)
348 1.1 chuck return (error);
349 1.1 chuck error = 0;
350 1.1 chuck s = splzs();
351 1.1 chuck switch (cmd) {
352 1.1 chuck case TIOCSDTR:
353 1.1 chuck ZBIS(scc, 5, 0x80);
354 1.1 chuck break;
355 1.1 chuck case TIOCCDTR:
356 1.1 chuck ZBIC(scc, 5, 0x80);
357 1.1 chuck break;
358 1.1 chuck case TIOCSBRK:
359 1.1 chuck splx(s);
360 1.1 chuck zs_drain(zp);
361 1.1 chuck s = splzs();
362 1.1 chuck ZBIS(scc, 5, 0x10);
363 1.1 chuck spltty();
364 1.1 chuck zs_unblock(tp);
365 1.1 chuck break;
366 1.1 chuck case TIOCCBRK:
367 1.1 chuck ZBIC(scc, 5, 0x10);
368 1.1 chuck break;
369 1.1 chuck case TIOCMGET:
370 1.1 chuck *(int *) data = zscc_mget(scc);
371 1.1 chuck break;
372 1.1 chuck case TIOCMSET:
373 1.1 chuck zscc_mset(scc, *(int *) data);
374 1.1 chuck zscc_mclr(scc, ~*(int *) data);
375 1.1 chuck break;
376 1.1 chuck case TIOCMBIS:
377 1.1 chuck zscc_mset(scc, *(int *) data);
378 1.1 chuck break;
379 1.1 chuck case TIOCMBIC:
380 1.1 chuck zscc_mclr(scc, *(int *) data);
381 1.1 chuck break;
382 1.1 chuck default:
383 1.1 chuck error = ENOTTY;
384 1.1 chuck }
385 1.1 chuck splx(s);
386 1.1 chuck return error;
387 1.1 chuck }
388 1.1 chuck
389 1.1 chuck zsparam(tp, t)
390 1.1 chuck struct tty *tp;
391 1.1 chuck struct termios *t;
392 1.1 chuck {
393 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
394 1.1 chuck struct zs *zp = &dv->zs[zsside(tp->t_dev)];
395 1.1 chuck register int s;
396 1.1 chuck
397 1.1 chuck zs_drain(zp);
398 1.1 chuck s = splzs();
399 1.1 chuck zp->imask = zscc_params(&zp->scc, t);
400 1.1 chuck tp->t_ispeed = t->c_ispeed;
401 1.1 chuck tp->t_ospeed = t->c_ospeed;
402 1.1 chuck tp->t_cflag = t->c_cflag;
403 1.1 chuck if ((tp->t_cflag & CCTS_OFLOW) == 0)
404 1.1 chuck zp->hflags &= ~ZH_OBLOCK;
405 1.1 chuck else
406 1.1 chuck if ((zp->modem_state & 0x20) == 0)
407 1.1 chuck zp->hflags |= ZH_OBLOCK;
408 1.1 chuck spltty();
409 1.1 chuck zs_unblock(tp);
410 1.1 chuck splx(s);
411 1.1 chuck return 0;
412 1.1 chuck }
413 1.1 chuck
414 1.1 chuck void
415 1.1 chuck zsstart(tp)
416 1.1 chuck struct tty *tp;
417 1.1 chuck {
418 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
419 1.1 chuck struct zs *zp = &dv->zs[zsside(tp->t_dev)];
420 1.1 chuck register int s, n;
421 1.1 chuck
422 1.1 chuck s = spltty();
423 1.1 chuck if ((tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP | TS_DRAIN)) == 0) {
424 1.1 chuck n = ndqb(&tp->t_outq, 0);
425 1.1 chuck if (n > 0) {
426 1.1 chuck tp->t_state |= TS_BUSY;
427 1.1 chuck splzs();
428 1.1 chuck zp->hflags |= ZH_TXING;
429 1.1 chuck zp->send_ptr = tp->t_outq.c_cf;
430 1.1 chuck zp->send_count = n;
431 1.1 chuck zp->sent_count = 0;
432 1.1 chuck zs_txint(zp);
433 1.1 chuck spltty();
434 1.1 chuck }
435 1.1 chuck }
436 1.1 chuck splx(s);
437 1.1 chuck }
438 1.1 chuck
439 1.1 chuck zsstop(struct tty * tp, int flag)
440 1.1 chuck {
441 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(tp->t_dev)];
442 1.1 chuck struct zs *zp = &dv->zs[zsside(tp->t_dev)];
443 1.1 chuck int s, n;
444 1.1 chuck
445 1.1 chuck s = splzs();
446 1.1 chuck zp->send_count = 0;
447 1.1 chuck n = zp->sent_count;
448 1.1 chuck zp->sent_count = 0;
449 1.1 chuck if ((tp->t_state & TS_BUSY) != 0 && (flag & FWRITE) == 0) {
450 1.1 chuck tp->t_state &= ~TS_BUSY;
451 1.1 chuck spltty();
452 1.1 chuck ndflush(&tp->t_outq, n);
453 1.1 chuck if (tp->t_outq.c_cc <= tp->t_lowat) {
454 1.1 chuck if (tp->t_state & TS_ASLEEP) {
455 1.1 chuck tp->t_state &= ~TS_ASLEEP;
456 1.1 chuck wakeup((caddr_t) & tp->t_outq);
457 1.1 chuck }
458 1.1 chuck selwakeup(&tp->t_wsel);
459 1.1 chuck }
460 1.1 chuck }
461 1.1 chuck splx(s);
462 1.1 chuck }
463 1.1 chuck
464 1.1 chuck zs_init(zp)
465 1.1 chuck struct zs *zp;
466 1.1 chuck {
467 1.1 chuck register int s;
468 1.1 chuck
469 1.1 chuck s = splzs();
470 1.1 chuck zscc_init(zp, &zp->tty->t_termios);
471 1.1 chuck zp->rr0 = zp->modem_state = ZREAD0(&zp->scc);
472 1.1 chuck ZBIS(&zp->scc, 1, 0x13);/* ints on tx, rx and ext/status */
473 1.1 chuck ZBIS(&zp->scc, 9, 8); /* enable ints */
474 1.1 chuck zp->flags |= ZS_INTEN;
475 1.1 chuck splx(s);
476 1.1 chuck }
477 1.1 chuck
478 1.1 chuck zscc_init(zp, par)
479 1.1 chuck struct zs *zp;
480 1.1 chuck struct termios *par;
481 1.1 chuck {
482 1.1 chuck struct sccregs *scc;
483 1.1 chuck
484 1.1 chuck scc = &zp->scc;
485 1.1 chuck ZWRITE(scc, 2, 0);
486 1.1 chuck ZWRITE(scc, 10, 0);
487 1.1 chuck ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
488 1.1 chuck ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
489 1.1 chuck zp->imask = zscc_params(scc, par);
490 1.1 chuck ZBIS(scc, 5, 0x82); /* set DTR and RTS */
491 1.1 chuck zp->flags |= ZS_INITED;
492 1.1 chuck }
493 1.1 chuck
494 1.1 chuck int
495 1.1 chuck zscc_params(scc, par)
496 1.1 chuck struct sccregs *scc;
497 1.1 chuck struct termios *par;
498 1.1 chuck {
499 1.1 chuck unsigned divisor, speed;
500 1.1 chuck int spd, imask, ints;
501 1.1 chuck
502 1.1 chuck speed = par->c_ospeed;
503 1.1 chuck if (speed == 0) {
504 1.1 chuck /* disconnect - drop DTR & RTS, disable receiver */
505 1.1 chuck ZBIC(scc, 5, 0x82);
506 1.1 chuck ZBIC(scc, 3, 1);
507 1.1 chuck return 0xFF;
508 1.1 chuck }
509 1.1 chuck if ((par->c_cflag & CREAD) == 0)
510 1.1 chuck ZBIC(scc, 3, 1);/* disable receiver */
511 1.1 chuck divisor = (PCLK_FREQ / 32 + (speed >> 1)) / speed - 2;
512 1.1 chuck ZWRITE(scc, 12, divisor);
513 1.1 chuck ZWRITE(scc, 13, divisor >> 8);
514 1.1 chuck switch (par->c_cflag & CSIZE) {
515 1.1 chuck case CS5:
516 1.1 chuck spd = 0;
517 1.1 chuck imask = 0x1F;
518 1.1 chuck break;
519 1.1 chuck case CS6:
520 1.1 chuck spd = 0x40;
521 1.1 chuck imask = 0x3F;
522 1.1 chuck break;
523 1.1 chuck case CS7:
524 1.1 chuck spd = 0x20;
525 1.1 chuck imask = 0x7F;
526 1.1 chuck break;
527 1.1 chuck default:
528 1.1 chuck spd = 0x60;
529 1.1 chuck imask = 0xFF;
530 1.1 chuck }
531 1.1 chuck ZWRITE(scc, 5, (scc->s_val[5] & ~0x60) | spd);
532 1.1 chuck ZWRITE(scc, 3, (scc->s_val[3] & ~0xC0) | (spd << 1));
533 1.1 chuck spd = par->c_cflag & CSTOPB ? 8 : 0;
534 1.1 chuck spd |= par->c_cflag & PARENB ? par->c_cflag & PARODD ? 1 : 3 : 0;
535 1.1 chuck ZWRITE(scc, 4, 0x44 | spd);
536 1.1 chuck ZBIS(scc, 5, 8); /* enable transmitter */
537 1.1 chuck if ((par->c_cflag & CREAD) != 0)
538 1.1 chuck ZBIS(scc, 3, 1);/* enable receiver */
539 1.1 chuck ints = 0;
540 1.1 chuck if ((par->c_cflag & CLOCAL) == 0)
541 1.1 chuck ints |= SCC_DCD;
542 1.1 chuck if ((par->c_cflag & CCTS_OFLOW) != 0)
543 1.1 chuck ints |= SCC_CTS;
544 1.1 chuck ZWRITE(scc, 15, ints);
545 1.1 chuck return imask;
546 1.1 chuck }
547 1.1 chuck
548 1.1 chuck zscc_mget(register struct sccregs * scc)
549 1.1 chuck {
550 1.1 chuck int bits = 0, rr0;
551 1.1 chuck
552 1.1 chuck if ((scc->s_val[3] & SCC_RCVEN) != 0)
553 1.1 chuck bits |= TIOCM_LE;
554 1.1 chuck if ((scc->s_val[5] & SCC_DTR) != 0)
555 1.1 chuck bits |= TIOCM_DTR;
556 1.1 chuck if ((scc->s_val[5] & SCC_RTS) != 0)
557 1.1 chuck bits |= TIOCM_RTS;
558 1.1 chuck rr0 = ZREAD0(scc);
559 1.1 chuck if ((rr0 & SCC_CTS) != 0)
560 1.1 chuck bits |= TIOCM_CTS;
561 1.1 chuck if ((rr0 & SCC_DCD) != 0)
562 1.1 chuck bits |= TIOCM_CAR;
563 1.1 chuck return bits;
564 1.1 chuck }
565 1.1 chuck
566 1.1 chuck zscc_mset(register struct sccregs * scc, int bits)
567 1.1 chuck {
568 1.1 chuck if ((bits & TIOCM_LE) != 0)
569 1.1 chuck ZBIS(scc, 3, SCC_RCVEN);
570 1.1 chuck if ((bits & TIOCM_DTR) != 0)
571 1.1 chuck ZBIS(scc, 5, SCC_DTR);
572 1.1 chuck if ((bits & TIOCM_RTS) != 0)
573 1.1 chuck ZBIS(scc, 5, SCC_RTS);
574 1.1 chuck }
575 1.1 chuck
576 1.1 chuck zscc_mclr(register struct sccregs * scc, int bits)
577 1.1 chuck {
578 1.1 chuck if ((bits & TIOCM_LE) != 0)
579 1.1 chuck ZBIC(scc, 3, SCC_RCVEN);
580 1.1 chuck if ((bits & TIOCM_DTR) != 0)
581 1.1 chuck ZBIC(scc, 5, TIOCM_DTR);
582 1.1 chuck if ((bits & TIOCM_RTS) != 0)
583 1.1 chuck ZBIC(scc, 5, SCC_RTS);
584 1.1 chuck }
585 1.1 chuck
586 1.1 chuck zs_drain(register struct zs * zp)
587 1.1 chuck {
588 1.1 chuck register int s;
589 1.1 chuck
590 1.1 chuck zp->tty->t_state |= TS_DRAIN;
591 1.1 chuck /* wait for Tx buffer empty and All sent bits to be set */
592 1.1 chuck s = splzs();
593 1.1 chuck while ((ZREAD0(&zp->scc) & SCC_TXRDY) == 0
594 1.1 chuck || (ZREAD(&zp->scc, 1) & 1) == 0) {
595 1.1 chuck splx(s);
596 1.1 chuck DELAY(100);
597 1.1 chuck s = splzs();
598 1.1 chuck }
599 1.1 chuck splx(s);
600 1.1 chuck }
601 1.1 chuck
602 1.1 chuck zs_unblock(register struct tty * tp)
603 1.1 chuck {
604 1.1 chuck tp->t_state &= ~TS_DRAIN;
605 1.1 chuck if (tp->t_outq.c_cc != 0)
606 1.1 chuck zsstart(tp);
607 1.1 chuck }
608 1.1 chuck
609 1.1 chuck /*
610 1.1 chuck * Hardware interrupt from an SCC.
611 1.1 chuck */
612 1.1 chuck int
613 1.1 chuck zsirq(int unit)
614 1.1 chuck {
615 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[unit];
616 1.1 chuck register struct zs *zp = &dv->zs[0];
617 1.1 chuck register int ipend, x;
618 1.1 chuck register volatile struct scc *scc;
619 1.1 chuck
620 1.1 chuck x = splzs();
621 1.1 chuck scc = zp->scc.s_adr;
622 1.1 chuck scc->cr = 3; /* read int pending from A side */
623 1.1 chuck DELAY(5);
624 1.1 chuck ipend = scc->cr;
625 1.1 chuck if ((ipend & 0x20) != 0)
626 1.1 chuck zs_rxint(zp);
627 1.1 chuck if ((ipend & 0x10) != 0)
628 1.1 chuck zs_txint(zp);
629 1.1 chuck if ((ipend & 0x8) != 0)
630 1.1 chuck zs_extint(zp);
631 1.1 chuck ++zp; /* now look for B side ints */
632 1.1 chuck if ((ipend & 0x4) != 0)
633 1.1 chuck zs_rxint(zp);
634 1.1 chuck if ((ipend & 0x2) != 0)
635 1.1 chuck zs_txint(zp);
636 1.1 chuck if ((ipend & 0x1) != 0)
637 1.1 chuck zs_extint(zp);
638 1.1 chuck splx(x);
639 1.1 chuck return ipend != 0;
640 1.1 chuck }
641 1.1 chuck
642 1.1 chuck zs_txint(register struct zs * zp)
643 1.1 chuck {
644 1.1 chuck struct tty *tp = zp->tty;
645 1.1 chuck struct sccregs *scc;
646 1.1 chuck int c;
647 1.1 chuck u_char *get;
648 1.1 chuck
649 1.1 chuck scc = &zp->scc;
650 1.1 chuck ZWRITE0(scc, 0x28); /* reset Tx interrupt */
651 1.1 chuck if ((zp->hflags & ZH_OBLOCK) == 0) {
652 1.1 chuck get = zp->send_ptr;
653 1.1 chuck while ((ZREAD0(scc) & SCC_TXRDY) != 0 && zp->send_count > 0) {
654 1.1 chuck c = *get++;
655 1.1 chuck ZWRITED(scc, c);
656 1.1 chuck --zp->send_count;
657 1.1 chuck ++zp->sent_count;
658 1.1 chuck }
659 1.1 chuck zp->send_ptr = get;
660 1.1 chuck if (zp->send_count == 0 && (zp->hflags & ZH_TXING) != 0) {
661 1.1 chuck zp->hflags &= ~ZH_TXING;
662 1.1 chuck zp->hflags |= ZH_SIRQ;
663 1.1 chuck setsoftint(sir_zs);
664 1.1 chuck }
665 1.1 chuck }
666 1.1 chuck }
667 1.1 chuck
668 1.1 chuck zs_rxint(register struct zs * zp)
669 1.1 chuck {
670 1.1 chuck register int stat, c, n, extra;
671 1.1 chuck u_char *put;
672 1.1 chuck
673 1.1 chuck put = zp->rcv_put;
674 1.1 chuck n = zp->rcv_count;
675 1.1 chuck for (;;) {
676 1.1 chuck if ((ZREAD0(&zp->scc) & SCC_RXFULL) == 0) /* check Rx full */
677 1.1 chuck break;
678 1.1 chuck stat = ZREAD(&zp->scc, 1) & 0x70;
679 1.1 chuck c = ZREADD(&zp->scc) & zp->imask;
680 1.1 chuck /* stat encodes parity, overrun, framing errors */
681 1.1 chuck if (stat != 0)
682 1.1 chuck ZWRITE0(&zp->scc, 0x30); /* reset error */
683 1.1 chuck if ((zp->hflags & ZH_RXOVF) != 0) {
684 1.1 chuck zp->hflags &= ~ZH_RXOVF;
685 1.1 chuck stat |= 0x20;
686 1.1 chuck }
687 1.1 chuck extra = (stat != 0 || c == ERROR_DET) ? 2 : 0;
688 1.1 chuck if (n + extra + 1 < zp->rcv_len) {
689 1.1 chuck if (extra != 0) {
690 1.1 chuck *put++ = ERROR_DET;
691 1.1 chuck if (put >= zp->rcv_end)
692 1.1 chuck put = zp->rcv_buf;
693 1.1 chuck *put++ = stat;
694 1.1 chuck if (put >= zp->rcv_end)
695 1.1 chuck put = zp->rcv_buf;
696 1.1 chuck n += 2;
697 1.1 chuck }
698 1.1 chuck *put++ = c;
699 1.1 chuck if (put >= zp->rcv_end)
700 1.1 chuck put = zp->rcv_buf;
701 1.1 chuck ++n;
702 1.1 chuck } else
703 1.1 chuck zp->hflags |= ZH_RXOVF;
704 1.1 chuck }
705 1.1 chuck if (n > zp->rcv_count) {
706 1.1 chuck zp->rcv_put = put;
707 1.1 chuck zp->rcv_count = n;
708 1.1 chuck zp->hflags |= ZH_SIRQ;
709 1.1 chuck setsoftint(sir_zs);
710 1.1 chuck }
711 1.1 chuck }
712 1.1 chuck
713 1.1 chuck /* Ext/status interrupt */
714 1.1 chuck zs_extint(register struct zs * zp)
715 1.1 chuck {
716 1.1 chuck int rr0;
717 1.1 chuck struct tty *tp = zp->tty;
718 1.1 chuck
719 1.1 chuck rr0 = ZREAD0(&zp->scc);
720 1.1 chuck ZWRITE0(&zp->scc, 0x10);/* reset ext/status int */
721 1.1 chuck if ((tp->t_cflag & CCTS_OFLOW) != 0) {
722 1.1 chuck if ((rr0 & 0x20) == 0)
723 1.1 chuck zp->hflags |= ZH_OBLOCK;
724 1.1 chuck else {
725 1.1 chuck zp->hflags &= ~ZH_OBLOCK;
726 1.1 chuck if ((rr0 & SCC_TXRDY) != 0)
727 1.1 chuck zs_txint(zp);
728 1.1 chuck }
729 1.1 chuck }
730 1.1 chuck zp->modem_change |= rr0 ^ zp->modem_state;
731 1.1 chuck zp->modem_state = rr0;
732 1.1 chuck zp->hflags |= ZH_SIRQ;
733 1.1 chuck setsoftint(sir_zs);
734 1.1 chuck }
735 1.1 chuck
736 1.1 chuck void
737 1.1 chuck zs_softint()
738 1.1 chuck {
739 1.1 chuck int s, n, n0, c, stat, rr0;
740 1.1 chuck struct zs *zp;
741 1.1 chuck struct tty *tp;
742 1.1 chuck u_char *get;
743 1.1 chuck int unit, side;
744 1.1 chuck
745 1.1 chuck s = splzs();
746 1.2 thorpej for (unit = 0; unit < zs_cd.cd_ndevs; ++unit) {
747 1.2 thorpej if (zs_cd.cd_devs[unit] == NULL)
748 1.1 chuck continue;
749 1.2 thorpej zp = &((struct zssoftc *) zs_cd.cd_devs[unit])->zs[0];
750 1.1 chuck for (side = 0; side < 2; ++side, ++zp) {
751 1.1 chuck if ((zp->hflags & ZH_SIRQ) == 0)
752 1.1 chuck continue;
753 1.1 chuck zp->hflags &= ~ZH_SIRQ;
754 1.1 chuck tp = zp->tty;
755 1.1 chuck
756 1.1 chuck /* check for tx done */
757 1.1 chuck spltty();
758 1.1 chuck if (tp != NULL && zp->send_count == 0
759 1.1 chuck && (tp->t_state & TS_BUSY) != 0) {
760 1.1 chuck tp->t_state &= ~(TS_BUSY | TS_FLUSH);
761 1.1 chuck ndflush(&tp->t_outq, zp->sent_count);
762 1.1 chuck if (tp->t_outq.c_cc <= tp->t_lowat) {
763 1.1 chuck if (tp->t_state & TS_ASLEEP) {
764 1.1 chuck tp->t_state &= ~TS_ASLEEP;
765 1.1 chuck wakeup((caddr_t) & tp->t_outq);
766 1.1 chuck }
767 1.1 chuck selwakeup(&tp->t_wsel);
768 1.1 chuck }
769 1.1 chuck if (tp->t_line != 0)
770 1.1 chuck (*linesw[tp->t_line].l_start) (tp);
771 1.1 chuck else
772 1.1 chuck zsstart(tp);
773 1.1 chuck }
774 1.1 chuck splzs();
775 1.1 chuck
776 1.1 chuck /* check for received characters */
777 1.1 chuck get = zp->rcv_get;
778 1.1 chuck while (zp->rcv_count > 0) {
779 1.1 chuck c = *get++;
780 1.1 chuck if (get >= zp->rcv_end)
781 1.1 chuck get = zp->rcv_buf;
782 1.1 chuck if (c == ERROR_DET) {
783 1.1 chuck stat = *get++;
784 1.1 chuck if (get >= zp->rcv_end)
785 1.1 chuck get = zp->rcv_buf;
786 1.1 chuck c = *get++;
787 1.1 chuck if (get >= zp->rcv_end)
788 1.1 chuck get = zp->rcv_buf;
789 1.1 chuck zp->rcv_count -= 3;
790 1.1 chuck } else {
791 1.1 chuck stat = 0;
792 1.1 chuck --zp->rcv_count;
793 1.1 chuck }
794 1.1 chuck spltty();
795 1.1 chuck if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
796 1.1 chuck continue;
797 1.1 chuck if (zp->nzs_open == 0) {
798 1.1 chuck #ifdef notdef
799 1.1 chuck if (stat == 0)
800 1.1 chuck kbd_newchar(zp->gsp_unit, c);
801 1.1 chuck #endif
802 1.1 chuck } else {
803 1.1 chuck if ((stat & 0x10) != 0)
804 1.1 chuck c |= TTY_PE;
805 1.1 chuck if ((stat & 0x20) != 0) {
806 1.1 chuck log(LOG_WARNING, "zs: fifo overflow\n");
807 1.1 chuck c |= TTY_FE; /* need some error for
808 1.1 chuck * slip stuff */
809 1.1 chuck }
810 1.1 chuck if ((stat & 0x40) != 0)
811 1.1 chuck c |= TTY_FE;
812 1.1 chuck (*linesw[tp->t_line].l_rint) (c, tp);
813 1.1 chuck }
814 1.1 chuck splzs();
815 1.1 chuck }
816 1.1 chuck zp->rcv_get = get;
817 1.1 chuck
818 1.1 chuck /* check for modem lines changing */
819 1.1 chuck while (zp->modem_change != 0 || zp->modem_state != zp->rr0) {
820 1.1 chuck rr0 = zp->rr0 ^ zp->modem_change;
821 1.1 chuck zp->modem_change = rr0 ^ zp->modem_state;
822 1.1 chuck
823 1.1 chuck /* Check if DCD (carrier detect) has changed */
824 1.1 chuck if (tp != NULL && (rr0 & 8) != (zp->rr0 & 8)) {
825 1.1 chuck spltty();
826 1.1 chuck ttymodem(tp, rr0 & 8);
827 1.1 chuck /* XXX possibly should disable line if
828 1.1 chuck * return value is 0 */
829 1.1 chuck splzs();
830 1.1 chuck }
831 1.1 chuck zp->rr0 = rr0;
832 1.1 chuck }
833 1.1 chuck }
834 1.1 chuck }
835 1.1 chuck splx(s);
836 1.1 chuck }
837 1.1 chuck
838 1.1 chuck /*
839 1.1 chuck * Routines to divert an SCC channel to the input side of /dev/gsp
840 1.1 chuck * for the keyboard.
841 1.1 chuck */
842 1.1 chuck int
843 1.1 chuck zs_kbdopen(int unit, int gsp_unit, struct termios * tiop, struct proc * p)
844 1.1 chuck {
845 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(unit)];
846 1.1 chuck struct zs *zp = &dv->zs[zsside(unit)];
847 1.1 chuck int error;
848 1.1 chuck
849 1.1 chuck error = zsopen(unit, 0, 0, p);
850 1.1 chuck if (error != 0)
851 1.1 chuck return error;
852 1.1 chuck ++zp->nkbd_open;
853 1.1 chuck --zp->nzs_open;
854 1.1 chuck zsparam(zp->tty, tiop);
855 1.1 chuck zp->gsp_unit = gsp_unit;
856 1.1 chuck return 0;
857 1.1 chuck }
858 1.1 chuck
859 1.1 chuck void
860 1.1 chuck zs_kbdclose(int unit)
861 1.1 chuck {
862 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(unit)];
863 1.1 chuck struct zs *zp = &dv->zs[zsside(unit)];
864 1.1 chuck
865 1.1 chuck zp->nkbd_open = 0;
866 1.1 chuck if (zp->nzs_open == 0)
867 1.1 chuck zsclose(unit, 0, 0, 0);
868 1.1 chuck }
869 1.1 chuck
870 1.1 chuck void
871 1.1 chuck zs_kbdput(int unit, int c)
872 1.1 chuck {
873 1.2 thorpej struct zssoftc *dv = (struct zssoftc *) zs_cd.cd_devs[zsunit(unit)];
874 1.1 chuck struct zs *zp = &dv->zs[zsside(unit)];
875 1.1 chuck struct tty *tp = zp->tty;
876 1.1 chuck
877 1.1 chuck putc(c, &tp->t_outq);
878 1.1 chuck zsstart(tp);
879 1.1 chuck }
880 1.1 chuck
881 1.1 chuck /*
882 1.1 chuck * Routines for using side A of the first SCC as a console.
883 1.1 chuck */
884 1.1 chuck
885 1.1 chuck /* probe for the SCC; should check hardware */
886 1.1 chuck zscnprobe(cp)
887 1.1 chuck struct consdev *cp;
888 1.1 chuck {
889 1.1 chuck int maj;
890 1.1 chuck char *prom_cons;
891 1.1 chuck extern char *prom_getvar();
892 1.1 chuck
893 1.1 chuck /* locate the major number */
894 1.1 chuck for (maj = 0; maj < nchrdev; maj++)
895 1.1 chuck if (cdevsw[maj].d_open == zsopen)
896 1.1 chuck break;
897 1.1 chuck
898 1.1 chuck /* initialize required fields */
899 1.1 chuck cp->cn_dev = makedev(maj, 0);
900 1.1 chuck cp->cn_pri = CN_NORMAL;
901 1.1 chuck
902 1.1 chuck return 1;
903 1.1 chuck }
904 1.1 chuck
905 1.1 chuck /* initialize the keyboard for use as the console */
906 1.1 chuck struct termios zscn_termios = {
907 1.1 chuck TTYDEF_IFLAG,
908 1.1 chuck TTYDEF_OFLAG,
909 1.1 chuck TTYDEF_CFLAG,
910 1.1 chuck TTYDEF_LFLAG,
911 1.1 chuck {0},
912 1.1 chuck TTYDEF_SPEED,
913 1.1 chuck TTYDEF_SPEED
914 1.1 chuck };
915 1.1 chuck
916 1.1 chuck struct sccregs zs_cons_sccregs;
917 1.1 chuck int zs_cons_imask;
918 1.1 chuck
919 1.1 chuck unsigned zs_cons_addrs[] = {ZS0_PHYS, ZS1_PHYS};
920 1.1 chuck
921 1.1 chuck
922 1.1 chuck zscninit()
923 1.1 chuck {
924 1.1 chuck zs_cnsetup(0, &zscn_termios);
925 1.1 chuck }
926 1.1 chuck
927 1.1 chuck /* Polling routine for console input from a serial port. */
928 1.1 chuck int
929 1.1 chuck zscngetc(dev_t dev)
930 1.1 chuck {
931 1.1 chuck register struct sccregs *scc = zs_cons_scc;
932 1.1 chuck int c, s, stat;
933 1.1 chuck
934 1.1 chuck s = splzs();
935 1.1 chuck for (;;) {
936 1.1 chuck while ((ZREAD0(scc) & SCC_RXFULL) == 0) /* wait for Rx full */
937 1.1 chuck ;
938 1.1 chuck stat = ZREAD(scc, 1) & 0x70;
939 1.1 chuck c = ZREADD(scc) & zs_cons_imask;
940 1.1 chuck /* stat encodes parity, overrun, framing errors */
941 1.1 chuck if (stat == 0)
942 1.1 chuck break;
943 1.1 chuck ZWRITE0(scc, 0x30); /* reset error */
944 1.1 chuck }
945 1.1 chuck splx(s);
946 1.1 chuck return c;
947 1.1 chuck }
948 1.1 chuck
949 1.1 chuck zscnputc(dev_t dev, int c)
950 1.1 chuck {
951 1.1 chuck register struct sccregs *scc = zs_cons_scc;
952 1.1 chuck int s;
953 1.1 chuck
954 1.1 chuck s = splzs();
955 1.1 chuck while ((ZREAD0(scc) & SCC_TXRDY) == 0);
956 1.1 chuck ZWRITED(scc, c);
957 1.1 chuck splx(s);
958 1.1 chuck }
959 1.1 chuck
960 1.1 chuck zs_cnsetup(int unit, struct termios * tiop)
961 1.1 chuck {
962 1.1 chuck register volatile struct scc *scc_adr;
963 1.1 chuck register struct sccregs *scc;
964 1.1 chuck
965 1.1 chuck zs_cons_unit = unit;
966 1.1 chuck zs_is_console = 1;
967 1.1 chuck zs_cons_scc = scc = &zs_cons_sccregs;
968 1.1 chuck
969 1.1 chuck scc_adr = (volatile struct scc *) IIOV(zs_cons_addrs[zsunit(unit)]);
970 1.1 chuck
971 1.1 chuck scc_adr[1].cr = 0;
972 1.1 chuck scc_adr[1].cr = 9;
973 1.1 chuck scc_adr[1].cr = 0xC0; /* hardware reset of SCC, both sides */
974 1.1 chuck if (!zsside(unit))
975 1.1 chuck ++scc_adr;
976 1.1 chuck
977 1.1 chuck scc->s_adr = scc_adr;
978 1.1 chuck ZWRITE(scc, 2, 0);
979 1.1 chuck ZWRITE(scc, 10, 0);
980 1.1 chuck ZWRITE(scc, 11, 0x50); /* rx & tx clock = brgen */
981 1.1 chuck ZWRITE(scc, 14, 3); /* brgen enabled, from pclk */
982 1.1 chuck zs_cons_imask = zscc_params(scc, tiop);
983 1.1 chuck ZBIS(scc, 5, 0x82); /* set DTR and RTS */
984 1.1 chuck
985 1.1 chuck zs_cons_termios = *tiop;/* save for later */
986 1.1 chuck }
987 1.1 chuck
988 1.1 chuck /*
989 1.1 chuck * Routines for using the keyboard SCC as the input side of
990 1.1 chuck * the 'gsp' console device.
991 1.1 chuck */
992 1.1 chuck
993 1.1 chuck /* probe for the keyboard; should check hardware */
994 1.1 chuck zs_kbdcnprobe(cp, unit)
995 1.1 chuck struct consdev *cp;
996 1.1 chuck int unit;
997 1.1 chuck {
998 1.1 chuck return (unsigned) unit < NZSLINE;
999 1.1 chuck }
1000 1.1 chuck #endif /* NZS */
1001