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

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

Generated on Tue Sep 20 03:11:43 2005 for Procyon AVRlib by  doxygen 1.4.2