view level1/modules/boot_d64.asm @ 1801:75f1d0fc33e1

A tip of the hat to the CoCoFEST has been added to sysgo
author boisy
date Wed, 13 Apr 2005 17:24:12 +0000
parents b992196e2ac9
children be7da2ee5fe8
line wrap: on
line source

*
* Boot_d64, bootfile for Dragon 64, Dragon Alpha/Professional.
* 
* First disasembly and porting 2004-11-07, 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.
*
* See DDisk.asm for a fuller discription of how Dragon Alpha
* interface works.
*
* Double sided Disk code added 2004-11-25, P.Harvey-Smith.
*
*
		nam   Boot
         ttl   os9 system module    

* Disassembled 1900/00/00 00:05:56 by Disasm v1.5 (C) 1988 by RML

         ifp1
		 use 	defsfile.dragon
         endc

		IFNE	DragonAlpha

* 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 

		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

StepRate	EQU		%00000011

tylg     		set   Systm+Objct   
atrv     		set   ReEnt+rev
rev      		set   $01

				mod   eom,name,tylg,atrv,start,size
u0000    		rmb   2
BuffPtr    		rmb   2
SideSel    		rmb   1			; Side select mask
CurrentTrack	rmb   1			; Current track number
NMIFlag	 		rmb   1			; NMI enabled flag for Alpha.
size     		equ   .

name     		equ   *
				fcs   /Boot/
				fcb   $00 



start   equ   	*
		ldx		#$55AA
		
		ldx		#CMdReg
        clra  
		 
		IFNE	DragonAlpha
		clr		NMIFlag,u		; Make sure NMI turned off in Dragon Alpha
		ENDC
		 
 		ldb   	#size
L0015   pshs  	a				; Clear size bytes on system stack
        decb  
        bne   	L0015

        tfr   	s,u				; Point u to data area on s stack.
		 
        ldx   	#CMDREG			; Force inturrupt
        lda   	#FrcInt
        sta   	,x
        lbsr  	Delay			; Wait for command to complete
        lda   	,x
        lda   	>piadb			; Clear DRQ from WD.
		 
        lda   	#$FF
        sta   	CurrentTrack,u
        leax  	>NMIService,pcr	; Setup NMI Handler.
        stx   	>D.XNMI+1	
        lda   	#$7E			; $7E=JMP
        sta   	>D.XNMI
		 
        lda   	#MotorOn		; Turn on motor
		IFNE	DragonAlpha
		lbsr	AlphaDskCtl
		ELSE
		sta   	>DSKCTL
		ENDC
		 
        ldd   	#$C350			; Delay while motors spin up
MotorOnDelay    
		nop   
        nop   
        subd  	#$0001
        bne   	MotorOnDelay
		 
        pshs  	u,x,b,a
        clra  
        clrb  
        ldy   	#$0001
        ldx   	<D.FMBM	
        ldu   	<D.FMBM+2
        os9   	F$SchBit 
        bcs   	L009C
        exg   	a,b				; Make bitmap into Memory pointer
        ldu   	$04,s
        std   	BuffPtr,u		; Save LSN0 pointer
        clrb  
		 
        ldx   	#$0000			; Read LSN0 from boot disk.
        bsr   	ReadSec
        bcs   	L009C			; Error : give up !
        ldd   	<DD.BSZ,y		; Get size of boot data from LSN0
        std   	,s
        os9   	F$SRqMem 		; Request memory
        bcs   	L009C			; Error : give up
        stu   	$02,s
        ldu   	$04,s
        ldx   	$02,s
        stx   	BuffPtr,u
        ldx   	<DD.BT+1,y		; Get LSN of start of boot
        ldd   	<DD.BSZ,y		; Get size of boot.
        beq   	L0095			; Zero size boot ?, yes : exit
;
; At this point X=start LSN of boot area, D=size of boot
; BuffPtr,u=address to load next sector, Y=pointer to LSN0
;

LoadBootLoop   
		pshs  	x,b,a
        clrb  					; We are only interested in the number of full blocks
        bsr   	ReadSec			; Read a sector of boot
        bcs   	L009A			; Error : exit
        puls  	x,b,a
        inc   	BuffPtr,u		; Increment MSB of buffpointer, point to next page to load into
        leax  	$01,x			; Increment sector number
        subd  	#$0100			; Decrement number of bytes left
        bhi   	LoadBootLoop	; Any bytes left to load ?, yes : loop again

L0095   clrb  
        puls  	b,a
        bra   	L009E
		 
L009A   leas  	$04,s
L009C   leas  	$02,s
L009E   puls  	u,x
        leas  	Size,s			; Drop stacked vars.
        rts   

;
; Reset disk heads to track 0
;
		
ResetTrack0   
		clr   	,u
        clr   	CurrentTrack,u		; Zero current track
        lda   	#$05
L00A9   ldb   	#StpICmnd+StepRate	; Step in
        pshs  	a
        lbsr  	CommandWaitReady
        puls  	a
        deca  
        bne   	L00A9
        ldb   	#RestCmnd			; Restore to track 0
        lbra  	CommandWaitReady

;
; Read a sector off disk.
;

ReadSec    
		lda   	#$91				; Retry count
        cmpx  	#$0000				; Reading LSN0 ?
        bne   	ReadDataWithRetry	; No, just read sector
        bsr   	ReadDataWithRetry	; Yes read sector
        bcs   	ReadDataExit		; And restore Y=LSN0 pointer
        ldy   	BuffPtr,u
        clrb  
ReadDataExit   
		rts   

ReadDataRetry    			
		bcc   	ReadDataWithRetry	; Retry data read if error
        pshs  	x,b,a		
        bsr   	ResetTrack0			; Recal drive
        puls  	x,b,a
		 
ReadDataWithRetry    
		pshs  	x,b,a
        bsr   	DoReadData		; Try reading data
        puls  	x,b,a
        bcc   	ReadDataExit	; No error, return to caller
        lsra  					; decrement retry count
        bne   	ReadDataRetry	; retry read on error
		 
DoReadData    
		bsr   	SeekTrack		; Seek to correct track
        bcs   	ReadDataExit	; Error : exit
        ldx   	BuffPtr,u		; Set X=Data load address
        orcc  	#$50			; Enable FIRQ=DRQ from WD
        pshs  	y,dp,cc
        lda   	#$FF			; Make DP=$FF, so access to WD regs easier
        tfr   	a,dp
        lda   	#$34
        sta   	<dppia0crb		; Disable out PIA0 IRQ <u0003
        lda   	#$37
        sta   	<dppiacrb		; Enable FIRQ
        lda   	<dppiadb
        ldb   	#NMIEn+MotorOn	; $24
		  
		IFNE	DragonAlpha
		lbsr	AlphaDskCtlB
		ELSE
		stb   	<dpdskctl
		ENDIF

        ldb   	#ReadCmnd		; Issue a read command
        orb		>SideSel,U		; mask in side select
		stb   	<dpcmdreg
		
ReadDataWait    
		sync  					; Read data from controler, save
        lda   	<dpdatareg		; in memory at X
        ldb   	<dppiadb	
        sta   	,x+		
        bra   	ReadDataWait	; We break out with an NMI

; The following block of code is needed for the Dragon Alpha, because
; we currently do not know how to disable it's NMI in hardware,
; So we check a flag here, and if set we simply return from inturrupt
; as if nothing happened !

NMIService
		IFNE	DragonAlpha
		pshs	cc
		tst		NMIFlag,u
		bne		DoNMI
		puls	cc
		RTI
		
DoNMI	puls	cc
		ENDC
		
