INITIO  TITLE   "Z80 BCPL Run Time System  -  Section INITIO"
        GET     "HEADER"
        LAYOUT
;  This section contains the basic stand alone I/O routines for the Z80 BCPL
;  system.  The nature of the raw I/O devices will depend on the hardware
;  for which the code is intended.
        LAYOUT
        REF     C.FNDI
        REF     C.FNDO
        REF     B.FNDI
        REF     B.FNDO

        DEF     C.RDCH
        DEF     C.WRCH

G.SARD  EQU     2*21                    ;  Global number of "sardch"
G.SAWR  EQU     2*22                    ;  Global number of "sawrch"
G.INIO  EQU     2*50                    ;  Global number of "initio"
G.IOLS  EQU     2*51                    ;  Global number of "iolist"
G.MAXG  EQU     2*150                   ;  Highest referenced global
        LAYOUT
;  UART Equates
;  ------------


U.CONT  EQU     #X10                    ;  UART control register
U.STAT  EQU     #X10                    ;  UART status register
U.TX    EQU     #X11                    ;  UART transmit register
U.RX    EQU     #X11                    ;  UART receive register

U.RESET EQU     #X03                    ;  RESET command
U.INIT  EQU     #X09                    ;  INIT values

U.RDRF  EQU     #X01                    ;  Read register full
U.TDRE  EQU     #X02                    ;  Transmit register empty
        LAYOUT
        RELOCATABLE

        ORG     0

INITIO  DEFB    'BCPL'                  ;  Entry flag for BCPL module
        DEFW    INITIOE-INITIO          ;  Length of module in bytes
        LAYOUT
;  INITIO
;  ------
;
;    initio()


        ALIGN

INIO    SETLINK                         ;  Set up BCPL linkage

;  Open and select the default input stream:
;
;    selectinput( findinput( "**" ) )

        LD      HL,INAME                ;  Name of default input file
        SRL     H                       ;  Make BCPL pointer ...
        RR      L                       ;  ... from file name
        EXX                             ;  Save argument register set
        LD      L,(IY-10)               ;  Low byte of "findinput"
        LD      H,(IY-9)                ;  High byte of "findinput"
        APPLY                           ;  Apply the function
        DEFB    0                       ;  Increase in stack size
        EXX                             ;  Save argument register set
        LD      L,(IY-6)                ;  Low byte of "selectinput"
        LD      H,(IY-5)                ;  High byte of "selectinput"
        APPLY                           ;  Apply the function
        DEFB    0                       ;  Increase in stack size

;  Open and select the default output stream:
;
;    selectoutput( findoutput( "**" ) )

        LD      HL,ONAME                ;  Name of default output file
        SRL     H                       ;  Make BCPL pointer ...
        RR      L                       ;  ... from file name
        EXX                             ;  Save argument register set
        LD      L,(IY-8)                ;  Low byte of "findoutput"
        LD      H,(IY-7)                ;  High byte of "findoutput"
        APPLY                           ;  Apply the function
        DEFB    0                       ;  Increase in stack size
        EXX                             ;  Save argument register set
        LD      L,(IY-4)                ;  Low byte of "selectoutput"
        LD      H,(IY-3)                ;  High byte of "selectoutput"
        APPLY                           ;  Apply the function
        DEFB    0                       ;  Increase in stack size

;  Now, initialise the UART so that we can use it later.

        LD      A,U.RESET               ;  RESET command
        OUT     (U.CONT),A              ;  Reset the UART
        LD      A,U.INIT                ;  INIT values
        OUT     (U.CONT),A              ;  Initialise the UART

        RETURN                          ;  And return


        ALIGN
INAME   DEFB    "**"                    ;  Default input file name

        ALIGN
ONAME   DEFB    "**"                    ;  Default output file name
        LAYOUT
;  SARDCH
;  ------
;
;    ch  :=  sardch()


        ALIGN

SARD    PUSH    HL                      ;  Save return address
        CALL    C.RDCH                  ;  Read a character
        LD      H,0                     ;  High byte of result
        LD      L,A                     ;  Character
        RET                             ;  And return
        LAYOUT
;  SAWRCH
;  ------
;
;    sawrch( ch )


        ALIGN

SAWR    PUSH    HL                      ;  Save return address
        EXX                             ;  Switch register sets
        LD      A,L                     ;  Load character to be printed
        CALL    C.WRCH                  ;  Write it out
        RET                             ;  And return
        LAYOUT
;  C.RDCH, C.WRCH
;  --------------
;
;    Raw console read and console write routines.  These routines are called
;    from SARDCH and SAWRCH, and also from the console handler.  Entry is
;    via Z80 CALL, and arguments/results are passed in A.  No other registers
;    are corrupted.


C.RDCH  IN      A,(U.STAT)              ;  Read status register
        AND     U.RDRF                  ;  Is there a character ?
        JP      Z,C.RDCH                ;  No, so loop until there is

        IN      A,(U.RX)                ;  Read the character
        RET                             ;  And return


C.WRCH  PUSH    AF                      ;  Save character
C.WRCH0 IN      A,(U.STAT)              ;  Read status register
        AND     U.TDRE                  ;  Is register empty ?
        JP      Z,C.WRCH0               ;  Loop until it is

        POP     AF                      ;  Restore character
        OUT     (U.TX),A                ;  Write it out
        RET                             ;  And return
        LAYOUT
;  IOLIST
;  ------
;
;    List of device names and their associated "findinput" and "findoutput"
;    routines.


        ALIGN

IOLS    DEFW    C.NAME,C.FNDI,C.FNDO    ;  Console handler
        DEFW    B.NAME,B.FNDI,B.FNDO    ;  Byte stream handler
        DEFW    0,0,0                   ;  End of list marker


C.NAME  DEFB    "**"                    ;  Name of console device
B.NAME  DEFB    "BSP"                   ;  Name of byte stream device
        LAYOUT
        ALIGN

        DEFW    0                       ;  End of global list
        DEFW    G.SARD,SARD             ;  Entry of SARDCH
        DEFW    G.SAWR,SAWR             ;  Entry of SAWRCH
        DEFW    G.INIO,INIO             ;  Entry of INITIO
        DEFW    G.IOLS,IOLS             ;  Address of IOLIST
        DEFW    G.MAXG                  ;  HRG
        LAYOUT
INITIOE END


