📄 rtl8019.c
字号:
#include "rtl8019.h"#include "delay.h"#include "debug.h"#include "avr/pgmspace.h"#include "rtlregs.h"#ifndef cbi#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))#endif#ifndef sbi#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))#endif#define outp(val, port) do { (port) = (val); } while(0)#define inp(port) (port)/****************************************************************************** Module Name: Realtek 8019AS Driver** Created By: Louis Beaudoin (www.embedded-creations.com)** Original Release: September 21, 2002** Module Description:* Provides functions to initialize the Realtek 8019AS, and send and retreive* packets** November 15, 2002 - Louis Beaudoin* processRTL8019Interrupt() - bit mask mistake fixed** September 30, 2002 - Louis Beaudoin* Receive functions modified to handle errors encountered when receiving a* fast data stream. Functions now manually retreive data instead of* using the send packet command. Interface improved by checking for* overruns and data in the buffer internally.* Corrected the overrun function - overrun flag was not reset after overrun* Added support for the Imagecraft Compiler* Added support to communicate with the NIC using general I/O ports******************************************************************************//****************************************************************************** writeRTL( RTL_ADDRESS, RTL_DATA )* Args: 1. unsigned char RTL_ADDRESS - register offset of RTL register* 2. unsigned char RTL_DATA - data to write to register* Created By: Louis Beaudoin* Date: September 21, 2002* Description: Writes byte to RTL8019 register.** Notes - If using the External SRAM Interface, performs a write to* address MEMORY_MAPPED_RTL8019_OFFSET + (RTL_ADDRESS<<8)* The address is sent in the non-multiplxed upper address port so* no latch is required.** If using general I/O ports, the data port is left in the input* state with pullups enabled******************************************************************************/#if MEMORY_MAPPED_NIC == 1/*#define writeRTL(RTL_ADDRESS,RTL_DATA) do{ *(volatile unsigned char *) \ (MEMORY_MAPPED_RTL8019_OFFSET \ + (((unsigned char)(RTL_ADDRESS)) << 8)) = \ (unsigned char)(RTL_DATA); } while(0)*/#define writeRTL nic_write#elsevoid writeRTL(unsigned char address, unsigned char data){ // put the address and data in the port registers - data port is output outp( address, RTL8019_ADDRESS_PORT ); outp( 0xFF, RTL8019_DATA_DDR ); outp( data, RTL8019_DATA_PORT ); // toggle write pin RTL8019_CLEAR_WRITE; RTL8019_SET_WRITE; // set data port back to input with pullups enabled outp( 0x00, RTL8019_DATA_DDR ); outp( 0xFF, RTL8019_DATA_PORT );}#endif/****************************************************************************** readRTL(RTL_ADDRESS)* Args: unsigned char RTL_ADDRESS - register offset of RTL register* Created By: Louis Beaudoin* Date: September 21, 2002* Description: Reads byte from RTL8019 register** Notes - If using the External SRAM Interface, performs a read from* address MEMORY_MAPPED_RTL8019_OFFSET + (RTL_ADDRESS<<8)* The address is sent in the non-multiplxed upper address port so* no latch is required.** If using general I/O ports, the data port is assumed to already be* an input, and is left as an input port when done******************************************************************************/#if MEMORY_MAPPED_NIC == 1/*#define readRTL(RTL_ADDRESS) (*(volatile unsigned char *) \ (MEMORY_MAPPED_RTL8019_OFFSET \ + (((unsigned char)(RTL_ADDRESS)) << 8)) )*/#define readRTL nic_read#elseunsigned char readRTL(unsigned char address){ unsigned char byte; // drive the read address outp( address, RTL8019_ADDRESS_PORT ); //nop(); // assert read RTL8019_CLEAR_READ; nop(); // read in the data byte = inp( RTL8019_DATA_PIN ); // negate read RTL8019_SET_READ; return byte;}#endif/****************************************************************************** RTL8019setupPorts(void);** Created By: Louis Beaudoin* Date: September 21, 2002* Description: Sets up the ports used for communication with the RTL8019 NIC* (data bus, address bus, read, write, and reset)*****************************************************************************/void RTL8019setupPorts(void){volatile unsigned char *base = (unsigned char *)0x8300;#if MEMORY_MAPPED_NIC == 1 // enable external SRAM interface - no wait states outp(inp(MCUCR) | (1<<SRE), MCUCR);#else // make the address port output outp( 0xFF, RTL8019_ADDRESS_DDR ); // make the data port input with pull-ups outp( 0xFF, RTL8019_DATA_PORT ); // make the control port read and write pins outputs and asserted //outp( inp(RTL8019_CONTROL_DDR) | (1<<RTL8019_CONTROL_READPIN) | // (1<<RTL8019_CONTROL_WRITEPIN), RTL8019_CONTROL_DDR ); sbi( RTL8019_CONTROL_DDR, RTL8019_CONTROL_READPIN ); sbi( RTL8019_CONTROL_DDR, RTL8019_CONTROL_WRITEPIN ); //outp( inp(RTL8019_CONTROL_PORT) | (1<<RTL8019_CONTROL_READPIN) | // (1<<RTL8019_CONTROL_WRITEPIN), RTL8019_CONTROL_PORT ); sbi( RTL8019_CONTROL_PORT, RTL8019_CONTROL_READPIN ); sbi( RTL8019_CONTROL_PORT, RTL8019_CONTROL_WRITEPIN );#endif // enable output pin for Resetting the RTL8019 sbi( RTL8019_RESET_DDR, RTL8019_RESET_PIN ); }/****************************************************************************** HARD_RESET_RTL8019()** Created By: Louis Beaudoin* Date: September 21, 2002* Description: Simply toggles the pin that resets the NIC*****************************************************************************//*#define HARD_RESET_RTL8019() do{ sbi(RTL8019_RESET_PORT, RTL8019_RESET_PIN); \ Delay_10ms(1); \ cbi(RTL8019_RESET_PORT, RTL8019_RESET_PIN);} \ while(0)*//****************************************************************************** overrun(void);** Created By: Louis Beaudoin* Date: September 21, 2002* Description: "Canned" receive buffer overrun function originally from* a National Semiconductor appnote* Notes: This function must be called before retreiving packets from* the NIC if there is a buffer overrun*****************************************************************************/void overrun(void);//******************************************************************//* REALTEK CONTROL REGISTER OFFSETS//* All offsets in Page 0 unless otherwise specified//* All functions accessing CR must leave CR in page 0 upon exit//******************************************************************#define CR 0x00#define PSTART 0x01#define PAR0 0x01 // Page 1#define CR9346 0x01 // Page 3#define PSTOP 0x02#define BNRY 0x03#define TSR 0x04#define TPSR 0x04#define TBCR0 0x05#define NCR 0x05#define TBCR1 0x06#define ISR 0x07#define CURR 0x07 // Page 1#define RSAR0 0x08#define CRDA0 0x08#define RSAR1 0x09#define CRDA1 0x09#define RBCR0 0x0A#define RBCR1 0x0B#define RSR 0x0C#define RCR 0x0C#define TCR 0x0D#define CNTR0 0x0D#define DCR 0x0E#define CNTR1 0x0E#define IMR 0x0F#define CNTR2 0x0F#define RDMAPORT 0x10#define RSTPORT 0x18/******************************************************************************* RTL ISR Register Bits******************************************************************************/#define ISR_RST 7#define ISR_OVW 4#define ISR_PRX 0#define ISR_RDC 6#define ISR_PTX 1/******************************************************************************* RTL Register Initialization Values******************************************************************************/// RCR : accept broadcast packets and packets destined to this MAC// drop short frames and receive errors#define RCR_INIT 0x04// TCR : default transmit operation - CRC is generated#define TCR_INIT 0x00// DCR : allows send packet to be used for packet retreival// FIFO threshold: 8-bits (works)// 8-bit transfer mode#define DCR_INIT 0x58// IMR : interrupt enabled for receive and overrun events#define IMR_INIT 0x11// buffer boundaries - transmit has 6 256-byte pages// receive has 26 256-byte pages// entire available packet buffer space is allocated#define TXSTART_INIT 0x40#define RXSTART_INIT 0x46#define RXSTOP_INIT 0x60void RTL8019beginPacketSend(unsigned int packetLength){ volatile unsigned char *base = (unsigned char *)0x8300; unsigned int sendPacketLength; sendPacketLength = (packetLength>=ETHERNET_MIN_PACKET_LENGTH) ? packetLength : ETHERNET_MIN_PACKET_LENGTH ; //start the NIC writeRTL(CR,0x22); // still transmitting a packet - wait for it to finish while( readRTL(CR) & 0x04 ); //load beginning page for transmit buffer writeRTL(TPSR,TXSTART_INIT); //set start address for remote DMA operation writeRTL(RSAR0,0x00); writeRTL(RSAR1,0x40); //clear the packet stored interrupt writeRTL(ISR,(1<<ISR_PTX)); //load data byte count for remote DMA writeRTL(RBCR0, (unsigned char)(packetLength)); writeRTL(RBCR1, (unsigned char)(packetLength>>8)); writeRTL(TBCR0, (unsigned char)(sendPacketLength)); writeRTL(TBCR1, (unsigned char)((sendPacketLength)>>8)); //do remote write operation writeRTL(CR,0x12);}void RTL8019sendPacketData(unsigned char * localBuffer, unsigned int length){ unsigned int i; volatile unsigned char *base = (unsigned char *)0x8300; for(i=0;i<length;i++) writeRTL(RDMAPORT, localBuffer[i]);}void RTL8019endPacketSend(void){ volatile unsigned char *base = (unsigned char *)0x8300; //send the contents of the transmit buffer onto the network writeRTL(CR,0x24); // clear the remote DMA interrupt writeRTL(ISR, (1<<ISR_RDC));}// pointers to locations in the RTL8019 receive bufferstatic unsigned char nextPage;static unsigned int currentRetreiveAddress;// location of items in the RTL8019's page header#define enetpacketstatus 0x00#define nextblock_ptr 0x01#define enetpacketLenL 0x02#define enetpacketLenH 0x03unsigned int RTL8019beginPacketRetreive(void){ volatile unsigned char *base = (unsigned char *)0x8300; unsigned char i; unsigned char bnry; unsigned char pageheader[4]; unsigned int rxlen; // check for and handle an overflow processRTL8019Interrupt(); // read CURR from page 1 writeRTL(CR,0x62); i = readRTL(CURR); // return to page 0 writeRTL(CR,0x22); // read the boundary register - pointing to the beginning of the packet bnry = readRTL(BNRY) ; /* debug_print(PSTR("bnry: ")); debug_print8(bnry);*/ /* debug_print(PSTR("RXSTOP_INIT: ")); debug_print8(RXSTOP_INIT); debug_print(PSTR("RXSTART_INIT: ")); debug_print8(RXSTART_INIT);*/ // return if there is no packet in the buffer if( bnry == i ) { return 0; } // clear the packet received interrupt flag writeRTL(ISR, (1<<ISR_PRX)); // the boundary pointer is invalid, reset the contents of the buffer and exit if( (bnry >= RXSTOP_INIT) || (bnry < RXSTART_INIT) ) { writeRTL(BNRY, RXSTART_INIT); writeRTL(CR, 0x62); writeRTL(CURR, RXSTART_INIT); writeRTL(CR, 0x22); return 0; } // initiate DMA to transfer the RTL8019 packet header writeRTL(RBCR0, 4); writeRTL(RBCR1, 0); writeRTL(RSAR0, 0); writeRTL(RSAR1, bnry); writeRTL(CR, 0x0A); /* debug_print(PSTR("Page header: "));*/ for(i=0;i<4;i++) { pageheader[i] = readRTL(RDMAPORT); /* debug_print8(pageheader[i]);*/ } // end the DMA operation writeRTL(CR, 0x22); for(i = 0; i <= 20; i++) { if(readRTL(ISR) & 1<<6) { break; } } writeRTL(ISR, 1<<6); rxlen = (pageheader[enetpacketLenH]<<8) + pageheader[enetpacketLenL]; nextPage = pageheader[nextblock_ptr] ; currentRetreiveAddress = (bnry<<8) + 4; /* debug_print(PSTR("nextPage: ")); debug_print8(nextPage);*/ // if the nextPage pointer is invalid, the packet is not ready yet - exit if( (nextPage >= RXSTOP_INIT) || (nextPage < RXSTART_INIT) ) { /* UDR0 = '0';*/ return 0; } return rxlen-4;}void RTL8019retreivePacketData(unsigned char * localBuffer, unsigned int length){ unsigned int i; volatile unsigned char *base = (unsigned char *)0x8300; // initiate DMA to transfer the data writeRTL(RBCR0, (unsigned char)length); writeRTL(RBCR1, (unsigned char)(length>>8)); writeRTL(RSAR0, (unsigned char)currentRetreiveAddress); writeRTL(RSAR1, (unsigned char)(currentRetreiveAddress>>8)); writeRTL(CR, 0x0A); for(i=0;i<length;i++) localBuffer[i] = readRTL(RDMAPORT); // end the DMA operation writeRTL(CR, 0x22);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -