📄 ne2000.c
字号:
/***********************************************************************
* $Workfile: net2000.c $
* $Revision: 1.1.1.1 $
* $Author: meterchen $
* $Date: 2003/11/10 17:00:55 $
*
* Project: Shenzhen-Nucleus-Net
*
* Description:
* ne2000 driver
*
* Revision History:
*
***********************************************************************
*
* Copyright (c) 2003 CHENMENG
*
* All rights reserved
*
**********************************************************************/
#define CFG_NE2000_IOBASE 0x06000000
#define CFG_NE2000_IRQ 0x18
#include "nucleus.h"
#include "44b.h"
#include "externs.h"
#include "ethernet.h"
#include "ostype.h"
#include "ne2000.h"
#define IP_ALEN 4 /* number of bytes in an IP address */
#define ETH_ALEN 6 /* number of bytes in an ETHERNET address */
#define TOK_ALEN 6 /* number of bytes in a Token Ring address */
#define LL_ALEN 6 /* number of bytes in a Link Layer address */
/* (token ring or ethernet) */
#define ETHERSIZE 1514 /* maximum number of bytes in ETHERNET packet */
/* (used by ethernet drivers) */
struct _ether
{
UINT8 eth_dest[ETH_ALEN]; /* where the packet is going */
UINT8 eth_source[ETH_ALEN]; /* who it came from */
UINT16 eth_type; /* Ethernet packet type for 802.3 */
/* or length of (IP layer + LLC,SNAP) if 802.2 */
};
#define HW_Address_Size 6 /* Length of Ethernet Addresses */
#define TYPE_LENGTH 2 /* Length of Header Type/Length Field */
#define MTU_Size 1500 /* MAX Transmission Unit, excluding media */
/* header length for ethernet */
/* Ethernet header size: dest addr, source addr, Type/Length */
#define ETH_HeaderSize ((HW_Address_Size * 2) + TYPE_LENGTH)
NU_HISR Ether_Xmit;
NU_HISR Ether_Rcv;
volatile UINT32 et_data_ptr;
volatile UINT32 et_data_len;
int Hisr_Activated = 0;
STATUS Rtl8019_Transmit(DV_DEVICE_ENTRY *dev, NET_BUFFER *buf_ptr);
STATUS Rtl8019_Receive(DV_DEVICE_ENTRY *device);
STATUS Rtl8019_Ioctl(DV_DEVICE_ENTRY *dev, INT option, DV_REQ *d_req);
/* ******************************************************************** */
/* ******************************************************************** */
/* I/O ROUTINES */
/* ******************************************************************** */
/* ******************************************************************** */
/* tbd: rep move simulated in 'C' */
void insw(IOADDRESS ioaddr, PFWORD dst, int n)
{
while (n--)
*dst++ = (word)INWORD(ioaddr);
}
void insb(IOADDRESS ioaddr, PFBYTE dst, int n)
{
while (n--)
*dst++ = INBYTE(ioaddr);
}
void outsw(IOADDRESS ioaddr, PFWORD src, int n)
{
while (n--)
OUTWORD(ioaddr, *src++);
}
void outsb(IOADDRESS ioaddr, PFCBYTE src, int n)
{
while (n--)
OUTBYTE(ioaddr, *src++);
}
#define NEW_WAIT 1
#define DISPLAY_ERROR 0 /* display error during interrupt */
#define DEBUG_RING 0
#define DEBUG_NIC 1
#if (DEBUG_RING)
int recovery_count = 0; /* count of ring buffer overflows */
#endif
/* ******************************************************************** */
#define ETHER_MIN_LEN 64 /* includes header */
#define ETHER_MAX_LEN (ETHERSIZE+4) /* includes header */
#define CRC_LEN 4
#define EROUND ((sizeof(struct _ether) + 3) & ~3)
#define EOFF (EROUND - sizeof(struct _ether))
NE2000_SOFTC KS_FAR ne2000softc[1];
extern KS_CONSTANT UINT8 KS_FAR test_pattern[32];
/* ******************************************************************** */
void ne2000_getmcaf(PFBYTE mclist, int bytesmclist, PFBYTE af);
void ne2000_reset(/*PIFACE pi, */PNE2000_SOFTC sc);
void ne2000_interrupt(int minor_no);
int ne2000_probe_Novell(/*PIFACE pi, */PNE2000_SOFTC sc);
void ne2000_stop(PNE2000_SOFTC sc);
void ne2000_init(/*PIFACE pi, */PNE2000_SOFTC sc);
void ne2000_pio_readmem(PNE2000_SOFTC sc, UINT16 src, PFBYTE dst, int amount);
BOOLEAN ne2000_pio_write_pkt(/*PIFACE pi, */PNE2000_SOFTC sc, PFCBYTE packet, int length, UINT16 dst);
UINT16 ne2000_ring_copy(PNE2000_SOFTC sc, UINT16 src, PFBYTE dst, UINT16 amount);
void ne2000_ring_overflow_recovery2(void);
void ne2000_get_packet(/*PIFACE pi, */PNE2000_SOFTC sc, UINT16 nic_buf, int len, BOOLEAN rint);
void ne2000_read_ring_pkt(/*PIFACE pi, */PNE2000_SOFTC sc, BOOLEAN rint);
/* ******************************************************************** */
/* MEMORY MANAGMENT */
/* ******************************************************************** */
#define iface_to_softc() (PNE2000_SOFTC) &ne2000softc[0]
#define off_to_softc() (PNE2000_SOFTC) &ne2000softc[0]
/*
* Probe and vendor-specific initialization routine for NE1000/2000 boards.
*/
int ne2000_probe_Novell(PNE2000_SOFTC sc)
{
UINT8 tmp;
IOADDRESS nic_addr;
IOADDRESS asic_addr;
/* meaningless, the asic addr i think maybe used on PC's netcard */
sc->asic_addr = (IOADDRESS) (sc->ia_iobase + (UINT16) NE2000_NOVELL_ASIC_OFFSET);
asic_addr = sc->asic_addr; /* used in the macro to calculate register pointers */
ASSIGN_ASIC_ADDR(NE2000_NOVELL_DATA, asic_addr_NE2000_NOVELL_DATA)
ASSIGN_ASIC_ADDR(NE2000_NOVELL_RESET, asic_addr_NE2000_NOVELL_RESET)
sc->nic_addr = (IOADDRESS)(sc->ia_iobase + NE2000_NOVELL_NIC_OFFSET);
nic_addr = sc->nic_addr; /* used in the macro to calculate register pointers */
ASSIGN_REG_ADDR(NE2000_P0_BNRY,nic_addr_NE2000_P0_BNRY)
ASSIGN_REG_ADDR(NE2000_P0_CNTR0,nic_addr_NE2000_P0_CNTR0)
ASSIGN_REG_ADDR(NE2000_P0_CNTR1,nic_addr_NE2000_P0_CNTR1)
ASSIGN_REG_ADDR(NE2000_P0_DCR,nic_addr_NE2000_P0_DCR)
ASSIGN_REG_ADDR(NE2000_P0_CNTR2,nic_addr_NE2000_P0_CNTR2)
ASSIGN_REG_ADDR(NE2000_P0_CR,nic_addr_NE2000_P0_CR)
ASSIGN_REG_ADDR(NE2000_P0_IMR,nic_addr_NE2000_P0_IMR)
ASSIGN_REG_ADDR(NE2000_P0_ISR,nic_addr_NE2000_P0_ISR)
ASSIGN_REG_ADDR(NE2000_P0_NCR,nic_addr_NE2000_P0_NCR)
ASSIGN_REG_ADDR(NE2000_P0_PSTART,nic_addr_NE2000_P0_PSTART)
ASSIGN_REG_ADDR(NE2000_P0_PSTOP,nic_addr_NE2000_P0_PSTOP)
ASSIGN_REG_ADDR(NE2000_P0_RBCR0,nic_addr_NE2000_P0_RBCR0)
ASSIGN_REG_ADDR(NE2000_P0_RBCR1,nic_addr_NE2000_P0_RBCR1)
ASSIGN_REG_ADDR(NE2000_P0_RCR,nic_addr_NE2000_P0_RCR)
ASSIGN_REG_ADDR(NE2000_P0_RSAR0,nic_addr_NE2000_P0_RSAR0)
ASSIGN_REG_ADDR(NE2000_P0_RSAR1,nic_addr_NE2000_P0_RSAR1)
ASSIGN_REG_ADDR(NE2000_P0_RSR,nic_addr_NE2000_P0_RSR)
ASSIGN_REG_ADDR(NE2000_P0_TBCR0,nic_addr_NE2000_P0_TBCR0)
ASSIGN_REG_ADDR(NE2000_P0_TBCR1,nic_addr_NE2000_P0_TBCR1)
ASSIGN_REG_ADDR(NE2000_P0_TCR,nic_addr_NE2000_P0_TCR)
ASSIGN_REG_ADDR(NE2000_P0_TPSR,nic_addr_NE2000_P0_TPSR)
ASSIGN_REG_ADDR(NE2000_P0_TSR,nic_addr_NE2000_P0_TSR)
ASSIGN_REG_ADDR(NE2000_P1_CR,nic_addr_NE2000_P1_CR)
ASSIGN_REG_ADDR(NE2000_P1_CURR,nic_addr_NE2000_P1_CURR)
ASSIGN_REG_ADDR(NE2000_P1_MAR0,nic_addr_NE2000_P1_MAR0)
ASSIGN_REG_ADDR(NE2000_P1_MAR1,nic_addr_NE2000_P1_MAR1)
ASSIGN_REG_ADDR(NE2000_P1_MAR2,nic_addr_NE2000_P1_MAR2)
ASSIGN_REG_ADDR(NE2000_P1_MAR3,nic_addr_NE2000_P1_MAR3)
ASSIGN_REG_ADDR(NE2000_P1_MAR4,nic_addr_NE2000_P1_MAR4)
ASSIGN_REG_ADDR(NE2000_P1_MAR5,nic_addr_NE2000_P1_MAR5)
ASSIGN_REG_ADDR(NE2000_P1_MAR6,nic_addr_NE2000_P1_MAR6)
ASSIGN_REG_ADDR(NE2000_P1_MAR7,nic_addr_NE2000_P1_MAR7)
ASSIGN_REG_ADDR(NE2000_P1_PAR0,nic_addr_NE2000_P1_PAR0)
/* Reset the board. */
tmp = INBYTE(REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_RESET));
OUTBYTE(REF_ASIC_ADDR(asic_addr_NE2000_NOVELL_RESET), tmp);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
NU_Sleep(2); /* 5000 usec */
/* initialize DCR for byte operations. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_LS);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTART),8192 / NE2000_PAGE_SIZE); //this value is overridden in ne2000_init
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTOP), 16384 / NE2000_PAGE_SIZE);
sc->isa16bit = 0;
#define MEMSIZE 16384
#define MEMSTART 16384
sc->mem_start = MEMSTART;
sc->mem_size = MEMSIZE;
sc->mem_end = (UINT16)((long)MEMSTART + (long)MEMSIZE);
/* XMIT Page offset is the begining of ram to the NE
RCV Page offset is xmit offset + size of xmite ring
RCV End is Begining of ram + size of rem */
sc->tx_page_start = (UINT16) (MEMSTART / NE2000_PAGE_SIZE);
sc->rec_page_start = (UINT16)((MEMSTART / NE2000_PAGE_SIZE) + NE2000_TXBUF_SIZE);
sc->rec_page_stop = (UINT16) ((MEMSTART / NE2000_PAGE_SIZE) + MEMSIZE / NE2000_PAGE_SIZE);
sc->mem_ring = MEMSTART + NE2000_PAGE_SIZE * NE2000_TXBUF_SIZE;
//ne2000_pio_readmem(sc, 0, romdata, 16);
//for (n = 0; n < ETH_ALEN; n++)
// pi->addr.my_hw_addr[n] = romdata[n*(sc->isa16bit+1)];
/* Clear any pending interrupts that might have occurred above. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), 0xff);
return (1);
}
/* ******************************************************************** */
/* OPEN and CLOSE routines. */
/* ******************************************************************** */
void ne2000_close(/*PIFACE pi*/) /*__fn__*/
{
PNE2000_SOFTC sc;
sc = iface_to_softc();
if (!sc)
return;
ne2000_stop(sc);
}
/* ******************************************************************** */
/* Install interface into kernel networking data structures. */
BOOLEAN ne2000_open(VOID)
{
PNE2000_SOFTC sc;
VOID (*oldfptr)(INT);
sc = iface_to_softc();
if (!sc)
{
//set_errno(ENUMDEVICE);
return(FALSE);
}
tc_memset((PFBYTE) sc, 0, sizeof(*sc));
/* determine which device and initialize */
sc->ia_iobase = (IOADDRESS) CFG_NE2000_IOBASE;
sc->ia_irq = CFG_NE2000_IRQ;
if (!(ne2000_probe_Novell(sc)))
{
//DEBUG_ERROR("ne2000probe failed", NOVAR, 0, 0);
//set_errno(EPROBEFAIL);
return(FALSE);
}
/* Set interface to stopped condition (reset). */
ne2000_stop(sc);
/* Register interrupt lisr */
NU_Register_LISR(sc->ia_irq/*22*/, ne2000_interrupt, &oldfptr);
rI_ISPR |= BIT_EINT1; //clear pending bit
rINTMSK &= ~BIT_EINT1; //enable interrupt bit
ne2000_reset(sc);
return(TRUE);
}
/* Reset interface. */
void ne2000_reset(/*PIFACE pi, */PNE2000_SOFTC sc)
{
STATUS previous_int_value;
/* Lock out interrupts. */
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
ne2000_stop(sc);
ne2000_init(sc);
NU_Control_Interrupts(previous_int_value);
}
/* Take interface offline. */
void ne2000_stop(PNE2000_SOFTC sc)
{
int n = 5000;
/* Stop everything on the interface, and select page 0 registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
/*
* Wait for interface to enter stopped state, but limit # of checks to
* 'n' (about 5ms). It shouldn't even take 5us on modern DS8390's, but
* just in case it's an old one.
*/
while (((INBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR)) & NE2000_ISR_RST) == 0) && --n);
}
/* Initialize device. */
void ne2000_init(PNE2000_SOFTC sc)
{
int i;
STATUS previous_int_value;
UINT8 mcaf[8]; /* multicast address filter */
UINT8 my_hw_addr[6];
tc_memset(my_hw_addr, 2, 6); //set the macaddress is all 2
tc_memset(mcaf, 1, 8); //accept all multicast packet
/*
* Initialize the NIC in the exact order outlined in the NS manual.
* This init procedure is "mandatory"...don't change what or when
* things happen.
*/
/* Lock out interrupts. */
previous_int_value = NU_Control_Interrupts(NU_DISABLE_INTERRUPTS);
/* This variable is used below - don't move this assignment. */
sc->next_packet = (UINT16) (sc->rec_page_start + 1);
/* Set interface for page 0, remote DMA complete, stopped. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_CR), NE2000_CR_RD2 | NE2000_CR_PAGE_0 | NE2000_CR_STP);
if (sc->isa16bit)
{
/*
* Set FIFO threshold to 8, No auto-init Remote DMA, UINT8
* order=80x86, UINT16-wide DMA xfers,
*/
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_WTS | NE2000_DCR_LS);
}
else
{
/* Same as above, but UINT8-wide DMA xfers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_LS);
}
/* Clear remote UINT8 count registers. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR0), 0);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RBCR1), 0);
/* Tell RCR to do nothing for now. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_RCR), NE2000_RCR_MON);
/* Place NIC in internal loopback mode. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TCR), NE2000_TCR_LB0);
/* Initialize transmit/receive (ring-buffer) page start. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_TPSR), sc->tx_page_start);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTART), sc->rec_page_start);
/* Initialize receiver (ring-buffer) page stop and boundary. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_PSTOP), sc->rec_page_stop);
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_BNRY), sc->rec_page_start);
/*
* Clear all interrupts. A '1' in each bit position clears the
* corresponding flag.
*/
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_ISR), 0xff);
/*
* Enable the following interrupts: receive/transmit complete,
* receive/transmit error, and Receiver OverWrite.
*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -