1 /* $NetBSD: dhu.c,v 1.54 2008/05/27 14:13:41 ad Exp $ */
3 * Copyright (c) 2003, Hugh Graham.
4 * Copyright (c) 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Ralph Campbell and Rick Macklem.
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.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * Copyright (c) 1996 Ken C. Wellsch. All rights reserved.
38 * This code is derived from software contributed to Berkeley by
39 * Ralph Campbell and Rick Macklem.
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. All advertising materials mentioning features or use of this software
50 * must display the following acknowledgement:
51 * This product includes software developed by the University of
52 * California, Berkeley and its contributors.
53 * 4. Neither the name of the University nor the names of its contributors
54 * may be used to endorse or promote products derived from this software
55 * without specific prior written permission.
57 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
58 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
59 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
60 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
61 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
62 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
63 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
64 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
65 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: dhu.c,v 1.54 2008/05/27 14:13:41 ad Exp $");
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/ioctl.h>
82 #include <sys/kernel.h>
83 #include <sys/syslog.h>
84 #include <sys/device.h>
85 #include <sys/kauth.h>
88 #include <machine/scb.h>
90 #include <dev/qbus/ubavar.h>
92 #include <dev/qbus/dhureg.h>
96 /* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */
100 #define DHU_M2U(c) ((c)>>4) /* convert minor(dev) to unit # */
101 #define DHU_LINE(u) ((u)&0xF) /* extract line # from minor(dev) */
104 device_t sc_dev
; /* Device struct used by config */
105 struct evcnt sc_rintrcnt
; /* Interrupt statistics */
106 struct evcnt sc_tintrcnt
; /* Interrupt statistics */
107 int sc_type
; /* controller type, DHU or DHV */
108 int sc_lines
; /* number of lines */
109 bus_space_tag_t sc_iot
;
110 bus_space_handle_t sc_ioh
;
111 bus_dma_tag_t sc_dmat
;
113 struct tty
*dhu_tty
; /* what we work on */
114 bus_dmamap_t dhu_dmah
;
115 int dhu_state
; /* to manage TX output status */
116 short dhu_cc
; /* character count on TX */
117 short dhu_modem
; /* modem bits state */
121 #define IS_DHU 16 /* Unibus DHU-11 board linecount */
122 #define IS_DHV 8 /* Q-bus DHV-11 or DHQ-11 */
124 #define STATE_IDLE 000 /* no current output in progress */
125 #define STATE_DMA_RUNNING 001 /* DMA TX in progress */
126 #define STATE_DMA_STOPPED 002 /* DMA TX was aborted */
127 #define STATE_TX_ONE_CHAR 004 /* did a single char directly */
129 /* Flags used to monitor modem bits, make them understood outside driver */
131 #define DML_DTR TIOCM_DTR
132 #define DML_RTS TIOCM_RTS
133 #define DML_CTS TIOCM_CTS
134 #define DML_DCD TIOCM_CD
135 #define DML_RI TIOCM_RI
136 #define DML_DSR TIOCM_DSR
137 #define DML_BRK 0100000 /* no equivalent, we will mask */
139 #define DHU_READ_WORD(reg) \
140 bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
141 #define DHU_WRITE_WORD(reg, val) \
142 bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
143 #define DHU_READ_BYTE(reg) \
144 bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg)
145 #define DHU_WRITE_BYTE(reg, val) \
146 bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
149 /* On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */
150 /* a baud rate from the same group. So limiting to B is likely */
151 /* best, although clone boards like the ABLE QHV allow all settings. */
153 static const struct speedtab dhuspeedtab
[] = {
154 { 0, 0 }, /* Groups */
155 { 50, DHU_LPR_B50
}, /* A */
156 { 75, DHU_LPR_B75
}, /* B */
157 { 110, DHU_LPR_B110
}, /* A and B */
158 { 134, DHU_LPR_B134
}, /* A and B */
159 { 150, DHU_LPR_B150
}, /* B */
160 { 300, DHU_LPR_B300
}, /* A and B */
161 { 600, DHU_LPR_B600
}, /* A and B */
162 { 1200, DHU_LPR_B1200
}, /* A and B */
163 { 1800, DHU_LPR_B1800
}, /* B */
164 { 2000, DHU_LPR_B2000
}, /* B */
165 { 2400, DHU_LPR_B2400
}, /* A and B */
166 { 4800, DHU_LPR_B4800
}, /* A and B */
167 { 7200, DHU_LPR_B7200
}, /* A */
168 { 9600, DHU_LPR_B9600
}, /* A and B */
169 { 19200, DHU_LPR_B19200
}, /* B */
170 { 38400, DHU_LPR_B38400
}, /* A */
174 static int dhu_match(device_t
, cfdata_t
, void *);
175 static void dhu_attach(device_t
, device_t
, void *);
176 static void dhurint(void *);
177 static void dhuxint(void *);
178 static void dhustart(struct tty
*);
179 static int dhuparam(struct tty
*, struct termios
*);
180 static int dhuiflow(struct tty
*, int);
181 static unsigned dhumctl(struct dhu_softc
*,int, int, int);
183 CFATTACH_DECL_NEW(dhu
, sizeof(struct dhu_softc
),
184 dhu_match
, dhu_attach
, NULL
, NULL
);
186 static dev_type_open(dhuopen
);
187 static dev_type_close(dhuclose
);
188 static dev_type_read(dhuread
);
189 static dev_type_write(dhuwrite
);
190 static dev_type_ioctl(dhuioctl
);
191 static dev_type_stop(dhustop
);
192 static dev_type_tty(dhutty
);
193 static dev_type_poll(dhupoll
);
195 const struct cdevsw dhu_cdevsw
= {
205 .d_kqfilter
= ttykqfilter
,
209 /* Autoconfig handles: setup the controller to interrupt, */
210 /* then complete the housecleaning for full operation */
213 dhu_match(device_t parent
, cfdata_t cf
, void *aux
)
215 struct uba_attach_args
*ua
= aux
;
218 /* Reset controller to initialize, enable TX/RX interrupts */
219 /* to catch floating vector info elsewhere when completed */
221 bus_space_write_2(ua
->ua_iot
, ua
->ua_ioh
, DHU_UBA_CSR
,
222 DHU_CSR_MASTER_RESET
| DHU_CSR_RXIE
| DHU_CSR_TXIE
);
224 /* Now wait up to 3 seconds for self-test to complete. */
226 for (n
= 0; n
< 300; n
++) {
228 if ((bus_space_read_2(ua
->ua_iot
, ua
->ua_ioh
, DHU_UBA_CSR
) &
229 DHU_CSR_MASTER_RESET
) == 0)
233 /* If the RESET did not clear after 3 seconds, */
234 /* the controller must be broken. */
239 /* Check whether diagnostic run has signalled a failure. */
241 if ((bus_space_read_2(ua
->ua_iot
, ua
->ua_ioh
, DHU_UBA_CSR
) &
242 DHU_CSR_DIAG_FAIL
) != 0)
249 dhu_attach(device_t parent
, device_t self
, void *aux
)
251 struct dhu_softc
*sc
= device_private(self
);
252 struct uba_attach_args
*ua
= aux
;
257 sc
->sc_iot
= ua
->ua_iot
;
258 sc
->sc_ioh
= ua
->ua_ioh
;
259 sc
->sc_dmat
= ua
->ua_dmat
;
260 /* Process the 8 bytes of diagnostic info put into */
261 /* the FIFO following the master reset operation. */
264 for (n
= 0; n
< 8; n
++) {
265 c
= DHU_READ_WORD(DHU_UBA_RBUF
);
267 if ((c
&DHU_DIAG_CODE
) == DHU_DIAG_CODE
) {
268 if ((c
&0200) == 0000)
269 aprint_error_dev(self
, "rom(%d) version %d\n",
270 ((c
>>1)&01), ((c
>>2)&037));
271 else if (((c
>>2)&07) != 0)
272 aprint_error_dev(self
, "diag-error(proc%d)=%x\n",
273 ((c
>>1)&01), ((c
>>2)&07));
277 c
= DHU_READ_WORD(DHU_UBA_STAT
);
279 sc
->sc_type
= (c
& DHU_STAT_DHU
)? IS_DHU
: IS_DHV
;
281 sc
->sc_lines
= 8; /* default */
282 if (sc
->sc_type
== IS_DHU
&& (c
& DHU_STAT_MDL
))
285 aprint_normal_dev(self
, "DH%s-11\n",
286 sc
->sc_type
== IS_DHU
? "U" : "V");
288 for (i
= 0; i
< sc
->sc_lines
; i
++) {
290 tp
= sc
->sc_dhu
[i
].dhu_tty
= ttymalloc();
291 sc
->sc_dhu
[i
].dhu_state
= STATE_IDLE
;
292 bus_dmamap_create(sc
->sc_dmat
, tp
->t_outq
.c_cn
, 1,
293 tp
->t_outq
.c_cn
, 0, BUS_DMA_ALLOCNOW
|BUS_DMA_NOWAIT
,
294 &sc
->sc_dhu
[i
].dhu_dmah
);
295 bus_dmamap_load(sc
->sc_dmat
, sc
->sc_dhu
[i
].dhu_dmah
,
296 tp
->t_outq
.c_cs
, tp
->t_outq
.c_cn
, 0, BUS_DMA_NOWAIT
);
300 /* Now establish RX & TX interrupt handlers */
302 uba_intr_establish(ua
->ua_icookie
, ua
->ua_cvec
,
303 dhurint
, sc
, &sc
->sc_rintrcnt
);
304 uba_intr_establish(ua
->ua_icookie
, ua
->ua_cvec
+ 4,
305 dhuxint
, sc
, &sc
->sc_tintrcnt
);
306 evcnt_attach_dynamic(&sc
->sc_rintrcnt
, EVCNT_TYPE_INTR
, ua
->ua_evcnt
,
307 device_xname(sc
->sc_dev
), "rintr");
308 evcnt_attach_dynamic(&sc
->sc_tintrcnt
, EVCNT_TYPE_INTR
, ua
->ua_evcnt
,
309 device_xname(sc
->sc_dev
), "tintr");
312 /* Receiver Interrupt */
317 struct dhu_softc
*sc
= arg
;
323 while ((c
= DHU_READ_WORD(DHU_UBA_RBUF
)) & DHU_RBUF_DATA_VALID
) {
325 /* Ignore diagnostic FIFO entries. */
327 if ((c
& DHU_DIAG_CODE
) == DHU_DIAG_CODE
)
331 line
= DHU_LINE(c
>>8);
332 tp
= sc
->sc_dhu
[line
].dhu_tty
;
334 /* LINK.TYPE is set so we get modem control FIFO entries */
336 if ((c
& DHU_DIAG_CODE
) == DHU_MODEM_CODE
) {
338 /* Do MDMBUF flow control, wakeup sleeping opens */
339 if (c
& DHU_STAT_DCD
) {
340 if (!(tp
->t_state
& TS_CARR_ON
))
341 (void)(*tp
->t_linesw
->l_modem
)(tp
, 1);
343 else if ((tp
->t_state
& TS_CARR_ON
) &&
344 (*tp
->t_linesw
->l_modem
)(tp
, 0) == 0)
345 (void) dhumctl(sc
, line
, 0, DMSET
);
347 /* Do CRTSCTS flow control */
348 delta
= c
^ sc
->sc_dhu
[line
].dhu_modem
;
349 sc
->sc_dhu
[line
].dhu_modem
= c
;
350 if ((delta
& DHU_STAT_CTS
) &&
351 (tp
->t_state
& TS_ISOPEN
) &&
352 (tp
->t_cflag
& CRTSCTS
)) {
353 if (c
& DHU_STAT_CTS
) {
354 tp
->t_state
&= ~TS_TTSTOP
;
357 tp
->t_state
|= TS_TTSTOP
;
364 if (!(tp
->t_state
& TS_ISOPEN
)) {
365 cv_broadcast(&tp
->t_rawcv
);
369 if ((c
& DHU_RBUF_OVERRUN_ERR
) && overrun
== 0) {
370 log(LOG_WARNING
, "%s: silo overflow, line %d\n",
371 device_xname(sc
->sc_dev
), line
);
374 /* A BREAK key will appear as a NULL with a framing error */
375 if (c
& DHU_RBUF_FRAMING_ERR
)
377 if (c
& DHU_RBUF_PARITY_ERR
)
380 (*tp
->t_linesw
->l_rint
)(cc
, tp
);
384 /* Transmitter Interrupt */
389 struct dhu_softc
*sc
= arg
;
393 while ((i
= DHU_READ_BYTE(DHU_UBA_CSR_HI
)) & (DHU_CSR_TX_ACTION
>> 8)) {
396 tp
= sc
->sc_dhu
[line
].dhu_tty
;
398 if (i
& (DHU_CSR_TX_DMA_ERROR
>> 8))
399 printf("%s: DMA ERROR on line: %d\n",
400 device_xname(sc
->sc_dev
), line
);
401 if (i
& (DHU_CSR_DIAG_FAIL
>> 8))
402 printf("%s: DIAG FAIL on line: %d\n",
403 device_xname(sc
->sc_dev
), line
);
405 tp
->t_state
&= ~TS_BUSY
;
406 if (tp
->t_state
& TS_FLUSH
)
407 tp
->t_state
&= ~TS_FLUSH
;
409 if (sc
->sc_dhu
[line
].dhu_state
== STATE_DMA_STOPPED
)
410 sc
->sc_dhu
[line
].dhu_cc
-=
411 DHU_READ_WORD(DHU_UBA_TBUFCNT
);
412 ndflush(&tp
->t_outq
, sc
->sc_dhu
[line
].dhu_cc
);
413 sc
->sc_dhu
[line
].dhu_cc
= 0;
416 sc
->sc_dhu
[line
].dhu_state
= STATE_IDLE
;
418 (*tp
->t_linesw
->l_start
)(tp
);
423 dhuopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
427 struct dhu_softc
*sc
;
430 unit
= DHU_M2U(minor(dev
));
431 line
= DHU_LINE(minor(dev
));
433 sc
= device_lookup_private(&dhu_cd
, unit
);
437 if (line
>= sc
->sc_lines
)
440 mutex_spin_enter(&tty_lock
);
441 if (sc
->sc_type
== IS_DHU
) {
442 /* CSR 3:0 must be 0 */
443 DHU_WRITE_BYTE(DHU_UBA_CSR
, DHU_CSR_RXIE
);
444 /* RX int delay 10ms */
445 DHU_WRITE_BYTE(DHU_UBA_RXTIME
, 10);
447 DHU_WRITE_BYTE(DHU_UBA_CSR
, DHU_CSR_RXIE
| line
);
448 sc
->sc_dhu
[line
].dhu_modem
= DHU_READ_WORD(DHU_UBA_STAT
);
450 tp
= sc
->sc_dhu
[line
].dhu_tty
;
452 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
455 tp
->t_oproc
= dhustart
;
456 tp
->t_param
= dhuparam
;
457 tp
->t_hwiflow
= dhuiflow
;
460 if ((tp
->t_state
& TS_ISOPEN
) == 0) {
462 if (tp
->t_ispeed
== 0) {
463 tp
->t_iflag
= TTYDEF_IFLAG
;
464 tp
->t_oflag
= TTYDEF_OFLAG
;
465 tp
->t_cflag
= TTYDEF_CFLAG
;
466 tp
->t_lflag
= TTYDEF_LFLAG
;
467 tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
469 (void) dhuparam(tp
, &tp
->t_termios
);
472 /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
473 if (dhumctl(sc
, line
, DML_DTR
|DML_RTS
, DMBIS
) & DML_DCD
)
474 tp
->t_state
|= TS_CARR_ON
;
475 while (!(flag
& O_NONBLOCK
) && !(tp
->t_cflag
& CLOCAL
) &&
476 !(tp
->t_state
& TS_CARR_ON
)) {
478 error
= ttysleep(tp
, &tp
->t_rawcv
, true, 0);
483 mutex_spin_exit(&tty_lock
);
486 return ((*tp
->t_linesw
->l_open
)(dev
, tp
));
491 dhuclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
493 const int unit
= DHU_M2U(minor(dev
));
494 const int line
= DHU_LINE(minor(dev
));
495 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, unit
);
496 struct tty
*tp
= sc
->sc_dhu
[line
].dhu_tty
;
498 (*tp
->t_linesw
->l_close
)(tp
, flag
);
500 /* Make sure a BREAK state is not left enabled. */
502 (void) dhumctl(sc
, line
, DML_BRK
, DMBIC
);
504 /* Do a hangup if so required. */
506 if ((tp
->t_cflag
& HUPCL
) || tp
->t_wopen
|| !(tp
->t_state
& TS_ISOPEN
))
507 (void) dhumctl(sc
, line
, 0, DMSET
);
509 return (ttyclose(tp
));
513 dhuread(dev_t dev
, struct uio
*uio
, int flag
)
515 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, DHU_M2U(minor(dev
)));
516 struct tty
*tp
= sc
->sc_dhu
[DHU_LINE(minor(dev
))].dhu_tty
;
518 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
522 dhuwrite(dev_t dev
, struct uio
*uio
, int flag
)
524 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, DHU_M2U(minor(dev
)));
525 struct tty
*tp
= sc
->sc_dhu
[DHU_LINE(minor(dev
))].dhu_tty
;
527 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
531 dhupoll(dev_t dev
, int events
, struct lwp
*l
)
533 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, DHU_M2U(minor(dev
)));
534 struct tty
*tp
= sc
->sc_dhu
[DHU_LINE(minor(dev
))].dhu_tty
;
536 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
541 dhuioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
543 const int unit
= DHU_M2U(minor(dev
));
544 const int line
= DHU_LINE(minor(dev
));
545 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, unit
);
546 struct tty
*tp
= sc
->sc_dhu
[line
].dhu_tty
;
549 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
550 if (error
!= EPASSTHROUGH
)
553 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
554 if (error
!= EPASSTHROUGH
)
560 (void) dhumctl(sc
, line
, DML_BRK
, DMBIS
);
564 (void) dhumctl(sc
, line
, DML_BRK
, DMBIC
);
568 (void) dhumctl(sc
, line
, DML_DTR
|DML_RTS
, DMBIS
);
572 (void) dhumctl(sc
, line
, DML_DTR
|DML_RTS
, DMBIC
);
576 (void) dhumctl(sc
, line
, *(int *)data
, DMSET
);
580 (void) dhumctl(sc
, line
, *(int *)data
, DMBIS
);
584 (void) dhumctl(sc
, line
, *(int *)data
, DMBIC
);
588 *(int *)data
= (dhumctl(sc
, line
, 0, DMGET
) & ~DML_BRK
);
592 return (EPASSTHROUGH
);
600 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, DHU_M2U(minor(dev
)));
602 return sc
->sc_dhu
[DHU_LINE(minor(dev
))].dhu_tty
;
607 dhustop(struct tty
*tp
, int flag
)
613 if (tp
->t_state
& TS_BUSY
) {
614 const int unit
= DHU_M2U(minor(tp
->t_dev
));
615 const int line
= DHU_LINE(minor(tp
->t_dev
));
616 struct dhu_softc
*sc
= device_lookup_private(&dhu_cd
, unit
);
618 if (sc
->sc_dhu
[line
].dhu_state
== STATE_DMA_RUNNING
) {
620 sc
->sc_dhu
[line
].dhu_state
= STATE_DMA_STOPPED
;
622 DHU_WRITE_BYTE(DHU_UBA_CSR
, DHU_CSR_RXIE
| line
);
623 DHU_WRITE_WORD(DHU_UBA_LNCTRL
,
624 DHU_READ_WORD(DHU_UBA_LNCTRL
) |
625 DHU_LNCTRL_DMA_ABORT
);
628 if (!(tp
->t_state
& TS_TTSTOP
))
629 tp
->t_state
|= TS_FLUSH
;
635 dhustart(struct tty
*tp
)
637 struct dhu_softc
*sc
;
643 if (tp
->t_state
& (TS_TIMEOUT
|TS_BUSY
|TS_TTSTOP
))
647 cc
= ndqb(&tp
->t_outq
, 0);
651 tp
->t_state
|= TS_BUSY
;
653 sc
= device_lookup_private(&dhu_cd
,DHU_M2U(minor(tp
->t_dev
)));
655 line
= DHU_LINE(minor(tp
->t_dev
));
657 DHU_WRITE_BYTE(DHU_UBA_CSR
, DHU_CSR_RXIE
| line
);
659 sc
->sc_dhu
[line
].dhu_cc
= cc
;
661 if (cc
== 1 && sc
->sc_type
== IS_DHV
) {
663 sc
->sc_dhu
[line
].dhu_state
= STATE_TX_ONE_CHAR
;
665 DHU_WRITE_WORD(DHU_UBA_TXCHAR
,
666 DHU_TXCHAR_DATA_VALID
| *tp
->t_outq
.c_cf
);
670 sc
->sc_dhu
[line
].dhu_state
= STATE_DMA_RUNNING
;
672 addr
= sc
->sc_dhu
[line
].dhu_dmah
->dm_segs
[0].ds_addr
+
673 (tp
->t_outq
.c_cf
- tp
->t_outq
.c_cs
);
675 DHU_WRITE_WORD(DHU_UBA_TBUFCNT
, cc
);
676 DHU_WRITE_WORD(DHU_UBA_TBUFAD1
, addr
& 0xFFFF);
677 DHU_WRITE_WORD(DHU_UBA_TBUFAD2
, ((addr
>>16) & 0x3F) |
678 DHU_TBUFAD2_TX_ENABLE
);
679 DHU_WRITE_WORD(DHU_UBA_LNCTRL
,
680 DHU_READ_WORD(DHU_UBA_LNCTRL
) & ~DHU_LNCTRL_DMA_ABORT
);
681 DHU_WRITE_WORD(DHU_UBA_TBUFAD2
,
682 DHU_READ_WORD(DHU_UBA_TBUFAD2
) | DHU_TBUFAD2_DMA_START
);
690 dhuparam(struct tty
*tp
, struct termios
*t
)
692 int cflag
= t
->c_cflag
;
693 int ispeed
= ttspeedtab(t
->c_ispeed
, dhuspeedtab
);
694 int ospeed
= ttspeedtab(t
->c_ospeed
, dhuspeedtab
);
697 const int unit
= DHU_M2U(minor(tp
->t_dev
));
698 const int line
= DHU_LINE(minor(tp
->t_dev
));
699 struct dhu_softc
* const sc
= device_lookup_private(&dhu_cd
, unit
);
703 /* check requested parameters */
704 if (ospeed
< 0 || ispeed
< 0)
707 tp
->t_ispeed
= t
->c_ispeed
;
708 tp
->t_ospeed
= t
->c_ospeed
;
712 (void) dhumctl(sc
, line
, 0, DMSET
); /* hang up line */
717 DHU_WRITE_BYTE(DHU_UBA_CSR
, DHU_CSR_RXIE
| line
);
719 lpr
= ((ispeed
&017)<<8) | ((ospeed
&017)<<12) ;
721 switch (cflag
& CSIZE
) {
724 lpr
|= DHU_LPR_5_BIT_CHAR
;
728 lpr
|= DHU_LPR_6_BIT_CHAR
;
732 lpr
|= DHU_LPR_7_BIT_CHAR
;
736 lpr
|= DHU_LPR_8_BIT_CHAR
;
741 lpr
|= DHU_LPR_PARENB
;
742 if (!(cflag
& PARODD
))
745 lpr
|= DHU_LPR_2_STOP
;
747 DHU_WRITE_WORD(DHU_UBA_LPR
, lpr
);
749 DHU_WRITE_WORD(DHU_UBA_TBUFAD2
,
750 DHU_READ_WORD(DHU_UBA_TBUFAD2
) | DHU_TBUFAD2_TX_ENABLE
);
752 lnctrl
= DHU_READ_WORD(DHU_UBA_LNCTRL
);
754 /* Setting LINK.TYPE enables modem signal change interrupts. */
756 lnctrl
|= (DHU_LNCTRL_RX_ENABLE
| DHU_LNCTRL_LINK_TYPE
);
758 /* Enable the auto XON/XOFF feature on the controller */
760 if (t
->c_iflag
& IXON
)
761 lnctrl
|= DHU_LNCTRL_OAUTO
;
763 lnctrl
&= ~DHU_LNCTRL_OAUTO
;
765 if (t
->c_iflag
& IXOFF
)
766 lnctrl
|= DHU_LNCTRL_IAUTO
;
768 lnctrl
&= ~DHU_LNCTRL_IAUTO
;
770 DHU_WRITE_WORD(DHU_UBA_LNCTRL
, lnctrl
);
777 dhuiflow(struct tty
*tp
, int flag
)
780 if (tp
->t_cflag
& CRTSCTS
) {
781 const int unit
= DHU_M2U(minor(tp
->t_dev
));
782 const int line
= DHU_LINE(minor(tp
->t_dev
));
783 struct dhu_softc
* const sc
= device_lookup_private(&dhu_cd
, unit
);
784 (void) dhumctl(sc
, line
, DML_RTS
, ((flag
)? DMBIC
: DMBIS
));
791 dhumctl(struct dhu_softc
*sc
, int line
, int bits
, int how
)
800 DHU_WRITE_BYTE(DHU_UBA_CSR
, DHU_CSR_RXIE
| line
);
804 /* external signals as seen from the port */
806 status
= DHU_READ_WORD(DHU_UBA_STAT
);
808 if (status
& DHU_STAT_CTS
)
811 if (status
& DHU_STAT_DCD
)
814 if (status
& DHU_STAT_DSR
)
817 if (status
& DHU_STAT_RI
)
820 /* internal signals/state delivered to port */
822 lnctrl
= DHU_READ_WORD(DHU_UBA_LNCTRL
);
824 if (lnctrl
& DHU_LNCTRL_RTS
)
827 if (lnctrl
& DHU_LNCTRL_DTR
)
830 if (lnctrl
& DHU_LNCTRL_BREAK
)
853 lnctrl
|= DHU_LNCTRL_RTS
;
855 lnctrl
&= ~DHU_LNCTRL_RTS
;
858 lnctrl
|= DHU_LNCTRL_DTR
;
860 lnctrl
&= ~DHU_LNCTRL_DTR
;
863 lnctrl
|= DHU_LNCTRL_BREAK
;
865 lnctrl
&= ~DHU_LNCTRL_BREAK
;
867 DHU_WRITE_WORD(DHU_UBA_LNCTRL
, lnctrl
);