📄 ne2000.c
字号:
do
{
memcpy(FramePtr, buf_ptr->data_ptr, buf_ptr->data_len);
length += buf_ptr->data_len;
FramePtr += buf_ptr->data_len;
/* Move on to the next buffer. */
buf_ptr = buf_ptr->next_buffer;
} while (buf_ptr != 0);
/* make sure packet is within legal size */
if (length < ETHER_MIN_LEN)
length = ETHER_MIN_LEN;
if (length > ETHERSIZE)
{
//DEBUG_ERROR("ne2000xmit - length is too large: length = ",
// EBS_INT1, length, 0);
length = ETHERSIZE; /* what a terriable hack! */
}
/* Send requires interrupts disabled. So the ISR does not change
the register back out from under us (particularly the dma
pointer) */
/* Disable interrupts */
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
/* Set NIC to page 0 registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/* mask off all isr's */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), 0);
NU_Control_Interrupts(previous_int_value);
ret_val = 0;
if (ne2000_pio_write_pkt(sc, (PFCBYTE)TEMP_BUF_T, length, sc->mem_start))
{
/* Set NIC for page 0 register access. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/* Set TX buffer start page. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TPSR), sc->tx_page_start);
/* Set TX length. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TBCR0), length);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TBCR1), length >> 8);
/* Set page 0, remote DMA complete, transmit packet, and *start*. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_TXP | NE2000_CR_STA);
}
else
{
//ret_val = ENETDOWN;
}
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS); /* Disable interrupts */
/* Set NIC to page 0 registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/* Turn ints back on */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_IMR), NORMAL_NE2000_INTS);
NU_Control_Interrupts(previous_int_value);
return(ret_val);
}
/************************************************************************
* FUNCTION
*
* Rtl8019_Receive
*
* DESCRIPTION
*
* Processes a frame into Net buffers that can be used by the
* upper layers. Once the frame is processed, the Ether_Rcv HISR
* is activated, which will eventually let the upper layers know
* about the new packets.
*
* AUTHOR
*
* Meter Chen
*
* INPUTS
*
* DV_DEVICE_ENTRY *device Pointer to the device structure.
*
* OUTPUTS
*
* None.
*
************************************************************************/
STATUS Rtl8019_Receive(DV_DEVICE_ENTRY *device)
{
NET_BUFFER *buf_ptr;
UINT32 pkt_size, bytes_left;
/* This function is responsible for moving received packets from
** shared memory into the packet buffers. Start by allocating a
** buffer (from the Free List) into which the received packet
** will be copied.
*******************************************************************/
/* Copy the Rx Packet into as many NET Buffers as it takes! */
/* Get the packet size fron the RxFD & allocate buffer(s) for it! */
pkt_size = et_data_len;
/* Allocate a buffer (or a chain of buffers) into which the Rx
** packet can be copied! */
if (pkt_size <= NET_PARENT_BUFFER_SIZE) /* One buffer case! */
{
buf_ptr = MEM_Buffer_Dequeue(&MEM_Buffer_Freelist);
}
else /* More than one buffer is needed! */
{
buf_ptr = MEM_Buffer_Chain_Dequeue(&MEM_Buffer_Freelist, pkt_size);
}
if (buf_ptr == NU_NULL)
{
//NU_Tcp_Log_Error (TCP_PARTITION_ERROR, TCP_RECOVERABLE,
// __FILE__, __LINE__);
/* Return that there was an error with a packet reception */
return(-1);
}
else
{
/* Put the head of the chain (or only one) on the incoming
** packet buffer list */
MEM_Buffer_Enqueue (&MEM_Buffer_List, buf_ptr);
/* Get the total number of bytes that must be copied */
bytes_left = pkt_size;
/* This sets Total Packet Length in the first (or only) buffer! */
buf_ptr->mem_total_data_len = pkt_size;
/* Set the device into the buffer header! */
buf_ptr->mem_buf_device = device;
/* Clear the flags field! */
buf_ptr->mem_flags = 0;
if (pkt_size <= NET_PARENT_BUFFER_SIZE) /* One buffer case. */
{
/* The MEM Buffer Dequeue function returns a Ptr to the Buffer's */
/* Data area at the TOP of the Buffer. */
buf_ptr->data_ptr = (UINT8 *) buf_ptr;
/* Data in this buffer, same as total for this case. */
buf_ptr->data_len = pkt_size;
/* Do the copy. */
memcpy(buf_ptr->data_ptr, (UINT8 *)et_data_ptr, pkt_size);
}
else /* More than one NET Buffer required! Pack the first one and */
{ /* enter the while loop to fill the remaining ones needed. */
/* Data area in the first buffer is less than in the rest. */
buf_ptr->data_len = NET_PARENT_BUFFER_SIZE;
/* The Ptr is to the Buffer's Data area at the TOP of the */
/* Buffer, so copy the buf_ptr to the Buffer's Data Ptr. */
buf_ptr->data_ptr = (UINT8 *) buf_ptr;
/* Do the copy. */
memcpy(buf_ptr->data_ptr, (UINT8 *)et_data_ptr,
NET_PARENT_BUFFER_SIZE);
bytes_left -= NET_PARENT_BUFFER_SIZE;
/* Advance data ptr to next block start. */
et_data_ptr += NET_PARENT_BUFFER_SIZE;
while (bytes_left > 0)
{
/* Move to the next buffer in the chain */
buf_ptr = (NET_BUFFER *) buf_ptr->next_buffer;
/* The Ptr is to the Buffer's Header start, NOT the Data area */
/* at the TOP of the Buffer, so copy the Adjusted Ptr to the */
/* Buffer's Data Ptr. */
buf_ptr->data_ptr = (UINT8 *) buf_ptr;
/* See if a Full Buffer is needed! Note that these buffers */
/* hold more data (0x218/536) since the me_bufhdr is not */
/* needed! */
if (bytes_left > NET_MAX_BUFFER_SIZE)
{
buf_ptr->data_len = NET_MAX_BUFFER_SIZE;
bytes_left -= NET_MAX_BUFFER_SIZE;
/* Do the copy. */
memcpy(buf_ptr->data_ptr, (UINT8 *)et_data_ptr,
buf_ptr->data_len);
/* Advance data ptr to next block start! */
et_data_ptr += NET_MAX_BUFFER_SIZE;
}
else
{
buf_ptr->data_len = bytes_left;
bytes_left = 0;
/* Do the copy. */
memcpy(buf_ptr->data_ptr,
(UINT8 *)et_data_ptr,
buf_ptr->data_len);
}
} /* END: while (bytes_left > 0) */
} /* END: else (more than one NET Buffer needed) */
if (!Hisr_Activated)
{
Hisr_Activated = 1;
/* Activate the Receive HISR. */
NU_Activate_HISR (&Ether_Rcv);
}
return (NU_SUCCESS);
}
} /* END */
/************************************************************************
* FUNCTION
*
* Rtl8019_Ioctl
*
* DESCRIPTION
*
* Called by group management functions to add or remove an
* address from the CAM.
*
* AUTHOR
*
* MeterChen
*
* INPUTS
*
* DV_DEVICE_ENTRY *dev Pointer to the device
* structure for this device.
*
* INT option Option to perform (Add or
* Delete).
*
* DV_REQ *d_req Pointer to request structure.
*
* OUTPUTS
*
* STATUS (0) NU_SUCCESS
* (-1) CAM_FULL
*
************************************************************************/
STATUS Rtl8019_Ioctl(DV_DEVICE_ENTRY *dev, INT option, DV_REQ *d_req)
{
#if 0
STATUS status = NU_SUCCESS;
UINT32 slot = 0x00000002;
UINT8 entry = 1;
UINT8 multi_addr[6] = {0,0,0,0,0,0};
UINT32 CamEnReg;
/* Convert the IP address to a multicast ethernet address. */
NET_MAP_IP_TO_ETHER_MULTI(&d_req->dvr_addr, multi_addr);
switch (option)
{
case DEV_ADDMULTI:
CamEnReg = CAMEN;
/* Compare each bit in the CAMEN to find an available entry. */
while (CamEnReg & (slot & 0x000FFFFF))
{
slot <<= 1;
entry++;
}
if (slot & 0x000FFFFE)
{
/* Join the ethernet multicast group. */
status = NET_Add_Multi(dev, d_req);
/* A status of NU_RESET means the operation was a success. */
if (status == NU_RESET)
{
KS5_CamWrite(entry, multi_addr);
}
else
break;
/* Enable the new address. */
CAMEN = (CamEnReg | slot);
status = NU_SUCCESS;
}
else
/* Only 21 entries allowed. */
status = CAM_FULL;
break;
case DEV_DELMULTI :
/* Convert the IP address to a multicast ethernet address. */
NET_MAP_IP_TO_ETHER_MULTI(&d_req->dvr_addr, multi_addr);
/* Delete the ethernet multicast group. */
status = NET_Del_Multi(dev, d_req);
/* A status of NU_RESET means the operation was a success. */
if (status == NU_RESET)
{
/* Find the multicast entry in the CAM */
for (entry = 1; memcmp(KS5_CamRead(entry), multi_addr, 6) != 0
&& entry <= 20; entry++)
{
slot <<= 1;
}
/* Address not found */
if (entry > 20)
break;
else
{
/* Address found... just disable its CAMEN slot. */
CAMEN = (CamEnReg & ~slot);
status = NU_SUCCESS;
}
break;
}
/* Fall through if NET_Del_Multi() failed. */
default :
status = NU_INVAL;
break;
}
return (status);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -