English translation by Mick Lock verified by Peter West 1996,1997
-----------------------------------------------------------------


Definition Of A Software Interface, Providing A Fully Hardware
Independent Use For Serial Interfaces
==============================================================

Written by: Harun Scheutzow, Dresdener Straáe 83, D-10179 Berlin 
Internet-Email: Harun_Scheutzow@B.maus.de
Last amendment to the Definition: 12.Nov.1993
Last amendment to the Explanations: 24.Oct.1994

All functions, where possible, should be defined, be it a terminal 
program, a transfer protocol such as ZMODEM or even a fax program that 
you want or need. These functions need a hardware independent 
interface for all programs.

This proposal is known to Eric Smith. When he wrote to me last, he said:
"Note  that  I can't say that this will be an  'official'  Atari  standard
right  now;  we  haven't  had time to review it  completely  and  make  it
official. But it seems OK to me, and it seems better to have an unofficial
standard  than no standard at all,  I think." (The only feedback  concerns
callbacks that could affect memory protection).


MiNT,TOS or a loaded driver should support as far as possible, the 
functions described here, hardware permitting. But all software must 
consider that when a function doesn't exist, it should return the 
errorcode EINVFN (-32). If the absence of a function prevents the software 
from working properly, then the user must be informed about it.

This is an attempt to standardise the interface found by user 
programs. Nothing will be written here about the internal working of 
the driver implementation.
All functions and options should be implementable on a 68000 with 8MHZ 
and 38400Bd transfer rate by the MFP (68901, without hardware FIFO). 
The increased performance of CPUs doesn't present any argument because 
the required data transfer increases constantly too.

Fopen, Fread, Fwrite, Fclose are well known as normal 
GEMDOS-functions. Fcntl (available in MINT and HSMODEM) is the GEMDOS 
function $104, LONG Fcntl( WORD filehandle, void * special, WORD 
subfunction). Fcntl returns mostly a 0 as the OK message, or otherwise 
a error code.  "filehandle" is the GEMDOS Filehandle, also used by 
Fread and Fwrite. "subfunction" is a 16 Bit value,that the executing 
function gives. "special" is a pointer to a memory location, whose 
data type (WORD, LONG, some kind of structure) is stored in the 
individual sub functions. Fcntl also expects to find its input 
parameters at this memory location as well. Returned parameters could 
also be stored here too.

The reservation of an interface I would carry out using the open mode of 
Fopen.

Here is an attempt to document what MiNT should already be providing. 
However not all of the functions are present in MiNT or do not quite work 
in the way they should.

Several lines are C, many of them are commented. The function calls are 
really examples, not prototypes.


How many bytes may be transferred nonblocking?
----------------------------------------------

#define FIONREAD  (('F'<< 8) | 1)
#define FIONWRITE (('F'<< 8) | 2)
Fcntl( handle, &count, FIONREAD)
Fcntl( handle, &count, FIONWRITE)

count is a 32Bit-value in which the function returns the number of bytes, 
which can be at least read / written during the next Fread/Fwrite. Because 
more than one program could write to a interface, nobody should rely on 
this. Only Fread/Fwrite return how many bytes are really transferred.


Set and Reset Break
-------------------

#define TIOCCBRK (('T'<< 8) | 20)
#define TIOCSBRK (('T'<< 8) | 21)
Fcntl( handle, dummy, TIOCSBRK); /* activate Break */
Fcntl( handle, dummy, TIOCCBRK); /* clear Break */
Any desired pointer can be used for "dummy" as it is not evaluated.


Set/Inquire the input speed and DTR-line control
------------------------------------------------

#define TIOCIBAUD (('T'<< 8) | 18)
Fcntl( handle, &speed, TIOCIBAUD);

Set the input speed of the interface. speed is a 32Bit-value, which 
contains the requested speed uncoded in bits per second. speed = 19200 
would set the speed to 19200bps. The input speed before the TIOCIBAUD 
call is returned in speed. If the old speed is unknown, -1 is 
returned. If speed = -1 at the call of TIOCIBAUD, only the input speed 
is asked for. If speed = 0, the DTR-line will be inactivated (cleared, 
dropped), without influence on the real speed. Every TIOCIBAUD-call 
which sets the speed, activates automatically DTR. Returnvalue is 
ERANGE if the requested speed is not available. In this case (a 
exception) the next lowest legal speed is returned in speed. If a next 
lowest speed is unavailable too, the lowest legal speed is returned.

Set/Inquire the output speed and DTR-line control
-------------------------------------------------

#define TIOCOBAUD (('T'<< 8) | 19)
Fcntl( handle, &speed, TIOCOBAUD);

Set output speed of the interface. The function description is identical 
with TIOCIBAUD. If a device does not support different input and output 
speed, TIOCIBAUD and TIOCOBAUD affects both speeds.


Inquire transmission protocol settings
--------------------------------------

#define TIOCGFLAGS (('T'<< 8) | 22)
Fcntl( handle, &flags, TIOCGFLAGS);

Returns in flags a 16 bit value of the current terminal state, which 
have an OR-connection with the following values. All other bits are 
reserved. They should be ignored by TIOCGFLAGS.  A program should read 
the flags with TIOCGFLAGS, modify the known values, and set the new 
value with TIOCSFLAGS.

/* Number of stopbits */

#define TF_STOPBITS 0x0003

/* 0x0000  illegal

Extension proposal: This activates the synchronous mode. The remaining 
bits will have other meanings in synchronous mode, which must be defined 
in future. */

#define TF_1STOP   0x0001 /* 1 Stopbit */
#define TF_15STOP  0x0002 /* 1.5 Stopbit */
#define	TF_2STOP   0x0003 /* 2 Stopbit */

/* Bits per character */

#define TF_CHARBITS 0x000C
#define TF_8BIT	0x0 /* 8 Bit */
#define TF_7BIT	0x4
#define TF_6BIT	0x8
#define TF_5BIT	0xC /* 5 Bit */

/* Handshake and parity */

#define TF_FLAG  0xF000
#define T_TANDEM 0x1000 /* XON/XOFF (=^Q/^S) flow control active */
#define T_RTSCTS 0x2000 /* RTS/CTS flow control active */
#define T_EVENP  0x4000 /* even parity active */
#define T_ODDP   0x8000 /* odd parity active */

/* even and odd are mutually exclusive */


Set transmission protocol settings
----------------------------------

#define TIOCSFLAGS (('T'<< 8) | 23)
Fcntl( handle, &flags, TIOCSFLAGS);

Set the settings, description see TIOCGFLAGS. Returnvalue is ERANGE if a 
illegal or not support combination occurs in flags.


End of documentation of existing MiNT functions. New proposals follow:


Flush serial buffers
--------------------

#define TIOCFLUSH (('T'<< 8) | 8)
Fcntl( handle, special, TIOCFLUSH);

(in MiNT "/* BUG: this should flush the input/output buffers */") Selected 
by the special-parameter the buffers are flushed in different ways:

special  function

0        Send the transmit buffer. The function returns, if the transmit 
         buffer is empty (return E_OK, =0) or if a internal timeout occurs 
         (return EDRVNR, =-2). The system takes a reasonable timeout.

1        Clear the receive buffer.

2        Clear the transmit buffer.

3        Clear receive and transmit buffer.

-tout    A negative parameter works the same as 0, but tout (Note: 
         tout is positive) gives the timeout in 1/200 seconds.

At present there is an incompatibility here between MiNT and the 
HSMODA-drivers. In newer MiNT versions modes 0 to 3 are realised and 
special is a pointer to a WORD (16 bit) that contains the mode. With 
the HSMODA-drivers however special is not a pointer but the mode value 
itself!

Stop receive
------------

#define TIOCSTOP (('T'<< 8) | 9)

Is  only  available in the handshake modes and signals  the  communication
partner that the computer wants to receive nothing.  The function waits  a
reasonable time for collecting characters already in transmission. Then it
returns, assuming that the partner stopped transmission. (Example for use: an 
8MHz-ST is unable to do simultaneously DMA and 57600Bd-receive by MFP.)


Start receive
-------------
#define TIOCSTART (('T'<< 8) | 10)

Eliminates effects of TIOCSTOP.


Inquire/Set buffer settings
---------------------------

#define TIOCBUFFER (('T'<<8) | 128)

special points to a structure:
LONG   input buffer size in byte
LONG   low water mark in byte
LONG   high water mark in byte
LONG   output buffer size in byte

If a value is only to be established but not altered, use a -1 instead 
of the value. If -1 is returned instead of a value, this function is 
not supported. If values are set one should also examine the returned 
values, because with unsuitable entries the driver may set and use the 
nearest value that suits it. (Note: It is up to the driver to allocate 
and free the memory. That can also be implemented under plain TOS.)


Inquire I/O-lines and signalling capabilities
--------------------------------------------

#define TIOCCTLMAP (('T'<<8) | 129)

special is a pointer to a structure of 6 LONGs which is filled out by 
the driver. In every LONG the corresponding bit is set to 1 for a 
existing control line or capability.

1.LONG: line inquire/setable with TIOCCTL(GET/SET)
2.LONG: action (routine call) possible at start of condition
3.LONG: action (routine call) possible at end of condition
4.LONG: reserved for future extension, till then 0
5.LONG: reserved for future extension, till then 0
6.LONG: reserved for future extension, till then 0

corresponding bits and "lines":

#define TIOCM_LE   0x0001    /* line enable output, output */
#define TIOCM_DTR  0x0002    /* data terminal ready, output */
#define TIOCM_RTS  0x0004    /* ready to send, has another meaning, output */
#define TIOCM_CTS  0x0008    /* clear to send, has another meaning, input */
#define TIOCM_CAR  0x0010    /* data carrier detect, input */
#define TIOCM_CD   TIOCM_CAR /* alternative name */
#define TIOCM_RNG  0x0020    /* ring indicator, input */
#define TIOCM_RI   TIOCM_RNG /* alternative name */
#define TIOCM_DSR  0x0040    /* data set ready, input */
#define TIOCM_LEI  0x0080    /* line enable input, input */
#define TIOCM_TXD  0x0100    /* transmit data line, output */
#define TIOCM_RXD  0x0200    /* receive data line, input */
#define TIOCM_BRK  0x0400    /* Break detected, pseudo-input */
#define TIOCM_TER  0x0800    /* transmit error, pseudo-input */
#define TIOCM_RER  0x1000    /* receive error, pseudo-input */
#define TIOCM_TBE  0x2000    /* hardware-transmitter buffer empty, 
                                pseudo-input */

#define TIOCM_RBF  0x4000 /* hardware-receiver buffer full, pseudo-input */

Undefined bits should be ignored.

The absence of a line in TIOCCTLMAP means only, that this line is not 
accessible by TIOCCTLxxx. It does not mean, that this line does not exist 
in the hardware. It is possible, that a line can only be by monitored by 
callbacks, but not by TIOCCTLGET.

Some TIOCM_* have special features, described here:

TIOCM_TER, TIOCM_RER
The routine gets in D0.b a byte, describing the error in detail:

Byte Error
0    no more information available about this error
1    hardware-receiver buffer overflow
2    software-receiver buffer overflow
3    parity error
4    framing error

Requesting TIOCM_BRK, TIOCM_RER or TIOCM_TER via TIOCCTLGET: If the 
condition occurs, the corresponding status bit is set. A common (-1) or 
dedicated (BRK, RER or TER) request returns the state of the corresponding 
bit and resets it.

TIOCM_TBE
The routine is passed -1 in D0.w if the software-transmit buffer is empty.
Otherwise a byte is read out from the software-transmit buffer and  passed
in D0.b,  in which case D0.bit15 is =0.  The routine returns -1 in D0.w if
nothing is to be sent. If a Byte is to be sent, it returns D0.bit15 =0 and
the Byte that is to be sent in D0.b.  The routine is called also if a  new
byte is written into the software-transmit buffer and the buffer was empty
before for some time. If the routine returns a self generated -1 and there
are bytes available in the software-transmit buffer, the routine is called
again after one second at most.

TIOCM_RBF
The routine is passed the received byte in D0.b. The routine returns -1 in
D0.w  if  nothing  is  to be written  into  the  software-receive  buffer.
Otherwise  it  returns  D0.bit15 =0 and in D0.b the Byte  that  is  to  be
written into the software-receive buffer.


Inquire I/O-lines and signals
-----------------------------

#define TIOCCTLGET (('T'<<8) | 130)

returns  a LONG in the memory cell special points to,  which contains  the
current conditions of the CTLlines,  coded as in TIOCCTLMAP.  A  parameter
is also passed to special:  If it is -1 then all CTLlines are inquired, if 
it is <> -1  then only one bit may be set  and only this CTLline is inquired. 
The driver may provide  the values of  the  other  lines nevertheless, for 
reasons of speed. Meaninglessly set bits are ignored.

Set I/O-lines and signals
-------------------------

#define TIOCCTLSET (('T'<<8) | 131)

special pointers to a structure:

LONG ctlmaske
LONG ctlvalues
The bits which are set in ctlmaske (coding see TIOCCTLMAP), are set to the 
values in ctlvalues. A software should only set bit(s) in ctlmaske, if it 
knows its functions. Input lines are unchangeable, such bits are ignored 
as senseless bits.


Concept of callback-functions
-----------------------------

A  program can install functions which are called almost immediately if  a
condition  occurs.  A function becomes installed by giving its address  in
procadr.  During  this installation Bit0 is always 0.  A function  becomes
uninstalled by the same call,  but with set bit0 (=1) in procadr,  with  a
odd  address!  Bit31-1  and  ctlline must have the same  value  as  during
installation.  If there are no special remarks for outstanding  functions,
the following basic rules apply:
        - Only register D0 and A0 may be changed.
        - It  must  be extremely short,  more than 20  "normal"  assembler
          instructions are not allowed (a MOVEM.L D1-D7/A1-A6,...  or  DIV
          is not "normal").  The run time of the routine should not exceed
          200 clocks on a CPU MC68000.
        - Call is made in supervisor mode.
        - The current InterruptPriorityLevel is unknown.
        - End with RTS.
It  is possible that several programs watch one line  simultaneously.  The
routine must be deinstalled before it is removed from memory due to a non-
resident program termination.  It is unimportant which file handle is used
for  (de-/)registration,  as long as it matches the  corresponding  device
(e.g. Fopen, Fcntl(...,TIOCCTLSFAST) /* installation */, Fclose,
...Fopen, Fcntl(...,TIOCCTLSFAST) /* deinstallation */, Fclose).

Some  functions  exist  only under special handshake modes  and  can  only
installed if this mode is active,  but deinstalled under every mode.  Such
functions are automatically activated and deactivated, as long as they are
installed.


Install/Deinstall fast callback-functions
-----------------------------------------

#define TIOCCTLSFAST (('T'<<8) | 132)

Installation and uninstallation of routines, which are called if changes 
on the CTLlines occur. special is a pointer to a structure:

LONG ctlline
LONG procadr
The routine is called on every transition (if possible, see TIOCCTLMAP) on 
the line marked in ctlline (only one bit should be set, see TIOCCTLMAP). 
The new level of the line is given in D0.b: 0 inactive (on the DSR line 
inactive means TTL-high-level, for example) and $FF active. Returnvalues 
of TIOCCTLSFAST:

E_OK    everything OK
1       routine  installed,  but it is not the  only  one.  Slowly 
        things  become time-critical,  so if possible the  program 
        should   deinstall   the  routine.   (This   is   only   a 
        recommendation).
EINVFN  this watch capability does not exist
EACCDN  routine can not be installed.


Install/Deinstall slow callback functions
-----------------------------------------

#define TIOCCTLSSLOW (('T'<<8) | 133)

nearly identical to TIOCCTLSFAST, with one difference: The routine may be 
(nearly) as long as it likes to be.


Inquire number of unsent bytes
------------------------------

#define TIONOTSEND (('T'<<8) | 134)
Fcntl( handle, &count, TIONOTSEND)

The function returns in count the number of bytes which have not yet  been
sent  as  a 32bit-value.  The function tries to ascertain  as  exactly  as
it  can,  limited  by  the  hardware  (hardware-FIFOs),  how  many  unsent
characters remain in the computer.


Set error behaviour
------------------

#define TIOCERROR (('T'<<8) | 135)
Fcntl( handle, &errmode, TIOCERROR);

Errmode  is  a  32bit value LONG.  If errmode is  -1,  then  errmode  only
returns  the current setting.  If errmode >=0,  then the settings will  be
made and the old values returned in errmode.  Bit7..0 of errmode will pass
a character.  Bit8 =1 switches on the insertion of this character into the
receive  buffer  if  a receive error occurs.  Normally  Bit8  =0,  and  no
character is inserted in the buffer.  Bit9 =1 switches on the clearance of
receive  buffer if Break is received,  normally Bit9 =0 and the buffer  is
not cleared by Break.  Return value is E_OK,  or ERANGE for not  supported
settings.
