.set noreorder .include "hwregs_a.h" .section .text .global DMACallback .type DMACallback, @function DMACallback: # a0 - DMA channel # a1 - Callback function addiu $sp, -8 sw $ra, 0($sp) beqz $a1, .Lremove_cb # Remove callback if function is NULL nop addiu $sp, -8 # Install IRQ handler for DMA handler sw $a0, 0($sp) # if not set installed yet sw $a1, 4($sp) jal GetInterruptCallback li $a0, 3 bnez $v0, .Lskip_install nop la $a1, _dma_handler jal InterruptCallback li $a0, 3 .Lskip_install: lw $a0, 0($sp) lw $a1, 4($sp) addiu $sp, 8 la $v0, _dma_func_table sll $v1, $a0, 2 addu $v0, $v1 lw $v1, 0($v0) sw $a1, 0($v0) sw $v1, 4($sp) lui $a2, IOBASE lw $v0, DICR($a2) # Enable DMA interrupt lui $v1, 0x1 sll $v1, $a0 or $v0, $v1 lui $v1, 0x80 or $v0, $v1 sw $v0, DICR($a2) b .Lskip_remove nop .Lremove_cb: la $v0, _dma_func_table # Set callback address sll $v1, $a0, 2 addu $v0, $v1 lw $v1, 0($v0) sw $a1, 0($v0) sw $v1, 4($sp) lui $a2, IOBASE # Disable DMA interrupt lw $v0, DICR($a2) lui $v1, 0x1 sll $v1, $a0 .set noat addiu $at, $0, -1 xor $v1, $at and $v0, $v1 lui $v1, 0x7f00 xor $v1, $at and $v0, $v1 .set at sw $v0, DICR($a2) jal _dma_has_cb # Check if callbacks are present nop bnez $v0, .Lskip_remove nop sw $0 , DICR($a2) jal GetInterruptCallback # Check if callback is the DMA handler li $a0, 3 la $v1, _dma_handler bne $v0, $v1, .Lskip_remove nop li $a0, 3 jal InterruptCallback move $a1, $0 .Lskip_remove: lw $ra, 0($sp) lw $v0, 4($sp) jr $ra addiu $sp, 8 .type _dma_has_cb, @function _dma_has_cb: la $v1, _dma_func_table li $t0, 6 .Lscan_loop: lw $v0, 0($v1) addiu $v1, 4 bnez $v0, .Lhas_cb nop bgtz $t0, .Lscan_loop addiu $t0, -1 jr $ra move $v0, $0 .Lhas_cb: jr $ra li $v0, 1 .type _dma_handler, @function _dma_handler: addiu $sp, -12 sw $ra, 0($sp) sw $s0, 4($sp) sw $s1, 8($sp) move $s0, $0 la $s1, _dma_func_table .Lhandler_loop: lui $a0, IOBASE lw $v0, DICR($a0) li $v1, 24 addu $v1, $s0 srl $v0, $v1 andi $v0, 0x1 lw $v1, 0($s1) beqz $v0, .Lno_irq addiu $s1, 4 beqz $v1, .Lno_irq nop jalr $v1 nop .Lno_irq: blt $s0, 6, .Lhandler_loop addi $s0, 1 lui $a0, IOBASE lw $v0, DICR($a0) nop sw $v0, DICR($a0) lw $ra, 0($sp) lw $s0, 4($sp) lw $s1, 8($sp) jr $ra addiu $sp, -12 .section .data _dma_func_table: .word 0 .word 0 .word 0 .word 0 .word 0 .word 0 .word 0