rspboot.s 3.72 KB

/*
 * rspboot.s
 *
 * Fri Apr  7 10:35:20 PDT 1995
 *
 * The RSP boot ucode is loaded by the host processor.
 *
 * The task header (OSTask) is loaded by the host processor into
 * the very end of DMEM.
 *
 */

#include <rcp.h>
#include <rsp.h>
#include <os.h>
#include <sptask.h>

		.text		RSPBOOTBASE

.name	zero,	$0
.name	taskp,	$1
.name	tmp,	$30
.name	return,	$31
	
RSPBoot:	
		/*
		 * Jump to beginning of Boot routine
		 */
		j	checkDP
 		addi	taskp, zero, ((SP_DMEM_END)+(-(OS_TASK_SIZE))+1)
 ### BRANCH OCCURS HERE TO checkDP:
	
 # register $1 now has the task header address
 #
 # format for the task header:
 #	(see os.h)
 #

 #
 # Load the ucode:
 #
loadUCode:
		lw	$2, OS_TASK_OFF_UCODE(taskp)		# ucode pointer
		addi	$3, zero, ((4096)+(-(32*4))+(-1))	# ucode size

.name	task_base,	$7
	
		addi	task_base, zero, TASKBASELO
		mtc0	$7, DMA_CACHE
		mtc0	$2, DMA_DRAM
		mtc0	$3, DMA_READ_LENGTH

loadcodeloop:	mfc0	$4, $6	# wait for the code to load
		bne	$4, zero, loadcodeloop
		nop

		jal	YieldCheck	# Do we need to yield?
		nop

	# jump to beginning of task.
 		jr	task_base
		mtc0	zero, SP_RESERVED	# delay slot

.name	yield,	$8
YieldCheck:
		mfc0    yield, SP_STATUS
		andi    yield, yield, SP_STATUS_YIELD
		bne     yield, zero, doYield
		nop
		jr	return

#define BOOT_YIELD (SP_SET_TASKDONE|SP_SET_YIELDED|SP_CLR_YIELD)
doYield:

		mtc0	zero, SP_RESERVED	# delay slot
		ori     yield, zero, BOOT_YIELD
		mtc0    yield, SP_STATUS                # DONE, Boot Yield
		break
		nop

.unname	yield

 #################################################################
 ####    Stuff after this point may be overwritten by IMEM    ####
 #################################################################

   # 
   # This is where the boot routine begins
   #

   #
   # if the OS_TASK_DP_WAIT flag is set in the task header
   # then wait for the DP to complete before loading
   # DMEM (This is neccessary because the DP may be reading
   # a display list which is still in DMEM).	
   #
.name	flag,	$2
checkDP:
			lw	flag, OS_TASK_OFF_FLAGS(taskp)
			andi	flag, flag, OS_TASK_DP_WAIT
			beq	flag, zero, LoadDMEM
			nop
 ### BRANCH TO LoadDMEM IF OS_TASK_DP_WAIT FLAG IS NOT SET

   #
   # Spin until the 'dma busy' in DPC_STATUS_REG is clear (meaning the
   # DP has read out all of the current display list).  While waiting
   # continuously check the yield bit by calling YieldCheck in case
   # a yield is required before the audio task is complete
   #
			jal	YieldCheck		# Do we need to yield?
			nop

doDPWait:		mfc0	flag, CMD_STATUS
			andi	flag, flag, 0x100	# dma busy
			bgtz	flag, YieldCheck	# Do we need to yield?
			nop
 ### BRANCH TO YieldCheck (THEN LOOP TO doDPWait UNTIL DP IS FINISHED)
.unname	flag
	

   #
   # Prepare to load the DMEM for the next task
   #
.name	daddr,	$2
.name	dsize,	$3
LoadDMEM:
		lw	daddr, OS_TASK_OFF_UDATA(taskp)
		lw	dsize, OS_TASK_OFF_UDATA_SZ(taskp)
		addi	dsize, dsize, -1	# need length - 1

#if 0
	# request DMA access: (get semaphore)
	ReqDMA:
		mfc0	tmp, SP_RESERVED
		bne	tmp, zero, ReqDMA
		nop
#endif
	#
	# Wait until the DMA is available
	#
	DMAFull:
		mfc0	tmp, DMA_FULL
		bne	tmp, zero, DMAFull
		nop
 ### LOOP UNTIL DMA IS AVAILABLE
	
	# WARNING!
	# We should check here to enforce that we don't overwrite
	# the task header. The ucode will need it...
	#
	
	# this is an optimization, the PDATA is first in dmem...

   #
   # Load  DMEM for the next task
   #
		mtc0	zero, DMA_CACHE
		mtc0	daddr, DMA_DRAM
		mtc0	dsize, DMA_READ_LENGTH
	
   #
   # wait for the DMA to complete
   #
loaddataloop:	mfc0	$4, $6	# wait for the data to load
		bne	$4, zero, loaddataloop
		nop
 ### LOOP UNTIL DMA IS COMPLETE

		jal	YieldCheck	# Do we need to yield?
		nop

 		j	loadUCode
		nop

.unname	daddr
.unname	dsize
.unname	zero
.unname	tmp
.unname	return