1
0
Files
irix-657m-src/stand/arcs/IP21prom/epcuart.s
2022-09-29 17:59:04 +03:00

241 lines
5.9 KiB
ArmAsm

/***********************************************************************\
* File: epcuart.s *
* *
* Contains simple read and write routines for the IO4 EPC UART. *
* These routines are written in assembler so that they can *
* easily be called even when we have no stack. *
* *
* WARNING: *
* init_epc_uart() must be called before these routines will work. *
* *
\***********************************************************************/
#include "ml.h"
#include <sys/regdef.h>
#include <asm.h>
#include <sys/sbd.h>
#include <sys/cpu.h>
#include <sys/EVEREST/epc.h>
#include <sys/z8530.h>
#include "ip21prom.h"
#define CNTRL 0x0
#define DATA 0x10
/*
* Routine epcuart_getc
* Read a character from the EPC uart. This routine will never return
* unless a character is available. Use epcuart_poll to check whether
* a character is available.
* Arguments:
* a0 -- Selected channel
* Returns:
* v0 -- the character read.
* Uses registers:
* a0, a1, v0, v1.
*/
LEAF(epcuart_getc)
.set noreorder
GET_DUARTBASE(a1)
dadd a0, a1 # Add
2:
lb a1, CNTRL(a0) # Read the EPC UART control reg
andi v0, a1, RR0_RX_CHR # Check to see if chr was recvd.
beqz v0, 2b # If not received, jump back to top
nop # (BD)
3:
li a1, RR1
sb a1, CNTRL(a0) # Tell uart we want the RR1 register
nop
lb a1, CNTRL(a0) # Actually perform the read
nop
lb v0, DATA(a0) # Read the data register.
andi a1, (RR1_RX_ORUN_ERR | RR1_FRAMING_ERR | RR1_PARITY_ERR)
beq a1, zero, 9f # If an ERROR occurred THEN
nop # (BD)
move v0, zero # Put a zero into the return value
9:
j ra # Return
nop # (BD)
END(epcuart_getc)
/*
* epcuart_flush
* Flushes the input buffer of the UART.
* Arguments:
* a0 -- Selected channel number.
* Uses:
* a0, v0
*/
LEAF(epcuart_flush)
.set noreorder
GET_DUARTBASE(v0)
dadd a0, v0 # Add in the channel selector
lb v0, CNTRL(a0) # Read the control reg.
andi v0, RR0_RX_CHR # Check to see if char was recvd.
beqz v0, 3f # Goto end if no character.
nop #
lb v0, DATA(a0) # Read the character
3:
j ra # Return
nop #
END(epcuart_flush)
/*
* Routine epcuart_putc
* Writes a single character to the EPC UART.
*
* Arguments:
* a0 -- the byte to write.
* a1 -- the channel to write to.
* Returns:
* nothing.
* Uses registers:
* a0, a1, v0, v1.
*/
LEAF(epcuart_putc)
.set noreorder
GET_DUARTBASE(v0)
dadd a1, v0 # Add in the channel selector
li v0, 10000 # Number of retry attempts
1:
lb v1, CNTRL(a1) # Read the control register
nop
andi v1, RR0_TX_EMPTY # UNTIL ready to transmit
bnez v1, 2f # OR
subu v0, 1 # (BD) (--cnt == 0)
bnez v0, 1b #
nop # (BD)
j ra
nop # (BD)
2:
j ra # Return
sb a0, DATA(a1) # Write the character out
END(epcuart_putc)
/*
* Routine epcuart_poll
* Checks to see whether a character is available for reading.
* If a character is available, v0 will be non-zero.
* Arguments
* a0 -- Channel to poll on.
* Returns:
* v0 -- Non-zero if a character is available, zero otherwise.
* Uses registers:
* a0, v0.
*/
LEAF(epcuart_poll)
.set noreorder
GET_DUARTBASE(v0)
dadd v0, a0 # Add in the channel selector
1:
lb v0, CNTRL(v0) # Read
nop
j ra # Return
andi v0, RR0_RX_CHR
END(epcuart_poll)
/*
* Routine epc_puthex
* Writes a 64-bit hex number to EPC UART.
*
* Arguments:
* a0 -- the 64-bit hex number to write.
* a1 -- Channel to write to.
* Returns:
* v0 -- Success. Non-zero indicates write successful.
* Uses registers:
* a0, a1, a2, v0, v1, ta1, ta2, ta3, t8, t9
*/
LEAF(epcuart_puthex)
.set noreorder
move t9, ra
jal getendian
li t8, 16
move ta2, v0
move ta1, a0 # Copy argument to ta1
move a2, a1 # Save channel value
2:
dsrl a0,ta1,30 # Shift right 60 bits ($@!&*# assembler
dsrl a0,a0,30 # won't assemble srl32 a0,ta1,28)
# This isolates the rightmost nibble
dla ta3,hexdigit
beq ta2,zero,3f # 0 = big endian
daddu a0,ta3 # (BD)
xor a0,3 # assumes hexdigit burned in eb order
3:
jal get_char
nop # (BD)
move a1, a2 # Reload channel information
jal epcuart_putc # Print it
move a0, v0 # (BD) Load character to be written
beqz v0, 4f # If putc fails, give up on the number
sub t8,1 # Entire number printed?
bne t8,zero,2b
dsll ta1,4 # Set up next nibble
4:
j t9 # Yes - done
nop
END(epcuart_puthex)
/*
* Routine epcuart_puts
* Writes a null-terminates string to the EPC UART.
*
* Arguments:
* a0 -- the address of the first character of the string.
* a1 -- The channel to write to.
* Returns:
* v0 -- If non-zero, puts (probably) succeeeded. Otherwise, it failed.
* Uses:
* a0, a1, a2, v0, v1, ta2, ta3, t8, t9
*/
LEAF(epcuart_puts)
.set noreorder
move t9, ra # Save the return address
move ta3, a0 # Save the argument register
move a2, a1 # Save the channel number
jal getendian # Get endianess
nop
move t8, v0 # Put endianess in t8
1:
beq t8, zero, 2f # Skip to write char if big-endian
move ta2, ta3 # (BD) Copy next_char to curr_char
xor ta2, 3 # If EL, swizzle the bits
2:
jal get_char
move a0, ta2
move a0, v0
dadd ta3, 1 # Increment next char.
beq a0, zero, 3f # If char == zero, return
nop # (BD)
jal epcuart_putc #
move a1, a2 # (BD) Reload channel number
beqz v0, 3f # If putc fails, give up on the string
nop # (BD)
b 1b # Loop back up
nop # (BD)
3:
j t9 # Return
nop # (BD)
END(epcuart_puts)