📄 rtl8019.c
字号:
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 + -