Annotation of src/sys/dev/ic/com.c, Revision 1.138
1.138 ! mycroft 1: /* $NetBSD: com.c,v 1.137 1998/02/19 09:33:33 mycroft Exp $ */
1.38 cgd 2:
1.1 cgd 3: /*-
1.99 mycroft 4: * Copyright (c) 1993, 1994, 1995, 1996, 1997
1.71 mycroft 5: * Charles M. Hannum. All rights reserved.
1.99 mycroft 6: *
7: * Interrupt processing and hardware flow control partly based on code from
8: * Onno van der Linden and Gordon Ross.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by Charles M. Hannum.
21: * 4. The name of the author may not be used to endorse or promote products
22: * derived from this software without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34: */
35:
36: /*
1.1 cgd 37: * Copyright (c) 1991 The Regents of the University of California.
38: * All rights reserved.
39: *
40: * Redistribution and use in source and binary forms, with or without
41: * modification, are permitted provided that the following conditions
42: * are met:
43: * 1. Redistributions of source code must retain the above copyright
44: * notice, this list of conditions and the following disclaimer.
45: * 2. Redistributions in binary form must reproduce the above copyright
46: * notice, this list of conditions and the following disclaimer in the
47: * documentation and/or other materials provided with the distribution.
48: * 3. All advertising materials mentioning features or use of this software
49: * must display the following acknowledgement:
50: * This product includes software developed by the University of
51: * California, Berkeley and its contributors.
52: * 4. Neither the name of the University nor the names of its contributors
53: * may be used to endorse or promote products derived from this software
54: * without specific prior written permission.
55: *
56: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
57: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
59: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
60: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
62: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
63: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
64: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
65: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
66: * SUCH DAMAGE.
67: *
1.38 cgd 68: * @(#)com.c 7.5 (Berkeley) 5/16/91
1.1 cgd 69: */
70:
71: /*
1.99 mycroft 72: * COM driver, uses National Semiconductor NS16450/NS16550AF UART
1.116 fvdl 73: * Supports automatic hardware flow control on StarTech ST16C650A UART
1.1 cgd 74: */
1.115 explorer 75:
76: #include "rnd.h"
77: #if NRND > 0 && defined(RND_COM)
78: #include <sys/rnd.h>
79: #endif
80:
1.14 mycroft 81: #include <sys/param.h>
82: #include <sys/systm.h>
83: #include <sys/ioctl.h>
84: #include <sys/select.h>
85: #include <sys/tty.h>
86: #include <sys/proc.h>
87: #include <sys/user.h>
88: #include <sys/conf.h>
89: #include <sys/file.h>
90: #include <sys/uio.h>
91: #include <sys/kernel.h>
92: #include <sys/syslog.h>
93: #include <sys/types.h>
1.21 mycroft 94: #include <sys/device.h>
1.127 mycroft 95: #include <sys/malloc.h>
1.14 mycroft 96:
1.99 mycroft 97: #include <machine/intr.h>
1.82 mycroft 98: #include <machine/bus.h>
1.14 mycroft 99:
1.113 thorpej 100: #include <dev/ic/comreg.h>
101: #include <dev/ic/comvar.h>
1.60 cgd 102: #include <dev/ic/ns16550reg.h>
1.116 fvdl 103: #include <dev/ic/st16650reg.h>
1.65 christos 104: #ifdef COM_HAYESP
105: #include <dev/ic/hayespreg.h>
106: #endif
1.62 mycroft 107: #define com_lcr com_cfcr
1.106 drochner 108: #include <dev/cons.h>
1.14 mycroft 109:
1.77 cgd 110: #include "com.h"
111:
1.65 christos 112: #ifdef COM_HAYESP
1.99 mycroft 113: int comprobeHAYESP __P((bus_space_handle_t hayespioh, struct com_softc *sc));
1.65 christos 114: #endif
1.102 thorpej 115:
1.104 drochner 116: #if defined(DDB) || defined(KGDB)
117: static void com_enable_debugport __P((struct com_softc *));
118: #endif
1.99 mycroft 119: void com_attach_subr __P((struct com_softc *sc));
1.131 marc 120: void com_config __P((struct com_softc *));
1.109 is 121: int comspeed __P((long, long));
1.106 drochner 122: static u_char cflag2lcr __P((tcflag_t));
1.80 christos 123: int comparam __P((struct tty *, struct termios *));
124: void comstart __P((struct tty *));
1.99 mycroft 125: void comstop __P((struct tty *, int));
126: int comhwiflow __P((struct tty *, int));
127:
128: void com_loadchannelregs __P((struct com_softc *));
1.101 mycroft 129: void com_hwiflow __P((struct com_softc *));
1.99 mycroft 130: void com_break __P((struct com_softc *, int));
131: void com_modem __P((struct com_softc *, int));
132: void com_iflush __P((struct com_softc *));
1.80 christos 133:
1.102 thorpej 134: int com_common_getc __P((bus_space_tag_t, bus_space_handle_t));
135: void com_common_putc __P((bus_space_tag_t, bus_space_handle_t, int));
136:
1.80 christos 137: /* XXX: These belong elsewhere */
138: cdev_decl(com);
139: bdev_decl(com);
140:
141: int comcngetc __P((dev_t));
142: void comcnputc __P((dev_t, int));
143: void comcnpollc __P((dev_t, int));
144:
1.99 mycroft 145: #define integrate static inline
1.127 mycroft 146: #ifdef __GENERIC_SOFT_INTERRUPTS
147: void comsoft __P((void *));
148: #else
1.133 cgd 149: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.127 mycroft 150: void comsoft __P((void));
151: #else
152: void comsoft __P((void *));
153: #endif
154: #endif
155: integrate void com_rxsoft __P((struct com_softc *, struct tty *));
156: integrate void com_txsoft __P((struct com_softc *, struct tty *));
157: integrate void com_stsoft __P((struct com_softc *, struct tty *));
1.101 mycroft 158: integrate void com_schedrx __P((struct com_softc *));
1.127 mycroft 159: void comdiag __P((void *));
160:
1.130 thorpej 161: extern struct cfdriver com_cd;
1.76 thorpej 162:
1.127 mycroft 163: /*
164: * Make this an option variable one can patch.
165: * But be warned: this must be a power of 2!
166: */
167: u_int com_rbuf_size = COM_RING_SIZE;
168:
169: /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
170: u_int com_rbuf_hiwat = (COM_RING_SIZE * 1) / 4;
171: u_int com_rbuf_lowat = (COM_RING_SIZE * 3) / 4;
172:
1.106 drochner 173: static int comconsaddr;
174: static bus_space_tag_t comconstag;
175: static bus_space_handle_t comconsioh;
176: static int comconsattached;
177: static int comconsrate;
178: static tcflag_t comconscflag;
1.99 mycroft 179:
1.111 christos 180: static u_char tiocm_xxx2mcr __P((int));
181:
1.99 mycroft 182: #ifndef __GENERIC_SOFT_INTERRUPTS
1.133 cgd 183: #ifdef __NO_SOFT_SERIAL_INTERRUPT
1.99 mycroft 184: volatile int com_softintr_scheduled;
185: #endif
186: #endif
1.1 cgd 187:
188: #ifdef KGDB
1.102 thorpej 189: #include <sys/kgdb.h>
1.106 drochner 190:
191: static int com_kgdb_addr;
192: static bus_space_tag_t com_kgdb_iot;
193: static bus_space_handle_t com_kgdb_ioh;
194: static int com_kgdb_attached;
1.102 thorpej 195:
196: int com_kgdb_getc __P((void *));
197: void com_kgdb_putc __P((void *, int));
198: #endif /* KGDB */
1.1 cgd 199:
1.21 mycroft 200: #define COMUNIT(x) (minor(x))
1.1 cgd 201:
1.21 mycroft 202: int
1.109 is 203: comspeed(speed, frequency)
204: long speed, frequency;
1.1 cgd 205: {
1.21 mycroft 206: #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
207:
208: int x, err;
209:
1.99 mycroft 210: #if 0
1.21 mycroft 211: if (speed == 0)
1.99 mycroft 212: return (0);
213: #endif
214: if (speed <= 0)
215: return (-1);
1.109 is 216: x = divrnd(frequency / 16, speed);
1.21 mycroft 217: if (x <= 0)
1.99 mycroft 218: return (-1);
1.114 is 219: err = divrnd(((quad_t)frequency) * 1000 / 16, speed * x) - 1000;
1.21 mycroft 220: if (err < 0)
221: err = -err;
222: if (err > COM_TOLERANCE)
1.99 mycroft 223: return (-1);
224: return (x);
1.21 mycroft 225:
226: #undef divrnd(n, q)
227: }
228:
1.99 mycroft 229: #ifdef COM_DEBUG
1.101 mycroft 230: int com_debug = 0;
231:
1.99 mycroft 232: void comstatus __P((struct com_softc *, char *));
233: void
234: comstatus(sc, str)
235: struct com_softc *sc;
236: char *str;
237: {
238: struct tty *tp = sc->sc_tty;
239:
240: printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n",
241: sc->sc_dev.dv_xname, str,
242: ISSET(tp->t_cflag, CLOCAL) ? "+" : "-",
243: ISSET(sc->sc_msr, MSR_DCD) ? "+" : "-",
244: ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-",
245: ISSET(sc->sc_mcr, MCR_DTR) ? "+" : "-",
246: sc->sc_tx_stopped ? "+" : "-");
247:
1.101 mycroft 248: printf("%s: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n",
1.99 mycroft 249: sc->sc_dev.dv_xname, str,
250: ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-",
251: ISSET(sc->sc_msr, MSR_CTS) ? "+" : "-",
252: ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-",
253: ISSET(sc->sc_mcr, MCR_RTS) ? "+" : "-",
1.101 mycroft 254: sc->sc_rx_flags);
1.99 mycroft 255: }
256: #endif
257:
1.21 mycroft 258: int
1.91 thorpej 259: comprobe1(iot, ioh, iobase)
260: bus_space_tag_t iot;
261: bus_space_handle_t ioh;
1.41 mycroft 262: int iobase;
1.21 mycroft 263: {
264:
1.1 cgd 265: /* force access to id reg */
1.91 thorpej 266: bus_space_write_1(iot, ioh, com_lcr, 0);
267: bus_space_write_1(iot, ioh, com_iir, 0);
268: if (bus_space_read_1(iot, ioh, com_iir) & 0x38)
1.99 mycroft 269: return (0);
1.21 mycroft 270:
1.99 mycroft 271: return (1);
1.1 cgd 272: }
273:
1.65 christos 274: #ifdef COM_HAYESP
275: int
1.75 cgd 276: comprobeHAYESP(hayespioh, sc)
1.91 thorpej 277: bus_space_handle_t hayespioh;
1.64 christos 278: struct com_softc *sc;
279: {
1.65 christos 280: char val, dips;
1.64 christos 281: int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
1.91 thorpej 282: bus_space_tag_t iot = sc->sc_iot;
1.64 christos 283:
284: /*
285: * Hayes ESP cards have two iobases. One is for compatibility with
286: * 16550 serial chips, and at the same ISA PC base addresses. The
287: * other is for ESP-specific enhanced features, and lies at a
1.65 christos 288: * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
1.64 christos 289: */
290:
291: /* Test for ESP signature */
1.91 thorpej 292: if ((bus_space_read_1(iot, hayespioh, 0) & 0xf3) == 0)
1.99 mycroft 293: return (0);
1.64 christos 294:
295: /*
296: * ESP is present at ESP enhanced base address; unknown com port
297: */
298:
299: /* Get the dip-switch configurations */
1.91 thorpej 300: bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
301: dips = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1);
1.64 christos 302:
303: /* Determine which com port this ESP card services: bits 0,1 of */
304: /* dips is the port # (0-3); combaselist[val] is the com_iobase */
1.65 christos 305: if (sc->sc_iobase != combaselist[dips & 0x03])
1.99 mycroft 306: return (0);
1.65 christos 307:
1.90 christos 308: printf(": ESP");
1.64 christos 309:
1.65 christos 310: /* Check ESP Self Test bits. */
1.64 christos 311: /* Check for ESP version 2.0: bits 4,5,6 == 010 */
1.91 thorpej 312: bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
1.99 mycroft 313: val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1); /* Clear reg1 */
1.91 thorpej 314: val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS2);
1.64 christos 315: if ((val & 0x70) < 0x20) {
1.90 christos 316: printf("-old (%o)", val & 0x70);
1.64 christos 317: /* we do not support the necessary features */
1.99 mycroft 318: return (0);
1.64 christos 319: }
320:
321: /* Check for ability to emulate 16550: bit 8 == 1 */
322: if ((dips & 0x80) == 0) {
1.90 christos 323: printf(" slave");
1.64 christos 324: /* XXX Does slave really mean no 16550 support?? */
1.99 mycroft 325: return (0);
1.64 christos 326: }
327:
328: /*
329: * If we made it this far, we are a full-featured ESP v2.0 (or
330: * better), at the correct com port address.
331: */
332:
1.65 christos 333: SET(sc->sc_hwflags, COM_HW_HAYESP);
1.90 christos 334: printf(", 1024 byte fifo\n");
1.99 mycroft 335: return (1);
1.64 christos 336: }
1.65 christos 337: #endif
1.64 christos 338:
1.104 drochner 339: #if defined(DDB) || defined(KGDB)
340: static void
341: com_enable_debugport(sc)
342: struct com_softc *sc;
343: {
344: int s;
345:
346: /* Turn on line break interrupt, set carrier. */
347: s = splserial();
348: sc->sc_ier = IER_ERXRDY;
349: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
350: SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
351: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
352: splx(s);
353: }
354: #endif
1.1 cgd 355:
1.29 mycroft 356: void
1.99 mycroft 357: com_attach_subr(sc)
358: struct com_softc *sc;
1.29 mycroft 359: {
1.99 mycroft 360: int iobase = sc->sc_iobase;
361: bus_space_tag_t iot = sc->sc_iot;
362: bus_space_handle_t ioh = sc->sc_ioh;
1.127 mycroft 363: struct tty *tp;
1.118 fvdl 364: #ifdef COM16650
1.116 fvdl 365: u_int8_t lcr;
1.118 fvdl 366: #endif
1.65 christos 367: #ifdef COM_HAYESP
368: int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
369: int *hayespp;
370: #endif
1.117 mycroft 371:
372: /* Disable interrupts before configuring the device. */
373: sc->sc_ier = 0;
1.131 marc 374: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.1 cgd 375:
1.106 drochner 376: if (iot == comconstag && iobase == comconsaddr) {
1.105 drochner 377: comconsattached = 1;
378:
1.96 mycroft 379: /* Make sure the console is always "hardwired". */
1.75 cgd 380: delay(1000); /* wait for output to finish */
381: SET(sc->sc_hwflags, COM_HW_CONSOLE);
1.99 mycroft 382: SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
1.75 cgd 383: }
1.26 cgd 384:
1.65 christos 385: #ifdef COM_HAYESP
386: /* Look for a Hayes ESP board. */
1.75 cgd 387: for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
1.91 thorpej 388: bus_space_handle_t hayespioh;
1.75 cgd 389:
390: #define HAYESP_NPORTS 8 /* XXX XXX XXX ??? ??? ??? */
1.92 cgd 391: if (bus_space_map(iot, *hayespp, HAYESP_NPORTS, 0, &hayespioh))
1.75 cgd 392: continue;
393: if (comprobeHAYESP(hayespioh, sc)) {
394: sc->sc_hayespioh = hayespioh;
1.99 mycroft 395: sc->sc_fifolen = 1024;
396:
1.65 christos 397: break;
398: }
1.91 thorpej 399: bus_space_unmap(iot, hayespioh, HAYESP_NPORTS);
1.75 cgd 400: }
1.65 christos 401: /* No ESP; look for other things. */
1.131 marc 402: if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
1.65 christos 403: #endif
1.99 mycroft 404: sc->sc_fifolen = 1;
1.1 cgd 405: /* look for a NS 16550AF UART with FIFOs */
1.91 thorpej 406: bus_space_write_1(iot, ioh, com_fifo,
1.21 mycroft 407: FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
1.20 mycroft 408: delay(100);
1.99 mycroft 409: if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK)
410: == IIR_FIFO_MASK)
411: if (ISSET(bus_space_read_1(iot, ioh, com_fifo), FIFO_TRIGGER_14)
412: == FIFO_TRIGGER_14) {
1.62 mycroft 413: SET(sc->sc_hwflags, COM_HW_FIFO);
1.116 fvdl 414:
1.118 fvdl 415: #ifdef COM16650
1.116 fvdl 416: /*
417: * IIR changes into the EFR if LCR is set to LCR_EERS
418: * on 16650s. We also know IIR != 0 at this point.
419: * Write 0 into the EFR, and read it. If the result
420: * is 0, we have a 16650.
421: *
422: * Older 16650s were broken; the test to detect them
423: * is taken from the Linux driver. Apparently
424: * setting DLAB enable gives access to the EFR on
425: * these chips.
426: */
427: lcr = bus_space_read_1(iot, ioh, com_lcr);
428: bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
429: bus_space_write_1(iot, ioh, com_efr, 0);
430: if (bus_space_read_1(iot, ioh, com_efr) == 0) {
431: bus_space_write_1(iot, ioh, com_lcr,
432: lcr | LCR_DLAB);
433: if (bus_space_read_1(iot, ioh, com_efr) == 0) {
434: CLR(sc->sc_hwflags, COM_HW_FIFO);
435: sc->sc_fifolen = 0;
436: } else {
437: SET(sc->sc_hwflags, COM_HW_FLOW);
438: sc->sc_fifolen = 32;
439: }
1.118 fvdl 440: } else
441: #endif
1.116 fvdl 442: sc->sc_fifolen = 16;
443:
1.118 fvdl 444: #ifdef COM16650
1.119 drochner 445: bus_space_write_1(iot, ioh, com_lcr, lcr);
446: if (sc->sc_fifolen == 0)
447: printf(": st16650, broken fifo\n");
448: else if (sc->sc_fifolen == 32)
449: printf(": st16650a, working fifo\n");
450: else
1.118 fvdl 451: #endif
1.119 drochner 452: printf(": ns16550a, working fifo\n");
1.21 mycroft 453: } else
1.90 christos 454: printf(": ns16550, broken fifo\n");
1.21 mycroft 455: else
1.90 christos 456: printf(": ns8250 or ns16450, no fifo\n");
1.91 thorpej 457: bus_space_write_1(iot, ioh, com_fifo, 0);
1.65 christos 458: #ifdef COM_HAYESP
459: }
460: #endif
1.21 mycroft 461:
1.127 mycroft 462: tp = ttymalloc();
463: tp->t_oproc = comstart;
464: tp->t_param = comparam;
465: tp->t_hwiflow = comhwiflow;
466: tty_attach(tp);
467:
468: sc->sc_tty = tp;
469: sc->sc_rbuf = malloc(com_rbuf_size << 1, M_DEVBUF, M_WAITOK);
470: sc->sc_ebuf = sc->sc_rbuf + (com_rbuf_size << 1);
471:
1.99 mycroft 472: if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
473: SET(sc->sc_mcr, MCR_IENABLE);
1.30 mycroft 474:
1.96 mycroft 475: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.106 drochner 476: int maj;
477:
478: /* locate the major number */
479: for (maj = 0; maj < nchrdev; maj++)
480: if (cdevsw[maj].d_open == comopen)
481: break;
482:
483: cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
1.131 marc 484:
1.96 mycroft 485: printf("%s: console\n", sc->sc_dev.dv_xname);
486: }
487:
1.1 cgd 488: #ifdef KGDB
1.102 thorpej 489: /*
490: * Allow kgdb to "take over" this port. If this is
491: * the kgdb device, it has exclusive use.
492: */
1.106 drochner 493: if (iot == com_kgdb_iot && iobase == com_kgdb_addr) {
494: com_kgdb_attached = 1;
495:
1.104 drochner 496: SET(sc->sc_hwflags, COM_HW_KGDB);
1.103 drochner 497: printf("%s: kgdb\n", sc->sc_dev.dv_xname);
498: }
1.99 mycroft 499: #endif
500:
501: #ifdef __GENERIC_SOFT_INTERRUPTS
502: sc->sc_si = softintr_establish(IPL_SOFTSERIAL, comsoft, sc);
1.1 cgd 503: #endif
1.115 explorer 504:
505: #if NRND > 0 && defined(RND_COM)
506: rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
507: RND_TYPE_TTY);
508: #endif
1.131 marc 509:
510: /* if there are no enable/disable functions, assume the device
511: is always enabled */
512: if (!sc->enable)
513: sc->enabled = 1;
514:
515: com_config(sc);
1.132 cgd 516:
517: SET(sc->sc_hwflags, COM_HW_DEV_OK);
1.131 marc 518: }
519:
520: void
521: com_config(sc)
522: struct com_softc *sc;
523: {
524: bus_space_tag_t iot = sc->sc_iot;
525: bus_space_handle_t ioh = sc->sc_ioh;
526:
527: /* Disable interrupts before configuring the device. */
528: sc->sc_ier = 0;
529: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
530:
531: #ifdef COM_HAYESP
532: /* Look for a Hayes ESP board. */
533: if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
534: sc->sc_fifolen = 1024;
535:
536: /* Set 16550 compatibility mode */
537: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
538: HAYESP_SETMODE);
539: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
540: HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
541: HAYESP_MODE_SCALE);
542:
543: /* Set RTS/CTS flow control */
544: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
545: HAYESP_SETFLOWTYPE);
546: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
547: HAYESP_FLOW_RTS);
548: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
549: HAYESP_FLOW_CTS);
550:
551: /* Set flow control levels */
552: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
553: HAYESP_SETRXFLOW);
554: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
555: HAYESP_HIBYTE(HAYESP_RXHIWMARK));
556: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
557: HAYESP_LOBYTE(HAYESP_RXHIWMARK));
558: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
559: HAYESP_HIBYTE(HAYESP_RXLOWMARK));
560: bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
561: HAYESP_LOBYTE(HAYESP_RXLOWMARK));
562: }
563: #endif
564:
565: #ifdef DDB
566: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
567: com_enable_debugport(sc);
568: #endif
569:
570: #ifdef KGDB
571: /*
572: * Allow kgdb to "take over" this port. If this is
573: * the kgdb device, it has exclusive use.
574: */
575: if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
576: com_enable_debugport(sc);
577: #endif
1.1 cgd 578: }
579:
1.21 mycroft 580: int
581: comopen(dev, flag, mode, p)
582: dev_t dev;
583: int flag, mode;
584: struct proc *p;
1.1 cgd 585: {
1.21 mycroft 586: int unit = COMUNIT(dev);
587: struct com_softc *sc;
588: struct tty *tp;
1.99 mycroft 589: int s, s2;
1.1 cgd 590: int error = 0;
591:
1.76 thorpej 592: if (unit >= com_cd.cd_ndevs)
1.99 mycroft 593: return (ENXIO);
1.76 thorpej 594: sc = com_cd.cd_devs[unit];
1.132 cgd 595: if (!sc || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK))
1.99 mycroft 596: return (ENXIO);
1.21 mycroft 597:
1.102 thorpej 598: #ifdef KGDB
599: /*
600: * If this is the kgdb port, no other use is permitted.
601: */
602: if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
603: return (EBUSY);
604: #endif
605:
1.120 mycroft 606: tp = sc->sc_tty;
1.21 mycroft 607:
1.99 mycroft 608: if (ISSET(tp->t_state, TS_ISOPEN) &&
609: ISSET(tp->t_state, TS_XCLUDE) &&
610: p->p_ucred->cr_uid != 0)
611: return (EBUSY);
612:
613: s = spltty();
614:
615: /* We need to set this early for the benefit of comsoft(). */
616: SET(tp->t_state, TS_WOPEN);
617:
618: /*
619: * Do the following iff this is a first open.
620: */
1.62 mycroft 621: if (!ISSET(tp->t_state, TS_ISOPEN)) {
1.99 mycroft 622: struct termios t;
623:
1.127 mycroft 624: tp->t_dev = dev;
625:
1.120 mycroft 626: s2 = splserial();
627:
1.131 marc 628: if (sc->enable) {
629: if ((*sc->enable)(sc)) {
1.134 enami 630: splx(s);
1.131 marc 631: printf("%s: device enable failed\n",
632: sc->sc_dev.dv_xname);
633: return (EIO);
634: }
635: sc->enabled = 1;
636: com_config(sc);
637: }
638:
1.99 mycroft 639: /* Turn on interrupts. */
640: sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
641: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
642:
643: /* Fetch the current modem control status, needed later. */
644: sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr);
645:
1.120 mycroft 646: splx(s2);
1.99 mycroft 647:
648: /*
649: * Initialize the termios status to the defaults. Add in the
650: * sticky bits from TIOCSFLAGS.
651: */
652: t.c_ispeed = 0;
1.98 mycroft 653: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.99 mycroft 654: t.c_ospeed = comconsrate;
655: t.c_cflag = comconscflag;
1.98 mycroft 656: } else {
1.99 mycroft 657: t.c_ospeed = TTYDEF_SPEED;
658: t.c_cflag = TTYDEF_CFLAG;
1.98 mycroft 659: }
1.99 mycroft 660: if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
661: SET(t.c_cflag, CLOCAL);
662: if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
663: SET(t.c_cflag, CRTSCTS);
664: if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
665: SET(t.c_cflag, MDMBUF);
1.129 mycroft 666: /* Make sure comparam() will do something. */
667: tp->t_ospeed = 0;
1.120 mycroft 668: (void) comparam(tp, &t);
1.99 mycroft 669: tp->t_iflag = TTYDEF_IFLAG;
670: tp->t_oflag = TTYDEF_OFLAG;
1.16 ws 671: tp->t_lflag = TTYDEF_LFLAG;
1.99 mycroft 672: ttychars(tp);
1.1 cgd 673: ttsetwater(tp);
1.21 mycroft 674:
1.136 mycroft 675: s2 = splserial();
676:
1.99 mycroft 677: /*
678: * Turn on DTR. We must always do this, even if carrier is not
679: * present, because otherwise we'd have to use TIOCSDTR
1.121 mycroft 680: * immediately after setting CLOCAL, which applications do not
681: * expect. We always assert DTR while the device is open
682: * unless explicitly requested to deassert it.
1.99 mycroft 683: */
684: com_modem(sc, 1);
1.65 christos 685:
1.99 mycroft 686: /* Clear the input ring, and unblock. */
1.127 mycroft 687: sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
688: sc->sc_rbavail = com_rbuf_size;
1.99 mycroft 689: com_iflush(sc);
1.101 mycroft 690: CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
691: com_hwiflow(sc);
1.65 christos 692:
1.99 mycroft 693: #ifdef COM_DEBUG
1.101 mycroft 694: if (com_debug)
695: comstatus(sc, "comopen ");
1.65 christos 696: #endif
1.21 mycroft 697:
1.99 mycroft 698: splx(s2);
699: }
700: error = 0;
1.21 mycroft 701:
1.99 mycroft 702: /* If we're doing a blocking open... */
1.62 mycroft 703: if (!ISSET(flag, O_NONBLOCK))
1.99 mycroft 704: /* ...then wait for carrier. */
705: while (!ISSET(tp->t_state, TS_CARR_ON) &&
706: !ISSET(tp->t_cflag, CLOCAL | MDMBUF)) {
1.62 mycroft 707: error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
708: ttopen, 0);
1.21 mycroft 709: if (error) {
1.99 mycroft 710: /*
711: * If the open was interrupted and nobody
712: * else has the device open, then hang up.
713: */
714: if (!ISSET(tp->t_state, TS_ISOPEN)) {
1.136 mycroft 715: s2 = splserial();
716:
717: /* Hang up. */
1.99 mycroft 718: com_modem(sc, 0);
1.136 mycroft 719:
1.99 mycroft 720: CLR(tp->t_state, TS_WOPEN);
721: ttwakeup(tp);
1.136 mycroft 722:
723: splx(s2);
1.99 mycroft 724: }
725: break;
1.21 mycroft 726: }
1.99 mycroft 727: SET(tp->t_state, TS_WOPEN);
1.21 mycroft 728: }
1.99 mycroft 729:
1.21 mycroft 730: splx(s);
1.99 mycroft 731: if (error == 0)
732: error = (*linesw[tp->t_line].l_open)(dev, tp);
733: return (error);
1.1 cgd 734: }
735:
1.21 mycroft 736: int
1.1 cgd 737: comclose(dev, flag, mode, p)
738: dev_t dev;
739: int flag, mode;
740: struct proc *p;
741: {
1.127 mycroft 742: struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.50 mycroft 743: struct tty *tp = sc->sc_tty;
1.57 mycroft 744: int s;
745:
746: /* XXX This is for cons.c. */
1.62 mycroft 747: if (!ISSET(tp->t_state, TS_ISOPEN))
1.99 mycroft 748: return (0);
1.21 mycroft 749:
1.1 cgd 750: (*linesw[tp->t_line].l_close)(tp, flag);
751: ttyclose(tp);
1.99 mycroft 752:
1.120 mycroft 753: s = splserial();
754:
1.99 mycroft 755: /* If we were asserting flow control, then deassert it. */
1.101 mycroft 756: SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
757: com_hwiflow(sc);
1.122 mycroft 758:
1.99 mycroft 759: /* Clear any break condition set with TIOCSBRK. */
760: com_break(sc, 0);
1.120 mycroft 761:
1.99 mycroft 762: /*
763: * Hang up if necessary. Wait a bit, so the other side has time to
764: * notice even if we immediately open the port again.
765: */
766: if (ISSET(tp->t_cflag, HUPCL)) {
767: com_modem(sc, 0);
768: (void) tsleep(sc, TTIPRI, ttclos, hz);
1.21 mycroft 769: }
1.99 mycroft 770:
771: /* Turn off interrupts. */
1.104 drochner 772: #ifdef DDB
1.122 mycroft 773: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
1.104 drochner 774: sc->sc_ier = IER_ERXRDY; /* interrupt on break */
775: else
1.127 mycroft 776: #endif
1.104 drochner 777: sc->sc_ier = 0;
1.99 mycroft 778: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
1.120 mycroft 779:
1.131 marc 780: if (sc->disable) {
781: if (sc->enabled) {
782: (*sc->disable)(sc);
783: sc->enabled = 0;
784: }
785: }
786:
1.99 mycroft 787: splx(s);
788:
789: return (0);
1.1 cgd 790: }
791:
1.21 mycroft 792: int
1.1 cgd 793: comread(dev, uio, flag)
794: dev_t dev;
795: struct uio *uio;
1.21 mycroft 796: int flag;
1.1 cgd 797: {
1.76 thorpej 798: struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.52 mycroft 799: struct tty *tp = sc->sc_tty;
1.1 cgd 800:
801: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
802: }
803:
1.21 mycroft 804: int
1.1 cgd 805: comwrite(dev, uio, flag)
806: dev_t dev;
807: struct uio *uio;
1.21 mycroft 808: int flag;
1.1 cgd 809: {
1.76 thorpej 810: struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.52 mycroft 811: struct tty *tp = sc->sc_tty;
1.1 cgd 812:
813: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
814: }
1.50 mycroft 815:
816: struct tty *
817: comtty(dev)
818: dev_t dev;
819: {
1.76 thorpej 820: struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.52 mycroft 821: struct tty *tp = sc->sc_tty;
1.50 mycroft 822:
1.52 mycroft 823: return (tp);
1.50 mycroft 824: }
1.111 christos 825:
826: static u_char
827: tiocm_xxx2mcr(data)
828: int data;
829: {
830: u_char m = 0;
831:
832: if (ISSET(data, TIOCM_DTR))
833: SET(m, MCR_DTR);
834: if (ISSET(data, TIOCM_RTS))
835: SET(m, MCR_RTS);
836: return m;
837: }
1.1 cgd 838:
1.21 mycroft 839: int
1.19 mycroft 840: comioctl(dev, cmd, data, flag, p)
1.1 cgd 841: dev_t dev;
1.39 cgd 842: u_long cmd;
1.1 cgd 843: caddr_t data;
1.19 mycroft 844: int flag;
845: struct proc *p;
1.1 cgd 846: {
1.127 mycroft 847: struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.50 mycroft 848: struct tty *tp = sc->sc_tty;
1.21 mycroft 849: int error;
1.136 mycroft 850: int s;
1.21 mycroft 851:
1.19 mycroft 852: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1.1 cgd 853: if (error >= 0)
1.99 mycroft 854: return (error);
855:
1.19 mycroft 856: error = ttioctl(tp, cmd, data, flag, p);
1.1 cgd 857: if (error >= 0)
1.99 mycroft 858: return (error);
1.138 ! mycroft 859:
! 860: error = 0;
1.1 cgd 861:
1.136 mycroft 862: s = splserial();
863:
1.1 cgd 864: switch (cmd) {
865: case TIOCSBRK:
1.99 mycroft 866: com_break(sc, 1);
1.1 cgd 867: break;
1.99 mycroft 868:
1.1 cgd 869: case TIOCCBRK:
1.99 mycroft 870: com_break(sc, 0);
1.1 cgd 871: break;
1.99 mycroft 872:
1.1 cgd 873: case TIOCSDTR:
1.99 mycroft 874: com_modem(sc, 1);
1.1 cgd 875: break;
1.99 mycroft 876:
1.1 cgd 877: case TIOCCDTR:
1.99 mycroft 878: com_modem(sc, 0);
1.1 cgd 879: break;
1.99 mycroft 880:
881: case TIOCGFLAGS:
882: *(int *)data = sc->sc_swflags;
883: break;
884:
885: case TIOCSFLAGS:
886: error = suser(p->p_ucred, &p->p_acflag);
887: if (error)
1.136 mycroft 888: break;
1.99 mycroft 889: sc->sc_swflags = *(int *)data;
890: break;
891:
1.1 cgd 892: case TIOCMSET:
1.111 christos 893: CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
894: /*FALLTHROUGH*/
895:
1.1 cgd 896: case TIOCMBIS:
1.111 christos 897: SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
898: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
899: break;
900:
1.1 cgd 901: case TIOCMBIC:
1.111 christos 902: CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
903: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
904: break;
905:
906: case TIOCMGET: {
907: u_char m;
908: int bits = 0;
909:
910: m = sc->sc_mcr;
911: if (ISSET(m, MCR_DTR))
912: SET(bits, TIOCM_DTR);
913: if (ISSET(m, MCR_RTS))
914: SET(bits, TIOCM_RTS);
915: m = sc->sc_msr;
916: if (ISSET(m, MSR_DCD))
917: SET(bits, TIOCM_CD);
918: if (ISSET(m, MSR_CTS))
919: SET(bits, TIOCM_CTS);
920: if (ISSET(m, MSR_DSR))
921: SET(bits, TIOCM_DSR);
922: if (ISSET(m, MSR_RI | MSR_TERI))
923: SET(bits, TIOCM_RI);
924: if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_ier))
925: SET(bits, TIOCM_LE);
926: *(int *)data = bits;
927: break;
928: }
1.99 mycroft 929: default:
1.136 mycroft 930: error = ENOTTY;
931: break;
1.21 mycroft 932: }
1.22 cgd 933:
1.136 mycroft 934: splx(s);
935:
1.99 mycroft 936: #ifdef COM_DEBUG
1.101 mycroft 937: if (com_debug)
1.99 mycroft 938: comstatus(sc, "comioctl ");
939: #endif
940:
1.136 mycroft 941: return (error);
1.99 mycroft 942: }
943:
1.101 mycroft 944: integrate void
945: com_schedrx(sc)
946: struct com_softc *sc;
947: {
948:
949: sc->sc_rx_ready = 1;
950:
951: /* Wake up the poller. */
952: #ifdef __GENERIC_SOFT_INTERRUPTS
953: softintr_schedule(sc->sc_si);
954: #else
1.133 cgd 955: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.101 mycroft 956: setsoftserial();
957: #else
958: if (!com_softintr_scheduled) {
959: com_softintr_scheduled = 1;
960: timeout(comsoft, NULL, 1);
961: }
962: #endif
963: #endif
964: }
965:
1.99 mycroft 966: void
967: com_break(sc, onoff)
968: struct com_softc *sc;
969: int onoff;
970: {
971:
972: if (onoff)
973: SET(sc->sc_lcr, LCR_SBREAK);
974: else
975: CLR(sc->sc_lcr, LCR_SBREAK);
1.22 cgd 976:
1.99 mycroft 977: if (!sc->sc_heldchange) {
978: if (sc->sc_tx_busy) {
979: sc->sc_heldtbc = sc->sc_tbc;
980: sc->sc_tbc = 0;
981: sc->sc_heldchange = 1;
982: } else
983: com_loadchannelregs(sc);
1.22 cgd 984: }
1.99 mycroft 985: }
1.22 cgd 986:
1.99 mycroft 987: void
988: com_modem(sc, onoff)
989: struct com_softc *sc;
990: int onoff;
991: {
1.22 cgd 992:
1.99 mycroft 993: if (onoff)
994: SET(sc->sc_mcr, sc->sc_mcr_dtr);
995: else
996: CLR(sc->sc_mcr, sc->sc_mcr_dtr);
1.22 cgd 997:
1.99 mycroft 998: if (!sc->sc_heldchange) {
999: if (sc->sc_tx_busy) {
1000: sc->sc_heldtbc = sc->sc_tbc;
1001: sc->sc_tbc = 0;
1002: sc->sc_heldchange = 1;
1003: } else
1004: com_loadchannelregs(sc);
1.22 cgd 1005: }
1.1 cgd 1006: }
1007:
1.106 drochner 1008: static u_char
1009: cflag2lcr(cflag)
1.110 enami 1010: tcflag_t cflag;
1.106 drochner 1011: {
1012: u_char lcr = 0;
1013:
1014: switch (ISSET(cflag, CSIZE)) {
1.127 mycroft 1015: case CS5:
1.106 drochner 1016: SET(lcr, LCR_5BITS);
1017: break;
1.127 mycroft 1018: case CS6:
1.106 drochner 1019: SET(lcr, LCR_6BITS);
1020: break;
1.127 mycroft 1021: case CS7:
1.106 drochner 1022: SET(lcr, LCR_7BITS);
1023: break;
1.127 mycroft 1024: case CS8:
1.106 drochner 1025: SET(lcr, LCR_8BITS);
1026: break;
1027: }
1028: if (ISSET(cflag, PARENB)) {
1029: SET(lcr, LCR_PENAB);
1030: if (!ISSET(cflag, PARODD))
1031: SET(lcr, LCR_PEVEN);
1032: }
1033: if (ISSET(cflag, CSTOPB))
1034: SET(lcr, LCR_STOPB);
1035:
1.110 enami 1036: return (lcr);
1.106 drochner 1037: }
1038:
1.21 mycroft 1039: int
1.1 cgd 1040: comparam(tp, t)
1.21 mycroft 1041: struct tty *tp;
1042: struct termios *t;
1.1 cgd 1043: {
1.76 thorpej 1044: struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1.109 is 1045: int ospeed = comspeed(t->c_ospeed, sc->sc_frequency);
1.62 mycroft 1046: u_char lcr;
1.21 mycroft 1047: int s;
1048:
1.127 mycroft 1049: /* Check requested parameters. */
1.99 mycroft 1050: if (ospeed < 0)
1051: return (EINVAL);
1052: if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
1053: return (EINVAL);
1.21 mycroft 1054:
1.99 mycroft 1055: /*
1056: * For the console, always force CLOCAL and !HUPCL, so that the port
1057: * is always active.
1058: */
1059: if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
1060: ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1061: SET(t->c_cflag, CLOCAL);
1062: CLR(t->c_cflag, HUPCL);
1.62 mycroft 1063: }
1.129 mycroft 1064:
1065: /*
1066: * If there were no changes, don't do anything. This avoids dropping
1067: * input and improves performance when all we did was frob things like
1068: * VMIN and VTIME.
1069: */
1070: if (tp->t_ospeed == t->c_ospeed &&
1071: tp->t_cflag == t->c_cflag)
1072: return (0);
1.126 mycroft 1073:
1074: lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag);
1075:
1076: s = splserial();
1077:
1078: sc->sc_lcr = lcr;
1.36 mycroft 1079:
1080: /*
1.99 mycroft 1081: * If we're not in a mode that assumes a connection is present, then
1082: * ignore carrier changes.
1.36 mycroft 1083: */
1.99 mycroft 1084: if (ISSET(t->c_cflag, CLOCAL | MDMBUF))
1085: sc->sc_msr_dcd = 0;
1086: else
1087: sc->sc_msr_dcd = MSR_DCD;
1088: /*
1089: * Set the flow control pins depending on the current flow control
1090: * mode.
1091: */
1092: if (ISSET(t->c_cflag, CRTSCTS)) {
1093: sc->sc_mcr_dtr = MCR_DTR;
1094: sc->sc_mcr_rts = MCR_RTS;
1095: sc->sc_msr_cts = MSR_CTS;
1.116 fvdl 1096: sc->sc_efr = EFR_AUTORTS | EFR_AUTOCTS;
1.99 mycroft 1097: } else if (ISSET(t->c_cflag, MDMBUF)) {
1098: /*
1099: * For DTR/DCD flow control, make sure we don't toggle DTR for
1100: * carrier detection.
1101: */
1102: sc->sc_mcr_dtr = 0;
1103: sc->sc_mcr_rts = MCR_DTR;
1104: sc->sc_msr_cts = MSR_DCD;
1.116 fvdl 1105: sc->sc_efr = 0;
1.99 mycroft 1106: } else {
1107: /*
1108: * If no flow control, then always set RTS. This will make
1109: * the other side happy if it mistakenly thinks we're doing
1110: * RTS/CTS flow control.
1111: */
1112: sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
1113: sc->sc_mcr_rts = 0;
1114: sc->sc_msr_cts = 0;
1.116 fvdl 1115: sc->sc_efr = 0;
1.99 mycroft 1116: if (ISSET(sc->sc_mcr, MCR_DTR))
1117: SET(sc->sc_mcr, MCR_RTS);
1118: else
1119: CLR(sc->sc_mcr, MCR_RTS);
1120: }
1121: sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
1122:
1.95 mycroft 1123: #if 0
1.99 mycroft 1124: if (ospeed == 0)
1125: CLR(sc->sc_mcr, sc->sc_mcr_dtr);
1126: else
1127: SET(sc->sc_mcr, sc->sc_mcr_dtr);
1.66 mycroft 1128: #endif
1129:
1.99 mycroft 1130: sc->sc_dlbl = ospeed;
1131: sc->sc_dlbh = ospeed >> 8;
1.66 mycroft 1132:
1.99 mycroft 1133: /*
1134: * Set the FIFO threshold based on the receive speed.
1135: *
1136: * * If it's a low speed, it's probably a mouse or some other
1137: * interactive device, so set the threshold low.
1138: * * If it's a high speed, trim the trigger level down to prevent
1139: * overflows.
1140: * * Otherwise set it a bit higher.
1141: */
1142: if (ISSET(sc->sc_hwflags, COM_HW_HAYESP))
1143: sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8;
1144: else if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
1145: sc->sc_fifo = FIFO_ENABLE |
1146: (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 :
1147: t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4);
1148: else
1149: sc->sc_fifo = 0;
1.21 mycroft 1150:
1.127 mycroft 1151: /* And copy to tty. */
1.99 mycroft 1152: tp->t_ispeed = 0;
1.57 mycroft 1153: tp->t_ospeed = t->c_ospeed;
1154: tp->t_cflag = t->c_cflag;
1.25 cgd 1155:
1.99 mycroft 1156: if (!sc->sc_heldchange) {
1157: if (sc->sc_tx_busy) {
1158: sc->sc_heldtbc = sc->sc_tbc;
1159: sc->sc_tbc = 0;
1160: sc->sc_heldchange = 1;
1161: } else
1162: com_loadchannelregs(sc);
1163: }
1164:
1.124 mycroft 1165: if (!ISSET(t->c_cflag, CHWFLOW)) {
1.125 mycroft 1166: /* Disable the high water mark. */
1167: sc->sc_r_hiwat = 0;
1168: sc->sc_r_lowat = 0;
1.124 mycroft 1169: if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
1170: CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1171: com_schedrx(sc);
1172: }
1173: if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
1174: CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
1175: com_hwiflow(sc);
1176: }
1.125 mycroft 1177: } else {
1.127 mycroft 1178: sc->sc_r_hiwat = com_rbuf_hiwat;
1179: sc->sc_r_lowat = com_rbuf_lowat;
1.124 mycroft 1180: }
1181:
1.99 mycroft 1182: splx(s);
1183:
1.25 cgd 1184: /*
1.99 mycroft 1185: * Update the tty layer's idea of the carrier bit, in case we changed
1.124 mycroft 1186: * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1187: * explicit request.
1.25 cgd 1188: */
1.99 mycroft 1189: (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD));
1190:
1191: #ifdef COM_DEBUG
1.101 mycroft 1192: if (com_debug)
1193: comstatus(sc, "comparam ");
1.99 mycroft 1194: #endif
1195:
1196: if (!ISSET(t->c_cflag, CHWFLOW)) {
1197: if (sc->sc_tx_stopped) {
1198: sc->sc_tx_stopped = 0;
1199: comstart(tp);
1200: }
1.21 mycroft 1201: }
1.1 cgd 1202:
1.99 mycroft 1203: return (0);
1204: }
1205:
1206: void
1207: com_iflush(sc)
1208: struct com_softc *sc;
1209: {
1210: bus_space_tag_t iot = sc->sc_iot;
1211: bus_space_handle_t ioh = sc->sc_ioh;
1.131 marc 1212: #ifdef DIAGNOSTIC
1213: int reg;
1214: #endif
1215: int timo;
1.99 mycroft 1216:
1.131 marc 1217: #ifdef DIAGNOSTIC
1218: reg = 0xffff;
1219: #endif
1220: timo = 50000;
1.99 mycroft 1221: /* flush any pending I/O */
1.131 marc 1222: while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)
1223: && --timo)
1224: #ifdef DIAGNOSTIC
1225: reg =
1226: #else
1227: (void)
1228: #endif
1229: bus_space_read_1(iot, ioh, com_data);
1230: #ifdef DIAGNOSTIC
1231: if (!timo)
1232: printf("%s: com_iflush timeout %02x\n", sc->sc_dev.dv_xname,
1233: reg);
1234: #endif
1.99 mycroft 1235: }
1236:
1237: void
1238: com_loadchannelregs(sc)
1239: struct com_softc *sc;
1240: {
1241: bus_space_tag_t iot = sc->sc_iot;
1242: bus_space_handle_t ioh = sc->sc_ioh;
1243:
1244: /* XXXXX necessary? */
1245: com_iflush(sc);
1246:
1247: bus_space_write_1(iot, ioh, com_ier, 0);
1248:
1.116 fvdl 1249: if (ISSET(sc->sc_hwflags, COM_HW_FLOW)) {
1250: bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
1251: bus_space_write_1(iot, ioh, com_efr, sc->sc_efr);
1252: }
1.99 mycroft 1253: bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB);
1254: bus_space_write_1(iot, ioh, com_dlbl, sc->sc_dlbl);
1255: bus_space_write_1(iot, ioh, com_dlbh, sc->sc_dlbh);
1256: bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
1257: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active = sc->sc_mcr);
1258: bus_space_write_1(iot, ioh, com_fifo, sc->sc_fifo);
1259:
1260: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1261: }
1262:
1263: int
1264: comhwiflow(tp, block)
1265: struct tty *tp;
1266: int block;
1267: {
1268: struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1269: int s;
1270:
1271: if (sc->sc_mcr_rts == 0)
1272: return (0);
1273:
1274: s = splserial();
1275: if (block) {
1.101 mycroft 1276: if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1277: SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
1278: com_hwiflow(sc);
1279: }
1.99 mycroft 1280: } else {
1.101 mycroft 1281: if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
1282: CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1283: com_schedrx(sc);
1284: }
1285: if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1286: CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
1287: com_hwiflow(sc);
1288: }
1.99 mycroft 1289: }
1.21 mycroft 1290: splx(s);
1.99 mycroft 1291: return (1);
1292: }
1293:
1294: /*
1295: * (un)block input via hw flowcontrol
1296: */
1297: void
1.101 mycroft 1298: com_hwiflow(sc)
1.99 mycroft 1299: struct com_softc *sc;
1300: {
1301: bus_space_tag_t iot = sc->sc_iot;
1302: bus_space_handle_t ioh = sc->sc_ioh;
1303:
1304: if (sc->sc_mcr_rts == 0)
1305: return;
1306:
1.101 mycroft 1307: if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
1.99 mycroft 1308: CLR(sc->sc_mcr, sc->sc_mcr_rts);
1309: CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
1310: } else {
1311: SET(sc->sc_mcr, sc->sc_mcr_rts);
1312: SET(sc->sc_mcr_active, sc->sc_mcr_rts);
1313: }
1314: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
1.1 cgd 1315: }
1.21 mycroft 1316:
1.99 mycroft 1317:
1.12 deraadt 1318: void
1.1 cgd 1319: comstart(tp)
1.21 mycroft 1320: struct tty *tp;
1.1 cgd 1321: {
1.76 thorpej 1322: struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1.91 thorpej 1323: bus_space_tag_t iot = sc->sc_iot;
1324: bus_space_handle_t ioh = sc->sc_ioh;
1.21 mycroft 1325: int s;
1326:
1.1 cgd 1327: s = spltty();
1.127 mycroft 1328: if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1.70 mycroft 1329: goto out;
1.99 mycroft 1330: if (sc->sc_tx_stopped)
1.127 mycroft 1331: goto out;
1.99 mycroft 1332:
1.61 mycroft 1333: if (tp->t_outq.c_cc <= tp->t_lowat) {
1.62 mycroft 1334: if (ISSET(tp->t_state, TS_ASLEEP)) {
1335: CLR(tp->t_state, TS_ASLEEP);
1336: wakeup(&tp->t_outq);
1.61 mycroft 1337: }
1.99 mycroft 1338: selwakeup(&tp->t_wsel);
1.61 mycroft 1339: if (tp->t_outq.c_cc == 0)
1.127 mycroft 1340: goto out;
1.61 mycroft 1341: }
1.99 mycroft 1342:
1343: /* Grab the first contiguous region of buffer space. */
1344: {
1345: u_char *tba;
1346: int tbc;
1347:
1348: tba = tp->t_outq.c_cf;
1349: tbc = ndqb(&tp->t_outq, 0);
1350:
1351: (void)splserial();
1352:
1353: sc->sc_tba = tba;
1354: sc->sc_tbc = tbc;
1355: }
1356:
1.62 mycroft 1357: SET(tp->t_state, TS_BUSY);
1.99 mycroft 1358: sc->sc_tx_busy = 1;
1.64 christos 1359:
1.99 mycroft 1360: /* Enable transmit completion interrupts if necessary. */
1.70 mycroft 1361: if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
1362: SET(sc->sc_ier, IER_ETXRDY);
1.91 thorpej 1363: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.70 mycroft 1364: }
1.99 mycroft 1365:
1366: /* Output the first chunk of the contiguous buffer. */
1367: {
1368: int n;
1369:
1.127 mycroft 1370: n = sc->sc_tbc;
1371: if (n > sc->sc_fifolen)
1372: n = sc->sc_fifolen;
1.99 mycroft 1373: bus_space_write_multi_1(iot, ioh, com_data, sc->sc_tba, n);
1374: sc->sc_tbc -= n;
1375: sc->sc_tba += n;
1.64 christos 1376: }
1.99 mycroft 1377: out:
1.1 cgd 1378: splx(s);
1.99 mycroft 1379: return;
1.1 cgd 1380: }
1.21 mycroft 1381:
1.1 cgd 1382: /*
1383: * Stop output on a line.
1384: */
1.85 mycroft 1385: void
1.1 cgd 1386: comstop(tp, flag)
1.21 mycroft 1387: struct tty *tp;
1.80 christos 1388: int flag;
1.1 cgd 1389: {
1.99 mycroft 1390: struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1.21 mycroft 1391: int s;
1.1 cgd 1392:
1.99 mycroft 1393: s = splserial();
1394: if (ISSET(tp->t_state, TS_BUSY)) {
1395: /* Stop transmitting at the next chunk. */
1396: sc->sc_tbc = 0;
1397: sc->sc_heldtbc = 0;
1.62 mycroft 1398: if (!ISSET(tp->t_state, TS_TTSTOP))
1399: SET(tp->t_state, TS_FLUSH);
1.99 mycroft 1400: }
1.1 cgd 1401: splx(s);
1402: }
1403:
1.33 mycroft 1404: void
1405: comdiag(arg)
1406: void *arg;
1407: {
1408: struct com_softc *sc = arg;
1.99 mycroft 1409: int overflows, floods;
1.33 mycroft 1410: int s;
1411:
1.99 mycroft 1412: s = splserial();
1.33 mycroft 1413: overflows = sc->sc_overflows;
1414: sc->sc_overflows = 0;
1.57 mycroft 1415: floods = sc->sc_floods;
1416: sc->sc_floods = 0;
1.99 mycroft 1417: sc->sc_errors = 0;
1.57 mycroft 1418: splx(s);
1419:
1.127 mycroft 1420: log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
1.57 mycroft 1421: sc->sc_dev.dv_xname,
1422: overflows, overflows == 1 ? "" : "s",
1.99 mycroft 1423: floods, floods == 1 ? "" : "s");
1.57 mycroft 1424: }
1425:
1.99 mycroft 1426: integrate void
1.127 mycroft 1427: com_rxsoft(sc, tp)
1428: struct com_softc *sc;
1429: struct tty *tp;
1.99 mycroft 1430: {
1.127 mycroft 1431: int (*rint) __P((int c, struct tty *tp)) = linesw[tp->t_line].l_rint;
1432: u_char *get, *end;
1433: u_int cc, scc;
1434: u_char lsr;
1435: int code;
1436: int s;
1.57 mycroft 1437:
1.127 mycroft 1438: end = sc->sc_ebuf;
1.99 mycroft 1439: get = sc->sc_rbget;
1.127 mycroft 1440: scc = cc = com_rbuf_size - sc->sc_rbavail;
1.99 mycroft 1441:
1.127 mycroft 1442: if (cc == com_rbuf_size) {
1.99 mycroft 1443: sc->sc_floods++;
1444: if (sc->sc_errors++ == 0)
1445: timeout(comdiag, sc, 60 * hz);
1446: }
1447:
1.101 mycroft 1448: while (cc) {
1.128 mycroft 1449: code = get[0];
1.127 mycroft 1450: lsr = get[1];
1.128 mycroft 1451: if (ISSET(lsr, LSR_OE | LSR_BI | LSR_FE | LSR_PE)) {
1452: if (ISSET(lsr, LSR_OE)) {
1453: sc->sc_overflows++;
1454: if (sc->sc_errors++ == 0)
1455: timeout(comdiag, sc, 60 * hz);
1456: }
1.127 mycroft 1457: if (ISSET(lsr, LSR_BI | LSR_FE))
1458: SET(code, TTY_FE);
1459: if (ISSET(lsr, LSR_PE))
1460: SET(code, TTY_PE);
1461: }
1462: if ((*rint)(code, tp) == -1) {
1.101 mycroft 1463: /*
1464: * The line discipline's buffer is out of space.
1465: */
1466: if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
1467: /*
1468: * We're either not using flow control, or the
1469: * line discipline didn't tell us to block for
1470: * some reason. Either way, we have no way to
1471: * know when there's more space available, so
1472: * just drop the rest of the data.
1473: */
1.127 mycroft 1474: get += cc << 1;
1475: if (get >= end)
1476: get -= com_rbuf_size << 1;
1.101 mycroft 1477: cc = 0;
1478: } else {
1479: /*
1480: * Don't schedule any more receive processing
1481: * until the line discipline tells us there's
1482: * space available (through comhwiflow()).
1483: * Leave the rest of the data in the input
1484: * buffer.
1485: */
1486: SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
1487: }
1488: break;
1489: }
1.127 mycroft 1490: get += 2;
1491: if (get >= end)
1492: get = sc->sc_rbuf;
1.101 mycroft 1493: cc--;
1.99 mycroft 1494: }
1495:
1.101 mycroft 1496: if (cc != scc) {
1497: sc->sc_rbget = get;
1498: s = splserial();
1499: cc = sc->sc_rbavail += scc - cc;
1500: /* Buffers should be ok again, release possible block. */
1501: if (cc >= sc->sc_r_lowat) {
1502: if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1503: CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1504: SET(sc->sc_ier, IER_ERXRDY);
1505: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
1506: }
1507: if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
1508: CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1509: com_hwiflow(sc);
1510: }
1511: }
1512: splx(s);
1.57 mycroft 1513: }
1.99 mycroft 1514: }
1515:
1516: integrate void
1.127 mycroft 1517: com_txsoft(sc, tp)
1518: struct com_softc *sc;
1519: struct tty *tp;
1.99 mycroft 1520: {
1.33 mycroft 1521:
1.99 mycroft 1522: CLR(tp->t_state, TS_BUSY);
1523: if (ISSET(tp->t_state, TS_FLUSH))
1524: CLR(tp->t_state, TS_FLUSH);
1525: else
1526: ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
1527: (*linesw[tp->t_line].l_start)(tp);
1528: }
1.57 mycroft 1529:
1.99 mycroft 1530: integrate void
1.127 mycroft 1531: com_stsoft(sc, tp)
1532: struct com_softc *sc;
1533: struct tty *tp;
1.99 mycroft 1534: {
1535: u_char msr, delta;
1536: int s;
1.57 mycroft 1537:
1.99 mycroft 1538: s = splserial();
1539: msr = sc->sc_msr;
1540: delta = sc->sc_msr_delta;
1541: sc->sc_msr_delta = 0;
1542: splx(s);
1.57 mycroft 1543:
1.99 mycroft 1544: if (ISSET(delta, sc->sc_msr_dcd)) {
1545: /*
1546: * Inform the tty layer that carrier detect changed.
1547: */
1548: (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD));
1549: }
1.61 mycroft 1550:
1.99 mycroft 1551: if (ISSET(delta, sc->sc_msr_cts)) {
1552: /* Block or unblock output according to flow control. */
1553: if (ISSET(msr, sc->sc_msr_cts)) {
1554: sc->sc_tx_stopped = 0;
1555: (*linesw[tp->t_line].l_start)(tp);
1556: } else {
1557: sc->sc_tx_stopped = 1;
1.61 mycroft 1558: }
1.99 mycroft 1559: }
1560:
1561: #ifdef COM_DEBUG
1.101 mycroft 1562: if (com_debug)
1.127 mycroft 1563: comstatus(sc, "com_stsoft");
1.99 mycroft 1564: #endif
1565: }
1566:
1567: #ifdef __GENERIC_SOFT_INTERRUPTS
1568: void
1569: comsoft(arg)
1570: void *arg;
1571: {
1572: struct com_softc *sc = arg;
1573: struct tty *tp;
1574:
1.131 marc 1575: if (!sc->enabled)
1576: return;
1577:
1.99 mycroft 1578: {
1579: #else
1580: void
1.133 cgd 1581: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.99 mycroft 1582: comsoft()
1583: #else
1584: comsoft(arg)
1585: void *arg;
1586: #endif
1587: {
1588: struct com_softc *sc;
1589: struct tty *tp;
1590: int unit;
1.133 cgd 1591: #ifdef __NO_SOFT_SERIAL_INTERRUPT
1.99 mycroft 1592: int s;
1593:
1594: s = splsoftserial();
1595: com_softintr_scheduled = 0;
1596: #endif
1.57 mycroft 1597:
1.99 mycroft 1598: for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
1599: sc = com_cd.cd_devs[unit];
1.132 cgd 1600: if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK))
1.99 mycroft 1601: continue;
1.57 mycroft 1602:
1.131 marc 1603: if (!sc->enabled)
1604: continue;
1605:
1.99 mycroft 1606: tp = sc->sc_tty;
1607: if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN))
1.57 mycroft 1608: continue;
1.108 is 1609: #endif
1610: tp = sc->sc_tty;
1.99 mycroft 1611:
1612: if (sc->sc_rx_ready) {
1613: sc->sc_rx_ready = 0;
1.127 mycroft 1614: com_rxsoft(sc, tp);
1.57 mycroft 1615: }
1616:
1.99 mycroft 1617: if (sc->sc_st_check) {
1618: sc->sc_st_check = 0;
1.127 mycroft 1619: com_stsoft(sc, tp);
1.62 mycroft 1620: }
1.57 mycroft 1621:
1.99 mycroft 1622: if (sc->sc_tx_done) {
1623: sc->sc_tx_done = 0;
1.127 mycroft 1624: com_txsoft(sc, tp);
1.57 mycroft 1625: }
1626: }
1627:
1.99 mycroft 1628: #ifndef __GENERIC_SOFT_INTERRUPTS
1.133 cgd 1629: #ifdef __NO_SOFT_SERIAL_INTERRUPT
1.99 mycroft 1630: splx(s);
1631: #endif
1632: #endif
1.21 mycroft 1633: }
1.1 cgd 1634:
1.21 mycroft 1635: int
1.49 cgd 1636: comintr(arg)
1.127 mycroft 1637: void *arg;
1.21 mycroft 1638: {
1.49 cgd 1639: struct com_softc *sc = arg;
1.91 thorpej 1640: bus_space_tag_t iot = sc->sc_iot;
1641: bus_space_handle_t ioh = sc->sc_ioh;
1.127 mycroft 1642: u_char *put, *end;
1643: u_int cc;
1644: u_char lsr, iir;
1.55 mycroft 1645:
1.131 marc 1646: if (!sc->enabled)
1647: return (0);
1648:
1.91 thorpej 1649: iir = bus_space_read_1(iot, ioh, com_iir);
1.88 mycroft 1650: if (ISSET(iir, IIR_NOPEND))
1.55 mycroft 1651: return (0);
1.21 mycroft 1652:
1.127 mycroft 1653: end = sc->sc_ebuf;
1.99 mycroft 1654: put = sc->sc_rbput;
1655: cc = sc->sc_rbavail;
1656:
1657: do {
1658: u_char msr, delta;
1.21 mycroft 1659:
1.91 thorpej 1660: lsr = bus_space_read_1(iot, ioh, com_lsr);
1.103 drochner 1661: #if defined(DDB) || defined(KGDB)
1662: if (ISSET(lsr, LSR_BI)) {
1663: #ifdef DDB
1664: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1665: Debugger();
1666: continue;
1667: }
1668: #endif
1669: #ifdef KGDB
1670: if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) {
1671: kgdb_connect(1);
1672: continue;
1673: }
1674: #endif
1.102 thorpej 1675: }
1.103 drochner 1676: #endif /* DDB || KGDB */
1.102 thorpej 1677:
1.101 mycroft 1678: if (ISSET(lsr, LSR_RCV_MASK) &&
1679: !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1.127 mycroft 1680: while (cc > 0) {
1681: put[0] = bus_space_read_1(iot, ioh, com_data);
1682: put[1] = lsr;
1683: put += 2;
1684: if (put >= end)
1685: put = sc->sc_rbuf;
1686: cc--;
1687:
1.99 mycroft 1688: lsr = bus_space_read_1(iot, ioh, com_lsr);
1.127 mycroft 1689: if (!ISSET(lsr, LSR_RCV_MASK))
1690: break;
1.99 mycroft 1691: }
1.127 mycroft 1692:
1.99 mycroft 1693: /*
1694: * Current string of incoming characters ended because
1.127 mycroft 1695: * no more data was available or we ran out of space.
1696: * Schedule a receive event if any data was received.
1697: * If we're out of space, turn off receive interrupts.
1.99 mycroft 1698: */
1699: sc->sc_rbput = put;
1700: sc->sc_rbavail = cc;
1.101 mycroft 1701: if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
1702: sc->sc_rx_ready = 1;
1.127 mycroft 1703:
1.99 mycroft 1704: /*
1705: * See if we are in danger of overflowing a buffer. If
1706: * so, use hardware flow control to ease the pressure.
1707: */
1.101 mycroft 1708: if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
1.99 mycroft 1709: cc < sc->sc_r_hiwat) {
1.101 mycroft 1710: SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
1711: com_hwiflow(sc);
1.99 mycroft 1712: }
1.127 mycroft 1713:
1.99 mycroft 1714: /*
1.101 mycroft 1715: * If we're out of space, disable receive interrupts
1716: * until the queue has drained a bit.
1.99 mycroft 1717: */
1718: if (!cc) {
1.101 mycroft 1719: SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1720: CLR(sc->sc_ier, IER_ERXRDY);
1721: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.99 mycroft 1722: }
1.88 mycroft 1723: } else {
1724: if ((iir & IIR_IMASK) == IIR_RXRDY) {
1.91 thorpej 1725: bus_space_write_1(iot, ioh, com_ier, 0);
1.88 mycroft 1726: delay(10);
1.99 mycroft 1727: bus_space_write_1(iot, ioh, com_ier,sc->sc_ier);
1.88 mycroft 1728: iir = IIR_NOPEND;
1729: continue;
1730: }
1731: }
1.55 mycroft 1732:
1.99 mycroft 1733: msr = bus_space_read_1(iot, ioh, com_msr);
1734: delta = msr ^ sc->sc_msr;
1735: sc->sc_msr = msr;
1736: if (ISSET(delta, sc->sc_msr_mask)) {
1.127 mycroft 1737: SET(sc->sc_msr_delta, delta);
1.99 mycroft 1738:
1739: /*
1740: * Stop output immediately if we lose the output
1741: * flow control signal or carrier detect.
1742: */
1743: if (ISSET(~msr, sc->sc_msr_mask)) {
1744: sc->sc_tbc = 0;
1745: sc->sc_heldtbc = 0;
1.69 mycroft 1746: #ifdef COM_DEBUG
1.101 mycroft 1747: if (com_debug)
1748: comstatus(sc, "comintr ");
1.69 mycroft 1749: #endif
1.99 mycroft 1750: }
1.55 mycroft 1751:
1.99 mycroft 1752: sc->sc_st_check = 1;
1.55 mycroft 1753: }
1.99 mycroft 1754: } while (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND));
1.55 mycroft 1755:
1.99 mycroft 1756: /*
1757: * Done handling any receive interrupts. See if data can be
1758: * transmitted as well. Schedule tx done event if no data left
1759: * and tty was marked busy.
1760: */
1761: if (ISSET(lsr, LSR_TXRDY)) {
1762: /*
1763: * If we've delayed a parameter change, do it now, and restart
1764: * output.
1765: */
1766: if (sc->sc_heldchange) {
1767: com_loadchannelregs(sc);
1768: sc->sc_heldchange = 0;
1769: sc->sc_tbc = sc->sc_heldtbc;
1770: sc->sc_heldtbc = 0;
1771: }
1.127 mycroft 1772:
1.99 mycroft 1773: /* Output the next chunk of the contiguous buffer, if any. */
1774: if (sc->sc_tbc > 0) {
1775: int n;
1776:
1.127 mycroft 1777: n = sc->sc_tbc;
1778: if (n > sc->sc_fifolen)
1779: n = sc->sc_fifolen;
1.99 mycroft 1780: bus_space_write_multi_1(iot, ioh, com_data, sc->sc_tba, n);
1781: sc->sc_tbc -= n;
1782: sc->sc_tba += n;
1.127 mycroft 1783: } else {
1784: /* Disable transmit completion interrupts if necessary. */
1785: if (ISSET(sc->sc_ier, IER_ETXRDY)) {
1786: CLR(sc->sc_ier, IER_ETXRDY);
1787: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1788: }
1789: if (sc->sc_tx_busy) {
1790: sc->sc_tx_busy = 0;
1791: sc->sc_tx_done = 1;
1792: }
1.62 mycroft 1793: }
1.99 mycroft 1794: }
1.62 mycroft 1795:
1.99 mycroft 1796: /* Wake up the poller. */
1797: #ifdef __GENERIC_SOFT_INTERRUPTS
1798: softintr_schedule(sc->sc_si);
1799: #else
1.133 cgd 1800: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.99 mycroft 1801: setsoftserial();
1802: #else
1803: if (!com_softintr_scheduled) {
1804: com_softintr_scheduled = 1;
1805: timeout(comsoft, NULL, 1);
1.1 cgd 1806: }
1.99 mycroft 1807: #endif
1808: #endif
1.115 explorer 1809:
1810: #if NRND > 0 && defined(RND_COM)
1811: rnd_add_uint32(&sc->rnd_source, iir | lsr);
1812: #endif
1813:
1.88 mycroft 1814: return (1);
1.1 cgd 1815: }
1816:
1817: /*
1.102 thorpej 1818: * The following functions are polled getc and putc routines, shared
1819: * by the console and kgdb glue.
1820: */
1821:
1822: int
1823: com_common_getc(iot, ioh)
1824: bus_space_tag_t iot;
1825: bus_space_handle_t ioh;
1826: {
1827: int s = splserial();
1828: u_char stat, c;
1829:
1.135 thorpej 1830: /* block until a character becomes available */
1831: while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
1.102 thorpej 1832: ;
1.135 thorpej 1833:
1.102 thorpej 1834: c = bus_space_read_1(iot, ioh, com_data);
1835: stat = bus_space_read_1(iot, ioh, com_iir);
1836: splx(s);
1837: return (c);
1838: }
1839:
1840: void
1841: com_common_putc(iot, ioh, c)
1842: bus_space_tag_t iot;
1843: bus_space_handle_t ioh;
1844: int c;
1845: {
1846: int s = splserial();
1847: u_char stat;
1.127 mycroft 1848: int timo;
1.102 thorpej 1849:
1850: /* wait for any pending transmission to finish */
1851: timo = 50000;
1852: while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY)
1853: && --timo)
1854: ;
1.135 thorpej 1855:
1.102 thorpej 1856: bus_space_write_1(iot, ioh, com_data, c);
1857: /* wait for this transmission to complete */
1858: timo = 1500000;
1859: while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY)
1860: && --timo)
1861: ;
1.135 thorpej 1862:
1.102 thorpej 1863: /* clear any interrupts generated by this transmission */
1864: stat = bus_space_read_1(iot, ioh, com_iir);
1865: splx(s);
1866: }
1867:
1868: /*
1.99 mycroft 1869: * Initialize UART to known state.
1870: */
1.106 drochner 1871: int
1.109 is 1872: cominit(iot, iobase, rate, frequency, cflag, iohp)
1.91 thorpej 1873: bus_space_tag_t iot;
1.106 drochner 1874: int iobase;
1.109 is 1875: int rate, frequency;
1.106 drochner 1876: tcflag_t cflag;
1877: bus_space_handle_t *iohp;
1.1 cgd 1878: {
1.106 drochner 1879: bus_space_handle_t ioh;
1880:
1881: if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
1.110 enami 1882: return (ENOMEM); /* ??? */
1.1 cgd 1883:
1.116 fvdl 1884: bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
1885: bus_space_write_1(iot, ioh, com_efr, 0);
1.91 thorpej 1886: bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
1.109 is 1887: rate = comspeed(rate, frequency);
1.91 thorpej 1888: bus_space_write_1(iot, ioh, com_dlbl, rate);
1889: bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
1.106 drochner 1890: bus_space_write_1(iot, ioh, com_lcr, cflag2lcr(cflag));
1.99 mycroft 1891: bus_space_write_1(iot, ioh, com_mcr, 0);
1.91 thorpej 1892: bus_space_write_1(iot, ioh, com_fifo,
1.87 mycroft 1893: FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
1.99 mycroft 1894: bus_space_write_1(iot, ioh, com_ier, 0);
1.106 drochner 1895:
1896: *iohp = ioh;
1.110 enami 1897: return (0);
1.99 mycroft 1898: }
1899:
1900: /*
1.106 drochner 1901: * Following are all routines needed for COM to act as console
1.99 mycroft 1902: */
1.106 drochner 1903:
1904: int
1.109 is 1905: comcnattach(iot, iobase, rate, frequency, cflag)
1.99 mycroft 1906: bus_space_tag_t iot;
1.106 drochner 1907: int iobase;
1.109 is 1908: int rate, frequency;
1.106 drochner 1909: tcflag_t cflag;
1.99 mycroft 1910: {
1.106 drochner 1911: int res;
1.120 mycroft 1912: static struct consdev comcons = {
1913: NULL, NULL, comcngetc, comcnputc, comcnpollc, NODEV, CN_NORMAL
1914: };
1.106 drochner 1915:
1.109 is 1916: res = cominit(iot, iobase, rate, frequency, cflag, &comconsioh);
1.110 enami 1917: if (res)
1918: return (res);
1.106 drochner 1919:
1920: cn_tab = &comcons;
1921:
1922: comconstag = iot;
1923: comconsaddr = iobase;
1924: comconsrate = rate;
1925: comconscflag = cflag;
1.99 mycroft 1926:
1.110 enami 1927: return (0);
1.1 cgd 1928: }
1929:
1.80 christos 1930: int
1.1 cgd 1931: comcngetc(dev)
1.21 mycroft 1932: dev_t dev;
1.1 cgd 1933: {
1934:
1.102 thorpej 1935: return (com_common_getc(comconstag, comconsioh));
1.1 cgd 1936: }
1937:
1938: /*
1939: * Console kernel output character routine.
1940: */
1.48 mycroft 1941: void
1.1 cgd 1942: comcnputc(dev, c)
1943: dev_t dev;
1.21 mycroft 1944: int c;
1.1 cgd 1945: {
1946:
1.102 thorpej 1947: com_common_putc(comconstag, comconsioh, c);
1.37 mycroft 1948: }
1949:
1950: void
1951: comcnpollc(dev, on)
1952: dev_t dev;
1953: int on;
1954: {
1955:
1.106 drochner 1956: }
1957:
1958: #ifdef KGDB
1959: int
1.109 is 1960: com_kgdb_attach(iot, iobase, rate, frequency, cflag)
1.106 drochner 1961: bus_space_tag_t iot;
1962: int iobase;
1.112 mikel 1963: int rate, frequency;
1.106 drochner 1964: tcflag_t cflag;
1965: {
1966: int res;
1.107 drochner 1967:
1968: if (iot == comconstag && iobase == comconsaddr)
1.110 enami 1969: return (EBUSY); /* cannot share with console */
1.106 drochner 1970:
1.109 is 1971: res = cominit(iot, iobase, rate, frequency, cflag, &com_kgdb_ioh);
1.110 enami 1972: if (res)
1973: return (res);
1.106 drochner 1974:
1975: kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
1976: kgdb_dev = 123; /* unneeded, only to satisfy some tests */
1977:
1978: com_kgdb_iot = iot;
1979: com_kgdb_addr = iobase;
1980:
1.110 enami 1981: return (0);
1.106 drochner 1982: }
1983:
1984: /* ARGSUSED */
1985: int
1986: com_kgdb_getc(arg)
1987: void *arg;
1988: {
1989:
1990: return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));
1991: }
1992:
1993: /* ARGSUSED */
1994: void
1995: com_kgdb_putc(arg, c)
1996: void *arg;
1997: int c;
1998: {
1999:
2000: return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
2001: }
2002: #endif /* KGDB */
2003:
2004: /* helper function to identify the com ports used by
2005: console or KGDB (and not yet autoconf attached) */
2006: int
2007: com_is_console(iot, iobase, ioh)
1.110 enami 2008: bus_space_tag_t iot;
2009: int iobase;
2010: bus_space_handle_t *ioh;
1.106 drochner 2011: {
2012: bus_space_handle_t help;
2013:
1.110 enami 2014: if (!comconsattached &&
2015: iot == comconstag && iobase == comconsaddr)
1.106 drochner 2016: help = comconsioh;
2017: #ifdef KGDB
1.110 enami 2018: else if (!com_kgdb_attached &&
2019: iot == com_kgdb_iot && iobase == com_kgdb_addr)
1.106 drochner 2020: help = com_kgdb_ioh;
2021: #endif
2022: else
1.110 enami 2023: return (0);
1.106 drochner 2024:
1.110 enami 2025: if (ioh)
2026: *ioh = help;
2027: return (1);
1.2 cgd 2028: }
CVSweb <webmaster@jp.NetBSD.org>