dcm.c revision 1.43 1 /* $NetBSD: dcm.c,v 1.43 1998/01/12 18:30:47 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 extern struct cfdriver dcm_cd;
316
317 int
318 dcmmatch(parent, match, aux)
319 struct device *parent;
320 struct cfdata *match;
321 void *aux;
322 {
323 struct dio_attach_args *da = aux;
324
325 switch (da->da_id) {
326 case DIO_DEVICE_ID_DCM:
327 case DIO_DEVICE_ID_DCMREM:
328 return (1);
329 }
330
331 return (0);
332 }
333
334 void
335 dcmattach(parent, self, aux)
336 struct device *parent, *self;
337 void *aux;
338 {
339 struct dcm_softc *sc = (struct dcm_softc *)self;
340 struct dio_attach_args *da = aux;
341 struct dcmdevice *dcm;
342 int brd = self->dv_unit;
343 int scode = da->da_scode;
344 int i, mbits, code, ipl;
345
346 sc->sc_flags = 0;
347
348 if (scode == conscode) {
349 dcm = (struct dcmdevice *)conaddr;
350 sc->sc_flags |= DCM_ISCONSOLE;
351
352 /*
353 * We didn't know which unit this would be during
354 * the console probe, so we have to fixup cn_dev here.
355 * Note that we always assume port 1 on the board.
356 */
357 cn_tab->cn_dev = makedev(dcmmajor, (brd << 2) | DCMCONSPORT);
358 } else {
359 dcm = (struct dcmdevice *)iomap(dio_scodetopa(da->da_scode),
360 da->da_size);
361 if (dcm == NULL) {
362 printf("\n%s: can't map registers\n",
363 sc->sc_dev.dv_xname);
364 return;
365 }
366 }
367
368 sc->sc_dcm = dcm;
369
370 ipl = DIO_IPL(dcm);
371 printf(" ipl %d", ipl);
372
373 /*
374 * XXX someone _should_ fix this; the self test screws
375 * autoconfig messages.
376 */
377 if ((sc->sc_flags & DCM_ISCONSOLE) && dcmselftest(sc)) {
378 printf("\n%s: self-test failed\n", sc->sc_dev.dv_xname);
379 return;
380 }
381
382 /* Extract configuration info from flags. */
383 sc->sc_softCAR = self->dv_cfdata->cf_flags & DCM_SOFTCAR;
384 sc->sc_flags |= self->dv_cfdata->cf_flags & DCM_FLAGMASK;
385
386 /* Mark our unit as configured. */
387 sc->sc_flags |= DCM_ACTIVE;
388
389 /* Establish the interrupt handler. */
390 (void) dio_intr_establish(dcmintr, sc, ipl, IPL_TTY);
391
392 if (dcmistype == DIS_TIMER)
393 dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
394 else
395 dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
396
397 /* load pointers to modem control */
398 sc->sc_modem[0] = &dcm->dcm_modem0;
399 sc->sc_modem[1] = &dcm->dcm_modem1;
400 sc->sc_modem[2] = &dcm->dcm_modem2;
401 sc->sc_modem[3] = &dcm->dcm_modem3;
402
403 /* set DCD (modem) and CTS (flow control) on all ports */
404 if (sc->sc_flags & DCM_STDDCE)
405 mbits = hp2dce_in(MI_CD|MI_CTS);
406 else
407 mbits = MI_CD|MI_CTS;
408
409 for (i = 0; i < NDCMPORT; i++)
410 sc->sc_modem[i]->mdmmsk = mbits;
411
412 /*
413 * Get current state of mdmin register on all ports, so that
414 * deltas will work properly.
415 */
416 for (i = 0; i < NDCMPORT; i++) {
417 code = sc->sc_modem[i]->mdmin;
418 if (sc->sc_flags & DCM_STDDCE)
419 code = hp2dce_in(code);
420 sc->sc_mcndlast[i] = code;
421 }
422
423 dcm->dcm_ic = IC_IE; /* turn all interrupts on */
424
425 /*
426 * Need to reset baud rate, etc. of next print so reset dcmconsinit.
427 * Also make sure console is always "hardwired"
428 */
429 if (sc->sc_flags & DCM_ISCONSOLE) {
430 dcmconsinit = 0;
431 sc->sc_softCAR |= (1 << DCMCONSPORT);
432 printf(": console on port %d\n", DCMCONSPORT);
433 } else
434 printf("\n");
435
436 #ifdef KGDB
437 if (major(kgdb_dev) == dcmmajor &&
438 DCMBOARD(DCMUNIT(kgdb_dev)) == brd) {
439 if (dcmconsole == DCMUNIT(kgdb_dev)) /* XXX fixme */
440 kgdb_dev = NODEV; /* can't debug over console port */
441 #ifndef KGDB_CHEAT
442 /*
443 * The following could potentially be replaced
444 * by the corresponding code in dcmcnprobe.
445 */
446 else {
447 dcminit(dcm, DCMPORT(DCMUNIT(kgdb_dev)),
448 kgdb_rate);
449 if (kgdb_debug_init) {
450 printf("%s port %d: ", sc->sc_dev.dv_xname,
451 DCMPORT(DCMUNIT(kgdb_dev)));
452 kgdb_connect(1);
453 } else
454 printf("%s port %d: kgdb enabled\n",
455 sc->sc_dev.dv_xname,
456 DCMPORT(DCMUNIT(kgdb_dev)));
457 }
458 /* end could be replaced */
459 #endif /* KGDB_CHEAT */
460 }
461 #endif /* KGDB */
462 }
463
464 /* ARGSUSED */
465 int
466 dcmopen(dev, flag, mode, p)
467 dev_t dev;
468 int flag, mode;
469 struct proc *p;
470 {
471 struct dcm_softc *sc;
472 struct tty *tp;
473 int unit, brd, port;
474 int error = 0, mbits, s;
475
476 unit = DCMUNIT(dev);
477 brd = DCMBOARD(unit);
478 port = DCMPORT(unit);
479
480 if (brd >= dcm_cd.cd_ndevs || port >= NDCMPORT ||
481 (sc = dcm_cd.cd_devs[brd]) == NULL)
482 return (ENXIO);
483
484 if ((sc->sc_flags & DCM_ACTIVE) == 0)
485 return (ENXIO);
486
487 if (sc->sc_tty[port] == NULL) {
488 tp = sc->sc_tty[port] = ttymalloc();
489 tty_attach(tp);
490 } else
491 tp = sc->sc_tty[port];
492
493 tp->t_oproc = dcmstart;
494 tp->t_param = dcmparam;
495 tp->t_dev = dev;
496
497 if ((tp->t_state & TS_ISOPEN) == 0) {
498 /*
499 * Sanity clause: reset the card on first open.
500 * The card might be left in an inconsistent state
501 * if the card memory is read inadvertently.
502 */
503 dcminit(sc->sc_dcm, port, dcmdefaultrate);
504
505 tp->t_state |= TS_WOPEN;
506 ttychars(tp);
507 tp->t_iflag = TTYDEF_IFLAG;
508 tp->t_oflag = TTYDEF_OFLAG;
509 tp->t_cflag = TTYDEF_CFLAG;
510 tp->t_lflag = TTYDEF_LFLAG;
511 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
512
513 s = spltty();
514
515 (void) dcmparam(tp, &tp->t_termios);
516 ttsetwater(tp);
517 } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
518 return (EBUSY);
519 else
520 s = spltty();
521
522 /* Set modem control state. */
523 mbits = MO_ON;
524 if (sc->sc_flags & DCM_STDDCE)
525 mbits |= MO_SR; /* pin 23, could be used as RTS */
526
527 (void) dcmmctl(dev, mbits, DMSET); /* enable port */
528
529 /* Set soft-carrier if so configured. */
530 if ((sc->sc_softCAR & (1 << port)) ||
531 (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))
532 tp->t_state |= TS_CARR_ON;
533
534 #ifdef DEBUG
535 if (dcmdebug & DDB_MODEM)
536 printf("%s: dcmopen port %d softcarr %c\n",
537 sc->sc_dev.dv_xname, port,
538 (tp->t_state & TS_CARR_ON) ? '1' : '0');
539 #endif
540
541 /* Wait for carrier if necessary. */
542 if ((flag & O_NONBLOCK) == 0)
543 while ((tp->t_cflag & CLOCAL) == 0 &&
544 (tp->t_state & TS_CARR_ON) == 0) {
545 tp->t_state |= TS_WOPEN;
546 error = ttysleep(tp, (caddr_t)&tp->t_rawq,
547 TTIPRI | PCATCH, ttopen, 0);
548 if (error) {
549 splx(s);
550 return (error);
551 }
552 }
553
554 splx(s);
555
556 #ifdef DEBUG
557 if (dcmdebug & DDB_OPENCLOSE)
558 printf("%s port %d: dcmopen: st %x fl %x\n",
559 sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags);
560 #endif
561 if (error == 0)
562 error = (*linesw[tp->t_line].l_open)(dev, tp);
563
564 return (error);
565 }
566
567 /*ARGSUSED*/
568 int
569 dcmclose(dev, flag, mode, p)
570 dev_t dev;
571 int flag, mode;
572 struct proc *p;
573 {
574 int s, unit, board, port;
575 struct dcm_softc *sc;
576 struct tty *tp;
577
578 unit = DCMUNIT(dev);
579 board = DCMBOARD(unit);
580 port = DCMPORT(unit);
581
582 sc = dcm_cd.cd_devs[board];
583 tp = sc->sc_tty[port];
584
585 (*linesw[tp->t_line].l_close)(tp, flag);
586
587 s = spltty();
588
589 if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
590 (tp->t_state & TS_ISOPEN) == 0)
591 (void) dcmmctl(dev, MO_OFF, DMSET);
592 #ifdef DEBUG
593 if (dcmdebug & DDB_OPENCLOSE)
594 printf("%s port %d: dcmclose: st %x fl %x\n",
595 sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags);
596 #endif
597 splx(s);
598 ttyclose(tp);
599 #if 0
600 tty_detach(tp);
601 ttyfree(tp);
602 sc->sc_tty[port] == NULL;
603 #endif
604 return (0);
605 }
606
607 int
608 dcmread(dev, uio, flag)
609 dev_t dev;
610 struct uio *uio;
611 int flag;
612 {
613 int unit, board, port;
614 struct dcm_softc *sc;
615 struct tty *tp;
616
617 unit = DCMUNIT(dev);
618 board = DCMBOARD(unit);
619 port = DCMPORT(unit);
620
621 sc = dcm_cd.cd_devs[board];
622 tp = sc->sc_tty[port];
623
624 return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
625 }
626
627 int
628 dcmwrite(dev, uio, flag)
629 dev_t dev;
630 struct uio *uio;
631 int flag;
632 {
633 int unit, board, port;
634 struct dcm_softc *sc;
635 struct tty *tp;
636
637 unit = DCMUNIT(dev);
638 board = DCMBOARD(unit);
639 port = DCMPORT(unit);
640
641 sc = dcm_cd.cd_devs[board];
642 tp = sc->sc_tty[port];
643
644 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
645 }
646
647 struct tty *
648 dcmtty(dev)
649 dev_t dev;
650 {
651 int unit, board, port;
652 struct dcm_softc *sc;
653
654 unit = DCMUNIT(dev);
655 board = DCMBOARD(unit);
656 port = DCMPORT(unit);
657
658 sc = dcm_cd.cd_devs[board];
659
660 return (sc->sc_tty[port]);
661 }
662
663 int
664 dcmintr(arg)
665 void *arg;
666 {
667 struct dcm_softc *sc = arg;
668 struct dcmdevice *dcm = sc->sc_dcm;
669 struct dcmischeme *dis = &sc->sc_scheme;
670 int brd = sc->sc_dev.dv_unit;
671 int code, i;
672 int pcnd[4], mcode, mcnd[4];
673
674 /*
675 * Do all guarded accesses right off to minimize
676 * block out of hardware.
677 */
678 SEM_LOCK(dcm);
679 if ((dcm->dcm_ic & IC_IR) == 0) {
680 SEM_UNLOCK(dcm);
681 return (0);
682 }
683 for (i = 0; i < 4; i++) {
684 pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
685 dcm->dcm_icrtab[i].dcm_data = 0;
686 code = sc->sc_modem[i]->mdmin;
687 if (sc->sc_flags & DCM_STDDCE)
688 code = hp2dce_in(code);
689 mcnd[i] = code;
690 }
691 code = dcm->dcm_iir & IIR_MASK;
692 dcm->dcm_iir = 0; /* XXX doc claims read clears interrupt?! */
693 mcode = dcm->dcm_modemintr;
694 dcm->dcm_modemintr = 0;
695 SEM_UNLOCK(dcm);
696
697 #ifdef DEBUG
698 if (dcmdebug & DDB_INTR) {
699 printf("%s: dcmintr: iir %x pc %x/%x/%x/%x ",
700 sc->sc_dev.dv_xname, code, pcnd[0], pcnd[1],
701 pcnd[2], pcnd[3]);
702 printf("miir %x mc %x/%x/%x/%x\n",
703 mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);
704 }
705 #endif
706 if (code & IIR_TIMEO)
707 dcmrint(sc);
708 if (code & IIR_PORT0)
709 dcmpint(sc, 0, pcnd[0]);
710 if (code & IIR_PORT1)
711 dcmpint(sc, 1, pcnd[1]);
712 if (code & IIR_PORT2)
713 dcmpint(sc, 2, pcnd[2]);
714 if (code & IIR_PORT3)
715 dcmpint(sc, 3, pcnd[3]);
716 if (code & IIR_MODM) {
717 if (mcode == 0 || mcode & 0x1) /* mcode==0 -> 98642 board */
718 dcmmint(sc, 0, mcnd[0]);
719 if (mcode & 0x2)
720 dcmmint(sc, 1, mcnd[1]);
721 if (mcode & 0x4)
722 dcmmint(sc, 2, mcnd[2]);
723 if (mcode & 0x8)
724 dcmmint(sc, 3, mcnd[3]);
725 }
726
727 /*
728 * Chalk up a receiver interrupt if the timer running or one of
729 * the ports reports a special character interrupt.
730 */
731 if ((code & IIR_TIMEO) ||
732 ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))
733 dis->dis_intr++;
734 /*
735 * See if it is time to check/change the interrupt rate.
736 */
737 if (dcmistype < 0 &&
738 (i = time.tv_sec - dis->dis_time) >= dcminterval) {
739 /*
740 * If currently per-character and averaged over 70 interrupts
741 * per-second (66 is threshold of 600 baud) in last interval,
742 * switch to timer mode.
743 *
744 * XXX decay counts ala load average to avoid spikes?
745 */
746 if (dis->dis_perchar && dis->dis_intr > 70 * i)
747 dcmsetischeme(brd, DIS_TIMER);
748 /*
749 * If currently using timer and had more interrupts than
750 * received characters in the last interval, switch back
751 * to per-character. Note that after changing to per-char
752 * we must process any characters already in the queue
753 * since they may have arrived before the bitmap was setup.
754 *
755 * XXX decay counts?
756 */
757 else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {
758 dcmsetischeme(brd, DIS_PERCHAR);
759 dcmrint(sc);
760 }
761 dis->dis_intr = dis->dis_char = 0;
762 dis->dis_time = time.tv_sec;
763 }
764 return (1);
765 }
766
767 /*
768 * Port interrupt. Can be two things:
769 * First, it might be a special character (exception interrupt);
770 * Second, it may be a buffer empty (transmit interrupt);
771 */
772 void
773 dcmpint(sc, port, code)
774 struct dcm_softc *sc;
775 int port, code;
776 {
777
778 if (code & IT_SPEC)
779 dcmreadbuf(sc, port);
780 if (code & IT_TX)
781 dcmxint(sc, port);
782 }
783
784 void
785 dcmrint(sc)
786 struct dcm_softc *sc;
787 {
788 int port;
789
790 for (port = 0; port < NDCMPORT; port++)
791 dcmreadbuf(sc, port);
792 }
793
794 void
795 dcmreadbuf(sc, port)
796 struct dcm_softc *sc;
797 int port;
798 {
799 struct dcmdevice *dcm = sc->sc_dcm;
800 struct dcmpreg *pp = dcm_preg(dcm, port);
801 struct dcmrfifo *fifo;
802 struct tty *tp;
803 int c, stat;
804 u_int head;
805 int nch = 0;
806 #ifdef DCMSTATS
807 struct dcmstats *dsp = &sc->sc_stats;
808
809 dsp->rints++;
810 #endif
811 tp = sc->sc_tty[port];
812 if (tp == NULL)
813 return;
814
815 if ((tp->t_state & TS_ISOPEN) == 0) {
816 #ifdef KGDB
817 if ((makedev(dcmmajor, minor(tp->t_dev)) == kgdb_dev) &&
818 (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
819 dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) {
820 pp->r_head = (head + 2) & RX_MASK;
821 kgdb_connect(0); /* trap into kgdb */
822 return;
823 }
824 #endif /* KGDB */
825 pp->r_head = pp->r_tail & RX_MASK;
826 return;
827 }
828
829 head = pp->r_head & RX_MASK;
830 fifo = &dcm->dcm_rfifos[3-port][head>>1];
831 /*
832 * XXX upper bound on how many chars we will take in one swallow?
833 */
834 while (head != (pp->r_tail & RX_MASK)) {
835 /*
836 * Get character/status and update head pointer as fast
837 * as possible to make room for more characters.
838 */
839 c = fifo->data_char;
840 stat = fifo->data_stat;
841 head = (head + 2) & RX_MASK;
842 pp->r_head = head;
843 fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];
844 nch++;
845
846 #ifdef DEBUG
847 if (dcmdebug & DDB_INPUT)
848 printf("%s port %d: dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n",
849 sc->sc_dev.dv_xname, port,
850 c&0xFF, c, stat&0xFF,
851 tp->t_flags, head, pp->r_tail);
852 #endif
853 /*
854 * Check for and handle errors
855 */
856 if (stat & RD_MASK) {
857 #ifdef DEBUG
858 if (dcmdebug & (DDB_INPUT|DDB_SIOERR))
859 printf("%s port %d: dcmreadbuf: err: c%x('%c') s%x\n",
860 sc->sc_dev.dv_xname, port,
861 stat, c&0xFF, c);
862 #endif
863 if (stat & (RD_BD | RD_FE))
864 c |= TTY_FE;
865 else if (stat & RD_PE)
866 c |= TTY_PE;
867 else if (stat & RD_OVF)
868 log(LOG_WARNING,
869 "%s port %d: silo overflow\n",
870 sc->sc_dev.dv_xname, port);
871 else if (stat & RD_OE)
872 log(LOG_WARNING,
873 "%s port %d: uart overflow\n",
874 sc->sc_dev.dv_xname, port);
875 }
876 (*linesw[tp->t_line].l_rint)(c, tp);
877 }
878 sc->sc_scheme.dis_char += nch;
879
880 #ifdef DCMSTATS
881 dsp->rchars += nch;
882 if (nch <= DCMRBSIZE)
883 dsp->rsilo[nch]++;
884 else
885 dsp->rsilo[DCMRBSIZE+1]++;
886 #endif
887 }
888
889 void
890 dcmxint(sc, port)
891 struct dcm_softc *sc;
892 int port;
893 {
894 struct tty *tp;
895
896 tp = sc->sc_tty[port];
897 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
898 return;
899
900 tp->t_state &= ~TS_BUSY;
901 if (tp->t_state & TS_FLUSH)
902 tp->t_state &= ~TS_FLUSH;
903 (*linesw[tp->t_line].l_start)(tp);
904 }
905
906 void
907 dcmmint(sc, port, mcnd)
908 struct dcm_softc *sc;
909 int port, mcnd;
910 {
911 int delta;
912 struct tty *tp;
913 struct dcmdevice *dcm = sc->sc_dcm;
914
915 tp = sc->sc_tty[port];
916 if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
917 return;
918
919 #ifdef DEBUG
920 if (dcmdebug & DDB_MODEM)
921 printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n",
922 sc->sc_dev.dv_xname, port, mcnd, sc->sc_mcndlast[port]);
923 #endif
924 delta = mcnd ^ sc->sc_mcndlast[port];
925 sc->sc_mcndlast[port] = mcnd;
926 if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
927 (tp->t_flags & CCTS_OFLOW)) {
928 if (mcnd & MI_CTS) {
929 tp->t_state &= ~TS_TTSTOP;
930 ttstart(tp);
931 } else
932 tp->t_state |= TS_TTSTOP; /* inline dcmstop */
933 }
934 if (delta & MI_CD) {
935 if (mcnd & MI_CD)
936 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
937 else if ((sc->sc_softCAR & (1 << port)) == 0 &&
938 (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
939 sc->sc_modem[port]->mdmout = MO_OFF;
940 SEM_LOCK(dcm);
941 dcm->dcm_modemchng |= (1 << port);
942 dcm->dcm_cr |= CR_MODM;
943 SEM_UNLOCK(dcm);
944 DELAY(10); /* time to change lines */
945 }
946 }
947 }
948
949 int
950 dcmioctl(dev, cmd, data, flag, p)
951 dev_t dev;
952 u_long cmd;
953 caddr_t data;
954 int flag;
955 struct proc *p;
956 {
957 struct dcm_softc *sc;
958 struct tty *tp;
959 struct dcmdevice *dcm;
960 int board, port, unit = DCMUNIT(dev);
961 int error, s;
962
963 port = DCMPORT(unit);
964 board = DCMBOARD(unit);
965
966 sc = dcm_cd.cd_devs[board];
967 dcm = sc->sc_dcm;
968 tp = sc->sc_tty[port];
969
970 #ifdef DEBUG
971 if (dcmdebug & DDB_IOCTL)
972 printf("%s port %d: dcmioctl: cmd %lx data %x flag %x\n",
973 sc->sc_dev.dv_xname, port, cmd, *data, flag);
974 #endif
975 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
976 if (error >= 0)
977 return (error);
978 error = ttioctl(tp, cmd, data, flag, p);
979 if (error >= 0)
980 return (error);
981
982 switch (cmd) {
983 case TIOCSBRK:
984 /*
985 * Wait for transmitter buffer to empty
986 */
987 s = spltty();
988 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
989 DELAY(DCM_USPERCH(tp->t_ospeed));
990 SEM_LOCK(dcm);
991 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
992 dcm->dcm_cr |= (1 << port); /* start break */
993 SEM_UNLOCK(dcm);
994 splx(s);
995 break;
996
997 case TIOCCBRK:
998 SEM_LOCK(dcm);
999 dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
1000 dcm->dcm_cr |= (1 << port); /* end break */
1001 SEM_UNLOCK(dcm);
1002 break;
1003
1004 case TIOCSDTR:
1005 (void) dcmmctl(dev, MO_ON, DMBIS);
1006 break;
1007
1008 case TIOCCDTR:
1009 (void) dcmmctl(dev, MO_ON, DMBIC);
1010 break;
1011
1012 case TIOCMSET:
1013 (void) dcmmctl(dev, *(int *)data, DMSET);
1014 break;
1015
1016 case TIOCMBIS:
1017 (void) dcmmctl(dev, *(int *)data, DMBIS);
1018 break;
1019
1020 case TIOCMBIC:
1021 (void) dcmmctl(dev, *(int *)data, DMBIC);
1022 break;
1023
1024 case TIOCMGET:
1025 *(int *)data = dcmmctl(dev, 0, DMGET);
1026 break;
1027
1028 case TIOCGFLAGS: {
1029 int bits = 0;
1030
1031 if ((sc->sc_softCAR & (1 << port)))
1032 bits |= TIOCFLAG_SOFTCAR;
1033
1034 if (tp->t_cflag & CLOCAL)
1035 bits |= TIOCFLAG_CLOCAL;
1036
1037 *(int *)data = bits;
1038 break;
1039 }
1040
1041 case TIOCSFLAGS: {
1042 int userbits;
1043
1044 error = suser(p->p_ucred, &p->p_acflag);
1045 if (error)
1046 return (EPERM);
1047
1048 userbits = *(int *)data;
1049
1050 if ((userbits & TIOCFLAG_SOFTCAR) ||
1051 ((sc->sc_flags & DCM_ISCONSOLE) &&
1052 (port == DCMCONSPORT)))
1053 sc->sc_softCAR |= (1 << port);
1054
1055 if (userbits & TIOCFLAG_CLOCAL)
1056 tp->t_cflag |= CLOCAL;
1057
1058 break;
1059 }
1060
1061 default:
1062 return (ENOTTY);
1063 }
1064 return (0);
1065 }
1066
1067 int
1068 dcmparam(tp, t)
1069 struct tty *tp;
1070 struct termios *t;
1071 {
1072 struct dcm_softc *sc;
1073 struct dcmdevice *dcm;
1074 int unit, board, port, mode, cflag = t->c_cflag;
1075 int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);
1076
1077 unit = DCMUNIT(tp->t_dev);
1078 board = DCMBOARD(unit);
1079 port = DCMPORT(unit);
1080
1081 sc = dcm_cd.cd_devs[board];
1082 dcm = sc->sc_dcm;
1083
1084 /* check requested parameters */
1085 if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
1086 return (EINVAL);
1087 /* and copy to tty */
1088 tp->t_ispeed = t->c_ispeed;
1089 tp->t_ospeed = t->c_ospeed;
1090 tp->t_cflag = cflag;
1091 if (ospeed == 0) {
1092 (void) dcmmctl(DCMUNIT(tp->t_dev), MO_OFF, DMSET);
1093 return (0);
1094 }
1095
1096 mode = 0;
1097 switch (cflag&CSIZE) {
1098 case CS5:
1099 mode = LC_5BITS; break;
1100 case CS6:
1101 mode = LC_6BITS; break;
1102 case CS7:
1103 mode = LC_7BITS; break;
1104 case CS8:
1105 mode = LC_8BITS; break;
1106 }
1107 if (cflag&PARENB) {
1108 if (cflag&PARODD)
1109 mode |= LC_PODD;
1110 else
1111 mode |= LC_PEVEN;
1112 }
1113 if (cflag&CSTOPB)
1114 mode |= LC_2STOP;
1115 else
1116 mode |= LC_1STOP;
1117 #ifdef DEBUG
1118 if (dcmdebug & DDB_PARAM)
1119 printf("%s port %d: dcmparam: cflag %x mode %x speed %d uperch %d\n",
1120 sc->sc_dev.dv_xname, port, cflag, mode, tp->t_ospeed,
1121 DCM_USPERCH(tp->t_ospeed));
1122 #endif
1123
1124 /*
1125 * Wait for transmitter buffer to empty.
1126 */
1127 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
1128 DELAY(DCM_USPERCH(tp->t_ospeed));
1129 /*
1130 * Make changes known to hardware.
1131 */
1132 dcm->dcm_data[port].dcm_baud = ospeed;
1133 dcm->dcm_data[port].dcm_conf = mode;
1134 SEM_LOCK(dcm);
1135 dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
1136 dcm->dcm_cr |= (1 << port);
1137 SEM_UNLOCK(dcm);
1138 /*
1139 * Delay for config change to take place. Weighted by baud.
1140 * XXX why do we do this?
1141 */
1142 DELAY(16 * DCM_USPERCH(tp->t_ospeed));
1143 return (0);
1144 }
1145
1146 void
1147 dcmstart(tp)
1148 struct tty *tp;
1149 {
1150 struct dcm_softc *sc;
1151 struct dcmdevice *dcm;
1152 struct dcmpreg *pp;
1153 struct dcmtfifo *fifo;
1154 char *bp;
1155 u_int head, tail, next;
1156 int unit, board, port, nch;
1157 char buf[16];
1158 int s;
1159 #ifdef DCMSTATS
1160 struct dcmstats *dsp = &sc->sc_stats;
1161 int tch = 0;
1162 #endif
1163
1164 unit = DCMUNIT(tp->t_dev);
1165 board = DCMBOARD(unit);
1166 port = DCMPORT(unit);
1167
1168 sc = dcm_cd.cd_devs[board];
1169 dcm = sc->sc_dcm;
1170
1171 s = spltty();
1172 #ifdef DCMSTATS
1173 dsp->xints++;
1174 #endif
1175 #ifdef DEBUG
1176 if (dcmdebug & DDB_OUTPUT)
1177 printf("%s port %d: dcmstart: state %x flags %x outcc %d\n",
1178 sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags,
1179 tp->t_outq.c_cc);
1180 #endif
1181 if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
1182 goto out;
1183 if (tp->t_outq.c_cc <= tp->t_lowat) {
1184 if (tp->t_state&TS_ASLEEP) {
1185 tp->t_state &= ~TS_ASLEEP;
1186 wakeup((caddr_t)&tp->t_outq);
1187 }
1188 selwakeup(&tp->t_wsel);
1189 }
1190 if (tp->t_outq.c_cc == 0) {
1191 #ifdef DCMSTATS
1192 dsp->xempty++;
1193 #endif
1194 goto out;
1195 }
1196
1197 pp = dcm_preg(dcm, port);
1198 tail = pp->t_tail & TX_MASK;
1199 next = (tail + 1) & TX_MASK;
1200 head = pp->t_head & TX_MASK;
1201 if (head == next)
1202 goto out;
1203 fifo = &dcm->dcm_tfifos[3-port][tail];
1204 again:
1205 nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK);
1206 #ifdef DCMSTATS
1207 tch += nch;
1208 #endif
1209 #ifdef DEBUG
1210 if (dcmdebug & DDB_OUTPUT)
1211 printf("\thead %x tail %x nch %d\n", head, tail, nch);
1212 #endif
1213 /*
1214 * Loop transmitting all the characters we can.
1215 */
1216 for (bp = buf; --nch >= 0; bp++) {
1217 fifo->data_char = *bp;
1218 pp->t_tail = next;
1219 /*
1220 * If this is the first character,
1221 * get the hardware moving right now.
1222 */
1223 if (bp == buf) {
1224 tp->t_state |= TS_BUSY;
1225 SEM_LOCK(dcm);
1226 dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
1227 dcm->dcm_cr |= (1 << port);
1228 SEM_UNLOCK(dcm);
1229 }
1230 tail = next;
1231 fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0];
1232 next = (next + 1) & TX_MASK;
1233 }
1234 /*
1235 * Head changed while we were loading the buffer,
1236 * go back and load some more if we can.
1237 */
1238 if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) {
1239 #ifdef DCMSTATS
1240 dsp->xrestarts++;
1241 #endif
1242 head = pp->t_head & TX_MASK;
1243 goto again;
1244 }
1245
1246 /*
1247 * Kick it one last time in case it finished while we were
1248 * loading the last bunch.
1249 */
1250 if (bp > &buf[1]) {
1251 tp->t_state |= TS_BUSY;
1252 SEM_LOCK(dcm);
1253 dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
1254 dcm->dcm_cr |= (1 << port);
1255 SEM_UNLOCK(dcm);
1256 }
1257 #ifdef DEBUG
1258 if (dcmdebug & DDB_INTR)
1259 printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n",
1260 sc->sc_dev.dv_xname, port, head, tail, tp->t_outq.c_cc);
1261 #endif
1262 out:
1263 #ifdef DCMSTATS
1264 dsp->xchars += tch;
1265 if (tch <= DCMXBSIZE)
1266 dsp->xsilo[tch]++;
1267 else
1268 dsp->xsilo[DCMXBSIZE+1]++;
1269 #endif
1270 splx(s);
1271 }
1272
1273 /*
1274 * Stop output on a line.
1275 */
1276 void
1277 dcmstop(tp, flag)
1278 struct tty *tp;
1279 int flag;
1280 {
1281 int s;
1282
1283 s = spltty();
1284 if (tp->t_state & TS_BUSY) {
1285 /* XXX is there some way to safely stop transmission? */
1286 if ((tp->t_state&TS_TTSTOP) == 0)
1287 tp->t_state |= TS_FLUSH;
1288 }
1289 splx(s);
1290 }
1291
1292 /*
1293 * Modem control
1294 */
1295 int
1296 dcmmctl(dev, bits, how)
1297 dev_t dev;
1298 int bits, how;
1299 {
1300 struct dcm_softc *sc;
1301 struct dcmdevice *dcm;
1302 int s, unit, brd, port, hit = 0;
1303
1304 unit = DCMUNIT(dev);
1305 brd = DCMBOARD(unit);
1306 port = DCMPORT(unit);
1307
1308 sc = dcm_cd.cd_devs[brd];
1309 dcm = sc->sc_dcm;
1310
1311 #ifdef DEBUG
1312 if (dcmdebug & DDB_MODEM)
1313 printf("%s port %d: dcmmctl: bits 0x%x how %x\n",
1314 sc->sc_dev.dv_xname, port, bits, how);
1315 #endif
1316
1317 s = spltty();
1318
1319 switch (how) {
1320 case DMSET:
1321 sc->sc_modem[port]->mdmout = bits;
1322 hit++;
1323 break;
1324
1325 case DMBIS:
1326 sc->sc_modem[port]->mdmout |= bits;
1327 hit++;
1328 break;
1329
1330 case DMBIC:
1331 sc->sc_modem[port]->mdmout &= ~bits;
1332 hit++;
1333 break;
1334
1335 case DMGET:
1336 bits = sc->sc_modem[port]->mdmin;
1337 if (sc->sc_flags & DCM_STDDCE)
1338 bits = hp2dce_in(bits);
1339 break;
1340 }
1341 if (hit) {
1342 SEM_LOCK(dcm);
1343 dcm->dcm_modemchng |= 1<<(unit & 3);
1344 dcm->dcm_cr |= CR_MODM;
1345 SEM_UNLOCK(dcm);
1346 DELAY(10); /* delay until done */
1347 (void) splx(s);
1348 }
1349 return (bits);
1350 }
1351
1352 /*
1353 * Set board to either interrupt per-character or at a fixed interval.
1354 */
1355 void
1356 dcmsetischeme(brd, flags)
1357 int brd, flags;
1358 {
1359 struct dcm_softc *sc = dcm_cd.cd_devs[brd];
1360 struct dcmdevice *dcm = sc->sc_dcm;
1361 struct dcmischeme *dis = &sc->sc_scheme;
1362 int i;
1363 u_char mask;
1364 int perchar = flags & DIS_PERCHAR;
1365
1366 #ifdef DEBUG
1367 if (dcmdebug & DDB_INTSCHM)
1368 printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n",
1369 sc->sc_dev.dv_xname, perchar, dis->dis_perchar,
1370 dis->dis_intr, dis->dis_char);
1371 if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) {
1372 printf("%s: dcmsetischeme: redundent request %d\n",
1373 sc->sc_dev.dv_xname, perchar);
1374 return;
1375 }
1376 #endif
1377 /*
1378 * If perchar is non-zero, we enable interrupts on all characters
1379 * otherwise we disable perchar interrupts and use periodic
1380 * polling interrupts.
1381 */
1382 dis->dis_perchar = perchar;
1383 mask = perchar ? 0xf : 0x0;
1384 for (i = 0; i < 256; i++)
1385 dcm->dcm_bmap[i].data_data = mask;
1386 /*
1387 * Don't slow down tandem mode, interrupt on flow control
1388 * chars for any port on the board.
1389 */
1390 if (!perchar) {
1391 struct tty *tp;
1392 int c;
1393
1394 for (i = 0; i < NDCMPORT; i++) {
1395 tp = sc->sc_tty[i];
1396
1397 if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE)
1398 dcm->dcm_bmap[c].data_data |= (1 << i);
1399 if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE)
1400 dcm->dcm_bmap[c].data_data |= (1 << i);
1401 }
1402 }
1403 /*
1404 * Board starts with timer disabled so if first call is to
1405 * set perchar mode then we don't want to toggle the timer.
1406 */
1407 if (flags == (DIS_RESET|DIS_PERCHAR))
1408 return;
1409 /*
1410 * Toggle card 16.7ms interrupts (we first make sure that card
1411 * has cleared the bit so it will see the toggle).
1412 */
1413 while (dcm->dcm_cr & CR_TIMER)
1414 ;
1415 SEM_LOCK(dcm);
1416 dcm->dcm_cr |= CR_TIMER;
1417 SEM_UNLOCK(dcm);
1418 }
1419
1420 void
1421 dcminit(dcm, port, rate)
1422 struct dcmdevice *dcm;
1423 int port, rate;
1424 {
1425 int s, mode;
1426
1427 mode = LC_8BITS | LC_1STOP;
1428
1429 s = splhigh();
1430
1431 /*
1432 * Wait for transmitter buffer to empty.
1433 */
1434 while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
1435 DELAY(DCM_USPERCH(rate));
1436
1437 /*
1438 * Make changes known to hardware.
1439 */
1440 dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
1441 dcm->dcm_data[port].dcm_conf = mode;
1442 SEM_LOCK(dcm);
1443 dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
1444 dcm->dcm_cr |= (1 << port);
1445 SEM_UNLOCK(dcm);
1446
1447 /*
1448 * Delay for config change to take place. Weighted by baud.
1449 * XXX why do we do this?
1450 */
1451 DELAY(16 * DCM_USPERCH(rate));
1452 splx(s);
1453 }
1454
1455 /*
1456 * Empirically derived self-test magic
1457 */
1458 int
1459 dcmselftest(sc)
1460 struct dcm_softc *sc;
1461 {
1462 struct dcmdevice *dcm = sc->sc_dcm;
1463 int timo = 0;
1464 int s, rv;
1465
1466 rv = 1;
1467
1468 s = splhigh();
1469 dcm->dcm_rsid = DCMRS;
1470 DELAY(50000); /* 5000 is not long enough */
1471 dcm->dcm_rsid = 0;
1472 dcm->dcm_ic = IC_IE;
1473 dcm->dcm_cr = CR_SELFT;
1474 while ((dcm->dcm_ic & IC_IR) == 0) {
1475 if (++timo == 20000)
1476 goto out;
1477 DELAY(1);
1478 }
1479 DELAY(50000); /* XXX why is this needed ???? */
1480 while ((dcm->dcm_iir & IIR_SELFT) == 0) {
1481 if (++timo == 400000)
1482 goto out;
1483 DELAY(1);
1484 }
1485 DELAY(50000); /* XXX why is this needed ???? */
1486 if (dcm->dcm_stcon != ST_OK) {
1487 #if 0
1488 if (hd->hp_args->hw_sc != conscode)
1489 printf("dcm%d: self test failed: %x\n",
1490 brd, dcm->dcm_stcon);
1491 #endif
1492 goto out;
1493 }
1494 dcm->dcm_ic = IC_ID;
1495 rv = 0;
1496
1497 out:
1498 splx(s);
1499 return (rv);
1500 }
1501
1502 /*
1503 * Following are all routines needed for DCM to act as console
1504 */
1505
1506 int
1507 dcm_console_scan(scode, va, arg)
1508 int scode;
1509 caddr_t va;
1510 void *arg;
1511 {
1512 struct dcmdevice *dcm = (struct dcmdevice *)va;
1513 struct consdev *cp = arg;
1514 u_char *dioiidev;
1515 int force = 0, pri;
1516
1517 switch (dcm->dcm_rsid) {
1518 case DCMID:
1519 pri = CN_NORMAL;
1520 break;
1521
1522 case DCMID|DCMCON:
1523 pri = CN_REMOTE;
1524 break;
1525
1526 default:
1527 return (0);
1528 }
1529
1530 #ifdef CONSCODE
1531 /*
1532 * Raise our priority, if appropriate.
1533 */
1534 if (scode == CONSCODE) {
1535 pri = CN_REMOTE;
1536 force = conforced = 1;
1537 }
1538 #endif
1539
1540 /* Only raise priority. */
1541 if (pri > cp->cn_pri)
1542 cp->cn_pri = pri;
1543
1544 /*
1545 * If our priority is higher than the currently-remembered
1546 * console, stash our priority, for the benefit of dcmcninit().
1547 */
1548 if (((cn_tab == NULL) || (cp->cn_pri > cn_tab->cn_pri)) || force) {
1549 cn_tab = cp;
1550 if (scode >= 132) {
1551 dioiidev = (u_char *)va;
1552 return ((dioiidev[0x101] + 1) * 0x100000);
1553 }
1554 return (DIOCSIZE);
1555 }
1556 return (0);
1557 }
1558
1559 void
1560 dcmcnprobe(cp)
1561 struct consdev *cp;
1562 {
1563
1564 /* locate the major number */
1565 for (dcmmajor = 0; dcmmajor < nchrdev; dcmmajor++)
1566 if (cdevsw[dcmmajor].d_open == dcmopen)
1567 break;
1568
1569 /* initialize required fields */
1570 cp->cn_dev = makedev(dcmmajor, 0); /* XXX */
1571 cp->cn_pri = CN_DEAD;
1572
1573 /* Abort early if console already forced. */
1574 if (conforced)
1575 return;
1576
1577 console_scan(dcm_console_scan, cp);
1578
1579 #ifdef KGDB_CHEAT
1580 /* XXX this needs to be fixed. */
1581 /*
1582 * This doesn't currently work, at least not with ite consoles;
1583 * the console hasn't been initialized yet.
1584 */
1585 if (major(kgdb_dev) == dcmmajor &&
1586 DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) {
1587 dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate);
1588 if (kgdb_debug_init) {
1589 /*
1590 * We assume that console is ready for us...
1591 * this assumes that a dca or ite console
1592 * has been selected already and will init
1593 * on the first putc.
1594 */
1595 printf("dcm%d: ", DCMUNIT(kgdb_dev));
1596 kgdb_connect(1);
1597 }
1598 }
1599 #endif
1600 }
1601
1602 /* ARGSUSED */
1603 void
1604 dcmcninit(cp)
1605 struct consdev *cp;
1606 {
1607
1608 dcm_cn = (struct dcmdevice *)conaddr;
1609 dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate);
1610 dcmconsinit = 1;
1611 }
1612
1613 /* ARGSUSED */
1614 int
1615 dcmcngetc(dev)
1616 dev_t dev;
1617 {
1618 struct dcmrfifo *fifo;
1619 struct dcmpreg *pp;
1620 u_int head;
1621 int s, c, stat;
1622
1623 pp = dcm_preg(dcm_cn, DCMCONSPORT);
1624
1625 s = splhigh();
1626 head = pp->r_head & RX_MASK;
1627 fifo = &dcm_cn->dcm_rfifos[3-DCMCONSPORT][head>>1];
1628 while (head == (pp->r_tail & RX_MASK))
1629 ;
1630 /*
1631 * If board interrupts are enabled, just let our received char
1632 * interrupt through in case some other port on the board was
1633 * busy. Otherwise we must clear the interrupt.
1634 */
1635 SEM_LOCK(dcm_cn);
1636 if ((dcm_cn->dcm_ic & IC_IE) == 0)
1637 stat = dcm_cn->dcm_iir;
1638 SEM_UNLOCK(dcm_cn);
1639 c = fifo->data_char;
1640 stat = fifo->data_stat;
1641 pp->r_head = (head + 2) & RX_MASK;
1642 splx(s);
1643 return (c);
1644 }
1645
1646 /*
1647 * Console kernel output character routine.
1648 */
1649 /* ARGSUSED */
1650 void
1651 dcmcnputc(dev, c)
1652 dev_t dev;
1653 int c;
1654 {
1655 struct dcmpreg *pp;
1656 unsigned tail;
1657 int s, stat;
1658
1659 pp = dcm_preg(dcm_cn, DCMCONSPORT);
1660
1661 s = splhigh();
1662 #ifdef KGDB
1663 if (dev != kgdb_dev)
1664 #endif
1665 if (dcmconsinit == 0) {
1666 dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate);
1667 dcmconsinit = 1;
1668 }
1669 tail = pp->t_tail & TX_MASK;
1670 while (tail != (pp->t_head & TX_MASK))
1671 ;
1672 dcm_cn->dcm_tfifos[3-DCMCONSPORT][tail].data_char = c;
1673 pp->t_tail = tail = (tail + 1) & TX_MASK;
1674 SEM_LOCK(dcm_cn);
1675 dcm_cn->dcm_cmdtab[DCMCONSPORT].dcm_data |= CT_TX;
1676 dcm_cn->dcm_cr |= (1 << DCMCONSPORT);
1677 SEM_UNLOCK(dcm_cn);
1678 while (tail != (pp->t_head & TX_MASK))
1679 ;
1680 /*
1681 * If board interrupts are enabled, just let our completion
1682 * interrupt through in case some other port on the board
1683 * was busy. Otherwise we must clear the interrupt.
1684 */
1685 if ((dcm_cn->dcm_ic & IC_IE) == 0) {
1686 SEM_LOCK(dcm_cn);
1687 stat = dcm_cn->dcm_iir;
1688 SEM_UNLOCK(dcm_cn);
1689 }
1690 splx(s);
1691 }
1692