]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/zs/zs.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / sys / dev / zs / zs.c
1 /*-
2  * Copyright (c) 1994 Gordon W. Ross
3  * Copyright (c) 1992, 1993
4  *      The Regents of the University of California.  All rights reserved.
5  *
6  * This software was developed by the Computer Systems Engineering group
7  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
8  * contributed to Berkeley.
9  *
10  * All advertising materials mentioning features or use of this software
11  * must display the following acknowledgement:
12  *      This product includes software developed by the University of
13  *      California, Lawrence Berkeley Laboratory.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *      @(#)zs.c        8.1 (Berkeley) 7/19/93
40  */
41
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD$");
44 /*-
45  * Copyright (c) 2003 Jake Burkholder.
46  * All rights reserved.
47  *
48  * Redistribution and use in source and binary forms, with or without
49  * modification, are permitted provided that the following conditions
50  * are met:
51  * 1. Redistributions of source code must retain the above copyright
52  *    notice, this list of conditions and the following disclaimer.
53  * 2. Redistributions in binary form must reproduce the above copyright
54  *    notice, this list of conditions and the following disclaimer in the
55  *    documentation and/or other materials provided with the distribution.
56  *
57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
58  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
61  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67  * SUCH DAMAGE.
68  *
69  */
70
71 /*
72  * Zilog Z8530 Dual UART driver.
73  */
74
75 #include "opt_comconsole.h"
76
77 #include <sys/param.h>
78 #include <sys/systm.h>
79 #include <sys/bus.h>
80 #include <sys/conf.h>
81 #include <sys/cons.h>
82 #include <sys/fcntl.h>
83 #include <sys/interrupt.h>
84 #include <sys/kdb.h>
85 #include <sys/kernel.h>
86 #include <sys/ktr.h>
87 #include <sys/mutex.h>
88 #include <sys/proc.h>
89 #include <machine/bus.h>
90 #include <machine/resource.h>
91 #include <sys/rman.h>
92 #include <sys/serial.h>
93 #include <sys/syslog.h>
94 #include <sys/tty.h>
95
96 #include <dev/zs/z8530reg.h>
97 #include <dev/zs/z8530var.h>
98
99 #define ZS_READ(sc, r) \
100         bus_space_read_1((sc)->sc_bt, (r), 0)
101 #define ZS_WRITE(sc, r, v) \
102         bus_space_write_1((sc)->sc_bt, (r), 0, (v))
103
104 #define ZS_READ_REG(sc, r) ({ \
105         ZS_WRITE((sc), (sc)->sc_csr, (r)); \
106         ZS_READ((sc), (sc)->sc_csr); \
107 })
108
109 #define ZS_WRITE_REG(sc, r, v) ({ \
110         ZS_WRITE((sc), (sc)->sc_csr, (r)); \
111         ZS_WRITE((sc), (sc)->sc_csr, (v)); \
112 })
113
114 #define ZSTTY_LOCK(sz)          mtx_lock_spin(&(sc)->sc_mtx)
115 #define ZSTTY_UNLOCK(sz)        mtx_unlock_spin(&(sc)->sc_mtx)
116
117 static void zs_softintr(void *v);
118 static void zs_shutdown(void *v);
119
120 static int zstty_intr(struct zstty_softc *sc, uint8_t rr3);
121 static void zstty_softintr(struct zstty_softc *sc) __unused;
122 static int zstty_param(struct zstty_softc *sc, struct tty *tp,
123     struct termios *t);
124 static void zstty_flush(struct zstty_softc *sc) __unused;
125 static int zstty_speed(struct zstty_softc *sc, int rate);
126 static void zstty_load_regs(struct zstty_softc *sc);
127
128 static cn_probe_t zs_cnprobe;
129 static cn_init_t zs_cninit;
130 static cn_term_t zs_cnterm;
131 static cn_getc_t zs_cngetc;
132 static cn_checkc_t zs_cncheckc;
133 static cn_putc_t zs_cnputc;
134 static cn_dbctl_t zs_cndbctl;
135
136 static int zstty_cngetc(struct zstty_softc *sc);
137 static int zstty_cncheckc(struct zstty_softc *sc);
138 static void zstty_cnputc(struct zstty_softc *sc, int c);
139
140 static d_open_t zsttyopen;
141 static d_close_t zsttyclose;
142
143 static void zsttystart(struct tty *tp);
144 static void zsttystop(struct tty *tp, int rw);
145 static int zsttyparam(struct tty *tp, struct termios *t);
146 static void zsttybreak(struct tty *tp, int brk);
147 static int zsttymodem(struct tty *tp, int biton, int bitoff);
148
149 static struct cdevsw zstty_cdevsw = {
150         .d_version =    D_VERSION,
151         .d_open =       zsttyopen,
152         .d_close =      zsttyclose,
153         .d_name =       "zstty",
154         .d_flags =      D_TTY | D_NEEDGIANT,
155 };
156
157 static struct zstty_softc *zstty_cons;
158
159 CONS_DRIVER(zs, zs_cnprobe, zs_cninit, zs_cnterm, zs_cngetc, zs_cncheckc,
160     zs_cnputc, zs_cndbctl);
161
162 int
163 zs_probe(device_t dev)
164 {
165
166         device_set_desc(dev, "Zilog Z8530");
167         return (0);
168 }
169
170 int
171 zs_attach(device_t dev)
172 {
173         struct device *child[ZS_NCHAN];
174         struct zs_softc *sc;
175         int i;
176
177         sc = device_get_softc(dev);
178         sc->sc_dev = dev;
179
180         for (i = 0; i < ZS_NCHAN; i++)
181                 child[i] = device_add_child(dev, "zstty", -1);
182         bus_generic_attach(dev);
183         for (i = 0; i < ZS_NCHAN; i++)
184                 sc->sc_child[i] = device_get_softc(child[i]);
185
186         swi_add(&tty_intr_event, "zs", zs_softintr, sc, SWI_TTY,
187             INTR_TYPE_TTY, &sc->sc_softih);
188
189         ZS_WRITE_REG(sc->sc_child[0], 2, sc->sc_child[0]->sc_creg[2]);
190         ZS_WRITE_REG(sc->sc_child[0], 9, sc->sc_child[0]->sc_creg[9]);
191
192         if (zstty_cons != NULL) {
193                 DELAY(50000);
194                 cninit();
195         }
196
197         EVENTHANDLER_REGISTER(shutdown_final, zs_shutdown, sc,
198             SHUTDOWN_PRI_DEFAULT);
199
200         return (0);
201 }
202
203 void
204 zs_intr(void *v)
205 {
206         struct zs_softc *sc = v;
207         int needsoft;
208         uint8_t rr3;
209
210         /*
211          * There is only one status register, which is on channel a.  In order
212          * to avoid needing to know which channel we're on in the tty interrupt
213          * handler we shift the channel a status bits into the channel b
214          * bit positions and always test the channel b bits.
215          */
216         needsoft = 0;
217         rr3 = ZS_READ_REG(sc->sc_child[0], 3);
218         if ((rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) != 0)
219                 needsoft |= zstty_intr(sc->sc_child[0], rr3 >> 3);
220         if ((rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) != 0)
221                 needsoft |= zstty_intr(sc->sc_child[1], rr3);
222         if (needsoft)
223                 swi_sched(sc->sc_softih, 0);
224 }
225
226 static void
227 zs_softintr(void *v)
228 {
229         struct zs_softc *sc = v;
230
231         zstty_softintr(sc->sc_child[0]);
232         zstty_softintr(sc->sc_child[1]);
233 }
234
235 static void
236 zs_shutdown(void *v)
237 {
238 }
239
240 int
241 zstty_probe(device_t dev)
242 {
243         return (0);
244 }
245
246 int
247 zstty_attach(device_t dev)
248 {
249         struct zstty_softc *sc;
250         struct tty *tp;
251         char mode[32];
252         int reset;
253         int baud;
254         int clen;
255         char parity;
256         int stop;
257         char c;
258
259         sc = device_get_softc(dev);
260         mtx_init(&sc->sc_mtx, "zstty", NULL, MTX_SPIN);
261         sc->sc_dev = dev;
262         sc->sc_iput = sc->sc_iget = sc->sc_ibuf;
263         sc->sc_oget = sc->sc_obuf;
264
265         tp = ttyalloc();
266         tp->t_sc = sc;
267         sc->sc_si = make_dev(&zstty_cdevsw, device_get_unit(dev),
268             UID_ROOT, GID_WHEEL, 0600, "%s", device_get_desc(dev));
269         sc->sc_si->si_drv1 = sc;
270         sc->sc_si->si_tty = tp;
271         tp->t_dev = sc->sc_si;
272         sc->sc_tty = tp;
273
274         tp->t_oproc = zsttystart;
275         tp->t_param = zsttyparam;
276         tp->t_modem = zsttymodem;
277         tp->t_break = zsttybreak;
278         tp->t_stop = zsttystop;
279         ttyinitmode(tp, 0, 0);
280         tp->t_cflag = CREAD | CLOCAL | CS8;
281
282         if (zstty_console(dev, mode, sizeof(mode))) {
283                 ttychars(tp);
284                 /* format: 9600,8,n,1,- */
285                 if (sscanf(mode, "%d,%d,%c,%d,%c", &baud, &clen, &parity,
286                     &stop, &c) == 5) {
287                         tp->t_ospeed = baud;
288                         tp->t_ispeed = baud;
289                         tp->t_cflag = CREAD | CLOCAL;
290                         switch (clen) {
291                         case 5:
292                                 tp->t_cflag |= CS5;
293                                 break;
294                         case 6:
295                                 tp->t_cflag |= CS6;
296                                 break;
297                         case 7:
298                                 tp->t_cflag |= CS7;
299                                 break;
300                         case 8:
301                         default:
302                                 tp->t_cflag |= CS8;
303                                 break;
304                         }
305
306                         if (parity == 'e')
307                                 tp->t_cflag |= PARENB;
308                         else if (parity == 'o')
309                                 tp->t_cflag |= PARENB | PARODD;
310
311                         if (stop == 2)
312                                 tp->t_cflag |= CSTOPB;
313                 }
314                 device_printf(dev, "console %s\n", mode);
315                 sc->sc_console = 1;
316                 zstty_cons = sc;
317         } else {
318                 if ((device_get_unit(dev) & 1) == 0)
319                         reset = ZSWR9_A_RESET;
320                 else
321                         reset = ZSWR9_B_RESET;
322                 ZS_WRITE_REG(sc, 9, reset);
323         }
324
325         return (0);
326 }
327
328 /*
329  * Note that the rr3 value is shifted so the channel a status bits are in the
330  * channel b bit positions, which makes the bit positions uniform for both
331  * channels.
332  */
333 static int
334 zstty_intr(struct zstty_softc *sc, uint8_t rr3)
335 {
336         int needsoft;
337         uint8_t rr0;
338         uint8_t rr1;
339         uint8_t c;
340         int brk;
341
342         ZSTTY_LOCK(sc);
343
344         ZS_WRITE(sc, sc->sc_csr, ZSWR0_CLR_INTR);
345
346         brk = 0;
347         needsoft = 0;
348         if ((rr3 & ZSRR3_IP_B_RX) != 0) {
349                 needsoft = 1;
350                 do {
351                         /*
352                          * First read the status, because reading the received
353                          * char destroys the status of this char.
354                          */
355                         rr1 = ZS_READ_REG(sc, 1);
356                         c = ZS_READ(sc, sc->sc_data);
357
358                         if ((rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) != 0)
359                                 ZS_WRITE(sc, sc->sc_csr, ZSWR0_RESET_ERRORS);
360 #if defined(KDB) && defined(ALT_BREAK_TO_DEBUGGER)
361                         if (sc->sc_console != 0)
362                                 brk = kdb_alt_break(c,
363                                     &sc->sc_alt_break_state);
364 #endif
365                         *sc->sc_iput++ = c;
366                         *sc->sc_iput++ = rr1;
367                         if (sc->sc_iput == sc->sc_ibuf + sizeof(sc->sc_ibuf))
368                                 sc->sc_iput = sc->sc_ibuf;
369                 } while ((ZS_READ(sc, sc->sc_csr) & ZSRR0_RX_READY) != 0);
370         }
371
372         if ((rr3 & ZSRR3_IP_B_STAT) != 0) {
373                 rr0 = ZS_READ(sc, sc->sc_csr);
374                 ZS_WRITE(sc, sc->sc_csr, ZSWR0_RESET_STATUS);
375 #if defined(KDB) && defined(BREAK_TO_DEBUGGER)
376                 if (sc->sc_console != 0 && (rr0 & ZSRR0_BREAK) != 0)
377                         brk = 1;
378 #endif
379                 /* XXX do something about flow control */
380         }
381
382         if ((rr3 & ZSRR3_IP_B_TX) != 0) {
383                 /*
384                  * If we've delayed a paramter change, do it now.
385                  */
386                 if (sc->sc_preg_held) {
387                         sc->sc_preg_held = 0;
388                         zstty_load_regs(sc);
389                 }
390                 if (sc->sc_ocnt > 0) {
391                         ZS_WRITE(sc, sc->sc_data, *sc->sc_oget++);
392                         sc->sc_ocnt--;
393                 } else {
394                         /*
395                          * Disable transmit completion interrupts if
396                          * necessary.
397                          */
398                         if ((sc->sc_preg[1] & ZSWR1_TIE) != 0) {
399                                 sc->sc_preg[1] &= ~ZSWR1_TIE;
400                                 sc->sc_creg[1] = sc->sc_preg[1];
401                                 ZS_WRITE_REG(sc, 1, sc->sc_creg[1]);
402                         }
403                         sc->sc_tx_done = 1;
404                         sc->sc_tx_busy = 0;
405                         needsoft = 1;
406                 }
407         }
408
409         ZSTTY_UNLOCK(sc);
410
411         if (brk != 0)
412                 breakpoint();
413
414         return (needsoft);
415 }
416
417 static void
418 zstty_softintr(struct zstty_softc *sc)
419 {
420         struct tty *tp = sc->sc_tty;
421         int data;
422         int stat;
423
424         if ((tp->t_state & TS_ISOPEN) == 0)
425                 return;
426
427         while (sc->sc_iget != sc->sc_iput) {
428                 data = *sc->sc_iget++;
429                 stat = *sc->sc_iget++;
430                 if ((stat & ZSRR1_PE) != 0)
431                         data |= TTY_PE;
432                 if ((stat & ZSRR1_FE) != 0)
433                         data |= TTY_FE;
434                 if (sc->sc_iget == sc->sc_ibuf + sizeof(sc->sc_ibuf))
435                         sc->sc_iget = sc->sc_ibuf;
436
437                 ttyld_rint(tp, data);
438         }
439
440         if (sc->sc_tx_done != 0) {
441                 sc->sc_tx_done = 0;
442                 tp->t_state &= ~TS_BUSY;
443                 ttyld_start(tp);
444         }
445 }
446
447 static int
448 zsttyopen(struct cdev *dev, int flags, int mode, struct thread *td)
449 {
450         struct zstty_softc *sc;
451         struct tty *tp;
452         int error;
453
454         sc = dev->si_drv1;
455         tp = dev->si_tty;
456
457         if ((tp->t_state & TS_ISOPEN) != 0 &&
458             (tp->t_state & TS_XCLUDE) != 0 &&
459             suser(td) != 0)
460                 return (EBUSY);
461
462         if ((tp->t_state & TS_ISOPEN) == 0) {
463                 struct termios t;
464
465                 /*
466                  * Enable receive and status interrupts in zstty_param.
467                  */
468                 sc->sc_preg[1] |= ZSWR1_RIE | ZSWR1_SIE;
469                 sc->sc_iput = sc->sc_iget = sc->sc_ibuf;
470
471                 ttyconsolemode(tp, 0);
472                 /* Make sure zstty_param() will do something. */
473                 tp->t_ospeed = 0;
474                 (void)zstty_param(sc, tp, &t);
475                 ttychars(tp);
476                 ttsetwater(tp);
477
478                 /* XXX turn on DTR */
479
480                 /* XXX handle initial DCD */
481         }
482
483         error = tty_open(dev, tp);
484         if (error != 0)
485                 return (error);
486
487         error = ttyld_open(tp, dev);
488         if (error != 0)
489                 return (error);
490
491         return (0);
492 }
493
494 static int
495 zsttyclose(struct cdev *dev, int flags, int mode, struct thread *td)
496 {
497         struct tty *tp;
498
499         tp = dev->si_tty;
500
501         if ((tp->t_state & TS_ISOPEN) == 0)
502                 return (0);
503
504         ttyld_close(tp, flags);
505         tty_close(tp);
506
507         return (0);
508 }
509
510 static void
511 zsttystart(struct tty *tp)
512 {
513         struct zstty_softc *sc;
514         uint8_t c;
515
516         sc = tp->t_sc;
517
518         if ((tp->t_state & TS_TBLOCK) != 0)
519                 /* XXX clear RTS */;
520         else
521                 /* XXX set RTS */;
522
523         if ((tp->t_state & (TS_BUSY | TS_TIMEOUT | TS_TTSTOP)) != 0) {
524                 ttwwakeup(tp);
525                 return;
526         }
527
528         if (tp->t_outq.c_cc <= tp->t_olowat) {
529                 if ((tp->t_state & TS_SO_OLOWAT) != 0) {
530                         tp->t_state &= ~TS_SO_OLOWAT;
531                         wakeup(TSA_OLOWAT(tp));
532                 }
533                 selwakeuppri(&tp->t_wsel, TTOPRI);
534                 if (tp->t_outq.c_cc == 0) {
535                         if ((tp->t_state & (TS_BUSY | TS_SO_OCOMPLETE)) ==
536                             TS_SO_OCOMPLETE && tp->t_outq.c_cc == 0) {
537                                 tp->t_state &= ~TS_SO_OCOMPLETE;
538                                 wakeup(TSA_OCOMPLETE(tp));
539                         }
540                         return;
541                 }
542         }
543
544         sc->sc_ocnt = q_to_b(&tp->t_outq, sc->sc_obuf, sizeof(sc->sc_obuf));
545         if (sc->sc_ocnt == 0)
546                 return;
547         c = sc->sc_obuf[0];
548         sc->sc_oget = sc->sc_obuf + 1;
549         sc->sc_ocnt--;
550
551         tp->t_state |= TS_BUSY;
552         sc->sc_tx_busy = 1;
553
554         /*
555          * Enable transmit interrupts if necessary and send the first
556          * character to start up the transmitter.
557          */
558         if ((sc->sc_preg[1] & ZSWR1_TIE) == 0) {
559                 sc->sc_preg[1] |= ZSWR1_TIE;
560                 sc->sc_creg[1] = sc->sc_preg[1];
561                 ZS_WRITE_REG(sc, 1, sc->sc_creg[1]);
562         }
563         ZS_WRITE(sc, sc->sc_data, c);
564
565         ttwwakeup(tp);
566 }
567
568 static void
569 zsttystop(struct tty *tp, int flag)
570 {
571         struct zstty_softc *sc;
572
573         sc = tp->t_sc;
574
575         if ((flag & FREAD) != 0) {
576                 /* XXX stop reading, anything to do? */;
577         }
578
579         if ((flag & FWRITE) != 0) {
580                 if ((tp->t_state & TS_BUSY) != 0) {
581                         /* XXX do what? */
582                         if ((tp->t_state & TS_TTSTOP) == 0)
583                                 tp->t_state |= TS_FLUSH;
584                 }
585         }
586 }
587
588 static int
589 zsttyparam(struct tty *tp, struct termios *t)
590 {
591         struct zstty_softc *sc;
592
593         sc = tp->t_sc;
594         return (zstty_param(sc, tp, t));
595 }
596
597
598 static void
599 zsttybreak(struct tty *tp, int brk)
600 {
601         struct zstty_softc *sc;
602
603         sc = tp->t_sc;
604
605         if (brk)
606                 ZS_WRITE_REG(sc, 5, ZS_READ_REG(sc, 5) | ZSWR5_BREAK);
607         else
608                 ZS_WRITE_REG(sc, 5, ZS_READ_REG(sc, 5) & ~ZSWR5_BREAK);
609 }
610
611 static int
612 zsttymodem(struct tty *tp, int biton, int bitoff)
613 {
614         /* XXX implement! */
615         return (0);
616 }
617
618 static int
619 zstty_param(struct zstty_softc *sc, struct tty *tp, struct termios *t)
620 {
621         tcflag_t cflag;
622         uint8_t wr3;
623         uint8_t wr4;
624         uint8_t wr5;
625         int ospeed;
626
627         ospeed = zstty_speed(sc, t->c_ospeed);
628         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
629                 return (EINVAL);
630
631         /*
632          * If there were no changes, don't do anything.  This avoids dropping
633          * input and improves performance when all we did was frob things like
634          * VMIN and VTIME.
635          */
636         if (tp->t_ospeed == t->c_ospeed &&
637             tp->t_cflag == t->c_cflag)
638                 return (0);
639
640         if (t->c_ospeed != 0)
641                 zsttymodem(tp, SER_DTR, 0);
642         else
643                 zsttymodem(tp, 0, SER_DTR);
644
645         cflag = t->c_cflag;
646
647         if (sc->sc_console != 0) {
648                 cflag |= CLOCAL;
649                 cflag &= ~HUPCL;
650         }
651
652         wr3 = ZSWR3_RX_ENABLE;
653         wr5 = ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
654
655         switch (cflag & CSIZE) {
656         case CS5:
657                 wr3 |= ZSWR3_RX_5;
658                 wr5 |= ZSWR5_TX_5;
659                 break;
660         case CS6:
661                 wr3 |= ZSWR3_RX_6;
662                 wr5 |= ZSWR5_TX_6;
663                 break;
664         case CS7:
665                 wr3 |= ZSWR3_RX_7;
666                 wr5 |= ZSWR5_TX_7;
667                 break;
668         case CS8:
669         default:
670                 wr3 |= ZSWR3_RX_8;
671                 wr5 |= ZSWR5_TX_8;
672                 break;
673         }
674
675         wr4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
676         if ((cflag & PARODD) == 0)
677                 wr4 |= ZSWR4_EVENP;
678         if (cflag & PARENB)
679                 wr4 |= ZSWR4_PARENB;
680
681         tp->t_ispeed = 0;
682         tp->t_ospeed = t->c_ospeed;
683         tp->t_cflag = cflag;
684
685         ttsetwater(tp);
686
687         ZSTTY_LOCK(sc);
688
689         sc->sc_preg[3] = wr3;
690         sc->sc_preg[4] = wr4;
691         sc->sc_preg[5] = wr5;
692
693         zstty_set_speed(sc, ospeed);
694
695         if (cflag & CRTSCTS)
696                 sc->sc_preg[15] |= ZSWR15_CTS_IE;
697         else
698                 sc->sc_preg[15] &= ~ZSWR15_CTS_IE;
699
700         zstty_load_regs(sc);
701
702         ZSTTY_UNLOCK(sc);
703         
704         return (0);
705 }
706
707 static void
708 zstty_flush(struct zstty_softc *sc)
709 {
710         uint8_t rr0;
711         uint8_t rr1;
712         uint8_t c;
713
714         for (;;) {
715                 rr0 = ZS_READ(sc, sc->sc_csr);
716                 if ((rr0 & ZSRR0_RX_READY) == 0)
717                         break;
718
719                 rr1 = ZS_READ_REG(sc, 1);
720                 c = ZS_READ(sc, sc->sc_data);
721
722                 if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE))
723                         ZS_WRITE(sc, sc->sc_data, ZSWR0_RESET_ERRORS);
724         }
725 }
726
727 static void
728 zstty_load_regs(struct zstty_softc *sc)
729 {
730
731         /*
732          * If the transmitter may be active, just hold the change and do it
733          * in the tx interrupt handler.  Changing the registers while tx is
734          * active may hang the chip.
735          */
736         if (sc->sc_tx_busy != 0) {
737                 sc->sc_preg_held = 1;
738                 return;
739         }
740
741         /* If the regs are the same do nothing. */
742         if (bcmp(sc->sc_preg, sc->sc_creg, 16) == 0)
743                 return;
744
745         bcopy(sc->sc_preg, sc->sc_creg, 16);
746
747         /* XXX: reset error condition */
748         ZS_WRITE(sc, sc->sc_csr, ZSM_RESET_ERR);
749
750         /* disable interrupts */
751         ZS_WRITE_REG(sc, 1, sc->sc_creg[1] & ~ZSWR1_IMASK);
752
753         /* baud clock divisor, stop bits, parity */
754         ZS_WRITE_REG(sc, 4, sc->sc_creg[4]);
755
756         /* misc. TX/RX control bits */
757         ZS_WRITE_REG(sc, 10, sc->sc_creg[10]);
758
759         /* char size, enable (RX/TX) */
760         ZS_WRITE_REG(sc, 3, sc->sc_creg[3] & ~ZSWR3_RX_ENABLE);
761         ZS_WRITE_REG(sc, 5, sc->sc_creg[5] & ~ZSWR5_TX_ENABLE);
762
763         /* Shut down the BRG */
764         ZS_WRITE_REG(sc, 14, sc->sc_creg[14] & ~ZSWR14_BAUD_ENA);
765
766         /* clock mode control */
767         ZS_WRITE_REG(sc, 11, sc->sc_creg[11]);
768
769         /* baud rate (lo/hi) */
770         ZS_WRITE_REG(sc, 12, sc->sc_creg[12]);
771         ZS_WRITE_REG(sc, 13, sc->sc_creg[13]);
772
773         /* Misc. control bits */
774         ZS_WRITE_REG(sc, 14, sc->sc_creg[14]);
775
776         /* which lines cause status interrupts */
777         ZS_WRITE_REG(sc, 15, sc->sc_creg[15]);
778
779         /*
780          * Zilog docs recommend resetting external status twice at this
781          * point. Mainly as the status bits are latched, and the first
782          * interrupt clear might unlatch them to new values, generating
783          * a second interrupt request.
784          */
785         ZS_WRITE(sc, sc->sc_csr, ZSM_RESET_STINT);
786         ZS_WRITE(sc, sc->sc_csr, ZSM_RESET_STINT);
787
788         /* char size, enable (RX/TX)*/
789         ZS_WRITE_REG(sc, 3, sc->sc_creg[3]);
790         ZS_WRITE_REG(sc, 5, sc->sc_creg[5]);
791
792         /* interrupt enables: RX, TX, STATUS */
793         ZS_WRITE_REG(sc, 1, sc->sc_creg[1]);
794 }
795
796 static int
797 zstty_speed(struct zstty_softc *sc, int rate)
798 {
799         int tconst;
800
801         if (rate == 0)
802                 return (0);
803         tconst = BPS_TO_TCONST(sc->sc_brg_clk, rate);
804         if (tconst < 0 || TCONST_TO_BPS(sc->sc_brg_clk, tconst) != rate)
805                 return (-1);
806         return (tconst);
807 }
808
809 static void
810 zs_cnprobe(struct consdev *cn)
811 {
812         struct zstty_softc *sc = zstty_cons;
813
814         if (sc == NULL)
815                 cn->cn_pri = CN_DEAD;
816         else {
817                 cn->cn_pri = CN_REMOTE;
818                 strcpy(cn->cn_name, devtoname(sc->sc_si));
819                 cn->cn_tp = sc->sc_tty;
820         }
821 }
822
823 static void
824 zs_cninit(struct consdev *cn)
825 {
826 }
827
828 static void
829 zs_cnterm(struct consdev *cn)
830 {
831 }
832
833 static int
834 zs_cngetc(struct consdev *cn)
835 {
836         struct zstty_softc *sc = zstty_cons;
837
838         if (sc == NULL)
839                 return (-1);
840         return (zstty_cngetc(sc));
841 }
842
843 static int
844 zs_cncheckc(struct consdev *cn)
845 {
846         struct zstty_softc *sc = zstty_cons;
847
848         if (sc == NULL)
849                 return (-1);
850         return (zstty_cncheckc(sc));
851 }
852
853 static void
854 zs_cnputc(struct consdev *cn, int c)
855 {
856         struct zstty_softc *sc = zstty_cons;
857
858         if (sc == NULL)
859                 return;
860         zstty_cnputc(sc, c);
861 }
862
863 static void
864 zs_cndbctl(struct consdev *cn, int c)
865 {
866 }
867
868 static void
869 zstty_cnopen(struct zstty_softc *sc)
870 {
871 }
872
873 static void
874 zstty_cnclose(struct zstty_softc *sc)
875 {
876 }
877
878 static int
879 zstty_cngetc(struct zstty_softc *sc)
880 {
881         uint8_t c;
882
883         zstty_cnopen(sc);
884         while ((ZS_READ(sc, sc->sc_csr) & ZSRR0_RX_READY) == 0)
885                 ;
886         c = ZS_READ(sc, sc->sc_data);
887         zstty_cnclose(sc);
888         return (c);
889 }
890
891 static int
892 zstty_cncheckc(struct zstty_softc *sc)
893 {
894         int c;
895
896         c = -1;
897         zstty_cnopen(sc);
898         if ((ZS_READ(sc, sc->sc_csr) & ZSRR0_RX_READY) != 0)
899                 c = ZS_READ(sc, sc->sc_data);
900         zstty_cnclose(sc);
901         return (c);
902 }
903
904 static void
905 zstty_cnputc(struct zstty_softc *sc, int c)
906 {
907
908         zstty_cnopen(sc);
909         while ((ZS_READ(sc, sc->sc_csr) & ZSRR0_TX_READY) == 0)
910                 ;
911         ZS_WRITE(sc, sc->sc_data, c);
912         zstty_cnclose(sc);
913 }