1 /* $NetBSD: sab.c,v 1.42 2008/06/11 18:52:32 cegger Exp $ */
2 /* $OpenBSD: sab.c,v 1.7 2002/04/08 17:49:42 jason Exp $ */
5 * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Jason L. Wright
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
34 * Effort sponsored in part by the Defense Advanced Research Projects
35 * Agency (DARPA) and Air Force Research Laboratory, Air Force
36 * Materiel Command, USAF, under agreement number F30602-01-2-0537.
41 * SAB82532 Dual UART driver
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: sab.c,v 1.42 2008/06/11 18:52:32 cegger Exp $");
48 #include <sys/types.h>
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #include <sys/device.h>
54 #include <sys/ioctl.h>
55 #include <sys/kernel.h>
58 #include <sys/syslog.h>
59 #include <sys/kauth.h>
63 #include <machine/autoconf.h>
64 #include <machine/openfirm.h>
68 #include <dev/ebus/ebusreg.h>
69 #include <dev/ebus/ebusvar.h>
70 #include <sparc64/dev/sab82532reg.h>
74 #define SABUNIT(x) (minor(x) & 0x7ffff)
75 #define SABDIALOUT(x) (minor(x) & 0x80000)
77 #define SABTTY_RBUF_SIZE 1024 /* must be divisible by 2 */
81 struct intrhand
* sc_ih
;
82 bus_space_tag_t sc_bt
;
83 bus_space_handle_t sc_bh
;
84 struct sabtty_softc
* sc_child
[SAB_NCHAN
];
90 struct sabtty_attach_args
{
96 struct sab_softc
* sc_parent
;
97 bus_space_tag_t sc_bt
;
98 bus_space_handle_t sc_bh
;
101 uint8_t sc_pvr_dtr
, sc_pvr_dsr
;
102 uint8_t sc_imr0
, sc_imr1
;
107 #define SABTTYF_STOP 0x01
108 #define SABTTYF_DONE 0x02
109 #define SABTTYF_RINGOVERFLOW 0x04
110 #define SABTTYF_CDCHG 0x08
111 #define SABTTYF_CONS_IN 0x10
112 #define SABTTYF_CONS_OUT 0x20
113 #define SABTTYF_TXDRAIN 0x40
114 #define SABTTYF_DONTDDB 0x80
115 uint8_t sc_rbuf
[SABTTY_RBUF_SIZE
];
116 uint8_t *sc_rend
, *sc_rput
, *sc_rget
;
117 uint8_t sc_polling
, sc_pollrfc
;
120 struct sabtty_softc
*sabtty_cons_input
;
121 struct sabtty_softc
*sabtty_cons_output
;
123 #define SAB_READ(sc,r) \
124 bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, (r))
125 #define SAB_WRITE(sc,r,v) \
126 bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, (r), (v))
127 #define SAB_WRITE_BLOCK(sc,r,p,c) \
128 bus_space_write_region_1((sc)->sc_bt, (sc)->sc_bh, (r), (p), (c))
130 int sab_match(struct device
*, struct cfdata
*, void *);
131 void sab_attach(struct device
*, struct device
*, void *);
132 int sab_print(void *, const char *);
133 int sab_intr(void *);
135 void sab_softintr(void *);
136 void sab_cnputc(dev_t
, int);
137 int sab_cngetc(dev_t
);
138 void sab_cnpollc(dev_t
, int);
140 int sabtty_match(struct device
*, struct cfdata
*, void *);
141 void sabtty_attach(struct device
*, struct device
*, void *);
142 void sabtty_start(struct tty
*);
143 int sabtty_param(struct tty
*, struct termios
*);
144 int sabtty_intr(struct sabtty_softc
*, int *);
145 void sabtty_softintr(struct sabtty_softc
*);
146 int sabtty_mdmctrl(struct sabtty_softc
*, int, int);
147 void sabtty_cec_wait(struct sabtty_softc
*);
148 void sabtty_tec_wait(struct sabtty_softc
*);
149 void sabtty_reset(struct sabtty_softc
*);
150 void sabtty_flush(struct sabtty_softc
*);
151 int sabtty_speed(int);
152 void sabtty_console_flags(struct sabtty_softc
*);
153 void sabtty_cnpollc(struct sabtty_softc
*, int);
154 void sabtty_shutdown(void *);
155 int sabttyparam(struct sabtty_softc
*, struct tty
*, struct termios
*);
158 int sab_kgdb_check(struct sabtty_softc
*);
159 void sab_kgdb_init(struct sabtty_softc
*);
162 void sabtty_cnputc(struct sabtty_softc
*, int);
163 int sabtty_cngetc(struct sabtty_softc
*);
165 CFATTACH_DECL(sab
, sizeof(struct sab_softc
),
166 sab_match
, sab_attach
, NULL
, NULL
);
168 extern struct cfdriver sab_cd
;
170 CFATTACH_DECL(sabtty
, sizeof(struct sabtty_softc
),
171 sabtty_match
, sabtty_attach
, NULL
, NULL
);
173 extern struct cfdriver sabtty_cd
;
175 dev_type_open(sabopen
);
176 dev_type_close(sabclose
);
177 dev_type_read(sabread
);
178 dev_type_write(sabwrite
);
179 dev_type_ioctl(sabioctl
);
180 dev_type_stop(sabstop
);
181 dev_type_tty(sabtty
);
182 dev_type_poll(sabpoll
);
184 static struct cnm_state sabtty_cnm_state
;
186 const struct cdevsw sabtty_cdevsw
= {
187 sabopen
, sabclose
, sabread
, sabwrite
, sabioctl
,
188 sabstop
, sabtty
, sabpoll
, nommap
, ttykqfilter
, D_TTY
196 struct sabtty_rate sabtty_baudtable
[] = {
224 sab_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
226 struct ebus_attach_args
*ea
= aux
;
229 if (strcmp(ea
->ea_name
, "se") == 0)
232 compat
= prom_getpropstring(ea
->ea_node
, "compatible");
233 if (compat
!= NULL
&& !strcmp(compat
, "sab82532"))
240 sab_attach(struct device
*parent
, struct device
*self
, void *aux
)
242 struct sab_softc
*sc
= (struct sab_softc
*)self
;
243 struct ebus_attach_args
*ea
= aux
;
246 int locs
[SABCF_NLOCS
];
248 sc
->sc_bt
= ea
->ea_bustag
;
249 sc
->sc_node
= ea
->ea_node
;
251 /* Use prom mapping, if available. */
253 sparc_promaddr_to_handle(sc
->sc_bt
, ea
->ea_vaddr
[0],
255 else if (bus_space_map(sc
->sc_bt
, EBUS_ADDR_FROM_REG(&ea
->ea_reg
[0]),
256 ea
->ea_reg
[0].size
, 0, &sc
->sc_bh
) != 0) {
257 printf(": can't map register space\n");
261 sc
->sc_ih
= bus_intr_establish(ea
->ea_bustag
, ea
->ea_intr
[0],
262 IPL_TTY
, sab_intr
, sc
);
263 if (sc
->sc_ih
== NULL
) {
264 printf(": can't map interrupt\n");
268 sc
->sc_softintr
= softint_establish(SOFTINT_SERIAL
, sab_softintr
, sc
);
269 if (sc
->sc_softintr
== NULL
) {
270 printf(": can't get soft intr\n");
274 aprint_normal(": rev ");
275 r
= SAB_READ(sc
, SAB_VSTR
) & SAB_VSTR_VMASK
;
284 aprint_normal("3.2");
287 aprint_normal("unknown(0x%x)", r
);
292 /* Let current output drain */
295 /* Set all pins, except DTR pins to be inputs */
296 SAB_WRITE(sc
, SAB_PCR
, ~(SAB_PVR_DTR_A
| SAB_PVR_DTR_B
));
297 /* Disable port interrupts */
298 SAB_WRITE(sc
, SAB_PIM
, 0xff);
299 SAB_WRITE(sc
, SAB_PVR
, SAB_PVR_DTR_A
| SAB_PVR_DTR_B
| SAB_PVR_MAGIC
);
300 SAB_WRITE(sc
, SAB_IPC
, SAB_IPC_ICPL
);
302 for (i
= 0; i
< SAB_NCHAN
; i
++) {
303 struct sabtty_attach_args stax
;
307 locs
[SABCF_CHANNEL
] = i
;
310 (struct sabtty_softc
*)config_found_sm_loc(self
,
311 "sab", locs
, &stax
, sab_print
, config_stdsubmatch
);
312 if (sc
->sc_child
[i
] != NULL
)
318 sab_print(void *args
, const char *name
)
320 struct sabtty_attach_args
*sa
= args
;
323 aprint_normal("sabtty at %s", name
);
324 aprint_normal(" port %u", sa
->sbt_portno
);
331 struct sab_softc
*sc
= vsc
;
332 int r
= 0, needsoft
= 0;
335 gis
= SAB_READ(sc
, SAB_GIS
);
338 if ((gis
& (SAB_GIS_ISA1
| SAB_GIS_ISA0
)) && sc
->sc_child
[0] &&
339 sc
->sc_child
[0]->sc_tty
)
340 r
|= sabtty_intr(sc
->sc_child
[0], &needsoft
);
343 if ((gis
& (SAB_GIS_ISB1
| SAB_GIS_ISB0
)) && sc
->sc_child
[1] &&
344 sc
->sc_child
[1]->sc_tty
)
345 r
|= sabtty_intr(sc
->sc_child
[1], &needsoft
);
348 softint_schedule(sc
->sc_softintr
);
354 sab_softintr(void *vsc
)
356 struct sab_softc
*sc
= vsc
;
358 if (sc
->sc_child
[0] && sc
->sc_child
[0]->sc_tty
)
359 sabtty_softintr(sc
->sc_child
[0]);
360 if (sc
->sc_child
[1] && sc
->sc_child
[1]->sc_tty
)
361 sabtty_softintr(sc
->sc_child
[1]);
365 sabtty_match(struct device
*parent
, struct cfdata
*match
, void *aux
)
372 sabtty_attach(struct device
*parent
, struct device
*self
, void *aux
)
374 struct sabtty_softc
*sc
= (struct sabtty_softc
*)self
;
375 struct sabtty_attach_args
*sa
= aux
;
382 is_kgdb
= sab_kgdb_check(sc
);
386 sc
->sc_tty
= ttymalloc();
387 if (sc
->sc_tty
== NULL
) {
388 aprint_normal(": failed to allocate tty\n");
391 tty_attach(sc
->sc_tty
);
392 sc
->sc_tty
->t_oproc
= sabtty_start
;
393 sc
->sc_tty
->t_param
= sabtty_param
;
396 sc
->sc_parent
= (struct sab_softc
*)parent
;
397 sc
->sc_bt
= sc
->sc_parent
->sc_bt
;
398 sc
->sc_portno
= sa
->sbt_portno
;
399 sc
->sc_rend
= sc
->sc_rbuf
+ SABTTY_RBUF_SIZE
;
401 switch (sa
->sbt_portno
) {
403 sc
->sc_pvr_dtr
= SAB_PVR_DTR_A
;
404 sc
->sc_pvr_dsr
= SAB_PVR_DSR_A
;
405 r
= bus_space_subregion(sc
->sc_bt
, sc
->sc_parent
->sc_bh
,
406 SAB_CHAN_A
, SAB_CHANLEN
, &sc
->sc_bh
);
409 sc
->sc_pvr_dtr
= SAB_PVR_DTR_B
;
410 sc
->sc_pvr_dsr
= SAB_PVR_DSR_B
;
411 r
= bus_space_subregion(sc
->sc_bt
, sc
->sc_parent
->sc_bh
,
412 SAB_CHAN_B
, SAB_CHANLEN
, &sc
->sc_bh
);
415 aprint_normal(": invalid channel: %u\n", sa
->sbt_portno
);
419 aprint_normal(": failed to allocate register subregion\n");
423 sabtty_console_flags(sc
);
425 if (sc
->sc_flags
& (SABTTYF_CONS_IN
| SABTTYF_CONS_OUT
)) {
429 /* Let residual prom output drain */
432 switch (sc
->sc_flags
& (SABTTYF_CONS_IN
| SABTTYF_CONS_OUT
)) {
433 case SABTTYF_CONS_IN
:
436 case SABTTYF_CONS_OUT
:
439 case SABTTYF_CONS_IN
|SABTTYF_CONS_OUT
:
446 node
= sc
->sc_parent
->sc_node
;
447 /* Are we connected to an E250 RSC? */
448 if (sc
->sc_portno
== prom_getpropint(node
, "ssp-console", -1) ||
449 sc
->sc_portno
== prom_getpropint(node
, "ssp-control", -1))
453 t
.c_cflag
= CREAD
| CS8
| HUPCL
;
454 sc
->sc_tty
->t_ospeed
= 0;
455 sabttyparam(sc
, sc
->sc_tty
, &t
);
457 if (sc
->sc_flags
& SABTTYF_CONS_IN
) {
458 sabtty_cons_input
= sc
;
459 cn_tab
->cn_pollc
= sab_cnpollc
;
460 cn_tab
->cn_getc
= sab_cngetc
;
461 maj
= cdevsw_lookup_major(&sabtty_cdevsw
);
462 cn_tab
->cn_dev
= makedev(maj
, device_unit(self
));
463 shutdownhook_establish(sabtty_shutdown
, sc
);
464 cn_init_magic(&sabtty_cnm_state
);
465 cn_set_magic("\047\001"); /* default magic is BREAK */
468 if (sc
->sc_flags
& SABTTYF_CONS_OUT
) {
470 sabtty_cons_output
= sc
;
471 cn_tab
->cn_putc
= sab_cnputc
;
472 maj
= cdevsw_lookup_major(&sabtty_cdevsw
);
473 cn_tab
->cn_dev
= makedev(maj
, device_unit(self
));
475 aprint_normal(": console %s", acc
);
477 /* Not a console... */
483 aprint_normal(": kgdb");
492 sabtty_intr(struct sabtty_softc
*sc
, int *needsoftp
)
495 int i
, len
= 0, needsoft
= 0, r
= 0, clearfifo
= 0;
497 isr0
= SAB_READ(sc
, SAB_ISR0
);
498 isr1
= SAB_READ(sc
, SAB_ISR1
);
503 if (isr0
& SAB_ISR0_RPF
) {
507 if (isr0
& SAB_ISR0_TCD
) {
508 len
= (32 - 1) & SAB_READ(sc
, SAB_RBCL
);
511 if (isr0
& SAB_ISR0_TIME
) {
513 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RFRD
);
515 if (isr0
& SAB_ISR0_RFO
) {
516 sc
->sc_flags
|= SABTTYF_RINGOVERFLOW
;
523 for (i
= 0; i
< len
; i
++) {
524 b
= SAB_READ(sc
, SAB_RFIFO
);
525 if (i
% 2 == 0) /* skip status byte */
526 cn_check_magic(sc
->sc_tty
->t_dev
,
527 b
, sabtty_cnm_state
);
529 if (ptr
== sc
->sc_rend
)
531 if (ptr
== sc
->sc_rget
) {
532 if (ptr
== sc
->sc_rbuf
)
535 sc
->sc_flags
|= SABTTYF_RINGOVERFLOW
;
544 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RMC
);
547 if (isr0
& SAB_ISR0_CDSC
) {
548 sc
->sc_flags
|= SABTTYF_CDCHG
;
552 if (isr1
& SAB_ISR1_BRKT
)
553 cn_check_magic(sc
->sc_tty
->t_dev
,
554 CNC_BREAK
, sabtty_cnm_state
);
556 if (isr1
& (SAB_ISR1_XPR
| SAB_ISR1_ALLS
)) {
557 if ((SAB_READ(sc
, SAB_STAR
) & SAB_STAR_XFW
) &&
558 (sc
->sc_flags
& SABTTYF_STOP
) == 0) {
565 SAB_WRITE_BLOCK(sc
, SAB_XFIFO
, sc
->sc_txp
, len
);
570 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_XF
);
573 * Prevent the false end of xmit from
574 * confusing things below.
576 isr1
&= ~SAB_ISR1_ALLS
;
580 if ((sc
->sc_txc
== 0) || (sc
->sc_flags
& SABTTYF_STOP
)) {
581 if ((sc
->sc_imr1
& SAB_IMR1_XPR
) == 0) {
582 sc
->sc_imr1
|= SAB_IMR1_XPR
;
583 sc
->sc_imr1
&= ~SAB_IMR1_ALLS
;
584 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
589 if ((isr1
& SAB_ISR1_ALLS
) && ((sc
->sc_txc
== 0) ||
590 (sc
->sc_flags
& SABTTYF_STOP
))) {
591 if (sc
->sc_flags
& SABTTYF_TXDRAIN
)
593 sc
->sc_flags
&= ~SABTTYF_STOP
;
594 sc
->sc_flags
|= SABTTYF_DONE
;
595 sc
->sc_imr1
|= SAB_IMR1_ALLS
;
596 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
601 *needsoftp
= needsoft
;
606 sabtty_softintr(struct sabtty_softc
*sc
)
608 struct tty
*tp
= sc
->sc_tty
;
615 if ((tp
->t_state
& TS_ISOPEN
) == 0)
618 while (sc
->sc_rget
!= sc
->sc_rput
) {
622 data
= sc
->sc_rget
[0];
623 stat
= sc
->sc_rget
[1];
625 if (stat
& SAB_RSTAT_PE
)
627 if (stat
& SAB_RSTAT_FE
)
629 if (sc
->sc_rget
== sc
->sc_rend
)
630 sc
->sc_rget
= sc
->sc_rbuf
;
632 (*tp
->t_linesw
->l_rint
)(data
, tp
);
636 flags
= sc
->sc_flags
;
637 sc
->sc_flags
&= ~(SABTTYF_DONE
|SABTTYF_CDCHG
|SABTTYF_RINGOVERFLOW
);
640 if (flags
& SABTTYF_CDCHG
) {
642 r
= SAB_READ(sc
, SAB_VSTR
) & SAB_VSTR_CD
;
645 (*tp
->t_linesw
->l_modem
)(tp
, r
);
648 if (flags
& SABTTYF_RINGOVERFLOW
)
649 log(LOG_WARNING
, "%s: ring overflow\n",
650 device_xname(&sc
->sc_dv
));
652 if (flags
& SABTTYF_DONE
) {
653 ndflush(&tp
->t_outq
, sc
->sc_txp
- tp
->t_outq
.c_cf
);
654 tp
->t_state
&= ~TS_BUSY
;
655 (*tp
->t_linesw
->l_start
)(tp
);
660 sabopen(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
662 struct sabtty_softc
*sc
;
667 sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
675 if (kauth_authorize_device_tty(l
->l_cred
, KAUTH_DEVICE_TTY_OPEN
, tp
))
678 mutex_spin_enter(&tty_lock
);
679 if ((tp
->t_state
& TS_ISOPEN
) == 0) {
681 tp
->t_iflag
= TTYDEF_IFLAG
;
682 tp
->t_oflag
= TTYDEF_OFLAG
;
683 tp
->t_cflag
= TTYDEF_CFLAG
;
684 if (sc
->sc_openflags
& TIOCFLAG_CLOCAL
)
685 tp
->t_cflag
|= CLOCAL
;
686 if (sc
->sc_openflags
& TIOCFLAG_CRTSCTS
)
687 tp
->t_cflag
|= CRTSCTS
;
688 if (sc
->sc_openflags
& TIOCFLAG_MDMBUF
)
689 tp
->t_cflag
|= MDMBUF
;
690 tp
->t_lflag
= TTYDEF_LFLAG
;
691 tp
->t_ispeed
= tp
->t_ospeed
= TTYDEF_SPEED
;
693 sc
->sc_rput
= sc
->sc_rget
= sc
->sc_rbuf
;
699 sabtty_param(tp
, &tp
->t_termios
);
700 sc
->sc_imr0
= SAB_IMR0_PERR
| SAB_IMR0_FERR
| SAB_IMR0_PLLA
;
701 SAB_WRITE(sc
, SAB_IMR0
, sc
->sc_imr0
);
702 sc
->sc_imr1
= SAB_IMR1_BRK
| SAB_IMR1_ALLS
| SAB_IMR1_XDU
|
703 SAB_IMR1_TIN
| SAB_IMR1_CSC
| SAB_IMR1_XMR
| SAB_IMR1_XPR
;
704 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
705 SAB_WRITE(sc
, SAB_CCR0
, SAB_READ(sc
, SAB_CCR0
) | SAB_CCR0_PU
);
707 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_XRES
);
709 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RRES
);
715 if ((sc
->sc_openflags
& TIOCFLAG_SOFTCAR
) ||
716 (SAB_READ(sc
, SAB_VSTR
) & SAB_VSTR_CD
))
717 tp
->t_state
|= TS_CARR_ON
;
719 tp
->t_state
&= ~TS_CARR_ON
;
722 if ((flags
& O_NONBLOCK
) == 0) {
723 while ((tp
->t_cflag
& CLOCAL
) == 0 &&
724 (tp
->t_state
& TS_CARR_ON
) == 0) {
727 error
= ttysleep(tp
, &tp
->t_rawcv
, true, 0);
729 mutex_spin_exit(&tty_lock
);
735 mutex_spin_exit(&tty_lock
);
737 s
= (*tp
->t_linesw
->l_open
)(dev
, tp
);
739 mutex_spin_enter(&tty_lock
);
740 if (tp
->t_state
& TS_ISOPEN
) {
741 mutex_spin_exit(&tty_lock
);
744 if (tp
->t_cflag
& HUPCL
) {
745 sabtty_mdmctrl(sc
, 0, DMSET
);
746 cv_wait(&lbolt
, &tty_lock
);
749 if ((sc
->sc_flags
& (SABTTYF_CONS_IN
| SABTTYF_CONS_OUT
)) == 0) {
750 /* Flush and power down if we're not the console */
754 mutex_spin_exit(&tty_lock
);
760 sabclose(dev_t dev
, int flags
, int mode
, struct lwp
*l
)
762 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
763 struct sab_softc
*bc
= sc
->sc_parent
;
764 struct tty
*tp
= sc
->sc_tty
;
767 (*tp
->t_linesw
->l_close
)(tp
, flags
);
771 if ((tp
->t_state
& TS_ISOPEN
) == 0) {
772 /* Wait for output drain */
773 sc
->sc_imr1
&= ~SAB_IMR1_ALLS
;
774 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
775 sc
->sc_flags
|= SABTTYF_TXDRAIN
;
776 (void)tsleep(sc
, TTIPRI
, ttclos
, 5 * hz
);
777 sc
->sc_imr1
|= SAB_IMR1_ALLS
;
778 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
779 sc
->sc_flags
&= ~SABTTYF_TXDRAIN
;
781 if (tp
->t_cflag
& HUPCL
) {
782 sabtty_mdmctrl(sc
, 0, DMSET
);
783 (void)tsleep(bc
, TTIPRI
, ttclos
, hz
);
786 if ((sc
->sc_flags
& (SABTTYF_CONS_IN
| SABTTYF_CONS_OUT
)) == 0) {
787 /* Flush and power down if we're not the console */
800 sabread(dev_t dev
, struct uio
*uio
, int flags
)
802 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
803 struct tty
*tp
= sc
->sc_tty
;
805 return ((*tp
->t_linesw
->l_read
)(tp
, uio
, flags
));
809 sabwrite(dev_t dev
, struct uio
*uio
, int flags
)
811 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
812 struct tty
*tp
= sc
->sc_tty
;
814 return ((*tp
->t_linesw
->l_write
)(tp
, uio
, flags
));
818 sabioctl(dev_t dev
, u_long cmd
, void *data
, int flags
, struct lwp
*l
)
820 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
821 struct tty
*tp
= sc
->sc_tty
;
824 error
= (*tp
->t_linesw
->l_ioctl
)(tp
, cmd
, data
, flags
, l
);
828 error
= ttioctl(tp
, cmd
, data
, flags
, l
);
836 SAB_WRITE(sc
, SAB_DAFO
,
837 SAB_READ(sc
, SAB_DAFO
) | SAB_DAFO_XBRK
);
840 SAB_WRITE(sc
, SAB_DAFO
,
841 SAB_READ(sc
, SAB_DAFO
) & ~SAB_DAFO_XBRK
);
844 sabtty_mdmctrl(sc
, TIOCM_DTR
, DMBIS
);
847 sabtty_mdmctrl(sc
, TIOCM_DTR
, DMBIC
);
850 sabtty_mdmctrl(sc
, *((int *)data
), DMBIS
);
853 sabtty_mdmctrl(sc
, *((int *)data
), DMBIC
);
856 *((int *)data
) = sabtty_mdmctrl(sc
, 0, DMGET
);
859 sabtty_mdmctrl(sc
, *((int *)data
), DMSET
);
862 *((int *)data
) = sc
->sc_openflags
;
865 if (kauth_authorize_device_tty(l
->l_cred
,
866 KAUTH_DEVICE_TTY_PRIVSET
, tp
))
869 sc
->sc_openflags
= *((int *)data
) &
870 (TIOCFLAG_SOFTCAR
| TIOCFLAG_CLOCAL
|
871 TIOCFLAG_CRTSCTS
| TIOCFLAG_MDMBUF
);
883 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
889 sabstop(struct tty
*tp
, int flag
)
891 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(tp
->t_dev
));
895 if (tp
->t_state
& TS_BUSY
) {
896 if ((tp
->t_state
& TS_TTSTOP
) == 0)
897 tp
->t_state
|= TS_FLUSH
;
898 sc
->sc_flags
|= SABTTYF_STOP
;
899 sc
->sc_imr1
&= ~SAB_IMR1_ALLS
;
900 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
906 sabpoll(dev_t dev
, int events
, struct lwp
*l
)
908 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(dev
));
909 struct tty
*tp
= sc
->sc_tty
;
911 return ((*tp
->t_linesw
->l_poll
)(tp
, events
, l
));
915 sabtty_mdmctrl(struct sabtty_softc
*sc
, int bits
, int how
)
924 if (SAB_READ(sc
, SAB_STAR
) & SAB_STAR_CTS
)
926 if ((SAB_READ(sc
, SAB_VSTR
) & SAB_VSTR_CD
) == 0)
929 r
= SAB_READ(sc
, SAB_PVR
);
930 if ((r
& sc
->sc_pvr_dtr
) == 0)
932 if ((r
& sc
->sc_pvr_dsr
) == 0)
935 r
= SAB_READ(sc
, SAB_MODE
);
936 if ((r
& (SAB_MODE_RTS
|SAB_MODE_FRTS
)) == SAB_MODE_RTS
)
940 r
= SAB_READ(sc
, SAB_MODE
);
941 if (bits
& TIOCM_RTS
) {
945 r
|= SAB_MODE_FRTS
| SAB_MODE_RTS
;
946 SAB_WRITE(sc
, SAB_MODE
, r
);
948 r
= SAB_READ(sc
, SAB_PVR
);
949 if (bits
& TIOCM_DTR
)
950 r
&= ~sc
->sc_pvr_dtr
;
953 SAB_WRITE(sc
, SAB_PVR
, r
);
956 if (bits
& TIOCM_RTS
) {
957 r
= SAB_READ(sc
, SAB_MODE
);
960 SAB_WRITE(sc
, SAB_MODE
, r
);
962 if (bits
& TIOCM_DTR
) {
963 r
= SAB_READ(sc
, SAB_PVR
);
964 r
&= ~sc
->sc_pvr_dtr
;
965 SAB_WRITE(sc
, SAB_PVR
, r
);
969 if (bits
& TIOCM_RTS
) {
970 r
= SAB_READ(sc
, SAB_MODE
);
971 r
|= SAB_MODE_FRTS
| SAB_MODE_RTS
;
972 SAB_WRITE(sc
, SAB_MODE
, r
);
974 if (bits
& TIOCM_DTR
) {
975 r
= SAB_READ(sc
, SAB_PVR
);
977 SAB_WRITE(sc
, SAB_PVR
, r
);
986 sabttyparam(struct sabtty_softc
*sc
, struct tty
*tp
, struct termios
*t
)
992 ospeed
= sabtty_speed(t
->c_ospeed
);
993 if (ospeed
< 0 || (t
->c_ispeed
&& t
->c_ispeed
!= t
->c_ospeed
))
998 /* hang up line if ospeed is zero, otherwise raise dtr */
999 sabtty_mdmctrl(sc
, TIOCM_DTR
,
1000 (t
->c_ospeed
== 0) ? DMBIC
: DMBIS
);
1002 dafo
= SAB_READ(sc
, SAB_DAFO
);
1006 if (sc
->sc_flags
& (SABTTYF_CONS_IN
| SABTTYF_CONS_OUT
)) {
1012 dafo
|= SAB_DAFO_STOP
;
1014 dafo
&= ~SAB_DAFO_STOP
;
1016 dafo
&= ~SAB_DAFO_CHL_CSIZE
;
1017 switch (cflag
& CSIZE
) {
1019 dafo
|= SAB_DAFO_CHL_CS5
;
1022 dafo
|= SAB_DAFO_CHL_CS6
;
1025 dafo
|= SAB_DAFO_CHL_CS7
;
1028 dafo
|= SAB_DAFO_CHL_CS8
;
1032 dafo
&= ~SAB_DAFO_PARMASK
;
1033 if (cflag
& PARENB
) {
1035 dafo
|= SAB_DAFO_PAR_ODD
;
1037 dafo
|= SAB_DAFO_PAR_EVEN
;
1039 dafo
|= SAB_DAFO_PAR_NONE
;
1040 SAB_WRITE(sc
, SAB_DAFO
, dafo
);
1043 SAB_WRITE(sc
, SAB_BGR
, ospeed
& 0xff);
1044 r
= SAB_READ(sc
, SAB_CCR2
);
1045 r
&= ~(SAB_CCR2_BR9
| SAB_CCR2_BR8
);
1046 r
|= (ospeed
>> 2) & (SAB_CCR2_BR9
| SAB_CCR2_BR8
);
1047 SAB_WRITE(sc
, SAB_CCR2
, r
);
1050 r
= SAB_READ(sc
, SAB_MODE
);
1052 if (cflag
& CRTSCTS
) {
1053 r
&= ~(SAB_MODE_RTS
| SAB_MODE_FCTS
);
1055 sc
->sc_imr1
&= ~SAB_IMR1_CSC
;
1057 r
|= SAB_MODE_RTS
| SAB_MODE_FCTS
;
1058 r
&= ~SAB_MODE_FRTS
;
1059 sc
->sc_imr1
|= SAB_IMR1_CSC
;
1061 SAB_WRITE(sc
, SAB_MODE
, r
);
1062 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
1064 tp
->t_cflag
= cflag
;
1071 sabtty_param(struct tty
*tp
, struct termios
*t
)
1073 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(tp
->t_dev
));
1075 return (sabttyparam(sc
, tp
, t
));
1079 sabtty_start(struct tty
*tp
)
1081 struct sabtty_softc
*sc
= device_lookup_private(&sabtty_cd
, SABUNIT(tp
->t_dev
));
1085 if ((tp
->t_state
& (TS_TTSTOP
| TS_TIMEOUT
| TS_BUSY
)) == 0) {
1087 sc
->sc_txc
= ndqb(&tp
->t_outq
, 0);
1088 sc
->sc_txp
= tp
->t_outq
.c_cf
;
1089 tp
->t_state
|= TS_BUSY
;
1090 sc
->sc_imr1
&= ~(SAB_ISR1_XPR
| SAB_ISR1_ALLS
);
1091 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
1098 sabtty_cec_wait(struct sabtty_softc
*sc
)
1103 if ((SAB_READ(sc
, SAB_STAR
) & SAB_STAR_CEC
) == 0)
1112 sabtty_tec_wait(struct sabtty_softc
*sc
)
1117 if ((SAB_READ(sc
, SAB_STAR
) & SAB_STAR_TEC
) == 0)
1126 sabtty_reset(struct sabtty_softc
*sc
)
1129 SAB_WRITE(sc
, SAB_CCR0
, 0);
1131 /* set basic configuration */
1132 SAB_WRITE(sc
, SAB_CCR0
,
1133 SAB_CCR0_MCE
| SAB_CCR0_SC_NRZ
| SAB_CCR0_SM_ASYNC
);
1134 SAB_WRITE(sc
, SAB_CCR1
, SAB_CCR1_ODS
| SAB_CCR1_BCR
| SAB_CCR1_CM_7
);
1135 SAB_WRITE(sc
, SAB_CCR2
, SAB_CCR2_BDF
| SAB_CCR2_SSEL
| SAB_CCR2_TOE
);
1136 SAB_WRITE(sc
, SAB_CCR3
, 0);
1137 SAB_WRITE(sc
, SAB_CCR4
, SAB_CCR4_MCK4
| SAB_CCR4_EBRG
| SAB_CCR4_ICD
);
1138 SAB_WRITE(sc
, SAB_MODE
, SAB_MODE_RTS
| SAB_MODE_FCTS
| SAB_MODE_RAC
);
1139 SAB_WRITE(sc
, SAB_RFC
,
1140 SAB_RFC_DPS
| SAB_RFC_RFDF
| SAB_RFC_RFTH_32CHAR
);
1142 /* clear interrupts */
1143 sc
->sc_imr0
= sc
->sc_imr1
= 0xff;
1144 SAB_WRITE(sc
, SAB_IMR0
, sc
->sc_imr0
);
1145 SAB_WRITE(sc
, SAB_IMR1
, sc
->sc_imr1
);
1146 (void)SAB_READ(sc
, SAB_ISR0
);
1147 (void)SAB_READ(sc
, SAB_ISR1
);
1151 sabtty_flush(struct sabtty_softc
*sc
)
1154 sabtty_cec_wait(sc
);
1155 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RRES
);
1158 sabtty_cec_wait(sc
);
1159 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_XRES
);
1163 sabtty_speed(int rate
)
1169 len
= sizeof(sabtty_baudtable
)/sizeof(sabtty_baudtable
[0]);
1170 for (i
= 0; i
< len
; i
++) {
1171 if (rate
== sabtty_baudtable
[i
].baud
) {
1172 r
= sabtty_baudtable
[i
].n
|
1173 (sabtty_baudtable
[i
].m
<< 6);
1181 sabtty_cnputc(struct sabtty_softc
*sc
, int c
)
1183 sabtty_tec_wait(sc
);
1184 SAB_WRITE(sc
, SAB_TIC
, c
);
1185 sabtty_tec_wait(sc
);
1189 sabtty_cngetc(struct sabtty_softc
*sc
)
1195 r
= SAB_READ(sc
, SAB_STAR
);
1196 } while ((r
& SAB_STAR_RFNE
) == 0);
1199 * Ok, at least one byte in RFIFO, ask for permission to access RFIFO
1200 * (I hate this chip... hate hate hate).
1202 sabtty_cec_wait(sc
);
1203 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RFRD
);
1205 /* Wait for RFIFO to come ready */
1207 r
= SAB_READ(sc
, SAB_ISR0
);
1208 } while ((r
& SAB_ISR0_TCD
) == 0);
1210 len
= SAB_READ(sc
, SAB_RBCL
) & (32 - 1);
1212 goto again
; /* Shouldn't happen... */
1214 r
= SAB_READ(sc
, SAB_RFIFO
);
1217 * Blow away everything left in the FIFO...
1219 sabtty_cec_wait(sc
);
1220 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RMC
);
1225 sabtty_cnpollc(struct sabtty_softc
*sc
, int on
)
1232 SAB_WRITE(sc
, SAB_IPC
, SAB_READ(sc
, SAB_IPC
) | SAB_IPC_VIS
);
1233 r
= sc
->sc_pollrfc
= SAB_READ(sc
, SAB_RFC
);
1234 r
&= ~(SAB_RFC_RFDF
);
1235 SAB_WRITE(sc
, SAB_RFC
, r
);
1236 sabtty_cec_wait(sc
);
1237 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RRES
);
1240 if (!sc
->sc_polling
)
1242 SAB_WRITE(sc
, SAB_IPC
, SAB_READ(sc
, SAB_IPC
) & ~SAB_IPC_VIS
);
1243 SAB_WRITE(sc
, SAB_RFC
, sc
->sc_pollrfc
);
1244 sabtty_cec_wait(sc
);
1245 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RRES
);
1251 sab_cnputc(dev_t dev
, int c
)
1253 struct sabtty_softc
*sc
= sabtty_cons_output
;
1257 sabtty_cnputc(sc
, c
);
1261 sab_cnpollc(dev_t dev
, int on
)
1263 struct sabtty_softc
*sc
= sabtty_cons_input
;
1265 sabtty_cnpollc(sc
, on
);
1269 sab_cngetc(dev_t dev
)
1271 struct sabtty_softc
*sc
= sabtty_cons_input
;
1275 return (sabtty_cngetc(sc
));
1279 sabtty_console_flags(struct sabtty_softc
*sc
)
1281 int node
, channel
, cookie
;
1284 node
= sc
->sc_parent
->sc_node
;
1285 channel
= sc
->sc_portno
;
1287 /* Default to channel 0 if there are no explicit prom args */
1290 if (node
== prom_instance_to_package(prom_stdin())) {
1291 if (prom_getoption("input-device", buf
, sizeof buf
) == 0 &&
1292 strcmp("ttyb", buf
) == 0)
1295 if (channel
== cookie
)
1296 sc
->sc_flags
|= SABTTYF_CONS_IN
;
1299 /* Default to same channel if there are no explicit prom args */
1301 if (node
== prom_instance_to_package(prom_stdout())) {
1302 if (prom_getoption("output-device", buf
, sizeof buf
) == 0 &&
1303 strcmp("ttyb", buf
) == 0)
1306 if (channel
== cookie
)
1307 sc
->sc_flags
|= SABTTYF_CONS_OUT
;
1312 sabtty_shutdown(void *vsc
)
1314 struct sabtty_softc
*sc
= vsc
;
1316 /* Have to put the chip back into single char mode */
1317 sc
->sc_flags
|= SABTTYF_DONTDDB
;
1318 SAB_WRITE(sc
, SAB_RFC
, SAB_READ(sc
, SAB_RFC
) & ~SAB_RFC_RFDF
);
1319 sabtty_cec_wait(sc
);
1320 SAB_WRITE(sc
, SAB_CMDR
, SAB_CMDR_RRES
);
1321 sabtty_cec_wait(sc
);
1326 sab_kgdb_getc(void *arg
)
1328 struct sabtty_softc
*sc
= arg
;
1330 return sabtty_cngetc(sc
);
1334 sab_kgdb_putc(void *arg
, int c
)
1336 struct sabtty_softc
*sc
= arg
;
1338 return sabtty_cnputc(sc
, c
);
1341 #ifndef KGDB_DEVRATE
1342 #define KGDB_DEVRATE 9600
1346 sab_kgdb_check(struct sabtty_softc
*sc
)
1348 return strcmp(device_xname(&sc
->sc_dv
), KGDB_DEVNAME
) == 0;
1352 sab_kgdb_init(struct sabtty_softc
*sc
)
1356 extern int kgdb_break_at_attach
;
1358 kgdb_attach(sab_kgdb_getc
, sab_kgdb_putc
, sc
);
1359 kgdb_dev
= 123; /* not used, but checked against NODEV */
1362 * Configure the port to speed/8n1
1364 dafo
= SAB_READ(sc
, SAB_DAFO
);
1365 dafo
&= ~(SAB_DAFO_STOP
|SAB_DAFO_CHL_CSIZE
|SAB_DAFO_PARMASK
);
1366 dafo
|= SAB_DAFO_CHL_CS8
|SAB_DAFO_PAR_NONE
;
1367 SAB_WRITE(sc
, SAB_DAFO
, dafo
);
1368 sp
= sabtty_speed(KGDB_DEVRATE
);
1369 SAB_WRITE(sc
, SAB_BGR
, sp
& 0xff);
1370 r
= SAB_READ(sc
, SAB_CCR2
);
1371 r
&= ~(SAB_CCR2_BR9
| SAB_CCR2_BR8
);
1372 r
|= (sp
>> 2) & (SAB_CCR2_BR9
| SAB_CCR2_BR8
);
1373 SAB_WRITE(sc
, SAB_CCR2
, r
);
1376 * If we are booting with -d, break into kgdb now
1378 if (kgdb_break_at_attach
)