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 
00072 #include <inet/debug.h>
00073 #include <inet/datatypes.h>
00074 #include <inet/system.h>
00075 #include <inet/ethernet.h>
00076 
00077 
00078 #include <inet/arch/config.h>
00079 
00080 UINT8   NE2000NextPktPtr;                       
00081 UINT8   NE2000CurrPktPtr;                       
00083 UINT8   EtherSleep = 0; 
00094 struct ethernet_frame received_frame;
00095 
00106 struct ethernet_frame send_frame;
00107 
00108 
00119 void outNE2000 (UINT8 reg , UINT8 dat)
00120 {
00121 
00122         UINT8 temp = reg;
00123         
00124         DATADIR = DDR_OUT;                              /* datapins = output */
00125         DATABUS = dat;                          /* data to bus */
00126         ADRBUS =  (temp | 0x60);        /* dont change R,W,Reset pins */
00127         
00128         /* Wait until bus free */
00129         
00130         while(IOCHRDY == 0);
00131         
00132         IOW = 0;                                        /* do writestrobe */
00133         IOW = 1;
00134 
00135 }       
00136 
00150 void outNE2000again (UINT8 dat)
00151 {
00152         /* Write data to same reg as outNE2000 before */
00153         
00154         DATABUS = dat;
00155         
00156         /* Wait until bus free */
00157         
00158         while(IOCHRDY == 0);
00159         
00160         IOW = 0;                                /* do writestrobe */
00161         IOW = 1;
00162  
00163 }
00164 
00175 UINT8 inNE2000 (UINT8 reg)
00176 {
00177         UINT8 temp = reg;
00178         DATADIR = DDR_IN;                               /* port input */
00179         ADRBUS = (temp | 0x60);
00180         
00181         /* Wait until bus free */
00182         
00183         while(IOCHRDY == 0);
00184         
00185         IOR = 0;                                        /* do readstrobe */
00186         temp = DATABUS;
00187         IOR = 1;
00188         
00189         return temp;
00190 }
00191 
00204 UINT8 inNE2000again (void)
00205 {
00206         UINT8 temp;
00207         
00208         /* Wait until bus free */
00209         
00210         while(IOCHRDY == 0);
00211         
00212         IOR = 0;
00213         temp = DATABUS;
00214         IOR = 1;
00215         
00216         return(temp);
00217  
00218 }
00219 
00231 UINT8 NE2000CheckRxFrame (void)
00232 {
00233         /* Checks to see if ethernet frame has been received */
00234         
00235         UINT8 temp;
00236         
00237         outNE2000( CR ,0x62);                   /* page 1, abort DMA */
00238         temp = inNE2000( CURR );
00239         outNE2000( CR, 0x02 );                  /* page 0 */
00240         
00241         if( temp != inNE2000( BOUNDARY ) ) {
00242                 /* Boundary != Current => packet exists */
00243  
00244                 return(TRUE);
00245         }       
00246         
00247         return(FALSE);
00248  
00249 }
00250 
00259 void NE2000DumpRxFrame (void)
00260 {
00261  
00262         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00263         
00264         /* Set boundary to start of next packet */
00265         
00266         outNE2000( BOUNDARY, NE2000NextPktPtr );        
00267 
00268  
00269 }
00270  
00271  
00282 void NE2000Init (UINT8* mac)
00283 {
00284 
00285         /* Give HW Reset        */
00286         
00287         RESETPIN_NE2000 = 1;
00288         wait(10000);
00289         RESETPIN_NE2000 = 0;
00290         wait(10000);
00291         
00292         outNE2000( RESETPORT, 0 );              /* reset NE2000*/
00293         /* Wait for a while */
00294         
00295         wait(30000);
00296 
00297         
00298         /* Goto page 3 and set registers */
00299         outNE2000( CR, 0xC1 );                  /* page3, stop */
00300         outNE2000( 0x01, 0xC0 );                /* config reg. write enble */
00301         outNE2000( 0x05, 0 );                   /* link test enable */
00302         /* outNE2000( 0x06, 0x70 );             //Full duplex, leds */
00303         
00304         /* Goto page 1 and set registers */
00305         
00306         outNE2000( CR, 0x41 );                                                          /* page1, stop */
00307         outNE2000( PAR5, *mac++);                       /* Set MAC Address  */
00308         outNE2000( PAR4, *mac++);
00309         outNE2000( PAR3, *mac++);
00310         outNE2000( PAR2, *mac++);
00311         outNE2000( PAR1, *mac++);
00312         outNE2000( PAR0, *mac); 
00313         
00314         outNE2000( CURR, RXBUF_START ); /* Current address */
00315         
00316         /* Goto page 0 and set registers */
00317         
00318         outNE2000( CR, 0 );                                             /* page0, Stop */
00319         outNE2000( PSTART, RXBUF_START);                /* Rx buffer start address */
00320         outNE2000( PSTOP, RXBUF_END );                  /* Rx buffer end address */
00321         outNE2000( BOUNDARY, RXBUF_START );             /* Boundary */
00322         outNE2000( ISR, 0xFF );                                 /* Interrupt services */
00323         outNE2000( RCR, 0xD6);                                  /* Rx config (Accept all), was C4 */
00324         outNE2000( TCR, 0xE0);                                  /* Tx config */
00325         outNE2000( DCR, 0xB8);                                  /* Dataconfig */
00326         
00327         /* Start action ! */
00328         
00329         outNE2000( CR, 0x22 );                   /* Page0, start */
00330         
00331 }
00332 
00333 
00346 void NE2000CheckOverFlow (void)
00347 {
00348         /* Checks if Receive Buffer overflow has happened */
00349         /* and re-initializes the NIC if needed                   */
00350         
00351         UINT8 temp;
00352 
00353         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00354 
00355         if( inNE2000( ISR ) & 0x10 ) {
00356         
00357                 /* OverFlow occured!! */
00358         
00359                 outNE2000( CR, 0x21 );          /* Issue Stop-command           */
00360  
00361                 outNE2000( RBCR0, 0x00 );       /* Clear remote Byte Count      */
00362                 outNE2000( RBCR1, 0x00 );
00363         
00364                 /* Poll the interrupt status register for RST bit */
00365         
00366                 kick_WD();
00367                 while( ( inNE2000( ISR ) & 0x80 ) == 0 );
00368 
00369                 /* RST was set, NIC is in Stop mode     */
00370                 /* Enter to LOOPBACK mode now           */
00371         
00372                 outNE2000( TCR, 0x02 );
00373         
00374                 /* Issue Start Command                                                  */
00375                 /* NIC is still inactive because LOOPBACK on    */
00376         
00377                 outNE2000(CR,0x22);
00378         
00379                 /* Remove Packet from buffer */
00380         
00381                 NE2000DumpRxFrame();
00382                 
00383                 outNE2000( ISR, 0xFF );                  /* Interrupt services */
00384         
00385                 /* Exit from loopback to normal mode */
00386         
00387                 outNE2000( TCR, 0xE0);                   /* Tx config */
00388         
00389         }
00390  
00391 }
00392 
00412 UINT8 NE2000ReceiveFrame (void)
00413 {
00414 
00415         
00416         if( NE2000CheckRxFrame() == FALSE ) 
00417                 return(FALSE);
00418 
00419         
00420         /* There is data, receive Ethernet info */
00421         
00422         NE2000CurrPktPtr = inNE2000(BOUNDARY);  /* Store pointer */
00423         outNE2000( CR, 0x22 );                                  /* page0, abort DMA */
00424         
00425         /* Initialize DMA  to Start of the packet       */
00426         
00427         
00428         outNE2000( RSAR0, 0 );
00429         outNE2000( RSAR1, NE2000CurrPktPtr );
00430         outNE2000( RBCR0, 0xFF );                               /* Set DMA length for */
00431         outNE2000( RBCR1, 0x0F );                               /* definitely sufficient */
00432 
00433         outNE2000( CR, 0x0A );                                  /* page 0, remote read */
00434         
00435         inNE2000( IOPORT );                                             /* ignore receive status */
00436         
00437         NE2000NextPktPtr = inNE2000again();             /* Store pointer */
00438         
00439         /* Record Frame Size                                    */
00440         
00441         received_frame.frame_size = inNE2000again();                                    
00442         received_frame.frame_size |= ((UINT16)inNE2000again()) << 8;
00443         
00444         if(received_frame.frame_size > 4)
00445                 received_frame.frame_size -= 4;                 /* Remove chip specific bytes   */
00446         else
00447                 return(FALSE);
00448         
00449         /* Record destination Ethernet Address  */
00450         
00451         received_frame.destination[5] = inNE2000again();                                                
00452         received_frame.destination[4] = inNE2000again();
00453         received_frame.destination[3] = inNE2000again();
00454         received_frame.destination[2] = inNE2000again();
00455         received_frame.destination[1] = inNE2000again();
00456         received_frame.destination[0] = inNE2000again();
00457         
00458         /* Record senders Ethernet address              */
00459         
00460         received_frame.source[5] = inNE2000again();
00461         received_frame.source[4] = inNE2000again();
00462         received_frame.source[3] = inNE2000again();
00463         received_frame.source[2] = inNE2000again();
00464         received_frame.source[1] = inNE2000again();
00465         received_frame.source[0] = inNE2000again(); 
00466         
00467         /* Record Protocol      */
00468         
00469         received_frame.protocol = inNE2000again();
00470         received_frame.protocol <<= 8;
00471         received_frame.protocol |= inNE2000again();
00472         
00473         /* Give the next layer data start buffer index from the start   */
00474         
00475         received_frame.buf_index = ETH_HEADER_LEN;
00476         
00477         /* Stop DMA */
00478         
00479         outNE2000( CR, 0x22 );  
00480         
00481         ETH_DEBUGOUT("Ethernet Frame Received\n\r");
00482         
00483         return(TRUE);                                           /* Indicate we got packet */
00484         
00485 }
00486 
00500 void InitTransmission (UINT8 page)
00501 {
00502         /* Initializes NE2000 for remote write                                          */
00503         
00504         while( (inNE2000(CR) & 0x04) ) ;                /* wait Tx to complete */
00505         
00506         outNE2000( CR, 0x22 );                          /* page0, abort DMA */
00507         
00508         outNE2000( TPSR, page );                        /* Tx buffer Start */
00509         
00510         outNE2000( RSAR0, 0x00 );                       /* Remote DMA start */
00511         outNE2000( RSAR1, page );
00512         
00513         outNE2000( RBCR0, 0xEA );                       /* Max.Ethernet frame */
00514         outNE2000( RBCR1, 0x05 );                       /* size */
00515         
00516         outNE2000( CR, 0x12 );                          /* page0, remote write */
00517         
00518         /* Set Address lines to be ready        */
00519         
00520         DATADIR = 0xFF;                         /* datapins = output */
00521         ADRBUS =  (IOPORT | 0x60);      /* dont change R,W,Reset pins */
00522                 
00523         
00524 }
00525 
00538 void NE2000WriteEthernetHeader (struct ethernet_frame* frame)
00539 {
00540         INT8 i;
00541         
00542         /* Write destination Ethernet Address   */
00543         
00544         for(i=ETH_ADDRESS_LEN-1; i >= 0; i--) {
00545                 outNE2000again(frame->destination[i]);
00546         }
00547 
00548         /* Write sender (our) Ethernet address  */
00549         
00550         for(i=ETH_ADDRESS_LEN-1; i >= 0; i--) {
00551                 outNE2000again(frame->source[i]);
00552         }
00553         
00554         /* Write protocol                                               */
00555         
00556         outNE2000again( (UINT8)(frame->protocol >> 8) );
00557         outNE2000again( (UINT8)frame->protocol );
00558 
00559 }
00560 
00569 void NE2000DMAInit (UINT8 page)
00570 {
00571         
00572         outNE2000( CR, 0x22 );                  /* page0, abort DMA  */
00573         
00574         /* Initialize DMA  to address field in Ethernet Frame   */
00575         /* That is, isolate chip specific fields from                   */
00576         /* actual Ethernet Frame                                                                */
00577         
00578         outNE2000( RSAR0, 4 );
00579         outNE2000( RSAR1, page );
00580         outNE2000( RBCR0, 0xFF );               /* Set DMA length for */
00581         outNE2000( RBCR1, 0x0F );               /* definitely sufficient */
00582         
00583 }
00584 
00595 void NE2000DMAInit_position (UINT16 pos)
00596 {
00597         
00598         UINT16 abspos;
00599         UINT16 page;
00600         UINT8 offset;
00601         
00602         /* Calculate start page */
00603         
00604         abspos = pos + 4;
00605         
00606         page = (UINT8)(abspos >> 8);
00607         page += NE2000CurrPktPtr;
00608         
00609         /* Check we are not exceeding the Rx buffer space       */
00610         
00611         if( page >= RXBUF_END ) {
00612                 page = RXBUF_START + (page - RXBUF_END);
00613         } 
00614         
00615         offset = (UINT8)(abspos & 0xFF);
00616         
00617         /* Make settings                */
00618          
00619         outNE2000( CR, 0x22 );                  /* page0, abort DMA */
00620         
00621         /* Initialize DMA  to address field in Ethernet Frame   */
00622         /* That is, isolate chip specific fields from                   */
00623         /* actual Ethernet Frame                                                                */
00624         
00625         outNE2000( RSAR0, offset );
00626         outNE2000( RSAR1, (UINT8)page );
00627         outNE2000( RBCR0, 0xFF );               /* Set DMA length for */
00628         outNE2000( RBCR1, 0x0F );               /* definitely sufficient */
00629         
00630         outNE2000( CR, 0x0A );                  /* page 0, remote read */
00631         
00632         /* Init Address bus     */
00633 
00634         DATADIR = 0x00;                         /* port input */
00635         ADRBUS = (IOPORT | 0x60);
00636         
00637         /* Now just read by inNE2000again()             */
00638 }
00639 
00640 
00641 
00655 void NE2000SendFrame ( UINT16 len )
00656 {
00657         /* After filling Tx buffer, call this function to send it */
00658         /* Input:       Len: packet length                                                        */
00659 
00660         
00661         /* Check if we need to insert Pad bytes */
00662         
00663         while(len < 50) {
00664                 outNE2000again((BYTE)0x00);
00665                 len++;
00666         }
00667         
00668         len += 6 + 6 + 2;
00669         
00670         outNE2000( CR, (BYTE)0x22 );                            /* Page0, abort DMA */
00671         
00672         outNE2000( TBCR0, (BYTE)(len) );
00673         outNE2000( TBCR1, (BYTE)(len >> 8 ) );
00674         
00675         /* Transmit packet to Ether */
00676         
00677         outNE2000( CR, (BYTE)0x06 );            /* Page0, transmit */
00678         
00679         
00680 }
00681 
00690 void NE2000EnterSleep (void) 
00691 {
00692         if (EtherSleep)
00693                 return;
00694 
00695         EtherSleep = 1;
00696         
00697         outNE2000( CR, 0xE2 );                  /* page3, abort DMA      */
00698         outNE2000( 0x06, 0x04);                 /* Sleep */
00699 }
00700 
00709 void NE2000ExitSleep (void) 
00710 {
00711         if (EtherSleep) {
00712                 outNE2000( CR, 0xE2 );                  /* age3, abort DMA       */
00713                 outNE2000( 0x06, 0x00);                 /* Wake up */
00714                 EtherSleep = 0;
00715         }
00716                 
00717 }

Generated on Sat Jan 25 17:13:14 2003 for OpenTCP by doxygen1.2.18