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