;  PROGRAM:  IOLOADER
;  AUTHOR:  RICHARD CONN
;  VERSION:  1.3
;  DATE:  6 Jan 83
;  PREVIOUS VERSIONS:  1.0 (10 Oct 82), 1.1 (29 Dec 82), 1.2 (5 Jan 83)
;
VERS    EQU     13

;
;       This program is Copyright (c) 1982, 1983 by Richard Conn
;       All Rights Reserved
;
;       ZCPR2 and its utilities, including this one, are released
; to the public domain.  Anyone who wishes to USE them may do so with
; no strings attached.  The author assumes no responsibility or
; liability for the use of ZCPR2 and its utilities.
;
;       The author, Richard Conn, has sole rights to this program.
; ZCPR2 and its utilities may not be sold without the express,
; written permission of the author.
;


;
;       IOLOADER is a program which loads a file of Redirectable I/O
; Drivers into the proper place in the CHBIOSZ for later use.  This
; place is defined by the IOBADR buffer in the front of this program.
;
;       IOLOADER is invoked in one of two ways:
;               IOLOADER -- Loads the File SYSIO.IO
;               IOLOADER filename -- Loads the File filename.IO
;               IOLOADER filename.typ -- Loads the File filename.typ
;
       EXT     PRINT,ZGPINS,CLINE,MOVEB,LOGUD,BDOS
       EXT     ZFNAME,ZPFIND,F$OPEN,F$CLOSE,F$READ,INITFCB

TBUFF   EQU     80H     ;TBUFF OF ZCPR2
CR      EQU     0DH
LF      EQU     0AH

;
;  Branch to Start of Program
;
       jmp     start

;
;******************************************************************
;
;  SINSFORM -- ZCPR2 Utility Standard General Purpose Initialization Format
;
;       This data block precisely defines the data format for
; initial features of a ZCPR2 system which are required for proper
; initialization of the ZCPR2-Specific Routines in SYSLIB.
;

;
;  EXTERNAL PATH DATA
;
EPAVAIL:
       DB      0FFH    ; IS EXTERNAL PATH AVAILABLE? (0=NO, 0FFH=YES)
EPADR:
       DW      40H     ; ADDRESS OF EXTERNAL PATH IF AVAILABLE

;
;  INTERNAL PATH DATA
;
INTPATH:
       DB      0,0     ; DISK, USER FOR FIRST PATH ELEMENT
                       ; DISK = 1 FOR A, '$' FOR CURRENT
                       ; USER = NUMBER, '$' FOR CURRENT
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0
       DB      0,0     ; DISK, USER FOR 8TH PATH ELEMENT
       DB      0       ; END OF PATH

;
;  MULTIPLE COMMAND LINE BUFFER DATA
;
MCAVAIL:
       DB      0FFH    ; IS MULTIPLE COMMAND LINE BUFFER AVAILABLE?
MCADR:
       DW      0FF00H  ; ADDRESS OF MULTIPLE COMMAND LINE BUFFER IF AVAILABLE

;
;  DISK/USER LIMITS
;
MDISK:
       DB      4       ; MAXIMUM NUMBER OF DISKS
MUSER:
       DB      31      ; MAXIMUM USER NUMBER

;
;  FLAGS TO PERMIT LOG IN FOR DIFFERENT USER AREA OR DISK
;
DOK:
       DB      0FFH    ; ALLOW DISK CHANGE? (0=NO, 0FFH=YES)
UOK:
       DB      0FFH    ; ALLOW USER CHANGE? (0=NO, 0FFH=YES)

;
;  PRIVILEGED USER DATA
;
PUSER:
       DB      10      ; BEGINNING OF PRIVILEGED USER AREAS
PPASS:
       DB      'chdir',0       ; PASSWORD FOR MOVING INTO PRIV USER AREAS
       DS      41-($-PPASS)    ; 40 CHARS MAX IN BUFFER + 1 for ending NULL

;
;  CURRENT USER/DISK INDICATOR
;
CINDIC:
       DB      '$'     ; USUAL VALUE (FOR PATH EXPRESSIONS)

;
;  DMA ADDRESS FOR DISK TRANSFERS
;
DMADR:
       DW      80H     ; TBUFF AREA

;
;  NAMED DIRECTORY INFORMATION
;
NDRADR:
       DW      00000H  ; ADDRESS OF MEMORY-RESIDENT NAMED DIRECTORY
NDNAMES:
       DB      64      ; MAX NUMBER OF DIRECTORY NAMES
DNFILE:
       DB      'NAMES   '      ; NAME OF DISK NAME FILE
       DB      'DIR'           ; TYPE OF DISK NAME FILE

;
;  REQUIREMENTS FLAGS
;
EPREQD:
       DB      0FFH    ; EXTERNAL PATH?
MCREQD:
       DB      000H    ; MULTIPLE COMMAND LINE?
MXREQD:
       DB      000H    ; MAX USER/DISK?
UDREQD:
       DB      000H    ; ALLOW USER/DISK CHANGE?
PUREQD:
       DB      000H    ; PRIVILEGED USER?
CDREQD:
       DB      0FFH    ; CURRENT INDIC AND DMA?
NDREQD:
       DB      000H    ; NAMED DIRECTORIES?
Z2CLASS:
       DB      1       ; CLASS 1
       DB      'ZCPR2'
       DS      10      ; RESERVED

;
;  END OF SINSFORM -- STANDARD DEFAULT PARAMETER DATA
;
;******************************************************************
;
IOBADR:
       DW      0       ;Base Address of I/O System

