Index: share/man/man4/Makefile =================================================================== --- share/man/man4/Makefile +++ share/man/man4/Makefile @@ -121,7 +121,6 @@ cxgb.4 \ cxgbe.4 \ cxgbev.4 \ - cy.4 \ cyapa.4 \ da.4 \ dc.4 \ @@ -434,7 +433,6 @@ ${_qlnxe.4} \ ral.4 \ random.4 \ - rc.4 \ rctl.4 \ re.4 \ rgephy.4 \ @@ -442,7 +440,6 @@ rl.4 \ rndtest.4 \ route.4 \ - rp.4 \ rtwn.4 \ rtwnfw.4 \ rtwn_pci.4 \ Index: share/man/man4/cy.4 =================================================================== --- share/man/man4/cy.4 +++ /dev/null @@ -1,257 +0,0 @@ -.\" Copyright (c) 1990, 1991 The Regents of the University of California. -.\" All rights reserved. -.\" -.\" This code is derived from software contributed to Berkeley by -.\" the Systems Programming Group of the University of Utah Computer -.\" Science Department. -.\" 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 University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. -.\" -.\" from: @(#)dca.4 5.2 (Berkeley) 3/27/91 -.\" from: com.4,v 1.1 1993/08/06 11:19:07 cgd Exp -.\" from: sio.4,v 1.16 1995/06/26 06:05:30 bde Exp $ -.\" $FreeBSD$ -.\" -.Dd May 24, 2004 -.Dt CY 4 -.Os -.Sh NAME -.Nm cy -.Nd Cyclades Cyclom-Y serial driver -.Sh SYNOPSIS -For one ISA card: -.Bd -ragged -offset indent -compact -.Cd "device cy" -.Pp -In -.Pa /boot/device.hints : -.Cd hint.cy.0.at="isa" -.Cd hint.cy.0.irq="10" -.Cd hint.cy.0.maddr="0xd4000" -.Cd hint.cy.0.msize="0x2000" -.Ed -.Pp -For two ISA cards: -.Bd -ragged -offset indent -compact -.Cd "device cy" -.Pp -In -.Pa /boot/device.hints : -.Cd hint.cy.0.at="isa" -.Cd hint.cy.0.irq="10" -.Cd hint.cy.0.maddr="0xd4000" -.Cd hint.cy.0.msize="0x2000" -.Cd hint.cy.1.at="isa" -.Cd hint.cy.1.irq="11" -.Cd hint.cy.1.maddr="0xd6000" -.Cd hint.cy.1.msize="0x2000" -.Ed -.Pp -For PCI cards: -.Bd -ragged -offset indent -compact -.Cd "device cy" -.Cd "options CY_PCI_FASTINTR" -.Pp -No lines are required in -.Pa /boot/device.hints -for PCI cards. -.Ed -.Pp -Minor numbering: -.Bd -literal -offset indent -compact -0b\fIMMMMMMMMMMMMMMMMxxxxxxxxOLIMMMMM\fR - call\fBO\fRut - \fBL\fRock - \fBI\fRnitial - \fBMMMMMMMMMMMMMMMM MMMMMM\fRinor -.Ed -.Sh DESCRIPTION -The -.Nm -driver provides support for Cirrus Logic CD1400-based -.Tn EIA -.Tn RS-232C -.Pf ( Tn CCITT -.Tn V.24 ) -communications interfaces (ports) on Cyclades Cyclom-Y boards. -Each CD1400 provides 4 ports. -Cyclom-Y boards with various numbers of CD1400's are available. -This driver supports up to 8 CD1400's (32 ports) per board. -.Pp -Input and output for each line may set independently -to the following speeds: -50, 75, 110, 134.5, 150, 300, 600, 1200, 1800, 2400, 4800, 9600, -19200, 38400, 57600, or 115200 bps. -Other speeds of up to 150000 are supported by the termios interface -but not by the sgttyb compatibility interface. -The CD1400 is not fast enough to handle speeds above 115200 bps -effectively. -It can transmit on a single line at slightly more than 115200 bps, -but when 4 lines are active in both directions its limit is about -90000 bps on each line. -.\" XXX the following should be true for all serial drivers and -.\" should not be repeated in the man pages for all serial drivers. -.\" It was copied from sio.4. The only change was s/sio/cy/g. -.Pp -Serial ports controlled by the -.Nm -driver can be used for both `callin' and `callout'. -For each port there is a callin device and a callout device. -The minor number of the callout device is 128 higher -than that of the corresponding callin port. -The callin device is general purpose. -Processes opening it normally wait for carrier -and for the callout device to become inactive. -The callout device is used to steal the port from -processes waiting for carrier on the callin device. -Processes opening it do not wait for carrier -and put any processes waiting for carrier on the callin device into -a deeper sleep so that they do not conflict with the callout session. -The callout device is abused for handling programs that are supposed -to work on general ports and need to open the port without waiting -but are too stupid to do so. -.Pp -The -.Nm -driver also supports an initial-state and a lock-state control -device for each of the callin and the callout "data" devices. -The minor number of the initial-state device is 32 higher -than that of the corresponding data device. -The minor number of the lock-state device is 64 higher -than that of the corresponding data device. -The termios settings of a data device are copied -from those of the corresponding initial-state device -on first opens and are not inherited from previous opens. -Use -.Xr stty 1 -in the normal way on the initial-state devices to program -initial termios states suitable for your setup. -.Pp -The lock termios state acts as flags to disable changing -the termios state. -E.g., to lock a flag variable such as -CRTSCTS, use -.Em "stty crtscts" -on the lock-state device. -Speeds and special characters -may be locked by setting the corresponding value in the lock-state -device to any nonzero value. -.Pp -Correct programs talking to correctly wired external devices -work with almost arbitrary initial states and almost no locking, -but other setups may benefit from changing some of the default -initial state and locking the state. -In particular, the initial states for non (POSIX) standard flags -should be set to suit the devices attached and may need to be -locked to prevent buggy programs from changing them. -E.g., CRTSCTS should be locked on for devices that support -RTS/CTS handshaking at all times and off for devices that do not -support it at all. -CLOCAL should be locked on for devices -that do not support carrier. -HUPCL may be locked off if you do not -want to hang up for some reason. -In general, very bad things happen -if something is locked to the wrong state, and things should not -be locked for devices that support more than one setting. -The -CLOCAL flag on callin ports should be locked off for logins -to avoid certain security holes, but this needs to be done by -getty if the callin port is used for anything else. -.Ss Kernel Configuration Options -The -.Em CY_PCI_FASTINTR -option should be used to avoid suboptimal interrupt handling for -PCI Cyclades boards. -The PCI BIOS must be configured with the -.Nm -interrupt not shared with any other active device -for this option to work. -This option is not the default because it is currently harmful in -certain cases where it does not work. -.Sh FILES -.\" XXX more cloning: s/d/c/g and add a ? for the card number. -.Bl -tag -width /dev/ttyic?? -compact -.It Pa /dev/ttyc?? -for callin ports -.It Pa /dev/ttyic?? -.It Pa /dev/ttylc?? -corresponding callin initial-state and lock-state devices -.Pp -.\" XXX more cloning: s/a/c/g. No consistency :-(. -.It Pa /dev/cuac?? -for callout ports -.It Pa /dev/cuaic?? -.It Pa /dev/cualc?? -corresponding callout initial-state and lock-state devices -.El -.Pp -.Bl -tag -width /etc/rc.serial -compact -.It Pa /etc/rc.serial -examples of setting the initial-state and lock-state devices -.El -.Pp -The first question mark in these device names is short for the -card number -(a decimal number between 0 and 65535 inclusive). -The second question mark is short for the port number -(a letter in the range [0-9a-v]). -.Sh DIAGNOSTICS -.Bl -diag -.\" XXX back to s/sio/cy/g. -.It cy%d: silo overflow. -Problem in the interrupt handler. -.El -.Bl -diag -.It cy%d: interrupt-level buffer overflow. -Problem in the bottom half of the driver. -.El -.Bl -diag -.It cy%d: tty-level buffer overflow. -Problem in the application. -Input has arrived faster than the given module could process it -and some has been lost. -.El -.\" .Bl -diag -.\" .It sio%d: reduced fifo trigger level to %d. -.\" Attempting to avoid further silo overflows. -.\" .El -.Sh SEE ALSO -.Xr stty 1 , -.Xr termios 4 , -.Xr tty 4 , -.Xr comcontrol 8 , -.Xr pstat 8 -.Sh HISTORY -The -.Nm -driver is derived from the -.Nm sio -driver and the -.Nx -.Nm -driver and is -.Ud -.Sh BUGS -Serial consoles are not implemented. Index: share/man/man4/rc.4 =================================================================== --- share/man/man4/rc.4 +++ /dev/null @@ -1,124 +0,0 @@ -.\" -.\" Copyright (c) 2004 Tom Rhodes -.\" 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. -.\" -.\" 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$ -.\" -.Dd March 18, 2005 -.Dt RC 4 -.Os -.Sh NAME -.Nm rc -.Nd RISCom/8 multiport card -.Sh SYNOPSIS -.Cd device isa -.Cd device rc -.Sh DESCRIPTION -The -.Tn RISCom/8 -is an eight port -.Tn ISA -.Tn RS-232C -communications multiplexer with a built in -.Tn RISC -processor. -It uses a block of sixteen -.Tn I/O -ports in the range 0x200 to 0x3f0 selectable by on-board -switches or jumpers. -The block must be aligned on a sixteen port boundary. -The jumper-selectable hardware interrupt level may be set to -be detected during system -initialization using settings found in the -.Pa /boot/device.hints -file. -.Pp -This driver is mostly based on the Cirrus Logic CL-CD180 driver. -.Sh HARDWARE -The -.Nm -driver provides support for the -.Tn SDL -Communications -.Tn RISCom/8 -boards. -.Sh DIAGNOSTICS -The following driver specific error messages -may be reported: -.Bl -diag -.It "rc%d channel%d: interrupt-level buffer overflow" -An internal buffer overflow error has occurred on -the listed channel. -The -.Nm -driver will need to be reloaded to correct this. -.It "rc%d: Bad char chan %d" -The channel has obtained a bad set of characters. -.It "rc%d: Got extra chars chan %d" -The -.Nm -driver got more characters than expected on the channel shown. -.It "rc%d: data mismatch chan %d ptr %d (%d != %d)" -Data sent from channel -.Ar %d -to the rx buffer was different then expected. -.It "rc%d: channel %d command timeout, rc.c line: %d" -A command timeout has occurred on the channel, the -.Pa src/sys/dev/rc/rc.c -file can be consulted for more information. -.El -.Sh SEE ALSO -.Xr tty 1 , -.Xr ttyname 3 , -.Xr tty 4 , -.Xr device.hints 5 , -.Xr comcontrol 8 , -.Xr getty 8 , -.Xr mutex 9 , -.Xr splx 9 -.Pp -.Pa http://www.sdlcomm.com -.Sh HISTORY -The -.Nm -driver first appeared in -.Fx 2.0.5 . -This manual page first appeared in -.Fx 5.3 . -.Sh AUTHORS -This manual page was written by -.An Tom Rhodes Aq Mt trhodes@FreeBSD.org . -.Sh BUGS -The -.Nm -driver code still uses the -.Xr spl 9 -functions. -These should be replaced by -.Xr mutex 9 -functions. -.Pp -The various -.Fn ttyld_* -functions should be documented. Index: share/man/man4/rp.4 =================================================================== --- share/man/man4/rp.4 +++ /dev/null @@ -1,195 +0,0 @@ -.\" Copyright (c) 1995 Comtrol, Inc. -.\" All rights reserved. -.\" -.\" $FreeBSD$ -.Dd November 15, 1995 -.Dt RP 4 -.Os -.Sh NAME -.Nm rp -.Nd "driver for Comtrol RocketPort Intelligent Serial Port Cards" -.Sh SYNOPSIS -.Cd "device rp" -.Pp -For ISA cards, you must specify the port address in -.Pa /boot/device.hints : -.Cd hint.rp.0.at="isa" -.Cd hint.rp.0.port="0x100" -.Sh DESCRIPTION -This driver provides a kernel device driver for the -.Tn RocketPort -and -.Tn RocketPort RA -serial boards. -These boards provide 8, 16, or 32 high-speed serial ports -while requiring only 68 bytes of I/O space for all 8, 16, -or 32 ports, and do not require an interrupt channel. -This driver supports up to four -.Tn RocketPort -or -.Tn RocketPort RA -boards in one machine simultaneously. -If you are using four 32 port -.Tn RocketPort -boards, you can put as many as 128 intelligent serial ports -on your system. -.Pp -The -.Nm -driver supports the following speeds: 50, 75, 110, 134, 150, -200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 7200, -14400, 57600, 76800, 115200, and 230400. -(You must use -.Xr termios 4 , -rather than the old style ioctl interface to use non-traditional -speeds.) -.Pp -An open on the -.Nm -driver will block until carrier is present, unless -.Dv O_NONBLOCK -or -.Dv CLOCAL -is set. -.Sh HARDWARE CONFIGURATION -The first -.Tn RocketPort -or -.Tn RocketPort RA -card requires a 68-byte contiguous block of I/O addresses, -starting at one of the following: -0x100h, 0x140h, 0x180h, 0x200h, 0x240h, 0x280h, 0x300h, 0x340h, -0x380h. -The second, third, and fourth -.Tn RocketPort -cards require only a -64-byte contiguous block of I/O addresses, starting at one of the -above address ranges. -The I/O address range used by any of the -.Tn RocketPort -cards must not conflict with any other cards in the system, -including other -.Tn RocketPort -cards. -The starting range of the I/O ports used by each card -must match with the I/O address specified in -.Pa /boot/device.hints . -.Pp -Since the first -.Tn RocketPort -uses 68 I/O addresses, if the first card is -set to use an I/O block starting at 0x100, -it will occupy the I/O ports between 0x100 and 0x143. -This means that the second, third, or fourth -.Tn RocketPort -board may not use the block of addresses starting at 0x140, -since the first three I/O addresses of that range -are used by the first board. -This is an important point to keep in mind. -.Pp -If you have two ISA cards, one installed at 0x100 and the -second installed at 0x180, then you should add the following to -.Pa /boot/device.hints : -.Pp -.Dl hint.rp.0.at="isa" -.Dl hint.rp.0.port="0x100" -.Dl hint.rp.1.at="isa" -.Dl hint.rp.1.port="0x180" -.Pp -The configuration of the -.Tn RocketPort -cards is done via the set of 8 DIP switches, -labeled SW1 on the -.Tn RocketPort -card: -.Bd -literal -offset indent -+-------------------------------+ -| 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | -+-------+-------+---------------+ -| Unused| Card | I/O Port Block| -+-------------------------------+ -.Ed -.Pp -DIP switches 7 and 8 are unused, and must be left on. -.Pp -DIP switches 6 and 5 identify the card number of each -.Tn RocketPort -card. -The first card installed in the system must have its DIP switches set -as card number one; the second card installed in the system must have -its DIP switches set as card number two; and so on. -As shipped from -the factory, DIP switches 6 and 5 are both on by default, indicating -that this is the first card installed on the system: -.Bd -literal -offset indent -DIP Switches -6 5 -=================== -On On First Card -On Off Second Card -Off On Third Card -Off Off Fourth Card -.Ed -.Pp -DIP switches 4, 3, 2, and 1 indicate the I/O address range used by the -first -.Tn RocketPort -card. -If there are more than one -.Tn RocketPort -cards installed in a system, -the second, third and fourth -.Tn RocketPort -cards must -also be set to the I/O address range used by the first -.Tn RocketPort -card; -all cards must have these DIP switches set identically -for proper operation. -As shipped from the factory, DIP switch 4 is on, -and switches 3, 2, and 1 are off by default, -indicating an I/O address range used by the first -card which starts at 0x180 and extends to 0x1C3. -.Bd -literal -offset indent -DIP Switches I/O Address Range -4 3 2 1 Used by the First Card -===================================== -On Off On Off 100-143 -On Off Off On 140-183 -On Off Off Off 180-1C3 -Off On On Off 200-243 -Off On Off On 240-283 -Off On Off Off 280-2C3 -Off Off On Off 300-343 -Off Off Off On 340-383 -Off Off Off Off 380-3C3 -.Ed -.Sh FILES -.Bl -tag -width ".Pa /dev/ttyR[0-4][0-9a-f]" -.It Pa /dev/ttyR[0-4][0-9a-f] -.El -.Sh AUTHORS -.An Theodore Ts'o Aq Mt tytso@mit.edu -.Pp -This driver was written under contract for Comtrol Corporation. -For dealer, distributor and other information regarding Comtrol -.Tn RocketPort , -contact Comtrol Corporation at (800) 926-6876 or send email to -.Aq Mt info@comtrol.com . -To report bugs for this driver, please send email to -.Aq Mt bug-bsdi-rocketport@comtrol.com . -.Sh BUGS -If incoming software flow control is enabled on a 486 or Pentium -machine, and the flow control is very heavily exercised, on rare occasions -a character will get dropped. -This problem does not occur on a 386, and -it is not currently known whether the bug is in the -.Nm -driver -or in the -.Bsx -tty layer. -.\" (Although my bet is that it's in the higher-level tty layer; -.\" given the bugs I found while writing this driver, it's clear -.\" the BSD software flow control code has not been tested very much -.\" at all! -- TYT) Index: sys/dev/cy/cy.c =================================================================== --- sys/dev/cy/cy.c +++ sys/dev/cy/cy.c @@ -1,2242 +0,0 @@ -/*- - * cyclades cyclom-y serial driver - * Andrew Herbert , 17 August 1993 - * - * SPDX-License-Identifier: BSD-3-Clause - * - * 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. - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * 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 -#include - -#define NCY 10 /* KLUDGE */ - -#define NPORTS (NCY * CY_MAX_PORTS) - -#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 */ - -/* - * 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 cystart(), cypoll() and - * comstop()) - * CS_TTGO = ~TS_TTSTOP (maintained by cyparam() and cystart()) - * CS_CTS_OFLOW = CCTS_OFLOW (maintained by cyparam()) - * CS_RTS_IFLOW = CRTS_IFLOW (maintained by cyparam()) - * 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_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]) - -#ifdef SMP -#define COM_LOCK() mtx_lock_spin(&cy_lock) -#define COM_UNLOCK() mtx_unlock_spin(&cy_lock) -#else -#define COM_LOCK() -#define COM_UNLOCK() -#endif - -/* types. XXX - should be elsewhere */ -typedef u_char bool_t; /* boolean */ - -/* 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 */ - u_char etc; /* pending Embedded Transmit Command */ - u_char extra_state; /* more flag bits, separate for order trick */ - u_char gfrcr_image; /* copy of value read from GFRCR */ - 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 */ - int unit; /* unit number */ - - /* - * 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 *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 */ - - 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 cystart() */ - 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]; -}; - -devclass_t cy_devclass; -char cy_driver_name[] = "cy"; - -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 void cyinput(struct com_s *com); -static int cyparam(struct tty *tp, struct termios *t); -static void cypoll(void *arg); -static void cysettimeout(void); -static int cysetwater(struct com_s *com, speed_t speed); -static int cyspeed(speed_t speed, u_long cy_clock, int *prescaler_io); -static void cystart(struct tty *tp); -static void comstop(struct tty *tp, int rw); -static timeout_t cywakeup; -static void disc_optim(struct tty *tp, struct termios *t, - struct com_s *com); - -static t_break_t cybreak; -static t_modem_t cymodem; -static t_open_t cyopen; -static t_close_t cyclose; - -#ifdef CyDebug -void cystatus(int unit); -#endif - -static struct mtx cy_lock; -static int cy_inited; - -/* table and macro for fast conversion from a unit number to its com struct */ -static struct com_s *p_cy_addr[NPORTS]; -#define cy_addr(unit) (p_cy_addr[unit]) - -static u_int cy_events; /* input chars + weighted output completions */ -static void *cy_fast_ih; -static void *cy_slow_ih; -static int cy_timeout; -static int cy_timeouts_until_log; -static struct callout_handle cy_timeout_handle - = CALLOUT_HANDLE_INITIALIZER(&cy_timeout_handle); - -#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); - -int -cy_units(cy_addr cy_iobase, int cy_align) -{ - int cyu; - u_char firmware_version; - 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); - - /* XXX bogus initialization to avoid a gcc bug/warning. */ - firmware_version = 0; - - /* 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); -} - -void * -cyattach_common(cy_addr cy_iobase, int cy_align) -{ - int adapter; - int cyu; - u_char firmware_version; - cy_addr iobase; - int ncyu; - int unit; - struct tty *tp; - - while (cy_inited != 2) - if (atomic_cmpset_int(&cy_inited, 0, 1)) { - mtx_init(&cy_lock, cy_driver_name, NULL, MTX_SPIN); - atomic_store_rel_int(&cy_inited, 2); - } - - adapter = cy_total_devices; - if ((u_int)adapter >= NCY) { - printf( - "cy%d: can't attach adapter: insufficient cy devices configured\n", - adapter); - return (NULL); - } - ncyu = cy_units(cy_iobase, cy_align); - if (ncyu == 0) - return (NULL); - 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; - int s; - - com = malloc(sizeof *com, M_DEVBUF, M_NOWAIT | M_ZERO); - if (com == NULL) - break; - com->unit = unit; - com->gfrcr_image = firmware_version; - if (CY_RTS_DTR_SWAPPED(firmware_version)) { - com->mcr_dtr = CD1400_MSVR1_RTS; - com->mcr_rts = CD1400_MSVR2_DTR; - com->mcr_rts_reg = CD1400_MSVR2; - } else { - com->mcr_dtr = CD1400_MSVR2_DTR; - com->mcr_rts = CD1400_MSVR1_RTS; - com->mcr_rts_reg = CD1400_MSVR1; - } - 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; - - tp = com->tp = ttyalloc(); - tp->t_open = cyopen; - tp->t_close = cyclose; - tp->t_oproc = cystart; - tp->t_stop = comstop; - tp->t_param = cyparam; - tp->t_break = cybreak; - tp->t_modem = cymodem; - tp->t_sc = com; - - if (cysetwater(com, tp->t_init_in.c_ispeed) != 0) { - free(com, M_DEVBUF); - return (NULL); - } - - s = spltty(); - cy_addr(unit) = com; - splx(s); - - if (cy_fast_ih == NULL) { - swi_add(&tty_intr_event, "cy", cypoll, NULL, SWI_TTY, 0, - &cy_fast_ih); - swi_add(&clk_intr_event, "cy", cypoll, NULL, SWI_CLOCK, 0, - &cy_slow_ih); - } - ttycreate(tp, TS_CALLOUT, "c%r%r", - adapter, unit % CY_MAX_PORTS); - } - } - - /* ensure an edge for the next interrupt */ - cy_outb(cy_iobase, CY_CLEAR_INTR, cy_align, 0); - - return (cy_addr(adapter * CY_MAX_PORTS)); -} - -static int -cyopen(struct tty *tp, struct cdev *dev) -{ - struct com_s *com; - int s; - - com = tp->t_sc; - s = spltty(); - /* - * We jump to this label after all non-interrupted sleeps to pick - * up any changes of the device state. - */ - - /* Encode per-board unit in LIVR for access in intr routines. */ - cd_setreg(com, CD1400_LIVR, - (com->unit & CD1400_xIVR_CHAN) << CD1400_xIVR_CHAN_SHIFT); - - /* - * 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); - - critical_enter(); - COM_LOCK(); - 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); - COM_UNLOCK(); - critical_exit(); - cysettimeout(); - return (0); -} - - -static void -cyclose(struct tty *tp) -{ - cy_addr iobase; - struct com_s *com; - int s; - int unit; - - com = tp->t_sc; - unit = com->unit; - iobase = com->iobase; - s = spltty(); - /* XXX */ - critical_enter(); - COM_LOCK(); - com->etc = ETC_NONE; - cd_setreg(com, CD1400_COR2, com->cor[1] &= ~CD1400_COR2_ETC); - COM_UNLOCK(); - critical_exit(); - cd_etc(com, CD1400_ETC_STOPBREAK); - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); - - { - critical_enter(); - COM_LOCK(); - cd_setreg(com, CD1400_SRER, com->intr_enable = 0); - COM_UNLOCK(); - critical_exit(); - 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. - */ - || (!tp->t_actout - && !(com->prev_modem_status & CD1400_MSVR2_CD) - && !(tp->t_init_in.c_cflag & CLOCAL)) - || !(tp->t_state & TS_ISOPEN)) { - (void)cymodem(tp, 0, SER_DTR); - - /* Disable receiver (leave transmitter enabled). */ - com->channel_control = CD1400_CCR_CMDCHANCTL - | CD1400_CCR_XMTEN - | CD1400_CCR_RCVDIS; - cd1400_channel_cmd(com, com->channel_control); - - ttydtrwaitstart(tp); - } - } - tp->t_actout = FALSE; - wakeup(&tp->t_actout); - wakeup(TSA_CARR_ON(tp)); /* restart any wopeners */ - splx(s); -} - -/* - * This function: - * a) needs to be called with COM_LOCK() held, and - * b) needs to return with COM_LOCK() held. - */ -static void -cyinput(struct com_s *com) -{ - u_char *buf; - int incc; - u_char line_status; - int recv_data; - struct tty *tp; - - buf = com->ibuf; - tp = com->tp; - if (!(tp->t_state & TS_ISOPEN)) { - cy_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 { - /* - * This may look odd, but it is using save-and-enable - * semantics instead of the save-and-disable semantics - * that are used everywhere else. - */ - COM_UNLOCK(); - critical_exit(); - 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; - cystart(tp); - } - critical_enter(); - COM_LOCK(); - } while (buf < com->iptr); - } else { - do { - /* - * This may look odd, but it is using save-and-enable - * semantics instead of the save-and-disable semantics - * that are used everywhere else. - */ - COM_UNLOCK(); - critical_exit(); - line_status = buf[com->ierroff]; - recv_data = *buf++; - if (line_status - & (CD1400_RDSR_BREAK | CD1400_RDSR_FE | CD1400_RDSR_OE | CD1400_RDSR_PE)) { - if (line_status & CD1400_RDSR_BREAK) - recv_data |= TTY_BI; - if (line_status & CD1400_RDSR_FE) - recv_data |= TTY_FE; - if (line_status & CD1400_RDSR_OE) - recv_data |= TTY_OE; - if (line_status & CD1400_RDSR_PE) - recv_data |= TTY_PE; - } - ttyld_rint(tp, recv_data); - critical_enter(); - COM_LOCK(); - } while (buf < com->iptr); - } - cy_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)) - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -} - -int -cyintr(void *vcom) -{ - struct com_s *basecom; - int baseu; - int cy_align; - cy_addr cy_iobase; - int cyu; - cy_addr iobase; - u_char status; - int unit; - - COM_LOCK(); /* XXX could this be placed down lower in the loop? */ - - basecom = (struct com_s *)vcom; - baseu = basecom->unit; - cy_align = basecom->cy_align; - cy_iobase = basecom->cy_iobase; - unit = baseu / CY_MAX_PORTS; - - /* 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; // XXX - FILTER_STRAY? -#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); - cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_rir & CD1400_CAR_CHAN; - - serv_type = cd_inb(iobase, CD1400_RIVR, cy_align); - com = cy_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 = cy_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->tp->t_hotchar != 0) - swi_sched(cy_fast_ih, 0); - -#endif -#if 1 /* XXX "intelligent" PFO error handling would break O error handling */ - if (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE|CD1400_RDSR_BREAK)) { - /* - 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 & (CD1400_RDSR_PE|CD1400_RDSR_FE)) - && (com->tp->t_iflag & IGNPAR)) - || ((line_status & CD1400_RDSR_BREAK) - && (com->tp->t_iflag & IGNBRK))) - goto cont; - if ( (line_status & (CD1400_RDSR_PE|CD1400_RDSR_FE)) - && (com->tp->t_state & TS_CAN_BYPASS_L_RINT) - && ((line_status & CD1400_RDSR_FE) - || ((line_status & CD1400_RDSR_PE) - && (com->tp->t_iflag & INPCK)))) - recv_data = 0; - } -#endif /* 1 */ - ++com->bytes_in; -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 && recv_data == com->tp->t_hotchar) - swi_sched(cy_fast_ih, 0); -#endif - ioptr = com->iptr; - if (ioptr >= com->ibufend) - CE_RECORD(com, CE_INTERRUPT_BUF_OVERFLOW); - else { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - ++cy_events; - ioptr[0] = recv_data; - ioptr[com->ierroff] = line_status; - com->iptr = ++ioptr; - if (ioptr == com->ihighwater - && com->state & CS_RTS_IFLOW) - cd_outb(iobase, com->mcr_rts_reg, - cy_align, - com->mcr_image &= - ~com->mcr_rts); - if (line_status & CD1400_RDSR_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; - cy_events += ifree; - if (ifree != 0) { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - do { - recv_data = cd_inb(iobase, - CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 - && recv_data - == com->tp->t_hotchar) - swi_sched(cy_fast_ih, - 0); -#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->tp->t_hotchar != 0 - && recv_data == com->tp->t_hotchar) - swi_sched(cy_fast_ih, 0); -#endif - } while (--count != 0); - } else { - if (com->tp != NULL && com->tp->t_do_timestamp) - microtime(&com->tp->t_timestamp); - if (ioptr <= com->ihighwater - && ioptr + count > com->ihighwater - && com->state & CS_RTS_IFLOW) - cd_outb(iobase, com->mcr_rts_reg, - cy_align, - com->mcr_image - &= ~com->mcr_rts); - cy_events += count; - do { - recv_data = cd_inb(iobase, CD1400_RDSR, - cy_align); -#ifdef SOFT_HOTCHAR - if (com->tp->t_hotchar != 0 - && recv_data == com->tp->t_hotchar) - swi_sched(cy_fast_ih, 0); -#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); - cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_mir & CD1400_CAR_CHAN; - - com = cy_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 = cy_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) { - /* - * 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)) { - cy_events += LOTS_OF_EVENTS; - com->state |= CS_CHECKMSR; - swi_sched(cy_fast_ih, 0); - } - -#ifdef SOFT_CTS_OFLOW - /* handle CTS change immediately for crisp flow ctl */ - if (com->state & CS_CTS_OFLOW) { - if (modem_status & CD1400_MSVR2_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); - cy_addr(baseu + cyu * CD1400_NO_OF_CHANNELS)->car - = save_tir & CD1400_CAR_CHAN; - - com = cy_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 = cy_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)) { - cy_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - swi_sched(cy_fast_ih, 0); - } - 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)) { - cy_events += LOTS_OF_EVENTS; - com->extra_state |= CSE_ODONE; - swi_sched(cy_fast_ih, 0); - } - 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) { - cy_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)) { - cy_events += LOTS_OF_EVENTS; - com->state |= CS_ODONE; - - /* handle at high level ASAP */ - swi_sched(cy_fast_ih, 0); - } - } - } - - /* 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); - - swi_sched(cy_slow_ih, SWI_DELAY); - - COM_UNLOCK(); - return (FILTER_HANDLED); -} - -static void -cybreak(struct tty *tp, int sig) -{ - struct com_s *com; - - com = tp->t_sc; - if (sig) - cd_etc(com, CD1400_ETC_SENDBREAK); - else - cd_etc(com, CD1400_ETC_STOPBREAK); -} - -static void -cypoll(void *arg) -{ - int unit; - -#ifdef CyDebug - ++cy_timeouts; -#endif - if (cy_events == 0) - return; -repeat: - for (unit = 0; unit < NPORTS; ++unit) { - struct com_s *com; - int incc; - struct tty *tp; - - com = cy_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. - */ - critical_enter(); - COM_LOCK(); - incc = com->iptr - com->ibuf; - com->iptr = com->ibuf; - if (com->state & CS_CHECKMSR) { - incc += LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - } - cy_events -= incc; - COM_UNLOCK(); - critical_exit(); - if (incc != 0) - log(LOG_DEBUG, - "cy%d: %d events for device with no tp\n", - unit, incc); - continue; - } - if (com->iptr != com->ibuf) { - critical_enter(); - COM_LOCK(); - cyinput(com); - COM_UNLOCK(); - critical_exit(); - } - if (com->state & CS_CHECKMSR) { - u_char delta_modem_status; - - critical_enter(); - COM_LOCK(); - cyinput(com); - delta_modem_status = com->last_modem_status - ^ com->prev_modem_status; - com->prev_modem_status = com->last_modem_status; - cy_events -= LOTS_OF_EVENTS; - com->state &= ~CS_CHECKMSR; - COM_UNLOCK(); - critical_exit(); - if (delta_modem_status & CD1400_MSVR2_CD) - ttyld_modem(tp, - com->prev_modem_status & CD1400_MSVR2_CD); - } - if (com->extra_state & CSE_ODONE) { - critical_enter(); - COM_LOCK(); - cy_events -= LOTS_OF_EVENTS; - com->extra_state &= ~CSE_ODONE; - COM_UNLOCK(); - critical_exit(); - 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) { - critical_enter(); - COM_LOCK(); - cy_events -= LOTS_OF_EVENTS; - com->state &= ~CS_ODONE; - COM_UNLOCK(); - critical_exit(); - ttyld_start(tp); - } - if (cy_events == 0) - break; - } - if (cy_events >= LOTS_OF_EVENTS) - goto repeat; -} - -static int -cyparam(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 s; - - com = tp->t_sc; - - /* check requested parameters */ - cy_clock = CY_CLOCK(com->gfrcr_image); - idivisor = cyspeed(t->c_ispeed, cy_clock, &iprescaler); - if (idivisor <= 0) - return (EINVAL); - odivisor = cyspeed(t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed, - cy_clock, &oprescaler); - if (odivisor <= 0) - return (EINVAL); - - /* parameters are OK, convert them to the com struct and the device */ - s = spltty(); - if (t->c_ospeed == 0) - (void)cymodem(tp, 0, SER_DTR); - else - (void)cymodem(tp, SER_DTR, 0); - - (void) cysetwater(com, t->c_ispeed); - - /* XXX we don't actually change the speed atomically. */ - - cd_setreg(com, CD1400_RBPR, idivisor); - cd_setreg(com, CD1400_RCOR, iprescaler); - 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). - */ - itimeout = howmany(1000 * bits, 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 - critical_enter(); - COM_LOCK(); - if (opt != com->cor[1]) { - cor_change |= CD1400_CCR_COR2; - cd_setreg(com, CD1400_COR2, com->cor[1] = opt); - } - COM_UNLOCK(); - critical_exit(); - - /* - * 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. - */ - critical_enter(); - COM_LOCK(); - - 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 CD1400_MSVR1_RTS. This isn't urgent, - * so do it later by calling cystart() instead of repeating - * a lot of code from cystart() here. - */ - } else if (com->state & CS_RTS_IFLOW) { - com->state &= ~CS_RTS_IFLOW; - /* - * CS_RTS_IFLOW just changed from on to off. Force CD1400_MSVR1_RTS - * on here, since cystart() won't do it later. - */ - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); - } - - /* - * 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 & CD1400_MSVR2_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 cyintr1() - * unconditionally, but that defeated the careful discarding of - * stale input in cyopen(). - */ - if (com->state >= (CS_BUSY | CS_TTGO)) - cyintr1(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); - } - - COM_UNLOCK(); - critical_exit(); - splx(s); - cystart(tp); - if (com->ibufold != NULL) { - free(com->ibufold, M_DEVBUF); - com->ibufold = NULL; - } - return (0); -} - -static int -cysetwater(struct com_s *com, speed_t speed) -{ - int cp4ticks; - u_char *ibuf; - int ibufsize; - struct tty *tp; - - /* - * 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) { - 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 = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT); - if (ibuf == NULL) { - return (ENOMEM); - } - - /* 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. - */ - critical_enter(); - COM_LOCK(); - if (com->iptr != com->ibuf) - cyinput(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; - - COM_UNLOCK(); - critical_exit(); - return (0); -} - -static void -cystart(struct tty *tp) -{ - struct com_s *com; - int s; -#ifdef CyDebug - bool_t started; -#endif - - com = tp->t_sc; - s = spltty(); - -#ifdef CyDebug - ++com->start_count; - started = FALSE; -#endif - - critical_enter(); - COM_LOCK(); - 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 &= ~CD1400_MSVR1_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 |= CD1400_MSVR1_RTS); -#else - cd_setreg(com, com->mcr_rts_reg, - com->mcr_image |= com->mcr_rts); -#endif - } - COM_UNLOCK(); - critical_exit(); - if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) { - ttwwakeup(tp); - splx(s); - 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; - critical_enter(); - COM_LOCK(); - 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); - } - COM_UNLOCK(); - critical_exit(); - } - 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; - critical_enter(); - COM_LOCK(); - 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); - } - COM_UNLOCK(); - critical_exit(); - } - tp->t_state |= TS_BUSY; - } -#ifdef CyDebug - if (started) - ++com->start_real; -#endif -#if 0 - critical_enter(); - COM_LOCK(); - if (com->state >= (CS_BUSY | CS_TTGO)) - cyintr1(com); /* fake interrupt to start output */ - COM_UNLOCK(); - critical_exit(); -#endif - ttwwakeup(tp); - splx(s); -} - -static void -comstop(struct tty *tp, int rw) -{ - struct com_s *com; - bool_t wakeup_etc; - - com = tp->t_sc; - wakeup_etc = FALSE; - critical_enter(); - COM_LOCK(); - if (rw & FWRITE) { - com->obufs[0].l_queued = FALSE; - com->obufs[1].l_queued = FALSE; - if (com->extra_state & CSE_ODONE) { - cy_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) - cy_events -= LOTS_OF_EVENTS; - com->state &= ~(CS_ODONE | CS_BUSY); - } - if (rw & FREAD) { - /* XXX no way to reset only input fifo. */ - cy_events -= (com->iptr - com->ibuf); - com->iptr = com->ibuf; - } - COM_UNLOCK(); - critical_exit(); - if (wakeup_etc) - wakeup(&com->etc); - if (rw & FWRITE && com->etc == ETC_NONE) - cd1400_channel_cmd(com, CD1400_CCR_CMDRESET | CD1400_CCR_FTF); - cystart(tp); -} - -static int -cymodem(struct tty *tp, int sigon, int sigoff) -{ - struct com_s *com; - int mcr; - int msr; - - com = tp->t_sc; - if (sigon == 0 && sigoff == 0) { - sigon = 0; - mcr = com->mcr_image; - if (mcr & com->mcr_dtr) - sigon |= SER_DTR; - if (mcr & com->mcr_rts) - /* XXX wired on for Cyclom-8Ys */ - sigon |= SER_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 & CD1400_MSVR2_CTS) - sigon |= SER_CTS; - if (msr & CD1400_MSVR2_CD) - sigon |= SER_DCD; - if (msr & CD1400_MSVR2_DSR) - sigon |= SER_DSR; - if (msr & CD1400_MSVR2_RI) - /* XXX not connected except for Cyclom-16Y? */ - sigon |= SER_RI; - return (sigon); - } - mcr = com->mcr_image; - if (sigon & SER_DTR) - mcr |= com->mcr_dtr; - if (sigoff & SER_DTR) - mcr &= ~com->mcr_dtr; - if (sigon & SER_RTS) - mcr |= com->mcr_rts; - if (sigoff & SER_RTS) - mcr &= ~com->mcr_rts; - critical_enter(); - COM_LOCK(); - com->mcr_image = mcr; - cd_setreg(com, CD1400_MSVR1, mcr); - cd_setreg(com, CD1400_MSVR2, mcr); - COM_UNLOCK(); - critical_exit(); - return (0); -} - -static void -cysettimeout() -{ - struct com_s *com; - bool_t someopen; - int unit; - - /* - * 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. - */ - untimeout(cywakeup, (void *)NULL, cy_timeout_handle); - cy_timeout = hz; - someopen = FALSE; - for (unit = 0; unit < NPORTS; ++unit) { - com = cy_addr(unit); - if (com != NULL && com->tp != NULL - && com->tp->t_state & TS_ISOPEN) { - someopen = TRUE; - } - } - if (someopen) { - cy_timeouts_until_log = hz / cy_timeout; - cy_timeout_handle = timeout(cywakeup, (void *)NULL, - cy_timeout); - } else { - /* Flush error messages, if any. */ - cy_timeouts_until_log = 1; - cywakeup((void *)NULL); - untimeout(cywakeup, (void *)NULL, cy_timeout_handle); - } -} - -static void -cywakeup(void *chan) -{ - struct com_s *com; - int unit; - - cy_timeout_handle = timeout(cywakeup, (void *)NULL, cy_timeout); - - /* - * Check for and log errors, but not too often. - */ - if (--cy_timeouts_until_log > 0) - return; - cy_timeouts_until_log = hz / cy_timeout; - for (unit = 0; unit < NPORTS; ++unit) { - int errnum; - - com = cy_addr(unit); - if (com == NULL) - continue; - for (errnum = 0; errnum < CE_NTYPES; ++errnum) { - u_int delta; - u_long total; - - critical_enter(); - COM_LOCK(); - delta = com->delta_error_counts[errnum]; - com->delta_error_counts[errnum] = 0; - COM_UNLOCK(); - critical_exit(); - 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); - } - } -} - -static void -disc_optim(struct tty *tp, struct termios *t, struct com_s *com) -{ -#ifndef SOFT_HOTCHAR - u_char opt; -#endif - - ttyldoptim(tp); -#ifndef SOFT_HOTCHAR - opt = com->cor[2] & ~CD1400_COR3_SCD34; - if (com->tp->t_hotchar != 0) { - cd_setreg(com, CD1400_SCHR3, com->tp->t_hotchar); - cd_setreg(com, CD1400_SCHR4, com->tp->t_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 -} - -#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 session are raw anyhow. - */ -} -#endif /* Smarts */ - -static int -cyspeed(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); - - *prescaler_io = prescaler_unit; - return (divider); -} - -static void -cd1400_channel_cmd(struct com_s *com, int cmd) -{ - cd1400_channel_cmd_wait(com); - cd_setreg(com, CD1400_CCR, cmd); - cd1400_channel_cmd_wait(com); -} - -static void -cd1400_channel_cmd_wait(struct com_s *com) -{ - struct timeval start; - struct timeval tv; - long usec; - - 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; - } - } -} - -static void -cd_etc(struct com_s *com, int etc) -{ - - /* - * 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. - */ - critical_enter(); - COM_LOCK(); - if (com->etc == etc) - 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))) { - COM_UNLOCK(); - critical_exit(); - return; - } - com->etc = etc; - cd_setreg(com, CD1400_SRER, - com->intr_enable - = (com->intr_enable & ~CD1400_SRER_TXRDY) | CD1400_SRER_TXMPTY); -wait: - COM_UNLOCK(); - critical_exit(); - while (com->etc == etc - && tsleep(&com->etc, TTIPRI | PCATCH, "cyetc", 0) == 0) - continue; -} - -static int -cd_getreg(struct com_s *com, int reg) -{ - struct com_s *basecom; - u_char car; - int cy_align; - cy_addr iobase; -#ifdef SMP - int need_unlock; -#endif - int val; - - basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - critical_enter(); -#ifdef SMP - need_unlock = 0; - if (!mtx_owned(&cy_lock)) { - COM_LOCK(); - need_unlock = 1; - } -#endif - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - val = cd_inb(iobase, reg, cy_align); -#ifdef SMP - if (need_unlock) - COM_UNLOCK(); -#endif - critical_exit(); - return (val); -} - -static void -cd_setreg(struct com_s *com, int reg, int val) -{ - struct com_s *basecom; - u_char car; - int cy_align; - cy_addr iobase; -#ifdef SMP - int need_unlock; -#endif - - basecom = cy_addr(com->unit & ~(CD1400_NO_OF_CHANNELS - 1)); - car = com->unit & CD1400_CAR_CHAN; - cy_align = com->cy_align; - iobase = com->iobase; - critical_enter(); -#ifdef SMP - need_unlock = 0; - if (!mtx_owned(&cy_lock)) { - COM_LOCK(); - need_unlock = 1; - } -#endif - if (basecom->car != car) - cd_outb(iobase, CD1400_CAR, cy_align, basecom->car = car); - cd_outb(iobase, reg, cy_align, val); -#ifdef SMP - if (need_unlock) - COM_UNLOCK(); -#endif - critical_exit(); -} - -#ifdef CyDebug -/* useful in ddb */ -void -cystatus(int unit) -{ - struct com_s *com; - cy_addr iobase; - u_int ocount; - struct tty *tp; - - com = cy_addr(unit); - printf("info for channel %d\n", unit); - printf("------------------\n"); - printf("total cyclom service probes:\t%d\n", cy_svrr_probes); - printf("calls to upper layer:\t\t%d\n", cy_timeouts); - if (com == NULL) - return; - iobase = com->iobase; - printf("\n"); - printf("cd1400 base address:\\tt%p\n", iobase); - printf("saved channel_control:\t\t0x%02x\n", com->channel_control); - printf("saved cor1-3:\t\t\t0x%02x 0x%02x 0x%02x\n", - com->cor[0], com->cor[1], com->cor[2]); - printf("service request enable reg:\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_SRER), com->intr_enable); - printf("service request register:\t0x%02x\n", - cd_inb(iobase, CD1400_SVRR, com->cy_align)); - printf("modem status:\t\t\t0x%02x (0x%02x cached)\n", - cd_getreg(com, CD1400_MSVR2), com->prev_modem_status); - printf("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)); - printf("\n"); - printf("com state:\t\t\t0x%02x\n", com->state); - printf("calls to cystart():\t\t%d (%d useful)\n", - com->start_count, com->start_real); - printf("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; - printf("tx buffer chars:\t\t%u\n", ocount); - printf("received chars:\t\t\t%d\n", com->bytes_in); - printf("received exceptions:\t\t%d\n", com->recv_exception); - printf("modem signal deltas:\t\t%d\n", com->mdm); - printf("transmitted chars:\t\t%d\n", com->bytes_out); - printf("\n"); - tp = com->tp; - if (tp != NULL) { - printf("tty state:\t\t\t0x%08x\n", tp->t_state); - printf( - "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 - printf("tty state:\t\t\tclosed\n"); -} -#endif /* CyDebug */ Index: sys/dev/cy/cy_isa.c =================================================================== --- sys/dev/cy/cy_isa.c +++ sys/dev/cy/cy_isa.c @@ -1,152 +0,0 @@ -/*- - * cyclades cyclom-y serial driver - * Andrew Herbert , 17 August 1993 - * - * SPDX-License-Identifier: BSD-3-Clause - * - * 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. - */ - -/* - * Cyclades Y ISA serial interface driver - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -static int cy_isa_attach(device_t dev); -static int cy_isa_probe(device_t dev); - -static device_method_t cy_isa_methods[] = { - /* Device interface. */ - DEVMETHOD(device_probe, cy_isa_probe), - DEVMETHOD(device_attach, cy_isa_attach), - - { 0, 0 } -}; - -static driver_t cy_isa_driver = { - cy_driver_name, - cy_isa_methods, - 0, -}; - -DRIVER_MODULE(cy, isa, cy_isa_driver, cy_devclass, 0, 0); - -static int -cy_isa_probe(device_t dev) -{ - struct resource *mem_res; - cy_addr iobase; - int error, mem_rid; - - if (isa_get_logicalid(dev) != 0) /* skip PnP probes */ - return (ENXIO); - - mem_rid = 0; - mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, - RF_ACTIVE); - if (mem_res == NULL) { - device_printf(dev, "ioport resource allocation failed\n"); - return (ENXIO); - } - iobase = rman_get_virtual(mem_res); - - /* Cyclom-16Y hardware reset (Cyclom-8Ys don't care) */ - cy_inb(iobase, CY16_RESET, 0); /* XXX? */ - DELAY(500); /* wait for the board to get its act together */ - - /* this is needed to get the board out of reset */ - cy_outb(iobase, CY_CLEAR_INTR, 0, 0); - DELAY(500); - - error = (cy_units(iobase, 0) == 0 ? ENXIO : 0); - bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); - return (error); -} - -static int -cy_isa_attach(device_t dev) -{ - struct resource *irq_res, *mem_res; - void *irq_cookie, *vaddr, *vsc; - int irq_rid, mem_rid; - - irq_res = NULL; - mem_res = NULL; - - mem_rid = 0; - mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, - RF_ACTIVE); - if (mem_res == NULL) { - device_printf(dev, "memory resource allocation failed\n"); - goto fail; - } - vaddr = rman_get_virtual(mem_res); - - vsc = cyattach_common(vaddr, 0); - if (vsc == NULL) { - device_printf(dev, "no ports found!\n"); - goto fail; - } - - irq_rid = 0; - irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (irq_res == NULL) { - device_printf(dev, "interrupt resource allocation failed\n"); - goto fail; - } - if (bus_setup_intr(dev, irq_res, INTR_TYPE_TTY, - cyintr, NULL, vsc, &irq_cookie) != 0) { - device_printf(dev, "interrupt setup failed\n"); - goto fail; - } - - return (0); - -fail: - if (irq_res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); - if (mem_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); - return (ENXIO); -} Index: sys/dev/cy/cy_pci.c =================================================================== --- sys/dev/cy/cy_pci.c +++ sys/dev/cy/cy_pci.c @@ -1,194 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * 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. - */ - -/* - * Cyclades Y PCI serial interface driver - */ - -#include -__FBSDID("$FreeBSD$"); - -#include "opt_cy_pci_fastintr.h" - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#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 - -static int cy_pci_attach(device_t dev); -static int cy_pci_probe(device_t dev); - -static device_method_t cy_pci_methods[] = { - /* Device interface. */ - DEVMETHOD(device_probe, cy_pci_probe), - DEVMETHOD(device_attach, cy_pci_attach), - - { 0, 0 } -}; - -static driver_t cy_pci_driver = { - cy_driver_name, - cy_pci_methods, - 0, -}; - -DRIVER_MODULE(cy, pci, cy_pci_driver, cy_devclass, 0, 0); -MODULE_DEPEND(cy, pci, 1, 1, 1); - -static int -cy_pci_probe(dev) - device_t dev; -{ - u_int32_t device_id; - - device_id = pci_get_devid(dev); - device_id &= ~0x00060000; - if (device_id != 0x0100120e && device_id != 0x0101120e) - return (ENXIO); - device_set_desc(dev, "Cyclades Cyclom-Y Serial Adapter"); - return (BUS_PROBE_DEFAULT); -} - -static int -cy_pci_attach(dev) - device_t dev; -{ - struct resource *ioport_res, *irq_res, *mem_res; - void *irq_cookie, *vaddr, *vsc; - u_int32_t ioport; - int irq_setup, ioport_rid, irq_rid, mem_rid; - u_char plx_ver; - - ioport_res = NULL; - irq_res = NULL; - mem_res = NULL; - - ioport_rid = CY_PCI_BASE_ADDR1; - ioport_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &ioport_rid, - RF_ACTIVE); - if (ioport_res == NULL) { - device_printf(dev, "ioport resource allocation failed\n"); - goto fail; - } - ioport = rman_get_start(ioport_res); - - mem_rid = CY_PCI_BASE_ADDR2; - mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &mem_rid, - RF_ACTIVE); - if (mem_res == NULL) { - device_printf(dev, "memory resource allocation failed\n"); - goto fail; - } - vaddr = rman_get_virtual(mem_res); - - vsc = cyattach_common(vaddr, 1); - if (vsc == NULL) { - device_printf(dev, "no ports found!\n"); - goto fail; - } - - irq_rid = 0; - irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &irq_rid, - RF_SHAREABLE | RF_ACTIVE); - if (irq_res == NULL) { - device_printf(dev, "interrupt resource allocation failed\n"); - goto fail; - } -#ifdef CY_PCI_FASTINTR - irq_setup = bus_setup_intr(dev, irq_res, INTR_TYPE_TTY, - cyintr, NULL, vsc, &irq_cookie); -#else - irq_setup = ENXIO; -#endif - if (irq_setup != 0) - irq_setup = bus_setup_intr(dev, irq_res, INTR_TYPE_TTY, - NULL, (driver_intr_t *)cyintr, vsc, &irq_cookie); - if (irq_setup != 0) { - device_printf(dev, "interrupt setup failed\n"); - 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 (0); - -fail: - if (ioport_res != NULL) - bus_release_resource(dev, SYS_RES_IOPORT, ioport_rid, - ioport_res); - if (irq_res != NULL) - bus_release_resource(dev, SYS_RES_IRQ, irq_rid, irq_res); - if (mem_res != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, mem_rid, mem_res); - return (ENXIO); -} Index: sys/dev/cy/cyreg.h =================================================================== --- sys/dev/cy/cyreg.h +++ sys/dev/cy/cyreg.h @@ -1,77 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * 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$ - */ - -/* - * 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 Index: sys/dev/cy/cyvar.h =================================================================== --- sys/dev/cy/cyvar.h +++ sys/dev/cy/cyvar.h @@ -1,38 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2004 Bruce D. 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. - * - * 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$ - */ - -typedef u_char volatile *cy_addr; - -extern devclass_t cy_devclass; -extern char cy_driver_name[]; - -void *cyattach_common(cy_addr cy_iobase, int cy_align); -driver_filter_t cyintr; -int cy_units(cy_addr cy_iobase, int cy_align); Index: sys/dev/rc/rc.c =================================================================== --- sys/dev/rc/rc.c +++ sys/dev/rc/rc.c @@ -1,1314 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (C) 1995 by Pavel Antonov, Moscow, Russia. - * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia. - * All rights reserved. - * Copyright (C) 2002 by John Baldwin - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 REGENTS 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$ - */ - -/* - * SDL Communications Riscom/8 (based on Cirrus Logic CL-CD180) driver - * - */ - -/*#define RCDEBUG*/ - -#include "opt_tty.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define IOBASE_ADDRS 14 - -#define rcin(sc, port) RC_IN(sc, port) -#define rcout(sc, port, v) RC_OUT(sc, port, v) - -#define WAITFORCCR(sc, chan) rc_wait0((sc), (chan), __LINE__) - -#define CCRCMD(sc, chan, cmd) do { \ - WAITFORCCR((sc), (chan)); \ - rcout((sc), CD180_CCR, (cmd)); \ -} while (0) - -#define RC_IBUFSIZE 256 -#define RB_I_HIGH_WATER (TTYHOG - 2 * RC_IBUFSIZE) -#define RC_OBUFSIZE 512 -#define RC_IHIGHWATER (3 * RC_IBUFSIZE / 4) -#define INPUT_FLAGS_SHIFT (2 * RC_IBUFSIZE) -#define LOTS_OF_EVENTS 64 - -#define RC_FAKEID 0x10 - -/* Per-channel structure */ -struct rc_chans { - struct rc_softc *rc_rcb; /* back ptr */ - u_short rc_flags; /* Misc. flags */ - int rc_chan; /* Channel # */ - u_char rc_ier; /* intr. enable reg */ - u_char rc_msvr; /* modem sig. status */ - u_char rc_cor2; /* options reg */ - u_char rc_pendcmd; /* special cmd pending */ - u_int rc_dcdwaits; /* how many waits DCD in open */ - struct tty *rc_tp; /* tty struct */ - u_char *rc_iptr; /* Chars input buffer */ - u_char *rc_hiwat; /* hi-water mark */ - u_char *rc_bufend; /* end of buffer */ - u_char *rc_optr; /* ptr in output buf */ - u_char *rc_obufend; /* end of output buf */ - u_char rc_ibuf[4 * RC_IBUFSIZE]; /* input buffer */ - u_char rc_obuf[RC_OBUFSIZE]; /* output buffer */ - struct callout rc_dtrcallout; -}; - -/* Per-board structure */ -struct rc_softc { - device_t sc_dev; - struct resource *sc_irq; - struct resource *sc_port[IOBASE_ADDRS]; - int sc_irqrid; - void *sc_hwicookie; - bus_space_tag_t sc_bt; - bus_space_handle_t sc_bh; - u_int sc_unit; /* unit # */ - u_char sc_dtr; /* DTR status */ - int sc_scheduled_event; - void *sc_swicookie; - struct rc_chans sc_channels[CD180_NCHAN]; /* channels */ -}; - -/* Static prototypes */ -static t_close_t rc_close; -static void rc_break(struct tty *, int); -static void rc_release_resources(device_t dev); -static void rc_intr(void *); -static void rc_hwreset(struct rc_softc *, unsigned int); -static int rc_test(struct rc_softc *); -static void rc_discard_output(struct rc_chans *); -static int rc_modem(struct tty *, int, int); -static void rc_start(struct tty *); -static void rc_stop(struct tty *, int rw); -static int rc_param(struct tty *, struct termios *); -static void rc_pollcard(void *); -static void rc_reinit(struct rc_softc *); -#ifdef RCDEBUG -static void printrcflags(); -#endif -static void rc_wait0(struct rc_softc *sc, int chan, int line); - -static devclass_t rc_devclass; - -/* Flags */ -#define RC_DTR_OFF 0x0001 /* DTR wait, for close/open */ -#define RC_ACTOUT 0x0002 /* Dial-out port active */ -#define RC_RTSFLOW 0x0004 /* RTS flow ctl enabled */ -#define RC_CTSFLOW 0x0008 /* CTS flow ctl enabled */ -#define RC_DORXFER 0x0010 /* RXFER event planned */ -#define RC_DOXXFER 0x0020 /* XXFER event planned */ -#define RC_MODCHG 0x0040 /* Modem status changed */ -#define RC_OSUSP 0x0080 /* Output suspended */ -#define RC_OSBUSY 0x0100 /* start() routine in progress */ -#define RC_WAS_BUFOVFL 0x0200 /* low-level buffer ovferflow */ -#define RC_WAS_SILOVFL 0x0400 /* silo buffer overflow */ -#define RC_SEND_RDY 0x0800 /* ready to send */ - -/* Table for translation of RCSR status bits to internal form */ -static int rc_rcsrt[16] = { - 0, TTY_OE, TTY_FE, - TTY_FE|TTY_OE, TTY_PE, TTY_PE|TTY_OE, - TTY_PE|TTY_FE, TTY_PE|TTY_FE|TTY_OE, TTY_BI, - TTY_BI|TTY_OE, TTY_BI|TTY_FE, TTY_BI|TTY_FE|TTY_OE, - TTY_BI|TTY_PE, TTY_BI|TTY_PE|TTY_OE, TTY_BI|TTY_PE|TTY_FE, - TTY_BI|TTY_PE|TTY_FE|TTY_OE -}; - -static int rc_ports[] = - { 0x220, 0x240, 0x250, 0x260, 0x2a0, 0x2b0, 0x300, 0x320 }; -static int iobase_addrs[IOBASE_ADDRS] = - { 0, 0x400, 0x800, 0xc00, 0x1400, 0x1800, 0x1c00, 0x2000, - 0x3000, 0x3400, 0x3800, 0x3c00, 0x4000, 0x8000 }; - -/**********************************************/ - -static int -rc_probe(device_t dev) -{ - u_int port; - int i, found; - - /* - * We don't know of any PnP ID's for these cards. - */ - if (isa_get_logicalid(dev) != 0) - return (ENXIO); - - /* - * We have to have an IO port hint that is valid. - */ - port = isa_get_port(dev); - if (port == -1) - return (ENXIO); - found = 0; - for (i = 0; i < nitems(rc_ports); i++) - if (rc_ports[i] == port) { - found = 1; - break; - } - if (!found) - return (ENXIO); - - /* - * We have to have an IRQ hint. - */ - if (isa_get_irq(dev) == -1) - return (ENXIO); - - device_set_desc(dev, "SDL Riscom/8"); - return (0); -} - -static int -rc_attach(device_t dev) -{ - struct rc_chans *rc; - struct tty *tp; - struct rc_softc *sc; - u_int port; - int base, chan, error, i, x; - - sc = device_get_softc(dev); - sc->sc_dev = dev; - - /* - * We need to have IO ports. Lots of them. We need - * the following ranges relative to the base port: - * 0x0 - 0x10 - * 0x400 - 0x410 - * 0x800 - 0x810 - * 0xc00 - 0xc10 - * 0x1400 - 0x1410 - * 0x1800 - 0x1810 - * 0x1c00 - 0x1c10 - * 0x2000 - 0x2010 - * 0x3000 - 0x3010 - * 0x3400 - 0x3410 - * 0x3800 - 0x3810 - * 0x3c00 - 0x3c10 - * 0x4000 - 0x4010 - * 0x8000 - 0x8010 - */ - port = isa_get_port(dev); - for (i = 0; i < IOBASE_ADDRS; i++) - if (bus_set_resource(dev, SYS_RES_IOPORT, i, - port + iobase_addrs[i], 0x10) != 0) - return (ENXIO); - error = ENOMEM; - for (i = 0; i < IOBASE_ADDRS; i++) { - x = i; - sc->sc_port[i] = bus_alloc_resource_anywhere(dev, - SYS_RES_IOPORT, &x, 0x10, RF_ACTIVE); - if (x != i) { - device_printf(dev, "ioport %d was rid %d\n", i, x); - goto fail; - } - if (sc->sc_port[i] == NULL) { - device_printf(dev, "failed to alloc ioports %x-%x\n", - port + iobase_addrs[i], - port + iobase_addrs[i] + 0x10); - goto fail; - } - } - sc->sc_bt = rman_get_bustag(sc->sc_port[0]); - sc->sc_bh = rman_get_bushandle(sc->sc_port[0]); - - sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqrid, - RF_ACTIVE); - if (sc->sc_irq == NULL) { - device_printf(dev, "failed to alloc IRQ\n"); - goto fail; - } - - /* - * Now do some actual tests to make sure it works. - */ - error = ENXIO; - rcout(sc, CD180_PPRL, 0x22); /* Random values to Prescale reg. */ - rcout(sc, CD180_PPRH, 0x11); - if (rcin(sc, CD180_PPRL) != 0x22 || rcin(sc, CD180_PPRH) != 0x11) - goto fail; - if (rc_test(sc)) - goto fail; - - /* - * Ok, start actually hooking things up. - */ - sc->sc_unit = device_get_unit(dev); - /*sc->sc_chipid = 0x10 + device_get_unit(dev);*/ - device_printf(dev, "%d chans, firmware rev. %c\n", - CD180_NCHAN, (rcin(sc, CD180_GFRCR) & 0xF) + 'A'); - rc = sc->sc_channels; - base = CD180_NCHAN * sc->sc_unit; - for (chan = 0; chan < CD180_NCHAN; chan++, rc++) { - rc->rc_rcb = sc; - rc->rc_chan = chan; - rc->rc_iptr = rc->rc_ibuf; - rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER]; - rc->rc_optr = rc->rc_obufend = rc->rc_obuf; - callout_init(&rc->rc_dtrcallout, 0); - tp = rc->rc_tp = ttyalloc(); - tp->t_sc = rc; - tp->t_oproc = rc_start; - tp->t_param = rc_param; - tp->t_modem = rc_modem; - tp->t_break = rc_break; - tp->t_close = rc_close; - tp->t_stop = rc_stop; - ttycreate(tp, TS_CALLOUT, "m%d", chan + base); - } - - error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_TTY, NULL, rc_intr, - sc, &sc->sc_hwicookie); - if (error) { - device_printf(dev, "failed to register interrupt handler\n"); - goto fail; - } - - swi_add(&tty_intr_event, "rc", rc_pollcard, sc, SWI_TTY, 0, - &sc->sc_swicookie); - return (0); - -fail: - rc_release_resources(dev); - return (error); -} - -static int -rc_detach(device_t dev) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int error, i; - - sc = device_get_softc(dev); - - rc = sc->sc_channels; - for (i = 0; i < CD180_NCHAN; i++, rc++) - ttyfree(rc->rc_tp); - - error = bus_teardown_intr(dev, sc->sc_irq, sc->sc_hwicookie); - if (error) - device_printf(dev, "failed to deregister interrupt handler\n"); - swi_remove(sc->sc_swicookie); - rc_release_resources(dev); - - return (0); -} - -static void -rc_release_resources(device_t dev) -{ - struct rc_softc *sc; - int i; - - sc = device_get_softc(dev); - if (sc->sc_irq != NULL) { - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid, - sc->sc_irq); - sc->sc_irq = NULL; - } - for (i = 0; i < IOBASE_ADDRS; i++) { - if (sc->sc_port[i] == NULL) - break; - bus_release_resource(dev, SYS_RES_IOPORT, i, sc->sc_port[i]); - sc->sc_port[i] = NULL; - } -} - -/* RC interrupt handling */ -static void -rc_intr(void *arg) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int resid, chan; - u_char val, iack, bsr, ucnt, *optr; - int good_data, t_state; - - sc = (struct rc_softc *)arg; - bsr = ~(rcin(sc, RC_BSR)); - if (!(bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT))) { - device_printf(sc->sc_dev, "extra interrupt\n"); - rcout(sc, CD180_EOIR, 0); - return; - } - - while (bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT)) { -#ifdef RCDEBUG_DETAILED - device_printf(sc->sc_dev, "intr (%p) %s%s%s%s\n", arg, bsr, - (bsr & RC_BSR_TOUT)?"TOUT ":"", - (bsr & RC_BSR_RXINT)?"RXINT ":"", - (bsr & RC_BSR_TXINT)?"TXINT ":"", - (bsr & RC_BSR_MOINT)?"MOINT":""); -#endif - if (bsr & RC_BSR_TOUT) { - device_printf(sc->sc_dev, - "hardware failure, reset board\n"); - rcout(sc, RC_CTOUT, 0); - rc_reinit(sc); - return; - } - if (bsr & RC_BSR_RXINT) { - iack = rcin(sc, RC_PILR_RX); - good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID)); - if (!good_data && iack != (GIVR_IT_REI | RC_FAKEID)) { - device_printf(sc->sc_dev, - "fake rxint: %02x\n", iack); - goto more_intrs; - } - chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); - rc = &sc->sc_channels[chan]; - t_state = rc->rc_tp->t_state; - /* Do RTS flow control stuff */ - if ( (rc->rc_flags & RC_RTSFLOW) - || !(t_state & TS_ISOPEN) - ) { - if ( ( !(t_state & TS_ISOPEN) - || (t_state & TS_TBLOCK) - ) - && (rc->rc_msvr & MSVR_RTS) - ) - rcout(sc, CD180_MSVR, - rc->rc_msvr &= ~MSVR_RTS); - else if (!(rc->rc_msvr & MSVR_RTS)) - rcout(sc, CD180_MSVR, - rc->rc_msvr |= MSVR_RTS); - } - ucnt = rcin(sc, CD180_RDCR) & 0xF; - resid = 0; - - if (t_state & TS_ISOPEN) { - /* check for input buffer overflow */ - if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) { - resid = ucnt; - ucnt = rc->rc_bufend - rc->rc_iptr; - resid -= ucnt; - if (!(rc->rc_flags & RC_WAS_BUFOVFL)) { - rc->rc_flags |= RC_WAS_BUFOVFL; - sc->sc_scheduled_event++; - } - } - optr = rc->rc_iptr; - /* check foor good data */ - if (good_data) { - while (ucnt-- > 0) { - val = rcin(sc, CD180_RDR); - optr[0] = val; - optr[INPUT_FLAGS_SHIFT] = 0; - optr++; - sc->sc_scheduled_event++; - if (val != 0 && val == rc->rc_tp->t_hotchar) - swi_sched(sc->sc_swicookie, 0); - } - } else { - /* Store also status data */ - while (ucnt-- > 0) { - iack = rcin(sc, CD180_RCSR); - if (iack & RCSR_Timeout) - break; - if ( (iack & RCSR_OE) - && !(rc->rc_flags & RC_WAS_SILOVFL)) { - rc->rc_flags |= RC_WAS_SILOVFL; - sc->sc_scheduled_event++; - } - val = rcin(sc, CD180_RDR); - /* - Don't store PE if IGNPAR and BREAK if IGNBRK, - this hack allows "raw" tty optimization - works even if IGN* is set. - */ - if ( !(iack & (RCSR_PE|RCSR_FE|RCSR_Break)) - || ((!(iack & (RCSR_PE|RCSR_FE)) - || !(rc->rc_tp->t_iflag & IGNPAR)) - && (!(iack & RCSR_Break) - || !(rc->rc_tp->t_iflag & IGNBRK)))) { - if ( (iack & (RCSR_PE|RCSR_FE)) - && (t_state & TS_CAN_BYPASS_L_RINT) - && ((iack & RCSR_FE) - || ((iack & RCSR_PE) - && (rc->rc_tp->t_iflag & INPCK)))) - val = 0; - else if (val != 0 && val == rc->rc_tp->t_hotchar) - swi_sched(sc->sc_swicookie, 0); - optr[0] = val; - optr[INPUT_FLAGS_SHIFT] = iack; - optr++; - sc->sc_scheduled_event++; - } - } - } - rc->rc_iptr = optr; - rc->rc_flags |= RC_DORXFER; - } else - resid = ucnt; - /* Clear FIFO if necessary */ - while (resid-- > 0) { - if (!good_data) - iack = rcin(sc, CD180_RCSR); - else - iack = 0; - if (iack & RCSR_Timeout) - break; - (void) rcin(sc, CD180_RDR); - } - goto more_intrs; - } - if (bsr & RC_BSR_MOINT) { - iack = rcin(sc, RC_PILR_MODEM); - if (iack != (GIVR_IT_MSCI | RC_FAKEID)) { - device_printf(sc->sc_dev, "fake moint: %02x\n", - iack); - goto more_intrs; - } - chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); - rc = &sc->sc_channels[chan]; - iack = rcin(sc, CD180_MCR); - rc->rc_msvr = rcin(sc, CD180_MSVR); - rcout(sc, CD180_MCR, 0); -#ifdef RCDEBUG - printrcflags(rc, "moint"); -#endif - if (rc->rc_flags & RC_CTSFLOW) { - if (rc->rc_msvr & MSVR_CTS) - rc->rc_flags |= RC_SEND_RDY; - else - rc->rc_flags &= ~RC_SEND_RDY; - } else - rc->rc_flags |= RC_SEND_RDY; - if ((iack & MCR_CDchg) && !(rc->rc_flags & RC_MODCHG)) { - sc->sc_scheduled_event += LOTS_OF_EVENTS; - rc->rc_flags |= RC_MODCHG; - swi_sched(sc->sc_swicookie, 0); - } - goto more_intrs; - } - if (bsr & RC_BSR_TXINT) { - iack = rcin(sc, RC_PILR_TX); - if (iack != (GIVR_IT_TDI | RC_FAKEID)) { - device_printf(sc->sc_dev, "fake txint: %02x\n", - iack); - goto more_intrs; - } - chan = ((rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH); - rc = &sc->sc_channels[chan]; - if ( (rc->rc_flags & RC_OSUSP) - || !(rc->rc_flags & RC_SEND_RDY) - ) - goto more_intrs; - /* Handle breaks and other stuff */ - if (rc->rc_pendcmd) { - rcout(sc, CD180_COR2, rc->rc_cor2 |= COR2_ETC); - rcout(sc, CD180_TDR, CD180_C_ESC); - rcout(sc, CD180_TDR, rc->rc_pendcmd); - rcout(sc, CD180_COR2, rc->rc_cor2 &= ~COR2_ETC); - rc->rc_pendcmd = 0; - goto more_intrs; - } - optr = rc->rc_optr; - resid = rc->rc_obufend - optr; - if (resid > CD180_NFIFO) - resid = CD180_NFIFO; - while (resid-- > 0) - rcout(sc, CD180_TDR, *optr++); - rc->rc_optr = optr; - - /* output completed? */ - if (optr >= rc->rc_obufend) { - rcout(sc, CD180_IER, rc->rc_ier &= ~IER_TxRdy); -#ifdef RCDEBUG - device_printf(sc->sc_dev, - "channel %d: output completed\n", - rc->rc_chan); -#endif - if (!(rc->rc_flags & RC_DOXXFER)) { - sc->sc_scheduled_event += LOTS_OF_EVENTS; - rc->rc_flags |= RC_DOXXFER; - swi_sched(sc->sc_swicookie, 0); - } - } - } - more_intrs: - rcout(sc, CD180_EOIR, 0); /* end of interrupt */ - rcout(sc, RC_CTOUT, 0); - bsr = ~(rcin(sc, RC_BSR)); - } -} - -/* Feed characters to output buffer */ -static void -rc_start(struct tty *tp) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int s; - - rc = tp->t_sc; - if (rc->rc_flags & RC_OSBUSY) - return; - sc = rc->rc_rcb; - s = spltty(); - rc->rc_flags |= RC_OSBUSY; - critical_enter(); - if (tp->t_state & TS_TTSTOP) - rc->rc_flags |= RC_OSUSP; - else - rc->rc_flags &= ~RC_OSUSP; - /* Do RTS flow control stuff */ - if ( (rc->rc_flags & RC_RTSFLOW) - && (tp->t_state & TS_TBLOCK) - && (rc->rc_msvr & MSVR_RTS) - ) { - rcout(sc, CD180_CAR, rc->rc_chan); - rcout(sc, CD180_MSVR, rc->rc_msvr &= ~MSVR_RTS); - } else if (!(rc->rc_msvr & MSVR_RTS)) { - rcout(sc, CD180_CAR, rc->rc_chan); - rcout(sc, CD180_MSVR, rc->rc_msvr |= MSVR_RTS); - } - critical_exit(); - if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) - goto out; -#ifdef RCDEBUG - printrcflags(rc, "rcstart"); -#endif - ttwwakeup(tp); -#ifdef RCDEBUG - printf("rcstart: outq = %d obuf = %d\n", - tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr); -#endif - if (tp->t_state & TS_BUSY) - goto out; /* output still in progress ... */ - - if (tp->t_outq.c_cc > 0) { - u_int ocnt; - - tp->t_state |= TS_BUSY; - ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf); - critical_enter(); - rc->rc_optr = rc->rc_obuf; - rc->rc_obufend = rc->rc_optr + ocnt; - critical_exit(); - if (!(rc->rc_ier & IER_TxRdy)) { -#ifdef RCDEBUG - device_printf(sc->sc_dev, - "channel %d: rcstart enable txint\n", rc->rc_chan); -#endif - rcout(sc, CD180_CAR, rc->rc_chan); - rcout(sc, CD180_IER, rc->rc_ier |= IER_TxRdy); - } - } -out: - rc->rc_flags &= ~RC_OSBUSY; - (void) splx(s); -} - -/* Handle delayed events. */ -void -rc_pollcard(void *arg) -{ - struct rc_softc *sc; - struct rc_chans *rc; - struct tty *tp; - u_char *tptr, *eptr; - int chan, icnt; - - sc = (struct rc_softc *)arg; - if (sc->sc_scheduled_event == 0) - return; - do { - rc = sc->sc_channels; - for (chan = 0; chan < CD180_NCHAN; rc++, chan++) { - tp = rc->rc_tp; -#ifdef RCDEBUG - if (rc->rc_flags & (RC_DORXFER|RC_DOXXFER|RC_MODCHG| - RC_WAS_BUFOVFL|RC_WAS_SILOVFL)) - printrcflags(rc, "rcevent"); -#endif - if (rc->rc_flags & RC_WAS_BUFOVFL) { - critical_enter(); - rc->rc_flags &= ~RC_WAS_BUFOVFL; - sc->sc_scheduled_event--; - critical_exit(); - device_printf(sc->sc_dev, - "channel %d: interrupt-level buffer overflow\n", - chan); - } - if (rc->rc_flags & RC_WAS_SILOVFL) { - critical_enter(); - rc->rc_flags &= ~RC_WAS_SILOVFL; - sc->sc_scheduled_event--; - critical_exit(); - device_printf(sc->sc_dev, - "channel %d: silo overflow\n", chan); - } - if (rc->rc_flags & RC_MODCHG) { - critical_enter(); - rc->rc_flags &= ~RC_MODCHG; - sc->sc_scheduled_event -= LOTS_OF_EVENTS; - critical_exit(); - ttyld_modem(tp, !!(rc->rc_msvr & MSVR_CD)); - } - if (rc->rc_flags & RC_DORXFER) { - critical_enter(); - rc->rc_flags &= ~RC_DORXFER; - eptr = rc->rc_iptr; - if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) - tptr = &rc->rc_ibuf[RC_IBUFSIZE]; - else - tptr = rc->rc_ibuf; - icnt = eptr - tptr; - if (icnt > 0) { - if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) { - rc->rc_iptr = rc->rc_ibuf; - rc->rc_bufend = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_hiwat = &rc->rc_ibuf[RC_IHIGHWATER]; - } else { - rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_bufend = &rc->rc_ibuf[2 * RC_IBUFSIZE]; - rc->rc_hiwat = - &rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER]; - } - if ( (rc->rc_flags & RC_RTSFLOW) - && (tp->t_state & TS_ISOPEN) - && !(tp->t_state & TS_TBLOCK) - && !(rc->rc_msvr & MSVR_RTS) - ) { - rcout(sc, CD180_CAR, chan); - rcout(sc, CD180_MSVR, - rc->rc_msvr |= MSVR_RTS); - } - sc->sc_scheduled_event -= icnt; - } - critical_exit(); - - if (icnt <= 0 || !(tp->t_state & TS_ISOPEN)) - goto done1; - - if ( (tp->t_state & TS_CAN_BYPASS_L_RINT) - && !(tp->t_state & TS_LOCAL)) { - if ((tp->t_rawq.c_cc + icnt) >= RB_I_HIGH_WATER - && ((rc->rc_flags & RC_RTSFLOW) || (tp->t_iflag & IXOFF)) - && !(tp->t_state & TS_TBLOCK)) - ttyblock(tp); - tk_nin += icnt; - tk_rawcc += icnt; - tp->t_rawcc += icnt; - if (b_to_q(tptr, icnt, &tp->t_rawq)) - device_printf(sc->sc_dev, - "channel %d: tty-level buffer overflow\n", - chan); - 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; - rc_start(tp); - } - } else { - for (; tptr < eptr; tptr++) - ttyld_rint(tp, - (tptr[0] | - rc_rcsrt[tptr[INPUT_FLAGS_SHIFT] & 0xF])); - } -done1: ; - } - if (rc->rc_flags & RC_DOXXFER) { - critical_enter(); - sc->sc_scheduled_event -= LOTS_OF_EVENTS; - rc->rc_flags &= ~RC_DOXXFER; - rc->rc_tp->t_state &= ~TS_BUSY; - critical_exit(); - ttyld_start(tp); - } - if (sc->sc_scheduled_event == 0) - break; - } - } while (sc->sc_scheduled_event >= LOTS_OF_EVENTS); -} - -static void -rc_stop(struct tty *tp, int rw) -{ - struct rc_softc *sc; - struct rc_chans *rc; - u_char *tptr, *eptr; - - rc = tp->t_sc; - sc = rc->rc_rcb; -#ifdef RCDEBUG - device_printf(sc->sc_dev, "channel %d: rc_stop %s%s\n", - rc->rc_chan, (rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":""); -#endif - if (rw & FWRITE) - rc_discard_output(rc); - critical_enter(); - if (rw & FREAD) { - rc->rc_flags &= ~RC_DORXFER; - eptr = rc->rc_iptr; - if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) { - tptr = &rc->rc_ibuf[RC_IBUFSIZE]; - rc->rc_iptr = &rc->rc_ibuf[RC_IBUFSIZE]; - } else { - tptr = rc->rc_ibuf; - rc->rc_iptr = rc->rc_ibuf; - } - sc->sc_scheduled_event -= eptr - tptr; - } - if (tp->t_state & TS_TTSTOP) - rc->rc_flags |= RC_OSUSP; - else - rc->rc_flags &= ~RC_OSUSP; - critical_exit(); -} - -static void -rc_close(struct tty *tp) -{ - struct rc_chans *rc; - struct rc_softc *sc; - int s; - - rc = tp->t_sc; - sc = rc->rc_rcb; - s = spltty(); - rcout(sc, CD180_CAR, rc->rc_chan); - - /* Disable rx/tx intrs */ - rcout(sc, CD180_IER, rc->rc_ier = 0); - if ( (tp->t_cflag & HUPCL) - || (!(rc->rc_flags & RC_ACTOUT) - && !(rc->rc_msvr & MSVR_CD) - && !(tp->t_cflag & CLOCAL)) - || !(tp->t_state & TS_ISOPEN) - ) { - CCRCMD(sc, rc->rc_chan, CCR_ResetChan); - WAITFORCCR(sc, rc->rc_chan); - (void) rc_modem(tp, SER_RTS, 0); - ttydtrwaitstart(tp); - } - rc->rc_flags &= ~RC_ACTOUT; - wakeup( &rc->rc_rcb); /* wake bi */ - wakeup(TSA_CARR_ON(tp)); - (void) splx(s); -} - -/* Reset the bastard */ -static void -rc_hwreset(struct rc_softc *sc, u_int chipid) -{ - CCRCMD(sc, -1, CCR_HWRESET); /* Hardware reset */ - DELAY(20000); - WAITFORCCR(sc, -1); - - rcout(sc, RC_CTOUT, 0); /* Clear timeout */ - rcout(sc, CD180_GIVR, chipid); - rcout(sc, CD180_GICR, 0); - - /* Set Prescaler Registers (1 msec) */ - rcout(sc, CD180_PPRL, ((RC_OSCFREQ + 999) / 1000) & 0xFF); - rcout(sc, CD180_PPRH, ((RC_OSCFREQ + 999) / 1000) >> 8); - - /* Initialize Priority Interrupt Level Registers */ - rcout(sc, CD180_PILR1, RC_PILR_MODEM); - rcout(sc, CD180_PILR2, RC_PILR_TX); - rcout(sc, CD180_PILR3, RC_PILR_RX); - - /* Reset DTR */ - rcout(sc, RC_DTREG, ~0); -} - -/* Set channel parameters */ -static int -rc_param(struct tty *tp, struct termios *ts) -{ - struct rc_softc *sc; - struct rc_chans *rc; - int idivs, odivs, s, val, cflag, iflag, lflag, inpflow; - - if ( ts->c_ospeed < 0 || ts->c_ospeed > 76800 - || ts->c_ispeed < 0 || ts->c_ispeed > 76800 - ) - return (EINVAL); - if (ts->c_ispeed == 0) - ts->c_ispeed = ts->c_ospeed; - odivs = RC_BRD(ts->c_ospeed); - idivs = RC_BRD(ts->c_ispeed); - - rc = tp->t_sc; - sc = rc->rc_rcb; - s = spltty(); - - /* Select channel */ - rcout(sc, CD180_CAR, rc->rc_chan); - - /* If speed == 0, hangup line */ - if (ts->c_ospeed == 0) { - CCRCMD(sc, rc->rc_chan, CCR_ResetChan); - WAITFORCCR(sc, rc->rc_chan); - (void) rc_modem(tp, 0, SER_DTR); - } - - tp->t_state &= ~TS_CAN_BYPASS_L_RINT; - cflag = ts->c_cflag; - iflag = ts->c_iflag; - lflag = ts->c_lflag; - - if (idivs > 0) { - rcout(sc, CD180_RBPRL, idivs & 0xFF); - rcout(sc, CD180_RBPRH, idivs >> 8); - } - if (odivs > 0) { - rcout(sc, CD180_TBPRL, odivs & 0xFF); - rcout(sc, CD180_TBPRH, odivs >> 8); - } - - /* set timeout value */ - if (ts->c_ispeed > 0) { - int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1; - - if ( !(lflag & ICANON) - && ts->c_cc[VMIN] != 0 && ts->c_cc[VTIME] != 0 - && ts->c_cc[VTIME] * 10 > itm) - itm = ts->c_cc[VTIME] * 10; - - rcout(sc, CD180_RTPR, itm <= 255 ? itm : 255); - } - - switch (cflag & CSIZE) { - case CS5: val = COR1_5BITS; break; - case CS6: val = COR1_6BITS; break; - case CS7: val = COR1_7BITS; break; - default: - case CS8: val = COR1_8BITS; break; - } - if (cflag & PARENB) { - val |= COR1_NORMPAR; - if (cflag & PARODD) - val |= COR1_ODDP; - if (!(cflag & INPCK)) - val |= COR1_Ignore; - } else - val |= COR1_Ignore; - if (cflag & CSTOPB) - val |= COR1_2SB; - rcout(sc, CD180_COR1, val); - - /* Set FIFO threshold */ - val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2; - inpflow = 0; - if ( (iflag & IXOFF) - && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE - && ( ts->c_cc[VSTART] != _POSIX_VDISABLE - || (iflag & IXANY) - ) - ) - ) { - inpflow = 1; - val |= COR3_SCDE|COR3_FCT; - } - rcout(sc, CD180_COR3, val); - - /* Initialize on-chip automatic flow control */ - val = 0; - rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY); - if (cflag & CCTS_OFLOW) { - rc->rc_flags |= RC_CTSFLOW; - val |= COR2_CtsAE; - } else - rc->rc_flags |= RC_SEND_RDY; - if (tp->t_state & TS_TTSTOP) - rc->rc_flags |= RC_OSUSP; - else - rc->rc_flags &= ~RC_OSUSP; - if (cflag & CRTS_IFLOW) - rc->rc_flags |= RC_RTSFLOW; - else - rc->rc_flags &= ~RC_RTSFLOW; - - if (inpflow) { - if (ts->c_cc[VSTART] != _POSIX_VDISABLE) - rcout(sc, CD180_SCHR1, ts->c_cc[VSTART]); - rcout(sc, CD180_SCHR2, ts->c_cc[VSTOP]); - val |= COR2_TxIBE; - if (iflag & IXANY) - val |= COR2_IXM; - } - - rcout(sc, CD180_COR2, rc->rc_cor2 = val); - - CCRCMD(sc, rc->rc_chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); - - ttyldoptim(tp); - - /* modem ctl */ - val = cflag & CLOCAL ? 0 : MCOR1_CDzd; - if (cflag & CCTS_OFLOW) - val |= MCOR1_CTSzd; - rcout(sc, CD180_MCOR1, val); - - val = cflag & CLOCAL ? 0 : MCOR2_CDod; - if (cflag & CCTS_OFLOW) - val |= MCOR2_CTSod; - rcout(sc, CD180_MCOR2, val); - - /* enable i/o and interrupts */ - CCRCMD(sc, rc->rc_chan, - CCR_XMTREN | ((cflag & CREAD) ? CCR_RCVREN : CCR_RCVRDIS)); - WAITFORCCR(sc, rc->rc_chan); - - rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD; - if (cflag & CCTS_OFLOW) - rc->rc_ier |= IER_CTS; - if (cflag & CREAD) - rc->rc_ier |= IER_RxData; - if (tp->t_state & TS_BUSY) - rc->rc_ier |= IER_TxRdy; - if (ts->c_ospeed != 0) - rc_modem(tp, SER_DTR, 0); - if ((cflag & CCTS_OFLOW) && (rc->rc_msvr & MSVR_CTS)) - rc->rc_flags |= RC_SEND_RDY; - rcout(sc, CD180_IER, rc->rc_ier); - (void) splx(s); - return 0; -} - -/* Re-initialize board after bogus interrupts */ -static void -rc_reinit(struct rc_softc *sc) -{ - struct rc_chans *rc; - int i; - - rc_hwreset(sc, RC_FAKEID); - rc = sc->sc_channels; - for (i = 0; i < CD180_NCHAN; i++, rc++) - (void) rc_param(rc->rc_tp, &rc->rc_tp->t_termios); -} - -/* Modem control routines */ - -static int -rc_modem(struct tty *tp, int biton, int bitoff) -{ - struct rc_chans *rc; - struct rc_softc *sc; - u_char *dtr; - u_char msvr; - - rc = tp->t_sc; - sc = rc->rc_rcb; - dtr = &sc->sc_dtr; - rcout(sc, CD180_CAR, rc->rc_chan); - - if (biton == 0 && bitoff == 0) { - msvr = rc->rc_msvr = rcin(sc, CD180_MSVR); - - if (msvr & MSVR_RTS) - biton |= SER_RTS; - if (msvr & MSVR_CTS) - biton |= SER_CTS; - if (msvr & MSVR_DSR) - biton |= SER_DSR; - if (msvr & MSVR_DTR) - biton |= SER_DTR; - if (msvr & MSVR_CD) - biton |= SER_DCD; - if (~rcin(sc, RC_RIREG) & (1 << rc->rc_chan)) - biton |= SER_RI; - return biton; - } - if (biton & SER_DTR) - rcout(sc, RC_DTREG, ~(*dtr |= 1 << rc->rc_chan)); - if (bitoff & SER_DTR) - rcout(sc, RC_DTREG, ~(*dtr &= ~(1 << rc->rc_chan))); - msvr = rcin(sc, CD180_MSVR); - if (biton & SER_DTR) - msvr |= MSVR_DTR; - if (bitoff & SER_DTR) - msvr &= ~MSVR_DTR; - if (biton & SER_RTS) - msvr |= MSVR_RTS; - if (bitoff & SER_RTS) - msvr &= ~MSVR_RTS; - rcout(sc, CD180_MSVR, msvr); - return 0; -} - -static void -rc_break(struct tty *tp, int brk) -{ - struct rc_chans *rc; - - rc = tp->t_sc; - - if (brk) - rc->rc_pendcmd = CD180_C_SBRK; - else - rc->rc_pendcmd = CD180_C_EBRK; -} - -#define ERR(s) do { \ - device_printf(sc->sc_dev, "%s", ""); \ - printf s ; \ - printf("\n"); \ - (void) splx(old_level); \ - return 1; \ -} while (0) - -/* Test the board. */ -int -rc_test(struct rc_softc *sc) -{ - int chan = 0; - int i = 0, rcnt, old_level; - unsigned int iack, chipid; - unsigned short divs; - static u_char ctest[] = "\377\125\252\045\244\0\377"; -#define CTLEN 8 - - struct rtest { - u_char txbuf[CD180_NFIFO]; /* TX buffer */ - u_char rxbuf[CD180_NFIFO]; /* RX buffer */ - int rxptr; /* RX pointer */ - int txptr; /* TX pointer */ - } tchans[CD180_NCHAN]; - - old_level = spltty(); - - chipid = RC_FAKEID; - - /* First, reset board to initial state */ - rc_hwreset(sc, chipid); - - divs = RC_BRD(19200); - - /* Initialize channels */ - for (chan = 0; chan < CD180_NCHAN; chan++) { - - /* Select and reset channel */ - rcout(sc, CD180_CAR, chan); - CCRCMD(sc, chan, CCR_ResetChan); - WAITFORCCR(sc, chan); - - /* Set speed */ - rcout(sc, CD180_RBPRL, divs & 0xFF); - rcout(sc, CD180_RBPRH, divs >> 8); - rcout(sc, CD180_TBPRL, divs & 0xFF); - rcout(sc, CD180_TBPRH, divs >> 8); - - /* set timeout value */ - rcout(sc, CD180_RTPR, 0); - - /* Establish local loopback */ - rcout(sc, CD180_COR1, COR1_NOPAR | COR1_8BITS | COR1_1SB); - rcout(sc, CD180_COR2, COR2_LLM); - rcout(sc, CD180_COR3, CD180_NFIFO); - CCRCMD(sc, chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3); - CCRCMD(sc, chan, CCR_RCVREN | CCR_XMTREN); - WAITFORCCR(sc, chan); - rcout(sc, CD180_MSVR, MSVR_RTS); - - /* Fill TXBUF with test data */ - for (i = 0; i < CD180_NFIFO; i++) { - tchans[chan].txbuf[i] = ctest[i]; - tchans[chan].rxbuf[i] = 0; - } - tchans[chan].txptr = tchans[chan].rxptr = 0; - - /* Now, start transmit */ - rcout(sc, CD180_IER, IER_TxMpty|IER_RxData); - } - /* Pseudo-interrupt poll stuff */ - for (rcnt = 10000; rcnt-- > 0; rcnt--) { - i = ~(rcin(sc, RC_BSR)); - if (i & RC_BSR_TOUT) - ERR(("BSR timeout bit set\n")); - else if (i & RC_BSR_TXINT) { - iack = rcin(sc, RC_PILR_TX); - if (iack != (GIVR_IT_TDI | chipid)) - ERR(("Bad TX intr ack (%02x != %02x)\n", - iack, GIVR_IT_TDI | chipid)); - chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH; - /* If no more data to transmit, disable TX intr */ - if (tchans[chan].txptr >= CD180_NFIFO) { - iack = rcin(sc, CD180_IER); - rcout(sc, CD180_IER, iack & ~IER_TxMpty); - } else { - for (iack = tchans[chan].txptr; - iack < CD180_NFIFO; iack++) - rcout(sc, CD180_TDR, - tchans[chan].txbuf[iack]); - tchans[chan].txptr = iack; - } - rcout(sc, CD180_EOIR, 0); - } else if (i & RC_BSR_RXINT) { - u_char ucnt; - - iack = rcin(sc, RC_PILR_RX); - if (iack != (GIVR_IT_RGDI | chipid) && - iack != (GIVR_IT_REI | chipid)) - ERR(("Bad RX intr ack (%02x != %02x)\n", - iack, GIVR_IT_RGDI | chipid)); - chan = (rcin(sc, CD180_GICR) & GICR_CHAN) >> GICR_LSH; - ucnt = rcin(sc, CD180_RDCR) & 0xF; - while (ucnt-- > 0) { - iack = rcin(sc, CD180_RCSR); - if (iack & RCSR_Timeout) - break; - if (iack & 0xF) - ERR(("Bad char chan %d (RCSR = %02X)\n", - chan, iack)); - if (tchans[chan].rxptr > CD180_NFIFO) - ERR(("Got extra chars chan %d\n", - chan)); - tchans[chan].rxbuf[tchans[chan].rxptr++] = - rcin(sc, CD180_RDR); - } - rcout(sc, CD180_EOIR, 0); - } - rcout(sc, RC_CTOUT, 0); - for (iack = chan = 0; chan < CD180_NCHAN; chan++) - if (tchans[chan].rxptr >= CD180_NFIFO) - iack++; - if (iack == CD180_NCHAN) - break; - } - for (chan = 0; chan < CD180_NCHAN; chan++) { - /* Select and reset channel */ - rcout(sc, CD180_CAR, chan); - CCRCMD(sc, chan, CCR_ResetChan); - } - - if (!rcnt) - ERR(("looses characters during local loopback\n")); - /* Now, check data */ - for (chan = 0; chan < CD180_NCHAN; chan++) - for (i = 0; i < CD180_NFIFO; i++) - if (ctest[i] != tchans[chan].rxbuf[i]) - ERR(("data mismatch chan %d ptr %d (%d != %d)\n", - chan, i, ctest[i], tchans[chan].rxbuf[i])); - (void) splx(old_level); - return 0; -} - -#ifdef RCDEBUG -static void -printrcflags(struct rc_chans *rc, char *comment) -{ - struct rc_softc *sc; - u_short f = rc->rc_flags; - - sc = rc->rc_rcb; - printf("rc%d/%d: %s flags: %s%s%s%s%s%s%s%s%s%s%s%s\n", - rc->rc_rcb->rcb_unit, rc->rc_chan, comment, - (f & RC_DTR_OFF)?"DTR_OFF " :"", - (f & RC_ACTOUT) ?"ACTOUT " :"", - (f & RC_RTSFLOW)?"RTSFLOW " :"", - (f & RC_CTSFLOW)?"CTSFLOW " :"", - (f & RC_DORXFER)?"DORXFER " :"", - (f & RC_DOXXFER)?"DOXXFER " :"", - (f & RC_MODCHG) ?"MODCHG " :"", - (f & RC_OSUSP) ?"OSUSP " :"", - (f & RC_OSBUSY) ?"OSBUSY " :"", - (f & RC_WAS_BUFOVFL) ?"BUFOVFL " :"", - (f & RC_WAS_SILOVFL) ?"SILOVFL " :"", - (f & RC_SEND_RDY) ?"SEND_RDY":""); - - rcout(sc, CD180_CAR, rc->rc_chan); - - printf("rc%d/%d: msvr %02x ier %02x ccsr %02x\n", - rc->rc_rcb->rcb_unit, rc->rc_chan, - rcin(sc, CD180_MSVR), - rcin(sc, CD180_IER), - rcin(sc, CD180_CCSR)); -} -#endif /* RCDEBUG */ - -static void -rc_discard_output(struct rc_chans *rc) -{ - critical_enter(); - if (rc->rc_flags & RC_DOXXFER) { - rc->rc_rcb->sc_scheduled_event -= LOTS_OF_EVENTS; - rc->rc_flags &= ~RC_DOXXFER; - } - rc->rc_optr = rc->rc_obufend; - rc->rc_tp->t_state &= ~TS_BUSY; - critical_exit(); - ttwwakeup(rc->rc_tp); -} - -static void -rc_wait0(struct rc_softc *sc, int chan, int line) -{ - int rcnt; - - for (rcnt = 50; rcnt && rcin(sc, CD180_CCR); rcnt--) - DELAY(30); - if (rcnt == 0) - device_printf(sc->sc_dev, - "channel %d command timeout, rc.c line: %d\n", chan, line); -} - -static device_method_t rc_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rc_probe), - DEVMETHOD(device_attach, rc_attach), - DEVMETHOD(device_detach, rc_detach), - { 0, 0 } -}; - -static driver_t rc_driver = { - "rc", - rc_methods, sizeof(struct rc_softc), -}; - -DRIVER_MODULE(rc, isa, rc_driver, rc_devclass, 0, 0); Index: sys/dev/rc/rcreg.h =================================================================== --- sys/dev/rc/rcreg.h +++ sys/dev/rc/rcreg.h @@ -1,72 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (C) 1995 by Pavel Antonov, Moscow, Russia. - * Copyright (C) 1995 by Andrey A. Chernov, Moscow, Russia. - * All rights reserved. - * Copyright (C) 2002 by John Baldwin - * - * 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 REGENTS 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$ - */ - -/* - * Cirrus Logic CD180 -based RISCom/8 board definitions - */ - -/* Oscillator frequency - 19660.08Mhz / 2 */ -#define RC_OSCFREQ 9830400 - -#define RC_BRD(s) ((s) == 0 ? 0 : \ - (((RC_OSCFREQ + (s) / 2) / (s)) + CD180_CTICKS/2) / CD180_CTICKS) - -/* Riscom/8 board ISA I/O mapping */ -#define RC_IOMAP(r) ((((r) & 07) << 1) | (((r) & ~07) << 7)) - -/* I/O commands */ -#define RC_OUT(sc, addr, value) \ - bus_space_write_1((sc)->sc_bt, (sc)->sc_bh, RC_IOMAP(addr), (value)) -#define RC_IN(sc, addr) \ - bus_space_read_1((sc)->sc_bt, (sc)->sc_bh, RC_IOMAP(addr)) - -/* Riscom on-board registers (mapping assumed) */ -#define RC_RIREG 0x100 /* Ring Indicator Register (read-only) */ -#define RC_DTREG 0x100 /* DTR Register (write-only) */ -#define RC_BSR 0x101 /* Board Status Register (read-only) */ -#define RC_CTOUT 0x101 /* Clear Timeout (write-only) */ - -/* Board Status Register */ -#define RC_BSR_TOUT 0x08 /* Timeout */ -#define RC_BSR_RXINT 0x04 /* Receiver Interrupt */ -#define RC_BSR_TXINT 0x02 /* Transmitter Interrupt */ -#define RC_BSR_MOINT 0x01 /* Modem Control Interrupt */ - -/* Interrupt groups */ -#define RC_MODEMGRP 0x01 /* Modem interrupt group */ -#define RC_RXGRP 0x02 /* Receiver interrupt group */ -#define RC_TXGRP 0x04 /* Transmitter interrupt group */ - -/* Priority Interrupt Level definitions */ -#define RC_PILR_MODEM (0x80 | RC_MODEMGRP) -#define RC_PILR_RX (0x80 | RC_RXGRP ) -#define RC_PILR_TX (0x80 | RC_TXGRP ) Index: sys/dev/rp/rp.c =================================================================== --- sys/dev/rp/rp.c +++ sys/dev/rp/rp.c @@ -1,1113 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -/* - * rp.c - for RocketPort FreeBSD - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ROCKET_C -#include -#include - -static const char RocketPortVersion[] = "3.02"; - -static Byte_t RData[RDATASIZE] = -{ - 0x00, 0x09, 0xf6, 0x82, - 0x02, 0x09, 0x86, 0xfb, - 0x04, 0x09, 0x00, 0x0a, - 0x06, 0x09, 0x01, 0x0a, - 0x08, 0x09, 0x8a, 0x13, - 0x0a, 0x09, 0xc5, 0x11, - 0x0c, 0x09, 0x86, 0x85, - 0x0e, 0x09, 0x20, 0x0a, - 0x10, 0x09, 0x21, 0x0a, - 0x12, 0x09, 0x41, 0xff, - 0x14, 0x09, 0x82, 0x00, - 0x16, 0x09, 0x82, 0x7b, - 0x18, 0x09, 0x8a, 0x7d, - 0x1a, 0x09, 0x88, 0x81, - 0x1c, 0x09, 0x86, 0x7a, - 0x1e, 0x09, 0x84, 0x81, - 0x20, 0x09, 0x82, 0x7c, - 0x22, 0x09, 0x0a, 0x0a -}; - -static Byte_t RRegData[RREGDATASIZE]= -{ - 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */ - 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */ - 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */ - 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */ - 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */ - 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */ - 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */ - 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */ - 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */ - 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */ - 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */ - 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */ - 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */ -}; - -#if 0 -/* IRQ number to MUDBAC register 2 mapping */ -Byte_t sIRQMap[16] = -{ - 0,0,0,0x10,0x20,0x30,0,0,0,0x40,0x50,0x60,0x70,0,0,0x80 -}; -#endif - -Byte_t rp_sBitMapClrTbl[8] = -{ - 0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f -}; - -Byte_t rp_sBitMapSetTbl[8] = -{ - 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 -}; - -static void rpfree(void *); - -/*************************************************************************** -Function: sReadAiopID -Purpose: Read the AIOP idenfication number directly from an AIOP. -Call: sReadAiopID(CtlP, aiop) - CONTROLLER_T *CtlP; Ptr to controller structure - int aiop: AIOP index -Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X - is replace by an identifying number. - Flag AIOPID_NULL if no valid AIOP is found -Warnings: No context switches are allowed while executing this function. - -*/ -int sReadAiopID(CONTROLLER_T *CtlP, int aiop) -{ - Byte_t AiopID; /* ID byte from AIOP */ - - rp_writeaiop1(CtlP, aiop, _CMD_REG, RESET_ALL); /* reset AIOP */ - rp_writeaiop1(CtlP, aiop, _CMD_REG, 0x0); - AiopID = rp_readaiop1(CtlP, aiop, _CHN_STAT0) & 0x07; - if(AiopID == 0x06) - return(1); - else /* AIOP does not exist */ - return(-1); -} - -/*************************************************************************** -Function: sReadAiopNumChan -Purpose: Read the number of channels available in an AIOP directly from - an AIOP. -Call: sReadAiopNumChan(CtlP, aiop) - CONTROLLER_T *CtlP; Ptr to controller structure - int aiop: AIOP index -Return: int: The number of channels available -Comments: The number of channels is determined by write/reads from identical - offsets within the SRAM address spaces for channels 0 and 4. - If the channel 4 space is mirrored to channel 0 it is a 4 channel - AIOP, otherwise it is an 8 channel. -Warnings: No context switches are allowed while executing this function. -*/ -int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop) -{ - Word_t x, y; - - rp_writeaiop4(CtlP, aiop, _INDX_ADDR,0x12340000L); /* write to chan 0 SRAM */ - rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0); /* read from SRAM, chan 0 */ - x = rp_readaiop2(CtlP, aiop, _INDX_DATA); - rp_writeaiop2(CtlP, aiop, _INDX_ADDR,0x4000); /* read from SRAM, chan 4 */ - y = rp_readaiop2(CtlP, aiop, _INDX_DATA); - if(x != y) /* if different must be 8 chan */ - return(8); - else - return(4); -} - -/*************************************************************************** -Function: sInitChan -Purpose: Initialization of a channel and channel structure -Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) - CONTROLLER_T *CtlP; Ptr to controller structure - CHANNEL_T *ChP; Ptr to channel structure - int AiopNum; AIOP number within controller - int ChanNum; Channel number within AIOP -Return: int: TRUE if initialization succeeded, FALSE if it fails because channel - number exceeds number of channels available in AIOP. -Comments: This function must be called before a channel can be used. -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. -*/ -int sInitChan( CONTROLLER_T *CtlP, - CHANNEL_T *ChP, - int AiopNum, - int ChanNum) -{ - int i, ChOff; - Byte_t *ChR; - static Byte_t R[4]; - - if(ChanNum >= CtlP->AiopNumChan[AiopNum]) - return(FALSE); /* exceeds num chans in AIOP */ - - /* Channel, AIOP, and controller identifiers */ - ChP->CtlP = CtlP; - ChP->ChanID = CtlP->AiopID[AiopNum]; - ChP->AiopNum = AiopNum; - ChP->ChanNum = ChanNum; - - /* Initialize the channel from the RData array */ - for(i=0; i < RDATASIZE; i+=4) - { - R[0] = RData[i]; - R[1] = RData[i+1] + 0x10 * ChanNum; - R[2] = RData[i+2]; - R[3] = RData[i+3]; - rp_writech4(ChP,_INDX_ADDR,le32dec(R)); - } - - ChR = ChP->R; - for(i=0; i < RREGDATASIZE; i+=4) - { - ChR[i] = RRegData[i]; - ChR[i+1] = RRegData[i+1] + 0x10 * ChanNum; - ChR[i+2] = RRegData[i+2]; - ChR[i+3] = RRegData[i+3]; - } - - /* Indexed registers */ - ChOff = (Word_t)ChanNum * 0x1000; - - ChP->BaudDiv[0] = (Byte_t)(ChOff + _BAUD); - ChP->BaudDiv[1] = (Byte_t)((ChOff + _BAUD) >> 8); - ChP->BaudDiv[2] = (Byte_t)BRD9600; - ChP->BaudDiv[3] = (Byte_t)(BRD9600 >> 8); - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->BaudDiv)); - - ChP->TxControl[0] = (Byte_t)(ChOff + _TX_CTRL); - ChP->TxControl[1] = (Byte_t)((ChOff + _TX_CTRL) >> 8); - ChP->TxControl[2] = 0; - ChP->TxControl[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); - - ChP->RxControl[0] = (Byte_t)(ChOff + _RX_CTRL); - ChP->RxControl[1] = (Byte_t)((ChOff + _RX_CTRL) >> 8); - ChP->RxControl[2] = 0; - ChP->RxControl[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); - - ChP->TxEnables[0] = (Byte_t)(ChOff + _TX_ENBLS); - ChP->TxEnables[1] = (Byte_t)((ChOff + _TX_ENBLS) >> 8); - ChP->TxEnables[2] = 0; - ChP->TxEnables[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxEnables)); - - ChP->TxCompare[0] = (Byte_t)(ChOff + _TXCMP1); - ChP->TxCompare[1] = (Byte_t)((ChOff + _TXCMP1) >> 8); - ChP->TxCompare[2] = 0; - ChP->TxCompare[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxCompare)); - - ChP->TxReplace1[0] = (Byte_t)(ChOff + _TXREP1B1); - ChP->TxReplace1[1] = (Byte_t)((ChOff + _TXREP1B1) >> 8); - ChP->TxReplace1[2] = 0; - ChP->TxReplace1[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace1)); - - ChP->TxReplace2[0] = (Byte_t)(ChOff + _TXREP2); - ChP->TxReplace2[1] = (Byte_t)((ChOff + _TXREP2) >> 8); - ChP->TxReplace2[2] = 0; - ChP->TxReplace2[3] = 0; - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxReplace2)); - - ChP->TxFIFOPtrs = ChOff + _TXF_OUTP; - ChP->TxFIFO = ChOff + _TX_FIFO; - - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESTXFCNT); /* apply reset Tx FIFO count */ - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Tx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - rp_writech2(ChP,_INDX_DATA,0); - ChP->RxFIFOPtrs = ChOff + _RXF_OUTP; - ChP->RxFIFO = ChOff + _RX_FIFO; - - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum | RESRXFCNT); /* apply reset Rx FIFO count */ - rp_writech1(ChP,_CMD_REG,(Byte_t)ChanNum); /* remove reset Rx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ - rp_writech2(ChP,_INDX_DATA,0); - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - rp_writech2(ChP,_INDX_DATA,0); - ChP->TxPrioCnt = ChOff + _TXP_CNT; - rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); - rp_writech1(ChP,_INDX_DATA,0); - ChP->TxPrioPtr = ChOff + _TXP_PNTR; - rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioPtr); - rp_writech1(ChP,_INDX_DATA,0); - ChP->TxPrioBuf = ChOff + _TXP_BUF; - sEnRxProcessor(ChP); /* start the Rx processor */ - - return(TRUE); -} - -/*************************************************************************** -Function: sStopRxProcessor -Purpose: Stop the receive processor from processing a channel. -Call: sStopRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure - -Comments: The receive processor can be started again with sStartRxProcessor(). - This function causes the receive processor to skip over the - stopped channel. It does not stop it from processing other channels. - -Warnings: No context switches are allowed while executing this function. - - Do not leave the receive processor stopped for more than one - character time. - - After calling this function a delay of 4 uS is required to ensure - that the receive processor is no longer processing this channel. -*/ -void sStopRxProcessor(CHANNEL_T *ChP) -{ - Byte_t R[4]; - - R[0] = ChP->R[0]; - R[1] = ChP->R[1]; - R[2] = 0x0a; - R[3] = ChP->R[3]; - rp_writech4(ChP,_INDX_ADDR,le32dec(R)); -} - -/*************************************************************************** -Function: sFlushRxFIFO -Purpose: Flush the Rx FIFO -Call: sFlushRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -void sFlushRxFIFO(CHANNEL_T *ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ - - if(sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ - return; /* don't need to flush */ - - RxFIFOEnabled = FALSE; - if(ChP->R[0x32] == 0x08) /* Rx FIFO is enabled */ - { - RxFIFOEnabled = TRUE; - sDisRxFIFO(ChP); /* disable it */ - for(i=0; i < 2000/200; i++) /* delay 2 uS to allow proc to disable FIFO*/ - rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ - } - sGetChanStatus(ChP); /* clear any pending Rx errors in chan stat */ - Ch = (Byte_t)sGetChanNum(ChP); - rp_writech1(ChP,_CMD_REG,Ch | RESRXFCNT); /* apply reset Rx FIFO count */ - rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Rx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs); /* clear Rx out ptr */ - rp_writech2(ChP,_INDX_DATA,0); - rp_writech2(ChP,_INDX_ADDR,ChP->RxFIFOPtrs + 2); /* clear Rx in ptr */ - rp_writech2(ChP,_INDX_DATA,0); - if(RxFIFOEnabled) - sEnRxFIFO(ChP); /* enable Rx FIFO */ -} - -/*************************************************************************** -Function: sFlushTxFIFO -Purpose: Flush the Tx FIFO -Call: sFlushTxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: void -Comments: To prevent data from being enqueued or dequeued in the Tx FIFO - while it is being flushed the receive processor is stopped - and the transmitter is disabled. After these operations a - 4 uS delay is done before clearing the pointers to allow - the receive processor to stop. These items are handled inside - this function. -Warnings: No context switches are allowed while executing this function. -*/ -void sFlushTxFIFO(CHANNEL_T *ChP) -{ - int i; - Byte_t Ch; /* channel number within AIOP */ - int TxEnabled; /* TRUE if transmitter enabled */ - - if(sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ - return; /* don't need to flush */ - - TxEnabled = FALSE; - if(ChP->TxControl[3] & TX_ENABLE) - { - TxEnabled = TRUE; - sDisTransmit(ChP); /* disable transmitter */ - } - sStopRxProcessor(ChP); /* stop Rx processor */ - for(i = 0; i < 4000/200; i++) /* delay 4 uS to allow proc to stop */ - rp_readch1(ChP,_INT_CHAN); /* depends on bus i/o timing */ - Ch = (Byte_t)sGetChanNum(ChP); - rp_writech1(ChP,_CMD_REG,Ch | RESTXFCNT); /* apply reset Tx FIFO count */ - rp_writech1(ChP,_CMD_REG,Ch); /* remove reset Tx FIFO count */ - rp_writech2(ChP,_INDX_ADDR,ChP->TxFIFOPtrs); /* clear Tx in/out ptrs */ - rp_writech2(ChP,_INDX_DATA,0); - if(TxEnabled) - sEnTransmit(ChP); /* enable transmitter */ - sStartRxProcessor(ChP); /* restart Rx processor */ -} - -/*************************************************************************** -Function: sWriteTxPrioByte -Purpose: Write a byte of priority transmit data to a channel -Call: sWriteTxPrioByte(ChP,Data) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Data; The transmit data byte - -Return: int: 1 if the bytes is successfully written, otherwise 0. - -Comments: The priority byte is transmitted before any data in the Tx FIFO. - -Warnings: No context switches are allowed while executing this function. -*/ -int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data) -{ - Byte_t DWBuf[4]; /* buffer for double word writes */ - - if(sGetTxCnt(ChP) > 1) /* write it to Tx priority buffer */ - { - rp_writech2(ChP,_INDX_ADDR,ChP->TxPrioCnt); /* get priority buffer status */ - if(rp_readch1(ChP,_INDX_DATA) & PRI_PEND) /* priority buffer busy */ - return(0); /* nothing sent */ - - le16enc(DWBuf,ChP->TxPrioBuf); /* data byte address */ - - DWBuf[2] = Data; /* data byte value */ - DWBuf[3] = 0; /* priority buffer pointer */ - rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */ - - le16enc(DWBuf,ChP->TxPrioCnt); /* Tx priority count address */ - - DWBuf[2] = PRI_PEND + 1; /* indicate 1 byte pending */ - DWBuf[3] = 0; /* priority buffer pointer */ - rp_writech4(ChP,_INDX_ADDR,le32dec(DWBuf)); /* write it out */ - } - else /* write it to Tx FIFO */ - { - sWriteTxByte(ChP,sGetTxRxDataIO(ChP),Data); - } - return(1); /* 1 byte sent */ -} - -/*************************************************************************** -Function: sEnInterrupts -Purpose: Enable one or more interrupts for a channel -Call: sEnInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt enable flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Allow channel interrupt signal to the AIOP's - Interrupt Channel Register. -Return: void -Comments: If an interrupt enable flag is set in Flags, that interrupt will be - enabled. If an interrupt enable flag is not set in Flags, that - interrupt will not be changed. Interrupts can be disabled with - function sDisInterrupts(). - - This function sets the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This allows - this channel's bit to be set in the AIOP's Interrupt Channel Register. - - Interrupts must also be globally enabled before channel interrupts - will be passed on to the host. This is done with function - sEnGlobalInt(). - - In some cases it may be desirable to disable interrupts globally but - enable channel interrupts. This would allow the global interrupt - status register to be used to determine which AIOPs need service. -*/ -void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] |= - ((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); - - ChP->TxControl[2] |= ((Byte_t)Flags & TXINT_EN); - - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); - - if(Flags & CHANINT_EN) - { - Mask = rp_readch1(ChP,_INT_MASK) | rp_sBitMapSetTbl[ChP->ChanNum]; - rp_writech1(ChP,_INT_MASK,Mask); - } -} - -/*************************************************************************** -Function: sDisInterrupts -Purpose: Disable one or more interrupts for a channel -Call: sDisInterrupts(ChP,Flags) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Flags: Interrupt flags, can be any combination - of the following flags: - TXINT_EN: Interrupt on Tx FIFO empty - RXINT_EN: Interrupt on Rx FIFO at trigger level (see - sSetRxTrigger()) - SRCINT_EN: Interrupt on SRC (Special Rx Condition) - MCINT_EN: Interrupt on modem input change - CHANINT_EN: Disable channel interrupt signal to the - AIOP's Interrupt Channel Register. -Return: void -Comments: If an interrupt flag is set in Flags, that interrupt will be - disabled. If an interrupt flag is not set in Flags, that - interrupt will not be changed. Interrupts can be enabled with - function sEnInterrupts(). - - This function clears the appropriate bit for the channel in the AIOP's - Interrupt Mask Register if the CHANINT_EN flag is set. This blocks - this channel's bit from being set in the AIOP's Interrupt Channel - Register. -*/ -void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags) -{ - Byte_t Mask; /* Interrupt Mask Register */ - - ChP->RxControl[2] &= - ~((Byte_t)Flags & (RXINT_EN | SRCINT_EN | MCINT_EN)); - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->RxControl)); - ChP->TxControl[2] &= ~((Byte_t)Flags & TXINT_EN); - rp_writech4(ChP,_INDX_ADDR,le32dec(ChP->TxControl)); - - if(Flags & CHANINT_EN) - { - Mask = rp_readch1(ChP,_INT_MASK) & rp_sBitMapClrTbl[ChP->ChanNum]; - rp_writech1(ChP,_INT_MASK,Mask); - } -} - -/********************************************************************* - Begin FreeBsd-specific driver code -**********************************************************************/ - -#define POLL_INTERVAL (hz / 100) - -#define RP_ISMULTIPORT(dev) ((dev)->id_flags & 0x1) -#define RP_MPMASTER(dev) (((dev)->id_flags >> 8) & 0xff) -#define RP_NOTAST4(dev) ((dev)->id_flags & 0x04) - -/* - * The top-level routines begin here - */ - -static void rpclose(struct tty *tp); -static void rphardclose(struct tty *tp); -static int rpmodem(struct tty *, int, int); -static int rpparam(struct tty *, struct termios *); -static void rpstart(struct tty *); -static int rpioctl(struct tty *, u_long, caddr_t, struct thread *); -static int rpopen(struct tty *); - -static void rp_do_receive(struct rp_port *rp, struct tty *tp, - CHANNEL_t *cp, unsigned int ChanStatus) -{ - unsigned int CharNStat; - int ToRecv, ch, err = 0; - - ToRecv = sGetRxCnt(cp); - if(ToRecv == 0) - return; - -/* If status indicates there are errored characters in the - FIFO, then enter status mode (a word in FIFO holds - characters and status) -*/ - - if(ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) { - if(!(ChanStatus & STATMODE)) { - ChanStatus |= STATMODE; - sEnRxStatusMode(cp); - } - } -/* - if we previously entered status mode then read down the - FIFO one word at a time, pulling apart the character and - the status. Update error counters depending on status. -*/ - tty_lock(tp); - if(ChanStatus & STATMODE) { - while(ToRecv) { - CharNStat = rp_readch2(cp,sGetTxRxDataIO(cp)); - ch = CharNStat & 0xff; - - if((CharNStat & STMBREAK) || (CharNStat & STMFRAMEH)) - err |= TRE_FRAMING; - else if (CharNStat & STMPARITYH) - err |= TRE_PARITY; - else if (CharNStat & STMRCVROVRH) { - rp->rp_overflows++; - err |= TRE_OVERRUN; - } - - ttydisc_rint(tp, ch, err); - ToRecv--; - } -/* - After emtying FIFO in status mode, turn off status mode -*/ - - if(sGetRxCnt(cp) == 0) { - sDisRxStatusMode(cp); - } - } else { - ToRecv = sGetRxCnt(cp); - while (ToRecv) { - ch = rp_readch1(cp,sGetTxRxDataIO(cp)); - ttydisc_rint(tp, ch & 0xff, err); - ToRecv--; - } - } - ttydisc_rint_done(tp); - tty_unlock(tp); -} - -static void rp_handle_port(struct rp_port *rp) -{ - CHANNEL_t *cp; - struct tty *tp; - unsigned int IntMask, ChanStatus; - - if(!rp) - return; - - cp = &rp->rp_channel; - tp = rp->rp_tty; - IntMask = sGetChanIntID(cp); - IntMask = IntMask & rp->rp_intmask; - ChanStatus = sGetChanStatus(cp); - if(IntMask & RXF_TRIG) - rp_do_receive(rp, tp, cp, ChanStatus); - if(IntMask & DELTA_CD) { - if(ChanStatus & CD_ACT) { - (void)ttydisc_modem(tp, 1); - } else { - (void)ttydisc_modem(tp, 0); - } - } -/* oldcts = rp->rp_cts; - rp->rp_cts = ((ChanStatus & CTS_ACT) != 0); - if(oldcts != rp->rp_cts) { - printf("CTS change (now %s)... on port %d\n", rp->rp_cts ? "on" : "off", rp->rp_port); - } -*/ -} - -static void rp_do_poll(void *arg) -{ - CONTROLLER_t *ctl; - struct rp_port *rp; - struct tty *tp; - int count; - unsigned char CtlMask, AiopMask; - - rp = arg; - tp = rp->rp_tty; - tty_assert_locked(tp); - ctl = rp->rp_ctlp; - CtlMask = ctl->ctlmask(ctl); - if (CtlMask & (1 << rp->rp_aiop)) { - AiopMask = sGetAiopIntStatus(ctl, rp->rp_aiop); - if (AiopMask & (1 << rp->rp_chan)) { - rp_handle_port(rp); - } - } - - count = sGetTxCnt(&rp->rp_channel); - if (count >= 0 && (count <= rp->rp_restart)) { - rpstart(tp); - } - callout_schedule(&rp->rp_timer, POLL_INTERVAL); -} - -static struct ttydevsw rp_tty_class = { - .tsw_flags = TF_INITLOCK|TF_CALLOUT, - .tsw_open = rpopen, - .tsw_close = rpclose, - .tsw_outwakeup = rpstart, - .tsw_ioctl = rpioctl, - .tsw_param = rpparam, - .tsw_modem = rpmodem, - .tsw_free = rpfree, -}; - - -static void -rpfree(void *softc) -{ - struct rp_port *rp = softc; - CONTROLLER_t *ctlp = rp->rp_ctlp; - - atomic_subtract_32(&ctlp->free, 1); -} - -int -rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports) -{ - int unit; - int num_chan; - int aiop, chan, port; - int ChanStatus; - int retval; - struct rp_port *rp; - struct tty *tp; - - unit = device_get_unit(ctlp->dev); - - printf("RocketPort%d (Version %s) %d ports.\n", unit, - RocketPortVersion, num_ports); - - ctlp->num_ports = num_ports; - ctlp->rp = rp = (struct rp_port *) - malloc(sizeof(struct rp_port) * num_ports, M_DEVBUF, M_NOWAIT | M_ZERO); - if (rp == NULL) { - device_printf(ctlp->dev, "rp_attachcommon: Could not malloc rp_ports structures.\n"); - retval = ENOMEM; - goto nogo; - } - - port = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - num_chan = sGetAiopNumChan(ctlp, aiop); - for(chan=0; chan < num_chan; chan++, port++, rp++) { - rp->rp_tty = tp = tty_alloc(&rp_tty_class, rp); - callout_init_mtx(&rp->rp_timer, tty_getlock(tp), 0); - rp->rp_port = port; - rp->rp_ctlp = ctlp; - rp->rp_unit = unit; - rp->rp_chan = chan; - rp->rp_aiop = aiop; - - rp->rp_intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | - DELTA_CD | DELTA_CTS | DELTA_DSR; -#ifdef notdef - ChanStatus = sGetChanStatus(&rp->rp_channel); -#endif /* notdef */ - if(sInitChan(ctlp, &rp->rp_channel, aiop, chan) == 0) { - device_printf(ctlp->dev, "RocketPort sInitChan(%d, %d, %d) failed.\n", - unit, aiop, chan); - retval = ENXIO; - goto nogo; - } - ChanStatus = sGetChanStatus(&rp->rp_channel); - rp->rp_cts = (ChanStatus & CTS_ACT) != 0; - tty_makedev(tp, NULL, "R%r%r", unit, port); - } - } - - mtx_init(&ctlp->hwmtx, "rp_hwmtx", NULL, MTX_DEF); - ctlp->hwmtx_init = 1; - return (0); - -nogo: - rp_releaseresource(ctlp); - - return (retval); -} - -void -rp_releaseresource(CONTROLLER_t *ctlp) -{ - struct rp_port *rp; - int i; - - if (ctlp->rp != NULL) { - for (i = 0; i < ctlp->num_ports; i++) { - rp = ctlp->rp + i; - atomic_add_32(&ctlp->free, 1); - tty_lock(rp->rp_tty); - tty_rel_gone(rp->rp_tty); - } - free(ctlp->rp, M_DEVBUF); - ctlp->rp = NULL; - } - - while (ctlp->free != 0) { - pause("rpwt", hz / 10); - } - - if (ctlp->hwmtx_init) - mtx_destroy(&ctlp->hwmtx); -} - -static int -rpopen(struct tty *tp) -{ - struct rp_port *rp; - int flags; - unsigned int IntMask, ChanStatus; - - rp = tty_softc(tp); - - flags = 0; - flags |= SET_RTS; - flags |= SET_DTR; - rp->rp_channel.TxControl[3] = - ((rp->rp_channel.TxControl[3] - & ~(SET_RTS | SET_DTR)) | flags); - rp_writech4(&rp->rp_channel,_INDX_ADDR, - le32dec(rp->rp_channel.TxControl)); - sSetRxTrigger(&rp->rp_channel, TRIG_1); - sDisRxStatusMode(&rp->rp_channel); - sFlushRxFIFO(&rp->rp_channel); - sFlushTxFIFO(&rp->rp_channel); - - sEnInterrupts(&rp->rp_channel, - (TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN)); - sSetRxTrigger(&rp->rp_channel, TRIG_1); - - sDisRxStatusMode(&rp->rp_channel); - sClrTxXOFF(&rp->rp_channel); - -/* sDisRTSFlowCtl(&rp->rp_channel); - sDisCTSFlowCtl(&rp->rp_channel); -*/ - sDisTxSoftFlowCtl(&rp->rp_channel); - - sStartRxProcessor(&rp->rp_channel); - - sEnRxFIFO(&rp->rp_channel); - sEnTransmit(&rp->rp_channel); - -/* sSetDTR(&rp->rp_channel); - sSetRTS(&rp->rp_channel); -*/ - - IntMask = sGetChanIntID(&rp->rp_channel); - IntMask = IntMask & rp->rp_intmask; - ChanStatus = sGetChanStatus(&rp->rp_channel); - - callout_reset(&rp->rp_timer, POLL_INTERVAL, rp_do_poll, rp); - - device_busy(rp->rp_ctlp->dev); - return(0); -} - -static void -rpclose(struct tty *tp) -{ - struct rp_port *rp; - - rp = tty_softc(tp); - callout_stop(&rp->rp_timer); - rphardclose(tp); - device_unbusy(rp->rp_ctlp->dev); -} - -static void -rphardclose(struct tty *tp) -{ - struct rp_port *rp; - CHANNEL_t *cp; - - rp = tty_softc(tp); - cp = &rp->rp_channel; - - sFlushRxFIFO(cp); - sFlushTxFIFO(cp); - sDisTransmit(cp); - sDisInterrupts(cp, TXINT_EN|MCINT_EN|RXINT_EN|SRCINT_EN|CHANINT_EN); - sDisRTSFlowCtl(cp); - sDisCTSFlowCtl(cp); - sDisTxSoftFlowCtl(cp); - sClrTxXOFF(cp); - -#ifdef DJA - if(tp->t_cflag&HUPCL || !(tp->t_state&TS_ISOPEN) || !tp->t_actout) { - sClrDTR(cp); - } - if(ISCALLOUT(tp->t_dev)) { - sClrDTR(cp); - } - tp->t_actout = FALSE; - wakeup(&tp->t_actout); - wakeup(TSA_CARR_ON(tp)); -#endif /* DJA */ -} - -static int -rpioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) -{ - struct rp_port *rp; - - rp = tty_softc(tp); - switch (cmd) { - case TIOCSBRK: - sSendBreak(&rp->rp_channel); - return (0); - case TIOCCBRK: - sClrBreak(&rp->rp_channel); - return (0); - default: - return ENOIOCTL; - } -} - -static int -rpmodem(struct tty *tp, int sigon, int sigoff) -{ - struct rp_port *rp; - int i, j, k; - - rp = tty_softc(tp); - if (sigon != 0 || sigoff != 0) { - i = j = 0; - if (sigon & SER_DTR) - i = SET_DTR; - if (sigoff & SER_DTR) - j = SET_DTR; - if (sigon & SER_RTS) - i = SET_RTS; - if (sigoff & SER_RTS) - j = SET_RTS; - rp->rp_channel.TxControl[3] &= ~i; - rp->rp_channel.TxControl[3] |= j; - rp_writech4(&rp->rp_channel,_INDX_ADDR, - le32dec(rp->rp_channel.TxControl)); - } else { - i = sGetChanStatusLo(&rp->rp_channel); - j = rp->rp_channel.TxControl[3]; - k = 0; - if (j & SET_DTR) - k |= SER_DTR; - if (j & SET_RTS) - k |= SER_RTS; - if (i & CD_ACT) - k |= SER_DCD; - if (i & DSR_ACT) - k |= SER_DSR; - if (i & CTS_ACT) - k |= SER_CTS; - return(k); - } - return (0); -} - -static struct -{ - int baud; - int conversion; -} baud_table[] = { - {B0, 0}, {B50, BRD50}, {B75, BRD75}, - {B110, BRD110}, {B134, BRD134}, {B150, BRD150}, - {B200, BRD200}, {B300, BRD300}, {B600, BRD600}, - {B1200, BRD1200}, {B1800, BRD1800}, {B2400, BRD2400}, - {B4800, BRD4800}, {B9600, BRD9600}, {B19200, BRD19200}, - {B38400, BRD38400}, {B7200, BRD7200}, {B14400, BRD14400}, - {B57600, BRD57600}, {B76800, BRD76800}, - {B115200, BRD115200}, {B230400, BRD230400}, - {-1, -1} -}; - -static int rp_convert_baud(int baud) { - int i; - - for (i = 0; baud_table[i].baud >= 0; i++) { - if (baud_table[i].baud == baud) - break; - } - - return baud_table[i].conversion; -} - -static int -rpparam(tp, t) - struct tty *tp; - struct termios *t; -{ - struct rp_port *rp; - CHANNEL_t *cp; - int cflag, iflag, oflag, lflag; - int ospeed; -#ifdef RPCLOCAL - int devshift; -#endif - - rp = tty_softc(tp); - cp = &rp->rp_channel; - - cflag = t->c_cflag; -#ifdef RPCLOCAL - devshift = umynor / 32; - devshift = 1 << devshift; - if ( devshift & RPCLOCAL ) { - cflag |= CLOCAL; - } -#endif - iflag = t->c_iflag; - oflag = t->c_oflag; - lflag = t->c_lflag; - - ospeed = rp_convert_baud(t->c_ispeed); - if(ospeed < 0 || t->c_ispeed != t->c_ospeed) - return(EINVAL); - - if(t->c_ospeed == 0) { - sClrDTR(cp); - return(0); - } - rp->rp_fifo_lw = ((t->c_ospeed*2) / 1000) +1; - - /* Set baud rate ----- we only pay attention to ispeed */ - sSetDTR(cp); - sSetRTS(cp); - sSetBaud(cp, ospeed); - - if(cflag & CSTOPB) { - sSetStop2(cp); - } else { - sSetStop1(cp); - } - - if(cflag & PARENB) { - sEnParity(cp); - if(cflag & PARODD) { - sSetOddParity(cp); - } else { - sSetEvenParity(cp); - } - } - else { - sDisParity(cp); - } - if((cflag & CSIZE) == CS8) { - sSetData8(cp); - rp->rp_imask = 0xFF; - } else { - sSetData7(cp); - rp->rp_imask = 0x7F; - } - - if(iflag & ISTRIP) { - rp->rp_imask &= 0x7F; - } - - if(cflag & CLOCAL) { - rp->rp_intmask &= ~DELTA_CD; - } else { - rp->rp_intmask |= DELTA_CD; - } - - /* Put flow control stuff here */ - - if(cflag & CCTS_OFLOW) { - sEnCTSFlowCtl(cp); - } else { - sDisCTSFlowCtl(cp); - } - - if(cflag & CRTS_IFLOW) { - rp->rp_rts_iflow = 1; - } else { - rp->rp_rts_iflow = 0; - } - - if(cflag & CRTS_IFLOW) { - sEnRTSFlowCtl(cp); - } else { - sDisRTSFlowCtl(cp); - } - - return(0); -} - -static void -rpstart(struct tty *tp) -{ - struct rp_port *rp; - CHANNEL_t *cp; - char flags; - int xmit_fifo_room; - int i, count, wcount; - - rp = tty_softc(tp); - cp = &rp->rp_channel; - flags = rp->rp_channel.TxControl[3]; - - if(rp->rp_xmit_stopped) { - sEnTransmit(cp); - rp->rp_xmit_stopped = 0; - } - - xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp); - count = ttydisc_getc(tp, &rp->TxBuf, xmit_fifo_room); - if(xmit_fifo_room > 0) { - for( i = 0, wcount = count >> 1; wcount > 0; i += 2, wcount-- ) { - rp_writech2(cp, sGetTxRxDataIO(cp), le16dec(&rp->TxBuf[i])); - } - if ( count & 1 ) { - rp_writech1(cp, sGetTxRxDataIO(cp), rp->TxBuf[(count-1)]); - } - } -} Index: sys/dev/rp/rp_isa.c =================================================================== --- sys/dev/rp/rp_isa.c +++ sys/dev/rp/rp_isa.c @@ -1,508 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * ISA-specific part separated from: - * sys/i386/isa/rp.c,v 1.33 1999/09/28 11:45:27 phk Exp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ROCKET_C -#include -#include - -#include - -/* ISA-specific part of CONTROLLER_t */ -struct ISACONTROLLER_T { - int MBaseIO; /* rid of the Mudbac controller for this controller */ - int MReg0IO; /* offset0 of the Mudbac controller for this controller */ - int MReg1IO; /* offset1 of the Mudbac controller for this controller */ - int MReg2IO; /* offset2 of the Mudbac controller for this controller */ - int MReg3IO; /* offset3 of the Mudbac controller for this controller */ - Byte_t MReg2; - Byte_t MReg3; -}; -typedef struct ISACONTROLLER_T ISACONTROLLER_t; - -#define ISACTL(ctlp) ((ISACONTROLLER_t *)((ctlp)->bus_ctlp)) - -/*************************************************************************** -Function: sControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sControllerEOI(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sControllerEOI(MudbacCtlP,CtlP) \ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2 | INT_STROB) - -/*************************************************************************** -Function: sDisAiop -Purpose: Disable I/O access to an AIOP -Call: sDisAiop(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sDisAiop(MudbacCtlP,CtlP,AIOPNUM) \ -{ \ - ISACTL(CtlP)->MReg3 &= rp_sBitMapClrTbl[AIOPNUM]; \ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \ -} - -/*************************************************************************** -Function: sEnAiop -Purpose: Enable I/O access to an AIOP -Call: sEnAiop(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; Number of AIOP on controller -*/ -#define sEnAiop(MudbacCtlP,CtlP,AIOPNUM) \ -{ \ - ISACTL(CtlP)->MReg3 |= rp_sBitMapSetTbl[AIOPNUM]; \ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); \ -} - -/*************************************************************************** -Function: sGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sGetControllerIntStatus(MudbacCtlP,CtlP) - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sGetControllerIntStatus(MudbacCtlP,CtlP) \ - (rp_readio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg1IO) & 0x0f) - -static devclass_t rp_devclass; -static CONTROLLER_t *rp_controller; -static int rp_nisadevs; - -static int rp_probe(device_t dev); -static int rp_attach(device_t dev); -static void rp_isareleaseresource(CONTROLLER_t *ctlp); -static int sInitController(CONTROLLER_T *CtlP, - CONTROLLER_T *MudbacCtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly); -static rp_aiop2rid_t rp_isa_aiop2rid; -static rp_aiop2off_t rp_isa_aiop2off; -static rp_ctlmask_t rp_isa_ctlmask; - -static int -rp_probe(device_t dev) -{ - int unit; - CONTROLLER_t *controller; - int num_aiops; - CONTROLLER_t *ctlp; - int retval; - - /* - * We have no PnP RocketPort cards. - * (At least according to LINT) - */ - if (isa_get_logicalid(dev) != 0) - return (ENXIO); - - /* We need IO port resource to configure an ISA device. */ - if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 0) - return (ENXIO); - - unit = device_get_unit(dev); - if (unit >= 4) { - device_printf(dev, "rpprobe: unit number %d invalid.\n", unit); - return (ENXIO); - } - device_printf(dev, "probing for RocketPort(ISA) unit %d.\n", unit); - - ctlp = device_get_softc(dev); - bzero(ctlp, sizeof(*ctlp)); - ctlp->dev = dev; - ctlp->aiop2rid = rp_isa_aiop2rid; - ctlp->aiop2off = rp_isa_aiop2off; - ctlp->ctlmask = rp_isa_ctlmask; - - /* The IO ports of AIOPs for an ISA controller are discrete. */ - ctlp->io_num = 1; - ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO); - ctlp->io = malloc(sizeof(*(ctlp->io)) * MAX_AIOPS_PER_BOARD, M_DEVBUF, M_NOWAIT | M_ZERO); - if (ctlp->io_rid == NULL || ctlp->io == NULL) { - device_printf(dev, "rp_attach: Out of memory.\n"); - retval = ENOMEM; - goto nogo; - } - - ctlp->bus_ctlp = malloc(sizeof(ISACONTROLLER_t) * 1, M_DEVBUF, M_NOWAIT | M_ZERO); - if (ctlp->bus_ctlp == NULL) { - device_printf(dev, "rp_attach: Out of memory.\n"); - retval = ENOMEM; - goto nogo; - } - - ctlp->io_rid[0] = 0; - if (rp_controller != NULL) { - controller = rp_controller; - ctlp->io[0] = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0x40, RF_ACTIVE); - } else { - controller = rp_controller = ctlp; - ctlp->io[0] = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &ctlp->io_rid[0], 0x44, RF_ACTIVE); - } - if (ctlp->io[0] == NULL) { - device_printf(dev, "rp_attach: Resource not available.\n"); - retval = ENXIO; - goto nogo; - } - - num_aiops = sInitController(ctlp, - controller, - MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); - if (num_aiops <= 0) { - device_printf(dev, "board%d init failed.\n", unit); - retval = ENXIO; - goto nogo; - } - - if (rp_controller == NULL) - rp_controller = controller; - rp_nisadevs++; - - device_set_desc(dev, "RocketPort ISA"); - - return (0); - -nogo: - rp_isareleaseresource(ctlp); - - return (retval); -} - -static int -rp_attach(device_t dev) -{ - int unit; - int num_ports, num_aiops; - int aiop; - CONTROLLER_t *ctlp; - int retval; - - unit = device_get_unit(dev); - - ctlp = device_get_softc(dev); - -#ifdef notdef - num_aiops = sInitController(ctlp, - rp_controller, - MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0); -#else - num_aiops = ctlp->NumAiop; -#endif /* notdef */ - - num_ports = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - sEnAiop(rp_controller, ctlp, aiop); - num_ports += sGetAiopNumChan(ctlp, aiop); - } - - retval = rp_attachcommon(ctlp, num_aiops, num_ports); - if (retval != 0) - goto nogo; - - return (0); - -nogo: - rp_isareleaseresource(ctlp); - - return (retval); -} - -static void -rp_isareleaseresource(CONTROLLER_t *ctlp) -{ - int i; - - rp_releaseresource(ctlp); - - if (ctlp == rp_controller) - rp_controller = NULL; - if (ctlp->io != NULL) { - for (i = 0 ; i < MAX_AIOPS_PER_BOARD ; i++) - if (ctlp->io[i] != NULL) - bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[i], ctlp->io[i]); - free(ctlp->io, M_DEVBUF); - } - if (ctlp->io_rid != NULL) - free(ctlp->io_rid, M_DEVBUF); - if (rp_controller != NULL && rp_controller->io[ISACTL(ctlp)->MBaseIO] != NULL) { - bus_release_resource(rp_controller->dev, SYS_RES_IOPORT, rp_controller->io_rid[ISACTL(ctlp)->MBaseIO], rp_controller->io[ISACTL(ctlp)->MBaseIO]); - rp_controller->io[ISACTL(ctlp)->MBaseIO] = NULL; - rp_controller->io_rid[ISACTL(ctlp)->MBaseIO] = 0; - } - if (ctlp->bus_ctlp != NULL) - free(ctlp->bus_ctlp, M_DEVBUF); -} - -/*************************************************************************** -Function: sInitController -Purpose: Initialization of controller global registers and controller - structure. -Call: sInitController(CtlP,MudbacCtlP,AiopNum, - IRQNum,Frequency,PeriodicOnly) - CONTROLLER_T *CtlP; Ptr to controller structure - CONTROLLER_T *MudbacCtlP; Ptr to Mudbac controller structure - int AiopNum; Number of Aiops - int IRQNum; Interrupt Request number. Can be any of the following: - 0: Disable global interrupts - 3: IRQ 3 - 4: IRQ 4 - 5: IRQ 5 - 9: IRQ 9 - 10: IRQ 10 - 11: IRQ 11 - 12: IRQ 12 - 15: IRQ 15 - Byte_t Frequency: A flag identifying the frequency - of the periodic interrupt, can be any one of the following: - FREQ_DIS - periodic interrupt disabled - FREQ_137HZ - 137 Hertz - FREQ_69HZ - 69 Hertz - FREQ_34HZ - 34 Hertz - FREQ_17HZ - 17 Hertz - FREQ_9HZ - 9 Hertz - FREQ_4HZ - 4 Hertz - If IRQNum is set to 0 the Frequency parameter is - overidden, it is forced to a value of FREQ_DIS. - int PeriodicOnly: TRUE if all interrupts except the periodic - interrupt are to be blocked. - FALSE is both the periodic interrupt and - other channel interrupts are allowed. - If IRQNum is set to 0 the PeriodicOnly parameter is - overidden, it is forced to a value of FALSE. -Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller - initialization failed. - -Comments: - If periodic interrupts are to be disabled but AIOP interrupts - are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. - - If interrupts are to be completely disabled set IRQNum to 0. - - Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an - invalid combination. - - This function performs initialization of global interrupt modes, - but it does not actually enable global interrupts. To enable - and disable global interrupts use functions sEnGlobalInt() and - sDisGlobalInt(). Enabling of global interrupts is normally not - done until all other initializations are complete. - - Even if interrupts are globally enabled, they must also be - individually enabled for each channel that is to generate - interrupts. - -Warnings: No range checking on any of the parameters is done. - - No context switches are allowed while executing this function. - - After this function all AIOPs on the controller are disabled, - they can be enabled with sEnAiop(). -*/ -static int -sInitController( CONTROLLER_T *CtlP, - CONTROLLER_T *MudbacCtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly) -{ - int i; - int ctl_base, aiop_base, aiop_size; - - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - - ISACTL(CtlP)->MBaseIO = rp_nisadevs; - if (MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] != NULL) { - ISACTL(CtlP)->MReg0IO = 0x40 + 0; - ISACTL(CtlP)->MReg1IO = 0x40 + 1; - ISACTL(CtlP)->MReg2IO = 0x40 + 2; - ISACTL(CtlP)->MReg3IO = 0x40 + 3; - } else { - MudbacCtlP->io_rid[ISACTL(CtlP)->MBaseIO] = ISACTL(CtlP)->MBaseIO; - ctl_base = rman_get_start(MudbacCtlP->io[0]) + 0x40 + 0x400 * rp_nisadevs; - MudbacCtlP->io[ISACTL(CtlP)->MBaseIO] = bus_alloc_resource(MudbacCtlP->dev, SYS_RES_IOPORT, &CtlP->io_rid[ISACTL(CtlP)->MBaseIO], ctl_base, ctl_base + 3, 4, RF_ACTIVE); - ISACTL(CtlP)->MReg0IO = 0; - ISACTL(CtlP)->MReg1IO = 1; - ISACTL(CtlP)->MReg2IO = 2; - ISACTL(CtlP)->MReg3IO = 3; - } -#if 1 - ISACTL(CtlP)->MReg2 = 0; /* interrupt disable */ - ISACTL(CtlP)->MReg3 = 0; /* no periodic interrupts */ -#else - if(sIRQMap[IRQNum] == 0) /* interrupts globally disabled */ - { - ISACTL(CtlP)->MReg2 = 0; /* interrupt disable */ - ISACTL(CtlP)->MReg3 = 0; /* no periodic interrupts */ - } - else - { - ISACTL(CtlP)->MReg2 = sIRQMap[IRQNum]; /* set IRQ number */ - ISACTL(CtlP)->MReg3 = Frequency; /* set frequency */ - if(PeriodicOnly) /* periodic interrupt only */ - { - ISACTL(CtlP)->MReg3 |= PERIODIC_ONLY; - } - } -#endif - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg2IO,ISACTL(CtlP)->MReg2); - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO,ISACTL(CtlP)->MReg3IO,ISACTL(CtlP)->MReg3); - sControllerEOI(MudbacCtlP,CtlP); /* clear EOI if warm init */ - - /* Init AIOPs */ - CtlP->NumAiop = 0; - for(i=0; i < AiopNum; i++) - { - if (CtlP->io[i] == NULL) { - CtlP->io_rid[i] = i; - aiop_base = rman_get_start(CtlP->io[0]) + 0x400 * i; - if (rp_nisadevs == 0) - aiop_size = 0x44; - else - aiop_size = 0x40; - CtlP->io[i] = bus_alloc_resource(CtlP->dev, SYS_RES_IOPORT, &CtlP->io_rid[i], aiop_base, aiop_base + aiop_size - 1, aiop_size, RF_ACTIVE); - } else - aiop_base = rman_get_start(CtlP->io[i]); - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO, - ISACTL(CtlP)->MReg2IO, - ISACTL(CtlP)->MReg2 | (i & 0x03)); /* AIOP index */ - rp_writeio1(MudbacCtlP,ISACTL(CtlP)->MBaseIO, - ISACTL(CtlP)->MReg0IO, - (Byte_t)(aiop_base >> 6)); /* set up AIOP I/O in MUDBAC */ - sEnAiop(MudbacCtlP,CtlP,i); /* enable the AIOP */ - - CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ - if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - { - sDisAiop(MudbacCtlP,CtlP,i); /* disable AIOP */ - bus_release_resource(CtlP->dev, SYS_RES_IOPORT, CtlP->io_rid[i], CtlP->io[i]); - CtlP->io[i] = NULL; - break; /* done looking for AIOPs */ - } - - CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); /* num channels in AIOP */ - rp_writeaiop2(CtlP,i,_INDX_ADDR,_CLK_PRE); /* clock prescaler */ - rp_writeaiop1(CtlP,i,_INDX_DATA,CLOCK_PRESC); - CtlP->NumAiop++; /* bump count of AIOPs */ - sDisAiop(MudbacCtlP,CtlP,i); /* disable AIOP */ - } - - if(CtlP->NumAiop == 0) - return(-1); - else - return(CtlP->NumAiop); -} - -/* - * ARGSUSED - * Maps (aiop, offset) to rid. - */ -static int -rp_isa_aiop2rid(int aiop, int offset) -{ - /* rid equals to aiop for an ISA controller. */ - return aiop; -} - -/* - * ARGSUSED - * Maps (aiop, offset) to the offset of resource. - */ -static int -rp_isa_aiop2off(int aiop, int offset) -{ - /* Each aiop has its own resource. */ - return offset; -} - -/* Read the int status for an ISA controller. */ -static unsigned char -rp_isa_ctlmask(CONTROLLER_t *ctlp) -{ - return sGetControllerIntStatus(rp_controller,ctlp); -} - -static device_method_t rp_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rp_probe), - DEVMETHOD(device_attach, rp_attach), - - { 0, 0 } -}; - -static driver_t rp_driver = { - "rp", - rp_methods, - sizeof(CONTROLLER_t), -}; - -/* - * rp can be attached to an isa bus. - */ -DRIVER_MODULE(rp, isa, rp_driver, rp_devclass, 0, 0); Index: sys/dev/rp/rp_pci.c =================================================================== --- sys/dev/rp/rp_pci.c +++ sys/dev/rp/rp_pci.c @@ -1,368 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * PCI-specific part separated from: - * sys/i386/isa/rp.c,v 1.33 1999/09/28 11:45:27 phk Exp - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ROCKET_C -#include -#include - -#include -#include - -/* PCI IDs */ -#define RP_VENDOR_ID 0x11FE -#define RP_DEVICE_ID_32I 0x0001 -#define RP_DEVICE_ID_8I 0x0002 -#define RP_DEVICE_ID_16I 0x0003 -#define RP_DEVICE_ID_4Q 0x0004 -#define RP_DEVICE_ID_8O 0x0005 -#define RP_DEVICE_ID_8J 0x0006 -#define RP_DEVICE_ID_4J 0x0007 -#define RP_DEVICE_ID_6M 0x000C -#define RP_DEVICE_ID_4M 0x000D -#define RP_DEVICE_ID_UPCI_32 0x0801 -#define RP_DEVICE_ID_UPCI_16 0x0803 -#define RP_DEVICE_ID_UPCI_8O 0x0805 - -/************************************************************************** - MUDBAC remapped for PCI -**************************************************************************/ - -#define _CFG_INT_PCI 0x40 -#define _PCI_INT_FUNC 0x3A - -#define PCI_STROB 0x2000 -#define INTR_EN_PCI 0x0010 - -/*************************************************************************** -Function: sPCIControllerEOI -Purpose: Strobe the MUDBAC's End Of Interrupt bit. -Call: sPCIControllerEOI(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -*/ -#define sPCIControllerEOI(CtlP) rp_writeio2(CtlP, 0, _PCI_INT_FUNC, PCI_STROB) - -/*************************************************************************** -Function: sPCIGetControllerIntStatus -Purpose: Get the controller interrupt status -Call: sPCIGetControllerIntStatus(CtlP) - CONTROLLER_T *CtlP; Ptr to controller structure -Return: Byte_t: The controller interrupt status in the lower 4 - bits. Bits 0 through 3 represent AIOP's 0 - through 3 respectively. If a bit is set that - AIOP is interrupting. Bits 4 through 7 will - always be cleared. -*/ -#define sPCIGetControllerIntStatus(CTLP) ((rp_readio2(CTLP, 0, _PCI_INT_FUNC) >> 8) & 0x1f) - -static devclass_t rp_devclass; - -static int rp_pciprobe(device_t dev); -static int rp_pciattach(device_t dev); -#ifdef notdef -static int rp_pcidetach(device_t dev); -static int rp_pcishutdown(device_t dev); -#endif /* notdef */ -static void rp_pcireleaseresource(CONTROLLER_t *ctlp); -static int sPCIInitController( CONTROLLER_t *CtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly, - int VendorDevice); -static rp_aiop2rid_t rp_pci_aiop2rid; -static rp_aiop2off_t rp_pci_aiop2off; -static rp_ctlmask_t rp_pci_ctlmask; - -/* - * The following functions are the pci-specific part - * of rp driver. - */ - -static int -rp_pciprobe(device_t dev) -{ - char *s; - - s = NULL; - if (pci_get_vendor(dev) == RP_VENDOR_ID) - s = "RocketPort PCI"; - - if (s != NULL) { - device_set_desc(dev, s); - return (BUS_PROBE_DEFAULT); - } - - return (ENXIO); -} - -static int -rp_pciattach(device_t dev) -{ - int num_ports, num_aiops; - int aiop; - CONTROLLER_t *ctlp; - int unit; - int retval; - - ctlp = device_get_softc(dev); - bzero(ctlp, sizeof(*ctlp)); - ctlp->dev = dev; - unit = device_get_unit(dev); - ctlp->aiop2rid = rp_pci_aiop2rid; - ctlp->aiop2off = rp_pci_aiop2off; - ctlp->ctlmask = rp_pci_ctlmask; - - /* The IO ports of AIOPs for a PCI controller are continuous. */ - ctlp->io_num = 1; - ctlp->io_rid = malloc(sizeof(*(ctlp->io_rid)) * ctlp->io_num, M_DEVBUF, M_NOWAIT | M_ZERO); - ctlp->io = malloc(sizeof(*(ctlp->io)) * ctlp->io_num, M_DEVBUF, M_NOWAIT | M_ZERO); - if (ctlp->io_rid == NULL || ctlp->io == NULL) { - device_printf(dev, "rp_pciattach: Out of memory.\n"); - retval = ENOMEM; - goto nogo; - } - - ctlp->bus_ctlp = NULL; - - switch (pci_get_device(dev)) { - case RP_DEVICE_ID_UPCI_16: - case RP_DEVICE_ID_UPCI_32: - case RP_DEVICE_ID_UPCI_8O: - ctlp->io_rid[0] = PCIR_BAR(2); - break; - default: - ctlp->io_rid[0] = PCIR_BAR(0); - break; - } - ctlp->io[0] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &ctlp->io_rid[0], RF_ACTIVE); - if(ctlp->io[0] == NULL) { - device_printf(dev, "ioaddr mapping failed for RocketPort(PCI).\n"); - retval = ENXIO; - goto nogo; - } - - num_aiops = sPCIInitController(ctlp, - MAX_AIOPS_PER_BOARD, 0, - FREQ_DIS, 0, pci_get_device(dev)); - - num_ports = 0; - for(aiop=0; aiop < num_aiops; aiop++) { - sResetAiopByNum(ctlp, aiop); - num_ports += sGetAiopNumChan(ctlp, aiop); - } - - retval = rp_attachcommon(ctlp, num_aiops, num_ports); - if (retval != 0) - goto nogo; - - return (0); - -nogo: - rp_pcireleaseresource(ctlp); - - return (retval); -} - -static int -rp_pcidetach(device_t dev) -{ - CONTROLLER_t *ctlp; - - ctlp = device_get_softc(dev); - rp_pcireleaseresource(ctlp); - - return (0); -} - -static int -rp_pcishutdown(device_t dev) -{ - CONTROLLER_t *ctlp; - - ctlp = device_get_softc(dev); - rp_pcireleaseresource(ctlp); - - return (0); -} - -static void -rp_pcireleaseresource(CONTROLLER_t *ctlp) -{ - rp_releaseresource(ctlp); - if (ctlp->io != NULL) { - if (ctlp->io[0] != NULL) - bus_release_resource(ctlp->dev, SYS_RES_IOPORT, ctlp->io_rid[0], ctlp->io[0]); - free(ctlp->io, M_DEVBUF); - ctlp->io = NULL; - } - if (ctlp->io_rid != NULL) { - free(ctlp->io_rid, M_DEVBUF); - ctlp->io = NULL; - } -} - -static int -sPCIInitController( CONTROLLER_t *CtlP, - int AiopNum, - int IRQNum, - Byte_t Frequency, - int PeriodicOnly, - int VendorDevice) -{ - int i; - - CtlP->CtlID = CTLID_0001; /* controller release 1 */ - - sPCIControllerEOI(CtlP); - - /* Init AIOPs */ - CtlP->NumAiop = 0; - for(i=0; i < AiopNum; i++) - { - /*device_printf(CtlP->dev, "aiop %d.\n", i);*/ - CtlP->AiopID[i] = sReadAiopID(CtlP, i); /* read AIOP ID */ - /*device_printf(CtlP->dev, "ID = %d.\n", CtlP->AiopID[i]);*/ - if(CtlP->AiopID[i] == AIOPID_NULL) /* if AIOP does not exist */ - { - break; /* done looking for AIOPs */ - } - - switch( VendorDevice ) { - case RP_DEVICE_ID_4Q: - case RP_DEVICE_ID_4J: - case RP_DEVICE_ID_4M: - CtlP->AiopNumChan[i] = 4; - break; - case RP_DEVICE_ID_6M: - CtlP->AiopNumChan[i] = 6; - break; - case RP_DEVICE_ID_8O: - case RP_DEVICE_ID_8J: - case RP_DEVICE_ID_8I: - case RP_DEVICE_ID_16I: - case RP_DEVICE_ID_32I: - CtlP->AiopNumChan[i] = 8; - break; - default: -#ifdef notdef - CtlP->AiopNumChan[i] = 8; -#else - CtlP->AiopNumChan[i] = sReadAiopNumChan(CtlP, i); -#endif /* notdef */ - break; - } - /*device_printf(CtlP->dev, "%d channels.\n", CtlP->AiopNumChan[i]);*/ - rp_writeaiop2(CtlP, i, _INDX_ADDR,_CLK_PRE); /* clock prescaler */ - /*device_printf(CtlP->dev, "configuring clock prescaler.\n");*/ - rp_writeaiop1(CtlP, i, _INDX_DATA,CLOCK_PRESC); - /*device_printf(CtlP->dev, "configured clock prescaler.\n");*/ - CtlP->NumAiop++; /* bump count of AIOPs */ - } - - if(CtlP->NumAiop == 0) - return(-1); - else - return(CtlP->NumAiop); -} - -/* - * ARGSUSED - * Maps (aiop, offset) to rid. - */ -static int -rp_pci_aiop2rid(int aiop, int offset) -{ - /* Always return zero for a PCI controller. */ - return 0; -} - -/* - * ARGSUSED - * Maps (aiop, offset) to the offset of resource. - */ -static int -rp_pci_aiop2off(int aiop, int offset) -{ - /* Each AIOP reserves 0x40 bytes. */ - return aiop * 0x40 + offset; -} - -/* Read the int status for a PCI controller. */ -static unsigned char -rp_pci_ctlmask(CONTROLLER_t *ctlp) -{ - return sPCIGetControllerIntStatus(ctlp); -} - -static device_method_t rp_pcimethods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rp_pciprobe), - DEVMETHOD(device_attach, rp_pciattach), - DEVMETHOD(device_detach, rp_pcidetach), - DEVMETHOD(device_shutdown, rp_pcishutdown), - - { 0, 0 } -}; - -static driver_t rp_pcidriver = { - "rp", - rp_pcimethods, - sizeof(CONTROLLER_t), -}; - -/* - * rp can be attached to a pci bus. - */ -DRIVER_MODULE(rp, pci, rp_pcidriver, rp_devclass, 0, 0); Index: sys/dev/rp/rpreg.h =================================================================== --- sys/dev/rp/rpreg.h +++ sys/dev/rp/rpreg.h @@ -1,1033 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE 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$ - */ - -/* - * Begin OS-specific defines - rpreg.h - for RocketPort FreeBSD - */ - -typedef uint8_t Byte_t; -typedef uint8_t ByteIO_t; - -typedef uint16_t Word_t; -typedef uint16_t WordIO_t; - -typedef uint32_t DWord_t; -typedef uint32_t DWordIO_t; - -#define rp_readio(size, ctlp, rid, offset) \ - (bus_read_##size(ctlp->io[rid], offset)) -#define rp_readmultiio(size, ctlp, rid, offset, addr, count) \ - (bus_read_multi_##size(ctlp->io[rid], offset, addr, count)) -#define rp_writeio(size, ctlp, rid, offset, data) \ - (bus_write_##size(ctlp->io[rid], offset, data)) -#define rp_writemultiio(size, ctlp, rid, offset, addr, count) \ - (bus_write_multi_##size(ctlp->io[rid], offset, addr, count)) - -#define rp_readio1(ctlp, rid, offset) rp_readio(1, ctlp, rid, offset) -#define rp_readio2(ctlp, rid, offset) rp_readio(2, ctlp, rid, offset) -#define rp_readio4(ctlp, rid, offset) rp_readio(4, ctlp, rid, offset) -#define rp_writeio1(ctlp, rid, offset, data) rp_writeio(1, ctlp, rid, offset, data) -#define rp_writeio2(ctlp, rid, offset, data) rp_writeio(2, ctlp, rid, offset, data) -#define rp_writeio4(ctlp, rid, offset, data) rp_writeio(4, ctlp, rid, offset, data) -#define rp_readmultiio1(ctlp, rid, offset, addr, count) rp_readmultiio(1, ctlp, rid, offset, addr, count) -#define rp_readmultiio2(ctlp, rid, offset, addr, count) rp_readmultiio(2, ctlp, rid, offset, addr, count) -#define rp_readmultiio4(ctlp, rid, offset, addr, count) rp_readmultiio(4, ctlp, rid, offset, addr, count) -#define rp_writemultiio1(ctlp, rid, offset, addr, count) rp_writemultiio(1, ctlp, rid, offset, addr, count) -#define rp_writemultiio2(ctlp, rid, offset, addr, count) rp_writemultiio(2, ctlp, rid, offset, addr, count) -#define rp_writemultiio4(ctlp, rid, offset, addr, count) rp_writemultiio(4, ctlp, rid, offset, addr, count) - -#define rp_readaiop1(ctlp, aiop, offset) \ - (rp_readio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset))) -#define rp_readaiop2(ctlp, aiop, offset) \ - (rp_readio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset))) -#define rp_readaiop4(ctlp, aiop, offset) \ - (rp_readio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset))) -#define rp_readmultiaiop1(ctlp, aiop, offset, addr, count) \ - (rp_readmultiio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_readmultiaiop2(ctlp, aiop, offset, addr, count) \ - (rp_readmultiio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_readmultiaiop4(ctlp, aiop, offset, addr, count) \ - (rp_readmultiio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_writeaiop1(ctlp, aiop, offset, data) \ - (rp_writeio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), data)) -#define rp_writeaiop2(ctlp, aiop, offset, data) \ - (rp_writeio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), data)) -#define rp_writeaiop4(ctlp, aiop, offset, data) \ - (rp_writeio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), data)) -#define rp_writemultiaiop1(ctlp, aiop, offset, addr, count) \ - (rp_writemultiio1((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_writemultiaiop2(ctlp, aiop, offset, addr, count) \ - (rp_writemultiio2((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) -#define rp_writemultiaiop4(ctlp, aiop, offset, addr, count) \ - (rp_writemultiio4((ctlp), (ctlp)->aiop2rid(aiop, offset), (ctlp)->aiop2off(aiop, offset), addr, count)) - -#define rp_readch1(chp, offset) \ - (rp_readaiop1((chp)->CtlP, (chp)->AiopNum, offset)) -#define rp_readch2(chp, offset) \ - (rp_readaiop2((chp)->CtlP, (chp)->AiopNum, offset)) -#define rp_readch4(chp, offset) \ - (rp_readaiop4((chp)->CtlP, (chp)->AiopNum, offset)) -#define rp_readmultich1(chp, offset, addr, count) \ - (rp_readmultiaiop1((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_readmultich2(chp, offset, addr, count) \ - (rp_readmultiaiop2((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_readmultich4(chp, offset, addr, count) \ - (rp_readmultiaiop4((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_writech1(chp, offset, data) \ - (rp_writeaiop1((chp)->CtlP, (chp)->AiopNum, offset, data)) -#define rp_writech2(chp, offset, data) \ - (rp_writeaiop2((chp)->CtlP, (chp)->AiopNum, offset, data)) -#define rp_writech4(chp, offset, data) \ - (rp_writeaiop4((chp)->CtlP, (chp)->AiopNum, offset, data)) -#define rp_writemultich1(chp, offset, addr, count) \ - (rp_writemultiaiop1((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_writemultich2(chp, offset, addr, count) \ - (rp_writemultiaiop2((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) -#define rp_writemultich4(chp, offset, addr, count) \ - (rp_writemultiaiop4((chp)->CtlP, (chp)->AiopNum, offset, addr, count)) - -/* - * End of OS-specific defines - */ - -#define ROCKET_H - -#define CTL_SIZE 4 -#define AIOP_CTL_SIZE 4 -#define CHAN_AIOP_SIZE 8 -#define MAX_PORTS_PER_AIOP 8 -#define MAX_AIOPS_PER_BOARD 4 -#define MAX_PORTS_PER_BOARD 32 - -/* Controller ID numbers */ -#define CTLID_NULL -1 /* no controller exists */ -#define CTLID_0001 0x0001 /* controller release 1 */ - -/* AIOP ID numbers, identifies AIOP type implementing channel */ -#define AIOPID_NULL -1 /* no AIOP or channel exists */ -#define AIOPID_0001 0x0001 /* AIOP release 1 */ - -#define NULLDEV -1 /* identifies non-existant device */ -#define NULLCTL -1 /* identifies non-existant controller */ -#define NULLCTLPTR (CONTROLLER_T *)0 /* identifies non-existant controller */ -#define NULLAIOP -1 /* identifies non-existant AIOP */ -#define NULLCHAN -1 /* identifies non-existant channel */ - -/************************************************************************ - Global Register Offsets - Direct Access - Fixed values -************************************************************************/ - -#define _CMD_REG 0x38 /* Command Register 8 Write */ -#define _INT_CHAN 0x39 /* Interrupt Channel Register 8 Read */ -#define _INT_MASK 0x3A /* Interrupt Mask Register 8 Read / Write */ -#define _UNUSED 0x3B /* Unused 8 */ -#define _INDX_ADDR 0x3C /* Index Register Address 16 Write */ -#define _INDX_DATA 0x3E /* Index Register Data 8/16 Read / Write */ - -/************************************************************************ - Channel Register Offsets for 1st channel in AIOP - Direct Access -************************************************************************/ -#define _TD0 0x00 /* Transmit Data 16 Write */ -#define _RD0 0x00 /* Receive Data 16 Read */ -#define _CHN_STAT0 0x20 /* Channel Status 8/16 Read / Write */ -#define _FIFO_CNT0 0x10 /* Transmit/Receive FIFO Count 16 Read */ -#define _INT_ID0 0x30 /* Interrupt Identification 8 Read */ - -/************************************************************************ - Tx Control Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _TX_ENBLS 0x980 /* Tx Processor Enables Register 8 Read / Write */ -#define _TXCMP1 0x988 /* Transmit Compare Value #1 8 Read / Write */ -#define _TXCMP2 0x989 /* Transmit Compare Value #2 8 Read / Write */ -#define _TXREP1B1 0x98A /* Tx Replace Value #1 - Byte 1 8 Read / Write */ -#define _TXREP1B2 0x98B /* Tx Replace Value #1 - Byte 2 8 Read / Write */ -#define _TXREP2 0x98C /* Transmit Replace Value #2 8 Read / Write */ - -/************************************************************************ - Receive FIFO -************************************************************************/ -#define RXFIFO_DATA 0x5f -#define RXFIFO_OUT 0x5c -#define RXFIFO_EN 0x08 -#define RXFIFO_DIS 0xa7 - -/************************************************************************ -Memory Controller Register Offsets - Indexed - External - Fixed -************************************************************************/ -#define _RX_FIFO 0x000 /* Rx FIFO */ -#define _TX_FIFO 0x800 /* Tx FIFO */ -#define _RXF_OUTP 0x990 /* Rx FIFO OUT pointer 16 Read / Write */ -#define _RXF_INP 0x992 /* Rx FIFO IN pointer 16 Read / Write */ -#define _TXF_OUTP 0x994 /* Tx FIFO OUT pointer 8 Read / Write */ -#define _TXF_INP 0x995 /* Tx FIFO IN pointer 8 Read / Write */ -#define _TXP_CNT 0x996 /* Tx Priority Count 8 Read / Write */ -#define _TXP_PNTR 0x997 /* Tx Priority Pointer 8 Read / Write */ - -#define PRI_PEND 0x80 /* Priority data pending (bit7, Tx pri cnt) */ -#define TXFIFO_SIZE 255 /* size of Tx FIFO */ -#define RXFIFO_SIZE 1023 /* size of Rx FIFO */ - -/************************************************************************ -Tx Priority Buffer - Indexed - External - Fixed -************************************************************************/ -#define _TXP_BUF 0x9C0 /* Tx Priority Buffer 32 Bytes Read / Write */ -#define TXP_SIZE 0x20 /* 32 bytes */ - -/************************************************************************ -Channel Register Offsets - Indexed - Internal - Fixed -************************************************************************/ - -#define _TX_CTRL 0xFF0 /* Transmit Control 16 Write */ -#define _RX_CTRL 0xFF2 /* Receive Control 8 Write */ -#define _BAUD 0xFF4 /* Baud Rate 16 Write */ -#define _CLK_PRE 0xFF6 /* Clock Prescaler 8 Write */ - -#define CLOCK_PRESC 0x19 /* mod 9 (divide by 10) prescale */ - -#define BRD50 4607 -#define BRD75 3071 -#define BRD110 2094 -#define BRD134 1712 -#define BRD150 1535 -#define BRD200 1151 -#define BRD300 767 -#define BRD600 383 -#define BRD1200 191 -#define BRD1800 127 -#define BRD2000 114 -#define BRD2400 95 -#define BRD3600 64 -#define BRD4800 47 -#define BRD7200 31 -#define BRD9600 23 -#define BRD14400 15 -#define BRD19200 11 -#define BRD38400 5 -#define BRD57600 3 -#define BRD76800 2 -#define BRD115200 1 -#define BRD230400 0 - -#define STMBREAK 0x08 /* BREAK */ -#define STMFRAME 0x04 /* framing error */ -#define STMRCVROVR 0x02 /* receiver over run error */ -#define STMPARITY 0x01 /* parity error */ -#define STMERROR (STMBREAK | STMFRAME | STMPARITY) -#define STMBREAKH 0x800 /* BREAK */ -#define STMFRAMEH 0x400 /* framing error */ -#define STMRCVROVRH 0x200 /* receiver over run error */ -#define STMPARITYH 0x100 /* parity error */ -#define STMERRORH (STMBREAKH | STMFRAMEH | STMPARITYH) - -#define CTS_ACT 0x20 /* CTS input asserted */ -#define DSR_ACT 0x10 /* DSR input asserted */ -#define CD_ACT 0x08 /* CD input asserted */ -#define TXFIFOMT 0x04 /* Tx FIFO is empty */ -#define TXSHRMT 0x02 /* Tx shift register is empty */ -#define RDA 0x01 /* Rx data available */ -#define DRAINED (TXFIFOMT | TXSHRMT) /* indicates Tx is drained */ - -#define STATMODE 0x8000 /* status mode enable bit */ -#define RXFOVERFL 0x2000 /* receive FIFO overflow */ -#define RX2MATCH 0x1000 /* receive compare byte 2 match */ -#define RX1MATCH 0x0800 /* receive compare byte 1 match */ -#define RXBREAK 0x0400 /* received BREAK */ -#define RXFRAME 0x0200 /* received framing error */ -#define RXPARITY 0x0100 /* received parity error */ -#define STATERROR (RXBREAK | RXFRAME | RXPARITY) - -#define CTSFC_EN 0x80 /* CTS flow control enable bit */ -#define RTSTOG_EN 0x40 /* RTS toggle enable bit */ -#define TXINT_EN 0x10 /* transmit interrupt enable */ -#define STOP2 0x08 /* enable 2 stop bits (0 = 1 stop) */ -#define PARITY_EN 0x04 /* enable parity (0 = no parity) */ -#define EVEN_PAR 0x02 /* even parity (0 = odd parity) */ -#define DATA8BIT 0x01 /* 8 bit data (0 = 7 bit data) */ - -#define SETBREAK 0x10 /* send break condition (must clear) */ -#define LOCALLOOP 0x08 /* local loopback set for test */ -#define SET_DTR 0x04 /* assert DTR */ -#define SET_RTS 0x02 /* assert RTS */ -#define TX_ENABLE 0x01 /* enable transmitter */ - -#define RTSFC_EN 0x40 /* RTS flow control enable */ -#define RXPROC_EN 0x20 /* receive processor enable */ -#define TRIG_NO 0x00 /* Rx FIFO trigger level 0 (no trigger) */ -#define TRIG_1 0x08 /* trigger level 1 char */ -#define TRIG_1_2 0x10 /* trigger level 1/2 */ -#define TRIG_7_8 0x18 /* trigger level 7/8 */ -#define TRIG_MASK 0x18 /* trigger level mask */ -#define SRCINT_EN 0x04 /* special Rx condition interrupt enable */ -#define RXINT_EN 0x02 /* Rx interrupt enable */ -#define MCINT_EN 0x01 /* modem change interrupt enable */ - -#define RXF_TRIG 0x20 /* Rx FIFO trigger level interrupt */ -#define TXFIFO_MT 0x10 /* Tx FIFO empty interrupt */ -#define SRC_INT 0x08 /* special receive condition interrupt */ -#define DELTA_CD 0x04 /* CD change interrupt */ -#define DELTA_CTS 0x02 /* CTS change interrupt */ -#define DELTA_DSR 0x01 /* DSR change interrupt */ - -#define REP1W2_EN 0x10 /* replace byte 1 with 2 bytes enable */ -#define IGN2_EN 0x08 /* ignore byte 2 enable */ -#define IGN1_EN 0x04 /* ignore byte 1 enable */ -#define COMP2_EN 0x02 /* compare byte 2 enable */ -#define COMP1_EN 0x01 /* compare byte 1 enable */ - -#define RESET_ALL 0x80 /* reset AIOP (all channels) */ -#define TXOVERIDE 0x40 /* Transmit software off override */ -#define RESETUART 0x20 /* reset channel's UART */ -#define RESTXFCNT 0x10 /* reset channel's Tx FIFO count register */ -#define RESRXFCNT 0x08 /* reset channel's Rx FIFO count register */ - -#define INTSTAT0 0x01 /* AIOP 0 interrupt status */ -#define INTSTAT1 0x02 /* AIOP 1 interrupt status */ -#define INTSTAT2 0x04 /* AIOP 2 interrupt status */ -#define INTSTAT3 0x08 /* AIOP 3 interrupt status */ - -#define INTR_EN 0x08 /* allow interrupts to host */ -#define INT_STROB 0x04 /* strobe and clear interrupt line (EOI) */ - -#define CHAN3_EN 0x08 /* enable AIOP 3 */ -#define CHAN2_EN 0x04 /* enable AIOP 2 */ -#define CHAN1_EN 0x02 /* enable AIOP 1 */ -#define CHAN0_EN 0x01 /* enable AIOP 0 */ -#define FREQ_DIS 0x00 -#define FREQ_274HZ 0x60 -#define FREQ_137HZ 0x50 -#define FREQ_69HZ 0x40 -#define FREQ_34HZ 0x30 -#define FREQ_17HZ 0x20 -#define FREQ_9HZ 0x10 -#define PERIODIC_ONLY 0x80 /* only PERIODIC interrupt */ - -#define CHANINT_EN 0x0100 /* flags to enable/disable channel ints */ - -#define RDATASIZE 72 -#define RREGDATASIZE 52 - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -struct CONTROLLER_str; -struct CHANNEL_str; - -/* The types of bus-specific methods */ -typedef int rp_aiop2rid_t(int, int); -typedef int rp_aiop2off_t(int, int); -typedef unsigned char rp_ctlmask_t(struct CONTROLLER_str *); - -/* Controller level information structure */ -struct CONTROLLER_str -{ - int CtlID; - int NumAiop; - int AiopID[AIOP_CTL_SIZE]; - int AiopNumChan[AIOP_CTL_SIZE]; - - struct mtx hwmtx; /* Spinlock protecting hardware. */ - int hwmtx_init; - int free; - int num_ports; - - /* Device and resource management */ - device_t dev; /* device */ - int io_num; /* Number of IO resources */ - int *io_rid; /* IO resource IDs */ - struct resource **io; /* IO resources */ - - struct rp_port *rp; /* port */ - - /* Device nodes */ - struct cdev **dev_nodes; - - /* Bus-specific properties */ - void *bus_ctlp; - - /* Bus-specific methods */ - rp_aiop2rid_t *aiop2rid; /* (aiop, offset) -> rid */ - rp_aiop2off_t *aiop2off; /* (aiop, offset) -> off */ - rp_ctlmask_t *ctlmask; /* Int status */ -}; -typedef struct CONTROLLER_str CONTROLLER_T; -typedef CONTROLLER_T CONTROLLER_t; - -/* Channel level information structure */ -struct CHANNEL_str -{ - CONTROLLER_t *CtlP; - int AiopNum; - int ChanID; - int ChanNum; - - Word_t TxFIFO; - Word_t TxFIFOPtrs; - Word_t RxFIFO; - Word_t RxFIFOPtrs; - Word_t TxPrioCnt; - Word_t TxPrioPtr; - Word_t TxPrioBuf; - - Byte_t R[RREGDATASIZE]; - - Byte_t BaudDiv[4]; - Byte_t TxControl[4]; - Byte_t RxControl[4]; - Byte_t TxEnables[4]; - Byte_t TxCompare[4]; - Byte_t TxReplace1[4]; - Byte_t TxReplace2[4]; -}; - -typedef struct CHANNEL_str CHANNEL_T; -typedef CHANNEL_T CHANNEL_t; -typedef CHANNEL_T * CHANPTR_T; - -#define CHNOFF_TXRXDATA(chp) ((chp)->ChanNum * 2 + _TD0) -#define CHNOFF_CHANSTAT(chp) ((chp)->ChanNum * 2 + _CHN_STAT0) -#define CHNOFF_TXRXCOUNT(chp) ((chp)->ChanNum * 2 + _FIFO_CNT0) -#define CHNOFF_INTID(chp) ((chp)->ChanNum + _INT_ID0) - -/*************************************************************************** -Function: sClrBreak -Purpose: Stop sending a transmit BREAK signal -Call: sClrBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrBreak(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SETBREAK; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sClrDTR -Purpose: Clr the DTR output -Call: sClrDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrDTR(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SET_DTR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sClrRTS -Purpose: Clr the RTS output -Call: sClrRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrRTS(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sClrTxXOFF -Purpose: Clear any existing transmit software flow control off condition -Call: sClrTxXOFF(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sClrTxXOFF(ChP) \ -{ \ - rp_writech1(ChP,_CMD_REG,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \ - rp_writech1(ChP,_CMD_REG,(Byte_t)(ChP)->ChanNum); \ -} - -/*************************************************************************** -Function: sDisCTSFlowCtl -Purpose: Disable output flow control using CTS -Call: sDisCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisCTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~CTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: DisParity -Purpose: Disable parity -Call: sDisParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). -*/ -#define sDisParity(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~PARITY_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sDisRxFIFO -Purpose: Disable Rx FIFO -Call: sDisRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisRxFIFO(ChP) \ -{ \ - (ChP)->R[0x32] = 0x0a; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R + 0x30)); \ -} - -/*************************************************************************** -Function: sDisRxStatusMode -Purpose: Disable the Rx status mode -Call: sDisRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This takes the channel out of the receive status mode. All - subsequent reads of receive data using sReadRxWord() will return - two data bytes. -*/ -#define sDisRxStatusMode(ChP) rp_writech2(ChP,CHNOFF_CHANSTAT(ChP),0) - -/*************************************************************************** -Function: sDisTransmit -Purpose: Disable transmit -Call: sDisTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure - This disables movement of Tx data from the Tx FIFO into the 1 byte - Tx buffer. Therefore there could be up to a 2 byte latency - between the time sDisTransmit() is called and the transmit buffer - and transmit shift register going completely empty. -*/ -#define sDisTransmit(ChP) \ -{ \ - (ChP)->TxControl[3] &= ~TX_ENABLE; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sDisTxSoftFlowCtl -Purpose: Disable Tx Software Flow Control -Call: sDisTxSoftFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sDisTxSoftFlowCtl(ChP) \ -{ \ - (ChP)->R[0x06] = 0x8a; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R + 0x04)); \ -} - -/*************************************************************************** -Function: sEnCTSFlowCtl -Purpose: Enable output flow control using CTS -Call: sEnCTSFlowCtl(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnCTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] |= CTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: EnParity -Purpose: Enable parity -Call: sEnParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: Before enabling parity odd or even parity should be chosen using - functions sSetOddParity() or sSetEvenParity(). -*/ -#define sEnParity(ChP) \ -{ \ - (ChP)->TxControl[2] |= PARITY_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sEnRTSFlowCtl -Return: void -*/ -#define sEnRTSFlowCtl(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~RTSTOG_EN; \ - (ChP)->TxControl[3] &= ~SET_RTS; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ - (ChP)->RxControl[2] |= RTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sDisRTSFlowCtl -Return: void -*/ -#define sDisRTSFlowCtl(ChP) \ -{ \ - (ChP)->RxControl[2] &= ~RTSFC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sEnRxFIFO -Purpose: Enable Rx FIFO -Call: sEnRxFIFO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnRxFIFO(ChP) \ -{ \ - (ChP)->R[0x32] = 0x08; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R + 0x30)); \ -} - -/*************************************************************************** -Function: sEnRxProcessor -Purpose: Enable the receive processor -Call: sEnRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start the receive processor. When - the channel is in the reset state the receive processor is not - running. This is done to prevent the receive processor from - executing invalid microcode instructions prior to the - downloading of the microcode. - -Warnings: This function must be called after valid microcode has been - downloaded to the AIOP, and it must not be called before the - microcode has been downloaded. -*/ -#define sEnRxProcessor(ChP) \ -{ \ - (ChP)->RxControl[2] |= RXPROC_EN; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sEnRxStatusMode -Purpose: Enable the Rx status mode -Call: sEnRxStatusMode(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This places the channel in the receive status mode. All subsequent - reads of receive data using sReadRxWord() will return a data byte - in the low word and a status byte in the high word. - -*/ -#define sEnRxStatusMode(ChP) rp_writech2(ChP,CHNOFF_CHANSTAT(ChP),STATMODE) - -/*************************************************************************** -Function: sEnTransmit -Purpose: Enable transmit -Call: sEnTransmit(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sEnTransmit(ChP) \ -{ \ - (ChP)->TxControl[3] |= TX_ENABLE; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sGetAiopIntStatus -Purpose: Get the AIOP interrupt status -Call: sGetAiopIntStatus(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: Byte_t: The AIOP interrupt status. Bits 0 through 7 - represent channels 0 through 7 respectively. If a - bit is set that channel is interrupting. -*/ -#define sGetAiopIntStatus(CtlP,AIOPNUM) rp_readaiop1(CtlP,AIOPNUM,_INT_CHAN) - -/*************************************************************************** -Function: sGetAiopNumChan -Purpose: Get the number of channels supported by an AIOP -Call: sGetAiopNumChan(CtlP,AiopNum) - CONTROLLER_T *CtlP; Ptr to controller structure - int AiopNum; AIOP number -Return: int: The number of channels supported by the AIOP -*/ -#define sGetAiopNumChan(CtlP,AIOPNUM) CtlP->AiopNumChan[AIOPNUM] - -/*************************************************************************** -Function: sGetChanIntID -Purpose: Get a channel's interrupt identification byte -Call: sGetChanIntID(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel interrupt ID. Can be any - combination of the following flags: - RXF_TRIG: Rx FIFO trigger level interrupt - TXFIFO_MT: Tx FIFO empty interrupt - SRC_INT: Special receive condition interrupt - DELTA_CD: CD change interrupt - DELTA_CTS: CTS change interrupt - DELTA_DSR: DSR change interrupt -*/ -#define sGetChanIntID(ChP) (rp_readch1(ChP,(ChP)->ChanNum+_INT_ID0) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR)) - -/*************************************************************************** -Function: sGetChanNum -Purpose: Get the number of a channel within an AIOP -Call: sGetChanNum(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: Channel number within AIOP, or NULLCHAN if channel does - not exist. -*/ -#define sGetChanNum(ChP) (ChP)->ChanNum - -/*************************************************************************** -Function: sGetChanStatus -Purpose: Get the channel status -Call: sGetChanStatus(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Word_t: The channel status. Can be any combination of - the following flags: - LOW BYTE FLAGS - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available - - HIGH BYTE FLAGS - STATMODE: status mode enable bit - RXFOVERFL: receive FIFO overflow - RX2MATCH: receive compare byte 2 match - RX1MATCH: receive compare byte 1 match - RXBREAK: received BREAK - RXFRAME: received framing error - RXPARITY: received parity error -Warnings: This function will clear the high byte flags in the Channel - Status Register. -*/ -#define sGetChanStatus(ChP) rp_readch2(ChP,CHNOFF_CHANSTAT(ChP)) - -/*************************************************************************** -Function: sGetChanStatusLo -Purpose: Get the low byte only of the channel status -Call: sGetChanStatusLo(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The channel status low byte. Can be any combination - of the following flags: - CTS_ACT: CTS input asserted - DSR_ACT: DSR input asserted - CD_ACT: CD input asserted - TXFIFOMT: Tx FIFO is empty - TXSHRMT: Tx shift register is empty - RDA: Rx data available -*/ -#define sGetChanStatusLo(ChP) rp_readch1(ChP,CHNOFF_CHANSTAT(ChP)) - -/*************************************************************************** -Function: sGetRxCnt -Purpose: Get the number of data bytes in the Rx FIFO -Call: sGetRxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: int: The number of data bytes in the Rx FIFO. -Comments: Byte read of count register is required to obtain Rx count. - -*/ -#define sGetRxCnt(ChP) rp_readch2(ChP,CHNOFF_TXRXCOUNT(ChP)) - -/*************************************************************************** -Function: sGetTxCnt -Purpose: Get the number of data bytes in the Tx FIFO -Call: sGetTxCnt(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: Byte_t: The number of data bytes in the Tx FIFO. -Comments: Byte read of count register is required to obtain Tx count. - -*/ -#define sGetTxCnt(ChP) rp_readch1(ChP,CHNOFF_TXRXCOUNT(ChP)) - -/***************************************************************************** -Function: sGetTxRxDataIO -Purpose: Get the offset of a channel's TxRx Data register -Call: sGetTxRxDataIO(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Return: WordIO_t: offset of a channel's TxRx Data register -*/ -#define sGetTxRxDataIO(ChP) CHNOFF_TXRXDATA(ChP) - -/*************************************************************************** -Function: sInitChanDefaults -Purpose: Initialize a channel structure to its default state. -Call: sInitChanDefaults(ChP) - CHANNEL_T *ChP; Ptr to the channel structure -Comments: This function must be called once for every channel structure - that exists before any other SSCI calls can be made. - -*/ -#define sInitChanDefaults(ChP) \ -{ \ - (ChP)->CtlP = NULLCTLPTR; \ - (ChP)->AiopNum = NULLAIOP; \ - (ChP)->ChanID = AIOPID_NULL; \ - (ChP)->ChanNum = NULLCHAN; \ -} - -/*************************************************************************** -Function: sResetAiopByNum -Purpose: Reset the AIOP by number -Call: sResetAiopByNum(CTLP,AIOPNUM) - CONTROLLER_T CTLP; Ptr to controller structure - AIOPNUM; AIOP index -*/ -#define sResetAiopByNum(CTLP,AIOPNUM) \ -{ \ - rp_writeaiop1(CTLP,AIOPNUM,_CMD_REG,RESET_ALL); \ - rp_writeaiop1(CTLP,AIOPNUM,_CMD_REG,0x0); \ -} - -/*************************************************************************** -Function: sSendBreak -Purpose: Send a transmit BREAK signal -Call: sSendBreak(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSendBreak(ChP) \ -{ \ - (ChP)->TxControl[3] |= SETBREAK; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetBaud -Purpose: Set baud rate -Call: sSetBaud(ChP,Divisor) - CHANNEL_T *ChP; Ptr to channel structure - Word_t Divisor; 16 bit baud rate divisor for channel -*/ -#define sSetBaud(ChP,DIVISOR) \ -{ \ - (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \ - (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->BaudDiv)); \ -} - -/*************************************************************************** -Function: sSetData7 -Purpose: Set data bits to 7 -Call: sSetData7(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData7(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~DATA8BIT; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetData8 -Purpose: Set data bits to 8 -Call: sSetData8(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetData8(ChP) \ -{ \ - (ChP)->TxControl[2] |= DATA8BIT; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetDTR -Purpose: Set the DTR output -Call: sSetDTR(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetDTR(ChP) \ -{ \ - (ChP)->TxControl[3] |= SET_DTR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetEvenParity -Purpose: Set even parity -Call: sSetEvenParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetEvenParity(ChP) \ -{ \ - (ChP)->TxControl[2] |= EVEN_PAR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetOddParity -Purpose: Set odd parity -Call: sSetOddParity(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: Function sSetParity() can be used in place of functions sEnParity(), - sDisParity(), sSetOddParity(), and sSetEvenParity(). - -Warnings: This function has no effect unless parity is enabled with function - sEnParity(). -*/ -#define sSetOddParity(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~EVEN_PAR; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetRTS -Purpose: Set the RTS output -Call: sSetRTS(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetRTS(ChP) \ -{ \ - (ChP)->TxControl[3] |= SET_RTS; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetRxTrigger -Purpose: Set the Rx FIFO trigger level -Call: sSetRxProcessor(ChP,Level) - CHANNEL_T *ChP; Ptr to channel structure - Byte_t Level; Number of characters in Rx FIFO at which the - interrupt will be generated. Can be any of the following flags: - - TRIG_NO: no trigger - TRIG_1: 1 character in FIFO - TRIG_1_2: FIFO 1/2 full - TRIG_7_8: FIFO 7/8 full -Comments: An interrupt will be generated when the trigger level is reached - only if function sEnInterrupt() has been called with flag - RXINT_EN set. The RXF_TRIG flag in the Interrupt Idenfification - register will be set whenever the trigger level is reached - regardless of the setting of RXINT_EN. - -*/ -#define sSetRxTrigger(ChP,LEVEL) \ -{ \ - (ChP)->RxControl[2] &= ~TRIG_MASK; \ - (ChP)->RxControl[2] |= LEVEL; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->RxControl)); \ -} - -/*************************************************************************** -Function: sSetStop1 -Purpose: Set stop bits to 1 -Call: sSetStop1(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop1(ChP) \ -{ \ - (ChP)->TxControl[2] &= ~STOP2; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sSetStop2 -Purpose: Set stop bits to 2 -Call: sSetStop2(ChP) - CHANNEL_T *ChP; Ptr to channel structure -*/ -#define sSetStop2(ChP) \ -{ \ - (ChP)->TxControl[2] |= STOP2; \ - rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->TxControl)); \ -} - -/*************************************************************************** -Function: sStartRxProcessor -Purpose: Start a channel's receive processor -Call: sStartRxProcessor(ChP) - CHANNEL_T *ChP; Ptr to channel structure -Comments: This function is used to start a Rx processor after it was - stopped with sStopRxProcessor() or sStopSWInFlowCtl(). It - will restart both the Rx processor and software input flow control. - -*/ -#define sStartRxProcessor(ChP) rp_writech4(ChP,_INDX_ADDR,le32dec((ChP)->R)) - -/*************************************************************************** -Function: sWriteTxByte -Purpose: Write a transmit data byte to a channel. - CHANNEL_T *ChP; Ptr to channel structure - ByteIO_t io: Channel transmit register I/O address. This can - be obtained with sGetTxRxDataIO(). - Byte_t Data; The transmit data byte. -Warnings: This function writes the data byte without checking to see if - sMaxTxSize is exceeded in the Tx FIFO. -*/ -#define sWriteTxByte(ChP,IO,DATA) rp_writech1(ChP,IO,DATA) - -int sReadAiopID(CONTROLLER_T *CtlP, int aiop); -int sReadAiopNumChan(CONTROLLER_T *CtlP, int aiop); -int sInitChan( CONTROLLER_T *CtlP, - CHANNEL_T *ChP, - int AiopNum, - int ChanNum); -Byte_t sGetRxErrStatus(CHANNEL_T *ChP); -void sStopRxProcessor(CHANNEL_T *ChP); -void sStopSWInFlowCtl(CHANNEL_T *ChP); -void sFlushRxFIFO(CHANNEL_T *ChP); -void sFlushTxFIFO(CHANNEL_T *ChP); -int sWriteTxPrioByte(CHANNEL_T *ChP, Byte_t Data); -void sEnInterrupts(CHANNEL_T *ChP,Word_t Flags); -void sDisInterrupts(CHANNEL_T *ChP,Word_t Flags); -int rp_attachcommon(CONTROLLER_T *ctlp, int num_aiops, int num_ports); -void rp_releaseresource(CONTROLLER_t *ctlp); -static __inline void -rp_lock(CONTROLLER_T *CtlP) -{ - if (CtlP->hwmtx_init != 0) - mtx_lock(&CtlP->hwmtx); -} -static __inline void -rp_unlock(CONTROLLER_T *CtlP) -{ - if (CtlP->hwmtx_init != 0) - mtx_unlock(&CtlP->hwmtx); -} - -#ifndef ROCKET_C -extern Byte_t R[RDATASIZE]; -extern CONTROLLER_T sController[CTL_SIZE]; -extern Byte_t sIRQMap[16]; -#endif -extern Byte_t rp_sBitMapClrTbl[8]; -extern Byte_t rp_sBitMapSetTbl[8]; Index: sys/dev/rp/rpvar.h =================================================================== --- sys/dev/rp/rpvar.h +++ sys/dev/rp/rpvar.h @@ -1,76 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-4-Clause - * - * Copyright (c) Comtrol Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted prodived that the follwoing conditions - * are met. - * 1. Redistributions of source code must retain the above copyright - * notive, this list of conditions and the following disclainer. - * 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 prodided 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 Comtrol Corporation. - * 4. The name of Comtrol Corporation may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY COMTROL CORPORATION ``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 COMTROL CORPORATION 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, LIFE 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$ - */ - -/* - * rpvar.h --- RocketPort data structure includes for FreeBSD - */ - -#define RP_UNIT(x) dv_unit(x) -#define RP_PORT(x) (dev2unit(x) & 0x3f) -#define MAX_RP_PORTS 128 - - -struct rp_port { - struct tty * rp_tty; /* cross reference */ - struct callout rp_timer; - - unsigned char state; /* state of dtr */ - - int rp_port; - int rp_flags; - int rp_unit:2; - int rp_aiop:2; - int rp_chan:3; - int rp_intmask; - int rp_imask; /* Input mask */ - int rp_fifo_lw; - int rp_restart; - int rp_overflows; - int rp_rts_iflow:1; - int rp_disable_writes:1; - int rp_cts:1; - int rp_waiting:1; - int rp_xmit_stopped:1; - CONTROLLER_t * rp_ctlp; - CHANNEL_t rp_channel; - unsigned char TxBuf[TXFIFO_SIZE]; - unsigned char RxBuf[RXFIFO_SIZE]; -}; - -/* Actually not used */ -#ifdef notdef -extern struct termios deftermios; -#endif /* notdef */ Index: sys/modules/rc/Makefile =================================================================== --- sys/modules/rc/Makefile +++ sys/modules/rc/Makefile @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/rc - -KMOD= rc -SRCS= rc.c device_if.h bus_if.h isa_if.h - -.include