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 darber 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