         page  SDNET Interface definitions
*     SDNET10DEFS.ASM -- definitions file for SDNET version 1.0
*     Contains equates and definitions required to implement SDNET system
*     modules (SDNETDEVICE.ASM, SDNETSKTMGR.ASM, SDNETSERVER.ASM)
*     and hardware-specific SDNET link driver modules (including ASLD.ASM).
;
*********************************************************************
* What follows is unfinished business. Stuff listed here probably doesn't
* belong here; it is here now until the issues are resolved and the
* results can be placed someplace appropriate.
? ; Network server: channel capability should include pointer to table entry
; ?? in remote machine containing channel capability to save time
? ; should have call to ask system what LogicalUserNumber is?
;
! ; the following belong in the SDOS definitions file
cnfg:mtprims       equ     $28         ; pointer to /MT primitives table
timeout:parameter  equ     timeout:dcb parameter value to pass to timeout routine
;
;        SDOS/RT entry point offset definitions
         org    0
RT:ITMO  rmb    3                      ; Initialize Timeout block
RT:RTMO  rmb    3                      ; Remove Timeout block from active state
RT:UTMO  rmb    3                      ; Update Timeout block with new value
RT:STMO  equ    RT:UTMO                ; Set Timeout block active
;
;        SDOS/RT Timout Block definitions (Note: Not same as TIMEOUT:xxx!)
;
         org    0
TOB:FLINK rmb   2                      ; Forward link: points to next TOB
TOB:BLINK rmb   2                      ; Backward link: points to previous TOB
TOB:DELAYDELTA rmb  2                  ; Holds Millisecond Delta for timeout expiration
TOB:ROUTINE rmb 2                      ; Points to timeout interrupt routine
TOB:PARAMETER rmb 2                    ; Value to pass to timeout interrupt routine
TOB:SIZE rmb    0                      ; Size of timeout block

;        Interrupt Poll Block (IPB:) definitions
        org     0
IPB:PRIORITY rmb 1                     ; Priority byte: 0 is low
                                       ; >$80 --> no stack switch
IPB:JMPNEXTIPB rmb 3                   ; contains JMP >xxxx
IPB:POLLCODE rmb 0                     ; contains code to test for device int
;     <test for device interrupt>
;     Bxx  IPB:JMPNEXTIPB     b/ device does not want interrupt
;
*********************************************************************

*
* Abbreviations used:
*   ASLD:xxx    Asynchronous Serial Link Driver.  Link driver for Asynch devices
*   LD:xxx      Link Driver.  Implements management of physical link device.
*   SM:xxx      Socket Manager. Implements inter-task pipes using LD:
*   NET:xxx     Net Device.  Implements remote file I/O via SM:xxx
*
                   page
                   ifund m6800
; Must be ASMV1.3 or earlier.  Default machine type to 6800.
m6800              equ   1
m6801              equ   0
m6811              equ   0
m6809              equ   0
                   fin

                   ifund m6811        ; Need this for current assemblers
; Must be ASMV1.4 or earlier --> machine type cannot be 6811.
m6811              equ   0
                   fin

minstacksize equ contextblock:size*3 room for context, IRQ + NMI
                   page
*                  User program interface definitions
*
*                  Errors specific to SDNET
                   org   1400
err:nodenumbertoobig rmb 1 ; node number selected is too large for net specified
err:nofreeNRBs     rmb 1 ; No free Node Representative Blocks available
err:nodenoresponse rmb 1 ; haven't heard from remote node in a long time
err:nodecrazy      rmb 1 ; remote node babbles incoherently
err:nodequit       rmb 1 ; remote node said "QUIT" conversation
err:cantgetether   rmb 1 ; no opportunities to transmit, link traffic too heavy
err:newincarnation rmb 1 ; "INITIATING" sent by remote node
err:nodesaiddie    rmb 1 ; remote node thinks WE are crazy
err:cantsendmessage rmb 1 ; can't send a complete message reliably
err:nodetooslow    rmb 1 ; remote node won't send us data we need
err:noPLCBs        rmb 1 ; No Physical Link Control Blocks defined
err:illegalnetID   rmb 1 ; Network ID specified does not exist
err:illegalnodeID  rmb 1 ; Node ID specified does not exist on specified network


*                  Device type for network links
*
dvtyp:link         equ $C              stream data device
*
*                  Link driver types for SC:GETERRORSTATS call
*
                   org 0
ldtype:asld        rmb 1               type of link driver = ASLD
; add other link driver types as necessary
;
; Status Calls for NETSERVER: device
                   org   sc:devicespecificop
sc:createreceivesocket rmb 1           create recieve socket and return capability for it
sc:readsocketdata  rmb 1               read data from socket
sc:getbuffercount  rmb 1               read amount of data ready
sc:anysocketready  rmb 1               determine if some NETSERVER: socket has data
;
; Control Calls for NETSERVER: device
                   org   cc:devicespecificop
cc:destroysocket   rmb 1               destroy socket
cc:writesocketdata rmb 1               write data to a socket
                   page
; Capability (CAPABILITY:) definitions (THIS BELONGS IN SDOSDEFS.ASM)
                   org 0
capability:encryptedobjectID rmb 6     holds object ID encrypted
capability:encryptedrights rmb 2       holds rights carried by capability
capability:type    rmb 1               type of object referenced
capability:netID   rmb 1               holds global Network number 0..255
capability:nodeID  rmb 1               holds ID of node in specified network
capability:regionID rmb 1              holds region inside node (memory, disk, etc.)
capability:locatorinfo rmb 4           type-specific object locator
capability:size rmb 0                  size of capability object
                   page

                   org 0
