Home | History | Annotate | Line # | Download | only in dev
mfc.c revision 1.10
      1  1.10  thorpej /*	$NetBSD: mfc.c,v 1.10 1996/03/17 01:17:43 thorpej Exp $ */
      2   1.3   chopps 
      3   1.1   chopps /*
      4   1.1   chopps  * Copyright (c) 1994 Michael L. Hitch
      5   1.1   chopps  * Copyright (c) 1982, 1990 The Regents of the University of California.
      6   1.1   chopps  * All rights reserved.
      7   1.1   chopps  *
      8   1.1   chopps  * Redistribution and use in source and binary forms, with or without
      9   1.1   chopps  * modification, are permitted provided that the following conditions
     10   1.1   chopps  * are met:
     11   1.1   chopps  * 1. Redistributions of source code must retain the above copyright
     12   1.1   chopps  *    notice, this list of conditions and the following disclaimer.
     13   1.1   chopps  * 2. Redistributions in binary form must reproduce the above copyright
     14   1.1   chopps  *    notice, this list of conditions and the following disclaimer in the
     15   1.1   chopps  *    documentation and/or other materials provided with the distribution.
     16   1.1   chopps  * 3. All advertising materials mentioning features or use of this software
     17   1.1   chopps  *    must display the following acknowledgement:
     18   1.1   chopps  *	This product includes software developed by the University of
     19   1.1   chopps  *	California, Berkeley and its contributors.
     20   1.1   chopps  * 4. Neither the name of the University nor the names of its contributors
     21   1.1   chopps  *    may be used to endorse or promote products derived from this software
     22   1.1   chopps  *    without specific prior written permission.
     23   1.1   chopps  *
     24   1.1   chopps  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     25   1.1   chopps  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26   1.1   chopps  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27   1.1   chopps  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     28   1.1   chopps  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29   1.1   chopps  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30   1.1   chopps  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31   1.1   chopps  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32   1.1   chopps  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33   1.1   chopps  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34   1.1   chopps  * SUCH DAMAGE.
     35   1.1   chopps  */
     36   1.1   chopps 
     37   1.1   chopps #include <sys/param.h>
     38   1.1   chopps #include <sys/systm.h>
     39   1.1   chopps #include <sys/kernel.h>
     40   1.1   chopps #include <sys/device.h>
     41   1.1   chopps #include <sys/tty.h>
     42   1.1   chopps #include <sys/proc.h>
     43   1.1   chopps #include <sys/conf.h>
     44   1.1   chopps #include <sys/file.h>
     45   1.1   chopps #include <sys/malloc.h>
     46   1.1   chopps #include <sys/uio.h>
     47   1.1   chopps #include <sys/kernel.h>
     48   1.1   chopps #include <sys/syslog.h>
     49   1.1   chopps #include <sys/queue.h>
     50   1.1   chopps #include <machine/cpu.h>
     51   1.1   chopps #include <amiga/amiga/device.h>
     52   1.2   chopps #include <amiga/amiga/isr.h>
     53   1.1   chopps #include <amiga/amiga/custom.h>
     54   1.1   chopps #include <amiga/amiga/cia.h>
     55   1.1   chopps #include <amiga/amiga/cc.h>
     56   1.2   chopps #include <amiga/dev/zbusvar.h>
     57   1.1   chopps 
     58   1.1   chopps #include <dev/cons.h>
     59   1.1   chopps 
     60   1.1   chopps #include "mfcs.h"
     61   1.1   chopps 
     62   1.7   chopps #ifndef SEROBUF_SIZE
     63   1.1   chopps #define SEROBUF_SIZE	128
     64   1.7   chopps #endif
     65   1.7   chopps #ifndef SERIBUF_SIZE
     66   1.1   chopps #define SERIBUF_SIZE	1024
     67   1.7   chopps #endif
     68   1.1   chopps 
     69   1.2   chopps #define splser()	spl6()
     70   1.2   chopps 
     71   1.2   chopps /*
     72   1.2   chopps  * 68581 DUART registers
     73   1.2   chopps  */
     74   1.1   chopps struct mfc_regs {
     75   1.1   chopps 	volatile u_char du_mr1a;
     76   1.1   chopps #define	du_mr2a		du_mr1a
     77   1.1   chopps 	u_char pad0;
     78   1.1   chopps 	volatile u_char du_csra;
     79   1.1   chopps #define	du_sra		du_csra
     80   1.1   chopps 	u_char pad2;
     81   1.1   chopps 	volatile u_char du_cra;
     82   1.1   chopps 	u_char pad4;
     83   1.1   chopps 	volatile u_char du_tba;
     84   1.1   chopps #define	du_rba		du_tba
     85   1.1   chopps 	u_char pad6;
     86   1.1   chopps 	volatile u_char du_acr;
     87   1.1   chopps #define	du_ipcr		du_acr
     88   1.1   chopps 	u_char pad8;
     89   1.1   chopps 	volatile u_char du_imr;
     90   1.1   chopps #define	du_isr		du_imr
     91   1.1   chopps 	u_char pad10;
     92   1.1   chopps 	volatile u_char du_ctur;
     93   1.1   chopps #define	du_cmsb		du_ctur
     94   1.1   chopps 	u_char pad12;
     95   1.1   chopps 	volatile u_char du_ctlr;
     96   1.1   chopps #define	du_clsb		du_ctlr
     97   1.1   chopps 	u_char pad14;
     98   1.1   chopps 	volatile u_char du_mr1b;
     99   1.1   chopps #define	du_mr2b		du_mr1b
    100   1.1   chopps 	u_char pad16;
    101   1.1   chopps 	volatile u_char du_csrb;
    102   1.1   chopps #define	du_srb		du_csrb
    103   1.1   chopps 	u_char pad18;
    104   1.1   chopps 	volatile u_char du_crb;
    105   1.1   chopps 	u_char pad20;
    106   1.1   chopps 	volatile u_char du_tbb;
    107   1.1   chopps #define	du_rbb		du_tbb
    108   1.1   chopps 	u_char pad22;
    109   1.1   chopps 	volatile u_char du_ivr;
    110   1.1   chopps 	u_char pad24;
    111   1.1   chopps 	volatile u_char du_opcr;
    112   1.1   chopps #define	du_ip		du_opcr
    113   1.1   chopps 	u_char pad26;
    114   1.1   chopps 	volatile u_char du_btst;
    115   1.1   chopps #define	du_strc		du_btst
    116   1.1   chopps 	u_char pad28;
    117   1.1   chopps 	volatile u_char du_btrst;
    118   1.1   chopps #define	du_stpc		du_btrst
    119   1.1   chopps 	u_char pad30;
    120   1.1   chopps };
    121   1.1   chopps 
    122   1.2   chopps /*
    123   1.2   chopps  * 68681 DUART serial port registers
    124   1.2   chopps  */
    125   1.1   chopps struct duart_regs {
    126   1.1   chopps 	volatile u_char ch_mr1;
    127   1.1   chopps #define	ch_mr2		ch_mr1
    128   1.1   chopps 	u_char pad0;
    129   1.1   chopps 	volatile u_char	ch_csr;
    130   1.1   chopps #define	ch_sr		ch_csr
    131   1.1   chopps 	u_char pad1;
    132   1.1   chopps 	volatile u_char	ch_cr;
    133   1.1   chopps 	u_char pad2;
    134   1.1   chopps 	volatile u_char	ch_tb;
    135   1.1   chopps #define	ch_rb		ch_tb
    136   1.1   chopps 	u_char pad3;
    137   1.1   chopps };
    138   1.1   chopps 
    139   1.1   chopps struct mfc_softc {
    140   1.1   chopps 	struct	device sc_dev;
    141   1.2   chopps 	struct	isr sc_isr;
    142   1.1   chopps 	struct	mfc_regs *sc_regs;
    143   1.1   chopps 	u_long	clk_frq;
    144   1.1   chopps 	u_short	ct_val;
    145   1.1   chopps 	u_char	ct_usecnt;
    146   1.1   chopps 	u_char	imask;
    147   1.1   chopps 	u_char	mfc_iii;
    148   1.1   chopps 	u_char	last_ip;
    149   1.1   chopps };
    150   1.1   chopps 
    151   1.2   chopps #if NMFCS > 0
    152   1.1   chopps struct mfcs_softc {
    153   1.1   chopps 	struct	device sc_dev;
    154   1.6   chopps 	struct	tty *sc_tty;
    155   1.1   chopps 	struct	duart_regs *sc_duart;
    156   1.1   chopps 	struct	mfc_regs *sc_regs;
    157   1.1   chopps 	struct	mfc_softc *sc_mfc;
    158   1.9      jtc 	int	swflags;
    159   1.1   chopps 	long	flags;			/* XXX */
    160   1.1   chopps #define CT_USED	1			/* CT in use */
    161   1.1   chopps 	u_short	*rptr, *wptr, incnt, ovfl;
    162   1.1   chopps 	u_short	inbuf[SERIBUF_SIZE];
    163   1.1   chopps 	char	*ptr, *end;
    164   1.1   chopps 	char	outbuf[SEROBUF_SIZE];
    165   1.9      jtc 	struct vbl_node vbl_node;
    166   1.1   chopps };
    167   1.2   chopps #endif
    168   1.2   chopps 
    169   1.2   chopps #if NMFCP > 0
    170   1.2   chopps struct mfcp_softc {
    171   1.2   chopps };
    172   1.2   chopps #endif
    173   1.1   chopps 
    174   1.1   chopps struct mfc_args {
    175   1.1   chopps 	struct zbus_args zargs;
    176   1.1   chopps 	char	*subdev;
    177   1.1   chopps 	char	unit;
    178   1.1   chopps };
    179   1.1   chopps 
    180   1.1   chopps int mfcprint __P((void *auxp, char *));
    181   1.1   chopps void mfcattach __P((struct device *, struct device *, void *));
    182  1.10  thorpej int mfcmatch __P((struct device *, void *, void *));
    183   1.2   chopps #if NMFCS > 0
    184   1.1   chopps void mfcsattach __P((struct device *, struct device *, void *));
    185  1.10  thorpej int mfcsmatch __P((struct device *, void *, void *));
    186   1.2   chopps #endif
    187   1.2   chopps #if NMFCP > 0
    188   1.2   chopps void mfcpattach __P((struct device *, struct device *, void *));
    189  1.10  thorpej int mfcpmatch __P((struct device *, void *, void *));
    190   1.2   chopps #endif
    191   1.2   chopps int mfcintr __P((struct mfc_softc *));
    192   1.1   chopps void mfcsmint __P((register int unit));
    193   1.1   chopps 
    194  1.10  thorpej struct mfc_ca = {
    195  1.10  thorpej 	sizeof(struct mfc_softc), mfcmatch, mfcattach
    196  1.10  thorpej };
    197  1.10  thorpej 
    198  1.10  thorpej struct cfdriver mfc_cd = {
    199  1.10  thorpej 	NULL, "mfc", DV_DULL, NULL, 0
    200  1.10  thorpej };
    201   1.1   chopps 
    202   1.2   chopps #if NMFCS > 0
    203  1.10  thorpej struct cfattach mfcs_ca = {
    204  1.10  thorpej 	sizeof(struct mfcs_softc), mfcsmatch, mfcsattach
    205  1.10  thorpej };
    206  1.10  thorpej 
    207  1.10  thorpej struct cfdriver mfcs_cd = {
    208  1.10  thorpej 	NULL, "mfcs", DV_TTY, NULL, 0
    209  1.10  thorpej };
    210   1.2   chopps #endif
    211   1.2   chopps 
    212   1.2   chopps #if NMFCP > 0
    213  1.10  thorpej struct cfattach mfcp_ca = {
    214  1.10  thorpej 	sizeof(struct mfcp_softc, mfcpmatch, mfcpattach
    215  1.10  thorpej };
    216  1.10  thorpej 
    217  1.10  thorpej struct cfdriver mfcp_cd = {
    218  1.10  thorpej 	NULL, "mfcp", DV_DULL, NULL, 0
    219  1.10  thorpej };
    220   1.2   chopps #endif
    221   1.1   chopps 
    222   1.1   chopps int	mfcsstart(), mfcsparam(), mfcshwiflow();
    223   1.1   chopps int	mfcs_active;
    224   1.1   chopps int	mfcsdefaultrate = 38400 /*TTYDEF_SPEED*/;
    225   1.9      jtc #define SWFLAGS(dev) (sc->swflags | (((dev) & 0x80) == 0 ? TIOCFLAG_SOFTCAR : 0))
    226   1.1   chopps 
    227   1.4   chopps #ifdef notyet
    228   1.4   chopps /*
    229   1.4   chopps  * MultiFaceCard III, II+ (not supported yet), and
    230   1.4   chopps  * SerialMaster 500+ (not supported yet)
    231   1.4   chopps  * baud rate tables for BRG set 1 [not used yet]
    232   1.4   chopps  */
    233   1.4   chopps 
    234   1.4   chopps struct speedtab mfcs3speedtab1[] = {
    235   1.4   chopps 	0,	0,
    236   1.4   chopps 	100,	0x00,
    237   1.4   chopps 	220,	0x11,
    238   1.4   chopps 	600,	0x44,
    239   1.4   chopps 	1200,	0x55,
    240   1.4   chopps 	2400,	0x66,
    241   1.4   chopps 	4800,	0x88,
    242   1.4   chopps 	9600,	0x99,
    243   1.4   chopps 	19200,	0xbb,
    244   1.4   chopps 	115200,	0xcc,
    245   1.4   chopps 	-1,	-1
    246   1.4   chopps };
    247   1.4   chopps 
    248   1.4   chopps /*
    249   1.4   chopps  * MultiFaceCard II, I, and SerialMaster 500
    250   1.4   chopps  * baud rate tables for BRG set 1 [not used yet]
    251   1.4   chopps  */
    252   1.4   chopps 
    253   1.4   chopps struct speedtab mfcs2speedtab1[] = {
    254   1.4   chopps 	0,	0,
    255   1.4   chopps 	50,	0x00,
    256   1.4   chopps 	110,	0x11,
    257   1.4   chopps 	300,	0x44,
    258   1.4   chopps 	600,	0x55,
    259   1.4   chopps 	1200,	0x66,
    260   1.4   chopps 	2400,	0x88,
    261   1.4   chopps  	4800,	0x99,
    262   1.4   chopps 	9600,	0xbb,
    263   1.4   chopps 	38400,	0xcc,
    264   1.4   chopps 	-1,	-1
    265   1.4   chopps };
    266   1.4   chopps #endif
    267   1.4   chopps 
    268   1.4   chopps /*
    269   1.4   chopps  * MultiFaceCard III, II+ (not supported yet), and
    270   1.4   chopps  * SerialMaster 500+ (not supported yet)
    271   1.4   chopps  * baud rate tables for BRG set 2
    272   1.4   chopps  */
    273   1.4   chopps 
    274   1.4   chopps struct speedtab mfcs3speedtab2[] = {
    275   1.1   chopps 	0,	0,
    276   1.1   chopps 	150,	0x00,
    277   1.1   chopps 	200,	0x11,
    278   1.1   chopps 	300,	0x33,
    279   1.1   chopps 	600,	0x44,
    280   1.1   chopps 	1200,	0x55,
    281   1.1   chopps 	2400,	0x66,
    282   1.1   chopps 	4800,	0x88,
    283   1.1   chopps 	9600,	0x99,
    284   1.1   chopps 	19200,	0xbb,
    285   1.1   chopps 	38400,	0xcc,
    286   1.1   chopps 	-1,	-1
    287   1.1   chopps };
    288   1.1   chopps 
    289   1.4   chopps /*
    290   1.4   chopps  * MultiFaceCard II, I, and SerialMaster 500
    291   1.4   chopps  * baud rate tables for BRG set 2
    292   1.4   chopps  */
    293   1.4   chopps 
    294   1.4   chopps struct speedtab mfcs2speedtab2[] = {
    295   1.1   chopps 	0,	0,
    296   1.1   chopps 	75,	0x00,
    297   1.1   chopps 	100,	0x11,
    298   1.1   chopps 	150,	0x33,
    299   1.1   chopps 	300,	0x44,
    300   1.1   chopps 	600,	0x55,
    301   1.1   chopps 	1200,	0x66,
    302   1.1   chopps 	2400,	0x88,
    303   1.1   chopps  	4800,	0x99,
    304   1.1   chopps 	9600,	0xbb,
    305   1.1   chopps 	19200,	0xcc,
    306   1.1   chopps 	-1,	-1
    307   1.1   chopps };
    308   1.1   chopps 
    309   1.1   chopps /*
    310   1.1   chopps  * if we are an bsc/Alf Data MultFaceCard (I, II, and III)
    311   1.1   chopps  */
    312   1.1   chopps int
    313  1.10  thorpej mfcmatch(pdp, match, auxp)
    314   1.1   chopps 	struct device *pdp;
    315  1.10  thorpej 	void *match, *auxp;
    316   1.1   chopps {
    317  1.10  thorpej 	struct cfdata *cdp = match;
    318   1.1   chopps 	struct zbus_args *zap;
    319   1.1   chopps 
    320   1.1   chopps 	zap = auxp;
    321   1.1   chopps 	if (zap->manid == 2092 &&
    322   1.1   chopps 	    (zap->prodid == 16 || zap->prodid == 17 || zap->prodid == 18))
    323   1.2   chopps 
    324   1.1   chopps 		return(1);
    325   1.1   chopps 	return(0);
    326   1.1   chopps }
    327   1.1   chopps 
    328   1.1   chopps void
    329   1.1   chopps mfcattach(pdp, dp, auxp)
    330   1.1   chopps 	struct device *pdp, *dp;
    331   1.1   chopps 	void *auxp;
    332   1.1   chopps {
    333   1.1   chopps 	struct mfc_softc *scc;
    334   1.1   chopps 	struct zbus_args *zap;
    335   1.1   chopps 	struct mfc_args ma;
    336   1.1   chopps 	int unit;
    337   1.1   chopps 	struct mfc_regs *rp;
    338   1.1   chopps 
    339   1.1   chopps 	zap = auxp;
    340   1.2   chopps 
    341   1.1   chopps 	printf ("\n");
    342   1.1   chopps 
    343   1.1   chopps 	scc = (struct mfc_softc *)dp;
    344   1.1   chopps 	unit = scc->sc_dev.dv_unit;
    345   1.1   chopps 	scc->sc_regs = rp = zap->va;
    346   1.1   chopps 	if (zap->prodid == 18)
    347   1.1   chopps 		scc->mfc_iii = 3;
    348   1.1   chopps 	scc->clk_frq = scc->mfc_iii ? 230400 : 115200;
    349   1.1   chopps 
    350   1.1   chopps 	rp->du_opcr = 0x00;		/* configure output port? */
    351   1.1   chopps 	rp->du_btrst = 0x0f;		/* clear modem lines */
    352   1.1   chopps 	rp->du_ivr = 0;			/* IVR */
    353   1.1   chopps 	rp->du_imr = 0;			/* IMR */
    354   1.1   chopps 	rp->du_acr = 0xe0;		/* baud rate generate set 2 */
    355   1.1   chopps 	rp->du_ctur = 0;
    356   1.1   chopps 	rp->du_ctlr = 4;
    357   1.1   chopps 	rp->du_csra = 0xcc;		/* clock select = 38400 */
    358   1.1   chopps 	rp->du_cra = 0x10;		/* reset mode register ptr */
    359   1.1   chopps 	rp->du_cra = 0x20;
    360   1.1   chopps 	rp->du_cra = 0x30;
    361   1.1   chopps 	rp->du_cra = 0x40;
    362   1.1   chopps 	rp->du_mr1a = 0x93;		/* MRA1 */
    363   1.1   chopps 	rp->du_mr2a = 0x17;		/* MRA2 */
    364   1.1   chopps 	rp->du_csrb = 0xcc;		/* clock select = 38400 */
    365   1.1   chopps 	rp->du_crb = 0x10;		/* reset mode register ptr */
    366   1.1   chopps 	rp->du_crb = 0x20;
    367   1.1   chopps 	rp->du_crb = 0x30;
    368   1.1   chopps 	rp->du_crb = 0x40;
    369   1.1   chopps 	rp->du_mr1b = 0x93;		/* MRB1 */
    370   1.1   chopps 	rp->du_mr2b = 0x17;		/* MRB2 */
    371   1.1   chopps 	rp->du_cra = 0x05;		/* enable A Rx & Tx */
    372   1.1   chopps 	rp->du_crb = 0x05;		/* enable B Rx & Tx */
    373   1.1   chopps 
    374   1.2   chopps 	scc->sc_isr.isr_intr = mfcintr;
    375   1.2   chopps 	scc->sc_isr.isr_arg = scc;
    376   1.2   chopps 	scc->sc_isr.isr_ipl = 6;
    377   1.2   chopps 	add_isr(&scc->sc_isr);
    378   1.1   chopps 
    379   1.1   chopps 	/* configure ports */
    380   1.1   chopps 	bcopy(zap, &ma.zargs, sizeof(struct zbus_args));
    381   1.1   chopps 	ma.subdev = "mfcs";
    382   1.1   chopps 	ma.unit = unit * 2;
    383   1.1   chopps 	config_found(dp, &ma, mfcprint);
    384   1.1   chopps 	ma.unit = unit * 2 + 1;
    385   1.1   chopps 	config_found(dp, &ma, mfcprint);
    386   1.1   chopps 	ma.subdev = "mfcp";
    387   1.1   chopps 	ma.unit = unit;
    388   1.1   chopps 	config_found(dp, &ma, mfcprint);
    389   1.1   chopps }
    390   1.1   chopps 
    391   1.1   chopps /*
    392   1.2   chopps  *
    393   1.1   chopps  */
    394   1.1   chopps int
    395  1.10  thorpej mfcsmatch(pdp, match, auxp)
    396   1.1   chopps 	struct device *pdp;
    397  1.10  thorpej 	void *match, *auxp;
    398   1.1   chopps {
    399  1.10  thorpej 	struct cfdata *cdp = match;
    400   1.1   chopps 	struct mfc_args *ma;
    401   1.1   chopps 
    402   1.1   chopps 	ma = auxp;
    403   1.1   chopps 	if (strcmp(ma->subdev, "mfcs") == 0)
    404   1.1   chopps 		return (1);
    405   1.1   chopps 	return (0);
    406   1.1   chopps }
    407   1.1   chopps 
    408   1.1   chopps void
    409   1.1   chopps mfcsattach(pdp, dp, auxp)
    410   1.1   chopps 	struct device *pdp, *dp;
    411   1.1   chopps 	void *auxp;
    412   1.1   chopps {
    413   1.1   chopps 	int unit;
    414   1.1   chopps 	struct mfcs_softc *sc;
    415   1.1   chopps 	struct mfc_softc *scc;
    416   1.1   chopps 	struct mfc_args *ma;
    417   1.1   chopps 	struct mfc_regs *rp;
    418   1.1   chopps 
    419   1.1   chopps 	sc = (struct mfcs_softc *) dp;
    420   1.1   chopps 	scc = (struct mfc_softc *) pdp;
    421   1.1   chopps 	ma = auxp;
    422   1.1   chopps 
    423   1.1   chopps 	if (dp) {
    424   1.1   chopps 		printf (": input fifo %d output fifo %d\n", SERIBUF_SIZE,
    425   1.1   chopps 		    SEROBUF_SIZE);
    426   1.1   chopps 		alloc_sicallback();
    427   1.1   chopps 	}
    428   1.1   chopps 
    429   1.1   chopps 	unit = ma->unit;
    430   1.1   chopps 	mfcs_active |= 1 << unit;
    431   1.1   chopps 	sc->rptr = sc->wptr = sc->inbuf;
    432   1.1   chopps 	sc->sc_mfc = scc;
    433   1.1   chopps 	sc->sc_regs = rp = scc->sc_regs;
    434   1.1   chopps 	sc->sc_duart = (struct duart_regs *) ((unit & 1) ? &rp->du_mr1b :
    435   1.1   chopps 	    &rp->du_mr1a);
    436   1.1   chopps 	/*
    437   1.1   chopps 	 * should have only one vbl routine to handle all ports?
    438   1.1   chopps 	 */
    439   1.9      jtc 	sc->vbl_node.function = (void (*) (void *)) mfcsmint;
    440   1.9      jtc 	sc->vbl_node.data = (void *) unit;
    441   1.9      jtc 	add_vbl_function(&sc->vbl_node, 1, (void *) unit);
    442   1.1   chopps }
    443   1.1   chopps 
    444   1.1   chopps /*
    445   1.1   chopps  * print diag if pnp is NULL else just extra
    446   1.1   chopps  */
    447   1.1   chopps int
    448   1.1   chopps mfcprint(auxp, pnp)
    449   1.1   chopps 	void *auxp;
    450   1.1   chopps 	char *pnp;
    451   1.1   chopps {
    452   1.1   chopps 	if (pnp == NULL)
    453   1.1   chopps 		return(UNCONF);
    454   1.1   chopps 	return(QUIET);
    455   1.1   chopps }
    456   1.1   chopps 
    457   1.1   chopps int
    458   1.1   chopps mfcsopen(dev, flag, mode, p)
    459   1.1   chopps 	dev_t dev;
    460   1.1   chopps 	int flag, mode;
    461   1.1   chopps 	struct proc *p;
    462   1.1   chopps {
    463   1.1   chopps 	struct tty *tp;
    464   1.6   chopps 	struct mfcs_softc *sc;
    465   1.1   chopps 	int unit, error, s;
    466   1.1   chopps 
    467   1.1   chopps 	error = 0;
    468   1.1   chopps 	unit = dev & 0x1f;
    469   1.1   chopps 
    470  1.10  thorpej 	if (unit >= mfcs_cd.cd_ndevs || (mfcs_active & (1 << unit)) == 0)
    471   1.1   chopps 		return (ENXIO);
    472  1.10  thorpej 	sc = mfcs_cd.cd_devs[unit];
    473   1.1   chopps 
    474   1.1   chopps 	s = spltty();
    475   1.1   chopps 
    476   1.6   chopps 	if (sc->sc_tty)
    477   1.6   chopps 		tp = sc->sc_tty;
    478   1.1   chopps 	else
    479   1.6   chopps 		tp = sc->sc_tty = ttymalloc();
    480   1.1   chopps 
    481   1.1   chopps 	tp->t_oproc = (void (*) (struct tty *)) mfcsstart;
    482   1.1   chopps 	tp->t_param = mfcsparam;
    483   1.1   chopps 	tp->t_dev = dev;
    484   1.1   chopps 	tp->t_hwiflow = mfcshwiflow;
    485   1.1   chopps 
    486   1.1   chopps 	if ((tp->t_state & TS_ISOPEN) == 0) {
    487   1.1   chopps 		tp->t_state |= TS_WOPEN;
    488   1.1   chopps 		ttychars(tp);
    489   1.1   chopps 		if (tp->t_ispeed == 0) {
    490   1.1   chopps 			/*
    491   1.1   chopps 			 * only when cleared do we reset to defaults.
    492   1.1   chopps 			 */
    493   1.1   chopps 			tp->t_iflag = TTYDEF_IFLAG;
    494   1.1   chopps 			tp->t_oflag = TTYDEF_OFLAG;
    495   1.1   chopps 			tp->t_cflag = TTYDEF_CFLAG;
    496   1.1   chopps 			tp->t_lflag = TTYDEF_LFLAG;
    497   1.1   chopps 			tp->t_ispeed = tp->t_ospeed = mfcsdefaultrate;
    498   1.1   chopps 		}
    499   1.1   chopps 		/*
    500   1.1   chopps 		 * do these all the time
    501   1.1   chopps 		 */
    502   1.9      jtc 		if (sc->swflags & TIOCFLAG_CLOCAL)
    503   1.1   chopps 			tp->t_cflag |= CLOCAL;
    504   1.9      jtc 		if (sc->swflags & TIOCFLAG_CRTSCTS)
    505   1.1   chopps 			tp->t_cflag |= CRTSCTS;
    506   1.9      jtc 		if (sc->swflags & TIOCFLAG_MDMBUF)
    507   1.1   chopps 			tp->t_cflag |= MDMBUF;
    508   1.1   chopps 		mfcsparam(tp, &tp->t_termios);
    509   1.1   chopps 		ttsetwater(tp);
    510   1.2   chopps 
    511   1.1   chopps 		(void)mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
    512   1.2   chopps 		if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) ||
    513   1.1   chopps 		    (mfcsmctl(dev, 0, DMGET) & TIOCM_CD))
    514   1.1   chopps 			tp->t_state |= TS_CARR_ON;
    515   1.1   chopps 		else
    516   1.1   chopps 			tp->t_state &= ~TS_CARR_ON;
    517   1.1   chopps 	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
    518   1.1   chopps 		splx(s);
    519   1.1   chopps 		return(EBUSY);
    520   1.1   chopps 	}
    521   1.1   chopps 
    522   1.1   chopps 	/*
    523   1.1   chopps 	 * if NONBLOCK requested, ignore carrier
    524   1.1   chopps 	 */
    525   1.1   chopps 	if (flag & O_NONBLOCK)
    526   1.1   chopps 		goto done;
    527   1.1   chopps 
    528   1.1   chopps 	/*
    529   1.1   chopps 	 * block waiting for carrier
    530   1.1   chopps 	 */
    531   1.1   chopps 	while ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
    532   1.1   chopps 		tp->t_state |= TS_WOPEN;
    533   1.2   chopps 		error = ttysleep(tp, (caddr_t)&tp->t_rawq,
    534   1.1   chopps 		    TTIPRI | PCATCH, ttopen, 0);
    535   1.1   chopps 		if (error) {
    536   1.1   chopps 			splx(s);
    537   1.1   chopps 			return(error);
    538   1.1   chopps 		}
    539   1.1   chopps 	}
    540   1.1   chopps done:
    541   1.1   chopps 	/* This is a way to handle lost XON characters */
    542   1.1   chopps 	if ((flag & O_TRUNC) && (tp->t_state & TS_TTSTOP)) {
    543   1.1   chopps 		tp->t_state &= ~TS_TTSTOP;
    544   1.1   chopps 	        ttstart (tp);
    545   1.1   chopps 	}
    546   1.1   chopps 
    547   1.1   chopps 	splx(s);
    548   1.1   chopps 	/*
    549   1.1   chopps 	 * Reset the tty pointer, as there could have been a dialout
    550   1.1   chopps 	 * use of the tty with a dialin open waiting.
    551   1.1   chopps 	 */
    552   1.1   chopps 	tp->t_dev = dev;
    553   1.1   chopps 	return((*linesw[tp->t_line].l_open)(dev, tp));
    554   1.1   chopps }
    555   1.1   chopps 
    556   1.1   chopps /*ARGSUSED*/
    557   1.1   chopps int
    558   1.1   chopps mfcsclose(dev, flag, mode, p)
    559   1.1   chopps 	dev_t dev;
    560   1.1   chopps 	int flag, mode;
    561   1.1   chopps 	struct proc *p;
    562   1.1   chopps {
    563   1.1   chopps 	struct tty *tp;
    564   1.1   chopps 	int unit;
    565  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
    566   1.1   chopps 	struct mfc_softc *scc= sc->sc_mfc;
    567   1.1   chopps 
    568   1.1   chopps 	unit = dev & 31;
    569   1.1   chopps 
    570   1.6   chopps 	tp = sc->sc_tty;
    571   1.1   chopps 	(*linesw[tp->t_line].l_close)(tp, flag);
    572   1.1   chopps 	sc->sc_duart->ch_cr = 0x70;			/* stop break */
    573   1.1   chopps 
    574   1.1   chopps 	scc->imask &= ~(0x7 << ((unit & 1) * 4));
    575   1.1   chopps 	scc->sc_regs->du_imr = scc->imask;
    576   1.1   chopps 	if (sc->flags & CT_USED) {
    577   1.1   chopps 		--scc->ct_usecnt;
    578   1.1   chopps 		sc->flags &= ~CT_USED;
    579   1.1   chopps 	}
    580   1.1   chopps 
    581   1.1   chopps 	/*
    582   1.1   chopps 	 * If the device is closed, it's close, no matter whether we deal with
    583   1.1   chopps 	 * modem control signals nor not.
    584   1.1   chopps 	 */
    585   1.1   chopps #if 0
    586   1.1   chopps 	if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
    587   1.1   chopps 	    (tp->t_state & TS_ISOPEN) == 0)
    588   1.1   chopps #endif
    589   1.1   chopps 		(void) mfcsmctl(dev, 0, DMSET);
    590   1.1   chopps 	ttyclose(tp);
    591   1.1   chopps #if not_yet
    592   1.1   chopps 	if (tp != &mfcs_cons) {
    593   1.9      jtc 		remove_vbl_function(&sc->vbl_node);
    594   1.1   chopps 		ttyfree(tp);
    595   1.6   chopps 		sc->sc_tty = (struct tty *) NULL;
    596   1.1   chopps 	}
    597   1.1   chopps #endif
    598   1.1   chopps 	return (0);
    599   1.1   chopps }
    600   1.1   chopps 
    601   1.1   chopps int
    602   1.1   chopps mfcsread(dev, uio, flag)
    603   1.1   chopps 	dev_t dev;
    604   1.1   chopps 	struct uio *uio;
    605   1.1   chopps 	int flag;
    606   1.1   chopps {
    607  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
    608   1.6   chopps 	struct tty *tp = sc->sc_tty;
    609   1.6   chopps 	if (tp == NULL)
    610   1.1   chopps 		return(ENXIO);
    611   1.1   chopps 	return((*linesw[tp->t_line].l_read)(tp, uio, flag));
    612   1.1   chopps }
    613   1.1   chopps 
    614   1.1   chopps int
    615   1.1   chopps mfcswrite(dev, uio, flag)
    616   1.1   chopps 	dev_t dev;
    617   1.1   chopps 	struct uio *uio;
    618   1.1   chopps 	int flag;
    619   1.1   chopps {
    620  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
    621   1.6   chopps 	struct tty *tp = sc->sc_tty;
    622   1.1   chopps 
    623   1.6   chopps 	if (tp == NULL)
    624   1.1   chopps 		return(ENXIO);
    625   1.1   chopps 	return((*linesw[tp->t_line].l_write)(tp, uio, flag));
    626   1.1   chopps }
    627   1.5   chopps 
    628   1.5   chopps struct tty *
    629   1.5   chopps mfcstty(dev)
    630   1.5   chopps 	dev_t dev;
    631   1.5   chopps {
    632  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
    633   1.6   chopps 
    634   1.6   chopps 	return (sc->sc_tty);
    635   1.5   chopps }
    636   1.5   chopps 
    637   1.1   chopps int
    638   1.1   chopps mfcsioctl(dev, cmd, data, flag, p)
    639   1.1   chopps 	dev_t	dev;
    640   1.1   chopps 	caddr_t data;
    641   1.1   chopps 	struct proc *p;
    642   1.1   chopps {
    643   1.1   chopps 	register struct tty *tp;
    644   1.1   chopps 	register int unit = dev & 31;
    645   1.1   chopps 	register int error;
    646  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
    647   1.1   chopps 
    648   1.6   chopps 	tp = sc->sc_tty;
    649   1.1   chopps 	if (!tp)
    650   1.1   chopps 		return ENXIO;
    651   1.1   chopps 
    652   1.1   chopps 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    653   1.1   chopps 	if (error >= 0)
    654   1.1   chopps 		return(error);
    655   1.1   chopps 
    656   1.1   chopps 	error = ttioctl(tp, cmd, data, flag, p);
    657   1.1   chopps 	if (error >= 0)
    658   1.1   chopps 		return(error);
    659   1.1   chopps 
    660   1.1   chopps 	switch (cmd) {
    661   1.1   chopps 	case TIOCSBRK:
    662   1.1   chopps 		sc->sc_duart->ch_cr = 0x60;		/* start break */
    663   1.1   chopps 		break;
    664   1.1   chopps 
    665   1.1   chopps 	case TIOCCBRK:
    666   1.1   chopps 		sc->sc_duart->ch_cr = 0x70;		/* stop break */
    667   1.1   chopps 		break;
    668   1.1   chopps 
    669   1.1   chopps 	case TIOCSDTR:
    670   1.1   chopps 		(void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
    671   1.1   chopps 		break;
    672   1.1   chopps 
    673   1.1   chopps 	case TIOCCDTR:
    674   1.1   chopps 		(void) mfcsmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
    675   1.1   chopps 		break;
    676   1.1   chopps 
    677   1.1   chopps 	case TIOCMSET:
    678   1.1   chopps 		(void) mfcsmctl(dev, *(int *) data, DMSET);
    679   1.1   chopps 		break;
    680   1.1   chopps 
    681   1.1   chopps 	case TIOCMBIS:
    682   1.1   chopps 		(void) mfcsmctl(dev, *(int *) data, DMBIS);
    683   1.1   chopps 		break;
    684   1.1   chopps 
    685   1.1   chopps 	case TIOCMBIC:
    686   1.1   chopps 		(void) mfcsmctl(dev, *(int *) data, DMBIC);
    687   1.1   chopps 		break;
    688   1.1   chopps 
    689   1.1   chopps 	case TIOCMGET:
    690   1.1   chopps 		*(int *)data = mfcsmctl(dev, 0, DMGET);
    691   1.1   chopps 		break;
    692   1.1   chopps 	case TIOCGFLAGS:
    693   1.1   chopps 		*(int *)data = SWFLAGS(dev);
    694   1.1   chopps 		break;
    695   1.1   chopps 	case TIOCSFLAGS:
    696   1.2   chopps 		error = suser(p->p_ucred, &p->p_acflag);
    697   1.1   chopps 		if (error != 0)
    698   1.2   chopps 			return(EPERM);
    699   1.1   chopps 
    700   1.9      jtc 		sc->swflags = *(int *)data;
    701   1.9      jtc                 sc->swflags &= /* only allow valid flags */
    702   1.1   chopps                   (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
    703   1.4   chopps 		/* XXXX need to change duart parameters? */
    704   1.1   chopps 		break;
    705   1.1   chopps 	default:
    706   1.1   chopps 		return(ENOTTY);
    707   1.1   chopps 	}
    708   1.1   chopps 
    709   1.1   chopps 	return(0);
    710   1.1   chopps }
    711   1.1   chopps 
    712   1.1   chopps int
    713   1.1   chopps mfcsparam(tp, t)
    714   1.1   chopps 	struct tty *tp;
    715   1.1   chopps 	struct termios *t;
    716   1.1   chopps {
    717   1.1   chopps 	int cfcr, cflag, unit, ospeed;
    718  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[tp->t_dev & 31];
    719   1.1   chopps 	struct mfc_softc *scc= sc->sc_mfc;
    720   1.2   chopps 
    721   1.1   chopps 	cflag = t->c_cflag;
    722   1.1   chopps 	unit = tp->t_dev & 31;
    723   1.1   chopps 	if (sc->flags & CT_USED) {
    724   1.1   chopps 		--scc->ct_usecnt;
    725   1.1   chopps 		sc->flags &= ~CT_USED;
    726   1.1   chopps 	}
    727   1.4   chopps 	ospeed = ttspeedtab(t->c_ospeed, scc->mfc_iii ? mfcs3speedtab2 :
    728   1.4   chopps 	    mfcs2speedtab2);
    729   1.1   chopps 
    730   1.1   chopps 	/*
    731   1.1   chopps 	 * If Baud Rate Generator can't generate requested speed,
    732   1.1   chopps 	 * try to use the counter/timer.
    733   1.1   chopps 	 */
    734   1.1   chopps 	if (ospeed < 0 && (scc->clk_frq % t->c_ospeed) == 0) {
    735   1.1   chopps 		ospeed = scc->clk_frq / t->c_ospeed;	/* divisor */
    736   1.1   chopps 		if (scc->ct_usecnt > 0 && scc->ct_val != ospeed)
    737   1.1   chopps 			ospeed = -1;
    738   1.1   chopps 		else {
    739   1.1   chopps 			scc->sc_regs->du_ctur = ospeed >> 8;
    740   1.1   chopps 			scc->sc_regs->du_ctlr = ospeed;
    741   1.1   chopps 			scc->ct_val = ospeed;
    742   1.1   chopps 			++scc->ct_usecnt;
    743   1.1   chopps 			sc->flags |= CT_USED;
    744   1.1   chopps 			ospeed = 0xdd;
    745   1.1   chopps 		}
    746   1.1   chopps 	}
    747   1.1   chopps 	/* XXXX 68681 duart could handle split speeds */
    748   1.1   chopps 	if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
    749   1.1   chopps 		return(EINVAL);
    750   1.1   chopps 
    751   1.4   chopps 	/* XXXX handle parity, character size, stop bits, flow control */
    752   1.4   chopps 
    753   1.2   chopps 	/*
    754   1.1   chopps 	 * copy to tty
    755   1.1   chopps 	 */
    756   1.1   chopps 	tp->t_ispeed = t->c_ispeed;
    757   1.1   chopps 	tp->t_ospeed = t->c_ospeed;
    758   1.1   chopps 	tp->t_cflag = cflag;
    759   1.1   chopps 
    760   1.1   chopps 	/*
    761   1.1   chopps 	 * enable interrupts
    762   1.1   chopps 	 */
    763   1.1   chopps 	scc->imask |= (0x2 << ((unit & 1) * 4)) | 0x80;
    764   1.1   chopps 	scc->sc_regs->du_imr = scc->imask;
    765   1.1   chopps #if defined(DEBUG) && 0
    766   1.1   chopps 	printf("mfcsparam: speed %d => %x ct %d imask %x cflag %x\n",
    767   1.1   chopps 	    t->c_ospeed, ospeed, scc->ct_val, scc->imask, cflag);
    768   1.1   chopps #endif
    769   1.1   chopps 	if (ospeed == 0)
    770   1.1   chopps 		(void)mfcsmctl(tp->t_dev, 0, DMSET);	/* hang up line */
    771   1.1   chopps 	else {
    772   1.2   chopps 		/*
    773   1.1   chopps 		 * (re)enable DTR
    774   1.1   chopps 		 * and set baud rate. (8 bit mode)
    775   1.1   chopps 		 */
    776   1.1   chopps 		(void)mfcsmctl(tp->t_dev, TIOCM_DTR | TIOCM_RTS, DMSET);
    777   1.1   chopps 		sc->sc_duart->ch_csr = ospeed;
    778   1.1   chopps 	}
    779   1.1   chopps 	return(0);
    780   1.1   chopps }
    781   1.1   chopps 
    782   1.1   chopps int mfcshwiflow(tp, flag)
    783   1.1   chopps         struct tty *tp;
    784   1.1   chopps         int flag;
    785   1.1   chopps {
    786  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[tp->t_dev & 31];
    787   1.1   chopps 	int unit = tp->t_dev & 1;
    788   1.1   chopps 
    789   1.1   chopps         if (flag)
    790   1.1   chopps 		sc->sc_regs->du_btrst = 1 << unit;
    791   1.1   chopps 	else
    792   1.1   chopps 		sc->sc_regs->du_btst = 1 << unit;
    793   1.1   chopps         return 1;
    794   1.1   chopps }
    795   1.1   chopps 
    796   1.1   chopps int
    797   1.1   chopps mfcsstart(tp)
    798   1.1   chopps 	struct tty *tp;
    799   1.1   chopps {
    800   1.1   chopps 	int cc, s, unit;
    801  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[tp->t_dev & 31];
    802   1.1   chopps 	struct mfc_softc *scc= sc->sc_mfc;
    803   1.1   chopps 
    804   1.1   chopps 	if ((tp->t_state & TS_ISOPEN) == 0)
    805   1.1   chopps 		return;
    806   1.1   chopps 
    807   1.1   chopps 	unit = tp->t_dev & 1;
    808   1.1   chopps 
    809   1.2   chopps 	s = splser();
    810   1.1   chopps 	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP))
    811   1.1   chopps 		goto out;
    812   1.1   chopps 
    813   1.1   chopps 	cc = tp->t_outq.c_cc;
    814   1.1   chopps 	if (cc <= tp->t_lowat) {
    815   1.1   chopps 		if (tp->t_state & TS_ASLEEP) {
    816   1.1   chopps 			tp->t_state &= ~TS_ASLEEP;
    817   1.1   chopps 			wakeup((caddr_t) & tp->t_outq);
    818   1.1   chopps 		}
    819   1.1   chopps 		selwakeup(&tp->t_wsel);
    820   1.1   chopps 	}
    821   1.1   chopps 	if (cc == 0 || (tp->t_state & TS_BUSY))
    822   1.1   chopps 		goto out;
    823   1.1   chopps 
    824   1.1   chopps 	/*
    825   1.1   chopps 	 * We only do bulk transfers if using CTSRTS flow control, not for
    826   1.1   chopps 	 * (probably sloooow) ixon/ixoff devices.
    827   1.1   chopps 	 */
    828   1.1   chopps 	if ((tp->t_cflag & CRTSCTS) == 0)
    829   1.1   chopps 		cc = 1;
    830   1.1   chopps 
    831   1.1   chopps 	/*
    832   1.1   chopps 	 * Limit the amount of output we do in one burst
    833   1.1   chopps 	 * to prevent hogging the CPU.
    834   1.1   chopps 	 */
    835   1.1   chopps 	if (cc > SEROBUF_SIZE)
    836   1.1   chopps 		cc = SEROBUF_SIZE;
    837   1.1   chopps 	cc = q_to_b(&tp->t_outq, sc->outbuf, cc);
    838   1.1   chopps 	if (cc > 0) {
    839   1.1   chopps 		tp->t_state |= TS_BUSY;
    840   1.1   chopps 
    841   1.1   chopps 		sc->ptr = sc->outbuf;
    842   1.1   chopps 		sc->end = sc->outbuf + cc;
    843   1.1   chopps 
    844   1.1   chopps 		/*
    845   1.1   chopps 		 * Get first character out, then have TBE-interrupts blow out
    846   1.1   chopps 		 * further characters, until buffer is empty, and TS_BUSY gets
    847   1.2   chopps 		 * cleared.
    848   1.1   chopps 		 */
    849   1.1   chopps 		sc->sc_duart->ch_tb = *sc->ptr++;
    850   1.1   chopps 		scc->imask |= 1 << (unit * 4);
    851   1.1   chopps 		sc->sc_regs->du_imr = scc->imask;
    852   1.1   chopps 	}
    853   1.1   chopps out:
    854   1.1   chopps 	splx(s);
    855   1.1   chopps }
    856   1.1   chopps 
    857   1.1   chopps /*
    858   1.1   chopps  * Stop output on a line.
    859   1.1   chopps  */
    860   1.1   chopps /*ARGSUSED*/
    861   1.1   chopps int
    862   1.1   chopps mfcsstop(tp, flag)
    863   1.1   chopps 	struct tty *tp;
    864   1.1   chopps {
    865   1.1   chopps 	int s;
    866   1.1   chopps 
    867   1.2   chopps 	s = splser();
    868   1.1   chopps 	if (tp->t_state & TS_BUSY) {
    869   1.1   chopps 		if ((tp->t_state & TS_TTSTOP) == 0)
    870   1.1   chopps 			tp->t_state |= TS_FLUSH;
    871   1.1   chopps 	}
    872   1.1   chopps 	splx(s);
    873   1.1   chopps }
    874   1.1   chopps 
    875   1.1   chopps int
    876   1.1   chopps mfcsmctl(dev, bits, how)
    877   1.1   chopps 	dev_t dev;
    878   1.1   chopps 	int bits, how;
    879   1.1   chopps {
    880   1.1   chopps 	int unit, s;
    881   1.1   chopps 	u_char ub;
    882  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[dev & 31];
    883   1.1   chopps 
    884   1.1   chopps 	unit = dev & 1;
    885   1.1   chopps 
    886   1.1   chopps 	/*
    887   1.1   chopps 	 * convert TIOCM* mask into CIA mask
    888   1.1   chopps 	 * which is active low
    889   1.1   chopps 	 */
    890   1.1   chopps 	if (how != DMGET) {
    891   1.1   chopps 		ub = 0;
    892   1.1   chopps 		/*
    893   1.1   chopps 		 * need to save current state of DTR & RTS ?
    894   1.1   chopps 		 */
    895   1.1   chopps 		if (bits & TIOCM_DTR)
    896   1.1   chopps 			ub |= 0x04 << unit;
    897   1.1   chopps 		if (bits & TIOCM_RTS)
    898   1.1   chopps 			ub |= 0x01 << unit;
    899   1.1   chopps 	}
    900   1.2   chopps 	s = splser();
    901   1.1   chopps 	switch (how) {
    902   1.1   chopps 	case DMSET:
    903   1.1   chopps 		sc->sc_regs->du_btst = ub;
    904   1.4   chopps 		sc->sc_regs->du_btrst = ub ^ (0x05 << unit);
    905   1.1   chopps 		break;
    906   1.1   chopps 
    907   1.1   chopps 	case DMBIC:
    908   1.1   chopps 		sc->sc_regs->du_btrst = ub;
    909   1.1   chopps 		ub = ~sc->sc_regs->du_ip;
    910   1.1   chopps 		break;
    911   1.1   chopps 
    912   1.1   chopps 	case DMBIS:
    913   1.1   chopps 		sc->sc_regs->du_btst = ub;
    914   1.1   chopps 		ub = ~sc->sc_regs->du_ip;
    915   1.1   chopps 		break;
    916   1.1   chopps 
    917   1.1   chopps 	case DMGET:
    918   1.1   chopps 		ub = ~sc->sc_regs->du_ip;
    919   1.1   chopps 		break;
    920   1.1   chopps 	}
    921   1.1   chopps 	(void)splx(s);
    922   1.1   chopps 
    923   1.4   chopps 	/* XXXX should keep DTR & RTS states in softc? */
    924   1.1   chopps 	bits = TIOCM_DTR | TIOCM_RTS;
    925   1.1   chopps 	if (ub & (1 << unit))
    926   1.1   chopps 		bits |= TIOCM_CTS;
    927   1.1   chopps 	if (ub & (4 << unit))
    928   1.1   chopps 		bits |= TIOCM_DSR;
    929   1.1   chopps 	if (ub & (0x10 << unit))
    930   1.1   chopps 		bits |= TIOCM_CD;
    931   1.4   chopps 	/* XXXX RI is not supported on all boards */
    932   1.1   chopps 	if (sc->sc_regs->pad26 & (1 << unit))
    933   1.1   chopps 		bits |= TIOCM_RI;
    934   1.1   chopps 
    935   1.1   chopps 	return(bits);
    936   1.1   chopps }
    937   1.1   chopps 
    938   1.1   chopps /*
    939   1.2   chopps  * Level 6 interrupt processing for the MultiFaceCard 68681 DUART
    940   1.1   chopps  */
    941   1.1   chopps 
    942   1.1   chopps int
    943   1.2   chopps mfcintr (scc)
    944   1.2   chopps 	struct mfc_softc *scc;
    945   1.1   chopps {
    946   1.1   chopps 	struct mfcs_softc *sc;
    947   1.1   chopps 	struct mfc_regs *regs;
    948   1.2   chopps 	struct tty *tp;
    949   1.2   chopps 	int istat, unit;
    950   1.2   chopps 	u_short c;
    951   1.1   chopps 
    952   1.2   chopps 	regs = scc->sc_regs;
    953   1.2   chopps 	istat = regs->du_isr & scc->imask;
    954   1.2   chopps 	if (istat == 0)
    955   1.2   chopps 		return (0);
    956   1.2   chopps 	unit = scc->sc_dev.dv_unit * 2;
    957   1.2   chopps 	if (istat & 0x02) {		/* channel A receive interrupt */
    958  1.10  thorpej 		sc = mfcs_cd.cd_devs[unit];
    959   1.2   chopps 		while (1) {
    960   1.2   chopps 			c = regs->du_sra << 8;
    961   1.2   chopps 			if ((c & 0x0100) == 0)
    962   1.2   chopps 				break;
    963   1.2   chopps 			c |= regs->du_rba;
    964   1.2   chopps 			if (sc->incnt == SERIBUF_SIZE)
    965   1.2   chopps 				++sc->ovfl;
    966   1.2   chopps 			else {
    967   1.2   chopps 				*sc->wptr++ = c;
    968   1.2   chopps 				if (sc->wptr == sc->inbuf + SERIBUF_SIZE)
    969   1.2   chopps 					sc->wptr = sc->inbuf;
    970   1.2   chopps 				++sc->incnt;
    971   1.2   chopps 				if (sc->incnt > SERIBUF_SIZE - 16)
    972   1.2   chopps 					regs->du_btrst = 1;
    973   1.1   chopps 			}
    974   1.2   chopps 			if (c & 0x1000)
    975   1.2   chopps 				regs->du_cra = 0x40;
    976   1.1   chopps 		}
    977   1.2   chopps 	}
    978   1.2   chopps 	if (istat & 0x20) {		/* channel B receive interrupt */
    979  1.10  thorpej 		sc = mfcs_cd.cd_devs[unit + 1];
    980   1.2   chopps 		while (1) {
    981   1.2   chopps 			c = regs->du_srb << 8;
    982   1.2   chopps 			if ((c & 0x0100) == 0)
    983   1.2   chopps 				break;
    984   1.2   chopps 			c |= regs->du_rbb;
    985   1.2   chopps 			if (sc->incnt == SERIBUF_SIZE)
    986   1.2   chopps 				++sc->ovfl;
    987   1.2   chopps 			else {
    988   1.2   chopps 				*sc->wptr++ = c;
    989   1.2   chopps 				if (sc->wptr == sc->inbuf + SERIBUF_SIZE)
    990   1.2   chopps 					sc->wptr = sc->inbuf;
    991   1.2   chopps 				++sc->incnt;
    992   1.2   chopps 				if (sc->incnt > SERIBUF_SIZE - 16)
    993   1.2   chopps 					regs->du_btrst = 2;
    994   1.1   chopps 			}
    995   1.2   chopps 			if (c & 0x1000)
    996   1.2   chopps 				regs->du_crb = 0x40;
    997   1.1   chopps 		}
    998   1.2   chopps 	}
    999   1.2   chopps 	if (istat & 0x01) {		/* channel A transmit interrupt */
   1000  1.10  thorpej 		sc = mfcs_cd.cd_devs[unit];
   1001   1.6   chopps 		tp = sc->sc_tty;
   1002   1.2   chopps 		if (sc->ptr == sc->end) {
   1003   1.2   chopps 			tp->t_state &= ~(TS_BUSY | TS_FLUSH);
   1004   1.2   chopps 			scc->imask &= ~0x01;
   1005   1.2   chopps 			regs->du_imr = scc->imask;
   1006   1.2   chopps 			add_sicallback (tp->t_line ?
   1007   1.8   chopps 			    (sifunc_t)linesw[tp->t_line].l_start
   1008   1.8   chopps 			    : (sifunc_t)mfcsstart, tp, NULL);
   1009   1.2   chopps 
   1010   1.1   chopps 		}
   1011   1.2   chopps 		else
   1012   1.2   chopps 			regs->du_tba = *sc->ptr++;
   1013   1.2   chopps 	}
   1014   1.2   chopps 	if (istat & 0x10) {		/* channel B transmit interrupt */
   1015  1.10  thorpej 		sc = mfcs_cd.cd_devs[unit + 1];
   1016   1.6   chopps 		tp = sc->sc_tty;
   1017   1.2   chopps 		if (sc->ptr == sc->end) {
   1018   1.2   chopps 			tp->t_state &= ~(TS_BUSY | TS_FLUSH);
   1019   1.2   chopps 			scc->imask &= ~0x10;
   1020   1.2   chopps 			regs->du_imr = scc->imask;
   1021   1.2   chopps 			add_sicallback (tp->t_line ?
   1022   1.8   chopps 			    (sifunc_t)linesw[tp->t_line].l_start
   1023   1.8   chopps 			    : (sifunc_t)mfcsstart, tp, NULL);
   1024   1.1   chopps 		}
   1025   1.2   chopps 		else
   1026   1.2   chopps 			regs->du_tbb = *sc->ptr++;
   1027   1.2   chopps 	}
   1028   1.2   chopps 	if (istat & 0x80) {		/* input port change interrupt */
   1029   1.2   chopps 		c = regs->du_ipcr;
   1030   1.2   chopps 		printf ("%s: ipcr %02x", scc->sc_dev.dv_xname, c);
   1031   1.1   chopps 	}
   1032   1.2   chopps 	return(1);
   1033   1.1   chopps }
   1034   1.1   chopps 
   1035   1.1   chopps int
   1036   1.1   chopps mfcsxintr(unit)
   1037   1.1   chopps 	int unit;
   1038   1.1   chopps {
   1039   1.1   chopps 	int s1, s2, ovfl;
   1040  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[unit];
   1041   1.6   chopps 	struct tty *tp = sc->sc_tty;
   1042   1.1   chopps 
   1043   1.1   chopps 	/*
   1044   1.1   chopps 	 * Make sure we're not interrupted by another
   1045   1.1   chopps 	 * vbl, but allow level6 ints
   1046   1.1   chopps 	 */
   1047   1.1   chopps 	s1 = spltty();
   1048   1.1   chopps 
   1049   1.1   chopps 	/*
   1050   1.1   chopps 	 * pass along any acumulated information
   1051   1.1   chopps 	 * while input is not blocked
   1052   1.1   chopps 	 */
   1053   1.1   chopps 	while (sc->incnt && (tp->t_state & TS_TBLOCK) == 0) {
   1054   1.2   chopps 		/*
   1055   1.1   chopps 		 * no collision with ser_fastint()
   1056   1.1   chopps 		 */
   1057   1.1   chopps 		mfcseint(unit, *sc->rptr++);
   1058   1.1   chopps 
   1059   1.1   chopps 		ovfl = 0;
   1060   1.1   chopps 		/* lock against mfcs_fastint() */
   1061   1.2   chopps 		s2 = splser();
   1062   1.1   chopps 		--sc->incnt;
   1063   1.1   chopps 		if (sc->rptr == sc->inbuf + SERIBUF_SIZE)
   1064   1.1   chopps 			sc->rptr = sc->inbuf;
   1065   1.1   chopps 		if (sc->ovfl != 0) {
   1066   1.1   chopps 			ovfl = sc->ovfl;
   1067   1.1   chopps 			sc->ovfl = 0;
   1068   1.1   chopps 		}
   1069   1.1   chopps 		splx(s2);
   1070   1.1   chopps 		if (ovfl != 0)
   1071   1.1   chopps 			log(LOG_WARNING, "%s: %d buffer overflow!\n",
   1072   1.1   chopps 			    sc->sc_dev.dv_xname, ovfl);
   1073   1.1   chopps 	}
   1074   1.1   chopps 	if (sc->incnt == 0 && (tp->t_state & TS_TBLOCK) == 0) {
   1075   1.4   chopps 		sc->sc_regs->du_btst = 1 << unit;	/* XXXX */
   1076   1.1   chopps 	}
   1077   1.1   chopps 	splx(s1);
   1078   1.1   chopps }
   1079   1.1   chopps 
   1080   1.1   chopps int
   1081   1.1   chopps mfcseint(unit, stat)
   1082   1.1   chopps 	int unit, stat;
   1083   1.1   chopps {
   1084  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[unit];
   1085   1.1   chopps 	struct tty *tp;
   1086   1.1   chopps 	u_char ch;
   1087   1.1   chopps 	int c;
   1088   1.1   chopps 
   1089   1.6   chopps 	tp = sc->sc_tty;
   1090   1.1   chopps 	ch = stat & 0xff;
   1091   1.1   chopps 	c = ch;
   1092   1.1   chopps 
   1093   1.1   chopps 	if ((tp->t_state & TS_ISOPEN) == 0) {
   1094   1.1   chopps #ifdef KGDB
   1095   1.1   chopps 		/* we don't care about parity errors */
   1096   1.1   chopps 		if (kgdb_dev == makedev(sermajor, unit) && c == FRAME_END)
   1097   1.1   chopps 			kgdb_connect(0);	/* trap into kgdb */
   1098   1.1   chopps #endif
   1099   1.1   chopps 		return;
   1100   1.1   chopps 	}
   1101   1.1   chopps 
   1102   1.1   chopps 	/*
   1103   1.1   chopps 	 * Check for break and (if enabled) parity error.
   1104   1.1   chopps 	 */
   1105   1.1   chopps 	if (stat & 0xc000)
   1106   1.1   chopps 		c |= TTY_FE;
   1107   1.1   chopps 	else if (stat & 0x2000)
   1108   1.1   chopps 			c |= TTY_PE;
   1109   1.1   chopps 
   1110   1.1   chopps 	if (stat & 0x1000)
   1111   1.2   chopps 		log(LOG_WARNING, "%s: fifo overflow\n",
   1112  1.10  thorpej 		    ((struct mfcs_softc *)mfcs_cd.cd_devs[unit])->sc_dev.dv_xname);
   1113   1.1   chopps 
   1114   1.1   chopps 	(*linesw[tp->t_line].l_rint)(c, tp);
   1115   1.1   chopps }
   1116   1.1   chopps 
   1117   1.1   chopps /*
   1118   1.1   chopps  * This interrupt is periodically invoked in the vertical blank
   1119   1.1   chopps  * interrupt.  It's used to keep track of the modem control lines
   1120   1.1   chopps  * and (new with the fast_int code) to move accumulated data
   1121   1.1   chopps  * up into the tty layer.
   1122   1.1   chopps  */
   1123   1.1   chopps void
   1124   1.1   chopps mfcsmint(unit)
   1125   1.1   chopps 	int unit;
   1126   1.1   chopps {
   1127   1.1   chopps 	struct tty *tp;
   1128  1.10  thorpej 	struct mfcs_softc *sc = mfcs_cd.cd_devs[unit];
   1129   1.1   chopps 	u_char stat, last, istat;
   1130   1.1   chopps 
   1131   1.6   chopps 	tp = sc->sc_tty;
   1132   1.1   chopps 	if (!tp)
   1133   1.1   chopps 		return;
   1134   1.1   chopps 
   1135   1.1   chopps 	if ((tp->t_state & (TS_ISOPEN | TS_WOPEN)) == 0) {
   1136   1.1   chopps 		sc->rptr = sc->wptr = sc->inbuf;
   1137   1.1   chopps 		sc->incnt = 0;
   1138   1.1   chopps 		return;
   1139   1.1   chopps 	}
   1140   1.1   chopps 	/*
   1141   1.1   chopps 	 * empty buffer
   1142   1.1   chopps 	 */
   1143   1.1   chopps 	mfcsxintr(unit);
   1144   1.1   chopps 
   1145   1.1   chopps 	stat = ~sc->sc_regs->du_ip;
   1146   1.1   chopps 	last = sc->sc_mfc->last_ip;
   1147   1.1   chopps 	sc->sc_mfc->last_ip = stat;
   1148   1.1   chopps 
   1149   1.1   chopps 	/*
   1150   1.1   chopps 	 * check whether any interesting signal changed state
   1151   1.1   chopps 	 */
   1152   1.1   chopps 	istat = stat ^ last;
   1153   1.1   chopps 
   1154   1.1   chopps 	if ((istat & (0x10 << (unit & 1))) && 		/* CD changed */
   1155   1.1   chopps 	    (SWFLAGS(tp->t_dev) & TIOCFLAG_SOFTCAR) == 0) {
   1156   1.1   chopps 		if (stat & (0x10 << (unit & 1)))
   1157   1.1   chopps 			(*linesw[tp->t_line].l_modem)(tp, 1);
   1158   1.1   chopps 		else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
   1159   1.1   chopps 			sc->sc_regs->du_btrst = 0x0a << (unit & 1);
   1160   1.1   chopps 		}
   1161   1.1   chopps 	}
   1162   1.1   chopps }
   1163