home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol041
/
xerox.z80
< prev
Wrap
Text File
|
1984-04-29
|
12KB
|
659 lines
; XEROX REQUIRES 4MHZ ZPU OPERATION
EXTRN BINH2
XEROX:
ld hl,(6)
ld sp,hl
LD A,(5CH); CDOS FCB-1
LD (TO),A
LD A,(6CH); CDOS FCB-2
LD (FROM),A
LD A,(TO)
OR A
JR NZ,NXT
LD C,C.DISK
CALL CDOS
INC A
LD (TO),A
NXT:
LD A,(FROM)
OR A
JR NZ,NXT2
LD C,C.DISK
CALL CDOS
INC A
LD (FROM),A
NXT2:
LD HL,TO
CP (HL)
JR NZ,NXT2A
LD DE,NOTSAME
LD C,W.LINE
CALL CDOS
JP 0
NOTSAME:DB LF,CR,BEL,BEL,BEL,'CANNOT COPY TO SAME FLOPPY',LF,CR,'$'
NXT2A:
LD A,(TO)
ADD 40H
LD (DR),A
LD DE,QUEST
LD C,W.LINE
CALL CDOS
LD C,R.CHAR
CALL CDOS
CP 'Y'
JR Z,OK
CP 'y'
JR Z,OK
JP 0
QUEST: DB LF,CR,BEL,BEL,BEL,'OK TO DESTROY CURRENT CONTENTS OF FLOPPY ON DRIVE '
DR: DB ' ? $'
CRLF: DB LF,CR,'$'
FROM: DB 0
TO: DB 0
CURR: DB 0
SAMEDR: DB 0
DENSITY: DB 0
RETRY: DB 0
HLSAVE: DW 0
TRKSINMEM: DB 0
TRKIN: DB 0
TRKOUT: DB 0
TRKCNT: DB 0
ENTRY $MEMRY
$MEMRY: DW 0
OK:
LD DE,CRLF
LD C,W.LINE
CALL CDOS
LD A,0; TEST IF FLOPPIES ON SAME DUAL DRIVE
LD (SAMEDR),A
LD A,(FROM)
LD B,A
LD A,(TO)
SUB B
JP P,POSA
NEG
POSA: CP 1
JR NZ,NOTONE; NO
LD A,(TO); IF DIFFERENCE IS ONE IT MUST BE A 1,2 OR 3,4
CP B; COMBINATION
JP P,AGR
LD A,B
AGR: RRA; I.E. THE LARGEST MUST BE EVEN
JR C,NOTONE; NOT ON SAME DUAL DRIVE
LD (SAMEDR),A
NOTONE:
LD A,(FROM)
LD B,A
XOR A
SCF
NXT3: RLA
DJNZ NXT3
OR MOTORON+MAXI+DBLDEN
LD (FROM),A
LD A,(TO)
LD B,A
XOR A
SCF
NXT4: RLA
DJNZ NXT4
OR MOTORON+MAXI+DBLDEN
LD (TO),A
MSKINTRP: EQU 03H
AUXDSK: EQU 04H; INPUT/OUTPUT PORT FOR FAST SEEK
FASTSEEK: EQU 0EFH
SEEKCOMP: EQU 40H
RESETFST: EQU 0FFH
;
DSKSTAT:EQU 30H; INPUT PORT FOR DISK STATUS
NOTREADY: EQU 80H
PROTECT:EQU 40H
HEADDOWN: EQU 20H
WRFAULT:EQU 20H
NOTFND: EQU 10H
CRCERR: EQU 08H
LOSTDATA: EQU 04H
DRQ: EQU 02H
BUSY: EQU 01H
;
DSKCMD: EQU 30H; OUTPUT PORT FOR DISK COMMANDS
RESTORE:EQU 0CH
SEEK: EQU 18H
READ: EQU 88H
ENBLHOLD: EQU 04H
WRITE: EQU 0A8H
RESET: EQU 0D0H
;
TRKREG: EQU 31H; I/O PORT FOR TRACK REGISTER
;
SECREG: EQU 32H; I/O PORT FOR SECTOR REGISTER
;
DATAREG:EQU 33H; I/O PORT FOR DATA
;
DSKCNTRL:EQU 34H; OUTPUT PORT FOR DISK CONTROL
MOTORON:EQU 20H
MAXI: EQU 10H
DBLDEN: EQU 40H
AUTOWAIT: EQU 80H
;
DSKFLGS:EQU 34H; INPUT PORT FOR DISK FLAGS
HEADLOAD: EQU 20H
EOJ: EQU 01H
;
CDOS: EQU 5; CDOS CALL ADDRESS
; CDOS CALL CODES
C.DISK: EQU 25
R.CHAR: EQU 1
W.LINE: EQU 9
DIVIDE: EQU 138
RES.CDOS: EQU 13
SEL.DISK: EQU 14
; TTY CONTROL CODES
CR: EQU 0DH
LF: EQU 0AH
BEL: EQU 07H
; DISK CONSTANTS
MAXRETRY: EQU 10 ; NUMBER OF RETRIES IF R/W ERROR
NRTRKS: EQU 77
NRSECS: EQU 26 ; SINGLE DEN
NRSECS2: EQU 16 ; DOUBLE DEN
TRKSIZE:EQU NRSECS2*512; SIZE OF A TRACK
TRKSIZ1:EQU NRSECS*128
XOR A
LD (TRKIN),A
LD (TRKOUT),A
LD HL,($MEMRY); GET START OF BUFFER
EX DE,HL; SAVE IN DE
LD HL,(6); GET HIGHEST MEMORY ADDRESS
SCF
SBC HL,DE; CALCULATE AVAILABLE MEMORY
LD DE,TRKSIZE; SIZE OF A TRACK
LD C,DIVIDE
CALL CDOS
LD A,L
LD (TRKSINMEM),A; SET MAX. NR OF TRACKS READABLE
LD A,(FROM)
AND NOT DBLDEN ; DISABLE DOUBLE DENSITY FOR HOME
LD (CURR),A
OUT DSKCNTRL,A; SELECT INPUT DISK
LD D,NOTREADY+NOTFND+CRCERR+BUSY
LD A,RESTORE; RESTORE DISK TO TRACK ZERO
CALL EXECUTE
LD A,(TO)
AND NOT DBLDEN
LD (CURR),A
OUT DSKCNTRL,A
LD D,NOTREADY+PROTECT+NOTFND+CRCERR+BUSY
LD A,RESTORE
CALL EXECUTE
; READ IN FIRST SECTOR TO SEE IF DOUBLE OR SINGLE DENSITY
LD HL,($MEMRY)
LD A,(FROM)
AND NOT DBLDEN
LD (CURR),A
CALL SETUP
ADD READ
LD D,NOTREADY+NOTFND+CRCERR+LOSTDATA
LD C,SECREG
LD E,1
OUT (C),E
LD C,DATAREG
OUT DSKCMD,A; START READING
LOOP2:
IN A,DSKFLGS; WAIT FOR DRQ OR EOJ
RRA
JR C,DENSREADY; EOJ FOUND?
INI; PLACE NEXT BYTE AT (HL) AND UPDATE
JR LOOP2; GET NEXT BYTE FROM SECTOR
DENSREADY:
IN A,DSKSTAT; GET STATUS AFTER SECTOR
LD B,A
AND D
JP NZ,ERROR
LD IX,($MEMRY)
LD A,'L'
CP (IX+78H)
JR NZ,SINGLE
LD A,'G'
CP (IX+79H)
JR NZ,SINGLE
LD A,'S'
CP (IX+7AH)
JR NZ,SINGLE
CP (IX+7BH)
JR NZ,SINGLE
LD A,'D'
CP (IX+7CH)
JR NZ,SINGLE
CP (IX+7DH)
JR NZ,SINGLE
LD A,0FFH
LD (DENSITY),A
LD DE,DOUBLEDEN
JR DENMESS
SINGLE:
XOR A
LD (DENSITY),A
LD DE,SINGLEDEN
DENMESS:
LD C,W.LINE
CALL CDOS
JR RESTART
DOUBLEDEN: DB 'Double density transfer.',CR,LF,'$'
SINGLEDEN: DB 'Single density transfer.',CR,LF,'$'
RESTART:
LD HL,($MEMRY)
LD A,0
LD (TRKCNT),A
LD A,(DENSITY)
OR A
JR Z,SNGSKP1
IN A,TRKREG
OR A ; CHECK FOR TRACK 2 OR GREATER
SNGSKP1: LD A,(FROM)
JR NZ,DBLSKP1
AND NOT DBLDEN
DBLSKP1:
LD (CURR),A
CALL SETUP; PREPARE DISK FOR COMING OPERATION
ADD READ; CONSTRUCT READ COMMAND
RDTRACK:
LD E,1; SECTOR COUNTER
LD D,NOTREADY+NOTFND+CRCERR+LOSTDATA
PUSH HL
LD HL,RETRY
LD (HL),0
POP HL
AGAIN:
LD (HLSAVE),HL ;SAVE FOR RETRIES
LD C,SECREG
OUT (C),E
LD C,DATAREG
OUT DSKCMD,A; START READING
AGAIN2:
IN A,DSKFLGS; WAIT FOR DRQ OR EOJ
RRA
JR C,READREADY; EOJ FOUND?
INI; PLACE NEXT BYTE AT (HL) AND UPDATE
JR AGAIN2; GET NEXT BYTE FROM SECTOR
READREADY:
IN A,DSKSTAT; GET STATUS AFTER SECTOR
LD B,A
AND D
JP NZ,RERROR
LD A,E
CP NRSECS
JP Z,LSTSEC; LAST SECTOR OF TRACK INPUT
LD A,(DENSITY)
OR A
JR Z,DBLSKP4
IN A,TRKREG ; CHECK FOR DBLDEN
OR A
JR Z,DBLSKP4
LD A,E
CP NRSECS2
JP Z,LSTSEC
DBLSKP4: INC E
RRETRY:
LD A,(DENSITY)
OR A
JR Z,SNGSKP8
IN A,TRKREG
OR A ; CHECK FOR TRACK 2 OR GREATER
SNGSKP8:
LD A,(FROM)
JR NZ,DBLSKP8
AND NOT DBLDEN
DBLSKP8:
OR AUTOWAIT
OUT DSKCNTRL,A
LD A,READ
JR AGAIN
RERROR:
LD A,(RETRY)
CP MAXRETRY
JP Z,ERROR
INC A
LD (RETRY),A
PUSH DE
PUSH BC
LD A,B
LD HL,RSTAT; SET ERROR OR STATUS BITS
CALL BINH2
IN A,TRKREG; GET TRACK-NUMBER
LD HL,RTRK
CALL BINH2
IN A,SECREG; GET SECTOR-NUMBER
LD HL,RSEC
CALL BINH2
LD DE,MESRETRY
LD C,W.LINE
CALL CDOS
POP BC
POP DE
LD HL,(HLSAVE)
JR RRETRY
MESRETRY: DB 'Retry, Status = '
RSTAT: DB ' , Track = '
RTRK: DB ' , Sector = '
RSEC: DB ' .',CR,LF,'$'
LSTSEC:
LD A,(TRKIN); DO IT FOR 77 TRACKS
CP NRTRKS-1
JP Z,WRTHEM
INC A
LD (TRKIN),A
LD B,A
DEC A
CALL SEEKTRK; GO TO NEXT TRACK
LD A,(TRKSINMEM)
LD B,A
LD A,(TRKCNT)
INC A
CP B
JP Z,WRTHEM
LD (TRKCNT),A
LD A,(DENSITY)
OR A
JR Z,SNGSKPA
IN A,TRKREG
OR A ; CHECK FOR TRACK 2 OR GREATER
SNGSKPA:
LD A,(FROM)
JR NZ,DBLSKPA
AND NOT DBLDEN
DBLSKPA:
OR AUTOWAIT
OUT DSKCNTRL,A
LD A,READ
JP RDTRACK
WRTHEM:
LD HL,($MEMRY)
LD A,0
LD (TRKCNT),A
LD A,(SAMEDR); TEST IF ON SAME DUAL DRIVE IS INPUT
OR A
JR Z,DIFDR; NO
LD A,(TRKOUT)
LD B,A
LD A,(TRKIN)
CALL SEEKTRK; SEEK BACK TO WRITING POSITION
DIFDR:
LD A,(TRKOUT)
OUT TRKREG,A
LD A,(DENSITY)
OR A
JR Z,SNGSKP2
IN A,TRKREG
OR A ; CHECK FOR TRACK 2 OR GREATER
SNGSKP2:
LD A,(TO)
JR NZ,DBLSKP2
AND NOT DBLDEN
DBLSKP2:
LD (CURR),A
CALL SETUP; PREPARE DISK FOR COMING OPERATION
ADD WRITE; CONTRUCT WRITE COMMAND
WRTRACK:
LD E,1; SECTOR COUNTER
LD D,NOTREADY+PROTECT+WRFAULT+NOTFND+CRCERR+LOSTDATA
BACK:
LD C,SECREG
OUT (C),E
LD C,DATAREG
OUT DSKCMD,A; START WRITING
BACK2:
IN A,DSKFLGS; WAIT FOR DRQ OR EOJ
RRA
JR C,WRREADY; EOJ FOUND?
OUTI; GET NEXT BYTE FROM (HL) AND UPDATE
JR BACK2; WRITE NEXT BYTE TO SECTOR
WRREADY:
IN A,DSKSTAT; GET STATUS AFTER SECTOR
LD B,A
AND D
JP NZ,ERROR
LD A,E;
CP NRSECS
JR Z,VERIFY; LAST SECTOR OF TRACK WRITTEN
LD A,(DENSITY)
OR A
JR Z,DBLSKP5
IN A,TRKREG ; CHECK FOR DBLDEN
OR A
JR Z,DBLSKP5
LD A,E
CP NRSECS2
JR Z,VERIFY
DBLSKP5: INC E
LD A,(DENSITY)
OR A
JR Z,SNGSKP9
IN A,TRKREG
OR A ; CHECK FOR TRACK 2 OR GREATER
SNGSKP9:
LD A,(TO)
JR NZ,DBLSKP9
AND NOT DBLDEN
DBLSKP9:
OR AUTOWAIT
OUT DSKCNTRL,A
LD A,WRITE
JR BACK
VERIFY:
LD E,1; RESTART AT FIRST SECTOR
LD D,NOTREADY+NOTFND+CRCERR+LOSTDATA
BACK3:
LD A,(DENSITY)
OR A
JR Z,SNGSKP3
LD A,(TRKOUT)
OR A ; CHECK FOR TRACK 2 OR GREATER
SNGSKP3:
LD A,(TO)
JR NZ,DBLSKP3
AND NOT DBLDEN
DBLSKP3:
OR AUTOWAIT
OUT DSKCNTRL,A
LD B,0FFH; SET ERROR CODE TO "VERIFY ERROR"
LD C,SECREG
OUT (C),E
LD A,READ
OUT DSKCMD,A; START READING
BACK4:
IN A,DSKFLGS; WAIT FOR DRQ OR EOJ
RRA
JR C,SECREAD; IF EOJ, SECTOR IS READ
IN A,DATAREG; GET BYTE
JR BACK4
SECREAD:
IN A,DSKSTAT; STATUS AFTER SECTOR READ
LD B,A
AND D
JP NZ,ERROR
LD A,E; LAST SECTOR OF TRACK?
CP NRSECS
JR Z,ENDVERIFY
LD A,(DENSITY)
OR A
JR Z,DBLSKP6
IN A,TRKREG ; CHECK FOR DBLDEN
OR A
JR Z,DBLSKP6
LD A,E
CP NRSECS2
JR Z,ENDVERIFY
DBLSKP6: INC E
JR BACK3
ENDVERIFY:
LD A,(TRKOUT); DO IT FOR 77 TRACKS
CP NRTRKS-1
JP Z,TERM
INC A
LD (TRKOUT),A
LD B,A
DEC A
CALL SEEKTRK; GO TO NEXT TRACK
LD A,(TRKSINMEM); CHECK IF END OF MEMORY
LD B,A
LD A,(TRKCNT)
INC A
CP B
JP Z,RESTART
LD (TRKCNT),A
LD A,(DENSITY)
OR A
JR Z,SNGSKPB
IN A,TRKREG
OR A
SNGSKPB:
LD A,(TO)
JR NZ,DBLSKPB
AND NOT DBLDEN
DBLSKPB:
OR AUTOWAIT
OUT DSKCNTRL,A
LD A,WRITE
JP WRTRACK
;
;THIS SUBROUTINE IS USED AFTER SWITCH TO NEW DRIVE TO PREPARE IT
;FOR A NEW SEQUENCE OF READS OR WRITES
;
SETUP:
OUT DSKCNTRL,A
LD B,A; READ/WRITE FROM FIRST SECTOR ONWARDS
LD A,1;
OUT SECREG,A
IN A,DSKFLGS
AND HEADLOAD; HEAD LOADED?
LD C,A
LD A,B
OR A,AUTOWAIT; FOR NEXT COMMANDS USE AUTO WAIT MODE
OUT DSKCNTRL,A
LD A,C
OR A; WAS HEAD LOADED?
LD A,4
RET Z; NO
XOR A
RET
;
;THIS SUBROUTINE EXECUTES "RESTORES" AND "SEEKS" (ERROR MASK IN REG.D)
;
EXECUTE:
OUT DSKCMD,A
WAIT:
IN A,DSKFLGS; CHECK IF READY
RRA
JR NC,WAIT
IN A,DSKSTAT
LD B,A
AND D; COMPARE TO ERROR MASK
JR NZ,ERROR
RET
;
;THIS ROUTINE EXECUTES A FAST SEEK FROM (A) TO (B)
;
SEEKTRK:
OUT TRKREG,A; SET TO CURRENT TRACK
LD A,B; GET REQUIRED TRACK-NR
OUT DATAREG,A; GIVE DESIRED TRACK TO 4FDC
LD A,FASTSEEK; SET TO FAST SEEK
OUT AUXDSK,A
LD A,SEEK;
LD D,NOTREADY
CALL EXECUTE
REDO2: IN A,AUXDSK; SEEK COMPLETED?
AND SEEKCOMP
JR NZ,REDO2
LD A,RESETFST; RESET FAST SEEK MODE
OUT AUXDSK,A
RET
;
;THIS HANDLES ANY ERROR AND TERMINATES THE PROGRAM WITH AN APPROPRIATE
;ERROR MESSAGE
;
ERROR:
PUSH BC; SAVE ERROR STATUS
LD A,B
LD HL,ERSTAT; SET ERROR OR STATUS BITS
CALL BINH2
IN A,TRKREG; GET TRACK-NUMBER
LD HL,TRK
CALL BINH2
IN A,SECREG; GET SECTOR-NUMBER
LD HL,SEC
CALL BINH2
LD A,RESET; RESET ANY CURRENT COMMAND
OUT DSKCMD,A
LD A,(CURR)
AND 0FH
LD B,1
RRA: RRA ; FIND OUT DEVICE NAME
JR C,DEVFND
INC B
JR RRA
DEVFND: LD A,B
ADD 40H
LD (DEV),A
LD DE,ERMSG
LD C,W.LINE
CALL CDOS
POP BC; RESTORE ERROR FLAG
LD A,B
LD DE,VERFERR
CP 0FFH
JR Z,ERTERM; ERROR FOUND IN VERIFICATION
LD DE,IOERR
AND NOTFND+CRCERR
JR NZ,ERTERM; REAL READ OR WRITE ERROR
LD A,B
LD DE,READYERR
AND NOTREADY
JR NZ,ERTERM; DRIVE IS NOT READY
LD A,B
LD DE,PROTERR
AND PROTECT
JR NZ,ERTERM; FLOPPY IS WRITE PROTECTED
LD A,B
LD DE,WRERR
AND WRFAULT
JR NZ,ERTERM; I/O ERROR ON WRITING
LD DE,UNKNERR; STRANGE ERROR
ERTERM:
LD C,W.LINE; PREPARE FOR WRITE MESSAGE
CALL CDOS
LD DE,ERMSG2
CALL CDOS
JP TERM2
VERFERR:DB '(DATA READ BACK UNEQUAL TO DATA WRITTEN)$'
IOERR: DB '(DATA ERROR WHEN READING OR WRITING)$'
READYERR: DB '(DRIVE NOT READY: MAKE READY AND RETRY)$'
PROTERR:DB '(FLOPPY IS WRITE PROTECTED)$'
WRERR: DB '(DATA ERROR WHEN WRITING: RE-INITIALIZE FLOPPY)$'
UNKNERR:DB '(UNIDENTIFIABLE PROBLEM)$'
ERMSG: DB BEL,BEL,BEL,'ERROR ',BEL,BEL,'ON DRIVE ',BEL,BEL,BEL
DEV: DB ' , AT TRACK '
TRK: DB ' , SECTOR '
SEC: DB ' ,',LF,CR,'STATUS='
ERSTAT: DB ' $'
ERMSG2: DB '.',LF,CR,'PROGRAM PREMATURELY TERMINATED.$'
TRMMSG: DB 'FAST COPY OPERATION SUCCEEDED. FLOPPY WRITTEN AND VERIFIED.$'
;
;THIS TERMINATES THE PROGRAM AFTER RESTORING THE "CURRENT DISK" SELECTION
;
TERM:
LD C,W.LINE
LD DE,TRMMSG
CALL CDOS
TERM2:
LD C,C.DISK; GET CURRENT DRIVE
CALL CDOS
LD E,A
LD C,RES.CDOS; RESET CDOS AND LOG OFF ALL DISKS
CALL CDOS
LD C,SEL.DISK; RESTORE CURRENT DISK SELECTION
CALL CDOS
JP 100H
END XEROX