summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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