; Message types handled by SDOS Server code
SDOSserverfilenamesyscall rmb   1      ; 1st byte of "file name syscall" msg
SDOSservernoniosyscall  rmb     1      ; 1st byte of "syscall w/o channel" msg
SDOSserverfileiosyscall rmb     1      ; 1st byte of "sycall with channel" msg"

PLCBpointer        equ 4               ; Physical Link Control Block pointer
SocketPointer      equ DCBPointer      ; points to socket while in SM:
NRBpointer         equ DCBpointer      ; points to NRB while in physical link driver

                   page
*     Additional SDOS Entry Points
*
*     Used as portals into the "black box" called SDNET

sdos:surprise      equ $AF7A-$AE00     0 --> makes SDOS:RTI do SDOS:RESCHEDULE

VTDriver           equ SDOS-$2000      kluge to make assembler shut up

sdos:netextensionsize equ $20          extends SDOS: table
                   org -sdos:netextensionsize

*                  Assorted entry points for the outside world

sdos:LogicalUserNumber rmb 1           holds User number of current User
                                       ; set by SDOS/MT on SelectUser call
sdos:netlistenertask rmb 3             Newly hatched listener TCB points (PC) here
sdos:netdispatch   rmb driver:pfrestart+2 VT driver dispatch vector
         page
*
* Extensions to the Configuration Table
*
                   org cnfg:mtprims+2  extends configuration table for NET:
cnfg:ConsoleDriver rmb 2 ; which device is to be opened as CONSOLE:
; Above goodie needs more thought: what if device name is not CONSOLE: ?
; Swap name pointers in DCB?
cnfg:BootDefaultDisk rmb 2 ; which device is to be DefaultDisk after bootup

cnfg:NetID         rmb 1 ; Network which contains this node's unique official name
;                  (Node can have unofficial names if acting as gateway)
cnfg:NodeID        rmb 1 ; Node number of this node's unique official name
cnfg:NRBchain      rmb 2 ; points to list of all NRBs (live or dead) in I/O package
cnfg:freeNRBs      rmb 2 ; points to list of NRBs not assigned to nodes
cnfg:MaxValidNetID rmb 1 ; contains maximum valid Network ID this node knows.
cnfg:NetIDtoNITMap rmb 2 ; points to list of pointers to NITs
;    There is one NIT for each network reachable (in)directly by this node
;    that table is found by indexing this map with the NetID.
cnfg:NetPLCBChain  rmb 2 ; points to list of all Physical Link Control Blocks

cnfg:netsize       equ   *
        page    SD Line Protocol Control field values
*
*       SDLP control field values
*
sdlpcontrol:normal      equ     0      normal data-carrying message
                                       ; (data ack when convenient)
sdlpcontrol:acksoon     equ     1      normal data-carrying message
                                       ; (please send data ack soon)
sdlpcontrol:initiating  equ     2      initiate a connection
sdlpcontrol:resynched   equ     3      re-synchronized response
sdlpcontrol:wantquit    equ     4      wants to quit
sdlpcontrol:agreequit   equ     5      agrees to quit
sdlpcontrol:quit        equ     6      quit!
sdlpcontrol:die         equ     7      sent to node shouting heresies
sdlpcontrol:initiatequit equ    8      initiate, have data, and quit
;
SDLPMsgOverhead         equ     17     total non-data bytes in a message
*
*       NRB states (function of SDLP message protocol)
                        org     0
nodestate:dead          rmb     1      represented node is dead
nodestate:agreequit     rmb     1      represented node sent "wantquit"
nodestate:wantquit      rmb     1      need to disconnect from represented node
nodestate:initiating    rmb     1      we are trying to establish contact with represented node
nodestate:resynched     rmb     1      represented node sent "initiating"
nodestate:initiated     rmb     1      represented node sent "resynched"
nodestate:converser     rmb     1      conversing, expect to receive next
nodestate:converses     rmb     1      conversing, expect to send next
nodestate:conversei     rmb     1      conversing, nothing to say ("idle")
nodestate:quit          rmb     1      we must send "quit" msg to represented node
nodestate:die           rmb     1      we must send "die" mesg to represented node
                        page
*        Network Representative Block (NRB:xxx) definitions
*        NOTE: Information is placed in this NRB in an order that minimizes
*        the space occupied by indexed '09 offsets, (or sometimes, that
*        minimizes the time used by a frequently executed routine).
*        This ordering is based on an empirical analysis of static
*        references to NRB: offsets, and on a dynamic analysis of
*        interrupt and task wake-up condition routines.
*        Altering the order of these definitions may cause the driver
*        to grow significantly, or to impair its performance.

                   org     0
*        The following items have 4 bit offsets on 6809
*        This ensure fast task wakeup routines, fast reference pointers, etc.
nrb:xbuflk         rmb     1           transmit buffer lock (must be offset 0)
         ; receive buffer lock unnecessary because only listener task receives
nrb:ringoutroom    rmb     2           amount of room available for task level
nrb:ringindata     rmb     2           count of input data avail for task level
nrb:state          rmb     1           state of node being represented

*        End gauranteed 4 bit offsets for 6809

nrb:xmitqflink     rmb     2           forward link to next nrb in order list
nrb:xmitqblink     rmb     2           backward link to previous nrb in order list

nrb:nodeid         rmb     1           ; holds Node number within a network (0-->free)
nrb:netid          rmb     1           ; holds Network number in universe
nrb:linkdriver     rmb     2           ; points to vector of entry points...
                                       ; into logical link driver module
