Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages   Examples  

/opentcp/ethernet.c

Go to the documentation of this file.
00001 /*
00002  *Copyright (c) 2000-2002 Viola Systems Ltd.
00003  *All rights reserved.
00004  *
00005  *Redistribution and use in source and binary forms, with or without 
00006  *modification, are permitted provided that the following conditions 
00007  *are met:
00008  *
00009  *1. Redistributions of source code must retain the above copyright 
00010  *notice, this list of conditions and the following disclaimer.
00011  *
00012  *2. Redistributions in binary form must reproduce the above copyright 
00013  *notice, this list of conditions and the following disclaimer in the 
00014  *documentation and/or other materials provided with the distribution.
00015  *
00016  *3. The end-user documentation included with the redistribution, if 
00017  *any, must include the following acknowledgment:
00018  *      "This product includes software developed by Viola 
00019  *      Systems (http://www.violasystems.com/)."
00020  *
00021  *Alternately, this acknowledgment may appear in the software itself, 
00022  *if and wherever such third-party acknowledgments normally appear.
00023  *
00024  *4. The names "OpenTCP" and "Viola Systems" must not be used to 
00025  *endorse or promote products derived from this software without prior 
00026  *written permission. For written permission, please contact 
00027  *opentcp@opentcp.org.
00028  *
00029  *5. Products derived from this software may not be called "OpenTCP", 
00030  *nor may "OpenTCP" appear in their name, without prior written 
00031  *permission of the Viola Systems Ltd.
00032  *
00033  *THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 
00034  *WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00035  *MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
00036  *IN NO EVENT SHALL VIOLA SYSTEMS LTD. OR ITS CONTRIBUTORS BE LIABLE 
00037  *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
00038  *CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
00039  *SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 
00040  *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00041  *WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00042  *OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
00043  *EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00044  *====================================================================
00045  *
00046  *OpenTCP is the unified open source TCP/IP stack available on a series 
00047  *of 8/16-bit microcontrollers, please see <http://www.opentcp.org>.
00048  *
00049  *For more information on how to network-enable your devices, or how to 
00050  *obtain commercial technical support for OpenTCP, please see 
00051  *<http://www.violasystems.com/>.
00052  */
00053 
00071 #include <inet/debug.h>
00072 #include <inet/datatypes.h>
00073 #include <inet/system.h>
00074 #include <inet/ethernet.h>
00075 
00076 
00077 #include <inet/arch/config.h>
00078 
00079 UINT8   NE2000NextPktPtr;                       
00080 UINT8   NE2000CurrPktPtr;                       
00082 UINT8   EtherSleep = 0; 
00093 struct ethernet_frame received_frame;
00094 
00105 struct ethernet_frame send_frame;
00106 
00107 
00118 void outNE2000 (UINT8 reg , UINT8 dat)
00119 {
00120 
00121         UINT8 temp = reg;
00122         
00123         DATADIR = DDR_OUT;                              /* datapins = output */
00124         DATABUS = dat;                          /* data to bus */
00125         ADRBUS =  (temp | 0x60);        /* dont change R,W,Reset pins */
00126         
00127         /* Wait until bus free */
00128         
00129         IOW = 0;                                        /* do writestrobe */
00130         while(IOCHRDY == 0);
00131         IOW = 1;
00132 
00133 }       
00134 
00148 void outNE2000again (UINT8 dat)
00149 {
00150         /* Write data to same reg as outNE2000 before */
00151         
00152         DATABUS = dat;
00153         
00154         /* Wait until bus free */
00155 
00156         IOW = 0;                                /* do writestrobe */
00157         while(IOCHRDY == 0);
00158         IOW = 1;
00159 }
00160 
00175 void outNE2000againbuf (UINT8* buf, UINT16 len)
00176 {
00177 
00178         while(len--)
00179         {
00180                 DATABUS = *buf++;
00181                 IOW = 0;
00182                 while(IOCHRDY == 0);            /* Wait until bus free */
00183                 IOW = 1;
00184         }
00185 }
00186 
00187 
00198 UINT8 inNE2000 (UINT8 reg)
00199 {
00200         UINT8 temp = reg;
00201         DATADIR = DDR_IN;                               /* port input */
00202         ADRBUS = (temp | 0x60);
00203         
00204         /* Wait until bus free */
00205         
00206         IOR = 0;                                        /* do readstrobe */
00207         while(IOCHRDY == 0);
00208         temp = DATABUS;
00209         IOR = 1;
00210         
00211         return temp;
00212 }
00213 
00226 UINT8 inNE2000again (void)
00227 {
00228         UINT8 temp;
00229         
00230         /* Wait until bus free */
00231 
00232         IOR = 0;        
00233         while(IOCHRDY == 0);
00234         temp = DATABUS;
00235         IOR = 1;
00236         
00237         return(temp);
00238  
00239 }
00240 
00252 void inNE2000againbuf (UINT8* buf, UINT16 len)
00253 {
00254         while(len--)
00255         {
00256                 IOR = 0;
00257                 while(IOCHRDY == 0);            /* Wait until bus free */                               
00258                 *buf++ = DATABUS;
00259                 IOR = 1;        
00260         }
00261 }
00262 
00274 UINT8 NE2000CheckRxFrame (void)
00275 {
00276         /* Checks to see if ethernet frame has been received */
00277         
00278         UINT8 temp;
00279         
00280         outNE2000( CR ,0x62);                   /* page 1, abort DMA */
00281         temp = inNE2000( CURR );
00282         outNE2000( CR, 0x02 );                  /* page 0 */
00283         
00284         if( temp != inNE2000( BOUNDARY ) ) {
00285                 /* Boundary != Current => packet exists */
00286                 
00287                 /* Check still for receive status       */
00288                 if(inNE2000(RCR) & 0x01)
00289                         return(TRUE);
00290 
00291         }       
00292         
00293         return(FALSE); 
00294 }
00295 
00304 void NE2000DumpRxFrame (void)
00305 {
00306  
00307         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00308         
00309         /* Set boundary to start of next packet */
00310         
00311         outNE2000( BOUNDARY, NE2000NextPktPtr );        
00312 
00313  
00314 }
00315  
00316  
00327 void NE2000Init (UINT8* mac)
00328 {
00329 
00330         /* Give HW Reset        */
00331         
00332         RESETPIN_NE2000 = 1;
00333         wait(10000);
00334         RESETPIN_NE2000 = 0;
00335         wait(10000);
00336         
00337         outNE2000( RESETPORT, 0 );              /* reset NE2000*/
00338         /* Wait for a while */
00339         
00340         wait(30000);
00341 
00342         
00343         /* Goto page 3 and set registers */
00344         outNE2000( CR, 0xC1 );                  /* page3, stop */
00345         outNE2000( 0x01, 0xC0 );                /* config reg. write enble */
00346         outNE2000( 0x05, 0 );                   /* link test enable */
00347         /* outNE2000( 0x06, 0x70 );             //Full duplex, leds */
00348         
00349         /* Goto page 1 and set registers */
00350         
00351         outNE2000( CR, 0x41 );                                                          /* page1, stop */
00352         outNE2000( PAR5, *mac++);                       /* Set MAC Address  */
00353         outNE2000( PAR4, *mac++);
00354         outNE2000( PAR3, *mac++);
00355         outNE2000( PAR2, *mac++);
00356         outNE2000( PAR1, *mac++);
00357         outNE2000( PAR0, *mac); 
00358         
00359         outNE2000( CURR, RXBUF_START ); /* Current address */
00360         NE2000NextPktPtr = RXBUF_START;
00361         NE2000CurrPktPtr = RXBUF_START;
00362         
00363         /* Goto page 0 and set registers */
00364         
00365         outNE2000( CR, 0 );                                             /* page0, Stop */
00366         outNE2000( PSTART, RXBUF_START);                /* Rx buffer start address */
00367         outNE2000( PSTOP, RXBUF_END );                  /* Rx buffer end address */
00368         outNE2000( BOUNDARY, RXBUF_START );             /* Boundary */
00369         outNE2000( ISR, 0xFF );                                 /* Interrupt services */
00370         outNE2000( RCR, 0xC4);                                  /* Rx config (Accept all), was C4 */
00371         outNE2000( TCR, 0xE0);                                  /* Tx config */
00372         outNE2000( DCR, 0xB8);                                  /* Dataconfig */
00373         
00374         /* Start action ! */
00375         
00376         outNE2000( CR, 0x22 );                   /* Page0, start */
00377         
00378 }
00379 
00380 
00393 void NE2000CheckOverFlow (void)
00394 {
00395         /* Checks if Receive Buffer overflow has happened */
00396         /* and re-initializes the NIC if needed                   */
00397         
00398         UINT8 temp;
00399 
00400         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00401 
00402         if( inNE2000( ISR ) & 0x10 ) {
00403         
00404                 /* OverFlow occured!! */
00405         
00406                 outNE2000( CR, 0x21 );          /* Issue Stop-command           */
00407  
00408                 outNE2000( RBCR0, 0x00 );       /* Clear remote Byte Count      */
00409                 outNE2000( RBCR1, 0x00 );
00410         
00411                 /* Poll the interrupt status register for RST bit */
00412         
00413                 kick_WD();
00414                 while( ( inNE2000( ISR ) & 0x80 ) == 0 );
00415 
00416                 /* RST was set, NIC is in Stop mode     */
00417                 /* Enter to LOOPBACK mode now           */
00418         
00419                 outNE2000( TCR, 0x02 );
00420         
00421                 /* Issue Start Command                                                  */
00422                 /* NIC is still inactive because LOOPBACK on    */
00423         
00424                 outNE2000(CR,0x22);
00425         
00426                 /* Remove Packet from buffer */
00427         
00428                 if(inNE2000(BOUNDARY) != NE2000NextPktPtr) {
00429                         ETH_DEBUGOUT("\r\n*********Normal Overflow**********\r\n");
00430                         outNE2000( BOUNDARY, NE2000NextPktPtr );
00431                 } else {
00432                         /* There has been an overflow after we have received the packet */
00433                         /* last time                                                                                                    */
00434                 
00435                         ETH_DEBUGOUT("???????????????????????????????????\r\n");
00436                         ETH_DEBUGOUT("Unrecognized overflow!!\r\n");
00437                         ETH_DEBUGOUT("¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤\r\n");
00438                 
00439                         outNE2000(CR ,0x62);                    /* page 1, abort DMA */
00440                         temp = inNE2000(CURR);
00441                         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00442                 
00443                         /* Dischard the whole buffer    */
00444                 
00445                         outNE2000( BOUNDARY, temp);
00446                         
00447                         NE2000NextPktPtr = temp;
00448                         NE2000CurrPktPtr = temp;                        
00449                 
00450                 }
00451  
00452                 
00453                 outNE2000( ISR, 0xFF );                  /* Interrupt services */
00454         
00455                 /* Exit from loopback to normal mode */
00456         
00457                 outNE2000( TCR, 0xE0);                   /* Tx config */
00458         
00459         }
00460  
00461 }
00462 
00482 UINT8 NE2000ReceiveFrame (void)
00483 {
00484 
00485         
00486         if( NE2000CheckRxFrame() == FALSE ) 
00487                 return(FALSE);
00488 
00489         
00490         /* There is data, receive Ethernet info */
00491         
00492         NE2000CurrPktPtr = inNE2000(BOUNDARY);  /* Store pointer */
00493         outNE2000( CR, 0x22 );                                  /* page0, abort DMA */
00494         
00495         /* Initialize DMA  to Start of the packet       */
00496         
00497         
00498         outNE2000( RSAR0, 0 );
00499         outNE2000( RSAR1, NE2000CurrPktPtr );
00500         outNE2000( RBCR0, 0xFF );                               /* Set DMA length for */
00501         outNE2000( RBCR1, 0x0F );                               /* definitely sufficient */
00502 
00503         outNE2000( CR, 0x0A );                                  /* page 0, remote read */
00504         
00505         inNE2000( IOPORT );                                             /* ignore receive status */
00506         
00507         NE2000NextPktPtr = inNE2000again();             /* Store pointer */
00508         
00509         /* Record Frame Size                                    */
00510         
00511         received_frame.frame_size = inNE2000again();                                    
00512         received_frame.frame_size |= ((UINT16)inNE2000again()) << 8;
00513         
00514         if(received_frame.frame_size > 4)
00515                 received_frame.frame_size -= 4;                 /* Remove chip specific bytes   */
00516         else
00517                 return(FALSE);
00518         
00519         /* Record destination Ethernet Address  */
00520         
00521         received_frame.destination[5] = inNE2000again();                                                
00522         received_frame.destination[4] = inNE2000again();
00523         received_frame.destination[3] = inNE2000again();
00524         received_frame.destination[2] = inNE2000again();
00525         received_frame.destination[1] = inNE2000again();
00526         received_frame.destination[0] = inNE2000again();
00527         
00528         /* Record senders Ethernet address              */
00529         
00530         received_frame.source[5] = inNE2000again();
00531         received_frame.source[4] = inNE2000again();
00532         received_frame.source[3] = inNE2000again();
00533         received_frame.source[2] = inNE2000again();
00534         received_frame.source[1] = inNE2000again();
00535         received_frame.source[0] = inNE2000again(); 
00536         
00537         /* Record Protocol      */
00538         
00539         received_frame.protocol = inNE2000again();
00540         received_frame.protocol <<= 8;
00541         received_frame.protocol |= inNE2000again();
00542         
00543         /* Give the next layer data start buffer index from the start   */
00544         
00545         received_frame.buf_index = ETH_HEADER_LEN;
00546         
00547         /* Stop DMA */
00548         
00549         outNE2000( CR, 0x22 );  
00550         
00551         ETH_DEBUGOUT("Ethernet Frame Received\n\r");
00552         
00553         return(TRUE);                                           /* Indicate we got packet */
00554         
00555 }
00556 
00570 void InitTransmission (UINT8 page)
00571 {
00572         /* Initializes NE2000 for remote write                                          */
00573         
00574         while( (inNE2000(CR) & 0x04) ) ;                /* wait Tx to complete */
00575         
00576         outNE2000( CR, 0x22 );                          /* page0, abort DMA */
00577         
00578         outNE2000( TPSR, page );                        /* Tx buffer Start */
00579         
00580         outNE2000( RSAR0, 0x00 );                       /* Remote DMA start */
00581         outNE2000( RSAR1, page );
00582         
00583         outNE2000( RBCR0, 0xEA );                       /* Max.Ethernet frame */
00584         outNE2000( RBCR1, 0x05 );                       /* size */
00585         
00586         outNE2000( CR, 0x12 );                          /* page0, remote write */
00587         
00588         /* Set Address lines to be ready        */
00589         
00590         DATADIR = DDR_OUT;                              /* datapins = output */
00591         ADRBUS =  (IOPORT | 0x60);      /* dont change R,W,Reset pins */
00592                 
00593         
00594 }
00595 
00608 void NE2000WriteEthernetHeader (struct ethernet_frame* frame)
00609 {
00610         INT8 i;
00611         
00612         /* Write destination Ethernet Address   */
00613         
00614         for(i=ETH_ADDRESS_LEN-1; i >= 0; i--) {
00615                 outNE2000again(frame->destination[i]);
00616         }
00617 
00618         /* Write sender (our) Ethernet address  */
00619         
00620         for(i=ETH_ADDRESS_LEN-1; i >= 0; i--) {
00621                 outNE2000again(frame->source[i]);
00622         }
00623         
00624         /* Write protocol                                               */
00625         
00626         outNE2000again( (UINT8)(frame->protocol >> 8) );
00627         outNE2000again( (UINT8)frame->protocol );
00628 
00629 }
00630 
00639 void NE2000DMAInit (UINT8 page)
00640 {
00641         
00642         outNE2000( CR, 0x22 );                  /* page0, abort DMA  */
00643         
00644         /* Initialize DMA  to address field in Ethernet Frame   */
00645         /* That is, isolate chip specific fields from                   */
00646         /* actual Ethernet Frame                                                                */
00647         
00648         outNE2000( RSAR0, 4 );
00649         outNE2000( RSAR1, page );
00650         outNE2000( RBCR0, 0xFF );               /* Set DMA length for */
00651         outNE2000( RBCR1, 0x0F );               /* definitely sufficient */
00652         
00653 }
00654 
00665 void NE2000DMAInit_position (UINT16 pos)
00666 {
00667         
00668         UINT16 abspos;
00669         UINT16 page;
00670         UINT8 offset;
00671         
00672         /* Calculate start page */
00673         
00674         abspos = pos + 4;
00675         
00676         page = (UINT8)(abspos >> 8);
00677         page += NE2000CurrPktPtr;
00678         
00679         /* Check we are not exceeding the Rx buffer space       */
00680         
00681         if( page >= RXBUF_END ) {
00682                 page = RXBUF_START + (page - RXBUF_END);
00683         } 
00684         
00685         offset = (UINT8)(abspos & 0xFF);
00686         
00687         /* Make settings                */
00688          
00689         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00690         
00691         /* Initialize DMA  to address field in Ethernet Frame   */
00692         /* That is, isolate chip specific fields from                   */
00693         /* actual Ethernet Frame                                                                */
00694         
00695         outNE2000( RSAR0, offset );
00696         outNE2000( RSAR1, (UINT8)page );
00697         outNE2000( RBCR0, 0xFF );               /* Set DMA length for */
00698         outNE2000( RBCR1, 0x0F );               /* definitely sufficient */
00699         
00700         outNE2000( CR, 0x0A );                  /* page 0, remote read */
00701         
00702         /* Init Address bus     */
00703 
00704         DATADIR = DDR_IN;                               /* port input */
00705         ADRBUS = (IOPORT | 0x60);
00706         
00707         /* Now just read by inNE2000again()             */
00708 }
00709 
00710 
00711 
00725 void NE2000SendFrame ( UINT16 len )
00726 {
00727         /* After filling Tx buffer, call this function to send it */
00728         /* Input:       Len: packet length                                                        */
00729 
00730         
00731         /* Check if we need to insert Pad bytes */
00732         
00733         while(len < 50) {
00734                 outNE2000again((BYTE)0x00);
00735                 len++;
00736         }
00737         
00738         len += 6 + 6 + 2;
00739         
00740         outNE2000( CR, (BYTE)0x22 );                            /* Page0, abort DMA */
00741         
00742         outNE2000( TBCR0, (BYTE)(len) );
00743         outNE2000( TBCR1, (BYTE)(len >> 8 ) );
00744         
00745         /* Transmit packet to Ether */
00746         
00747         outNE2000( CR, (BYTE)0x06 );            /* Page0, transmit */
00748         
00749         
00750 }
00751 
00760 void NE2000EnterSleep (void) 
00761 {
00762         if (EtherSleep)
00763                 return;
00764 
00765         EtherSleep = 1;
00766         
00767         outNE2000( CR, 0xE2 );                  /* page3, abort DMA      */
00768         outNE2000( 0x06, 0x04);                 /* Sleep */
00769 }
00770 
00779 void NE2000ExitSleep (void) 
00780 {
00781         if (EtherSleep) {
00782                 outNE2000( CR, 0xE2 );                  /* age3, abort DMA       */
00783                 outNE2000( 0x06, 0x00);                 /* Wake up */
00784                 EtherSleep = 0;
00785         }
00786                 
00787 }

Generated on Sun Aug 3 20:32:59 2003 for OpenTCP by doxygen1.2.18