summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2004-03-14 06:48:36 +0000
committerimp <imp@FreeBSD.org>2004-03-14 06:48:36 +0000
commit9fca0846583dcbd31ff4cbbb64c140193283b235 (patch)
treeb97707caa5a9ad3bc88f001e07e0bb885beb518a
parentf12ed405d13a8799736ce8347eb2442e49fa7fd8 (diff)
downloadFreeBSD-src-9fca0846583dcbd31ff4cbbb64c140193283b235.zip
FreeBSD-src-9fca0846583dcbd31ff4cbbb64c140193283b235.tar.gz
stl and stli use the old COMPAT_ISA api. slt also uses the really old
COMPAT_PCI api. This API is going away, so this driver is going away also. If users are interested in updating this, please contact the author since he has some preliminary work to move this to newer APIs.
-rw-r--r--sys/conf/files.i3862
-rw-r--r--sys/conf/files.pc982
-rw-r--r--sys/i386/conf/NOTES27
-rw-r--r--sys/i386/include/cdk.h495
-rw-r--r--sys/i386/isa/README.stl536
-rw-r--r--sys/i386/isa/istallion.c3850
-rw-r--r--sys/i386/isa/stallion.c3072
7 files changed, 0 insertions, 7984 deletions
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 22406ea..89b317a 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -272,7 +272,6 @@ i386/isa/isa.c optional isa
i386/isa/isa_compat.c optional isa compat_oldisa \
warning "Old ISA driver compatibility shims present."
i386/isa/isa_dma.c optional isa
-i386/isa/istallion.c optional stli nowerror
i386/isa/mse.c optional mse
i386/isa/nmi.c standard
i386/isa/npx.c optional npx
@@ -288,7 +287,6 @@ i386/isa/prof_machdep.c optional profiling-routine
i386/isa/spic.c optional spic
i386/isa/spigot.c count spigot
i386/isa/spkr.c optional speaker
-i386/isa/stallion.c optional stl nowerror
i386/isa/vesa.c optional vga vesa
i386/linux/imgact_linux.c optional compat_linux
i386/linux/linux_dummy.c optional compat_linux
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 981ee6d..d0a3f66 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -205,12 +205,10 @@ i386/isa/elink.c optional ie
i386/isa/isa.c optional isa
i386/isa/isa_compat.c optional isa compat_oldisa \
warning "Old ISA driver compatibility shims present."
-i386/isa/istallion.c optional stli nowerror
i386/isa/npx.c optional npx
i386/isa/pmtimer.c optional pmtimer
i386/isa/prof_machdep.c optional profiling-routine
i386/isa/spkr.c optional speaker
-i386/isa/stallion.c optional stl nowerror
i386/linux/imgact_linux.c optional compat_linux
i386/linux/linux_dummy.c optional compat_linux
i386/linux/linux_locore.s optional compat_linux \
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 4be524a..f6fe2d4 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -637,8 +637,6 @@ options SAFE_RNDTEST # enable rndtest support
# digi: Digiboard driver
# gsc: Genius GS-4500 hand scanner.
# spic: Sony Programmable I/O controller (VAIO notebooks)
-# stl: Stallion EasyIO and EasyConnection 8/32 (cd1400 based)
-# stli: Stallion EasyConnection 8/64, ONboard, Brumby (intelligent)
# Notes on APM
# The flags takes the following meaning for apm0:
@@ -673,21 +671,6 @@ options SAFE_RNDTEST # enable rndtest support
# is the only thing truly supported, but apparently a fair percentage
# of the Vaio extra features are controlled by this device.
-# Notes on the Stallion stl and stli drivers:
-# See src/i386/isa/README.stl for complete instructions.
-# This is version 0.0.5alpha, unsupported by Stallion.
-# The stl driver has a secondary IO port hard coded at 0x280. You need
-# to change src/i386/isa/stallion.c if you reconfigure this on the boards.
-# The "flags" and "msize" settings on the stli driver depend on the board:
-# EasyConnection 8/64 ISA: flags 23 msize 0x1000
-# EasyConnection 8/64 EISA: flags 24 msize 0x10000
-# EasyConnection 8/64 MCA: flags 25 msize 0x1000
-# ONboard ISA: flags 4 msize 0x10000
-# ONboard EISA: flags 7 msize 0x10000
-# ONboard MCA: flags 3 msize 0x10000
-# Brumby: flags 2 msize 0x4000
-# Stallion: flags 1 msize 0x10000
-
device spigot 1
hint.spigot.0.at="isa"
hint.spigot.0.port="0xad6"
@@ -721,16 +704,6 @@ hint.gsc.0.drq="3"
device spic
hint.spic.0.at="isa"
hint.spic.0.port="0x10a0"
-device stl
-hint.stl.0.at="isa"
-hint.stl.0.port="0x2a0"
-hint.stl.0.irq="10"
-device stli
-hint.stli.0.at="isa"
-hint.stli.0.port="0x2a0"
-hint.stli.0.maddr="0xcc000"
-hint.stli.0.flags="23"
-hint.stli.0.msize="0x1000"
# HOT1 Xilinx 6200 card (http://www.vcc.com/)
device xrpu
diff --git a/sys/i386/include/cdk.h b/sys/i386/include/cdk.h
deleted file mode 100644
index 8080f2b..0000000
--- a/sys/i386/include/cdk.h
+++ /dev/null
@@ -1,495 +0,0 @@
-/*****************************************************************************/
-
-/*
- * cdk.h -- CDK interface definitions.
- *
- * Copyright (c) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Greg Ungerer.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD$
- */
-
-/*****************************************************************************/
-#ifndef _CDK_H
-#define _CDK_H
-/*****************************************************************************/
-
-#pragma pack(2)
-
-/*
- * The following set of definitions is used to communicate with the
- * shared memory interface of the Stallion intelligent multiport serial
- * boards. The definitions in this file are taken directly from the
- * document titled "Generic Stackable Interface, Downloader and
- * Communications Development Kit".
- */
-
-/*
- * Define the set of importrant shared memory addresses. These are
- * required to intialize the board and get things started. All of these
- * addresses are relative to the start of the shared memory.
- */
-#define CDK_SIGADDR 0x200
-#define CDK_FEATADDR 0x280
-#define CDK_CDKADDR 0x300
-#define CDK_RDYADDR 0x262
-
-#define CDK_ALIVEMARKER 13
-
-/*
- * On hardware power up the ROMs located on the EasyConnection 8/64 will
- * fill out the following signature information into shared memory. This
- * way the host system can quickly determine that the board is present
- * and is operational.
- */
-typedef struct cdkecpsig {
- unsigned long magic;
- unsigned short romver;
- unsigned short cputype;
- unsigned char panelid[8];
-} cdkecpsig_t;
-
-#define ECP_MAGIC 0x21504345
-
-/*
- * On hardware power up the ROMs located on the ONboard, Stallion and
- * Brumbys will fill out the following signature information into shared
- * memory. This way the host system can quickly determine that the board
- * is present and is operational.
- */
-typedef struct cdkonbsig {
- unsigned short magic0;
- unsigned short magic1;
- unsigned short magic2;
- unsigned short magic3;
- unsigned short romver;
- unsigned short memoff;
- unsigned short memseg;
- unsigned short amask0;
- unsigned short pic;
- unsigned short status;
- unsigned short btype;
- unsigned short clkticks;
- unsigned short clkspeed;
- unsigned short amask1;
- unsigned short amask2;
-} cdkonbsig_t;
-
-#define ONB_MAGIC0 0xf2a7
-#define ONB_MAGIC1 0xa149
-#define ONB_MAGIC2 0x6352
-#define ONB_MAGIC3 0xf121
-
-/*
- * Define the feature area structure. The feature area is the set of
- * startup parameters used by the slave image when it starts executing.
- * They allow for the specification of buffer sizes, debug trace, etc.
- */
-typedef struct cdkfeature {
- unsigned long debug;
- unsigned long banner;
- unsigned long etype;
- unsigned long nrdevs;
- unsigned long brdspec;
- unsigned long txrqsize;
- unsigned long rxrqsize;
- unsigned long flags;
-} cdkfeature_t;
-
-#define ETYP_DDK 0
-#define ETYP_CDK 1
-
-/*
- * Define the CDK header structure. This is the info that the slave
- * environment sets up after it has been downloaded and started. It
- * essentially provides a memory map for the shared memory interface.
- */
-typedef struct cdkhdr {
- unsigned short command;
- unsigned short status;
- unsigned short port;
- unsigned short mode;
- unsigned long cmd_buf[14];
- unsigned short alive_cnt;
- unsigned short intrpt_mode;
- unsigned char intrpt_id[8];
- unsigned char ver_release;
- unsigned char ver_modification;
- unsigned char ver_fix;
- unsigned char deadman_restart;
- unsigned short deadman;
- unsigned short nrdevs;
- unsigned long memp;
- unsigned long hostp;
- unsigned long slavep;
- unsigned char hostreq;
- unsigned char slavereq;
- unsigned char cmd_reserved[30];
-} cdkhdr_t;
-
-#define MODE_DDK 0
-#define MODE_CDK 1
-
-#define IMD_INTR 0x0
-#define IMD_PPINTR 0x1
-#define IMD_POLL 0xff
-
-/*
- * Define the memory mapping structure. This structure is pointed to by
- * the memp field in the stlcdkhdr struct. As many as these structures
- * as required are layed out in shared memory to define how the rest of
- * shared memory is divided up. There will be one for each port.
- */
-typedef struct cdkmem {
- unsigned short dtype;
- unsigned long offset;
-} cdkmem_t;
-
-#define TYP_UNDEFINED 0x0
-#define TYP_ASYNCTRL 0x1
-#define TYP_ASYNC 0x20
-#define TYP_PARALLEL 0x40
-#define TYP_SYNCX21 0x60
-
-/*****************************************************************************/
-
-/*
- * Following is a set of defines and structures used to actually deal
- * with the serial ports on the board. Firstly is the set of commands
- * that can be applied to ports.
- */
-#define ASYCMD (((unsigned long) 'a') << 8)
-
-#define A_NULL (ASYCMD | 0)
-#define A_FLUSH (ASYCMD | 1)
-#define A_BREAK (ASYCMD | 2)
-#define A_GETPORT (ASYCMD | 3)
-#define A_SETPORT (ASYCMD | 4)
-#define A_SETPORTF (ASYCMD | 5)
-#define A_SETPORTFTX (ASYCMD | 6)
-#define A_SETPORTFRX (ASYCMD | 7)
-#define A_GETSIGNALS (ASYCMD | 8)
-#define A_SETSIGNALS (ASYCMD | 9)
-#define A_SETSIGNALSF (ASYCMD | 10)
-#define A_SETSIGNALSFTX (ASYCMD | 11)
-#define A_SETSIGNALSFRX (ASYCMD | 12)
-#define A_GETNOTIFY (ASYCMD | 13)
-#define A_SETNOTIFY (ASYCMD | 14)
-#define A_NOTIFY (ASYCMD | 15)
-#define A_PORTCTRL (ASYCMD | 16)
-#define A_GETSTATS (ASYCMD | 17)
-#define A_RQSTATE (ASYCMD | 18)
-#define A_FLOWSTATE (ASYCMD | 19)
-#define A_CLEARSTATS (ASYCMD | 20)
-
-/*
- * Define those arguments used for simple commands.
- */
-#define FLUSHRX 0x1
-#define FLUSHTX 0x2
-
-#define BREAKON -1
-#define BREAKOFF -2
-
-/*
- * Define the port setting structure, and all those defines that go along
- * with it. Basically this structure defines the charcateristics of this
- * port: baud rate, chars, parity, input/output char cooking etc.
- */
-typedef struct asyport {
- unsigned long baudout;
- unsigned long baudin;
- unsigned long iflag;
- unsigned long oflag;
- unsigned long lflag;
- unsigned long pflag;
- unsigned long flow;
- unsigned long spare1;
- unsigned short vtime;
- unsigned short vmin;
- unsigned short txlo;
- unsigned short txhi;
- unsigned short rxlo;
- unsigned short rxhi;
- unsigned short rxhog;
- unsigned short spare2;
- unsigned char csize;
- unsigned char stopbs;
- unsigned char parity;
- unsigned char stopin;
- unsigned char startin;
- unsigned char stopout;
- unsigned char startout;
- unsigned char parmark;
- unsigned char brkmark;
- unsigned char cc[11];
-} asyport_t;
-
-#define PT_STOP1 0x0
-#define PT_STOP15 0x1
-#define PT_STOP2 0x2
-
-#define PT_NOPARITY 0x0
-#define PT_ODDPARITY 0x1
-#define PT_EVENPARITY 0x2
-#define PT_MARKPARITY 0x3
-#define PT_SPACEPARITY 0x4
-
-#define F_NONE 0x0
-#define F_IXON 0x1
-#define F_IXOFF 0x2
-#define F_IXANY 0x4
-#define F_IOXANY 0x8
-#define F_RTSFLOW 0x10
-#define F_CTSFLOW 0x20
-#define F_DTRFLOW 0x40
-#define F_DCDFLOW 0x80
-#define F_DSROFLOW 0x100
-#define F_DSRIFLOW 0x200
-
-#define FI_NORX 0x1
-#define FI_RAW 0x2
-#define FI_ISTRIP 0x4
-#define FI_UCLC 0x8
-#define FI_INLCR 0x10
-#define FI_ICRNL 0x20
-#define FI_IGNCR 0x40
-#define FI_IGNBREAK 0x80
-#define FI_DSCRDBREAK 0x100
-#define FI_1MARKBREAK 0x200
-#define FI_2MARKBREAK 0x400
-#define FI_XCHNGBREAK 0x800
-#define FI_IGNRXERRS 0x1000
-#define FI_DSCDRXERRS 0x2000
-#define FI_1MARKRXERRS 0x4000
-#define FI_2MARKRXERRS 0x8000
-#define FI_XCHNGRXERRS 0x10000
-#define FI_DSCRDNULL 0x20000
-
-#define FO_OLCUC 0x1
-#define FO_ONLCR 0x2
-#define FO_OOCRNL 0x4
-#define FO_ONOCR 0x8
-#define FO_ONLRET 0x10
-#define FO_ONL 0x20
-#define FO_OBS 0x40
-#define FO_OVT 0x80
-#define FO_OFF 0x100
-#define FO_OTAB1 0x200
-#define FO_OTAB2 0x400
-#define FO_OTAB3 0x800
-#define FO_OCR1 0x1000
-#define FO_OCR2 0x2000
-#define FO_OCR3 0x4000
-#define FO_OFILL 0x8000
-#define FO_ODELL 0x10000
-
-#define P_RTSLOCK 0x1
-#define P_CTSLOCK 0x2
-#define P_MAPRTS 0x4
-#define P_MAPCTS 0x8
-#define P_LOOPBACK 0x10
-#define P_DTRFOLLOW 0x20
-#define P_FAKEDCD 0x40
-
-/*
- * Define a structure to communicate serial port signal and data state
- * information.
- */
-typedef struct asysigs {
- unsigned long data;
- unsigned long signal;
- unsigned long sigvalue;
-} asysigs_t;
-
-#define DT_TXBUSY 0x1
-#define DT_TXEMPTY 0x2
-#define DT_TXLOW 0x4
-#define DT_TXHIGH 0x8
-#define DT_TXFULL 0x10
-#define DT_TXHOG 0x20
-#define DT_TXFLOWED 0x40
-#define DT_TXBREAK 0x80
-
-#define DT_RXBUSY 0x100
-#define DT_RXEMPTY 0x200
-#define DT_RXLOW 0x400
-#define DT_RXHIGH 0x800
-#define DT_RXFULL 0x1000
-#define DT_RXHOG 0x2000
-#define DT_RXFLOWED 0x4000
-#define DT_RXBREAK 0x8000
-
-#define SG_DTR 0x1
-#define SG_DCD 0x2
-#define SG_RTS 0x4
-#define SG_CTS 0x8
-#define SG_DSR 0x10
-#define SG_RI 0x20
-
-/*
- * Define the notification setting structure. This is used to tell the
- * port what events we want to be informed about. Fields here use the
- * same defines as for the asysigs structure above.
- */
-typedef struct asynotify {
- unsigned long ctrl;
- unsigned long data;
- unsigned long signal;
- unsigned long sigvalue;
-} asynotify_t;
-
-/*
- * Define the port control structure. It is used to do fine grain
- * control operations on the port.
- */
-typedef struct {
- unsigned long rxctrl;
- unsigned long txctrl;
- char rximdch;
- char tximdch;
- char spare1;
- char spare2;
-} asyctrl_t;
-
-#define CT_ENABLE 0x1
-#define CT_DISABLE 0x2
-#define CT_STOP 0x4
-#define CT_START 0x8
-#define CT_STARTFLOW 0x10
-#define CT_STOPFLOW 0x20
-#define CT_SENDCHR 0x40
-
-/*
- * Define the stats structure kept for each port. This is a useful set
- * of data collected for each port on the slave. The A_GETSTATS command
- * is used to retrive this data from the slave.
- */
-typedef struct asystats {
- unsigned long opens;
- unsigned long txchars;
- unsigned long rxchars;
- unsigned long txringq;
- unsigned long rxringq;
- unsigned long txmsgs;
- unsigned long rxmsgs;
- unsigned long txflushes;
- unsigned long rxflushes;
- unsigned long overruns;
- unsigned long framing;
- unsigned long parity;
- unsigned long ringover;
- unsigned long lost;
- unsigned long rxstart;
- unsigned long rxstop;
- unsigned long txstart;
- unsigned long txstop;
- unsigned long dcdcnt;
- unsigned long dtrcnt;
- unsigned long ctscnt;
- unsigned long rtscnt;
- unsigned long dsrcnt;
- unsigned long ricnt;
- unsigned long txbreaks;
- unsigned long rxbreaks;
- unsigned long signals;
- unsigned long state;
- unsigned long hwid;
-} asystats_t;
-
-/*****************************************************************************/
-
-/*
- * All command and control communication with a device on the slave is
- * via a control block in shared memory. Each device has its own control
- * block, defined by the following structure. The control block allows
- * the host to open, close and control the device on the slave.
- */
-typedef struct cdkctrl {
- unsigned char open;
- unsigned char close;
- unsigned long openarg;
- unsigned long closearg;
- unsigned long cmd;
- unsigned long status;
- unsigned long args[32];
-} cdkctrl_t;
-
-/*
- * Each device on the slave passes data to and from the host via a ring
- * queue in shared memory. Define a ring queue structure to hold the
- * vital information about each ring queue. Two ring queues will be
- * allocated for each port, one for reveice data and one for transmit
- * data.
- */
-typedef struct cdkasyrq {
- unsigned long offset;
- unsigned short size;
- unsigned short head;
- unsigned short tail;
-} cdkasyrq_t;
-
-/*
- * Each asynchronous port is defined in shared memory by the following
- * structure. It contains a control block to command a device, and also
- * the neccessary data channel information as well.
- */
-typedef struct cdkasy {
- cdkctrl_t ctrl;
- unsigned short notify;
- asynotify_t changed;
- unsigned short receive;
- cdkasyrq_t rxq;
- unsigned short transmit;
- cdkasyrq_t txq;
-} cdkasy_t;
-
-#pragma pack()
-
-/*****************************************************************************/
-
-/*
- * Define the set of ioctls used by the driver to do special things
- * to the board. These include interrupting it, and initializeing
- * the driver after board startup and shutdown.
- */
-#define STL_BINTR _IO('s', 20)
-#define STL_BSTART _IO('s', 21)
-#define STL_BSTOP _IO('s', 22)
-#define STL_BRESET _IO('s', 23)
-
-/*
- * Define a set of ioctl extensions, used to get at special stuff.
- */
-#define STL_GETPFLAG _IOR('s', 80, unsigned long)
-#define STL_SETPFLAG _IOW('s', 81, unsigned long)
-
-/*****************************************************************************/
-#endif
diff --git a/sys/i386/isa/README.stl b/sys/i386/isa/README.stl
deleted file mode 100644
index d723dca..0000000
--- a/sys/i386/isa/README.stl
+++ /dev/null
@@ -1,536 +0,0 @@
-$FreeBSD$
-
-Stallion Multiport Serial Driver Readme
----------------------------------------
-
-Version: 0.0.5 alpha
-Date: 20MAR96
-Author: Greg Ungerer (gerg@stallion.oz.au)
-
-
-
-1. INTRODUCTION
-
-This is a FreeBSD driver for some of the Stallion Technologies range of
-multiport serial boards. This driver is still very new, so it should be
-considered to be of very alpha quality.
-
-This driver has not been developed by Stallion Technologies. I developed it
-in my spare time in the hope that it would be useful. As such there is no
-warranty or support of any form. What this means is that this driver is not
-officially supported by Stallion Technologies, so don't ring their support
-if you can't get it working. They will probably not be able to help you.
-Instead email me if you have problems or bug reports and I will do what I
-can... (Sorry to sound so heavy handed, but I need to stress that this driver
-is not officially supported in any way.)
-
-This package actually contains two drivers. One is for the true Stallion
-intelligent multiport boards, and the other is for the smart range of boards.
-
-All host driver source is included in this package, and is copyrighted under
-a BSD style copyright. The board "firmware" code in this package is copyright
-Stallion Technologies (the files cdk.sys and 2681.sys).
-
-
-1.1 SMART MULTIPORT BOARD DRIVER
-
-This driver supports the EasyIO and EasyConnection 8/32 range of boards.
-These boards are not classic intelligent multiport boards, but are host
-based multiport boards that use high performance Cirrus Logic CL-CD1400 RISC
-UART's (they have built in FIFO's, automatic flow control and some other
-good stuff).
-
-The EasyIO range of cards comes in 3 forms, the EasyIO-4, EasyIO-8 and the
-EasyIO-8M. All of these are non-expandable, low cost, ISA, multiport boards
-with 4, 8 and 8 RS-232C ports respectively. Each EasyIO board requires 8
-bytes of I/O address space and 1 interrupt. On an EISA system it is possible
-to share 1 interrupt between multiple boards. The EasyIO-4 has 10 pin RJ
-connectors, and the EasyIO-8 comes with a dongle cable with either 10 pin RJ
-connectors or DB-25 connectors. The EasyIO-8M has 6 pin RJ connectors.
-
-The EasyConnection 8/32 family of boards is a relatively low cost modular
-range of multiport serial boards. The EasyConnection 8/32 boards can be
-configured to have from 8 to 32 serial ports by plugging in external serial
-port modules that contain either 8 or 16 ports each. There is a wide range
-of external modules available that offer: DB-25 connectors, RJ-45 connectors
-(both with RS-232 D and E compatible drivers), and also RS-422 and RS-485
-ports. The EasyConnection 8/32 boards come in ISA, PCI and MCA bus versions.
-The board takes the form of a host adapter card, with an external connector
-cable that plugs into the external modules. The external modules just clip
-together to add ports (BTW, they are NOT hot pluggable). Each ISA
-EasyConnection 8/32 board requires two separate I/O address ranges, one two
-bytes in size and a secondary region of 32 bytes. Each PCI EasyConnection
-8/32 requires two regions of I/O address space, normally these will be
-automatically allocated by the system BIOS at system power on time. Each MCA
-EasyConnection board requires one I/O address region 64 bytes in size. All
-board types also require one interrupt. On EISA systems multiple boards can
-share one interrupt. The secondary I/O range of the ISA board (the 32 byte
-range) can be shared between multiple boards on any bus type.
-
-
-1.2 INTELLIGENT MULTIPORT BOARD DRIVER
-
-This driver is for Stallion's range of true intelligent multiport boards.
-It supports the EasyConnection 8/64, ONboard, Brumby and original Stallion
-families of multiport boards. The EasyConnection 8/64 and ONboard boards come
-in ISA, EISA and Microchannel bus versions. The Brumby and Stallion boards
-are only available in ISA versions.
-
-The EasyConnection 8/64 family of boards is a medium cost, high performance,
-modular range of intelligent multiport serial boards. The EasyConnection 8/64
-boards can be configured to have from 8 to 64 serial ports by plugging in
-external serial port modules that contain either 8 or 16 ports each (these
-modules are the same used by the EasyConnection 8/32 board). There is a wide
-range of external modules available that offer: DB-25 connectors, RJ-45
-connectors (both with RS-232 D and E compatible drivers), and also RS-422 and
-RS-485 ports. The board takes the form of a host adapter card, with an external
-connector cable that plugs into the external modules. The external modules
-just clip together to add ports (BTW, they are NOT hot pluggable). Each
-EasyConnection 8/64 board requires 4 bytes of I/O address space and a region
-of memory space. The size of the memory region required depends on the exact
-board type. The EISA version requires 64 Kbytes of address space (that can
-reside anywhere in the 4 Gigabyte physical address space). The ISA and MCA
-boards require 4 Kbytes of address space (which must reside in the lower
-1 Mbyte of physical address space - typically in the c8000 to e0000 range).
-No interrupts are required. The physical memory region of multiple
-EasyConnection 8/64 boards can be shared, but each board must have a separate
-I/O address space.
-
-The ONboard family of boards are traditional intelligent multiport serial
-boards. They are Stallion's older range of boards with a limited expansion
-capability. They come in 4, 8, 12, 16 and 32 port versions. The board uses
-the same base card (which has 4 ports on it) and is expanded to more ports
-via a mezzanine board that attaches directly onto the board. External panels
-plug into the ONboard providing RS-232C ports with DB-25 plugs. An RS-422
-DB-25 dual interface panel is also available. The ISA and microchannel
-ONboards require 16 bytes of I/O address space and 64K bytes of memory
-space. The memory space can be anywhere in the 16 Mbyte ISA bus address
-range. No interrupt is required. The EISA ONboard requires 64 Kbytes of
-memory space that can be anywhere in the 4 Gigabyte physical address space.
-All ONboard boards can share their memory region with other ONboards (or
-EasyConnection 8/64 boards).
-
-The Brumby family of boards are traditional, low cost intelligent multiport
-serial boards. They are non-expandable and come in 4, 8 and 16 port versions.
-They are only available for the ISA bus. The serial ports are all on DB-25
-"dongle" cables that attach to the rear of the board. Each Brumby board
-requires 16 bytes of I/O address space and 16 Kbytes of memory space. No
-interrupts are required.
-
-The original Stallion boards are old. They went out of production some years
-back. They offer limited expandability and are available in 8 or 16 port
-configurations. An external panel houses 16 RS-232C ports with DB-9
-connectors. They require 16 bytes of I/O address space, and either 64K or
-128K of memory space. No interrupt is required. I will not actively support
-these boards, although they will work with the driver.
-
-That's the boards supported by the second driver. The ONboard, Brumby and
-Stallion boards are Stallion's older range of intelligent multiports - so
-there are lots of them around. They only support a maximum baud rate of
-38400. The EasyConnection 8/64 is a true high performance intelligent
-multiport board, having much greater throughput than any of Stallion's
-older boards. It also supports speeds up to 115200 baud.
-
-
-1.3 HOW TO GET BOARDS
-
-Stallion Technologies has offices all over the world, as well as many more
-distributors and resellers. To find out about local availability please
-contact the nearest Stallion office and they can give you all the information
-you need.
-
- Stallion Technologies Sales and Support Offices
- ===============================================
-
- Stallion Technologies Pty. Ltd.
- P.O. Box 954
- Toowong, QLD 4066, Australia
- Tel. +61 7 3270 4242
- Fax. +61 7 3270 4245
- Email: support@stallion.oz.au
-
- Stallion Technologies Inc.
- 2880 Research Park Drive,
- Soquel, CA 95073, USA.
- Tel. +1 408 477 0440
- Fax. +1 408 477 0444
- Email: support@staltec.com
-
- Stallion Technologies Deutschland GmbH.
- Martin-Behaim-Strasse 12
- 63263 Neu-Isenburg
- Germany
- Tel. +49 6102 73970
- Fax. +49 6102 739710
-
-Another good source of information about the Stallion range of boards and
-local availability is on the Stallion Web page. Check it out at
-http://www.stallion.com.
-
-
-
-2. INSTALLATION
-
-This driver, as is, will work on a FreeBSD 2.1 system. It will run on
-a 2.0.5 system, or -current version systems by changing a define in the
-driver source.
-
-You will need to build a new kernel to use this driver. So the first thing
-you need is to have the full kernel source. Most people will have this
-(I hope!). The following assumes that the kernel source is in /usr/src/sys.
-
-The drivers can support up to 8 boards. For the smart board driver any
-combination of EasyIO and EasyConnection 8/32 boards can be installed. For
-the intelligent any combination of EasyConnection 8/64, ONboard, Brumby or
-original Stallion. So there is a theoretical maximum of 512 ports.
-(Off-course I have not tested a system with this many!)
-
-
-[[[ The install instructions are obsolete, it is now standard ]]]
-[[[ Skip forward to item 4, editing your kernel config file ]]]
-
-2.1 Instructions to install:
-
-1. Copy the driver source files into the kernel source tree.
-
- cp stallion.c istallion.c cdk.h comstats.h /usr/src/sys/i386/isa
- cp scd1400.h /usr/src/sys/i386/isa/ic
-
- Note: if you are NOT using FreeBSD 2.1.0 then you will need to edit the
- stallion.c and istallion.c files and change the VFREEBSD define to match
- your version.
-
-2. Skip to next step if on a FreeBSD kernel later than 2.1.0.
- Add a character device switch table entry for the driver that you which
- to use into the cdevsw table structure. This involves adding some code
- into the kernel conf.c file.
-
- If you are using an EasyIO or EasyConnection 8/32 then you need to use
- the stallion.c driver. All other board types (EasyConnection 8/64,
- ONboard, Brumby, Stallion) use the istallion.c driver. You can also have
- a mix of boards using both drivers. You will need to use a different
- major device number for the second driver though (not the default 72 -
- see below for more details on this).
-
-2.1. If using the stallion.c driver then do:
-
- cd /usr/src/sys/i386/i386
- vi conf.c
- - add the following lines (in 2.1 I put them at line 729):
-
-/* Stallion Multiport Serial Driver */
-#include "stl.h"
-#if NSTL > 0
-d_open_t stlopen;
-d_close_t stlclose;
-d_read_t stlread;
-d_write_t stlwrite;
-d_ioctl_t stlioctl;
-d_stop_t stlstop;
-d_ttycv_t stldevtotty;
-#define stlreset nxreset
-#define stlmmap nxmmap
-#define stlstrategy nxstrategy
-#else
-#define stlopen nxopen
-#define stlclose nxclose
-#define stlread nxread
-#define stlwrite nxwrite
-#define stlioctl nxioctl
-#define stlstop nxstop
-#define stlreset nxreset
-#define stlmmap nxmmap
-#define stlstrategy nxstrategy
-#define stldevtotty nxdevtotty
-#endif
-
-
- - and then inside the actual cdevsw structure definition, at the
- last entry add (this is now line 1384 in the 2.1 conf.c):
-
- { stlopen, stlclose, stlread, stlwrite, /*72*/
- stlioctl, stlstop, stlreset, stldevtotty,/*stallion*/
- ttselect, stlmmap, stlstrategy },
-
- - the line above used major number 72, but this may be different
- on your system. Take note of what major number you are using.
-
- - save the file and exit vi.
-
-
-2.2. If using the istallion.c driver then do:
-
- cd /usr/src/sys/i386/i386
- vi conf.c
- - add the following lines (in 2.1 I put them at line 729):
-
-/* Stallion Intelligent Multiport Serial Driver */
-#include "stl.h"
-#if NSTL > 0
-d_open_t stliopen;
-d_close_t stliclose;
-d_read_t stliread;
-d_write_t stliwrite;
-d_ioctl_t stliioctl;
-d_stop_t stlistop;
-d_ttycv_t stlidevtotty;
-#define stlireset nxreset
-#define stlimmap nxmmap
-#define stlistrategy nxstrategy
-#else
-#define stliopen nxopen
-#define stliclose nxclose
-#define stliread nxread
-#define stliwrite nxwrite
-#define stliioctl nxioctl
-#define stlistop nxstop
-#define stlireset nxreset
-#define stlimmap nxmmap
-#define stlistrategy nxstrategy
-#define stlidevtotty nxdevtotty
-#endif
-
-
- - and then inside the actual cdevsw structure definition, at the
- last entry add (this is now line 1384 in the 2.1 conf.c):
-
- { stliopen, stliclose, stliread, stliwrite, /*72*/
- stliioctl, stlistop, stlireset, stlidevtotty,/*istallion*/
- ttselect, stlimmap, stlistrategy },
-
- - the line above used major number 72, but this may be different
- on your system. Take note of what major number you are using.
-
- - save the file and exit vi.
-
-3. Add the driver source files to the kernel files list:
-
- cd /usr/src/sys/i386/conf
- vi files.i386
- - add the following definition lines into the list (it is stored
- alphabetically, so insert them appropriately):
-
-i386/isa/istallion.c optional stli device-driver
-
-i386/isa/stallion.c optional stl device-driver
-
- - save the file and exit vi.
-
-4. Add board probe entries into the kernel configuration file:
-
- cd /usr/src/sys/i386/conf
- cp GENERIC MYKERNEL
- - if you already have a kernel config that you use then you
- could just use that (instead of MYKERNEL)
- vi MYKERNEL
- - if only using ECH-PCI boards then you don't need to enter a
- configuration line, the kernel will automatically detect
- the board at boot up, so skip to step 5.
- - enter a line for each board that you want to use. For stallion.c
- boards entries should look like:
-
-device stl0 at isa? port 0x2a0 tty irq 10
-
- For istallion.c boards, the entries should look like:
-
-device stli0 at isa? port 0x2a0 tty iomem 0xcc000 iosiz 0x1000 flags 23
-
- (I suggest you put them after the sio? entries)
- (Don't enter lines for ECH-PCI boards)
- - change the entry resources as required. For the Stallion.c
- entries this may involve changing the port address or irq.
- For the istallion.c entries this may involve changing the port
- address, iomem address, iosiz value and the flags. Select from
- the following table for appropriate flags and iosiz values for
- your board type:
-
- EasyConnection 8/64 ISA: flags 23 iosiz 0x1000
- EasyConnection 8/64 EISA: flags 24 iosiz 0x10000
- EasyConnection 8/64 MCA: flags 25 iosiz 0x1000
- ONboard ISA: flags 4 iosiz 0x10000
- ONboard EISA: flags 7 iosiz 0x10000
- ONboard MCA: flags 3 iosiz 0x10000
- Brumby: flags 2 iosiz 0x4000
- Stallion: flags 1 iosiz 0x10000
-
- - save the file and exit
-
-5. Build a new kernel using this configuration.
-
- cd /usr/src/sys/i386/conf
- config MYKERNEL
- cd ../../compile/MYKERNEL
- make depend
- make all
- make install
-
-
-And there you have it! It is a little bit of effort to get it in there...
-
-Once you have a new kernel built reboot to start it up. On startup the
-Stallion board probes will report on whether the boards were found or not.
-For each board found the driver will print out the type of board found,
-and how many panels and ports it has.
-
-If a board is not found by the driver but is actually in the system then the
-most likely problem is that the IO address is incorrect. The easiest thing to
-do is change the DIP switches on the board to the desired address and reboot.
-
-On EasyIO and EasyConnection 8/32 boards the IRQ is software programmable,
-so if there is a conflict you may need to change the IRQ used for a board in
-the MYKERNEL configuration file and rebuild the kernel.
-
-Note that the secondary IO address of the EasyConnection 8/32 boards is hard
-coded into the stallion.c driver code. It is currently set to IO address
-0x280. If you need to use a different address then you will need to edit this
-file and change the variable named stl_ioshared.
-
-On intelligent boards it is possible that the board shared memory region is
-clashing with that of some other device. Check for this and change the device
-or kernel configuration as required.
-
-
-2.2 INTELLIGENT DRIVER OPERATION
-
-The intelligent boards also need to have their "firmware" code downloaded
-to them. This is done via a user level application supplied in the driver
-package called "stlload". Compile this program where ever you dropped the
-package files, by typing "make". In its simplest form you can then type
- ./stlload -i cdk.sys
-in this directory and that will download board 0 (assuming board 0 is an
-EasyConnection 8/64 board). To download to an ONboard, Brumby or Stallion do:
- ./stlload -i 2681.sys
-
-Normally you would want all boards to be downloaded as part of the standard
-system startup. To achieve this, add one of the lines above into the
-/etc/rc.serial file. To download each board just add the "-b <brd-number>"
-option to the line. You will need to download code for every board. You should
-probably move the stlload program into a system directory, such as /usr/sbin.
-Also, the default location of the cdk.sys image file in the stlload
-down-loader is /usr/lib/stallion. Create that directory and put the cdk.sys
-and 2681.sys files in it. (It's a convenient place to put them anyway). As an
-example your /etc/rc.serial file might have the following lines added to it
-(if you had 3 boards):
- /usr/sbin/stlload -b 0 -i /usr/lib/stallion/cdk.sys
- /usr/sbin/stlload -b 1 -i /usr/lib/stallion/2681.sys
- /usr/sbin/stlload -b 2 -i /usr/lib/stallion/2681.sys
-
-The image files cdk.sys and 2681.sys are specific to the board types. The
-cdk.sys will only function correctly on an EasyConnection 8/64 board. Similarly
-the 2681.sys image will only operate on ONboard, Brumby and Stallion boards.
-If you load the wrong image file into a board it will fail to start up, and
-of course the ports will not be operational!
-
-
-
-3. USING THE DRIVER
-
-Once the driver is installed you will need to setup some device nodes to
-access the serial ports. Use the supplied "mkdevnods" script to automatically
-create all required device entries for your boards. To make device nodes for
-more than 1 board then just supply the number of boards you are using as a
-command line parameter to mkdevnods and it will create nodes for that number
-of boards. By default it will create device nodes for 1 board only.
-
-Note that if the driver is not installed at character major number 72 then
-you will need to edit the mkdevnods script and modify the STL_SERIALMAJOR
-variable to the major number you are using.
-
-Device nodes created for the normal serial port devices are named /dev/ttyEX
-where X is the port number. (The second boards ports will start from ttyE64,
-the third boards from ttyE128, etc). It will also create a set of modem call
-out devices named cueX where again X is the port number.
-
-For the most part the Stallion driver tries to emulate the standard PC system
-com ports and the standard sio serial driver. The idea is that you should
-be able to use Stallion board ports and com ports inter-changeably without
-modifying anything but the device name. Anything that doesn't work like that
-should be considered a bug in this driver!
-
-Since this driver tries to emulate the standard serial ports as much as
-possible then most system utilities should work as they do for the standard
-com ports. Most importantly "stty" works as expected and "comcontrol" can be
-used just like for the serial ports.
-
-This driver should work with anything that works on standard com serial ports.
-Having said that, I have used it on at least the following types of "things"
-under FreeBSD:
- a) standard dumb terminals (using getty)
- b) modems (using cu, etc)
- c) ppp (through pppd, kernel ppp)
-
-
-
-4. NOTES
-
-Be aware that these drivers are still very new, so there is sure to be some
-bugs in them. Please email me any feedback on bugs, problems, or even good
-experiences with these drivers!
-
-You can use both drivers at once if you have a mix of board types installed
-in a system. However to do this you will need to change the major number used
-by one of the drivers. Currently both drivers use default major number 72 for
-their devices. Change one driver to use some other major number (how this is
-achieved will depend on the kernel version you are using), and then modify the
-mkdevnods script to make device nodes based on those new major numbers. For
-example, you could change the stallion.c driver to use major number 73. You
-will also need to create device nodes with different names for the ports, for
-eg ttyFXXX.
-
-Currently the intelligent board driver (istallion.c) does not have the
-ability to share a boards memory region with other boards (you can only do
-this on EasyConnection 8/64 and ONboards normally anyway). It also does
-not currently support any memory address ranges above the low 1Mb region.
-These will be fixed in a future release of the driver.
-
-Finding a free physical memory address range can be a problem. The older
-boards like the Stallion and ONboard need large areas (64K or even 128K), so
-they can be very difficult to get into a system. If you have 16 Mb of RAM
-then you have no choice but to put them somewhere in the 640K -> 1Mb range.
-ONboards require 64K, so typically 0xd0000 is good, or 0xe0000 on some
-systems. If you have an original Stallion board, "V4.0" or Rev.O, then you
-need a 64K memory address space, so again 0xd0000 and 0xe0000 are good. Older
-Stallion boards are a much bigger problem. They need 128K of address space and
-must be on a 128K boundary. If you don't have a VGA card then 0xc0000 might be
-usable - there is really no other place you can put them below 1Mb.
-
-Both the ONboard and old Stallion boards can use higher memory addresses as
-well, but you must have less than 16Mb of RAM to be able to use them. Usual
-high memory addresses used include 0xec0000 and 0xf00000.
-
-The Brumby boards only require 16Kb of address space, so you can usually
-squeeze them in somewhere. Common addresses are 0xc8000, 0xcc000, or in
-the 0xd0000 range. EasyConnection 8/64 boards are even better, they only
-require 4Kb of address space, again usually 0xc8000, 0xcc000 or 0xd0000
-are good.
-
-If you are using an EasyConnection 8/64-EI or ONboard/E then usually the
-0xd0000 or 0xe0000 ranges are the best options below 1Mb. If neither of
-them can be used then the high memory support to use the really high address
-ranges is the best option. Typically the 2Gb range is convenient for them,
-and gets them well out of the way.
-
-The ports of the EasyIO-8M board do not have DCD or DTR signals. So these
-ports cannot be used as real modem devices. Generally when using these
-ports you should only use the cueX devices.
-
-There is a new utility in this package that reports statistics on the
-serial ports. You will need to have the ncurses library installed on your
-system to build it.
-
-To build the statistics display program type:
- make stlstats
-Once compiled simply run it (you will need to be root) and it will display
-a port summary for the first board and panel installed. Use the digits to
-select different board numbers, or 'n' to cycle through the panels on a
-board. To look at detailed port information then hit 'p', that will display
-detailed port 0 information. Use the digits and letters 'a' through 'f' to
-select the different ports (on this board and panel).
-
-
-
-5. ACKNOWLEDGEMENTS
-
-This driver is loosely based on the code of the FreeBSD sio serial driver.
-A big thanks to Stallion Technologies for the use of their equipment.
-
diff --git a/sys/i386/isa/istallion.c b/sys/i386/isa/istallion.c
deleted file mode 100644
index f6f10b1..0000000
--- a/sys/i386/isa/istallion.c
+++ /dev/null
@@ -1,3850 +0,0 @@
-/*****************************************************************************/
-
-/*
- * istallion.c -- stallion intelligent multiport serial driver.
- *
- * Copyright (c) 1994-1996 Greg Ungerer (gerg@stallion.oz.au).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Greg Ungerer.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*****************************************************************************/
-
-#include "opt_compat.h"
-#include "opt_tty.h"
-
-#define TTYDEFCHARS 1
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/tty.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/uio.h>
-#include <sys/bus.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <i386/isa/isa_device.h>
-#include <machine/cdk.h>
-#include <machine/comstats.h>
-
-#ifndef COMPAT_OLDISA
-#error "The stli device requires the old isa compatibility shims"
-#endif
-
-/*****************************************************************************/
-
-/*
- * Define the version level of the kernel - so we can compile in the
- * appropriate bits of code. By default this will compile for a 2.1
- * level kernel.
- */
-#define VFREEBSD 220
-
-#if VFREEBSD >= 220
-#define STATIC static
-#else
-#define STATIC
-#endif
-
-/*****************************************************************************/
-
-/*
- * Define different board types. Not all of the following board types
- * are supported by this driver. But I will use the standard "assigned"
- * board numbers. Currently supported boards are abbreviated as:
- * ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
- * STAL = Stallion.
- */
-#define BRD_UNKNOWN 0
-#define BRD_STALLION 1
-#define BRD_BRUMBY4 2
-#define BRD_ONBOARD2 3
-#define BRD_ONBOARD 4
-#define BRD_BRUMBY8 5
-#define BRD_BRUMBY16 6
-#define BRD_ONBOARDE 7
-#define BRD_ONBOARD32 9
-#define BRD_ONBOARD2_32 10
-#define BRD_ONBOARDRS 11
-#define BRD_EASYIO 20
-#define BRD_ECH 21
-#define BRD_ECHMC 22
-#define BRD_ECP 23
-#define BRD_ECPE 24
-#define BRD_ECPMC 25
-#define BRD_ECHPCI 26
-
-#define BRD_BRUMBY BRD_BRUMBY4
-
-/*****************************************************************************/
-
-/*
- * Define important driver limitations.
- */
-#define STL_MAXBRDS 8
-#define STL_MAXPANELS 4
-#define STL_PORTSPERPANEL 16
-#define STL_PORTSPERBRD 64
-
-#define STL_MAXCHANS STL_PORTSPERBRD
-
-
-/*
- * Define the important minor number break down bits. These have been
- * chosen to be "compatible" with the standard sio driver minor numbers.
- * Extra high bits are used to distinguish between boards and also for
- * really high port numbers (> 32).
- */
-#define STL_CALLOUTDEV 0x80
-#define STL_CTRLLOCK 0x40
-#define STL_CTRLINIT 0x20
-#define STL_CTRLDEV (STL_CTRLLOCK | STL_CTRLINIT)
-
-#define STL_MEMDEV 0x07000000
-
-#define STL_DEFSPEED TTYDEF_SPEED
-#define STL_DEFCFLAG (CS8 | CREAD | HUPCL)
-
-/*****************************************************************************/
-
-/*
- * Define our local driver identity first. Set up stuff to deal with
- * all the local structures required by a serial tty driver.
- */
-static char stli_drvname[] = "stli";
-static char const stli_longdrvname[] = "Stallion Multiport Serial Driver";
-static char const stli_drvversion[] = "1.0.0";
-
-static int stli_nrbrds = 0;
-static int stli_doingtimeout = 0;
-
-static char *__file__ = /*__FILE__*/ "istallion.c";
-
-/*
- * Define some macros to use to class define boards.
- */
-#define BRD_ISA 0x1
-#define BRD_EISA 0x2
-#define BRD_MCA 0x4
-#define BRD_PCI 0x8
-
-static unsigned char stli_stliprobed[STL_MAXBRDS];
-
-/*****************************************************************************/
-
-/*
- * Define a set of structures to hold all the board/panel/port info
- * for our ports. These will be dynamically allocated as required at
- * driver initialization time.
- */
-
-/*
- * Port and board structures to hold status info about each object.
- * The board structure contains pointers to structures for each port
- * connected to it. Panels are not distinguished here, since
- * communication with the slave board will always be on a per port
- * basis.
- */
-typedef struct {
- struct tty tty;
- int portnr;
- int panelnr;
- int brdnr;
- int ioaddr;
- int callout;
- int devnr;
- int dtrwait;
- int dotimestamp;
- int waitopens;
- int hotchar;
- int rc;
- int argsize;
- void *argp;
- unsigned int state;
- unsigned int sigs;
- struct termios initintios;
- struct termios initouttios;
- struct termios lockintios;
- struct termios lockouttios;
- struct timeval timestamp;
- asysigs_t asig;
- unsigned long addr;
- unsigned long rxlost;
- unsigned long rxoffset;
- unsigned long txoffset;
- unsigned long pflag;
- unsigned int rxsize;
- unsigned int txsize;
- unsigned char reqidx;
- unsigned char reqbit;
- unsigned char portidx;
- unsigned char portbit;
-} stliport_t;
-
-/*
- * Use a structure of function pointers to do board level operations.
- * These include, enable/disable, paging shared memory, interrupting, etc.
- */
-typedef struct stlibrd {
- int brdnr;
- int brdtype;
- int unitid;
- int state;
- int nrpanels;
- int nrports;
- int nrdevs;
- unsigned int iobase;
- unsigned long paddr;
- void *vaddr;
- int memsize;
- int pagesize;
- int hostoffset;
- int slaveoffset;
- int bitsize;
- int confbits;
- void (*init)(struct stlibrd *brdp);
- void (*enable)(struct stlibrd *brdp);
- void (*reenable)(struct stlibrd *brdp);
- void (*disable)(struct stlibrd *brdp);
- void (*intr)(struct stlibrd *brdp);
- void (*reset)(struct stlibrd *brdp);
- char *(*getmemptr)(struct stlibrd *brdp,
- unsigned long offset, int line);
- int panels[STL_MAXPANELS];
- int panelids[STL_MAXPANELS];
- stliport_t *ports[STL_PORTSPERBRD];
-} stlibrd_t;
-
-static stlibrd_t *stli_brds[STL_MAXBRDS];
-
-static int stli_shared = 0;
-
-/*
- * Keep a local char buffer for processing chars into the LD. We
- * do this to avoid copying from the boards shared memory one char
- * at a time.
- */
-static int stli_rxtmplen;
-static stliport_t *stli_rxtmpport;
-static char stli_rxtmpbuf[TTYHOG];
-
-/*
- * Define global stats structures. Not used often, and can be re-used
- * for each stats call.
- */
-static comstats_t stli_comstats;
-static combrd_t stli_brdstats;
-static asystats_t stli_cdkstats;
-
-/*
- * Per board state flags. Used with the state field of the board struct.
- * Not really much here... All we need to do is keep track of whether
- * the board has been detected, and whether it is actully running a slave
- * or not.
- */
-#define BST_FOUND 0x1
-#define BST_STARTED 0x2
-
-/*
- * Define the set of port state flags. These are marked for internal
- * state purposes only, usually to do with the state of communications
- * with the slave. They need to be updated atomically.
- */
-#define ST_INITIALIZING 0x1
-#define ST_INITIALIZED 0x2
-#define ST_OPENING 0x4
-#define ST_CLOSING 0x8
-#define ST_CMDING 0x10
-#define ST_RXING 0x20
-#define ST_TXBUSY 0x40
-#define ST_DOFLUSHRX 0x80
-#define ST_DOFLUSHTX 0x100
-#define ST_DOSIGS 0x200
-#define ST_GETSIGS 0x400
-#define ST_DTRWAIT 0x800
-
-/*
- * Define an array of board names as printable strings. Handy for
- * referencing boards when printing trace and stuff.
- */
-static char *stli_brdnames[] = {
- "Unknown",
- "Stallion",
- "Brumby",
- "ONboard-MC",
- "ONboard",
- "Brumby",
- "Brumby",
- "ONboard-EI",
- (char *) NULL,
- "ONboard",
- "ONboard-MC",
- "ONboard-MC",
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- "EasyIO",
- "EC8/32-AT",
- "EC8/32-MC",
- "EC8/64-AT",
- "EC8/64-EI",
- "EC8/64-MC",
- "EC8/32-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- * Hardware configuration info for ECP boards. These defines apply
- * to the directly accessible io ports of the ECP. There is a set of
- * defines for each ECP board type, ISA, EISA and MCA.
- */
-#define ECP_IOSIZE 4
-#define ECP_MEMSIZE (128 * 1024)
-#define ECP_ATPAGESIZE (4 * 1024)
-#define ECP_EIPAGESIZE (64 * 1024)
-#define ECP_MCPAGESIZE (4 * 1024)
-
-#define STL_EISAID 0x8c4e
-
-/*
- * Important defines for the ISA class of ECP board.
- */
-#define ECP_ATIREG 0
-#define ECP_ATCONFR 1
-#define ECP_ATMEMAR 2
-#define ECP_ATMEMPR 3
-#define ECP_ATSTOP 0x1
-#define ECP_ATINTENAB 0x10
-#define ECP_ATENABLE 0x20
-#define ECP_ATDISABLE 0x00
-#define ECP_ATADDRMASK 0x3f000
-#define ECP_ATADDRSHFT 12
-
-/*
- * Important defines for the EISA class of ECP board.
- */
-#define ECP_EIIREG 0
-#define ECP_EIMEMARL 1
-#define ECP_EICONFR 2
-#define ECP_EIMEMARH 3
-#define ECP_EIENABLE 0x1
-#define ECP_EIDISABLE 0x0
-#define ECP_EISTOP 0x4
-#define ECP_EIEDGE 0x00
-#define ECP_EILEVEL 0x80
-#define ECP_EIADDRMASKL 0x00ff0000
-#define ECP_EIADDRSHFTL 16
-#define ECP_EIADDRMASKH 0xff000000
-#define ECP_EIADDRSHFTH 24
-#define ECP_EIBRDENAB 0xc84
-
-#define ECP_EISAID 0x4
-
-/*
- * Important defines for the Micro-channel class of ECP board.
- * (It has a lot in common with the ISA boards.)
- */
-#define ECP_MCIREG 0
-#define ECP_MCCONFR 1
-#define ECP_MCSTOP 0x20
-#define ECP_MCENABLE 0x80
-#define ECP_MCDISABLE 0x00
-
-/*
- * Hardware configuration info for ONboard and Brumby boards. These
- * defines apply to the directly accessible io ports of these boards.
- */
-#define ONB_IOSIZE 16
-#define ONB_MEMSIZE (64 * 1024)
-#define ONB_ATPAGESIZE (64 * 1024)
-#define ONB_MCPAGESIZE (64 * 1024)
-#define ONB_EIMEMSIZE (128 * 1024)
-#define ONB_EIPAGESIZE (64 * 1024)
-
-/*
- * Important defines for the ISA class of ONboard board.
- */
-#define ONB_ATIREG 0
-#define ONB_ATMEMAR 1
-#define ONB_ATCONFR 2
-#define ONB_ATSTOP 0x4
-#define ONB_ATENABLE 0x01
-#define ONB_ATDISABLE 0x00
-#define ONB_ATADDRMASK 0xff0000
-#define ONB_ATADDRSHFT 16
-
-#define ONB_HIMEMENAB 0x02
-
-/*
- * Important defines for the EISA class of ONboard board.
- */
-#define ONB_EIIREG 0
-#define ONB_EIMEMARL 1
-#define ONB_EICONFR 2
-#define ONB_EIMEMARH 3
-#define ONB_EIENABLE 0x1
-#define ONB_EIDISABLE 0x0
-#define ONB_EISTOP 0x4
-#define ONB_EIEDGE 0x00
-#define ONB_EILEVEL 0x80
-#define ONB_EIADDRMASKL 0x00ff0000
-#define ONB_EIADDRSHFTL 16
-#define ONB_EIADDRMASKH 0xff000000
-#define ONB_EIADDRSHFTH 24
-#define ONB_EIBRDENAB 0xc84
-
-#define ONB_EISAID 0x1
-
-/*
- * Important defines for the Brumby boards. They are pretty simple,
- * there is not much that is programmably configurable.
- */
-#define BBY_IOSIZE 16
-#define BBY_MEMSIZE (64 * 1024)
-#define BBY_PAGESIZE (16 * 1024)
-
-#define BBY_ATIREG 0
-#define BBY_ATCONFR 1
-#define BBY_ATSTOP 0x4
-
-/*
- * Important defines for the Stallion boards. They are pretty simple,
- * there is not much that is programmably configurable.
- */
-#define STAL_IOSIZE 16
-#define STAL_MEMSIZE (64 * 1024)
-#define STAL_PAGESIZE (64 * 1024)
-
-/*
- * Define the set of status register values for EasyConnection panels.
- * The signature will return with the status value for each panel. From
- * this we can determine what is attached to the board - before we have
- * actually down loaded any code to it.
- */
-#define ECH_PNLSTATUS 2
-#define ECH_PNL16PORT 0x20
-#define ECH_PNLIDMASK 0x07
-#define ECH_PNLINTRPEND 0x80
-
-/*
- * Define some macros to do things to the board. Even those these boards
- * are somewhat related there is often significantly different ways of
- * doing some operation on it (like enable, paging, reset, etc). So each
- * board class has a set of functions which do the commonly required
- * operations. The macros below basically just call these functions,
- * generally checking for a NULL function - which means that the board
- * needs nothing done to it to achieve this operation!
- */
-#define EBRDINIT(brdp) \
- if (brdp->init != NULL) \
- (* brdp->init)(brdp)
-
-#define EBRDENABLE(brdp) \
- if (brdp->enable != NULL) \
- (* brdp->enable)(brdp);
-
-#define EBRDDISABLE(brdp) \
- if (brdp->disable != NULL) \
- (* brdp->disable)(brdp);
-
-#define EBRDINTR(brdp) \
- if (brdp->intr != NULL) \
- (* brdp->intr)(brdp);
-
-#define EBRDRESET(brdp) \
- if (brdp->reset != NULL) \
- (* brdp->reset)(brdp);
-
-#define EBRDGETMEMPTR(brdp,offset) \
- (* brdp->getmemptr)(brdp, offset, __LINE__)
-
-/*
- * Define the maximal baud rate.
- */
-#define STL_MAXBAUD 230400
-
-/*****************************************************************************/
-
-/*
- * Define macros to extract a brd and port number from a minor number.
- * This uses the extended minor number range in the upper 2 bytes of
- * the device number. This gives us plenty of minor numbers to play
- * with...
- */
-#define MKDEV2BRD(m) ((minor(m) & 0x00700000) >> 20)
-#define MKDEV2PORT(m) ((minor(m) & 0x1f) | ((minor(m) & 0x00010000) >> 11))
-
-/*
- * Define some handy local macros...
- */
-#ifndef MIN
-#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
-#endif
-
-/*****************************************************************************/
-
-/*
- * Declare all those functions in this driver! First up is the set of
- * externally visible functions.
- */
-static int stliprobe(struct isa_device *idp);
-static int stliattach(struct isa_device *idp);
-
-STATIC d_open_t stliopen;
-STATIC d_close_t stliclose;
-STATIC d_read_t stliread;
-STATIC d_write_t stliwrite;
-STATIC d_ioctl_t stliioctl;
-
-/*
- * Internal function prototypes.
- */
-static stliport_t *stli_dev2port(dev_t dev);
-static int stli_isaprobe(struct isa_device *idp);
-static int stli_eisaprobe(struct isa_device *idp);
-static int stli_mcaprobe(struct isa_device *idp);
-static int stli_brdinit(stlibrd_t *brdp);
-static int stli_brdattach(stlibrd_t *brdp);
-static int stli_initecp(stlibrd_t *brdp);
-static int stli_initonb(stlibrd_t *brdp);
-static int stli_initports(stlibrd_t *brdp);
-static int stli_startbrd(stlibrd_t *brdp);
-static void stli_poll(void *arg);
-static __inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp);
-static __inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp);
-static __inline void stli_dodelaycmd(stliport_t *portp,
- volatile cdkctrl_t *cp);
-static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
-static long stli_mktiocm(unsigned long sigvalue);
-static void stli_rxprocess(stlibrd_t *brdp, stliport_t *portp);
-static void stli_flush(stliport_t *portp, int flag);
-static void stli_start(struct tty *tp);
-static void stli_stop(struct tty *tp, int rw);
-static int stli_param(struct tty *tp, struct termios *tiosp);
-static void stli_ttyoptim(stliport_t *portp, struct termios *tiosp);
-static void stli_dtrwakeup(void *arg);
-static int stli_initopen(stliport_t *portp);
-static int stli_shutdownclose(stliport_t *portp);
-static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp,
- unsigned long arg, int wait);
-static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp,
- unsigned long arg, int wait);
-static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp,
- unsigned long cmd, void *arg, int size, int copyback);
-static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp,
- unsigned long cmd, void *arg, int size, int copyback);
-static void stli_mkasyport(stliport_t *portp, asyport_t *pp,
- struct termios *tiosp);
-static int stli_memrw(dev_t dev, struct uio *uiop, int flag);
-static int stli_memioctl(dev_t dev, unsigned long cmd, caddr_t data,
- int flag, struct thread *td);
-static int stli_getbrdstats(caddr_t data);
-static int stli_getportstats(stliport_t *portp, caddr_t data);
-static int stli_clrportstats(stliport_t *portp, caddr_t data);
-static stliport_t *stli_getport(int brdnr, int panelnr, int portnr);
-
-static void stli_ecpinit(stlibrd_t *brdp);
-static void stli_ecpenable(stlibrd_t *brdp);
-static void stli_ecpdisable(stlibrd_t *brdp);
-static void stli_ecpreset(stlibrd_t *brdp);
-static char *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-static void stli_ecpintr(stlibrd_t *brdp);
-static void stli_ecpeiinit(stlibrd_t *brdp);
-static void stli_ecpeienable(stlibrd_t *brdp);
-static void stli_ecpeidisable(stlibrd_t *brdp);
-static void stli_ecpeireset(stlibrd_t *brdp);
-static char *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-static void stli_ecpmcenable(stlibrd_t *brdp);
-static void stli_ecpmcdisable(stlibrd_t *brdp);
-static void stli_ecpmcreset(stlibrd_t *brdp);
-static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-
-static void stli_onbinit(stlibrd_t *brdp);
-static void stli_onbenable(stlibrd_t *brdp);
-static void stli_onbdisable(stlibrd_t *brdp);
-static void stli_onbreset(stlibrd_t *brdp);
-static char *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-static void stli_onbeinit(stlibrd_t *brdp);
-static void stli_onbeenable(stlibrd_t *brdp);
-static void stli_onbedisable(stlibrd_t *brdp);
-static void stli_onbereset(stlibrd_t *brdp);
-static char *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-static void stli_bbyinit(stlibrd_t *brdp);
-static void stli_bbyreset(stlibrd_t *brdp);
-static char *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-static void stli_stalinit(stlibrd_t *brdp);
-static void stli_stalreset(stlibrd_t *brdp);
-static char *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset,
- int line);
-
-/*****************************************************************************/
-
-/*
- * Declare the driver isa structure.
- */
-struct isa_driver stlidriver = {
- INTR_TYPE_TTY,
- stliprobe,
- stliattach,
- stli_drvname
-};
-COMPAT_ISA_DRIVER(stli, stlidriver);
-
-/*****************************************************************************/
-
-#if VFREEBSD >= 220
-
-/*
- * FreeBSD-2.2+ kernel linkage.
- */
-
-static struct cdevsw stli_cdevsw = {
- .d_version = D_VERSION,
- .d_open = stliopen,
- .d_close = stliclose,
- .d_read = stliread,
- .d_write = stliwrite,
- .d_ioctl = stliioctl,
- .d_name = stli_drvname,
- .d_flags = D_TTY | D_NEEDGIANT,
-};
-
-#endif
-
-/*****************************************************************************/
-
-static stlibrd_t *stli_brdalloc(void)
-{
- stlibrd_t *brdp;
-
- brdp = (stlibrd_t *) malloc(sizeof(stlibrd_t), M_TTYS, M_NOWAIT|M_ZERO);
- if (brdp == (stlibrd_t *) NULL) {
- printf("STALLION: failed to allocate memory (size=%d)\n",
- sizeof(stlibrd_t));
- return((stlibrd_t *) NULL);
- }
- return(brdp);
-}
-
-/*****************************************************************************/
-
-/*
- * Find an available internal board number (unit number). The problem
- * is that the same unit numbers can be assigned to different class
- * boards - but we only want to maintain one setup board structures.
- */
-
-static int stli_findfreeunit(void)
-{
- int i;
-
- for (i = 0; (i < STL_MAXBRDS); i++)
- if (stli_brds[i] == (stlibrd_t *) NULL)
- break;
- return((i >= STL_MAXBRDS) ? -1 : i);
-}
-
-/*****************************************************************************/
-
-/*
- * Try and determine the ISA board type. Hopefully the board
- * configuration entry will help us out, using the flags field.
- * If not, we may ne be able to determine the board type...
- */
-
-static int stli_isaprobe(struct isa_device *idp)
-{
- int btype;
-
-#if DEBUG
- printf("stli_isaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
- (int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
-#endif
-
- switch (idp->id_flags) {
- case BRD_STALLION:
- case BRD_BRUMBY4:
- case BRD_BRUMBY8:
- case BRD_BRUMBY16:
- case BRD_ONBOARD:
- case BRD_ONBOARD32:
- case BRD_ECP:
- btype = idp->id_flags;
- break;
- default:
- btype = 0;
- break;
- }
- return(btype);
-}
-
-/*****************************************************************************/
-
-/*
- * Probe for an EISA board type. We should be able to read the EISA ID,
- * that will tell us if a board is present or not...
- */
-
-static int stli_eisaprobe(struct isa_device *idp)
-{
- int btype, eid;
-
-#if DEBUG
- printf("stli_eisaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
- (int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
-#endif
-
-/*
- * Firstly check if this is an EISA system. Do this by probing for
- * the system board EISA ID. If this is not an EISA system then
- * don't bother going any further!
- */
- outb(0xc80, 0xff);
- if (inb(0xc80) == 0xff)
- return(0);
-
-/*
- * Try and read the EISA ID from the board at specified address.
- * If one is present it will tell us the board type as well.
- */
- outb((idp->id_iobase + 0xc80), 0xff);
- eid = inb(idp->id_iobase + 0xc80);
- eid |= inb(idp->id_iobase + 0xc81) << 8;
- if (eid != STL_EISAID)
- return(0);
-
- btype = 0;
- eid = inb(idp->id_iobase + 0xc82);
- if (eid == ECP_EISAID)
- btype = BRD_ECPE;
- else if (eid == ONB_EISAID)
- btype = BRD_ONBOARDE;
-
- outb((idp->id_iobase + 0xc84), 0x1);
- return(btype);
-}
-
-/*****************************************************************************/
-
-/*
- * Probe for an MCA board type. Not really sure how to do this yet,
- * so for now just use the supplied flag specifier as board type...
- */
-
-static int stli_mcaprobe(struct isa_device *idp)
-{
- int btype;
-
-#if DEBUG
- printf("stli_mcaprobe(idp=%x): unit=%d iobase=%x flags=%x\n",
- (int) idp, idp->id_unit, idp->id_iobase, idp->id_flags);
-#endif
-
- switch (idp->id_flags) {
- case BRD_ONBOARD2:
- case BRD_ONBOARD2_32:
- case BRD_ONBOARDRS:
- case BRD_ECHMC:
- case BRD_ECPMC:
- btype = idp->id_flags;
- break;
- default:
- btype = 0;
- break;
- }
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Probe for a board. This is involved, since we need to enable the
- * shared memory region to see if the board is really there or not...
- */
-
-static int stliprobe(struct isa_device *idp)
-{
- stlibrd_t *brdp;
- int btype, bclass;
-
-#if DEBUG
- printf("stliprobe(idp=%x): unit=%d iobase=%x flags=%x\n", (int) idp,
- idp->id_unit, idp->id_iobase, idp->id_flags);
-#endif
-
- if (idp->id_unit > STL_MAXBRDS)
- return(0);
-
-/*
- * First up determine what bus type of board we might be dealing
- * with. It is easy to separate out the ISA from the EISA and MCA
- * boards, based on their IO addresses. We may not be able to tell
- * the EISA and MCA apart on IO address alone...
- */
- bclass = 0;
- if ((idp->id_iobase > 0) && (idp->id_iobase < 0x400)) {
- bclass |= BRD_ISA;
- } else {
- /* ONboard2 range */
- if ((idp->id_iobase >= 0x700) && (idp->id_iobase < 0x900))
- bclass |= BRD_MCA;
- /* EC-MCA ranges */
- if ((idp->id_iobase >= 0x7000) && (idp->id_iobase < 0x7400))
- bclass |= BRD_MCA;
- if ((idp->id_iobase >= 0x8000) && (idp->id_iobase < 0xc000))
- bclass |= BRD_MCA;
- /* EISA board range */
- if ((idp->id_iobase & ~0xf000) == 0)
- bclass |= BRD_EISA;
- }
-
- if ((bclass == 0) || (idp->id_iobase == 0))
- return(0);
-
-/*
- * Based on the board bus type, try and figure out what it might be...
- */
- btype = 0;
- if (bclass & BRD_ISA)
- btype = stli_isaprobe(idp);
- if ((btype == 0) && (bclass & BRD_EISA))
- btype = stli_eisaprobe(idp);
- if ((btype == 0) && (bclass & BRD_MCA))
- btype = stli_mcaprobe(idp);
- if (btype == 0)
- return(0);
-
-/*
- * Go ahead and try probing for the shared memory region now.
- * This way we will really know if the board is here...
- */
- if ((brdp = stli_brdalloc()) == (stlibrd_t *) NULL)
- return(0);
-
- brdp->brdnr = stli_findfreeunit();
- brdp->brdtype = btype;
- brdp->unitid = idp->id_unit;
- brdp->iobase = idp->id_iobase;
- brdp->vaddr = idp->id_maddr;
- brdp->paddr = vtophys(idp->id_maddr);
-
-#if DEBUG
- printf("%s(%d): btype=%x unit=%d brd=%d io=%x mem=%lx(%p)\n",
- __file__, __LINE__, btype, brdp->unitid, brdp->brdnr,
- brdp->iobase, brdp->paddr, (void *) brdp->vaddr);
-#endif
-
- stli_stliprobed[idp->id_unit] = brdp->brdnr;
- stli_brdinit(brdp);
- if ((brdp->state & BST_FOUND) == 0) {
- stli_brds[brdp->brdnr] = (stlibrd_t *) NULL;
- return(0);
- }
- stli_nrbrds++;
- return(1);
-}
-
-/*****************************************************************************/
-
-/*
- * Allocate resources for and initialize a board.
- */
-
-static int stliattach(struct isa_device *idp)
-{
- stlibrd_t *brdp;
- int brdnr;
-
-#if DEBUG
- printf("stliattach(idp=%p): unit=%d iobase=%x\n", (void *) idp,
- idp->id_unit, idp->id_iobase);
-#endif
-
- brdnr = stli_stliprobed[idp->id_unit];
- brdp = stli_brds[brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return(0);
- if (brdp->state & BST_FOUND)
- stli_brdattach(brdp);
- if (0) {
- make_dev(&stli_cdevsw, 0, 0, 0, 0, "istallion_is_broken");
- }
- return(1);
-}
-
-
-/*****************************************************************************/
-
-STATIC int stliopen(dev_t dev, int flag, int mode, struct thread *td)
-{
- struct tty *tp;
- stliport_t *portp;
- int error, callout, x;
-
-#if DEBUG
- printf("stliopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag,
- mode, (int) td);
-#endif
-
-/*
- * Firstly check if the supplied device number is a valid device.
- */
- if (minor(dev) & STL_MEMDEV)
- return(0);
-
- portp = stli_dev2port(dev);
- if (portp == (stliport_t *) NULL)
- return(ENXIO);
- tp = &portp->tty;
- dev->si_tty = tp;
- callout = minor(dev) & STL_CALLOUTDEV;
- error = 0;
-
- x = spltty();
-
-stliopen_restart:
-/*
- * Wait here for the DTR drop timeout period to expire.
- */
- while (portp->state & ST_DTRWAIT) {
- error = tsleep(&portp->dtrwait, (TTIPRI | PCATCH),
- "stlidtr", 0);
- if (error)
- goto stliopen_end;
- }
-
-/*
- * If the port is in its raw hardware initialization phase, then
- * hold up here 'till it is done.
- */
- while (portp->state & (ST_INITIALIZING | ST_CLOSING)) {
- error = tsleep(&portp->state, (TTIPRI | PCATCH),
- "stliraw", 0);
- if (error)
- goto stliopen_end;
- }
-
-/*
- * We have a valid device, so now we check if it is already open.
- * If not then initialize the port hardware and set up the tty
- * struct as required.
- */
- if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_oproc = stli_start;
- tp->t_param = stli_param;
- tp->t_stop = stli_stop;
- tp->t_dev = dev;
- tp->t_termios = callout ? portp->initouttios :
- portp->initintios;
- stli_initopen(portp);
- wakeup(&portp->state);
- if ((portp->sigs & TIOCM_CD) || callout)
- (*linesw[tp->t_line].l_modem)(tp, 1);
- } else {
- if (callout) {
- if (portp->callout == 0) {
- error = EBUSY;
- goto stliopen_end;
- }
- } else {
- if (portp->callout != 0) {
- if (flag & O_NONBLOCK) {
- error = EBUSY;
- goto stliopen_end;
- }
- error = tsleep(&portp->callout,
- (TTIPRI | PCATCH), "stlicall", 0);
- if (error)
- goto stliopen_end;
- goto stliopen_restart;
- }
- }
- if ((tp->t_state & TS_XCLUDE) &&
- suser(td)) {
- error = EBUSY;
- goto stliopen_end;
- }
- }
-
-/*
- * If this port is not the callout device and we do not have carrier
- * then we need to sleep, waiting for it to be asserted.
- */
- if (((tp->t_state & TS_CARR_ON) == 0) && !callout &&
- ((tp->t_cflag & CLOCAL) == 0) &&
- ((flag & O_NONBLOCK) == 0)) {
- portp->waitopens++;
- error = tsleep(TSA_CARR_ON(tp), (TTIPRI | PCATCH), "stlidcd",0);
- portp->waitopens--;
- if (error)
- goto stliopen_end;
- goto stliopen_restart;
- }
-
-/*
- * Open the line discipline.
- */
- error = (*linesw[tp->t_line].l_open)(dev, tp);
- stli_ttyoptim(portp, &tp->t_termios);
- if ((tp->t_state & TS_ISOPEN) && callout)
- portp->callout = 1;
-
-/*
- * If for any reason we get to here and the port is not actually
- * open then close of the physical hardware - no point leaving it
- * active when the open failed...
- */
-stliopen_end:
- splx(x);
- if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0))
- stli_shutdownclose(portp);
-
- return(error);
-}
-
-/*****************************************************************************/
-
-STATIC int stliclose(dev_t dev, int flag, int mode, struct thread *td)
-{
- struct tty *tp;
- stliport_t *portp;
- int x;
-
-#if DEBUG
- printf("stliclose(dev=%s,flag=%x,mode=%x,p=%p)\n",
- devtoname(dev), flag, mode, (void *) td);
-#endif
-
- if (minor(dev) & STL_MEMDEV)
- return(0);
-
- portp = stli_dev2port(dev);
- if (portp == (stliport_t *) NULL)
- return(ENXIO);
- tp = &portp->tty;
-
- x = spltty();
- (*linesw[tp->t_line].l_close)(tp, flag);
- stli_ttyoptim(portp, &tp->t_termios);
- stli_shutdownclose(portp);
- ttyclose(tp);
- splx(x);
- return(0);
-}
-
-
-STATIC int stliread(dev_t dev, struct uio *uiop, int flag)
-{
-
-#if DEBUG
- printf("stliread(dev=%s,uiop=%p,flag=%x)\n", devtoname(dev),
- (void *) uiop, flag);
-#endif
-
- if (minor(dev) & STL_MEMDEV)
- return(stli_memrw(dev, uiop, flag));
- else
- return(ttyread(dev, uiop, flag));
-}
-
-/*****************************************************************************/
-
-#if VFREEBSD >= 220
-
-STATIC void stli_stop(struct tty *tp, int rw)
-{
-#if DEBUG
- printf("stli_stop(tp=%x,rw=%x)\n", (int) tp, rw);
-#endif
-
- stli_flush((stliport_t *) tp, rw);
-}
-
-#else
-
-STATIC int stlistop(struct tty *tp, int rw)
-{
-#if DEBUG
- printf("stlistop(tp=%x,rw=%x)\n", (int) tp, rw);
-#endif
-
- stli_flush((stliport_t *) tp, rw);
- return(0);
-}
-
-#endif
-
-/*****************************************************************************/
-
-STATIC int stliwrite(dev_t dev, struct uio *uiop, int flag)
-{
-#if DEBUG
- printf("stliwrite(dev=%s,uiop=%p,flag=%x)\n", devtoname(dev),
- (void *) uiop, flag);
-#endif
-
- if (minor(dev) & STL_MEMDEV)
- return(stli_memrw(dev, uiop, flag));
- else
- return(ttywrite(dev, uiop, flag));
-}
-
-/*****************************************************************************/
-
-STATIC int stliioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
- struct thread *td)
-{
- struct termios *newtios, *localtios;
- struct tty *tp;
- stlibrd_t *brdp;
- stliport_t *portp;
- long arg;
- int error, i, x;
-
-#if DEBUG
- printf("stliioctl(dev=%s,cmd=%lx,data=%p,flag=%x,p=%p)\n",
- devtoname(dev), cmd, (void *) data, flag, (void *) td);
-#endif
-
- if (minor(dev) & STL_MEMDEV)
- return(stli_memioctl(dev, cmd, data, flag, td));
-
- portp = stli_dev2port(dev);
- if (portp == (stliport_t *) NULL)
- return(ENODEV);
- if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
- return(ENODEV);
- tp = &portp->tty;
- error = 0;
-
-/*
- * First up handle ioctls on the control devices.
- */
- if (minor(dev) & STL_CTRLDEV) {
- if ((minor(dev) & STL_CTRLDEV) == STL_CTRLINIT)
- localtios = (minor(dev) & STL_CALLOUTDEV) ?
- &portp->initouttios : &portp->initintios;
- else if ((minor(dev) & STL_CTRLDEV) == STL_CTRLLOCK)
- localtios = (minor(dev) & STL_CALLOUTDEV) ?
- &portp->lockouttios : &portp->lockintios;
- else
- return(ENODEV);
-
- switch (cmd) {
- case TIOCSETA:
- if ((error = suser(td)) == 0)
- *localtios = *((struct termios *) data);
- break;
- case TIOCGETA:
- *((struct termios *) data) = *localtios;
- break;
- case TIOCGETD:
- *((int *) data) = TTYDISC;
- break;
- case TIOCGWINSZ:
- bzero(data, sizeof(struct winsize));
- break;
- default:
- error = ENOTTY;
- break;
- }
- return(error);
- }
-
-/*
- * Deal with 4.3 compatibility issues if we have too...
- */
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- if (1) {
- struct termios tios;
- unsigned long oldcmd;
-
- tios = tp->t_termios;
- oldcmd = cmd;
- if ((error = ttsetcompat(tp, &cmd, data, &tios)))
- return(error);
- if (cmd != oldcmd)
- data = (caddr_t) &tios;
- }
-#endif
-
-/*
- * Carry out some pre-cmd processing work first...
- * Hmmm, not so sure we want this, disable for now...
- */
- if ((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
- newtios = (struct termios *) data;
- localtios = (minor(dev) & STL_CALLOUTDEV) ? &portp->lockouttios :
- &portp->lockintios;
-
- newtios->c_iflag = (tp->t_iflag & localtios->c_iflag) |
- (newtios->c_iflag & ~localtios->c_iflag);
- newtios->c_oflag = (tp->t_oflag & localtios->c_oflag) |
- (newtios->c_oflag & ~localtios->c_oflag);
- newtios->c_cflag = (tp->t_cflag & localtios->c_cflag) |
- (newtios->c_cflag & ~localtios->c_cflag);
- newtios->c_lflag = (tp->t_lflag & localtios->c_lflag) |
- (newtios->c_lflag & ~localtios->c_lflag);
- for (i = 0; (i < NCCS); i++) {
- if (localtios->c_cc[i] != 0)
- newtios->c_cc[i] = tp->t_cc[i];
- }
- if (localtios->c_ispeed != 0)
- newtios->c_ispeed = tp->t_ispeed;
- if (localtios->c_ospeed != 0)
- newtios->c_ospeed = tp->t_ospeed;
- }
-
-/*
- * Call the line discipline and the common command processing to
- * process this command (if they can).
- */
- error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
- if (error != ENOIOCTL)
- return(error);
-
- x = spltty();
- error = ttioctl(tp, cmd, data, flag);
- stli_ttyoptim(portp, &tp->t_termios);
- if (error != ENOIOCTL) {
- splx(x);
- return(error);
- }
-
- error = 0;
-
-/*
- * Process local commands here. These are all commands that only we
- * can take care of (they all rely on actually doing something special
- * to the actual hardware).
- */
- switch (cmd) {
- case TIOCSBRK:
- arg = BREAKON;
- error = stli_cmdwait(brdp, portp, A_BREAK, &arg,
- sizeof(unsigned long), 0);
- break;
- case TIOCCBRK:
- arg = BREAKOFF;
- error = stli_cmdwait(brdp, portp, A_BREAK, &arg,
- sizeof(unsigned long), 0);
- break;
- case TIOCSDTR:
- stli_mkasysigs(&portp->asig, 1, -1);
- error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 0);
- break;
- case TIOCCDTR:
- stli_mkasysigs(&portp->asig, 0, -1);
- error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 0);
- break;
- case TIOCMSET:
- i = *((int *) data);
- stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 1 : 0),
- ((i & TIOCM_RTS) ? 1 : 0));
- error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 0);
- break;
- case TIOCMBIS:
- i = *((int *) data);
- stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 1 : -1),
- ((i & TIOCM_RTS) ? 1 : -1));
- error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 0);
- break;
- case TIOCMBIC:
- i = *((int *) data);
- stli_mkasysigs(&portp->asig, ((i & TIOCM_DTR) ? 0 : -1),
- ((i & TIOCM_RTS) ? 0 : -1));
- error = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 0);
- break;
- case TIOCMGET:
- if ((error = stli_cmdwait(brdp, portp, A_GETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 1)) < 0)
- break;
- portp->sigs = stli_mktiocm(portp->asig.sigvalue);
- *((int *) data) = (portp->sigs | TIOCM_LE);
- break;
- case TIOCMSDTRWAIT:
- if ((error = suser(td)) == 0)
- portp->dtrwait = *((int *) data) * hz / 100;
- break;
- case TIOCMGDTRWAIT:
- *((int *) data) = portp->dtrwait * 100 / hz;
- break;
- case TIOCTIMESTAMP:
- portp->dotimestamp = 1;
- *((struct timeval *) data) = portp->timestamp;
- break;
- default:
- error = ENOTTY;
- break;
- }
- splx(x);
-
- return(error);
-}
-
-/*****************************************************************************/
-
-/*
- * Convert the specified minor device number into a port struct
- * pointer. Return NULL if the device number is not a valid port.
- */
-
-STATIC stliport_t *stli_dev2port(dev_t dev)
-{
- stlibrd_t *brdp;
-
- brdp = stli_brds[MKDEV2BRD(dev)];
- if (brdp == (stlibrd_t *) NULL)
- return((stliport_t *) NULL);
- if ((brdp->state & BST_STARTED) == 0)
- return((stliport_t *) NULL);
- return(brdp->ports[MKDEV2PORT(dev)]);
-}
-
-/*****************************************************************************/
-
-/*
- * Carry out first open operations on a port. This involves a number of
- * commands to be sent to the slave. We need to open the port, set the
- * notification events, set the initial port settings, get and set the
- * initial signal values. We sleep and wait in between each one. But
- * this still all happens pretty quickly.
- */
-
-static int stli_initopen(stliport_t *portp)
-{
- stlibrd_t *brdp;
- asynotify_t nt;
- asyport_t aport;
- int rc;
-
-#if DEBUG
- printf("stli_initopen(portp=%x)\n", (int) portp);
-#endif
-
- if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
- return(ENXIO);
- if (portp->state & ST_INITIALIZED)
- return(0);
- portp->state |= ST_INITIALIZED;
-
- if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
- return(rc);
-
- bzero(&nt, sizeof(asynotify_t));
- nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
- nt.signal = SG_DCD;
- if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
- sizeof(asynotify_t), 0)) < 0)
- return(rc);
-
- stli_mkasyport(portp, &aport, &portp->tty.t_termios);
- if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
- sizeof(asyport_t), 0)) < 0)
- return(rc);
-
- portp->state |= ST_GETSIGS;
- if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 1)) < 0)
- return(rc);
- if (portp->state & ST_GETSIGS) {
- portp->sigs = stli_mktiocm(portp->asig.sigvalue);
- portp->state &= ~ST_GETSIGS;
- }
-
- stli_mkasysigs(&portp->asig, 1, 1);
- if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
- sizeof(asysigs_t), 0)) < 0)
- return(rc);
-
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Shutdown the hardware of a port.
- */
-
-static int stli_shutdownclose(stliport_t *portp)
-{
- stlibrd_t *brdp;
- struct tty *tp;
- int x;
-
-#if DEBUG
- printf("stli_shutdownclose(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
- (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
-#endif
-
- if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
- return(ENXIO);
-
- tp = &portp->tty;
- stli_rawclose(brdp, portp, 0, 0);
- stli_flush(portp, (FWRITE | FREAD));
- if (tp->t_cflag & HUPCL) {
- x = spltty();
- stli_mkasysigs(&portp->asig, 0, 0);
- if (portp->state & ST_CMDING) {
- portp->state |= ST_DOSIGS;
- } else {
- stli_sendcmd(brdp, portp, A_SETSIGNALS,
- &portp->asig, sizeof(asysigs_t), 0);
- }
- splx(x);
- if (portp->dtrwait != 0) {
- portp->state |= ST_DTRWAIT;
- timeout(stli_dtrwakeup, portp, portp->dtrwait);
- }
- }
- portp->callout = 0;
- portp->state &= ~ST_INITIALIZED;
- wakeup(&portp->callout);
- wakeup(TSA_CARR_ON(tp));
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Clear the DTR waiting flag, and wake up any sleepers waiting for
- * DTR wait period to finish.
- */
-
-static void stli_dtrwakeup(void *arg)
-{
- stliport_t *portp;
-
- portp = (stliport_t *) arg;
- portp->state &= ~ST_DTRWAIT;
- wakeup(&portp->dtrwait);
-}
-
-/*****************************************************************************/
-
-/*
- * Send an open message to the slave. This will sleep waiting for the
- * acknowledgement, so must have user context. We need to co-ordinate
- * with close events here, since we don't want open and close events
- * to overlap.
- */
-
-static int stli_rawopen(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
-{
- volatile cdkhdr_t *hdrp;
- volatile cdkctrl_t *cp;
- volatile unsigned char *bits;
- int rc, x;
-
-#if DEBUG
- printf("stli_rawopen(brdp=%x,portp=%x,arg=%x,wait=%d)\n", (int) brdp,
- (int) portp, (int) arg, wait);
-#endif
-
- x = spltty();
-
-/*
- * Slave is already closing this port. This can happen if a hangup
- * occurs on this port. So we must wait until it is complete. The
- * order of opens and closes may not be preserved across shared
- * memory, so we must wait until it is complete.
- */
- while (portp->state & ST_CLOSING) {
- rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
- if (rc) {
- splx(x);
- return(rc);
- }
- }
-
-/*
- * Everything is ready now, so write the open message into shared
- * memory. Once the message is in set the service bits to say that
- * this port wants service.
- */
- EBRDENABLE(brdp);
- cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
- cp->openarg = arg;
- cp->open = 1;
- hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
- portp->portidx;
- *bits |= portp->portbit;
- EBRDDISABLE(brdp);
-
- if (wait == 0) {
- splx(x);
- return(0);
- }
-
-/*
- * Slave is in action, so now we must wait for the open acknowledgment
- * to come back.
- */
- rc = 0;
- portp->state |= ST_OPENING;
- while (portp->state & ST_OPENING) {
- rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
- if (rc) {
- splx(x);
- return(rc);
- }
- }
- splx(x);
-
- if ((rc == 0) && (portp->rc != 0))
- rc = EIO;
- return(rc);
-}
-
-/*****************************************************************************/
-
-/*
- * Send a close message to the slave. Normally this will sleep waiting
- * for the acknowledgement, but if wait parameter is 0 it will not. If
- * wait is true then must have user context (to sleep).
- */
-
-static int stli_rawclose(stlibrd_t *brdp, stliport_t *portp, unsigned long arg, int wait)
-{
- volatile cdkhdr_t *hdrp;
- volatile cdkctrl_t *cp;
- volatile unsigned char *bits;
- int rc, x;
-
-#if DEBUG
- printf("stli_rawclose(brdp=%x,portp=%x,arg=%x,wait=%d)\n", (int) brdp,
- (int) portp, (int) arg, wait);
-#endif
-
- x = spltty();
-
-/*
- * Slave is already closing this port. This can happen if a hangup
- * occurs on this port.
- */
- if (wait) {
- while (portp->state & ST_CLOSING) {
- rc = tsleep(&portp->state, (TTIPRI | PCATCH),
- "stliraw", 0);
- if (rc) {
- splx(x);
- return(rc);
- }
- }
- }
-
-/*
- * Write the close command into shared memory.
- */
- EBRDENABLE(brdp);
- cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
- cp->closearg = arg;
- cp->close = 1;
- hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
- portp->portidx;
- *bits |= portp->portbit;
- EBRDDISABLE(brdp);
-
- portp->state |= ST_CLOSING;
- if (wait == 0) {
- splx(x);
- return(0);
- }
-
-/*
- * Slave is in action, so now we must wait for the open acknowledgment
- * to come back.
- */
- rc = 0;
- while (portp->state & ST_CLOSING) {
- rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
- if (rc) {
- splx(x);
- return(rc);
- }
- }
- splx(x);
-
- if ((rc == 0) && (portp->rc != 0))
- rc = EIO;
- return(rc);
-}
-
-/*****************************************************************************/
-
-/*
- * Send a command to the slave and wait for the response. This must
- * have user context (it sleeps). This routine is generic in that it
- * can send any type of command. Its purpose is to wait for that command
- * to complete (as opposed to initiating the command then returning).
- */
-
-static int stli_cmdwait(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
- int rc, x;
-
-#if DEBUG
- printf("stli_cmdwait(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
- "copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
- (int) arg, size, copyback);
-#endif
-
- x = spltty();
- while (portp->state & ST_CMDING) {
- rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
- if (rc) {
- splx(x);
- return(rc);
- }
- }
-
- stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-
- while (portp->state & ST_CMDING) {
- rc = tsleep(&portp->state, (TTIPRI | PCATCH), "stliraw", 0);
- if (rc) {
- splx(x);
- return(rc);
- }
- }
- splx(x);
-
- if (portp->rc != 0)
- return(EIO);
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Start (or continue) the transfer of TX data on this port. If the
- * port is not currently busy then load up the interrupt ring queue
- * buffer and kick of the transmitter. If the port is running low on
- * TX data then refill the ring queue. This routine is also used to
- * activate input flow control!
- */
-
-static void stli_start(struct tty *tp)
-{
- volatile cdkasy_t *ap;
- volatile cdkhdr_t *hdrp;
- volatile unsigned char *bits;
- unsigned char *shbuf;
- stliport_t *portp;
- stlibrd_t *brdp;
- unsigned int len, stlen, head, tail, size;
- int count, x;
-
- portp = (stliport_t *) tp;
-
-#if DEBUG
- printf("stli_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp,
- portp->brdnr, portp->portnr);
-#endif
-
- x = spltty();
-
-#if VFREEBSD == 205
-/*
- * Check if the output cooked clist buffers are near empty, wake up
- * the line discipline to fill it up.
- */
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup(&tp->t_outq);
- }
- selwakeuppri(&tp->t_wsel, TTOPRI);
- }
-#endif
-
- if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
- splx(x);
- return;
- }
-
-/*
- * Copy data from the clists into the interrupt ring queue. This will
- * require at most 2 copys... What we do is calculate how many chars
- * can fit into the ring queue, and how many can fit in 1 copy. If after
- * the first copy there is still more room then do the second copy.
- */
- if (tp->t_outq.c_cc != 0) {
- brdp = stli_brds[portp->brdnr];
- if (brdp == (stlibrd_t *) NULL) {
- splx(x);
- return;
- }
-
- EBRDENABLE(brdp);
- ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
- head = (unsigned int) ap->txq.head;
- tail = (unsigned int) ap->txq.tail;
- if (tail != ((unsigned int) ap->txq.tail))
- tail = (unsigned int) ap->txq.tail;
- size = portp->txsize;
- if (head >= tail) {
- len = size - (head - tail) - 1;
- stlen = size - head;
- } else {
- len = tail - head - 1;
- stlen = len;
- }
-
- count = 0;
- shbuf = (char *) EBRDGETMEMPTR(brdp, portp->txoffset);
-
- if (len > 0) {
- stlen = MIN(len, stlen);
- count = q_to_b(&tp->t_outq, (shbuf + head), stlen);
- len -= count;
- head += count;
- if (head >= size) {
- head = 0;
- if (len > 0) {
- stlen = q_to_b(&tp->t_outq, shbuf, len);
- head += stlen;
- count += stlen;
- }
- }
- }
-
- ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
- ap->txq.head = head;
- hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
- portp->portidx;
- *bits |= portp->portbit;
- portp->state |= ST_TXBUSY;
- tp->t_state |= TS_BUSY;
-
- EBRDDISABLE(brdp);
- }
-
-#if VFREEBSD != 205
-/*
- * Do any writer wakeups.
- */
- ttwwakeup(tp);
-#endif
-
- splx(x);
-}
-
-/*****************************************************************************/
-
-/*
- * Send a new port configuration to the slave.
- */
-
-static int stli_param(struct tty *tp, struct termios *tiosp)
-{
- stlibrd_t *brdp;
- stliport_t *portp;
- asyport_t aport;
- int x, rc;
-
- portp = (stliport_t *) tp;
- if ((brdp = stli_brds[portp->brdnr]) == (stlibrd_t *) NULL)
- return(ENXIO);
-
- x = spltty();
- stli_mkasyport(portp, &aport, tiosp);
- /* can we sleep here? */
- rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
- stli_ttyoptim(portp, tiosp);
- splx(x);
- return(rc);
-}
-
-/*****************************************************************************/
-
-/*
- * Flush characters from the lower buffer. We may not have user context
- * so we cannot sleep waiting for it to complete. Also we need to check
- * if there is chars for this port in the TX cook buffer, and flush them
- * as well.
- */
-
-static void stli_flush(stliport_t *portp, int flag)
-{
- stlibrd_t *brdp;
- unsigned long ftype;
- int x;
-
-#if DEBUG
- printf("stli_flush(portp=%x,flag=%x)\n", (int) portp, flag);
-#endif
-
- if (portp == (stliport_t *) NULL)
- return;
- if ((portp->brdnr < 0) || (portp->brdnr >= stli_nrbrds))
- return;
- brdp = stli_brds[portp->brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return;
-
- x = spltty();
- if (portp->state & ST_CMDING) {
- portp->state |= (flag & FWRITE) ? ST_DOFLUSHTX : 0;
- portp->state |= (flag & FREAD) ? ST_DOFLUSHRX : 0;
- } else {
- ftype = (flag & FWRITE) ? FLUSHTX : 0;
- ftype |= (flag & FREAD) ? FLUSHRX : 0;
- portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX);
- stli_sendcmd(brdp, portp, A_FLUSH, &ftype,
- sizeof(unsigned long), 0);
- }
- if ((flag & FREAD) && (stli_rxtmpport == portp))
- stli_rxtmplen = 0;
- splx(x);
-}
-
-/*****************************************************************************/
-
-/*
- * Generic send command routine. This will send a message to the slave,
- * of the specified type with the specified argument. Must be very
- * carefull of data that will be copied out from shared memory -
- * containing command results. The command completion is all done from
- * a poll routine that does not have user coontext. Therefore you cannot
- * copy back directly into user space, or to the kernel stack of a
- * process. This routine does not sleep, so can be called from anywhere,
- * and must be called with interrupt locks set.
- */
-
-static void stli_sendcmd(stlibrd_t *brdp, stliport_t *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
- volatile cdkhdr_t *hdrp;
- volatile cdkctrl_t *cp;
- volatile unsigned char *bits;
-
-#if DEBUG
- printf("stli_sendcmd(brdp=%x,portp=%x,cmd=%x,arg=%x,size=%d,"
- "copyback=%d)\n", (int) brdp, (int) portp, (int) cmd,
- (int) arg, size, copyback);
-#endif
-
- if (portp->state & ST_CMDING) {
- printf("STALLION: command already busy, cmd=%x!\n", (int) cmd);
- return;
- }
-
- EBRDENABLE(brdp);
- cp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
- if (size > 0) {
- bcopy(arg, (void *) &(cp->args[0]), size);
- if (copyback) {
- portp->argp = arg;
- portp->argsize = size;
- }
- }
- cp->status = 0;
- cp->cmd = cmd;
- hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- bits = ((volatile unsigned char *) hdrp) + brdp->slaveoffset +
- portp->portidx;
- *bits |= portp->portbit;
- portp->state |= ST_CMDING;
- EBRDDISABLE(brdp);
-}
-
-/*****************************************************************************/
-
-/*
- * Read data from shared memory. This assumes that the shared memory
- * is enabled and that interrupts are off. Basically we just empty out
- * the shared memory buffer into the tty buffer. Must be carefull to
- * handle the case where we fill up the tty buffer, but still have
- * more chars to unload.
- */
-
-static void stli_rxprocess(stlibrd_t *brdp, stliport_t *portp)
-{
- volatile cdkasyrq_t *rp;
- volatile char *shbuf;
- struct tty *tp;
- unsigned int head, tail, size;
- unsigned int len, stlen, i;
- int ch;
-
-#if DEBUG
- printf("stli_rxprocess(brdp=%x,portp=%d)\n", (int) brdp, (int) portp);
-#endif
-
- tp = &portp->tty;
- if ((tp->t_state & TS_ISOPEN) == 0) {
- stli_flush(portp, FREAD);
- return;
- }
- if (tp->t_state & TS_TBLOCK)
- return;
-
- rp = &((volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
- head = (unsigned int) rp->head;
- if (head != ((unsigned int) rp->head))
- head = (unsigned int) rp->head;
- tail = (unsigned int) rp->tail;
- size = portp->rxsize;
- if (head >= tail) {
- len = head - tail;
- stlen = len;
- } else {
- len = size - (tail - head);
- stlen = size - tail;
- }
-
- if (len == 0)
- return;
-
- shbuf = (volatile char *) EBRDGETMEMPTR(brdp, portp->rxoffset);
-
-/*
- * If we can bypass normal LD processing then just copy direct
- * from board shared memory into the tty buffers.
- */
- if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
- if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
- ((tp->t_cflag & CRTS_IFLOW) || (tp->t_iflag & IXOFF)) &&
- ((tp->t_state & TS_TBLOCK) == 0)) {
- ch = TTYHOG - tp->t_rawq.c_cc - 1;
- len = (ch > 0) ? ch : 0;
- stlen = MIN(stlen, len);
- tp->t_state |= TS_TBLOCK;
- }
- i = b_to_q((char *) (shbuf + tail), stlen, &tp->t_rawq);
- tail += stlen;
- len -= stlen;
- if (tail >= size) {
- tail = 0;
- i += b_to_q((char *) shbuf, len, &tp->t_rawq);
- tail += len;
- }
- portp->rxlost += i;
- ttwakeup(tp);
- rp = &((volatile cdkasy_t *)
- EBRDGETMEMPTR(brdp, portp->addr))->rxq;
- rp->tail = tail;
-
- } else {
-/*
- * Copy the data from board shared memory into a local
- * memory buffer. Then feed them from here into the LD.
- * We don't want to go into board shared memory one char
- * at a time, it is too slow...
- */
- if (len > TTYHOG) {
- len = TTYHOG - 1;
- stlen = min(len, stlen);
- }
- stli_rxtmpport = portp;
- stli_rxtmplen = len;
- bcopy((char *) (shbuf + tail), &stli_rxtmpbuf[0], stlen);
- len -= stlen;
- if (len > 0)
- bcopy((char *) shbuf, &stli_rxtmpbuf[stlen], len);
-
- for (i = 0; (i < stli_rxtmplen); i++) {
- ch = (unsigned char) stli_rxtmpbuf[i];
- (*linesw[tp->t_line].l_rint)(ch, tp);
- }
- EBRDENABLE(brdp);
- rp = &((volatile cdkasy_t *)
- EBRDGETMEMPTR(brdp, portp->addr))->rxq;
- if (stli_rxtmplen == 0) {
- head = (unsigned int) rp->head;
- if (head != ((unsigned int) rp->head))
- head = (unsigned int) rp->head;
- tail = head;
- } else {
- tail += i;
- if (tail >= size)
- tail -= size;
- }
- rp->tail = tail;
- stli_rxtmpport = (stliport_t *) NULL;
- stli_rxtmplen = 0;
- }
-
- portp->state |= ST_RXING;
-}
-
-/*****************************************************************************/
-
-/*
- * Set up and carry out any delayed commands. There is only a small set
- * of slave commands that can be done "off-level". So it is not too
- * difficult to deal with them as a special case here.
- */
-
-static __inline void stli_dodelaycmd(stliport_t *portp, volatile cdkctrl_t *cp)
-{
- int cmd;
-
- if (portp->state & ST_DOSIGS) {
- if ((portp->state & ST_DOFLUSHTX) &&
- (portp->state & ST_DOFLUSHRX))
- cmd = A_SETSIGNALSF;
- else if (portp->state & ST_DOFLUSHTX)
- cmd = A_SETSIGNALSFTX;
- else if (portp->state & ST_DOFLUSHRX)
- cmd = A_SETSIGNALSFRX;
- else
- cmd = A_SETSIGNALS;
- portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX | ST_DOSIGS);
- bcopy((void *) &portp->asig, (void *) &(cp->args[0]),
- sizeof(asysigs_t));
- cp->status = 0;
- cp->cmd = cmd;
- portp->state |= ST_CMDING;
- } else if ((portp->state & ST_DOFLUSHTX) ||
- (portp->state & ST_DOFLUSHRX)) {
- cmd = ((portp->state & ST_DOFLUSHTX) ? FLUSHTX : 0);
- cmd |= ((portp->state & ST_DOFLUSHRX) ? FLUSHRX : 0);
- portp->state &= ~(ST_DOFLUSHTX | ST_DOFLUSHRX);
- bcopy((void *) &cmd, (void *) &(cp->args[0]), sizeof(int));
- cp->status = 0;
- cp->cmd = A_FLUSH;
- portp->state |= ST_CMDING;
- }
-}
-
-/*****************************************************************************/
-
-/*
- * Host command service checking. This handles commands or messages
- * coming from the slave to the host. Must have board shared memory
- * enabled and interrupts off when called. Notice that by servicing the
- * read data last we don't need to change the shared memory pointer
- * during processing (which is a slow IO operation).
- * Return value indicates if this port is still awaiting actions from
- * the slave (like open, command, or even TX data being sent). If 0
- * then port is still busy, otherwise the port request bit flag is
- * returned.
- */
-
-static __inline int stli_hostcmd(stlibrd_t *brdp, stliport_t *portp)
-{
- volatile cdkasy_t *ap;
- volatile cdkctrl_t *cp;
- asynotify_t nt;
- unsigned long oldsigs;
- unsigned int head, tail;
- int rc, donerx;
-
-#if DEBUG
- printf("stli_hostcmd(brdp=%x,portp=%x)\n", (int) brdp, (int) portp);
-#endif
-
- ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
- cp = &ap->ctrl;
-
-/*
- * Check if we are waiting for an open completion message.
- */
- if (portp->state & ST_OPENING) {
- rc = (int) cp->openarg;
- if ((cp->open == 0) && (rc != 0)) {
- if (rc > 0)
- rc--;
- cp->openarg = 0;
- portp->rc = rc;
- portp->state &= ~ST_OPENING;
- wakeup(&portp->state);
- }
- }
-
-/*
- * Check if we are waiting for a close completion message.
- */
- if (portp->state & ST_CLOSING) {
- rc = (int) cp->closearg;
- if ((cp->close == 0) && (rc != 0)) {
- if (rc > 0)
- rc--;
- cp->closearg = 0;
- portp->rc = rc;
- portp->state &= ~ST_CLOSING;
- wakeup(&portp->state);
- }
- }
-
-/*
- * Check if we are waiting for a command completion message. We may
- * need to copy out the command results associated with this command.
- */
- if (portp->state & ST_CMDING) {
- rc = cp->status;
- if ((cp->cmd == 0) && (rc != 0)) {
- if (rc > 0)
- rc--;
- if (portp->argp != (void *) NULL) {
- bcopy((void *) &(cp->args[0]), portp->argp,
- portp->argsize);
- portp->argp = (void *) NULL;
- }
- cp->status = 0;
- portp->rc = rc;
- portp->state &= ~ST_CMDING;
- stli_dodelaycmd(portp, cp);
- wakeup(&portp->state);
- }
- }
-
-/*
- * Check for any notification messages ready. This includes lots of
- * different types of events - RX chars ready, RX break received,
- * TX data low or empty in the slave, modem signals changed state.
- * Must be extremely carefull if we call to the LD, it may call
- * other routines of ours that will disable the memory...
- * Something else we need to be carefull of is race conditions on
- * marking the TX as empty...
- */
- donerx = 0;
-
- if (ap->notify) {
- struct tty *tp;
-
- nt = ap->changed;
- ap->notify = 0;
- tp = &portp->tty;
-
- if (nt.signal & SG_DCD) {
- oldsigs = portp->sigs;
- portp->sigs = stli_mktiocm(nt.sigvalue);
- portp->state &= ~ST_GETSIGS;
- (*linesw[tp->t_line].l_modem)(tp,
- (portp->sigs & TIOCM_CD));
- EBRDENABLE(brdp);
- }
- if (nt.data & DT_RXBUSY) {
- donerx++;
- stli_rxprocess(brdp, portp);
- }
- if (nt.data & DT_RXBREAK) {
- (*linesw[tp->t_line].l_rint)(TTY_BI, tp);
- EBRDENABLE(brdp);
- }
- if (nt.data & DT_TXEMPTY) {
- ap = (volatile cdkasy_t *)
- EBRDGETMEMPTR(brdp, portp->addr);
- head = (unsigned int) ap->txq.head;
- tail = (unsigned int) ap->txq.tail;
- if (tail != ((unsigned int) ap->txq.tail))
- tail = (unsigned int) ap->txq.tail;
- head = (head >= tail) ? (head - tail) :
- portp->txsize - (tail - head);
- if (head == 0) {
- portp->state &= ~ST_TXBUSY;
- tp->t_state &= ~TS_BUSY;
- }
- }
- if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
- (*linesw[tp->t_line].l_start)(tp);
- EBRDENABLE(brdp);
- }
- }
-
-/*
- * It might seem odd that we are checking for more RX chars here.
- * But, we need to handle the case where the tty buffer was previously
- * filled, but we had more characters to pass up. The slave will not
- * send any more RX notify messages until the RX buffer has been emptied.
- * But it will leave the service bits on (since the buffer is not empty).
- * So from here we can try to process more RX chars.
- */
- if ((!donerx) && (portp->state & ST_RXING)) {
- portp->state &= ~ST_RXING;
- stli_rxprocess(brdp, portp);
- }
-
- return((portp->state & (ST_OPENING | ST_CLOSING | ST_CMDING |
- ST_TXBUSY | ST_RXING)) ? 0 : 1);
-}
-
-/*****************************************************************************/
-
-/*
- * Service all ports on a particular board. Assumes that the boards
- * shared memory is enabled, and that the page pointer is pointed
- * at the cdk header structure.
- */
-
-static __inline void stli_brdpoll(stlibrd_t *brdp, volatile cdkhdr_t *hdrp)
-{
- stliport_t *portp;
- unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
- unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
- unsigned char *slavep;
- int bitpos, bitat, bitsize;
- int channr, nrdevs, slavebitchange;
-
- bitsize = brdp->bitsize;
- nrdevs = brdp->nrdevs;
-
-/*
- * Check if slave wants any service. Basically we try to do as
- * little work as possible here. There are 2 levels of service
- * bits. So if there is nothing to do we bail early. We check
- * 8 service bits at a time in the inner loop, so we can bypass
- * the lot if none of them want service.
- */
- bcopy((((unsigned char *) hdrp) + brdp->hostoffset), &hostbits[0],
- bitsize);
-
- bzero(&slavebits[0], bitsize);
- slavebitchange = 0;
-
- for (bitpos = 0; (bitpos < bitsize); bitpos++) {
- if (hostbits[bitpos] == 0)
- continue;
- channr = bitpos * 8;
- bitat = 0x1;
- for (; (channr < nrdevs); channr++, bitat <<=1) {
- if (hostbits[bitpos] & bitat) {
- portp = brdp->ports[(channr - 1)];
- if (stli_hostcmd(brdp, portp)) {
- slavebitchange++;
- slavebits[bitpos] |= bitat;
- }
- }
- }
- }
-
-/*
- * If any of the ports are no longer busy then update them in the
- * slave request bits. We need to do this after, since a host port
- * service may initiate more slave requests...
- */
- if (slavebitchange) {
- hdrp = (volatile cdkhdr_t *)
- EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- slavep = ((unsigned char *) hdrp) + brdp->slaveoffset;
- for (bitpos = 0; (bitpos < bitsize); bitpos++) {
- if (slavebits[bitpos])
- slavep[bitpos] &= ~slavebits[bitpos];
- }
- }
-}
-
-/*****************************************************************************/
-
-/*
- * Driver poll routine. This routine polls the boards in use and passes
- * messages back up to host when neccesary. This is actually very
- * CPU efficient, since we will always have the kernel poll clock, it
- * adds only a few cycles when idle (since board service can be
- * determined very easily), but when loaded generates no interrupts
- * (with their expensive associated context change).
- */
-
-static void stli_poll(void *arg)
-{
- volatile cdkhdr_t *hdrp;
- stlibrd_t *brdp;
- int brdnr, x;
-
- x = spltty();
-
-/*
- * Check each board and do any servicing required.
- */
- for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
- brdp = stli_brds[brdnr];
- if (brdp == (stlibrd_t *) NULL)
- continue;
- if ((brdp->state & BST_STARTED) == 0)
- continue;
-
- EBRDENABLE(brdp);
- hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- if (hdrp->hostreq)
- stli_brdpoll(brdp, hdrp);
- EBRDDISABLE(brdp);
- }
- splx(x);
-
- timeout(stli_poll, 0, 1);
-}
-
-/*****************************************************************************/
-
-/*
- * Translate the termios settings into the port setting structure of
- * the slave.
- */
-
-static void stli_mkasyport(stliport_t *portp, asyport_t *pp, struct termios *tiosp)
-{
-#if DEBUG
- printf("stli_mkasyport(portp=%x,pp=%x,tiosp=%d)\n", (int) portp,
- (int) pp, (int) tiosp);
-#endif
-
- bzero(pp, sizeof(asyport_t));
-
-/*
- * Start of by setting the baud, char size, parity and stop bit info.
- */
- if (tiosp->c_ispeed == 0)
- tiosp->c_ispeed = tiosp->c_ospeed;
- if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > STL_MAXBAUD))
- tiosp->c_ospeed = STL_MAXBAUD;
- pp->baudout = tiosp->c_ospeed;
- pp->baudin = pp->baudout;
-
- switch (tiosp->c_cflag & CSIZE) {
- case CS5:
- pp->csize = 5;
- break;
- case CS6:
- pp->csize = 6;
- break;
- case CS7:
- pp->csize = 7;
- break;
- default:
- pp->csize = 8;
- break;
- }
-
- if (tiosp->c_cflag & CSTOPB)
- pp->stopbs = PT_STOP2;
- else
- pp->stopbs = PT_STOP1;
-
- if (tiosp->c_cflag & PARENB) {
- if (tiosp->c_cflag & PARODD)
- pp->parity = PT_ODDPARITY;
- else
- pp->parity = PT_EVENPARITY;
- } else {
- pp->parity = PT_NOPARITY;
- }
-
- if (tiosp->c_iflag & ISTRIP)
- pp->iflag |= FI_ISTRIP;
-
-/*
- * Set up any flow control options enabled.
- */
- if (tiosp->c_iflag & IXON) {
- pp->flow |= F_IXON;
- if (tiosp->c_iflag & IXANY)
- pp->flow |= F_IXANY;
- }
- if (tiosp->c_iflag & IXOFF)
- pp->flow |= F_IXOFF;
- if (tiosp->c_cflag & CCTS_OFLOW)
- pp->flow |= F_CTSFLOW;
- if (tiosp->c_cflag & CRTS_IFLOW)
- pp->flow |= F_RTSFLOW;
-
- pp->startin = tiosp->c_cc[VSTART];
- pp->stopin = tiosp->c_cc[VSTOP];
- pp->startout = tiosp->c_cc[VSTART];
- pp->stopout = tiosp->c_cc[VSTOP];
-
-/*
- * Set up the RX char marking mask with those RX error types we must
- * catch. We can get the slave to help us out a little here, it will
- * ignore parity errors and breaks for us, and mark parity errors in
- * the data stream.
- */
- if (tiosp->c_iflag & IGNPAR)
- pp->iflag |= FI_IGNRXERRS;
- if (tiosp->c_iflag & IGNBRK)
- pp->iflag |= FI_IGNBREAK;
- if (tiosp->c_iflag & (INPCK | PARMRK))
- pp->iflag |= FI_1MARKRXERRS;
-
-/*
- * Transfer any persistent flags into the asyport structure.
- */
- pp->pflag = portp->pflag;
-}
-
-/*****************************************************************************/
-
-/*
- * Construct a slave signals structure for setting the DTR and RTS
- * signals as specified.
- */
-
-static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
-{
-#if DEBUG
- printf("stli_mkasysigs(sp=%x,dtr=%d,rts=%d)\n", (int) sp, dtr, rts);
-#endif
-
- bzero(sp, sizeof(asysigs_t));
- if (dtr >= 0) {
- sp->signal |= SG_DTR;
- sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
- }
- if (rts >= 0) {
- sp->signal |= SG_RTS;
- sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
- }
-}
-
-/*****************************************************************************/
-
-/*
- * Convert the signals returned from the slave into a local TIOCM type
- * signals value. We keep them localy in TIOCM format.
- */
-
-static long stli_mktiocm(unsigned long sigvalue)
-{
- long tiocm;
-
-#if DEBUG
- printf("stli_mktiocm(sigvalue=%x)\n", (int) sigvalue);
-#endif
-
- tiocm = 0;
- tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
- tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
- tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
- tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
- tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
- tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
- return(tiocm);
-}
-
-/*****************************************************************************/
-
-/*
- * Enable l_rint processing bypass mode if tty modes allow it.
- */
-
-static void stli_ttyoptim(stliport_t *portp, struct termios *tiosp)
-{
- struct tty *tp;
-
- tp = &portp->tty;
- if (((tiosp->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR)) == 0) &&
- (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
- (((tiosp->c_iflag & PARMRK) == 0) ||
- ((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
- ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
- (linesw[tp->t_line].l_rint == ttyinput))
- tp->t_state |= TS_CAN_BYPASS_L_RINT;
- else
- tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
- portp->hotchar = linesw[tp->t_line].l_hotchar;
-}
-
-/*****************************************************************************/
-
-/*
- * All panels and ports actually attached have been worked out. All
- * we need to do here is set up the appropriate per port data structures.
- */
-
-static int stli_initports(stlibrd_t *brdp)
-{
- stliport_t *portp;
- int i, panelnr, panelport;
-
-#if DEBUG
- printf("stli_initports(brdp=%x)\n", (int) brdp);
-#endif
-
- for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
- portp = (stliport_t *) malloc(sizeof(stliport_t), M_TTYS,
- M_NOWAIT | M_ZERO);
- if (portp == (stliport_t *) NULL) {
- printf("STALLION: failed to allocate port structure\n");
- continue;
- }
-
- portp->portnr = i;
- portp->brdnr = brdp->brdnr;
- portp->panelnr = panelnr;
- portp->initintios.c_ispeed = STL_DEFSPEED;
- portp->initintios.c_ospeed = STL_DEFSPEED;
- portp->initintios.c_cflag = STL_DEFCFLAG;
- portp->initintios.c_iflag = 0;
- portp->initintios.c_oflag = 0;
- portp->initintios.c_lflag = 0;
- bcopy(&ttydefchars[0], &portp->initintios.c_cc[0],
- sizeof(portp->initintios.c_cc));
- portp->initouttios = portp->initintios;
- portp->dtrwait = 3 * hz;
-
- panelport++;
- if (panelport >= brdp->panels[panelnr]) {
- panelport = 0;
- panelnr++;
- }
- brdp->ports[i] = portp;
- }
-
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * All the following routines are board specific hardware operations.
- */
-
-static void stli_ecpinit(stlibrd_t *brdp)
-{
- unsigned long memconf;
-
-#if DEBUG
- printf("stli_ecpinit(brdp=%d)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ECP_ATCONFR), ECP_ATSTOP);
- DELAY(10);
- outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
- DELAY(100);
-
- memconf = (brdp->paddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
- outb((brdp->iobase + ECP_ATMEMAR), memconf);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpenable(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_ecpenable(brdp=%x)\n", (int) brdp);
-#endif
- outb((brdp->iobase + ECP_ATCONFR), ECP_ATENABLE);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpdisable(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_ecpdisable(brdp=%x)\n", (int) brdp);
-#endif
- outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
-}
-
-/*****************************************************************************/
-
-static char *stli_ecpgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
- unsigned char val;
-
-#if DEBUG
- printf("stli_ecpgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
- (int) offset);
-#endif
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- val = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % ECP_ATPAGESIZE);
- val = (unsigned char) (offset / ECP_ATPAGESIZE);
- }
- outb((brdp->iobase + ECP_ATMEMPR), val);
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpreset(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_ecpreset(brdp=%x)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ECP_ATCONFR), ECP_ATSTOP);
- DELAY(10);
- outb((brdp->iobase + ECP_ATCONFR), ECP_ATDISABLE);
- DELAY(500);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpintr(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_ecpintr(brdp=%x)\n", (int) brdp);
-#endif
- outb(brdp->iobase, 0x1);
-}
-
-/*****************************************************************************/
-
-/*
- * The following set of functions act on ECP EISA boards.
- */
-
-static void stli_ecpeiinit(stlibrd_t *brdp)
-{
- unsigned long memconf;
-
-#if DEBUG
- printf("stli_ecpeiinit(brdp=%x)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ECP_EIBRDENAB), 0x1);
- outb((brdp->iobase + ECP_EICONFR), ECP_EISTOP);
- DELAY(10);
- outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
- DELAY(500);
-
- memconf = (brdp->paddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
- outb((brdp->iobase + ECP_EIMEMARL), memconf);
- memconf = (brdp->paddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
- outb((brdp->iobase + ECP_EIMEMARH), memconf);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeienable(stlibrd_t *brdp)
-{
- outb((brdp->iobase + ECP_EICONFR), ECP_EIENABLE);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeidisable(stlibrd_t *brdp)
-{
- outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
-}
-
-/*****************************************************************************/
-
-static char *stli_ecpeigetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
- unsigned char val;
-
-#if DEBUG
- printf("stli_ecpeigetmemptr(brdp=%x,offset=%x,line=%d)\n",
- (int) brdp, (int) offset, line);
-#endif
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- val = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % ECP_EIPAGESIZE);
- if (offset < ECP_EIPAGESIZE)
- val = ECP_EIENABLE;
- else
- val = ECP_EIENABLE | 0x40;
- }
- outb((brdp->iobase + ECP_EICONFR), val);
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeireset(stlibrd_t *brdp)
-{
- outb((brdp->iobase + ECP_EICONFR), ECP_EISTOP);
- DELAY(10);
- outb((brdp->iobase + ECP_EICONFR), ECP_EIDISABLE);
- DELAY(500);
-}
-
-/*****************************************************************************/
-
-/*
- * The following set of functions act on ECP MCA boards.
- */
-
-static void stli_ecpmcenable(stlibrd_t *brdp)
-{
- outb((brdp->iobase + ECP_MCCONFR), ECP_MCENABLE);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcdisable(stlibrd_t *brdp)
-{
- outb((brdp->iobase + ECP_MCCONFR), ECP_MCDISABLE);
-}
-
-/*****************************************************************************/
-
-static char *stli_ecpmcgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
- unsigned char val;
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- val = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % ECP_MCPAGESIZE);
- val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
- }
- outb((brdp->iobase + ECP_MCCONFR), val);
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcreset(stlibrd_t *brdp)
-{
- outb((brdp->iobase + ECP_MCCONFR), ECP_MCSTOP);
- DELAY(10);
- outb((brdp->iobase + ECP_MCCONFR), ECP_MCDISABLE);
- DELAY(500);
-}
-
-/*****************************************************************************/
-
-/*
- * The following routines act on ONboards.
- */
-
-static void stli_onbinit(stlibrd_t *brdp)
-{
- unsigned long memconf;
- int i;
-
-#if DEBUG
- printf("stli_onbinit(brdp=%d)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ONB_ATCONFR), ONB_ATSTOP);
- DELAY(10);
- outb((brdp->iobase + ONB_ATCONFR), ONB_ATDISABLE);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-
- memconf = (brdp->paddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
- outb((brdp->iobase + ONB_ATMEMAR), memconf);
- outb(brdp->iobase, 0x1);
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-static void stli_onbenable(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_onbenable(brdp=%x)\n", (int) brdp);
-#endif
- outb((brdp->iobase + ONB_ATCONFR), (ONB_ATENABLE | brdp->confbits));
-}
-
-/*****************************************************************************/
-
-static void stli_onbdisable(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_onbdisable(brdp=%x)\n", (int) brdp);
-#endif
- outb((brdp->iobase + ONB_ATCONFR), (ONB_ATDISABLE | brdp->confbits));
-}
-
-/*****************************************************************************/
-
-static char *stli_onbgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
-
-#if DEBUG
- printf("stli_onbgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
- (int) offset);
-#endif
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % ONB_ATPAGESIZE);
- }
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbreset(stlibrd_t *brdp)
-{
- int i;
-
-#if DEBUG
- printf("stli_onbreset(brdp=%x)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ONB_ATCONFR), ONB_ATSTOP);
- DELAY(10);
- outb((brdp->iobase + ONB_ATCONFR), ONB_ATDISABLE);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-/*
- * The following routines act on ONboard EISA.
- */
-
-static void stli_onbeinit(stlibrd_t *brdp)
-{
- unsigned long memconf;
- int i;
-
-#if DEBUG
- printf("stli_onbeinit(brdp=%d)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ONB_EIBRDENAB), 0x1);
- outb((brdp->iobase + ONB_EICONFR), ONB_EISTOP);
- DELAY(10);
- outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-
- memconf = (brdp->paddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
- outb((brdp->iobase + ONB_EIMEMARL), memconf);
- memconf = (brdp->paddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
- outb((brdp->iobase + ONB_EIMEMARH), memconf);
- outb(brdp->iobase, 0x1);
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-static void stli_onbeenable(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_onbeenable(brdp=%x)\n", (int) brdp);
-#endif
- outb((brdp->iobase + ONB_EICONFR), ONB_EIENABLE);
-}
-
-/*****************************************************************************/
-
-static void stli_onbedisable(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_onbedisable(brdp=%x)\n", (int) brdp);
-#endif
- outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
-}
-
-/*****************************************************************************/
-
-static char *stli_onbegetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
- unsigned char val;
-
-#if DEBUG
- printf("stli_onbegetmemptr(brdp=%x,offset=%x,line=%d)\n", (int) brdp,
- (int) offset, line);
-#endif
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- val = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % ONB_EIPAGESIZE);
- if (offset < ONB_EIPAGESIZE)
- val = ONB_EIENABLE;
- else
- val = ONB_EIENABLE | 0x40;
- }
- outb((brdp->iobase + ONB_EICONFR), val);
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbereset(stlibrd_t *brdp)
-{
- int i;
-
-#if DEBUG
- printf("stli_onbereset(brdp=%x)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + ONB_EICONFR), ONB_EISTOP);
- DELAY(10);
- outb((brdp->iobase + ONB_EICONFR), ONB_EIDISABLE);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-/*
- * The following routines act on Brumby boards.
- */
-
-static void stli_bbyinit(stlibrd_t *brdp)
-{
- int i;
-
-#if DEBUG
- printf("stli_bbyinit(brdp=%d)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + BBY_ATCONFR), BBY_ATSTOP);
- DELAY(10);
- outb((brdp->iobase + BBY_ATCONFR), 0);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
- outb(brdp->iobase, 0x1);
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-static char *stli_bbygetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
- unsigned char val;
-
-#if DEBUG
- printf("stli_bbygetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
- (int) offset);
-#endif
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- val = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % BBY_PAGESIZE);
- val = (unsigned char) (offset / BBY_PAGESIZE);
- }
- outb((brdp->iobase + BBY_ATCONFR), val);
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_bbyreset(stlibrd_t *brdp)
-{
- int i;
-
-#if DEBUG
- printf("stli_bbyreset(brdp=%x)\n", (int) brdp);
-#endif
-
- outb((brdp->iobase + BBY_ATCONFR), BBY_ATSTOP);
- DELAY(10);
- outb((brdp->iobase + BBY_ATCONFR), 0);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-/*
- * The following routines act on original old Stallion boards.
- */
-
-static void stli_stalinit(stlibrd_t *brdp)
-{
- int i;
-
-#if DEBUG
- printf("stli_stalinit(brdp=%d)\n", (int) brdp);
-#endif
-
- outb(brdp->iobase, 0x1);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-static char *stli_stalgetmemptr(stlibrd_t *brdp, unsigned long offset, int line)
-{
- void *ptr;
-
-#if DEBUG
- printf("stli_stalgetmemptr(brdp=%x,offset=%x)\n", (int) brdp,
- (int) offset);
-#endif
-
- if (offset > brdp->memsize) {
- printf("STALLION: shared memory pointer=%x out of range at "
- "line=%d(%d), brd=%d\n", (int) offset, line,
- __LINE__, brdp->brdnr);
- ptr = 0;
- } else {
- ptr = (char *) brdp->vaddr + (offset % STAL_PAGESIZE);
- }
- return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_stalreset(stlibrd_t *brdp)
-{
- volatile unsigned long *vecp;
- int i;
-
-#if DEBUG
- printf("stli_stalreset(brdp=%x)\n", (int) brdp);
-#endif
-
- vecp = (volatile unsigned long *) ((char *) brdp->vaddr + 0x30);
- *vecp = 0xffff0000;
- outb(brdp->iobase, 0);
- for (i = 0; (i < 1000); i++)
- DELAY(1000);
-}
-
-/*****************************************************************************/
-
-/*
- * Try to find an ECP board and initialize it. This handles only ECP
- * board types.
- */
-
-static int stli_initecp(stlibrd_t *brdp)
-{
- cdkecpsig_t sig;
- cdkecpsig_t *sigsp;
- unsigned int status, nxtid;
- int panelnr;
-
-#if DEBUG
- printf("stli_initecp(brdp=%x)\n", (int) brdp);
-#endif
-
-/*
- * Do a basic sanity check on the IO and memory addresses.
- */
- if ((brdp->iobase == 0) || (brdp->paddr == 0))
- return(EINVAL);
-
-/*
- * Based on the specific board type setup the common vars to access
- * and enable shared memory. Set all board specific information now
- * as well.
- */
- switch (brdp->brdtype) {
- case BRD_ECP:
- brdp->memsize = ECP_MEMSIZE;
- brdp->pagesize = ECP_ATPAGESIZE;
- brdp->init = stli_ecpinit;
- brdp->enable = stli_ecpenable;
- brdp->reenable = stli_ecpenable;
- brdp->disable = stli_ecpdisable;
- brdp->getmemptr = stli_ecpgetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_ecpreset;
- break;
-
- case BRD_ECPE:
- brdp->memsize = ECP_MEMSIZE;
- brdp->pagesize = ECP_EIPAGESIZE;
- brdp->init = stli_ecpeiinit;
- brdp->enable = stli_ecpeienable;
- brdp->reenable = stli_ecpeienable;
- brdp->disable = stli_ecpeidisable;
- brdp->getmemptr = stli_ecpeigetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_ecpeireset;
- break;
-
- case BRD_ECPMC:
- brdp->memsize = ECP_MEMSIZE;
- brdp->pagesize = ECP_MCPAGESIZE;
- brdp->init = NULL;
- brdp->enable = stli_ecpmcenable;
- brdp->reenable = stli_ecpmcenable;
- brdp->disable = stli_ecpmcdisable;
- brdp->getmemptr = stli_ecpmcgetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_ecpmcreset;
- break;
-
- default:
- return(EINVAL);
- }
-
-/*
- * The per-board operations structure is all setup, so now lets go
- * and get the board operational. Firstly initialize board configuration
- * registers.
- */
- EBRDINIT(brdp);
-
-/*
- * Now that all specific code is set up, enable the shared memory and
- * look for the a signature area that will tell us exactly what board
- * this is, and what it is connected to it.
- */
- EBRDENABLE(brdp);
- sigsp = (cdkecpsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
- bcopy(sigsp, &sig, sizeof(cdkecpsig_t));
- EBRDDISABLE(brdp);
-
-#if 0
- printf("%s(%d): sig-> magic=%x rom=%x panel=%x,%x,%x,%x,%x,%x,%x,%x\n",
- __file__, __LINE__, (int) sig.magic, sig.romver,
- sig.panelid[0], (int) sig.panelid[1], (int) sig.panelid[2],
- (int) sig.panelid[3], (int) sig.panelid[4],
- (int) sig.panelid[5], (int) sig.panelid[6],
- (int) sig.panelid[7]);
-#endif
-
- if (sig.magic != ECP_MAGIC)
- return(ENXIO);
-
-/*
- * Scan through the signature looking at the panels connected to the
- * board. Calculate the total number of ports as we go.
- */
- for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
- status = sig.panelid[nxtid];
- if ((status & ECH_PNLIDMASK) != nxtid)
- break;
- brdp->panelids[panelnr] = status;
- if (status & ECH_PNL16PORT) {
- brdp->panels[panelnr] = 16;
- brdp->nrports += 16;
- nxtid += 2;
- } else {
- brdp->panels[panelnr] = 8;
- brdp->nrports += 8;
- nxtid++;
- }
- brdp->nrpanels++;
- }
-
- brdp->state |= BST_FOUND;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Try to find an ONboard, Brumby or Stallion board and initialize it.
- * This handles only these board types.
- */
-
-static int stli_initonb(stlibrd_t *brdp)
-{
- cdkonbsig_t sig;
- cdkonbsig_t *sigsp;
- int i;
-
-#if DEBUG
- printf("stli_initonb(brdp=%x)\n", (int) brdp);
-#endif
-
-/*
- * Do a basic sanity check on the IO and memory addresses.
- */
- if ((brdp->iobase == 0) || (brdp->paddr == 0))
- return(EINVAL);
-
-/*
- * Based on the specific board type setup the common vars to access
- * and enable shared memory. Set all board specific information now
- * as well.
- */
- switch (brdp->brdtype) {
- case BRD_ONBOARD:
- case BRD_ONBOARD32:
- case BRD_ONBOARD2:
- case BRD_ONBOARD2_32:
- case BRD_ONBOARDRS:
- brdp->memsize = ONB_MEMSIZE;
- brdp->pagesize = ONB_ATPAGESIZE;
- brdp->init = stli_onbinit;
- brdp->enable = stli_onbenable;
- brdp->reenable = stli_onbenable;
- brdp->disable = stli_onbdisable;
- brdp->getmemptr = stli_onbgetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_onbreset;
- brdp->confbits = (brdp->paddr > 0x100000) ? ONB_HIMEMENAB : 0;
- break;
-
- case BRD_ONBOARDE:
- brdp->memsize = ONB_EIMEMSIZE;
- brdp->pagesize = ONB_EIPAGESIZE;
- brdp->init = stli_onbeinit;
- brdp->enable = stli_onbeenable;
- brdp->reenable = stli_onbeenable;
- brdp->disable = stli_onbedisable;
- brdp->getmemptr = stli_onbegetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_onbereset;
- break;
-
- case BRD_BRUMBY4:
- case BRD_BRUMBY8:
- case BRD_BRUMBY16:
- brdp->memsize = BBY_MEMSIZE;
- brdp->pagesize = BBY_PAGESIZE;
- brdp->init = stli_bbyinit;
- brdp->enable = NULL;
- brdp->reenable = NULL;
- brdp->disable = NULL;
- brdp->getmemptr = stli_bbygetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_bbyreset;
- break;
-
- case BRD_STALLION:
- brdp->memsize = STAL_MEMSIZE;
- brdp->pagesize = STAL_PAGESIZE;
- brdp->init = stli_stalinit;
- brdp->enable = NULL;
- brdp->reenable = NULL;
- brdp->disable = NULL;
- brdp->getmemptr = stli_stalgetmemptr;
- brdp->intr = stli_ecpintr;
- brdp->reset = stli_stalreset;
- break;
-
- default:
- return(EINVAL);
- }
-
-/*
- * The per-board operations structure is all setup, so now lets go
- * and get the board operational. Firstly initialize board configuration
- * registers.
- */
- EBRDINIT(brdp);
-
-/*
- * Now that all specific code is set up, enable the shared memory and
- * look for the a signature area that will tell us exactly what board
- * this is, and how many ports.
- */
- EBRDENABLE(brdp);
- sigsp = (cdkonbsig_t *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
- bcopy(sigsp, &sig, sizeof(cdkonbsig_t));
- EBRDDISABLE(brdp);
-
-#if 0
- printf("%s(%d): sig-> magic=%x:%x:%x:%x romver=%x amask=%x:%x:%x\n",
- __file__, __LINE__, sig.magic0, sig.magic1, sig.magic2,
- sig.magic3, sig.romver, sig.amask0, sig.amask1, sig.amask2);
-#endif
-
- if ((sig.magic0 != ONB_MAGIC0) || (sig.magic1 != ONB_MAGIC1) ||
- (sig.magic2 != ONB_MAGIC2) || (sig.magic3 != ONB_MAGIC3))
- return(ENXIO);
-
-/*
- * Scan through the signature alive mask and calculate how many ports
- * there are on this board.
- */
- brdp->nrpanels = 1;
- if (sig.amask1) {
- brdp->nrports = 32;
- } else {
- for (i = 0; (i < 16); i++) {
- if (((sig.amask0 << i) & 0x8000) == 0)
- break;
- }
- brdp->nrports = i;
- }
- brdp->panels[0] = brdp->nrports;
-
- brdp->state |= BST_FOUND;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Start up a running board. This routine is only called after the
- * code has been down loaded to the board and is operational. It will
- * read in the memory map, and get the show on the road...
- */
-
-static int stli_startbrd(stlibrd_t *brdp)
-{
- volatile cdkhdr_t *hdrp;
- volatile cdkmem_t *memp;
- volatile cdkasy_t *ap;
- stliport_t *portp;
- int portnr, nrdevs, i, rc, x;
-
-#if DEBUG
- printf("stli_startbrd(brdp=%x)\n", (int) brdp);
-#endif
-
- rc = 0;
-
- x = spltty();
- EBRDENABLE(brdp);
- hdrp = (volatile cdkhdr_t *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
- nrdevs = hdrp->nrdevs;
-
-#if 0
- printf("%s(%d): CDK version %d.%d.%d --> nrdevs=%d memp=%x hostp=%x "
- "slavep=%x\n", __file__, __LINE__, hdrp->ver_release,
- hdrp->ver_modification, hdrp->ver_fix, nrdevs,
- (int) hdrp->memp, (int) hdrp->hostp, (int) hdrp->slavep);
-#endif
-
- if (nrdevs < (brdp->nrports + 1)) {
- printf("STALLION: slave failed to allocate memory for all "
- "devices, devices=%d\n", nrdevs);
- brdp->nrports = nrdevs - 1;
- }
- brdp->nrdevs = nrdevs;
- brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
- brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
- brdp->bitsize = (nrdevs + 7) / 8;
- memp = (volatile cdkmem_t *) (void *) (uintptr_t) hdrp->memp;
- if (((uintptr_t) (void *) memp) > brdp->memsize) {
- printf("STALLION: corrupted shared memory region?\n");
- rc = EIO;
- goto stli_donestartup;
- }
- memp = (volatile cdkmem_t *) EBRDGETMEMPTR(brdp,
- (uintptr_t) (void *) memp);
- if (memp->dtype != TYP_ASYNCTRL) {
- printf("STALLION: no slave control device found\n");
- rc = EIO;
- goto stli_donestartup;
- }
- memp++;
-
-/*
- * Cycle through memory allocation of each port. We are guaranteed to
- * have all ports inside the first page of slave window, so no need to
- * change pages while reading memory map.
- */
- for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
- if (memp->dtype != TYP_ASYNC)
- break;
- portp = brdp->ports[portnr];
- if (portp == (stliport_t *) NULL)
- break;
- portp->devnr = i;
- portp->addr = memp->offset;
- portp->reqidx = (unsigned char) (i * 8 / nrdevs);
- portp->reqbit = (unsigned char) (0x1 << portp->reqidx);
- portp->portidx = (unsigned char) (i / 8);
- portp->portbit = (unsigned char) (0x1 << (i % 8));
- }
-
- hdrp->slavereq = 0xff;
-
-/*
- * For each port setup a local copy of the RX and TX buffer offsets
- * and sizes. We do this separate from the above, because we need to
- * move the shared memory page...
- */
- for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
- portp = brdp->ports[portnr];
- if (portp == (stliport_t *) NULL)
- break;
- if (portp->addr == 0)
- break;
- ap = (volatile cdkasy_t *) EBRDGETMEMPTR(brdp, portp->addr);
- if (ap != (volatile cdkasy_t *) NULL) {
- portp->rxsize = ap->rxq.size;
- portp->txsize = ap->txq.size;
- portp->rxoffset = ap->rxq.offset;
- portp->txoffset = ap->txq.offset;
- }
- }
-
-stli_donestartup:
- EBRDDISABLE(brdp);
- splx(x);
-
- if (rc == 0)
- brdp->state |= BST_STARTED;
-
- if (stli_doingtimeout == 0) {
- timeout(stli_poll, 0, 1);
- stli_doingtimeout++;
- }
-
- return(rc);
-}
-
-/*****************************************************************************/
-
-/*
- * Probe and initialize the specified board.
- */
-
-static int stli_brdinit(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_brdinit(brdp=%x)\n", (int) brdp);
-#endif
-
- stli_brds[brdp->brdnr] = brdp;
-
- switch (brdp->brdtype) {
- case BRD_ECP:
- case BRD_ECPE:
- case BRD_ECPMC:
- stli_initecp(brdp);
- break;
- case BRD_ONBOARD:
- case BRD_ONBOARDE:
- case BRD_ONBOARD2:
- case BRD_ONBOARD32:
- case BRD_ONBOARD2_32:
- case BRD_ONBOARDRS:
- case BRD_BRUMBY4:
- case BRD_BRUMBY8:
- case BRD_BRUMBY16:
- case BRD_STALLION:
- stli_initonb(brdp);
- break;
- case BRD_EASYIO:
- case BRD_ECH:
- case BRD_ECHMC:
- case BRD_ECHPCI:
- printf("STALLION: %s board type not supported in this driver\n",
- stli_brdnames[brdp->brdtype]);
- return(ENODEV);
- default:
- printf("STALLION: unit=%d is unknown board type=%d\n",
- brdp->brdnr, brdp->brdtype);
- return(ENODEV);
- }
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Finish off the remaining initialization for a board.
- */
-
-static int stli_brdattach(stlibrd_t *brdp)
-{
-#if DEBUG
- printf("stli_brdattach(brdp=%x)\n", (int) brdp);
-#endif
-
-#if 0
- if ((brdp->state & BST_FOUND) == 0) {
- printf("STALLION: %s board not found, unit=%d io=%x mem=%x\n",
- stli_brdnames[brdp->brdtype], brdp->brdnr,
- brdp->iobase, (int) brdp->paddr);
- return(ENXIO);
- }
-#endif
-
- stli_initports(brdp);
- printf("stli%d: %s (driver version %s), unit=%d nrpanels=%d "
- "nrports=%d\n", brdp->unitid, stli_brdnames[brdp->brdtype],
- stli_drvversion, brdp->brdnr, brdp->nrpanels, brdp->nrports);
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Check for possible shared memory sharing between boards.
- * FIX: need to start this optimization somewhere...
- */
-
-#ifdef notdef
-static int stli_chksharemem()
-{
- stlibrd_t *brdp, *nxtbrdp;
- int i, j;
-
-#if DEBUG
- printf("stli_chksharemem()\n");
-#endif
-
-/*
- * All found boards are initialized. Now for a little optimization, if
- * no boards are sharing the "shared memory" regions then we can just
- * leave them all enabled. This is in fact the usual case.
- */
- stli_shared = 0;
- if (stli_nrbrds > 1) {
- for (i = 0; (i < stli_nrbrds); i++) {
- brdp = stli_brds[i];
- if (brdp == (stlibrd_t *) NULL)
- continue;
- for (j = i + 1; (j < stli_nrbrds); j++) {
- nxtbrdp = stli_brds[j];
- if (nxtbrdp == (stlibrd_t *) NULL)
- continue;
- if ((brdp->paddr >= nxtbrdp->paddr) &&
- (brdp->paddr <= (nxtbrdp->paddr +
- nxtbrdp->memsize - 1))) {
- stli_shared++;
- break;
- }
- }
- }
- }
-
- if (stli_shared == 0) {
- for (i = 0; (i < stli_nrbrds); i++) {
- brdp = stli_brds[i];
- if (brdp == (stlibrd_t *) NULL)
- continue;
- if (brdp->state & BST_FOUND) {
- EBRDENABLE(brdp);
- brdp->enable = NULL;
- brdp->disable = NULL;
- }
- }
- }
-
- return(0);
-}
-#endif /* notdef */
-
-/*****************************************************************************/
-
-/*
- * Return the board stats structure to user app.
- */
-
-static int stli_getbrdstats(caddr_t data)
-{
- stlibrd_t *brdp;
- int i;
-
-#if DEBUG
- printf("stli_getbrdstats(data=%p)\n", (void *) data);
-#endif
-
- stli_brdstats = *((combrd_t *) data);
- if (stli_brdstats.brd >= STL_MAXBRDS)
- return(-ENODEV);
- brdp = stli_brds[stli_brdstats.brd];
- if (brdp == (stlibrd_t *) NULL)
- return(-ENODEV);
-
- bzero(&stli_brdstats, sizeof(combrd_t));
- stli_brdstats.brd = brdp->brdnr;
- stli_brdstats.type = brdp->brdtype;
- stli_brdstats.hwid = 0;
- stli_brdstats.state = brdp->state;
- stli_brdstats.ioaddr = brdp->iobase;
- stli_brdstats.memaddr = brdp->paddr;
- stli_brdstats.nrpanels = brdp->nrpanels;
- stli_brdstats.nrports = brdp->nrports;
- for (i = 0; (i < brdp->nrpanels); i++) {
- stli_brdstats.panels[i].panel = i;
- stli_brdstats.panels[i].hwid = brdp->panelids[i];
- stli_brdstats.panels[i].nrports = brdp->panels[i];
- }
-
- *((combrd_t *) data) = stli_brdstats;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Resolve the referenced port number into a port struct pointer.
- */
-
-static stliport_t *stli_getport(int brdnr, int panelnr, int portnr)
-{
- stlibrd_t *brdp;
- int i;
-
- if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
- return((stliport_t *) NULL);
- brdp = stli_brds[brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return((stliport_t *) NULL);
- for (i = 0; (i < panelnr); i++)
- portnr += brdp->panels[i];
- if ((portnr < 0) || (portnr >= brdp->nrports))
- return((stliport_t *) NULL);
- return(brdp->ports[portnr]);
-}
-
-/*****************************************************************************/
-
-/*
- * Return the port stats structure to user app. A NULL port struct
- * pointer passed in means that we need to find out from the app
- * what port to get stats for (used through board control device).
- */
-
-static int stli_getportstats(stliport_t *portp, caddr_t data)
-{
- stlibrd_t *brdp;
- int rc;
-
- if (portp == (stliport_t *) NULL) {
- stli_comstats = *((comstats_t *) data);
- portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
- stli_comstats.port);
- if (portp == (stliport_t *) NULL)
- return(-ENODEV);
- }
-
- brdp = stli_brds[portp->brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return(-ENODEV);
-
- if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS, &stli_cdkstats,
- sizeof(asystats_t), 1)) < 0)
- return(rc);
-
- stli_comstats.brd = portp->brdnr;
- stli_comstats.panel = portp->panelnr;
- stli_comstats.port = portp->portnr;
- stli_comstats.state = portp->state;
- /*stli_comstats.flags = portp->flags;*/
- stli_comstats.ttystate = portp->tty.t_state;
- stli_comstats.cflags = portp->tty.t_cflag;
- stli_comstats.iflags = portp->tty.t_iflag;
- stli_comstats.oflags = portp->tty.t_oflag;
- stli_comstats.lflags = portp->tty.t_lflag;
-
- stli_comstats.txtotal = stli_cdkstats.txchars;
- stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
- stli_comstats.txbuffered = stli_cdkstats.txringq;
- stli_comstats.rxbuffered = stli_cdkstats.rxringq;
- stli_comstats.rxoverrun = stli_cdkstats.overruns;
- stli_comstats.rxparity = stli_cdkstats.parity;
- stli_comstats.rxframing = stli_cdkstats.framing;
- stli_comstats.rxlost = stli_cdkstats.ringover + portp->rxlost;
- stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
- stli_comstats.txbreaks = stli_cdkstats.txbreaks;
- stli_comstats.txxon = stli_cdkstats.txstart;
- stli_comstats.txxoff = stli_cdkstats.txstop;
- stli_comstats.rxxon = stli_cdkstats.rxstart;
- stli_comstats.rxxoff = stli_cdkstats.rxstop;
- stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
- stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
- stli_comstats.modem = stli_cdkstats.dcdcnt;
- stli_comstats.hwid = stli_cdkstats.hwid;
- stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
-
- *((comstats_t *) data) = stli_comstats;;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stli_clrportstats(stliport_t *portp, caddr_t data)
-{
- stlibrd_t *brdp;
- int rc;
-
- if (portp == (stliport_t *) NULL) {
- stli_comstats = *((comstats_t *) data);
- portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
- stli_comstats.port);
- if (portp == (stliport_t *) NULL)
- return(-ENODEV);
- }
-
- brdp = stli_brds[portp->brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return(-ENODEV);
-
- if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, 0, 0, 0)) < 0)
- return(rc);
-
- portp->rxlost = 0;
- bzero(&stli_comstats, sizeof(comstats_t));
- stli_comstats.brd = portp->brdnr;
- stli_comstats.panel = portp->panelnr;
- stli_comstats.port = portp->portnr;
-
- *((comstats_t *) data) = stli_comstats;;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Code to handle a "staliomem" read and write operations. This device
- * is the contents of the board shared memory. It is used for down
- * loading the slave image (and debugging :-)
- */
-
-STATIC int stli_memrw(dev_t dev, struct uio *uiop, int flag)
-{
- stlibrd_t *brdp;
- void *memptr;
- int brdnr, size, n, error, x;
-
-#if DEBUG
- printf("stli_memrw(dev=%x,uiop=%x,flag=%x)\n", (int) dev,
- (int) uiop, flag);
-#endif
-
- brdnr = minor(dev) & 0x7;
- brdp = stli_brds[brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return(ENODEV);
- if (brdp->state == 0)
- return(ENODEV);
-
- if (uiop->uio_offset >= brdp->memsize)
- return(0);
-
- error = 0;
- size = brdp->memsize - uiop->uio_offset;
-
- x = spltty();
- EBRDENABLE(brdp);
- while (size > 0) {
- memptr = (void *) EBRDGETMEMPTR(brdp, uiop->uio_offset);
- n = MIN(size, (brdp->pagesize -
- (((unsigned long) uiop->uio_offset) % brdp->pagesize)));
- error = uiomove(memptr, n, uiop);
- if ((uiop->uio_resid == 0) || error)
- break;
- }
- EBRDDISABLE(brdp);
- splx(x);
-
- return(error);
-}
-
-/*****************************************************************************/
-
-/*
- * The "staliomem" device is also required to do some special operations
- * on the board. We need to be able to send an interrupt to the board,
- * reset it, and start/stop it.
- */
-
-static int stli_memioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
- struct thread *td)
-{
- stlibrd_t *brdp;
- int brdnr, rc;
-
-#if DEBUG
- printf("stli_memioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n",
- devtoname(dev), cmd, (void *) data, flag);
-#endif
-
- brdnr = minor(dev) & 0x7;
- brdp = stli_brds[brdnr];
- if (brdp == (stlibrd_t *) NULL)
- return(ENODEV);
- if (brdp->state == 0)
- return(ENODEV);
-
- rc = 0;
-
- switch (cmd) {
- case STL_BINTR:
- EBRDINTR(brdp);
- break;
- case STL_BSTART:
- rc = stli_startbrd(brdp);
- break;
- case STL_BSTOP:
- brdp->state &= ~BST_STARTED;
- break;
- case STL_BRESET:
- brdp->state &= ~BST_STARTED;
- EBRDRESET(brdp);
- if (stli_shared == 0) {
- if (brdp->reenable != NULL)
- (* brdp->reenable)(brdp);
- }
- break;
- case COM_GETPORTSTATS:
- rc = stli_getportstats((stliport_t *) NULL, data);
- break;
- case COM_CLRPORTSTATS:
- rc = stli_clrportstats((stliport_t *) NULL, data);
- break;
- case COM_GETBRDSTATS:
- rc = stli_getbrdstats(data);
- break;
- default:
- rc = ENOTTY;
- break;
- }
-
- return(rc);
-}
-
-/*****************************************************************************/
diff --git a/sys/i386/isa/stallion.c b/sys/i386/isa/stallion.c
deleted file mode 100644
index 9a99f74..0000000
--- a/sys/i386/isa/stallion.c
+++ /dev/null
@@ -1,3072 +0,0 @@
-/*****************************************************************************/
-
-/*
- * stallion.c -- stallion multiport serial driver.
- *
- * Copyright (c) 1995-1996 Greg Ungerer (gerg@stallion.oz.au).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by Greg Ungerer.
- * 4. Neither the name of the author nor the names of any co-contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*****************************************************************************/
-
-#define TTYDEFCHARS 1
-
-#include "opt_compat.h"
-#include "opt_tty.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/tty.h>
-#include <sys/conf.h>
-#include <sys/fcntl.h>
-#include <sys/bus.h>
-#include <i386/isa/isa_device.h>
-#include <i386/isa/ic/scd1400.h>
-#include <machine/comstats.h>
-
-#warning "The stallion pci attachment is broken and not compiled"
-#define NPCI 0
-#if NPCI > 0
-#ifndef COMPAT_OLDPCI
-#error "The stallion pci driver requires the old pci compatibility shims"
-#endif
-#include <dev/pci/pcivar.h>
-#include <dev/pci/pcireg.h>
-#endif
-
-/*****************************************************************************/
-
-/*
- * Define the version level of the kernel - so we can compile in the
- * appropriate bits of code. By default this will compile for a 2.1
- * level kernel.
- */
-#define VFREEBSD 220
-
-#if VFREEBSD >= 220
-#define STATIC static
-#else
-#define STATIC
-#endif
-
-/*****************************************************************************/
-
-/*
- * Define different board types. At the moment I have only declared
- * those boards that this driver supports. But I will use the standard
- * "assigned" board numbers. In the future this driver will support
- * some of the other Stallion boards. Currently supported boards are
- * abbreviated as EIO = EasyIO and ECH = EasyConnection 8/32.
- */
-#define BRD_EASYIO 20
-#define BRD_ECH 21
-#define BRD_ECHMC 22
-#define BRD_ECHPCI 26
-
-/*
- * When using the BSD "config" stuff there is no easy way to specifiy
- * a secondary IO address region. So it is hard wired here. Also the
- * shared interrupt information is hard wired here...
- */
-static unsigned int stl_ioshared = 0x280;
-static unsigned int stl_irqshared = 0;
-
-/*****************************************************************************/
-
-/*
- * Define important driver limitations.
- */
-#define STL_MAXBRDS 8
-#define STL_MAXPANELS 4
-#define STL_PORTSPERPANEL 16
-#define STL_PORTSPERBRD 64
-
-/*
- * Define the important minor number break down bits. These have been
- * chosen to be "compatible" with the standard sio driver minor numbers.
- * Extra high bits are used to distinguish between boards.
- */
-#define STL_CALLOUTDEV 0x80
-#define STL_CTRLLOCK 0x40
-#define STL_CTRLINIT 0x20
-#define STL_CTRLDEV (STL_CTRLLOCK | STL_CTRLINIT)
-
-#define STL_MEMDEV 0x07000000
-
-#define STL_DEFSPEED TTYDEF_SPEED
-#define STL_DEFCFLAG (CS8 | CREAD | HUPCL)
-
-/*
- * I haven't really decided (or measured) what buffer sizes give
- * a good balance between performance and memory usage. These seem
- * to work pretty well...
- */
-#define STL_RXBUFSIZE 2048
-#define STL_TXBUFSIZE 2048
-
-#define STL_TXBUFLOW (STL_TXBUFSIZE / 4)
-#define STL_RXBUFHIGH (3 * STL_RXBUFSIZE / 4)
-
-/*****************************************************************************/
-
-/*
- * Define our local driver identity first. Set up stuff to deal with
- * all the local structures required by a serial tty driver.
- */
-static const char stl_drvname[] = "stl";
-static const char stl_longdrvname[] = "Stallion Multiport Serial Driver";
-static const char stl_drvversion[] = "1.0.0";
-static int stl_brdprobed[STL_MAXBRDS];
-
-static int stl_nrbrds = 0;
-static int stl_doingtimeout = 0;
-
-static const char __file__[] = /*__FILE__*/ "stallion.c";
-
-/*
- * Define global stats structures. Not used often, and can be
- * re-used for each stats call.
- */
-static combrd_t stl_brdstats;
-static comstats_t stl_comstats;
-
-/*****************************************************************************/
-
-/*
- * Define a set of structures to hold all the board/panel/port info
- * for our ports. These will be dynamically allocated as required.
- */
-
-/*
- * Define a ring queue structure for each port. This will hold the
- * TX data waiting to be output. Characters are fed into this buffer
- * from the line discipline (or even direct from user space!) and
- * then fed into the UARTs during interrupts. Will use a clasic ring
- * queue here for this. The good thing about this type of ring queue
- * is that the head and tail pointers can be updated without interrupt
- * protection - since "write" code only needs to change the head, and
- * interrupt code only needs to change the tail.
- */
-typedef struct {
- char *buf;
- char *endbuf;
- char *head;
- char *tail;
-} stlrq_t;
-
-/*
- * Port, panel and board structures to hold status info about each.
- * The board structure contains pointers to structures for each panel
- * connected to it, and in turn each panel structure contains pointers
- * for each port structure for each port on that panel. Note that
- * the port structure also contains the board and panel number that it
- * is associated with, this makes it (fairly) easy to get back to the
- * board/panel info for a port. Also note that the tty struct is at
- * the top of the structure, this is important, since the code uses
- * this fact to get the port struct pointer from the tty struct
- * pointer!
- */
-typedef struct {
- struct tty tty;
- int portnr;
- int panelnr;
- int brdnr;
- int ioaddr;
- int uartaddr;
- int pagenr;
- int callout;
- int brklen;
- int dtrwait;
- int dotimestamp;
- int waitopens;
- int hotchar;
- unsigned int state;
- unsigned int hwid;
- unsigned int sigs;
- unsigned int rxignoremsk;
- unsigned int rxmarkmsk;
- unsigned long clk;
- struct termios initintios;
- struct termios initouttios;
- struct termios lockintios;
- struct termios lockouttios;
- struct timeval timestamp;
- comstats_t stats;
- stlrq_t tx;
- stlrq_t rx;
- stlrq_t rxstatus;
-} stlport_t;
-
-typedef struct {
- int panelnr;
- int brdnr;
- int pagenr;
- int nrports;
- int iobase;
- unsigned int hwid;
- unsigned int ackmask;
- stlport_t *ports[STL_PORTSPERPANEL];
-} stlpanel_t;
-
-typedef struct {
- int brdnr;
- int brdtype;
- int unitid;
- int state;
- int nrpanels;
- int nrports;
- int irq;
- int irqtype;
- unsigned int ioaddr1;
- unsigned int ioaddr2;
- unsigned int iostatus;
- unsigned int ioctrl;
- unsigned int ioctrlval;
- unsigned int hwid;
- unsigned long clk;
- stlpanel_t *panels[STL_MAXPANELS];
- stlport_t *ports[STL_PORTSPERBRD];
-} stlbrd_t;
-
-static stlbrd_t *stl_brds[STL_MAXBRDS];
-
-/*
- * Per board state flags. Used with the state field of the board struct.
- * Not really much here yet!
- */
-#define BRD_FOUND 0x1
-
-/*
- * Define the port structure state flags. These set of flags are
- * modified at interrupt time - so setting and reseting them needs
- * to be atomic.
- */
-#define ASY_TXLOW 0x1
-#define ASY_RXDATA 0x2
-#define ASY_DCDCHANGE 0x4
-#define ASY_DTRWAIT 0x8
-#define ASY_RTSFLOW 0x10
-#define ASY_RTSFLOWMODE 0x20
-#define ASY_CTSFLOWMODE 0x40
-
-#define ASY_ACTIVE (ASY_TXLOW | ASY_RXDATA | ASY_DCDCHANGE)
-
-/*
- * Define an array of board names as printable strings. Handy for
- * referencing boards when printing trace and stuff.
- */
-static char *stl_brdnames[] = {
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- "EasyIO",
- "EC8/32-AT",
- "EC8/32-MC",
- (char *) NULL,
- (char *) NULL,
- (char *) NULL,
- "EC8/32-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- * Hardware ID bits for the EasyIO and ECH boards. These defines apply
- * to the directly accessible io ports of these boards (not the cd1400
- * uarts - they are in scd1400.h).
- */
-#define EIO_8PORTRS 0x04
-#define EIO_4PORTRS 0x05
-#define EIO_8PORTDI 0x00
-#define EIO_8PORTM 0x06
-#define EIO_IDBITMASK 0x07
-#define EIO_INTRPEND 0x08
-#define EIO_INTEDGE 0x00
-#define EIO_INTLEVEL 0x08
-
-#define ECH_ID 0xa0
-#define ECH_IDBITMASK 0xe0
-#define ECH_BRDENABLE 0x08
-#define ECH_BRDDISABLE 0x00
-#define ECH_INTENABLE 0x01
-#define ECH_INTDISABLE 0x00
-#define ECH_INTLEVEL 0x02
-#define ECH_INTEDGE 0x00
-#define ECH_INTRPEND 0x01
-#define ECH_BRDRESET 0x01
-
-#define ECHMC_INTENABLE 0x01
-#define ECHMC_BRDRESET 0x02
-
-#define ECH_PNLSTATUS 2
-#define ECH_PNL16PORT 0x20
-#define ECH_PNLIDMASK 0x07
-#define ECH_PNLINTRPEND 0x80
-#define ECH_ADDR2MASK 0x1e0
-
-#define EIO_CLK 25000000
-#define EIO_CLK8M 20000000
-#define ECH_CLK EIO_CLK
-
-/*
- * Define the offsets within the register bank for all io registers.
- * These io address offsets are common to both the EIO and ECH.
- */
-#define EREG_ADDR 0
-#define EREG_DATA 4
-#define EREG_RXACK 5
-#define EREG_TXACK 6
-#define EREG_MDACK 7
-
-#define EREG_BANKSIZE 8
-
-/*
- * Define the PCI vendor and device id for ECH8/32-PCI.
- */
-#define STL_PCIDEVID 0xd001100b
-
-/*
- * Define the vector mapping bits for the programmable interrupt board
- * hardware. These bits encode the interrupt for the board to use - it
- * is software selectable (except the EIO-8M).
- */
-static unsigned char stl_vecmap[] = {
- 0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
- 0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
-};
-
-/*
- * Set up enable and disable macros for the ECH boards. They require
- * the secondary io address space to be activated and deactivated.
- * This way all ECH boards can share their secondary io region.
- * If this is an ECH-PCI board then also need to set the page pointer
- * to point to the correct page.
- */
-#define BRDENABLE(brdnr,pagenr) \
- if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
- outb(stl_brds[(brdnr)]->ioctrl, \
- (stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE));\
- else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI) \
- outb(stl_brds[(brdnr)]->ioctrl, (pagenr));
-
-#define BRDDISABLE(brdnr) \
- if (stl_brds[(brdnr)]->brdtype == BRD_ECH) \
- outb(stl_brds[(brdnr)]->ioctrl, \
- (stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE));
-
-/*
- * Define the cd1400 baud rate clocks. These are used when calculating
- * what clock and divisor to use for the required baud rate. Also
- * define the maximum baud rate allowed, and the default base baud.
- */
-static int stl_cd1400clkdivs[] = {
- CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
-};
-
-#define STL_MAXBAUD 230400
-
-/*****************************************************************************/
-
-/*
- * Define macros to extract a brd and port number from a minor number.
- * This uses the extended minor number range in the upper 2 bytes of
- * the device number. This gives us plenty of minor numbers to play
- * with...
- */
-#define MKDEV2BRD(m) ((minor(m) & 0x00700000) >> 20)
-#define MKDEV2PORT(m) ((minor(m) & 0x1f) | ((minor(m) & 0x00010000) >> 11))
-
-/*
- * Define some handy local macros...
- */
-#ifndef MIN
-#define MIN(a,b) (((a) <= (b)) ? (a) : (b))
-#endif
-
-/*****************************************************************************/
-
-/*
- * Declare all those functions in this driver! First up is the set of
- * externally visible functions.
- */
-
-static int stlprobe(struct isa_device *idp);
-static int stlattach(struct isa_device *idp);
-
-STATIC d_open_t stlopen;
-STATIC d_close_t stlclose;
-STATIC d_ioctl_t stlioctl;
-
-/*
- * Internal function prototypes.
- */
-static stlport_t *stl_dev2port(dev_t dev);
-static int stl_findfreeunit(void);
-static int stl_rawopen(stlport_t *portp);
-static int stl_rawclose(stlport_t *portp);
-static int stl_param(struct tty *tp, struct termios *tiosp);
-static void stl_start(struct tty *tp);
-static void stl_stop(struct tty *tp, int);
-static void stl_ttyoptim(stlport_t *portp, struct termios *tiosp);
-static void stl_dotimeout(void);
-static void stl_poll(void *arg);
-static void stl_rxprocess(stlport_t *portp);
-static void stl_dtrwakeup(void *arg);
-static int stl_brdinit(stlbrd_t *brdp);
-static int stl_initeio(stlbrd_t *brdp);
-static int stl_initech(stlbrd_t *brdp);
-static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-static ointhand2_t stlintr;
-static __inline void stl_txisr(stlpanel_t *panelp, int ioaddr);
-static __inline void stl_rxisr(stlpanel_t *panelp, int ioaddr);
-static __inline void stl_mdmisr(stlpanel_t *panelp, int ioaddr);
-static void stl_setreg(stlport_t *portp, int regnr, int value);
-static int stl_getreg(stlport_t *portp, int regnr);
-static int stl_updatereg(stlport_t *portp, int regnr, int value);
-static int stl_getsignals(stlport_t *portp);
-static void stl_setsignals(stlport_t *portp, int dtr, int rts);
-static void stl_flowcontrol(stlport_t *portp, int hw, int sw);
-static void stl_ccrwait(stlport_t *portp);
-static void stl_enablerxtx(stlport_t *portp, int rx, int tx);
-static void stl_startrxtx(stlport_t *portp, int rx, int tx);
-static void stl_disableintrs(stlport_t *portp);
-static void stl_sendbreak(stlport_t *portp, long len);
-static void stl_flush(stlport_t *portp, int flag);
-static int stl_memioctl(dev_t dev, unsigned long cmd, caddr_t data,
- int flag, struct thread *td);
-static int stl_getbrdstats(caddr_t data);
-static int stl_getportstats(stlport_t *portp, caddr_t data);
-static int stl_clrportstats(stlport_t *portp, caddr_t data);
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
-
-#if NPCI > 0
-static const char *stlpciprobe(pcici_t tag, pcidi_t type);
-static void stlpciattach(pcici_t tag, int unit);
-static void stlpciintr(void * arg);
-#endif
-
-/*****************************************************************************/
-
-/*
- * Declare the driver isa structure.
- */
-struct isa_driver stldriver = {
- INTR_TYPE_TTY,
- stlprobe,
- stlattach,
- "stl"
-};
-COMPAT_ISA_DRIVER(stl, stldriver);
-
-/*****************************************************************************/
-
-#if NPCI > 0
-
-/*
- * Declare the driver pci structure.
- */
-static unsigned long stl_count;
-
-static struct pci_device stlpcidriver = {
- "stl",
- stlpciprobe,
- stlpciattach,
- &stl_count,
- NULL,
-};
-
-COMPAT_PCI_DRIVER (stlpci, stlpcidriver);
-
-#endif
-
-/*****************************************************************************/
-
-#if VFREEBSD >= 220
-
-/*
- * FreeBSD-2.2+ kernel linkage.
- */
-
-static struct cdevsw stl_cdevsw = {
- .d_version = D_VERSION,
- .d_open = stlopen,
- .d_close = stlclose,
- .d_ioctl = stlioctl,
- .d_name = "stl",
- .d_flags = D_TTY | D_NEEDGIANT,
-};
-
-#endif
-
-/*****************************************************************************/
-
-/*
- * Probe for some type of EasyIO or EasyConnection 8/32 board at
- * the supplied address. All we do is check if we can find the
- * board ID for the board... (Note, PCI boards not checked here,
- * they are done in the stlpciprobe() routine).
- */
-
-static int stlprobe(struct isa_device *idp)
-{
- unsigned int status;
-
-#if DEBUG
- printf("stlprobe(idp=%x): unit=%d iobase=%x\n", (int) idp,
- idp->id_unit, idp->id_iobase);
-#endif
-
- if (idp->id_unit > STL_MAXBRDS)
- return(0);
-
- status = inb(idp->id_iobase + 1);
- if ((status & ECH_IDBITMASK) == ECH_ID) {
- stl_brdprobed[idp->id_unit] = BRD_ECH;
- return(1);
- }
-
- status = inb(idp->id_iobase + 2);
- switch (status & EIO_IDBITMASK) {
- case EIO_8PORTRS:
- case EIO_8PORTM:
- case EIO_8PORTDI:
- case EIO_4PORTRS:
- stl_brdprobed[idp->id_unit] = BRD_EASYIO;
- return(1);
- default:
- break;
- }
-
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Find an available internal board number (unit number). The problem
- * is that the same unit numbers can be assigned to different boards
- * detected during the ISA and PCI initialization phases.
- */
-
-static int stl_findfreeunit()
-{
- int i;
-
- for (i = 0; (i < STL_MAXBRDS); i++)
- if (stl_brds[i] == (stlbrd_t *) NULL)
- break;
- return((i >= STL_MAXBRDS) ? -1 : i);
-}
-
-/*****************************************************************************/
-
-/*
- * Allocate resources for and initialize the specified board.
- */
-
-static int stlattach(struct isa_device *idp)
-{
- stlbrd_t *brdp;
-
-#if DEBUG
- printf("stlattach(idp=%p): unit=%d iobase=%x\n", (void *) idp,
- idp->id_unit, idp->id_iobase);
-#endif
-
- idp->id_ointr = stlintr;
-
- brdp = (stlbrd_t *) malloc(sizeof(stlbrd_t), M_TTYS, M_NOWAIT | M_ZERO);
- if (brdp == (stlbrd_t *) NULL) {
- printf("STALLION: failed to allocate memory (size=%d)\n",
- sizeof(stlbrd_t));
- return(0);
- }
-
- if ((brdp->brdnr = stl_findfreeunit()) < 0) {
- printf("STALLION: too many boards found, max=%d\n",
- STL_MAXBRDS);
- return(0);
- }
- if (brdp->brdnr >= stl_nrbrds)
- stl_nrbrds = brdp->brdnr + 1;
-
- brdp->unitid = idp->id_unit;
- brdp->brdtype = stl_brdprobed[idp->id_unit];
- brdp->ioaddr1 = idp->id_iobase;
- brdp->ioaddr2 = stl_ioshared;
- brdp->irq = ffs(idp->id_irq) - 1;
- brdp->irqtype = stl_irqshared;
- stl_brdinit(brdp);
-
- if (0) {
- make_dev(&stl_cdevsw, 0, 0, 0, 0, "stallion_is_broken");
- }
- return(1);
-}
-
-/*****************************************************************************/
-
-#if NPCI > 0
-
-/*
- * Probe specifically for the PCI boards. We need to be a little
- * carefull here, since it looks sort like a Nat Semi IDE chip...
- */
-
-static const char *stlpciprobe(pcici_t tag, pcidi_t type)
-{
- unsigned long class;
-
-#if DEBUG
- printf("stlpciprobe(tag=%x,type=%x)\n", (int) &tag, (int) type);
-#endif
-
- switch (type) {
- case STL_PCIDEVID:
- break;
- default:
- return((char *) NULL);
- }
-
- class = pci_conf_read(tag, PCI_CLASS_REG);
- if ((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE)
- return((char *) NULL);
-
- return("Stallion EasyConnection 8/32-PCI");
-}
-
-/*****************************************************************************/
-
-/*
- * Allocate resources for and initialize the specified PCI board.
- */
-
-void stlpciattach(pcici_t tag, int unit)
-{
- stlbrd_t *brdp;
-
-#if DEBUG
- printf("stlpciattach(tag=%x,unit=%x)\n", (int) &tag, unit);
-#endif
-
- brdp = (stlbrd_t *) malloc(sizeof(stlbrd_t), M_TTYS, M_NOWAIT | M_ZERO);
- if (brdp == (stlbrd_t *) NULL) {
- printf("STALLION: failed to allocate memory (size=%d)\n",
- sizeof(stlbrd_t));
- return;
- }
-
- if ((unit < 0) || (unit > STL_MAXBRDS)) {
- printf("STALLION: bad PCI board unit number=%d\n", unit);
- return;
- }
-
-/*
- * Allocate us a new driver unique unit number.
- */
- if ((brdp->brdnr = stl_findfreeunit()) < 0) {
- printf("STALLION: too many boards found, max=%d\n",
- STL_MAXBRDS);
- return;
- }
- if (brdp->brdnr >= stl_nrbrds)
- stl_nrbrds = brdp->brdnr + 1;
-
- brdp->unitid = 0;
- brdp->brdtype = BRD_ECHPCI;
- brdp->ioaddr1 = ((unsigned int) pci_conf_read(tag, 0x14)) & 0xfffc;
- brdp->ioaddr2 = ((unsigned int) pci_conf_read(tag, 0x10)) & 0xfffc;
- brdp->irq = ((int) pci_conf_read(tag, 0x3c)) & 0xff;
- brdp->irqtype = 0;
- if (pci_map_int(tag, stlpciintr, (void *) NULL, &tty_imask) == 0) {
- printf("STALLION: failed to map interrupt irq=%d for unit=%d\n",
- brdp->irq, brdp->brdnr);
- return;
- }
-
-#if 0
- printf("%s(%d): ECH-PCI iobase=%x iopage=%x irq=%d\n", __file__, __LINE__, brdp->ioaddr2, brdp->ioaddr1, brdp->irq);
-#endif
- stl_brdinit(brdp);
-}
-
-#endif
-
-/*****************************************************************************/
-
-STATIC int stlopen(dev_t dev, int flag, int mode, struct thread *td)
-{
- struct tty *tp;
- stlport_t *portp;
- int error, callout, x;
-
-#if DEBUG
- printf("stlopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag,
- mode, (int) td);
-#endif
-
-/*
- * Firstly check if the supplied device number is a valid device.
- */
- if (minor(dev) & STL_MEMDEV)
- return(0);
-
- portp = stl_dev2port(dev);
- if (portp == (stlport_t *) NULL)
- return(ENXIO);
- tp = &portp->tty;
- dev->si_tty = tp;
- callout = minor(dev) & STL_CALLOUTDEV;
- error = 0;
-
- x = spltty();
-
-stlopen_restart:
-/*
- * Wait here for the DTR drop timeout period to expire.
- */
- while (portp->state & ASY_DTRWAIT) {
- error = tsleep(&portp->dtrwait, (TTIPRI | PCATCH),
- "stldtr", 0);
- if (error)
- goto stlopen_end;
- }
-
-/*
- * We have a valid device, so now we check if it is already open.
- * If not then initialize the port hardware and set up the tty
- * struct as required.
- */
- if ((tp->t_state & TS_ISOPEN) == 0) {
- tp->t_oproc = stl_start;
- tp->t_stop = stl_stop;
- tp->t_param = stl_param;
- tp->t_dev = dev;
- tp->t_termios = callout ? portp->initouttios :
- portp->initintios;
- stl_rawopen(portp);
- if ((portp->sigs & TIOCM_CD) || callout)
- (*linesw[tp->t_line].l_modem)(tp, 1);
- } else {
- if (callout) {
- if (portp->callout == 0) {
- error = EBUSY;
- goto stlopen_end;
- }
- } else {
- if (portp->callout != 0) {
- if (flag & O_NONBLOCK) {
- error = EBUSY;
- goto stlopen_end;
- }
- error = tsleep(&portp->callout,
- (TTIPRI | PCATCH), "stlcall", 0);
- if (error)
- goto stlopen_end;
- goto stlopen_restart;
- }
- }
- if ((tp->t_state & TS_XCLUDE) &&
- suser(td)) {
- error = EBUSY;
- goto stlopen_end;
- }
- }
-
-/*
- * If this port is not the callout device and we do not have carrier
- * then we need to sleep, waiting for it to be asserted.
- */
- if (((tp->t_state & TS_CARR_ON) == 0) && !callout &&
- ((tp->t_cflag & CLOCAL) == 0) &&
- ((flag & O_NONBLOCK) == 0)) {
- portp->waitopens++;
- error = tsleep(TSA_CARR_ON(tp), (TTIPRI | PCATCH), "stldcd", 0);
- portp->waitopens--;
- if (error)
- goto stlopen_end;
- goto stlopen_restart;
- }
-
-/*
- * Open the line discipline.
- */
- error = (*linesw[tp->t_line].l_open)(dev, tp);
- stl_ttyoptim(portp, &tp->t_termios);
- if ((tp->t_state & TS_ISOPEN) && callout)
- portp->callout = 1;
-
-/*
- * If for any reason we get to here and the port is not actually
- * open then close of the physical hardware - no point leaving it
- * active when the open failed...
- */
-stlopen_end:
- splx(x);
- if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0))
- stl_rawclose(portp);
-
- return(error);
-}
-
-/*****************************************************************************/
-
-STATIC int stlclose(dev_t dev, int flag, int mode, struct thread *td)
-{
- struct tty *tp;
- stlport_t *portp;
- int x;
-
-#if DEBUG
- printf("stlclose(dev=%s,flag=%x,mode=%x,p=%p)\n", devtoname(dev),
- flag, mode, (void *) td);
-#endif
-
- if (minor(dev) & STL_MEMDEV)
- return(0);
-
- portp = stl_dev2port(dev);
- if (portp == (stlport_t *) NULL)
- return(ENXIO);
- tp = &portp->tty;
-
- x = spltty();
- (*linesw[tp->t_line].l_close)(tp, flag);
- stl_ttyoptim(portp, &tp->t_termios);
- stl_rawclose(portp);
- ttyclose(tp);
- splx(x);
- return(0);
-}
-
-/*****************************************************************************/
-
-#if VFREEBSD >= 220
-
-STATIC void stl_stop(struct tty *tp, int rw)
-{
-#if DEBUG
- printf("stl_stop(tp=%x,rw=%x)\n", (int) tp, rw);
-#endif
-
- stl_flush((stlport_t *) tp, rw);
-}
-
-#else
-
-STATIC int stlstop(struct tty *tp, int rw)
-{
-#if DEBUG
- printf("stlstop(tp=%x,rw=%x)\n", (int) tp, rw);
-#endif
-
- stl_flush((stlport_t *) tp, rw);
- return(0);
-}
-
-#endif
-
-/*****************************************************************************/
-
-STATIC int stlioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
- struct thread *td)
-{
- struct termios *newtios, *localtios;
- struct tty *tp;
- stlport_t *portp;
- int error, i, x;
-
-#if DEBUG
- printf("stlioctl(dev=%s,cmd=%lx,data=%p,flag=%x,p=%p)\n",
- devtoname(dev), cmd, (void *) data, flag, (void *) td);
-#endif
-
- if (minor(dev) & STL_MEMDEV)
- return(stl_memioctl(dev, cmd, data, flag, td));
-
- portp = stl_dev2port(dev);
- if (portp == (stlport_t *) NULL)
- return(ENODEV);
- tp = &portp->tty;
- error = 0;
-
-/*
- * First up handle ioctls on the control devices.
- */
- if (minor(dev) & STL_CTRLDEV) {
- if ((minor(dev) & STL_CTRLDEV) == STL_CTRLINIT)
- localtios = (minor(dev) & STL_CALLOUTDEV) ?
- &portp->initouttios : &portp->initintios;
- else if ((minor(dev) & STL_CTRLDEV) == STL_CTRLLOCK)
- localtios = (minor(dev) & STL_CALLOUTDEV) ?
- &portp->lockouttios : &portp->lockintios;
- else
- return(ENODEV);
-
- switch (cmd) {
- case TIOCSETA:
- if ((error = suser(td)) == 0)
- *localtios = *((struct termios *) data);
- break;
- case TIOCGETA:
- *((struct termios *) data) = *localtios;
- break;
- case TIOCGETD:
- *((int *) data) = TTYDISC;
- break;
- case TIOCGWINSZ:
- bzero(data, sizeof(struct winsize));
- break;
- default:
- error = ENOTTY;
- break;
- }
- return(error);
- }
-
-/*
- * Deal with 4.3 compatibility issues if we have too...
- */
-#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
- if (1) {
- struct termios tios;
- unsigned long oldcmd;
-
- tios = tp->t_termios;
- oldcmd = cmd;
- if ((error = ttsetcompat(tp, &cmd, data, &tios)))
- return(error);
- if (cmd != oldcmd)
- data = (caddr_t) &tios;
- }
-#endif
-
-/*
- * Carry out some pre-cmd processing work first...
- * Hmmm, not so sure we want this, disable for now...
- */
- if ((cmd == TIOCSETA) || (cmd == TIOCSETAW) || (cmd == TIOCSETAF)) {
- newtios = (struct termios *) data;
- localtios = (minor(dev) & STL_CALLOUTDEV) ?
- &portp->lockouttios : &portp->lockintios;
-
- newtios->c_iflag = (tp->t_iflag & localtios->c_iflag) |
- (newtios->c_iflag & ~localtios->c_iflag);
- newtios->c_oflag = (tp->t_oflag & localtios->c_oflag) |
- (newtios->c_oflag & ~localtios->c_oflag);
- newtios->c_cflag = (tp->t_cflag & localtios->c_cflag) |
- (newtios->c_cflag & ~localtios->c_cflag);
- newtios->c_lflag = (tp->t_lflag & localtios->c_lflag) |
- (newtios->c_lflag & ~localtios->c_lflag);
- for (i = 0; (i < NCCS); i++) {
- if (localtios->c_cc[i] != 0)
- newtios->c_cc[i] = tp->t_cc[i];
- }
- if (localtios->c_ispeed != 0)
- newtios->c_ispeed = tp->t_ispeed;
- if (localtios->c_ospeed != 0)
- newtios->c_ospeed = tp->t_ospeed;
- }
-
-/*
- * Call the line discipline and the common command processing to
- * process this command (if they can).
- */
- error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, td);
- if (error != ENOIOCTL)
- return(error);
-
- x = spltty();
- error = ttioctl(tp, cmd, data, flag);
- stl_ttyoptim(portp, &tp->t_termios);
- if (error != ENOIOCTL) {
- splx(x);
- return(error);
- }
-
- error = 0;
-
-/*
- * Process local commands here. These are all commands that only we
- * can take care of (they all rely on actually doing something special
- * to the actual hardware).
- */
- switch (cmd) {
- case TIOCSBRK:
- stl_sendbreak(portp, -1);
- break;
- case TIOCCBRK:
- stl_sendbreak(portp, -2);
- break;
- case TIOCSDTR:
- stl_setsignals(portp, 1, -1);
- break;
- case TIOCCDTR:
- stl_setsignals(portp, 0, -1);
- break;
- case TIOCMSET:
- i = *((int *) data);
- stl_setsignals(portp, ((i & TIOCM_DTR) ? 1 : 0),
- ((i & TIOCM_RTS) ? 1 : 0));
- break;
- case TIOCMBIS:
- i = *((int *) data);
- stl_setsignals(portp, ((i & TIOCM_DTR) ? 1 : -1),
- ((i & TIOCM_RTS) ? 1 : -1));
- break;
- case TIOCMBIC:
- i = *((int *) data);
- stl_setsignals(portp, ((i & TIOCM_DTR) ? 0 : -1),
- ((i & TIOCM_RTS) ? 0 : -1));
- break;
- case TIOCMGET:
- *((int *) data) = (stl_getsignals(portp) | TIOCM_LE);
- break;
- case TIOCMSDTRWAIT:
- if ((error = suser(td)) == 0)
- portp->dtrwait = *((int *) data) * hz / 100;
- break;
- case TIOCMGDTRWAIT:
- *((int *) data) = portp->dtrwait * 100 / hz;
- break;
- case TIOCTIMESTAMP:
- portp->dotimestamp = 1;
- *((struct timeval *) data) = portp->timestamp;
- break;
- default:
- error = ENOTTY;
- break;
- }
- splx(x);
-
- return(error);
-}
-
-/*****************************************************************************/
-
-/*
- * Convert the specified minor device number into a port struct
- * pointer. Return NULL if the device number is not a valid port.
- */
-
-STATIC stlport_t *stl_dev2port(dev_t dev)
-{
- stlbrd_t *brdp;
-
- brdp = stl_brds[MKDEV2BRD(dev)];
- if (brdp == (stlbrd_t *) NULL)
- return((stlport_t *) NULL);
- return(brdp->ports[MKDEV2PORT(dev)]);
-}
-
-/*****************************************************************************/
-
-/*
- * Initialize the port hardware. This involves enabling the transmitter
- * and receiver, setting the port configuration, and setting the initial
- * signal state.
- */
-
-static int stl_rawopen(stlport_t *portp)
-{
-#if DEBUG
- printf("stl_rawopen(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
- (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
-#endif
- stl_param(&portp->tty, &portp->tty.t_termios);
- portp->sigs = stl_getsignals(portp);
- stl_setsignals(portp, 1, 1);
- stl_enablerxtx(portp, 1, 1);
- stl_startrxtx(portp, 1, 0);
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Shutdown the hardware of a port. Disable its transmitter and
- * receiver, and maybe drop signals if appropriate.
- */
-
-static int stl_rawclose(stlport_t *portp)
-{
- struct tty *tp;
-
-#if DEBUG
- printf("stl_rawclose(portp=%p): brdnr=%d panelnr=%d portnr=%d\n",
- (void *) portp, portp->brdnr, portp->panelnr, portp->portnr);
-#endif
-
- tp = &portp->tty;
- stl_disableintrs(portp);
- stl_enablerxtx(portp, 0, 0);
- stl_flush(portp, (FWRITE | FREAD));
- if (tp->t_cflag & HUPCL) {
- stl_setsignals(portp, 0, 0);
- if (portp->dtrwait != 0) {
- portp->state |= ASY_DTRWAIT;
- timeout(stl_dtrwakeup, portp, portp->dtrwait);
- }
- }
- portp->callout = 0;
- portp->brklen = 0;
- portp->state &= ~(ASY_ACTIVE | ASY_RTSFLOW);
- wakeup(&portp->callout);
- wakeup(TSA_CARR_ON(tp));
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Clear the DTR waiting flag, and wake up any sleepers waiting for
- * DTR wait period to finish.
- */
-
-static void stl_dtrwakeup(void *arg)
-{
- stlport_t *portp;
-
- portp = (stlport_t *) arg;
- portp->state &= ~ASY_DTRWAIT;
- wakeup(&portp->dtrwait);
-}
-
-/*****************************************************************************/
-
-/*
- * Start (or continue) the transfer of TX data on this port. If the
- * port is not currently busy then load up the interrupt ring queue
- * buffer and kick of the transmitter. If the port is running low on
- * TX data then refill the ring queue. This routine is also used to
- * activate input flow control!
- */
-
-static void stl_start(struct tty *tp)
-{
- stlport_t *portp;
- unsigned int len, stlen;
- char *head, *tail;
- int count, x;
-
- portp = (stlport_t *) tp;
-
-#if DEBUG
- printf("stl_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp,
- portp->brdnr, portp->portnr);
-#endif
-
- x = spltty();
-
-/*
- * Check if the ports input has been blocked, and take appropriate action.
- * Not very often do we really need to do anything, so make it quick.
- */
- if (tp->t_state & TS_TBLOCK) {
- if ((portp->state & ASY_RTSFLOW) == 0)
- stl_flowcontrol(portp, 0, -1);
- } else {
- if (portp->state & ASY_RTSFLOW)
- stl_flowcontrol(portp, 1, -1);
- }
-
-#if VFREEBSD == 205
-/*
- * Check if the output cooked clist buffers are near empty, wake up
- * the line discipline to fill it up.
- */
- if (tp->t_outq.c_cc <= tp->t_lowat) {
- if (tp->t_state & TS_ASLEEP) {
- tp->t_state &= ~TS_ASLEEP;
- wakeup(&tp->t_outq);
- }
- selwakeuppri(&tp->t_wsel, TTOPRI);
- }
-#endif
-
- if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
- splx(x);
- return;
- }
-
-/*
- * Copy data from the clists into the interrupt ring queue. This will
- * require at most 2 copys... What we do is calculate how many chars
- * can fit into the ring queue, and how many can fit in 1 copy. If after
- * the first copy there is still more room then do the second copy.
- * The beauty of this type of ring queue is that we do not need to
- * spl protect our-selves, since we only ever update the head pointer,
- * and the interrupt routine only ever updates the tail pointer.
- */
- if (tp->t_outq.c_cc != 0) {
- head = portp->tx.head;
- tail = portp->tx.tail;
- if (head >= tail) {
- len = STL_TXBUFSIZE - (head - tail) - 1;
- stlen = portp->tx.endbuf - head;
- } else {
- len = tail - head - 1;
- stlen = len;
- }
-
- if (len > 0) {
- stlen = MIN(len, stlen);
- count = q_to_b(&tp->t_outq, head, stlen);
- len -= count;
- head += count;
- if (head >= portp->tx.endbuf) {
- head = portp->tx.buf;
- if (len > 0) {
- stlen = q_to_b(&tp->t_outq, head, len);
- head += stlen;
- count += stlen;
- }
- }
- portp->tx.head = head;
- if (count > 0)
- stl_startrxtx(portp, -1, 1);
- }
-
-/*
- * If we sent something, make sure we are called again.
- */
- tp->t_state |= TS_BUSY;
- }
-
-#if VFREEBSD != 205
-/*
- * Do any writer wakeups.
- */
- ttwwakeup(tp);
-#endif
-
- splx(x);
-}
-
-/*****************************************************************************/
-
-static void stl_flush(stlport_t *portp, int flag)
-{
- char *head, *tail;
- int len, x;
-
-#if DEBUG
- printf("stl_flush(portp=%x,flag=%x)\n", (int) portp, flag);
-#endif
-
- if (portp == (stlport_t *) NULL)
- return;
-
- x = spltty();
-
- if (flag & FWRITE) {
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x03));
- stl_ccrwait(portp);
- stl_setreg(portp, CCR, CCR_TXFLUSHFIFO);
- stl_ccrwait(portp);
- portp->tx.tail = portp->tx.head;
- BRDDISABLE(portp->brdnr);
- }
-
-/*
- * The only thing to watch out for when flushing the read side is
- * the RX status buffer. The interrupt code relys on the status
- * bytes as being zeroed all the time (it does not bother setting
- * a good char status to 0, it expects that it already will be).
- * We also need to un-flow the RX channel if flow control was
- * active.
- */
- if (flag & FREAD) {
- head = portp->rx.head;
- tail = portp->rx.tail;
- if (head != tail) {
- if (head >= tail) {
- len = head - tail;
- } else {
- len = portp->rx.endbuf - tail;
- bzero(portp->rxstatus.buf,
- (head - portp->rx.buf));
- }
- bzero((tail + STL_RXBUFSIZE), len);
- portp->rx.tail = head;
- }
-
- if ((portp->state & ASY_RTSFLOW) &&
- ((portp->tty.t_state & TS_TBLOCK) == 0))
- stl_flowcontrol(portp, 1, -1);
- }
-
- splx(x);
-}
-
-/*****************************************************************************/
-
-/*
- * These functions get/set/update the registers of the cd1400 UARTs.
- * Access to the cd1400 registers is via an address/data io port pair.
- * (Maybe should make this inline...)
- */
-
-static int stl_getreg(stlport_t *portp, int regnr)
-{
- outb(portp->ioaddr, (regnr + portp->uartaddr));
- return(inb(portp->ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-static void stl_setreg(stlport_t *portp, int regnr, int value)
-{
- outb(portp->ioaddr, (regnr + portp->uartaddr));
- outb((portp->ioaddr + EREG_DATA), value);
-}
-
-/*****************************************************************************/
-
-static int stl_updatereg(stlport_t *portp, int regnr, int value)
-{
- outb(portp->ioaddr, (regnr + portp->uartaddr));
- if (inb(portp->ioaddr + EREG_DATA) != value) {
- outb((portp->ioaddr + EREG_DATA), value);
- return(1);
- }
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Wait for the command register to be ready. We will poll this, since
- * it won't usually take too long to be ready, and it is only really
- * used for non-critical actions.
- */
-
-static void stl_ccrwait(stlport_t *portp)
-{
- int i;
-
- for (i = 0; (i < CCR_MAXWAIT); i++) {
- if (stl_getreg(portp, CCR) == 0) {
- return;
- }
- }
-
- printf("STALLION: cd1400 device not responding, brd=%d panel=%d"
- "port=%d\n", portp->brdnr, portp->panelnr, portp->portnr);
-}
-
-/*****************************************************************************/
-
-/*
- * Transmit interrupt handler. This has gotta be fast! Handling TX
- * chars is pretty simple, stuff as many as possible from the TX buffer
- * into the cd1400 FIFO. Must also handle TX breaks here, since they
- * are embedded as commands in the data stream. Oh no, had to use a goto!
- * This could be optimized more, will do when I get time...
- * In practice it is possible that interrupts are enabled but that the
- * port has been hung up. Need to handle not having any TX buffer here,
- * this is done by using the side effect that head and tail will also
- * be NULL if the buffer has been freed.
- */
-
-static __inline void stl_txisr(stlpanel_t *panelp, int ioaddr)
-{
- stlport_t *portp;
- int len, stlen;
- char *head, *tail;
- unsigned char ioack, srer;
-
-#if DEBUG
- printf("stl_txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
-
- ioack = inb(ioaddr + EREG_TXACK);
- if (((ioack & panelp->ackmask) != 0) ||
- ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
- printf("STALLION: bad TX interrupt ack value=%x\n", ioack);
- return;
- }
- portp = panelp->ports[(ioack >> 3)];
-
-/*
- * Unfortunately we need to handle breaks in the data stream, since
- * this is the only way to generate them on the cd1400. Do it now if
- * a break is to be sent. Some special cases here: brklen is -1 then
- * start sending an un-timed break, if brklen is -2 then stop sending
- * an un-timed break, if brklen is -3 then we have just sent an
- * un-timed break and do not want any data to go out, if brklen is -4
- * then a break has just completed so clean up the port settings.
- */
- if (portp->brklen != 0) {
- if (portp->brklen >= -1) {
- outb(ioaddr, (TDR + portp->uartaddr));
- outb((ioaddr + EREG_DATA), ETC_CMD);
- outb((ioaddr + EREG_DATA), ETC_STARTBREAK);
- if (portp->brklen > 0) {
- outb((ioaddr + EREG_DATA), ETC_CMD);
- outb((ioaddr + EREG_DATA), ETC_DELAY);
- outb((ioaddr + EREG_DATA), portp->brklen);
- outb((ioaddr + EREG_DATA), ETC_CMD);
- outb((ioaddr + EREG_DATA), ETC_STOPBREAK);
- portp->brklen = -4;
- } else {
- portp->brklen = -3;
- }
- } else if (portp->brklen == -2) {
- outb(ioaddr, (TDR + portp->uartaddr));
- outb((ioaddr + EREG_DATA), ETC_CMD);
- outb((ioaddr + EREG_DATA), ETC_STOPBREAK);
- portp->brklen = -4;
- } else if (portp->brklen == -3) {
- outb(ioaddr, (SRER + portp->uartaddr));
- srer = inb(ioaddr + EREG_DATA);
- srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
- outb((ioaddr + EREG_DATA), srer);
- } else {
- outb(ioaddr, (COR2 + portp->uartaddr));
- outb((ioaddr + EREG_DATA),
- (inb(ioaddr + EREG_DATA) & ~COR2_ETC));
- portp->brklen = 0;
- }
- goto stl_txalldone;
- }
-
- head = portp->tx.head;
- tail = portp->tx.tail;
- len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
- if ((len == 0) || ((len < STL_TXBUFLOW) &&
- ((portp->state & ASY_TXLOW) == 0))) {
- portp->state |= ASY_TXLOW;
- stl_dotimeout();
- }
-
- if (len == 0) {
- outb(ioaddr, (SRER + portp->uartaddr));
- srer = inb(ioaddr + EREG_DATA);
- if (srer & SRER_TXDATA) {
- srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
- } else {
- srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
- portp->tty.t_state &= ~TS_BUSY;
- }
- outb((ioaddr + EREG_DATA), srer);
- } else {
- len = MIN(len, CD1400_TXFIFOSIZE);
- portp->stats.txtotal += len;
- stlen = MIN(len, (portp->tx.endbuf - tail));
- outb(ioaddr, (TDR + portp->uartaddr));
- outsb((ioaddr + EREG_DATA), tail, stlen);
- len -= stlen;
- tail += stlen;
- if (tail >= portp->tx.endbuf)
- tail = portp->tx.buf;
- if (len > 0) {
- outsb((ioaddr + EREG_DATA), tail, len);
- tail += len;
- }
- portp->tx.tail = tail;
- }
-
-stl_txalldone:
- outb(ioaddr, (EOSRR + portp->uartaddr));
- outb((ioaddr + EREG_DATA), 0);
-}
-
-/*****************************************************************************/
-
-/*
- * Receive character interrupt handler. Determine if we have good chars
- * or bad chars and then process appropriately. Good chars are easy
- * just shove the lot into the RX buffer and set all status bytes to 0.
- * If a bad RX char then process as required. This routine needs to be
- * fast!
- */
-
-static __inline void stl_rxisr(stlpanel_t *panelp, int ioaddr)
-{
- stlport_t *portp;
- struct tty *tp;
- unsigned int ioack, len, buflen, stlen;
- unsigned char status;
- char ch;
- char *head, *tail;
- static char unwanted[CD1400_RXFIFOSIZE];
-
-#if DEBUG
- printf("stl_rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
-
- ioack = inb(ioaddr + EREG_RXACK);
- if ((ioack & panelp->ackmask) != 0) {
- printf("STALLION: bad RX interrupt ack value=%x\n", ioack);
- return;
- }
- portp = panelp->ports[(ioack >> 3)];
- tp = &portp->tty;
-
-/*
- * First up, caluclate how much room there is in the RX ring queue.
- * We also want to keep track of the longest possible copy length,
- * this has to allow for the wrapping of the ring queue.
- */
- head = portp->rx.head;
- tail = portp->rx.tail;
- if (head >= tail) {
- buflen = STL_RXBUFSIZE - (head - tail) - 1;
- stlen = portp->rx.endbuf - head;
- } else {
- buflen = tail - head - 1;
- stlen = buflen;
- }
-
-/*
- * Check if the input buffer is near full. If so then we should take
- * some flow control action... It is very easy to do hardware and
- * software flow control from here since we have the port selected on
- * the UART.
- */
- if (buflen <= (STL_RXBUFSIZE - STL_RXBUFHIGH)) {
- if (((portp->state & ASY_RTSFLOW) == 0) &&
- (portp->state & ASY_RTSFLOWMODE)) {
- portp->state |= ASY_RTSFLOW;
- stl_setreg(portp, MCOR1,
- (stl_getreg(portp, MCOR1) & 0xf0));
- stl_setreg(portp, MSVR2, 0);
- portp->stats.rxrtsoff++;
- }
- }
-
-/*
- * OK we are set, process good data... If the RX ring queue is full
- * just chuck the chars - don't leave them in the UART.
- */
- if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
- outb(ioaddr, (RDCR + portp->uartaddr));
- len = inb(ioaddr + EREG_DATA);
- if (buflen == 0) {
- outb(ioaddr, (RDSR + portp->uartaddr));
- insb((ioaddr + EREG_DATA), &unwanted[0], len);
- portp->stats.rxlost += len;
- portp->stats.rxtotal += len;
- } else {
- len = MIN(len, buflen);
- portp->stats.rxtotal += len;
- stlen = MIN(len, stlen);
- if (len > 0) {
- outb(ioaddr, (RDSR + portp->uartaddr));
- insb((ioaddr + EREG_DATA), head, stlen);
- head += stlen;
- if (head >= portp->rx.endbuf) {
- head = portp->rx.buf;
- len -= stlen;
- insb((ioaddr + EREG_DATA), head, len);
- head += len;
- }
- }
- }
- } else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
- outb(ioaddr, (RDSR + portp->uartaddr));
- status = inb(ioaddr + EREG_DATA);
- ch = inb(ioaddr + EREG_DATA);
- if (status & ST_BREAK)
- portp->stats.rxbreaks++;
- if (status & ST_FRAMING)
- portp->stats.rxframing++;
- if (status & ST_PARITY)
- portp->stats.rxparity++;
- if (status & ST_OVERRUN)
- portp->stats.rxoverrun++;
- if (status & ST_SCHARMASK) {
- if ((status & ST_SCHARMASK) == ST_SCHAR1)
- portp->stats.txxon++;
- if ((status & ST_SCHARMASK) == ST_SCHAR2)
- portp->stats.txxoff++;
- goto stl_rxalldone;
- }
- if ((portp->rxignoremsk & status) == 0) {
- if ((tp->t_state & TS_CAN_BYPASS_L_RINT) &&
- ((status & ST_FRAMING) ||
- ((status & ST_PARITY) && (tp->t_iflag & INPCK))))
- ch = 0;
- if ((portp->rxmarkmsk & status) == 0)
- status = 0;
- *(head + STL_RXBUFSIZE) = status;
- *head++ = ch;
- if (head >= portp->rx.endbuf)
- head = portp->rx.buf;
- }
- } else {
- printf("STALLION: bad RX interrupt ack value=%x\n", ioack);
- return;
- }
-
- portp->rx.head = head;
- portp->state |= ASY_RXDATA;
- stl_dotimeout();
-
-stl_rxalldone:
- outb(ioaddr, (EOSRR + portp->uartaddr));
- outb((ioaddr + EREG_DATA), 0);
-}
-
-/*****************************************************************************/
-
-/*
- * Modem interrupt handler. The is called when the modem signal line
- * (DCD) has changed state. Leave most of the work to the off-level
- * processing routine.
- */
-
-static __inline void stl_mdmisr(stlpanel_t *panelp, int ioaddr)
-{
- stlport_t *portp;
- unsigned int ioack;
- unsigned char misr;
-
-#if DEBUG
- printf("stl_mdmisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr);
-#endif
-
- ioack = inb(ioaddr + EREG_MDACK);
- if (((ioack & panelp->ackmask) != 0) ||
- ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
- printf("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
- return;
- }
- portp = panelp->ports[(ioack >> 3)];
-
- outb(ioaddr, (MISR + portp->uartaddr));
- misr = inb(ioaddr + EREG_DATA);
- if (misr & MISR_DCD) {
- portp->state |= ASY_DCDCHANGE;
- portp->stats.modem++;
- stl_dotimeout();
- }
-
- outb(ioaddr, (EOSRR + portp->uartaddr));
- outb((ioaddr + EREG_DATA), 0);
-}
-
-/*****************************************************************************/
-
-/*
- * Interrupt handler for EIO and ECH boards. This code ain't all that
- * pretty, but the idea is to make it as fast as possible. This code is
- * well suited to be assemblerized :-) We don't use the general purpose
- * register access functions here, for speed we will go strait to the
- * io register.
- */
-
-static void stlintr(int unit)
-{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
- unsigned char svrtype;
- int i, panelnr, iobase;
- int cnt;
-
-#if DEBUG
- printf("stlintr(unit=%d)\n", unit);
-#endif
-
- cnt = 0;
- panelp = (stlpanel_t *) NULL;
- for (i = 0; (i < stl_nrbrds); ) {
- if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL) {
- i++;
- continue;
- }
- if (brdp->state == 0) {
- i++;
- continue;
- }
-/*
- * The following section of code handles the subtle differences
- * between board types. It is sort of similar, but different
- * enough to handle each separately.
- */
- if (brdp->brdtype == BRD_EASYIO) {
- if ((inb(brdp->iostatus) & EIO_INTRPEND) == 0) {
- i++;
- continue;
- }
- panelp = brdp->panels[0];
- iobase = panelp->iobase;
- outb(iobase, SVRR);
- svrtype = inb(iobase + EREG_DATA);
- if (brdp->nrports > 4) {
- outb(iobase, (SVRR + 0x80));
- svrtype |= inb(iobase + EREG_DATA);
- }
- } else if (brdp->brdtype == BRD_ECH) {
- if ((inb(brdp->iostatus) & ECH_INTRPEND) == 0) {
- i++;
- continue;
- }
- outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE));
- for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
- panelp = brdp->panels[panelnr];
- iobase = panelp->iobase;
- if (inb(iobase + ECH_PNLSTATUS) & ECH_PNLINTRPEND)
- break;
- if (panelp->nrports > 8) {
- iobase += 0x8;
- if (inb(iobase + ECH_PNLSTATUS) & ECH_PNLINTRPEND)
- break;
- }
- }
- if (panelnr >= brdp->nrpanels) {
- i++;
- continue;
- }
- outb(iobase, SVRR);
- svrtype = inb(iobase + EREG_DATA);
- outb(iobase, (SVRR + 0x80));
- svrtype |= inb(iobase + EREG_DATA);
- } else if (brdp->brdtype == BRD_ECHPCI) {
- iobase = brdp->ioaddr2;
- for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
- panelp = brdp->panels[panelnr];
- outb(brdp->ioctrl, panelp->pagenr);
- if (inb(iobase + ECH_PNLSTATUS) & ECH_PNLINTRPEND)
- break;
- if (panelp->nrports > 8) {
- outb(brdp->ioctrl, (panelp->pagenr + 1));
- if (inb(iobase + ECH_PNLSTATUS) & ECH_PNLINTRPEND)
- break;
- }
- }
- if (panelnr >= brdp->nrpanels) {
- i++;
- continue;
- }
- outb(iobase, SVRR);
- svrtype = inb(iobase + EREG_DATA);
- outb(iobase, (SVRR + 0x80));
- svrtype |= inb(iobase + EREG_DATA);
- } else if (brdp->brdtype == BRD_ECHMC) {
- if ((inb(brdp->iostatus) & ECH_INTRPEND) == 0) {
- i++;
- continue;
- }
- for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {
- panelp = brdp->panels[panelnr];
- iobase = panelp->iobase;
- if (inb(iobase + ECH_PNLSTATUS) & ECH_PNLINTRPEND)
- break;
- if (panelp->nrports > 8) {
- iobase += 0x8;
- if (inb(iobase + ECH_PNLSTATUS) & ECH_PNLINTRPEND)
- break;
- }
- }
- if (panelnr >= brdp->nrpanels) {
- i++;
- continue;
- }
- outb(iobase, SVRR);
- svrtype = inb(iobase + EREG_DATA);
- outb(iobase, (SVRR + 0x80));
- svrtype |= inb(iobase + EREG_DATA);
- } else {
- printf("STALLION: unknown board type=%x\n", brdp->brdtype);
- i++;
- continue;
- }
-
-/*
- * We have determined what type of service is required for a
- * port. From here on in the service of a port is the same no
- * matter what the board type...
- */
- if (svrtype & SVRR_RX)
- stl_rxisr(panelp, iobase);
- if (svrtype & SVRR_TX)
- stl_txisr(panelp, iobase);
- if (svrtype & SVRR_MDM)
- stl_mdmisr(panelp, iobase);
-
- if (brdp->brdtype == BRD_ECH)
- outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE));
- }
-}
-
-/*****************************************************************************/
-
-#if NPCI > 0
-
-static void stlpciintr(void *arg)
-{
- stlintr(0);
-}
-
-#endif
-
-/*****************************************************************************/
-
-/*
- * If we haven't scheduled a timeout then do it, some port needs high
- * level processing.
- */
-
-static void stl_dotimeout()
-{
-#if DEBUG
- printf("stl_dotimeout()\n");
-#endif
-
- if (stl_doingtimeout == 0) {
- timeout(stl_poll, 0, 1);
- stl_doingtimeout++;
- }
-}
-
-/*****************************************************************************/
-
-/*
- * Service "software" level processing. Too slow or painfull to be done
- * at real hardware interrupt time. This way we might also be able to
- * do some service on other waiting ports as well...
- */
-
-static void stl_poll(void *arg)
-{
- stlbrd_t *brdp;
- stlport_t *portp;
- struct tty *tp;
- int brdnr, portnr, rearm, x;
-
-#if DEBUG
- printf("stl_poll()\n");
-#endif
-
- stl_doingtimeout = 0;
- rearm = 0;
-
- x = spltty();
- for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {
- if ((brdp = stl_brds[brdnr]) == (stlbrd_t *) NULL)
- continue;
- for (portnr = 0; (portnr < brdp->nrports); portnr++) {
- if ((portp = brdp->ports[portnr]) == (stlport_t *) NULL)
- continue;
- if ((portp->state & ASY_ACTIVE) == 0)
- continue;
- tp = &portp->tty;
-
- if (portp->state & ASY_RXDATA)
- stl_rxprocess(portp);
- if (portp->state & ASY_DCDCHANGE) {
- portp->state &= ~ASY_DCDCHANGE;
- portp->sigs = stl_getsignals(portp);
- (*linesw[tp->t_line].l_modem)(tp,
- (portp->sigs & TIOCM_CD));
- }
- if (portp->state & ASY_TXLOW) {
- portp->state &= ~ASY_TXLOW;
- (*linesw[tp->t_line].l_start)(tp);
- }
-
- if (portp->state & ASY_ACTIVE)
- rearm++;
- }
- }
- splx(x);
-
- if (rearm)
- stl_dotimeout();
-}
-
-/*****************************************************************************/
-
-/*
- * Process the RX data that has been buffered up in the RX ring queue.
- */
-
-static void stl_rxprocess(stlport_t *portp)
-{
- struct tty *tp;
- unsigned int len, stlen, lostlen;
- char *head, *tail;
- char status;
- int ch;
-
-#if DEBUG
- printf("stl_rxprocess(portp=%x): brdnr=%d portnr=%d\n", (int) portp,
- portp->brdnr, portp->portnr);
-#endif
-
- tp = &portp->tty;
- portp->state &= ~ASY_RXDATA;
-
- if ((tp->t_state & TS_ISOPEN) == 0) {
- stl_flush(portp, FREAD);
- return;
- }
-
-/*
- * Calculate the amount of data in the RX ring queue. Also calculate
- * the largest single copy size...
- */
- head = portp->rx.head;
- tail = portp->rx.tail;
- if (head >= tail) {
- len = head - tail;
- stlen = len;
- } else {
- len = STL_RXBUFSIZE - (tail - head);
- stlen = portp->rx.endbuf - tail;
- }
-
- if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
- if (len > 0) {
- if (((tp->t_rawq.c_cc + len) >= TTYHOG) &&
- ((portp->state & ASY_RTSFLOWMODE) ||
- (tp->t_iflag & IXOFF)) &&
- ((tp->t_state & TS_TBLOCK) == 0)) {
- ch = TTYHOG - tp->t_rawq.c_cc - 1;
- len = (ch > 0) ? ch : 0;
- stlen = MIN(stlen, len);
- ttyblock(tp);
- }
- lostlen = b_to_q(tail, stlen, &tp->t_rawq);
- tail += stlen;
- len -= stlen;
- if (tail >= portp->rx.endbuf) {
- tail = portp->rx.buf;
- lostlen += b_to_q(tail, len, &tp->t_rawq);
- tail += len;
- }
- portp->stats.rxlost += lostlen;
- ttwakeup(tp);
- portp->rx.tail = tail;
- }
- } else {
- while (portp->rx.tail != head) {
- ch = (unsigned char) *(portp->rx.tail);
- status = *(portp->rx.tail + STL_RXBUFSIZE);
- if (status) {
- *(portp->rx.tail + STL_RXBUFSIZE) = 0;
- if (status & ST_BREAK)
- ch |= TTY_BI;
- if (status & ST_FRAMING)
- ch |= TTY_FE;
- if (status & ST_PARITY)
- ch |= TTY_PE;
- if (status & ST_OVERRUN)
- ch |= TTY_OE;
- }
- (*linesw[tp->t_line].l_rint)(ch, tp);
- if (portp->rx.tail == head)
- break;
-
- if (++(portp->rx.tail) >= portp->rx.endbuf)
- portp->rx.tail = portp->rx.buf;
- }
- }
-
- if (head != portp->rx.tail)
- portp->state |= ASY_RXDATA;
-
-/*
- * If we where flow controled then maybe the buffer is low enough that
- * we can re-activate it.
- */
- if ((portp->state & ASY_RTSFLOW) && ((tp->t_state & TS_TBLOCK) == 0))
- stl_flowcontrol(portp, 1, -1);
-}
-
-/*****************************************************************************/
-
-/*
- * Set up the cd1400 registers for a port based on the termios port
- * settings.
- */
-
-static int stl_param(struct tty *tp, struct termios *tiosp)
-{
- stlport_t *portp;
- unsigned int clkdiv;
- unsigned char cor1, cor2, cor3;
- unsigned char cor4, cor5, ccr;
- unsigned char srer, sreron, sreroff;
- unsigned char mcor1, mcor2, rtpr;
- unsigned char clk, div;
- int x;
-
- portp = (stlport_t *) tp;
-
-#if DEBUG
- printf("stl_param(tp=%x,tiosp=%x): brdnr=%d portnr=%d\n", (int) tp,
- (int) tiosp, portp->brdnr, portp->portnr);
-#endif
-
- cor1 = 0;
- cor2 = 0;
- cor3 = 0;
- cor4 = 0;
- cor5 = 0;
- ccr = 0;
- rtpr = 0;
- clk = 0;
- div = 0;
- mcor1 = 0;
- mcor2 = 0;
- sreron = 0;
- sreroff = 0;
-
-/*
- * Set up the RX char ignore mask with those RX error types we
- * can ignore. We could have used some special modes of the cd1400
- * UART to help, but it is better this way because we can keep stats
- * on the number of each type of RX exception event.
- */
- portp->rxignoremsk = 0;
- if (tiosp->c_iflag & IGNPAR)
- portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
- if (tiosp->c_iflag & IGNBRK)
- portp->rxignoremsk |= ST_BREAK;
-
- portp->rxmarkmsk = ST_OVERRUN;
- if (tiosp->c_iflag & (INPCK | PARMRK))
- portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
- if (tiosp->c_iflag & BRKINT)
- portp->rxmarkmsk |= ST_BREAK;
-
-/*
- * Go through the char size, parity and stop bits and set all the
- * option registers appropriately.
- */
- switch (tiosp->c_cflag & CSIZE) {
- case CS5:
- cor1 |= COR1_CHL5;
- break;
- case CS6:
- cor1 |= COR1_CHL6;
- break;
- case CS7:
- cor1 |= COR1_CHL7;
- break;
- default:
- cor1 |= COR1_CHL8;
- break;
- }
-
- if (tiosp->c_cflag & CSTOPB)
- cor1 |= COR1_STOP2;
- else
- cor1 |= COR1_STOP1;
-
- if (tiosp->c_cflag & PARENB) {
- if (tiosp->c_cflag & PARODD)
- cor1 |= (COR1_PARENB | COR1_PARODD);
- else
- cor1 |= (COR1_PARENB | COR1_PAREVEN);
- } else {
- cor1 |= COR1_PARNONE;
- }
-
- if (tiosp->c_iflag & ISTRIP)
- cor5 |= COR5_ISTRIP;
-
-/*
- * Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
- * space for hardware flow control and the like. This should be set to
- * VMIN. Also here we will set the RX data timeout to 10ms - this should
- * really be based on VTIME...
- */
- cor3 |= FIFO_RXTHRESHOLD;
- rtpr = 2;
-
-/*
- * Calculate the baud rate timers. For now we will just assume that
- * the input and output baud are the same. Could have used a baud
- * table here, but this way we can generate virtually any baud rate
- * we like!
- */
- if (tiosp->c_ispeed == 0)
- tiosp->c_ispeed = tiosp->c_ospeed;
- if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > STL_MAXBAUD))
- return(EINVAL);
-
- if (tiosp->c_ospeed > 0) {
- for (clk = 0; (clk < CD1400_NUMCLKS); clk++) {
- clkdiv = ((portp->clk / stl_cd1400clkdivs[clk]) /
- tiosp->c_ospeed);
- if (clkdiv < 0x100)
- break;
- }
- div = (unsigned char) clkdiv;
- }
-
-/*
- * Check what form of modem signaling is required and set it up.
- */
- if ((tiosp->c_cflag & CLOCAL) == 0) {
- mcor1 |= MCOR1_DCD;
- mcor2 |= MCOR2_DCD;
- sreron |= SRER_MODEM;
- }
-
-/*
- * Setup cd1400 enhanced modes if we can. In particular we want to
- * handle as much of the flow control as possbile automatically. As
- * well as saving a few CPU cycles it will also greatly improve flow
- * control reliablilty.
- */
- if (tiosp->c_iflag & IXON) {
- cor2 |= COR2_TXIBE;
- cor3 |= COR3_SCD12;
- if (tiosp->c_iflag & IXANY)
- cor2 |= COR2_IXM;
- }
-
- if (tiosp->c_cflag & CCTS_OFLOW)
- cor2 |= COR2_CTSAE;
- if (tiosp->c_cflag & CRTS_IFLOW)
- mcor1 |= FIFO_RTSTHRESHOLD;
-
-/*
- * All cd1400 register values calculated so go through and set them
- * all up.
- */
-#if DEBUG
- printf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr,
- portp->panelnr, portp->brdnr);
- printf(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", cor1, cor2,
- cor3, cor4, cor5);
- printf(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
- mcor1, mcor2, rtpr, sreron, sreroff);
- printf(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
- printf(" schr1=%x schr2=%x schr3=%x schr4=%x\n",
- tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP], tiosp->c_cc[VSTART],
- tiosp->c_cc[VSTOP]);
-#endif
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x3));
- srer = stl_getreg(portp, SRER);
- stl_setreg(portp, SRER, 0);
- ccr += stl_updatereg(portp, COR1, cor1);
- ccr += stl_updatereg(portp, COR2, cor2);
- ccr += stl_updatereg(portp, COR3, cor3);
- if (ccr) {
- stl_ccrwait(portp);
- stl_setreg(portp, CCR, CCR_CORCHANGE);
- }
- stl_setreg(portp, COR4, cor4);
- stl_setreg(portp, COR5, cor5);
- stl_setreg(portp, MCOR1, mcor1);
- stl_setreg(portp, MCOR2, mcor2);
- if (tiosp->c_ospeed == 0) {
- stl_setreg(portp, MSVR1, 0);
- } else {
- stl_setreg(portp, MSVR1, MSVR1_DTR);
- stl_setreg(portp, TCOR, clk);
- stl_setreg(portp, TBPR, div);
- stl_setreg(portp, RCOR, clk);
- stl_setreg(portp, RBPR, div);
- }
- stl_setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
- stl_setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
- stl_setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
- stl_setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
- stl_setreg(portp, RTPR, rtpr);
- mcor1 = stl_getreg(portp, MSVR1);
- if (mcor1 & MSVR1_DCD)
- portp->sigs |= TIOCM_CD;
- else
- portp->sigs &= ~TIOCM_CD;
- stl_setreg(portp, SRER, ((srer & ~sreroff) | sreron));
- BRDDISABLE(portp->brdnr);
- portp->state &= ~(ASY_RTSFLOWMODE | ASY_CTSFLOWMODE);
- portp->state |= ((tiosp->c_cflag & CRTS_IFLOW) ? ASY_RTSFLOWMODE : 0);
- portp->state |= ((tiosp->c_cflag & CCTS_OFLOW) ? ASY_CTSFLOWMODE : 0);
- stl_ttyoptim(portp, tiosp);
- splx(x);
-
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Action the flow control as required. The hw and sw args inform the
- * routine what flow control methods it should try.
- */
-
-static void stl_flowcontrol(stlport_t *portp, int hw, int sw)
-{
- unsigned char *head, *tail;
- int len, hwflow, x;
-
-#if DEBUG
- printf("stl_flowcontrol(portp=%x,hw=%d,sw=%d)\n", (int) portp, hw, sw);
-#endif
-
- hwflow = -1;
-
- if (portp->state & ASY_RTSFLOWMODE) {
- if (hw == 0) {
- if ((portp->state & ASY_RTSFLOW) == 0)
- hwflow = 0;
- } else if (hw > 0) {
- if (portp->state & ASY_RTSFLOW) {
- head = portp->rx.head;
- tail = portp->rx.tail;
- len = (head >= tail) ? (head - tail) :
- (STL_RXBUFSIZE - (tail - head));
- if (len < STL_RXBUFHIGH)
- hwflow = 1;
- }
- }
- }
-
-/*
- * We have worked out what to do, if anything. So now apply it to the
- * UART port.
- */
- if (hwflow >= 0) {
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x03));
- if (hwflow == 0) {
- portp->state |= ASY_RTSFLOW;
- stl_setreg(portp, MCOR1,
- (stl_getreg(portp, MCOR1) & 0xf0));
- stl_setreg(portp, MSVR2, 0);
- portp->stats.rxrtsoff++;
- } else if (hwflow > 0) {
- portp->state &= ~ASY_RTSFLOW;
- stl_setreg(portp, MSVR2, MSVR2_RTS);
- stl_setreg(portp, MCOR1,
- (stl_getreg(portp, MCOR1) | FIFO_RTSTHRESHOLD));
- portp->stats.rxrtson++;
- }
- BRDDISABLE(portp->brdnr);
- splx(x);
- }
-}
-
-
-/*****************************************************************************/
-
-/*
- * Set the state of the DTR and RTS signals.
- */
-
-static void stl_setsignals(stlport_t *portp, int dtr, int rts)
-{
- unsigned char msvr1, msvr2;
- int x;
-
-#if DEBUG
- printf("stl_setsignals(portp=%x,dtr=%d,rts=%d)\n", (int) portp,
- dtr, rts);
-#endif
-
- msvr1 = 0;
- msvr2 = 0;
- if (dtr > 0)
- msvr1 = MSVR1_DTR;
- if (rts > 0)
- msvr2 = MSVR2_RTS;
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x03));
- if (rts >= 0)
- stl_setreg(portp, MSVR2, msvr2);
- if (dtr >= 0)
- stl_setreg(portp, MSVR1, msvr1);
- BRDDISABLE(portp->brdnr);
- splx(x);
-}
-
-/*****************************************************************************/
-
-/*
- * Get the state of the signals.
- */
-
-static int stl_getsignals(stlport_t *portp)
-{
- unsigned char msvr1, msvr2;
- int sigs, x;
-
-#if DEBUG
- printf("stl_getsignals(portp=%x)\n", (int) portp);
-#endif
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x3));
- msvr1 = stl_getreg(portp, MSVR1);
- msvr2 = stl_getreg(portp, MSVR2);
- BRDDISABLE(portp->brdnr);
- splx(x);
-
- sigs = 0;
- sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
- sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
- sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
- sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
- sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
- sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
- return(sigs);
-}
-
-/*****************************************************************************/
-
-/*
- * Enable or disable the Transmitter and/or Receiver.
- */
-
-static void stl_enablerxtx(stlport_t *portp, int rx, int tx)
-{
- unsigned char ccr;
- int x;
-
-#if DEBUG
- printf("stl_enablerxtx(portp=%x,rx=%d,tx=%d)\n", (int) portp, rx, tx);
-#endif
-
- ccr = 0;
- if (tx == 0)
- ccr |= CCR_TXDISABLE;
- else if (tx > 0)
- ccr |= CCR_TXENABLE;
- if (rx == 0)
- ccr |= CCR_RXDISABLE;
- else if (rx > 0)
- ccr |= CCR_RXENABLE;
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x03));
- stl_ccrwait(portp);
- stl_setreg(portp, CCR, ccr);
- stl_ccrwait(portp);
- BRDDISABLE(portp->brdnr);
- splx(x);
-}
-
-/*****************************************************************************/
-
-/*
- * Start or stop the Transmitter and/or Receiver.
- */
-
-static void stl_startrxtx(stlport_t *portp, int rx, int tx)
-{
- unsigned char sreron, sreroff;
- int x;
-
-#if DEBUG
- printf("stl_startrxtx(portp=%x,rx=%d,tx=%d)\n", (int) portp, rx, tx);
-#endif
-
- sreron = 0;
- sreroff = 0;
- if (tx == 0)
- sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
- else if (tx == 1)
- sreron |= SRER_TXDATA;
- else if (tx >= 2)
- sreron |= SRER_TXEMPTY;
- if (rx == 0)
- sreroff |= SRER_RXDATA;
- else if (rx > 0)
- sreron |= SRER_RXDATA;
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x3));
- stl_setreg(portp, SRER,
- ((stl_getreg(portp, SRER) & ~sreroff) | sreron));
- BRDDISABLE(portp->brdnr);
- if (tx > 0)
- portp->tty.t_state |= TS_BUSY;
- splx(x);
-}
-
-/*****************************************************************************/
-
-/*
- * Disable all interrupts from this port.
- */
-
-static void stl_disableintrs(stlport_t *portp)
-{
- int x;
-
-#if DEBUG
- printf("stl_disableintrs(portp=%x)\n", (int) portp);
-#endif
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x3));
- stl_setreg(portp, SRER, 0);
- BRDDISABLE(portp->brdnr);
- splx(x);
-}
-
-/*****************************************************************************/
-
-static void stl_sendbreak(stlport_t *portp, long len)
-{
- int x;
-
-#if DEBUG
- printf("stl_sendbreak(portp=%x,len=%d)\n", (int) portp, (int) len);
-#endif
-
- x = spltty();
- BRDENABLE(portp->brdnr, portp->pagenr);
- stl_setreg(portp, CAR, (portp->portnr & 0x3));
- stl_setreg(portp, COR2, (stl_getreg(portp, COR2) | COR2_ETC));
- stl_setreg(portp, SRER,
- ((stl_getreg(portp, SRER) & ~SRER_TXDATA) | SRER_TXEMPTY));
- BRDDISABLE(portp->brdnr);
- if (len > 0) {
- len = len / 5;
- portp->brklen = (len > 255) ? 255 : len;
- } else {
- portp->brklen = len;
- }
- splx(x);
- portp->stats.txbreaks++;
-}
-
-/*****************************************************************************/
-
-/*
- * Enable l_rint processing bypass mode if tty modes allow it.
- */
-
-static void stl_ttyoptim(stlport_t *portp, struct termios *tiosp)
-{
- struct tty *tp;
-
- tp = &portp->tty;
- if (((tiosp->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR)) == 0) &&
- (((tiosp->c_iflag & BRKINT) == 0) || (tiosp->c_iflag & IGNBRK)) &&
- (((tiosp->c_iflag & PARMRK) == 0) ||
- ((tiosp->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK))) &&
- ((tiosp->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) ==0) &&
- (linesw[tp->t_line].l_rint == ttyinput))
- tp->t_state |= TS_CAN_BYPASS_L_RINT;
- else
- tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
- portp->hotchar = linesw[tp->t_line].l_hotchar;
-}
-
-/*****************************************************************************/
-
-/*
- * Try and find and initialize all the ports on a panel. We don't care
- * what sort of board these ports are on - since the port io registers
- * are almost identical when dealing with ports.
- */
-
-static int stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
-{
- stlport_t *portp;
- unsigned int chipmask;
- unsigned int gfrcr;
- int nrchips, uartaddr, ioaddr;
- int i, j;
-
-#if DEBUG
- printf("stl_initports(panelp=%x)\n", (int) panelp);
-#endif
-
- BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- * Check that each chip is present and started up OK.
- */
- chipmask = 0;
- nrchips = panelp->nrports / CD1400_PORTS;
- for (i = 0; (i < nrchips); i++) {
- if (brdp->brdtype == BRD_ECHPCI) {
- outb(brdp->ioctrl, (panelp->pagenr + (i >> 1)));
- ioaddr = panelp->iobase;
- } else {
- ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
- }
- uartaddr = (i & 0x01) ? 0x080 : 0;
- outb(ioaddr, (GFRCR + uartaddr));
- outb((ioaddr + EREG_DATA), 0);
- outb(ioaddr, (CCR + uartaddr));
- outb((ioaddr + EREG_DATA), CCR_RESETFULL);
- outb((ioaddr + EREG_DATA), CCR_RESETFULL);
- outb(ioaddr, (GFRCR + uartaddr));
- for (j = 0; (j < CCR_MAXWAIT); j++) {
- gfrcr = inb(ioaddr + EREG_DATA);
- if ((gfrcr > 0x40) && (gfrcr < 0x60))
- break;
- }
- if (j >= CCR_MAXWAIT) {
- printf("STALLION: cd1400 not responding, brd=%d "
- "panel=%d chip=%d\n", panelp->brdnr,
- panelp->panelnr, i);
- continue;
- }
- chipmask |= (0x1 << i);
- outb(ioaddr, (PPR + uartaddr));
- outb((ioaddr + EREG_DATA), PPR_SCALAR);
- }
-
-/*
- * All cd1400's are initialized (if found!). Now go through and setup
- * each ports data structures. Also init the LIVR register of cd1400
- * for each port.
- */
- ioaddr = panelp->iobase;
- for (i = 0; (i < panelp->nrports); i++) {
- if (brdp->brdtype == BRD_ECHPCI) {
- outb(brdp->ioctrl, (panelp->pagenr + (i >> 3)));
- ioaddr = panelp->iobase;
- } else {
- ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 3));
- }
- if ((chipmask & (0x1 << (i / 4))) == 0)
- continue;
- portp = (stlport_t *) malloc(sizeof(stlport_t), M_TTYS,
- M_NOWAIT | M_ZERO);
- if (portp == (stlport_t *) NULL) {
- printf("STALLION: failed to allocate port memory "
- "(size=%d)\n", sizeof(stlport_t));
- break;
- }
-
- portp->portnr = i;
- portp->brdnr = panelp->brdnr;
- portp->panelnr = panelp->panelnr;
- portp->clk = brdp->clk;
- portp->ioaddr = ioaddr;
- portp->uartaddr = (i & 0x4) << 5;
- portp->pagenr = panelp->pagenr + (i >> 3);
- portp->hwid = stl_getreg(portp, GFRCR);
- stl_setreg(portp, CAR, (i & 0x3));
- stl_setreg(portp, LIVR, (i << 3));
- panelp->ports[i] = portp;
-
- j = STL_TXBUFSIZE + (2 * STL_RXBUFSIZE);
- portp->tx.buf = (char *) malloc(j, M_TTYS, M_NOWAIT);
- if (portp->tx.buf == (char *) NULL) {
- printf("STALLION: failed to allocate buffer memory "
- "(size=%d)\n", j);
- break;
- }
- portp->tx.endbuf = portp->tx.buf + STL_TXBUFSIZE;
- portp->tx.head = portp->tx.buf;
- portp->tx.tail = portp->tx.buf;
- portp->rx.buf = portp->tx.buf + STL_TXBUFSIZE;
- portp->rx.endbuf = portp->rx.buf + STL_RXBUFSIZE;
- portp->rx.head = portp->rx.buf;
- portp->rx.tail = portp->rx.buf;
- portp->rxstatus.buf = portp->rx.buf + STL_RXBUFSIZE;
- portp->rxstatus.endbuf = portp->rxstatus.buf + STL_RXBUFSIZE;
- portp->rxstatus.head = portp->rxstatus.buf;
- portp->rxstatus.tail = portp->rxstatus.buf;
- bzero(portp->rxstatus.head, STL_RXBUFSIZE);
-
- portp->initintios.c_ispeed = STL_DEFSPEED;
- portp->initintios.c_ospeed = STL_DEFSPEED;
- portp->initintios.c_cflag = STL_DEFCFLAG;
- portp->initintios.c_iflag = 0;
- portp->initintios.c_oflag = 0;
- portp->initintios.c_lflag = 0;
- bcopy(&ttydefchars[0], &portp->initintios.c_cc[0],
- sizeof(portp->initintios.c_cc));
- portp->initouttios = portp->initintios;
- portp->dtrwait = 3 * hz;
- }
-
- BRDDISABLE(panelp->brdnr);
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Try to find and initialize an EasyIO board.
- */
-
-static int stl_initeio(stlbrd_t *brdp)
-{
- stlpanel_t *panelp;
- unsigned int status;
-
-#if DEBUG
- printf("stl_initeio(brdp=%x)\n", (int) brdp);
-#endif
-
- brdp->ioctrl = brdp->ioaddr1 + 1;
- brdp->iostatus = brdp->ioaddr1 + 2;
- brdp->clk = EIO_CLK;
-
- status = inb(brdp->iostatus);
- switch (status & EIO_IDBITMASK) {
- case EIO_8PORTM:
- brdp->clk = EIO_CLK8M;
- /* FALLTHROUGH */
- case EIO_8PORTRS:
- case EIO_8PORTDI:
- brdp->nrports = 8;
- break;
- case EIO_4PORTRS:
- brdp->nrports = 4;
- break;
- default:
- return(ENODEV);
- }
-
-/*
- * Check that the supplied IRQ is good and then use it to setup the
- * programmable interrupt bits on EIO board. Also set the edge/level
- * triggered interrupt bit.
- */
- if ((brdp->irq < 0) || (brdp->irq > 15) ||
- (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
- printf("STALLION: invalid irq=%d for brd=%d\n", brdp->irq,
- brdp->brdnr);
- return(EINVAL);
- }
- outb(brdp->ioctrl, (stl_vecmap[brdp->irq] |
- ((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)));
-
- panelp = (stlpanel_t *) malloc(sizeof(stlpanel_t), M_TTYS,
- M_NOWAIT | M_ZERO);
- if (panelp == (stlpanel_t *) NULL) {
- printf("STALLION: failed to allocate memory (size=%d)\n",
- sizeof(stlpanel_t));
- return(ENOMEM);
- }
-
- panelp->brdnr = brdp->brdnr;
- panelp->panelnr = 0;
- panelp->nrports = brdp->nrports;
- panelp->iobase = brdp->ioaddr1;
- panelp->hwid = status;
- brdp->panels[0] = panelp;
- brdp->nrpanels = 1;
- brdp->hwid = status;
- brdp->state |= BRD_FOUND;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Try to find an ECH board and initialize it. This code is capable of
- * dealing with all types of ECH board.
- */
-
-static int stl_initech(stlbrd_t *brdp)
-{
- stlpanel_t *panelp;
- unsigned int status, nxtid;
- int panelnr, ioaddr, i;
-
-#if DEBUG
- printf("stl_initech(brdp=%x)\n", (int) brdp);
-#endif
-
-/*
- * Set up the initial board register contents for boards. This varys a
- * bit between the different board types. So we need to handle each
- * separately. Also do a check that the supplied IRQ is good.
- */
- if (brdp->brdtype == BRD_ECH) {
- brdp->ioctrl = brdp->ioaddr1 + 1;
- brdp->iostatus = brdp->ioaddr1 + 1;
- status = inb(brdp->iostatus);
- if ((status & ECH_IDBITMASK) != ECH_ID)
- return(ENODEV);
- brdp->hwid = status;
-
- if ((brdp->irq < 0) || (brdp->irq > 15) ||
- (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
- printf("STALLION: invalid irq=%d for brd=%d\n",
- brdp->irq, brdp->brdnr);
- return(EINVAL);
- }
- status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
- status |= (stl_vecmap[brdp->irq] << 1);
- outb(brdp->ioaddr1, (status | ECH_BRDRESET));
- brdp->ioctrlval = ECH_INTENABLE |
- ((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
- outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE));
- outb(brdp->ioaddr1, status);
- } else if (brdp->brdtype == BRD_ECHMC) {
- brdp->ioctrl = brdp->ioaddr1 + 0x20;
- brdp->iostatus = brdp->ioctrl;
- status = inb(brdp->iostatus);
- if ((status & ECH_IDBITMASK) != ECH_ID)
- return(ENODEV);
- brdp->hwid = status;
-
- if ((brdp->irq < 0) || (brdp->irq > 15) ||
- (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
- printf("STALLION: invalid irq=%d for brd=%d\n",
- brdp->irq, brdp->brdnr);
- return(EINVAL);
- }
- outb(brdp->ioctrl, ECHMC_BRDRESET);
- outb(brdp->ioctrl, ECHMC_INTENABLE);
- } else if (brdp->brdtype == BRD_ECHPCI) {
- brdp->ioctrl = brdp->ioaddr1 + 2;
- }
-
- brdp->clk = ECH_CLK;
-
-/*
- * Scan through the secondary io address space looking for panels.
- * As we find'em allocate and initialize panel structures for each.
- */
- ioaddr = brdp->ioaddr2;
- panelnr = 0;
- nxtid = 0;
-
- for (i = 0; (i < STL_MAXPANELS); i++) {
- if (brdp->brdtype == BRD_ECHPCI) {
- outb(brdp->ioctrl, nxtid);
- ioaddr = brdp->ioaddr2;
- }
- status = inb(ioaddr + ECH_PNLSTATUS);
- if ((status & ECH_PNLIDMASK) != nxtid)
- break;
- panelp = (stlpanel_t *) malloc(sizeof(stlpanel_t), M_TTYS,
- M_NOWAIT | M_ZERO);
- if (panelp == (stlpanel_t *) NULL) {
- printf("STALLION: failed to allocate memory"
- "(size=%d)\n", sizeof(stlpanel_t));
- break;
- }
- panelp->brdnr = brdp->brdnr;
- panelp->panelnr = panelnr;
- panelp->iobase = ioaddr;
- panelp->pagenr = nxtid;
- panelp->hwid = status;
- if (status & ECH_PNL16PORT) {
- if ((brdp->nrports + 16) > 32)
- break;
- panelp->nrports = 16;
- panelp->ackmask = 0x80;
- brdp->nrports += 16;
- ioaddr += (EREG_BANKSIZE * 2);
- nxtid += 2;
- } else {
- panelp->nrports = 8;
- panelp->ackmask = 0xc0;
- brdp->nrports += 8;
- ioaddr += EREG_BANKSIZE;
- nxtid++;
- }
- brdp->panels[panelnr++] = panelp;
- brdp->nrpanels++;
- if (ioaddr >= (brdp->ioaddr2 + 0x20))
- break;
- }
-
- if (brdp->brdtype == BRD_ECH)
- outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE));
-
- brdp->state |= BRD_FOUND;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Initialize and configure the specified board. This firstly probes
- * for the board, if it is found then the board is initialized and
- * then all its ports are initialized as well.
- */
-
-static int stl_brdinit(stlbrd_t *brdp)
-{
- stlpanel_t *panelp;
- int i, j, k;
-
-#if DEBUG
- printf("stl_brdinit(brdp=%x): unit=%d type=%d io1=%x io2=%x irq=%d\n",
- (int) brdp, brdp->brdnr, brdp->brdtype, brdp->ioaddr1,
- brdp->ioaddr2, brdp->irq);
-#endif
-
- switch (brdp->brdtype) {
- case BRD_EASYIO:
- stl_initeio(brdp);
- break;
- case BRD_ECH:
- case BRD_ECHMC:
- case BRD_ECHPCI:
- stl_initech(brdp);
- break;
- default:
- printf("STALLION: unit=%d is unknown board type=%d\n",
- brdp->brdnr, brdp->brdtype);
- return(ENODEV);
- }
-
- stl_brds[brdp->brdnr] = brdp;
- if ((brdp->state & BRD_FOUND) == 0) {
-#if 0
- printf("STALLION: %s board not found, unit=%d io=%x irq=%d\n",
- stl_brdnames[brdp->brdtype], brdp->brdnr,
- brdp->ioaddr1, brdp->irq);
-#endif
- return(ENODEV);
- }
-
- for (i = 0, k = 0; (i < STL_MAXPANELS); i++) {
- panelp = brdp->panels[i];
- if (panelp != (stlpanel_t *) NULL) {
- stl_initports(brdp, panelp);
- for (j = 0; (j < panelp->nrports); j++)
- brdp->ports[k++] = panelp->ports[j];
- }
- }
-
- printf("stl%d: %s (driver version %s) unit=%d nrpanels=%d nrports=%d\n",
- brdp->unitid, stl_brdnames[brdp->brdtype], stl_drvversion,
- brdp->brdnr, brdp->nrpanels, brdp->nrports);
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Return the board stats structure to user app.
- */
-
-static int stl_getbrdstats(caddr_t data)
-{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
- int i;
-
- stl_brdstats = *((combrd_t *) data);
- if (stl_brdstats.brd >= STL_MAXBRDS)
- return(-ENODEV);
- brdp = stl_brds[stl_brdstats.brd];
- if (brdp == (stlbrd_t *) NULL)
- return(-ENODEV);
-
- bzero(&stl_brdstats, sizeof(combrd_t));
- stl_brdstats.brd = brdp->brdnr;
- stl_brdstats.type = brdp->brdtype;
- stl_brdstats.hwid = brdp->hwid;
- stl_brdstats.state = brdp->state;
- stl_brdstats.ioaddr = brdp->ioaddr1;
- stl_brdstats.ioaddr2 = brdp->ioaddr2;
- stl_brdstats.irq = brdp->irq;
- stl_brdstats.nrpanels = brdp->nrpanels;
- stl_brdstats.nrports = brdp->nrports;
- for (i = 0; (i < brdp->nrpanels); i++) {
- panelp = brdp->panels[i];
- stl_brdstats.panels[i].panel = i;
- stl_brdstats.panels[i].hwid = panelp->hwid;
- stl_brdstats.panels[i].nrports = panelp->nrports;
- }
-
- *((combrd_t *) data) = stl_brdstats;;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Resolve the referenced port number into a port struct pointer.
- */
-
-static stlport_t *stl_getport(int brdnr, int panelnr, int portnr)
-{
- stlbrd_t *brdp;
- stlpanel_t *panelp;
-
- if ((brdnr < 0) || (brdnr >= STL_MAXBRDS))
- return((stlport_t *) NULL);
- brdp = stl_brds[brdnr];
- if (brdp == (stlbrd_t *) NULL)
- return((stlport_t *) NULL);
- if ((panelnr < 0) || (panelnr >= brdp->nrpanels))
- return((stlport_t *) NULL);
- panelp = brdp->panels[panelnr];
- if (panelp == (stlpanel_t *) NULL)
- return((stlport_t *) NULL);
- if ((portnr < 0) || (portnr >= panelp->nrports))
- return((stlport_t *) NULL);
- return(panelp->ports[portnr]);
-}
-
-/*****************************************************************************/
-
-/*
- * Return the port stats structure to user app. A NULL port struct
- * pointer passed in means that we need to find out from the app
- * what port to get stats for (used through board control device).
- */
-
-static int stl_getportstats(stlport_t *portp, caddr_t data)
-{
- unsigned char *head, *tail;
-
- if (portp == (stlport_t *) NULL) {
- stl_comstats = *((comstats_t *) data);
- portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
- stl_comstats.port);
- if (portp == (stlport_t *) NULL)
- return(-ENODEV);
- }
-
- portp->stats.state = portp->state;
- /*portp->stats.flags = portp->flags;*/
- portp->stats.hwid = portp->hwid;
- portp->stats.ttystate = portp->tty.t_state;
- portp->stats.cflags = portp->tty.t_cflag;
- portp->stats.iflags = portp->tty.t_iflag;
- portp->stats.oflags = portp->tty.t_oflag;
- portp->stats.lflags = portp->tty.t_lflag;
-
- head = portp->tx.head;
- tail = portp->tx.tail;
- portp->stats.txbuffered = ((head >= tail) ? (head - tail) :
- (STL_TXBUFSIZE - (tail - head)));
-
- head = portp->rx.head;
- tail = portp->rx.tail;
- portp->stats.rxbuffered = (head >= tail) ? (head - tail) :
- (STL_RXBUFSIZE - (tail - head));
-
- portp->stats.signals = (unsigned long) stl_getsignals(portp);
-
- *((comstats_t *) data) = portp->stats;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stl_clrportstats(stlport_t *portp, caddr_t data)
-{
- if (portp == (stlport_t *) NULL) {
- stl_comstats = *((comstats_t *) data);
- portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
- stl_comstats.port);
- if (portp == (stlport_t *) NULL)
- return(-ENODEV);
- }
-
- bzero(&portp->stats, sizeof(comstats_t));
- portp->stats.brd = portp->brdnr;
- portp->stats.panel = portp->panelnr;
- portp->stats.port = portp->portnr;
- *((comstats_t *) data) = stl_comstats;
- return(0);
-}
-
-/*****************************************************************************/
-
-/*
- * The "staliomem" device is used for stats collection in this driver.
- */
-
-static int stl_memioctl(dev_t dev, unsigned long cmd, caddr_t data, int flag,
- struct thread *td)
-{
- stlbrd_t *brdp;
- int brdnr, rc;
-
-#if DEBUG
- printf("stl_memioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n",
- devtoname(dev), cmd, (void *) data, flag);
-#endif
-
- brdnr = minor(dev) & 0x7;
- brdp = stl_brds[brdnr];
- if (brdp == (stlbrd_t *) NULL)
- return(ENODEV);
- if (brdp->state == 0)
- return(ENODEV);
-
- rc = 0;
-
- switch (cmd) {
- case COM_GETPORTSTATS:
- rc = stl_getportstats((stlport_t *) NULL, data);
- break;
- case COM_CLRPORTSTATS:
- rc = stl_clrportstats((stlport_t *) NULL, data);
- break;
- case COM_GETBRDSTATS:
- rc = stl_getbrdstats(data);
- break;
- default:
- rc = ENOTTY;
- break;
- }
-
- return(rc);
-}
-
-/*****************************************************************************/
OpenPOWER on IntegriCloud