File:  [DragonFly] / src / sys / dev / serial / stli / istallion.c
Revision 1.10: download - view: text, annotated - select for diffs
Thu May 13 23:49:20 2004 UTC (10 years, 4 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*****************************************************************************/
    2: 
    3: /*
    4:  * istallion.c  -- stallion intelligent multiport serial driver.
    5:  *
    6:  * Copyright (c) 1994-1998 Greg Ungerer (gerg@stallion.oz.au).
    7:  * All rights reserved.
    8:  *
    9:  * Redistribution and use in source and binary forms, with or without
   10:  * modification, are permitted provided that the following conditions
   11:  * are met:
   12:  * 1. Redistributions of source code must retain the above copyright
   13:  *    notice, this list of conditions and the following disclaimer.
   14:  * 2. Redistributions in binary form must reproduce the above copyright
   15:  *    notice, this list of conditions and the following disclaimer in the
   16:  *    documentation and/or other materials provided with the distribution.
   17:  * 3. All advertising materials mentioning features or use of this software
   18:  *    must display the following acknowledgement:
   19:  *	This product includes software developed by Greg Ungerer.
   20:  * 4. Neither the name of the author nor the names of any co-contributors
   21:  *    may be used to endorse or promote products derived from this software
   22:  *    without specific prior written permission.
   23:  *
   24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34:  * SUCH DAMAGE.
   35:  *
   36:  * $FreeBSD: src/sys/i386/isa/istallion.c,v 1.36.2.2 2001/08/30 12:29:57 murray Exp $
   37:  * $DragonFly: src/sys/dev/serial/stli/istallion.c,v 1.10 2004/05/13 23:49:20 dillon Exp $
   38:  */
   39: 
   40: /*****************************************************************************/
   41: 
   42: #include "opt_compat.h"
   43: 
   44: #define	TTYDEFCHARS	1
   45: 
   46: #include <sys/param.h>
   47: #include <sys/systm.h>
   48: #include <sys/kernel.h>
   49: #include <sys/malloc.h>
   50: #include <sys/tty.h>
   51: #include <sys/proc.h>
   52: #include <sys/conf.h>
   53: #include <sys/fcntl.h>
   54: #include <sys/uio.h>
   55: #include <machine/clock.h>
   56: #include <vm/vm.h>
   57: #include <vm/pmap.h>
   58: #include <bus/isa/i386/isa_device.h>
   59: #include <machine/cdk.h>
   60: #include <machine/comstats.h>
   61: 
   62: #undef STLDEBUG
   63: 
   64: /*****************************************************************************/
   65: 
   66: /*
   67:  *	Define the version level of the kernel - so we can compile in the
   68:  *	appropriate bits of code. By default this will compile for a 2.1
   69:  *	level kernel.
   70:  */
   71: #define	VFREEBSD	220
   72: 
   73: #if VFREEBSD >= 220
   74: #define	STATIC		static
   75: #else
   76: #define	STATIC
   77: #endif
   78: 
   79: /*****************************************************************************/
   80: 
   81: /*
   82:  *	Define different board types. Not all of the following board types
   83:  *	are supported by this driver. But I will use the standard "assigned"
   84:  *	board numbers. Currently supported boards are abbreviated as:
   85:  *	ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
   86:  *	STAL = Stallion.
   87:  */
   88: #define	BRD_UNKNOWN	0
   89: #define	BRD_STALLION	1
   90: #define	BRD_BRUMBY4	2
   91: #define	BRD_ONBOARD2	3
   92: #define	BRD_ONBOARD	4
   93: #define	BRD_BRUMBY8	5
   94: #define	BRD_BRUMBY16	6
   95: #define	BRD_ONBOARDE	7
   96: #define	BRD_ONBOARD32	9
   97: #define	BRD_ONBOARD2_32	10
   98: #define	BRD_ONBOARDRS	11
   99: #define	BRD_EASYIO	20
  100: #define	BRD_ECH		21
  101: #define	BRD_ECHMC	22
  102: #define	BRD_ECP		23
  103: #define BRD_ECPE	24
  104: #define	BRD_ECPMC	25
  105: #define	BRD_ECHPCI	26
  106: #define	BRD_ECH64PCI	27
  107: #define	BRD_EASYIOPCI	28
  108: 
  109: #define	BRD_BRUMBY	BRD_BRUMBY4
  110: 
  111: /*****************************************************************************/
  112: 
  113: /*
  114:  *	Define important driver limitations.
  115:  */
  116: #define	STL_MAXBRDS		8
  117: #define	STL_MAXPANELS		4
  118: #define	STL_PORTSPERPANEL	16
  119: #define	STL_PORTSPERBRD		64
  120: 
  121: #define	STL_MAXCHANS		STL_PORTSPERBRD
  122: 
  123: 
  124: /*
  125:  *	Define the important minor number break down bits. These have been
  126:  *	chosen to be "compatible" with the standard sio driver minor numbers.
  127:  *	Extra high bits are used to distinguish between boards and also for
  128:  *	really high port numbers (> 32).
  129:  */
  130: #define	STL_CALLOUTDEV	0x80
  131: #define	STL_CTRLLOCK	0x40
  132: #define	STL_CTRLINIT	0x20
  133: #define	STL_CTRLDEV	(STL_CTRLLOCK | STL_CTRLINIT)
  134: 
  135: #define	STL_MEMDEV	0x07000000
  136: 
  137: #define	STL_DEFSPEED	TTYDEF_SPEED
  138: #define	STL_DEFCFLAG	(CS8 | CREAD | HUPCL)
  139: 
  140: /*****************************************************************************/
  141: 
  142: /*
  143:  *	Define our local driver identity first. Set up stuff to deal with
  144:  *	all the local structures required by a serial tty driver.
  145:  */
  146: static char 		stli_drvname[] = "stli";
  147: static char const	stli_drvtitle[] = "Stallion Multiport Serial Driver";
  148: static char const	stli_drvversion[] = "2.0.0";
  149: 
  150: static int	stli_nrbrds = 0;
  151: static int	stli_doingtimeout = 0;
  152: 
  153: /*
  154:  *	Define some macros to use to class define boards.
  155:  */
  156: #define	BRD_ISA		0x1
  157: #define	BRD_EISA	0x2
  158: #define	BRD_MCA		0x4
  159: #define	BRD_PCI		0x8
  160: 
  161: static unsigned char	stli_stliprobed[STL_MAXBRDS];
  162: 
  163: /*****************************************************************************/
  164: 
  165: /*
  166:  *	Define a set of structures to hold all the board/panel/port info
  167:  *	for our ports. These will be dynamically allocated as required at
  168:  *	driver initialization time.
  169:  */
  170: 
  171: /*
  172:  *	Port and board structures to hold status info about each object.
  173:  *	The board structure contains pointers to structures for each port
  174:  *	connected to it. Panels are not distinguished here, since
  175:  *	communication with the slave board will always be on a per port
  176:  *	basis.
  177:  */
  178: typedef struct {
  179: 	struct tty	tty;
  180: 	int		portnr;
  181: 	int		panelnr;
  182: 	int		brdnr;
  183: 	int		ioaddr;
  184: 	int		callout;
  185: 	int		devnr;
  186: 	int		dtrwait;
  187: 	int		dotimestamp;
  188: 	int		waitopens;
  189: 	int		hotchar;
  190: 	int		rc;
  191: 	int		argsize;
  192: 	void		*argp;
  193: 	unsigned int	state;
  194: 	unsigned int	sigs;
  195: 	struct termios	initintios;
  196: 	struct termios	initouttios;
  197: 	struct termios	lockintios;
  198: 	struct termios	lockouttios;
  199: 	struct timeval	timestamp;
  200: 	asysigs_t	asig;
  201: 	unsigned long	addr;
  202: 	unsigned long	rxlost;
  203: 	unsigned long	rxoffset;
  204: 	unsigned long	txoffset;
  205: 	unsigned long	pflag;
  206: 	unsigned int	rxsize;
  207: 	unsigned int	txsize;
  208: 	unsigned char	reqidx;
  209: 	unsigned char	reqbit;
  210: 	unsigned char	portidx;
  211: 	unsigned char	portbit;
  212: } stliport_t;
  213: 
  214: /*
  215:  *	Use a structure of function pointers to do board level operations.
  216:  *	These include, enable/disable, paging shared memory, interrupting, etc.
  217:  */
  218: typedef struct stlibrd {
  219: 	int		brdnr;
  220: 	int		brdtype;
  221: 	int		unitid;
  222: 	int		state;
  223: 	int		nrpanels;
  224: 	int		nrports;
  225: 	int		nrdevs;
  226: 	unsigned int	iobase;
  227: 	unsigned long	paddr;
  228: 	void		*vaddr;
  229: 	int		memsize;
  230: 	int		pagesize;
  231: 	int		hostoffset;
  232: 	int		slaveoffset;
  233: 	int		bitsize;
  234: 	int		confbits;
  235: 	void		(*init)(struct stlibrd *brdp);
  236: 	void		(*enable)(struct stlibrd *brdp);
  237: 	void		(*reenable)(struct stlibrd *brdp);
  238: 	void		(*disable)(struct stlibrd *brdp);
  239: 	void		(*intr)(struct stlibrd *brdp);
  240: 	void		(*reset)(struct stlibrd *brdp);
  241: 	char		*(*getmemptr)(struct stlibrd *brdp,
  242: 				unsigned long offset, int line);
  243: 	int		panels[STL_MAXPANELS];
  244: 	int		panelids[STL_MAXPANELS];
  245: 	stliport_t	*ports[STL_PORTSPERBRD];
  246: } stlibrd_t;
  247: 
  248: static stlibrd_t	*stli_brds[STL_MAXBRDS];
  249: 
  250: static int		stli_shared = 0;
  251: 
  252: /*
  253:  *	Keep a local char buffer for processing chars into the LD. We
  254:  *	do this to avoid copying from the boards shared memory one char
  255:  *	at a time.
  256:  */
  257: static int		stli_rxtmplen;
  258: static stliport_t	*stli_rxtmpport;
  259: static char		stli_rxtmpbuf[TTYHOG];
  260: 
  261: /*
  262:  *	Define global stats structures. Not used often, and can be re-used
  263:  *	for each stats call.
  264:  */
  265: static comstats_t	stli_comstats;
  266: static combrd_t		stli_brdstats;
  267: static asystats_t	stli_cdkstats;
  268: 
  269: /*
  270:  *	Per board state flags. Used with the state field of the board struct.
  271:  *	Not really much here... All we need to do is keep track of whether
  272:  *	the board has been detected, and whether it is actully running a slave
  273:  *	or not.
  274:  */
  275: #define	BST_FOUND	0x1
  276: #define	BST_STARTED	0x2
  277: 
  278: /*
  279:  *	Define the set of port state flags. These are marked for internal
  280:  *	state purposes only, usually to do with the state of communications
  281:  *	with the slave. They need to be updated atomically.
  282:  */
  283: #define	ST_INITIALIZING	0x1
  284: #define	ST_INITIALIZED	0x2
  285: #define	ST_OPENING	0x4
  286: #define	ST_CLOSING	0x8
  287: #define	ST_CMDING	0x10
  288: #define	ST_RXING	0x20
  289: #define	ST_TXBUSY	0x40
  290: #define	ST_DOFLUSHRX	0x80
  291: #define	ST_DOFLUSHTX	0x100
  292: #define	ST_DOSIGS	0x200
  293: #define	ST_GETSIGS	0x400
  294: #define	ST_DTRWAIT	0x800
  295: 
  296: /*
  297:  *	Define an array of board names as printable strings. Handy for
  298:  *	referencing boards when printing trace and stuff.
  299:  */
  300: static char	*stli_brdnames[] = {
  301: 	"Unknown",
  302: 	"Stallion",
  303: 	"Brumby",
  304: 	"ONboard-MC",
  305: 	"ONboard",
  306: 	"Brumby",
  307: 	"Brumby",
  308: 	"ONboard-EI",
  309: 	(char *) NULL,
  310: 	"ONboard",
  311: 	"ONboard-MC",
  312: 	"ONboard-MC",
  313: 	(char *) NULL,
  314: 	(char *) NULL,
  315: 	(char *) NULL,
  316: 	(char *) NULL,
  317: 	(char *) NULL,
  318: 	(char *) NULL,
  319: 	(char *) NULL,
  320: 	(char *) NULL,
  321: 	"EasyIO",
  322: 	"EC8/32-AT",
  323: 	"EC8/32-MC",
  324: 	"EC8/64-AT",
  325: 	"EC8/64-EI",
  326: 	"EC8/64-MC",
  327: 	"EC8/32-PCI",
  328: };
  329: 
  330: /*****************************************************************************/
  331: 
  332: /*
  333:  *	Hardware configuration info for ECP boards. These defines apply
  334:  *	to the directly accessable io ports of the ECP. There is a set of
  335:  *	defines for each ECP board type, ISA, EISA and MCA.
  336:  */
  337: #define	ECP_IOSIZE	4
  338: #define	ECP_MEMSIZE	(128 * 1024)
  339: #define	ECP_ATPAGESIZE	(4 * 1024)
  340: #define	ECP_EIPAGESIZE	(64 * 1024)
  341: #define	ECP_MCPAGESIZE	(4 * 1024)
  342: 
  343: #define	STL_EISAID	0x8c4e
  344: 
  345: /*
  346:  *	Important defines for the ISA class of ECP board.
  347:  */
  348: #define	ECP_ATIREG	0
  349: #define	ECP_ATCONFR	1
  350: #define	ECP_ATMEMAR	2
  351: #define	ECP_ATMEMPR	3
  352: #define	ECP_ATSTOP	0x1
  353: #define	ECP_ATINTENAB	0x10
  354: #define	ECP_ATENABLE	0x20
  355: #define	ECP_ATDISABLE	0x00
  356: #define	ECP_ATADDRMASK	0x3f000
  357: #define	ECP_ATADDRSHFT	12
  358: 
  359: /*
  360:  *	Important defines for the EISA class of ECP board.
  361:  */
  362: #define	ECP_EIIREG	0
  363: #define	ECP_EIMEMARL	1
  364: #define	ECP_EICONFR	2
  365: #define	ECP_EIMEMARH	3
  366: #define	ECP_EIENABLE	0x1
  367: #define	ECP_EIDISABLE	0x0
  368: #define	ECP_EISTOP	0x4
  369: #define	ECP_EIEDGE	0x00
  370: #define	ECP_EILEVEL	0x80
  371: #define	ECP_EIADDRMASKL	0x00ff0000
  372: #define	ECP_EIADDRSHFTL	16
  373: #define	ECP_EIADDRMASKH	0xff000000
  374: #define	ECP_EIADDRSHFTH	24
  375: #define	ECP_EIBRDENAB	0xc84
  376: 
  377: #define	ECP_EISAID	0x4
  378: 
  379: /*
  380:  *	Important defines for the Micro-channel class of ECP board.
  381:  *	(It has a lot in common with the ISA boards.)
  382:  */
  383: #define	ECP_MCIREG	0
  384: #define	ECP_MCCONFR	1
  385: #define	ECP_MCSTOP	0x20
  386: #define	ECP_MCENABLE	0x80
  387: #define	ECP_MCDISABLE	0x00
  388: 
  389: /*
  390:  *	Hardware configuration info for ONboard and Brumby boards. These
  391:  *	defines apply to the directly accessable io ports of these boards.
  392:  */
  393: #define	ONB_IOSIZE	16
  394: #define	ONB_MEMSIZE	(64 * 1024)
  395: #define	ONB_ATPAGESIZE	(64 * 1024)
  396: #define	ONB_MCPAGESIZE	(64 * 1024)
  397: #define	ONB_EIMEMSIZE	(128 * 1024)
  398: #define	ONB_EIPAGESIZE	(64 * 1024)
  399: 
  400: /*
  401:  *	Important defines for the ISA class of ONboard board.
  402:  */
  403: #define	ONB_ATIREG	0
  404: #define	ONB_ATMEMAR	1
  405: #define	ONB_ATCONFR	2
  406: #define	ONB_ATSTOP	0x4
  407: #define	ONB_ATENABLE	0x01
  408: #define	ONB_ATDISABLE	0x00
  409: #define	ONB_ATADDRMASK	0xff0000
  410: #define	ONB_ATADDRSHFT	16
  411: 
  412: #define	ONB_HIMEMENAB	0x02
  413: 
  414: /*
  415:  *	Important defines for the EISA class of ONboard board.
  416:  */
  417: #define	ONB_EIIREG	0
  418: #define	ONB_EIMEMARL	1
  419: #define	ONB_EICONFR	2
  420: #define	ONB_EIMEMARH	3
  421: #define	ONB_EIENABLE	0x1
  422: #define	ONB_EIDISABLE	0x0
  423: #define	ONB_EISTOP	0x4
  424: #define	ONB_EIEDGE	0x00
  425: #define	ONB_EILEVEL	0x80
  426: #define	ONB_EIADDRMASKL	0x00ff0000
  427: #define	ONB_EIADDRSHFTL	16
  428: #define	ONB_EIADDRMASKH	0xff000000
  429: #define	ONB_EIADDRSHFTH	24
  430: #define	ONB_EIBRDENAB	0xc84
  431: 
  432: #define	ONB_EISAID	0x1
  433: 
  434: /*
  435:  *	Important defines for the Brumby boards. They are pretty simple,
  436:  *	there is not much that is programmably configurable.
  437:  */
  438: #define	BBY_IOSIZE	16
  439: #define	BBY_MEMSIZE	(64 * 1024)
  440: #define	BBY_PAGESIZE	(16 * 1024)
  441: 
  442: #define	BBY_ATIREG	0
  443: #define	BBY_ATCONFR	1
  444: #define	BBY_ATSTOP	0x4
  445: 
  446: /*
  447:  *	Important defines for the Stallion boards. They are pretty simple,
  448:  *	there is not much that is programmably configurable.
  449:  */
  450: #define	STAL_IOSIZE	16
  451: #define	STAL_MEMSIZE	(64 * 1024)
  452: #define	STAL_PAGESIZE	(64 * 1024)
  453: 
  454: /*
  455:  *	Define the set of status register values for EasyConnection panels.
  456:  *	The signature will return with the status value for each panel. From
  457:  *	this we can determine what is attached to the board - before we have
  458:  *	actually down loaded any code to it.
  459:  */
  460: #define	ECH_PNLSTATUS	2
  461: #define	ECH_PNL16PORT	0x20
  462: #define	ECH_PNLIDMASK	0x07
  463: #define	ECH_PNLXPID	0x40
  464: #define	ECH_PNLINTRPEND	0x80
  465: 
  466: /*
  467:  *	Define some macros to do things to the board. Even those these boards
  468:  *	are somewhat related there is often significantly different ways of
  469:  *	doing some operation on it (like enable, paging, reset, etc). So each
  470:  *	board class has a set of functions which do the commonly required
  471:  *	operations. The macros below basically just call these functions,
  472:  *	generally checking for a NULL function - which means that the board
  473:  *	needs nothing done to it to achieve this operation!
  474:  */
  475: #define	EBRDINIT(brdp)					\
  476: 	if (brdp->init != NULL)				\
  477: 		(* brdp->init)(brdp)
  478: 
  479: #define	EBRDENABLE(brdp)				\
  480: 	if (brdp->enable != NULL)			\
  481: 		(* brdp->enable)(brdp);
  482: 
  483: #define	EBRDDISABLE(brdp)				\
  484: 	if (brdp->disable != NULL)			\
  485: 		(* brdp->disable)(brdp);
  486: 
  487: #define	EBRDINTR(brdp)					\
  488: 	if (brdp->intr != NULL)				\
  489: 		(* brdp->intr)(brdp);
  490: 
  491: #define	EBRDRESET(brdp)					\
  492: 	if (brdp->reset != NULL)			\
  493: 		(* brdp->reset)(brdp);
  494: 
  495: #define	EBRDGETMEMPTR(brdp,offset)			\
  496: 	(* brdp->getmemptr)(brdp, offset, __LINE__)
  497: 
  498: /*
  499:  *	Define the maximal baud rate.
  500:  */
  501: #define	STL_MAXBAUD	230400
  502: 
  503: /*****************************************************************************/
  504: 
  505: /*
  506:  *	Define macros to extract a brd and port number from a minor number.
  507:  *	This uses the extended minor number range in the upper 2 bytes of
  508:  *	the device number. This gives us plenty of minor numbers to play
  509:  *	with...
  510:  */
  511: #define	MKDEV2BRD(m)	((minor(m) & 0x00700000) >> 20)
  512: #define	MKDEV2PORT(m)	((minor(m) & 0x1f) | ((minor(m) & 0x00010000) >> 11))
  513: 
  514: /*
  515:  *	Define some handy local macros...
  516:  */
  517: #ifndef	MIN
  518: #define	MIN(a,b)	(((a) <= (b)) ? (a) : (b))
  519: #endif
  520: 
  521: /*****************************************************************************/
  522: 
  523: /*
  524:  *	Declare all those functions in this driver!  First up is the set of
  525:  *	externally visible functions.
  526:  */
  527: static int	stliprobe(struct isa_device *idp);
  528: static int	stliattach(struct isa_device *idp);
  529: 
  530: STATIC	d_open_t	stliopen;
  531: STATIC	d_close_t	stliclose;
  532: STATIC	d_read_t	stliread;
  533: STATIC	d_write_t	stliwrite;
  534: STATIC	d_ioctl_t	stliioctl;
  535: 
  536: /*
  537:  *	Internal function prototypes.
  538:  */
  539: static stliport_t *stli_dev2port(dev_t dev);
  540: static int	stli_isaprobe(struct isa_device *idp);
  541: static int	stli_eisaprobe(struct isa_device *idp);
  542: static int	stli_mcaprobe(struct isa_device *idp);
  543: static int	stli_brdinit(stlibrd_t *brdp);
  544: static int	stli_brdattach(stlibrd_t *brdp);
  545: static int	stli_initecp(stlibrd_t *brdp);
  546: static int	stli_initonb(stlibrd_t *brdp);
  547: static int	stli_initports(stlibrd_t *brdp);
  548: static int	stli_startbrd(stlibrd_t *brdp);
  549: static void	stli_poll(void *arg);
  550: static __inline void	stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp);
  551: static __inline int	stli_hostcmd(stlibrd_t *brdp, stliport_t *portp);
  552: static __inline void	stli_dodelaycmd(stliport_t *portp,
  553: 					volatile cdkctrl_t *cp);
  554: static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
  555: static long	stli_mktiocm(unsigned long sigvalue);
  556: static void	stli_rxprocess(stlibrd_t *brdp, stliport_t *portp);
  557: static void	stli_flush(stliport_t *portp, int flag);
  558: static void	stli_start(struct tty *tp);
  559: static void	stli_stop(struct tty *tp, int rw);
  560: static int	stli_param(struct tty *tp, struct termios *tiosp);
  561: static void	stli_ttyoptim(stliport_t *portp, struct termios *tiosp);
  562: static void	stli_dtrwakeup(void *arg);
  563: static int	stli_initopen(stliport_t *portp);
  564: static int	stli_shutdownclose(stliport_t *portp);
  565: static int	stli_rawopen(stlibrd_t *brdp, stliport_t *portp,
  566: 			unsigned long arg, int wait);
  567: static int	stli_rawclose(stlibrd_t *brdp, stliport_t *portp,
  568: 			unsigned long arg, int wait);
  569: static int	stli_cmdwait(stlibrd_t *brdp, stliport_t *portp,
  570: 			unsigned long cmd, void *arg, int size, int copyback);
  571: static void	stli_sendcmd(stlibrd_t *brdp, stliport_t *portp,
  572: 			unsigned long cmd, void *arg, int size, int copyback);
  573: static void	stli_mkasyport(stliport_t *portp, asyport_t *pp,
  574: 			struct termios *tiosp);
  575: static int	stli_memrw(dev_t dev, struct uio *uiop, int flag);
  576: static int	stli_memioctl(dev_t dev, unsigned long cmd, caddr_t data,
  577: 			int flag, struct thread *td);
  578: static int	stli_getbrdstats(caddr_t data);
  579: static int	stli_getportstats(stliport_t *portp, caddr_t data);
  580: static int	stli_clrportstats(stliport_t *portp, caddr_t data);
  581: static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
  582: 
  583: static void	stli_ecpinit(stlibrd_t *brdp);
  584: static void	stli_ecpenable(stlibrd_t *brdp);
  585: static void	stli_ecpdisable(stlibrd_t *brdp);
  586: static void	stli_ecpreset(stlibrd_t *brdp);
  587: static char	*stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset,
  588: 			int line);
  589: static void	stli_ecpintr(stlibrd_t *brdp);
  590: static void	stli_ecpeiinit(stlibrd_t *brdp);
  591: static void	stli_ecpeienable(stlibrd_t *brdp);
  592: static void	stli_ecpeidisable(stlibrd_t *brdp);
  593: static void	stli_ecpeireset(stlibrd_t *brdp);
  594: static char	*stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset,
  595: 			int line);
  596: static void	stli_ecpmcenable(stlibrd_t *brdp);
  597: static void	stli_ecpmcdisable(stlibrd_t *brdp);
  598: static void	stli_ecpmcreset(stlibrd_t *brdp);
  599: static char	*stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset,
  600: 			int line);
  601: 
  602: static void	stli_onbinit(stlibrd_t *brdp);
  603: static void	stli_onbenable(stlibrd_t *brdp);
  604: static void	stli_onbdisable(stlibrd_t *brdp);
  605: static void	stli_onbreset(stlibrd_t *brdp);
  606: static char	*stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset,
  607: 			int line);
  608: static void	stli_onbeinit(stlibrd_t *brdp);
  609: static void	stli_onbeenable(stlibrd_t *brdp);
  610: static void	stli_onbedisable(stlibrd_t *brdp);
  611: static void	stli_onbereset(stlibrd_t *brdp);
  612: static char	*stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset,
  613: 			int line);
  614: static void	stli_bbyinit(stlibrd_t *brdp);
  615: static void	stli_bbyreset(stlibrd_t *brdp);
  616: static char	*stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset,
  617: 			int line);
  618: static void	stli_stalinit(stlibrd_t *brdp);
  619: static void	stli_stalreset(stlibrd_t *brdp);
  620: static char	*stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset,
  621: 			int line);
  622: 
  623: /*****************************************************************************/
  624: 
  625: /*
  626:  *	Declare the driver isa structure.
  627:  */
  628: struct isa_driver	stlidriver = {
  629: 	stliprobe, stliattach, stli_drvname
  630: };
  631: 
  632: /*****************************************************************************/
  633: 
  634: #if VFREEBSD >= 220
  635: 
  636: /*
  637:  *	FreeBSD-2.2+ kernel linkage.
  638:  */
  639: 
  640: #define	CDEV_MAJOR	75
  641: static struct cdevsw stli_cdevsw = {
  642: 	/* name */	stli_drvname,
  643: 	/* maj */	CDEV_MAJOR,
  644: 	/* flags */	D_TTY | D_KQFILTER,
  645: 	/* port */	NULL,
  646: 	/* clone */	NULL,
  647: 
  648: 	/* open */	stliopen,
  649: 	/* close */	stliclose,
  650: 	/* read */	stliread,
  651: 	/* write */	stliwrite,
  652: 	/* ioctl */	stliioctl,
  653: 	/* poll */	ttypoll,
  654: 	/* mmap */	nommap,
  655: 	/* strategy */	nostrategy,
  656: 	/* dump */	nodump,
  657: 	/* psize */	nopsize,
  658: 	/* kqfilter */	ttykqfilter
  659: };
  660: 
  661: #endif
  662: 
  663: /*****************************************************************************/
  664: 
  665: static stlibrd_t *stli_brdalloc(void)
  666: {
  667: 	stlibrd_t	*brdp;
  668: 
  669: 	brdp = (stlibrd_t *) malloc(sizeof(stlibrd_t), M_TTYS, M_NOWAIT);
  670: 	if (brdp == (stlibrd_t *) NULL) {
  671: 		printf("STALLION: failed to allocate memory (size=%d)\n",
  672: 			sizeof(stlibrd_t));
  673: 		return((stlibrd_t *) NULL);
  674: 	}
  675: 	bzero(brdp, sizeof(stlibrd_t));
  676: 	return(brdp);
  677: }
  678: 
  679: /*****************************************************************************/
  680: 
  681: /*
  682:  *	Find an available internal board number (unit number). The problem
  683:  *	is that the same unit numbers can be assigned to different class
  684:  *	boards - but we only want to maintain one setup board structures.
  685:  */
  686: 
  687: static int stli_findfreeunit(void)
  688: {
  689: 	int	i;
  690: 
  691: 	for (i = 0; (i < STL_MAXBRDS); i++)
  692: 		if (stli_brds[i] == (stlibrd_t *) NULL)
  693: 			break;
  694: 	return((i >= STL_MAXBRDS) ? -1 : i);
  695: }
  696: 
  697: /*****************************************************************************/
  698: 
  699: /*
  700:  *	Try and determine the ISA board type. Hopefully the board
  701:  *	configuration entry will help us out, using the flags field.
  702:  *	If not, we may ne be able to determine the board type...
  703:  */
  704: 
  705: static int stli_isaprobe(struct isa_device *idp)
  706: {
  707: 	int	btype;
  708: 
  709: #if STLDEBUG
  710: 	printf("stli_isaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
  711: 		(int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
  712: #endif
  713: 
  714: 	switch (idp->id_flags) {
  715: 	case BRD_STALLION:
  716: 	case BRD_BRUMBY4:
  717: 	case BRD_BRUMBY8:
  718: 	case BRD_BRUMBY16:
  719: 	case BRD_ONBOARD:
  720: 	case BRD_ONBOARD32:
  721: 	case BRD_ECP:
  722: 		btype = idp->id_flags;
  723: 		break;
  724: 	default:
  725: 		btype = 0;
  726: 		break;
  727: 	}
  728: 	return(btype);
  729: }
  730: 
  731: /*****************************************************************************/
  732: 
  733: /*
  734:  *	Probe for an EISA board type. We should be able to read the EISA ID,
  735:  *	that will tell us if a board is present or not...
  736:  */
  737: 
  738: static int stli_eisaprobe(struct isa_device *idp)
  739: {
  740: 	int	btype, eid;
  741: 
  742: #if STLDEBUG
  743: 	printf("stli_eisaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
  744: 		(int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
  745: #endif
  746: 
  747: /*
  748:  *	Firstly check if this is an EISA system. Do this by probing for
  749:  *	the system board EISA ID. If this is not an EISA system then
  750:  *	don't bother going any further!
  751:  */
  752: 	outb(0xc80, 0xff);
  753: 	if (inb(0xc80) == 0xff)
  754: 		return(0);
  755: 
  756: /*
  757:  *	Try and read the EISA ID from the board at specified address.
  758:  *	If one is present it will tell us the board type as well.
  759:  */
  760: 	outb((idp->id_iobase + 0xc80), 0xff);
  761: 	eid = inb(idp->id_iobase + 0xc80);
  762: 	eid |= inb(idp->id_iobase + 0xc81) << 8;
  763: 	if (eid != STL_EISAID)
  764: 		return(0);
  765: 
  766: 	btype = 0;
  767: 	eid = inb(idp->id_iobase + 0xc82);
  768: 	if (eid == ECP_EISAID)
  769: 		btype = BRD_ECPE;
  770: 	else if (eid == ONB_EISAID)
  771: 		btype = BRD_ONBOARDE;
  772: 
  773: 	outb((idp->id_iobase + 0xc84), 0x1);
  774: 	return(btype);
  775: }
  776: 
  777: /*****************************************************************************/
  778: 
  779: /*
  780:  *	Probe for an MCA board type. Not really sure how to do this yet,
  781:  *	so for now just use the supplied flag specifier as board type...
  782:  */
  783: 
  784: static int stli_mcaprobe(struct isa_device *idp)
  785: {
  786: 	int	btype;
  787: 
  788: #if STLDEBUG
  789: 	printf("stli_mcaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
  790: 		(int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
  791: #endif
  792: 
  793: 	switch (idp->id_flags) {
  794: 	case BRD_ONBOARD2:
  795: 	case BRD_ONBOARD2_32:
  796: 	case BRD_ONBOARDRS:
  797: 	case BRD_ECHMC:
  798: 	case BRD_ECPMC:
  799: 		btype = idp->id_flags;
  800: 		break;
  801: 	default:
  802: 		btype = 0;
  803: 		break;
  804: 	}
  805: 	return(0);
  806: }
  807: 
  808: /*****************************************************************************/
  809: 
  810: /*
  811:  *	Probe for a board. This is involved, since we need to enable the
  812:  *	shared memory region to see if the board is really there or not...
  813:  */
  814: 
  815: static int stliprobe(struct isa_device *idp)
  816: {
  817: 	stlibrd_t	*brdp;
  818: 	int		btype, bclass;
  819: 	static int once;
  820: 
  821: 	if (!once++)
  822: 		cdevsw_add(&stli_cdevsw);
  823: 
  824: #if STLDEBUG
  825: 	printf("stliprobe(idp=%x): unit=%d iobase=%x flags=%x\n", (int) idp,
  826: 		idp->id_unit, idp->id_iobase, idp->id_flags);
  827: #endif
  828: 
  829: 	if (idp->id_unit > STL_MAXBRDS)
  830: 		return(0);
  831: 
  832: /*
  833:  *	First up determine what bus type of board we might be dealing
  834:  *	with. It is easy to separate out the ISA from the EISA and MCA
  835:  *	boards, based on their IO addresses. We may not be able to tell
  836:  *	the EISA and MCA apart on IO address alone...
  837:  */
  838: 	bclass = 0;
  839: 	if ((idp->id_iobase > 0) && (idp->id_iobase < 0x400)) {
  840: 		bclass |= BRD_ISA;
  841: 	} else {
  842: 		/* ONboard2 range */
  843: 		if ((idp->id_iobase >= 0x700) && (idp->id_iobase < 0x900))
  844: 			bclass |= BRD_MCA;
  845: 		/* EC-MCA ranges */
  846: 		if ((idp->id_iobase >= 0x7000) && (idp->id_iobase < 0x7400))
  847: 			bclass |= BRD_MCA;
  848: 		if ((idp->id_iobase >= 0x8000) && (idp->id_iobase < 0xc000))
  849: 			bclass |= BRD_MCA;
  850: 		/* EISA board range */
  851: 		if ((idp->id_iobase & ~0xf000) == 0)
  852: 			bclass |= BRD_EISA;
  853: 	}
  854: 
  855: 	if ((bclass == 0) || (idp->id_iobase == 0))
  856: 		return(0);
  857: 
  858: /*
  859:  *	Based on the board bus type, try and figure out what it might be...
  860:  */
  861: 	btype = 0;
  862: 	if (bclass & BRD_ISA)
  863: 		btype = stli_isaprobe(idp);
  864: 	if ((btype == 0) && (bclass & BRD_EISA))
  865: 		btype = stli_eisaprobe(idp);
  866: 	if ((btype == 0) && (bclass & BRD_MCA))
  867: 		btype = stli_mcaprobe(idp);
  868: 	if (btype == 0)
  869: 		return(0);
  870: 
  871: /*
  872:  *	Go ahead and try probing for the shared memory region now.
  873:  *	This way we will really know if the board is here...
  874:  */
  875: 	if ((brdp = stli_brdalloc()) == (stlibrd_t *) NULL)
  876: 		return(0);
  877: 
  878: 	brdp->brdnr = stli_findfreeunit();
  879: 	brdp->brdtype = btype;
  880: 	brdp->unitid = idp->id_unit;
  881: 	brdp->iobase = idp->id_iobase;
  882: 	brdp->vaddr = idp->id_maddr;
  883: 	brdp->paddr = vtophys(idp->id_maddr);
  884: 
  885: #if STLDEBUG
  886: 	printf("%s(%d): btype=%x unit=%d brd=%d io=%x mem=%lx(%p)\n",
  887: 		__file__, __LINE__, btype, brdp->unitid, brdp->brdnr,
  888: 		brdp->iobase, brdp->paddr, (void *) brdp->vaddr);
  889: #endif
  890: 
  891: 	stli_stliprobed[idp->id_unit] = brdp->brdnr;
  892: 	stli_brdinit(brdp);
  893: 	if ((brdp->state & BST_FOUND) == 0) {
  894: 		stli_brds[brdp->brdnr] = (stlibrd_t *) NULL;
  895: 		return(0);
  896: 	}
  897: 	stli_nrbrds++;
  898: 	return(1);
  899: }
  900: 
  901: /*****************************************************************************/
  902: 
  903: /*
  904:  *	Allocate resources for and initialize a board.
  905:  */
  906: 
  907: static int stliattach(struct isa_device *idp)
  908: {
  909: 	stlibrd_t	*brdp;
  910: 	int		brdnr;
  911: 
  912: #if STLDEBUG
  913: 	printf("stliattach(idp=%p): unit=%d iobase=%x\n", (void *) idp,
  914: 		idp->id_unit, idp->id_iobase);
  915: #endif
  916: 
  917: 	brdnr = stli_stliprobed[idp->id_unit];
  918: 	brdp = stli_brds[brdnr];
  919: 	if (brdp == (stlibrd_t *) NULL)
  920: 		return(0);
  921: 	if (brdp->state & BST_FOUND)
  922: 		stli_brdattach(brdp);
  923: 	return(1);
  924: }
  925: 
  926: 
  927: /*****************************************************************************/
  928: 
  929: STATIC int stliopen(dev_t dev, int flag, int mode, struct thread *td)
  930: {
  931: 	struct tty	*tp;
  932: 	stliport_t	*portp;
  933: 	int		error, callout, x;
  934: 
  935: #if STLDEBUG
  936: 	printf("stliopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag,
  937: 		mode, (int) p);
  938: #endif
  939: 
  940: /*
  941:  *	Firstly check if the supplied device number is a valid device.
  942:  */
  943: 	if (minor(dev) & STL_MEMDEV)
  944: 		return(0);
  945: 
  946: 	portp = stli_dev2port(dev);
  947: 	if (portp == (stliport_t *) NULL)
  948: 		return(ENXIO);
  949: 	if (minor(dev) & STL_CTRLDEV)
  950: 		return(0);
  951: 	tp = &portp->tty;
  952: 	dev->si_tty = tp;
  953: 	callout = minor(dev) & STL_CALLOUTDEV;
  954: 	error = 0;
  955: 
  956: 	x = spltty();
  957: 
  958: stliopen_restart:
  959: /*
  960:  *	Wait here for the DTR drop timeout period to expire.
  961:  */
  962: 	while (portp->state & ST_DTRWAIT) {
  963: 		error = tsleep(&portp->dtrwait, PCATCH, "stlidtr", 0);
  964: 		if (error)
  965: 			goto stliopen_end;
  966: 	}
  967: 
  968: /*
  969:  *	If the port is in its raw hardware initialization phase, then
  970:  *	hold up here 'till it is done.
  971:  */
  972: 	while (portp->state & (ST_INITIALIZING | ST_CLOSING)) {
  973: 		error = tsleep(&portp->state, PCATCH, "stliraw", 0);
  974: 		if (error)
  975: 			goto stliopen_end;
  976: 	}
  977: 
  978: /*
  979:  *	We have a valid device, so now we check if it is already open.
  980:  *	If not then initialize the port hardware and set up the tty
  981:  *	struct as required.
  982:  */
  983: 	if ((tp->t_state & TS_ISOPEN) == 0) {
  984: 		tp->t_oproc = stli_start;
  985: 		tp->t_param = stli_param;
  986: 		tp->t_stop = stli_stop;
  987: 		tp->t_dev = dev;
  988: 		tp->t_termios = callout ? portp->initouttios :
  989: 			portp->initintios;
  990: 		stli_initopen(portp);
  991: 		wakeup(&portp->state);
  992: 		ttsetwater(tp);
  993: 		if ((portp->sigs & TIOCM_CD) || callout)
  994: 			(*linesw[tp->t_line].l_modem)(tp, 1);
  995: 	} else {
  996: 		if (callout) {
  997: 			if (portp->callout == 0) {
  998: 				error = EBUSY;
  999: 				goto stliopen_end;
 1000: 			}
 1001: 		} else {
 1002: 			if (portp->callout != 0) {
 1003: 				if (flag & O_NONBLOCK) {
 1004: 					error = EBUSY;
 1005: 					goto stliopen_end;
 1006: 				}
 1007: 				error = tsleep(&portp->callout,
 1008: 					    PCATCH, "stlicall", 0);
 1009: 				if (error)
 1010: 					goto stliopen_end;
 1011: 				goto stliopen_restart;
 1012: 			}
 1013: 		}
 1014: 		if ((tp->t_state & TS_XCLUDE) &&
 1015: 		    suser(td)) {
 1016: 			error = EBUSY;
 1017: 			goto stliopen_end;
 1018: 		}
 1019: 	}
 1020: 
 1021: /*
 1022:  *	If this port is not the callout device and we do not have carrier
 1023:  *	then we need to sleep, waiting for it to be asserted.
 1024:  */
 1025: 	if (((tp->t_state & TS_CARR_ON) == 0) && !callout &&
 1026: 			((tp->t_cflag & CLOCAL) == 0) &&
 1027: 			((flag & O_NONBLOCK) == 0)) {
 1028: 		portp->waitopens++;
 1029: 		error = tsleep(TSA_CARR_ON(tp), PCATCH, "stlidcd",0);
 1030: 		portp->waitopens--;
 1031: 		if (error)
 1032: 			goto stliopen_end;
 1033: 		goto stliopen_restart;
 1034: 	}
 1035: 
 1036: /*
 1037:  *	Open the line discipline.
 1038:  */
 1039: 	error = (*linesw[tp->t_line].l_open)(dev, tp);
 1040: 	stli_ttyoptim(portp, &tp->t_termios);
 1041: 	if ((tp->t_state & TS_ISOPEN) && callout)
 1042: 		portp->callout = 1;
 1043: 
 1044: /*
 1045:  *	If for any reason we get to here and the port is not actually
 1046:  *	open then close of the physical hardware - no point leaving it
 1047:  *	active when the open failed...
 1048:  */
 1049: stliopen_end:
 1050: 	splx(x);
 1051: 	if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0))
 1052: 		stli_shutdownclose(portp);
 1053: 
 1054: 	return(error);
 1055: }
 1056: 
 1057: /*****************************************************************************/
 1058: 
 1059: STATIC int stliclose(dev_t dev, int flag, int mode, struct thread *td)
 1060: {
 1061: 	struct tty	*tp;
 1062: 	stliport_t	*portp;
 1063: 	int		x;
 1064: 
 1065: #if STLDEBUG
 1066: 	printf("stliclose(dev=%s,flag=%x,mode=%x,p=%p)\n",
 1067: 		devtoname(dev), flag, mode, (void *) p);
 1068: #endif
 1069: 
 1070: 	if (minor(dev) & STL_MEMDEV)
 1071: 		return(0);
 1072: 	if (minor(dev) & STL_CTRLDEV)
 1073: 		return(0);
 1074: 
 1075: 	portp = stli_dev2port(dev);
 1076: 	if (portp == (stliport_t *) NULL)
 1077: 		return(ENXIO);
 1078: 	tp = &portp->tty;
 1079: 
 1080: 	x = spltty();
 1081: 	(*linesw[tp->t_line].l_close)(tp, flag);
 1082: 	stli_ttyoptim(portp, &tp->t_termios);
 1083: 	stli_shutdownclose(portp);
 1084: 	ttyclose(tp);
 1085: 	splx(x);
 1086: 	return(0);
 1087: }
 1088: 
 1089: 
 1090: STATIC int stliread(dev_t dev, struct uio *uiop, int flag)
 1091: {
 1092: 	stliport_t	*portp;
 1093: 
 1094: #if STLDEBUG
 1095: 	printf("stliread(dev=%s,uiop=%p,flag=%x)\n", devtoname(dev),
 1096: 		(void *) uiop, flag);
 1097: #endif
 1098: 
 1099: 	if (minor(dev) & STL_MEMDEV)
 1100: 		return(stli_memrw(dev, uiop, flag));
 1101: 	if (minor(dev) & STL_CTRLDEV)
 1102: 		return(ENODEV);
 1103: 
 1104: 	portp = stli_dev2port(dev);
 1105: 	if (portp == (stliport_t *) NULL)
 1106: 		return(ENODEV);
 1107: 	return ttyread(dev, uiop, flag);
 1108: }
 1109: 
 1110: /*****************************************************************************/
 1111: 
 1112: #if VFREEBSD >= 220
 1113: 
 1114: STATIC void stli_stop(struct tty *tp, int rw)
 1115: {
 1116: #if STLDEBUG
 1117: 	printf("stli_stop(tp=%x,rw=%x)\n", (int) tp, rw);
 1118: #endif
 1119: 
 1120: 	stli_flush((stliport_t *) tp, rw);
 1121: }
 1122: 
 1123: #else
 1124: 
 1125: STATIC int stlistop(struct tty *tp, int rw)
 1126: {
 1127: #if STLDEBUG
 1128: 	printf("stlistop(tp=%x,rw=%x)\n", (int) tp, rw);
 1129: #endif
 1130: 
 1131: 	stli_flush((stliport_t *) tp, rw);
 1132: 	return(0);
 1133: }
 1134: 
 1135: #endif
 1136: 
 1137: /*****************************************************************************/
 1138: 
 1139: STATIC int stliwrite(dev_t dev, struct uio *uiop, int flag)
 1140: {
 1141: 	stliport_t	*portp;
 1142: 
 1143: #if STLDEBUG
 1144: 	printf("stliwrite(dev=%s,uiop=%p,flag=%x)\n", devtoname(dev),
 1145: 		(void *) uiop, flag);
 1146: #endif
 1147: 
 1148: 	if (minor(dev) & STL_MEMDEV)
 1149: 		return(stli_memrw(dev, uiop, flag));
 1150: 	if (minor(dev) & STL_CTRLDEV)
 1151: 		return(ENODEV);
 1152: 	portp = stli_dev2port(dev);
 1153: 	if (portp == (stliport_t *) NULL)
 1154: 		return(ENODEV);
 1155: 	return ttywrite(dev, uiop, flag);
 1156: }
 1157: 
 1158: /*****************************************************************************/
 1159: 
 1160: STATIC int stliioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
 1161: 		     struct thread *td)
 1162: {
 1163: 	struct termios	*newtios, *localtios;
 1164: 	struct tty	*tp;
 1165: 	stlibrd_t	*brdp;
 1166: 	stliport_t	*portp;
 1167: 	long		arg;
 1168: 	int		error, i, x;
 1169: 
 1170: #if STLDEBUG
 1171: 	printf("stliioctl(dev=%s,cmd=%lx,data=%p,flag=%x,p=%p)\n",
 1172: 		devtoname(dev), cmd, (void *) data, flag, (void *) p);
 1173: #endif
 1174: 
 1175: 	if (minor(dev) & STL_MEMDEV)
 1176: 		return(stli_memioctl(dev, cmd, data, flag, td));
 1177: 
 1178: 	portp = stli_dev2port(dev);
 1179: 	if (portp == (stliport_t *) NULL)
 1180: 		return(ENODEV);
 1181: 	if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1182: 		return(ENODEV);
 1183: 	tp = &portp->tty;
 1184: 	error = 0;
 1185: 	
 1186: /*
 1187:  *	First up handle ioctls on the control devices.
 1188:  */
 1189: 	if (minor(dev) & STL_CTRLDEV) {
 1190: 		if ((minor(dev) & STL_CTRLDEV) == STL_CTRLINIT)
 1191: 			localtios = (minor(dev) & STL_CALLOUTDEV) ?
 1192: 				&portp->initouttios : &portp->initintios;
 1193: 		else if ((minor(dev) & STL_CTRLDEV) == STL_CTRLLOCK)
 1194: 			localtios = (minor(dev) & STL_CALLOUTDEV) ?
 1195: 				&portp->lockouttios : &portp->lockintios;
 1196: 		else
 1197: 			return(ENODEV);
 1198: 
 1199: 		switch (cmd) {
 1200: 		case TIOCSETA:
 1201: 			if ((error = suser(td)) == 0)
 1202: 				*localtios = *((struct termios *) data);
 1203: 			break;
 1204: 		case TIOCGETA:
 1205: 			*((struct termios *) data) = *localtios;
 1206: 			break;
 1207: 		case TIOCGETD:
 1208: 			*((int *) data) = TTYDISC;
 1209: 			break;
 1210: 		case TIOCGWINSZ:
 1211: 			bzero(data, sizeof(struct winsize));
 1212: 			break;
 1213: 		default:
 1214: 			error = ENOTTY;
 1215: 			break;
 1216: 		}
 1217: 		return(error);
 1218: 	}
 1219: 
 1220: /*
 1221:  *	Deal with 4.3 compatibility issues if we have too...
 1222:  */
 1223: #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 1224: 	if (1) {
 1225: 		struct termios	tios;
 1226: 		unsigned long	oldcmd;
 1227: 
 1228: 		tios = tp->t_termios;
 1229: 		oldcmd = cmd;
 1230: 		if ((error = ttsetcompat(tp, &cmd, data, &tios)))
 1231: 			return(error);
 1232: 		if (cmd != oldcmd)
 1233: 			data = (caddr_t) &tios;
 1234: 	}
 1235: #endif
 1236: 
 1237: /*
 1238:  *	Carry out some pre-cmd processing work first...
 1239:  *	Hmmm, not so sure we want this, disable for now...
 1240:  */
 1241: 	if ((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
 1242: 		newtios = (struct termios *) data;
 1243: 		localtios = (minor(dev) & STL_CALLOUTDEV) ? &portp->lockouttios :
 1244: 			 &portp->lockintios;
 1245: 
 1246: 		newtios->c_iflag = (tp->t_iflag & localtios->c_iflag) |
 1247: 			(newtios->c_iflag & ~localtios->c_iflag);
 1248: 		newtios->c_oflag = (tp->t_oflag & localtios->c_oflag) |
 1249: 			(newtios->c_oflag & ~localtios->c_oflag);
 1250: 		newtios->c_cflag = (tp->t_cflag & localtios->c_cflag) |
 1251: 			(newtios->c_cflag & ~localtios->c_cflag);
 1252: 		newtios->c_lflag = (tp->t_lflag & localtios->c_lflag) |
 1253: 			(newtios->c_lflag & ~localtios->c_lflag);
 1254: 		for (i = 0; (i < NCCS); i++) {
 1255: 			if (localtios->c_cc[i] != 0)
 1256: 				newtios->c_cc[i] = tp->t_cc[i];
 1257: 		}
 1258: 		if (localtios->c_ispeed != 0)
 1259: 			newtios->c_ispeed = tp->t_ispeed;
 1260: 		if (localtios->c_ospeed != 0)
 1261: 			newtios->c_ospeed = tp->t_ospeed;
 1262: 	}
 1263: 
 1264: /*
 1265:  *	Call the line discipline and the common command processing to
 1266:  *	process this command (if they can).
 1267:  */
 1268: 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
 1269: 	if (error != ENOIOCTL)
 1270: 		return(error);
 1271: 
 1272: 	x = spltty();
 1273: 	error = ttioctl(tp, cmd, data, flag);
 1274: 	stli_ttyoptim(portp, &tp->t_termios);
 1275: 	if (error != ENOIOCTL) {
 1276: 		splx(x);
 1277: 		return(error);
 1278: 	}
 1279: 
 1280: 	error = 0;
 1281: 
 1282: /*
 1283:  *	Process local commands here. These are all commands that only we
 1284:  *	can take care of (they all rely on actually doing something special
 1285:  *	to the actual hardware).
 1286:  */
 1287: 	switch (cmd) {
 1288: 	case TIOCSBRK:
 1289: 		arg = BREAKON;
 1290: 		error = stli_cmdwait(brdp, portp, A_BREAK, &arg,
 1291: 			sizeof(unsigned long), 0);
 1292: 		break;
 1293: 	case TIOCCBRK:
 1294: 		arg = BREAKOFF;
 1295: 		error = stli_cmdwait(brdp, portp, A_BREAK, &arg,
 1296: 			sizeof(unsigned long), 0);
 1297: 		break;
 1298: 	case TIOCSDTR:
 1299: 		stli_mkasysigs(&portp->asig, 1, -1);
 1300: 		error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1301: 			sizeof(asysigs_t), 0);
 1302: 		break;
 1303: 	case TIOCCDTR:
 1304: 		stli_mkasysigs(&portp->asig, 0, -1);
 1305: 		error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1306: 			sizeof(asysigs_t), 0);
 1307: 		break;
 1308: 	case TIOCMSET:
 1309: 		i = *((int *) data);
 1310: 		stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 1 : 0),
 1311: 			((i & TIOCM_RTS) ? 1 : 0));
 1312: 		error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1313: 			sizeof(asysigs_t), 0);
 1314: 		break;
 1315: 	case TIOCMBIS:
 1316: 		i = *((int *) data);
 1317: 		stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 1 : -1),
 1318: 			((i & TIOCM_RTS) ? 1 : -1));
 1319: 		error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1320: 			sizeof(asysigs_t), 0);
 1321: 		break;
 1322: 	case TIOCMBIC:
 1323: 		i = *((int *) data);
 1324: 		stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 0 : -1),
 1325: 			((i & TIOCM_RTS) ? 0 : -1));
 1326: 		error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1327: 			sizeof(asysigs_t), 0);
 1328: 		break;
 1329: 	case TIOCMGET:
 1330: 		if ((error = stli_cmdwait(brdp, portp, A_GETSIGNALS,
 1331: 				&portp->asig, sizeof(asysigs_t), 1)) < 0)
 1332: 			break;
 1333: 		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
 1334: 		*((int *) data) = (portp->sigs | TIOCM_LE);
 1335: 		break;
 1336: 	case TIOCMSDTRWAIT:
 1337: 		if ((error = suser(td)) == 0)
 1338: 			portp->dtrwait = *((int *) data) * hz / 100;
 1339: 		break;
 1340: 	case TIOCMGDTRWAIT:
 1341: 		*((int *) data) = portp->dtrwait * 100 / hz;
 1342: 		break;
 1343: 	case TIOCTIMESTAMP:
 1344: 		portp->dotimestamp = 1;
 1345: 		*((struct timeval *) data) = portp->timestamp;
 1346: 		break;
 1347: 	case STL_GETPFLAG:
 1348: 		*((unsigned long *) data) = portp->pflag;
 1349: 		break;
 1350: 	case STL_SETPFLAG:
 1351: 		portp->pflag = *((unsigned long *) data);
 1352: 		stli_param(&portp->tty, &portp->tty.t_termios);
 1353: 		break;
 1354: 	default:
 1355: 		error = ENOTTY;
 1356: 		break;
 1357: 	}
 1358: 	splx(x);
 1359: 
 1360: 	return(error);
 1361: }
 1362: 
 1363: /*****************************************************************************/
 1364: 
 1365: /*
 1366:  *	Convert the specified minor device number into a port struct
 1367:  *	pointer. Return NULL if the device number is not a valid port.
 1368:  */
 1369: 
 1370: STATIC stliport_t *stli_dev2port(dev_t dev)
 1371: {
 1372: 	stlibrd_t	*brdp;
 1373: 
 1374: 	brdp = stli_brds[MKDEV2BRD(dev)];
 1375: 	if (brdp == (stlibrd_t *) NULL)
 1376: 		return((stliport_t *) NULL);
 1377: 	if ((brdp->state & BST_STARTED) == 0)
 1378: 		return((stliport_t *) NULL);
 1379: 	return(brdp->ports[MKDEV2PORT(dev)]);
 1380: }
 1381: 
 1382: /*****************************************************************************/
 1383: 
 1384: /*
 1385:  *	Carry out first open operations on a port. This involves a number of
 1386:  *	commands to be sent to the slave. We need to open the port, set the
 1387:  *	notification events, set the initial port settings, get and set the
 1388:  *	initial signal values. We sleep and wait in between each one. But
 1389:  *	this still all happens pretty quickly.
 1390:  */
 1391: 
 1392: static int stli_initopen(stliport_t *portp)
 1393: {
 1394: 	stlibrd_t	*brdp;
 1395: 	asynotify_t	nt;
 1396: 	asyport_t	aport;
 1397: 	int		rc;
 1398: 
 1399: #if STLDEBUG
 1400: 	printf("stli_initopen(portp=%x)\n", (int) portp);
 1401: #endif
 1402: 
 1403: 	if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1404: 		return(ENXIO);
 1405: 	if (portp->state & ST_INITIALIZED)
 1406: 		return(0);
 1407: 	portp->state |= ST_INITIALIZED;
 1408: 
 1409: 	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
 1410: 		return(rc);
 1411: 
 1412: 	bzero(&nt, sizeof(asynotify_t));
 1413: 	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
 1414: 	nt.signal = SG_DCD;
 1415: 	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
 1416: 	    sizeof(asynotify_t), 0)) < 0)
 1417: 		return(rc);
 1418: 
 1419: 	stli_mkasyport(portp, &aport, &portp->tty.t_termios);
 1420: 	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
 1421: 	    sizeof(asyport_t), 0)) < 0)
 1422: 		return(rc);
 1423: 
 1424: 	portp->state |= ST_GETSIGS;
 1425: 	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
 1426: 	    sizeof(asysigs_t), 1)) < 0)
 1427: 		return(rc);
 1428: 	if (portp->state & ST_GETSIGS) {
 1429: 		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
 1430: 		portp->state &= ~ST_GETSIGS;
 1431: 	}
 1432: 
 1433: 	stli_mkasysigs(&portp->asig, 1, 1);
 1434: 	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
 1435: 	    sizeof(asysigs_t), 0)) < 0)
 1436: 		return(rc);
 1437: 
 1438: 	return(0);
 1439: }
 1440: 
 1441: /*****************************************************************************/
 1442: 
 1443: /*
 1444:  *	Shutdown the hardware of a port.
 1445:  */
 1446: 
 1447: static int stli_shutdownclose(stliport_t *portp)
 1448: {
 1449: 	stlibrd_t	*brdp;
 1450: 	struct tty	*tp;
 1451: 	int		x;
 1452: 
 1453: #if STLDEBUG
 1454: 	printf("stli_shutdownclose(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
 1455: 		(void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
 1456: #endif
 1457: 
 1458: 	if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1459: 		return(ENXIO);
 1460: 
 1461: 	tp = &portp->tty;
 1462: 	stli_rawclose(brdp, portp, 0, 0);
 1463: 	stli_flush(portp, (FWRITE | FREAD));
 1464: 	if (tp->t_cflag & HUPCL) {
 1465: 		x = spltty();
 1466: 		stli_mkasysigs(&portp->asig, 0, 0);
 1467: 		if (portp->state & ST_CMDING) {
 1468: 			portp->state |= ST_DOSIGS;
 1469: 		} else {
 1470: 			stli_sendcmd(brdp, portp, A_SETSIGNALS,
 1471: 				&portp->asig, sizeof(asysigs_t), 0);
 1472: 		}
 1473: 		splx(x);
 1474: 		if (portp->dtrwait != 0) {
 1475: 			portp->state |= ST_DTRWAIT;
 1476: 			timeout(stli_dtrwakeup, portp, portp->dtrwait);
 1477: 		}
 1478: 	}
 1479: 	portp->callout = 0;
 1480: 	portp->state &= ~ST_INITIALIZED;
 1481: 	wakeup(&portp->callout);
 1482: 	wakeup(TSA_CARR_ON(tp));
 1483: 	return(0);
 1484: }
 1485: 
 1486: /*****************************************************************************/
 1487: 
 1488: /*
 1489:  *	Clear the DTR waiting flag, and wake up any sleepers waiting for
 1490:  *	DTR wait period to finish.
 1491:  */
 1492: 
 1493: static void stli_dtrwakeup(void *arg)
 1494: {
 1495: 	stliport_t	*portp;
 1496: 
 1497: 	portp = (stliport_t *) arg;
 1498: 	portp->state &= ~ST_DTRWAIT;
 1499: 	wakeup(&portp->dtrwait);
 1500: }
 1501: 
 1502: /*****************************************************************************/
 1503: 
 1504: /*
 1505:  *	Send an open message to the slave. This will sleep waiting for the
 1506:  *	acknowledgement, so must have user context. We need to co-ordinate
 1507:  *	with close events here, since we don't want open and close events
 1508:  *	to overlap.
 1509:  */
 1510: 
 1511: static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
 1512: {
 1513: 	volatile cdkhdr_t	*hdrp;
 1514: 	volatile cdkctrl_t	*cp;
 1515: 	volatile unsigned char	*bits;
 1516: 	int			rc, x;
 1517: 
 1518: #if STLDEBUG
 1519: 	printf("stli_rawopen(brdp=%x,portp=%x,arg=%x,wait=%d)\n", (int) brdp,
 1520: 		(int) portp, (int) arg, wait);
 1521: #endif
 1522: 
 1523: 	x = spltty();
 1524: 
 1525: /*
 1526:  *	Slave is already closing this port. This can happen if a hangup
 1527:  *	occurs on this port. So we must wait until it is complete. The
 1528:  *	order of opens and closes may not be preserved across shared
 1529:  *	memory, so we must wait until it is complete.
 1530:  */
 1531: 	while (portp->state & ST_CLOSING) {
 1532: 		rc = tsleep(&portp->state, PCATCH, "stliraw", 0);
 1533: 		if (rc) {
 1534: 			splx(x);
 1535: 			return(rc);
 1536: 		}
 1537: 	}
 1538: 
 1539: /*
 1540:  *	Everything is ready now, so write the open message into shared
 1541:  *	memory. Once the message is in set the service bits to say that
 1542:  *	this port wants service.
 1543:  */
 1544: 	EBRDENABLE(brdp);
 1545: 	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 1546: 	cp->openarg = arg;
 1547: 	cp->open = 1;
 1548: 	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1549: 	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1550: 		portp->portidx;
 1551: 	*bits |= portp->portbit;
 1552: 	EBRDDISABLE(brdp);
 1553: 
 1554: 	if (wait == 0) {
 1555: 		splx(x);
 1556: 		return(0);
 1557: 	}
 1558: 
 1559: /*
 1560:  *	Slave is in action, so now we must wait for the open acknowledgment
 1561:  *	to come back.
 1562:  */
 1563: 	rc = 0;
 1564: 	portp->state |= ST_OPENING;
 1565: 	while (portp->state & ST_OPENING) {
 1566: 		rc = tsleep(&portp->state, PCATCH, "stliraw", 0);
 1567: 		if (rc) {
 1568: 			splx(x);
 1569: 			return(rc);
 1570: 		}
 1571: 	}
 1572: 	splx(x);
 1573: 
 1574: 	if ((rc == 0) && (portp->rc != 0))
 1575: 		rc = EIO;
 1576: 	return(rc);
 1577: }
 1578: 
 1579: /*****************************************************************************/
 1580: 
 1581: /*
 1582:  *	Send a close message to the slave. Normally this will sleep waiting
 1583:  *	for the acknowledgement, but if wait parameter is 0 it will not. If
 1584:  *	wait is true then must have user context (to sleep).
 1585:  */
 1586: 
 1587: static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
 1588: {
 1589: 	volatile cdkhdr_t	*hdrp;
 1590: 	volatile cdkctrl_t	*cp;
 1591: 	volatile unsigned char	*bits;
 1592: 	int			rc, x;
 1593: 
 1594: #if STLDEBUG
 1595: 	printf("stli_rawclose(brdp=%x,portp=%x,arg=%x,wait=%d)\n", (int) brdp,
 1596: 		(int) portp, (int) arg, wait);
 1597: #endif
 1598: 
 1599: 	x = spltty();
 1600: 
 1601: /*
 1602:  *	Slave is already closing this port. This can happen if a hangup
 1603:  *	occurs on this port.
 1604:  */
 1605: 	if (wait) {
 1606: 		while (portp->state & ST_CLOSING) {
 1607: 			rc = tsleep(&portp->state, PCATCH, "stliraw", 0);
 1608: 			if (rc) {
 1609: 				splx(x);
 1610: 				return(rc);
 1611: 			}
 1612: 		}
 1613: 	}
 1614: 
 1615: /*
 1616:  *	Write the close command into shared memory.
 1617:  */
 1618: 	EBRDENABLE(brdp);
 1619: 	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 1620: 	cp->closearg = arg;
 1621: 	cp->close = 1;
 1622: 	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1623: 	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1624: 		portp->portidx;
 1625: 	*bits |= portp->portbit;
 1626: 	EBRDDISABLE(brdp);
 1627: 
 1628: 	portp->state |= ST_CLOSING;
 1629: 	if (wait == 0) {
 1630: 		splx(x);
 1631: 		return(0);
 1632: 	}
 1633: 
 1634: /*
 1635:  *	Slave is in action, so now we must wait for the open acknowledgment
 1636:  *	to come back.
 1637:  */
 1638: 	rc = 0;
 1639: 	while (portp->state & ST_CLOSING) {
 1640: 		rc = tsleep(&portp->state, PCATCH, "stliraw", 0);
 1641: 		if (rc) {
 1642: 			splx(x);
 1643: 			return(rc);
 1644: 		}
 1645: 	}
 1646: 	splx(x);
 1647: 
 1648: 	if ((rc == 0) && (portp->rc != 0))
 1649: 		rc = EIO;
 1650: 	return(rc);
 1651: }
 1652: 
 1653: /*****************************************************************************/
 1654: 
 1655: /*
 1656:  *	Send a command to the slave and wait for the response. This must
 1657:  *	have user context (it sleeps). This routine is generic in that it
 1658:  *	can send any type of command. Its purpose is to wait for that command
 1659:  *	to complete (as opposed to initiating the command then returning).
 1660:  */
 1661: 
 1662: static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
 1663: {
 1664: 	int	rc, x;
 1665: 
 1666: #if STLDEBUG
 1667: 	printf("stli_cmdwait(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
 1668: 		"copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
 1669: 		(int) arg, size, copyback);
 1670: #endif
 1671: 
 1672: 	x = spltty();
 1673: 	while (portp->state & ST_CMDING) {
 1674: 		rc = tsleep(&portp->state, PCATCH, "stliraw", 0);
 1675: 		if (rc) {
 1676: 			splx(x);
 1677: 			return(rc);
 1678: 		}
 1679: 	}
 1680: 
 1681: 	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
 1682: 
 1683: 	while (portp->state & ST_CMDING) {
 1684: 		rc = tsleep(&portp->state, PCATCH, "stliraw", 0);
 1685: 		if (rc) {
 1686: 			splx(x);
 1687: 			return(rc);
 1688: 		}
 1689: 	}
 1690: 	splx(x);
 1691: 
 1692: 	if (portp->rc != 0)
 1693: 		return(EIO);
 1694: 	return(0);
 1695: }
 1696: 
 1697: /*****************************************************************************/
 1698: 
 1699: /*
 1700:  *	Start (or continue) the transfer of TX data on this port. If the
 1701:  *	port is not currently busy then load up the interrupt ring queue
 1702:  *	buffer and kick of the transmitter. If the port is running low on
 1703:  *	TX data then refill the ring queue. This routine is also used to
 1704:  *	activate input flow control!
 1705:  */
 1706: 
 1707: static void stli_start(struct tty *tp)
 1708: {
 1709: 	volatile cdkasy_t	*ap;
 1710: 	volatile cdkhdr_t	*hdrp;
 1711: 	volatile unsigned char	*bits;
 1712: 	unsigned char		*shbuf;
 1713: 	stliport_t		*portp;
 1714: 	stlibrd_t		*brdp;
 1715: 	unsigned int		len, stlen, head, tail, size;
 1716: 	int			count, x;
 1717: 
 1718: 	portp = (stliport_t *) tp;
 1719: 
 1720: #if STLDEBUG
 1721: 	printf("stli_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp, 
 1722: 		portp->brdnr, portp->portnr);
 1723: #endif
 1724: 
 1725: 	x = spltty();
 1726: 
 1727: #if VFREEBSD == 205
 1728: /*
 1729:  *	Check if the output cooked clist buffers are near empty, wake up
 1730:  *	the line discipline to fill it up.
 1731:  */
 1732: 	if (tp->t_outq.c_cc <= tp->t_lowat) {
 1733: 		if (tp->t_state & TS_ASLEEP) {
 1734: 			tp->t_state &= ~TS_ASLEEP;
 1735: 			wakeup(&tp->t_outq);
 1736: 		}
 1737: 		selwakeup(&tp->t_wsel);
 1738: 	}
 1739: #endif
 1740: 
 1741: 	if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
 1742: 		splx(x);
 1743: 		return;
 1744: 	}
 1745: 
 1746: /*
 1747:  *	Copy data from the clists into the interrupt ring queue. This will
 1748:  *	require at most 2 copys... What we do is calculate how many chars
 1749:  *	can fit into the ring queue, and how many can fit in 1 copy. If after
 1750:  *	the first copy there is still more room then do the second copy. 
 1751:  */
 1752: 	if (tp->t_outq.c_cc != 0) {
 1753: 		brdp = stli_brds[portp->brdnr];
 1754: 		if (brdp == (stlibrd_t *) NULL) {
 1755: 			splx(x);
 1756: 			return;
 1757: 		}
 1758: 
 1759: 		EBRDENABLE(brdp);
 1760: 		ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 1761: 		head = (unsigned int) ap->txq.head;
 1762: 		tail = (unsigned int) ap->txq.tail;
 1763: 		if (tail != ((unsigned int) ap->txq.tail))
 1764: 			tail = (unsigned int) ap->txq.tail;
 1765: 		size = portp->txsize;
 1766: 		if (head >= tail) {
 1767: 			len = size - (head - tail) - 1;
 1768: 			stlen = size - head;
 1769: 		} else {
 1770: 			len = tail - head - 1;
 1771: 			stlen = len;
 1772: 		}
 1773: 
 1774: 		count = 0;
 1775: 		shbuf = (char *) EBRDGETMEMPTR(brdp, portp->txoffset);
 1776: 
 1777: 		if (len > 0) {
 1778: 			stlen = MIN(len, stlen);
 1779: 			count = q_to_b(&tp->t_outq, (shbuf + head), stlen);
 1780: 			len -= count;
 1781: 			head += count;
 1782: 			if (head >= size) {
 1783: 				head = 0;
 1784: 				if (len > 0) {
 1785: 					stlen = q_to_b(&tp->t_outq, shbuf, len);
 1786: 					head += stlen;
 1787: 					count += stlen;
 1788: 				}
 1789: 			}
 1790: 		}
 1791: 
 1792: 		ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 1793: 		ap->txq.head = head;
 1794: 		hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1795: 		bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1796: 			portp->portidx;
 1797: 		*bits |= portp->portbit;
 1798: 		portp->state |= ST_TXBUSY;
 1799: 		tp->t_state |= TS_BUSY;
 1800: 
 1801: 		EBRDDISABLE(brdp);
 1802: 	}
 1803: 
 1804: #if VFREEBSD != 205
 1805: /*
 1806:  *	Do any writer wakeups.
 1807:  */
 1808: 	ttwwakeup(tp);
 1809: #endif
 1810: 
 1811: 	splx(x);
 1812: }
 1813: 
 1814: /*****************************************************************************/
 1815: 
 1816: /*
 1817:  *	Send a new port configuration to the slave.
 1818:  */
 1819: 
 1820: static int stli_param(struct tty *tp, struct termios *tiosp)
 1821: {
 1822: 	stlibrd_t	*brdp;
 1823: 	stliport_t	*portp;
 1824: 	asyport_t	aport;
 1825: 	int		x, rc;
 1826: 
 1827: 	portp = (stliport_t *) tp;
 1828: 	if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
 1829: 		return(ENXIO);
 1830: 
 1831: 	x = spltty();
 1832: 	stli_mkasyport(portp, &aport, tiosp);
 1833: 	/* can we sleep here? */
 1834: 	rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
 1835: 	stli_ttyoptim(portp, tiosp);
 1836: 	splx(x);
 1837: 	return(rc);
 1838: }
 1839: 
 1840: /*****************************************************************************/
 1841: 
 1842: /*
 1843:  *	Flush characters from the lower buffer. We may not have user context
 1844:  *	so we cannot sleep waiting for it to complete. Also we need to check
 1845:  *	if there is chars for this port in the TX cook buffer, and flush them
 1846:  *	as well.
 1847:  */
 1848: 
 1849: static void stli_flush(stliport_t *portp, int flag)
 1850: {
 1851: 	stlibrd_t	*brdp;
 1852: 	unsigned long	ftype;
 1853: 	int		x;
 1854: 
 1855: #if STLDEBUG
 1856: 	printf("stli_flush(portp=%x,flag=%x)\n", (int) portp, flag);
 1857: #endif
 1858: 
 1859: 	if (portp == (stliport_t *) NULL)
 1860: 		return;
 1861: 	if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
 1862: 		return;
 1863: 	brdp = stli_brds[portp->brdnr];
 1864: 	if (brdp == (stlibrd_t *) NULL)
 1865: 		return;
 1866: 
 1867: 	x = spltty();
 1868: 	if (portp->state & ST_CMDING) {
 1869: 		portp->state |= (flag & FWRITE) ? ST_DOFLUSHTX : 0;
 1870: 		portp->state |= (flag & FREAD) ? ST_DOFLUSHRX : 0;
 1871: 	} else {
 1872: 		ftype = (flag & FWRITE) ? FLUSHTX : 0;
 1873: 		ftype |= (flag & FREAD) ? FLUSHRX : 0;
 1874: 		portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX);
 1875: 		stli_sendcmd(brdp, portp, A_FLUSH, &ftype,
 1876: 			sizeof(unsigned long), 0);
 1877: 	}
 1878: 	if ((flag & FREAD) && (stli_rxtmpport == portp))
 1879: 		stli_rxtmplen = 0;
 1880: 	splx(x);
 1881: }
 1882: 
 1883: /*****************************************************************************/
 1884: 
 1885: /*
 1886:  *	Generic send command routine. This will send a message to the slave,
 1887:  *	of the specified type with the specified argument. Must be very
 1888:  *	carefull of data that will be copied out from shared memory -
 1889:  *	containing command results. The command completion is all done from
 1890:  *	a poll routine that does not have user coontext. Therefore you cannot
 1891:  *	copy back directly into user space, or to the kernel stack of a
 1892:  *	process. This routine does not sleep, so can be called from anywhere,
 1893:  *	and must be called with interrupt locks set.
 1894:  */
 1895: 
 1896: static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
 1897: {
 1898: 	volatile cdkhdr_t	*hdrp;
 1899: 	volatile cdkctrl_t	*cp;
 1900: 	volatile unsigned char	*bits;
 1901: 
 1902: #if STLDEBUG
 1903: 	printf("stli_sendcmd(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
 1904: 		"copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
 1905: 		(int) arg, size, copyback);
 1906: #endif
 1907: 
 1908: 	if (portp->state & ST_CMDING) {
 1909: 		printf("STALLION: command already busy, cmd=%x!\n", (int) cmd);
 1910: 		return;
 1911: 	}
 1912: 
 1913: 	EBRDENABLE(brdp);
 1914: 	cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
 1915: 	if (size > 0) {
 1916: 		bcopy(arg, &(cp->args[0]), size);
 1917: 		if (copyback) {
 1918: 			portp->argp = arg;
 1919: 			portp->argsize = size;
 1920: 		}
 1921: 	}
 1922: 	cp->status = 0;
 1923: 	cp->cmd = cmd;
 1924: 	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 1925: 	bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
 1926: 		portp->portidx;
 1927: 	*bits |= portp->portbit;
 1928: 	portp->state |= ST_CMDING;
 1929: 	EBRDDISABLE(brdp);
 1930: }
 1931: 
 1932: /*****************************************************************************/
 1933: 
 1934: /*
 1935:  *	Read data from shared memory. This assumes that the shared memory
 1936:  *	is enabled and that interrupts are off. Basically we just empty out
 1937:  *	the shared memory buffer into the tty buffer. Must be carefull to
 1938:  *	handle the case where we fill up the tty buffer, but still have
 1939:  *	more chars to unload.
 1940:  */
 1941: 
 1942: static void stli_rxprocess(stlibrd_t *brdp, stliport_t *portp)
 1943: {
 1944: 	volatile cdkasyrq_t	*rp;
 1945: 	volatile char		*shbuf;
 1946: 	struct tty		*tp;
 1947: 	unsigned int		head, tail, size;
 1948: 	unsigned int		len, stlen, i;
 1949: 	int			ch;
 1950: 
 1951: #if STLDEBUG
 1952: 	printf("stli_rxprocess(brdp=%x,portp=%d)\n", (int) brdp, (int) portp);
 1953: #endif
 1954: 
 1955: 	tp = &portp->tty;
 1956: 	if ((tp->t_state & TS_ISOPEN) == 0) {
 1957: 		stli_flush(portp, FREAD);
 1958: 		return;
 1959: 	}
 1960: 	if (tp->t_state & TS_TBLOCK)
 1961: 		return;
 1962: 
 1963: 	rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
 1964: 	head = (unsigned int) rp->head;
 1965: 	if (head != ((unsigned int) rp->head))
 1966: 		head = (unsigned int) rp->head;
 1967: 	tail = (unsigned int) rp->tail;
 1968: 	size = portp->rxsize;
 1969: 	if (head >= tail) {
 1970: 		len = head - tail;
 1971: 		stlen = len;
 1972: 	} else {
 1973: 		len = size - (tail - head);
 1974: 		stlen = size - tail;
 1975: 	}
 1976: 
 1977: 	if (len == 0)
 1978: 		return;
 1979: 
 1980: 	shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
 1981: 
 1982: /*
 1983:  *	If we can bypass normal LD processing then just copy direct
 1984:  *	from board shared memory into the tty buffers.
 1985:  */
 1986: 	if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
 1987: 		if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
 1988: 		    ((tp->t_cflag & CRTS_IFLOW) || (tp->t_iflag & IXOFF)) &&
 1989: 		    ((tp->t_state & TS_TBLOCK) == 0)) {
 1990: 			ch = TTYHOG - tp->t_rawq.c_cc - 1;
 1991: 			len = (ch > 0) ? ch : 0;
 1992: 			stlen = MIN(stlen, len);
 1993: 			tp->t_state |= TS_TBLOCK;
 1994: 		}
 1995: 		i = b_to_q((char *) (shbuf + tail), stlen, &tp->t_rawq);
 1996: 		tail += stlen;
 1997: 		len -= stlen;
 1998: 		if (tail >= size) {
 1999: 			tail = 0;
 2000: 			i += b_to_q((char *) shbuf, len, &tp->t_rawq);
 2001: 			tail += len;
 2002: 		}
 2003: 		portp->rxlost += i;
 2004: 		ttwakeup(tp);
 2005: 		rp = &((volatile cdkasy_t *)
 2006: 			EBRDGETMEMPTR(brdp, portp->addr))->rxq;
 2007: 		rp->tail = tail;
 2008: 
 2009: 	} else {
 2010: /*
 2011:  *		Copy the data from board shared memory into a local
 2012:  *		memory buffer. Then feed them from here into the LD.
 2013:  *		We don't want to go into board shared memory one char
 2014:  *		at a time, it is too slow...
 2015:  */
 2016: 		if (len > TTYHOG) {
 2017: 			len = TTYHOG - 1;
 2018: 			stlen = min(len, stlen);
 2019: 		}
 2020: 		stli_rxtmpport = portp;
 2021: 		stli_rxtmplen = len;
 2022: 		bcopy((char *) (shbuf + tail), &stli_rxtmpbuf[0], stlen);
 2023: 		len -= stlen;
 2024: 		if (len > 0)
 2025: 			bcopy(shbuf, &stli_rxtmpbuf[stlen], len);
 2026: 		
 2027: 		for (i = 0; (i < stli_rxtmplen); i++) {
 2028: 			ch = (unsigned char) stli_rxtmpbuf[i];
 2029: 			(*linesw[tp->t_line].l_rint)(ch, tp);
 2030: 		}
 2031: 		EBRDENABLE(brdp);
 2032: 		rp = &((volatile cdkasy_t *)
 2033: 			EBRDGETMEMPTR(brdp, portp->addr))->rxq;
 2034: 		if (stli_rxtmplen == 0) {
 2035: 			head = (unsigned int) rp->head;
 2036: 			if (head != ((unsigned int) rp->head))
 2037: 				head = (unsigned int) rp->head;
 2038: 			tail = head;
 2039: 		} else {
 2040: 			tail += i;
 2041: 			if (tail >= size)
 2042: 				tail -= size;
 2043: 		}
 2044: 		rp->tail = tail;
 2045: 		stli_rxtmpport = (stliport_t *) NULL;
 2046: 		stli_rxtmplen = 0;
 2047: 	}
 2048: 
 2049: 	portp->state |= ST_RXING;
 2050: }
 2051: 
 2052: /*****************************************************************************/
 2053: 
 2054: /*
 2055:  *	Set up and carry out any delayed commands. There is only a small set
 2056:  *	of slave commands that can be done "off-level". So it is not too
 2057:  *	difficult to deal with them as a special case here.
 2058:  */
 2059: 
 2060: static __inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
 2061: {
 2062: 	int	cmd;
 2063: 
 2064: 	if (portp->state & ST_DOSIGS) {
 2065: 		if ((portp->state & ST_DOFLUSHTX) &&
 2066: 		    (portp->state & ST_DOFLUSHRX))
 2067: 			cmd = A_SETSIGNALSF;
 2068: 		else if (portp->state & ST_DOFLUSHTX)
 2069: 			cmd = A_SETSIGNALSFTX;
 2070: 		else if (portp->state & ST_DOFLUSHRX)
 2071: 			cmd = A_SETSIGNALSFRX;
 2072: 		else
 2073: 			cmd = A_SETSIGNALS;
 2074: 		portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX | ST_DOSIGS);
 2075: 		bcopy(&portp->asig, &(cp->args[0]), sizeof(asysigs_t));
 2076: 		cp->status = 0;
 2077: 		cp->cmd = cmd;
 2078: 		portp->state |= ST_CMDING;
 2079: 	} else if ((portp->state & ST_DOFLUSHTX) ||
 2080: 	    (portp->state & ST_DOFLUSHRX)) {
 2081: 		cmd = ((portp->state & ST_DOFLUSHTX) ? FLUSHTX : 0);
 2082: 		cmd |= ((portp->state & ST_DOFLUSHRX) ? FLUSHRX : 0);
 2083: 		portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX);
 2084: 		bcopy(&cmd, &(cp->args[0]), sizeof(int));
 2085: 		cp->status = 0;
 2086: 		cp->cmd = A_FLUSH;
 2087: 		portp->state |= ST_CMDING;
 2088: 	}
 2089: }
 2090: 
 2091: /*****************************************************************************/
 2092: 
 2093: /*
 2094:  *	Host command service checking. This handles commands or messages
 2095:  *	coming from the slave to the host. Must have board shared memory
 2096:  *	enabled and interrupts off when called. Notice that by servicing the
 2097:  *	read data last we don't need to change the shared memory pointer
 2098:  *	during processing (which is a slow IO operation).
 2099:  *	Return value indicates if this port is still awaiting actions from
 2100:  *	the slave (like open, command, or even TX data being sent). If 0
 2101:  *	then port is still busy, otherwise the port request bit flag is
 2102:  *	returned.
 2103:  */
 2104: 
 2105: static __inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
 2106: {
 2107: 	volatile cdkasy_t	*ap;
 2108: 	volatile cdkctrl_t	*cp;
 2109: 	asynotify_t		nt;
 2110: 	unsigned long		oldsigs;
 2111: 	unsigned int		head, tail;
 2112: 	int			rc, donerx;
 2113: 
 2114: #if STLDEBUG
 2115: 	printf("stli_hostcmd(brdp=%x,portp=%x)\n", (int) brdp, (int) portp);
 2116: #endif
 2117: 
 2118: 	ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 2119: 	cp = &ap->ctrl;
 2120: 
 2121: /*
 2122:  *	Check if we are waiting for an open completion message.
 2123:  */
 2124: 	if (portp->state & ST_OPENING) {
 2125: 		rc = (int) cp->openarg;
 2126: 		if ((cp->open == 0) && (rc != 0)) {
 2127: 			if (rc > 0)
 2128: 				rc--;
 2129: 			cp->openarg = 0;
 2130: 			portp->rc = rc;
 2131: 			portp->state &= ~ST_OPENING;
 2132: 			wakeup(&portp->state);
 2133: 		}
 2134: 	}
 2135: 
 2136: /*
 2137:  *	Check if we are waiting for a close completion message.
 2138:  */
 2139: 	if (portp->state & ST_CLOSING) {
 2140: 		rc = (int) cp->closearg;
 2141: 		if ((cp->close == 0) && (rc != 0)) {
 2142: 			if (rc > 0)
 2143: 				rc--;
 2144: 			cp->closearg = 0;
 2145: 			portp->rc = rc;
 2146: 			portp->state &= ~ST_CLOSING;
 2147: 			wakeup(&portp->state);
 2148: 		}
 2149: 	}
 2150: 
 2151: /*
 2152:  *	Check if we are waiting for a command completion message. We may
 2153:  *	need to copy out the command results associated with this command.
 2154:  */
 2155: 	if (portp->state & ST_CMDING) {
 2156: 		rc = cp->status;
 2157: 		if ((cp->cmd == 0) && (rc != 0)) {
 2158: 			if (rc > 0)
 2159: 				rc--;
 2160: 			if (portp->argp != (void *) NULL) {
 2161: 				bcopy(&(cp->args[0]), portp->argp,
 2162: 					portp->argsize);
 2163: 				portp->argp = (void *) NULL;
 2164: 			}
 2165: 			cp->status = 0;
 2166: 			portp->rc = rc;
 2167: 			portp->state &= ~ST_CMDING;
 2168: 			stli_dodelaycmd(portp, cp);
 2169: 			wakeup(&portp->state);
 2170: 		}
 2171: 	}
 2172: 
 2173: /*
 2174:  *	Check for any notification messages ready. This includes lots of
 2175:  *	different types of events - RX chars ready, RX break received,
 2176:  *	TX data low or empty in the slave, modem signals changed state.
 2177:  *	Must be extremely carefull if we call to the LD, it may call
 2178:  *	other routines of ours that will disable the memory...
 2179:  *	Something else we need to be carefull of is race conditions on
 2180:  *	marking the TX as empty...
 2181:  */
 2182: 	donerx = 0;
 2183: 
 2184: 	if (ap->notify) {
 2185: 		struct tty	*tp;
 2186: 
 2187: 		nt = ap->changed;
 2188: 		ap->notify = 0;
 2189: 		tp = &portp->tty;
 2190: 
 2191: 		if (nt.signal & SG_DCD) {
 2192: 			oldsigs = portp->sigs;
 2193: 			portp->sigs = stli_mktiocm(nt.sigvalue);
 2194: 			portp->state &= ~ST_GETSIGS;
 2195: 			(*linesw[tp->t_line].l_modem)(tp,
 2196: 				(portp->sigs & TIOCM_CD));
 2197: 			EBRDENABLE(brdp);
 2198: 		}
 2199: 		if (nt.data & DT_RXBUSY) {
 2200: 			donerx++;
 2201: 			stli_rxprocess(brdp, portp);
 2202: 		}
 2203: 		if (nt.data & DT_RXBREAK) {
 2204: 			(*linesw[tp->t_line].l_rint)(TTY_BI, tp);
 2205: 			EBRDENABLE(brdp);
 2206: 		}
 2207: 		if (nt.data & DT_TXEMPTY) {
 2208: 			ap = (volatile cdkasy_t *)
 2209: 				EBRDGETMEMPTR(brdp, portp->addr);
 2210: 			head = (unsigned int) ap->txq.head;
 2211: 			tail = (unsigned int) ap->txq.tail;
 2212: 			if (tail != ((unsigned int) ap->txq.tail))
 2213: 				tail = (unsigned int) ap->txq.tail;
 2214: 			head = (head >= tail) ? (head - tail) :
 2215: 				portp->txsize - (tail - head);
 2216: 			if (head == 0) {
 2217: 				portp->state &= ~ST_TXBUSY;
 2218: 				tp->t_state &= ~TS_BUSY;
 2219: 			}
 2220: 		}
 2221: 		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
 2222: 			(*linesw[tp->t_line].l_start)(tp);
 2223: 			EBRDENABLE(brdp);
 2224: 		}
 2225: 	}
 2226: 
 2227: /*
 2228:  *	It might seem odd that we are checking for more RX chars here.
 2229:  *	But, we need to handle the case where the tty buffer was previously
 2230:  *	filled, but we had more characters to pass up. The slave will not
 2231:  *	send any more RX notify messages until the RX buffer has been emptied.
 2232:  *	But it will leave the service bits on (since the buffer is not empty).
 2233:  *	So from here we can try to process more RX chars.
 2234:  */
 2235: 	if ((!donerx) && (portp->state & ST_RXING)) {
 2236: 		portp->state &= ~ST_RXING;
 2237: 		stli_rxprocess(brdp, portp);
 2238: 	}
 2239: 
 2240: 	return((portp->state & (ST_OPENING | ST_CLOSING | ST_CMDING |
 2241: 		ST_TXBUSY | ST_RXING)) ? 0 : 1);
 2242: }
 2243: 
 2244: /*****************************************************************************/
 2245: 
 2246: /*
 2247:  *	Service all ports on a particular board. Assumes that the boards
 2248:  *	shared memory is enabled, and that the page pointer is pointed
 2249:  *	at the cdk header structure.
 2250:  */
 2251: 
 2252: static __inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
 2253: {
 2254: 	stliport_t	*portp;
 2255: 	unsigned char	hostbits[(STL_MAXCHANS / 8) + 1];
 2256: 	unsigned char	slavebits[(STL_MAXCHANS / 8) + 1];
 2257: 	unsigned char	*slavep;
 2258: 	int		bitpos, bitat, bitsize;
 2259: 	int 		channr, nrdevs, slavebitchange;
 2260: 
 2261: 	bitsize = brdp->bitsize;
 2262: 	nrdevs = brdp->nrdevs;
 2263: 
 2264: /*
 2265:  *	Check if slave wants any service. Basically we try to do as
 2266:  *	little work as possible here. There are 2 levels of service
 2267:  *	bits. So if there is nothing to do we bail early. We check
 2268:  *	8 service bits at a time in the inner loop, so we can bypass
 2269:  *	the lot if none of them want service.
 2270:  */
 2271: 	bcopy((((unsigned char *) hdrp) + brdp->hostoffset), &hostbits[0],
 2272: 		bitsize);
 2273: 
 2274: 	bzero(&slavebits[0], bitsize);
 2275: 	slavebitchange = 0;
 2276: 
 2277: 	for (bitpos = 0; (bitpos < bitsize); bitpos++) {
 2278: 		if (hostbits[bitpos] == 0)
 2279: 			continue;
 2280: 		channr = bitpos * 8;
 2281: 		bitat = 0x1;
 2282: 		for (; (channr < nrdevs); channr++, bitat <<=1) {
 2283: 			if (hostbits[bitpos] & bitat) {
 2284: 				portp = brdp->ports[(channr - 1)];
 2285: 				if (stli_hostcmd(brdp, portp)) {
 2286: 					slavebitchange++;
 2287: 					slavebits[bitpos] |= bitat;
 2288: 				}
 2289: 			}
 2290: 		}
 2291: 	}
 2292: 
 2293: /*
 2294:  *	If any of the ports are no longer busy then update them in the
 2295:  *	slave request bits. We need to do this after, since a host port
 2296:  *	service may initiate more slave requests...
 2297:  */
 2298: 	if (slavebitchange) {
 2299: 		hdrp = (volatile cdkhdr_t *)
 2300: 			EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 2301: 		slavep = ((unsigned char *) hdrp) + brdp->slaveoffset;
 2302: 		for (bitpos = 0; (bitpos < bitsize); bitpos++) {
 2303: 			if (slavebits[bitpos])
 2304: 				slavep[bitpos] &= ~slavebits[bitpos];
 2305: 		}
 2306: 	}
 2307: }
 2308: 
 2309: /*****************************************************************************/
 2310: 
 2311: /*
 2312:  *	Driver poll routine. This routine polls the boards in use and passes
 2313:  *	messages back up to host when neccesary. This is actually very
 2314:  *	CPU efficient, since we will always have the kernel poll clock, it
 2315:  *	adds only a few cycles when idle (since board service can be
 2316:  *	determined very easily), but when loaded generates no interrupts
 2317:  *	(with their expensive associated context change).
 2318:  */
 2319: 
 2320: static void stli_poll(void *arg)
 2321: {
 2322: 	volatile cdkhdr_t	*hdrp;
 2323: 	stlibrd_t		*brdp;
 2324: 	int 			brdnr, x;
 2325: 
 2326: 	x = spltty();
 2327: 
 2328: /*
 2329:  *	Check each board and do any servicing required.
 2330:  */
 2331: 	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
 2332: 		brdp = stli_brds[brdnr];
 2333: 		if (brdp == (stlibrd_t *) NULL)
 2334: 			continue;
 2335: 		if ((brdp->state & BST_STARTED) == 0)
 2336: 			continue;
 2337: 
 2338: 		EBRDENABLE(brdp);
 2339: 		hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 2340: 		if (hdrp->hostreq)
 2341: 			stli_brdpoll(brdp, hdrp);
 2342: 		EBRDDISABLE(brdp);
 2343: 	}
 2344: 	splx(x);
 2345: 
 2346: 	timeout(stli_poll, 0, 1);
 2347: }
 2348: 
 2349: /*****************************************************************************/
 2350: 
 2351: /*
 2352:  *	Translate the termios settings into the port setting structure of
 2353:  *	the slave.
 2354:  */
 2355: 
 2356: static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
 2357: {
 2358: #if STLDEBUG
 2359: 	printf("stli_mkasyport(portp=%x,pp=%x,tiosp=%d)\n", (int) portp,
 2360: 		(int) pp, (int) tiosp);
 2361: #endif
 2362: 
 2363: 	bzero(pp, sizeof(asyport_t));
 2364: 
 2365: /*
 2366:  *	Start of by setting the baud, char size, parity and stop bit info.
 2367:  */
 2368: 	if (tiosp->c_ispeed == 0)
 2369: 		tiosp->c_ispeed = tiosp->c_ospeed;
 2370: 	if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > STL_MAXBAUD))
 2371: 		tiosp->c_ospeed = STL_MAXBAUD;
 2372: 	pp->baudout = tiosp->c_ospeed;
 2373: 	pp->baudin = pp->baudout;
 2374: 
 2375: 	switch (tiosp->c_cflag & CSIZE) {
 2376: 	case CS5:
 2377: 		pp->csize = 5;
 2378: 		break;
 2379: 	case CS6:
 2380: 		pp->csize = 6;
 2381: 		break;
 2382: 	case CS7:
 2383: 		pp->csize = 7;
 2384: 		break;
 2385: 	default:
 2386: 		pp->csize = 8;
 2387: 		break;
 2388: 	}
 2389: 
 2390: 	if (tiosp->c_cflag & CSTOPB)
 2391: 		pp->stopbs = PT_STOP2;
 2392: 	else
 2393: 		pp->stopbs = PT_STOP1;
 2394: 
 2395: 	if (tiosp->c_cflag & PARENB) {
 2396: 		if (tiosp->c_cflag & PARODD)
 2397: 			pp->parity = PT_ODDPARITY;
 2398: 		else
 2399: 			pp->parity = PT_EVENPARITY;
 2400: 	} else {
 2401: 		pp->parity = PT_NOPARITY;
 2402: 	}
 2403: 
 2404: 	if (tiosp->c_iflag & ISTRIP)
 2405: 		pp->iflag |= FI_ISTRIP;
 2406: 
 2407: /*
 2408:  *	Set up any flow control options enabled.
 2409:  */
 2410: 	if (tiosp->c_iflag & IXON) {
 2411: 		pp->flow |= F_IXON;
 2412: 		if (tiosp->c_iflag & IXANY)
 2413: 			pp->flow |= F_IXANY;
 2414: 	}
 2415: 	if (tiosp->c_iflag & IXOFF)
 2416: 		pp->flow |= F_IXOFF;
 2417: 	if (tiosp->c_cflag & CCTS_OFLOW)
 2418: 		pp->flow |= F_CTSFLOW;
 2419: 	if (tiosp->c_cflag & CRTS_IFLOW)
 2420: 		pp->flow |= F_RTSFLOW;
 2421: 
 2422: 	pp->startin = tiosp->c_cc[VSTART];
 2423: 	pp->stopin = tiosp->c_cc[VSTOP];
 2424: 	pp->startout = tiosp->c_cc[VSTART];
 2425: 	pp->stopout = tiosp->c_cc[VSTOP];
 2426: 
 2427: /*
 2428:  *	Set up the RX char marking mask with those RX error types we must
 2429:  *	catch. We can get the slave to help us out a little here, it will
 2430:  *	ignore parity errors and breaks for us, and mark parity errors in
 2431:  *	the data stream.
 2432:  */
 2433: 	if (tiosp->c_iflag & IGNPAR)
 2434: 		pp->iflag |= FI_IGNRXERRS;
 2435: 	if (tiosp->c_iflag & IGNBRK)
 2436: 		pp->iflag |= FI_IGNBREAK;
 2437: 	if (tiosp->c_iflag & (INPCK | PARMRK))
 2438: 		pp->iflag |= FI_1MARKRXERRS;
 2439: 
 2440: /*
 2441:  *	Transfer any persistent flags into the asyport structure.
 2442:  */
 2443: 	pp->pflag = (portp->pflag & 0xffff);
 2444: 	pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0;
 2445: 	pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0;
 2446: 	pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0;
 2447: }
 2448: 
 2449: /*****************************************************************************/
 2450: 
 2451: /*
 2452:  *	Construct a slave signals structure for setting the DTR and RTS
 2453:  *	signals as specified.
 2454:  */
 2455: 
 2456: static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
 2457: {
 2458: #if STLDEBUG
 2459: 	printf("stli_mkasysigs(sp=%x,dtr=%d,rts=%d)\n", (int) sp, dtr, rts);
 2460: #endif
 2461: 
 2462: 	bzero(sp, sizeof(asysigs_t));
 2463: 	if (dtr >= 0) {
 2464: 		sp->signal |= SG_DTR;
 2465: 		sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
 2466: 	}
 2467: 	if (rts >= 0) {
 2468: 		sp->signal |= SG_RTS;
 2469: 		sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
 2470: 	}
 2471: }
 2472: 
 2473: /*****************************************************************************/
 2474: 
 2475: /*
 2476:  *	Convert the signals returned from the slave into a local TIOCM type
 2477:  *	signals value. We keep them localy in TIOCM format.
 2478:  */
 2479: 
 2480: static long stli_mktiocm(unsigned long sigvalue)
 2481: {
 2482: 	long	tiocm;
 2483: 
 2484: #if STLDEBUG
 2485: 	printf("stli_mktiocm(sigvalue=%x)\n", (int) sigvalue);
 2486: #endif
 2487: 
 2488: 	tiocm = 0;
 2489: 	tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
 2490: 	tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
 2491: 	tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
 2492: 	tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
 2493: 	tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
 2494: 	tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
 2495: 	return(tiocm);
 2496: }
 2497: 
 2498: /*****************************************************************************/
 2499: 
 2500: /*
 2501:  *	Enable l_rint processing bypass mode if tty modes allow it.
 2502:  */
 2503: 
 2504: static void stli_ttyoptim(stliport_t *portp, struct termios *tiosp)
 2505: {
 2506: 	struct tty	*tp;
 2507: 
 2508: 	tp = &portp->tty;
 2509: 	if (((tiosp->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR)) == 0) &&
 2510: 	    (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
 2511: 	    (((tiosp->c_iflag & PARMRK) == 0) ||
 2512: 		((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
 2513: 	    ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
 2514: 	    (linesw[tp->t_line].l_rint == ttyinput))
 2515: 		tp->t_state |= TS_CAN_BYPASS_L_RINT;
 2516: 	else
 2517: 		tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
 2518: 	portp->hotchar = linesw[tp->t_line].l_hotchar;
 2519: }
 2520: 
 2521: /*****************************************************************************/
 2522: 
 2523: /*
 2524:  *	All panels and ports actually attached have been worked out. All
 2525:  *	we need to do here is set up the appropriate per port data structures.
 2526:  */
 2527: 
 2528: static int stli_initports(stlibrd_t *brdp)
 2529: {
 2530: 	stliport_t	*portp;
 2531: 	int		i, panelnr, panelport;
 2532: 
 2533: #if STLDEBUG
 2534: 	printf("stli_initports(brdp=%x)\n", (int) brdp);
 2535: #endif
 2536: 
 2537: 	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
 2538: 		portp = (stliport_t *) malloc(sizeof(stliport_t), M_TTYS,
 2539: 			M_NOWAIT);
 2540: 		if (portp == (stliport_t *) NULL) {
 2541: 			printf("STALLION: failed to allocate port structure\n");
 2542: 			continue;
 2543: 		}
 2544: 		bzero(portp, sizeof(stliport_t));
 2545: 
 2546: 		portp->portnr = i;
 2547: 		portp->brdnr = brdp->brdnr;
 2548: 		portp->panelnr = panelnr;
 2549: 		portp->initintios.c_ispeed = STL_DEFSPEED;
 2550: 		portp->initintios.c_ospeed = STL_DEFSPEED;
 2551: 		portp->initintios.c_cflag = STL_DEFCFLAG;
 2552: 		portp->initintios.c_iflag = 0;
 2553: 		portp->initintios.c_oflag = 0;
 2554: 		portp->initintios.c_lflag = 0;
 2555: 		bcopy(&ttydefchars[0], &portp->initintios.c_cc[0],
 2556: 			sizeof(portp->initintios.c_cc));
 2557: 		portp->initouttios = portp->initintios;
 2558: 		portp->dtrwait = 3 * hz;
 2559: 
 2560: 		panelport++;
 2561: 		if (panelport >= brdp->panels[panelnr]) {
 2562: 			panelport = 0;
 2563: 			panelnr++;
 2564: 		}
 2565: 		brdp->ports[i] = portp;
 2566: 
 2567: 	}
 2568: 
 2569: 	return(0);
 2570: }
 2571: 
 2572: /*****************************************************************************/
 2573: 
 2574: /*
 2575:  *	All the following routines are board specific hardware operations.
 2576:  */
 2577: 
 2578: static void stli_ecpinit(stlibrd_t *brdp)
 2579: {
 2580: 	unsigned long	memconf;
 2581: 
 2582: #if STLDEBUG
 2583: 	printf("stli_ecpinit(brdp=%d)\n", (int) brdp);
 2584: #endif
 2585: 
 2586: 	outb((brdp->iobase + ECP_ATCONFR), ECP_ATSTOP);
 2587: 	DELAY(10);
 2588: 	outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
 2589: 	DELAY(100);
 2590: 
 2591: 	memconf = (brdp->paddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
 2592: 	outb((brdp->iobase + ECP_ATMEMAR), memconf);
 2593: }
 2594: 
 2595: /*****************************************************************************/
 2596: 
 2597: static void stli_ecpenable(stlibrd_t *brdp)
 2598: {	
 2599: #if STLDEBUG
 2600: 	printf("stli_ecpenable(brdp=%x)\n", (int) brdp);
 2601: #endif
 2602: 	outb((brdp->iobase + ECP_ATCONFR), ECP_ATENABLE);
 2603: }
 2604: 
 2605: /*****************************************************************************/
 2606: 
 2607: static void stli_ecpdisable(stlibrd_t *brdp)
 2608: {	
 2609: #if STLDEBUG
 2610: 	printf("stli_ecpdisable(brdp=%x)\n", (int) brdp);
 2611: #endif
 2612: 	outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
 2613: }
 2614: 
 2615: /*****************************************************************************/
 2616: 
 2617: static char *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2618: {	
 2619: 	void		*ptr;
 2620: 	unsigned char	val;
 2621: 
 2622: #if STLDEBUG
 2623: 	printf("stli_ecpgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 2624: 		(int) offset);
 2625: #endif
 2626: 
 2627: 	if (offset > brdp->memsize) {
 2628: 		printf("STALLION: shared memory pointer=%x out of range at "
 2629: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 2630: 			__LINE__, brdp->brdnr);
 2631: 		ptr = 0;
 2632: 		val = 0;
 2633: 	} else {
 2634: 		ptr = (char *) brdp->vaddr + (offset % ECP_ATPAGESIZE);
 2635: 		val = (unsigned char) (offset / ECP_ATPAGESIZE);
 2636: 	}
 2637: 	outb((brdp->iobase + ECP_ATMEMPR), val);
 2638: 	return(ptr);
 2639: }
 2640: 
 2641: /*****************************************************************************/
 2642: 
 2643: static void stli_ecpreset(stlibrd_t *brdp)
 2644: {	
 2645: #if STLDEBUG
 2646: 	printf("stli_ecpreset(brdp=%x)\n", (int) brdp);
 2647: #endif
 2648: 
 2649: 	outb((brdp->iobase + ECP_ATCONFR), ECP_ATSTOP);
 2650: 	DELAY(10);
 2651: 	outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
 2652: 	DELAY(500);
 2653: }
 2654: 
 2655: /*****************************************************************************/
 2656: 
 2657: static void stli_ecpintr(stlibrd_t *brdp)
 2658: {	
 2659: #if STLDEBUG
 2660: 	printf("stli_ecpintr(brdp=%x)\n", (int) brdp);
 2661: #endif
 2662: 	outb(brdp->iobase, 0x1);
 2663: }
 2664: 
 2665: /*****************************************************************************/
 2666: 
 2667: /*
 2668:  *	The following set of functions act on ECP EISA boards.
 2669:  */
 2670: 
 2671: static void stli_ecpeiinit(stlibrd_t *brdp)
 2672: {
 2673: 	unsigned long	memconf;
 2674: 
 2675: #if STLDEBUG
 2676: 	printf("stli_ecpeiinit(brdp=%x)\n", (int) brdp);
 2677: #endif
 2678: 
 2679: 	outb((brdp->iobase + ECP_EIBRDENAB), 0x1);
 2680: 	outb((brdp->iobase + ECP_EICONFR), ECP_EISTOP);
 2681: 	DELAY(10);
 2682: 	outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
 2683: 	DELAY(500);
 2684: 
 2685: 	memconf = (brdp->paddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
 2686: 	outb((brdp->iobase + ECP_EIMEMARL), memconf);
 2687: 	memconf = (brdp->paddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
 2688: 	outb((brdp->iobase + ECP_EIMEMARH), memconf);
 2689: }
 2690: 
 2691: /*****************************************************************************/
 2692: 
 2693: static void stli_ecpeienable(stlibrd_t *brdp)
 2694: {	
 2695: 	outb((brdp->iobase + ECP_EICONFR), ECP_EIENABLE);
 2696: }
 2697: 
 2698: /*****************************************************************************/
 2699: 
 2700: static void stli_ecpeidisable(stlibrd_t *brdp)
 2701: {	
 2702: 	outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
 2703: }
 2704: 
 2705: /*****************************************************************************/
 2706: 
 2707: static char *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2708: {	
 2709: 	void		*ptr;
 2710: 	unsigned char	val;
 2711: 
 2712: #if STLDEBUG
 2713: 	printf("stli_ecpeigetmemptr(brdp=%x,offset=%x,line=%d)\n",
 2714: 		(int) brdp, (int) offset, line);
 2715: #endif
 2716: 
 2717: 	if (offset > brdp->memsize) {
 2718: 		printf("STALLION: shared memory pointer=%x out of range at "
 2719: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 2720: 			__LINE__, brdp->brdnr);
 2721: 		ptr = 0;
 2722: 		val = 0;
 2723: 	} else {
 2724: 		ptr = (char *) brdp->vaddr + (offset % ECP_EIPAGESIZE);
 2725: 		if (offset < ECP_EIPAGESIZE)
 2726: 			val = ECP_EIENABLE;
 2727: 		else
 2728: 			val = ECP_EIENABLE | 0x40;
 2729: 	}
 2730: 	outb((brdp->iobase + ECP_EICONFR), val);
 2731: 	return(ptr);
 2732: }
 2733: 
 2734: /*****************************************************************************/
 2735: 
 2736: static void stli_ecpeireset(stlibrd_t *brdp)
 2737: {	
 2738: 	outb((brdp->iobase + ECP_EICONFR), ECP_EISTOP);
 2739: 	DELAY(10);
 2740: 	outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
 2741: 	DELAY(500);
 2742: }
 2743: 
 2744: /*****************************************************************************/
 2745: 
 2746: /*
 2747:  *	The following set of functions act on ECP MCA boards.
 2748:  */
 2749: 
 2750: static void stli_ecpmcenable(stlibrd_t *brdp)
 2751: {	
 2752: 	outb((brdp->iobase + ECP_MCCONFR), ECP_MCENABLE);
 2753: }
 2754: 
 2755: /*****************************************************************************/
 2756: 
 2757: static void stli_ecpmcdisable(stlibrd_t *brdp)
 2758: {	
 2759: 	outb((brdp->iobase + ECP_MCCONFR), ECP_MCDISABLE);
 2760: }
 2761: 
 2762: /*****************************************************************************/
 2763: 
 2764: static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2765: {	
 2766: 	void		*ptr;
 2767: 	unsigned char	val;
 2768: 
 2769: 	if (offset > brdp->memsize) {
 2770: 		printf("STALLION: shared memory pointer=%x out of range at "
 2771: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 2772: 			__LINE__, brdp->brdnr);
 2773: 		ptr = 0;
 2774: 		val = 0;
 2775: 	} else {
 2776: 		ptr = (char *) brdp->vaddr + (offset % ECP_MCPAGESIZE);
 2777: 		val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
 2778: 	}
 2779: 	outb((brdp->iobase + ECP_MCCONFR), val);
 2780: 	return(ptr);
 2781: }
 2782: 
 2783: /*****************************************************************************/
 2784: 
 2785: static void stli_ecpmcreset(stlibrd_t *brdp)
 2786: {	
 2787: 	outb((brdp->iobase + ECP_MCCONFR), ECP_MCSTOP);
 2788: 	DELAY(10);
 2789: 	outb((brdp->iobase + ECP_MCCONFR), ECP_MCDISABLE);
 2790: 	DELAY(500);
 2791: }
 2792: 
 2793: /*****************************************************************************/
 2794: 
 2795: /*
 2796:  *	The following routines act on ONboards.
 2797:  */
 2798: 
 2799: static void stli_onbinit(stlibrd_t *brdp)
 2800: {
 2801: 	unsigned long	memconf;
 2802: 	int		i;
 2803: 
 2804: #if STLDEBUG
 2805: 	printf("stli_onbinit(brdp=%d)\n", (int) brdp);
 2806: #endif
 2807: 
 2808: 	outb((brdp->iobase + ONB_ATCONFR), ONB_ATSTOP);
 2809: 	DELAY(10);
 2810: 	outb((brdp->iobase + ONB_ATCONFR), ONB_ATDISABLE);
 2811: 	for (i = 0; (i < 1000); i++)
 2812: 		DELAY(1000);
 2813: 
 2814: 	memconf = (brdp->paddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
 2815: 	outb((brdp->iobase + ONB_ATMEMAR), memconf);
 2816: 	outb(brdp->iobase, 0x1);
 2817: 	DELAY(1000);
 2818: }
 2819: 
 2820: /*****************************************************************************/
 2821: 
 2822: static void stli_onbenable(stlibrd_t *brdp)
 2823: {	
 2824: #if STLDEBUG
 2825: 	printf("stli_onbenable(brdp=%x)\n", (int) brdp);
 2826: #endif
 2827: 	outb((brdp->iobase + ONB_ATCONFR), (ONB_ATENABLE | brdp->confbits));
 2828: }
 2829: 
 2830: /*****************************************************************************/
 2831: 
 2832: static void stli_onbdisable(stlibrd_t *brdp)
 2833: {	
 2834: #if STLDEBUG
 2835: 	printf("stli_onbdisable(brdp=%x)\n", (int) brdp);
 2836: #endif
 2837: 	outb((brdp->iobase + ONB_ATCONFR), (ONB_ATDISABLE | brdp->confbits));
 2838: }
 2839: 
 2840: /*****************************************************************************/
 2841: 
 2842: static char *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2843: {	
 2844: 	void	*ptr;
 2845: 
 2846: #if STLDEBUG
 2847: 	printf("stli_onbgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 2848: 		(int) offset);
 2849: #endif
 2850: 
 2851: 	if (offset > brdp->memsize) {
 2852: 		printf("STALLION: shared memory pointer=%x out of range at "
 2853: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 2854: 			__LINE__, brdp->brdnr);
 2855: 		ptr = 0;
 2856: 	} else {
 2857: 		ptr = (char *) brdp->vaddr + (offset % ONB_ATPAGESIZE);
 2858: 	}
 2859: 	return(ptr);
 2860: }
 2861: 
 2862: /*****************************************************************************/
 2863: 
 2864: static void stli_onbreset(stlibrd_t *brdp)
 2865: {	
 2866: 	int	i;
 2867: 
 2868: #if STLDEBUG
 2869: 	printf("stli_onbreset(brdp=%x)\n", (int) brdp);
 2870: #endif
 2871: 
 2872: 	outb((brdp->iobase + ONB_ATCONFR), ONB_ATSTOP);
 2873: 	DELAY(10);
 2874: 	outb((brdp->iobase + ONB_ATCONFR), ONB_ATDISABLE);
 2875: 	for (i = 0; (i < 1000); i++)
 2876: 		DELAY(1000);
 2877: }
 2878: 
 2879: /*****************************************************************************/
 2880: 
 2881: /*
 2882:  *	The following routines act on ONboard EISA.
 2883:  */
 2884: 
 2885: static void stli_onbeinit(stlibrd_t *brdp)
 2886: {
 2887: 	unsigned long	memconf;
 2888: 	int		i;
 2889: 
 2890: #if STLDEBUG
 2891: 	printf("stli_onbeinit(brdp=%d)\n", (int) brdp);
 2892: #endif
 2893: 
 2894: 	outb((brdp->iobase + ONB_EIBRDENAB), 0x1);
 2895: 	outb((brdp->iobase + ONB_EICONFR), ONB_EISTOP);
 2896: 	DELAY(10);
 2897: 	outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
 2898: 	for (i = 0; (i < 1000); i++)
 2899: 		DELAY(1000);
 2900: 
 2901: 	memconf = (brdp->paddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
 2902: 	outb((brdp->iobase + ONB_EIMEMARL), memconf);
 2903: 	memconf = (brdp->paddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
 2904: 	outb((brdp->iobase + ONB_EIMEMARH), memconf);
 2905: 	outb(brdp->iobase, 0x1);
 2906: 	DELAY(1000);
 2907: }
 2908: 
 2909: /*****************************************************************************/
 2910: 
 2911: static void stli_onbeenable(stlibrd_t *brdp)
 2912: {	
 2913: #if STLDEBUG
 2914: 	printf("stli_onbeenable(brdp=%x)\n", (int) brdp);
 2915: #endif
 2916: 	outb((brdp->iobase + ONB_EICONFR), ONB_EIENABLE);
 2917: }
 2918: 
 2919: /*****************************************************************************/
 2920: 
 2921: static void stli_onbedisable(stlibrd_t *brdp)
 2922: {	
 2923: #if STLDEBUG
 2924: 	printf("stli_onbedisable(brdp=%x)\n", (int) brdp);
 2925: #endif
 2926: 	outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
 2927: }
 2928: 
 2929: /*****************************************************************************/
 2930: 
 2931: static char *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 2932: {	
 2933: 	void		*ptr;
 2934: 	unsigned char	val;
 2935: 
 2936: #if STLDEBUG
 2937: 	printf("stli_onbegetmemptr(brdp=%x,offset=%x,line=%d)\n", (int) brdp,
 2938: 		(int) offset, line);
 2939: #endif
 2940: 
 2941: 	if (offset > brdp->memsize) {
 2942: 		printf("STALLION: shared memory pointer=%x out of range at "
 2943: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 2944: 			__LINE__, brdp->brdnr);
 2945: 		ptr = 0;
 2946: 		val = 0;
 2947: 	} else {
 2948: 		ptr = (char *) brdp->vaddr + (offset % ONB_EIPAGESIZE);
 2949: 		if (offset < ONB_EIPAGESIZE)
 2950: 			val = ONB_EIENABLE;
 2951: 		else
 2952: 			val = ONB_EIENABLE | 0x40;
 2953: 	}
 2954: 	outb((brdp->iobase + ONB_EICONFR), val);
 2955: 	return(ptr);
 2956: }
 2957: 
 2958: /*****************************************************************************/
 2959: 
 2960: static void stli_onbereset(stlibrd_t *brdp)
 2961: {	
 2962: 	int	i;
 2963: 
 2964: #if STLDEBUG
 2965: 	printf("stli_onbereset(brdp=%x)\n", (int) brdp);
 2966: #endif
 2967: 
 2968: 	outb((brdp->iobase + ONB_EICONFR), ONB_EISTOP);
 2969: 	DELAY(10);
 2970: 	outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
 2971: 	for (i = 0; (i < 1000); i++)
 2972: 		DELAY(1000);
 2973: }
 2974: 
 2975: /*****************************************************************************/
 2976: 
 2977: /*
 2978:  *	The following routines act on Brumby boards.
 2979:  */
 2980: 
 2981: static void stli_bbyinit(stlibrd_t *brdp)
 2982: {
 2983: 	int	i;
 2984: 
 2985: #if STLDEBUG
 2986: 	printf("stli_bbyinit(brdp=%d)\n", (int) brdp);
 2987: #endif
 2988: 
 2989: 	outb((brdp->iobase + BBY_ATCONFR), BBY_ATSTOP);
 2990: 	DELAY(10);
 2991: 	outb((brdp->iobase + BBY_ATCONFR), 0);
 2992: 	for (i = 0; (i < 1000); i++)
 2993: 		DELAY(1000);
 2994: 	outb(brdp->iobase, 0x1);
 2995: 	DELAY(1000);
 2996: }
 2997: 
 2998: /*****************************************************************************/
 2999: 
 3000: static char *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 3001: {	
 3002: 	void		*ptr;
 3003: 	unsigned char	val;
 3004: 
 3005: #if STLDEBUG
 3006: 	printf("stli_bbygetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 3007: 		(int) offset);
 3008: #endif
 3009: 
 3010: 	if (offset > brdp->memsize) {
 3011: 		printf("STALLION: shared memory pointer=%x out of range at "
 3012: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 3013: 			__LINE__, brdp->brdnr);
 3014: 		ptr = 0;
 3015: 		val = 0;
 3016: 	} else {
 3017: 		ptr = (char *) brdp->vaddr + (offset % BBY_PAGESIZE);
 3018: 		val = (unsigned char) (offset / BBY_PAGESIZE);
 3019: 	}
 3020: 	outb((brdp->iobase + BBY_ATCONFR), val);
 3021: 	return(ptr);
 3022: }
 3023: 
 3024: /*****************************************************************************/
 3025: 
 3026: static void stli_bbyreset(stlibrd_t *brdp)
 3027: {	
 3028: 	int	i;
 3029: 
 3030: #if STLDEBUG
 3031: 	printf("stli_bbyreset(brdp=%x)\n", (int) brdp);
 3032: #endif
 3033: 
 3034: 	outb((brdp->iobase + BBY_ATCONFR), BBY_ATSTOP);
 3035: 	DELAY(10);
 3036: 	outb((brdp->iobase + BBY_ATCONFR), 0);
 3037: 	for (i = 0; (i < 1000); i++)
 3038: 		DELAY(1000);
 3039: }
 3040: 
 3041: /*****************************************************************************/
 3042: 
 3043: /*
 3044:  *	The following routines act on original old Stallion boards.
 3045:  */
 3046: 
 3047: static void stli_stalinit(stlibrd_t *brdp)
 3048: {
 3049: 	int	i;
 3050: 
 3051: #if STLDEBUG
 3052: 	printf("stli_stalinit(brdp=%d)\n", (int) brdp);
 3053: #endif
 3054: 
 3055: 	outb(brdp->iobase, 0x1);
 3056: 	for (i = 0; (i < 1000); i++)
 3057: 		DELAY(1000);
 3058: }
 3059: 
 3060: /*****************************************************************************/
 3061: 
 3062: static char *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
 3063: {	
 3064: 	void	*ptr;
 3065: 
 3066: #if STLDEBUG
 3067: 	printf("stli_stalgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
 3068: 		(int) offset);
 3069: #endif
 3070: 
 3071: 	if (offset > brdp->memsize) {
 3072: 		printf("STALLION: shared memory pointer=%x out of range at "
 3073: 			"line=%d(%d), brd=%d\n", (int) offset, line,
 3074: 			__LINE__, brdp->brdnr);
 3075: 		ptr = 0;
 3076: 	} else {
 3077: 		ptr = (char *) brdp->vaddr + (offset % STAL_PAGESIZE);
 3078: 	}
 3079: 	return(ptr);
 3080: }
 3081: 
 3082: /*****************************************************************************/
 3083: 
 3084: static void stli_stalreset(stlibrd_t *brdp)
 3085: {	
 3086: 	volatile unsigned long	*vecp;
 3087: 	int			i;
 3088: 
 3089: #if STLDEBUG
 3090: 	printf("stli_stalreset(brdp=%x)\n", (int) brdp);
 3091: #endif
 3092: 
 3093: 	vecp = (volatile unsigned long *) ((char *) brdp->vaddr + 0x30);
 3094: 	*vecp = 0xffff0000;
 3095: 	outb(brdp->iobase, 0);
 3096: 	for (i = 0; (i < 1000); i++)
 3097: 		DELAY(1000);
 3098: }
 3099: 
 3100: /*****************************************************************************/
 3101: 
 3102: /*
 3103:  *	Try to find an ECP board and initialize it. This handles only ECP
 3104:  *	board types.
 3105:  */
 3106: 
 3107: static int stli_initecp(stlibrd_t *brdp)
 3108: {
 3109: 	cdkecpsig_t	sig;
 3110: 	cdkecpsig_t	*sigsp;
 3111: 	unsigned int	status, nxtid;
 3112: 	int		panelnr;
 3113: 
 3114: #if STLDEBUG
 3115: 	printf("stli_initecp(brdp=%x)\n", (int) brdp);
 3116: #endif
 3117: 
 3118: /*
 3119:  *	Do a basic sanity check on the IO and memory addresses.
 3120:  */
 3121: 	if ((brdp->iobase == 0) || (brdp->paddr == 0))
 3122: 		return(EINVAL);
 3123: 
 3124: /*
 3125:  *	Based on the specific board type setup the common vars to access
 3126:  *	and enable shared memory. Set all board specific information now
 3127:  *	as well.
 3128:  */
 3129: 	switch (brdp->brdtype) {
 3130: 	case BRD_ECP:
 3131: 		brdp->memsize = ECP_MEMSIZE;
 3132: 		brdp->pagesize = ECP_ATPAGESIZE;
 3133: 		brdp->init = stli_ecpinit;
 3134: 		brdp->enable = stli_ecpenable;
 3135: 		brdp->reenable = stli_ecpenable;
 3136: 		brdp->disable = stli_ecpdisable;
 3137: 		brdp->getmemptr = stli_ecpgetmemptr;
 3138: 		brdp->intr = stli_ecpintr;
 3139: 		brdp->reset = stli_ecpreset;
 3140: 		break;
 3141: 
 3142: 	case BRD_ECPE:
 3143: 		brdp->memsize = ECP_MEMSIZE;
 3144: 		brdp->pagesize = ECP_EIPAGESIZE;
 3145: 		brdp->init = stli_ecpeiinit;
 3146: 		brdp->enable = stli_ecpeienable;
 3147: 		brdp->reenable = stli_ecpeienable;
 3148: 		brdp->disable = stli_ecpeidisable;
 3149: 		brdp->getmemptr = stli_ecpeigetmemptr;
 3150: 		brdp->intr = stli_ecpintr;
 3151: 		brdp->reset = stli_ecpeireset;
 3152: 		break;
 3153: 
 3154: 	case BRD_ECPMC:
 3155: 		brdp->memsize = ECP_MEMSIZE;
 3156: 		brdp->pagesize = ECP_MCPAGESIZE;
 3157: 		brdp->init = NULL;
 3158: 		brdp->enable = stli_ecpmcenable;
 3159: 		brdp->reenable = stli_ecpmcenable;
 3160: 		brdp->disable = stli_ecpmcdisable;
 3161: 		brdp->getmemptr = stli_ecpmcgetmemptr;
 3162: 		brdp->intr = stli_ecpintr;
 3163: 		brdp->reset = stli_ecpmcreset;
 3164: 		break;
 3165: 
 3166: 	default:
 3167: 		return(EINVAL);
 3168: 	}
 3169: 
 3170: /*
 3171:  *	The per-board operations structure is all setup, so now lets go
 3172:  *	and get the board operational. Firstly initialize board configuration
 3173:  *	registers.
 3174:  */
 3175: 	EBRDINIT(brdp);
 3176: 
 3177: /*
 3178:  *	Now that all specific code is set up, enable the shared memory and
 3179:  *	look for the a signature area that will tell us exactly what board
 3180:  *	this is, and what it is connected to it.
 3181:  */
 3182: 	EBRDENABLE(brdp);
 3183: 	sigsp = (cdkecpsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
 3184: 	bcopy(sigsp, &sig, sizeof(cdkecpsig_t));
 3185: 	EBRDDISABLE(brdp);
 3186: 
 3187: #if 0
 3188: 	printf("%s(%d): sig-> magic=%x rom=%x panel=%x,%x,%x,%x,%x,%x,%x,%x\n",
 3189: 		__file__, __LINE__, (int) sig.magic, sig.romver,
 3190: 		sig.panelid[0], (int) sig.panelid[1], (int) sig.panelid[2],
 3191: 		(int) sig.panelid[3], (int) sig.panelid[4],
 3192: 		(int) sig.panelid[5], (int) sig.panelid[6],
 3193: 		(int) sig.panelid[7]);
 3194: #endif
 3195: 
 3196: 	if (sig.magic != ECP_MAGIC)
 3197: 		return(ENXIO);
 3198: 
 3199: /*
 3200:  *	Scan through the signature looking at the panels connected to the
 3201:  *	board. Calculate the total number of ports as we go.
 3202:  */
 3203: 	for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
 3204: 		status = sig.panelid[nxtid];
 3205: 		if ((status & ECH_PNLIDMASK) != nxtid)
 3206: 			break;
 3207: 		brdp->panelids[panelnr] = status;
 3208: 		if (status & ECH_PNL16PORT) {
 3209: 			brdp->panels[panelnr] = 16;
 3210: 			brdp->nrports += 16;
 3211: 			nxtid += 2;
 3212: 		} else {
 3213: 			brdp->panels[panelnr] = 8;
 3214: 			brdp->nrports += 8;
 3215: 			nxtid++;
 3216: 		}
 3217: 		brdp->nrpanels++;
 3218: 	}
 3219: 
 3220: 	brdp->state |= BST_FOUND;
 3221: 	return(0);
 3222: }
 3223: 
 3224: /*****************************************************************************/
 3225: 
 3226: /*
 3227:  *	Try to find an ONboard, Brumby or Stallion board and initialize it.
 3228:  *	This handles only these board types.
 3229:  */
 3230: 
 3231: static int stli_initonb(stlibrd_t *brdp)
 3232: {
 3233: 	cdkonbsig_t	sig;
 3234: 	cdkonbsig_t	*sigsp;
 3235: 	int		i;
 3236: 
 3237: #if STLDEBUG
 3238: 	printf("stli_initonb(brdp=%x)\n", (int) brdp);
 3239: #endif
 3240: 
 3241: /*
 3242:  *	Do a basic sanity check on the IO and memory addresses.
 3243:  */
 3244: 	if ((brdp->iobase == 0) || (brdp->paddr == 0))
 3245: 		return(EINVAL);
 3246: 
 3247: /*
 3248:  *	Based on the specific board type setup the common vars to access
 3249:  *	and enable shared memory. Set all board specific information now
 3250:  *	as well.
 3251:  */
 3252: 	switch (brdp->brdtype) {
 3253: 	case BRD_ONBOARD:
 3254: 	case BRD_ONBOARD32:
 3255: 	case BRD_ONBOARD2:
 3256: 	case BRD_ONBOARD2_32:
 3257: 	case BRD_ONBOARDRS:
 3258: 		brdp->memsize = ONB_MEMSIZE;
 3259: 		brdp->pagesize = ONB_ATPAGESIZE;
 3260: 		brdp->init = stli_onbinit;
 3261: 		brdp->enable = stli_onbenable;
 3262: 		brdp->reenable = stli_onbenable;
 3263: 		brdp->disable = stli_onbdisable;
 3264: 		brdp->getmemptr = stli_onbgetmemptr;
 3265: 		brdp->intr = stli_ecpintr;
 3266: 		brdp->reset = stli_onbreset;
 3267: 		brdp->confbits = (brdp->paddr > 0x100000) ? ONB_HIMEMENAB : 0;
 3268: 		break;
 3269: 
 3270: 	case BRD_ONBOARDE:
 3271: 		brdp->memsize = ONB_EIMEMSIZE;
 3272: 		brdp->pagesize = ONB_EIPAGESIZE;
 3273: 		brdp->init = stli_onbeinit;
 3274: 		brdp->enable = stli_onbeenable;
 3275: 		brdp->reenable = stli_onbeenable;
 3276: 		brdp->disable = stli_onbedisable;
 3277: 		brdp->getmemptr = stli_onbegetmemptr;
 3278: 		brdp->intr = stli_ecpintr;
 3279: 		brdp->reset = stli_onbereset;
 3280: 		break;
 3281: 
 3282: 	case BRD_BRUMBY4:
 3283: 	case BRD_BRUMBY8:
 3284: 	case BRD_BRUMBY16:
 3285: 		brdp->memsize = BBY_MEMSIZE;
 3286: 		brdp->pagesize = BBY_PAGESIZE;
 3287: 		brdp->init = stli_bbyinit;
 3288: 		brdp->enable = NULL;
 3289: 		brdp->reenable = NULL;
 3290: 		brdp->disable = NULL;
 3291: 		brdp->getmemptr = stli_bbygetmemptr;
 3292: 		brdp->intr = stli_ecpintr;
 3293: 		brdp->reset = stli_bbyreset;
 3294: 		break;
 3295: 
 3296: 	case BRD_STALLION:
 3297: 		brdp->memsize = STAL_MEMSIZE;
 3298: 		brdp->pagesize = STAL_PAGESIZE;
 3299: 		brdp->init = stli_stalinit;
 3300: 		brdp->enable = NULL;
 3301: 		brdp->reenable = NULL;
 3302: 		brdp->disable = NULL;
 3303: 		brdp->getmemptr = stli_stalgetmemptr;
 3304: 		brdp->intr = stli_ecpintr;
 3305: 		brdp->reset = stli_stalreset;
 3306: 		break;
 3307: 
 3308: 	default:
 3309: 		return(EINVAL);
 3310: 	}
 3311: 
 3312: /*
 3313:  *	The per-board operations structure is all setup, so now lets go
 3314:  *	and get the board operational. Firstly initialize board configuration
 3315:  *	registers.
 3316:  */
 3317: 	EBRDINIT(brdp);
 3318: 
 3319: /*
 3320:  *	Now that all specific code is set up, enable the shared memory and
 3321:  *	look for the a signature area that will tell us exactly what board
 3322:  *	this is, and how many ports.
 3323:  */
 3324: 	EBRDENABLE(brdp);
 3325: 	sigsp = (cdkonbsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
 3326: 	bcopy(sigsp, &sig, sizeof(cdkonbsig_t));
 3327: 	EBRDDISABLE(brdp);
 3328: 
 3329: #if 0
 3330: 	printf("%s(%d): sig-> magic=%x:%x:%x:%x romver=%x amask=%x:%x:%x\n",
 3331: 		__file__, __LINE__, sig.magic0, sig.magic1, sig.magic2,
 3332: 		sig.magic3, sig.romver, sig.amask0, sig.amask1, sig.amask2);
 3333: #endif
 3334: 
 3335: 	if ((sig.magic0 != ONB_MAGIC0) || (sig.magic1 != ONB_MAGIC1) ||
 3336: 	    (sig.magic2 != ONB_MAGIC2) || (sig.magic3 != ONB_MAGIC3))
 3337: 		return(ENXIO);
 3338: 
 3339: /*
 3340:  *	Scan through the signature alive mask and calculate how many ports
 3341:  *	there are on this board.
 3342:  */
 3343: 	brdp->nrpanels = 1;
 3344: 	if (sig.amask1) {
 3345: 		brdp->nrports = 32;
 3346: 	} else {
 3347: 		for (i = 0; (i < 16); i++) {
 3348: 			if (((sig.amask0 << i) & 0x8000) == 0)
 3349: 				break;
 3350: 		}
 3351: 		brdp->nrports = i;
 3352: 	}
 3353: 	brdp->panels[0] = brdp->nrports;
 3354: 
 3355: 	brdp->state |= BST_FOUND;
 3356: 	return(0);
 3357: }
 3358: 
 3359: /*****************************************************************************/
 3360: 
 3361: /*
 3362:  *	Start up a running board. This routine is only called after the
 3363:  *	code has been down loaded to the board and is operational. It will
 3364:  *	read in the memory map, and get the show on the road...
 3365:  */
 3366: 
 3367: static int stli_startbrd(stlibrd_t *brdp)
 3368: {
 3369: 	volatile cdkhdr_t	*hdrp;
 3370: 	volatile cdkmem_t	*memp;
 3371: 	volatile cdkasy_t	*ap;
 3372: 	stliport_t		*portp;
 3373: 	int			portnr, nrdevs, i, rc, x;
 3374: 
 3375: #if STLDEBUG
 3376: 	printf("stli_startbrd(brdp=%x)\n", (int) brdp);
 3377: #endif
 3378: 
 3379: 	rc = 0;
 3380: 
 3381: 	x = spltty();
 3382: 	EBRDENABLE(brdp);
 3383: 	hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
 3384: 	nrdevs = hdrp->nrdevs;
 3385: 
 3386: #if 0
 3387: 	printf("%s(%d): CDK version %d.%d.%d --> nrdevs=%d memp=%x hostp=%x "
 3388: 		"slavep=%x\n", __file__, __LINE__, hdrp->ver_release,
 3389: 		hdrp->ver_modification, hdrp->ver_fix, nrdevs,
 3390: 		(int) hdrp->memp, (int) hdrp->hostp, (int) hdrp->slavep);
 3391: #endif
 3392: 
 3393: 	if (nrdevs < (brdp->nrports + 1)) {
 3394: 		printf("STALLION: slave failed to allocate memory for all "
 3395: 			"devices, devices=%d\n", nrdevs);
 3396: 		brdp->nrports = nrdevs - 1;
 3397: 	}
 3398: 	brdp->nrdevs = nrdevs;
 3399: 	brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
 3400: 	brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
 3401: 	brdp->bitsize = (nrdevs + 7) / 8;
 3402: 	memp = (volatile cdkmem_t *) (void *) (uintptr_t) hdrp->memp;
 3403: 	if (((uintptr_t) (void *) memp) > brdp->memsize) {
 3404: 		printf("STALLION: corrupted shared memory region?\n");
 3405: 		rc = EIO;
 3406: 		goto stli_donestartup;
 3407: 	}
 3408: 	memp = (volatile cdkmem_t *) EBRDGETMEMPTR(brdp,
 3409: 						   (uintptr_t) (void *) memp);
 3410: 	if (memp->dtype != TYP_ASYNCTRL) {
 3411: 		printf("STALLION: no slave control device found\n");
 3412: 		rc = EIO;
 3413: 		goto stli_donestartup;
 3414: 	}
 3415: 	memp++;
 3416: 
 3417: /*
 3418:  *	Cycle through memory allocation of each port. We are guaranteed to
 3419:  *	have all ports inside the first page of slave window, so no need to
 3420:  *	change pages while reading memory map.
 3421:  */
 3422: 	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
 3423: 		if (memp->dtype != TYP_ASYNC)
 3424: 			break;
 3425: 		portp = brdp->ports[portnr];
 3426: 		if (portp == (stliport_t *) NULL)
 3427: 			break;
 3428: 		portp->devnr = i;
 3429: 		portp->addr = memp->offset;
 3430: 		portp->reqidx = (unsigned char) (i * 8 / nrdevs);
 3431: 		portp->reqbit = (unsigned char) (0x1 << portp->reqidx);
 3432: 		portp->portidx = (unsigned char) (i / 8);
 3433: 		portp->portbit = (unsigned char) (0x1 << (i % 8));
 3434: 	}
 3435: 
 3436: 	hdrp->slavereq = 0xff;
 3437: 
 3438: /*
 3439:  *	For each port setup a local copy of the RX and TX buffer offsets
 3440:  *	and sizes. We do this separate from the above, because we need to
 3441:  *	move the shared memory page...
 3442:  */
 3443: 	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
 3444: 		portp = brdp->ports[portnr];
 3445: 		if (portp == (stliport_t *) NULL)
 3446: 			break;
 3447: 		if (portp->addr == 0)
 3448: 			break;
 3449: 		ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
 3450: 		if (ap != (volatile cdkasy_t *) NULL) {
 3451: 			portp->rxsize = ap->rxq.size;
 3452: 			portp->txsize = ap->txq.size;
 3453: 			portp->rxoffset = ap->rxq.offset;
 3454: 			portp->txoffset = ap->txq.offset;
 3455: 		}
 3456: 	}
 3457: 
 3458: stli_donestartup:
 3459: 	EBRDDISABLE(brdp);
 3460: 	splx(x);
 3461: 
 3462: 	if (rc == 0)
 3463: 		brdp->state |= BST_STARTED;
 3464: 
 3465: 	if (stli_doingtimeout == 0) {
 3466: 		timeout(stli_poll, 0, 1);
 3467: 		stli_doingtimeout++;
 3468: 	}
 3469: 
 3470: 	return(rc);
 3471: }
 3472: 
 3473: /*****************************************************************************/
 3474: 
 3475: /*
 3476:  *	Probe and initialize the specified board.
 3477:  */
 3478: 
 3479: static int stli_brdinit(stlibrd_t *brdp)
 3480: {
 3481: #if STLDEBUG
 3482: 	printf("stli_brdinit(brdp=%x)\n", (int) brdp);
 3483: #endif
 3484: 
 3485: 	stli_brds[brdp->brdnr] = brdp;
 3486: 
 3487: 	switch (brdp->brdtype) {
 3488: 	case BRD_ECP:
 3489: 	case BRD_ECPE:
 3490: 	case BRD_ECPMC:
 3491: 		stli_initecp(brdp);
 3492: 		break;
 3493: 	case BRD_ONBOARD:
 3494: 	case BRD_ONBOARDE:
 3495: 	case BRD_ONBOARD2:
 3496: 	case BRD_ONBOARD32:
 3497: 	case BRD_ONBOARD2_32:
 3498: 	case BRD_ONBOARDRS:
 3499: 	case BRD_BRUMBY4:
 3500: 	case BRD_BRUMBY8:
 3501: 	case BRD_BRUMBY16:
 3502: 	case BRD_STALLION:
 3503: 		stli_initonb(brdp);
 3504: 		break;
 3505: 	case BRD_EASYIO:
 3506: 	case BRD_ECH:
 3507: 	case BRD_ECHMC:
 3508: 	case BRD_ECHPCI:
 3509: 		printf("STALLION: %s board type not supported in this driver\n",
 3510: 			stli_brdnames[brdp->brdtype]);
 3511: 		return(ENODEV);
 3512: 	default:
 3513: 		printf("STALLION: unit=%d is unknown board type=%d\n",
 3514: 			brdp->brdnr, brdp->brdtype);
 3515: 		return(ENODEV);
 3516: 	}
 3517: 
 3518: 	return(0);
 3519: }
 3520: 
 3521: /*****************************************************************************/
 3522: 
 3523: /*
 3524:  *	Finish off the remaining initialization for a board.
 3525:  */
 3526: 
 3527: static int stli_brdattach(stlibrd_t *brdp)
 3528: {
 3529: #if STLDEBUG
 3530: 	printf("stli_brdattach(brdp=%x)\n", (int) brdp);
 3531: #endif
 3532: 
 3533: #if 0
 3534: 	if ((brdp->state & BST_FOUND) == 0) {
 3535: 		printf("STALLION: %s board not found, unit=%d io=%x mem=%x\n",
 3536: 			stli_brdnames[brdp->brdtype], brdp->brdnr,
 3537: 			brdp->iobase, (int) brdp->paddr);
 3538: 		return(ENXIO);
 3539: 	}
 3540: #endif
 3541: 
 3542: 	stli_initports(brdp);
 3543: 	printf("stli%d: %s (driver version %s), unit=%d nrpanels=%d "
 3544: 		"nrports=%d\n", brdp->unitid, stli_brdnames[brdp->brdtype],
 3545: 		stli_drvversion, brdp->brdnr, brdp->nrpanels, brdp->nrports);
 3546: 	return(0);
 3547: }
 3548: 
 3549: /*****************************************************************************/
 3550: 
 3551: /*****************************************************************************/
 3552: 
 3553: /*
 3554:  *	Return the board stats structure to user app.
 3555:  */
 3556: 
 3557: static int stli_getbrdstats(caddr_t data)
 3558: {
 3559: 	stlibrd_t	*brdp;
 3560: 	int		i;
 3561: 
 3562: #if STLDEBUG
 3563: 	printf("stli_getbrdstats(data=%p)\n", (void *) data);
 3564: #endif
 3565: 
 3566: 	stli_brdstats = *((combrd_t *) data);
 3567: 	if (stli_brdstats.brd >= STL_MAXBRDS)
 3568: 		return(ENODEV);
 3569: 	brdp = stli_brds[stli_brdstats.brd];
 3570: 	if (brdp == (stlibrd_t *) NULL)
 3571: 		return(ENODEV);
 3572: 
 3573: 	bzero(&stli_brdstats, sizeof(combrd_t));
 3574: 	stli_brdstats.brd = brdp->brdnr;
 3575: 	stli_brdstats.type = brdp->brdtype;
 3576: 	stli_brdstats.hwid = 0;
 3577: 	stli_brdstats.state = brdp->state;
 3578: 	stli_brdstats.ioaddr = brdp->iobase;
 3579: 	stli_brdstats.memaddr = brdp->paddr;
 3580: 	stli_brdstats.nrpanels = brdp->nrpanels;
 3581: 	stli_brdstats.nrports = brdp->nrports;
 3582: 	for (i = 0; (i < brdp->nrpanels); i++) {
 3583: 		stli_brdstats.panels[i].panel = i;
 3584: 		stli_brdstats.panels[i].hwid = brdp->panelids[i];
 3585: 		stli_brdstats.panels[i].nrports = brdp->panels[i];
 3586: 	}
 3587: 
 3588: 	*((combrd_t *) data) = stli_brdstats;
 3589: 	return(0);
 3590: }
 3591: 
 3592: /*****************************************************************************/
 3593: 
 3594: /*
 3595:  *	Resolve the referenced port number into a port struct pointer.
 3596:  */
 3597: 
 3598: static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
 3599: {
 3600: 	stlibrd_t	*brdp;
 3601: 	int		i;
 3602: 
 3603: 	if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
 3604: 		return((stliport_t *) NULL);
 3605: 	brdp = stli_brds[brdnr];
 3606: 	if (brdp == (stlibrd_t *) NULL)
 3607: 		return((stliport_t *) NULL);
 3608: 	for (i = 0; (i < panelnr); i++)
 3609: 		portnr += brdp->panels[i];
 3610: 	if ((portnr < 0) || (portnr >= brdp->nrports))
 3611: 		return((stliport_t *) NULL);
 3612: 	return(brdp->ports[portnr]);
 3613: }
 3614: 
 3615: /*****************************************************************************/
 3616: 
 3617: /*
 3618:  *	Return the port stats structure to user app. A NULL port struct
 3619:  *	pointer passed in means that we need to find out from the app
 3620:  *	what port to get stats for (used through board control device).
 3621:  */
 3622: 
 3623: static int stli_getportstats(stliport_t *portp, caddr_t data)
 3624: {
 3625: 	stlibrd_t	*brdp;
 3626: 	int		rc;
 3627: 
 3628: 	if (portp == (stliport_t *) NULL) {
 3629: 		stli_comstats = *((comstats_t *) data);
 3630: 		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
 3631: 			stli_comstats.port);
 3632: 		if (portp == (stliport_t *) NULL)
 3633: 			return(ENODEV);
 3634: 	}
 3635: 
 3636: 	brdp = stli_brds[portp->brdnr];
 3637: 	if (brdp == (stlibrd_t *) NULL)
 3638: 		return(ENODEV);
 3639: 
 3640: 	if (brdp->state & BST_STARTED) {
 3641: 		if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, &stli_cdkstats,
 3642: 		    sizeof(asystats_t), 1)) < 0)
 3643: 			return(rc);
 3644: 	} else {
 3645: 		bzero(&stli_cdkstats, sizeof(asystats_t));
 3646: 	}
 3647: 
 3648: 	stli_comstats.brd = portp->brdnr;
 3649: 	stli_comstats.panel = portp->panelnr;
 3650: 	stli_comstats.port = portp->portnr;
 3651: 	stli_comstats.state = portp->state;
 3652: 	/*stli_comstats.flags = portp->flags;*/
 3653: 	stli_comstats.ttystate = portp->tty.t_state;
 3654: 	stli_comstats.cflags = portp->tty.t_cflag;
 3655: 	stli_comstats.iflags = portp->tty.t_iflag;
 3656: 	stli_comstats.oflags = portp->tty.t_oflag;
 3657: 	stli_comstats.lflags = portp->tty.t_lflag;
 3658: 
 3659: 	stli_comstats.txtotal = stli_cdkstats.txchars;
 3660: 	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
 3661: 	stli_comstats.txbuffered = stli_cdkstats.txringq;
 3662: 	stli_comstats.rxbuffered = stli_cdkstats.rxringq;
 3663: 	stli_comstats.rxoverrun = stli_cdkstats.overruns;
 3664: 	stli_comstats.rxparity = stli_cdkstats.parity;
 3665: 	stli_comstats.rxframing = stli_cdkstats.framing;
 3666: 	stli_comstats.rxlost = stli_cdkstats.ringover + portp->rxlost;
 3667: 	stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
 3668: 	stli_comstats.txbreaks = stli_cdkstats.txbreaks;
 3669: 	stli_comstats.txxon = stli_cdkstats.txstart;
 3670: 	stli_comstats.txxoff = stli_cdkstats.txstop;
 3671: 	stli_comstats.rxxon = stli_cdkstats.rxstart;
 3672: 	stli_comstats.rxxoff = stli_cdkstats.rxstop;
 3673: 	stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
 3674: 	stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
 3675: 	stli_comstats.modem = stli_cdkstats.dcdcnt;
 3676: 	stli_comstats.hwid = stli_cdkstats.hwid;
 3677: 	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
 3678: 
 3679: 	*((comstats_t *) data) = stli_comstats;;
 3680: 	return(0);
 3681: }
 3682: 
 3683: /*****************************************************************************/
 3684: 
 3685: /*
 3686:  *	Clear the port stats structure. We also return it zeroed out...
 3687:  */
 3688: 
 3689: static int stli_clrportstats(stliport_t *portp, caddr_t data)
 3690: {
 3691: 	stlibrd_t	*brdp;
 3692: 	int		rc;
 3693: 
 3694: 	if (portp == (stliport_t *) NULL) {
 3695: 		stli_comstats = *((comstats_t *) data);
 3696: 		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
 3697: 			stli_comstats.port);
 3698: 		if (portp == (stliport_t *) NULL)
 3699: 			return(ENODEV);
 3700: 	}
 3701: 
 3702: 	brdp = stli_brds[portp->brdnr];
 3703: 	if (brdp == (stlibrd_t *) NULL)
 3704: 		return(ENODEV);
 3705: 
 3706: 	if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, 0, 0, 0)) < 0)
 3707: 		return(rc);
 3708: 
 3709: 	portp->rxlost = 0;
 3710: 	bzero(&stli_comstats, sizeof(comstats_t));
 3711: 	stli_comstats.brd = portp->brdnr;
 3712: 	stli_comstats.panel = portp->panelnr;
 3713: 	stli_comstats.port = portp->portnr;
 3714: 
 3715: 	*((comstats_t *) data) = stli_comstats;;
 3716: 	return(0);
 3717: }
 3718: 
 3719: /*****************************************************************************/
 3720: 
 3721: /*
 3722:  *	Code to handle an "staliomem" read and write operations. This device
 3723:  *	is the contents of the board shared memory. It is used for down
 3724:  *	loading the slave image (and debugging :-)
 3725:  */
 3726: 
 3727: STATIC int stli_memrw(dev_t dev, struct uio *uiop, int flag)
 3728: {
 3729: 	stlibrd_t	*brdp;
 3730: 	void		*memptr;
 3731: 	int		brdnr, size, n, error, x;
 3732: 
 3733: #if STLDEBUG
 3734: 	printf("stli_memrw(dev=%x,uiop=%x,flag=%x)\n", (int) dev,
 3735: 		(int) uiop, flag);
 3736: #endif
 3737: 
 3738: 	brdnr = minor(dev) & 0x7;
 3739: 	brdp = stli_brds[brdnr];
 3740: 	if (brdp == (stlibrd_t *) NULL)
 3741: 		return(ENODEV);
 3742: 	if (brdp->state == 0)
 3743: 		return(ENODEV);
 3744: 
 3745: 	if (uiop->uio_offset >= brdp->memsize)
 3746: 		return(0);
 3747: 
 3748: 	error = 0;
 3749: 	size = brdp->memsize - uiop->uio_offset;
 3750: 
 3751: 	x = spltty();
 3752: 	EBRDENABLE(brdp);
 3753: 	while (size > 0) {
 3754: 		memptr = (void *) EBRDGETMEMPTR(brdp, uiop->uio_offset);
 3755: 		n = MIN(size, (brdp->pagesize -
 3756: 			(((unsigned long) uiop->uio_offset) % brdp->pagesize)));
 3757: 		error = uiomove(memptr, n, uiop);
 3758: 		if ((uiop->uio_resid == 0) || error)
 3759: 			break;
 3760: 	}
 3761: 	EBRDDISABLE(brdp);
 3762: 	splx(x);
 3763: 
 3764: 	return(error);
 3765: }
 3766: 
 3767: /*****************************************************************************/
 3768: 
 3769: /*
 3770:  *	The "staliomem" device is also required to do some special operations
 3771:  *	on the board. We need to be able to send an interrupt to the board,
 3772:  *	reset it, and start/stop it.
 3773:  */
 3774: 
 3775: static int stli_memioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
 3776: 			 struct thread *td)
 3777: {
 3778: 	stlibrd_t	*brdp;
 3779: 	int		brdnr, rc;
 3780: 
 3781: #if STLDEBUG
 3782: 	printf("stli_memioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n",
 3783: 		devtoname(dev), cmd, (void *) data, flag);
 3784: #endif
 3785: 
 3786: /*
 3787:  *	Handle board independant ioctls first.
 3788:  */
 3789: 	switch (cmd) {
 3790: 	case COM_GETPORTSTATS:
 3791: 		return(stli_getportstats((stliport_t *) NULL, data));
 3792: 		break;
 3793: 	case COM_CLRPORTSTATS:
 3794: 		return(stli_clrportstats((stliport_t *) NULL, data));
 3795: 		break;
 3796: 	case COM_GETBRDSTATS:
 3797: 		return(stli_getbrdstats(data));
 3798: 		break;
 3799: 	default:
 3800: 		break;
 3801: 	}
 3802: 
 3803: /*
 3804:  *	Handle board dependant ioctls now.
 3805:  */
 3806: 	brdnr = minor(dev) & 0x7;
 3807: 	brdp = stli_brds[brdnr];
 3808: 	if (brdp == (stlibrd_t *) NULL)
 3809: 		return(ENODEV);
 3810: 	if (brdp->state == 0)
 3811: 		return(ENODEV);
 3812: 
 3813: 	rc = 0;
 3814: 
 3815: 	switch (cmd) {
 3816: 	case STL_BINTR:
 3817: 		EBRDINTR(brdp);
 3818: 		break;
 3819: 	case STL_BSTART:
 3820: 		rc = stli_startbrd(brdp);
 3821: 		break;
 3822: 	case STL_BSTOP:
 3823: 		brdp->state &= ~BST_STARTED;
 3824: 		break;
 3825: 	case STL_BRESET:
 3826: 		brdp->state &= ~BST_STARTED;
 3827: 		EBRDRESET(brdp);
 3828: 		if (stli_shared == 0) {
 3829: 			if (brdp->reenable != NULL)
 3830: 				(* brdp->reenable)(brdp);
 3831: 		}
 3832: 		break;
 3833: 	case COM_GETPORTSTATS:
 3834: 		rc = stli_getportstats((stliport_t *) NULL, data);
 3835: 		break;
 3836: 	case COM_CLRPORTSTATS:
 3837: 		rc = stli_clrportstats((stliport_t *) NULL, data);
 3838: 		break;
 3839: 	case COM_GETBRDSTATS:
 3840: 		rc = stli_getbrdstats(data);
 3841: 		break;
 3842: 	default:
 3843: 		rc = ENOTTY;
 3844: 		break;
 3845: 	}
 3846: 
 3847: 	return(rc);
 3848: }
 3849: 
 3850: /*****************************************************************************/