        DONGLE USER NOTES

 The dongle attaches to a standard PC-type parallel port, and provides 512
bytes of non-volatile memory. All the normal printer lines are passed
straight through, so the dongle may be used with bidirectional ports.
(Under Windows-95, a new printer - HP Laserjet 4L - was successfully
identified and configured with the dongle in place.)
 The only printer line intercepted is PE (paper end). With the dongle
inactive, this line is simply buffered and passed through.

 It is not intended that more than one dongle of this type be connected
simultaneously to a given parallel port.

 Users should be aware that the PC parallel interface is specified for TTL
voltage levels. Strictly, a parallel port generating a logic High of 2.4V
would comply with the specification, however this is quite insufficient to
write to the FRAM device in the dongle (it would probably read correctly).
Most newer computers use a CMOS port driver, which delivers almost 5V as
logic High. The dongle works correctly with this type of machine.

 The software supplied implements the lowest level of a dongle security
function. Four functions are provided: OPEN, CLOSE, READ and WRITE. All
arguments are passed in registers. By convention, all functions return
CY=0 and AX=0 if successful, and CY=1 and AX!=0 if an error occurred.
Error status is returned in AX.

DONGLE_OPEN
 Entry:         AL = parallel port number (1..4)
 Exit:          AX = status:
                suxes   equ     0       ;Good
                badarg  equ     1       ;Invalid arguments passed
                nodong  equ     4       ;No dongle present
                opnerr  equ     5       ;Dongle open already

                CY = error flag

 This must be called before any other operations. An attempt will be made
to initialise a dongle on the named port. If the given port is invalid, the
code "badarg" is returned. After initialisation, the PE line should be high
(the idle state for an I2C data line). If low, the code "nodong" is
returned, else "suxes". Note that "suxes" is not conclusive proof that a
dongle is present, as a floating PE line can appear high (or a paperless
printer).

DONGLE_CLOSE
 Entry:         None
 Exit:          AX = status:
                suxes   equ     0       ;Closed successfully
                opnerr  equ     5       ;Closed already

                CY = error flag

 This should be called after all dongle transactions are complete
(including after an unsuccessful OPEN call, when the return "opnerr" may be
ignored). It will reset any dongle present, so enabling normal printing
operations to resume.

DONGLE_READ
 Entry:
                AL    = slave no.  (0..3)
                BX    = FRAM addr. (0..1FF)
                CX    = length     (1..1FF)
                ES:DI = buffer address

 Exit:          AX = status:
                suxes   equ     0       ;Good
                badarg  equ     1       ;Invalid FRAM address/length
                nochip  equ     2       ;No from FRAM command
                opnerr  equ     5       ;Dongle not opened

                CY = error flag

 This routine reads a block of data from the FRAM chip in the dongle. The
"slave no." is currently fixed at 0: future revisions may provide for up to
4 "families" of dongles, using different slave addresses.
 The top FRAM address (BX+CX) must not exceed 0x200: overflow is checked,
and will return "badarg" status.
 This function, called with no dongle present, will return "nochip".

DONGLE_WRITE
 Entry:
                AL    = slave no.  (0..3)
                BX    = FRAM addr. (0..1FF)
                CX    = length     (1..1FF)
                DS:SI = buffer address

 Exit:          AX = status:
                suxes   equ     0       ;Good
                badarg  equ     1       ;Invalid FRAM address/length
                nochip  equ     2       ;No ACK frm FRAM command
                wrterr  equ     3       ;No ACK from write data
                opnerr  equ     5       ;Dongle not opened

                CY = error flag

 This routine writes a block of data to the FRAM. The arguments operate
similarly to the READ function. Note that this function does not perform a
read-after-write check on the data: this task is left to a higher software
level.
