From: Sascha Wildner Date: Mon, 3 Aug 2015 08:16:50 +0000 (+0200) Subject: i386 removal, part 29/x: Remove old serial drivers, cy(4) and stl(4). X-Git-Tag: v4.5.0~984 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/d69d461d812b3c3b40b49082487919e9cded1661 i386 removal, part 29/x: Remove old serial drivers, cy(4) and stl(4). stlstats(8), too. --- diff --git a/Makefile_upgrade.inc b/Makefile_upgrade.inc index 89738d6ffe..82f723a643 100644 --- a/Makefile_upgrade.inc +++ b/Makefile_upgrade.inc @@ -2161,15 +2161,17 @@ TO_REMOVE+=/usr/share/locale/kk_KZ* TO_REMOVE+=/usr/share/locale/UTF-8 TO_REMOVE+=/usr/sbin/pnpinfo TO_REMOVE+=/usr/share/man/man8/pnpinfo.8.gz - -.if ${MACHINE_ARCH} == "x86_64" +TO_REMOVE+=/usr/include/machine/cdk.h +TO_REMOVE+=/usr/include/machine/comstats.h TO_REMOVE+=/usr/sbin/stlstats TO_REMOVE+=/usr/share/man/man8/i386/stlstats.8.gz TO_REMOVE+=/usr/share/man/man4/i386/stl.4.gz +TO_REMOVE+=/boot/kernel/pst.ko + +.if ${MACHINE_ARCH} == "x86_64" TO_REMOVE+=/usr/sbin/kgzip TO_REMOVE+=/usr/share/man/man8/kgzip.8.gz TO_REMOVE+=/boot/kernel/glxsb.ko -TO_REMOVE+=/boot/kernel/pst.ko .endif .if !defined(WANT_INSTALLER) diff --git a/sys/dev/serial/cy/cd1400.h b/sys/dev/serial/cy/cd1400.h deleted file mode 100644 index d257b25410..0000000000 --- a/sys/dev/serial/cy/cd1400.h +++ /dev/null @@ -1,203 +0,0 @@ -/*- - * cyclades cyclom-y serial driver - * Andrew Herbert , 17 August 1993 - * - * Copyright (c) 1993 Andrew Herbert. - * 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. The name Andrew Herbert may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``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 I 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: src/sys/i386/isa/ic/cd1400.h,v 1.6 1999/08/28 00:45:12 peter Exp $ - */ - -/* - * Definitions for Cirrus Logic CD1400 serial/parallel chips. - */ - -#define CD1400_NO_OF_CHANNELS 4 /* 4 serial channels per chip */ -#define CD1400_RX_FIFO_SIZE 12 -#define CD1400_TX_FIFO_SIZE 12 - -/* - * Global registers. - */ -#define CD1400_GFRCR 0x40 /* global firmware revision code */ -#define CD1400_CAR 0x68 /* channel access */ -#define CD1400_CAR_CHAN (3<<0) /* channel select */ -#define CD1400_GCR 0x4B /* global configuration */ -#define CD1400_GCR_PARALLEL (1<<7) /* channel 0 is parallel */ -#define CD1400_SVRR 0x67 /* service request */ -#define CD1400_SVRR_MDMCH (1<<2) -#define CD1400_SVRR_TXRDY (1<<1) -#define CD1400_SVRR_RXRDY (1<<0) -#define CD1400_RICR 0x44 /* receive interrupting channel */ -#define CD1400_TICR 0x45 /* transmit interrupting channel */ -#define CD1400_MICR 0x46 /* modem interrupting channel */ -#define CD1400_RIR 0x6B /* receive interrupt status */ -#define CD1400_RIR_RDIREQ (1<<7) /* rx service required */ -#define CD1400_RIR_RBUSY (1<<6) /* rx service in progress */ -#define CD1400_RIR_CHAN (3<<0) /* channel select */ -#define CD1400_TIR 0x6A /* transmit interrupt status */ -#define CD1400_TIR_RDIREQ (1<<7) /* tx service required */ -#define CD1400_TIR_RBUSY (1<<6) /* tx service in progress */ -#define CD1400_TIR_CHAN (3<<0) /* channel select */ -#define CD1400_MIR 0x69 /* modem interrupt status */ -#define CD1400_MIR_RDIREQ (1<<7) /* modem service required */ -#define CD1400_MIR_RBUSY (1<<6) /* modem service in progress */ -#define CD1400_MIR_CHAN (3<<0) /* channel select */ -#define CD1400_PPR 0x7E /* prescaler period */ -#define CD1400_PPR_PRESCALER 512 - -/* - * Virtual registers. - */ -#define CD1400_RIVR 0x43 /* receive interrupt vector */ -#define CD1400_RIVR_EXCEPTION (1<<2) /* receive exception bit */ -#define CD1400_TIVR 0x42 /* transmit interrupt vector */ -#define CD1400_MIVR 0x41 /* modem interrupt vector */ -#define CD1400_TDR 0x63 /* transmit data */ -#define CD1400_RDSR 0x62 /* receive data/status */ -#define CD1400_RDSR_TIMEOUT (1<<7) /* rx timeout */ -#define CD1400_RDSR_SPECIAL_SHIFT 4 /* rx special char shift */ -#define CD1400_RDSR_SPECIAL (7<<4) /* rx special char */ -#define CD1400_RDSR_BREAK (1<<3) /* rx break */ -#define CD1400_RDSR_PE (1<<2) /* rx parity error */ -#define CD1400_RDSR_FE (1<<1) /* rx framing error */ -#define CD1400_RDSR_OE (1<<0) /* rx overrun error */ -#define CD1400_MISR 0x4C /* modem interrupt status */ -#define CD1400_MISR_DSRd (1<<7) /* DSR delta */ -#define CD1400_MISR_CTSd (1<<6) /* CTS delta */ -#define CD1400_MISR_RId (1<<5) /* RI delta */ -#define CD1400_MISR_CDd (1<<4) /* CD delta */ -#define CD1400_EOSRR 0x60 /* end of service request */ - -/* - * Channel registers. - */ -#define CD1400_LIVR 0x18 /* local interrupt vector */ -#define CD1400_CCR 0x05 /* channel control */ -#define CD1400_CCR_CMDRESET (1<<7) /* enables following: */ -#define CD1400_CCR_FTF (1<<1) /* flush tx fifo */ -#define CD1400_CCR_FULLRESET (1<<0) /* full reset */ -#define CD1400_CCR_CHANRESET 0 /* current channel */ -#define CD1400_CCR_CMDCORCHG (1<<6) /* enables following: */ -#define CD1400_CCR_COR3 (1<<3) /* COR3 changed */ -#define CD1400_CCR_COR2 (1<<2) /* COR2 changed */ -#define CD1400_CCR_COR1 (1<<1) /* COR1 changed */ -#define CD1400_CCR_CMDSENDSC (1<<5) /* enables following: */ -#define CD1400_CCR_SC (7<<0) /* special char 1-4 */ -#define CD1400_CCR_CMDCHANCTL (1<<4) /* enables following: */ -#define CD1400_CCR_XMTEN (1<<3) /* tx enable */ -#define CD1400_CCR_XMTDIS (1<<2) /* tx disable */ -#define CD1400_CCR_RCVEN (1<<1) /* rx enable */ -#define CD1400_CCR_RCVDIS (1<<0) /* rx disable */ -#define CD1400_SRER 0x06 /* service request enable */ -#define CD1400_SRER_MDMCH (1<<7) /* modem change */ -#define CD1400_SRER_RXDATA (1<<4) /* rx data */ -#define CD1400_SRER_TXRDY (1<<2) /* tx fifo empty */ -#define CD1400_SRER_TXMPTY (1<<1) /* tx shift reg empty */ -#define CD1400_SRER_NNDT (1<<0) /* no new data */ -#define CD1400_COR1 0x08 /* channel option 1 */ -#define CD1400_COR1_PARODD (1<<7) -#define CD1400_COR1_PARNORMAL (2<<5) -#define CD1400_COR1_PARFORCE (1<<5) /* odd/even = force 1/0 */ -#define CD1400_COR1_PARNONE (0<<5) -#define CD1400_COR1_NOINPCK (1<<4) -#define CD1400_COR1_STOP2 (2<<2) -#define CD1400_COR1_STOP15 (1<<2) /* 1.5 stop bits */ -#define CD1400_COR1_STOP1 (0<<2) -#define CD1400_COR1_CS8 (3<<0) -#define CD1400_COR1_CS7 (2<<0) -#define CD1400_COR1_CS6 (1<<0) -#define CD1400_COR1_CS5 (0<<0) -#define CD1400_COR2 0x09 /* channel option 2 */ -#define CD1400_COR2_IXANY (1<<7) /* implied XON mode */ -#define CD1400_COR2_IXOFF (1<<6) /* in-band tx flow control */ -#define CD1400_COR2_ETC (1<<5) /* embedded tx command */ -#define CD1400_ETC_CMD 0x00 /* start an ETC */ -#define CD1400_ETC_SENDBREAK 0x81 -#define CD1400_ETC_INSERTDELAY 0x82 -#define CD1400_ETC_STOPBREAK 0x83 -#define CD1400_COR2_LLM (1<<4) /* local loopback mode */ -#define CD1400_COR2_RLM (1<<3) /* remote loopback mode */ -#define CD1400_COR2_RTSAO (1<<2) /* RTS auto output */ -#define CD1400_COR2_CCTS_OFLOW (1<<1) /* CTS auto enable */ -#define CD1400_COR2_CDSR_OFLOW (1<<0) /* DSR auto enable */ -#define CD1400_COR3 0x0A /* channel option 3 */ -#define CD1400_COR3_SCDRNG (1<<7) /* special char detect range */ -#define CD1400_COR3_SCD34 (1<<6) /* special char detect 3-4 */ -#define CD1400_COR3_FTC (1<<5) /* flow control transparency */ -#define CD1400_COR3_SCD12 (1<<4) /* special char detect 1-2 */ -#define CD1400_COR3_RXTH (15<<0) /* rx fifo threshold */ -#define CD1400_COR4 0x1E /* channel option 4 */ -#define CD1400_COR4_IGNCR (1<<7) -#define CD1400_COR4_ICRNL (1<<6) -#define CD1400_COR4_INLCR (1<<5) -#define CD1400_COR4_IGNBRK (1<<4) -#define CD1400_COR4_NOBRKINT (1<<3) -#define CD1400_COR4_PFO_ESC (4<<0) /* parity/framing/overrun... */ -#define CD1400_COR4_PFO_NUL (3<<0) -#define CD1400_COR4_PFO_DISCARD (2<<0) -#define CD1400_COR4_PFO_GOOD (1<<0) -#define CD1400_COR4_PFO_EXCEPTION (0<<0) -#define CD1400_COR5 0x1F /* channel option 5 */ -#define CD1400_COR5_ISTRIP (1<<7) -#define CD1400_COR5_LNEXT (1<<6) -#define CD1400_COR5_CMOE (1<<5) /* char matching on error */ -#define CD1400_COR5_EBD (1<<2) /* end of break detected */ -#define CD1400_COR5_ONLCR (1<<1) -#define CD1400_COR5_OCRNL (1<<0) -#define CD1400_CCSR 0x0B /* channel control status */ -#define CD1400_RDCR 0x0E /* received data count */ -#define CD1400_SCHR1 0x1A /* special character 1 */ -#define CD1400_SCHR2 0x1B /* special character 2 */ -#define CD1400_SCHR3 0x1C /* special character 3 */ -#define CD1400_SCHR4 0x1D /* special character 4 */ -#define CD1400_SCRL 0x22 /* special character range, low */ -#define CD1400_SCRH 0x23 /* special character range, high */ -#define CD1400_LNC 0x24 /* lnext character */ -#define CD1400_MCOR1 0x15 /* modem change option 1 */ -#define CD1400_MCOR1_DSRzd (1<<7) /* DSR one-to-zero delta */ -#define CD1400_MCOR1_CTSzd (1<<6) -#define CD1400_MCOR1_RIzd (1<<5) -#define CD1400_MCOR1_CDzd (1<<4) -#define CD1400_MCOR1_DTRth (15<<0) /* dtrflow threshold */ -#define CD1400_MCOR2 0x16 /* modem change option 2 */ -#define CD1400_MCOR2_DSRod (1<<7) /* DSR zero-to-one delta */ -#define CD1400_MCOR2_CTSod (1<<6) -#define CD1400_MCOR2_RIod (1<<5) -#define CD1400_MCOR2_CDod (1<<4) -#define CD1400_RTPR 0x21 /* receive timeout period */ -#define CD1400_MSVR1 0x6C /* modem signal value 1 */ -#define CD1400_MSVR1_RTS (1<<0) /* RTS line (r/w) */ -#define CD1400_MSVR2 0x6D /* modem signal value 2 */ -#define CD1400_MSVR2_DSR (1<<7) /* !DSR line (r) */ -#define CD1400_MSVR2_CTS (1<<6) /* !CTS line (r) */ -#define CD1400_MSVR2_RI (1<<5) /* !RI line (r) */ -#define CD1400_MSVR2_CD (1<<4) /* !CD line (r) */ -#define CD1400_MSVR2_DTR (1<<1) /* DTR line (r/w) */ -#define CD1400_PSVR 0x6F /* printer signal value */ -#define CD1400_RBPR 0x78 /* receive baud rate period */ -#define CD1400_RCOR 0x7C /* receive clock option */ -#define CD1400_TBPR 0x72 /* transmit baud rate period */ -#define CD1400_TCOR 0x76 /* transmit clock option */ diff --git a/sys/dev/serial/cy/cy.c b/sys/dev/serial/cy/cy.c deleted file mode 100644 index 95465fb168..0000000000 --- a/sys/dev/serial/cy/cy.c +++ /dev/null @@ -1,2886 +0,0 @@ -/*- - * (MPSAFE) - * - * cyclades cyclom-y serial driver - * Andrew Herbert , 17 August 1993 - * - * Copyright (c) 1993 Andrew Herbert. - * 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. The name Andrew Herbert may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ``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 I 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: src/sys/i386/isa/cy.c,v 1.97.2.2 2001/08/22 13:04:58 bde Exp $ - */ - -#include "opt_compat.h" -#include "use_cy.h" - -/* - * TODO: - * Atomic COR change. - * Consoles. - */ - -/* - * Temporary compile-time configuration options. - */ -#define RxFifoThreshold (CD1400_RX_FIFO_SIZE / 2) - /* Number of chars in the receiver FIFO before an - * an interrupt is generated. Should depend on - * line speed. Needs to be about 6 on a 486DX33 - * for 4 active ports at 115200 bps. Why doesn't - * 10 work? - */ -#define PollMode /* Use polling-based irq service routine, not the - * hardware svcack lines. Must be defined for - * Cyclom-16Y boards. Less efficient for Cyclom-8Ys, - * and stops 4 * 115200 bps from working. - */ -#undef Smarts /* Enable slightly more CD1400 intelligence. Mainly - * the output CR/LF processing, plus we can avoid a - * few checks usually done in ttyinput(). - * - * XXX not fully implemented, and not particularly - * worthwhile. - */ -#undef CyDebug /* Include debugging code (not very expensive). */ - -/* These will go away. */ -#undef SOFT_CTS_OFLOW -#define SOFT_HOTCHAR - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cyreg.h" -#include "cd1400.h" - -#define disable_intr() com_lock() -#define enable_intr() com_unlock() - -/* - * Dictionary so that I can name everything *sio* or *com* to compare with - * sio.c. There is also lots of ugly formatting and unnecessary ifdefs to - * simplify the comparision. These will go away. - */ -#define LSR_BI CD1400_RDSR_BREAK -#define LSR_FE CD1400_RDSR_FE -#define LSR_OE CD1400_RDSR_OE -#define LSR_PE CD1400_RDSR_PE -#define MCR_DTR CD1400_MSVR2_DTR -#define MCR_RTS CD1400_MSVR1_RTS -#define MSR_CTS CD1400_MSVR2_CTS -#define MSR_DCD CD1400_MSVR2_CD -#define MSR_DSR CD1400_MSVR2_DSR -#define MSR_RI CD1400_MSVR2_RI -#define NSIO (NCY * CY_MAX_PORTS) -#define comconsole cyconsole -#define comdefaultrate cydefaultrate -#define com_events cy_events -#define comhardclose cyhardclose -#define commctl cymctl -#define comparam cyparam -#define comspeed cyspeed -#define comstart cystart -#define comwakeup cywakeup -#define nsio_tty ncy_tty -#define p_com_addr p_cy_addr -#define sioattach cyattach -#define sioclose cyclose -#define siodriver cydriver -#define siodtrwakeup cydtrwakeup -#define sioinput cyinput -#define siointr cyintr -#define siointr1 cyintr1 -#define sioioctl cyioctl -#define sioopen cyopen -#define siopoll cypoll -#define sioprobe cyprobe -#define siosettimeout cysettimeout -#define siosetwater cysetwater -#define comstop cystop -#define siowrite cywrite -#define sio_registered cy_registered -#define sio_timeout cy_timeout -#define sio_timeout_handle cy_timeout_handle -#define sio_timeouts_until_log cy_timeouts_until_log -#define sio_tty cy_tty - -#define CY_MAX_PORTS (CD1400_NO_OF_CHANNELS * CY_MAX_CD1400s) - -/* We encode the cyclom unit number (cyu) in spare bits in the IVR's. */ -#define CD1400_xIVR_CHAN_SHIFT 3 -#define CD1400_xIVR_CHAN 0x1F - -/* - * ETC states. com->etc may also contain a hardware ETC command value, - * meaning that execution of that command is pending. - */ -#define ETC_NONE 0 /* we depend on bzero() setting this */ -#define ETC_BREAK_STARTING 1 -#define ETC_BREAK_STARTED 2 -#define ETC_BREAK_ENDING 3 -#define ETC_BREAK_ENDED 4 - -#define LOTS_OF_EVENTS 64 /* helps separate urgent events from input */ - -#define CALLOUT_MASK 0x80 -#define CONTROL_MASK 0x60 -#define CONTROL_INIT_STATE 0x20 -#define CONTROL_LOCK_STATE 0x40 -#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) -#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) -/* - * Not all of the magic is parametrized in the following macros. 16 and - * 0xff are related to the bitfields in a udev_t. CY_MAX_PORTS must be - * ((0xff & ~MINOR_MAGIC_MASK) + 1) for things to work. - */ -#define MINOR_TO_UNIT(mynor) (((mynor) >> 16) * CY_MAX_PORTS \ - | (((mynor) & 0xff) & ~MINOR_MAGIC_MASK)) -#define UNIT_TO_MINOR(unit) (((unit) / CY_MAX_PORTS) << 16 \ - | (((unit) & 0xff) & ~MINOR_MAGIC_MASK)) - -/* - * com state bits. - * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher - * than the other bits so that they can be tested as a group without masking - * off the low bits. - * - * The following com and tty flags correspond closely: - * CS_BUSY = TS_BUSY (maintained by comstart(), siopoll() and - * comstop()) - * CS_TTGO = ~TS_TTSTOP (maintained by comparam() and comstart()) - * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) - * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) - * TS_FLUSH is not used. - * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. - * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). - */ -#define CS_BUSY 0x80 /* output in progress */ -#define CS_TTGO 0x40 /* output not stopped by XOFF */ -#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ -#define CS_CHECKMSR 1 /* check of MSR scheduled */ -#define CS_CTS_OFLOW 2 /* use CTS output flow control */ -#define CS_DTR_OFF 0x10 /* DTR held off */ -#define CS_ODONE 4 /* output completed */ -#define CS_RTS_IFLOW 8 /* use RTS input flow control */ -#define CSE_ODONE 1 /* output transmitted */ - -static char const * const error_desc[] = { -#define CE_OVERRUN 0 - "silo overflow", -#define CE_INTERRUPT_BUF_OVERFLOW 1 - "interrupt-level buffer overflow", -#define CE_TTY_BUF_OVERFLOW 2 - "tty-level buffer overflow", -}; - -#define CE_NTYPES 3 -#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) - -/* types. XXX - should be elsewhere */ -typedef u_char bool_t; /* boolean */ -typedef u_char volatile *cy_addr; - -/* queue of linear buffers */ -struct lbq { - u_char *l_head; /* next char to process */ - u_char *l_tail; /* one past the last char to process */ - struct lbq *l_next; /* next in queue */ - bool_t l_queued; /* nonzero if queued */ -}; - -/* com device structure */ -struct com_s { - u_char state; /* miscellaneous flag bits */ - bool_t active_out; /* nonzero if the callout device is open */ -#if 0 - u_char cfcr_image; /* copy of value written to CFCR */ -#endif - u_char etc; /* pending Embedded Transmit Command */ - u_char extra_state; /* more flag bits, separate for order trick */ -#if 0 - u_char fifo_image; /* copy of value written to FIFO */ -#endif - u_char gfrcr_image; /* copy of value read from GFRCR */ -#if 0 - bool_t hasfifo; /* nonzero for 16550 UARTs */ - bool_t loses_outints; /* nonzero if device loses output interrupts */ -#endif - u_char mcr_dtr; /* MCR bit that is wired to DTR */ - u_char mcr_image; /* copy of value written to MCR */ - u_char mcr_rts; /* MCR bit that is wired to RTS */ -#if 0 -#ifdef COM_MULTIPORT - bool_t multiport; /* is this unit part of a multiport device? */ -#endif /* COM_MULTIPORT */ - bool_t no_irq; /* nonzero if irq is not attached */ - bool_t poll; /* nonzero if polling is required */ - bool_t poll_output; /* nonzero if polling for output is required */ -#endif - int unit; /* unit number */ - int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ - struct callout dtr_ch; -#if 0 - u_int tx_fifo_size; -#endif - u_int wopeners; /* # processes waiting for DCD in open() */ - - /* - * The high level of the driver never reads status registers directly - * because there would be too many side effects to handle conveniently. - * Instead, it reads copies of the registers stored here by the - * interrupt handler. - */ - u_char last_modem_status; /* last MSR read by intr handler */ - u_char prev_modem_status; /* last MSR handled by high level */ - - u_char hotchar; /* ldisc-specific char to be handled ASAP */ - u_char *ibuf; /* start of input buffer */ - u_char *ibufend; /* end of input buffer */ - u_char *ibufold; /* old input buffer, to be freed */ - u_char *ihighwater; /* threshold in input buffer */ - u_char *iptr; /* next free spot in input buffer */ - int ibufsize; /* size of ibuf (not include error bytes) */ - int ierroff; /* offset of error bytes in ibuf */ - - struct lbq obufq; /* head of queue of output buffers */ - struct lbq obufs[2]; /* output buffers */ - - int cy_align; /* index for register alignment */ - cy_addr cy_iobase; /* base address of this port's cyclom */ - cy_addr iobase; /* base address of this port's cd1400 */ - int mcr_rts_reg; /* cd1400 reg number of reg holding mcr_rts */ - - struct tty *tp; /* cross reference */ - - /* Initial state. */ - struct termios it_in; /* should be in struct tty */ - struct termios it_out; - - /* Lock state. */ - struct termios lt_in; /* should be in struct tty */ - struct termios lt_out; - - bool_t do_timestamp; - bool_t do_dcd_timestamp; - struct timeval timestamp; - struct timeval dcd_timestamp; - - u_long bytes_in; /* statistics */ - u_long bytes_out; - u_int delta_error_counts[CE_NTYPES]; - u_long error_counts[CE_NTYPES]; - - u_int recv_exception; /* exception chars received */ - u_int mdm; /* modem signal changes */ -#ifdef CyDebug - u_int start_count; /* no. of calls to comstart() */ - u_int start_real; /* no. of calls that did something */ -#endif - u_char car; /* CD1400 CAR shadow (if first unit in cd) */ - u_char channel_control;/* CD1400 CCR control command shadow */ - u_char cor[3]; /* CD1400 COR1-3 shadows */ - u_char intr_enable; /* CD1400 SRER shadow */ - - /* - * Data area for output buffers. Someday we should build the output - * buffer queue without copying data. - */ - u_char obuf1[256]; - u_char obuf2[256]; -}; - -/* PCI driver entry point. */ -int cyattach_common (cy_addr cy_iobase, int cy_align); -void siointr(void *); - -static int cy_units (cy_addr cy_iobase, int cy_align); -static void cd1400_channel_cmd (struct com_s *com, int cmd); -static void cd1400_channel_cmd_wait (struct com_s *com); -static void cd_etc (struct com_s *com, int etc); -static int cd_getreg (struct com_s *com, int reg); -static void cd_setreg (struct com_s *com, int reg, int val); -static timeout_t siodtrwakeup; -static void comhardclose (struct com_s *com); -static void sioinput (struct com_s *com); -#if 0 -static void siointr1 (struct com_s *com); -#endif -static int commctl (struct com_s *com, int bits, int how); -static int comparam (struct tty *tp, struct termios *t); -static inthand2_t siopoll; -static void siosettimeout (void); -static int siosetwater (struct com_s *com, speed_t speed); -static int comspeed (speed_t speed, u_long cy_clock, - int *prescaler_io); -static void comstart (struct tty *tp); -static void comstop (struct tty *tp, int rw); -static timeout_t comwakeup; -static void disc_optim (struct tty *tp, struct termios *t, - struct com_s *com); - -#ifdef CyDebug -void cystatus (int unit); -#endif - -static char driver_name[] = "cy"; - -/* table and macro for fast conversion from a unit number to its com struct */ -static struct com_s *p_com_addr[NSIO]; -#define com_addr(unit) (p_com_addr[unit]) - -static d_open_t sioopen; -static d_close_t sioclose; -static d_write_t siowrite; -static d_ioctl_t sioioctl; - -static struct dev_ops sio_ops = { - { driver_name, 0, D_TTY }, - .d_open = sioopen, - .d_close = sioclose, - .d_read = ttyread, - .d_write = siowrite, - .d_ioctl = sioioctl, - .d_kqfilter = ttykqfilter, - .d_revoke = ttyrevoke -}; - -static int comconsole = -1; -static speed_t comdefaultrate = TTYDEF_SPEED; -static u_int com_events; /* input chars + weighted output completions */ -static bool_t sio_registered; -static int sio_timeout; -static int sio_timeouts_until_log; -static struct callout sio_timeout_handle; -#if 0 /* XXX */ -static struct tty *sio_tty[NSIO]; -#else -static struct tty sio_tty[NSIO]; -#endif -static const int nsio_tty = NSIO; - -#ifdef CyDebug -static u_int cd_inbs; -static u_int cy_inbs; -static u_int cd_outbs; -static u_int cy_outbs; -static u_int cy_svrr_probes; -static u_int cy_timeouts; -#endif - -static int cy_chip_offset[] = { - 0x0000, 0x0400, 0x0800, 0x0c00, 0x0200, 0x0600, 0x0a00, 0x0e00, -}; -static int cy_nr_cd1400s[NCY]; -static int cy_total_devices; -#undef RxFifoThreshold -static int volatile RxFifoThreshold = (CD1400_RX_FIFO_SIZE / 2); - -static int -cy_units(cy_addr cy_iobase, int cy_align) -{ - int cyu; - u_char firmware_version = 0; /* assign to avoid warning */ - int i; - cy_addr iobase; - - for (cyu = 0; cyu < CY_MAX_CD1400s; ++cyu) { - iobase = cy_iobase + (cy_chip_offset[cyu] << cy_align); - - /* wait for chip to become ready for new command */ - for (i = 0; i < 10; i++) { - DELAY(50); - if (!cd_inb(iobase, CD1400_CCR, cy_align)) - break; - } - - /* clear the GFRCR register */ - cd_outb(iobase, CD1400_GFRCR, cy_align, 0); - - /* issue a reset command */ - cd_outb(iobase, CD1400_CCR, cy_align, - CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET); - - /* wait for the CD1400 to initialize itself */ - for (i = 0; i < 200; i++) { - DELAY(50); - - /* retrieve firmware version */ - firmware_version = cd_inb(iobase, CD1400_GFRCR, - cy_align); - if ((firmware_version & 0xf0) == 0x40) - break; - } - - /* - * Anything in the 0x40-0x4F range is fine. - * If one CD1400 is bad then we don't support higher - * numbered good ones on this board. - */ - if ((firmware_version & 0xf0) != 0x40) - break; - } - return (cyu); -} - -/* - * NOTE: Must be called with tty_token held - */ -int -cyattach_common(cy_addr cy_iobase, int cy_align) -{ - int adapter; - int cyu; - u_char firmware_version; - cy_addr iobase; - int minorbase; - int ncyu; - int unit; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - adapter = cy_total_devices; - if ((u_int)adapter >= NCY) { - kprintf( - "cy%d: can't attach adapter: insufficient cy devices configured\n", - adapter); - return (-1); - } - ncyu = cy_units(cy_iobase, cy_align); - if (ncyu == 0) - return (-1); - cy_nr_cd1400s[adapter] = ncyu; - cy_total_devices++; - - unit = adapter * CY_MAX_PORTS; - for (cyu = 0; cyu < ncyu; ++cyu) { - int cdu; - - iobase = (cy_addr) (cy_iobase - + (cy_chip_offset[cyu] << cy_align)); - firmware_version = cd_inb(iobase, CD1400_GFRCR, cy_align); - - /* Set up a receive timeout period of than 1+ ms. */ - cd_outb(iobase, CD1400_PPR, cy_align, - howmany(CY_CLOCK(firmware_version) - / CD1400_PPR_PRESCALER, 1000)); - - for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; ++cdu, ++unit) { - struct com_s *com; - - com = kmalloc(sizeof *com, M_DEVBUF, M_WAITOK | M_ZERO); - com->unit = unit; - callout_init_mp(&com->dtr_ch); - com->gfrcr_image = firmware_version; - if (CY_RTS_DTR_SWAPPED(firmware_version)) { - com->mcr_dtr = MCR_RTS; - com->mcr_rts = MCR_DTR; - com->mcr_rts_reg = CD1400_MSVR2; - } else { - com->mcr_dtr = MCR_DTR; - com->mcr_rts = MCR_RTS; - com->mcr_rts_reg = CD1400_MSVR1; - } - com->dtr_wait = 3 * hz; - com->obufs[0].l_head = com->obuf1; - com->obufs[1].l_head = com->obuf2; - - com->cy_align = cy_align; - com->cy_iobase = cy_iobase; - com->iobase = iobase; - com->car = ~CD1400_CAR_CHAN; - - /* - * We don't use all the flags from since they - * are only relevant for logins. It's important to have echo off - * initially so that the line doesn't start blathering before the - * echo flag can be turned off. - */ - com->it_in.c_iflag = 0; - com->it_in.c_oflag = 0; - com->it_in.c_cflag = TTYDEF_CFLAG; - com->it_in.c_lflag = 0; - if (unit == comconsole) { - com->it_in.c_iflag = TTYDEF_IFLAG; - com->it_in.c_oflag = TTYDEF_OFLAG; - com->it_in.c_cflag = TTYDEF_CFLAG | CLOCAL; - com->it_in.c_lflag = TTYDEF_LFLAG; - com->lt_out.c_cflag = com->lt_in.c_cflag = CLOCAL; - } - if (siosetwater(com, com->it_in.c_ispeed) != 0) { - enable_intr(); - kfree(com, M_DEVBUF); - return (0); - } - enable_intr(); - termioschars(&com->it_in); - com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate; - com->it_out = com->it_in; - - crit_enter(); - com_addr(unit) = com; - crit_exit(); - - if (!sio_registered) { - callout_init_mp(&sio_timeout_handle); - register_swi_mp(SWI_TTY, siopoll, NULL, "cy", NULL, -1); - sio_registered = TRUE; - } - minorbase = UNIT_TO_MINOR(unit); - make_dev(&sio_ops, minorbase, - UID_ROOT, GID_WHEEL, 0600, "ttyc%r%r", adapter, - unit % CY_MAX_PORTS); - make_dev(&sio_ops, minorbase | CONTROL_INIT_STATE, - UID_ROOT, GID_WHEEL, 0600, "ttyic%r%r", adapter, - unit % CY_MAX_PORTS); - make_dev(&sio_ops, minorbase | CONTROL_LOCK_STATE, - UID_ROOT, GID_WHEEL, 0600, "ttylc%r%r", adapter, - unit % CY_MAX_PORTS); - make_dev(&sio_ops, minorbase | CALLOUT_MASK, - UID_UUCP, GID_DIALER, 0660, "cuac%r%r", adapter, - unit % CY_MAX_PORTS); - make_dev(&sio_ops, minorbase | CALLOUT_MASK | CONTROL_INIT_STATE, - UID_UUCP, GID_DIALER, 0660, "cuaic%r%r", adapter, - unit % CY_MAX_PORTS); - make_dev(&sio_ops, minorbase | CALLOUT_MASK | CONTROL_LOCK_STATE, - UID_UUCP, GID_DIALER, 0660, "cualc%r%r", adapter, - unit % CY_MAX_PORTS); - - /* for(cdu...), for(cyu...) terminating blocks */ - } - } - - /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - - return (adapter); -} - -static int -sioopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct com_s *com; - int error; - int mynor; - struct tty *tp; - int unit; - - mynor = minor(dev); - unit = MINOR_TO_UNIT(mynor); - if ((u_int) unit >= NSIO || (com = com_addr(unit)) == NULL) - return (ENXIO); - if (mynor & CONTROL_MASK) - return (0); - - lwkt_gettoken(&tty_token); -#if 0 /* XXX */ - tp = com->tp = sio_tty[unit] = ttymalloc(sio_tty[unit]); -#else - tp = com->tp = &sio_tty[unit]; -#endif - dev->si_tty = tp; - crit_enter(); - /* - * We jump to this label after all non-interrupted sleeps to pick - * up any changes of the device state. - */ -open_top: - while (com->state & CS_DTR_OFF) { - error = tsleep(&com->dtr_wait, PCATCH, "cydtr", 0); - if (error != 0) - goto out; - } - if (tp->t_state & TS_ISOPEN) { - /* - * The device is open, so everything has been initialized. - * Handle conflicts. - */ - if (mynor & CALLOUT_MASK) { - if (!com->active_out) { - error = EBUSY; - goto out; - } - } else { - if (com->active_out) { - if (ap->a_oflags & O_NONBLOCK) { - error = EBUSY; - goto out; - } - error = tsleep(&com->active_out, - PCATCH, "cybi", 0); - if (error != 0) - goto out; - goto open_top; - } - } - if (tp->t_state & TS_XCLUDE && - priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) { - error = EBUSY; - goto out; - } - } else { - /* - * The device isn't open, so there are no conflicts. - * Initialize it. Initialization is done twice in many - * cases: to preempt sleeping callin opens if we are - * callout, and to complete a callin open after DCD rises. - */ - tp->t_oproc = comstart; - tp->t_stop = comstop; - tp->t_param = comparam; - tp->t_dev = dev; - tp->t_termios = mynor & CALLOUT_MASK - ? com->it_out : com->it_in; - - /* Encode per-board unit in LIVR for access in intr routines. */ - cd_setreg(com, CD1400_LIVR, - (unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); - - (void)commctl(com, TIOCM_DTR | TIOCM_RTS, DMSET); -#if 0 - com->poll = com->no_irq; - com->poll_output = com->loses_outints; -#endif - ++com->wopeners; - error = comparam(tp, &tp->t_termios); - --com->wopeners; - if (error != 0) - goto out; -#if 0 - if (com->hasfifo) { - /* - * (Re)enable and flush fifos. - * - * Certain SMC chips cause problems if the fifos - * are enabled while input is ready. Turn off the - * fifo if necessary to clear the input. We test - * the input ready bit after enabling the fifos - * since we've already enabled them in comparam() - * and to handle races between enabling and fresh - * input. - */ - while (TRUE) { - outb(iobase + com_fifo, - FIFO_RCV_RST | FIFO_XMT_RST - | com->fifo_image); - DELAY(100); - if (!(inb(com->line_status_port) & LSR_RXRDY)) - break; - outb(iobase + com_fifo, 0); - DELAY(100); - (void) inb(com->data_port); - } - } - - disable_intr(); - (void) inb(com->line_status_port); - (void) inb(com->data_port); - com->prev_modem_status = com->last_modem_status - = inb(com->modem_status_port); - outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS - | IER_EMSC); - enable_intr(); -#else /* !0 */ - /* - * Flush fifos. This requires a full channel reset which - * also disables the transmitter and receiver. Recover - * from this. - */ - cd1400_channel_cmd(com, - CD1400_CCR_CMDRESET | CD1400_CCR_CHANRESET); - cd1400_channel_cmd(com, com->channel_control); - - disable_intr(); - com->prev_modem_status = com->last_modem_status - = cd_getreg(com, CD1400_MSVR2); - cd_setreg(com, CD1400_SRER, - com->intr_enable - = CD1400_SRER_MDMCH | CD1400_SRER_RXDATA); - enable_intr(); -#endif /* 0 */ - /* - * Handle initial DCD. Callout devices get a fake initial - * DCD (trapdoor DCD). If we are callout, then any sleeping - * callin opens get woken up and resume sleeping on "cybi" - * instead of "cydcd". - */ - /* - * XXX `mynor & CALLOUT_MASK' should be - * `tp->t_cflag & (SOFT_CARRIER | TRAPDOOR_CARRIER) where - * TRAPDOOR_CARRIER is the default initial state for callout - * devices and SOFT_CARRIER is like CLOCAL except it hides - * the true carrier. - */ - if (com->prev_modem_status & MSR_DCD || mynor & CALLOUT_MASK) - (*linesw[tp->t_line].l_modem)(tp, 1); - } - /* - * Wait for DCD if necessary. - */ - if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) - && !(tp->t_cflag & CLOCAL) && !(ap->a_oflags & O_NONBLOCK)) { - ++com->wopeners; - error = tsleep(TSA_CARR_ON(tp), PCATCH, "cydcd", 0); - --com->wopeners; - if (error != 0) - goto out; - goto open_top; - } - error = (*linesw[tp->t_line].l_open)(dev, tp); - disc_optim(tp, &tp->t_termios, com); - if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) - com->active_out = TRUE; - siosettimeout(); -out: - crit_exit(); - if (!(tp->t_state & TS_ISOPEN) && com->wopeners == 0) - comhardclose(com); - lwkt_reltoken(&tty_token); - return (error); -} - -/* - * NOTE: Must be called with tty_token held - */ -static int -sioclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct com_s *com; - int mynor; - struct tty *tp; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - mynor = minor(dev); - if (mynor & CONTROL_MASK) - return (0); - lwkt_gettoken(&tty_token); - com = com_addr(MINOR_TO_UNIT(mynor)); - tp = com->tp; - crit_enter(); - cd_etc(com, CD1400_ETC_STOPBREAK); - (*linesw[tp->t_line].l_close)(tp, ap->a_fflag); - disc_optim(tp, &tp->t_termios, com); - comstop(tp, FREAD | FWRITE); - comhardclose(com); - ttyclose(tp); - siosettimeout(); - crit_exit(); -#ifdef broken /* session holds a ref to the tty; can't deallocate */ - ttyfree(tp); - com->tp = sio_tty[unit] = NULL; -#endif - lwkt_reltoken(&tty_token); - return (0); -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -comhardclose(struct com_s *com) -{ - struct tty *tp; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - crit_enter(); -#if 0 - com->poll = FALSE; - com->poll_output = FALSE; -#endif - com->do_timestamp = 0; -#if 0 - outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#else - /* XXX */ - disable_intr(); - com->etc = ETC_NONE; - cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); - enable_intr(); - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); -#endif - - { -#if 0 - outb(iobase + com_ier, 0); -#else - disable_intr(); - cd_setreg(com, CD1400_SRER, com->intr_enable = 0); - enable_intr(); -#endif - tp = com->tp; - if ((tp->t_cflag & HUPCL) - /* - * XXX we will miss any carrier drop between here and the - * next open. Perhaps we should watch DCD even when the - * port is closed; it is not sufficient to check it at - * the next open because it might go up and down while - * we're not watching. - */ - || (!com->active_out - && !(com->prev_modem_status & MSR_DCD) - && !(com->it_in.c_cflag & CLOCAL)) - || !(tp->t_state & TS_ISOPEN)) { - (void)commctl(com, TIOCM_DTR, DMBIC); - - /* Disable receiver (leave transmitter enabled). */ - com->channel_control = CD1400_CCR_CMDCHANCTL - | CD1400_CCR_XMTEN - | CD1400_CCR_RCVDIS; - cd1400_channel_cmd(com, com->channel_control); - - if (com->dtr_wait != 0 && !(com->state & CS_DTR_OFF)) { - callout_reset(&com->dtr_ch, com->dtr_wait, - siodtrwakeup, com); - com->state |= CS_DTR_OFF; - } - } - } -#if 0 - if (com->hasfifo) { - /* - * Disable fifos so that they are off after controlled - * reboots. Some BIOSes fail to detect 16550s when the - * fifos are enabled. - */ - outb(iobase + com_fifo, 0); - } -#endif - com->active_out = FALSE; - wakeup(&com->active_out); - wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ - crit_exit(); -} - -static int -siowrite(struct dev_write_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct uio *uio = ap->a_uio; - int mynor; - struct tty *tp; - int unit; - int ret; - - mynor = minor(dev); - if (mynor & CONTROL_MASK) - return (ENODEV); - - lwkt_gettoken(&tty_token); - unit = MINOR_TO_UNIT(mynor); - tp = com_addr(unit)->tp; - /* - * (XXX) We disallow virtual consoles if the physical console is - * a serial port. This is in case there is a display attached that - * is not the console. In that situation we don't need/want the X - * server taking over the console. - */ - if (constty != NULL && unit == comconsole) - constty = NULL; -#ifdef Smarts - /* XXX duplicate ttwrite(), but without so much output processing on - * CR & LF chars. Hardly worth the effort, given that high-throughput - * sessions are raw anyhow. - */ - ret = 0; -#else - ret = (*linesw[tp->t_line].l_write)(tp, uio, ap->a_ioflag); -#endif - lwkt_reltoken(&tty_token); - return(ret); -} - -static void -siodtrwakeup(void *chan) -{ - struct com_s *com; - - lwkt_gettoken(&tty_token); - com = (struct com_s *)chan; - com->state &= ~CS_DTR_OFF; - wakeup(&com->dtr_wait); - lwkt_reltoken(&tty_token); -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -sioinput(struct com_s *com) -{ - u_char *buf; - int incc; - u_char line_status; - int recv_data; - struct tty *tp; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - buf = com->ibuf; - tp = com->tp; - if (!(tp->t_state & TS_ISOPEN)) { - com_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - return; - } - if (tp->t_state & TS_CAN_BYPASS_L_RINT) { - /* - * Avoid the grotesquely inefficient lineswitch routine - * (ttyinput) in "raw" mode. It usually takes about 450 - * instructions (that's without canonical processing or echo!). - * slinput is reasonably fast (usually 40 instructions plus - * call overhead). - */ - do { - enable_intr(); - incc = com->iptr - buf; - if (tp->t_rawq.c_cc + incc > tp->t_ihiwat - && (com->state & CS_RTS_IFLOW - || tp->t_iflag & IXOFF) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - com->delta_error_counts[CE_TTY_BUF_OVERFLOW] - += b_to_q((char *)buf, incc, &tp->t_rawq); - buf += incc; - tk_nin += incc; - tk_rawcc += incc; - tp->t_rawcc += incc; - ttwakeup(tp); - if (tp->t_state & TS_TTSTOP - && (tp->t_iflag & IXANY - || tp->t_cc[VSTART] == tp->t_cc[VSTOP])) { - tp->t_state &= ~TS_TTSTOP; - tp->t_lflag &= ~FLUSHO; - comstart(tp); - } - disable_intr(); - } while (buf < com->iptr); - } else { - do { - enable_intr(); - line_status = buf[com->ierroff]; - recv_data = *buf++; - if (line_status - & (LSR_BI | LSR_FE | LSR_OE | LSR_PE)) { - if (line_status & LSR_BI) - recv_data |= TTY_BI; - if (line_status & LSR_FE) - recv_data |= TTY_FE; - if (line_status & LSR_OE) - recv_data |= TTY_OE; - if (line_status & LSR_PE) - recv_data |= TTY_PE; - } - (*linesw[tp->t_line].l_rint)(recv_data, tp); - disable_intr(); - } while (buf < com->iptr); - } - com_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - - /* - * There is now room for another low-level buffer full of input, - * so enable RTS if it is now disabled and there is room in the - * high-level buffer. - */ - if ((com->state & CS_RTS_IFLOW) && !(com->mcr_image & com->mcr_rts) && - !(tp->t_state & TS_TBLOCK)) -#if 0 - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -#endif -} - -void -siointr(void *arg) -{ - int unit = (int)arg; - int baseu; - int cy_align; - cy_addr cy_iobase; - int cyu; - cy_addr iobase; - u_char status; - - lwkt_gettoken(&tty_token); - com_lock(); /* XXX could this be placed down lower in the loop? */ - - baseu = unit * CY_MAX_PORTS; - cy_align = com_addr(baseu)->cy_align; - cy_iobase = com_addr(baseu)->cy_iobase; - - /* check each CD1400 in turn */ - for (cyu = 0; cyu < cy_nr_cd1400s[unit]; ++cyu) { - iobase = (cy_addr) (cy_iobase - + (cy_chip_offset[cyu] << cy_align)); - /* poll to see if it has any work */ - status = cd_inb(iobase, CD1400_SVRR, cy_align); - if (status == 0) - continue; -#ifdef CyDebug - ++cy_svrr_probes; -#endif - /* service requests as appropriate, giving priority to RX */ - if (status & CD1400_SVRR_RXRDY) { - struct com_s *com; - u_int count; - u_char *ioptr; - u_char line_status; - u_char recv_data; - u_char serv_type; -#ifdef PollMode - u_char save_rir; -#endif - -#ifdef PollMode - save_rir = cd_inb(iobase, CD1400_RIR, cy_align); - - /* enter rx service */ - cd_outb(iobase, CD1400_CAR, cy_align, save_rir); - com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_rir & CD1400_CAR_CHAN; - - serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); - com = com_addr(baseu - + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#else - /* ack receive service */ - serv_type = cy_inb(iobase, CY8_SVCACKR, cy_align); - - com = com_addr(baseu + - + ((serv_type >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#endif - - if (serv_type & CD1400_RIVR_EXCEPTION) { - ++com->recv_exception; - line_status = cd_inb(iobase, CD1400_RDSR, cy_align); - /* break/unnattached error bits or real input? */ - recv_data = cd_inb(iobase, CD1400_RDSR, cy_align); -#ifndef SOFT_HOTCHAR - if (line_status & CD1400_RDSR_SPECIAL - && com->hotchar != 0) - setsofttty(); -#endif -#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ - if (line_status & (LSR_PE|LSR_FE|LSR_BI)) { - /* - Don't store PE if IGNPAR and BI if IGNBRK, - this hack allows "raw" tty optimization - works even if IGN* is set. - */ - if ( com->tp == NULL - || !(com->tp->t_state & TS_ISOPEN) - || ((line_status & (LSR_PE|LSR_FE)) - && (com->tp->t_iflag & IGNPAR)) - || ((line_status & LSR_BI) - && (com->tp->t_iflag & IGNBRK))) - goto cont; - if ( (line_status & (LSR_PE|LSR_FE)) - && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) - && ((line_status & LSR_FE) - || ((line_status & LSR_PE) - && (com->tp->t_iflag & INPCK)))) - recv_data = 0; - } -#endif /* 1 */ - ++com->bytes_in; -#ifdef SOFT_HOTCHAR - if (com->hotchar != 0 && recv_data == com->hotchar) - setsofttty(); -#endif - ioptr = com->iptr; - if (ioptr >= com->ibufend) - CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); - else { - if (com->do_timestamp) - microtime(&com->timestamp); - ++com_events; - ioptr[0] = recv_data; - ioptr[com->ierroff] = line_status; - com->iptr = ++ioptr; - if (ioptr == com->ihighwater - && com->state & CS_RTS_IFLOW) -#if 0 - outb(com->modem_ctl_port, - com->mcr_image &= ~MCR_RTS); -#else - cd_outb(iobase, com->mcr_rts_reg, - cy_align, - com->mcr_image &= - ~com->mcr_rts); -#endif - if (line_status & LSR_OE) - CE_RECORD(com, CE_OVERRUN); - } - goto cont; - } else { - int ifree; - - count = cd_inb(iobase, CD1400_RDCR, cy_align); - if (!count) - goto cont; - com->bytes_in += count; - ioptr = com->iptr; - ifree = com->ibufend - ioptr; - if (count > ifree) { - count -= ifree; - com_events += ifree; - if (ifree != 0) { - if (com->do_timestamp) - microtime(&com->timestamp); - do { - recv_data = cd_inb(iobase, - CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->hotchar != 0 - && recv_data - == com->hotchar) - setsofttty(); -#endif - ioptr[0] = recv_data; - ioptr[com->ierroff] = 0; - ++ioptr; - } while (--ifree != 0); - } - com->delta_error_counts - [CE_INTERRUPT_BUF_OVERFLOW] += count; - do { - recv_data = cd_inb(iobase, CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->hotchar != 0 - && recv_data == com->hotchar) - setsofttty(); -#endif - } while (--count != 0); - } else { - if (com->do_timestamp) - microtime(&com->timestamp); - if (ioptr <= com->ihighwater - && ioptr + count > com->ihighwater - && com->state & CS_RTS_IFLOW) -#if 0 - outb(com->modem_ctl_port, - com->mcr_image &= ~MCR_RTS); -#else - cd_outb(iobase, com->mcr_rts_reg, - cy_align, - com->mcr_image - &= ~com->mcr_rts); -#endif - com_events += count; - do { - recv_data = cd_inb(iobase, CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->hotchar != 0 - && recv_data == com->hotchar) - setsofttty(); -#endif - ioptr[0] = recv_data; - ioptr[com->ierroff] = 0; - ++ioptr; - } while (--count != 0); - } - com->iptr = ioptr; - } -cont: - - /* terminate service context */ -#ifdef PollMode - cd_outb(iobase, CD1400_RIR, cy_align, - save_rir - & ~(CD1400_RIR_RDIREQ | CD1400_RIR_RBUSY)); -#else - cd_outb(iobase, CD1400_EOSRR, cy_align, 0); -#endif - } - if (status & CD1400_SVRR_MDMCH) { - struct com_s *com; - u_char modem_status; -#ifdef PollMode - u_char save_mir; -#else - u_char vector; -#endif - -#ifdef PollMode - save_mir = cd_inb(iobase, CD1400_MIR, cy_align); - - /* enter modem service */ - cd_outb(iobase, CD1400_CAR, cy_align, save_mir); - com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_mir & CD1400_CAR_CHAN; - - com = com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS - + (save_mir & CD1400_MIR_CHAN)); -#else - /* ack modem service */ - vector = cy_inb(iobase, CY8_SVCACKM, cy_align); - - com = com_addr(baseu - + ((vector >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#endif - ++com->mdm; - modem_status = cd_inb(iobase, CD1400_MSVR2, cy_align); - if (modem_status != com->last_modem_status) { - if (com->do_dcd_timestamp - && !(com->last_modem_status & MSR_DCD) - && modem_status & MSR_DCD) - microtime(&com->dcd_timestamp); - - /* - * Schedule high level to handle DCD changes. Note - * that we don't use the delta bits anywhere. Some - * UARTs mess them up, and it's easy to remember the - * previous bits and calculate the delta. - */ - com->last_modem_status = modem_status; - if (!(com->state & CS_CHECKMSR)) { - com_events += LOTS_OF_EVENTS; - com->state |= CS_CHECKMSR; - setsofttty(); - } - -#ifdef SOFT_CTS_OFLOW - /* handle CTS change immediately for crisp flow ctl */ - if (com->state & CS_CTS_OFLOW) { - if (modem_status & MSR_CTS) { - com->state |= CS_ODEVREADY; - if (com->state >= (CS_BUSY | CS_TTGO - | CS_ODEVREADY) - && !(com->intr_enable - & CD1400_SRER_TXRDY)) - cd_outb(iobase, CD1400_SRER, - cy_align, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXMPTY - | CD1400_SRER_TXRDY); - } else { - com->state &= ~CS_ODEVREADY; - if (com->intr_enable - & CD1400_SRER_TXRDY) - cd_outb(iobase, CD1400_SRER, - cy_align, - com->intr_enable - = com->intr_enable - & ~CD1400_SRER_TXRDY - | CD1400_SRER_TXMPTY); - } - } -#endif - } - - /* terminate service context */ -#ifdef PollMode - cd_outb(iobase, CD1400_MIR, cy_align, - save_mir - & ~(CD1400_MIR_RDIREQ | CD1400_MIR_RBUSY)); -#else - cd_outb(iobase, CD1400_EOSRR, cy_align, 0); -#endif - } - if (status & CD1400_SVRR_TXRDY) { - struct com_s *com; -#ifdef PollMode - u_char save_tir; -#else - u_char vector; -#endif - -#ifdef PollMode - save_tir = cd_inb(iobase, CD1400_TIR, cy_align); - - /* enter tx service */ - cd_outb(iobase, CD1400_CAR, cy_align, save_tir); - com_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_tir & CD1400_CAR_CHAN; - - com = com_addr(baseu - + cyu * CD1400_NO_OF_CHANNELS - + (save_tir & CD1400_TIR_CHAN)); -#else - /* ack transmit service */ - vector = cy_inb(iobase, CY8_SVCACKT, cy_align); - - com = com_addr(baseu - + ((vector >> CD1400_xIVR_CHAN_SHIFT) - & CD1400_xIVR_CHAN)); -#endif - - if (com->etc != ETC_NONE) { - if (com->intr_enable & CD1400_SRER_TXRDY) { - /* - * Here due to sloppy SRER_TXRDY - * enabling. Ignore. Come back when - * tx is empty. - */ - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - goto terminate_tx_service; - } - switch (com->etc) { - case CD1400_ETC_SENDBREAK: - case CD1400_ETC_STOPBREAK: - /* - * Start the command. Come back on - * next tx empty interrupt, hopefully - * after command has been executed. - */ - cd_outb(iobase, CD1400_COR2, cy_align, - com->cor[1] |= CD1400_COR2_ETC); - cd_outb(iobase, CD1400_TDR, cy_align, - CD1400_ETC_CMD); - cd_outb(iobase, CD1400_TDR, cy_align, - com->etc); - if (com->etc == CD1400_ETC_SENDBREAK) - com->etc = ETC_BREAK_STARTING; - else - com->etc = ETC_BREAK_ENDING; - goto terminate_tx_service; - case ETC_BREAK_STARTING: - /* - * BREAK is now on. Continue with - * SRER_TXMPTY processing, hopefully - * don't come back. - */ - com->etc = ETC_BREAK_STARTED; - break; - case ETC_BREAK_STARTED: - /* - * Came back due to sloppy SRER_TXMPTY - * enabling. Hope again. - */ - break; - case ETC_BREAK_ENDING: - /* - * BREAK is now off. Continue with - * SRER_TXMPTY processing and don't - * come back. The SWI handler will - * restart tx interrupts if necessary. - */ - cd_outb(iobase, CD1400_COR2, cy_align, - com->cor[1] - &= ~CD1400_COR2_ETC); - com->etc = ETC_BREAK_ENDED; - if (!(com->state & CS_ODONE)) { - com_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - setsofttty(); - } - break; - case ETC_BREAK_ENDED: - /* - * Shouldn't get here. Hope again. - */ - break; - } - } - if (com->intr_enable & CD1400_SRER_TXMPTY) { - if (!(com->extra_state & CSE_ODONE)) { - com_events += LOTS_OF_EVENTS; - com->extra_state |= CSE_ODONE; - setsofttty(); - } - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - &= ~CD1400_SRER_TXMPTY); - goto terminate_tx_service; - } - if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { - u_char *ioptr; - u_int ocount; - - ioptr = com->obufq.l_head; - ocount = com->obufq.l_tail - ioptr; - if (ocount > CD1400_TX_FIFO_SIZE) - ocount = CD1400_TX_FIFO_SIZE; - com->bytes_out += ocount; - do - cd_outb(iobase, CD1400_TDR, cy_align, - *ioptr++); - while (--ocount != 0); - com->obufq.l_head = ioptr; - if (ioptr >= com->obufq.l_tail) { - struct lbq *qp; - - qp = com->obufq.l_next; - qp->l_queued = FALSE; - qp = qp->l_next; - if (qp != NULL) { - com->obufq.l_head = qp->l_head; - com->obufq.l_tail = qp->l_tail; - com->obufq.l_next = qp; - } else { - /* output just completed */ - com->state &= ~CS_BUSY; - - /* - * The setting of CSE_ODONE may be - * stale here. We currently only - * use it when CS_BUSY is set, and - * fixing it when we clear CS_BUSY - * is easiest. - */ - if (com->extra_state & CSE_ODONE) { - com_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - } - - cd_outb(iobase, CD1400_SRER, cy_align, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - } - if (!(com->state & CS_ODONE)) { - com_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - - /* handle at high level ASAP */ - setsofttty(); - } - } - } - - /* terminate service context */ -terminate_tx_service: -#ifdef PollMode - cd_outb(iobase, CD1400_TIR, cy_align, - save_tir - & ~(CD1400_TIR_RDIREQ | CD1400_TIR_RBUSY)); -#else - cd_outb(iobase, CD1400_EOSRR, cy_align, 0); -#endif - } - } - - /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - - schedsofttty(); - - com_unlock(); - lwkt_reltoken(&tty_token); -} - -#if 0 -static void -siointr1(struct com_s *com) -{ -} -#endif - -static int -sioioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - caddr_t data = ap->a_data; - u_long cmd = ap->a_cmd; - struct com_s *com; - int error; - int mynor; - struct tty *tp; -#if defined(COMPAT_43) - int oldcmd; - struct termios term; -#endif - - lwkt_gettoken(&tty_token); - mynor = minor(dev); - com = com_addr(MINOR_TO_UNIT(mynor)); - if (mynor & CONTROL_MASK) { - struct termios *ct; - - switch (mynor & CONTROL_MASK) { - case CONTROL_INIT_STATE: - ct = mynor & CALLOUT_MASK ? &com->it_out : &com->it_in; - break; - case CONTROL_LOCK_STATE: - ct = mynor & CALLOUT_MASK ? &com->lt_out : &com->lt_in; - break; - default: - lwkt_reltoken(&tty_token); - return (ENODEV); /* /dev/nodev */ - } - switch (cmd) { - case TIOCSETA: - error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0); - if (error != 0) { - lwkt_reltoken(&tty_token); - return (error); - } - *ct = *(struct termios *)data; - lwkt_reltoken(&tty_token); - return (0); - case TIOCGETA: - *(struct termios *)data = *ct; - lwkt_reltoken(&tty_token); - return (0); - case TIOCGETD: - *(int *)data = TTYDISC; - lwkt_reltoken(&tty_token); - return (0); - case TIOCGWINSZ: - bzero(data, sizeof(struct winsize)); - lwkt_reltoken(&tty_token); - return (0); - default: - lwkt_reltoken(&tty_token); - return (ENOTTY); - } - } - tp = com->tp; -#if defined(COMPAT_43) - term = tp->t_termios; - oldcmd = cmd; - error = ttsetcompat(tp, &cmd, data, &term); - if (error != 0) { - lwkt_reltoken(&tty_token); - return (error); - } - if (cmd != oldcmd) - data = (caddr_t)&term; -#endif - if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { - int cc; - struct termios *dt = (struct termios *)data; - struct termios *lt = mynor & CALLOUT_MASK - ? &com->lt_out : &com->lt_in; - - dt->c_iflag = (tp->t_iflag & lt->c_iflag) - | (dt->c_iflag & ~lt->c_iflag); - dt->c_oflag = (tp->t_oflag & lt->c_oflag) - | (dt->c_oflag & ~lt->c_oflag); - dt->c_cflag = (tp->t_cflag & lt->c_cflag) - | (dt->c_cflag & ~lt->c_cflag); - dt->c_lflag = (tp->t_lflag & lt->c_lflag) - | (dt->c_lflag & ~lt->c_lflag); - for (cc = 0; cc < NCCS; ++cc) - if (lt->c_cc[cc] != 0) - dt->c_cc[cc] = tp->t_cc[cc]; - if (lt->c_ispeed != 0) - dt->c_ispeed = tp->t_ispeed; - if (lt->c_ospeed != 0) - dt->c_ospeed = tp->t_ospeed; - } - error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, - ap->a_fflag, ap->a_cred); - if (error != ENOIOCTL) { - lwkt_reltoken(&tty_token); - return (error); - } - crit_enter(); - error = ttioctl(tp, cmd, data, ap->a_fflag); - disc_optim(tp, &tp->t_termios, com); - if (error != ENOIOCTL) { - crit_exit(); - lwkt_reltoken(&tty_token); - return (error); - } - switch (cmd) { - case TIOCSBRK: -#if 0 - outb(iobase + com_cfcr, com->cfcr_image |= CFCR_SBREAK); -#else - cd_etc(com, CD1400_ETC_SENDBREAK); -#endif - break; - case TIOCCBRK: -#if 0 - outb(iobase + com_cfcr, com->cfcr_image &= ~CFCR_SBREAK); -#else - cd_etc(com, CD1400_ETC_STOPBREAK); -#endif - break; - case TIOCSDTR: - (void)commctl(com, TIOCM_DTR, DMBIS); - break; - case TIOCCDTR: - (void)commctl(com, TIOCM_DTR, DMBIC); - break; - /* - * XXX should disallow changing MCR_RTS if CS_RTS_IFLOW is set. The - * changes get undone on the next call to comparam(). - */ - case TIOCMSET: - (void)commctl(com, *(int *)data, DMSET); - break; - case TIOCMBIS: - (void)commctl(com, *(int *)data, DMBIS); - break; - case TIOCMBIC: - (void)commctl(com, *(int *)data, DMBIC); - break; - case TIOCMGET: - *(int *)data = commctl(com, 0, DMGET); - break; - case TIOCMSDTRWAIT: - /* must be root since the wait applies to following logins */ - error = priv_check_cred(ap->a_cred, PRIV_ROOT, 0); - if (error != 0) { - crit_exit(); - lwkt_reltoken(&tty_token); - return (error); - } - com->dtr_wait = *(int *)data * hz / 100; - break; - case TIOCMGDTRWAIT: - *(int *)data = com->dtr_wait * 100 / hz; - break; - case TIOCTIMESTAMP: - com->do_timestamp = TRUE; - *(struct timeval *)data = com->timestamp; - break; - case TIOCDCDTIMESTAMP: - com->do_dcd_timestamp = TRUE; - *(struct timeval *)data = com->dcd_timestamp; - break; - default: - crit_exit(); - lwkt_reltoken(&tty_token); - return (ENOTTY); - } - crit_exit(); - lwkt_reltoken(&tty_token); - return (0); -} - -static void -siopoll(void *data, void *frame) -{ - int unit; - - lwkt_gettoken(&tty_token); -#ifdef CyDebug - ++cy_timeouts; -#endif - if (com_events == 0) { - lwkt_reltoken(&tty_token); - return; - } -repeat: - for (unit = 0; unit < NSIO; ++unit) { - struct com_s *com; - int incc; - struct tty *tp; - - com = com_addr(unit); - if (com == NULL) - continue; - tp = com->tp; - if (tp == NULL) { - /* - * XXX forget any events related to closed devices - * (actually never opened devices) so that we don't - * loop. - */ - disable_intr(); - incc = com->iptr - com->ibuf; - com->iptr = com->ibuf; - if (com->state & CS_CHECKMSR) { - incc += LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - } - com_events -= incc; - enable_intr(); - if (incc != 0) - log(LOG_DEBUG, - "sio%d: %d events for device with no tp\n", - unit, incc); - continue; - } - if (com->iptr != com->ibuf) { - disable_intr(); - sioinput(com); - enable_intr(); - } - if (com->state & CS_CHECKMSR) { - u_char delta_modem_status; - - disable_intr(); - delta_modem_status = com->last_modem_status - ^ com->prev_modem_status; - com->prev_modem_status = com->last_modem_status; - com_events -= LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - enable_intr(); - if (delta_modem_status & MSR_DCD) - (*linesw[tp->t_line].l_modem) - (tp, com->prev_modem_status & MSR_DCD); - } - if (com->extra_state & CSE_ODONE) { - disable_intr(); - com_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - enable_intr(); - if (!(com->state & CS_BUSY)) { - tp->t_state &= ~TS_BUSY; - ttwwakeup(com->tp); - } - if (com->etc != ETC_NONE) { - if (com->etc == ETC_BREAK_ENDED) - com->etc = ETC_NONE; - wakeup(&com->etc); - } - } - if (com->state & CS_ODONE) { - disable_intr(); - com_events -= LOTS_OF_EVENTS; - com->state &= ~CS_ODONE; - enable_intr(); - (*linesw[tp->t_line].l_start)(tp); - } - if (com_events == 0) - break; - } - if (com_events >= LOTS_OF_EVENTS) - goto repeat; - lwkt_reltoken(&tty_token); -} - -static int -comparam(struct tty *tp, struct termios *t) -{ - int bits; - int cflag; - struct com_s *com; - u_char cor_change; - u_long cy_clock; - int idivisor; - int iflag; - int iprescaler; - int itimeout; - int odivisor; - int oprescaler; - u_char opt; - int unit; - - lwkt_gettoken(&tty_token); - /* do historical conversions */ - if (t->c_ispeed == 0) - t->c_ispeed = t->c_ospeed; - - unit = DEV_TO_UNIT(tp->t_dev); - com = com_addr(unit); - - /* check requested parameters */ - cy_clock = CY_CLOCK(com->gfrcr_image); - idivisor = comspeed(t->c_ispeed, cy_clock, &iprescaler); - if (idivisor < 0) { - lwkt_reltoken(&tty_token); - return (EINVAL); - } - odivisor = comspeed(t->c_ospeed, cy_clock, &oprescaler); - if (odivisor < 0) { - lwkt_reltoken(&tty_token); - return (EINVAL); - } - - /* parameters are OK, convert them to the com struct and the device */ - crit_enter(); - if (odivisor == 0) - (void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */ - else - (void)commctl(com, TIOCM_DTR, DMBIS); - - /* - * This returns with interrupts disabled so that we can complete - * the speed change atomically. - */ - (void) siosetwater(com, t->c_ispeed); - - /* XXX we don't actually change the speed atomically. */ - enable_intr(); - - if (idivisor != 0) { - cd_setreg(com, CD1400_RBPR, idivisor); - cd_setreg(com, CD1400_RCOR, iprescaler); - } - if (odivisor != 0) { - cd_setreg(com, CD1400_TBPR, odivisor); - cd_setreg(com, CD1400_TCOR, oprescaler); - } - - /* - * channel control - * receiver enable - * transmitter enable (always set) - */ - cflag = t->c_cflag; - opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN - | (cflag & CREAD ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS); - if (opt != com->channel_control) { - com->channel_control = opt; - cd1400_channel_cmd(com, opt); - } - -#ifdef Smarts - /* set special chars */ - /* XXX if one is _POSIX_VDISABLE, can't use some others */ - if (t->c_cc[VSTOP] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR1, t->c_cc[VSTOP]); - if (t->c_cc[VSTART] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR2, t->c_cc[VSTART]); - if (t->c_cc[VINTR] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR3, t->c_cc[VINTR]); - if (t->c_cc[VSUSP] != _POSIX_VDISABLE) - cd_setreg(com, CD1400_SCHR4, t->c_cc[VSUSP]); -#endif - - /* - * set channel option register 1 - - * parity mode - * stop bits - * char length - */ - opt = 0; - /* parity */ - if (cflag & PARENB) { - if (cflag & PARODD) - opt |= CD1400_COR1_PARODD; - opt |= CD1400_COR1_PARNORMAL; - } - iflag = t->c_iflag; - if (!(iflag & INPCK)) - opt |= CD1400_COR1_NOINPCK; - bits = 1 + 1; - /* stop bits */ - if (cflag & CSTOPB) { - ++bits; - opt |= CD1400_COR1_STOP2; - } - /* char length */ - switch (cflag & CSIZE) { - case CS5: - bits += 5; - opt |= CD1400_COR1_CS5; - break; - case CS6: - bits += 6; - opt |= CD1400_COR1_CS6; - break; - case CS7: - bits += 7; - opt |= CD1400_COR1_CS7; - break; - default: - bits += 8; - opt |= CD1400_COR1_CS8; - break; - } - cor_change = 0; - if (opt != com->cor[0]) { - cor_change |= CD1400_CCR_COR1; - cd_setreg(com, CD1400_COR1, com->cor[0] = opt); - } - - /* - * Set receive time-out period, normally to max(one char time, 5 ms). - */ - if (t->c_ispeed == 0) - itimeout = cd_getreg(com, CD1400_RTPR); - else { - itimeout = (1000 * bits + t->c_ispeed - 1) / t->c_ispeed; -#ifdef SOFT_HOTCHAR -#define MIN_RTP 1 -#else -#define MIN_RTP 5 -#endif - if (itimeout < MIN_RTP) - itimeout = MIN_RTP; - } - if (!(t->c_lflag & ICANON) && t->c_cc[VMIN] != 0 && t->c_cc[VTIME] != 0 - && t->c_cc[VTIME] * 10 > itimeout) - itimeout = t->c_cc[VTIME] * 10; - if (itimeout > 255) - itimeout = 255; - cd_setreg(com, CD1400_RTPR, itimeout); - - /* - * set channel option register 2 - - * flow control - */ - opt = 0; -#ifdef Smarts - if (iflag & IXANY) - opt |= CD1400_COR2_IXANY; - if (iflag & IXOFF) - opt |= CD1400_COR2_IXOFF; -#endif -#ifndef SOFT_CTS_OFLOW - if (cflag & CCTS_OFLOW) - opt |= CD1400_COR2_CCTS_OFLOW; -#endif - disable_intr(); - if (opt != com->cor[1]) { - cor_change |= CD1400_CCR_COR2; - cd_setreg(com, CD1400_COR2, com->cor[1] = opt); - } - enable_intr(); - - /* - * set channel option register 3 - - * receiver FIFO interrupt threshold - * flow control - */ - opt = RxFifoThreshold; -#ifdef Smarts - if (t->c_lflag & ICANON) - opt |= CD1400_COR3_SCD34; /* detect INTR & SUSP chars */ - if (iflag & IXOFF) - /* detect and transparently handle START and STOP chars */ - opt |= CD1400_COR3_FCT | CD1400_COR3_SCD12; -#endif - if (opt != com->cor[2]) { - cor_change |= CD1400_CCR_COR3; - cd_setreg(com, CD1400_COR3, com->cor[2] = opt); - } - - /* notify the CD1400 if COR1-3 have changed */ - if (cor_change) - cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | cor_change); - - /* - * set channel option register 4 - - * CR/NL processing - * break processing - * received exception processing - */ - opt = 0; - if (iflag & IGNCR) - opt |= CD1400_COR4_IGNCR; -#ifdef Smarts - /* - * we need a new ttyinput() for this, as we don't want to - * have ICRNL && INLCR being done in both layers, or to have - * synchronisation problems - */ - if (iflag & ICRNL) - opt |= CD1400_COR4_ICRNL; - if (iflag & INLCR) - opt |= CD1400_COR4_INLCR; -#endif - if (iflag & IGNBRK) - opt |= CD1400_COR4_IGNBRK | CD1400_COR4_NOBRKINT; - /* - * The `-ignbrk -brkint parmrk' case is not handled by the hardware, - * so only tell the hardware about -brkint if -parmrk. - */ - if (!(iflag & (BRKINT | PARMRK))) - opt |= CD1400_COR4_NOBRKINT; -#if 0 - /* XXX using this "intelligence" breaks reporting of overruns. */ - if (iflag & IGNPAR) - opt |= CD1400_COR4_PFO_DISCARD; - else { - if (iflag & PARMRK) - opt |= CD1400_COR4_PFO_ESC; - else - opt |= CD1400_COR4_PFO_NUL; - } -#else - opt |= CD1400_COR4_PFO_EXCEPTION; -#endif - cd_setreg(com, CD1400_COR4, opt); - - /* - * set channel option register 5 - - */ - opt = 0; - if (iflag & ISTRIP) - opt |= CD1400_COR5_ISTRIP; - if (t->c_iflag & IEXTEN) - /* enable LNEXT (e.g. ctrl-v quoting) handling */ - opt |= CD1400_COR5_LNEXT; -#ifdef Smarts - if (t->c_oflag & ONLCR) - opt |= CD1400_COR5_ONLCR; - if (t->c_oflag & OCRNL) - opt |= CD1400_COR5_OCRNL; -#endif - cd_setreg(com, CD1400_COR5, opt); - - /* - * We always generate modem status change interrupts for CD changes. - * Among other things, this is necessary to track TS_CARR_ON for - * pstat to print even when the driver doesn't care. CD changes - * should be rare so interrupts for them are not worth extra code to - * avoid. We avoid interrupts for other modem status changes (except - * for CTS changes when SOFT_CTS_OFLOW is configured) since this is - * simplest and best. - */ - - /* - * set modem change option register 1 - * generate modem interrupts on which 1 -> 0 input transitions - * also controls auto-DTR output flow-control, which we don't use - */ - opt = CD1400_MCOR1_CDzd; -#ifdef SOFT_CTS_OFLOW - if (cflag & CCTS_OFLOW) - opt |= CD1400_MCOR1_CTSzd; -#endif - cd_setreg(com, CD1400_MCOR1, opt); - - /* - * set modem change option register 2 - * generate modem interrupts on specific 0 -> 1 input transitions - */ - opt = CD1400_MCOR2_CDod; -#ifdef SOFT_CTS_OFLOW - if (cflag & CCTS_OFLOW) - opt |= CD1400_MCOR2_CTSod; -#endif - cd_setreg(com, CD1400_MCOR2, opt); - - /* - * XXX should have done this long ago, but there is too much state - * to change all atomically. - */ - disable_intr(); - - com->state &= ~CS_TTGO; - if (!(tp->t_state & TS_TTSTOP)) - com->state |= CS_TTGO; - if (cflag & CRTS_IFLOW) { - com->state |= CS_RTS_IFLOW; - /* - * If CS_RTS_IFLOW just changed from off to on, the change - * needs to be propagated to MCR_RTS. This isn't urgent, - * so do it later by calling comstart() instead of repeating - * a lot of code from comstart() here. - */ - } else if (com->state & CS_RTS_IFLOW) { - com->state &= ~CS_RTS_IFLOW; - /* - * CS_RTS_IFLOW just changed from on to off. Force MCR_RTS - * on here, since comstart() won't do it later. - */ -#if 0 - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -#endif - } - - /* - * Set up state to handle output flow control. - * XXX - worth handling MDMBUF (DCD) flow control at the lowest level? - * Now has 10+ msec latency, while CTS flow has 50- usec latency. - */ - com->state |= CS_ODEVREADY; -#ifdef SOFT_CTS_OFLOW - com->state &= ~CS_CTS_OFLOW; - if (cflag & CCTS_OFLOW) { - com->state |= CS_CTS_OFLOW; - if (!(com->last_modem_status & MSR_CTS)) - com->state &= ~CS_ODEVREADY; - } -#endif - /* XXX shouldn't call functions while intrs are disabled. */ - disc_optim(tp, t, com); -#if 0 - /* - * Recover from fiddling with CS_TTGO. We used to call siointr1() - * unconditionally, but that defeated the careful discarding of - * stale input in sioopen(). - */ - if (com->state >= (CS_BUSY | CS_TTGO)) - siointr1(com); -#endif - if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY)) { - if (!(com->intr_enable & CD1400_SRER_TXRDY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } else { - if (com->intr_enable & CD1400_SRER_TXRDY) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - } - - enable_intr(); - crit_exit(); - comstart(tp); - if (com->ibufold != NULL) { - kfree(com->ibufold, M_DEVBUF); - com->ibufold = NULL; - } - lwkt_reltoken(&tty_token); - return (0); -} - -/* - * NOTE: Must be called with tty_token held - */ -static int -siosetwater(struct com_s *com, speed_t speed) -{ - int cp4ticks; - u_char *ibuf; - int ibufsize; - struct tty *tp; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - /* - * Make the buffer size large enough to handle a softtty interrupt - * latency of about 2 ticks without loss of throughput or data - * (about 3 ticks if input flow control is not used or not honoured, - * but a bit less for CS5-CS7 modes). - */ - cp4ticks = speed / 10 / hz * 4; - for (ibufsize = 128; ibufsize < cp4ticks;) - ibufsize <<= 1; - if (ibufsize == com->ibufsize) { - disable_intr(); - return (0); - } - - /* - * Allocate input buffer. The extra factor of 2 in the size is - * to allow for an error byte for each input byte. - */ - ibuf = kmalloc(2 * ibufsize, M_DEVBUF, M_WAITOK); - - /* Initialize non-critical variables. */ - com->ibufold = com->ibuf; - com->ibufsize = ibufsize; - tp = com->tp; - if (tp != NULL) { - tp->t_ififosize = 2 * ibufsize; - tp->t_ispeedwat = (speed_t)-1; - tp->t_ospeedwat = (speed_t)-1; - } - - /* - * Read current input buffer, if any. Continue with interrupts - * disabled. - */ - disable_intr(); - if (com->iptr != com->ibuf) - sioinput(com); - - /*- - * Initialize critical variables, including input buffer watermarks. - * The external device is asked to stop sending when the buffer - * exactly reaches high water, or when the high level requests it. - * The high level is notified immediately (rather than at a later - * clock tick) when this watermark is reached. - * The buffer size is chosen so the watermark should almost never - * be reached. - * The low watermark is invisibly 0 since the buffer is always - * emptied all at once. - */ - com->iptr = com->ibuf = ibuf; - com->ibufend = ibuf + ibufsize; - com->ierroff = ibufsize; - com->ihighwater = ibuf + 3 * ibufsize / 4; - return (0); -} - -static void -comstart(struct tty *tp) -{ - struct com_s *com; -#ifdef CyDebug - bool_t started; -#endif - int unit; - - unit = DEV_TO_UNIT(tp->t_dev); - com = com_addr(unit); - crit_enter(); - lwkt_gettoken(&tty_token); - -#ifdef CyDebug - ++com->start_count; - started = FALSE; -#endif - - disable_intr(); - if (tp->t_state & TS_TTSTOP) { - com->state &= ~CS_TTGO; - if (com->intr_enable & CD1400_SRER_TXRDY) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) - | CD1400_SRER_TXMPTY); - } else { - com->state |= CS_TTGO; - if (com->state >= (CS_BUSY | CS_TTGO | CS_ODEVREADY) - && !(com->intr_enable & CD1400_SRER_TXRDY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } - if (tp->t_state & TS_TBLOCK) { - if (com->mcr_image & com->mcr_rts && com->state & CS_RTS_IFLOW) -#if 0 - outb(com->modem_ctl_port, com->mcr_image &= ~MCR_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image &= ~com->mcr_rts); -#endif - } else { - if (!(com->mcr_image & com->mcr_rts) - && com->iptr < com->ihighwater - && com->state & CS_RTS_IFLOW) -#if 0 - outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -#endif - } - enable_intr(); - if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - lwkt_reltoken(&tty_token); - crit_exit(); - return; - } - if (tp->t_outq.c_cc != 0) { - struct lbq *qp; - struct lbq *next; - - if (!com->obufs[0].l_queued) { -#ifdef CyDebug - started = TRUE; -#endif - com->obufs[0].l_tail - = com->obuf1 + q_to_b(&tp->t_outq, com->obuf1, - sizeof com->obuf1); - com->obufs[0].l_next = NULL; - com->obufs[0].l_queued = TRUE; - disable_intr(); - if (com->state & CS_BUSY) { - qp = com->obufq.l_next; - while ((next = qp->l_next) != NULL) - qp = next; - qp->l_next = &com->obufs[0]; - } else { - com->obufq.l_head = com->obufs[0].l_head; - com->obufq.l_tail = com->obufs[0].l_tail; - com->obufq.l_next = &com->obufs[0]; - com->state |= CS_BUSY; - if (com->state >= (CS_BUSY | CS_TTGO - | CS_ODEVREADY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } - enable_intr(); - } - if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) { -#ifdef CyDebug - started = TRUE; -#endif - com->obufs[1].l_tail - = com->obuf2 + q_to_b(&tp->t_outq, com->obuf2, - sizeof com->obuf2); - com->obufs[1].l_next = NULL; - com->obufs[1].l_queued = TRUE; - disable_intr(); - if (com->state & CS_BUSY) { - qp = com->obufq.l_next; - while ((next = qp->l_next) != NULL) - qp = next; - qp->l_next = &com->obufs[1]; - } else { - com->obufq.l_head = com->obufs[1].l_head; - com->obufq.l_tail = com->obufs[1].l_tail; - com->obufq.l_next = &com->obufs[1]; - com->state |= CS_BUSY; - if (com->state >= (CS_BUSY | CS_TTGO - | CS_ODEVREADY)) - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable - & ~CD1400_SRER_TXMPTY) - | CD1400_SRER_TXRDY); - } - enable_intr(); - } - tp->t_state |= TS_BUSY; - } -#ifdef CyDebug - if (started) - ++com->start_real; -#endif -#if 0 - disable_intr(); - if (com->state >= (CS_BUSY | CS_TTGO)) - siointr1(com); /* fake interrupt to start output */ - enable_intr(); -#endif - ttwwakeup(tp); - lwkt_reltoken(&tty_token); - crit_exit(); -} - -static void -comstop(struct tty *tp, int rw) -{ - struct com_s *com; - bool_t wakeup_etc; - - lwkt_gettoken(&tty_token); - com = com_addr(DEV_TO_UNIT(tp->t_dev)); - wakeup_etc = FALSE; - disable_intr(); - if (rw & FWRITE) { - com->obufs[0].l_queued = FALSE; - com->obufs[1].l_queued = FALSE; - if (com->extra_state & CSE_ODONE) { - com_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - if (com->etc != ETC_NONE) { - if (com->etc == ETC_BREAK_ENDED) - com->etc = ETC_NONE; - wakeup_etc = TRUE; - } - } - com->tp->t_state &= ~TS_BUSY; - if (com->state & CS_ODONE) - com_events -= LOTS_OF_EVENTS; - com->state &= ~(CS_ODONE | CS_BUSY); - } - if (rw & FREAD) { - /* XXX no way to reset only input fifo. */ - com_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - } - enable_intr(); - if (wakeup_etc) - wakeup(&com->etc); - if (rw & FWRITE && com->etc == ETC_NONE) - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); - comstart(tp); - lwkt_reltoken(&tty_token); -} - -/* - * NOTE: Must be called with tty_token held - */ -static int -commctl(struct com_s *com, int bits, int how) -{ - int mcr; - int msr; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - if (how == DMGET) { - if (com->channel_control & CD1400_CCR_RCVEN) - bits |= TIOCM_LE; - mcr = com->mcr_image; - if (mcr & com->mcr_dtr) - bits |= TIOCM_DTR; - if (mcr & com->mcr_rts) - /* XXX wired on for Cyclom-8Ys */ - bits |= TIOCM_RTS; - - /* - * We must read the modem status from the hardware because - * we don't generate modem status change interrupts for all - * changes, so com->prev_modem_status is not guaranteed to - * be up to date. This is safe, unlike for sio, because - * reading the status register doesn't clear pending modem - * status change interrupts. - */ - msr = cd_getreg(com, CD1400_MSVR2); - - if (msr & MSR_CTS) - bits |= TIOCM_CTS; - if (msr & MSR_DCD) - bits |= TIOCM_CD; - if (msr & MSR_DSR) - bits |= TIOCM_DSR; - if (msr & MSR_RI) - /* XXX not connected except for Cyclom-16Y? */ - bits |= TIOCM_RI; - return (bits); - } - mcr = 0; - if (bits & TIOCM_DTR) - mcr |= com->mcr_dtr; - if (bits & TIOCM_RTS) - mcr |= com->mcr_rts; - disable_intr(); - switch (how) { - case DMSET: - com->mcr_image = mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); - break; - case DMBIS: - com->mcr_image = mcr = com->mcr_image | mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); - break; - case DMBIC: - com->mcr_image = mcr = com->mcr_image & ~mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); - break; - } - enable_intr(); - return (0); -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -siosettimeout(void) -{ - struct com_s *com; - bool_t someopen; - int unit; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - /* - * Set our timeout period to 1 second if no polled devices are open. - * Otherwise set it to max(1/200, 1/hz). - * Enable timeouts iff some device is open. - */ - callout_stop(&sio_timeout_handle); - sio_timeout = hz; - someopen = FALSE; - for (unit = 0; unit < NSIO; ++unit) { - com = com_addr(unit); - if (com != NULL && com->tp != NULL - && com->tp->t_state & TS_ISOPEN) { - someopen = TRUE; -#if 0 - if (com->poll || com->poll_output) { - sio_timeout = hz > 200 ? hz / 200 : 1; - break; - } -#endif - } - } - if (someopen) { - sio_timeouts_until_log = hz / sio_timeout; - callout_reset(&sio_timeout_handle, sio_timeout, - comwakeup, NULL); - } else { - /* Flush error messages, if any. */ - sio_timeouts_until_log = 1; - comwakeup(NULL); - callout_stop(&sio_timeout_handle); - } -} - -static void -comwakeup(void *chan) -{ - struct com_s *com; - int unit; - - lwkt_gettoken(&tty_token); - callout_reset(&sio_timeout_handle, sio_timeout, comwakeup, NULL); - -#if 0 - /* - * Recover from lost output interrupts. - * Poll any lines that don't use interrupts. - */ - for (unit = 0; unit < NSIO; ++unit) { - com = com_addr(unit); - if (com != NULL - && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) { - disable_intr(); - siointr1(com); - enable_intr(); - } - } -#endif - - /* - * Check for and log errors, but not too often. - */ - if (--sio_timeouts_until_log > 0) { - lwkt_reltoken(&tty_token); - return; - } - sio_timeouts_until_log = hz / sio_timeout; - for (unit = 0; unit < NSIO; ++unit) { - int errnum; - - com = com_addr(unit); - if (com == NULL) - continue; - for (errnum = 0; errnum < CE_NTYPES; ++errnum) { - u_int delta; - u_long total; - - disable_intr(); - delta = com->delta_error_counts[errnum]; - com->delta_error_counts[errnum] = 0; - enable_intr(); - if (delta == 0) - continue; - total = com->error_counts[errnum] += delta; - log(LOG_ERR, "cy%d: %u more %s%s (total %lu)\n", - unit, delta, error_desc[errnum], - delta == 1 ? "" : "s", total); - } - } - lwkt_reltoken(&tty_token); -} - -static void -disc_optim(struct tty *tp, struct termios *t, struct com_s *com) -{ -#ifndef SOFT_HOTCHAR - u_char opt; -#endif - - lwkt_gettoken(&tty_token); - /* - * XXX can skip a lot more cases if Smarts. Maybe - * (IGNCR | ISTRIP | IXON) in c_iflag. But perhaps we - * shouldn't skip if (TS_CNTTB | TS_LNCH) is set in t_state. - */ - if (!(t->c_iflag & (ICRNL | IGNCR | IMAXBEL | INLCR | ISTRIP | IXON)) - && (!(t->c_iflag & BRKINT) || (t->c_iflag & IGNBRK)) - && (!(t->c_iflag & PARMRK) - || (t->c_iflag & (IGNPAR | IGNBRK)) == (IGNPAR | IGNBRK)) - && !(t->c_lflag & (ECHO | ICANON | IEXTEN | ISIG | PENDIN)) - && linesw[tp->t_line].l_rint == ttyinput) - tp->t_state |= TS_CAN_BYPASS_L_RINT; - else - tp->t_state &= ~TS_CAN_BYPASS_L_RINT; - com->hotchar = linesw[tp->t_line].l_hotchar; -#ifndef SOFT_HOTCHAR - opt = com->cor[2] & ~CD1400_COR3_SCD34; - if (com->hotchar != 0) { - cd_setreg(com, CD1400_SCHR3, com->hotchar); - cd_setreg(com, CD1400_SCHR4, com->hotchar); - opt |= CD1400_COR3_SCD34; - } - if (opt != com->cor[2]) { - cd_setreg(com, CD1400_COR3, com->cor[2] = opt); - cd1400_channel_cmd(com, CD1400_CCR_CMDCORCHG | CD1400_CCR_COR3); - } -#endif - lwkt_reltoken(&tty_token); -} - -#ifdef Smarts -/* standard line discipline input routine */ -int -cyinput(int c, struct tty *tp) -{ - /* XXX duplicate ttyinput(), but without the IXOFF/IXON/ISTRIP/IPARMRK - * bits, as they are done by the CD1400. Hardly worth the effort, - * given that high-throughput sessions are raw anyhow. - */ -} -#endif /* Smarts */ - -static int -comspeed(speed_t speed, u_long cy_clock, int *prescaler_io) -{ - int actual; - int error; - int divider; - int prescaler; - int prescaler_unit; - - if (speed == 0) - return (0); - if (speed < 0 || speed > 150000) - return (-1); - - /* determine which prescaler to use */ - for (prescaler_unit = 4, prescaler = 2048; prescaler_unit; - prescaler_unit--, prescaler >>= 2) { - if (cy_clock / prescaler / speed > 63) - break; - } - - divider = (cy_clock / prescaler * 2 / speed + 1) / 2; /* round off */ - if (divider > 255) - divider = 255; - actual = cy_clock/prescaler/divider; - - /* 10 times error in percent: */ - error = ((actual - (long)speed) * 2000 / (long)speed + 1) / 2; - - /* 3.0% max error tolerance */ - if (error < -30 || error > 30) - return (-1); - -#if 0 - kprintf("prescaler = %d (%d)\n", prescaler, prescaler_unit); - kprintf("divider = %d (%x)\n", divider, divider); - kprintf("actual = %d\n", actual); - kprintf("error = %d\n", error); -#endif - - *prescaler_io = prescaler_unit; - return (divider); -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -cd1400_channel_cmd(struct com_s *com, int cmd) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - cd1400_channel_cmd_wait(com); - cd_setreg(com, CD1400_CCR, cmd); - cd1400_channel_cmd_wait(com); -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -cd1400_channel_cmd_wait(struct com_s *com) -{ - struct timeval start; - struct timeval tv; - long usec; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - if (cd_getreg(com, CD1400_CCR) == 0) - return; - microtime(&start); - for (;;) { - if (cd_getreg(com, CD1400_CCR) == 0) - return; - microtime(&tv); - usec = 1000000 * (tv.tv_sec - start.tv_sec) + - tv.tv_usec - start.tv_usec; - if (usec >= 5000) { - log(LOG_ERR, - "cy%d: channel command timeout (%ld usec)\n", - com->unit, usec); - return; - } - } -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -cd_etc(struct com_s *com, int etc) -{ - ASSERT_LWKT_TOKEN_HELD(&tty_token); - /* - * We can't change the hardware's ETC state while there are any - * characters in the tx fifo, since those characters would be - * interpreted as commands! Unputting characters from the fifo - * is difficult, so we wait up to 12 character times for the fifo - * to drain. The command will be delayed for up to 2 character - * times for the tx to become empty. Unputting characters from - * the tx holding and shift registers is impossible, so we wait - * for the tx to become empty so that the command is sure to be - * executed soon after we issue it. - */ - disable_intr(); - if (com->etc == etc) { - enable_intr(); - goto wait; - } - if ((etc == CD1400_ETC_SENDBREAK - && (com->etc == ETC_BREAK_STARTING - || com->etc == ETC_BREAK_STARTED)) - || (etc == CD1400_ETC_STOPBREAK - && (com->etc == ETC_BREAK_ENDING || com->etc == ETC_BREAK_ENDED - || com->etc == ETC_NONE))) { - enable_intr(); - return; - } - com->etc = etc; - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); - enable_intr(); -wait: - while (com->etc == etc - && tsleep(&com->etc, PCATCH, "cyetc", 0) == 0) - continue; -} - -/* - * NOTE: Must be called with tty_token held - */ -static int -cd_getreg(struct com_s *com, int reg) -{ - struct com_s *basecom; - u_char car; - int cy_align; - u_long ef; - cy_addr iobase; - int val; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - ef = read_eflags(); - if (ef & PSL_I) - disable_intr(); - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - val = cd_inb(iobase, reg, cy_align); - if (ef & PSL_I) - enable_intr(); - return (val); -} - -/* - * NOTE: Must be called with tty_token held - */ -static void -cd_setreg(struct com_s *com, int reg, int val) -{ - struct com_s *basecom; - u_char car; - int cy_align; - u_long ef; - cy_addr iobase; - - ASSERT_LWKT_TOKEN_HELD(&tty_token); - - basecom = com_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - ef = read_eflags(); - if (ef & PSL_I) - disable_intr(); - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - cd_outb(iobase, reg, cy_align, val); - if (ef & PSL_I) - enable_intr(); -} - -#ifdef CyDebug -/* useful in ddb */ -void -cystatus(int unit) -{ - struct com_s *com; - cy_addr iobase; - u_int ocount; - struct tty *tp; - - com = com_addr(unit); - kprintf("info for channel %d\n", unit); - kprintf("------------------\n"); - kprintf("total cyclom service probes:\t%d\n", cy_svrr_probes); - kprintf("calls to upper layer:\t\t%d\n", cy_timeouts); - if (com == NULL) - return; - lwkt_gettoken(&tty_token); - iobase = com->iobase; - kprintf("\n"); - kprintf("cd1400 base address:\\tt%p\n", iobase); - kprintf("saved channel_control:\t\t0x%02x\n", com->channel_control); - kprintf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", - com->cor[0], com->cor[1], com->cor[2]); - kprintf("service request enable reg:\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_SRER), com->intr_enable); - kprintf("service request register:\t0x%02x\n", - cd_inb(iobase, CD1400_SVRR, com->cy_align)); - kprintf("modem status:\t\t\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); - kprintf("rx/tx/mdm interrupt registers:\t0x%02x 0x%02x 0x%02x\n", - cd_inb(iobase, CD1400_RIR, com->cy_align), - cd_inb(iobase, CD1400_TIR, com->cy_align), - cd_inb(iobase, CD1400_MIR, com->cy_align)); - kprintf("\n"); - kprintf("com state:\t\t\t0x%02x\n", com->state); - kprintf("calls to comstart():\t\t%d (%d useful)\n", - com->start_count, com->start_real); - kprintf("rx buffer chars free:\t\t%d\n", com->iptr - com->ibuf); - ocount = 0; - if (com->obufs[0].l_queued) - ocount += com->obufs[0].l_tail - com->obufs[0].l_head; - if (com->obufs[1].l_queued) - ocount += com->obufs[1].l_tail - com->obufs[1].l_head; - kprintf("tx buffer chars:\t\t%u\n", ocount); - kprintf("received chars:\t\t\t%d\n", com->bytes_in); - kprintf("received exceptions:\t\t%d\n", com->recv_exception); - kprintf("modem signal deltas:\t\t%d\n", com->mdm); - kprintf("transmitted chars:\t\t%d\n", com->bytes_out); - kprintf("\n"); - tp = com->tp; - if (tp != NULL) { - kprintf("tty state:\t\t\t0x%08x\n", tp->t_state); - kprintf( - "upper layer queue lengths:\t%d raw, %d canon, %d output\n", - tp->t_rawq.c_cc, tp->t_canq.c_cc, tp->t_outq.c_cc); - } else { - kprintf("tty state:\t\t\tclosed\n"); - } - lwkt_reltoken(&tty_token); -} -#endif /* CyDebug */ diff --git a/sys/dev/serial/cy/cy_pci.c b/sys/dev/serial/cy/cy_pci.c deleted file mode 100644 index 69cacce51a..0000000000 --- a/sys/dev/serial/cy/cy_pci.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 1996, David Greenman - * 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 unmodified, 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. - * - * 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: src/sys/pci/cy_pci.c,v 1.17.2.1 2002/03/17 04:14:18 bde Exp $ - * $DragonFly: src/sys/dev/serial/cy/cy_pci.c,v 1.10 2007/04/12 18:35:08 swildner Exp $ - */ - -/* - * Cyclades Y PCI serial interface driver - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include "cy_pcireg.h" - -static const char *cy_probe (pcici_t, pcidi_t); -static void cy_attach (pcici_t, int); - -extern int cyattach_common(void *, int); /* Not exactly correct */ -extern void cyintr(int); - -static u_long cy_count; - -static struct pci_device cy_device = { - "cy", - cy_probe, - cy_attach, - &cy_count, - NULL -}; -COMPAT_PCI_DRIVER(cy_pci, cy_device); - -static const char * -cy_probe(pcici_t config_id, pcidi_t device_id) -{ - device_id &= ~0x00060000; - if (device_id == 0x0100120e || device_id == 0x0101120e) - return ("Cyclades Cyclom-Y Serial Adapter"); - return (NULL); -} - -static void -cy_attach(pcici_t config_id, int unit) -{ - vm_offset_t paddr; - void *vaddr; - u_int32_t ioport; - int adapter; - u_char plx_ver; - - ioport = (u_int32_t) pci_conf_read(config_id, CY_PCI_BASE_ADDR1) & ~0x3; - paddr = pci_conf_read(config_id, CY_PCI_BASE_ADDR2) & ~0xf; -#if 0 - if (!pci_map_mem(config_id, CY_PCI_BASE_ADDR2, &vaddr, &paddr)) { - kprintf("cy%d: couldn't map shared memory\n", unit); - return; - }; -#endif - vaddr = pmap_mapdev(paddr, 0x4000); - - adapter = cyattach_common(vaddr, 1); - if (adapter < 0) { - /* - * No ports found. Release resources and punt. - */ - kprintf("cy%d: no ports found!\n", unit); - goto fail; - } - - /* - * Allocate our interrupt. - * XXX Using the ISA interrupt handler directly is a bit of a violation - * since it doesn't actually take the same argument. For PCI, the - * argument is a void * token, but for ISA it is a unit. Since - * there is no overlap in PCI/ISA unit numbers for this driver, and - * since the ISA driver must handle the interrupt anyway, we use - * the unit number as the token even for PCI. - */ - if (!pci_map_int_right(config_id, (pci_inthand_t *)cyintr, - (void *)adapter, INTR_MPSAFE)) { - kprintf("cy%d: couldn't map interrupt\n", unit); - goto fail; - } - - /* - * Enable the "local" interrupt input to generate a - * PCI interrupt. - */ - plx_ver = *((u_char *)vaddr + PLX_VER) & 0x0f; - switch (plx_ver) { - case PLX_9050: - outw(ioport + CY_PLX_9050_ICS, - CY_PLX_9050_ICS_IENABLE | CY_PLX_9050_ICS_LOCAL_IENABLE | - CY_PLX_9050_ICS_LOCAL_IPOLARITY); - break; - case PLX_9060: - case PLX_9080: - default: /* Old board, use PLX_9060 values. */ - outw(ioport + CY_PLX_9060_ICS, - inw(ioport + CY_PLX_9060_ICS) | CY_PLX_9060_ICS_IENABLE | - CY_PLX_9060_ICS_LOCAL_IENABLE); - break; - } - - return; - -fail: - /* XXX should release any allocated virtual memory */ - return; -} diff --git a/sys/dev/serial/cy/cy_pcireg.h b/sys/dev/serial/cy/cy_pcireg.h deleted file mode 100644 index 851d37ca91..0000000000 --- a/sys/dev/serial/cy/cy_pcireg.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 1996, David Greenman - * 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 unmodified, 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. - * - * 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: src/sys/pci/cy_pcireg.h,v 1.7.2.1 2002/03/17 04:14:18 bde Exp $ - * $DragonFly: src/sys/dev/serial/cy/cy_pcireg.h,v 1.2 2003/06/17 04:28:56 dillon Exp $ - */ - -#define CY_PCI_BASE_ADDR0 0x10 -#define CY_PCI_BASE_ADDR1 0x14 -#define CY_PCI_BASE_ADDR2 0x18 - -#define CY_PLX_9050_ICS 0x4c -#define CY_PLX_9060_ICS 0x68 -#define CY_PLX_9050_ICS_IENABLE 0x040 -#define CY_PLX_9050_ICS_LOCAL_IENABLE 0x001 -#define CY_PLX_9050_ICS_LOCAL_IPOLARITY 0x002 -#define CY_PLX_9060_ICS_IENABLE 0x100 -#define CY_PLX_9060_ICS_LOCAL_IENABLE 0x800 - -/* Cyclom-Y Custom Register for PLX ID. */ -#define PLX_VER 0x3400 -#define PLX_9050 0x0b -#define PLX_9060 0x0c -#define PLX_9080 0x0d diff --git a/sys/dev/serial/cy/cyreg.h b/sys/dev/serial/cy/cyreg.h deleted file mode 100644 index 99c483f4e4..0000000000 --- a/sys/dev/serial/cy/cyreg.h +++ /dev/null @@ -1,76 +0,0 @@ -/*- - * Copyright (c) 1995 Bruce Evans. - * 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. Neither the name of the author nor the names of 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: src/sys/i386/isa/cyreg.h,v 1.9 1999/08/28 00:44:40 peter Exp $ - * $DragonFly: src/sys/dev/serial/cy/cyreg.h,v 1.2 2003/06/17 04:28:37 dillon Exp $ - */ - -/* - * Definitions for Cyclades Cyclom-Y serial boards. - */ - -/* - * Cyclades register offsets. These are physical offsets for ISA boards - * and physical offsets divided by 2 for PCI boards. - */ -#define CY8_SVCACKR 0x100 /* (r) */ -#define CY8_SVCACKT 0x200 /* (r) */ -#define CY8_SVCACKM 0x300 /* (r) */ -#define CY16_RESET 0x1400 /* (r) */ -#define CY_CLEAR_INTR 0x1800 /* intr ack address (w) */ - -#define CY_MAX_CD1400s 8 /* for Cyclom-32Y */ - -#define CY_CLOCK(version) ((version) >= 0x48 ? 60000000 : 25000000) -#define CY_RTS_DTR_SWAPPED(version) ((version) >= 0x48) - -/* - * The `cd' macros are for access to cd1400 registers. The `cy' macros - * are for access to Cyclades registers. Both sets of macros scale the - * register number to get an offset, but the scales are different for - * mostly historical reasons. - */ -#ifdef CyDebug -#define cd_inb(iobase, reg, cy_align) \ - (++cd_inbs, *((iobase) + (2 * (reg) << (cy_align)))) -#define cy_inb(iobase, reg, cy_align) \ - (++cy_inbs, *((iobase) + ((reg) << (cy_align)))) -#define cd_outb(iobase, reg, cy_align, val) \ - (++cd_outbs, (void)(*((iobase) + (2 * (reg) << (cy_align))) = (val))) -#define cy_outb(iobase, reg, cy_align, val) \ - (++cy_outbs, (void)(*((iobase) + ((reg) << (cy_align))) = (val))) -#else -#define cd_inb(iobase, reg, cy_align) \ - (*((iobase) + (2 * (reg) << (cy_align)))) -#define cy_inb(iobase, reg, cy_align) \ - (*((iobase) + ((reg) << (cy_align)))) -#define cd_outb(iobase, reg, cy_align, val) \ - ((void)(*((iobase) + (2 * (reg) << (cy_align))) = (val))) -#define cy_outb(iobase, reg, cy_align, val) \ - ((void)(*((iobase) + ((reg) << (cy_align))) = (val))) -#endif diff --git a/sys/dev/serial/stl/sc26198.h b/sys/dev/serial/stl/sc26198.h deleted file mode 100644 index d0597344a3..0000000000 --- a/sys/dev/serial/stl/sc26198.h +++ /dev/null @@ -1,546 +0,0 @@ -/*****************************************************************************/ - -/* - * sc26198.h -- SC26198 UART hardware info. - * - * Copyright (c) 1995-1998 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: src/sys/i386/isa/ic/sc26198.h,v 1.1.2.1 2001/08/30 12:29:55 murray Exp $ - */ - -/*****************************************************************************/ -#ifndef _SC26198_H -#define _SC26198_H -/*****************************************************************************/ - -/* - * Define the number of async ports per sc26198 uart device. - */ -#define SC26198_PORTS 8 - -/* - * Baud rate timing clocks. All derived from a master 14.7456 MHz clock. - */ -#define SC26198_MASTERCLOCK 14745600L -#define SC26198_DCLK (SC26198_MASTERCLOCK) -#define SC26198_CCLK (SC26198_MASTERCLOCK / 2) -#define SC26198_BCLK (SC26198_MASTERCLOCK / 4) - -/* - * Define internal FIFO sizes for the 26198 ports. - */ -#define SC26198_TXFIFOSIZE 16 -#define SC26198_RXFIFOSIZE 16 - -/*****************************************************************************/ - -/* - * Global register definitions. These registers are global to each 26198 - * device, not specific ports on it. - */ -#define TSTR 0x0d -#define GCCR 0x0f -#define ICR 0x1b -#define WDTRCR 0x1d -#define IVR 0x1f -#define BRGTRUA 0x84 -#define GPOSR 0x87 -#define GPOC 0x8b -#define UCIR 0x8c -#define CIR 0x8c -#define BRGTRUB 0x8d -#define GRXFIFO 0x8e -#define GTXFIFO 0x8e -#define GCCR2 0x8f -#define BRGTRLA 0x94 -#define GPOR 0x97 -#define GPOD 0x9b -#define BRGTCR 0x9c -#define GICR 0x9c -#define BRGTRLB 0x9d -#define GIBCR 0x9d -#define GITR 0x9f - -/* - * Per port channel registers. These are the register offsets within - * the port address space, so need to have the port address (0 to 7) - * inserted in bit positions 4:6. - */ -#define MR0 0x00 -#define MR1 0x01 -#define IOPCR 0x02 -#define BCRBRK 0x03 -#define BCRCOS 0x04 -#define BCRX 0x06 -#define BCRA 0x07 -#define XONCR 0x08 -#define XOFFCR 0x09 -#define ARCR 0x0a -#define RXCSR 0x0c -#define TXCSR 0x0e -#define MR2 0x80 -#define SR 0x81 -#define SCCR 0x81 -#define ISR 0x82 -#define IMR 0x82 -#define TXFIFO 0x83 -#define RXFIFO 0x83 -#define IPR 0x84 -#define IOPIOR 0x85 -#define XISR 0x86 - -/* - * For any given port calculate the address to use to access a specified - * register. This is only used for unusual access... - */ -#define SC26198_PORTREG(port,reg) ((((port) & 0x07) << 4) | (reg)) - -/*****************************************************************************/ - -/* - * Global configuration control register bit definitions. - */ -#define GCCR_NOACK 0x00 -#define GCCR_IVRACK 0x02 -#define GCCR_IVRCHANACK 0x04 -#define GCCR_IVRTYPCHANACK 0x06 -#define GCCR_ASYNCCYCLE 0x00 -#define GCCR_SYNCCYCLE 0x40 - -/*****************************************************************************/ - -/* - * Mode register 0 bit definitions. - */ -#define MR0_ADDRNONE 0x00 -#define MR0_AUTOWAKE 0x01 -#define MR0_AUTODOZE 0x02 -#define MR0_AUTOWAKEDOZE 0x03 -#define MR0_SWFNONE 0x00 -#define MR0_SWFTX 0x04 -#define MR0_SWFRX 0x08 -#define MR0_SWFRXTX 0x0c -#define MR0_TXMASK 0x30 -#define MR0_TXEMPTY 0x00 -#define MR0_TXHIGH 0x10 -#define MR0_TXHALF 0x20 -#define MR0_TXRDY 0x00 -#define MR0_ADDRNT 0x00 -#define MR0_ADDRT 0x40 -#define MR0_SWFNT 0x00 -#define MR0_SWFT 0x80 - -/* - * Mode register 1 bit definitions. - */ -#define MR1_CS5 0x00 -#define MR1_CS6 0x01 -#define MR1_CS7 0x02 -#define MR1_CS8 0x03 -#define MR1_PAREVEN 0x00 -#define MR1_PARODD 0x04 -#define MR1_PARENB 0x00 -#define MR1_PARFORCE 0x08 -#define MR1_PARNONE 0x10 -#define MR1_PARSPECIAL 0x18 -#define MR1_ERRCHAR 0x00 -#define MR1_ERRBLOCK 0x20 -#define MR1_ISRUNMASKED 0x00 -#define MR1_ISRMASKED 0x40 -#define MR1_AUTORTS 0x80 - -/* - * Mode register 2 bit definitions. - */ -#define MR2_STOP1 0x00 -#define MR2_STOP15 0x01 -#define MR2_STOP2 0x02 -#define MR2_STOP916 0x03 -#define MR2_RXFIFORDY 0x00 -#define MR2_RXFIFOHALF 0x04 -#define MR2_RXFIFOHIGH 0x08 -#define MR2_RXFIFOFULL 0x0c -#define MR2_AUTOCTS 0x10 -#define MR2_TXRTS 0x20 -#define MR2_MODENORM 0x00 -#define MR2_MODEAUTOECHO 0x40 -#define MR2_MODELOOP 0x80 -#define MR2_MODEREMECHO 0xc0 - -/*****************************************************************************/ - -/* - * Baud Rate Generator (BRG) selector values. - */ -#define BRG_50 0x00 -#define BRG_75 0x01 -#define BRG_150 0x02 -#define BRG_200 0x03 -#define BRG_300 0x04 -#define BRG_450 0x05 -#define BRG_600 0x06 -#define BRG_900 0x07 -#define BRG_1200 0x08 -#define BRG_1800 0x09 -#define BRG_2400 0x0a -#define BRG_3600 0x0b -#define BRG_4800 0x0c -#define BRG_7200 0x0d -#define BRG_9600 0x0e -#define BRG_14400 0x0f -#define BRG_19200 0x10 -#define BRG_28200 0x11 -#define BRG_38400 0x12 -#define BRG_57600 0x13 -#define BRG_115200 0x14 -#define BRG_230400 0x15 -#define BRG_GIN0 0x16 -#define BRG_GIN1 0x17 -#define BRG_CT0 0x18 -#define BRG_CT1 0x19 -#define BRG_RX2TX316 0x1b -#define BRG_RX2TX31 0x1c - -/*****************************************************************************/ - -/* - * Command register command definitions. - */ -#define CR_NULL 0x04 -#define CR_ADDRNORMAL 0x0c -#define CR_RXRESET 0x14 -#define CR_TXRESET 0x1c -#define CR_CLEARRXERR 0x24 -#define CR_BREAKRESET 0x2c -#define CR_TXSTARTBREAK 0x34 -#define CR_TXSTOPBREAK 0x3c -#define CR_RTSON 0x44 -#define CR_RTSOFF 0x4c -#define CR_ADDRINIT 0x5c -#define CR_RXERRBLOCK 0x6c -#define CR_TXSENDXON 0x84 -#define CR_TXSENDXOFF 0x8c -#define CR_GANGXONSET 0x94 -#define CR_GANGXOFFSET 0x9c -#define CR_GANGXONINIT 0xa4 -#define CR_GANGXOFFINIT 0xac -#define CR_HOSTXON 0xb4 -#define CR_HOSTXOFF 0xbc -#define CR_CANCELXOFF 0xc4 -#define CR_ADDRRESET 0xdc -#define CR_RESETALLPORTS 0xf4 -#define CR_RESETALL 0xfc - -#define CR_RXENABLE 0x01 -#define CR_TXENABLE 0x02 - -/*****************************************************************************/ - -/* - * Channel status register. - */ -#define SR_RXRDY 0x01 -#define SR_RXFULL 0x02 -#define SR_TXRDY 0x04 -#define SR_TXEMPTY 0x08 -#define SR_RXOVERRUN 0x10 -#define SR_RXPARITY 0x20 -#define SR_RXFRAMING 0x40 -#define SR_RXBREAK 0x80 - -#define SR_RXERRS (SR_RXPARITY | SR_RXFRAMING | SR_RXOVERRUN) - -/*****************************************************************************/ - -/* - * Interrupt status register and interrupt mask register bit definitions. - */ -#define IR_TXRDY 0x01 -#define IR_RXRDY 0x02 -#define IR_RXBREAK 0x04 -#define IR_XONXOFF 0x10 -#define IR_ADDRRECOG 0x20 -#define IR_RXWATCHDOG 0x40 -#define IR_IOPORT 0x80 - -/*****************************************************************************/ - -/* - * Interrupt vector register field definitions. - */ -#define IVR_CHANMASK 0x07 -#define IVR_TYPEMASK 0x18 -#define IVR_CONSTMASK 0xc0 - -#define IVR_RXDATA 0x10 -#define IVR_RXBADDATA 0x18 -#define IVR_TXDATA 0x08 -#define IVR_OTHER 0x00 - -/*****************************************************************************/ - -/* - * BRG timer control register bit definitions. - */ -#define BRGCTCR_DISABCLK0 0x00 -#define BRGCTCR_ENABCLK0 0x08 -#define BRGCTCR_DISABCLK1 0x00 -#define BRGCTCR_ENABCLK1 0x80 - -#define BRGCTCR_0SCLK16 0x00 -#define BRGCTCR_0SCLK32 0x01 -#define BRGCTCR_0SCLK64 0x02 -#define BRGCTCR_0SCLK128 0x03 -#define BRGCTCR_0X1 0x04 -#define BRGCTCR_0X12 0x05 -#define BRGCTCR_0IO1A 0x06 -#define BRGCTCR_0GIN0 0x07 - -#define BRGCTCR_1SCLK16 0x00 -#define BRGCTCR_1SCLK32 0x10 -#define BRGCTCR_1SCLK64 0x20 -#define BRGCTCR_1SCLK128 0x30 -#define BRGCTCR_1X1 0x40 -#define BRGCTCR_1X12 0x50 -#define BRGCTCR_1IO1B 0x60 -#define BRGCTCR_1GIN1 0x70 - -/*****************************************************************************/ - -/* - * Watch dog timer enable register. - */ -#define WDTRCR_ENABALL 0xff - -/*****************************************************************************/ - -/* - * XON/XOFF interrupt status register. - */ -#define XISR_TXCHARMASK 0x03 -#define XISR_TXCHARNORMAL 0x00 -#define XISR_TXWAIT 0x01 -#define XISR_TXXOFFPEND 0x02 -#define XISR_TXXONPEND 0x03 - -#define XISR_TXFLOWMASK 0x0c -#define XISR_TXNORMAL 0x00 -#define XISR_TXSTOPPEND 0x04 -#define XISR_TXSTARTED 0x08 -#define XISR_TXSTOPPED 0x0c - -#define XISR_RXFLOWMASK 0x30 -#define XISR_RXFLOWNONE 0x00 -#define XISR_RXXONSENT 0x10 -#define XISR_RXXOFFSENT 0x20 - -#define XISR_RXXONGOT 0x40 -#define XISR_RXXOFFGOT 0x80 - -/*****************************************************************************/ - -/* - * Current interrupt register. - */ -#define CIR_TYPEMASK 0xc0 -#define CIR_TYPEOTHER 0x00 -#define CIR_TYPETX 0x40 -#define CIR_TYPERXGOOD 0x80 -#define CIR_TYPERXBAD 0xc0 - -#define CIR_RXDATA 0x80 -#define CIR_RXBADDATA 0x40 -#define CIR_TXDATA 0x40 - -#define CIR_CHANMASK 0x07 -#define CIR_CNTMASK 0x38 - -#define CIR_SUBTYPEMASK 0x38 -#define CIR_SUBNONE 0x00 -#define CIR_SUBCOS 0x08 -#define CIR_SUBADDR 0x10 -#define CIR_SUBXONXOFF 0x18 -#define CIR_SUBBREAK 0x28 - -/*****************************************************************************/ - -/* - * Global interrupting channel register. - */ -#define GICR_CHANMASK 0x07 - -/*****************************************************************************/ - -/* - * Global interrupting byte count register. - */ -#define GICR_COUNTMASK 0x0f - -/*****************************************************************************/ - -/* - * Global interrupting type register. - */ -#define GITR_RXMASK 0xc0 -#define GITR_RXNONE 0x00 -#define GITR_RXBADDATA 0x80 -#define GITR_RXGOODDATA 0xc0 -#define GITR_TXDATA 0x20 - -#define GITR_SUBTYPEMASK 0x07 -#define GITR_SUBNONE 0x00 -#define GITR_SUBCOS 0x01 -#define GITR_SUBADDR 0x02 -#define GITR_SUBXONXOFF 0x03 -#define GITR_SUBBREAK 0x05 - -/*****************************************************************************/ - -/* - * Input port change register. - */ -#define IPR_CTS 0x01 -#define IPR_DTR 0x02 -#define IPR_RTS 0x04 -#define IPR_DCD 0x08 -#define IPR_CTSCHANGE 0x10 -#define IPR_DTRCHANGE 0x20 -#define IPR_RTSCHANGE 0x40 -#define IPR_DCDCHANGE 0x80 - -#define IPR_CHANGEMASK 0xf0 - -/*****************************************************************************/ - -/* - * IO port interrupt and output register. - */ -#define IOPR_CTS 0x01 -#define IOPR_DTR 0x02 -#define IOPR_RTS 0x04 -#define IOPR_DCD 0x08 -#define IOPR_CTSCOS 0x10 -#define IOPR_DTRCOS 0x20 -#define IOPR_RTSCOS 0x40 -#define IOPR_DCDCOS 0x80 - -/*****************************************************************************/ - -/* - * IO port configuration register. - */ -#define IOPCR_SETCTS 0x00 -#define IOPCR_SETDTR 0x04 -#define IOPCR_SETRTS 0x10 -#define IOPCR_SETDCD 0x00 - -#define IOPCR_SETSIGS (IOPCR_SETRTS | IOPCR_SETRTS | IOPCR_SETDTR | IOPCR_SETDCD) - -/*****************************************************************************/ - -/* - * General purpose output select register. - */ -#define GPORS_TXC1XA 0x08 -#define GPORS_TXC16XA 0x09 -#define GPORS_RXC16XA 0x0a -#define GPORS_TXC16XB 0x0b -#define GPORS_GPOR3 0x0c -#define GPORS_GPOR2 0x0d -#define GPORS_GPOR1 0x0e -#define GPORS_GPOR0 0x0f - -/*****************************************************************************/ - -/* - * General purpose output register. - */ -#define GPOR_0 0x01 -#define GPOR_1 0x02 -#define GPOR_2 0x04 -#define GPOR_3 0x08 - -/*****************************************************************************/ - -/* - * General purpose output clock register. - */ -#define GPORC_0NONE 0x00 -#define GPORC_0GIN0 0x01 -#define GPORC_0GIN1 0x02 -#define GPORC_0IO3A 0x02 - -#define GPORC_1NONE 0x00 -#define GPORC_1GIN0 0x04 -#define GPORC_1GIN1 0x08 -#define GPORC_1IO3C 0x0c - -#define GPORC_2NONE 0x00 -#define GPORC_2GIN0 0x10 -#define GPORC_2GIN1 0x20 -#define GPORC_2IO3E 0x20 - -#define GPORC_3NONE 0x00 -#define GPORC_3GIN0 0x40 -#define GPORC_3GIN1 0x80 -#define GPORC_3IO3G 0xc0 - -/*****************************************************************************/ - -/* - * General purpose output data register. - */ -#define GPOD_0MASK 0x03 -#define GPOD_0SET1 0x00 -#define GPOD_0SET0 0x01 -#define GPOD_0SETR0 0x02 -#define GPOD_0SETIO3B 0x03 - -#define GPOD_1MASK 0x0c -#define GPOD_1SET1 0x00 -#define GPOD_1SET0 0x04 -#define GPOD_1SETR0 0x08 -#define GPOD_1SETIO3D 0x0c - -#define GPOD_2MASK 0x30 -#define GPOD_2SET1 0x00 -#define GPOD_2SET0 0x10 -#define GPOD_2SETR0 0x20 -#define GPOD_2SETIO3F 0x30 - -#define GPOD_3MASK 0xc0 -#define GPOD_3SET1 0x00 -#define GPOD_3SET0 0x40 -#define GPOD_3SETR0 0x80 -#define GPOD_3SETIO3H 0xc0 - -/*****************************************************************************/ -#endif diff --git a/sys/dev/serial/stl/scd1400.h b/sys/dev/serial/stl/scd1400.h deleted file mode 100644 index 4d6a470980..0000000000 --- a/sys/dev/serial/stl/scd1400.h +++ /dev/null @@ -1,312 +0,0 @@ -/*****************************************************************************/ - -/* - * cd1400.h -- cd1400 UART hardware info. - * - * Copyright (c) 1995 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: src/sys/i386/isa/ic/scd1400.h,v 1.5 1999/08/28 00:45:15 peter Exp $ - */ - -/*****************************************************************************/ -#ifndef _CD1400_H -#define _CD1400_H -/*****************************************************************************/ - -/* - * Define the number of async ports per cd1400 uart chip. - */ -#define CD1400_PORTS 4 - -/* - * Define the cd1400 uarts internal FIFO sizes. - */ -#define CD1400_TXFIFOSIZE 12 -#define CD1400_RXFIFOSIZE 12 - -/* - * Local RX FIFO thresh hold level. Also define the RTS thresh hold - * based on the RX thresh hold. - */ -#define FIFO_RXTHRESHOLD 6 -#define FIFO_RTSTHRESHOLD 7 - -/*****************************************************************************/ - -/* - * Define the cd1400 register addresses. These are all the valid - * registers with the cd1400. Some are global, some virtual, some - * per port. - */ -#define GFRCR 0x40 -#define CAR 0x68 -#define GCR 0x4b -#define SVRR 0x67 -#define RICR 0x44 -#define TICR 0x45 -#define MICR 0x46 -#define RIR 0x6b -#define TIR 0x6a -#define MIR 0x69 -#define PPR 0x7e - -#define RIVR 0x43 -#define TIVR 0x42 -#define MIVR 0x41 -#define TDR 0x63 -#define RDSR 0x62 -#define MISR 0x4c -#define EOSRR 0x60 - -#define LIVR 0x18 -#define CCR 0x05 -#define SRER 0x06 -#define COR1 0x08 -#define COR2 0x09 -#define COR3 0x0a -#define COR4 0x1e -#define COR5 0x1f -#define CCSR 0x0b -#define RDCR 0x0e -#define SCHR1 0x1a -#define SCHR2 0x1b -#define SCHR3 0x1c -#define SCHR4 0x1d -#define SCRL 0x22 -#define SCRH 0x23 -#define LNC 0x24 -#define MCOR1 0x15 -#define MCOR2 0x16 -#define RTPR 0x21 -#define MSVR1 0x6c -#define MSVR2 0x6d -#define PSVR 0x6f -#define RBPR 0x78 -#define RCOR 0x7c -#define TBPR 0x72 -#define TCOR 0x76 - -/*****************************************************************************/ - -/* - * Define the set of baud rate clock divisors. - */ -#define CD1400_CLK0 8 -#define CD1400_CLK1 32 -#define CD1400_CLK2 128 -#define CD1400_CLK3 512 -#define CD1400_CLK4 2048 - -#define CD1400_NUMCLKS 5 - -/*****************************************************************************/ - -/* - * Define the clock pre-scalar value to be a 5 ms clock. This should be - * OK for now. It would probably be better to make it 10 ms, but we - * can't fit that divisor into 8 bits! - */ -#define PPR_SCALAR 244 - -/*****************************************************************************/ - -/* - * Define values used to set character size options. - */ -#define COR1_CHL5 0x00 -#define COR1_CHL6 0x01 -#define COR1_CHL7 0x02 -#define COR1_CHL8 0x03 - -/* - * Define values used to set the number of stop bits. - */ -#define COR1_STOP1 0x00 -#define COR1_STOP15 0x04 -#define COR1_STOP2 0x08 - -/* - * Define values used to set the parity scheme in use. - */ -#define COR1_PARNONE 0x00 -#define COR1_PARFORCE 0x20 -#define COR1_PARENB 0x40 -#define COR1_PARIGNORE 0x10 - -#define COR1_PARODD 0x80 -#define COR1_PAREVEN 0x00 - -#define COR2_IXM 0x80 -#define COR2_TXIBE 0x40 -#define COR2_ETC 0x20 -#define COR2_LLM 0x10 -#define COR2_RLM 0x08 -#define COR2_RTSAO 0x04 -#define COR2_CTSAE 0x02 - -#define COR3_SCDRNG 0x80 -#define COR3_SCD34 0x40 -#define COR3_FCT 0x20 -#define COR3_SCD12 0x10 - -/* - * Define the bit values of COR4. - */ -#define COR4_BRKINT 0x08 -#define COR4_IGNBRK 0x18 - -/* - * Define the bit values of COR5. - */ -#define COR5_ISTRIP 0x80 - -/*****************************************************************************/ - -/* - * Define the modem control register values. - * Note that the actual hardware is a little different to the conventional - * pin names on the cd1400. - */ -#define MSVR1_DTR 0x01 -#define MSVR1_DSR 0x10 -#define MSVR1_RI 0x20 -#define MSVR1_CTS 0x40 -#define MSVR1_DCD 0x80 - -#define MSVR2_RTS 0x02 -#define MSVR2_DSR 0x10 -#define MSVR2_RI 0x20 -#define MSVR2_CTS 0x40 -#define MSVR2_DCD 0x80 - -#define MCOR1_DCD 0x80 -#define MCOR1_CTS 0x40 -#define MCOR1_RI 0x20 -#define MCOR1_DSR 0x10 - -#define MCOR2_DCD 0x80 -#define MCOR2_CTS 0x40 -#define MCOR2_RI 0x20 -#define MCOR2_DSR 0x10 - -/*****************************************************************************/ - -/* - * Define the bits used with the service (interrupt) enable register. - */ -#define SRER_NNDT 0x01 -#define SRER_TXEMPTY 0x02 -#define SRER_TXDATA 0x04 -#define SRER_RXDATA 0x10 -#define SRER_MODEM 0x80 - -/*****************************************************************************/ - -/* - * Define operational commands for the command register. - */ -#define CCR_RESET 0x80 -#define CCR_CORCHANGE 0x4e -#define CCR_SENDCH 0x20 -#define CCR_CHANCTRL 0x10 - -#define CCR_TXENABLE (CCR_CHANCTRL | 0x08) -#define CCR_TXDISABLE (CCR_CHANCTRL | 0x04) -#define CCR_RXENABLE (CCR_CHANCTRL | 0x02) -#define CCR_RXDISABLE (CCR_CHANCTRL | 0x01) - -#define CCR_SENDSCHR1 (CCR_SENDCH | 0x01) -#define CCR_SENDSCHR2 (CCR_SENDCH | 0x02) -#define CCR_SENDSCHR3 (CCR_SENDCH | 0x03) -#define CCR_SENDSCHR4 (CCR_SENDCH | 0x04) - -#define CCR_RESETCHAN (CCR_RESET | 0x00) -#define CCR_RESETFULL (CCR_RESET | 0x01) -#define CCR_TXFLUSHFIFO (CCR_RESET | 0x02) - -#define CCR_MAXWAIT 10000 - -/*****************************************************************************/ - -/* - * Define the valid acknowledgement types (for hw ack cycle). - */ -#define ACK_TYPMASK 0x07 -#define ACK_TYPTX 0x02 -#define ACK_TYPMDM 0x01 -#define ACK_TYPRXGOOD 0x03 -#define ACK_TYPRXBAD 0x07 - -#define SVRR_RX 0x01 -#define SVRR_TX 0x02 -#define SVRR_MDM 0x04 - -#define ST_OVERRUN 0x01 -#define ST_FRAMING 0x02 -#define ST_PARITY 0x04 -#define ST_BREAK 0x08 -#define ST_SCHAR1 0x10 -#define ST_SCHAR2 0x20 -#define ST_SCHAR3 0x30 -#define ST_SCHAR4 0x40 -#define ST_RANGE 0x70 -#define ST_SCHARMASK 0x70 -#define ST_TIMEOUT 0x80 - -#define MISR_DCD 0x80 -#define MISR_CTS 0x40 -#define MISR_RI 0x20 -#define MISR_DSR 0x10 - -/*****************************************************************************/ - -/* - * Defines for the CCSR status register. - */ -#define CCSR_RXENABLED 0x80 -#define CCSR_RXFLOWON 0x40 -#define CCSR_RXFLOWOFF 0x20 -#define CCSR_TXENABLED 0x08 -#define CCSR_TXFLOWON 0x04 -#define CCSR_TXFLOWOFF 0x02 - -/*****************************************************************************/ - -/* - * Define the embedded commands. - */ -#define ETC_CMD 0x00 -#define ETC_STARTBREAK 0x81 -#define ETC_DELAY 0x82 -#define ETC_STOPBREAK 0x83 - -/*****************************************************************************/ -#endif diff --git a/sys/dev/serial/stl/stallion.c b/sys/dev/serial/stl/stallion.c deleted file mode 100644 index 7d490a32fa..0000000000 --- a/sys/dev/serial/stl/stallion.c +++ /dev/null @@ -1,4449 +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. - * - * $FreeBSD: src/sys/i386/isa/stallion.c,v 1.39.2.2 2001/08/30 12:29:57 murray Exp $ - */ - -/*****************************************************************************/ - -#define TTYDEFCHARS 1 - -#include "opt_compat.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#undef STLDEBUG - -/*****************************************************************************/ - -/* - * 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 -#define BRD_ECH64PCI 27 -#define BRD_EASYIOPCI 28 - -/*****************************************************************************/ - -/* - * Define important driver limitations. - */ -#define STL_MAXBRDS 8 -#define STL_MAXPANELS 4 -#define STL_MAXBANKS 8 -#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[] = "2.0.0"; - -static int stl_nrbrds = 0; -static int stl_doingtimeout = 0; -static struct callout stl_poll_ch; - -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 stlport { - 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; - void *uartp; - unsigned int state; - unsigned int hwid; - unsigned int sigs; - unsigned int rxignoremsk; - unsigned int rxmarkmsk; - unsigned int crenable; - unsigned int imr; - 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; - struct callout dtr_ch; -} stlport_t; - -typedef struct stlpanel { - int panelnr; - int brdnr; - int pagenr; - int nrports; - int iobase; - unsigned int hwid; - unsigned int ackmask; - void (*isr)(struct stlpanel *panelp, unsigned int iobase); - void *uartp; - stlport_t *ports[STL_PORTSPERPANEL]; -} stlpanel_t; - -typedef struct stlbrd { - int brdnr; - int brdtype; - int unitid; - int state; - int nrpanels; - int nrports; - int nrbnks; - 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; - void (*isr)(struct stlbrd *brdp); - unsigned int bnkpageaddr[STL_MAXBANKS]; - unsigned int bnkstataddr[STL_MAXBANKS]; - stlpanel_t *bnk2panel[STL_MAXBANKS]; - 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_TXFLOWED 0x80 -#define ASY_TXBUSY 0x100 -#define ASY_TXEMPTY 0x200 - -#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[] = { - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "EasyIO", - "EC8/32-AT", - "EC8/32-MC", - NULL, - NULL, - NULL, - "EC8/32-PCI", - "EC8/64-PCI", - "EasyIO-PCI", -}; - -/*****************************************************************************/ - -/* - * Hardware ID bits for the EasyIO and ECH boards. These defines apply - * to the directly accessable 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_MK3 0x03 -#define EIO_IDBITMASK 0x07 - -#define EIO_BRDMASK 0xf0 -#define ID_BRD4 0x10 -#define ID_BRD8 0x20 -#define ID_BRD16 0x30 - -#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_PNLXPID 0x40 -#define ECH_PNLINTRPEND 0x80 -#define ECH_ADDR2MASK 0x1e0 - -#define EIO_CLK 25000000 -#define EIO_CLK8M 20000000 -#define ECH_CLK EIO_CLK - -/* - * Define the PCI vendor and device ID for Stallion PCI boards. - */ -#define STL_PCINSVENDID 0x100b -#define STL_PCINSDEVID 0xd001 - -#define STL_PCIVENDID 0x124d -#define STL_PCI32DEVID 0x0000 -#define STL_PCI64DEVID 0x0002 -#define STL_PCIEIODEVID 0x0003 - -#define STL_PCIBADCLASS 0x0101 - -typedef struct stlpcibrd { - unsigned short vendid; - unsigned short devid; - int brdtype; -} stlpcibrd_t; - -static stlpcibrd_t stl_pcibrds[] = { - { STL_PCIVENDID, STL_PCI64DEVID, BRD_ECH64PCI }, - { STL_PCIVENDID, STL_PCIEIODEVID, BRD_EASYIOPCI }, - { STL_PCIVENDID, STL_PCI32DEVID, BRD_ECHPCI }, - { STL_PCINSVENDID, STL_PCINSDEVID, BRD_ECHPCI }, -}; - -static int stl_nrpcibrds = NELEM(stl_pcibrds); - -/*****************************************************************************/ - -/* - * 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 some spare buffer space for un-wanted received characters. - */ -static char stl_unwanted[SC26198_RXFIFOSIZE]; - -/*****************************************************************************/ - -/* - * 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 d_open_t stlopen; -static d_close_t stlclose; -static d_ioctl_t stlioctl; - -/* - * Internal function prototypes. - */ -static stlport_t *stl_dev2port(cdev_t dev); -static int stl_findfreeunit(void); -static int stl_rawopen(stlport_t *portp); -static int stl_rawclose(stlport_t *portp); -static void stl_flush(stlport_t *portp, int flag); -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_flowcontrol(stlport_t *portp, int hw, int sw); -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 void stl_eiointr(stlbrd_t *brdp); -static void stl_echatintr(stlbrd_t *brdp); -static void stl_echmcaintr(stlbrd_t *brdp); -static void stl_echpciintr(stlbrd_t *brdp); -static void stl_echpci64intr(stlbrd_t *brdp); -static int stl_memioctl(cdev_t dev, unsigned long cmd, caddr_t data, - int flag); -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); -static void stlintr(void *); - -static const char *stlpciprobe(pcici_t tag, pcidi_t type); -static void stlpciattach(pcici_t tag, int unit); -static void stlpciintr(void * arg); - -/* - * CD1400 uart specific handling functions. - */ -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value); -static int stl_cd1400getreg(stlport_t *portp, int regnr); -static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value); -static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static int stl_cd1400setport(stlport_t *portp, struct termios *tiosp); -static int stl_cd1400getsignals(stlport_t *portp); -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts); -static void stl_cd1400ccrwait(stlport_t *portp); -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx); -static void stl_cd1400disableintrs(stlport_t *portp); -static void stl_cd1400sendbreak(stlport_t *portp, long len); -static void stl_cd1400sendflow(stlport_t *portp, int hw, int sw); -static int stl_cd1400datastate(stlport_t *portp); -static void stl_cd1400flush(stlport_t *portp, int flag); -static __inline void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr); -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase); -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase); - -/* - * SC26198 uart specific handling functions. - */ -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getreg(stlport_t *portp, int regnr); -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value); -static int stl_sc26198getglobreg(stlport_t *portp, int regnr); -static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp); -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); -static int stl_sc26198setport(stlport_t *portp, struct termios *tiosp); -static int stl_sc26198getsignals(stlport_t *portp); -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts); -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx); -static void stl_sc26198disableintrs(stlport_t *portp); -static void stl_sc26198sendbreak(stlport_t *portp, long len); -static void stl_sc26198sendflow(stlport_t *portp, int hw, int sw); -static int stl_sc26198datastate(stlport_t *portp); -static void stl_sc26198flush(stlport_t *portp, int flag); -static void stl_sc26198txunflow(stlport_t *portp); -static void stl_sc26198wait(stlport_t *portp); -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase); -static void stl_sc26198txisr(stlport_t *port); -static void stl_sc26198rxisr(stlport_t *port, unsigned int iack); -static void stl_sc26198rxgoodchars(stlport_t *portp); -static void stl_sc26198rxbadchars(stlport_t *portp); -static void stl_sc26198otherisr(stlport_t *port, unsigned int iack); - -/*****************************************************************************/ - -/* - * Generic UART support structure. - */ -typedef struct uart { - int (*panelinit)(stlbrd_t *brdp, stlpanel_t *panelp); - void (*portinit)(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp); - int (*setport)(stlport_t *portp, struct termios *tiosp); - int (*getsignals)(stlport_t *portp); - void (*setsignals)(stlport_t *portp, int dtr, int rts); - void (*enablerxtx)(stlport_t *portp, int rx, int tx); - void (*startrxtx)(stlport_t *portp, int rx, int tx); - void (*disableintrs)(stlport_t *portp); - void (*sendbreak)(stlport_t *portp, long len); - void (*sendflow)(stlport_t *portp, int hw, int sw); - void (*flush)(stlport_t *portp, int flag); - int (*datastate)(stlport_t *portp); - void (*intr)(stlpanel_t *panelp, unsigned int iobase); -} uart_t; - -/* - * Define some macros to make calling these functions nice and clean. - */ -#define stl_panelinit (* ((uart_t *) panelp->uartp)->panelinit) -#define stl_portinit (* ((uart_t *) portp->uartp)->portinit) -#define stl_setport (* ((uart_t *) portp->uartp)->setport) -#define stl_getsignals (* ((uart_t *) portp->uartp)->getsignals) -#define stl_setsignals (* ((uart_t *) portp->uartp)->setsignals) -#define stl_enablerxtx (* ((uart_t *) portp->uartp)->enablerxtx) -#define stl_startrxtx (* ((uart_t *) portp->uartp)->startrxtx) -#define stl_disableintrs (* ((uart_t *) portp->uartp)->disableintrs) -#define stl_sendbreak (* ((uart_t *) portp->uartp)->sendbreak) -#define stl_sendflow (* ((uart_t *) portp->uartp)->sendflow) -#define stl_uartflush (* ((uart_t *) portp->uartp)->flush) -#define stl_datastate (* ((uart_t *) portp->uartp)->datastate) - -/*****************************************************************************/ - -/* - * CD1400 UART specific data initialization. - */ -static uart_t stl_cd1400uart = { - stl_cd1400panelinit, - stl_cd1400portinit, - stl_cd1400setport, - stl_cd1400getsignals, - stl_cd1400setsignals, - stl_cd1400enablerxtx, - stl_cd1400startrxtx, - stl_cd1400disableintrs, - stl_cd1400sendbreak, - stl_cd1400sendflow, - stl_cd1400flush, - stl_cd1400datastate, - stl_cd1400eiointr -}; - -/* - * Define the offsets within the register bank of a cd1400 based panel. - * These io address offsets are common to the EasyIO board as well. - */ -#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 CD1400_CLK 25000000 -#define CD1400_CLK8M 20000000 - -/* - * 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 the maximum baud rate of the cd1400 devices. - */ -#define CD1400_MAXBAUD 230400 - -/*****************************************************************************/ - -/* - * SC26198 UART specific data initization. - */ -static uart_t stl_sc26198uart = { - stl_sc26198panelinit, - stl_sc26198portinit, - stl_sc26198setport, - stl_sc26198getsignals, - stl_sc26198setsignals, - stl_sc26198enablerxtx, - stl_sc26198startrxtx, - stl_sc26198disableintrs, - stl_sc26198sendbreak, - stl_sc26198sendflow, - stl_sc26198flush, - stl_sc26198datastate, - stl_sc26198intr -}; - -/* - * Define the offsets within the register bank of a sc26198 based panel. - */ -#define XP_DATA 0 -#define XP_ADDR 1 -#define XP_MODID 2 -#define XP_STATUS 2 -#define XP_IACK 3 - -#define XP_BANKSIZE 4 - -/* - * Define the sc26198 baud rate table. Offsets within the table - * represent the actual baud rate selector of sc26198 registers. - */ -static unsigned int sc26198_baudtable[] = { - 50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600, - 4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200, - 230400, 460800 -}; - -#define SC26198_NRBAUDS NELEM(sc26198_baudtable) - -/* - * Define the maximum baud rate of the sc26198 devices. - */ -#define SC26198_MAXBAUD 460800 - -/*****************************************************************************/ - -/* - * 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); - -/*****************************************************************************/ - -/* - * FreeBSD-2.2+ kernel linkage. - */ - -#define CDEV_MAJOR 72 -static struct dev_ops stl_ops = { - { "stl", 0, D_TTY }, - .d_open = stlopen, - .d_close = stlclose, - .d_read = ttyread, - .d_write = ttywrite, - .d_ioctl = stlioctl, - .d_kqfilter = ttykqfilter, - .d_revoke = ttyrevoke -}; - -static void stl_drvinit(void *unused) -{ -} - -SYSINIT(sidev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,stl_drvinit,NULL); - -/*****************************************************************************/ - -/* - * 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(void) -{ - int i; - - for (i = 0; (i < STL_MAXBRDS); i++) - if (stl_brds[i] == NULL) - break; - return((i >= STL_MAXBRDS) ? -1 : i); -} - -/*****************************************************************************/ - -/* - * 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; - int i, brdtype; - -#ifdef STLDEBUG - kprintf("stlpciprobe(tag=%x,type=%x)\n", (int) &tag, (int) type); -#endif - - brdtype = 0; - for (i = 0; (i < stl_nrpcibrds); i++) { - if (((type & 0xffff) == stl_pcibrds[i].vendid) && - (((type >> 16) & 0xffff) == stl_pcibrds[i].devid)) { - brdtype = stl_pcibrds[i].brdtype; - break; - } - } - - if (brdtype == 0) - return(NULL); - - class = pci_conf_read(tag, PCI_CLASS_REG); - if ((class & PCI_CLASS_MASK) == PCI_CLASS_MASS_STORAGE) - return(NULL); - - return(stl_brdnames[brdtype]); -} - -/*****************************************************************************/ - -/* - * Allocate resources for and initialize the specified PCI board. - */ - -void stlpciattach(pcici_t tag, int unit) -{ - stlbrd_t *brdp; - unsigned int bar[4]; - unsigned int id; - int i; - int boardnr, portnr, minor_dev; - -#ifdef STLDEBUG - kprintf("stlpciattach(tag=%x,unit=%x)\n", (int) &tag, unit); -#endif - - brdp = kmalloc(sizeof(stlbrd_t), M_TTYS, M_WAITOK | M_ZERO); - - if ((unit < 0) || (unit > STL_MAXBRDS)) { - kprintf("STALLION: bad PCI board unit number=%d\n", unit); - return; - } - -/* - * Allocate us a new driver unique unit number. - */ - if ((brdp->brdnr = stl_findfreeunit()) < 0) { - kprintf("STALLION: too many boards found, max=%d\n", - STL_MAXBRDS); - return; - } - if (brdp->brdnr >= stl_nrbrds) - stl_nrbrds = brdp->brdnr + 1; - -/* - * Determine what type of PCI board this is... - */ - id = (unsigned int) pci_conf_read(tag, 0x0); - for (i = 0; (i < stl_nrpcibrds); i++) { - if (((id & 0xffff) == stl_pcibrds[i].vendid) && - (((id >> 16) & 0xffff) == stl_pcibrds[i].devid)) { - brdp->brdtype = stl_pcibrds[i].brdtype; - break; - } - } - - if (i >= stl_nrpcibrds) { - kprintf("STALLION: probed PCI board unknown type=%x\n", id); - return; - } - - for (i = 0; (i < 4); i++) - bar[i] = (unsigned int) pci_conf_read(tag, 0x10 + (i * 4)) & - 0xfffc; - - switch (brdp->brdtype) { - case BRD_ECH64PCI: - brdp->ioaddr1 = bar[1]; - brdp->ioaddr2 = bar[2]; - break; - case BRD_EASYIOPCI: - brdp->ioaddr1 = bar[2]; - brdp->ioaddr2 = bar[1]; - break; - case BRD_ECHPCI: - brdp->ioaddr1 = bar[1]; - brdp->ioaddr2 = bar[0]; - break; - default: - kprintf("STALLION: unknown PCI board type=%d\n", brdp->brdtype); - return; - break; - } - - brdp->unitid = brdp->brdnr; /* PCI units auto-assigned */ - brdp->irq = ((int) pci_conf_read(tag, 0x3c)) & 0xff; - brdp->irqtype = 0; - if (pci_map_int(tag, stlpciintr, NULL) == 0) { - kprintf("STALLION: failed to map interrupt irq=%d for unit=%d\n", - brdp->irq, brdp->brdnr); - return; - } - - stl_brdinit(brdp); - - /* register devices for DEVFS */ - boardnr = brdp->brdnr; - make_dev(&stl_ops, boardnr + 0x1000000, UID_ROOT, GID_WHEEL, - 0600, "staliomem%d", boardnr); - - for (portnr = 0, minor_dev = boardnr * 0x100000; - portnr < 32; portnr++, minor_dev++) { - /* hw ports */ - make_dev(&stl_ops, minor_dev, - UID_ROOT, GID_WHEEL, 0600, - "ttyE%d", portnr + (boardnr * 64)); - make_dev(&stl_ops, minor_dev + 32, - UID_ROOT, GID_WHEEL, 0600, - "ttyiE%d", portnr + (boardnr * 64)); - make_dev(&stl_ops, minor_dev + 64, - UID_ROOT, GID_WHEEL, 0600, - "ttylE%d", portnr + (boardnr * 64)); - make_dev(&stl_ops, minor_dev + 128, - UID_ROOT, GID_WHEEL, 0600, - "cue%d", portnr + (boardnr * 64)); - make_dev(&stl_ops, minor_dev + 160, - UID_ROOT, GID_WHEEL, 0600, - "cuie%d", portnr + (boardnr * 64)); - make_dev(&stl_ops, minor_dev + 192, - UID_ROOT, GID_WHEEL, 0600, - "cule%d", portnr + (boardnr * 64)); - - /* sw ports */ - make_dev(&stl_ops, minor_dev + 0x10000, - UID_ROOT, GID_WHEEL, 0600, - "ttyE%d", portnr + (boardnr * 64) + 32); - make_dev(&stl_ops, minor_dev + 32 + 0x10000, - UID_ROOT, GID_WHEEL, 0600, - "ttyiE%d", portnr + (boardnr * 64) + 32); - make_dev(&stl_ops, minor_dev + 64 + 0x10000, - UID_ROOT, GID_WHEEL, 0600, - "ttylE%d", portnr + (boardnr * 64) + 32); - make_dev(&stl_ops, minor_dev + 128 + 0x10000, - UID_ROOT, GID_WHEEL, 0600, - "cue%d", portnr + (boardnr * 64) + 32); - make_dev(&stl_ops, minor_dev + 160 + 0x10000, - UID_ROOT, GID_WHEEL, 0600, - "cuie%d", portnr + (boardnr * 64) + 32); - make_dev(&stl_ops, minor_dev + 192 + 0x10000, - UID_ROOT, GID_WHEEL, 0600, - "cule%d", portnr + (boardnr * 64) + 32); - } -} - -/*****************************************************************************/ - -static int stlopen(struct dev_open_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct tty *tp; - stlport_t *portp; - int error, callout; - -#ifdef STLDEBUG - kprintf("stlopen(dev=%x,flag=%x,mode=%x,p=%x)\n", (int) dev, flag, - mode, (int) p); -#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 == NULL) - return(ENXIO); - if (minor(dev) & STL_CTRLDEV) - return(0); - tp = &portp->tty; - dev->si_tty = tp; - callout = minor(dev) & STL_CALLOUTDEV; - error = 0; - - crit_enter(); - -stlopen_restart: -/* - * Wait here for the DTR drop timeout period to expire. - */ - while (portp->state & ASY_DTRWAIT) { - error = tsleep(&portp->dtrwait, 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); - ttsetwater(tp); - 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 (ap->a_oflags & O_NONBLOCK) { - error = EBUSY; - goto stlopen_end; - } - error = tsleep(&portp->callout, - PCATCH, "stlcall", 0); - if (error) - goto stlopen_end; - goto stlopen_restart; - } - } - if ((tp->t_state & TS_XCLUDE) && priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) { - 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) && - ((ap->a_oflags & O_NONBLOCK) == 0)) { - portp->waitopens++; - error = tsleep(TSA_CARR_ON(tp), 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: - crit_exit(); - if (((tp->t_state & TS_ISOPEN) == 0) && (portp->waitopens == 0)) - stl_rawclose(portp); - - return(error); -} - -/*****************************************************************************/ - -static int stlclose(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct tty *tp; - stlport_t *portp; - -#ifdef STLDEBUG - kprintf("stlclose(dev=%s,flag=%x,mode=%x,p=%p)\n", devtoname(dev), - flag, mode, (void *) p); -#endif - - if (minor(dev) & STL_MEMDEV) - return(0); - if (minor(dev) & STL_CTRLDEV) - return(0); - - portp = stl_dev2port(dev); - if (portp == NULL) - return(ENXIO); - tp = &portp->tty; - - crit_enter(); - (*linesw[tp->t_line].l_close)(tp, ap->a_fflag); - stl_ttyoptim(portp, &tp->t_termios); - stl_rawclose(portp); - ttyclose(tp); - crit_exit(); - return(0); -} - -/*****************************************************************************/ - -static void stl_stop(struct tty *tp, int rw) -{ -#ifdef STLDEBUG - kprintf("stl_stop(tp=%x,rw=%x)\n", (int) tp, rw); -#endif - - stl_flush((stlport_t *) tp, rw); -} - -/*****************************************************************************/ - -static int stlioctl(struct dev_ioctl_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - u_long cmd = ap->a_cmd; - caddr_t data = ap->a_data; - struct termios *newtios, *localtios; - struct tty *tp; - stlport_t *portp; - int error, i; - -#ifdef STLDEBUG - kprintf("stlioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n", - devtoname(dev), cmd, (void *) data, ap->a_fflag); -#endif - - if (minor(dev) & STL_MEMDEV) - return(stl_memioctl(dev, cmd, data, ap->a_fflag)); - - portp = stl_dev2port(dev); - if (portp == 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 = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) == 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) - 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, - ap->a_fflag, ap->a_cred); - if (error != ENOIOCTL) - return(error); - - crit_enter(); - error = ttioctl(tp, cmd, data, ap->a_fflag); - stl_ttyoptim(portp, &tp->t_termios); - if (error != ENOIOCTL) { - crit_exit(); - 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 = priv_check_cred(ap->a_cred, PRIV_ROOT, 0)) == 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; - } - crit_exit(); - - 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(cdev_t dev) -{ - stlbrd_t *brdp; - - brdp = stl_brds[MKDEV2BRD(dev)]; - if (brdp == NULL) - return(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) -{ -#ifdef STLDEBUG - kprintf("stl_rawopen(portp=%p): brdnr=%d panelnr=%d portnr=%d\n", - (void *) portp, portp->brdnr, portp->panelnr, portp->portnr); -#endif - - stl_setport(portp, &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; - -#ifdef STLDEBUG - kprintf("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; - callout_reset(&portp->dtr_ch, portp->dtrwait, - stl_dtrwakeup, portp); - } - } - 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; - - portp = (stlport_t *) tp; - -#ifdef STLDEBUG - kprintf("stl_start(tp=%x): brdnr=%d portnr=%d\n", (int) tp, - portp->brdnr, portp->portnr); -#endif - - crit_enter(); - -/* - * 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_RTSFLOWMODE) && - ((portp->state & ASY_RTSFLOW) == 0)) - stl_flowcontrol(portp, 0, -1); - } else { - if (portp->state & ASY_RTSFLOW) - stl_flowcontrol(portp, 1, -1); - } - - if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - crit_exit(); - 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; - } - -/* - * Do any writer wakeups. - */ - ttwwakeup(tp); - - crit_exit(); -} - -/*****************************************************************************/ - -static void stl_flush(stlport_t *portp, int flag) -{ - char *head, *tail; - int len; - -#ifdef STLDEBUG - kprintf("stl_flush(portp=%x,flag=%x)\n", (int) portp, flag); -#endif - - if (portp == NULL) - return; - - crit_enter(); - - if (flag & FWRITE) { - stl_uartflush(portp, FWRITE); - portp->tx.tail = portp->tx.head; - } - -/* - * 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); - } - - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Interrupt handler for host based boards. Interrupts for all boards - * are vectored through here. - */ - -void stlintr(void *arg) -{ - stlbrd_t *brdp; - int i; - -#ifdef STLDEBUG - kprintf("stlintr(unit=%d)\n", (int)arg); -#endif - - for (i = 0; (i < stl_nrbrds); i++) { - if ((brdp = stl_brds[i]) == NULL) - continue; - if (brdp->state == 0) - continue; - (* brdp->isr)(brdp); - } -} - -/*****************************************************************************/ - -static void stlpciintr(void *arg) -{ - stlintr(NULL); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for EasyIO boards. - */ - -static void stl_eiointr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - int iobase; - -#ifdef STLDEBUG - kprintf("stl_eiointr(brdp=%p)\n", brdp); -#endif - - panelp = brdp->panels[0]; - iobase = panelp->iobase; - while (inb(brdp->iostatus) & EIO_INTRPEND) - (* panelp->isr)(panelp, iobase); -} - -/* - * Interrupt service routine for ECH-AT board types. - */ - -static void stl_echatintr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; - - outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDENABLE)); - - while (inb(brdp->iostatus) & ECH_INTRPEND) { - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } - - outb(brdp->ioctrl, (brdp->ioctrlval | ECH_BRDDISABLE)); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-MCA board types. - */ - -static void stl_echmcaintr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; - - while (inb(brdp->iostatus) & ECH_INTRPEND) { - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for ECH-PCI board types. - */ - -static void stl_echpciintr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr, recheck; - -#ifdef STLDEBUG - kprintf("stl_echpciintr(brdp=%x)\n", (int) brdp); -#endif - - for (;;) { - recheck = 0; - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - outb(brdp->ioctrl, brdp->bnkpageaddr[bnknr]); - ioaddr = brdp->bnkstataddr[bnknr]; - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - recheck++; - } - } - if (! recheck) - break; - } -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for EC8/64-PCI board types. - */ - -static void stl_echpci64intr(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int ioaddr; - int bnknr; - -#ifdef STLDEBUG - kprintf("stl_echpci64intr(brdp=%p)\n", brdp); -#endif - - while (inb(brdp->ioctrl) & 0x1) { - for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) { - ioaddr = brdp->bnkstataddr[bnknr]; -#ifdef STLDEBUG - kprintf(" --> ioaddr=%x status=%x(%x)\n", ioaddr, inb(ioaddr) & ECH_PNLINTRPEND, inb(ioaddr)); -#endif - if (inb(ioaddr) & ECH_PNLINTRPEND) { - panelp = brdp->bnk2panel[bnknr]; - (* panelp->isr)(panelp, (ioaddr & 0xfffc)); - } - } - } -} - -/*****************************************************************************/ - -/* - * If we haven't scheduled a timeout then do it, some port needs high - * level processing. - */ - -static void stl_dotimeout(void) -{ -#ifdef STLDEBUG - kprintf("stl_dotimeout()\n"); -#endif - if (stl_doingtimeout == 0) { - if ((stl_poll_ch.c_flags & CALLOUT_DID_INIT) == 0) - callout_init(&stl_poll_ch); - callout_reset(&stl_poll_ch, 1, stl_poll, NULL); - 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; - -#ifdef STLDEBUG - kprintf("stl_poll()\n"); -#endif - - stl_doingtimeout = 0; - rearm = 0; - - crit_enter(); - for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) { - if ((brdp = stl_brds[brdnr]) == NULL) - continue; - for (portnr = 0; (portnr < brdp->nrports); portnr++) { - if ((portp = brdp->ports[portnr]) == 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_TXEMPTY) { - if (stl_datastate(portp) == 0) { - portp->state &= ~ASY_TXEMPTY; - tp->t_state &= ~TS_BUSY; - (*linesw[tp->t_line].l_start)(tp); - } - } - if (portp->state & ASY_TXLOW) { - portp->state &= ~ASY_TXLOW; - (*linesw[tp->t_line].l_start)(tp); - } - - if (portp->state & ASY_ACTIVE) - rearm++; - } - } - crit_exit(); - - 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; - -#ifdef STLDEBUG - kprintf("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 were 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); -} - -/*****************************************************************************/ - -static int stl_param(struct tty *tp, struct termios *tiosp) -{ - stlport_t *portp; - - portp = (stlport_t *) tp; - if (portp == NULL) - return(ENODEV); - - return(stl_setport(portp, tiosp)); -} - -/*****************************************************************************/ - -/* - * 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; - -#ifdef STLDEBUG - kprintf("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. - */ - stl_sendflow(portp, hwflow, sw); -} - -/*****************************************************************************/ - -/* - * 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 | ISTRIP)) == 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; - int i, j; - -#ifdef STLDEBUG - kprintf("stl_initports(panelp=%x)\n", (int) panelp); -#endif - -/* - * All UART's are initialized if found. Now go through and setup - * each ports data structures. Also initialize each individual - * UART port. - */ - for (i = 0; (i < panelp->nrports); i++) { - portp = kmalloc(sizeof(stlport_t), M_TTYS, M_WAITOK | M_ZERO); - - portp->portnr = i; - portp->brdnr = panelp->brdnr; - portp->panelnr = panelp->panelnr; - portp->uartp = panelp->uartp; - portp->clk = brdp->clk; - panelp->ports[i] = portp; - - j = STL_TXBUFSIZE + (2 * STL_RXBUFSIZE); - portp->tx.buf = kmalloc(j, M_TTYS, M_WAITOK); - 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; - callout_init(&portp->dtr_ch); - - stl_portinit(brdp, panelp, portp); - } - - return(0); -} - -/*****************************************************************************/ - -/* - * Try to find and initialize an EasyIO board. - */ - -static int stl_initeio(stlbrd_t *brdp) -{ - stlpanel_t *panelp; - unsigned int status; - -#ifdef STLDEBUG - kprintf("stl_initeio(brdp=%x)\n", (int) brdp); -#endif - - brdp->ioctrl = brdp->ioaddr1 + 1; - brdp->iostatus = brdp->ioaddr1 + 2; - brdp->clk = EIO_CLK; - brdp->isr = stl_eiointr; - - status = inb(brdp->iostatus); - switch (status & EIO_IDBITMASK) { - case EIO_8PORTM: - brdp->clk = EIO_CLK8M; - /* fall thru */ - case EIO_8PORTRS: - case EIO_8PORTDI: - brdp->nrports = 8; - break; - case EIO_4PORTRS: - brdp->nrports = 4; - break; - case EIO_MK3: - switch (status & EIO_BRDMASK) { - case ID_BRD4: - brdp->nrports = 4; - break; - case ID_BRD8: - brdp->nrports = 8; - break; - case ID_BRD16: - brdp->nrports = 16; - break; - default: - return(ENODEV); - } - brdp->ioctrl++; - break; - default: - return(ENODEV); - } - - if (brdp->brdtype == BRD_EASYIOPCI) { - outb((brdp->ioaddr2 + 0x4c), 0x41); - } else { -/* - * 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)) { - kprintf("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 = kmalloc(sizeof(stlpanel_t), M_TTYS, M_WAITOK | M_ZERO); - panelp->brdnr = brdp->brdnr; - panelp->panelnr = 0; - panelp->nrports = brdp->nrports; - panelp->iobase = brdp->ioaddr1; - panelp->hwid = status; - if ((status & EIO_IDBITMASK) == EIO_MK3) { - panelp->uartp = (void *) &stl_sc26198uart; - panelp->isr = stl_sc26198intr; - } else { - panelp->uartp = (void *) &stl_cd1400uart; - panelp->isr = stl_cd1400eiointr; - } - 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, banknr, i; - -#ifdef STLDEBUG - kprintf("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. - */ - switch (brdp->brdtype) { - - case BRD_ECH: - brdp->isr = stl_echatintr; - 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)) { - kprintf("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); - break; - - case BRD_ECHMC: - brdp->isr = stl_echmcaintr; - 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)) { - kprintf("STALLION: invalid irq=%d for brd=%d\n", - brdp->irq, brdp->brdnr); - return(EINVAL); - } - outb(brdp->ioctrl, ECHMC_BRDRESET); - outb(brdp->ioctrl, ECHMC_INTENABLE); - break; - - case BRD_ECHPCI: - brdp->isr = stl_echpciintr; - brdp->ioctrl = brdp->ioaddr1 + 2; - break; - - case BRD_ECH64PCI: - brdp->isr = stl_echpci64intr; - brdp->ioctrl = brdp->ioaddr2 + 0x40; - outb((brdp->ioaddr1 + 0x4c), 0x43); - break; - - default: - kprintf("STALLION: unknown board type=%d\n", brdp->brdtype); - break; - } - - 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; - banknr = 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 = kmalloc(sizeof(stlpanel_t), M_TTYS, M_WAITOK | M_ZERO); - panelp->brdnr = brdp->brdnr; - panelp->panelnr = panelnr; - panelp->iobase = ioaddr; - panelp->pagenr = nxtid; - panelp->hwid = status; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS; - - if (status & ECH_PNLXPID) { - panelp->uartp = (void *) &stl_sc26198uart; - panelp->isr = stl_sc26198intr; - if (status & ECH_PNL16PORT) { - panelp->nrports = 16; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + 4 + - ECH_PNLSTATUS; - } else { - panelp->nrports = 8; - } - } else { - panelp->uartp = (void *) &stl_cd1400uart; - panelp->isr = stl_cd1400echintr; - if (status & ECH_PNL16PORT) { - panelp->nrports = 16; - panelp->ackmask = 0x80; - if (brdp->brdtype != BRD_ECHPCI) - ioaddr += EREG_BANKSIZE; - brdp->bnk2panel[banknr] = panelp; - brdp->bnkpageaddr[banknr] = ++nxtid; - brdp->bnkstataddr[banknr++] = ioaddr + - ECH_PNLSTATUS; - } else { - panelp->nrports = 8; - panelp->ackmask = 0xc0; - } - } - - nxtid++; - ioaddr += EREG_BANKSIZE; - brdp->nrports += panelp->nrports; - brdp->panels[panelnr++] = panelp; - if ((brdp->brdtype == BRD_ECH) || (brdp->brdtype == BRD_ECHMC)){ - if (ioaddr >= (brdp->ioaddr2 + 0x20)) { - kprintf("STALLION: too many ports attached " - "to board %d, remove last module\n", - brdp->brdnr); - break; - } - } - } - - brdp->nrpanels = panelnr; - brdp->nrbnks = banknr; - 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; - -#ifdef STLDEBUG - kprintf("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: - case BRD_EASYIOPCI: - stl_initeio(brdp); - break; - case BRD_ECH: - case BRD_ECHMC: - case BRD_ECHPCI: - case BRD_ECH64PCI: - stl_initech(brdp); - break; - default: - kprintf("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 - kprintf("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 != NULL) { - stl_initports(brdp, panelp); - for (j = 0; (j < panelp->nrports); j++) - brdp->ports[k++] = panelp->ports[j]; - } - } - - kprintf("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 == 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(NULL); - brdp = stl_brds[brdnr]; - if (brdp == NULL) - return(NULL); - if ((panelnr < 0) || (panelnr >= brdp->nrpanels)) - return(NULL); - panelp = brdp->panels[panelnr]; - if (panelp == NULL) - return(NULL); - if ((portnr < 0) || (portnr >= panelp->nrports)) - return(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 == NULL) { - stl_comstats = *((comstats_t *) data); - portp = stl_getport(stl_comstats.brd, stl_comstats.panel, - stl_comstats.port); - if (portp == 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 == NULL) { - stl_comstats = *((comstats_t *) data); - portp = stl_getport(stl_comstats.brd, stl_comstats.panel, - stl_comstats.port); - if (portp == 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(cdev_t dev, unsigned long cmd, caddr_t data, int flag) -{ - int rc; - -#ifdef STLDEBUG - kprintf("stl_memioctl(dev=%s,cmd=%lx,data=%p,flag=%x)\n", - devtoname(dev), cmd, (void *) data, flag); -#endif - - rc = 0; - - switch (cmd) { - case COM_GETPORTSTATS: - rc = stl_getportstats(NULL, data); - break; - case COM_CLRPORTSTATS: - rc = stl_clrportstats(NULL, data); - break; - case COM_GETBRDSTATS: - rc = stl_getbrdstats(data); - break; - default: - rc = ENOTTY; - break; - } - - return(rc); -} - -/*****************************************************************************/ - -/*****************************************************************************/ -/* CD1400 UART CODE */ -/*****************************************************************************/ - -/* - * These functions get/set/update the registers of the cd1400 UARTs. - * Access to the cd1400 registers is via an address/data io port pair. - */ - -static int stl_cd1400getreg(stlport_t *portp, int regnr) -{ - outb(portp->ioaddr, (regnr + portp->uartaddr)); - return(inb(portp->ioaddr + EREG_DATA)); -} - -/*****************************************************************************/ - -static void stl_cd1400setreg(stlport_t *portp, int regnr, int value) -{ - outb(portp->ioaddr, (regnr + portp->uartaddr)); - outb((portp->ioaddr + EREG_DATA), value); -} - -/*****************************************************************************/ - -static int stl_cd1400updatereg(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); -} - -/*****************************************************************************/ - -static void stl_cd1400flush(stlport_t *portp, int flag) -{ - -#ifdef STLDEBUG - kprintf("stl_cd1400flush(portp=%x,flag=%x)\n", (int) portp, flag); -#endif - - if (portp == NULL) - return; - - crit_enter(); - - if (flag & FWRITE) { - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO); - stl_cd1400ccrwait(portp); - BRDDISABLE(portp->brdnr); - } - - if (flag & FREAD) { - /* Hmmm */ - } - - crit_exit(); -} - -/*****************************************************************************/ - -static void stl_cd1400ccrwait(stlport_t *portp) -{ - int i; - - for (i = 0; (i < CCR_MAXWAIT); i++) { - if (stl_cd1400getreg(portp, CCR) == 0) - return; - } - - kprintf("stl%d: cd1400 device not responding, 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! - */ - -static __inline void stl_cd1400txisr(stlpanel_t *panelp, int ioaddr) -{ - stlport_t *portp; - unsigned char ioack, srer; - char *head, *tail; - int len, stlen; - -#ifdef STLDEBUG - kprintf("stl_cd1400txisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif - - ioack = inb(ioaddr + EREG_TXACK); - if (((ioack & panelp->ackmask) != 0) || - ((ioack & ACK_TYPMASK) != ACK_TYPTX)) { - kprintf("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->state |= ASY_TXEMPTY; - portp->state &= ~ASY_TXBUSY; - } - 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. - */ - -static __inline void stl_cd1400rxisr(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; - -#ifdef STLDEBUG - kprintf("stl_cd1400rxisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif - - ioack = inb(ioaddr + EREG_RXACK); - if ((ioack & panelp->ackmask) != 0) { - kprintf("STALLION: bad RX interrupt ack value=%x\n", ioack); - return; - } - portp = panelp->ports[(ioack >> 3)]; - tp = &portp->tty; - -/* - * First up, calculate 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_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) & 0xf0)); - stl_cd1400setreg(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), &stl_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 { - kprintf("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. - */ - -static __inline void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr) -{ - stlport_t *portp; - unsigned int ioack; - unsigned char misr; - -#ifdef STLDEBUG - kprintf("stl_cd1400mdmisr(panelp=%x,ioaddr=%x)\n", (int) panelp, ioaddr); -#endif - - ioack = inb(ioaddr + EREG_MDACK); - if (((ioack & panelp->ackmask) != 0) || - ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) { - kprintf("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 service routine for cd1400 EasyIO boards. - */ - -static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase) -{ - unsigned char svrtype; - -#ifdef STLDEBUG - kprintf("stl_cd1400eiointr(panelp=%x,iobase=%x)\n", (int) panelp, - iobase); -#endif - - outb(iobase, SVRR); - svrtype = inb(iobase + EREG_DATA); - if (panelp->nrports > 4) { - outb(iobase, (SVRR + 0x80)); - svrtype |= inb(iobase + EREG_DATA); - } -#ifdef STLDEBUG -kprintf("stl_cd1400eiointr(panelp=%x,iobase=%x): svrr=%x\n", (int) panelp, iobase, svrtype); -#endif - - if (svrtype & SVRR_RX) - stl_cd1400rxisr(panelp, iobase); - else if (svrtype & SVRR_TX) - stl_cd1400txisr(panelp, iobase); - else if (svrtype & SVRR_MDM) - stl_cd1400mdmisr(panelp, iobase); -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for cd1400 panels. - */ - -static void stl_cd1400echintr(stlpanel_t *panelp, unsigned int iobase) -{ - unsigned char svrtype; - -#ifdef STLDEBUG - kprintf("stl_cd1400echintr(panelp=%x,iobase=%x)\n", (int) panelp, - iobase); -#endif - - outb(iobase, SVRR); - svrtype = inb(iobase + EREG_DATA); - outb(iobase, (SVRR + 0x80)); - svrtype |= inb(iobase + EREG_DATA); - if (svrtype & SVRR_RX) - stl_cd1400rxisr(panelp, iobase); - else if (svrtype & SVRR_TX) - stl_cd1400txisr(panelp, iobase); - else if (svrtype & SVRR_MDM) - stl_cd1400mdmisr(panelp, iobase); -} - -/*****************************************************************************/ - -/* - * Set up the cd1400 registers for a port based on the termios port - * settings. - */ - -static int stl_cd1400setport(stlport_t *portp, struct termios *tiosp) -{ - 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; - -#ifdef STLDEBUG - kprintf("stl_cd1400setport(portp=%x,tiosp=%x): brdnr=%d portnr=%d\n", - (int) portp, (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; - } - -/* - * 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 > CD1400_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. - */ -#ifdef STLDEBUG - kprintf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr, - portp->panelnr, portp->brdnr); - kprintf(" cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n", cor1, cor2, - cor3, cor4, cor5); - kprintf(" mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n", - mcor1, mcor2, rtpr, sreron, sreroff); - kprintf(" tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div); - kprintf(" 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 - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - srer = stl_cd1400getreg(portp, SRER); - stl_cd1400setreg(portp, SRER, 0); - ccr += stl_cd1400updatereg(portp, COR1, cor1); - ccr += stl_cd1400updatereg(portp, COR2, cor2); - ccr += stl_cd1400updatereg(portp, COR3, cor3); - if (ccr) { - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, CCR_CORCHANGE); - } - stl_cd1400setreg(portp, COR4, cor4); - stl_cd1400setreg(portp, COR5, cor5); - stl_cd1400setreg(portp, MCOR1, mcor1); - stl_cd1400setreg(portp, MCOR2, mcor2); - if (tiosp->c_ospeed == 0) { - stl_cd1400setreg(portp, MSVR1, 0); - } else { - stl_cd1400setreg(portp, MSVR1, MSVR1_DTR); - stl_cd1400setreg(portp, TCOR, clk); - stl_cd1400setreg(portp, TBPR, div); - stl_cd1400setreg(portp, RCOR, clk); - stl_cd1400setreg(portp, RBPR, div); - } - stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]); - stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]); - stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]); - stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]); - stl_cd1400setreg(portp, RTPR, rtpr); - mcor1 = stl_cd1400getreg(portp, MSVR1); - if (mcor1 & MSVR1_DCD) - portp->sigs |= TIOCM_CD; - else - portp->sigs &= ~TIOCM_CD; - stl_cd1400setreg(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); - crit_exit(); - - 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_cd1400sendflow(stlport_t *portp, int hw, int sw) -{ - -#ifdef STLDEBUG - kprintf("stl_cd1400sendflow(portp=%x,hw=%d,sw=%d)\n", - (int) portp, hw, sw); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - - if (sw >= 0) { - stl_cd1400ccrwait(portp); - if (sw) { - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2); - portp->stats.rxxoff++; - } else { - stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1); - portp->stats.rxxon++; - } - stl_cd1400ccrwait(portp); - } - - if (hw == 0) { - portp->state |= ASY_RTSFLOW; - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) & 0xf0)); - stl_cd1400setreg(portp, MSVR2, 0); - portp->stats.rxrtsoff++; - } else if (hw > 0) { - portp->state &= ~ASY_RTSFLOW; - stl_cd1400setreg(portp, MSVR2, MSVR2_RTS); - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) | FIFO_RTSTHRESHOLD)); - portp->stats.rxrtson++; - } - - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Return the current state of data flow on this port. This is only - * really interresting when determining if data has fully completed - * transmission or not... This is easy for the cd1400, it accurately - * maintains the busy port flag. - */ - -static int stl_cd1400datastate(stlport_t *portp) -{ -#ifdef STLDEBUG - kprintf("stl_cd1400datastate(portp=%x)\n", (int) portp); -#endif - - if (portp == NULL) - return(0); - - return((portp->state & ASY_TXBUSY) ? 1 : 0); -} - -/*****************************************************************************/ - -/* - * Set the state of the DTR and RTS signals. Got to do some extra - * work here to deal hardware flow control. - */ - -static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts) -{ - unsigned char msvr1, msvr2; - -#ifdef STLDEBUG - kprintf("stl_cd1400setsignals(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; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - if (rts >= 0) { - if (portp->tty.t_cflag & CRTS_IFLOW) { - if (rts == 0) { - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) & 0xf0)); - portp->stats.rxrtsoff++; - } else { - stl_cd1400setreg(portp, MCOR1, - (stl_cd1400getreg(portp, MCOR1) | - FIFO_RTSTHRESHOLD)); - portp->stats.rxrtson++; - } - } - stl_cd1400setreg(portp, MSVR2, msvr2); - } - if (dtr >= 0) - stl_cd1400setreg(portp, MSVR1, msvr1); - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Get the state of the signals. - */ - -static int stl_cd1400getsignals(stlport_t *portp) -{ - unsigned char msvr1, msvr2; - int sigs; - -#ifdef STLDEBUG - kprintf("stl_cd1400getsignals(portp=%x)\n", (int) portp); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - msvr1 = stl_cd1400getreg(portp, MSVR1); - msvr2 = stl_cd1400getreg(portp, MSVR2); - BRDDISABLE(portp->brdnr); - crit_exit(); - - sigs = 0; - sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0; - sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0; - sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0; - sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0; -#if 0 - sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0; - sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0; -#else - sigs |= TIOCM_DSR; -#endif - return(sigs); -} - -/*****************************************************************************/ - -/* - * Enable or disable the Transmitter and/or Receiver. - */ - -static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char ccr; - -#ifdef STLDEBUG - kprintf("stl_cd1400enablerxtx(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; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03)); - stl_cd1400ccrwait(portp); - stl_cd1400setreg(portp, CCR, ccr); - stl_cd1400ccrwait(portp); - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Start or stop the Transmitter and/or Receiver. - */ - -static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char sreron, sreroff; - -#ifdef STLDEBUG - kprintf("stl_cd1400startrxtx(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; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - stl_cd1400setreg(portp, SRER, - ((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron)); - BRDDISABLE(portp->brdnr); - if (tx > 0) { - portp->state |= ASY_TXBUSY; - portp->tty.t_state |= TS_BUSY; - } - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Disable all interrupts from this port. - */ - -static void stl_cd1400disableintrs(stlport_t *portp) -{ - -#ifdef STLDEBUG - kprintf("stl_cd1400disableintrs(portp=%x)\n", (int) portp); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - stl_cd1400setreg(portp, SRER, 0); - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -static void stl_cd1400sendbreak(stlport_t *portp, long len) -{ - -#ifdef STLDEBUG - kprintf("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, - (int) len); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - stl_cd1400setreg(portp, COR2, - (stl_cd1400getreg(portp, COR2) | COR2_ETC)); - stl_cd1400setreg(portp, SRER, - ((stl_cd1400getreg(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; - } - crit_exit(); - portp->stats.txbreaks++; -} - -/*****************************************************************************/ - -/* - * 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 void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) -{ -#ifdef STLDEBUG - kprintf("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif - - if ((brdp == NULL) || (panelp == NULL) || - (portp == NULL)) - return; - - portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) || - (portp->portnr < 8)) ? 0 : EREG_BANKSIZE); - portp->uartaddr = (portp->portnr & 0x04) << 5; - portp->pagenr = panelp->pagenr + (portp->portnr >> 3); - - BRDENABLE(portp->brdnr, portp->pagenr); - stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3)); - stl_cd1400setreg(portp, LIVR, (portp->portnr << 3)); - portp->hwid = stl_cd1400getreg(portp, GFRCR); - BRDDISABLE(portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Inbitialize the UARTs in 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_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp) -{ - unsigned int gfrcr; - int chipmask, i, j; - int nrchips, uartaddr, ioaddr; - -#ifdef STLDEBUG - kprintf("stl_cd1400panelinit(brdp=%x,panelp=%x)\n", (int) brdp, - (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((panelp->pagenr + (i >> 1)), brdp->ioctrl); - 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++) { - if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0) - break; - } - if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) { - kprintf("STALLION: cd1400 not responding, " - "board=%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); - } - - - BRDDISABLE(panelp->brdnr); - return(chipmask); -} - -/*****************************************************************************/ -/* SC26198 HARDWARE FUNCTIONS */ -/*****************************************************************************/ - -/* - * These functions get/set/update the registers of the sc26198 UARTs. - * Access to the sc26198 registers is via an address/data io port pair. - * (Maybe should make this inline...) - */ - -static int stl_sc26198getreg(stlport_t *portp, int regnr) -{ - outb((portp->ioaddr + XP_ADDR), (regnr | portp->uartaddr)); - return(inb(portp->ioaddr + XP_DATA)); -} - -static void stl_sc26198setreg(stlport_t *portp, int regnr, int value) -{ - outb((portp->ioaddr + XP_ADDR), (regnr | portp->uartaddr)); - outb((portp->ioaddr + XP_DATA), value); -} - -static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value) -{ - outb((portp->ioaddr + XP_ADDR), (regnr | portp->uartaddr)); - if (inb(portp->ioaddr + XP_DATA) != value) { - outb((portp->ioaddr + XP_DATA), value); - return(1); - } - return(0); -} - -/*****************************************************************************/ - -/* - * Functions to get and set the sc26198 global registers. - */ - -static int stl_sc26198getglobreg(stlport_t *portp, int regnr) -{ - outb((portp->ioaddr + XP_ADDR), regnr); - return(inb(portp->ioaddr + XP_DATA)); -} - -#if 0 -static void stl_sc26198setglobreg(stlport_t *portp, int regnr, int value) -{ - outb((portp->ioaddr + XP_ADDR), regnr); - outb((portp->ioaddr + XP_DATA), value); -} -#endif - -/*****************************************************************************/ - -/* - * Inbitialize the UARTs in 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_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp) -{ - int chipmask, i; - int nrchips, ioaddr; - -#ifdef STLDEBUG - kprintf("stl_sc26198panelinit(brdp=%x,panelp=%x)\n", (int) brdp, - (int) panelp); -#endif - - BRDENABLE(panelp->brdnr, panelp->pagenr); - -/* - * Check that each chip is present and started up OK. - */ - chipmask = 0; - nrchips = (panelp->nrports + 4) / SC26198_PORTS; - if (brdp->brdtype == BRD_ECHPCI) - outb(brdp->ioctrl, panelp->pagenr); - - for (i = 0; (i < nrchips); i++) { - ioaddr = panelp->iobase + (i * 4); - outb((ioaddr + XP_ADDR), SCCR); - outb((ioaddr + XP_DATA), CR_RESETALL); - outb((ioaddr + XP_ADDR), TSTR); - if (inb(ioaddr + XP_DATA) != 0) { - kprintf("STALLION: sc26198 not responding, " - "board=%d panel=%d chip=%d\n", panelp->brdnr, - panelp->panelnr, i); - continue; - } - chipmask |= (0x1 << i); - outb((ioaddr + XP_ADDR), GCCR); - outb((ioaddr + XP_DATA), GCCR_IVRTYPCHANACK); - outb((ioaddr + XP_ADDR), WDTRCR); - outb((ioaddr + XP_DATA), 0xff); - } - - BRDDISABLE(panelp->brdnr); - return(chipmask); -} - -/*****************************************************************************/ - -/* - * Initialize hardware specific port registers. - */ - -static void stl_sc26198portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp) -{ -#ifdef STLDEBUG - kprintf("stl_sc26198portinit(brdp=%x,panelp=%x,portp=%x)\n", - (int) brdp, (int) panelp, (int) portp); -#endif - - if ((brdp == NULL) || (panelp == NULL) || - (portp == NULL)) - return; - - portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4); - portp->uartaddr = (portp->portnr & 0x07) << 4; - portp->pagenr = panelp->pagenr; - portp->hwid = 0x1; - - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS); - BRDDISABLE(portp->brdnr); -} - -/*****************************************************************************/ - -/* - * Set up the sc26198 registers for a port based on the termios port - * settings. - */ - -static int stl_sc26198setport(stlport_t *portp, struct termios *tiosp) -{ - unsigned char mr0, mr1, mr2, clk; - unsigned char imron, imroff, iopr, ipr; - -#ifdef STLDEBUG - kprintf("stl_sc26198setport(portp=%x,tiosp=%x): brdnr=%d portnr=%d\n", - (int) portp, (int) tiosp, portp->brdnr, portp->portnr); -#endif - - mr0 = 0; - mr1 = 0; - mr2 = 0; - clk = 0; - iopr = 0; - imron = 0; - imroff = 0; - -/* - * Set up the RX char ignore mask with those RX error types we - * can ignore. - */ - portp->rxignoremsk = 0; - if (tiosp->c_iflag & IGNPAR) - portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING | - SR_RXOVERRUN); - if (tiosp->c_iflag & IGNBRK) - portp->rxignoremsk |= SR_RXBREAK; - - portp->rxmarkmsk = SR_RXOVERRUN; - if (tiosp->c_iflag & (INPCK | PARMRK)) - portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING); - if (tiosp->c_iflag & BRKINT) - portp->rxmarkmsk |= SR_RXBREAK; - -/* - * Go through the char size, parity and stop bits and set all the - * option registers appropriately. - */ - switch (tiosp->c_cflag & CSIZE) { - case CS5: - mr1 |= MR1_CS5; - break; - case CS6: - mr1 |= MR1_CS6; - break; - case CS7: - mr1 |= MR1_CS7; - break; - default: - mr1 |= MR1_CS8; - break; - } - - if (tiosp->c_cflag & CSTOPB) - mr2 |= MR2_STOP2; - else - mr2 |= MR2_STOP1; - - if (tiosp->c_cflag & PARENB) { - if (tiosp->c_cflag & PARODD) - mr1 |= (MR1_PARENB | MR1_PARODD); - else - mr1 |= (MR1_PARENB | MR1_PAREVEN); - } else { - mr1 |= MR1_PARNONE; - } - - mr1 |= MR1_ERRBLOCK; - -/* - * Set the RX FIFO threshold at 8 chars. This gives a bit of breathing - * space for hardware flow control and the like. This should be set to - * VMIN. - */ - mr2 |= MR2_RXFIFOHALF; - -/* - * Calculate the baud rate timers. For now we will just assume that - * the input and output baud are the same. The sc26198 has a fixed - * baud rate table, so only discrete baud rates possible. - */ - if (tiosp->c_ispeed == 0) - tiosp->c_ispeed = tiosp->c_ospeed; - if ((tiosp->c_ospeed < 0) || (tiosp->c_ospeed > SC26198_MAXBAUD)) - return(EINVAL); - - if (tiosp->c_ospeed > 0) { - for (clk = 0; (clk < SC26198_NRBAUDS); clk++) { - if (tiosp->c_ospeed <= sc26198_baudtable[clk]) - break; - } - } - -/* - * Check what form of modem signaling is required and set it up. - */ - if ((tiosp->c_cflag & CLOCAL) == 0) { - iopr |= IOPR_DCDCOS; - imron |= IR_IOPORT; - } - -/* - * Setup sc26198 enhanced modes if we can. In particular we want to - * handle as much of the flow control as possible automatically. As - * well as saving a few CPU cycles it will also greatly improve flow - * control reliability. - */ - if (tiosp->c_iflag & IXON) { - mr0 |= MR0_SWFTX | MR0_SWFT; - imron |= IR_XONXOFF; - } else { - imroff |= IR_XONXOFF; - } -#if 0 - if (tiosp->c_iflag & IXOFF) - mr0 |= MR0_SWFRX; -#endif - - if (tiosp->c_cflag & CCTS_OFLOW) - mr2 |= MR2_AUTOCTS; - if (tiosp->c_cflag & CRTS_IFLOW) - mr1 |= MR1_AUTORTS; - -/* - * All sc26198 register values calculated so go through and set - * them all up. - */ - -#ifdef STLDEBUG - kprintf("SETPORT: portnr=%d panelnr=%d brdnr=%d\n", portp->portnr, - portp->panelnr, portp->brdnr); - kprintf(" mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk); - kprintf(" iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff); - kprintf(" 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 - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IMR, 0); - stl_sc26198updatereg(portp, MR0, mr0); - stl_sc26198updatereg(portp, MR1, mr1); - stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK); - stl_sc26198updatereg(portp, MR2, mr2); - iopr = (stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr; - if (tiosp->c_ospeed == 0) { - iopr &= ~IPR_DTR; - } else { - iopr |= IPR_DTR; - stl_sc26198setreg(portp, TXCSR, clk); - stl_sc26198setreg(portp, RXCSR, clk); - } - stl_sc26198updatereg(portp, IOPIOR, iopr); - stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]); - stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]); - ipr = stl_sc26198getreg(portp, IPR); - if (ipr & IPR_DCD) - portp->sigs &= ~TIOCM_CD; - else - portp->sigs |= TIOCM_CD; - portp->imr = (portp->imr & ~imroff) | imron; - stl_sc26198setreg(portp, IMR, portp->imr); - 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); - crit_exit(); - - return(0); -} - -/*****************************************************************************/ - -/* - * Set the state of the DTR and RTS signals. - */ - -static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts) -{ - unsigned char iopioron, iopioroff; - -#ifdef STLDEBUG - kprintf("stl_sc26198setsignals(portp=%x,dtr=%d,rts=%d)\n", - (int) portp, dtr, rts); -#endif - - iopioron = 0; - iopioroff = 0; - if (dtr == 0) - iopioroff |= IPR_DTR; - else if (dtr > 0) - iopioron |= IPR_DTR; - if (rts == 0) - iopioroff |= IPR_RTS; - else if (rts > 0) - iopioron |= IPR_RTS; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - if ((rts >= 0) && (portp->tty.t_cflag & CRTS_IFLOW)) { - if (rts == 0) { - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); - portp->stats.rxrtsoff++; - } else { - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS)); - portp->stats.rxrtson++; - } - } - stl_sc26198setreg(portp, IOPIOR, - ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron)); - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Return the state of the signals. - */ - -static int stl_sc26198getsignals(stlport_t *portp) -{ - unsigned char ipr; - int sigs; - -#ifdef STLDEBUG - kprintf("stl_sc26198getsignals(portp=%x)\n", (int) portp); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - ipr = stl_sc26198getreg(portp, IPR); - BRDDISABLE(portp->brdnr); - crit_exit(); - - sigs = TIOCM_DSR; - sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD; - sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS; - sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR; - sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS; - return(sigs); -} - -/*****************************************************************************/ - -/* - * Enable/Disable the Transmitter and/or Receiver. - */ - -static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char ccr; - -#ifdef STLDEBUG - kprintf("stl_sc26198enablerxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif - - ccr = portp->crenable; - if (tx == 0) - ccr &= ~CR_TXENABLE; - else if (tx > 0) - ccr |= CR_TXENABLE; - if (rx == 0) - ccr &= ~CR_RXENABLE; - else if (rx > 0) - ccr |= CR_RXENABLE; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, SCCR, ccr); - BRDDISABLE(portp->brdnr); - portp->crenable = ccr; - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Start/stop the Transmitter and/or Receiver. - */ - -static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx) -{ - unsigned char imr; - -#ifdef STLDEBUG - kprintf("stl_sc26198startrxtx(portp=%x,rx=%d,tx=%d)\n", - (int) portp, rx, tx); -#endif - - imr = portp->imr; - if (tx == 0) - imr &= ~IR_TXRDY; - else if (tx == 1) - imr |= IR_TXRDY; - if (rx == 0) - imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG); - else if (rx > 0) - imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - stl_sc26198setreg(portp, IMR, imr); - BRDDISABLE(portp->brdnr); - portp->imr = imr; - if (tx > 0) { - portp->state |= ASY_TXBUSY; - portp->tty.t_state |= TS_BUSY; - } - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Disable all interrupts from this port. - */ - -static void stl_sc26198disableintrs(stlport_t *portp) -{ - -#ifdef STLDEBUG - kprintf("stl_sc26198disableintrs(portp=%x)\n", (int) portp); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - portp->imr = 0; - stl_sc26198setreg(portp, IMR, 0); - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -static void stl_sc26198sendbreak(stlport_t *portp, long len) -{ - -#ifdef STLDEBUG - kprintf("stl_sc26198sendbreak(portp=%x,len=%d)\n", - (int) portp, (int) len); -#endif - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - if (len == -1) { - stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK); - portp->stats.txbreaks++; - } else { - stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK); - } - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Take flow control actions... - */ - -static void stl_sc26198sendflow(stlport_t *portp, int hw, int sw) -{ - unsigned char mr0; - -#ifdef STLDEBUG - kprintf("stl_sc26198sendflow(portp=%x,hw=%d,sw=%d)\n", - (int) portp, hw, sw); -#endif - - if (portp == NULL) - return; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - - if (sw >= 0) { - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - if (sw > 0) { - stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF); - mr0 &= ~MR0_SWFRX; - portp->stats.rxxoff++; - } else { - stl_sc26198setreg(portp, SCCR, CR_TXSENDXON); - mr0 |= MR0_SWFRX; - portp->stats.rxxon++; - } - stl_sc26198wait(portp); - stl_sc26198setreg(portp, MR0, mr0); - } - - if (hw == 0) { - portp->state |= ASY_RTSFLOW; - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS)); - portp->stats.rxrtsoff++; - } else if (hw > 0) { - portp->state &= ~ASY_RTSFLOW; - stl_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) | MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS)); - portp->stats.rxrtson++; - } - - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * Return the current state of data flow on this port. This is only - * really interresting when determining if data has fully completed - * transmission or not... The sc26198 interrupt scheme cannot - * determine when all data has actually drained, so we need to - * check the port statusy register to be sure. - */ - -static int stl_sc26198datastate(stlport_t *portp) -{ - unsigned char sr; - -#ifdef STLDEBUG - kprintf("stl_sc26198datastate(portp=%x)\n", (int) portp); -#endif - - if (portp == NULL) - return(0); - if (portp->state & ASY_TXBUSY) - return(1); - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - sr = stl_sc26198getreg(portp, SR); - BRDDISABLE(portp->brdnr); - crit_exit(); - - return((sr & SR_TXEMPTY) ? 0 : 1); -} - -/*****************************************************************************/ - -static void stl_sc26198flush(stlport_t *portp, int flag) -{ - -#ifdef STLDEBUG - kprintf("stl_sc26198flush(portp=%x,flag=%x)\n", (int) portp, flag); -#endif - - if (portp == NULL) - return; - - crit_enter(); - BRDENABLE(portp->brdnr, portp->pagenr); - if (flag & FWRITE) { - stl_sc26198setreg(portp, SCCR, CR_TXRESET); - stl_sc26198setreg(portp, SCCR, portp->crenable); - } - if (flag & FREAD) { - while (stl_sc26198getreg(portp, SR) & SR_RXRDY) - stl_sc26198getreg(portp, RXFIFO); - } - BRDDISABLE(portp->brdnr); - crit_exit(); -} - -/*****************************************************************************/ - -/* - * If we are TX flow controlled and in IXANY mode then we may - * need to unflow control here. We gotta do this because of the - * automatic flow control modes of the sc26198 - which downs't - * support any concept of an IXANY mode. - */ - -static void stl_sc26198txunflow(stlport_t *portp) -{ - unsigned char mr0; - - mr0 = stl_sc26198getreg(portp, MR0); - stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX)); - stl_sc26198setreg(portp, SCCR, CR_HOSTXON); - stl_sc26198setreg(portp, MR0, mr0); - portp->state &= ~ASY_TXFLOWED; -} - -/*****************************************************************************/ - -/* - * Delay for a small amount of time, to give the sc26198 a chance - * to process a command... - */ - -static void stl_sc26198wait(stlport_t *portp) -{ - int i; - -#ifdef STLDEBUG - kprintf("stl_sc26198wait(portp=%x)\n", (int) portp); -#endif - - if (portp == NULL) - return; - - for (i = 0; (i < 20); i++) - stl_sc26198getglobreg(portp, TSTR); -} - -/*****************************************************************************/ - -/* - * 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 sc26198 FIFO. - */ - -static __inline void stl_sc26198txisr(stlport_t *portp) -{ - unsigned int ioaddr; - unsigned char mr0; - char *head, *tail; - int len, stlen; - -#ifdef STLDEBUG - kprintf("stl_sc26198txisr(portp=%x)\n", (int) portp); -#endif - - ioaddr = portp->ioaddr; - - 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 + XP_ADDR), (MR0 | portp->uartaddr)); - mr0 = inb(ioaddr + XP_DATA); - if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) { - portp->imr &= ~IR_TXRDY; - outb((ioaddr + XP_ADDR), (IMR | portp->uartaddr)); - outb((ioaddr + XP_DATA), portp->imr); - portp->state |= ASY_TXEMPTY; - portp->state &= ~ASY_TXBUSY; - } else { - mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY); - outb((ioaddr + XP_DATA), mr0); - } - } else { - len = MIN(len, SC26198_TXFIFOSIZE); - portp->stats.txtotal += len; - stlen = MIN(len, (portp->tx.endbuf - tail)); - outb((ioaddr + XP_ADDR), GTXFIFO); - outsb((ioaddr + XP_DATA), tail, stlen); - len -= stlen; - tail += stlen; - if (tail >= portp->tx.endbuf) - tail = portp->tx.buf; - if (len > 0) { - outsb((ioaddr + XP_DATA), tail, len); - tail += len; - } - portp->tx.tail = tail; - } -} - -/*****************************************************************************/ - -/* - * 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 byte to 0. - * If a bad RX char then process as required. This routine needs to be - * fast! - */ - -static __inline void stl_sc26198rxisr(stlport_t *portp, unsigned int iack) -{ -#ifdef STLDEBUG - kprintf("stl_sc26198rxisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif - - if ((iack & IVR_TYPEMASK) == IVR_RXDATA) - stl_sc26198rxgoodchars(portp); - else - stl_sc26198rxbadchars(portp); - -/* - * If we are TX flow controlled and in IXANY mode then we may need - * to unflow control here. We gotta do this because of the automatic - * flow control modes of the sc26198. - */ - if ((portp->state & ASY_TXFLOWED) && (portp->tty.t_iflag & IXANY)) - stl_sc26198txunflow(portp); -} - -/*****************************************************************************/ - -/* - * Process the good received characters from RX FIFO. - */ - -static void stl_sc26198rxgoodchars(stlport_t *portp) -{ - unsigned int ioaddr, len, buflen, stlen; - char *head, *tail; - -#ifdef STLDEBUG - kprintf("stl_sc26198rxgoodchars(port=%x)\n", (int) portp); -#endif - - ioaddr = portp->ioaddr; - -/* - * First up, calculate 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_sc26198setreg(portp, MR1, - (stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS)); - stl_sc26198setreg(portp, IOPIOR, - (stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS)); - 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. - */ - outb((ioaddr + XP_ADDR), GIBCR); - len = inb(ioaddr + XP_DATA) + 1; - if (buflen == 0) { - outb((ioaddr + XP_ADDR), GRXFIFO); - insb((ioaddr + XP_DATA), &stl_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 + XP_ADDR), GRXFIFO); - insb((ioaddr + XP_DATA), head, stlen); - head += stlen; - if (head >= portp->rx.endbuf) { - head = portp->rx.buf; - len -= stlen; - insb((ioaddr + XP_DATA), head, len); - head += len; - } - } - } - - portp->rx.head = head; - portp->state |= ASY_RXDATA; - stl_dotimeout(); -} - -/*****************************************************************************/ - -/* - * Process all characters in the RX FIFO of the UART. Check all char - * status bytes as well, and process as required. We need to check - * all bytes in the FIFO, in case some more enter the FIFO while we - * are here. To get the exact character error type we need to switch - * into CHAR error mode (that is why we need to make sure we empty - * the FIFO). - */ - -static void stl_sc26198rxbadchars(stlport_t *portp) -{ - unsigned char mr1; - unsigned int status; - char *head, *tail; - char ch; - int len; - -/* - * First up, calculate 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; - len = (head >= tail) ? (STL_RXBUFSIZE - (head - tail) - 1) : - (tail - head - 1); - -/* - * To get the precise error type for each character we must switch - * back into CHAR error mode. - */ - mr1 = stl_sc26198getreg(portp, MR1); - stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK)); - - while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) { - stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR); - ch = stl_sc26198getreg(portp, RXFIFO); - - if (status & SR_RXBREAK) - portp->stats.rxbreaks++; - if (status & SR_RXFRAMING) - portp->stats.rxframing++; - if (status & SR_RXPARITY) - portp->stats.rxparity++; - if (status & SR_RXOVERRUN) - portp->stats.rxoverrun++; - if ((portp->rxignoremsk & status) == 0) { - if ((portp->tty.t_state & TS_CAN_BYPASS_L_RINT) && - ((status & SR_RXFRAMING) || - ((status & SR_RXPARITY) && - (portp->tty.t_iflag & INPCK)))) - ch = 0; - if ((portp->rxmarkmsk & status) == 0) - status = 0; - if (len > 0) { - *(head + STL_RXBUFSIZE) = status; - *head++ = ch; - if (head >= portp->rx.endbuf) - head = portp->rx.buf; - len--; - } - } - } - -/* - * To get correct interrupt class we must switch back into BLOCK - * error mode. - */ - stl_sc26198setreg(portp, MR1, mr1); - - portp->rx.head = head; - portp->state |= ASY_RXDATA; - stl_dotimeout(); -} - -/*****************************************************************************/ - -/* - * Other interrupt handler. This includes modem signals, flow - * control actions, etc. - */ - -static void stl_sc26198otherisr(stlport_t *portp, unsigned int iack) -{ - unsigned char cir, ipr, xisr; - -#ifdef STLDEBUG - kprintf("stl_sc26198otherisr(portp=%x,iack=%x)\n", (int) portp, iack); -#endif - - cir = stl_sc26198getglobreg(portp, CIR); - - switch (cir & CIR_SUBTYPEMASK) { - case CIR_SUBCOS: - ipr = stl_sc26198getreg(portp, IPR); - if (ipr & IPR_DCDCHANGE) { - portp->state |= ASY_DCDCHANGE; - portp->stats.modem++; - stl_dotimeout(); - } - break; - case CIR_SUBXONXOFF: - xisr = stl_sc26198getreg(portp, XISR); - if (xisr & XISR_RXXONGOT) { - portp->state |= ASY_TXFLOWED; - portp->stats.txxoff++; - } - if (xisr & XISR_RXXOFFGOT) { - portp->state &= ~ASY_TXFLOWED; - portp->stats.txxon++; - } - break; - case CIR_SUBBREAK: - stl_sc26198setreg(portp, SCCR, CR_BREAKRESET); - stl_sc26198rxbadchars(portp); - break; - default: - break; - } -} - -/*****************************************************************************/ - -/* - * Interrupt service routine for sc26198 panels. - */ - -static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase) -{ - stlport_t *portp; - unsigned int iack; - -/* - * Work around bug in sc26198 chip... Cannot have A6 address - * line of UART high, else iack will be returned as 0. - */ - outb((iobase + 1), 0); - - iack = inb(iobase + XP_IACK); -#ifdef STLDEBUG - kprintf("stl_sc26198intr(panelp=%p,iobase=%x): iack=%x\n", panelp, iobase, iack); -#endif - portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)]; - - if (iack & IVR_RXDATA) - stl_sc26198rxisr(portp, iack); - else if (iack & IVR_TXDATA) - stl_sc26198txisr(portp); - else - stl_sc26198otherisr(portp, iack); -} - -/*****************************************************************************/ diff --git a/sys/platform/pc64/include/cdk.h b/sys/platform/pc64/include/cdk.h deleted file mode 100644 index 31d482449c..0000000000 --- a/sys/platform/pc64/include/cdk.h +++ /dev/null @@ -1,501 +0,0 @@ -/*****************************************************************************/ - -/* - * cdk.h -- CDK interface definitions. - * - * Copyright (c) 1994-1998 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: src/sys/i386/include/cdk.h,v 1.5.2.1 2001/08/30 12:29:57 murray Exp $ - * $DragonFly: src/sys/platform/pc32/include/cdk.h,v 1.3 2003/06/28 04:16:03 dillon Exp $ - */ - -#ifndef _CDK_H_ -#define _CDK_H_ - -#include - -#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 P_RXIMIN 0x10000 -#define P_RXITIME 0x20000 -#define P_RXTHOLD 0x40000 - -/* - * 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/platform/pc64/include/comstats.h b/sys/platform/pc64/include/comstats.h deleted file mode 100644 index c2be5bcc81..0000000000 --- a/sys/platform/pc64/include/comstats.h +++ /dev/null @@ -1,124 +0,0 @@ -/*****************************************************************************/ - -/* - * comstats.h -- Serial Port Stats. - * - * 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: src/sys/i386/include/comstats.h,v 1.5 1999/08/28 00:44:09 peter Exp $ - * $DragonFly: src/sys/platform/pc32/include/comstats.h,v 1.4 2008/05/18 03:02:53 pavalos Exp $ - */ - -#ifndef _COMSTATS_H_ -#define _COMSTATS_H_ - -#include - -/* - * Serial port stats structure. The structure itself is UART - * independent, but some fields may be UART/driver specific (for - * example state). - */ - -typedef struct { - unsigned long brd; - unsigned long panel; - unsigned long port; - unsigned long hwid; - unsigned long type; - unsigned long txtotal; - unsigned long rxtotal; - unsigned long txbuffered; - unsigned long rxbuffered; - unsigned long rxoverrun; - unsigned long rxparity; - unsigned long rxframing; - unsigned long rxlost; - unsigned long txbreaks; - unsigned long rxbreaks; - unsigned long txxon; - unsigned long txxoff; - unsigned long rxxon; - unsigned long rxxoff; - unsigned long txctson; - unsigned long txctsoff; - unsigned long rxrtson; - unsigned long rxrtsoff; - unsigned long modem; - unsigned long state; - unsigned long flags; - unsigned long ttystate; - unsigned long cflags; - unsigned long iflags; - unsigned long oflags; - unsigned long lflags; - unsigned long signals; -} comstats_t; - - -/* - * Board stats structure. Returns useful info about the board. - */ - -#define COM_MAXPANELS 8 - -typedef struct { - unsigned long panel; - unsigned long type; - unsigned long hwid; - unsigned long nrports; -} companel_t; - -typedef struct { - unsigned long brd; - unsigned long type; - unsigned long hwid; - unsigned long state; - unsigned long ioaddr; - unsigned long ioaddr2; - unsigned long memaddr; - unsigned long irq; - unsigned long nrpanels; - unsigned long nrports; - companel_t panels[COM_MAXPANELS]; -} combrd_t; - - -/* - * Define the ioctl operations for stats stuff. - */ -#define COM_GETPORTSTATS _IOWR('c', 30, comstats_t) -#define COM_CLRPORTSTATS _IOWR('c', 31, comstats_t) -#define COM_GETBRDSTATS _IOWR('c', 32, combrd_t) - -/*****************************************************************************/ - -#endif diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 7119748675..703a3b3e8e 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -162,8 +162,7 @@ SUBDIR+=btxld \ .endif .if ${MACHINE_ARCH} == "i386" -SUBDIR+=kgzip \ - stlstats +SUBDIR+=kgzip .endif .ifdef BOOT0CFG_SUPPORT diff --git a/usr.sbin/stlstats/Makefile b/usr.sbin/stlstats/Makefile deleted file mode 100644 index 725ad541d1..0000000000 --- a/usr.sbin/stlstats/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# $FreeBSD: src/usr.sbin/stallion/stlstats/Makefile,v 1.6.2.2 2001/04/25 12:10:59 ru Exp $ - -PROG= stlstats -MAN= stlstats.8 -MANSUBDIR=/i386 -WARNS?= 2 - -DPADD= ${LIBNCURSES} -LDADD= -lncurses - -.include diff --git a/usr.sbin/stlstats/stlstats.8 b/usr.sbin/stlstats/stlstats.8 deleted file mode 100644 index 103ff154a1..0000000000 --- a/usr.sbin/stlstats/stlstats.8 +++ /dev/null @@ -1,142 +0,0 @@ -.\" Copyright (c) 1996-1998 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: src/usr.sbin/stallion/stlstats/stlstats.8,v 1.5.2.6 2003/03/11 22:31:33 trhodes Exp $ -.\" -.Dd January 8, 1998 -.Dt STLSTATS 8 i386 -.Os -.Sh NAME -.Nm stlstats -.Nd "Stallion Technologies multiport serial statistics display" -.Sh SYNOPSIS -.Nm -.Op Fl hVi -.Op Fl c Ar control-device -.Op Fl b Ar board-number -.Op Fl p Ar port-number -.Op Fl d Ar port-device -.Sh DESCRIPTION -The -.Nm -utility -is used to display statistical information about the ports on Stallion -Technologies multiport serial boards. -.Pp -The -.Nm -utility normally runs as a full screen menu driven application. -A help line is displayed at the bottom of each screen with the valid -input keys for this screen. -.Pp -Generally the digit keys ('0' through '9') specify the number of the -device to display statistics for. -Where digits alone are not enough to access all possible devices -(for example on 16 port panels) then the first letters of the alphabet -are used to access the remaining devices. -The letters 'a' through 'f' are used to access devices 10 through 15. -.Pp -The 'q' key is always used to move back to the previous level screen. -The escape key can also be used to move back to the previous screen. -.Pp -The first screen is a display of all ports on panel 0 of board 0. -Values displayed on this screen are a summary of the information for -each port. The statistics displayed are: driver and TTY state flags, -termios flags (cflags, iflags, oflags, lflags), RS-232 signal values -(as per TIOCM signal defines), total transmit and receive character -counts. -.Pp -From this screen you can look at summary information -about each panel and board installed in the system. -Each board is accessed by the digit keys ('0' through '7'), -while panels of each board can be cycled through using the 'n' key. -.Pp -The per port screen displays some detailed information about a -particular port. -This is accessed from the board screen using the 'p' key. -The first port displayed will be port 0. -To display other ports use the digit and alphabetic keys -('0' through '9' and 'a' through 'f'). -This screen displays: driver and TTY state flags, hardware ID, -termios flags (cflags, iflags, oflags, lflags), -total transmitted and received character counts, -current transmit and receive characters buffered, -receiver error counts (overruns, parity, framing, lost), -software flow control characters transmitted and received, -hardware flow control actions taken, -count of transmitted and received breaks, -modem signal transitions and -current RS-232 signal states. -.Pp -The options are: -.Bl -tag -width indent -.It Fl h -Output usage information. -.It Fl V -Output version information. -.It Fl i -Output only the board type information. -This output is useful for scripts or other programs that need to know -a little bit about the board (for example an automated download script). -The -.Nm -utility will not enter full screen interactive mode. -.It Fl c Ar control-device -Specify the board control device through which to gather port statistics. -The default is -.Pa /dev/staliomem0 . -.It Fl b Ar board-number -Specify the board number to display first. -The default is to display board 0. -.It Fl p Ar port-number -Specify the port number to display first. -The -.Nm -utility -will go straight into the port display screen (bypassing board display) -when this option is used. -.It Fl d Ar port-device -Specify the port special device file (the -.Pa /dev/ttyXXX -file) to -display first. -The board screen is bypassed and the port statistics screen is shown -immediately on start up. -.El -.Sh FILES -.Bl -tag -width /dev/staliomem0 -.It Pa /dev/staliomem0 -driver control device used for statistics collection -.El -.Sh SEE ALSO -.Xr stl 4 -.Sh HISTORY -This program was originally developed by -.An Greg Ungerer Aq Mt gerg@stallion.com . diff --git a/usr.sbin/stlstats/stlstats.c b/usr.sbin/stlstats/stlstats.c deleted file mode 100644 index 1489f661be..0000000000 --- a/usr.sbin/stlstats/stlstats.c +++ /dev/null @@ -1,590 +0,0 @@ -/*****************************************************************************/ - -/* - * stlstats.c -- stallion intelligent multiport stats display. - * - * Copyright (c) 1994-1998 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: src/usr.sbin/stallion/stlstats/stlstats.c,v 1.9.2.1 2001/08/30 12:29:58 murray Exp $ - * $DragonFly: src/usr.sbin/stallion/stlstats/stlstats.c,v 1.4 2006/08/03 16:40:49 swildner Exp $ - */ - -/*****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/*****************************************************************************/ - -char *version = "2.0.0"; -char *defdevice = "/dev/staliomem0"; - -char *ctrldevice; -int ctrlfd; -int displaybrdnr = 0; -int displaypanelnr = 0; -int displayportnr = 0; -int displayportbank = 0; - -#define MAXBRDS 8 -#define MAXPORTS 32 - -combrd_t brdstats; -comstats_t stats[MAXPORTS]; - -char *line = " "; - -/*****************************************************************************/ - -/* - * Declare internal function prototypes here. - */ -static void usage(void); -void useportdevice(char *devname); -void localexit(int nr); -void menuport(); -void displayport(); -void menuallports(); -void displayallports(); -void getallstats(); -void getbrdstats(); -void clearportstats(); -void clearallstats(); - -/*****************************************************************************/ - -static void -usage(void) -{ - fprintf(stderr, "%s\n%s\n", - "usage: stlstats [-hVi] [-c control-device] [-b board-number]", - " [-p port-number] [-d port-device]"); - exit(0); -} - -/*****************************************************************************/ - -void -useportdevice(char *devname) -{ - struct stat statinfo; - int portnr, portcnt; - int i; - - if (stat(devname, &statinfo) < 0) - errx(1, "port device %s does not exist", devname); - if ((statinfo.st_mode & S_IFMT) != S_IFCHR) - errx(1, "port device %s is not a char device", devname); - - displaybrdnr = (statinfo.st_rdev & 0x00700000) >> 20; - portnr = (statinfo.st_rdev & 0x1f) | - ((statinfo.st_rdev & 0x00010000) >> 11); - getbrdstats(); - if (brdstats.ioaddr == 0) - errx(1, "device %s does not exist", devname); - - for (portcnt = 0, i = 0; (i < brdstats.nrpanels); i++) { - if ((portnr >= portcnt) && - (portnr < (portcnt + brdstats.panels[i].nrports))) - break; - portcnt += brdstats.panels[i].nrports; - } - if (i >= brdstats.nrpanels) - errx(1, "device %s does not exist", devname); - displaypanelnr = i; - displayportnr = portnr - portcnt; - if (displayportnr >= 16) - displayportbank = 16; -} - -/*****************************************************************************/ - -/* - * Get the board stats for the current display board. - */ - -void -getbrdstats(void) -{ - brdstats.brd = displaybrdnr; - if (ioctl(ctrlfd, COM_GETBRDSTATS, &brdstats) < 0) - memset((combrd_t *) &brdstats, 0, sizeof(combrd_t)); -} - -/*****************************************************************************/ - -/* - * Zero out stats for the current display port. - */ - -void -clearportstats(void) -{ - stats[displayportnr].brd = displaybrdnr; - stats[displayportnr].panel = displaypanelnr; - stats[displayportnr].port = displayportnr; - ioctl(ctrlfd, COM_CLRPORTSTATS, &stats[displayportnr]); -} - -/*****************************************************************************/ - -/* - * Zero out all stats for all ports on all boards. - */ - -void -clearallstats(void) -{ - int brdnr, panelnr, portnr; - - for (brdnr = 0; (brdnr < MAXBRDS); brdnr++) { - for (panelnr = 0; (panelnr < COM_MAXPANELS); panelnr++) { - for (portnr = 0; (portnr < MAXPORTS); portnr++) { - stats[0].brd = brdnr; - stats[0].panel = panelnr; - stats[0].port = portnr; - ioctl(ctrlfd, COM_CLRPORTSTATS, &stats[0]); - } - } - } -} - -/*****************************************************************************/ - -/* - * Get the stats for the current display board/panel. - */ - -void -getallstats(void) -{ - int i; - - for (i = 0; (i < brdstats.panels[displaypanelnr].nrports); i++) { - stats[i].brd = displaybrdnr; - stats[i].panel = displaypanelnr; - stats[i].port = i; - if (ioctl(ctrlfd, COM_GETPORTSTATS, &stats[i]) < 0) { - warn("ioctl(COM_GETPORTSTATS) failed"); - localexit(1); - } - } -} - -/*****************************************************************************/ - -/* - * Display the per ports stats screen. - */ - -void -displayport(void) -{ - mvprintw(0, 0, "STALLION SERIAL PORT STATISTICS"); - mvprintw(2, 0, - "Board=%d Type=%d HwID=%02x State=%06x TotalPorts=%d", - displaybrdnr, brdstats.type, brdstats.hwid, brdstats.state, - brdstats.nrports); - mvprintw(3, 0, "Panel=%d HwID=%02x Ports=%d", displaypanelnr, - brdstats.panels[displaypanelnr].hwid, - brdstats.panels[displaypanelnr].nrports); - - attron(A_REVERSE); - mvprintw(5, 0, line); - mvprintw(5, 0, "Port=%d ", displayportnr); - attroff(A_REVERSE); - - mvprintw(7, 0, "STATE: State=%08x", stats[displayportnr].state); - mvprintw(7, 29, "Tty=%08x", stats[displayportnr].ttystate); - mvprintw(7, 47, "Flags=%08x", stats[displayportnr].flags); - mvprintw(7, 65, "HwID=%02x", stats[displayportnr].hwid); - - mvprintw(8, 0, "CONFIG: Cflag=%08x", stats[displayportnr].cflags); - mvprintw(8, 29, "Iflag=%08x", stats[displayportnr].iflags); - mvprintw(8, 47, "Oflag=%08x", stats[displayportnr].oflags); - mvprintw(8, 65, "Lflag=%08x", stats[displayportnr].lflags); - - mvprintw(10, 0, "TX DATA: Total=%d", stats[displayportnr].txtotal); - mvprintw(10, 29, "Buffered=%d ", stats[displayportnr].txbuffered); - mvprintw(11, 0, "RX DATA: Total=%d", stats[displayportnr].rxtotal); - mvprintw(11, 29, "Buffered=%d ", stats[displayportnr].rxbuffered); - mvprintw(12, 0, "RX ERRORS: Parity=%d", stats[displayportnr].rxparity); - mvprintw(12, 29, "Framing=%d", stats[displayportnr].rxframing); - mvprintw(12, 47, "Overrun=%d", stats[displayportnr].rxoverrun); - mvprintw(12, 65, "Lost=%d", stats[displayportnr].rxlost); - - mvprintw(14, 0, "FLOW TX: Xoff=%d", stats[displayportnr].txxoff); - mvprintw(14, 29, "Xon=%d", stats[displayportnr].txxon); -#if 0 - mvprintw(14, 47, "CTSoff=%d", stats[displayportnr].txctsoff); - mvprintw(14, 65, "CTSon=%d", stats[displayportnr].txctson); -#endif - mvprintw(15, 0, "FLOW RX: Xoff=%d", stats[displayportnr].rxxoff); - mvprintw(15, 29, "Xon=%d", stats[displayportnr].rxxon); - mvprintw(15, 47, "RTSoff=%d", stats[displayportnr].rxrtsoff); - mvprintw(15, 65, "RTSon=%d", stats[displayportnr].rxrtson); - - mvprintw(17, 0, "OTHER: TXbreaks=%d", - stats[displayportnr].txbreaks); - mvprintw(17, 29, "RXbreaks=%d", stats[displayportnr].rxbreaks); - mvprintw(17, 47, "Modem=%d", stats[displayportnr].modem); - - mvprintw(19, 0, "SIGNALS: DCD=%d DTR=%d CTS=%d RTS=%d " - "DSR=%d RI=%d", - (stats[displayportnr].signals & TIOCM_CD) ? 1 : 0, - (stats[displayportnr].signals & TIOCM_DTR) ? 1 : 0, - (stats[displayportnr].signals & TIOCM_CTS) ? 1 : 0, - (stats[displayportnr].signals & TIOCM_RTS) ? 1 : 0, - (stats[displayportnr].signals & TIOCM_DSR) ? 1 : 0, - (stats[displayportnr].signals & TIOCM_RI) ? 1 : 0); - - attron(A_REVERSE); - mvprintw(22, 0, line); - attroff(A_REVERSE); - - mvprintw(24, 19, "(q=Quit,0123456789abcdef=Port,Z=ZeroStats)"); - refresh(); -} - -/*****************************************************************************/ - -/* - * Continuously update and display the per ports stats screen. - * Also checks for keyboard input, and processes it as appropriate. - */ - -void -menuport(void) -{ - int ch, done; - - clear(); - done = 0; - - while ((ch = getch()) != 27) { - switch (ch) { - case ERR: - break; - case ' ': - refresh(); - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - ch = (ch - 'a' + '0' + 10); - /* fall thru */ - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - ch -= '0'; - if (ch >= brdstats.panels[displaypanelnr].nrports) { - beep(); - } else { - displayportnr = displayportbank + ch; - clear(); - } - break; - case 'Z': - clearportstats(); - clear(); - break; - case 'q': - done = 1; - break; - default: - beep(); - break; - } - - if (done) - break; - - getallstats(); - displayport(); - } -} - -/*****************************************************************************/ - -/* - * Display the all ports stats screen. - */ - -void -displayallports(void) -{ - int i, nrports, portnr; - - nrports = brdstats.panels[displaypanelnr].nrports; - - mvprintw(0, 0, "STALLION SERIAL PORT STATISTICS"); - mvprintw(2, 0, "Board=%d Type=%d HwID=%02x State=%06x TotalPorts=%d", - displaybrdnr, brdstats.type, brdstats.hwid, brdstats.state, - brdstats.nrports); - mvprintw(3, 0, "Panel=%d HwID=%02x Ports=%d", displaypanelnr, - brdstats.panels[displaypanelnr].hwid, nrports); - - attron(A_REVERSE); - mvprintw(5, 0, "Port State Tty Flags Cflag Iflag Oflag Lflag " - "Sigs TX Total RX Total "); - attroff(A_REVERSE); - - if (nrports > 0) { - if (nrports > 16) - nrports = 16; - portnr = displayportbank; - for (i = 0; (i < nrports); i++, portnr++) { - mvprintw((6 + i), 1, "%2d", portnr); - mvprintw((6 + i), 5, "%06x", stats[portnr].state); - mvprintw((6 + i), 12, "%06x", stats[portnr].ttystate); - mvprintw((6 + i), 19, "%08x", stats[portnr].flags); - mvprintw((6 + i), 28, "%05x", stats[portnr].cflags); - mvprintw((6 + i), 34, "%05x", stats[portnr].iflags); - mvprintw((6 + i), 40, "%05x", stats[portnr].oflags); - mvprintw((6 + i), 46, "%05x", stats[portnr].lflags); - mvprintw((6 + i), 52, "%04x", stats[portnr].signals); - mvprintw((6 + i), 58, "%10d", stats[portnr].txtotal); - mvprintw((6 + i), 69, "%10d", stats[portnr].rxtotal); - } - } else { - mvprintw(12, 32, "NO BOARD %d FOUND", displaybrdnr); - i = 16; - } - - attron(A_REVERSE); - mvprintw((6 + i), 0, line); - attroff(A_REVERSE); - - mvprintw(24, 14, - "(q=Quit,01234567=Board,n=Panels,p=Ports,Z=ZeroStats)"); - refresh(); -} - -/*****************************************************************************/ - -/* - * Continuously update and display the all ports stats screen. - * Also checks for keyboard input, and processes it as appropriate. - */ - -void -menuallports(void) -{ - int ch, done; - - clear(); - getbrdstats(); - - done = 0; - while ((ch = getch()) != 27) { - switch (ch) { - case ERR: - break; - case ' ': - refresh(); - break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - displaybrdnr = ch - '0'; - displaypanelnr = 0; - getbrdstats(); - if (brdstats.state == 0) - beep(); - clear(); - break; - case 'n': - if (brdstats.panels[displaypanelnr].nrports > 16) { - if (displayportbank == 0) { - displayportbank = 16; - clear(); - break; - } - } - displayportbank = 0; - displaypanelnr++; - if (displaypanelnr >= brdstats.nrpanels) - displaypanelnr = 0; - clear(); - break; - case 'p': - if (brdstats.panels[displaypanelnr].nrports > 0) { - displayportnr = displayportbank; - menuport(); - clear(); - } else { - beep(); - } - break; - case 'Z': - clearallstats(); - clear(); - break; - case 'q': - done = 1; - break; - default: - beep(); - break; - } - - if (done) - break; - - getallstats(); - displayallports(); - } -} - -/*****************************************************************************/ - -/* - * A local exit routine - shuts down curses before exiting. - */ - -void -localexit(int nr) -{ - refresh(); - endwin(); - exit(nr); -} - -/*****************************************************************************/ - -int -main(int argc, char *argv[]) -{ - struct stat statinfo; - int c, useport; - char *portdev; - - ctrldevice = defdevice; - useport = 0; - - while ((c = getopt(argc, argv, "hvVb:p:d:c:")) != -1) { - switch (c) { - case 'V': - printf("stlstats version %s\n", version); - exit(0); - break; - case 'h': - usage(); - break; - case 'b': - displaybrdnr = atoi(optarg); - break; - case 'p': - displaypanelnr = atoi(optarg); - break; - case 'd': - useport++; - portdev = optarg; - break; - case 'c': - ctrldevice = optarg; - break; - case '?': - default: - usage(); - break; - } - } - -/* - * Check that the control device exits and is a character device. - */ - if (stat(ctrldevice, &statinfo) < 0) - errx(1, "control device %s does not exist", ctrldevice); - if ((statinfo.st_mode & S_IFMT) != S_IFCHR) - errx(1, "control device %s is not a char device", ctrldevice); - if ((ctrlfd = open(ctrldevice, O_RDWR)) < 0) - errx(1, "open of %s failed", ctrldevice); - -/* - * Validate the panel number supplied by user. We do this now since we - * need to have parsed the entire command line first. - */ - getbrdstats(); - if (displaypanelnr >= brdstats.nrpanels) - displaypanelnr = 0; - - if (useport) - useportdevice(portdev); - -/* - * Everything is now ready, lets go! - */ - initscr(); - cbreak(); - halfdelay(5); - noecho(); - clear(); - if (useport) { - menuport(); - clear(); - } - menuallports(); - refresh(); - endwin(); - - close(ctrlfd); - printf("\n"); - exit(0); -} - -/*****************************************************************************/