******************************************************************************* * trackdisk.device.S Written by Readysoft. * Copyright 1992,1993,1994 RS. All rights reserved. 1992.02.23.-1994.07.18. * v2.0. ******************************************************************************* ******************************************************************************* * Macros ******************************************************************************* ;------------------------------------------------------------------------------ ; TrackDiskName Macro ;------------------------------------------------------------------------------ TRD.NAM MACRO DC.B 'trackdisk.device',0 EVEN ENDM ******************************************************************************* * DEV Macro ******************************************************************************* TRD.DEV MACRO ******************************************************************************* * Constant Definitions ******************************************************************************* ;------------------------------------------------------------------------------ ; Drive ;------------------------------------------------------------------------------ trd_NumUnits EQU 4 # of units trd_NumCyls EQU 82 # of cylinders trd_NumHeads EQU 2 # of heads trd_NumTracks EQU trd_NumCyls*trd_NumHeads # of tracks trd_NumSecs EQU 12 # of sectors per track trd_SecSize EQU 512 bytes per sector trd_TrackSize EQU trd_SecSize*trd_NumSecs bytes per track ;------------------------------------------------------------------------------ ; Buffers ;------------------------------------------------------------------------------ trd_DMABuffSize EQU $3200 size of DMA buffer trd_BuffSize EQU $1800 size of buffer ;------------------------------------------------------------------------------ ; Other ;------------------------------------------------------------------------------ trd_StepDelay EQU $aff cia delay ;------------------------------------------------------------------------------ ; Error Codes ;------------------------------------------------------------------------------ trd_er_OK EQU $00000000 all right trd_er_NoMem EQU $80070001 no memory for buffer trd_er_NoBuffer EQU $00070002 no DMA buffer trd_er_NoDisk EQU $00070003 no disk in drive trd_er_WrProt EQU $00070004 write protected trd_er_UnitNum EQU $00070005 bad unitnum trd_er_Seek EQU $00070006 invalid position trd_er_Verify EQU $00070007 verify error trd_er_Decoder EQU $00070008 unable to decode trd_er_UnDef EQU $8007ffff undefined error ******************************************************************************* * Varibles ******************************************************************************* RSRESET trd_HeadPos RS.W 1 head position trd_TrackIn RS.W 1 track in buffer trd_DMABuffer RS.L 1 $3200 byte DMA buffer trd_Buffer RS.L 1 $1800 byte buffer trd_Updated RS.B 1 0 if updated trd_UserBuffOn RS.B 1 0 if user buffers trd_SizeOf RS.B 0 ******************************************************************************* * Routine Offsets ******************************************************************************* RSRESET RS.B -6 trd_Init RS.B -6 trd_Format RS.B -6 trd_Motor RS.B -6 trd_ReadSector RS.B -6 trd_WriteSector RS.B -6 trd_Status RS.B -6 trd_UserBuffers RS.B -6 trd_AutoBuffers RS.B -6 ******************************************************************************* * Code ******************************************************************************* jmp trd.AutoBuffers jmp trd.UserBuffers jmp trd.Status jmp trd.WriteSector jmp trd.ReadSector jmp trd.Motor jmp trd.Format jmp trd.Init trackdisk.dev BLK.B trd_SizeOf,0 EVEN ;------------------------------------------------------------------------------ ; Init NoOp ;------------------------------------------------------------------------------ trd.Init movem.l d0/a0/a5,-(a7) lea trackdisk.dev(pc),a5 move.l a5,a0 clear varible area move.w #trd_SizeOf-1,d0 .Clear clr.b (a0)+ dbf d0,.Clear move.w #-1,trd_HeadPos(a5) head not positioned move.w #-1,trd_TrackIn(a5) no track loaded clr.b trd_Updated(a5) updated st trd_UserBuffOn(a5) no user buffers bsr trd.MotorOff movem.l (a7)+,d0/a0/a5 rts ;------------------------------------------------------------------------------ ; Format UnitNum,Verify(d1,d2) --> Error(d0) ;------------------------------------------------------------------------------ trd.Format movem.l d1-d3/a0/a5,-(a7) lea trackdisk.dev(pc),a5 bsr trd.InitBuffers move.l trd_Buffer(a5),a0 clear databuffer move.w #383,d3 .Clear move.l #' I L',(a0)+ move.l #'ove ',(a0)+ move.l #'Jess',(a0)+ move.l #'y. ',(a0)+ dbf d3,.Clear move.l #trd_NumTracks,d1 number of tracks .Cycle bsr trd.WriteTrack format tst.l d0 error ? bne.s .Exit tst.l d2 verify ? beq.s .NoVerify bsr trd.ReadTrack load tst.l d0 error ? bne.s .Exit move.l trd_Buffer(a5),a0 verify move.w #383,d3 .Verify cmpi.l #' I L',(a0)+ bne.s .Error cmpi.l #'ove ',(a0)+ bne.s .Error cmpi.l #'Jess',(a0)+ bne.s .Error cmpi.l #'y. ',(a0)+ bne.s .Error dbf d3,.Verify .NoVerify dbf d1,.Cycle .Exit bsr trd.FreeBuffers movem.l (a7)+,d1-d3/a0/a5 rts .Error move.l #trd_er_Verify,d0 bra.s .Exit ;------------------------------------------------------------------------------ ; Motor UnitNum(d1) --> Error(d0) ;------------------------------------------------------------------------------ trd.Motor movem.l d1-d2/a5,-(a7) lea trackdisk.dev(pc),a5 tst.b d1 off ? bmi .Off bsr trd.Select select drive bsr trd.Status get drive status tst.l d2 disk inserted ? bne.s .DiskIn bsr trd.MoveHead move head bsr trd.Status get drive status tst.l d2 disk inserted ? beq.s .NoDisk .DiskIn bsr trd.MotorOn motor on moveq #0,d0 all right .Exit movem.l (a7)+,d1-d2/a5 rts .Off bsr trd.MotorOff motor off moveq #0,d0 all right bra.s .Exit .NoDisk move.l #trd_er_NoDisk,d0 no disk in drive ! bra.s .Exit ;------------------------------------------------------------------------------ ; ReadSector Addr,Sector,Len(a0,d0,d1) --> Error(d0) ;------------------------------------------------------------------------------ trd.ReadSector movem.l d1-d2/a0/a5,-(a7) lea trackdisk.dev(pc),a5 bsr trd.InitBuffers move.l d0,d2 subq.w #1,d1 .Loop move.l d2,d0 bsr trd.RdOneSect read one sector tst.l d0 error ? bne.s .Exit addq.w #1,d2 next sector lea trd_SecSize(a0),a0 dbf d1,.Loop moveq #0,d0 all right .Exit bsr trd.FreeBuffers movem.l (a7)+,d1-d2/a0/a5 rts ;------------------------------------------------------------------------------ ; WriteSector Addr,Sector,Len(a0,d0,d1) --> Error(d0) ;------------------------------------------------------------------------------ trd.WriteSector movem.l d1-d2/a0/a5,-(a7) lea trackdisk.dev(pc),a5 bsr trd.InitBuffers move.l d0,d2 subq.w #1,d1 .Loop move.l d2,d0 bsr trd.WrOneSect write one sector tst.l d0 error ? bne.s .Exit addq.w #1,d2 next sector lea trd_SecSize(a0),a0 dbf d1,.Loop bsr trd.Update .Exit bsr trd.FreeBuffers movem.l (a7)+,d1-d2/a0/a5 rts ;------------------------------------------------------------------------------ ; Status UnitNum(d1) --> Changed,WrProt(d2,d3) ;------------------------------------------------------------------------------ trd.Status movem.l d1/a5,-(a7) lea trackdisk.dev(pc),a5 moveq #-1,d2 0 if changed moveq #-1,d3 0 if protected bsr trd.Select select drive btst #cia_APRA_b_CHNG,cia_APRA /CHNG ? bne.s .CHNGOK moveq #0,d2 .CHNGOK btst #cia_APRA_b_WPRO,cia_APRA /WPRO ? bne.s .WPROOK moveq #0,d3 .WPROOK movem.l (a7)+,d1/a5 rts ;------------------------------------------------------------------------------ ; UserBuffers DMABuffer,Buffer(a0,a1) ;------------------------------------------------------------------------------ trd.UserBuffers move.l a5,-(a7) lea trackdisk.dev(pc),a5 move.l a0,trd_DMABuffer(a5) move.l a1,trd_Buffer(a5) clr.b trd_UserBuffOn(a5) user buffers on move.l (a7)+,a5 rts ;------------------------------------------------------------------------------ ; AutoBuffers NoOp ;------------------------------------------------------------------------------ trd.AutoBuffers move.l a5,-(a7) lea trackdisk.dev(pc),a5 st trd_UserBuffOn(a5) user buffers off move.l (a7)+,a5 rts ******************************************************************************* * Private Routines ******************************************************************************* ;------------------------------------------------------------------------------ ; Select UnitNum(d1) ;------------------------------------------------------------------------------ trd.Select move.b #$fd,cia_BPRB select nop nop move.b #$f5,cia_BPRB drive0 nop nop rts ;------------------------------------------------------------------------------ ; MotorOn UnitNum(d1) ;------------------------------------------------------------------------------ trd.MotorOn move.b #$7d,cia_BPRB motor on nop nop move.b #$75,cia_BPRB drive0 nop nop rts ;------------------------------------------------------------------------------ ; MotorOff NoOp ;------------------------------------------------------------------------------ trd.MotorOff move.b #$fd,cia_BPRB motor off nop nop move.b #$f5,cia_BPRB drive0 nop nop rts ;------------------------------------------------------------------------------ ; DiskReady NoOp ;------------------------------------------------------------------------------ trd.DiskReady btst #cia_APRA_b_RDY,cia_APRA disk ready ? bne.s trd.DiskReady rts ;------------------------------------------------------------------------------ ; Delay NoOp ;------------------------------------------------------------------------------ trd.Delay move.l d0,-(a7) move.w #trd_StepDelay,d0 jsr cia.Delay move.l (a7)+,d0 rts ;------------------------------------------------------------------------------ ; Track0 NoOp ;------------------------------------------------------------------------------ trd.Track0 move.l a5,-(a7) lea trackdisk.dev(pc),a5 .Loop btst #cia_APRA_b_TK0,cia_APRA track 0 ? beq.s .OK bsr trd.HeadMinus bra.s .Loop .OK bsr trd.HeadPlus bsr trd.HeadPlus clr.w trd_HeadPos(a5) track 4 = pos 0 move.l (a7)+,a5 rts ;------------------------------------------------------------------------------ ; Seek HeadPos(d1) --> Error(d0) ;------------------------------------------------------------------------------ trd.Seek movem.l d1/a5,-(a7) lea trackdisk.dev(pc),a5 and.l #$ff,d1 cmpi.w #trd_NumTracks,d1 Pos > NumTracks ? bgt.s .Error error ! tst.w trd_HeadPos(a5) bpl.s .Real bsr trd.Track0 .Real move.w trd_HeadPos(a5),d0 move.w d1,trd_HeadPos(a5) bset #cia_BPRB_b_SIDE,cia_BPRB lsr.w #1,d0 lsr.w #1,d1 bcc.s .Side0 bclr #cia_BPRB_b_SIDE,cia_BPRB .Side0 sub.w d0,d1 beq.s .OK bmi.s .Backw .Forw subq.w #1,d1 bmi.s .OK bsr trd.HeadPlus bra.s .Forw .Backw neg.w d1 .Loop subq.w #1,d1 bmi.s .OK bsr trd.HeadMinus bra.s .Loop .OK moveq #0,d1 move.w trd_HeadPos(a5),d1 moveq #0,d0 all right .Exit movem.l (a7)+,d1/a5 rts .Error move.l #trd_er_Seek,d0 invalid position bra.s .Exit ;------------------------------------------------------------------------------ ; HeadPlus NoOp ;------------------------------------------------------------------------------ trd.HeadPlus bclr #cia_BPRB_b_DIR,cia_BPRB bclr #cia_BPRB_b_STEP,cia_BPRB nop nop bset #cia_BPRB_b_STEP,cia_BPRB bsr trd.Delay rts ;------------------------------------------------------------------------------ ; HeadMinus NoOp ;------------------------------------------------------------------------------ trd.HeadMinus bset #cia_BPRB_b_DIR,cia_BPRB bclr #cia_BPRB_b_STEP,cia_BPRB nop nop bset #cia_BPRB_b_STEP,cia_BPRB bsr trd.Delay rts ;------------------------------------------------------------------------------ ; MoveHead NoOp ;------------------------------------------------------------------------------ trd.MoveHead movem.l d0-d1,-(a7) move.w trd_HeadPos(a5),d1 move head and.w #3,d1 eor.w #2,d1 bsr trd.Seek movem.l (a7)+,d0-d1 rts ;------------------------------------------------------------------------------ ; ReadTrack TNum(d1) --> Error(d0) ;------------------------------------------------------------------------------ trd.ReadTrack movem.l d1/a5/a6,-(a7) lea trackdisk.dev(pc),a5 lea cus_BASE,a6 bsr trd.Seek seek tst.l trd_DMABuffer(a5) beq .Error bsr trd.CalcSync move.w d0,cus_DSKSYNC(a6) syncron move.w #$7fff,cus_ADKCON(a6) move.w #$9500,cus_ADKCON(a6) move.w #$8210,cus_DMACON(a6) bsr trd.DiskReady move.l trd_DMABuffer(a5),d0 move.l d0,cus_DSKPT(a6) Address move.w #$9900,cus_DSKLEN(a6) $3200 byte move.w #$9900,cus_DSKLEN(a6) move.w #2,cus_INTREQ(a6) .Wait move.w cus_INTREQR(a6),d1 btst #1,d1 beq.s .Wait move.w #$0000,cus_DSKLEN(a6) move.w #$0010,cus_DMACON(a6) bsr trd.DecodeTrack decode track tst.l d0 error ? bmi.s .Exit move.w trd_HeadPos(a5),d0 move.w d0,trd_TrackIn(a5) moveq #0,d0 .Exit movem.l (a7)+,d1/a5/a6 rts .Error move.l #trd_er_NoBuffer,d0 bra.s .Exit ;------------------------------------------------------------------------------ ; DecodeTrack NoOp --> Error(d0) ;------------------------------------------------------------------------------ trd.DecodeTrack movem.l d1-d2/a0-a2/a5,-(a7) lea trackdisk.dev(pc),a5 bsr trd.CalcSync syncron word in d0 move.l trd_DMABuffer(a5),a1 searching cmp.w (a1)+,d0 found ? bne .Error move.l a1,a2 checksum address move.l trd_Buffer(a5),a0 buffer address move.w #1535,d2 1535 long = 6144 byte .SectIn bsr trd.LongIn longword in eor.l #'KJKJ',d0 decode rol.w #2,d0 swap d0 ror.w #2,d0 move.l d0,(a0)+ next longword dbf d2,.SectIn move.w #3071,d1 3072 longwords bsr trd.CheckSum move.l d0,d1 checksum in d1 bsr trd.LongIn longword in cmp.l d0,d1 checksum error ? bne.s .Error bsr trd.LongIn longword in cmp.l d0,d1 checksum error ? bne.s .Error moveq #0,d0 .Exit movem.l (a7)+,d1-d2/a0-a2/a5 rts .Error move.l #trd_er_Decoder,d0 unable to decode bra.s .Exit ;------------------------------------------------------------------------------ ; LongIn NoOp --> Long(d0) ;------------------------------------------------------------------------------ trd.LongIn move.l d1,-(a7) bsr trd.HLongIn odd bits in lsl.l #1,d0 move.l d0,d1 bsr trd.HLongIn even bits in or.l d1,d0 move.l (a7)+,d1 rts ;------------------------------------------------------------------------------ ; HLongIn NoOp --> HLong(d0) ;------------------------------------------------------------------------------ trd.HLongIn move.l (a1)+,d0 and.l #$55555555,d0 even bits only rts ;------------------------------------------------------------------------------ ; WriteTrack TNum(d1) --> Error(d0) ;------------------------------------------------------------------------------ trd.WriteTrack movem.l d1/a5/a6,-(a7) lea trackdisk.dev(pc),a5 lea cus_BASE,a6 bsr trd.Seek seek tst.l trd_DMABuffer(a5) beq .Error bsr trd.CodeTrack code move.w #$7fff,cus_ADKCON(a6) move.w #$9100,cus_ADKCON(a6) move.w #$8210,cus_DMACON(a6) bsr trd.DiskReady move.l trd_DMABuffer(a5),d0 move.l d0,cus_DSKPT(a6) Address move.w #$d900,cus_DSKLEN(a6) $3200 byte move.w #$d900,cus_DSKLEN(a6) move.w #2,cus_INTREQ(a6) .Wait move.w cus_INTREQR(a6),d1 btst #1,d1 beq.s .Wait move.w #$0000,cus_DSKLEN(a6) move.w #$0010,cus_DMACON(a6) moveq #0,d0 all right .Exit movem.l (a7)+,d1/a5/a6 rts .Error move.l #trd_er_NoBuffer,d0 bra.s .Exit ;------------------------------------------------------------------------------ ; CodeTrack NoOp ;------------------------------------------------------------------------------ trd.CodeTrack movem.l d0-d2/a0-a2/a5,-(a7) lea trackdisk.dev(pc),a5 move.l trd_DMABuffer(a5),a1 moveq #115,d0 116*4=464 byte header .Buffer move.l #$aaaaaaaa,(a1)+ dbf d0,.Buffer move.l trd_Buffer(a5),a0 data address moveq #0,d0 half-long (0) out bsr trd.HLongOut bsr trd.CalcSync move.w d0,(a1)+ syncron out move.w d0,(a1)+ syncron out move.l a1,a2 checksum address move.w #1535,d2 1536 long = 6144 byte .SectOut move.l (a0)+,d0 next longword rol.w #2,d0 code swap d0 ror.w #2,d0 eor.l #'KJKJ',d0 bsr trd.LongOut longword out dbf d2,.SectOut move.w #3071,d1 3072 longword bsr trd.CheckSum bsr trd.LongOut checksum out bsr trd.LongOut checksum out moveq #0,d0 bsr trd.LongOut null longwords out bsr trd.LongOut bsr trd.LongOut movem.l (a7)+,d0-d2/a0-a2/a5 rts ;------------------------------------------------------------------------------ ; LongOut Long(d0) ;------------------------------------------------------------------------------ trd.LongOut movem.l d0-d1,-(a7) move.l d0,d1 lsr.l #1,d0 bsr trd.HLongOut out odd bits move.l d1,d0 bsr trd.HLongOut out even bits movem.l (a7)+,d0-d1 rts ;------------------------------------------------------------------------------ ; HLongOut HLong(d0) ;------------------------------------------------------------------------------ trd.HLongOut movem.l d0-d2,-(a7) and.l #$55555555,d0 even bits only move.l d0,d2 eori.l #$55555555,d2 complement move.l d2,d1 lsl.l #1,d2 _word <-- lsr.l #1,d1 _word --> bset #31,d1 and.l d2,d1 --> and <-- or.l d1,d0 MFM code in d0 btst #0,-1(a1) last bit set ? beq.s .Last0 bclr #31,d0 clear MSB .Last0 move.l d0,(a1)+ write logword movem.l (a7)+,d0-d2 rts ;------------------------------------------------------------------------------ ; ChechSum Address,Length(a2,d1) --> CheckSum(d0) ;------------------------------------------------------------------------------ trd.CheckSum movem.l d1-d2/a2,-(a7) calculate checksum lsr.w #2,d1 subq.w #1,d1 moveq #0,d0 .Loop move.l (a2)+,d2 eor.l d2,d0 dbf d1,.Loop and.l #$55555555,d0 movem.l (a7)+,d1-d2/a2 rts ;------------------------------------------------------------------------------ ; CalcSync NoOp --> SyncronWord(d0) ;------------------------------------------------------------------------------ trd.CalcSync movem.l a0/a5,-(a7) lea trackdisk.dev(pc),a5 move.w trd_HeadPos(a5),d0 and.w #$000f,d0 lsl.w #1,d0 lea trd.da.DiskSync(pc),a0 move.w 0(a0,d0.w),d0 movem.l (a7)+,a0/a5 rts ;------------------------------------------------------------------------------ ; RdOneSect Addr,Sector(a0,d0) --> Error(d0) ;------------------------------------------------------------------------------ trd.RdOneSect movem.l d1-d2/a0-a1/a5,-(a7) lea trackdisk.dev(pc),a5 move.l d0,d2 divu #trd_NumSecs,d2 move.l d2,d1 and.l #$ffff,d1 # of track clr.w d2 swap d2 # of sector in track cmp.w trd_TrackIn(a5),d1 is this track in ? beq .In bsr trd.ReadTrack read this track tst.l d0 error ? bne .Exit .In move.l trd_Buffer(a5),a1 buffer address mulu #trd_SecSize,d2 lea 0(a1,d2.l),a1 sector address moveq #127,d2 .Copy move.l (a1)+,(a0)+ dbf d2,.Copy moveq #0,d0 all right .Exit movem.l (a7)+,d1-d2/a0-a1/a5 rts ;------------------------------------------------------------------------------ ; WrOneSect Addr,Sector(a0,d0) --> Error(d0) ;------------------------------------------------------------------------------ trd.WrOneSect movem.l d1-d2/a0-a1/a5,-(a7) lea trackdisk.dev(pc),a5 move.l d0,d2 divu #trd_NumSecs,d2 move.l d2,d1 and.l #$ffff,d1 # of track clr.w d2 swap d2 # of sector in track cmp.w trd_TrackIn(a5),d1 is this track in ? beq .In bsr trd.Update update last changes bsr trd.ReadTrack read this track tst.l d0 error ? bne .Exit .In move.l trd_Buffer(a5),a1 buffer address mulu #trd_SecSize,d2 lea 0(a1,d2.l),a1 sector address moveq #127,d2 .Copy move.l (a0)+,(a1)+ dbf d2,.Copy st trd_Updated(a5) not updated ! moveq #0,d0 all right .Exit movem.l (a7)+,d1-d2/a0-a1/a5 rts ;------------------------------------------------------------------------------ ; Update NoOp --> Error(d0) ;------------------------------------------------------------------------------ trd.Update movem.l d1/a5,-(a7) lea trackdisk.dev(pc),a5 tst.b trd_Updated(a5) updated ? beq.s .Updated moveq #0,d1 move.w trd_TrackIn(a5),d1 bsr trd.WriteTrack bra.s .Exit .Updated moveq #0,d0 all right .Exit movem.l (a7)+,d1/a5 rts ;------------------------------------------------------------------------------ ; InitBuffers NoOp ;------------------------------------------------------------------------------ trd.InitBuffers movem.l d0-d1/a0/a5,-(a7) lea trackdisk.dev(pc),a5 tst.b trd_UserBuffOn(a5) user buffer on ? beq .Exit move.l #trd_DMABuffSize,d0 allocate DMA buffer move.l #mem_ty_Chip,d1 in Chip-Mem jsr mem.AllocMem tst.l d0 beq.s .NoMem move.l a0,trd_DMABuffer(a5) store buffer address move.w #trd_DMABuffSize/4-1,d0 fill DMA buffer .FillDB move.l #$aaaaaaaa,(a0)+ dbf d0,.FillDB move.l #trd_BuffSize,d0 allocate buffer move.l #mem_ty_Public,d1 in Public-Mem jsr mem.AllocMem tst.l d0 beq.s .NoMem move.l a0,trd_Buffer(a5) store buffer address move.w #trd_BuffSize/4-1,d0 fill buffer .FillB clr.l (a0)+ dbf d0,.FillB .Exit move.w #-1,trd_TrackIn(a5) no track in buffer movem.l (a7)+,d0-d1/a0/a5 rts .NoMem move.l #trd_er_NoMem,d0 no memory for buffer jmp sys.FatalError ;------------------------------------------------------------------------------ ; FreeBuffers NoOp ;------------------------------------------------------------------------------ trd.FreeBuffers movem.l d0/a1/a5,-(a7) lea trackdisk.dev(pc),a5 tst.b trd_UserBuffOn(a5) user buffer on ? beq .Exit move.l trd_DMABuffer(a5),a1 free DMABuffer move.l #trd_DMABuffSize,d0 jsr mem.FreeMem move.l trd_Buffer(a5),a1 free Buffer move.l #trd_BuffSize,d0 jsr mem.FreeMem .Exit movem.l (a7)+,d0/a1/a5 rts ******************************************************************************* * DataArea ******************************************************************************* trd.da.DiskSync DC.W $4b4a,$4b4a,$4b52,$4b52 syncron word data DC.W $4b49,$448a,$4b4a,$4b52 DC.W $4b52,$4b4a,$448a,$4b49 DC.W $4b4a,$4b4a,$4b52,$4b52 ENDM