Home | History | Annotate | Line # | Download | only in dev
scn.c revision 1.10
      1  1.10  riastrad /*	$NetBSD: scn.c,v 1.10 2022/10/26 23:59:14 riastradh Exp $ */
      2   1.1    rumble 
      3   1.1    rumble /*
      4   1.1    rumble  * Resurrected from the old pc532 port 1/18/2009.
      5   1.1    rumble  *
      6   1.1    rumble  * XXX- The locking in this is probably totally broken. I haven't attempted
      7   1.1    rumble  *      to get it right, but it seems to work okay anyhow.
      8   1.1    rumble  */
      9   1.1    rumble 
     10   1.1    rumble /*
     11   1.1    rumble  * Copyright (c) 1991, 1992, 1993
     12   1.1    rumble  *	The Regents of the University of California.  All rights reserved.
     13   1.1    rumble  *
     14   1.1    rumble  * Portions of this software were developed by the Computer Systems
     15   1.1    rumble  * Engineering group at Lawrence Berkeley Laboratory under DARPA
     16   1.1    rumble  * contract BG 91-66 and contributed to Berkeley.
     17   1.1    rumble  *
     18   1.1    rumble  * All advertising materials mentioning features or use of this software
     19   1.1    rumble  * must display the following acknowledgement:
     20   1.1    rumble  *	This product includes software developed by the University of
     21   1.1    rumble  *	California, Lawrence Berkeley Laboratory.
     22   1.1    rumble  *
     23   1.1    rumble  * Redistribution and use in source and binary forms, with or without
     24   1.1    rumble  * modification, are permitted provided that the following conditions
     25   1.1    rumble  * are met:
     26   1.1    rumble  * 1. Redistributions of source code must retain the above copyright
     27   1.1    rumble  *    notice, this list of conditions and the following disclaimer.
     28   1.1    rumble  * 2. Redistributions in binary form must reproduce the above copyright
     29   1.1    rumble  *    notice, this list of conditions and the following disclaimer in the
     30   1.1    rumble  *    documentation and/or other materials provided with the distribution.
     31   1.1    rumble  * 3. Neither the name of the University nor the names of its contributors
     32   1.1    rumble  *    may be used to endorse or promote products derived from this software
     33   1.1    rumble  *    without specific prior written permission.
     34   1.1    rumble  *
     35   1.1    rumble  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     36   1.1    rumble  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     37   1.1    rumble  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     38   1.1    rumble  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     39   1.1    rumble  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     40   1.1    rumble  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     41   1.1    rumble  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     42   1.1    rumble  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     43   1.1    rumble  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     44   1.1    rumble  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     45   1.1    rumble  * SUCH DAMAGE.
     46   1.1    rumble  *
     47   1.1    rumble  *	from: @(#)com.c	7.5 (Berkeley) 5/16/91
     48   1.1    rumble  */
     49   1.1    rumble 
     50   1.1    rumble /*
     51   1.1    rumble  * Copyright (c) 1996, 1997 Philip L. Budne.
     52   1.1    rumble  * Copyright (c) 1993 Philip A. Nelson.
     53   1.1    rumble  *
     54   1.1    rumble  * Portions of this software were developed by the Computer Systems
     55   1.1    rumble  * Engineering group at Lawrence Berkeley Laboratory under DARPA
     56   1.1    rumble  * contract BG 91-66 and contributed to Berkeley.
     57   1.1    rumble  *
     58   1.1    rumble  * All advertising materials mentioning features or use of this software
     59   1.1    rumble  * must display the following acknowledgement:
     60   1.1    rumble  *	This product includes software developed by the University of
     61   1.1    rumble  *	California, Lawrence Berkeley Laboratory.
     62   1.1    rumble  *
     63   1.1    rumble  * Redistribution and use in source and binary forms, with or without
     64   1.1    rumble  * modification, are permitted provided that the following conditions
     65   1.1    rumble  * are met:
     66   1.1    rumble  * 1. Redistributions of source code must retain the above copyright
     67   1.1    rumble  *    notice, this list of conditions and the following disclaimer.
     68   1.1    rumble  * 2. Redistributions in binary form must reproduce the above copyright
     69   1.1    rumble  *    notice, this list of conditions and the following disclaimer in the
     70   1.1    rumble  *    documentation and/or other materials provided with the distribution.
     71   1.1    rumble  * 3. All advertising materials mentioning features or use of this software
     72   1.1    rumble  *    must display the following acknowledgement:
     73   1.1    rumble  *	This product includes software developed by the University of
     74   1.1    rumble  *	California, Berkeley and its contributors.
     75   1.1    rumble  * 4. Neither the name of the University nor the names of its contributors
     76   1.1    rumble  *    may be used to endorse or promote products derived from this software
     77   1.1    rumble  *    without specific prior written permission.
     78   1.1    rumble  *
     79   1.1    rumble  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     80   1.1    rumble  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     81   1.1    rumble  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     82   1.1    rumble  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     83   1.1    rumble  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     84   1.1    rumble  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     85   1.1    rumble  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     86   1.1    rumble  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     87   1.1    rumble  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     88   1.1    rumble  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     89   1.1    rumble  * SUCH DAMAGE.
     90   1.1    rumble  *
     91   1.1    rumble  *	from: @(#)com.c	7.5 (Berkeley) 5/16/91
     92   1.1    rumble  */
     93   1.1    rumble 
     94   1.1    rumble #include <sys/cdefs.h>
     95  1.10  riastrad __KERNEL_RCSID(0, "$NetBSD: scn.c,v 1.10 2022/10/26 23:59:14 riastradh Exp $");
     96   1.1    rumble 
     97   1.1    rumble #include "opt_ddb.h"
     98   1.1    rumble #include "opt_kgdb.h"
     99   1.1    rumble #include "scn.h"
    100   1.1    rumble 
    101   1.1    rumble #include <sys/param.h>
    102   1.1    rumble #include <sys/systm.h>
    103   1.1    rumble #include <sys/ioctl.h>
    104   1.1    rumble #include <sys/select.h>
    105   1.1    rumble #include <sys/tty.h>
    106   1.1    rumble #include <sys/proc.h>
    107   1.1    rumble #include <sys/file.h>
    108   1.1    rumble #include <sys/uio.h>
    109   1.1    rumble #include <sys/kernel.h>
    110   1.1    rumble #include <sys/syslog.h>
    111   1.1    rumble #include <sys/types.h>
    112   1.1    rumble #include <sys/device.h>
    113   1.1    rumble #include <sys/malloc.h>
    114   1.1    rumble #include <sys/conf.h>
    115   1.1    rumble #include <sys/intr.h>
    116   1.1    rumble #ifdef KGDB
    117   1.1    rumble #include <sys/kgdb.h>
    118   1.1    rumble #endif
    119   1.1    rumble #include <sys/kauth.h>
    120   1.1    rumble 
    121   1.1    rumble #include <dev/cons.h>
    122   1.1    rumble 
    123   1.1    rumble #include <machine/autoconf.h>
    124   1.1    rumble #include <machine/machtype.h>
    125   1.1    rumble 
    126   1.1    rumble #include <sgimips/dev/scnreg.h>
    127   1.1    rumble #include <sgimips/dev/scnvar.h>
    128   1.1    rumble 
    129   1.1    rumble int     scn_match(device_t, struct cfdata *, void *);
    130   1.1    rumble void    scn_attach(device_t, device_t, void *);
    131   1.1    rumble int     scnparam(struct tty *, struct termios *);
    132   1.1    rumble void    scnstart(struct tty *);
    133   1.1    rumble int     scnhwiflow(struct tty *, int);
    134   1.1    rumble 
    135   1.1    rumble void	scncnprobe(struct consdev *);
    136   1.1    rumble void	scncninit(struct consdev *);
    137   1.1    rumble int     scncngetc(dev_t);
    138   1.1    rumble void    scncnputc(dev_t, int);
    139   1.1    rumble void	scncnpollc(dev_t, int);
    140   1.1    rumble int	scninit(dev_t, int);
    141   1.1    rumble void	scncnreinit(void *);
    142   1.1    rumble 
    143   1.4       chs CFATTACH_DECL_NEW(scn, sizeof(struct scn_softc),
    144   1.1    rumble     scn_match, scn_attach, NULL, NULL);
    145   1.1    rumble 
    146   1.1    rumble extern struct cfdriver scn_cd;
    147   1.1    rumble 
    148   1.1    rumble dev_type_open(scnopen);
    149   1.1    rumble dev_type_close(scnclose);
    150   1.1    rumble dev_type_read(scnread);
    151   1.1    rumble dev_type_write(scnwrite);
    152   1.1    rumble dev_type_ioctl(scnioctl);
    153   1.1    rumble dev_type_stop(scnstop);
    154   1.1    rumble dev_type_tty(scntty);
    155   1.1    rumble dev_type_poll(scnpoll);
    156   1.1    rumble 
    157   1.1    rumble const struct cdevsw scn_cdevsw = {
    158   1.5  dholland 	.d_open = scnopen,
    159   1.5  dholland 	.d_close = scnclose,
    160   1.5  dholland 	.d_read = scnread,
    161   1.5  dholland 	.d_write = scnwrite,
    162   1.5  dholland 	.d_ioctl = scnioctl,
    163   1.5  dholland 	.d_stop = scnstop,
    164   1.5  dholland 	.d_tty = scntty,
    165   1.5  dholland 	.d_poll = scnpoll,
    166   1.5  dholland 	.d_mmap = nommap,
    167   1.5  dholland 	.d_kqfilter = ttykqfilter,
    168   1.7  dholland 	.d_discard = nodiscard,
    169   1.5  dholland 	.d_flag = D_TTY
    170   1.1    rumble };
    171   1.1    rumble 
    172   1.1    rumble struct consdev scn_cn = {
    173   1.1    rumble 	scncnprobe,
    174   1.1    rumble 	scncninit,
    175   1.1    rumble 	scncngetc,
    176   1.1    rumble 	scncnputc,
    177   1.1    rumble 	scncnpollc,
    178   1.1    rumble 	NULL,
    179   1.1    rumble 	NULL,
    180   1.1    rumble 	NULL,
    181   1.1    rumble 	NODEV,
    182   1.1    rumble 	CN_NORMAL
    183   1.1    rumble };
    184   1.1    rumble 
    185   1.1    rumble #ifndef CONSOLE_SPEED
    186   1.1    rumble #define CONSOLE_SPEED TTYDEF_SPEED
    187   1.1    rumble #endif
    188   1.1    rumble 
    189   1.1    rumble #ifndef SCNDEF_CFLAG
    190   1.1    rumble #define SCNDEF_CFLAG TTYDEF_CFLAG
    191   1.1    rumble #endif
    192   1.1    rumble 
    193   1.1    rumble #ifdef CPU30MHZ
    194   1.1    rumble #define RECOVER()	__asm volatile("bispsrw 0x800" : : : "cc")
    195   1.1    rumble #else
    196   1.1    rumble #define RECOVER()
    197   1.1    rumble #endif
    198   1.1    rumble 
    199   1.1    rumble int     scndefaultrate = TTYDEF_SPEED;
    200   1.1    rumble int     scnconsrate = CONSOLE_SPEED;
    201   1.1    rumble 
    202   1.1    rumble static inline struct scn_softc *
    203   1.1    rumble SOFTC(int unit)
    204   1.1    rumble {
    205   1.1    rumble 	if (unit < 0 || unit >= scn_cd.cd_ndevs)
    206   1.1    rumble 		return (NULL);
    207   1.4       chs 	return device_private(scn_cd.cd_devs[unit]);
    208   1.1    rumble }
    209   1.1    rumble 
    210   1.1    rumble static int	scnintr(void *);
    211   1.1    rumble static void	scnrxintr(void *);
    212   1.1    rumble static int	scn_rxintr(struct scn_softc *);
    213   1.1    rumble static void	scnsoft(void *);
    214   1.1    rumble static void	scn_setchip(struct scn_softc *sc);
    215   1.1    rumble static int	scniter(int *, int, int*, int*, struct chan *, int);
    216   1.1    rumble static int	scn_config(int, int, int, int, u_char, u_char);
    217   1.1    rumble static void	scn_rxenable(struct scn_softc *);
    218   1.1    rumble static void	scn_rxdisable(struct scn_softc *);
    219   1.1    rumble static void	dcd_int(struct scn_softc *, struct tty *, u_char);
    220   1.1    rumble static void	scnoverrun(int, long *, const char *);
    221   1.1    rumble static u_char	opbits(struct scn_softc *, int);
    222   1.1    rumble 
    223   1.1    rumble static void *scnsir = NULL;		/* s/w intr cookie */
    224   1.1    rumble #define setsoftscn()	softint_schedule(scnsir)
    225   1.1    rumble 
    226   1.1    rumble #ifdef SCN_TIMING
    227   1.1    rumble /*
    228   1.1    rumble  * Keep timing info on latency of software interrupt used by
    229   1.1    rumble  * the ringbuf code to empty ring buffer.
    230   1.1    rumble  * "getinfo" program reads data from /dev/kmem.
    231   1.1    rumble  */
    232   1.1    rumble static struct timeval tstart;
    233   1.1    rumble #define NJITTER 100
    234   1.1    rumble int     scn_njitter = NJITTER;
    235   1.1    rumble int     scn_jitter[NJITTER];
    236   1.1    rumble #endif
    237   1.1    rumble 
    238   1.1    rumble #define SCN_CLOCK	3686400		/* input clock */
    239   1.1    rumble 
    240   1.1    rumble /* speed table groups ACR[7] */
    241   1.1    rumble #define GRP_A	0
    242   1.1    rumble #define GRP_B	ACR_BRG
    243   1.1    rumble 
    244   1.1    rumble /* combo of MR0[2:0] and ACR[7] */
    245   1.1    rumble #define MODE0A	MR0_MODE_0
    246   1.1    rumble #define MODE0B	(MR0_MODE_0|ACR_BRG)
    247   1.1    rumble #define MODE1A	MR0_MODE_1
    248   1.1    rumble #define MODE1B	(MR0_MODE_1|ACR_BRG)
    249   1.1    rumble #define MODE2A	MR0_MODE_2
    250   1.1    rumble #define MODE2B	(MR0_MODE_2|ACR_BRG)
    251   1.1    rumble 
    252   1.1    rumble #define ANYMODE	-1
    253   1.1    rumble #define DEFMODE(C92) MODE0A		/* use MODE4A if 26c92? */
    254   1.1    rumble 
    255   1.1    rumble /* speed code for Counter/Timer (all modes, groups) */
    256   1.1    rumble #define USE_CT 0xd
    257   1.1    rumble 
    258   1.1    rumble /*
    259   1.1    rumble  * Rate table, ordered by speed, then mode.
    260   1.1    rumble  * NOTE: ordering of modes must be done carefully!
    261   1.1    rumble  */
    262   1.1    rumble struct tabent {
    263   1.1    rumble 	int32_t speed;
    264   1.1    rumble 	int16_t code;
    265   1.1    rumble 	int16_t mode;
    266   1.1    rumble } table[] = {
    267   1.1    rumble 	{     50, 0x0, MODE0A },
    268   1.1    rumble 	{     75, 0x0, MODE0B },
    269   1.1    rumble 	{    110, 0x1, MODE0A },
    270   1.1    rumble 	{    110, 0x1, MODE0B },
    271   1.1    rumble 	{    110, 0x1, MODE1A },
    272   1.1    rumble 	{    110, 0x1, MODE1B },
    273   1.1    rumble 	{    134, 0x2, MODE0A },	/* 134.5 */
    274   1.1    rumble 	{    134, 0x2, MODE0B },	/* 134.5 */
    275   1.1    rumble 	{    134, 0x2, MODE1A },	/* 134.5 */
    276   1.1    rumble 	{    134, 0x2, MODE1B },	/* 134.5 */
    277   1.1    rumble 	{    150, 0x3, MODE0A },
    278   1.1    rumble 	{    150, 0x3, MODE0A },
    279   1.1    rumble 	{    200, 0x3, MODE0A },
    280   1.1    rumble 	{    300, 0x4, MODE0A },
    281   1.1    rumble 	{    300, 0x4, MODE0B },
    282   1.1    rumble 	{    300, 0x0, MODE1A },
    283   1.1    rumble 	{    450, 0x0, MODE1B },
    284   1.1    rumble 	{    600, 0x5, MODE0A },
    285   1.1    rumble 	{    600, 0x5, MODE0B },
    286   1.1    rumble 	{    880, 0x1, MODE2A },
    287   1.1    rumble 	{    880, 0x1, MODE2B },
    288   1.1    rumble 	{    900, 0x3, MODE1B },
    289   1.1    rumble 	{   1050, 0x7, MODE0A },
    290   1.1    rumble 	{   1050, 0x7, MODE1A },
    291   1.1    rumble 	{   1076, 0x2, MODE2A },
    292   1.1    rumble 	{   1076, 0x2, MODE2B },
    293   1.1    rumble 	{   1200, 0x6, MODE0A },
    294   1.1    rumble 	{   1200, 0x6, MODE0B },
    295   1.1    rumble 	{   1200, 0x3, MODE1A },
    296   1.1    rumble 	{   1800, 0xa, MODE0B },
    297   1.1    rumble 	{   1800, 0x4, MODE1A },
    298   1.1    rumble 	{   1800, 0x4, MODE1B },
    299   1.1    rumble 	{   2000, 0x7, MODE0B },
    300   1.1    rumble 	{   2000, 0x7, MODE1B },
    301   1.1    rumble 	{   2400, 0x8, MODE0A },
    302   1.1    rumble 	{   2400, 0x8, MODE0B },
    303   1.1    rumble 	{   3600, 0x5, MODE1A },
    304   1.1    rumble 	{   3600, 0x5, MODE1B },
    305   1.1    rumble 	{   4800, 0x9, MODE2A },
    306   1.1    rumble 	{   4800, 0x9, MODE2B },
    307   1.1    rumble 	{   4800, 0x9, MODE0A },
    308   1.1    rumble 	{   4800, 0x9, MODE0B },
    309   1.1    rumble 	{   7200, 0xa, MODE0A },
    310   1.1    rumble 	{   7200, 0x0, MODE2B },
    311   1.1    rumble 	{   7200, 0x6, MODE1A },
    312   1.1    rumble 	{   7200, 0x6, MODE1B },
    313   1.1    rumble 	{   9600, 0xb, MODE2A },
    314   1.1    rumble 	{   9600, 0xb, MODE2B },
    315   1.1    rumble 	{   9600, 0xb, MODE0A },
    316   1.1    rumble 	{   9600, 0xb, MODE0B },
    317   1.1    rumble 	{   9600, 0xd, MODE1A },	/* use C/T as entre' to mode1 */
    318   1.1    rumble 	{   9600, 0xd, MODE1B },	/* use C/T as entre' to mode1 */
    319   1.1    rumble 	{  14400, 0x3, MODE2B },
    320   1.1    rumble 	{  14400, 0x8, MODE1A },
    321   1.1    rumble 	{  14400, 0x8, MODE1B },
    322   1.1    rumble 	{  19200, 0x3, MODE2A },
    323   1.1    rumble 	{  19200, 0xc, MODE2B },
    324   1.1    rumble 	{  19200, 0xc, MODE0B },
    325   1.1    rumble 	{  19200, 0xd, MODE1A },	/* use C/T as entre' to mode1 */
    326   1.1    rumble 	{  19200, 0xd, MODE1B },	/* use C/T as entre' to mode1 */
    327   1.1    rumble 	{  28800, 0x4, MODE2A },
    328   1.1    rumble 	{  28800, 0x4, MODE2B },
    329   1.1    rumble 	{  28800, 0x9, MODE1A },
    330   1.1    rumble 	{  28800, 0x9, MODE1B },
    331   1.1    rumble 	{  38400, 0xc, MODE2A },
    332   1.1    rumble 	{  38400, 0xc, MODE0A },
    333   1.1    rumble 	{  57600, 0x5, MODE2A },
    334   1.1    rumble 	{  57600, 0x5, MODE2B },
    335   1.1    rumble 	{  57600, 0xb, MODE1A },
    336   1.1    rumble 	{  57600, 0xb, MODE1B },
    337   1.1    rumble 	{ 115200, 0x6, MODE2A },
    338   1.1    rumble 	{ 115200, 0x6, MODE2B },
    339   1.1    rumble 	{ 115200, 0xc, MODE1B },
    340   1.1    rumble 	{ 230400, 0xc, MODE1A }
    341   1.1    rumble };
    342   1.1    rumble #define TABENTRIES (sizeof(table)/sizeof(table[0]))
    343   1.1    rumble 
    344   1.1    rumble /*
    345   1.1    rumble  * boolean for speed codes which are identical in both A/B BRG groups
    346   1.1    rumble  * in all modes
    347   1.1    rumble  */
    348   1.1    rumble static u_char bothgroups[16] = {
    349   1.1    rumble 	0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1
    350   1.1    rumble };
    351   1.1    rumble 
    352   1.1    rumble /*
    353   1.1    rumble  * Manually constructed divisors table
    354   1.1    rumble  * for minimum error (from some of Dave Rand's code)
    355   1.1    rumble  */
    356   1.1    rumble const struct {
    357   1.1    rumble 	uint16_t speed;
    358   1.1    rumble 	uint16_t div;
    359   1.1    rumble } divs[] = {
    360   1.1    rumble 	{    50, 2303 },	/* 2304 is exact?? */
    361   1.1    rumble 	{   110, 1047 },	/* Should be 1047.27 */
    362   1.1    rumble 	{   134, 857 },		/* Should be 856.505576 */
    363   1.1    rumble 	{  1050, 110 },		/* Should be 109.7142857 */
    364   1.1    rumble 	{  2000, 57 }		/* Should be 57.6 */
    365   1.1    rumble };
    366   1.1    rumble #define DIVS (sizeof(divs)/sizeof(divs[0]))
    367   1.1    rumble 
    368   1.1    rumble /*
    369   1.1    rumble  * minor unit bit decode:
    370   1.1    rumble  * CxxxUUU
    371   1.1    rumble  *
    372   1.1    rumble  * C - carrier
    373   1.1    rumble  *	0 - delay open until carrier high
    374   1.1    rumble  *	1 - allow open with carrier low
    375   1.1    rumble  * UUU - unit 0-7
    376   1.1    rumble  */
    377   1.1    rumble 
    378   1.1    rumble #define DEV_UNIT(x)	(minor(x) & 0x7)
    379   1.1    rumble #define DEV_DIALOUT(x)	(minor(x) & 0x80)
    380   1.1    rumble 
    381   1.1    rumble #define SCN_MAXDUART 4
    382   1.1    rumble static struct duart scn_duart[SCN_MAXDUART];
    383   1.1    rumble 
    384   1.1    rumble #ifdef KGDB
    385   1.1    rumble extern int kgdb_dev;
    386   1.1    rumble extern int kgdb_rate;
    387   1.1    rumble extern int kgdb_debug_init;
    388   1.1    rumble #endif
    389   1.1    rumble 
    390   1.1    rumble /* XXXXX - fix this */
    391   1.1    rumble #define splrtty() spltty()
    392   1.1    rumble 
    393   1.1    rumble /* RS-232 configuration routines */
    394   1.1    rumble 
    395   1.1    rumble /*
    396   1.1    rumble  * set chip parameters, or mark for delayed change.
    397   1.1    rumble  * called at spltty() or on TxEMPTY interrupt.
    398   1.1    rumble  *
    399   1.1    rumble  * Reads current values to avoid glitches from redundant sets.
    400   1.1    rumble  * Perhaps should save last value set to avoid read/write?  NOTE:
    401   1.1    rumble  * Would still need to do read if write not needed to advance MR
    402   1.1    rumble  * pointer.
    403   1.1    rumble  *
    404   1.1    rumble  * new 2/97 -plb
    405   1.1    rumble  */
    406   1.1    rumble 
    407   1.1    rumble static void
    408   1.1    rumble scn_setchip(struct scn_softc *sc)
    409   1.1    rumble {
    410   1.1    rumble 	struct duart *dp;
    411   1.1    rumble 	u_char acr, csr, mr1, mr2;
    412   1.1    rumble 	int chan;
    413   1.1    rumble 
    414   1.1    rumble 	if (sc->sc_tty && (sc->sc_tty->t_state & TS_BUSY)) {
    415   1.1    rumble 		sc->sc_heldchanges = 1;
    416   1.1    rumble 		return;
    417   1.1    rumble 	}
    418   1.1    rumble 
    419   1.1    rumble 	chan = sc->sc_channel;
    420   1.1    rumble 	dp = sc->sc_duart;
    421   1.1    rumble 	if (dp->type == SC26C92) {
    422   1.1    rumble 		u_char nmr0a, mr0a;
    423   1.1    rumble 
    424   1.1    rumble 		/* input rate high enough so 64 bit time watchdog not
    425   1.1    rumble 		 * onerous? */
    426   1.1    rumble 		if (dp->chan[chan].ispeed >= 1200) {
    427   1.1    rumble 			/* set FIFO threshold at 6 for other
    428   1.1    rumble 			 * thresholds we could have to set MR1_FFULL
    429   1.1    rumble 			 */
    430   1.1    rumble 			dp->chan[chan].mr0 |= MR0_RXWD | MR0_RXINT;
    431   1.1    rumble 		} else {
    432   1.1    rumble 			dp->chan[chan].mr0 &= ~(MR0_RXWD | MR0_RXINT);
    433   1.1    rumble 		}
    434   1.1    rumble 
    435   1.1    rumble 		/* select BRG mode (MR0A only) */
    436   1.1    rumble 		nmr0a = dp->chan[0].mr0 | (dp->mode & MR0_MODE);
    437   1.1    rumble 
    438   1.1    rumble 		dp->base[CH_CR] = CR_CMD_MR0;
    439   1.1    rumble 		RECOVER();
    440   1.1    rumble 
    441   1.1    rumble 		mr0a = dp->base[CH_MR];
    442   1.1    rumble 		if (mr0a != nmr0a) {
    443   1.1    rumble 			dp->base[CH_CR] = CR_CMD_MR0;
    444   1.1    rumble 			RECOVER();
    445   1.1    rumble 			dp->base[CH_MR] = nmr0a;
    446   1.1    rumble 		}
    447   1.1    rumble 
    448   1.1    rumble 		if (chan) {	 /* channel B? */
    449   1.1    rumble 			u_char mr0b;
    450   1.1    rumble 
    451   1.1    rumble 			sc->sc_chbase[CH_CR] = CR_CMD_MR0;
    452   1.1    rumble 			RECOVER();
    453   1.1    rumble 			mr0b = dp->base[CH_MR];
    454   1.1    rumble 
    455   1.1    rumble 			if (dp->chan[chan].mr0 != mr0b) {
    456   1.1    rumble 				sc->sc_chbase[CH_CR] = CR_CMD_MR0;
    457   1.1    rumble 				RECOVER();
    458   1.1    rumble 				sc->sc_chbase[CH_MR] = dp->chan[chan].mr0;
    459   1.1    rumble 			}
    460   1.1    rumble 		}
    461   1.1    rumble 	} else {
    462   1.1    rumble 		sc->sc_chbase[CH_CR] = CR_CMD_MR1;
    463   1.1    rumble 		RECOVER();
    464   1.1    rumble 	}
    465   1.1    rumble 
    466   1.1    rumble 	mr1 = sc->sc_chbase[CH_MR];
    467   1.1    rumble 	mr2 = sc->sc_chbase[CH_MR];
    468   1.1    rumble 	if (mr1 != dp->chan[chan].new_mr1 ||
    469   1.1    rumble 	    mr2 != dp->chan[chan].new_mr2) {
    470   1.1    rumble 		sc->sc_chbase[CH_CR] = CR_CMD_MR1;
    471   1.1    rumble 		RECOVER();
    472   1.1    rumble 		sc->sc_chbase[CH_MR] = dp->chan[chan].new_mr1;
    473   1.1    rumble 		sc->sc_chbase[CH_MR] = dp->chan[chan].new_mr2;
    474   1.1    rumble 	}
    475   1.1    rumble 
    476   1.1    rumble 	acr = dp->acr | (dp->mode & ACR_BRG);
    477   1.1    rumble 	dp->base[DU_ACR] = acr;		/* write-only reg! */
    478   1.1    rumble 
    479   1.1    rumble 	/* set speed codes */
    480   1.1    rumble 	csr = (dp->chan[chan].icode<<4) | dp->chan[chan].ocode;
    481   1.1    rumble 	if (sc->sc_chbase[CH_CSR] != csr) {
    482   1.1    rumble 		sc->sc_chbase[CH_CSR] = csr;
    483   1.1    rumble 	}
    484   1.1    rumble 
    485   1.1    rumble 	/* see if counter/timer in use */
    486   1.1    rumble 	if (dp->counter &&
    487   1.1    rumble 	    (dp->chan[0].icode == USE_CT || dp->chan[0].ocode == USE_CT ||
    488   1.1    rumble 	     dp->chan[1].icode == USE_CT || dp->chan[1].ocode == USE_CT)) {
    489   1.1    rumble 
    490   1.1    rumble 		/* program counter/timer only if necessary */
    491   1.1    rumble 		if (dp->counter != dp->ocounter) {
    492   1.1    rumble 			uint16_t div;
    493   1.1    rumble #ifdef DIVS
    494   1.1    rumble 			int i;
    495   1.1    rumble 
    496   1.1    rumble 			/* look for precalculated rate, for minimum error */
    497   1.1    rumble 			for (i = 0; i < DIVS && divs[i].speed <= dp->counter; i++) {
    498   1.1    rumble 				if (divs[i].speed == dp->counter) {
    499   1.1    rumble 					div = divs[i].div;
    500   1.1    rumble 					goto found;
    501   1.1    rumble 				}
    502   1.1    rumble 			}
    503   1.1    rumble #endif
    504   1.1    rumble 
    505   1.1    rumble 			/* not found in table; calculate a value (rounding up) */
    506   1.1    rumble 			div = ((long)SCN_CLOCK/16/2 + dp->counter/2) / dp->counter;
    507   1.1    rumble 
    508   1.1    rumble 		found:
    509   1.1    rumble 			/* halt before loading? may ALWAYS glitch?
    510   1.1    rumble 			 * reload race may only sometimes glitch??
    511   1.1    rumble 			 */
    512   1.1    rumble 			dp->base[DU_CTUR] = div >> 8;
    513   1.1    rumble 			dp->base[DU_CTLR] = div & 255;
    514   1.1    rumble 			if (dp->ocounter == 0) {
    515   1.1    rumble 				/* not previously used? */
    516   1.1    rumble 				u_char temp;
    517   1.1    rumble 				/* start C/T running */
    518   1.1    rumble 				temp = dp->base[DU_CSTRT];
    519   1.6  christos 				__USE(temp);
    520   1.1    rumble 			}
    521   1.1    rumble 			dp->ocounter = dp->counter;
    522   1.1    rumble 		}
    523   1.1    rumble 	} else {
    524   1.1    rumble 		/* counter not in use; mark as free */
    525   1.1    rumble 		dp->counter = 0;
    526   1.1    rumble 	}
    527   1.1    rumble 	sc->sc_heldchanges = 0;
    528   1.1    rumble 
    529   1.1    rumble 	/*
    530   1.1    rumble 	 * delay a tiny bit to try and avoid tx glitching.
    531   1.1    rumble 	 * I know we're at spltty(), but this is much better than the
    532   1.1    rumble 	 * old version used DELAY((96000 / out_speed) * 10000)
    533   1.1    rumble 	 * -plb
    534   1.1    rumble 	 */
    535   1.1    rumble 	DELAY(10);
    536   1.1    rumble }
    537   1.1    rumble 
    538   1.1    rumble /*
    539   1.1    rumble  * iterator function for speeds.
    540   1.1    rumble  * (could be called "findnextcode")
    541   1.1    rumble  * Returns sequence of possible speed codes for a given rate.
    542   1.1    rumble  * should set index to zero before first call.
    543   1.1    rumble  *
    544   1.1    rumble  * Could be implemented as a "checkspeed()" function called
    545   1.1    rumble  * to evaluate table entries, BUT this allows more variety in
    546   1.1    rumble  * use of C/T with fewer table entries.
    547   1.1    rumble  */
    548   1.1    rumble 
    549   1.1    rumble static int
    550   1.1    rumble scniter(int *index, int wanted, int *counter, int *mode, struct chan *other,
    551   1.1    rumble     int c92)
    552   1.1    rumble {
    553   1.1    rumble 
    554   1.1    rumble 	while (*index < TABENTRIES) {
    555   1.1    rumble 		struct tabent *tp;
    556   1.1    rumble 
    557   1.1    rumble 		tp = table + (*index)++;
    558   1.1    rumble 		if (tp->speed != wanted)
    559   1.1    rumble 			continue;
    560   1.1    rumble 
    561   1.1    rumble 		/* if not a 26C92 only look at MODE0 entries */
    562   1.1    rumble 		if (!c92 && (tp->mode & MR0_MODE) != MR0_MODE_0)
    563   1.1    rumble 			continue;
    564   1.1    rumble 
    565   1.1    rumble 		/*
    566   1.1    rumble 		 * check mode;
    567   1.1    rumble 		 * OK if this table entry for current mode, or mode not
    568   1.1    rumble 		 * yet set, or other channel's rates are available in both
    569   1.1    rumble 		 * A and B groups.
    570   1.1    rumble 		 */
    571   1.1    rumble 
    572   1.1    rumble 		if (tp->mode == *mode || *mode == ANYMODE ||
    573   1.1    rumble 		    (other != NULL && (tp->mode & MR0_MODE) == (*mode & MR0_MODE) &&
    574   1.1    rumble 		     bothgroups[other->icode] && bothgroups[other->ocode])) {
    575   1.1    rumble 			/*
    576   1.1    rumble 			 * for future table entries specifying
    577   1.1    rumble 			 * use of counter/timer
    578   1.1    rumble 			 */
    579   1.1    rumble 			if (tp->code == USE_CT) {
    580   1.1    rumble 				if (*counter != wanted && *counter != 0)
    581   1.1    rumble 					continue;	/* counter busy */
    582   1.1    rumble 				*counter = wanted;
    583   1.1    rumble 			}
    584   1.1    rumble 			*mode = tp->mode;
    585   1.1    rumble 			return tp->code;
    586   1.1    rumble 		}
    587   1.1    rumble 	}
    588   1.1    rumble 
    589   1.1    rumble 	/* here after returning all applicable table entries */
    590   1.1    rumble 	/* XXX return sequence of USE_CT with all possible modes?? */
    591   1.1    rumble 	if ((*index)++ == TABENTRIES) {
    592   1.1    rumble 		/* Max C/T rate (even on 26C92?) is 57600 */
    593   1.1    rumble 		if (wanted <= 57600 && (*counter == wanted || *counter == 0)) {
    594   1.1    rumble 			*counter = wanted;
    595   1.1    rumble 			return USE_CT;
    596   1.1    rumble 		}
    597   1.1    rumble 	}
    598   1.1    rumble 
    599   1.1    rumble 	return -1;			/* FAIL */
    600   1.1    rumble }
    601   1.1    rumble 
    602   1.1    rumble /*
    603   1.1    rumble  * calculate configuration
    604   1.1    rumble  * rewritten 2/97 -plb
    605   1.1    rumble  */
    606   1.1    rumble static int
    607   1.1    rumble scn_config(int unit, int chan, int ispeed, int ospeed, u_char mr1, u_char mr2)
    608   1.1    rumble {
    609   1.1    rumble 	struct scn_softc *sc;
    610   1.1    rumble 	struct duart *dp;
    611   1.1    rumble 	int other;		/* opposite of chan */
    612   1.1    rumble 	int mode;
    613   1.1    rumble 	int counter;
    614   1.1    rumble 	int i, o;		/* input, output iterator indexes */
    615   1.1    rumble 	int ic, oc;		/* input, output codes */
    616   1.1    rumble 	struct chan *ocp;	/* other duart channel */
    617   1.1    rumble 	struct tty *otp;	/* other channel tty struct */
    618   1.1    rumble 	int c92;		/* true if duart is sc26c92 */
    619   1.1    rumble 	int s;
    620   1.1    rumble 
    621   1.1    rumble 	/* Set up softc pointer. */
    622   1.1    rumble 	if (unit >= scn_cd.cd_ndevs)
    623   1.1    rumble 		return ENXIO;
    624   1.1    rumble 	sc = SOFTC(unit);
    625   1.1    rumble 	chan = sc->sc_channel;
    626   1.1    rumble 	other = chan ^ 1;
    627   1.1    rumble 	dp = sc->sc_duart;
    628   1.1    rumble 	ocp = &dp->chan[other];
    629   1.1    rumble 	otp = ocp->tty;
    630   1.1    rumble 	c92 = (dp->type == SC26C92);
    631   1.1    rumble 
    632   1.1    rumble 	/*
    633   1.1    rumble 	 * Right now the first combination that works is used.
    634   1.1    rumble 	 * Perhaps it should search entire solution space for "best"
    635   1.1    rumble 	 * combination. For example, use heuristic weighting of mode
    636   1.1    rumble 	 * preferences, and use of counter timer?
    637   1.1    rumble 	 *
    638   1.1    rumble 	 * For example right now with 2681/2692 when default rate is
    639   1.1    rumble 	 * 9600 and other channel is closed setting 19200 will pick
    640   1.1    rumble 	 * mode 0a and use counter/timer.  Better solution might be
    641   1.1    rumble 	 * mode 0b, leaving counter/timer free!
    642   1.1    rumble 	 *
    643   1.1    rumble 	 * When other channel is open might want to prefer
    644   1.1    rumble 	 * leaving counter timer free, or not flipping A/B group?
    645   1.1    rumble 	 */
    646   1.1    rumble 	if (otp && (otp->t_state & TS_ISOPEN)) {
    647   1.1    rumble 
    648   1.1    rumble 		/*
    649   1.1    rumble 		 * Other channel open;
    650   1.1    rumble 		 * Find speed codes compatible with current mode/counter.
    651   1.1    rumble 		 */
    652   1.1    rumble 
    653   1.1    rumble 		i = 0;
    654   1.1    rumble 		for (;;) {
    655   1.1    rumble 			mode = dp->mode;
    656   1.1    rumble 			counter = dp->counter;
    657   1.1    rumble 
    658   1.1    rumble 			/* NOTE: pass other chan pointer to allow group flipping */
    659   1.1    rumble 			ic = scniter(&i, ispeed, &counter, &mode, ocp, c92);
    660   1.1    rumble 			if (ic == -1)
    661   1.1    rumble 				break;
    662   1.1    rumble 
    663   1.1    rumble 			o = 0;
    664   1.1    rumble 			if ((oc = scniter(&o, ospeed, &counter,
    665   1.1    rumble 					  &mode, NULL, c92)) != -1) {
    666   1.1    rumble 				/*
    667   1.1    rumble 				 * take first match
    668   1.1    rumble 				 *
    669   1.1    rumble 				 * Perhaps calculate heuristic "score",
    670   1.1    rumble 				 * save score,codes,mode,counter if score
    671   1.1    rumble 				 * better than previous best?
    672   1.1    rumble 				 */
    673   1.1    rumble 				goto gotit;
    674   1.1    rumble 			}
    675   1.1    rumble 		}
    676   1.1    rumble 		/* XXX try looping for ospeed? */
    677   1.1    rumble 	} else {
    678   1.1    rumble 		/* other channel closed */
    679   1.1    rumble 		int oo, oi;	/* other input, output iterators */
    680   1.1    rumble 		int oic, ooc;	/* other input, output codes */
    681   1.1    rumble 
    682   1.1    rumble 		/*
    683   1.1    rumble 		 * Here when other channel closed.  Finds first
    684   1.1    rumble 		 * combination that will allow other channel to be opened
    685   1.1    rumble 		 * (with defaults) and fits our needs.
    686   1.1    rumble 		 */
    687   1.1    rumble 		oi = 0;
    688   1.1    rumble 		for (;;) {
    689   1.1    rumble 			mode = ANYMODE;
    690   1.1    rumble 			counter = 0;
    691   1.1    rumble 
    692   1.1    rumble 			oic = scniter(&oi, ocp->ispeed, &counter, &mode, NULL, c92);
    693   1.1    rumble 			if (oic == -1)
    694   1.1    rumble 				break;
    695   1.1    rumble 
    696   1.1    rumble 			oo = 0;
    697   1.1    rumble 			while ((ooc = scniter(&oo, ocp->ospeed, &counter,
    698   1.1    rumble 					   &mode, NULL, c92)) != -1) {
    699   1.1    rumble 				i = 0;
    700   1.1    rumble 				while ((ic = scniter(&i, ispeed, &counter,
    701   1.1    rumble 						  &mode, NULL, c92)) != -1) {
    702   1.1    rumble 					o = 0;
    703   1.1    rumble 					if ((oc = scniter(&o, ospeed, &counter,
    704   1.1    rumble 						       &mode, NULL, c92)) != -1) {
    705   1.1    rumble 						/*
    706   1.1    rumble 						 * take first match
    707   1.1    rumble 						 *
    708   1.1    rumble 						 * Perhaps calculate heuristic
    709   1.1    rumble 						 * "score", save
    710   1.1    rumble 						 *     score,codes,mode,counter
    711   1.1    rumble 						 * if score better than
    712   1.1    rumble 						 * previous best?
    713   1.1    rumble 						 */
    714   1.1    rumble 						s = spltty();
    715   1.1    rumble 						dp->chan[other].icode = oic;
    716   1.1    rumble 						dp->chan[other].ocode = ooc;
    717   1.1    rumble 						goto gotit2;
    718   1.1    rumble 					}
    719   1.1    rumble 				}
    720   1.1    rumble 			}
    721   1.1    rumble 		}
    722   1.1    rumble 	}
    723   1.1    rumble 	return EINVAL;
    724   1.1    rumble 
    725   1.1    rumble  gotit:
    726   1.1    rumble 	s = spltty();
    727   1.1    rumble  gotit2:
    728   1.1    rumble 	dp->chan[chan].new_mr1 = mr1;
    729   1.1    rumble 	dp->chan[chan].new_mr2 = mr2;
    730   1.1    rumble 	dp->chan[chan].ispeed = ispeed;
    731   1.1    rumble 	dp->chan[chan].ospeed = ospeed;
    732   1.1    rumble 	dp->chan[chan].icode = ic;
    733   1.1    rumble 	dp->chan[chan].ocode = oc;
    734   1.1    rumble 	if (mode == ANYMODE)		/* no mode selected?? */
    735   1.1    rumble 		mode = DEFMODE(c92);
    736   1.1    rumble 	dp->mode = mode;
    737   1.1    rumble 	dp->counter = counter;
    738   1.1    rumble 
    739   1.1    rumble 	scn_setchip(sc);		/* set chip now, if possible */
    740   1.1    rumble 	splx(s);
    741   1.1    rumble 	return (0);
    742   1.1    rumble }
    743   1.1    rumble 
    744   1.1    rumble int
    745   1.1    rumble scn_match(device_t parent, struct cfdata *cf, void *aux)
    746   1.1    rumble {
    747   1.1    rumble 	struct mainbus_attach_args *ma = aux;
    748   1.1    rumble 
    749   1.1    rumble 	if ((mach_type == MACH_SGI_IP6 || mach_type == MACH_SGI_IP10) &&
    750   1.1    rumble 	    ma->ma_addr == 0x1fb80004)
    751   1.1    rumble 		return (1);
    752   1.1    rumble 
    753   1.1    rumble 	return (0);
    754   1.1    rumble }
    755   1.1    rumble 
    756   1.1    rumble /*
    757   1.1    rumble  * No need to make scn_rx{en,dis}able too efficient,
    758   1.1    rumble  * they're only called on setup, open & close!
    759   1.1    rumble  */
    760   1.1    rumble static inline void
    761   1.1    rumble scn_rxenable(struct scn_softc *sc)
    762   1.1    rumble {
    763   1.1    rumble 	struct duart *dp;
    764   1.1    rumble 	int channel;
    765   1.1    rumble 
    766   1.1    rumble 	dp = sc->sc_duart;
    767   1.1    rumble 	channel = sc->sc_channel;
    768   1.1    rumble 
    769   1.1    rumble 	/* Outputs wire-ored and connected to ICU input for fast rx interrupt. */
    770   1.1    rumble 	if (channel == 0)
    771   1.1    rumble 		dp->opcr |= OPCR_OP4_RXRDYA;
    772   1.1    rumble 	else
    773   1.1    rumble 		dp->opcr |= OPCR_OP5_RXRDYB;
    774   1.1    rumble 	dp->base[DU_OPCR] = dp->opcr;
    775   1.1    rumble 	dp->imr |= sc->sc_rx_int;
    776   1.1    rumble 	dp->base[DU_IMR] = dp->imr;
    777   1.1    rumble }
    778   1.1    rumble 
    779   1.1    rumble static inline void
    780   1.1    rumble scn_rxdisable(struct scn_softc *sc)
    781   1.1    rumble {
    782   1.1    rumble 	struct duart *dp;
    783   1.1    rumble 	int channel;
    784   1.1    rumble 
    785   1.1    rumble 	dp = sc->sc_duart;
    786   1.1    rumble 	channel = sc->sc_channel;
    787   1.1    rumble 
    788   1.1    rumble 	/* Outputs wire-ored and connected to ICU input for fast rx interrupt. */
    789   1.1    rumble 	if (channel == 0)
    790   1.1    rumble 		dp->opcr &= ~OPCR_OP4_RXRDYA;
    791   1.1    rumble 	else
    792   1.1    rumble 		dp->opcr &= ~OPCR_OP5_RXRDYB;
    793   1.1    rumble 	dp->base[DU_OPCR] = dp->opcr;
    794   1.1    rumble 	dp->imr &= ~sc->sc_rx_int;
    795   1.1    rumble 	dp->base[DU_IMR] = dp->imr;
    796   1.1    rumble }
    797   1.1    rumble 
    798   1.1    rumble void
    799   1.1    rumble scn_attach(device_t parent, device_t self, void *aux)
    800   1.1    rumble {
    801   1.1    rumble 	struct mainbus_attach_args *ma = aux;
    802   1.1    rumble 	struct scn_softc *sc;
    803   1.1    rumble 	struct duart *duart;
    804   1.1    rumble 	volatile u_char *ch_base;
    805   1.1    rumble 	volatile u_char *duart_base;
    806   1.1    rumble 	int channel;
    807   1.1    rumble 	int speed;
    808   1.1    rumble 	int s;
    809   1.6  christos 	int maj __diagused;
    810   1.1    rumble 	u_char unit;
    811   1.1    rumble 	u_char duartno;
    812   1.1    rumble 	u_char delim = ':';
    813   1.1    rumble 	u_char mr1, mr2;
    814   1.1    rumble 	enum scntype scntype = SCNUNK;
    815   1.1    rumble 	const char *duart_type = "Unknown";
    816   1.1    rumble 	bool console, first;
    817   1.1    rumble 	devmajor_t major;
    818   1.1    rumble 
    819   1.1    rumble 	(void)major;
    820   1.1    rumble 
    821   1.1    rumble 	sc = device_private(self);
    822   1.1    rumble 	unit = device_unit(self);
    823   1.1    rumble 
    824   1.1    rumble 	/* XXX - hard-coded */
    825   1.1    rumble 	if (ma->ma_addr == 0x1fb80004)
    826   1.1    rumble 		duartno = 1;
    827   1.1    rumble 	else
    828   1.1    rumble 		duartno = 0;
    829   1.1    rumble 	channel = 0;
    830   1.1    rumble 	console = 1;
    831   1.1    rumble 
    832   1.1    rumble 	duart = sc->sc_duart = &scn_duart[duartno];
    833   1.1    rumble 	duart->chan[channel].sc = sc;
    834   1.1    rumble 	first =	(duart->base == NULL);
    835   1.1    rumble 
    836   1.1    rumble 	if (console) {
    837   1.1    rumble 		sc->sc_isconsole = 1;
    838   1.1    rumble 		sc->sc_swflags |= SCN_SW_SOFTCAR;	/* ignore carrier */
    839   1.1    rumble 	}
    840   1.1    rumble 
    841   1.1    rumble 	duart_base = (volatile u_char *)MIPS_PHYS_TO_KSEG1(ma->ma_addr);
    842   1.1    rumble 	ch_base    = duart_base; /* XXX */
    843   1.1    rumble 
    844   1.1    rumble 	if (first) {
    845   1.1    rumble 		/* Probe DUART type */
    846   1.1    rumble 		s = spltty();
    847   1.1    rumble 		if (console) {
    848   1.1    rumble 			ch_base[CH_CR] = CR_DIS_TX;
    849   1.1    rumble 			delay(5 * 10000);
    850   1.1    rumble 		}
    851   1.1    rumble 		ch_base[CH_CR] = CR_CMD_MR1;
    852   1.1    rumble 		RECOVER();
    853   1.1    rumble 		mr1 = ch_base[CH_MR];
    854   1.1    rumble 		mr2 = ch_base[CH_MR];
    855   1.1    rumble 		ch_base[CH_CR] = CR_CMD_MR1;
    856   1.1    rumble 		RECOVER();
    857   1.1    rumble 		ch_base[CH_MR] = 1;
    858   1.1    rumble 		ch_base[CH_MR] = 0;
    859   1.1    rumble 		ch_base[CH_CR] = CR_CMD_MR1;
    860   1.1    rumble 		RECOVER();
    861   1.1    rumble 		if (ch_base[CH_MR] == 1) {
    862   1.1    rumble 			/* MR 2 selected */
    863   1.1    rumble 			ch_base[CH_CR] = CR_CMD_MR0;
    864   1.1    rumble 			RECOVER();
    865   1.1    rumble 			/* if 2681, MR2 still selected */
    866   1.1    rumble 			ch_base[CH_MR] = 1;
    867   1.1    rumble 			ch_base[CH_CR] = CR_CMD_MR1;
    868   1.1    rumble 			RECOVER();
    869   1.1    rumble 			ch_base[CH_MR] = 0; /* MR1 */
    870   1.1    rumble 			ch_base[CH_MR] = 0; /* MR2 */
    871   1.1    rumble 			ch_base[CH_CR] = CR_CMD_MR0;
    872   1.1    rumble 			RECOVER();
    873   1.1    rumble 			/* if 2681, MR2 still selected */
    874   1.1    rumble 			if((ch_base[CH_MR] & 1) == 1) {
    875   1.1    rumble 				duart_type = "sc26c92";
    876   1.1    rumble 				scntype = SC26C92;
    877   1.1    rumble 			} else {
    878   1.1    rumble 				/* 2681 treats as MR1 Select */
    879   1.1    rumble 				ch_base[CH_CR] = CR_CMD_RTS_OFF;
    880   1.1    rumble 				RECOVER();
    881   1.1    rumble 				ch_base[CH_MR] = 1;
    882   1.1    rumble 				ch_base[CH_MR] = 0;
    883   1.1    rumble 				ch_base[CH_CR] = CR_CMD_RTS_OFF;
    884   1.1    rumble 				RECOVER();
    885   1.1    rumble 				if (ch_base[CH_MR] == 1) {
    886   1.1    rumble 					duart_type = "scn2681";
    887   1.1    rumble 					scntype = SCN2681;
    888   1.1    rumble 				} else {
    889   1.1    rumble 					duart_type = "scn2692";
    890   1.1    rumble 					scntype = SCN2692;
    891   1.1    rumble 				}
    892   1.1    rumble 			}
    893   1.1    rumble 		}
    894   1.1    rumble 
    895   1.1    rumble 		/* If a 2681, the CR_CMD_MR0 is interpreted as a TX_RESET */
    896   1.1    rumble 		if (console) {
    897   1.1    rumble 			ch_base[CH_CR] = CR_ENA_TX;
    898   1.1    rumble 			RECOVER();
    899   1.1    rumble 		}
    900   1.1    rumble 		ch_base[CH_CR] = CR_CMD_MR1;
    901   1.1    rumble 		RECOVER();
    902   1.1    rumble 		ch_base[CH_MR] = mr1;
    903   1.1    rumble 		ch_base[CH_MR] = mr2;
    904   1.1    rumble 		splx(s);
    905   1.1    rumble 
    906   1.1    rumble 		/*
    907   1.1    rumble 		 * On IP6 the console chip is duart1. The keyboard/mouse
    908   1.1    rumble 		 * is duart0. Each chip has two channels and the channels
    909   1.1    rumble 		 * share an interrupt. Duart0 is interrupt 0, duart1 is
    910   1.1    rumble 		 * interrupt 1.
    911   1.1    rumble 		 */
    912   1.1    rumble 		if (duartno != 0 && duartno != 1)
    913   1.1    rumble 			panic("scn_attach: bad duartno: %d", duartno);
    914   1.1    rumble 		cpu_intr_establish(duartno, IPL_TTY, scnintr, duart);
    915   1.1    rumble 
    916   1.1    rumble 		printf("%c %s", delim, duart_type);
    917   1.1    rumble 		delim = ',';
    918   1.1    rumble 
    919   1.1    rumble 		duart->base = duart_base;
    920   1.1    rumble 		duart->type = scntype;
    921   1.1    rumble 	}
    922   1.1    rumble 	/* Record channel, uart */
    923   1.1    rumble 	sc->sc_channel = channel;
    924   1.1    rumble 	sc->sc_chbase = ch_base;
    925   1.1    rumble 
    926   1.1    rumble 	/* Initialize modem/interrupt bit masks */
    927   1.1    rumble 	if (channel == 0) {
    928   1.1    rumble 		sc->sc_op_rts = OP_RTSA;
    929   1.1    rumble 		sc->sc_op_dtr = OP_DTRA;
    930   1.1    rumble 		sc->sc_ip_cts = IP_CTSA;
    931   1.1    rumble 		sc->sc_ip_dcd = IP_DCDA;
    932   1.1    rumble 
    933   1.1    rumble 		sc->sc_tx_int = INT_TXA;
    934   1.1    rumble 		sc->sc_rx_int = INT_RXA;
    935   1.1    rumble 	} else {
    936   1.1    rumble 		sc->sc_op_rts = OP_RTSB;
    937   1.1    rumble 		sc->sc_op_dtr = OP_DTRB;
    938   1.1    rumble 		sc->sc_ip_cts = IP_CTSB;
    939   1.1    rumble 		sc->sc_ip_dcd = IP_DCDB;
    940   1.1    rumble 
    941   1.1    rumble 		sc->sc_tx_int = INT_TXB;
    942   1.1    rumble 		sc->sc_rx_int = INT_RXB;
    943   1.1    rumble 	}
    944   1.1    rumble 
    945   1.1    rumble 	/* Initialize counters */
    946   1.1    rumble 	sc->sc_framing_errors = 0;
    947   1.1    rumble 	sc->sc_fifo_overruns = 0;
    948   1.1    rumble 	sc->sc_parity_errors = 0;
    949   1.1    rumble 	sc->sc_breaks = 0;
    950   1.1    rumble 
    951   1.1    rumble 	if (console) {
    952   1.1    rumble 		DELAY(5 * 10000);	/* Let the output go out.... */
    953   1.1    rumble 	}
    954   1.1    rumble 
    955   1.1    rumble 	/*
    956   1.1    rumble 	 * Set up the hardware to a base state, in particular:
    957   1.1    rumble 	 * o reset transmitter and receiver
    958   1.1    rumble 	 * o set speeds and configurations
    959   1.1    rumble 	 * o receiver interrupts only (RxRDY and BREAK)
    960   1.1    rumble 	 */
    961   1.1    rumble 
    962   1.1    rumble 	s = spltty();
    963   1.1    rumble 	/* RTS off... */
    964   1.1    rumble 	SCN_OP_BIC(sc, sc->sc_op_rts);	/* "istop" */
    965   1.1    rumble 
    966   1.1    rumble 	ch_base[CH_CR] = CR_DIS_RX | CR_DIS_TX;
    967   1.1    rumble 	RECOVER();
    968   1.1    rumble 	ch_base[CH_CR] = CR_CMD_RESET_RX;
    969   1.1    rumble 	RECOVER();
    970   1.1    rumble 	ch_base[CH_CR] = CR_CMD_RESET_TX;
    971   1.1    rumble 	RECOVER();
    972   1.1    rumble 	ch_base[CH_CR] = CR_CMD_RESET_ERR;
    973   1.1    rumble 	RECOVER();
    974   1.1    rumble 	ch_base[CH_CR] = CR_CMD_RESET_BRK;
    975   1.1    rumble 	RECOVER();
    976   1.1    rumble 	ch_base[CH_CR] = CR_CMD_MR1;
    977   1.1    rumble 	RECOVER();
    978   1.1    rumble 
    979   1.1    rumble 	/* No receiver control of RTS. */
    980   1.1    rumble 	ch_base[CH_MR] = 0;
    981   1.1    rumble 	ch_base[CH_MR] = 0;
    982   1.1    rumble 
    983   1.1    rumble 	/* Initialize the uart structure if this is channel A. */
    984   1.1    rumble 	if (first) {
    985   1.1    rumble 		/* Disable all interrupts. */
    986   1.1    rumble 		duart_base[DU_IMR] = duart->imr = 0;
    987   1.1    rumble 
    988   1.1    rumble 		/* Output port config */
    989   1.1    rumble 		duart_base[DU_OPCR] = duart->opcr = 0;
    990   1.1    rumble 
    991   1.1    rumble 		/* Speeds... */
    992   1.1    rumble 		duart->mode = 0;
    993   1.1    rumble 
    994   1.1    rumble 		/*
    995   1.1    rumble 		 * Set initial speed to an illegal code that can be changed to
    996   1.1    rumble 		 * any other baud.
    997   1.1    rumble 		 */
    998   1.1    rumble 		duart->chan[0].icode = duart->chan[0].ocode = 0x2f;
    999   1.1    rumble 		duart->chan[1].icode = duart->chan[1].ocode = 0x2f;
   1000   1.1    rumble 		duart->chan[0].ispeed = duart->chan[0].ospeed = 0;
   1001   1.1    rumble 		duart->chan[1].ispeed = duart->chan[1].ospeed = 0;
   1002   1.1    rumble 
   1003   1.1    rumble 		duart->acr = 0;
   1004   1.1    rumble 		duart->acr |= ACR_CT_TCLK1;	/* timer mode 1x clk */
   1005   1.1    rumble 	}
   1006   1.1    rumble 
   1007   1.1    rumble 	if (channel == 0) {
   1008   1.1    rumble 		duart->acr |= ACR_DELTA_DCDA;	/* Set CD int */
   1009   1.1    rumble 	} else {
   1010   1.1    rumble 		duart->acr |= ACR_DELTA_DCDB;	/* Set CD int */
   1011   1.1    rumble 	}
   1012   1.1    rumble 
   1013   1.1    rumble 	if (scnsir == NULL) {
   1014   1.1    rumble 		/* software intr: calls tty code, hence IPL_TTY */
   1015   1.1    rumble 		scnsir = softint_establish(SOFTINT_SERIAL, scnsoft, NULL);
   1016   1.1    rumble 	}
   1017   1.1    rumble 
   1018   1.1    rumble 	duart_base[DU_ACR] = (duart->mode & ACR_BRG) | duart->acr;
   1019   1.1    rumble 
   1020   1.1    rumble 	if (console)
   1021   1.1    rumble 		speed = scnconsrate;
   1022   1.1    rumble 	else
   1023   1.1    rumble 		speed = scndefaultrate;
   1024   1.1    rumble 
   1025   1.1    rumble 	scn_config(unit, channel, speed, speed, MR1_PNONE | MR1_CS8, MR2_STOP1);
   1026   1.1    rumble 	if (console) {
   1027   1.1    rumble 		maj = cdevsw_lookup_major(&scn_cdevsw);
   1028   1.1    rumble 		KASSERT(maj != NODEVMAJOR);
   1029   1.1    rumble 		shutdownhook_establish(scncnreinit, NULL);
   1030   1.1    rumble 		/* Make sure console can do scncngetc */
   1031   1.1    rumble 		duart_base[DU_OPSET] = channel ? (OP_RTSB | OP_DTRB) :
   1032   1.1    rumble 			(OP_RTSA | OP_DTRA);
   1033   1.1    rumble 	}
   1034   1.1    rumble 
   1035   1.1    rumble 	/* Turn on the receiver and transmitters */
   1036   1.1    rumble 	ch_base[CH_CR] = CR_ENA_RX | CR_ENA_TX;
   1037   1.1    rumble 
   1038   1.1    rumble 	/* Set up the interrupts. */
   1039   1.1    rumble 	duart->imr |= INT_IP;
   1040   1.1    rumble 	scn_rxdisable(sc);
   1041   1.1    rumble 	splx(s);
   1042   1.1    rumble 
   1043   1.1    rumble 	if (sc->sc_swflags) {
   1044   1.1    rumble 		printf("%c flags %d", delim, sc->sc_swflags);
   1045   1.1    rumble 		delim = ',';
   1046   1.1    rumble 	}
   1047   1.1    rumble 
   1048   1.1    rumble #ifdef KGDB
   1049   1.1    rumble 	major = cdevsw_lookup_major(&scn_cdevsw);
   1050   1.1    rumble 	KASSERT(major != NODEVMAJOR);
   1051   1.1    rumble 	if (kgdb_dev == makedev(major, unit)) {
   1052   1.1    rumble 		if (console)
   1053   1.1    rumble 			kgdb_dev = NODEV; /* can't debug over console port */
   1054   1.1    rumble 		else {
   1055   1.1    rumble 			scninit(kgdb_dev, kgdb_rate);
   1056   1.1    rumble 			scn_rxenable(sc);
   1057   1.1    rumble 			scn->sc_iskgdb = 1;
   1058   1.1    rumble 			kgdb_attach(scncngetc, scncnputc, kgdb_dev);
   1059   1.1    rumble 			if (kgdb_debug_init) {
   1060   1.1    rumble 				printf("%c ", delim);
   1061   1.1    rumble 				kgdb_connect(1);
   1062   1.1    rumble 			} else
   1063   1.1    rumble 				printf("%c kgdb enabled", delim);
   1064   1.1    rumble 			delim = ',';
   1065   1.1    rumble 		}
   1066   1.1    rumble 	}
   1067   1.1    rumble #endif
   1068   1.1    rumble 	printf("\n");
   1069   1.1    rumble }
   1070   1.1    rumble 
   1071   1.1    rumble /* ARGSUSED */
   1072   1.1    rumble int
   1073   1.1    rumble scnopen(dev_t dev, int flags, int mode, struct lwp *l)
   1074   1.1    rumble {
   1075   1.1    rumble 	struct tty *tp;
   1076   1.1    rumble 	int unit = DEV_UNIT(dev);
   1077   1.1    rumble 	struct scn_softc *sc;
   1078   1.1    rumble 	int error = 0;
   1079   1.1    rumble 
   1080   1.1    rumble 	if (unit >= scn_cd.cd_ndevs)
   1081   1.1    rumble 		return ENXIO;
   1082   1.1    rumble 	sc = SOFTC(unit);
   1083   1.1    rumble 	if (!sc)
   1084   1.1    rumble 		return ENXIO;
   1085   1.1    rumble 
   1086   1.1    rumble 	tp = sc->sc_tty;
   1087   1.1    rumble 	if (!tp) {
   1088   1.3     rmind 		tp = tty_alloc();
   1089   1.1    rumble 		sc->sc_tty = sc->sc_duart->chan[sc->sc_channel].tty = tp;
   1090   1.1    rumble 		tty_attach(tp);
   1091   1.1    rumble 	}
   1092   1.1    rumble 
   1093   1.1    rumble 	tp->t_oproc = scnstart;
   1094   1.1    rumble 	tp->t_param = scnparam;
   1095   1.1    rumble 	tp->t_hwiflow = scnhwiflow;
   1096   1.1    rumble 	tp->t_dev = dev;
   1097   1.1    rumble 
   1098   1.1    rumble 	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
   1099   1.1    rumble 		return (EBUSY);
   1100   1.1    rumble 
   1101  1.10  riastrad 	ttylock(tp);
   1102   1.1    rumble 
   1103   1.1    rumble 	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
   1104   1.1    rumble 		ttychars(tp);
   1105   1.1    rumble 		tp->t_iflag = TTYDEF_IFLAG;
   1106   1.1    rumble 		tp->t_oflag = TTYDEF_OFLAG;
   1107   1.1    rumble 		tp->t_cflag = SCNDEF_CFLAG;
   1108   1.1    rumble 
   1109   1.1    rumble 		sc->sc_rx_blocked = 0;
   1110   1.1    rumble 
   1111   1.1    rumble 		if (sc->sc_swflags & SCN_SW_CLOCAL)
   1112   1.1    rumble 			tp->t_cflag |= CLOCAL;
   1113   1.1    rumble 		if (sc->sc_swflags & SCN_SW_CRTSCTS)
   1114   1.1    rumble 			tp->t_cflag |= CCTS_OFLOW | CRTS_IFLOW;
   1115   1.1    rumble 		tp->t_lflag = TTYDEF_LFLAG;
   1116   1.1    rumble 		if (sc->sc_isconsole)
   1117   1.1    rumble 			tp->t_ispeed = tp->t_ospeed = scnconsrate;
   1118   1.1    rumble 		else
   1119   1.1    rumble 			tp->t_ispeed = tp->t_ospeed = scndefaultrate;
   1120   1.1    rumble 		scnparam(tp, &tp->t_termios);
   1121   1.1    rumble 		ttsetwater(tp);
   1122   1.1    rumble 
   1123   1.1    rumble 		/* Turn on DTR and RTS. */
   1124   1.1    rumble 		SCN_OP_BIS(sc, sc->sc_op_rts | sc->sc_op_dtr);
   1125   1.1    rumble 
   1126   1.1    rumble 		/* enable receiver interrupts */
   1127   1.1    rumble 		scn_rxenable(sc);
   1128   1.1    rumble 
   1129   1.1    rumble 		/* set carrier state; */
   1130   1.1    rumble 		if ((sc->sc_swflags & SCN_SW_SOFTCAR) || /* check ttyflags */
   1131   1.1    rumble 		    SCN_DCD(sc) ||			 /* check h/w */
   1132   1.1    rumble 		    DEV_DIALOUT(dev))
   1133   1.1    rumble 			tp->t_state |= TS_CARR_ON;
   1134   1.1    rumble 		else
   1135   1.1    rumble 			tp->t_state &= ~TS_CARR_ON;
   1136   1.1    rumble 	}
   1137   1.1    rumble 
   1138  1.10  riastrad 	ttyunlock(tp);
   1139   1.1    rumble 
   1140   1.1    rumble 	error = ttyopen(tp, SCN_DIALOUT(sc), flags & O_NONBLOCK);
   1141   1.1    rumble if (error) printf("ttyopen failed line %d, error %d\n", __LINE__, error);
   1142   1.1    rumble 	if (error)
   1143   1.1    rumble 		goto bad;
   1144   1.1    rumble 
   1145   1.1    rumble 	error = (*tp->t_linesw->l_open) (dev, tp);
   1146   1.1    rumble if (error) printf("l_open failed line %d, error %d\n", __LINE__, error);
   1147   1.1    rumble 	if (error)
   1148   1.1    rumble 		goto bad;
   1149   1.1    rumble 
   1150   1.1    rumble 	return (0);
   1151   1.1    rumble 
   1152   1.1    rumble bad:
   1153   1.1    rumble 	if ((tp->t_state & TS_ISOPEN) == 0 && tp->t_wopen == 0) {
   1154   1.1    rumble 		scn_rxdisable(sc);
   1155   1.1    rumble 		SCN_OP_BIC(sc, sc->sc_op_rts | sc->sc_op_dtr);
   1156   1.1    rumble 	}
   1157   1.1    rumble 
   1158   1.1    rumble 	return (error);
   1159   1.1    rumble }
   1160   1.1    rumble 
   1161   1.1    rumble 
   1162   1.1    rumble /*ARGSUSED*/
   1163   1.1    rumble int
   1164   1.1    rumble scnclose(dev_t dev, int flags, int mode, struct lwp *l)
   1165   1.1    rumble {
   1166   1.1    rumble 	int unit = DEV_UNIT(dev);
   1167   1.1    rumble 	struct scn_softc *sc = SOFTC(unit);
   1168   1.1    rumble 	struct tty *tp = sc->sc_tty;
   1169   1.1    rumble 	devmajor_t major;
   1170   1.1    rumble 
   1171   1.1    rumble 	(void)major;
   1172   1.1    rumble 
   1173   1.1    rumble 	if ((tp->t_state & TS_ISOPEN) == 0)
   1174   1.1    rumble 		return 0;
   1175   1.1    rumble 
   1176   1.1    rumble 	(*tp->t_linesw->l_close) (tp, flags);
   1177   1.1    rumble 
   1178   1.1    rumble #ifdef KGDB
   1179   1.1    rumble 	/* do not disable interrupts if debugging */
   1180   1.1    rumble 	major = cdevsw_lookup_major(&scn_devsw);
   1181   1.1    rumble 	KASSERT(major != cdevsw_lookup_major);
   1182   1.1    rumble 	if (kgdb_dev != makedev(major, unit))
   1183   1.1    rumble #endif
   1184   1.1    rumble 		if ((tp->t_state & TS_ISOPEN) == 0) {
   1185   1.1    rumble 			scn_rxdisable(sc);
   1186   1.1    rumble 		}
   1187   1.1    rumble 	if ((tp->t_cflag & HUPCL) && (sc->sc_swflags & SCN_SW_SOFTCAR) == 0) {
   1188   1.1    rumble 		SCN_OP_BIC(sc, sc->sc_op_dtr);
   1189   1.1    rumble 		/* hold low for 1 second */
   1190   1.1    rumble 		tsleep(sc, TTIPRI, ttclos, hz);
   1191   1.1    rumble 	}
   1192   1.1    rumble 	SCN_CLRDIALOUT(sc);
   1193   1.1    rumble 	ttyclose(tp);
   1194   1.1    rumble 
   1195   1.1    rumble #if 0
   1196   1.1    rumble 	if ((tp->t_state & TS_ISOPEN) == 0) {
   1197   1.3     rmind 		tty_free(tp);
   1198   1.1    rumble 		sc->sc_tty = (struct tty *) NULL;
   1199   1.1    rumble 	}
   1200   1.1    rumble #endif
   1201   1.1    rumble 
   1202   1.1    rumble 	return (0);
   1203   1.1    rumble }
   1204   1.1    rumble 
   1205   1.1    rumble int
   1206   1.1    rumble scnread(dev_t dev, struct uio *uio, int flags)
   1207   1.1    rumble {
   1208   1.1    rumble 	struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
   1209   1.1    rumble 	struct tty *tp = sc->sc_tty;
   1210   1.1    rumble 
   1211   1.1    rumble 	return ((*tp->t_linesw->l_read) (tp, uio, flags));
   1212   1.1    rumble }
   1213   1.1    rumble 
   1214   1.1    rumble int
   1215   1.1    rumble scnwrite(dev_t dev, struct uio *uio, int flags)
   1216   1.1    rumble {
   1217   1.1    rumble 	struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
   1218   1.1    rumble 	struct tty *tp = sc->sc_tty;
   1219   1.1    rumble 
   1220   1.1    rumble 	return ((*tp->t_linesw->l_write) (tp, uio, flags));
   1221   1.1    rumble }
   1222   1.1    rumble 
   1223   1.1    rumble int
   1224   1.1    rumble scnpoll(dev_t dev, int events, struct lwp *l)
   1225   1.1    rumble {
   1226   1.1    rumble 	struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
   1227   1.1    rumble 	struct tty *tp = sc->sc_tty;
   1228   1.1    rumble 
   1229   1.1    rumble 	return ((*tp->t_linesw->l_poll)(tp, events, l));
   1230   1.1    rumble }
   1231   1.1    rumble 
   1232   1.1    rumble struct tty *
   1233   1.1    rumble scntty(dev_t dev)
   1234   1.1    rumble {
   1235   1.1    rumble 	struct scn_softc *sc = SOFTC(DEV_UNIT(dev));
   1236   1.1    rumble 
   1237   1.1    rumble 	return sc->sc_tty;
   1238   1.1    rumble }
   1239   1.1    rumble 
   1240   1.1    rumble /* Worker routines for interrupt processing */
   1241   1.1    rumble static inline void
   1242   1.1    rumble dcd_int(struct scn_softc *sc, struct tty *tp, u_char new)
   1243   1.1    rumble {
   1244   1.1    rumble 
   1245   1.1    rumble 	if (sc->sc_swflags & SCN_SW_SOFTCAR)
   1246   1.1    rumble 		return;
   1247   1.1    rumble 
   1248   1.1    rumble #if 0
   1249   1.1    rumble 	printf("scn%d: dcd_int ip %x SCN_DCD %x new %x ipcr %x\n",
   1250   1.1    rumble 	    sc->unit,
   1251   1.1    rumble 	    sc->sc_duart->base[DU_IP],
   1252   1.1    rumble 	    SCN_DCD(sc),
   1253   1.1    rumble 	    new,
   1254   1.1    rumble 	    sc->sc_duart->base[DU_IPCR]
   1255   1.1    rumble 	    );
   1256   1.1    rumble #endif
   1257   1.1    rumble 
   1258   1.1    rumble /* XXX set some flag to have some lower (soft) int call line discipline? */
   1259   1.1    rumble 	if (!(*tp->t_linesw->l_modem) (tp, new == 0? 1: 0)) {
   1260   1.1    rumble 		SCN_OP_BIC(sc, sc->sc_op_rts | sc->sc_op_dtr);
   1261   1.1    rumble 	}
   1262   1.1    rumble }
   1263   1.1    rumble 
   1264   1.1    rumble /*
   1265   1.1    rumble  * Print out a ring or fifo overrun error message.
   1266   1.1    rumble  */
   1267   1.1    rumble static void
   1268   1.1    rumble scnoverrun(int unit, long *ptime, const char *what)
   1269   1.1    rumble {
   1270   1.1    rumble 
   1271   1.1    rumble 	if (*ptime != time_second) {
   1272   1.1    rumble 		*ptime = time_second;
   1273   1.1    rumble 		log(LOG_WARNING, "scn%d: %s overrun\n", unit, what);
   1274   1.1    rumble 	}
   1275   1.1    rumble }
   1276   1.1    rumble 
   1277   1.1    rumble /*
   1278   1.1    rumble  * Try to block or unblock input using hardware flow-control.
   1279   1.1    rumble  * This is called by kern/tty.c if MDMBUF|CRTSCTS is set, and
   1280   1.1    rumble  * if this function returns non-zero, the TS_TBLOCK flag will
   1281   1.1    rumble  * be set or cleared according to the "stop" arg passed.
   1282   1.1    rumble  */
   1283   1.1    rumble int
   1284   1.1    rumble scnhwiflow(struct tty *tp, int stop)
   1285   1.1    rumble {
   1286   1.1    rumble 	int unit = DEV_UNIT(tp->t_dev);
   1287   1.1    rumble 	struct scn_softc *sc = SOFTC(unit);
   1288   1.1    rumble 	int s;
   1289   1.1    rumble 
   1290   1.1    rumble 	s = splrtty();
   1291   1.1    rumble 	if (!stop) {
   1292   1.1    rumble 		if (sc->sc_rbput - sc->sc_rbget - 1) {
   1293   1.1    rumble 			setsoftscn();
   1294   1.1    rumble 		}
   1295   1.1    rumble 	}
   1296   1.1    rumble 	splx(s);
   1297   1.1    rumble 	return 1;
   1298   1.1    rumble }
   1299   1.1    rumble 
   1300   1.1    rumble static int
   1301   1.1    rumble scnintr(void *arg)
   1302   1.1    rumble {
   1303   1.1    rumble 	struct duart *duart = arg;
   1304   1.1    rumble 	struct scn_softc *sc0 = duart->chan[0].sc;
   1305   1.1    rumble 	struct scn_softc *sc1 = duart->chan[1].sc;
   1306   1.1    rumble 
   1307   1.1    rumble 	struct tty *tp0 = (sc0 != NULL) ? sc0->sc_tty : NULL;
   1308   1.1    rumble 	struct tty *tp1 = (sc1 != NULL) ? sc1->sc_tty : NULL;
   1309   1.1    rumble 
   1310   1.1    rumble 	char rs_work;
   1311   1.1    rumble 	u_char rs_stat;
   1312   1.1    rumble 	u_char rs_ipcr;
   1313   1.1    rumble 
   1314   1.1    rumble 	/* Check for RX interrupts first, since we cannot distinguish by irq. */
   1315   1.1    rumble 	scnrxintr(duart);
   1316   1.1    rumble 
   1317   1.1    rumble 	do {
   1318   1.1    rumble 		/* Loop to pick up ALL pending interrupts for device. */
   1319   1.1    rumble 		rs_work = false;
   1320   1.1    rumble 		rs_stat = duart->base[DU_ISR];
   1321   1.1    rumble 
   1322   1.1    rumble /* channel a */
   1323   1.1    rumble 		if (tp0 != NULL) {
   1324   1.1    rumble 			if ((rs_stat & INT_TXA) && (tp0->t_state & TS_BUSY)) {
   1325   1.1    rumble 				/* output char done. */
   1326   1.1    rumble 				tp0->t_state &= ~(TS_BUSY | TS_FLUSH);
   1327   1.1    rumble 
   1328   1.1    rumble 				/* disable tx ints */
   1329   1.1    rumble 				duart->imr &= ~sc0->sc_tx_int;
   1330   1.1    rumble 				duart->base[DU_IMR] = duart->imr;
   1331   1.1    rumble 
   1332   1.1    rumble 				if (sc0->sc_heldchanges) {
   1333   1.1    rumble 					scn_setchip(sc0);
   1334   1.1    rumble 				}
   1335   1.1    rumble 
   1336   1.1    rumble 				(*tp0->t_linesw->l_start) (tp0);
   1337   1.1    rumble 				rs_work = true;
   1338   1.1    rumble 			}
   1339   1.1    rumble 		}
   1340   1.1    rumble 		/* channel b */
   1341   1.1    rumble 		if (tp1 != NULL) {
   1342   1.1    rumble 			if ((rs_stat & INT_TXB) && (tp1->t_state & TS_BUSY)) {
   1343   1.1    rumble 				/* output char done. */
   1344   1.1    rumble 				tp1->t_state &= ~(TS_BUSY | TS_FLUSH);
   1345   1.1    rumble 
   1346   1.1    rumble 				/* disable tx ints */
   1347   1.1    rumble 				duart->imr &= ~sc1->sc_tx_int;
   1348   1.1    rumble 				duart->base[DU_IMR] = duart->imr;
   1349   1.1    rumble 
   1350   1.1    rumble 				if (sc1->sc_heldchanges) {
   1351   1.1    rumble 					scn_setchip(sc1);
   1352   1.1    rumble 				}
   1353   1.1    rumble 
   1354   1.1    rumble 				(*tp1->t_linesw->l_start) (tp1);
   1355   1.1    rumble 				rs_work = true;
   1356   1.1    rumble 			}
   1357   1.1    rumble 		}
   1358   1.1    rumble 		if (rs_stat & INT_IP) {
   1359   1.1    rumble 			rs_work = true;
   1360   1.1    rumble 			rs_ipcr = duart->base[DU_IPCR];
   1361   1.1    rumble 
   1362   1.1    rumble 			if (rs_ipcr & IPCR_DELTA_DCDA && tp0 != NULL) {
   1363   1.1    rumble 				dcd_int(sc0, tp0, rs_ipcr & IPCR_DCDA);
   1364   1.1    rumble 			}
   1365   1.1    rumble 			if (rs_ipcr & IPCR_DELTA_DCDB && tp1 != NULL) {
   1366   1.1    rumble 				dcd_int(sc1, tp1, rs_ipcr & IPCR_DCDB);
   1367   1.1    rumble 			}
   1368   1.1    rumble 		}
   1369   1.1    rumble 	} while (rs_work);
   1370   1.1    rumble 
   1371   1.1    rumble 	return (1);	/* ? */
   1372   1.1    rumble }
   1373   1.1    rumble 
   1374   1.1    rumble /*
   1375   1.1    rumble  * Handle rxrdy/ffull interrupt: QUICKLY poll both channels (checking
   1376   1.1    rumble  * status first) and stash data in a ring buffer.  Ring buffer scheme
   1377   1.1    rumble  * borowed from sparc/zs.c requires NO interlock on data!
   1378   1.1    rumble  *
   1379   1.1    rumble  * This interrupt should NOT be included in spltty() mask since it
   1380   1.1    rumble  * invokes NO tty code!  The whole point is to allow tty input as much
   1381   1.1    rumble  * of the time as possible, while deferring "heavy" character
   1382   1.1    rumble  * processing until later.
   1383   1.1    rumble  *
   1384   1.1    rumble  * see scn.hw.README and scnsoft() for more info.
   1385   1.1    rumble  *
   1386   1.1    rumble  * THIS ROUTINE SHOULD BE KEPT AS CLEAN AS POSSIBLE!!
   1387   1.1    rumble  * IT'S A CANDIDATE FOR RECODING IN ASSEMBLER!!
   1388   1.1    rumble  */
   1389   1.1    rumble static inline int
   1390   1.1    rumble scn_rxintr(struct scn_softc *sc)
   1391   1.1    rumble {
   1392   1.1    rumble 	char sr;
   1393   1.1    rumble 	int i, n;
   1394   1.1    rumble 	int work;
   1395   1.1    rumble 
   1396   1.1    rumble 	work = 0;
   1397   1.1    rumble 	i = sc->sc_rbput;
   1398   1.1    rumble 	while (work <= 10) {
   1399   1.1    rumble #define SCN_GETCH(SC) \
   1400   1.1    rumble 		sr = (SC)->sc_chbase[CH_SR]; \
   1401   1.1    rumble 		if ((sr & SR_RX_RDY) == 0) \
   1402   1.1    rumble 			break; \
   1403   1.1    rumble 		if (sr & (SR_PARITY | SR_FRAME | SR_BREAK | SR_OVERRUN)) \
   1404   1.1    rumble 			goto exception; \
   1405   1.1    rumble 		work++; \
   1406   1.1    rumble 		(SC)->sc_rbuf[i++ & SCN_RING_MASK] = (SC)->sc_chbase[CH_DAT]
   1407   1.1    rumble 
   1408   1.1    rumble 		SCN_GETCH(sc); SCN_GETCH(sc); SCN_GETCH(sc);
   1409   1.1    rumble 		/* XXX more here if 26C92? -plb */
   1410   1.1    rumble 		continue;
   1411   1.1    rumble 	exception:
   1412   1.1    rumble #if defined(DDB)
   1413   1.1    rumble 		if (sc->sc_isconsole && (sr & SR_BREAK)) {
   1414   1.1    rumble 			Debugger();
   1415   1.1    rumble 			sr = sc->sc_chbase[CH_SR];
   1416   1.1    rumble 		}
   1417   1.1    rumble #endif
   1418   1.1    rumble #if defined(KGDB)
   1419   1.1    rumble 		if (sc->sc_iskgdb && (sr & SR_RX_RDY)) {
   1420   1.1    rumble 			kgdb_connect(1);
   1421   1.1    rumble 			sr = sc->sc_chbase[CH_SR];
   1422   1.1    rumble 		}
   1423   1.1    rumble #endif
   1424   1.1    rumble 		work++;
   1425   1.1    rumble 		sc->sc_rbuf[i++ & SCN_RING_MASK] = (sr << 8) | sc->sc_chbase[CH_DAT];
   1426   1.1    rumble 		sc->sc_chbase[CH_CR] = CR_CMD_RESET_ERR;	/* resets break? */
   1427   1.1    rumble 		RECOVER();
   1428   1.1    rumble 	}
   1429   1.1    rumble 	/*
   1430   1.1    rumble 	 * If ring is getting too full, try to block input.
   1431   1.1    rumble 	 */
   1432   1.1    rumble 	n = i - sc->sc_rbget;
   1433   1.1    rumble 	if (sc->sc_rbhiwat && (n > sc->sc_rbhiwat)) {
   1434   1.1    rumble 		/* If not CRTSCTS sc_rbhiwat is such that this
   1435   1.1    rumble 		 *  never happens.
   1436   1.1    rumble 		 * Clear RTS
   1437   1.1    rumble 		 */
   1438   1.1    rumble 		SCN_OP_BIC(sc, sc->sc_op_rts);
   1439   1.1    rumble 		sc->sc_rx_blocked = 1;
   1440   1.1    rumble 	}
   1441   1.1    rumble 	sc->sc_rbput = i;
   1442   1.1    rumble 
   1443   1.1    rumble 	return work;
   1444   1.1    rumble }
   1445   1.1    rumble 
   1446   1.1    rumble static void
   1447   1.1    rumble scnrxintr(void *arg)
   1448   1.1    rumble {
   1449   1.1    rumble 	struct duart *duart = arg;
   1450   1.1    rumble 	int work = 0;
   1451   1.1    rumble 
   1452   1.1    rumble 	if (duart->chan[0].sc != NULL)
   1453   1.1    rumble 		work += scn_rxintr(duart->chan[0].sc);
   1454   1.1    rumble 	if (duart->chan[1].sc != NULL)
   1455   1.1    rumble 		work += scn_rxintr(duart->chan[1].sc);
   1456   1.1    rumble 	if (work > 0) {
   1457   1.1    rumble 		setsoftscn();	/* trigger s/w intr */
   1458   1.1    rumble #ifdef SCN_TIMING
   1459   1.1    rumble 		microtime(&tstart);
   1460   1.1    rumble #endif
   1461   1.1    rumble 	}
   1462   1.1    rumble }
   1463   1.1    rumble 
   1464   1.1    rumble /*
   1465   1.1    rumble  * Here on soft interrupt (at spltty) to empty ring buffers.
   1466   1.1    rumble  *
   1467   1.1    rumble  * Dave's original scheme was to use the DUART receiver timeout
   1468   1.1    rumble  * interrupt. This requires 2692's (which my board doesn't have), and
   1469   1.1    rumble  * I also liked the idea of using the C/T to generate alternate and/or
   1470   1.1    rumble  * arbitrary bauds. -plb
   1471   1.1    rumble  *
   1472   1.1    rumble  * The ringbuffer code comes from Chris Torek's SPARC 44bsd zs driver
   1473   1.1    rumble  * (hence the LBL notice on top of this file), DOES NOT require
   1474   1.1    rumble  * interlocking with interrupt levels!
   1475   1.1    rumble  *
   1476   1.1    rumble  * The 44bsd sparc/zs driver reads the ring buffer from a separate
   1477   1.1    rumble  * zssoftint, while the SunOS 4.x zs driver appears to use
   1478   1.1    rumble  * timeout()'s.  timeouts seem to be too slow to deal with high data
   1479   1.1    rumble  * rates.  I know, I tried them.
   1480   1.1    rumble  * -plb.
   1481   1.1    rumble  */
   1482   1.1    rumble static void
   1483   1.1    rumble scnsoft(void *arg)
   1484   1.1    rumble {
   1485   1.1    rumble 	int s, unit;
   1486   1.1    rumble #ifdef SCN_TIMING
   1487   1.1    rumble 	struct timeval tend;
   1488   1.1    rumble 	u_long  t;
   1489   1.1    rumble 
   1490   1.1    rumble 	microtime(&tend);
   1491   1.1    rumble 	t = (tend.tv_sec - tstart.tv_sec) * 1000000 + (tend.tv_usec - tstart.tv_usec);
   1492   1.1    rumble 	t = (t + tick / 20) / (tick / 10);
   1493   1.1    rumble 	if (t >= NJITTER - 1) {
   1494   1.1    rumble 		t = NJITTER - 1;
   1495   1.1    rumble 	}
   1496   1.1    rumble 	scn_jitter[t]++;
   1497   1.1    rumble #endif
   1498   1.1    rumble 
   1499   1.1    rumble 	for (unit = 0; unit < scn_cd.cd_ndevs; unit++) {
   1500   1.1    rumble 		struct scn_softc *sc;
   1501   1.1    rumble 		struct tty *tp;
   1502   1.1    rumble 		int n, get;
   1503   1.1    rumble 
   1504   1.1    rumble 		sc = SOFTC(unit);
   1505   1.1    rumble 		if (sc == NULL) {
   1506   1.1    rumble 			continue;
   1507   1.1    rumble 		}
   1508   1.1    rumble 		tp = sc->sc_tty;
   1509   1.1    rumble #ifdef KGDB
   1510   1.1    rumble 		if (tp == NULL) {
   1511   1.1    rumble 			sc->sc_rbget = sc->sc_rbput;
   1512   1.1    rumble 			continue;
   1513   1.1    rumble 		}
   1514   1.1    rumble #endif
   1515   1.1    rumble 		if (tp == NULL || tp->t_state & TS_TBLOCK) {
   1516   1.1    rumble 			continue;
   1517   1.1    rumble 		}
   1518   1.1    rumble 
   1519   1.1    rumble 
   1520   1.1    rumble 		get = sc->sc_rbget;
   1521   1.1    rumble 
   1522   1.1    rumble 		/* NOTE: fetch from rbput is atomic */
   1523   1.1    rumble 		while (get != (n = sc->sc_rbput)) {
   1524   1.1    rumble 			/*
   1525   1.1    rumble 			 * Compute the number of interrupts in the receive ring.
   1526   1.1    rumble 			 * If the count is overlarge, we lost some events, and
   1527   1.1    rumble 			 * must advance to the first valid one.  It may get
   1528   1.1    rumble 			 * overwritten if more data are arriving, but this is
   1529   1.1    rumble 			 * too expensive to check and gains nothing (we already
   1530   1.1    rumble 			 * lost out; all we can do at this point is trade one
   1531   1.1    rumble 			 * kind of loss for another).
   1532   1.1    rumble 			 */
   1533   1.1    rumble 			n -= get;
   1534   1.1    rumble 			if (n > SCN_RING_SIZE) {
   1535   1.1    rumble 				scnoverrun(unit, &sc->sc_rotime, "ring");
   1536   1.1    rumble 				get += n - SCN_RING_SIZE;
   1537   1.1    rumble 				n = SCN_RING_SIZE;
   1538   1.1    rumble 				sc->sc_ring_overruns++;
   1539   1.1    rumble 			}
   1540   1.1    rumble 			while (--n >= 0) {
   1541   1.1    rumble 				int c, sr;
   1542   1.1    rumble 
   1543   1.1    rumble 				if (tp->t_state & TS_TBLOCK) {
   1544   1.1    rumble 					sc->sc_rbget = get;
   1545   1.1    rumble 					goto done;
   1546   1.1    rumble 				}
   1547   1.1    rumble 				/* Race to keep ahead of incoming interrupts. */
   1548   1.1    rumble 				c = sc->sc_rbuf[get++ & SCN_RING_MASK];
   1549   1.1    rumble 
   1550   1.1    rumble 				sr = c >> 8;	/* extract status */
   1551   1.1    rumble 				c &= 0xff;	/* leave just character */
   1552   1.1    rumble 
   1553   1.1    rumble 				if (sr & SR_OVERRUN) {
   1554   1.1    rumble 					scnoverrun(unit, &sc->sc_fotime, "fifo");
   1555   1.1    rumble 					sc->sc_fifo_overruns++;
   1556   1.1    rumble 				}
   1557   1.1    rumble 				if (sr & SR_PARITY) {
   1558   1.1    rumble 					c |= TTY_PE;
   1559   1.1    rumble 					sc->sc_parity_errors++;
   1560   1.1    rumble 				}
   1561   1.1    rumble 				if (sr & SR_FRAME) {
   1562   1.1    rumble 					c |= TTY_FE;
   1563   1.1    rumble 					sc->sc_framing_errors++;
   1564   1.1    rumble 				}
   1565   1.1    rumble 				if (sr & SR_BREAK) {
   1566   1.1    rumble #if 0
   1567   1.1    rumble 					/*
   1568   1.1    rumble 					 * See DDB_CHECK() comments in
   1569   1.1    rumble 					 * scnrxintr()
   1570   1.1    rumble 					 */
   1571   1.1    rumble 					if (sc->sc_isconsole)
   1572   1.1    rumble 						Debugger();
   1573   1.1    rumble #endif
   1574   1.1    rumble 					c = TTY_FE | 0;
   1575   1.1    rumble 					sc->sc_breaks++;
   1576   1.1    rumble 				}
   1577   1.1    rumble 
   1578   1.1    rumble 				(*tp->t_linesw->l_rint) (c, tp);
   1579   1.1    rumble 
   1580   1.1    rumble 				if (sc->sc_rx_blocked && n < SCN_RING_THRESH) {
   1581   1.1    rumble 					s = splrtty();
   1582   1.1    rumble 					sc->sc_rx_blocked = 0;
   1583   1.1    rumble 					SCN_OP_BIS(sc, sc->sc_op_rts);
   1584   1.1    rumble 					splx(s);
   1585   1.1    rumble 				}
   1586   1.1    rumble 
   1587   1.1    rumble 			}
   1588   1.1    rumble 			sc->sc_rbget = get;
   1589   1.1    rumble 		}
   1590   1.1    rumble 	done: ;
   1591   1.1    rumble 	}
   1592   1.1    rumble }
   1593   1.1    rumble 
   1594   1.1    rumble /* Convert TIOCM_xxx bits to output port bits. */
   1595   1.1    rumble static unsigned char
   1596   1.1    rumble opbits(struct scn_softc *sc, int tioc_bits)
   1597   1.1    rumble {
   1598   1.1    rumble 
   1599   1.1    rumble 	return ((((tioc_bits) & TIOCM_DTR) ? sc->sc_op_dtr : 0) |
   1600   1.1    rumble 	    (((tioc_bits) & TIOCM_RTS) ? sc->sc_op_rts : 0));
   1601   1.1    rumble }
   1602   1.1    rumble 
   1603   1.1    rumble int
   1604   1.1    rumble scnioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
   1605   1.1    rumble {
   1606   1.1    rumble 	int unit = DEV_UNIT(dev);
   1607   1.1    rumble 	struct scn_softc *sc = SOFTC(unit);
   1608   1.1    rumble 	struct tty *tp = sc->sc_tty;
   1609   1.1    rumble 	int error;
   1610   1.1    rumble 
   1611   1.1    rumble 	error = (*tp->t_linesw->l_ioctl) (tp, cmd, data, flags, l);
   1612   1.1    rumble 	if (error != EPASSTHROUGH)
   1613   1.1    rumble 		return (error);
   1614   1.1    rumble 
   1615   1.1    rumble 	error = ttioctl(tp, cmd, data, flags, l);
   1616   1.1    rumble 	if (error != EPASSTHROUGH)
   1617   1.1    rumble 		return (error);
   1618   1.1    rumble 
   1619   1.1    rumble 	switch (cmd) {
   1620   1.1    rumble 	case TIOCSBRK:
   1621   1.1    rumble 		sc->sc_chbase[CH_CR] = CR_CMD_START_BRK;
   1622   1.1    rumble 		break;
   1623   1.1    rumble 
   1624   1.1    rumble 	case TIOCCBRK:
   1625   1.1    rumble 		sc->sc_chbase[CH_CR] = CR_CMD_STOP_BRK;
   1626   1.1    rumble 		break;
   1627   1.1    rumble 
   1628   1.1    rumble 	case TIOCSDTR:
   1629   1.1    rumble 		SCN_OP_BIS(sc, sc->sc_op_dtr | sc->sc_op_rts);
   1630   1.1    rumble 		break;
   1631   1.1    rumble 
   1632   1.1    rumble 	case TIOCCDTR:
   1633   1.1    rumble 		SCN_OP_BIC(sc, sc->sc_op_dtr | sc->sc_op_rts);
   1634   1.1    rumble 		break;
   1635   1.1    rumble 
   1636   1.1    rumble 	case TIOCMSET: {
   1637   1.1    rumble 			int     s;
   1638   1.1    rumble 			unsigned char sbits, cbits;
   1639   1.1    rumble 
   1640   1.1    rumble 			/* set bits */
   1641   1.1    rumble 			sbits = opbits(sc, *(int *) data);
   1642   1.1    rumble 
   1643   1.1    rumble 			/* get bits to clear */
   1644   1.1    rumble 			cbits = ~sbits & (sc->sc_op_dtr | sc->sc_op_rts);
   1645   1.1    rumble 
   1646   1.1    rumble 			s = spltty();
   1647   1.1    rumble 			if (sbits) {
   1648   1.1    rumble 				SCN_OP_BIS(sc, sbits);
   1649   1.1    rumble 			}
   1650   1.1    rumble 			if (cbits) {
   1651   1.1    rumble 				SCN_OP_BIC(sc, cbits);
   1652   1.1    rumble 			}
   1653   1.1    rumble 			splx(s);
   1654   1.1    rumble 			break;
   1655   1.1    rumble 		}
   1656   1.1    rumble 
   1657   1.1    rumble 	case TIOCMBIS:
   1658   1.1    rumble 		SCN_OP_BIS(sc, opbits(sc, *(int *) data));
   1659   1.1    rumble 		break;
   1660   1.1    rumble 
   1661   1.1    rumble 	case TIOCMBIC:
   1662   1.1    rumble 		SCN_OP_BIC(sc, opbits(sc, *(int *) data));
   1663   1.1    rumble 		break;
   1664   1.1    rumble 
   1665   1.1    rumble 	case TIOCMGET: {
   1666   1.1    rumble 			int     bits;
   1667   1.6  christos 			unsigned char ip;
   1668   1.1    rumble 
   1669   1.1    rumble 			/* s = spltty(); */
   1670   1.1    rumble 			ip = sc->sc_duart->base[DU_IP];
   1671   1.1    rumble 			/* splx(s); */
   1672   1.1    rumble 
   1673   1.1    rumble 			bits = 0;
   1674   1.1    rumble 			if (ip & sc->sc_ip_dcd)
   1675   1.1    rumble 				bits |= TIOCM_CD;
   1676   1.1    rumble 			if (ip & sc->sc_ip_cts)
   1677   1.1    rumble 				bits |= TIOCM_CTS;
   1678   1.1    rumble 
   1679   1.1    rumble #if 0
   1680   1.6  christos 			/*
   1681   1.6  christos 			 * XXX sigh; cannot get op current state!! even if
   1682   1.6  christos 			 * maintained in private, RTS is done in h/w!!
   1683   1.6  christos 			 */
   1684   1.6  christos 			unsigned char op = 0;
   1685   1.1    rumble 			if (op & sc->sc_op_dtr)
   1686   1.1    rumble 				bits |= TIOCM_DTR;
   1687   1.1    rumble 			if (op & sc->sc_op_rts)
   1688   1.1    rumble 				bits |= TIOCM_RTS;
   1689   1.1    rumble #endif
   1690   1.1    rumble 
   1691   1.1    rumble 			*(int *) data = bits;
   1692   1.1    rumble 			break;
   1693   1.1    rumble 		}
   1694   1.1    rumble 
   1695   1.1    rumble 	case TIOCGFLAGS:{
   1696   1.1    rumble 			int     bits = 0;
   1697   1.1    rumble 
   1698   1.1    rumble 			if (sc->sc_swflags & SCN_SW_SOFTCAR)
   1699   1.1    rumble 				bits |= TIOCFLAG_SOFTCAR;
   1700   1.1    rumble 			if (sc->sc_swflags & SCN_SW_CLOCAL)
   1701   1.1    rumble 				bits |= TIOCFLAG_CLOCAL;
   1702   1.1    rumble 			if (sc->sc_swflags & SCN_SW_CRTSCTS)
   1703   1.1    rumble 				bits |= TIOCFLAG_CRTSCTS;
   1704   1.1    rumble 			if (sc->sc_swflags & SCN_SW_MDMBUF)
   1705   1.1    rumble 				bits |= TIOCFLAG_MDMBUF;
   1706   1.1    rumble 
   1707   1.1    rumble 			*(int *) data = bits;
   1708   1.1    rumble 			break;
   1709   1.1    rumble 		}
   1710   1.1    rumble 	case TIOCSFLAGS:{
   1711   1.1    rumble 			int     userbits, driverbits = 0;
   1712   1.1    rumble 
   1713   1.1    rumble 			error = kauth_authorize_device_tty(l->l_cred,
   1714   1.1    rumble 			    KAUTH_DEVICE_TTY_PRIVSET, tp);
   1715   1.1    rumble 			if (error != 0)
   1716   1.1    rumble 				return (EPERM);
   1717   1.1    rumble 
   1718   1.1    rumble 			userbits = *(int *) data;
   1719   1.1    rumble 			if (userbits & TIOCFLAG_SOFTCAR)
   1720   1.1    rumble 				driverbits |= SCN_SW_SOFTCAR;
   1721   1.1    rumble 			if (userbits & TIOCFLAG_CLOCAL)
   1722   1.1    rumble 				driverbits |= SCN_SW_CLOCAL;
   1723   1.1    rumble 			if (userbits & TIOCFLAG_CRTSCTS)
   1724   1.1    rumble 				driverbits |= SCN_SW_CRTSCTS;
   1725   1.1    rumble 			if (userbits & TIOCFLAG_MDMBUF)
   1726   1.1    rumble 				driverbits |= SCN_SW_MDMBUF;
   1727   1.1    rumble 
   1728   1.1    rumble 			sc->sc_swflags = driverbits;
   1729   1.1    rumble 
   1730   1.1    rumble 			break;
   1731   1.1    rumble 		}
   1732   1.1    rumble 
   1733   1.1    rumble 	default:
   1734   1.1    rumble 		return (EPASSTHROUGH);
   1735   1.1    rumble 	}
   1736   1.1    rumble 	return (0);
   1737   1.1    rumble }
   1738   1.1    rumble 
   1739   1.1    rumble int
   1740   1.1    rumble scnparam(struct tty *tp, struct termios *t)
   1741   1.1    rumble {
   1742   1.1    rumble 	int cflag = t->c_cflag;
   1743   1.1    rumble 	int unit = DEV_UNIT(tp->t_dev);
   1744   1.1    rumble 	char mr1, mr2;
   1745   1.1    rumble 	int error;
   1746   1.1    rumble 	struct scn_softc *sc = SOFTC(unit);
   1747   1.1    rumble 
   1748   1.1    rumble 	/* Is this a hang up? */
   1749   1.1    rumble 	if (t->c_ospeed == B0) {
   1750   1.1    rumble 		SCN_OP_BIC(sc, sc->sc_op_dtr);
   1751   1.1    rumble 		/* leave DTR down. see comment in scnclose() -plb */
   1752   1.1    rumble 		return (0);
   1753   1.1    rumble 	}
   1754   1.1    rumble 	mr1 = mr2 = 0;
   1755   1.1    rumble 
   1756   1.1    rumble 	/* Parity? */
   1757   1.1    rumble 	if (cflag & PARENB) {
   1758   1.1    rumble 		if ((cflag & PARODD) == 0)
   1759   1.1    rumble 			mr1 |= MR1_PEVEN;
   1760   1.1    rumble 		else
   1761   1.1    rumble 			mr1 |= MR1_PODD;
   1762   1.1    rumble 	} else
   1763   1.1    rumble 		mr1 |= MR1_PNONE;
   1764   1.1    rumble 
   1765   1.1    rumble 	/* Stop bits. */
   1766   1.1    rumble 	if (cflag & CSTOPB)
   1767   1.1    rumble 		mr2 |= MR2_STOP2;
   1768   1.1    rumble 	else
   1769   1.1    rumble 		mr2 |= MR2_STOP1;
   1770   1.1    rumble 
   1771   1.1    rumble 	/* Data bits. */
   1772   1.1    rumble 	switch (cflag & CSIZE) {
   1773   1.1    rumble 	case CS5:
   1774   1.1    rumble 		mr1 |= MR1_CS5;
   1775   1.1    rumble 		break;
   1776   1.1    rumble 	case CS6:
   1777   1.1    rumble 		mr1 |= MR1_CS6;
   1778   1.1    rumble 		break;
   1779   1.1    rumble 	case CS7:
   1780   1.1    rumble 		mr1 |= MR1_CS7;
   1781   1.1    rumble 		break;
   1782   1.1    rumble 	case CS8:
   1783   1.1    rumble 	default:
   1784   1.1    rumble 		mr1 |= MR1_CS8;
   1785   1.1    rumble 		break;
   1786   1.1    rumble 	}
   1787   1.1    rumble 
   1788   1.1    rumble 	if (cflag & CCTS_OFLOW)
   1789   1.1    rumble 		mr2 |= MR2_TXCTS;
   1790   1.1    rumble 
   1791   1.1    rumble 	if (cflag & CRTS_IFLOW) {
   1792   1.1    rumble 		mr1 |= MR1_RXRTS;
   1793   1.1    rumble 		sc->sc_rbhiwat = SCN_RING_HIWAT;
   1794   1.1    rumble 	} else {
   1795   1.1    rumble 		sc->sc_rbhiwat = 0;
   1796   1.1    rumble 	}
   1797   1.1    rumble 
   1798   1.1    rumble 	error = scn_config(unit, sc->sc_channel, t->c_ispeed,
   1799   1.1    rumble 	    t->c_ospeed, mr1, mr2);
   1800   1.1    rumble 
   1801   1.1    rumble 	/* If successful, copy to tty */
   1802   1.1    rumble 	if (!error) {
   1803   1.1    rumble 		tp->t_ispeed = t->c_ispeed;
   1804   1.1    rumble 		tp->t_ospeed = t->c_ospeed;
   1805   1.1    rumble 		tp->t_cflag = cflag;
   1806   1.1    rumble 	}
   1807   1.1    rumble 	return (error);
   1808   1.1    rumble }
   1809   1.1    rumble 
   1810   1.1    rumble /*
   1811   1.1    rumble  * Start or restart a transmission.
   1812   1.1    rumble  */
   1813   1.1    rumble void
   1814   1.1    rumble scnstart(struct tty *tp)
   1815   1.1    rumble {
   1816   1.1    rumble 	int s, c;
   1817   1.1    rumble 	int unit = DEV_UNIT(tp->t_dev);
   1818   1.1    rumble 	struct scn_softc *sc = SOFTC(unit);
   1819   1.1    rumble 
   1820   1.1    rumble 	s = spltty();
   1821   1.1    rumble 	if (tp->t_state & (TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
   1822   1.1    rumble 		goto out;
   1823   1.1    rumble 	if (!ttypull(tp))
   1824   1.1    rumble 		goto out;
   1825   1.1    rumble 
   1826   1.1    rumble 	tp->t_state |= TS_BUSY;
   1827   1.1    rumble 
   1828   1.1    rumble 	while (sc->sc_chbase[CH_SR] & SR_TX_RDY) {
   1829   1.1    rumble 		if ((c = getc(&tp->t_outq)) == -1)
   1830   1.1    rumble 			break;
   1831   1.1    rumble 		sc->sc_chbase[CH_DAT] = c;
   1832   1.1    rumble 	}
   1833   1.1    rumble 	sc->sc_duart->imr |= (sc->sc_tx_int | sc->sc_rx_int);
   1834   1.1    rumble 	sc->sc_duart->base[DU_IMR] = sc->sc_duart->imr;
   1835   1.1    rumble 
   1836   1.1    rumble out:
   1837   1.1    rumble 	splx(s);
   1838   1.1    rumble }
   1839   1.1    rumble 
   1840   1.1    rumble /*
   1841   1.1    rumble  * Stop output on a line.
   1842   1.1    rumble  */
   1843   1.1    rumble /*ARGSUSED*/
   1844   1.1    rumble void
   1845   1.1    rumble scnstop(struct tty *tp, int flags)
   1846   1.1    rumble {
   1847   1.1    rumble 	int s;
   1848   1.1    rumble 
   1849   1.1    rumble 	s = spltty();
   1850   1.1    rumble 	if (tp->t_state & TS_BUSY) {
   1851   1.1    rumble 		if ((tp->t_state & TS_TTSTOP) == 0)
   1852   1.1    rumble 			tp->t_state |= TS_FLUSH;
   1853   1.1    rumble 	}
   1854   1.1    rumble 	splx(s);
   1855   1.1    rumble }
   1856   1.1    rumble 
   1857   1.1    rumble /*
   1858   1.1    rumble  * Following are all routines needed for SCN to act as console.
   1859   1.1    rumble  */
   1860   1.1    rumble 
   1861   1.1    rumble void
   1862   1.1    rumble scncnprobe(struct consdev *cn)
   1863   1.1    rumble {
   1864   1.1    rumble }
   1865   1.1    rumble 
   1866   1.1    rumble void
   1867   1.1    rumble scncnreinit(void *v)
   1868   1.1    rumble {
   1869   1.1    rumble 	volatile u_char *du_base =
   1870   1.1    rumble 	    (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004);
   1871   1.1    rumble 
   1872   1.1    rumble 	du_base[DU_OPSET] =
   1873   1.1    rumble 	    SCN_CONSCHAN ? (OP_RTSB | OP_DTRB) : (OP_RTSA | OP_DTRA);
   1874   1.1    rumble }
   1875   1.1    rumble 
   1876   1.1    rumble void
   1877   1.1    rumble scncninit(struct consdev *cn)
   1878   1.1    rumble {
   1879   1.1    rumble 	devmajor_t major;
   1880   1.1    rumble 
   1881   1.1    rumble 	/* initialize required fields */
   1882   1.1    rumble 	major = cdevsw_lookup_major(&scn_cdevsw);
   1883   1.1    rumble 	KASSERT(major != NODEV);
   1884   1.1    rumble 	cn->cn_dev = makedev(major, SCN_CONSOLE);
   1885   1.1    rumble 	cn->cn_pri = CN_REMOTE;
   1886   1.1    rumble 
   1887   1.1    rumble 	scninit(cn->cn_dev, scnconsrate);
   1888   1.1    rumble }
   1889   1.1    rumble 
   1890   1.1    rumble /* Used by scncninit and kgdb startup. */
   1891   1.1    rumble int
   1892   1.1    rumble scninit(dev_t dev, int rate)
   1893   1.1    rumble {
   1894   1.1    rumble /* XXX - maintain PROM's settings */
   1895   1.1    rumble #if 0
   1896   1.1    rumble 	volatile u_char *du_base =
   1897   1.1    rumble 	    (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004);
   1898   1.1    rumble 	int unit = DEV_UNIT(dev);
   1899   1.1    rumble 
   1900   1.1    rumble 	du_base[DU_OPSET] =
   1901   1.1    rumble 	    SCN_CONSCHAN ? (OP_RTSB | OP_DTRB) : (OP_RTSA | OP_DTRA);
   1902   1.1    rumble 	scn_config(unit, SCN_CONSCHAN, rate, rate,
   1903   1.1    rumble 	    MR1_PNONE | MR1_CS8, MR2_STOP1);
   1904   1.1    rumble #endif
   1905   1.1    rumble 	return (0);
   1906   1.1    rumble }
   1907   1.1    rumble 
   1908   1.1    rumble /*
   1909   1.1    rumble  * Console kernel input character routine.
   1910   1.1    rumble  */
   1911   1.1    rumble int
   1912   1.1    rumble scncngetc(dev_t dev)
   1913   1.1    rumble {
   1914   1.1    rumble 	volatile u_char *ch_base =
   1915   1.1    rumble 	    (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004);
   1916   1.1    rumble 	char c;
   1917   1.1    rumble 	int s;
   1918   1.1    rumble 
   1919   1.1    rumble 	s = spltty();
   1920   1.1    rumble 
   1921   1.1    rumble 	while ((ch_base[CH_SR] & SR_RX_RDY) == 0)
   1922   1.1    rumble 		;
   1923   1.1    rumble 	c = ch_base[CH_DAT];
   1924   1.1    rumble 
   1925   1.1    rumble 	splx(s);
   1926   1.1    rumble 	return c;
   1927   1.1    rumble }
   1928   1.1    rumble 
   1929   1.1    rumble void
   1930   1.1    rumble scncnpollc(dev_t dev, int on)
   1931   1.1    rumble {
   1932   1.1    rumble }
   1933   1.1    rumble 
   1934   1.1    rumble /*
   1935   1.1    rumble  * Console kernel output character routine.
   1936   1.1    rumble  */
   1937   1.1    rumble void
   1938   1.1    rumble scncnputc(dev_t dev, int c)
   1939   1.1    rumble {
   1940   1.1    rumble 	volatile u_char *ch_base =
   1941   1.1    rumble 	    (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004);
   1942   1.1    rumble 	volatile u_char *du_base =
   1943   1.1    rumble 	    (volatile u_char *)MIPS_PHYS_TO_KSEG1(0x1fb80004);
   1944   1.1    rumble 	int s;
   1945   1.1    rumble 
   1946   1.1    rumble 	s = spltty();
   1947   1.1    rumble 
   1948   1.1    rumble 	if (c == '\n')
   1949   1.1    rumble 		scncnputc(dev, '\r');
   1950   1.1    rumble 
   1951   1.1    rumble 	while ((ch_base[CH_SR] & SR_TX_RDY) == 0)
   1952   1.1    rumble 		;
   1953   1.1    rumble 	ch_base[CH_DAT] = c;
   1954   1.1    rumble 	while ((ch_base[CH_SR] & SR_TX_RDY) == 0)
   1955   1.1    rumble 		;
   1956   1.1    rumble 	du_base[DU_ISR];
   1957   1.1    rumble 
   1958   1.1    rumble 	splx(s);
   1959   1.1    rumble }
   1960