📄 ldc.c
字号:
/*************************************************************************
*
* Copyright (c) 1993 - 2001 Accelerated Technology, Inc.
*
* PROPRIETARY RIGHTS of Accelerated Technology are involved in the
* subject matter of this material. All manufacturing, reproduction,
* use, and sales rights pertaining to this subject matter are governed
* by the license agreement. The recipient of this software implicitly
* accepts the terms of the license.
*
*************************************************************************/
/*************************************************************************
*
* FILE NAME VERSION
*
* ldc.c 4.4
*
* COMPONENT
*
* LD - Loopback Device
*
* DESCRIPTION
*
* This module supplies the functionality needed to implement a
* loopback device. It is responsible for looping all transmitted
* packets back up the stack. It also provides an Ioctl function
* to be used by the stack for multicasting support. This way
* multicast packets can be loopedback too.
*
* DATA STRUCTURES
*
* None
*
* FUNCTIONS
*
* LDC_Init
* LDC_TX_Packet
* LDC_Ioctl
*
* DEPENDENCIES
*
* nucleus.h
* target.h
* externs.h
* nerrs.h
* dev.h
* ld_defs.h
* ld_extr.h
*
*************************************************************************/
#include "plus/nucleus.h"
#include "net/target.h"
#include "net/inc/externs.h"
#include "net/inc/nerrs.h"
#include "net/inc/dev.h"
#include "net/inc/ld_defs.h"
#include "net/inc/ld_extr.h"
#if (INCLUDE_SNMP == NU_TRUE)
#include SNMP_GLUE
#endif
/*************************************************************************
*
* FUNCTION
*
* LDC_Init
*
* DESCRIPTION
*
* Initializes the loopback device. Sets up the correct values in
* the device structure, including the function pointers that hook
* this driver to the stack.
*
* INPUTS
*
* *dev_ptr Pointer to the device structure for
* the loopback device.
*
* OUTPUTS
*
* STATUS NU_SUCCESS
*
*
************************************************************************/
STATUS LDC_Init (DV_DEVICE_ENTRY *dev_ptr)
{
/* Fill in device specific information. */
dev_ptr->dev_type = DVT_LOOP;
dev_ptr->dev_addrlen = LD_ADDRESS_LENGTH;
dev_ptr->dev_hdrlen = LD_HEADER_LENGTH;
dev_ptr->dev_mtu = LD_MTU;
dev_ptr->dev_flags |= (DV_MULTICAST);
/* The vector is not important for the loopback device
since it does not generate interrupts. It does, though,
need to be different from any other registered NIC so that
they can be independantly identified. Here we will just make
it a large value that should not make sense for any interrupt
controller.
*/
dev_ptr->dev_vect = (unsigned short)LD_INVALID_VECTOR;
/* Initialize the functions pointers that link the stack
and the driver together. Since this is a loop back device
we do not make use of all of these. */
dev_ptr->dev_start = LDC_TX_Packet;
dev_ptr->dev_ioctl = LDC_Ioctl;
dev_ptr->dev_output = NET_Ether_Send;
dev_ptr->dev_input = NET_Ether_Input;
/* Init the basic interface information. */
SNMP_ifDescr(dev_ptr->dev_index, "Nucleus NET Software Loopback Interface");
SNMP_ifType(dev_ptr->dev_index, 24);
SNMP_ifMtu(dev_ptr->dev_index, dev_ptr->dev_mtu);
SNMP_ifSpeed(dev_ptr->dev_index, 10000000);
/* Initialize the Physical address in the MIB. */
SNMP_ifPhysAddress(dev_ptr->dev_index, (UINT8*)"\0\0\0\0\0\0");
/* Set the current status to operational. */
SNMP_ifAdminStatus(dev_ptr->dev_index, 1);
SNMP_ifOperStatus(dev_ptr->dev_index, 1);
return (NU_SUCCESS);
} /* end LDC_Init */
/*************************************************************************
*
* FUNCTION
*
* LDC_TX_Packet
*
* DESCRIPTION
*
* Makes a copy of the packet to be transmitted and places it onto
* the recevie packet list. Then set an event to tell the stack that
* a packet has arrived.
*
* INPUTS
*
* *dev_ptr Pointer to the device structure used
* to send the packet.
* *buf_ptr Pointer to the buffer that holds the
* packet to send.
*
* OUTPUTS
*
* STATUS NU_SUCCESS if the packet was sent.
* NU_NO_BUFFERS if there were not enough
* buffer to complete the transmission.
*
*************************************************************************/
STATUS LDC_TX_Packet (DV_DEVICE_ENTRY *dev_ptr, NET_BUFFER *buf_ptr)
{
NET_BUFFER *dest_buf_ptr;
STATUS ret_status = NU_SUCCESS;
/* Allocate some buffers to hold this packet. */
dest_buf_ptr = MEM_Buffer_Chain_Dequeue (&MEM_Buffer_Freelist,
(INT32)buf_ptr->mem_total_data_len);
/* Make sure we got the buffers. */
if (dest_buf_ptr)
{
/* Setup the data pointer. */
dest_buf_ptr -> data_ptr = dest_buf_ptr -> mem_parent_packet;
/* Copy the packet to the destination buffers. */
MEM_Chain_Copy (dest_buf_ptr, buf_ptr, 0, (INT32)buf_ptr -> mem_total_data_len);
/* The number of octets sent and received on this interface are the same. */
SNMP_ifInOctets(dev_ptr->dev_index, buf_ptr->mem_total_data_len);
SNMP_ifOutOctets(dev_ptr->dev_index, buf_ptr->mem_total_data_len);
}
else
{
SNMP_ifOutDiscards_Inc(dev_ptr->dev_index);
}
#ifndef PACKET
/* Remove the packet from the devices transmit queue. */
MEM_Buffer_Dequeue (&dev_ptr->dev_transq);
/* Decrement the queue length counter. */
--dev_ptr->dev_transq_length;
/* Free the transmit buffer to its deallocation list. */
MEM_One_Buffer_Chain_Free (buf_ptr, buf_ptr->mem_dlist);
#endif
/* Again check for success of the allocation above. This if
statement is broken like this because the ifdefed code
above needs to be executed even if the buffer allocation
failed. */
if (dest_buf_ptr)
{
/* Set the device for this just "reveived" packet. */
dest_buf_ptr -> mem_buf_device = dev_ptr;
/* And the total data length. */
dest_buf_ptr -> mem_total_data_len = buf_ptr -> mem_total_data_len;
/* Put the "received" packet onto the receive buffer list. */
MEM_Buffer_Enqueue (&MEM_Buffer_List, dest_buf_ptr);
/* Set the event to tell the stack that a packet has arrived. */
NU_Set_Events (&Buffers_Available, 2, NU_OR);
}
else
{
/* Log the error and return an error. */
NERRS_Log_Error (NERR_SEVERE, __FILE__, __LINE__);
ret_status = NU_NO_BUFFERS;
}
return (ret_status);
} /* end LDC_TX_Packet */
/*************************************************************************
*
* FUNCTION
*
* LDC_Ioctl
*
* DESCRIPTION
*
* This function processes IOCTL requests to the loopback driver.
* Right now this only includes requests for multicasting support.
*
* INPUTS
*
* *dev Pointer to the device for this request.
* option Which option to do.
* *d_req Pointer to the request packet to send.
*
* OUTPUTS
*
* STATUS NU_SUCCESS or NU_INVAL
*
************************************************************************/
STATUS LDC_Ioctl(DV_DEVICE_ENTRY *dev, INT option, DV_REQ *d_req)
{
STATUS ret_status;
switch (option)
{
case DEV_ADDMULTI :
/* Join the ethernet multicast group. */
ret_status = NET_Add_Multi(dev, d_req);
/* A status of NU_RESET means the operation was a success and as a
result the ethernet setup frame needs to be reset. Since this
is a loopback device there is no receive filtering to update.
Set the status to NU_SUCCESS and return. */
if (ret_status == NU_RESET)
ret_status = NU_SUCCESS;
break;
case DEV_DELMULTI :
/* Join the ethernet multicast group. */
ret_status = NET_Del_Multi(dev, d_req);
/* A status of NU_RESET means the operation was a success and as a
result the ethernet setup frame needs to be reset. Since this
is a loopback device there is no receive filtering to update.
Set the status to NU_SUCCESS and return. */
if (ret_status == NU_RESET)
ret_status = NU_SUCCESS;
break;
default :
ret_status = NU_INVAL;
break;
}
return (ret_status);
} /* end LDC_Ioctl */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -