com.c revision 1.21 1 /*-
2 * Copyright (c) 1993, 1994 Charles Hannum.
3 * Copyright (c) 1991 The Regents of the University of California.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by the University of
17 * California, Berkeley and its contributors.
18 * 4. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#)com.c 7.5 (Berkeley) 5/16/91
35 * $Id: com.c,v 1.21 1994/03/08 08:12:56 mycroft Exp $
36 */
37
38 /*
39 * COM driver, based on HP dca driver
40 * uses National Semiconductor NS16450/NS16550AF UART
41 */
42 #include "com.h"
43
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/ioctl.h>
47 #include <sys/select.h>
48 #include <sys/tty.h>
49 #include <sys/proc.h>
50 #include <sys/user.h>
51 #include <sys/conf.h>
52 #include <sys/file.h>
53 #include <sys/uio.h>
54 #include <sys/kernel.h>
55 #include <sys/syslog.h>
56 #include <sys/types.h>
57 #include <sys/device.h>
58
59 #include <machine/cpu.h>
60 #include <machine/pio.h>
61
62 #include <i386/isa/isa_device.h>
63 #include <i386/isa/comreg.h>
64 #include <i386/isa/ic/ns16550.h>
65
66 struct com_softc {
67 struct device sc_dev;
68
69 u_short sc_iobase;
70 u_char sc_flags;
71 #define COM_SOFTCAR 0x01
72 #define COM_FIFO 0x02
73 u_char sc_msr, sc_mcr;
74 } com_softc[NCOM];
75 /* XXXX should be in com_softc, but not ready for that yet */
76 struct tty *com_tty[NCOM];
77
78 int comprobe __P((struct isa_device *));
79 int comattach __P((struct isa_device *));
80 int comopen __P((dev_t, int, int, struct proc *));
81 int comclose __P((dev_t, int, int, struct proc *));
82 int comintr __P((int));
83 int comparam __P((struct tty *, struct termios *));
84 void comstart __P((struct tty *));
85
86 struct isa_driver comdriver = {
87 comprobe, comattach, "com"
88 };
89
90 int comdefaultrate = TTYDEF_SPEED;
91 #ifdef COMCONSOLE
92 int comconsole = COMCONSOLE;
93 #else
94 int comconsole = -1;
95 #endif
96 int comconsinit;
97 int commajor;
98
99 #ifdef KGDB
100 #include <machine/remote-sl.h>
101 extern int kgdb_dev;
102 extern int kgdb_rate;
103 extern int kgdb_debug_init;
104 #endif
105
106 #define COMUNIT(x) (minor(x))
107
108 #define bis(c, b) do { const register u_short com_ad = (c); \
109 outb(com_ad, inb(com_ad) | (b)); } while(0)
110 #define bic(c, b) do { const register u_short com_ad = (c); \
111 outb(com_ad, inb(com_ad) & ~(b)); } while(0)
112
113 int
114 comspeed(speed)
115 long speed;
116 {
117 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
118
119 int x, err;
120
121 if (speed == 0)
122 return 0;
123 if (speed < 0)
124 return -1;
125 x = divrnd((COM_FREQ / 16), speed);
126 if (x <= 0)
127 return -1;
128 err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
129 if (err < 0)
130 err = -err;
131 if (err > COM_TOLERANCE)
132 return -1;
133 return x;
134
135 #undef divrnd(n, q)
136 }
137
138 int
139 comprobe1(iobase)
140 u_short iobase;
141 {
142
143 /* force access to id reg */
144 outb(iobase + com_cfcr, 0);
145 outb(iobase + com_iir, 0);
146 if (inb(iobase + com_iir) & 0x38)
147 return 0;
148
149 return 1;
150 }
151
152 int
153 comprobe(isa_dev)
154 struct isa_device *isa_dev;
155 {
156 struct com_softc *sc = &com_softc[isa_dev->id_unit];
157 u_short iobase = isa_dev->id_iobase;
158
159 /* XXX HACK */
160 sprintf(sc->sc_dev.dv_xname, "%s%d", comdriver.name, isa_dev->id_unit);
161 sc->sc_dev.dv_unit = isa_dev->id_unit;
162
163 if (!comprobe1(iobase))
164 return 0;
165
166 return COM_NPORTS;
167 }
168
169 int
170 comattach(isa_dev)
171 struct isa_device *isa_dev;
172 {
173 int unit = isa_dev->id_unit;
174 struct com_softc *sc = &com_softc[unit];
175 u_short iobase = isa_dev->id_iobase;
176 struct tty *tp;
177
178 if (unit == comconsole)
179 delay(1000);
180
181 sc->sc_iobase = iobase;
182 sc->sc_flags = 0;
183
184 printf("%s: ", sc->sc_dev.dv_xname);
185
186 /* look for a NS 16550AF UART with FIFOs */
187 outb(iobase + com_fifo,
188 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
189 delay(100);
190 if ((inb(iobase + com_iir) & IIR_FIFO_MASK) == IIR_FIFO_MASK)
191 if ((inb(iobase + com_fifo) & FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
192 sc->sc_flags |= COM_FIFO;
193 printf("ns16550a, working fifo\n");
194 } else
195 printf("ns82550 or ns16550, broken fifo\n");
196 else
197 printf("ns82450 or ns16450, no fifo\n");
198 outb(iobase + com_fifo, 0);
199
200 /* disable interrupts */
201 outb(iobase + com_ier, 0);
202 outb(iobase + com_mcr, 0);
203
204 #ifdef KGDB
205 if (kgdb_dev == makedev(commajor, unit)) {
206 if (comconsole == unit)
207 kgdb_dev = -1; /* can't debug over console port */
208 else {
209 (void) cominit(unit, kgdb_rate);
210 if (kgdb_debug_init) {
211 /*
212 * Print prefix of device name,
213 * let kgdb_connect print the rest.
214 */
215 printf("%s: ", sc->sc_dev.dv_xname);
216 kgdb_connect(1);
217 } else
218 printf("%s: kgdb enabled\n",
219 sc->sc_dev.dv_xname);
220 }
221 }
222 #endif
223
224 /*
225 * Need to reset baud rate, etc. of next print so reset comconsinit.
226 * Also make sure console is always "hardwired".
227 */
228 if (unit == comconsole) {
229 comconsinit = 0;
230 sc->sc_flags |= COM_SOFTCAR;
231 }
232 }
233
234 int
235 comopen(dev, flag, mode, p)
236 dev_t dev;
237 int flag, mode;
238 struct proc *p;
239 {
240 int unit = COMUNIT(dev);
241 struct com_softc *sc;
242 u_short iobase;
243 struct tty *tp;
244 int s;
245 int error = 0;
246
247 if (unit > NCOM)
248 return ENXIO;
249 sc = &com_softc[unit];
250 if (!sc->sc_iobase)
251 return ENXIO;
252
253 s = spltty();
254
255 if (!com_tty[unit])
256 tp = com_tty[unit] = ttymalloc();
257 else
258 tp = com_tty[unit];
259
260 tp->t_oproc = comstart;
261 tp->t_param = comparam;
262 tp->t_dev = dev;
263 if ((tp->t_state & TS_ISOPEN) == 0) {
264 tp->t_state |= TS_WOPEN;
265 ttychars(tp);
266 tp->t_iflag = TTYDEF_IFLAG;
267 tp->t_oflag = TTYDEF_OFLAG;
268 tp->t_cflag = TTYDEF_CFLAG;
269 tp->t_lflag = TTYDEF_LFLAG;
270 tp->t_ispeed = tp->t_ospeed = comdefaultrate;
271 comparam(tp, &tp->t_termios);
272 ttsetwater(tp);
273
274 iobase = sc->sc_iobase;
275 /* flush any pending I/O */
276 if (sc->sc_flags & COM_FIFO)
277 outb(iobase + com_fifo,
278 FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
279 FIFO_TRIGGER_8);
280 (void) inb(iobase + com_lsr);
281 (void) inb(iobase + com_data);
282 /* you turn me on, baby */
283 outb(iobase + com_mcr,
284 sc->sc_mcr = MCR_DTR | MCR_RTS | MCR_IENABLE);
285 outb(iobase + com_ier,
286 IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC);
287
288 sc->sc_msr = inb(iobase + com_msr);
289 if (sc->sc_flags & COM_SOFTCAR || sc->sc_msr & MSR_DCD)
290 tp->t_state |= TS_CARR_ON;
291 else
292 tp->t_state &= ~TS_CARR_ON;
293 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0) {
294 splx(s);
295 return EBUSY;
296 }
297
298 /* wait for carrier if necessary */
299 if ((flag & O_NONBLOCK) == 0)
300 while ((tp->t_cflag & CLOCAL) == 0 &&
301 (tp->t_state & TS_CARR_ON) == 0) {
302 tp->t_state |= TS_WOPEN;
303 error = ttysleep(tp, (caddr_t)&tp->t_rawq,
304 TTIPRI | PCATCH, ttopen, 0);
305 if (error) {
306 /* XXX should turn off chip if we're the
307 only waiter */
308 splx(s);
309 return error;
310 }
311 }
312 splx(s);
313
314 return (*linesw[tp->t_line].l_open)(dev, tp);
315 }
316
317 int
318 comclose(dev, flag, mode, p)
319 dev_t dev;
320 int flag, mode;
321 struct proc *p;
322 {
323 int unit = COMUNIT(dev);
324 struct com_softc *sc = &com_softc[unit];
325 u_short iobase = sc->sc_iobase;
326 struct tty *tp = com_tty[unit];
327
328 (*linesw[tp->t_line].l_close)(tp, flag);
329 #ifdef KGDB
330 /* do not disable interrupts if debugging */
331 if (kgdb_dev != makedev(commajor, unit))
332 #endif
333 {
334 bic(iobase + com_cfcr, CFCR_SBREAK);
335 outb(iobase + com_ier, 0);
336 if (tp->t_cflag & HUPCL && (sc->sc_flags & COM_SOFTCAR) == 0)
337 /* XXX perhaps only clear DTR */
338 outb(iobase + com_mcr, 0);
339 }
340 ttyclose(tp);
341 #ifdef notyet /* XXXX */
342 if (unit != comconsole) {
343 ttyfree(tp);
344 com_tty[unit] = (struct tty *)NULL;
345 }
346 #endif
347 return 0;
348 }
349
350 int
351 comread(dev, uio, flag)
352 dev_t dev;
353 struct uio *uio;
354 int flag;
355 {
356 struct tty *tp = com_tty[COMUNIT(dev)];
357
358 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
359 }
360
361 int
362 comwrite(dev, uio, flag)
363 dev_t dev;
364 struct uio *uio;
365 int flag;
366 {
367 struct tty *tp = com_tty[COMUNIT(dev)];
368
369 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
370 }
371
372 static u_char
373 tiocm_xxx2mcr(data)
374 int data;
375 {
376 u_char m = 0;
377
378 if (data & TIOCM_DTR)
379 m |= MCR_DTR;
380 if (data & TIOCM_RTS)
381 m |= MCR_RTS;
382 return m;
383 }
384
385 int
386 comioctl(dev, cmd, data, flag, p)
387 dev_t dev;
388 int cmd;
389 caddr_t data;
390 int flag;
391 struct proc *p;
392 {
393 int unit = COMUNIT(dev);
394 struct com_softc *sc = &com_softc[unit];
395 u_short iobase = sc->sc_iobase;
396 struct tty *tp = com_tty[unit];
397 int error;
398
399 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
400 if (error >= 0)
401 return error;
402 error = ttioctl(tp, cmd, data, flag, p);
403 if (error >= 0)
404 return error;
405
406 switch (cmd) {
407 case TIOCSBRK:
408 bis(iobase + com_cfcr, CFCR_SBREAK);
409 break;
410 case TIOCCBRK:
411 bic(iobase + com_cfcr, CFCR_SBREAK);
412 break;
413 case TIOCSDTR:
414 outb(iobase + com_mcr, sc->sc_mcr |= (MCR_DTR | MCR_RTS));
415 break;
416 case TIOCCDTR:
417 outb(iobase + com_mcr, sc->sc_mcr &= ~(MCR_DTR | MCR_RTS));
418 break;
419 case TIOCMSET:
420 sc->sc_mcr &= ~(MCR_DTR | MCR_RTS);
421 case TIOCMBIS:
422 outb(iobase + com_mcr,
423 sc->sc_mcr |= tiocm_xxx2mcr(*(int *)data));
424 break;
425 case TIOCMBIC:
426 outb(iobase + com_mcr,
427 sc->sc_mcr &= ~tiocm_xxx2mcr(*(int *)data));
428 break;
429 case TIOCMGET: {
430 u_char m;
431 int bits = 0;
432
433 m = sc->sc_mcr;
434 if (m & MCR_DTR)
435 bits |= TIOCM_DTR;
436 if (m & MCR_RTS)
437 bits |= TIOCM_RTS;
438 m = sc->sc_msr;
439 if (m & MSR_DCD)
440 bits |= TIOCM_CD;
441 if (m & MSR_CTS)
442 bits |= TIOCM_CTS;
443 if (m & MSR_DSR)
444 bits |= TIOCM_DSR;
445 if (m & (MSR_RI | MSR_TERI))
446 bits |= TIOCM_RI;
447 if (inb(iobase + com_ier))
448 bits |= TIOCM_LE;
449 *(int *)data = bits;
450 break;
451 }
452 default:
453 return ENOTTY;
454 }
455
456 return 0;
457 }
458
459 int
460 comparam(tp, t)
461 struct tty *tp;
462 struct termios *t;
463 {
464 struct com_softc *sc = &com_softc[COMUNIT(tp->t_dev)];
465 u_short iobase = sc->sc_iobase;
466 int ospeed = comspeed(t->c_ospeed);
467 u_char cfcr;
468 int s;
469
470 /* check requested parameters */
471 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
472 return EINVAL;
473
474 switch (t->c_cflag & CSIZE) {
475 case CS5:
476 cfcr = CFCR_5BITS;
477 break;
478 case CS6:
479 cfcr = CFCR_6BITS;
480 break;
481 case CS7:
482 cfcr = CFCR_7BITS;
483 break;
484 case CS8:
485 cfcr = CFCR_8BITS;
486 break;
487 }
488 if (t->c_cflag & PARENB) {
489 cfcr |= CFCR_PENAB;
490 if ((t->c_cflag & PARODD) == 0)
491 cfcr |= CFCR_PEVEN;
492 }
493 if (t->c_cflag & CSTOPB)
494 cfcr |= CFCR_STOPB;
495
496 s = spltty();
497
498 /* and copy to tty */
499 tp->t_ispeed = t->c_ispeed;
500 tp->t_ospeed = t->c_ospeed;
501 tp->t_cflag = t->c_cflag;
502
503 if (ospeed == 0)
504 outb(iobase + com_mcr, sc->sc_mcr &= ~MCR_DTR);
505 else
506 outb(iobase + com_mcr, sc->sc_mcr |= MCR_DTR);
507
508 outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
509 outb(iobase + com_dlbl, ospeed);
510 outb(iobase + com_dlbh, ospeed>>8);
511 outb(iobase + com_cfcr, cfcr);
512
513 /* When not using CRTS_IFLOW, RTS follows DTR. */
514 if ((t->c_cflag & CRTS_IFLOW) == 0) {
515 if (sc->sc_mcr & MCR_DTR) {
516 if ((sc->sc_mcr & MCR_RTS) == 0)
517 outb(iobase + com_mcr, sc->sc_mcr |= MCR_RTS);
518 } else {
519 if (sc->sc_mcr & MCR_RTS)
520 outb(iobase + com_mcr, sc->sc_mcr &= ~MCR_RTS);
521 }
522 }
523
524 /* If CTS is off and CCTS_OFLOW is changed, we must toggle TS_TTSTOP. */
525 if ((sc->sc_msr & MSR_CTS) == 0 &&
526 (tp->t_cflag & CCTS_OFLOW) != (t->c_cflag & CCTS_OFLOW)) {
527 if ((t->c_cflag & CCTS_OFLOW) == 0) {
528 tp->t_state &= ~TS_TTSTOP;
529 ttstart(tp);
530 } else
531 tp->t_state |= TS_TTSTOP;
532 }
533
534 splx(s);
535 return 0;
536 }
537
538 void
539 comstart(tp)
540 struct tty *tp;
541 {
542 struct com_softc *sc = &com_softc[COMUNIT(tp->t_dev)];
543 u_short iobase = sc->sc_iobase;
544 int s;
545
546 s = spltty();
547 if (tp->t_state & (TS_TTSTOP | TS_BUSY))
548 goto out;
549 #if 0 /* XXXX I think this is handled adequately by commint() and comparam(). */
550 if (tp->t_cflag & CCTS_OFLOW && (sc->sc_mcr & MSR_CTS) == 0)
551 goto out;
552 #endif
553 if (tp->t_outq.c_cc <= tp->t_lowat) {
554 if (tp->t_state & TS_ASLEEP) {
555 tp->t_state &= ~TS_ASLEEP;
556 wakeup((caddr_t)&tp->t_outq);
557 }
558 selwakeup(&tp->t_wsel);
559 }
560 if (tp->t_outq.c_cc == 0)
561 goto out;
562 tp->t_state |= TS_BUSY;
563 if ((inb(iobase + com_lsr) & LSR_TXRDY) == 0)
564 goto out;
565 if (sc->sc_flags & COM_FIFO) {
566 u_char buffer[16], *cp = buffer;
567 int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
568 do {
569 outb(iobase + com_data, *cp++);
570 } while (--n);
571 } else
572 outb(iobase + com_data, getc(&tp->t_outq));
573 out:
574 splx(s);
575 }
576
577 /*
578 * Stop output on a line.
579 */
580 void
581 comstop(tp, flag)
582 struct tty *tp;
583 {
584 int s;
585
586 s = spltty();
587 if (tp->t_state & TS_BUSY)
588 if ((tp->t_state & TS_TTSTOP) == 0)
589 tp->t_state |= TS_FLUSH;
590 splx(s);
591 }
592
593 static inline void
594 comeint(sc, stat)
595 struct com_softc *sc;
596 int stat;
597 {
598 u_short iobase = sc->sc_iobase;
599 int unit = sc->sc_dev.dv_unit;
600 struct tty *tp = com_tty[unit];
601 int c;
602
603 c = inb(iobase + com_data);
604 if ((tp->t_state & TS_ISOPEN) == 0) {
605 #ifdef KGDB
606 /* we don't care about parity errors */
607 if (((stat & (LSR_BI | LSR_FE | LSR_PE)) == LSR_PE) &&
608 kgdb_dev == makedev(commajor, unit) && c == FRAME_END)
609 kgdb_connect(0); /* trap into kgdb */
610 #endif
611 return;
612 }
613 if (stat & (LSR_BI | LSR_FE))
614 c |= TTY_FE;
615 else if (stat & LSR_PE)
616 c |= TTY_PE;
617 if (stat & LSR_OE)
618 log(LOG_WARNING, "%s: silo overflow\n", sc->sc_dev.dv_xname);
619 /* XXXX put in FIFO and process later */
620 (*linesw[tp->t_line].l_rint)(c, tp);
621 }
622
623 static inline void
624 commint(sc)
625 struct com_softc *sc;
626 {
627 u_short iobase = sc->sc_iobase;
628 struct tty *tp = com_tty[sc->sc_dev.dv_unit];
629 u_char msr, delta;
630
631 msr = inb(iobase + com_msr);
632 delta = msr ^ sc->sc_msr;
633 sc->sc_msr = msr;
634
635 if (delta & MSR_DCD && (sc->sc_flags & COM_SOFTCAR) == 0) {
636 if (msr & MSR_DCD)
637 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
638 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
639 outb(iobase + com_mcr,
640 sc->sc_mcr &= ~(MCR_DTR | MCR_RTS));
641 }
642 if (delta & MSR_CTS && tp->t_cflag & CCTS_OFLOW) {
643 /* the line is up and we want to do rts/cts flow control */
644 if (msr & MSR_CTS) {
645 tp->t_state &= ~TS_TTSTOP;
646 ttstart(tp);
647 } else
648 tp->t_state |= TS_TTSTOP;
649 }
650 }
651
652 int
653 comintr(unit)
654 int unit;
655 {
656 struct com_softc *sc = &com_softc[unit];
657 u_short iobase = sc->sc_iobase;
658 struct tty *tp;
659 u_char code;
660
661 code = inb(iobase + com_iir) & IIR_IMASK;
662 if (code & IIR_NOPEND)
663 return 0;
664
665 for (;;) {
666 if (code & IIR_RXRDY) {
667 tp = com_tty[sc->sc_dev.dv_unit];
668 /* XXXX put in FIFO and process later */
669 while (code = (inb(iobase + com_lsr) & LSR_RCV_MASK)) {
670 if (code == LSR_RXRDY) {
671 code = inb(iobase + com_data);
672 if (tp->t_state & TS_ISOPEN)
673 (*linesw[tp->t_line].l_rint)(code, tp);
674 #ifdef KGDB
675 else {
676 if (kgdb_dev == makedev(commajor, unit) &&
677 code == FRAME_END)
678 kgdb_connect(0);
679 }
680 #endif
681 } else
682 comeint(sc, code);
683 }
684 } else if (code == IIR_TXRDY) {
685 tp = com_tty[sc->sc_dev.dv_unit];
686 tp->t_state &= ~TS_BUSY;
687 if (tp->t_state & TS_FLUSH)
688 tp->t_state &= ~TS_FLUSH;
689 else
690 if (tp->t_line)
691 (*linesw[tp->t_line].l_start)(tp);
692 else
693 comstart(tp);
694 } else if (code == IIR_MLSC) {
695 commint(sc);
696 } else {
697 log(LOG_WARNING, "%s: weird interrupt: iir=0x%02x\n",
698 sc->sc_dev.dv_xname, code);
699 }
700 code = inb(iobase + com_iir) & IIR_IMASK;
701 if (code & IIR_NOPEND)
702 return 1;
703 }
704 }
705
706 /*
707 * Following are all routines needed for COM to act as console
708 */
709 #include <dev/cons.h>
710
711 comcnprobe(cp)
712 struct consdev *cp;
713 {
714 int unit = CONUNIT;
715
716 if (!comprobe1(CONADDR)) {
717 cp->cn_pri = CN_DEAD;
718 return;
719 }
720
721 /* locate the major number */
722 for (commajor = 0; commajor < nchrdev; commajor++)
723 if (cdevsw[commajor].d_open == comopen)
724 break;
725
726 com_softc[unit].sc_iobase = CONADDR;
727
728 /* initialize required fields */
729 cp->cn_dev = makedev(commajor, unit);
730 #ifdef COMCONSOLE
731 cp->cn_pri = CN_REMOTE; /* Force a serial port console */
732 #else
733 cp->cn_pri = CN_NORMAL;
734 #endif
735 }
736
737 comcninit(cp)
738 struct consdev *cp;
739 {
740 int unit = CONUNIT;
741
742 cominit(unit, comdefaultrate);
743 comconsole = unit;
744 comconsinit = 0;
745 }
746
747 cominit(unit, rate)
748 int unit, rate;
749 {
750 int s = splhigh();
751 u_short iobase = com_softc[unit].sc_iobase;
752 u_char stat;
753
754 outb(iobase + com_cfcr, CFCR_DLAB);
755 rate = comspeed(comdefaultrate);
756 outb(iobase + com_dlbl, rate);
757 outb(iobase + com_dlbh, rate >> 8);
758 outb(iobase + com_cfcr, CFCR_8BITS);
759 outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY);
760 outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
761 stat = inb(iobase + com_iir);
762 splx(s);
763 }
764
765 comcngetc(dev)
766 dev_t dev;
767 {
768 int s = splhigh();
769 u_short iobase = com_softc[COMUNIT(dev)].sc_iobase;
770 u_char stat, c;
771
772 while (((stat = inb(iobase + com_lsr)) & LSR_RXRDY) == 0)
773 ;
774 c = inb(iobase + com_data);
775 stat = inb(iobase + com_iir);
776 splx(s);
777 return c;
778 }
779
780 /*
781 * Console kernel output character routine.
782 */
783 comcnputc(dev, c)
784 dev_t dev;
785 int c;
786 {
787 int s = splhigh();
788 u_short iobase = com_softc[COMUNIT(dev)].sc_iobase;
789 u_char stat;
790 register int timo;
791
792 #ifdef KGDB
793 if (dev != kgdb_dev)
794 #endif
795 if (comconsinit == 0) {
796 (void) cominit(COMUNIT(dev), comdefaultrate);
797 comconsinit = 1;
798 }
799 /* wait for any pending transmission to finish */
800 timo = 50000;
801 while (((stat = inb(iobase + com_lsr)) & LSR_TXRDY) == 0 && --timo)
802 ;
803 outb(iobase + com_data, c);
804 /* wait for this transmission to complete */
805 timo = 1500000;
806 while (((stat = inb(iobase + com_lsr)) & LSR_TXRDY) == 0 && --timo)
807 ;
808 /* clear any interrupts generated by this transmission */
809 stat = inb(iobase + com_iir);
810 splx(s);
811 }
812