; ; BETA-VERSION ; ; Bullet_Cache_BIOS_CBIOS.pdf ; ; ASSEMBLER-CODE FOR ASIDE ASSEMBLER ; 15.08.2008 HR ; 22.08.2008 HR ; 27.08.2008 HR ;*****************************************************************************; ; THE "WAVE-MATE" CACHE BIOS FOR THE "BULLET" SINGLE BOARD COMPUTER. .; ; FIRST VERSION BY ARCY FOR ARCHIVE COMPUTER SERVICES -- 24 MAY 82. REVLEV: EQU 'C7' ;*****************************************************************************; ;• MODIFICATION HISTORY ... (FIRST RUNABLE VERSION : 02/JUNE/82) ;01:DEC:82 - ; 16:OCT:82 ;25:SEP:82 - ; 18:SEP:82 ;15:AUG:82 - ; 11:AUG'82 ;25:JUL:82 - ; 12:JUN:82 ; 10:JUN:82 - ; 07:JUN:82 - ; 02:JUN:82 - ; DAYS: EQU 335 ;DAYS SINCE Ist Jan 1982 TO LAST CODE UPDATE. ;UNCONDITIONAL: RELATIVE JUMP MNUMONIC CHANGED AND "HOOK5" ADDED. ;- "MORROW" 2 SIDED DISC FORMAT CORRECTED. UNDEFINED LABLE FIXED. ;MEMORY DRIVE (DRIVE "M:") ADDED - 48K MAXIMUM. ;- WARMBOOT FROM RAM. "NOT READY" ERROR TRAF'. "SELECT" BUG FIXED. REAL TIME CLOCK ADDED, HRS:MIN:SEC AT 42H;41H;40H. ;- CTS HARDWARE HANDSHAKE ADDED ON SERIAL CHANNEL "B" ERROR IN PARALLEL PRINTER STATUS CORRECTED. ;- FULL I/O BYTE DECODE, REMOTE CONSOLE, AND COLD-BOOT AUTO COMMAND CALCULATION OF SKEW FACTORS IMPLEMENTED. ;AUTO DISC FORMAT SELECT AND PARAM BLOCK REVISION. COLD BOOT CODE MOVED INTO UNINITIALISED DATA AREA. ;335 ;DAYS SINCE Ist Jan 1982 TO LAST CODE UPDATE. ;i**************e*************************************************************** ; MACRO FILE ;MACLI B Z80 ;FOR USE WITH D.R'S "MAC" ASSEMBLER. ;MACLI B MINICODE;FOR O.E.M. QUAD DISC SYSTEMS. ;TITLE `ARCHIVE COMPUTER SERVICE S' ;****************************************************************************** ;LOCATE THE BIOS EXECUTION ADDRESS DEPENDANT ON THE CP/M SIZE. SIZE: EQU 64 ;SIZE OF CP/M IN "K" BYTES CCP: EQU (SIZE*1024)-2400H ;CPM LOAD ADDRESS (9K TOTAL OVERHEAD) = 7i)c00 BDOS: EQU CCP+0800H ;SYSTEM LOAD ADDRESS (2K FOR CCP) 11-:.4r» BIOS: EQU BDOS+0E00H ;BIOS LOAD ADDRESS (3.75K FOR BDOS) = F200 SYSIZE: EQU BIOS-CCP ;*******************Y********************************************************** ; GENERAL SYSTEM EQUATES AND EXTERNAL ADDRESSES. ;00000H ;LOCATION OF TRACK CACHE IN 2ND BANK. ;CACH+(8*1024) ;CCP+BDOS IN BANK 2 (ALLOW 8K FOR TRACK BUFFER) ;128 ;64 02.T.0 SECONDS ;SECS+1 ; " MINUTES ;MINS+1 " HOURS. ;DAYS SINCE 1ST JAN 1982. ;05 ;03 ;04 CACH: EQU 0C000H ; FEHLER WBHOLD: EQU CACH+ (8+1024) ; DEFBUF: EQU 128 SECS: EQU 64 MINS: EQU SECS+1 HRS: EQU MINS+1 DATE: EQU HRS+1 BDOSVEC: EQU 05H IOBYTE: EQU 03H ;CDISK: EQU 0 ;ESC: EQU 0 ;EOF: DC3: EQU 19 DC1: EQU 17 ACR: EQU 13 CDISK: EQU 04 ESC: EQU 27 EOF: EQU 24 ;DC3: EQU 19 ;DC1: EQU 17 ;ACR: EQU 13 ALF: EQU 10 BEL: EQU 07 ; ;****************************************************************************** ; HARDWARE PORT EQUATES. DARTAD: EQU 0 ;DART 'A' DATA DARTAC: EQU 1 ; CONTROL DARTBD: EQU 2 ; " 'B' DATA DARTBC: EQU 3 ; " CONTROL PIOAD: EQU 4 ;PIO 'A' DATA PIOBD: EQU 5 ; " 7E7 H PIOAC: EQU 6 ; 4 'A' CONTROL PIOBC: EQU 7 ; H 3B, h CTC0: EQU 8 ;COUNTER TIMER 0 CTC1: EQU 9 ; " " 1 CTC2: EQU 0AH ; II Pi 7 CTC3: EQU 0BH ; . FE 3 FCOM: EQU 10H ;FLOPPY DISC COMMAND/STATUS FTRK: EQU 11H ; . " TRACK REGISTER FSEC: EQU 12H ; i II " SECTOR REGISTER FDATA: EQU 13H ; H U DATA FORT ZDMA: EQU 14H ;DMA CONTROLLER DISCM: EQU 16H ;DISC HARDWARE CONTROL MUXM: EQU 17H ; MEMORY MULTIPLEXER CONTROL DSEP: EQU 18H ;DISC DATA SEFERATOR CONTROL HWSTAT: EQU 19H ;PORT FOR HEADS-LOADED ETC.. BANK: EQU 1AH ;MEMORY BANK SELECT FORT ; ;*************M************************************************************** ; CONTROL BOOLEANS FOR DISC DRIVES SUPPORTED IN THIS COMPILE. (MAXIMUM 4). FALSE: EQU 00 TRUE: EQU NOT FALSE DOAUTO: EQU TRUE ;TRUE FOR "OBEY COLD-START COMMAND" MAXI: EQU FALSE ;TRUE FOR 8" DRIVES MINI: EQU TRUE ;TRUE FOR 5" DRIVES BOTH: EQU MAXI AND MINI ;A: & B: ARE MAXI, C: & D: ARE MINI. DRIVES: EQU 4 ;i****************************************************************************** ; DRIVE STEP RATE EQUATES: VALUE MAXI MINI ;0 3Ms 6Ms ;1 6Ms 12Ms ;; 2 10Ms 20Ms ;; 3 15Ms 30Ms MAXIRATE: EQU 0 ;FOR "YE DATA" MAXI DRIVES MINIRATE: EQU 0 ;FOR "MPI" MINI DRIVES ;****************************************************************************** ; I/O BYTE CONTROL, DEVICES IMPLEMENTED ARE: ;CON: CRT: -- VIDEO CONSOLE VIA DART CHANNEL "A' ;CON: UC1: -- REMOTE DIAGNOSTICCONSOLE, DART CHANNELS "A" u n ;B ;LST: TTY: -- SERIAL PRINTER, READY/BUSY HANDSHAKE, PART CHANNEL "B" LST: ;LPT: -- PARALLEL "CENTRONIX" LIKE PRINTER. PIO. ;'7? 1 ; CCM: =CPT ST: PT: ;+ ;LJ1. III. ZGRIML— rMINICM, MCMIJI/ZUT rIMNIJMMINC5 MMM1 —1J- ;LST: LPT: -- PARALLEL "CENTRONIX" LIKE PRINTER, PIO. ; INITIO: EQU 0 ;****************************************************************************** ; THE FOLLOWING IS THE CP/M JUMP VECTOR TABLE. lT MUST NOT BE ALTERED. ORG BIOS JP BOOT ;COLD BOOT JP WBOOT ;WARM BOOT JP CONSTAT ;GET CONSOLE STATUS JP CONIN ;GET CONSOLE INPUT JP CONOUT ;WRITE TO CONSOLE JP PLIST ;OUTPUT TO PRINTER DEVICE JP PUNCH ;PUNCH OUTPUT JP READER ;READER INPUT JP HOME ;HOME DISC DRIVE JP SETDSK ;SELECT DISC DRIVE JP SETTRK ;SET DISC TRACK JP SETSEC ;SET DISC SECTOR JP SETDMA ;SET TRANSFER ADDREDD JP READ ;READ DISC JP WRITE ;WRITE TO DISC JP LISTST ;TEST LIST STATUS JP SECTRAN ;LOGICAL TO PHYSICAL SECTOR CONVERT ;****************************************************************************** ; POINTERS TO VALUES WHICH CERTAIN EXTERNAL UTILITIES WILL NEED TO ACCESS. ; DEFW 'RC' ;AUTHORS INITIALS ARE A VERSION CHECK WORD. IOVALU: DEFB INITIO ;USED AT COLD—START TO INITIALIZE ASSIGNMENTS DEFW BPSA ;ADDRESS OF BAUD RATE "A" DEFW BPSB ; • ,, ;" BAUD RATE "B" DEFW HOOK5 ; " 5" TABLE (ZERO IF ABSENT). DEFW DR0 ; 9 DISC DRIVE CHARACTERISTICS DEFW MINIVAL ; " MOTOR OFF TIMEOUT COUNT ; ;*************************k**************************************************** ; ; THESE ARE THE VECTORED INTERRUPT DISPATCH ADDRESSES. MOST POINT TO A ; SIMPLE IDLE ROUTINE THAT ENABLES INTERRUPTS AND RETURNS. ; VIR1: DEFW IDARTA ;CONSOLE INPUT SERVICER DEFW IDLE ;DO NOTHING DEFW IDLE ; 0 /I DEFW IDLE ; „ u DEFW IDLE ; a IP ;e u DEFW IDLE ; • II ;) PI DEFW IDLE ; s I; ;9 „ DEFW IDLE ; ° " ;e H DEFW IDLE ; • IP ;5 „ DEFW IDLE ; . ,, ;9 », DEFW IDLE ; r Ii ;A eI DEFW IDLE ; „ n DEFW IDLE ; 16 11 DEFW IDLE ; • 16 ;9 u DEFW IDLE ; . ,, ;9 9e DEFW IDLE ; • ii ;5 H VIR2: DEFW IDLE ;CTC CHANNEL 0 DEFW IDLE ; • u ; i. I DEFW IDLE ; „ . 2 DEFW IRTC ; „ „ 3 DEFW IDLE ;DO NOTHING DEFW IDLE ; /I ; ;10000001B ; CON:=CRT: LST:=LPT: • ;W***4-****************44.444-4-4444-444-444444444444444-444444 DEFW IDLE ;DO NOTHING ;;DEFT IDLE ;****************************************************************************** CONSOLE INPUT VECTORS CONIN: LD B,1 CALL DISPAT DEFW 0 ;TTY: ;;DEFW CRTIN ;CRT: ;;DEFW RDRIN ;BAT: DEFW REMIN ;UC1: ;****************************************************************************** ; CONSOLE STATUS VECTORS CONSTAT: ;;LDB,1 CALL DISPAT DEFW 0 ;TTY: DEFW CRTSTAT ;CRT: DEFW RDRST ;BAT: DEFW REMSTAT ;UC1: ;***********************e44-**************************************************** CONSOLE OUTPUT VECTORS CONOUT: LD B,1 CALL DISPAT DEFW 0 ;TTY! DEFW CRTOUT ;CRT: DEFW PLIST ;BAT: DEFW REMOUT ;UC1: ;;************************4-44************************************************** ; READER DEVICE INPUT VECTORS READER: LD B,3 CALL DISPAT ;;DEFW RDRIN ;TTY: DEFW 0 ;PTR: DEFW 0 ;URI: DEFW 0 ;UR2: ;**************************************************************************** ; PUNCH DEVICE OUTPUT VECTORS PUNCH: LD B,5 CALL DISPAT DEFW SLIST ;TTY: DEFW 0 ;PTP: DEFW 0 ;UP1: DEFW 0 ;UP2: ;;*****i(************************************************************************ ; LIST DEVICE OUTPUT VECTORS PLIST: ;; LD B,7 ;; CALL DISPAT ;;Lle1 MeVIUt Vt.LIUKb ;;PLIST: LD B,7 CALL DISPAT DEFW SLIST ;TTY: DEFW CRTOUT ;CRT: DEFW PLIST ;LPT: DEFW 0 ;ULI: ;****************************************************************************** ; LIST DEVICE STATUS VECTORS LISTST: LD B,7 CALL DISPAT ;;DEFW SLISST ;TTY: DEFW CRTSTAT ;CRT: DEFW PLISST ;LPT: DEFW 0 ;ULI: ;****************************************************************************** ; I/O BYTE DISPATCHER. ON ENTRY, THE TOP OF STACK POINTS TO A 4 WORD TABLE ; OF SERVICE ROUTINES. HAS A ROTATE COUNT TO USE FOR MASKING. DISPAT: LD A,(IOBYTE) RLCA ;GET AND PRE-CONDITION THE I/O BYTE DISPAL: RRCA DJNZ DISPAL AND 3 ;USE THE I/O VALUE AS AN OFFSET ;;;ADD A LD E,A LD D,0 POP HL ;ADD TO THE TABLE BASE ADD HL,DE LD E,(HL) ;LOAD THE SERVICE ROUTINE ADDRESS INC HL LD D,(HL) ;THEN GO THERE EX DE, HL JP (HL) ;****************************************************************************** ; REMOTE CONSOLE INPUT. BOTH SERIAL CHANNELS ARE TESTED IN ROTATION UNTIL ; ONE OF THE USERS HAS SOMETHING TO SAY. REMIN: CALL RDRST ;;JR NZ RDRIN CALL CRTSTAT ;;JR Z REMIN ;****************************************************************************** ;GET THE NEXT CHARACTER FROM THE CONSOLE FIFO QUEUE BUFFER. WAIT IF NEED BE. CALL CRTSTAT ;WAIT UNTIL THERE IS ;;JR Z CRTIN ; DATA IN THE QUEUE LD A, (BC) AND 7FH ;GET THE DATA AND STRIP PARITY ;;;;;LD HI ,CBUrTnr ;SEE IF THE CHAR CAME FROM THE ;;DSBC B ; LAST BYTE OF THE QUEUE MACRO ;;JR Z RES INC BC ;IF NOT, POINT TO THE NEXT POSY ;;JR SET;! ; INTHE QUEUE ;;;t n BC,FIFnBUP ;LOAD THE BEGINNING OF THE QUEUE ;;;'7.7,77 717-4.7 !,-zr7T tnrATT,-^m c-ne C'•'T (rnicii= c.=An RESQ: SETQ: JR Z,RESQ INC BC ;IF NOT, POINT TO THE NEXT POS'(' JR SETQ ;: ; INTHE QUEUE ;; LD Bfl,FIFnBU ;LOAD THE BEGINNING OF THE QUEUE ;; SBCD rJTAIL ;SET LOCATION FOR NEXT QUEUE READ RET ;*************************************J(**************************************** ; INPUT STATUS FOR DART CHANNEL "B" RDRST: ;;;;IN A,DARTBC in a,(DARTBC) RRA ;SEE IF DATA IS AVAILABLE ;;SEC A RET ;****************************************************************************** ; ;;GET DATA FROM DART CHANNEL "B" CALL RDRST ;;JR Z RDRIN ;;IN A,DARTBD in a,(DARTBD) ;;AND 0177FH RET ;****************************************************************************** ; REMOTE CONSOLE OUTPUT. ALL CHARACTERS ARE SENT TO BOTH DART SERIAL CHANNELS. REMOUT: CALL SLIST ;DO "B" THEN FALL THRU TO "A" ;****************************************************************************** ; CONSOLE OUTPUT ROUTINE. CHARACTER TO PRINT IS IN REGISTER . CRTOUT: ;;IN A,DARTAC in a,(DARTAC) AND 4 ;;JR Z CRTOUT ;WAIT UNTIL THE LAST CHAR IS GONE LD A,C ; THEN OUTPUT THIS ONE. ;;OUT DARTAD,A OUT (DARTAD),a RET ;****************************************************************************** ; REMOTE CONSOLE STATUS. BOTH DART CHANNEL INPUTS ARE SAMPLED FOR DATA READY. ; CHANNEL "B" IS ASSUMED CONNECTED TO A MODEM AND IS TESTED FIRST. REMSTAT: CALL RDRST ;TEST DART CH "B", IF NOT READY, RET NZ ; FALL THROUGH TO CH "A". ;**************.*******v-******************************************************** ; SEE IF ANY DATA IS IN THE CONSOLE FIFO QUEUE. ON EXIT 00 = NO, FF = YES. CRTSTAT: ;;XOR LD HL,(QHEAD) ;GET WHERE INPUT PUTS THEM ;;LBCD QTAIL ; AND WHERE OUTPUT TAKES 'EM. ;;DSBC RET Z ;IF EQUAL THE OUEUE'S EMPTY LD A,0FFH ; IF NOT EMPTY RETURN AN FF. RET ;************-*****************************e************************************ LD A,0FFH ; IF NOT EMPTY RETURN AN FF. RET ;************>***************************************************************** ; ANY INPUT CHARACTERS WILL VECTOR TO HERE WHEN HIGHER PRIORITY DEVICES ALLOW THE INTERRUPY DAISY CHAIN. THIS ROUTINE MAY BE INTERRUPTED TOO. IDARTA: ;;SSPD SPHOLD1 ;SAVE PROGRAMS STACK POINTER LD SP,REGSAVE ; AND SET OUR OWN PUSH AF ; THEN SAVE ALL REGISTERS PUSH BC PUSH DE PUSH HL ;;IN A,DARTAD ;GET AND SAVE THE DATA in a,(DARTAD) PUSH AF ;;LBCD QHEAD ;GET THE LOCATION OF THE LAST LD D,B ; CHAR TO ENTER THE FIFO QUEUE LD E,C LD HL,CBUFTOP ;SEE IF lT IS AT THE TOP LIMIT XOR A ;;DSBC B ;IF SO THIS CHAR MUST GO JR Z,QRES ; TO THE START OF THE QUEUE INC BC ;ELSE JUST POINT TO THE NEXT HOLE JR QSET QRES: LD BC,FIFOBUF ;START OF FIFO ADDRESS QSET: ;;; LD HL,(QTAIL) LD HL,(0) ; only for Test LD HL,(QTAIL) POP AF ;GET THE CHAR BACK OR A ;WE DON'T STORE NULLS ;;DSBC B ; NOR DO WE ALLOW OVEP-RUNS JR Z,NULCHR LD (DE),A ;PUT lT IN THE QUEUE ;;SBCD QEAD ; AND UPDATE THE POINTER NULCHR: POP HL POP DE ;;POP PC pop bc POP AF ;;LSPD SPHOLD1 ;RESTORE ALL REGS FOR EXIT ;****************************************************************************** THIS IS THE GENERAL "DO NOTHING" INTERRUPT SERVICE CODE. IDLE: EI RETI ;****************************************************************************** ; PARALLEL STATUS ROUTINE. THE RETURNED VALUE REFLECTS THE CENTRONIX LINE "I/O BUSY". ON EXIT, REGISTER. VALUES 0.. "DRIVES" ARE ACCEPTED AND THE RELEVENT ;DISC PARAMETER ENTRY ADDRESS RETURNED IN SETDSK: LD A,C LD HL,0 ;00 IS AN ERROR RETURN CP 'M'-'A' JR NZ,SETRST ;REQUEST FOR DRIVE M: LD HL,DPEM LD (SEKDSK),A RET SETRST: CP DRIVES ;IS THE UNIT LEGAL RET NC LD A,E ;SEE IF CP/M HAS LOOKED AT THIS AND A ; DISC RECIENTLY. LD L,C ADD HL,HL ; (*16) ADD HL,HL ADD HL,HL ADD HL,HL ;MAKE IT A 16 BYTE OFFSET LD DE,DPE0 ; TO THE PARAM ENTRY TABLES ADD HL,DE ;RETURN THE PARAM ENTRY LD A,C ;EXIT IF WE KNOW ABOUT THIS DISC LD (SEKDSK),A ;SAVE SELECTED UNIT RET NZ PUSH IX ;SAVE INDEX REGISTER <%< PUSH HL ;AND DPH POINTER CALL DRPARAM ;SET : A,5 ;IN THE CONFIG. BLOCK LD (PRECOMP),A ; AND THE SAVE AREA LD E,1 ;SET A LOW RETRY COUNT JP RDID1 ;READ A SECTOR HEADER ;************************-X***************************************************** ; SAVE THE SECTOR PASSED IN REG eC> FOR A FUTURE ACCESS. SETSEC: LD A,C LD (SEKSEC),A RET ;****************************************************************************** ; SAVE THE ADDRESS PASSED IN AS THE SOURCE/DESTINATION FOR A DISC ACCESS. SETDMA: ;SBCD SEKDMA RET ;****************************************************************************** ; THIS ROUTINE IS USED TO CONVERT THE LOGICAL SECTOR NUMBER PASSED INTO A ; PHYSICAL SECTOR NUMEER. SINCE THE "CACHE" BIOS PERFORMS WHOLE TRACK TRANSFERS ; ANY SKEW IS UNIMPORTANT. HOWEVER, IN EMULATING ALIEN DISC SYSTEMS WE MUST ; DUPLICATE THE SKEW. IF A TRANSLATE TABLE EXISTS, IT IS PASSED IN . SECTRAN: LD A,D OR E ;TEST FOR NO XLAT TABLE. JR NZ,XLAT ;;LD H,P ;GET THE SECTOR VALUE IN ‚HL\ LD L,C INC HL ;ADJUST FOR A FIRST SECTOR OF RET ; ONE, AND EXIT ;****************************************************************************** INC HL ;ADJUST FOR A FIRST SECTOR OF- RET ; ONE, AND EXIT ;****************************************************************************** ; THIS ROUTINE PERFORMS SEQUENTIAL TO SKEWED SECTOR TRANSLATIONS BASED ON A ; 4 BYTE TABLE POINTED TO BY := DIV := (SECTOR NO.) MOD (SIZE FACTOR) OR L ;COMBINE THIS WITH THE BASE SECTOR AND ADJUST INC A ; FOR A FIRST SECTOR NUMBER OF ONE. LD L,A RET ;****************************************************************************** ; TRANSFER THE REQUESTED BLOCK FROM CACHE MEMORY IF POSSIBLE. IF NOT, READ ; THE DESIRED TRACK THEN DO IT. READCACH: CALL CHKMAP ;;LD A, 2ACHFUL1 ;;;READCACH: CALL CHKMAP LD A,(CACHFUL) AND A ;IS ANYTHING IN THE CACHE ? JR Z,DOREAD CALL CACHADR JR Z,DOREAD LD A,(TRACK) ;SEE IF THE TRACKS MATCH LD HL,SEKTRK CP (HL) JR NZ,DOREAD LD A,(DISK) ;AND IF SO, ARE THE DISC UNITS LD HL,SEKDSK ; THE SAME ? CP (HL) JR Z,INCORE ;IF SO, NO READS ARE NECCESSARY DOREAD: LD A,(SEKDSK) LD (DISK),A ;SET THE PARAMS FOR THE TRANSFER LD A,(SEKTRK) ; FIRST THE TRACK, THEN THE SECTOR LD (TRACK),A CALL READTRK ;NOW FILL THE CACHE XFRIN: CALL CACHADR LD C,1 JR Z,BDMA1 ;LDED SEKDMA ;GET THE DESTINATION MEMORY ADDRESS PUSH DE LD A,18H ;SET MODE CACHE TO MAIN MEMORY CALL M2MXFER ; AND DO IT. POP HL LD BC,128 ;ADD THE BLOCK SIZE ADD HL,BC LD C,0 BDMA1: LD A,20 ;LD (PNTR2),A ;0F349H LD A,0FFH LD (CACHFUL),A ;0F7DBH LD A,C RET ;****************************************************************************** ; WHEN WE ARRIVE HERE, THE REQUIRED TRACK IS IN THE CACHE, SO DO THE TRANSFER. INCORE: CALL XFRIN ;DO THE TRANSFER AND A ; AND TEST THE RESULT CALL NZ,DOREAD ;RE-TRY IF NECCESSARY. RET ;****************************************************************************** ; THE MEMORY DRIVE (M:) IS IMPLEMENTED IN THE SECOND BANK AS A 48K "DISC" ; WITH 192 TRACKS HAVING TWO 128 BYTE SECTORS EACH. THIS GEOGRAPHY ENABLES US ; TO USE THE TRAK VALUE AS THE PAGE NUMBER AND THE SECTOR AS THE OFFSET ; WITHIN THE PAGE. A FLAG SET ON ENTRY DECIDES WETHER THE TRANSFER IS TO OR ; FROM THE PGUEDO-DISC. MREAD: DEFB 02EH MWRITE: XOR A AND A PUSH AF LD A,(SEKTRK) LD D,A LD A,(SEKSEC) DEC A JR Z,MEMF1 LD A,128 MEMF1: LD E,A ;;LD HL,(SEF.DMA) BECOMES "MVI A,0AFH" ;SAVE THE DRIECTION FLAG ;PAGE NUMBER ;SECTOR 1 IS AT TRACK + 80H JR Z,MEMF1 ;5ECTUR 1 15 Af /KALK + bOM LD A,128 ;MEMF1: LD E,A LD HL,(SEKDMA) POP AF ;RE-GET DIRECTION INDICATOR LD A,10H JR Z,MEMF2 LD A,18H ;SET THE MEMORY MANAGER VALUE EX DE,HL MEMF2: CALL M2MXFER XOR A ;ALWAYS RETURN A SUCCESS RET ;****************************************************************************** ; THIS IS THE OUTER LEVEL CACHE READ ROUTINE, UNIT, TRACK, SECTOR AND ; DMA ADDRESS HAVING BEEN SET UP PREVIOUSLY. READ: LD A,(SEKDSK) CP 'M'-'A' ;THE MEMORY DRIVE ? JR Z,MREAD ;SSPD SPHOLD2 ;SAVE USERS STACK POINTER MACRO LD SP,FIFOBUF ; AND USE OUR OWN CALL READCACH ;DO THE READ ;LSPD SPHOLD2 ; THEN RESTORE AND EXIT. MACRO RET ;****************************************************************************** ; OUTERMOST WRITE DISC DATA ROUTINE. ACTUAL WRITE NOT DONE HERE. ON FIRST ; WRITE TO THE CACHE, THE MAP IS RESET TO ALL "FF". BLOCKS THAT ARE CHANGED ; HAVE THEIR MAP BYTE SET TO ZERO, AND ARE CHANGED IN THE CACHE BUFFER. ; FINALLY "FLAG1" IS SET SO THAT THE REAL TIME CLOCK WILL CAUSE THE ACTUAL ; WRITE TO OCCUR. WRITE: LD A,(SEKDSK) ;CP JR Z,MWRITE ;SSPD SPHOLD2 ;SAVE USERS STACK MACRO LD SP,FIFOBUF ; AND SUBSTITUTE OUR OWN. XOR A LD (FLAG1),A LD (CACHFUL),A LD A,(MAPMT) ;IF DISC NOT YET UPDATED, SKIP THE AND A ; NEXT BIT. JR NZ,WRITEC CALL FILLMAP ;FLAG THE MAP "ALL NEED WRITING" JR XFROUT WRITEC: LD A,(SEKDSK) ;ARE THE UNITS THE SAME LD HL,DISK CP (HL) JR NZ,MTCACH LD A,(SEKTRK) ;ARE THE TRACKS THE SAME '2 LD HL,TRACK ;C (HL) JR Z,XFROUT MTCACH: CALL CHKMAP ;CLEAR OUT THE MAP XFROUT: LD A,0FFH LD (MAPMT),A ;FLAG MAP TO "NEEDS WRITING" LD A,(SEKDSK) LD (DISK),A ;SET THE TRANSFER DISC LD A,(SEKTRK) ; AND THE TRANSFER TRACK LD (TRACK),A CALL CACHADR ;CALCULATE BLOCK# IN CACHE REQUESTED XOR A LD (DE),A ;SET MAP TO SHOW "UPDATED" EX DE,HL ;;LD HL,(EKDMA) THE USER DMA ADDRESS XOR A LD (DE),A ;SET MAP TO SHOW "UPDATED" EX DE,HL ;;LD HL,OSEKDMA ;GET THE USER DMA ADDRESS PUSH HL LD A,10H ;MODE IS MEMORY TO CACHE CALL M2MXFER ; MOVE IT IN POP HL LD BC,128 ;UP THE TRANSFER ADDRESS ADD HL,BC ;RETURN UPDATED DMA TO CP/M ;;LD A,..; ;SET "FLAG1" SO THAT INTERRUPT SERVICER LD (FLAG1),A ; CAN WRITE DISC ON NEXT SERVICE. XOR A ;ENSURE CP/M SEES SUCCESS ;LSPD SPHOLD2 ;RESTORE STACK MACRO RET ;****************************************************************************** ; HERE, AT LAST, IS THE ACTUAL WRITE MECnINISM. "MAPMT" IS CHECKED FOR BEING ; NON-ZERO. IF IT IS, THEN ANY SECTORS CONTAINING BLOCKS WHICH HAVE BEEN ; CHANGED (I.E. BYTE=00), ARE WRITTEN OUT. FINALLY THE WHOLE MAP IS RESET TO ; "FE". THIS ROUTINE WILL PROBABLY BE CALLED FROM THE REAL TIME CLOCK ROUTINE. CHKMAP: XOR A LD (FLAG1),A ;FLAG THE MAP AS CHECKED LD HL,MAPMT ;IF THE MAP IS ALREADY LD A,(HL) ; INITIALISED, THEN WE CAN AND A ; EXIT NOW. RET XOR A LD (HL),A ;FLAG IT AS INITIALISED CALL DOFN ;WRITE ANY UPDATED SECTORS JP FILLMAP ;RESET ALL BYTES TO "FF" ;****************************************************************************** ; THIS ROUTINE READS A WHOLE TRACK INTO THE CACHE BUFFER. MAP BYTES ARE ZEROED ; EOR EACH SECTOR THAT IS READ SUCCESSFULLY. READTRK: PUSH IX PUSH IY CALL FILLMAP ;"FF" THE MAP CALL SEEK ; AND MOVE THE HEADS JR NZ,READT6 ;JUMP ON A SEEK ERROR CALL RDID ;GET THE NEXT AVAILABLE SECTOR HEADER JR NZ,READT6 ; AND EXIT IF DISC UNREADABLE ;;LD A,(SECMAX) ;SET THE TOTAL 128 BYTE BLOCKS ON TRACK LD (BLKCNT),A ; AND SAVE AS A BLOCK COUNT READT1: LD C,1 ;SET A RETRY COUNT OF 1. LD A,(SEKSEC) ;GET THE REC4UESTED SECTOR LD HL,PRVHLD SUB (HL) JR C,READT2 LD HL,SECSIZE CP (HL) JR NC,READT2 LD C,12 ;SET NORMAL RETRY COUNT READT2: LD A,C ;STORE RETRY COUNT LD (RWRTRY),A ;;CALL CACHA3 ;GET AND SAVE THE MAP POINTER PUSH DE CALL READS ;READ "NXTSEC" READT3: POP HL LD A,(SECSIZE) ;GET THE SECTOR SIZE VALUE LD C,A ; FOR FUTURE USE LD B,A JR NZ,READT5 ;JF THE READ FAILED, DO NEXT SECTOR READT4: ;)D LD C,A ; FOR FUTURE USE LD L,A JR NZ,READT5 ;IF THE READ FAILED, DO NEXT SECTOR ;;;;;READT4: LD (HL),0 INC HL ;ZERO OUT THE APPROPRIATE NUMBER DJNZ READT4 ; OF MAP BLOCK BYTES READT5: CALL SECWARP ;SET UP THE NEXT SECTOR TO READ JR NZ,READT1 ; AND LOOP TIL ALL DONE. READT6: LD A,100 LD (MINIVAL),A ;SET MINI MOTRO DELAY POP IY ;ALL DONE, RESTORE AND EXIT. POP IX RET ;****************************************************************************** ; CHECK THE CACHE BYTE-MAP FOR SECTORS CONTAINING ALTERED BLOCKS AND RE-WRITE ; THESE SECTORS. DOFN: PUSH IX PUSH IY XOR A ;;LD (OPEAIL),A ;SET OPERATION OK CALL SEEK ;POSITION HEADS JR NZ,DERROR ; INFORM USER ABOUT FAILS LD A,12 LD (RWRTRY),A ;SET READ/WRITE RETRY COUNT LD A,12 LD (FLAG5),A ; AND READ AFTER WRITE RETRYS ;;LD A,(SECMAX) ;SET BLOCKCOUNT LD (BLKCNT),A LD A,1 LD (PRVHLD),A ;AND FIRST SECTOR DOFN1: CALL DEBLOCK ;ARE ALL MAP BYTES OF "PRVHLD" JR NZ,DOFN2 ; EQUAL ? (JUMP IF NOT SO) CALL SECWARP ;GET NEXT SECTOR/BLOCK VALUE ;;;;; JR NZ,DOPN1 ;JUMP "BLKCNT" NOT YET ZERO JR DOFN5 DOFN2: CALL RDID ;FIND OUT WHAT HAS JUST GONE JR NZ,DERROR ; RAST THE HEADS ;;LD A,(SECMAX) LD (BLKCNT),A ;RESET THE BLOCKCOUNT DOFN3: CALL DEBLOCK ;ALL MAP BYTES OF "PRVHLD" EQUAL ? JR Z,DOFN4 ; (JUMP IF SO) LD HL,CACH-400H ;SET UP TRANSFER BASE 1K BELOW CACHE CALL READS ; AND READ THE SECTOR CALL NZ,RWFAIL ;SERVICE ANY ERRORS CALL MEMOVE ;MOVE THE BLOCK DOFN4: CALL SECWARP ;GET NEXT SECTOR/BLOCK VALUES JR NZ,DOFN3 ;LOOP IF ANY LEFT IN "BLKCNT" DOFN5: CALL RDID ;GET AN I.D. JR NZ,DERROR ;;LD A,(SECMAX) ;RESET TOTAL BLOCK COUNT LD (BLKCNT),A DOFN6: ;;;CALL CACHA3 ;SEE IF MAP VALUE = "FF" JR Z,DOFN7 ; JUMP IF SO. PUSH DE ;SAVE MAP POINTER CALL WRITES ;WRITE THE SECTOR POP HL JR Z,DOFN7 ;IF AN ERROR OCCURRED, LD (HL),0FFH ; FLAG SECTOR "NEEDS RE-WRITING" DOFN7: CALL SECWARP ;GET NEXT SECTOR/BLOCK VALUES JR NZ,DOFN6 ;LOOP IF ANY BLOCKD STILL TO GO ;;LD A,(SECMAX) ;RESET TOTAL BLOCKS LD (BLKCNT),A DOEN8: ;;;; CALL CACHA3 ;SEE IF MAP VALUE = "FF" CALL NZ,RAWS ;IF NOT DO READ AFTER WRITE CALL SECWARP ;LOOP WHILE MORE BLOCKS LEFT JR NZ,DOFN3 DOFN8: ;CALL CACHA3 ;SEE IF MAP VALUE = "FF" ;;CALL -NZ,RAWS ;IF NOT DO READ AFTER WRITE CALL SECWARP ;LOOP WHILE MORE BLOCKS LEFT JR NZ,DOEN8 DERROR: POP IY POP IX LD A,100 ;START THE MINI MOTORS SHUTDOWN LD (MINIVAL),A ; SEQUENCE. LD A,(OPFAIL) ;EXIT IF NOT AN ERROR AND A RET LD A,(DISK) PUSH AF ;NON-ZERO = "WRITE ERROR" JP DERR2 ;****************************************************************************** ; REPORT A DISC OPERATION FAILURE AND WAIT FOR USER RESPONSE. DERR1: ;SEC A PUSH AF ; 'ZERO = "NOT READY" ;LDX A,0 AND 3 DERR2: ;;;; ADD 'A' ; THE MESSAGE LD (RAWDSK),A CALL PRINTO ;TELL OPERATOR DEFB BEL,ACR,ALF DEFM 'CBIOS Error on ' RAWDSK: DEFB 0 ;SPACE FOR UNIT IN ERROR DEFB ',0 POP AF JR NZ,DERR3 ;DO WE NEED TO WAIT NOW ? CALL PRINTO DEFM 'NOT READY ',0 DERR3: CALL CONIN ;WAIT FOR CONSOLE DATA CP 3 JP Z,WBOOT ;RESET ALL ON A CONTROL + "C" CP ESC RET Z ; OR TRY AGAIN ON AN "ESCAPE" JR DERR3 ;****************************************************************************** ; ADJUST THE "NXTSEC" AND ITS BLOCK # (IN "PRVHLD") TO THE NEXT IN LINE. WRAP ; AROUND TO SECTOR 1 WHEN TRACK LIMIT EXCEEDED. REMOVE ONE SECTORS WORTH OF ; BLOCKS FROM "BLKCN1". RETURN A ZERO FLAG WHEN "BLKCNT" IS EXPIRED, SECWARP: LD HL,NXTSEC LD DE,PRVHLD LD A,(DE) ;GOT BLOCK # ;ADDX 03H ADD BLOCKS/SECOER ;CMPX 02H COMPARE WITH BLOCKS/TRACK JR C,SWARP1 ;SEE IF WE'VE REACHED THE LAST JR Z,SWARP1 ; SECTOR YET. LD A,1 LD B,1 ;IF SO, WRAP AROUND TO SECTOR 1 AGAIN JR SWARP2 SWARP1: LD B,(HL) ;GET NEXT SECTOR ;INC SWARP2: LD (DE),A ;STORE CALCULATED FIRST BLOCK # OF LD (HL),B ; THE NEXT SECTOR, AND THE SECTOR # ;;LD HL,ELKONT LD A,(HL) ;REMOVE 1 SECTOR OF BLOCKS FROM THE ;SUBX 03H ; RUNNING TOTAL LD (HL),A RET ;****************************************************************************** • ;SUBX 03H ; RUNNING TOTAL LD (HL),A RET ;*******-********4=************************************************************** ; RETURN ZERO IF ALL THE MAP BYTES REFERENCED BY THE SECTOR IN "PRVHLD" ; ARE OE THE SAME VALUE. DEBLOCK: LD A,(SECSIZE) ;NO ACTION IF 128 BYTE SECTORS DEC A RET Z PUSH AF ;;CALL CACHA3 ;GET BLOCK # AND MAP VALUE OF FIRST. POP BC ;GOT BLOCKS/SECTOR — 1. (IN eslr, NOW). EX DE,HL DEBLK1: INC HL ;SEE IF NEXT MAP ENTRY IS THE CP (HL) ; SAME AS THE LAST RET NZ DJNZ DEBLK1 ;LOOP ON IT ;;;;;AND RET ;****************************************************************************** ; ROUTINE TO TRANSFER BLOCKS (128 BYTES) OF MEMORY INTO AND OUTOF THE CACHE. MEMOVE: ;;CALL CACHA3 ;SAVE SECTOR IN CACHE ADDRESS LD (MSRCE),HL ; FOR TRANSFER LD HL,CACH-400H LD (MDEST),HL ;AND WHERE IT>S TO GO LD A,(SECSIZE) ;GET BLOCKS/SECTOR LD B,A PUSH BC MEMOV1: LD A,(DE) ;GET MAP BYTE AND A JR Z,MEMOV2 ;HAS IT BEEN READ '2 PUSH DE LD HL,(MDEST) ;REGET THE MEMORY POINTERS ;LDED MSRCE LD A,8 ;SET THE MEMORY CONTROL MODE CALL M2MXFER ; AND SHIFT THE BLOCK POP DE XOR A ;FLAG IT IN THE MAP LD (DE),A MEMOV2: POP BC DEC B ;BLOCKS/SECTOR — 1 RET Z ; DONE IF 128 BYTES/SEC PUSH BC LD BC,128 ;LOAD BLOCK SIZE LD HL,(MSRCE) ADD HL,BC ;FORM OFFSET INTO CACHE LD (MSRCE),HL ; SAVE IT LD HL,(MDEST) ;UP DESTINATION TOO ADD HL,BC LD (MDEST),HL ; AND SAVE THAT INC DE ;BUMP MAP POINTER JR MEMOV1 ;AND LOOP ;***********3(****************************************************************** ; READ A SECTOR I.D. FROM THE CURRENT DISC. RDID: LD B,12 ;SET RETRY COUNT RDID1: LD A,0C0H ;READ I.D. COMMAND LD HL,IDSAVE ;BUFFER TO RECEIVE IT ;P' BC ;;LD ilL,IDSAVE ;BUFFER TO RECEIVE IT PUSH BC CALL RDWRT ;DO THE READ. POP BC AND 9DH ;MASK ERROR BITS JR Z,SECPERV ;DO NEXT STEP IF THE READ WAS OK. DJNZ RDID1 ;LOOP 11 MORE TIMES LD A,0FFH LD (OPFAIL),A ; BEFORE FLAGGING A BIG FAIL. AND A RET ;****************************************************************************** ; SET "NXTSEC" TO THE SECTOR WHICH WILL APPEAR NEXT. SET "PRVHLD" TO THE FIRST ; BLOCK # OF THIS SECTOR. REDUCE "BLKCNT" BY A SECTOR OF BLOCKS. SECPERV: ;;LD A,(ID3EC) LD (NXTSEC),A ;STORE THE SECTOR # JUST PASSED LD C,A ;;DEC LESS ONE... LD HL,SECSIZE ;GET THE SPECIFIED # nF, PLOCv.9 LD B,(HL) ; IN A SECTOR XOR A SECPV1: ;; ADD C ;PL=K # = ((SFC-1,*7="1-2)+1 DJNZ SECPV1 ;;INC ;;LD (7Rvuun),A ; 7s4v7 17 ;;CALL CHECK FOR '4RAP—AROUND OF TRACK ;;XOR RET ;***,e*****›,v--,44h-,4********Y********************************************** ; READ "NXTSEC". REPEAT UP TO "RWRTRY" TIMES. RETURN ZERO IF SUCCESSFUL. READS: LD A,(NXTSEC) ;SEND SECTOR VALUE TO CONTROLLER ;OUT FSEC,A out (FSEC),a LD A,(RWRTRY) ;LOAD UP THE RETRY LIMIT LD B,A READS1: LD A,80H ;BASIS OF SECTOR READ COMMAND PUSH BC CALL RDWRT ;DO THE READ POP BC AND 9DH ;MASK ERROR BITS RET Z ; EXIT IF OK DJNZ READS1 LD A,1 ;FLAG AN ERROR EXIT AND A RET ;****************************************************************************** ; WRITE "NXTSEC" TO DISC. REPEAT UP TO "RWRTRY" TIMES. RETURN ZERO IF WRITE OK. WRITES: LD A,(NXTSEC) ;SET UP SECTOR FOR CONTROLLER ;OUT FSEC,A out (FSEC),a ;;LD A,(PWRTRY) ;LOAD RETRY LIMIT LD B,A WRITE1: LD A,0A0H ;BASIS OF A WRITE COMMAND PUSH BC CALL RDWRT ;DO THE WRITE POP BC AND 0FDH ;MASK ERROR BITS RET DJNZ WRITE1 ;AND gFDH ;MASK ERROR BITS RET DJNZ WRITE1 JP RWFAIL ;****************************************************************************** ; PERFORM A "READ-AFTER-WRITE" CHECK. RAWS: LD A,(NXTSEC) ;SET THE SECTOR ;OUT FSEC,A out (FSEC),a LD A,(FLAG5) ; AND THE RETRY COUNT LD B,A RAWS1: LD A,0FFH ;THIS WILL BECOME A SPECIAL PUSH BC ; READ COMMAND CALL RDWRT ;SO DO IT. POP BC AND 9DH ;MASK ERRORS RET Z ;; 7 ; EXIT SUCCESSFUL ;;DEC JR Z,RWFAIL ;TOO MANY ERRORS PUSH BC CALL WRITES ;WRITE IT AGAIN POP BC JR Z,RAWS1 ;NOW TRY TO READ IT AGAIN RET ;****************************************************************************** ; FLAG FAILED READ/WRITE OPERATIONS RWFAIL: LD A,2 LD (OPFAIL),A ;SET OPFAIL = 2 LD (RWRTRY),A ;AND BOTH RETRY COUNTS = 1 DEC A LD (FLAG5),A RET ;****************************************************************************** ; MOVE THE HEADS OF THE SELECTED DISC TO THE TRACK STORED IN "REALTRK". ; SAVE THE VALUE OF THE PARAM BLOCK EOR THE DRIVE FOR EASY ACCESS. IF A SEEK ; ERROR OCCURS, DO A RETURN ZERO SEEK AND RETRY UP TO 5 TIMES BEFOR FAILING. SEEK: LD A,(DISK) ;USE THE SELECTED UNIT TO CALL DRPARAM ; GET THE UNIT CHARACTERISTICS XOR A ;INHIBIT MINI MOTOR SHUT-OFF LD (MINIVAL),A LD C,A LD A,(TRACK) ;GET THE TRACK REQUIRED ;BITX 0,01H ;TEST THE TWO-SIDE FLAG JR Z,SEEK1 ;SRLR A ;IF TWO-SIDED, HALF THE TRACK NO JR NC,SEEK1 ; AND SET SIDE 2 ON ODD TRACKS LD C,10H SEEK1: LD (REALTRK),A ;HAVE THE ACTUAL TRACK HERE ;CMPX 04H JR C,SEEK2 ;LOOK AT THE WRITE PRE-COMP TRACK #. ;;SETB 7,C set 7,c SEEK2: ;;;;LDX A,00H ;GET THE SELECT UNIT BITS OR C ; AND MERGE THE OPTIONS LD (UNITSEL),A ;SET THE UNIT PRECOMP VALUE ;;OUT DISCM,A out (DISCM),a ;;LDX A,06H ;GET THE LAST USED TRACK # ;;OUT FTRK,A ; TO RECHARGE THE TRACK REGISTER out (FTRK),a AND A ;;7PM7 ;Ir IT WAS A :Epn, 3Luz7 FIRE OFF ;;VO•d• V111^111..... •—^ I I. VI• .1 .+`^~~.. V •-•••-•—•^.-. • ;;OUT DISCM,A out (DISCM),a ;;LDX A,06H ;GET THE LAST USED TRACK # ;;OUT FTRK,A ; TO RECHARGE THE TRACK REGISTER out (FTRK),a AND A JR NZ,SEKRTRY ;IF IT WAS A ZERO, JUST FIRE OFF CALL DSEL0 ; A FORCE INTERRUPT TO READ STATUS BIT 2,A ;NOW CHECK TRACK ZERO STATUS BIT JR NZ,SEKRTRY ; TO BE SURE WE ARE REALLY THERE. ;LDX A,7 ;ISSUE A RESET DRIVE AT FULL SPEED CALL DOCMND BIT 2,A ;LOOK AT SEEK ERROR AGAIN ;;; JR Z,SEEKERP SEKRTRY: LD B,5 ;SET RETRY LIMIT SEEK3: ;; LD A,(REALTR) ;PUT THE TRACK REQUIRED ;OUT FDATA,A ; OUT TO THE DATA PORT out (FDATA),a LD C,A PUSH BC ;SAVE IT TO XOR A CALL RDWRT ;SET THE UNIT DENSITY PRE-COMP POP BC LD A,1CH ;FORM A SEEK COMMAND ;ORX 07H ; MERGE THE SEEK RATE CALL DOCMND ;NOW DO IT AND 99H ;MASK READY/DONE ;IN A,FTRK ;LOAD THE FOUND TRACK in a,(FTRK) ;STX A,6 ;SAVE IT IN THE PARAM BLOCK JR NZ,SEEK4 ;JUMP ON ERRORS CP C ;SEE IF IT'S WHERE WE SHOULD BE RET Z SEEK4: ;;IN A.ECOM ;IF THE DRIVE IS NOT READY, in a,(FCOM) AND 80H JR NZ,SEEK3 LD A,3 ;RESET, SLOW SEEK. CALL DOCMND DJNZ SEEK3 ;RE-TRY 5 TIMES SEEKERR: LD A,0FFH ;CAN'T GET ON TRACK, SO LD (OPFAIL),A ; FLAG AN ERROR AND A RET ;****************************************************************************** ; THIS CODE PERFORMS READS, WRITE AND READ-AFTER-WRITES. TRANSFER PARAMS HAVE ; BEEN SET, AND HAS SOURCE AND HAS ; THE DESTINATION. eA%, HAS THE MEMORY MODE SO .. ;00H = BANK TO BANK. 03H = CACHE TO CACHE. 10H = BANK TO CACHE. 18H = CACHE TO BANK. M2MXFER: ; OUT MUel,A ;SET MEMORY MODE LD (M2MDST),HL ;SET DESTINATION ; SDED M2MSRC ; AND SOURCE LD HL,M2MDMA ;POINT TO DMA DEVICE PARAMS CALL ZINIT ; AND KICK IT OFF M2MXF1: LD A,0BFH ; OUT ZDMA.A ;TEST DMA DEVICE STATUS out (ZDMA),a ; IN A,ZDMA ; AND LOOP TILE COMPLETE in a,(ZDMA) AND 20H JR NZ,M2MXF1 LD A,88H ;DISABLE DMA DEVICE ; OUT ZDMA,A out (ZDMA),a RET ;****************************************************************************** ; DMA INITIALIZATION VALUES FOR A DMA MEMORY TO MEMORY TRANSFER. M2MDMA: DEFB 16 ;16 COMMANDS TO THE DEFB ZDMA ;DMA CONTROLLER DEFB 83H ;DISABLE DMA DEFB 7DH ;XFER ONLY, ADDR LENGTH FOLLOW M2MDST: DEFW 00 ;PORT "A" ADDRESS DEFW SYSIZE ;BLOCK LENGTH - 1 DEFB 14H ;INCREMENT "A" AS MEMORY DEFB 10H ; "B" AS MEMORY DEFB 0CDH ;"B" ADDR FOLLOWS, I'RUPT EACH BYTE M2MSRC: DEFW 00 ;PORT "B" ADDRESS DEFB 82H ;RDY IS ACTIVE LOW DEFB 0CFH ;RESET AND LOAD REGISTERS DEFB 8BH ;RESET STATUS DEFB 0B3H ;DISABLE DMA XFER DEFB 87H ;ENABLE DMA NOW DEFB 0 ;****************************************************************************** ;INITIALIZE A 64 BYTE BLOCK TO ALL FF. USED TO FLAG USED BLOCKS IN ; THE CACHE BUFEER BEGINNING AT OCOO0H IN THE SECOND BANK. FILLMAP: LD HL,BLOKMAP LD E,64 FILM1: LD (HL),0FFH INC HL ; 1,72NZ FILM1 ;FILM1: LD (HL),0FFH INC HL ; UNZ FILMI ; PET ret ;****************************************************************************** CACHADR: ; LD ;CACHA2: LD LD LD ADD ; LD LD ; SRLR RARR LD ; ADD LD CP RET ;CACHA3: LD ; JR ; A,.(SEKSEC) HL,BLOKMAP-1 C,A ; B4O ; HL , BC ; DE,HL ; F,A C,0 ; r ; HL,CACH-128 HL,BC ; A, (DE) ; OFFH ; A,(PRVHLD) CACHA2 ;USE THE REQUIRED LOGICAL SECTOR ; AS AN OFFSET INTO THE TRACK MAP ;NOW MULTIPLY SECTOR BY 128 TO ; FORM AN OFFSET INTO THE CACHE ;FORM THE CACHE ADDRESS POINTER ;SET THE ZERO FLAG FRON THE MAP ; AND EXIT ;GET THE REGJUIRED PHYSICAL SECTOR ;****************************************************************************** ;LISE THE UNIT I.D. IN TO SET THE s'N' INDEX POINTER TO THE DRIVE CHAPACTERISTICS TAFLE. COPY THIS TAFLE TO A BUFFER AREA. DRPARAM: ;LD ;INC ;ADJUST THE UNIT NUMBER TO 1..8 ;LD ; AND LOAD THE TAFLE ENTRY LENGTH ;PRPRMI: ADD DEC JPNZ ;PRPRM2: PUSH ;POPIX LD ;LDIR RET ;****************************************************************************** ; WARM BOOT CODE REREADS THE CCP AND BDOS FROM THE SECOND PAGE OF RAM, THEN ; ENTERS THE CCP WITH THE CURRENT DISC NUMBER IN REGISTER + THIS MEANS THAT ; WARM—START DISCS NEED NEITHER HAVE A SYSTEM ON THEM, NOR BE DOUBLE DENSITY. WBOOT: ;HL,DR0-8 A ;BC,8 HL,BC A ;PRPRM1 ;HL ;DE,PRMSAVE ;FORM THE OFFSET FROM THE BASE ;AND LOAD IT INTO THE INDEX REGISTER ;BLOCK MOVE THE ENTRY INTO ; A FIXED SAVE AREA ;LD LD LD LD LD LD CALL ;LD LD ;SP,DEFBUF HL,SYSIZE ;(M2MDST+2),HL ;PERVERT THE BLOCK LENGTH FOR A ;HL,WBHOLD ; MEMORY TO MEMORY BLOCK MOVE. ;DE, CCP ;A,18H ;A PAGE 2 TO PAGE 1 TRANSFER ;M2MXFER ;HL,127 ;RESTORE CP/M'S LOGICAL BLOCK SIZE ;(M2MDST+2),HL ;HL,CCP+3 ; CCP ENTRY FOR NO AUTO FUNCTION ; ;****************************************************************************** ; THIS CODE IS USED BY BOTH COLD AND WARM BOOTS TO RESET LOW MEMORY VECTORS ; AND ENTER THE CCP. NOTE THAT CURRENT DRIVE/USER IS NOT CHANGED. FINALLY, ;EtolRY IE MADE ,Ir-/-4 A r ADDPg '!+ ;) in1J %,UMIC. 1Z UZGL Ml MUln LULL MINIL WMMVI MUU)Z IU MMZC) LUW )'ICVIUM) VGLIUMZ ; AND ENTER THE CCP. NOTE THAT CURRENT DRIVE/USER IS NOT CHANGED. FINALLY, ;ENTRY IS MADE TO CP/'M AT ADDRESS . SETLOW: LD A,0C3H ; JMP ;STORE A "JMP" INSTRUCTION ; TO "WARMBOOT" AT 0000. LD (0),A ;AND A JUMP TO THE "BDOS" ; AT 0005. LD DE,BIOS+3 ;LOAD UP THE CURRENT DISC/USER ; AND ENTER THE CCP ;SDED 1 LD (BDOSVEC),A LD DE,BDOS+6 ;SDED BDOSVEC+1 ; MACRO LD A,(CDISK) LD C,A JP (HL) ;****************************************************************************** ;THIS ROUTINE INITIALISES ZILOG DEVICES FROM A TABLE ENDING WITH ZERO. ; THE FIRST VALUE IS THE NUMBER OF PARAMS, THE SECOND THE PORT #. ZINIT: LD A,(HL) OR A ;EXIT ON A ZERO RET LD B,A ;LOAD THE COUNT INC HL lD C,(HL) ;AND THE PORT NUMBER INC HL ; THEN POINT TO THE DATA ZSET: OTIR ;OUTIR JR ZINIT ;****************************************************************************** ; INTERRUPT SERVICE FROM CHANNEL 3 OF THE ZILOG CTC. IRTC: ;SSPD SPHOLD3 MACRO LD SP,SPHOLD1 ;USER STACK NOT USED. PUSH AF PUSH HL LD HL,RTCVAL ;INCREMENT THE RTC TIMER VALUE INC (HL) LD A,(HL) ;GET IT AND SAVE FOR LATER PUSH AF CP 61 ;SEE IF ONE SECOND HAS PASSED JR NZ,IRTC1 LD (HL),0 ;RESET THE RTC TICKER LD A,60 ;FOR SECONDS/MINUTS COMPARISON LD HL,SECS ;LOW MEMORY LOCATION OF REAL TIME CLOCK INC (HL) ;UP THE SECONDS COUNT CP (HL) ; AND TEST FOR A MINUTE PASSED JR NZ,IRTC1 LD (HL),0 ;RESET AT 60 (NATURALLY) INC HL ;NOW Dis MINUTES INC (HL) CP (HL) ;AN HOUR PASSED ? JR NZ,IRTC1 LD (HL),0 ;RESET THE MINUTES AND UP THE HOURS INC HL INC (HL) LD A,(HL) ;A DAY GONE CP 24 ;WE USE A 24 HOUR CLOCK HERE. JR NZ,IRTC1 LD (HL),0 ;A NEW DAY HAS DAWNED LD HL,(DATE) INC HL ;ADD ONE TO THE DATE VALUE LD (DATE),HL IRTC1: ;; AE) ;CHECK THE REST EVERY 8TH TICK ;7PN- TETc-'T LD HL,(DATE) INC HL ;ADD ONE TO THE DATE VALUE LD (DATE),HL ;A‹ü 7/ ;CHECK THE REST EVERY 8TH TICK JR NZ,IDISXT ;/ ;fp5s / LD HL,MINIVAL ;GET THE MINI-DISC MOTOR DELAY LD A,(HL) OR A ;IF IT HAS TIMED OUT, SKIP ON JR Z,IDIS1 DEC (HL) ;IF NOT, COUNT IT DOWN TO TURN OFF JR NZ,IDIS1 ; THE 5" MOTORS. LD A,(UNITSEL) OR 20H ;KEEP THE CURRENT UNIT SELECTED, ;OUT DISCM,A ; BUT MOTORS OFF. out (DISCM),a IDIS1: ;;LD HL,PNTR2 LD A,(HL) ;ANOTHER PROTECTION MECHINISM. OR A ;THIS COUNTER IS SET TO 20 JR Z,IDIS2 ; AT THE END OF EACH BLOCK READ. DEC (HL) JR NZ,IDIS2 XOR A LD (CACHFUL),A IDIS2: LD HL,FLAG1 ;SEE IF DISC NEEDS WRITING LD A,(HL) ;THIS VALUE IS ZERO WHEN NO WRITES OR A ; ARE PENDING. JR Z,IDISXT ;EACH WRITE RESETS IT TO 5, SO DEC (HL) ; WE CAN BE SURE THAT NO WRITES ARE JR NZ,IDISXT ; IN PROGRESS WHEN IT REACHES ZERO. POP HL POP AF LD SP,SPHOLD2 ;SET A DEEPER LEVEL OF STACK PUSH AF PUSH HL LD HL,(SPHOLD3) ;WITH THE OLD PC AT THE TOP PUSH HL CALL IDISEN ;THIS MAKES THE ROUTINE RE-ENTRANT PUSH DE PUSH BC CALL CHKMAP ;UPDATE ANY NEEDED SECTORS IDIS4: POP BC POP DE DI ;SAFEGUARD THE STACK POINTER RELOAD POP HL LD (SPHOLD3),HL ;REPLACE THE SP FOR THE EXIT ROUTINE IDISXT: POP HL POP AF ;LSPD SPHOLD3 ;RESTORE REGS. AND EXIT ; MACRO IDISEN: EI RETI ;****************************************************************************** SKEW TABLES FOR USE IN 8" SYSTEMS. IF MAXI ; SKEW TABLE FOR SINGLE DENSITY IBM CAMPATABLE CP/M DISCS. X8TI28: DEFB 0,24,13,6 ;SKEW TABLE FOR DOUBLE DENSITY LIFEBOAT/MORROW FORMAT DISCS. X8T296: DEFB 1,26,26,9 ; SKEW TABLE FOR DOUBLE DENSITY CCS 1024 BYTE/SECTOR DISCS. ;>!.8T1024: ;bKLW MUM IMUISLL MtNbIlY LLS 1024; bYlt/bLLIUM 1.11bLb. ; X8T1024: DEFB 2,8,8,3 ENDIF ;****************************************************************************** ; SKEW TABLES FOR USE IN 5" SYSTEMS IF MINI ;MINIS KW ENDIF ;1****************************************************************************** ; DISC PARAMETER ENTRIES FOR USE BY THE SYSTEM. CONDITIONAL ASSEMBLY WILL RESULT IN A FOUR DRIVE SYSTEM WHICH, IF MIXED, MAPS AS :- ; DRIVES ;LOGICAL PHYSICAL SIZE ;A: A: 8 ;B: B: 8 ;C: A: 5 ;D: B: 5 ;M: BANK 2 OF MEMORY - 48K DPEM: DEFW 0 DEFW 0 DEFW 0 DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW MEMDSK ;POINTER TO DISC PARAM BLOCK DEFW CSVM ;CHECKSUM VECTOR ADDRESS DEFW ALVM ;ALLOCATION VECTOR ADDRESS ;ACTUAL DISC DRIVE PARAMETER HEADERS DPE0: ;MAXI DEFW 0 DEFW 0 DEFW 0 DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV0 ;CHECKSUM VECTOR ADDRESS DEFW ALV0 ;ALLOCATION VECTOR ADDRESS DPE1: DEFW 0 DEFW 0 DEFW 0 DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV1 ;CHECKSUM VECTOR ADDRESS DEFW 00; ALV1 ;ALLOCATION VECTOR ADDRESS ;1 ;ENDIF IF MAXI AND NOT BOTH DPE2: DEFW 0 DEFW 0 DEFW 0 DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV2 ;CHECKSUM VECTOR ADDRESS ;TIRgU u7 flinr•-77nm 1Arrrn ADDmcc:c DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV2 ;CHECKSUM VECTOR ADDRESS DEFW ALV2 ;ALLOCATION VECTOR ADDRESS DPE3: DEFW 0 DEFW 0 DEFW 0 DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV3 ;CHECKSUM VECTOR ADDRESS DEFW ALV3 ;ALLOCATION VECTOR ADDRESS ENDIF IF MINI DPE4: DEFW 0 DEFW 0 ;;;; ;DEr 0 ;DEr0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV2 ;CHECKSUM VECTOR ADDRESS DEFW ALV2 ;ALLOCATION VECTOR ADDRESS DPE5: DEFW 0 DEFW 0 ;nEulJ DEFW 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER ;;7.)Fw ;POINTER TO DISC PARAM BLOCK ;;£JEFW ; CHECKSUM VECTOR ADDRESS DEFW ALV3 ;ALLOCATION VECTOR ADDRESS ENDIF IF MINI AND NOT BOTH ;;DPEC ;p--7Fw ;77 ;;0 ;7T 0 DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;POINTER TO DISC PARAM BLOCK DEFW CSV0 ;CHECKSUM VECTOR ADDRESS DEFW ALV0 ;ALLOCATION VECTOR ADDRESS DPE7: DEFW 0 DEFW 0 DEFW 0 ;;DEF DEFW DIRBUF ;COMMON DIRECTORY BUFFER DEFW 0 ;;; ;POINTER TO DISC PARAM BLOCK DEFW 0 ;;;;;;CHECKSUM VECTOR ADDRESS DEFW ALV0 ;ALLOCATION VECTOR ADDRESS ENDIF ;****************************************************************************** ; ;THESE TABLES MAP THE VALID SECTOR SIZES AND DENSITIES TO DISC PARAM BLOCKS. ; EACH TABLE ENTRY BEGINS WITH A VALUE E9UAL TO THE NUMBER OF 128 BYTE BLOCKS ; IN THE SECTOR AND IS 5 BYTES LONG. THE TABLES ARE REPEATED 4 TIMES FOR EACH ; DISC SECTOR SIZE. UNSUPPORTED FORMATS HAVE ZERO SECTORS PER TRACK. ; THE ENTRIES ARE SEOUENCED: ;I =1DF 1D 1 AIDE, 2D ; 2 SIDE 1D EIDE 2D ; ;1 ="IDE, I ;i 2D ; 2 SIDE 1D ; 2 EIDE 2D ; AND HAVE THE FORM: ; POINTER ; PARAM BLOCK POINTER ; SECTORS/TRACK ; SKEW TABLE ; EM8TBL: IF MAXI ; DEFB 1 ;128 BYTE SECTORS ;;DEFB DEFW 26 X8T128,SDSS0 ; A.A. , SINGLE SIDED , 1D DEFB 0 ; A.A 5 A.A , 2D DEFW 0,0 ;; DEFB DEFW 0 ; A.A. , DOUBLE SIDED , 1D ; 0,0 DEFB 0 ° A.A n A.A. . 2D DEFW 0,0 ; ;;DEFB 2 z. ;256 BYTE SECTORS ;;DEFB DEFW 0 ; A.A. , SINGLE SIDED , 1D ; 0,0 DEFB 52 ; A.A 4 A.A , 2D DEFW X8T256,DDSS1 DEFB DEFW 0 ; A.A. , DOUBLE SIDED , 1D ; 0,0 DEFB 52 ; A.A 4 A.A. . 2D DEFW X8T256,DDDS1 ; DEFB 4 ;512 BYTE SECTORS ;;DEFB DEFW 0 ; A.A. , SINGLE SIDED , 1D ; 0,0 DEFB 60 ; A.A n A.A . 2D DEFW 0,DDSS2 ;;DEFB DEFW 0 ; A.A. , DOUBLE SIDED , 1D ; 0,0 DEFB 60 ; A.A 4 A.A. , 2D DEFW 0,DDDS2 ; DEFB 8 ;1024 BYTE SECTORS ;;DEFB DEFW 0 ; A.A , SINGLE SIDED , 1D ; 0,0 ;;DEFB DEFW 64 ; A.A 5 A.A , 2D ; X8T1024,DDSS3 ;;DEFB DEFW 0 ; A.A. , DOUBLE SIDED , 1D ; 0,0 DEFB 64 ; A.A 4 A.A. , 2D DEFW X8T1024,DDDS3 ; ENDIF ;****************************************************************************** SIMILAR TABLE FOR USE WITH 5" DRIVES. IF NOT MINI HOOK5: ;; # EQU 0 ELSE ;;HOOK5: ;; EQU 0 ;;;MINIT: 0;BL ENDIF ;****************************************************************************** ; DISC PARAMETER BLOCKS DESCRIBING DISC CHARACTERISTICS OF EACH FORMAT. IF MAXI ; DISC PARAMETER BLOCKS DESCRIBING DISC CHARACTERISTICS OF EACH FORMAT. ;;:)-- TAFLE FOR 1024 IF MAXI DEFW 64 DEFB 4,15,0 DEFW 299 , DEFW 127 DEFB 000H,0 DEFW 32 DEFW 2 .r. ; TABLE FOR 1024 DEFW 64 DEFB 6,63,7 DEFW 149 DEFW 127 DEFB 80H,0 DEFW 32 DEFW 4 ; TAFLE FOR 512 ;BYTE/SEC ONE SIDED DOUBLE DENSITY , ;SECTORS PER TRACK ;LOGICAL BLOCK SIZE IS 4K BYTES. ;NUMBER OF BLOCKS (GROUPS) ON DISC ;- ;128 DIRECTORY ENTRIES ;DIRECTORY BLOCK MASK ;128 CHECKED DIRECTORY ENTRIES ;2 RESERVED TRACKS ;BYTE/SEC TWO SIDED DOUBLE DENSITY (C(7`-; ;SECTORS PER TRACK ;LOGICAL BLOCK SIZE IS 8K BYTES. ;NUMBER OF BLOCKS (GROUPS) ON DISC ;128 DIRECTORY ENTRIES ;DIRECTORY BLOCK MASK ;128 CHECKED DIRECTORY ENTRIES ;4 RESERVED TRACKS ;BYTE/SEC ONE SIDED DOUBLE DENSITY 7 . ;SECTORS PER TRACK ;LOGICAL BLOCK SIZE IS 4K BYTES. ;NUMBER OF BLOCKS (GROUPS) ON DISC ;128 DIRECTORY ENTRIES ;DIRECTORY BLOCK MASK ;128 CHECKED DIRECTORY ENTRIES ;2 RESERVED TRACKS DDSS2: ; .-(373 DEFW 60 DEFB 5,31,1 DEFW 143 DEFW 127 DEFB 20H,0 DEFW 32 DEFW 2 ; ;,. , i.,, ; THIS TÄBLE FOR 512 BYTE/SEC DDD92: ; '--";“ ; THIS ;DDS53 ; THIS ;DDDS2;) ; ;THIS ;TWO SIDED DOUBLE DENSITY ( ,,,-, ''') ',.• --- ^~l /1 i, iL J ;\ ; THIS DDSS1: DEFW 60 DEFB 5,31,1 DEFW 284 DEFW 177 DEFB 80H,0 ;; '2: DEFW 2 ; TABLE FOR 256 DEFW 52 DEFB 4,15,0 DEFW 242 DEFW 127 DEFB 000H,0 DEFW 32 DEFW 2 ;SECTORS PER TRACK ;LOGICAL BLOCK SIZE IS 4K BYTES. ;NUMBER OF BLOCKS (GROUPS) ON DISC ;129 DIRECTORY ENTRIES ;DIRECTORY BLOCK MASK ;CHECKED DIRECTORY ENTRIES ;2 RESERVED TRACKS DEFW 32 ;128 ;SECTORS PER TRACK ;LOGICAL BLOCK SIZE IS 2K BYTES. ;NUMBER OF BLOCKS (GROUPS) ON DISC ;128 DIRECTORY ENTRIES ;DIRECTORY BLOCK MASK ;128' CHECKED DIRECTORY ENTRIES ;2 RESERVED TRACKS ;BYTE/SEC ONE SIDED DOUBLE DENSITY ("MORROW" FORMAT) ;{- ; THIS TAFLE FOR 256 BYTE/SEC ;DDD E 1 : DEFW 52 DEFB 4,19,0 DEFW 486 ;NUMEER DEFW 255 DEFB 0F0H,0 ; rIpr-,) &1,,4 _ ;PvEW 4 ;;TWO SIDED DOUBLE DENSITY (''MORROW" FORMAT) ;SECTORS PER TRACK ;LOGICAL BLOCK SIZE IS 2K BYTES. OF BLOCKS (GROUPS) ON DISC ;256 DIRECTORY ENTRIES ;DIRECTORY BLOCK MASK ;256 CHECKED DIRECTORY ENTRIES ;4- RESERVED TRACKS (2 ACTHAO UI') ;;DEFW ;;DEFB ;;DEFW DEFW —255 0F0H,0 .c94 ;256 DIRECTORY ENTRIES 4 ;DIRECTORY BLOCK MASK ;256 CHECKED DIRECTORY ENTRIES ;4 RESERVED TRACKS (2 ACTUALLY) ;;5 THIS': TAFLE FOR 128 BYTE/SEC SINGLE SIDED SINGLE DENSITY ("IBM" FORMAT") ; SDSSO: DEFW 26 ;SECTORS PER TRACK DEFB 3,7,0 ;LOGICAL BLOCK SIZE IS 1K BYTES. DEFW 242 ;NUMBER OF BLOCKS (GROUPS) ON DISC DEFW 63 ;64 DIRECTORY ENTRIES DEFB 000H,0 ;DIRECTORY BLOCK MASK DEFW 16 ;64 CHECKED DIRECTORY ENTRIES DEFW 2 ;2 RESERVED TRACKS ENDIF ;*******X********************************************************************** ; THIS TAFLE FOR THE PSUEDO—DISC DRIVE "M:" MEMDSK: DEFW 2 ;SECTORS PER TRACK DEFB 3,7,0 ;LOGICAL BLOCK SIZE IS 1K BYTES. DEFW 47 ;NUMBER OF BLOCKS (GROUPS) ON DISC DEFW 31 ;31 DIRECTORY ENTRIES DEFB 080H,0 ;DIRECTORY BLOCK MASK DEFW 0 ;NO CHECKED DIRECTORY ENTRIES DEFW 0 ;NO RESERVED TRACKS ;*******************************************************.********************** ; MINI DISC PARAMETER BLOCKS. IF MINI ;MINID ;MACRO WILL SUPPLY MINI DISC PARAMETER BLOCKS. ENDIF ; ;****************************************************************************** ; THE FOLLOWING 8—BYTE TABLES ARE USED TO SET THE INDIVIDUAL DRIVE FORMATS. ; THE BYTE USAGE IS : ;BYTE 0 UNIT SELECT BITS, DRIVE SIZE (5/84). ;1 -- 00 = SINGLE SIDED, FF = DOUBLE SIDED. ;2 -- NUMBER OF 128 BYTE BLOCKS PER TRACK. ; SECTOP SIZE / 128. ;4 -- TRACK AT WHICH TO TURN ON WRITE PRE—COMP (FOR "FMAT") ;5 -- DENSITY/PRE—COMPENSATION ;6 -- LAST ACCESSED TRACK STORAGE ;7 -- STEP RATE ; WHEN BOTH 5" AND 8" DRIVES ARE CONFIGURED IN, DRIVES "A:" AND "B:" WILL ; BE 8", WHILE DRIVES "C:" AND "D:" WILL BE 5". DR0: IF MAXI ;8" CONFIG TABLES DEFB 0CH,0FFH,60,4,64,10H,0,MAXIRATE DEFB 0DH,0FFH;60,4;64;10H,0,MAXIRATE ENDIF IF MAXI AND NOT BOTH DEFB 0EH,0FFH,60,4,64,10H,0,MAXIRATE DEFB 0FH,0FFH,60;4,64,10H,0,MAXIRATE ENDIF IF MINI ;5" CONFIG TABLES ;MINIA B ENDIF ;;9 IF -MINI ;5" CONFIG TABLES ;MINIA B ENDIF IF MINI AND NOT BOTH ;MINIC D ENDIF ;****************************************************************************** ; HERE ARE SOME PRE-INITIALISED DATA VARIABLE STORAGE LOCATIONS. QHEAD: DEFW FIFOBUF OTAIL: DEFW FIFOBUF PNTR9: DEFB 00 RTCVAL: DEFB 0 FLAG1: DEFB 00 PNTP2: DEFB 00 MINIVAL: DEFB 100 ;MINI-DISC MOTOR OFF DELAY COUNT ;*****************************************************************************; ;* *; ;* ALL RAM FROM HERE ON IS UNINITIALISED. THE "BOOT" CODE IS ONLY NEEDED AT *; ;* COLD BOOT TIME AND SO IS LATER OVERWRITTEN AS REQUIRED FOR COMPACTNESS. *; ;* *; ;*****************************************************************************; ; THE DISC BOOTSTRAP ARRIVES HERE WHEN ALL CP/M IS LOADED. WE NOW SET THE ;= INTERRUPT MODE, PRINT A SIGN-ON MESSAGE, INITIALIZE LOW MEMORY AND ENTER CCP. BOOT: DI ;NO INTERRUPTS YET IM 2 ;SET INTERRUPT MODE 2 LD A,BIOS SHR 8 ;STAI ;SET INTERRUPT BASE REGISTER ;;LD HL,INITBL ;POINTER TO INITAL VALUES CALL ZINIT ; SEND TO PORTS ;IN A,DARTAD ;SUCK UP ANY JUNK in a,(DARTAD) ;IN A,DARTAD (DART IS TRIPLE BUFFERED) in a,(DARTAD) ;IN A,DARTAD in a,(DARTAD) CALL RESET ;SET ALL DRIVES TO TRACK ZERO, THEN LD HL,CCP ;SAVE THE CCP+BDOS IN THE SECOND BANK LD DE,WBHOLD ; FOR LATER WARM BOOT OPERATIONS LD A,10H ;SET TO MOVE FROM PAGE 1 TO PAGE 2. CALL M2MXFER LD HL,122 ;RESTORE THE CP/M BLOCK LENGTH LD (M2MDST+2),HL EI ; ALLOW RTC AND CONSOLE INTERRUPTS CALL PRINTO ;PRINT THE SIGN-ON. DEFB EOF ; CLEAR SCREEN DEFB ACR,ALF ; ONE LINE DOWN DEFM 'ARCHIVE Computer Services' DEFB ACR,ALF DEFB (SIZE / 10) ; '0'; CP/M SIZE (TENS) DEFB (SIZE MOD 10) + '0'; CP/M SIZE (UNITS) DEFM 'K CP/M Ver 2.2 - Mod ' DEFW REVLEV DEFB ACR,ALF DEFM 'Drives Supported ' IF NOT BOTH IF MAXI DEFM '3" Only,' IF NOT BOTH IF MAXI DEFM '8" Only,' ENDIF IF MINI DEFM '5" Only.' ENDIF ENDIF IF BOTH DEFB '8' ; 5 ENDIF DEFB ACR,ALF,ALF DEFM "** With "Enhanced CCP" **1" DEFB ACR,ALF,ALF,0 XOR A LD (CDISK),A ;FORCE TO DEFAULT DRIVE LD (SECS),A ;ZERO THE SECONDS COUNT, LD (MINS),A ; THE MINUTES, LD (HRS),A ; AND THE HOURS. LD HL,DAYS ;STORE THE DAYS SINCE JAN-Ist-1982 LD (DATE),HL LD A,(IOVALU) ;SETUP INITIAL I/O BYTE LD (I0BYTE),A LD A,5 ;ADDRESS DART CH. "B" REGISTER 5 OUT DARTBC,A ; AND TURN ON DTR AND CTS LD A,0EAH OUT DARTBC,A LD HL,CCP ;SET FOR A CCP ENTRY WITH AUTO-COMMAND JP SETLOW ;NOW DO COMMON BOOT CODE. ;****************************************************************************** ; THE FOLLOWING TABLE INITIALISES THE CTC, DART, AND PIO. ; BAUD RATES FOR CTC CHANNELS 0, 1 AND 2 ARE: ; 300 ,. 80H 4900 8 ;9 530 .. 40H 9600 .. 4 ;1200 .. 20H 19200 .. 2 ;2400 ,. 10H 38400 .. 1 ;VECTORED INTERRUPTS ARE SET FOR CONSOLE INPUT AND RTC (CTC 2/3) ONLY. INITBL: ;EB2C DEFB 2 DEFB CTC0 ;CTC 0 DEFB 45H ;COUNTER, 16X BPSA: DEFB 2;19200 BPS DEFB 9 ;9 VALUES IN SET FOLLOW DEFB DARTAC ;DART CHANNEL A DEFB 18H ;CHANNEL RESET DEFB 14H ;RESET, SELECT REG 4 MODEA: DEFB 84H ;16X CLOCK, 1 STOP BIT, NO PARITY DEFB 13H ;RESET, SELECT REG 3 DEFB 0CH ;RX ENABLE, 8 BITS DEFB 15H ;RESET, SELECT REG 5 DEFB 0EAH ;TX ENABLE, 8 BITS, DTR AND RTS ON. DEFB 1 ;SELECT REG 1 DEFB 18H ;INTERUPT ON ALL RX CHARS FROM CH. A ;2 DEFB CTC1 ;CTC 1 DEFB 45H ;COUNTER, 16X BPSB: DEFB 80H ;300 BPS DEFB 11 ;11 VALUES IN SET DEFB DARTBC ;DART CHANNEL B DEFB 18H ;CHANNEL RESET DEFB 12H ;RESET, SELECT REG 2 DEFB (VIR1 ANO 0FFH) ;SET INTERRUPT VECTOR DEFB 14H ;RESET, SELECT REG 4 MODEB: DEFB 84H CLOCK, STOP BITS AND PARITY DEFB 134 ;RESET, SELECT REG 3 DEFB (VIR1 AND 0FFH) ;SET INTERRUPT VECTOR DEFB 14H ;RESET, SELECT REG 4 ;MODEB: DEFB 84H ; CLOCK, STOP BITS AND PARITY ; DEFB 13H ;RESET, SELECT REG 3 BITSB: DEFB 0E1H ;RX ENABLE, 8 DATA BITS, CTS HANDSHAKE. DEFB 15H ;RESET, SELECT REG 5 DEFB OEAH ;TX ENABLE, 8 BITS, DTR AND RTS ON. DEFB 1 ; REG 1 DEFB 0 ;NO INTERRUPTS. DEFB 2 DEFB PIOAC ;PIO CHANNEL A DEFB OFH ;CHANNEL A IS OUTPUT DEFB 3 ;NO INTERRUPTS DEFB 4 DEFB PIOBC ;PIO CHANNEL B DEFB 0CFH ;CHANNEL B IS CONTROL DEFB 0FFH ;ALL BITS ARE INPUTS DEFB 37H ;NO INTERRUPTS DEFB 1 DEFB 1 DEFB CTC0 ;CTC 0 DEFB (VIR2 AND 0FFH) ;INTERRUPT VECTOR DEFB 2 DEFB CTC2 ;CTC 2 DEFB 45H ;COUNTER, 16X DEFB 1 ; 38400 BPS DEFB 2 DEFB CTC3 ;CTC 3 DEFB 0A5H ;TIMR DEFB 0 ;COUNTDOWN VALUE DEFB 0 ;1****************************************************************************** ; THE PEMAINING ARE IS UNINITIALISED DATA, BUT MUST OF COURSE BE AVAILABLE. ORG BOOT DIRBUF: ; DEFS 128 ;COMMON DIRECTORY BUFFER AREA ;ALLOCATION AND CHECK VECTORS FOR 8" AND 5" DRIVES ALV0: ; "ALV" STORAGE IS ALLOCATED AS: DEFS 38 ABS(TOTAL-BLOCKS/S) + 1 BYTES ALV1: ;"CSV" STORAGE IS ALLOCATED AS: DEFS 38 CHECKED DIRECTORY ENTRIES/4 BYTES. ALV2: DEFS 38 ;VALUES ARE SET TO EQUAL THE MAXIMUM REQUIREMENT ALV3: ;FOR 8" DRIVES. DEFS 38 ALVM: DEFS 07 IF MAXI AND NOT MINI;MUST ALLOW 64 BYTES FOR "MORROW" TWO SIDE CSV0: ;DISCS WITH 256 DIRECTORY ENTRIES. SINCE DEFS 64 ;WE ARE GETTING SHORT ON ROOM, THE FOLLOWING CSV1: ;CONDITIONALS PREVENT US HAVING MORE THAN DEFS 64 ;TWO OF THIS TYPE IF THE MINI-DRIVE CODE IS CSV2: ;INCLUDED. DEFS 64 ;clz;v3; ;CSV0: DEFS 44 ;CSV1: ENDIF IF MINI AND NOT MAXI DEFS 32 DEFS 32 ;CSVO: CSV1: ;;r53V7: ;CSV3:_ ;CSV0: ;CSV1: ;CSV2: ;CSV3: DEFS 32 DEFS DEFS 32 DEFS 32 ENDIF IF BOTH DEFS 64 DEFS 64 DEFS 32 DEFS 32 ENDIF CSVM: DEFS 0 ;BECAUSE DRIVE IS NON-EXCHANGABLE ;****************************************************************************** ;• PRVHLD: DEFS 1 NXTSEC: DEFS 1 REALTRK: DEFS 2 MSRCE: DEFS 2 MDEST: DEFS 2 SEKDMA: DEFS 2 SEKDSK: DEFS 1 SEKTRK: DEFS 1 SEKSEC: DEFS 1 DISK: DEFS 1 TRACK: DEFS 1 MAPMT: DEFS 1 CACHFUL: DEFS 1 OPFAIL: DEFS 1 RWRTRY: DEFS 1 FLAG5: DEFS 1 BLKCNT: DEFS 1 UNITSEL: DEFS 1 SPHOLD3: DEFS 2 DEFS 6 SPHOLD1: DEFS 2 DEFS 16 ; "•••• ;FEGISAVE: ; DEFS 6 ;SPHOLD1: ; DEFS 2 ; DEFS 16 REGSAVE: DEFS 48 SPHOLD2: DEFS 2 DEFS 49 FIFOBUF: DEFS 63 CBUFTOP: DEFS 1 PPMSAVE: ;AREA TO HOLD DRIVE PARAMS DEFS 2 ; FOR EASY (NON-INDEXED) ACCESS SECMAv: DEFS 1 ;BLOCKS/TRACK SECSIZE: DEFS 2 ;BLOCKS/SECTOR PRECOMP: DEFS 1 ;TEMPSTORE ;D2 2 ;****************************************************************************** THIS 6 BYTE AREA HOLDS SECTOR HEADER INFORMATION. IDSAVE: DEFS 1 ;TRACK NUMBER IDSIDE: DEFS 1 ;SIDE NUMBER IDSEC: DEFS 1 ;SECTOR NUMBER IDSIZE: DEFS 1 ;SECTOR SIZE (0..3) DEFS 2 ;CRC VALUE ;****************************************************************************** ; THIS AREA IS USED TO FLAG BLOCKS OF THE TRACK BUFFER WHICH HAVE BEEN CHANGED ; (WRITTEN TO). EACH BYTE REPRESENTS A 128 BYTE BLOCK. WHEN A SECTOR IS READ, ; THE CORRESPONDING BYTES ARE ZEROED. ANY BLOCK WHICH IS SUBSEQUENTLY WRITTEN ; TO IS SET TO "FF". THE MAP IS USED TO UPDATE THE DISC WHEN THE HEADS MOVE. ;9 BLOKMAP: DEFS 64 ;FLAGS FOR A POSSIBLE 8K TRACK. ;****************************************************************************** ;;END