⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 et9000if.c

📁 DM9000A some kinda source codes that might help
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * et9000if.c
 * NC9100 Ethernet driver for DM9000E
 * 2004-05-05
 */
 
#include "sysdef.h"

#include "lwip/debug.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "netif/etharp.h"

#include "at91lib.h"
//#include "dump.h"
#include "lwipopts.h"
#include "et9000if.h"

#include "string.h"
#include "schedule.h"
#include "lwip/stats.h"

#include "config.h"

#define IFNAME0 			'e'
#define IFNAME1 			't'

extern struct stats_ lwip_stats;

// Board/System/Debug information/definition

#define NIC_BASE        	((u8_t *)0x03000000)
#define DM9000_ID		    0x90000A46

#define DM9000_REG00		0x00
#define DM9000_REG05		0x30	// SKIP_CRC/SKIP_LONG
#define DM9000_REG08		0x27
#define DM9000_REG09		0x38
#define DM9000_REG0A		0xff 
#define DM9000_REGFF		0x83	// IMR

#define DM9000_PHY			0x40	// PHY address 0x01
#define DM9000_PKT_MAX		1536	// Received packet max size
#define DM9000_PKT_RDY		0x01	// Packet ready to receive
#define DM9000_INDEX		0x00
#define DM9000_DATA			0x04
#define DM9000_INT_MII		0x00
#define DM9000_EXT_MII		0x80

#define DM9000_VID_L		0x28
#define DM9000_VID_H		0x29
#define DM9000_PID_L		0x2A
#define DM9000_PID_H		0x2B

#define DM9801_NOISE_FLOOR	0x08
#define DM9802_NOISE_FLOOR	0x05

#define DMFE_SUCC       	0
#define MAX_PACKET_SIZE		1514
#define DMFE_MAX_MULTICAST	14

#define DM9000_RX_INTR			0x01
#define DM9000_TX_INTR			0x02
#define DM9000_OVERFLOW_INTR	0x04

#define DM9000_DWORD_MODE	1
#define DM9000_BYTE_MODE	2
#define DM9000_WORD_MODE	0


enum DM9000_PHY_mode {
	DM9000_10MHD   = 0, 
	DM9000_100MHD  = 1, 
	DM9000_10MFD   = 4,
	DM9000_100MFD  = 5, 
	DM9000_AUTO    = 8, 
	DM9000_1M_HPNA = 0x10 
};

enum DM9000_NIC_TYPE {
	FASTETHER_NIC = 0, 
	HOMERUN_NIC   = 1, 
	LONGRUN_NIC   = 2 
};

struct dev_mc_list {       
  struct dev_mc_list    *next;
  u8_t					dmi_addr[8];
  unsigned char		    dmi_addrlen;
  int					dmi_users;
  int					dmi_gusers;
};



//_____________________________________________________________________________________


static int media_mode = DM9000_AUTO;
static u8_t nfloor    = 0;

Dm9000if_t dm9000if;

static u8_t *ethernetnic = NIC_BASE;


          

// Help routines_______________________________________________________________________

static u32_t ether_crc_le(int cnt, unsigned char *addr)
{
    unsigned int crc = 0xffffffff;
    u8_t byte, idx, bit;
   
    for (idx = 0; idx < cnt; idx++) 
        for (byte = *addr++, bit = 0; bit < 8; bit++, byte >>= 1)
            crc = (crc >> 1) ^ (((crc ^ byte) & 1) ? 0xedb88320U : 0);
            
    return crc;
}



//  Calculate the CRC valude of the Rx packet
//  flag = 1 : return the reverse CRC (for the received packet CRC)
//         0 : return the normal CRC (for Hash Table index)
static u32_t cal_CRC(unsigned char * Data, unsigned int Len, u8_t flag)
{
	
	u32_t crc = ether_crc_le(Len, Data);

	if (flag) 
		return ~crc;
		
	return crc;
}

static inline void udelay(volatile int time)
{
  while (--time > 0);
}

static inline u8_t inb(u16_t portno)
{
    return *(volatile u8_t *)(ethernetnic + portno);
}

static inline void outb(u8_t value, u16_t portno)
{
  *(volatile u8_t *)(ethernetnic + portno) = value;
}

// Read a byte from I/O port
static u8_t ior(int reg)
{                                               
	outb(reg, DM9000_INDEX);
  return inb(DM9000_DATA);
}

// Write a byte to I/O port
static void iow(int reg, u8_t value)
{
	outb(reg, DM9000_INDEX);
  outb(value, DM9000_DATA);
}

// Read a word from phyxcer
static u16_t phy_read(int reg)
{
	// Fill the phyxcer register into REG_0C
	iow(0xc, DM9000_PHY | reg);

	iow(0xb, 0xc); 	// Issue phyxcer read command
	udelay(100);	// Wait read complete
	iow(0xb, 0x0); 	// Clear phyxcer read command

	// The read data keeps on REG_0D & REG_0E
	return ( ior(0xe) << 8 ) | ior(0xd);
}

// Write a word to phyxcer
static void phy_write(int reg, u16_t value)
{
	/* Fill the phyxcer register into REG_0C */
	iow(0xc, DM9000_PHY | reg);

	/* Fill the written data into REG_0D & REG_0E */
	iow(0xd, (value & 0xff));
	iow(0xe, ( (value >> 8) & 0xff));

	iow(0xb, 0xa);		/* Issue phyxcer write command */
	udelay(500);			/* Wait write complete */
	iow(0xb, 0x0);		/* Clear phyxcer write command */
}						

