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