1 /* $NetBSD: dcm.c,v 1.80 2008/04/28 20:23:19 martin Exp $ */
4 * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1982, 1986, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
36 * This code is derived from software contributed to Berkeley by
37 * the Systems Programming Group of the University of Utah Computer
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * from Utah: $Hdr: dcm.c 1.29 92/01/21$
66 * @(#)dcm.c 8.4 (Berkeley) 1/12/94
69 * Copyright (c) 1988 University of Utah.
71 * This code is derived from software contributed to Berkeley by
72 * the Systems Programming Group of the University of Utah Computer
75 * Redistribution and use in source and binary forms, with or without
76 * modification, are permitted provided that the following conditions
78 * 1. Redistributions of source code must retain the above copyright
79 * notice, this list of conditions and the following disclaimer.
80 * 2. Redistributions in binary form must reproduce the above copyright
81 * notice, this list of conditions and the following disclaimer in the
82 * documentation and/or other materials provided with the distribution.
83 * 3. All advertising materials mentioning features or use of this software
84 * must display the following acknowledgement:
85 * This product includes software developed by the University of
86 * California, Berkeley and its contributors.
87 * 4. Neither the name of the University nor the names of its contributors
88 * may be used to endorse or promote products derived from this software
89 * without specific prior written permission.
91 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
92 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
95 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
97 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
100 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
103 * from Utah: $Hdr: dcm.c 1.29 92/01/21$
105 * @(#)dcm.c 8.4 (Berkeley) 1/12/94
111 * Test console support.
118 #include <sys/cdefs.h>
119 __KERNEL_RCSID(0, "$NetBSD: dcm.c,v 1.80 2008/04/28 20:23:19 martin Exp $");
121 #include "opt_kgdb.h"
123 #include <sys/param.h>
124 #include <sys/systm.h>
125 #include <sys/ioctl.h>
126 #include <sys/proc.h>
128 #include <sys/conf.h>
129 #include <sys/file.h>
131 #include <sys/kernel.h>
132 #include <sys/syslog.h>
133 #include <sys/time.h>
134 #include <sys/device.h>
135 #include <sys/kauth.h>
137 #include <machine/bus.h>
139 #include <dev/cons.h>
141 #include <hp300/dev/diovar.h>
142 #include <hp300/dev/diodevs.h>
143 #include <hp300/dev/dcmreg.h>
147 #ifndef DEFAULT_BAUD_RATE
148 #define DEFAULT_BAUD_RATE 9600
151 static const struct speedtab dcmspeedtab
[] = {
170 /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */
171 #define DCM_USPERCH(s) (10000000 / (s))
174 * Per board interrupt scheme. 16.7ms is the polling interrupt rate
175 * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms).
178 #define DIS_PERCHAR 1
181 static int dcmistype
= -1; /* -1 == dynamic, 0 == timer, 1 == perchar */
182 static int dcminterval
= 5; /* interval (secs) between checks */
184 int dis_perchar
; /* non-zero if interrupting per char */
185 long dis_time
; /* last time examined */
186 int dis_intr
; /* recv interrupts during last interval */
187 int dis_char
; /* characters read during last interval */
194 #include <machine/remote-sl.h>
196 extern dev_t kgdb_dev
;
197 extern int kgdb_rate
;
198 extern int kgdb_debug_init
;
201 /* #define DCMSTATS */
205 #define DDB_SIOERR 0x01
206 #define DDB_PARAM 0x02
207 #define DDB_INPUT 0x04
208 #define DDB_OUTPUT 0x08
209 #define DDB_INTR 0x10
210 #define DDB_IOCTL 0x20
211 #define DDB_INTSCHM 0x40
212 #define DDB_MODEM 0x80
213 #define DDB_OPENCLOSE 0x100
221 long xints
; /* # of xmit ints */
222 long xchars
; /* # of xmit chars */
223 long xempty
; /* times outq is empty in dcmstart */
224 long xrestarts
; /* times completed while xmitting */
225 long rints
; /* # of recv ints */
226 long rchars
; /* # of recv chars */
227 long xsilo
[DCMXBSIZE
+2]; /* times this many chars xmit on one int */
228 long rsilo
[DCMRBSIZE
+2]; /* times this many chars read on one int */
232 #define DCMUNIT(x) (minor(x) & 0x7ffff)
233 #define DCMDIALOUT(x) (minor(x) & 0x80000)
234 #define DCMBOARD(x) (((x) >> 2) & 0x3f)
235 #define DCMPORT(x) ((x) & 3)
238 * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux,
239 * the distribution panel uses "HP DCE" conventions. If requested via
240 * the device flags, we swap the inputs to something closer to normal DCE,
241 * allowing a straight-through cable to a DTE or a reversed cable
242 * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected;
243 * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect
244 * DSR or make RTS work, though). The following gives the full
245 * details of a cable from this mux panel to a modem:
251 * CTS 4 5 CTS (only needed for CCTS_OFLOW)
253 * "DSR" 9 6 DSR (unneeded)
254 * RI 22 22 RI (unneeded)
258 * "DTR" 6 not connected
260 * "SR" 23 4 RTS (often not needed)
262 #define hp2dce_in(ibits) (iconv[(ibits) & 0xf])
263 static const char iconv
[16] = {
264 0, MI_DM
, MI_CTS
, MI_CTS
|MI_DM
,
265 MI_CD
, MI_CD
|MI_DM
, MI_CD
|MI_CTS
, MI_CD
|MI_CTS
|MI_DM
,
266 MI_RI
, MI_RI
|MI_DM
, MI_RI
|MI_CTS
, MI_RI
|MI_CTS
|MI_DM
,
267 MI_RI
|MI_CD
, MI_RI
|MI_CD
|MI_DM
, MI_RI
|MI_CD
|MI_CTS
,
268 MI_RI
|MI_CD
|MI_CTS
|MI_DM
272 * Note that 8-port boards appear as 2 4-port boards at consecutive
278 device_t sc_dev
; /* generic device glue */
280 bus_space_tag_t sc_bst
;
281 bus_space_handle_t sc_bsh
;
283 struct dcmdevice
*sc_dcm
; /* pointer to hardware */
284 struct tty
*sc_tty
[NDCMPORT
]; /* our tty instances */
285 struct modemreg
*sc_modem
[NDCMPORT
]; /* modem control */
286 char sc_mcndlast
[NDCMPORT
]; /* XXX last modem status for port */
287 short sc_softCAR
; /* mask of ports with soft-carrier */
288 struct dcmischeme sc_scheme
; /* interrupt scheme for board */
291 * Mask of soft-carrier bits in config flags.
293 #define DCM_SOFTCAR 0x0000000f
295 int sc_flags
; /* misc. configuration info */
300 #define DCM_ACTIVE 0x00000001 /* indicates board is alive */
301 #define DCM_ISCONSOLE 0x00000002 /* indicates board is console */
302 #define DCM_STDDCE 0x00000010 /* re-map DCE to standard */
303 #define DCM_FLAGMASK (DCM_STDDCE) /* mask of valid bits in config flags */
306 struct dcmstats sc_stats
; /* metrics gathering */
310 static int dcmintr(void *);
311 static void dcmpint(struct dcm_softc
*, int, int);
312 static void dcmrint(struct dcm_softc
*);
313 static void dcmreadbuf(struct dcm_softc
*, int);
314 static void dcmxint(struct dcm_softc
*, int);
315 static void dcmmint(struct dcm_softc
*, int, int);
317 static int dcmparam(struct tty
*, struct termios
*);
318 static void dcmstart(struct tty
*);
319 static int dcmmctl(dev_t
, int, int);
320 static void dcmsetischeme(int, int);
321 static void dcminit(struct dcmdevice
*, int, int);
323 static int dcmselftest(struct dcm_softc
*);
325 static int dcmcngetc(dev_t
);
326 static void dcmcnputc(dev_t
, int);
328 int dcmcnattach(bus_space_tag_t
, bus_addr_t
, int);
330 static int dcmmatch(device_t
, cfdata_t
, void *);
331 static void dcmattach(device_t
, device_t
, void *);
333 CFATTACH_DECL_NEW(dcm
, sizeof(struct dcm_softc
),
334 dcmmatch
, dcmattach
, NULL
, NULL
);
337 * Stuff for DCM console support. This could probably be done a little
340 static struct dcmdevice
*dcm_cn
= NULL
; /* pointer to hardware */
341 static int dcmconsinit
; /* has been initialized */
343 static int dcm_lastcnpri
= CN_DEAD
; /* XXX last priority */
346 static struct consdev dcm_cons
= {
359 int dcmdefaultrate
= DEFAULT_BAUD_RATE
;
360 int dcmconbrdbusy
= 0;
362 static dev_type_open(dcmopen
);
363 static dev_type_close(dcmclose
);
364 static dev_type_read(dcmread
);
365 static dev_type_write(dcmwrite
);
366 static dev_type_ioctl(dcmioctl
);
367 static dev_type_stop(dcmstop
);
368 static dev_type_tty(dcmtty
);
369 static dev_type_poll(dcmpoll
);
371 const struct cdevsw dcm_cdevsw
= {
372 dcmopen
, dcmclose
, dcmread
, dcmwrite
, dcmioctl
,
373 dcmstop
, dcmtty
, dcmpoll
, nommap
, ttykqfilter
, D_TTY
377 dcmmatch(device_t parent
, cfdata_t cf
, void *aux
)
379 struct dio_attach_args
*da
= aux
;
382 case DIO_DEVICE_ID_DCM
:
383 case DIO_DEVICE_ID_DCMREM
:
391 dcmattach(device_t parent
, device_t self
, void *aux
)
393 struct dcm_softc
*sc
= device_private(self
);
394 struct dio_attach_args
*da
= aux
;
395 struct dcmdevice
*dcm
;
396 int brd
= device_unit(self
);
397 int scode
= da
->da_scode
;
403 if (scode
== dcmconscode
) {
405 sc
->sc_flags
|= DCM_ISCONSOLE
;
408 * We didn't know which unit this would be during
409 * the console probe, so we have to fixup cn_dev here.
410 * Note that we always assume port 1 on the board.
412 cn_tab
->cn_dev
= makedev(cdevsw_lookup_major(&dcm_cdevsw
),
413 (brd
<< 2) | DCMCONSPORT
);
415 sc
->sc_bst
= da
->da_bst
;
416 if (bus_space_map(sc
->sc_bst
, da
->da_addr
, da
->da_size
,
417 BUS_SPACE_MAP_LINEAR
, &sc
->sc_bsh
)) {
418 aprint_error(": can't map registers\n");
421 dcm
= bus_space_vaddr(sc
->sc_bst
, sc
->sc_bsh
);
427 * XXX someone _should_ fix this; the self test screws
428 * autoconfig messages.
430 if ((sc
->sc_flags
& DCM_ISCONSOLE
) && dcmselftest(sc
)) {
432 aprint_error_dev(self
, "self-test failed\n");
436 /* Extract configuration info from flags. */
437 sc
->sc_softCAR
= device_cfdata(self
)->cf_flags
& DCM_SOFTCAR
;
438 sc
->sc_flags
|= device_cfdata(self
)->cf_flags
& DCM_FLAGMASK
;
440 /* Mark our unit as configured. */
441 sc
->sc_flags
|= DCM_ACTIVE
;
443 /* Establish the interrupt handler. */
444 (void)dio_intr_establish(dcmintr
, sc
, da
->da_ipl
, IPL_TTY
);
446 if (dcmistype
== DIS_TIMER
)
447 dcmsetischeme(brd
, DIS_RESET
|DIS_TIMER
);
449 dcmsetischeme(brd
, DIS_RESET
|DIS_PERCHAR
);
451 /* load pointers to modem control */
452 sc
->sc_modem
[0] = &dcm
->dcm_modem0
;
453 sc
->sc_modem
[1] = &dcm
->dcm_modem1
;
454 sc
->sc_modem
[2] = &dcm
->dcm_modem2
;
455 sc
->sc_modem
[3] = &dcm
->dcm_modem3
;
457 /* set DCD (modem) and CTS (flow control) on all ports */
458 if (sc
->sc_flags
& DCM_STDDCE
)
459 mbits
= hp2dce_in(MI_CD
|MI_CTS
);
461 mbits
= MI_CD
|MI_CTS
;
463 for (i
= 0; i
< NDCMPORT
; i
++)
464 sc
->sc_modem
[i
]->mdmmsk
= mbits
;
467 * Get current state of mdmin register on all ports, so that
468 * deltas will work properly.
470 for (i
= 0; i
< NDCMPORT
; i
++) {
471 code
= sc
->sc_modem
[i
]->mdmin
;
472 if (sc
->sc_flags
& DCM_STDDCE
)
473 code
= hp2dce_in(code
);
474 sc
->sc_mcndlast
[i
] = code
;
477 dcm
->dcm_ic
= IC_IE
; /* turn all interrupts on */
480 * Need to reset baud rate, etc. of next print so reset dcmconsinit.
481 * Also make sure console is always "hardwired"
483 if (sc
->sc_flags
& DCM_ISCONSOLE
) {
485 sc
->sc_softCAR
|= (1 << DCMCONSPORT
);
486 aprint_normal(": console on port %d\n", DCMCONSPORT
);
491 if (cdevsw_lookup(kgdb_dev
) == &dcm_cdevsw
&&
492 DCMBOARD(DCMUNIT(kgdb_dev
)) == brd
) {
493 if (dcmconsole
== DCMUNIT(kgdb_dev
)) /* XXX fixme */
494 kgdb_dev
= NODEV
; /* can't debug over console port */
497 * The following could potentially be replaced
498 * by the corresponding code in dcmcnprobe.
501 dcminit(dcm
, DCMPORT(DCMUNIT(kgdb_dev
)),
503 if (kgdb_debug_init
) {
504 aprint_normal_dev(self
, "port %d: ",
505 DCMPORT(DCMUNIT(kgdb_dev
)));
508 aprint_normal_dev(self
,
509 "port %d: kgdb enabled\n",
510 DCMPORT(DCMUNIT(kgdb_dev
)));
512 /* end could be replaced */
513 #endif /* KGDB_CHEAT */
520 dcmopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
522 struct dcm_softc
*sc
;
525 int error
= 0, mbits
, s
;
528 brd
= DCMBOARD(unit
);
529 port
= DCMPORT(unit
);
531 sc
= device_lookup_private(&dcm_cd
, brd
);
535 if ((sc
->sc_flags
& DCM_ACTIVE
) == 0)
538 if (sc
->sc_tty
[port
] == NULL
) {
539 tp
= sc
->sc_tty
[port
] = ttymalloc();
542 tp
= sc
->sc_tty
[port
];
544 tp
->t_oproc
= dcmstart
;
545 tp
->t_param
= dcmparam
;
548 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
553 if ((tp
->t_state
& TS_ISOPEN
) == 0 && tp
->t_wopen
== 0) {
555 * Sanity clause: reset the card on first open.
556 * The card might be left in an inconsistent state
557 * if the card memory is read inadvertently.
559 dcminit(sc
->sc_dcm
, port
, dcmdefaultrate
);
562 tp
->t_iflag
= TTYDEF_IFLAG
;
563 tp
->t_oflag
= TTYDEF_OFLAG
;
564 tp
->t_cflag
= TTYDEF_CFLAG
;
565 tp
->t_lflag
= TTYDEF_LFLAG
;
566 tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
568 (void) dcmparam(tp
, &tp
->t_termios
);
571 /* Set modem control state. */
573 if (sc
->sc_flags
& DCM_STDDCE
)
574 mbits
|= MO_SR
; /* pin 23, could be used as RTS */
576 (void) dcmmctl(dev
, mbits
, DMSET
); /* enable port */
578 /* Set soft-carrier if so configured. */
579 if ((sc
->sc_softCAR
& (1 << port
)) ||
580 (dcmmctl(dev
, MO_OFF
, DMGET
) & MI_CD
))
581 tp
->t_state
|= TS_CARR_ON
;
587 if (dcmdebug
& DDB_MODEM
)
588 printf("%s: dcmopen port %d softcarr %c\n",
589 device_xname(sc
->sc_dev
), port
,
590 (tp
->t_state
& TS_CARR_ON
) ? '1' : '0');
593 error
= ttyopen(tp
, DCMDIALOUT(dev
), (flag
& O_NONBLOCK
));
598 if (dcmdebug
& DDB_OPENCLOSE
)
599 printf("%s port %d: dcmopen: st %x fl %x\n",
600 device_xname(sc
->sc_dev
), port
, tp
->t_state
, tp
->t_flags
);
602 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
610 dcmclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
612 int s
, unit
, board
, port
;
613 struct dcm_softc
*sc
;
617 board
= DCMBOARD(unit
);
618 port
= DCMPORT(unit
);
620 sc
= device_lookup_private(&dcm_cd
,board
);
621 tp
= sc
->sc_tty
[port
];
623 (*tp
->t_linesw
->l_close
)(tp
, flag
);
627 if (tp
->t_cflag
& HUPCL
|| tp
->t_wopen
!= 0 ||
628 (tp
->t_state
& TS_ISOPEN
) == 0)
629 (void) dcmmctl(dev
, MO_OFF
, DMSET
);
631 if (dcmdebug
& DDB_OPENCLOSE
)
632 printf("%s port %d: dcmclose: st %x fl %x\n",
633 device_xname(sc
->sc_dev
), port
, tp
->t_state
, tp
->t_flags
);
640 sc
->sc_tty
[port
] == NULL
;
646 dcmread(dev_t dev
, struct uio
*uio
, int flag
)
648 int unit
, board
, port
;
649 struct dcm_softc
*sc
;
653 board
= DCMBOARD(unit
);
654 port
= DCMPORT(unit
);
656 sc
= device_lookup_private(&dcm_cd
,board
);
657 tp
= sc
->sc_tty
[port
];
659 return (*tp
->t_linesw
->l_read
)(tp
, uio
, flag
);
663 dcmwrite(dev_t dev
, struct uio
*uio
, int flag
)
665 int unit
, board
, port
;
666 struct dcm_softc
*sc
;
670 board
= DCMBOARD(unit
);
671 port
= DCMPORT(unit
);
673 sc
= device_lookup_private(&dcm_cd
, board
);
674 tp
= sc
->sc_tty
[port
];
676 return (*tp
->t_linesw
->l_write
)(tp
, uio
, flag
);
680 dcmpoll(dev_t dev
, int events
, struct lwp
*l
)
682 int unit
, board
, port
;
683 struct dcm_softc
*sc
;
687 board
= DCMBOARD(unit
);
688 port
= DCMPORT(unit
);
690 sc
= device_lookup_private(&dcm_cd
, board
);
691 tp
= sc
->sc_tty
[port
];
693 return (*tp
->t_linesw
->l_poll
)(tp
, events
, l
);
699 int unit
, board
, port
;
700 struct dcm_softc
*sc
;
703 board
= DCMBOARD(unit
);
704 port
= DCMPORT(unit
);
706 sc
= device_lookup_private(&dcm_cd
, board
);
708 return sc
->sc_tty
[port
];
714 struct dcm_softc
*sc
= arg
;
715 struct dcmdevice
*dcm
= sc
->sc_dcm
;
716 struct dcmischeme
*dis
= &sc
->sc_scheme
;
717 int brd
= device_unit(sc
->sc_dev
);
719 int pcnd
[4], mcode
, mcnd
[4];
722 * Do all guarded accesses right off to minimize
723 * block out of hardware.
726 if ((dcm
->dcm_ic
& IC_IR
) == 0) {
730 for (i
= 0; i
< 4; i
++) {
731 pcnd
[i
] = dcm
->dcm_icrtab
[i
].dcm_data
;
732 dcm
->dcm_icrtab
[i
].dcm_data
= 0;
733 code
= sc
->sc_modem
[i
]->mdmin
;
734 if (sc
->sc_flags
& DCM_STDDCE
)
735 code
= hp2dce_in(code
);
738 code
= dcm
->dcm_iir
& IIR_MASK
;
739 dcm
->dcm_iir
= 0; /* XXX doc claims read clears interrupt?! */
740 mcode
= dcm
->dcm_modemintr
;
741 dcm
->dcm_modemintr
= 0;
745 if (dcmdebug
& DDB_INTR
) {
746 printf("%s: dcmintr: iir %x pc %x/%x/%x/%x ",
747 device_xname(sc
->sc_dev
), code
, pcnd
[0], pcnd
[1],
749 printf("miir %x mc %x/%x/%x/%x\n",
750 mcode
, mcnd
[0], mcnd
[1], mcnd
[2], mcnd
[3]);
753 if (code
& IIR_TIMEO
)
755 if (code
& IIR_PORT0
)
756 dcmpint(sc
, 0, pcnd
[0]);
757 if (code
& IIR_PORT1
)
758 dcmpint(sc
, 1, pcnd
[1]);
759 if (code
& IIR_PORT2
)
760 dcmpint(sc
, 2, pcnd
[2]);
761 if (code
& IIR_PORT3
)
762 dcmpint(sc
, 3, pcnd
[3]);
763 if (code
& IIR_MODM
) {
764 if (mcode
== 0 || mcode
& 0x1) /* mcode==0 -> 98642 board */
765 dcmmint(sc
, 0, mcnd
[0]);
767 dcmmint(sc
, 1, mcnd
[1]);
769 dcmmint(sc
, 2, mcnd
[2]);
771 dcmmint(sc
, 3, mcnd
[3]);
775 * Chalk up a receiver interrupt if the timer running or one of
776 * the ports reports a special character interrupt.
778 if ((code
& IIR_TIMEO
) ||
779 ((pcnd
[0]|pcnd
[1]|pcnd
[2]|pcnd
[3]) & IT_SPEC
))
782 * See if it is time to check/change the interrupt rate.
785 (i
= time_second
- dis
->dis_time
) >= dcminterval
) {
787 * If currently per-character and averaged over 70 interrupts
788 * per-second (66 is threshold of 600 baud) in last interval,
789 * switch to timer mode.
791 * XXX decay counts ala load average to avoid spikes?
793 if (dis
->dis_perchar
&& dis
->dis_intr
> 70 * i
)
794 dcmsetischeme(brd
, DIS_TIMER
);
796 * If currently using timer and had more interrupts than
797 * received characters in the last interval, switch back
798 * to per-character. Note that after changing to per-char
799 * we must process any characters already in the queue
800 * since they may have arrived before the bitmap was setup.
804 else if (!dis
->dis_perchar
&& dis
->dis_intr
> dis
->dis_char
) {
805 dcmsetischeme(brd
, DIS_PERCHAR
);
808 dis
->dis_intr
= dis
->dis_char
= 0;
809 dis
->dis_time
= time_second
;
815 * Port interrupt. Can be two things:
816 * First, it might be a special character (exception interrupt);
817 * Second, it may be a buffer empty (transmit interrupt);
820 dcmpint(struct dcm_softc
*sc
, int port
, int code
)
824 dcmreadbuf(sc
, port
);
830 dcmrint(struct dcm_softc
*sc
)
834 for (port
= 0; port
< NDCMPORT
; port
++)
835 dcmreadbuf(sc
, port
);
839 dcmreadbuf(struct dcm_softc
*sc
, int port
)
841 struct dcmdevice
*dcm
= sc
->sc_dcm
;
842 struct dcmpreg
*pp
= dcm_preg(dcm
, port
);
843 struct dcmrfifo
*fifo
;
849 struct dcmstats
*dsp
= &sc
->sc_stats
;
853 tp
= sc
->sc_tty
[port
];
857 if ((tp
->t_state
& TS_ISOPEN
) == 0) {
861 maj
= cdevsw_lookup_major(&dcm_cdevsw
);
863 if ((makedev(maj
, minor(tp
->t_dev
)) == kgdb_dev
) &&
864 (head
= pp
->r_head
& RX_MASK
) != (pp
->r_tail
& RX_MASK
) &&
865 dcm
->dcm_rfifos
[3-port
][head
>>1].data_char
== FRAME_START
) {
866 pp
->r_head
= (head
+ 2) & RX_MASK
;
867 kgdb_connect(0); /* trap into kgdb */
871 pp
->r_head
= pp
->r_tail
& RX_MASK
;
875 head
= pp
->r_head
& RX_MASK
;
876 fifo
= &dcm
->dcm_rfifos
[3-port
][head
>>1];
878 * XXX upper bound on how many chars we will take in one swallow?
880 while (head
!= (pp
->r_tail
& RX_MASK
)) {
882 * Get character/status and update head pointer as fast
883 * as possible to make room for more characters.
886 stat
= fifo
->data_stat
;
887 head
= (head
+ 2) & RX_MASK
;
889 fifo
= head
? fifo
+1 : &dcm
->dcm_rfifos
[3-port
][0];
893 if (dcmdebug
& DDB_INPUT
)
894 printf("%s port %d: "
895 "dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n",
896 device_xname(sc
->sc_dev
), port
,
897 c
&0xFF, c
, stat
&0xFF,
898 tp
->t_flags
, head
, pp
->r_tail
);
901 * Check for and handle errors
903 if (stat
& RD_MASK
) {
905 if (dcmdebug
& (DDB_INPUT
|DDB_SIOERR
))
906 printf("%s port %d: "
907 "dcmreadbuf: err: c%x('%c') s%x\n",
908 device_xname(sc
->sc_dev
), port
,
911 if (stat
& (RD_BD
| RD_FE
))
913 else if (stat
& RD_PE
)
915 else if (stat
& RD_OVF
)
917 "%s port %d: silo overflow\n",
918 device_xname(sc
->sc_dev
), port
);
919 else if (stat
& RD_OE
)
921 "%s port %d: uart overflow\n",
922 device_xname(sc
->sc_dev
), port
);
924 (*tp
->t_linesw
->l_rint
)(c
, tp
);
926 sc
->sc_scheme
.dis_char
+= nch
;
930 if (nch
<= DCMRBSIZE
)
933 dsp
->rsilo
[DCMRBSIZE
+1]++;
938 dcmxint(struct dcm_softc
*sc
, int port
)
942 tp
= sc
->sc_tty
[port
];
943 if (tp
== NULL
|| (tp
->t_state
& TS_ISOPEN
) == 0)
946 tp
->t_state
&= ~TS_BUSY
;
947 if (tp
->t_state
& TS_FLUSH
)
948 tp
->t_state
&= ~TS_FLUSH
;
949 (*tp
->t_linesw
->l_start
)(tp
);
953 dcmmint(struct dcm_softc
*sc
, int port
, int mcnd
)
957 struct dcmdevice
*dcm
= sc
->sc_dcm
;
960 if (dcmdebug
& DDB_MODEM
)
961 printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n",
962 device_xname(sc
->sc_dev
), port
, mcnd
,
963 sc
->sc_mcndlast
[port
]);
965 delta
= mcnd
^ sc
->sc_mcndlast
[port
];
966 sc
->sc_mcndlast
[port
] = mcnd
;
967 tp
= sc
->sc_tty
[port
];
968 if (tp
== NULL
|| (tp
->t_state
& TS_ISOPEN
) == 0)
971 if ((delta
& MI_CTS
) && (tp
->t_state
& TS_ISOPEN
) &&
972 (tp
->t_cflag
& CCTS_OFLOW
)) {
974 tp
->t_state
&= ~TS_TTSTOP
;
977 tp
->t_state
|= TS_TTSTOP
; /* inline dcmstop */
981 (void)(*tp
->t_linesw
->l_modem
)(tp
, 1);
982 else if ((sc
->sc_softCAR
& (1 << port
)) == 0 &&
983 (*tp
->t_linesw
->l_modem
)(tp
, 0) == 0) {
984 sc
->sc_modem
[port
]->mdmout
= MO_OFF
;
986 dcm
->dcm_modemchng
|= (1 << port
);
987 dcm
->dcm_cr
|= CR_MODM
;
989 DELAY(10); /* time to change lines */
995 dcmioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
997 struct dcm_softc
*sc
;
999 struct dcmdevice
*dcm
;
1000 int board
, port
, unit
= DCMUNIT(dev
);
1003 port
= DCMPORT(unit
);
1004 board
= DCMBOARD(unit
);
1006 sc
= device_lookup_private(&dcm_cd
, board
);
1008 tp
= sc
->sc_tty
[port
];
1011 if (dcmdebug
& DDB_IOCTL
)
1012 printf("%s port %d: dcmioctl: cmd %lx data %x flag %x\n",
1013 device_xname(sc
->sc_dev
), port
, cmd
, *(int *)data
, flag
);
1016 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
1017 if (error
!= EPASSTHROUGH
)
1020 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
1021 if (error
!= EPASSTHROUGH
)
1027 * Wait for transmitter buffer to empty
1030 while (dcm
->dcm_thead
[port
].ptr
!= dcm
->dcm_ttail
[port
].ptr
)
1031 DELAY(DCM_USPERCH(tp
->t_ospeed
));
1033 dcm
->dcm_cmdtab
[port
].dcm_data
|= CT_BRK
;
1034 dcm
->dcm_cr
|= (1 << port
); /* start break */
1041 dcm
->dcm_cmdtab
[port
].dcm_data
|= CT_BRK
;
1042 dcm
->dcm_cr
|= (1 << port
); /* end break */
1047 (void) dcmmctl(dev
, MO_ON
, DMBIS
);
1051 (void) dcmmctl(dev
, MO_ON
, DMBIC
);
1055 (void) dcmmctl(dev
, *(int *)data
, DMSET
);
1059 (void) dcmmctl(dev
, *(int *)data
, DMBIS
);
1063 (void) dcmmctl(dev
, *(int *)data
, DMBIC
);
1067 *(int *)data
= dcmmctl(dev
, 0, DMGET
);
1073 if ((sc
->sc_softCAR
& (1 << port
)))
1074 bits
|= TIOCFLAG_SOFTCAR
;
1076 if (tp
->t_cflag
& CLOCAL
)
1077 bits
|= TIOCFLAG_CLOCAL
;
1079 *(int *)data
= bits
;
1086 if (kauth_authorize_device_tty(l
->l_cred
,
1087 KAUTH_DEVICE_TTY_PRIVSET
, tp
))
1090 userbits
= *(int *)data
;
1092 if ((userbits
& TIOCFLAG_SOFTCAR
) ||
1093 ((sc
->sc_flags
& DCM_ISCONSOLE
) &&
1094 (port
== DCMCONSPORT
)))
1095 sc
->sc_softCAR
|= (1 << port
);
1097 if (userbits
& TIOCFLAG_CLOCAL
)
1098 tp
->t_cflag
|= CLOCAL
;
1104 return EPASSTHROUGH
;
1110 dcmparam(struct tty
*tp
, struct termios
*t
)
1112 struct dcm_softc
*sc
;
1113 struct dcmdevice
*dcm
;
1114 int unit
, board
, port
, mode
, cflag
= t
->c_cflag
;
1115 int ospeed
= ttspeedtab(t
->c_ospeed
, dcmspeedtab
);
1117 unit
= DCMUNIT(tp
->t_dev
);
1118 board
= DCMBOARD(unit
);
1119 port
= DCMPORT(unit
);
1121 sc
= device_lookup_private(&dcm_cd
, board
);
1124 /* check requested parameters */
1125 if (ospeed
< 0 || (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
))
1127 /* and copy to tty */
1128 tp
->t_ispeed
= t
->c_ispeed
;
1129 tp
->t_ospeed
= t
->c_ospeed
;
1130 tp
->t_cflag
= cflag
;
1132 (void)dcmmctl(DCMUNIT(tp
->t_dev
), MO_OFF
, DMSET
);
1137 switch (cflag
&CSIZE
) {
1139 mode
= LC_5BITS
; break;
1141 mode
= LC_6BITS
; break;
1143 mode
= LC_7BITS
; break;
1145 mode
= LC_8BITS
; break;
1158 if (dcmdebug
& DDB_PARAM
)
1159 printf("%s port %d: "
1160 "dcmparam: cflag %x mode %x speed %d uperch %d\n",
1161 device_xname(sc
->sc_dev
), port
, cflag
, mode
, tp
->t_ospeed
,
1162 DCM_USPERCH(tp
->t_ospeed
));
1166 * Wait for transmitter buffer to empty.
1168 while (dcm
->dcm_thead
[port
].ptr
!= dcm
->dcm_ttail
[port
].ptr
)
1169 DELAY(DCM_USPERCH(tp
->t_ospeed
));
1171 * Make changes known to hardware.
1173 dcm
->dcm_data
[port
].dcm_baud
= ospeed
;
1174 dcm
->dcm_data
[port
].dcm_conf
= mode
;
1176 dcm
->dcm_cmdtab
[port
].dcm_data
|= CT_CON
;
1177 dcm
->dcm_cr
|= (1 << port
);
1180 * Delay for config change to take place. Weighted by baud.
1181 * XXX why do we do this?
1183 DELAY(16 * DCM_USPERCH(tp
->t_ospeed
));
1188 dcmstart(struct tty
*tp
)
1190 struct dcm_softc
*sc
;
1191 struct dcmdevice
*dcm
;
1193 struct dcmtfifo
*fifo
;
1195 u_int head
, tail
, next
;
1196 int unit
, board
, port
, nch
;
1200 struct dcmstats
*dsp
= &sc
->sc_stats
;
1204 unit
= DCMUNIT(tp
->t_dev
);
1205 board
= DCMBOARD(unit
);
1206 port
= DCMPORT(unit
);
1208 sc
= device_lookup_private(&dcm_cd
, board
);
1216 if (dcmdebug
& DDB_OUTPUT
)
1217 printf("%s port %d: dcmstart: state %x flags %x outcc %d\n",
1218 device_xname(sc
->sc_dev
), port
, tp
->t_state
, tp
->t_flags
,
1221 if (tp
->t_state
& (TS_TIMEOUT
|TS_BUSY
|TS_TTSTOP
))
1230 pp
= dcm_preg(dcm
, port
);
1231 tail
= pp
->t_tail
& TX_MASK
;
1232 next
= (tail
+ 1) & TX_MASK
;
1233 head
= pp
->t_head
& TX_MASK
;
1236 fifo
= &dcm
->dcm_tfifos
[3-port
][tail
];
1238 nch
= q_to_b(&tp
->t_outq
, buf
, (head
- next
) & TX_MASK
);
1243 if (dcmdebug
& DDB_OUTPUT
)
1244 printf("\thead %x tail %x nch %d\n", head
, tail
, nch
);
1247 * Loop transmitting all the characters we can.
1249 for (bp
= buf
; --nch
>= 0; bp
++) {
1250 fifo
->data_char
= *bp
;
1253 * If this is the first character,
1254 * get the hardware moving right now.
1257 tp
->t_state
|= TS_BUSY
;
1259 dcm
->dcm_cmdtab
[port
].dcm_data
|= CT_TX
;
1260 dcm
->dcm_cr
|= (1 << port
);
1264 fifo
= tail
? fifo
+1 : &dcm
->dcm_tfifos
[3-port
][0];
1265 next
= (next
+ 1) & TX_MASK
;
1268 * Head changed while we were loading the buffer,
1269 * go back and load some more if we can.
1271 if (tp
->t_outq
.c_cc
&& head
!= (pp
->t_head
& TX_MASK
)) {
1275 head
= pp
->t_head
& TX_MASK
;
1280 * Kick it one last time in case it finished while we were
1281 * loading the last bunch.
1284 tp
->t_state
|= TS_BUSY
;
1286 dcm
->dcm_cmdtab
[port
].dcm_data
|= CT_TX
;
1287 dcm
->dcm_cr
|= (1 << port
);
1291 if (dcmdebug
& DDB_INTR
)
1292 printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n",
1293 device_xname(sc
->sc_dev
), port
, head
, tail
,
1299 if (tch
<= DCMXBSIZE
)
1302 dsp
->xsilo
[DCMXBSIZE
+1]++;
1308 * Stop output on a line.
1311 dcmstop(struct tty
*tp
, int flag
)
1316 if (tp
->t_state
& TS_BUSY
) {
1317 /* XXX is there some way to safely stop transmission? */
1318 if ((tp
->t_state
&TS_TTSTOP
) == 0)
1319 tp
->t_state
|= TS_FLUSH
;
1328 dcmmctl(dev_t dev
, int bits
, int how
)
1330 struct dcm_softc
*sc
;
1331 struct dcmdevice
*dcm
;
1332 int s
, unit
, brd
, port
, hit
= 0;
1334 unit
= DCMUNIT(dev
);
1335 brd
= DCMBOARD(unit
);
1336 port
= DCMPORT(unit
);
1338 sc
= device_lookup_private(&dcm_cd
, brd
);
1342 if (dcmdebug
& DDB_MODEM
)
1343 printf("%s port %d: dcmmctl: bits 0x%x how %x\n",
1344 device_xname(sc
->sc_dev
), port
, bits
, how
);
1351 sc
->sc_modem
[port
]->mdmout
= bits
;
1356 sc
->sc_modem
[port
]->mdmout
|= bits
;
1361 sc
->sc_modem
[port
]->mdmout
&= ~bits
;
1366 bits
= sc
->sc_modem
[port
]->mdmin
;
1367 if (sc
->sc_flags
& DCM_STDDCE
)
1368 bits
= hp2dce_in(bits
);
1373 dcm
->dcm_modemchng
|= 1<<(unit
& 3);
1374 dcm
->dcm_cr
|= CR_MODM
;
1376 DELAY(10); /* delay until done */
1383 * Set board to either interrupt per-character or at a fixed interval.
1386 dcmsetischeme(int brd
, int flags
)
1388 struct dcm_softc
*sc
= device_lookup_private(&dcm_cd
, brd
);
1389 struct dcmdevice
*dcm
= sc
->sc_dcm
;
1390 struct dcmischeme
*dis
= &sc
->sc_scheme
;
1393 int perchar
= flags
& DIS_PERCHAR
;
1396 if (dcmdebug
& DDB_INTSCHM
)
1397 printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n",
1398 device_xname(sc
->sc_dev
), perchar
, dis
->dis_perchar
,
1399 dis
->dis_intr
, dis
->dis_char
);
1400 if ((flags
& DIS_RESET
) == 0 && perchar
== dis
->dis_perchar
) {
1401 printf("%s: dcmsetischeme: redundent request %d\n",
1402 device_xname(sc
->sc_dev
), perchar
);
1407 * If perchar is non-zero, we enable interrupts on all characters
1408 * otherwise we disable perchar interrupts and use periodic
1409 * polling interrupts.
1411 dis
->dis_perchar
= perchar
;
1412 mask
= perchar
? 0xf : 0x0;
1413 for (i
= 0; i
< 256; i
++)
1414 dcm
->dcm_bmap
[i
].data_data
= mask
;
1416 * Don't slow down tandem mode, interrupt on flow control
1417 * chars for any port on the board.
1423 for (i
= 0; i
< NDCMPORT
; i
++) {
1426 if ((c
= tp
->t_cc
[VSTART
]) != _POSIX_VDISABLE
)
1427 dcm
->dcm_bmap
[c
].data_data
|= (1 << i
);
1428 if ((c
= tp
->t_cc
[VSTOP
]) != _POSIX_VDISABLE
)
1429 dcm
->dcm_bmap
[c
].data_data
|= (1 << i
);
1433 * Board starts with timer disabled so if first call is to
1434 * set perchar mode then we don't want to toggle the timer.
1436 if (flags
== (DIS_RESET
|DIS_PERCHAR
))
1439 * Toggle card 16.7ms interrupts (we first make sure that card
1440 * has cleared the bit so it will see the toggle).
1442 while (dcm
->dcm_cr
& CR_TIMER
)
1445 dcm
->dcm_cr
|= CR_TIMER
;
1450 dcminit(struct dcmdevice
*dcm
, int port
, int rate
)
1454 mode
= LC_8BITS
| LC_1STOP
;
1459 * Wait for transmitter buffer to empty.
1461 while (dcm
->dcm_thead
[port
].ptr
!= dcm
->dcm_ttail
[port
].ptr
)
1462 DELAY(DCM_USPERCH(rate
));
1465 * Make changes known to hardware.
1467 dcm
->dcm_data
[port
].dcm_baud
= ttspeedtab(rate
, dcmspeedtab
);
1468 dcm
->dcm_data
[port
].dcm_conf
= mode
;
1470 dcm
->dcm_cmdtab
[port
].dcm_data
|= CT_CON
;
1471 dcm
->dcm_cr
|= (1 << port
);
1475 * Delay for config change to take place. Weighted by baud.
1476 * XXX why do we do this?
1478 DELAY(16 * DCM_USPERCH(rate
));
1483 * Empirically derived self-test magic
1486 dcmselftest(struct dcm_softc
*sc
)
1488 struct dcmdevice
*dcm
= sc
->sc_dcm
;
1495 dcm
->dcm_rsid
= DCMRS
;
1496 DELAY(50000); /* 5000 is not long enough */
1498 dcm
->dcm_ic
= IC_IE
;
1499 dcm
->dcm_cr
= CR_SELFT
;
1500 while ((dcm
->dcm_ic
& IC_IR
) == 0) {
1501 if (++timo
== 20000)
1505 DELAY(50000); /* XXX why is this needed ???? */
1506 while ((dcm
->dcm_iir
& IIR_SELFT
) == 0) {
1507 if (++timo
== 400000)
1511 DELAY(50000); /* XXX why is this needed ???? */
1512 if (dcm
->dcm_stcon
!= ST_OK
) {
1514 if (hd
->hp_args
->hw_sc
!= conscode
)
1515 aprint_error_dev(sc
->sc_dev
, "self test failed: %x\n",
1520 dcm
->dcm_ic
= IC_ID
;
1529 * Following are all routines needed for DCM to act as console
1533 dcmcnattach(bus_space_tag_t bst
, bus_addr_t addr
, int scode
)
1535 bus_space_handle_t bsh
;
1537 struct dcmdevice
*dcm
;
1540 if (bus_space_map(bst
, addr
, DIOCSIZE
, 0, &bsh
))
1543 va
= bus_space_vaddr(bst
, bsh
);
1544 dcm
= (struct dcmdevice
*)va
;
1546 switch (dcm
->dcm_rsid
) {
1556 dcminit(dcm
, DCMCONSPORT
, dcmdefaultrate
);
1558 dcmconscode
= scode
;
1561 /* locate the major number */
1562 maj
= cdevsw_lookup_major(&dcm_cdevsw
);
1564 /* initialize required fields */
1566 cn_tab
->cn_dev
= makedev(maj
, 0);
1569 /* XXX this needs to be fixed. */
1571 * This doesn't currently work, at least not with ite consoles;
1572 * the console hasn't been initialized yet.
1574 if (major(kgdb_dev
) == maj
&&
1575 DCMBOARD(DCMUNIT(kgdb_dev
)) == DCMBOARD(unit
)) {
1576 dcminit(dcm_cn
, DCMPORT(DCMUNIT(kgdb_dev
)), kgdb_rate
);
1577 if (kgdb_debug_init
) {
1579 * We assume that console is ready for us...
1580 * this assumes that a dca or ite console
1581 * has been selected already and will init
1582 * on the first putc.
1584 printf("dcm%d: ", DCMUNIT(kgdb_dev
));
1594 bus_space_unmap(bst
, bsh
, DIOCSIZE
);
1600 dcmcngetc(dev_t dev
)
1602 struct dcmrfifo
*fifo
;
1607 pp
= dcm_preg(dcm_cn
, DCMCONSPORT
);
1610 head
= pp
->r_head
& RX_MASK
;
1611 fifo
= &dcm_cn
->dcm_rfifos
[3-DCMCONSPORT
][head
>>1];
1612 while (head
== (pp
->r_tail
& RX_MASK
))
1615 * If board interrupts are enabled, just let our received char
1616 * interrupt through in case some other port on the board was
1617 * busy. Otherwise we must clear the interrupt.
1620 if ((dcm_cn
->dcm_ic
& IC_IE
) == 0)
1621 stat
= dcm_cn
->dcm_iir
;
1623 c
= fifo
->data_char
;
1624 stat
= fifo
->data_stat
;
1625 pp
->r_head
= (head
+ 2) & RX_MASK
;
1631 * Console kernel output character routine.
1635 dcmcnputc(dev_t dev
, int c
)
1641 pp
= dcm_preg(dcm_cn
, DCMCONSPORT
);
1645 if (dev
!= kgdb_dev
)
1647 if (dcmconsinit
== 0) {
1648 dcminit(dcm_cn
, DCMCONSPORT
, dcmdefaultrate
);
1651 tail
= pp
->t_tail
& TX_MASK
;
1652 while (tail
!= (pp
->t_head
& TX_MASK
))
1654 dcm_cn
->dcm_tfifos
[3-DCMCONSPORT
][tail
].data_char
= c
;
1655 pp
->t_tail
= tail
= (tail
+ 1) & TX_MASK
;
1657 dcm_cn
->dcm_cmdtab
[DCMCONSPORT
].dcm_data
|= CT_TX
;
1658 dcm_cn
->dcm_cr
|= (1 << DCMCONSPORT
);
1660 while (tail
!= (pp
->t_head
& TX_MASK
))
1663 * If board interrupts are enabled, just let our completion
1664 * interrupt through in case some other port on the board
1665 * was busy. Otherwise we must clear the interrupt.
1667 if ((dcm_cn
->dcm_ic
& IC_IE
) == 0) {
1669 stat
= dcm_cn
->dcm_iir
;