;*************************************************************************** ; ; File Name :"RTL8019.asm" ; Title :RTL8019AS Ethernet Controller driver ; Date :2002.11.22. ; Version :1.0.0 ; Support telephone :+36-70-333-4034, old: +36-30-9541-658 VFX ; Support fax : ; Support Email :info@vfx.hu ; Target MCU :AT90S8515 ; ;*************************************************************************** ; D E S C R I P T I O N ; ; EGZ-03002-v1 Ethernet Driver ; ; Support Devices ; RTL8019AS Ethernet Controller Card ; ; Provides functions to initialize the Realtek 8019AS, and send and retreive ; packets ; ;Ethernet Frame Header ; ; +--------------------------------------+ ; | Destination | Source | Frame | ; | Address | Address | Type | ; | (6 octets) | (6 octets) |(2 octets)| ; +--------------------------------------+ ; .EQU NICBASE = 0x4300h ; IRQ = 0 ; BOOTROM = none ;****************************************************************** ;* REALTEK CONTROL REGISTER OFFSETS ;* All offsets in Page 0 unless otherwise specified ;* All functions accessing CR must leave CR in page 0 upon exit ;****************************************************************** ; RTL8019AS Register Def .EQU NICCR = 0x00 ;Command Register R/W ;This register is used to select register pages, ;enable or disable remote DMA operation and ;issue commands. .EQU NICISR = 0x07 ;Interrupt Status Register, R/W in Page0 ;This register reflects the NIC status. The host ;reads it to determine the cause of an interrupt ;Individual bits are cleared by writing a "1" ;into the corresponding bit. ;It must be cleared after power up. .EQU NICIMR = 0x0F ;Interrupt Mask Register, W in Page0, Type=R in Page2 ;All bits correspond to the bits in the ISR register ;POWER UP=all 0s. Setting individual bits will ;enable the corresponding interrupts. .EQU NICDCR = 0x0E ;Data Configuration Register, Type=W in Page0, Type=R in Page2 .EQU NICTCR = 0x0D ;Transmit Configuration Register, Type=W in Page0, Type=R in Page2 .EQU NICTSR = 0x04 ;Transmit Status Register, Type=R in Page0 ;This register indicates the status of a packet transmission .EQU NICRCR = 0x0C ;Receive Configuration Register, Type=W in Page0, Type=R in Page2 .EQU NICRSR = 0x0C ;Receive Status Register, Type=R in Page0 .EQU NICCLDA0 = 0x01 .EQU NICCLDA1 = 0x02 ;Current Local DMA Registers Type=R in Page0 ;These two registers can be read to get the ;current local DMA address. .EQU NICPSTART = 0x01 ;Page Start Register, Type=W in Page0, Type=R in Page 2 ;The Page Start register sets the start page ;address of the receive buffer ring .EQU NICPSTOP = 0x02 ;Page Stop Register, Type=W in Page0, Type=R in Page2 ;The Page Stop register sets the stop page ;address of the receive buffer ring. In 8 bit ;mode the PSTOP register should not exceed ;to 0x60, in 16 bit mode the PSTOP register ;should not exceed to 0x80. .EQU NICBNRY = 0x03 ;Boundary Register, Type=R/W in Page0 ;This register is used to prevent overwrite ;of the receive buffer ring. It is typically ;used as a pointer indicating the last receive ;buffer page the host has read. .EQU NICTPSR = 0x04 ;Transmit Page Start Register, Type=W in Page0 ;This register sets the start page address of the ;packet to the transmitted .EQU NICTBCR0 = 0x05 .EQU NICTBCR1 = 0x06 ;Transmit Byte Count Registers, Type=W in Page0 ;These two registers set the byte counts of the ;packet to be transmitted. .EQU NICNCR = 0x05 ;Number of Collisions Register, Type=R in Page0 ;The register records the number of collisions ;a node experiences during a packet transmission. .EQU NICFIFO = 0x06 ;First In First Out Register, Type=R in Page0 ;This register allows the host to examine ;the contents of the FIFO after loopback. .EQU NICCRDA0 = 0x08 .EQU NICCRDA1 = 0x09 ;Current Remote DMA Address registers, Type=R in Page0 ;These two registers contain the current address of remote DMA. .EQU NICRSAR0 = 0x08 .EQU NICRSAR1 = 0x09 ;Remote Start Address Registers, Type=W in Page0 ;These two registers set the start address of ;remote DMA. .EQU NICRBCR0 = 0x0A .EQU NICRBCR1 = 0x0B ;Remote Byte Count Registers, Type=W in Page0 ;These two registers se the data byte counts of ;remote DMA. .EQU NICCNTR0 = 0x0D ;Frame Alignment Error Tally Counter Register, Type=R in Page0 .EQU NICCNTR1 = 0x0E ;CRC Error Tally Counter Register, Type=R in Page0 .EQU NICCNTR2 = 0x0F ;Missed Packet Tally Counter Register, Type=R in Page0 .EQU NICPAR0 = 0x01 .EQU NICPAR1 = 0x02 .EQU NICPAR2 = 0x03 .EQU NICPAR3 = 0x04 .EQU NICPAR4 = 0x05 .EQU NICPAR5 = 0x06 ;Physical Address Registers, Type=R/W in Page1 ;These registers contain my Ethernet node address ;and are used to compare the destination adderss ;of incoming packets for acceptation or rejection .EQU NICCURR = 0x07 ;Current Page Register, Type=R/W in Page1 ;This register points to the page address of ;the first receive buffer page to be used for ;a packet reception. .EQU NICMAR0 = 0x08 .EQU NICMAR1 = 0x09 .EQU NICMAR2 = 0x0A .EQU NICMAR3 = 0x0B .EQU NICMAR4 = 0x0C .EQU NICMAR5 = 0x0D .EQU NICMAR6 = 0x0E .EQU NICMAR7 = 0x0F ;Multicast Address Register, Type=R/W in Page1 ;These registers provide filtering bits of ;multicast addresses hashed by the CRC logic .EQU NICCR9346 = 0x01 ;Page 3 .EQU NICRDMAPORT = 0x10 .EQU NICRSTPORT = 0x18 ;***************************************************************************** ; ; RTL ISR Register Bits ; ;****************************************************************************/ .EQU ISR_RST = 7 .EQU ISR_RDC = 6 .EQU ISR_OVW = 4 .EQU ISR_PTX = 1 .EQU ISR_PRX = 0 ;***************************************************************************** ; ; RTL Register Initialization Values ; ;**************************************************************************** ;RCR : accept broadcast packets and packets destined to this MAC ; drop short frames and receive errors .equ RCR_INIT = 0x04 ;TCR : default transmit operation - CRC is generated .equ TCR_INIT = 0x00 ;DCR : allows send packet to be used for packet retreival ; FIFO threshold: 8-bits (works) ; 8-bit transfer mode .equ DCR_INIT = 0x58 ;IMR : interrupt enabled for receive and overrun events .equ IMR_INIT = 0x11 ;buffer boundaries - transmit has 6 256-byte pages ; receive has 26 256-byte pages ; entire available packet buffer space is allocated .equ TXSTART_INIT = 0x40 .equ RXSTART_INIT = 0x46 .equ RXSTOP_INIT = 0x60 ;********************************************************* ;* Receive RTL8019's Ring Buffer Page Header Layout ;* This is the 4-byte header that resides infront of the ;* data packet in the receive buffer. ;********************************************************* .equ enetpacketstatus= 0x00 .equ nextblock_ptr = 0x01 .equ enetpacketLenL = 0x02 .equ enetpacketLenH = 0x03 ; LANBUFSIZE: The size of the buffer that holds incoming and outgoing packets. .equ LANBUFSIZE = 1564 ;***************************************************************************** ; ; Ethernet constants ; ;**************************************************************************** .equ ETHERNET_MIN_PACKET_LENGTH = 0x3C .equ ETHERNET_HEADER_LENGTH = 0x0E .equ IP_TCP_HEADER_LENGTH = 40 .equ TOTAL_HEADER_LENGTH = IP_TCP_HEADER_LENGTH+ETHERNET_HEADER_LENGTH ;*************************************************************************** .ESEG ; ETHADDR: The Ethernet address ; 48 bit IEEE OUI (Organizationally Unique Identifier) EETHADDR: .db "DEDO",0x00,0x01 ;*************************************************************************** .DSEG ; packet[LANBUFSIZE] ; ; The packet array is used to hold incoming and outgoing packets. ; The device driver fills this with incoming packets. pageheader: .byte 4 ;Rx RTL8019's page header packet: .byte LANBUFSIZE nextPage: .byte 1 ;RTL8019's page header -> next page currentRetreiveAddress: .byte 2 ;innen kell a kilvasast folytatni (pointer) ;pointers to locations in the RTL8019 receive buffer uip_len: .byte 2 ETHADDR: .byte 6 ;*************************************************************************** .CSEG ;***************************************************** ;** SetLANToActive ;** ;** IN: - ;** ;** Out: - ;* ;* Alt: R16 ;* ;* Description: Sets LAN to Active & SRAM to Inactive ;* ; SetLANToActive: SBI RAMCS_PORT,RAMCS nop CBI LANCS_PORT,LANCS nop ret ;***************************************************** ;** SetLANToInactive ;** ;** IN: - ;** ;** Out: - ;* ;* Alt: R16 ;* ;* Description: Sets LAN to Inactive LANCS=H ;* ; SetLANToInactive: SBI LANCS_PORT,LANCS nop ret ;***************************************************** ;** SetISAReset ;** ;** IN: R0 -> 1 ISA Reset, 0 Normal mode ;** ;** Out: - ;* ;* Alt: - ;* ;* Description: Sets ISA RESET Line to R0; 0 = low, 1 = hi ;* ; SetISAReset: sbrs R0,0 CBI LANRES_PORT,LANRES sbrc R0,0 SBI LANRES_PORT,LANRES nop ret ;***************************************************** ;** Wait1ms ;** ;** In: R16 - 16*1ms varakozas ;** ;** Out: - ;** ;** ;** Alt R16, XL,XH ;** ;** Description: wating for R16 * 1 ms ;* Wait1ms: ldi XL,low(SYSCLK/(5*1000)) ldi Xh,high(SYSCLK/(5*1000)) Waitx1: sbiw XL,1 ;[2] \ nop ;[1] - 5 cycles in loop brne Waitx1 ;[2] / dec R16 brne Wait1ms ret ;****************************************************** ;** RTLHW_Reset ;** ;** In: - ;** ;** Out: - ;** ;** ALt: R0, R16, XL, XH ;** ;** Description: Power-up initialization of the RTL8019 and ISA ;* RTLHW_Reset: rcall SetLANToInactive clr R0 inc R0 rcall SetISAReset ldi R16,10 rcall Wait1ms ;10ms warakozas clr R0 rcall SetISAReset ret ;***************************************************************************** ;** RTLreadReg ;** ;** IN: R16 - RTL_ADDRESS offset ;** ;** Out: R17 - register data ;** ;** Alt: - ;** ;** Description: Reads byte from RTL8019 register ;* RTLReadReg: rcall SetLANToActive push XL push XH ldi XL,low(NICBASE) add XL,R16 ldi XH,high(NICBASE) ldi R17,0 adc XH,R17 ;X = NIC real address to ISA ld R17,X rcall SetLANToInactive pop XH pop XL ret ;***************************************************************************** ;** RTLWriteReg ;** ;** IN: R16 - RTL_ADDRESS offset ;** R17 - RTL_DATA ;** ;** Out: - ;** ;** Alt: R0 ;** ;** Description: Writes byte to RTL8019 register. ;* RTLWriteReg: rcall SetLANToActive push XL push XH clr R0 ldi XL,low(NICBASE) add XL,R16 ldi XH,high(NICBASE) adc XH,R0 ;X = NIC real address to ISA st X,R17 rcall SetLANToInactive pop XH pop XL ret ;*********************************************************************** ;** RTL8019_Init ;** ;** IN: - ;** ;** Out: - ;** ;** ALt: R0, R16, XL, XH ;** ;* Description: Sets up the RTL8019 NIC hardware interface, and initializes ;* the buffers and configuration of the NIC ; RTL8019_Init: rcall RTLHW_Reset ;do soft reset & clear pending interrupt ldi R16,NICISR ;clear Interrupt register rcall RTLReadReg ldi R16,NICISR rcall RTLWriteReg ldi R16,50 ;50ms varakozas rcall Wait1ms ldi R16,NICCR ;stop the NIC, abort DMA, page 0 ldi R17,0x21 rcall RTLWriteReg ldi R16,2 ;Delay 2ms rcall Wait1ms ;make sure nothing is coming in or going out ; CONFIGx ldi R16,NICCR ldi R17,0xC0 ;select Page3 rcall RTLWriteReg ldi R16,NICCR9346 ;Enable SW Config ldi R17,0xC0 rcall RTLWriteReg ldi R16,0x04 ldi R17,0b10000000 ;IRQ0, Base 0x300 rcall RTLWriteReg ldi R16,0x05 ldi R17,0b00100000 ;AutoDetect, ROM Disabled rcall RTLWriteReg ldi R16,0x06 ldi R17,0b00010000 ;Halfduplex, LED0 - link, LED1 - RX led2 - TX rcall RTLWriteReg ldi R16,0x0D ldi R17,0x00 rcall RTLWriteReg ldi R16,NICCR9346 ldi R17,0x00 ;End Config rcall RTLWriteReg ; !!!! ldi R16,NICCR ;stop the NIC, page 0 ldi R17,0x01 rcall RTLWriteReg ldi R16,NICDCR ldi R17,DCR_INIT ;0x58 Normal Operation, FIFO Treshold, Auto Init Remote rcall RTLWriteReg ldi R16,NICRBCR0 ldi R17,0x00 rcall RTLWriteReg ldi R16,NICRBCR1 rcall RTLWriteReg ;Remote DMA Byte Count =0x0000 ldi R16,NICRCR ldi R17,0x04 ;only packets with broadcast rcall RTLWriteReg ;destination address are accepted ldi R16,NICTPSR ldi R17,TXSTART_INIT ;Transmit Page Start Register=40 rcall RTLWriteReg ldi R16,NICTCR ldi R17,0x02 ;Internal loopback rcall RTLWriteReg ldi R16,NICPSTART ldi R17,RXSTART_INIT ;page address of the receive buffer ring = 46 rcall RTLWriteReg ldi R16,NICBNRY ;utolso olvasott page = 46 rcall RTLWriteReg ldi R16,NICPSTOP ldi R17,RXSTOP_INIT ;stop page address of the receive buffer ring = 60 rcall RTLWriteReg ldi R16,NICCR ldi R17,0x61 ;Stop & Abort DMA rcall RTLWriteReg ldi R16,2 ;2ms varakozas rcall Wait1ms ldi R16,NICCURR ldi R17,RXSTART_INIT ;Rx Page = 46 rcall RTLWriteReg ldi ZL,low(EETHADDR) ;MAC address from EEPROM ldi ZH,high(EETHADDR) call EERead sts ETHADDR+0,R0 mov R17,R0 ldi R16,NICPAR0 ;Setup our MAC Address rcall RTLWriteReg adiw ZL,1 call EERead sts ETHADDR+1,R0 mov R17,R0 ldi R16,NICPAR1 rcall RTLWriteReg adiw ZL,1 call EERead sts ETHADDR+2,R0 mov R17,R0 ldi R16,NICPAR2 rcall RTLWriteReg adiw ZL,1 call EERead sts ETHADDR+3,R0 mov R17,R0 ldi R16,NICPAR3 rcall RTLWriteReg adiw ZL,1 call EERead sts ETHADDR+4,R0 mov R17,R0 ldi R16,NICPAR4 rcall RTLWriteReg adiw ZL,1 call EERead sts ETHADDR+5,R0 mov R17,R0 ldi R16,NICPAR5 rcall RTLWriteReg ldi R16,NICCR ldi R17,0x21 ;Stop NIC, Abort DMA rcall RTLWriteReg ldi R16,NICDCR ldi R17,DCR_INIT ;58 Normal operation... rcall RTLWriteReg ldi R16,NICCR ldi R17,0x22 ;Start Command, DMA abort rcall RTLWriteReg ldi R16,NICISR ldi R17,0xFF rcall RTLWriteReg ;Clear pending Interrupt ldi R16,NICIMR ldi R17,IMR_INIT ;11, Interrupt Enable rcall RTLWriteReg ;packet received with no errors ;receive buffer has been exhausted ldi R16,NICTCR ldi R17,TCR_INIT ;00 - Normal operation rcall RTLWriteReg ldi R16,NICCR ldi R17,0x22 rcall RTLWriteReg ;start the NIC ret ;*********************************************************************** ;** RTL8019endPacketSend ;** ;** In : - ;** ;** ;** Alt : ;** ;* Description: Ends a packet send operation and instructs the NIC to transmit ;* the frame over the network ; RTL8019endPacketSend: ldi R16,NICCR ;send the contents of the transmit buffer onto the network ldi R17,0x24 rcall RTLWriteReg ;clear the remote DMA interrupt ldi R16,NICISR ldi R17,(1< sendPacketLength push R16 ;R17:R16 - > packetLength ldi R16,NICCR ldi R17,0x22 rcall RTLWriteReg ;start the NIC packf: ldi R16,NICCR ;still transmitting a packet - wait for it to finish rcall RTLReadReg ;while( readRTL(CR) & 0x04 ); andi R17,0x04 brne packf ;load beginning page for transmit buffer ldi R16,NICTPSR ldi R17,TXSTART_INIT rcall RTLWriteReg ;set start address for remote DMA operation ldi R16,NICRSAR0 ldi R17,0x00 rcall RTLWriteReg ldi R16,NICRSAR1 ldi R17,0x40 rcall RTLWriteReg ;clear the packet stored interrupt ldi R16,NICISR ldi R17,(1<= RXSTOP_INIT) || (bnry < RXSTART_INIT)) invpointer: ldi R16,NICBNRY ldi R17,RXSTART_INIT rcall RTLWriteReg ldi R16,NICCR ldi R17,0x62 rcall RTLWriteReg ldi R16,NICCURR ldi R17,RXSTART_INIT rcall RTLWriteReg ldi R16,NICCR ldi R17,0x22 rcall RTLWriteReg clc ret ;Z= meg mindig 0!! jopointer: ldi R16,NICRBCR0 ;initiate DMA to transfer the RTL8019 packet header ldi R17,0x04 rcall RTLWriteReg ldi R16,NICRBCR1 ldi R17,0x00 rcall RTLWriteReg ;Remote Byte Count = 4 ldi R16,NICRSAR0 ldi R17,0x00 rcall RTLWriteReg ldi R16,NICRSAR1 mov R17,R20 rcall RTLWriteReg ;Remote start address= Start boundary page ldi R16,NICCR ldi R17,0x0A rcall RTLWriteReg ;Start Remote Read DMA ldi R18,4 ;4 byte-ot olvasunk be ldi XL,Low(pageheader) ;ide ldi XH,high(pageheader) Getph: ldi R16,NICRDMAPORT rcall RTLReadReg st X+,R17 dec R18 brne Getph ldi R16,NICCR ;end the DMA operation ldi R17,0x22 rcall RTLWriteReg rcall WaitToDMA lds ZL,pageheader+enetpacketLenL lds ZH,pageheader+enetpacketLenH ;Z=rxlen lds R16,pageheader+nextblock_ptr ;nextPage sts nextPage,R16 ;eltaroljuk ,aborthoz kell ldi R17,4 sts currentRetreiveAddress+0,R17 sts currentRetreiveAddress+1,R20 ;innen folytatjuk majd a kiolvasast (offset cim) ;if the nextPage pointer is invalid, the packet is not ready yet - exit ldi R18,RXSTOP_INIT cp R16,R18 brsh pageErr1 ldi R18,RXSTART_INIT cp R16,R18 brcs pageErr1 ;if((nextPage >= RXSTOP_INIT) || (nextPage < RXSTART_INIT)) clr R18 sub ZL,R17 sbc ZH,R18 ;rxlen-4 sec ret pageErr1: clr Zl clr ZH clc ret ;***************************************************************************** ; Device Manager ; A foprogrambol ezek hivhatoak ;***************************************************************************** ;* RTL8019dev_send ;* ;* In: ;* ;* Out: ;* ;* Alt: ;* ;* Description: Sends the packet contained in packet over the network ; RTL8019dev_send: ldi R16,low(LANBUFSIZE) ldi R17,high(LANBUFSIZE) RTL8019dev_sendA: push R16 push R17 rcall RTL8019beginPacketSend ;send packet, using data in ip_appdata if over the IP+TCP header size ldi XL,Low(packet) ldi XH,high(packet) pop ZH pop ZL rcall RTL8019sendPacketData rcall RTL8019endPacketSend ret ;***************************************************************************** ;* RTL8019dev_poll ;* ;* In: - ;* ;* Out: Z = Length of the packet retreived, or zero if no packet retreived ;* Y = Address of retreived packet ;* c flag = 0, no packet ;* ;* Description: Polls the RTL8019 looking for an overflow condition or a new ;* packet in the receive buffer. If a new packet exists and will ;* fit in packet, it is retreived, and the length is returned. ;* A packet bigger than the buffer is discarded ;*****************************************************************************/ ; RTL8019dev_poll: rcall RTL8019beginPacketRetreive ;Z = packetLength brcs Vanpacket2 ;if there's no packet or an error ;exit without ending the operation ret Vanpacket2: cpi ZL,low(LANBUFSIZE+1) ldi R16,high(LANBUFSIZE+1) ;drop anything too big for the buffer cpc ZH,R16 brcs PacketSizejo ;Ezt el kell dobni, tul nagy rcall RTL8019endPacketRetreive clr ZL clr ZH clc ret PacketSizejo: push ZL ;copy the packet data into the IP packet buffer push ZH ldi XL,low(packet) ldi XH,high(packet) rcall RTL8019retreivePacketData rcall RTL8019endPacketRetreive pop ZH pop ZL sts pageheader+enetpacketLenL,ZL sts pageheader+enetpacketLenH,ZH ldi YL,low(packet) ldi YH,high(packet) sec ret