FAS 2.09 async driver, part 2/4

Uwe Doering gemini at geminix.in-berlin.de
Mon Jun 24 06:29:01 AEST 1991


Submitted-by: gemini at geminix.in-berlin.de
Archive-name: fas209/part02

#!/bin/sh
# this is fas209.02 (part 2 of fas209)
# do not concatenate these parts, unpack them in order with /bin/sh
# file README continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 2; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
	echo 'x - still skipping README'
else
echo 'x - continuing file README'
sed 's/^X//' << 'SHAR_EOF' >> 'README' &&
X
X     Makefile.ISC   A makefile for ISC 386/ix systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X     Makefile.ESIX  A makefile for ESIX systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X     Makefile.BELL  A makefile for Bell Tech/Intel UNIX 3.2 systems.  This
X                    is generic and should work for all configurations of
X                    lines and interrupts.
X
X     Makefile.SCO   A makefile for SCO UNIX 386 systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X     Makefile.X386  A makefile for SCO Xenix 386 systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X     Makefile.X286  A makefile for SCO Xenix 286 systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X     Makefile.ATT   A makefile for AT&T UNIX 386 systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X     Makefile.SVR4  A makefile for SysVr4 UNIX 386 systems.  This is generic
X                    and should work for all configurations of lines
X                    and interrupts.
X
X------------------------------------------------------------------------
X
XWhat you will need to use this package:
X
X     You will need one of the above mentioned UNIX systems with the
X     kernel link kit and the software development package.
X
X------------------------------------------------------------------------
X
XThe original asy replacement driver for Microport UNIX/386 (FAS' predecessor)
Xwas developed by
X
XJim Murray              INET            jjm%jjmhome at m2c.m2c.org
X2 Mohawk Circle         UUCP            harvard!m2c!jjmhome!jjm
XWestboro Mass 01581     
XUSA                                     voice (508) 366-2813
X
XCredits to him for releasing this great driver to the Usenet community.
XBut if you have problems with FAS please don't contact him because he
Xwasn't involved in the developement of FAS.
X
XFAS was developed by
X
XUwe Doering             INET : gemini at geminix.in-berlin.de
XBillstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
X1000 Berlin 20
XGermany
X
X    ^    ^    ^    ^    ^    ^    ^    ^    ^    ^
XSend your questions and bug reports to this address.
SHAR_EOF
echo 'File README is complete' &&
true || echo 'restore of README failed'
rm -f _shar_wnt_.tmp
fi
# ============= RELEASENOTES ==============
if test -f 'RELEASENOTES' -a X"$1" != X"-c"; then
	echo 'x - skipping RELEASENOTES (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting RELEASENOTES (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'RELEASENOTES' &&
X     release 1.1a Sat Nov 11, 1989
X
X     This is an unofficial release as I'm not the original author
X     of this async driver.
X
X     Uwe Doering             INET : gemini at geminix.in-berlin.de
X     Billstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
X     1000 Berlin 20
X     Germany
X
X     New Features:
X
X          Added a third minor tty device number for every physical
X          port. See description preceding the asyopen function in
X          asy.c. Changed the behavior of ttyxx, too.
X
X          Added output hardware handshake support for DSR. Now you
X          can do handshake with CTS, DSR or both. Input hardware
X          handshake is on if you use at least one of the output
X          handshake signals.
X
X          More flexible support of additional interrupt registers
X          on mux boards. This is fully configurable now.
X
X          Added support for the CREAD flag. If not set, receiver
X          interrupts are still serviced, but the received characters
X          are simply thrown away. This is not as elegant as disabeling
X          the interrupts themselves, but with the already existing
X          driver it was the easiest way, and the most new-bugs-preventing,
X          too.
X
X          Added a lot of comments to the source so that the curious
X          user can understand why and how things are done.
X
X
X     Bug Fixes:
X
X          The hang-up-on-last-close flag (HUPCL) was ignored. DTR
X          was asserted regardless of this flag.
X
X          Made the detection of CTS and DCD more bullet-proof.
X          Especially because between a close and the next open of
X          a line, where interrupts are ignored, the software copys of
X          CTS and DCD must be set up propperly in the asyopen function
X          or the tty line would be blocked under certain circum-
X          stances. For similar reasons, there is also a setup in the
X          asyparam function.
X
X          Rewrote the input character processing function to work
X          according to the TERMIO(7) man page.
X
X          Changed the behavior of BREAK generation to let the
X          transmitter drain before TX is set to low.
X
X          Changed line hangup procedure so that the closing
X          process returns immediately and doesn't sleep during
X          the hangup delay/time. Instead, if an other process tries
X          to open the line while hangup is still in progress, this
X          process will sleep until hangup is competed.
X
X          With DOS Merge, on MicroPort V/386 3.0e the linker was
X          missing the function `init8250'. Reengineered this from
X          a disassembler listing of MicroPort's original driver and
X          modified it to work with the NS16550A 16-byte FIFO. This
X          funktion was added simply to be able to link the kernel.
X          DOS Merge's virtual COM ports are still unusable with this
X          release, though. To include this function, add a `-DMERGE'
X          to the CFLAGS line in your makefile.
X
X          Made a lot of other corrections and enhancements in both
X          speed and functionallity. As a result of all my effords
X          I think this driver is slightly faster, more versatile
X          and much more stable than the original release.
X
X     ------------------------------------------------------------
X          
X     release 1.1b Sat Nov 25, 1989
X
X     New Features:
X
X          Changed the minor device number scheme again.
X          There are now two main groups: The unblocked open
X          and the blocked open. Every group has four sub-modes
X          and an additional hardware handshake flag. All this
X          is coded in the higher four bits of the minor device
X          number. Because of this, the maximum of 32 ports was
X          reduced to 16 ports so that the port number fits into
X          the remaining lower four bits of the minor device number.
X          32 dumb ports in a single machine would have been overkill
X          anyway. For more details refer to the description in the
X          README file.
X
X     ------------------------------------------------------------
X          
X     release 2.00 Mon Nov 27, 1989
X
X     As this release differs so much from the original version I got,
X     I now declare this as independant from the original author
X     Jim Murray. This allows me to introduce new release levels
X     without wondering whether they will collide with Jim's releases.
X     Of course many credits to Jim for writing this software in the
X     first place. Without his driver as a base I never would have
X     been able to do such kernel driver development.
X
X     Bug Fixes:
X
X          If there were glitches on the hardware handshake lines
X          and the DCD line a getty on this port would sometimes
X          hang and become an immortal process. I think this was
X          because the output buffer wasn't flushed properly
X          on carrier loss. I hope I fixed this now. We'll see.
X
X     ------------------------------------------------------------
X          
X     release 2.01 Tue Nov 28, 1989
X
X     Did some cleanup in the source code.
X
X     I splitted the driver into two parts: The driver itself and
X     the file `space.c'.
X     `space.c' contains all data structures necessary to configure
X     the driver and is compiled at kernel link time. Therefore, if you
X     change your serial card configuration you simply change `space.c'
X     directly in the link kit directory and relink the kernel. No
X     driver recompilation or installation is necessary for this.
X     But note that whenever you use `make install' your setup in
X     the link kit directory is overwritten by the original `space.c'
X     file. Therefore, you should copy your new `space.c' back to
X     the source directory when you are finished with the configuration.
X
X     Renamed the package to `FAS Final Async Solution'. The following
X     files have been renamed:
X          asy.c          -> fas.c
X          asy.h          -> fas.h
X          asy_conf-xxxxx -> space-xxxxx
X
X     ISC 386/ix is supported now. There are separate makefiles
X     for uPort and ISC to cope with the differences in link kit
X     installation.
X
X     Bug Fixes:
X
X          `getty' still hung sometimes on a line with hardware
X          handshake. Tried to fix it this time.
X
X     ------------------------------------------------------------
X          
X     release 2.02 Thu Nov 30, 1989
X
X     Abandoned the distinction between space-xxxxx files with
X     and without hardware flow control because this is selected
X     by the minor device number now.
X
X     Bug Fixes:
X
X          Set the high and low water marks for hardware input flow
X          control to higher values than software flow control. This
X          gives precedence to software flow control if both methods
X          are used. These marks are self-adjusting and don't need to
X          be changed if some flavor of UNIX has a different buffer
X          size than the standard 256 characters. Before this change
X          concurrent use of both flow controls could cause trouble
X          with some high-speed modems. This is fixed now.
X
X          A flush read or write buffer request now also clears the
X          receiver or transmitter FIFO, respectively. An ioctl
X          call with a TCSETA* command clears the FIFOs, too.
X
X     ------------------------------------------------------------
X          
X     release 2.03 Fri Dec 01, 1989
X
X     Wrote an installation guide. The driver should be quite
X     easy to install now.
X
X     Added tty node configuration files for ISC.
X
X     Hardware input flow control is bound now to the level of the
X     receiver ring buffer instead of the UNIX input buffer. This
X     has the advantage that buffer size and trigger levels are
X     defined in the driver and therefore can be varied as needed.
X
X     New Features:
X
X          Added a boot time status message that shows the init
X          state of each port. This tells you immediately what
X          ports are found and initted by the driver. Useful to
X          determine hardware configuration problems. Look at
X          the description in the README file. Thanks to
X          Kritt Gierlewsen (kritt at einoed.UUCP) for this proposal.
X
X     ------------------------------------------------------------
X          
X     release 2.04 Thu Dec 07, 1989
X
X     Did some cleanup in the source.
X
X     Removed the FIFO clear from the ioctl function. We don't want
X     to do things there that aren't in the book.
X
X     An ioctl call that switches off the CLOCAL flag will create
X     a SIGHUP signal if the carrier is actually missing at this
X     time.
X
X     Every device is tested now quite thoroughly during initialization.
X     If the test fails the corresponding device keeps unconfigured.
X
X     ------------------------------------------------------------
X          
X     release 2.05 Sat Jan 13, 1990
X
X     This is the first public release of the FAS driver.
X
X     Special thanks to the sysops of my test sites, Axel Fischer
X     (fischer at utower.UUCP) and Kritt Gierlewsen (kritt at einoed.UUCP).
X
X     FAS is now an independant driver with its own driver name (`fas'),
X     major device number, link kit directory and other things necessary
X     for a driver. The original asy driver may or may not be linked
X     with the kernel. You only need it if you want to access some
X     serial devices via the virtual COM ports of the DOS emulator
X     (DosMerge or VP/ix) because the FAS driver doesn't have this
X     (really vendor dependant) feature.
X
X     The default prefix for tty device node names is `ttyF' now.
X     This prevents mix-ups with the device names of the original
X     asy driver.
X
X     Dropped the SYSV/AT support. I couldn't test the driver
X     for several release generations on uPort SYSV/AT, and because
X     there are not very much systems left with that flavor of UNIX
X     it doesn't make sense to try to maintain compatibility with it.
X     If someone really wants to use this driver on a 286 he has
X     to port it himself.
X
X     Improved the transmitter FIFO fill procedure. Now it will try
X     harder to fill the FIFO as much as possible to cut down on
X     transmitter interrupts.
X
X     Software input flow control (XON/XOFF) is controlled by the driver now.
X     It is bound to the level of the receiver ring buffer (as is hardware
X     flow control). As usual, it can be switched on and off by the
X     IXOFF flag in the termio(7) structure.
X
X     Changed and speeded up the ring buffer -> unix buffer processing.
X
X     For ISC, the getty lines for the inittab file are installed
X     by the makefile now.
X
X     The conditional compilation of the function `init8250' (for
X     DosMerge) is now controlled by a define in `fas.h'. The compiler
X     switch `-DMERGE' is not used any more.
X
X     Improved the documentation.
X
X     The signals used for modem control and hardware flow control are
X     fully configurable in the `space.c' file now. Look at `fas.h' for
X     possible macros and combinations.
X
X     There are some new modes for hardware flow control, for instance
X     HO_CTS_ON_DSR. This means that CTS is only looked at if DSR is on.
X     If DSR is off output is possible regardless of CTS. The underlying
X     assumption here is that we can expect proper handshake handling
X     only from devices that are in the ready state (indicated by DSR).
X     As a spin-off the problem with the hanging getty on lines with
X     turned-off terminals (mentioned in earlier releases) should be
X     gone if you use this new mode.
X
X     If the XCLUDE-Flag is availabe (SYSV 3.2 because of Xenix
X     compatibility) exclusive open of a device is possible.
X
X     The default size of the input ring buffer is now 5000 bytes.
X     This makes streaming input more likely even on loaded systems.
X
X     Bug Fixes:
X
X          The task state busy flag wasn't reset in some rare cases.
X          This could cause processes to become immortal while waiting
X          for the busy flag.
X
X          Under some special conditions an ioctl call with a TCSETA?
X          command could corrupt the last character in the transmitter
X          shift register. This is fixed now.
X
X          More fixing of the busy flag handling was necessary.
X          Co-ordinating several delayed tasks controlling this flag
X          is kind of tricky.
X
X          After a TCSETA* ioctl command we disable the transmitter
X          for 2 sec (measured from the last transmitted character)
X          if the character format and/or speed has changed. This
X          gives the receiving side some time to do the same changes.
X          This is kind of experimental. There may be applications that
X          suffer from this delay. You may change the #define ADAPT_TIME
X          in `fas.h' to a smaller value.
X
X     ------------------------------------------------------------
X          
X     release 2.06 Fri Mar 16, 1990
X
X     This should have been patch #3 for release 2.05, but there are
X     so many changes now that I decided to make it a new release.
X     Therefore, some of the changes are described in the 2.05 release
X     notes above but were never released to the public.
X
X     New Features:
X
X          There is a transmitter ring buffer now to make the output
X          less system load dependent. This really speeds things up
X          because the transmitter FIFO gets filled with more characters
X          at once. The buffer size depends on the actual baud rate to
X          prevent long output buffer drains at low speeds.
X
X          There are also bigger input buffers to make FAS more competitive
X          against "intelligent" cards.
X
X          Lots of speed improvements and many small changes.
X
X     Bug Fixes:
X
X          Fixed input/output buffer flush on carrier loss while close
X          is waiting for the output to drain.
X
X     ------------------------------------------------------------
X          
X     release 2.07 Tue Sep 18, 1990
X
X     This is a major redesign of the previous release. I put most of the
X     time consuming tasks in one function that is invoked asynchronously
X     by timeout calls. Inside this function most of the code runs at
X     a lower system priority level (spl5) than the interrupts. That
X     means that during character processing tty interrupts are allowed.
X     This is the main key to operation at 38400 bps on multiple ports
X     at the same time which is possible now with this release.
X
X     New Features:
X
X          FAS supports the VP/ix DOS emulator!
X          Now you can throw out the vendor's original driver even
X          if you like to have a serial mouse or modem access in DOS.
X          Read the paragraph about VP/ix in the README file.
X
X          The Intel i82510 port chip is supported. It has separate
X          4-character FIFOs for input and output. Although the
X          NS16550A is much better this chip is your second choice
X          if you can't get your hands on the National chips.
X          Thanks to Christian Seyb (cs at gold.UUCP) for sending me
X          patches and the necessary documentation for the Intel
X          chips.
X
X          There is an init sequence in `space.c'. You can put any
X          number of address-data pairs in a null terminated array
X          to program your serial card or other hardware before
X          FAS makes the first access to the ports. AST 4-port cards,
X          for instance, have an additional port that needs to be
X          written to with a certain bit pattern to allow shared
X          interrupts. If you need to read a port to achieve the
X          setting or resetting of flags as a side effect, this
X          is possible, too.
X
X          ESIX is officially supported now.
X
X          SCO UNIX is officially supported, too. FAS needs to be
X          compiled with the command line flag `-DSCO'. The makefile
X          for SCO takes care of that. Thanks to Walter Mecky
X          (walter at mecky.systemware.de) and Frank Simon
X          (terra at sol.north.de) for helping me in making the necessary
X          changes for SCO UNIX.
X
X          SCO Xenix 386 is also officially supported. FAS needs to be
X          compiled with the command line flag `-DXENIX'. The makefile
X          for SCO Xenix takes care of that. Thanks to Andreas
X          Steinmetzler (andreas at oil.UUCP) for doing the port.
X
X          If you have the RTSFLOW and CTSFLOW termio(7) flags,
X          hardware handshake can be controlled by them.
X          Note that enabling handware flow control via the
X          minor device number overrides these flags. If you
X          like to use them you need to create tty device nodes
X          with minor device numbers in which the bit for hardware
X          handshake is set to 0. Look at the description in the
X          README file for more details.
X          Note also that if you choose to use RTSFLOW and CTSFLOW
X          all your programs that do initial access to tty devices
X          (getty, uucico, cu, SLIP dialup program etc.) need to know
X          about these flags or hardware handshake will not be used.
X
X          The `O_EXCL' flag for the open(2) call is honored now.
X          This allowes exclusive access to an FAS device without
X          suffering from race conditions which could occure with
X          the termio(7) XCLUDE flag method.
X
X          The `fas_test_device' function returns a digit now that
X          indicates at which phase the test exited due to an error.
X          This error digit is displayed in the boot message. Thanks
X          to Brian Beattie (beattie at visenix.UUCP) for sending me
X          the necessary patches.
X
X     Bug Fixes:
X
X          Automatic input FIFO flush after unblocking the getty
X          open by the carrier or the unblock signal. This makes sure
X          that there is no chance that there are characters in the
X          FIFO that were received before the open got unblocked.
X
X          The sdevice entry for the AST 4-port card had a wrong
X          I/O address range (`s_fas-mux4'). This didn't affect FAS
X          but is checked by the kernel config program.
X
X          The gcc (GNU cc) support was removed because gcc's object
X          file wants to link in some "helpful" functions that aren't
X          contained in the kernel. But anyway, FAS is tuned so carefully
X          and depends on the optimization behaviour of the AT&T
X          standard C compiler that gcc won't have any advantages.
X
X          I changed the method with which the `fas_test_device' function
X          waits for certain events. The `delay' function was used
X          for that purpose but it turned out that with some flavors
X          of UNIX it is prohibited to use this function during the
X          xxinit phase of the boot process. Now a simple timeout loop
X          is used instead.
X
X          Removed the ADAPT_TIME mechanismn introduced in release 2.05.
X
X          The open() call now returns an `EBUSY' error number if the
X          device is already open and can't be opened in the desired
X          mode at this time.
X
X          The handling of the RING signal needed fixing. Unlike the other
X          three modem status lines RING generates an interrupt only at
X          the trailing edge.
X
X          No SIGHUP signal is sent any more if an ioctl call clears
X          the CLOCAL termio(7) flag while there is no carrier present.
X          SIGHUP is only sent if the actual DCD modem line drops.
X
X          The files *-mux4 were renamed to *-ast4 because this type of
X          card was originally developed by AST (AST 4-port card).
X
X     ------------------------------------------------------------
X          
X     release 2.08 Sun Feb 03, 1991
X
X     New Features:
X
X          Bell Tech/Intel UNIX 3.2 is supported.
X
X          SCO Xenix 286 is also supported now. Thanks to Nickolay Saukh
X          (nms at saukh.rd.jvd.su) for providing the patches.
X
X          The Bell Tech HUB-6 card can be used with FAS. Thanks to
X          Keith Walker (kew at cims2.UUCP) for the patches.
X
X          For AT&T derived flavors of UNIX there is a line automatically
X          added to the kernel description file that makes the adding
X          and removing of FAS possible via the `kconfig' program. Thanks
X          to John Adams (johna at grumpy.boston.ma.us) for this idea.
X
X          There is a mechanismn now that prevents excessive modem status
X          interrupts caused by crosstalking between wires or by a loose
X          cable.
X
X          You can disable the FIFOs in a UART by "oring" the macro
X          `NO_FIFO' to the base port address of this device. This is
X          useful for mouse devices where you need immediate response
X          to the mouse movement.
X
X          The meaning of the bit mapped part of the minor device
X          numbers has changed. Some rather useless functions were
X          removed in favor of more control over the hardware handshake
X          modes. Even systems where the SCO RTSFLOW/CTSFLOW termio(7)
X          flags are not available can now use half duplex hardware
X          flow control (selected via the minor device number).
X
X          The assignment of RS232C lines to certain FAS functions
X          is even more flexible now. This allows to connect two
X          UNIX systems (with FAS) via a null modem cable, running
X          a getty at both ends. For more details, read the paragraph
X          about CABLING in the README file.
X
X          A special handling of the NS16550A input FIFO was introduced.
X          This causes multiple receiver interrupts (on the same IRQ
X          line) to be synchronized so that only one interrupt is
X          necessary to process all receiving ports. This reduces the
X          interrupt handling overhead and therefore results in lower
X          CPU load for concurrent serial input at high speeds.
X
X          The `fas_event' function processes all scheduled events
X          for all units with one single call. Previously, every unit
X          launched its own timeout() call if there was work to
X          do. This could lead to up to 16 timeouts at the same time,
X          resulting in some timeout handling overhead. This overhead
X          is minimized now.
X
X     Bug Fixes:
X
X          There were two bugs that could cause a port to lock up,
X          resulting in an immortal process.
X
X          Almost any kernel sleep is killable now (at least with one or
X          two `kill -9'). Therefore, there should be no more immortal
X          processes. Even killing a process that is hanging in a
X          close-on-exit call is possible.
X
X          The meaning of the RTSFLOW/CTSFLOW termio(7) flags was converted
X          to what SCO had in mind (half duplex flow control). This is for
X          compatibility reasons. Full duplex RTS/CTS hardware flow control
X          is still possible via the minor device number method. Thanks to
X          Dmitry V. Volodin (dvv at hq.demos.su) for providing me with the
X          necessary knowledge.
X
X          If a process is already sleeping in a getty open it will only
X          unblock on DCD low->high. In particular, if in the meantime
X          the device was open for dialout and DCD is still present if
X          the getty open takes over again this won't unblock the getty
X          open any more.
X
X          And there were, as usual, a number of other small bug fixes.
X
X     ------------------------------------------------------------
X          
X     release 2.09 Sun Jun 23, 1991
X
X     New Features:
X
X          AT&T UNIX 3.2 Version 2.1 is supported.
X
X          Support was added for SysVr4 UNIX 386 (with the tty compatibility
X          drivers). This was mostly a problem of ANSI-fying certain parts
X          of the FAS sources. For this operating system, there is no VP/ix
X          support in FAS. This will change when FAS is converted into a
X          STREAMS driver.
X
X          Killing a process hanging on an FAS port that had output
X          flow stopped was usually done by issuing one or two `kill -9'
X          commands. However, this method could hang the whole UNIX kernel.
X          Therefore, another method to release hung processes is
X          introduced in this release.
X          If you open an FAS device with the O_TRUNC flag, the input
X          and output buffers of that device get flushed. As a side
X          effect, if you had previously tried to kill a hung process,
X          and it continued to hang on an FAS device, you simply have
X          to open that device with the O_TRUNC flag, and the hung
X          process is released. All you have to do is to type
X          echo '\c' > /dev/ttyname
X          and the device buffers are flushed.
X
X          There is a new array called fas_overrun[], which is of
X          type `uint', that contains three receiver overrun counters
X          for NS16450, i82510 and NS16550A UART chips, in that order.
X          If you have a tool that permits you to look at kernel
X          variables during runtime, you can determine yourself
X          whether the problems you may have might be caused by
X          lost input characters. With every receiver overrun, the
X          respective counter is incremented by one.
X
X     Bug Fixes:
X
X          The problem with the excessive modem status interrupts
X          is fixed. Well, kind of. It is suppressed, at least.
X          Crosstalk between the lines in a serial cable wastes
X          only a minor amount of CPU time now. Therefore, it isn't
X          necessary any more to shut down a port when this happens.
X          However, if you use an operating mode (selected by the
X          minor device number) that assigns certain functions to
X          the input pins at the RS232C connector (DCD, DSR, CTS and
X          RI), and these pins toggle because of crosstalk in the cable,
X          problems may still occure. But at least it won't panic the
X          kernel any more, nor will it consume lots of CPU time.
X
X          Additionally, in operating modes where FAS doesn't need to
X          know anything about modem status lines, the modem status
X          interrupt is actually disabled. For instance, when a minor
X          device number of 0 + port# is used. On the other hand,
X          switching the device to DOS mode always _enables_ the
X          modem status interrupts.
X
X          A problem was fixed when a port was in the canonical (cooked)
X          mode and FAS still tried to protect the CLIST input buffer
X          from overflowing. This blocked the connected terminal until
X          a break signal or a hangup. The input buffer protection
X          should, of course, only happen in raw mode.
X
X          The TIMEOUT tty state flag isn't used any more by FAS.
X          Because this flag is used by the line discipline as well,
X          its usage in FAS could cause problems.
X
X          There was a bug in the handling of one pointer in the
X          fas_test_device() function.
X
X          In fas_event(), looping for the same port several times until
X          all events are serviced could cause temporary deadlocks. We
X          now don't loop any more. If an event occures while in fas_event(),
X          but the branch responsible for processing was already passed,
X          this event has to wait until the next call of fas_event()
X          (usually one or two kernel ticks later).
X
X          The AIOCINFO ioctl() command returned the minor device number.
X          Now it returns the unit number.
X
X          SIGHUP will be sent only if the port is the controlling terminal
X          of a process group.
X
X          There was a problem with the initialization macros for the
X          fas_modem[] and fas_flow[] arrays. Under Xenix 286, some
X          of these macros expanded to a value of zero because the
X          size of type int is 16 bits, while it is 32 bits for all
X          the 386 UNIX flavors. This resulted in dropped bits with
X          some macros that use the `<<' operator.
X
X          An fasopen() call is checked immediately for permissions now,
X          even if another process is currently hanging in fasclose().
X          The fasopen() call, of course, can be completed only after
X          the other process has returned from fasclose().
SHAR_EOF
true || echo 'restore of RELEASENOTES failed'
rm -f _shar_wnt_.tmp
fi
# ============= config-ast4 ==============
if test -f 'config-ast4' -a X"$1" != X"-c"; then
	echo 'x - skipping config-ast4 (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting config-ast4 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-ast4' &&
X* its character device number 4
Xcharacter(4)
X
X* its name
Xprefix = fas
X
X* The interrupt vectors handled by this controller
Xintvec = 4
X
X* its mask level
Xintpri = SPLTTY
X
X* the functions it supports
Xfunctions = init, open, close, read, write, ioctl, tty
SHAR_EOF
true || echo 'restore of config-ast4 failed'
rm -f _shar_wnt_.tmp
fi
# ============= config-ast4c12 ==============
if test -f 'config-ast4c12' -a X"$1" != X"-c"; then
	echo 'x - skipping config-ast4c12 (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting config-ast4c12 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-ast4c12' &&
X* its character device number 4
Xcharacter(4)
X
X* its name
Xprefix = fas
X
X* The interrupt vectors handled by this controller
Xintvec = 9,4,3
X
X* its mask level
Xintpri = SPLTTY
X
X* the functions it supports
Xfunctions = init, open, close, read, write, ioctl, tty
SHAR_EOF
true || echo 'restore of config-ast4c12 failed'
rm -f _shar_wnt_.tmp
fi
# ============= config-c1-2 ==============
if test -f 'config-c1-2' -a X"$1" != X"-c"; then
	echo 'x - skipping config-c1-2 (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting config-c1-2 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-c1-2' &&
X* its character device number 4
Xcharacter(4)
X
X* its name
Xprefix = fas
X
X* The interrupt vectors handled by this controller
Xintvec = 4,3
X
X* its mask level
Xintpri = SPLTTY
X
X* the functions it supports
Xfunctions = init, open, close, read, write, ioctl, tty
SHAR_EOF
true || echo 'restore of config-c1-2 failed'
rm -f _shar_wnt_.tmp
fi
# ============= config-c1-3 ==============
if test -f 'config-c1-3' -a X"$1" != X"-c"; then
	echo 'x - skipping config-c1-3 (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting config-c1-3 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-c1-3' &&
X* its character device number 4
Xcharacter(4)
X
X* its name
Xprefix = fas
X
X* The interrupt vectors handled by this controller
Xintvec = 4,3,9
X
X* its mask level
Xintpri = SPLTTY
X
X* the functions it supports
Xfunctions = init, open, close, read, write, ioctl, tty
SHAR_EOF
true || echo 'restore of config-c1-3 failed'
rm -f _shar_wnt_.tmp
fi
# ============= config-hub6 ==============
if test -f 'config-hub6' -a X"$1" != X"-c"; then
	echo 'x - skipping config-hub6 (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting config-hub6 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-hub6' &&
X* its character device number 4
Xcharacter(4)
X
X* its name
Xprefix = fas
X
X* The interrupt vectors handled by this controller
Xintvec = 3
X
X* its mask level
Xintpri = SPLTTY
X
X* the functions it supports
Xfunctions = init, open, close, read, write, ioctl, tty
SHAR_EOF
true || echo 'restore of config-hub6 failed'
rm -f _shar_wnt_.tmp
fi
# ============= fas.c ==============
if test -f 'fas.c' -a X"$1" != X"-c"; then
	echo 'x - skipping fas.c (File already exists)'
	rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting fas.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'fas.c' &&
X/* FAS Final Async Solution driver for 286/386 versions of system V UNIX */
X
X/* FAS was developed by
XUwe Doering             INET : gemini at geminix.in-berlin.de
XBillstedter Pfad 17 b   UUCP : ...!unido!fub!geminix.in-berlin.de!gemini
X1000 Berlin 20
XGermany
X*/
X
X#if !defined (M_I286)
X#ident	"@(#)fas.c	2.09"
X#endif
X
X/* Note: This source code was quite heavily optimized for speed. You
X         may wonder that register variables aren't used everywhere.
X         This is because there is an overhead in memory accesses
X         when using register variables. As you may know data accesses
X         usually need much more wait states on the memory bus than
X         code accesses (because of page or cache misses). Therefore,
X         saving some data accesses has higher priority than saving
X         code accesses.
X
X         You may also note some not very elegant constructions that
X         may be intentional because they are faster. If you want to
X         make style improvements you should check the assembler output
X         whether this wouldn't slow things down.
X
X         Decisions for speed optimization were based on assembler
X         listings produced by the standard UNIX V [34].X/386 C compiler.
X*/
X
X#if defined (XENIX)
X#include "fas.h"
X#else
X#include <sys/fas.h>
X#if !defined (NO_ASM)
X#include <sys/inline.h>
X#endif
X#endif
X
X#if defined (SCO) || defined (XENIX)
X#define asyputchar sioputchar
X#define asygetchar siogetchar
X#endif
X
X#if defined (XENIX) || defined (NO_ASM)
X#define intr_disable()	old_level = SPLINT ()
X#define intr_restore()	(void) splx (old_level)
X#define REGVAR
X#else
X/* This is a terrible ugly kludge to speed up the `inb' and `outb'
X   functions. I.e., originally, the `outb' inline function had an
X   overhead of four data memory accesses for parameter passing. This
X   parameter passing actually consumed more clock cycles than the
X   assembler `outb' command itself. Although this solution can't
X   prevent unnessessary register moves it limits them at least to
X   register to register moves that are much faster. You need a
X   line like the following in the declaration part of every
X   function that uses `inb' or `outb' calls:
X
X	REGVAR;
X
X   This hack should work with every compiler that knows about the
X   UNIX V [34].X/386 standard compiler's inline assembler directives.
X*/
X
Xasm	void loadal (val)
X{
X%reg	val;
X	movl	val,%eax
X%mem	val;
X	movb	val,%al
X}
X
Xasm	void loaddx (val)
X{
X%reg	val;
X	movl	val,%edx
X%mem	val;
X	movw	val,%dx
X}
X
Xasm	int outbyte ()
X{
X	outb	(%dx)
X}
X
Xasm	int inbyte ()
X{
X	xorl	%eax,%eax
X	inb	(%dx)
X}
X
X/* The port parameter of the `outb' macro must be one of the predefined
X   port macros from `fas.h' or a simple uint variable (no indirection
X   is allowed). Additionally, `fip' must be a register variable in the
X   functions where `outb' is used. This prevents the destruction of the
X   `eax' CPU register while loading the `edx' register with the port
X   address. This is highly compiler implementation specific.
X*/
X#define outb(port,val) (regvar = (val), loadal (regvar), regvar = (port), loaddx (regvar), outbyte ())
X
X#define inb(port) (regvar = (port), loaddx (regvar), inbyte ())
X
X#define REGVAR register uint	regvar
X
X/* This function inserts the address optimization assembler pseudo-op
X   wherever called.
X*/
X
Xasm	void optim ()
X{
X	.optim
X}
X
X/* This dummy function has nothing to do but to call optim so that
X   the `.optim' assembler pseudo-op will be included in the assembler
X   file. This must be the first of all functions.
X*/
X
X#if defined (OPTIM)	/* Define for uPort, ISC doesn't know about */
Xstatic void		/* `.optim', but has turned on optimization by */
Xdummy ()		/* default, so we don't need it there anyway. */
X{
X	optim ();
X}
X#endif
X#endif	/* XENIX || NO_ASM */
X
X/* functions provided by this driver */
Xint		fasinit ();
Xint		fasopen ();
Xint		fasclose ();
Xint		fasread ();
Xint		faswrite ();
Xint		fasioctl ();
Xint		fasintr ();
X#if defined (NEED_PUT_GETCHAR)
Xint		asyputchar ();
Xint		asygetchar ();
X#endif
X#if defined (NEED_INIT8250)
Xint		init8250 ();
X#endif
Xstatic int	fas_proc ();
Xstatic void	fas_param ();
Xstatic void	fas_fproc ();
Xstatic void	fas_mproc ();
Xstatic uint	fas_rproc ();
Xstatic void	fas_xproc ();
Xstatic void	fas_event ();
X#if defined (HAVE_VPIX)
Xstatic int	fas_vpix_sr ();
X#endif
Xstatic void	fas_rxfer ();
Xstatic void	fas_xxfer ();
Xstatic void	fas_ihlw_check ();
Xstatic void	fas_hdx_check ();
Xstatic void	fas_hangup ();
Xstatic void	fas_timeout ();
Xstatic void	fas_cmd ();
Xstatic void	fas_open_device ();
Xstatic void	fas_close_device ();
Xstatic uint	fas_make_ctl_val ();
Xstatic int	fas_test_device ();
X
X/* external functions used by this driver */
Xextern int	ttinit ();
Xextern int	ttiocom ();
Xextern int	ttyflush ();
Xextern int	SPLINT ();
Xextern int	SPLWRK ();
Xextern int	splx ();
Xextern int	sleep ();
Xextern int	wakeup ();
Xextern void	longjmp ();
X#if !defined (SVR4)
Xextern int	signal ();
X#endif
Xextern int	timeout ();
Xextern int	untimeout ();
X#if defined (SCO) || defined (XENIX)
Xextern int	printcfg ();
X#else
Xextern int	printf ();
X#endif
X#if defined (HAVE_VPIX)
Xextern int	fubyte ();
Xextern int	subyte ();
Xextern int	v86setint ();
X#endif
X#if defined (XENIX)
Xextern int	inb ();
Xextern int	outb ();
X#endif
X
X/* external data objects used by this driver */
Xextern int	tthiwat [];
X
X/* the following stuff is defined in space.c */
Xextern uint	fas_physical_units;
Xextern ulong	fas_port [];
Xextern uint	fas_vec [];
Xextern uint	fas_init_seq [];
Xextern uint	fas_mcb [];
Xextern ulong	fas_modem [];
Xextern ulong	fas_flow [];
Xextern uint	fas_ctl_port [];
Xextern uint	fas_ctl_val [];
Xextern uint	fas_int_ack_port [];
Xextern uint	fas_int_ack [];
Xextern struct fas_info	fas_info [];
Xextern struct tty	fas_tty [];
Xextern struct fas_info	*fas_info_ptr [];
Xextern struct tty	*fas_tty_ptr [];
X/* end of space.c references */
X
X/* fas_is_initted
X   Flag to indicate that we have been thru init.
X   This is realy only necessary for systems that use asyputchar
X   and asygetchar but it doesn't hurt to have it anyway.
X*/
Xstatic int	fas_is_initted = FALSE;
X
X/* event_scheduled
X   Flag to indicate that the event handler has been scheduled
X   via the timeout() function.
X*/
Xstatic int	event_scheduled = FALSE;
X
X/* array of pointers to the first fas_info structure for each
X   interrupt vector
X*/
Xstatic struct fas_info	*fas_first_int_user [NUM_INT_VECTORS];
X
X/* counters for receiver overruns, each UART type has its own counter
X   in the following order: NS16450, i82510, NS16550A
X*/
Xuint	fas_overrun [3];
X
X/* the values for the various baud rates */
Xstatic uint	fas_speeds [CBAUD + 1] =
X{	1,			BAUD_BASE/50,
X	BAUD_BASE/75,		BAUD_BASE/110,
X	(2*BAUD_BASE+134)/269,	BAUD_BASE/150,
X	BAUD_BASE/200,		BAUD_BASE/300,
X	BAUD_BASE/600,		BAUD_BASE/1200,
X	BAUD_BASE/1800,		BAUD_BASE/2400,
X	BAUD_BASE/4800,		BAUD_BASE/9600,
X	BAUD_BASE/19200,	BAUD_BASE/38400
X};
X
X/* time for one character to completely leave the transmitter shift register */
Xstatic uint	fas_ctimes [CBAUD + 1] =
X{	1,		HZ*15/50+2,
X	HZ*15/75+2,	HZ*15/110+2,
X	HZ*30/269+2,	HZ*15/150+2,
X	HZ*15/200+2,	HZ*15/300+2,
X	HZ*15/600+2,	HZ*15/1200+2,
X	HZ*15/1800+2,	HZ*15/2400+2,
X	HZ*15/4800+2,	HZ*15/9600+2,
X	HZ*15/19200+2,	HZ*15/38400+2
X};
X
X/* dynamically adapt xmit buffer size to baud rate to prevent long buffer
X   drains at low speeds
X   These values are checked against boundaries and will be modified if
X   necessary before use. Checking is done in fas_param (). Drain time
X   is about 5 seconds with continuous character flow.
X*/
Xstatic uint	fas_xbuf_size [CBAUD + 1] =
X{	1,		50/2,
X	75/2,		110/2,
X	269/4,		150/2,
X	200/2,		300/2,
X	600/2,		1200/2,
X	1800/2,		2400/2,
X	4800/2,		9600/2,
X	19200/2,	38400/2
X};
X
X/* lookup table for minor device number -> open mode flags translation */
Xstatic uint	fas_open_modes [16] =
X{
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE
X							| OS_HWI_HANDSHAKE,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_CLOCAL | OS_HWO_HANDSHAKE
X							| OS_HDX_HANDSHAKE,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE
X						| OS_HWI_HANDSHAKE,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE,
X	OS_OPEN_FOR_DIALOUT | OS_FAKE_CARR_ON | OS_HWO_HANDSHAKE
X						| OS_HDX_HANDSHAKE,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE
X							| OS_HWI_HANDSHAKE,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_NO_DIALOUT | OS_HWO_HANDSHAKE
X							| OS_HDX_HANDSHAKE,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
X						| OS_HWI_HANDSHAKE,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE,
X	OS_OPEN_FOR_GETTY | OS_WAIT_OPEN | OS_HWO_HANDSHAKE
X						| OS_HDX_HANDSHAKE
X};
X
X/* The following defines are used to access multiplexed ports. */
X#define GET_PORT(port,num) \
X	((fip->device_flags.i & DF_CTL_EVERY)\
X			? (port)\
X			: (port) + (num))
X
X#define fas_first_ctl(fip,port) \
X	((void) (((fip)->device_flags.i & DF_CTL_FIRST)\
X			? outb (CTL_PORT, (port).p.ctl)\
X			: 0))
X
X#define fas_ctl(fip,port) \
X	((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
X			? outb (CTL_PORT, (port).p.ctl)\
X			: 0))
X
X#define fas_first_outb(fip,port,val) \
X	((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
X			? outb (CTL_PORT, (port).p.ctl)\
X			: 0),\
X		(void) outb ((port).addr, (val)))
X
X#define fas_outb(fip,port,val) \
X	((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
X			? outb (CTL_PORT, (port).p.ctl)\
X			: 0),\
X		(void) outb ((port).addr, (val)))
X
X#define fas_first_inb(fip,port) \
X	((void) (((fip)->device_flags.i & (DF_CTL_FIRST | DF_CTL_EVERY))\
X			? outb (CTL_PORT, (port).p.ctl)\
X			: 0),\
X		inb ((port).addr))
X
X#define fas_inb(fip,port) \
X	((void) (((fip)->device_flags.i & DF_CTL_EVERY)\
X			? outb (CTL_PORT, (port).p.ctl)\
X			: 0),\
X		inb ((port).addr))
X
X/* The following defines are used to take apart the minor device numbers. */
X#define GET_UNIT(dev)		((dev) & 0x0f)
X#define GET_OPEN_MODE(dev)	(fas_open_modes [((dev) >> 4) & 0x0f])
X
X/* lock device against concurrent use */
X#define get_device_lock(fip,prio) \
X{\
X	/* sleep while device is used by an other process */\
X	while ((fip)->device_flags.i & DF_DEVICE_LOCKED)\
X		(void) sleep ((caddr_t) &(fip)->device_flags.i, (prio));\
X	(fip)->device_flags.s |= DF_DEVICE_LOCKED;\
X}
X
X/* release device */
X#define release_device_lock(fip) \
X{\
X	(fip)->device_flags.s &= ~DF_DEVICE_LOCKED;\
X	/* wakeup the process that may wait for this device */\
X	(void) wakeup ((caddr_t) &(fip)->device_flags.i);\
X}
X
X/* schedule event */
X#define event_sched(fip,event) \
X{\
X	(fip)->event_flags.s |= (event);\
X	if (!event_scheduled)\
X	{\
X		event_scheduled = TRUE;\
X		(void) timeout (fas_event, (void *) NULL,\
X				(EVENT_TIME) * (HZ) / 1000);\
X	}\
X}
X
X/* fasinit
X   This routine checks for the presense of the devices in the fas_port
X   array and if the device is present tests and initializes it.
X   During the initialization if the device is determined to be an
X   NS16550A chip the DF_DEVICE_IS_NS16550A flag is set and the FIFOs will
X   be used. If the device is an i82510 chip the DF_DEVICE_IS_I82510 flag
X   is set and the device will be handled accordingly.
X*/
X
Xint
Xfasinit ()
X{
X	register struct fas_info	*fip;
X	register uint	unit;
X	uint	logical_units, port, *seq_ptr;
X	char	port_stat [MAX_UNITS + 1];
X	REGVAR;
X
X	if (fas_is_initted)
X		return (0);
X
X	fas_is_initted = TRUE;
X
X	/* execute the init sequence for the serial card */
X	for (seq_ptr = fas_init_seq; *seq_ptr; seq_ptr++)
X	{
X		port = *seq_ptr;
X		seq_ptr++;
X		if (*seq_ptr & READ_PORT)
X			(void) inb (port);
X		else
X			(void) outb (port, *seq_ptr);
X	}
X
X	/* setup the list of pointers to the tty structures */
X	for (unit = 0, logical_units = fas_physical_units * 2;
X		unit < logical_units; unit++)
X		fas_tty_ptr [unit] = &fas_tty [unit];
X
X	/* setup and initialize all serial ports */
X	for (unit = 0; unit < fas_physical_units; unit++)
X	{
X		fas_info_ptr [unit] = fip = &fas_info [unit];
X		port_stat [unit] = '-';
X		if (port = (uint) ((ushort) (fas_port [unit])))
X		{
X			/* check the int vector */
X			if (fas_vec [unit] >= NUM_INT_VECTORS)
X			{
X				port_stat [unit] = '>';
X				continue;
X			}
X
X			/* init all of its ports */
X			if (fas_ctl_port [unit])
X			{
X				fip->ctl_port = fas_ctl_port [unit];
X
X				if (fas_ctl_val [unit] & 0xff00)
X					fip->device_flags.s |= DF_CTL_EVERY;
X				else
X					fip->device_flags.s |= DF_CTL_FIRST;
X			}
X
X			fip->port_0.p.addr = GET_PORT (port, 0);
X			fip->port_1.p.addr = GET_PORT (port, 1);
X			fip->port_2.p.addr = GET_PORT (port, 2);
X			fip->port_3.p.addr = GET_PORT (port, 3);
X			fip->port_4.p.addr = GET_PORT (port, 4);
X			fip->port_5.p.addr = GET_PORT (port, 5);
X			fip->port_6.p.addr = GET_PORT (port, 6);
X			fip->port_0.p.ctl = fas_make_ctl_val (fip, unit, 0);
X			fip->port_1.p.ctl = fas_make_ctl_val (fip, unit, 1);
X			fip->port_2.p.ctl = fas_make_ctl_val (fip, unit, 2);
X			fip->port_3.p.ctl = fas_make_ctl_val (fip, unit, 3);
X			fip->port_4.p.ctl = fas_make_ctl_val (fip, unit, 4);
X			fip->port_5.p.ctl = fas_make_ctl_val (fip, unit, 5);
X			fip->port_6.p.ctl = fas_make_ctl_val (fip, unit, 6);
X			fip->vec = fas_vec [unit];
X			fip->modem.l = fas_modem [unit];
X			fip->flow.l = fas_flow [unit];
X
X			/* mask off invalid bits */
X			fip->modem.m.di &= MC_ANY_CONTROL;
X			fip->modem.m.eo &= MC_ANY_CONTROL;
X			fip->modem.m.ei &= MC_ANY_CONTROL;
X			fip->modem.m.ca &= MS_ANY_PRESENT;
X			fip->flow.m.ic &= MC_ANY_CONTROL;
X			fip->flow.m.oc &= MS_ANY_PRESENT;
X			fip->flow.m.oe &= MS_ANY_PRESENT;
X			fip->flow.m.hc &= MC_ANY_CONTROL;
X
X			fip->recv_ring_put_ptr = fip->recv_buffer;
X			fip->recv_ring_take_ptr = fip->recv_buffer;
X			fip->xmit_ring_put_ptr = fip->xmit_buffer;
X			fip->xmit_ring_take_ptr = fip->xmit_buffer;
X			fip->xmit_fifo_size = 1;
X
X			fip->ier = IE_NONE;	/* disable all ints */
X			fas_first_outb (fip, INT_ENABLE_PORT, fip->ier);
X
X			/* is there a serial chip ? */
X			if (fas_inb (fip, INT_ENABLE_PORT) != fip->ier)
X			{
X				port_stat [unit] = '?';
X				continue;	/* a hardware error */
X			}
X
X			/* test the chip thoroughly */
X			if ((port_stat [unit] = (fas_test_device (fip) + '0'))
X				!= '0')
X			{
X				continue;	/* a hardware error */
X			}
X
X			fip->lcr = 0;
X			fas_outb (fip, LINE_CTL_PORT, fip->lcr);
X			fip->mcr = fas_mcb [unit] | fip->modem.m.di;
X			fas_outb (fip, MDM_CTL_PORT, fip->mcr);
X
X			port_stat [unit] = '*';
X
X			/* let's see if it's an NS16550A */
X			fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_INIT_CMD);
X			if (!(~fas_inb (fip, INT_ID_PORT) & II_NS_FIFO_ENABLED))
X			{
X				fip->device_flags.s |= DF_DEVICE_IS_NS16550A;
X				fip->xmit_fifo_size = OUTPUT_NS_FIFO_SIZE;
X				port_stat [unit] = 'F';
X				fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
X			}
X			else
X			{
X				fas_outb (fip, NS_FIFO_CTL_PORT, NS_FIFO_CLEAR_CMD);
X				/* or is it an i82510 ? */
X				fas_outb (fip, I_BANK_PORT, I_BANK_2);
X				if (!(~fas_inb (fip, I_BANK_PORT) & I_BANK_2))
X				{
X					fip->device_flags.s |= DF_DEVICE_IS_I82510;
X					fip->xmit_fifo_size = OUTPUT_I_FIFO_SIZE;
X					port_stat [unit] = 'f';
X					fas_outb (fip, I_BANK_PORT, I_BANK_1);
X					fas_outb (fip, I_TCM_PORT, I_FIFO_CLR_XMIT);
X					fas_outb (fip, I_RCM_PORT, I_FIFO_CLR_RECV);
X				}
X				fas_outb (fip, I_BANK_PORT, I_BANK_0);
X			}
X
X			/* disable FIFOs if requested in space.c */
X			if ((fas_port [unit] & NO_FIFO) && (fip->device_flags.i
X						& (DF_DEVICE_IS_NS16550A
X							| DF_DEVICE_IS_I82510)))
X			{
X				fip->device_flags.s &= ~(DF_DEVICE_IS_NS16550A
X							| DF_DEVICE_IS_I82510);
X				fip->xmit_fifo_size = 1;
X				port_stat [unit] = '+';
X			}
X
X			/* clear potential interrupts */
X			(void) fas_inb (fip, MDM_STATUS_PORT);
X			(void) fas_inb (fip, RCV_DATA_PORT);
X			(void) fas_inb (fip, RCV_DATA_PORT);
X			(void) fas_inb (fip, LINE_STATUS_PORT);
X			(void) fas_inb (fip, INT_ID_PORT);
X			if (port = fas_int_ack_port [fip->vec])
X				(void) outb (port, fas_int_ack [fip->vec]);
X
X			/* show that it is present and configured */
X			fip->device_flags.s |= DF_DEVICE_CONFIGURED;
X		}
X	}
X
X#if defined (NEED_PUT_GETCHAR)
X	fip = &fas_info [0];
X	fip->mcr &= ~fip->modem.m.di;
X	fip->mcr |= INITIAL_MDM_CONTROL;
X	fas_first_outb (fip, MDM_CTL_PORT, fip->mcr);
X
X	fip->lcr = INITIAL_LINE_CONTROL;
X	fas_outb (fip, LINE_CTL_PORT, fip->lcr | LC_ENABLE_DIVISOR);
X	fas_outb (fip, DIVISOR_LSB_PORT, INITIAL_BAUD_RATE);
X	fas_outb (fip, DIVISOR_MSB_PORT, (INITIAL_BAUD_RATE) >> 8);
X	fas_outb (fip, LINE_CTL_PORT, fip->lcr);
X#endif
X
X#if defined (SCO) || defined (XENIX)
X	for (unit = 0; unit < fas_physical_units; unit++)
X		(void) printcfg ("fas", (uint) ((ushort) (fas_port [unit])), 7,
X					fas_vec [unit], -1,
X					"unit=%d type=%c release=2.09.0",
X					unit, port_stat [unit]);
X#else
X	port_stat [unit] = '\0';
X	(void) printf ("\nFAS 2.09.0 async driver: Unit 0-%d init state is [%s]\n\n",
X			unit - 1,
X			port_stat);
X#endif
X	return (0);
X}
X
X/* Open a tty line. This function is called for every open, as opposed
X   to the fasclose function which is called only with the last close.
X*/
Xint
Xfasopen (dev, flag)
Xint	dev;
Xint	flag;
X{
X	register struct fas_info	*fip;
X	register struct tty		*ttyp;
X	register uint	open_mode;
X	uint	physical_unit;
X	int	have_lock;
X	int	old_level;
X
X	physical_unit = GET_UNIT (dev);
X
X	/* check for valid port number */
X	if (physical_unit >= fas_physical_units)
X	{
X		u.u_error = ENXIO;
X		return (-1);
X	}
X
X	fip = fas_info_ptr [physical_unit];
X
X	/* was the port present at init time ? */
X	if (!(fip->device_flags.i & DF_DEVICE_CONFIGURED))
X	{
X		u.u_error = ENXIO;
X		return (-1);
X	}
X
X	open_mode = GET_OPEN_MODE (dev);
X	have_lock = FALSE;
X	old_level = SPLINT ();
X
X	/* loop until we've got the device lock and, owning the lock, we've
X	   checked whether the current open mode permits us to open the
X	   device
X	*/
X	for (;;)
X	{
X		/* If this is a getty open, the device is already open for
X		   dialout and the FNDELAY flag is not set, wait until device
X		   is closed.
X		*/
X		while ((open_mode & OS_OPEN_FOR_GETTY)
X					&& (fip->o_state & OS_OPEN_FOR_DIALOUT)
X					&& !(flag & FNDELAY))
X		{
X			if (have_lock)
X			{
X				release_device_lock (fip);
X				have_lock = FALSE;
X			}
X			(void) sleep ((caddr_t) &fip->o_state, TTIPRI);
X		}
X		
X		/* If the device is already open and another open uses a
X		   different open mode or if a getty open waits for carrier
X		   and doesn't allow parallel dialout opens, return with
X		   EBUSY error.
X		*/
X		if ((fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
X					? (OS_OPEN_STATES | OS_WAIT_OPEN)
X					: (OS_OPEN_STATES | OS_NO_DIALOUT)))
X			&& ((flag & FEXCL)
X				|| ((open_mode ^ fip->o_state) & (u.u_uid
X							? OS_TEST_MASK
X							: OS_SU_TEST_MASK))))
X		{
X			if (have_lock)
X				release_device_lock (fip);
X			(void) splx (old_level);
X			u.u_error = EBUSY;
X			return (-1);
X		}
X
X		/* If device is already open and the FTRUNC flag is set,
X		   flush input and output buffers. This may be used to
X		   release processes that got stuck in fasclose() during
X		   an exit() call.
X		*/
X		if ((fip->o_state & OS_OPEN_STATES) && (flag & FTRUNC))
X		{
X			flag &= ~FTRUNC;	/* flush only once */
X			(void) SPLWRK ();
X			(void) ttyflush (fip->tty, FREAD | FWRITE);
X			(void) SPLINT ();
X		}
X
X		/* if we don't have the device lock, yet, try to get it */
X		if (!have_lock)
X		{
X			if (fip->device_flags.i & DF_DEVICE_LOCKED)
X			{
X				get_device_lock (fip, TTIPRI);
X				have_lock = TRUE;
X				/* we had to sleep for some time to get the
X				   lock, therefore, re-check whether the
X				   current open mode still permits us to
X				   open the device
X				*/
X				continue;
X			}
X			else
X				get_device_lock (fip, TTIPRI);
X		}
X
X		break;
X	}
X
X	/* disable subsequent opens */
X	if (flag & FEXCL)
X		open_mode |= OS_EXCLUSIVE_OPEN_1;
X
X	/* set up pointer to tty structure */
X	ttyp = (open_mode & OS_OPEN_FOR_GETTY)
X		? fas_tty_ptr [physical_unit + fas_physical_units]
X		: fas_tty_ptr [physical_unit];
X
X	/* things to do on first open only */
X	if (!(fip->o_state & ((open_mode & OS_OPEN_FOR_GETTY)
X				? (OS_OPEN_STATES | OS_WAIT_OPEN)
X				: OS_OPEN_STATES)))
X	{
X		/* init data structures */
X		fip->tty = ttyp;
X		(void) ttinit (ttyp);
X		ttyp->t_proc = fas_proc;
X		fip->po_state = fip->o_state;
X		fip->o_state = open_mode & ~OS_OPEN_STATES;
X#if defined (HAVE_VPIX)
X		/* initialize VP/ix related variables */
X		fip->v86_proc = (v86_t *) NULL;
X		fip->v86_intmask = 0;
X		fip->v86_ss.ss_start = CSTART;
X		fip->v86_ss.ss_stop = CSTOP;
X#endif
X		fas_open_device (fip);		/* open physical device */
X		fas_param (fip, HARD_INIT);	/* set up port registers */
X
X		/* allow pending tty interrupts */
X		(void) SPLWRK ();
X		(void) SPLINT ();
X	}
X
X	/* If getty open and the FNDELAY flag is not set,
X	   block and wait for carrier if device not yet open.
X	*/
X	if ((open_mode & OS_OPEN_FOR_GETTY) && !(flag & FNDELAY))
X	{
X		/* sleep while open for dialout or no carrier */
X		while ((fip->o_state & OS_OPEN_FOR_DIALOUT)
X			|| !(ttyp->t_state & (ISOPEN | CARR_ON)))
X		{
X			ttyp->t_state |= WOPEN;
X			release_device_lock (fip);
X			(void) sleep ((caddr_t) &ttyp->t_canq, TTIPRI);
X			get_device_lock (fip, TTIPRI);
X		}
X		ttyp->t_state &= ~WOPEN;
X	}
X
X	/* wakeup processes that are still sleeping in getty open */
X	if (ttyp->t_state & WOPEN)
X		(void) wakeup ((caddr_t) &ttyp->t_canq);
X
X	/* we need to flush the receiver with the first open */
X	if (!(fip->o_state & OS_OPEN_STATES))
X		fas_cmd (fip, ttyp, T_RFLUSH);
X
X	(*linesw [ttyp->t_line].l_open) (ttyp);
X
X	/* set open type flags */
X	fip->o_state = open_mode;
X
X	release_device_lock (fip);
X	(void) splx (old_level);
X	return (0);
X}
X
X/* Close a tty line. This is only called if there is no other
X   concurrent open left. A blocked getty open is not counted as
X   a concurrent open because in this state it isn't really open.
X*/
Xint
Xfasclose (dev)
Xint	dev;
X{
X	register struct fas_info	*fip;
X	register struct tty		*ttyp;
X	uint	physical_unit;
X	uint	open_mode;
X	int	old_level;
X
X	physical_unit = GET_UNIT (dev);
X
X	fip = fas_info_ptr [physical_unit];
X
X	open_mode = GET_OPEN_MODE (dev);
X
X	/* set up pointer to tty structure */
X	ttyp = (open_mode & OS_OPEN_FOR_GETTY)
X		? fas_tty_ptr [physical_unit + fas_physical_units]
X		: fas_tty_ptr [physical_unit];
X	
X	old_level = SPLINT ();
X	get_device_lock (fip, TTIPRI);
X
X	/* wait for output buffer drain only if device was open */
X	if (ttyp->t_state & ISOPEN)
X	{
X		/* wait for buffer drain and catch interrupts */
X		while (ttyp->t_outq.c_cc || (ttyp->t_state & (BUSY | TIMEOUT)))
X		{
X			ttyp->t_state |= TTIOW;
X			if (sleep ((caddr_t) &ttyp->t_oflag, TTOPRI | PCATCH))
X			{
X				/* caught signal */
X				ttyp->t_state &= ~TTIOW;
X				release_device_lock (fip);
X				(void) splx (old_level);
X				longjmp (u.u_qsav);
X			}
X		}
X		/* block transmitter and wait until it is
X		   empty
X		*/
X		fip->device_flags.s |= DF_XMIT_LOCKED;
X		while (fip->device_flags.i & (DF_XMIT_BUSY
X					| DF_XMIT_BREAK
X					| DF_GUARD_TIMEOUT))
X			(void) sleep ((caddr_t) &fip->device_flags.i,
X							PZERO - 1);
X	}
X
X	(*linesw [ttyp->t_line].l_close) (ttyp);
X
X	/* allow pending tty interrupts */
X	(void) SPLWRK ();
X	(void) SPLINT ();
X
X	if (open_mode & OS_OPEN_FOR_GETTY)
X	{
X		/* not waiting any more */
X		ttyp->t_state &= ~WOPEN;
X		if (!(fip->o_state & OS_OPEN_FOR_DIALOUT))
X		{
X			fas_close_device (fip);
X			fip->o_state = OS_DEVICE_CLOSED;
X		}
X		else
X			fip->po_state = OS_DEVICE_CLOSED;
X	}
X	else
X	{
X		fas_close_device (fip);
X		fip->o_state = OS_DEVICE_CLOSED;
X		/* If there is a waiting getty open on
X		   this port, reopen the physical device.
X		*/
X		if (fip->po_state & OS_WAIT_OPEN)
X		{
X			/* get the getty version of the
X			   tty structure
X			*/
X			fip->tty = fas_tty_ptr [physical_unit
X					+ fas_physical_units];
X			fip->o_state = fip->po_state;
X			fip->po_state = OS_DEVICE_CLOSED;
X#if defined (HAVE_VPIX)
X			/* initialize VP/ix related variables */
X			fip->v86_proc = (v86_t *) NULL;
X			fip->v86_intmask = 0;
X			fip->v86_ss.ss_start = CSTART;
X			fip->v86_ss.ss_stop = CSTOP;
X#endif
X			if (!(fip->device_flags.i & DF_DO_HANGUP))
X			{
X				fas_open_device (fip);
X				/* set up port registers */
X				fas_param (fip, HARD_INIT);
X			}
X		}
X		(void) wakeup ((caddr_t) &fip->o_state);
X	}
X
X	if (!(fip->device_flags.i & DF_DO_HANGUP))
X		release_device_lock (fip);
X
X	(void) splx (old_level);
X	return (0);
X}
X
X/* read characters from the input buffer */
Xint
Xfasread (dev)
Xint	dev;
X{
X	register struct fas_info	*fip;
X	register struct tty	*ttyp;
X	int	old_level;
X
X	fip = fas_info_ptr [GET_UNIT (dev)];
X	ttyp = fip->tty;
X
X	(*linesw [ttyp->t_line].l_read) (ttyp);
X
X	old_level = SPLINT ();
X
X	/* schedule character transfer to UNIX buffer */
X	if (fip->recv_ring_cnt && (ttyp->t_line || (ttyp->t_lflag & ICANON)
X#if defined (HAVE_VPIX)
X		|| ((((fip->iflag & DOSMODE)
X			? MAX_VPIX_FILL - MIN_READ_CHUNK
X			: MAX_UNIX_FILL - MIN_READ_CHUNK)
X				>= ttyp->t_rawq.c_cc)
X#else
X		|| (((MAX_UNIX_FILL - MIN_READ_CHUNK) >= ttyp->t_rawq.c_cc)
X#endif
X		&& !(fip->flow_flags.i & FF_RXFER_STOPPED))))
X	{
X		event_sched (fip, EF_DO_RXFER);
X	}
X
X	(void) splx (old_level);
X	return (0);
SHAR_EOF
true || echo 'restore of fas.c failed'
fi
echo 'End of fas209 part 2'
echo 'File fas.c is continued in part 3'
echo 3 > _shar_seq_.tmp
exit 0
-- 
Uwe Doering  |  INET : gemini at geminix.in-berlin.de
Berlin       |----------------------------------------------------------------
Germany      |  UUCP : ...!unido!fub!geminix.in-berlin.de!gemini



More information about the Alt.sources mailing list