TITL PTDOS 2.00
PAGE
ASCF 0 NO EXTENDED ASCII
IFLS . LIST THE IF'S TOO
*
*
*
*
*
*
*
*
* PTDOS v2.00
*
* FLOPPY DISK OPERATING SYSTEM
*
*
*
* COPYRIGHT 1978 BY:
*
* PROCESSOR TECHNOLOGY CORP.
* 7100 JOHNSON INDUSTRIAL DRIVE
* PLEASANTON, CALIF 94566
*
* << ALL RIGHTS RESERVED >>
*
*
* DESIGNED AND WRITTEN BY: PHILIP LEVY
*
***********************************************************
PAGE
*
*
*
* THE FOLLOWING DEFINE THE SYSTEM CONFIGURATION
*
*
*
* CONFIGURATION PARAMETERS
*
*********************
*
* SYSTEM OPERATIONS
*
CREOP EQU 0 CREATE FILE
OPEOP EQU 1 OPEN FILE
KILOP EQU 2 DELETE FILE
RBLOP EQU 3 READ BLOCK
WBLOP EQU 4 WRITE BLOCK
SPAOP EQU 5 SPACE
EOFOP EQU 6 ENDFILE
CLOOP EQU 7 CLOSE FILE
CHTOP EQU 8 CHANGE TYPE
CHAOP EQU 9 CHANGE ATTRIBUTES
CHNOP EQU 10 CHANGE NAME
INFOP EQU 11 INFORMATION REQUEST
SUNOP EQU 12 SET DISK UNIT
RETOP EQU 13 RETURN TO CI
RESOP EQU 14 RESET, THEN RETURN TO CI
ABTOP EQU 15 ABORT, THEN RETURN TO CI
SEKOP EQU 16 SEEK OPERATION
RNDOP EQU 17 RANDOMIZE
CAOP EQU 18 CLOSE ALL/UNIT
CTLOP EQU 19 FILE CONTROL/STATUS
SREST EQU 20 SHORT RESET TO CI
DRDOP EQU 21 DELIMITED READ
DWROP EQU 22 DELIMITED WRITE
DSPOP EQU 23 DELIMITED SPACE OPERATION
RTROP EQU 24 RETURN WITH TRAP OPERAITON
*
MAXOP EQU RTROP MAX OPERATION
*
*
*********************
*
* ERROR NUMBERS
*
*
* THESE ARE THE CORRECT ERROR NUMBERS
*
ERNEX EQU 1 NONEXISTENT FILE
ERAEX EQU ERNEX+1 FILE ALREADY EXISTS
ERUFN EQU ERAEX+1 UNASSIGNED FILE NUMBER
ERPRO EQU ERUFN+1 PROTECTION VIOLATION
ERNIF EQU ERPRO+1 FILE NOT TYPE IMAGE
ERMOP EQU ERNIF+1 ILLEGAL OPERATION ON MUDTIPLY OPEN FILE
ERRAC EQU ERMOP+1 RANDOM ACCESS TO NON-RANDON FILE
ERRDV EQU ERRAC+1 RANDOM ACCESS TO DEVICE FILE
ERZBC EQU ERRDV+1 EMPTY DEVICE FILE
*
ERIOP EQU ERZBC+1 ILLEGAL PTDOS OPERATION
ERIBF EQU ERIOP+1 ILLEGAL BUFFER ADDRESS
ERIBS EQU ERIBF+1 ILLEGAL BLOCK SIZE
ERINM EQU ERIBS+1 ILLEGAL CHARACTER IN NAME
ERICU EQU ERINM+1 ILLEGAL CHARACTER IN UNIT
ERIUN EQU ERICU+1 ILLEGAL UNIT
ERNTL EQU ERIUN+1 NAME TOO LONG
ERMEM EQU ERNTL+1 USER MEMORY PROTECT VIOLATION
ERSMP EQU ERMEM+1 SYSTEM MEMORY PROTECT VIOLATION
ERUCN EQU ERSMP+1 UNIT CONFLICT
ERIUP EQU ERUCN+1 ILLEGAL UTILITY OPERATION
ERDRI EQU ERIUP+1 DRIVER ERROR
ERIDA EQU ERDRI+1 ILLEGAL DRIVER ACCESS
ERNCT EQU ERIDA+1 DRIVER NOT PARTICIPATING IN THIS CTRL
* OPERATION
*
EREOF EQU 24 END OF FILE ENCOUNTERED (OR BOF)
ERSEK EQU EREOF+1 SEEK ADDRESS OUT OF RANGE
*
ERTOP EQU ERSEK+1 TOO MANY FILES OPEN
ERMOV EQU ERTOP+1 MEMORY OVERFLOW
ERNID EQU ERMOV+1 NO FILE ID'S LEFT
ERDFL EQU ERNID+1 DISK FULL
ERDIR EQU ERDFL+1 DIRECTORY FULL
ERBLF EQU ERDIR+1 BAD LOAD FILE
*
*
ERFSB EQU 32 FILE STRUCTURE BAD
ERFIC EQU ERFSB+1 FILE ID CONFLICT
ERBSC EQU ERFIC+1 BLOCK SIZE CONFLICT
ERSCC EQU ERBSC+1 SECTOR CONFLICT
ERCFS EQU ERSCC+1 CAN'T FIND SECTOR
ERCRC EQU ERCFS+1 CRC ERROR OR READ/WRITE ABORTS
ERCFT EQU ERCRC+1 CAN'T FIND TRACK
ERRBC EQU ERCFT+1 READ-BACK-CHECK FAILED
ERLOK EQU ERRBC+1 DISK IS WRITE LOCKED
ERXXX EQU ERLOK+1 CATESTROPHIC ERROR
*
*
ERRED EQU 39H DRIVE NOT READY
*
**
* THESE ARE THE OLD SYMBOLS,WHICH ARE STILL USED HERE
*
SERR0 EQU ERRAC - FILE NOT INDEXED
SERR2 EQU ERSEK - SEEK ADDR OUT OF RANGE
RERR0 EQU ERRDV - RANDOM OP ON DEVICE FILE
*
CER0 EQU ERAEX - FILE ALREADY EXISTS
CER1 EQU ERDIR - DIRECTORY FULL
DER0 EQU ERNEX - NONEXISTENT FILE
DER1 EQU ERMOP - ATTEMPT TO KILL OR EOF MULTIPLY OPEN FILE
OER1 EQU ERIBF - ILLEGAL BUFFER ADDRESS
PER0 EQU ERPRO - PROTECT VIOLATION
EER0 EQU EREOF - END OF FILE
FINE0 EQU ERNEX - FILE DOES NOT EXIST
FINE1 EQU ERPRO - PROTECTION
FER0 EQU ERTOP - NO FCBS AVAILABLE
MER0 EQU ERMOV - MEMORY OVERFLOW
PER1 EQU ERUFN - ILLEGAL FCB
IER0 EQU ERNID - NO IDS LEFT
FBER EQU ERFSB - FS BAD
CHER EQU ERPRO - ALTERATION PROTECTED
CIER0 EQU ERBLF - BAD LOAD FILE
CIER1 EQU ERNIF - NOT IMAGE FILE
*
*
DAER0 EQU ERDFL - DISC IS FULL
DAER1 EQU ERIBS - ILLEGAL BLOCK SIZE
DVER0 EQU ERDRI - DRIVER ERROR
IDAER EQU ERIDA - ILLEGAL DRIVER ACCESS
ILOER EQU ERIOP - ILLEGAL OPERATION
UNER0 EQU ERIUN - ILLEGAL UNIT
LDE2 EQU ERZBC - BAD DRIVER--ZERO
UTE0 EQU ERIUP - BAD UTILITY OPERATION
*
MPE0 EQU ERMEM - MEMORY PROTECT
MPE1 EQU ERSMP - SYSTEM MEMORY PROTECT
CHR2 EQU ERUCN - UNIT CONFLICT
ICE0 EQU ERINM - ILLEGAL CHARACTER IN NAME
ICE1 EQU ERICU - ILLEGAL CHARACTER IN UNIT
CSER0 EQU ERXXX - CATESTROPHIC ERROR
*
*
*********************
*
* DRIVER TYPE/STATUS BITS
*
SBDUP EQU 128 DUPLICATIVE
SBIAT EQU 64 INTERACTIVE
SBTAB EQU 32 TABBING
SBSTB EQU 16 SET TABS
SBFF EQU 8 FORM-FEED
SBATB EQU 4 ABSOLUTE TABS
SBINT EQU 2 INTERRUPT DRIVEN
SBPRO EQU 1 SETTABLE PROMPT
*
*********************
*
* SECONDARY OPERATIONS
*
UXOP EQU 0 EXPLAIN ERROR NICELY
UXOP1 EQU 1 SECOND LEVEL
*
CCLDE EQU 32 LOADER OPERATION CODE
*
*
*********************
*
*
*
* SYSTEM FILE INFORMATION
*
*
* DIRECTORY INFORMATION
*
IDDIR EQU 2 DIRECTORY FILE ID
DIRDB EQU 200 FIRST BLOCK OF DISK DIRECTORY
*
NMLEN EQU 8 NAME LENGTH
DREMS EQU 24 MAX ENTRIES PER SECTOR
DICNT EQU 8 NUMBER OF DIRECTORY SECTORS
*
*
* SYSTEM GLOBAL FILE
*
DASPB EQU 6 FIRST BLOCK OF SYSTEM GLOBAL
IDSPA EQU 5 FILE ID
*
*
* SYSTEM RESIDENT
*
DAREB EQU 8 FIRST SECTOR OF RESIDENT
IDRES EQU 4 FILE ID
D2REB EQU 16 SECOND SECTION OF RESIDENT
*
*
* FSM (FREE SPACE MAP) INFORMATION
*
IDFSM EQU 1 FSM FILE ID
DAFSB EQU 208 BLOCK # OF FSM (TRACK 26)
*
*
* NEXT FILE ID FILE INFORMATION
*
IDNID EQU 3 NEXT ID FILE ID
DANIB EQU 209 BLOCK OF NEXT ID FILE
NIDBC EQU 2 BYTE COUNT OF BLOCK
*
*
* BOOTSTRAP FILE
*
DABOS EQU 0 ST ADDR OF DISK BLOCK # ( must never change)
IDBOT EQU 6 FILE ID
*
*********************
*
* HEADER VALUES ETC
*
*
* SECTOR SIZES
*
SECTSZ EQU 500
FULSZ EQU 512 # DATA BYTES IN FOLLOWING BLOCKS
*
*
* FILE STRUCTURE LINKAGE VALUES
*
BOFCD EQU 65535 BOF CODE IN BACK POINTER
EOFCD EQU 32768 EOF BIT IN FORE POINTER
*
*
* FILE PROTECTION ATTRIBUTE BITS
*
PDEL EQU 1 DELETE PROTECT
PWRI EQU 2 WRITE PROTECT
PREA EQU 4 READ PROTECT
PFINF EQU 8 INFORMATION PROTECT
PATR EQU 16 ATTRIBUTE CHANGE PROTECT
PNAT EQU 32 NAME AND TYPE CHANGE PROTECT
PALO EQU 64 ALLOCATION PROTECTION
*
*
* DEFINE FILE TYPES
*
SYSIM EQU 00H SYSTEM IMAGE TYPE --(I00)
BNTYP EQU 80H BINARY DATA FILE --(00)
UTTYP EQU 01H UTILITY TYPE
*
IMTYPE EQU 80H IMAGE FILE MASK (OFF IS IMAGE!!)
*
*
*******************************************
*
*
* DRIVER TABLE STRUCTURE
*
* THESE ARE DISPLACEMENTS INTO A DRIVER
*
DTRB EQU 0 READ BLOCK
DTRNB EQU 2 READ NEXT BLOCK
DTRLB EQU 4 READ LAST BLOCK
DTWBR EQU 6 WRITE BLOCK: LOAD NEXT
DTWB EQU 8 WRITE BLOCK
DTREW EQU 10 REWIND
DTEOF EQU 12 END-FILE
DTCLO EQU 14 CLOSE
DTSEK EQU 16 SEEK
DTCTL EQU 18 CONTROL/STATUS
DTBLK EQU 20 BLOCK SIZE
DTITO EQU 22 IMMEDIATE TRANSFER OPTION
DTINI EQU 23 INITIALIZE ENTRY POINT
*
PAGE
*
*
*******************************************
*
*
* SYSTEM GLOBAL AREA STUFF
*
*
* MEMORY AREA
*
MINMA EQU 08800H LOWEST MEMORY ADDRESS
LNMBF EQU 0FB8H LENGTH OF MAIN BUFFER AREA (4024)
FCB0 EQU MINMA+LNMBF START OF FCB AREA
XFER EQU 0F016H DISK ROUTINE
*
*
* FILE CONTROL BLOCKS
*
MAXFCB EQU 8 MAX. NUMBER OF OPEN FILES
MINFCB EQU 5 MIN. NUMBER OF FILE CONTROL BLOCKS
LNFCB EQU 34 LENGTH OF FCB. MUST AGREE WITH LAYOUT !!!!!!
FCBLN EQU LNFCB*MAXFCB LENGTH OF FCB AREA
*
* FCB SIZE DEFINED LITERALLY <<-------------< WARNING
*
*
* DEFINE SYSTEM STACK
*
BOTSK EQU FCB0+FCBLN MAX TOP OF STACK ADDRESS
STKSZ EQU 60 STACK SIZE
TOPSK EQU BOTSK+STKSZ BOTTOM OF STACK (INITIAL TOP)
*
* INITIAL ELEMENTS IN THE STACK ALWAYS LOOK LIKE THIS
*
UHL EQU TOPSK-2 USER HL
UL EQU UHL USER L
UH EQU UHL+1 USER H
UD EQU TOPSK-3 USER D
UE EQU TOPSK-4 USER E
UDE EQU UE
UB EQU TOPSK-5 USER B
UC EQU TOPSK-6 USER C
UBC EQU UC
UA EQU TOPSK-7 USER A
UPSW EQU TOPSK-8 USER PSW
UTOS EQU TOPSK-10 USER SP
*
PAGE
*
*
*******************************************
*
*
*
*
*
* SYSTEM GLOBAL AREA
*
ORG TOPSK
*
SGAREA EQU $ BEGINNING OF THE SYSTEM GLOBAL AREA
SP1 EQU -MINFCB*LNFCB+SGAREA LOAD ADDRESS FOR SYSGLOBL
MASPA EQU SP1 SAME
*
*
*
* THE FOLLOWING PARAMETERS ARE AVAILABLE TO THE USER
* THROUGH THE POINTER IN THE ENTRY POINT AREA.
*
*
* DEFAULT FILE NUMBERS
*
CIFILE DB 0 C/I INPUT FILE
COFILE DB 1 C/I OUTPUT FILE
UTIL DB 2 DEFAULT UTILITY FILE =2
ECFILE DB 1 ECHO OUTPUT FILE
*
* DO NOT CHANGE THE ORDER OR POSITION OF THE ABOVE FOUR
* PARAMETERS UNDER ANY CIRCUMSTANCES!!!!
*
DUNIT DB 0 DEFAULT DISK DRIVE AND UNIT
SYSFIL DB 3 NUMBER OF SYSTEM FILES CONFIGURED
MAXUN DB 2 NUMBER OF DRIVES+1 CONFIGURED
*
SWITCHS DB 0 BITS FOR ON OFF
DB 0 USER SENSE SWITCHES
*
*
* ERROR HANDLING
*
EERR DW -1 EOF-BOF ERRORS
AERR DW 0 ABORTIVE ERRORS
FERR DW 0 FATAL, SERIOUS ERRORS
*
*
* MISC.
*
CRTRAP DW -1 C/I TRAP RETURN
UPROT DW 0 USER MEMORY PROTECT
*
STFLG DB 0 EXTRA CHARACTER WAITING ON CONIN FLAG
INBYT DB 0 THE SAID EXTRA CHARACTER
*
* CI READ/WRITE/TEST POINTERS
*
RCH DW CIRCH READ CONSOLE
WCH DW CIVDM WRITE CONSOLE
SCH DW CITCH TEST CONSOLE
*
NULLS DB 0 NUMBER OF NULLS TO FOLLOW CR
*
*
*
* CONFIGURATION INFORMATION
*
* SYSTEM VERSION
*
DB 52H SYS VERSION 2.0.2
DB 01H MONTH MM
DB 01H DATE DD
DB 88H YEAR YY
*
ASC 'PTDOS2.0' DISK NAME
*
ASC 'PTDOS' PASSWORD
DW 0 (8 CHARS, ZERO FILL)
DB 0
*
*
* INTERRUPT STUFF
*
BDSK1 DW -1 STANDARD RETURN INTERRUPT ADDRESS
BDSK2 DW -1 FAST " " " " " "
IFLG1 DB 0 FLAG TO RE-ENABLE INTERRUPTS
IFLG2 DB 0 DISK DONE FLAG FOR INT HANDLER
*
*
* MEMORY CONFIGURATION
*
LOWAD DW MINMA MINIMUM AVAILABLE LOCATION
*
*
* SYSTEM SWITCH FLAGS
*
SWECH DB 0 ECHO ENABLE
SWLOK DB 0 DISK WRITE LOCK
SWUPS DB 0 UPSHIFT ASCII
SWRBC DB 0 DISK READ-BACK-CHECK AFTER WRITE
SWBIO DB 0 BINARY I/O ON CONSOLE
SWLOG DB 0 LOG FILE FOR CI ECHO FLAG
SWVRB DB 1 VERBOSE DISABLE
SWFTR DB 0 FUTURE (I.E. ISN'T 8 A NICE NUMBER)
*
*
* LEAVE SOME ROOM FOR FUTURE JUNK
*
GLVDC DW PCRCK SET SCREEN LINE ADDRESS
DW -1
*
PAGE
*
*
*
*
*
* ///// THE PARAMETERS BELOW ARE DEFINED FOR SYSTEM ////
* ///// USE FROM SYSGLO. DO NOT CHANGE THEIR LOCATION ///
*
*
* FCB AREA PARAMETERS
*
HIGHA DW MAXFCB*LNFCB+FCB0 TOP AVAILABLE LOCATION
MINAD DW FCB0-BUFT-BUFT2 MINIMUM BUFFER ALLOCATED SO FAR
FCBASE DW FCB0 FIRST FCB ADDRESS
NFCB DB MAXFCB NUMBER OF FCBS
*
CRSEEN DB 0 CR FLAG FOR TTY DRIVER
TDPRO DW CIMSG CI TTY PROMPT MESSAGE POINTER
FRADD DW 0 FCB RESTORATION ADDRESS
*
*
*
*
PAGE
*
*
*******************************************
*
*
* < PARAMETER CONVERTER >
* ASCII: - BINARY
*
* VERSION 1.1 OCT. 25, 1976 S. DOMPIER
*
* CALLING SEQUENCE:
* reg HL has ASCII value string address
* terminated by a binary zero.
*
* PCONA: reg B has alpha base chr
* PCONB: reg B has binary base
*
* max parameter values: FFFF<:H> 65535:D
* 1111 1111 1111 1111:B 177777:Q
*
* alpha base notation: B = binary
* O = octal
* Q = octal
* D = decimal
* H = hexidecimal
*
*
PCONA LXI D,PBTBL-1 base table
XCHG
MVI C,6 table entry count+1
MOV A,B get base chr
*
CBASE DCR C
JZ ZRET illegal base chr
INX H
CMP M
INX H point to next base chr/value
JNZ CBASE
MOV B,M get binary base value
XCHG
*
* convert base-n digits to binary
*
PCONB MOV A,B get base
STA PBASE save base
PUSH H save input buffer address
LXI D,0 initialize total
*
CNUM2 LDA PBASE get base
MOV B,A
POP H
MOV A,M get chr
ORA A binary zero?
RZ . yes, we are done
*
INX H
PUSH H save CBUF pointer
SUI 30H strip ascii bias
CPI 10 >10?
JC CNUM3
ANI 0DFH upshift, if necessary
SUI 7 strip alpha bias
CPI 10H illegal chr? > "F"
JNC ZRET
CPI 10
JC ZRET
*
CNUM3 MOV C,A save number
SUB B subtract base
JP ZRET not legal in base
LXI H,0 clear temp total
CALL MULT total * base
MVI B,1 one pass
MVI D,0
MOV E,C
CALL MULT add digit
XCHG
JMP CNUM2 get next digit
*
*
* multilpy DE*B
*
MULT INR B
MULT2 DCR B
RZ . done ~.~.~.~.~.~ EXIT ~.~.~.~.~
DAD D
JNC MULT2 continue if no overflow
JMP ZRET > 64K error
*
*
* alpha base table
*
PBTBL DW 242H 'B' binary
DW 84FH 'O' octal
DW 851H 'Q' octal
DW 0A44H 'D' decimal
DW 1048H 'H' hexidecimal
*
*
MAXIN EQU 20 maximum chr input count
*
*
* THIS IS THE REST OF PSCAN FROM PAGE "B" UP TOP
*
* error returns
*
ERRET CALL PREAD set-up error return address
ZRET XRA A zero reg A = field error
ERET STC . set carry = error
MOV E,A error number to reg E
JMP PNR2
*
*
PREAD CPI 0D5H ascii in HL from base in B?
LHLD UIBUF -> USER INPUT
JNZ PR2 nope
CALL PCONB convert value; returns DE
JMP PNR1 normal return
*
*
PR2 ANI 20H one chr only?
JZ R1 no
CALL G1 get one chr from CI or user buffer
STA LC
JMP PNR1 go home
*
*
* read chrs into OUBUF
*
R1 MVI C,0
LHLD UOBUF
R2 CALL GETCH get chr
JZ STOP done, found delimiter ,/;/cr
MOV M,A store chr in UOBUF
INX H
INR C update chr count
MVI A,MAXIN maximum input count
SUB C
RZ . to many chrs
JMP R2 get next chr
*
*
* get input character
* RETURN IN A, ZERO IF DELIMITER
*
GETCH PUSH H save output pointer
GETC2 CALL G1
CPI ' ' skip spaces
JZ GETC2
MOV L,A SAVE CHR IN L
LDA OPT
ANI 88H
ADD A SET CARRY AND ZERO FLAGS FOR JUMPS BELOW
MOV A,L RESTOR CHR
POP H
JNZ DLTEST SKIP ALL BUT NORMAL DELIMITERS
JC DLMTST VALUE OP, SKIP NO DELIMITERS
JMP DLTST NAME OP, SKIP ALL BUT NAME DELIMITERS
*
*
G1 LDA OPT
ANI 40H user input buffer?
JNZ G2 yes
LDA CIFILE get cifile number from DOS
PUSH B
CALL RB read one byte from cifile
JMP ERET
POP B
RET
*
*
G2 LHLD UIBUF get user input buffer pointer
MOV A,M
INX H
SHLD UIBUF
RET
*
*
STOP MVI M,0 set stop byte (last UOBUF chr),
MOV L,C stops scan in PCON or puts 0
MOV H,A after name
SHLD CCLC save chr count and last chr scanned
MOV A,C
ORA A any characters?
JZ PNRET nope, its a default field
LHLD UOBUF get name/scratch buffer pointer
LDA OPT get options
MOV B,A
ANI 8 CHECK IF READ ALL CHRS TO NORMAL,
JNZ PNRET RETURN CHR - , ; cr 0
MOV A,B
RAL . name?
JNC NAME
*
* VALUE FIELD
*
DCX H
MVI B,'H' set hexidecimal base default
*
V2 INX H
MOV A,M
ORA A
JZ V3 if binary zero, field is finished
SUI ':' base?
JNZ V2 no, look for ':' or binary zero
MOV M,A set binary zero in place of ':'
INX H
MOV B,M get base chr
INX H
CMP M better be zero!
RNZ . error, only one base chr allowed.
*
V3 LHLD UOBUF point to value string
CALL PCONA convert ascii string to binary
POP H
RET . normal return, value in DE
*
*
* NAME FIELD
*
NAME LDA LC GET LAST CHR SCANNED
CALL DLTEST CHECK IF , ; cr 0
MVI A,-1 REG E = -1 ON RETURN,
JNZ NOPEN FILE NOT CREATED OR OPENED
*
MOV A,M GET FIRST NAME CHR
CPI '#' file number?
LXI B,0A00H SET C=0 & BINARY BASE = 10
JNZ N1 NOPE
INX H
CALL PCONB CONVERT FILE NUMBER TO BINARY
POP H CLEAR STACK FOR NORMAL RETURN
RET
*
*
N1 LDA OPT GET OPTIONS
ORA C ADD IN POSSIBLE SUPPRESS CREATE FROM OPEN
RAR . suppress create?
LHLD UOBUF POINT TO NAME
JC POPEN yes
LXI D,-4 POINT TO TYPE (CREATE BLOCK)
DAD D
XCHG
CALL SYS
DB CREOP create file
JMP CREER something wrong
CRNR MVI C,1 set suppress create
JMP N1 now attempt to open file
*
*
CREER CPI ERAEX existing file?
JNZ ERET no, something else wrong
LDA OPT get options
ANI 2 . force create?
JZ CRNR no, open file
MVI A,ERAEX yes; and,
JMP ERET set existing file error.
*
*
* OPEN, DE HAS UOBUF WITH NAME
*
POPEN LXI D,0 clear value/ set static buffer
RAR . suppress open?
RAR
JC PNRET yes, return
XCHG . name pointer to DE,
CALL SYS static buffer to HL.
DB OPEOP open named file
JMP ERET opps!
*
*
NOPEN MOV E,A save file number OR -1
MVI D,0 clear reg D
POP H return, with file number in E
RET
*
*
*
*
* LAST WORD LOADED
*
DB 0 THIS BYTE IT A SPARE
*
SP2 EQU $-1
LNSPA EQU SP2-SP1+1 LENGTH OF SYSGLOBL (DO NOT CHANGE)
*
* *** WARNING, MAX = 380H (ELSE MOVE SYS GLO AREA) ***
*
*
PAGE
*
*
*******************************************
*
*
*
* TEMPORARY STORAGE AREA
*
*
OPER RES 1 DOS OPERATION
*
* DIRECTORY SEARCH PARAMETERS
*
DFC RES 2 FREE DIRECTORY ENTRY ADDRESS
DBUF RES 2 DIRECTORY ENTRY POINTER
DCNT RES 1 DIRECTORY ENTRY COUNTER
DRID RES 2 FILE ID TO SEARCH FOR
*
TBUFA RES 2 TRUE BUFFER ADDRESS (USED ALL OVER)
*
DISA RES 2 DISPATCH ADDRESS (SYS)
*
AFBT1 RES 1 BLOCKS REQUIRED
AFBT3 RES 2 TRACK MAP POINTER
AFBT4 RES 2 START SECTOR (BLOCK#)
AFBT6 RES 2 PBUF POINTER
*
DABT1 RES 2 BUFFER ADDRESS
DABT2 RES 2 BUFFER SIZE
DABT3 RES 1 FCB COUNTER
*
*
WBUFSZ RES 2 AUTO DEALLOCATION
WBUFAD RES 2
*
SFCT1 RES 1 COUNT FOUND
SFCT2 RES 1 FCB COUNTER
*
LNKT1 RES 2 CURRENT BLOCK #
LNKT2 RES 2 BACK POINTER
*
*
SOU RES 2 SOURCE (RWP)
DEST RES 2 DESTINATION
RWF RES 1 READ/WRITE FLAG
LCNT RES 2 LOCAL COUNT
DELFG RES 1 DELIMITER FLAG (0=>NONE,-1=>SEARCHING,1=>FND)
*
ETMP RES 2 FOR EOF
ECRS RES 2 LAST BLOCK
CLCNT EQU SOU CLOSE ALL FCB COUNTER
RINAD RES 2 RANDOM INDEX ADDRESS (IN MEMORY)
*
LSECT RES 2 LAST BLOCK ADDRESS (DDRNB)
*
RFBCN RES 1 COUNT, (RFBLK)
RFBC1 RES 1 COUNT, (RFBLK)
*
*
XA RES 1 A FOR UTIL AND CI
XHL RES 2 HL FOR UTIL
XOPER RES 1 OPER FOR UTIL
*
RNPTR RES 2 RANDOM INDEX POINTER
RNCNT RES 1 ENTRY COUNT
CICNT RES 1 COUNTER (CI)
CPNT RES 2 POINTER (CI)
CECT EQU CPNT ECHO COUNT (CI)
CERC EQU CICNT LINE POSITION (CI)
FRAD2 RES 2 FOR OPEN
XQFLG RES 1 EXECUTE FLAG FOR CI
CONCH RES 1 CHARACTER READ BY CONIN OR CONOUT
*
*
* PSCAN TEMPORARIES
*
PBASE DS 1 BASE CHARACTER
OPT DS 1 OPTIONS
UOBUF DS 2 USER OUTPUT BUFFER POINTER
UIBUF DS 2 USER INPUT BUFFER POINTER
CCLC EQU $ CHAR CT/LAST CHAR
CC DS 1 CHARACTER COUNT
LC DS 1 LAST CHARACTER
ERSWC DS 2 AERR SAVE AREA
RSTK DS 2 RETURN ADDRESS
*
*
* VDM TEMPORARIES
*
SPEED RES 1
VDMAD RES 2
BOT RES 1
KNTT RES 1
*
* DISK DRIVER TEMPORARIES USED IN RDSK,WDSK(H)
*
*
INTRT DS 2 FOR INTERRUPT PROCESSING RETURN
INRET DS 2 INTERRUPT TEST ROUTINE ADDRESS
DSKRT DS 2 SYSTEM STACK SAVE LOCATION
DRVRT DS 2 DRIVER STACK SAVE LOCATION
DSKRD DS 2 DRIVE NOT READY RETURN TRAP
*
PAGE
*
*
*******************************************
*
*
*
* SYSTEM BUFFERS
*
*
*
* DISK ALLOCATION BUFFER
DKBUF RES 80 TRACKS/DISK ( 1 BIT/BLOCK)
*
* NOTE: OUTPUT TRANSFERS EAT GARBAGE PAST THIS (UP TO 256)
*
*
*
* COMMAND INTERPRETER INPUT BUFFER
*
* (THIS BUFFER IS HERE TO SOLVE MEMORY PROTECT PROBLEMS)
*
CBUF RES NMLEN+2+1
*
*
*
* DIRECTORY SEARCH BUFFER
DIBUF RES SECTSZ 500 BYTES
*
*
* HEADER OFFSET VAUES FOR DIBUF
*
DINE EQU DIBUF NUMBER OF ENTRIES
DIND EQU DIBUF+1 NEXT ENTRY DISPLACEMENT (2 BYTES TO ADDR 500)
DRFDS EQU DIND+2 ADDRESS OF FIRST ENTRY
*
*
*
* NEXT FILE ID BUFFER
*
IDBUF RES NIDBC
*
*
*
* TRACK MAP BUFFER
*
TMBUF RES 8 FOR UNPACKED TRACK MAP
*
*
*
* COMMAND INTERPRETER STACK
*
CISS RES 50 FOR CI STACK
CISTK EQU CISS+50 CI STACK
*
*
* DIRECTORY ENTRY BUFFER
*
DEBUF RES NMLEN NAME
DETYP RES 1 TYPE
DEBBS RES 2 BLOCK SIZE IN BYTES
DEPRO RES 1 PROTECTION ATTRIBUTES
DEFID RES 2 FILE ID
DEINX RES 2 FILE INDEX
DEFBA RES 2 FIRST BLOCK DISK ADDRESS
DENBL RES 2 NUMBER OF BLOCKS
*
DRESZ EQU DENBL+2-DEBUF ENTRY SIZE
*
PAGE
*
*
*******************************************
*
*
*
* FCB ENTRY FORMAT, CURRENT FCB ENTRY
*
FCBORG RES 1 BEGINNING
FTYPE EQU FCBORG FILE TYPE
FBLKS RES 2 BLOCK SIZE
FPROT RES 1 PROTECTION
FID RES 2 FILE ID
FINDX RES 2 INDEX ADDRESS
FFBA RES 2 FIRST BLOCK ADDRESS
FUNIT RES 1 UNIT
FBUFA RES 2 BUFFER ADDRESS/UNBUFFERED FLAG
FDLTA RES 2 DELTA ALLOCATION IN BLOCKS
FDRIV RES 2 DRIVER POINTER
FAIND RES 2 MEMORY ADDRESS OF FILE INDEX BLOCK OR -1
FNBD RES 2 NEXT BYTE DISPLACEMENT
FBDL RES 2 BYTE DISPLACEMENT LIMIT
FFLAG RES 1 DIRTY BLOCK FLAG
FCURSC RES 2 CURRENT SECTOR ADDRESS
FGSPR RES 1 GARYS SPARE
FFORE RES 2 FORE POINTER
FBACK RES 2 BACK POINTER
FHID RES 2 ID FROM HEADER
FPRST RES 1 PROTECTION/STATUS
*
* NOTES:
* 1) FTYPE-FFBA MUST MATCH DETYP-DEFBA
* 2) FFORE-FPRST MUST MATCH THE DISK HEADER
*
TSTV1 EQU FTYPE-FFBA
TSTV2 EQU DETYP-DEFBA
TSTV3 EQU FFORE-FPRST
*
*
* LNFCB EQU FPRST+1-FCBORG FCB LENGTH
*
TSTV4 EQU LNFCB
TSTV5 EQU FPRST+1-FCBORG
*
* THIS MUST AGREE OR ELSE!
*
PAGE
*
*
*******************************************
*
*
* DISK INTERFACE CONTROL BLOCKS
*
*
* TRANSFER DESCRIPTOR or BLOCK TRANSFER DESCRIPTOR
* Used to describe all transfers between disk and memory by
* by calling XFER in SAMDI (disk interface) at $F016.
* On entry HL ^ to BXD.
* CALL XFER transfer data bet disk and memory
* JMP ERROR error return (HL ^ to BXD, error code in A)
* .... standard return
*
*
TDAD EQU $
TSEC RES 2
TBCNT RES 2
TFID RES 2
TBUF RES 2
TUNIT RES 1
*
BXD EQU $
BXDEV RES 1
BXOP RES 1
BXRZ RES 2
BXFR RES 2
BXXA RES 2
BXRES RES 2
*
*
*
*
* INCOMING HEADER
* The header exists on disk as the last 12 bytes of a block
* When a block is read from the disk to memory the header is
* transferred from the buffer to here by RDDSK.
*
IHEAD EQU $
IHBLK RES 2 BLOCK
IHFOR RES 2 FORE POINTER
IHBAK RES 2 BACK POINTER
IHFID RES 2 FILE ID
IHPRO RES 1 PROTECTION/BLOCK SIZE (# of blocks)
IHSIZ RES 2 BLOCK SIZE ie # of bytes in a block
IHSPR RES 1
RWBUF RES SECTSZ DATA PUT HERE AFTER BUFFER SO WRITTEN TOGETHE
*
*
* OUTGOING HEADER
* The filing header is written to disk as the last 12 bytes of
* a block. When a block of a file is to be written the header
* is assembled here, then transferred to the end of the block
* by WRDSK.
*
OHEAD EQU $
OHBLK RES 2 SECTOR # (starts at 0)
OHFOR RES 2 FORE POINTER
OHBAK RES 2 BACK POINTER
OHFID RES 2 FILE ID
OHPRO RES 1 PROTECTION-SECTORS/BLOCK
OHSIZ RES 2 BLOCK SIZE
OHSPR RES 1
*
ENPAR EQU $ END OF THIS
*
*
MARES EQU 0A002H SYSTEM RESIDENT WILL START HERE
*
PAGE
*
*
*******************************************
*
*
*
* FILE 0 FCB
*
*
* THIS FILE IS THE SYSTEM CONSOLE. IT IS USED FOR
* DEFAULT INPUT AND CANNOT BE CLOSED.
*
*
* THE INITIAL FCB'S ARE ASSEMBLED HERE AND MOVED
* TO FCB0 (THEIR PROPER PLACE) WHEN THE SYSTEM IS
* BOOTSTRAPPED.
*
*
ORG SP1 INITIALLY HERE
*
*
* FILE '0'--C/I INPUT FILE
*
DB 255 TYPE IS DEVICE
DW BUFT BLOCK SIZE
DB PWRI WRITE PROTECTED KEYBOARD
DW -1 ID
DW 0 INDEX
DW 0 FIRST BLOCK
DB 0 UNIT
DW FCB0-BUFT BUFFER ADDRESS
DW 0 DELTA
DW TDRIV TTY DRIVER
DW -1 ALTERNATE INDEX
DW 0 NBD
DW 0 BDL
DB 0 FLAG
DW 0 CURRENT SECTOR
DB 0 FGSPR
DW EOFCD FORE = EOF
DW BOFCD BACK = BOF
DW -1 FILE ID
DB 0 PROTECTION
*
*
*
* FILE '1'--CI OUTPUT FILE
*
DB 255 TYPE
DW BUFT2 BLOCK SIZE
DB PREA READ PROTECTED TYPER
DW -1 IDENTIFICATION
DW 0 INDEX
DW 0 FBA
DB 0 UNIT
DW FCB0-BUFT-BUFT2
DW 0 DELTA
DW TDRIV DRIVER
DW -1 ALTERNATE INDEX ADDRESS
DW 0 NBD
DW 0 BDL
DB 0 FLAG
DW 0 CUR SECT
DB 0 FGSPR
DW EOFCD FORE
DW BOFCD BACK
DW -1 ID
DB 0 PROT
*
*
*
* UTILITY FILE RESIDES HERE (FILE '2')
*
DB 80H
DW 1F4H
DB 0
DW 8
DW 214
DW 210
DB 0
DW FCB0-BUFT-BUFT2-1F4H
DW 0
DW DDRIV
DW -1
DW 0
DW 0
DB 0 DIRTY FLAG
DW -1
DB 0
DW 211
DW -1
DW 8
DB 0
PAGE
*
*
******************************************************
*
*
*
ORG MARES SYSTEM RESIDENT <|----------------<<---<<---<<<
AP1 EQU MARES STARTS HERE.
*
*
*
*
*
*
* **** PTDOS SYSTEM ENTRY POINT ****
*
*
*
* SAVE REGISTERS AND DISPATCH TO OPERATION
*
*
SYS DI . DISABLE INTERRUPTS FOR AWHILE
SHLD UHL SAVE HL
LXI H,0
SHLD WBUFSZ CLEAR LOCAL BUFFER FLAG
DAD SP HL=SP
LXI SP,UHL SET SYSTEM STACK POINTER
PUSH D SAVE D,E
PUSH B SAVE B,C
PUSH PSW SAVE A,FLAGS
PUSH H SAVE SP
SPHL . RESTORE USER SP
POP H GET RETURN ADDRESS
MOV A,M
INX H MOVE PAST IT
PUSH H SAVE RETURN ADDR AGAIN
STA OPER SAVE OPERATION
LXI SP,UTOS RESTORE SP
CALL TSTEI PUT THE INTERRUPTS BACK ON IF DESIRED
*
* VALIDATE OPERATION
*
LDA OPER GET OPERATION
CPI MAXOP+1
JC SDISPT IF OK GO TO OPERATION
*
* ILLEGAL OPERATION
*
ERR0 CALL ERRL1 ILLEGAL OPERATION
DB ERIOP
*
*
* DISPATCH TO OPERATION
*
* LOOK UP IN TABLE
*
SDISPT LXI H,DISPA DISPATCH ADDRESS
MOV E,A
MVI D,0 HL <--DISPA+(2*A)
DAD D
DAD D
MOV A,M
INX H
MOV H,M
MOV L,A
*
* HL NOW CONTAINS THE DISPATCH ADDRESS
*
PCHL . GO TO OPERATION
*
*
*
* SYSTEM DISPATCH TABLE
*
*
DISPA DW CREATE 0
DW OPEN 1
DW KILL 2
DW READ 3
DW WRITE 4
DW SPACE 5
DW EOF 6
DW CLOSE 7
DW CHTYP 8
DW CHATR 9
DW CHNAM 10
DW FINFO 11
DW SUNH 12
DW RETURN 13
DW USRES 14
DW ABURP 15
DW SEEK 16
DW RNDOM 17
DW CA 18 CLOSE ALL FILES OPERATION
DW FCTRL 19 DRIVER CONTROL/STATUS
DW USRES 20
DW DREAD 21
DW DWRITE 22
DW DSPACE 23
DW RETRAP 24
*
PAGE
*
*
*****************************************
*
*
*
* NORMAL RETURN
*
* RESTORE USER REGISTERS AND STACK
*
NRET CALL RFCB
DI . NO INTERRUPTS THROUGH HERE
LHLD UTOS
SPHL
POP H GET USER RETURN ADDRESS
INX H
INX H
INX H
PUSH H MAKE IT NORMAL RETURN
*
NRE10 DI . NO INTERRUPTS
LHLD UHL
PUSH H PUT USER HL ON USER STACK
LXI SP,UPSW
POP PSW RESTORE A,FLAGS
POP B RESTORE BC
POP D RESTORE DE
*
* FINAL RESTORATION
*
LHLD UTOS
SPHL . RESET USER STACK POINTER
DCX SP
DCX SP MOVE BACK TO HL
POP H RESTORE HL
PUSH PSW
CALL TSTEI RESTORE INTERRUPTS IF NEEDED
POP PSW
RET . GO BACK TO CALL
*
PAGE
*
*
*****************************************
*
*
* ERROR RETURN
*
* LEVELS ARE:
*
* 0 VERY SERIOUS - BAD FILES, DISK PROBLEMS
* 1 SERIOUS - USER PROBLEM
* 2 EOF/BOF - ALWAYS HAPPEN
*
ERRL0 LHLD FERR GET PROCESSOR ADDRESS
JMP ERRLP
*
*
ERRL1 LHLD AERR GET LEVEL 1 PROCESSER
JMP ERRLP
*
*
ERRL2 LHLD EERR GET LEVEL 2 ERROR PROCESSER
*
* ERRLP - RESTORE FCB, RELEASE BUFFER, AND RECORD ERROR #
*
ERRLP DI . NO INTERRUPTS FOR A BIT
PUSH H SAVE TYPE OF HANDLING
CALL RFCB RESTORE FCB, IF ANY
CALL RIDBF CLEAN UP BUFFER
POP H ERROR HANDLING TYPE
POP D POINTER TO ERROR NUMBER FROM CALL
LDAX D = ERROR #
STA UA RETURN IT TO THE HANDLER OR USER
*
* IF HL IS ZERO, SYSTEM PROCESSES ERROR
* IF HL IS -1, USER ERROR RETURN, ELSE JUMP THERE
*
ERRP XCHG . TYPE
LHLD UTOS RESTORE USERS STACK
SPHL
INX D
MOV A,E
ORA D
JZ NRE10 USER ERROR RETURN
DCX D
MOV A,E
ORA D
JZ ERRP7 SYSTEM HANDLES IT
*
* CHANGE RETURN ADDRESS TO HL FOR ERROR TRAP
*
POP H GET RID OF OLD RETURN
PUSH D PUT IN TRAP ADDRESS
JMP NRE10 GO LOOK NORMAL
*
*
* SYSTEM ERROR HANDLER, FORGET ABOUT USER PROGRAM
*
ERRP7 POP H GET RETURN ADDRESS IN HL
LDA UTIL SEE IF A UTILITY FILE IS GOING
INR A (-1 IF NOT)
JNZ ERRP8 OK, USE IT
LDA OPER
MOV B,A GET OPERATION IN B
LDA UA GET ERROR NUMBER IN A
CALL SYS GO AWAY AND DON'T COME BACK
DB ABTOP ABORT
*
*
*
* EXPLAIN THE ERROR USING UTILITY
*
ERRP8 LDA UA
STA ERCD SET ERROR CODE (OPER ALREADY SET)
LDA OPER
STA EOPR SET OPERATION CODE
*
ERRPX PUSH H
LXI H,XTRP TRAP ANY SERIOUS ERRORS
SHLD AERR
SHLD FERR
POP H
MVI A,3 (=> NUMBER AND "CALLER FROM" MSG.)
JMP ERRP9
*
PAGE
*
*
*****************************************
*
*
*
*
* CREATE FILE OPERATION
*
*
* USER DE POINTS TO A BLOCK WITH THE FOLLOWING FORM....
*
* BYTE CONTENTS
* 0 FILE TYPE
* 1-2 FILE BLOCK SIZE
* 3 FILE PROTECTION WORD
* 4 ..... FILE NAME <0> OR NAME/UNIT #
*
*
* ERRORS:
* FILE ALREADY EXISTS
* DIRECTORY FULL
* MEMORY OVERFLOW
* DISK FULL
* ILLEGAL NAME
*
* FIRST, SEARCH DIRECTORY FOR FILE
*
CREATE LHLD UDE GET NAME POINTER
LXI D,DEPRO-DETYP+1
DAD D
CALL SDIR SEARCH
JMP CRE10 NOT FOUND, OK
CALL ERRL1 ERROR
DB ERAEX
*
* CHECK FOR FULL DIRECTORY
*
CRE10 LHLD DFC
MOV A,L
ORA H
JZ ERDIR FREE PTR IS ZERO - ERROR
*
* CREATE A DIRECTORY ENTRY IN DEBUF
* COPY CONSTANT PARAMETERS
*
LHLD UDE
XCHG . PARAMETER PTR IN DE
LXI H,DETYP BUFFER PTR IN HL
CALL MOVEF MOVE USER PARAMETERS
DB DEPRO-DETYP+1
*
* ALLOCATE BUFFER FOR INITIAL BLOCK ALLOCATION
*
LHLD DEBBS
SHLD FBLKS PUT BLOCK SIZE INTO FCB
*
* PICK SOMEWHERE FOR A BUFFER JUST USE ANYWHERE
*
LHLD LOWAD
SHLD TBUFA SAVE ADDRESS
*
* ALLOCATE FILE ID
*
CALL GFID
XCHG
SHLD DEFID SAVE ID IN DIREC. ENTRY
*
* SETUP PSEUDO FCB FOR CALL TO AFBLK
*
SHLD FHID SAVE ID
LXI H,EOFCD SET EOF
SHLD FFORE
LXI H,BOFCD AND BOF
SHLD FBACK
XRA A =0
STA FPRST SET NOT DIRTY
*
* ALLOCATE BLOCK
*
CALL AFBLK
SHLD DEFBA SAVE FIRST BLOCK ADDR IN DIREC.
LXI H,1
SHLD DENBL SET NUMBER OF BLOCKS TO 1
DCX H MAKE HL=0
SHLD DEINX SET NO INDEX
* MAKE DIRECTORY ENTRY
CALL EDIR
JMP NRET RETURN TO USER
*
*
CERR1 CALL ERRL1 DIRECTORY FULL
DB CER1
*
PAGE
*
*
*****************************************
*
*
*
* DELETE (KILL) FILE OPERATION
*
*
* USER DE POINTS TO NAME
*
* ERRORS:
* FILE DOES NOT EXIST
* FILE IS DELETE-PROTECTED OR OPEN
* MEMORY OVERFLOW
*
*
KILL LHLD UDE
CALL SDIR SEARCH DIRECTORY
JMP KIL90 ERROR - NONEXISTENT
*
* CHECK FOR DELETE PROTECTION
*
LDA DEPRO
ANI PDEL DEL. PROT. BIT
JNZ EOFE0 ERROR - PROTECTED
*
* CHECK IF FILE IS OPEN
*
LHLD DEFID FILE ID
SHLD FID SET SO RBLK WILL WORK
CALL SFCBS
JMP KIL91 FOUND, OPEN ERROR
JMP KIL91 FOUND
*
LHLD DEBBS
SHLD FBLKS SETUP BLOCK SIZE FOR DEALLOCATION
XCHG
CALL ALBUF GET A BUFFER
SHLD TBUFA
*
CALL RDIR REMOVE DIREC ENTRY
*
* RELEASE DISK SPACE
*
LHLD DEFBA
SHLD FCURSC NOW, DISK ADDR, ID, AND BLK SZ SET
LXI H,DDRIV SET DRIVER
SHLD FDRIV ADDRESS IN FCB
XRA A =0
STA FFLAG SET NOT DIRTY
CALL RBLK READ FIRST BLOCK
*
* RELEASE EACH BLOCK
*
KIL20 CALL RFBLK RELEASE
CALL DDRNB READ NEXT BLOCK
JMP KIL50 EOF, DONE
JMP KIL20
*
* RELEASE BUFFER
*
KIL50 LHLD FBLKS
XCHG
LHLD TBUFA
CALL DLBUF RELEASE IT
*
* RELEASE FILE INDEX
*
LHLD DEINX GET INDEX POINTER
MOV A,H
ORA L
JZ NRET NONE
SHLD FCURSC SET ESECT TO RET
MVI A,1
STA FPRST SECTOR COUNT IS 1
CALL RFBLK RELEASE BLOCK
JMP NRET DONE
*
*
KIL90 CALL ERRL1 NONEXISTENT
DB ERNEX
KIL91 CALL ERRL1 FILE OPEN
DB ERMOP
*
PAGE
*
*
*******************************************
*
*
*
*
* OPEN FILE OPERATION
*
*
* USER DE POINTS TO NAME
* USER HL HAS BUFFER OPTIONS:
*
* IF -1 THEN UNBUFFERED
* IF 0 THEN SYSTEM BUFFERED
* ELSE USER BUFFERED
*
*
* ON NORMAL RETURN,
* A HAS THE FILE NUMBER
* B HAS THE FILE TYPE, AND IF A=255:
*
* DE HAS THE DRIVER SIZE
* HL HAS THE DRIVER LOAD ADDRESS
*
*
* ERRORS:
* FILE DOES NOT EXIST
* NO FCBS AVAILABLE
* MEMORY OVERFLOW
* ILLEGAL USER BUFFER ADDRESS
*
*
*
* FIRST, LOOK UP FILE
*
OPEN LHLD UDE
CALL SDIR
JMP KIL90 DOESN'T EXIST
*
* FOUND, ALLOCATE FCB
*
LXI H,0
SHLD FRADD
CALL ALFCB
*
* MOVE STUFF FROM DIRECTORY ENTRY TO FCB
*
LHLD DBUF
LXI D,DETYP-DEBUF DISPLACEMENT TO TYPE
DAD D
XCHG . DE GETS SOURCE
LXI H,FTYPE HL GETS DESTINATION
CALL MOVEF
DB DEFBA-DETYP+2
*
LXI H,0
SHLD FNBD SET NBD=O
SHLD FDLTA SET DELTA=O
DCX H = -1
SHLD FAIND SET FAIND = -1
LHLD FFBA FIRST BLOCK ADDRESS
SHLD FCURSC MAKE IT CURRENT BLOCK
XRA A
STA FFLAG CLEAR DIRTY FLAG
*
LXI H,DDRIV
SHLD FDRIV SET DRIVER
CALL OBUF
JMP OPE70 UNBUFFERED
* FILE IS BUFFERED
CALL RBLK LOAD IN FIRST BLOCK
SHLD FBDL SET BDL, (NBD=0)
*
OPE70 CALL LODRI SET UP DRIVER
LHLD FRAD2
SHLD FRADD
*
* IF ALREADY OPEN, DON'T ALLOW NEW ALLOCATIONS
*
LHLD FID
CALL SFCBS CHECK FOR OTHER FCB'S WITH SAME ID, UNIT
JMP OPE75 YES
JMP OPE75 YES, = 1 ALREADY
JMP NRET NO, THIS WILL BE THE FIRST
*
*
*
* FILE ALREADY OPEN, SET PALO
*
OPE75 LDA FPROT FILE ALREADY OPEN,
ORI PALO NO ALLOCATION ALLOWED.
STA FPROT
JMP NRET
*
*
* CHECK FOR UNBUFFERED
*
OBUF LHLD UHL USER HL
MOV D,H
MOV E,L MAKE COPY IN DE
INX D DE IS 0 IF UNBUFFERED
MOV A,D
ORA E ZERO TEST
JZ OPE60 YES, UNBUFFERED
*
* CHECK FOR SYSTEM BUFFER REQUEST
*
MOV A,H
ORA L IS IT ZERO
JZ OPE40 YES, ALLOCATE SYSTEM BUFFER
*
* (S)HE HAS SPECIFIED A USER BUFFER
* VALIDATE ADDRESS
*
XCHG
LHLD FBLKS
XCHG . DE = BLOCKSIZE, HL -> BUFFER
CALL MEMCHK CHECK
*
OPE20 LHLD UHL
*
* COME HERE WITH BUFFER ADDRESS IN HL
*
OPE30 SHLD FBUFA
SHLD TBUFA
JMP RP2 RETURN CALL PLUS 2
*
*
* ALLOCATE SYSTEM BUFFER
*
OPE40 LHLD FBLKS
XCHG
CALL ALBUF ALLOCATE BUFFER
JMP OPE30 GOT IT
*
*
* FILE IS UNBUFFERED
*
OPE60 LXI H,-1
SHLD FBUFA
RET
*
PAGE
*
*
******************
*
*
*
*
* ALLOCATE FILE CONTROL BLOCK
*
* NO PARAMETERS
*
* CALL ALFCB
* RETURN FRADD SET, UA GETS NUMBER
* ABORT IF NO FCB IS AVAILABLE
*
ALFCB LHLD FCBASE
LXI D,FID-FCBORG
DAD D FORM FID ADDRESS OF UST FCB
LDA NFCB
MOV C,A C = COUNT
MVI B,-1 START WITH ZERO
*
ALF10 INR B COUNT UP
MOV A,M GET ID
INX H
ORA M
JZ ALF50 FOUND ONE
LXI D,LNFCB-1
DAD D MOVE TO NEXT FCB
DCR C COUNT DOWN
JNZ ALF10
*
* ABORT, NONE AVAILABLE
*
CALL ERRL1 LEVEL 1
DB ERTOP
*
* FOUND ONE
*
ALF50 MOV A,B
STA UA
LXI D,FCBORG-FID-1
DAD D MOVE BACK
SHLD FRAD2 SET ADDRESS
RET
*
PAGE
*
*
*****************************************
*
*
*
* "LODRI" CHECK IF DEVICE FILE AND LOAD IF SO
*
LODRI LDA FTYPE GET FILE TYPE
STA UB RETURN TO CALLER IN "B"
INR A CHECK FOR DEVICE FILE
RNZ . ASSUMPTIONS SOMETIMES PROVE OUT
*
*
*
* LOAD A DEVICE DRIVER
*
*
* THE FILE IS A DEVICE FILE. IT'S TIME TO LOAD IT.
* THE DRIVER FILE IS AN IMAGE STRUCTURED FILE WHOSE
* FIRST LOAD ADDRESS IS THE DRIVER TABLE ADDRESS.
* ONLY A SINGLE BLOCK IS LAODED AND,OF COURSE, THE
* START ADDRESS, IF ANY, IS NOT PROCESSED.
*
*
*
LOD20 CALL PBUF PREPARE THE BUFFER AND SAVE UBC,UDE
*
* NOW READ THE BLOCK. THE FIRST FILE BLOCK CONTAINS
* THE COUNT AND LOAD ADDRESS SO IS SPECIAL.
*
LHLD FBDL
LXI D,-4
DAD D
JNC LER2 THE FILE DOESN'T EVEN HAVE FOUR BYTES!!
*
SHLD LCNT LCNT=FBDL-4
LHLD TBUFA CALCUALATE SOURCE ADDESS
LXI D,4
DAD D
SHLD SOU SOU=TBUF+4
*
* PICKUP COUNT AND LOAD ADDRESS
*
XCHG
DCX D BACKUP TO LAST BYTE OF ADDRESS
LDAX D
MOV H,A SET HIGH OF ADDRESS
DCX D
LDAX D
MOV L,A LOW OF ADDRESS
SHLD UDE SET LOAD ADDRESS
*
* NOW GET COUNT
*
DCX D
LDAX D
MOV H,A GET H OF COUNT
DCX D
LDAX D
MOV L,A GET L OF COUNT
SHLD UBC SET BLOCK COUNT
ORA H
JZ LER2 ERROR--ZERO BLOCK COUNT
*
* SAVE SIZE, LOAD ADDRESS FOR RETURN TO THE USER
*
PUSH H COUNT
LHLD UDE
PUSH H ADDRESS
XRA A
STA DELFG NO DELIMITER, PLEASE!
*
* NOW LOOP AND MOVE THE BLOCK
*
LOD30 LHLD UDE DESTINATION ADDEESS
SHLD DEST SET IT
LHLD LCNT
XCHG . DE HAS LOCAL COUNT
LHLD UBC HL HAS GLOBAL COUNT
CALL MBLK
LHLD UBC CHECK FOR LOAD COMPLETED
MOV A,H
ORA L
JZ LOD40 COMPLETED--COUNT NOW ZERO
*
* READ IN NEXT BLOCK AND SET UP TRANSFER
*
LHLD FBLKS
CALL RDNB READ NEXT BLOCK
JMP LER3 EOF, ERROR
LHLD TBUFA
SHLD SOU SET SOURCE TO BUFFER
LHLD FBDL
SHLD LCNT SET LOCAL OUNT
JMP LOD30 MOVE NEXT BUFFER LOAD
*
*
* NEXT SET THE DRIVER ADDRESS IN THE FCB AND THROW
* AWAY THE BUFFER USED TO READ THE FILE.
*
LOD40 POP H ADDRESS WAS THE THE STACK,REMEMBER
PUSH H BUT KEEP IT
SHLD FDRIV
CALL CLBUX CLOSE OUT BUFFER
*
* GET NEW BLOCK SIZE FOR DEVICE AND REPROCESS BUFFER
*
LHLD FDRIV
LXI D,DTBLK
DAD D HL POINTS TO BLOCK SIZE
MOV E,M
INX H
MOV D,M GOT IT IN DE
XCHG
SHLD FBLKS SET NEW BLOCK SIZE
CALL OBUF OPEN A BUFFER
NOP . YES THESE ARE REQUIRED.....
NOP
NOP
*
* FINALLY SET UP THE FCB FOR USE
*
LXI H,0
SHLD FNBD NBD=0
SHLD FBDL BDL=0
SHLD FINDX INDEX PTR TO ZERO
DCX H MINUS ONE
SHLD FBACK BACK IS BOF
MOV A,H
STA FUNIT SET UNIT=255
LXI H,EOFCD
SHLD FFORE FORE IS EOF
*
* SET UBC,UDE TO REPORT BACK TO CALLER
*
POP H FROM STACK
SHLD UDE
POP H AREN'T STACKS WONDERFUL
SHLD UBC
*
* INITIALIZE THE DRIVER
*
CALL DVBR INITIAL ENTRY
DB DTINI
*
RET
*
*
* ERRORS ERRS ERS
*
LER2 CALL ERRL1 BAD DRIVER--ZERO COUNT
DB ERZBC
*
LER3 CALL ERRL1 BAD DRIVER--EOF
DB EREOF
*
******************
*
*
*
* DISK DRIVER INTERFACE TO SYSTEM
*
*
DDRIV DW DDRBL READ BLOCK
DW DDRNB READ NEXT BLOCK
DW DDRLB READ LAST BLOCK
DW DDWBR WRITE/READ BLOCK
DW DDWBL WRITE BLOCK
DW DDREW REWIND
DW DDEOF ENDFILE
DW DDCLO CLOSE
DW DDSEK SEEK
DW DDCTL CONTROL
DW 0 BUFFER SIZE
DB 0 ITO (DO NOT CHANGE)
DW DDCLO INITIALIZE
DDCLO RET
*
IDAC CALL ERRL1 ILLEGAL DRIVER OPERATION
DB ERIDA
*
PAGE
*
*
*******************************************
*
*
*
*
* FILE READ/WRITE PROCESSER
*
* USER A - HAS FILE NUMBER
* USER BC - HAS TRANSFER COUNT
* USER DE - HAS SOURCE/DESTINATION ADDRESS
* USER L - DELIMITER (IF DREAD OR DWRITE ENTRY)
*
* USES RWF, SOU, DEST, LCNT FOR TEMP STORAGE
*
* ERRORS:
*
* ILLEGAL FILE NUMBER
* READ/WRITE PROTECTED FILE
* EOF
* DISK FULL
* OTHER, MORE SERIOUS ERRORS
*
* DELIMITED READ ENTRY POINT
*
DREAD MVI A,-1 DEFLG GETS THIS RWF GETS 0
JMP RWP00 SET THE TWO FLAGS
*
* WRITE ENTRY POINT
*
WRITE XRA A
RWP00 STA DELFG SET DELIMETER
CMA . NOW INVERT THE FLAG
JMP RWP02 AND SET THE READ/WRITE FLAG
*
* DELIMITED WRITE ENTRY POINT
*
DWRITE MVI A,-1
JMP RWP01
*
* READ ENTRY POINT
*
READ XRA A =0
RWP01 STA DELFG THE DELIMITED FLAG
RWP02 STA RWF THE READ/WRITE FLAG
*
* PREPARE FCB, ETC.
* READ ENTRY POINT
*
CALL PFCB PREPARE THE FCB
*
* CHECK PROTECTION
*
RWCON LDA RWF
ORA A
JZ RWP10 READ
*
* CHECK AND REPORT WRITE PROTECT
*
CALL PROTST
DB PWRI
JMP RER0 ERROR - WRITE PROTECT
JMP RWP20 OK
*
* CHECK AND REPORT READ PROTECT
*
RWP10 CALL PROTST
DB PREA
JMP RER0 ERROR - READ PROTECTION
LHLD UBC
XCHG . DE = COUNT
LHLD UDE HL = ADDRESS
CALL MEMCHK CHECK FOR WRITE INTO PROTECTED MEMORY
*
* PREPARE BUFFER
*
RWP20 CALL PBUF
* SET UP TRANSFER OR RESTART AFTER NEW BUFFER LOAD
RWP22 LHLD FNBD GET NEXT BYTE DISPLACEMENT
XCHG
LHLD TBUFA BUFFER ADDRESS
DAD D HL = BUFF+NBD = SOURCE
XCHG
LHLD UDE = USER ADDRESS
LDA RWF = READ/WRITE FLAG
ORA A
JZ RWP25 READ
*
* WRITE, INTERCHANGE SOURCE AND DEST
*
XCHG
*
RWP25 SHLD DEST SAVE DEST
XCHG
SHLD SOU AND SOURCE
LHLD FNBD
XCHG . DE MUST HAVE FNBD FOR RWP26
LHLD FBLKS = BLOCK SIZE
*
* IF WRITE, USE BLOCKSIZE AS BDL, ELSE BDL
*
JNZ RWP26
LHLD FBDL
*
* DE HAS NBD, HL HAS BDL OR BLOCK SIZE
* COMPUTE HL-DE AS LOCAL COUNT
*
RWP26 CALL ARITH HL=HL-DE
SHLD LCNT SAVE LOCAL COUNT
XCHG . DE HAS LOCAL COUNT
*
* TEST IF COUNT IS ZERO (DE HAS LCNT)
*
RWP30 LHLD UBC
MOV A,H
ORA L
JZ RWP70 YES, COUNT IS 0 --DONE
*
* SEE IF DELIMITER SEEN
*
LDA DELFG
DCR A
JZ RWP70 YES!, STOP TRANSFER
*
* TEST IF LOCAL COUNT IS ZERO
*
MOV A,D
ORA E
JNZ RWP50 NON-ZERO, MOVE DATA
*
* LOCAL COUNT IS ZERO
*
CALL UPBDL UPDATE BDL
LDA RWF
ORA A READ OR WRITE?
JNZ RWP40 WRITE
* READ
LHLD FBLKS READ
CALL RDNB READ NEXT BLOCK
JMP EOFER EOF HIT
JMP RWP22 CONTINUE THE READ
*
*
* WRITE
*
RWP40 LHLD FBDL
CALL WDBR WRITE BLOCK
JMP RWP22 AND ONWARD
*
*
* COUNT IS ZERO, OPERATION IS COMPLETE
* UPDATE BDL IF NECESSARY
*
* WE CAN ALWAYS CALL FDB EVEN IF OPER=READ
* IF WE ASSUME READ DIDN'T SET DIRTY
*
RWP70 CALL UPBDL
CALL FDB YES, FLUSH DEVICE BUFFER
CALL RBUF RELEASE BUFFER
JMP NRET NORMAL RETURN WHEN DONE
*
*
* UPDATE BDL
*
UPBDL LHLD FBDL
XCHG
LHLD FNBD
CALL COMP CHECK BDL AND NBD
RNC . BDL GE NBD
SHLD FBDL UPDATE BDL
RET
*
*
* SET DIRTY IF WRITING
*
RWP50 CALL MBLK
LHLD LCNT
XCHG . DE GETS NEW LOCAL COUNT FOR LATER
LDA RWF
ORA A
JZ RWP30 NOT WRITE
STA FFLAG IT'S WRITE SET DIRTY FLAG
JMP RWP30
*
*********************
*
* CALCULATE HL = HL-BC
*
RWPS MOV A,L
SUB C
MOV L,A
MOV A,H
SBB B
MOV H,A
RET
*
*
* CALCULATE HL = HL-DE
*
ARITH MOV A,L
SUB E
MOV L,A
MOV A,H
SBB D
MOV H,A
RET
*****************************************
*
*
* CHECK FOR READ OR BUFFER IN PROTECTED AREAS
*
* ON CALL HL HAS START ADDRESS
* DE HAS COUNT
*
* ON RETURN, ALL REGISTERS DESTROYED; ABORT IF ERROR
*
MEMCHK DCX D LOWER COUNT FOR PROPER TESTS
PUSH D SAVE COUNT
LXI D,SYSTOP TOP OF SYSTEM
CALL COMP DO COMPARE
POP D
JNC MEMC0 IF START ADDRESS LESS THAN TOP OF SYSTEM
*
* START IS ABOVE SYSTEM. OK IF IT DOESN'T PASS ZER0
*
DAD D HL= TOP OF WRITE
MOV A,H GET HIGH BYTE
ORA A
RM . STILL MINUS....OK
*
MERR1 CALL ERRL1
DB ERMEM USER MEMORY PROTECT ERROR
*
MEMC0 PUSH H ADDRESS
PUSH D COUNT
DAD D HL GETS HIGEST USED ADDRESS
XCHG . TO DE
LHLD LOWAD GET LOWEST SYSTEM ADDRESS
CALL COMP
POP H COUNT TO HL
POP D START ADDRESS
MOV B,H
MOV C,L SAVE COUNT IN BC
JC MEM10 DE .LT. LOWAD OK STILL
*
* ATTEMPTING TO WRITE INTO SYSTEM..SEE IF CBUF
*
LXI H,CBUF
CALL COMP DE HAS WRITE ADDRESS
JNZ MERR2 IF IT WASN'T CBUF
*
* NOW TEST COUNT FOR 256 OR LESS
*
LXI H,-256
DAD B BC = COUNT
RNC . IF COUNT .LT. 256
*
MERR2 CALL ERRL1
DB ERSMP SYSTEM MEMORY PROTECT
*
*
* SEE IF ABOVE USER PROTECT
*
MEM10 LHLD UPROT DE HAS MEMORY WRITE START
CALL COMP
RNC . HL .GE. DE (START <= UPROT ), OK
JMP MERR1 USER MEMORY PROTECT
*
*
*********************
*
*
* MOVE DATA
*
* COME HERE WITH LOCAL COUNT IN DE, GLOBAL IN HL
*
MBLK CALL COMP
JNC RWP52 DE => HL, USE GLOBAL COUNT
XCHG . USE LOCAL COUNT
*
RWP52 CALL CKDEL CHECK FOR DELIMITER
MOV B,H
MOV C,L COUNT IN BC
*
LHLD UDE UPDATE NUMBERS
DAD B
SHLD UDE SOU/DEST ADDRESS
LHLD UBC
CALL RWPS
SHLD UBC USER COUNT
LHLD LCNT
CALL RWPS
SHLD LCNT LOCAL COUNT
LHLD FNBD
DAD B
SHLD FNBD NBD
*
LHLD SOU
XCHG . DE HAS SOURCE
LHLD DEST HL HAS DESTINATION
JMP MOVEV BC HAS COUNT, MOVE AND RETURN
*
*********************
*
*
* CHECK FOR DELIMITER
*
* SET FLAG IF FOUND
* HL = COUNT
* RETURN, HL = POSSIBLY REDUCED COUNT, DELFG SET
*
CKDEL LDA DELFG
ORA A SEE IF CHECKING FOR DELIMITERS AT ALL
RZ . NO
PUSH H
XCHG
LHLD SOU HL -> DATA, DE = MAX COUNT
*
* LOOP FOR END OF COUNT OR DELIMITER
*
CKD20 MOV A,D TEST IF OUT OF COUNT
ORA E
JZ CKD30
*
DCX D ACCOUNT FOR THIS ONE
LDA UL = DELIMITER
CMP M
JZ CKD50 FOUND!
INX H
JMP CKD20 LOOP
*
* END OF COUNT... NOT FOUND
*
CKD30 POP H RESTORE COUNT
RET
*
*
* FOUND, COMPUTE UPDATED COUNT
*
CKD50 POP H
MOV B,D
MOV C,E DECREMENTED COUNT IN BC
CALL RWPS HL=HL-BC
MVI A,1
STA DELFG SET FLAG
RET . ALL SET
*
PAGE
*
*
*******************************************
*
*
*
*
* READ SINGLE BYTE OPERATION
*
* "A" HAS THE FILE NUMBER
*
* THIS OPERATION USES THE USER STACK. THE
* STANDARD ENTRY AND EXIT ROUTINES ARE NOT USED.
*
* ERRORS:
* ILLEGAL FILE NUMBER
* PROTECTED FILE
* EOF
*
RB CALL RWPREP SAVE A BUNCH OF JUNK AND PREPARE
CALL PROTST CHECK IF PROTECTED
DB PREA
*
JMP RER0 ERROR - PROTECTED
CALL PBUF PREPARE BUFFER
*
* CHECK IF BUFFER EMPTY
*
LHLD FNBD
XCHG
LHLD FBDL BBD BDL
CALL COMP COMPARE DE HL
JC RB50 NBD LT BDL, OK
*
* FILL BUFFER
*
LHLD FBLKS
CALL RDNB
JMP RBEOF
*
* LOAD BYTE AND UPDATE NBD
*
RB50 CALL UPNBD GET THE BUFFER ADDRESS AND COUNT UP
MOV A,M
STA UA SAVE BYTE
CALL RBUF RELEASE BUFFER
CALL RFCB RESTORE FCB
LDA UA RETURN WITH BYTE IN A
*
*
* EVERYONE COMES HERE FOR CALL+2
* RETURN THROUGH HL
*
RP2 POP H
RP3 INX H
INX H
INX H
PCHL . NORMAL RETURN
*
*
* PROTECTED
*
RER0 CALL ERRL1
DB ERPRO
*
*********************
*
*
* PREPARE FOR READS AND WRITES
*
RWPREP STA UA SAVE FILE NUMBER IN USER A
MOV A,B
STA UB WRITE USES THIS
LXI H,0
SHLD WBUFSZ CLEAR DANGLING BUFFER FLAG
DAD SP
INX H
INX H
SHLD UTOS SET UTOS FOR ERRORS
JMP PFCB PREPARE FCB AND RETURN
*
*
* UDATE NEXT BYTE DISPLACEMENT AND RETURN BUFFER ADDRESS
*
UPNBD LHLD FNBD GET NEXT BYTE DISPLACEMENT
INX H BUMP IT FOR THIS BYTE
SHLD FNBD
DCX H ADJUST COUNT TO POINT TO CURRENT POSITION
XCHG
LHLD TBUFA
DAD D HL = NBD + BUFF ADDRESS
RET
*
PAGE
*
*
*******************************************
*
*
*
*
* WRITE SINGLE BYTE OPERATION
*
* A HAS THE FILE NUMBER
* B HAS THE BYTE
*
*
* ON RETURN,
* A,B ARE UNCHANGED
*
* THIS OPERATION USES THE USER STACK. STANDARD ENTRY,
* EXIT, AND ERROR ROUTINES ARE NOT USED
*
* ERRORS:
* ILLEGAL FILE NUMBER
* PROTECTED FILE
* DISK FULL
*
*
*
WB CALL RWPREP PREPARE EVERYTHING
CALL PROTST CHECK PROTECTION
DB PWRI
JMP RER0 ERROR - PROTECTED
CALL PBUF PREPARE BUFFER
*
* CHECK FOR FULL BLOCK
*
LHLD FNBD
XCHG
LHLD FBLKS NBD BLOCK SIZE
CALL COMP COMPARE DE HL
JC WB50 NBD LT BLOCKSIZE
CALL WDBR BUFFER IS FULL...WRITE IT
*
* STORE BYTE, UPDATE NBD
*
WB50 CALL UPNBD
LDA UB
MOV M,A STORE BYTE
MVI A,1
STA FFLAG SET DIRTY
*
* UPDATE BDL IF NECESSARY
*
INX D
LHLD FBDL DE HAS NBD
CALL COMP
JC WB60 NBD LT BDL, LEAVE BDL ALONE
XCHG
SHLD FBDL UPDATE BOL
*
* FINISH UP
*
WB60 CALL FDB FLUSH BUFFER IF DEVICE FILE
CALL RBUF RESTORE BUFFER
CALL RFCB RESTORE FCB
LDA UB
MOV B,A SET B
LDA UA RESTORE A
JMP RP2
*
PAGE
*
*
*******************************************
*
*
*
*
* MOVE FILE POINTER OPERATION (SPACE)
*
* UA HAS FILE NUMBER
* UBC HAS DELTA VALUE
* UD= 0 FOR REWIND
* -1 FOR SPACE-TO-END
* 1 FOR SPACE FOREWARD
* 200(8) FOR SPACE BACKWARDS
* UL DELIMITER IF DSPACE
*
*
* ERRORS:
* ILLEGAL FILE NUMBER
* EOF/BOF
*
*
* DELIMITER SPACE ENTRY
*
DSPACE MVI A,-1
JMP SPA01
*
*
* STANDARD SPACE ENTRY
*
SPACE XRA A
SPA01 STA DELFG SETUP DELIMITER SCAN FLAG
CALL PFCB PREPARE FCB
CALL PBUF PREPARE BUFFER
CALL WDBUF FLUSH OUT ANYTHING
LDA UD
ORA A LOOK AT OPTIONS
JNZ SPA20 NOT REWIND
*
* D=0...REWIND FILE
*
LHLD FBLKS GET BLOCK SIZE
XCHG
LHLD TBUFA DE=COUNT, HL->BUFFER
CALL DVBR DO THE REWIND
DB DTREW
*
SHLD FBDL GOOD, SET BDL FROM HEADER COUNT
LXI H,0
SHLD FNBD
JMP SPA80
*
*********************
*
*
* (PART OF DISK INTERFACE) COME HERE TO REWIND DISK FILE
*
DDREW LHLD FCURSC CURRENT SECTOR AND TRACK
XCHG
LHLD FFBA FIRST SECTOR AND TRACK
CALL COMP CHECK IF CORRECT BLOCK IS IN
JZ REW10 YES
SHLD FCURSC SET AS CURRENT SECTOR
CALL RBLK PRIME WITH FIRST BLOCK
RET . HL HAS COUNT IN SECTOR
*
*
* CURRENT BLOCK IS IN
*
REW10 LHLD FBDL RETURN SIZE
RET
*
*
* SPACE FORWARD OR BACKWARD
*
SPA20 JP SPAF (S)HE WANTS FOREWARD
INR A
JNZ SPAB (S)HE WANTS BACKWARDS
*
* MOVE TO EOF
*
SPA22 LHLD FBLKS
CALL RDNB READ NEXT BLOCK
JMP SPA25 EOF
JMP SPA22 TRY AGAIN
*
*
SPA25 LHLD FBDL
SHLD FNBD SET NBD=BDL
JMP SPA80 GO QUIT
*
*
* SPACE FOREWARD
*
SPAF LHLD FNBD
XCHG . DE HAS NBD
LHLD FBDL HL HAS BDL
CALL ARITH HL=HL-DE
XCHG . DE HAS BDL-NBD
CALL UPCNT GET MAXIMUM COUNT TO HL
PUSH H
LHLD TBUFA COMPUTE -> DATA
XCHG
LHLD FNBD
DAD D -> DATA
SHLD SOU SET DATA SOURCE POINTER
POP H GET BACK COUNT
*
* IF DELIMITED, DO PRESCAN FOR DELIMITER
*
CALL CKDEL FIND NEW COUNT IF DELIMITED
XCHG . DE HAS MIN OF USER, LOCAL CNT.
LHLD FNBD
DAD D
SHLD FNBD UPDATE NBD
LHLD UBC
CALL ARITH HL=HL-DE= NEW USER COUNT
SHLD UBC UPDATE USER COUNT
*
* TEST FOR ZERO COUNT OR DELIMITER
*
ORA L "A" HAS "H" FROM ARITH
JZ SPA80 YES, GO QUIT
*
LDA DELFG CHECK IF DELIMITER SEEN
DCR A
JZ SPA80 YES, GO QUIT
*
* NO, MOVE TO NEXT BLOCK
*
CALL RDNB MOVE TO NEXT
JMP SEOF EOF
JMP SPAF
*
*********************
*
*
* FIND MIN OF UBC, AND DE INTO HL
*
UPCNT LHLD UBC
CALL COMP
RNC . HL GE DE
XCHG . DE LT HL
RET
*
*********************
*
* SPACE REVERSE
*
SPAB LHLD FNBD
SPABX XCHG . DE HAS NBD
LHLD UBC
CALL UPCNT HL GETS MIN OF DE,HL
*
* HL = MAX COUNT, THIS BUFFER
* SCAN BACKWARD FOR DEL
*
LDA DELFG
ORA A
JZ SPA69 NO DELIMITER TO LOOK FOR, SKIP THIS JUNK
*
* CHECK FOR DELIMITER BACKWARDS
*
PUSH H
MOV B,H
MOV C,L BC = MAX COUNT
LHLD TBUFA
XCHG
LHLD FNBD
DAD D HL -> BUFFER END (NEXT CHAR)
*
SPA60 MOV A,B
ORA C CHECK FOR ZERO COUNT
JZ SPA63 YES, END OF BUFFER, NOT FOUND
DCX H
LDA UL = DELIMITER
CMP M
DCX B
JNZ SPA60 TRY AGAIN
INX B RESTORE THE COUNT
*
* FOUND THE DELIMITER...TIME TO QUIT
*
SPA65 POP H
CALL RWPS HL = HL - BC
MVI A,1
STA DELFG SET DELIM FOUND FLAG
*
* UPDATE NBD
*
SPA69 XCHG . BUFFER ADDRESS TO DE
LHLD FNBD OLD BUFFER DISPLACEMENT
CALL ARITH HL=HL-DE
SHLD FNBD
*
* UPDATE USER COUNT (UBC)
*
LHLD UBC
CALL ARITH HL=HL-DE
SHLD UBC
ORA L IS COUNT ZERO? A HAS H FROM ARITH
JZ SPA80 YES, GO QUIT
*
LDA DELFG
DCR A
JNZ SPA81 DELIMITER NOT FOUND
*
* DONE, END OF COUNT OR DELIMITER FOUND
*
SPA80 CALL RBUF RELEASE BUFFER
JMP NRET
*
*
* READ LAST SECTOR
*
SPA81 LHLD FBLKS
XCHG
LHLD TBUFA
CALL DVBR READ LAST BLOCK
DB DTRLB
*
JMP SEOF EOF
SHLD FBDL SET SIZE
SHLD FNBD AND PTR TO END
JMP SPABX CONTINUE
*
*
* NOT FOUND IN THIS BUFFER
*
SPA63 POP H
JMP SPA69 MAKE LIKE NOTHING HAPPENED
*
*
* EOF
*
SEOF CALL RBUF
CALL ERRL2 ERROR
DB EREOF
*
EOFER EQU SEOF
RBEOF EQU SEOF
*
PAGE
*
*
*******************************************
*
*
*
*
* CLOSE FILE OPERATION
*
* UA HAS FILE NUMBER
* THE FCB IS RELEASED
*
* ERRORS:
* ILLEGAL FILE NUMBER
*
*
*
CLOSE LDA UA GET FILE NUMBER
LXI H,SYSFIL
CMP M
JC NRET OK, IT'S DONE BUT NOT SO!!!
CALL PFCB
CALL CLOSIT CLOSE THE FILE
JMP NRET DONE
*
*********************
*
*
* CLOSE FILE SUBROUTINE
*
* COME HERE WITH CURRENT FCB SET
*
CLOSIT CALL CLBUF CLOSE BUFFER
LHLD FDLTA
MOV A,H
ORA L NO CHANGE... NOT NEEDED
JZ CLO30
LHLD FID
CALL SDIRX SEARCH DIRECTORY BY ID
*
* UPDATE FILE SIZE
*
LHLD DBUF
LXI D,DENBL-DEBUF DISPLACEMENT TO SIZE
DAD D
XCHG
LHLD FDLTA GET NUMBER BLOCKS ALLOCATED
LDAX D
ADD L UPDATE
STAX D FILE
INX D SIZE
LDAX D IN
ADC H BLOCKS
STAX D
CALL WDSK REWRITE DIRECTORY
*
CLO30 LXI H,0
SHLD FID RELEASE THE FILE CONTROL BLOCK
RET
*
*********************
*
*
* WRITE DIRTY BLOCK AND DEALLOCATE BUFFER
*
CLBUF LHLD FBUFA
INX H
MOV A,H
ORA L
RZ . UNBUFFERED, NOTHING TO DO
DCX H
SHLD TBUFA SET TBUFA FOR UTILITIES
CALL WDBUF FLUSH BUFFER
CALL DVBR TAKE CLOSE DRIVER
DB DTCLO ENTRY
*
* COME HERE TO JUST RELEASE BUFFER
*
CLBUX LHLD FBUFA
INX H
MOV A,H
ORA L
RZ . UNBUFFERED, QUIT
DCX H
XCHG . DE HAS BUFFER ADDRESS
LHLD MINAD HL HAS BOTTOM OF SYS GLOBAL
CALL COMP
RC . DE LT HL, USER BUFFER
LXI H,SYSTOP NOW TOP OF SYSTEM
CALL COMP
RNC . DE GT HL USER BUFFER
*
* RELEASE BUFFER
*
LHLD FBLKS
XCHG . DE HAS SIZE, HL HAS ADDRESS
CALL DLBUF DEALLOCATE BUFFER
RET
*
PAGE
*
*
*******************************************
*
*
*
* CLOSE MULTIPLE FILES
*
* UA = UNIT #<0-254> CLOSE ALL ON UNIT SPECIFIED
* = 255 CLOSE ALL OPEN FILES
*
* ERRORS: NONE OTHER THAN DISK
*
*
CA MVI A,0
STA CLCNT COUNT UP FROM ZERO THROUGH FCB'S
LHLD FCBASE START AT FIRST FCB
*
* LOOP HERE WITH NEXT FCB (PNTR ON TOS)
*
CA20 PUSH H SAVE FCB POINTER
*
* SEE IF FILE # < SYSFIL
*
LXI H,SYSFIL
LDA CLCNT
CMP M IS FILE# < SYSFIL?
JC CA50 YES, SKIP
POP H
PUSH H RESTORE HL
*
* CHECK FILE ID FOR A OPEN FILE FCB (REAL? OOOBOY)
*
LXI D,FID-FCBORG
DAD D MOVE TO FID BYTES
MOV A,M
INX H
ORA M CHECK IF ID=0
JZ CA50 YES, SKIP IT
*
* CHECK IF DESIRED UNIT
*
LXI D,FUNIT-FID-1
DAD D MOVE TO UNIT NUMBER
LDA UA
CPI 255 CLOSE ALL
JZ CA30 YES
CMP M CHECK IF THIS UNIT
JNZ CA50 NOT THE ONE, LEAVE OPEN
*
* CLOSE CURRENT FILE
*
CA30 POP H GET POINTER TO FCB
PUSH H
CALL PFC6 SETUP FCB
CALL CLOSIT CLOSE THE FILE
CALL RFCB RESTORE FCB
*
* MOVE TO NEXT FILE
*
CA50 LXI H,CLCNT --> COUNTER
INR M COUNT UP
LDA NFCB = # OF FCB'S
CMP M HAVE WE DONE EM ALL?
JZ NRET YES, DONE
*
* STILL MORE
*
POP H
LXI D,LNFCB
DAD D MOVE TO NEXT FILE
JMP CA20 AND LOOP
*
PAGE
*
*
*******************************************
*
*
*
* ENDFILE OPERATION
*
* UA HAS FILE NUMBER
*
* ERRORS:
* ILLEGAL FILE NUMBER
* PROTECTED FILE
*
*
EOF CALL PFCB PREPARE FCB
CALL PROTST
DB PWRI
JMP RER0 ERROR - PROTECTED FILE
CALL PBUF PREPARE BUFFER
LHLD FNBD
SHLD FBDL SET BDL TO CURRENT POINTER
XCHG
LHLD TBUFA DE=CT, HL=BUF
CALL DVBR CALL DRIVER
DB DTEOF
*
EOF1A CALL WDB50 CLEAR THE DIRTY FLAG
CALL RBUF RELEASE BUFFER
JMP NRET RETURN
*
*********************
*
*
* DISK FILE CLOSE (PART OF DISK INTERFACE)
*
DDEOF LHLD FID
CALL SFCBS
JMP RER0 OPEN MORE THAN ONCE, ERROR
JMP EOF10 OPEN ONCE, OK
*
EOF10 LHLD FFORE
SHLD ETMP SAVE FORE PTR
LHLD FNBD
SHLD FBDL SET BDL,ALSO
MOV A,H
ORI 128 SET HIGH BIT
MOV H,A
SHLD FFORE SET EOF AND BYTE COUNT
LHLD FCURSC
SHLD ECRS SAVE CURRENT SECTOR
CALL WBLK WRITE BLOCK
*
* RELEASE ALL BLOCKS PAST THIS ONE
*
LHLD ETMP
SHLD FFORE RESTORE FORE PTR
*
EOF20 CALL DDRNB MOVE TO NEXT BLOCK
JMP EOF50 EOF, DONE
CALL RFBLK RELEASE BLOCK
JMP EOF20 MOVE TO NEXT
*
*
EOF50 LHLD FINDX GET INDEX FILE
MOV A,H IS THERE AN INDEX
ORA L
JZ EOF60 NO, DONE
CALL RBUF RELEASE BUFFER
CALL RFCB YES,RESTRE FCB, THEN
JMP RNDOM UPDATE INDEX
*
*
EOF60 LHLD FCURSC TEST IF AT CORRECT BLOCK
XCHG
LHLD ECRS
CALL COMP
JZ EOF70 DON'T READ
SHLD FCURSC
CALL RBLK RESTORE CURRENT BLOCK
SHLD FBDL SET BDL
*
EOF70 LHLD FBDL
SHLD FNBD SET NBD
JMP EOF1A
*
*
EOFE0 EQU RER0 PROTECTED FILE
*
*
PAGE
*
*
*******************************************
*
*
*
*
* FILE INFORMATION REQUEST OPERATION
*
*
* UDE POINTS TO NAME
* UHL HAS DATA BLOCK ADDRESS
*
* ERRORS:
* FILE DOES NOT EXIST
* FILE IS PROTECTED
*
*
FINFO LHLD UDE
CALL SDIR SEE IF NAME EXISTS
JMP FIN90 WE RETURN HERE IF NOT
*
* IT EXISTS.....CHECK FOR OVERWRITE INTO SYSTEM
*
LXI D,DRESZ+3 SIZE
LHLD UHL USER SPECIFIED ADDRESS
CALL MEMCHK
*
* OK, COPY DIREC ENTRY
*
LXI D,DEFID -> FILE ID
LHLD UHL HL POINTS TO USER AREA
CALL MOVEF MOVE
DB DENBL-DEFID+2 THIS MANY WORDS
*
LXI D,DETYP -> FILE TYPE
LHLD UHL
LXI B,DENBL-DEFID+3+2
DAD B
CALL MOVEF MOVE CREATE PARM PART
DB DEPRO-DETYP+1
*
LHLD DBUF -> NAME
XCHG
LHLD UHL
LXI B,DENBL-DEFID+3+2+DEPRO-DETYP+1
DAD B
CALL MOVEF MOVE NAME
DB NMLEN
*
* SEE IF FILE IS OPEN
*
LHLD DBUF
LXI D,DEFID-DEBUF
DAD D HL POINTS TO FILE ID
MOV E,M
INX H
MOV D,M
XCHG . HL HAS FILE ID
CALL SFCBS SEARCH....TRIPLE LEVEL RETURN
JMP FIN20 YES
JMP FIN20 YES
XRA A NO
JMP FIN21
*
*
* "A" HAS NUMBER OF FCBS
*
FIN20 MVI A,1 YES
FIN21 LHLD UHL STORE A 1 PAST DIREC ENTRY
LXI D,DENBL-DEFID+3
DAD D
MOV M,A
XRA A =0
LXI D,NMLEN+DEPRO-DETYP+1+1+1
DAD D
MOV M,A PUT ZERO BYTE AFTER NAME
JMP NRET ALL DONE
*
*
FIN90 CALL ERRL2
DB ERNEX NONEXISTENT
*
PAGE
*
*
*******************************************
*
*
*
*
* ALTER FILE CHARACTERISTICS OPERATIONS
*
*
* USER DE ALWAYS POINTS TO NAME
*
*
*
* CHANGE FILE TYPE OPERATION
*
* ON CALL USER H HAS NEW TYPE
*
* ERRORS:
* FILE DOES NOT EXIST
* FILE IS PROTECTED
*
CHTYP CALL FFILE CHECK FOR PROTECTION (NAME AND TYPE)
DB PNAT
LDA UH
STA DETYP CHANGE TYPE
JMP UWFIL FINISH UP
*
*********************
*
*
* CHANGE ATTRIBUTES OPERATION
*
* USER H HAS NEW ONES
*
CHATR CALL FFILE
DB PATR
LDA UH
STA DEPRO SET NEW PROTECTION
JMP UWFIL
*
*********************
*
*
* CHANGE NAME OPERATION
*
* USER HL POINTS TO NEW NAME
*
CHNAM LHLD UHL
CALL SDIR SEE IF NEW NAME EXISTS
JMP CHN20 NO
CALL ERRL1 YES
DB ERAEX FILE ALREADY EXISTS
*
*
CHN20 LDA FUNIT GET DEFAULT UNIT
PUSH PSW
CALL FFILE SET UP
DB PNAT
*
* MOVE IN NEW NAME
*
POP H H=UNIT
LDA FUNIT
CMP H SAME?
JNZ CHER1 NO, UNIT CONFLICT
LHLD UHL
CALL NAMIN READ IN NAME
*
* UPDATE DIRECTORY ENTRY FROM DEBUF, THEN
* REWRITE DIRECTORY SECTOR AND RETURN.
*
UWFIL LXI D,DEBUF
LHLD DBUF
CALL MOVEF MOVE ENTRY BACK
DB DRESZ
CALL WDSK WRITE IT OUT
JMP NRET THEN GO.
*
*
* SEARCH FOR FILE AND SET UP
*
FFILE LHLD UDE HL POINT TO NAME
CALL SDIR
JMP KIL90 NONEXISTENT
POP H
LDA DEPRO
ANA M
INX H
JNZ CHER0 ERROR...PROTECTED
PCHL . OK, RETURN CALL+1
*
*
CHER0 CALL ERRL1 ERROR
DB ERPRO
*
CHER1 CALL ERRL1 UNIT CONFLICT
DB ERUCN
*
PAGE
*
*
*******************************************
*
*
*
*
* SEEK OPERATION
*
*
* USER A HAS FILE NUMBER
* USER B = 0 => HL = BYTE#
* <> 0 => HL = BLOCK#
* USER HL HAS REQUESTED BYTE NUMBER
*
* ERRORS:
* DEVICE FILE
* FILE NOT RANDOM
* TOO FAR IN FILE
* EOF
*
*
SEEK CALL PFCB
CALL PBUF PREPARE BUFFER
LHLD UHL
PUSH H SAVE SEEK ADDRESS
LHLD FBLKS
XCHG
LHLD TBUFA
LDA UB GET BLOCK OPTIONS
CALL DVBR
DB DTSEK GO SEEK
JMP SEKE1 OUT OF RANGE
* CALL TO DVBR RETURNS HERE IF OK
SHLD FBDL SET BDL
XCHG
SHLD FNBD AND NBD
CALL RBUF DONE
JMP NRET
*
*********************
*
*
* DISK INTERFACE FOR SEEK
*
* CHECK IF RANDOM INDEX EXISTS
* THEN READ IT INTO DIRECTORY BUFFER IF NOT ALREADY IN
* MEMORY
*
DDSEK LHLD FAIND SEE IF INDEX IN MEMORY
SHLD RINAD ASSUME LOADED
INX H (ITS -1 IF NOT)
MOV A,H
ORA L
CZ RINDX LOAD AND SET RINAD IF NOT
*
* COMPUTE QUOTIENT AND REMAINDER OF UHL/FBLKS
*
LHLD FBLKS
MOV B,H
MOV C,L BC IS BLOCK SIZE
POP H =RETURN ADDRESS
XTHL . HL=SEEK POINT, STACK= RETURN ADDRESS
LXI D,0 DE HAS QUOTIENT..IT WILL,IT WILL
*
* CHECK FOR SEEK BLOCK
*
LDA UB GET OPTION...BLOCK OR BYTE
ORA A
JZ SEK10 NO BYTE
XCHG . DE = BLOCK#
LXI B,0
LXI H,0 SET SO NBD = 0 EVENTUALLY
JMP SEK20
*
*
* GO TO INDIVIDUAL BYTE
*
SEK10 CALL RWPS HL = HL - BC
INX D
JNC SEK10
DCX D
*
* GOT IT
*
SEK20 MOV A,D
ORA A
RNZ . ERROR, REQUESTED BLOCK .GT. 256
MOV A,E
CPI 250
RNC . ERROR, ITS GE 250
DAD B HL IS REMAINDER
PUSH H SAVE IT AS FUTURE NBD
*
* NOW FETCH INDEX ENTRY
*
LHLD RINAD -> INDEX BLOCK
DAD D
DAD D HL POINTS TO APPROPRITE ONE
*
* PICK IT UP
*
MOV E,M
INX H
MOV D,M
PUSH D SECTOR/TRACK OF DISK ADDRESS
PUSH H INDEX BLOCK ADDRESS
LHLD FCURSC GET CURRENT SECTOR/TRACK
CALL COMP COMPARE
PUSH PSW SAVE FLAGS FOR LATER
CNZ WDBUF WRITE OUT DIRTY BUFFER IF NOT SAME ADDRESS
POP PSW
POP D INDEX ADDRESS
POP H DISK ADDRESS
PUSH PSW
*
* IS DISK ADDRESS IN EXISTENCE YET
*
MOV A,H
ORA L
JZ SEX NO, PAST EOF ERROR, PROBABLY
*
* HL HAS ADDRESS OF NEW CURRENT BLOCK, NBD ON TOP OF STACK
*
SHLD FCURSC SAVE AS CURRNT ADDRESS
POP PSW
LHLD FBDL IN CASE WE DON'T READ IN THE BLOCK
CNZ RBLK READ NEW BLOCK
POP D
*
* DE=NBD, HL=BDL; CHECK NBD .LE. BDL
*
CALL COMP
JZ RX2 OK, WE'RE AT THE EOF
JC RX2 OK, WE'RE NOT AT THE EOF, BUT IN THE FILE
RET . EOF ERROR, WE'VE GONE TOO FAR
*
*********************
*
*
* THERE ARE SOME NASTY SPECIAL CASES ABOUT SEEKING
* TO THE END OF FILE. IT IS OK TO SEEK TO LAST BYTE +1,
* BUT, UNFOUTUNATELY, A SPECIAL TEST MUST BE MADE TO
* FORCE THE CURSOR INTO THE LAST LEGAL BLOCK INSTEAD
* OF THE NEXT, NOT-YET-EXISTENT BLOCK.
*
* ADDRESS DIDN'T EXIST, SEE IF ALTERNATE ADDRESS AT
* END OF LAST BLOCK APPLIES.
*
* FIRST, SETUP FOR PREVIOUS SECTOR
*
SEX XCHG . HL -> 1 BEYOND CURRENT
DCX H
DCX H
POP PSW
MOV A,M FOR H LATER
DCX H
MOV L,M
MOV H,A
ORA L TEST FOR EXISTENCE
POP D KEEP STACK CLEAN
RZ . NO, WE'RE DEFINITLY BEYOND EOF
SHLD FCURSC WELL, MAYBE OK, LAST BLOCK EXISTS
*
* SEE IF NBD WAS ZERO, IF SO, COULD ALSO USE BDL OF LAST BL
*
MOV A,D
ORA E
RNZ . NOT ZERO, OUT OF RANGE
*
* OK, LOAD LAST BLOCK, SET NBD=BDL, BUT ERR IF NOT FULL
*
CALL RBLK
XCHG
LHLD FBLKS BDL MUST = BLOCK SIZE, ELSE OUT OF RANGE
CALL COMP
JZ RX2 OK
RET . NO, GO BACK WITH ERROR
*
*
SEKE0 CALL ERRL1 FILE NOT RANDOM
DB ERRAC
*
SEKE1 CALL ERRL1 SEEK ADDRESS OUT OF RANGE
DB ERSEK
*
*********************
*
*
* READ FILE INDEX
*
* ENTER AT RINDX TO READ INTO DIBUF
* ENTER AT RINDY WITH HL -> WHERE TO LOAD
* LOAD INDEX AND SET RINAD TO -> INDEX IN EITHER CASE
*
RINDX LXI H,DIBUF
RINDY SHLD RINAD SET LOAD ADDRESS
LHLD FINDX INDEX ADDRESS
MOV A,H
ORA L
JZ SEKE0 ITS ZERO, ERROR
*
CALL STDAD SET XFER DESC....
LHLD FINDX
SHLD TDAD
LXI H,SECTSZ BLOCKSIZE IS 500 OR ELSE
SHLD TBCNT
LHLD RINAD
SHLD TBUF READ INTO SPECIFIED ADDRESS
JMP RDSK READ INDEX AND RETURN
*
PAGE
*
*
*******************************************
*
*
*
* MAKE FILE RANDOM OPERATION
*
*
* CREATE IF NECESSARY AND UPDATE INDEX BLOCK
*
*
* USER A HAS THE FILE NUMBER
*
* ERRORS:
* DEVICE FILE
*
*
RNDOM CALL PFCB PREPARE FCB
LDA FTYPE CHECK FOR DEVICE FILE
INR A
JZ RNER0 YES...ERROR
CALL PBUF PREPARE BUFFER
CALL WDBUF CLEAN IT UP
*
* READ FIRST BLOCK
*
LHLD FFBA
SHLD FCURSC
CALL RBLK
*
* ZERO THE DIRECTORY BUFFER..DIBUF
*
MVI D,0
LXI B,SECTSZ COUNT=SECTSZ
LXI H,DIBUF
SHLD RNPTR RNPTR IS ''DIBUF''
*
RND10 MOV M,D ZERO A WORD
INX H
DCX B COUNT DOWN
MOV A,B
ORA C
JNZ RND10
*
* CHECK IF FILE ALREADY HAS AN INDEX
*
LHLD FINDX
MOV A,H
ORA L
JNZ RND20 YES...
*
* ALLOCATE AN INDEX BLOCK FOR THE FILE
*
LHLD FBLKS
PUSH H SAVE BLOCK SIZE
LXI H,SECTSZ
SHLD FBLKS
CALL AFBLK ALLOCATE INDEX BLOCK
SHLD FINDX SAVE ITS ADDRESS
POP H
SHLD FBLKS RESTORE BLOCK SIZE
*
* NOW READ THROUGH THE FILE AND NOTE THE ADDRESS
* OF EACH BLOCK IN THE INDEX
*
RND20 MVI A,250
STA RNCNT 250 MAX
*
* DO NEXT BLOCK
*
RND30 LHLD FCURSC
XCHG
LHLD RNPTR
MOV M,E STORE CURENT SECTOR ADDRESS
INX H
MOV M,D INTO MAP
INX H
SHLD RNPTR UPDATE MAP POINTER
LDA RNCNT
DCR A DECREMENT COUNT
STA RNCNT
JZ RND35 DONE 128, MOVE TO EOF
*
* MOVE TO NEXT BLOCK
*
CALL DDRNB
JMP RND40 EOF, DONE
JMP RND30
*
*
* SPACE UNTIL EOF
*
RND35 CALL DDRNB
JMP RND40 EOF
JMP RND35 MOVE TO NEXT BLOCK
*
* NOW WRITE OUT MAP...ID IS SET IN TFID.,SO IS UNIT
*
RND40 SHLD FBDL
SHLD FNBD SET AT EOF
LHLD FINDX
SHLD TDAD
LXI H,DIBUF
SHLD TBUF
LXI H,SECTSZ GET STANDARD SECTOR SIZE
SHLD TBCNT
CALL WDSK
*
* UPDATE INDEX SAVED IN MEMORY, IF ANY
*
CALL UPIM
*
* UPDATE DIRECTORY INDEX POINTER
*
LHLD FID
CALL SDIRX SEARCH FOR FILE
LHLD DBUF POINTS TO ENTRY FOR FILE
LXI D,DEINX-DEBUF
DAD D
XCHG
LHLD FINDX PUT IN INDEX ADDRESS
MOV A,L
STAX D
INX D LOW
MOV A,H
STAX D HIGH
CALL WDSK REWRITE DIRCTORY
*
* THATS IT
*
CALL RBUF RELEASE BUFFER
JMP NRET
*
*
RNER0 CALL ERRL1 DEVICE FILE RANDOM OPERATION
DB RERR0
*
*********************
*
*
* UPDATE INDEX POINTED TO BY FAIND, IF ANY
* MAKE A COPY OF DIBUF INTO IT
*
UPIM LHLD FAIND
INX H FAIND = -1 IF NONE
MOV A,H
ORA L
RZ . NONE TO DO
DCX H -> MEMORY COPY OF INDEX
LXI D,DIBUF -> MASTER COPY
LXI B,SECTSZ
CALL MOVEV MOVE IT
RET . SIMPLE, NO?
*
PAGE
*
*
*******************************************
*
*
*
* ABORT OPERATION
*
*
* TYPE ERR FOLLOWED BY THE CONTENTS OF USER A,
* USER B, AND USER HL.
*
* RETURN TO THE SYSTEM THROUGH SRESET.
*
*
ABURP CALL OUST TYPE CR LF ERR
DB CR
DB LF
ASC 'ERR: '
DB 0
LDA UA
CALL OUT8B TYPE A
LDA UB
CALL OUT8B TYPE B
CALL O16N TYPE HL
DW UHL
JMP SRESET RETURN THRU SRESET
*
*********************
*
*
* PRINT THE 16 BIT NUMBER POINTER TO BY CALL+1,
* PRECEEDED BY A BLANK.
* RETURN PAST THE POINTER
*
O16N MVI A,BLNK
CALL CONOUT
POP H -> POINTER
MOV E,M
INX H
MOV D,M DE = POINTER
INX H
PUSH H UPDATE RETURN
XCHG
MOV E,M
INX H
MOV D,M
XCHG . = NUMBER
* FALL INTO OUT16
*
* OUTPUT THE 16 BIT NUMBER IN HL
*
OUT16 MOV A,H
CALL OUT8
MOV A,L
*
* OUTPUT 8 BIT NUMBER
*
OUT8 MOV C,A
RAR
RAR . OVER IT GOES
RAR
RAR
CALL OUT8A
MOV A,C
*
*
OUT8A ANI 15
ADI 48
CPI 58
JC CONOUT IT WAS A NUMBER, OUTPUT IT AND RETURN
ADI 7
JMP CONOUT
*
*
* OUTPUT A 8 BIT NUMBER FOLLOWED BY A BLANK
*
OUT8B CALL OUT8
MVI A,BLNK NOW THE SPACE
JMP CONOUT OUTPUT IT AND RETURN
*
*
* OUTPUT ASCII MESSAGE FOLLOWING CALL TO ZERO BYTE
*
OUST POP H
OUST5 MOV A,M FETCH CHAR
INX H
ORA A
JZ OUST9 ZERO BYTE, RETURN
CALL CONOUT TYPE CHAR
JMP OUST5
*
OUST9 PCHL
*
PAGE
*
*
*******************************************
*
*
*
* SET UNIT OPERATION
*
* UA HAS THE DESIRED UNIT NUMBER
*
* ERRORS:
* ILLEGAL UNIT NUMBER
*
*
SUNH LDA UA
LXI H,MAXUN POINT TO MAXIMUM UNIT NUMBER
CMP M
JNC SUNER YES, IT IS ILLEGAL
STA DUNIT NO, SET UNIT,DEFAULT
JMP NRET
*
*
SUNER CALL ERRL1
DB UNER0 ILLEGAL UNIT
*
PAGE
*
*
*******************************************
*
*
*
*
* FILE CONTROL STATUS CHECK
*
* UA HAS THE FILE NUMBER
*
FCTRL CALL PFCB PREPARE
LHLD UDE LOAD A, DE, HL
XCHG
LHLD UHL
LDA UB
CALL DVBR CALL DRIVER
DB DTCTL
*
SHLD UHL SAVE REGISTERS
XCHG . FOR
SHLD UDE RETURN
STA UA
JMP NRET
*
*********************
*
*
* ALLOCATE BUFFER
*
* DE HAS DESIRED SIZE
* CALL ALBUF
* RETURN HL HAS THE BUFFER
*
* MINAD-DE IS USED, MINAD IS UPDATED
* ABORT EXIT IF NO SPACE
*
ALBUF LHLD MINAD GET LOWEST ADDRESS IN USE
CALL ARITH HL=HL-DE
XCHG
SHLD WBUFSZ SAVE SIZE FOR ERROR DEALLOCATION
LHLD LOWAD GET LOWEST ALLOWED ADDRESS
CALL COMP PASSING MIN ADDR?
JC ALB9 NEW MIN LT LOWAD, MEM OVERFLOW
XCHG
SHLD MINAD
SHLD WBUFAD SAVE FOR ERROR DEALLOCATION
RET
*
*
* ABORT, NO SPACE IS AVAILABLE
*
ALB9 LXI H,0
SHLD WBUFSZ CLEAR TO AVOID SCREW-UPS
CALL ERRL1
DB MER0
*
*********************
*
*
* COMPARE DE AND HL
*
* DE,HL ARE UNCHANGED
*
* CARRY IF HL > DE UNSIGNED
* ZERO IF HL = DE
*
COMP MOV A,D
SUB H
RC
RNZ
MOV A,E
SUB L
RET . SIGN AND ZERO SET
*
*********************
*
*
* PROTECTION TEST (PROTEST)
*
* CURRENT FCB IS SET
* CALL PROTST
* BIT(S) TO TEST
* RETURN, NO (NONZERO RESULT)
* RETURN, OK (ZERO RESULT)
*
*
PROTST POP H GET RETURN ADDRESS, POINTER TO PROTECTION
LDA FPROT GET FILE ATTRIBUTES
ANA M MASK AND TEST
INX H MOVE PAST TEST WORD
JZ RP3 OK...RETURN PAST IT
PCHL . RETURN, PROTECTION SET
*
*
*
*********************
*
*
* MOVE MEMORY ROUTINES
*
* DE HAS SOU ADDRESS, HL HAS DEST ADDRESS
* CALL MOVEF
* MOVE COUNT
* RETURN
*
*
MOVEF XTHL . GET RETURN ADDRESS
MOV C,M IT POINTED TO THE COUNT
INX H MOVE UP RETURN
XTHL . PUT IT BACK
XRA A
MOV B,A BC HAS COUNT
JMP MOVEA
*
*********************
*
*
* MOVE VARIABLE SIZE BLOCK
*
* BC HAS COUNT, DE HAS SOURCE, HL HAS DESTINATION
* CALL MOVEV
* RETURN
*
MOVV1 LDAX D
MOV M,A
INX H BUMP POINTERS
INX D
DCX B
MOVEV MOV A,B
MOVEA ORA C
JNZ MOVV1
RET
*
*********************
*
*
*
* PREPARE FCB
*
* UA HAS FCB NUMBER
* CALL PFCB
* RETURN FCB FRADD SET
* ABORT IF ILLEGAL FCB NUMBER
*
*
PFCB LDA NFCB GET NUMBER OF FCB'S
MOV B,A
LDA UA GET FILE NUMBER DESIRED
CMP B
JNC PFC90 ERROR, TOO BIG
*
LHLD FCBASE BOTTOM OF FCB'S
LXI D,LNFCB LENGTH OF EACH ONE
ORA A
JZ PFC6 FILE "0" NO ADDING NEEDED
*
PFC5 DAD D MOVE TO NEXT FCB
DCR A
JNZ PFC5
*
*
* SPECIAL ENTRY POINT FOR CLOSE ALL OPERATION
*
* ENTER WITH HL--> FCB
*
PFC6 SHLD FRADD SAVE THE FCB ADDRESS
XCHG
LXI H,FCBORG MAKE A COPY TO FCBORG
CALL MOVEF MOVE IT
DB LNFCB
*
* CHECK IF UNOCCUPIED
*
LHLD FID
MOV A,H
ORA L
RNZ . NON ZERO ID, OK
*
PFC90 CALL ERRL1 ERROR
DB ERUFN
*
*********************
*
*
* IF BUFFER IS DYNAMIC RELEASE IT
*
* CURRENT FCB IS SET
* CALL RBUF
* RETURN
*
RBUF LHLD FBUFA
INX H
MOV A,H
ORA L
RNZ . FILE IS NOT UNBUFFERED
*
* RELEASE BUFFER
*
CALL WDBUF WRITE DIRTY BUFFER
LHLD FBLKS
XCHG . DE HAS SIZE
LHLD TBUFA HL HAS ADDRESS
CALL DLBUF DEALLOCATE
LXI H,0
SHLD TBUFA ZERO BUFFER POINTER
RET
*
*********************
*
*
* NAMIN, PROCESS IN A NAME
*
* HL POINTS TO NAME
* CALL NAMIN
*
* NAME IS ASSEMBLED INTO DEBUF
* FUNIT IS SET
*
* FIRST ZERO OUT NMLEN BYTES
*
NAMIN LXI D,DEBUF
MVI B,NMLEN
XRA A
*
NAM05 STAX D
INX D
DCR B
JNZ NAM05
LXI D,DEBUF PUT IT HERE
MVI B,NMLEN+1 MAXCOUNT+1
*
*
* LOOP HERE WITH: DE--> NEXT CHARACTER POSITION
* B = NUMBER OF CHARACTERS REMAINING
* HL--> NEXT INPUT CHARACTER
*
NAM10 MOV A,M PICKUP A CHAR
CALL NAMTST
JZ ICIN ERROR!!
*
* FALL THROUGH WITH LEGAL CHAR IN 'A'
*
NAM20 STAX D
INX H
INX D
DCR B
JNZ NAM10
*
* ERROR--TOO MANY CHARACTERS
*
CALL ERRL1
DB ERNTL NAME TOO LONG
*
*
* ZERO BYTE FOUND (NAMTST COMES HERE)
*
NAM30 POP B GET RID OF RET
LDA DUNIT USE DEFAULT UNIT
NAM31 STA FUNIT AS FILE UNIT
LDA DEBUF CHECK FOR NULL NAME
ORA A
RNZ . IF OK
*
ICIN CALL ERRL1
DB ERINM ILLEGAL NAME
*
*
* FOUND UNIT, PICK IT UP
*
NAM40 POP B
INX H
MOV A,M PICKUP CHAR
ANI 127
SBI '0' SUBTRACT ZERO CHR
JC ICIU BAD CHAR
LXI H,MAXUN CHECK RANGE OF UNIT NUMBER
CMP M
JC NAM31 OK, SELECT IT
*
ICIU CALL ERRL1
DB ERICU UNIT ERROR
*
*********************
*
*
* TEST A NAME CHARACTER IN "A"
*
* RETURN IF NONSPECIAL LEGAL CHARACTER
* ERROR IF ILLEGAL CHARACTER
*
* GO TO NAM30 OR NAM40 IF TERMINATOR FOUND
* (RETURN DISPOSED OF)
*
NAMTST ANI 127 MASK DOWN
JZ NAM30 END OF NAME
CPI '/' SLASH?
JZ NAM40 SELECT UNIT
CALL DLTST CHECK FOR BAD CHARS
RZ . IF SO
*
CPI '#' THE OTHER ONES
RZ . BAD
CPI ' '+1 SPACE
JC ICIN CONTROL CHAR OR SPACE
CPI 127 NOT .EQ. OR .GT.
RET . LEGAL CHAR
*
PAGE
*
*
*********************
*
*
*
* SEARCH DIRECTORY
*
*
* HL POINTS TO NAME, CURRENT DIREC SET ( ??? )
*
* CALL SDIR
* RETURN = NOT FOUND, DFC=BLOCK WITH ROOM OR 0 IF DIR FULL
* RETURN = FOUND, DBUF POINTS TO ENTRY
*
SDIR CALL NAMIN PROCESS NAME
XRA A
STA DRID SET ID TO ZERO
STA DRID+1
*
* ALTERNATE ENTRY FROM SDIRX
* COME HERE WITH A=0,DRID EQU FILE ID
*
SDI02 STA DFC INITIALIZE
STA DFC+1 FREE POINTER
*
* READ FIRST SECTOR
*
LXI D,DDSC
LXI H,TDAD
CALL MOVEF SET TRANSFER DESCRIPTOR
DB TBUF-TDAD+2
LDA FUNIT
STA TUNIT DISK UNIT
* READ
SDI07 CALL RDSK
*
* SEE ABOUT FREE STUFF
*
LHLD DFC
MOV A,L
ORA H
JNZ SDI20 ALREADY FOUND ONE
LDA DINE
CPI DREMS
JNC SDI20 SECTOR IS FULL
LHLD TDAD
SHLD DFC SAVE AVAILABLE SECTOR
*
* SET UP DIRECTORY SECTOR SEARCH
*
SDI20 LXI H,DRFDS FIRST ENTRY ADDRESS
SHLD DBUF SAVE POINTER
LDA DINE
STA DCNT SAVE COUNT
ORA A
JZ SDI70 SECTOR IS EMPTY, MOVE TO NEXT
*
* LOOP AND TEST ENTRIES
*
SDI30 LHLD DRID
MOV A,L
ORA H
JNZ SDI50 ITS A SEARCH BY ID
*
* TEST NAME
*
LXI D,DEBUF USER NAME
LHLD DBUF NAME IN SECTOR
*
* COMPARE STRINGS
*
MVI B,NMLEN
SDI40 LDAX D
CMP M
JZ SDI44 MATHC ON THIS CHARACTER
*
* TRY TO MATCH UPPER/LOWER CASE CHARACTERS
*
CPI 97 ="a"
JC SDI42 DEBUF CHARACTER NOT LOWER CASE
SBI 32 DEBUF CHAR WAS LC, UPSHIFT AND TRY
JMP SDI43 TO MATCH AGAIN
*
* DEBUF CHAR NOT LC, TRY TO UPSHIFT DIREC CHAR
*
SDI42 MOV A,M
CPI 97 ="a"
JC SDI60 DIREC CHAR NOT LC, NO MATCH
LDAX D GET DEBUG CHAR
ADI 32 DOWNSHIFT DEBUG CHAR TO TRY MATCH
*
* TRY ALTERNATE MATCH
*
SDI43 CMP M
JNZ SDI60 NO, SECOND MATCH ATTEMPT FAILED
*
SDI44 INX D MATCH
INX H
DCR B MOVE TO NEXT CHARACTER
JNZ SDI40
*
* MATCH
*
SDI45 LHLD DBUF MOVE ENTRY INTO
XCHG
LXI H,DEBUF DEBUF
CALL MOVEF
DB DRESZ
JMP RP2 RETURN TO CALL PLUS 2
*
*
* MOVE TO NEXT ENTRY
*
SDI60 LDA DCNT
DCR A COUNT DOWN
JZ SDI70 SECTOR EMPTY
STA DCNT
LHLD DBUF
LXI D,DRESZ MOVE POINTER
DAD D
SHLD DBUF
JMP SDI30
*
*
* MOVE TO NEXT SECTOR
*
SDI70 LHLD IHFOR FORE POINTER
MOV A,H
ORA A
RM . EOF, FAIL
SHLD TDAD SET NEXT BLOCK
JMP SDI07
*
*
* CHECK FILE ID, NOT NAME
*
SDI50 LHLD DBUF
LXI D,DEFID-DEBUF
DAD D HL POINT TO ID
LDA DRID
CMP M
JNZ SDI60 NOT SAME
INX H
LDA DRID+1
CMP M
JNZ SDI60 NOPE
JMP SDI45 YES, MATCH
*
*********************
*
*
* SEARCH DIRECTORY BY ID
*
* SAME AS SDIR BUT HL HAVE ID
* ENTER AT SDIRY WITH A = UNIT#, ALSO
*
* THE FILE MUST EXIST. THE DIRECTORY ON WHICH THE
* FILE EXISTS IS SEARCHED.
*
SDIRY STA FUNIT SPECIAL ENTRY FOR "OPEN?"
SDIRX SHLD DRID SAVE ID
XRA A SET A TO ZERO
CALL SDI02 GO SEARCH
CALL CI98 FILE MUST EXIST, OR ELSE!
RET
*
*********************
*
*
* DIRECTORY FILE DESCRIPTOR
*
DDSC DW DIRDB READ OPCODE
DDSC2 DW SECTSZ
DW IDDIR
DW DIBUF
*
*********************
*
*
* MAKE ENTRY IN DIRECTORY
*
* DEBUF HAS ENTRY, DFC IS SET
*
EDIR LHLD DFC
MOV A,L
ORA H
CZ CI98 BETTER NOT BE FULL!
*
* READ SECTOR WITH FREE ENTRY
*
EDI10 SHLD TDAD SAVE DISK ADDRESS
LXI D,DDSC2
LXI H,TBCNT
CALL MOVEF
DB TBUF-TBCNT+2
LDA FUNIT
STA TUNIT UNIT
CALL RDSK READ SECTOR
*
* MOVE IN ENTRY
*
LXI D,DIBUF
LHLD DIND HL = NEXT DISPLACEMENT
DAD D HL = DESTINATION
LXI D,DEBUF DE = ENTRY BUFFER
CALL MOVEF
DB DRESZ
*
* UPDATE HEADER
*
LXI H,DINE
INR M NUMBER OF ENTRIES
LHLD DIND
LXI D,DRESZ
DAD D
SHLD DIND NEXT ENTRY DISPLACEMENT
CALL WDSK RE WRITE THE ENTRY
RET . THATS ALL
*
*********************
*
*
* REMOVE DIRECTORY ENTRY
*
* DIBUF HAS SECTOR
* DBUF POINTS TO ENTRY
* ALWAYS NORMAL RETURN
*
RDIR LXI H,DINE
DCR M UPDATE COUNT
JZ RDI60 IT IS NOW ZERO, NOTHING TO MOVE
*
* CALCULATE NUMBER OF WORDS TO MOVE
*
*
LXI D,DIBUF
LHLD DIND
DAD D HL=ADDR OF NEXT FREE DIR ENTRY
LXI D,-DRESZ
DAD D SUBTRACT ONE ENTRY
XCHG
LHLD DBUF
MOV A,E CALCULATE BC=DE-HL =NO.OF BYTES TO BE MOVED
SUB L
MOV C,A
MOV A,D
SBB H
MOV B,A
ORA C
JZ RDI60 NOTHING TO MOVE
LXI D,DRESZ
PUSH H SAVE DBUF FOR DESTINATION
DAD D = SOURCE ADDRESS (DBUF+DRESZ)
XCHG . PUT IN DE
POP H = DESTINATION ADDRESS (DBUF)
CALL MOVEV RECALL THAT BC HAS COUNT
*
RDI60 LHLD DIND
LXI D,-DRESZ UPDATE NEXT ENTRY DISPLACEMENT
DAD D
SHLD DIND
CALL WDSK TDAD STILL IS SET, REWRITE
RET
*
*********************
*
*
* GET FILE ID
*
* CURRENT LOGICAL UNIT DESCRIPTOR IS SET UP
* CALL GFID
* RET WITH ID IN DE
* ABORT IF NO IDS ARE AVAILABLE
*
* SET UP READ
*
GFID LXI D,NIDD
LXI H,TDAD
CALL MOVEF SET TRANSFER DESCRIPTOR
DB TBUF-TDAD+2
LDA FUNIT
STA TUNIT UNIT.
CALL RDSK READ IT
*
LHLD IDBUF
PUSH H SAVE ID
INX H INCREMENT
MOV A,H
ORA L
JZ NOIDS NO IDS LEFT, SERIOUS
SHLD IDBUF OK, REWRITE
CALL WDSK
POP D PUT ID INTO DE
RET
*
*
NOIDS POP D GET RID OF IT
CALL ERRL0
DB ERNID NO IDS LEFT
*
*********************
*
*
* FSM DESCRIPTOR
*
NIDD DW DANIB BLOCK #
DW NIDBC BYTE COUNT
DW IDNID FILE ID
DW IDBUF BUFFER
*
*********************
*
*
* WRITE BUFFER TO DEVICE IF DIRTY
*
WDBUF LDA FFLAG
ORA A TEST DIRTY FLAG
RZ . NOT DIRTY
*
LHLD FBDL THE LAST BYTE IN THE BUFFER
XCHG
LHLD TBUFA SET HL=START ADDRESS, DE=LAST ADDRESS
CALL DVBR WRITE BLOCK
DB DTWB
JMP SEOF EOF, ERROR
JMP WDB50
*
*********************
*
*
* READ NEXT BUFFER LOAD FROM DEVICE
*
* CLEAN BUFFERS, READ BLOCK, THEN SET NBD=0,
* AND BDL=INCOMING BLOCK SIZE
* COME WITH HL=BUFFER SIZE
*
RDNB PUSH H
CALL WDBUF CLEAN IF DIRTY
POP D
LHLD TBUFA
CALL DVBR READ NEXT
DB DTRNB
RET . EOF ENCOUNTERED
NOP
NOP
SHLD FBDL SET BDL
LXI H,0
SHLD FNBD NBD=0
JMP RP2 RETURN CALL +2
*
*********************
*
*
* WRITE CURRENT BUFFER AND LOAD NEXT
*
* CALL WITH SIZE IN HL
* SET NBD=0, BDL FROM DRIVER, FFLAG=0
*
WDBR XCHG
LHLD TBUFA
CALL DVBR WRITE
DB DTWBR
JMP SEOF EOF, ERROR
*
WDB45 SHLD FBDL SET BDL
LXI H,0
SHLD FNBD NBD=0
*
WDB50 XRA A
STA FFLAG FFLAG=0
RET . RETURN
*
*********************
*
*
* DEVICE DRIVER BRANCH
*
* CALL WITH CALL+1=OPERATION
* PASS DE, HL, AND A TO THE DRIVER
*
DVBR XTHL
MOV C,M PICKUP DISPLACEMENT
INX H MOVE PAST IT
MVI B,0 BC=DISPLACEMENT
XTHL . SAVE UPDATED RETURN
PUSH H
LHLD FDRIV
DAD B HL->DISPATCH ADDRESS
MOV B,A
MOV A,M PICKUP FIRST PART
INX H
MOV H,M THEN SECOND
MOV L,A HL=DISPATCH ADDRESS
ORA H
JZ IDAC NO ZERO OPERATION.. ERROR
MOV A,B
XTHL . RESTORE HL,
RET . THEN GO INTO DRIVER.
*
*********************
*
*
* DISK DRIVER READ LAST BLOCK
*
DDRLB LHLD FBACK GET BACK POINTER
MOV A,H TEST FOR BOF
ORA A
RM . YES, WE'RE ALL THE WAY BACK
SHLD FCURSC SET AS CURRENT SECTOR AND FALL THROUGH
*
*
*
* DISK DRIVER READ BLOCK
*
DDRBL CALL RBLK
RX2 XTHL . RETURN CALL+2, BUT
INX H LEAVE
INX H HL
INX H ALONE.
XTHL
RET
*
*
*
PAGE
*
*
*********************
*
*
*
* DISK DRIVER CONTROL/STATUS OPERATION
*
* COME HERE WITH A, DE, HL SET FROM USER CALL B,DE,HL
*
DDCTL ORA A
JZ DDC2 IF STATUS REQUEST
*
*
CPI 7
JZ CTRL7 RETURN STATUS
*
*
CPI 8
JZ CTRL8 SET DRIVE READY TRAP
CPI 9
JZ CTRL9 READ BUFFER
CPI 10
JZ CTR10 WRITE BUFFER
*
CPI 4 IS IT A "LOAD INDEX" REQUEST?
JZ DDC4 YES
*
CALL ERRL2 NO, BUT THAT'S ALL WE DO
DB ERNCT
*
CTRL7 EQU $
* <============ NEED TO LOOK INTO THIS ROUTINE =====
*
LHLD FNBD GET CURRENT BYTE DISPLACEMENT
XCHG
LHLD FBLKS AND THE BLOCK SIZE
CALL ARITH HL = HL - DE
XCHG . RETURN IT IN DE
MVI A,-1 SAY DRIVE READY FOR NOW <=============
RET
*
*
*
* SET DRIVE NOT READY TRAP
*
CTRL8 SHLD DSKRD SET IT
RET . QUICK CALL
*
*
* REFRESH BUFFER OF STATIC BUFFERED FILE
*
CTRL9 CALL BUFTST TEST TYPE OF BUFFERING
RZ . IF DYNAMIC BUFFER
JMP RBLK READ THE BLOCK AGAIN AND RETURN
*
*
* WRITE OUT THE BUFFER IF STATIC BUFFERED
*
CTR10 CALL BUFTST TEST TYPE OF BUFFERING
RZ
XRA A
STA FFLAG CLEAR THE BUFFER DIRTY FLAG
JMP WBLK WRITE IT OUT AND RETURN
*
*
*
* RETURN FILE STATUS
*
DDC2 LDA FPROT A = FILE PROTECTION
MVI D,0 NOTHING ELSE OF IMPORTANCE!
RET
*
*
* LOAD INDEX INTO ADDRESS IN HL
*
DDC4 INX H TEST FOR -1 FIRST
MOV A,H
ORA L
DCX H
JZ DDC4A IT IS -1, SKIP TEST
*
LXI D,SECTSZ CHECK FOR OVERWRITE
CALL MEMCHK
MVI A,1
ORA A SET NZ TO FORCE CALL
*
DDC4A LHLD UHL WE KNOW WHERE IT IS
SHLD FAIND ALL IS WELL, SET IT IN
CNZ RINDY LOAD THE INDEX
RET
*
PAGE
*
*
*********************
*
*
*
* DISK DRIVER WRITE BLOCK
*
DDWBL CALL WBLK WRITE IT
JMP RX2 AND RETURN
*
*
*
* DISK DRIVER WRITE BLOCK/READ NEXT
*
DDWBR CALL WBLK WRITE OUT
CALL DDRNB READ NEXT
CALL LNKBLK NONE SO ADD ONE
JMP RX2 WASN'T THAT EASY
*
* NOTE: THE ABOVE ROUTINE IS REALLY ESTHETICALLY
* PLEASING. (IF I DO SAY SO MYSELF.)
*
*********************
*
*
* WRITE BLOCK OF DISK FILE
*
* WRITE THE CURRENT BLOCK OF THE CURRENT FILE.
* IF THIS BLOCK HAS THE EOF, UPDATE THE HEADER.
*
* INFORMATION IN THE CURRENT FCB IS USED.
*
*
* UPDATE HEADER IF NECESSARY
*
WBLK LDA FFORE+1 HIGH ORDER FORE
ORA A
JP WBL60 NO EOF, JUST WRITE
LHLD FBDL
MOV A,H
ORI 128 SET HIGH BIT
MOV H,A
SHLD FFORE SET NEW COUNT IN FORE PTR
*
* SET OUTGOING HEADER
*
LXI D,FFORE
LXI H,OHFOR
CALL MOVEF JUST MOVE IT
DB OHPRO-OHFOR+1
CALL STDAD SET TRANSFER DESCRIPTOR
JMP WDSKH WRITE BLOCK AND HEADER
*
*
* WRITE BLOCK TO DISK OR OTHER WONDERFUL DEVICE
*
WBL60 CALL STDAD SET TRANSFER DESCRIPTOR
JMP WDSK WRITE IT OUT
*
*********************
*
*
* SET TRANSFER DESCRIPTOR
*
* COPY STUFF FROM FCB TO TDAD
*
STDAD LHLD FCURSC
SHLD TDAD DISK ADDRESS
LHLD FBLKS
SHLD TBCNT BYTE COUNT
LHLD FID
SHLD TFID FILE ID
LHLD TBUFA
SHLD TBUF BUFFER ADDRESS
LDA FUNIT
STA TUNIT DISK UNIT
RET
*
*********************
*
*
* READ NEXT BLOCK OF A DISK FILE
*
* CURRENT FCB HAS HEADER, ID, ETC.
* CALL DDRNB
* RETURN - EOF
* RETURN - OK, HEADER, FCB UPDATED
*
*
* TEST FOR EOF
*
DDRNB LHLD FFORE
MOV A,H
ANI 127
CMP H IS A=H=127?
MOV H,A HAVE HL=COUNT IN CASE
RNZ . A AND H DIFFER BY HIGH BIT, => EOF
*
XCHG . DE HAS NEXT SECTOR ADDRESS
LHLD FCURSC
SHLD LSECT SAVE CURRENT SECTOR ADDRESS
XCHG
SHLD FCURSC SET CURRENT AS NEXT
CALL RBLK READ BLOCK
PUSH H SAVE BDL
*
* PERFORM STRUCTURE TEST
*
LXI H,LSECT POINT TO LAST SECTOR ADDRESS
LDA FBACK
CMP M COMPARE LOW ORDER
JNZ FSBAD BAD BAD BAD
INX H
LDA FBACK+1
CMP M COMPARE HIGH ORDER
JNZ FSBAD BAD BAD BAD
POP H PASS BACK BDL
JMP RX2
*
*
FSBAD CALL ERRL0 SERIOUS ERROR
DB FBER FILE STRUCTURE BAD
*
*********************
*
*
*
* READ DISK BLOCK
*
* CURRENT FCB IS SET
* CALL RBLK
* RETURN
*
*
RBLK CALL STDAD SET TRANSFER DESCRIPTOR
CALL RDSK READ IT
*
* COME HERE AFTER TRANSFER
*
RBL30 LXI D,IHFOR COPY HEADER TO
LXI H,FFORE FCB.
CALL MOVEF
DB FPRST-FFORE+1
*
* IF EOF, RETURN COUNT, ELSE BLOCK SIZE
*
LHLD FFORE
MOV A,H
ORA A TEST HIGH BIT FOR EOF
JP RBL40 NO EOF
ANI 127 MASK OFF HIGH BIT
MOV H,A HL HAVE NEW COUNT
RET . RETURN
*
RBL40 LHLD FBLKS NO EOF, USE BLOCK SIZE
RET
*
*********************
*
*
* FLUSH DEVICE BUFFER
*
FDB LHLD FDRIV
LXI D,DTITO DISPL. TO ITO
DAD D
MOV A,M PICK UP ITO
ORA A
RZ . ZERO, RETURN
CALL WDBUF WRITE OUT (IT BETTER BE DIRTY)
LXI H,0 THEN BDL=NBD=0
JMP WDB45
*
PAGE
*
*
*********************
*
*
*
* RELEASE FILE BLOCK
*
* CURRENT FCB HAS STUFF
* CALL RFBLK
* RETURN
*
* FCURSC IS THE BLOCK RELEASED.
* THE FREE SPACE MAP IS UPDATED.
* FDLTA IS UPDATED
*
* GET COUNT OF TRUE NUMBER OF SECTORS
*
RFBLK LDA FPRST
ANI 7 EXTRACT LOW 3 BITS
STA RFBCN
STA RFBC1 SAVE
*
* REWRITE BLOCK
* SET OUTPUT HEADER, THEN LOOP AND WRITE
*
LXI H,0
SHLD OHFOR
SHLD OHBAK
SHLD OHFID
SHLD TFID
MVI A,1
STA OHPRO 1 SECTOR
LHLD FCURSC
SHLD TDAD SET DISK ADDRESS
LXI H,SECTSZ
SHLD TBCNT SET STANDARD BYTE COUNT
LXI H,DKBUF
SHLD TBUF SET TO USE DISK ALLOC. BUFFER
LDA FUNIT
STA TUNIT SET UNIT
*
RFB10 CALL WDSKH WRITE SECTOR AND HEADER
LHLD TDAD
INX H MOVE TO NEXT SECTOR
SHLD TDAD
LXI H,RFBCN
DCR M COUNT DOWN ON SECTOR COUNT
JNZ RFB10
*
* READ FREE MAP
*
LXI D,MAPDS
LXI H,TDAD
CALL MOVEF MOVE STUFF TO TRANSFER DESCRIPTOR
DB TBUF-TDAD+2
CALL RDSK
*
* FIND WORD TO UPDATE
*
LHLD FCURSC BLOCK NUMBER
DAD H
DAD H
DAD H
DAD H
DAD H *32/256 = /8
MOV L,H
MVI H,0 HL HAS TRACK NO.
LXI D,DKBUF
DAD D HL POINTS TO ENTRY
*
* UNPACK IT
*
PUSH H SAVE HL
MOV B,M
CALL UNPK UNPACK INTO PBUF
*
* SET BITS
*
LXI D,TMBUF TRACK MAP BUFFER
LDA FCURSC
ANI 7
MOV L,A
MVI H,0 HL HAVE SECTOR ADDRESS
DAD D HL NOW POINT TO WORD
LDA RFBC1 GET COUNT OF SECTORS
*
RFB30 MVI M,1 SET BIT
INX H
DCR A
JNZ RFB30
CALL PACK RE PACK THE WORD
POP H
MOV M,B STORE BACK INTO MAP
*
* REWRITE MAP
*
CALL WDSK
LHLD FDLTA
DCX H
SHLD FDLTA
RET . THAT IS ALL
*
*********************
*
*
* FREE SPACE MAP DESCRIPTOR
*
MAPDS DW DAFSB
DW 80 MAP LENGTH
DW IDFSM MAP ID
DW DKBUF USE DISK ALLOCATION BUFFER
*
*********************
*
*
* UNPACK B INTO TMBUF
* 1 BIT IS PLACED IN EACH WORD.
*
*
UNPK LXI H,TMBUF
MVI D,8 ZERO IT FIRST
XRA A = 0
*
UNPK5 MOV M,A
INX H
DCR D
JNZ UNPK5
*
LXI H,TMBUF
MOV A,B
*
* UNPACK A INTO HL
*
UNP ORA A
RZ . ZERO, DONE
RAL . LEFT 1 PLACE, ZERO FILL
MVI M,0
JNC UNP10 NO CARRY, ITS ZERO
INR M INCREMENT TO 1
UNP10 INX H
JMP UNP
*
*
* PACK TMBUF INTO B, RETURNS B
*
*
PACK LXI H,TMBUF
* PACK HL INTO B
*
PAC XRA A
MVI D,8 COUNT IS 8
*
PAC5 MOV E,A SAVE PARTIAL
MOV A,M GET BIT
RAR . PUT IN CARRY
MOV A,E GET PARTIAL
RAL . SHIFT IN BIT
INX H
DCR D
JNZ PAC5 AGAIN
MOV B,A
RET . QUIT
*
*********************
*
*
* PREPARE BUFFER
*
* CURRENT FCB IS SET UP
* CALL PBUF
* RETURN - BUFFER IS SET UP
*
PBUF CALL BUFTST
RNZ . ALL DONE IF BUFFERED
*
* UNBUFFERED, ALLOCATE AND PRIME BUFFER
*
PBU70 LHLD FBLKS
PUSH H SAVE BLOCK SIZE
XCHG
CALL ALBUF ALLOCATE BUFFER
SHLD TBUFA OK
POP D DE=CT, HL->BUFFER
CALL DVBR READ IN BLOCK
DB DTRB
JMP SEOF BAD IDEA *******
SHLD FBDL
RET
*
*
* TEST IF FILE IS UNBUFFERED
*
BUFTST LHLD FBUFA
INX H
MOV A,H
ORA L IF IT WAS -1, IT IS UNBUFFERED
DCX H BACK TO TRUE
SHLD TBUFA SET IT TO TRUE BUFFERED ADDRESS
RET . ZERO PSW IF UNBUFFERED
*
*********************
*
*
* RESTORE FCB
*
* IF FRADD ZERO, DO NOTHING. LEAVE FRADD ZERO.
*
RFCB LHLD FRADD
MOV A,L
ORA H
RZ . ZERO, JUST RETURN
LXI D,FCBORG
CALL MOVEF MOVE BACK
DB LNFCB
*
RFCB1 LXI H,0
SHLD FRADD SET FRADD TO ZERO
RET
*
*********************
*
*
* LINK BLOCK
*
* ALLOCATE AND LINK A BLOCK ONTO THE CURRENT ONE.
* FOR DISK FILES ONLY.
*
LNKBLK CALL PROTST CHECK IF ALLOCATE PROTECTED
DB PALO
JMP EOFE0 YES, PROTECTED!
*
LHLD FBACK
SHLD LNKT2 SAVE BACK POINTER
*
* SET UP HEADER FOR NEW BLOCK
*
LHLD FCURSC
SHLD FBACK SET BACK AS CURRENT
SHLD LNKT1 SAVE CURRENT
LXI H,EOFCD
SHLD FFORE SET FORE = EOF
*
* ID, ETC. ARE THE SAME, ALLOCATE NEW
*
CALL AFBLK
SHLD FCURSC SET AS CURRENT SECTOR
*
* UPDATE HEADER OF LAST BLOCK
*
SHLD OHFOR FORE IS NEW SECTOR
LHLD LNKT1
SHLD TDAD DISK ADDRESS OF LAST BLOCK
LHLD LNKT2
SHLD OHBAK RESTORE BACK POINTER
CALL WDSKH
LHLD FINDX INDEXED?
MOV A,H
ORA L
JZ LNK40 NO, FORGET IT
*
* UPDATE RANDOM FILE INDEX
*
CALL RINDX READ INDEX
MVI B,250
LXI H,DIBUF
*
* SEARCH FOR ZERO ENTRY
*
LNK10 MOV A,M
INX H
ORA M
JNZ LNK30
XCHG
LHLD FCURSC GET CURRENT BLOCK
XCHG
MOV M,D PUT IN NEW ENTRY
DCX H
MOV M,E
CALL WDSK WRITE OUT INDEX
CALL UPIM UPDATE INDEX IN MEMORY, IF ANY
MVI B,1 SET FLAG THAT WE FOUND IT
*
LNK30 INX H
DCR B
JNZ LNK10 NOT YET
LNK40 LXI H,0 NO BYTES YET
RET
*
PAGE
*
*
*********************
*
*
* SEARCH FILE CONTROL BLOCKS
*
* HL HAS FILE ID
* FUNIT HAS UNIT
* CALL SFCBS
*
* RETURN - >1 FOUND
* RETURN - 1 FOUND
* RETURN - 0 FOUND
*
SFCBS XCHG . DE HAS ID NOW
XRA A
STA SFCT1 INITIALIZE COUNT
LHLD FCBASE HL POINT TO FCB
LDA NFCB
STA SFCT2 SET COUNT
*
SFC20 LXI B,FID-FCBORG
DAD B HL POINT TO FILE ID
MOV A,M GET LOW ORDER ID
INX H
CMP E CHECK
JNZ SFC70 NO, MOVE TO NEXT
*
MOV A,M GET HIGH ORDER ID
CMP D CHECK
JNZ SFC70 NO, MOVE TO NEXT
*
* ID MATCH, CHECK UNIT
*
LXI B,FUNIT-FID-1
DAD B MOVE TO UNIT
LDA FUNIT
CMP M CHECK UNIT
JNZ SFC40 NO, UNITS DIFFER
*
* FOUND
*
LDA SFCT1 COUNT UP
INR A
STA SFCT1
*
SFC40 LXI B,FPRST-FUNIT+1
DAD B MOVE TO BEGINNING OF NEXT FCB
JMP SFC75
*
*
SFC70 LXI B,FPRST-FID-1+1
DAD B MOVE TO NEXT FROM FID+1
*
SFC75 LDA SFCT2
DCR A
STA SFCT2 DROP COUNT
JNZ SFC20 DO NEXT
*
* DONE, DO RETURN
*
LDA SFCT1 GET COUNT
CPI 2
RNC . MORE THAN 2
POP H
INX H
INX H
INX H
PUSH H UPDATE RETURN
ORA A SET FLAGS
RNZ . MUST BE 1
INX H
INX H
INX H
XTHL . UPDATE RETURN
RET . AND RETURN FOR ZERO.
*
PAGE
*
*
*********************
*
*
* GET RID OF DANGLING BUFFER
* BECAUSE OF AN ERROR
*
RIDBF LHLD WBUFSZ
MOV A,H
ORA L
RZ . NONE
XCHG
LHLD WBUFAD GET IT AND FALL THROUGH TO DEALLOCATE
*
* FALL THROUGH
*
*********************
*
*
* DEALLOCATE BUFFER
*
* HL POINTS TO BUFFER
* DE HAS BUFFER SIZE
* THE BUFFER MUST BE IN THE SYSTEM GLOBAL AREA.
* CALL DLBUF
* RETURN
*
DLBUF SHLD DABT1 SAVE BUFFER ADDRESS
XCHG
SHLD DABT2 SAVE BUFFER SIZE
DAD D ADDRESS OF NEXT BUFFER (HL)
PUSH H
LXI H,0
SHLD WBUFSZ CLEAR SAVED BUF
POP H
*
* BUFFER ADDRESS (DE)
*
* COMPRESS BUFFER SPACE
*
* DE POINTS TO ONE WORD HIGHER THAN BUFFER
* HL POINTS ONE WORD HIGHER THAN NEXT LOWER BUFFER.
*
DAB10 PUSH H
LHLD MINAD COMPARE DE WITH MINIMUM ADDRESS
CALL COMP
POP H RESTORE HL
JZ DAB30 MOVE IS DONE
* MOVE A BYTE
DCX H
DCX D
LDAX D
MOV M,A
JMP DAB10
*
*
* ADJUST ANY AFFECTED ADDRESSES IN THE FCBS
*
DAB30 SHLD MINAD
LHLD FCBASE
LXI D,FBUFA-FCBORG
DAD D
PUSH H FIRST BUFFER ADDRESS
LDA NFCB
STA DABT3
*
DAB40 MOV E,M
INX H
MOV D,M GET BUFFER ADDRESS FROM FCB
LHLD LOWAD
CALL COMP COMPARE WITH GLOBAL BASE
JC DAB50 BELOW, MUST BE A USER BUFFER
*
LHLD DABT1
CALL COMP COMPARE WITH BUFFER ADDRESS
JNC DAB50 ABOVE AFFECTED AREA
*
LHLD DABT2 GET DELTA
DAD D = UPDATED BUFFER ADDRESS
XCHG . IN DE
POP H
MOV M,E
INX H
MOV M,D PUT BACK INTO FCB
DCX H
PUSH H
*
* MOVE TO NEXT
*
DAB50 POP H GET POINTER TO BUFF +1
LXI D,LNFCB DELTA TO NEXT FCB
DAD D
LDA DABT3 CHECK COUNT
DCR A
RZ
STA DABT3
PUSH H SAVE POINTER AGAIN
JMP DAB40
*
*
PAGE
*
*
*********************
*
*
* ALLOCATE FILE BLOCK
*
* THE CURRENT FCB HAS THE DESIRED BLOCK SIZE AND HEADER.
* AN ABORT IS TAKEN IF THE BLOCK SIZE IS ILLEGAL OR
* IF THE DISK IS TOO FULL.
*
* CONTROL RETURNS TO CALL+1 WITH THE BLOCK ADDRESS IN HL
*
AFBLK LHLD FBLKS FIRST CHECK FOR LEGAL BLOCK SIZE
PUSH H
MOV A,L
ORA H IS IT ZERO?
JZ AFB95 IF SO, ILLEGAL
LXI D,-4084
DAD D >=4084? (8*512-12)
JC AFB95 YES ILLEGAL
POP H GET BACK BLOCK SIZE
CALL AFCALC CALCULATE THE REQUIRED NUMBER OF SECTORS
*
AFB10 MOV A,C C HAS THE NUMBER OF SECTORS
STA AFBT1 WE SAVE IT HERE
*
* READ THE FSMAP
*
LXI D,MAPDS FROM HERE
LXI H,TDAD TO THE TRANSFER DESCRIPTOR
CALL MOVEF SET UP
DB TBUF-TDAD+2
LDA FUNIT GET WHICH UNIT
STA TUNIT SET FOR DISK DRIVER
CALL RDSK
*
* SET UP MAP SEARCH FOR FREE SPACE
*
LXI H,0
SHLD AFBT4 SET BLOCK NUMBER
LXI H,DKBUF ALLOCATION MAP BUFFER
SHLD AFBT3 SET TRACK MAP POINTER
*
* OUTER LOOP FOR ALLOCATION BEGINS HERE
* LOOK FOR NEXT TRACK
*
AFB20 LHLD AFBT3
MOV B,M PICKUP MAP
INX H
SHLD AFBT3 SAVE UPDATED POINTER
CALL UNPK UNPACK THE MAP
*
* A TRACK MAP IS NOW UNPACKED IN PBUF
* AFBT1 HAS THE REQUIRED NUMBER OF SECTORS
* SET UP FOR MAP SCAN
*
LDA AFBT1 NUMBER OF SECTORS REQUIRED
MOV B,A CALCULATE NUMBER FOR LOOP
MVI A,9 ITERATIONS = 8-AFTB1+1
SUB B
MOV B,A B HAS LOOP COUNT
LXI H,TMBUF SCAN STARTING POINT
*
* THE INNER LOOP TO SCAN THE MAP OF THE CURRENT
* TRACK BEGINS HERE
*
AFB40 SHLD AFBT6 SAVE PBUF POINTER
LDA AFBT1
MOV C,A NUMBER OF SECTORS REQUIRED
*
AFB50 MOV A,M
ORA A
JZ AFB70 NO, THIS BLOCK IS NO GOOD
INX H BUMP POINTER
DCR C COUNT DOWN
JNZ AFB50 TRY NEXT SECTOR
*
* AT THIS POINT WE HAVE FOUND A BLOCK ON THE CURRENT
* TRACK OF SUFFICIENT LENGTH. WE NOW PROCEED TO GIVE
* IT TO THE USER.
*
* CLEAR BITS IN MAP
*
LHLD AFBT6 PBUF POINTER
LDA AFBT1 SECTOR COUNT
AFB60 MVI M,0 CLEAR BIT
INX H MOVE TO NEXT
DCR A
JNZ AFB60
*
* REPACK CURRENT TRACK MAP AND REWRITE TO DISK
*
CALL PACK
LHLD AFBT3 GET UPDATED TRACK MAP POINTER
DCX H
MOV M,B STORE MAP BACK IN
CALL WDSK WRITE MAP, TDAD IS STILL SET UP
*
* INITIALIZE BLOCK FOR USER
*
LHLD AFBT4 GET SECTOR NUMBER
SHLD TDAD TO THE TRANSFER DESCRIPTOR
*
* SET OUTGOING HEADER AND TRANSFER DESCRIPTOR
*
LHLD FBLKS
SHLD TBCNT BYTE COUNT
LXI H,0
SHLD TFID SET FREE SPACE FILE ID
LHLD TBUFA
SHLD TBUF SET BUFFER ADDRESS
*
* UNIT IS ALREADY SET
*
LXI D,FFORE
LXI H,OHFOR
CALL MOVEF MOVE IN USER HEADER
DB OHPRO-OHFOR+1
*
* INITIALIZE DISK BLOCK
*
CALL WDSKH WRITE HEADER AND DATA
*
* RETURN DISK ADDRESS TO USER AND UPDATE DELTA
*
LHLD FDLTA
INX H
SHLD FDLTA
LHLD TDAD
RET
*
*********************
*
*
* CALCULATE NUMBER OF SECTORS REQUIRED
*
AFCALC MVI C,0 FOR STARTERS
LXI D,-SECTSZ FIRST SECTOR IS THIS BIG
*
AFB05 DAD D SUBTRACT AMOUNT IN THIS SECTOR
INR C BUMP THE SECTOR COUNT
MOV A,H
ORA A
RM . RESULT NEGATIVE, GOT ENOUGH
*
ORA L ZERO IS GOOD ENOUGH, THOUGH
RZ
*
LXI D,-FULSZ SUBSEQUENT SECTORS ARE THIS BIG
JMP AFB05
*
*********************
*
* CAN'T ALLOCATE ONE HERE...MOVE TO NEXT
*
*
AFB70 LHLD AFBT4
DCR B TOTAL ITERATIONS
JZ AFB80 THIS TRACK IS FULL
INX H BUMP SECTOR NUMBER
SHLD AFBT4
LHLD AFBT6 MOVE PBUF POINTER
INX H UP ONE
JMP AFB40 AND LOOP
*
*
* THIS TRACK IS TOO FULL, TRY NEXT TRACK
*
AFB80 MOV A,L HL HAS SECTOR #
ORI 7
MOV L,A
INX H NOW AT NEXT TRACK
SHLD AFBT4
DAD H
MOV A,H
CPI 5 UP TO SECTOR 280H ?
JC AFB20 STILL OK
*
* DISK IS FULL ABORT
*
LHLD LNKT1 GET BACK CURRENT SECTOR
SHLD FCURSC
LHLD LNKT2 AND BACK POINTER
SHLD FBACK
*
CALL ERRL1
DB DAER0 DISK FULL
*
*
AFB95 CALL ERRL1
DB DAER1 ILLEGAL BLOCK SIZE
*
PAGE
*
*
****************************
*
*
* SHORT RESET AFTER ABORT
*
USRES XRA A
STA UA
SRESET XRA A
STA CIFILE SET CIFILE TO 0
INR A
STA COFILE
INR A
STA UTIL SET UTILITY FILE = 2
*
* CLEAR COMMAND STRING
*
LHLD FCBASE
LXI D,FNBD-FCBORG
DAD D POINT TO NBD WORD IN FCB #0
MVI A,4 CLEAR FOUR BYTES
*
CSTRG MVI M,0
INX H
DCR A
JNZ CSTRG NBD=BDL=0
*
LXI SP,CISTK USE CI STACK
CALL INRST RESET THE DISK TRAPS
SHLD CRTRAP CLEAR CI RETURN TRAP = -1
LDA UA
ORA A
JZ CI CAN'T EXPLAIN ZERO
*
* WAIT FOR A CHARACTER
*
CALL CONIN
CPI CR
JZ CI CR....DON'T EXPLAIN
*
* TYPE MESSAGE
*
LHLD UTOS GET USER RETURN INTO HL
SPHL
POP H = USER RETURN HOPEFULLY
LXI SP,CISTK
MVI A,-1
STA OPER ERRP8 SETS EOPR TO OPER
JMP ERRP8
*
*
*********************
*
SRE50 STA UA SAVE SYSTEM ERROR
*
* 1) SET ERCD TO UA (THE CALLED ERROR #)
* 2) SET ERROR TRAPS
* 3) DO UTILITY WILL "CALLED FROM" MSG
*
* TRAP HERE IF ERROR DURING EXPLAIN
*
XTRP CALL OUST
DB CR
DB LF
ASC "CAN'T EXPLAIN"
DB 0
JMP ABURP TRY TO ABORT AGAIN
*
*
PAGE
*
*
*******************************************
*
*
*
*
* COMMAND INTERPRETER
* *********************
*
*
* SOME CHARACTERS
*
CR EQU 13 ASCII CR
LF EQU 10 ASCII LF
SEMI EQU 59 SEMICOLON
COMMA EQU ','
SLASH EQU '/'
NSIGN EQU '#'
ZCHR EQU '0'
ASTRC EQU '*'
*
*********************
*
*
* EOF ON INPUT FILE, IF CIFILE = 0 (CONSOLE), THEN
* DO A CLOSE ALL, ELSE DO A SHORT RESET.
*
CIEIF LDA CIFILE
ORA A CHECK FOR ZERO
JNZ USRES NOT ZERO, DO A SHORT RESET TO MOVE THE CONSOLE
MVI A,255 CLOSE ALL FILES
CALL SYS
DB CAOP
JMP CIABT
JMP USRES WHY NOT?
*
*********************
*
*
* "RETURN" ENTRY
*
* PROCESS NEXT COMMAND, IF ANY
* IF NONE, RETYPE PROMPT
*
RETURN LXI SP,CISTK
CALL INRST RESET INT TRAPS
LHLD CRTRAP CHECK RETURN TRAP
INX H IF =-1, NOTHING TO DO
MOV A,H
ORA L
JZ CI50 NONE
DCX H <> -1, JUMP TO ADDRESS
PUSH H HERE WE GO
LXI H,-1
SHLD CRTRAP CLEAR TRAP
RET . GO TO TRAPPER
*
*********************
*
*
* SET ERROR TRAPS TO CI STANDARD AND RESET INT TRAPS
*
CIRST LXI H,0
SHLD AERR
SHLD FERR
DCX H
SHLD EERR
*
* RESET BOTH INTERRUPT TRAPS
*
* RETURN HL=-1
*
INRST LXI H,0
SHLD DSKRD SET DISKREADY TO 0
DCX H NOW FOR -1
SHLD BDSK1
SHLD BDSK2
RET . MUST RETURN WITH -1
*
*********************
*
*
* ECHO CHARACTER TO CI LOG FILE
*
* COME WITH CHAR IN A, AND RETURN THAT WAY
*
CRECHO MVI A,CR ENTRY POINT TO ECHO A CARRIAGE RETURN
*
ECHOUT MOV B,A
LDA ECFILE
CALL WB WRITE IT OUT
CALL CI98 PANIC!!!
MOV A,B
RET
*
*********************
*
*
* RETURN AND SET TRAP
*
* COME HERE WITH TRAP ADDRESS IN USER HL
*
RETRAP LHLD UHL
* SET CRTRAP AND FALL INTO CI
SHLD CRTRAP
*
*********************
*
*
* READ AND PROCESS A COMMAND
*
CI LXI SP,CISTK SETUP STACK
*
CI50 LXI H,CIMSG RESET PROMPT STRING
SHLD TDPRO
CALL CIRST
*
* EAT LEADING BLANKS AND ","'S
*
CI51 CALL CIBNK
JZ CIEIF ZERO INDICATES EOF
CALL CIBUP WASN'T " " OR ","... BACK UP 1 CHAR
*
* ECHO THE COMMAND
*
LDA SWECH
RRC
JNC CI59 NO ECHO
LXI H,0
SHLD CECT SET COUNT TO ZERO
*
CI53 LDA ECFILE GET ECHO FILE NUMBER
DCR A
CZ CRECH DO A CR IF IT'S #1
XRA A
STA CERC CRLF COUNT TO ZERO
*
CI55 LDA CIFILE
CALL RB
JMP CI57
CALL ECHOUT PRINT CHAR
LHLD CECT
INX H
SHLD CECT INCREMENT CHARACTER COUNT
*
CPI CR
JZ CI58 CR -- DONE
CPI ';'
JZ CI57 ; -- DONE
*
LXI H,CERC
INR M BUMP LINE POSITION
MVI A,72 DO AUTO CRLF FOR TTY'S ETC
CMP M
JNC CI55 NOT PAST, KEEP GOING
CALL CRECH PAST 70, TYPE CR
JMP CI53 LOOP
*
*********************
*
*
* DONE WITH ECHO, MOVE BACK
*
CI57 CALL CRECHO TYPE A CR
*
CI58 LHLD CECT
MOV B,H
MOV C,L BC HAVE NUMBER OF CHARACTERS TYPED
LDA CIFILE
MVI D,128
CALL SYS
DB SPAOP SPACE BACK
JMP CIABT ERROR- CAN'T BACK UP
*
*
*
* INITIALIZE FOR COMMAND READ
*
CNBF EQU DKBUF PUT NAME OUT OF THE WAY!
*
CI59 LXI H,CNBF
SHLD CPNT SET STORAGE POINTER
MVI A,NMLEN+2
STA CICNT SET MAX CHAR COUNT
MVI A,1
STA XQFLG SET XEQ FLAG
*
* YES, HERE WE AGAIN EAT BLANKS AND COMMAS
*
CALL CIBNK
JZ USRES END OF FILE
JMP CI65 GO PROCESS THE FIRST CHR
*
*
* READ COMMAND
*
CI60 LDA CIFILE
CALL RB
JMP USRES SHORT RESET TO CONSOLE
*
CI65 CPI CR
JZ CI68 ITS A CR, GO PROCESS
CPI SEMI
JZ CI68 ITS A SEMICOLON, GO PROCESS
CPI BLNK
JZ CI71 SPACE, GO PROCESS
CPI COMMA
JZ CI67
MOV B,A
LDA CICNT
ORA A ANY MORE CHARACTERS NEEDED?
JZ CI60 NO, JUST IGNORE
DCR A
STA CICNT YES, COUNT DOWN
LHLD CPNT
MOV M,B STORE CHARACTER
INX H
MVI M,0
SHLD CPNT UPDATE POINTER
JMP CI60
*
*
* COMMA, INHIBIT EXECUTION
*
CI67 XRA A
STA XQFLG
JMP CI71 GO PROCESS
*
*********************
*
*
* EAT COMMA'S AND SPACES FROM CI FILE
*
CIBNK LDA CIFILE
CALL RB
NOP
XRA A SET UP FOR EOF RETURN
RET
CPI BLNK
JZ CIBNK
CPI COMMA
RNZ
JMP CIBNK LOOP FOR " ","," OR EOF
*
*********************
*
*
* BACKUP ONE CHARACTER IN CIFILE
*
CIBUP LDA CIFILE
LXI B,1
MVI D,128
CALL SYS
DB SPAOP BACKUP 1 CHAR
JMP CIABT SERIOUS ERROR
RET
*
*********************
*
*
* CLOSE LOAD FILE
*
CICLO LDA CICNT
CALL SYS CLOSE
DB CLOOP
JMP CIABT ERROR
RET
*
*********************
*
*
* PROCESS COMMAND
*
* COME HERE FOR CR AND ;
* BACKUP SO ROUTINE CAN SEE THE CHARACTER
*
CI68 LDA CICNT CHECK FOR NULL COMMAND
CPI NMLEN+2
CNZ CIBUP BACKUP IF NON-NULL, IF NULL FOLLOWING TEST WILL
* DO.
CI71 LDA CICNT
CPI NMLEN+2 CHECK FOR NULL COMMAND
JZ RETURN YES
*
* OPEN FILE
*
LXI D,CNBF NAME POINTER
CI71A LXI H,-1
SHLD AERR GET MOST ERRORS
INX H =0, SYSTEM BUFFER OPTION
CALL SYS OPEN FILE
DB OPEOP
JMP CIOER TRY TO REPORT THE ERROR
*
STA CICNT SAVE FILE NUMBER
LXI H,0
SHLD AERR SET NORNAL ERROR TRAPPING
*
* CHECK FILE TYPE
*
LDA FTYPE
ANI IMTYPE
JNZ CI94 NOT IMAGE FILE, CANT LOAD
*
* LOAD THE FILE
*
CI75 LDA CICNT GET FILE NUMBER
LXI B,4 4 BYTES
LXI D,CBUF INTO CBUF
CALL SYS READ BLOCK
DB RBLOP
JMP CI80 EOF ENCOUNTERED
*
*
* NORMAL RETURN...GET COUNT AND DEST
*
LHLD CBUF WE READ IT TO HERE
MOV B,H
MOV C,L BC HAVE COUNT
LHLD CBUF+2 HL GET DESTINATION
MOV A,B CHECK FOR ZERO COUNT
ORA C
JZ CI96 YES, PROBABLY UTILITY
LDA CICNT A WILL BE NUMBER
XCHG . DE HAVE ADDRESS
CALL SYS A STILL HAS NUMBER
DB RBLOP
JMP CI89 BAD LOAD FILE
JMP CI75 OK, DO NEXT BLOCK
*
*********************
*
*
* CHECK FOR SELF START
*
CI80 CPI EER0 CHECK FOR EOF
JNZ CI98 NOT EOF, VERY BAD
MOV A,C
CPI 2 ARE 2 BYTES LEFT
JZ CI95 YES, SELF START
*
* CLOSE FILE
*
CALL CICLO
LDA XQFLG IF XQFLG=0 (=> COMMA),
ORA A THEN JUST HANDLE NEXT
JZ CI59 WITHOUT ECHO
JMP RETURN TRY NEXT COMMAND
*
*********************
*
*
CI94 MVI A,ERNIF NOT IMAGE FILE
JMP CI90
*
*
* BAD LOAD FILE, CLOSE FIRST
*
CI89 MVI A,ERBLF
*
* COME HERE WITH ERROR # IN A
*
*
CI90 PUSH PSW SAE ERROR NUMBER
CALL CICLO CLOSE THE LOAD FILE
POP PSW A = ERROR #
*
CIOER STA ERCD SET ERROR NUMBER FOR UTILITY CALL
MVI A,CCLDE =CODE FOR LOADER
STA EOPR SET OPERATION
MVI A,0 MESSAGE AND NO RETURN
LXI H,CNBF -> FILE NAME
JMP ERRP9 GIVE MESSAGE
*
*********************
*
*
* CATESTROPHIC ERROR
*
CI98 POP H SHOW ADDRESS
CI99 MVI A,ERXXX CATESTROPHIC
*
*********************
*
*
* ABORT. USE EXISTING REGISTERS
*
CIABT PUSH PSW RESTORE ECHO FILE TO CONSOLE
MVI A,1
STA ECFILE
POP PSW
CALL SYS
DB ABTOP
*
*********************
*
*
*
* START UP USER PROGRAM
*
* CLOSE THE FILE
*
CI95 CALL CICLO
LHLD CBUF SET START ADDRESS
*
* COME HERE WITH HL EQUAL TO START ADDRESS
* THE FILE WILL NOT BE CLOSED
*
CI96 LDA XQFLG
ORA A
JZ CI59 COMMAND ENDED WITH "," - LOAD NEXT FILE
LDA XA
PUSH H
LHLD XHL
RET
*
PAGE
*
*
*******************************************
*
*
*
*
* CONSOLE TELETYPE DRIVER
*
*
SSTA EQU 02 NEW STATUS PORT
USTA EQU 0
UDAI EQU 04 NEW INPUT PORT
UDAO EQU 1
INRDY EQU 20H READY BIT
OTRDY EQU 128
*
BUFT EQU 80 BUFFER SIZE IN BYTES (255 MAX)
BUFT2 EQU 40 OUTBUF SIZE
*
*********************
*
* DRIVER TABLE
*
TDRIV DW TDRL READ BLOCK
DW TDRL READ NEXT
DW IDAC READ LAST, NO CAN DO
DW TDWL WRITE BLOCK, NEXT
DW TDWL WRITE BLOCK
DW TDNGO REWIND
DW TDNGO EOF
DW TDNGO CLOSE
DW IDAC SEEK
DW TDCTL CONTROL
DW 0 BUFFER SIZE HOLDER
DB 1 IMMEDIATE TRANSFER OPTION
DW TDNGO INITIALIZE, ETC... A CONVINIENT RETURN
*
*******************************************
*
*
*
* CONSOLE INPUT DRIVER DISPATCH POINT
*
CONIN LDA STFLG CHARACTER WAITING?
ORA A
JZ CONI1 NO
XRA A =0
STA STFLG CLEAR FLAG
LDA INBYT RETURN WAITING CHR
JMP CONI2 GO
*
*********************
*
*
* GET CHR FROM RCH DRIVER
*
CONI1 PUSH H SAVE HL
LXI H,CONI2 SETUP RETURN POINT
XTHL . RETURN ADDRESS NOW ON STACK
PUSH H
LHLD RCH GET READ CHARACTER ADDRESS
XTHL . GET BACK HL
TDNGO RET . DISPATCH TO RCH
*
*********************
*
*
* RETURN HERE WITH CHARACTER IN A
*
CONI2 STA CONCH SAVE IT AWAY
PUSH B DON'T DISTURB BC
CALL UPSH UPSHIFT CHARACTER
LDA CONCH BINARY, RELOAD CHAR
POP B NON-BINARY RETURN
STA INBYT SAVE BYTE FOR POSSIBLE LATER USE
RET
*
*********************
*
*
* READ SINGLE BYTE
*
CIRCH CALL CITCH GET THE STATUS
JZ CIRCH WAIT
IN UDAI READ IT
PUSH PSW SAVE FOR SWITCH TEST
LDA SWBIO BINARY I/O?
RRC
JC CIR20 YES!
POP PSW NO
ANI 127 MASK PARITY
RET
*
*
CIR20 POP PSW
RET
*
*******************************************
*
*
* CONSOLE STATUS TEST DISPATCH POINT
*
CONST PUSH H SAVE HL
LXI H,CONT20
PUSH H SETUP RETURN ADDRESS
LHLD SCH
PCHL . DISPATCH TO SCH
*
*
* COME HERE AFTER TEST WITH Z/NZ SET
*
CONT20 POP H RESTORE HL
JNZ CONT30 GOT A CHARACTER WAITING, USE IT
LDA STFLG NO REAL CHAR, WHAT ABOUT A PSEUDO ONE
ORA A
RET . GO WITH FLAGS SET
*
*
* A REAL CHAR, CLEAR PSEUDO CHAR FLAG
*
CONT30 XRA A
STA STFLG
INR A DON'T FORGET ABOUT THE REAL ONE
RET
*
*
* CONSOLE TEST INPUT CHAR
*
CITCH IN SSTA
NOP . THIS FORMAT CANT BE CHANGED ( OVERLAYED ON RESET )
ANI INRDY
RET . FLAGS SET (Z=NO CHAR)
*
*******************************************
*
*
*
* CONSOLE OUTPUT CHARACTER ROUTINES
*
CONOUT STA CONCH SAVE CHARACTER
CALL UPSH UPSHIFT CHARACTER
JMP CON40 RETURN HERE => BINARY SWITCH SET, JUST OUTPUT
STA CONCH SAVE UPDATED CHARACTER
*
* IF CR, SET CRSEEN FLAG AND OUTPUT NULLS
*
CPI CR
JNZ CON20 NOT A CR
STA CRSEEN SET FLAG
JMP CON90 OUTPUT THE CHARACTER
*
*
* NOT A CR, SEE ABOUT LF
*
CON20 CPI LF
JZ CON30 YES, IT WAS
*
* NOT A LF, IF LAST WAS CR, OUTPUT LF AND CLEAR CRSEEN
*
MOV B,A
LDA CRSEEN
ORA A
MOV A,B
JZ CON40 LAST WASN'T A CR, JUST OUTPUT CHAR
MVI A,LF OUTPUT A LF TO PREVENT OVERPRINTING
CALL CON90
*
CON30 XRA A
STA CRSEEN CLEAR CRSEEN FLAG
*
* OUTPUT CHAR IN CONCH
*
CON40 LDA CONCH
CON90 CPI LF LF?
JZ CON91 YES, FOLLOW WITH NULLS
CONXO MOV B,A
PUSH H SETUP CALL TO WCH ROUTINE
LHLD WCH -> ROUTINE
XTHL
RET . GET US THERE
*
*
* SEND NULLS AFTER LF
*
CON91 CALL CONXO TYPE TH ELF
LDA NULLS A=LF BEFORE SO NO NEED TO SAVE
PUSH D SAVE DE
MOV D,A
ORA A
JZ CON93 NONE TO DO
*
CON92 XRA A
CALL CONXO SEND NULL
DCR D COUNT DOWN
JNZ CON92 MORE
*
CON93 POP D
MVI A,LF RETURN WIT LF FOR CONSISTANCY
RET . NOW RETURN FOR REAL
*
*
*
* THIS DOES THE ACTUAL OUTPUT. CONTROL USUALLY COMES HERE
* THROUGH (WCH) BY CON90.
*
CIWCH IN 0F8H
STBYT EQU $-1
DB 0 PATCH ROOM
ANI OTRDY
JZ CIWCH
MOV A,B GET CHR
OUT 0F9H
DABYT EQU $-1
RET
*
*******************************************
*
*
* UPSHIFT ASCII SUBROUTINE
*
* COME HERE WITH CHAR IN CONCH
*
* BINARY, NO CHANGE, CHAR IN CONCH (NOT IN A)
* OK, POSSIBLY UPDATED CHARACTER IN A
*
UPSH LDA SWBIO BINARY CONSOLE?
RRC
RC . YES, SKIP THE WHOLE THING AND LET CON.. KNOW
*
LDA SWUPS SEE IF UPSHIFT REQUESTED
RRC
LDA CONCH A=CHAR
CC UPSH1 CHECK IT
JMP RX2 NO, SKIP IT
*
*
* SEE ABOUT UPSHIFTING CHAR
*
UPSH1 CPI 123 ="z"+1
RNC . >"z", NO CHANGE
CPI 97 ="a"
RC . <"a", NO CHANGE
SBI 32 UPSHIFT
RET . OK
*
*******************************************
*
* CI PROMPT MESSAGE
*
CIMSG DB CR
DB LF
DB ASTRC THE ACTUAL PROMPT
DB 0 END OF MESSAGE
*
*
* OUTPUT STRING TO CONSOLE
*
* LIKE OUST BUT COME WITH HL -> STRING
* THE STRING TERMINATES WITH A ZERO BYTE AND CONTROL
* RETURNS TO CALL+1
*
OUSTH MOV A,M
ORA A
RZ
INX H
CALL CONOUT PRINT
JMP OUSTH
*
PAGE
*
*
*******************************************
*
*
* ----------------- TTY DRIVER FOR CONSOLE -----------
*
TDWB EQU CONOUT OUTPUT CHARACTER ROUTINE
*
* WRITE BLOCK
*
* BUFFER ADDR IN HL, COUNT IN DE
*
TDWL MOV A,E
ORA A TEST COUNT
JZ TDW30 ZERO, => DONE
MOV A,M GET CHAR
CALL TDWB PRINT
INX H BUMP POINTER
DCR E DEC. COUNT
JMP TDWL
*
*
* RETURN A ZERO COUNT
*
TDW30 LXI H,0
JMP RX2 RETURN CALL+2
*
*
* READ BLOCK
*
* COME WITH BUFF IN HL, COUNT IN DE
*
* PRINT PROMPT
*
TDRL PUSH H
PUSH D SAVE IMPORTANT NUMBERS
LHLD TDPRO -> PROMPT MESSAGE
CALL OUSTH PRINT IT
POP D
POP H
MVI D,0 INITIALIZE CHAR COUNT
*
TDRL2 CALL CONIN GET A CHARACTER
CPI CTRLX CANCEL?
JZ TDRLC YES, DELETE LINE
CPI BSP BACKSPACE?
JZ TDRLB YES, BACKSPACE
MOV B,A
MOV A,D ONLY CHECK CTRL-C IF D=0 (1ST CHAR)
ORA A
JNZ TDRL3 SKIP TEST
MOV A,B
CPI CTRLC CTRL-C ?
JZ TDRLE YES, EOF
*
TDRL3 MOV A,E
ORA A
JZ TDRLF BUFFER IS FULL
MOV M,B STORE CHAR
MOV A,B
INX H
CALL CONOUT ECHO
INR D COUNT UP
DCR E COUNT DOWN
CPI CR IS IT A CR?
JZ TDRLQ CR, QUIT
JMP TDRL2 GET NEXT.
*
*
* DELETE ENTIRE LINE
*
TDRLC MVI A,'!' TYPE !,CR, LF
CALL TDWB
MVI A,CR
CALL TDWB
MVI A,LF
CALL TDWB
*
* MOV BUFFER POINTER AND COUNTS BACK TO BEGINNING
*
TDRL5 MOV A,D
ORA A
JZ TDRL2
INR E MORE CHARS AVAIL
DCX H MOVE BACK BUFFER PTR
DCR D COUNT DOWN CHARS
JMP TDRL5
*
*
* BACK SPACE
*
TDRLB MOV A,D
ORA A
JZ TDRLF ITS EMPTY, FORGET IT
DCX H ADJUST POINTER
DCR D AND
INR E COUNTS.
MVI A,LARO
CALL TDWB TYPE BACK ARROW
JMP TDRL2 AND GO ON
*
*
* END OF FILE ENCOUNTERED.
*
* **** THIS ROUTINE USED AS INIT ENTRY POINT ***
* WATCH OUT!!
*
TDRLE RET . THATS IT
*
* BUFFER IS FULL (OR EMPTY)
*
TDRLF MVI A,BELL
CALL TDWB DING
JMP TDRL2 TRY AGAIN
*
* CARRIAGE RETURN-QUIT.
*
TDRLQ MOV L,D COUNT IN HL
MVI H,0
JMP RX2
*
PAGE
*
*
*******************************************
*
*
*
* TTY CONTROL/STATUS OPERATION
*
* HANDLES STATUS AND PROMPT SET REQUESTS
*
TDCTL ORA A
JNZ TDCT2 NOT STATUS REQUEST
*
MVI A,PALO+PNAT+PATR+PDEL PROTECT WORD
LXI D,SBDUP+SBIAT+SBPRO*256 TYPE WORD
RET . THAT'S ALL
*
*
* CHECK IF PROMPT SET OPERATION
*
TDCT2 CPI 2
JNZ TDCER NO, ERROR
SHLD TDPRO YES, SET PROMPT POINTER
RET
*
*
TDCER CALL ERRL2
DB ERNCT CAN'T DO THAT CONTROL OPERATION
*
*******************************************
*
*
*
* HERE ARE SOME USEFUL ASCII CHARACTERS
*
BSP EQU 127 RUBOUT
CTRLC EQU 3 CONTROL-C
CTRLX EQU 24 CONTROL-X
BELL EQU 7 BELL
BSLSH EQU 92 BACK-SLASH
LARO EQU 95 LEFT ARROW
BLNK EQU 32 SPACE
*
PAGE
*
*
*******************************************
*
*
*
*
* UTILITY OPERATION MANAGER
* *****************************
*
*
* THIS OPERATION RUNS ON THE CALLING STACK
*
* CALL UTIL
* OPERATION
* ERROR RETURN
* NORMAL RETURN
*
* THE CALLED OPERATION IS PASSED HL AND A
*
UTILTY SHLD XHL SAVE HL
STA XA AND A
*
* PICKUP THE OPERATION
*
POP H
MOV A,M
INX H MOVE RETURN PAST OPER
PUSH H
STA XOPER SAVE OPERATION
*
* REWIND THE FILE
*
LDA UTIL
MVI D,0
CALL SYS REWIND
DB SPAOP
JMP UER2
*
* LOAD UTILITY FILE PREFIX
*
LXI B,255 BC IS COUNT
LXI H,CBUF READ INTO CMD BUFFER
XRA A A IS ZERO
MOV M,A MAKE SURE A ZERO IS THERE
XCHG . DE IS DEST ADDRESS
*
LDA UTIL UTILITY FILE IS ALWAYS OPEN
CALL SYS
DB RBLOP MEMORY PROTECT WILL SAY NO
NOP
NOP . IGNORE
NOP . EOF
*
* CHECK OPERATION
*
LDA XOPER
LXI H,CBUF
CMP M COMPARE TO MAX
JNC UER1 ERROR, ITS TOO BIG
*
* FIND OPERATION
*
INX H MOVE PAST MAX
MOV C,A
MVI B,0
DAD B + OPERATION
DAD B
MOV A,M
INX H
MOV H,M
MOV L,A = BRANCH ADDRESS
ORA H
JZ UER1 IT'S ZERO, FORGET IT
*
* SETUP FOR CI IMAGE LOAD
*
LDA UTIL
STA CICNT NOTE: B= 0 FROM ABOVE
CALL SYS
DB SEKOP
JMP UER2
*
* FINAL SETUP FOR CI LOAD IS DONE
*
MVI A,1
STA XQFLG FORCE EXECUTION....BANG, BANG...SHOOT, STAB
JMP CI75
*
*
*
UER1 MVI A,UTE0 BAD UTILITY OPERATION
UER2 RET . JUST RETURN WITH SYS STUFF
*
*
*
PAGE
*
*
*
*
* << PTDOS PARAMETER SCANNER >>
*
*
*
* VERSION 1.4 MAY 10, 1977 S. DOMPIER
*
* ~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~.~
*
* COMMON VALUES: ( from PTDEF:LB )
*
* VALUE +40H = MY BUFFER FROM REG HL
*
* PSN EQU 5 READ NAME TO REG DE
* PSV EQU 85H CONVERT VALUE INTO REG DE
* PSFC EQU 6 FORCE CREATE FILE
* PSFCO EQU 2 FORCE CREATE AND OPEN FILE
* PSC EQU 4 CREATE FILE IF NONE EXIST
* PSCO EQU 0 CREATE IF NONE EXIST AND OPEN
* PSOP EQU 1 OPEN FILE
* PSONE EQU 0A5H READ SINGLE BYTE
* PSOPT EQU 8 READ ALL CHRS TO , ; cr 0
*
* NOTE: ABOVE VALUES + 40H = USER INPUT BUFFER IN REG HL
*
*
* PSCN EQU 95H CONVERT MY VALUE TO DE, BASE IN REG B
*
*
*
PSCAN STA OPT save options
SHLD UIBUF save user input buffer address
XCHG . (if any)
SHLD UOBUF save output (work) buffer address
LXI H,0
DAD SP
SHLD RSTK save return address
LHLD AERR AERR save error switch value
SHLD ERSWC
LXI H,-1 return to me, my nus one!
SHLD AERR AERR set new error switch
CALL ERRET set-up normal return address
*
* normal return
*
PNRET LDA CC get chr count
MOV C,A clear carry,
PNR1 ORA A set/reset zero (for chr count).
*
PNR2 LDA LC get last chacter scanned to reg A
LHLD ERSWC reset DOS error switch
SHLD AERR
LHLD RSTK get return address
SPHL . reset caller's stack pointer
RET . go home
*
*
* THE REST OF THIS ROUTINE IS USED BY NAMTST IN THE
* SYSTEM PROPER...USE CARE!!!
*
DLMTST CPI '*'
RZ .
CPI '!'
RZ .
DLTST CPI '<' special chrs, RETURN IMMEDIATLY
RZ . NO CHR COUNT FOR THESE!
CPI '>' CHR IS RETURNED IN REG A.
RZ
CPI '='
RZ
* THESE CHRS ARE ILEGAL FOR NMTST...ALREADY TESTED ZERO
DLTEST CPI ';' check for normal terminators
RZ
CPI 0DH
RZ
CPI ','
RZ
ORA A BINARY ZERO
RET
*
PAGE
*
***************************
*
*
*
* SIMPLE VDM DRIVER
*
*
*
*
* CHARACTER OUTPUT ROUTINE, CHARACTER PASSED IN B
* NULLS, RUBOUT1
*
CIVDM MOV A,B GET CHARACTER
ORA A NULL?
RZ
CPI 127 OR RUBOUT?
RZ
PUSH H NONE OF THOSE, SAVE REGS
PUSH D
PUSH B SAVE CALLING "B"
ANI 7FH STRIP HIGH BIT
MOV B,A
CPI LF LINE FEEDS MUST GO FROM HERE
JZ AGDLY OR CONCH WILL BE CHANGED BY CONIN
CALL NCHK SEE IF NEW SPEED ON EACH CHR
LDA SPEED GET DELAY
MOV H,A COUNT IN HL
MVI L,1
*
AGAIN DCX H
MOV A,H HIGH BYTE OF DELAY
ORA A CHECK IT
JNZ AGAIN
*
* END OF DELAY LOOP
*
AGDLY LHLD VDMAD CURRENT CURSOR ADDRESS
MOV A,M
ANI 7FH
MOV M,A
MOV A,B
CPI CR HOW ABOUT CR (END OF LINE)
JZ PCR1 YES, GO PROCESS IT
CPI LARO BACK SPACE?
JZ VBKSP IF SO YOU SEE
CPI LF NOW TRY LINE FEED
LDA KNTT CHAR COUNT IN THIS LINE
JZ LFPCR GO TO LINEFEED WITH KNTT
INR A + 1
STA KNTT STORE IT BACK
CPI 65 CHECK FOR END OF LINE
CNC PCR NOT END OF LINE YET
MOV M,B OVERWRITE IT WITH CHARACTER
INX H POINT TO NEXT LOCATION
*
GOBK MVI M,' '+80H PUT CURSOR ON SCREEN
GOBK1 SHLD VDMAD STORE IT
POP B RESTORE REGS
POP D
POP H
MOV A,B RETURN CALLING OUTPUT CHARACTER
RET
*
*
* BACKSPACE AND ERASE LAST CHR
*
VBKSP DCX H
LDA KNTT GET CHARACTER COUNT
DCR A
STA KNTT
JMP GOBK
*
*
* CHECK FOR SPEED CONTROL
*
NCHK CALL CONST
RZ . IF NO CHR
NCHKA CALL CONIN FOR NEW SPEED
CALL CK CHECK FOR NEW SPEED
JNC PCR4 IF WASN'T SPEED
*
NCHK1 ANI 0FH ASCII BIAS
MOV C,A SAVE DELAY NUMBER
XRA A
STC . INIT DELAY BIT IN CARRY
*
TRY DCR C DEC DELAY NUMBER
STA SPEED
RZ . STOP NOW
RAL . SHIFT DELAY
JMP TRY DO IT AGAIN
*
*
* CHECK NEW CHARACTER FOR A NUMBER
*
CK ANI 7FH JUST IN CASE
CPI '9'+1 UPPER LIMIT
RNC . NOT NUMBER
CPI '1' LOWER LIMIT
CMC
RET
*
PCR4 INR A IN CASE OF NULL
STA STFLG SAY CHR IS WAITING
DCR A
RET
*
*
* PROCESS THE CARRIAGE RETURN
*
PCR1 CALL NCHK SEE IF CHR WAS INPUT
JZ PCR3 IF NOT OR IF NEW SPEED
*
WAIT CPI ' ' CHECK FOR A BLANK
JNZ PCR3 NO - CONTINUE
WAIT1 XRA A
STA STFLG CLEAR FLAG...WE ARE USING THE SPACE
*
CALL NCHKA
JZ PCR3 A NUMBER, CONTINUE
CPI ' ' SPACE WILL CONTINUE ALSO
JNZ WAIT1 IF IT WASN'T
XRA A
STA STFLG CLEAR THE FLAG AGAIN
*
* MOVE CURSOR TO LEFT MOST POSITION (CARRIAGE RET)
*
PCR3 CALL VDAD1 GET CORNER POSITION
MOV A,M GET CHR
ORI 80H
MOV M,A
JMP GOBK1
*
*
* END OF LINE PROCESSING
*
LFPCR CALL PCR
JMP GOBK
*
*
* LINE FEED OR END OF LINE SCROLL COME HERE
*
PCR LDA BOT SCROLL CONTROL
INR A NEXT ONE
PCRCK ANI 0FH KEEP ONLY LOW ORDER 4 BITS
STA BOT SAVE IT
OUT VPORT OUTPUT TO VDM
DB 0,0 <<-------------------<<<<<
CALL VDAD1 GET ADDRESS
PUSH H SAVE ADDRESS
MVI C,64 CHARACTER COUNT
*
MOVE MVI M,' ' BLANK CHAR ON BOTTOM LINE
INX H BUMP POINTER
DCR C DECREMENT COUNT
JNZ MOVE DO AGAIN
POP H GET ADDRESS BACK AGAIN
RET
*
*
* CALCULATE SCREEN ADDRESS
*
VDAD1 XRA A ZERO THE CHR POSITION
STA KNTT
LDA BOT
*
VDADD ADI 15 LINE 15
RRC
RRC
MOV L,A
ANI 3
ADI 0FCH
MOV H,A
MOV A,L
ANI 0C0H
MOV L,A GOT NEW ADDRESS
RET .
*
*
* A FEW VDM EQUATES
*
VSCREN EQU 0FC00H VDM SCREEN ADDR
VPORT EQU 0C8H STANDARD OUTPUT PORT
VEND EQU 00 HIGH BYTE OF SCREEN END
*
************
PAGE
*
**
* VERSION: 78.10.04
*
* EQUATES
*
*
* ERROR CODES
*
SIZER EQU ERBSC SIZE CONFLICT
FIDER EQU ERFIC FILE ID CONFLICT
SECER EQU ERSCC SECTOR CONFLICT
FORER EQU ERCFS FORMAT ERROR (CAN'T FIND SECTOR)
TRIER EQU ERCRC ABORTS AND CRCC'S
TRKER EQU ERCFT CAN'T FIND TRACK
RWERR EQU ERRBC READ AFTER WRITE ERROR
LOCER EQU ERLOK SYSTEM LOCKED
*
*
* *************************
* * *
* *** DISK DRIVER ***
* * *
* *************************
*
* Original source code for ptdos stores the lenght for a
* transfer in DRLEN not in the BXD. This MUST be fixed
*
*
* VERSION: 05.01.88
*
* Introduction. The disk operating system used on the HELIOS
* uses a controller which had the capacity to write and rewrite
* both the header and data segments of the disk. This was
* achieved by using a hard sectored disk. In addition sector
* lengths were variable, up to 4095 bytes long. The IBM format
* uses only fixed length sectors, which can never be changed
* after definition. Only the fixed length data sectors can be
* changed; the headers are fixed and inaccessable once they have
* been written. The original data structure used by PTDOS
* was a doubly linked list; with linking pointers and filing
* information stored in the header for each data block. The
* headers changed continually. As this is not available with
* soft sectored disks and alternate place must be found to
* store the headers. This is the the last 12 bytes of each
* sector. When a file block is written to disk the header is
* concatenated to the data, before being written. When a block
* is read the header is located and transferred from the end of
* the block (=sector) to an area reserved for the incoming
* header. The RDDSK and WRDSK routines are responsible for
* handling the header/data seperation.
*
* Each file buffer in memory must have the 12 following
* bytes spare at the "top end" to put the header. Disk writes
* transfer the header from the location OHEAD to this space
* befor the block is written. Disk reads move the header to
* IHEAD from the end of the block. Merging and seperating
* the header and data segments is the responsibility of
* RDDSK and WRDSK.
*
* PTDOS is well protected against its own software being faulty.
* It checks the incoming header file id number against the same
* data in memory. If these disagree an error is apparent,
* and it traps to an error handler. This ensures that if the
* linking pointers are incorrect, potentially corrupting the
* the disk structure, this will be prevented.
*
*
* TRANSFER COMMANDS
*
INIOP EQU 00 reset the disk and home to trk 00
RDOP EQU 01 read a block from the disk
WROP EQU 02 write
*
* ERROR CODES
*
NOER EQU 00 no error detected
PAERR EQU 01 parameter error
RNFER EQU 02 record not found - can't find sector
RDERR EQU 04 read data incorrectly
WRERR EQU 08 write error
WPERR EQU 16 attempted write to a protected disk
UOERR EQU 32 unsupported operation
NSERR EQU 64 non standard error - for special devices
* user defined error code in A
DNRER EQU 128 drive not ready error
*
* MISC
*
HELEN EQU 12 LENGTH OF HEADER
*
PAGE
************************
*
*
*
*
* ENTRY POINTS FOR READ AND WRITE DATA
*
*
*
* ON CALL: BXD IS TRANSFER DESCRIPTOR AND MUST BE CORRECT
* IHEAD OR OHEAD MUST BE CORRECT
* RETURNS: CALL+1 FOR NORMAL
* ERRL0 FOR ERRORS
*
*
* WRITE DISK BLOCK
*
WDSK CALL LKCHK CHECK WRITE LOCK AND SET OPERATION
JMP WDSK1
*
*
* READ DISK BLOCK
*
RDSK MVI A,RDOP READ OPERATION
CALL OPSE1 SET OPERATION AND CLEAR INT STUFF
*
WDSK1 EQU $
* READ HEADER
LHLD TSEC GET BLK # FROM PT TRANSFER DESCRIPTOR
SHLD HBXFR INTO BXD BLOCK #
LXI H,HBXD+1
MVI M,RDOP SET READ CODE
DCX H
LDA TUNIT INTO DRIVE BXD
MOV M,A
CALL XFER READ THE HEADER
JMP TRYER
* CHECK HEADER JUST READ AGAINST TDAD
LXI H,TDAD DO THE HEADERS MATCH?
LDA IHBLK
CMP M
JNZ SZCON NO .. !
INX H
LDA IHBLK+1
CMP M
JNZ SZCON NO .. !
INX H
LDA IHSIZ ARE THE FILE BLOCK SIZES THE SAME?
CMP M
JNZ BLKER
INX H
LDA IHSIZ+1
CMP M
JNZ BLKER
INX H
LDA IHFID DO THE FILE ID'S MATCH?
CMP M
JNZ FIERR
INX H
LDA IHFID+1
CMP M
JNZ FIERR
LDA OHPRO ARE THERE THE SAME # OF BLOCKS
ANI 15
MOV B,A
LDA IHPRO
ANI 15
CMP B
JNZ SZCON
* THE HEADERS SEEM TO MATCH .. START TRANSFER
LHLD TBCNT GET THE # OF BYTES IN PT BLOCK
LXI D,SECTSZ
CALL COMP IS TBCNT > SECTOR SIZE?
MOV B,H (cy set is HL > DE)
MOV C,L cy reset if HL <= sector size
JNC WDSK3 NO ..
WDSK2 LXI B,SECTSZ YES .. BC has tbcnt or sectz, whichever smlr
WDSK3 LXI D,RWBUF
LHLD TBUF
LDA BXOP
CPI RDOP
PUSH PSW
JZ WDSK4
XCHG . SWITCH SOURCE,DEST. FOR WRITE
WDSK4 CALL MOVEV MOVE BC BYTES FROM DE TO HL
POP PSW
JZ WDSK5
* WRITE BUFFER TO DISK
LXI H,HBXD+1
MVI M,WROP
DCX H POINT TO START OF BXD TABLE
CALL XFER TRANSFER ONE BLOCK ..
JMP TRYER
* CHECK IF MORE THAN 1 SECTOR TO DO
WDSK5 LDA IHPRO
ANI 15
DCR A
RZ . NO MORE TO DO
LHLD TBUF
LXI D,SECTSZ
DAD D
SHLD BXXA
LDA TUNIT
STA BXDEV
LHLD TBCNT
LXI D,-SECTSZ
DAD D
SHLD BXRZ
LHLD TDAD
INX H
SHLD BXFR
* DO REMAINING SECTORS
WDSK6 LXI H,BXD
CALL XFER
JMP TRYER
*
*LDA BXRZ+1
*DCR A TAKE 512 OF # BYTES REMAINING
*DCR A
*RM . FINISHED
*STA BXRZ+1
*
* THIS IS THE PATCH TO FIX THE RAM DISK EOS BUG
LHLD BXRZ GET RECORD SIZE
LXI D,-512
DAD D TAKE OFF 512 FOR THE BLOCK JUST WRITTEN
MOV A,H
ORA A <0?
RM . YES .. WE'RE DONE
ORA L ZERO?
RZ . YES ..
SHLD BXRZ
* END OF PATCH
LHLD BXFR
INX H
SHLD BXFR
LXI H,BXXA+1
INR M ADD 512 TO DEST. ADDR.
INR M
JMP WDSK6
*
* INITIAL TRANSFER DISCRIPTOR
HBXD DB 0,RDOP UNIT,OP
DW 512 # BYTES
HBXFR DW 0 SECTOR #
DW IHEAD BUFFER AT IHEAD AND 500 BYTES AFTER
DB 0 RESULT
*
*
*
******************
*
*
* HERE WE RETURN TO THE SYSTEM
*
INTD0 DI . NO INTERRUPT
XRA A
STA IFLG2 SAY WE ARN'T DONE BECAUSE WE WERE
LXI H,0 CLEAN HOUSE
SHLD INRET BE VERY SURE
SHLD INTRT EVERY ONE IS CLEAR
SHLD DRVRT EVEN HIM
LHLD DSKRT GET BACK SYSTEM STACK
SPHL . NORMAL AGAIN
*OUT ADRLO RESET CONTROLLER FLAGS
*
* TEST IF INTERRUPTS SHOULD BE RE-ENABLED AND DO SO IF
*
TSTEI LDA IFLG1
ORA A
RZ . NOPE
*EI . YUP
RET
*
*
*****************************************
*
*
*
* THIS ENTRY POINT IS FROM DDONE IF A TASK HANDLER
* WAS PRESENT. THE HANDLER CALLS HERE WHEN IFLG2 IS
* <0>.
*
INTDN LHLD INTRT SEE IF A TASKER STACK IS LAYING AROUND
MOV A,H
ORA L
JNZ INTD0 SEEMS LEGAL??
*
* BAD, BAD, BAD
*
CALL ERRL0
DB ERIDA ILLEGAL DRIVER ACCESS
*
*
******************
*
*
*
* INTERRUPT PROCESSING ROUTINES
*
*
* THE EXTERNAL TASK ROUTINE COMES HERE THROUGH THE ENTRY
* POINT AREA TO SEE IF WE CAUSED AN INTERRUPT. IF WE
* DID THEN CONTROL RETURNS TO THE INTST CALL. IF NOT
* THEN CONTROL RETURNS TO THE INTERRUPT HANDLER.
*
INTDK DI . JUST IN CASE
LHLD INRET WAS IT US?
MOV A,H
ORA L
RZ . COULDN'T BE US...WE'RE NOT HERE!!!
PCHL . GO FIND OUT IF WE DID
*
*******************
*
*
* WRITE DISK HEADER (AND DATA) WDSKH ***
*
*
* OHEAD IS SET UP BY CALLER
*
* WRITE HEADER FOLLOWED BY DATA BLOCK
*
WDSKH EQU $
LHLD OHFID
SHLD TFID
CALL LKCHK
LHLD TSEC
SHLD OHEAD
SHLD HBXFR
MOV A,L
ANI 7
MOV B,A
LDA TUNIT
STA HBXD SET UNIT
*
* CHECK FOR WRITE OVER INDEX
*
LDA OHPRO
ANI 7
ADD B
CPI 9
JNC SZCON ERROR- BLOCK CROSSES TRACK DIVISION
LXI H,IHEAD
LXI D,OHEAD
CALL MOVEF
DB HELEN
JMP WDSK2 TRANSFER DATA NOW
*
**************
*
* TEST IF SYSTEM IS LOCKED
*
* ERROR THROUGH ERRL0
* NORMAL SET OPERATION AND RETURN
*
LKCHK LDA SWLOK TEST IF WRITE LOCKED
RRC
JC LOKER YES, SWITCH IS SET
MVI A,WROP
*
* SAVE OPERATION AND CLEAR THE TASK AND INTERRUPT
* STUFF
*
OPSE1 STA BXOP SET OPERATION FOR LATER
LXI H,0 SET UP STACK FOR RETURN
POP D GET THIS CALL OFF STACK
DAD SP GET SYSTEM RETURN WITH STACK
SHLD DSKRT
PUSH D OUR CALL GOES BACK ON
JMP BLKLN SET UP TRANSFER PARAMETERS AND RETURN
*
*
*
*
*
* THIS ROUTINE CALCULATES THE TRANSFER SIZE FROM THE
* HEADER INFORMATION AND SETS THE NUMBER OF SECTORS
* INTO OHPRO.
*
*
BLKLN LHLD TBCNT GET COUNT FROM TRANSFER DESCRIPTOR
SHLD OHSIZ
CALL AFCALC CALCULATE NUMBER OF SECTORS
LDA OHPRO OUTGOING HEADER PROTECTION WORD
ANI 80H CLEAR PREVIOUS COUNT
ORA C ADD IN THE SECTOR COUNT
STA OHPRO PUT IT BACK
RET
*
*
*
******************
*
*
* DISK ERROR PROCESSOR
*
FMTER CALL DEREP CAN'T FIND SECTOR
DB ERCFS
*
BLKER CALL DEREP SIZE CONFLICT
DB ERBSC
*
FIERR CALL DEREP FID CONFLICT
DB ERFIC
*
SZCON CALL DEREP SECTOR CONFLICT
DB ERSCC
*
TRYER CALL DEREP DRIVER ERROR
DB ERDRI
*
ERTRK CALL DEREP
DB ERCFT
*
LOKER CALL DEREP SYSTEM LOCKED
DB ERLOK
*
******************
*
*
* DISK ERROR REPORT ROUTINE
*
* CONTROL GOES TO ERRL0 EVENTUALLY
* CALL WITH CALL+1 = ERROR #
*
DEREP CALL DREP PRINT ID, TRACK, ETC.
JMP ERRL0 JUST GIVE ERROR
*
*
* SUBROUTINE TO PRINT FILE ID, TRACK, IHFID, IHSIZ
* AS A PREFIX TO AN ABORT MESSAGE
* BUT,... SKIP IF ERROR IS USER TRAPPED
*
DREP LHLD FERR
MOV A,H
ORA L IS SOMEONE ELSE HANDLING THE ERROR?
RNZ . YES, NOTHING TO DO
CALL OUST SAY SOMETHING
DB CR
DB LF
ASC "DSK:"
DB 0
*
CALL O16N PRINT # POINTED TO BY CALL+1, ALSO BLANK
DW TFID
CALL O16N
DW TDAD TRACK AND SECTOR
CALL O16N
DW IHFID
CALL O16N
DW IHSIZ
RET
*
******************
*
*
* ERROR HANDLER FOR SYSTEM
*
* *** NOTE ***
*
* EOPR AND ERCD GET MODIFIED BY THE SYSTEM
*
ERRP9 CALL UTILTY DO THE ERROR TYPEOUT
DB UXOP
JMP SRE50 ERROR!!!
EOPR DB -1 DOS OPERATION
ERCD DB -1 ERROR CODE
JMP SRE50 JUST IN CASE OF SCREWUPS
*
*
*
PAGE
***********************
*
*
*
* DEFINE THE TOP OF THE SYSTEM
*
*
MEMTOP EQU 0C000H ABSOLUTE TOP
*
ORG MEMTOP DEFINE THE BIG BUFFERS
*
DS -256 COME DOWN ONE SECTOR SIZE
DS -320 PLUS ANOTHER BIG ONE
OLBUF EQU $ OVERLAY BUFFER
*
DS -256 NOW ANOTHER SECTOR
CXBUF EQU $ COMMAND EXECUTION BUFFER
*
*
*
* NOW FOR THE TOP OF THE SYSTEM
*
SYSTOP EQU $-1
*
NUENT EQU 15 NUMBER OF JUMP ENTRYS
EPLEN EQU 3*NUENT+6 JUMPS+DW
*
ORG SYSTOP-EPLEN LENGTH OF ENTRY POINT AREA
*
*
* FIXED ENTRY POINT AREA
*
DW CIVDM -> VDM DRIVER OUTPUT CHAR
DW CIWCH -> TERMINAL OUTPUT CHAR
JMP SDIRY SEARCH DIRECTORY BY ID
JMP INTDK CONTINUE INTERRUPT PROCESSING
JMP INTDN PROCESSING DONE
JMP PSCAN PARAMETER SCANNER
JMP CONST CONSOLE TEST INPUT
JMP CONOUT CONSOLE OUTPUT 1 CHAR
JMP CONIN CONSOL INPUT 1 CHAR
DW CIFILE FIXED PARM AREA
JMP ERRL2 ERROR LEVEL I
JMP ERRL1 1
JMP ERRL0 0
JMP USRES SHORT RESET
JMP UTILTY UTILITY CALL
JMP WB WRITE BYTE
JMP RB READ BYTE
JMP SYS MAIN CALL
*
AP2 EQU $ LAST BYTE + 1 OF RESIDENT
*
PAGE
*
*
*
*
*
*
* ONCE ONLY CODE FOLLOWING BOOTSTRAP.
*
* THIS CODE LOADS THE SYSTEM GLOBAL AREA AND
* ADJUSTS THE INITIAL FCBS'S POSITIONS.
*
ORG CXBUF PART OF THE SYSTEM
*
RESET DI .
LXI SP,CISTK SETUP STACK
LXI H,SAM+7FFH MAKE SURE THAT THIS VERSION OF PTDOS MATCHES
LDA REVNR THE DRIVER IN SAM
CMP M DOES IT?
JNZ REVER NO .. !! THEN ABHORT THE BOOTING
LXI H,0
SHLD DSKRD CLEAR THE DRIVE NOT READY TRAP
SHLD AERR CLEAR ANY ERROR HANDLING
SHLD FERR
SHLD EERR
DCX H =-1
SHLD BDSK1 CLEAR ANY INTERRUPT LINK
SHLD BDSK2
XRA A
STA IFLG1 DON'T RESTORE INTERRUPTS
MVI A,2 SET MAXUN TO 2 TO INITIALIZE PROPERLY
STA MAXUN
CALL DDRI INITIALIZE DISK DRIVER
*
* LOAD THE SYSTEM GLOBAL AREA
*
LXI D,RESPA
LXI H,TDAD
CALL MOVEF MOVE SYSGLOBL DESCRIPTOR
DB TUNIT-TDAD+1
*
CALL RDSK READ IT IN
*
* NEXT, MOVE THE FCB'S TO THE RIGHT PLACE
*
LXI D,SP1 MOVE FROM HERE
LHLD FCBASE TO HERE
LXI B,MINFCB*LNFCB = LENGTH
CALL MOVEV
*
* ZERO THE UNUSED FCB'S
*
LHLD FCBASE
LXI D,LNFCB = FCB LENGTH
LDA SYSFIL = NUMBER OF ALLOCATED FCB'S
*
INI10 ORA A
JZ INI20 HL -> FIRST UNUSED FCB, GO ZERO
DAD D
DCR A
JMP INI10
*
*
INI20 XCHG . DE -> FIRST WORD TO ZERO
LXI H,SGAREA HL -> FIRST WORD NOT TO ZERO
INI25 CALL COMP
JNC INI30 ALL DONE
XRA A = 0
STAX D
INX D
JMP INI25 OK FOR NEXT
*
*
* INITALIZE I/O DRIVERS
*
* IF SOLOS/CUTER, SEND I/O TO SAME PLACE AS CURRENT
* PSEUDO-PORT. ELSE, SEND IT TO CUTER-TYPE SERIAL PORT.
SAM EQU 0F000H
*
INI30 LXI H,VSCREN INITIALIZE VDM
SHLD VDMAD SO USER CAN DO AN OUT V COMMAND LATER
XRA A
STA BOT
STA KNTT
STA SPEED
*
LDA SAM THERE IS, DETERMINE WHICH
LXI D,SOLTAB ASSUME SOLOS TILL PROVEN GUILTY
CPI 0
JZ INI40 SOLOS EXISTS
LXI D,CUTTAB ASSUME CUTER SINCE IT WASN'T SOLOS
*
INI40 LHLD SAM+1AH GET OUTPUT PSEUDO-PORT NUMBER
MOV A,M
CALL LKTAB MOVE TO PROPER TABLE ENTRY
CALL MODO NOW UPDATE THE INTERNAL OUTPUT DRIVERS
*
LHLD SAM+20H GET INPUT PSEUDO-PORT NUMBER
MOV A,M
CALL LKTA2 MOVE TO THE PROPER TABLE ENTRY
CALL MODI NOW UPDATE THE INTERNAL INPUT/TSTCHR DRIVERS
*
LHLD SAM+1AH GET OUTPUT PSEUDO-PORT NUMBER
MOV A,M
ANI 3 IS IT VDM?
JNZ INI60 NOPE
LHLD WCH YES-SET DRIVER POINTER TO VDM DRIVER
LXI D,-CIWCH
DAD D
MOV A,H
ORA L
JNZ INI60 UNLESS, OF COURSE, USER HAS ALLREADY CHANGED IT
LXI H,CIVDM
SHLD WCH
XRA A
OUT VPORT
CALL OUST CLEAR SCREEN
DB CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF
DB CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF,CR,LF
DB 0
JMP INI60
*
*
* SAY IT ALL
*
INI60 CALL OUST SAY SOMETHING
DB CR,LF,CR,LF,CR,LF
ASC "PTDOS 2.0 Rev AA Nov 88"
DB CR,LF
ASC "Copyright 1978"
DB CR,LF
ASC "Processor Technology Corporation"
DB CR,LF
ASC "Implemented Feb 88 by D. Sherratt"
DB CR,LF
DB 0
*
* SEE IF WE WANT A LOG FILE
*
LDA SWLOG GET LOG FILE SWITCH
ORA A
JZ INVRB
*
INLOG LXI H,-1 STATIC BUFFERING
SHLD AERR
SHLD EERR
SHLD FERR
INX H
LXI D,LNAME THE LOG FILE NAME
CALL SYS
DB OPEOP OPEN IT
*
JMP INCRE
SHLD AERR
SHLD FERR
MVI D,-1
CALL SYS
DB SPAOP SPACE TO END
JMP USRES RESET IF NOT
STA ECFILE SET AS ECHO FILE
INR A
STA SYSFIL CAN'T CLOSE IT NOW
XRA A
STA UA SET FOR NO ERROR REPORT FROM RESET
JMP INVRB
*
*
INCRE CPI ERNEX DOESN'T EXIST?
JNZ USRES
LXI D,LCBLK
CALL SYS
DB CREOP CREATE IT
JMP USRES
JMP INLOG
*
*
* OPEN AN INPUT FILE FOR GOOD COMMANDS
*
INVRB LDA SWVRB SEE HOW TALKATIVE WE ARE
ORA A
JZ SRESET OPEN ONLY IF VERBOSE IS WANTED
LXI D,CNAME NAME OF FILE
LXI H,0 STATIC BUFFERING
CALL SYS
DB OPEOP
JMP USRES SHORT RESET IF ERROR
STA CIFILE IT IS FOR INPUT
CALL SYS
DB RETOP RETURN TO RUNIT
*
REVNR EQU $
DB 0AAH THIS BYTE MUST MATCH THE LAST BYTE IN SAM ROM
* OR THE DRIVER WILL CORRUPT PTDOS FILES
REVER EQU $
CALL OUST
DB LF,CR
ASC "THIS VERSION OF PTDOS DOES NOT MATCH THE DISK DRIVER"
DB LF,CR
ASC "IN SAM. BOOT ABHORTED !"
DB LF,CR,0
JMP SAM+4 QUIT
*
*
*
CNAME ASC "start.up/0" THE SYSTEM START UP FILE
LCBLK DB 80H TYPE
DW 256 BLOCK SIZE
DB 0 NO ATTRIBUTES
LNAME ASC "syst.log/0" THE SYSTEM LOG FILE
*
*
*
* SYSTEM GLOBAL FILE DESCRIPTOR
*
RESPA DW DASPB SECTOR #
DW LNSPA LENGTH
DW IDSPA FILES ID NO.
DW MASPA LOAD ADDRESS
DB 0 UNIT
*
*
*
*
*
*
*
*
* DRIVE AND DRIVER INITIALIZATION ROUTINES
*
* THIS ROUTINE INITIALIZES ALL DRIVES AND SETS THE
* TRACK COUNT VALUES IN THE UNIT TABLE TO ZERO.
*
DDRI LDA MAXUN NO. OF DRIVES TO RESTORE
DDRI1 DCR A
LXI H,BXD+1
MVI M,INIOP OPCODE FOR INITIALISE
DCX H =BXD =UNIT
MOV M,A =HIGHEST UNIT NO.
DDRI2 CALL XFER
NOP NO ERRORS FOR INITIALISE
NOP
NOP
LXI H,BXD
DCR M NEXT UNIT
RM FINISHED
JMP DDRI2
*
*
*
*
*
****************************************************************
*
* MOVE TO TABLE ENTRY SPECIFIED BY A (TABLE POINTED TO BY DE)
*
LKTA2 INX D ENTRY HERE FOR INPUT TABLE
INX D (INPUT IS 4 BYTES PAST OUTPUT)
INX D
INX D
LKTAB MOV H,D ENTRY HERE FOR OUTPUT TABLE
MOV L,E
ANI 3
CPI 3
JNZ LKTA5
MVI A,1 IF PSEUDO-PORT WAS 3 (CUSTOM), MAKE IT A 1 (SERIAL)
LKTA5 ADD A ENTRIES ARE 8 LONG, SO MULTIPLY BY 8
ADD A
ADD A
MOV C,A
MVI B,0
DAD B ADD TO CORRECT ENTRY
RET . RETURN WITH HL POINTING TO ENTRY DESIRED
*
*************************
*
MODO MOV A,M MODIFY OUTPUT DRIVERS
STA STBYT
INX H
MOV A,M
STA STBYT+1
INX H
MOV A,M
STA STBYT+3
INX H
MOV A,M
STA DABYT
RET .
*
MODI MOV A,M MODIFY INPUT DRIVERS
STA CITCH+1
INX H
MOV A,M
STA CITCH+2
INX H
MOV A,M
STA CITCH+4
INX H
MOV A,M
STA CIRCH+7
RET .
*
****************************************
*
* I/O DRIVER MODIFICATION TABLES
*
* NOTE: IF THE CURRENT-PSEUDO PORT WAS 0, THE DRIVER
* GETS MODIFIED TO THE SERIAL PORT, BUT THE SYSGLOBL
* POINTER POINTS TO THE VDM DRIVER INSTEAD. SO IF AN
* OUT P COMMAND IS DONE, OUTPUT WILL GO SERIAL.
*
********************
*
SOLTAB EQU $ TABLE FOR SOLOS-TYPE PORTS
*
***** IF CURRENT PSEUDO-PORT WAS ZERO (VDM/KBD)
*
DB 0F8H OUTPUT STATUS PORT
NOP . DON'T INVERT STATUS BITS
DB 080H MASK FOR READY BIT
DB 0F9H OUTPUT PORT
*
DB 0FAH INPUT STATUS PORT
CMA .
DB 1 MASK FOR READY BIT
DB 0FCH INPUT PORT
*
***** IF CURRENT PSEUDO-PORT WAS 1 OR 3 (SERIAL)
*
DB 0F8H
NOP .
DB 80H
DB 0F9H
*
DB 0F8H
NOP .
DB 40H
DB 0F9H
*
***** IF CURRENT PSEUDO-PORT WAS 2 (PARALLEL)
*
DB 0FAH
CMA .
DB 4
DB 0FDH
*
DB 0FAH
CMA .
DB 2
DB 0FDH
*
********************
*
CUTTAB EQU $ TABLE FOR CUTER-TYPE PORTS
*
***** IF CURRENT PSEUDO-PORT WAS 0 (VDM/KBD)
*
DB 0
NOP .
DB 80H
DB 1
*
DB 2 PARALLEL KBD
NOP .
DB 20H
DB 4
*
***** IF CURRENT PSEUDO-PORT WAS 1 OR 3 (SERIAL)
*
NEITAB DB 0 THIS TABLE IS ALSO USED IF NEITHER SOLOS OR CUTER
NOP .
DB 80H
DB 1
*
DB 0
NOP .
DB 40H
DB 1
*
***** IF CURRENT PSEUDO-PORT WAS 2 (PARALLEL)
*
DB 0
CMA .
DB 4
DB 2
*
DB 0
CMA .
DB 2
DB 2
*
****************************************************************
*
PAGE
*
*
*
*
ORG 07000H
*
*
* SYSTEM LOADER
*
* THIS SET OF ROUTINES WHOSE STARTING ADDRESS
* IS LISTED ABOVE ESTABLISHES AN INITIAL SYSTEM
* ON A PRE-WRITTEN DISK IN DRIVE 0, UNIT 0.
*
*
* START AT LDR01 TO JUST REWRITE THE SYSTEM LEAVING
* EVERYTHING ELSE ALONE
*
*
LDR XRA A
STA UPFLG
LDR01 LXI SP,LDSTK SET STACK UP
CALL LDRI INITIALIZE DRIVER
*
* WRITE OUT RESIDENT
*
LXI D,LRES
CALL LPTD SET TRANSFER DESCRIPTOR
LXI D,LRESH
CALL LPHD SET OUTGOING HEADER
CALL LWDSH WRITE OUT
*
*
LXI D,LRES2
CALL LPTD SET TDAD
LXI D,LRESD
CALL LPHD SET OHEAD
CALL LWDSH WRITE OUT
*
* WRITE OUT SYSTEM GLOBAL AREA
*
LXI D,LSGL
CALL LPTD SET TRANSFER DESCRIPTOR
LXI D,LSGLH
CALL LPHD SET OUTGOING HEADER
CALL LWDSH WRITE OUT
*
* IF UPDATE ONLY, STOP
*
LDA UPFLG
ORA A
JNZ LDR60
*
* WRITE OUT BOOTSTRAP
*
*LXI D,LBOO
*CALL LPTD SET TRANSFER DESCRIPTOR
*LXI D,LBOOH
*CALL LPHD SET OUTGOING HEADER
*CALL LWDSH WRITE OUT
*
DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
* WRITE NEXT ID FILE
*
LXI D,LNIF
CALL LPTD SET TRANSFER DESCRIPTOR
LXI D,LNIFH
CALL LPHD SET OUTGOING HEADER
CALL LWDSH WRITE OUT
*
* INITIALIZE EMBRYONIC DIRECTORY
*
* WRITE FIRST SECTOR
*
LXI D,LDS0
CALL LPTD SET TRANSFER DESCRIPTOR
LXI D,LDS0H
CALL LPHD SET OUTGOING HEADER
CALL LWDSH WRITE OUT
* LOOP AND WRITE REST OF DIRECTORY
MVI A,DICNT-2
STA LDCNT SET COUNT OF REMAINING SECTORS
* SET HEADERS
LXI D,LDS1
CALL LPTD SET TRANSFER DESCRIPTOR
LXI D,LDS1H
CALL LPHD SET OUTGOING HEADER
*
* IF LAST SECTOR, SET EOF
*
LDR20 LDA LDCNT
ORA A =O?
JNZ LDR30 NO, NOT LAST SECTOR
* SET EOF
LXI H,EOFCD
LXI D,SECTSZ
DAD D EOF+COUNT
SHLD LOHFOR SET IN FORE PTR.
*
LDR30 CALL LWDSH WRITE
* UPDATE POINTERS
LXI H,LTSEC PTR TO SECTOR ADDRESS
INR M
LXI H,LOHFOR PTR TO SECTOR FORE PTR
INR M
LXI H,LOHBAK PTR TO SECTOR BACK PTR
INR M
* CHECK COUNT
LDA LDCNT
ORA A
JZ LDR40
DCR A NOPE
STA LDCNT
JMP LDR20 DO NEXT SECTOR.
*
*
LDR40 MVI B,80
MVI A,-1
LXI H,FMBF
* ZERO THE FSM
LDR42 MOV M,A
INX H
DCR B
JNZ LDR42
LXI H,FMBF
INR A =0
MOV M,A
INX H
MOV M,A
INX H
MOV M,A
LXI H,FMBF+25 DIR TRK
MOV M,A
INX H
MOV M,A FSM,NID
* WRITE OUT FSM
LXI D,LFSM
CALL LPTD SET TRANSFER DESCRIPTOR
LXI D,LFSMH
CALL LPHD SET OUTGOING HEADER
CALL LWDSH
*
*
* LOAD COMPLETE
*
*
LDR60 CALL OUST
DB LF,CR CRLF
ASC 'Load Complete
DB LF,CR AGAIN
DB 0
DONE JMP 0F004H HEAD ON UP TO SAMDI
*
*
* PREPARE TRANSFER DESCRIPTOR
*
LPTD LXI H,LTDAD
CALL MOVEF
DB LTUNIT-LTDAD+1
RET
*
* PREPARE OUTGOING HEADER
*
LPHD LXI H,LOHFOR
CALL MOVEF
DB OHPRO-OHFOR+1
RET
*
*
* THESE TABLES DESCRIBE THE MODULES TO BE
* LOADED.
*
* RESIDENT
*
*
LRES DW DAREB DISK ADDRESS
DW 4084 LENGTH
DW IDRES ID
DW 0A002H ADDRESS <<-----------------<< WATCH MARES!!
DB 0 UNIT
*
LRESH DW D2REB FORE
DW BOFCD
DW IDRES
DB 0 (PROTECTION)
*
*
LRES2 DW D2REB SECTOR
DW 4084 LENGTH
DW IDRES ID
DW 0AFF6H ADDRESS
DB 0 UNIT
*
LRESD DW EOFCD+4084 FORE
DW DAREB BACK
DW IDRES ID
DB 0 PROT
*
* BOOTLOAD
*
BOLEN EQU FULSZ+SECTSZ TWO SECTORS WORTH
*
LBOO DW DABOS SECTOR
DW BOLEN LENGTH
DW IDBOT ID
DW 0F900H ADDRESS
DB 0 UNIT
*
LBOOH DW EOFCD+BOLEN FORE (BOCNT=BOLEN ???)
DW BOFCD BACK
DW IDBOT ID
DB 0 PROTECTION
*
* SYSTEM GLOBAL
*
LSGL DW DASPB SECTOR
DW LNSPA COUNT
DW IDSPA ID
DW SP1 MEMORY ADDRESS
DB 0 UNIT
*
LSGLH DW SP2-SP1+1+EOFCD
DW BOFCD BACK
DW IDSPA ID
DB 0 PROT.
*
* NEXT ID FILE
*
LNIF DW DANIB SECTOR
DW NIDBC COUNT
DW IDNID ID
DW LIDBF ADDRESS
DB 0 UNIT
*
LNIFH DW EOFCD+NIDBC FORE
DW BOFCD BACK
DW IDNID ID
DB 0 PROT.
*
* FSM
*
LFSM DW DAFSB SECTOR
DW 80 LENGTH
DW IDFSM ID
DW FMBF ADDR
DB 0 UNIT
*
LFSMH DW EOFCD+80 FORE
DW BOFCD BACK
DW IDFSM ID
DB 0 PROTECT
*
* DIRECTOR SECTOR 0
*
LDS0 DW DIRDB SECTOR
DW SECTSZ SIZE
DW IDDIR ID
DW DS0 ADDRESS
DB 0 UNIT
*
LDS0H DW DIRDB+1 FORE
DW BOFCD BACK POINTER
DW IDDIR ID
DB 0 PROT.
*
* DIRECTORY SECTORS 1 TO 15
*
LDS1 DW DIRDB+1 SECTOR
DW SECTSZ SIZE
DW IDDIR ID
DW DS1 ADDRESS
DB 0 UNIT
*
LDS1H DW DIRDB+2 FORE
DW DIRDB BACK
DW IDDIR ID
DB 0 UNIT
*
*
* INITIAL DIRECTORY
* FIRST SECTOR
*
*
DS0 DB 6 NUMBER OF ENTRIES
DW DS0N-DS0 NEXT ENTRY DISPLACEMENT
*
ASC 'DIRECTRY'
DB BNTYP TYPE
DW SECTSZ BLOCK SIZE
DB PDEL+PWRI+PFINF+PATR+PNAT
DW IDDIR ID
DW 0 INDEX FILE POINTER
DW DIRDB DISK
DW DICNT BLOCK COUNT
*
ASC 'NEXTID'
DB 0
DB 0
DB BNTYP TYPE
DW NIDBC BLOCK SIZE
DB PDEL+PWRI+PATR+PNAT+PFINF
DW IDNID ID
DW 0 INDEX
DW DANIB FBA
DW 1 BLOCK COUNT
*
ASC 'FSMAP'
DB 0
DB 0
DB 0
DB BNTYP TYPE
DW 80 BLOCK SIZE
DB PDEL+PWRI+PATR+PNAT+PFINF
DW IDFSM ID
DW 0 INDEX
DW DAFSB DA
DW 1 BLOCK COUNT
*
ASC 'SUTIL'
DB 0
DW 0
DB BNTYP TYPE
DW 500 BLOCK SIZE
DB PDEL+PNAT+PFINF
DW 8 ID
DW 214 INDEX
DW 210 DISK
DW 4 BLOCK COUNT
*
ASC 'SYSGLOBL'
DB BNTYP TYPE
DW LNSPA BLOCK SIZE
DB PDEL+PWRI+PATR+PNAT+PFINF
DW IDSPA ID
DW 0 INDEX
DW DASPB DISK
DW 1 BLOCK COUNT
*
ASC 'RESIDENT'
DB BNTYP TYPE
DW 4084 BLOCKSIZE
DB PDEL+PWRI+PREA+PFINF+PATR+PNAT
DW IDRES ID
DW 0 INDEX
DW DAREB DA
DW 2 BLOCK COUNT
DS0L EQU $
*
DS0N EQU DS0L DISPLACEMENT TO NEXT ENTRY
*
*
* IMAGE OF REMAINDER OF DIRECTORY SECTORS
*
*
DS1 DB 0 NUMBER OF ENTRIES
DW 3 NEXT ENTRY DISPLACEMENT
DW 0
*
* NEXT ID FILE IMAGE
*
LIDBF DW 22H NEXT FILE ID.
*
*
* TEMP STORAGE FOR LOADER
*
*
LDCNT RES 1 DIRECTORY ENTRY COUNTER
UPFLG DB 1
*
* TRANSFER DESCRIPTOR
*
LTDAD RES 2 DISK ADDRESS
LTSEC EQU LTDAD
LTBCNT RES 2 BYTE COUNT
LTFID RES 2 FILE ID
LTBUF RES 2 BUFFER ADDRESS
LTUNIT RES 1 UNIT
*
* INCOMMING HEADER
*
LIHEAD RES 2 DISK ADDRESS
LIHSEC EQU LIHEAD
LIHFOR RES 2 FORE
LIHBAK RES 2 BACK
LIHFID RES 2 ID
LIHPRO RES 1 PROT-SIZE
LIHSIZ RES 2 BLOCK SIZE
LIHSPR RES 2 EXPANSION ROOM
*
* OUTGOING HEADER
*
LOHSEC RES 2 SECTOR AND TRACK BUFFER
LOHFOR RES 2 FORE
LOHBAK RES 2 BACK
LOHFID RES 2 ID
LOHPRO RES 1 PROT-SIZE
LOHSIZ RES 2 BLOCK SIZE
LOHSPR RES 2 MORE ROOM
*
LOHEA EQU LOHSEC
*
* LOADER STACK
*
RES 20
LDSTK DB 0
*
FMBF DS 80+2 BEGINNING OF 80 ZERO BUFFER
*
*
BUFEND EQU $
*
*
* DISK WRITE ROUTINES FOR SYSTEM LOADER
*
LDRI MVI A,1 ONLY INITIALISE 1 DRIVE
JMP DDRI1
*
*
*
LWDS2 LXI B,SECTSZ
LXI D,RWBUF
LHLD LTBUF
XCHG . SWITCH SOURCE,DEST. FOR WRITE
CALL MOVEV
* WRITE BUFFER TO DISK
LXI H,HBXD+1
MVI M,WROP
DCX H POINT TO START OF BXD TABLE
CALL XFER
JMP SZCON
* CHECK IF MORE THAN 1 SECTOR TO DO
LWDS5 LDA IHPRO
ANI 15
DCR A
RZ . NO MORE TO DO
LHLD LTBUF
LXI D,SECTSZ
DAD D
SHLD BXXA
LDA LTUNIT
STA BXDEV
LHLD LTBCNT
LXI D,-SECTSZ
DAD D
SHLD BXRZ
LHLD LTDAD
INX H
SHLD BXFR
* DO REMAINING SECTORS
LWDS6 LXI H,BXD
CALL XFER
JMP SZCON
LHLD BXRZ
LXI D,-FULSZ
DAD D
SHLD BXRZ
MOV A,H
ORA A
RM . FINISHED
ORA L
RZ .
LHLD BXFR
INX H
SHLD BXFR
LXI H,BXXA+1
INR M ADD 512 TO DEST. ADDR.
INR M
JMP LWDS6
*
*
* WRITE DISK HEADER (AND DATA) LWDSH ***
*
*
* LOHEAD IS SET UP BY CALLER
*
* WRITE HEADER FOLLOWED BY DATA BLOCK
*
LWDSH EQU $
MVI A,WROP
STA BXOP
LHLD LOHFID
SHLD LTFID
CALL LBLKL
LHLD LTSEC
SHLD LOHEAD
SHLD HBXFR
XRA A
STA HBXD UNIT 0
MOV A,L
ANI 7
MOV B,A
*
* CHECK FOR WRITE OVER INDEX
*
LDA LOHPRO
ANI 7
ADD B
CPI 9
JNC SZCON ERROR- BOLCK CROSSES TRACK DIVISION
LXI H,IHEAD
LXI D,LOHEAD
CALL MOVEF
DB HELEN
JMP LWDS2 TRANSFER DATA NOW
*
*
* THIS ROUTINE CALCULATES THE TRANSFER SIZE FROM THE
* HEADER INFORMATION AND SETS THE NUMBER OF SECTORS
* INTO LOHPRO.
*
*
LBLKL LHLD LTBCNT GET COUNT FROM TRANSFER DESCRIPTOR
SHLD LOHSIZ
CALL AFCALC CALCULATE NUMBER OF SECTORS
LDA LOHPRO OUTGOING HEADER PROTECTION WORD
ANI 80H CLEAR PREVIOUS COUNT
ORA C ADD IN THE SECTOR COUNT
STA LOHPRO PUT IT BACK
RET
*
*
*