Example #1
0
/**
 * Reads a single byte via Remote DMA from the current MAC Receive buffer.
 * If the last byte of the RX Buffer was read, this function automatically
 * updates the Remote DMA read address to the first page of the RX Buffer.
 * See PreConditions for more info.
 *
 * @preCondition:    Remote DMA address has to be set up prior to calling this function.
 *                  The Remote DMA registers are NOT configured by this function,
 *                  and simply continue reading from the current "Remote DMA Address". A function
 *                  like MACRxbufGetHdr() can be called prior to this function to configure Remote
 *                  DMA to read the next packet in RX Buffer (situated in Remote DMA RAM)
 *
 * @return      Read byte
 */
BYTE    MACRxbufGet(void)
{
#if defined(__18CXX)
    overlay
#endif
    BYTE b;

    //Configure RBCR (Remote Byte Count Register) for bytes to be read via DMA
    FirstFastNICPut(RBCR0, 1);
    FastNICPut(RBCR1, 0);

    //Last byte of MAC RX Buffer is read wronge by RTL8019AS - Address has to be set again!
    if ((DMAAddr.v[0] == 0xff) && (DMAAddr.v[1] == (RXSTOP-1))) {
        //Set NIC Remote DMA read again - this fixes the RTL8019AS bug!!!!
        NICSetAddr((RXSTOP << 8) - 1);

        //Remote DMA Read command. This causes given (RBCR0 & 1) number of bytes, starting at given
        //address (RSAR0 & 1) set by NICSetAddr() to be read with each I/O read cycle.
        FastNICPut(CMDR, 0x0a); 

        b = NICGet(NIC_DATAPORT);   //Read I/O port

        //Reset to first byte of MAC RX Buffer - this function also updates DMAAddr
        //This fixes the RTL8019AS bug where the address point is not updated to first byte of Receive Buffer
        NICSetAddr(RXSTART << 8);
    }
    else {
        //Remote DMA Read command. This causes given (RBCR0 & 1) number of bytes, starting at given
        //address (RSAR0 & 1) set by NICSetAddr() to be read with each I/O read cycle.
        FastNICPut(CMDR, 0x0a); 

        //Read a byte from the I/O port
        TRISD = 0xff;   //Input
        WRITE_NIC_ADDR(NIC_DATAPORT);
        BEGIN_IO_CYCLE();
        NIC_IOR_IO = 0;
        WAIT_FOR_IOCHRDY();
        b = NIC_DATA_IO;
        NIC_IOR_IO = 1;
        LEAVE_IO_CYCLE();

        //The above I/O port operation updated the Remote DMA address
        DMAAddr.Val++;
    }

    return (b);
}
Example #2
0
void MACSetRxBuffer(int16 offset)
{
    WORD_VAL t;

    t.v[1] = NICCurrentRdPtr;
    t.v[0] = sizeof(NE_PREAMBLE);

    t.Val += offset;

    NICSetAddr(t.Val);
}
Example #3
0
void MACSetTxBuffer(BUFFER buff, int16 offset)
{
    WORD_VAL t;

    NICCurrentTxBuffer = buff;
    t.v[1] = TxBuffers[NICCurrentTxBuffer].Index;
    t.v[0] = sizeof(ETHER_HEADER);

    t.Val += offset;

    NICSetAddr(t.Val);
}
Example #4
0
/**
 * This function makes the given transmit buffer active, and sets it's access
 * pointer to be: <br>
 * - At the given offset after the Ethernet header <br>
 * - In the given TX Buffer <br><br>
 * So, if we pass 0 in as the offset, we will set the pointer to the
 * first byte after the Ethernet header.
 * Users must make sure that the supplied offset does not go beyond current transmit buffer content.
 * If offset overruns the current transmit buffer, all subsequent access to
 * that buffer would yield invalid data.
 *
 * @param buffer    A transmit buffer where this access offset be applied
 * @param offset    Location (with respect to beginning of buffer) where next access is to occur
 *
 */
void MACSetTxBuffer(BUFFER buffer, WORD offset)
{
    WORD_VAL t;

    MACCurrTxbuf = buffer;
    t.v[1] = TxBuffers[MACCurrTxbuf].Index;
    t.v[0] = sizeof(ETHER_HEADER);

    t.Val += offset;

    NICSetAddr(t.Val);
}
Example #5
0
/**
 * This function sets the access location for the active receive buffer,
 * relative to the first byte following the Ethernet header. If the given
 * offset is thus 0, the access location will be set to the first byte of
 * whatever follows the Ethernet header, for example the IP packet or ARP packet.
 * Users must make sure that the supplied offset does not go beyond
 * current receive buffer content. If offset overruns the current receive
 * buffer, all subsequent access to that buffer would yield invalid data.
 *
 * @param offset    Location (with respect to first byte following Ethernet header)
 *                  where next access is to occur.
 *
 */
void MACSetRxBuffer(WORD offset)
{
    WORD_VAL t;

    //Get pointer to first byte after Ethernet header
    t.v[1] = MACCurrRxbuf;       //Contains RAM page, is MSB of address
    t.v[0] = sizeof(NE_PREAMBLE);   //Preample data contained in RX Buffer

    t.Val += offset;    //Now add given offset to it

    NICSetAddr(t.Val);
}
Example #6
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]);
}
Example #7
0
/**
 * Discard the contents of the current RX buffer. 
 */
void MACRxbufDiscard(void)
{
    BYTE newBoundary;
    WORD_VAL t;

    //Read the "Next Packet Pointer" from current MAC RX buffer. The first 4 bytes of the current
    //buffer contains the status, next packet pointer and length bytes.
    //Set 
    t.v[1] = MACCurrRxbuf;   //Page poiner to current MAC Rx Buffer
    t.v[0] = 1;              //"Next packet pointer" is second byte of packet
    NICSetAddr(t.Val);
    newBoundary = MACRxbufGet();

    //Update BNRY pointer with new value - this will remove current MAC RX Buffer from ring!
    //NICPut(CMDR, 0x20);         // Select PAGE 0, Abort remote DMA
    NICPut(BNRY, newBoundary);  //BNRY is the receive buffer's GET pointer
    return;
}
Example #8
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]);

}
Example #9
0
int1 MACGetHeader(MAC_ADDR *remote, int8* type)
{
    NE_PREAMBLE     header;
    int8 NICWritePtr;
    WORD_VAL temp;

    *type = MAC_UNKNOWN;

    // Reset NIC if overrun has occured.
    if ( NICGet(ISR) & 0x10 )
    {
#if 1
        NICPut(CMDR, 0x21);
        Delay(0xff);
        NICPut(RBCR0, 0);
        NICPut(RBCR1, 0);
        NICPut(TCR, 0x02);
        NICPut(CMDR, 0x20);
        MACDiscardRx();
        NICPut(ISR, 0xff);
        NICPut(TCR, 0x00);
        return FALSE;
#else
        MACInit();
        return FALSE;
#endif
    }

    NICPut(CMDR, 0x60);
    NICWritePtr = NICGet(CURRP);
    NICPut(CMDR, 0x20);

    if ( NICWritePtr != NICReadPtr )
    {
        temp.v[1] = NICReadPtr;
        temp.v[0] = 0;
        NICSetAddr(temp.Val);

        //MACGetArray((int8*)&header, sizeof(header));

        debug("\r\n***************************************\r\n");

         MACGetArray(&header, sizeof(NE_PREAMBLE));

        debug(debug_putc,"\r\n\r\nGOT HDR = ST:%X NPP:%X LEN:%LU",
          (int8)header.Status,header.NextPacketPointer,header.ReceivedBytes);
        debug(debug_putc,"\r\n  DEST: %X.%X.%X.%X.%X.%X  SRC: %X.%X.%X.%X.%X.%X  TYPE:%LX",
            header.DestMACAddr.v[0],header.DestMACAddr.v[1],header.DestMACAddr.v[2],
            header.DestMACAddr.v[3],header.DestMACAddr.v[4],header.DestMACAddr.v[5],
            header.SourceMACAddr.v[0],header.SourceMACAddr.v[1],header.SourceMACAddr.v[2],
            header.SourceMACAddr.v[3],header.SourceMACAddr.v[4],header.SourceMACAddr.v[5],
            header.Type.Val);


        // Validate packet length and status.
        if ( header.Status.PRX && (header.ReceivedBytes >= MINFRAMEC) && (header.ReceivedBytes <= MAXFRAMEC) )
        {
            debug(debug_putc," VALID");
            header.Type.Val = swaps(header.Type.Val);

            //memcpy((char*)remote->v, (char*)header.SourceMACAddr.v, sizeof(*remote));
            memcpy(&remote->v[0], &header.SourceMACAddr.v[0], sizeof(MAC_ADDR));

            if ( (header.Type.v[1] == 0x08) && ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
                *type = header.Type.v[0];

        }

        NICCurrentRdPtr = NICReadPtr;
        NICReadPtr = header.NextPacketPointer;

        return TRUE;
    }
    return FALSE;

}
Example #10
0
/**
 * Check if the MAC Receive Buffer has any received packets.
 * Reads the following data from the next available packet in the RX buffer: <ul>
 *  <li> The MAC 4 bytes RX packet header (status, nex receive packet, length) </li>
 *  <li> The 14 byte Ethernet header </li></ul>
 * Once a data packet is fetched by calling MACRxbufGetHdr, the complete data
 * packet must be fetched (using MACRxbufGet) and discarded (using MACRxbufDiscard).
 * Users cannot call MACRxbufGetHdr multiple times to receive multiple packets
 * and fetch data later on.
 *
 * @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[out] type     Pointer to byte. This function will write the type of header to this variable.
 *                      Can be ETHER_IP, ETHER_ARP or MAC_UNKNOWN
 *
 * @return              True if RX Buffer contained a packet and it's header was read, False if not
 *
 */
BOOL MACRxbufGetHdr(MAC_ADDR *remote, BYTE* type)
{
    NE_PREAMBLE header;
    BYTE NICWritePtr;
    BYTE NICReadPtr;
    WORD_VAL temp;

    *type = MAC_UNKNOWN;

    //Read CURR and BNDY registers = RX Buffer's GET and PUT pointers
    NICPut(CMDR, 0x60);             //Set page 1
    NICWritePtr = NICGet(CURRP);    //Curr is the RX Buffer's PUT pointer
    NICPut(CMDR, 0x20);             //Reset to page 0
    NICReadPtr = NICGet(BNRY);      //Get BNRY pointer

    // Reset NIC if overrun has occured.
    if ( NICGet(ISR) & 0x10 )
    {
        BYTE resend;

        #if (DEBUG_MAC >= LOG_ERROR)
        debugPutMsg(3); //@mxd:3:Overrun error! Reseting MAC!
        #endif

        // Save TXP bit
        resend = NICGet(CMDR) & 0x04;

        //Issue STOP command to NIC and delay 2ms
        NICPut(CMDR, 0x21);
        DelayMs(2);

        //Clear Remote Byte count registers
        NICPut(RBCR0, 0);
        NICPut(RBCR1, 0);

        // TXP bit set?
        if (resend)
           // No re-send if Packet Transmitted or Transmit Error bit is set
           resend = !(NICGet(ISR) & 0x0A);

        //Put NIC in loopback mode and issue start command
        NICPut(TCR, 0x02);
        NICPut(CMDR, 0x22); // HM: Modified, changed to 22 to re-start NIC

        // Empty ring buffer completely
        MACCurrRxbuf = NICWritePtr;
        MACRxbufDiscard();

        //Reset ISR by writing FF to it
        NICPut(ISR, 0xff);

        //Take NIC out of loopback mode
        NICPut(TCR, 0x00);

        //Resend the packet
        if(resend)
           NICPut(CMDR, 0x26);
        return FALSE;
    }

    //Is there something in the buffer
    if ( NICWritePtr != NICReadPtr )
    {
        temp.v[1] = NICReadPtr; //Pointer to RAM page, is MSB of address
        temp.v[0] = 0;          //LSB is 0
        NICSetAddr(temp.Val);

        //Read the following from the current MAC RX Buffer:
        // - The MAC 4 bytes RX packet header (status, nex receive packet, length)
        // - The 14 byte Ethernet header
        MACRxbufGetArray((BYTE*)&header, sizeof(header));

        // Validate packet length and status as.
        if ( header.Status.PRX && (header.ReceivedBytes >= MINFRAMEC) && (header.ReceivedBytes <= MAXFRAMEC) &&
             (header.NextPacketPointer < RXSTOP) && (header.NextPacketPointer >= RXSTART) )
        {
            header.Type.Val = swaps(header.Type.Val);

            memcpy((void*)remote->v, (void*)header.SourceMACAddr.v, sizeof(*remote));

            if ( (header.Type.v[1] == 0x08) && ((header.Type.v[0] == ETHER_IP) || (header.Type.v[0] == ETHER_ARP)) )
                *type = header.Type.v[0];

            MACCurrRxbuf = NICReadPtr;   //Set MACCurrRxbuf with page address of current RX Buffer
            return TRUE;
        }

        //ERROR!!! Invalid packet received!
        #if (DEBUG_MAC >= LOG_ERROR)
        debugPutMsg(4); //@mxd:4:Invalid Packet Error!
        #endif

        //Ring now contains garbage
        MACCurrRxbuf = NICWritePtr; // Empty ring buffer completely
        MACRxbufDiscard();
    }
    return FALSE;

}