void ax88796ReceiveOverflowRecover(void) { // receive buffer overflow handling procedure // as specified in the AX88796 datasheet unsigned char cmdReg; unsigned char resend=0; // check if we were transmitting something cmdReg = ax88796Read(CR); // stop the interface ax88796Write(CR, (RD2|STOP)); // wait for timeout delay_ms(2); // clear remote byte count registers ax88796Write(RBCR0, 0x00); ax88796Write(RBCR1, 0x00); // if we were transmitting something if(cmdReg & TXP) { // check if the transmit completed cmdReg = ax88796Read(ISR); if((cmdReg & PTX) || (cmdReg & TXE)) resend = 0; // transmit completed else resend = 1; // transmit was interrupted, must resend } // switch to loopback mode ax88796Write(TCR, LB0); // start the interface ax88796Write(CR, (RD2|START)); // set boundary ax88796Write(BNRY, RXSTART_INIT); // go to page 1 ax88796Write(CR, (PS0|RD2|START)); // set current page register ax88796Write(CPR, RXSTART_INIT+1); // go to page 0 ax88796Write(CR, (RD2|START)); // clear the overflow int ax88796Write(ISR, OVW); // switch to normal (non-loopback mode) ax88796Write(TCR, TCR_INIT); // if previous transmit was interrupted, then resend if(resend) ax88796Write(CR, (RD2|TXP|START)); // recovery completed }
void ax88796Overrun(void) { unsigned char cmdReg, resend; // check if we were transmitting something cmdReg = ax88796Read(CR); // stop the interface ax88796Write(CR, (RD2|STOP)); // wait for timeout delay_ms(2); // clear remote byte count registers ax88796Write(RBCR0, 0x00); ax88796Write(RBCR1, 0x00); if(!(cmdReg & TXP)) { resend = 0; } else { cmdReg = ax88796Read(ISR); if((cmdReg & PTX) || (cmdReg & TXE)) resend = 0; else resend = 1; } // switch to loopback mode ax88796Write(TCR, LB0); // start the interface ax88796Write(CR, (RD2|START)); // set boundary ax88796Write(BNRY, RXSTART_INIT); // go to page 1 ax88796Write(CR, (PS0|RD2|START)); // set current page register ax88796Write(CURR, RXSTART_INIT+1); // go to page 0 ax88796Write(CR, (RD2|START)); // clear the overflow int ax88796Write(ISR, OVW); // switch to normal (non-loopback mode) ax88796Write(TCR, TCR_INIT); if(resend) ax88796Write(CR, (RD2|TXP|START)); //ax88796Write(ISR, 0xFF); }
void ax88796BeginPacketSend(unsigned int packetLength) { unsigned int sendPacketLength; sendPacketLength = (packetLength>=ETHERNET_MIN_PACKET_LENGTH) ? packetLength : ETHERNET_MIN_PACKET_LENGTH ; //start the NIC ax88796Write(CR,0x22); // still transmitting a packet - wait for it to finish while( ax88796Read(CR) & 0x04 ); //load beginning page for transmit buffer ax88796Write(TPSR,TXSTART_INIT); //set start address for remote DMA operation ax88796Write(RSAR0,0x00); ax88796Write(RSAR1,0x40); //clear the packet stored interrupt ax88796Write(ISR, PTX); //load data byte count for remote DMA ax88796Write(RBCR0, (unsigned char)(packetLength)); ax88796Write(RBCR1, (unsigned char)(packetLength>>8)); ax88796Write(TBCR0, (unsigned char)(sendPacketLength)); ax88796Write(TBCR1, (unsigned char)((sendPacketLength)>>8)); //do remote write operation ax88796Write(CR,0x12); }
void ax88796ProcessInterrupt(void) { unsigned char byte = ax88796Read(ISR); if( byte & OVW ) ax88796Overrun(); }
void ax88796ProcessInterrupt(void) { unsigned char intr = ax88796Read(ISR); // check for receive overflow if( intr & OVW ) ax88796ReceiveOverflowRecover(); }
void ax88796RetreivePacketData(unsigned char * localBuffer, unsigned int length) { unsigned int i; // initiate DMA to transfer the data ax88796Write(RBCR0, (unsigned char)length); ax88796Write(RBCR1, (unsigned char)(length>>8)); ax88796Write(RSAR0, (unsigned char)currentRetreiveAddress); ax88796Write(RSAR1, (unsigned char)(currentRetreiveAddress>>8)); ax88796Write(CR, (RD0|START)); for(i=0;i<length;i++) localBuffer[i] = ax88796Read(RDMAPORT); // end the DMA operation ax88796Write(CR, (RD2|START)); for(i = 0; i <= 20; i++) if(ax88796Read(ISR) & RDC) break; ax88796Write(ISR, RDC); currentRetreiveAddress += length; if( currentRetreiveAddress >= 0x6000 ) currentRetreiveAddress -= (0x6000-0x4600) ; }
unsigned int ax88796ReadMii(unsigned char phyad,unsigned char regad) { unsigned char mask8,i; unsigned int mask16,result16; mii_read; mask8 = 0x10; for(i=0;i<5;++i) { if(mask8 & phyad) set_mdo; else clr_mdo; mii_clk; mask8 >>= 1; } mask8 = 0x10; for(i=0;i<5;++i) { if(mask8 & regad) set_mdo; else clr_mdo; mii_clk; mask8 >>= 1; } mii_r_ta; mask16 = 0x8000; result16 = 0x0000; for(i=0;i<16;++i) { mii_clk; if(ax88796Read(MEMR) & 0x04) { result16 |= mask16; } else { nop(); break; } mask16 >>= 1; } return result16; }
void nicSetMacAddress(u08* macaddr) { u08 tempCR; // switch register pages tempCR = ax88796Read(CR); ax88796Write(CR,tempCR|PS0); // write MAC address registers ax88796Write(PAR0, *macaddr++); ax88796Write(PAR1, *macaddr++); ax88796Write(PAR2, *macaddr++); ax88796Write(PAR3, *macaddr++); ax88796Write(PAR4, *macaddr++); ax88796Write(PAR5, *macaddr++); // switch register pages back ax88796Write(CR,tempCR); }
void nicGetMacAddress(u08* macaddr) { u08 tempCR; // switch register pages tempCR = ax88796Read(CR); ax88796Write(CR,tempCR|PS0); // read MAC address registers *macaddr++ = ax88796Read(PAR0); *macaddr++ = ax88796Read(PAR1); *macaddr++ = ax88796Read(PAR2); *macaddr++ = ax88796Read(PAR3); *macaddr++ = ax88796Read(PAR4); *macaddr++ = ax88796Read(PAR5); // switch register pages back ax88796Write(CR,tempCR); }
void ax88796EndPacketRetreive(void) { unsigned char i; unsigned char bnryPagePtr; // end the DMA operation ax88796Write(CR, (RD2|START)); for(i = 0; i <= 20; i++) if(ax88796Read(ISR) & RDC) break; ax88796Write(ISR, RDC); // set the boundary register to point // to the start of the next packet-1 bnryPagePtr = nextPage-1; if(bnryPagePtr < RXSTART_INIT) bnryPagePtr = RXSTOP_INIT-1; ax88796Write(BNRY, bnryPagePtr); }
unsigned int ax88796BeginPacketRetreive(void) { unsigned char writePagePtr; unsigned char readPagePtr; unsigned char bnryPagePtr; unsigned char i; unsigned char pageheader[4]; unsigned int rxlen; // check for and handle an overflow ax88796ProcessInterrupt(); // read CURR from page 1 ax88796Write(CR,(PS0|RD2|START)); writePagePtr = ax88796Read(CURR); // read the boundary register from page 0 ax88796Write(CR,(RD2|START)); bnryPagePtr = ax88796Read(BNRY); // first packet is at page bnryPtr+1 readPagePtr = bnryPagePtr+1; if(readPagePtr >= RXSTOP_INIT) readPagePtr = RXSTART_INIT; // return if there is no packet in the buffer if( readPagePtr == writePagePtr ) { return 0; } // clear the packet received interrupt flag ax88796Write(ISR, PRX); // if the boundary pointer is invalid, // reset the contents of the buffer and exit if( (bnryPagePtr < RXSTART_INIT) || (bnryPagePtr >= RXSTOP_INIT) ) { ax88796Write(BNRY, RXSTART_INIT); ax88796Write(CR, (PS0|RD2|START)); ax88796Write(CURR, RXSTART_INIT+1); ax88796Write(CR, (RD2|START)); return 0; } // initiate DMA to transfer the RTL8019 packet header ax88796Write(RBCR0, 4); ax88796Write(RBCR1, 0); ax88796Write(RSAR0, 0); ax88796Write(RSAR1, readPagePtr); ax88796Write(CR, (RD0|START)); for(i=0;i<4;i++) pageheader[i] = ax88796Read(RDMAPORT); // end the DMA operation ax88796Write(CR, (RD2|START)); for(i = 0; i <= 20; i++) if(ax88796Read(ISR) & RDC) break; ax88796Write(ISR, RDC); rxlen = (pageheader[enetpacketLenH]<<8) + pageheader[enetpacketLenL]; nextPage = pageheader[nextblock_ptr] ; currentRetreiveAddress = (readPagePtr<<8) + 4; // if the nextPage pointer is invalid, the packet is not ready yet - exit if( (nextPage >= RXSTOP_INIT) || (nextPage < RXSTART_INIT) ) { return 0; } return rxlen-4; }
void ax88796Init(void) { unsigned char delaycount=10; unsigned char tcrFduFlag; ax88796SetupPorts(); // do a hard reset AX88796_RESET_PORT |= _BV(AX88796_RESET_PIN); delay_ms(10); AX88796_RESET_PORT &= ~_BV(AX88796_RESET_PIN); // do soft reset ax88796Write(ISR, ax88796Read(ISR)); delay_ms(50); // wait for PHY to come out of reset ax88796Read(RSTPORT); while(ax88796Read(TR) & RST_B); ax88796WriteMii(0x10,0x00,0x0800); while(delaycount--) delay_ms(255); ax88796WriteMii(0x10,0x00,0x1200); ax88796Write(CR,(RD2|STOP)); // stop the NIC, abort DMA, page 0 delay_ms(5); // make sure nothing is coming in or going out ax88796Write(DCR,DCR_INIT); ax88796Write(RBCR0,0x00); ax88796Write(RBCR1,0x00); ax88796Write(IMR,0x00); ax88796Write(ISR,0xFF); ax88796Write(RCR,0x20); ax88796Write(BNRY,RXSTART_INIT); ax88796Write(PSTART,RXSTART_INIT); ax88796Write(PSTOP,RXSTOP_INIT); // switch to page 1 ax88796Write(CR,(PS0|RD2|STOP)); // write mac address ax88796Write(PAR0+0, MYMAC_0); ax88796Write(PAR0+1, MYMAC_1); ax88796Write(PAR0+2, MYMAC_2); ax88796Write(PAR0+3, MYMAC_3); ax88796Write(PAR0+4, MYMAC_4); ax88796Write(PAR0+5, MYMAC_5); // set start point ax88796Write(CURR,RXSTART_INIT+1); ax88796Write(CR,(RD2|START)); ax88796Write(RCR,RCR_INIT); if(ax88796Read(GPI) & I_SPD) // check PHY speed setting tcrFduFlag = FDU; // if 100base, do full duplex else tcrFduFlag = 0; // if 10base, do half duplex ax88796Write(TCR,(tcrFduFlag|TCR_INIT)); ax88796Write(GPOC,MPSEL); // select media interface ax88796Write(TPSR,TXSTART_INIT); ax88796Write(CR,(RD2|STOP)); ax88796Write(DCR,DCR_INIT); ax88796Write(CR,(RD2|START)); ax88796Write(ISR,0xFF); ax88796Write(IMR,IMR_INIT); ax88796Write(TCR,(tcrFduFlag|TCR_INIT)); }
void ax88796RegDump(void) { unsigned char result; result = ax88796Read(TR); rprintf("Media State: "); if(!(result & AUTOD)) rprintf("Autonegotiation\r\n"); else if(result & RST_B) rprintf("PHY in Reset \r\n"); else if(!(result & RST_10B)) rprintf("10BASE-T \r\n"); else if(!(result & RST_TXB)) rprintf("100BASE-T \r\n"); //rprintf("TR regsiter : %x\r\n",result); //result = read_mii(0x10,0); //rprintf("MII regsiter 0x10: %x\r\n",result); rprintfProgStrM("Page0: CR BNRY PSR PST ISR TSR RSR MMR TR GPI\r\n"); rprintfProgStrM(" "); rprintfu08(ax88796Read(CR)); rprintfProgStrM(" "); rprintfu08(ax88796Read(BNRY)); rprintfProgStrM(" "); rprintfu08(ax88796Read(PSTART)); rprintfProgStrM(" "); rprintfu08(ax88796Read(PSTOP)); rprintfProgStrM(" "); rprintfu08(ax88796Read(ISR)); rprintfProgStrM(" "); rprintfu08(ax88796Read(TSR)); rprintfProgStrM(" "); rprintfu08(ax88796Read(RSR)); rprintfProgStrM(" "); rprintfu08(ax88796Read(MEMR)); rprintfProgStrM(" "); rprintfu08(ax88796Read(TR)); rprintfProgStrM(" "); rprintfu08(ax88796Read(GPI)); rprintfCRLF(); ax88796Write(CR,ax88796Read(CR)|PS0); rprintf("Page1: CR PAR CPR\r\n"); rprintfProgStrM(" "); rprintfu08(ax88796Read(CR)); rprintfProgStrM(" "); rprintfChar(ax88796Read(PAR0)); rprintfChar(ax88796Read(PAR1)); rprintfChar(ax88796Read(PAR2)); rprintfChar(ax88796Read(PAR3)); rprintfChar(ax88796Read(PAR4)); rprintfChar(ax88796Read(PAR5)); rprintfProgStrM(" "); rprintfu08(ax88796Read(CPR)); ax88796Write(CR,ax88796Read(CR)&~PS0); delay_ms(25); }
void ax88796Init(void) { unsigned char tcrFduFlag; // initialize I/O ports ax88796SetupPorts(); // do a hard reset sbi(AX88796_RESET_PORT, AX88796_RESET_PIN); delay_ms(100); cbi(AX88796_RESET_PORT, AX88796_RESET_PIN); // do soft reset ax88796Write(ISR, ax88796Read(ISR)); delay_ms(50); // wait for PHY to come out of reset ax88796Read(RSTPORT); while(ax88796Read(TR) & RST_B); ax88796WriteMii(0x10,0x00,0x0800); delay_ms(255); ax88796WriteMii(0x10,0x00,0x1200); ax88796Write(CR,(RD2|STOP)); // stop the NIC, abort DMA, page 0 delay_ms(5); // make sure nothing is coming in or going out ax88796Write(DCR,DCR_INIT); ax88796Write(RBCR0,0x00); ax88796Write(RBCR1,0x00); ax88796Write(IMR,0x00); ax88796Write(ISR,0xFF); ax88796Write(RCR,0x20); ax88796Write(BNRY,RXSTART_INIT); ax88796Write(PSTART,RXSTART_INIT); ax88796Write(PSTOP,RXSTOP_INIT); // switch to page 1 ax88796Write(CR,(PS0|RD2|STOP)); // write mac address ax88796Write(PAR0+0, AX88796_MAC0); ax88796Write(PAR0+1, AX88796_MAC1); ax88796Write(PAR0+2, AX88796_MAC2); ax88796Write(PAR0+3, AX88796_MAC3); ax88796Write(PAR0+4, AX88796_MAC4); ax88796Write(PAR0+5, AX88796_MAC5); // set start point ax88796Write(CURR,RXSTART_INIT+1); ax88796Write(CR,(RD2|START)); ax88796Write(RCR,RCR_INIT); if(ax88796Read(GPI) & I_SPD) // check PHY speed setting tcrFduFlag = FDU; // if 100base, do full duplex else tcrFduFlag = 0; // if 10base, do half duplex ax88796Write(TCR,(tcrFduFlag|TCR_INIT)); ax88796Write(GPOC,MPSEL); // select media interface ax88796Write(TPSR,TXSTART_INIT); ax88796Write(CR,(RD2|STOP)); ax88796Write(DCR,DCR_INIT); ax88796Write(CR,(RD2|START)); ax88796Write(ISR,0xFF); ax88796Write(IMR,IMR_INIT); ax88796Write(TCR,(tcrFduFlag|TCR_INIT)); //test /* while(1) { vt100SetCursorPos(18,0); ax88796RegDump(); } */ }