BlinkenArea - GitList
Repositories
Blog
Wiki
bluebox
Code
Commits
Branches
Tags
Search
Tree:
fd252ce
Branches
Tags
master
bluebox
BlueDataDistributor
firmware
rtl8019.c
initial commit of files from bluebox project
Stefan Schuermans
commited
fd252ce
at 2015-12-19 20:16:38
rtl8019.c
Blame
History
Raw
/* BlueDataDistributor - data distribution module from ethernet to 32 serial ports * version 0.1.1 date 2006-10-07 * Copyright (C) 2006 Stefan Schuermans <stefan@blinkenarea.org> * a BlinkenArea project - http://www.blinkenarea.org/ */ #include <avr/io.h> #include <avr/signal.h> #include "config.h" #include "ethernet.h" #include "macros.h" #include "rtl8019.h" #include "timing.h" // maximum receive unit #define RTL_MRU 1024 // reinitialization timeout // - if no reception is detected for this time, the RTL8019 is reinitialized #define RtlReinitTimeoutTicks 50 // in 200ms steps // IO pins of RTL8019 #define RTL_ADDR_DDR DDRC #define RTL_ADDR PORTC #define RTL_DATA_DDR DDRA #define RTL_DATA PORTA #define RTL_DATA_IN PINA #define RTL_ADDR_nRD 5 #define RTL_ADDR_nWR 6 #define RTL_ADDR_RST 7 // adress port masks (there are also RD, WR and RESET pins) #define RTL_ADDR_AND_MASK 0x1F #define RTL_ADDR_OR_MASK (1<<RTL_ADDR_nRD | 1<<RTL_ADDR_nWR) #define RTL_ADDR_RESET (1<<RTL_ADDR_nRD | 1<<RTL_ADDR_nWR | 1<<RTL_ADDR_RST) // special pins #define RTL_READ_ACT( ) (bit_clear( RTL_ADDR, RTL_ADDR_nRD )) #define RTL_READ_IDLE( ) (bit_set( RTL_ADDR, RTL_ADDR_nRD )) #define RTL_WRITE_ACT( ) (bit_clear( RTL_ADDR, RTL_ADDR_nWR )) #define RTL_WRITE_IDLE( ) (bit_set( RTL_ADDR, RTL_ADDR_nWR )) #define RTL_RESET_ACT( ) (bit_set( RTL_ADDR, RTL_ADDR_RST )) #define RTL_RESET_IDLE( ) (bit_clear( RTL_ADDR, RTL_ADDR_RST )) // RTL8019 registers #define RTL_REG_CR 0x00 #define RTL_REG_PSTART 0x01 #define RTL_REG_PAR0 0x01 #define RTL_REG_PSTOP 0x02 #define RTL_REG_BNRY 0x03 #define RTL_REG_TPSR 0x04 #define RTL_REG_TBCR0 0x05 #define RTL_REG_TBCR1 0x06 #define RTL_REG_ISR 0x07 #define RTL_REG_CURR 0x07 #define RTL_REG_RSAR0 0x08 #define RTL_REG_CRDA0 0x08 #define RTL_REG_RSAR1 0x09 #define RTL_REG_CRDAl 0x09 #define RTL_REG_RBCR0 0x0A #define RTL_REG_ID0 0x0A #define RTL_REG_ID1 0x0B #define RTL_REG_RBCR1 0x0B #define RTL_REG_RSR 0x0C #define RTL_REG_RCR 0x0C #define RTL_REG_TCR 0x0D #define RTL_REG_CNTR0 0x0D #define RTL_REG_DCR 0x0E #define RTL_REG_CNTR1 0x0E #define RTL_REG_IMR 0x0F #define RTL_REG_CNTR2 0x0F #define RTL_REG_RDMAPORT 0x10 #define RTL_REG_RSTPORT 0x18 // RTL8019AS CR register bits #define RTL_CR_STP 0 #define RTL_CR_STA 1 #define RTL_CR_TXP 2 #define RTL_CR_RD0 3 #define RTL_CR_RD1 4 #define RTL_CR_RD2 5 #define RTL_CR_PS0 6 #define RTL_CR_PS1 7 // RTL8019 ISR register bits #define RTL_ISR_PRX 0 #define RTL_ISR_PTX 1 #define RTL_ISR_RXE 2 #define RTL_ISR_TXE 3 #define RTL_ISR_OVW 4 #define RTL_ISR_CNT 5 #define RTL_ISR_RDC 6 #define RTL_ISR_RST 7 // RTL8019 (initial) register values #define RTL_VAL_RCR 0x04 #define RTL_VAL_TCR 0x00 #define RTL_VAL_DCR 0x58 #define RTL_VAL_IMR 0x00 #define RTL_VAL_TXSTART 0x40 #define RTL_VAL_RXSTART 0x46 #define RTL_VAL_RXSTOP 0x60 // write a RTL8019 register #define RTL_WRITE( reg, val ) \ { \ RTL_DATA_DDR = 0xFF; /* data port to output */ \ RTL_ADDR = ((reg) & RTL_ADDR_AND_MASK) | RTL_ADDR_OR_MASK; /* output address */ \ RTL_DATA = (val); /* output value */ \ RTL_WRITE_ACT( ); /* activate write signal */ \ nop( ); \ nop( ); \ RTL_WRITE_IDLE( ); /* take back write signal */ \ } // read a RTL8019 register #define RTL_READ( reg, var ) \ { \ RTL_DATA_DDR = 0x00; /* data port to input */ \ RTL_ADDR = ((reg) & RTL_ADDR_AND_MASK) | RTL_ADDR_OR_MASK; /* output address */ \ RTL_READ_ACT( ); /* activate read signal */ \ nop( ); \ nop( ); \ var = RTL_DATA_IN; /* read data */ \ RTL_READ_IDLE( ); /* take back read signal */ \ } // reinitialization timeout counter unsigned char RtlReinitTimeout = 0; // initialize void RtlInit( void ) // (extern) { unsigned char i; unsigned short j; // setup ports RTL_ADDR = RTL_ADDR_RESET; // default address value with reset set RTL_ADDR_DDR = 0xFF; // address port to output RTL_DATA_DDR = 0x00; // data port to input // take back reset for( i = 0; i < 10; i++ ) nop( ); RTL_RESET_IDLE( ); for( j = 0; j < 5000; j++ ) nop( ); // clear software reset RTL_READ( RTL_REG_RSTPORT, i ); RTL_WRITE( RTL_REG_RSTPORT, 0xFF ); for( i = 0; i < 100; i++ ) nop( ); // do the same as in reinitialization RtlReinit( ); } // re-initialize RT8019 (i.e. if MAC changed) void RtlReinit( void ) // (extern) { unsigned char i, j; // stop RTL8019 RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STP | 1<<RTL_CR_RD2 ); for( i = 0; i < 100; i++ ) nop( ); // output RTL8019 ID RTL_READ( RTL_REG_ID0, i ); RTL_READ( RTL_REG_ID1, j ); // set up RTL8019 RTL_WRITE( RTL_REG_DCR, RTL_VAL_DCR ); RTL_WRITE( RTL_REG_RBCR0, 0x00 ); RTL_WRITE( RTL_REG_RBCR1, 0x00 ); RTL_WRITE( RTL_REG_RCR, 0x04 ); RTL_WRITE( RTL_REG_TPSR, RTL_VAL_RXSTART ); RTL_WRITE( RTL_REG_TCR, 0x02 ); RTL_WRITE( RTL_REG_PSTART, RTL_VAL_RXSTART ); RTL_WRITE( RTL_REG_BNRY, RTL_VAL_RXSTART ); RTL_WRITE( RTL_REG_PSTOP, RTL_VAL_RXSTOP ); RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STP | 1<<RTL_CR_RD2 | 1<<RTL_CR_PS0 ); for( i = 0; i < 100; i++ ) nop( ); // write MAC to chip RTL_WRITE( RTL_REG_CURR, RTL_VAL_RXSTART ); for( i = 0; i < 6; i++ ) RTL_WRITE( RTL_REG_PAR0 + i, ConfigMac[i] ); // go on with intializing RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STP | 1<<RTL_CR_RD2 ); RTL_WRITE( RTL_REG_DCR, RTL_VAL_DCR ); RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 ); RTL_WRITE( RTL_REG_ISR, 1<<RTL_ISR_PRX | 1<<RTL_ISR_PTX | 1<<RTL_ISR_RXE | 1<<RTL_ISR_TXE | 1<<RTL_ISR_OVW | 1<<RTL_ISR_CNT | 1<<RTL_ISR_RDC | 1<<RTL_ISR_RST ); RTL_WRITE( RTL_REG_IMR, RTL_VAL_IMR ); RTL_WRITE( RTL_REG_TCR, RTL_VAL_TCR ); // start RTL8019 RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 ); // clear reinitialization timeout RtlReinitTimeout = 0; } // tick procedure - call every 200ms void RtlTick200( void ) // (extern) { // increment reinitialization timeout counter RtlReinitTimeout++; // reinitialization timeout if( RtlReinitTimeout >= RtlReinitTimeoutTicks ) // reinitialize RTL8019 (resets reinitialization timeout) RtlReinit( ); } // fetch and process a received packet static inline void RtlRecv( void ) { unsigned short PacketLen; unsigned char Packet[RTL_MRU]; // fetch packet from RTL8019 PacketLen = count( Packet ); RtlReadFrame( Packet, &PacketLen ); // pass packet on to ethernet EthernetRecv( Packet, PacketLen ); } // task function to do the work - call from main loop void RtlTask( void ) // (extern) { unsigned char isr, bnry, curr; // read interrupt register RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 ); RTL_READ( RTL_REG_ISR, isr ); // a packet was received if( isr & 1<<RTL_ISR_PRX ) // use current timestamp for generating some entropy TimingEntropy( ); // check if receive ring buffer is not empty RTL_READ( RTL_REG_BNRY, bnry ); RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 | 1<<RTL_CR_PS0 ); RTL_READ( RTL_REG_CURR, curr ); RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 ); if( bnry != curr ) // fetch and process a single received packet RtlRecv( ); // reset interrupt bits of RTL8019 RTL_WRITE( RTL_REG_ISR, 1<<RTL_ISR_PRX | 1<<RTL_ISR_PTX | 1<<RTL_ISR_RXE | 1<<RTL_ISR_TXE | 1<<RTL_ISR_OVW | 1<<RTL_ISR_CNT | 1<<RTL_ISR_RDC | 1<<RTL_ISR_RST ); // put RTL8019 in default state (default page selected, ...) RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 ); // clear reinitialization timeout RtlReinitTimeout = 0; } // write an ethernet frame to the RTL8019 void RtlWriteFrame( char * pData, unsigned short Length ) // (extern) { unsigned short i; unsigned char val; // initialize RTL8019 to transmit RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD2 ); RTL_WRITE( RTL_REG_TPSR, RTL_VAL_TXSTART ); RTL_WRITE( RTL_REG_RSAR0, 0x00 ); RTL_WRITE( RTL_REG_RSAR1, RTL_VAL_TXSTART ); RTL_WRITE( RTL_REG_ISR, 1<<RTL_ISR_PRX | 1<<RTL_ISR_PTX | 1<<RTL_ISR_RXE | 1<<RTL_ISR_TXE | 1<<RTL_ISR_OVW | 1<<RTL_ISR_CNT | 1<<RTL_ISR_RDC | 1<<RTL_ISR_RST ); if( Length < 0x3C ) // minimal length is 60 bytes { RTL_WRITE( RTL_REG_RBCR0, 0x3C ); RTL_WRITE( RTL_REG_RBCR1, 0x00 ); } else { RTL_WRITE( RTL_REG_RBCR0, (unsigned char)Length ); RTL_WRITE( RTL_REG_RBCR1, (unsigned char)(Length >> 8) ); } RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD1 ); // write data to RTL8019 for( i = 0; i < Length; i++ ) RTL_WRITE( RTL_REG_RDMAPORT, pData[i] ); for( ; i < 0x3C; i++ ) // padding RTL_WRITE( RTL_REG_RDMAPORT, 0x00 ); // wait for RTL8019 do { RTL_READ( RTL_REG_ISR, val ); } while( (val & 1<<RTL_ISR_RDC) == 0x00 ); // start transmission if( Length < 0x3C ) // minimal length is 60 bytes { RTL_WRITE( RTL_REG_TBCR0, 0x3C ); RTL_WRITE( RTL_REG_TBCR1, 0x00 ); } else { RTL_WRITE( RTL_REG_TBCR0, (unsigned char)Length ); RTL_WRITE( RTL_REG_TBCR1, (unsigned char)(Length >> 8) ); } RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_TXP | 1<<RTL_CR_RD2 ); } // read an ethernet frame from the RTL8019 // *pLength must be initialized to the buffer size void RtlReadFrame( char * pData, unsigned short * pLength ) // (extern) { unsigned char tmp1, tmp2; unsigned short read_len, len, cnt, i; // get size of received packet RTL_WRITE( RTL_REG_CR, 1<<RTL_CR_STA | 1<<RTL_CR_RD0 | 1<<RTL_CR_RD1 ); RTL_READ( RTL_REG_RDMAPORT, tmp1 ); RTL_READ( RTL_REG_RDMAPORT, tmp1 ); RTL_READ( RTL_REG_RDMAPORT, tmp1 ); RTL_READ( RTL_REG_RDMAPORT, tmp2 ); read_len = ((unsigned short)tmp2 << 8 | (unsigned short)tmp1); // subtract length of CRC (4 bytes) len = read_len < 4 ? 0 : read_len - 4; // read as much data as possible into buffer cnt = min( len, *pLength ); for( i = 0; i < cnt; i++ ) RTL_READ( RTL_REG_RDMAPORT, pData[i] ); *pLength = cnt; // get rest of data (rest of real data that did not fit into buffer, CRC) for( ; i < read_len; i++ ) RTL_READ( RTL_REG_RDMAPORT, tmp1 ); }