📄 davicom.c
字号:
/* DAVICOM DM9009/DM9102/DM9102A Etherboot Driver V1.00 This driver was ported from Marty Conner's Tulip Etherboot driver. Thanks Marty Connor (mdc@thinguin.org) You can get Tulip driver source file from this URL: "http://etherboot.sourceforge..net/#Distribution" This davicom etherboot driver supports DM9009/DM9102/DM9102A/ DM9102A+DM9801/DM9102A+DM9802 NICs. This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference.*//*********************************************************************//* Revision History *//*********************************************************************//* 19 OCT 2000 Sten 1.00 Different half and full duplex mode Do the different programming for DM9801/DM9802 12 OCT 2000 Sten 0.90 This driver was ported from tulip driver and it has the following difference. Changed symbol tulip/TULIP to davicom/DAVICOM Deleted some code that did not use in this driver. Used chain-strcture to replace ring structure for both TX/RX descriptor. Allocated two tx descriptor. According current media mode to set operating register(CR6)*//*********************************************************************//* Declarations *//*********************************************************************/#include "etherboot.h"#include "nic.h"#include "pci.h"#include "cards.h"#undef DAVICOM_DEBUG#undef DAVICOM_DEBUG_WHERE#define TX_TIME_OUT 2*TICKS_PER_SECtypedef unsigned char u8;typedef signed char s8;typedef unsigned short u16;typedef signed short s16;typedef unsigned int u32;typedef signed int s32;/* Register offsets for davicom device */enum davicom_offsets { CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28, CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58, CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0};/* EEPROM Address width definitions */#define EEPROM_ADDRLEN 6#define EEPROM_SIZE 32 /* 1 << EEPROM_ADDRLEN *//* Used to be 128, but we only need to read enough to get the MAC address at bytes 20..25 *//* Data Read from the EEPROM */static unsigned char ee_data[EEPROM_SIZE];/* The EEPROM commands include the alway-set leading bit. */#define EE_WRITE_CMD (5 << addr_len)#define EE_READ_CMD (6 << addr_len)#define EE_ERASE_CMD (7 << addr_len)/* EEPROM_Ctrl bits. */#define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */#define EE_CS 0x01 /* EEPROM chip select. */#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */#define EE_WRITE_0 0x01#define EE_WRITE_1 0x05#define EE_DATA_READ 0x08 /* EEPROM chip data out. */#define EE_ENB (0x4800 | EE_CS)/* Sten 10/11 for phyxcer */#define PHY_DATA_0 0x0#define PHY_DATA_1 0x20000#define MDCLKH 0x10000/* Delay between EEPROM clock transitions. Even at 33Mhz current PCI implementations don't overrun the EEPROM clock. We add a bus turn-around to insure that this remains true. */#define eeprom_delay() inl(ee_addr)/* helpful macro if on a big_endian machine for changing byte order. not strictly needed on Intel */#define le16_to_cpu(val) (val)/* transmit and receive descriptor format */struct txdesc { volatile unsigned long status; /* owner, status */ unsigned long buf1sz:11, /* size of buffer 1 */ buf2sz:11, /* size of buffer 2 */ control:10; /* control bits */ const unsigned char *buf1addr; /* buffer 1 address */ const unsigned char *buf2addr; /* buffer 2 address */};struct rxdesc { volatile unsigned long status; /* owner, status */ unsigned long buf1sz:11, /* size of buffer 1 */ buf2sz:11, /* size of buffer 2 */ control:10; /* control bits */ unsigned char *buf1addr; /* buffer 1 address */ unsigned char *buf2addr; /* buffer 2 address */};/* Size of transmit and receive buffers */#define BUFLEN 1536/*********************************************************************//* Global Storage *//*********************************************************************//* PCI Bus parameters */static unsigned short vendor, dev_id;static unsigned long ioaddr;/* Note: transmit and receive buffers must be longword aligned and longword divisable *//* transmit descriptor and buffer */#define NTXD 2static struct txdesc txd[NTXD] __attribute__ ((aligned(4)));#ifdef USE_LOWMEM_BUFFER#define txb ((char *)0x10000 - BUFLEN)#elsestatic unsigned char txb[BUFLEN] __attribute__ ((aligned(4)));#endif/* receive descriptor(s) and buffer(s) */#define NRXD 4static struct rxdesc rxd[NRXD] __attribute__ ((aligned(4)));#ifdef USE_LOWMEM_BUFFER#define rxb ((char *)0x10000 - NRXD * BUFLEN - BUFLEN)#elsestatic unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4)));#endifstatic int rxd_tail;static int TxPtr;/*********************************************************************//* Function Prototypes *//*********************************************************************/static void whereami(const char *str);static int read_eeprom(unsigned long ioaddr, int location, int addr_len);struct nic *davicom_probe(struct nic *nic, unsigned short *io_addrs, struct pci_device *pci);static void davicom_init_chain(struct nic *nic); /* Sten 10/9 */static void davicom_reset(struct nic *nic);static void davicom_transmit(struct nic *nic, const char *d, unsigned int t, unsigned int s, const char *p);static int davicom_poll(struct nic *nic);static void davicom_disable(struct nic *nic);static void whereami (const char *str);#ifdef DAVICOM_DEBUGstatic void davicom_more(void);#endif /* DAVICOM_DEBUG */static void davicom_wait(unsigned int nticks);static int phy_read(int);static void phy_write(int, u16);static void phy_write_1bit(u32, u32);static int phy_read_1bit(u32);static void davicom_media_chk(struct nic *);/*********************************************************************//* Utility Routines *//*********************************************************************/static inline void whereami (const char *str){#ifdef DAVICOM_DEBUG_WHERE printf("%s\n", str); /* sleep(2); */#endif}#ifdef DAVICOM_DEBUGstatic void davicom_more(){ printf("\n\n-- more --"); while (!iskey()) /* wait */; getchar(); printf("\n\n");}#endif /* DAVICOM_DEBUG */static void davicom_wait(unsigned int nticks){ unsigned int to = currticks() + nticks; while (currticks() < to) /* wait */ ;}/*********************************************************************//* For DAVICOM phyxcer register by MII interface *//*********************************************************************//* Read a word data from phy register*/static int phy_read(int location){ int i, phy_addr=1; u16 phy_data; u32 io_dcr9; whereami("phy_read\n"); io_dcr9 = ioaddr + CSR9; /* Send 33 synchronization clock to Phy controller */ for (i=0; i<34; i++) phy_write_1bit(io_dcr9, PHY_DATA_1); /* Send start command(01) to Phy */ phy_write_1bit(io_dcr9, PHY_DATA_0); phy_write_1bit(io_dcr9, PHY_DATA_1); /* Send read command(10) to Phy */ phy_write_1bit(io_dcr9, PHY_DATA_1); phy_write_1bit(io_dcr9, PHY_DATA_0); /* Send Phy addres */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0); /* Send register addres */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); /* Skip transition state */ phy_read_1bit(io_dcr9); /* read 16bit data */ for (phy_data=0, i=0; i<16; i++) { phy_data<<=1; phy_data|=phy_read_1bit(io_dcr9); } return phy_data;}/* Write a word to Phy register*/static void phy_write(int location, u16 phy_data){ u16 i, phy_addr=1; u32 io_dcr9; whereami("phy_write\n"); io_dcr9 = ioaddr + CSR9; /* Send 33 synchronization clock to Phy controller */ for (i=0; i<34; i++) phy_write_1bit(io_dcr9, PHY_DATA_1); /* Send start command(01) to Phy */ phy_write_1bit(io_dcr9, PHY_DATA_0); phy_write_1bit(io_dcr9, PHY_DATA_1); /* Send write command(01) to Phy */ phy_write_1bit(io_dcr9, PHY_DATA_0); phy_write_1bit(io_dcr9, PHY_DATA_1); /* Send Phy addres */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0); /* Send register addres */ for (i=0x10; i>0; i=i>>1) phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); /* written trasnition */ phy_write_1bit(io_dcr9, PHY_DATA_1); phy_write_1bit(io_dcr9, PHY_DATA_0); /* Write a word data to PHY controller */ for (i=0x8000; i>0; i>>=1) phy_write_1bit(io_dcr9, phy_data&i ? PHY_DATA_1: PHY_DATA_0);}/* Write one bit data to Phy Controller*/static void phy_write_1bit(u32 ee_addr, u32 phy_data){ whereami("phy_write_1bit\n"); outl(phy_data, ee_addr); /* MII Clock Low */ eeprom_delay(); outl(phy_data|MDCLKH, ee_addr); /* MII Clock High */ eeprom_delay(); outl(phy_data, ee_addr); /* MII Clock Low */ eeprom_delay();}/* Read one bit phy data from PHY controller*/static int phy_read_1bit(u32 ee_addr){ int phy_data; whereami("phy_read_1bit\n"); outl(0x50000, ee_addr); eeprom_delay(); phy_data=(inl(ee_addr)>>19) & 0x1; outl(0x40000, ee_addr); eeprom_delay(); return phy_data;}/* DM9801/DM9802 present check and program */static void HPNA_process(void){ if ( (phy_read(3) & 0xfff0) == 0xb900 ) { if ( phy_read(31) == 0x4404 ) { /* DM9801 present */ if (phy_read(3) == 0xb901)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -