📄 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 0x2c000400
#define CFG_NE2000_IRQ 15
#include "net/nettypes.h"
//#include "44b.h"
#include "net/inc/externs.h"
//#include "net/inc/ethernet.h"
#include "ethernet.h"
#include "ostype.h"
#include "ne2000.h"
#include "hardware_reg.h"
#include "hardware.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)
/* About Garfield chip, pessia */
#if 0
#define GPIO_MAC_RESET (0x01UL<<12) //PE12
#define GPIO_MAC_IRQ (0x01UL<<9) //PE9
#else
#define GPIO_MAC_RESET (0x01UL<<8) //PB8
#define GPIO_MAC_IRQ (0x01UL<<2) //PH2
#endif
#define setbit_gpio(addr, value) *((volatile unsigned long*)addr) |= (unsigned long)(value)
#define clearbit_gpio(addr, value) *((volatile unsigned long*)addr) &= ~((unsigned long)value)
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);
int ne2000_set_mac_addr (UINT8 *mac_addr);
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 */
#if 0
/* Set PE12 output GPIO */
setbit_gpio(PORTE_SEL, GPIO_MAC_RESET); //normal GPIO
clearbit_gpio(PORTE_DATA, GPIO_MAC_RESET);//low level
clearbit_gpio(PORTE_DIR, GPIO_MAC_RESET); //output
/* Hard Reset RTL8019AS chip */
clearbit_gpio(PORTE_DATA, GPIO_MAC_RESET);//low level
NU_Sleep(1); /* 1 ms */
setbit_gpio(PORTE_DATA, GPIO_MAC_RESET);//high level
NU_Sleep(10);/* 2 ms */
clearbit_gpio(PORTE_DATA, GPIO_MAC_RESET);//low level
NU_Sleep(150);/* 100 ms */
#else
/* Set PB8 output GPIO */
setbit_gpio (PORTB_SEL, GPIO_MAC_RESET); //normal GPIO
clearbit_gpio(PORTB_DATA, GPIO_MAC_RESET); //low level
clearbit_gpio(PORTB_DIR, GPIO_MAC_RESET); //output
/* Hard Reset RTL8019AS chip */
clearbit_gpio(PORTB_DATA, GPIO_MAC_RESET); //low level
NU_Sleep(1); /* 1 ms */
setbit_gpio (PORTB_DATA, GPIO_MAC_RESET); //high level
NU_Sleep(10);/* 2 ms */
clearbit_gpio(PORTB_DATA, GPIO_MAC_RESET); //low level
NU_Sleep(150);/* 100 ms */
#endif
/* Soft Reset RTL8019AS chip */
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(100); /* 10 ms */
/* initialize DCR for byte operations. */
OUTBYTE(REF_REG_ADDR(nic_addr_NE2000_P0_DCR), NE2000_DCR_FT1 | NE2000_DCR_LS); // byte-wide DMA transfer
/* Set the start/end page address of the receive buffer ring */
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);
#if DATA_BUS_16BIT
sc->isa16bit = 1; // 1
#else
/* 8-bit access, which means the DATA bus of 8019 could be 8-line.
* The endian problem could be ignored by using 8-bit access. */
sc->isa16bit = 0;
#endif
#define MEMSIZE 16384
#define MEMSTART 16384 //0x4000
sc->mem_start = MEMSTART; // the start page address of SRAM (16K)
sc->mem_size = MEMSIZE;
sc->mem_end = (UINT16)((long)MEMSTART + (long)MEMSIZE); // the end page address of SRAM (16K)
/* 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); // the start page address of the XMIT buffer ring
/* The size of the XMIT buffer ring is 6-page, and the remained pages are used by the receive buffer ring */
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);
/* The real address of the start of the receive buffer ring */
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);
}
void enable_ne2000_irq ( void )
{
#if 0
setbit_gpio(PORTE_DIR, GPIO_MAC_IRQ); //input
setbit_gpio(PORTE_SEL, GPIO_MAC_IRQ); //common gpio
// setbit_gpio(PORTE_INTRCTL, 0x1UL<<18); //falling edge irq
// setbit_gpio(PORTE_INTRCTL, 0x0UL<<18); //rising edge irq
setbit_gpio(PORTE_INTRCTL, 0x2UL<<18); //high level irq
// setbit_gpio(PORTE_INTRCTL, 0x3UL<<18); //low level irq
setbit_gpio(PORTE_INCTL, GPIO_MAC_IRQ); //external irq source
//setbit_gpio(PORTE_INTRCLR, GPIO_MAC_IRQ); //clear irq
//setbit_gpio(PORTE_INTRCLR, 0xfffUL); //clear irq
*((volatile unsigned long*)PORTE_INTRCLR) = 0xfffUL;
/* Clear mask bit in Interrupt Mask Register */
unmask_irq(10); //external IRQ9 is 10th bit
/* Enable the interrupt in Interrupt Control Register */
irq_enable(10); //external IRQ9 is 10th bit
#else
setbit_gpio(PORTH_DIR, GPIO_MAC_IRQ); //input
setbit_gpio(PORTH_SEL, GPIO_MAC_IRQ); //common gpio
setbit_gpio(PORTH_INTRCTL, 0x2UL<<4); //high level irq
setbit_gpio(PORTH_INCTL, GPIO_MAC_IRQ); //external irq source
*((volatile unsigned long*)PORTH_INTRCLR) = 0x6fUL;
/* Clear mask bit in Interrupt Mask Register */
unmask_irq(15); //external IRQ9 is 10th bit
/* Enable the interrupt in Interrupt Control Register */
irq_enable(15); //external IRQ9 is 10th bit
#endif
}
/* ******************************************************************** */
/* 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);
#if 0
/* 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
#else
/* Register a physical interrupt handler for Garfield chip.
* pessia 2005/01/12 */
/* The code has been removed into "Rtl8019_Initialize()" */
#endif
ne2000_reset(sc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -