⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 redlogic_rtl8019_t.c

📁 使用RTL8019芯片进行以太网通讯的VERILOG源代码.
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdefLWIP#include<stdlib.h>#include<stdio.h>#include<unistd.h>#include<altera_avalon_pio_regs.h>#include"alt_types.h"#include"redlogic_rtl8019_regs.h"#include"lwip/opt.h"#include"lwip/def.h"#include"lwip/mem.h"#include"lwip/pbuf.h"#include"lwip/sys.h"#include"lwip/netif.h"#include"lwip/stats.h"#include"netif/etharp.h"#include"system.h"#include"arch/perf.h"#include"sys/alt_irq.h"#include"redlogic_rtl8019.h"/*Uniquedescricptionofthenetworkinterface.*/#defineIFNAME0'n'#defineIFNAME1'9'externsys_mbox_trx_mbox;staticerr_tredlogic_rtl8019_output(structnetif*netif,structpbuf*p,structip_addr*ipaddr);staticstructpbuf*low_level_input(redlogic_rtl8019_if*dev);staticerr_tlow_level_output(structnetif*netif,structpbuf*p);staticerr_tlow_level_init(redlogic_rtl8019_if*dev);voidredlogic_rtl8019_irq(void*context,alt_u32interrupt);/*************************************************/staticunsignedcharmac[]={0x01,0x02,0x03,0x04,0x05,0x06};staticinlinevoidDelay16Cycles(void){unsignedinti;for(i=0;i<100;i++);}u_charreg_read(unsignedintbase,u_charreg){unsignedcharuc;uc=IORD_8DIRECT(base,reg);/*DYNAMICMEMORY*///uc=IORD(base,reg);/*NATIVEMEMORYSIZE*/returnuc;}u_charreg_write(base,reg,data){IOWR_8DIRECT(base,reg,data);/*DYNAMICMEMORY*///IOWR(base,reg,data);/*NATIVEMEMORYSIZE*/returndata;}/*voidgetState(void){unsignedcharold_cr,uc;unsignedchartsr,isr,rsr;unsignedcharrcr,tcr,dcr,imr;unsignedcharpstart,pstop;intiRet;old_cr=IORD_REDLOGIC_RTL8019_CR(RTL_BASE_ADDR);//changetopage0IOWR_REDLOGIC_RTL8019_CR(RTL_BASE_ADDR,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);tsr=IORD_REDLOGIC_RTL8019_TSR(RTL_BASE_ADDR);isr=IORD_REDLOGIC_RTL8019_ISR(RTL_BASE_ADDR);rsr=IORD_REDLOGIC_RTL8019_RSR(RTL_BASE_ADDR);//changetopage2IOWR_REDLOGIC_RTL8019_CR(RTL_BASE_ADDR,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK|REDLOGIC_RTL8019_CR_PS1_MSK);pstop=IORD_REDLOGIC_RTL8019_PSTOP(RTL_BASE_ADDR);pstart=IORD_REDLOGIC_RTL8019_PSTART(RTL_BASE_ADDR);rcr=IORD_REDLOGIC_RTL8019_RCR(RTL_BASE_ADDR);tcr=IORD_REDLOGIC_RTL8019_TCR(RTL_BASE_ADDR);dcr=IORD_REDLOGIC_RTL8019_DCR(RTL_BASE_ADDR);imr=IORD_REDLOGIC_RTL8019_IMR(RTL_BASE_ADDR);IOWR_REDLOGIC_RTL8019_CR(RTL_BASE_ADDR,old_cr);}*//*!*ResettheEthernetcontroller.*usehardwarelinee_rst*/intrtl8019_Reset(redlogic_rtl8019_if*dev){unsignedchari;unsignedcharj;/**Dothesoftwareresetbyreadingfromtheresetregisterfollowed*bywritingtotheresetregister.Waituntilthecontrollerenters*theresetstate.*/for(j=0;j<20;j++){IOWR_ALTERA_AVALON_PIO_DATA(E_RST_BASE,0x01);OSTimeDlyHMSM(0,0,1,0);IOWR_ALTERA_AVALON_PIO_DATA(E_RST_BASE,0x00);for(i=0;i<20;i++){OSTimeDlyHMSM(0,0,1,0);/**Wegottheresetbit.However,Ethernut1.1may*stillfailbecausetheNIChasn'tgotit'shardware*resetandthedatalinesremainintristate.Sowe*readnoiseinsteadoftheregister.Tosolvethis*problem,wewillverifytheNIC'sid.*/i=IORD_REDLOGIC_RTL8019_ISR(dev->base_addr);if((i&REDLOGIC_RTL8019_ISR_RST_MSK)!=0)return0;i=IORD_REDLOGIC_RTL8019_8019ID0(dev->base_addr);if(i==0x50)return0;i=IORD_REDLOGIC_RTL8019_8019ID1(dev->base_addr);if(i==0x70)return0;}}return-1;}/*-----------------------------------------------------------------------------------***redlogic_rtl8019_input():**Thisfunctionshouldbecalledwhenapacketisreadytoberead*fromtheinterface.Itusesthefunctionlow_level_input()that*shouldhandletheactualreceptionofbytesfromthenetwork*interface.***-----------------------------------------------------------------------------------*/staticvoidredlogic_rtl8019_input(redlogic_rtl8019_if*dev){structeth_hdr*ethhdr;structpbuf*p;structnetif*netif=dev->lwip_dev_list.dev.netif;/*movereceivedpacketintoanewpbuf*/p=low_level_input(dev);/*nopacketcouldberead,silentlyignorethis*/if(p==NULL)return;ethhdr=p->payload;switch(htons(ethhdr->type)){/*IPpacket?*/caseETHTYPE_IP:/**updateARPtable**ThecodewhichupdatestheARPtablesdoesnotappeartobethreadsafe*soI'veaddedaMUTEXaroundallcallstothearpcode**/sys_sem_wait(dev->arp_semaphore);etharp_ip_input(netif,p);sys_sem_signal(dev->arp_semaphore);/*skipEthernetheader*/pbuf_header(p,-(s16_t)sizeof(structeth_hdr));/*passtonetworklayer*/netif->input(p,netif);break;caseETHTYPE_ARP:/**passptoARPmodule**ThecodewhichupdatestheARPtablesdoesnotappeartobethreadsafe*soI'veaddedaMUTEXaroundallcallstothearpcode**/sys_sem_wait(dev->arp_semaphore);etharp_arp_input(netif,(structeth_addr*)&netif->hwaddr,p);sys_sem_signal(dev->arp_semaphore);break;default:pbuf_free(p);p=NULL;break;}}/*-----------------------------------------------------------------------------------***redlogic_rtl8019_init():**Shouldbecalledatthebeginningoftheprogramtosetupthe*networkinterface.Itcallsthefunctionlow_level_init()todothe*actualsetupofthehardware.***-----------------------------------------------------------------------------------*/err_tredlogic_rtl8019_init(structnetif*netif){err_tret_code;redlogic_rtl8019_if*dev=(redlogic_rtl8019_if*)netif->state;dev->lwip_dev_list.dev.netif=netif;LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("redlogic_rtl8019_init()\n"));netif->name[0]=IFNAME0;netif->name[1]=IFNAME1;netif->output=redlogic_rtl8019_output;netif->linkoutput=low_level_output;if(netif->state==NULL){ret_code=ERR_IF;gotoexit;}if(dev->bus_width!=8){printf("Thisdriverdoesn'tsupporttheEthernetaddoncardatpresent\n");ret_code=ERR_IF;gotoexit;}ret_code=low_level_init(dev);if(ret_code==ERR_OK){etharp_init();}else{free(netif->state);}exit:LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("redlogic_rtl8019_init()exit=%d\n",ret_code));returnret_code;}/**Firesupthenetworkinterface.NICinterrupts*shouldhavebeendisabledwhencallingthis*function.*/staticerr_tlow_level_init(redlogic_rtl8019_if*dev){unsignedchari;/**Needtohaveapointertoagenericelwip_dev*Thisissothattheget_mac_addrfunctioninterface*isdeviceagnostic*/alt_lwip_dev*lwip_dev=&dev->lwip_dev_list.dev;err_tret_code=ERR_OK;LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("low_level_init()\n"));/*SetMAChardwareaddresslength*/lwip_dev->netif->hwaddr_len=6;/*resetchip*/if(rtl8019_Reset(dev)){return-1;}/**Maskallinterruptsandclearanyinterruptstatusflagtosetthe*INTpinbacktolow.*/IOWR_REDLOGIC_RTL8019_IMR(dev->base_addr,0x00);IOWR_REDLOGIC_RTL8019_ISR(dev->base_addr,0xff);OSTimeDlyHMSM(0,0,1,0);/**Duringresetthenicloadeditsinitialconfigurationfroman*externaleeprom.Ontheethernutboardwedonothaveany*configurationeeprom,butsimplytiedtheeepromdatalineto*highlevel.Sowehavetoclearsomebitsintheconfiguration*register.Switchtoregisterpage3.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK|REDLOGIC_RTL8019_CR_PS0_MSK|REDLOGIC_RTL8019_CR_PS1_MSK);/**Thenicconfigurationregistersarewriteprotectedunlessboth*EEMbitsaresetto1.*/IOWR_REDLOGIC_RTL8019_9346CR(dev->base_addr,REDLOGIC_RTL8019_9346CR_EEM0_MSK|REDLOGIC_RTL8019_9346CR_EEM1_MSK);/**Networkmediahadbeensetto10Base2bythevirtualEEPROMand*willbesetnowtoautodetect.Thiswillinitiatealinktest.*Wedon'tforce10BaseT,becausethiswoulddisablethelinktest.*/IOWR_REDLOGIC_RTL8019_CONFIG2(dev->base_addr,REDLOGIC_RTL8019_CONFIG2_BSELB_MSK);/**Disablesleepandpowerdown.**ThevirtualEEPROM(resistortighttoVCC)willsetallbitsof*CONFIG3to1.Unfortunatelywearenotabletomodifythefull*duplexbit.TheonlysolutionistousearealEEPROMoremulate*one.*///reg_write(RTL_BASE_ADDR,NIC_PG3_CONFIG3,NIC_CONFIG3_LEDS0|NIC_CONFIG3_LEDS1);IOWR_REDLOGIC_RTL8019_CONFIG3(dev->base_addr,REDLOGIC_RTL8019_CONFIG3_LEDS0_MSK|REDLOGIC_RTL8019_CONFIG3_LEDS1_MSK);/**Reenablewriteprotectionofthenicconfigurationregisters*andwaitforlinktesttocomplete.*/IOWR_REDLOGIC_RTL8019_9346CR(dev->base_addr,0);OSTimeDlyHMSM(0,0,1,0);/**Switchtoregisterpage0andsetdataconfigurationregister*tobyte-wideDMAtransfers,normaloperation(noloopback),*sendcommandnotexecutedand8bytefifothreshold.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);IOWR_REDLOGIC_RTL8019_DCR(dev->base_addr,REDLOGIC_RTL8019_DCR_LS_MSK|REDLOGIC_RTL8019_DCR_FT1_MSK);/**Clearremotedmabytecountregister.*/IOWR_REDLOGIC_RTL8019_RBCR0(dev->base_addr,0);IOWR_REDLOGIC_RTL8019_RBCR1(dev->base_addr,0);/**Temporarilysetreceivertomonitormodeandtransmitterto*internalloopbackmode.Incomingpacketswillnotbestored*inthenicringbufferandnodatawillbesendtothenetwork.*/IOWR_REDLOGIC_RTL8019_RCR(dev->base_addr,REDLOGIC_RTL8019_RCR_MON_MSK);IOWR_REDLOGIC_RTL8019_TCR(dev->base_addr,REDLOGIC_RTL8019_TCR_LB0_MSK);/**Configurethenic'sringbufferpagelayout.*NIC_PG0_BNRY:Lastpageread.*NIC_PG0_PSTART:Firstpageofreceiverbuffer.*NIC_PG0_PSTOP:Lastpageofreceiverbuffer.*/IOWR_REDLOGIC_RTL8019_TPSR(dev->base_addr,NIC_FIRST_TX_PAGE);IOWR_REDLOGIC_RTL8019_BNRY(dev->base_addr,NIC_STOP_PAGE-1);IOWR_REDLOGIC_RTL8019_PSTART(dev->base_addr,NIC_FIRST_RX_PAGE);IOWR_REDLOGIC_RTL8019_PSTOP(dev->base_addr,NIC_STOP_PAGE);/**Onceagainclearinterruptstatusregister.*/IOWR_REDLOGIC_RTL8019_ISR(dev->base_addr,0xff);/**Switchtoregisterpage1andcopyourMACaddressintothenic.*Wearestillinstopmode.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK|REDLOGIC_RTL8019_CR_PS0_MSK);for(i=0;i<6;i++)reg_write(dev->base_addr,1+i,mac[i]);/**Clearmulticastfilterbitstodisableallpackets.*/for(i=0;i<8;i++)reg_write(dev->base_addr,8+i,0);/**Setcurrentpagepointertoonepageaftertheboundarypointer.*/IOWR_REDLOGIC_RTL8019_CURR(dev->base_addr,NIC_FIRST_RX_PAGE);/**Switchbacktoregisterpage0,remaininginstopmode.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);/**Takereceiveroutofmonitormodeandenableitforaccepting*broadcasts.*/IOWR_REDLOGIC_RTL8019_RCR(dev->base_addr,REDLOGIC_RTL8019_RCR_AB_MSK);/**Clearallinterruptstatusflagsandenableinterrupts.*/IOWR_REDLOGIC_RTL8019_ISR(dev->base_addr,0xff);/*Note:transmitterifpolled,thusnoNIC_IMR_PTXE*/IOWR_REDLOGIC_RTL8019_IMR(dev->base_addr,REDLOGIC_RTL8019_IMR_PRXE_MSK|REDLOGIC_RTL8019_IMR_RXEE_MSK|REDLOGIC_RTL8019_IMR_TXEE_MSK|REDLOGIC_RTL8019_IMR_OVWE_MSK);/**Fireupthenicbyclearingthestopbitandsettingthestartbit.*Toactivatethelocalreceivedmawemustalsotakethenicoutof*thelocalloopbackmode.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);IOWR_REDLOGIC_RTL8019_TCR(dev->base_addr,0);OSTimeDlyHMSM(0,0,1,0);/*maximumtransferunit*/dev->lwip_dev_list.dev.netif->mtu=1500;/*broadcastcapability*/dev->lwip_dev_list.dev.netif->flags=NETIF_FLAG_BROADCAST;dev->semaphore=sys_sem_new(1);if(dev->semaphore==NULL){ret_code=ERR_MEM;gotoexit;}dev->arp_semaphore=sys_sem_new(1);if(dev->arp_semaphore==NULL){ret_code=ERR_MEM;gotoexit;}if(alt_irq_register(dev->irq,dev,redlogic_rtl8019_irq)){ret_code=ERR_IF;gotoexit;}exit:LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("low_level_init()exit=%d\n",ret_code));returnret_code;}/*!*CompleteremoteDMA.*/staticvoidNicCompleteDma(unsignedintaddr){u_chari;/**Completeremotedma.*/IOWR_REDLOGIC_RTL8019_CR(addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);/**CheckthatwehaveaDMAcompleteflag.*/for(i=0;i<=20;i++)if(IORD_REDLOGIC_RTL8019_ISR(addr)&REDLOGIC_RTL8019_ISR_RDC_MSK)break;/**Resetremotedmacompleteflag.*/IOWR_REDLOGIC_RTL8019_ISR(addr,REDLOGIC_RTL8019_ISR_RDC_MSK);}/**WritedatablocktotheNIC.*/staticvoidNicWrite(unsignedintaddr,u_char*buf,u_shortlen){registeru_shortl=len-1;registeru_charih=(u_short)l>>8;registeru_charil=(u_char)l;if(!len)return;do{do{IOWR_REDLOGIC_RTL8019_DATA(addr,*buf++);}while(il--!=0);}while(ih--!=0);}/**ReaddatablockfromtheNIC.*/staticvoidNicRead(unsignedintaddr,u_char*buf,u_shortlen){registeru_shortl=len-1;registeru_charih=(u_short)l>>8;registeru_charil=(u_char)l;if(!len)return;do{do{*buf++=IORD_REDLOGIC_RTL8019_DATA(addr);}while(il--!=0);}while(ih--!=0);}/**redlogic_rtl8019_rx*Handleallthereceives*/voidredlogic_rtl8019_rx(alt_lwip_dev*dev){alt_u8isr;redlogic_rtl8019_if*lan_dev=(redlogic_rtl8019_if*)dev->netif->state;LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("rtl8019_rx()"));IOWR_REDLOGIC_RTL8019_CR(lan_dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);isr=IORD_REDLOGIC_RTL8019_ISR(lan_dev->base_addr);while(isr&REDLOGIC_RTL8019_ISR_PRX_MSK){redlogic_rtl8019_input(lan_dev);IOWR_REDLOGIC_RTL8019_CR(lan_dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);isr=IORD_REDLOGIC_RTL8019_ISR(lan_dev->base_addr);}/*Re-enableRXinterrupts*/IOWR_REDLOGIC_RTL8019_IMR(lan_dev->base_addr,REDLOGIC_RTL8019_IMR_PRXE_MSK|REDLOGIC_RTL8019_IMR_RXEE_MSK|REDLOGIC_RTL8019_IMR_TXEE_MSK|REDLOGIC_RTL8019_IMR_OVWE_MSK);}/*!*\briefFetchthenextpacketoutofthereceiveringbuffer.**Nicinterruptsmustbedisabledwhencallingthisfuntion.*//*-----------------------------------------------------------------------------------***low_level_input():**Shouldallocateapbufandtransferthebytesoftheincoming*packetfromtheinterfaceintothepbuf.***-----------------------------------------------------------------------------------*/staticstructpbuf*low_level_input(redlogic_rtl8019_if*dev){structpbuf*p=NULL,*q;structnic_pkt_headerhdr;u_shortcount;u_char*buf;u_charnextpg;u_charbnry;u_charcurr;u_shorti;u_chardrop=0;LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("low_level_input()\n"));/*wedon'twanttobeinterruptedbyNICowerflow*///irq_context=alt_irq_disable_all();/**Getthecurrentpagepointer.ItpointstothepagewheretheNIC*willstartsavingthenextincomingpacket.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK|REDLOGIC_RTL8019_CR_PS0_MSK);Delay16Cycles();curr=IORD_REDLOGIC_RTL8019_CURR(dev->base_addr);IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);/**Getthepointertothelastpagewereadfrom.Thefollowingpage*istheonewherewestartreading.Ifit'sequaltothecurrent*pagepointer,thenthere'snothingtoread.Inthiscasewereturn*anullpointer.*/if((bnry=IORD_REDLOGIC_RTL8019_BNRY(dev->base_addr)+1)>=NIC_STOP_PAGE)bnry=NIC_FIRST_RX_PAGE;if(bnry==curr){//alt_irq_enable_all(irq_context);return0;}/**ReadtheNICspecificpacketheader.*/IOWR_REDLOGIC_RTL8019_RBCR0(dev->base_addr,4);IOWR_REDLOGIC_RTL8019_RBCR1(dev->base_addr,0);IOWR_REDLOGIC_RTL8019_RSAR0(dev->base_addr,0);IOWR_REDLOGIC_RTL8019_RSAR1(dev->base_addr,bnry);buf=(u_char*)&hdr;IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD0_MSK);Delay16Cycles();for(i=0;i<sizeof(structnic_pkt_header);i++){*buf=IORD_REDLOGIC_RTL8019_DATA(dev->base_addr);buf++;}NicCompleteDma(dev->base_addr);/**Checkpacketlength.Silentlydiscardpacketsofillegalsize.*/if(hdr.ph_size<60+sizeof(structnic_pkt_header)||/**/hdr.ph_size>1514+sizeof(structnic_pkt_header)){drop=1;}/**Calculatethepageofthenextpacket.Ifitdiffersfromthe*pointerinthepacketheader,wereturnwitherrorcode.*/nextpg=bnry+(hdr.ph_size>>8)+((hdr.ph_size&0xFF)!=0);if(nextpg>=NIC_STOP_PAGE){nextpg-=NIC_STOP_PAGE;nextpg+=NIC_FIRST_RX_PAGE;}if(nextpg!=hdr.ph_nextpg){u_charnextpg1=nextpg+1;if(nextpg1>=NIC_STOP_PAGE){nextpg1-=NIC_STOP_PAGE;nextpg1+=NIC_FIRST_RX_PAGE;}if(nextpg1!=hdr.ph_nextpg){returnNULL;}nextpg=nextpg1;}/**Checkpacketstatus.Itshouldhavesetbit0,but*evenwithoutthisbitpacketsseemtobeOK.*/if(!drop&&((hdr.ph_status&0x0E)==0)){/**AllocateaNETBUF.*Omitthefcs.*/count=hdr.ph_size-4;/*Weallocateapbufchainofpbufsfromthepool.*/p=pbuf_alloc(PBUF_RAW,count,PBUF_POOL);if(p!=NULL){/**Setremotedmabytecountand*startaddress.Don'treadthe*headeragain.*/IOWR_REDLOGIC_RTL8019_RBCR0(dev->base_addr,count);IOWR_REDLOGIC_RTL8019_RBCR1(dev->base_addr,count>>8);IOWR_REDLOGIC_RTL8019_RSAR0(dev->base_addr,sizeof(structnic_pkt_header));IOWR_REDLOGIC_RTL8019_RSAR1(dev->base_addr,bnry);/**Performtheread.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD0_MSK);Delay16Cycles();for(q=p;q!=NULL;q=q->next){NicRead(dev->base_addr,q->payload,q->len);}NicCompleteDma(dev->base_addr);}}/**Setboundaryregistertothelastpageweread.*Thisalsodropspacketswitherrors*/if(--nextpg<NIC_FIRST_RX_PAGE)nextpg=NIC_STOP_PAGE-1;IOWR_REDLOGIC_RTL8019_BNRY(dev->base_addr,nextpg);returnp;}/*!*Loadapacketintothenic'stransmitringbuffer.***parambaseNIChardwarebaseaddress.*paramnbNetworkbufferstructurecontainingthepackettobesent.*Thestructuremusthavebeenallocatedbyaprevious*callNutNetBufAlloc().**return0onsuccess,-1incaseofanyerrors.Errors*willautomaticallyreleasethenetworkbuffer*structure.*/staticerr_tlow_level_output(structnetif*netif,structpbuf*p){structpbuf*q;redlogic_rtl8019_if*dev=netif->state;u_shorti;u_charpadding=0;unsignedshortintsize;LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("low_level_output(%#x)\n",p));size=0;for(q=p;q!=NULL;q=q->next){size+=q->len;}/**Calculatethenumberofbytestobesend.Donot*sendpacketslargerthan1514bytes.**Thepreviousversionwaswrongbyspecifyingamaximum*of1518,becauseitdidn'ttaketheCRCintoaccount,*whichisgeneratedbythehardwareandautomatically*appended.ThankstoBengtFlorin,whodiscoveredthis.*/if(size>1514)return-1;/**Thecontrollerwillnotappendpadbytes,*sowehavetodothis.*/if(size<60){padding=(u_char)(60-p->tot_len);size=60;}/**BengtFlorinintroducespollingmodeforthetransmitter.Be*aware,thatthismayintroduceotherproblems.Ifahigh*prioritythreadiswaitingforthetransmitter,itmayhold*theCPUformorethan1.2millisecondsinworstcases.*//*while(NICINB(NIC_CR)&NIC_CR_TXP)NutThreadYield();*//*wedon'twanttobeinterruptedbyNICowerflow*///irq_context=alt_irq_disable_all();/**Setremotedmabytecount*andstartaddress.*/IOWR_REDLOGIC_RTL8019_RBCR0(dev->base_addr,size);IOWR_REDLOGIC_RTL8019_RBCR1(dev->base_addr,size>>8);IOWR_REDLOGIC_RTL8019_RSAR0(dev->base_addr,0);IOWR_REDLOGIC_RTL8019_RSAR1(dev->base_addr,NIC_FIRST_TX_PAGE);/**Peformthewrite.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD1_MSK);/**TransfertheEthernetframe.*/for(q=p;q!=NULL;q=q->next){NicWrite(dev->base_addr,q->payload,q->len);}/**Addpadbytes.*/for(i=0;i<padding;i++)IOWR_REDLOGIC_RTL8019_DATA(dev->base_addr,0);/**Completeremotedma.*/NicCompleteDma(dev->base_addr);/**Numberofbytestobetransmitted.*/IOWR_REDLOGIC_RTL8019_TBCR0(dev->base_addr,(size&0xff));IOWR_REDLOGIC_RTL8019_TBCR1(dev->base_addr,((size>>8)&0xff));/**Firstpageofpackettobetransmitted.*/IOWR_REDLOGIC_RTL8019_TPSR(dev->base_addr,NIC_FIRST_TX_PAGE);/**Starttransmission.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_TXP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);LWIP_DEBUGF(NETIF_DEBUG|DBG_TRACE,("low_level_ouptput()returnOK\n"));return0;}/**\briefHandleNICoverflows.**Whenareceiverbufferoverflowoccurs,theNICwilldeferanysubsequent*actionuntilproperlyrestarted.**Thisroutineiscalledwithininterruptcontext,whichintroducesabig*problem.Itwaitsforthelasttransmissiontofinish,whichmaytake*severalmilliseconds.SinceNut/OS3.5,wedonotsupportnestedinterrupts*onAVRsystemsanymore.Sothisroutinemaynowincreaseinterrupt*latencyinanunacceptableway.Thesolutionmightbetohandleoverflows*inthereceiverthread.**Inanycase,thisroutinesneedsamajorredesign.Butithasbeen*testedinitscurrentformtogracefullywithstandpingfloods.Thanks*toBengtFlorinforcontributinghiscode,whichprovidesmuchmore*stabilitythanitspredecessor.*/u_charNicOverflow(redlogic_rtl8019_if*dev){u_charcr;u_charresend=0;u_charcurr;/**Waitforanytransmissioninprogress.Savethecommandregister,*sowecanlaterdetermine,ifNICtransmitterhasbeeninterrupted.*orreceptioninprogress.*/while(IORD_REDLOGIC_RTL8019_CR(dev->base_addr)&REDLOGIC_RTL8019_CR_TXP_MSK);cr=IORD_REDLOGIC_RTL8019_CR(dev->base_addr);/**Getthecurrentpagepointer.ItpointstothepagewheretheNIC*willstartsavingthenextincomingpacket.*/IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK|REDLOGIC_RTL8019_CR_PS0_MSK);curr=IORD_REDLOGIC_RTL8019_CURR(dev->base_addr);IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);/*Clearremotebytecountregister.*/IOWR_REDLOGIC_RTL8019_RBCR0(dev->base_addr,0);IOWR_REDLOGIC_RTL8019_RBCR1(dev->base_addr,0);/*Checkforanyincompletetransmission.*/if((cr&REDLOGIC_RTL8019_CR_TXP_MSK)&&((IORD_REDLOGIC_RTL8019_ISR(dev->base_addr)&(REDLOGIC_RTL8019_ISR_PTX_MSK|REDLOGIC_RTL8019_ISR_TXE_MSK))==0)){resend=1;}/*EnterloopbackmodeandrestarttheNIC.*/IOWR_REDLOGIC_RTL8019_TCR(dev->base_addr,REDLOGIC_RTL8019_TCR_LB0_MSK);IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);/**Discardallpacketsfromthereceiverbuffer.Setboundary*registertothelastpageweread.*/if(--curr<NIC_FIRST_RX_PAGE){curr=NIC_STOP_PAGE-1;}IOWR_REDLOGIC_RTL8019_BNRY(dev->base_addr,curr);/*Switchfromloopbacktonormalmodemode.*/IOWR_REDLOGIC_RTL8019_TCR(dev->base_addr,0);/*Re-invokeanyinterruptedtransmission.*/if(resend){IOWR_REDLOGIC_RTL8019_CR(dev->base_addr,REDLOGIC_RTL8019_CR_STA_MSK|REDLOGIC_RTL8019_CR_TXP_MSK|REDLOGIC_RTL8019_CR_RD2_MSK);}/*Finallycleartheoverflowflag*/IOWR_REDLOGIC_RTL8019_ISR(dev->base_addr,REDLOGIC_RTL8019_ISR_OVW_MSK);returnresend;}/**\briefNICinterruptentry.*/voidredlogic_rtl8019_irq(void*context,alt_u32interrupt){u_charisr;intrx_frame_errors;intrx_crc_errors;intrx_missed_errors;redlogic_rtl8019_if*dev=(redlogic_rtl8019_if*)context;isr=IORD_REDLOGIC_RTL8019_ISR(dev->base_addr);IOWR_REDLOGIC_RTL8019_ISR(dev->base_addr,isr);/**Recoverfromreceivebufferoverflow.Thismaytakesome*time,soweenableglobalinterruptsbutkeepNIC*interruptsdisabled.*/if(isr&REDLOGIC_RTL8019_ISR_OVW_MSK){NicOverflow(dev);}else{/**Ifthisisatransmitinterrupt,thenapackethasbeensent.*Sowecanclearthetransmitterbusyflagandwakeupthe*transmitterthread.*/if(isr&REDLOGIC_RTL8019_ISR_TXE_MSK);/**Ifthisisareceiveinterrupt,thenwakeupthereceiver*thread.*/if(isr&REDLOGIC_RTL8019_ISR_PRX_MSK){sys_mbox_post(rx_mbox,&dev->lwip_dev_list.dev);}if(isr&REDLOGIC_RTL8019_ISR_RXE_MSK){rx_frame_errors+=IORD_REDLOGIC_RTL8019_CNTR0(dev->base_addr);rx_crc_errors+=IORD_REDLOGIC_RTL8019_CNTR1(dev->base_addr);rx_missed_errors+=IORD_REDLOGIC_RTL8019_CNTR2(dev->base_addr);}}}/*-----------------------------------------------------------------------------------***redlogic_rtl8019_output():**ThisfunctioniscalledbytheTCP/IPstackwhenanIPpacket*shouldbesent.Itcallsthefunctioncalledlow_level_output()to*dotheactualltransmissionofthepacket.***-----------------------------------------------------------------------------------*/staticerr_tredlogic_rtl8019_output(structnetif*netif,structpbuf*p,structip_addr*ipaddr){err_terr;redlogic_rtl8019_if*dev=(redlogic_rtl8019_if*)netif->state;sys_sem_wait(dev->arp_semaphore);/**resolvehardwareaddress,thensend(orqueue)packet*ThecodewhichupdatestheARPtablesdoesnotappeartobethreadsafe*soI'veaddedaMUTEXaroundallcallstothearpcode**/err=etharp_output(netif,ipaddr,p);sys_sem_signal(dev->arp_semaphore);returnerr;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -