view 3rdparty/utils/fpgarom/boot.asm @ 3222:c086a5d69b78

Corrected ,pc should have been ,pcr in KRNP3.asm
author David Ladd <drencor-xeen@users.sourceforge.net>
date Wed, 20 Dec 2017 23:28:18 -0600
parents ffa4b0273cc7
children
line wrap: on
line source

;;;
;;;  Boot OS9 via CoCoBoot interface
;;;
;;;


	include "sd.def"

	export	prestart

	import	start.bss
	import  length.bss
	
CR	equ	13
SP	equ	32
	
DBUF0	equ	$600			; we'll borrow some memory from basic
DBUF1	equ	$700			; another buffer
SCRPTR	equ	$0002		; point to the os screen pointer


DD.BIT	equ	$6		; 2B no of sectors per cluster
DD.NAM	equ	$1f		; 32B volume name field
DD.DIR	equ	$8		; 3B descriptor cluster for root dir

FD.SIZ	equ	$9		; 4B size of file in bytes
	

		.area	.bss
root		rmb	3		; 3b lsn of root dir
;; FCB - vars needed to control file access.
sptr		rmb	2		; ptr to current segment
dptr		rmb	2		; ptr to data buffer
bcount	rmb	2		; number of bytes left in buffer
fcounth	rmb	2		; number of bytes left in file (high word)
fcount 	rmb	2		; number of bytes left in file (low word)
cptr		rmb	2		; pointer in block (boot cpu address)
blocks	rmb	1		; number of regular contigeous blocks
block		rmb	1		; current block number
dirbuf	rmb	32		;
ksize		rmb	2		; "stacked" size of os9 boot file
offset	rmb	3		; 3B offset of root partition
stack1	rmb	64
stackb

		.area	.bounce
BOUNCE	rmb	255

		.area	.code
prestart
		jmp	start		; me first, but jump over DATA

BOOT		fcn	"OS9Boot"
KRN		fcn	"ccbkrn"
str0		fcn	"Loading OS9Boot"
str1		fcn	"Loading ccbkrn"
str2		fcn	"Xfr Control to KRN..."
str3		fcn	"CoCoBoot SDIO"
str4		fcn	"Vol Name: "

start
		orcc	#$50		; shut off interrupts
		clr	$ffa0		; set mmu bank 0 to phys 0
		clr	$ffdf		; set SAM RAM mode
		clr	$ffd9		; high speed poke
;; clear ram vars
		ldx	#start.bss
a@		clr	,x+
		cmpx	#(start.bss+length.bss)
		bne	a@
;; 
		lds	#stackb	; set stack
		ldx	#$ff90	; setup gimme
		jsr	gime		;
;; setup screen
		jsr	scrSetup	; setup screen
		ldx	#str3		; print banner
		jsr	putscr		;
;; init SD card
		jsr	ll_init		
		lbcs	initerr
;; get LSN0
		ldx	#DBUF0	; set disk arg
		stx	DPTR
		clr	LSN
		clr	LSN+1
		clr	LSN+2
;; Test for CCPT
		jsr	ccpttest
;; try to mount os9 filesystem
		jsr	getlsn
;; print volume name
		ldx	#str4
		jsr	puts
		ldx	#DBUF0+DD.NAM
		jsr	putscr
;; get root dir's lsn
		ldx	#DBUF0+DD.DIR
		ldu	#root
		jsr	cpy3
;; open boot file
		ldx	#str0
		jsr	puts
		ldx	#BOOT
		jsr	nopen
		lbcs	fnferr
		ldx	#dirbuf+$1d	; !!! replace with constant
		ldu	#LSN		;
		jsr	cpy3		; set LSN = lsn of dirent
		jsr	open		; and open the file
		ldd	fcounth	; check size 
		lbne	toobig	; 
;; calculate start address
		ldd	fcount	; save os9 size for passing to KRN
		std	ksize		;
		ldd	#$f000	; f000 - fcount = start address
		subd	fcount	;
		clrb			; and round it down to near page boundary
		tfr	d,x		; X = cpu load address
		pshs	x		; push onto stack ( cpustart )
		cmpx	#$2000		; cant go lower
		lblo	toobig
;; set calc init mmu for bounce routine
		lsra			; make A = mmu reg no
		lsra			; take top three bits
		lsra			;
		lsra			;
		lsra			;
		pshs	a		; push start mmu no ( cpustart mmustart )
;; calc no of contigeous block for os9boot loading routine
		ldb	#7		; A = no of contigeous block
		subb	,s		;
		stb	blocks	; save for loading routine
