Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals

rtl8019.c

Go to the documentation of this file.
00001 /*! \file rtl8019.c \brief Realtek RTL8019AS Ethernet Interface Driver. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'rtl8019.c'
00005 // Title        : Realtek RTL8019AS Ethernet Interface Driver
00006 // Author       : Pascal Stang
00007 // Created      : 7/6/2004
00008 // Revised      : 8/22/2005
00009 // Version      : 0.1
00010 // Target MCU   : Atmel AVR series
00011 // Editor Tabs  : 4
00012 //
00013 //*****************************************************************************
00014 
00015 #include "global.h"
00016 #include "timer.h"
00017 #include "rprintf.h"
00018 
00019 #include "rtl8019.h"
00020 
00021 // include configuration
00022 #include "rtl8019conf.h"
00023 
00024 // pointers to locations in the RTL8019 receive buffer
00025 static unsigned char NextPage;              // page pointer to next Rx packet
00026 static unsigned int CurrentRetreiveAddress; // DMA address for read Rx packet location
00027 
00028 
00029 void nicInit(void)
00030 {
00031     rtl8019Init();
00032 }
00033 
00034 void nicSend(unsigned int len, unsigned char* packet)
00035 {
00036     rtl8019BeginPacketSend(len);
00037     rtl8019SendPacketData(packet, len);
00038     rtl8019EndPacketSend();
00039 }
00040 
00041 unsigned int nicPoll(unsigned int maxlen, unsigned char* packet)
00042 {
00043     unsigned int packetLength;
00044     
00045     packetLength = rtl8019BeginPacketRetreive();
00046 
00047     // if there's no packet or an error - exit without ending the operation
00048     if( !packetLength )
00049         return 0;
00050 
00051     // drop anything too big for the buffer
00052     if( packetLength > maxlen )
00053     {
00054         rtl8019EndPacketRetreive();
00055         return 0;
00056     }
00057     
00058     // copy the packet data into the packet buffer
00059     rtl8019RetreivePacketData( packet, packetLength );
00060     rtl8019EndPacketRetreive();
00061         
00062     return packetLength;
00063 }
00064 
00065 void nicGetMacAddress(u08* macaddr)
00066 {
00067     u08 tempCR;
00068     // switch register pages
00069     tempCR = rtl8019Read(CR);
00070     rtl8019Write(CR,tempCR|PS0);
00071     // read MAC address registers
00072     *macaddr++ = rtl8019Read(PAR0);
00073     *macaddr++ = rtl8019Read(PAR1);
00074     *macaddr++ = rtl8019Read(PAR2);
00075     *macaddr++ = rtl8019Read(PAR3);
00076     *macaddr++ = rtl8019Read(PAR4);
00077     *macaddr++ = rtl8019Read(PAR5);
00078     // switch register pages back
00079     rtl8019Write(CR,tempCR);
00080 }
00081 
00082 void nicRegDump(void)
00083 {
00084     rtl8019RegDump();
00085 }
00086 
00087 
00088 void rtl8019SetupPorts(void)
00089 {
00090 #if NIC_CONNECTION == MEMORY_MAPPED
00091     // enable external SRAM interface - no wait states
00092     sbi(MCUCR, SRE);
00093 //  sbi(MCUCR, SRW10);
00094 //  sbi(XMCRA, SRW00);
00095 //  sbi(XMCRA, SRW01);
00096 //  sbi(XMCRA, SRW11);
00097 #else
00098     // make the address port output
00099     RTL8019_ADDRESS_DDR = RTL8019_ADDRESS_MASK;
00100     // make the data port input with pull-ups
00101     RTL8019_DATA_PORT = 0xFF;
00102 
00103     // initialize the control port read and write pins to de-asserted
00104     RTL8019_CONTROL_DDR |= (1<<RTL8019_CONTROL_READPIN);
00105     RTL8019_CONTROL_DDR |= (1<<RTL8019_CONTROL_WRITEPIN);
00106     // set the read and write pins to output
00107     RTL8019_CONTROL_PORT |= (1<<RTL8019_CONTROL_READPIN);
00108     RTL8019_CONTROL_PORT |= (1<<RTL8019_CONTROL_WRITEPIN);
00109 #endif
00110     // set reset pin to output
00111     sbi(RTL8019_RESET_DDR, RTL8019_RESET_PIN);
00112 }
00113 
00114 
00115 #if NIC_CONNECTION == MEMORY_MAPPED
00116 inline void rtl8019Write(u08 address, u08 data)
00117 {
00118     *(volatile u08*)(RTL8019_MEMORY_MAPPED_OFFSET + address) = data;
00119 }
00120 #else
00121 void rtl8019Write(unsigned char address, unsigned char data)
00122 {
00123     // assert the address
00124     RTL8019_ADDRESS_PORT = address | (RTL8019_ADDRESS_PORT&~RTL8019_ADDRESS_MASK);
00125     // set data bus as output and place data on bus
00126     RTL8019_DATA_DDR = 0xFF;
00127     RTL8019_DATA_PORT = data;
00128     // clock write pin
00129     cbi(RTL8019_CONTROL_PORT, RTL8019_CONTROL_WRITEPIN);
00130     nop();
00131     nop();
00132     sbi(RTL8019_CONTROL_PORT, RTL8019_CONTROL_WRITEPIN);
00133     // set data port back to input with pullups enabled
00134     RTL8019_DATA_DDR = 0x00;
00135     RTL8019_DATA_PORT = 0xFF;
00136 }
00137 #endif
00138 
00139 
00140 #if NIC_CONNECTION == MEMORY_MAPPED
00141 inline u08 ax88796Read(u08 address)
00142 {
00143     return *(volatile u08*)(RTL8019_MEMORY_MAPPED_OFFSET + address);
00144 }
00145 #else
00146 unsigned char rtl8019Read(unsigned char address)
00147 {
00148     unsigned char data;
00149    
00150     // assert the address
00151     RTL8019_ADDRESS_PORT = address | (RTL8019_ADDRESS_PORT&~RTL8019_ADDRESS_MASK);
00152     // assert read
00153     cbi(RTL8019_CONTROL_PORT, RTL8019_CONTROL_READPIN);
00154     nop();
00155     nop();
00156     // read in the data
00157     data = RTL8019_DATA_PIN;
00158     // negate read
00159     sbi(RTL8019_CONTROL_PORT, RTL8019_CONTROL_READPIN);
00160     // return data
00161     return data;
00162 }
00163 #endif                       
00164 
00165 
00166 void rtl8019Init(void)
00167 {
00168     // setup I/O ports
00169     rtl8019SetupPorts();
00170     
00171     // do a hard reset
00172     sbi(RTL8019_RESET_PORT, RTL8019_RESET_PIN);
00173     delay_ms(10);
00174     cbi(RTL8019_RESET_PORT, RTL8019_RESET_PIN);
00175 
00176     // clear interrupt state
00177     rtl8019Write( ISR, rtl8019Read(ISR) );
00178     delay_ms(50);
00179 
00180     // switch to page 3 to load config registers
00181     rtl8019Write(CR, (PS0|PS1|RD2|STOP));
00182 
00183     // disable EEPROM write protect of config registers
00184     rtl8019Write(RTL_EECR, (EEM1|EEM0));
00185 
00186     // set network type to 10 Base-T link test
00187     rtl8019Write(CONFIG2, 0x20);
00188 
00189     // disable powerdown and sleep
00190     rtl8019Write(CONFIG3, 0);
00191     delay_ms(255);
00192 
00193     // reenable EEPROM write protect
00194     rtl8019Write(RTL_EECR, 0);
00195 
00196     // go back to page 0, stop NIC, abort DMA
00197     rtl8019Write(CR, (RD2|STOP));
00198     delay_ms(2);                    // wait for traffic to complete
00199     rtl8019Write(DCR, DCR_INIT);
00200     rtl8019Write(RBCR0,0x00);
00201     rtl8019Write(RBCR1,0x00);
00202     rtl8019Write(RCR, AB);
00203     rtl8019Write(TPSR, TXSTART_INIT);
00204     rtl8019Write(TCR, LB0);
00205     rtl8019Write(PSTART, RXSTART_INIT);
00206     rtl8019Write(BNRY, RXSTART_INIT);
00207     rtl8019Write(PSTOP, RXSTOP_INIT);
00208     rtl8019Write(CR, (PS0|RD2|STOP));   // switch to page 1
00209     delay_ms(2);
00210     rtl8019Write(CPR, RXSTART_INIT);
00211     
00212     // set MAC address
00213     rtl8019Write(PAR0, RTL8019_MAC0);
00214     rtl8019Write(PAR1, RTL8019_MAC1);
00215     rtl8019Write(PAR2, RTL8019_MAC2);
00216     rtl8019Write(PAR3, RTL8019_MAC3);
00217     rtl8019Write(PAR4, RTL8019_MAC4);
00218     rtl8019Write(PAR5, RTL8019_MAC5);
00219     
00220     // initialize sequence per NE2000 spec
00221     rtl8019Write(CR, (RD2|STOP));
00222     rtl8019Write(DCR, DCR_INIT);
00223     rtl8019Write(CR, (RD2|START));
00224     rtl8019Write(ISR,0xFF);         // clear all interrupts
00225     rtl8019Write(IMR, IMR_INIT);
00226     rtl8019Write(TCR, TCR_INIT);
00227     
00228     rtl8019Write(CR, (RD2|START));  // start the NIC
00229 }
00230 
00231 
00232 void rtl8019BeginPacketSend(unsigned int packetLength)
00233 {
00234     unsigned int sendPacketLength;
00235     sendPacketLength = (packetLength>=ETHERNET_MIN_PACKET_LENGTH)?
00236                         (packetLength):ETHERNET_MIN_PACKET_LENGTH;
00237     
00238     //start the NIC
00239     rtl8019Write(CR, (RD2|START));
00240     
00241     // still transmitting a packet - wait for it to finish
00242     while( rtl8019Read(CR) & TXP );
00243 
00244     // load beginning page for transmit buffer
00245     rtl8019Write(TPSR,TXSTART_INIT);
00246     
00247     // set start address for remote DMA operation
00248     rtl8019Write(RSAR0,0x00);
00249     rtl8019Write(RSAR1,0x40);
00250     
00251     // clear the packet stored interrupt
00252     rtl8019Write(ISR,PTX);
00253 
00254     // load data byte count for remote DMA
00255     rtl8019Write(RBCR0, (unsigned char)(packetLength));
00256     rtl8019Write(RBCR1, (unsigned char)(packetLength>>8));
00257 
00258     rtl8019Write(TBCR0, (unsigned char)(sendPacketLength));
00259     rtl8019Write(TBCR1, (unsigned char)((sendPacketLength)>>8));
00260     
00261     // do remote write operation
00262     rtl8019Write(CR,(RD1|START));
00263 }
00264 
00265 
00266 void rtl8019SendPacketData(unsigned char *localBuffer, unsigned int length)
00267 {
00268     unsigned int i;
00269     
00270     // write data to DMA port
00271     for(i=0;i<length;i++)
00272         rtl8019Write(RDMAPORT, localBuffer[i]);
00273 }
00274 
00275 
00276 void rtl8019EndPacketSend(void)
00277 {
00278     //send the contents of the transmit buffer onto the network
00279     rtl8019Write(CR,(RD2|TXP));
00280     // clear the remote DMA interrupt
00281     rtl8019Write(ISR, RDC);
00282 }
00283 
00284 
00285 unsigned int rtl8019BeginPacketRetreive(void)
00286 {
00287     unsigned char i;
00288     unsigned char bnry;
00289     
00290     unsigned char pageheader[4];
00291     unsigned int rxlen;
00292     
00293     // check for and handle an overflow
00294     rtl8019ProcessInterrupt();
00295     
00296     // read CPR from page 1
00297     rtl8019Write(CR,(PS0|RD2|START));
00298     i = rtl8019Read(CPR);
00299     
00300     // return to page 0
00301     rtl8019Write(CR,(RD2|START));
00302     
00303     // read the boundary register - pointing to the beginning of the packet
00304     bnry = rtl8019Read(BNRY) ;
00305     
00306     // return if there is no packet in the buffer
00307     if( bnry == i )
00308         return 0;
00309 
00310     // clear the packet received interrupt flag
00311     rtl8019Write(ISR, PRX);
00312     
00313     // if boundary pointer is invalid
00314     if( (bnry >= RXSTOP_INIT) || (bnry < RXSTART_INIT) )
00315     {
00316         // reset the contents of the buffer and exit
00317         rtl8019Write(BNRY, RXSTART_INIT);
00318         rtl8019Write(CR, (PS0|RD2|START));
00319         rtl8019Write(CPR, RXSTART_INIT);
00320         rtl8019Write(CR, (RD2|START));
00321         return 0;
00322     }
00323 
00324     // initiate DMA to transfer the RTL8019 packet header
00325     rtl8019Write(RBCR0, 4);
00326     rtl8019Write(RBCR1, 0);
00327     rtl8019Write(RSAR0, 0);
00328     rtl8019Write(RSAR1, bnry);
00329     rtl8019Write(CR, (RD0|START));
00330     // transfer packet header
00331     for(i=0;i<4;i++)
00332         pageheader[i] = rtl8019Read(RDMAPORT);
00333     // end the DMA operation
00334     rtl8019Write(CR, (RD2|START));
00335     // wait for remote DMA complete
00336     for(i = 0; i < 20; i++)
00337         if(rtl8019Read(ISR) & RDC)
00338             break;
00339     rtl8019Write(ISR, RDC);
00340 
00341     rxlen = (pageheader[PKTHEADER_PKTLENH]<<8) + pageheader[PKTHEADER_PKTLENL];
00342     NextPage = pageheader[PKTHEADER_NEXTPAGE];
00343     
00344     CurrentRetreiveAddress = (bnry<<8) + 4;
00345     
00346     // if the NextPage pointer is invalid, the packet is not ready yet - exit
00347     if( (NextPage >= RXSTOP_INIT) || (NextPage < RXSTART_INIT) )
00348         return 0;
00349     
00350     return rxlen-4;
00351 }
00352 
00353 
00354 void rtl8019RetreivePacketData(unsigned char * localBuffer, unsigned int length)
00355 {
00356     unsigned int i;
00357     
00358     // initiate DMA to transfer the data
00359     rtl8019Write(RBCR0, (unsigned char)length);
00360     rtl8019Write(RBCR1, (unsigned char)(length>>8));
00361     rtl8019Write(RSAR0, (unsigned char)CurrentRetreiveAddress);
00362     rtl8019Write(RSAR1, (unsigned char)(CurrentRetreiveAddress>>8));
00363     rtl8019Write(CR, (RD0|START));
00364     // transfer packet data
00365     for(i=0;i<length;i++)
00366         localBuffer[i] = rtl8019Read(RDMAPORT);
00367     // end the DMA operation
00368     rtl8019Write(CR, (RD2|START));
00369     // wait for remote DMA complete
00370     for(i=0; i<20; i++)
00371         if(rtl8019Read(ISR) & RDC)
00372             break;
00373     rtl8019Write(ISR, RDC);
00374     // keep track of current address
00375     CurrentRetreiveAddress += length;
00376     if( CurrentRetreiveAddress >= 0x6000 )
00377         CurrentRetreiveAddress = CurrentRetreiveAddress - (0x6000-0x4600) ;
00378 }
00379 
00380 
00381 void rtl8019EndPacketRetreive(void)
00382 {
00383     unsigned char i;
00384 
00385     // end the DMA operation
00386     rtl8019Write(CR, (RD2|START));
00387     // wait for remote DMA complete
00388     for(i=0; i<20; i++)
00389         if(rtl8019Read(ISR) & RDC)
00390             break;
00391     rtl8019Write(ISR, RDC);
00392 
00393     // set the boundary register to point to the start of the next packet
00394     rtl8019Write(BNRY, NextPage);
00395 }
00396 
00397 
00398 void rtl8019ProcessInterrupt(void)
00399 {
00400     unsigned char byte = rtl8019Read(ISR);
00401     
00402     if( byte & OVW )
00403         rtl8019ReceiveOverflowRecover();
00404 }
00405 
00406 void rtl8019ReceiveOverflowRecover(void)
00407 {
00408     unsigned char data_L, resend;   
00409 
00410     data_L = rtl8019Read(CR);
00411     rtl8019Write(CR, 0x21);
00412     delay_ms(2);
00413     rtl8019Write(RBCR0, 0x00);
00414     rtl8019Write(RBCR1, 0x00);
00415     if(!(data_L & 0x04))
00416         resend = 0;
00417     else if(data_L & 0x04)
00418     {
00419         data_L = rtl8019Read(ISR);
00420         if((data_L & 0x02) || (data_L & 0x08))
00421             resend = 0;
00422         else
00423             resend = 1;
00424     }
00425     
00426     rtl8019Write(TCR, 0x02);
00427     rtl8019Write(CR, 0x22);
00428     rtl8019Write(BNRY, RXSTART_INIT);
00429     rtl8019Write(CR, 0x62);
00430     rtl8019Write(CPR, RXSTART_INIT);
00431     rtl8019Write(CR, 0x22);
00432     rtl8019Write(ISR, 0x10);
00433     rtl8019Write(TCR, TCR_INIT);
00434     
00435     if(resend)
00436         rtl8019Write(CR, 0x26);
00437 
00438     rtl8019Write(ISR, 0xFF);
00439 }
00440 
00441 
00442 void rtl8019RegDump(void)
00443 {
00444 //  unsigned char result;
00445 //  result = rtl8019Read(TR);
00446     
00447 //  rprintf("Media State: ");
00448 //  if(!(result & AUTOD))
00449 //          rprintf("Autonegotiation\r\n");
00450 //  else if(result & RST_B)
00451 //          rprintf("PHY in Reset   \r\n");
00452 //  else if(!(result & RST_10B))
00453 //      rprintf("10BASE-T       \r\n");
00454 //  else if(!(result & RST_TXB))
00455 //      rprintf("100BASE-T      \r\n");
00456                 
00457     //rprintf("TR regsiter      : %x\r\n",result);
00458     //result = read_mii(0x10,0);
00459     //rprintf("MII regsiter 0x10: %x\r\n",result);
00460 
00461     rprintf("Page0: CR  BNRY PSR PST ISR TSR RSR MMR TR  GPI\r\n");
00462     rprintfProgStrM("       ");
00463     rprintfu08(rtl8019Read(CR));
00464     rprintfProgStrM("  ");
00465     rprintfu08(rtl8019Read(BNRY));
00466     rprintfProgStrM("   ");
00467     rprintfu08(rtl8019Read(PSTART));
00468     rprintfProgStrM("  ");
00469     rprintfu08(rtl8019Read(PSTOP));
00470     rprintfProgStrM("  ");
00471     rprintfu08(rtl8019Read(ISR));
00472     rprintfProgStrM("  ");
00473     rprintfu08(rtl8019Read(TSR));
00474     rprintfProgStrM("  ");
00475     rprintfu08(rtl8019Read(RSR));
00476     rprintfProgStrM("  ");
00477 //  rprintfu08(rtl8019Read(MEMR));
00478     rprintfProgStrM("  ");
00479 //  rprintfu08(rtl8019Read(TR));
00480     rprintfProgStrM("  ");
00481 //  rprintfu08(rtl8019Read(GPI));
00482     rprintfCRLF();
00483 
00484     rtl8019Write(CR,rtl8019Read(CR)|PS0);
00485 
00486     rprintf("Page1: CR  PAR    CPR\r\n");
00487     rprintfProgStrM("       ");
00488     rprintfu08(rtl8019Read(CR));
00489     rprintfProgStrM("  ");
00490     rprintfChar(rtl8019Read(PAR0));
00491     rprintfChar(rtl8019Read(PAR1));
00492     rprintfChar(rtl8019Read(PAR2));
00493     rprintfChar(rtl8019Read(PAR3));
00494     rprintfChar(rtl8019Read(PAR4));
00495     rprintfChar(rtl8019Read(PAR5));
00496     rprintfProgStrM(" ");
00497     rprintfu08(rtl8019Read(CPR));
00498     
00499     rtl8019Write(CR,rtl8019Read(CR)&~PS0);
00500 
00501     delay_ms(25);
00502 }
00503 

Generated on Mon Aug 22 04:29:27 2005 for Procyon AVRlib by  doxygen 1.4.2