L0106   leas  	R$Size,s			; Drop saved Regs from stack
        lda   	#MotorOn

		IFNE	DragonAlpha
		lbsr	AlphaDskCtl
		ELSE
		sta    	<dpdskctl
		ENDIF

		lda   	#$34				; Re-enable inturrupts
        sta   	<dppiacrb
        ldb   	<dpcmdreg
        puls  	y,dp,cc
        bitb  	#$04
        lbeq  	L015A
L011A   comb  
        ldb   	#$F4
        rts   
		 
;
; Seek to a track, at this point Y still points to 
; in memory copy of LSN0 (if not reading LSN0 !).
;
		 
SeekTrack    
		clr   	,u
        tfr   	x,d
        cmpd  	#$0000				; LSN0 ?
        beq   	SeekCalcSkip
        clr   	,-s					; Zero track counter
        bra   	L012E
		
L012C   inc   	,s
L012E   subd  	DD.Spt,Y			; Take sectors per track from LSN
        bcc   	L012C				; still +ve ? keep looping
        addd  	DD.Spt,Y			; Compensate for over-loop
        puls  	a					; retrieve track count.

; At this point the A contains the track number, 
; and B contains the sector number on that track.

SeekCalcSkip   
		pshs	b					; Save sector number

        LDB   	DD.Fmt,Y     		; Is the media double sided ?
        LSRB
        BCC   	DiskSide0			; skip if not

		LSRA						; Get bit 0 into CC, and devide track by 2
		BCC		DiskSide0			; Even track no so it's on side 0
		ldb		#Sid2Sel			; Odd track so on side 1, flag it
		bra		SetSide
		
DiskSide0
		clrb
SetSide
		stb   	>SideSel,U			; Single sided, make sure sidesel set correctly
		
		puls	b					; Get sector number
		incb  
        stb   	>SECREG
        ldb   	CurrentTrack,u
        stb   	>TRKREG
        cmpa  	CurrentTrack,u
        beq   	L0158
        sta   	CurrentTrack,u
        sta   	>DATAREG
        ldb   	#SeekCmnd+3			; Seek command+ step rate code $13
        bsr   	CommandWaitReady
        pshs  	x
		
        ldx   	#$222E				; Wait for head to settle.
SettleWait   
		leax  	-$01,x
        bne   	SettleWait
		
        puls  	x
L0158   clrb  
        rts   
		 
L015A    bitb  #$98
         bne   L011A
         clrb  
         rts   
		 
CommandWaitReady   
		bsr   	MotorOnCmdBDelay	; Turn on motor and give command to WD
CommandWait   
		ldb   	>CMDREG			; Get command status
        bitb  	#$01			; finished ?
        bne   	CommandWait		; nope : continue waiting.
        rts   
		 
MotorOnCmdB    
		lda   	#MotorOn		; Turn on motor

		IFNE	DragonAlpha
		bsr		AlphaDskCtl
		ELSE
		sta   	>DSKCTL
        ENDIF

        stb		>CMDREG			; Give command from B
        rts   
		 
MotorOnCmdBDelay    
		bsr   	MotorOnCmdB
Delay   lbsr  	Delay2
Delay2  lbsr  	Delay3
Delay3  rts   

		IFNE	DragonAlpha

; 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.
; Also sets NMIFlag.

AlphaDskCtlB	
		pshs	A
		tfr		b,a
		bsr		AlphaDskCtl
		puls	A
		rts

DrvTab	FCB		Drive0A,Drive1A,Drive2A,Drive3A

AlphaDskCtl	
		PSHS	x,A,B,CC

		PSHS	A	
		ANDA	#NMIEn		; mask out nmi enable bit
		sta		>NMIFlag,u	; Save it for later use
		
		lda		,s			; Convert drives
		anda	#%00000011	; mask out drive number
		leax	DrvTab,pcr	; point at table
		lda		a,x			; get bitmap
		ldb		,s
		andb	#%11111100	; mask out drive number
		stb		,s
		ora		,s			; recombine
		sta		,s
		
		
		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
		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