nrb:plcb           rmb     2           ; points to physical link control block
nrb:closelink      rmb     1           <>0 --> want to disconnect from remote node
nrb:nextnrb        rmb     2           ; points to next NRB in list of all NRBs
nrb:nextfreenrb    equ     nrb:linkdriver ; points to next NRB not currently in use
                   page
*                  Information used to manage standard ring buffers
*                  These definitions should have relatively short
*                  offsets due to both high static frequency of reference,
*                  and high dynamic reference rate in Link Driver
*                  routines LDE:SBYT and LDE:RBYT.
*
nrb:ringinbank     rmb     1           ring buffer; logical bank containing input ring
nrb:ringinfetch    rmb     2           ring buffer; input fetch pointer
nrb:ringinfdter    rmb     2           ring buffer; fetch distance to end ring
nrb:ringinstore    rmb     2           ring buffer; input store pointer
nrb:ringinsdter    rmb     2           ring buffer; store distance to end ring
nrb:ringinbase     rmb     2           ring buffer; base of input ring pointer
nrb:ringinlen      rmb     2           ring buffer; length of input ring buffer
nrb:ringinroom     rmb     2           ring buffer; room avail for int. level
*
nrb:ringoutbank    rmb     1           ring buffer; logical bank containing output ring
nrb:ringoutfetch   rmb     2           ring buffer; output fetch pointer
nrb:ringoutfdter   rmb     2           ring buffer; fetch distance to end ring
nrb:ringoutstore   rmb     2           ring buffer; output store pointer
nrb:ringoutsdter   rmb     2           ring buffer; store distance to end ring
nrb:ringoutbase    rmb     2           ring buffer; base of output ring buffer
nrb:ringoutlen     rmb     2           ring buffer; length of output ring buffer
nrb:ringoutdata    rmb     2           ring buffer; data avail for int. level

nrb:retry          rmb     1           number of timeouts to conclude dead
nrb:xvpos          rmb     2           transmit virtual position (modulo 2**16)
nrb:rvpos          rmb     2           received virtual position (modulo 2**16)
nrb:rcvdrdy        rmb     2           last rcvdready count
****************** Beyond this point, the number of static/dynamic references
****************** to variables is low enough so order is not important
nrb:maxackrvpos    rmb     2           maximum RVPOS legal in ack message
nrb:datarequiredflag rmb   1           <>0 --> task is waiting for new data
nrb:datarequiredtimestamp rmb 2        contains sdos:clock time when data required
nrb:remotehasmore  rmb     1           remote node has more data to send us
nrb:datasenttimestamp rmb  2           sdos:clock time when data last put into ringout buffer
nrb:averagemsgexcess rmb   2           average amount extra remote sends
nrb:goof           rmb     1           set this to holler "goof!!!"
nrb:epitaph        rmb     2           holds error code describing NRB's death

nrb:recvtob        rmb     tob:size    used to time out expected, valid response
                   if      0
; The following would be needed if SDOS/RT is implemented.
nrb:recvecb        rmb     ecb$size    used to signal arrival of new data
nrb:xmitecb        rmb     ecb$size    used to signal available room
                   fin     0

; THESE SKT: DEFINITIONS ARE PLACED TEMPORARILY IN NRBS UNTIL SKTMGR BUILT
; Socket Control Block (SKT:) definitions
skt:userchainflink rmb     2           ; forward User Socket Chain link
skt:userchainblink rmb     2           ; backward User Socket Chain link
skt:userchainreferencecount rmb 1      ; number of Channels using this socket
skt:nrbpointer     rmb     2           ; points to NRB to use with socket
                   if      0
; The following would be needed if SDOS/RT is implemented.
skt:ecb            rmb     ecb:size    ; holds event control block for socket
                   fin     0

nrb:tcb            rmb     tcb:size    this node's listener task's tcb
nrb:tcbstacksize   equ     20+minstack amount of stack space needed by listener task
nrb:tcbstack       rmb     nrb:tcbstacksize stack space for listener task
nrb:stackbase      rmb     1           stack base for listener task
nrb:size           equ     *
                        page
                        org     0
; Network Information Table Node Data Entry (NITNDE:)
;    Contains all the information about a particular node on a network
;    There is one entry per valid node ID in each NIT: (see below)
NITNDE:PLCB             rmb     2      ; points to PLCB to use for this node
NITNDE:NRB              rmb     2      ; points to NRB assigned to node (or zero if none)
;    Used by link drivers to associate incoming messages with NRB associated
;    with node sending the message.
NITNDE:Size             rmb     0      ; size of NITNDE: slot

                        org     0
; Network Information Table (NIT:)
;    Contains all the information about a particular network.
;    Also contains identity of THIS node.
;
NIT:NetID               rmb     1      ; Network Identity of nodes on this net
NIT:NodeID              rmb     1      ; Node ID of this node on network NIT:NetID
;                       ; NOTE: NOT NECESSARYILY EQUAL TO CNFG:NODEID!
NIT:MaxNodeID           rmb     1      ; Maximum valid node ID on network
NIT:GatewayNodeID       equ     NIT:NodeID ; Which node to send gateway msgs to
NIT:GatewayNetID        rmb     1      ; <>0 --> forward messages to gateway
;                                      ; i.e., NIT:NetID not directly reachable
NIT:NodeLookupBase rmb NITNDE:Size*256 ; Room for 256 NRB pointers
; This table indexed by NodeID*NIT:NodeLookupEntrySize+...:Base

                        org     0
