Mercurial > hg > Members > kono > nitros9-code
view level1/modules/ddisk.asm @ 3109:118cd9951d24
Small fixups in level 3 boot script
And add it and the boot list to the coco3 build.
author | Tormod Volden <debian.tormod@gmail.com> |
---|---|
date | Sun, 28 Feb 2016 22:48:32 +0100 |
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