/** * Function for performing MAC related tasks * * @preCondition Must be called every couple of ms */ void MACTask(void) { #if (DEBUG_MAC >= LOG_WARN) BYTE tmpSum; char buf[5]; #endif #if defined(MAC_CNTR1_3) cntr0.Val += NICGet(CNTR0); cntr1.Val += NICGet(CNTR1); cntr2.Val += NICGet(CNTR2); #endif #if (DEBUG_MAC >= LOG_WARN) tmpSum = LSB(cntr0) + MSB(cntr0) + LSB(cntr1) + MSB(cntr1) + LSB(cntr2) + MSB(cntr2); //If any of the error counter have changed, print them out! if (cntrSum != tmpSum) { debugPutMsg(1); //@mxd:1:Frame Alignment=%s, CRC=%s, Missed Packets=%s itoa(cntr0.Val, buf); debugPutString(buf); itoa(cntr1.Val, buf); debugPutString(buf); itoa(cntr2.Val, buf); debugPutString(buf); cntrSum = tmpSum; } #endif }
int16 MACGetOffset(void) { WORD_VAL t; t.v[1] = NICGet(RSAR1); t.v[0] = NICGet(RSAR0); return t.Val; }
/** * Get the current Remote DMA address. This is the address set by the NICSetAddr register. * It will however be incremented after each Remote DMA read. * The MACRxbufGet() function for example does a remote DMA read. * * @return The current Remote DMA address. */ WORD MACGetNICAddr(void) { WORD_VAL t; t.v[1] = NICGet(RSAR1); t.v[0] = NICGet(RSAR0); return t.Val; }
int8 MACGet(void) { NICPut(RBCR0, 1); NICPut(RBCR1, 0); NICPut(CMDR, 0x0a); return NICGet(NIC_DATAPORT); }
int1 MACIsTxReady(void) { // NICCurrentTxBuffer always points to free buffer, if there is any. // If there is none, NICCurrentTxBuffer will be a in 'Use' state. //return TxBuffers[NICCurrentTxBuffer].bFree; return !(NICGet(CMDR) & 0x04); }
/** * Check if ready for next transmission. * * @return TRUE if transmit buffer is empty <br> * FALSE if transmit buffer is not empty * */ BOOL MACIsTxReady(void) { // MACCurrTxbuf always points to free buffer, if there is any. // If there is none, MACCurrTxbuf will be a in 'Use' state. //return TxBuffers[MACCurrTxbuf].bFree; // Check to see if previous transmission was successful or not. return !(NICGet(CMDR) & 0x04); }
int1 MACIsLinked(void) { int8 temp; // Select Page 3 NICPut(CMDR, 0xe0); // Read CONFIG0. temp = NICGet(0x03); // Reset to page 0. NICPut(CMDR, 0x20); // Bit 2 "BNC" will be '0' if LINK is established. return (!bit_test(temp,2)); }
/** * Check if the MAC is linked * * @return TRUE if linked, else FALSE */ BOOL MACIsLinked(void) { BYTE_VAL temp; // Select Page 3 NICPut(CMDR, 0xe0); // Read CONFIG0. temp.Val = NICGet(0x03); // Reset to page 0. NICPut(CMDR, 0x20); // Bit 2 "BNC" will be '0' if LINK is established. return (temp.bits.b2 == 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); }
int16 MACGetFreeRxSize(void) { int8 NICWritePtr; int8 temp; WORD_VAL tempVal; NICPut(CMDR, 0x60); NICWritePtr = NICGet(CURRP); NICPut(CMDR, 0x20); if ( NICWritePtr < NICCurrentRdPtr ) temp = (RXSTOP - NICCurrentRdPtr) + NICWritePtr; else temp = NICWritePtr - NICCurrentRdPtr; temp = RXPAGES - temp; tempVal.v[1] = temp; tempVal.v[0] = 0; return tempVal.Val; }
int16 MACGetArray(int8 *val, int16 len) { WORD_VAL t; t.Val = len; NICPut(ISR, 0x40); NICPut(RBCR0, t.v[0]); NICPut(RBCR1, t.v[1]); NICPut(CMDR, 0x0a); debug("\r\nMACGETARRAY: "); while( len-- > 0 ) { *val++ = NICGet(NIC_DATAPORT); debug("%X ",*(val-1)); } return t.Val; }
/** * This function returns total receive buffer size available for future data packets. */ WORD MACGetFreeRxSize(void) { BYTE NICWritePtr; //CURR register - RX buffer's PUT pointer BYTE temp; WORD_VAL tempVal; //Read current page pointer - Curr is the RX Buffer's PUT pointer NICPut(CMDR, 0x60); //Set page 1 NICWritePtr = NICGet(CURRP); //Curr is the RX Buffer's PUT pointer NICPut(CMDR, 0x20); //Reset to page 0 if ( NICWritePtr < MACCurrRxbuf ) temp = (RXSTOP - MACCurrRxbuf) + NICWritePtr; else temp = NICWritePtr - MACCurrRxbuf; temp = RXPAGES - temp; tempVal.v[1] = temp; tempVal.v[0] = 0; return tempVal.Val; }
void MACPutArray(int8 *val, int16 len) { WORD_VAL t; t.Val = len + (len & 1); debug("\r\nMACPUTARRAY %LX: ",len); NICPut(ISR, 0x40); NICPut(RBCR0, t.v[0]); NICPut(RBCR1, t.v[1]); NICPut(CMDR, 0x12); // index bug corrected RJS 8/3/04 while ( t.val-- > 0 ) { NICPut(NIC_DATAPORT, *val++); debug("%X ",*(val-1)); } // Make sure that DMA is complete. len = 255; while( len && (NICGet(ISR) & 0x40) == 0 ) len--; }
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; }
void MACInit(void) { int8 i; // On Init, all transmit buffers are free. for ( i = 0; i < MAX_DATA_BUFFERS; i++ ) { TxBuffers[i].Index = TXSTART + (i * (MAC_TX_BUFFER_SIZE/NIC_PAGE_SIZE)); TxBuffers[i].bFree = TRUE; } NICCurrentTxBuffer = 0; NICReset(); delay_ms(2); NICPut(NIC_RESET, NICGet(NIC_RESET)); delay_ms(2); // mimimum Delay of 1.6 ms // Continue only if reset state is entered. if ( (NICGet(ISR) & 0x80) != 0 ) { // Select Page 0 NICPut(CMDR, 0x21); delay_ms(2); // Initialize Data Configuration Register NICPut(DCR, DCRVAL); // Clear Remote Byte Count Registers NICPut(RBCR0, 0); NICPut(RBCR1, 0); // Initialize Receive Configuration Register NICPut(RCR, 0x04); // Place NIC in LOOPBACK mode 1 NICPut(TCR, 0x02); // Initialize Transmit buffer queue NICPut(TPSR, TxBuffers[NICCurrentTxBuffer].Index); // Initialize Receive Buffer Ring NICPut(PSTART, RXSTART); NICPut(PSTOP, RXSTOP); NICPut(BNRY, (BYTE)(RXSTOP-1)); // Initialize Interrupt Mask Register // Clear all status bits NICPut(ISR, 0xff); // No interrupt enabled. NICPut(IMR, 0x00); // Select Page 1 NICPut(CMDR, 0x61); // Initialize Physical Address Registers NICPut(PAR0, MY_MAC_BYTE1); NICPut(PAR0+1, MY_MAC_BYTE2); NICPut(PAR0+2, MY_MAC_BYTE3); NICPut(PAR0+3, MY_MAC_BYTE4); NICPut(PAR0+4, MY_MAC_BYTE5); NICPut(PAR0+5, MY_MAC_BYTE6); // Initialize Multicast registers for ( i = 0; i < 8; i++ ) NICPut(MAR0+i, 0xff); // Initialize CURRent pointer NICPut(CURRP, RXSTART); // Remember current receive page NICReadPtr = RXSTART; // Page 0, Abort Remote DMA and Activate the transmitter. NICPut(CMDR, 0x22); // Set Normal Mode NICPut(TCR, 0x00); } }
void MACInit(void) { BYTE i; /* SBC45EC - use port B*/ #if defined(BRD_SBC44EC) TRISB = 0xe0; //RB0-4 are outputs //NIC_DISABLE_IOCHRDY can be defined if the MAC should NOT use the IOCHRDY signal on the RTL8019AS chip. // - For SBC44EC PIC port pin B5 will be available for user IO. Solder jumper SJ5 must be opened! #if !defined(NIC_DISABLE_IOCHRDY) NIC_IOCHRDY_TRIS = 1; //IOCHRDY is an input #endif /* SBC45EC - use port A*/ #elif defined(BRD_SBC45EC) TRISA = 0xd0; //RA0-3 and RA5 are outputs //NIC_DISABLE_IOCHRDY can be defined if the MAC should NOT use the IOCHRDY signal on the RTL8019AS chip. // - For SBC45EC PIC port pin A4 will be available for user IO. Solder jumper SJ5 must be opened! #if !defined(NIC_DISABLE_IOCHRDY) NIC_IOCHRDY_TRIS = 1; //IOCHRDY is an input #endif /* SBC65EC - use port E*/ #elif defined(BRD_SBC65EC) TRISE = 0x00; //RE0-7 are outputs //NIC_DISABLE_IOCHRDY can be defined if the MAC should NOT use the IOCHRDY signal on the RTL8019AS chip. // - For SBC65EC and SBC68EC this frees up PIC pin RG4. This pin is currently however not routed to an connectors //#if !defined(NIC_DISABLE_IOCHRDY) NIC_IOCHRDY = 1; NIC_IOCHRDY_TRIS = 1; //IOCHRDY is an input //#endif #endif //Reset all error counters #ifdef MAC_CNTR1_3 cntr0.Val = 0; cntr1.Val = 0; cntr2.Val = 0; #endif #if (DEBUG_MAC >= LOG_WARN) cntrSum = 0; #endif // On Init, all transmit buffers are free. for ( i = 0; i < MAX_DATA_BUFFERS; i++ ) { //Set to NIC SRAM page TxBuffers[i].Index = TXSTART + (i * (MAC_TX_BUFFER_SIZE/NIC_PAGE_SIZE)); TxBuffers[i].bFree = TRUE; } MACCurrTxbuf = 0; NICReset(); DelayMs(5); // Give RTL8019AS time to load EEPROM values - takes about 2ms NICPut(NIC_RESET, NICGet(NIC_RESET)); //Writing to NIC_RESET register caused NIC to reset // mimimum Delay of 1.6 ms DelayMs(5); // Give RTL8019AS time to load EEPROM values - takes about 2ms //Some documentation states that reset bit is unreliable - only check it for 100ms //if ( (NICGet(ISR) & 0x80) != 0 ) { #if defined(BRD_SBC44EC) || defined(BRD_SBC45EC) //Because the EEPROM read pin is floating on some boards, the registers initialized by the //EEPROM will all contain non defined values. Write them with correct values //MACInitEepromRegs(); // TEST TEST #endif // Select Page 0 AND issue STOP Command NICPut(CMDR, 0x21); DelayMs(5); // Initialize Data Configuration Register NICPut(DCR, DCRVAL); // Clear Remote Byte Count Registers NICPut(RBCR0, 0); NICPut(RBCR1, 0); // Initialize Receive Configuration Register NICPut(RCR, 0x04); // Place NIC in LOOPBACK mode 1 NICPut(TCR, 0x02); // Initialize Transmit buffer queue NICPut(TPSR, TxBuffers[MACCurrTxbuf].Index); // Initialize Receive Buffer Ring NICPut(PSTART, RXSTART); NICPut(PSTOP, RXSTOP); NICPut(BNRY, RXSTART); //Receive buffer GET pointer // Initialize Interrupt Mask Register // Clear all status bits NICPut(ISR, 0xff); // No interrupt enabled. NICPut(IMR, 0x00); // Select Page 1 NICPut(CMDR, 0x61); // Initialize Physical Address Registers NICPut(PAR0, MY_MAC_BYTE1); NICPut(PAR0+1, MY_MAC_BYTE2); NICPut(PAR0+2, MY_MAC_BYTE3); NICPut(PAR0+3, MY_MAC_BYTE4); NICPut(PAR0+4, MY_MAC_BYTE5); NICPut(PAR0+5, MY_MAC_BYTE6); // Initialize Multicast registers for ( i = 0; i < 8; i++ ) NICPut(MAR0+i, 0xff); // Initialize CURRent pointer - this is the RX Buffer PUT pointer NICPut(CURRP, RXSTART); // TCP layer uses this value to calculate window size. Without init the // first window size value sent would be wrong if no packet has been received before. MACCurrRxbuf = RXSTART; // Page 0, Abort Remote DMA and Activate the transmitter. NICPut(CMDR, 0x22); // Set Normal Mode NICPut(TCR, 0x00); } #if defined(BRD_SBC44EC) || defined(BRD_SBC45EC) //Because the EEPROM read pin is floating on some boards, the registers initialized by the //EEPROM will all contain non defined values. Write them with correct values //MACInitEepromRegs(); // TEST TEST #endif //Disable RTL8019AS interrupts. All INT lines go tri-state, and PIC pin is available to user. The //PIC port pin that becomes available is: // - For SBC44EC this has no affect - no PIC pins are connected to the interrupt pins // - For SBC45EC this has no affect - no PIC pins are connected to the interrupt pins // - For SBC65EC and SBC68EC this frees up PIC pin RB0. #if (defined(BRD_SBC65EC) || defined(BRD_SBC68EC)) && defined(NIC_DISABLE_INT0) NICPut(CMDR, 0xe0); //Select page 3 NICPut(RTL9346CR, 0xc0); //Config register write enable NICPut(RTLCONF1, 0); //Interrupt disable - will cause INT0 to be high impedance. NICPut(RTL9346CR, 0x00); //Normal operating mode NICPut(CMDR, 0x20); //Reset to default = Page 0 #endif }
/** * 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; }