; Physical Link Control Block.
;    This block is used to store all of the context required by a Link Driver
;    to operate a single physical link; usually, a single link has many
;    nodes attached to it.  However, a single network may require several
;    Physical Links to reach all of the nodes in it.
;
PLCB:NextPLCB           rmb     2      ; Points to next PLCB in chain or zero
PLCB:LinkDriver         rmb     2      ; Points to Link Driver which runs link
PLCB:NITpointer         rmb     2      ; Points to NIT for network which PLCB represents
PLCB:LinkSpecificInformation rmb 0     ; all further data is Link Driver dependent
                        page
; Device Control Block extensions for Remote node DCBs
;
                        org     DCB:DRIVER+2
dcb:netid               rmb     1      ; specifies network number for node (usually = 0)
dcb:nodeid              rmb     1      ; holds remote node physical number
dcb:netsize             rmb     0      ; size of network DCB

         if    0
; Each remote node known by name to the local node must have a DCB
; in the local node with the following form:
; (This kind of DCB will go away when SDOS is modified to hunt for a node
; when given a name which does not match any local DCB).
         fcb   1                       ; DCB:DONEFLAG (dummy: ignored)
         fdb   0                       ; DCB:LASTERROR (dummy: ignored)
         fdb   NodeName                ; DCB:NAME points to node name
         fdb   NextDCB                 ; DCB:NEXTDCB points to next device DCB
         fdb   NetDeviceDriver         ; DCB:DRIVER points to SDNETDEVICE driver entry point
         fcb   NetworkID               ; DCB:NETID specifies network number for node (usually = 0)
         fcb   NodePhysicalNumber      ; DCB:NODEID holds remote node physical number

NodeName fcc   "NAME:"                 ; Sysgen-time assigned remote node name
         fcb   0
         fin
                   page
*
*        Common Entry points into Link Driver
                        org     0      ; physical link driver entry (LDE:) points
lde:reset               rmb     2      ; reset device associated with PLCB
lde:olnk                rmb     2      ; open link using NRB
lde:clnk                rmb     2      ; close link to node nicely
lde:blnk                rmb     2      ; break link with node NOW
lde:sbyt                rmb     2      ; send 1 byte
lde:sblk                rmb     2      ; send a block of data
lde:thnt                rmb     2      ; transmit hint
lde:rhnt                rmb     2      ; receive hint
lde:rcnt                rmb     2      ; get received data count
lde:gbyt                rmb     2      ; get byte soon or die
lde:rbyt                rmb     2      ; receive byte leisurely
lde:gblk                rmb     2      ; get block soon or die
lde:rblk                rmb     2      ; receive block leisurely
lde:bcst                rmb     2      ; broadcast message
lde:rqb                 rmb     2      ; request broadcast count
lde:stats               rmb     2      ; get error statistics from PLCB
lde:customentrypoints   rmb     0      ; custom entry points start here

         ifund NeedASLDdefinitions
NeedASLDdefinitions equ 0 ; We don't need ASLD-specific definitions
         fin

         if    NeedASLDdefinitions      ; want to gen for ASLD driver
         page  ASLD Interface Definitions
; Definitions used only by the Asynchronous Link Driver and/or
; I/O packages using ASLD for network support.

; Entry points into Asynchronous Serial Link Driver from I/O package
;
         org   lde:customentrypoints   ; custom entry points start here

asld:interruptplcb rmb   2             must point to PLCB on interrupt entry to ASLD

asld:inputbadinterrupt rmb 3           JMP here if input data is malformed
*        Come here when malformed data detected, Stacks must not be switched
*        Intended to handle conditions like FRAMING ERROR (garbled character)

asld:inputlateinterrupt rmb 3          JMP here if we lost input data
*        Come here when we detect lost data, Stacks must not be switched
*        Intended to handle conditions like OVERRUN (we missed a character)

; Note: there are two other implicit interrupt entry points to ASLD,
; one for "inputdatainterrupt" and one for "outputdatainterrupt",
; which are defined in the PLCB for efficiency reasons.  ASLD sets
; them up, so the I/O package implementer need not do so.
         page
* Link control tuning parameter defaults (suitable for 9600 baud)
* The defaults are named ASLDC:xxx, and supply suitable values for
* places in the PLCB slots correspondingly named PLCBASC:xxxx
*
         ifund asldc:datarate
asldc:datarate equ 960                 ; bytes per second
         fin

         ifund asldc:messagedatasizemax
asldc:messagedatasizemax equ 256       ; space for message content, max
         fin

         ifund asldc:efficientmsgthreshold ; data bytes in an efficient SDLP packet
asldc:efficientmsgthreshold equ 5*SDLPMsgOverHead
         fin

         ifund asldc:characterticks    ; # clock ticks per char xmit/rcv
asldc:characterticks equ (10000/166)/(asldc:datarate)+1
; Above time is (1000 Milliseconds)/(Milliseconds/Clock Tick)...
; divided by the number of characters that can arrive per second
; The "+1" is  because 1 tick can occur instantly
         fin

         ifund asldc:messagetime ; how long in time the longest message is
asldc:messagetime set SDLPMsgOverhead+asldc:messagedatasizemax ; msg size in characters
asldc:messagetime set asldc:messagetime/(1000/asldc:datarate)+1 ; msg time in 60Hz ticks
; The "+1" is because 1 tick can occur instantly
         fin

         ifund asldc:xmitpatiencetime ; max time to try for transmission before giving up
asldc:xmitpatiencetime equ 60*1000 ; 1 minute of trying with no success
         fin

         ifund asldc:respondtime ; how long to wait before responding to a message just received
; This value is determined, not by data transmission rates or message sizes,
; but rather by how long it takes the network logic to fill its transmit
; buffers.
asldc:respondtime equ 50              ; milliseconds
         fin

         ifund asldc:retrytime ; how long to wait before retransmitting our message
