📄 drivers.asm
字号:
// Page 0 -> 1, PSTART(at page 0)=0x46/CR=0x61
R1 = RTL8019AS_CR_STOP|RTL8019AS_CR_ABORT|RTL8019AS_CR_P1
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R1, BP
// 15. Write Port (IOBase + 0x01 - 0x06) with Ethernet Address Byte 0 - Byte5
// Page 1, PAR0=0x52
R1 = [_guwEthAddr+0] // PAR0/PAR1
R1 = R1 lsr 4
R1 = R1 lsr 4
RTL8019AS_WR_WORD RTL8019AS_ADDR_01, R1, BP
// Page 1, PAR1=0x54
R1 = [_guwEthAddr+0] // PAR0/PAR1
RTL8019AS_WR_WORD RTL8019AS_ADDR_02, R1, BP
// Page 1, PAR2=0xab
R1 = [_guwEthAddr+1] // PAR2/PAR3
R1 = R1 lsr 4
R1 = R1 lsr 4
RTL8019AS_WR_WORD RTL8019AS_ADDR_03, R1, BP
// Page 1, PAR3=0x1d
R1 = [_guwEthAddr+1] // PAR2/PAR3
RTL8019AS_WR_WORD RTL8019AS_ADDR_04, R1, BP
// Page 1, PAR4=0xa4
R1 = [_guwEthAddr+2] // PAR4/PAR5
R1 = R1 lsr 4
R1 = R1 lsr 4
RTL8019AS_WR_WORD RTL8019AS_ADDR_05, R1, BP
// Page 1, PAR5=0xf9
R1 = [_guwEthAddr+2] // PAR4/PAR5
RTL8019AS_WR_WORD RTL8019AS_ADDR_06, R1, BP
// 16. Write Port (IOBase + 0x7) with 0x47, Set Current Page Register
// 17. Write Port (IOBase + 0x08 - 0x0F) with Multicast Address Byte 0 - Byte 7
// Page 1, CPR =0x47
R1 = RTL8019AS_CPR
RTL8019AS_WR_WORD RTL8019AS_ADDR_07, R1, BP
// Page 1, MAR1=0x41/MAR0=0x00
R1 = RTL8019AS_MAR0
RTL8019AS_WR_WORD RTL8019AS_ADDR_08, R1, BP
R1 = RTL8019AS_MAR1
RTL8019AS_WR_WORD RTL8019AS_ADDR_09, R1, BP
// Page 1, MAR3=0x80/MAR2=0x00
R1 = RTL8019AS_MAR2
RTL8019AS_WR_WORD RTL8019AS_ADDR_0A, R1, BP
R1 = RTL8019AS_MAR3
RTL8019AS_WR_WORD RTL8019AS_ADDR_0B, R1, BP
// Page 1, MAR5=0x00/MAR4=0x00
R1 = RTL8019AS_MAR4
RTL8019AS_WR_WORD RTL8019AS_ADDR_0C, R1, BP
R1 = RTL8019AS_MAR5
RTL8019AS_WR_WORD RTL8019AS_ADDR_0D, R1, BP
// Page 1, MAR7=0x00/MAR6=0x00
R1 = RTL8019AS_MAR6
RTL8019AS_WR_WORD RTL8019AS_ADDR_0E, R1, BP
R1 = RTL8019AS_MAR7
RTL8019AS_WR_WORD RTL8019AS_ADDR_0F, R1, BP
// 18. Write Port (IOBase + 0x00) with 0x21, Set to Page 0
// Page 1 -> 0, PAR0(at page 1)=0x52/CR=0x21
R1 = RTL8019AS_CR_P0|RTL8019AS_CR_ABORT|RTL8019AS_CR_STOP
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R1, BP
// 19. Write Port (IOBase + 0x0E) with 0x89, Word-wide data transfer, Normal
// Page 0, IMR=0x0f/DCR=0x89
R1 = RTL8019AS_DCR
RTL8019AS_WR_WORD RTL8019AS_ADDR_0E, R1, BP
// 20. Write Port (IOBase + 0x0D) with 0xf0, TCR, Normal
// Page 0, TCR=0xf0/RCR=0xcc
R1 = RTL8019AS_TCR
RTL8019AS_WR_WORD RTL8019AS_ADDR_0D, R1, BP
// 21. Write Port (IOBase + 0x00) with 0x22, Set to Page 0 and Start work
// Page 0, CR=0x22
R1 = RTL8019AS_CR_P0|RTL8019AS_CR_ABORT|RTL8019AS_CR_START
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R1, BP
R1 = 1
RTL8019AS_INIT_EXIT:
// Recall default IO Statue
SP_RECALL_IO BP
pop BP from [SP]
retf
.endp
//////////////////////////////////////////////////////////////////
// Function: void RTL8019AS_TX(UINT16 ByteLen, UINT16 *mbuf)
// ByteLen: 传送以太包的字节数
// mbuf: 以太包缓冲区的首指针
//////////////////////////////////////////////////////////////////
.code
.public _RTL8019AS_TX
_RTL8019AS_TX: .proc
push R1,BP to [SP]
BP = SP + 2 + 5 + 1 //
R4 = [BP++] // R4 record Packet bye length
BP = [BP] // Get mbuf Point to BP
// Chang IOA to output
SP_IOA_OUT R3
// 1. Write port (IOBase + 0x05) with low byte of packet length
// Page 0, TBCR0/TPSR
RTL8019AS_WR_WORD RTL8019AS_ADDR_05, R4, R3
// 2. Write port (IOBase + 0x06) with high byte of packet length
// Page 0, ISR=0xff/TBCR1
R3 = R4 lsr 4
R3 = R3 lsr 4
RTL8019AS_WR_WORD RTL8019AS_ADDR_06, R3, R2
// 3. Write port (IOBase + 0x08) with 0x00
// 4. Write port (IOBase + 0x09) with 0x40
// Page 0, RSAR1=0x40/RSAR0=0x00
R3 = 0x00
RTL8019AS_WR_WORD RTL8019AS_ADDR_08, R3, R2
R3 = RTL8019AS_TPSR
RTL8019AS_WR_WORD RTL8019AS_ADDR_09,R3, R2
// 5. Write port (IOBase + 0x0A) with low byte of packet length
// 6. Write port (IOBase + 0x0B) with high byte of packet length
// Page 0, RBCR1/RBCR0
RTL8019AS_WR_WORD RTL8019AS_ADDR_0A, R4, R3
R3 = R4 lsr 4
R3 = R3 lsr 4
RTL8019AS_WR_WORD RTL8019AS_ADDR_0B, R3, R2
// 7. Write port (IOBase + 0x00) with 0x12
// Page 0, PSTART=0x46/CR=0x12
R3 = RTL8019AS_CR_WRITE|RTL8019AS_CR_START|RTL8019AS_CR_P0
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R3, R2
// 8. Write port (IOBase + 0x10) with first word of packet for (packet length/2) times
RTL8019AS_TX_1:
R1 = [BP++] // Get data
// Exchange high 8bit to low 8bit
R2 = R1 lsl 4
R1 = R1 rol 4 //
R2 = R1 lsl 4 //
R1 = R1 rol 4 //
// Write 1 Word to RTL8019AS
RTL8019AS_WR_WORD RTL8019AS_ADDR_10, R1, R3
// Count
R4 -= 2 // Count 2 byes
jg RTL8019AS_TX_1 // Write (bye length)/2 times
// 9. Write port (IOBase + 0x00) with 0x26
// Page 0, PSTART=0x46/CR=0x26
BP = RTL8019AS_CR_ABORT|RTL8019AS_CR_TXP|RTL8019AS_CR_START|RTL8019AS_CR_P0
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, BP, R4
// Recall default IO Statue
SP_RECALL_IO BP
pop R1, BP from [SP]
retf
.endp
//////////////////////////////////////////////////////////////////
// Function: UINT16 RTL8019AS_RX(UINT16 *mbuf)
// mbuf: 以太包缓冲区的首指针
// 返回接收以太包的字节数。如果是0,则没有包。
//////////////////////////////////////////////////////////////////
.code
.public _RTL8019AS_RX
_RTL8019AS_RX: .proc
push R2,BP to [SP]
// 1. Read port (IOBase + 0x03) to get BNRY
RTL8019AS_RD_WORD RTL8019AS_ADDR_03, R1, BP
BP = R1 & 0x00ff; // 清除高8位,保留 BNRY 到 BP
// 2. Read port (IOBase + 0x07), Get CPR
// 2.1 Change IOA to output
SP_IOA_OUT R4
// 2.2 Page 0 -> 1
R4 = RTL8019AS_CR_START|RTL8019AS_CR_ABORT|RTL8019AS_CR_P1
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R4, R3
// 2.3 Change IOA to input
SP_IOA_IN R4
// 2.4 Read port (IOBase + 0x07), Get CURR
RTL8019AS_RD_WORD RTL8019AS_ADDR_07, R1, R4
R4 = R1&0x00ff // 清除高8位,保留 CURR 给 R4
// 2.5 Change IOA to output
SP_IOA_OUT R3
// 2.6 Page 1 -> 0
R3 = RTL8019AS_CR_START|RTL8019AS_CR_ABORT|RTL8019AS_CR_P0
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R3, R2
// 3. Compare: if BNRY+1 != CURR? Some Packet is coming! goto 6.
BP += 1 // 从这里开始,以下程序不允许改变 BP 值,保存将要读取的包的CPR
cmp BP, R4 // BNRY+1 == CURR ?
jnz RTL8019AS_RX_2 // 从这里开始,以下程序可以改变 R4 值。
// 3.1 Change IOA to input
SP_IOA_IN R4
// 4. If no packet is received, Read port (IOBase + 0x07), Get ISR
RTL8019AS_RD_WORD RTL8019AS_ADDR_07, R1, R3
// 5 Check RTL8019AS buffer is overflow? If yes, call RTL8019AS_INIT and return 0.
test R1, RTL8019AS_ISR_OVW
jz RTL8019AS_RX_1 // no packet reived! Normal statue.
PC = RTL8019AS_RX_ERROR // no packet reived! 8019AS memory overflow!!!
RTL8019AS_RX_1:
R4 = 0 // Return 0 Packet length
PC = RTL8019AS_RX_EXIT
RTL8019AS_RX_2:
// Change IOA to output
SP_IOA_OUT R3
// 6. Write port (IOBase + 0x08) with 0x00
// 7. Write port (IOBase + 0x09) with value of last current page register
// Page 0, Remote Start page Address
R3 = 0x00
RTL8019AS_WR_WORD RTL8019AS_ADDR_08, R3, R2
RTL8019AS_WR_WORD RTL8019AS_ADDR_09, BP, R3
// 8. Write port (IOBase + 0x0A) with 0x04
// 9. Write port (IOBase + 0x0B) with 0x00
// Page 0, Remote Byte Count
R3 = 0x04
RTL8019AS_WR_WORD RTL8019AS_ADDR_0A, R3, R2
R3 = 0x00
RTL8019AS_WR_WORD RTL8019AS_ADDR_0B, R3, R2
// 10. Write port (IOBase + 0x00) with 0x0A
// Page 0, Remote Read Command
R3 = RTL8019AS_CR_READ|RTL8019AS_CR_START|RTL8019AS_CR_P0
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, R3, R2
// Change IOA to input
SP_IOA_IN R3
// 11. Read port (IOBase + 0x10) and get first word of packet
// (Next Page Number-high_8bit and RX STATUS-low_8bit)
// Page 0, Read 'RTL8019AS Data Port'
RTL8019AS_RD_WORD RTL8019AS_ADDR_10, R3, R4
// R3 Saved (Next Page Number and RX STATUS)
// 12. Read port (IOBase + 0x10) and get second word of packet
// (Packet Length)
RTL8019AS_RD_WORD RTL8019AS_ADDR_10, R4, R2
R4 -= 4
// R4 Saved (Packet Length), Throw away 4 byte CRC
// 13. Check Receice Error. Yes, call RTL8019AS_INIT and return.
test R3, 0x0001 // Error Receiver
jnz RTL8019AS_RX_3
PC = RTL8019AS_RX_ERROR
// 14. Check Packet Length <= 1514? If no, call RTL8019AS_INIT and return 0.
RTL8019AS_RX_3:
cmp R4, 1514
jna RTL8019AS_RX_4
PC = RTL8019AS_RX_ERROR
RTL8019AS_RX_4:
// Chang IOA to output
SP_IOA_OUT R2
// 15. Write port (IOBase + 0x08) with 0x04
// 16. Write port (IOBase + 0x09) with value of last current page register
// Page 0, Remote Start page Address
R2 = 0x04
RTL8019AS_WR_WORD RTL8019AS_ADDR_08, R2, R1
RTL8019AS_WR_WORD RTL8019AS_ADDR_09, BP, R2 // 从这里开始,以下程序可以改变 BP 值
// 17. Write port (IOBase + 0x0A) with low byte of packet length
// 18. Write port (IOBase + 0x0B) with high byte of packet length
// Page 0, Remote Bye Count,Throw away 4 CRC bytes
RTL8019AS_WR_WORD RTL8019AS_ADDR_0A, R4, BP
BP = R4 lsr 4
BP = BP lsr 4
RTL8019AS_WR_WORD RTL8019AS_ADDR_0B, BP, R2
// 19. Write port (IOBase + 0x00) with 0x0A
// Page 0, Remote Read Command
BP = RTL8019AS_CR_READ|RTL8019AS_CR_START|RTL8019AS_CR_P0
RTL8019AS_WR_WORD RTL8019AS_ADDR_00, BP, R2
// Change IOA to input
SP_IOA_IN BP
// Get Point mbuf
BP = SP + 2 + 4 + 1
BP = [BP]
// push (Next Page Number and RX STATUS) and (Packet Length) to [SP]
push R3,R4 to [SP]
RTL8019AS_RX_5:
// 20. Read port (IOBase + 0x10) for (packet length / 2) times
// to get packet data
RTL8019AS_RD_WORD RTL8019AS_ADDR_10, R1, R3
// Exchange high 8bit to low 8bit
R2 = R1 lsl 4
R1 = R1 rol 4
R2 = R1 lsl 4
R1 = R1 rol 4
// Write to mbuf
[BP++] = R1
// Count
R4 -= 2
jg RTL8019AS_RX_5 // if (R4 > 0) continue.
pop R3, R4 from [SP] // Restore (Next Page Number and RX STATUS) and (Packet length)
// Chang IOA into output
SP_IOA_OUT BP
// 21. Write port (IOBase + 0x03) with the value of next_page _point -1
R2 = R3 lsr 4 // Clear RX STATUS, R2 = Next_Page_Point(high 8bit)
R2 = R2 lsr 4
R2 -= 1 // BNRY = (Next Page Number) - 1
RTL8019AS_WR_WORD RTL8019AS_ADDR_03, R2, BP
jmp RTL8019AS_RX_EXIT
RTL8019AS_RX_ERROR:
call _RTL8019AS_INIT
R4 = 0 // Return 0 Packet length
RTL8019AS_RX_EXIT:
// Recall default IO Statue
SP_RECALL_IO BP
R1 = R4 // Return Packet length
pop R2, BP from [SP]
retf
.endp
//////////////////////////////////////////////////////////////////
// Function: void MEMCPY(UINT16 ByteLen, UINT16 *inbuf, UINT16 *outbuf)
// Function: copy memory regions
// Description: <outbuf>表示输出word类型的内存指针
// <inbuf>表示输入word类型的内存指针
// <Byte>表示要拷贝的字节数(bytes)
// 不对<outbuf>做边界校验!!!
//////////////////////////////////////////////////////////////////
.code
.public _MEMCPY
_MEMCPY: .proc
push R2, BP to [SP]
BP = SP + 2 + 4 + 1
R4 = [BP++] // Get: ByteLen
R3 = [BP++] // Get: inbuf
BP = [BP] // Get: outbuf
MEMCPY_1:
R2 = [R3++]
[BP++] = R2
R4 -= 2
jg MEMCPY_1
pop R2, BP from [SP]
retf
.endp
////////////////////////////////////////////////////////////////////////
// UINT16 checksum(UINT16 ByteLen, UINT16 *mbuf)
// TCP/IP 通用校验和过程。由于用汇编,所以只适宜BIG_ENDIAN模式。
// ByteLen: 长度bytes,必须满足条件:ByteLen >= 2 否则计算没有意义
// mbuf: 存放Word缓冲区首指针
////////////////////////////////////////////////////////////////////////
.code
.public _checksum
_checksum: .proc
push R3, BP to [SP]
BP = SP + 2 + 3 + 1
R4 = [BP++] // Get: uwByteLen
BP = [BP] // Get: inbuf
R3 = R4 lsr 1
R1 = 0
checksum_1:
R1 += [BP++]
R1 += 0, Carry
R3 -= 1
jnz checksum_1
test R4, 0x0001 // 奇偶测试
jz checksum_even
// 是奇数长度:处理最后1个byte
R3 = [BP]
R3 &= 0xff00
R1 += R3
R1 += 0, Carry
checksum_even:
// 是偶数,结束处理
pop R3, BP from [SP]
retf
.endp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -