home *** CD-ROM | disk | FTP | other *** search
- TITLE 'SETIO SETS THE CP/M IOBYTE'
-
- ; This program is intended to replace the IOBYTE set/view
- ; functions found in the standard CP/M program STAT. With the
- ; advent of multitudinous directory programs which provide
- ; size and attribute information, the use of the STAT program
- ; has been reduced to altering IOBYTEs and changing $SYS and $RO
- ; attributes. This program and its accompanying "SETATTR" program
- ; announce the death knell of the STAT program.
- ;
- ; WRITTEN BY: Thomas N. Hill
- ; Alaska Micro Systems
- ; 200 Oklahoma St.
- ; Anchorage, Alaska 99504
- ; (907) 337-1984 (9 AM - 5 PM, AST)
- ;
- ;Modification and Update List:
- ;
- ; 06/20/82 Version 1.0 (TNH)
- ;
- ; system equates
-
- ; SYSTEM EQUATES
-
- CPM EQU 0
- BDOS EQU CPM+5H ; bdos entry point
- FCB1 EQU CPM+5CH ; first File Control Block
- FCB2 EQU CPM+6CH ; second FCB
- CBUF EQU CPM+80H ; command buffer
- TPA EQU CPM+0100H
-
- ; NON-DISK I/O FUNCTIONS
-
- CONIN EQU 1 ; CONSOLE INPUT
- CONOUT EQU 2 ; CONSOLE OUTPUT
- LSTOUT EQU 5 ; LIST DEVICE OUTPUT
- PRTBUF EQU 9 ; SEND A STRING TO THE CONSOLE
- RDBUF EQU 10 ; GET A STRING FROM THE CONSOLE
- CONSTAT EQU 11 ; CONSOLE STATUS
- GETIOB EQU 7 ; get iobyte
- SETIOB EQU 8 ; set iobyte
- VERS EQU 12 ; RETURN CP/M (MP/M) VERSION NUMBER
-
- ; DISK I/O FUNCTIONS
-
- SELDSK EQU 14 ; SELECT DISK
- OPENF EQU 15 ; OPEN FILE
- CLOSEF EQU 16 ; CLOSE A FILE
- DELETF EQU 19 ; DELETE A FILE
- RENAME EQU 23 ; rename a file
- READF EQU 20 ; READ A RECORD
- WRITEF EQU 21 ; WRITE A RECORD
- MAKEF EQU 22 ; CREATE A FILE
- SETDMA EQU 26 ; SET DISK DMA ADDRESS
- SIZEF EQU 35 ; COMPUTE FILE SIZE
-
- ; THOSE FUNCTIONS REQUIRING A BYTE ARGUMENT WILL EXPECT THAT BYTE
- ; TO BE IN THE E REGISTER. ADDRESS ARGUMENTS ARE PASSED IN THE
- ; DE REGISTER. RETURN CODES ARE PASSED IN THE ACC. IN GENERAL,
- ; A RETURN OF ZERO INDICATES SUCCESS, WHILE A OFFH INDICATES FAILURE.
-
- ; character equates
-
- CR EQU 0DH ; carriage return
- LF EQU 0AH ; line feed
- ESC EQU 1BH ; escape code
- EOF EQU 1AH ; end-of-file, control-z
- BELL EQU 07H ; terminal bell
- BS EQU 08H ; backspace
- TAB EQU 09H ; tab char
- ;
- FALSE EQU 00H
- TRUE EQU 0FFH
- ;
-
-
- ORG TPA
-
- ; main program loop
-
- SETIO: CALL INIT ; initialize things
- MAIN: CALL COMMAND ; get the input command
- JNZ PCERR ; print command error
- CALL EXECUTE ; execute the command
- LDA CFLAG ; was command from CP/M input buffer?
- ORA A
- JNZ FINPROG ; yes, return to CP/M
- JMP MAIN ; no, do it again.
-
- PCERR: LXI D,CERMSG
- CALL PSTRING
- LXI D,MENU
- CALL PSTRING
- JMP MAIN
-
- ; subroutines begin here.
-
- ; here is the command interpreter
- ; it examines the contents of the buffer at 80H and if there is
- ; a command string fromthe CP/M command line, it returns to the
- ; main program for execution, else it requests the command from
- ; the user.
-
- COMMAND:
- LDA CFLAG ; was a command on the input line?
- ORA A
- JZ COMM0 ; nope.
- LXI H,CBUF
- LXI D,CBUF+1 ; must absorb extra space on line
- MOV B,A ; convert to upper case
- LP1: INX H
- INX D
- LDAX D
- CALL UCASE
- MOV M,A
- DCR B
- JNZ LP1
- LDA CBUF ; adjust count
- DCR A
- STA CBUF ; for lost space
- JMP COMM1
-
- ; no command on input, must get one.
-
- COMM0: LXI D,PROMPT
- CALL PSTRING
- LXI D,IBUF ; use internal command buffer
- MVI C,RDBUF
- CALL BDOS ; get the command
- CALL CRLF
- LXI H,IBUF+1 ; prepare to move command string
- MOV A,M ; command length
- ORA A ; any thing there?
- JZ FINPROG ; finish program
- COMM2: LXI D,CBUF
- INR A
- MOV B,A ; put length + 1 in B and use for move count
- COMM3: MOV A,M
- CALL UCASE ; CONVERT TO UPPERCASE
- STAX D
- INX H
- INX D
- DCR B
- JNZ COMM3
- XRA A
- STAX D ; mark line end
-
- ; have a command, figure out what it is.
-
- COMM1: LXI H,CBUF
- MOV B,M ; get the length for use
- INX H
- LXI D,CTABLE ; point to command table
- LOOK: PUSH H ; save command pointer
- LOOK0: LDAX D
- ORA A ; zero byte from table?
- JZ FOUND
- CPI TRUE ; else is end?
- JZ COMERR ; command error
- CMP M
- JNZ NEXTCOM ; can't be this one, go to next
- INX H
- INX D
- JMP LOOK0 ; else check next char
- NEXTCOM:
- INX D
- LDAX D
- ORA A ; advance to next command in table
- JNZ NEXTCOM
- INX D ; first byte of command address
- INX D ; second byte
- INX D ; first of next command
- POP H ; re-point to command buffer start
- JMP LOOK ; try next command
- FOUND: SHLD CPTR ; save current loc. in command string
- POP H ; clean stack
- RET
-
- COMERR: POP H ; clean off stack
- XRA A
- STA CBUF ; set command length to zero
- STA CFLAG
- INR A ; reset zero flag
- RET
-
- ; here is the EXECUTE routine. It recovers the command address
- ; fromthe command table and branches to it, placing a return
- ; address on the stack first.
-
- EXECUTE:
- INX D ; past end-of-command byte
- XCHG
- MOV E,M
- INX H
- MOV D,M ; command address to DE
- LXI H,FINEXC ; proper return address
- PUSH H
- XCHG
- PCHL ; do the command
- FINEXC: RET
-
- FINPROG:LDA ALTFLAG ; did we change a definition?
- ORA A
- JZ CPM
-
- ; if a definition has been changed, then we have to re-write
- ; the program to disk in order to save the altered names.
-
- LXI D,SAVEMSG
- CALL PSTRING ; check a bout saving new definitions
- MVI C,CONIN
- CALL BDOS
- PUSH PSW
- CALL CRLF
- POP PSW
- ANI 5FH ; upper case
- CPI 'Y'
- JZ FIN1 ; yes, save it.
- CPI 'N'
- JZ CPM ; nope, ignore changes
- JMP MAIN ; else continue with program
- FIN1: LXI D,PFCB
- MVI C,MAKEF
- CALL BDOS
- INR A
- JZ PRERR
- LXI D,PFCB
- MVI C,OPENF ; open the output file
- CALL BDOS
- INR A
- JZ PRERR ; disk error, cannot save new names
- LXI H,SETIO
- LXI B,(IBUF-SETIO)/128 ; sectors to save
- INX B ; plus one (safety sake)
- SAVE1: PUSH B
- PUSH H
- XCHG
- MVI C,SETDMA
- CALL BDOS
- LXI D,PFCB
- MVI C,WRITEF ; write a sector
- CALL BDOS
- CPI 0 ; error?
- JNZ PRERR
- POP H
- LXI D,80H
- DAD D
- POP B
- DCR C
- JNZ SAVE1 ; do some more
- LXI D,PFCB
- MVI C,CLOSEF
- CALL BDOS ; close it
- INR A
- JZ PRERR
- LXI D,OLDFCB
- MVI C,DELETF ; erase old file name
- CALL BDOS
- LXI D,RENFCB
- MVI C,RENAME
- CALL BDOS ; rename the new file
- JMP CPM ; finished
-
- PRERR: ORA A
- JZ PRERR1
- LXI D,DSKERR0
- CALL PSTRING
- JMP CPM
- PRERR1: LXI D,DSKERR1
- CALL PSTRING
- JMP CPM
-
-
-
-
-
-
- ; here are the various command routines.
-
- ; this command displays the current IOBYTE device assignments.
- ; the intial program uses the standard CP/M device names, but
- ; the user has the option of using his own names, thru the
- ; "DEFINE" command.
-
- WHERE: MVI C,GETIOB
- CALL BDOS ; current IOBYTE setting
- STA IOBYTE ; save it
- LXI D,CONSOLE ; tell about console field
- CALL PSTRING
- LDA IOBYTE
- MVI B,03H ; console field mask
- LXI H,CNAMES ; console names
- CALL FIELD ; find the proper name string
- CALL PSTRING ; print the name
- CALL CRLF
- LXI D,READER
- CALL PSTRING
- LDA IOBYTE
- MVI B,0CH ; reader field mask
- LXI H,RNAMES ; reader names
- CALL FIELD
- CALL PSTRING
- CALL CRLF
- LXI D,PUNCH
- CALL PSTRING
- LDA IOBYTE ; same for punch
- MVI B,30H
- LXI H,PNAMES ; punch names
- CALL FIELD
- CALL PSTRING
- CALL CRLF
- LXI D,LIST
- CALL PSTRING
- LDA IOBYTE ; and the list field
- MVI B,0C0H
- LXI H,LNAMES
- CALL FIELD
- CALL PSTRING
- CALL CRLF
- RET ; return to MAIN
-
- ; this routine displays the possible logical to physical device
- ; assignments.
-
- WHAT: LXI D,CONMSG1
- CALL PSTRING ; console first
- LXI H,CNAMES
- MVI B,4 ; four total devices
- CALL DEVPRNT ; print the device list
- LXI D,RDRMSG1
- CALL PSTRING
- LXI H,RNAMES
- MVI B,4 ; and the reader list
- CALL DEVPRNT
- LXI D,PNCMSG1
- CALL PSTRING
- LXI H,PNAMES
- MVI B,4
- CALL DEVPRNT ; ... and the punch list
- LXI D,LSTMSG1
- CALL PSTRING
- LXI H,LNAMES
- DEVPRNT:LXI B,0431H
- DVPT0: PUSH B
- DVPT1: MOV E,M
- INX H
- MOV D,M ; pick up string address
- INX H
- PUSH H ; save pointer
- PUSH D
- MOV E,C
- MVI C,CONOUT
- CALL BDOS
- MVI E,' '
- MVI C,CONOUT
- CALL BDOS
- POP D
- CALL PSTRING ; print the console assignment
- CALL CRLF
- POP H
- POP B
- INR C
- DCR B ; done yet?
- JNZ DVPT0
- RET
-
- ; here is the DEFINE routine. IT allows the user to define
- ; his own names for each of the physical devices. A limit of
- ; 24 chars is set on the length of the input string.
-
- DEFINE: LXI D,DEFWHAT
- CALL PSTRING ; ask which logiacl device to change
- MVI C,CONIN
- CALL BDOS ; accept a numeric entry, 1 - 4.
- PUSH PSW
- CALL CRLF
- POP PSW
- CALL NUMCHK ; check for valid digit
- JZ DEFINE ; not right, try again.
- CALL DEFGET
- PUSH D
- LXI D,CURMSG
- CALL PSTRING ; "currently is:"
- POP D
- MVI B,4
- LXI H,CNAMES ; point to start of address table
- DAD D ; now pointing to logical device list
- DEFG: MOV E,M
- INX H ; get address of current phy. device name
- MOV D,M
- INX H
- PUSH B
- PUSH H ; save pointer
- PUSH D ; save string address again
- CALL PSTRING ; "..."
- DEFG0: LXI D,CHANGE
- CALL PSTRING ; "change to->"
- LXI D,IBUF
- MVI C,RDBUF
- CALL BDOS
- CALL CRLF ; get new name
- LDA IBUF+1 ; check string length
- ORA A
- JZ DEFG4
- CPI 24 ; to big?
- JC DEFG1 ; nope, so OK.
- LXI D,TOOBIG
- CALL PSTRING
- CALL CRLF
- JMP DEFG0
- DEFG1: LXI H,IBUF+2 ; move string to proper place
- POP D ; string address
- MOV B,A ; bytes to move
- ORA A ; if length is zero, then null assignment
- JZ DEFG3 ; mark as null string
- DEFG2: MOV A,M
- STAX D
- INX H
- INX D
- DCR B
- JNZ DEFG2 ; move the string
- DEFG3: MVI A,'$'
- STAX D ; mark the end
- PUSH D
- DEFG4: POP D
- POP H ; recover string address table pointer
- POP B ; and device count
- DCR B
- JNZ DEFG ; do another one
- MVI A,TRUE
- STA ALTFLAG ; tell program definitions were altered
- RET
-
- NUMCHK: CPI '1'
- JC BADNUM
- CPI '5'
- JNC BADNUM
- ORA A ; reset zero
- RET
- BADNUM: XRA A ; set zero
- RET
-
- ; here is the set routine. It will display the currently stored
- ; selections for the logical device selected and alter the IOBYTE
- ; to reflect the users choice.
-
- SETIBYTE:
- LXI D,DEFWHAT
- CALL PSTRING
- MVI C,CONIN
- CALL BDOS
- PUSH PSW
- CALL CRLF
- POP PSW
- CALL NUMCHK
- JNZ SETI0
- JMP SETIBYTE ; invalid selection, try again
- SETI0: STA LDEVNUM ; save the logical device number
- CALL DEFGET ; get the proper logical device printed
- LXI H,CNAMES
- DAD D ; point to phys. device add. table
- PUSH H ; save it
- LXI D,CURMSG
- CALL PSTRING
- POP H
- MVI B,4
- CALL DEVPRNT ; print device names
- CALL CRLF
- SETI1: LXI D,SELASK ; ask about selection
- CALL PSTRING
- MVI C,CONIN
- CALL BDOS ; get an answer
- PUSH PSW
- CALL CRLF
- POP PSW
- CALL NUMCHK
- JZ SETI1
- PUSH PSW
- MVI C,GETIOB
- CALL BDOS ; get current io byte
- MOV C,A
- POP PSW
- SUI '0'
- DCR A
- MOV B,A ; phys. device number
- LDA LDEVNUM ; recover logical device
- SUI '0'
- DCR A ; convert to pure binary
- CPI 0
- JZ SETICON ; set console
- CPI 1
- JZ SETIRDR ; set reader
- CPI 2
- JZ SETIPUN ; set punch
- SETILST:
- STC
- CMC ; clear carry
- MOV A,B ; phys. device
- RAR
- RAR ; rotate list device into place
- RAR ; one more to pass carry
- MOV B,A
- MOV A,C ; recover IOBYTE
- ANI 03FH ; remove old list assignments
- ORA B ; combine with new
- JMP SETI3
- SETICON:
- MOV A,C ; recover IOBYTE
- ANI 0FCH ; remove the old console
- ORA B ; combine with the new
- JMP SETI3
- SETIRDR:
- STC
- CMC ; clear carry
- MOV A,B ; phys. device
- RAL
- RAL ; rotate to reader position
- MOV B,A
- MOV A,C
- ANI 0F3H ; remove old reader
- ORA B ; combine with new
- JMP SETI3
- SETIPUN:
- STC
- CMC ; clear carry
- MOV A,B ; phys. device
- RAL
- RAL
- RAL
- RAL ; postion at punch field
- MOV B,A
- MOV A,C
- ANI 0CFH ; out with the old,....
- ORA B ; in with the new.
- SETI3: MOV E,A
- MVI C,SETIOB
- CALL BDOS ; set new IOBYTE
- RET
-
-
- DEFGET: SUI '0' ; make to binary
- DCR A ; adjust for range
- RAL ; times 2
- PUSH PSW
- MOV E,A ; first, find proper logical device name
- MVI D,0
- LXI H,LOGDEV
- DAD D
- MOV E,M
- INX H
- MOV D,M
- CALL PSTRING ; and print it
- POP PSW
- RAL
- RAL ; final count times 8
- MOV E,A
- MVI D,0
- RET
-
- FIELD: STC
- CMC ; clear the carry flag
- MOV C,A ; save iobyte
- MOV A,B ; get mask
- MVI E,0 ; clear counter for rotates
- FIELD1: RAR ; rotate until carry is set,
- INR E
- JNC FIELD1
- DCR E ; then back up one rotate
- RAL
-
- ; field mask no aligned on bits 0 & 1, and E = count of rotates
-
- MOV B,A ; put mask back
- MOV A,C ; recover origianl field mask
- DCR E
- INR E ; check for already zero
- JZ FIELD3
- FIELD2: RAR
- DCR E ; rotate to count in E
- JNZ FIELD2
- FIELD3: ANA B ; now isolate bits
- ADD A ; double it
- MOV E,A
- MVI D,0
- DAD D ; fianlly find index
- MOV E,M ; get the real address
- INX H
- MOV D,M
- RET
-
-
-
- ; initialize routine. Print opening remarks and clear and/or set
- ; various counters & flags.
-
- INIT: LDA CBUF ; if a command on command line, user knows
- ORA A ; what he is doing, so don't
- JNZ INIT1 ; print things he already knows.
- LXI D,OPNMSG
- INIT0: CALL PSTRING ; print titles, etc.
- XRA A
- INIT1: STA CFLAG ; set flag for command line input.
- XRA A
- STA ALTFLAG
- CALL CRLF
- LXI H,OFCBX
- MVI B,24 ; fill FCBs with zeros
- INIT2: MVI M,0
- INX H
- DCR B
- JNZ INIT2
- LXI H,PFCBX
- MVI B,24
- INIT3: MVI M,0
- INX H
- DCR B
- JNZ INIT3
- RET
-
- UCASE: CPI 'a'
- RC
- CPI 'z'+1
- RNC
- ANI 5FH
- RET
-
-
- PSTRING:
- MVI C,PRTBUF
- JMP BDOS ; print the string pointed to by DE
-
- CRLF: LXI D,CRLFMSG
- JMP PSTRING ; print a CR,LF on the console
-
-
-
-
- ;data areas
-
- OPNMSG: DB tab,tab,'IOBYTE Control Utility, Version 1.0',cr,lf
- db tab,tab,' Written by Thomas N. Hill',cr,lf
- DB tab,tab,' June 20, 1982',cr,lf,lf,lf
- MENU: DB 'COMMAND MENU:',cr,lf,lf
- DB tab,'WHERE Displays current IOBYTE device assignments'
- DB cr,lf
- DB tab,'WHAT Displays available IOBYTE assignment options'
- DB cr,lf
- DB tab,'SET Allows the user to alter IOBYTE settings'
- DB cr,lf
- DB tab,'DEFINE Allows the user to define IOBYTE device names'
- DB cr,lf
- DB tab,'<CR> RETURN at the prompt returns user to CP/M.'
- DB cr,lf,'$'
- PROMPT: DB CR,LF,'-->$'
-
- SAVEMSG:DB 'Save new definitions to disk or return to menu (Y/N/R)?'
- CRLFMSG:DB CR,LF,'$'
- CONSOLE:DB 'Console is currently assigned to --> $'
- READER: DB 'Reader is currently assigned to ---> $'
- PUNCH: DB 'Punch is currently assigned to ----> $'
- LIST: DB 'List is currently assigned to -----> $'
- CONMSG1:DB 'CONSOLE may be assigned to the following:',cr,lf,'$'
- RDRMSG1:DB 'READER may be assigned to the following:',cr,lf,'$'
- PNCMSG1:DB 'PUNCH may be assigned to the following:',cr,lf,'$'
- LSTMSG1:DB 'LIST may be assigned to the following:',cr,lf,'$'
- DEFWHAT:DB 'Enter number of logical device:',cr,lf
- DB tab,'1. CONSOLE',cr,lf
- DB tab,'2. READER',cr,lf
- DB tab,'3. PUNCH',cr,lf
- DB tab,'4. LIST',cr,lf,lf,'$'
- CURMSG: DB ' Current assignments are:',cr,lf,'$'
- CHANGE: DB ' Change to -> ','$'
- TOOBIG: DB bell,'Name as entered is too long, make less than 24 chars.'
- DB cr,lf,'$'
- DSKERR0:DB BELL,'OPEN OR CLOSE ERROR DURING PROGRAM UPDATING.',CR,LF,'$'
- DSKERR1:DB BELL,'DISK WRITE ERROR DURING PROGRAM UPDATE.',CR,LF,'$'
- SELASK: DB 'Enter the number of the new I/O device: ','$'
- CERMSG: DB bell,'Invalid Command, please re-enter from the Menu.'
- DB cr,lf,'$'
-
- ; iobyte field names
-
- ; lookup table of string addresses
-
- CNAMES: DW CTTY,CCRT,CBAT,CUC1
- RNAMES: DW RTTY,RPTR,RUR1,RUR2
- PNAMES: DW PTTY,PPTP,PUP1,PUP2
- LNAMES: DW LTTY,LCRT,LLPT,LUL1
-
- LOGDEV: DW CONS
- DW READ
- DW PUN
- DW LST
-
- CONS: DB 'CONSOLE$'
- READ: DB 'READER$'
- PUN: DB 'PUNCH$'
- LST: DB 'LIST$'
-
- ; name strings here.
- ; since user may assign new names, allow up to 24 chars per name.
-
- ; CONSOLE field names
-
- CTTY: DB 'TTY:$'
- DS 20
- CCRT: DB 'CRT:$'
- DS 20
- CBAT: DB 'BAT:$'
- DS 20
- CUC1: DB 'UC1:$'
- DS 20
-
- ; READER field names
-
- RTTY: DB 'TTY:$'
- DS 20
- RPTR: DB 'PTR:$'
- DS 20
- RUR1: DB 'UR1:$'
- DS 20
- RUR2: DB 'UR2:$'
- DS 20
-
- ; PUNCH field names
-
- PTTY: DB 'TTY:$'
- DS 20
- PPTP: DB 'PTP:$'
- DS 20
- PUP1: DB 'UP1:$'
- DS 20
- PUP2: DB 'UP2:$'
- DS 20
-
- ; LIST field names
-
- LTTY: DB 'TTY:$'
- DS 20
- LCRT: DB 'CRT:$'
- DS 20
- LLPT: DB 'LPT:$'
- DS 20
- LUL1: DB 'UL1:$'
- DS 20
-
- ; command table and addresses
-
- CTABLE: DB 'WHERE',0
- DW WHERE
- DB 'WHAT',0
- DW WHAT
- DB 'SET',0
- DW SETIBYTE
- DB 'DEFINE',0
- DW DEFINE
- DB 0FFH
-
- ; file control blocks
-
- OLDFCB: DB 0,'SETIO COM'
- OFCBX: DW 0,0,0,0,0,0,0,0,0,0,0,0
- PFCB: DB 0,'SETIO $$$'
- PFCBX: DW 0,0,0,0,0,0,0,0,0,0,0,0
- RENFCB: DB 0,'SETIO $$$',0,0,0,0
- DB 0,'SETIO COM',0,0,0,0
-
- ; flags and address storage
-
- CFLAG: DB 0
- CPTR: DS 2
- IOBYTE: DB 0
- ALTFLAG:DB 0
- LDEVNUM:DB 0
- ; buffer(s)
-
- IBUF: DB 80H
- DS 80H
-
- END