asldc:retrytime equ 10*asldc:respondtime+10*asldc:messagetime ; milliseconds
         fin

         ifund asldc:datarequiredtime ; max time before remote must send data
; This value determined by how long it takes remote node to fill its transmit
; buffers with new data.
asldc:datarequiredtime equ 2*asldc:messagetime+asldc:respondtime
         fin

         ifund asldc:retrycount ; how many times to try before declaring dead node
; This value is inversely related to the reliability of the transmission link
asldc:retrycount equ 100               ; # times to query remote node
         fin
         page
; Physical Link Control Block extensions specific to ASLD

         org   PLCB:LinkSpecificInformation

; Contains data which parameterizes a particular physical link device
; One PLCB is needed for EACH physical link device involved.
; These offsets are all prefixed with PLCBAS:xxx standing for
; "Physical Link Control Block Asynchronous Link (Driver): xxxx"
; The prefix PLCBASC:xxx means that this label is a Customizing point, i.e,
; it is used by ASLD but defined (or filled) by the I/O package implementer.
; The more conventional prefix PLCBAS:xxx are PLCB slots dynamically
; filled in by ASLD; the I/O package implementer need only reserve
; enough space as specified by PLCBAS:SIZE.
;
; ------------------------------------------------------------------------
; The following variables are here to ensure short index displacements.
; This minimizes time to access these while transmitting/recieving data.
;
; PLCBAS:STATE is used to synchronize various parts of the ASLD driver
; Normally it says "uncommitted", i.e., neither receiving or transmitting
; When the driver decides to transmit, or message bytes start arriving,
; The state variable is set appropriately so the driver will not attempt the
; complementary operation in the middle of another.
; The RECIEVE state is entered whenever any message bytes arrive,
; even if the message is not for this node; this prevents us from
; trying to transmit while there is traffic on the bus
;
plcbas:state   rmb 1                     represent XMIT/RECV mechanism state
;   0 --> uncommitted                    -1 --> receiving or ignoring a message
;   >0 --> transmitting a message        :80 --> receiving, only watching for ETB
;
plcbas:msgpart1count      rmb 2          - # bytes in 1st part of data portion of message
plcbas:msgpart2count      rmb 2          - # bytes in 2nd part of data portion of message

plcbas:counter            rmb 2          GP counter: used by Verify logic,
;   Message head receive logic, and Ignore Chunk receive logic.
plcbas:computedcrcupper   rmb 1          upper 8 bits of computed CRC
plcbas:computedcrclower   rmb 1          lower 8 bits of computed CRC
plcbas:waitbyteandcrcreturn rmb 2        return address for ASLDIR:WAITBYTEANDCRC
; ------------------------------------------------------------------------
                          page
; ------------------------------------------------------------------------
; The following variables are referenced infrequently, and so short index
; offsets for performance reasons are unnecessary.
; They are referenced often enough so 16 bit offsets would be unfortunate.

;    transmit/recieve message buffer head
;
plcbas:msgsyn             rmb 1          leading byte of message
plcbas:msgto              rmb 1          who message was sent to
plcbas:msgfrom            rmb 1          who we received the message from
plcbas:msgidcrc           rmb 2          holds crc over TO and FROM
plcbas:msgcontrol         rmb 1          control byte sent by other computer
plcbas:msgrvpos           rmb 2          virtual position of our file that other computer has
plcbas:msgreadycount      rmb 2          available buffer space that other computer has
plcbas:msgxmitcount       rmb 2          # data bytes sent by other computer in this message
plcbas:msgxmitbase        rmb 2          virtual address mod 2**16 of first data byte in message

plcbas:msgcrc             rmb 2          recieved CRC bytes

plcbas:msgheadptr         rmb 2          pointer into message head
plcbas:msgpart1ptr        rmb 2          pointer into 1st part of data portion of message
plcbas:msgpart2ptr        rmb 2          pointer into 2nd part of data portion of message
plcbas:nrbptr             rmb 2          pointer to receiving NRB or 0
plcbas:nrbindexptr        rmb 2          points to NRBINDEX slot for tentatively
                                         ; assigned NRB
plcbas:collisionresolutionactive rmb 1   <>0 --> waiting for collision resolution to complete
plcbas:xdelaymask         rmb 2          quadratic transmit conflict resolution window mask

plcbas:datasavedcount     rmb 2          number of msg data bytes put into ring
plcbas:msgexcesscount     rmb 2          number of msg data bytes we would like
;                                        to have saved but had no room for
; ------------------------------------------------------------------------
; Variables from this point on are referenced infrequently.
; Even 16 bit offsets wouldn't be a terrible time or space penalty.
        page
;       statistics about network link operation
;
plcbas:statisticsbegin ; begin statistical counters

plcbas:enbrcvcount        rmb  2         # times we enabled reciever to hear new message
plcbas:badcrccount        rmb  2         # msgs with bad crc received
plcbas:goodidcount        rmb  2         # msgs whose id CRC is good
plcbas:goodcrccount       rmb  2         # msgs with good crc received
plcbas:inputerrorcount    rmb  2         # msgs we muffed on receive somehow
plcbas:noclockcount       rmb  2         # times received message stopped in middle
plcbas:collisioncount     rmb  2         # times that a collision occurred on transmit
plcbas:xmitokcount        rmb  2         # times we successfully sent a complete message
plcbas:etherbusycount     rmb  2         # times ether was busy when we wanted to transmit
plcbas:timedoutcount      rmb  2         # times we timed out expecting a response
plcbas:crazymsgcount      rmb  2         # crazy messages received
plcbas:xmittimeoutcount   rmb  2         # times xmit failed to get output int
plcbas:inputlatecount     rmb  2         # times we lost a byte by being too slow
plcbas:inputbadcount      rmb  2         # time we got bad data interrupt
plcbas:outofsynccount     rmb  2         # times good msg not followed by <gap>
plcbas:missedETBcount     rmb  2         # times we hunted for ETB and missed it
plcbas:notenoughNRBscount rmb  2         # times we lost a message becuz no NRBs
plcbas:broadcasttoolongcount rmb 2       # broadcasts too long to retain completely
plcbas:headerverifyfailcount rmb 2       # times header only partially verified
plcbas:unexpectedTDREcount rmb 2         # times we got unexpected TDRE interrupt
plcbas:xmittooslow        rmb  2         # took too long for use to xmit a message
plcbas:xmitfailcount      rmb  2         # times we failed to send message reliably

