Programmers Manual for SERSOFST.TXT-compatible drivers
======================================================

Dies ist in Englisch geschrieben, weil anscheinend besonders die nicht 
deutsch sprechenden Programmierer besondere Schwierigkeiten haben. Man mag 
darber denken, wie man will.

Because the non-German developers seems to have more difficulties than the 
Germans, this text is in English language.

It is a _quick_ collection of some hints. I repeat me: I'm not payed for 
doing this and it would be very nice, if I would get some sample code or 
so from other people.


Literature
----------
A real programmer should read the SERSOFST.TXT, the RSVF_COO.TXT and the 
text files of drivers and DRVIN. The MiNT documentation is also a source.


BIOS/XBIOS versus GEMDOS
------------------------
At the moment you may mix GEMDOS-calls and BIOS/XBIOS-calls for one 
port. But I recommend only to use the GEMDOS-calls, if you like to write a 
"nice" program. I you maintain an old program (which uses only (X)BIOS 
and direct hardware accesses), and you like to make it 
"clean", then it should have a user-selectable possibility only to use 
(X)BIOS and _not_ to access the hardware directly.


GEMDOS and the AUX
------------------
Atari recommends not to use the GEMDOS-AUX, especially the GEMDOS-calls 
number 3, 4, 18, 19. I recommend too not to use this calls and even not to 
use the "AUX:" or "U:\DEV\AUX", because this dirty things aren't 
supported, that means, they remain very slow under TOS. GEMDOS number 3, 
4, 18, 19 is the slowest way, because your program does an trap#1 to the 
gemdos and the gemdos does a trap#13 to the bios (for bios device number 
1). Additionally, that means that the GEMDOS could redirect this calls to 
another thing and the BIOS could do it again. If you use these 
gemdos-calls despite all warnings, you have to set the correct interface 
configuration via XBIOS Rsconf, and the correct BIOS device via Bconmap 
(if available).


Opening a port
--------------
If there is a RSVF-cookie (see RSVF_COO.TXT) then you can find out which 
ports are availabe and which GEMDOS-names and BIOS-numbers they have. 
Mostly there will be a MODEM1.

You get a handle for this by using the GEMDOS-Fopen-function called with 
the name "U:\DEV\MODEM1". (C-Programmers: double the backslashs). This 
will work if DRVIN (and the driver) is installed, under MiNT, unter MagiC.

Handling the I/O-ports like files is the normal way under many modern 
operating systems. And it is a fast way, because you can transfer many 
characters at on call.


Using the handle
----------------
Please read the SERSOFST.TXT. It explains nearly everything.

Some remarks: Fread and Fwrite work normally in a non-blocking mode, that 
means if you pass more bytes to Fwrite than actually can be transfered 
into the transmitter buffer (from the buffer they are transmitted by an 
interrupt routine or any other way not interesting for the application 
programmer), then the first n bytes will be transfered (n = as much as fit 
into the buffer) and Fwrite returns this n. This is the same behavior 
which shows Fwrite if you try to write to a disk which becomes full. And 
in a multitask system an other task could delete a file on the disk and a 
subsequent Fwrite will write again some bytes, the same way it works on 
this I/O-ports.

If you request more bytes than actually available via Fread, then Fread 
will return as much bytes as available and the number of bytes. The same 
way as trying to read more bytes from a file on disk then being in this 
file.


Why this SERSOFST.TXT-standard?
-------------------------------
I think it's explained in the SERSOFST.TXT. Again: It makes programs fast 
(faster than using only BIOS at the clean way) and independend form the 
underlaying hardware. All good Atari-emulators provide a 
SERSOFST-compatible interface for the serial ports, that is my personal 
opinion (yes, there are even bad emulators. That is my personal opinion. 
Harun Scheutzow. Ask for SERSOFST.TXT/HSMODA-support :-) ). And if your 
program is clean, using the SERSOFST-stuff, it will run on every port, no 
matter whether this port is a MFP, a SCC, a 82550-FIFO-UART, an ACIA, some 
mystic hardware of an Atari-emulator, or even an emulated modem via a 
large network.

Using clean programs (as Connect, GSZRZ, a self written Midicom-driver and 
so on) I had some successes even on unusual hardware: the programs runned 
correctly without any change on the Macintosh with the MagiCMac. The only 
precondition was the SERSOFST-conform driver for that hardware.


Speed
-----
Some people believe that serial communications have to be slow all the 
time. But even an old 8MHz-ST can transmit more than 15000cps 
(15KByte/second) via a SERSOFST-compatible driver using a well implemented 
Zmodem. This speeds become interesting for ISDN (or servicing more than 
one modem per computer).


Buffer sizes and XBIOS Iorec
----------------------------
As long as (or if) the Fcntl TIOCBUFFER isn't implemented (that means it 
returns an error if requesting the actual buffer sizes), it is legal to 
change the size and address and water marks of buffers directly in the 
IOREC. The clean way for this direct access: Switch to "no handshake", 
disable the interrupts, change the buffers, re-enable the interrupts, 
switch to the old handshake mode.


DTR on MODEM2/SERIAL2 via direct access, The SCC
------------------------------------------------
(ugly things not directly associated with SERSOFST)
The Atari developer documentation is _very_ _wrong_. If you use the 
drivers you aren't in need of accessing DTR directly in the hardware. But 
if you do it, do it in the _only_ _one_ correct way:

disable interrupts
get the WR5-shadow-register from IOREC(of this port)+$1D (it is a byte)
modify this shadow and write it back into the IOREC
select WR5 in the SCC
write the shadow into the SCC (WR5)
re-enable interrupts (restore old state)

This shadow exists because it's impossible on normal SCCs to read WR5 (and 
even on enhanced SCCs it is difficult and slow). This shadow exist for 
MODEM2 and SERIAL2 (the SCC ports) in all TOS-versions and MagiC and even 
the SERSOFST-drivers (for compatibility).

HINT! Disable the interrupts every time you like to access a SCC-register 
other than RR0, WR0 and the data-register (directly, not via WR8/RR8). If 
you forget it, and your program wrote the register number into WR0, there 
may come an interrupt and access the SCC too, producing trouble, because 
the SCC thinks the value the interrupt routine writes to WR0 is some data 
and not a new register number, returning to your program the trouble 
continues. (The only way to end it: read from RR0, and forgetting the read 
data. You can read/write from/to RR0/WR0 without first writing a 0 to WR0, 
if you look into the TOS, you see that it writes 0es, this is nonsens, 
forget this senceless behavior!)


The Function Fcntl
------------------
In a C-language environment this function ist normally declared in a 
header file either
LONG Fcntl(WORD handle, LONG special, WORD command);
or
LONG Fcntl(WORD handle, void * special, WORD command);

Sometimes LONG is replaced by long and WORD by int.

The function itself is defined (implemented) either in an other header 
file by using more or less compiler dependent methods (inline or a 
gemdos()-function) or in a library. As long as your compiler passes the 
parameters on the stack, the both declarations are identical on Ataris, 
because LONG and void * use the same amount of storage (4 bytes) on the 
stack.

But if your compiler passes the parameters in registers to a library 
function and it distinguishes between "normal data" and pointers, like the 
PureC, you must use the correct declaration as supplied with your 
compiler package.

Like nearly all GEMDOS functions, Fcntl returns 32 Bit, a LONG, as the 
function result. You should correct it in the headers of of your compiler, 
if it is wrong there.

In most cases "special" is the placeholder for a pointer to something. I 
will give an example of use for both declaration variants. I like to call 
the Fcntl TIOCIBAUD to set the input baud rate.

LONG my_err;
LONG baudrate;
WORD my_handle;

/* Open a device and assign a useable value to "my_handle" */

baudrate = 9600L;

/* if declared "LONG special" then use */
my_err = Fcntl(my_handle, (LONG)(&baudrate), TIOCIBAUD);

/* if declared "void * special" then use */
my_err = Fcntl(my_handle, &baudrate, TIOCIBAUD);


The Subfunction Fcntl TIOCFLUSH
-------------------------------
There is an _incompatibility_ between all drivers from HSMODA* and MACM1* 
packages and MiNT. MiNT assumes that the "special" parameter of this 
TIOCFLUSH Fcntl is a pointer to a long which contains the information 
about the desired flush, but the HSMODA* and MACM1* assume "special" 
itself contains this information, that means it is not a pointer.

I try to fix this in a compatible way in the next HSMODA-package, 
HSMODA08. The compatible fix-way I will use if I do it: If special is 0, 
1, 2 or 3, then it is the desired flush itself. If special is larger, and 
any valid pointer is larger with nearly 100% probability, then it is a 
pointer to the desired flush type. But at the moment I'm not shure how to 
handle negative special values. So my question: Does anybody use negative 
special values? (I could assume that any valid pointer is signed-positive, 
or that signed-negative values are only near by 0 are invalid pointers 
...)

Dear Developer, if you currently use TIOCFLUSH, please give a short 
response via email to Harun_Scheutzow@h.maus.de or 
harun@village.village.de.



Harun Scheutzow, 1994-11-25 and later
