📄 ne2000.c
字号:
/* Set up DMA byte count. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), amount);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), amount >> 8);
/* Set up source address in NIC mem. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR0), src);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR1), src >> 8);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD0 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
if (sc->isa16bit)
insw((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), (unsigned short KS_FAR *) dst, amount / 2);
else
insb((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), dst, amount);
}
/*
* Write a DCU to the destination NIC memory address using programmed I/O
*/
BOOLEAN ne2000_pio_write_pkt(PNE2000_SOFTC sc, PFCBYTE packet, int length, UINT16 dst)
{
int maxwait; /* about 120us */
UINT8 savebyte[2];
BOOLEAN ret_val=TRUE;
/* Select page 0 registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/* Reset remote DMA complete flag. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), NE2000_ISR_RDC);
/* Set up DMA UINT8 count. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), length);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), length >> 8);
/* Set up destination address in NIC mem. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR0), dst);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RSAR1), dst >> 8);
/* Set remote DMA write. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD1 | NE2000_CR_PAGE_0 | NE2000_CR_STA);
/*
* Transfer DCU to the NIC memory.
* 16-bit cards require that data be transferred as words, and only
* words, so that case requires some extra code to patch over
* odd-length DCUs.
*/
if (!sc->isa16bit)
{
/* NE1000s are easy. */
outsb((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), packet, length);
}
else
{
/* NE2000s are a bit trickier. */
/* Output contiguous words. */
if (length > 1)
{
outsw((IOADDRESS) REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), (unsigned short KS_FAR *) packet, length >> 1);
packet += length;
length &= 1;
if (length)
packet--;
}
/* If odd number of bytes, output last UINT8 as a UINT16 with a 0 appended */
if (length == 1)
{
savebyte[0] = *packet;
savebyte[1] = 0;
OUTWORD(REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_DATA), *(UINT16 *)savebyte);
}
}
/*
* Wait for remote DMA complete. This is necessary because on the
* transmit side, data is handled internally by the NIC in bursts and
* we can't start another remote DMA until this one completes. Not
* waiting causes really bad things to happen - like the NIC
* irrecoverably jamming the ISA bus.
*/
#if (NEW_WAIT)
maxwait = 300; /* about 360usec */
#else
maxwait = 1000;
#endif
while (maxwait--)
{
if ( ((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RDC) == NE2000_ISR_RDC))
break;
}
/* If pi is zero we are probing so don't reset */
if (!maxwait)
{
#if (NEW_WAIT)
#define ks_msec_p_tick() (1000/NU_PLUS_Ticks_Per_Second)
#define ks_sleep(x) NU_Sleep(x)
//DEBUG_ERROR("NE2000: sleep in xmit", NOVAR, 0, 0);
/* the while() above was not enough. Cannot afford to tie up the */
/* CPU longer than .5 msec, so sleep 20 msecs longer now. */
if (ks_msec_p_tick() >= 20)
ks_sleep(1);
else
ks_sleep((UINT16)((20+ks_msec_p_tick()-1)/ks_msec_p_tick()));
++sc->stats.tx_delayed;
#endif
#if (NEW_WAIT)
if ((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RDC) != NE2000_ISR_RDC)
#endif
{
//DEBUG_ERROR("remote transmit DMA failed to complete", NOVAR, 0, 0);
sc->stats.errors_out++;
sc->stats.tx_other_errors++;
ne2000_reset(sc);
ret_val = FALSE;
}
}
return(ret_val);
}
/*********************************************************************/
/* */
/* NUCLEUS NET FUNCTION */
/* */
/*********************************************************************/
VOID MAC_TxHisr(DV_DEVICE_ENTRY* device)
{
STATUS previous_int_value;
if (device == NU_NULL)
return;
/* Lock out interrupts. */
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
DEV_Recover_TX_Buffers (device);
/* If there is another item on the list, transmit it. */
if(device -> dev_transq.head)
{
/* Re-enable interrupts. */
NU_Control_Interrupts(previous_int_value);
/* Transmit the next packet. */
Rtl8019_Transmit(device, device->dev_transq.head);
}
/* Re-enable interrupts. */
NU_Control_Interrupts(previous_int_value);
} /* MAC_TxHisr */
VOID Rtl8019_TxHisr()
{
DV_DEVICE_ENTRY *device;
/* Get a pointer to the device. */
#if RTL8019_LOOPBACK_TEST
device = DEV_Get_Dev_By_Name("loopback");
#else
device = DEV_Get_Dev_By_Name("RTL8019");
#endif
MAC_TxHisr(device);
}
void Rtl8019_RxHisr ()
{
/* Let the upper layer know a good packet is here. */
NU_Set_Events(&Buffers_Available, (UNSIGNED)2, NU_OR);
Hisr_Activated = 0;
} /* END */
/************************************************************************
* FUNCTION
*
* Rtl8019_Initialize
*
* DESCRIPTION
*
* This function intializes the media layer of the protocol stack.
*
* AUTHOR
*
* MeterChen
*
* INPUTS
*
* DV_DEVICE_ENTRY *dev_ptr Pointer to the device
* structure for this device.
*
* OUTPUTS
*
* STATUS Returns NU_SUCCESS if
* initialization is successful,
* else a value less than 0 is
* returned.
*
************************************************************************/
STATUS Rtl8019_Initialize(DV_DEVICE_ENTRY *dev_ptr)
{
STATUS status;
VOID *pointer;
/* Fill in the device table */
dev_ptr->dev_output = NET_Ether_Send; /* net.c */
dev_ptr->dev_input = NET_Ether_Input; /* net.c */
dev_ptr->dev_start = Rtl8019_Transmit;
dev_ptr->dev_receive = Rtl8019_Receive;
dev_ptr->dev_addrlen = HW_Address_Size;
dev_ptr->dev_hdrlen = ETH_HeaderSize;
dev_ptr->dev_mtu = MTU_Size; /* 1500 */
dev_ptr->dev_ioctl = Rtl8019_Ioctl;
/* Get the hardware address from the device structure and */
/* set it into the CAM filter. */
//Rtl8019_SetMacAddr(dev_ptr);
/* Initialize the MAC. */
if (ne2000_open() != TRUE)
{
return (-1);
}
/* Allow reception of broadcast and multicast packets. */
dev_ptr->dev_flags |= (DV_BROADCAST | DV_MULTICAST);
/* CAM filter setting is done in api_MacHWInit routine */
memcpy(dev_ptr->dev_mac_addr, (UINT8*)dev_ptr->dev_driver_options, 6);
/* Set the input MAC ADDRESS */
if (ne2000_set_mac_addr(dev_ptr->dev_mac_addr) != TRUE)
{
return (-1);
}
/* Init the basic interface information. */
SNMP_ifDescr(device->dev_unit + 1, "Realtek 8019as Ethernet: Software revision 1.2");
SNMP_ifType(device->dev_unit + 1, 6);
SNMP_ifMtu(device->dev_unit + 1, device->dev_mtu);
/* Create the HISR for receiving packets from the MAC */
status = NU_Allocate_Memory (&System_Memory,
&pointer,
2000,
NU_NO_SUSPEND);
if (status != NU_SUCCESS)
{
return (-2);
}
status = NU_Create_HISR (&Ether_Rcv, "ETH_RX_HISR",
Rtl8019_RxHisr,
0, pointer, 2000);
if (status != NU_SUCCESS)
{
return (-3);
}
/* Create the HISR for transmitting packets */
status = NU_Allocate_Memory (&System_Memory,
&pointer,
2000,
NU_NO_SUSPEND);
if (status != NU_SUCCESS)
{
return (-4);
}
status = NU_Create_HISR (&Ether_Xmit, "ETH_TX_HISR",
Rtl8019_TxHisr,
0, pointer, 2000);
if (status != NU_SUCCESS)
{
return (-5);
}
/* Set the current status to operational. */
SNMP_ifAdminStatus(device->dev_unit + 1, 1);
SNMP_ifOperStatus(device->dev_unit + 1, 1);
enable_ne2000_irq();//pessia
return (NU_SUCCESS);
}
/************************************************************************
* FUNCTION
*
* Rtl8019_Transmit
*
* DESCRIPTION
*
* Accepts a packet from the upper layers and generates an
* ethernet frame for transmission.
*
* AUTHOR
*
* Meterchen
*
* INPUTS
*
* DV_DEVICE_ENTRY *dev Pointer to the device structure.
* NET_BUFFER *buf_ptr Pointer to the data we want to
* send.
*
* OUTPUTS
*
* STATUS (0) NU_SUCCESS
*
************************************************************************/
CHAR TEMP_BUF_T[2000];
STATUS Rtl8019_Transmit(DV_DEVICE_ENTRY *dev, NET_BUFFER *buf_ptr)
{
PNE2000_SOFTC sc;
STATUS previous_int_value; /* We'll be push/popping interupt flags */
int ret_val;
UINT32 length; /* This is needed to handle packets that are bigger than one NET Buffer can hold. */
CHAR *FramePtr;
FramePtr = TEMP_BUF_T;
sc = iface_to_softc();
//if (!sc)
// return(ENUMDEVICE);
//if (sc->do_recovery)
// return(ENETDOWN);
#if INCLUDE_SNMP
/* Find out if this is a unicast or non-unicast packet, and update MIB. */
if ((buf_ptr->mem_flags & NET_BCAST) || (buf_ptr->mem_flags & NET_MCAST))
SNMP_ifOutNUcastPkts_Inc(device->dev_unit + 1);
else
SNMP_ifOutUcastPkts_Inc(device->dev_unit + 1);
#endif
length = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -