CoCoZilla's
MFM Mass Storage
Presented by: Only On Saturday Night |
nam 'CCHDisk'
ttl OS9/NitrOS-9 Hard Disk Driver MFM * Date: April 21, 1999 * for: 6809E CPU * WDXT-GEN2+ * WDXT-GEN * NDrvs equ 2 * change to 1 if only single drive wanted * Rev equ 15 * Card equ $FF3C * the base address of the WDXT card RData equ card+0 * from $FF3C to ... WData equ card+0 Status equ card+1 * $FF3D Reset equ card+1 Config equ card+2 * $FF3E Select equ card+2 IntReg equ card+3 * $FF3F * Fodder equ $FF Blocks equ $01 Interlv equ $03 * HdSize equ 512 Os9Size equ 256 Mask equ $0F AdvMask equ $3F Selected equ $0D CmdByte equ $0D WrByte equ $09 RdByte equ $0B CmpByte equ $0F ErrBit equ %00000010 Drv1Bit equ %00100000 NDrv1Bit equ %11011111 IntBit equ %00000010 DoTk00 equ $06 SeekStil equ $08 * * MFM commands: * TestCmd equ $00 RecalCmd equ $01 ReqsCmd equ $03 FmtCmd equ $04 VfyCmd equ $05 ReadCmd equ $08 WritCmd equ $0A SeekCmd equ $0B InitCmd equ $0C ReadBuf equ $0E WritBuf equ $0F * ifp1 use /DD/DEFS/DEFSFile endc * tylg set Drivr+Objct atrv set ReEnt+Rev * mod pgmend,modnam,tylg,atrv,start,size * fcb %11111111 mode byte * org DrvBeg H0 rmb DrvMem ifeq NDrvs-2 H1 rmb DrvMem endc * * Init values for each Drive: * DiskVar0 rmb 8 ifeq NDrvs-2 DiskVar1 rmb 8 endc * * Command Block to Drive: * Class rmb 1 Head rmb 1 SecCyl rmb 1 Cylindr rmb 1 BlkCnt rmb 1 StepSiz rmb 1 * * Linear Sector Number Storage: * Odd rmb 1 HiByte rmb 1 MidByte rmb 1 LowByte rmb 1 ZeroFlag rmb 1 * * Various Buffers: * RetStat rmb 1 ReqBufr rmb 4 HdBuff rmb HdSize Stack rmb 40 Size equ . * Start lbra Init bra ReadSec nop lbra WriteSec lbra Reads3 * GetSta lbra SetSta lbra Reads3 * Termin * ReadSec lbsr LSN lbsr ChkSeek bcs RdXit bsr Read bcc Reads2 lbsr Request lbcs Test * Reads2 lbsr Blk2Os9 lda ZeroFlag,u bne Reads3 bsr Lsn0 * Reads3 clrb * RdXit rts * Read lda #ReadCmd lbsr SendCmd leax HdBuff,u ldd #HdSize * * D=Count * BlkIn pshs y tfr d,y * Read2 lda Status lsra bcc Read2 * ldb RData stb ,x+ leay -1,y bne Read2 * puls y lbra Complete * Lsn0 lbsr Getable * target ldb #DD.SIZ * length pshs y ldy PD.BUF,y * source * Read3 lda ,y+ sta ,x+ decb bne Read3 puls y,pc * * patch in the appropriate * OS9 256 byte block into * the /H0 512 byte sector * WriteSec bsr LSN lbsr ChkSeek bcs WrErr bsr Read bcc Writes2 lbsr Request bcs WrErr * Writes2 lbsr Os92Blk bsr Write bcc Writes3 lbsr Request bcs WrErr * Writes3 tst PD.VFY,y bne RetNoErr bsr Verify bcc RetNoErr comb ldb #E$Write * WrErr rts * RetNoErr clrb rts * Write lda #WritCmd * Write0 lbsr SendCmd leax HdBuff,u ldd #HdSize * * D=Count * BlkOut pshs y tfr d,y * Data2 lda Status lsra bcc Data2 * ldb ,x+ stb WData leay -1,y bne Data2 * puls y lbra Complete * Verify lda #VfyCmd lbsr General ldb RetStat,u beq VfyXit coma * VfyXit rts * * LSN * 0000000C:CCCCCCCC:CSSSSHHO * for up to 20meg drives only. * for 4 heads only ! * Cylinder-bits, Sector-bits, Head-bits, Odd-bit * Odd-bit decides which half of the 512-byte sector * gets read or (read, modify &) write. * LSN clr Odd,u stb HiByte,u stx MidByte,u orb MidByte,u orb LowByte,u stb ZeroFlag,u * ldd MidByte,u * move one cylinder bit lslb rola rol HiByte,u sta Cylindr,u * lda HiByte,u * get ls-bit of LSN lsra rorb lsra rorb rol Odd,u * save that bit * tfr b,a andb #%11001111 stb SecCyl,u lsra lsra lsra lsra sta Head,u rts * Os92Blk pshs y clrb * Loop transfer counter ldx PD.BUF,y leay HdBuff,u tst Odd,u beq LowHalf leay Os9Size,y * LowHalf lda ,x+ sta ,y+ decb bne LowHalf puls y,pc * Blk2Os9 pshs y clrb * Loop Counter leax HdBuff,u * destination ldy PD.BUF,y * source tst Odd,u beq LowHalf leax Os9Size,x bra LowHalf * TestDrv lda #TestCmd bsr SendCmd * Test1 lda Status anda #Mask cmpa #CmpByte bne Test1 ldb WData * get error bits andb #^Drv1Bit * without drive# beq TestXit coma * set error flag * TestXit rts * Sleep pshs x ldx #1 OS9 F$Sleep puls x,pc * Chk2 bsr Sleep * ChkSeek bsr TestDrv bcc Exit2 cmpb #SeekStil beq Chk2 cmpb #DoTk00 beq Chk2 bra Request * some other error * Exit2 rts * ifeq NDrvs-2 GetDrive lda Head,u * get drive/head variable tst PD.DRV,y * if /H0 beq UseH0 ora #Drv1Bit * slave, /H1 bra Drive *- UseH0 anda #^Drv1Bit * master, /H0 *- Drive sta Head,u * update drive-bit rts endc * SendCmd sta Select sta Class,u bsr GetDrive * NotRdy lda Status anda #Mask cmpa #Selected bne NotRdy leax Class,u ldb #6 * SendData lda Status lsra bcc SendData * 1=ready for data lda ,x+ sta WData decb bne SendData rts * General bsr SendCmd * Complete lda Status anda #Mask cmpa #CmpByte bne Complete ldb RData andb #ErrBit stb RetStat,u beq CompExit coma * set carry bit * CompExit rts * Request lda #ReqsCmd bsr SendCmd leax ReqBufr,u ldd #$04 * get request data string lbsr BlkIn ldb ReqBufr,u * check the error byte andb #AdvMask * eliminate the ADV-BIT bne Test * if not=0 then error clrb rts * Test cmpb #4 bne tst2 comb ldb #$FA rts * Tst2 cmpb #3 bne tst3 comb ldb #$F5 rts * Tst3 cmpb #2 bne Tst4 comb ldb #$F0 rts * Tst4 cmpb #$15 bne Tst5 comb ldb #$F7 rts * Tst5 cmpb #$21 bne ErrSet comb ldb #$F1 rts * ErrSet comb ldb #$CB rts *- GeTable ifeq NDrvs-2 tst PD.DRV,y bne Slave endc leax H0,u rts *- ifeq NDrvs-2 Slave leax H1,u rts endc * Init sta Reset ldb #NDrvs stb V.NDRV,u lda #$FF leax H0,u * InitLoop sta DD.TOT+1,x sta V.TRAK,x ifeq NDrvs-2 leax DRVMEM,x decb bne InitLoop endc * lda #IntBit sta IntReg * no interrupts sta Reset * reset the controller ldb $14,y * It.Stp dev desc orb #$C0 * step rate bits stb StepSiz,u clr SecCyl,u clr Cylindr,u clr V.BUSY,u clr V.WAKE,u lda #Blocks * sector count sta BlkCnt,u leax $20+1,y * IT.SAS+1 pshs x,y * Y is on bottom bsr GetVar tfr x,y puls x * Y is still there ldb #$08 * MoveIt lda ,x+ sta ,y+ decb bne MoveIt * puls y lda #InitCmd lbsr SendCmd bsr GetVar * X=pointer ldd #8 * table length lbsr BlkOut * send command bra Home * GetVar leax DiskVar0,u ifeq NDrvs-2 tst PD.DRV,y beq GetH0 leax DiskVar1,u * GetH0 endc rts * SetSta cmpb #SS.Reset bne Set2 bsr Home rts * Set2 cmpb #SS.Wtrk bne SetErr bsr FmtHd * low-level format rts * SetErr comb ldb #E$UnkSvc * Exit rts * * Format a MFM Hard Drive: * first: "dmode /h0 dns=0" * second: "format /h0" * This allows drive to be low-level formatted. * Software then sets dns=1 and quits. * FmtHd tst PD.DNS,y beq FmtCont * if =0 then FORMAT & set=1 * Fmt2 lda #Blocks sta PD.DNS,y * formatting is forced OFF sta BlkCnt,u clrb rts * First: fill the MDM drive's * internal buffer with sector data. * Second: format the WHOLE drive with that data. FmtCont bsr Home bcs Exit lda #WritBuf * the fill-buffer command lbsr SendCmd lda #Fodder * the data to fill every sector with ldx #HdSize * Loop ldb Status * send that buffer data andb #Mask cmpb #WrByte bne Loop * sta WData leax -1,x bne Loop * lbsr Complete bcs Exit * lda #Interlv * now format the while drive sta BlkCnt,u lda #FmtCmd * with the MFM-FORMAT command lbsr General * listen to it step ... bcs Exit bsr Fmt2 * same as: dmode /h0 dns=1 * * and fall into... * Home lbsr GeTable * move the drive heads to track=00 clr V.TRAK,x clr Cylindr,u clr SecCyl,u clr Head,u ifeq NDrvs-2 lbsr GetDrive * update drive# bit endc lda #RecalCmd * send heads to tk00 lbsr General bcc Exit lbra Request * modnam fcs /CCHDisk/ fcb Rev * emod pgmend equ * end |