1 /* $NetBSD: sbscn.c,v 1.30 2009/11/21 17:40:28 rmind Exp $ */
5 * Broadcom Corporation. All rights reserved.
7 * This software is furnished under license and may be used and copied only
8 * in accordance with the following terms and conditions. Subject to these
9 * conditions, you may download, copy, install, use, modify and distribute
10 * modified or unmodified copies of this software in source and/or binary
11 * form. No title or ownership is transferred hereby.
13 * 1) Any source code used, modified or distributed must reproduce and
14 * retain this copyright notice and list of conditions as they appear in
17 * 2) No right is granted to use any trade name, trademark, or logo of
18 * Broadcom Corporation. The "Broadcom Corporation" name may not be
19 * used to endorse or promote products derived from this software
20 * without the prior written permission of Broadcom Corporation.
22 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED WARRANTIES OF
24 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
25 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM BE LIABLE
26 * FOR ANY DAMAGES WHATSOEVER, AND IN PARTICULAR, BROADCOM SHALL NOT BE
27 * LIABLE FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
31 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
32 * OR OTHERWISE), EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 /* from: $NetBSD: com.c,v 1.172 2000/05/03 19:19:04 thorpej Exp */
38 * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
39 * All rights reserved.
41 * This code is derived from software contributed to The NetBSD Foundation
42 * by Charles M. Hannum.
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
53 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
54 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
55 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
57 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
58 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
59 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
60 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
61 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
62 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
63 * POSSIBILITY OF SUCH DAMAGE.
67 * Copyright (c) 1991 The Regents of the University of California.
68 * All rights reserved.
70 * Redistribution and use in source and binary forms, with or without
71 * modification, are permitted provided that the following conditions
73 * 1. Redistributions of source code must retain the above copyright
74 * notice, this list of conditions and the following disclaimer.
75 * 2. Redistributions in binary form must reproduce the above copyright
76 * notice, this list of conditions and the following disclaimer in the
77 * documentation and/or other materials provided with the distribution.
78 * 3. Neither the name of the University nor the names of its contributors
79 * may be used to endorse or promote products derived from this software
80 * without specific prior written permission.
82 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
83 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
84 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
85 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
86 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
87 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
88 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
89 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
90 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
91 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94 * @(#)com.c 7.5 (Berkeley) 5/16/91
98 * `sbscn' driver, supports SiByte SB-1250 SOC DUART.
100 * This DUART is quite similar in programming model to the scn2681/68681
101 * DUARTs supported by the NetBSD/amiga `mfc' and NetBSD/pc532 `scn'
102 * driver, but substantial rework would have been necessary to make
103 * those drivers sane w.r.t. bus_space (which would then have been
104 * required on NetBSD/sbmips very early on), and to accommodate the
105 * different register mappings.
107 * So, another driver. Eventually there should be One True Driver,
108 * but we're not here to save the world.
111 #include <sys/cdefs.h>
112 __KERNEL_RCSID(0, "$NetBSD: sbscn.c,v 1.30 2009/11/21 17:40:28 rmind Exp $");
119 #if NRND > 0 && defined(RND_SBSCN)
123 #include <sys/param.h>
124 #include <sys/systm.h>
125 #include <sys/ioctl.h>
126 #include <sys/select.h>
128 #include <sys/proc.h>
129 #include <sys/conf.h>
130 #include <sys/file.h>
132 #include <sys/kernel.h>
133 #include <sys/syslog.h>
134 #include <sys/types.h>
135 #include <sys/device.h>
136 #include <sys/malloc.h>
137 #include <sys/vnode.h>
138 #include <sys/kauth.h>
139 #include <sys/intr.h>
141 #include <mips/sibyte/dev/sbobiovar.h>
143 #include <mips/sibyte/dev/sbscnreg.h>
145 #include <mips/sibyte/dev/sbscnvar.h>
146 #include <dev/cons.h>
147 #include <machine/locore.h>
149 void sbscn_attach_channel(struct sbscn_softc
*sc
, int chan
, int intr
);
150 #if defined(DDB) || defined(KGDB)
151 static void sbscn_enable_debugport(struct sbscn_channel
*ch
);
153 void sbscn_config(struct sbscn_channel
*ch
);
154 void sbscn_shutdown(struct sbscn_channel
*ch
);
155 int sbscn_speed(long, long *);
156 static int cflag2modes(tcflag_t
, u_char
*, u_char
*);
157 int sbscn_param(struct tty
*, struct termios
*);
158 void sbscn_start(struct tty
*);
159 int sbscn_hwiflow(struct tty
*, int);
161 void sbscn_loadchannelregs(struct sbscn_channel
*);
162 void sbscn_dohwiflow(struct sbscn_channel
*);
163 void sbscn_break(struct sbscn_channel
*, int);
164 void sbscn_modem(struct sbscn_channel
*, int);
165 void tiocm_to_sbscn(struct sbscn_channel
*, int, int);
166 int sbscn_to_tiocm(struct sbscn_channel
*);
167 void sbscn_iflush(struct sbscn_channel
*);
169 int sbscn_init(u_long addr
, int chan
, int rate
, tcflag_t cflag
);
170 int sbscn_common_getc(u_long addr
, int chan
);
171 void sbscn_common_putc(u_long addr
, int chan
, int c
);
172 void sbscn_intr(void *arg
, uint32_t status
, vaddr_t pc
);
174 int sbscn_cngetc(dev_t dev
);
175 void sbscn_cnputc(dev_t dev
, int c
);
176 void sbscn_cnpollc(dev_t dev
, int on
);
178 extern struct cfdriver sbscn_cd
;
180 dev_type_open(sbscnopen
);
181 dev_type_close(sbscnclose
);
182 dev_type_read(sbscnread
);
183 dev_type_write(sbscnwrite
);
184 dev_type_ioctl(sbscnioctl
);
185 dev_type_stop(sbscnstop
);
186 dev_type_tty(sbscntty
);
187 dev_type_poll(sbscnpoll
);
189 const struct cdevsw sbscn_cdevsw
= {
190 sbscnopen
, sbscnclose
, sbscnread
, sbscnwrite
, sbscnioctl
,
191 sbscnstop
, sbscntty
, sbscnpoll
, nommap
, ttykqfilter
, D_TTY
194 #define integrate static inline
195 void sbscn_soft(void *);
196 integrate
void sbscn_rxsoft(struct sbscn_channel
*, struct tty
*);
197 integrate
void sbscn_txsoft(struct sbscn_channel
*, struct tty
*);
198 integrate
void sbscn_stsoft(struct sbscn_channel
*, struct tty
*);
199 integrate
void sbscn_schedrx(struct sbscn_channel
*);
200 void sbscn_diag(void *);
203 * Make this an option variable one can patch.
204 * But be warned: this must be a power of 2!
206 u_int sbscn_rbuf_size
= SBSCN_RING_SIZE
;
208 /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
209 u_int sbscn_rbuf_hiwat
= (SBSCN_RING_SIZE
* 1) / 4;
210 u_int sbscn_rbuf_lowat
= (SBSCN_RING_SIZE
* 3) / 4;
212 static int sbscn_cons_present
;
213 static int sbscn_cons_attached
;
214 static u_long sbscn_cons_addr
;
215 static int sbscn_cons_chan
;
216 static int sbscn_cons_rate
;
217 static tcflag_t sbscn_cons_cflag
;
220 #include <sys/kgdb.h>
222 static int sbscn_kgdb_present
;
223 static int sbscn_kgdb_attached
;
224 static u_long sbscn_kgdb_addr
;
225 static int sbscn_kgdb_chan
;
227 int sbscn_kgdb_getc(void *);
228 void sbscn_kgdb_putc(void *, int);
231 static int sbscn_match(struct device
*, struct cfdata
*, void *);
232 static void sbscn_attach(struct device
*, struct device
*, void *);
234 CFATTACH_DECL(sbscn
, sizeof(struct sbscn_softc
),
235 sbscn_match
, sbscn_attach
, NULL
, NULL
);
237 #define READ_REG(rp) (mips3_ld((volatile uint64_t *)(rp)))
238 #define WRITE_REG(rp, val) (mips3_sd((volatile uint64_t *)(rp), (val)))
241 * input and output signals are actually the _inverse_ of the bits in the
242 * input and output port registers!
244 #define GET_INPUT_SIGNALS(ch) \
245 ((~READ_REG(MIPS_PHYS_TO_KSEG1((ch)->ch_sc->sc_addr + 0x280))) & (ch)->ch_i_mask)
246 #define SET_OUTPUT_SIGNALS(ch, val) \
248 int sigs_to_set, sigs_to_clr; \
250 sigs_to_set = (ch)->ch_o_mask & val; \
251 sigs_to_clr = (ch)->ch_o_mask & ~val; \
253 /* set signals by clearing op bits, and vice versa */ \
254 WRITE_REG(MIPS_PHYS_TO_KSEG1((ch)->ch_sc->sc_addr + 0x2c0), \
256 WRITE_REG(MIPS_PHYS_TO_KSEG1((ch)->ch_sc->sc_addr + 0x2b0), \
261 sbscn_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
263 struct sbobio_attach_args
*sap
= aux
;
265 if (sap
->sa_locs
.sa_type
!= SBOBIO_DEVTYPE_DUART
)
272 sbscn_attach(struct device
*parent
, struct device
*self
, void *aux
)
274 struct sbscn_softc
*sc
= (struct sbscn_softc
*)self
;
275 struct sbobio_attach_args
*sap
= aux
;
278 sc
->sc_addr
= sap
->sa_locs
.sa_addr
;
281 for (i
= 0; i
< 2; i
++)
282 sbscn_attach_channel(sc
, i
, sap
->sa_locs
.sa_intr
[i
]);
284 /* init duart_opcr */
285 WRITE_REG(MIPS_PHYS_TO_KSEG1(sc
->sc_addr
+ 0x270), 0);
286 /* init duart_aux_ctrl */
287 WRITE_REG(MIPS_PHYS_TO_KSEG1(sc
->sc_addr
+ 0x210), 0x0f); /* XXX */
291 sbscn_attach_channel(struct sbscn_softc
*sc
, int chan
, int intr
)
293 struct sbscn_channel
*ch
= &sc
->sc_channels
[chan
];
300 chan_addr
= sc
->sc_addr
+ (0x100 * chan
);
301 ch
->ch_base
= (void *)MIPS_PHYS_TO_KSEG1(chan_addr
);
303 (void *)MIPS_PHYS_TO_KSEG1(sc
->sc_addr
+ 0x220 + (0x20 * chan
));
305 (void *)MIPS_PHYS_TO_KSEG1(sc
->sc_addr
+ 0x230 + (0x20 * chan
));
308 (void *)MIPS_PHYS_TO_KSEG1(sc
->sc_addr
+ 0x2d0 + (0x10 * chan
));
311 ch
->ch_i_dcd
= ch
->ch_i_dcd_pin
= 0 /* XXXCGD */;
312 ch
->ch_i_cts
= ch
->ch_i_cts_pin
= 0 /* XXXCGD */;
313 ch
->ch_i_dsr
= ch
->ch_i_dsr_pin
= 0 /* XXXCGD */;
314 ch
->ch_i_ri
= ch
->ch_i_ri_pin
= 0 /* XXXCGD */;
316 ch
->ch_i_dcd
| ch
->ch_i_cts
| ch
->ch_i_dsr
| ch
->ch_i_ri
;
317 ch
->ch_o_dtr
= ch
->ch_o_dtr_pin
= 0 /* XXXCGD */;
318 ch
->ch_o_rts
= ch
->ch_o_rts_pin
= 0 /* XXXCGD */;
319 ch
->ch_o_mask
= ch
->ch_o_dtr
| ch
->ch_o_rts
;
321 ch
->ch_intrhand
= cpu_intr_establish(intr
, IPL_SERIAL
, sbscn_intr
, ch
);
322 callout_init(&ch
->ch_diag_callout
, 0);
324 /* Disable interrupts before configuring the device. */
326 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
328 if (sbscn_cons_present
&&
329 sbscn_cons_addr
== chan_addr
&& sbscn_cons_chan
== chan
) {
330 sbscn_cons_attached
= 1;
332 /* Make sure the console is always "hardwired". */
333 delay(1000); /* wait for output to finish */
334 SET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
);
335 SET(ch
->ch_swflags
, TIOCFLAG_SOFTCAR
);
339 tp
->t_oproc
= sbscn_start
;
340 tp
->t_param
= sbscn_param
;
341 tp
->t_hwiflow
= sbscn_hwiflow
;
344 ch
->ch_rbuf
= malloc(sbscn_rbuf_size
<< 1, M_DEVBUF
, M_NOWAIT
);
345 if (ch
->ch_rbuf
== NULL
) {
346 printf("%s: channel %d: unable to allocate ring buffer\n",
347 sc
->sc_dev
.dv_xname
, chan
);
350 ch
->ch_ebuf
= ch
->ch_rbuf
+ (sbscn_rbuf_size
<< 1);
354 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
)) {
357 /* locate the major number */
358 maj
= cdevsw_lookup_major(&sbscn_cdevsw
);
360 cn_tab
->cn_dev
= makedev(maj
,
361 (device_unit(&sc
->sc_dev
) << 1) + chan
);
363 printf("%s: channel %d: console\n", sc
->sc_dev
.dv_xname
, chan
);
368 * Allow kgdb to "take over" this port. If this is
369 * the kgdb device, it has exclusive use.
371 if (sbscn_kgdb_present
&&
372 sbscn_kgdb_addr
== chan_addr
&& sbscn_kgdb_chan
== chan
) {
373 sbscn_kgdb_attached
= 1;
375 SET(sc
->sc_hwflags
, SBSCN_HW_KGDB
);
376 printf("%s: channel %d: kgdb\n", sc
->sc_dev
.dv_xname
, chan
);
380 ch
->ch_si
= softint_establish(SOFTINT_SERIAL
, sbscn_soft
, ch
);
382 #if NRND > 0 && defined(RND_SBSCN)
383 rnd_attach_source(&ch
->ch_rnd_source
, sc
->sc_dev
.dv_xname
,
389 SET(ch
->ch_hwflags
, SBSCN_HW_DEV_OK
);
393 sbscn_speed(long speed
, long *brcp
)
395 #define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */
398 int frequency
= 100000000;
400 *brcp
= divrnd(frequency
/ 20, speed
) - 1;
404 x
= divrnd(frequency
/ 20, speed
);
407 err
= divrnd(((quad_t
)frequency
) * 1000 / 20, speed
* x
) - 1000;
410 if (err
> SBSCN_TOLERANCE
)
419 void sbscn_status(struct sbscn_channel
*, const char *);
421 int sbscn_debug
= 0 /* XXXCGD */;
424 sbscn_status(struct sbscn_channel
*ch
, const char *str
)
426 struct sbscn_softc
*sc
= ch
->ch_sc
;
427 struct tty
*tp
= ch
->ch_tty
;
429 printf("%s: chan %d: %s %sclocal %sdcd %sts_carr_on %sdtr %stx_stopped\n",
430 sc
->sc_dev
.dv_xname
, ch
->ch_num
, str
,
431 ISSET(tp
->t_cflag
, CLOCAL
) ? "+" : "-",
432 ISSET(ch
->ch_iports
, ch
->ch_i_dcd
) ? "+" : "-",
433 ISSET(tp
->t_state
, TS_CARR_ON
) ? "+" : "-",
434 ISSET(ch
->ch_oports
, ch
->ch_o_dtr
) ? "+" : "-",
435 ch
->ch_tx_stopped
? "+" : "-");
437 printf("%s: chan %d: %s %scrtscts %scts %sts_ttstop %srts %xrx_flags\n",
438 sc
->sc_dev
.dv_xname
, ch
->ch_num
, str
,
439 ISSET(tp
->t_cflag
, CRTSCTS
) ? "+" : "-",
440 ISSET(ch
->ch_iports
, ch
->ch_i_cts
) ? "+" : "-",
441 ISSET(tp
->t_state
, TS_TTSTOP
) ? "+" : "-",
442 ISSET(ch
->ch_oports
, ch
->ch_o_rts
) ? "+" : "-",
447 #if defined(DDB) || defined(KGDB)
449 sbscn_enable_debugport(struct sbscn_channel
*ch
)
453 /* Turn on line break interrupt, set carrier. */
456 #if 0 /* DO NOT turn on break interrupt at this time. */
461 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
462 SET(ch
->ch_oports
, ch
->ch_o_dtr
| ch
->ch_o_rts
);
463 SET_OUTPUT_SIGNALS(ch
, ch
->ch_oports
);
470 sbscn_config(struct sbscn_channel
*ch
)
473 /* Disable interrupts before configuring the device. */
475 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
478 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
))
479 sbscn_enable_debugport(ch
);
484 * Allow kgdb to "take over" this port. If this is
485 * the kgdb device, it has exclusive use.
487 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_KGDB
))
488 sbscn_enable_debugport(ch
);
493 sbscn_shutdown(struct sbscn_channel
*ch
)
495 struct tty
*tp
= ch
->ch_tty
;
500 /* If we were asserting flow control, then deassert it. */
501 SET(ch
->ch_rx_flags
, RX_IBUF_BLOCKED
);
504 /* Clear any break condition set with TIOCSBRK. */
508 * Hang up if necessary. Wait a bit, so the other side has time to
509 * notice even if we immediately open the port again.
510 * Avoid tsleeping above splhigh().
512 if (ISSET(tp
->t_cflag
, HUPCL
)) {
515 /* XXX tsleep will only timeout */
516 (void) tsleep(ch
, TTIPRI
, ttclos
, hz
);
520 /* Turn off interrupts. */
522 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
))
523 #if 0 /* DO NOT turn on break interrupt at this time. */
524 ch
->ch_imr
= 0x04; /* interrupt on break */
531 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
537 sbscnopen(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
539 int chan
= SBSCN_CHAN(dev
);
540 struct sbscn_softc
*sc
;
541 struct sbscn_channel
*ch
;
546 sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
549 ch
= &sc
->sc_channels
[chan
];
550 if (!ISSET(ch
->ch_hwflags
, SBSCN_HW_DEV_OK
) || ch
->ch_rbuf
== NULL
)
555 * If this is the kgdb port, no other use is permitted.
557 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_KGDB
))
563 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
569 * Do the following iff this is a first open.
571 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
578 /* Turn on receive, break, and status change interrupts. */
579 #if 0 /* DO NOT turn on break or status change interrupt at this time. */
584 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
586 /* Fetch the current modem control status, needed later. */
587 ch
->ch_iports
= GET_INPUT_SIGNALS(ch
);
588 ch
->ch_iports_delta
= 0;
592 * Initialize the termios status to the defaults. Add in the
593 * sticky bits from TIOCSFLAGS.
596 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
)) {
597 t
.c_ospeed
= sbscn_cons_rate
;
598 t
.c_cflag
= sbscn_cons_cflag
;
600 t
.c_ospeed
= TTYDEF_SPEED
;
601 t
.c_cflag
= TTYDEF_CFLAG
;
603 if (ISSET(ch
->ch_swflags
, TIOCFLAG_CLOCAL
))
604 SET(t
.c_cflag
, CLOCAL
);
605 if (ISSET(ch
->ch_swflags
, TIOCFLAG_CRTSCTS
))
606 SET(t
.c_cflag
, CRTSCTS
);
607 if (ISSET(ch
->ch_swflags
, TIOCFLAG_MDMBUF
))
608 SET(t
.c_cflag
, MDMBUF
);
609 /* Make sure sbscn_param() will do something. */
611 (void) sbscn_param(tp
, &t
);
612 tp
->t_iflag
= TTYDEF_IFLAG
;
613 tp
->t_oflag
= TTYDEF_OFLAG
;
614 tp
->t_lflag
= TTYDEF_LFLAG
;
621 * Turn on DTR. We must always do this, even if carrier is not
622 * present, because otherwise we'd have to use TIOCSDTR
623 * immediately after setting CLOCAL, which applications do not
624 * expect. We always assert DTR while the device is open
625 * unless explicitly requested to deassert it.
629 /* Clear the input ring, and unblock. */
630 ch
->ch_rbput
= ch
->ch_rbget
= ch
->ch_rbuf
;
631 ch
->ch_rbavail
= sbscn_rbuf_size
;
633 CLR(ch
->ch_rx_flags
, RX_ANY_BLOCK
);
638 sbscn_status(ch
, "sbscnopen ");
646 error
= ttyopen(tp
, SBSCN_DIALOUT(dev
), ISSET(flag
, O_NONBLOCK
));
650 error
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
657 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
659 * We failed to open the device, and nobody else had it opened.
660 * Clean up the state as appropriate.
669 sbscnclose(dev_t dev
, int flag
, int mode
, struct lwp
*l
)
671 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
672 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(dev
)];
673 struct tty
*tp
= ch
->ch_tty
;
675 /* XXX This is for cons.c. */
676 if (!ISSET(tp
->t_state
, TS_ISOPEN
))
679 (*tp
->t_linesw
->l_close
)(tp
, flag
);
682 if (!ISSET(tp
->t_state
, TS_ISOPEN
) && tp
->t_wopen
== 0) {
684 * Although we got a last close, the device may still be in
685 * use; e.g. if this was the dialout node, and there are still
686 * processes waiting for carrier on the non-dialout node.
695 sbscnread(dev_t dev
, struct uio
*uio
, int flag
)
697 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
698 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(dev
)];
699 struct tty
*tp
= ch
->ch_tty
;
701 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flag
));
705 sbscnwrite(dev_t dev
, struct uio
*uio
, int flag
)
707 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
708 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(dev
)];
709 struct tty
*tp
= ch
->ch_tty
;
711 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flag
));
715 sbscnpoll(dev_t dev
, int events
, struct lwp
*l
)
717 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
718 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(dev
)];
719 struct tty
*tp
= ch
->ch_tty
;
721 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
727 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
728 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(dev
)];
729 struct tty
*tp
= ch
->ch_tty
;
735 sbscnioctl(dev_t dev
, u_long cmd
, void *data
, int flag
, struct lwp
*l
)
737 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(dev
));
738 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(dev
)];
739 struct tty
*tp
= ch
->ch_tty
;
743 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flag
, l
);
744 if (error
!= EPASSTHROUGH
)
747 error
= ttioctl(tp
, cmd
, data
, flag
, l
);
748 if (error
!= EPASSTHROUGH
)
773 *(int *)data
= ch
->ch_swflags
;
777 error
= kauth_authorize_device_tty(l
->l_cred
,
778 KAUTH_DEVICE_TTY_PRIVSET
, tp
);
781 ch
->ch_swflags
= *(int *)data
;
787 tiocm_to_sbscn(ch
, cmd
, *(int *)data
);
791 *(int *)data
= sbscn_to_tiocm(ch
);
795 error
= EPASSTHROUGH
;
803 sbscn_status(ch
, "sbscn_ioctl ");
810 sbscn_schedrx(struct sbscn_channel
*ch
)
815 /* Wake up the poller. */
816 softint_schedule(ch
->ch_si
);
820 sbscn_break(struct sbscn_channel
*ch
, int onoff
)
823 /* XXXCGD delay break until not busy */
825 WRITE_REG(ch
->ch_base
+ 0x50, 0x60);
827 WRITE_REG(ch
->ch_base
+ 0x50, 0x70);
830 if (!ch
->ch_heldchange
) {
831 if (ch
->ch_tx_busy
) {
832 ch
->ch_heldtbc
= ch
->ch_tbc
;
834 ch
->ch_heldchange
= 1;
836 sbscn_loadchannelregs(ch
);
842 sbscn_modem(struct sbscn_channel
*ch
, int onoff
)
845 if (ch
->ch_o_dtr
== 0)
849 SET(ch
->ch_oports
, ch
->ch_o_dtr
);
851 CLR(ch
->ch_oports
, ch
->ch_o_dtr
);
853 if (!ch
->ch_heldchange
) {
854 if (ch
->ch_tx_busy
) {
855 ch
->ch_heldtbc
= ch
->ch_tbc
;
857 ch
->ch_heldchange
= 1;
859 sbscn_loadchannelregs(ch
);
864 tiocm_to_sbscn(struct sbscn_channel
*ch
, int how
, int ttybits
)
869 if (ISSET(ttybits
, TIOCM_DTR
))
870 SET(bits
, ch
->ch_o_dtr
);
871 if (ISSET(ttybits
, TIOCM_RTS
))
872 SET(bits
, ch
->ch_o_rts
);
876 CLR(ch
->ch_oports
, bits
);
880 SET(ch
->ch_oports
, bits
);
884 ch
->ch_oports
= bits
;
888 if (!ch
->ch_heldchange
) {
889 if (ch
->ch_tx_busy
) {
890 ch
->ch_heldtbc
= ch
->ch_tbc
;
892 ch
->ch_heldchange
= 1;
894 sbscn_loadchannelregs(ch
);
899 sbscn_to_tiocm(struct sbscn_channel
*ch
)
904 hwbits
= ch
->ch_oports
;
905 if (ISSET(hwbits
, ch
->ch_o_dtr
))
906 SET(ttybits
, TIOCM_DTR
);
907 if (ISSET(hwbits
, ch
->ch_o_rts
))
908 SET(ttybits
, TIOCM_RTS
);
910 hwbits
= ch
->ch_iports
;
911 if (ISSET(hwbits
, ch
->ch_i_dcd
))
912 SET(ttybits
, TIOCM_CD
);
913 if (ISSET(hwbits
, ch
->ch_i_cts
))
914 SET(ttybits
, TIOCM_CTS
);
915 if (ISSET(hwbits
, ch
->ch_i_dsr
))
916 SET(ttybits
, TIOCM_DSR
);
917 if (ISSET(hwbits
, ch
->ch_i_ri
))
918 SET(ttybits
, TIOCM_RI
);
921 SET(ttybits
, TIOCM_LE
);
927 cflag2modes(tcflag_t cflag
, u_char
*mode1p
, u_char
*mode2p
)
935 switch (ISSET(cflag
, CSIZE
)) {
937 mode1
|= 2; /* XXX */
941 /* FALLTHRU for sanity */
943 mode1
|= 3; /* XXX */
946 if (!ISSET(cflag
, PARENB
))
950 if (ISSET(cflag
, PARODD
))
954 if (ISSET(cflag
, CSTOPB
))
955 mode2
|= 1 << 3; /* two stop bits XXX not std */
957 if (ISSET(cflag
, CRTSCTS
)) {
968 sbscn_param(struct tty
*tp
, struct termios
*t
)
970 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(tp
->t_dev
));
971 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(tp
->t_dev
)];
976 /* XXX reset to console parameters if console? */
981 /* Check requested parameters. */
982 if (sbscn_speed(t
->c_ospeed
, &brc
) < 0)
984 if (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
)
988 * For the console, always force CLOCAL and !HUPCL, so that the port
991 if (ISSET(ch
->ch_swflags
, TIOCFLAG_SOFTCAR
) ||
992 ISSET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
)) {
993 SET(t
->c_cflag
, CLOCAL
);
994 CLR(t
->c_cflag
, HUPCL
);
998 * If there were no changes, don't do anything. This avoids dropping
999 * input and improves performance when all we did was frob things like
1002 if (tp
->t_ospeed
== t
->c_ospeed
&&
1003 tp
->t_cflag
== t
->c_cflag
)
1006 if (cflag2modes(t
->c_cflag
, &mode1
, &mode2
) < 0)
1011 ch
->ch_mode1
= mode1
;
1012 ch
->ch_mode2
= mode2
;
1015 * If we're not in a mode that assumes a connection is present, then
1016 * ignore carrier changes.
1018 if (ISSET(t
->c_cflag
, CLOCAL
| MDMBUF
))
1021 ch
->ch_i_dcd
= ch
->ch_i_dcd_pin
;
1023 * Set the flow control pins depending on the current flow control
1026 if (ISSET(t
->c_cflag
, CRTSCTS
)) {
1027 ch
->ch_o_dtr
= ch
->ch_o_dtr_pin
;
1028 ch
->ch_o_rts
= ch
->ch_o_rts_pin
;
1029 ch
->ch_i_cts
= ch
->ch_i_cts_pin
;
1030 /* hw controle enable bits in mod regs set by cflag2modes */
1031 } else if (ISSET(t
->c_cflag
, MDMBUF
)) {
1033 * For DTR/DCD flow control, make sure we don't toggle DTR for
1034 * carrier detection.
1037 ch
->ch_o_rts
= ch
->ch_o_dtr_pin
;
1038 ch
->ch_i_cts
= ch
->ch_i_dcd_pin
;
1041 * If no flow control, then always set RTS. This will make
1042 * the other side happy if it mistakenly thinks we're doing
1043 * RTS/CTS flow control.
1045 ch
->ch_o_dtr
= ch
->ch_o_dtr_pin
| ch
->ch_o_rts_pin
;
1048 if (ISSET(ch
->ch_oports
, ch
->ch_o_dtr_pin
))
1049 SET(ch
->ch_oports
, ch
->ch_o_rts_pin
);
1051 CLR(ch
->ch_oports
, ch
->ch_o_rts_pin
);
1053 /* XXX maybe mask the ports which generate intrs? */
1057 /* XXX maybe set fifo-full receive mode if RTSCTS and high speed? */
1059 /* And copy to tty. */
1061 tp
->t_ospeed
= t
->c_ospeed
;
1062 tp
->t_cflag
= t
->c_cflag
;
1064 if (!ch
->ch_heldchange
) {
1065 if (ch
->ch_tx_busy
) {
1066 ch
->ch_heldtbc
= ch
->ch_tbc
;
1068 ch
->ch_heldchange
= 1;
1070 sbscn_loadchannelregs(ch
);
1073 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
1074 /* Disable the high water mark. */
1077 if (ISSET(ch
->ch_rx_flags
, RX_TTY_OVERFLOWED
)) {
1078 CLR(ch
->ch_rx_flags
, RX_TTY_OVERFLOWED
);
1081 if (ISSET(ch
->ch_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
)) {
1082 CLR(ch
->ch_rx_flags
, RX_TTY_BLOCKED
|RX_IBUF_BLOCKED
);
1083 sbscn_dohwiflow(ch
);
1086 ch
->ch_r_hiwat
= sbscn_rbuf_hiwat
;
1087 ch
->ch_r_lowat
= sbscn_rbuf_lowat
;
1093 * Update the tty layer's idea of the carrier bit, in case we changed
1094 * CLOCAL or MDMBUF. We don't hang up here; we only do that by
1097 (void) (*tp
->t_linesw
->l_modem
)(tp
,
1098 ISSET(ch
->ch_iports
, ch
->ch_i_dcd
));
1102 sbscn_status(ch
, "sbscnparam ");
1105 if (!ISSET(t
->c_cflag
, CHWFLOW
)) {
1106 if (ch
->ch_tx_stopped
) {
1107 ch
->ch_tx_stopped
= 0;
1116 sbscn_iflush(struct sbscn_channel
*ch
)
1127 /* flush any pending I/O */
1128 while (ISSET(READ_REG(ch
->ch_base
+ 0x20), 0x01)
1135 READ_REG(ch
->ch_base
+ 0x60);
1138 printf("%s: sbscn_iflush timeout %02x\n",
1139 ch
->ch_sc
->sc_dev
.dv_xname
, reg
& 0xff);
1144 sbscn_loadchannelregs(struct sbscn_channel
*ch
)
1147 /* XXXXX necessary? */
1150 WRITE_REG(ch
->ch_imr_base
, 0);
1153 WRITE_REG(ch
->ch_base
+ 0x00, ch
->ch_mode1
);
1154 WRITE_REG(ch
->ch_base
+ 0x10, ch
->ch_mode2
);
1155 WRITE_REG(ch
->ch_base
+ 0x30, ch
->ch_brc
);
1157 ch
->ch_oports_active
= ch
->ch_oports
;
1158 SET_OUTPUT_SIGNALS(ch
, ch
->ch_oports_active
);
1160 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1164 sbscn_hwiflow(struct tty
*tp
, int block
)
1166 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(tp
->t_dev
));
1167 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(tp
->t_dev
)];
1170 if (ch
->ch_o_rts
== 0)
1175 if (!ISSET(ch
->ch_rx_flags
, RX_TTY_BLOCKED
)) {
1176 SET(ch
->ch_rx_flags
, RX_TTY_BLOCKED
);
1177 sbscn_dohwiflow(ch
);
1180 if (ISSET(ch
->ch_rx_flags
, RX_TTY_OVERFLOWED
)) {
1181 CLR(ch
->ch_rx_flags
, RX_TTY_OVERFLOWED
);
1184 if (ISSET(ch
->ch_rx_flags
, RX_TTY_BLOCKED
)) {
1185 CLR(ch
->ch_rx_flags
, RX_TTY_BLOCKED
);
1186 sbscn_dohwiflow(ch
);
1194 * (un)block input via hw flowcontrol
1197 sbscn_dohwiflow(struct sbscn_channel
*ch
)
1200 if (ch
->ch_o_rts
== 0)
1203 if (ISSET(ch
->ch_rx_flags
, RX_ANY_BLOCK
)) {
1204 CLR(ch
->ch_oports
, ch
->ch_o_rts
);
1205 CLR(ch
->ch_oports_active
, ch
->ch_o_rts
);
1207 SET(ch
->ch_oports
, ch
->ch_o_rts
);
1208 SET(ch
->ch_oports_active
, ch
->ch_o_rts
);
1210 SET_OUTPUT_SIGNALS(ch
, ch
->ch_oports_active
);
1214 sbscn_start(struct tty
*tp
)
1216 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(tp
->t_dev
));
1217 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(tp
->t_dev
)];
1221 if (ISSET(tp
->t_state
, TS_BUSY
| TS_TIMEOUT
| TS_TTSTOP
))
1223 if (ch
->ch_tx_stopped
)
1228 /* Grab the first contiguous region of buffer space. */
1233 tba
= tp
->t_outq
.c_cf
;
1234 tbc
= ndqb(&tp
->t_outq
, 0);
1242 SET(tp
->t_state
, TS_BUSY
);
1245 /* Enable transmit completion interrupts if necessary. */
1246 if (!ISSET(ch
->ch_imr
, 0x1)) {
1247 SET(ch
->ch_imr
, 0x1);
1248 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1251 /* Output the first chunk of the contiguous buffer. */
1255 while (ch
->ch_tbc
&& READ_REG(ch
->ch_base
+ 0x20) & 0x04) {
1258 WRITE_REG(ch
->ch_base
+ 0x70, c
);
1267 * Stop output on a line.
1270 sbscnstop(struct tty
*tp
, int flag
)
1272 struct sbscn_softc
*sc
= device_lookup_private(&sbscn_cd
, SBSCN_UNIT(tp
->t_dev
));
1273 struct sbscn_channel
*ch
= &sc
->sc_channels
[SBSCN_CHAN(tp
->t_dev
)];
1277 if (ISSET(tp
->t_state
, TS_BUSY
)) {
1278 /* Stop transmitting at the next chunk. */
1281 if (!ISSET(tp
->t_state
, TS_TTSTOP
))
1282 SET(tp
->t_state
, TS_FLUSH
);
1288 sbscn_diag(void *arg
)
1290 struct sbscn_channel
*ch
= arg
;
1291 struct sbscn_softc
*sc
= ch
->ch_sc
;
1292 int overflows
, floods
;
1296 overflows
= ch
->ch_overflows
;
1297 ch
->ch_overflows
= 0;
1298 floods
= ch
->ch_floods
;
1303 log(LOG_WARNING
, "%s: channel %d: %d fifo overflow%s, %d ibuf flood%s\n",
1304 sc
->sc_dev
.dv_xname
, ch
->ch_num
,
1305 overflows
, overflows
== 1 ? "" : "s",
1306 floods
, floods
== 1 ? "" : "s");
1310 sbscn_rxsoft(struct sbscn_channel
*ch
, struct tty
*tp
)
1312 int (*rint
)(int, struct tty
*) = tp
->t_linesw
->l_rint
;
1321 scc
= cc
= sbscn_rbuf_size
- ch
->ch_rbavail
;
1323 if (cc
== sbscn_rbuf_size
) {
1325 if (ch
->ch_errors
++ == 0)
1326 callout_reset(&ch
->ch_diag_callout
, 60 * hz
,
1333 if (ISSET(sr
, 0xf0)) {
1334 if (ISSET(sr
, 0x10)) {
1336 if (ch
->ch_errors
++ == 0)
1337 callout_reset(&ch
->ch_diag_callout
,
1338 60 * hz
, sbscn_diag
, ch
);
1340 if (ISSET(sr
, 0xc0))
1342 if (ISSET(sr
, 0x20))
1345 if ((*rint
)(code
, tp
) == -1) {
1347 * The line discipline's buffer is out of space.
1349 if (!ISSET(ch
->ch_rx_flags
, RX_TTY_BLOCKED
)) {
1351 * We're either not using flow control, or the
1352 * line discipline didn't tell us to block for
1353 * some reason. Either way, we have no way to
1354 * know when there's more space available, so
1355 * just drop the rest of the data.
1359 get
-= sbscn_rbuf_size
<< 1;
1363 * Don't schedule any more receive processing
1364 * until the line discipline tells us there's
1365 * space available (through comhwiflow()).
1366 * Leave the rest of the data in the input
1369 SET(ch
->ch_rx_flags
, RX_TTY_OVERFLOWED
);
1382 cc
= ch
->ch_rbavail
+= scc
- cc
;
1383 /* Buffers should be ok again, release possible block. */
1384 if (cc
>= ch
->ch_r_lowat
) {
1385 if (ISSET(ch
->ch_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1386 CLR(ch
->ch_rx_flags
, RX_IBUF_OVERFLOWED
);
1387 SET(ch
->ch_imr
, 0x02);
1388 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1390 if (ISSET(ch
->ch_rx_flags
, RX_IBUF_BLOCKED
)) {
1391 CLR(ch
->ch_rx_flags
, RX_IBUF_BLOCKED
);
1392 sbscn_dohwiflow(ch
);
1400 sbscn_txsoft(struct sbscn_channel
*ch
, struct tty
*tp
)
1403 CLR(tp
->t_state
, TS_BUSY
);
1404 if (ISSET(tp
->t_state
, TS_FLUSH
))
1405 CLR(tp
->t_state
, TS_FLUSH
);
1407 ndflush(&tp
->t_outq
, (int)(ch
->ch_tba
- tp
->t_outq
.c_cf
));
1408 (*tp
->t_linesw
->l_start
)(tp
);
1412 sbscn_stsoft(struct sbscn_channel
*ch
, struct tty
*tp
)
1414 u_char iports
, delta
;
1418 iports
= ch
->ch_iports
;
1419 delta
= ch
->ch_iports_delta
;
1420 ch
->ch_iports_delta
= 0;
1423 if (ISSET(delta
, ch
->ch_i_dcd
)) {
1425 * Inform the tty layer that carrier detect changed.
1427 (void) (*tp
->t_linesw
->l_modem
)(tp
,
1428 ISSET(iports
, ch
->ch_i_dcd
));
1431 if (ISSET(delta
, ch
->ch_i_cts
)) {
1432 /* Block or unblock output according to flow control. */
1433 if (ISSET(iports
, ch
->ch_i_cts
)) {
1434 ch
->ch_tx_stopped
= 0;
1435 (*tp
->t_linesw
->l_start
)(tp
);
1437 ch
->ch_tx_stopped
= 1;
1443 sbscn_status(ch
, "sbscn_stsoft");
1448 sbscn_soft(void *arg
)
1450 struct sbscn_channel
*ch
= arg
;
1451 struct tty
*tp
= ch
->ch_tty
;
1453 if (ch
->ch_rx_ready
) {
1454 ch
->ch_rx_ready
= 0;
1455 sbscn_rxsoft(ch
, tp
);
1458 if (ch
->ch_st_check
) {
1459 ch
->ch_st_check
= 0;
1460 sbscn_stsoft(ch
, tp
);
1463 if (ch
->ch_tx_done
) {
1465 sbscn_txsoft(ch
, tp
);
1470 sbscn_intr(void *arg
, uint32_t status
, vaddr_t pc
)
1472 struct sbscn_channel
*ch
= arg
;
1478 isr
= READ_REG(ch
->ch_isr_base
) & ch
->ch_imr
;
1484 cc
= ch
->ch_rbavail
;
1487 u_char iports
, delta
;
1491 sr
= READ_REG(ch
->ch_base
+ 0x20);
1492 /* XXX sr 0x01 bit must be set at this point */
1494 #if defined(DDB) || defined(KGDB)
1495 if ((sr
& 0x80) == 0x80) {
1497 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_CONSOLE
)) {
1498 (void)READ_REG(ch
->ch_base
+ 0x60);
1504 if (ISSET(ch
->ch_hwflags
, SBSCN_HW_KGDB
)) {
1505 (void)READ_REG(ch
->ch_base
+ 0x60);
1511 #endif /* DDB || KGDB */
1513 if (!ISSET(ch
->ch_rx_flags
, RX_IBUF_OVERFLOWED
)) {
1515 put
[0] = READ_REG(ch
->ch_base
+ 0x60);
1522 sr
= READ_REG(ch
->ch_base
+ 0x20);
1523 if (!ISSET(sr
, 0x02))
1528 * Current string of incoming characters ended
1529 * because no more data was available or we
1530 * ran out of space. Schedule a receive event
1531 * if any data was received. If we're out of
1532 * space, turn off receive interrupts.
1535 ch
->ch_rbavail
= cc
;
1536 if (!ISSET(ch
->ch_rx_flags
, RX_TTY_OVERFLOWED
))
1537 ch
->ch_rx_ready
= 1;
1540 * See if we are in danger of overflowing a
1541 * buffer. If so, use hardware flow control
1542 * to ease the pressure.
1544 if (!ISSET(ch
->ch_rx_flags
, RX_IBUF_BLOCKED
) &&
1545 cc
< ch
->ch_r_hiwat
) {
1546 SET(ch
->ch_rx_flags
, RX_IBUF_BLOCKED
);
1547 sbscn_dohwiflow(ch
);
1551 * If we're out of space, disable receive
1552 * interrupts until the queue has drained
1556 SET(ch
->ch_rx_flags
,
1557 RX_IBUF_OVERFLOWED
);
1558 CLR(ch
->ch_imr
, 0x02);
1559 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1563 CLR(ch
->ch_imr
, 0x02);
1564 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1570 CLR(ch
->ch_imr
, 0x01);
1571 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1577 clear input signal change
!
1580 iports
= GET_INPUT_SIGNALS(ch
);
1581 delta
= iports
^ ch
->ch_iports
;
1582 ch
->ch_iports
= iports
;
1585 * Process normal status changes
1587 if (ISSET(delta
, ch
->ch_i_mask
)) {
1588 SET(ch
->ch_iports_delta
, delta
);
1591 * Stop output immediately if we lose the output
1592 * flow control signal or carrier detect.
1594 if (ISSET(~iports
, ch
->ch_i_mask
)) {
1599 sbscn_status(ch
, "sbscn_intr ");
1603 ch
->ch_st_check
= 1;
1605 } while ((isr
= (READ_REG(ch
->ch_isr_base
) & ch
->ch_imr
)) != 0);
1608 * Done handling any receive interrupts and status changes, and
1609 * clearing the tx-ready interrupt if it was set. See if data can
1610 * be transmitted as well. Schedule tx done event if no data left
1611 * and tty was marked busy.
1613 sr
= READ_REG(ch
->ch_base
+ 0x20);
1614 if (ISSET(sr
, 0x4)) {
1617 * If we've delayed a parameter change, do it now, and restart
1620 if (ch
->ch_heldchange
) {
1621 sbscn_loadchannelregs(ch
);
1622 ch
->ch_heldchange
= 0;
1623 ch
->ch_tbc
= ch
->ch_heldtbc
;
1627 /* Output the next chunk of the contiguous buffer, if any. */
1628 if (ch
->ch_tbc
> 0) {
1633 while (ch
->ch_tbc
&&
1634 READ_REG(ch
->ch_base
+ 0x20) & 0x04) {
1638 WRITE_REG(ch
->ch_base
+ 0x70, c
);
1641 SET(ch
->ch_imr
, 0x01);
1642 WRITE_REG(ch
->ch_imr_base
, ch
->ch_imr
);
1646 * transmit completion interrupts already disabled,
1647 * mark the channel tx state as done.
1649 if (ch
->ch_tx_busy
) {
1656 /* Wake up the poller. */
1657 softint_schedule(ch
->ch_si
);
1659 #if NRND > 0 && defined(RND_SBSCN)
1660 rnd_add_uint32(&ch
->ch_rnd_source
, isr
| sr
);
1665 * The following functions are polled getc and putc routines, shared
1666 * by the console and kgdb glue.
1670 sbscn_common_getc(u_long addr
, int chan
)
1673 u_long base
= MIPS_PHYS_TO_KSEG1(addr
+ (chan
* 0x100));
1676 /* block until a character becomes available */
1677 while ((READ_REG(base
+ 0x20) & 0x01) == 0)
1680 c
= READ_REG(base
+ 0x60) & 0xff;
1686 sbscn_common_putc(u_long addr
, int chan
, int c
)
1690 u_long base
= MIPS_PHYS_TO_KSEG1(addr
+ (chan
* 0x100));
1692 /* wait for any pending transmission to finish */
1694 while ((READ_REG(base
+ 0x20) & 0x08) == 0 && --timo
)
1697 WRITE_REG(base
+ 0x70, c
);
1699 /* wait for this transmission to complete */
1701 while ((READ_REG(base
+ 0x20) & 0x08) == 0 && --timo
)
1708 * Initialize UART for use as console or KGDB line.
1711 sbscn_init(u_long addr
, int chan
, int rate
, tcflag_t cflag
)
1714 u_long chanregbase
= MIPS_PHYS_TO_KSEG1(addr
+ (chan
* 0x100));
1715 u_long imaskreg
= MIPS_PHYS_TO_KSEG1(addr
+ 0x230 + (chan
* 0x20));
1716 u_char mode1
, mode2
;
1720 WRITE_REG(imaskreg
, 0); /* disable channel intrs */
1722 /* XXX should we really do the following? how about only if enabled? */
1723 /* wait for any pending transmission to finish */
1725 while ((READ_REG(chanregbase
+ 0x20) & 0x08) == 0 && --timo
)
1728 /* XXX: wait a little. THIS SHOULD NOT BE NECESSARY!!! (?) */
1733 WRITE_REG(chanregbase
+ 0x50, 2 << 4); /* reset receiver */
1734 WRITE_REG(chanregbase
+ 0x50, 3 << 4); /* reset transmitter */
1736 /* set up the line for use */
1737 (void)cflag2modes(cflag
, &mode1
, &mode2
);
1738 (void)sbscn_speed(rate
, &brc
);
1739 WRITE_REG(chanregbase
+ 0x00, mode1
);
1740 WRITE_REG(chanregbase
+ 0x10, mode2
);
1741 WRITE_REG(chanregbase
+ 0x30, brc
);
1743 /* enable transmit and receive */
1744 #define M_DUART_RX_EN 0x01
1745 #define M_DUART_TX_EN 0x04
1746 WRITE_REG(chanregbase
+ 0x50,M_DUART_RX_EN
| M_DUART_TX_EN
);
1749 /* XXX: wait a little. THIS SHOULD NOT BE NECESSARY!!! (?) */
1755 bus_space_handle_t ioh
;
1757 if (bus_space_map(iot
, iobase
, COM_NPORTS
, 0, &ioh
))
1758 return (ENOMEM
); /* ??? */
1760 bus_space_write_1(iot
, ioh
, com_lcr
, LCR_EERS
);
1761 bus_space_write_1(iot
, ioh
, com_efr
, 0);
1762 bus_space_write_1(iot
, ioh
, com_lcr
, LCR_DLAB
);
1763 rate
= comspeed(rate
, frequency
);
1764 bus_space_write_1(iot
, ioh
, com_dlbl
, rate
);
1765 bus_space_write_1(iot
, ioh
, com_dlbh
, rate
>> 8);
1766 bus_space_write_1(iot
, ioh
, com_lcr
, cflag2lcr(cflag
));
1767 bus_space_write_1(iot
, ioh
, com_mcr
, MCR_DTR
| MCR_RTS
);
1768 bus_space_write_1(iot
, ioh
, com_fifo
,
1769 FIFO_ENABLE
| FIFO_RCV_RST
| FIFO_XMT_RST
| FIFO_TRIGGER_1
);
1770 bus_space_write_1(iot
, ioh
, com_ier
, 0);
1780 * Following are all routines needed for sbscn to act as console
1783 sbscn_cnattach(u_long addr
, int chan
, int rate
, tcflag_t cflag
)
1786 static struct consdev sbscn_cons
= {
1787 NULL
, NULL
, sbscn_cngetc
, sbscn_cnputc
, sbscn_cnpollc
, NULL
,
1788 NULL
, NULL
, NODEV
, CN_NORMAL
1791 res
= sbscn_init(addr
, chan
, rate
, cflag
);
1795 cn_tab
= &sbscn_cons
;
1797 sbscn_cons_present
= 1;
1798 sbscn_cons_addr
= addr
;
1799 sbscn_cons_chan
= chan
;
1800 sbscn_cons_rate
= rate
;
1801 sbscn_cons_cflag
= cflag
;
1807 sbscn_cngetc(dev_t dev
)
1810 return (sbscn_common_getc(sbscn_cons_addr
, sbscn_cons_chan
));
1814 * Console kernel output character routine.
1817 sbscn_cnputc(dev_t dev
, int c
)
1820 sbscn_common_putc(sbscn_cons_addr
, sbscn_cons_chan
, c
);
1824 sbscn_cnpollc(dev_t dev
, int on
)
1831 sbscn_kgdb_attach(u_long addr
, int chan
, int rate
, tcflag_t cflag
)
1835 if (!sbscn_cons_present
&&
1836 sbscn_cons_addr
== addr
&& sbscn_cons_chan
== chan
)
1837 return (EBUSY
); /* cannot share with console */
1839 res
= sbscn_init(addr
, chan
, rate
, cflag
);
1843 kgdb_attach(sbscn_kgdb_getc
, sbscn_kgdb_putc
, NULL
);
1844 kgdb_dev
= 123; /* unneeded, only to satisfy some tests */
1846 sbscn_kgdb_present
= 1;
1847 sbscn_kgdb_addr
= addr
;
1848 sbscn_kgdb_chan
= chan
;
1855 sbscn_kgdb_getc(void *arg
)
1858 return (sbscn_common_getc(sbscn_kgdb_addr
, sbscn_kgdb_chan
));
1863 sbscn_kgdb_putc(void *arg
, int c
)
1866 sbscn_common_getc(sbscn_kgdb_addr
, sbscn_kgdb_chan
, c
);
1871 * helper function to identify the sbscn channels used by
1872 * console or KGDB (and not yet autoconf attached)
1875 sbscn_is_console(u_long addr
, int chan
)
1878 if (sbscn_cons_present
&& !sbscn_cons_attached
&&
1879 sbscn_cons_addr
== addr
&& sbscn_cons_chan
== chan
)
1882 if (sbscn_kgdb_present
&& !sbscn_kgdb_attached
&&
1883 sbscn_kgdb_addr
== addr
&& sbscn_kgdb_chan
== chan
)