KFOSSIL 1.0 - a FOSSIL driver for DOS
=====================================

KFOSSIL gives DOS programs the FOSSIL interface (revision 5) on INT 14h:
the standard way BBS software and door games talk to a serial port without
knowing anything about the hardware. Load it once, before the BBS:

    KFOSSIL                     COM1 at 3F8, IRQ 4
    KFOSSIL 1 2                 COM1 and COM2
    KFOSSIL 1:3F8,4,38400       COM1, port rate locked at 38400 (8N1)
    KFOSSIL /C 1                COM1, carrier detect always on
    KFOSSIL /U                  take it out of memory again
    KFOSSIL /?                  help

It needs any PC from an 8088 up, and DOS 2 or later.


What it does
------------

  - Up to four ports, COM1 to COM4 (FOSSIL ports 0 to 3), at any I/O
    address and IRQ 2 to 15. Ports can share an IRQ (COM1 and COM3 on 4).
  - Interrupt driven: each port has a 2K receive buffer and a 1K send
    buffer, so nothing is lost while a program is busy.
  - 8250, 16450 and 16550A UARTs. On a 16550A the FIFOs are used (receive
    trigger at 8 bytes, up to 16 bytes sent at a time).
  - Flow control (function 0Fh): RTS/CTS, and XON/XOFF either way. With
    RTS/CTS on, KFOSSIL drops RTS when the receive buffer is 3/4 full and
    raises it again when it is down to 1/4; it stops sending while CTS is
    low.
  - Carrier detect in the status (function 03h), the watchdog (14h: reboot
    when carrier is lost), break (1Ah), ^C/^K checking (10h), the timer
    tick chain (16h), block reads and writes (18h, 19h) and the driver
    information (1Bh).
  - A locked port rate: give the rate after the IRQ and programs can't
    change it with function 00h (the usual set-up for a modem or a fast
    null-modem link, where the BBS and its doors should all use one rate).
  - /C makes the carrier detect line read as always on, for null-modem
    cables without DCD and emulators that have no DCD (DOSBox's nullmodem).
    The watchdog is ignored then.
  - KFOSSIL /U removes it, if no program has taken over its interrupts
    since: the ports' interrupts are switched off (DTR and RTS are left as
    they are), the vectors and PIC masks are put back and the memory is
    freed.

Memory: about 2.3K, plus 3K of buffers for each port (5.3K for one port,
14.5K for four). KFOSSIL gives back its environment block.

Calls for ports it isn't handling go on to whatever had INT 14h before
(normally the BIOS). Port number 00FFh works for functions 04h and 05h, as
the specification says.


The port specification
----------------------

    port[:base[,irq[,rate]]]

    port   1 to 4
    base   the I/O address in hex           (defaults 3F8, 2F8, 3E8, 2E8)
    irq    2 to 15                          (defaults 4, 3, 4, 3)
    rate   lock the port at this rate, 8N1: one that 115200 divides,
           e.g. 2400, 9600, 19200, 38400, 57600, 115200

With no ports given, KFOSSIL uses COM1. It checks each port for a UART
before loading, and tells you what it found:

    COM1 at 03F8, IRQ 4, 16550A FIFOs, locked at 38400


The functions
-------------

    00h  set the port rate and line (ignored when the rate is locked)
    01h  send a byte, waiting for room          02h  receive, waiting
    03h  status                                 04h  initialise
    05h  de-initialise (DTR stays as it is)     06h  DTR up or down
    07h  timer tick information                 08h  wait until all sent
    09h  throw away unsent output               0Ah  throw away input
    0Bh  send a byte if there's room            0Ch  look at the next byte
    0Dh  keyboard: look at the next key         0Eh  keyboard: wait for one
    0Fh  flow control                           10h  ^C/^K checking
    11h  set the cursor                         12h  get the cursor
    13h  write a character through ANSI         14h  watchdog
    15h  write a character through the BIOS     16h  timer tick chain
    17h  reboot                                 18h  read a block
    19h  write a block                          1Ah  break
    1Bh  driver information

Function 04h returns AX = 1954h, BL = 1Bh (the highest function) and
BH = 5 (the FOSSIL revision). Function 05h leaves the port receiving into
its buffer, so typed-ahead keys aren't lost between the BBS and a door.


Testing
-------

The test/ folder has the programs and scripts used to test KFOSSIL in
DOSBox, whose COM1 can be an emulated 16550A connected to a TCP socket:

    FTEST.COM       echoes everything it receives (block read and write)
    BLAST.COM       sends 20000 bytes of a known pattern with function 01h
    WAITCALL.COM    waits for the caller's first byte, like a BBS answering
    echo_test.py    20000 random bytes through FTEST, then /U
    flow_test.py    RTS/CTS both ways (DOSBox's nullmodem with modem lines)
    blast_test.py   checks BLAST's bytes
    door_test.py    a real door, Ember Reach's REACH.EXE, played through
                    KFOSSIL: found a house, look at the map, quit
    run_tests.sh    all of them

Results for 1.0 (DOSBox 0.74-3): the echo test is clean; the flow test
shows nothing sent while CTS is low, RTS dropping after the buffers fill
(2574 bytes) and rising again, and all 30000 bytes back in order; BLAST is
clean; the door plays through. It has not yet been tried on a real PC
with a real modem.


Building
--------

    nasm -f bin -o KFOSSIL.COM kfossil.asm        (or: make)

The source is plain 8086 code for NASM. It is laid out as the resident part
(the INT 14h, IRQ and timer handlers and their data), then the buffers,
which are placed over the installer once it has finished; the installer is
last and isn't kept.


Licence
-------

KFOSSIL is Copyright (C) 2026 Michael Slater.

It is free software: you may copy, change and share it under the terms of
the GNU General Public License, version 2 or (at your option) any later
version (the file COPYING). It comes with NO WARRANTY. If you share the
program, the source must be available too.

The FOSSIL interface is the one in the FidoNet FOSSIL specification
(FSC-0015, revision 5).
