minor wording updates
[unix-history] / usr / src / sys / hp / dev / dca.c
CommitLineData
60f56dfc
KM
1/*
2 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 *
7b7da76f 7 * @(#)dca.c 7.16 (Berkeley) %G%
60f56dfc
KM
8 */
9
10#include "dca.h"
11#if NDCA > 0
12/*
7b7da76f
MH
13 * Driver for National Semiconductor INS8250/NS16550AF/WD16C552 UARTs.
14 * Includes:
15 * 98626/98644/internal serial interface on hp300/hp400
16 * internal serial ports on hp700
17 *
18 * N.B. On the hp700, there is a "secret bit" with undocumented behavior.
19 * The third bit of the Modem Control Register (MCR_IEN == 0x08) must be
20 * set to enable interrupts.
60f56dfc 21 */
b28b3a13
KB
22#include "sys/param.h"
23#include "sys/systm.h"
24#include "sys/ioctl.h"
2723e1ed 25#include "sys/proc.h"
2d32402a 26#include "sys/tty.h"
b28b3a13
KB
27#include "sys/conf.h"
28#include "sys/file.h"
29#include "sys/uio.h"
30#include "sys/kernel.h"
31#include "sys/syslog.h"
60f56dfc 32
7b7da76f 33#include "hp/dev/device.h"
60f56dfc 34#include "dcareg.h"
7b7da76f 35
2723e1ed 36#include "machine/cpu.h"
7b7da76f
MH
37#ifdef hp300
38#include "../../hp300/hp300/isr.h"
39#endif
40#ifdef hp700
41#include "machine/asp.h"
42#endif
60f56dfc
KM
43
44int dcaprobe();
45struct driver dcadriver = {
46 dcaprobe, "dca",
47};
48
ed5ecb43
KM
49void dcastart();
50int dcaparam(), dcaintr();
60f56dfc
KM
51int dcasoftCAR;
52int dca_active;
9c7e9b26 53int dca_hasfifo;
60f56dfc 54int ndca = NDCA;
2723e1ed
MK
55#ifdef DCACONSOLE
56int dcaconsole = DCACONSOLE;
57#else
60f56dfc 58int dcaconsole = -1;
2723e1ed
MK
59#endif
60int dcaconsinit;
60f56dfc 61int dcadefaultrate = TTYDEF_SPEED;
2723e1ed 62int dcamajor;
60f56dfc
KM
63struct dcadevice *dca_addr[NDCA];
64struct tty dca_tty[NDCA];
7b7da76f 65#ifdef hp300
60f56dfc 66struct isr dcaisr[NDCA];
7b7da76f 67#endif
60f56dfc
KM
68
69struct speedtab dcaspeedtab[] = {
70 0, 0,
71 50, DCABRD(50),
72 75, DCABRD(75),
73 110, DCABRD(110),
74 134, DCABRD(134),
75 150, DCABRD(150),
76 200, DCABRD(200),
77 300, DCABRD(300),
78 600, DCABRD(600),
79 1200, DCABRD(1200),
80 1800, DCABRD(1800),
81 2400, DCABRD(2400),
82 4800, DCABRD(4800),
83 9600, DCABRD(9600),
84 19200, DCABRD(19200),
85 38400, DCABRD(38400),
86 -1, -1
87};
88
60f56dfc 89#ifdef KGDB
2723e1ed
MK
90#include "machine/remote-sl.h"
91
05d25f26 92extern dev_t kgdb_dev;
60f56dfc
KM
93extern int kgdb_rate;
94extern int kgdb_debug_init;
95#endif
96
97#define UNIT(x) minor(x)
98
9c7e9b26
MH
99#ifdef DEBUG
100long fifoin[17];
101long fifoout[17];
102long dcaintrcount[16];
103long dcamintcount[16];
104#endif
105
60f56dfc
KM
106dcaprobe(hd)
107 register struct hp_device *hd;
108{
109 register struct dcadevice *dca;
110 register int unit;
111
112 dca = (struct dcadevice *)hd->hp_addr;
7b7da76f
MH
113#ifdef hp300
114 if (dca->dca_id != DCAID0 &&
115 dca->dca_id != DCAREMID0 &&
116 dca->dca_id != DCAID1 &&
117 dca->dca_id != DCAREMID1)
60f56dfc 118 return (0);
7b7da76f 119#endif
60f56dfc
KM
120 unit = hd->hp_unit;
121 if (unit == dcaconsole)
122 DELAY(100000);
7b7da76f
MH
123#ifdef hp300
124 dca->dca_reset = 0xFF;
60f56dfc 125 DELAY(100);
7b7da76f 126#endif
60f56dfc 127
9c7e9b26
MH
128 /* look for a NS 16550AF UART with FIFOs */
129 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
130 DELAY(100);
131 if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK)
132 dca_hasfifo |= 1 << unit;
133
7b7da76f
MH
134 dca_addr[unit] = dca;
135#ifdef hp300
60f56dfc
KM
136 hd->hp_ipl = DCAIPL(dca->dca_ic);
137 dcaisr[unit].isr_ipl = hd->hp_ipl;
138 dcaisr[unit].isr_arg = unit;
139 dcaisr[unit].isr_intr = dcaintr;
60f56dfc 140 isrlink(&dcaisr[unit]);
7b7da76f
MH
141#endif
142 dca_active |= 1 << unit;
143 if (hd->hp_flags)
144 dcasoftCAR |= (1 << unit);
60f56dfc 145#ifdef KGDB
2723e1ed 146 if (kgdb_dev == makedev(dcamajor, unit)) {
60f56dfc 147 if (dcaconsole == unit)
05d25f26 148 kgdb_dev = NODEV; /* can't debug over console port */
60f56dfc 149 else {
2723e1ed 150 (void) dcainit(unit, kgdb_rate);
05d25f26 151 dcaconsinit = 1; /* don't re-init in dcaputc */
60f56dfc 152 if (kgdb_debug_init) {
2723e1ed
MK
153 /*
154 * Print prefix of device name,
155 * let kgdb_connect print the rest.
156 */
157 printf("dca%d: ", unit);
158 kgdb_connect(1);
60f56dfc
KM
159 } else
160 printf("dca%d: kgdb enabled\n", unit);
161 }
162 }
163#endif
7b7da76f 164#ifdef hp300
60f56dfc 165 dca->dca_ic = IC_IE;
7b7da76f 166#endif
60f56dfc 167 /*
2723e1ed
MK
168 * Need to reset baud rate, etc. of next print so reset dcaconsinit.
169 * Also make sure console is always "hardwired."
60f56dfc
KM
170 */
171 if (unit == dcaconsole) {
2723e1ed 172 dcaconsinit = 0;
60f56dfc
KM
173 dcasoftCAR |= (1 << unit);
174 }
175 return (1);
176}
177
2723e1ed
MK
178/* ARGSUSED */
179#ifdef __STDC__
180dcaopen(dev_t dev, int flag, int mode, struct proc *p)
181#else
182dcaopen(dev, flag, mode, p)
60f56dfc 183 dev_t dev;
2723e1ed
MK
184 int flag, mode;
185 struct proc *p;
186#endif
60f56dfc
KM
187{
188 register struct tty *tp;
189 register int unit;
037e7e94 190 int error = 0;
60f56dfc
KM
191
192 unit = UNIT(dev);
193 if (unit >= NDCA || (dca_active & (1 << unit)) == 0)
194 return (ENXIO);
195 tp = &dca_tty[unit];
196 tp->t_oproc = dcastart;
197 tp->t_param = dcaparam;
198 tp->t_dev = dev;
199 if ((tp->t_state & TS_ISOPEN) == 0) {
c98f3d99 200 tp->t_state |= TS_WOPEN;
60f56dfc 201 ttychars(tp);
2723e1ed
MK
202 if (tp->t_ispeed == 0) {
203 tp->t_iflag = TTYDEF_IFLAG;
204 tp->t_oflag = TTYDEF_OFLAG;
205 tp->t_cflag = TTYDEF_CFLAG;
206 tp->t_lflag = TTYDEF_LFLAG;
207 tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
208 }
60f56dfc
KM
209 dcaparam(tp, &tp->t_termios);
210 ttsetwater(tp);
2723e1ed 211 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
60f56dfc
KM
212 return (EBUSY);
213 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMSET);
214 if ((dcasoftCAR & (1 << unit)) || (dcamctl(dev, 0, DMGET) & MSR_DCD))
215 tp->t_state |= TS_CARR_ON;
216 (void) spltty();
23166e33 217 while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
60f56dfc
KM
218 (tp->t_state & TS_CARR_ON) == 0) {
219 tp->t_state |= TS_WOPEN;
23166e33
MH
220 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
221 ttopen, 0))
222 break;
60f56dfc
KM
223 }
224 (void) spl0();
23166e33
MH
225 if (error == 0)
226 error = (*linesw[tp->t_line].l_open)(dev, tp);
227 return (error);
60f56dfc
KM
228}
229
230/*ARGSUSED*/
f5daa13d 231dcaclose(dev, flag, mode, p)
60f56dfc 232 dev_t dev;
f5daa13d
MT
233 int flag, mode;
234 struct proc *p;
60f56dfc
KM
235{
236 register struct tty *tp;
237 register struct dcadevice *dca;
238 register int unit;
239
240 unit = UNIT(dev);
241 dca = dca_addr[unit];
242 tp = &dca_tty[unit];
f5daa13d 243 (*linesw[tp->t_line].l_close)(tp, flag);
60f56dfc
KM
244 dca->dca_cfcr &= ~CFCR_SBREAK;
245#ifdef KGDB
246 /* do not disable interrupts if debugging */
2723e1ed 247 if (dev != kgdb_dev)
60f56dfc
KM
248#endif
249 dca->dca_ier = 0;
05d25f26
MK
250 if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
251 (tp->t_state&TS_ISOPEN) == 0)
252 (void) dcamctl(dev, 0, DMSET);
60f56dfc 253 ttyclose(tp);
05d25f26 254 return (0);
60f56dfc
KM
255}
256
257dcaread(dev, uio, flag)
258 dev_t dev;
259 struct uio *uio;
260{
261 register struct tty *tp = &dca_tty[UNIT(dev)];
262
263 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
264}
265
266dcawrite(dev, uio, flag)
267 dev_t dev;
268 struct uio *uio;
269{
270 int unit = UNIT(dev);
271 register struct tty *tp = &dca_tty[unit];
7b7da76f 272 extern struct tty *constty;
60f56dfc 273
fdf2ec5d
KM
274 /*
275 * (XXX) We disallow virtual consoles if the physical console is
276 * a serial port. This is in case there is a display attached that
277 * is not the console. In that situation we don't need/want the X
278 * server taking over the console.
279 */
280 if (constty && unit == dcaconsole)
281 constty = NULL;
60f56dfc
KM
282 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
283}
284
285dcaintr(unit)
286 register int unit;
287{
288 register struct dcadevice *dca;
05a2e58f
MH
289 register u_char code;
290 register struct tty *tp;
60f56dfc
KM
291
292 dca = dca_addr[unit];
7b7da76f
MH
293#ifdef hp300
294 if ((dca->dca_ic & (IC_IR|IC_IE)) != (IC_IR|IC_IE))
05d25f26 295 return (0);
7b7da76f 296#endif
05a2e58f
MH
297 while (1) {
298 code = dca->dca_iir;
9c7e9b26
MH
299#ifdef DEBUG
300 dcaintrcount[code & IIR_IMASK]++;
301#endif
302 switch (code & IIR_IMASK) {
05a2e58f
MH
303 case IIR_NOPEND:
304 return (1);
9c7e9b26 305 case IIR_RXTOUT:
05a2e58f
MH
306 case IIR_RXRDY:
307 /* do time-critical read in-line */
308 tp = &dca_tty[unit];
9c7e9b26
MH
309/*
310 * Process a received byte. Inline for speed...
311 */
05a2e58f 312#ifdef KGDB
9c7e9b26
MH
313#define RCVBYTE() \
314 code = dca->dca_data; \
315 if ((tp->t_state & TS_ISOPEN) == 0) { \
05d25f26
MK
316 if (code == FRAME_END && \
317 kgdb_dev == makedev(dcamajor, unit)) \
9c7e9b26
MH
318 kgdb_connect(0); /* trap into kgdb */ \
319 } else \
320 (*linesw[tp->t_line].l_rint)(code, tp)
321#else
322#define RCVBYTE() \
323 code = dca->dca_data; \
324 if ((tp->t_state & TS_ISOPEN) != 0) \
325 (*linesw[tp->t_line].l_rint)(code, tp)
05a2e58f 326#endif
9c7e9b26
MH
327 RCVBYTE();
328 if (dca_hasfifo & (1 << unit)) {
329#ifdef DEBUG
330 register int fifocnt = 1;
331#endif
332 while ((code = dca->dca_lsr) & LSR_RCV_MASK) {
333 if (code == LSR_RXRDY) {
334 RCVBYTE();
335 } else
336 dcaeint(unit, code, dca);
337#ifdef DEBUG
338 fifocnt++;
339#endif
340 }
341#ifdef DEBUG
342 if (fifocnt > 16)
343 fifoin[0]++;
344 else
345 fifoin[fifocnt]++;
346#endif
347 }
05a2e58f
MH
348 break;
349 case IIR_TXRDY:
350 tp = &dca_tty[unit];
351 tp->t_state &=~ (TS_BUSY|TS_FLUSH);
352 if (tp->t_line)
353 (*linesw[tp->t_line].l_start)(tp);
354 else
355 dcastart(tp);
356 break;
357 case IIR_RLS:
9c7e9b26 358 dcaeint(unit, dca->dca_lsr, dca);
05a2e58f
MH
359 break;
360 default:
361 if (code & IIR_NOPEND)
362 return (1);
363 log(LOG_WARNING, "dca%d: weird interrupt: 0x%x\n",
364 unit, code);
365 /* fall through */
366 case IIR_MLSC:
60f56dfc 367 dcamint(unit, dca);
05a2e58f
MH
368 break;
369 }
60f56dfc 370 }
60f56dfc
KM
371}
372
9c7e9b26
MH
373dcaeint(unit, stat, dca)
374 register int unit, stat;
60f56dfc
KM
375 register struct dcadevice *dca;
376{
377 register struct tty *tp;
9c7e9b26 378 register int c;
60f56dfc
KM
379
380 tp = &dca_tty[unit];
05a2e58f 381 c = dca->dca_data;
60f56dfc
KM
382 if ((tp->t_state & TS_ISOPEN) == 0) {
383#ifdef KGDB
384 /* we don't care about parity errors */
385 if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
2723e1ed
MK
386 kgdb_dev == makedev(dcamajor, unit) && c == FRAME_END)
387 kgdb_connect(0); /* trap into kgdb */
60f56dfc
KM
388#endif
389 return;
390 }
391 if (stat & (LSR_BI | LSR_FE))
392 c |= TTY_FE;
393 else if (stat & LSR_PE)
394 c |= TTY_PE;
395 else if (stat & LSR_OE)
396 log(LOG_WARNING, "dca%d: silo overflow\n", unit);
397 (*linesw[tp->t_line].l_rint)(c, tp);
398}
399
60f56dfc
KM
400dcamint(unit, dca)
401 register int unit;
402 register struct dcadevice *dca;
403{
404 register struct tty *tp;
7b7da76f 405 register u_char stat;
60f56dfc
KM
406
407 tp = &dca_tty[unit];
408 stat = dca->dca_msr;
9c7e9b26
MH
409#ifdef DEBUG
410 dcamintcount[stat & 0xf]++;
411#endif
05a2e58f 412 if ((stat & MSR_DDCD) && (dcasoftCAR & (1 << unit)) == 0) {
60f56dfc 413 if (stat & MSR_DCD)
05a2e58f 414 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
60f56dfc
KM
415 else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
416 dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
05a2e58f
MH
417 } else if ((stat & MSR_DCTS) && (tp->t_state & TS_ISOPEN) &&
418 (tp->t_flags & CRTSCTS)) {
419 /* the line is up and we want to do rts/cts flow control */
420 if (stat & MSR_CTS) {
421 tp->t_state &=~ TS_TTSTOP;
422 ttstart(tp);
423 } else
424 tp->t_state |= TS_TTSTOP;
60f56dfc
KM
425 }
426}
427
9aceb128 428dcaioctl(dev, cmd, data, flag, p)
60f56dfc 429 dev_t dev;
9aceb128 430 int cmd;
60f56dfc 431 caddr_t data;
9aceb128
KM
432 int flag;
433 struct proc *p;
60f56dfc
KM
434{
435 register struct tty *tp;
436 register int unit = UNIT(dev);
437 register struct dcadevice *dca;
438 register int error;
439
440 tp = &dca_tty[unit];
9aceb128 441 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
60f56dfc
KM
442 if (error >= 0)
443 return (error);
444 error = ttioctl(tp, cmd, data, flag);
445 if (error >= 0)
446 return (error);
447
448 dca = dca_addr[unit];
449 switch (cmd) {
450
451 case TIOCSBRK:
452 dca->dca_cfcr |= CFCR_SBREAK;
453 break;
454
455 case TIOCCBRK:
456 dca->dca_cfcr &= ~CFCR_SBREAK;
457 break;
458
459 case TIOCSDTR:
460 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIS);
461 break;
462
463 case TIOCCDTR:
464 (void) dcamctl(dev, MCR_DTR | MCR_RTS, DMBIC);
465 break;
466
467 case TIOCMSET:
468 (void) dcamctl(dev, *(int *)data, DMSET);
469 break;
470
471 case TIOCMBIS:
472 (void) dcamctl(dev, *(int *)data, DMBIS);
473 break;
474
475 case TIOCMBIC:
476 (void) dcamctl(dev, *(int *)data, DMBIC);
477 break;
478
479 case TIOCMGET:
480 *(int *)data = dcamctl(dev, 0, DMGET);
481 break;
482
483 default:
484 return (ENOTTY);
485 }
486 return (0);
487}
488
489dcaparam(tp, t)
490 register struct tty *tp;
491 register struct termios *t;
492{
493 register struct dcadevice *dca;
494 register int cfcr, cflag = t->c_cflag;
495 int unit = UNIT(tp->t_dev);
496 int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
497
498 /* check requested parameters */
499 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
05d25f26 500 return (EINVAL);
60f56dfc
KM
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 dca = dca_addr[unit];
507 dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
7b7da76f
MH
508#ifdef hp700
509 dca->dca_mcr |= MCR_IEN;
510#endif
60f56dfc
KM
511 if (ospeed == 0) {
512 (void) dcamctl(unit, 0, DMSET); /* hang up line */
05d25f26 513 return (0);
60f56dfc
KM
514 }
515 dca->dca_cfcr |= CFCR_DLAB;
516 dca->dca_data = ospeed & 0xFF;
517 dca->dca_ier = ospeed >> 8;
518 switch (cflag&CSIZE) {
519 case CS5:
520 cfcr = CFCR_5BITS; break;
521 case CS6:
522 cfcr = CFCR_6BITS; break;
523 case CS7:
524 cfcr = CFCR_7BITS; break;
525 case CS8:
526 cfcr = CFCR_8BITS; break;
527 }
528 if (cflag&PARENB) {
529 cfcr |= CFCR_PENAB;
530 if ((cflag&PARODD) == 0)
531 cfcr |= CFCR_PEVEN;
532 }
533 if (cflag&CSTOPB)
534 cfcr |= CFCR_STOPB;
535 dca->dca_cfcr = cfcr;
9c7e9b26
MH
536 if (dca_hasfifo & (1 << unit))
537 dca->dca_fifo = FIFO_ENABLE | FIFO_TRIGGER_14;
05d25f26 538 return (0);
60f56dfc
KM
539}
540
ed5ecb43 541void
60f56dfc
KM
542dcastart(tp)
543 register struct tty *tp;
544{
545 register struct dcadevice *dca;
546 int s, unit, c;
547
548 unit = UNIT(tp->t_dev);
549 dca = dca_addr[unit];
550 s = spltty();
05a2e58f 551 if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
60f56dfc
KM
552 goto out;
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 }
2d32402a 558 selwakeup(&tp->t_wsel);
60f56dfc
KM
559 }
560 if (tp->t_outq.c_cc == 0)
561 goto out;
05a2e58f
MH
562 if (dca->dca_lsr & LSR_TXRDY) {
563 c = getc(&tp->t_outq);
564 tp->t_state |= TS_BUSY;
565 dca->dca_data = c;
9c7e9b26
MH
566 if (dca_hasfifo & (1 << unit)) {
567 for (c = 1; c < 16 && tp->t_outq.c_cc; ++c)
568 dca->dca_data = getc(&tp->t_outq);
569#ifdef DEBUG
570 if (c > 16)
571 fifoout[0]++;
572 else
573 fifoout[c]++;
574#endif
575 }
05a2e58f 576 }
60f56dfc
KM
577out:
578 splx(s);
579}
580
581/*
582 * Stop output on a line.
583 */
584/*ARGSUSED*/
585dcastop(tp, flag)
586 register struct tty *tp;
587{
588 register int s;
589
590 s = spltty();
591 if (tp->t_state & TS_BUSY) {
592 if ((tp->t_state&TS_TTSTOP)==0)
593 tp->t_state |= TS_FLUSH;
594 }
595 splx(s);
596}
597
598dcamctl(dev, bits, how)
599 dev_t dev;
600 int bits, how;
601{
602 register struct dcadevice *dca;
603 register int unit;
604 int s;
605
606 unit = UNIT(dev);
607 dca = dca_addr[unit];
7b7da76f
MH
608#ifdef hp700
609 /*
610 * Always make sure MCR_IEN is set (unless setting to 0)
611 */
612#ifdef KGDB
613 if (how == DMSET && kgdb_dev == makedev(dcamajor, unit))
614 bits |= MCR_IEN;
615 else
616#endif
617 if (how == DMBIS || (how == DMSET && bits))
618 bits |= MCR_IEN;
619 else if (how == DMBIC)
620 bits &= ~MCR_IEN;
621#endif
60f56dfc
KM
622 s = spltty();
623 switch (how) {
624
625 case DMSET:
626 dca->dca_mcr = bits;
627 break;
628
629 case DMBIS:
630 dca->dca_mcr |= bits;
631 break;
632
633 case DMBIC:
634 dca->dca_mcr &= ~bits;
635 break;
636
637 case DMGET:
638 bits = dca->dca_msr;
639 break;
640 }
641 (void) splx(s);
05d25f26 642 return (bits);
60f56dfc
KM
643}
644
645/*
646 * Following are all routines needed for DCA to act as console
647 */
7b7da76f 648#include "hp/dev/cons.h"
60f56dfc
KM
649
650dcacnprobe(cp)
651 struct consdev *cp;
652{
9c7e9b26 653 int unit;
2723e1ed
MK
654
655 /* locate the major number */
656 for (dcamajor = 0; dcamajor < nchrdev; dcamajor++)
657 if (cdevsw[dcamajor].d_open == dcaopen)
658 break;
60f56dfc
KM
659
660 /* XXX: ick */
661 unit = CONUNIT;
7b7da76f 662#ifdef hp300
9c7e9b26 663 dca_addr[CONUNIT] = (struct dcadevice *) sctova(CONSCODE);
60f56dfc
KM
664
665 /* make sure hardware exists */
666 if (badaddr((short *)dca_addr[unit])) {
667 cp->cn_pri = CN_DEAD;
668 return;
669 }
7b7da76f
MH
670#endif
671#ifdef hp700
672 dca_addr[CONUNIT] = CONPORT;
673#endif
60f56dfc 674
60f56dfc 675 /* initialize required fields */
2723e1ed 676 cp->cn_dev = makedev(dcamajor, unit);
60f56dfc 677 cp->cn_tp = &dca_tty[unit];
7b7da76f
MH
678#ifdef hp300
679 switch (dca_addr[unit]->dca_id) {
60f56dfc
KM
680 case DCAID0:
681 case DCAID1:
682 cp->cn_pri = CN_NORMAL;
683 break;
684 case DCAREMID0:
685 case DCAREMID1:
686 cp->cn_pri = CN_REMOTE;
687 break;
688 default:
689 cp->cn_pri = CN_DEAD;
690 break;
691 }
7b7da76f
MH
692#endif
693#ifdef hp700
694 cp->cn_pri = CN_NORMAL;
695#endif
2723e1ed 696 /*
9c7e9b26 697 * If dcaconsole is initialized, raise our priority.
2723e1ed
MK
698 */
699 if (dcaconsole == unit)
700 cp->cn_pri = CN_REMOTE;
9c7e9b26 701#ifdef KGDB
2723e1ed
MK
702 if (major(kgdb_dev) == 1) /* XXX */
703 kgdb_dev = makedev(dcamajor, minor(kgdb_dev));
9c7e9b26 704#endif
60f56dfc
KM
705}
706
707dcacninit(cp)
708 struct consdev *cp;
709{
710 int unit = UNIT(cp->cn_dev);
711
2723e1ed 712 dcainit(unit, dcadefaultrate);
60f56dfc 713 dcaconsole = unit;
2723e1ed 714 dcaconsinit = 1;
60f56dfc
KM
715}
716
2723e1ed
MK
717dcainit(unit, rate)
718 int unit, rate;
60f56dfc
KM
719{
720 register struct dcadevice *dca;
2723e1ed 721 int s;
60f56dfc
KM
722 short stat;
723
724#ifdef lint
725 stat = unit; if (stat) return;
726#endif
727 dca = dca_addr[unit];
728 s = splhigh();
7b7da76f
MH
729#ifdef hp300
730 dca->dca_reset = 0xFF;
60f56dfc
KM
731 DELAY(100);
732 dca->dca_ic = IC_IE;
7b7da76f 733#endif
60f56dfc 734 dca->dca_cfcr = CFCR_DLAB;
2723e1ed 735 rate = ttspeedtab(rate, dcaspeedtab);
60f56dfc
KM
736 dca->dca_data = rate & 0xFF;
737 dca->dca_ier = rate >> 8;
738 dca->dca_cfcr = CFCR_8BITS;
739 dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
7b7da76f
MH
740#ifdef hp700
741 dca->dca_mcr |= MCR_IEN;
742#endif
9c7e9b26 743 dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
7b7da76f 744 DELAY(100);
60f56dfc
KM
745 stat = dca->dca_iir;
746 splx(s);
747}
748
749dcacngetc(dev)
750{
751 register struct dcadevice *dca = dca_addr[UNIT(dev)];
7b7da76f 752 register u_char stat;
60f56dfc
KM
753 int c, s;
754
755#ifdef lint
05d25f26 756 stat = dev; if (stat) return (0);
60f56dfc
KM
757#endif
758 s = splhigh();
759 while (((stat = dca->dca_lsr) & LSR_RXRDY) == 0)
760 ;
761 c = dca->dca_data;
762 stat = dca->dca_iir;
763 splx(s);
05d25f26 764 return (c);
60f56dfc
KM
765}
766
767/*
768 * Console kernel output character routine.
769 */
770dcacnputc(dev, c)
771 dev_t dev;
772 register int c;
773{
774 register struct dcadevice *dca = dca_addr[UNIT(dev)];
775 register int timo;
7b7da76f 776 register u_char stat;
60f56dfc
KM
777 int s = splhigh();
778
779#ifdef lint
780 stat = dev; if (stat) return;
2723e1ed
MK
781#endif
782 if (dcaconsinit == 0) {
783 (void) dcainit(UNIT(dev), dcadefaultrate);
784 dcaconsinit = 1;
60f56dfc
KM
785 }
786 /* wait for any pending transmission to finish */
787 timo = 50000;
788 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
789 ;
790 dca->dca_data = c;
791 /* wait for this transmission to complete */
792 timo = 1500000;
793 while (((stat = dca->dca_lsr) & LSR_TXRDY) == 0 && --timo)
794 ;
7b7da76f
MH
795 /*
796 * If the "normal" interface was busy transfering a character
797 * we must let our interrupt through to keep things moving.
798 * Otherwise, we clear the interrupt that we have caused.
799 */
800 if ((dca_tty[UNIT(dev)].t_state & TS_BUSY) == 0)
801 stat = dca->dca_iir;
60f56dfc
KM
802 splx(s);
803}
804#endif