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