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

📄 rtl8019.c

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	memcpy(temp_tx_buf, buf, count);
	#endif /* IP_STACK_LWIP */

	count = p->tot_len;
	if (count < 64)
	{
		while (count < 64 )
		{
			temp_tx_buf[count] = 0;
			count ++;
		}
	}

	/* close receive interrupt */
	NE_CR = CMD_PAGE2 | CMD_NODMA | CMD_RUN;
	isr = NE_IMR;
	isr &= ~ISR_PRX;
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
	NE_IMR = isr;

	NE_ISR = ISR_RDC;

    /* set the length of send */
	NE_RBCR0 = count & 0xff;
	NE_RBCR1 = (count >> 8) & 0xff;

    /* the address on NIC to store */
	NE_RSAR0 = XMIT_START & 0xff;
	NE_RSAR1 = (XMIT_START >> 8) & 0xff;

	/* start to transmit */
	NE_CR = CMD_PAGE0 | CMD_WRITE | CMD_RUN;

	ne_copyout(p->len, p->payload);
	
	/* wait for remote dma to complete */
	while((u_char)(NE_ISR & ISR_RDC) == 0 );

	/* clear RDC */
	NE_ISR = ISR_RDC;

	/* issue the transmit command.(start local dma) */
 	NE_TPSR = XMIT_START >> 8;
	NE_TBCR0 = count & 0xff;
	NE_TBCR1 = (count >> 8) & 0xff;

	/* start transmission */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_XMIT | CMD_RUN;

	/* reopen receive interrupt */
	NE_CR = CMD_PAGE2 | CMD_NODMA | CMD_RUN;
	isr = NE_IMR;
	isr |= ISR_PRX;
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
	NE_IMR = isr;

	rt_hw_interrupt_enable(temp);

	return count;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_poll_start
