/** * 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); }
void MACSetRxBuffer(int16 offset) { WORD_VAL t; t.v[1] = NICCurrentRdPtr; t.v[0] = sizeof(NE_PREAMBLE); t.Val += offset; NICSetAddr(t.Val); }
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); }
/** * 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); }
/** * 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); }
/** * 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]); }
/** * 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; }
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]); }
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; }
/** * 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; }