Home | History | Annotate | Line # | Download | only in dev
msc.c revision 1.6.4.1
      1  1.6.4.1   mhitch /*	$NetBSD: msc.c,v 1.6.4.1 1996/06/06 04:53:17 mhitch Exp $ */
      2      1.1   chopps 
      3      1.1   chopps /*
      4      1.1   chopps  * Copyright (c) 1993 Zik.
      5      1.1   chopps  * Copyright (c) 1995 Jukka Marin <jmarin (at) teeri.jmp.fi>.
      6      1.1   chopps  * Copyright (c) 1995 Timo Rossi <trossi (at) jyu.fi>.
      7      1.1   chopps  * Copyright (c) 1995 Rob Healey <rhealey (at) kas.helios.mn.org>.
      8      1.1   chopps  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
      9      1.1   chopps  * All rights reserved.
     10      1.1   chopps  *
     11      1.1   chopps  * Redistribution and use in source and binary forms, with or without
     12      1.1   chopps  * modification, are permitted provided that the following conditions
     13      1.1   chopps  * are met:
     14      1.1   chopps  * 1. Redistributions of source code must retain the above copyright
     15      1.1   chopps  *    notice, this list of conditions and the following disclaimer.
     16      1.1   chopps  * 2. Redistributions in binary form must reproduce the above copyright
     17      1.1   chopps  *    notice, this list of conditions and the following disclaimer in the
     18      1.1   chopps  *    documentation and/or other materials provided with the distribution.
     19      1.1   chopps  * 3. All advertising materials mentioning features or use of this software
     20      1.1   chopps  *    must display the following acknowledgement:
     21      1.1   chopps  *	This product includes software developed by the University of
     22      1.1   chopps  *	California, Berkeley and its contributors.
     23      1.1   chopps  * 4. Neither the name of the University nor the names of its contributors
     24      1.1   chopps  *    may be used to endorse or promote products derived from this software
     25      1.1   chopps  *    without specific prior written permission.
     26      1.1   chopps  *
     27      1.1   chopps  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     28      1.1   chopps  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     29      1.1   chopps  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     30      1.1   chopps  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     31      1.1   chopps  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     32      1.1   chopps  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     33      1.1   chopps  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     34      1.1   chopps  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     35      1.1   chopps  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     36      1.1   chopps  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     37      1.1   chopps  * SUCH DAMAGE.
     38      1.1   chopps  *
     39      1.1   chopps  *   - converted from NetBSD Amiga serial driver to A2232 serial driver
     40      1.1   chopps  *     by zik 931207
     41      1.1   chopps  *   - added ttyflags hooks rfh 940419
     42      1.1   chopps  *   - added new style config support rfh 940601
     43      1.1   chopps  *   - added code to halt board during memory load so board doesn't flip
     44      1.1   chopps  *     out. /dev/reload works now. Also created mschwiflow function so BSD can
     45      1.1   chopps  *     attempt to use board RTS flow control now. rfh 950108
     46      1.1   chopps  *   - Integrated work from Jukka Marin <jmarin (at) jmp.fi> and
     47      1.1   chopps  *     Timo Rossi <trossi (at) jyu.fi> The mscmint() code is Jukka's. 950916
     48      1.1   chopps  *     Integrated more bug fixes by Jukka Marin <jmarin (at) jmp.fi> 950918
     49      1.1   chopps  *     Also added Jukka's turbo board code. 950918
     50      1.1   chopps  *   - Reformatted to NetBSD style format.
     51      1.1   chopps  */
     52      1.1   chopps 
     53      1.1   chopps #include "msc.h"
     54      1.1   chopps 
     55      1.1   chopps #if NMSC > 0
     56      1.1   chopps #include <sys/param.h>
     57      1.1   chopps #include <sys/systm.h>
     58      1.1   chopps #include <sys/ioctl.h>
     59      1.1   chopps #include <sys/tty.h>
     60      1.1   chopps #include <sys/proc.h>
     61      1.1   chopps #include <sys/file.h>
     62      1.1   chopps #include <sys/malloc.h>
     63      1.1   chopps #include <sys/uio.h>
     64      1.1   chopps #include <sys/kernel.h>
     65      1.1   chopps #include <sys/syslog.h>
     66      1.1   chopps #include <sys/device.h>
     67      1.1   chopps 
     68      1.1   chopps #include <amiga/amiga/device.h>
     69      1.1   chopps #include <amiga/dev/zbusvar.h>
     70      1.1   chopps #include <amiga/dev/mscreg.h>
     71      1.3  mycroft #include <machine/cpu.h>
     72      1.1   chopps 
     73      1.1   chopps #include <amiga/amiga/custom.h>
     74      1.1   chopps #include <amiga/amiga/cia.h>
     75      1.1   chopps #include <amiga/amiga/cc.h>
     76      1.1   chopps 
     77      1.6    veego #include <sys/conf.h>
     78      1.6    veego #include <machine/conf.h>
     79      1.6    veego 
     80      1.1   chopps /* 6502 code for A2232 card */
     81      1.1   chopps #include "msc6502.h"
     82      1.1   chopps 
     83      1.1   chopps /*
     84      1.1   chopps  * Note: These are Zik's original comments:
     85      1.1   chopps  * There is a bit of a "gotcha" concerning the numbering
     86      1.1   chopps  * of msc devices and the specification of the number of serial
     87      1.1   chopps  * lines in the kernel.
     88      1.1   chopps  *
     89      1.1   chopps  * Each board has seven lines, but for programming convenience
     90      1.1   chopps  * and compatibility with Amiga UNIX the boards' minor device
     91      1.1   chopps  * numbers are allocated in groups of sixteen:
     92      1.1   chopps  *
     93      1.1   chopps  *                     minor device numbers
     94      1.1   chopps  * First board		0  2  4  6  8 10 12
     95      1.1   chopps  * Second board        16 18 20 22 24 26 28
     96      1.1   chopps  * Third board	       32 34 36 38 40 42 44
     97      1.1   chopps  *
     98      1.1   chopps  * The intermediate minor device numbers are dialin versions
     99      1.1   chopps  * of the same devices. ie. 10 is dialout line 6 and 11 is
    100      1.1   chopps  * the dialin version of line 6.
    101      1.1   chopps  *
    102      1.1   chopps  * On the other hand, I have made the NMSC config option refer
    103      1.1   chopps  * to the total number of a2232 cards, not the maximum
    104      1.1   chopps  * minor device number. So you might have NMSC=3, in which case
    105      1.1   chopps  * you have three boards with minor device numbers from 0 to 45.
    106      1.1   chopps  */
    107      1.1   chopps 
    108      1.6    veego int	mscparam __P((struct tty *, struct termios *));
    109      1.6    veego void	mscstart __P((struct tty *));
    110      1.1   chopps int	mschwiflow __P((struct tty *, int));
    111      1.1   chopps int	mscinitcard __P((struct zbus_args *));
    112      1.1   chopps 
    113      1.1   chopps int	mscdefaultrate = TTYDEF_SPEED;
    114      1.1   chopps 
    115      1.1   chopps struct	mscdevice mscdev[MSCSLOTS];	/* device structs for all lines */
    116      1.1   chopps struct	tty *msc_tty[MSCTTYS];		/* ttys for all lines */
    117      1.1   chopps 
    118      1.1   chopps struct	vbl_node msc_vbl_node[NMSC];	/* vbl interrupt node per board */
    119      1.1   chopps 
    120      1.1   chopps struct speedtab mscspeedtab_normal[] = {
    121      1.6    veego 	{ 0,		0		},
    122      1.6    veego 	{ 50,		MSCPARAM_B50	},
    123      1.6    veego 	{ 75,		MSCPARAM_B75 	},
    124      1.6    veego 	{ 110,		MSCPARAM_B110 	},
    125      1.6    veego 	{ 134,		MSCPARAM_B134	},
    126      1.6    veego 	{ 150,		MSCPARAM_B150	},
    127      1.6    veego 	{ 300,		MSCPARAM_B300	},
    128      1.6    veego 	{ 600,		MSCPARAM_B600	},
    129      1.6    veego 	{ 1200,		MSCPARAM_B1200	},
    130      1.6    veego 	{ 1800,		MSCPARAM_B1800	},
    131      1.6    veego 	{ 2400,		MSCPARAM_B2400	},
    132      1.6    veego 	{ 3600,		MSCPARAM_B3600	},
    133      1.6    veego 	{ 4800,		MSCPARAM_B4800	},
    134      1.6    veego 	{ 7200,		MSCPARAM_B7200	},
    135      1.6    veego 	{ 9600,		MSCPARAM_B9600	},
    136      1.6    veego 	{ 19200,	MSCPARAM_B19200	},
    137      1.6    veego 	{ 115200,	MSCPARAM_B115200 },
    138      1.6    veego 	{ -1,		-1		}
    139      1.1   chopps };
    140      1.1   chopps 
    141      1.1   chopps struct speedtab mscspeedtab_turbo[] = {
    142      1.6    veego 	{ 0,		0		},
    143      1.6    veego 	{ 100,		MSCPARAM_B50	},
    144      1.6    veego 	{ 150,		MSCPARAM_B75	},
    145      1.6    veego 	{ 220,		MSCPARAM_B110	},
    146      1.6    veego 	{ 269,		MSCPARAM_B134	},
    147      1.6    veego 	{ 300,		MSCPARAM_B150	},
    148      1.6    veego 	{ 600,		MSCPARAM_B300	},
    149      1.6    veego 	{ 1200,		MSCPARAM_B600	},
    150      1.6    veego 	{ 2400,		MSCPARAM_B1200	},
    151      1.6    veego 	{ 3600,		MSCPARAM_B1800	},
    152      1.6    veego 	{ 4800,		MSCPARAM_B2400	},
    153      1.6    veego 	{ 7200,		MSCPARAM_B3600	},
    154      1.6    veego 	{ 9600,		MSCPARAM_B4800	},
    155      1.6    veego 	{ 14400,	MSCPARAM_B7200	},
    156      1.6    veego 	{ 19200,	MSCPARAM_B9600	},
    157      1.6    veego 	{ 38400,	MSCPARAM_B19200	},
    158      1.6    veego 	{ 230400,	MSCPARAM_B115200 },
    159      1.6    veego 	{ -1,		-1		}
    160      1.1   chopps };
    161      1.1   chopps 
    162      1.1   chopps struct   speedtab *mscspeedtab;
    163      1.1   chopps 
    164      1.1   chopps int mscmctl __P((dev_t dev, int bits, int howto));
    165      1.1   chopps void mscmint __P((register void *data));
    166      1.1   chopps 
    167      1.4  thorpej int mscmatch __P((struct device *, void *, void *));
    168      1.1   chopps void mscattach __P((struct device *, struct device *, void *));
    169      1.1   chopps 
    170      1.1   chopps #define	SWFLAGS(dev)	(msc->openflags | (MSCDIALIN(dev) ? 0 : TIOCFLAG_SOFTCAR))
    171      1.1   chopps #define	DEBUG_MSC	0
    172      1.1   chopps #define	DEBUG_CD	0
    173      1.1   chopps 
    174      1.4  thorpej struct cfattach msc_ca = {
    175      1.4  thorpej 	sizeof(struct device), mscmatch, mscattach
    176      1.4  thorpej };
    177      1.4  thorpej 
    178      1.4  thorpej struct cfdriver msc_cd = {
    179      1.5   mhitch 	NULL, "msc",DV_TTY, NULL, 0
    180      1.1   chopps };
    181      1.1   chopps 
    182      1.2   chopps #if DEBUG_MSC
    183      1.2   chopps void
    184      1.2   chopps bugi(msc, string)
    185      1.2   chopps 	struct mscdevice *msc;
    186      1.2   chopps 	char *string;
    187      1.2   chopps {
    188      1.2   chopps 	volatile struct mscstatus *ms;
    189      1.2   chopps 	volatile struct mscmemory *mscmem;
    190      1.2   chopps 
    191      1.2   chopps 	mscmem = msc->board;
    192      1.2   chopps 	ms = &mscmem->Status[msc->port];
    193      1.2   chopps 
    194      1.2   chopps 	printf("msc  %s u%d f%08lx F%08lx\n", string, msc->port, msc->flags,
    195      1.2   chopps 		msc->openflags);
    196      1.2   chopps 	printf("msc  h%d t%d H%d t%d p%02x c%02x CD%02x\n", ms->InHead,
    197      1.2   chopps 		ms->InTail, ms->OutHead, ms->OutTail, ms->Param, ms->Command,
    198      1.2   chopps 		ms->chCD);
    199      1.2   chopps 	printf("msc  a%02x b%02x c%02x\n", ms->Pad_a, ms->Pad_b, ms->Padc);
    200      1.2   chopps 
    201      1.2   chopps 	return
    202      1.2   chopps }
    203      1.2   chopps 
    204      1.2   chopps #endif
    205      1.2   chopps 
    206      1.1   chopps int
    207      1.4  thorpej mscmatch(pdp, match, auxp)
    208      1.1   chopps 	struct device *pdp;
    209      1.4  thorpej 	void *match, *auxp;
    210      1.1   chopps {
    211      1.1   chopps 	struct zbus_args *zap;
    212      1.1   chopps 
    213      1.1   chopps 	zap = auxp;
    214      1.1   chopps 	if (zap->manid == 514 && (zap->prodid == 70 || zap->prodid == 69))
    215      1.1   chopps 		return(1);
    216      1.1   chopps 
    217      1.1   chopps 	return (0);
    218      1.1   chopps }
    219      1.1   chopps 
    220      1.1   chopps void
    221      1.1   chopps mscattach(pdp, dp, auxp)
    222      1.1   chopps 	struct device *pdp, *dp;
    223      1.1   chopps 	void *auxp;
    224      1.1   chopps {
    225      1.1   chopps   volatile struct mscmemory *mscmem;
    226      1.1   chopps   struct mscdevice *msc;
    227      1.1   chopps   struct zbus_args *zap;
    228      1.1   chopps   int unit;
    229      1.1   chopps   int Count;
    230      1.1   chopps 
    231      1.1   chopps   zap = (struct zbus_args *)auxp;
    232      1.1   chopps   unit = dp->dv_unit;
    233      1.1   chopps 
    234      1.1   chopps   if (mscinitcard(zap) != 0) {
    235      1.1   chopps     printf("\nmsc%d: Board initialize failed, bad download code.\n", unit);
    236      1.1   chopps     return;
    237      1.1   chopps   }
    238      1.1   chopps 
    239      1.1   chopps   printf("\nmsc%d: Board successfully initialized.\n", unit);
    240      1.1   chopps 
    241      1.1   chopps   mscmem = (struct mscmemory *) zap->va;
    242      1.1   chopps 
    243      1.1   chopps   if (mscmem->Common.Crystal == MSC_UNKNOWN) {
    244      1.1   chopps 	printf("msc%d: Unable to detect crystal frequency.\n", unit);
    245      1.1   chopps 	return;
    246      1.1   chopps   }
    247      1.1   chopps 
    248      1.1   chopps   if (mscmem->Common.Crystal == MSC_TURBO) {
    249      1.1   chopps 	printf("msc%d: Turbo version detected (%02x%02x:%d)\n", unit,
    250      1.1   chopps 		mscmem->Common.TimerH, mscmem->Common.TimerL,
    251      1.1   chopps 		mscmem->Common.Pad_a);
    252      1.1   chopps 	mscspeedtab = mscspeedtab_turbo;
    253      1.1   chopps   } else {
    254      1.1   chopps 	printf("msc%d: Normal version detected (%02x%02x:%d)\n", unit,
    255      1.1   chopps 		mscmem->Common.TimerH, mscmem->Common.TimerL,
    256      1.1   chopps 		mscmem->Common.Pad_a);
    257      1.1   chopps 	mscspeedtab = mscspeedtab_normal;
    258      1.1   chopps   }
    259      1.1   chopps 
    260      1.1   chopps   /* XXX 8 is a constant */
    261      1.1   chopps   for (Count = 0; Count < 8 && MSCSLOTUL(unit, Count) < MSCSLOTS; Count++) {
    262      1.1   chopps     msc = &mscdev[MSCSLOTUL(unit, Count)];
    263      1.1   chopps     msc->board = mscmem;
    264      1.1   chopps     msc->port = Count;
    265      1.1   chopps     msc->flags = 0;
    266      1.1   chopps     msc->openflags = 0;
    267      1.1   chopps     msc->active = 1;
    268      1.1   chopps     msc->closing = FALSE;
    269      1.1   chopps     msc_tty[MSCTTYSLOT(MSCSLOTUL(unit, Count))] = NULL;
    270      1.1   chopps     msc_tty[MSCTTYSLOT(MSCSLOTUL(unit, Count))+1] = NULL;
    271      1.1   chopps 
    272      1.1   chopps   }
    273      1.1   chopps 
    274      1.1   chopps   /* disable the non-existant eighth port */
    275      1.1   chopps   if (MSCSLOTUL(unit, NUMLINES) < MSCSLOTS)
    276      1.1   chopps     mscdev[MSCSLOTUL(unit, NUMLINES)].active = 0;
    277      1.1   chopps 
    278      1.1   chopps   msc_vbl_node[unit].function = (void (*) (void *)) mscmint;
    279      1.1   chopps   msc_vbl_node[unit].data = (void *) unit;
    280      1.1   chopps 
    281      1.1   chopps   add_vbl_function (&msc_vbl_node[unit], MSC_VBL_PRIORITY, (void *)unit);
    282      1.1   chopps 
    283      1.1   chopps   return;
    284      1.1   chopps }
    285      1.1   chopps 
    286      1.1   chopps /* ARGSUSED */
    287      1.1   chopps int
    288      1.1   chopps mscopen(dev, flag, mode, p)
    289      1.1   chopps 	dev_t dev;
    290      1.1   chopps 	int flag, mode;
    291      1.1   chopps 	struct proc *p;
    292      1.1   chopps {
    293      1.1   chopps   register struct tty *tp;
    294      1.1   chopps   int error = 0;
    295      1.1   chopps   int s;
    296      1.1   chopps   int slot;
    297      1.1   chopps   int ttyn;
    298      1.1   chopps   struct mscdevice *msc;
    299      1.1   chopps   volatile struct mscstatus *ms;
    300      1.1   chopps 
    301      1.1   chopps   /* get the device structure */
    302      1.1   chopps   slot = MSCSLOT(dev);
    303      1.1   chopps   ttyn = MSCTTY(dev);
    304      1.1   chopps 
    305      1.1   chopps   if (slot >= MSCSLOTS)
    306      1.1   chopps     return ENXIO;
    307      1.1   chopps 
    308      1.1   chopps   if (MSCLINE(dev) >= NUMLINES)
    309      1.1   chopps     return ENXIO;
    310      1.1   chopps 
    311      1.1   chopps   msc = &mscdev[slot];
    312      1.1   chopps   ms = &msc->board->Status[msc->port];
    313      1.1   chopps 
    314      1.1   chopps   if (!msc->active)
    315      1.1   chopps     return ENXIO;
    316      1.1   chopps 
    317      1.1   chopps   /*
    318      1.1   chopps    * RFH: WHY here? Put down by while like other serial drivers
    319      1.1   chopps    *      But if we do that it makes things bomb.
    320      1.1   chopps    */
    321      1.1   chopps   s = spltty();
    322      1.1   chopps 
    323      1.1   chopps   if (!msc_tty[ttyn]) {
    324      1.1   chopps 
    325      1.1   chopps       tp = ttymalloc();
    326  1.6.4.1   mhitch       tty_attach(tp);
    327      1.1   chopps       msc_tty[ttyn] = tp;
    328      1.1   chopps       msc_tty[ttyn+1] = (struct tty *)NULL;
    329      1.1   chopps 
    330      1.2   chopps #if 0
    331      1.1   chopps       /* default values are not optimal for this device, increase buffers. */
    332      1.1   chopps       clfree(&tp->t_rawq);
    333      1.1   chopps       clfree(&tp->t_canq);
    334      1.1   chopps       clfree(&tp->t_outq);
    335      1.1   chopps       clalloc(&tp->t_rawq, 8192, 1);
    336      1.1   chopps       clalloc(&tp->t_canq, 8192, 1);
    337      1.1   chopps       clalloc(&tp->t_outq, 8192, 0);
    338      1.2   chopps #endif
    339      1.1   chopps 
    340      1.1   chopps   }
    341      1.1   chopps   else
    342      1.1   chopps     tp = msc_tty[ttyn];
    343      1.1   chopps 
    344      1.1   chopps   tp->t_oproc = (void (*) (struct tty *)) mscstart;
    345      1.1   chopps   tp->t_param = mscparam;
    346      1.1   chopps   tp->t_dev = dev;
    347      1.1   chopps   tp->t_hwiflow = mschwiflow;
    348      1.1   chopps 
    349      1.1   chopps   /* if port is still closing, just bitbucket remaining characters */
    350      1.1   chopps   if (msc->closing) {
    351      1.1   chopps 
    352      1.1   chopps       ms->OutFlush = TRUE;
    353      1.1   chopps       msc->closing = FALSE;
    354      1.1   chopps   }
    355      1.1   chopps 
    356      1.1   chopps   /* initialize tty */
    357      1.1   chopps   if ((tp->t_state & TS_ISOPEN) == 0) {
    358      1.1   chopps 
    359      1.1   chopps       tp->t_state |= TS_WOPEN;
    360      1.1   chopps       ttychars(tp);
    361      1.1   chopps       if (tp->t_ispeed == 0) {
    362      1.1   chopps 
    363      1.1   chopps 	  tp->t_iflag = TTYDEF_IFLAG;
    364      1.1   chopps 	  tp->t_oflag = TTYDEF_OFLAG;
    365      1.1   chopps 	  tp->t_cflag = TTYDEF_CFLAG;
    366      1.1   chopps 	  tp->t_lflag = TTYDEF_LFLAG;
    367      1.1   chopps 	  tp->t_ispeed = tp->t_ospeed = mscdefaultrate;
    368      1.1   chopps       }
    369      1.1   chopps 
    370      1.1   chopps       /* flags changed to be private to every unit by JM */
    371      1.1   chopps       if (msc->openflags & TIOCFLAG_CLOCAL)
    372      1.1   chopps 		tp->t_cflag |= CLOCAL;
    373      1.1   chopps       if (msc->openflags & TIOCFLAG_CRTSCTS)
    374      1.1   chopps 		tp->t_cflag |= CRTSCTS;
    375      1.1   chopps       if (msc->openflags & TIOCFLAG_MDMBUF)
    376      1.1   chopps 		tp->t_cflag |= MDMBUF;
    377      1.1   chopps 
    378      1.1   chopps       mscparam(tp, &tp->t_termios);
    379      1.1   chopps       ttsetwater(tp);
    380      1.1   chopps 
    381      1.1   chopps       (void) mscmctl(dev, TIOCM_DTR | TIOCM_RTS, DMSET);
    382      1.1   chopps 
    383      1.1   chopps       if ((SWFLAGS(dev) & TIOCFLAG_SOFTCAR) ||
    384      1.1   chopps 	  (mscmctl(dev, 0, DMGET) & TIOCM_CD))
    385      1.1   chopps             tp->t_state |= TS_CARR_ON;
    386      1.1   chopps       else
    387      1.1   chopps             tp->t_state &= ~TS_CARR_ON;
    388      1.1   chopps 
    389      1.1   chopps   }
    390      1.1   chopps   else {
    391      1.1   chopps         if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) {
    392      1.1   chopps 	    splx(s);
    393      1.1   chopps 	    return (EBUSY);
    394      1.1   chopps        }
    395      1.1   chopps   }
    396      1.1   chopps 
    397      1.1   chopps   /*
    398      1.1   chopps    * if NONBLOCK requested, ignore carrier
    399      1.1   chopps    */
    400      1.1   chopps   if (flag & O_NONBLOCK)
    401      1.1   chopps     goto done;
    402      1.1   chopps 
    403      1.1   chopps   /*
    404      1.1   chopps    * s = spltty();
    405      1.1   chopps    *
    406      1.1   chopps    * This causes hangs when put here, like other TTY drivers do, rather than
    407      1.1   chopps    * above, WHY? RFH
    408      1.1   chopps    *
    409      1.1   chopps    */
    410      1.1   chopps 
    411      1.1   chopps   while ((tp->t_state & TS_CARR_ON) == 0 && (tp->t_cflag & CLOCAL) == 0) {
    412      1.1   chopps 
    413      1.1   chopps       tp->t_state |= TS_WOPEN;
    414      1.1   chopps 
    415      1.2   chopps #if DEBUG_CD
    416      1.2   chopps       printf("msc %ld waiting for CD\n", MSCLINE(dev));
    417      1.2   chopps #endif
    418      1.1   chopps       error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH, ttopen, 0);
    419      1.1   chopps 
    420      1.1   chopps       if (error) {
    421      1.1   chopps                splx(s);
    422      1.1   chopps                return(error);
    423      1.1   chopps       }
    424      1.1   chopps   }
    425      1.1   chopps 
    426      1.2   chopps done:
    427      1.1   chopps #if DEBUG_CD
    428      1.2   chopps   printf("msc %ld waiting for CD\n", MSCLINE(dev));
    429      1.1   chopps #endif
    430      1.1   chopps   /* This is a way to handle lost XON characters */
    431      1.1   chopps   if ((flag & O_TRUNC) && (tp->t_state & TS_TTSTOP)) {
    432      1.1   chopps           tp->t_state &= ~TS_TTSTOP;
    433      1.1   chopps           ttstart (tp);
    434      1.1   chopps   }
    435      1.1   chopps 
    436      1.1   chopps   splx(s);
    437      1.1   chopps 
    438      1.1   chopps   /*
    439      1.1   chopps    * Reset the tty pointer, as there could have been a dialout
    440      1.1   chopps    * use of the tty with a dialin open waiting.
    441      1.1   chopps    */
    442      1.1   chopps   tp->t_dev = dev;
    443      1.1   chopps 
    444      1.1   chopps   return((*linesw[tp->t_line].l_open)(dev, tp));
    445      1.1   chopps 
    446      1.1   chopps }
    447      1.1   chopps 
    448      1.1   chopps int
    449      1.1   chopps mscclose(dev, flag, mode, p)
    450      1.1   chopps 	dev_t dev;
    451      1.1   chopps 	int flag, mode;
    452      1.1   chopps 	struct proc *p;
    453      1.1   chopps {
    454      1.1   chopps   register struct tty *tp;
    455      1.1   chopps   int slot;
    456      1.1   chopps   volatile struct mscstatus *ms;
    457      1.1   chopps   struct mscdevice *msc;
    458      1.1   chopps 
    459      1.1   chopps   /* get the device structure */
    460      1.1   chopps   slot = MSCSLOT(dev);
    461      1.1   chopps 
    462      1.1   chopps   if (slot >= MSCSLOTS)
    463      1.1   chopps     return ENXIO;
    464      1.1   chopps 
    465      1.1   chopps   msc = &mscdev[slot];
    466      1.1   chopps 
    467      1.1   chopps   if (!msc->active)
    468      1.1   chopps     return ENXIO;
    469      1.1   chopps 
    470      1.1   chopps   ms = &msc->board->Status[msc->port];
    471      1.1   chopps 
    472      1.2   chopps #if DEBUG_MSC
    473      1.2   chopps   bugi(msc, "close1");
    474      1.2   chopps #endif
    475      1.2   chopps 
    476      1.1   chopps   tp = msc_tty[MSCTTY(dev)];
    477      1.1   chopps   (*linesw[tp->t_line].l_close)(tp, flag);
    478      1.1   chopps 
    479      1.1   chopps   (void) mscmctl(dev, 0, DMSET);
    480      1.1   chopps 
    481      1.1   chopps   ttyclose(tp);
    482      1.1   chopps 
    483      1.1   chopps   if (msc->flags & TIOCM_DTR)
    484      1.1   chopps     msc->closing = TRUE; /* flush remaining characters before dropping DTR */
    485      1.1   chopps   else
    486      1.1   chopps     ms->OutFlush = TRUE; /* just bitbucket remaining characters */
    487      1.1   chopps 
    488      1.2   chopps #if DEBUG_MSC
    489      1.2   chopps   bugi(msc, "close2");
    490      1.2   chopps #endif
    491      1.2   chopps 
    492      1.1   chopps   return (0);
    493      1.1   chopps 
    494      1.1   chopps }
    495      1.1   chopps 
    496      1.1   chopps int
    497      1.1   chopps mscread(dev, uio, flag)
    498      1.1   chopps 	dev_t dev;
    499      1.1   chopps 	struct uio *uio;
    500      1.1   chopps 	int flag;
    501      1.1   chopps {
    502      1.1   chopps 	register struct tty *tp;
    503      1.1   chopps 
    504      1.1   chopps 	tp = msc_tty[MSCTTY(dev)];
    505      1.1   chopps 
    506      1.1   chopps 	if (! tp)
    507      1.1   chopps 	 return ENXIO;
    508      1.1   chopps 
    509      1.1   chopps 	return((*linesw[tp->t_line].l_read)(tp, uio, flag));
    510      1.1   chopps }
    511      1.1   chopps 
    512      1.1   chopps int
    513      1.1   chopps mscwrite(dev, uio, flag)
    514      1.1   chopps 	dev_t dev;
    515      1.1   chopps 	struct uio *uio;
    516      1.1   chopps 	int flag;
    517      1.1   chopps {
    518      1.1   chopps   register struct tty *tp;
    519      1.1   chopps 
    520      1.1   chopps   tp = msc_tty[MSCTTY(dev)];
    521      1.1   chopps 
    522      1.1   chopps   if (! tp)
    523      1.1   chopps     return ENXIO;
    524      1.1   chopps 
    525      1.1   chopps   return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
    526      1.1   chopps }
    527      1.1   chopps 
    528      1.1   chopps /*
    529      1.1   chopps  * This interrupt is periodically invoked in the vertical blank
    530      1.1   chopps  * interrupt. It's used to keep track of the modem control lines
    531      1.1   chopps  * and (new with the fast_int code) to move accumulated data up in
    532      1.1   chopps  * to the tty layer.
    533      1.1   chopps  *
    534      1.1   chopps  * NOTE: MSCCDHACK is an invention of mine for dubious purposes. If you
    535      1.1   chopps  *	 want to activate it add
    536      1.1   chopps  *	 options MSCCDHACK
    537      1.1   chopps  *	 in the kernel conf file. Basically it forces CD->Low transitions
    538      1.1   chopps  *	 to ALWAYS send a signal to the process, even if the device is in
    539      1.1   chopps  *	 clocal mode or an outdial device. RFH
    540      1.1   chopps  */
    541      1.1   chopps void
    542      1.1   chopps mscmint (data)
    543      1.1   chopps 	register void *data;
    544      1.1   chopps {
    545      1.1   chopps   int unit;
    546      1.1   chopps   register struct tty *tp;
    547      1.1   chopps   int slot;
    548      1.1   chopps   int maxslot;
    549      1.1   chopps   struct mscdevice *msc;
    550      1.1   chopps   volatile struct mscstatus *ms;
    551      1.1   chopps   volatile u_char *ibuf, *cbuf;
    552      1.1   chopps   unsigned char newhead; /* was int */
    553      1.1   chopps   unsigned char bufpos;  /* was int */
    554      1.1   chopps   int s;
    555      1.1   chopps 
    556      1.1   chopps   unit = (int) data;
    557      1.1   chopps 
    558      1.1   chopps   /* check each line on this board */
    559      1.1   chopps   maxslot = MSCSLOTUL(unit, NUMLINES);
    560      1.1   chopps   if (maxslot > MSCSLOTS)
    561      1.1   chopps     maxslot = MSCSLOTS;
    562      1.1   chopps 
    563      1.1   chopps   for (slot = MSCSLOTUL(unit, 0); slot < maxslot; slot++)
    564      1.1   chopps     {
    565      1.1   chopps       msc = &mscdev[slot];
    566      1.1   chopps 
    567      1.1   chopps       if (!msc->active)
    568      1.1   chopps         continue;
    569      1.1   chopps 
    570      1.1   chopps       tp = msc_tty[MSCTTYSLOT(slot)];
    571      1.1   chopps       ms = &msc->board->Status[msc->port];
    572      1.1   chopps 
    573      1.1   chopps       newhead = ms->InHead;		/* 65c02 write pointer */
    574      1.1   chopps 
    575      1.1   chopps       /* yoohoo, is the port open? */
    576      1.1   chopps       if (tp && (tp->t_state & (TS_ISOPEN|TS_WOPEN))) {
    577      1.1   chopps 	/* port is open, handle all type of events */
    578      1.1   chopps 
    579      1.1   chopps 	/* set interrupt priority level */
    580      1.1   chopps         s = spltty();
    581      1.1   chopps 
    582      1.1   chopps       /* check for input for this port */
    583      1.1   chopps       if (newhead != (bufpos = ms->InTail))
    584      1.1   chopps       {
    585      1.1   chopps #if DEBUG_MSC
    586      1.1   chopps 	      printf("iop%d\n",slot);
    587      1.1   chopps #endif
    588      1.1   chopps 	      /* buffer for input chars/events */
    589      1.1   chopps 	      ibuf = &msc->board->InBuf[msc->port][0];
    590      1.1   chopps 
    591      1.1   chopps 	      /* data types of bytes in ibuf */
    592      1.1   chopps 	      cbuf = &msc->board->InCtl[msc->port][0];
    593      1.1   chopps 
    594      1.1   chopps 	      /* do for all chars, if room */
    595      1.1   chopps 	      while (bufpos != newhead)
    596      1.1   chopps 	      {
    597      1.1   chopps 		  /* which type of input data? */
    598      1.1   chopps 		  switch (cbuf[bufpos])
    599      1.1   chopps 		  {
    600      1.1   chopps 		      /* input event (CD, BREAK, etc.) */
    601      1.1   chopps 		      case MSCINCTL_EVENT:
    602      1.1   chopps 			switch (ibuf[bufpos++])
    603      1.1   chopps 			{
    604      1.1   chopps 			    /* carrier detect change OFF -> ON */
    605      1.1   chopps 			    case MSCEVENT_CarrierOn:
    606      1.1   chopps #if DEBUG_CD
    607      1.2   chopps 			      printf("msc  CD ON %d\n", msc->port);
    608      1.1   chopps #endif
    609      1.1   chopps 			      msc->flags |= TIOCM_CD;
    610      1.2   chopps 			      if (MSCDIALIN(tp->t_dev))
    611      1.1   chopps 				(*linesw[tp->t_line].l_modem)(tp, 1);
    612      1.1   chopps 			      break;
    613      1.1   chopps 
    614      1.1   chopps 			    /*  carrier detect change ON -> OFF */
    615      1.1   chopps 			    case MSCEVENT_CarrierOff:
    616      1.1   chopps #if DEBUG_CD
    617      1.2   chopps 			      printf("msc  CD OFF %d\n", msc->port);
    618      1.1   chopps #endif
    619      1.1   chopps 			      msc->flags &= ~TIOCM_CD;
    620      1.1   chopps #ifndef MSCCDHACK
    621      1.2   chopps 			      if (MSCDIALIN(tp->t_dev))
    622      1.2   chopps #endif			    /* Note to format police: Don't merge the { below
    623      1.2   chopps 			       in to the line above! */
    624      1.1   chopps 			      {
    625      1.1   chopps 				  if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
    626      1.1   chopps 				  {
    627      1.1   chopps 				      /* clear RTS and DTR, bitbucket output */
    628      1.1   chopps 				      ms->Command = (ms->Command & ~MSCCMD_CMask) | MSCCMD_Close;
    629      1.1   chopps 				      ms->Setup = TRUE;
    630      1.1   chopps 				      msc->flags &= ~(TIOCM_DTR | TIOCM_RTS);
    631      1.1   chopps 				      ms->OutFlush = TRUE;
    632      1.1   chopps 				  }
    633      1.1   chopps 			      }
    634      1.1   chopps 			      break;
    635      1.1   chopps 
    636      1.1   chopps 			    case MSCEVENT_Break:
    637      1.1   chopps #if DEBUG_MSC
    638      1.1   chopps 			      printf("Break received on msc%d\n", slot);
    639      1.1   chopps #endif
    640      1.1   chopps 			      (*linesw[tp->t_line].l_rint)(TTY_FE, tp);
    641      1.1   chopps 			      break;
    642      1.1   chopps 
    643      1.1   chopps 			    default:
    644      1.1   chopps 			      printf("msc: unknown event type %d\n",
    645      1.1   chopps 				      ibuf[(bufpos-1)&0xff]);
    646      1.1   chopps 
    647      1.1   chopps 			} /* event type switch */
    648      1.1   chopps 			break;
    649      1.1   chopps 
    650      1.1   chopps 		      case MSCINCTL_CHAR:
    651      1.2   chopps 			 if (tp->t_state & TS_TBLOCK) {
    652      1.2   chopps 			   if (ms->chCD) {
    653      1.2   chopps 			     /* Carrier detect ON -> OFF */
    654      1.2   chopps #if DEBUG_CD
    655      1.2   chopps 			     printf("msc  CD OFF blocked %d msc->flags %08lx\n",
    656      1.2   chopps 				    msc->port, msc->flags);
    657      1.2   chopps #endif
    658      1.2   chopps 			     msc->flags &= ~TIOCM_CD;
    659      1.2   chopps 
    660      1.2   chopps #ifndef MSCCDHACK
    661      1.2   chopps 			     if (MSCDIALIN(tp->t_dev))
    662      1.2   chopps #endif
    663      1.2   chopps 			     {
    664      1.2   chopps 			       if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
    665      1.2   chopps 				 /* Clear RTS and DTR, bitbucket output */
    666      1.2   chopps 				 ms->Command = (ms->Command & ~MSCCMD_CMask) |
    667      1.2   chopps 					       MSCCMD_Close;
    668      1.2   chopps 				 ms->Setup = TRUE;
    669      1.2   chopps 				 msc->flags &= ~(TIOCM_DTR | TIOCM_RTS);
    670      1.2   chopps 				 ms->OutFlush = TRUE;
    671      1.2   chopps 			       }
    672      1.2   chopps 			     }
    673      1.2   chopps 			   }
    674      1.1   chopps 			   goto NoRoomForYa;
    675      1.2   chopps 			 }
    676      1.1   chopps #if DEBUG_MSC
    677      1.1   chopps 			 printf("'%c' ",ibuf[bufpos]);
    678      1.1   chopps #endif
    679      1.1   chopps 			 (*linesw[tp->t_line].l_rint)((int)ibuf[bufpos++], tp);
    680      1.1   chopps 			break;
    681      1.1   chopps 
    682      1.1   chopps 		      default:
    683      1.1   chopps 			printf("msc: unknown data type %d\n", cbuf[bufpos]);
    684      1.1   chopps 			bufpos++;
    685      1.1   chopps 
    686      1.1   chopps 		   } /* switch on input data type */
    687      1.1   chopps 
    688      1.1   chopps 		} /* while there's something in the buffer */
    689      1.1   chopps NoRoomForYa:
    690      1.1   chopps 	      ms->InTail = bufpos;		/* tell 65C02 what we've read */
    691      1.1   chopps 
    692      1.1   chopps 	    } /* if there was something in the buffer */
    693      1.1   chopps 
    694      1.1   chopps 	  /* we get here only when the port is open */
    695      1.1   chopps 	  /* send output */
    696      1.1   chopps 	   if (tp->t_state & (TS_BUSY|TS_FLUSH))
    697      1.1   chopps 	    {
    698      1.1   chopps 
    699      1.1   chopps 	      bufpos = ms->OutHead - ms->OutTail;
    700      1.1   chopps 
    701      1.1   chopps 	      /* busy and below low water mark? */
    702      1.1   chopps 	      if (tp->t_state & TS_BUSY)
    703      1.1   chopps 	        {
    704      1.1   chopps 	          if (bufpos < IOBUFLOWWATER)
    705      1.1   chopps 		    {
    706      1.1   chopps 		      tp->t_state &= ~TS_BUSY;	/* not busy any more */
    707      1.1   chopps 		      if (tp->t_line)
    708      1.1   chopps 		        (*linesw[tp->t_line].l_start)(tp);
    709      1.1   chopps 		      else
    710      1.1   chopps 		        mscstart(tp);
    711      1.1   chopps 		    }
    712      1.1   chopps 		}
    713      1.1   chopps 
    714      1.1   chopps 	      /* waiting for flush and buffer empty? */
    715      1.1   chopps 	      if (tp->t_state & TS_FLUSH)
    716      1.1   chopps 	        {
    717      1.1   chopps 	          if (bufpos == 0)
    718      1.1   chopps 	            tp->t_state &= ~TS_FLUSH;	/* finished flushing */
    719      1.1   chopps 	        }
    720      1.1   chopps 	    } /* BUSY or FLUSH */
    721      1.1   chopps 
    722      1.1   chopps 	     splx(s);
    723      1.1   chopps 
    724      1.1   chopps       } else { /* End of port open */
    725      1.1   chopps 	/* port is closed, don't pass on the chars from it */
    726      1.1   chopps 
    727      1.1   chopps       /* check for input for this port */
    728      1.1   chopps       if (newhead != (bufpos = ms->InTail))
    729      1.1   chopps       {
    730      1.1   chopps #if DEBUG_MSC
    731      1.1   chopps 	      printf("icp%d\n",slot);
    732      1.1   chopps #endif
    733      1.1   chopps 	      /* buffer for input chars/events */
    734      1.1   chopps 	      ibuf = &msc->board->InBuf[msc->port][0];
    735      1.1   chopps 
    736      1.1   chopps 	      /* data types of bytes in ibuf */
    737      1.1   chopps 	      cbuf = &msc->board->InCtl[msc->port][0];
    738      1.1   chopps 
    739      1.1   chopps 	      /* do for all chars, if room */
    740      1.1   chopps 	      while (bufpos != newhead)
    741      1.1   chopps 	      {
    742      1.1   chopps 		  /* which type of input data? */
    743      1.1   chopps 		  switch (cbuf[bufpos])
    744      1.1   chopps 		  {
    745      1.1   chopps 		      /* input event (CD, BREAK, etc.) */
    746      1.1   chopps 		      case MSCINCTL_EVENT:
    747      1.1   chopps 			switch (ibuf[bufpos++])
    748      1.1   chopps 			{
    749      1.1   chopps 			    /* carrier detect change OFF -> ON */
    750      1.1   chopps 			    case MSCEVENT_CarrierOn:
    751      1.1   chopps #if DEBUG_CD
    752      1.2   chopps 			      printf("msc  CD ON %d (closed)\n", msc->port);
    753      1.1   chopps #endif
    754      1.1   chopps 			      msc->flags |= TIOCM_CD;
    755      1.1   chopps 			      break;
    756      1.1   chopps 
    757      1.1   chopps 			    /*  carrier detect change ON -> OFF */
    758      1.1   chopps 			    case MSCEVENT_CarrierOff:
    759      1.1   chopps #if DEBUG_CD
    760      1.2   chopps 			      printf("msc  CD OFF %d (closed)\n", msc->port);
    761      1.1   chopps #endif
    762      1.1   chopps 			      msc->flags &= ~TIOCM_CD;
    763      1.1   chopps #ifndef MSCCDHACK
    764      1.1   chopps 			      if (tp && MSCDIALIN(tp->t_dev))
    765      1.1   chopps #else
    766      1.1   chopps 			      if (tp )
    767      1.1   chopps #endif
    768      1.1   chopps 			      {
    769      1.1   chopps 				  if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
    770      1.1   chopps 				  {
    771      1.1   chopps 				      /* clear RTS and DTR, bitbucket output */
    772      1.1   chopps 				      ms->Command = (ms->Command & ~MSCCMD_CMask) | MSCCMD_Close;
    773      1.1   chopps 				      ms->Setup = TRUE;
    774      1.1   chopps 				      msc->flags &= ~(TIOCM_DTR | TIOCM_RTS);
    775      1.1   chopps 				      ms->OutFlush = TRUE;
    776      1.1   chopps 				  }
    777      1.1   chopps 			      }
    778      1.1   chopps 			      break;
    779      1.1   chopps 
    780      1.1   chopps 			    default:
    781      1.1   chopps 			      printf("msc: unknown event type %d\n",
    782      1.1   chopps 				     ibuf[(bufpos-1)&0xff]);
    783      1.1   chopps 
    784      1.1   chopps 			} /* event type switch */
    785      1.1   chopps 			break;
    786      1.1   chopps 
    787      1.1   chopps 		      default:
    788      1.2   chopps 			bufpos++;
    789      1.1   chopps 
    790      1.1   chopps 		   } /* switch on input data type */
    791      1.1   chopps 
    792      1.1   chopps 		} /* while there's something in the buffer */
    793      1.1   chopps 
    794      1.1   chopps 	        ms->InTail = bufpos;		/* tell 65C02 what we've read */
    795      1.1   chopps 
    796      1.1   chopps 	    } /* if there was something in the buffer */
    797      1.1   chopps       } /* End of port open/close */
    798      1.1   chopps 
    799      1.1   chopps       /* is this port closing? */
    800      1.1   chopps       if (msc->closing)
    801      1.1   chopps         {
    802      1.1   chopps 	  /* if DTR is off, just bitbucket remaining characters */
    803      1.1   chopps 	  if ( (msc->flags & TIOCM_DTR) == 0)
    804      1.1   chopps 	    {
    805      1.1   chopps 	      ms->OutFlush = TRUE;
    806      1.1   chopps 	      msc->closing = FALSE;
    807      1.1   chopps 	    }
    808      1.1   chopps 	  /* if output has drained, drop DTR */
    809      1.1   chopps           else if (ms->OutHead == ms->OutTail)
    810      1.1   chopps 	    {
    811      1.1   chopps 	      (void) mscmctl(tp->t_dev, 0, DMSET);
    812      1.1   chopps 	      msc->closing = FALSE;
    813      1.1   chopps             }
    814      1.1   chopps         }
    815      1.1   chopps     }  /* For all ports */
    816      1.1   chopps 
    817      1.1   chopps }
    818      1.1   chopps 
    819      1.1   chopps int
    820      1.1   chopps mscioctl(dev, cmd, data, flag, p)
    821      1.1   chopps 	dev_t dev;
    822      1.6    veego 	u_long cmd;
    823      1.1   chopps 	caddr_t data;
    824      1.1   chopps 	int flag;
    825      1.1   chopps 	struct proc *p;
    826      1.1   chopps {
    827      1.1   chopps   register struct tty *tp;
    828      1.1   chopps   register int slot;
    829      1.1   chopps   register int error;
    830      1.1   chopps   struct mscdevice *msc;
    831      1.1   chopps   volatile struct mscstatus *ms;
    832      1.1   chopps   int s;
    833      1.1   chopps 
    834      1.1   chopps   /* get the device structure */
    835      1.1   chopps   slot = MSCSLOT(dev);
    836      1.1   chopps 
    837      1.1   chopps   if (slot >= MSCSLOTS)
    838      1.1   chopps     return ENXIO;
    839      1.1   chopps 
    840      1.1   chopps   msc = &mscdev[slot];
    841      1.1   chopps 
    842      1.1   chopps   if (!msc->active)
    843      1.1   chopps     return ENXIO;
    844      1.1   chopps 
    845      1.1   chopps   ms = &msc->board->Status[msc->port];
    846      1.2   chopps   if (!(tp = msc_tty[MSCTTY(dev)]))
    847      1.2   chopps     return ENXIO;
    848      1.1   chopps 
    849      1.1   chopps   error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    850      1.1   chopps 
    851      1.1   chopps   if (error >= 0)
    852      1.1   chopps     return (error);
    853      1.1   chopps 
    854      1.1   chopps   error = ttioctl(tp, cmd, data, flag, p);
    855      1.1   chopps 
    856      1.1   chopps   if (error >= 0)
    857      1.1   chopps     return (error);
    858      1.1   chopps 
    859      1.1   chopps   switch (cmd) {
    860      1.1   chopps 
    861      1.1   chopps       /* send break */
    862      1.1   chopps     case TIOCSBRK:
    863      1.1   chopps       s = spltty();
    864      1.1   chopps       ms->Command = (ms->Command & (~MSCCMD_RTSMask)) | MSCCMD_Break;
    865      1.1   chopps       ms->Setup = TRUE;
    866      1.1   chopps       splx(s);
    867      1.1   chopps       break;
    868      1.1   chopps 
    869      1.1   chopps       /* clear break */
    870      1.1   chopps     case TIOCCBRK:
    871      1.1   chopps       s = spltty();
    872      1.1   chopps       ms->Command = (ms->Command & (~MSCCMD_RTSMask)) | MSCCMD_RTSOn;
    873      1.1   chopps       ms->Setup = TRUE;
    874      1.1   chopps       splx(s);
    875      1.1   chopps       break;
    876      1.1   chopps 
    877      1.1   chopps     case TIOCSDTR:
    878      1.1   chopps       (void) mscmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIS);
    879      1.1   chopps       break;
    880      1.1   chopps 
    881      1.1   chopps     case TIOCCDTR:
    882      1.1   chopps       if (!MSCDIALIN(dev))	/* don't let dialins drop DTR */
    883      1.1   chopps         (void) mscmctl(dev, TIOCM_DTR | TIOCM_RTS, DMBIC);
    884      1.1   chopps       break;
    885      1.1   chopps 
    886      1.1   chopps     case TIOCMSET:
    887      1.1   chopps       (void) mscmctl(dev, *(int *)data, DMSET);
    888      1.1   chopps       break;
    889      1.1   chopps 
    890      1.1   chopps     case TIOCMBIS:
    891      1.1   chopps       (void) mscmctl(dev, *(int *)data, DMBIS);
    892      1.1   chopps       break;
    893      1.1   chopps 
    894      1.1   chopps     case TIOCMBIC:
    895      1.1   chopps       if (MSCDIALIN(dev))	/* don't let dialins drop DTR */
    896      1.1   chopps         (void) mscmctl(dev, *(int *)data & TIOCM_DTR, DMBIC);
    897      1.1   chopps       else
    898      1.1   chopps         (void) mscmctl(dev, *(int *)data, DMBIC);
    899      1.1   chopps       break;
    900      1.1   chopps 
    901      1.1   chopps     case TIOCMGET:
    902      1.1   chopps       *(int *)data = mscmctl(dev, 0, DMGET);
    903      1.1   chopps       break;
    904      1.1   chopps 
    905      1.1   chopps     case TIOCGFLAGS:
    906      1.1   chopps       *(int *)data = SWFLAGS(dev);
    907      1.1   chopps       break;
    908      1.1   chopps 
    909      1.1   chopps     case TIOCSFLAGS:
    910      1.1   chopps       error = suser(p->p_ucred, &p->p_acflag);
    911      1.1   chopps       if (error != 0)
    912      1.1   chopps               return(EPERM);
    913      1.1   chopps 
    914      1.1   chopps       msc->openflags = *(int *)data;
    915      1.1   chopps 
    916      1.1   chopps       /* only allow valid flags */
    917      1.1   chopps       msc->openflags &= (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL | TIOCFLAG_CRTSCTS);
    918      1.1   chopps 
    919      1.1   chopps       break;
    920      1.1   chopps 
    921      1.1   chopps     default:
    922      1.1   chopps       return (ENOTTY);
    923      1.1   chopps     }
    924      1.1   chopps 
    925      1.1   chopps   return (0);
    926      1.1   chopps }
    927      1.1   chopps 
    928      1.1   chopps 
    929      1.1   chopps int
    930      1.1   chopps mscparam(tp, t)
    931      1.1   chopps 	register struct tty *tp;
    932      1.1   chopps 	register struct termios *t;
    933      1.1   chopps {
    934      1.6    veego   register int cflag = t->c_cflag;
    935      1.1   chopps   int slot;
    936      1.1   chopps   struct mscdevice *msc;
    937      1.1   chopps   volatile struct mscstatus *ms;
    938      1.1   chopps   int s;
    939      1.1   chopps   int ospeed = ttspeedtab(t->c_ospeed, mscspeedtab);
    940      1.1   chopps 
    941      1.1   chopps   /* get the device structure */
    942      1.1   chopps   slot = MSCSLOT(tp->t_dev);
    943      1.1   chopps 
    944      1.1   chopps   if (slot >= MSCSLOTS)
    945      1.1   chopps     return ENXIO;
    946      1.1   chopps 
    947      1.1   chopps   msc = &mscdev[slot];
    948      1.1   chopps 
    949      1.1   chopps   if (!msc->active)
    950      1.1   chopps     return ENXIO;
    951      1.1   chopps 
    952      1.1   chopps   ms = &msc->board->Status[msc->port];
    953      1.1   chopps 
    954      1.2   chopps #if DEBUG_MSC
    955      1.2   chopps   bugi(msc, "param1");
    956      1.2   chopps #endif
    957      1.1   chopps   /* check requested parameters */
    958      1.1   chopps   if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
    959      1.1   chopps     return (EINVAL);
    960      1.1   chopps 
    961      1.1   chopps   /* and copy to tty */
    962      1.1   chopps   tp->t_ispeed = t->c_ispeed;
    963      1.1   chopps   tp->t_ospeed = t->c_ospeed;
    964      1.1   chopps   tp->t_cflag = cflag;
    965      1.1   chopps 
    966      1.1   chopps   /* hang up if baud is zero */
    967      1.1   chopps   if (t->c_ospeed == 0) {
    968      1.1   chopps 
    969      1.1   chopps       if (!MSCDIALIN(tp->t_dev))  /* don't let dialins drop DTR */
    970      1.1   chopps         (void) mscmctl(tp->t_dev, 0, DMSET);
    971      1.1   chopps   }
    972      1.1   chopps   else {
    973      1.1   chopps 
    974      1.1   chopps       /* set the baud rate */
    975      1.1   chopps       s = spltty();
    976      1.1   chopps       ms->Param = (ms->Param & ~MSCPARAM_BaudMask) | ospeed | MSCPARAM_RcvBaud;
    977      1.1   chopps 
    978      1.1   chopps       /* make sure any previous hangup is undone, ie.  reenable DTR.
    979      1.1   chopps        * also mscmctl will cause the speed to be set
    980      1.1   chopps        */
    981      1.1   chopps       (void) mscmctl (tp->t_dev, TIOCM_DTR | TIOCM_RTS, DMSET);
    982      1.2   chopps 
    983      1.1   chopps       splx(s);
    984      1.1   chopps   }
    985      1.1   chopps 
    986      1.2   chopps #if DEBUG_MSC
    987      1.2   chopps   bugi(msc, "param2");
    988      1.2   chopps #endif
    989      1.1   chopps   return (0);
    990      1.1   chopps 
    991      1.1   chopps }
    992      1.1   chopps 
    993      1.1   chopps 
    994      1.1   chopps /*
    995      1.1   chopps  *	Jukka's code initializes alot of stuff that other drivers don't
    996      1.1   chopps  *	I'm including it here so that this code is a common set of work
    997      1.1   chopps  *	done by both of us. rfh
    998      1.1   chopps  */
    999      1.1   chopps int
   1000      1.1   chopps mschwiflow(tp, flag)
   1001      1.1   chopps 	struct tty *tp;
   1002      1.1   chopps 	int flag;
   1003      1.1   chopps {
   1004      1.1   chopps 
   1005      1.1   chopps /* Rob's version */
   1006      1.1   chopps #if 1
   1007      1.1   chopps #if DEBUG_MSC
   1008      1.1   chopps 	printf("mschwiflow %d\n", flag);
   1009      1.1   chopps #endif
   1010      1.1   chopps 
   1011      1.1   chopps 	if (flag)
   1012      1.1   chopps 	   mscmctl( tp->t_dev, TIOCM_RTS, DMBIC); /* Clear/Lower RTS */
   1013      1.1   chopps 	else
   1014      1.1   chopps 	   mscmctl( tp->t_dev, TIOCM_RTS, DMBIS); /* Set/Raise RTS */
   1015      1.1   chopps 
   1016      1.1   chopps #endif
   1017      1.1   chopps 
   1018      1.1   chopps /* Jukka's version */
   1019      1.1   chopps #if 0
   1020      1.1   chopps   int slot;
   1021      1.1   chopps   struct mscdevice *msc;
   1022      1.1   chopps   volatile struct mscstatus *ms;
   1023      1.1   chopps   int s;
   1024      1.1   chopps 
   1025      1.1   chopps   /* get the device structure */
   1026      1.1   chopps   slot = MSCSLOT(tp->t_dev);
   1027      1.1   chopps   if (slot >= MSCSLOTS)
   1028      1.1   chopps     return ENXIO;
   1029      1.1   chopps   msc = &mscdev[slot];
   1030      1.1   chopps   if (!msc->active)
   1031      1.1   chopps     return ENXIO;
   1032      1.1   chopps   ms = &msc->board->Status[msc->port];
   1033      1.1   chopps 
   1034      1.2   chopps #if DEBUG_MSC
   1035      1.2   chopps   bugi(msc, "hwiflow");
   1036      1.2   chopps #endif
   1037      1.1   chopps   /* Well, we should really _do_ something here, but the 65c02 code
   1038      1.1   chopps    * manages the RTS signal on its own now, so...  This will probably
   1039      1.1   chopps    * change in the future.
   1040      1.1   chopps    */
   1041      1.1   chopps 
   1042      1.1   chopps #endif
   1043      1.1   chopps 	return 1;
   1044      1.1   chopps 
   1045      1.1   chopps }
   1046      1.1   chopps 
   1047      1.6    veego void
   1048      1.1   chopps mscstart(tp)
   1049      1.1   chopps 	register struct tty *tp;
   1050      1.1   chopps {
   1051      1.1   chopps   register int cc;
   1052      1.1   chopps   register char *cp;
   1053      1.1   chopps   register int mhead;
   1054      1.1   chopps   int s;
   1055      1.1   chopps   int slot;
   1056      1.1   chopps   struct mscdevice *msc;
   1057      1.1   chopps   volatile struct mscstatus *ms;
   1058      1.1   chopps   volatile char *mob;
   1059      1.1   chopps   int hiwat = 0;
   1060      1.1   chopps   int maxout;
   1061      1.1   chopps 
   1062      1.1   chopps   if (! (tp->t_state & TS_ISOPEN))
   1063      1.1   chopps     return;
   1064      1.1   chopps 
   1065      1.1   chopps   slot = MSCSLOT(tp->t_dev);
   1066      1.1   chopps 
   1067      1.1   chopps #if 0
   1068      1.1   chopps   printf("starting msc%d\n", slot);
   1069      1.1   chopps #endif
   1070      1.1   chopps 
   1071      1.1   chopps   s = spltty();
   1072      1.1   chopps 
   1073      1.1   chopps   /* don't start if explicitly stopped */
   1074      1.1   chopps   if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
   1075      1.1   chopps     goto out;
   1076      1.1   chopps 
   1077      1.1   chopps   /* wake up if below low water */
   1078      1.1   chopps   cc = tp->t_outq.c_cc;
   1079      1.1   chopps 
   1080      1.1   chopps   if (cc <= tp->t_lowat) {
   1081      1.1   chopps       if (tp->t_state & TS_ASLEEP) {
   1082      1.1   chopps 
   1083      1.1   chopps 	  tp->t_state &= ~TS_ASLEEP;
   1084      1.1   chopps 	  wakeup((caddr_t)&tp->t_outq);
   1085      1.1   chopps 	}
   1086      1.1   chopps 
   1087      1.1   chopps       selwakeup(&tp->t_wsel);
   1088      1.1   chopps   }
   1089      1.1   chopps 
   1090      1.1   chopps   /* don't bother if no characters or busy */
   1091      1.2   chopps   if (cc == 0 || (tp->t_state & TS_BUSY))
   1092      1.1   chopps     goto out;
   1093      1.1   chopps 
   1094      1.1   chopps   /*
   1095      1.1   chopps    * Limit the amount of output we do in one burst
   1096      1.1   chopps    */
   1097      1.1   chopps   msc = &mscdev[slot];
   1098      1.1   chopps   ms = &msc->board->Status[msc->port];
   1099      1.1   chopps   mhead = ms->OutHead;
   1100      1.1   chopps   maxout = mhead - ms->OutTail;
   1101      1.1   chopps 
   1102      1.1   chopps   if (maxout < 0)
   1103      1.1   chopps       maxout += IOBUFLEN;
   1104      1.1   chopps 
   1105      1.1   chopps   maxout = IOBUFLEN - 1 - maxout;
   1106      1.1   chopps 
   1107      1.1   chopps   if (cc >= maxout) {
   1108      1.1   chopps       hiwat++;
   1109      1.1   chopps       cc = maxout;
   1110      1.1   chopps   }
   1111      1.1   chopps 
   1112      1.1   chopps   cc = q_to_b (&tp->t_outq, msc->tmpbuf, cc);
   1113      1.1   chopps 
   1114      1.1   chopps   if (cc > 0) {
   1115      1.1   chopps       tp->t_state |= TS_BUSY;
   1116      1.1   chopps 
   1117      1.1   chopps       mob = &msc->board->OutBuf[msc->port][0];
   1118      1.1   chopps       cp = &msc->tmpbuf[0];
   1119      1.1   chopps 
   1120      1.1   chopps       /* enable output */
   1121      1.1   chopps       ms->OutDisable = FALSE;
   1122      1.1   chopps 
   1123      1.1   chopps #if 0
   1124      1.1   chopps       msc->tmpbuf[cc] = 0;
   1125      1.1   chopps       printf("sending '%s'\n", msctmpbuf);
   1126      1.1   chopps #endif
   1127      1.1   chopps 
   1128      1.1   chopps       /* send the first char across to reduce latency */
   1129      1.1   chopps       mob[mhead++] = *cp++;
   1130      1.1   chopps       mhead &= IOBUFLENMASK;
   1131      1.1   chopps       ms->OutHead = mhead;
   1132      1.1   chopps       cc--;
   1133      1.1   chopps 
   1134      1.1   chopps       /* copy the rest of the chars across quickly */
   1135      1.1   chopps       while (cc > 0) {
   1136      1.1   chopps 	  mob[mhead++] = *cp++;
   1137      1.1   chopps 	  mhead &= IOBUFLENMASK;
   1138      1.1   chopps 	  cc--;
   1139      1.1   chopps       }
   1140      1.1   chopps       ms->OutHead = mhead;
   1141      1.1   chopps 
   1142      1.1   chopps       /* leave the device busy if we've filled the buffer */
   1143      1.1   chopps       if (!hiwat)
   1144      1.1   chopps         tp->t_state &= ~TS_BUSY;
   1145      1.1   chopps     }
   1146      1.1   chopps 
   1147      1.1   chopps out:
   1148      1.1   chopps   splx(s);
   1149      1.1   chopps 
   1150      1.1   chopps }
   1151      1.1   chopps 
   1152      1.1   chopps /* XXX */
   1153      1.1   chopps /*
   1154      1.1   chopps  * Stop output on a line.
   1155      1.1   chopps  */
   1156      1.1   chopps /*ARGSUSED*/
   1157      1.1   chopps int
   1158      1.1   chopps mscstop(tp, flag)
   1159      1.1   chopps 	register struct tty *tp;
   1160      1.1   chopps 	int flag;			/* defaulted to int anyway */
   1161      1.1   chopps {
   1162      1.1   chopps 	register int s;
   1163      1.6    veego #if 0
   1164      1.1   chopps 	struct mscdevice *msc;
   1165      1.1   chopps 	volatile struct mscstatus *ms;
   1166      1.6    veego #endif
   1167      1.1   chopps 
   1168      1.1   chopps 	s = spltty();
   1169      1.1   chopps 	if (tp->t_state & TS_BUSY) {
   1170      1.6    veego 		if ((tp->t_state & TS_TTSTOP) == 0) {
   1171      1.1   chopps 			tp->t_state |= TS_FLUSH;
   1172      1.1   chopps #if 0
   1173      1.1   chopps 			msc = &mscdev[MSCSLOT(tp->t_dev)];
   1174      1.1   chopps 			ms = &msc->board->Status[msc->port];
   1175      1.1   chopps 			printf("stopped output on msc%d\n", MSCSLOT(tp->t_dev));
   1176      1.1   chopps 			ms->OutDisable = TRUE;
   1177      1.1   chopps #endif
   1178      1.1   chopps 		}
   1179      1.1   chopps 	}
   1180      1.1   chopps 	splx(s);
   1181      1.6    veego 	return 0;
   1182      1.1   chopps }
   1183      1.1   chopps 
   1184      1.1   chopps /*
   1185      1.1   chopps  * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR
   1186      1.1   chopps  */
   1187      1.1   chopps int
   1188      1.1   chopps mscmctl(dev, bits, how)
   1189      1.1   chopps 	dev_t dev;
   1190      1.1   chopps 	int bits, how;
   1191      1.1   chopps {
   1192      1.1   chopps   struct mscdevice *msc;
   1193      1.1   chopps   volatile struct mscstatus *ms;
   1194      1.1   chopps   int slot;
   1195      1.1   chopps   int s;
   1196      1.1   chopps   u_char newcmd;
   1197      1.1   chopps   int OldFlags;
   1198      1.1   chopps 
   1199      1.1   chopps   /* get the device structure */
   1200      1.1   chopps   slot = MSCSLOT(dev);
   1201      1.1   chopps 
   1202      1.1   chopps   if (slot >= MSCSLOTS)
   1203      1.1   chopps     return ENXIO;
   1204      1.1   chopps 
   1205      1.1   chopps   msc = &mscdev[slot];
   1206      1.1   chopps 
   1207      1.1   chopps   if (!msc->active)
   1208      1.1   chopps     return ENXIO;
   1209      1.1   chopps 
   1210      1.2   chopps #if DEBUG_MSC
   1211      1.2   chopps   bugi(msc, "mctl1");
   1212      1.2   chopps #endif
   1213      1.2   chopps 
   1214      1.2   chopps   s = spltty();		/* Jukka wants spl6() here, WHY?!! RFH */
   1215      1.1   chopps 
   1216      1.1   chopps   if (how != DMGET) {
   1217      1.1   chopps       OldFlags = msc->flags;
   1218      1.1   chopps       bits &= TIOCM_DTR | TIOCM_RTS; /* can only modify DTR and RTS */
   1219      1.1   chopps 
   1220      1.1   chopps       switch (how) {
   1221      1.1   chopps         case DMSET:
   1222      1.1   chopps 	  msc->flags = (bits | (msc->flags & ~(TIOCM_DTR | TIOCM_RTS)));
   1223      1.1   chopps           break;
   1224      1.1   chopps 
   1225      1.1   chopps         case DMBIC:
   1226      1.1   chopps           msc->flags &= ~bits;
   1227      1.1   chopps           break;
   1228      1.1   chopps 
   1229      1.1   chopps         case DMBIS:
   1230      1.1   chopps           msc->flags |= bits;
   1231      1.1   chopps           break;
   1232      1.1   chopps       }
   1233      1.1   chopps 
   1234      1.2   chopps #if DEBUG_MSC
   1235      1.2   chopps     bugi(msc, "mctl2");
   1236      1.2   chopps #endif
   1237      1.2   chopps 
   1238      1.1   chopps       /* modify modem control state */
   1239      1.1   chopps       ms = &msc->board->Status[msc->port];
   1240      1.1   chopps 
   1241      1.1   chopps       if (msc->flags & TIOCM_RTS)	/* was bits & */
   1242      1.1   chopps 	newcmd = MSCCMD_RTSOn;
   1243      1.1   chopps       else			/* this doesn't actually work now */
   1244      1.1   chopps 	newcmd = MSCCMD_RTSOff;
   1245      1.1   chopps 
   1246      1.1   chopps       if (msc->flags & TIOCM_DTR)	/* was bits & */
   1247      1.1   chopps 	newcmd |= MSCCMD_Enable;
   1248      1.1   chopps 
   1249      1.1   chopps       ms->Command = (ms->Command & (~MSCCMD_RTSMask & ~MSCCMD_Enable)) | newcmd;
   1250      1.1   chopps       ms->Setup = TRUE;
   1251      1.1   chopps 
   1252      1.1   chopps       /* if we've dropped DTR, bitbucket any pending output */
   1253      1.1   chopps       if ( (OldFlags & TIOCM_DTR) && ((bits & TIOCM_DTR) == 0))
   1254      1.1   chopps         ms->OutFlush = TRUE;
   1255      1.1   chopps   }
   1256      1.1   chopps 
   1257      1.1   chopps   bits = msc->flags;
   1258      1.1   chopps 
   1259      1.1   chopps   (void) splx(s);
   1260      1.1   chopps 
   1261      1.2   chopps #if DEBUG_MSC
   1262      1.2   chopps     bugi(msc, "mctl3");
   1263      1.2   chopps #endif
   1264      1.2   chopps 
   1265      1.1   chopps   return(bits);
   1266      1.1   chopps 
   1267      1.1   chopps }
   1268      1.1   chopps 
   1269      1.1   chopps struct tty *
   1270      1.1   chopps msctty(dev)
   1271      1.1   chopps 	dev_t dev;
   1272      1.1   chopps {
   1273      1.1   chopps 	return(msc_tty[MSCTTY(dev)]);
   1274      1.1   chopps }
   1275      1.1   chopps 
   1276      1.1   chopps /*
   1277      1.1   chopps  * Load JM's freely redistributable A2232 6502c code. Let turbo detector
   1278      1.1   chopps  * run for a while too.
   1279      1.1   chopps  */
   1280      1.1   chopps 
   1281      1.1   chopps int
   1282      1.1   chopps mscinitcard(zap)
   1283      1.1   chopps 	struct zbus_args *zap;
   1284      1.1   chopps {
   1285      1.1   chopps   int bcount;
   1286      1.1   chopps   short start;
   1287      1.1   chopps   u_char *from;
   1288      1.1   chopps   volatile u_char *to;
   1289      1.1   chopps   volatile struct mscmemory *mlm;
   1290      1.1   chopps 
   1291      1.1   chopps   mlm = (volatile struct mscmemory *)zap->va;
   1292      1.1   chopps   (void)mlm->Enable6502Reset;
   1293      1.1   chopps 
   1294      1.1   chopps   /* copy the code across to the board */
   1295      1.1   chopps   to = (u_char *)mlm;
   1296      1.1   chopps   from = msc6502code; bcount = sizeof(msc6502code) - 2;
   1297      1.1   chopps   start = *(short *)from; from += sizeof(start);
   1298      1.1   chopps   to += start;
   1299      1.1   chopps 
   1300      1.1   chopps #if DEBUG_MSC
   1301      1.1   chopps   printf("\n** copying %ld bytes from %08lx to %08lx (start=%04lx)\n",
   1302      1.1   chopps 	  (unsigned long)bcount, (unsigned long)from, to, start);
   1303      1.1   chopps   printf("First byte to copy is %02lx\n", *from);
   1304      1.1   chopps #endif
   1305      1.1   chopps 
   1306      1.1   chopps   while(bcount--) *to++ = *from++;
   1307      1.1   chopps 
   1308      1.1   chopps   mlm->Common.Crystal = MSC_UNKNOWN;	/* use automatic speed check */
   1309      1.1   chopps 
   1310      1.2   chopps   /* start 6502 running */
   1311      1.1   chopps   (void)mlm->ResetBoard;
   1312      1.1   chopps 
   1313      1.1   chopps   /* wait until speed detector has finished */
   1314      1.1   chopps   for (bcount = 0; bcount < 200; bcount++) {
   1315      1.1   chopps 	delay(10000);
   1316      1.1   chopps 	if (mlm->Common.Crystal) break;
   1317      1.1   chopps   }
   1318      1.1   chopps 
   1319      1.1   chopps   return(0);
   1320      1.1   chopps 
   1321      1.1   chopps }
   1322      1.1   chopps 
   1323      1.1   chopps #endif  /* NMSC > 0 */
   1324