static inline u16_t inw(u16_t portno)
{
    return  *(volatile u16_t *)(ethernetnic + portno);
}

static inline void outw(u16_t value, u16_t portno)
{
    *(volatile u16_t *)(ethernetnic + portno) = value;
}

static void outsw(u16_t *p, int len)
{
    int i;

    len = (len + 1) >> 1;  
    for (i = 0; i < len; i++)
        *(volatile u16_t *)(ethernetnic + DM9000_DATA) = *p++; 
}

static void insw(u16_t *p, int len)
{
    int i;
 
    len = (len + 1) >> 1;

    for (i = 0; i < len; i++)  
        *p++ = *(volatile u16_t *)(ethernetnic + DM9000_DATA);
}

/*
static u8_t readReg(int reg)
{
    u8_t reg_save;
    u8_t status;
  
	reg_save = inb(DM9000_INDEX);
  
    status = ior(reg);
  
    outb(reg_save, DM9000_INDEX);
    return status;
}  
*/

// DM9000 NIC____________________________________________________

static int dmfe_probe(Dm9000if_t *db)
{
	u32_t id_val;

	/* Id DM9000 NIC */
	id_val = ior(DM9000_VID_L);
	id_val |= ior(DM9000_VID_H) << 8;
	id_val |= ior(DM9000_PID_L) << 16;
	id_val |= ior(DM9000_PID_H) << 24;

	if (id_val != DM9000_ID) 
		return -1;

	return 0;
}

// Set PHY operationg mode
static void set_PHY_mode(Dm9000if_t *db)
{
	u16_t phy_reg4 = 0x01e1, phy_reg0=0x1000;

	if (!(db->op_mode & DM9000_AUTO)) {
    	switch(db->op_mode) {
    	case DM9000_10MHD:
            phy_reg4 = 0x21; 
            phy_reg0 = 0x0000; 
    		break;
    			
        case DM9000_10MFD:
            phy_reg4 = 0x41; 
            phy_reg0 = 0x1100; 
            break;
    			
        case DM9000_100MHD:
            phy_reg4 = 0x81; 
    		phy_reg0 = 0x2000; 
    		break;
    			
        case DM9000_100MFD:
            phy_reg4 = 0x101; 
    		phy_reg0 = 0x3100; 
    		break;
    	}
    	phy_write(4, phy_reg4);	/* Set PHY media mode */
    	phy_write(0, phy_reg0);	/*  Tmp */
	}
	iow(0x1e, 0x01);			/* Let GPIO0 output */
	iow(0x1f, 0x00);			/* Enable PHY */
}

// Init HomeRun DM9801
static void program_dm9801(u16_t HPNA_rev)
{
	u16_t reg16, reg17, reg24, reg25;

	if (!nfloor) 
		nfloor = DM9801_NOISE_FLOOR;

	reg16 = phy_read(16);
	reg17 = phy_read(17);
	reg24 = phy_read(24);
	reg25 = phy_read(25);

	switch(HPNA_rev) {
	case 0xb900: /* DM9801 E3 */
		reg16 |= 0x1000;
		reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xf000;
		break;
		
    case 0xb901: /* DM9801 E4 */
		reg25 = ( (reg24 + nfloor) & 0x00ff) | 0xc200;
		reg17 = (reg17 & 0xfff0) + nfloor + 3;
		break;
		
    case 0xb902: /* DM9801 E5 */
		case 0xb903: /* DM9801 E6 */
		
    default:
		reg16 |= 0x1000;
		reg25 = ( (reg24 + nfloor - 3) & 0x00ff) | 0xc200;
		reg17 = (reg17 & 0xfff0) + nfloor;
	}
	phy_write(16, reg16);
	phy_write(17, reg17);
	phy_write(25, reg25);
}

// Init LongRun DM9802
static void program_dm9802(void)
{
	u16_t reg25;

	if (!nfloor) 
		nfloor = DM9802_NOISE_FLOOR;

	reg25 = phy_read(25);
	reg25 = (reg25 & 0xff00) + nfloor;
	phy_write(25, reg25);
}

// Identify NIC type
static void identify_nic(Dm9000if_t *db)
{
	u16_t phy_reg3;

	iow(0, DM9000_EXT_MII);
	phy_reg3 = phy_read(3);
	
	switch(phy_reg3 & 0xfff0) {
	case 0xb900:
	    if (phy_read(31) == 0x4404) {
			db->nic_type =  HOMERUN_NIC;
			program_dm9801(phy_reg3);
		}
        else {
			db->nic_type = LONGRUN_NIC;
			program_dm9802();
		}
		break;
			
	default: 
        db->nic_type = FASTETHER_NIC; 
		break;
	}
	iow(0, DM9000_INT_MII);	
}

// Set DM9000 multicast address
static void dm9000_hash_table(Dm9000if_t *db)
{
	struct dev_mc_list *mcptr = NULL;
	int mc_cnt = 0;
	u32_t hash_val;
	u16_t i, oft, hash_table[4];

	/* Clear Hash Table */
	for (i = 0; i < 4; i++)
		hash_table[i] = 0x0;

	/* broadcast address */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -