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

📄 dm9008_8bit_mode.c

📁 dm9008_8bit_mode_linux2.4 driver
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
  $Id: dm9ks.c,v 1.1.1.1 2004/12/02 10:02:45 jackal Exp $

  dm9ks.c: Version 1.10 12/29/2004
  
        A Davicom DM9000A/DM9010 ISA NIC fast Ethernet driver for Linux.
	Copyright (C) 1997 2004  Sten Wang Jackal Huang

	This program is free software; you can redistribute it and/or
	modify it under the terms of the GNU General Public License
	as published by the Free Software Foundation; either version 2
	of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.


  (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.

	
V1.00	10/13/2004	Add new function Early transmit & IP/TCP/UDP Checksum
			offload enable & flow control is default
V1.1	12/29/2004	Add Two packet mode & modify RX function
*/

#if defined(MODVERSIONS)
#include <linux/modversions.h>
#endif
				
#include <linux/module.h>            /* for module function set by dd */
#include <linux/ioport.h>

#include <linux/netdevice.h>	     /* for net_device and net_device_stats frame, set by dd */	
				     /* include if.h for ioctl and if_ehter.h for ETH_ set by dd */		
#include <linux/etherdevice.h>       /* for ether_setup function ,set by dd */

#include <linux/skbuff.h>            /* for sk_buff frame , set by dd */
#include <linux/version.h>	     /* linux version */ 			
#include <asm/dma.h>
#include <linux/spinlock.h>          /* for spinlock function set by dd */ 
#include <linux/crc32.h>	     /* ? */	#include <asm/kaida/kaida.h>

/* Board/System/Debug information/definition ---------------- */

#define DM9KS_ID		0x90000A46

#define DM9KS_NCR		0x00	/* Network control Reg.*/
#define DM9KS_NSR		0x01	/* Network Status Reg.*/
#define DM9KS_TCR		0x02	/* TX control Reg.*/
#define DM9KS_RXCR		0x05	/* RX control Reg.*/
#define DM9KS_SMCR		0x2f 	/* Special Mode Control Reg.*/
#define DM9KS_ETCR		0x30	/* Early Transmit control/status Reg.*/
#define	DM9KS_TCCR		0x31	/* Checksum cntrol Reg. */
#define DM9KS_RCSR		0x32	/* Receive Checksum status Reg.*/
#define DM9KS_REG05		0x30	/* SKIP_CRC/SKIP_LONG */
#define DM9KS_REG08		0x37
#define DM9KS_REG09		0x38
#define DM9KS_REG0A		0x29	/* Flow Control Enable */ 
#define DM9KS_GPCR		0x1e	/* General purpose control register */
#define DM9KS_GPR		0x1f	/* General purpose register */
#define DM9KS_ISR		0xfe
#define DM9KS_IMR		0xff
#define DM9KS_REGFF		0x83	/* IMR */
#define DM9KS_DISINTR		0x80

#define DM9KS_PHY		0x40	/* PHY address 0x01 */
#define DM9KS_PKT_MAX		1536	/* Received packet max size */
#define DM9KS_PKT_RDY		0x01	/* Packet ready to receive */
#define DM9KS_MIN_IO		0x300
#define DM9KS_MAX_IO		0x370
#define DM9K_IRQ   		KAIDA_IRQ_USER1
#define DM9KS_VID_L		0x28
#define DM9KS_VID_H		0x29
#define DM9KS_PID_L		0x2A
#define DM9KS_PID_H		0x2B

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

#define DM9KS_RX_INTR		0x01
#define DM9KS_TX_INTR		0x02
#define DM9KS_OVERFLOW_INTR	0x04

#define DM9KS_DWORD_MODE	1
#define DM9KS_BYTE_MODE		2
#define DM9KS_WORD_MODE		0

#define TRUE			1
#define FALSE			0

#define MAXSIZE			16	

#define DMFE_TIMER_WUT  jiffies+(HZ*2)	/* timer wakeup time : 2 second */
#define DMFE_TX_TIMEOUT (HZ*2)		/* tx packet time-out time 1.5 s" */

#if defined(AUTOMDIX)
#define DMFE_TIMER_MDIX	jiffies+(HZ*1)  /* timer wakeup time : 1 second */
#endif

#if defined(DM9KS_DEBUG)
#define DMFE_DBUG(dbug_now, msg, vaule)\
if (dmfe_debug||dbug_now) printk(KERN_ERR "dmfe: %s %x\n", msg, vaule)
#else
#define DMFE_DBUG(dbug_now, msg, vaule)\
if (dbug_now) printk(KERN_ERR "dmfe: %s %x\n", msg, vaule)  
#endif
//    for make time to choose IO_MODE ,set by dd 

//#if (IO_MODE == 1)
#define VALOUT(x, y)	dmfe_outb(x, y)
#define VALIN(x)	dmfe_inb(x)
typedef u8 DATA_TYPE;
/*
#elif (IO_MODE == 2)

#define VALOUT(x, y)	outw(x, y)
#define VALIN(x)	inw(x)
typedef u16 DATA_TYPE;

#elif (IO_MODE == 4)   10M FULL SPEED 

#define VALOUT(x, y)	outl(x, y)
#define VALIN(x)	inl(x)
typedef u32 DATA_TYPE;

#else
#error **** You should specify access mode ****
#endif 
*/
#pragma pack(push, 1)
typedef struct _RX_DESC
{
	u8 rxbyte;
	u8 status;
	u16 length;
}RX_DESC;

typedef union{
	u8 buf[4];
	RX_DESC desc;
} rx_t;

#pragma pack(pop)

//enum DM9KS_PHY_mode {
//	DM9KS_10MHD   = 0, 
//	DM9KS_100MHD  = 1, 
//	DM9KS_10MFD   = 4,
//	DM9KS_100MFD  = 5, 
//	DM9KS_AUTO    = 8, 
//};
// add by dd,06.08.20
char mac[]={0x52,0x54,0x4c,0x33,0xf7,0x42,0x00};/*
#define SCU_MASK 0xBFF807D5
#define SCU_FL   0xBFF807D4
#define ICU_BASE 0xBFF00000
#define SCU_INTMA  	*(volatile unsigned char *)(SCU_MASK)
#define SCU_FLAG 	*(volatile unsigned char *)(SCU_FL)

#define ICR		*(volatile unsigned short *)(ICU_BASE+0x0002)
#define ISR		*(volatile unsigned short *)(ICU_BASE+0x0000)
#define IER		*(volatile unsigned short *)(ICU_BASE+0x0004)
#define ITR 		*(volatile unsigned short *)(ICU_BASE+0x0006)
#define IPR 		*(volatile unsigned short *)(ICU_BASE+0x0008)*/
/* Structure/enum declaration ------------------------------- */
typedef struct board_info {

	u32 runt_length_counter;	/* counter: RX length < 64byte */ 
	u32 long_length_counter;	/* counter: RX length > 1514byte */ 
	u32 reset_counter;		/* counter: RESET */ 
	u32 reset_tx_timeout;		/* RESET caused by TX Timeout */ 
	u32 reset_rx_status;		/* RESET caused by RX Statsus wrong */

	u32 io_addr;			/* Register I/O base address */
	u32 io_data;			/* Data I/O address */
	u32 irq;			/* IRQ */

	u16 tx_pkt_cnt;
	u16 sent_pkt_len, queue_pkt_len;
	u16 queue_start_addr;
	u16 dbug_cnt;

	u8 op_mode;			/* PHY operation mode */
	u8 io_mode;			/* 0:word, 2:byte */
	u8 phy_addr;
	u8 link_failed;			/* Ever link failed */
	u8 nsr;				/*Network Status Register */
	u8 link_status;			/* Detect link state */
	u8 device_wait_reset;		/* device state */
	u8 ncr;
	u8 flowcontrol_p;
//add by dd .6.8.17
//	u8 speed;
	struct timer_list timer;
	struct net_device_stats stats;
//	unsigned char srom[128];
	spinlock_t lock;
//add by dd 06.8.17
	int cont_rx_pkt_cnt;
} board_info_t;

/* Global variable declaration ----------------------------- */
static int dmfe_debug = 0;
static struct net_device * dmfe_dev = NULL;	/*set net_device ,set by dd */

/* For module input parameter */
static int debug      = 0;
//static int mode       = DM9KS_AUTO;
//static int media_mode = DM9KS_AUTO;
static u8 irqline     = KAIDA_IRQ_USER1;

/* function declaration ------------------------------------- */
int dmfe_probe(struct net_device *dev);
static int dmfe_open(struct net_device *dev);
static int dmfe_start_xmit(struct sk_buff *, struct net_device *dev);
static void dmfe_tx_done(unsigned long);
static void dmfe_packet_receive(struct net_device *dev);
static int dmfe_stop(struct net_device *dev);
static struct net_device_stats * dmfe_get_stats(struct net_device *); 
static int dmfe_do_ioctl(struct net_device *, struct ifreq *, int cmd);
static void dmfe_interrupt(int , void *, struct pt_regs *regs);
static void dmfe_timer(unsigned long);
static void dmfe_init_dm9000(struct net_device *dev);
static void dmfe_reset_dm9000(struct net_device *);
static unsigned long cal_CRC(unsigned char *, unsigned int, u8);
//add by dd ,06.08.14
static void dmfe_outb(u8 data, u32 b4addr);
static u8 dmfe_inb(u32 b4addr);
// 
static u8 ior(board_info_t *, int);
static void iow(board_info_t *, int, u8);
static u16 phy_read(board_info_t *, int);
static void phy_write(board_info_t *, int, u16);
//static u16 read_srom_word(board_info_t *, int);
static void dm9000_hash_table(struct net_device *);

//#if defined(CHECKSUM)
//static u8 check_rx_ready(u8);
//#endif

DECLARE_TASKLET(dmfe_tx_tasklet,dmfe_tx_done,0);

/* DM9000 network baord routine ---------------------------- */

/*
  Search DM9000 board, allocate space and register it
*/
//add by dd ,06.08.12
/*
struct net_device * __init dmfe_probe1(void)
{
	struct net_device *dev;
	int err;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
	dev = init_etherdev(NULL,sizeof(struct board_info));
	ether_setup(dev);
#else
	dev=alloc_etherdev(sizeof(struct board_info));
#endif
	if(!dev)
	return ERR_PTR(-ENOMEM);
//	SET_MODULE_OWNER(dev);
	err=dmfe_probe(dev);
	if (err)
	goto out;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
	err=register_netdev(dev);
	if (err)
	goto out1;
#endif
	return dev;
out1:
	release_region(dev->base_addr,2);
out:
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
	kfree(dev);
#else
	free_netdev(dev);

#endif
	return ERR_PTR(err);
}
*/
// add by dd /*
void dmfe_int(void)
{
	*KAIDA_SYSINTIER=*KAIDA_SYSINTIER|0x4000;  		// user int 1
	*KAIDA_SCUMASK=*KAIDA_SCUMASK|0x04;	// open ISA int 	
	*KAIDA_SYSINTIPR=*KAIDA_SYSINTIPR|0xE000;			// active low 		
	*KAIDA_SYSINTICR=*KAIDA_SYSINTICR|0xE000;
}
*/
//
int  dmfe_probe(struct net_device *dev)
{
//	printk("dmfe_probe found Net Driver  \n");
	struct board_info *db;    /* Point a board information structure */		u32 id_val;
//	u16 iobase = DM9KS_MIN_IO;
	u32 iobase = 0xBC000300 ;
//	u16 i;
	u16 dm9000_found = FALSE;
	DMFE_DBUG(0, "dmfe_probe()",0);

	/* Search All DM9000 serial NIC */
//	do {
		dmfe_outb(DM9KS_VID_L, iobase);
		id_val = dmfe_inb(iobase + 4);
		printk("id_val=%x",id_val);
		dmfe_outb(DM9KS_VID_H, iobase);
		id_val |= dmfe_inb(iobase + 4) << 8;
		dmfe_outb(DM9KS_PID_L, iobase);
		id_val |= dmfe_inb(iobase + 4) << 16;		/* Product ID */
		dmfe_outb(DM9KS_PID_H, iobase);
		//tmp=dmfe_inb(iobase + 4);
		//printk("last number is %x \n",tmp);
		id_val |= dmfe_inb(iobase + 4) << 24;
//
//		if (id_val == DM9KS_ID) {                       /* 90 00 0A 46 */
//			
//		        id_val=0x90000A46;
			printk("<NET> I/O: %x, VID: %x \n",iobase, id_val);

			dm9000_found = TRUE;

			/* Init network device */
			dev = init_etherdev(dev, 0);
			
			/* Allocated board information structure */
			db = (void *)(kmalloc(sizeof(*db), GFP_KERNEL));
		
		//add by dd ,2006,08,12 
		//	memset(dev->priv,0,sizeof(struct board_info));
		//	db=(board_info_t *)dev->priv;		
		//
			memset(db, 0, sizeof(*db));
			dev->priv   = db;   /* link device and board info */
			dmfe_dev    = dev;
			db->io_addr  = iobase;
			db->io_data = iobase + 4;

			/* driver system function */
			ether_setup(dev);
				
			dev->base_addr 		= iobase;
			dev->irq 		= irqline;
			dev->open 		= &dmfe_open;
			dev->hard_start_xmit 	= &dmfe_start_xmit;
			dev->stop 		= &dmfe_stop;
			dev->get_stats 		= &dmfe_get_stats;
			dev->set_multicast_list = &dm9000_hash_table;
			dev->do_ioctl 		= &dmfe_do_ioctl;
	//		dev->init		= &dmfe_init_dm9000; 
			




//#if defined(CHECKSUM)
//			(struct det_device*)dev->features = dev->features | NETIF_F_NO_CSUM;
//#endif

			SET_MODULE_OWNER(dev);

			/* Read SROM content */
//			for (i=0; i<64; i++)
//				((u16 *)db->srom)[i] = read_srom_word(db, i);

			/* Set Node Address */
	//		for (i=0; i<6; i++)
	//			dev->dev_addr[i] = db->srom[i];
	//modi by dd 
			memcpy(dev->dev_addr,mac,dev->addr_len);
			/* Request IO from system */
			request_region(iobase, 2, dev->name);

//		} 
//		iobase += 0x10;
//	}while(!dm9000_found && iobase <= DM9KS_MAX_IO);

	return 0;
}

/*
  Open the interface.
  The interface is opened whenever "ifconfig" actives it.
*/

static int dmfe_open(struct net_device *dev)
{
//	printk("dmfe_open \n");
	board_info_t * db = (board_info_t *)dev->priv;
	DMFE_DBUG(0, "dmfe_open", 0);
	MOD_INC_USE_COUNT;
// modi by dd 
//	if (request_irq(dev->irq,&dmfe_interrupt,SA_SHIRQ,dev->name,dev)) 

	
//if (request_irq(dev->irq,&dmfe_interrupt,SA_INTERRUPT,dev->name,dev))
        if (request_irq(dev->irq,&dmfe_interrupt,SA_SHIRQ,dev->name,dev))		{
		printk("not irq \n" );
		return -EAGAIN;
		}
// add by dd 
      //  dmfe_int();             //change 07.4.3
	/* Initilize DM910X board */
	dmfe_init_dm9000(dev);
 
	/* Init driver variable */
	db->dbug_cnt 		= 0;
	db->runt_length_counter = 0;
	db->long_length_counter = 0;
	db->reset_counter 	= 0;
	//add by dd.06.08.12
	//db->reset_tx_timeout  = 0;
	//db->cont_rx_pkt_cnt	= 0;
	//db->speed		=10;
	//
	/* set and active a timer process */
	init_timer(&db->timer);
	db->timer.expires 	= DMFE_TIMER_WUT * 2;
	db->timer.data 		= (unsigned long)dev;
	db->timer.function 	= &dmfe_timer;
	add_timer(&db->timer);	//Move to DM9000 initiallization was finished.
	
	netif_start_queue(dev);

	return 0;
}



static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
	board_info_t *db = (board_info_t *)dev->priv;
	DATA_TYPE * data_ptr;
	int i, tmplen;

	DMFE_DBUG(0, "dmfe_start_xmit", 0);

	if (db->tx_pkt_cnt >= 2)
		return 1;

	db->stats.tx_packets++;

⌨️ 快捷键说明

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