1 /* $NetBSD: ser.c,v 1.44 2009/07/08 12:23:10 tsutsui Exp $ */
4 * Copyright (c) 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.
32 * Copyright (c) 1993, 1994, 1995, 1996, 1997
33 * Charles M. Hannum. All rights reserved.
35 * Interrupt processing and hardware flow control partly based on code from
36 * Onno van der Linden and Gordon Ross.
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed by Charles M. Hannum.
49 * 4. The name of the author may not be used to endorse or promote products
50 * derived from this software without specific prior written permission.
52 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
65 * Copyright (c) 1991 The Regents of the University of California.
66 * All rights reserved.
68 * Redistribution and use in source and binary forms, with or without
69 * modification, are permitted provided that the following conditions
71 * 1. Redistributions of source code must retain the above copyright
72 * notice, this list of conditions and the following disclaimer.
73 * 2. Redistributions in binary form must reproduce the above copyright
74 * notice, this list of conditions and the following disclaimer in the
75 * documentation and/or other materials provided with the distribution.
76 * 3. Neither the name of the University nor the names of its contributors
77 * may be used to endorse or promote products derived from this software
78 * without specific prior written permission.
80 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
81 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
82 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
83 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
84 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
85 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
86 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
87 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
88 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
89 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
92 * @(#)com.c 7.5 (Berkeley) 5/16/91
95 #include <sys/cdefs.h>
96 __KERNEL_RCSID(0, "$NetBSD: ser.c,v 1.44 2009/07/08 12:23:10 tsutsui Exp $");
99 #include "opt_mbtype.h"
100 #include "opt_serconsole.h"
102 #include <sys/param.h>
103 #include <sys/systm.h>
104 #include <sys/ioctl.h>
105 #include <sys/select.h>
107 #include <sys/proc.h>
108 #include <sys/conf.h>
109 #include <sys/file.h>
111 #include <sys/kernel.h>
112 #include <sys/syslog.h>
113 #include <sys/types.h>
114 #include <sys/device.h>
115 #include <sys/kauth.h>
117 #include <m68k/asm_single.h>
119 #include <machine/iomap.h>
120 #include <machine/mfp.h>
121 #include <machine/intr.h>
122 #include <atari/dev/serreg.h>
124 #if !defined(_MILANHW_)
125 #include <atari/dev/ym2149reg.h>
127 /* MILAN has no ym2149 */
128 #define ym2149_dtr(set) { \
130 single_inst_bset_b(MFP->mf_gpip, 0x08); \
131 else single_inst_bclr_b(MFP->mf_gpip, 0x08); \
134 #define ym2149_rts(set) { \
136 single_inst_bset_b(MFP->mf_gpip, 0x01); \
137 else single_inst_bclr_b(MFP->mf_gpip, 0x01); \
139 #endif /* _MILANHW_ */
141 /* #define SER_DEBUG */
143 #define SERUNIT(x) (minor(x) & 0x7ffff)
144 #define SERDIALOUT(x) (minor(x) & 0x80000)
147 #define CONSBAUD 9600
148 #define CONSCFLAG TTYDEF_CFLAG
151 /* Buffer size for character buffer */
152 #define RXBUFSIZE 2048 /* More than enough.. */
153 #define RXBUFMASK (RXBUFSIZE-1) /* Only iff previous is a power of 2 */
154 #define RXHIWAT (RXBUFSIZE >> 2)
157 struct device sc_dev
;
160 struct callout sc_diag_ch
;
169 int sc_ospeed
; /* delay + timer-d data */
172 u_char sc_ucr
; /* Uart control */
173 u_char sc_msr
; /* Modem status */
174 u_char sc_tsr
; /* Tranceiver status */
175 u_char sc_rsr
; /* Receiver status */
176 u_char sc_mcr
; /* (Pseudo) Modem ctrl. */
180 u_char sc_mcr_active
;
181 u_char sc_mcr_dtr
, sc_mcr_rts
, sc_msr_cts
, sc_msr_dcd
;
184 volatile u_int sc_rbget
;
185 volatile u_int sc_rbput
;
186 volatile u_int sc_rbavail
;
187 u_char sc_rbuf
[RXBUFSIZE
];
188 u_char sc_lbuf
[RXBUFSIZE
];
190 volatile u_char sc_rx_blocked
;
191 volatile u_char sc_rx_ready
;
192 volatile u_char sc_tx_busy
;
193 volatile u_char sc_tx_done
;
194 volatile u_char sc_tx_stopped
;
195 volatile u_char sc_st_check
;
201 volatile u_char sc_heldchange
;
209 #define SER_HW_CONSOLE 0x01
211 void ser_break(struct ser_softc
*, int);
212 void ser_hwiflow(struct ser_softc
*, int);
213 void ser_iflush(struct ser_softc
*);
214 void ser_loadchannelregs(struct ser_softc
*);
215 void ser_modem(struct ser_softc
*, int);
216 void serdiag(void *);
217 int serhwiflow(struct tty
*, int);
219 void serinitcons(int);
220 int sermintr(void *);
221 int sertrintr(void *);
222 int serparam(struct tty
*, struct termios
*);
223 void serstart(struct tty
*);
226 void sercnprobe(struct consdev
*);
227 void sercninit(struct consdev
*);
228 int sercngetc(dev_t
);
229 void sercnputc(dev_t
, int);
230 void sercnpollc(dev_t
, int);
232 static void sermsrint(struct ser_softc
*, struct tty
*);
233 static void serrxint(struct ser_softc
*, struct tty
*);
234 static void ser_shutdown(struct ser_softc
*);
235 static int serspeed(long);
236 static void sersoft(void *);
237 static void sertxint(struct ser_softc
*, struct tty
*);
242 static void serattach(struct device
*, struct device
*, void *);
243 static int sermatch(struct device
*, struct cfdata
*, void *);
245 CFATTACH_DECL(ser
, sizeof(struct ser_softc
),
246 sermatch
, serattach
, NULL
, NULL
);
248 extern struct cfdriver ser_cd
;
250 dev_type_open(seropen
);
251 dev_type_close(serclose
);
252 dev_type_read(serread
);
253 dev_type_write(serwrite
);
254 dev_type_ioctl(serioctl
);
255 dev_type_stop(serstop
);
256 dev_type_tty(sertty
);
257 dev_type_poll(serpoll
);
259 const struct cdevsw ser_cdevsw
= {
260 seropen
, serclose
, serread
, serwrite
, serioctl
,
261 serstop
, sertty
, serpoll
, nommap
, ttykqfilter
, D_TTY
266 sermatch(struct device
*pdp
, struct cfdata
*cfp
, void *auxp
)
268 static int ser_matched
= 0;
270 /* Match at most one ser unit */
271 if (strcmp((char *)auxp
, "ser") || ser_matched
)
280 serattach(struct device
*pdp
, struct device
*dp
, void *auxp
)
282 struct ser_softc
*sc
= device_private(dp
);
284 if (intr_establish(1, USER_VEC
, 0, (hw_ifun_t
)sermintr
, sc
) == NULL
)
285 printf("serattach: Can't establish interrupt (1)\n");
286 if (intr_establish(2, USER_VEC
, 0, (hw_ifun_t
)sermintr
, sc
) == NULL
)
287 printf("serattach: Can't establish interrupt (2)\n");
288 if (intr_establish(14, USER_VEC
, 0, (hw_ifun_t
)sermintr
, sc
) == NULL
)
289 printf("serattach: Can't establish interrupt (14)\n");
290 if (intr_establish(9, USER_VEC
, 0, (hw_ifun_t
)sertrintr
, sc
) == NULL
)
291 printf("serattach: Can't establish interrupt (9)\n");
292 if (intr_establish(10, USER_VEC
, 0, (hw_ifun_t
)sertrintr
, sc
) == NULL
)
293 printf("serattach: Can't establish interrupt (10)\n");
294 if (intr_establish(11, USER_VEC
, 0, (hw_ifun_t
)sertrintr
, sc
) == NULL
)
295 printf("serattach: Can't establish interrupt (11)\n");
296 if (intr_establish(12, USER_VEC
, 0, (hw_ifun_t
)sertrintr
, sc
) == NULL
)
297 printf("serattach: Can't establish interrupt (12)\n");
299 sc
->sc_sicookie
= softint_establish(SOFTINT_SERIAL
, sersoft
, sc
);
305 * Enable but mask interrupts...
306 * XXX: Look at edge-sensitivity for DCD/CTS interrupts.
308 MFP
->mf_ierb
|= IB_SCTS
|IB_SDCD
;
309 MFP
->mf_iera
|= IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
;
310 MFP
->mf_imrb
&= ~(IB_SCTS
|IB_SDCD
);
311 MFP
->mf_imra
&= ~(IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
);
313 callout_init(&sc
->sc_diag_ch
, 0);
317 * Activate serial console when DCD present...
319 if (!(MFP
->mf_gpip
& MCR_DCD
))
320 SET(sc
->sc_hwflags
, SER_HW_CONSOLE
);
321 #endif /* SERCONSOLE > 0 */
324 if (ISSET(sc
->sc_hwflags
, SER_HW_CONSOLE
)) {
326 printf("%s: console\n", sc
->sc_dev
.dv_xname
);
331 void serstatus(struct ser_softc
*, char *);
333 serstatus(struct ser_softc
*sc
, char *str
)
335 struct tty
*tp
= sc
->sc_tty
;
337 printf("%s: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n",
338 sc
->sc_dev
.dv_xname
, str
,
339 ISSET(tp
->t_cflag
, CLOCAL
) ? "+" : "-",
340 ISSET(sc
->sc_msr
, MCR_DCD
) ? "+" : "-",
341 ISSET(tp
->t_state
, TS_CARR_ON
) ? "+" : "-",
342 ISSET(sc
->sc_mcr
, MCR_DTR
) ? "+" : "-",
343 sc
->sc_tx_stopped
? "+" : "-");
345 printf("%s: %s %scrtscts %scts %sts_ttstop %srts %srx_blocked\n",
346 sc
->sc_dev
.dv_xname
, str
,
347 ISSET(tp
->t_cflag
, CRTSCTS
) ? "+" : "-",
348 ISSET(sc
->sc_msr
, MCR_CTS
) ? "+" : "-",
349 ISSET(tp
->t_state
, TS_TTSTOP
) ? "+" : "-",
350 ISSET(sc
->sc_mcr
, MCR_RTS
) ? "+" : "-",
351 sc
->sc_rx_blocked
? "+" : "-");
353 #endif /* SER_DEBUG */
356 seropen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
358 int unit
= SERUNIT(dev
);
359 struct ser_softc
*sc
;
364 sc
= device_lookup_private(&ser_cd
, unit
);
369 tp
= sc
->sc_tty
= ttymalloc();
374 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
380 * Do the following if this is a first open.
382 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
385 /* Turn on interrupts. */
386 sc
->sc_imra
= IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
;
387 sc
->sc_imrb
= IB_SCTS
|IB_SDCD
;
388 single_inst_bset_b(MFP
->mf_imra
, sc
->sc_imra
);
389 single_inst_bset_b(MFP
->mf_imrb
, sc
->sc_imrb
);
391 /* Fetch the current modem control status, needed later. */
392 sc
->sc_msr
= ~MFP
->mf_gpip
& (IO_SDCD
|IO_SCTS
|IO_SRI
);
394 /* Add some entry points needed by the tty layer. */
395 tp
->t_oproc
= serstart
;
396 tp
->t_param
= serparam
;
397 tp
->t_hwiflow
= serhwiflow
;
401 * Initialize the termios status to the defaults. Add in the
402 * sticky bits from TIOCSFLAGS.
405 if (ISSET(sc
->sc_hwflags
, SER_HW_CONSOLE
)) {
406 t
.c_ospeed
= CONSBAUD
;
407 t
.c_cflag
= CONSCFLAG
;
410 t
.c_ospeed
= TTYDEF_SPEED
;
411 t
.c_cflag
= TTYDEF_CFLAG
;
413 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CLOCAL
))
414 SET(t
.c_cflag
, CLOCAL
);
415 if (ISSET(sc
->sc_swflags
, TIOCFLAG_CRTSCTS
))
416 SET(t
.c_cflag
, CRTSCTS
);
417 if (ISSET(sc
->sc_swflags
, TIOCFLAG_MDMBUF
))
418 SET(t
.c_cflag
, MDMBUF
);
419 tp
->t_iflag
= TTYDEF_IFLAG
;
420 tp
->t_oflag
= TTYDEF_OFLAG
;
421 tp
->t_lflag
= TTYDEF_LFLAG
;
423 (void) serparam(tp
, &t
);
429 * Turn on DTR. We must always do this, even if carrier is not
430 * present, because otherwise we'd have to use TIOCSDTR
431 * immediately after setting CLOCAL. We will drop DTR only on
432 * the next high-low transition of DCD, or by explicit request.
436 /* Clear the input ring, and unblock. */
437 sc
->sc_rbput
= sc
->sc_rbget
= 0;
438 sc
->sc_rbavail
= RXBUFSIZE
;
440 sc
->sc_rx_blocked
= 0;
444 serstatus(sc
, "seropen ");
452 error
= ttyopen(tp
, SERDIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
456 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
463 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
465 * We failed to open the device, and nobody else had it opened.
466 * Clean up the state as appropriate.
475 serclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
477 int unit
= SERUNIT(dev
);
478 struct ser_softc
*sc
= device_lookup_private(&ser_cd
, unit
);
479 struct tty
*tp
= sc
->sc_tty
;
481 /* XXX This is for cons.c. */
482 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
485 (*tp
->t_linesw
->l_close
)(tp
, flag
);
488 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
490 * Although we got a last close, the device may still be in
491 * use; e.g. if this was the dialout node, and there are still
492 * processes waiting for carrier on the non-dialout node.
501 serread(dev_t dev
, struct uio
*uio
, int flag
)
503 struct ser_softc
*sc
= device_lookup_private(&ser_cd
, SERUNIT(dev
));
504 struct tty
*tp
= sc
->sc_tty
;
506 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
510 serwrite(dev_t dev
, struct uio
*uio
, int flag
)
512 struct ser_softc
*sc
= device_lookup_private(&ser_cd
, SERUNIT(dev
));
513 struct tty
*tp
= sc
->sc_tty
;
515 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
519 serpoll(dev_t dev
, int events
, struct lwp
*l
)
521 struct ser_softc
*sc
= device_lookup_private(&ser_cd
, SERUNIT(dev
));
522 struct tty
*tp
= sc
->sc_tty
;
524 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
530 struct ser_softc
*sc
= device_lookup_private(&ser_cd
, SERUNIT(dev
));
531 struct tty
*tp
= sc
->sc_tty
;
537 serioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
539 int unit
= SERUNIT(dev
);
540 struct ser_softc
*sc
= device_lookup_private(&ser_cd
, unit
);
541 struct tty
*tp
= sc
->sc_tty
;
544 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
545 if (error
!= EPASSTHROUGH
)
548 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
549 if (error
!= EPASSTHROUGH
)
570 *(int *)data
= sc
->sc_swflags
;
574 error
= kauth_authorize_device_tty(l
->l_cred
,
575 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
578 sc
->sc_swflags
= *(int *)data
;
586 return (EPASSTHROUGH
);
590 serstatus(sc
, "serioctl ");
597 ser_break(struct ser_softc
*sc
, int onoff
)
603 SET(sc
->sc_tsr
, TSR_SBREAK
);
605 CLR(sc
->sc_tsr
, TSR_SBREAK
);
607 if (!sc
->sc_heldchange
) {
608 if (sc
->sc_tx_busy
) {
609 sc
->sc_heldtbc
= sc
->sc_tbc
;
611 sc
->sc_heldchange
= 1;
613 ser_loadchannelregs(sc
);
619 ser_modem(struct ser_softc
*sc
, int onoff
)
625 SET(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
627 CLR(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
629 if (!sc
->sc_heldchange
) {
630 if (sc
->sc_tx_busy
) {
631 sc
->sc_heldtbc
= sc
->sc_tbc
;
633 sc
->sc_heldchange
= 1;
635 ser_loadchannelregs(sc
);
641 serparam(struct tty
*tp
, struct termios
*t
)
643 struct ser_softc
*sc
=
644 device_lookup_private(&ser_cd
, SERUNIT(tp
->t_dev
));
645 int ospeed
= serspeed(t
->c_ospeed
);
650 /* check requested parameters */
653 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
656 sc
->sc_rsr
= RSR_ENAB
;
657 sc
->sc_tsr
= TSR_ENAB
;
661 switch (ISSET(t
->c_cflag
, CSIZE
)) {
675 if (ISSET(t
->c_cflag
, PARENB
)) {
677 if (!ISSET(t
->c_cflag
, PARODD
))
680 if (ISSET(t
->c_cflag
, CSTOPB
))
681 SET(ucr
, UCR_STOPB2
);
683 SET(ucr
, UCR_STOPB1
);
690 * For the console, always force CLOCAL and !HUPCL, so that the port
693 if (ISSET(sc
->sc_swflags
, TIOCFLAG_SOFTCAR
) ||
694 ISSET(sc
->sc_hwflags
, SER_HW_CONSOLE
)) {
695 SET(t
->c_cflag
, CLOCAL
);
696 CLR(t
->c_cflag
, HUPCL
);
700 * If we're not in a mode that assumes a connection is present, then
701 * ignore carrier changes.
703 if (ISSET(t
->c_cflag
, CLOCAL
| MDMBUF
))
706 sc
->sc_msr_dcd
= MCR_DCD
;
708 * Set the flow control pins depending on the current flow control
711 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
712 sc
->sc_mcr_dtr
= MCR_DTR
;
713 sc
->sc_mcr_rts
= MCR_RTS
;
714 sc
->sc_msr_cts
= MCR_CTS
;
715 sc
->sc_r_hiwat
= RXHIWAT
;
716 } else if (ISSET(t
->c_cflag
, MDMBUF
)) {
718 * For DTR/DCD flow control, make sure we don't toggle DTR for
722 sc
->sc_mcr_rts
= MCR_DTR
;
723 sc
->sc_msr_cts
= MCR_DCD
;
724 sc
->sc_r_hiwat
= RXHIWAT
;
727 * If no flow control, then always set RTS. This will make
728 * the other side happy if it mistakenly thinks we're doing
729 * RTS/CTS flow control.
731 sc
->sc_mcr_dtr
= MCR_DTR
| MCR_RTS
;
735 if (ISSET(sc
->sc_mcr
, MCR_DTR
))
736 SET(sc
->sc_mcr
, MCR_RTS
);
738 CLR(sc
->sc_mcr
, MCR_RTS
);
740 sc
->sc_msr_mask
= sc
->sc_msr_cts
| sc
->sc_msr_dcd
;
744 CLR(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
746 SET(sc
->sc_mcr
, sc
->sc_mcr_dtr
);
749 sc
->sc_ospeed
= ospeed
;
751 /* and copy to tty */
753 tp
->t_ospeed
= t
->c_ospeed
;
754 tp
->t_cflag
= t
->c_cflag
;
756 if (!sc
->sc_heldchange
) {
757 if (sc
->sc_tx_busy
) {
758 sc
->sc_heldtbc
= sc
->sc_tbc
;
760 sc
->sc_heldchange
= 1;
762 ser_loadchannelregs(sc
);
768 * Update the tty layer's idea of the carrier bit, in case we changed
769 * CLOCAL or MDMBUF. We don't hang up here; we only do that if we
770 * lose carrier while carrier detection is on.
772 (void) (*tp
->t_linesw
->l_modem
)(tp
, ISSET(sc
->sc_msr
, MCR_DCD
));
775 serstatus(sc
, "serparam ");
779 /* Block or unblock as needed. */
780 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
781 if (sc
->sc_rx_blocked
) {
782 sc
->sc_rx_blocked
= 0;
785 if (sc
->sc_tx_stopped
) {
786 sc
->sc_tx_stopped
= 0;
799 ser_iflush(struct ser_softc
*sc
)
803 /* flush any pending I/O */
804 while (ISSET(MFP
->mf_rsr
, RSR_CIP
|RSR_BFULL
))
809 ser_loadchannelregs(struct ser_softc
*sc
)
811 /* XXXXX necessary? */
815 * No interrupts please...
817 if((MFP
->mf_imra
& (IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
)) != sc
->sc_imra
) {
818 printf("loadchannelregs: mf_imra: %x sc_imra: %x\n", (u_int
)MFP
->mf_imra
,
821 if((MFP
->mf_imrb
& (IB_SCTS
|IB_SDCD
)) != sc
->sc_imrb
) {
822 printf("loadchannelregs: mf_imrb: %x sc_imrb: %x\n", (u_int
)MFP
->mf_imrb
,
825 single_inst_bclr_b(MFP
->mf_imra
, IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
);
826 single_inst_bclr_b(MFP
->mf_imrb
, IB_SCTS
|IB_SDCD
);
828 MFP
->mf_ucr
= sc
->sc_ucr
;
829 MFP
->mf_rsr
= sc
->sc_rsr
;
830 MFP
->mf_tsr
= sc
->sc_tsr
;
832 single_inst_bclr_b(MFP
->mf_tcdcr
, 0x07);
833 MFP
->mf_tddr
= sc
->sc_ospeed
;
834 single_inst_bset_b(MFP
->mf_tcdcr
, (sc
->sc_ospeed
>> 8) & 0x0f);
836 sc
->sc_mcr_active
= sc
->sc_mcr
;
838 if (machineid
& ATARI_HADES
) {
839 /* PCB fault, wires exchanged..... */
840 ym2149_rts(!(sc
->sc_mcr_active
& MCR_DTR
));
841 ym2149_dtr(!(sc
->sc_mcr_active
& MCR_RTS
));
844 ym2149_rts(!(sc
->sc_mcr_active
& MCR_RTS
));
845 ym2149_dtr(!(sc
->sc_mcr_active
& MCR_DTR
));
848 single_inst_bset_b(MFP
->mf_imra
, sc
->sc_imra
);
849 single_inst_bset_b(MFP
->mf_imrb
, sc
->sc_imrb
);
853 serhwiflow(struct tty
*tp
, int block
)
855 struct ser_softc
*sc
=
856 device_lookup_private(&ser_cd
, SERUNIT(tp
->t_dev
));
859 if (sc
->sc_mcr_rts
== 0)
865 * The tty layer is asking us to block input.
866 * If we already did it, just return TRUE.
868 if (sc
->sc_rx_blocked
)
870 sc
->sc_rx_blocked
= 1;
873 * The tty layer is asking us to resume input.
874 * The input ring is always empty by now.
876 sc
->sc_rx_blocked
= 0;
878 ser_hwiflow(sc
, block
);
885 * (un)block input via hw flowcontrol
888 ser_hwiflow(struct ser_softc
*sc
, int block
)
890 if (sc
->sc_mcr_rts
== 0)
894 CLR(sc
->sc_mcr
, sc
->sc_mcr_rts
);
895 CLR(sc
->sc_mcr_active
, sc
->sc_mcr_rts
);
897 SET(sc
->sc_mcr
, sc
->sc_mcr_rts
);
898 SET(sc
->sc_mcr_active
, sc
->sc_mcr_rts
);
900 if (machineid
& ATARI_HADES
) {
901 /* PCB fault, wires exchanged..... */
902 ym2149_dtr(sc
->sc_mcr_active
& MCR_RTS
);
905 ym2149_rts(sc
->sc_mcr_active
& MCR_RTS
);
910 serstart(struct tty
*tp
)
912 struct ser_softc
*sc
=
913 device_lookup_private(&ser_cd
, SERUNIT(tp
->t_dev
));
917 if (ISSET(tp
->t_state
, TS_BUSY
))
919 if (ISSET(tp
->t_state
, TS_TIMEOUT
| TS_TTSTOP
))
922 if (sc
->sc_tx_stopped
)
927 /* Grab the first contiguous region of buffer space. */
932 tba
= tp
->t_outq
.c_cf
;
933 tbc
= ndqb(&tp
->t_outq
, 0);
941 SET(tp
->t_state
, TS_BUSY
);
944 /* Enable transmit completion interrupts if necessary. */
945 if (!ISSET(sc
->sc_imra
, IA_TRDY
)) {
946 SET(sc
->sc_imra
, IA_TRDY
|IA_TERR
);
947 single_inst_bset_b(MFP
->mf_imra
, IA_TRDY
|IA_TERR
);
950 /* Output the first char */
951 MFP
->mf_udr
= *sc
->sc_tba
;
959 /* Disable transmit completion interrupts if necessary. */
960 if (ISSET(sc
->sc_imra
, IA_TRDY
)) {
961 CLR(sc
->sc_imra
, IA_TRDY
|IA_TERR
);
962 single_inst_bclr_b(MFP
->mf_imra
, IA_TRDY
|IA_TERR
);
970 * Stop output on a line.
973 serstop(struct tty
*tp
, int flag
)
975 struct ser_softc
*sc
=
976 device_lookup_private(&ser_cd
, SERUNIT(tp
->t_dev
));
980 if (ISSET(tp
->t_state
, TS_BUSY
)) {
981 /* Stop transmitting at the next chunk. */
984 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
985 SET(tp
->t_state
, TS_FLUSH
);
993 struct ser_softc
*sc
= arg
;
994 int overflows
, floods
;
998 overflows
= sc
->sc_overflows
;
999 sc
->sc_overflows
= 0;
1000 floods
= sc
->sc_floods
;
1006 "%s: %d silo overflow%s, %d ibuf flood%s\n",
1007 sc
->sc_dev
.dv_xname
,
1008 overflows
, overflows
== 1 ? "" : "s",
1009 floods
, floods
== 1 ? "" : "s");
1013 void ser_shutdown(sc
)
1014 struct ser_softc
*sc
;
1017 struct tty
*tp
= sc
->sc_tty
;
1022 /* If we were asserting flow control, then deassert it. */
1023 sc
->sc_rx_blocked
= 1;
1026 /* Clear any break condition set with TIOCSBRK. */
1030 * Hang up if necessary. Wait a bit, so the other side has time to
1031 * notice even if we immediately open the port again.
1033 if (ISSET(tp
->t_cflag
, HUPCL
)) {
1035 (void) tsleep(sc
, TTIPRI
, ttclos
, hz
);
1038 /* Turn off interrupts. */
1039 CLR(sc
->sc_imra
, IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
);
1040 CLR(sc
->sc_imrb
, IB_SCTS
|IB_SDCD
);
1041 single_inst_bclr_b(MFP
->mf_imrb
, IB_SCTS
|IB_SDCD
);
1042 single_inst_bclr_b(MFP
->mf_imra
, IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
);
1047 serrxint(struct ser_softc
*sc
, struct tty
*tp
)
1053 static int lsrmap
[8] = {
1055 TTY_FE
, TTY_PE
|TTY_FE
,
1056 TTY_FE
, TTY_PE
|TTY_FE
,
1057 TTY_FE
, TTY_PE
|TTY_FE
1061 scc
= cc
= RXBUFSIZE
- sc
->sc_rbavail
;
1063 if (cc
== RXBUFSIZE
) {
1065 if (sc
->sc_errors
++ == 0)
1066 callout_reset(&sc
->sc_diag_ch
, 60 * hz
, serdiag
, sc
);
1070 rsr
= sc
->sc_lbuf
[get
];
1071 if (ISSET(rsr
, RSR_BREAK
)) {
1073 if (ISSET(sc
->sc_hwflags
, SER_HW_CONSOLE
))
1077 else if (ISSET(rsr
, RSR_OERR
)) {
1079 if (sc
->sc_errors
++ == 0)
1080 callout_reset(&sc
->sc_diag_ch
, 60 * hz
,
1083 code
= sc
->sc_rbuf
[get
] |
1084 lsrmap
[(rsr
& (RSR_BREAK
|RSR_FERR
|RSR_PERR
)) >> 3];
1085 (*tp
->t_linesw
->l_rint
)(code
, tp
);
1086 get
= (get
+ 1) & RXBUFMASK
;
1091 sc
->sc_rbavail
+= scc
;
1093 * Buffers should be ok again, release possible block, but only if the
1094 * tty layer isn't blocking too.
1096 if (sc
->sc_rx_blocked
&& !ISSET(tp
->t_state
, TS_TBLOCK
)) {
1097 sc
->sc_rx_blocked
= 0;
1104 sertxint(struct ser_softc
*sc
, struct tty
*tp
)
1107 CLR(tp
->t_state
, TS_BUSY
);
1108 if (ISSET(tp
->t_state
, TS_FLUSH
))
1109 CLR(tp
->t_state
, TS_FLUSH
);
1111 ndflush(&tp
->t_outq
, (int)(sc
->sc_tba
- tp
->t_outq
.c_cf
));
1112 (*tp
->t_linesw
->l_start
)(tp
);
1116 sermsrint(struct ser_softc
*sc
, struct tty
*tp
)
1123 delta
= sc
->sc_msr_delta
;
1124 sc
->sc_msr_delta
= 0;
1127 if (ISSET(delta
, sc
->sc_msr_dcd
)) {
1129 * Inform the tty layer that carrier detect changed.
1131 (void) (*tp
->t_linesw
->l_modem
)(tp
, ISSET(msr
, MCR_DCD
));
1134 if (ISSET(delta
, sc
->sc_msr_cts
)) {
1135 /* Block or unblock output according to flow control. */
1136 if (ISSET(msr
, sc
->sc_msr_cts
)) {
1137 sc
->sc_tx_stopped
= 0;
1138 (*tp
->t_linesw
->l_start
)(tp
);
1140 sc
->sc_tx_stopped
= 1;
1146 serstatus(sc
, "sermsrint");
1153 struct ser_softc
*sc
= arg
;
1160 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && (tp
->t_wopen
== 0))
1163 if (sc
->sc_rx_ready
) {
1164 sc
->sc_rx_ready
= 0;
1168 if (sc
->sc_st_check
) {
1169 sc
->sc_st_check
= 0;
1173 if (sc
->sc_tx_done
) {
1182 struct ser_softc
*sc
= arg
;
1185 msr
= ~MFP
->mf_gpip
;
1186 delta
= msr
^ sc
->sc_msr
;
1187 sc
->sc_msr
= sc
->sc_msr
& ~(MCR_CTS
|MCR_DCD
|MCR_RI
);
1188 sc
->sc_msr
|= msr
& (MCR_CTS
|MCR_DCD
|MCR_RI
);
1190 if (ISSET(delta
, sc
->sc_msr_mask
)) {
1191 sc
->sc_msr_delta
|= delta
;
1194 * Stop output immediately if we lose the output
1195 * flow control signal or carrier detect.
1197 if (ISSET(~msr
, sc
->sc_msr_mask
)) {
1201 serstatus(sc
, "sermintr ");
1205 sc
->sc_st_check
= 1;
1207 softint_schedule(sc
->sc_sicookie
);
1212 sertrintr(void *arg
)
1214 struct ser_softc
*sc
= arg
;
1219 cc
= sc
->sc_rbavail
;
1222 if (ISSET(rsr
, RSR_BFULL
|RSR_BREAK
)) {
1223 for (; ISSET(rsr
, RSR_BFULL
|RSR_BREAK
) && cc
> 0; cc
--) {
1224 sc
->sc_rbuf
[put
] = MFP
->mf_udr
;
1225 sc
->sc_lbuf
[put
] = rsr
;
1226 put
= (put
+ 1) & RXBUFMASK
;
1227 if ((rsr
& RSR_BREAK
) && (MFP
->mf_rsr
& RSR_BREAK
))
1229 else rsr
= MFP
->mf_rsr
;
1232 * Current string of incoming characters ended because
1233 * no more data was available. Schedule a receive event
1234 * if any data was received. Drop any characters that
1235 * we couldn't handle.
1238 sc
->sc_rbavail
= cc
;
1239 sc
->sc_rx_ready
= 1;
1241 * See if we are in danger of overflowing a buffer. If
1242 * so, use hardware flow control to ease the pressure.
1244 if (sc
->sc_rx_blocked
== 0 &&
1245 cc
< sc
->sc_r_hiwat
) {
1246 sc
->sc_rx_blocked
= 1;
1250 * If we're out of space, throw away any further input.
1253 while (ISSET(rsr
, RSR_BFULL
|RSR_BREAK
)) {
1261 * Done handling any receive interrupts. See if data can be
1262 * transmitted as well. Schedule tx done event if no data left
1263 * and tty was marked busy.
1266 if (ISSET(tsr
, TSR_BE
)) {
1268 * If we've delayed a parameter change, do it now, and restart
1271 if (sc
->sc_heldchange
) {
1272 ser_loadchannelregs(sc
);
1273 sc
->sc_heldchange
= 0;
1274 sc
->sc_tbc
= sc
->sc_heldtbc
;
1277 /* Output the next character, if any. */
1278 if (sc
->sc_tbc
> 0) {
1279 MFP
->mf_udr
= *sc
->sc_tba
;
1282 } else if (sc
->sc_tx_busy
) {
1287 softint_schedule(sc
->sc_sicookie
);
1292 serspeed(long speed
)
1294 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
1301 for (div
= 4; div
<= 64; div
*= 4) {
1302 x
= divrnd((SER_FREQ
/ div
), speed
);
1305 * The value must fit in the timer-d dataregister. If
1306 * not, try another delay-mode.
1312 * Baudrate to high for the interface or cannot be made
1318 err
= divrnd((SER_FREQ
/ div
) * 1000, speed
* x
) - 1000;
1321 if (err
> SER_TOLERANCE
)
1325 * Translate 'div' to delay-code
1334 return ((x
/2) | (div
<< 8));
1342 * Following are all routines needed for SER to act as console
1344 #include <dev/cons.h>
1347 sercnprobe(struct consdev
*cp
)
1350 * Activate serial console when DCD present...
1352 if (MFP
->mf_gpip
& MCR_DCD
) {
1353 cp
->cn_pri
= CN_DEAD
;
1357 /* initialize required fields */
1358 /* XXX: LWP What unit? */
1359 cp
->cn_dev
= makedev(cdevsw_lookup_major(&ser_cdevsw
), 0);
1361 cp
->cn_pri
= CN_REMOTE
; /* Force a serial port console */
1363 cp
->cn_pri
= CN_NORMAL
;
1364 #endif /* SERCONSOLE > 0 */
1368 sercninit(struct consdev
*cp
)
1370 serinitcons(CONSBAUD
);
1374 * Initialize UART to known state.
1379 int ospeed
= serspeed(baud
);
1381 MFP
->mf_ucr
= UCR_CLKDIV
|UCR_8BITS
|UCR_STOPB1
;
1382 MFP
->mf_rsr
= RSR_ENAB
;
1383 MFP
->mf_tsr
= TSR_ENAB
;
1385 single_inst_bclr_b(MFP
->mf_tcdcr
, 0x07);
1386 MFP
->mf_tddr
= ospeed
;
1387 single_inst_bset_b(MFP
->mf_tcdcr
, (ospeed
>> 8) & 0x0f);
1391 * Set UART for console use. Do normal init, then enable interrupts.
1394 serinitcons(int baud
)
1402 single_inst_bset_b(MFP
->mf_imra
, (IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
));
1406 sercngetc(dev_t dev
)
1412 while (!ISSET(stat
= MFP
->mf_rsr
, RSR_BFULL
)) {
1413 if (!ISSET(stat
, RSR_ENAB
)) /* XXX */
1414 MFP
->mf_rsr
|= RSR_ENAB
;
1415 if (stat
& (RSR_FERR
|RSR_PERR
|RSR_OERR
))
1424 u_int s_stat1
, s_stat2
, s_stat3
;
1426 sercnputc(dev_t dev
, int c
)
1431 /* Mask serial interrupts */
1432 imra
= MFP
->mf_imra
& (IA_RRDY
|IA_RERR
|IA_TRDY
|IA_TERR
);
1433 single_inst_bclr_b(MFP
->mf_imra
, imra
);
1436 /* wait for any pending transmission to finish */
1438 s_stat1
= MFP
->mf_tsr
;
1439 while (!ISSET(stat
= MFP
->mf_tsr
, TSR_BE
) && --timo
)
1442 /* wait for this transmission to complete */
1444 s_stat2
= MFP
->mf_tsr
;
1445 while (!ISSET(stat
= MFP
->mf_tsr
, TSR_BE
) && --timo
)
1448 s_stat3
= MFP
->mf_tsr
;
1449 /* Clear pending serial interrupts and re-enable */
1450 MFP
->mf_ipra
= (u_int8_t
)~imra
;
1451 single_inst_bset_b(MFP
->mf_imra
, imra
);
1455 sercnpollc(dev_t dev
, int on
)