dcm.c revision 1.20 1 /* $NetBSD: dcm.c,v 1.20 1995/12/02 18:18:50 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1995 Jason R. Thorpe. All rights reserved.
5 * Copyright (c) 1988 University of Utah.
6 * Copyright (c) 1982, 1986, 1990, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * the Systems Programming Group of the University of Utah Computer
11 * Science Department.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. All advertising materials mentioning features or use of this software
22 * must display the following acknowledgement:
23 * This product includes software developed by the University of
24 * California, Berkeley and its contributors.
25 * 4. Neither the name of the University nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * from Utah: $Hdr: dcm.c 1.29 92/01/21$
42 *
43 * @(#)dcm.c 8.4 (Berkeley) 1/12/94
44 */
45
46 /*
47 * TODO:
48 * Timeouts
49 * Test console support.
50 */
51
52 #include "dcm.h"
53 #if NDCM > 0
54 /*
55 * 98642/MUX
56 */
57 #include <sys/param.h>
58 #include <sys/systm.h>
59 #include <sys/ioctl.h>
60 #include <sys/proc.h>
61 #include <sys/tty.h>
62 #include <sys/conf.h>
63 #include <sys/file.h>
64 #include <sys/uio.h>
65 #include <sys/kernel.h>
66 #include <sys/syslog.h>
67 #include <sys/time.h>
68
69 #include <machine/cpu.h>
70
71 #include <hp300/dev/device.h>
72 #include <hp300/dev/dcmreg.h>
73 #include <hp300/hp300/isr.h>
74
75 #ifndef DEFAULT_BAUD_RATE
76 #define DEFAULT_BAUD_RATE 9600
77 #endif
78
79 int dcmmatch(), dcmintr(), dcmparam();
80 void dcmattach(), dcmstart();
81 struct driver dcmdriver = {
82 dcmmatch, dcmattach, "dcm",
83 };
84
85 struct speedtab dcmspeedtab[] = {
86 0, BR_0,
87 50, BR_50,
88 75, BR_75,
89 110, BR_110,
90 134, BR_134,
91 150, BR_150,
92 300, BR_300,
93 600, BR_600,
94 1200, BR_1200,
95 1800, BR_1800,
96 2400, BR_2400,
97 4800, BR_4800,
98 9600, BR_9600,
99 19200, BR_19200,
100 38400, BR_38400,
101 -1, -1
102 };
103
104 /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */
105 #define DCM_USPERCH(s) (10000000 / (s))
106
107 /*
108 * Per board interrupt scheme. 16.7ms is the polling interrupt rate
109 * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms).
110 */
111 #define DIS_TIMER 0
112 #define DIS_PERCHAR 1
113 #define DIS_RESET 2
114
115 int dcmistype = -1; /* -1 == dynamic, 0 == timer, 1 == perchar */
116 int dcminterval = 5; /* interval (secs) between checks */
117 struct dcmischeme {
118 int dis_perchar; /* non-zero if interrupting per char */
119 long dis_time; /* last time examined */
120 int dis_intr; /* recv interrupts during last interval */
121 int dis_char; /* characters read during last interval */
122 };
123
124 /*
125 * Console support
126 */
127 #ifdef DCMCONSOLE
128 int dcmconsole = DCMCONSOLE;
129 #else
130 int dcmconsole = -1;
131 #endif
132 int dcmconsinit;
133 int dcmdefaultrate = DEFAULT_BAUD_RATE;
134 int dcmconbrdbusy = 0;
135 int dcmmajor;
136
137 #ifdef KGDB
138 /*
139 * Kernel GDB support
140 */
141 #include <machine/remote-sl.h>
142
143 extern dev_t kgdb_dev;
144 extern int kgdb_rate;
145 extern int kgdb_debug_init;
146 #endif
147
148 /* #define DCMSTATS */
149
150 #ifdef DEBUG
151 int dcmdebug = 0x0;
152 #define DDB_SIOERR 0x01
153 #define DDB_PARAM 0x02
154 #define DDB_INPUT 0x04
155 #define DDB_OUTPUT 0x08
156 #define DDB_INTR 0x10
157 #define DDB_IOCTL 0x20
158 #define DDB_INTSCHM 0x40
159 #define DDB_MODEM 0x80
160 #define DDB_OPENCLOSE 0x100
161 #endif
162
163 #ifdef DCMSTATS
164 #define DCMRBSIZE 94
165 #define DCMXBSIZE 24
166
167 struct dcmstats {
168 long xints; /* # of xmit ints */
169 long xchars; /* # of xmit chars */
170 long xempty; /* times outq is empty in dcmstart */
171 long xrestarts; /* times completed while xmitting */
172 long rints; /* # of recv ints */
173 long rchars; /* # of recv chars */
174 long xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */
175 long rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */
176 };
177 #endif
178
179 #define DCMUNIT(x) minor(x)
180 #define DCMBOARD(x) (((x) >> 2) & 0x3f)
181 #define DCMPORT(x) ((x) & 3)
182
183 /*
184 * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux,
185 * the distribution panel uses "HP DCE" conventions. If requested via
186 * the device flags, we swap the inputs to something closer to normal DCE,
187 * allowing a straight-through cable to a DTE or a reversed cable
188 * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected;
189 * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect
190 * DSR or make RTS work, though). The following gives the full
191 * details of a cable from this mux panel to a modem:
192 *
193 * HP modem
194 * name pin pin name
195 * HP inputs:
196 * "Rx" 2 3 Tx
197 * CTS 4 5 CTS (only needed for CCTS_OFLOW)
198 * DCD 20 8 DCD
199 * "DSR" 9 6 DSR (unneeded)
200 * RI 22 22 RI (unneeded)
201 *
202 * HP outputs:
203 * "Tx" 3 2 Rx
204 * "DTR" 6 not connected
205 * "RTS" 8 20 DTR
206 * "SR" 23 4 RTS (often not needed)
207 */
208 #define hp2dce_in(ibits) (iconv[(ibits) & 0xf])
209 static char iconv[16] = {
210 0, MI_DM, MI_CTS, MI_CTS|MI_DM,
211 MI_CD, MI_CD|MI_DM, MI_CD|MI_CTS, MI_CD|MI_CTS|MI_DM,
212 MI_RI, MI_RI|MI_DM, MI_RI|MI_CTS, MI_RI|MI_CTS|MI_DM,
213 MI_RI|MI_CD, MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS,
214 MI_RI|MI_CD|MI_CTS|MI_DM
215 };
216
217 #define NDCMPORT 4 /* XXX what about 8-port cards? */
218
219 struct dcm_softc {
220 struct hp_device *sc_hd; /* device info */
221 struct dcmdevice *sc_dcm; /* pointer to hardware */
222 struct tty *sc_tty[NDCMPORT]; /* our tty instances */
223 struct modemreg *sc_modem[NDCMPORT]; /* modem control */
224 char sc_mcndlast[NDCMPORT]; /* XXX last modem status for port */
225 struct isr sc_isr; /* interrupt handler */
226 short sc_softCAR; /* mask of ports with soft-carrier */
227 struct dcmischeme sc_scheme; /* interrupt scheme for board */
228
229 /*
230 * Mask of soft-carrier bits in config flags.
231 * XXX What about 8-port cards?
232 */
233 #define DCM_SOFTCAR 0x0000000f
234
235 int sc_flags; /* misc. configuration info */
236
237 /*
238 * Bits for sc_flags
239 */
240 #define DCM_ACTIVE 0x00000001 /* indicates board is alive */
241 #define DCM_STDDCE 0x00000010 /* re-map DCE to standard */
242 #define DCM_FLAGMASK (DCM_STDDCE) /* mask of valid bits in config flags */
243
244 #ifdef DCMSTATS
245 struct dcmstats sc_stats; /* metrics gathering */
246 #endif
247 } dcm_softc[NDCM];
248
249 int
250 dcmmatch(hd)
251 register struct hp_device *hd;
252 {
253 struct dcm_softc *sc = &dcm_softc[hd->hp_unit];
254 struct dcmdevice *dcm;
255 int i, timo = 0;
256 int s, brd, isconsole, mbits;
257
258 dcm = (struct dcmdevice *)hd->hp_addr;
259 if ((dcm->dcm_rsid & 0x1f) != DCMID)
260 return (0);
261
262 brd = hd->hp_unit;
263 isconsole = (brd == DCMBOARD(dcmconsole));
264
265 /*
266 * XXX selected console device (CONSUNIT) as determined by
267 * dcmcnprobe does not agree with logical numbering imposed
268 * by the config file (i.e. lowest address DCM is not unit
269 * CONSUNIT). Don't recognize this card.
270 */
271 if (isconsole && (dcm != sc->sc_dcm))
272 return (0);
273
274 sc->sc_hd = hd;
275 hd->hp_ipl = DCMIPL(dcm->dcm_ic);
276
277 /*
278 * Empirically derived self-test magic
279 */
280 s = spltty();
281 dcm->dcm_rsid = DCMRS;
282 DELAY(50000); /* 5000 is not long enough */
283 dcm->dcm_rsid = 0;
284 dcm->dcm_ic = IC_IE;
285 dcm->dcm_cr = CR_SELFT;
286 while ((dcm->dcm_ic & IC_IR) == 0)
287 if (++timo == 20000)
288 return (0);
289 DELAY(50000) /* XXX why is this needed ???? */
290 while ((dcm->dcm_iir & IIR_SELFT) == 0)
291 if (++timo == 400000)
292 return (0);
293 DELAY(50000) /* XXX why is this needed ???? */
294 if (dcm->dcm_stcon != ST_OK) {
295 if (!isconsole)
296 printf("dcm%d: self test failed: %x\n",
297 brd, dcm->dcm_stcon);
298 return (0);
299 }
300 dcm->dcm_ic = IC_ID;
301 splx(s);
302
303 return (1);
304 }
305
306 void
307 dcmattach(hd)
308 register struct hp_device *hd;
309 {
310 struct dcm_softc *sc = &dcm_softc[hd->hp_unit];
311 struct dcmdevice *dcm;
312 int i, timo = 0;
313 int s, brd, isconsole, mbits;
314
315 dcm = sc->sc_dcm = (struct dcmdevice *)hd->hp_addr;
316
317 brd = hd->hp_unit;
318 isconsole = (brd == DCMBOARD(dcmconsole));
319
320 /* Extract configuration info from flags. */
321 sc->sc_softCAR = (hd->hp_flags & DCM_SOFTCAR);
322 sc->sc_flags = (hd->hp_flags & DCM_FLAGMASK);
323
324 /* Mark our unit as configured. */
325 sc->sc_flags |= DCM_ACTIVE;
326
327 /* Establish the interrupt handler. */
328 sc->sc_isr.isr_ipl = hd->hp_ipl;
329 sc->sc_isr.isr_arg = brd;
330 sc->sc_isr.isr_intr = dcmintr;
331 isrlink(&sc->sc_isr);
332
333 if (dcmistype == DIS_TIMER)
334 dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
335 else
336 dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
337
338 /* load pointers to modem control */
339 sc->sc_modem[0] = &dcm->dcm_modem0;
340 sc->sc_modem[1] = &dcm->dcm_modem1;
341 sc->sc_modem[2] = &dcm->dcm_modem2;
342 sc->sc_modem[3] = &dcm->dcm_modem3;
343
344 /* set DCD (modem) and CTS (flow control) on all ports */
345 if (sc->sc_flags & DCM_STDDCE)
346 mbits = hp2dce_in(MI_CD|MI_CTS);
347 else
348 mbits = MI_CD|MI_CTS;
349
350 for (i = 0; i < NDCMPORT; i++)
351 sc->sc_modem[i]->mdmmsk = mbits;
352
353 dcm->dcm_ic = IC_IE; /* turn all interrupts on */
354
355 /*
356 * Need to reset baud rate, etc. of next print so reset dcmconsole.
357 * Also make sure console is always "hardwired"
358 */
359 if (isconsole) {
360 dcmconsinit = 0;
361 sc->sc_softCAR |= (1 << DCMPORT(dcmconsole));
362 printf(": console on port %d\n", DCMPORT(dcmconsole));
363 } else
364 printf("\n");
365
366 #ifdef KGDB
367 if (major(kgdb_dev) == dcmmajor &&
368 DCMBOARD(DCMUNIT(kgdb_dev)) == brd) {
369 if (dcmconsole == DCMUNIT(kgdb_dev))
370 kgdb_dev = NODEV; /* can't debug over console port */
371 #ifndef KGDB_CHEAT
372 /*
373 * The following could potentially be replaced
374 * by the corresponding code in dcmcnprobe.
375 */
376 else {
377 (void) dcminit(kgdb_dev, kgdb_rate);
378 if (kgdb_debug_init) {
379 printf("%s port %d: ", sc->sc_hd->hp_xname,
380 DCMPORT(DCMUNIT(kgdb_dev)));
381 kgdb_connect(1);
382 } else
383 printf("%s port %d: kgdb enabled\n",
384 sc->sc_hd->hp_xname,
385 DCMPORT(DCMUNIT(kgdb_dev)));
386 }
387 /* end could be replaced */
388 #endif
389 }
390 #endif
391 }
392
393 /* ARGSUSED */
394 int
395 dcmopen(dev, flag, mode, p)
396 dev_t dev;
397 int flag, mode;
398 struct proc *p;
399 {
400 struct dcm_softc *sc;
401 struct tty *tp;
402 int unit, brd, port;
403 int error = 0, mbits, s;
404
405 unit = DCMUNIT(dev);
406 brd = DCMBOARD(unit);
407 port = DCMPORT(unit);
408
409 if ((brd >= NDCM) || (port >= NDCMPORT))
410 return (ENXIO);
411
412 sc = &dcm_softc[brd];
413 if ((sc->sc_flags & DCM_ACTIVE) == 0)
414 return (ENXIO);
415
416 if (sc->sc_tty[port] == NULL)
417 tp = sc->sc_tty[port] = ttymalloc();
418 else
419 tp = sc->sc_tty[port];
420
421 tp->t_oproc = dcmstart;
422 tp->t_param = dcmparam;
423 tp->t_dev = dev;
424
425 if ((tp->t_state & TS_ISOPEN) == 0) {
426 /*
427 * Sanity clause: reset the card on first open.
428 * The card might be left in an inconsistent state
429 * if the card memory is read inadvertently.
430 */
431 dcminit(dev, dcmdefaultrate);
432
433 tp->t_state |= TS_WOPEN;
434 ttychars(tp);
435 tp->t_iflag = TTYDEF_IFLAG;
436 tp->t_oflag = TTYDEF_OFLAG;
437 tp->t_cflag = TTYDEF_CFLAG;
438 tp->t_lflag = TTYDEF_LFLAG;
439 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
440
441 s = spltty();
442
443 (void) dcmparam(tp, &tp->t_termios);
444 ttsetwater(tp);
445 } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
446 return (EBUSY);
447 else
448 s = spltty();
449
450 /* Set modem control state. */
451 mbits = MO_ON;
452 if (sc->sc_flags & DCM_STDDCE)
453 mbits |= MO_SR; /* pin 23, could be used as RTS */
454
455 (void) dcmmctl(dev, mbits, DMSET); /* enable port */
456
457 /* Set soft-carrier if so configured. */
458 if ((sc->sc_softCAR & (1 << port)) ||
459 (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))
460 tp->t_state |= TS_CARR_ON;
461
462 #ifdef DEBUG
463 if (dcmdebug & DDB_MODEM)
464 printf("%s: dcmopen port %d softcarr %c\n",
465 sc->sc_hd->hp_xname, port,
466 (tp->t_state & TS_CARR_ON) ? '1' : '0');
467 #endif
468
469 /* Wait for carrier if necessary. */
470 if ((flag & O_NONBLOCK) == 0)
471 while ((tp->t_cflag & CLOCAL) == 0 &&
472 (tp->t_state & TS_CARR_ON) == 0) {
473 tp->t_state |= TS_WOPEN;
474 error = ttysleep(tp, (caddr_t)&tp->t_rawq,
475 TTIPRI | PCATCH, ttopen, 0);
476 if (error) {
477 splx(s);
478 return (error);
479 }
480 }
481
482 splx(s);
483
484 #ifdef DEBUG
485 if (dcmdebug & DDB_OPENCLOSE)
486 printf("%s port %d: dcmopen: st %x fl %x\n",
487 sc->sc_hd->hp_xname, port, tp->t_state, tp->t_flags);
488 #endif
489 if (error == 0)
490 error = (*linesw[tp->t_line].l_open)(dev, tp);
491
492 return (error);
493 }
494
495 /*ARGSUSED*/
496 int
497 dcmclose(dev, flag, mode, p)
498 dev_t dev;
499 int flag, mode;
500 struct proc *p;
501 {
502 int s, unit, board, port;
503 struct dcm_softc *sc;
504 struct tty *tp;
505
506 unit = DCMUNIT(dev);
507 board = DCMBOARD(unit);
508 port = DCMPORT(unit);
509
510 sc = &dcm_softc[board];
511 tp = sc->sc_tty[port];
512
513 (*linesw[tp->t_line].l_close)(tp, flag);
514
515 s = spltty();
516
517 if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
518 (tp->t_state & TS_ISOPEN) == 0)
519 (void) dcmmctl(dev, MO_OFF, DMSET);
520 #ifdef DEBUG
521 if (dcmdebug & DDB_OPENCLOSE)
522 printf("%s port %d: dcmclose: st %x fl %x\n",
523 sc->sc_hd->hp_xname, port, tp->t_state, tp->t_flags);
524 #endif
525 splx(s);
526 ttyclose(tp);
527 #if 0
528 ttyfree(tp);
529 sc->sc_tty[port] == NULL;
530 #endif
531 return (0);
532 }
533
534 int
535 dcmread(dev, uio, flag)
536 dev_t dev;
537 struct uio *uio;
538 int flag;
539 {
540 int unit, board, port;
541 struct dcm_softc *sc;
542 register struct tty *tp;
543
544 unit = DCMUNIT(dev);
545 board = DCMBOARD(unit);
546 port = DCMPORT(unit);
547
548 sc = &dcm_softc[board];
549 tp = sc->sc_tty[port];
550
551 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
552 }
553
554 int
555 dcmwrite(dev, uio, flag)
556 dev_t dev;
557 struct uio *uio;
558 int flag;
559 {
560 int unit, board, port;
561 struct dcm_softc *sc;
562 register struct tty *tp;
563
564 unit = DCMUNIT(dev);
565 board = DCMBOARD(unit);
566 port = DCMPORT(unit);
567
568 sc = &dcm_softc[board];
569 tp = sc->sc_tty[port];
570
571 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
572 }
573
574 struct tty *
575 dcmtty(dev)
576 dev_t dev;
577 {
578 int unit, board, port;
579 struct dcm_softc *sc;
580
581 unit = DCMUNIT(dev);
582 board = DCMBOARD(unit);
583 port = DCMPORT(unit);
584
585 sc = &dcm_softc[board];
586
587 return (sc->sc_tty[port]);
588 }
589
590 int
591 dcmintr(brd)
592 register int brd;
593 {
594 struct dcm_softc *sc = &dcm_softc[brd];
595 struct dcmdevice *dcm = sc->sc_dcm;
596 struct dcmischeme *dis = &sc->sc_scheme;
597 int code, i;
598 int pcnd[4], mcode, mcnd[4];
599
600 /*
601 * Do all guarded register accesses right off to minimize
602 * block out of hardware.
603 */
604 SEM_LOCK(dcm);
605 if ((dcm->dcm_ic & IC_IR) == 0) {
606 SEM_UNLOCK(dcm);
607 return (0);
608 }
609 for (i = 0; i < 4; i++) {
610 pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
611 dcm->dcm_icrtab[i].dcm_data = 0;
612 code = sc->sc_modem[i]->mdmin;
613 if (sc->sc_flags & DCM_STDDCE)
614 code = hp2dce_in(code);
615 mcnd[i] = code;
616 }
617 code = dcm->dcm_iir & IIR_MASK;
618 dcm->dcm_iir = 0; /* XXX doc claims read clears interrupt?! */
619 mcode = dcm->dcm_modemintr;
620 dcm->dcm_modemintr = 0;
621 SEM_UNLOCK(dcm);
622
623 #ifdef DEBUG
624 if (dcmdebug & DDB_INTR) {
625 printf("%s: dcmintr: iir %x pc %x/%x/%x/%x ",
626 sc->sc_hd->hp_xname, code, pcnd[0], pcnd[1],
627 pcnd[2], pcnd[3]);
628 printf("miir %x mc %x/%x/%x/%x\n",
629 mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);
630 }
631 #endif
632 if (code & IIR_TIMEO)
633 dcmrint(sc);
634 if (code & IIR_PORT0)
635 dcmpint(sc, 0, pcnd[0]);
636 if (code & IIR_PORT1)
637 dcmpint(sc, 1, pcnd[1]);
638 if (code & IIR_PORT2)
639 dcmpint(sc, 2, pcnd[2]);
640 if (code & IIR_PORT3)
641 dcmpint(sc, 3, pcnd[3]);
642 if (code & IIR_MODM) {
643 if (mcode == 0 || mcode & 0x1) /* mcode==0 -> 98642 board */
644 dcmmint(sc, 0, mcnd[0]);
645 if (mcode & 0x2)
646 dcmmint(sc, 1, mcnd[1]);
647 if (mcode & 0x4)
648 dcmmint(sc, 2, mcnd[2]);
649 if (mcode & 0x8)
650 dcmmint(sc, 3, mcnd[3]);
651 }
652
653 /*
654 * Chalk up a receiver interrupt if the timer running or one of
655 * the ports reports a special character interrupt.
656 */
657 if ((code & IIR_TIMEO) ||
658 ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))
659 dis->dis_intr++;
660 /*
661 * See if it is time to check/change the interrupt rate.
662 */
663 if (dcmistype < 0 &&
664 (i = time.tv_sec - dis->dis_time) >= dcminterval) {
665 /*
666 * If currently per-character and averaged over 70 interrupts
667 * per-second (66 is threshold of 600 baud) in last interval,
668 * switch to timer mode.
669 *
670 * XXX decay counts ala load average to avoid spikes?
671 */
672 if (dis->dis_perchar && dis->dis_intr > 70 * i)
673 dcmsetischeme(brd, DIS_TIMER);
674 /*
675 * If currently using timer and had more interrupts than
676 * received characters in the last interval, switch back
677 * to per-character. Note that after changing to per-char
678 * we must process any characters already in the queue
679 * since they may have arrived before the bitmap was setup.
680 *
681 * XXX decay counts?
682 */
683 else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {
684 dcmsetischeme(brd, DIS_PERCHAR);
685 dcmrint(sc);
686 }
687 dis->dis_intr = dis->dis_char = 0;
688 dis->dis_time = time.tv_sec;
689 }
690 return (1);
691 }
692
693 /*
694 * Port interrupt. Can be two things:
695 * First, it might be a special character (exception interrupt);
696 * Second, it may be a buffer empty (transmit interrupt);
697 */
698 dcmpint(sc, port, code)
699 struct dcm_softc *sc;
700 int port, code;
701 {
702
703 if (code & IT_SPEC)
704 dcmreadbuf(sc, port);
705 if (code & IT_TX)
706 dcmxint(sc, port);
707 }
708
709 dcmrint(sc)
710 struct dcm_softc *sc;
711 {
712 int port;
713
714 for (port = 0; port < NDCMPORT; port++)
715 dcmreadbuf(sc, port);
716 }
717
718 dcmreadbuf(sc, port)
719 struct dcm_softc *sc;
720 int port;
721 {
722 struct dcmdevice *dcm = sc->sc_dcm;
723 struct tty *tp = sc->sc_tty[port];
724 struct dcmpreg *pp = dcm_preg(dcm, port);
725 struct dcmrfifo *fifo;
726 int c, stat;
727 u_int head;
728 int nch = 0;
729 #ifdef DCMSTATS
730 struct dcmstats *dsp = &sc->sc_stats;
731
732 dsp->rints++;
733 #endif
734 if ((tp->t_state & TS_ISOPEN) == 0) {
735 #ifdef KGDB
736 if ((makedev(dcmmajor, minor(tp->t_dev)) == kgdb_dev) &&
737 (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
738 dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) {
739 pp->r_head = (head + 2) & RX_MASK;
740 kgdb_connect(0); /* trap into kgdb */
741 return;
742 }
743 #endif /* KGDB */
744 pp->r_head = pp->r_tail & RX_MASK;
745 return;
746 }
747
748 head = pp->r_head & RX_MASK;
749 fifo = &dcm->dcm_rfifos[3-port][head>>1];
750 /*
751 * XXX upper bound on how many chars we will take in one swallow?
752 */
753 while (head != (pp->r_tail & RX_MASK)) {
754 /*
755 * Get character/status and update head pointer as fast
756 * as possible to make room for more characters.
757 */
758 c = fifo->data_char;
759 stat = fifo->data_stat;
760 head = (head + 2) & RX_MASK;
761 pp->r_head = head;
762 fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];
763 nch++;
764
765 #ifdef DEBUG
766 if (dcmdebug & DDB_INPUT)
767 printf("%s port %d: dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n",
768 sc->sc_hd->hp_xname, port,
769 c&0xFF, c, stat&0xFF,
770 tp->t_flags, head, pp->r_tail);
771 #endif
772 /*
773 * Check for and handle errors
774 */
775 if (stat & RD_MASK) {
776 #ifdef DEBUG
777 if (dcmdebug & (DDB_INPUT|DDB_SIOERR))
778 printf("%s port %d: dcmreadbuf: err: c%x('%c') s%x\n",
779 sc->sc_hd->hp_xname, port,
780 stat, c&0xFF, c);
781 #endif
782 if (stat & (RD_BD | RD_FE))
783 c |= TTY_FE;
784 else if (stat & RD_PE)
785 c |= TTY_PE;
786 else if (stat & RD_OVF)
787 log(LOG_WARNING,
788 "%s port %d: silo overflow\n",
789 sc->sc_hd->hp_xname, port);
790 else if (stat & RD_OE)
791 log(LOG_WARNING,
792 "%s port %d: uart overflow\n",
793 sc->sc_hd->hp_xname, port);
794 }
795 (*linesw[tp->t_line].l_rint)(c, tp);
796 }
797 sc->sc_scheme.dis_char += nch;
798
799 #ifdef DCMSTATS
800 dsp->rchars += nch;
801 if (nch <= DCMRBSIZE)
802 dsp->rsilo[nch]++;
803 else
804 dsp->rsilo[DCMRBSIZE+1]++;
805 #endif
806 }
807
808 dcmxint(sc, port)
809 struct dcm_softc *sc;
810 int port;
811 {
812 struct tty *tp = sc->sc_tty[port];
813
814 tp->t_state &= ~TS_BUSY;
815 if (tp->t_state & TS_FLUSH)
816 tp->t_state &= ~TS_FLUSH;
817 (*linesw[tp->t_line].l_start)(tp);
818 }
819
820 dcmmint(sc, port, mcnd)
821 struct dcm_softc *sc;
822 int port, mcnd;
823 {
824 int delta;
825 struct tty *tp;
826 struct dcmdevice *dcm = sc->sc_dcm;
827
828 tp = sc->sc_tty[port];
829
830 #ifdef DEBUG
831 if (dcmdebug & DDB_MODEM)
832 printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n",
833 sc->sc_hd->hp_xname, port, mcnd, sc->sc_mcndlast[port]);
834 #endif
835 delta = mcnd ^ sc->sc_mcndlast[port];
836 sc->sc_mcndlast[port] = mcnd;
837 if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
838 (tp->t_flags & CCTS_OFLOW)) {
839 if (mcnd & MI_CTS) {
840 tp->t_state &= ~TS_TTSTOP;
841 ttstart(tp);
842 } else
843 tp->t_state |= TS_TTSTOP; /* inline dcmstop */
844 }
845 if (delta & MI_CD) {
846 if (mcnd & MI_CD)
847 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
848 else if ((sc->sc_softCAR & (1 << port)) == 0 &&
849 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
850 sc->sc_modem[port]->mdmout = MO_OFF;
851 SEM_LOCK(dcm);
852 dcm->dcm_modemchng |= (1 << port);
853 dcm->dcm_cr |= CR_MODM;
854 SEM_UNLOCK(dcm);
855 DELAY(10); /* time to change lines */
856 }
857 }
858 }
859
860 int
861 dcmioctl(dev, cmd, data, flag, p)
862 dev_t dev;
863 int cmd;
864 caddr_t data;
865 int flag;
866 struct proc *p;
867 {
868 struct dcm_softc *sc;
869 struct tty *tp;
870 struct dcmdevice *dcm;
871 int board, port, unit = DCMUNIT(dev);
872 int error, s;
873
874 port = DCMPORT(unit);
875 board = DCMBOARD(unit);
876
877 sc = &dcm_softc[board];
878 dcm = sc->sc_dcm;
879 tp = sc->sc_tty[port];
880
881 #ifdef DEBUG
882 if (dcmdebug & DDB_IOCTL)
883 printf("%s port %d: dcmioctl: cmd %x data %x flag %x\n",
884 sc->sc_hd->hp_xname, port, cmd, *data, flag);
885 #endif
886 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
887 if (error >= 0)
888 return (error);
889 error = ttioctl(tp, cmd, data, flag, p);
890 if (error >= 0)
891 return (error);
892
893 switch (cmd) {
894 case TIOCSBRK:
895 /*
896 * Wait for transmitter buffer to empty
897 */
898 s = spltty();
899 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
900 DELAY(DCM_USPERCH(tp->t_ospeed));
901 SEM_LOCK(dcm);
902 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
903 dcm->dcm_cr |= (1 << port); /* start break */
904 SEM_UNLOCK(dcm);
905 splx(s);
906 break;
907
908 case TIOCCBRK:
909 SEM_LOCK(dcm);
910 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
911 dcm->dcm_cr |= (1 << port); /* end break */
912 SEM_UNLOCK(dcm);
913 break;
914
915 case TIOCSDTR:
916 (void) dcmmctl(dev, MO_ON, DMBIS);
917 break;
918
919 case TIOCCDTR:
920 (void) dcmmctl(dev, MO_ON, DMBIC);
921 break;
922
923 case TIOCMSET:
924 (void) dcmmctl(dev, *(int *)data, DMSET);
925 break;
926
927 case TIOCMBIS:
928 (void) dcmmctl(dev, *(int *)data, DMBIS);
929 break;
930
931 case TIOCMBIC:
932 (void) dcmmctl(dev, *(int *)data, DMBIC);
933 break;
934
935 case TIOCMGET:
936 *(int *)data = dcmmctl(dev, 0, DMGET);
937 break;
938
939 case TIOCGFLAGS: {
940 int bits = 0;
941
942 if ((sc->sc_softCAR & (1 << port)))
943 bits |= TIOCFLAG_SOFTCAR;
944
945 if (tp->t_cflag & CLOCAL)
946 bits |= TIOCFLAG_CLOCAL;
947
948 *(int *)data = bits;
949 break;
950 }
951
952 case TIOCSFLAGS: {
953 int userbits;
954
955 error = suser(p->p_ucred, &p->p_acflag);
956 if (error)
957 return (EPERM);
958
959 userbits = *(int *)data;
960
961 if ((userbits & TIOCFLAG_SOFTCAR) ||
962 ((board == DCMBOARD(dcmconsole)) &&
963 (port == DCMPORT(dcmconsole))))
964 sc->sc_softCAR |= (1 << port);
965
966 if (userbits & TIOCFLAG_CLOCAL)
967 tp->t_cflag |= CLOCAL;
968
969 break;
970 }
971
972 default:
973 return (ENOTTY);
974 }
975 return (0);
976 }
977
978 int
979 dcmparam(tp, t)
980 register struct tty *tp;
981 register struct termios *t;
982 {
983 struct dcm_softc *sc;
984 struct dcmdevice *dcm;
985 int unit, board, port, mode, cflag = t->c_cflag;
986 int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);
987
988 unit = DCMUNIT(tp->t_dev);
989 board = DCMBOARD(unit);
990 port = DCMPORT(unit);
991
992 sc = &dcm_softc[board];
993 dcm = sc->sc_dcm;
994
995 /* check requested parameters */
996 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
997 return (EINVAL);
998 /* and copy to tty */
999 tp->t_ispeed = t->c_ispeed;
1000 tp->t_ospeed = t->c_ospeed;
1001 tp->t_cflag = cflag;
1002 if (ospeed == 0) {
1003 (void) dcmmctl(DCMUNIT(tp->t_dev), MO_OFF, DMSET);
1004 return (0);
1005 }
1006
1007 mode = 0;
1008 switch (cflag&CSIZE) {
1009 case CS5:
1010 mode = LC_5BITS; break;
1011 case CS6:
1012 mode = LC_6BITS; break;
1013 case CS7:
1014 mode = LC_7BITS; break;
1015 case CS8:
1016 mode = LC_8BITS; break;
1017 }
1018 if (cflag&PARENB) {
1019 if (cflag&PARODD)
1020 mode |= LC_PODD;
1021 else
1022 mode |= LC_PEVEN;
1023 }
1024 if (cflag&CSTOPB)
1025 mode |= LC_2STOP;
1026 else
1027 mode |= LC_1STOP;
1028 #ifdef DEBUG
1029 if (dcmdebug & DDB_PARAM)
1030 printf("%s port %d: dcmparam: cflag %x mode %x speed %d uperch %d\n",
1031 sc->sc_hd->hp_xname, port, cflag, mode, tp->t_ospeed,
1032 DCM_USPERCH(tp->t_ospeed));
1033 #endif
1034
1035 /*
1036 * Wait for transmitter buffer to empty.
1037 */
1038 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
1039 DELAY(DCM_USPERCH(tp->t_ospeed));
1040 /*
1041 * Make changes known to hardware.
1042 */
1043 dcm->dcm_data[port].dcm_baud = ospeed;
1044 dcm->dcm_data[port].dcm_conf = mode;
1045 SEM_LOCK(dcm);
1046 dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
1047 dcm->dcm_cr |= (1 << port);
1048 SEM_UNLOCK(dcm);
1049 /*
1050 * Delay for config change to take place. Weighted by baud.
1051 * XXX why do we do this?
1052 */
1053 DELAY(16 * DCM_USPERCH(tp->t_ospeed));
1054 return (0);
1055 }
1056
1057 void
1058 dcmstart(tp)
1059 register struct tty *tp;
1060 {
1061 struct dcm_softc *sc;
1062 struct dcmdevice *dcm;
1063 struct dcmpreg *pp;
1064 struct dcmtfifo *fifo;
1065 char *bp;
1066 u_int head, tail, next;
1067 int unit, board, port, nch;
1068 char buf[16];
1069 int s;
1070 #ifdef DCMSTATS
1071 struct dcmstats *dsp = &sc->sc_stats;
1072 int tch = 0;
1073 #endif
1074
1075 unit = DCMUNIT(tp->t_dev);
1076 board = DCMBOARD(unit);
1077 port = DCMPORT(unit);
1078
1079 sc = &dcm_softc[board];
1080 dcm = sc->sc_dcm;
1081
1082 s = spltty();
1083 #ifdef DCMSTATS
1084 dsp->xints++;
1085 #endif
1086 #ifdef DEBUG
1087 if (dcmdebug & DDB_OUTPUT)
1088 printf("%s port %d: dcmstart: state %x flags %x outcc %d\n",
1089 sc->sc_hd->hp_xname, port, tp->t_state, tp->t_flags,
1090 tp->t_outq.c_cc);
1091 #endif
1092 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1093 goto out;
1094 if (tp->t_outq.c_cc <= tp->t_lowat) {
1095 if (tp->t_state&TS_ASLEEP) {
1096 tp->t_state &= ~TS_ASLEEP;
1097 wakeup((caddr_t)&tp->t_outq);
1098 }
1099 selwakeup(&tp->t_wsel);
1100 }
1101 if (tp->t_outq.c_cc == 0) {
1102 #ifdef DCMSTATS
1103 dsp->xempty++;
1104 #endif
1105 goto out;
1106 }
1107
1108 pp = dcm_preg(dcm, port);
1109 tail = pp->t_tail & TX_MASK;
1110 next = (tail + 1) & TX_MASK;
1111 head = pp->t_head & TX_MASK;
1112 if (head == next)
1113 goto out;
1114 fifo = &dcm->dcm_tfifos[3-port][tail];
1115 again:
1116 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK);
1117 #ifdef DCMSTATS
1118 tch += nch;
1119 #endif
1120 #ifdef DEBUG
1121 if (dcmdebug & DDB_OUTPUT)
1122 printf("\thead %x tail %x nch %d\n", head, tail, nch);
1123 #endif
1124 /*
1125 * Loop transmitting all the characters we can.
1126 */
1127 for (bp = buf; --nch >= 0; bp++) {
1128 fifo->data_char = *bp;
1129 pp->t_tail = next;
1130 /*
1131 * If this is the first character,
1132 * get the hardware moving right now.
1133 */
1134 if (bp == buf) {
1135 tp->t_state |= TS_BUSY;
1136 SEM_LOCK(dcm);
1137 dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
1138 dcm->dcm_cr |= (1 << port);
1139 SEM_UNLOCK(dcm);
1140 }
1141 tail = next;
1142 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0];
1143 next = (next + 1) & TX_MASK;
1144 }
1145 /*
1146 * Head changed while we were loading the buffer,
1147 * go back and load some more if we can.
1148 */
1149 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) {
1150 #ifdef DCMSTATS
1151 dsp->xrestarts++;
1152 #endif
1153 head = pp->t_head & TX_MASK;
1154 goto again;
1155 }
1156
1157 /*
1158 * Kick it one last time in case it finished while we were
1159 * loading the last bunch.
1160 */
1161 if (bp > &buf[1]) {
1162 tp->t_state |= TS_BUSY;
1163 SEM_LOCK(dcm);
1164 dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
1165 dcm->dcm_cr |= (1 << port);
1166 SEM_UNLOCK(dcm);
1167 }
1168 #ifdef DEBUG
1169 if (dcmdebug & DDB_INTR)
1170 printf("%s port %d: dcmstart(%d): head %x tail %x outqcc %d\n",
1171 sc->sc_hd->hp_xname, port, head, tail, tp->t_outq.c_cc);
1172 #endif
1173 out:
1174 #ifdef DCMSTATS
1175 dsp->xchars += tch;
1176 if (tch <= DCMXBSIZE)
1177 dsp->xsilo[tch]++;
1178 else
1179 dsp->xsilo[DCMXBSIZE+1]++;
1180 #endif
1181 splx(s);
1182 }
1183
1184 /*
1185 * Stop output on a line.
1186 */
1187 int
1188 dcmstop(tp, flag)
1189 register struct tty *tp;
1190 int flag;
1191 {
1192 int s;
1193
1194 s = spltty();
1195 if (tp->t_state & TS_BUSY) {
1196 /* XXX is there some way to safely stop transmission? */
1197 if ((tp->t_state&TS_TTSTOP) == 0)
1198 tp->t_state |= TS_FLUSH;
1199 }
1200 splx(s);
1201 }
1202
1203 /*
1204 * Modem control
1205 */
1206 dcmmctl(dev, bits, how)
1207 dev_t dev;
1208 int bits, how;
1209 {
1210 struct dcm_softc *sc;
1211 struct dcmdevice *dcm;
1212 int s, unit, brd, port, hit = 0;
1213
1214 unit = DCMUNIT(dev);
1215 brd = DCMBOARD(unit);
1216 port = DCMPORT(unit);
1217 sc = &dcm_softc[brd];
1218 dcm = sc->sc_dcm;
1219
1220 #ifdef DEBUG
1221 if (dcmdebug & DDB_MODEM)
1222 printf("%s port %d: dcmmctl: bits 0x%x how %x\n",
1223 sc->sc_hd->hp_xname, port, bits, how);
1224 #endif
1225
1226 s = spltty();
1227
1228 switch (how) {
1229 case DMSET:
1230 sc->sc_modem[port]->mdmout = bits;
1231 hit++;
1232 break;
1233
1234 case DMBIS:
1235 sc->sc_modem[port]->mdmout |= bits;
1236 hit++;
1237 break;
1238
1239 case DMBIC:
1240 sc->sc_modem[port]->mdmout &= ~bits;
1241 hit++;
1242 break;
1243
1244 case DMGET:
1245 bits = sc->sc_modem[port]->mdmin;
1246 if (sc->sc_flags & DCM_STDDCE)
1247 bits = hp2dce_in(bits);
1248 break;
1249 }
1250 if (hit) {
1251 SEM_LOCK(dcm);
1252 dcm->dcm_modemchng |= 1<<(unit & 3);
1253 dcm->dcm_cr |= CR_MODM;
1254 SEM_UNLOCK(dcm);
1255 DELAY(10); /* delay until done */
1256 (void) splx(s);
1257 }
1258 return (bits);
1259 }
1260
1261 /*
1262 * Set board to either interrupt per-character or at a fixed interval.
1263 */
1264 dcmsetischeme(brd, flags)
1265 int brd, flags;
1266 {
1267 struct dcm_softc *sc = &dcm_softc[brd];
1268 struct dcmdevice *dcm = sc->sc_dcm;
1269 struct dcmischeme *dis = &sc->sc_scheme;
1270 int i;
1271 u_char mask;
1272 int perchar = flags & DIS_PERCHAR;
1273
1274 #ifdef DEBUG
1275 if (dcmdebug & DDB_INTSCHM)
1276 printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n",
1277 sc->sc_hd->hp_xname, perchar, dis->dis_perchar,
1278 dis->dis_intr, dis->dis_char);
1279 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) {
1280 printf("%s: dcmsetischeme: redundent request %d\n",
1281 sc->sc_hd->hp_xname, perchar);
1282 return;
1283 }
1284 #endif
1285 /*
1286 * If perchar is non-zero, we enable interrupts on all characters
1287 * otherwise we disable perchar interrupts and use periodic
1288 * polling interrupts.
1289 */
1290 dis->dis_perchar = perchar;
1291 mask = perchar ? 0xf : 0x0;
1292 for (i = 0; i < 256; i++)
1293 dcm->dcm_bmap[i].data_data = mask;
1294 /*
1295 * Don't slow down tandem mode, interrupt on flow control
1296 * chars for any port on the board.
1297 */
1298 if (!perchar) {
1299 register struct tty *tp;
1300 int c;
1301
1302 for (i = 0; i < NDCMPORT; i++) {
1303 tp = sc->sc_tty[i];
1304
1305 if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE)
1306 dcm->dcm_bmap[c].data_data |= (1 << i);
1307 if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE)
1308 dcm->dcm_bmap[c].data_data |= (1 << i);
1309 }
1310 }
1311 /*
1312 * Board starts with timer disabled so if first call is to
1313 * set perchar mode then we don't want to toggle the timer.
1314 */
1315 if (flags == (DIS_RESET|DIS_PERCHAR))
1316 return;
1317 /*
1318 * Toggle card 16.7ms interrupts (we first make sure that card
1319 * has cleared the bit so it will see the toggle).
1320 */
1321 while (dcm->dcm_cr & CR_TIMER)
1322 ;
1323 SEM_LOCK(dcm);
1324 dcm->dcm_cr |= CR_TIMER;
1325 SEM_UNLOCK(dcm);
1326 }
1327
1328 /*
1329 * Following are all routines needed for DCM to act as console
1330 */
1331 #include <dev/cons.h>
1332
1333 void
1334 dcmcnprobe(cp)
1335 struct consdev *cp;
1336 {
1337 struct dcm_softc *sc;
1338 struct dcmdevice *dcm;
1339 struct hp_hw *hw;
1340 int unit;
1341
1342 /* locate the major number */
1343 for (dcmmajor = 0; dcmmajor < nchrdev; dcmmajor++)
1344 if (cdevsw[dcmmajor].d_open == dcmopen)
1345 break;
1346
1347 /*
1348 * Implicitly assigns the lowest select code DCM card found to be
1349 * logical unit 0 (actually CONUNIT). If your config file does
1350 * anything different, you're screwed.
1351 */
1352 for (hw = sc_table; hw->hw_type; hw++)
1353 if (HW_ISDEV(hw, D_COMMDCM) && !badaddr((short *)hw->hw_kva))
1354 break;
1355 if (!HW_ISDEV(hw, D_COMMDCM)) {
1356 cp->cn_pri = CN_DEAD;
1357 return;
1358 }
1359
1360 unit = CONUNIT;
1361 sc = &dcm_softc[DCMBOARD(CONUNIT)];
1362 dcm = sc->sc_dcm = (struct dcmdevice *)hw->hw_kva;
1363
1364 /* initialize required fields */
1365 cp->cn_dev = makedev(dcmmajor, unit);
1366 switch (dcm->dcm_rsid) {
1367 case DCMID:
1368 cp->cn_pri = CN_NORMAL;
1369 break;
1370
1371 case DCMID|DCMCON:
1372 cp->cn_pri = CN_REMOTE;
1373 break;
1374
1375 default:
1376 cp->cn_pri = CN_DEAD;
1377 return;
1378 }
1379
1380 /*
1381 * If dcmconsole is initialized, raise our priority.
1382 */
1383 if (dcmconsole == unit)
1384 cp->cn_pri = CN_REMOTE;
1385 #ifdef KGDB_CHEAT
1386 /*
1387 * This doesn't currently work, at least not with ite consoles;
1388 * the console hasn't been initialized yet.
1389 */
1390 if (major(kgdb_dev) == dcmmajor &&
1391 DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) {
1392 (void) dcminit(kgdb_dev, kgdb_rate);
1393 if (kgdb_debug_init) {
1394 /*
1395 * We assume that console is ready for us...
1396 * this assumes that a dca or ite console
1397 * has been selected already and will init
1398 * on the first putc.
1399 */
1400 printf("dcm%d: ", DCMUNIT(kgdb_dev));
1401 kgdb_connect(1);
1402 }
1403 }
1404 #endif
1405 }
1406
1407 void
1408 dcmcninit(cp)
1409 struct consdev *cp;
1410 {
1411
1412 dcminit(cp->cn_dev, dcmdefaultrate);
1413 dcmconsinit = 1;
1414 dcmconsole = DCMUNIT(cp->cn_dev);
1415 }
1416
1417 dcminit(dev, rate)
1418 dev_t dev;
1419 int rate;
1420 {
1421 struct dcm_softc *sc;
1422 struct dcmdevice *dcm;
1423 int s, mode, unit, board, port;
1424
1425 unit = DCMUNIT(dev);
1426 board = DCMBOARD(unit);
1427 port = DCMPORT(unit);
1428
1429 sc = &dcm_softc[board];
1430 dcm = sc->sc_dcm;
1431
1432 mode = LC_8BITS | LC_1STOP;
1433
1434 s = splhigh();
1435
1436 /*
1437 * Wait for transmitter buffer to empty.
1438 */
1439 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
1440 DELAY(DCM_USPERCH(rate));
1441
1442 /*
1443 * Make changes known to hardware.
1444 */
1445 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
1446 dcm->dcm_data[port].dcm_conf = mode;
1447 SEM_LOCK(dcm);
1448 dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
1449 dcm->dcm_cr |= (1 << port);
1450 SEM_UNLOCK(dcm);
1451
1452 /*
1453 * Delay for config change to take place. Weighted by baud.
1454 * XXX why do we do this?
1455 */
1456 DELAY(16 * DCM_USPERCH(rate));
1457 splx(s);
1458 }
1459
1460 int
1461 dcmcngetc(dev)
1462 dev_t dev;
1463 {
1464 struct dcm_softc *sc;
1465 struct dcmdevice *dcm;
1466 struct dcmrfifo *fifo;
1467 struct dcmpreg *pp;
1468 u_int head;
1469 int s, c, stat, unit, board, port;
1470
1471 unit = DCMUNIT(dev);
1472 board = DCMBOARD(unit);
1473 port = DCMPORT(unit);
1474
1475 sc = &dcm_softc[board];
1476 dcm = sc->sc_dcm;
1477 pp = dcm_preg(dcm, port);
1478
1479 s = splhigh();
1480 head = pp->r_head & RX_MASK;
1481 fifo = &dcm->dcm_rfifos[3-port][head>>1];
1482 while (head == (pp->r_tail & RX_MASK))
1483 ;
1484 /*
1485 * If board interrupts are enabled, just let our received char
1486 * interrupt through in case some other port on the board was
1487 * busy. Otherwise we must clear the interrupt.
1488 */
1489 SEM_LOCK(dcm);
1490 if ((dcm->dcm_ic & IC_IE) == 0)
1491 stat = dcm->dcm_iir;
1492 SEM_UNLOCK(dcm);
1493 c = fifo->data_char;
1494 stat = fifo->data_stat;
1495 pp->r_head = (head + 2) & RX_MASK;
1496 splx(s);
1497 return (c);
1498 }
1499
1500 /*
1501 * Console kernel output character routine.
1502 */
1503 void
1504 dcmcnputc(dev, c)
1505 dev_t dev;
1506 int c;
1507 {
1508 struct dcm_softc *sc;
1509 struct dcmdevice *dcm;
1510 struct dcmpreg *pp;
1511 unsigned tail;
1512 int s, unit, board, port, stat;
1513
1514 unit = DCMUNIT(dev);
1515 board = DCMBOARD(unit);
1516 port = DCMPORT(unit);
1517
1518 sc = &dcm_softc[board];
1519 dcm = sc->sc_dcm;
1520 pp = dcm_preg(dcm, port);
1521
1522 s = splhigh();
1523 #ifdef KGDB
1524 if (dev != kgdb_dev)
1525 #endif
1526 if (dcmconsinit == 0) {
1527 (void) dcminit(dev, dcmdefaultrate);
1528 dcmconsinit = 1;
1529 }
1530 tail = pp->t_tail & TX_MASK;
1531 while (tail != (pp->t_head & TX_MASK))
1532 ;
1533 dcm->dcm_tfifos[3-port][tail].data_char = c;
1534 pp->t_tail = tail = (tail + 1) & TX_MASK;
1535 SEM_LOCK(dcm);
1536 dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
1537 dcm->dcm_cr |= (1 << port);
1538 SEM_UNLOCK(dcm);
1539 while (tail != (pp->t_head & TX_MASK))
1540 ;
1541 /*
1542 * If board interrupts are enabled, just let our completion
1543 * interrupt through in case some other port on the board
1544 * was busy. Otherwise we must clear the interrupt.
1545 */
1546 if ((dcm->dcm_ic & IC_IE) == 0) {
1547 SEM_LOCK(dcm);
1548 stat = dcm->dcm_iir;
1549 SEM_UNLOCK(dcm);
1550 }
1551 splx(s);
1552 }
1553 #endif
1554