; Wavemate Bullet ; BETA-VERSION ; ; Bullet_Cache_BIOS_CBIOS.pdf ; ; ASSEMBLER-CODE FOR ASIDE ASSEMBLER ; HR = ROLF HARRMANN ; 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. ;************************************************************************** ; 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 SERVICES' ;************************************************************************** ; 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) = DC00 BDOS: EQU CCP+0800H ; SYSTEM LOAD ADDRESS (2K FOR CCP) = E400 BIOS: EQU BDOS+0E00H ; BIOS LOAD ADDRESS (3.75K FOR BDOS) = F200 SYSIZE: EQU BIOS-CCP ;************************************************************************** ; GENERAL SYSTEM EQUATES AND EXTERNAL ADDRESSES. CACH: EQU 0C000H ; LOCATION OF TRACK CACHE IN 2ND BANK WBHOLD: EQU CACH+ (8*1024) ; CCP+BDOS IN BANK 2 (ALLOW 8K FOR TRACK BUFFER) DEFBUF: EQU 128 ; SECS: EQU 64 ; R.T.C SECONDS MINS: EQU SECS+1 ; R.T.C MINUTES HRS: EQU MINS+1 ; R.T.C HOURS DATE: EQU HRS+1 ; DAYS SINCE 1ST JAN 1982 BDOSVEC: EQU 05 IOBYTE: EQU 03 CDISK: EQU 04 ESC: EQU 27 EOF: EQU 26 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 ; DART 'A' CONTROL DARTBD: EQU 2 ; DART 'B' DATA DARTBC: EQU 3 ; DART 'B' CONTROL PIOAD: EQU 4 ; PIO 'A' DATA PIOBD: EQU 5 ; PIO 'B' DATA PIOAC: EQU 6 ; PIO 'A' CONTROL PIOBC: EQU 7 ; PIO 'B' CONTROL CTC0: EQU 8 ; COUNTER TIMER 0 CTC1: EQU 9 ; COUNTER TIMER 1 CTC2: EQU 0AH ; COUNTER TIMER 2 CTC3: EQU 0BH ; COUNTER TIMER 3 FCOM: EQU 10H ; FLOPPY DISC COMMAND/STATUS FTRK: EQU 11H ; FLOPPY DISC TRACK REGISTER FSEC: EQU 12H ; FLOPPY DISC SECTOR REGISTER FDATA: EQU 13H ; FLOPPY DISC 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 ; ;************************************************************************** ; 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 ;************************************************************************** ; 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 10000001B ; CON:=CRT: LST:=LPT: ;************************************************************************** ; 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 ; ADDRESS OF BAUD RATE "B" DEFW HOOK5 ; ADDRESS OF 5" TABLE (ZERO IF ABSENT). DEFW DR0 ; ADDRESS OF DISC DRIVE CHARACTERISTICS DEFW MINIVAL ; ADDRESS OF MOTOR OFF TIMEOUT COUNT ; ;************************************************************************** ; ; 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 ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; DEFW IDLE ; VIR2: DEFW IDLE ; CTC CHANNEL 0 DEFW IDLE ; CTC CHANNEL 1 DEFW IDLE ; CTC CHANNEL 2 DEFW IRTC ; CTC CHANNEL 3 DEFW IDLE ; DO NOTHING DEFW IDLE ; DO NOTHING ;; DEFW IDLE ; DO NOTHING ;; DEFW IDLE ; DO NOTHING ;************************************************************************** ; ; 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: LD B,1 CALL DISPAT DEFW 0 ; TTY: DEFW CRTSTAT ; CRT: DEFW RDRST ; BAT: DEFW REMSTAT ; UC1: ;************************************************************************** ; CONSOLE OUTPUT VECTORS CONOUT: LD B,1 CALL DISPAT DEFW 0 ; TTY: DEFW CRTOUT ; CRT: DEFW PLIST ; BAT: DEFW REMOUT ; UC1: ;;************************************************************************* ; 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: ;************************************************************************** ; LIST DEVICE OUTPUT VECTORS 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,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. CRTIN: 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 HL,CBUFTOP ; SEE IF THE CHAR CAME FROM THE ;************************************************************************** ;;DSBC B ; LAST BYTE OF THE QUEUE MACRO SBC HL,BC ;************************************************************************** JR Z,RESQ INC BC ; IF NOT, POINT TO THE NEXT POSY JR SETQ ; INTHE QUEUE RESQ: LD BC,FIFOBUF ; LOAD THE BEGINNING OF THE QUEUE SETQ: ;************************************************************************** ;; SBCD QTAIL ; SET LOCATION FOR NEXT QUEUE READ ;; ld (0000h),bc ld (QTAIL),bc ;************************************************************************** RET ;*************************************J(*********************************** ; INPUT STATUS FOR DART CHANNEL "B" RDRST: IN A,(DARTBC) RRA ; SEE IF DATA IS AVAILABLE SBC A,A RET ;************************************************************************** ; ; GET DATA FROM DART CHANNEL "B" RDRIN: CALL RDRST JR Z,RDRIN IN A,(DARTBD) AND 07FH 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) AND 4 JR Z,CRTOUT ; WAIT UNTIL THE LAST CHAR IS GONE LD A,C ; THEN OUTPUT THIS ONE. 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". ;************************************************************************** ; SEE IF ANY DATA IS IN THE CONSOLE FIFO QUEUE. ON EXIT 00 = NO, FF = YES. CRTSTAT: XOR A LD HL,(QHEAD) ; GET WHERE INPUT PUTS THEM ;******** MACRO *********************************************************** ;;LBCD QTAIL ; AND WHERE OUTPUT TAKES 'EM. ld bc,(QTAIL) ;************************************************************************** ;************************************************************************** ;;DSBC SBC HL,BC ;************************************************************************** RET Z ; IF EQUAL THE OUEUE'S EMPTY LD A,0FFH ; IF NOT EMPTY RETURN AN FF. RET ;************************************************************************** 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: ;********** MACRO ********************************************************* ;;SSPD SPHOLD1 ; SAVE PROGRAMS STACK POINTER ld (SPHOLD1),sp ;************************************************************************** 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 ;********** MACRO ********************************************************* ;;LBCD QHEAD ; GET THE LOCATION OF THE LAST ld bc,(QHEAD) ;************************************************************************** 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 ;********** MACRO ********************************************************* ;;DSBC B ; IF SO THIS CHAR MUST GO SBC HL,BC ;************************************************************************** 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 POP AF ; GET THE CHAR BACK OR A ; WE DON'T STORE NULLS ;********** MACRO ********************************************************* ;;DSBC B ; NOR DO WE ALLOW OVEP-RUNS SBC HL,BC ;************************************************************************** JR Z,NULCHR LD (DE),A ; PUT lT IN THE QUEUE ;********** MACRO ********************************************************* ;;SBCD QEAD ; AND UPDATE THE POINTER ld (QHEAD),bc ;************************************************************************** NULCHR: POP HL POP DE POP BC POP AF ;******** MACRO *********************************************************** ;;LSPD SPHOLD1 ; RESTORE ALL REGS FOR EXIT ld sp,(SPHOLD1) ;************************************************************************** ; ;************************************************************************** ; 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 ;************************************************************************** ; 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: ; MACRO ;SBCD SEKDMA ld (SEKDMA),bc ; MACRO 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,B ; GET THE SECTOR VALUE IN LD L,C 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,(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 ; MACRO ; LDED SEKDMA ;GET THE DESTINATION MEMORY ADDRESS ; MACRO 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 (0F349H),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,(SEKDMA) ; SAVE THE DRIECTION FLAG ; PAGE NUMBER ; SECTOR 1 IS AT TRACK + 80H 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 ; MACRO ;SSPD SPHOLD2 ; SAVE USERS STACK POINTER MACRO ld (SPHOLD2),sp ; MACRO LD SP,FIFOBUF ; AND USE OUR OWN CALL READCACH ; DO THE READ ; MACRO ;LSPD SPHOLD2 ; THEN RESTORE AND EXIT. MACRO ld sp,(SPHOLD2) ; 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 'M'-'A' JR Z,MWRITE ;********* MACRO ********************************************************** ;SSPD SPHOLD2 ;SAVE USERS STACK MACRO ld (SPHOLD2),sp ;************************************************************************** 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,(SEKDMA) ; THE USER DMA ADDRESS XOR A LD (DE),A ; SET MAP TO SHOW "UPDATED" EX DE,HL LD HL,(SEKDMA) ; 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,5 ; SET "FLAG1" SO THAT INTERRUPT SERVICER LD (FLAG1),A ; CAN WRITE DISC ON NEXT SERVICE. XOR A ; ENSURE CP/M SEES SUCCESS ; MACRO ;LSPD SPHOLD2 ;RESTORE STACK MACRO ld sp,(SPHOLD2) ; 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: LD (HL),0 LD C,A ; FOR FUTURE USE LD L,A JR NZ,READT5 ; IF THE READ FAILED, DO NEXT SECTOR 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 (OPFAIL),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,DOFN1 ; 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: SBC A,A PUSH AF ; 'ZERO = "NOT READY" ;LDX A,0 ld a,(ix+0) AND 3 DERR2: ADD A,'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 B SWARP2: LD (DE),A ; STORE CALCULATED FIRST BLOCK # OF LD (HL),B ; THE NEXT SECTOR, AND THE SECTOR # LD HL,BLKCNT 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 ;************************************************************************** ; 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 B 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 ;********* MACRO ********************************************************** ;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 ;************************************************************************** ; 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 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,(IDSEC) LD (NXTSEC),A ; STORE THE SECTOR # JUST PASSED LD C,A DEC C ; LESS ONE... LD HL,SECSIZE ; GET THE SPECIFIED # nF, PLOCv.9 LD B,(HL) ; IN A SECTOR XOR A SECPV1: ADD A,C ; PL=K # = ((SFC-1,*7="1-2)+1 DJNZ SECPV1 INC A LD (PRVHLD),A ; 7s4v7 17 CALL SECWARP ; CHECK FOR '4RAP—AROUND OF TRACK XOR A RET ;************************************************************************** ; 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,(RWRTRY) ; 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 0FDH ; 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 ; EXIT SUCCESSFUL DEC B 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 #. ;********* MACRO ********************************************************** ;;SETB 7,C set 7,c ;************************************************************************** SEEK2: ;;;;LDX A,00H ; GET THE SELECT UNIT BITS ld a,(ix+0) 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 # ld a,(ix+6) ;;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 # ld a,(ix+6) ;;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 ld a,(ix+7) CALL DOCMND BIT 2,A ; LOOK AT SEEK ERROR AGAIN JR Z,SEEKERR SEKRTRY: LD B,5 ; SET RETRY LIMIT SEEK3: LD A,(REALTRK) ; 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 or (ix+07h) CALL DOCMND ; NOW DO IT AND 99H ; MASK READY/DONE ;IN A,FTRK ; LOAD THE FOUND TRACK in a,(FTRK) ;********* MACRO ********************************************************** ;STX A,6 ;SAVE IT IN THE PARAM BLOCK ld (ix+6),a ;************************************************************************** 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 ;********* MACRO ********************************************************** ; SDED M2MSRC ; AND SOURCE ld (M2MSRC),de ;************************************************************************** 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 DJNZ FILM1 RET ;************************************************************************** CACHADR: LD A,(SEKSEC) ; USE THE REQUIRED LOGICAL SECTOR CACHA2: LD HL,BLOKMAP-1 ; AS AN OFFSET INTO THE TRACK MAP ;LD LD LD ADD ; LD LD ; SRLR RARR LD ; ADD LD CP RET CACHA3: LD A,(PRVHLD) ; 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 ;********* MACRO ********************************************************** ;SDED 1 ld (1),de ;************************************************************************** LD (BDOSVEC),A LD DE,BDOS+6 ;********* MACRO ********************************************************** ;SDED BDOSVEC+1 ; MACRO ld (BDOSVEC+1),de ;************************************************************************** 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 (SPHOLD3),sp 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 ;******** MACRO *********************************************************** ;LSPD SPHOLD3 ;RESTORE REGS. AND EXIT ; MACRO ld sp,(SPHOLD3) ;************************************************************************** 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 ;************************************************************************** ; 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 ; FM8TBL: ;************************************************************************** FM5TBL: 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 ;************************************************************************** ; 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 QTAIL: DEFW FIFOBUF PNTR9: DEFB 00 RTCVAL: DEFB 0 FLAG1: DEFB 00 PNTR2: 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 ;************************************************************************** ; 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 SECMAX: 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. ;************************************************************************** ENDTEST: FAD2H: ;; END