+------------------------------------------------------------------------------
| Description : Starts realtek 8019 ethernet interface to poll mode
+------------------------------------------------------------------------------
*/
int rtl8019_poll_start()
{
	/* select PAGE0 and close nic */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;

	/* mask all interrupts */
	NE_IMR = 0;

	/* clear ISR */
	NE_ISR = 0xff;

	rtl8019_device.flags |= FLG_POLL;
	return 0;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_poll_stop
+------------------------------------------------------------------------------
| Description : Stops realtek 8019 ethernet interface poll mode
+------------------------------------------------------------------------------
*/
int rtl8019_poll_stop()
{
	/* select PAGE0 and start the nic */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;

	/* set interrupt mask reg */
	NE_IMR = ISR_OVW | ISR_TXE | ISR_PTX | ISR_PRX;

	/* clear ISR */
	NE_ISR = 0xff;

	rtl8019_device.flags &= ~FLG_POLL;

	return 0;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_poll_recv
+------------------------------------------------------------------------------
| Description : Receives some data buffer from realtek 8019 ethernet interface
|
| Parameters  : d,
|               buf,
|               count,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_poll_recv(int d, char *buf, size_t count)
{
	u_char isr; //, current_point;
	u_short received_length;

	if ( !rtl8019_device.flags & FLG_POLL ) return -1;

	/* select to PAGE0 */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;

	received_length = 0;
	while ( 1 )
	{
		isr = NE_ISR;
		if ( isr & ISR_OVW )	/* overflow */
		{
			NE_CR = CMD_STOP;

			/* delay */

			NE_RBCR0 = 0;
			NE_RBCR1 = 0;
#if 0
			NE_TCR = TCR_LOOP_INT;
			do
			{
				current_point = nic_to_pc();
			} while ( NE_BNRY != current_point );
#endif
		}

		if ( isr & ISR_PRX )	/* packet received */
		{
#if 0
			do
			{
				NE_ISR = ISR_PRX;
				current_point = nic_to_pc();
			} while ( NE_BNRY != current_point );
#endif
		}

		if ( !(isr & ISR_PRX) )
		{
			return 0; /* done */
		}
	}
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_poll_send
+------------------------------------------------------------------------------
| Description : Sends some data buffer to realtek 8019 ethernet interface
|
| Parameters  : d,
|               buf,
|               count,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
int rtl8019_poll_send(int d, const char *buf, size_t count)
{
	u_short pad_length, packet_length;

	/* parameters check */
	if ( !rtl8019_device.flags & FLG_POLL ) return -1;
	if(count > 1514) return -1;

	/* waiting for transmit */
	while ( NE_CR ==  (CMD_NODMA | CMD_XMIT | CMD_RUN)) ;

	/* setup to transfer the packet contents to the NIC RAM. */
	if (count < 60) /* packet_length muse not less than 60 */
	{
		pad_length = 60 - count;
		packet_length = 60;
	}
	else
	{
		pad_length = 0;
		packet_length = count;
	}

	NE_RSAR0 = XMIT_START & 0xff;
	NE_RSAR1 = (XMIT_START >> 8) & 0xff;
	NE_RBCR0 = packet_length & 0xff;
	NE_RBCR1 = (packet_length >> 8) & 0xff;

	/* write data */
	NE_CR = CMD_PAGE0 | CMD_WRITE | CMD_RUN;

	ne_copyout(packet_length - pad_length, (u_char*)buf);

	/* write padding */
	while (pad_length -- > 0) NE_DMA = 0;

	while (!NE_ISR & ISR_RDC) ;

	NE_ISR = ISR_RDC;
	NE_TPSR = XMIT_START >> 8;
	NE_TBCR0 =  packet_length & 0xff;
	NE_TBCR1 = (packet_length >> 8) & 0xff;

	/* start transmission */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_XMIT | CMD_RUN;

	return packet_length;
}

/*
+------------------------------------------------------------------------------
| Function    : rtl8019_isr
+------------------------------------------------------------------------------
| Description : The realtek 8019 ethernet interface interrupt service rountine
|
| Parameters  : d,
|               buf,
|               count,
| Returns     : the status of successful(0) or unsuccessful(negative).
+------------------------------------------------------------------------------
*/
void rtl8019_isr(int irqno)
{
	u_char isr, curr;

	//RTL8019_DEBUG("rtl8019 ISR coming");

	/* close nic */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;

	isr = NE_ISR;

	/* if ram overflow interrupt */
	if (isr & ISR_OVW )
	{
		RTL8019_DEBUG("overflow");

		/* clear interrupt */
		NE_ISR = ISR_OVW;
	}

	/* if Tx error, NIC abort tx due to excessive collisions */
	if (isr & ISR_TXE)
	{
		RTL8019_DEBUG("Tx error");

		/* clear interrupt */
		NE_ISR = ISR_TXE;

		rtl8019_device.stats.tx_errors ++;
	}

	/* if Rx error , reset BNRY pointer to CURR (use SEND PACKET mode) */
	if (isr & ISR_RXE)
	{
		RTL8019_DEBUG("Rx error");

		/* clear interrupt */
		NE_ISR = ISR_RXE;

		NE_CR = CMD_PAGE1 | CMD_NODMA | CMD_STOP;
		curr = NE_CURR;
		NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
		NE_BNRY = curr;

		rtl8019_device.stats.rx_errors ++;
	}

	/* no errors */
	if (isr & ISR_PRX)
	{
		//RTL8019_DEBUG("Receive a packet, add a net task job");

		NE_ISR = ISR_PRX;		/* clear interrupt */

		if(net_task_job_add(rtl8019_rx_job, RT_NULL) != RT_EOK) 
			rt_kprintf("RTL8019 net_task_job_add failed.\n");
	}

	/* Transfer complete, do nothing here */
	if( isr & ISR_PTX)
	{
		//RTL8019_DEBUG("Transfer complete");

		/* clear interrupt */
		NE_ISR = ISR_PTX;
		rtl8019_device.stats.tx_packets++;
	}

	NE_CR  = CMD_PAGE0 | CMD_NODMA | CMD_STOP;

	/* clear interrupt */
	NE_ISR = 0xff;		

	/* open nic for next packet */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;

//	RTL8019_DEBUG("Open rtl8019 ISR again");
}

//static char temp_rx_buf[1600];
static void rtl8019_rx_job(void *param)
{
	u_short packet_length, len;
	u_char pld_header[18]; /* temp storage for ethernet headers */
	u_char curr, bnry;
	struct pbuf *p, *q;
	u_char *payload;

	NE_CR = CMD_PAGE1 | CMD_NODMA | CMD_STOP;
	curr  = NE_CURR;
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
	bnry  = NE_BNRY;
	
	//rt_kprintf("to do rx job\n");

	/* receive all of packet */
	while (curr != bnry)
	{
		/* clear ISR status */
		NE_ISR   = ISR_RDC;
		NE_RBCR1 = 0x0f;
		NE_CR    = CMD_PAGE0 | CMD_SEND | CMD_RUN;

		/* get the first 18 bytes from nic */
		ne_copyin(18, pld_header);

		/* store real length, set len to packet length - header */
		/* ethernet packet header */
		packet_length = ((unsigned int) pld_header[2] | (pld_header[3] << 8 ));

		//memcpy(temp_rx_buf, pld_header + 4, 14);
		//ne_copyin(packet_length - 14, temp_rx_buf + 14);

		#ifdef IP_STACK_LWIP
		{
			void *pbuf;
			pbuf = (void *)lwip_buffer_alloc(packet_length);
			if(pbuf)
			{
				lwip_buffer_copy_from(temp_rx_buf, packet_length, pbuf);
				lwip_ethpkt_notify(pbuf);
			}
			else
			{
				/* no more PBUF resource, discard packet in buffer. */
				ne_discard(packet_length - 14);
			}
		}

		++rtl8019_device.stats.rx_packets;
		#endif /* IP_STACK_LWIP */

		p = pbuf_alloc(PBUF_LINK, packet_length, PBUF_POOL);

		if(p != RT_NULL) {
			/* We iterate over the pbuf chain until we have read the entire
	      		 packet into the pbuf. */
	           	// This assumes a minimum pbuf size of 14 ... a good assumption
	           	memcpy(p->payload, pld_header + 4, 14);
		
			for(q = p; q != RT_NULL; q= q->next)
			{
				/* Read enough bytes to fill this pbuf in the chain. The
				avaliable data in the pbuf is given by the q->len variable. */
				/* read data into(q->payload, q->len); */
				//First 14 bytes are already there, skip them
	      	
				payload = q->payload;
				len = q->len;

				if (q == p)
				{
					payload += 14;
					len -=14;
				}
				ne_copyin(len,payload);
			}
		}
		else 
		{
			rt_kprintf("NULL\n");
			/* no more PBUF resource, Discard packet in buffer. */
			ne_discard(packet_length-14);
  		}
		
		++rtl8019_device.stats.rx_packets;
		/*RTL8019_DEBUG("received %d size network packet, total %d network packets\n", 
				packet_length, rtl8019_device.stats.rx_packets);*/
		
		/* Send packet to upper layer */
		if (ethernetif_input(p, &rtl8019if) != RT_EOK) 
		{
			rt_kprintf("send packet to lwip error\n");
		}

		NE_CR = CMD_PAGE1 | CMD_NODMA | CMD_STOP;
		curr  = NE_CURR;
		NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
		bnry  = NE_BNRY;
	}

	NE_ISR = ISR_PRX;		/* clear interrupt */

	/* open nic for next packet */
	NE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
}

⌨️ 快捷键说明

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