示例#1
0
/*********************************************************************
 * Function:        LONG ICMPGetReply(void)
 *
 * PreCondition:    ICMPBeginUsage() returned TRUE and ICMPSendPing() 
 *					was called
 *
 * Input:           None
 *
 * Output:          -2: No response received yet
 *					-1: Operation timed out (longer than ICMP_TIMEOUT) 
 *						has elapsed.
 *					>=0: Number of TICKs that elapsed between 
 *						 initial ICMP transmission and reception of 
 *						 a valid echo.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
LONG ICMPGetReply(void)
{
	switch(ICMPState)
	{
		case SM_ARP_RESOLVE:
			// See if the ARP reponse was successfully received
			if(ARPIsResolved(&ICMPRemote.IPAddr, &ICMPRemote.MACAddr))
			{
				// Position the write pointer for the next IPPutHeader operation
			    MACSetWritePtr(BASE_TX_ADDR + sizeof(ETHER_HEADER));
			
			    // Wait for TX hardware to become available (finish transmitting 
			    // any previous packet)
			    while(!IPIsTxReady());
			
				// Create IP header in TX memory
				IPPutHeader(&ICMPRemote, IP_PROT_ICMP, sizeof(ICMP_HEADER) + 2);
				MACPutArray((BYTE*)&ICMPHeader, sizeof(ICMPHeader));
				MACPut(0x00);	// Send two dummy bytes as ping payload 
				MACPut(0x00);	// (needed for compatibility with some buggy NAT routers)
				MACFlush();

				// MAC Address resolved and echo sent, advance state
				ICMPState = SM_GET_ECHO;
				return -2;
			}

			// See if the ARP/echo request timed out
			if(TickGet() - ICMPTimer > ICMP_TIMEOUT)
			{
				ICMPState = SM_IDLE;
				return -1;
			}

			// No ARP response back yet
			return -2;

		case SM_GET_ECHO:
			// See if the echo was successfully received
			if(ICMPFlags.bReplyValid)
			{
				return (LONG)ICMPTimer;
			}
		
			// See if the ARP/echo request timed out
			if(TickGet() - ICMPTimer > ICMP_TIMEOUT)
			{
				ICMPState = SM_IDLE;
				return -1;
			}
		
			// No echo response back yet
			return -2;
		
		// SM_IDLE or illegal/impossible state:
		default:
			return -1;
	}
}
示例#2
0
/*********************************************************************
 * Function:        BOOL UDPPut(BYTE v)
 *
 * PreCondition:    UDPIsPutReady() == TRUE with desired UDP socket
 *                  that is to be loaded.
 *
 * Input:           v       - Data byte to loaded into transmit buffer
 *
 * Output:          TRUE if transmit buffer is still ready to accept
 *                  more data bytes
 *
 *                  FALSE if transmit buffer can no longer accept
 *                  any more data byte.
 *
 * Side Effects:    None
 *
 * Overview:        Given data byte is put into UDP transmit buffer
 *                  and active UDP socket buffer length is incremented
 *                  by one.
 *                  If buffer has become full, FALSE is returned.
 *                  Or else TRUE is returned.
 *
 * Note:            This function loads data into an active UDP socket
 *                  as determined by previous call to UDPIsPutReady()
 ********************************************************************/
BOOL UDPPut(BYTE v)
{
    UDP_SOCKET_INFO *p;
    WORD temp;

    p = &UDPSocketInfo[activeUDPSocket];

    if ( p->TxCount == 0 )
    {
        /*
         * This is the very first byte that is loaded in UDP buffer.
         * Remember what transmit buffer we are loading, and
         * start loading this and next bytes in data area of UDP
         * packet.
         */
        p->TxBuffer = MACGetTxBuffer();

        IPSetTxBuffer(p->TxBuffer, sizeof(UDP_HEADER));

        p->TxOffset = 0;
    }

    /*
     * Load it.
     */
    MACPut(v);

    if ( p->TxOffset++ >= p->TxCount )
        p->TxCount++;

#if 0
    /*
     * Keep track of number of bytes loaded.
     * If total bytes fill up buffer, transmit it.
     */
    p->TxCount++;
#endif

#define SIZEOF_MAC_HEADER       (14)

    /*
     * Depending on what communication media is used, allowable UDP
     * data length will vary.
     */
#if !defined(STACK_USE_SLIP)
#define MAX_UDP_DATA  (MAC_TX_BUFFER_SIZE - SIZEOF_MAC_HEADER - sizeof(IP_HEADER) - sizeof(UDP_HEADER))
#else
#define MAX_UDP_DATA  (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) )
#endif

    temp = p->TxCount;
    if ( temp >= MAX_UDP_DATA )
    {
        UDPFlush();
    }
#undef MAX_UDP_DATA

    return TRUE;
}
示例#3
0
/******************************************************************************
 * Function:        void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len)
 *
 * PreCondition:    None
 *
 * Input:           destAddr:	Destination address in the Ethernet memory to
 *								copy to.  If (PTR_BASE)-1 is specified, the 
 *								current EWRPT value will be used instead.
 *					sourceAddr:	Source address to read from.  If (PTR_BASE)-1 is
 *                              specified, the current ERDPT value will be used
 *                              instead.
 *					len:		Number of bytes to copy
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Bytes are asynchrnously transfered within the buffer.  Call
 *					MACIsMemCopyDone() to see when the transfer is complete.
 *
 * Note:            If a prior transfer is already in progress prior to
 *					calling this function, this function will block until it
 *					can start this transfer.
 *****************************************************************************/
void MACMemCopyAsync(PTR_BASE destAddr, PTR_BASE sourceAddr, WORD len) {
    WORD_VAL ReadSave, WriteSave;
    BOOL UpdateWritePointer = FALSE;
    BOOL UpdateReadPointer = FALSE;

    if (destAddr == (PTR_BASE) - 1) {
        UpdateWritePointer = TRUE;
        destAddr = EWRPT;
    }
    if (sourceAddr == (PTR_BASE) - 1) {
        UpdateReadPointer = TRUE;
        sourceAddr = ERDPT;
    }

    // Handle special conditions where len == 0 or len == 1
    // The DMA module is not capable of handling those corner cases
    if (len <= 1u) {
        ReadSave.Val = ERDPT;
        WriteSave.Val = EWRPT;
        ERDPT = sourceAddr;
        EWRPT = destAddr;
        while (len--)
            MACPut(MACGet());
        if (!UpdateReadPointer) {
            ERDPT = ReadSave.Val;
        }
        if (!UpdateWritePointer) {
            EWRPT = WriteSave.Val;
        }
    } else {
        if (UpdateWritePointer) {
            WriteSave.Val = destAddr + len;
            EWRPT = WriteSave.Val;
        }
        len += sourceAddr - 1;
        while (ECON1bits.DMAST);
        EDMAST = sourceAddr;
        EDMADST = destAddr;
        if ((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
            len -= RXSIZE;
        EDMAND = len;
        ECON1bits.CSUMEN = 0;
        ECON1bits.DMAST = 1;
        while (ECON1bits.DMAST); // DMA requires that you must not access EDATA while DMA active

        if (UpdateReadPointer) {
            len++;
            if ((sourceAddr <= RXSTOP) && (len > RXSTOP)) //&& (sourceAddr >= RXSTART))
                len -= RXSIZE;
            ERDPT = len;
        }
    }
}
示例#4
0
/******************************************************************************
 * Function:        void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen)
 *
 * PreCondition:    MACIsTxReady() must return TRUE.
 *
 * Input:           *remote: Pointer to memory which contains the destination
 * 							 MAC address (6 bytes)
 *					type: The constant ETHER_ARP or ETHER_IP, defining which
 *						  value to write into the Ethernet header's type field.
 *					dataLen: Length of the Ethernet data payload
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            Because of the dataLen parameter, it is probably
 *					advantagous to call this function immediately before
 *					transmitting a packet rather than initially when the
 *					packet is first created.  The order in which the packet
 *					is constructed (header first or data first) is not
 *					important.
 *****************************************************************************/
void MACPutHeader(MAC_ADDR *remote, BYTE type, WORD dataLen) {
    // Set the write pointer to the beginning of the transmit buffer
    EWRPT = TXSTART + 1;

    // Calculate where to put the TXND pointer
    dataLen += (WORD)sizeof (ETHER_HEADER) + TXSTART;

    // Write the TXND pointer into the registers, given the dataLen given
    ETXND = dataLen;

    // Set the per-packet control byte and write the Ethernet destination
    // address
    MACPutArray((BYTE*) remote, sizeof (*remote));

    // Write our MAC address in the Ethernet source field
    MACPutArray((BYTE*) & AppConfig.MyMACAddr, sizeof (AppConfig.MyMACAddr));

    // Write the appropriate Ethernet Type WORD for the protocol being used
    MACPut(0x08);
    MACPut((type == MAC_IP) ? ETHER_IP : ETHER_ARP);
}
示例#5
0
/**
 * This function writes the MAC header (Ethernet header) part of a packet that
 * has to be transmitted to the current TX buffer (page in NIC RAM).
 * After this function, the data must still be written to the TX buffer.
 * After both header and data has been written, bits are set to instruct
 * NIC to transmit transmit buffer. This function does the following: <ul>
 *  <li> Reset the NIC Remote DMA write pointer to the first byte of the current TX Buffer </li>
 *  <li> Write the given header to the current TX Buffer </li>
 *  <li> Set the NIC Remote DMA byte count to the given len. This configures the
 *    Remote DMA to receive the given number of bytes. </li></ul>
 *
 * @param[out] remote   Pointer to a MAC_ADDR structure. This function will write the MAC address of the
 *                      node who sent this packet to this structure
 * @param type          Type of header. Can be ETHER_IP, ETHER_ARP or MAC_UNKNOWN
 * @param dataLen       Size of the Data of this Ethernet packet. A Ethernet packet consists of: <br>
 *                      - 6 Bytes = Desitination MAC address <br>
 *                      - 6 Bytes = Source MAC address <br>
 *                      - 2 Bytes = Type field, currently only IP or ARP <br>
 *                      - n Bytes = Data. Minimum length of 46 bytes <br><br>
 *                      The data will be written to the TX buffer following this command.
 *
 * @return              True if header was read, False if not
 */
void    MACPutHeader(MAC_ADDR *remote,
                     BYTE type,
                     WORD dataLen)
{
    WORD_VAL mytemp;
    BYTE etherType;

    NICPut(ISR, 0x0a);

    //Set the address of the current Remote DMA. This is the address that all future MACPut()
    //functions will write data to in the current TX Buffer. This address is set to the start
    //address of the current MAC TX Buffer. The current TX Buffer will thus point to the first
    //byte in the packet that will be transmitted = first byte of Ethernet header
    mytemp.v[1] = TxBuffers[MACCurrTxbuf].Index;
    mytemp.v[0] = 0;
    NICSetAddr(mytemp.Val);

    /////////////////////////////////////////////////
    //Write Ethernet header part (MAC header) = Dest MAC Adrr, Source MAC Adr, Type
    MACPutArray((BYTE*)remote, sizeof(*remote));

    MACPut(MY_MAC_BYTE1);
    MACPut(MY_MAC_BYTE2);
    MACPut(MY_MAC_BYTE3);
    MACPut(MY_MAC_BYTE4);
    MACPut(MY_MAC_BYTE5);
    MACPut(MY_MAC_BYTE6);

    if ( type == MAC_IP )
        etherType = ETHER_IP;
    else
        etherType = ETHER_ARP;

    MACPut(0x08);
    MACPut(etherType);

    dataLen += (WORD)sizeof(ETHER_HEADER);

    //If datalength smaller than minimum Ethernet packet (not including CRC), pad till minimum size
    if ( dataLen < MINFRAME )
       dataLen = MINFRAME;

    mytemp.Val = dataLen;

    NICPut(TBCR0, mytemp.v[0]);
    NICPut(TBCR1, mytemp.v[1]);
}
示例#6
0
文件: UDP.c 项目: KiwiJaune/RecMiwiPi
/*****************************************************************************
  Function:
	BOOL UDPPut(BYTE v)

  Summary:
	Writes a byte to the currently active socket.
	
  Description:
	This function writes a single byte to the currently active UDP socket, 
	while incrementing the buffer length.  UDPIsPutReady should be used 
	before calling this function to specify the currently active socket.

  Precondition:
	UDPIsPutReady() was previously called to specify the current socket.

  Parameters:
	v - The byte to be loaded into the transmit buffer.

  Return Values:
  	TRUE - The byte was successfully written to the socket.
  	FALSE - The transmit buffer is already full and so the write failed.
  ***************************************************************************/
BOOL UDPPut(BYTE v)
{
	// See if we are out of transmit space.
	if(wPutOffset >= (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)))
	{
		return FALSE;
	}

    // Load application data byte
    MACPut(v);
	wPutOffset++;
	if(wPutOffset > UDPTxCount)
		UDPTxCount = wPutOffset;

    return TRUE;
}
示例#7
0
/*****************************************************************************
  Function:
    bool UDPPut(uint8_t v)

  Summary:
    Writes a byte to the currently active socket.

  Description:
    This function writes a single byte to the currently active UDP socket,
    while incrementing the buffer length.  UDPIsPutReady should be used
    before calling this function to specify the currently active socket.

  Precondition:
    UDPIsPutReady() was previously called to specify the current socket.

  Parameters:
    v - The byte to be loaded into the transmit buffer.

  Return Values:
    true - The byte was successfully written to the socket.
    false - The transmit buffer is already full and so the write failed.
  ***************************************************************************/
bool UDPPut(uint8_t v)
{
    // See if we are out of transmit space.
    if(wPutOffset >= (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER)))
    {
        return false;
    }

    // Load application data byte
    MACPut(v);
    wPutOffset++;
    if(wPutOffset > UDPTxCount)
        UDPTxCount = wPutOffset;

    return true;
}
示例#8
0
/**
 * Given data byte is put into the UDP transmit buffer and active UDP socket buffer
 * length is incremented. The data is NOT sent yet, and the UDPFlush() function must
 * be called to send all data contained in the transmit buffer.
 *
 * If the transmit buffer filled up, the contents of the transmit buffer will be sent,
 * and this function will return FALSE. In this case, it is VERY IMPORTANT to call the
 * UDPIsPutReady() function again before calling the UDPPut() or UDPPutArray() functions!
 *
 * Note: This function loads data into an active UDP socket as determined by previous
 * call to UDPIsPutReady().
 *
 * @preCondition    UDPIsPutReady() == TRUE with desired UDP socket
 *                  that is to be loaded.
 *
 * @param v       - Data byte to loaded into transmit buffer
 *
 * @return          TRUE if transmit buffer is still ready to accept more data bytes <br>
 *                  FALSE if transmit buffer can no longer accept any more data byte.<br>
 *                  If FALSE is returned, then UDPIsPutReady() has to be called again before
 *                  calling the UDPPut() or UDPPutArray() functions!
 */
BOOL UDPPut(BYTE v)
{
    UDP_SOCKET_INFO *p;

    p = &UDPSocketInfo[activeUDPSocket];

    //This UDP Socket does not contain any unsent data, and currently does not own a TX Buffer!
    //Assign it the next available TX Buffer
    if ( p->TxCount == 0 )
    {
        // This is the very first byte that is loaded in UDP buffer.
        // Remember what transmit buffer we are loading, and
        // start loading this and next bytes in data area of UDP packet.
        p->TxBuffer = MACGetTxBuffer(TRUE);

        // Make sure that we received a TX buffer
        if(p->TxBuffer == INVALID_BUFFER)
            return FALSE;

        //This sets the current TX Buffer pointer to the given offset after the IP header.
        //We give the size of the UDP header here as a parameter. This causes the current
        //write pointer to be set to firt byte after the UDP header, which is the UDP data area.
        IPSetTxBuffer(p->TxBuffer, sizeof(UDP_HEADER));
	    udpChecksum = 0;
        //p->TxOffset = 0;  /* TxOffset is not required! */
    }

    //Load it.
    MACPut(v);
	if (p->TxCount & 1) {
		udpChecksum += v;
		} else
		{
		udpChecksum += ((WORD)v << 8);
		}
    //Keep track of number of bytes loaded.
    //If total bytes fill up buffer, transmit it.
    p->TxCount++;

    if ( p->TxCount >= UDPGetMaxDataLength() )
    {
        UDPFlush();
		udpChecksum = 0;
    }
    
    return TRUE;
}
示例#9
0
void    MACPutHeader(MAC_ADDR *remote,
                     int8 type,
                     int16 dataLen)
{
    WORD_VAL mytemp;
    int8 etherType;

    NICPut(ISR, 0x0a);

    mytemp.v[1] = TxBuffers[NICCurrentTxBuffer].Index;
    mytemp.v[0] = 0;

    NICSetAddr(mytemp.Val);

//    MACPutArray((int8*)remote, sizeof(*remote));
    MACPutArray(remote, sizeof(MAC_ADDR));

   debug(debug_putc,"\r\n\r\nMACPUTHEADER: DA:%X.%X.%X.%X.%X.%X T=%X L=%LX",
      remote->v[0],remote->v[1],remote->v[2],remote->v[3],remote->v[4],remote->v[5],type,datalen);

    MACPut(MY_MAC_BYTE1);
    MACPut(MY_MAC_BYTE2);
    MACPut(MY_MAC_BYTE3);
    MACPut(MY_MAC_BYTE4);
    MACPut(MY_MAC_BYTE5);
    MACPut(MY_MAC_BYTE6);

    if ( type == MAC_IP )
        etherType = ETHER_IP;
    else
        etherType = ETHER_ARP;

    MACPut(0x08);
    MACPut(etherType);

    dataLen += (int16)sizeof(ETHER_HEADER);
    if ( dataLen < MINFRAME ) // 64 )      // NKR 4/23/02
        dataLen = 64; // MINFRAME;
    mytemp.Val = dataLen;

    NICPut(TBCR0, mytemp.v[0]);
    NICPut(TBCR1, mytemp.v[1]);

}
示例#10
0
BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *localIP, WORD len)
{
    UDP_HEADER h;
    UDP_SOCKET s;
    UDP_PSEUDO_HEADER pseudoHeader;
    WORD_VAL   checksum;

    /*
     * Retrieve UDP header.
     */
    //MACGetArray((BYTE*)&h, sizeof(h));
    MACGetArray(&h, sizeof(UDP_HEADER));

    h.SourcePort        = swaps(h.SourcePort);
    h.DestinationPort   = swaps(h.DestinationPort);
    h.Length            = swaps(h.Length) - sizeof(UDP_HEADER);

      debug_udp("\r\nUDP PROCESS SP=%LX DP=%LX PAYLOAD=%LX ",
            h.SourcePort,
            h.DestinationPort,
            h.Length
         );

   // See if we need to validate the checksum field (0x0000 is disabled)
   if(h.Checksum)
   {
       h.Checksum          = swaps(h.Checksum);

       // Calculate IP pseudoheader checksum.
       pseudoHeader.SourceAddress      = remoteNode->IPAddr;
       pseudoHeader.DestAddress.v[0]   = localIP->v[0];
       pseudoHeader.DestAddress.v[1]   = localIP->v[1];
       pseudoHeader.DestAddress.v[2]   = localIP->v[2];
       pseudoHeader.DestAddress.v[3]   = localIP->v[3];
       pseudoHeader.Zero               = 0x0;
       pseudoHeader.Protocol           = IP_PROT_UDP;
       pseudoHeader.Length             = len;

       SwapPseudoHeader(pseudoHeader);

       checksum.Val = ~CalcIPChecksum(&pseudoHeader,
                                       sizeof(pseudoHeader));


       // Set UDP packet checksum = pseudo header checksum in MAC RAM.
       IPSetRxBuffer(6);
       MACPut(checksum.v[0]);
      // In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address.
       IPSetRxBuffer(7);
       MACPut(checksum.v[1]);
       IPSetRxBuffer(0);

       // Now calculate UDP packet checksum in NIC RAM - including
       // pesudo header.
       checksum.Val = CalcIPBufferChecksum(len);

       if ( checksum.Val != h.Checksum )
       {
           debug_udp("INVALID-CS ");
           MACDiscardRx();
           return TRUE;
       }
   }

    s = FindMatching_UDP_Socket(&h, remoteNode, localIP);
    if ( s == INVALID_UDP_SOCKET )
    {
        /*
         * If there is no matching socket, There is no one to handle
         * this data.  Discard it.
         */
        debug_udp("INVALID-SOCKET ");
        MACDiscardRx();
    }
    else {
        UDPSocketInfo[s].RxCount = h.Length;
        UDPSocketInfo[s].Flags.bFirstRead = TRUE;

    debug_udp("MATCH AS:%U ", s);
    /*debug_udp("MAC-%X:%X:%X:%X:%X:%X",
         remoteNode->MACAddr.v[0],
         remoteNode->MACAddr.v[1],
         remoteNode->MACAddr.v[2],
         remoteNode->MACAddr.v[3],
         remoteNode->MACAddr.v[4],
         remoteNode->MACAddr.v[5]
      );*/
    }

    return TRUE;
}
示例#11
0
/*********************************************************************
 * Function:        BOOL UDPPut(BYTE v)
 *
 * PreCondition:    UDPIsPutReady() == TRUE with desired UDP socket
 *                  that is to be loaded.
 *
 * Input:           v       - Data byte to loaded into transmit buffer
 *
 * Output:          TRUE if transmit buffer is still ready to accept
 *                  more data bytes
 *
 *                  FALSE if transmit buffer can no longer accept
 *                  any more data byte.
 *
 * Side Effects:    None
 *
 * Overview:        Given data byte is put into UDP transmit buffer
 *                  and active UDP socket buffer length is incremented
 *                  by one.
 *                  If buffer has become full, FALSE is returned.
 *                  Or else TRUE is returned.
 *
 * Note:            This function loads data into an active UDP socket
 *                  as determined by previous call to UDPIsPutReady()
 ********************************************************************/