;
;  Start of Program
;
START:
       CALL    ZGPINS          ;INIT BUFFERS
       CALL    PRINT           ;PRINT BANNER
       DB      'IOLOADER, Version ',VERS/10+'0','.',(VERS MOD 10)+'0',0
       LHLD    IOBADR          ;BASE OF IO SYSTEM INITIALIZED?
       MOV     A,H
       ORA     L
       JNZ     IOL1
       CALL    PRINT
       DB      CR,LF,'I/O Base Address Not Initialized -- Aborting',0
       RET

;  DETERMINE FILE NAME
IOL1:
       LXI     H,TBUFF         ;PT TO TBUFF
       CALL    CLINE           ;EXTRACT LINE AS STRING
       CALL    SBLANK          ;SKIP TO NON-BLANK
       CPI     '/'             ;HELP?
       JNZ     IOL2            ;CONTINUE IF NOT
       CALL    PRINT           ;PRINT HELP MESSAGE
       DB      CR,LF,' IOLOADER is used to load the Redirectable I/O'
       DB      CR,LF,'Drivers for CHBIOSZ.  It is invoked by one of the'
       DB      CR,LF,'following forms --'
       DB      CR,LF,'    IOLOADER             <-- Loads SYSIO.IO'
       DB      CR,LF,'    IOLOADER //          <-- Print HELP Msg'
       DB      CR,LF,'    IOLOADER file        <-- Loads file.IO'
       DB      CR,LF,'    IOLOADER file.typ    <-- Loads file.typ'
       DB      CR,LF,0
       RET

;  DETERMINE FILE NAME AND FIND FILE
IOL2:
       LXI     D,DEFCB ;PT TO DEFAULT FCB
       ORA     A       ;USE DEFAULT NAME?
       JZ      IOL2A
       LXI     D,FCB   ;PT TO FCB
       PUSH    D       ;SAVE PTR
       CALL    ZFNAME  ;EXTRACT NAME DATA
       LXI     D,FCBTYP        ;ANY TYPE SPECIFIED?
       LXI     H,IOTYP ;PREP TO SET UP I/O TYPE
       MVI     B,3     ;3 BYTES
       LDAX    D       ;GET TYPE SPECIFIED
       CPI     ' '     ;ANY?
       CZ      MOVEB   ;COPY IF NOT
       POP     D       ;DE PTS TO FCB OF FILE TO LOOK FOR
IOL2A:
       MVI     B,0FFH  ;SEARCH CURRENT USER/DISK FIRST
       CALL    ZPFIND  ;SEARCH FOR FILE
       JNZ     IOL3    ;LOAD FILE
       CALL    PRINT
       DB      CR,LF,'I/O Driver NOT Found',0
       RET

;  LOAD FILE
IOL3:
       CALL    LOGUD           ;LOG INTO DIRECTORY
       CALL    INITFCB         ;INIT FCB
       CALL    F$OPEN          ;OPEN FILE FOR INPUT
       PUSH    D               ;SAVE FCB PTR
       LHLD    IOBADR          ;GET ADDRESS OF I/O BASE
       LXI     D,-128          ;BACK UP 1 BLOCK
       DAD     D
       POP     D               ;GET FCB PTR
       SHLD    DMAADR          ;SAVE IN BUFFER FOR NOW

;  FILE LOADING LOOP
IOL4:
       PUSH    D               ;SAVE FCB PTR
       LHLD    DMAADR          ;GET ADDRESS OF LAST BLOCK LOADED
       LXI     D,128           ;PT TO NEXT BLOCK TO LOAD
       DAD     D
       SHLD    DMAADR          ;SAVE ADDRESS OF CURRENT BLOCK LOADING
       XCHG                    ;DE PTS TO ADDRESS
       MVI     C,26            ;SET DMA ADDRESS
       CALL    BDOS
       POP     D               ;GET FCB PTR
       CALL    F$READ          ;READ NEXT BLOCK
       ORA     A               ;0=CONTINUE
       JZ      IOL4

;  CLOSE FILE
       CALL    F$CLOSE

;  RUN THE TERMINAL INIT ROUTINE
       CALL    TINIT   ;RUN THE INIT ROUTINE

;  PRINT FINAL MESSAGE AND EXIT
       CALL    PRINT
       DB      CR,LF,'Load Complete',0
       RET

;
;  TERMINAL INIT ROUTINE FROM I/O DRIVERS
;
TINIT:
       LHLD    IOBADR          ;GET ADDRESS OF I/O BASE
       LXI     D,9             ;ADD 9 FOR TINIT OFFSET
       DAD     D
       PCHL

;  SKIP TO NON-BLANK
SBLANK:
       MOV     A,M     ;GET CHAR
       INX     H       ;PT TO NEXT
       CPI     ' '     ;BLANK?
       JZ      SBLANK
       DCX     H       ;PT TO NON-BLANK
       RET

;  BUFFERS
       DS      60      ;30-ELT STACK
STACK:  DS      2       ;OLD STACK PTR

FCBPTR: DS      2       ;POINTER TO FCB FOR FILE SEARCH

DMAADR: DS      2       ;ADDRESS OF NEXT BLOCK TO LOAD

TMPUSR: DS      1       ;CURRENT USER NUMBER

FCB:
       DS      9
FCBTYP:
       DS      3
       DS      24

DEFCB:
       DB      0       ;CURRENT DISK
       DB      'SYSIO   '
IOTYP:
       DB      'IO '
       DB      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

       END