plcbas:statisticsend ; end statistical counters
        page
; Entry points to physical device I/O routines for Asynch LD to use
; The prefix PLCBASC:ILxxx indicates the routine is entered at interrupt
; level, i.e., the interrupt system is disabled, stacks not switched.
; Entered with (X) holding ASLD:INTERRUPTPLCB; must preserve (X)
;
plcbasc:ilputdev     rmb   4           JMP'd to by ASLD to output byte in (A).
; ilputdev should have an offset of <$80 to make 6809 output fast
;                                      Exit via RTI. Usually contains:
;                                      STAA >DEV\RTI

; The following PLCB slots MUST be near PLCBASC:IPB:POLLCODE
; so that in-line poll code there can reach these places by relative JMPs
; They should also have offsets <$80 to keep costs low
;
;        The following 2 slots MUST stay in the order specified
plcbas:iloutputint   rmb   1           come here to enter ASLD on output int
;                                      Filled by ASLD with JMP opcode
plcbas:iloutputintPC rmb   2           Holds ASLD output interrupt re-entry point

;        The following 2 slots MUST stay in the order specified
plcbas:ilinputint    rmb   1           come here to enter ASLD on input interrupt
;                                      Filled by ASLD with JMP opcode
plcbas:ilinputintPC  rmb   2           Holds ASLD input interrupt re-entry point
                     page
; CHARACTERTIMEOUT is used to time out "nano"scopic activities, in particular,
; individual character transmissions/receipts.
; This timeout is the old SDOS-style, very low overhead but inaccurate
; (errs on the too-generous side) type of timeout.
; Use of this kind of TOB is necessary due to the high data rates involved,
; and the cost of setting an accurate TOB for each character transaction.
; Since there is only one of these TOBs, when simultaneously transmitting
; and verifying, only the transmission of individual characters is timed.
; This TOB should have an offset of <$80 to make 6809 input/output fast
plcbasc:charactertimeout rmb timeout:size old-style, low overhead timeout block

plcbasc:ilenboi      rmb   3           called by LD to enable link output ints
; (interrupt when empty output buffer) returns Z reset if device ready NOW
plcbasc:ildisoi      rmb   3           call to disable empty buffer output int
plcbasc:ilenbii      rmb   3           called by LD to enable link input ints
plcbasc:ildisii      rmb   3           call to disable input interrupts
plcbasc:ilreset      rmb   3           called to initialize link hardware
;
; Entry points used to sense carrier/transmit gap
; Entered at interrupt level, with stacks switched and interrupts ENABLED
; The (X) need not be preserved.
;
plcbasc:ilcsma       rmb   3           call to sense carrier
plcbasc:ilxgap       rmb   3           transmit end of message gap
plcbasc:NITptr       rmb   2           points to network information table
                                       ; that this PLCB should use
                     page
; XMITFAILTOB is used to ensure that macroscopic xmit activities complete.
; It is set ONCE when an NRB first attempts to transmit, and is
; active during all attempts by that NRB to acquire the network link
; and send data.  This is safe because once an NRB attempts to transmit
; on a link, it cannot be usurped (as the next transmitter) until it succeeds
; or dies. When XMITFAILTOB goes off, ASLD decides that successful
; acquisition and transmission of the link is impossible and aborts the NRB.
plcbas:xmitfailtob        rmb tob:size "Ensure Xmit Success" timeout block

; XMITTOB is used to time out microscopic transmission activities,
; such as the following:
;     1) timing out failure of the output device to send
;        (this is accomplished by computing the expected delay for the
;         entire message and setting a timeout for slightly longer than that)
;     2) waiting for collision resolution periods to pass
; Note that XMITTOB can be active watching the transmission of a single
; message at the same time that XMITSUCCESSTOB is active for an NRB.
plcbas:xmittob            rmb tob:size Microscopic Xmit activity timer

; RECVTOB is used to time out various microscopic "receive" activities,
; such as the following:
;      1) timing out failure of balance of message to arrive
;         (this is accomplished by computing maximum length of message
;          and setting a timeout for slightly longer than that)
;      2) watching for bus silence while searching for ETB.
; Note that RECVTOB can be active while XMITTOB is being used for
; collision resolution, and XMITFAILTOB is watching for eventual success.
plcbas:recvtob            rmb tob:size Microscopic Receive activity timer

; XMITQ is used to record all NRBs which are ready to transmit NOW via
; this PLCB.  Newly ready NRBs are placed at the end of XMITQ.  An NRB
; arriving at the front of the XMITQ stays there until it either
; succeeds in transmitting its message, receives a message which kills
; it, or is killed by some local request.
plcbas:xmitqhead ; list of ready-to-transmit NRBs
                          rmb 2        corresponds to NRB:XMITQFLINK
                          rmb 2        corresponds to NRB:XMITQBLINK
         page
