|
|
DataMuseum.dkPresents historical artifacts from the history of: CP/M |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about CP/M Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 31232 (0x7a00)
Types: TextFile
Names: »FLOPPY.MAC«
└─⟦72577d508⟧ Bits:30003297 Diverse BIOS typer til RC703
└─⟦this⟧ »FLOPPY.MAC«
SUBTTL FLOPPY DISK DRIVER
;========================================================
;= FLOPPY DISK DRIVER =
;========================================================
WRALL EQU 0 ; WRITE TO ALLOCATED SECTOR.
WRDIR EQU 1 ; WRITE TO DIRECTORY SECTOR.
WRUAL EQU 2 ; WRITE TO UNALLOCATED SECTOR (FIRST SECTOR OF A
; NEW DATA BLOCK).
PAGE
;================================================
;= PROCEDURE SECTION =
;================================================
;SELECT DISK DRIVE
;ENTRY: C=DRIVE NUMBER
;EXIT : HL=DISK PARAMETER HEADER
SELD: LD HL,0 ; PROCEDURE SELECT_DISK;
ADD HL,SP ;
LD SP,STACK ; SP := LOCAL_STACK;
PUSH HL ;
LD HL,0 ; ERROR CODE
LD A,(DRNO) ; DRIVE OK?
CP C ; CY IF SO
JP C,RSELD ; RET IF ERROR
LD A,C ;
LD (SEKDSK),A ; INIT. SEEK DISK WITH NEW DRIVE NO.
LD BC,10H ; INIT. DPH LENGTH
LD DE,FD0 ; GET FD0 ADDRESS
LD HL,00H ; INIT. DPH OFFSET
SELD10: OR A ;
JP Z,SELD20 ;
INC DE ; DE:=DE+DRIVE_NO
ADD HL,BC ; HL:=HL+(DRIVE_NO.*DPH_LENGTH)
DEC A ;
JP SELD10 ;
SELD20: LD C,L ;
LD B,H ;
EX DE,HL ;
LD A,(HL) ;
LD HL,CFORM ;
CP (HL) ;
JP Z,SELN ;
PUSH AF ; IF: NEW_FORMAT # CURRENT_FORMAT THEN
PUSH BC ; IF: HOST_WRITE # 0 THEN
LD A,(HSTWRT) ; WRITE BUFFER TO DISK
OR A ; ELSE:
CALL NZ,WRTHST ; ELSE:
XOR A ;
LD (HSTWRT),A ;
POP BC ;
POP AF ;
LD (CFORM),A ; TFj VÆLG FLOPPY-
CP 16 ; TFj CLOCKFREKVENS
JP Z,MINIFL ; TFj
LD A,2 ; TFj
MINIFL: INC A ; TFj
OUT (SW1),A ; TFj
LD A,(CFORM) ; TFj
SELN: LD (CFORM),A ; CURRENT_FORMAT := FORMAT(DRIVE_NO);
CALL GFPA ; GET NEW FLOPPY_DISK_PARMS ADDRESS
LD (FORM),HL ;
INC HL ;
INC HL ;
INC HL ;
INC HL ;
LD A,(HL) ; INIT. NUMBER OF TRACKS ON ONE DISK PAGE
LD (EOTV),A ;
PUSH BC ;
LD A,(CFORM) ;
AND 11111000B ; REMOVE POSITION BITS
OR A ;
RLA ;
LD E,A ;
LD D,0 ;
LD HL,FSPA00 ;
ADD HL,DE ; INIT. ACTUAL DISK_PARMS_BLOCK
LD DE,DPBLCK ;
LD BC,10H ;
LDIR ;
LD HL,(DPBLCK) ; GET ADDRESS OF DPBXX (XX=0,08,16,,56,64)
LD BC,13 ; REL. TO START
ADD HL,BC ; ADDRESS OF OFFSET WORD
EX DE,HL ;
LD HL,TRKOFF ; TRACK OFFSET TABLE
LD B,0 ;
LD A,(SEKDSK) ; BC= SEEK DISK NO.
LD C,A ;
ADD HL,BC ;
ADD HL,BC ; HL= ADDRESS OF OFFSET VALUE IN OFFSET TBL
LD BC,2 ; NO OF BYTES TO MOVE
LDIR ;
POP BC ;
LD HL,DPBASE ;
ADD HL,BC ; GET ADR. OF ACTUAL DISK_PARMS_HEADER
EX DE,HL ;
LD HL,10 ;
ADD HL,DE ;
EX DE,HL ;
LD A,(DPBLCK) ; INIT. DISK_PARMS_HEADER WITH
LD (DE),A ; ACTUAL DISK_PARMS_BLOCK
INC DE ;
LD A,(DPBLCK+1) ;
LD (DE),A ;
RSELD: EX DE,HL ; HL:=DPH(DISK)
POP HL ;
LD SP,HL ;
EX DE,HL ;
RET ;
PAGE
GFPA: LD HL,FDF1 ;
LD A,(CFORM) ;
AND 11111000B ; REMOVE POSITION BITS
LD E,A ;
LD D,0 ;
ADD HL,DE ;
RET ;
;SETTRACK
;ENTRY: BC=TRACK NUMBER
SETT: LD H,B ;
LD L,C ;
LD (SEKTRK),HL ;
RET ;
;SETSECTOR
;ENTRY: BC=SECTOR NUMBER
SETS: LD L,C ;
LD H,B ;
LD (SEKSEC),HL ;
RET ;
;SET DMA ADDRESS
;ENTRY: BC=DMA ADDRESS
SETD: LD H,B ;
LD L,C ;
LD (DMAADR),HL ;
RET ;
;TRANSLATE SECTOR NUMBER
;ENTRY: BC=SECTOR NUMBER
SECTRA: LD H,B ;
LD L,C ;
RET ;
PAGE
;READ THE SELECTED CP/M SECTOR
;ENTRY:
;EXIT : A=RESULT (0 OK,1 HARD ERROR)
XREAD: XOR A ;PATCHES FROM DIGITAL
LD (UNACNT),A ;
LD A,1 ;
LD (READOP),A ; READ OPERATION
LD (RSFLAG),A ; MUST READ DATA
LD A,WRUAL ;
LD (WRTYPE),A ; TREAT AS UNALLOCATED
JP RWOPER ; TO PERFORM THE READ
;WRITE THE SELECTED CP/M SECTOR
;ENTRY:
;EXIT : C=WRITETYPE A=RESULT
XWRITE: XOR A ;
LD (READOP),A ; NOT A READ OPERATION
LD A,C ; WRITE TYPE IN C
LD (WRTYPE),A ;
CP WRUAL ; WRITE UNALLOCATED?
JP NZ,CHKUNA ; CHECK FOR UNALLOCATED
;WRITE TO UNALLOCATED, SET PARAMETERS
LD A,(CPMRBP) ; UNACNT := BLKSIZE/128;
LD (UNACNT),A ;
LD A,(SEKDSK) ; UNADSK := SEKDSK;
LD (UNADSK),A ;
LD HL,(SEKTRK) ; UNATRK := SEKTRK;
LD (UNATRK),HL ;
LD HL,(SEKSEC) ; UNASEC := SEKSEC;
LD (UNASEC),HL ;
;CHECK FOR WRITE TO UNALLOCATED SECTOR
CHKUNA: LD A,(UNACNT) ; ANY UNALLOCATED REMAIN?
OR A ;
JP Z,ALLOC ; SKIP IF NOT
PAGE
;MORE UNALLOCATED RECORDS REMAIN
DEC A ; UNACNT := UNACNT -1;
LD (UNACNT),A ;
LD A,(SEKDSK) ; SAME DISK?
LD HL,UNADSK ;
CP (HL) ; SEKDSK=UNADSK?
JP NZ,ALLOC ; SKIP IF NOT
;DISKS ARE THE SAME
LD HL,UNATRK ; SAME TRACK?
CALL TRKCMP ; SEKTRK=UNATRK?
JP NZ,ALLOC ; SKIP IF NOT
;TRACKS ARE THE SAME
LD A,(SEKSEC) ; SAME SECTOR?
LD HL,UNASEC ;
CP (HL) ; SEKSEC=UNASEC?
JP NZ,ALLOC ; SKIP IF NOT
LD A,(SEKSEC+1) ;
INC HL ;
CP (HL) ; COMPARE MSB
JP NZ,ALLOC ;
;MATCH, MOVE TO NEXT SECTOR FOR FUTURE REFERENCE
LD HL,(UNASEC) ;
INC HL ;
LD (UNASEC),HL ; UNASEC:=UNASEC+1
EX DE,HL ;
LD HL,CPMSPT ; GET SECTORS PER TRACK
PUSH BC ;
LD C,(HL) ;
INC HL ;
LD B,(HL) ;
EX DE,HL ;
AND A ; RESET CARRY
SBC HL,BC ; END OF TRACK
POP BC ;
JP C,NOOVF ; SKIP IF NO OVERFLOW
PAGE
;OVERFLOW TO NEXT TRACK
LD HL,00 ; UNASEC:=0
LD (UNASEC),HL ;
LD HL,(UNATRK) ;
INC HL ;
LD (UNATRK),HL ; UNATRK:=UNATRK+1
;MATCH FOUND, MARK AS UNNECESSARY READ
NOOVF: XOR A ;
LD (RSFLAG),A ; RSFLAG:=0
LD A,(SEKSEC) ;
LD HL,SECMSK ;
AND (HL) ;
CP (HL) ;
LD A,0 ;
JP NZ,SETMSK ;
INC A ;
SETMSK: LD (UNAMSK),A ;
JP RWOPER ; TO PERFORM THE WRITE
;NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
ALLOC: XOR A ;
LD (UNACNT),A ; UNACNT:=0
LD A,(SECMSK) ;
LD (RSFLAG),A ; RSFLAG:=1
PAGE
; COMMON CODE FOR READ AND WRITE FOLLOWS
RWOPER: LD HL,0 ;
ADD HL,SP ;
LD SP,STACK ; ESTABLISH LOCAL STACK
PUSH HL ; SAVE OLD SP
LD A,(SECSHF) ; COMPUTE HOST SECTOR
LD B,A ;
LD HL,(SEKSEC) ;
RSECS: DEC B ;
JP Z,SETSH ;
SRL H ; HOST_SECTOR := SEEK_SECTOR DIVIDED
RR L ; WITH SECTOR SHIFT CONSTANT
JP RSECS ;
SETSH: LD (SEKHST),HL ; HOST SECTOR TO SEEK
;ACTIVE HOST SECTOR?
LD HL,HSTACT ; HOST ACTIVE FLAG
LD A,(HL) ;
LD (HL),1 ; ALWAYS BECOMES 1
OR A ; WAS IT ALREADY?
JP Z,FILHST ; FILL HOST IF NOT
;HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?
LD A,(SEKDSK) ;
LD HL,HSTDSK ; SAME DISK?
CP (HL) ; SEKDSK=HSTDSK?
JP NZ,NOMATC ;
;SAME DISK, SAME TRACK?
LD HL,HSTTRK ;
CALL TRKCMP ; SEKTRK=HSTTRK
JP NZ,NOMATC ;
PAGE
;SAME DISK, SAME TRACK, SAME SECTOR?
LD A,(SEKHST) ;
LD HL,HSTSEC ; SEKHST=HSTSEC?
CP (HL) ;
JP NZ,NOMATC ; LSB COMPARE
LD A,(SEKHST+1) ;
INC HL ;
CP (HL) ; MSB COMPARE
JP Z,MATCH ; SKIP IF MATCH
;PROPER DISK, BUT NOT CORRECT SECTOR
NOMATC: LD A,(HSTWRT) ; HOST WRITTEN?
OR A ;
CALL NZ,WRTHST ; WRITE HOST BUFFER TO DISK
;MAY HAVE TO FILL THE HOST BUFFER
FILHST: LD A,(SEKDSK) ;
LD (HSTDSK),A ;
LD HL,(SEKTRK) ;
LD (HSTTRK),HL ;
LD HL,(SEKHST) ;
LD (HSTSEC),HL ;
LD A,(RSFLAG) ; NEAD TO READ?
OR A ;
CALL NZ,RDHST ; YES, IF 1
XOR A ;
LD (HSTWRT),A ; NO PENDING WRITE
PAGE
;COPY DATA TO OR FROM BUFFER
MATCH: LD A,(SEKSEC) ; MASK BUFFER NUMBER
LD HL,SECMSK ; LEAST SIGNIF BITS
AND (HL) ; TO POINT OUT POSISTION IN HOST BUFFER
LD L,A ; READY TO SHIFT
LD H,00H ;
ADD HL,HL ; SHIFT LEFT 7
ADD HL,HL ;
ADD HL,HL ;
ADD HL,HL ;
ADD HL,HL ;
ADD HL,HL ;
ADD HL,HL ; BUFF_OFFSET:=128*(SEEKSEC AND SECMASK);
;HL HAS RELATIVE HOST BUFFER ADDRESS
LD DE,HSTBUF ;
ADD HL,DE ; HL:=HOST BUFFER ADDRESS
EX DE,HL ; NOW IN DE
LD HL,(DMAADR) ; GET/PUT CP/M DATA
LD BC,128 ; LENGTH OF MOVE
EX DE,HL ;
LD A,(READOP) ; WHICH WAY?
OR A ;
JP NZ,RWMOVE ; SKIP IF READ
;WRITE OPERATION, MARK AND SWITCH DIRECTION
LD A,1 ; HOSTWRT:=1;
LD (HSTWRT),A ;
EX DE,HL ; SOURCE/DEST SWAP
PAGE
;BC INITIALLY 128, HL IS SOURCE, DE IS DEST
RWMOVE: LDIR ;
;DATA HAS BEEN MOVED TO/FROM HOST BUFFER
LD A,(WRTYPE) ; WRITE TYPE
CP WRDIR ; TO DIRECTORY?
LD HL,ERFLAG ; IN CASE OF ERRORS
LD A,(HL) ;
PUSH AF ;
OR A ;
JP Z,RRWOPX ;
XOR A ;
LD (HSTACT),A ; DO: SET HOST_ACTIVE:=FALSE
RRWOPX: POP AF ;
LD (HL),0 ;
JP NZ,RRWOP ; NO FURTHER PROCESSING
;CLEAR HOST BUFFER FOR DIRECTORY WRITE
OR A ; ERRORS?
JP NZ,RRWOP ; SKIP IF NOT SO
XOR A ;
LD (HSTWRT),A ; BUFFER WRITTEN
CALL WRTHST ;
LD HL,ERFLAG ;
LD A,(HL) ;
LD (HL),0 ;
RRWOP: POP HL ; RETURN:
LD SP,HL ; SP:=GLOBAL_SP;
RET ;
PAGE
;UTILITY SUBROUTINE FOR 16-BIT COMPARE
;HL=UNATRK OR HSTTRK, COMPARE WITH SEKTRK
TRKCMP: EX DE,HL ;
LD HL,SEKTRK ;
LD A,(DE) ; LOW BYTE COMPARE
CP (HL) ; SAME?
RET NZ ; RETURN IF NOT
;LOW BYTES EQUAL, TEST HIGH LS
INC DE ;
INC HL ;
LD A,(DE) ;
CP (HL) ; SETS FLAGS
RET ;
PAGE
;==========================================================
;= WRITEHOST performs the physical write to the host disk.=
;==========================================================
WRTHST: LD A,(DSKTYP) ; IF: DISK TYPE := HARD
OR A ; THEN: GOTO HARD WRITE HOST
JP NZ,HWRHST ; ELSE:
CALL CHKTRK ;
JP SECWR ;
;==========================================================
;= READHOST performs the physical read from the host disk =
;==========================================================
RDHST: LD A,(UNAMSK) ;
OR A ;
JP NZ,RCHECK ; IF UNAMSK THEN FORCE PRE_READ;
LD (UNACNT),A ;
RCHECK: LD A,(DSKTYP) ; IF: DISK TYPE := HARD
OR A ; THEN: GOTO HARD READ HOST
JP NZ,HRDHST ; ELSE:
CALL CHKTRK ;
JP SECRD ;
PAGE
;==============================================================================
;= CHECK HOST DISK AND TRACK EQUAL TO LAST HOST AND DISK =
;= =
;= S U P P O R T S O N L Y 2 5 6 S E C T O R S A N D T R A C K S =
;==============================================================================
CHKTRK: LD A,(HSTSEC) ;
LD C,A ; SECTOR:=HSTSEC;
LD A,(EOTV) ; HEADNO:=0;
LD B,A ;
DEC A ;
CP C ;
LD A,(HSTDSK) ;
JP NC,SET1 ; IF HSTSEC>EOTV-1 THEN END;
OR 4 ; BEGIN
LD (DSKNO),A ; HEADNO:=1;
LD A,C ; SECTOR:=SECTOR-EOTV;
SUB B ; END;
LD C,A ;
JP SET2 ;
SET1: LD (DSKNO),A ;
SET2: LD B,0 ;
LD HL,(TRANTB) ; TRANSLATE SECTOR
ADD HL,BC ;
LD A,(HL) ;
LD (ACSEC),A ; ACTUAL_SECTOR := TRANSLATED_SECTOR
LD A,(HSTTRK) ;
LD (ACTRA),A ; ACTUAL_TRACK := HOST_TRACK
LD HL,HSTBUF ;
LD (DSKAD),HL ;
LD A,(HSTDSK) ; IF: HOST_DISK := LAST_DISK THEN
LD HL,LSTDSK ;
CP (HL) ; IF: HOST_TRACK := LAST_TRACK THEN
JP NZ,SEEKT ;
LD A,(HSTTRK) ; END
LD HL,LSTTRK ;
CP (HL) ; ELSE:
JP NZ,SEEKT ;
LD A,(HSTTRK+1) ; ELSE:
INC HL ;
CP (HL) ; COMPARE MSB
RET Z ;
PAGE
SEEKT: LD A,(HSTDSK) ; LAST_DISK := HOST_DISK
LD (LSTDSK),A ;
LD HL,(HSTTRK) ; LAST_TRACK := HOST_TRACK
LD (LSTTRK),HL ;
CALL CLFIT ; CLEAR FLOPPY INTERRUPT FLAG
CALL FL07 ; SEEK DRIVE_NO, HEAD AND SECTOR
CALL WFITR ; AWAIT FLOPPY INTERRUPT
LD A,(DSKNO) ;
AND 3 ;
ADD A,32 ; REG. BC := COMPLETION CODE
CP B ; IF STATUS=SEEK_END THEN
RET Z ; RETURN;
RECA: CALL CLFIT ;
CALL FL04 ; RECALIBRATE;
PUSH BC ;
CALL WFITR ;
CALL FL07 ; SEEK(ACTRA);
CALL WFITR ;
POP BC ;
RET ; RETURN;
PAGE
SECRD: LD A,10 ;
LD (REPET),A ;
RPSC: CALL FDSTART ;
CALL CLFIT ;
LD HL,(FORM) ;
LD C,(HL) ;
INC HL ;
LD B,(HL) ;
INC HL ;
CALL FLPW ;
CALL RFDAT ;
CALL WATIR ;
LD C,0 ;
SECCH: LD HL,RSTAB ;
LD A,(HL) ;
AND 0F8H ;
RET Z ;
SCRP: AND 8 ;
JP NZ,SCR1 ;
LD A,(REPET) ;
DEC A ;
LD (REPET),A ;
JP Z,SCR1 ;
CP 5 ;
CALL Z,RECA ;
XOR A ;
CP C ;
JP Z,RPSC ;
JP RPSW ;
SCR1: LD A,C ;
LD (HSTACT),A ;
LD A,1 ;
LD (ERFLAG),A ;
RET ;
PAGE
SECWR: LD A,10 ;
LD (REPET),A ;
RPSW: CALL FDSTART ;
CALL CLFIT ;
LD HL,(FORM) ;
LD C,(HL) ;
INC HL ;
LD B,(HL) ;
INC HL ;
CALL FLPR ;
CALL WFDAT ;
CALL WATIR ;
LD C,1 ;
JP SECCH ;
RFDAT: LD A,6 ;
JP GNCOM ;
WFDAT: LD A,5 ;
JP GNCOM ;
PAGE
FDSTAR: IN A,(SW1) ; PROCEDURE START_FLOPPY_MOTOR;
AND 80H ; BEGIN
; TFj RET Z ; IF MINI_DRIVE THEN BEGIN
DI ; BEGIN
LD HL,(EXCNT1) ; STOPPED:=STOP_TIMER=0;
LD A,L ; STOP_TIMER:=FD_TIME_OUT;
OR H ; IF STOPPED THEN
LD HL,(FDTIMO) ; BEGIN
LD (EXCNT1),HL ; START_MOTOR;
EI ; WAITD(50); (* WAIT 1 SEC *)
RET NZ ; END;
; TFj LD A,1 ; END;
IN A,(SW1) ; TFj jeg bruger motorswitchen på
SET 0,A ; TFj drive C og D også
OUT (SW1),A ; END;
; TFj LD HL,50 ;
LD HL,15 ; TFj virker vist godtnok alligevel
CALL WAITD ;
RET ;
FDSTOP: IN A,(SW1) ; PROCEDURE STOP_FLOPPY_MOTOR;
AND 80H ; BEGIN (* CALLED WHEN STOP_TIMER REACH 0 *)
; TFj RET Z ; IF MINI_DRIVE THEN
; TFj LD A,0 ; STOP_MOTOR;
IN A,(SW1) ; TFj
RES 0,A ;
OUT (SW1),A ; END;
RET ;
WAITD: LD (DELCNT),HL ; PROCEDURE WAITD;
WAIT10: LD HL,(DELCNT) ;
LD A,L ;
OR H ;
JP NZ,WAIT10 ;
RET ;
PAGE
XHOME: LD A,(HSTWRT) ;PATCH FROM DIG. CHECK FOR PENDING WRITE
OR A ;
JR NZ,XHOM01 ;
LD (HSTACT),A ;CLEAR HOST ACTIVE FLAG
;END PATCH FROM DIGITAL.
XHOM01: LD A,(DSKTYP) ; IF: DISK TYPE := HARD
AND A ; THEN:
JP Z,XHOM20 ;
LD A,(SEKDSK) ;
LD (LSTDSK),A ; LAST_DISK:=SEEK_DISK
LD HL,(DPBLCK) ;
LD DE,13 ; GET TRACK OFFSET IN DISK PARMS. BLOCK
ADD HL,DE ;
LD E,(HL) ;
INC HL ;
LD D,(HL) ;
LD (LSTTRK),DE ; LAST_TRACK:=TRACK_OFFSET
CALL STSKFL ; SET UP TASK FILE TO WD1000
CALL HDSEEK ; POSITION HEADS
RET NC ; IF: NO COMMAND ISSUED
CALL WAITHD ; THEN: END
XHOM10: IN A,(HDSTRG) ; ELSE:
AND 10H ; AWAIT HARD DISK INTERRUPT
JP Z,XHOM10 ; AWAIT SEEK COMPLETE
RET ; END.
XHOM20: CALL FDSTAR ; ELSE:
LD A,(SEKDSK) ;
LD (DSKNO),A ;
LD (LSTDSK),A ;
XOR A ;
LD (LSTTRK),A ; LASTTRACK:=0
LD (LSTTRK+1),A ;
CALL CLFIT ; CLEAR FLOPPY INTERRUPT
CALL FL04 ; RECALIBRATE FLOPPY
CALL WFITR ; AWAIT FLOPPY INTERRUPT
RET ;
PAGE
; PROCEDURE WAIT_READY_WRITE;
FL02: IN A,(FDC) ;
AND 0C0H ;
CP 080H ;
JP NZ,FL02 ;
RET ;
; PROCEDURE WAIT_READY_READ;
FL03: IN A,(FDC) ;
AND 0C0H ;
CP 0C0H ;
JP NZ,FL03 ;
RET ;
; PROCEDURE RECALIBRATE;
FL04: CALL FL041 ; RECALIBRATE
CALL WATIR ; WAIT FINISHED
LD A,(RSTAB) ;
BIT 4,A ;
RET Z ; IF EQUIPTMENT CHECK THEN
FL041: CALL CLFIT ;
CALL FL02 ; WAIT_READY_WRITE;
LD A,7 ;
OUT (FDD),A ; RECALIBRATE;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(DSKNO) ;
AND 3 ;
OUT (FDD),A ; SELECT_DRIVE;
RET ;
; PROCEDURE SENSE_DRIVE_STATUS;
FL05: CALL FL02 ; WAIT_READY_WRITE;
LD A,4 ;
OUT (FDD),A ;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(DSKNO) ;
AND 3 ;
OUT (FDD),A ; SELECT_DRIVE;
CALL FL03 ; WAIT_READY_READ;
IN A,(FDD) ;
LD (RSTAB),A ; RSTAB:=INTERRUPT_REGISTER;
RET ;
PAGE
; PROCEDURE SENSE_INTERRUPT_STATUS;
FL06: CALL FL02 ; WAIT_READY_WRITE;
LD A,8 ;
OUT (FDD),A ; SENSE_INT;
CALL FL03 ; WAIT_READY_READ;
IN A,(FDD) ;
LD (RSTAB),A ; RSTAB:=STATUS_REGISTER_0;
AND 0C0H ;
CP 080H ;
RET Z ;
CALL FL03 ; WAIT_READY_READ;
IN A,(FDD) ;
LD (RSTAB+1),A ; RSTAB1:=STATUS_REGISTER_1;
RET ;
; PROCEDURE SEEK;
FL07: CALL FL02 ; WAIT_READY_WRITE;
LD A,15 ;
OUT (FDD),A ; SEEK;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(DSKNO) ; SELECT_DRIVE_AND_HEAD;
AND 3 ;
OUT (FDD),A ;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(ACTRA) ;
OUT (FDD),A ; SELECT_CYLINDER;
RET ;
PAGE
; PROCEDURE READ_RESULT;
RSULT: LD HL,RSTAB ; FOR D:=7 DOWNTO 0 DO
LD D,7 ; BEGIN
RSL1: CALL FL03 ; WAIT_READY_READ;
IN A,(FDD) ; RESULT_TABLE(D):=READCHAR(FDD);
LD (HL),A ;
INC HL ;
LD A,4 ;
RSL2: DEC A ; DELAY;
JP NZ,RSL2 ;
IN A,(FDC) ;
AND 10H ;
RET Z ;
DEC D ;
JP NZ,RSL1 ;
RET ; END;
CLFIT: DI ; PROCEDURE CLEAR_FLOPPY_INTERRUPT;
XOR A ;
LD (FL_FLG),A ;
EI ;
RET ;
WFITR: CALL WATIR ; PROCEDURE WAIT_CLEAR_FD_INTERRUPT;
LD A,(RSTAB) ;
LD B,A ;
LD A,(RSTAB+1) ;
LD C,A ;
CALL CLFIT ;
RET ;
PAGE
WATIR: LD A,(FL_FLG) ; PROCEDURE WAIT_FD_INTERRUPT;
OR A ;
JP Z,WATIR ;
RET ;
FLPR: LD A,5 ; PROCEDURE START_DMA_READ;
DI ;
OUT (DMAMAS),A ; SET_CH1_MASK;
LD A,49H ; MODE:=READ;
FLFW: OUT (DMAMOD),A ; SELECT_MODE;
OUT (DMACBC),A ; CLEAR_BYTECOUNTER;
LD A,(DSKAD+0) ;
OUT (DMAAD1),A ; SET_LOW_ADDRESS;
LD A,(DSKAD+1) ;
OUT (DMAAD1),A ; SET_HIGH_ADDRESS;
LD A,C ;
OUT (DMACN1),A ; SET_LOW_COUNT;
LD A,B ;
OUT (DMACN1),A ; SET_HIGH_COUNT;
LD A,1 ;
OUT (DMAMAS),A ; CLEAR_CH1_MASK;
EI ;
RET ;
FLPW: LD A,5 ; PROCEDURE START_DMA_WRITE;
DI ;
OUT (DMAMAS),A ; SET_CH1_MASK;
LD A,45H ; MODE:=WRITE;
JP FLFW ; GOTO START_DMA_COMMON;
PAGE
GNCOM: PUSH AF ; PROCEDURE GENERAL_COMMAND;
DI ;
CALL FL02 ; WAIT_READY_WRITE;
POP AF ;
LD B,(HL) ;
INC HL ;
ADD A,B ; ADD MF/FMF TO COMMAND;
OUT (FDD),A ;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(DSKNO) ;
OUT (FDD),A ; SELECT_HEAD_AND_DRIVE;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(ACTRA) ;
OUT (FDD),A ; SELECT_CYLINDER;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(DSKNO) ;
RRA ;
RRA ;
AND 3 ;
OUT (FDD),A ; SELECT_HEAD;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(ACSEC) ;
OUT (FDD),A ; SELECT_SECTOR;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(HL) ;
INC HL ;
OUT (FDD),A ; SELECT_NUMBER_TYPE;
CALL FL02 ; WAIT_READY_WRITE;
LD A,(HL) ;
INC HL ;
OUT (FDD),A ; SELECT_FINAL_SECTOR;
CALL FL02 ;
LD A,(HL) ;
OUT (FDD),A ; SELECT_GAP_LENGTH;
CALL FL02 ;
LD A,(DTLV) ;
OUT (FDD),A ; SELECT_DATA_LENGTH;
EI ;
RET ;
PAGE
;========================================================
;= UP765 FLOPPY DISK CONTROLLER INTERRUPT ROUTINE =
;========================================================
FLITR: LD (SP_SAV),SP ; SAVE ACCUMULATOR AND FLAGS
LD SP,ISTACK ; SAVE REGISTERS
PUSH AF ;
PUSH BC ;
PUSH DE ; ESTABLISH LOCAL STACK
PUSH HL ; SAVE GLOBAL STACK POINTER
LD A,0FFH ;
LD (FL_FLG),A ; FLOPPY_BUSY:=FALSE;
LD A,5 ;
FITX: DEC A ;
JP NZ,FITX ;
IN A,(FDC) ;
AND 16 ;
JP NZ,FIT1 ;
CALL FL06 ; SENSE_INTERRUPT_STATUS;
JP FIT2 ;
FIT1: CALL RSULT ; READ_RESULT;
FIT2: POP HL ;
POP DE ; RESTORE GLOBAL STACKPOINTER
POP BC ; RESTORE REGISTERS
POP AF ; RESTORE ACCUMULATOR AND FLAGS
LD SP,(SP_SAV) ;
EI ;
RETI ;
PAGE
«eof»