init: move.w $dff01c,oldintena move.w $dff01e,oldintreq bset #7,oldintena bset #7,oldintreq move.w #$7fff,$dff09a ; interrupts aus. move.w #$7fff,$dff09c ;
;****************************************************************
lea $dff000,a6 lea buffer(pc),a0 lea mfmbuffer,a2 move.l #$4200,d0 move.l #$59,d1 move.l #$0,d2 move.b #$0,d5 jsr TRACKLOADER
;****************************************************************
move.w oldintena(pc),$dff09a move.w oldintreq(pc),$dff09c moveq #0,d0 rts
oldintena: dc.w 0 oldintreq: dc.w 0 buffer: blk.b 130000,0 mfmbuffer: blk.w 6400,0
; ============================================================================
; HARDWARE-DISKLOADER (c) ALPHA ONE 2005 (MULTIDRIVE VERSION) ; *************************************************************************** ; IMPROVED TO READ FROM ODD BYTEPOSITIONS. ; PRO VERSION -> WITH TRACKCOUNTER. ; ; ADDITIONS AND CHANGES BY SCENEX ; *************************************************************************** ; – MULTI DRIVE SUPPORT (DF0-DF3) ; – SWITCHING OFF DRIVE MOTORS AFTER TRACKLOADING ; – DELAY OF 500 MS BEFORE CHECKING DSKRDY FLAG ; – TURNING OFF MOTORS WHEN DSKRDY CHECK FAILED AND RETURNING TO CALLER ; ; IN: A6=$DFF000 ; A2=MFMBUFFER.L ; A0=BUFFER.L ; ; D0=LENGTH.L ; D1=TRACKNR.L ; D2=BYTEOFFSET.L ; D5=DISKDRIVE.B
TRACKLOADER: LEA $BFD100,A4 ;DRIVESELECT REGISTER LEA $BFE001,A5 ;DRIVESTATUS REGISTER
AND.L #$FF,D5 ;CLEAR D5 EXCEPT FIRST BYTE
LEA DRIVENUMBER(PC),A1 ;STORE DRIVENUMBER MOVE.B D5,(A1) ;
MOVE.B D5,D3 ADD.B #3,D3
LEA DRIVEBIT(PC),A1 ;STORE DRIVEBIT MOVE.B D3,(A1) ;
BSET D3,(A4) ;SET BIT DRIVENUMBER ANDI.B #$7F,(A4) ;TURN ON MOTOR BCLR D3,(A4) ;TURN ON MOTOR ON GIVEN DRIVE
BSR DELAYLONG
BTST #5,(A5) ;CHECK FOR DISK READY BEQ PROCEED ;
BSR STOPDRIVE ;DISK NOT READY – RETURN RTS ;
PROCEED: LEA CURRENTTRACK(PC),A3 ADD.B D5,D5 ;MULTIPLY BY 2 BECAUSE 2 BYTES ADDA.W D5,A3 ;ADD OFFSET TO CURRENTTRACK
MOVEQ #0,D7 ;D7 = BYTECOUNTER ADD.L D2,D0 ;BYTES TO READ + BYTEOFFSET MOVE.L D0,D3 DIVS.W #$1600,D3 SWAP D3 TST.W D3 BNE.B NORMAL SWAP D3 SUBQ.B #1,D3 BRA.B CHECKER NORMAL: SWAP D3 CHECKER: MOVE.B D3,1(A3)
CMP.B #$FF,(A3) BNE.B MOVETOCYLINDER MOVE.B #0,(A3) BSET #1,(A4) ;CHOSE DIRECTION TOWARDS 0 MOVETOZERO: BTST #4,(A5) ;HEAD ON CYLINDER 0? BEQ.B MOVETOCYLINDER BSR.W MOVEHEAD ;MOVE HEAD + DELAY BRA.B MOVETOZERO
MOVETOCYLINDER: BSET #2,(A4) ;CHOOSE HEAD HIGH BTST #0,D1 ;EVEN OR ODD TRACK? BEQ.B HEADOK ;TRACK IS EVEN – ALRIGHT! BCLR #2,(A4) ;CHOOSE HEAD LOW HEADOK: MOVEQ #0,D3 MOVEQ #0,D5 MOVE.B D1,D3 ;NEW TRACKNUM -> D3 MOVE.B (A3),D5 ;CURRENT TRACK -> D5 MOVE.B D1,(A3) ;REPLACE CURRENT TRACK LSR.W #1,D3 ;GET CYLINDER NUM NEW TRACK LSR.W #1,D5 ;GET CYLINDER NUM CUR TRACK SUB.W D3,D5 BEQ.B READTRACK BMI.B OTHERDIRECTION BSET #1,(A4) ;CHOOSE DIRECTION TOWARDS 0 BRA.B CHOSEN OTHERDIRECTION: BCLR #1,(A4) ;CHOOSE DIRECTION OUTWARDS 0 NEG.W D5 CHOSEN: BSR.W MOVEHEAD SUBQ.B #1,D5 BNE.B CHOSEN
READTRACK: BSR.W DISKREADY ;EINEN TRACK LESEN MOVE.W #$8210,$96(A6) ;DMACON MOVE.W #$7F00,$9E(A6) ;ADKCON MOVE.W #$8500,$9E(A6) ;ADKCON MOVE.W #$4489,$7E(A6) ;DSKSYNC MOVE.W #$4000,$24(A6) ;DSKLEN MOVE.L A2,$20(A6) ;DSKPTH MOVE.W #$9900,$24(A6) ;DSKLEN MOVE.W #$9900,$24(A6) ;DSKLEN MOVE.W #$2,$9C(A6) ;INTREQ TRACKREADY: BTST #1,$DFF01F BEQ.B TRACKREADY MOVE.W #$4000,$24(A6)
MOVEQ #0,D5 ;DECODE TRACK DECODE: MOVE.L A2,A1 ;============ MOVE.L #$55555555,D4 FINDSYNC: CMP.W #$4489,(A1)+ BNE.B FINDSYNC CMP.W #$4489,(A1) BEQ.B FINDSYNC MOVE.L (A1),D3 MOVE.L 4(A1),D1 AND.L D4,D3 AND.L D4,D1 ASL.L #1,D3 OR.L D1,D3 ROR.L #8,D3 CMP.B D5,D3 BEQ.B SECTORFOUND ADD.L #1086,A1 ;$43E MFM SECTOR LENGTH BRA.B FINDSYNC SECTORFOUND: ADD.L #56,A1 MOVE.L #(512/4)-1,D6 DECODESECTOR: MOVE.L 512(A1),D1 MOVE.L (A1)+,D3 AND.L D4,D3 AND.L D4,D1 ASL.L #1,D3 OR.L D1,D3 LEA STORE(PC),A3 MOVE.L D3,(A3)
MOVEQ #4-1,D3 LOOP: CMP.L D7,D0 BEQ.B READREADY CMP.L D7,D2 BGT.B BELOW MOVE.B (A3),(A0)+ BELOW: ADDQ.L #1,A3 ADDQ.L #1,D7 DBF D3,LOOP
DBF D6,DECODESECTOR ADDQ.B #1,D5 CMP.B #11,D5 BNE.W DECODE
TRACKDONE: CMP.L D7,D0 ;TRACK DONE, GET ONTO NEXT. BEQ.B READREADY ;========================== BTST #2,(A4) BEQ.B ONTONEXT BCLR #2,(A4) BSR.W DELAYSHORT BRA.W READTRACK ONTONEXT: BSET #2,(A4) BSR.W DELAYSHORT BCLR #1,(A4) BSR.W MOVEHEAD BRA.W READTRACK
READREADY: MOVEM.L D6/A0,-(A7) LEA DRIVENUMBER(PC),A0 MOVEQ #0,D6 MOVE.B (A0),D6 ADD.B D6,D6 BSR STOPDRIVE LEA CURRENTTRACK(PC),A3 ADDA.W D6,A3 MOVEM.L (A7)+,D6/A0
MOVE.B 1(A3),D0 ADD.B D0,(A3) RTS
STOPDRIVE: MOVEM.L D0/D6/A0,-(A7) LEA DRIVEBIT(PC),A0 MOVE.B (A0),D6 MOVE.B #$80,D0 BSET D6,D0 ORI.B D0,(A4)
MOVE.B #$FF,D0 BCLR D6,D0 ANDI.B D0,(A4)
MOVE.B #0,D0 BSET D6,D0 ORI.B D0,(A4) MOVEM.L (A7)+,D0/D6/A0 RTS
DELAYSHORT: CLR.B $300(A4) ;BFD400 CIAB TIMER A LOW BYTE (TALO) MOVE.B #$19,$400(A4) ;BFD500 CIAB TIMER A HIGH BYTE (TAHI) MOVE.B #$1,$D00(A4) ;BFDE00 CIAB CONTROL REGISTER A (CRA) WAITSHORT: BTST #0,$C00(A4) ;BFDD00 CIAB INTERRUPT CONTROL REGISTER (ICR) BEQ.B WAITSHORT BCLR #0,$D00(A4) ;BFDE00 CIAB CONTROL REGISTER A (CRA) RTS
DELAYLONG: MOVEQ #$6,D6 DELAYLONGLOOP: CLR.B $300(A4) ;BFD400 CIAB TIMER A LOW BYTE (TALO) MOVE.B #$FF,$400(A4) ;BFD500 CIAB TIMER A HIGH BYTE (TAHI) MOVE.B #$1,$D00(A4) ;BFDE00 CIAB CONTROL REGISTER A (CRA) WAITLONG: BTST #0,$C00(A4) ;BFDD00 CIAB INTERRUPT CONTROL REGISTER (ICR) BEQ.B WAITLONG BCLR #0,$D00(A4) ;BFDE00 CIAB CONTROL REGISTER A (CRA) DBF D6,DELAYLONGLOOP RTS
DISKREADY: BTST #5,(A5) ;WAIT FOR DISK-READY BNE.B DISKREADY ;=================== RTS
MOVEHEAD: BCLR #0,(A4) BSR.W DELAYSHORT BSET #0,(A4) BSR.W DELAYSHORT RTS
CURRENTTRACK: DC.B $FF,0,$FF,0,$FF,0,$FF,0 STORE: DC.L 0 DRIVENUMBER: DC.B 0 DRIVEBIT DC.B 0
TRACKLOADERENDE:
; ============================================================================