📄 ethernet_dm9000.c
字号:
/****************************************Copyright (c)**************************************************** uestc EMBEDDED LAB QMY****--------------File Info-------------------------------------------------------------------------------** File name: dm9000.c** Last modified Date: 2008-07-07** Last Version: 1.0** Descriptions: DM9000E driver**------------------------------------------------------------------------------------------------------** Created by: qmy** Created date: 2008-06-16** Version: 1.0** Descriptions: The original version****------------------------------------------------------------------------------------------------------** ********************************************************************************************************/#define IN_DM9000#include "config.h"#include "dm9000.h"#define DW8 (0x0)#define DW16 (0x1)#define DW32 (0x2)#define WAIT (0x1<<2)#define UBLB (0x1<<3)#define B7_BWCON (DW16|WAIT|UBLB) #define B6_BWCON (DW32|UBLB) #define B5_BWCON (DW16|WAIT|UBLB) #define B4_BWCON (DW16|WAIT|UBLB) #define B3_BWCON (DW16|WAIT) #define B2_BWCON (DW16|WAIT|UBLB) #define B1_BWCON (DW16|WAIT|UBLB) #define B3_TACS (0X3)//0:0CLOCK 1:1CLOCK 2:2CLOCK 3:4CLOCK#define B3_TCOS (0X3)//0:0CLOCK 1:1CLOCK 2:2CLOCK 3:4CLOCK#define B3_TACC (0X7)//0:1CLOCK 1:2CLOCK 2:3CLOCK 3:4CLOCK 4:6CLOCK 5:8CLOCK 6:10CLOCK 7:14CLOCK#define B3_TCOH (0X3)//0:0CLOCK 1:1CLOCK 2:2CLOCK 3:4CLOCK#define B3_TCAH (0X3)//0:0CLOCK 1:1CLOCK 2:2CLOCK 3:4CLOCK#define DM9000_REG00 0x00#define DM9000_REG05 0x0c /*DISCARD LONG\CRC_ERR\mutilcast\Promiscuous,Pass Runt,RX not enable *///0x30 /* SKIP_CRC/SKIP_LONG */#define DM9000_REG08 0x37#define DM9000_REG09 0x38#define DM9000_REG0A 0xff #define DM9000_REGFF 0x83 /* IMR return auto;TX lunch;RX lunch*//******************************************************************************************************** function announce********************************************************************************************************/static int net_init(struct net_device *dev);static int net_open(struct net_device *dev);static int net_release(struct net_device *dev); static int net_config(struct net_device *dev, struct ifmap *map);static int net_tx(struct sk_buff *skb, struct net_device *dev);static void net_irq_handle(int irq, void *dev_id, struct pt_regs *regs);static int net_set_mac_address(struct net_device *dev, void *addr);int net_init_module(void);void net_cleanup(void);static void net_tasklet(unsigned long);/******************************************************************************************************** define announce********************************************************************************************************/static struct net_device *DM9000Dev;module_init(net_init_module);module_exit(net_cleanup);DECLARE_TASKLET(ZLG_net_tasklet, net_tasklet, (unsigned long)(&DM9000Dev));MODULE_LICENSE("Proprietary");MODULE_DESCRIPTION("GUANGZHOU ZHIYUAN ELECTRONICS Co.,LTD.\ngraduate school\nhttp://www.zyinside.com");MODULE_SUPPORTED_DEVICE("Linux 2.4.18 MagicARM2410 DM9000");MODULE_AUTHOR("Yehaoben");/*********************************************************************************************************** "全局和静态变量在这里定义" ** global variables and static variables define here********************************************************************************************************/static unsigned int usage;static u32 PinSel0Save;static board_info_t NetDriverInfo[1];/********************************************************************************************************/static struct net_device net_net ={ init: net_init,};/*********************************************************************************************************** Function name: ior**** Descriptions: read a reg form dm9000 **** input parameters: board_info_t *db ;dm9000 status struct** reg ;reg address of dm9000** Returned value: uint8 ;reg value ** ** Used global variables: None** Calling modules: None**** **-------------------------------------------------------------------------------------------------------** Modified by:** Modified date:**------------------------------------------------------------------------------------------------------********************************************************************************************************/static uint8 ior(board_info_t *db, uint8 reg){ unsigned int i; unsigned int rt; outb(reg, db->ioaddr); for (i = 0; i < BUS_DELAY; i++) { } rt = inb(db->io_data); for (i = 0; i < BUS_DELAY; i++) { } return rt;}/*********************************************************************************************************** Function name: iow**** Descriptions: write a value to a dm9000 reg **** input parameters: board_info_t *db ;dm9000 status struct** reg ;reg address of dm9000** value ;reg value ** Returned value: None ** ** Used global variables: None** Calling modules: None**** **-------------------------------------------------------------------------------------------------------** Modified by:** Modified date:**------------------------------------------------------------------------------------------------------********************************************************************************************************/ static void iow(board_info_t *db, uint8 reg, uint8 value){ unsigned int i; outb(reg, db->ioaddr); for(i = 0; i<BUS_DELAY; i++) { } outb(value, db->io_data); for(i = 0; i<BUS_DELAY; i++) { }}/*********************************************************************************************************** Function name: phy_write**** Descriptions: write a value to PHY device reg **** input parameters: board_info_t *db ;dm9000 status struct** reg ;reg address of PHY device** value ;reg value ** Returned value: None ** ** Used global variables: None** Calling modules: None**** **-------------------------------------------------------------------------------------------------------** Modified by:** Modified date:**------------------------------------------------------------------------------------------------------********************************************************************************************************/ static void phy_write(board_info_t *db, uint8 reg, uint16 value){ /* Fill the phyxcer register into REG_0C */ iow(db, 0xc, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow(db, 0xd, (value & 0xff)); iow(db, 0xe, ( (value >> 8) & 0xff)); iow(db, 0xb, 0xa); /* Issue phyxcer write command */ udelay(500); /* Wait write complete */ iow(db, 0xb, 0x0); /* Clear phyxcer write command */}/*********************************************************************************************************** Function name: set_PHY_mode**** Descriptions: set the PHY device working **** input parameters: board_info_t *db ;dm9000 status struct** ** Returned value: None ** ** Used global variables: None** Calling modules: None**** **-------------------------------------------------------------------------------------------------------** Modified by:** Modified date:**------------------------------------------------------------------------------------------------------********************************************************************************************************/ static void set_PHY_mode(board_info_t *db){ unsigned int phy_reg4 = 0x01e1, phy_reg0=0x1000; if ( !(db->op_mode & DM9000_AUTO)) { switch(db->op_mode) { case DM9000_10MHD: phy_reg4 = 0x21; /* 10M HALF DUPLEX*/ phy_reg0 = 0x0000; break; case DM9000_10MFD: phy_reg4 = 0x41; /* 10M FULL DUPLEX*/ phy_reg0 = 0x1100; break; case DM9000_100MHD: phy_reg4 = 0x81; /* 100M HALF DUPLEX*/ phy_reg0 = 0x2000; break; case DM9000_100MFD: phy_reg4 = 0x101;/* 100M HALF DUPLEX */ phy_reg0 = 0x3100; break; default: break; } phy_write(db, 4, phy_reg4); /* Set PHY media mode */ phy_write(db, 0, phy_reg0); /* Tmp */ } iow(db, 0x1e, 0x01); /* Let GPIO0 output */ iow(db, 0x1f, 0x00); /* Enable PHY */}/*********************************************************************************************************** Function name: device_init** Descriptions: device init** Input: dev: information of device** ** Output: 0: OK** other: errno** **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/ static int device_init(struct net_device *dev){ unsigned long flag; uint8 i; uint8 temp[16]; board_info_t *db = dev->priv; db->ioaddr = IOaddress0; db->io_data = IOaddress0 + 4; local_irq_save(flag); /* 硬件复位复位 */ Hardware_Initial0(); /* RESET device */ /*Hardware Reset*/ Hardware_Reset_Clr0(); udelay(500); Hardware_Reset_Set0(); udelay(500); Hardware_Reset_Clr0(); udelay(500); /*software reset*/ iow(db, 0, 1); udelay(500); /* delay 100us */ // printk(KERN_ERR "%d\n",ior(db, 0x28)); // printk(KERN_ERR "%d\n",ior(db, 0x29)); /* I/O mode */ db->io_mode = ior(db, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode *///read the io mode (8/16/32bits) //printk(KERN_ERR "%d\n",db->io_mode); /* NIC Type: FASTETHER, HOMERUN, LONGRUN */ db->nic_type = FASTETHER_NIC; //identify_nic(db); //just check for dm9801 or dm9802 /* GPIO0 on pre-activate PHY */ iow(db, 0x1f, 0x00); /*REG_1F bit0 activate internal phyxcer*/ /* Set PHY */ db->op_mode = DM9000_AUTO;//may set it to be each one of DM9000_PHY_mode type. set_PHY_mode(db); /* Init needed register value */ db->reg0 = DM9000_REG00; if ((db->nic_type != FASTETHER_NIC) && (db->op_mode & DM9000_1M_HPNA) )//for dm9801 or dm9802 { db->reg0 |= DM9000_EXT_MII; } /* User passed argument */ db->reg5 = DM9000_REG05; db->reg8 = DM9000_REG08; db->reg9 = DM9000_REG09; db->rega = DM9000_REG0A; /* Program operating register */ iow(db, 0x00, db->reg0);/* DISCARD LONG\CRC_ERR\mutilcast\Promiscuous\WatchDog,Pass Runt,RX not enable */ iow(db, 0x02, 0X14); /* TX Polling clear *///??????????????enable the PAD //OLD VALUE IS 0X00 iow(db, 0x08, 0x3f); /* Less 3Kb, 600us */ iow(db, 0x09, db->reg9); /* Flow Control : High/Low Water */ iow(db, 0x0a, db->rega); /* Flow Control */ iow(db, 0x2f, 0); /* Special Mode */ iow(db, 0x01, 0x2c); /* clear TX status *///clear wakeup status; clear TX2END and TX1END iow(db, 0xfe, 0x0f); /* Clear interrupt status */ /* Set address filter table */ for(i = 0; i < 6; i++) { db->nic_mac[i] = MyMacID[i]; } for(i = 0; i < 6; i++) { iow(db, 0x10 + i, db->nic_mac[i]); //将芯片物理地址写入到MAC寄存器 } /* Activate DM9000 */ iow(db, 0x05, db->reg5 | 1); /* RX enable */ iow(db, 0xff, DM9000_REGFF); /* Enable TX/RX interrupt mask */ //udelay(5000); local_irq_restore(flag); return 0;}/*********************************************************************************************************** Function name: net_init** Descriptions: net device init** Input: dev: information of device** ** Output: 0: OK** other: errno** **-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/ static int net_init(struct net_device *dev){ ether_setup(dev); /* assign some of the fields */ strcpy(dev->name, "eth0"); dev->open = net_open; dev->stop = net_release; dev->set_config = net_config; dev->hard_start_xmit = net_tx; dev->set_mac_address = net_set_mac_address; dev->flags &= ~(IFF_LOOPBACK | IFF_MULTICAST); dev->priv = NetDriverInfo; dev->base_addr = IOaddress0, dev->irq = NET_IRQ, //dev->watchdog_timeo = NET_TIMEOUT; memcpy(dev->dev_addr, MyMacID, dev->addr_len); SET_MODULE_OWNER(dev); return 0;}/*********************************************************************************************************** Function name: net_config** Descriptions: config device** Input: dev: information of device** map: config data** Output: 0: OK** other: errno****-------------------------------------------------------------------------------------------------------** Modified by:** Modified Date: **------------------------------------------------------------------------------------------------------********************************************************************************************************/ static int net_config(struct net_device *dev, struct ifmap *map){ return -EBUSY;}/*********************************************************************************************************** Function name: net_set_mac_address** Descriptions: set mac address** Input: dev: information of device
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -