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 Strae 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 an 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 
(eg. Fopen, Fcntl(...,TIOCCTLSFAST) /* installation */, Fclose,
...Fopen, Fcntl(...,TIOCCTLSFAST) /* deinstallation */, Fclose).

Some functions exist only under special handshake modes and can only be 
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.

Return values 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.
