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:

; ============================================================================

0

Publication author

offline 5 hours

mus@shi9

0
Comments: 1160Publics: 2778Registration: 06-03-2017

Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
scenex
8 years ago

Good to know Mr.Spiv, thanks for the information.
Could imagine that many loaders back in the time did not consider this “detail” and therefore led to different sorts of hangs.. About what percentage of disk drives are we talking here?

0
mr.spiv
Reply to  scenex
8 years ago

I have no idea.. Must have not been too common. My friend had an external drive with this issue -> got me aware of it quite early. I recall some later a1200s had the same?

0
scenex
Reply to  mr.spiv
8 years ago

Ok thanks Mr.Spiv, so I’ll maybe soon try to rewrite it to take this issue into consideration 🙂

0
mr.spiv
Reply to  scenex
8 years ago

I’ll have soon one kinky loader commented in tutorials, which uses this mechanism. (nb. “soon” to be considered with care, my last soon took 8 years 😉

0
mr.spiv
8 years ago

Nice 😉 Btw, there were disk drives around that never set DSKRDY but were perfectly usable. For those you just need to wait for 500ms and proceed. I did check for disk presence by stepping the head and then checking DSKCHANGE. Afair that was more reliable.

0
Authorization
*
*

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Registration
*
*
*

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Password generation

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

0
Would love your thoughts, please comment.x
()
x