;        What follows are the hardware specific tuning parameters and
;        device interface routine entry points.
;
plcbasc:messagedatasizemax rmb 2       maximum size of message body in chars
plcbasc:efficientmsgthreshold rmb 2    # data bytes req'd for efficient msg
;
;        The ...time variables are all measured in terms of milliseconds
;
plcbasc:characterticks rmb 1           max 60Hz ticks per character xmit/rcv time
;                                      (longer than <gap> after message)
plcbasc:messagetime  rmb   2           max time for message xmit/rcv
plcbasc:etheracquiretime rmb 2         max time to acquire ether
plcbasc:xmitpatiencetime rmb 2         max time to try for transmission before giving up
plcbasc:respondtime  rmb   2           max response time after msg receipt (defines "soon")
plcbasc:datarequiredtime rmb 2         max time to get required data
plcbasc:retrytime    rmb   2           max time to wait before re-xmit a message
plcbasc:retrycount   rmb   1           holds # times to re-xmit before give up
;
plcbasc:ipb:priority   rmb  1          priority byte for this link device hardware
plcbasc:ipb:jmpnextipb rmb  3          contains JMP to next IPB in poll chain
plcbasc:ipb:pollcode  rmb  0           room for code to test device for request
;        This code must determine if Link hardware device wants an interrupt,
;        and if so, acknowledge the device interrupt, grab any input data,
;        and vector to the proper ASLD entry point.
;        Error-free input and output data interrupts are vectored via
;        slots in the PLCB in order to keep overhead as low as possible.
;        If you must know the reason, look inside the ASLD driver module.
;        Input error interrupts need not have such high performance,
;        so the vector entry points are at the beginning of ASLD itself.
;        ASLD:INTERRUPTPLCB must be set by this code.
;        Note that no stack switching is performed (ASLD does it later).
;        This embedded Interrupt Poll Block must be near
;        PCBLAS:ILOUTPUTINT and PCBLAS:ILINPUTINT so that relative
;        branch instructions in the Pollcode can reach those two labels.
;        This part of PLCB is placed last so that interrupt poll code
;        can be as complex and lengthy as necessary.
PLCBAS:SIZE equ *                      ; Size of PLCB required by ASLD
         page
;        What follows is a typical example of code for PCBLASC: interface
;        This example is designed for Motorola 6850 ACIA
         if    0   ; so we can code sample ACIA network interface normally

         org   ThisPLCB+plcbasc:ilreset ; device hardware interface vectors
NETACIA:ILPUTDEV ; send (A) to device for transmission
; Note: this routine is actually placed IN the PLCBASC:ILPUTDEV slot
         staa  netACIAdata             store into transmit buffer
         rti                           all done

         org   ThisPLCB+plcbasc:charactertimeout+timeout:nexttimeout
         fdb   NextTimeout             must insert low overhead TOB statically
Ntimeouts equ NTimeouts+1 ; for benefit of rest of I/O package

         org   ThisPLCB+plcbasc:ilenboi
         jmp   NETACIA:ILENBOI ; enables "xmit buffer empty" interrupt
         jmp   NETACIA:ILDISOI ; disables "xmit buffer empty" interrupt
         jmp   NETACIA:ILENBII ; enables "input data available" interrupt
         jmp   NETACIA:ILDISII ; disable "input data available" interrupt
         jmp   NETACIA:ILRESET ; reset network ACIA and return node identity in (D)
         jmp   NETACIA:ILCSMA  ; Carrier-sense multiple access
         jmp   NETACIA:ILXGAP  ; transmit end-of-message "gap" (also clears overrun)
         fdb   NETACIA:NIT     ; Points to Net Info Table for this ACIA to use

         org   ThisPLCB+plcbasc:messagedatasizemax
         fdb   asldc:messagedatasizemax ; max size of data part of message
         fdb   asldc:efficientmsgthreshold ; size of efficient message
         fcb   asldc:characterticks    ; time for 1 character to be sent
         fdb   asldc:messagetime       ; how long in time the longest message is
         fdb   asldc:etheracquiretime  ; max time to acquire ether
         fdb   asldc:xmitpatiencetime  ; max time to try for transmission before giving up
         fdb   asldc:respondtime       ; how long to wait before responding to a message just received
         fdb   asldc:datarequiredtime  ; max time before remote must send data
         fdb   asldc:retrytime         ; how long to wait before retransmitting our message
         fcb   asldc:retrycount        ; how many times to try before declaring dead node
         fin   1st part of example
         page
         if    0  ; so we can code sample ACIA network interface normally
         org   ThisPLCB+plcbasc:ipb:priority ; put code in proper place
         fcb   $F0                     ; Interrupt Priority byte: "very fast"
         jmp   VTdevicePollChain       ; where to go if not network device
Interrupt ; interrupt vector passes control to here, stacks not switched
; check net ACIA first, due to stringent real-time constraints
; it has even higher priority than Virtual Terminal device interrupts
         ldab  netACIAstatus           ; (5~) fetch ACIA status register
         bpl   ThisPLCB+plcbas:ipb:jmpnextipb ; (3~) b/ ACIA doesn't want interrupt
         ldx   #ThisPLCB               ; (3~) fetch PLCB address
         stx   ASLD+asld:interruptplcb ; (5~) record PLCB address for ASLD's use
         bitb  #aciatdre               ; (2~) output interrupt requested ?
         bne   ThisPLCB+plcbas:iloutputint ; (3~) b/ yes, go service
         ldaa  netACIAdata             ; (5~) fetch data and acknowledge interrupt
         bitb  #aciape!aciaovrn!aciafe!aciadcd ; (2~) an input errors ?
         beq   ThisPLCB+plcbas:ilinputint ; (3~) b/ no, go service input interrupt
         bitb  #aciaovrn               ; (2~) overrun ?
         lbne  ASLD+asld:ilinputlateinterrupt ; (5~) b/ yes, go handle
         jmp   ASLD+asld:ilinputbadinterrupt ; (4~) no, go handle bad character
         fin   2nd part of example
         page
         if    0   ; so we can code sample ACIA network interface normally
