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