;; calc beginning cpu address
		ldd	1,s		; D = cpu start
		anda	#$1f
		addd	#$4000	; adjust for loader
		std	cptr
;; copy os9boot into memory
b@		jsr	testload	; load os9boot into memory
		jsr	putCR
;; open krn file
		ldx	#str1
		jsr	puts
		ldx	#KRN
		jsr	nopen
		bcs	fnferr
		ldx	#dirbuf+$1d	; !!! replace with constant
		ldu	#LSN		;
		jsr	cpy3		; set LSN = lsn of dirent
		jsr	open		; and open the file
		ldx	fcounth	; check size of krn file
		lbne	krnsize	; is way too big
		ldx	fcount	; 
		cmpx	#$f00		;
		lbne	krnsize	; wrong size
;; copy krn file into memory
		ldx	#$f000
		jsr	fload		; load ccbkrn into memory
		jsr	putCR
;; done with disk go high speed :(
		clr	$ffd9
;; clear out DP page
		ldx	#0
		clrb
		jsr	memz
;; set dp
		tfr	b,dp
;; set gime mirror
		ldx	#$90
		jsr	gime
;; copy bounce routine down to RAM
		ldx	#bounce
		ldu	#BOUNCE
		ldb	#bounceend-bounce
c@		lda	,x+
		sta	,u+
		decb
		bne	c@
;; jump to OS9
		ldx	#str2
		jsr	putscr
		jmp	BOUNCE

	
iloop	bra	iloop

	
fnferr	ldx	#p0@
	jsr	puts
a@	bra	a@
p0@	fcn	": FNF Error!"

initerr	ldx	#p0@
	jsr	puts
a@	bra	a@
p0@	fcn	"Driver Init Error!"

mnterr	ldx	#p0@
	jsr	puts
a@	bra	a@
p0@	fcn	"LSN0: bad format!"

toobig	ldx	#p0@
	jsr	puts
a@	bra	a@
p0@	fcn	"Too Big!"

krnsize
	ldx	#p0@
	jsr	puts
a@	bra	a@
p0@	fcn	"Wrong Size!"
	

;;; Test for presence of CCPT partitioning
ccpttest
	pshs	d,x
	ldd	DBUF0		; get magic
	cmpd	#$4343		; check for "CC"
	lbne	no@
	ldd	DBUF0+2		; check for "PT"
	cmpd	#$5054
	lbne	no@		;
no@	ldx	#p0@
	jsr	putscr
	puls	d,x,pc
p0@	fcn	"CCPT not found."

	
;;; Setup Screen for os9 (sigh)
scrSetup
	pshs	d,x
	;; set colors: green on black
	ldb	#$12
	stb	$ffbc
	ldb	#0
	stb	$ffbd
	;; clear a screen's worth of video memory
	ldb	#$3b
	stb	$ffa0
	ldx	#$0000
	ldd	#$2020
a@	std	,x++
	cmpx	#$0400
	bne	a@
	;; set screen pointer up
	ldd	#8
	std	SCRPTR
	clr	$ffa0
	puls	d,x,pc

	
;;; Setup memory with gimme setting, aka Do os9's work :(
;;;   takes: X = address
;;;   returns: nothing
;;;   modifies: nothing
gime
	pshs	d,x,u
	ldu	#table@
	lda	#16
a@	ldb	,u+
	stb	,x+
	deca
	bne	a@
	puls	d,x,u,pc
table@	.dw	$6c00
	.dw	$0000
	.dw	$0900
	.dw	$0000
	.dw	$0320
	.dw	$0000
	.db	$00
	.dw	$ec01
	.db	$00

;;; This bounce routine gets copied down into low memory
;;;   is completes the memory map.  Plz jump to me.
bounce			      ; ( cpustart mmustart )
	;; setup mmu to how os9 expects it
	clr	$ffa0		; phys block 0 is always mapped to $0000
	puls	a		; get mmu start ( cpustart )
	ldy	#$ffa0
	leay	a,y		; Y = beginning mmu
	ldb	#1		; 1 is first os9 system block
a@	stb	,y+		; store bank no in mmu
	cmpy	#$ffa7		; did we move to the last mmu block
	beq	b@		; yes, then quit looping
	incb			; increment bank no
	bra	a@		; repeat	
b@	ldb	#$3f		; and mmu7 is always $3f
	stb	,y
	;; find and jump to KRN module
	ldx	$f009		; KRN relative start address
	leax	$f000,x		; make it absolute
	ldu	#ksize		; U = ptr to os9boot size
	orcc	#$50		; really, really turn off interrupts
	jmp	,x		; jump to kernel (bye!)
bounceend




;;; Read os9 file into memory
;;;   takes: open os9 file,
testload
	pshs	d,x
	ldb	#1		; set initial bank to 1
	stb	block		;
	stb	$ffa2		;
	;; loop until EOF
a@	ldx	cptr		; get block pointer
	jsr	readb		; read a byte
	bcs	out@		; done!
	stb	,x+
	stx	cptr
	;; check for end of bank
	cmpx	#$6000
	bne	a@
	;; end of bank
	ldd	#$4000		; reset block pointer
	std	cptr
	dec	blocks		; any more blocks left
	bne	b@
	;; no more blocks left set $3f
	ldb	#$3f
	bra	c@
b@	inc	block
	ldb	block
c@	stb	$ffa2		; set mmu
	bra	a@
out@	puls	d,x,pc

;;; Read file into memory
;;;   takes: X = address to load, file opened.
;;;   modifies: nothing
fload	pshs	b,x
a@	jsr	readb
	bcs	done@
	stb	,x+
	bra	a@
done@	puls	b,x,pc


	
;;; open a file via a name
;;;    takes: X = filename (zero termed)
;;;    returns: dirbuf set to file's FD, C set on error.
nopen
	pshs	d,x,u
	;; open root directory
	ldx	#root
	ldu	#LSN
	jsr	cpy3
	jsr	open
	;; get a dirent into buffer
	ldu	2,s		; U = filename
b@	lda	#32
	ldx	#dirbuf
a@	jsr	readb
	bcs	nfound@
	stb	,x+
	deca
	bne	a@
	jsr	os9toz
	ldx	#dirbuf
	jsr	strcmp
	bcc	found@
	bra	b@
nfound@	coma
	puls	d,x,u,pc
found@	clra
	puls	d,x,u,pc


;;; zero mem
;;;   takes: X = ptr, B = number of byte to zero
;;;   returns: nothing
;;;   modifies: nothing
memz
	pshs	b,x
a@	clr	,x+
	decb
	bne	a@
	puls	b,x,pc

	

;;; strcmp
;;;   takes: X = zstring, U = zstring
;;;   returns: C clear if equal
strcmp
	pshs	b,x,u
a@	ldb	,x+
	cmpb	,u+
	bne	ne@		; not equal
	tstb
	beq	e@		; equal
	bra	a@		; loop
e@	clrb
	puls	b,x,u,pc
ne@	comb
	puls	b,x,u,pc
	
;;; change dirbuf's name to a z-string
os9toz
	pshs	b,x
	ldx	#dirbuf
	tst	,x
	beq	out@
a@	ldb	,x+
	bpl	a@
	andb	#$7f
	stb	-1,x
	clr	,x
out@	puls	b,x,pc
	

;;; Open file
;;;   takes: LSN = lsn of file's FD
;;;   returns: nothing
open
	pshs	d,x
	ldx	#DBUF1		; load dbuf1 with file's FD
	stx	DPTR
	jsr	getlsn
	ldd	#DBUF1+$10	; first segment
	std	sptr		; save ptr
	jsr	fill		; and get first sector
	;; set fcount
	ldd	DBUF1+FD.SIZ
	std	fcounth
	ldd	DBUF1+FD.SIZ+2
	std	fcount
	puls	d,x,pc

;;; get one byte from file
;;;   takes: nothing,
;;;   returns: B = byte, C set on EOF
readb
	pshs	a,x
	ldd	fcount		; is the entire file out of bytes?
	beq	eof@
	ldd	bcount
	bne	a@		; if left don't refill
	;; refill file's data buffer
	jsr	fill
	;; 
a@	ldd	fcount
	subd	#1
	std	fcount
	ldd	bcount
	subd	#1
	std	bcount
	ldx	dptr
	ldb	,x+
	stx	dptr
	clra
	puls	a,x,pc
eof@	coma
	puls	a,x,pc
	
	
fill
	pshs	d,x,u		; save regs
	jsr	spin1
	ldx	sptr
	ldd	3,x		; get sector count
	bne	a@		; no more secs left in seg?
	;; get next segment
	ldx	sptr
	leax	5,x
	stx	sptr
	;; fill buffer
a@	ldx	sptr		; copy segment's LSN to args
	ldu	#LSN		;
	jsr	cpy3		;
	ldx	#DBUF0		; set data buffer
	stx	DPTR		;
	jsr	getlsn		; and get the sector
	;; increment segment
	ldx	sptr		; increment segment's LSN
	jsr	inc3		; 
	ldd	3,x		; decrement segment's sector count
	subd	#1		;
	std	3,x		;
	;; set file dirs
	ldd	#256
	std	bcount
	ldd	#DBUF0
	std	dptr
	puls	d,x,u,pc	; return
	

;;; Spin the ticker
;;;   takes: nothing
;;;   returns: nothing
;;;   modifies: nothing
spin1
	pshs	b
	ldb	#'.
	jsr	putc
	puls	b,pc

	
;;; Copy 3 bytes value
;;;   take: X = src ptr, U = dst ptr
;;;   modifies: nothing
cpy3
	pshs	d,x,u
	ldd	,x++
	std	,u++
	ldb	,x
	stb	,u
	puls	d,x,u,pc

	
;;; Add 3 byte value store result in X ptr
;;;   takes: X = 3B ptr, U = 3B ptr
;;;   modifies: nothing
add3
	pshs	d
	ldd	1,u
	addd	1,x
	std	1,x
	ldb	,u
	adcb	,x
	stb	,x
	puls	d,pc
	


;;; increment 3 byte value by one
;;;  takes: X = ptr to 3 bytes
;;;  returns: nothing
inc3
	pshs	d,x
	ldd	1,x
	addd	#1
	std	1,x
	ldb	,x
	adcb	#0
	stb	,x
	puls	d,x,pc
	

;;; deblocker to translate 256B LSN to a 512B LSN
;;;   takes: args in LSN/DPTR
;;;   modifies: nothing
getlsn
	pshs	b,x
	ldx	#LSN		; get pointer
	lsr 	,x+
	ror	,x+
	ror	,x+
	ldb	#1		; 256b lower read
	bcc	a@
	negb
a@	stb	SMALL
	ldx	#LSN		; add partition offset
	ldu	#offset
	jsr	add3
	jsr	ll_read
	puls	b,x,pc
	


;;; Dump 128 byte to screen
;;;   takes: X = ptr to data
;;;   modifies: nothing
dump
	pshs	d,x
	jsr	putCR
	lda	#8
	pshs	a		; put row counter
b@	lda	#8		; column counter
	pshs	x
a@	ldb	,x+
	jsr	putb
	jsr	putSP
	deca
	bne	a@
	puls	x
	clr	8,x
	jsr	putscr
	dec	,s
	bne	b@
	leas	1,s
	puls	d,x,pc

;;; Print a Space
putSP
	pshs	b
	ldb	#SP
	jsr	putc
	puls	b,pc

	
;;; Print a CR
putCR
	pshs	d
	ldb	#$3b
	stb	$ffa0
	ldd	SCRPTR
	addd	#32-8
	andb	#~$1f
	addd	#8
	std	SCRPTR
	clr	$ffa0
	puls	d,pc


;;; Print a Z string
;;;   takes: X = ptr to string
;;;   modifies: nothing
puts
	pshs	b,x
a@	ldb	,x+
	beq	done@
	jsr	putc
	bra	a@
done@	puls	b,x,pc	
	
;;; Print a 3 byte value ( in hex )
;;;   takes: X = ptr to value
;;;   modifies: nothing
put3
	pshs	d,x
	ldd	,x++
	jsr	putw
	ldb	,x
	jsr	putb
	puls	d,x,pc
	

;;; Print a word ( in hex)
;;;   takes: D = word
;;;   modifies: nothing
putw
	pshs	b
	tfr	a,b
	bsr	putb
	puls	b
	bsr	putb
	rts
	
;;; Print a byte (in hex)
;;;   takes: B = byte
;;;   modifies: nothing
putb
	pshs	d
	lsrb
	lsrb
	lsrb
	lsrb
	bsr	putn
	ldb	1,s
	bsr	putn
	puls	d,pc

;;; Print a Char
;;;   takes: B = charactor
;;;   modifies: nothing
putc
	pshs	d,x
	lda	#$3b		; put 3b in bank 0
	sta	$ffa0
	ldx	SCRPTR
	stb	,x+
	stx	SCRPTR
	clr	$ffa0		; put 0 in bank 0
	puls	d,x,pc
	
	
;;; Print a nibble
;;;   takes: B = nibble
;;;   modifies: nothing
putn
	pshs	b
	andb	#$f
	addb	#$30
	cmpb	#$39
	bls	a@
	addb	#7
a@	jsr	putc
	puls	b,pc
	

;;; Print a string followed by a CR
;;;   takes: X = zero termed string
;;;   returns: nothing
;;;   modifies: nothing
putscr
	jsr	puts
	jsr	putCR
	rts