BDOSI SRCd BDOS PLMBDOS PLM} !"#$%&'()*+,-.PLMTX1 TMP'^/0123456789:ED IN A PUBLIC TRACK0 ;MOVE TRACK HEAD TO TRACK 0 PUBLIC SELDISK ;SELECT DISK DRIVE GIVEN BY REG C PUBLIC SELTRK ;SELECT TIA ; ; EXTERNALLY DEFINED DISK MONITOR ENTRY POINTS EXTRN DSKMON ; ; PUBLICALLY DEFINED ENTRY AND EXIT PARAMETERS PUBLICBDOS OBJc(;YamnBDOS LST<=>?@ABCDEFGHIJKBDOS LSTLMNOPQRSTUVWXZ[\BDOS LST{]^_`bcdefghijkloRACK GIVEN BY REG C PUBLIC SELSEC ;SELECT SECTOR GIVEN BY REG C PUBLIC SELDMA ;SET DMA ADDRESS TO ADD IN B & C PUBLIC READ FUNC ;FUNCTION NUMBER PUBLIC INFO ;INFORMATION ADDRESS IN CP/M CALL PUBLIC ARET ;RETURNED VALUE PUBLIC BOOT ;WARM START DISK ;READ DISK SECTOR PUBLIC WRITEDISK ;WRITE DISK SECTOR ; DB 0,0,0,0,0,0 ; ; ; ; ENTER HERE FROM THE USER'S PROGRAM PUBLIC CONRDY ;RETURNS CONSOLE STATUS PUBLIC CONINE ;RETURNS CHARACTER IN A PUBLIC CONCHAR ;CONSOLE CHARACTER SENT FROM C CSEG ;INCLUDE WITH CODE SEGMENT BIAS EQU 01503H ;ADDRESS OF WBOOT ENTRY RELATIVE TO 0000 SSIZE EQU 24 ;24 LEVEL STACK REBOOWITH FUNCTION NUMBER IN C, ; AND INFORMATION ADDRESS IN D,E. CALL THE PL/M DISK MONITOR JMP BDOSE ;PAST PARAMETER BLOCK ; PUBLIC LSTOUT ;LIST CHARACTER SENT FROM C PUBLIC PUNOUT ;PUNCH CHARACTER SENT FROM C PUBLIC READIN ;READER CHARACTER RETURNT EQU 0000H ;REBOOT SYSTEM ; BDOS INTERFACE MODULE ; ; COPYRIGHT (C) 1978 DIGITAL RESEARCH ; BOX 579 PACIFIC GROVE, CALIFORN PUBLIC PERERR PUBLIC SELERR PUBLIC RODERR ;USED BY BDOS FOR ERROR REPORTS ; **********************************************A ; FROM 001A THROUGH 0039, OR 3AH - 1AH BYTES, OR ; 20H = 32 (DECIMAL) BYTES, WHERE ; 001AH: TRAN(0) - TRANSLATION OF SECTORELATIVE LOCATIONS 001A-0033 TRAN (26 SECT) ** ; ************************************************* TRAN: DB 01H,07H,0DH,13H DTING SYSTEM TRACKS ; ; ************************************************ ; ** END OF DISK PARAMETER BLOCK 0007-0040 ** ;AL SECTOR ; REGISTER-C CONTAINS LOGICAL SECTOR 0 ... N ; COMPUTE PHYSICAL SECTOR BASED UPON ; SECTOR TRANSLATE TABLE. NOTE: - DIRECTORY BLOCKS PUBLIC OSTRKS ;40 - OPERATING SYSTEM TRACKS ; ************************************************** ; ** R** ; *** RELATIVE LOCATIONS 0009 - 000E *** ; ************************************************ PERERR: DW PERSUB ;P 0 ; 001BH: TRAN(1) - TRANSLATION OF SECTOR 1 ; ... ; 0039H: TRAN(31) - TRANSLATION OF SECTOR 31 ; IF THERE ARE MORE THAN 32B 19H,05H,0BH,11H DB 17H,03H,09H,0FH DB 15H,02H,08H,0EH DB 14H,1AH,06H,0CH DB 12H,18H,04H,0AH DB 10H,16H ; ; ******* ************************************************ ; ; ; ; BDOSE: ;ARRIVE HERE FROM USER PROGRAMS XCHG SHLD INFO LXI H THIS SUBROUTINE AND/OR ; TABLE CAN BE REPLACED FOR USE WITH DIFFERING DRIVE ; TYPES. LXI H,TRAN ;0009 = LOAD TRANSLATE BASEELATIVE LOCATIONS 003A-0040 HOLD PARAMETERS ** ; ************************************************** SECSIZ: DB 26 ;003A=SECTORERMANENT ERROR SUBROUTINE SELERR: DW SELSUB ;SELECT ERROR SUBROUTINE RODERR: DW RODSUB ;RO DISK ERROR SUBROUTINE ; ; FIXED D SECTORS TO TRANSLATE, ; REPLACE ; LXI H,TRAN ; BY A REFERENCE TO YOUR OWN TABLE ELSEWHERE IN ; MEMORY, OR REPLACE THE LXI***************************************** ; ** RELATIVE LOCATIONS 0034-0039 EXTEND TRAN ** ; *******************************,FUNC ;INFORMATION ADDRESS AND FUNCTION STORED MOV M,C ; SAVE THE USER'S STACK POINTER, AND SET TO A LOCAL STACK LXI H,0 MVI B,0 ;0012 = DOUBLE PRECISION LOGICAL SEC# DAD B ;0014 = HL = .TRAN(SECTOR) MOV C,M ;0015 = TRANSLATED VALUE TO C JMS PER TRACK DIRMAX: DB 63 ;003B=MAXIMUM DIRECTORY NUMBER BLKSHF: DB 3 ;003C=2**3 = 8 SECTORS PER BLOCK BLKMSK: DB 111B ;003D=ATA AREAS FOR USER PARAMETERS ; PUBLIC TRSECT PUBLIC TRAN ; ************************************************ ; ** RELATIV INSTRUCTION BY A JUMP ; TO A TRANSLATION SUBROUTINE. ; PUBLIC SECSIZ ;3A - SECTOR SIZE PUBLIC DIRMAX ;3B - DIRECTORY MA***************** DB 00H,00H ;34-35 DB 00H,00H,00H,00H ;36-39 ; ; NOTE THAT TRAN CAN BE EXTENDED TO OCCUPY THE AREDAD SP SHLD ENTSP ;USE THE MONITOR'S STACK LXI SP,LSTACK ;SET TO LOCAL STACK CALL DSKMON ; ; RETURN FROM THE DISK MONITOP SELSEC ;0016 = TO SELECT PHYSICAL SECTOR NOP ;0019 = (FILL) ; ; ************************************************* ; ** R2**3-1 MAXALL: DB 242 ;003E=243 BLOCKS DIRBLK: DB 0C0H ;003F=1100 0000 RESERVES TWO BLOCKS OSTRKS: DB 2 ;0040=NUMBER OF OPERAE LOCATIONS 000F-0019 = TRSECT *** ; ************************************************ TRSECT: ;TRANSLATE LOGICAL TO PHYSICX PUBLIC BLKSHF ;3C - BLOCK SHIFT PUBLIC BLKMSK ;3D - BLOCK MASK PUBLIC MAXALL ;3E - MAXIMUM ALLOC PUBLIC DIRBLK ;3FR LHLD ENTSP SPHL ;ENTRY STACK POINTER RESTORED LHLD ARET ;RETURNED VALUE MOV A,L MOV B,H ;B,A AND H,L CONTAIN RETURN RODSUB: ;REPORT WRITE TO READ/ONLY DISK LXI H,RODMSG WAITER: CALL ERRFLG JMP REBOOT ; ERRFLG: ;REPORT ERROR TO CONSOLE,RROW ; PUBLIC CONIN ;CONSOLE INPUT PUBLIC CONECH ;CONSOLE WITH ECHO PUBLIC CONBRK ;CONSOLE BREAK PUBLIC CONOUT ;CONSOLE HERE ; ; CONBRK: ;CHECK FOR CHARACTER READY LDA KBCHAR ;ALREADY FILLED? ORA A JNZ CONB1 ;RETURN WITH 1 IF FILLED CALAS+OSELDI SELTRK EQU BIAS+OSELTR SELSEC EQU BIAS+OSELSE SELDMA EQU BIAS+OSELDM READDI EQU BIAS+OREADD WRITED EQU BIAS+OWRITREG A LXI H,KBCHAR;ALREADY FILLED? MOV A,M MVI M,0 ;CLEAR IT IF SO ORA A ;SET FLAGS RNZ ;IF NON ZERO, THEN RETURN KBC VALUE ; (COMPATIBILITY BETWEEN PL/M VERSIONS REQUIRES THIS) RET ; ; ; OBOOT EQU 00H OCONRD EQU 03H OCONIN EQU 06H OCO MESSAGE ADDRESS IN HL PUSH H ;SAVE IT CALL CRLF ;CLEAR TO NEW LINE LDA CURDSK ADI 'A' ;CURRENT DISK NAME STA DSKERR ; OUT PUBLIC TABOUT ;TAB OUT PUBLIC CRLF ;CARRIAGE RETURN LINE FEED PUBLIC PRINT ;PRINT 'TIL $ PUBLIC READ ;READ LINE ; L CONRDY ;CHECK FOR CHARACTER READY ANI 1 ;CLEAR ALL BUT LSB RZ ;RETURN IF ZERO, OTHERWISE READ IT CALL CONINE ;GET CHARAE ; ; ; EQUATES FOR NON GRAPHIC CHARACTERS CTLC EQU 03H ;CONTROL C CTLS EQU 13H ;STOP/START SCREEN CTLU EQU 15H ;LINE DELEHAR JMP CONINE ;GET CHARACTER EXTERNALLY ; CONECH: ;READ CHARACTER WITH ECHO CALL CONIN CALL ECHOC ;ECHO CHARACTER? RCNCH EQU 09H OLSTOU EQU 0CH OPUNOU EQU 0FH OREADI EQU 12H OTRACK EQU 15H OSELDI EQU 18H OSELTR EQU 1BH OSELSE EQU 1EH OSESTORE INTO MESSAGE AREA LXI B,DSKMSG CALL PRINT ;PRINT TO THE END OF MESSAGE POP B ;GET MESSAGE CALL PRINT ;SEND TO CONS ; ERROR SUBROUTINES PERSUB: ;REPORT PERMANENT ERROR LXI H,PERMSG CALL ERRFLG ;TO REPORT THE ERROR CPI CTLC JZ REBOOTCTER TO A CPI CTLS ;MAY BE SCREEN FUNTCTION JNZ CONB0 ;RETURN 1 - SAVE CHAR CALL CONINE ;STOP OUTPUT, CHECK CHAR CPI CTLTE CTLE EQU 05H ;PHYSICAL EOL CTLP EQU 10H ;PRNT TOGGLE CTLR EQU 12H ;REPEAT LINE CTLX EQU 18H ;=CTL-U CTLZ EQU 1AH ;END OF ;CARRY IF NOT GRAPIC OR CONTROL PUSH PSW ;SAVE THE CHARACTER MOV C,A CALL TABOUT POP PSW RET ;WITH CHAR IN A ; ECLDM EQU 21H OREADD EQU 24H OWRITE EQU 27H ; ; ; BOOT EQU BIAS+OBOOT CONRDY EQU BIAS+OCONRD CONINE EQU BIAS+OCONIN CONCHOLE JMP CONIN ;READ CONSOLE CHARACTER ; ; ERROR MESSAGES DSKMSG: DB 'BDOS ERR ON ' DSKERR: DB ' : $' ;FILLED IN BY ERRFLG RET ;RETURN, IGNORE ERROR ; SELSUB: ;REPORT SELECT ERROR LXI H,SELMSG JMP WAITER ;WAIT FOR CONSOLE CHAR BEFORE BOOT ;C ;REBOOT? JZ REBOOT XRA A ;CLEAR CHARACTER AND RETURN RET CONB0: ;CHARACTER IN ACCUM, SAVE IT STA KBCHAR CONB1: ;RETU FILE RUBOUT EQU 7FH ;CHAR DELETE TAB EQU 09H ;TAB CHAR CR EQU 0DH ;CARRIAGE RETURN LF EQU 0AH ;LINE FEED CTL EQU 5EH ;UP AHOC: ;ECHO CHARACTER IF GRAPHIC OR CR, LF, TAB CPI CR RZ CPI LF RZ CPI TAB RZ CPI ' ' RET ;CARRY IF NOT GRAPHICA EQU BIAS+OCONCH LSTOUT EQU BIAS+OLSTOU PUNOUT EQU BIAS+OPUNOU READIN EQU BIAS+OREADI TRACK0 EQU BIAS+OTRACK SELDIS EQU BI PERMSG: DB 'BAD SECTOR$' SELMSG: DB 'SELECT$' RODMSG: DB 'R/O$' ; ; ; CONSOLE HANDLERS CONIN: ;READ CONSOLE CHARACTER TO RN WITH 1 FOR CONSOLE BREAK MVI A,1 RET ; CONOUT: ;WRITE CONSOLE CHARACTER FROM C PUSH B ;CHAR SAVED FOR LATER TESTS CFFER) LHLD INFO ;MAX LENGTH MOV C,M ;SAVE IN C INX H ;TO CURRENT LENGTH ADDRESS PUSH H ;SAVE FOR LATER FILL MVI B,0 ;CALL CONOUT LDA COLUMN ANI 111B ;MOD 8 JNZ TAB0 ;FOR ANOTHER ' ' RET ; CRLFP: ;# CRLF MVI C,'#' CALL CONOUT ; CRLETE (ALTERNATE TO CTLX) JZ DELINE CPI CTLU ;LINE DELETE? JNZ NOTU DELINE: CALL CRLFP ;BACK TO BEGINNING OF LINE POP H ; NOT MVI M,0 ;CLEAR COLUMN COUNTER RET ; CTLOUT: ;SEND CHARACTER WITH POSSIBLE PRECEDING ^ ; CHARACTER IS ASSUMED TO BE IH ;BACKUP POINTER TO BUFFER JMP RDECH1 ;ACT LIKE THIS IS AN ECHO ; NOTRUB: ;NOT A RUBOUT, CHECK FOR END OF LINE CPI CTLE ALL CONBRK ;CHECK FOR SCREEN STOP FUNCTION POP B ;RECALL CHARACTER TO C PUSH B ;SAVE IT AGAIN CALL CONCHAR ;TO WRITE THE CURRENT ACTIVE LENGTH READNX: ;READ NEXT CHARACTER PUSH B ;SAVE CURRENT/MAX LENGTHS PUSH H ;SAVE NEXT TO FILL-1 READN0: CALF: ;CARRIAGE RETURN LINE FEED MVI C,CR CALL CONOUT MVI C,LF JMP CONOUT ; PRINT: ;PRINT MESSAGE GIVEN BY BC 'TIL $ LDTHROW AWAY PUSHED VALUE JMP READ ;START ALL OVER ; NOTU: CPI CTLR ;REPEAT LINE? JNZ NOTR PUSH B ;SAVE LINE LENGTH CAN C MOV A,C CALL ECHOC ;TAB, CR, OR LF? JNC TABOUT ;SKIP IF GRAPIC OR TAB,CR,LF ; SEND PRECEDING UP ARROW PUSH PSW MV JNZ NOTE ;SKIP IF NOT PUSH B PUSH H ;READY FOR CRLF SEQUENCE CALL CRLF JMP READN0 ;FOR ANOTHER CHARACTER ; NOTE: ;NOTHARACTER POP B ;RECALL IT AGAIN PUSH B ;SAVE IT FOR LATER TESTS LDA LISTCP ;LIST COPY TOGGLE ORA A ;SET? CNZ LSTOUT ;TL CONIN ;NEXT CHARACTER IN ANI 7FH ;CLEAR PARITY POP H ;RECALL NEXT TO FILL-1 POP B ;RECALL LENGTHS CPI CR ;END OF LINE?AX B CPI '$' ;END OF MESSAGE? RZ ;RETURN IF SO INX B ;TO NEXT CHARACTER PUSH B MOV C,A ;READY TO PRINT CALL TABOUT LL CRLFP ;RETURN CARRIAGE POP B ;RECALL LINE LENGTH POP H ;RECALL START ADDRESS OF BUFFER-1 PUSH H ;PUT IT BACK PUSH B ;I C,CTL CALL CONOUT ;UP ARROW POP PSW ;RECALL CHAR ORI 40H ;BECOMES GRAPHIC MOV C,A ; TABOUT: ;EXPAND TABS TO CONSOLE END OF LINE, CTL-P? CPI CTLP JNZ NOTP ;SKIP IF NOT PUSH H ;INVERT THE PRINT TOGGLE LXI H,LISTCP MVI A,1 ;1-LISTCP SO PRINTER POP B ;RECALL CHARACTER MOV A,C ;GRAPIC? LXI H,COLUMN CPI RUBOUT RZ ;NO INCREMENT IF RUBOUT INR M ;INCREM JZ READEN ;SKIP TO END IF SO CPI RUBOUT ;CHARACTER DELETE? JNZ NOTRUB ;SKIP IF NOT MOV A,B ;RUBOUT CHARACTER, IF POSSIB;SEND THE CHARACTER POP B ;RECALL NEXT TO GET ADDR JMP PRINT ; READ: ;READ TO INFO ADDRESS (MAX LENGTH, CURRENT LENGTH, BUSAVE LINE LENGTH REP0: MOV A,B ;LINE LENGTH COUNTED DOWN TO ZERO? ORA A JZ REP1 ;END OF REPEAT? INX H ;NO, GET NEXT CHARA MOV A,C ;COMPARE WITH TAB CPI TAB JNZ CONOUT ;DIRECT TO CONSOLE IF NOT TAB0: MVI C,' ' ;PAD TO NEXT COLUMNAR POSITION CUB M MOV M,A ;BACK TO LISTCOPY POP H ;RECALL NXT TO FILL-1 JMP READNX ; NOTP: ;NOT THE PRINT TOGGLE CPI CTLX ;LINE DELENT COLUMN COUNT CPI ' ' RNC ;NO CARRY GEN'ED IF GRAPHIC DCR M ;NO COLUMN MOVEMENT CPI LF ;END OF LINE? RNZ ;DONE IFLE ORA A ;ZERO LENGTH? JZ READNX ;SKIP DELETE IF SO MOV A,M ;LAST FILLED CHARACTER DCR B ;DEC LENGTH TO DELETE IT DCX CTER MOV C,M ;READY TO PRINT DCR B ;COUNT B DOWN PUSH B ;SAVED FOR PRINTOUT PUSH H ;SAVED FOR PRINTOUT CALL CTLOUT ;CH PUBLIC CURDSK ;CURRENT DISK FOR ERR MESSAGES ; COLUMN: DB 0 ;COLUMN POSITION LISTCP: DB 0 ;LISTING TOGGLE KBCHAR: DB 0 ;IN TABLE (ACCESS TO TRAN IS ONLY THROUGH TRSECT) 003AH SECSIZ = NUMBER OF SECTORS PER TRACK (<=32)S FOR REBOOT CHECK MOV A,B ;CHECK THE LENGTH JNZ NOTCTC ;SKIP IF NOT CTLC ; CTLC FOUND, MUST BE LENGTH = 1 CPI 1 ;LENGTH INED PARAMETERS ARE FOUND AT THE BEGINNING OF THE BDOS AREA (SEE THE BDOSI INTERFACE) AND CAN BE ALTEREDARACTER ECHOED POP H ;RECALL NEXT ADDR-1 POP B ;RECALL REMAINING COUNT JMP REP0 ;FOR ANOTHER CHARACTER REP1: POP B ;RECALITIAL KEY CHAR = 00 CURDSK: DB 0 ;CURRENT DISK NUMBER ; FUNC: DS 1 ;FUNCTION NUMBER INFO: DS 2 ;INFORMATION ADDRESS ARET: D 003BH DIRMAX = LARGEST DIRECTORY ENTRY NUMBER (0..254) THE FOLLOWING VALUES ARE BASED UPON A BLONE JZ REBOOT ;BOOT THE SYSTEM IF FOUND NOTCTC: CMP C ;UP TO THE END OF THE BUFFER? JC READNX ;FOR ANOTHER CHARACTER ; RE TO FIT A RANGE OF DISK DRIVES STARTING WITH THE BASE OF THE BDOS AREA: 0009 - 000AH PERERR = .PERM ERROL LENGTHS JMP READNX ;FOR ANOTHER CHARACTER ; NOTR: RDECHO: INX H ;NEXT TO FILL MOV M,A ;STORE THE CHARACTER IN THE BUFFES 2 ;ADDRESS VALUE TO RETURN ENTSP: DS 2 ;ENTRY STACK POINTER DS SSIZE*2 ;STACK SIZE LSTACK: END OCK ALLOCATION SIZE OF BLKSIZ, WHICH IS USUALLY 1K FOR SINGLE DENSITY, 2K FOR DOUBLE DENSITY, AND MUST BADEN: ;END OF READ, FILL CURRENT LENGTH POP H ;.CURRENT LENGTH MOV M,B ;FILLED TO MEMORY MVI C,CR ;RETURN CARRIAGE JMP CR SUBROUTINE 000B - 000CH SELERR = .SELECT ERROR SUBROUTINE 000D - 000EH RODERR = .READ ONLY DISK ERROR R INR B ;INCREMENT THE LENGTH RDECH1: ;LOOK FOR CONTROL CHARACTERS PUSH B PUSH H ;SAVE THE PARAMETERS MOV C,A ;READY TOBDOS: DO; /* (NORMALLY ORG'ED DIRECTLY AFTER BDOSI AT 3100H IN 16K CP/M) */ /* COPYRIGHT (C) 1976,1977,1978 E COMPUTED IN SUCH A WAY THAT THE MAXIMUM ALLOCATION VALUE IS LESS THAN OR EQUAL TO 255 (A BYTE QUANTITONOUT ;RETURN THROUGH CONOUT ; ; ; DATA AREAS PUBLIC COLUMN PUBLIC LISTCP ;LIST COPY PUBLIC KBCHAR ;KEYBOARD CHARACTER SUBR 001A - 0019H TRSECT = SECTOR TRANSLATE SUBROUTINE 001A - 0039H TRAN = STANDARD SECTOR TRANSLATE PRINT CALL CTLOUT ;MAY BE ^CHAR POP H POP B ;PARAMETERS READY FOR CHECKS MOV A,M ;RECALL CHARACTER CPI CTLC ;SET FLAG DIGITAL RESEARCH BOX 579, PACIFIC GROVE CALIFORNIA, 93950 USER DEFY). 003CH BLKSHF = LOG2 OF BLOCK SIZE (BLKSIZ) 003DH BLKMSK = 2**BLKSHF-1 00ECTORY IS 64/4 = 16 SECTORS WHICH USES A TOTAL OF 2 OF THE BASIC BLOCKS (OF 1024 BYTES EACH) AND THUS THE AREA RESERVEROM ZERO THROUGH 242 (THE LAST 3/4 OF AN ALLOCATION BLOCK IS LOST), AND THUS THE VALUE MAXALL = 242 (MAXLITERALLY '0003H', CDLOC LITERALLY '0004H', JBDOS LITERALLY '0005H', BDOSA LITERALLY '0006H', /* ADDRESS FIELD OFDIRMAX = 63 (=64 DIRECTORY ENTRIES, FOR EXAMPLE) GIVEN TWO SYSTEM TRACKS, WE HAVE A USABLE STORAGE AREA OF GNED AS FOLLOWS: 0000H JMP WBOOT 0003H IOBYTE (USED IN BDOS, PIP, AND STAT) 0004H CDISK 3EH MAXALL = MAXIMUM ALLOCATION NUMBER 003FH DIRBLK = BIT PATTERN WHICH RESERVES ONE BLOCK D FOR THE DIRECTORY IS DIRBLK = 11000000B = 0C0H = 192 (DECIMAL) (I.E., THE FIRST TWO BLOCKS CANNOT BE ALLOIMUM ALLOCATION NUMBER) FURTHER, THE VALUE OF BLKSIZ (WHICH IS ONLY USED IN THE FOLLOWING COMPUTATIONS) IS ASSUMED T JMP INSTRUCTION */ TFCB LITERALLY '005CH', TBUFF LITERALLY '0080H'; /* THE FOLLOWING SUBROUTINES ARE ASS77-2 TRACKS TIMES 26 SECTORS PER TRACK = 75*26 = 1950 SECTORS GIVEN 512 BYTES PER ALLOCATION, WE GET 1950*1 (CURRENT DISK NUMBER, USED IN CCP, ED) 0005H JMP BDOS (PRIMARY BDOS ENTRY POINT) 0038H JMP DDT (RESTAR FOR EACH DIRECTORY GROUP (4 ENTRIES PER GROUP), BASED UPON BLKSIZ AND DIRMAX CATED TO DATA AREAS) */ DECLARE TRAN(32) BYTE EXTERNAL, SECSIZ BYTE EXTERNAL, DIRMAX BYTE EXTERNAL, O BE 1024. AS A RESULT, BLKSHF = LOG2 (1024/128) = LOG2 8 = 3 (I.E., 2**3=8), AND BLKMSK = 2**BLKSHF-UMED TO EXIST EXTERNALLY, STARTING AT THE ADDRESS 'BASE' (NORMALLY 3E00H IN 16K CP/M), AND ARE ACCESSED THROUGH THE BD28/512 = 487.5 ALLOCATION BLOCKS WHICH IS TOO LARGE TO FIT A BYTE VARIABLE. THUS, USING AN ALLOCATION OF 1024 BYTEST FILLED BY DDT) 005CH - 007CH DEFAULT FILE CONTROL BLOCK 0080H - 00FFH DEFAULT BUFFER AREA 0040H OSTRKS = NUMBER OF SYSTEM TRACKS AS AN EXAMPLE, GIVEN A STANDARD DISKETTE WITH 77 TRACKS USING 26 SECTOBLKSHF BYTE EXTERNAL, BLKMSK BYTE EXTERNAL, MAXALL BYTE EXTERNAL, DIRBLK BYTE EXTERNAL, OSTRKS BYT1 = 2**3-1 = 8-1 = 7 FURTHER, WE ARE USING DIRSIZ = 64 DIRECTORY ENTRIES, AND THUS THE DATA AREA CONSUMED BY THE DIROS INTERFACE PROGRAM. 00 BASE: BOOT SYSTEM REBOOT OPERATION 01 BASE+3 WBOOT SYSTEM REBOOT - WAR, 1950*128/1024 = 243.75 ALLOCATION BLOCKS WHICH IS WITHIN THE BYTE VALUE 0-255. THE BLOCKS ARE NUMBERED F 0100H - CCP TRANSIENT PROGRAM AREA */ DECLARE JBOOT LITERALLY '0000H', JDDT LITERALLY '0038H', IOLOC RS PER TRACK, WITH TWO TRACKS DEDICATED TO THE OPERATING SYSTEM: SECSIZ = 26 (SECTORS PER TRACK) E EXTERNAL, CURDSK BYTE EXTERNAL; /* CURRENT DISK (EXTERN FOR ERRS) */ /* THE FIRST PAGE OF ROM IS ASSIM START 02 BASE+6 CONSTAT CONSOLE STATUS - RETURNS 0 IN REG-A IF NO CONSOLE DATA READY RY SIZE 7: INTERROGATE DEVICE STATUS 8: CHANGE DEVICE STATUS 9: PRINT BUFFER ON CONSOLE S NOT ZERO UPON RETURN FROM THE BIOS. 14 BASE+42 WRITE WRITE DISK SECTOR (SETTRK.'CONCHA', SELDISK EQU 'SELDIS', READ$DISK EQU 'READDI', CONECHO EQU 'CONECH', PERM$ERROR$SUB EQU 'PEISK DRIVE GIVEN BY REGISTER C (0,1,..) 10 BASE+30 SETTRK SET TRACK (0-76) GIVEN BY REGISTER C 11 BASE+33 SETSE 25: RETURN CURRENTLY SELECTED DISK NUMBER 26: SET SUBSEQUENT DMA ADDRESS 27: RETURN BASE ADDRESS OF AL FF IF CHARACTER IS READY 03 BASE+9 CONIN CONSOLE CHARACTER INTO ACCUMULATOR - 0 PARITY 10: READ BUFFER FROM CONSOLE 11: CONSOLE CHARACTER READY 12: LIFT HEAD (NOT USED IN CURRENT SYSTEMS) .SELDSK ASSUMED) ERROR RETURNS IN REGISTER A AS ABOVE */ /* FUNC IS THE DISK MONITOR RERR', SEL$ERROR$SUB EQU 'SELERR', RO$ERROR$SUB EQU 'RODERR', WRITE$DISK EQU 'WRITED'; /* EXTERNALLY DEC SET SECTOR NUMBER GIVEN BY REG C (1-26) 12 BASE+36 SETDMA SET DMA ADDRESS GIVEN BY REG PAIR B,C (INITIALLY LOCATION VECTOR 28: WRITE PROTECT CURRENTLY SELECTED DISK 29: RETURN R/O DISK BIT VECTOR 30: SET D 04 BASE+12 CONOUT CONSOLE CHARACTER SENT FROM REGISTER C 05 BASE+15 LIST SEND CHARACTER FROM REGISTER C 13: RESET DISK SYSTEM - SELECT DISK 0 14: SELECT DISK 'INFO' 15: OPEN FILE 16: CLOSE FILE FUNCTION NUMBER AS SHOWN BELOW: 0: SYSTEM RESET 1: READ CONSOLE DEVICE 2: WRITE CONSOLE DEVICE FINED LABELS AND VARIABLES */ DECLARE PERM$ERROR$SUB ADDRESS EXTERNAL, SEL$ERROR$SUB ADDRESS EXTERNAL, RO$ERROR$ DEFAULTED TO 80H) 13 BASE+39 READ READ DISK SECTOR (SETTRK, SETSEC, SELDSK ASSUMED) MA ADDRESS FOR DIRECTORY OPERATIONS */ DECLARE EQU LITERALLY 'LITERALLY', FOREVER EQU 'WHILE TR TO LIST DEVICE 06 BASE+18 PUNCH SEND CHARACTER FROM REGISTER C TO PUNCH DEVICE 07 BASE+21 READER READ CH 17: SEARCH FOR FIRST OCCURRENCE 18: SEARCH FOR NEXT OCCURRENCE 19: DELETE A FILE 20: READ 3: READ READER DEVICE 4: WRITE PUNCH DEVICE 5: WRITE LIST DEVICE 6: INTERROGATE MEMOSUB ADDRESS EXTERNAL, MEMSIZE ADDRESS AT(BDOSA), /* ADDRESS FIELD OF JUMP AT 5 */ FUNC BYTE EXTERNAL, /* A PERMANENT ERROR IS ASSUMED IF THE LEAST SIGNIFICANT BIT IUE', TRUE EQU '1', FALSE EQU '0', /* TRUNCATE EXTERNAL NAMES FOR ASSEMBLER INTERFACE */ CONCHAR EQU ARACTER TO REGISTER A WITH 0 PARITY 08 BASE+24 HOME MOVE DISK HEAD TO TRACK 0 09 BASE+27 SELDSK SELECT DA FILE 21: WRITE A FILE 22: CREATE A FILE 23: RENAME A FILE 24: RETURN LOGIN VECTOR MONITOR FUNCTION NUMBER */ INFO ADDRESS EXTERNAL, /* DATA TO ACT UPON */ ARET ADDRESS EXTERNAL, /* RETUR PRINT: PROCEDURE(A) EXTERNAL; DECLARE A ADDRESS; /* PRINT THE STRING STARTING AT ADDRESS A UNTIL THE NEXT OCCXTERNAL; END WRITE$DISK; TRSECT: PROCEDURE(SECTOR) EXTERNAL; DECLARE SECTOR BYTE; /* TRANSLATE AND SET SECTOR A SET */ GETBUFF EQU 'BUFF'; /* CAN REPLACE BY FUNCTION */ DECLARE DMX EQU 'DIRMAX', /* DMX IS THE LPROCEDURE BYTE EXTERNAL; END READIN; TRACK0: PROCEDURE EXTERNAL; END TRACK0; SELDISK: PROCEDURE(DISK) EXTERNAL CHARACTERS SCANNED UPON RETURN */ END READ; DECLARE MAXDSK EQU '3', /* MAX DISK NUMBER 0,1,... */ NN VALUE */ RET BYTE, /* SET TO LOW(ARET) */ LINFO BYTE; /* SET TO LOW(INFO) */ URRENCE OF A DOLLAR SIGN */ END PRINT; READ: PROCEDURE EXTERNAL; /* READ CHARACTERS FROM THE CONSOLE DEVICE INUMBER */ END TRSECT; /* CONSOLE COMMUNICATION PROCEDURES */ DECLARE /* SPECIAL CHARACTERS */ CTLC EQUAST DIRECTORY ENTRY NUMBER (LISTED AS 0, 1, ... , DMX) */ CHKSIZ EQU '16', /* SIZE OF CHECKSUM VECTORS */ ; DECLARE DISK BYTE; END SELDISK; SELTRK: PROCEDURE(TRACK) EXTERNAL ; DECLARE TRACK BYTE; END SELTRK; DISK EQU '4'; /* NUMBER OF DISKS = MAXDSK+1 */ DECLARE (DPTR,DCNT,DREC) BYTE, /* DIRECTORY OPERATIONS AND DA BOOT: PROCEDURE EXTERNAL; /* WARM START */ END BOOT; CONECHO: PROCEDURE BYTE EXTERNAL; /* READ CHARACTER, ECNTO THE MEMORY LOCATION GIVEN BY 'INFO', UNTIL THE FIRST CARRIAGE RETURN IS ENCOUNTERED. ALLOW BACKSPACE (RUBOUT), '03H', TAB EQU '09H', LF EQU '0AH', CR EQU '0DH'; DECLARE IOSTAT BYTE AT(IOLOC) ; /* IO STATUS BYTE CHKSHF EQU '4', /* LOG2 CHKSIZ */ OFFSET EQU 'OSTRKS', /* NUMBER OF TRACKS USED BY BOOT */ AL1 EQU ' SELSEC: PROCEDURE(SECTOR) EXTERNAL ; DECLARE SECTOR BYTE; END SELSEC; SELDMA: PROCEDURE(DMA) EXTERNAL ; DETA TRANSFERS TAKE PLACE AT TBUFF (NORMALLY 80H) UNLESS CHANGED BY SYSTEM CALLS */ BUFFA ADDRESS INITIAL(TBUFF), HO GRAPHICS */ END CONECHO; CONBRK: PROCEDURE BYTE EXTERNAL; END CONBRK; LSTOUT: PROCEDURE(CHAR) EXTERNAL; LINE ELIMINATE (CTL U), AND SYSTEM RE-BOOT (CTL C) */ /* THE INFO POINTER IS ASSUMED TO ADDRESS AN AREA OF ME */ TABOUT: PROCEDURE(CHAR) EXTERNAL; DECLARE CHAR BYTE; END TABOUT; CRLF: PROCEDURE EXTERNAL; END CRLF; DIRBLK', /* FIRST ALLOCATION VECTOR ELEMENT. EACH BIT THAT IS '1' RESERVES A 1 K BLOCK FOR THE DIRECTOCLARE DMA ADDRESS; END SELDMA; READ$DISK: PROCEDURE BYTE EXTERNAL; END READ$DISK; WRITE$DISK: PROCEDURE BYTE E DMAAD ADDRESS INITIAL(TBUFF), BUFF BASED BUFFA (128) BYTE, DIRSET BYTE INITIAL(FALSE), /* TRUE IF DIR DM DECLARE CHAR BYTE; END LSTOUT; PUNOUT: PROCEDURE(CHAR) EXTERNAL; DECLARE CHAR BYTE; END PUNOUT; READIN: MORY CONTAINING TWO BYTE QUANTITIES. THE FIRST GIVES THE MAXIMUM BUFFER LENGTH, AND THE SECOND IS SET TO THE NUMBER OFRY. EACH BLOCK IS 8 RECORDS BY 128 BYTES PER RECORD (NOTE THAT RESERVATIONS START ON THE LEFT OF THE W LFB EQU '31', FNM EQU '13'; /* LENGTH OF FILE NAME */ DECLARE S BASED INFO (33) BYTE, /* FILE CONTROL BLOCK TO GET A SINGLE DISK ENTRY */ DMK EQU '11B', /* MASK CORRESPONDING TO DSF */ FLN EQU '32',15 OTHERWISE IT POINTS TO ALLOCATED DISK BLOCK THE FILE CONTROL BLOCK IS FOLLOWED BY ONE BYTE OF ECTOR 0 */ CHECK1 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 1 */ CHECK2 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 2 */ CH UNDEFINED NOW) NAME : 8 CHARACTER PRIMARY NAME EXT : 3 CHARACTER EXTENT ORD */ ALLOC0 (32) BYTE, /* ALLOCATION VECTOR FOR DISK 0 */ ALLOC1 (32) BYTE, /* ALLOCATION VECTOR FOR DISK PASSED TO THE DISK MONITOR FROM THE USER */ SZ BASED INFO BYTE; /* SZ = S(0) */ /* FSL EQU '5', /* AMOUNT TO SHIFT TO MULTIPLY BY THE FCB LENGTH (FLN) */ FDM EQU '1INFORMATION WHICH GIVES THE NEXT RECORD TO BE READ OR WRITTEN IN AN OPENED FILE. THIS INFORMATION IS NOECK3 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 3 */ CHECKA ADDRESS, /* POINTER TO CURRENT VECTOR */ CHECK BASED CHE COM IMPLIES COMMAND TYPE (OTHERWISE UNDEFINED NOW) REEL NO : 'REEL NUMBER' FIR 1 */ ALLOC2 (32) BYTE, /* ALLOCATION VECTOR FOR DISK 2 */ ALLOC3 (32) BYTE, /* ALLOCATION VECTOR FOR DISK 3 *THE FILE CONTROL BLOCK FORMAT IS SHOWN BELOW: ---------------------------------------------------------- 6', /* BEGINNING OF DISK MAP */ FRL EQU '32', /* LOCATION OF REC TO R/W */ FRC EQU '15', /* LOCATION OF RECOT A PART OF THE DIRECTORY. EACH READ OR WRITE WILL INCREMENT THIS RECORD COUNT. */ DECLARECKA (CHKSIZ) BYTE; /* CHECK SUM TEMPLATE */ DECLARE EMP EQU '0E5H', MAL EQU 'MAXALL', /* LARGEST BLOCK ST REEL IS 0, SECOND IS 1, AND SO FORTH UNTIL 255. XXX : UNUSED FOR NOW R/ ALLOCA ADDRESS, /* POINTER TO CURRENTLY REFERENCED ALLOC */ ALLOC BASED ALLOCA (32) BYTE; /* ALLOC VECTOR / 1 BY / 8 BY / 3 BY / 1 BY /2BY/1 BY/ 16 BY / /FILETYPE/ NAME / EXT / REEL NO/XXX/RCNT/DM0 .. DM1RD COUNT (MUST BE ONE BELOW DISK MAP) */ FRE EQU '12', /* POSITION OF REEL NUMBER */ OLDDSK BYTE, /* DISK ON ENTRY TO DOS */ FCBDSK BYTE, /* DISK NAMED IN FCB */ DLNUMBER */ MRC EQU '127', /* LARGEST RECORD NUMBER */ DSF EQU '2', /* AMOUNT TO SHIFT 128 BYTE RECORD CNT : RECORD COUNT IN FILE (0 TO 127) DM0 ... : DISK ALLOCATION MAP. 255 IF NOT ALLOCATED, DMTEMPLATE */ DECLARE RODSK BYTE INITIAL(0),/* READ ONLY DISK BIT VECTOR */ CHECK0 (CHKSIZ) BYTE, /* CHECK SUM V5/ ---------------------------------------------------------- FILETYPE : 0E5H IF AVAILABLE (OTHERWISEOG BYTE INITIAL(0), /* BIT VECTOR GIVING LOGGED-IN DISKS */ CURTRKV(NDISK) BYTE, /* TRACK VECTOR */ CURREAD$DISK; ELSE COND = WRITE$DISK; IF COND = 0 THEN RETURN; /* DISK I/O SUCCESSFUL */ /* ARRI+ SECSIZ); CURREC = T; CURTRK = CURTRK + 1; END; /* WE ARE NOW POSITIONED OVER THE TRACK CONT/* SEEK THE RECORD CONTAINING THE CURRENT DIRECTORY ENTRY */ ARECORD = DOUBLE(DREC := SHR(DCNT,DSF)); CALL SEEK; L RECORD */ HOME: PROCEDURE; /* MOVE TO HOME POSITION, THEN OFFSET BY DOS TRACKS */ CALL TRACK0; /* AT HO* COMPUTE ACTUAL TRACK ADDRESS (ASSUMES A PREVIOUS CALL TO INDEX */ ARECORD = SHL(ARECORD,BLKSHF) OR (VRECORD AND BRECV(NDISK) ADDRESS, /* RECORD VECTOR */ CURTRKA ADDRESS, /* POINTS TO CURRENT TRACK NUMBER */ CURRECVE HERE AFTER TOO MANY READ WRITE FAILURES */ CALL PERM$ERROR$SUB; END WAITIO; RDBUFF: PROCEDURE; /* START ANAINING THE ACTUAL RECORD. THE SECTOR TO BE READ IS ARECORD - CURREC + 1. THE TRACK NUMBER IS CURTRK */ CALL SEEND SEEK$DIR; COMPUTE$CS: PROCEDURE BYTE; /* COMPUTE CHECKSUM FOR CURRENT DIRECTORY BUFFER */ DECLARE (I,CS) BYTE;ME POSITION */ CALL SELTRK(OFFSET); /* SELECT FIRST DIRECTORY POSITION */ CURREC, CURTRK = 0; END HOME; SEEKLKMSK); END ATRAN; GETFCB: PROCEDURE; /* SET VARIABLES FROM CURRENTLY ADDRESSED FCB */ VRECORD = S(FRL); A ADDRESS, /* POINTS TO CURRENT RECORD NUMBER */ CURREC BASED CURRECA ADDRESS, /* CURRENTLY ADDRESSED RECORD */ I/O AND WAIT FOR IO FINISH */ CALL WAITIO(TRUE); END RDBUFF; WRBUFF: PROCEDURE; /* WRITE THE BUFFER, SELECT LTRK(CURTRK+OFFSET); CALL TRSECT(ARECORD - CURREC); END SEEK; WAITIO: PROCEDURE(READING); DECLARE READING BYT CS = 0; DO I = 0 TO LAST(BUFF); CS = CS + GETBUFF(I); END; RETURN CS; END COMPUTE$CS;: PROCEDURE; /* SEEK THE TRACK GIVEN BY ARECORD (ACTUAL RECORD) */ DECLARE T ADDRESS; DO WHILE ARECORD < C RCOUNT = S(FRC); END GETFCB; SETFCB: PROCEDURE; /* PLACE VALUES BACK INTO CURRENTLY ADDRESSED FCB, AND I CURTRK BASED CURTRKA BYTE, /* CURRENT TRACK 0-76 */ RCOUNT BYTE, /* RECORD COUNT IN CURRENTLY NON-DELETED DATA */ CALL WAITIO(FALSE); END WRBUFF; INDEX: PROCEDURE; /* COMPUTE DISK BLOCK NUMBER FROM CUE; /* TRUE IF READING, FALSE IF WRITING */ DECLARE COND BYTE; /* CONDITION UPON RETURN */ IF READING THEN COND = SET$CDISK: PROCEDURE(MASK) BYTE; /* SET A '1' VALUE IN CURDSK POSITION OF MASK */ DECLARE MASK BYTE; RETURN MURREC; CURREC = CURREC - SECSIZ; CURTRK = CURTRK - 1; END; DO WHILE ARECORD >= (T := CURREC NCREMENT THE RECORD COUNT */ S(FRL) = VRECORD + 1; S(FRC) = RCOUNT; END SETFCB; SEEK$DIR: PROCEDURE; ADDRESSED FCB */ VRECORD BYTE, /* CURRENT VIRTUAL RECORD */ ARECORD ADDRESS; /* CURRENT ACTUARRENT FCB ADDRESSED BY INFO */ ARECORD = S(FDM+SHR(VRECORD,BLKSHF)); END INDEX; ATRAN: PROCEDURE; /ASK OR ROR(ROL(1,CURDSK+1),1); END SET$CDISK; NOWRITE: PROCEDURE BYTE; /* RETURN TRUE IF DIR CHECKSUM DIFFERENCE */OC$BIT; SET$ALLOC$BIT: PROCEDURE(I,B); /* SET THE I-TH BIT OF ALLOC TO THE LSB OF B */ DECLARE (I,B) BYTE; ALTIALIZING SYSTEM */ /* READ NEXT DIRECTORY ENTRY (SET DCNT=255 INITIALLY)*/ IF (DCNT:=DCNT+1) > DMX THEN DO; TR+1) = '$'; /* SET ALLOC BIT TO 1 FOR EACH NON-ZERO DM ENTRY */ CALL SCANDM(1); END; HEN RETURN; /* SKIP IF BEYOND CHECKED AREA */ IF INIT THEN /* SET CHECKSUM VALUE */ CHECK(DREC) = COMPUTE$CS; ELSEOCEDURE; DECLARE I BYTE; /* INITIALIZE THE DISK SYSTEM */ RET = FALSE; /* SET TO TRUE IF $ FILE EXISTS */ RETURN ROL(ROR(RODSK,CURDSK+1),1); END NOWRITE; SET$RO: PROCEDURE; /* SET CURRENT DISK TO READ ONLY */ RLOC(SHR(I,3)) = ROR((GET$ALLOC$BIT(I) AND 0FEH) OR B, (I AND 111B) + 1); END SET$ALLOC$BIT; SCANDM: PROCEDURE(DCNT = 255; RETURN; END; IF (DPTR:=SHL(DCNT AND DMK,FSL)) = 0 THEN DO; CALL SEEK$DIR; CALL RDBUF END; END INITIALIZE; DECLARE SEARCHL BYTE, /* SEARCH LENGTH SET BY SEARCH */ SEARCHA ADDRESS; /* IF CHECK(DREC) <> COMPUTE$CS THEN /* CHECKSUM ERROR */ CALL SET$RO; /* DISK SET TO READ ONLY */ END CHECKSUM RODSK = 0; /* NO READ ONLY DISKS AT THIS POINT */ ALLOC(0) = AL1; DO I=1 TO LAST(ALLOC); ALLOC(I)=0; ENDODSK = SET$CDISK(RODSK); END SET$RO; CHECK$WRITE: PROCEDURE; /* CHECK FOR WRITE PROTECTED DISK */ IF NOWRITE TBIT); DECLARE (BIT, I, K) BYTE; /* SCANDM SCANS THE DISK MAP ADDRESSED BY DPTR FOR NON-ZERO ENTRIES -- THE ALLOCAF; CALL CHECKSUM(INIT); /* CHECKSUM OPERATION */ END; END READ$DIR; GET$ALLOC$BIT: PROCEDURE(I) BYTE; SEARCH ADDRESS SET BY SEARCH */ SEARCHN: PROCEDURE; /* SEARCH FOR THE NEXT DIRECTORY ELEMENT, ASSUMING A PREVIOUS ; WRDIR: PROCEDURE; /* WRITE THE CURRENT DIRECTORY ENTRY, SET CHECKSUM */ CALL CHECKSUM(TRUE); /* INITIALIZE ENTRY ; CALL HOME; DCNT = 255; DO FOREVER; CALL READ$DIR(TRUE); IF DCNT = 255 THEN RETURN; HEN CALL RO$ERROR$SUB; END CHECK$WRITE; CHECKSUM: PROCEDURE(INIT); DECLARE INIT BYTE; /* COMPUTE CURRTION VECTOR ENTRY CORRESPONDING TO A NON-ZERO ENTRY IS SET TO THE VALUE OF 'BIT' */ DO I = DPTR+FDM TO DPTR+LFB; /* RETURN THE I-TH BIT OF ALLOC */ DECLARE I BYTE; RETURN ROL(ALLOC(SHR(I,3)), (I AND 111B)+1); END GET$ALL CALL ON SEARCH WHICH SETS SEARCHA AND SEARCHL */ DECLARE (I,C) BYTE; INFO = SEARCHA; DO FOREVER; CA*/ CALL WRBUFF; /* WRITE THE BUFFER */ END WRDIR; READ$DIR: PROCEDURE(INIT); DECLARE INIT BYTE; /* TRUE IF INI IF GETBUFF(DPTR) <> EMP THEN DO; /* CHECK FOR $ FILE (IN CASE OF SUBMIT) */ RET = RET OR GETBUFF(DPENT CHECKSUM RECORD AND UPDATE THE DIRECTORY ELEMENT IF INIT, OR CHECK FOR EQUALITY IF NOT */ IF DREC >= CHKSIZ T IF (K := GETBUFF(I)) <> 0 THEN CALL SET$ALLOC$BIT(K,BIT); END; END SCANDM; INITIALIZE: PRLL READ$DIR(FALSE); IF (RET := DCNT) = 255 THEN RETURN; I = 0; DO WHILE (I < SEARCHL) AND RENTLY ADDRESSED DIRECTORY ENTRY */ DO WHILE (L:=L-1) <> 255; BUFF(L+DPTR) = S(B+L); END; CALL SAND IS CLOSEST TO THE BLOCK 'L'. RETURN A 0 IF NO BLOCK IS AVAILABLE */ DECLARE (L, R) BYTE; R = L; END OPEN; CLOSE: PROCEDURE; /* LOCATE THE DIRECTORY ELEMENT AND RE-WRITE */ RET = 0; IF NOWRITE THEN RETY UP THROUGH THREE CHARACTER EXTENT */ CALL SEARCH(FRE); DO FOREVER; IF DCNT = 255 THEN /* NO MORE ENTRIES MA CALL CHECK$WRITE; /* IN CASE WRITE PROTECTED */ /* SEARCH UP TO THE REEL NUMBER FIELD */ CALL SEARCH(FRE); S(FDM /* MATCH OR QUESTION MARK */ ((C := S(I)) = GETBUFF(DPTR+I) OR C = 63); I = I + 1; EEK$DIR; CALL WRDIR; /* WRITE DIR ENTRY */ END COPY$DIR; COPY$FCB: PROCEDURE; /* COPY THE ENTIRE FILE CONTROL DO WHILE (R < MAL) OR (L > 0); L = L - (1 AND L > 0); R = R + (1 AND R < MAL); IF NOT GET$ALLOC$BIT(URN; /* SKIP CLOSE IF WRITE PROTECTED */ CALL SEARCH(FNM); IF DCNT <> 255 THEN CALL COPY$FCB; END CLOSE;TCH */ RETURN; /* SET EACH NON-ZERO DISK MAP ENTRY TO 0 IN ALLOC VECTOR */ CALL SCANDM(0); BUFF(DPTR)) = SZ; /* ASSUME SAME DISK DRIVE FOR NEW NAMED FILE */ DO WHILE DCNT <> 255; CALL COPY$DIR(FDM,FRE); CALEND; IF I = SEARCHL THEN RETURN; END; END SEARCHN; SEARCH: PROCEDURE(XL); DECLARE XL BYTE; BLOCK */ CALL COPY$DIR(0,FRL); END COPY$FCB; RENAME: PROCEDURE; /* RENAME THE FILE DESCRIBED BY THE FIRST HAR) THEN RETURN R; IF NOT GET$ALLOC$BIT(L) THEN RETURN L; END; RETURN 0; END GET$BLOCK; COPY$DIR: MAKE: PROCEDURE; /* CREATE A NEW FILE; FIRST CREATE ENTRY IN THE DIRECTORY. FILE IS OPENED UPON RETURN */ D = EMP; /* ARECORD HAS BEEN PREVIOUSLY SOUGHT BY READDIR */ CALL WRDIR; /* WRITE DIRECTORY ENTRY */ CL SEARCHN; END; END RENAME; OPEN: PROCEDURE; DECLARE I BYTE; /* SEARCH FOR DIRECTORY ENTRY, COPY TO SEARCHL = XL; SEARCHA = INFO; DCNT = 255; CALL HOME; /* NOW READY TO READ THE DISK */ CALL SEARCHN; LF OF THE CURRENTLY ADDRESSED FILE CONTROL BLOCK. THE NEW NAME IS CONTAINED IN THE LAST HALF OF THE CURRENTLY ADDRESS PROCEDURE(B,L); DECLARE (B,L) BYTE; /* COPY FCB INFORMATION STARTING AT BYTE B FOR L BYTES INTO BEGINNING OF CURECLARE I BYTE, FCB ADDRESS; CALL CHECK$WRITE; /* MAY BE WRITE PROTECTED */ FCB = INFO; INFO = .(EMP); ALL SEARCHN; END; END DELETE; GET$BLOCK: PROCEDURE(L) BYTE; /* FIND A BLOCK WHICH IS AVAILABLE ON THE DISK FCB */ CALL SEARCH(FNM); IF DCNT <> 255 THEN DO I=FNM TO LFB; S(I) = GETBUFF(DPTR+I); END; END SEARCH; DELETE: PROCEDURE; DECLARE (I,J,K) BYTE; CALL CHECK$WRITE; /* WRITE PROTECTED? */ /* SEARCH ONLED FILE CONTROL BLOCK. THE FILE TYPE, FILE NAME, AND FILE EXT ARE CHANGED, BUT THE REEL NUMBER FIELD IS IGNORED */ /* LOOK FOR AN EMPTY DIRECTORY ENTRY */ CALL SEARCH(1); IF DCNT <> 255 THEN DO; /* SET ELEMENTS TO ZERO */ /* NOW READ THE BUFFER */ CALL SETDMA; /* SELECTS DATA DMA ADDRESS */ CALL RDBUFF; CALL RTHEN CALL SELDMA(BUFFA); END RESETDMA; DISKREAD: PROCEDURE; CALL GETFCB; IF RCOUNT <= VRECORD THEN END; END; /* CONTINUE IF NO ERROR IN ALLOCATION */ IF RET = 0 THEN DO; CALL RE) = S(FRE) + 1; CALL SEARCH(FNM); IF DCNT = 255 THEN DO; IF READING THEN RETURN; CALL MAKE; IS SHOULD BE THE LAST ALLOCATED BLOCK FOR THIS FILE, OR THE VALUE 0 IF NO SPACE HAS BEEN ALLOCATED TO INFO = FCB; DO I=FNM TO LFB; S(I) = 0; END; /* COPY INTO DIRECTORY ENTRYESETDMA; /* SELECTS DIR DMA ADDRESS */ CALL SETFCB; END; END; END DISKREAD; DISKWRIT DO; RET = 1; IF VRECORD = 128 THEN CALL OPEN$REEL(TRUE); VRECORD = 0; IF RET <> 0 THEN RETURN; ATRAN; CALL SEEK; CALL SETDMA; CALL WRBUFF; CALL RESETDMA; IF R END; ELSE CALL OPEN; IF DCNT = 255 THEN DO; RET = 1; /* END OF FILE IN DISK READ */ RETURN; THIS FILE */ I = 0; IF (L := FDM + SHR(VRECORD,3)) > FDM THEN /* THERE IS A PREVIOUS BLOC */ CALL COPY$FCB; END; END MAKE; OPEN$REEL: PROCEDURE(READING); DECLARE READING BYTE; /* CE: PROCEDURE; DECLARE (I,L) BYTE; CALL CHECK$WRITE; /* IN CASE WRITE PROTECTED */ CALL GETFCB; IF VRECORD > END; DO; CALL INDEX; /* ERROR 2 IF READING UNWRITTTEN DATA */ IF LOW(ARECORD) = 0 THEN RET = 1COUNT <= VRECORD THEN RCOUNT = VRECORD+1; /* CHECK FOR END-OF-REEL, IF FOUND ATTEMPT TO OPEN NEXT REEL END; CALL GETFCB; RET = 0; END OPEN$REEL; SETDMA: PROCEDURE; /* SELECT DATA DMA ADDRESS */ IF DK ALLOCATED */ I = S(L-1); IF (I := GET$BLOCK(I)) = 0 THEN /* NO MORE SPACE */ RET = 2; ELSE LOSE CURRENT REEL AND OPEN THE NEXT ONE, IF POSSIBLE READING IS TRUE IF WE ARE IN READ MODE */ CALL CLOSE; /* RETMRC THEN /* PAST EOF, NEXT REEL NOT OPENED */ RET = 1; ELSE DO; CALL INDEX; IF LOW(ARECORD) = 0 THEN ; ELSE DO; CALL ATRAN; /* ARECORD IS NOW ACTUAL DISK ADDRESS */ CALL SEEK; IN PREPARATION FOR THE NEXT WRITE */ IF VRECORD = MRC THEN DO; /* UPDATE CURRENTIRSET THEN CALL SELDMA(DMAAD); END SETDMA; RESETDMA: PROCEDURE; /* RESELECT ORIGINAL DMA ADDRESS */ IF DIRSET DO; CALL SET$ALLOC$BIT(I,1); /* BLOCK IS ALLOCATED */ ARECORD, S(L) = I; REMAINS AT 255 IF WE CANNOT OPEN THE NEXT REEL */ IF DCNT = 255 THEN RETURN; /* INCREMENT THE REEL NUMBER */ S(F/* NOT ALLOCATED */ DO; /* THE ARGUMENT TO GET$BLOCK IS THE STARTING POSITION FOR THE DISK SEARCH - TH FCB BEFORE GOING TO THE NEXT EXTENT */ CALL SETFCB; CALL OPENREEL(FALSE); /* VRECORD REMAINS BLIC; LINFO = LOW(INFO); ARET, RET, FCBDSK = 0; DO CASE FUNC; /* 0: SYSTEM RE-BOOT */ CALL BOOT; ROCEDURE; IF LINFO <> CURDSK THEN DO; CURDSK = LINFO; CALL SELECT; END; END CURSELECT; RESELECT:*/ DO; CALL RESELECT; CALL CLOSE; END; /* 17: SEARCH FOR FIRST OCCURRENCE OF A FILE */ E THAT THIS ASSUMES THERE ARE NO MORE THAN 8 DISKS ON THE SYSTEM - OTHERWISE REPLACE BY .ALLOC0(SHL(DOUBLE(CURDSK),5))/ CALL PRINT(INFO); /* 10: READ BUFFER FROM THE CONSOLE */ CALL READ; /* 11: CHECK FOR CONSOLE INPUTAT MRC CAUSING END-OF-FILE IF NO MORE DIRECTORY SPACE IS AVAILABLE */ IF RET = 0 THEN VRECORD /* 1: READ CONSOLE */ RET = CONECHO; /* 2: WRITE CONSOLE */ CALL TABOUT(LINFO); /* 3: READ READER PROCEDURE; /* CHECK CURRENT FCB TO SEE IF RESELECTION NECESSARY */ IF (LINFO := (SZ AND 1$1111B) -1) < 30 THEN DO; CALL RESELECT; CALL SEARCH(FNM); END; /* 18: SEARCH FOR NEXT OCCURRENCE OF A FILE NAME */ DO */ CHECKA = .CHECK0(SHL(CURDSK,CHKSHF)); CURTRKA = .CURTRKV(CURDSK); CURRECA = .CURRECV(CURDSK); /* SET READY */ RET = CONBRK; /* 12: */ ; /* 13: RESET DISK SYSTEM, INITIALIZE TO DISK 0 */ DO; C= 255; /* GOES TO ZERO */ RET = 0; END; CALL SETFCB; END; EDEVICE */ RET = READIN; /* 4: WRITE PUNCH DEVICE */ CALL PUNOUT(LINFO); /* 5: WRITE LIST DEVICE */ DO; OLDDSK = CURDSK; FCBDSK = SZ; SZ = SZ AND 1110$0000B; CALL CURSELECT; END; END RESELECT; SELBU; INFO = SEARCHA; CALL RESELECT; CALL SEARCHN; END; /* 19: DELETE A FILE */ DO; CALL RESELECT; CONTROLLER */ CALL SELDISK(CURDSK); /* CHECK TO INSURE THAT DISK IS LOGGED IN */ IF NOT ROR(ROL(DLOG,1),CURDSKURDSK,DLOG,DIRSET = 0; INFO = TBUFF; CALL SELBUFFA; CALL SELECT; END; /* 14: SELECT DISK 'INFO' ND; END DISKWRITE; SELECT: PROCEDURE; /* SELECT DISK 'INFO' FOR SUBSEQUENT INPUT OR OUTPUT OPERATIONS */ CALL LSTOUT(LINFO); /* 6: INTERROGATE MEMORY SIZE */ ARET = MEMSIZE; /* 7: INTERROGATE DEVICE STATUS FFA: PROCEDURE; /* SELECT DMA BUFFER ADDRESS */ CALL SELDMA(BUFFA := INFO); END SELBUFFA; DSKMON: PROCEDURE PU CALL DELETE; END; /* 20: READ A FILE */ DO; CALL RESELECT; CALL DISKREAD; END; +1) THEN DO; DLOG = SET$CDISK(DLOG); CALL INITIALIZE; END; END SELECT; CURSELECT: P*/ CALL CURSELECT; /* 15: OPEN */ DO; CALL RESELECT; CALL OPEN; END; /* 16: CLOSE IF CURDSK > MAXDSK THEN /* SELECTION ERROR */ CALL SEL$ERROR$SUB; ALLOCA = .ALLOC0(SHL(CURDSK,5)); /* NOT*/ ARET = IOSTAT; /* 8: CHANGE DEVICE STATUS */ IOSTAT = LINFO; /* 9: PRINT BUFFER AT THE CONSOLE * /* 21: WRITE A FILE */ DO; CALL RESELECT; CALL DISKWRITE; END; /* 22: CREATE A FILE */      NN ; OOPPQQ dR?<, SS?<, TT, +TE PROTECT CURRENT DISK */ CALL SET$RO; /* 29: RETURN R/O BIT VECTOR */ RET = RODSK; /* 30: SET DIRE76HI88JRS99Tde::f;;<<==?>> DO; CALL RESELECT; CALL MAKE; END; /* 23: RENAME A FILE */ DO; CALL RESELECT; CALLUVVAWWXX> YYm? ZZ[CTORY DMA */ DO; DIRSET = TRUE; /* MARK AS SEPARATE DIR AREA */ CALL SELBUFFA; END; END; /* OF C ??? Zm= H@@AABBCCT Z+U RENAME; END; /* 24: RETURN THE LOGIN VECTOR */ RET = DLOG; /* 25: RETURN SELECTED DISK NUMBER */   !!""##$$%%[T \\m? ]]^^j __ R ; +  Y0;`ASES */ GOBACK: IF FCBDSK <> 0 THEN /* RESTORE DISK NUMBER */ DO; SZ = FCBDSK; LINFO = OLDDSK; CALL CURSELECT;DD Z.0> EE H!6FFTUGGV Z.;+WHH Z: RET = CURDSK; /* 26: SET THE SUBSEQUENT DMA ADDRESS TO INFO */ DO; IF DIRSET THEN DMAAD = INFO; EL&&''(())  **   ++,,--../LMNcde`aa bb R ; d:;*:;ccdd END; /* RETURN A SINGLE OR DOUBLE BYTE VALUE */ ARET = ARET OR RET; END DSKMON; END;  :> II H!3JJVWKK H* ?LL Z+ ?MMSE CALL SELBUFFA; END; /* 27: RETURN THE LOGIN VECTOR ADDRESS */ ARET = ALLOCA; /* 28: WRI/00112233%&44'()55*+,66-457 ee Y<ff Y<gghh ii:l  Y <~ + = ~  Z ? >;l !3Z[?@A B;&! "+It<+ #? $?> % ?| &m ? }d~+m?D : Y &嘃? P   ? <f ?: dAm? c<+d; &ebf;  -&:  Y  < $- Yjj Ykkll mmQ<  1;nCDE;&F;&G H; &\m; *]:  '() ; *+, R  Y +$- -.? de ;  < f;v  | ;   + d? : :;*  Y 0)  1)?n,n,dcgh; !3ibcj;n?oopp qqrr; &ss0&Xm; *Ytt:  Y &I; !3\]J?K;&L^Mm? N+  O/ ;2  0123 ? +;2 * m0*$-   R  Y -& m; -+n,dgm; -++ n,0;v-&+; *$Y : $Y :? :*?P    *k`almn ;, op, < q Y  *< uu; !3XYvv wwxx ;( yyz: Y + PQR:Y Y 1)$;*Sm?D T n456D ;Z 78:;+<l Z+;l *[< ? v  ? v fgmėm?| ?T  ; $-< @, ; r;&st?u? vwx> yz{?f |z$- mEV;( *{{||: }}$- ;EN~~U^_VWXYZ[\ ]^_` ;a`b ;  h $0< +i ; *  Y:; *  Y? JJ;*KKL;&MM+Nm? OO;&PP+,,?R --+.// Y!300m ? 11+GIJm;*-KA-LMOIt ;^Y;PHs ;Y;$QlmR ;&?: dm ? +'(oo;&(')ppq " m(? *+rr:";:4 Y ",ss(-t hi? ?  m( m?  Q RRSST  ?j UU b0+!V;&"! WWX ? YY223 d455?h 6677?* 88+99:;&;:$Y;HRST:6o;ZU  ?VWXEN $-  ? h ?f  ; ;t%./uu+)0vvw? 1xx?2yy? 3zz?T 4{{? 5||; ?f m ?  : Y* j+?ZZ? [[?> \\? ]]? ^^"__``aa bb;<<==? >>;&??@@ AAdB  ?^v.YZ  ? <[? \.]^_\`;;  m? !!+""## ;$$;~ & nm;~ *o%%**}6$-<*78~~++9:;? m? <=>+km( m? ?   jk    *     m ? cc?f dd? eem;*#ff;&$#ggh?j ii b0+% jj!CCDD EEdF  ?^GGHH II*/a<?Fb/cderfg m*$0<+:~  Y &&&;~ !3no''? (())** ; ++,;&,?;&@+A? B)C$DEFF+;@ & lm;@ *m@ ;*  Y::@  Y  ;@ !3#$kk;"&%llR+0 m,&&mm4$0  Y<"&'nn " ? <"+0h< < m*i?\j0klmn>?@ABCDEFGHIJKLOPQR1+S G?r? 1H?r?h 1I?r E= $? $   1 F= $? $s  1 =?T<1>1?;&;&;&8;? :$5$ 1 ;$b:$; 1 <$S 1 =$5$n 1 >o ; ?^pqrs b0<tu8; <<<?\S+0> lm <no? 1J<1K<1LG = $? $e  1 H = $? $  1 I = ?F1@?\1A?r?* 1B?r 1 ?= $9$9$5% $5% $2 $Z  1 @$L 1v  _pwx2?(1yz3?><1{|4  ?1}~ $:$.$;p qr =s $5$}:$;t $9$9$5%uv $=wdM ;NM?N1O ;1P?P 1$? $  1 J$5$ 1 K$5$ 1 L = ?R 1C?rm ? 1D ;?r A= $? $  1 B= $? $  15?<16  ?17  ?j18 ;1x 2$ 1yz 3$5$y 1{| 4$u:$; 1}~ 5$5$D 1Q<1R;&?1p23456789:;<=$ M $5$ N M $2 N  1 O$5$L 1 P$ 1? 1E?r?> 1F?r? 1 C= $? $:% ;  1 D= $5$: $? $.  19:;1:<1;  ?R1<?z1 6$O:$; 1 7$c:$; 1 8$5$ 1 9$5$ 1 Q$5$8 1 R = $5% $2  1  1  $6% SBDOS OBJECT MODULE PLACED IN :F1:BDOS.OBJ COMPILER INVOKED BY: PLM80 :F1:BDOS.PLM PAGEWIDTH(80) PAGELENGTH(58) TITLE('BAS QU]dor ** *+-?!B,Kgl*uy0|!q:Ґ2Ö2:Ÿ!*3" $  001A - 0039H TRAN = STANDARD SECTOR TRANSLATE TABLE (ACCESS TO TRAN IS ONLY THROUGH TRSECT) CINFOARETBOOTCONECHCONBRKLSTOUTPUNOUTREADINTRACK0SELDISSELTRKSELSECSELDMAREADDIWRITEDTRSECTTAB THE BDOS AREA (SEE THE BDOSI INTERFACE) AND CAN BE ALTERED TO FIT A RANGE OF DISK DRIVES  = $.5$ $5$# $L  S $5$0$   BB"@ -IC DISK OPERATING SYSTEM') DATE(15 AUG 78) 1 BDOS: DO; /* (NORMALLY ORG'ED DIR}   |&", |!"&*M!O* n&"$L ) a 003AH SECSIZ = NUMBER OF SECTORS PER TRACK (<=3 - 2) 003BHOUTCRLFPRINTREAD@P0015@P0048@P0055@P0069@P0070@P00711@P0072@P0086@P0089@P0099@P0101@P0102t  STARTING WITH THE BASE OF THE BDOS AREA: 0009 - 000AH PERERR = .PERM ERROR SUB  1 @$y 1 A= $l $  1 B= $lECTLY AFTER BDOSI AT 3100H IN 16K CP/M) - */ /* COPYRIGHT (C) 1976*M!:!"~$ 9 (" * ~2* ~2q$  : DIRMAX = LARGEST DIRECTORY ENTRY NUMBER ( - 0..254) THE FOLLOWING VALUES ARE BADSKMONqmk g"*M*>w#6*wk$   g*ROUTINE 000B - 000CH SELERR = .SELECT ERROR SUBROUTINE 000D - 000EH RODERR = $  1 C= $l $J:A% ;  1 D= $5$g,1977,1978 DIGITAL RESEARCH BOX 579, PACIFIC GROVE PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 1 ISIS-II PL/M-80 V3.0 COMPILATION OF MODULE SED UPON A BLOCK ALLOCATION SIZE OF BLKSIZ, WHICH IS USUALLY 1K FOR SINGLE DENSITY, ;*:+s#r*5*:"c**s#r*4;*:O*Mɵ" #9Na$&5<EH .READ ONLY DISK ERROR SUBR 001A - 0019H TRSECT = SECTOR TRANSLATE SUBROUTINE BDOS0T  *TRANSECSIZDIRMAXBLKSHFBLKMSKMAXALLDIRBLKOSTRKSCURDSKPERERRSELERRRODERRFUN CALIFORNIA, 93950 USER DEFINED PARAMETERS ARE FOUND AT THE BEGINNING OF 2K FOR DOUBLE DENSITY, AND MUST BE COMPUTED IN SUCH A W - AY THAT THE MAXIMUM A 1950*128/1024 = 243.75 ALLOCATION BLOCKS WHICH IS WITHIN THE BYTE VALUE 0-255. THE BLOCKS ARE DISK OPERATING SYSTEM 15 AUG 78 PAGE 2 GIVEN TWO SYSTEM TRACKS, WE HAVE A USABLE STORAGE., THE FIRST TWO BLOCKS CANNOT BE ALLOCATED TO DATA AREAS) */ 2 1 DECLARE TRAN(32 - ROUP), BASED UPON BLKSIZ AND DIRMAX 0040H OSTND BLKMSK = 2**BLKSHF-1 = 2**3-1 = 8-1 = 7 FURTHER, WE ARE USING DIRSIZ = 64 DIRELLOCATION VALUE IS LESS THAN OR EQUAL - TO 255 (A BYTE QUANTITY). NUMBERED - FROM ZERO THROUGH 242 (THE LAST 3/4 OF AN ALLOCATION BLOCK IS LOST) - AREA OF 77-2 TRACKS TIMES 26 SECTORS PER TRACK = 75*26 = 1950 S - ECTORS ) BYTE EXTERNAL, SECSIZ BYTE EXTERNAL, DIRMAX BYTE EXTERNAL, BLKSHFRKS = NUMBER OF SYSTEM TRACKS AS AN EXAMPLE, GIVEN A STANDARD DISKETTE WITH 77 TRACKS USING - CTORY ENTRIES, AND THUS - THE DATA AREA CONSUMED BY THE DIRECTORY IS 64/4 = 16 SECTORS 003CH BLKSHF = LOG2 OF BLOCK SIZE (BLKSIZ) 003DH BLKMSK = 2**BLKSHF-1 , AND THUS THE VALUE MAXALL = 242 (MAXIMUM ALLOCATION NUMBER) GIVEN 512 BYTES PER ALLOCATION, WE GET 1950*128/512 = 487.5 ALLOCATION BLOCKS BYTE EXTERNAL, BLKMSK BYTE EXTERNAL, MAXALL BYTE EXTERNAL, DIRBL 26 SECTORS PER TRACK, WITH TWO TRACKS DEDICATED TO THE OPERATING SYSTEM: SECSIZ WHICH USES A TOTAL OF 2 OF THE BASIC BLOCKS (OF 1024 BYTES EAC - H) AND THUS THE AR 003EH MAXALL = MAXIMUM ALLOCATION NUMBER 003FH DIRBLK = BIT PATTERN WHI FURTHER, THE VALUE OF BLKSIZ (WHICH IS ONLY USED IN THE FOLLOW - ING COMPUTATIONS) IS ASSUME WHICH IS TOO LARGE TO FIT A BYTE VARIABLE. THUS, USING AN ALLOCATION OF 1024 BYTES, K BYTE EXTERNAL, OSTRKS BYTE EXTERNAL, CURDSK BYTE EXTERNAL; /* CURRENT DISK (EXTER = 26 (SECTORS PER TRACK) DIRMAX = 63 (=64 DIRECTORY ENTRIES, FOR EXAMPLE) PL/M-80 COMPILER BASICEA RESERVED FOR THE DIRECTORY IS DIRBLK = 11000000B = 0C0H = 192 (DECIMAL) (I.ECH RESERVES ONE B - LOCK FOR EACH DIRECTORY GROUP (4 ENTRIES PER G D TO BE 1024. AS A RESULT, BLKSHF = LOG2 (1024/128) = LOG2 8 = 3 (I.E., 2**3=8), A - N FOR ERRS) */ /* PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 3 - RETURNS 0 IN REG-A IF NO CONSOLE DATA READY ALLY '0080H'; /* THE FOLLOWING SUBROUTINES ARE ASSUMED TO EXIST EXTERNALLY DEFAULTED TO 80H) 13 BASE+39 READ READ DISK SECTOR (SETTRK, SETSEC, SELD PLER AREA 0100H - CCP TRANSIENT PROGRAM AREA */ 3 1 DECLARE A - RITY 08 BASE+24 HOME MOVE DISK HEAD TO TRACK 0 09 BASE+27 SELD THE FIRST PAGE OF ROM IS ASSIGNED AS FOLLOWS: 0000H JMP WBOOT FF IF CHARACTER IS READY 03 BASE+9 CONIN CONSOLE CHARACTER INTO ACCUMULATOR - 0 - , STARTING AT THE ADDRESS 'BASE' (NORMALLY 3E00H IN 16K CP/M), A - ND ARE AC/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 4 - SK ASSUMED) JBOOT LITERALLY '0000H', JDDT LITERALLY '0038H', IOLOC LITERALLY '0003H', SK SELECT DISK DRIVE GIVEN BY REGISTER C - (0,1,..) 10 BASE+30 SETTRK SET TRACK (0-7 0003H IOBYTE (USED IN BDOS, PIP, AND STAT) 0004H CDISK (CURRENT DISK NUMBER, USED IN CCP, E PARITY 04 BASE+12 CONOUT CONSOLE CHARACTER SENT FROM REGISTER C 05 BASE+15 LIST CESSED THROUGH THE BDOS INTERFACE PROGRAM. 00 BASE: BOOT SYSTEM REBOOT OPERATION A PERMANENT ERROR IS ASSUMED IF - THE CDLOC LITERALLY '0004H', JBDOS LITERALLY '0005H', BDOSA LITERALLY '0006H', /*6) GIVEN BY REGISTER C 11 BASE+33 SETSEC SET SECTOR NUMBER GIVEN BY REG C (1-26 - ) D) 0005H JMP BDOS (PRIMARY BDOS ENTRY POINT) 0038H JMP DDT (RESTART FILLED SEND CHARACTER FROM REGISTER C TO LIST - DEVICE 06 BASE+18 PUNCH SEND CHARACTER F 01 BASE+3 WBOOT SYSTEM REBOOT - WARM START 02 BASE+6 CONSTAT CONSOLE STATUS LEAST SIGNIFICANT BIT IS NOT ZER - O UPON RETURN FROM THE BIO ADDRESS FIELD OF JMP INSTRUCTION * - / TFCB LITERALLY '005CH', TBUFF LITER 12 BASE+36 SETDMA SET DMA ADDRESS GIVEN BY REG PAIR B,C - (INITIALLY BY DDT) 005CH - 007CH DEFAULT FILE CONTROL BLOCK 0080H - 00FFH DEFAULT BUFFROM REGISTER C TO PUNC - H DEVICE 07 BASE+21 READER READ CHARACTER TO REGISTER A WITH 0 PS. 14 BASE+42 WRITE WRITE DISK SECTOR (SETTRK..SELDSK ASSU - MED) RETURN BASE ADDRESS OF ALLOCATION VECTOR 28: WRITE PROTECT CURRENTLY SELECTED DISK 17: SEARCH FOR FIRST OCCURRENCE 18: SEARCH FOR NEXT OCCURRENCE SEL$ERROR$SUB ADDRESS EXTERNAL, RO$ERROR$SUB ADDRESS EXTERNAL, MEMSIZE ADD 7: INTERROGATE DEVICE STATUS 8: CHANGE DEVICE STATUS 9: PRS', READ$DISK EQU 'READDI', PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE ERROR RETURNS IN REGISTER A AS ABOVE */ /* FUNC IS 29: RETURN R/O DISK BIT VECTOR 30: SET DMA ADDRESS FOR DIRECTORY OPERATIONS */ 19: DELETE A FILE 20: READ A FILE 21: WRITE A FILE 22:RESS AT(BDOSA), /* ADDRESS FIELD OF JUMP AT 5 */ FUNC BYTE EXTERNAL, /* MONITOR FUNCTION NUMBER INT BUFFER ON CONSOLE 10: READ BUFFER FROM CONSOLE 11: CONSOLE CHARACTER READY 5 CONECHO EQU 'CONECH', PERM$ERROR$SUB EQU 'PERERR', SEL$ERROTHE DISK MONITOR FUNCTION NUMBER AS SHOWN BELOW: 0: SYSTEM RESET 1: READ CONSO 4 1 DECLARE EQU LITERALLY 'LITERALLY', CREATE A FILE 23: RENAME A FILE 24: RETURN LOGIN VECTOR */ INFO ADDRESS EXTERNAL, /* DATA TO ACT UPON */ ARET ADDRESS EXTERNAL, /* R 12: LIFT HEAD (NOT USED IN CURRENT SYSTEMS) 13: RESET DISK SYSTEM - SELECT DISK 0R$SUB EQU 'SELERR', RO$ERROR$SUB EQU 'RODERR', WRITE$DISK EQU 'WRITED'; LE DEVICE 2: WRITE CONSOLE DEVICE 3: READ READER DEVICE FOREVER EQU 'WHILE TRUE', TRUE EQU '1', FALSE EQU '0', /* TRUNC 25: RETURN CURRENTLY SELECTED DISK NUMBER 26: SET SUBSEQUENT DMA ADDRESS 27: ETURN VALUE */ RET BYTE, /* SET TO LOW(ARET) */ LINFO BYTE; 14: SELECT DISK 'INFO' 15: OPEN FILE 16: CLOSE FILE /* EXTERNALLY DEFINED LABELS AND VARIABLES */ 5 1 DECLARE PERM$ERROR$SUB ADDRESS EXTERNAL, 4: WRITE PUNCH DEVICE 5: WRITE LIST DEVICE 6: INTERROGATE MEMORY SIZE ATE EXTERNAL NAMES FOR ASSEMBLER INTERFACE */ CONCHAR EQU 'CONCHA', SELDISK EQU 'SELDI /* SET TO LOW(INFO) */ 6 1 BOOT: PROCEDURE EXTERNAL; /* WARM START */ 7 2 38 1 TRSECT: PROCEDURE(SECTOR) EXTERNAL; 39 2 DECLARE SECTOR BYTE; /* TRANSLATE AND SET ERNAL ; 29 2 DECLARE SECTOR BYTE; 30 2 END SELSEC; PL/M-80 COMPILER BASIC DISKROM THE CONSOLE DEVICE INTO THE MEMORY LOCATION GIVEN BY 'INFO', UNTIL THE FIRST CARRIAGE 18 1 READIN: PROCEDURE BYTE EXTERNAL; 19 2 END READIN; 20 1 TRACK0: PROCL; 44 2 DECLARE CHAR BYTE; 45 2 END TABOUT; 46 1 CRLF: PROCEDURE EXTERNAL END BOOT; 8 1 CONECHO: PROCEDURE BYTE EXTERNAL; /* READ CHARACTER, ECHO GRAPHICS */ 9 2 SECTOR NUMBER */ 40 2 END TRSECT; /* CONSOLE COMMUNICATION PROCEDURES */ OPERATING SYSTEM 15 AUG 78 PAGE 6 31 1 SELDMA: PROCEDURE(DMA) EXTERNAL ; 32 2 DECLARERETURN IS ENCOUNTERED. ALLOW BACKSPACE (RUBOUT), LINE ELIMINATE (CTL U), AND SYSTEM RE-BOEDURE EXTERNAL; 21 2 END TRACK0; 22 1 SELDISK: PROCEDURE(DISK) EXTERNAL; 23 2 ; 47 2 END CRLF; 48 1 PRINT: PROCEDURE(A) EXTERNAL; 49 2 DECLARE A ADDRES END CONECHO; 10 1 CONBRK: PROCEDURE BYTE EXTERNAL; 11 2 END CONBRK; 12 1 41 1 DECLARE /* SPECIAL CHARACTERS */ CTLC EQU '03H', DMA ADDRESS; 33 2 END SELDMA; 34 1 READ$DISK: PROCEDURE BYTE EXTERNAL; 35 2 OT (CTL C) */ /* THE INFO POINTER IS ASSUMED TO ADDRESS AN AREA OF MEM DECLARE DISK BYTE; 24 2 END SELDISK; 25 1 SELTRK: PROCEDURE(TRACK) EXTERNAL ; 2S; /* PRINT THE STRING STARTING AT ADDRESS A UNTIL THE NEXT OCCURRENCE OF A DOLLAR SIGN */ LSTOUT: PROCEDURE(CHAR) EXTERNAL; 13 2 DECLARE CHAR BYTE; 14 2 END LSTOUT; TAB EQU '09H', LF EQU '0AH', CR EQU '0DH'; 42 1 DECLARE END READ$DISK; 36 1 WRITE$DISK: PROCEDURE BYTE EXTERNAL; 37 2 END WRITE$DISK; ORY CONTAINING TWO BYTE QUANTITIES. THE FIRST GIVES THE MAXIMUM BUFFER LENGTH, AND THE SEC6 2 DECLARE TRACK BYTE; 27 2 END SELTRK; 28 1 SELSEC: PROCEDURE(SECTOR) EXT 50 2 END PRINT; 51 1 READ: PROCEDURE EXTERNAL; /* READ CHARACTERS F 15 1 PUNOUT: PROCEDURE(CHAR) EXTERNAL; 16 2 DECLARE CHAR BYTE; 17 2 END PUNOUT; IOSTAT BYTE AT(IOLOC) ; /* IO STATUS BYTE */ 43 1 TABOUT: PROCEDURE(CHAR) EXTERNAOND IS SET TO THE NUMBER OF CHARACTERS SCANNED UPON RETURN */ 52 2 END READ; ALLOC0 (32) BYTE, /* ALLOCATION VECTOR FOR DISK 0 */ ALLOC1 (32) BYORS */ CHKSHF EQU '4', /* LOG2 CHKSIZ */ OFFSET EQU 'OSTRKS', /* NUMBER OF TRACKS L EQU 'MAXALL', /* LARGEST BLOCK NUMBER */ MRC EQU '127', /* LARGEST RECORD NUMBER */ L(TBUFF), DMAAD ADDRESS INITIAL(TBUFF), BUFF BASED BUFFA (128) BYTE, HECK0 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 0 */ CHECK1 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 1 */ PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 7 53 1 DECLARE MATE, /* ALLOCATION VECTOR FOR DISK 1 */ ALLOC2 (32) BYTE, /* ALLOCATION VECTOR FOR DISK 2 */ USED BY BOOT */ AL1 EQU 'DIRBLK', /* FIRST ALLOCATION VECTOR EL DSF EQU '2', /* AMOUNT TO SHIFT 128 BYTE RECORD TO GET A SINGLE DISK ENTRY */ DIRSET BYTE INITIAL(FALSE), /* TRUE IF DIR DMA SET */ GETBUFF EQU 'BUFF'; /* CAN REPLACE BY FUNCTI CHECK2 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 2 */ CHECK3 (CHKSIZ) BYTE, /* CHECK SUM VECTOR 3 */ XDSK EQU '3', /* MAX DISK NUMBER 0,1,... */ NDISK EQU '4'; /* NUMBER OF DISKS = MAXDSK+1 */ ALLOC3 (32) BYTE, /* ALLOCATION VECTOR FOR DISK 3 */ ALLOCA ADDRESS, /* POINTER TO CURRENTLYEMENT. EACH BIT THAT IS '1' RESERVES A 1 K BLOCK FOR THE DIRECTORY. EACH BLOCK IS DMK EQU '11B', /* MASK CORRESPONDING TO DSF */ FLN EQU '32', FSON */ 55 1 DECLARE DMX EQU 'DIRMAX', /* DMX IS THE LAST DIRECTORY ENTRY CHECKA ADDRESS, /* POINTER TO CURRENT VECTOR */ CHECK BASED CHECKA (CHKSIZ) BYTE; /* C 54 1 DECLARE (DPTR,DCNT,DREC) BYTE, /* DIRECTORY OPERATIONS AND DATA TRANSFERS TAKE REFERENCED ALLOC - */ ALLOC BASED ALLOCA (32) BYTE; /* ALLOC VECTOR TEMPLATE */ 8 RECORDS BY 128 BYTES PER RECORD (NOTE THAT RESERVATIONS START ON THE LEFT OF THE WORD */ L EQU '5', /* AMOUNT TO SHIFT TO MULTIPLY BY THE FCB LENGTH (FLN) */ NUMBER (LISTED AS 0, 1, ... , DMX) */ CHKSIZ EQU '16', /* SIZE OF CHECKSUM VECTHECK SUM TEMPLATE */ 57 1 DECLARE EMP EQU '0E5H', MAPLACE AT TBUFF (NORMALLY 80H) UNLESS CHANGED BY SYSTEM CALLS */ BUFFA ADDRESS INITIA 56 1 DECLARE RODSK BYTE INITIAL(0),/* READ ONLY DISK BIT VECTOR */ C FDM EQU '16', /* BEGINNING OF DISK MAP */ PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGEBER' FIRST REEL IS 0, SECOND IS 1, AND SO FORTH UNTIL 255. XXX - 5/ -------------------------------------------------------- - -- (NDISK) BYTE, /* TRACK VECTOR */ CURRECV(NDISK) ADDRESS, /* RECORD VECTOR */ ISK MONITOR FROM THE USER */ SZ BASED INFO BYTE; /* SZ = S(0) */ IS NOT A PART OF THE DIRECTORY. EACH READ OR WRITE WILL INCREMENT THIS RECORD COUNT. 8 FRL EQU '32', /* LOCATION OF REC TO R/W */ FRC EQU '15', /* LOCATION OF RE : UNUSED FOR NOW RCNT : RECORD COUNT IN FILE (0 TO 127) DM0 ... FILETYPE : 0E5H IF AVAILABLE (OTHERWISE UNDEFINED NOW) NAME : 8 CHARACCURTRKA ADDRESS, /* POINTS TO CURRENT TRACK NUMBER - */ CURRECA ADDRESS, /* THE FILE CONTROL BLOCK FORMAT IS SHOWN BELOW: ------------ */ 59 1 DECLARE OCORD COUNT (MUST BE ONE BELOW DISK MAP) */ FRE EQU '12', /* POS: DISK ALLOCATION MAP. 255 IF NOT ALLOCATED, DM15 OTHERWISE IT POINTS TO ALLOCATED DISK BLOCKTER PRIMARY NAME EXT : 3 CHARACTER EXTENT COM IMPLIES /* POINTS TO CURRENT RECORD NUMBE - R */ PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 -------------------------------------------- - -- / 1 BY / 8 BY / 3 BY / 1 BY /2BLDDSK BYTE, /* DISK ON ENTRY TO DOS */ FCBDSK BYTE, /* DISK NAMED IN FCB */ ITION OF REEL NUMBER */ LFB EQU '31', FNM EQU '13'; /* LENGTH OF FILE NAME */ THE FILE CONTROL BLOCK IS FOLLOWED BY ONE BYTE OF INFORMATCOMMAND TYPE (OTHERWISE UNDEFINED NOW) REEL NO : 'REEL NUM PAGE 9 CURREC BASED CURRECA ADDRESS, /* CURRENTLY ADDRESSED RECORD - */ Y/1 BY/ 16 BY - / /FILETYPE/ NAME / EXT / REEL NO/XXX/RCNT/DM0 .. DM1 DLOG BYTE INITIAL(0), /* BIT VECTOR GIVING LOGGED-IN DI - SKS */ CURTRKV 58 1 DECLARE S BASED INFO (33) BYTE, /* FILE CONTROL BLOCK PASSED TO THE DION WHICH GIVES THE NEXT RECORD TO BE READ OR WRITTEN IN AN OPENED FILE. THIS INFORMATION CURTRK BASED CURTRKA BYTE, /* CURRENT TRACK 0-76 */ RCOUNT BYTE, /* RECORD COUNT IN CURRENTLY FALSE IF WRITING */ 80 2 DECLARE COND BYTE; /* CONDITION UPON RETURN */ 81 2 IF READING THEN CO CURTRK + 1; 74 3 END; /* WE ARE NOW POSITIONED OVER THE TRACK CONTAINING 97 1 ATRAN: PROCEDURE; /* COMPUTE ACTUAL TRACK ADDRESS (ASSUMES A ; 64 2 END HOME; 65 1 SEEK: PROCEDURE; /* SEEK THE TRACK GIVEN BY AR1 WRBUFF: PROCEDURE; PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 10 ADDRESSED FCB */ VRECORD BYTE, /* CURRENT VIRTUAL RECORD */ ND = READ$DISK; ELSE 83 2 COND = WRITE$DISK; 84 2 IF COND = 0 THEN RETURN; /* DISK THE ACTUAL RECORD. THE SECTOR TO BE READ IS ARECORD - CURREC + 1. THE TRACK NUMBER IS C PREVIOUS CALL TO INDEX */ 98 2 ARECORD = SHL(ARECORD,BLKSHF) OR (VRECORD AND BLKMSK); 99 2 ENDECORD (ACTUAL RECORD) */ 66 2 DECLARE T ADDRESS; 67 2 DO WHILE ARECORD < CURREC /* WRITE THE BUFFER, SELECT NON-DELETED DATA */ 92 2 CALL WAITIO(FALSE); 93 2 END WRBUFF; ARECORD ADDRESS; /* CURRENT ACTUAL RECORD */ 60 1 HOME: PRI/O SUCCESSFUL */ /* ARRIVE HERE AFTER TOO MANY READ WRITE FAILURES */ 86 2 CAURTRK */ 75 2 CALL SELTRK(CURTRK+OFFSET); 76 2 CALL TRSECT(ARECORD - CURREC); 77 2 END ATRAN; 100 1 GETFCB: PROCEDURE; /* SET VARIABLES FROM CURRENTLY ADDRESSED FCB */ ; 68 3 CURREC = CURREC - SECSIZ; 69 3 CURTRK = CURTRK - 1; 70 3 END; 71 94 1 INDEX: PROCEDURE; /* COMPUTE DISK BLOCK NUMBER FROM CURRENT OCEDURE; /* MOVE TO HOME POSITION, THEN OFFSET BY DOS TRACKS */ 61 2 CALL TRACK0; /* AT HOME LL PERM$ERROR$SUB; 87 2 END WAITIO; 88 1 RDBUFF: PROCEDURE; /* START SEEK; 78 1 WAITIO: PROCEDURE(READING); 79 2 DECLARE READING BYTE; /* TRUE IF READING, 101 2 VRECORD = S(FRL); 102 2 RCOUNT = S(FRC); 103 2 END GETFCB; 2 DO WHILE ARECORD >= (T := CURREC + SECSIZ); 72 3 CURREC = T; 73 3 CURTRK = FCB ADDRESSED BY INFO */ 95 2 ARECORD = S(FDM+SHR(VRECORD,BLKSHF)); 96 2 END INDEX; POSITION */ 62 2 CALL SELTRK(OFFSET); /* SELECT FIRST DIRECTORY POSITION */ 63 2 CURREC, CURTRK = 0 AN I/O AND WAIT FOR IO FINISH */ 89 2 CALL WAITIO(TRUE); 90 2 END RDBUFF; 91 104 1 SETFCB: PROCEDURE; /* PLACE VALUES BACK INTO CURRENTLY ADDRESSED /* CHECK FOR WRITE PROTECTED DISK */ 131 2 IF NOWRITE THEN 132 2 CALL RO$ERROR$ 2 END SET$CDISK; 124 1 NOWRITE: PROCEDURE BYTE; PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM TIALIZING SYSTEM */ /* READ NEXT DIRECTORY ENTRY (SET DCNT=255 INITIALLY)*/ 149 2 IF (DCNT:=DCNTECKSUM FOR CURRENT DIRECTORY BUFFER */ 113 2 DECLARE (I,CS) BYTE; 114 2 CS = 0; 115 2 IF CHECK(DREC) <> COMPUTE$CS THEN /* CHECKSUM ERROR */ 141 2 CALL SET$RO; /* DISK SET TO READ ONLY */ FCB, AND INCREMENT THE RECORD COUNT */ 105 2 S(FRL) = VRECORD + 1; 106 2 S(FRC) = RCOSUB; 133 2 END CHECK$WRITE; 134 1 CHECKSUM: PROCEDURE(INIT); 135 2 DECLARE INIT BYTE; 15 AUG 78 PAGE 11 /* RETURN TRUE IF DIR CHECKSUM DIFFERENCE */ 125 2 RETURN ROL(ROR(RODS+1) > DMX THEN 150 2 DO; DCNT = 255; RETURN; 153 3 END; 154 2 IF (DPTR:=SHL(DCNT DO I = 0 TO LAST(BUFF); 116 3 CS = CS + GETBUFF(I); 117 3 END; 118 2 RETURN CS; END CHECKSUM; 143 1 WRDIR: PROCEDURE; /* WRITE THE CURRENT DIRECTORY ENTRY, SET UNT; 107 2 END SETFCB; 108 1 SEEK$DIR: PROCEDURE; /* SEEK THE RECORD C /* COMPUTE CURRENT CHECKSUM RECORD AND UPDATE THE DIRECTORY ELEMENT IF INIT, OR CHECK K,CURDSK+1),1); 126 2 END NOWRITE; 127 1 SET$RO: PROCEDURE; /* SET CURRENT DISK TO REAND DMK,FSL)) = 0 THEN 155 2 DO; CALL SEEK$DIR; 157 3 CALL RDBUFF; 158 3 CALL 119 2 END COMPUTE$CS; 120 1 SET$CDISK: PROCEDURE(MASK) BYTE; /* SET A '1' VALUE IN CUCHECKSUM */ 144 2 CALL CHECKSUM(TRUE); /* INITIALIZE ENTRY */ 145 2 CALL WRBUFF; /* WRITE THE BUFFER *ONTAINING THE CURRENT DIRECTORY ENTRY */ 109 2 ARECORD = DOUBLE(DREC := SHR(DCNT,DSF)); 110 2 CALL SEE FOR EQUALITY IF NOT */ 136 2 IF DREC >= CHKSIZ THEN RETURN; /* SKIP IF BEYOND CHECKED AREA -AD ONLY */ 128 2 RODSK = SET$CDISK(RODSK); 129 2 END SET$RO; 130 1 CHECK$WRITE: PROCEDURE; CHECKSUM(INIT); /* CHECKSUM OPERATION */ 159 3 END; 160 2 END READ$DIR; 161 RDSK POSITION OF MASK */ 121 2 DECLARE MASK BYTE; 122 2 RETURN MASK OR ROR(ROL(1,CURDSK+1),1); 123 / 146 2 END WRDIR; 147 1 READ$DIR: PROCEDURE(INIT); 148 2 DECLARE INIT BYTE; /* TRUE IF INIK; 111 2 END SEEK$DIR; 112 1 COMPUTE$CS: PROCEDURE BYTE; /* COMPUTE CH */ 138 2 IF INIT THEN /* SET CHECKSUM VALUE */ 139 2 CHECK(DREC) = COMPUTE$CS; ELSE 140 2 1 GET$ALLOC$BIT: PROCEDURE(I) BYTE; /* RETURN THE I-TH BIT OF ALLOC */ 162 2 DECLARE I BYTEw*&*-{j"$  ͖ͮb"&=!q:<2O:!6:BIT); 174 3 END; 175 2 END SCANDM; 176 1 INITIALIZE: PROCEDURE; 177 IF DCNT = 255 THEN RETURN; 190 3 IF GETBUFF(DPTR) <> EMP THEN 191 3 DO; /* CHECK FOR $ 169 1 SCANDM: PROCEDURE(BIT); 170 2 DECLARE (BIT, I, K) BYTE; /* SCAN2 DECLARE I BYTE; /* INITIALIZE THE DISK SYSTEM */ 178 2 RET = FALSE; /* SET TO TRUE IF; 163 2 RETURN ROL(ALLOC(SHR(I,3)), (I AND 111B)+1); 164 2 END GET$ALLOC$BIT; 165 2ͨ*M͖"  $ . "!q:O* :!V*&*: FILE (IN CASE OF SUBMIT) */ 192 4 RET = RET OR GETBUFF(DPTR+1) = '$'; /* SET ALDM SCANS THE DISK MAP ADDRESSED BY DPTR FOR NON-ZERO EN - TRIES -- THE ALLOCATION VECTOR ENTRY $ FILE EXISTS */ 179 2 RODSK = 0; /* NO READ ONLY DISKS AT THIS POINT */ 180 2 ALLOC 1 SET$ALLOC$BIT: PROCEDURE(I,B); /* SET THE I-TH BIT OF ALLOC TO THE LSB OF B */ PL/M-80 COMPILER /42!s+q*M!>+!ɜ$[j _%fn:!*&*6!4¶o&w{*MZ2ɼ"V$|nҕ!*#"0  9@!q:ڣ:һ-*&* END; 196 2 END INITIALIZE; 197 1 DECLARE SEARCHL BYTE, I = DPTR+FDM TO DPTR+LFB; 172 3 IF (K := GETBUFF(I)) <> 0 THEN 173 3 CALL SET$ALLOC$BIT(K, 185 2 DCNT = 255; 186 2 DO FOREVER; 187 3 CALL READ$DIR(TRUE); 188 3 HR(I,3)) = ROR((GET$ALLOC$BIT(I) AND 0FEH) OR B, (I AND 111B) + 1); 168 2 END SET$ALLOC$BIT;!6:*&*~*& *~$!wbL"t$! /* SEARCH LENGTH SET BY SEARCH */ SEARCHA ADDRESS; /* SEARCH ADDRESS SET BY SEARCH */ THEN /* NO MORE ENTRIES MATCH */ RETURN; /* SET EACH NON-ZERO DISK MAP ENTRY TO 0 IN ALLOC VECTOR * INFO; 217 2 DCNT = 255; 218 2 CALL HOME; /* NOW READY TO READ THE DISK */ 219 EDURE(B,L); 248 2 DECLARE (B,L) BYTE; /* COPY FCB INFORMATION STARTING AT BYTE B FOR L BYTES INT OPERATING SYSTEM 15 AUG 78 PAGE 13 /* MATCH OR QUESTION MARK */ A 0 IF NO BLOCK IS AVAILABLE */ 235 2 DECLARE (L, R) BYTE; 236 2 R = L; 237 2 DO 198 1 SEARCHN: PROCEDURE; /* SEARCH FOR THE NEXT DIRECTORY ELEMENT, ASSUMING A PREVIOUS - / 228 3 CALL SCANDM(0); 229 3 BUFF(DPTR) = EMP; /* ARECORD H2 CALL SEARCHN; 220 2 END SEARCH; 221 1 DELETE: PROCEDURE; 222 2 DEO BEGINNING OF CURRENTLY ADDRESSED DIRECTORY ENTRY */ 249 2 DO WHILE (L:=L-1) <> 255; 250 ((C := S(I)) = GETBUFF(DPTR+I) OR C = 63); 207 4 I = I + 1; 208 4 END; 209 WHILE (R < MAL) OR (L > 0); 238 3 L = L - (1 AND L > 0); 239 3 R = R + (1 AND R < MAL); 240 CALL ON SEARCH WHICH SETS SEARCHA AND SEARCHL */ 199 2 DECLARE (I,C) BYTE; 200 2 INFO = SEARCHA;AS BEEN PREVIOUSLY SOUGHT BY READDIR */ 230 3 CALL WRDIR; /* WRITE DIRECTORY ENTRY */ 231 3 CACLARE (I,J,K) BYTE; 223 2 CALL CHECK$WRITE; /* WRITE PROTECTED? */ /* SEARCH ONLY UP THROUGH THR 3 BUFF(L+DPTR) = S(B+L); PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 14 2 3 IF I = SEARCHL THEN RETURN; 211 3 END; 212 2 END SEARCHN; 213 3 IF NOT GET$ALLOC$BIT(R) THEN RETURN R; 242 3 IF NOT GET$ALLOC$BIT(L) THEN RETURN L; 244 3 201 2 DO FOREVER; 202 3 CALL READ$DIR(FALSE); 203 3 IF (RET := DCNT) = 255 TLL SEARCHN; 232 3 END; 233 2 END DELETE; 234 1 GET$BLOCK: PROCEDURE(L) BYTEE CHARACTER EXTENT */ 224 2 CALL SEARCH(FRE); 225 2 DO FOREVER; 226 3 IF DCNT = 255 51 3 END; 252 2 CALL SEEK$DIR; 253 2 CALL WRDIR; /* WRITE DIR ENTRY */ 254 2 1 SEARCH: PROCEDURE(XL); 214 2 DECLARE XL BYTE; 215 2 SEARCHL = XL; 216 2 SEARCHA = END; 245 2 RETURN 0; 246 2 END GET$BLOCK; 247 1 COPY$DIR: PROCHEN RETURN; 205 3 I = 0; 206 3 DO WHILE (I < SEARCHL) AND PL/M-80 COMPILER BASIC DISKE; /* FIND A BLOCK WHICH IS AVAILABLE ON THE DISK AND IS CLOSEST TO THE BLOCK 'L'. RETURN END COPY$DIR; 255 1 COPY$FCB: PROCEDURE; /* COPY THE ENTIRE FILE CONTROL BLOCK *ITE PROTECTED */ 279 2 CALL SEARCH(FNM); 280 2 IF DCNT <> 255 THEN 281 2 CALL COPY$FC DECLARE I BYTE; /* SEARCH FOR DIRECTORY ENTRY, COPY TO FCB */ 269 2 CALL SEARCH(FNM); 270 P !u*":21!6!:*&*~2:!O* :?HH|!46!:‡ R FIELD IS IGNORED */ 259 2 CALL CHECK$WRITE; /* IN CASE WRITE PROTECTED */ /* /* LOOK FOR AN EMPTY DIRECTORY ENTRY */ 288 2 CALL SEARCH(1); 289 2 IF DCNT <> 255 THEN 290 2 / 256 2 CALL COPY$DIR(0,FRL); 257 2 END COPY$FCB; 258 1 RENAME: PROCEDURE; B; 282 2 END CLOSE; 283 1 MAKE: PROCEDURE; /* CREATE A NEW FILE; FIRST 2 IF DCNT <> 255 THEN 271 2 DO I=FNM TO LFB; 272 3 S(I) = GETBUFF(DPTR+I); 273 ɚ"#.szq$!&)27:?KNRYdv}"   EP !q:2*"!6D"$ SEARCH UP TO THE REEL NUMBER FIELD */ 260 2 CALL SEARCH(FRE); S(FDM) = SZ; /* ASSUME SAME DISK D DO; /* SET ELEMENTS TO ZERO */ 291 3 INFO = FCB; 292 3 DO I=FNM TO LFB; 293 /* RENAME THE FILE DESCRIBED BY THE FIRST HALF OF THE CURRENTL - Y ADDRESSED CREATE ENTRY IN THE DIRECTORY. FILE IS OPENED UPON RETURN */ 284 2 DECLARE I BYTE, 3 END; 274 2 END OPEN; 275 1 CLOSE: PROCEDURE; /* LOCATE  10͆ ͋:¸b*&*6ï/"$ f!q:2!:>!HRIVE FOR NEW NAMED FILE */ 262 2 DO WHILE DCNT <> 255; CALL COPY$DIR(FDM,FRE); 264 3 CALL SEAR 4 S(I) = 0; 294 4 END; /* COPY INTO DIRECTORY ENTRY */ 295 3 FILE CONTROL BLOCK. THE NEW NAME IS CONTAINED IN TH - E LAST HALF OF THE CURRENTLY ADDRESSED F FCB ADDRESS; 285 2 CALL CHECK$WRITE; /* MAY BE WRITE PROTECTED */ 286 2 FTHE DIRECTORY ELEMENT AND RE-WRITE */ 276 2 RET = 0; 277 2 IF NOWRITE THEN RETURN; /* SKIP CLOSE IF WR2>!~Hw#~!!w*M :*M/:>"%)0$ !, @CHN; 265 3 END; 266 2 END RENAME; 267 1 OPEN: PROCEDURE; 268 2 CALL COPY$FCB; 296 3 END; 297 2 END MAKE; 298 1 OPEN$REEL: PILE CONTROL BLOCK. THE FILE TYPE, FILE NAME, AND FILE EXT ARE CHANGED, BUT THE REEL NUMBECB = INFO; INFO = .(EMP); PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 15 5!s+q:=2j:!O* :!O* w;" Ehkn;$6<@HKVZaN  Rt q 5]" /* RESELECT ORIGINAL DMA ADDRESS */ 325 2 IF DIRSET THEN CALL SELDMA(BUFFA); 327 2 END RES 2 CALL OPEN; 312 2 IF DCNT = 255 THEN 313 2 DO; RET = 1; /* END OF FILE IN DISK READ */ CALL SETFCB; 350 4 END; 351 3 END; 352 2 END DISKREAD; OSSIBLE READING IS TRUE IF WE ARE IN READ MODE */ 300 2 CALL CLOSE; /* RET RE /* ERROR 2 IF READING UNWRITTTEN DATA */ 341 3 IF LOW(ARECORD) = 0 THEN RET = 1; ELSE 343 3 v]0y͆ ͋** w:ʤ 5Ï"zJ$>   C ͋:!6 >!:ETDMA; 328 1 DISKREAD: PROCEDURE; 329 2 CALL GETFCB; 330 2 IF RCOUNT <= VR 315 3 RETURN; 316 3 END; 317 2 CALL GETFCB; 318 2 RET = 0; 319 353 1 DISKWRITE: PROCEDURE; 354 2 DECLARE (I,L) BYTE; 355 2 CALL CHECK$WRITE; /* IN CASEMAINS AT 255 IF WE CANNOT OPEN THE NEXT REEL */ 301 2 IF DCNT = 255 THEN RETURN; /* INCREMENT TH DO; CALL ATRAN; /* ARECORD IS NOW ACTUAL DISK ADDRESS */ 345 4 CALL SEE!O* *&* w!4·ɇ" $  "!6n ͋:q"" ECORD THEN 331 2 DO; RET = 1; 333 3 IF VRECORD = 128 THEN CALL OPEN$REEL(TRUE); 335 3 2 END OPEN$REEL; 320 1 SETDMA: PROCEDURE; /* SELECT DATA DMA ADDRESS */ WRITE PROTECTED */ 356 2 CALL GETFCB; 357 2 IF VRECORD > MRC THEN /* PAST EOF, NEXT REEL NOT OPENED *E REEL NUMBER */ 303 2 S(FRE) = S(FRE) + 1; 304 2 CALL SEARCH(FNM); 305 2 IF DCNT = 255 TK; /* NOW READ THE BUFFER */ 346 4 CALL SETDMA; /* SELECTS DATA DMA ADDRESS */ $K͆*"!"͋:H*"!6 >!E*&*6!4)q" 0CF$ %,3? VRECORD = 0; 336 3 IF RET <> 0 THEN RETURN; 338 3 END; PL/M-80 COMPILER BASIC DI321 2 IF DIRSET THEN CALL SELDMA(DMAAD); 323 2 END SETDMA; 324 1 RESETDMA: PROCEDURE; / 358 2 RET = 1; ELSE 359 2 DO; CALL INDEX; 361 3 IF LOW(ARECORD) = 0 THEN /*HEN 306 2 DO; IF READING THEN RETURN; 309 3 CALL MAKE; 310 3 END; ELSE 311 347 4 CALL RDBUFF; 348 4 CALL RESETDMA; /* SELECTS DIR DMA ADDRESS */ 349 4 ROCEDURE(READING); 299 2 DECLARE READING BYTE; /* CLOSE CURRENT REEL AND OPEN THE NEXT ONE, IF PSK OPERATING SYSTEM 15 AUG 78 PAGE 16 339 2 DO; CALL INDEX; NOT ALLOCATED */ 362 3 DO; /* THE ARGUMENT TO GET$BLOCK IS THE STARTING POSIT - ION DISK OPERATING SYSTEM 15 AUG 78 PAGE 17 384 5 CALL SETFCB; CALL OPENREEL(FALSE); CALL WRBUFF; 379 4 CALL RESETDMA; 380 4 IF RCOUNT <= VRECORD THEN RCOUN CURTRKA = .CURTRKV(CURDSK); 400 2 CURRECA = .CURRECV(CURDSK); /* SET CON67 4 RET = 2; ELSE 368 4 DO; CALL SET$ALLOC$BIT(I,1); LECT DISK 'INFO' FOR SUBSEQUENT INPUT OR OUTPUT OPERATIONS */ 395 2 IF CURDSK > FOR THE DISK SEARCH - THIS SHOULD BE THE LAST ALLOCATE - D BLOCK FOR /* VRECORD REMAINS AT MRC CAUSING END-OF-FILE IF NO MORE DIRECTORY SPACT = VRECORD+1; /* CHECK FOR END-OF-REEL, IF FOUND ATTEMPT TO OPEN NEXT REETROLLER */ 401 2 CALL SELDISK(CURDSK); /* CHECK TO INSURE THAT DISK IS LOGGED I /* BLOCK IS ALLOCATED */ 370 5 ARECORD, S(L) = I; 371 5 END; 372 4 MAXDSK THEN /* SELECTION ERROR */ 396 2 CALL SEL$ERROR$SUB; 397 2 ALLOCA = .ALLOC0(SHL(CURDSK,5)) THIS FILE, OR THE VALUE 0 IF NO SPACE HAS BE - EN ALLOCATED TO THIS FILE */ 363 4 E IS AVAILABLE */ 386 5 IF RET = 0 THEN VRECORD = 255; /* GOES TO ZERO */ 388 5 L IN PREPARATION FOR THE NEXT WRITE */ 382 4 IF VRECORD = MRC THEN 383 4 DO; N */ 402 2 IF NOT ROR(ROL(DLOG,1),CURDSK+1) THEN 403 2 DO; 404 3 DLOG = SET$CDISK END; /* CONTINUE IF NO ERROR IN ALLOCATION */ 373 3 IF RET = 0 THEN 374; /* NOTE THAT THIS ASSUMES THERE ARE NO MORE THAN 8 DISKS ON THE SYSTEM - OTHERWISE I = 0; 364 4 IF (L := FDM + SHR(VRECORD,3)) > FDM THEN 365 4 /* THERE RET = 0; 389 5 END; 390 4 CALL SETFCB; 391 4 END; 392 3 /* UPDATE CURRENT FCB BEFORE GOING TO THE NEXT EXT - ENT */ PL/M-80 COMPILER BASIC (DLOG); 405 3 CALL INITIALIZE; 406 3 END; 407 2 END SELECT; 40 3 DO; CALL ATRAN; 376 4 CALL SEEK; 377 4 CALL SETDMA; 378 4 REPLACE BY .ALLOC0(SHL(DOUBLE(CURDSK),5)) */ 398 2 CHECKA = .CHECK0(SHL(CURDSK,CHKSHF)); 399 2 IS A PREVIOUS BLOCK ALLOCATED */ I = S(L-1); 366 4 IF (I := GET$BLOCK(I)) = 0 THEN /* NO MORE SPACE */ 3 END; 393 2 END DISKWRITE; 394 1 SELECT: PROCEDURE; /* SE8 1 CURSELECT: PROCEDURE; 409 2 IF LINFO <> CURDSK THEN 410 2 DO; CURDSK = LINFO; CALL SELE ARET = IOSTAT; /* 8: CHANGE DEVICE STATUS */ 439 3 IOSTAT = LINFO; ONECHO; /* 2: WRITE CONSOLE */ 433 3 CALL TABOUT(LINFO); /* 3: READ READELL RESELECT; 461 4 CALL SEARCH(FNM); 462 4 END; /* 18: SEARCH FOR NEXT OCCU SELECT DMA BUFFER ADDRESS */ 425 2 CALL SELDMA(BUFFA := INFO); 426 2 END SELBUFFA; PL/M-80 COMPIL CALL SELECT; 449 4 END; /* 14: SELECT DISK 'INFO' */ 450 3 CALL CCT; 413 3 END; 414 2 END CURSELECT; 415 1 RESELECT: PROCEDURE; /* 9: PRINT BUFFER AT THE CONSOLE */ 440 3 CALL PRINT(INFO); /* 10: READ BUFFER FROM R DEVICE */ 434 3 RET = READIN; /* 4: WRITE PUNCH DEVICE */ 435 3 CALL PUNORRENCE OF A FILE NAME */ 463 3 DO; INFO = SEARCHA; CALL RESELECT; 466 4 CALL SEARCHN; 467 ER BASIC DISK OPERATING SYSTEM 15 AUG 78 PAGE 18 427 1 DSKMON: PROCEDURE PUBLIC; 428 2 LURSELECT; /* 15: OPEN */ 451 3 DO; CALL RESELECT; 453 4 CALL OPEN; 454 /* CHECK CURRENT FCB TO SEE IF RESELECTION NECESSARY */ 416 2 IF (LINFO := (SZ AND 1$1111B) -1) < 30 THENTHE CONSOLE */ 441 3 CALL READ; /* 11: CHECK FOR CONSOLE INPUT READY */ 442 3 UT(LINFO); /* 5: WRITE LIST DEVICE */ 436 3 CALL LSTOUT(LINFO); /* 6: INT4 END; /* 19: DELETE A FILE */ PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM 15INFO = LOW(INFO); 429 2 ARET, RET, FCBDSK = 0; 430 2 DO CASE FUNC; /4 END; /* 16: CLOSE */ 455 3 DO; CALL RESELECT; 457 4 CALL CLO 417 2 DO; OLDDSK = CURDSK; FCBDSK = SZ; SZ = SZ AND 1110$0000B; 421 3 CALL CURSELECT; 422 RET = CONBRK; /* 12: */ 443 3 ; /* 13: RESET DISK SYSTEM, INITIALIZE TERROGATE MEMORY SIZE */ 437 3 ARET = MEMSIZE; /* 7: INTERROGATE DEVICE STATUS */ 438 3 AUG 78 PAGE 19 468 3 DO; CALL RESELECT; 470 4 CALL DELETE; 471 4 END; * 0: SYSTEM RE-BOOT */ 431 3 CALL BOOT; /* 1: READ CONSOLE */ 432 3 RET = CSE; 458 4 END; /* 17: SEARCH FOR FIRST OCCURRENCE OF A FILE */ 459 3 DO; CA 3 END; 423 2 END RESELECT; 424 1 SELBUFFA: PROCEDURE; /*O DISK 0 */ 444 3 DO; CURDSK,DLOG,DIRSET = 0; 446 4 INFO = TBUFF; CALL SELBUFFA; 448 4 /* 20: READ A FILE */ 472 3 DO; CALL RESELECT; 474 4 CALL DISKREAD; 475 4508 3 END; /* RETURN A SINGLE OR DOUBLE BYTE VALUE */ 509 2 ARET = ARET OR RET; 496 3 CALL SET$RO; /* 29: RETURN R/O BIT VECTOR */ 497 3 RET = RODSK; :2*~2*>wL"m$ hszd  ap v }*"DM$@  *}2!"TOR */ 488 3 RET = DLOG; /* 25: RETURN SELECTED DISK NUMBER */ 489 3 RET = 2*&"* &*:w:͖ͮͦ:!ڲ:<2:I:!6!6ɧ"0 "+CYai END; /* 21: WRITE A FILE */ 476 3 DO; CALL RESELECT; 478 4 CA    " 9QI!q:Y * 4 ͋:|:vͥ:!6!6"NVdlswz} /* 30: SET DIRECTORY DMA */ 498 3 DO; DIRSET = TRUE; /* MARK AS SEPARATE DIR AREA */ 500 4 }22*M! ^#V- 2- *M- 2- *M- *M- *"- *&"- :2- *DM- - 2CURDSK; /* 26: SET THE SUBSEQUENT DMA ADDRESS TO INFO */ 490 3 DO; 491 4 IFr$3%.3FRU\dluz}  M x>!!*:OLL DISKWRITE; 479 4 END; /* 22: CREATE A FILE */ 480 3 DO; CALL RESELECT; +$JQgo  ]h: ҥ*DM"7$ : ҵ*DM"'$q  CALL SELBUFFA; 501 4 END; 502 3 END; /* OF CASES */ 503 2 GOBACK: - - !6!6! 6!"͇- L- `ͥ- `- ` ͋- *"`- `ͧ- `Ͷ- ` - `- `y DIRSET THEN DMAAD = INFO; ELSE 493 4 CALL SELBUFFA; 494 4 END; /* 27: RETU! ":O! "*& "*&) "*M:: 0 THEN /* RESTORE DISK NUMBER */ 504 2 DO; SZ = FCBDSK; LINFO = OLDDSK; CALL CURSELECT; - :2- :2- : *"͇- *"- {- :2- ! 6͇-  $'EKT]hwRN THE LOGIN VECTOR ADDRESS */ 495 3 ARET = ALLOCA; /* 28: WRITE PROTECT CURRENT DISK */ ?FZ *  &*2'8kL!:_:2c"T]$PW MZ+`*>=2O; CALL RESELECT; 486 4 CALL RENAME; 487 4 END; /* 24: RETURN THE LOGIN VEC ͆>!!!6ʹ*}Š!6:#wO>T: =O* ~2*M2k!6Ê*M:E *:w:2L:+s#r""%=@CFILORUX[^cforux{~LE AREA SIZE = 010AH 266D MAXIMUM STACK SIZE = 0014H 20D PL/M-80 COMPILER BASIC DISK OPERATING SYSTEM              ! # % ' ) + 3 C y$9 15 AUG 78 PAGE 20 983 LINES READ 0 PROGRAM ERROR(S) END OF PL/M-80 COMPILATION -2i. 9 = @ F b    ( : l  6 I #L j 510 2 END DSKMON; 511 1 END; MODULE INFORMATION: CODE AREA SIZE = 0954H 2388D VARIAB