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