ETH97J60.c

Go to the documentation of this file.
00001 // ////////////////////////////////////////////////////////////////////////////
00002 // ////////////////////////////////////////////////////////////////////////////
00031 /*********************************************************************
00032  * Software License Agreement
00033  *
00034  * Copyright (C) 2002-2008 Microchip Technology Inc.  All rights 
00035  * reserved.
00036  *
00037  * Microchip licenses to you the right to use, modify, copy, and 
00038  * distribute: 
00039  * (i)  the Software when embedded on a Microchip microcontroller or 
00040  *      digital signal controller product ("Device") which is 
00041  *      integrated into Licensee's product; or
00042  * (ii) ONLY the Software driver source files ENC28J60.c and 
00043  *      ENC28J60.h ported to a non-Microchip device used in 
00044  *      conjunction with a Microchip ethernet controller for the 
00045  *      sole purpose of interfacing with the ethernet controller. 
00046  *
00047  * You should refer to the license agreement accompanying this 
00048  * Software for additional information regarding your rights and 
00049  * obligations.
00050  *
00051  * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 
00052  * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 
00053  * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 
00054  * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 
00055  * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 
00056  * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 
00057  * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 
00058  * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 
00059  * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 
00060  * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 
00061  * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
00062  *
00063  *
00064 /*********************************************************************
00065  * Author               Date     Comment
00066  *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00067  * Rawin Rojvanit       07/26/05 Stuff
00068  * Howard Schlunder     11/17/05 Ported to PIC18F97J60
00069  * Howard Schlunder     06/16/06 Synchronized with ENC28J60 code
00070  * Howard Schlunder     05/21/07 Fixed a TX lockup problem
00071 ********************************************************************/
00072 #define __ETH97J60_C
00073 
00074 #include "TCPIP.h"
00075 
00076 // MODIFIX: Removed the macro request for the ethernet transceiver.
00077 
00078 
00080 // Since the Ethernet PHY doesn't support auto-negotiation, full-duplex mode is 
00081 // not compatible with most switches/routers.  If a dedicated network is used 
00082 // where the duplex of the remote node can be manually configured, you may 
00083 // change this configuration.  Otherwise, half duplex should always be used.
00084 #define HALF_DUPLEX
00085 //#define FULL_DUPLEX
00086 
00087 // Pseudo Functions
00088 #define LOW(a)                  (a & 0xFF)
00089 #define HIGH(a)                 ((a>>8) & 0xFF)
00090 
00091 #define ETHER_IP    (0x00u)
00092 #define ETHER_ARP   (0x06u)
00093 
00094 // A header appended at the start of all RX frames by the hardware
00095 typedef struct _ENC_PREAMBLE
00096 {
00097     WORD            NextPacketPointer;
00098     RXSTATUS        StatusVector;
00099 
00100     MAC_ADDR        DestMACAddr;
00101     MAC_ADDR        SourceMACAddr;
00102     WORD_VAL        Type;
00103 } ENC_PREAMBLE;
00104 
00105 
00106 // Internal MAC level variables and flags.
00107 static WORD_VAL NextPacketLocation;
00108 static WORD_VAL CurrentPacketLocation;
00109 static BOOL WasDiscarded;
00110 static WORD wTXWatchdog;
00111 
00112 
00113 /******************************************************************************
00114  * Function:        void MACInit(void)
00115  *
00116  * PreCondition:    None
00117  *
00118  * Input:           None
00119  *
00120  * Output:          None
00121  *
00122  * Side Effects:    None
00123  *
00124  * Overview:        MACInit enables the Ethernet module, waits for the 
00125  *                  to become ready, and programs all registers for future 
00126  *                  TX/RX operations.
00127  *
00128  * Note:            This function blocks for at least 1ms, waiting for the 
00129  *                  hardware to stabilize.
00130  *****************************************************************************/
00131 void MACInit(void)
00132 {
00133     BYTE i;
00134     
00135     LATAbits.LATA0 = 0;
00136     LATAbits.LATA1 = 0;
00137 
00138     TRISAbits.TRISA0 = 0;   // Set LED0 as output
00139     TRISAbits.TRISA1 = 0;   // Set LED1 as output
00140     ECON2bits.ETHEN = 1;    // Enable Ethernet!
00141 
00142     // Wait for PHYRDY to become set.
00143     while(!ESTATbits.PHYRDY);
00144     
00145     // Configure the receive buffer boundary pointers 
00146     // and the buffer write protect pointer (receive buffer read pointer)
00147     WasDiscarded = TRUE;
00148     NextPacketLocation.Val = RXSTART;
00149     ERXST = RXSTART;
00150     ERXRDPTL = LOW(RXSTOP); // Write low byte first
00151     ERXRDPTH = HIGH(RXSTOP);// Write high byte last
00152     ERXND = RXSTOP;
00153     ETXST = TXSTART;
00154 
00155     // Write a permanant per packet control byte of 0x00
00156     EWRPT = TXSTART;
00157     MACPut(0x00);
00158 
00159     // Configure Receive Filters 
00160     // (No need to reconfigure - Unicast OR Broadcast with CRC checking is 
00161     // acceptable)
00162     //ERXFCON = ERXFCON_CRCEN;     // Promiscious mode
00163     ERXFCON = 0xA3;             // MODIFIX: Enable Multicasts
00164 
00165     // Configure the MAC
00166     // Enable the receive portion of the MAC
00167     MACON1 = MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN; Nop();
00168 
00169     // Pad packets to 60 bytes, add CRC, and check Type/Length field.
00170 #if defined(FULL_DUPLEX)
00171     MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX; Nop();
00172     MABBIPG = 0x15; Nop();
00173 #else
00174     MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN; Nop();
00175     MABBIPG = 0x12; Nop();
00176 #endif
00177 
00178     // Allow infinite deferals if the medium is continuously busy 
00179     // (do not time out a transmission if the half duplex medium is 
00180     // completely saturated with other people's data)
00181     MACON4 = MACON4_DEFER; Nop();
00182 
00183     // Set non-back-to-back inter-packet gap to 9.6us.  The back-to-back 
00184     // inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called 
00185     // later.
00186     MAIPGL = 0x12; Nop();
00187     MAIPGH = 0x0C; Nop();
00188 
00189     // Set the maximum packet size which the controller will accept
00190     MAMXFLL = LOW(6+6+2+1500+4); Nop();
00191     MAMXFLH = HIGH(6+6+2+1500+4); Nop();
00192     
00193     // MODIFIX: Initialize physical MAC address registers from flash.
00194     MAADR1 = pu8MAC[0]; Nop();
00195     MAADR2 = pu8MAC[1]; Nop();
00196     MAADR3 = pu8MAC[2]; Nop();
00197     MAADR4 = pu8MAC[3]; Nop();
00198     MAADR5 = pu8MAC[4]; Nop();
00199     MAADR6 = pu8MAC[5]; Nop();
00200 
00201     // Disable half duplex loopback in PHY and set RXAPDIS bit as per errata 
00202     WritePHYReg(PHCON2, PHCON2_HDLDIS | PHCON2_RXAPDIS);
00203 
00204     // Configure LEDA to display LINK status, LEDB to display TX/RX activity
00205     SetLEDConfig(0x3472);
00206     
00207     // Set the PHY into the proper duplex state
00208 #if defined(FULL_DUPLEX)
00209     WritePHYReg(PHCON1, PHCON1_PDPXMD);
00210 #else
00211     WritePHYReg(PHCON1, 0x0000);
00212 #endif
00213 
00214     // Enable packet reception
00215     ECON1bits.RXEN = 1;
00216 }//end MACInit
00217 
00218 
00219 /******************************************************************************
00220  * Function:        BOOL MACIsLinked(void)
00221  *
00222  * PreCondition:    None
00223  *
00224  * Input:           None
00225  *
00226  * Output:          TRUE: If the PHY reports that a link partner is present 
00227  *                        and the link has been up continuously since the last 
00228  *                        call to MACIsLinked()
00229  *                  FALSE: If the PHY reports no link partner, or the link went 
00230  *                         down momentarily since the last call to MACIsLinked()
00231  *
00232  * Side Effects:    None
00233  *
00234  * Overview:        Returns the PHSTAT1.LLSTAT bit.
00235  *
00236  * Note:            None
00237  *****************************************************************************/
00238 /*BOOL MACIsLinked(void)
00239 {
00240     // LLSTAT is a latching low link status bit.  Therefore, if the link 
00241     // goes down and comes back up before a higher level stack program calls
00242     // bMACIsLinked(), bMACIsLinked() will still return FALSE.  The next 
00243     // call to MACIsLinked() will return TRUE (unless the link goes down 
00244     // again).
00245     return ReadPHYReg(PHSTAT1).PHSTAT1bits.LLSTAT;
00246 }
00247 */
00248 BOOL MACIsLinked( void )
00249 {
00250     // MODIFIX: We simply check the link status LED, whether there is a link.
00252     return PORTAbits.RA0;
00253 }
00254 
00255 /******************************************************************************
00256  * Function:        BOOL MACIsTxReady(void)
00257  *
00258  * PreCondition:    None
00259  *
00260  * Input:           None
00261  *
00262  * Output:          TRUE: If no Ethernet transmission is in progress
00263  *                  FALSE: If a previous transmission was started, and it has 
00264  *                         not completed yet.  While FALSE, the data in the 
00265  *                         transmit buffer and the TXST/TXND pointers must not
00266  *                         be changed.
00267  *
00268  * Side Effects:    None
00269  *
00270  * Overview:        Returns the ECON1.TXRTS bit
00271  *
00272  * Note:            None
00273  *****************************************************************************/
00274 BOOL MACIsTxReady(void)
00275 {
00276     if(!ECON1bits.TXRTS)
00277         return TRUE;
00278 
00279     // Retry transmission if the current packet seems to be not completing
00280     // Wait 3ms before triggering the retry.
00281     if((WORD)TickGet() - wTXWatchdog >= (3ull*TICK_SECOND/1000ull))
00282     {
00283         ECON1bits.TXRTS = 0;
00284         MACFlush();
00285     }
00286     
00287     return FALSE;
00288 }
00289 
00290 /******************************************************************************
00291  * Function:        void MACDiscardRx(void)
00292  *
00293  * PreCondition:    None
00294  *
00295  * Input:           None
00296  *
00297  * Output:          None
00298  *
00299  * Side Effects:    None
00300  *
00301  * Overview:        Marks the last received packet (obtained using 
00302  *                  MACGetHeader())as being processed and frees the buffer 
00303  *                  memory associated with it
00304  *
00305  * Note:            Is is safe to call this function multiple times between 
00306  *                  MACGetHeader() calls.  Extra packets won't be thrown away 
00307  *                  until MACGetHeader() makes it available.
00308  *****************************************************************************/
00309 void MACDiscardRx(void)
00310 {
00311     WORD_VAL NewRXRDLocation;
00312 
00313     // Make sure the current packet was not already discarded
00314     if(WasDiscarded)
00315         return;
00316     WasDiscarded = TRUE;
00317 
00318     // Decrement the next packet pointer before writing it into 
00319     // the ERXRDPT registers.  This is a silicon errata workaround.
00320     // RX buffer wrapping must be taken into account if the 
00321     // NextPacketLocation is precisely RXSTART.
00322     NewRXRDLocation.Val = NextPacketLocation.Val - 1;
00323 #if RXSTART == 0
00324     if(NewRXRDLocation.Val > RXSTOP)
00325 #else
00326     if(NewRXRDLocation.Val < RXSTART || NewRXRDLocation.Val > RXSTOP)
00327 #endif
00328     {
00329         NewRXRDLocation.Val = RXSTOP;
00330     }
00331 
00332     // Decrement the RX packet counter register, EPKTCNT
00333     ECON2bits.PKTDEC = 1;
00334 
00335     // Move the receive read pointer to unwrite-protect the memory used by the 
00336     // last packet.  The writing order is important: set the low byte first, 
00337     // high byte last.
00338     ERXRDPTL = NewRXRDLocation.v[0];
00339     ERXRDPTH = NewRXRDLocation.v[1];
00340     
00341     // The PKTIF flag should automatically be cleared by hardware, but 
00342     // early beta silicon requires that you manually clear it.  This should be 
00343     // unneeded for production A0 silicon and later.
00344     EIRbits.PKTIF = 0;
00345 }
00346 
00347 
00348 /******************************************************************************
00349  * Function:        WORD MACGetFreeRxSize(void)
00350  *
00351  * PreCondition:    None
00352  *
00353  * Input:           None
00354  *
00355  * Output:          A WORD estimate of how much RX buffer space is free at 
00356  *                  the present time.
00357  *
00358  * Side Effects:    None
00359  *
00360  * Overview:        None
00361  *
00362  * Note:            None
00363  *****************************************************************************/
00364 WORD MACGetFreeRxSize(void)
00365 {
00366     WORD_VAL ReadPT, WritePT;
00367 
00368     // Read the Ethernet hardware buffer write pointer.  Because packets can be 
00369     // received at any time, it can change between reading the low and high 
00370     // bytes.  A loop is necessary to make certain a proper low/high byte pair
00371     // is read.
00372     do {
00373         // Save EPKTCNT in a temporary location
00374         ReadPT.v[0] = EPKTCNT;
00375     
00376         WritePT.Val = ERXWRPT;  
00377     } while(EPKTCNT != ReadPT.v[0]);
00378     
00379     // Determine where the write protection pointer is
00380     ReadPT.Val = ERXRDPT;
00381 
00382     
00383     // Calculate the difference between the pointers, taking care to account 
00384     // for buffer wrapping conditions
00385     if(WritePT.Val > ReadPT.Val)
00386     {
00387         return (RXSTOP - RXSTART) - (WritePT.Val - ReadPT.Val);
00388     }
00389     else if(WritePT.Val == ReadPT.Val)
00390     {
00391         return RXSIZE - 1;
00392     }
00393     else
00394     {
00395         return ReadPT.Val - WritePT.Val - 1;
00396     }
00397 }
00398 
00399 /******************************************************************************
00400  * Function:        BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
00401  *
00402  * PreCondition:    None
00403  *
00404  * Input:           *remote: Location to store the Source MAC address of the 
00405  *                           received frame.
00406  *                  *type: Location of a BYTE to store the constant 
00407  *                         MAC_UNKNOWN, ETHER_IP, or ETHER_ARP, representing 
00408  *                         the contents of the Ethernet type field.
00409  *
00410  * Output:          TRUE: If a packet was waiting in the RX buffer.  The 
00411  *                        remote, and type values are updated.
00412  *                  FALSE: If a packet was not pending.  remote and type are 
00413  *                         not changed.
00414  *
00415  * Side Effects:    Last packet is discarded if MACDiscardRx() hasn't already
00416  *                  been called.
00417  *
00418  * Overview:        None
00419  *
00420  * Note:            None
00421  *****************************************************************************/
00422 BOOL MACGetHeader(MAC_ADDR *remote, BYTE* type)
00423 {
00424     ENC_PREAMBLE header;
00425 
00426     // Test if at least one packet has been received and is waiting
00427     if(EPKTCNT == 0u)
00428     {
00429         return FALSE;
00430     }
00431 
00432     // Make absolutely certain that any previous packet was discarded
00433     if(WasDiscarded == FALSE)
00434     {
00435         MACDiscardRx();
00436         return FALSE;
00437     }
00438     // Save the location of this packet
00439     CurrentPacketLocation.Val = NextPacketLocation.Val;
00440 
00441     // Set the read pointer to the beginning of the next unprocessed packet
00442     ERDPT = CurrentPacketLocation.Val;
00443 
00444     // Obtain the MAC header from the Ethernet buffer
00445     MACGetArray((BYTE*)&header, sizeof(header));
00446 
00447     // The EtherType field, like most items transmitted on the Ethernet medium
00448     // are in big endian.
00449     header.Type.Val = swaps(header.Type.Val);
00450 
00451     // Do a sanity check.  There might be a bug in code someplace if this 
00452     // Reset() ever happens.  Check for potential errors in array/pointer writing code.
00453     if(header.NextPacketPointer > RXSTOP || ((BYTE_VAL*)(&header.NextPacketPointer))->bits.b0 ||
00454        header.StatusVector.bits.Zero ||
00455        header.StatusVector.bits.CRCError ||
00456        header.StatusVector.bits.ByteCount > 1518u ||
00457        !header.StatusVector.bits.ReceiveOk)
00458     {
00459         Reset();
00460     }
00461 
00462     // Save the location where the hardware will write the next packet to
00463     NextPacketLocation.Val = header.NextPacketPointer;
00464 
00465     // Return the Ethernet frame's Source MAC address field to the caller
00466     // This parameter is useful for replying to requests without requiring an 
00467     // ARP cycle.
00468     memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, sizeof(*remote));
00469 
00470     // Return a simplified version of the EtherType field to the caller
00471     *type = MAC_UNKNOWN;
00472     if( (header.Type.v[1] == 0x08u) && 
00473         ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
00474     {
00475         *type = header.Type.v[0];
00476     }
00477 
00478     // Mark this packet as discardable
00479     WasDiscarded = FALSE;   
00480     return TRUE;
00481 }
00482 
00483 
00484 /******************************************************************************
00485  * Function:        void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
00486  *
00487  * PreCondition:    MACIsTxReady() must return TRUE.
00488  *
00489  * Input:           *remote: Pointer to memory which contains the destination
00490  *                           MAC address (6 bytes)
00491  *                  type: The constant ETHER_ARP or ETHER_IP, defining which 
00492  *                        value to write into the Ethernet header's type field.
00493  *                  dataLen: Length of the Ethernet data payload
00494  *
00495  * Output:          None
00496  *
00497  * Side Effects:    None
00498  *
00499  * Overview:        None
00500  *
00501  * Note:            Because of the dataLen parameter, it is probably 
00502  *                  advantagous to call this function immediately before 
00503  *                  transmitting a packet rather than initially when the 
00504  *                  packet is first created.  The order in which the packet
00505  *                  is constructed (header first or data first) is not 
00506  *                  important.
00507  *****************************************************************************/
00508 void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
00509 {
00510     // Set the write pointer to the beginning of the transmit buffer
00511     EWRPT = TXSTART + 1;
00512 
00513     // Calculate where to put the TXND pointer
00514     dataLen += (WORD)sizeof(ETHER_HEADER) + TXSTART;
00515 
00516     // Write the TXND pointer into the registers, given the dataLen given
00517     ETXND = dataLen;
00518 
00519     // Set the per-packet control byte and write the Ethernet destination 
00520     // address
00521     MACPutArray((BYTE*)remote, sizeof(*remote));
00522 
00523     // MODIFIX: Write our MAC address from flash in the Ethernet source field
00524     MACPutROMArray( ( ROM BYTE * ) pu8MAC, sizeof( MAC_ADDR ) );
00525 
00526     // Write the appropriate Ethernet Type WORD for the protocol being used
00527     MACPut(0x08);
00528     MACPut((type == MAC_IP) ? ETHER_IP : ETHER_ARP);
00529 }
00530 
00531 /******************************************************************************
00532  * Function:        void MACFlush(void)
00533  *
00534  * PreCondition:    A packet has been created by calling MACPut() and 
00535  *                  MACPutHeader().
00536  *
00537  * Input:           None
00538  *
00539  * Output:          None
00540  *
00541  * Side Effects:    None
00542  *
00543  * Overview:        MACFlush causes the current TX packet to be sent out on 
00544  *                  the Ethernet medium.  The hardware MAC will take control
00545  *                  and handle CRC generation, collision retransmission and 
00546  *                  other details.
00547  *
00548  * Note:            After transmission completes (MACIsTxReady() returns TRUE), 
00549  *                  the packet can be modified and transmitted again by calling 
00550  *                  MACFlush() again.  Until MACPutHeader() or MACPut() is 
00551  *                  called (in the TX data area), the data in the TX buffer 
00552  *                  will not be corrupted.
00553  *****************************************************************************/
00554 void MACFlush(void)
00555 {
00556     // Reset the Ethernet TX logic.  This is a (suspected) errata workaround to 
00557     // prevent the TXRTS bit from getting stuck set indefinitely, causing the 
00558     // stack to lock up under certain bad conditions.
00559     ECON1bits.TXRST = 1;
00560     ECON1bits.TXRST = 0;    
00561 
00562     // Wait at least 1.6us after TX Reset before setting TXRTS.
00563     // If you don't wait long enough, the TX logic won't be finished resetting.
00564     {volatile BYTE i = 8; while(i--);}  
00565     EIRbits.TXERIF = 0;
00566 
00567     // Start the transmission
00568     // After transmission completes (MACIsTxReady() returns TRUE), the packet 
00569     // can be modified and transmitted again by calling MACFlush() again.
00570     // Until MACPutHeader() is called, the data in the TX buffer will not be 
00571     // corrupted.
00572     ECON1bits.TXRTS = 1;
00573     wTXWatchdog = TickGet();
00574 }
00575 
00576 
00577 /******************************************************************************
00578  * Function:        void MACSetReadPtrInRx(WORD offset)
00579  *
00580  * PreCondition:    A packet has been obtained by calling MACGetHeader() and 
00581  *                  getting a TRUE result.
00582  *
00583  * Input:           offset: WORD specifying how many bytes beyond the Ethernet 
00584  *                          header's type field to relocate the SPI read 
00585  *                          pointer.
00586  *
00587  * Output:          None
00588  *
00589  * Side Effects:    None
00590  *
00591  * Overview:        SPI read pointer are updated.  All calls to 
00592  *                  MACGet() and MACGetArray() will use these new values.
00593  *
00594  * Note:            RXSTOP must be statically defined as being > RXSTART for 
00595  *                  this function to work correctly.  In other words, do not 
00596  *                  define an RX buffer which spans the 0x1FFF->0x0000 memory
00597  *                  boundary.
00598  *****************************************************************************/
00599 void MACSetReadPtrInRx(WORD offset)
00600 {
00601     WORD_VAL ReadPT;
00602 
00603     // Determine the address of the beginning of the entire packet
00604     // and adjust the address to the desired location
00605     ReadPT.Val = CurrentPacketLocation.Val + sizeof(ENC_PREAMBLE) + offset;
00606     
00607     // Since the receive buffer is circular, adjust if a wraparound is needed
00608     if(ReadPT.Val > RXSTOP)
00609         ReadPT.Val -= RXSIZE;
00610     
00611     // Set the read pointer to the new calculated value
00612     ERDPTL = ReadPT.v[0];
00613     ERDPTH = ReadPT.v[1];
00614 }
00615 
00616 WORD_VAL u16MACGetCurrentReadPtrPos(void)
00617 {
00618     WORD_VAL ReadPT;
00619     ReadPT.v[0] = ERDPTL;
00620     ReadPT.v[1] = ERDPTH;
00621     return ReadPT;
00622 }
00623 
00624 void MACSetCurrentReadPtrPos(WORD_VAL u16Pos)
00625 {
00626     ERDPTL = u16Pos.v[0];
00627     ERDPTH = u16Pos.v[1];
00628 }
00629 
00630 /******************************************************************************
00631  * Function:        WORD MACSetWritePtr(WORD Address)
00632  *
00633  * PreCondition:    None
00634  *
00635  * Input:           Address: Address to seek to
00636  *
00637  * Output:          WORD: Old EWRPT location
00638  *
00639  * Side Effects:    None
00640  *
00641  * Overview:        SPI write pointer is updated.  All calls to 
00642  *                  MACPut() and MACPutArray() will use this new value.
00643  *
00644  * Note:            None
00645  *****************************************************************************/
00646 WORD MACSetWritePtr(WORD address)
00647 {
00648     WORD oldVal;
00649 
00650     oldVal = EWRPT;
00651     EWRPT = address;
00652     return oldVal;
00653 }
00654 
00655 /******************************************************************************
00656  * Function:        WORD MACSetReadPtr(WORD Address)
00657  *
00658  * PreCondition:    None
00659  *
00660  * Input:           Address: Address to seek to
00661  *
00662  * Output:          WORD: Old ERDPT value
00663  *
00664  * Side Effects:    None
00665  *
00666  * Overview:        SPI write pointer is updated.  All calls to 
00667  *                  MACPut() and MACPutArray() will use this new value.
00668  *
00669  * Note:            None
00670  *****************************************************************************/
00671 WORD MACSetReadPtr(WORD address)
00672 {
00673     WORD oldVal;
00674 
00675     oldVal = ERDPT;
00676     ERDPT = address;
00677     return oldVal;
00678 }
00679 
00680 
00681 /******************************************************************************
00682  * Function:        WORD MACCalcRxChecksum(WORD offset, WORD len)
00683  *
00684  * PreCondition:    None
00685  *
00686  * Input:           offset  - Number of bytes beyond the beginning of the 
00687  *                          Ethernet data (first byte after the type field) 
00688  *                          where the checksum should begin
00689  *                  len     - Total number of bytes to include in the checksum
00690  *
00691  * Output:          16-bit checksum as defined by RFC 793.
00692  *
00693  * Side Effects:    None
00694  *
00695  * Overview:        This function performs a checksum calculation in the MAC
00696  *                  buffer itself
00697  *
00698  * Note:            None
00699  *****************************************************************************/
00700 WORD MACCalcRxChecksum(WORD offset, WORD len)
00701 {
00702     WORD temp;
00703     WORD RDSave;
00704 
00705     // Add the offset requested by firmware plus the Ethernet header
00706     temp = CurrentPacketLocation.Val + sizeof(ENC_PREAMBLE) + offset;
00707     if(temp > RXSTOP)       // Adjust value if a wrap is needed
00708     {
00709         temp -= RXSIZE;
00710     }
00711 
00712     RDSave = ERDPT;
00713     ERDPT = temp;
00714     temp = CalcIPBufferChecksum(len);
00715     ERDPT = RDSave;
00716 
00717     return temp;
00718 }
00719 
00720 
00721 /******************************************************************************
00722  * Function:        WORD CalcIPBufferChecksum(WORD len)
00723  *
00724  * PreCondition:    Read buffer pointer set to starting of checksum data
00725  *
00726  * Input:           len: Total number of bytes to calculate the checksum over. 
00727  *                       The first byte included in the checksum is the byte 
00728  *                       pointed to by ERDPT, which is updated by calls to 
00729  *                       MACGet(), MACSetRxBuffer(), MACSetTxBuffer(), etc.
00730  *
00731  * Output:          16-bit checksum as defined by RFC 793
00732  *
00733  * Side Effects:    None
00734  *
00735  * Overview:        This function performs a checksum calculation in the MAC
00736  *                  buffer itself.  The MAC has a hardware DMA module 
00737  *                  which can calculate the checksum faster than software, so 
00738  *                  this function replaces the CaclIPBufferChecksum() function 
00739  *                  defined in the helpers.c file.  Through the use of 
00740  *                  preprocessor defines, this replacement is automatic.
00741  *
00742  * Note:            This function works either in the RX buffer area or the TX
00743  *                  buffer area.  No validation is done on the len parameter.
00744  *****************************************************************************/
00745 /*
00746 WORD CalcIPBufferChecksum(WORD len)
00747 {
00748     WORD_VAL temp;
00749 
00750     // Take care of special cases which the DMA cannot be used for
00751     if(len == 0u)
00752     {
00753         return 0xFFFF;
00754     }
00755     else if(len == 1u)
00756     {
00757         return ~((WORD)MACGet());
00758     }
00759         
00760 
00761     // Set the DMA starting address to the RAM read pointer value
00762     temp.Val = ERDPT;
00763     EDMAST = temp.Val;
00764     
00765     // See if we are calculating a checksum within the RX buffer (where 
00766     // wrapping rules apply) or TX/unused area (where wrapping rules are 
00767     // not applied)
00768 #if RXSTART == 0
00769     if(temp.Val <= RXSTOP)
00770 #else
00771     if(temp.Val >= RXSTART && temp.Val <= RXSTOP)
00772 #endif
00773     {
00774         // Calculate the DMA ending address given the starting address and len 
00775         // parameter.  The DMA will follow the receive buffer wrapping boundary.
00776         temp.Val += len-1;
00777         if(temp.Val > RXSTOP)
00778         {
00779             temp.Val -= RXSIZE;
00780         }
00781     }
00782     else
00783     {
00784         temp.Val += len-1;
00785     }   
00786 
00787     // Write the DMA end address
00788     EDMAND = temp.Val;
00789     
00790     // Begin the DMA checksum calculation and wait until it is finished
00791     ECON1bits.CSUMEN = 1;
00792     ECON1bits.DMAST = 1;
00793     while(ECON1bits.DMAST);
00794 
00795     // Return the resulting good stuff
00796     return (((WORD)EDMACSL)<<8) | EDMACSH;
00797 }
00798 */
00799 
00800 /******************************************************************************
00801  * Function:        WORD CalcIPBufferChecksum(WORD len)
00802  *
00803  * PreCondition:    Read buffer pointer set to starting of checksum data
00804  *
00805  * Input:           len: Total number of bytes to calculate the checksum over. 
00806  *                       The first byte included in the checksum is the byte 
00807  *                       pointed to by ERDPT, which is updated by calls to 
00808  *                       MACSetReadPtr(), MACGet(), MACGetArray(), 
00809  *                       MACGetHeader(), etc.
00810  *
00811  * Output:          16-bit checksum as defined by RFC 793
00812  *
00813  * Side Effects:    None
00814  *
00815  * Overview:        This function performs a checksum calculation in the MAC
00816  *                  buffer itself
00817  *
00818  * Note:            This function works either in the RX buffer area or the TX
00819  *                  buffer area.  No validation is done on the len parameter.
00820  *****************************************************************************/
00821 WORD CalcIPBufferChecksum(WORD len)
00822 {
00823     WORD Start;
00824     DWORD_VAL Checksum = {0x00000000ul};
00825     WORD ChunkLen;
00826     BYTE DataBuffer[20];    // Must be an even size
00827     WORD *DataPtr;
00828 
00829     // Save the read pointer starting address
00830     Start = ERDPT;
00831 
00832     while(len)
00833     {
00834         // Obtain a chunk of data (less SPI overhead compared 
00835         // to requesting one byte at a time)
00836         ChunkLen = len > sizeof(DataBuffer) ? sizeof(DataBuffer) : len;
00837         MACGetArray(DataBuffer, ChunkLen);
00838 
00839         len -= ChunkLen;
00840 
00841         // Take care of a last odd numbered data byte
00842         if(((WORD_VAL*)&ChunkLen)->bits.b0)
00843         {
00844             DataBuffer[ChunkLen] = 0x00;
00845             ChunkLen++;
00846         }
00847 
00848         // Calculate the checksum over this chunk
00849         DataPtr = (WORD*)&DataBuffer[0];
00850         while(ChunkLen)
00851         {
00852             Checksum.Val += *DataPtr++;
00853             ChunkLen -= 2;
00854         }
00855     }
00856 
00857     // Restore old read pointer location
00858     ERDPT = Start;
00859     
00860     // Do an end-around carry (one's complement arrithmatic)
00861     Checksum.Val = (DWORD)Checksum.w[0] + (DWORD)Checksum.w[1];
00862 
00863     // Do another end-around carry in case if the prior add 
00864     // caused a carry out
00865     Checksum.w[0] += Checksum.w[1];
00866 
00867     // Return the resulting checksum
00868     return ~Checksum.w[0];
00869 }
00870 
00871 /******************************************************************************
00872  * Function:        void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
00873  *
00874  * PreCondition:    None
00875  *
00876  * Input:           destAddr:   Destination address in the Ethernet memory to 
00877  *                              copy to.  If the MSb is set, the current EWRPT 
00878  *                              value will be used instead.
00879  *                  sourceAddr: Source address to read from.  If the MSb is 
00880  *                              set, the current ERDPT value will be used 
00881  *                              instead.
00882  *                  len:        Number of bytes to copy
00883  *
00884  * Output:          None
00885  *
00886  * Side Effects:    None
00887  *
00888  * Overview:        Bytes are asynchrnously transfered within the buffer.  Call 
00889  *                  MACIsMemCopyDone() to see when the transfer is complete.  
00890  *
00891  * Note:            If a prior transfer is already in progress prior to 
00892  *                  calling this function, this function will block until it 
00893  *                  can start this transfer.
00894  *****************************************************************************/
00895 void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
00896 {
00897     WORD_VAL ReadSave, WriteSave;
00898     BOOL UpdateWritePointer = FALSE;
00899     BOOL UpdateReadPointer = FALSE;
00900 
00901     if(((WORD_VAL*)&destAddr)->bits.b15)
00902     {
00903         UpdateWritePointer = TRUE;
00904         destAddr = EWRPT;
00905     }
00906     if(((WORD_VAL*)&sourceAddr)->bits.b15)
00907     {
00908         UpdateReadPointer = TRUE;
00909         sourceAddr = ERDPT;
00910     }
00911 
00912     // Handle special conditions where len == 0 or len == 1
00913     // The DMA module is not capable of handling those corner cases
00914     if(len <= 1u)
00915     {
00916         ReadSave.Val = ERDPT;
00917         WriteSave.Val = EWRPT;
00918         ERDPT = sourceAddr;
00919         EWRPT = destAddr;
00920         while(len--)
00921             MACPut(MACGet());
00922         if(!UpdateReadPointer)
00923         {
00924             ERDPT = ReadSave.Val;
00925         }
00926         if(!UpdateWritePointer)
00927         {
00928             EWRPT = WriteSave.Val;
00929         }
00930     }
00931     else
00932     {
00933         if(UpdateWritePointer)
00934         {
00935             WriteSave.Val = destAddr + len;
00936             EWRPT = WriteSave.Val;
00937         }
00938         len += sourceAddr - 1;
00939         while(ECON1bits.DMAST);
00940         EDMAST = sourceAddr;
00941         EDMADST = destAddr;
00942         if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
00943             len -= RXSIZE;
00944         EDMAND = len;
00945         ECON1bits.CSUMEN = 0;
00946         ECON1bits.DMAST = 1;
00947         while(ECON1bits.DMAST);         // DMA errata workaround: Must not access EDATA while DMA active
00948 
00949         if(UpdateReadPointer)
00950         {
00951             len++;
00952             if((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
00953                 len -= RXSIZE;
00954             ERDPT = len;
00955         }
00956     }
00957 }
00958 
00959 /*
00960 void MACMemCopyAsync(WORD destAddr, WORD sourceAddr, WORD len)
00961 {
00962     WORD_VAL ReadSave, WriteSave;
00963     BOOL UpdateWritePointer = FALSE;
00964     BOOL UpdateReadPointer = FALSE;
00965 
00966     if(((WORD_VAL*)&destAddr)->bits.b15)
00967     {
00968         UpdateWritePointer = TRUE;
00969         destAddr = EWRPT;
00970     }
00971     if(((WORD_VAL*)&sourceAddr)->bits.b15)
00972     {
00973         UpdateReadPointer = TRUE;
00974         sourceAddr = ERDPT;
00975     }
00976 
00977     ReadSave.Val = ERDPT;
00978     WriteSave.Val = EWRPT;
00979     ERDPT = sourceAddr;
00980     EWRPT = destAddr;
00981     while(len--)
00982     {
00983         MACPut(MACGet());
00984     }
00985 
00986     if(!UpdateReadPointer)
00987     {
00988         ERDPT = ReadSave.Val;
00989     }
00990     if(!UpdateWritePointer)
00991     {
00992         EWRPT = WriteSave.Val;
00993     }
00994 }
00995 */
00996 
00997 BOOL MACIsMemCopyDone(void)
00998 {
00999     return !ECON1bits.DMAST;
01000 }
01001 
01002 /******************************************************************************
01003  * Function:        BYTE MACGet()
01004  *
01005  * PreCondition:    ERDPT must point to the place to read from.
01006  *
01007  * Input:           None
01008  *
01009  * Output:          Byte read from the Ethernet's buffer RAM
01010  *
01011  * Side Effects:    None
01012  *
01013  * Overview:        MACGet returns the byte pointed to by ERDPT and 
01014  *                  increments ERDPT so MACGet() can be called again.  The 
01015  *                  increment will follow the receive buffer wrapping boundary.
01016  *
01017  * Note:            For better performance, implement this function as a macro:
01018  *                  #define MACGet()    (EDATA)
01019  *****************************************************************************/
01020 BYTE MACGet()
01021 {
01022     return EDATA;
01023 }//end MACGet
01024 
01025 
01026 /******************************************************************************
01027  * Function:        WORD MACGetArray(BYTE *val, WORD len)
01028  *
01029  * PreCondition:    ERDPT must point to the place to read from.
01030  *
01031  * Input:           *val: Pointer to storage location
01032  *                  len:  Number of bytes to read from the data buffer.
01033  *
01034  * Output:          Byte(s) of data read from the data buffer.
01035  *
01036  * Side Effects:    None
01037  *
01038  * Overview:        Reads several sequential bytes from the data buffer 
01039  *                  and places them into local memory.  ERDPT is incremented 
01040  *                  after each byte, following the same rules as MACGet().
01041  *
01042  * Note:            None
01043  *****************************************************************************/
01044 WORD MACGetArray(BYTE *val, WORD len)
01045 {
01046     WORD w;
01047     volatile BYTE i;
01048     
01049     w = len;
01050     if(val)
01051     {
01052         while(w--)
01053         {
01054             *val++ = EDATA;
01055         }
01056     }
01057     else
01058     {
01059         while(w--)
01060         {
01061             i = EDATA;
01062         }
01063     }
01064 
01065     return len;
01066 }//end MACGetArray
01067 
01068 
01069 /******************************************************************************
01070  * Function:        void MACPut(BYTE val)
01071  *
01072  * PreCondition:    EWRPT must point to the location to begin writing.
01073  *
01074  * Input:           Byte to write into the Ethernet buffer memory
01075  *
01076  * Output:          None
01077  *
01078  * Side Effects:    None
01079  *
01080  * Overview:        Writes to the EDATA register, which will indirectly 
01081 *                   increment EWRPTH:EWRPTL.
01082  *
01083  * Note:            None
01084  *****************************************************************************/
01085 void MACPut(BYTE val)
01086 {
01087     // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to 
01088     // write to EDATA or else the read pointer (ERDPT) will inadvertently 
01089     // increment.
01090     PRODL = val;
01091     #if defined(HI_TECH_C)
01092         asm("movff  _PRODL, _EDATA");
01093     #else
01094         _asm movff  PRODL, EDATA _endasm
01095     #endif
01096 }//end MACPut
01097 
01098 
01099 /******************************************************************************
01100  * Function:        void MACPutArray(BYTE *val, WORD len)
01101  *
01102  * PreCondition:    EWRPT must point to the location to begin writing.
01103  *
01104  * Input:           *val: Pointer to source of bytes to copy.
01105  *                  len:  Number of bytes to write to the data buffer.
01106  *
01107  * Output:          None
01108  *
01109  * Side Effects:    None
01110  *
01111  * Overview:        MACPutArray writes several sequential bytes to the 
01112  *                  Ethernet buffer RAM.  It performs faster than multiple MACPut()
01113  *                  calls.  EWRPT is incremented by len.
01114  *
01115  * Note:            None
01116  *****************************************************************************/
01117 void MACPutArray(BYTE *val, WORD len)
01118 {
01119     while(len--)
01120     {
01121         // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to 
01122         // write to EDATA or else the read pointer (ERDPT) will inadvertently 
01123         // increment.
01124         PRODL = *val++;
01125         #if defined(HI_TECH_C)
01126             asm("movff  _PRODL, _EDATA");
01127         #else
01128             _asm movff  PRODL, EDATA _endasm
01129         #endif
01130     }
01131 }//end MACPutArray
01132 
01133 void MACPutROMArray(ROM BYTE *val, WORD len)
01134 {
01135     while(len--)
01136     {
01137         // Note:  Due to a PIC18F97J60 bug, you must use the MOVFF instruction to 
01138         // write to EDATA or else the read pointer (ERDPT) will inadvertently 
01139         // increment.
01140         PRODL = *val++;
01141         #if defined(HI_TECH_C)
01142             asm("movff  _PRODL, _EDATA");
01143         #else
01144             _asm movff  PRODL, EDATA _endasm
01145         #endif
01146     }
01147 }//end MACPutROMArray
01148 
01149 
01150 /******************************************************************************
01151  * Function:        ReadPHYReg
01152  *
01153  * PreCondition:    Ethernet module must be enabled (ECON1.ETHEN = 1).
01154  *
01155  * Input:           Address of the PHY register to read from.
01156  *
01157  * Output:          16 bits of data read from the PHY register.
01158  *
01159  * Side Effects:    None
01160  *
01161  * Overview:        ReadPHYReg performs an MII read operation.  While in 
01162  *                  progress, it simply polls the MII BUSY bit wasting time 
01163  *                  (10.24us).
01164  *
01165  * Note:            None
01166  *****************************************************************************/
01167 PHYREG ReadPHYReg(BYTE Register)
01168 {
01169     PHYREG Result;
01170 
01171     // Set the right address and start the register read operation
01172     MIREGADR = Register; Nop();
01173     MICMD = MICMD_MIIRD; Nop();
01174 
01175     // Loop to wait until the PHY register has been read through the MII
01176     // This requires 10.24us
01177     while(MISTATbits.BUSY);
01178 
01179     // Stop reading
01180     MICMD = 0x00; Nop();
01181     
01182     // Obtain results and return
01183     Result.VAL.v[0] = MIRDL;
01184     Nop();
01185     Result.VAL.v[1] = MIRDH;
01186 
01187     return Result;
01188 }//end ReadPHYReg
01189 
01190 
01191 /******************************************************************************
01192  * Function:        WritePHYReg
01193  *
01194  * PreCondition:    Ethernet module must be enabled (ECON1.ETHEN = 1).
01195  *
01196  * Input:           Address of the PHY register to write to.
01197  *                  16 bits of data to write to PHY register.
01198  *
01199  * Output:          None
01200  *
01201  * Side Effects:    None
01202  *
01203  * Overview:        WritePHYReg performs an MII write operation.  While in 
01204  *                  progress, it simply polls the MII BUSY bit wasting time 
01205  *                  (10.24us).
01206  *
01207  * Note:            None
01208  *****************************************************************************/
01209 void WritePHYReg(BYTE Register, WORD Data)
01210 {
01211     BYTE GIESave;
01212 
01213     // Write the register address
01214     MIREGADR = Register;
01215 
01216     // Write the data through the MIIM interface
01217     // Order is important: write low byte first, high byte last
01218     //
01219     // Due to a silicon problem, you cannot access any register with LSb address 
01220     // bits of 0x16 between your write to MIWRL and MIWRH or else the value in 
01221     // MIWRL will be corrupted.  This inline assembly prevents this by copying 
01222     // the value to PRODH:PRODL first, which is at fixed locations of 
01223     // 0xFF4:0xFF3.  These addresses have LSb address bits of 0x14 and 0x13.
01224     // Interrupts must be disabled to prevent arbitrary ISR code from accessing
01225     // memory with LSb bits of 0x16 and corrupting the MIWRL value.
01226     PRODL = ((WORD_VAL*)&Data)->v[0];
01227     PRODH = ((WORD_VAL*)&Data)->v[1];
01228     GIESave = INTCON & 0xC0;        // Save GIEH and GIEL bits
01229     INTCON &= 0x3F;                 // Clear INTCONbits.GIEH and INTCONbits.GIEL
01230     #if defined(HI_TECH_C)
01231         asm("movff  _PRODL, _MIWRL");
01232         asm("nop");
01233         asm("movff  _PRODH, _MIWRH");
01234     #else
01235         _asm
01236         movff   PRODL, MIWRL
01237         nop
01238         movff   PRODH, MIWRH
01239         _endasm
01240     #endif
01241     INTCON |= GIESave;              // Restore GIEH and GIEL value
01242 
01243     // Wait until the PHY register has been written
01244     // This operation requires 10.24us
01245     while(MISTATbits.BUSY);
01246 }//end WritePHYReg
01247 
01248 
01249 /******************************************************************************
01250  * Function:        void MACPowerDown(void)
01251  *
01252  * PreCondition:    None
01253  *
01254  * Input:           None
01255  *
01256  * Output:          None
01257  *
01258  * Side Effects:    None
01259  *
01260  * Overview:        MACPowerDown disables the Ethernet module.
01261  *                  All MAC and PHY registers should not be accessed.
01262  *
01263  * Note:            Normally, this function would be called before putting the 
01264  *                  PIC to sleep.  If a packet is being transmitted while this 
01265  *                  function is called, this function will block until it is 
01266  *                  it complete. If anything is being received, it will be 
01267  *                  completed.
01268  *                  
01269  *                  The Ethernet module will continue to draw significant 
01270  *                  power in sleep mode if this function is not called first.
01271  *****************************************************************************/
01272 void MACPowerDown(void)
01273 {
01274     // Disable packet reception
01275     ECON1bits.RXEN = 0;
01276 
01277     // Make sure any last packet which was in-progress when RXEN was cleared 
01278     // is completed
01279     while(ESTATbits.RXBUSY);
01280 
01281     // If a packet is being transmitted, wait for it to finish
01282     while(ECON1bits.TXRTS);
01283     
01284     // Disable the Ethernet module
01285     ECON2bits.ETHEN = 0;
01286 
01287     // Switch off LEDs.
01288     LATAbits.LATA0 = 0;
01289     LATAbits.LATA1 = 0;
01290 
01291 }//end MACPowerDown
01292 
01293 /******************************************************************************
01294  * Function:        void MACPowerUp(void)
01295  *
01296  * PreCondition:    None
01297  *
01298  * Input:           None
01299  *
01300  * Output:          None
01301  *
01302  * Side Effects:    None
01303  *
01304  * Overview:        MACPowerUp returns the Ethernet module back to normal operation
01305  *                  after a previous call to MACPowerDown().  Calling this 
01306  *                  function when already powered up will have no effect.
01307  *
01308  * Note:            If a link partner is present, it will take 10s of 
01309  *                  milliseconds before a new link will be established after
01310  *                  waking up.  While not linked, packets which are 
01311  *                  transmitted will most likely be lost.  MACIsLinked() can 
01312  *                  be called to determine if a link is established.
01313  *****************************************************************************/
01314 void MACPowerUp(void)
01315 {   
01316     // Power up the Ethernet module
01317     ECON2bits.ETHEN = 1;
01318 
01319     // Wait for PHY to become ready
01320     while(!ESTATbits.PHYRDY)
01321 
01322     // Enable packet reception
01323     ECON1bits.RXEN = 1;
01324 }//end MACPowerUp
01325 
01326 
01327 
01328 /******************************************************************************
01329  * Function:        void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
01330  *
01331  * PreCondition:    SPI bus must be initialized (done in MACInit()).
01332  *
01333  * Input:           DestMACAddr: 6 byte group destination MAC address to allow 
01334  *                               through the Hash Table Filter
01335  *
01336  * Output:          Sets the appropriate bit in the EHT* registers to allow 
01337  *                  packets sent to DestMACAddr to be received if the Hash 
01338  *                  Table receive filter is enabled
01339  *
01340  * Side Effects:    None
01341  *
01342  * Overview:        Calculates a CRC-32 using polynomial 0x4C11DB7 and then, 
01343  *                  using bits 28:23 of the CRC, sets the appropriate bit in 
01344  *                  the EHT* registers
01345  *
01346  * Note:            This code is commented out to save code space on systems 
01347  *                  that do not need this function.  Change the "#if 0" line 
01348  *                  to "#if 1" to uncomment it.
01349  *****************************************************************************/
01350 #if 0
01351 void SetRXHashTableEntry(MAC_ADDR DestMACAddr)
01352 {
01353     DWORD_VAL CRC = {0xFFFFFFFF};
01354     BYTE *HTRegister;
01355     BYTE i, j;
01356 
01357     // Calculate a CRC-32 over the 6 byte MAC address 
01358     // using polynomial 0x4C11DB7
01359     for(i = 0; i < sizeof(MAC_ADDR); i++)
01360     {
01361         BYTE  crcnext;
01362     
01363         // shift in 8 bits
01364         for(j = 0; j < 8; j++)
01365         {
01366             crcnext = 0;
01367             if(((BYTE_VAL*)&(CRC.v[3]))->bits.b7)
01368                 crcnext = 1;
01369             crcnext ^= (((BYTE_VAL*)&DestMACAddr.v[i])->bits.b0);
01370     
01371             CRC.Val <<= 1;
01372             if(crcnext)
01373                 CRC.Val ^= 0x4C11DB7;
01374             // next bit
01375             DestMACAddr.v[i] >>= 1;
01376         }
01377     }
01378     
01379     // CRC-32 calculated, now extract bits 28:23
01380     // Bits 25:23 define where within the Hash Table byte the bit needs to be set
01381     // Bits 28:26 define which of the 8 Hash Table bytes that bits 25:23 apply to
01382     i = CRC.v[3] & 0x1F;
01383     HTRegister = (i >> 2) + &EHT0;
01384     i = (i << 1) & 0x06;
01385     ((BYTE_VAL*)&i)->bits.b0 = ((BYTE_VAL*)&CRC.v[2])->bits.b7;
01386     
01387     // Set the proper bit in the Hash Table
01388     *HTRegister |= 1<<i;
01389 }
01390 #endif

Generated on Sun Nov 27 20:02:38 2011 for eWicht by  doxygen 1.5.5