📄 ~dm9000x.c
字号:
/* dm9000.c: Version 1.2 12/15/2003 A Davicom DM9000 ISA NIC fast Ethernet driver for Linux. Copyright (C) 1997 Sten Wang 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.V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match 06/22/2001 Support DM9801 progrmming E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000 E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200 R17 = (R17 & 0xfff0) | NF + 3 E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200 R17 = (R17 & 0xfff0) | NFv1.00 modify by simon 2001.9.5 change for kernel 2.4.xv1.1 11/09/2001 fix force mode bugv1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>: Fixed phy reset. Added tx/rx 32 bit mode. Cleaned up for kernel merge.-------------------------------------- 12/15/2003 Initial port to u-boot by Sascha Hauer <saschahauer@web.de>TODO: Homerun NIC and longrun NIC are not functional, only internal at the moment.*///#include <common.h>#include "config.h"#include <types.h>#include <command.h>#include <net.h>#include <time.h>#include <printk.h>//#include <asm/io.h>#ifdef CONFIG_DRIVER_DM9000#include "dm9000x.h"/* Board/System/Debug information/definition ---------------- */#define DM9801_NOISE_FLOOR 0x08#define DM9802_NOISE_FLOOR 0x05/* #define CONFIG_DM9000_DEBUG */#define DM9000_DBG_T(fmt,args...) printk(__FUNCTION__"(): " fmt ,##args)#define DM9000_DBG_D(fmt,args...) printk(fmt ,##args)#ifdef CONFIG_DM9000_DEBUG#define DM9000_DBG(fmt,args...) printk(__FUNCTION__"(): " fmt ,##args)#else /* */#define DM9000_DBG(fmt,args...)#endif /* */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};/* 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 */ u16 tx_pkt_cnt; u16 queue_start_addr; u16 dbug_cnt; u8 phy_addr; u8 device_wait_reset; /* device state */ u8 nic_type; /* NIC type */ unsigned char srom[128];} board_info_t;board_info_t dmfe_info;/* For module input parameter */static int media_mode = DM9000_AUTO;static u8 nfloor = 0;/* function declaration ------------------------------------- */int eth_init(bd_t * bd);int eth_send(volatile void *, int);int eth_rx(void);void eth_halt(void);static int dm9000_probe(void);static u16 phy_read(int);static void phy_write(int, u16);static u16 read_srom_word(int);static u8 DM9000_ior(int);static void DM9000_iow(int reg, u8 value);/* DM9000 network board routine ---------------------------- *///#define DM9000_outb(d,r) ( *(volatile u8 *)r = d )//#define DM9000_outw(d,r) ( *(volatile u16 *)r = d )//#define DM9000_outl(d,r) ( *(volatile u32 *)r = d )//#define DM9000_inb(r) (*(volatile u8 *)r)//#define DM9000_inw(r) (*(volatile u16 *)r)//#define DM9000_inl(r) (*(volatile u32 *)r)static inline u8 DM9000_inb(u32 port){ return *(volatile u8 *)(port);}/*static inline u16 DM9000_inw(u32 port){ return *(volatile u16 *)(port);}*//*__asm__( "mov r2,%1\n" \ "ldrh %0, [r2]\n" \ : "=r" (val) \ : "r" (addr) \ : "r2");*/static inline u16 DM9000_inw(u32 addr){ register unsigned short val; __asm__ __volatile__ ( "ldrh %0, [%1]\n" \ : "=r" (val) : "r" (addr)); return val;}static inline u32 DM9000_inl(u32 port){ return *(volatile u32 *)(port);}static inline void DM9000_outb(u8 data, u32 port){ *(volatile u8 *)(port) = data;}/*static inline void DM9000_outw(u16 data, u32 port){ *(volatile u16 *)(port) = data;}*/static inline void DM9000_outw(u16 val, u32 addr){ __asm__ __volatile__( "strh %0, [%1]\n" \ :: "r" (val),"r" (addr));}static inline void DM9000_outl(u32 data, u32 port){ *(volatile u32 *)(port) = data;}#ifdef CONFIG_DM9000_DEBUGstatic voiddump_regs(void){ DM9000_DBG("\n"); DM9000_DBG("NCR (0x00): %02x\n", DM9000_ior(0)); DM9000_DBG("NSR (0x01): %02x\n", DM9000_ior(1)); DM9000_DBG("TCR (0x02): %02x\n", DM9000_ior(2)); DM9000_DBG("TSRI (0x03): %02x\n", DM9000_ior(3)); DM9000_DBG("TSRII (0x04): %02x\n", DM9000_ior(4)); DM9000_DBG("RCR (0x05): %02x\n", DM9000_ior(5)); DM9000_DBG("RSR (0x06): %02x\n", DM9000_ior(6)); DM9000_DBG("ISR (0xFE): %02x\n", DM9000_ior(DM9000_ISR)); DM9000_DBG("\n");}#endif /* *//* Search DM9000 board, allocate space and register it*/intdm9000_probe(void){ u32 id_val; id_val = DM9000_ior(DM9000_VIDL); id_val |= DM9000_ior(DM9000_VIDH) << 8; id_val |= DM9000_ior(DM9000_PIDL) << 16; id_val |= DM9000_ior(DM9000_PIDH) << 24; if (id_val == DM9000_ID) { printk("dm9000 i/o: 0x%x, id: 0x%x \n", CONFIG_DM9000_BASE, id_val); return 0; } else { printk("dm9000 not found at 0x%08x id: 0x%08x\n", CONFIG_DM9000_BASE, id_val); return -1; }}/* Set PHY operationg mode*/static voidset_PHY_mode(void){ u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1200; if (!(media_mode & DM9000_AUTO)) { switch (media_mode) { case DM9000_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x1000; break; case DM9000_10MFD: phy_reg4 = 0x41; phy_reg0 = 0x1100; break; case DM9000_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x3000; break; case DM9000_100MFD: phy_reg4 = 0x101; phy_reg0 = 0x3100; break; } } phy_write(0, phy_reg0); /* Tmp */ phy_write(4, phy_reg4); /* Set PHY media mode */ DM9000_iow(DM9000_GPCR, 0x01); /* Let GPIO0 output */ DM9000_iow(DM9000_GPR, 0x00); /* Enable PHY */}/* Init HomeRun DM9801*/static voidprogram_dm9801(u16 HPNA_rev){ __u16 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 voidprogram_dm9802(void){ __u16 reg25; if (!nfloor) nfloor = DM9802_NOISE_FLOOR; reg25 = phy_read(25); reg25 = (reg25 & 0xff00) + nfloor; phy_write(25, reg25);}/* Identify NIC type*/static voididentify_nic(void){ struct board_info *db = &dmfe_info; /* Point a board information structure */ u16 phy_reg3; DM9000_iow(DM9000_NCR, NCR_EXT_PHY); 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); DM9000_DBG("found homerun NIC\n"); } else { db->nic_type = LONGRUN_NIC; DM9000_DBG("found longrun NIC\n"); program_dm9802(); } break; default: db->nic_type = FASTETHER_NIC; break; } DM9000_iow(DM9000_NCR, 0);}/* General Purpose dm9000 reset routine */static voiddm9000_reset(void){ DM9000_DBG("resetting\n"); /* set the internal PHY power-on, GPIOs normal, and wait 2ms */ DM9000_iow(DM9000_GPR, 1); /* Power-Down PHY */ udelay(500); DM9000_iow(DM9000_GPR, 0); /* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */ udelay(20); /* wait 2ms for PHY power-on ready */ //DM9000_iow(DM9000_NCR, NCR_RST); DM9000_iow(DM9000_NCR, 3); udelay(20); /* delay 20us */ //DM9000_iow(DM9000_NCR, NCR_RST); DM9000_iow(DM9000_NCR, 3); udelay(1000); /* delay 1ms */}/* Initilize dm9000 board*/inteth_init(bd_t * bd){ int i, oft, lnk; DM9000_DBG("eth_init()\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -