Annotation of sys/dev/ic/com.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: com.c,v 1.117 2007/07/15 19:25:49 kettenis Exp $ */
2: /* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
3:
4: /*
5: * Copyright (c) 1997 - 1999, Jason Downs. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
17: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23: * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28: /*-
29: * Copyright (c) 1993, 1994, 1995, 1996
30: * Charles M. Hannum. All rights reserved.
31: * Copyright (c) 1991 The Regents of the University of California.
32: * All rights reserved.
33: *
34: * Redistribution and use in source and binary forms, with or without
35: * modification, are permitted provided that the following conditions
36: * are met:
37: * 1. Redistributions of source code must retain the above copyright
38: * notice, this list of conditions and the following disclaimer.
39: * 2. Redistributions in binary form must reproduce the above copyright
40: * notice, this list of conditions and the following disclaimer in the
41: * documentation and/or other materials provided with the distribution.
42: * 3. Neither the name of the University nor the names of its contributors
43: * may be used to endorse or promote products derived from this software
44: * without specific prior written permission.
45: *
46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56: * SUCH DAMAGE.
57: *
58: * @(#)com.c 7.5 (Berkeley) 5/16/91
59: */
60:
61: /*
62: * COM driver, based on HP dca driver
63: * uses National Semiconductor NS16450/NS16550AF UART
64: */
65: #include <sys/param.h>
66: #include <sys/systm.h>
67: #include <sys/ioctl.h>
68: #include <sys/selinfo.h>
69: #include <sys/tty.h>
70: #include <sys/proc.h>
71: #include <sys/user.h>
72: #include <sys/conf.h>
73: #include <sys/file.h>
74: #include <sys/uio.h>
75: #include <sys/kernel.h>
76: #include <sys/syslog.h>
77: #include <sys/device.h>
78: #include <sys/vnode.h>
79: #ifdef DDB
80: #include <ddb/db_var.h>
81: #endif
82:
83: #include <machine/bus.h>
84: #if defined(__sparc64__) || !defined(__sparc__)
85: #include <machine/intr.h>
86: #endif
87:
88: #if !defined(__sparc__) || defined(__sparc64__)
89: #define COM_CONSOLE
90: #include <dev/cons.h>
91: #endif
92:
93: #include <dev/ic/comreg.h>
94: #include <dev/ic/comvar.h>
95: #include <dev/ic/ns16550reg.h>
96: #define com_lcr com_cfcr
97:
98: #ifdef COM_PXA2X0
99: #define com_isr 8
100: #define ISR_SEND (ISR_RXPL | ISR_XMODE | ISR_XMITIR)
101: #define ISR_RECV (ISR_RXPL | ISR_XMODE | ISR_RCVEIR)
102: #endif
103:
104: #ifdef __zaurus__
105: #include <arch/zaurus/dev/zaurus_scoopvar.h>
106: #endif
107:
108: /* XXX: These belong elsewhere */
109: cdev_decl(com);
110:
111: static u_char tiocm_xxx2mcr(int);
112:
113: void compwroff(struct com_softc *);
114: void cominit(bus_space_tag_t, bus_space_handle_t, int, int);
115: int com_is_console(bus_space_tag_t, bus_addr_t);
116:
117: struct cfdriver com_cd = {
118: NULL, "com", DV_TTY
119: };
120:
121: int comdefaultrate = TTYDEF_SPEED;
122: #ifdef COM_PXA2X0
123: bus_addr_t comsiraddr;
124: #endif
125: #ifdef COM_CONSOLE
126: int comconsfreq;
127: int comconsinit;
128: bus_addr_t comconsaddr;
129: int comconsattached;
130: bus_space_tag_t comconsiot;
131: bus_space_handle_t comconsioh;
132: tcflag_t comconscflag = TTYDEF_CFLAG;
133: #endif
134:
135: int commajor;
136:
137: #ifdef KGDB
138: #include <sys/kgdb.h>
139:
140: bus_addr_t com_kgdb_addr;
141: bus_space_tag_t com_kgdb_iot;
142: bus_space_handle_t com_kgdb_ioh;
143:
144: int com_kgdb_getc(void *);
145: void com_kgdb_putc(void *, int);
146: #endif /* KGDB */
147:
148: #define DEVUNIT(x) (minor(x) & 0x7f)
149: #define DEVCUA(x) (minor(x) & 0x80)
150:
151: int
152: comspeed(long freq, long speed)
153: {
154: #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
155:
156: int x, err;
157:
158: if (speed == 0)
159: return 0;
160: if (speed < 0)
161: return -1;
162: x = divrnd((freq / 16), speed);
163: if (x <= 0)
164: return -1;
165: err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
166: if (err < 0)
167: err = -err;
168: if (err > COM_TOLERANCE)
169: return -1;
170: return x;
171:
172: #undef divrnd
173: }
174:
175: #ifdef COM_CONSOLE
176: int
177: comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
178: {
179: int i, k;
180:
181: /* force access to id reg */
182: bus_space_write_1(iot, ioh, com_lcr, 0);
183: bus_space_write_1(iot, ioh, com_iir, 0);
184: for (i = 0; i < 32; i++) {
185: k = bus_space_read_1(iot, ioh, com_iir);
186: if (k & 0x38) {
187: bus_space_read_1(iot, ioh, com_data); /* cleanup */
188: } else
189: break;
190: }
191: if (i >= 32)
192: return 0;
193:
194: return 1;
195: }
196: #endif
197:
198: int
199: com_detach(struct device *self, int flags)
200: {
201: struct com_softc *sc = (struct com_softc *)self;
202: int maj, mn;
203:
204: sc->sc_swflags |= COM_SW_DEAD;
205:
206: /* locate the major number */
207: for (maj = 0; maj < nchrdev; maj++)
208: if (cdevsw[maj].d_open == comopen)
209: break;
210:
211: /* Nuke the vnodes for any open instances. */
212: mn = self->dv_unit;
213: vdevgone(maj, mn, mn, VCHR);
214:
215: /* XXX a symbolic constant for the cua bit would be nicer. */
216: mn |= 0x80;
217: vdevgone(maj, mn, mn, VCHR);
218:
219: /* Detach and free the tty. */
220: if (sc->sc_tty) {
221: ttyfree(sc->sc_tty);
222: }
223:
224: timeout_del(&sc->sc_dtr_tmo);
225: timeout_del(&sc->sc_diag_tmo);
226: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
227: softintr_disestablish(sc->sc_si);
228: #else
229: timeout_del(&sc->sc_comsoft_tmo);
230: #endif
231:
232: return (0);
233: }
234:
235: int
236: com_activate(struct device *self, enum devact act)
237: {
238: struct com_softc *sc = (struct com_softc *)self;
239: int s, rv = 0;
240:
241: s = spltty();
242: switch (act) {
243: case DVACT_ACTIVATE:
244: break;
245:
246: case DVACT_DEACTIVATE:
247: #ifdef KGDB
248: if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
249: #else
250: if (sc->sc_hwflags & COM_HW_CONSOLE) {
251: #endif /* KGDB */
252: rv = EBUSY;
253: break;
254: }
255:
256: if (sc->disable != NULL && sc->enabled != 0) {
257: (*sc->disable)(sc);
258: sc->enabled = 0;
259: }
260: break;
261: }
262: splx(s);
263: return (rv);
264: }
265:
266: int
267: comopen(dev_t dev, int flag, int mode, struct proc *p)
268: {
269: int unit = DEVUNIT(dev);
270: struct com_softc *sc;
271: bus_space_tag_t iot;
272: bus_space_handle_t ioh;
273: struct tty *tp;
274: int s;
275: int error = 0;
276:
277: if (unit >= com_cd.cd_ndevs)
278: return ENXIO;
279: sc = com_cd.cd_devs[unit];
280: if (!sc)
281: return ENXIO;
282:
283: #ifdef KGDB
284: /*
285: * If this is the kgdb port, no other use is permitted.
286: */
287: if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
288: return (EBUSY);
289: #endif /* KGDB */
290:
291: s = spltty();
292: if (!sc->sc_tty) {
293: tp = sc->sc_tty = ttymalloc();
294: } else
295: tp = sc->sc_tty;
296: splx(s);
297:
298: tp->t_oproc = comstart;
299: tp->t_param = comparam;
300: tp->t_dev = dev;
301: if (!ISSET(tp->t_state, TS_ISOPEN)) {
302: SET(tp->t_state, TS_WOPEN);
303: ttychars(tp);
304: tp->t_iflag = TTYDEF_IFLAG;
305: tp->t_oflag = TTYDEF_OFLAG;
306: #ifdef COM_CONSOLE
307: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
308: tp->t_cflag = comconscflag;
309: else
310: #endif
311: tp->t_cflag = TTYDEF_CFLAG;
312: if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
313: SET(tp->t_cflag, CLOCAL);
314: if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
315: SET(tp->t_cflag, CRTSCTS);
316: if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
317: SET(tp->t_cflag, MDMBUF);
318: tp->t_lflag = TTYDEF_LFLAG;
319: tp->t_ispeed = tp->t_ospeed = comdefaultrate;
320:
321: s = spltty();
322:
323: sc->sc_initialize = 1;
324: comparam(tp, &tp->t_termios);
325: ttsetwater(tp);
326:
327: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
328: timeout_add(&sc->sc_comsoft_tmo, 1);
329: #endif
330:
331: sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
332: sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
333: sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
334:
335: iot = sc->sc_iot;
336: ioh = sc->sc_ioh;
337:
338: /*
339: * Wake up the sleepy heads.
340: */
341: switch (sc->sc_uarttype) {
342: case COM_UART_ST16650:
343: case COM_UART_ST16650V2:
344: bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
345: bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
346: bus_space_write_1(iot, ioh, com_ier, 0);
347: bus_space_write_1(iot, ioh, com_efr, 0);
348: bus_space_write_1(iot, ioh, com_lcr, 0);
349: break;
350: case COM_UART_TI16750:
351: bus_space_write_1(iot, ioh, com_ier, 0);
352: break;
353: case COM_UART_PXA2X0:
354: bus_space_write_1(iot, ioh, com_ier, IER_EUART);
355: break;
356: }
357:
358: if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
359: u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
360: u_int8_t lcr;
361:
362: if (tp->t_ispeed <= 1200)
363: fifo |= FIFO_TRIGGER_1;
364: else
365: fifo |= FIFO_TRIGGER_8;
366: if (sc->sc_uarttype == COM_UART_TI16750) {
367: fifo |= FIFO_ENABLE_64BYTE;
368: lcr = bus_space_read_1(iot, ioh, com_lcr);
369: bus_space_write_1(iot, ioh, com_lcr,
370: lcr | LCR_DLAB);
371: }
372:
373: /*
374: * (Re)enable and drain FIFOs.
375: *
376: * Certain SMC chips cause problems if the FIFOs are
377: * enabled while input is ready. Turn off the FIFO
378: * if necessary to clear the input. Test the input
379: * ready bit after enabling the FIFOs to handle races
380: * between enabling and fresh input.
381: *
382: * Set the FIFO threshold based on the receive speed.
383: */
384: for (;;) {
385: bus_space_write_1(iot, ioh, com_fifo, 0);
386: delay(100);
387: (void) bus_space_read_1(iot, ioh, com_data);
388: bus_space_write_1(iot, ioh, com_fifo, fifo |
389: FIFO_RCV_RST | FIFO_XMT_RST);
390: delay(100);
391: if(!ISSET(bus_space_read_1(iot, ioh,
392: com_lsr), LSR_RXRDY))
393: break;
394: }
395: if (sc->sc_uarttype == COM_UART_TI16750)
396: bus_space_write_1(iot, ioh, com_lcr, lcr);
397: }
398:
399: /* flush any pending I/O */
400: while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
401: (void) bus_space_read_1(iot, ioh, com_data);
402: /* you turn me on, baby */
403: sc->sc_mcr = MCR_DTR | MCR_RTS;
404: if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
405: SET(sc->sc_mcr, MCR_IENABLE);
406: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
407: sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
408: #ifdef COM_PXA2X0
409: if (sc->sc_uarttype == COM_UART_PXA2X0)
410: sc->sc_ier |= IER_EUART | IER_ERXTOUT;
411: #endif
412: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
413:
414: sc->sc_msr = bus_space_read_1(iot, ioh, com_msr);
415: if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
416: ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
417: SET(tp->t_state, TS_CARR_ON);
418: else
419: CLR(tp->t_state, TS_CARR_ON);
420: #ifdef COM_PXA2X0
421: if (sc->sc_uarttype == COM_UART_PXA2X0 &&
422: ISSET(sc->sc_hwflags, COM_HW_SIR)) {
423: bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
424: #ifdef __zaurus__
425: scoop_set_irled(1);
426: #endif
427: }
428: #endif
429: } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
430: return EBUSY;
431: else
432: s = spltty();
433:
434: if (DEVCUA(dev)) {
435: if (ISSET(tp->t_state, TS_ISOPEN)) {
436: /* Ah, but someone already is dialed in... */
437: splx(s);
438: return EBUSY;
439: }
440: sc->sc_cua = 1; /* We go into CUA mode */
441: } else {
442: /* tty (not cua) device; wait for carrier if necessary */
443: if (ISSET(flag, O_NONBLOCK)) {
444: if (sc->sc_cua) {
445: /* Opening TTY non-blocking... but the CUA is busy */
446: splx(s);
447: return EBUSY;
448: }
449: } else {
450: while (sc->sc_cua ||
451: (!ISSET(tp->t_cflag, CLOCAL) &&
452: !ISSET(tp->t_state, TS_CARR_ON))) {
453: SET(tp->t_state, TS_WOPEN);
454: error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0);
455: /*
456: * If TS_WOPEN has been reset, that means the cua device
457: * has been closed. We don't want to fail in that case,
458: * so just go around again.
459: */
460: if (error && ISSET(tp->t_state, TS_WOPEN)) {
461: CLR(tp->t_state, TS_WOPEN);
462: if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN))
463: compwroff(sc);
464: splx(s);
465: return error;
466: }
467: }
468: }
469: }
470: splx(s);
471:
472: return (*linesw[tp->t_line].l_open)(dev, tp);
473: }
474:
475: int
476: comclose(dev_t dev, int flag, int mode, struct proc *p)
477: {
478: int unit = DEVUNIT(dev);
479: struct com_softc *sc = com_cd.cd_devs[unit];
480: bus_space_tag_t iot = sc->sc_iot;
481: bus_space_handle_t ioh = sc->sc_ioh;
482: struct tty *tp = sc->sc_tty;
483: int s;
484:
485: #ifdef COM_CONSOLE
486: /* XXX This is for cons.c. */
487: if (!ISSET(tp->t_state, TS_ISOPEN))
488: return 0;
489: #endif
490:
491: if(sc->sc_swflags & COM_SW_DEAD)
492: return 0;
493:
494: (*linesw[tp->t_line].l_close)(tp, flag);
495: s = spltty();
496: if (ISSET(tp->t_state, TS_WOPEN)) {
497: /* tty device is waiting for carrier; drop dtr then re-raise */
498: CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
499: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
500: timeout_add(&sc->sc_dtr_tmo, hz * 2);
501: } else {
502: /* no one else waiting; turn off the uart */
503: compwroff(sc);
504: }
505: CLR(tp->t_state, TS_BUSY | TS_FLUSH);
506: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
507: timeout_del(&sc->sc_comsoft_tmo);
508: #endif
509: sc->sc_cua = 0;
510: splx(s);
511: ttyclose(tp);
512:
513: #ifdef COM_CONSOLE
514: #ifdef notyet /* XXXX */
515: if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
516: ttyfree(tp);
517: sc->sc_tty = 0;
518: }
519: #endif
520: #endif
521: return 0;
522: }
523:
524: void
525: compwroff(struct com_softc *sc)
526: {
527: bus_space_tag_t iot = sc->sc_iot;
528: bus_space_handle_t ioh = sc->sc_ioh;
529: struct tty *tp = sc->sc_tty;
530:
531: CLR(sc->sc_lcr, LCR_SBREAK);
532: bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
533: bus_space_write_1(iot, ioh, com_ier, 0);
534: if (ISSET(tp->t_cflag, HUPCL) &&
535: !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
536: /* XXX perhaps only clear DTR */
537: sc->sc_mcr = 0;
538: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
539: }
540:
541: /*
542: * Turn FIFO off; enter sleep mode if possible.
543: */
544: bus_space_write_1(iot, ioh, com_fifo, 0);
545: delay(100);
546: (void) bus_space_read_1(iot, ioh, com_data);
547: delay(100);
548: bus_space_write_1(iot, ioh, com_fifo,
549: FIFO_RCV_RST | FIFO_XMT_RST);
550:
551: switch (sc->sc_uarttype) {
552: case COM_UART_ST16650:
553: case COM_UART_ST16650V2:
554: bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
555: bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
556: bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
557: bus_space_write_1(iot, ioh, com_lcr, 0);
558: break;
559: case COM_UART_TI16750:
560: bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
561: break;
562: #ifdef COM_PXA2X0
563: case COM_UART_PXA2X0:
564: bus_space_write_1(iot, ioh, com_ier, 0);
565: #ifdef __zaurus__
566: if (ISSET(sc->sc_hwflags, COM_HW_SIR))
567: scoop_set_irled(0);
568: #endif
569: break;
570: #endif
571: }
572: }
573:
574: void
575: com_raisedtr(void *arg)
576: {
577: struct com_softc *sc = arg;
578:
579: SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
580: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
581: }
582:
583: int
584: comread(dev_t dev, struct uio *uio, int flag)
585: {
586: struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
587: struct tty *tp = sc->sc_tty;
588:
589: return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
590: }
591:
592: int
593: comwrite(dev_t dev, struct uio *uio, int flag)
594: {
595: struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
596: struct tty *tp = sc->sc_tty;
597:
598: return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
599: }
600:
601: struct tty *
602: comtty(dev_t dev)
603: {
604: struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
605: struct tty *tp = sc->sc_tty;
606:
607: return (tp);
608: }
609:
610: static u_char
611: tiocm_xxx2mcr(int data)
612: {
613: u_char m = 0;
614:
615: if (ISSET(data, TIOCM_DTR))
616: SET(m, MCR_DTR);
617: if (ISSET(data, TIOCM_RTS))
618: SET(m, MCR_RTS);
619: return m;
620: }
621:
622: int
623: comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
624: {
625: int unit = DEVUNIT(dev);
626: struct com_softc *sc = com_cd.cd_devs[unit];
627: struct tty *tp = sc->sc_tty;
628: bus_space_tag_t iot = sc->sc_iot;
629: bus_space_handle_t ioh = sc->sc_ioh;
630: int error;
631:
632: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
633: if (error >= 0)
634: return error;
635: error = ttioctl(tp, cmd, data, flag, p);
636: if (error >= 0)
637: return error;
638:
639: switch (cmd) {
640: case TIOCSBRK:
641: SET(sc->sc_lcr, LCR_SBREAK);
642: bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
643: break;
644: case TIOCCBRK:
645: CLR(sc->sc_lcr, LCR_SBREAK);
646: bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
647: break;
648: case TIOCSDTR:
649: SET(sc->sc_mcr, sc->sc_dtr);
650: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
651: break;
652: case TIOCCDTR:
653: CLR(sc->sc_mcr, sc->sc_dtr);
654: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
655: break;
656: case TIOCMSET:
657: CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
658: case TIOCMBIS:
659: SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
660: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
661: break;
662: case TIOCMBIC:
663: CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
664: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
665: break;
666: case TIOCMGET: {
667: u_char m;
668: int bits = 0;
669:
670: m = sc->sc_mcr;
671: if (ISSET(m, MCR_DTR))
672: SET(bits, TIOCM_DTR);
673: if (ISSET(m, MCR_RTS))
674: SET(bits, TIOCM_RTS);
675: m = sc->sc_msr;
676: if (ISSET(m, MSR_DCD))
677: SET(bits, TIOCM_CD);
678: if (ISSET(m, MSR_CTS))
679: SET(bits, TIOCM_CTS);
680: if (ISSET(m, MSR_DSR))
681: SET(bits, TIOCM_DSR);
682: if (ISSET(m, MSR_RI | MSR_TERI))
683: SET(bits, TIOCM_RI);
684: if (bus_space_read_1(iot, ioh, com_ier))
685: SET(bits, TIOCM_LE);
686: *(int *)data = bits;
687: break;
688: }
689: case TIOCGFLAGS: {
690: int driverbits, userbits = 0;
691:
692: driverbits = sc->sc_swflags;
693: if (ISSET(driverbits, COM_SW_SOFTCAR))
694: SET(userbits, TIOCFLAG_SOFTCAR);
695: if (ISSET(driverbits, COM_SW_CLOCAL))
696: SET(userbits, TIOCFLAG_CLOCAL);
697: if (ISSET(driverbits, COM_SW_CRTSCTS))
698: SET(userbits, TIOCFLAG_CRTSCTS);
699: if (ISSET(driverbits, COM_SW_MDMBUF))
700: SET(userbits, TIOCFLAG_MDMBUF);
701: if (ISSET(driverbits, COM_SW_PPS))
702: SET(userbits, TIOCFLAG_PPS);
703:
704: *(int *)data = userbits;
705: break;
706: }
707: case TIOCSFLAGS: {
708: int userbits, driverbits = 0;
709:
710: error = suser(p, 0);
711: if (error != 0)
712: return(EPERM);
713:
714: userbits = *(int *)data;
715: if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
716: ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
717: SET(driverbits, COM_SW_SOFTCAR);
718: if (ISSET(userbits, TIOCFLAG_CLOCAL))
719: SET(driverbits, COM_SW_CLOCAL);
720: if (ISSET(userbits, TIOCFLAG_CRTSCTS))
721: SET(driverbits, COM_SW_CRTSCTS);
722: if (ISSET(userbits, TIOCFLAG_MDMBUF))
723: SET(driverbits, COM_SW_MDMBUF);
724: if (ISSET(userbits, TIOCFLAG_PPS))
725: SET(driverbits, COM_SW_PPS);
726:
727: sc->sc_swflags = driverbits;
728: break;
729: }
730: default:
731: return ENOTTY;
732: }
733:
734: return 0;
735: }
736:
737: /* already called at spltty */
738: int
739: comparam(struct tty *tp, struct termios *t)
740: {
741: struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
742: bus_space_tag_t iot = sc->sc_iot;
743: bus_space_handle_t ioh = sc->sc_ioh;
744: int ospeed = comspeed(sc->sc_frequency, t->c_ospeed);
745: u_char lcr;
746: tcflag_t oldcflag;
747:
748: /* check requested parameters */
749: if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
750: return EINVAL;
751:
752: lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
753:
754: switch (ISSET(t->c_cflag, CSIZE)) {
755: case CS5:
756: SET(lcr, LCR_5BITS);
757: break;
758: case CS6:
759: SET(lcr, LCR_6BITS);
760: break;
761: case CS7:
762: SET(lcr, LCR_7BITS);
763: break;
764: case CS8:
765: SET(lcr, LCR_8BITS);
766: break;
767: }
768: if (ISSET(t->c_cflag, PARENB)) {
769: SET(lcr, LCR_PENAB);
770: if (!ISSET(t->c_cflag, PARODD))
771: SET(lcr, LCR_PEVEN);
772: }
773: if (ISSET(t->c_cflag, CSTOPB))
774: SET(lcr, LCR_STOPB);
775:
776: sc->sc_lcr = lcr;
777:
778: if (ospeed == 0) {
779: CLR(sc->sc_mcr, MCR_DTR);
780: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
781: }
782:
783: /*
784: * Set the FIFO threshold based on the receive speed, if we are
785: * changing it.
786: */
787: if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
788: sc->sc_initialize = 0;
789:
790: if (ospeed != 0) {
791: /*
792: * Make sure the transmit FIFO is empty before
793: * proceeding. If we don't do this, some revisions
794: * of the UART will hang. Interestingly enough,
795: * even if we do this while the last character is
796: * still being pushed out, they don't hang. This
797: * seems good enough.
798: */
799: while (ISSET(tp->t_state, TS_BUSY)) {
800: int error;
801:
802: ++sc->sc_halt;
803: error = ttysleep(tp, &tp->t_outq,
804: TTOPRI | PCATCH, "comprm", 0);
805: --sc->sc_halt;
806: if (error) {
807: comstart(tp);
808: return (error);
809: }
810: }
811:
812: bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
813: bus_space_write_1(iot, ioh, com_dlbl, ospeed);
814: bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8);
815: bus_space_write_1(iot, ioh, com_lcr, lcr);
816: SET(sc->sc_mcr, MCR_DTR);
817: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
818: } else
819: bus_space_write_1(iot, ioh, com_lcr, lcr);
820:
821: if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
822: if (sc->sc_uarttype == COM_UART_TI16750) {
823: bus_space_write_1(iot, ioh, com_lcr,
824: lcr | LCR_DLAB);
825: bus_space_write_1(iot, ioh, com_fifo,
826: FIFO_ENABLE | FIFO_ENABLE_64BYTE |
827: (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
828: bus_space_write_1(iot, ioh, com_lcr, lcr);
829: } else
830: bus_space_write_1(iot, ioh, com_fifo,
831: FIFO_ENABLE |
832: (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
833: }
834: } else
835: bus_space_write_1(iot, ioh, com_lcr, lcr);
836:
837: /* When not using CRTSCTS, RTS follows DTR. */
838: if (!ISSET(t->c_cflag, CRTSCTS)) {
839: if (ISSET(sc->sc_mcr, MCR_DTR)) {
840: if (!ISSET(sc->sc_mcr, MCR_RTS)) {
841: SET(sc->sc_mcr, MCR_RTS);
842: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
843: }
844: } else {
845: if (ISSET(sc->sc_mcr, MCR_RTS)) {
846: CLR(sc->sc_mcr, MCR_RTS);
847: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
848: }
849: }
850: sc->sc_dtr = MCR_DTR | MCR_RTS;
851: } else
852: sc->sc_dtr = MCR_DTR;
853:
854: /* and copy to tty */
855: tp->t_ispeed = t->c_ispeed;
856: tp->t_ospeed = t->c_ospeed;
857: oldcflag = tp->t_cflag;
858: tp->t_cflag = t->c_cflag;
859:
860: /*
861: * If DCD is off and MDMBUF is changed, ask the tty layer if we should
862: * stop the device.
863: */
864: if (!ISSET(sc->sc_msr, MSR_DCD) &&
865: !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
866: ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
867: (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
868: CLR(sc->sc_mcr, sc->sc_dtr);
869: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
870: }
871:
872: /* Just to be sure... */
873: comstart(tp);
874: return 0;
875: }
876:
877: void
878: comstart(struct tty *tp)
879: {
880: struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
881: bus_space_tag_t iot = sc->sc_iot;
882: bus_space_handle_t ioh = sc->sc_ioh;
883: int s;
884:
885: s = spltty();
886: if (ISSET(tp->t_state, TS_BUSY))
887: goto out;
888: if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
889: goto stopped;
890: if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
891: goto stopped;
892: if (tp->t_outq.c_cc <= tp->t_lowat) {
893: if (ISSET(tp->t_state, TS_ASLEEP)) {
894: CLR(tp->t_state, TS_ASLEEP);
895: wakeup(&tp->t_outq);
896: }
897: if (tp->t_outq.c_cc == 0)
898: goto stopped;
899: selwakeup(&tp->t_wsel);
900: }
901: SET(tp->t_state, TS_BUSY);
902:
903: #ifdef COM_PXA2X0
904: /* Enable transmitter slow infrared mode. */
905: if (sc->sc_uarttype == COM_UART_PXA2X0 &&
906: ISSET(sc->sc_hwflags, COM_HW_SIR))
907: bus_space_write_1(iot, ioh, com_isr, ISR_SEND);
908: #endif
909:
910: /* Enable transmit completion interrupts. */
911: if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
912: SET(sc->sc_ier, IER_ETXRDY);
913: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
914: }
915:
916: if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
917: u_char buffer[64]; /* XXX: largest fifo */
918:
919: int n = q_to_b(&tp->t_outq, buffer, sc->sc_fifolen);
920: int i;
921:
922: for (i = 0; i < n; i++) {
923: bus_space_write_1(iot, ioh, com_data, buffer[i]);
924: }
925: } else if (tp->t_outq.c_cc != 0)
926: bus_space_write_1(iot, ioh, com_data, getc(&tp->t_outq));
927: out:
928: splx(s);
929: return;
930: stopped:
931: if (ISSET(sc->sc_ier, IER_ETXRDY)) {
932: CLR(sc->sc_ier, IER_ETXRDY);
933: bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
934: #ifdef COM_PXA2X0
935: if (sc->sc_uarttype == COM_UART_PXA2X0 &&
936: ISSET(sc->sc_hwflags, COM_HW_SIR)) {
937: int timo;
938:
939: /* Wait for empty transmit shift register. */
940: timo = 20000;
941: while (!ISSET(bus_space_read_1(iot, ioh, com_lsr),
942: LSR_TSRE) && --timo)
943: delay(1);
944:
945: /* Enable receiver slow infrared mode. */
946: bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
947: }
948: #endif
949: }
950: splx(s);
951: }
952:
953: /*
954: * Stop output on a line.
955: */
956: int
957: comstop(struct tty *tp, int flag)
958: {
959: int s;
960:
961: s = spltty();
962: if (ISSET(tp->t_state, TS_BUSY))
963: if (!ISSET(tp->t_state, TS_TTSTOP))
964: SET(tp->t_state, TS_FLUSH);
965: splx(s);
966: return 0;
967: }
968:
969: void
970: comdiag(void *arg)
971: {
972: struct com_softc *sc = arg;
973: int overflows, floods;
974: int s;
975:
976: s = spltty();
977: sc->sc_errors = 0;
978: overflows = sc->sc_overflows;
979: sc->sc_overflows = 0;
980: floods = sc->sc_floods;
981: sc->sc_floods = 0;
982: splx(s);
983: log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
984: sc->sc_dev.dv_xname,
985: overflows, overflows == 1 ? "" : "s",
986: floods, floods == 1 ? "" : "s");
987: }
988:
989: void
990: comsoft(void *arg)
991: {
992: struct com_softc *sc = (struct com_softc *)arg;
993: struct tty *tp;
994: u_char *ibufp;
995: u_char *ibufend;
996: int c;
997: int s;
998: static int lsrmap[8] = {
999: 0, TTY_PE,
1000: TTY_FE, TTY_PE|TTY_FE,
1001: TTY_FE, TTY_PE|TTY_FE,
1002: TTY_FE, TTY_PE|TTY_FE
1003: };
1004:
1005: if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf)
1006: goto out;
1007:
1008: tp = sc->sc_tty;
1009:
1010: s = spltty();
1011:
1012: ibufp = sc->sc_ibuf;
1013: ibufend = sc->sc_ibufp;
1014:
1015: if (ibufp == ibufend) {
1016: splx(s);
1017: goto out;
1018: }
1019:
1020: sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
1021: sc->sc_ibufs[1] : sc->sc_ibufs[0];
1022: sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
1023: sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
1024:
1025: if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) {
1026: splx(s);
1027: goto out;
1028: }
1029:
1030: if (ISSET(tp->t_cflag, CRTSCTS) &&
1031: !ISSET(sc->sc_mcr, MCR_RTS)) {
1032: /* XXX */
1033: SET(sc->sc_mcr, MCR_RTS);
1034: bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr,
1035: sc->sc_mcr);
1036: }
1037:
1038: splx(s);
1039:
1040: while (ibufp < ibufend) {
1041: c = *ibufp++;
1042: if (ISSET(*ibufp, LSR_OE)) {
1043: sc->sc_overflows++;
1044: if (sc->sc_errors++ == 0)
1045: timeout_add(&sc->sc_diag_tmo, 60 * hz);
1046: }
1047: /* This is ugly, but fast. */
1048: c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
1049: (*linesw[tp->t_line].l_rint)(c, tp);
1050: }
1051:
1052: out:
1053: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
1054: timeout_add(&sc->sc_comsoft_tmo, 1);
1055: #else
1056: ;
1057: #endif
1058: }
1059:
1060: #ifdef KGDB
1061:
1062: /*
1063: * If a line break is set, or data matches one of the characters
1064: * gdb uses to signal a connection, then start up kgdb. Just gobble
1065: * any other data. Done in a stand alone function because comintr
1066: * does tty stuff and we don't have one.
1067: */
1068:
1069: int
1070: kgdbintr(void *arg)
1071: {
1072: struct com_softc *sc = arg;
1073: bus_space_tag_t iot = sc->sc_iot;
1074: bus_space_handle_t ioh = sc->sc_ioh;
1075: u_char lsr, data, msr, delta;
1076:
1077: if (!ISSET(sc->sc_hwflags, COM_HW_KGDB))
1078: return(0);
1079:
1080: for (;;) {
1081: lsr = bus_space_read_1(iot, ioh, com_lsr);
1082: if (ISSET(lsr, LSR_RXRDY)) {
1083: do {
1084: data = bus_space_read_1(iot, ioh, com_data);
1085: if (data == 3 || data == '$' || data == '+' ||
1086: ISSET(lsr, LSR_BI)) {
1087: kgdb_connect(1);
1088: data = 0;
1089: }
1090: lsr = bus_space_read_1(iot, ioh, com_lsr);
1091: } while (ISSET(lsr, LSR_RXRDY));
1092:
1093: }
1094: if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
1095: printf("weird lsr %02x\n", lsr);
1096:
1097: msr = bus_space_read_1(iot, ioh, com_msr);
1098:
1099: if (msr != sc->sc_msr) {
1100: delta = msr ^ sc->sc_msr;
1101: sc->sc_msr = msr;
1102: if (ISSET(delta, MSR_DCD)) {
1103: if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
1104: CLR(sc->sc_mcr, sc->sc_dtr);
1105: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1106: }
1107: }
1108: }
1109: if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1110: return (1);
1111: }
1112: }
1113: #endif /* KGDB */
1114:
1115: int
1116: comintr(void *arg)
1117: {
1118: struct com_softc *sc = arg;
1119: bus_space_tag_t iot = sc->sc_iot;
1120: bus_space_handle_t ioh = sc->sc_ioh;
1121: struct tty *tp;
1122: u_char lsr, data, msr, delta;
1123:
1124: if (!sc->sc_tty)
1125: return (0); /* can't do squat. */
1126:
1127: if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1128: return (0);
1129:
1130: tp = sc->sc_tty;
1131:
1132: for (;;) {
1133: lsr = bus_space_read_1(iot, ioh, com_lsr);
1134:
1135: if (ISSET(lsr, LSR_RXRDY)) {
1136: u_char *p = sc->sc_ibufp;
1137:
1138: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1139: softintr_schedule(sc->sc_si);
1140: #endif
1141: do {
1142: data = bus_space_read_1(iot, ioh, com_data);
1143: if (ISSET(lsr, LSR_BI)) {
1144: #if defined(COM_CONSOLE) && defined(DDB)
1145: if (ISSET(sc->sc_hwflags,
1146: COM_HW_CONSOLE)) {
1147: if (db_console)
1148: Debugger();
1149: goto next;
1150: }
1151: #endif
1152: data = 0;
1153: }
1154: if (p >= sc->sc_ibufend) {
1155: sc->sc_floods++;
1156: if (sc->sc_errors++ == 0)
1157: timeout_add(&sc->sc_diag_tmo, 60 * hz);
1158: } else {
1159: *p++ = data;
1160: *p++ = lsr;
1161: if (p == sc->sc_ibufhigh &&
1162: ISSET(tp->t_cflag, CRTSCTS)) {
1163: /* XXX */
1164: CLR(sc->sc_mcr, MCR_RTS);
1165: bus_space_write_1(iot, ioh, com_mcr,
1166: sc->sc_mcr);
1167: }
1168: }
1169: #if defined(COM_CONSOLE) && defined(DDB)
1170: next:
1171: #endif
1172: lsr = bus_space_read_1(iot, ioh, com_lsr);
1173: } while (ISSET(lsr, LSR_RXRDY));
1174:
1175: sc->sc_ibufp = p;
1176: }
1177: msr = bus_space_read_1(iot, ioh, com_msr);
1178:
1179: if (msr != sc->sc_msr) {
1180: delta = msr ^ sc->sc_msr;
1181:
1182: ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS,
1183: sc->sc_msr & MSR_DCD, msr & MSR_DCD);
1184:
1185: sc->sc_msr = msr;
1186: if (ISSET(delta, MSR_DCD)) {
1187: if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
1188: (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
1189: CLR(sc->sc_mcr, sc->sc_dtr);
1190: bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
1191: }
1192: }
1193: if (ISSET(delta & msr, MSR_CTS) &&
1194: ISSET(tp->t_cflag, CRTSCTS)) {
1195: /* the line is up and we want to do rts/cts flow control */
1196: (*linesw[tp->t_line].l_start)(tp);
1197: }
1198: }
1199:
1200: if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
1201: CLR(tp->t_state, TS_BUSY | TS_FLUSH);
1202: if (sc->sc_halt > 0)
1203: wakeup(&tp->t_outq);
1204: (*linesw[tp->t_line].l_start)(tp);
1205: }
1206:
1207: #ifdef COM_PXA2X0
1208: if (sc->sc_uarttype == COM_UART_PXA2X0 &&
1209: ISSET(sc->sc_hwflags, COM_HW_SIR) &&
1210: ISSET(lsr, LSR_TXRDY) && ISSET(lsr, LSR_TSRE))
1211: bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
1212: #endif
1213:
1214: if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
1215: return (1);
1216: }
1217: }
1218:
1219: /*
1220: * Following are all routines needed for COM to act as console
1221: */
1222:
1223: #if defined(__sgi__)
1224: #undef CONADDR
1225: #undef COM_FREQ
1226: #include <machine/autoconf.h>
1227: #endif
1228:
1229: /*
1230: * The following functions are polled getc and putc routines, shared
1231: * by the console and kgdb glue.
1232: */
1233:
1234: int
1235: com_common_getc(bus_space_tag_t iot, bus_space_handle_t ioh)
1236: {
1237: int s = splhigh();
1238: u_char stat, c;
1239:
1240: #ifdef COM_PXA2X0
1241: if (com_is_console(iot, comsiraddr))
1242: bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
1243: #endif
1244:
1245: /* block until a character becomes available */
1246: while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
1247: continue;
1248:
1249: c = bus_space_read_1(iot, ioh, com_data);
1250: /* clear any interrupts generated by this transmission */
1251: stat = bus_space_read_1(iot, ioh, com_iir);
1252: splx(s);
1253: return (c);
1254: }
1255:
1256: void
1257: com_common_putc(bus_space_tag_t iot, bus_space_handle_t ioh, int c)
1258: {
1259: int s = spltty();
1260: int timo;
1261:
1262: printf("com_common_putc: enter\n");
1263:
1264: /* wait for any pending transmission to finish */
1265: timo = 2000;
1266: while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
1267: delay(1);
1268:
1269: #ifdef COM_PXA2X0
1270: if (com_is_console(iot, comsiraddr))
1271: bus_space_write_1(iot, ioh, com_isr, ISR_SEND);
1272: #endif
1273: bus_space_write_1(iot, ioh, com_data, (u_int8_t)(c & 0xff));
1274: bus_space_barrier(iot, ioh, 0, COM_NPORTS,
1275: (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE));
1276:
1277: printf("com_common_putc: wait for TXRDY\n");
1278: /* wait for this transmission to complete */
1279: timo = 2000;
1280: while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
1281: delay(1);
1282:
1283: #ifdef COM_PXA2X0
1284: if (com_is_console(iot, comsiraddr)) {
1285: /* wait for transmit shift register to become empty */
1286: timo = 20000;
1287: while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TSRE)
1288: && --timo)
1289: delay(1);
1290:
1291: bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
1292: }
1293: #endif
1294:
1295: splx(s);
1296: }
1297:
1298: void
1299: cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate, int frequency)
1300: {
1301: int s = splhigh();
1302: u_char stat;
1303:
1304: bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
1305: rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */
1306: bus_space_write_1(iot, ioh, com_dlbl, rate);
1307: bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
1308: bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
1309: bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
1310: #ifdef COM_PXA2X0
1311: /* XXX */
1312: bus_space_write_1(iot, ioh, com_ier, IER_EUART); /* Make sure they are off */
1313: #else
1314: bus_space_write_1(iot, ioh, com_ier, 0); /* Make sure they are off */
1315: #endif
1316: bus_space_write_1(iot, ioh, com_fifo,
1317: FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
1318: stat = bus_space_read_1(iot, ioh, com_iir);
1319: splx(s);
1320: }
1321:
1322: #ifdef COM_CONSOLE
1323: void
1324: comcnprobe(struct consdev *cp)
1325: {
1326: /* XXX NEEDS TO BE FIXED XXX */
1327: #ifdef MD_ISA_IOT
1328: bus_space_tag_t iot = MD_ISA_IOT;
1329: #elif defined(__sgi__)
1330: bus_space_tag_t iot = sys_config.cons_iot;
1331: #else
1332: bus_space_tag_t iot = 0;
1333: #endif
1334: bus_space_handle_t ioh;
1335: int found;
1336:
1337: if (CONADDR == 0)
1338: return;
1339:
1340: comconsiot = iot;
1341: if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh))
1342: return;
1343: found = comprobe1(iot, ioh);
1344: bus_space_unmap(iot, ioh, COM_NPORTS);
1345: if (!found)
1346: return;
1347:
1348: /* locate the major number */
1349: for (commajor = 0; commajor < nchrdev; commajor++)
1350: if (cdevsw[commajor].d_open == comopen)
1351: break;
1352:
1353: /* initialize required fields */
1354: cp->cn_dev = makedev(commajor, CONUNIT);
1355: #if defined(COMCONSOLE) || defined(PCCOMCONSOLE) || !defined(__amd64__)
1356: cp->cn_pri = CN_REMOTE;
1357: #else
1358: cp->cn_pri = CN_NORMAL;
1359: #endif
1360: }
1361:
1362: void
1363: comcninit(struct consdev *cp)
1364: {
1365: comconsaddr = CONADDR;
1366:
1367: if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
1368: panic("comcninit: mapping failed");
1369:
1370: if (comconsfreq == 0)
1371: comconsfreq = COM_FREQ;
1372:
1373: cominit(comconsiot, comconsioh, comdefaultrate, comconsfreq);
1374: comconsinit = 0;
1375: }
1376:
1377:
1378: int
1379: comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency, tcflag_t cflag)
1380: {
1381: static struct consdev comcons = {
1382: NULL, NULL, comcngetc, comcnputc, comcnpollc, NULL,
1383: NODEV, CN_NORMAL
1384: };
1385:
1386: #ifndef __sparc64__
1387: if (bus_space_map(iot, iobase, COM_NPORTS, 0, &comconsioh))
1388: return ENOMEM;
1389: #endif
1390:
1391: cominit(iot, comconsioh, rate, frequency);
1392:
1393: cn_tab = &comcons;
1394:
1395: comconsiot = iot;
1396: comconsaddr = iobase;
1397: comconscflag = cflag;
1398: comconsfreq = frequency;
1399:
1400: return (0);
1401: }
1402:
1403: int
1404: comcngetc(dev_t dev)
1405: {
1406: return (com_common_getc(comconsiot, comconsioh));
1407: }
1408:
1409: /*
1410: * Console kernel output character routine.
1411: */
1412: void
1413: comcnputc(dev_t dev, int c)
1414: {
1415: com_common_putc(comconsiot, comconsioh, c);
1416: }
1417:
1418: void
1419: comcnpollc(dev_t dev, int on)
1420: {
1421:
1422: }
1423: #endif /* COM_CONSOLE */
1424:
1425: #ifdef KGDB
1426: int
1427: com_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
1428: int frequency,tcflag_t cflag)
1429: bus_space_tag_t iot;
1430: bus_addr_t iobase;
1431: int rate, frequency;
1432: tcflag_t cflag;
1433: {
1434: #ifdef COM_CONSOLE
1435: if (iot == comconsiot && iobase == comconsaddr) {
1436: return (EBUSY); /* cannot share with console */
1437: }
1438: #endif
1439:
1440: com_kgdb_iot = iot;
1441: com_kgdb_addr = iobase;
1442:
1443: if (bus_space_map(com_kgdb_iot, com_kgdb_addr, COM_NPORTS, 0,
1444: &com_kgdb_ioh))
1445: panic("com_kgdb_attach: mapping failed");
1446:
1447: /* XXX We currently don't respect KGDBMODE? */
1448: cominit(com_kgdb_iot, com_kgdb_ioh, rate, frequency);
1449:
1450: kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
1451: kgdb_dev = 123; /* unneeded, only to satisfy some tests */
1452:
1453: return (0);
1454: }
1455:
1456: /* ARGSUSED */
1457: int
1458: com_kgdb_getc(void *arg)
1459: {
1460:
1461: return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));
1462: }
1463:
1464: /* ARGSUSED */
1465: void
1466: com_kgdb_putc(void *arg, int c)
1467: {
1468:
1469: return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
1470: }
1471: #endif /* KGDB */
1472:
1473: #ifdef COM_PXA2X0
1474: int
1475: com_is_console(bus_space_tag_t iot, bus_addr_t iobase)
1476: {
1477:
1478: if (comconsiot == iot && comconsaddr == iobase)
1479: return (1);
1480: #ifdef KGDB
1481: else if (com_kgdb_iot == iot && com_kgdb_addr == iobase)
1482: return (1);
1483: #endif
1484: return (0);
1485: }
1486: #endif
CVSweb