;
;  PROGRAM:  DEVICE2
;  AUTHOR:  RICHARD CONN
;  VERSION:  1.3
;  DATE:  6 Jan 83
;  PREVIOUS VERSION:  1.0 (29 Dec 82), 1.1 (2 Jan 83), 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.
;


;
;       DEVICE is a program which enables the user to manipulate the
; extended ZCPR2 redirectable device drivers.  It allows the user to
; perform the following functions:
;
;               o Display the Names of the Current Devices
;               o Set One or More of the Current Devices
;               o Ask for Help
;
;       The format of the DEVICE command is:
;
;               DEVICE or DEVICE //             <-- Ask for Help
;               DEVICE command,command,command ...      <-- Issue Commands
;
; where "command" may take the following forms:
;
;               DISPLAY ALL     <-- Display Names of All Devices
;               DISPLAY CON     <-- Display Names of Consoles
;               DISPLAY LST     <-- Display Names of Printers
;               DISPLAY RDR     <-- Display Names of Readers
;               DISPLAY PUN     <-- Display Names of Punches
;
;               CON:=name       <-- Select Console
;               LST:=name       <-- Select Printer
;               RDR:=name       <-- Select Reader
;               PUN:=name       <-- Select Punch
;

;
;  Constants
;
tbuff   equ     80h
cr      equ     0dh
lf      equ     0ah

;
;  SYSLIB Routines
;
       ext     cin,cout,pstr,print,cline,bbline

;
;  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      000H    ; 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      000H    ; 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
;
;******************************************************************
;

;
;  Other Parameter Data
;
drvadr:
       dw      0       ; Address of I/O Drivers

;
;  Start of Program
;
start:
       call    print
       db      'DEVICE2, Version '
       db      (vers/10)+'0','.',(vers mod 10)+'0',0

       lhld    drvadr  ;check for initialization
       mov     a,h
       ora     l       ;must NOT be zero
       jnz     start0
       call    print
       db      cr,lf,'DEVICE NOT Initialized with I/O Base -- Aborting',0
       ret

start0:
       call    status  ;check for drivers
       jnz     start1
       call    print
       db      cr,lf,'Redirection Not Supported -- Aborting',0
       ret

start1:
       lxi     h,tbuff ;pt to input buffer
       call    cline   ;extract and save command line
       call    sblank  ;skip to non-blank
       ora     a       ;EOL?
       jz      command ;command mode
       cpi     '/'     ;help?
       jnz     docmd   ;run command subroutine

;
;  Print Help Message
;
help:
       call    print
       db      cr,lf,' DEVICE is a program which enables the user to'
       db      cr,lf,'manipulate the extended ZCPR2 redirectable device'
       db      cr,lf,'drivers.  It allows the user to perform the following'
       db      cr,lf,'functions:'
       db      cr,lf,'         Display the Names of the Current Devices'
       db      cr,lf,'         Set One or More of the Current Devices'
       db      cr,lf,' The format of the DEVICE command is:'
       db      cr,lf,'         DEVICE                          '
       db      '<-- Enter Interactive Mode'
       db      cr,lf,'         DEVICE //                       '
       db      '<-- Ask for Help'
       db      cr,lf,'         DEVICE '
help1:
       db      'Command,Command, ...   '
       db      '<-- Issue Commands'
       db      cr,lf,'where "command" may take the following forms:'
       db      cr,lf,'         DISPLAY=ALL     '
       db      '<-- Display Names of All Devices'
       db      cr,lf,'         DISPLAY=CON     '
       db      '<-- Display Names of Consoles'
       db      cr,lf,'         DISPLAY=LST     '
       db      '<-- Display Names of Printers'
       db      cr,lf,'         DISPLAY=RDR     '
       db      '<-- Display Names of Readers'
       db      cr,lf,'         DISPLAY=PUN     '
       db      '<-- Display Names of Punches'
       db      cr,lf
       db      cr,lf,'         CON:=name       <-- Select Console'
       db      cr,lf,'         LST:=name       <-- Select Printer'
       db      cr,lf,'         RDR:=name       <-- Select Reader'
       db      cr,lf,'         PUN:=name       <-- Select Punch'
       db      cr,lf,0
       ret
;
;  Skip to Non-Blank Routine
;
sblank:
       mov     a,m     ;get char
       inx     h       ;pt to next
       cpi     ' '     ;blank?
       jz      sblank  ;continue if so
       dcx     h       ;pt to non-blank
       ret

;
;  Skip until a delimiter encountered
;
sdelm:
       mov     a,m     ;get char
       inx     h       ;pt to next
       cpi     ' '+1   ;<SP> or less?
       rc
       cpi     '='
       rz
       cpi     ','
       rz
       cpi     ';'
       rz
       jmp     sdelm

;
;  COMMAND -- This is an interactive mainline which allows user input,
;    runs command lines via DOCMD, and permits Help and Comments
;
command:
       call    print
       db      cr,lf,'DEVICE2 Interactive Command System'
       db      cr,lf,'Type ? and Strike RETURN for Help'
       db      0
cloop:
       call    print
       db      cr,lf,'DEVICE2 Command? ',0
       mvi     a,0ffh  ;capitalize
       call    bbline
       call    sblank  ;skip to non-blank
       mov     a,m     ;empty line?
       ora     a       ;0=yes
       jz      cloop
       cpi     '?'     ;help?
       jz      chelp
       cpi     ';'     ;comment?
       jz      cloop
       cpi     'X'     ;done?
       rz
       call    docmd   ;run command line
       jmp     cloop
chelp:
       call    print
       db      cr,lf,'DEVICE2 Commands are of the form:',cr,lf,0
       lxi     h,help1
       call    pstr
       call    print
       db      cr,lf,'A command line beginning with a semicolon (;) is a'
       db      ' comment.'
       db      cr,lf,'The X Command Exits DEVICE2.'
       db      cr,lf,0
       jmp     cloop

;
;  DOCMD -- This subroutine processes the command line pted to by HL.
;    It is the Main Line if a DEVICE command line is given, it is just
;    a subroutine if the user is in interactive mode.
;
docmd:
       call    docmd1  ;do first command
       call    sdelm   ;skip to delim
       cpi     ','     ;another command?
       jz      docmd
       cpi     ';'     ;another also?
       jz      docmd
       ret
docmd1:
       mov     a,m     ;get command letter
       cpi     'C'     ;console assignment?
       jz      docon
       cpi     'D'     ;display?
       jz      dodisp
       cpi     'L'     ;LST:?
       jz      dolst
       cpi     'P'     ;PUN:?
       jz      dopun
       cpi     'R'     ;RDR:?
       jz      dordr
cerr:
       call    print
       db      cr,lf,'Command Error at -- ',0
       call    pstr    ;print rest
       ret

;
;  Do LST: Assignment
;
dolst:
       mvi     a,3     ;select LST:
       jmp     assign

;
;  Do PUN: Assignment
;
dopun:
       mvi     a,2     ;select PUN:
       jmp     assign

;
;  Do RDR: Assignment
;
dordr:
       mvi     a,1     ;select RDR:
       jmp     assign

;
;  Do CON: Assignment
;
docon:
       mvi     a,0     ;select console
;
;  Do Assignment in General
;
assign:
       mov     b,a     ;save A in B
       push    b       ;save BC
       call    sdelm   ;skip to delimiter
       pop     b       ;get BC
       cpi     ' '
       jz      asgn0
       cpi     '='
       jnz     cerr
asgn0:
       mov     a,b     ;get A back
       sta     logical ;save logical device number
       shld    name    ;save ptr to mnemonic
       mov     b,a     ;number in B
       inr     b       ;add 1 for offset
       call    status  ;get device status
       dcx     h       ;pt to previous
       dcx     h
asgn1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     asgn1
       mov     c,m     ;get number of devices in C
       mov     a,c     ;check for value of zero
       ora     a
       jnz     asgn2
       lhld    name    ;pt to error name
       jmp     cerr
asgn2:
       lda     logical ;get logical device number
       mov     b,a     ;... in B
       push    b       ;save device count
       dcr     c       ;pt to previous
       call    namer   ;get name
       xchg            ;name pted to by DE
       lhld    name    ;user's name pted to by HL
asgn3:
       ldax    d       ;get name of device
       cpi     ' '+1   ;done?
       jc      asgn3a
       cmp     m       ;compare to user
       jnz     asgn4
       inx     h       ;pt to next
       inx     d
       jmp     asgn3
asgn3a:
       mov     a,m     ;get user
       cpi     ' '+1   ;done?
       jc      asgn3b
       cpi     ','     ;done?
       jnz     asgn4
asgn3b:
       pop     b       ;match -- C-1 is selected device
       dcr     c       ;decrement
       call    select  ;select device
       lhld    name    ;pt to name for scan continuation
       ret
asgn4:
       pop     b       ;count down
       dcr     c       ;count down
       jnz     asgn2   ;continue
       lhld    name    ;pt to invalid name
       call    print
       db      cr,lf,'Invalid Name Assignment at -- ',0
       call    pstr
       lhld    name    ;pt to name for scan continuation
       ret

;
;  Display Devices and Assignments
;
dodisp:
       call    sdelm   ;skip to delimiter
       ora     a       ;none=all
       jz      dispall
       mov     a,m     ;get char after delimiter
       cpi     'A'     ;all?
       jz      dispall
       cpi     'C'     ;CON:
       jz      dispcon
       cpi     'L'     ;LST:
       jz      displst
       cpi     'P'     ;PUN:
       jz      disppun
       cpi     'R'     ;RDR:
       jz      disprdr
       jmp     cerr
dispall:
       call    dispcon ;successive displays
       call    disprdr
       call    print
       db      cr,lf,'Strike Any Key to Continue -- ',0
       call    cin
       call    disppun
       jmp     displst
dispcon:
       call    print
       db      cr,lf,cr,lf,'CON: Devices --',0
       mvi     a,0     ;select CON:
       call    disp
       jmp     current
displst:
       call    print
       db      cr,lf,cr,lf,'LST: Devices --',0
       mvi     a,3     ;select LST:
       call    disp
       jmp     current
disprdr:
       call    print
       db      cr,lf,cr,lf,'RDR: Devices --',0
       mvi     a,1     ;select RDR:
       call    disp
       jmp     current
disppun:
       call    print
       db      cr,lf,cr,lf,'PUN: Devices --',0
       mvi     a,2     ;select PUN:
       call    disp
;
;  Print Name of Current Device
;
current:
       push    h       ;save ptr
       mov     b,a     ;save number in B
       push    b       ;save B
       call    print
       db      cr,lf,'  Current Assignment: ',0
       push    b       ;save B
       call    status  ;get status
       pop     b       ;get B
       inr     b       ;add 1 for offset
       dcx     h       ;back up
curr:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     curr
       pop     b       ;get logical number in B
       mov     c,m     ;get physical number in C
       call    pname0  ;print first part of name only
       pop     h       ;get ptr
       ret
;
;  Print Names of All Physical Devices for a Logical Device
;
disp:
       push    h       ;save char ptr
       push    psw     ;save device number
       mov     b,a     ;logical device in B
       push    b       ;save for later
       push    b       ;save it
       call    status  ;get status report
       pop     b       ;get logical device number
       inr     b       ;add 1 for offset
       dcx     h       ;back up
       dcx     h
disp1:
       inx     h       ;pt to next
       inx     h
       dcr     b       ;count down
       jnz     disp1
       pop     b       ;get B back
       mov     c,m     ;get count of devices
disp2:
       push    b       ;save values
       dcr     c       ;pt to next name
       call    print
       db      cr,lf,' ',0
       call    pnamer  ;print name (B=logical, C=physical)
       pop     b       ;get count
       dcr     c       ;count down
       jnz     disp2
       pop     psw
       pop     h
       ret
;
;  Routine to Print Name of Selected Device
;       B=logical number, C=physical number
;
pnamer:
       push    b       ;save BC
       call    pname0  ;print first part of name
       call    print   ;print separator
       db      ' - ',0
       call    pstr    ;print rest as string
       pop     b       ;restore BC
       ret
;
;  Print first part of selected device name
;
pname0:
       call    namer   ;get ptr to string
       mvi     b,8     ;at most 8 chars
pname1:
       mov     a,m     ;get char
       inx     h       ;pt to next char
       cpi     ' '     ;end of name?
       jz      pname2
       call    cout    ;print char
       dcr     b       ;count down
       jnz     pname1
       ret
pname2:
       mvi     a,' '   ;print spaces
       call    cout
       dcr     b       ;count down
       jnz     pname2
       ret

;
;  Basic Interface Routines
;
status:
       lxi     d,0     ;Offset 0
runit:
       lhld    drvadr  ;device driver base
       dad     d
       pchl
select:
       lxi     d,3     ;Offset 3
       jmp     runit
namer:
       lxi     d,6     ;Offset 6
       jmp     runit

;
;  Buffers
;
logical:
       ds      1       ;Logical Device Number
name:
       ds      2       ;Pointer to User-Supplied Name

       end