goutfifo.s 4.33 KB


 ############################################################################
 #
 # Output coordination routines:
 #
 # We support three cases:
 #
 #      1.) output directly to RDP using DMEM as buffer. Requires
 #          producer/consumer synchronization.
 #
 #      2.) output routed to DRAM. In this case, we use DMEM as
 #          a temporary buffer, then DMA out to DRAM.
 #
 #	3.) output routed to DRAM, but DRAM is utilized as a circular 
 #	    buffer
 #
 # Goals:
 #
 #      - small code size.
 #      - efficient and non-obtrusive
 #      - flexible, can easily route to DRAM or RDP.
 #
 # In order to do this, and make it transparent to the parts of the
 # code which do the writing, we implement an open/close interface.
 #
 # FUNCTION:        OUTPUT TO RDP:                  OUTPUT TO DRAM:
 #-------------------------------------------------------------------------
 # open(size)   - wait for size avail in        - does nothing
 #                ring buffer.
 #              - possibly handle wrap
 #              - wait for 'current' to get
 #                out of the way
 #
 # close()      - advance CP0 pointer           - do DMA of cmd to DRAM
 #                                              - increment pointers
 #                                              - reset DMEM buffer
 #
 # In between the open() and close(), the ucode writes the data to DMEM.
 # (to either the RDP ring buffer or a temp buffer to be DMA'd)
 #
 ############################################################################

 # DMEM is utilized as follows for this output routine:
 # RSP_STATE_FIFO_OUTP:		pointer in dram to next empty ring buffer entry
 # RSP_STATE_FIFO_BUF_TOP:	pointer in dram to beginning of ring buffer
 # RSP_STATE_FIFO_BUF_END:	pointer in dram to end of ring buffer
 #                                 (ie the byte following the ring buffer)

        #
        # These registers used by both routines.
        #
.name   dmemp,          $20
.name   dramp,          $19
.name   outsz,          $18 # set by caller to max size to write

 ############################################################################
 #
 # 
 #
#if !(defined(OUTPUT_DRAM)||defined(OUTPUT_FIFO))
                .ent    OutputOpen

OutputOpen:
                jr      return
                nop

                .end    OutputOpen
#endif /* !(OUTPUT_DRAM || OUTPUT_FIFO) */
 #
 #
 #
 ############################################################################

 ############################################################################
 #
 #
 #
                .ent    OutputClose

OutputClose:
 # check if the packet will fit in the buffer
		add	$21, zero, return
		lw	dramp, RSP_STATE_FIFO_OUTP(rsp_state)
		addi	outsz, outp, (-1*RSP_OUTPUT_OFFSET)
		lw	outp,  RSP_STATE_FIFO_BUF_END(rsp_state)
		blez	outsz, CloseDone
		add	dmemp, dramp, outsz		# end data in dram
		sub	dmemp, outp, dmemp		# bigger than buffer?
                bgez    dmemp, CurrentFit

WrapBuffer:
 # packet will not fit, wait for current to wrap
                mfc0    dmemp, CMD_STATUS
                andi    dmemp, dmemp, 0x0400
                bne     dmemp, zero, WrapBuffer
                # note delay slot

 # wait for current to advance
AdvanceCurrent:
                mfc0    outp, CMD_CURRENT		# outp = current
		lw	dramp, RSP_STATE_FIFO_BUF_TOP(rsp_state) # buffer start
                beq     outp, dramp, AdvanceCurrent
                nop
                mtc0    dramp, CMD_START         # reset START
CurrentFit:
                # done if current_address <= dramp
                mfc0    outp, CMD_CURRENT		# outp = current
                sub     dmemp, dramp, outp
                bgez    dmemp, CloseDMA
                # note delay slot

                # loop if current_address <= (outp + outsz)
                add     dmemp, dramp, outsz
                sub     dmemp, dmemp, outp
                bgez    dmemp, CurrentFit
                nop
CloseDMA:
		add	outp, dramp, outsz
		addi	outsz, outsz, -1
		addi	dmemp, zero, RSP_OUTPUT_OFFSET
		jal	DMAproc
		addi	$17, zero, 1	# set 'iswrite'
		jal	DMAwait
		sw	outp, RSP_STATE_FIFO_OUTP(rsp_state)
		mtc0	outp, CMD_END

CloseDone:
                jr      $21
                addi	outp, zero, RSP_OUTPUT_OFFSET

                .end    OutputClose
 #
 #
 #
 ############################################################################

.unname outsz
.unname dramp
.unname dmemp