BOOL UDPPut(BYTE v)
{
    UDP_SOCKET_INFO *p;
    WORD temp;
    WORD tempOffset;
    WORD tempCount;

    p = &UDPSocketInfo[activeUDPSocket];

    tempCount=p->TxCount;

    if ( tempCount == 0 )
    {
        // This is the very first byte that is loaded in UDP buffer.
        // Remember what transmit buffer we are loading, and
        // start loading this and next bytes in data area of UDP packet.
        p->TxBuffer = MACGetTxBuffer(TRUE);

      // Make sure that we received a TX buffer
      if(p->TxBuffer == INVALID_BUFFER)
         return FALSE;

        IPSetTxBuffer(p->TxBuffer, sizeof(UDP_HEADER));

        p->TxOffset = 0;
    }

    tempOffset=p->TxOffset;

   /*if (v>=0x20)
      debug_udp("-%c", v);
   else
      debug_udp("-0x%X", v);*/
      
    // Load it.
    MACPut(v);

    // Keep track of number of bytes loaded.
    // If total bytes fill up buffer, transmit it.
    if (tempOffset >= tempCount)
    {
      tempCount++;
    }
    tempOffset++;

    /* //broken in ccs?
    if ( p->TxOffset++ >= p->TxCount )
    {
        p->TxCount++;
        debug_udp("!");
    }
    */



#define SIZEOF_MAC_HEADER       (14)

    // Depending on what communication media is used, allowable UDP
    // data length will vary.
#if STACK_USE_SLIP
#define MAX_UDP_DATA  (MAC_TX_BUFFER_SIZE - SIZEOF_MAC_HEADER - sizeof(IP_HEADER) - sizeof(UDP_HEADER))
#else
#define MAX_UDP_DATA  (MAC_TX_BUFFER_SIZE - sizeof(IP_HEADER) - sizeof(UDP_HEADER) )
#endif

   p->TxOffset = tempOffset;

    //temp = p->TxCount;
    //if ( temp >= MAX_UDP_DATA )
    p->TxCount = tempCount;
    if (tempCount >= MAX_UDP_DATA)
    {
        UDPFlush();
    }
#undef MAX_UDP_DATA


    return TRUE;
}
示例#12
0
void    MACPutArray(int8 *val, int16 len)
{
    while( len-- )
        MACPut(*val++);
}
示例#13
0
/******************************************************************************
 * Function:        void MACInit(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        MACInit enables the Ethernet module, waits for the
 *                  to become ready, and programs all registers for future
 *                  TX/RX operations.
 *
 * Note:            This function blocks for at least 1ms, waiting for the
 *                  hardware to stabilize.
 *****************************************************************************/
void MACInit(void) {
    BYTE i;

    TRISA &= 0xFC; // Clear TRISA0 and TRISA1 to set LED0 and LED1 as outputs for Ethernet module status
    ECON2bits.ETHEN = 1; // Enable Ethernet!

    // If Ethernet TPIN+/- RX polarity swap hardware exists, start controlling
    // it and default it to the non-swapped state.
#if defined(ETH_RX_POLARITY_SWAP_TRIS)
    ETH_RX_POLARITY_SWAP_TRIS = 0;
    ETH_RX_POLARITY_SWAP_IO = 0;
#endif

    // Wait for PHYRDY to become set.
    while (!ESTATbits.PHYRDY);

    // Configure the receive buffer boundary pointers
    // and the buffer write protect pointer (receive buffer read pointer)
    flags.v = 0;
    flags.bits.bWasDiscarded = 1;
    NextPacketLocation.Val = RXSTART;
    ERXST = RXSTART;
    ERXRDPTL = LOW(RXSTOP); // Write low byte first
    ERXRDPTH = HIGH(RXSTOP); // Write high byte last
    ERXND = RXSTOP;
    ETXST = TXSTART;

    // Write a permanant per packet control byte of 0x00
    EWRPT = TXSTART;
    MACPut(0x00);

    // Configure Receive Filters
    // (No need to reconfigure - Unicast OR Broadcast with CRC checking is
    // acceptable)
    //ERXFCON = ERXFCON_CRCEN;     // Promiscious mode

    // Configure the MAC
    // Enable the receive portion of the MAC
    MACON1 = MACON1_TXPAUS | MACON1_RXPAUS | MACON1_MARXEN;
    Nop();

    // Pad packets to 60 bytes, add CRC, and check Type/Length field.
#if defined(FULL_DUPLEX)
    MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN | MACON3_FULDPX;
    Nop();
    MABBIPG = 0x15;
    Nop();
#else
    MACON3 = MACON3_PADCFG0 | MACON3_TXCRCEN | MACON3_FRMLNEN;
    Nop();
    MABBIPG = 0x12;
    Nop();
#endif

    // Allow infinite deferals if the medium is continuously busy
    // (do not time out a transmission if the half duplex medium is
    // completely saturated with other people's data)
    MACON4 = MACON4_DEFER;
    Nop();

    // Set non-back-to-back inter-packet gap to 9.6us.  The back-to-back
    // inter-packet gap (MABBIPG) is set by MACSetDuplex() which is called
    // later.
    MAIPGL = 0x12;
    Nop();
    MAIPGH = 0x0C;
    Nop();

    // Set the maximum packet size which the controller will accept
    MAMXFLL = LOW(6 + 6 + 2 + 1500 + 4);
    Nop();
    MAMXFLH = HIGH(6 + 6 + 2 + 1500 + 4);
    Nop();

    // Initialize physical MAC address registers
    MAADR1 = 0; //AppConfig.MyMACAddr.v[0];
    Nop();
    MAADR2 = 0; //AppConfig.MyMACAddr.v[1];
    Nop();
    MAADR3 = 0; //AppConfig.MyMACAddr.v[2];
    Nop();
    MAADR4 = 0; //AppConfig.MyMACAddr.v[3];
    Nop();
    MAADR5 = 0; //AppConfig.MyMACAddr.v[4];
    Nop();
    MAADR6 = 0; //AppConfig.MyMACAddr.v[5];
    Nop();

    // Disable half duplex loopback in PHY and set RXAPDIS bit as per errata
    WritePHYReg(PHCON2, PHCON2_HDLDIS | PHCON2_RXAPDIS);

    // Configure LEDA to display LINK status, LEDB to display TX/RX activity
    SetLEDConfig(0x3472);

    // Set the PHY into the proper duplex state
#if defined(FULL_DUPLEX)
    WritePHYReg(PHCON1, PHCON1_PDPXMD);
#else
    WritePHYReg(PHCON1, 0x0000);
#endif

    // Enable packet reception
    ECON1bits.RXEN = 1;
}//end MACInit
示例#14
0
/**
 * This function transmit all data from the active UDP socket.
 *
 * @preCondition    UDPPut() is already called and desired UDP socket
 *                  is set as an active socket by calling
 *                  UDPIsPutReady().
 *
 * @return          All and any data associated with active UDP socket
 *                  buffer is marked as ready for transmission.
 *
 */
void UDPFlush(void)
{
    UDP_HEADER      h;
    UDP_SOCKET_INFO *p;
    WORD csLength;
	DWORD_VAL csChecksum;
    // Wait for TX hardware to become available (finish transmitting 
    // any previous packet)
    while( !IPIsTxReady(TRUE) ) FAST_USER_PROCESS();

    p = &UDPSocketInfo[activeUDPSocket];

    h.SourcePort.Val        = swaps(p->localPort);
    h.DestinationPort.Val   = swaps(p->remotePort);
    h.Length.Val            = (WORD)((WORD)p->TxCount + (WORD)sizeof(UDP_HEADER));
    // Do not swap h.Length yet.  It is needed in IPPutHeader.
    h.Checksum.Val      = 0x00;

    //Makes the given TX Buffer active, and set's the pointer to the first byte after the IP
    //header. This is the first byte of the UDP header. The UDP header follows the IP header.
    IPSetTxBuffer(p->TxBuffer, 0);

    //Load IP header.
    IPPutHeader( &p->remoteNode,
                 IP_PROT_UDP,
                 h.Length.Val );

    // save length before swap for checksum calculation
    csLength			= p->TxCount;

    //Now swap h.Length.Val
    h.Length.Val        = swaps(h.Length.Val);

    //Now load UDP header.
    IPPutArray((BYTE*)&h, sizeof(h));

    //Update checksum. !!!!!!!!!!!!!!! TO BE IMPLEMENTED !!!!!!!!!!!!!!!!!!!
	// Update checksum.
    
	// start the checksum with value for UDP protocol & length from pseudo header (and in the actual packet)
	csChecksum.Val = (WORD)IP_PROT_UDP + (WORD)csLength + sizeof(UDP_HEADER);
	// add in my address and the remoteNode address
	csChecksum.Val += ((WORD)MY_IP_BYTE1 << 8) + MY_IP_BYTE2;
	csChecksum.Val += ((WORD)MY_IP_BYTE3 << 8) + MY_IP_BYTE4;
	csChecksum.Val += ((WORD)p->remoteNode.IPAddr.v[0] << 8) +  ((WORD)p->remoteNode.IPAddr.v[1] ) +
					  ((WORD)p->remoteNode.IPAddr.v[2] << 8) +  ((WORD)p->remoteNode.IPAddr.v[3] );
			

    // set mac pointer to the ip_addr of the source, so all of pseudo header but length is included.
    // length of pseudo header is already included in previous instruction.
    //MACSetRxBuffer( sizeof(IP_HEADER)+sizeof(UDP_HEADER) );
	

	csChecksum.Val += (WORD)p->localPort;
	csChecksum.Val += (WORD)p->remotePort;
	csChecksum.Val += (WORD)csLength + sizeof(UDP_HEADER);

	//IPSetRxBuffer(BASE_TX_ADDR + sizeof(ETHER_HEADER) + sizeof(IP_HEADER) - ( sizeof(IP_ADDR) * 2 ) );
	
    // handled in UdpPut routines
	csChecksum.Val += udpChecksum;

	// add any carry over to the last word
	while((DWORD)csChecksum.word.MSW) {
		csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW;
	}	
	// add any carry over from adding the carry over
	//csChecksum.Val = (DWORD)csChecksum.word.LSW + (DWORD)csChecksum.word.MSW;
	
	// invert
	csChecksum.Val = ~csChecksum.Val;
	
	// set write pointer to location of checksum in packet
	//MACSetWritePtr( sizeof(ETHER_HEADER) + sizeof(IP_HEADER) + sizeof(UDP_HEADER) - 2 );
	IPSetTxBuffer(p->TxBuffer,   sizeof(UDP_HEADER) - 2);
	// write the swapped checksum to the packet
	
	
	//MACPut(	csChecksum.v[1] );
	//MACPut(	csChecksum.v[0] );
	MACPut(0);
	MACPut(0);
    //Send data contained in TX Buffer via MAC
    MACFlush();

    // The buffer was reserved with AutoFree, so we can immediately 
    // discard it.  The MAC layer will free it after transmission.
    p->TxBuffer         = INVALID_BUFFER;
    p->TxCount          = 0;

}
示例#15
0
BOOL    MACGetHeader(MAC_ADDR *remote, BYTE* type)
{
    /*
     * This marks that all future accesses to MACGet and MACPut
     * be applied to Receive buffer.
     */
    bIsRxActive = TRUE;

    if ( RxBuffer.PacketCount )
    {

        /*
         * Set up packet access index.
         */
        RxBuffer.CallerAccess = RxBuffer.CurrentPacket;

        RxBuffer.CallerAccess++;
        if ( RxBuffer.CallerAccess >= MAX_SLIP_BUFFER_SIZE )
            RxBuffer.CallerAccess = 0;


        /*
         * Handle modem commands differently.
         */
        if ( RxBuffer.Data[RxBuffer.CallerAccess] == 'A' )
        {
            /*
             * Once a modem command is detected, we are not interested
             * in detail.
             */
            MACDiscardRx(); //Discard the contents of the current RX buffer

            /*
             * Mark TxBuffer for Modem String.
             * This will make sure that Transmit ISR does nottransmit END
             * at the end.
             */
            TxBuffer.Flags.bits.bIsModemString = TRUE;

            /*
             * Since this special handling does not follow standard
             * SLIP buffer logic, we will setup all required variables
             * manually.
             */
            TxBuffer.Length = 4;
            TxBuffer.CallerAccess = 0;

            /*
             * Remember to use transmit buffer for MACPut
             */
            bIsRxActive = FALSE;

            /*
             * Now load modem response.
             */
            MACPut('O');
            MACPut('K');
            MACPut('\r');
            MACPut('\n');

            /*
             * Transmit it.
             */
            MACFlush();
        }
        else
        {
            /*
             * This was not a modem command.
             * It must be IP packet.  Mark it accordingly and return.
             */
            *type = MAC_IP;

            return TRUE;
        }
    }
    return FALSE;
}
示例#16
0
void    MACPutArray(BYTE *val, WORD len)
{
    while( len-- )
        MACPut(*val++);
}
示例#17
0
/**
 * Performs UDP related tasks. Must continuesly be called.
 *
 * @preCondition    UDPInit() is already called AND <br>
 *                  UDP segment is ready in MAC buffer
 *
 * @param remoteNode    Remote node info
 * @param len           Total length of UDP semgent
 * @param destIP        The Destination IP Address of the currently received packet
 *
 * @return          TRUE if this function has completed its task <br>
 *                  FALSE otherwise
 */
BOOL UDPProcess(NODE_INFO *remoteNode, IP_ADDR *destIP, WORD len)
{
    UDP_HEADER h;
    UDP_SOCKET s;
    PSEUDO_HEADER   pseudoHeader;
    WORD_VAL        checksum;
    #if defined(UDP_SPEED_OPTIMIZE)
    BYTE temp;
    #endif

    //Retrieve UDP header. The data is read from the current MAC RX Buffer
    MACGetArray((BYTE*)&h, sizeof(h));

    #if defined(UDP_SPEED_OPTIMIZE)
        temp                    = h.SourcePort.v[0];
        h.SourcePort.v[0]       = h.SourcePort.v[1];
        h.SourcePort.v[1]       = temp;

        temp                    = h.DestinationPort.v[0];
        h.DestinationPort.v[0]  = h.DestinationPort.v[1];
        h.DestinationPort.v[1]  = temp;

        //Will an overflow occur after the subtraction?
        if ((BYTE)sizeof(UDP_HEADER) > h.Length.v[1]) {
            temp                = h.Length.v[0] - 1;
        }
        else {
            temp                = h.Length.v[0];
        }
        h.Length.v[0]           = h.Length.v[1] - (BYTE)sizeof(UDP_HEADER);
        h.Length.v[1]           = temp;
    #else
        h.SourcePort.Val        = swaps(h.SourcePort.Val);
        h.DestinationPort.Val   = swaps(h.DestinationPort.Val);
        h.Length.Val            = swaps(h.Length.Val) - sizeof(UDP_HEADER);
    #endif

    // See if we need to validate the checksum field (0x0000 is disabled)
    if(h.Checksum.Val)
    {
        #if defined(UDP_SPEED_OPTIMIZE)
            temp                    = h.Checksum.v[0];
            h.Checksum.v[0]         = h.Checksum.v[1];
            h.Checksum.v[1]         = temp;
        #else
            h.Checksum.Val          = swaps(h.Checksum.Val);
        #endif

        // Calculate IP pseudoheader checksum.
        pseudoHeader.SourceAddress      = remoteNode->IPAddr;
        pseudoHeader.DestAddress.v[0]   = destIP->v[0];
        pseudoHeader.DestAddress.v[1]   = destIP->v[1];
        pseudoHeader.DestAddress.v[2]   = destIP->v[2];
        pseudoHeader.DestAddress.v[3]   = destIP->v[3];
        pseudoHeader.Zero               = 0x0;
        pseudoHeader.Protocol           = IP_PROT_UDP;
        pseudoHeader.Length             = len;

        SwapPseudoHeader(pseudoHeader);

        checksum.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
                                        sizeof(pseudoHeader));


        // Set UCP packet checksum = pseudo header checksum in MAC RAM.
        IPSetRxBuffer(6);
        MACPut(checksum.v[0]);
        // In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address.
        IPSetRxBuffer(7);
        MACPut(checksum.v[1]);
        IPSetRxBuffer(0);   //Set current receive buffer access pointer to first byte of IP data = first byte of TCP header

        // Now calculate UDP packet checksum in NIC RAM - including
        // pesudo header.
        checksum.Val = CalcIPBufferChecksum(len);

        if ( checksum.Val != h.Checksum.Val )
        {
            MACDiscardRx(); //Discard the contents of the current RX buffer
            return TRUE;
        }
    }

    s = FindMatchingSocket(&h, remoteNode, destIP);
    if ( s == INVALID_UDP_SOCKET )
    {
         // If there is no matching socket, There is no one to handle
         // this data.  Discard it.
        MACDiscardRx(); //Discard the contents of the current RX buffer
    }
    else
    {
        UDPSocketInfo[s].RxCount = h.Length.Val;
        UDPSocketInfo[s].Flags.bFirstRead = TRUE;
    }

    return TRUE;
}