*** Sample code to implement physical I/O routines
*** Each NETACIA:xxx routine gains control via a JMP planted in PLCBAS:xxx
 
NETACIA:ILRESET ; reset network ACIA and return node identity in (D)
         ldaa  #aciareset              zap the ACIA
         staa  netACIAcontrol
         ldaa  #aciaws81s+aciadiv16    set for 8 data bits + 1 stop bit
         staa  netACIAcontrolimage     update image of control word
         staa  netACIAcontrol          tell ACIA
         ldaa  netACIANETID            read hardware register holding NET ID
         ldab  netACIANODEID           read hardware register holding NODE ID
         rts

NETACIA:ILENBOI ; enables "xmit buffer empty" interrupt
         ldaa  netACIAcontrolimage     get image of control word
         oraa  #%00100000              set "int on xmit buffer empty"
         staa  netACIAcontrolimage     update image of control word
         staa  netACIAcontrol          tell acia
         rts
 
NETACIA:ILDISOI ; disables "xmit buffer empty" interrupt
         ldaa  netACIAcontrolimage     get image of control word
         anda  #\%01100000             set "no interrupt xmit buffer empty"
         staa  netACIAcontrolimage     update image of control word
         staa  netACIAcontrol          tell acia
         rts
 
NETACIA:ILENBII ; enables "input data available" interrupt
         ldaa  netACIAcontrolimage     get image of control word
         oraa  #%10000000              set "int on received character"
         staa  netACIAcontrolimage     update image of control word
         staa  netACIAcontrol          tell acia
         rts
 
NETACIA:ILDISII ; disable "input data available" interrupt
         ldaa  netACIAcontrolimage     get image of control word
         anda  #\%10000000             set "no int on received character"
         staa  netACIAcontrolimage     update image of control word
         staa  netACIAcontrol          tell acia
         rts
         fin   3rd part of example
         page
         if    0   ; so we can code sample ACIA network interface normally
NETACIA:ILXGAP ; transmit end-of-message "gap" (also clears overrun)
; Waits for arrival of ASCII:ETB character at end of message (max 1 char time)
; Clears Received Data and Data Overrun
; Then waits for 1 character time (this is what transmits the "gap")
; Operates with input and output interrupts disabled, CPU ints enabled
        ldaa    netACIAdata            acknowledge previous data
        bsr     NETACIA:ILCSMA         wait for ETB to arrive or 1 char time
        ldaa    netACIAdata            ack arrival of ETB, clear data overrun
;       bra     NETACIA:ILCSMA         go transmit the gap (nothing will come!)
 
NETACIA:ILCSMA ; Carrier-sense multiple access
; Ensures that "Ether" is free by watching bus for 1 character + 2 baud times,
; and making sure that no character is received in that window
; (this routine assumes 9600 bits per second)
; This routine is called only if input interrupts are disabled, and
; CPU interrupts ARE enabled, so it is acceptable to sit and loop while
; waiting.
 
         ldx   #(10+2)*(1e6/9600)/(4+4+4+2+4) # times around loop
; 10+2 = 1 character time (10 bits) + 2 baud
; 1e6 = 1Mhz clock rate
; 9600 = baud rate (per second)
; 4+4+4+2+4 = cycle count for loop body
NETACIA:ILCSMALoop
         dex                           (4~) down count 1 ms. delay
         beq   NETACIA:ILCSMARts       (4~) b/ 1 ms passed with no Ether traffic
         ldaa  netACIAcontrol          (4~) check acia status
         bita  #%00000001              (2~) receiver register have data ?
         beq   NETACIA:ILCSMALoop      (4~) b/ no, wait a little longer
NETACIA:ILCSMARts
         rts                           with Z reset if Ether is busy

netACIAcontrolimage fcb changed        holds image of ACIA control word
         fin   example network ACIA interface

         fin   NeedASLDdefinitions

         ifund NeedACIADefinitions
NeedACIADefinitions equ 0
         fin

         if    NeedACIADefinitions
         page  Motorola 6850 (ACIA) Definitions
*
*       Motorola 6850 (ACIA) status register bits definitions
*
aciairq         equ     %10000000      "acia wants interrupt"
aciape          equ     %01000000      "parity error on received data"
aciaovrn        equ     %00100000      receiver overrun
aciafe          equ     %00010000      framing error
aciacts         equ     %00001000      not cts
aciadcd         equ     %00000100      not data carrier detect
aciatdre        equ     %00000010      transmit data register empty
aciardrf        equ     %00000001      receive data register full
*
*       acia control register bit definitions
*
aciarie         equ     %10000000      receiver interrupt enable
aciatcbrk       equ     %01100000      set *rts low, transmit break
aciatcrtslow    equ     %01000000      set *rts high, disable transmit interrupt
aciatcenbi      equ     %00100000      set *rts low, enable transmit interrupt
aciatcdisi      equ     %00000000      set *rts low, disable transmit interrupt
aciaws81s       equ     %00010100      8 data bits + 1 stop bit
aciareset       equ     %00000011      master reset to acia
aciadiv16       equ     %00000001      divide clock by 16
         fin   NeedACIADefinitions

;        END of SDNET10DEFS.ASM
