Mercurial > hg > Members > kono > nitros9-code
view level1/modules/ddisk.asm @ 3246:be3446f758ca
Updated dwread.asm and dwwrite.asm so that the 6551 routines could have specially defined
flags so that some of the addresses could be overridden by the make files if needed.
author | David Ladd <drencor-xeen@users.sourceforge.net> |
---|---|
date | Sun, 11 Mar 2018 01:30:30 -0600 |
parents | 58bb6cac8939 |
children | c505ae3120c4 |
line wrap: on
line source
******************************************************************** * DDisk - Dragon Floppy driver * * $Id$ * * Edt/Rev YYYY/MM/DD Modified by * Comment * ------------------------------------------------------------------ * - ????/??/?? * Original Dragon Data distribution version * * Added Defines for IO ports. * 2004/11/09, P.Harvey-Smith * * Dragon Alpha code, 2004-11-09, P.Harvey-Smith. * I am not sure of how to disable NMI on the Alpha, it is * simulated in software using the NMIFlag. * * The Dragon Alpha/Professional uses the same FDC chip as * DragonDos, however it is mapped between FF2C and FF2F, * also the register order is REVERSED, so command/status is at * FF2F. * * Drive Selects, motor and write precompensation is controled * through the IO port of an AY-8912, which itself is connected * to a 3rd PIA mapped at FF24 to FF27, this PIA also has it's * inturrupt lines connected to the CPU's FIRQ. * * 2004-11-15, P.Harvey-Smith. * Fixed bug in inturrupt handling code that was making the * Dragon Alpha crash if a disk was accessed with no disk * in the drive. As the Alpha is using a simulated NMI disable * we have to ensure that the NMI enabling routine has completed * BEFORE isuing a command to the disk controler, or if the * inturrupt happens in the middle of the enable routine it * causes the machine to crash ! * * 2004-11-24, P.Harvey-Smith. * Fixed up so that double sided disks now work, origional * double sided code taken from Jon Bird's pages at : * http://www.onastick.clara.net/dragon.html and modified * for NitrOS9. * * 2004-11-27, P.Harvey-Smith. * Reformatted with tab=8. * * 2005-04-22, P.Harvey-Smith. * Hopefully fixed a bug that was causing the Dragon 64 target to * crash and burn when reading disks, this made a successfull boot * almost imposible ! Fixed by writing disk command before writing * disc control register, the Alpha target needs them the other way * around. Still has a problem doing lots of retries. * * 2005-04-24, P.Harvey-Smith. * Fixed constant lost data errors reading disks, again by slightly * re-ordering the instructions in the read data loop. * * 2005-04-24, P.Harvey-Smith. * Removed debugging code/messages. * * 2005-05-31, P.Harvey-Smith. * Added ability to read, write and format standard OS-9 format disks * including single denity, and disks with track 0 single denisity, but * all other tracks double density. * * Added code to make step rates work as on the rb1773 driver, they where * previously working back to front. * * 2005-06-06, P.Harvey-Smith. * Verified as working on a real Alpha, by Richard Harding. * * 2005-06-16, P.Harvey-Smith. * Added NMI enable/disable code, as I know know how to enable/disable * NMI on the Alpha, having disasembled the Alpha's OS9's ddisk. * * 2005-06-17, P.Harvey-Smith. * Ok, this'll teach me to submit code before testing on the real hardware ! * Seperated NMI disable/drive select code on alpha, as above patches * worked fine on Mess, but not on real hardware (timing problems). * * 2006-01-08, P.Harvey-Smith. * Added support for Dragon 32, that has had a memory upgraded to 64K, * this is treated like the Dragon 64 EXCEPT that the code to manipulate * the ACIA is not included. This is required due to the incomplete * address decoding, writes to the non-existant ACIA would hit the PIA * at FF00, and cause a crash. * * 2006-01-08, P.Harvey-Smith. * Since I now have a genuine Dragon 5.25" drive, found that nitros format * fell over accessing it, this was due to the step rate not being set * correctly in the drive recalibrate routine, I ahve corrected this to * use the value in the descriptor. * nam DDisk ttl Dragon Floppy driver * Disassembled 02/04/21 22:37:46 by Disasm v1.6 (C) 1988 by RML ifp1 use defsfile endc IFNE dalpha * Dragon Alpha has a third PIA at FF24, this is used for * Drive select / motor control, and provides FIRQ from the * disk controler. DPPIADA EQU DPPIA2DA DPPIACRA EQU DPPIA2CRA DPPIADB EQU DPPIA2DB DPPIACRB EQU DPPIA2CRB PIADA EQU DPPIADA+IO ; Side A Data/DDR PIACRA EQU DPPIACRA+IO ; Side A Control. PIADB EQU DPPIADB+IO ; Side A Data/DDR PIACRB EQU DPPIACRB+IO ; Side A Control. ;WD2797 Floppy disk controler, used in Alpha Note registers in reverse order ! DPCMDREG EQU DPCmdRegA ; command/status DPTRKREG EQU DPTrkRegA ; Track register DPSECREG EQU DPSecRegA ; Sector register DPDATAREG EQU DPDataRegA ; Data register CMDREG EQU DPCMDREG+IO ; command/status TRKREG EQU DPTRKREG+IO ; Track register SECREG EQU DPSECREG+IO ; Sector register DATAREG EQU DPDATAREG+IO ; Data register ; Disk IO bitmasks NMIEn EQU NMIEnA WPCEn EQU WPCEnA SDensEn EQU SDensEnA MotorOn EQU MotorOnA ; These are the bits that we know the function of on the Alpha interface KnownBits EQU Drive0A+Drive1A+Drive2A+Drive3A+MotorOnA+SDensEnA+WPCEnA ELSE DPPIADA EQU DPPIA1DA DPPIACRA EQU DPPIA1CRA DPPIADB EQU DPPIA1DB DPPIACRB EQU DPPIA1CRB PIADA EQU DPPIADA+IO ; Side A Data/DDR PIACRA EQU DPPIACRA+IO ; Side A Control. PIADB EQU DPPIADB+IO ; Side A Data/DDR PIACRB EQU DPPIACRB+IO ; Side A Control. ;WD2797 Floppy disk controler, used in DragonDos. DPCMDREG EQU DPCmdRegD ; command/status DPTRKREG EQU DPTrkRegD ; Track register DPSECREG EQU DPSecRegD ; Sector register DPDATAREG EQU DPDataRegD ; Data register CMDREG EQU DPCMDREG+IO ; command/status TRKREG EQU DPTRKREG+IO ; Track register SECREG EQU DPSECREG+IO ; Sector register DATAREG EQU DPDATAREG+IO ; Data register ; Disk IO bitmasks NMIEn EQU NMIEnD WPCEn EQU WPCEnD SDensEn EQU SDensEnD MotorOn EQU MotorOnD ENDC tylg set Drivr+Objct atrv set ReEnt+rev rev set $00 edition set 3 MaxDrv set 4 mod eom,name,tylg,atrv,start,size org DrvBeg DrvTab RMB MaxDrv*DrvMem ; Drive tables, 1 per drive CDrvTab rmb 2 ; Pointer to current drive table entry above DrivSel rmb 1 ; Saved drive mask Settle rmb 1 ; Head settle time SavePIA0CRB rmb 1 ; Saved copy of PIA0 control reg b SaveACIACmd rmb 1 ; Saved copy of ACIA command reg BuffPtr rmb 2 ; Buffer pointer SideSel rmb 1 ; Side select. Density rmb 1 ; Density 0=double, %00001000=single D64, %00100000=single Alpha DskError rmb 1 ; hardware disk error VIRQPak rmb 2 ; Vi.Cnt word for VIRQ u00B3 rmb 2 ; Vi.Rst word for VIRQ u00B5 rmb 1 ; Vi.Stat byte for VIRQ (drive motor timeout) VIRQInstalled rmb 1 ; Is VIRQ Installed yet ? size equ . fcb $FF name equ * fcs /DDisk/ fcb edition VIRQCnt fdb TkPerSec*4 Initial count for VIRQ (4 seconds) start lbra Init ; Initialise Driver lbra Read ; Read sector lbra Write ; Write sector lbra GetStat ; Get status lbra SetStat ; Set status lbra Term ; Terminate device IRQPkt fcb $00 ; Normal bits (flip byte) fcb $01 ; Bit 1 is interrupt request flag (Mask byte) fcb 10 ; Priority byte nop nop nop lbsr ResetTrack0 * Init * * Entry: * Y = address of device descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * DragonDebug EQU 0 Init IFNE DragonDebug pshs y ; This is here so I can find disk driver in mess ldy #$AA55 ; by setting register breakpoint to y=$AA55 ! sty $8000 puls y ENDC clra sta >D.DskTmr ; Zero motor timer IFNE dalpha ; Turn off all drives lbsr AlphaDskCtl lda #NMICA2Dis ; Set PIA2 CA2 as output & disable NMI sta PIA2CRA ELSE sta >DskCtl ENDC ldx #CmdReg ; Reset controler lda #FrcInt sta ,x lbsr Delay lda ,x lda #$FF ldb #MaxDrv leax DrvBeg,u InitDriveData sta DD.Tot,x ; Set total sectors = $FF sta <V.Trak,x ; Set current track = 0 leax <DrvMem,x ; Skip to next drive decb bne InitDriveData leax >NMIService,pcr ; Setup NMI handler stx >D.XNMI+1 lda #$7E ; $7E = JMP sta >D.XNMI clr VIRQInstalled,u ;flag not installed yet pshs y ; save device dsc. ptr leay >u00B5,u ; point to Vi.Stat in VIRQ packet tfr y,d ; make it the status register ptr for IRQ leay >IRQSvc,pc ; point to IRQ service routine leax >IRQPkt,pc ; point to IRQ packet os9 F$IRQ ; install IRQ puls y ; Get back device dsc. ptr ldd #$0100 ; Request a page of system ram pshs u ; used to verify writes os9 F$SRqMem tfr u,x puls u bcs Return stx >BuffPtr,u ; Save verify page pointer clrb Return rts * GetStat * * Entry: * A = function code * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * GetStat * Term * * Entry: * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * Term clrb rts * Read * * Entry: * B = MSB of the disk's LSN * X = LSB of the disk's LSN * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * Read lda #$91 ; Retry count cmpx #$0000 ; LSN ? bne ReadDataWithRetry ; No : Just do read, bsr ReadDataWithRetry ; Yes : do read and copy disk params bcs ReadDataExit ldx PD.Buf,y pshs y,x ldy >CDrvTab,u ldb #DD.Siz-1 L0082 lda b,x sta b,y decb bpl L0082 clrb puls pc,y,x ReadDataExit rts ; Read Retry ReadDataRetry bcc ReadDataWithRetry ; Retry entry point pshs x,b,a lbsr ResetTrack0 ; Reset track 0 puls x,b,a ReadDataWithRetry pshs x,b,a ; Normal entry point bsr DoReadData puls x,b,a bcc ReadDataExit lsra ; Check for retry bne ReadDataRetry DoReadData lbsr SeekTrack bcs ReadDataExit ldx PD.Buf,y ; Target address for data pshs y,dp,cc ldb #ReadCmnd ; Read command bsr PrepDiskRW ; Prepare disk DoReadDataLoop lda <DPPIACRB ; Is data ready ? bmi ReadDataReady ; Yes : read it leay -1,y bne DoReadDataLoop bsr RestoreSavedIO puls y,dp,cc lbra RetReadError ; Return read error to caller ReadDataWait sync ; Sync to inturrupts, wait for data ReadDataReady lda <DPDataReg ; Read data from FDC ldb <DPPIADB ; Clear PIA inturrupt status sta ,x+ ; save data in memory bra ReadDataWait ; do next ; ; Prepare to do disk read/write. ; PrepDiskRW clr DskError,u lda #$FF ; Make DP=$FF, to make i/o faster tfr a,dp ; ; Do not attempt to talk to ACIA if this machine does not have one ! ; IFEQ Upgraded32 lda <DPAciaCmd ; Save ACIA Command reg sta >SaveACIACmd,u anda #$FE ; Disable ACIA inturrupt sta <DPAciaCmd bita #$40 ; Is Tx inturrupt enabled ? beq L00DE L00D8 lda <DPAciaStat ; Yes, wait for Tx to complete bita #$10 beq L00D8 ENDC L00DE orcc #$50 ; Mask inturrupts lda <DPPia0CRB ; Save PIA0 IRQ Status sta >SavePIA0CRB,u lda #$34 ; Disable it. sta <DPPia0CRB IFEQ Upgraded32 lda <DPACIACmd ; Disable ACIA Inturrupt anda #$FE sta <DPACIACmd ENDC lda <DPPIACRB ; Set PIA to generate FIRQ on FDC DRQ ora #$03 sta <DPPIACRB lda <DPPIADB ; Clear any outstanding inturrupt ldy #$FFFF lda #NMIEn+MotorOn ; Enable NMI, and turn motor on ora >DrivSel,u ; mask in drives ora >Density,u ; mask in density ORB >SideSel,U ; Set up Side IFNE dalpha ; Turn on drives & NMI lbsr AlphaDskCtl stb <DPCmdReg ; issue command to controler lda #NMICA2En ; Enable NMI sta <DPPIA2CRA ELSE stb <DPCmdReg ; issue command to controler sta <DPDskCtl ENDC rts ; ; Restore saved iO states of peripherals. ; RestoreSavedIO IFNE dalpha lda #NMICA2Dis ; Disable NMI (Alpha) sta <DPPIA2CRA ENDC lda >DrivSel,u ; Deselect drives, but leave motor on ora #MotorOn IFNE dalpha ; Turn off drives & NMI lbsr AlphaDskCtl ELSE sta <DPDskCtl ENDC lda >SavePIA0CRB,u ; Recover PIA0 state sta <DPPia0CRB lda <DPPIACRB ; Disable Drive FIRQ source. anda #$FC sta <DPPIACRB IFEQ Upgraded32 lda >SaveACIACmd,u ; Recover ACIA state sta <DPAciaCmd ENDC rts * Write * * Entry: * B = MSB of the disk's LSN * X = LSB of the disk's LSN * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * Write lda #$91 ; Retry byte L0124 pshs x,b,a bsr DoWrite ; Attempt to do write puls x,b,a bcs WriteDataRetry ; On error, retry tst <PD.Vfy,y ; Written, should we verify ? bne WriteDone ; no : return lbsr WriteVerify ; yes : verify write bcs WriteDataRetry ; verify error, retry write WriteDone clrb ; Return status ok rts WriteDataRetry lsra ; Retry data write lbeq RetWriteError ; All retries exhausted ?, return error bcc L0124 pshs x,b,a ; Reset to track 0 lbsr ResetTrack0 puls x,b,a bra L0124 DoWrite lbsr SeekTrack ; Seek to correct track & sector lbcs ReadDataExit ldx PD.Buf,y ; Get data buffer in X pshs y,dp,cc ldb #WritCmnd ; Write command WriteTrackCmd lbsr PrepDiskRW ; Prepare for disk r/w lda ,x+ ; get byte to write L015A ldb <DPPIACRB ; Ready to write ? bmi WriteDataReady ; Yes, do it. leay -1,y bne L015A bsr RestoreSavedIO ; Restore saved peripheral states puls y,dp,cc lbra RetWriteError ; Return write error WriteDataWait lda ,x+ ; Get next byte to write sync ; Wait for drive WriteDataReady sta <DPDataReg ; Write data to FDC ldb <DPPIADB ; Clear pending FDC inturrupt bra WriteDataWait ; ; NMI Handler code. ; NMIService leas R$Size,s ; Drop regs from stack bsr RestoreSavedIO ; Restore saved IO states puls y,dp,cc ldb >CmdReg stb DskError,u bitb #LostMask ; check for lost record lbne RetReadError ; yes : return read error lbra TestForError ; esle test for other errors ; Verify a written sector. WriteVerify pshs x,b,a ldx PD.Buf,y ; Swap buffer pointers pshs x ldx >BuffPtr,u stx PD.Buf,y ldx 4,s lbsr DoReadData ; Read data back in puls x stx PD.Buf,y ; Swab buffer pointers back bcs VerifyEnd lda #$20 pshs u,y,a ldy >BuffPtr,u tfr x,u VerifyLoop ldx ,u ; Compare every 4th word cmpx ,y bne VerifyErrorEnd leau 8,u leay 8,y ; Increment pointers dec ,s bne VerifyLoop bra VerifyEndOk ; Verify succeeded. VerifyErrorEnd orcc #Carry ; Flag error VerifyEndOk puls u,y,a VerifyEnd puls pc,x,b,a ; ; Seek to a track ; SeekTrack CLR >Settle,U ; default no settle LBSR SelectDrive ; select and start correct drive TSTB BNE E.Sect TFR X,D LDX >CDrvTab,U CMPD #0 ; Skip calculation of track 0 BEQ SeekT1 CMPD DD.TOT+1,X ; Has an illegal LSN been BLO SeekT2 E.Sect COMB LDB #E$Sect RTS SeekT2 CLR ,-S ; Calculate track number SUBD PD.T0S,Y ; subtract no. of sectors in track 0 BHS SeekT4 ADDD PD.T0S,Y ; if -ve we are on track 0, so add back on again BRA SeekT3 SeekT4 INC ,S SUBD DD.Spt,X ; sectors per track for rest of disk BHS SeekT4 ; repeat, until -ve, incrementing track count ADDD DD.Spt,X ; re add sectors/track to get sector number on track ; At this point the byte on the top of the stack contains the track ; number, and B contains the sector number on that track. SeekT3 PULS A ; retrieve track count LBSR SetWPC ; set write precompensation LBSR SetDensity ; Set density PSHS B LDB DD.Fmt,X ; Is the media double sided ? LSRB BCC SingleSidedDisk ; skip if not LDB PD.Sid,Y ; Is the drive double sided ? DECB BNE SetupSideMask ; yes : deal with it. PULS B ; No then its an error COMB LDB #E$BTyp RTS SetupSideMask BSR SetSide ; Media & drive are double sided BRA SeekT9 SingleSidedDisk clr >SideSel,U ; Single sided, make sure sidesel set correctly BRA SeekT9 SeekT1 LBSR SetDensity ; make sure density set correctly even for LSN0 ! clr >SideSel,U ; make sure sidesel is always 0 if lsn0 PSHS B SeekT9 LDB PD.Typ,Y ; Dragon and Coco disks BITB #TYP.CCF ; count sectors from 1 no BEQ SeekT8 PULS B INCB ; so increment sector number BRA SeekT11 SeekT8 PULS B ; Count from 0 for other types SeekT11 STB >SecReg ; Write sector number to controler LBSR Delay CMPB >SecReg BNE SeekT11 SeekTS LDB <V.Trak,X ; Entry point for SS.WTrk command STB >TrkReg TST >Settle,U ; If settle has been flagged then wait for settle BNE SeekT5 CMPA <V.Trak,X ; otherwise check if this is BEQ SeekT6 ; track number to the last SeekT5 STA <V.Trak,X ; Do the seek STA >DataReg ; Write track no to controler bsr GetStepInB ; get step rate ORB #SeekCmnd ; add seek command LBSR FDCCommand PSHS X LDX #$222E ; Wait for head to settle SeekT7 LEAX -1,X BNE SeekT7 PULS X SeekT6 CLRB ; return no error to caller RTS ; ; Get step rate in bottom 2 bits of B ; GetStepInB ldb PD.Stp,Y ; Set Step Rate according to Parameter block andb #%00000011 ; mask in only step rate bits eorb #%00000011 ; flip bits to make correct encoding rts ; Set Side2 Mask ; A contains the track number on entry SetSide LSRA ; Get bit 0 into carry & devide track no by 2 PSHS A BCC Side0 ; Side 0 if even track no. LDA #Sid2Sel ; Odd track no. so side 2 BRA Side Side0 CLRA Side STA >SideSel,U PULS A,PC ; ; Select drive and start drive motors. ; On entry A=drive number. ; SelectDrive lbsr StartMotor ; Start motor lda <PD.Drv,y ; Check it's a valid drive cmpa #MaxDrv bcs SelectDriveValid ; yes : continue RetErrorBadUnit comb ; Return bad unit error ldb #E$Unit rts SelectDriveValid pshs x,b,a ; Unit valid so slect it sta >DrivSel,u ; Get DD table address leax DrvBeg,u ; Calculate offset into table ldb #DrvMem mul leax d,x cmpx >CDrvTab,u beq SelectDriveEnd stx >CDrvTab,u ; Force seek if different drive com >Settle,u SelectDriveEnd puls pc,x,b,a ; ; Analise device status return. ; TestForError bitb #ErrMask beq TestErrorEnd bitb #NotRMask ; not ready bne RetErrorNotReady bitb #WPMask ; Write protect bne RetErrorWP bitb #RTypMask ; Wrong type ? bne RetWriteError bitb #RNFMask ; Record Not found bne RetErrorSeek bitb #CRCMask bne RetErrorCRC TestErrorEnd clrb rts ; ; Return error code ; RetErrorNotReady comb ldb #E$NotRdy rts RetErrorWP comb ldb #E$WP rts RetWriteError comb ldb #E$Write rts RetErrorSeek comb ldb #E$Seek rts RetErrorCRC comb ldb #E$CRC rts RetReadError comb ldb #E$Read rts ; ; Issue a command to FDC and wait till it's ready ; FDCCommand bsr FDCCmd FDCCmdWait ldb >CmdReg ; Poll until not busy bitb #$01 beq Delay3 bra FDCCmdWait FDCCmdMotorOn lda #MotorOn ; Turn on motor ora >DrivSel,u IFNE dalpha lbsr AlphaDskCtl ELSE sta >DskCtl ENDC bsr SetupVIRQ stb >CmdReg ; Send Command to FDC rts SetupVIRQ pshs D ldd >VIRQCnt,pc ; Get VIRQ initial count value std >VIRQPak,u ; Save it lda VIRQInstalled,u ; Installed yet ? beq DoInsVIRQ ; Not installed yet, try installing it SetupVIRQExit PULS D rts DoInsVIRQ bsr InsVIRQ bra SetupVIRQExit InsVIRQ pshs D,y,x lda #$01 ; Flag drive motor is up to speed IFEQ Level-1 sta >D.DskTmr ELSE sta <D.MotOn ENDC ldx #$0001 ; Install VIRQ entry leay >VIRQPak,u ; Point to packet clr Vi.Stat,y ; Reset Status byte ldd >VIRQCnt,pc ; Get initial VIRQ count value os9 F$VIRQ ; Install VIRQ bcs VIRQOut ; Error, exit inc VIRQInstalled,u ; Flag it's installed VIRQOut puls X,Y,D rts * IRQ service routine for VIRQ (drive motor time) * Entry: U=Ptr to VIRQ memory area IRQSvc pshs a lda <D.DMAReq beq L0509 bsr InsVIRQ bra IRQOut L0509 IFNE dalpha lbsr AlphaDskCtl ELSE sta >DskCtl ENDC clr u00B5,u clr VIRQInstalled,u IFEQ Level-1 clr >D.DskTmr ELSE clr <D.MotOn ENDC IRQOut puls pc,a FDCCmd bsr FDCCmdMotorOn ; Delay routine ! Delay lbsr Delay2 Delay2 lbsr Delay3 Delay3 rts * SetStat * * Entry: * A = function code * Y = address of path descriptor * U = address of device memory area * * Exit: * CC = carry set on error * B = error code * SetStat ldx PD.Rgs,y ; Retrieve request ldb R$B,x cmpb #SS.Reset ; Restore to track 0. beq ResetTrack0 cmpb #SS.Wtrk ; Write (format) a track beq DoWriteTrack comb ldb #E$UnkSvc SetStatEnd rts ; ; Write (format) a track ; DoWriteTrack lbsr SelectDrive ; Select drive lda R$Y+1,x LBSR SetSide ; Set Side 2 if appropriate LDA R$U+1,X BSR SetWPC ; Set WPC by disk type bsr SetDensity ; Set density ;L02D5 ldx >CDrvTab,u lbsr SeekTS ; Move to correct track bcs SetStatEnd ldx PD.Rgs,y ldx R$X,x ldb #WtTkCmnd pshs y,dp,cc lbra WriteTrackCmd ; Reset track 0 ResetTrack0 lbsr SelectDrive ; Select drive ldx >CDrvTab,u clr <V.Trak,x ; Set current track as 0 lda #$05 ResetTrack0Loop lbsr GetStepInB ; Get step rate for this drive orb #StpICmnd ; Step away from track 0 5 times pshs a lbsr FDCCommand puls a deca bne ResetTrack0Loop lbsr GetStepInB ; Get step rate for this drive orb #RestCmnd ; Now issue a restore lbra FDCCommand ; ;Start drive motors ; StartMotor pshs x,b,a lda >D.DskTmr ; if timer <> 0 then skip as motor already on bne MotorsRunning lda #MotorOn ; else spin up IFNE dalpha bsr AlphaDskCtl ELSE sta >DskCtl ENDC ldx #$A000 ; Wait a little while for motors to get up to speed StartMotorLoop nop nop leax -1,x bne StartMotorLoop MotorsRunning lbsr SetupVIRQ ; lda #$F0 ; Start external motor timer ; sta >D.DskTmr ; external to driver puls pc,x,b,a ; ; Set Write Precompensation according to media type ; ; Entry : ; A = Track no SetWPC PSHS A,B LDB PD.DNS,Y BITB #T80Mask ; Is it 96 tpi drive BNE SetWP1 ASLA ; no then double SetWP1 CMPA #32 ; WPC needed ? BLS SetWP2 LDA >DrivSel,U ORA #WPCEn STA >DrivSel,U SetWP2 PULS A,B,PC ; ; Set density acording to disk type. ; ; Entry A = Track no ; SetDensity PSHS A,B ldb PD.TYP,Y ; Dragon/CoCo disk ? bitb #TYP.CCF bne SetDouble ; Always double density LDB PD.DNS,Y ; Get density flags from Path descriptor bitb #DNS.MFM ; Disk is MFM ? beq SetSingle ; no : set single density cmpa #0 ; track 0 ? bne SetDouble ; not track 0, exit tst SideSel,u ; is this side 0 ? bne SetDouble ; no : use double density bitb #DNS.MFM0 ; track 0 mfm ? bne SetDouble SetSingle lda #SDensEn ; flag single density sta Density,u bra ExitDensity SetDouble clr Density,u ; flag double density ExitDensity puls a,b,pc IFNE dalpha ; Translate DragonDos Drive select mechinisim to work on Alpha ; Takes byte that would be output to $FF48, reformats it and ; outputs to Alpha AY-8912's IO port, which is connected to ; Drive selects, motor on and enable precomp. ; This code now expects Alpha NMI/DDEN etc codes, as defined ; at top of this file (and dgndefs). The exception to this is ; the drive number is still passed in the bottom 2 bits and ; converted with a lookup table. ; We do not need to preserve the ROM select bit as this code ; operates in RAM only mode. ADrvTab FCB Drive0A,Drive1A,Drive2A,Drive3A AlphaDskCtl PSHS x,A,B,CC PSHS A anda #DDosDriveMask ; mask out dragondos format drive number leax ADrvTab,pcr ; point at table lda a,x ; get bitmap ldb ,s andb #AlphaCtrlMask ; mask out drive number bits stb ,s ora ,s ; recombine drive no & ctrl bits ; sta ,s bita #MotorOn ; test motor on ? bne MotorRunning clra ; No, turn off other bits. MotorRunning anda #Mask58 ; Mask out 5/8 bit to force the use of 5.25" clock sta ,s orcc #$50 ; disable inturrupts lda #AYIOREG ; AY-8912 IO register sta PIA2DB ; Output to PIA ldb #AYREGLatch ; Latch register to modify stb PIA2DA clr PIA2DA ; Idle AY lda ,s+ ; Fetch saved Drive Selects etc sta PIA2DB ; output to PIA ldb #AYWriteReg ; Write value to latched register stb PIA2DA ; Set register clr PIA2DA ; Idle AY PULS x,A,B,CC RTS ENDC emod eom equ * end