home *** CD-ROM | disk | FTP | other *** search
- ; INTEL MDS FDC CARD EMULATOR
- ;
- ; SOURCED NOV 79 BY TREVOR MARSHALL
- ; Dept E & E Eng
- ; University of West Australia
- ; NEDLANDS, W.A. 6009
- ;
- ; This version of the source produces, after linking,
- ; object code in memory from 600H to A000H to enable
- ; a Prom Programmer resident in the host system
- ; to directly program the object file
- ;
- ; A version ORGed at F800H is compiled seperately
- ; and is provided on the master disk as MDSABS.Z80
- ;
- ;
- ; REGISTER USAGE DURING READ AND WRITE:
- ; D contains the (auto wait) drive control byte
- ; IX points to the IOPB base
- ; HL points to the current memory DMA address
- ; B contains the input byte counter for INI & OUTI
- ; C contains DDATA for INI & OUTI
- ; B' (alternate) contains the number of records required
- ; D' (alternate) contains the current sector address
- ; E' (alternate) contains the retry count
- ; H' (alternate) contains the previously logged track
- ; AF' (alternate) contains the previous drive mask
- ; to skip read trk# if it is already logged
- ; and allow for fast response without interleaving
- ;
- ; FDC CONTROLLER DEFINITIONS:
- DCONTROL:EQU 63H ;Control Port
- DFLAGS: EQU 63H ;FDC Status Port
- DDATA: EQU 67H ;1793 Data Port
- DSTATUS: EQU 64H ;1793 Status Port
- DCOMMAND:EQU 64H ;1793 Command Port
- DTRACK: EQU 65H ;1793 Track Port
- DSECTOR: EQU 66H ;1793 Sector Port
- DSIDE: EQU 4 ;Bit 1=0 selects side 1
- ; of D/S drives
- ;
- ; DISK CONTROL PORT HARDWARE ENVIRONMENT
- ; Bits 0-3 select drives 1-4
- ; Bit 7 enables auto wait on accesses to DDATA
- ; Bit 5 enables dsk drive motors
- ; Bit 4 selects single density (S/D)
- ;
- ; DISK STATUS PORT HARDWARE REQUIREMENTS
- ; Bit 0 is 1793 INTREQ status output
- ; Bit 5 indicates head is loaded
- ;
- ; DISK DENSITY DEFINITIONS
- MAXSECTORS: EQU 1AH ;Single Density
- MAXTRACKS: EQU 4CH ; 8" Disks
- ;
- ; PIO DEFINITIONS:
- ACOMMAND:EQU 7AH
- ADATA: EQU 78H
- BCOMMAND:EQU 7BH
- BDATA: EQU 79H
- ;
- ; BUS CONTROL:
- RELEASE: EQU 7FH ;I/O To this addr releases bus
- HOLD: EQU 7CH ;I/O to this addr requests bus
- ;
- ; MDS PORT DEFINITIONS:
- STATUS: EQU 7EH ;S100 Bus reads 78H
- ;Note that port 78H is referenced directly in ASERVICE
- ;TYPE: Not Implemented
- RESULT: EQU 7DH ;S100 Bus reads 7BH
- ;RESET: Not Implemented
- IOPBLOW: EQU 79H
- IOPBHIGH:EQU 7AH
- ;
- ; DISKETTE INSTRUCTION CODES:
- NOP: EQU 0
- SEEK: EQU 1
- FORMAT: EQU 2
- RECALIB: EQU 3
- READ: EQU 4
- VERIFY: EQU 5
- WRITE: EQU 6
- WRITEDEL:EQU 7 ;Write deleted data mark;
- ;
- ; AS THERE IS NO STACK RAM AVAILABLE ALL CODE
- ; MUST BE SEQUENTIAL
- ;
- ; THE PROM PROGRAMMER REQUIRES AN ADDRESS OFFSET
- ; OF 0F200H FOR THIS ORG 0F800H CODE
- ;
- ; THE FOLLOWING MACROS FORM COMMONLY USED ROUTINES
- ;
- STOP: MACRO
- LD SP,STACK; Point at ROM stack
- IN A,RELEASE
- RETI
- MEND
- DONE: MACRO ;Set up status port & stop
- LD A,0FH
- OUT STATUS,A
- STOP
- MEND
- ;
- INTREQ: MACRO ;Wait for intreq
- LL#SYM: IN A,DFLAGS ;Loop until 1793 INTREQ active
- RRA
- JR NC,LL#SYM
- MEND
- ;
- ERRORS: MACRO #LOOP,#MASK ;Check 1793 for errors
- INTREQ
- IN A,DSTATUS
- EXX ;Save working registers
- LD C,A ;Save error byte
- AND 80H ;Not ready mask
- EXX
- JR NZ,#LOOP ;Loop until drive ready
- EXX
- LD A,C
- AND #MASK ;General error mask
- JP NZ,SELECT+OFFSET ;Retry if any errors
- EXX
- MEND
- ;
- SETUP: MACRO ;Set up read and write common parameters
- LP: DL AA#SYM
- AA#SYM: INC D ;Sector #
- LD A,D
- OUT DSECTOR,A
- EXX
- LD A,D
- OUT DCONTROL,A
- LD B,80H ;Input byte count
- IN A,DFLAGS ;Is head loaded?
- AND 20H
- JR Z,J2#SYM ;No
- LD A,0
- JR J3#SYM
- J2#SYM: LD A,04H ;Head load mask for 1793
- J3#SYM DL $
- MEND
- ;
- CHECK: MACRO ;See if read or write is complete
- EXX
- DJNZ LP
- EXX
- LD B,0 ;Done
- JP FINISH+OFFSET
- MEND
- ;
- ; NOTE THAT THE 1793 NEEDS TIME TO CALCULATE CRC
- ; BEFORE THE ERROR STATUS IS AVAILABLE
- ; IF THE DRQ IS NOT SERVICED
- ; The following delay loop is sufficient (4MHz Z-80)
- DELAY: MACRO
- LD B,30H ;12 to 15 give CRC errors
- ; 0 to 12 give BUSY flag
- DJNZ $
- MEND
- ;
- ; Check for 1793 errors during read and write
- DERROR: MACRO #MASK
- INTREQ
- IN A,DSTATUS
- EXX
- LD C,A ;Save error byte
- EXX
- ; Note that we will not check for deleted data marks
- AND #MASK
- JP NZ,S2+OFFSET ; Retry errors
- MEND
-
- ; LINKER AND PROM PROGRAMMER CODE REQUIREMENTS
- ORG 100H
- JP 0
- OFFSET: EQU 0F800H-600H
- ; Setup vectors at top of ROM
- ORG 9F4H ;Effectively FBF4
- VEC1: DW ASERVICE+OFFSET
- VEC2: DW BSERVICE+OFFSET
- WAIT: EI
- HALT ;wait for interrupt
- ; STACK: To enable interrupt structure we need a 'stack'
- DW WAIT+OFFSET
- STACK: EQU $+OFFSET
- DW WAIT+OFFSET
- DW WAIT+OFFSET
- ;
- ; Hardware Reset Code
- ORG 600H
- START: JP 0F804H
- NOP
- ; The ORG address is now effectively F804H
- ; Now setup PIO & Interupts
- ;
- IM2
- LD A,0FBH
- LD I,A ;Int vector table near FBF2
- LD A,0F4H ;IVEC(A) = FBF4
- OUT ACOMMAND,A
- LD A,0F6H ;IVEC(B) = FBF6
- OUT BCOMMAND,A
- LD A,4FH ;MODE 1
- OUT ACOMMAND,A
- OUT BCOMMAND,A
- IN A,ADATA ;Set READY handshake
- IN A,BDATA
- LD A,87H ;Enable PIO interrupt mode
- OUT ACOMMAND,A
- OUT BCOMMAND,A
- ; Now setup output latches
- LD A,00
- OUT RESULT,A
- LD A,0BH ;:F0:,:F1: ready, not D/D
- OUT STATUS,A
- EX AF,AF'
- LD A,0 ;Clear drive select mask
- EX AF,AF'
- EXX
- LD H,0FFH ;Clear logged trk
- EXX
- LD SP,STACK
- EI
- HALT
- ; Routine to service PIO inputs
- ; (79) go to IX lower, (7A) to IX upper
- ;
- ASERVICE: DI
- OUT HOLD,A ; Lock out bus until done
- NOP ;Allow time for bus control
- NOP
- IN A,78H ; S100 Status port read (& reset)
- ; ; must be done during bus access
- IN A,ADATA
- LD IX,0
- LD C,A
- LD B,0
- ADD IX,BC ;Now have A in IX
- STOP
- BSERVICE: DI
- OUT HOLD,A ; Lock out bus until done
- IN A,BDATA
- LD B,A
- LD C,0
- ADD IX,BC ; IX now points to IOPB
- ; Now select side 0 of disks
- LD A,2 ;Set bit 1
- OUT DSIDE,A
- ;
- EXX
- LD E,0AH ;10 retries
- JR SELECT
- ;
- ; NOW BEGIN DECODING COMMAND WORD
- ;
- ; FIRST SELECT THE DRIVE (:F0:=A:, :F1:=C:)
- ;
- S2: EXX
- LD H,0FFH ;Log off track if error occurs
- ; ;This will cause a RESTORE cmd
- ; ;To be executed for SEEK errors
- SELECT: LD A,E
- CP 0 ;Have we retried 10 times?
- LD A,C ;Error byte
-
- JP Z,EXIT+OFFSET
- DEC E
- EXX
- LD A,(IX+0)
- AND 3FH ;Check for acceptable channel word
- JP NZ,CHERROR+OFFSET ; Channel error
- ;
- ;If the op is NOP,FORMAT or RECALIBRATE
- ;Dont check address field
- LD A,(IX+1)
- AND 07H ;Now have opcode field
- CP 1 ;Seek
- JR Z,DONTSKIP
- SUB 4
- JR C,SKIP ; <=3
- DONTSKIP:
-
- ; Now check for valid IOPB addresses
- N12: LD A,(IX+3) ;Track address
- SUB MAXTRACKS+1 ;max track # + 1
- JP NC,ADDERROR+OFFSET
- LD A,(IX+4)
- ;
- ; Must reset bits 4 & 5 of sector byte (a drive select bit)
- ; to retain compatibility with S/D MDS systems
- AND A,09FH
- JP Z,ADDERROR+OFFSET ;Zero sector #
- SUB MAXSECTORS+1 ;Max sector # + 1
- JP NC,ADDERROR+OFFSET
- LD A,(IX+4) ;Sector addr
- ;
- ; Must reset bit 5 of sector byte (a drive select bit)
- ; to retain compatibility with S/D MDS systems
- AND A,09FH
- LD C,(IX+2) ;Number of records requested
- ADD A,C
- SUB A,MAXSECTORS+2
- JP NC,ADDERROR+OFFSET ;Final sector >1AH
- ; Address errors trapped, now seek to required track
- ;
- SKIP: LD A,(IX+1) ;Instruction word
- AND 30H ;Get drive mask
- RRC A
- RRC A
- RRC A
- RRC A
- CP 3 ; S/D MDS drive #1 mask
- JR Z,BSELECT ;Select drive B
- ; Dont allow for more than 2 drives
- LD D,0B1H ;Auto wait,motor on,S/D,A:
- JR J3
- BSELECT: LD D,0B2H ;Auto wait,motor on,S/D,B:
- ; D contains the drive control byte with auto wait set
- ;
- ; Now check for recalibrate, nop & format instructions
- ;
- J3: LD A,(IX+1)
- AND 07H
- CP RECALIB
- JR Z,RESTORE
- CP NOP
- JR Z,DONOP
- CP FORMAT
- JR Z,DONOP
- JR DOSEEK;Not one of these ops
- DONOP: LD B,0
- JP FINISH+OFFSET
- RESTORE: LD A,D ;Drive control byte
- AND 7FH ;Reset auto wait
- OUT DCONTROL,A
- LD A,0DH ;1793 Restore command
- OUT DCOMMAND,A
- ERRORS RESTORE,99H
- LD B,0
- JP FINISH+OFFSET
- ;
- DOSEEK: ;Read, write, verify & seek
- ;all require a seek op first
- ; Now check if drive is logged
- ; trk # will then be available without the read addr op
- ;
- EX AF,AF'
- CP A,D ;Is it the same as the last?
- LD A,D
- JR NZ,LOG ;No, log it
- EX AF,AF'
- EXX
- LD A,H ; fetch last trk #
- EXX
- LD B,A ;Save it
- CP (IX+3) ;Is the desired trk the same?
- JR NZ,LOG2 ;No, read address
- JP LOGGED+OFFSET
- ; Check current track # by reading address from disk
- ;NOTE THAT THE 1793 DOES NOT HEAD LOAD ON 'READ ADDRESS'
- ; IF THE READY INPUT IS NOT ACTIVE
- ; so we must issue a dummy SEEK command first
- ;
- LOG: EX AF,AF'
- ; Will first execute a RESTORE command on the new drive
- REST1: LD A,D
- AND 7FH ;Reset auto wait
- OUT DCONTROL,A
- LD A,0DH ;1793 Restore command
- OUT DCOMMAND,A
- ERRORS REST1,99H
- ;
- ; Now seek to desired track
- LOG2: LD A,D
- AND 7FH ;Reset auto wait
- OUT DCONTROL,A
- IN A,DTRACK
- OUT DDATA,A ;desired trk=current one
- L3: LD A,1AH ;Seek, no verify
- OUT DCOMMAND,A
- ERRORS LOG2,99H
- ;
- L2: LD A,0C4H ;1793 Read address cmd
- OUT DCOMMAND,A
- ;Discard the data bytes
- INTREQ
- DELAY
- IN A,DSTATUS
- AND 19H ; status would not be valid
- JR NZ,L2
- IN A,DSECTOR ;where the 1793 puts the trk
- LD B,A ;Save it
- EXX
- LD H,A ; log it
- EXX
- ;
- ; Now must clear the data request by reading DDATA
- IN A,DDATA
- ;
- LOGGED: LD A,B ;Fetch current track addr
- CP (IX+3) ;Is it the same?
- OUT DTRACK,A
- JR Z,J11 ;Yes, skip read addr
- LD A,(IX+3)
- OUT DDATA,A
- S1: LD A,D
- AND 7FH
- OUT DCONTROL,A ;Disable auto wait
- LD A,1DH ;Seek with verify
- OUT DCOMMAND,A
- ERRORS S1,99H
- ; Now have desired track, check to see if op was seek
- ;
- J11: LD A,(IX+1)
- AND 07H
- CP SEEK
- JP Z,FINISH+OFFSET ; was seek only
- ;
- ; Now calculate the number of records
- ; and setup dedicated register values
- ;
- EXX
- LD B,(IX+2) ;Number of records
- LD A,(IX+4)
- ;
- ; Must reset bit 5 of sector byte (a drive select bit)
- ; to retain compatibility with S/D MDS systems
- LD D,09FH
- AND A,D
- LD D,A
- DEC D ;Initial sector (-1 for SETUP)
- EXX
- ;
- LD H,(IX+6)
- LD L,(IX+5)
- LD C,DDATA
- ;
- ; Was it a read, write or writedel operation?
- LD A,(IX+1)
- AND 07H
- CP READ
- JR Z,DOREAD
- CP WRITE
- JP Z,DOWRT+OFFSET
- CP WRITEDEL
- JP Z,DOWRTDEL+OFFSET
- CP VERIFY
- JP DOVERIFY+OFFSET
- ;
- DOREAD: EXX
- SETUP
- ADD A,88H ;1797 Read command
- OUT DCOMMAND,A
- J13: IN A,DFLAGS
- RRA
- JR C,J12 ;INTREQ = error or read complete
- INI
- JP NZ,J13+OFFSET ;Fetch next data byte
- ; Z set when B=0, ie 128 bytes have been read
- J12: DERROR 9DH
- CHECK
- ;
- DOVERIFY: EXX ;Similar to DOREAD
- SETUP
- ADD 88H ;1797 compatible
- OUT DCOMMAND,A
- J14: IN A,DFLAGS
- RRA
- JR C,J15
- IN A,(C) ;Discard input data
- JP J14+OFFSET
- J15: DERROR 9DH
- CHECK
- ;
- DOWRT: EXX ;Similar to read in structure
- SETUP
- ADD A,0A8H ;1797 compatible
- OUT DCOMMAND,A
- J16: IN A,DFLAGS
- RRA
- JR C,J17
- OUTI
- JP NZ,J16+OFFSET
- J17: DERROR 0FDH
- CHECK
- ;
- DOWRTDEL: EXX
- SETUP
- ADD A,0A9H ;1797 compatible
- OUT DCOMMAND,A
- J20: IN A,DFLAGS
- RRA
- JR C,J19
- OUTI
- JP NZ,J20+OFFSET
- J19: DERROR 0FDH
- CHECK
- ;
- ; Address and Channel error routines
- ;
- ;THIS ENTRY IS VALID DURING ERROR TRAPS
- A1: LD A,08H
- OUT RESULT,A
- JP STAT+OFFSET
- ;
- ; 1793 Error exit routines
- ;
- ; Will print out error messages for ease of debugging
- ; Will use the RST7,RST6 area of RAM for stack
- ;
- EXIT: EXX
- LD SP,0038H ; Out of ISIS area
- PUSH AF
- CALL PMSGFOLLOWING+OFFSET
- DB 0DH,'1793',0A0H
- POP AF
- PUSH AF
- CALL P2HEX+OFFSET
- CALL PRINTIOPB+OFFSET
- POP AF
- LD B,0 ;Use B to hold result byte
- BIT 0,A
- JR Z,J5
- SET 0,B
- SET 7,B
- J5 BIT 1,A ;DRQ error
- JR Z,J6
- SET 4,B
- J6: BIT 2,A ;Lost data
- JR Z,J7
- SET 4,B
- J7: BIT 3,A ;CRC
- JR Z,J8
- SET 1,B
- J8: BIT 4,A ;Seek error
- JR Z,J9
- SET 2,B
- J9: BIT 6,A
- JR Z,FINISH
- SET 5,B
- FINISH: LD A,B
- OUT RESULT,A
- ; The following code has been nulled as it
- ; causes the motors to 'cycle' in speed too much.
- ; A delayed turnoff is needed
- ; Switch off the drive motors
- ; LD A,D
- ; AND 5FH ;motors + wait off
- ; OUT DCONTROL,A
- STAT: DONE
- ;
- ; OUTPUT MESSAGE ROUTINES
- PRINTIOPB: CALL PMSGFOLLOWING+OFFSET
- DB ' ERROR, IOPB A',0D4H
- PUSH IX
- POP HL
- CALL SPACE+OFFSET
- CALL PMSGFOLLOWING+OFFSET
- DB ', CONTENTS:',0A0H
- LD A,(IX+0)
- CALL P2HEX+OFFSET
- LD A,(IX+1)
- CALL P2HEX+OFFSET
- LD A,(IX+2)
- CALL P2HEX+OFFSET
- LD A,(IX+3)
- CALL P2HEX+OFFSET
- LD A,(IX+4)
- CALL P2HEX+OFFSET
- LD L,(IX+6) ;Print in reverse order
- LD H,(IX+5)
- CALL SPACE+OFFSET
- CALL PMSGFOLLOWING+OFFSET
- DB 0DH,8AH
- RET
- ADDERROR: LD SP,0038H ;Not in ISIS area
- CALL PMSGFOLLOWING+OFFSET
- DB 0DH,'ADDRESS',0A0H
- CALL PRINTIOPB+OFFSET
- JP A1+OFFSET
- CHERROR: LD SP,0038H
- CALL PMSGFOLLOWING+OFFSET
- DB 0DH,'CHANNEL',0A0H
- CALL PRINTIOPB+OFFSET
- JP A1+OFFSET
- PMSG: PUSH AF
- PS1: LD A,(HL)
- INC HL
- CALL PCHR+OFFSET
- RLA
- JR NC,PS1
- POP AF
- RET
- PMSGFOLLOWING:
- EX (SP),HL
- CALL PMSG+OFFSET
- EX (SP),HL
- RET
- PCHR: PUSH AF
- ;SJ2: IN A,0F7H ;CRT STATUS
- ; AND 1
- ; JR Z,SJ2
- ; POP AF
- ; PUSH AF
- ; OUT 0F6H,A ;CRT DATA
- SJ1: IN A,0FBH ;PRINTER STATUS
- AND 1
- JR Z,SJ1
- POP AF
- OUT 0FBH,A ;PRINT DATA
- RET
- SPACE: LD A,20H
- CALL PCHR+OFFSET
- LD A,H
- CALL P2HEX+OFFSET
- LD A,L
- P2HEX: PUSH AF
- LD A,20H
- CALL PCHR+OFFSET
- POP AF
- CALL P1HEX+OFFSET
- RRA
- P1HEX: RRA
- RRA
- RRA
- RRA
- PUSH AF
- AND 0FH
- CP 10
- JR C,PH1
- ADD 7
- PH1: ADD 30H
- CALL PCHR+OFFSET
- POP AF
- RET
- END START
-