1*1b8adde7SWilliam Kucharski #ifdef ALLMULTI 2*1b8adde7SWilliam Kucharski #error multicast support is not yet implemented 3*1b8adde7SWilliam Kucharski #endif 4*1b8adde7SWilliam Kucharski /* 5*1b8adde7SWilliam Kucharski DAVICOM DM9009/DM9102/DM9102A Etherboot Driver V1.00 6*1b8adde7SWilliam Kucharski 7*1b8adde7SWilliam Kucharski This driver was ported from Marty Connor's Tulip Etherboot driver. 8*1b8adde7SWilliam Kucharski Thanks Marty Connor (mdc@etherboot.org) 9*1b8adde7SWilliam Kucharski 10*1b8adde7SWilliam Kucharski This davicom etherboot driver supports DM9009/DM9102/DM9102A/ 11*1b8adde7SWilliam Kucharski DM9102A+DM9801/DM9102A+DM9802 NICs. 12*1b8adde7SWilliam Kucharski 13*1b8adde7SWilliam Kucharski This software may be used and distributed according to the terms 14*1b8adde7SWilliam Kucharski of the GNU Public License, incorporated herein by reference. 15*1b8adde7SWilliam Kucharski 16*1b8adde7SWilliam Kucharski */ 17*1b8adde7SWilliam Kucharski 18*1b8adde7SWilliam Kucharski /*********************************************************************/ 19*1b8adde7SWilliam Kucharski /* Revision History */ 20*1b8adde7SWilliam Kucharski /*********************************************************************/ 21*1b8adde7SWilliam Kucharski 22*1b8adde7SWilliam Kucharski /* 23*1b8adde7SWilliam Kucharski 19 OCT 2000 Sten 1.00 24*1b8adde7SWilliam Kucharski Different half and full duplex mode 25*1b8adde7SWilliam Kucharski Do the different programming for DM9801/DM9802 26*1b8adde7SWilliam Kucharski 27*1b8adde7SWilliam Kucharski 12 OCT 2000 Sten 0.90 28*1b8adde7SWilliam Kucharski This driver was ported from tulip driver and it 29*1b8adde7SWilliam Kucharski has the following difference. 30*1b8adde7SWilliam Kucharski Changed symbol tulip/TULIP to davicom/DAVICOM 31*1b8adde7SWilliam Kucharski Deleted some code that did not use in this driver. 32*1b8adde7SWilliam Kucharski Used chain-strcture to replace ring structure 33*1b8adde7SWilliam Kucharski for both TX/RX descriptor. 34*1b8adde7SWilliam Kucharski Allocated two tx descriptor. 35*1b8adde7SWilliam Kucharski According current media mode to set operating 36*1b8adde7SWilliam Kucharski register(CR6) 37*1b8adde7SWilliam Kucharski */ 38*1b8adde7SWilliam Kucharski 39*1b8adde7SWilliam Kucharski /*********************************************************************/ 40*1b8adde7SWilliam Kucharski /* Declarations */ 41*1b8adde7SWilliam Kucharski /*********************************************************************/ 42*1b8adde7SWilliam Kucharski 43*1b8adde7SWilliam Kucharski #include "etherboot.h" 44*1b8adde7SWilliam Kucharski #include "nic.h" 45*1b8adde7SWilliam Kucharski #include "pci.h" 46*1b8adde7SWilliam Kucharski 47*1b8adde7SWilliam Kucharski #undef DAVICOM_DEBUG 48*1b8adde7SWilliam Kucharski #undef DAVICOM_DEBUG_WHERE 49*1b8adde7SWilliam Kucharski 50*1b8adde7SWilliam Kucharski #define TX_TIME_OUT 2*TICKS_PER_SEC 51*1b8adde7SWilliam Kucharski 52*1b8adde7SWilliam Kucharski typedef unsigned char u8; 53*1b8adde7SWilliam Kucharski typedef signed char s8; 54*1b8adde7SWilliam Kucharski typedef unsigned short u16; 55*1b8adde7SWilliam Kucharski typedef signed short s16; 56*1b8adde7SWilliam Kucharski typedef unsigned int u32; 57*1b8adde7SWilliam Kucharski typedef signed int s32; 58*1b8adde7SWilliam Kucharski 59*1b8adde7SWilliam Kucharski /* Register offsets for davicom device */ 60*1b8adde7SWilliam Kucharski enum davicom_offsets { 61*1b8adde7SWilliam Kucharski CSR0=0, CSR1=0x08, CSR2=0x10, CSR3=0x18, CSR4=0x20, CSR5=0x28, 62*1b8adde7SWilliam Kucharski CSR6=0x30, CSR7=0x38, CSR8=0x40, CSR9=0x48, CSR10=0x50, CSR11=0x58, 63*1b8adde7SWilliam Kucharski CSR12=0x60, CSR13=0x68, CSR14=0x70, CSR15=0x78, CSR16=0x80, CSR20=0xA0 64*1b8adde7SWilliam Kucharski }; 65*1b8adde7SWilliam Kucharski 66*1b8adde7SWilliam Kucharski /* EEPROM Address width definitions */ 67*1b8adde7SWilliam Kucharski #define EEPROM_ADDRLEN 6 68*1b8adde7SWilliam Kucharski #define EEPROM_SIZE 32 /* 1 << EEPROM_ADDRLEN */ 69*1b8adde7SWilliam Kucharski /* Used to be 128, but we only need to read enough to get the MAC 70*1b8adde7SWilliam Kucharski address at bytes 20..25 */ 71*1b8adde7SWilliam Kucharski 72*1b8adde7SWilliam Kucharski /* Data Read from the EEPROM */ 73*1b8adde7SWilliam Kucharski static unsigned char ee_data[EEPROM_SIZE]; 74*1b8adde7SWilliam Kucharski 75*1b8adde7SWilliam Kucharski /* The EEPROM commands include the alway-set leading bit. */ 76*1b8adde7SWilliam Kucharski #define EE_WRITE_CMD (5 << addr_len) 77*1b8adde7SWilliam Kucharski #define EE_READ_CMD (6 << addr_len) 78*1b8adde7SWilliam Kucharski #define EE_ERASE_CMD (7 << addr_len) 79*1b8adde7SWilliam Kucharski 80*1b8adde7SWilliam Kucharski /* EEPROM_Ctrl bits. */ 81*1b8adde7SWilliam Kucharski #define EE_SHIFT_CLK 0x02 /* EEPROM shift clock. */ 82*1b8adde7SWilliam Kucharski #define EE_CS 0x01 /* EEPROM chip select. */ 83*1b8adde7SWilliam Kucharski #define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ 84*1b8adde7SWilliam Kucharski #define EE_WRITE_0 0x01 85*1b8adde7SWilliam Kucharski #define EE_WRITE_1 0x05 86*1b8adde7SWilliam Kucharski #define EE_DATA_READ 0x08 /* EEPROM chip data out. */ 87*1b8adde7SWilliam Kucharski #define EE_ENB (0x4800 | EE_CS) 88*1b8adde7SWilliam Kucharski 89*1b8adde7SWilliam Kucharski /* Sten 10/11 for phyxcer */ 90*1b8adde7SWilliam Kucharski #define PHY_DATA_0 0x0 91*1b8adde7SWilliam Kucharski #define PHY_DATA_1 0x20000 92*1b8adde7SWilliam Kucharski #define MDCLKH 0x10000 93*1b8adde7SWilliam Kucharski 94*1b8adde7SWilliam Kucharski /* Delay between EEPROM clock transitions. Even at 33Mhz current PCI 95*1b8adde7SWilliam Kucharski implementations don't overrun the EEPROM clock. We add a bus 96*1b8adde7SWilliam Kucharski turn-around to insure that this remains true. */ 97*1b8adde7SWilliam Kucharski #define eeprom_delay() inl(ee_addr) 98*1b8adde7SWilliam Kucharski 99*1b8adde7SWilliam Kucharski /* helpful macro if on a big_endian machine for changing byte order. 100*1b8adde7SWilliam Kucharski not strictly needed on Intel 101*1b8adde7SWilliam Kucharski Already defined in Etherboot includes 102*1b8adde7SWilliam Kucharski #define le16_to_cpu(val) (val) 103*1b8adde7SWilliam Kucharski */ 104*1b8adde7SWilliam Kucharski 105*1b8adde7SWilliam Kucharski /* transmit and receive descriptor format */ 106*1b8adde7SWilliam Kucharski struct txdesc { 107*1b8adde7SWilliam Kucharski volatile unsigned long status; /* owner, status */ 108*1b8adde7SWilliam Kucharski unsigned long buf1sz:11, /* size of buffer 1 */ 109*1b8adde7SWilliam Kucharski buf2sz:11, /* size of buffer 2 */ 110*1b8adde7SWilliam Kucharski control:10; /* control bits */ 111*1b8adde7SWilliam Kucharski const unsigned char *buf1addr; /* buffer 1 address */ 112*1b8adde7SWilliam Kucharski const unsigned char *buf2addr; /* buffer 2 address */ 113*1b8adde7SWilliam Kucharski }; 114*1b8adde7SWilliam Kucharski 115*1b8adde7SWilliam Kucharski struct rxdesc { 116*1b8adde7SWilliam Kucharski volatile unsigned long status; /* owner, status */ 117*1b8adde7SWilliam Kucharski unsigned long buf1sz:11, /* size of buffer 1 */ 118*1b8adde7SWilliam Kucharski buf2sz:11, /* size of buffer 2 */ 119*1b8adde7SWilliam Kucharski control:10; /* control bits */ 120*1b8adde7SWilliam Kucharski unsigned char *buf1addr; /* buffer 1 address */ 121*1b8adde7SWilliam Kucharski unsigned char *buf2addr; /* buffer 2 address */ 122*1b8adde7SWilliam Kucharski }; 123*1b8adde7SWilliam Kucharski 124*1b8adde7SWilliam Kucharski /* Size of transmit and receive buffers */ 125*1b8adde7SWilliam Kucharski #define BUFLEN 1536 126*1b8adde7SWilliam Kucharski 127*1b8adde7SWilliam Kucharski /*********************************************************************/ 128*1b8adde7SWilliam Kucharski /* Global Storage */ 129*1b8adde7SWilliam Kucharski /*********************************************************************/ 130*1b8adde7SWilliam Kucharski 131*1b8adde7SWilliam Kucharski /* PCI Bus parameters */ 132*1b8adde7SWilliam Kucharski static unsigned short vendor, dev_id; 133*1b8adde7SWilliam Kucharski static unsigned long ioaddr; 134*1b8adde7SWilliam Kucharski 135*1b8adde7SWilliam Kucharski /* Note: transmit and receive buffers must be longword aligned and 136*1b8adde7SWilliam Kucharski longword divisable */ 137*1b8adde7SWilliam Kucharski 138*1b8adde7SWilliam Kucharski /* transmit descriptor and buffer */ 139*1b8adde7SWilliam Kucharski #define NTXD 2 140*1b8adde7SWilliam Kucharski static struct txdesc txd[NTXD] __attribute__ ((aligned(4))); 141*1b8adde7SWilliam Kucharski static unsigned char txb[BUFLEN] __attribute__ ((aligned(4))); 142*1b8adde7SWilliam Kucharski 143*1b8adde7SWilliam Kucharski /* receive descriptor(s) and buffer(s) */ 144*1b8adde7SWilliam Kucharski #define NRXD 4 145*1b8adde7SWilliam Kucharski static struct rxdesc rxd[NRXD] __attribute__ ((aligned(4))); 146*1b8adde7SWilliam Kucharski static unsigned char rxb[NRXD * BUFLEN] __attribute__ ((aligned(4))); 147*1b8adde7SWilliam Kucharski static int rxd_tail; 148*1b8adde7SWilliam Kucharski static int TxPtr; 149*1b8adde7SWilliam Kucharski 150*1b8adde7SWilliam Kucharski 151*1b8adde7SWilliam Kucharski /*********************************************************************/ 152*1b8adde7SWilliam Kucharski /* Function Prototypes */ 153*1b8adde7SWilliam Kucharski /*********************************************************************/ 154*1b8adde7SWilliam Kucharski static void whereami(const char *str); 155*1b8adde7SWilliam Kucharski static int read_eeprom(unsigned long ioaddr, int location, int addr_len); 156*1b8adde7SWilliam Kucharski static int davicom_probe(struct dev *dev, struct pci_device *pci); 157*1b8adde7SWilliam Kucharski static void davicom_init_chain(struct nic *nic); /* Sten 10/9 */ 158*1b8adde7SWilliam Kucharski static void davicom_reset(struct nic *nic); 159*1b8adde7SWilliam Kucharski static void davicom_transmit(struct nic *nic, const char *d, unsigned int t, 160*1b8adde7SWilliam Kucharski unsigned int s, const char *p); 161*1b8adde7SWilliam Kucharski static int davicom_poll(struct nic *nic, int retrieve); 162*1b8adde7SWilliam Kucharski static void davicom_disable(struct dev *dev); 163*1b8adde7SWilliam Kucharski #ifdef DAVICOM_DEBUG 164*1b8adde7SWilliam Kucharski static void davicom_more(void); 165*1b8adde7SWilliam Kucharski #endif /* DAVICOM_DEBUG */ 166*1b8adde7SWilliam Kucharski static void davicom_wait(unsigned int nticks); 167*1b8adde7SWilliam Kucharski static int phy_read(int); 168*1b8adde7SWilliam Kucharski static void phy_write(int, u16); 169*1b8adde7SWilliam Kucharski static void phy_write_1bit(u32, u32); 170*1b8adde7SWilliam Kucharski static int phy_read_1bit(u32); 171*1b8adde7SWilliam Kucharski static void davicom_media_chk(struct nic *); 172*1b8adde7SWilliam Kucharski 173*1b8adde7SWilliam Kucharski 174*1b8adde7SWilliam Kucharski /*********************************************************************/ 175*1b8adde7SWilliam Kucharski /* Utility Routines */ 176*1b8adde7SWilliam Kucharski /*********************************************************************/ 177*1b8adde7SWilliam Kucharski static inline void whereami(const char *str) 178*1b8adde7SWilliam Kucharski { 179*1b8adde7SWilliam Kucharski printf("%s\n", str); 180*1b8adde7SWilliam Kucharski /* sleep(2); */ 181*1b8adde7SWilliam Kucharski } 182*1b8adde7SWilliam Kucharski 183*1b8adde7SWilliam Kucharski #ifdef DAVICOM_DEBUG 184*1b8adde7SWilliam Kucharski static void davicom_more() 185*1b8adde7SWilliam Kucharski { 186*1b8adde7SWilliam Kucharski printf("\n\n-- more --"); 187*1b8adde7SWilliam Kucharski while (!iskey()) 188*1b8adde7SWilliam Kucharski /* wait */; 189*1b8adde7SWilliam Kucharski getchar(); 190*1b8adde7SWilliam Kucharski printf("\n\n"); 191*1b8adde7SWilliam Kucharski } 192*1b8adde7SWilliam Kucharski #endif /* DAVICOM_DEBUG */ 193*1b8adde7SWilliam Kucharski 194*1b8adde7SWilliam Kucharski static void davicom_wait(unsigned int nticks) 195*1b8adde7SWilliam Kucharski { 196*1b8adde7SWilliam Kucharski unsigned int to = currticks() + nticks; 197*1b8adde7SWilliam Kucharski while (currticks() < to) 198*1b8adde7SWilliam Kucharski /* wait */ ; 199*1b8adde7SWilliam Kucharski } 200*1b8adde7SWilliam Kucharski 201*1b8adde7SWilliam Kucharski 202*1b8adde7SWilliam Kucharski /*********************************************************************/ 203*1b8adde7SWilliam Kucharski /* For DAVICOM phyxcer register by MII interface */ 204*1b8adde7SWilliam Kucharski /*********************************************************************/ 205*1b8adde7SWilliam Kucharski /* 206*1b8adde7SWilliam Kucharski Read a word data from phy register 207*1b8adde7SWilliam Kucharski */ 208*1b8adde7SWilliam Kucharski static int phy_read(int location) 209*1b8adde7SWilliam Kucharski { 210*1b8adde7SWilliam Kucharski int i, phy_addr=1; 211*1b8adde7SWilliam Kucharski u16 phy_data; 212*1b8adde7SWilliam Kucharski u32 io_dcr9; 213*1b8adde7SWilliam Kucharski 214*1b8adde7SWilliam Kucharski whereami("phy_read\n"); 215*1b8adde7SWilliam Kucharski 216*1b8adde7SWilliam Kucharski io_dcr9 = ioaddr + CSR9; 217*1b8adde7SWilliam Kucharski 218*1b8adde7SWilliam Kucharski /* Send 33 synchronization clock to Phy controller */ 219*1b8adde7SWilliam Kucharski for (i=0; i<34; i++) 220*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 221*1b8adde7SWilliam Kucharski 222*1b8adde7SWilliam Kucharski /* Send start command(01) to Phy */ 223*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_0); 224*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 225*1b8adde7SWilliam Kucharski 226*1b8adde7SWilliam Kucharski /* Send read command(10) to Phy */ 227*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 228*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_0); 229*1b8adde7SWilliam Kucharski 230*1b8adde7SWilliam Kucharski /* Send Phy addres */ 231*1b8adde7SWilliam Kucharski for (i=0x10; i>0; i=i>>1) 232*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0); 233*1b8adde7SWilliam Kucharski 234*1b8adde7SWilliam Kucharski /* Send register addres */ 235*1b8adde7SWilliam Kucharski for (i=0x10; i>0; i=i>>1) 236*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); 237*1b8adde7SWilliam Kucharski 238*1b8adde7SWilliam Kucharski /* Skip transition state */ 239*1b8adde7SWilliam Kucharski phy_read_1bit(io_dcr9); 240*1b8adde7SWilliam Kucharski 241*1b8adde7SWilliam Kucharski /* read 16bit data */ 242*1b8adde7SWilliam Kucharski for (phy_data=0, i=0; i<16; i++) { 243*1b8adde7SWilliam Kucharski phy_data<<=1; 244*1b8adde7SWilliam Kucharski phy_data|=phy_read_1bit(io_dcr9); 245*1b8adde7SWilliam Kucharski } 246*1b8adde7SWilliam Kucharski 247*1b8adde7SWilliam Kucharski return phy_data; 248*1b8adde7SWilliam Kucharski } 249*1b8adde7SWilliam Kucharski 250*1b8adde7SWilliam Kucharski /* 251*1b8adde7SWilliam Kucharski Write a word to Phy register 252*1b8adde7SWilliam Kucharski */ 253*1b8adde7SWilliam Kucharski static void phy_write(int location, u16 phy_data) 254*1b8adde7SWilliam Kucharski { 255*1b8adde7SWilliam Kucharski u16 i, phy_addr=1; 256*1b8adde7SWilliam Kucharski u32 io_dcr9; 257*1b8adde7SWilliam Kucharski 258*1b8adde7SWilliam Kucharski whereami("phy_write\n"); 259*1b8adde7SWilliam Kucharski 260*1b8adde7SWilliam Kucharski io_dcr9 = ioaddr + CSR9; 261*1b8adde7SWilliam Kucharski 262*1b8adde7SWilliam Kucharski /* Send 33 synchronization clock to Phy controller */ 263*1b8adde7SWilliam Kucharski for (i=0; i<34; i++) 264*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 265*1b8adde7SWilliam Kucharski 266*1b8adde7SWilliam Kucharski /* Send start command(01) to Phy */ 267*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_0); 268*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 269*1b8adde7SWilliam Kucharski 270*1b8adde7SWilliam Kucharski /* Send write command(01) to Phy */ 271*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_0); 272*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 273*1b8adde7SWilliam Kucharski 274*1b8adde7SWilliam Kucharski /* Send Phy addres */ 275*1b8adde7SWilliam Kucharski for (i=0x10; i>0; i=i>>1) 276*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, phy_addr&i ? PHY_DATA_1: PHY_DATA_0); 277*1b8adde7SWilliam Kucharski 278*1b8adde7SWilliam Kucharski /* Send register addres */ 279*1b8adde7SWilliam Kucharski for (i=0x10; i>0; i=i>>1) 280*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, location&i ? PHY_DATA_1: PHY_DATA_0); 281*1b8adde7SWilliam Kucharski 282*1b8adde7SWilliam Kucharski /* written trasnition */ 283*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_1); 284*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, PHY_DATA_0); 285*1b8adde7SWilliam Kucharski 286*1b8adde7SWilliam Kucharski /* Write a word data to PHY controller */ 287*1b8adde7SWilliam Kucharski for (i=0x8000; i>0; i>>=1) 288*1b8adde7SWilliam Kucharski phy_write_1bit(io_dcr9, phy_data&i ? PHY_DATA_1: PHY_DATA_0); 289*1b8adde7SWilliam Kucharski } 290*1b8adde7SWilliam Kucharski 291*1b8adde7SWilliam Kucharski /* 292*1b8adde7SWilliam Kucharski Write one bit data to Phy Controller 293*1b8adde7SWilliam Kucharski */ 294*1b8adde7SWilliam Kucharski static void phy_write_1bit(u32 ee_addr, u32 phy_data) 295*1b8adde7SWilliam Kucharski { 296*1b8adde7SWilliam Kucharski whereami("phy_write_1bit\n"); 297*1b8adde7SWilliam Kucharski outl(phy_data, ee_addr); /* MII Clock Low */ 298*1b8adde7SWilliam Kucharski eeprom_delay(); 299*1b8adde7SWilliam Kucharski outl(phy_data|MDCLKH, ee_addr); /* MII Clock High */ 300*1b8adde7SWilliam Kucharski eeprom_delay(); 301*1b8adde7SWilliam Kucharski outl(phy_data, ee_addr); /* MII Clock Low */ 302*1b8adde7SWilliam Kucharski eeprom_delay(); 303*1b8adde7SWilliam Kucharski } 304*1b8adde7SWilliam Kucharski 305*1b8adde7SWilliam Kucharski /* 306*1b8adde7SWilliam Kucharski Read one bit phy data from PHY controller 307*1b8adde7SWilliam Kucharski */ 308*1b8adde7SWilliam Kucharski static int phy_read_1bit(u32 ee_addr) 309*1b8adde7SWilliam Kucharski { 310*1b8adde7SWilliam Kucharski int phy_data; 311*1b8adde7SWilliam Kucharski 312*1b8adde7SWilliam Kucharski whereami("phy_read_1bit\n"); 313*1b8adde7SWilliam Kucharski 314*1b8adde7SWilliam Kucharski outl(0x50000, ee_addr); 315*1b8adde7SWilliam Kucharski eeprom_delay(); 316*1b8adde7SWilliam Kucharski 317*1b8adde7SWilliam Kucharski phy_data=(inl(ee_addr)>>19) & 0x1; 318*1b8adde7SWilliam Kucharski 319*1b8adde7SWilliam Kucharski outl(0x40000, ee_addr); 320*1b8adde7SWilliam Kucharski eeprom_delay(); 321*1b8adde7SWilliam Kucharski 322*1b8adde7SWilliam Kucharski return phy_data; 323*1b8adde7SWilliam Kucharski } 324*1b8adde7SWilliam Kucharski 325*1b8adde7SWilliam Kucharski /* 326*1b8adde7SWilliam Kucharski DM9801/DM9802 present check and program 327*1b8adde7SWilliam Kucharski */ 328*1b8adde7SWilliam Kucharski static void HPNA_process(void) 329*1b8adde7SWilliam Kucharski { 330*1b8adde7SWilliam Kucharski 331*1b8adde7SWilliam Kucharski if ( (phy_read(3) & 0xfff0) == 0xb900 ) { 332*1b8adde7SWilliam Kucharski if ( phy_read(31) == 0x4404 ) { 333*1b8adde7SWilliam Kucharski /* DM9801 present */ 334*1b8adde7SWilliam Kucharski if (phy_read(3) == 0xb901) 335*1b8adde7SWilliam Kucharski phy_write(16, 0x5); /* DM9801 E4 */ 336*1b8adde7SWilliam Kucharski else 337*1b8adde7SWilliam Kucharski phy_write(16, 0x1005); /* DM9801 E3 and others */ 338*1b8adde7SWilliam Kucharski phy_write(25, ((phy_read(24) + 3) & 0xff) | 0xf000); 339*1b8adde7SWilliam Kucharski } else { 340*1b8adde7SWilliam Kucharski /* DM9802 present */ 341*1b8adde7SWilliam Kucharski phy_write(16, 0x5); 342*1b8adde7SWilliam Kucharski phy_write(25, (phy_read(25) & 0xff00) + 2); 343*1b8adde7SWilliam Kucharski } 344*1b8adde7SWilliam Kucharski } 345*1b8adde7SWilliam Kucharski } 346*1b8adde7SWilliam Kucharski 347*1b8adde7SWilliam Kucharski /* 348*1b8adde7SWilliam Kucharski Sense media mode and set CR6 349*1b8adde7SWilliam Kucharski */ 350*1b8adde7SWilliam Kucharski static void davicom_media_chk(struct nic * nic __unused) 351*1b8adde7SWilliam Kucharski { 352*1b8adde7SWilliam Kucharski unsigned long to, csr6; 353*1b8adde7SWilliam Kucharski 354*1b8adde7SWilliam Kucharski csr6 = 0x00200000; /* SF */ 355*1b8adde7SWilliam Kucharski outl(csr6, ioaddr + CSR6); 356*1b8adde7SWilliam Kucharski 357*1b8adde7SWilliam Kucharski if (vendor == PCI_VENDOR_ID_DAVICOM && dev_id == PCI_DEVICE_ID_DM9009) { 358*1b8adde7SWilliam Kucharski /* Set to 10BaseT mode for DM9009 */ 359*1b8adde7SWilliam Kucharski phy_write(0, 0); 360*1b8adde7SWilliam Kucharski } else { 361*1b8adde7SWilliam Kucharski /* For DM9102/DM9102A */ 362*1b8adde7SWilliam Kucharski to = currticks() + 2 * TICKS_PER_SEC; 363*1b8adde7SWilliam Kucharski while ( ((phy_read(1) & 0x24)!=0x24) && (currticks() < to)) 364*1b8adde7SWilliam Kucharski /* wait */ ; 365*1b8adde7SWilliam Kucharski 366*1b8adde7SWilliam Kucharski if ( (phy_read(1) & 0x24) == 0x24 ) { 367*1b8adde7SWilliam Kucharski if (phy_read(17) & 0xa000) 368*1b8adde7SWilliam Kucharski csr6 |= 0x00000200; /* Full Duplex mode */ 369*1b8adde7SWilliam Kucharski } else 370*1b8adde7SWilliam Kucharski csr6 |= 0x00040000; /* Select DM9801/DM9802 when Ethernet link failed */ 371*1b8adde7SWilliam Kucharski } 372*1b8adde7SWilliam Kucharski 373*1b8adde7SWilliam Kucharski /* set the chip's operating mode */ 374*1b8adde7SWilliam Kucharski outl(csr6, ioaddr + CSR6); 375*1b8adde7SWilliam Kucharski 376*1b8adde7SWilliam Kucharski /* DM9801/DM9802 present check & program */ 377*1b8adde7SWilliam Kucharski if (csr6 & 0x40000) 378*1b8adde7SWilliam Kucharski HPNA_process(); 379*1b8adde7SWilliam Kucharski } 380*1b8adde7SWilliam Kucharski 381*1b8adde7SWilliam Kucharski 382*1b8adde7SWilliam Kucharski /*********************************************************************/ 383*1b8adde7SWilliam Kucharski /* EEPROM Reading Code */ 384*1b8adde7SWilliam Kucharski /*********************************************************************/ 385*1b8adde7SWilliam Kucharski /* EEPROM routines adapted from the Linux Tulip Code */ 386*1b8adde7SWilliam Kucharski /* Reading a serial EEPROM is a "bit" grungy, but we work our way 387*1b8adde7SWilliam Kucharski through:->. 388*1b8adde7SWilliam Kucharski */ 389*1b8adde7SWilliam Kucharski static int read_eeprom(unsigned long ioaddr, int location, int addr_len) 390*1b8adde7SWilliam Kucharski { 391*1b8adde7SWilliam Kucharski int i; 392*1b8adde7SWilliam Kucharski unsigned short retval = 0; 393*1b8adde7SWilliam Kucharski long ee_addr = ioaddr + CSR9; 394*1b8adde7SWilliam Kucharski int read_cmd = location | EE_READ_CMD; 395*1b8adde7SWilliam Kucharski 396*1b8adde7SWilliam Kucharski whereami("read_eeprom\n"); 397*1b8adde7SWilliam Kucharski 398*1b8adde7SWilliam Kucharski outl(EE_ENB & ~EE_CS, ee_addr); 399*1b8adde7SWilliam Kucharski outl(EE_ENB, ee_addr); 400*1b8adde7SWilliam Kucharski 401*1b8adde7SWilliam Kucharski /* Shift the read command bits out. */ 402*1b8adde7SWilliam Kucharski for (i = 4 + addr_len; i >= 0; i--) { 403*1b8adde7SWilliam Kucharski short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; 404*1b8adde7SWilliam Kucharski outl(EE_ENB | dataval, ee_addr); 405*1b8adde7SWilliam Kucharski eeprom_delay(); 406*1b8adde7SWilliam Kucharski outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr); 407*1b8adde7SWilliam Kucharski eeprom_delay(); 408*1b8adde7SWilliam Kucharski } 409*1b8adde7SWilliam Kucharski outl(EE_ENB, ee_addr); 410*1b8adde7SWilliam Kucharski 411*1b8adde7SWilliam Kucharski for (i = 16; i > 0; i--) { 412*1b8adde7SWilliam Kucharski outl(EE_ENB | EE_SHIFT_CLK, ee_addr); 413*1b8adde7SWilliam Kucharski eeprom_delay(); 414*1b8adde7SWilliam Kucharski retval = (retval << 1) | ((inl(ee_addr) & EE_DATA_READ) ? 1 : 0); 415*1b8adde7SWilliam Kucharski outl(EE_ENB, ee_addr); 416*1b8adde7SWilliam Kucharski eeprom_delay(); 417*1b8adde7SWilliam Kucharski } 418*1b8adde7SWilliam Kucharski 419*1b8adde7SWilliam Kucharski /* Terminate the EEPROM access. */ 420*1b8adde7SWilliam Kucharski outl(EE_ENB & ~EE_CS, ee_addr); 421*1b8adde7SWilliam Kucharski return retval; 422*1b8adde7SWilliam Kucharski } 423*1b8adde7SWilliam Kucharski 424*1b8adde7SWilliam Kucharski /*********************************************************************/ 425*1b8adde7SWilliam Kucharski /* davicom_init_chain - setup the tx and rx descriptors */ 426*1b8adde7SWilliam Kucharski /* Sten 10/9 */ 427*1b8adde7SWilliam Kucharski /*********************************************************************/ 428*1b8adde7SWilliam Kucharski static void davicom_init_chain(struct nic *nic) 429*1b8adde7SWilliam Kucharski { 430*1b8adde7SWilliam Kucharski int i; 431*1b8adde7SWilliam Kucharski 432*1b8adde7SWilliam Kucharski /* setup the transmit descriptor */ 433*1b8adde7SWilliam Kucharski /* Sten: Set 2 TX descriptor but use one TX buffer because 434*1b8adde7SWilliam Kucharski it transmit a packet and wait complete every time. */ 435*1b8adde7SWilliam Kucharski for (i=0; i<NTXD; i++) { 436*1b8adde7SWilliam Kucharski txd[i].buf1addr = (void *)virt_to_bus(&txb[0]); /* Used same TX buffer */ 437*1b8adde7SWilliam Kucharski txd[i].buf2addr = (void *)virt_to_bus(&txd[i+1]); /* Point to Next TX desc */ 438*1b8adde7SWilliam Kucharski txd[i].buf1sz = 0; 439*1b8adde7SWilliam Kucharski txd[i].buf2sz = 0; 440*1b8adde7SWilliam Kucharski txd[i].control = 0x184; /* Begin/End/Chain */ 441*1b8adde7SWilliam Kucharski txd[i].status = 0x00000000; /* give ownership to Host */ 442*1b8adde7SWilliam Kucharski } 443*1b8adde7SWilliam Kucharski 444*1b8adde7SWilliam Kucharski /* construct perfect filter frame with mac address as first match 445*1b8adde7SWilliam Kucharski and broadcast address for all others */ 446*1b8adde7SWilliam Kucharski for (i=0; i<192; i++) txb[i] = 0xFF; 447*1b8adde7SWilliam Kucharski txb[0] = nic->node_addr[0]; 448*1b8adde7SWilliam Kucharski txb[1] = nic->node_addr[1]; 449*1b8adde7SWilliam Kucharski txb[4] = nic->node_addr[2]; 450*1b8adde7SWilliam Kucharski txb[5] = nic->node_addr[3]; 451*1b8adde7SWilliam Kucharski txb[8] = nic->node_addr[4]; 452*1b8adde7SWilliam Kucharski txb[9] = nic->node_addr[5]; 453*1b8adde7SWilliam Kucharski 454*1b8adde7SWilliam Kucharski /* setup receive descriptor */ 455*1b8adde7SWilliam Kucharski for (i=0; i<NRXD; i++) { 456*1b8adde7SWilliam Kucharski rxd[i].buf1addr = (void *)virt_to_bus(&rxb[i * BUFLEN]); 457*1b8adde7SWilliam Kucharski rxd[i].buf2addr = (void *)virt_to_bus(&rxd[i+1]); /* Point to Next RX desc */ 458*1b8adde7SWilliam Kucharski rxd[i].buf1sz = BUFLEN; 459*1b8adde7SWilliam Kucharski rxd[i].buf2sz = 0; /* not used */ 460*1b8adde7SWilliam Kucharski rxd[i].control = 0x4; /* Chain Structure */ 461*1b8adde7SWilliam Kucharski rxd[i].status = 0x80000000; /* give ownership to device */ 462*1b8adde7SWilliam Kucharski } 463*1b8adde7SWilliam Kucharski 464*1b8adde7SWilliam Kucharski /* Chain the last descriptor to first */ 465*1b8adde7SWilliam Kucharski txd[NTXD - 1].buf2addr = (void *)virt_to_bus(&txd[0]); 466*1b8adde7SWilliam Kucharski rxd[NRXD - 1].buf2addr = (void *)virt_to_bus(&rxd[0]); 467*1b8adde7SWilliam Kucharski TxPtr = 0; 468*1b8adde7SWilliam Kucharski rxd_tail = 0; 469*1b8adde7SWilliam Kucharski } 470*1b8adde7SWilliam Kucharski 471*1b8adde7SWilliam Kucharski 472*1b8adde7SWilliam Kucharski /*********************************************************************/ 473*1b8adde7SWilliam Kucharski /* davicom_reset - Reset adapter */ 474*1b8adde7SWilliam Kucharski /*********************************************************************/ 475*1b8adde7SWilliam Kucharski static void davicom_reset(struct nic *nic) 476*1b8adde7SWilliam Kucharski { 477*1b8adde7SWilliam Kucharski unsigned long to; 478*1b8adde7SWilliam Kucharski 479*1b8adde7SWilliam Kucharski whereami("davicom_reset\n"); 480*1b8adde7SWilliam Kucharski 481*1b8adde7SWilliam Kucharski /* Stop Tx and RX */ 482*1b8adde7SWilliam Kucharski outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6); 483*1b8adde7SWilliam Kucharski 484*1b8adde7SWilliam Kucharski /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */ 485*1b8adde7SWilliam Kucharski outl(0x00000001, ioaddr + CSR0); 486*1b8adde7SWilliam Kucharski 487*1b8adde7SWilliam Kucharski davicom_wait(TICKS_PER_SEC); 488*1b8adde7SWilliam Kucharski 489*1b8adde7SWilliam Kucharski /* TX/RX descriptor burst */ 490*1b8adde7SWilliam Kucharski outl(0x0C00000, ioaddr + CSR0); /* Sten 10/9 */ 491*1b8adde7SWilliam Kucharski 492*1b8adde7SWilliam Kucharski /* set up transmit and receive descriptors */ 493*1b8adde7SWilliam Kucharski davicom_init_chain(nic); /* Sten 10/9 */ 494*1b8adde7SWilliam Kucharski 495*1b8adde7SWilliam Kucharski /* Point to receive descriptor */ 496*1b8adde7SWilliam Kucharski outl(virt_to_bus(&rxd[0]), ioaddr + CSR3); 497*1b8adde7SWilliam Kucharski outl(virt_to_bus(&txd[0]), ioaddr + CSR4); /* Sten 10/9 */ 498*1b8adde7SWilliam Kucharski 499*1b8adde7SWilliam Kucharski /* According phyxcer media mode to set CR6, 500*1b8adde7SWilliam Kucharski DM9102/A phyxcer can auto-detect media mode */ 501*1b8adde7SWilliam Kucharski davicom_media_chk(nic); 502*1b8adde7SWilliam Kucharski 503*1b8adde7SWilliam Kucharski /* Prepare Setup Frame Sten 10/9 */ 504*1b8adde7SWilliam Kucharski txd[TxPtr].buf1sz = 192; 505*1b8adde7SWilliam Kucharski txd[TxPtr].control = 0x024; /* SF/CE */ 506*1b8adde7SWilliam Kucharski txd[TxPtr].status = 0x80000000; /* Give ownership to device */ 507*1b8adde7SWilliam Kucharski 508*1b8adde7SWilliam Kucharski /* Start Tx */ 509*1b8adde7SWilliam Kucharski outl(inl(ioaddr + CSR6) | 0x00002000, ioaddr + CSR6); 510*1b8adde7SWilliam Kucharski /* immediate transmit demand */ 511*1b8adde7SWilliam Kucharski outl(0, ioaddr + CSR1); 512*1b8adde7SWilliam Kucharski 513*1b8adde7SWilliam Kucharski to = currticks() + TX_TIME_OUT; 514*1b8adde7SWilliam Kucharski while ((txd[TxPtr].status & 0x80000000) && (currticks() < to)) /* Sten 10/9 */ 515*1b8adde7SWilliam Kucharski /* wait */ ; 516*1b8adde7SWilliam Kucharski 517*1b8adde7SWilliam Kucharski if (currticks() >= to) { 518*1b8adde7SWilliam Kucharski printf ("TX Setup Timeout!\n"); 519*1b8adde7SWilliam Kucharski } 520*1b8adde7SWilliam Kucharski /* Point to next TX descriptor */ 521*1b8adde7SWilliam Kucharski TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */ 522*1b8adde7SWilliam Kucharski 523*1b8adde7SWilliam Kucharski #ifdef DAVICOM_DEBUG 524*1b8adde7SWilliam Kucharski printf("txd.status = %X\n", txd.status); 525*1b8adde7SWilliam Kucharski printf("ticks = %d\n", currticks() - (to - TX_TIME_OUT)); 526*1b8adde7SWilliam Kucharski davicom_more(); 527*1b8adde7SWilliam Kucharski #endif 528*1b8adde7SWilliam Kucharski 529*1b8adde7SWilliam Kucharski /* enable RX */ 530*1b8adde7SWilliam Kucharski outl(inl(ioaddr + CSR6) | 0x00000002, ioaddr + CSR6); 531*1b8adde7SWilliam Kucharski /* immediate poll demand */ 532*1b8adde7SWilliam Kucharski outl(0, ioaddr + CSR2); 533*1b8adde7SWilliam Kucharski } 534*1b8adde7SWilliam Kucharski 535*1b8adde7SWilliam Kucharski 536*1b8adde7SWilliam Kucharski /*********************************************************************/ 537*1b8adde7SWilliam Kucharski /* eth_transmit - Transmit a frame */ 538*1b8adde7SWilliam Kucharski /*********************************************************************/ 539*1b8adde7SWilliam Kucharski static void davicom_transmit(struct nic *nic, const char *d, unsigned int t, 540*1b8adde7SWilliam Kucharski unsigned int s, const char *p) 541*1b8adde7SWilliam Kucharski { 542*1b8adde7SWilliam Kucharski unsigned long to; 543*1b8adde7SWilliam Kucharski 544*1b8adde7SWilliam Kucharski whereami("davicom_transmit\n"); 545*1b8adde7SWilliam Kucharski 546*1b8adde7SWilliam Kucharski /* Stop Tx */ 547*1b8adde7SWilliam Kucharski /* outl(inl(ioaddr + CSR6) & ~0x00002000, ioaddr + CSR6); */ 548*1b8adde7SWilliam Kucharski 549*1b8adde7SWilliam Kucharski /* setup ethernet header */ 550*1b8adde7SWilliam Kucharski memcpy(&txb[0], d, ETH_ALEN); /* DA 6byte */ 551*1b8adde7SWilliam Kucharski memcpy(&txb[ETH_ALEN], nic->node_addr, ETH_ALEN); /* SA 6byte*/ 552*1b8adde7SWilliam Kucharski txb[ETH_ALEN*2] = (t >> 8) & 0xFF; /* Frame type: 2byte */ 553*1b8adde7SWilliam Kucharski txb[ETH_ALEN*2+1] = t & 0xFF; 554*1b8adde7SWilliam Kucharski memcpy(&txb[ETH_HLEN], p, s); /* Frame data */ 555*1b8adde7SWilliam Kucharski 556*1b8adde7SWilliam Kucharski /* setup the transmit descriptor */ 557*1b8adde7SWilliam Kucharski txd[TxPtr].buf1sz = ETH_HLEN+s; 558*1b8adde7SWilliam Kucharski txd[TxPtr].control = 0x00000184; /* LS+FS+CE */ 559*1b8adde7SWilliam Kucharski txd[TxPtr].status = 0x80000000; /* give ownership to device */ 560*1b8adde7SWilliam Kucharski 561*1b8adde7SWilliam Kucharski /* immediate transmit demand */ 562*1b8adde7SWilliam Kucharski outl(0, ioaddr + CSR1); 563*1b8adde7SWilliam Kucharski 564*1b8adde7SWilliam Kucharski to = currticks() + TX_TIME_OUT; 565*1b8adde7SWilliam Kucharski while ((txd[TxPtr].status & 0x80000000) && (currticks() < to)) 566*1b8adde7SWilliam Kucharski /* wait */ ; 567*1b8adde7SWilliam Kucharski 568*1b8adde7SWilliam Kucharski if (currticks() >= to) { 569*1b8adde7SWilliam Kucharski printf ("TX Timeout!\n"); 570*1b8adde7SWilliam Kucharski } 571*1b8adde7SWilliam Kucharski 572*1b8adde7SWilliam Kucharski /* Point to next TX descriptor */ 573*1b8adde7SWilliam Kucharski TxPtr = (++TxPtr >= NTXD) ? 0:TxPtr; /* Sten 10/9 */ 574*1b8adde7SWilliam Kucharski 575*1b8adde7SWilliam Kucharski } 576*1b8adde7SWilliam Kucharski 577*1b8adde7SWilliam Kucharski /*********************************************************************/ 578*1b8adde7SWilliam Kucharski /* eth_poll - Wait for a frame */ 579*1b8adde7SWilliam Kucharski /*********************************************************************/ 580*1b8adde7SWilliam Kucharski static int davicom_poll(struct nic *nic, int retrieve) 581*1b8adde7SWilliam Kucharski { 582*1b8adde7SWilliam Kucharski whereami("davicom_poll\n"); 583*1b8adde7SWilliam Kucharski 584*1b8adde7SWilliam Kucharski if (rxd[rxd_tail].status & 0x80000000) 585*1b8adde7SWilliam Kucharski return 0; 586*1b8adde7SWilliam Kucharski 587*1b8adde7SWilliam Kucharski if ( ! retrieve ) return 1; 588*1b8adde7SWilliam Kucharski 589*1b8adde7SWilliam Kucharski whereami("davicom_poll got one\n"); 590*1b8adde7SWilliam Kucharski 591*1b8adde7SWilliam Kucharski nic->packetlen = (rxd[rxd_tail].status & 0x3FFF0000) >> 16; 592*1b8adde7SWilliam Kucharski 593*1b8adde7SWilliam Kucharski if( rxd[rxd_tail].status & 0x00008000){ 594*1b8adde7SWilliam Kucharski rxd[rxd_tail].status = 0x80000000; 595*1b8adde7SWilliam Kucharski rxd_tail++; 596*1b8adde7SWilliam Kucharski if (rxd_tail == NRXD) rxd_tail = 0; 597*1b8adde7SWilliam Kucharski return 0; 598*1b8adde7SWilliam Kucharski } 599*1b8adde7SWilliam Kucharski 600*1b8adde7SWilliam Kucharski /* copy packet to working buffer */ 601*1b8adde7SWilliam Kucharski /* XXX - this copy could be avoided with a little more work 602*1b8adde7SWilliam Kucharski but for now we are content with it because the optimised 603*1b8adde7SWilliam Kucharski memcpy is quite fast */ 604*1b8adde7SWilliam Kucharski 605*1b8adde7SWilliam Kucharski memcpy(nic->packet, rxb + rxd_tail * BUFLEN, nic->packetlen); 606*1b8adde7SWilliam Kucharski 607*1b8adde7SWilliam Kucharski /* return the descriptor and buffer to receive ring */ 608*1b8adde7SWilliam Kucharski rxd[rxd_tail].status = 0x80000000; 609*1b8adde7SWilliam Kucharski rxd_tail++; 610*1b8adde7SWilliam Kucharski if (rxd_tail == NRXD) rxd_tail = 0; 611*1b8adde7SWilliam Kucharski 612*1b8adde7SWilliam Kucharski return 1; 613*1b8adde7SWilliam Kucharski } 614*1b8adde7SWilliam Kucharski 615*1b8adde7SWilliam Kucharski /*********************************************************************/ 616*1b8adde7SWilliam Kucharski /* eth_disable - Disable the interface */ 617*1b8adde7SWilliam Kucharski /*********************************************************************/ 618*1b8adde7SWilliam Kucharski static void davicom_disable(struct dev *dev) 619*1b8adde7SWilliam Kucharski { 620*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *)dev; 621*1b8adde7SWilliam Kucharski whereami("davicom_disable\n"); 622*1b8adde7SWilliam Kucharski 623*1b8adde7SWilliam Kucharski davicom_reset(nic); 624*1b8adde7SWilliam Kucharski 625*1b8adde7SWilliam Kucharski /* disable interrupts */ 626*1b8adde7SWilliam Kucharski outl(0x00000000, ioaddr + CSR7); 627*1b8adde7SWilliam Kucharski 628*1b8adde7SWilliam Kucharski /* Stop the chip's Tx and Rx processes. */ 629*1b8adde7SWilliam Kucharski outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6); 630*1b8adde7SWilliam Kucharski 631*1b8adde7SWilliam Kucharski /* Clear the missed-packet counter. */ 632*1b8adde7SWilliam Kucharski (volatile unsigned long)inl(ioaddr + CSR8); 633*1b8adde7SWilliam Kucharski } 634*1b8adde7SWilliam Kucharski 635*1b8adde7SWilliam Kucharski 636*1b8adde7SWilliam Kucharski /*********************************************************************/ 637*1b8adde7SWilliam Kucharski /* eth_irq - enable, disable and force interrupts */ 638*1b8adde7SWilliam Kucharski /*********************************************************************/ 639*1b8adde7SWilliam Kucharski static void davicom_irq(struct nic *nic __unused, irq_action_t action __unused) 640*1b8adde7SWilliam Kucharski { 641*1b8adde7SWilliam Kucharski switch ( action ) { 642*1b8adde7SWilliam Kucharski case DISABLE : 643*1b8adde7SWilliam Kucharski break; 644*1b8adde7SWilliam Kucharski case ENABLE : 645*1b8adde7SWilliam Kucharski break; 646*1b8adde7SWilliam Kucharski case FORCE : 647*1b8adde7SWilliam Kucharski break; 648*1b8adde7SWilliam Kucharski } 649*1b8adde7SWilliam Kucharski } 650*1b8adde7SWilliam Kucharski 651*1b8adde7SWilliam Kucharski 652*1b8adde7SWilliam Kucharski /*********************************************************************/ 653*1b8adde7SWilliam Kucharski /* eth_probe - Look for an adapter */ 654*1b8adde7SWilliam Kucharski /*********************************************************************/ 655*1b8adde7SWilliam Kucharski static int davicom_probe(struct dev *dev, struct pci_device *pci) 656*1b8adde7SWilliam Kucharski { 657*1b8adde7SWilliam Kucharski struct nic *nic = (struct nic *)dev; 658*1b8adde7SWilliam Kucharski unsigned int i; 659*1b8adde7SWilliam Kucharski 660*1b8adde7SWilliam Kucharski whereami("davicom_probe\n"); 661*1b8adde7SWilliam Kucharski 662*1b8adde7SWilliam Kucharski if (pci->ioaddr == 0) 663*1b8adde7SWilliam Kucharski return 0; 664*1b8adde7SWilliam Kucharski 665*1b8adde7SWilliam Kucharski vendor = pci->vendor; 666*1b8adde7SWilliam Kucharski dev_id = pci->dev_id; 667*1b8adde7SWilliam Kucharski ioaddr = pci->ioaddr & ~3; 668*1b8adde7SWilliam Kucharski 669*1b8adde7SWilliam Kucharski nic->irqno = 0; 670*1b8adde7SWilliam Kucharski nic->ioaddr = pci->ioaddr & ~3; 671*1b8adde7SWilliam Kucharski 672*1b8adde7SWilliam Kucharski /* wakeup chip */ 673*1b8adde7SWilliam Kucharski pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000); 674*1b8adde7SWilliam Kucharski 675*1b8adde7SWilliam Kucharski /* Stop the chip's Tx and Rx processes. */ 676*1b8adde7SWilliam Kucharski outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6); 677*1b8adde7SWilliam Kucharski 678*1b8adde7SWilliam Kucharski /* Clear the missed-packet counter. */ 679*1b8adde7SWilliam Kucharski (volatile unsigned long)inl(ioaddr + CSR8); 680*1b8adde7SWilliam Kucharski 681*1b8adde7SWilliam Kucharski /* Get MAC Address */ 682*1b8adde7SWilliam Kucharski /* read EEPROM data */ 683*1b8adde7SWilliam Kucharski for (i = 0; i < sizeof(ee_data)/2; i++) 684*1b8adde7SWilliam Kucharski ((unsigned short *)ee_data)[i] = 685*1b8adde7SWilliam Kucharski le16_to_cpu(read_eeprom(ioaddr, i, EEPROM_ADDRLEN)); 686*1b8adde7SWilliam Kucharski 687*1b8adde7SWilliam Kucharski /* extract MAC address from EEPROM buffer */ 688*1b8adde7SWilliam Kucharski for (i=0; i<ETH_ALEN; i++) 689*1b8adde7SWilliam Kucharski nic->node_addr[i] = ee_data[20+i]; 690*1b8adde7SWilliam Kucharski 691*1b8adde7SWilliam Kucharski printf("Davicom %! at ioaddr %#hX\n", nic->node_addr, ioaddr); 692*1b8adde7SWilliam Kucharski 693*1b8adde7SWilliam Kucharski /* initialize device */ 694*1b8adde7SWilliam Kucharski davicom_reset(nic); 695*1b8adde7SWilliam Kucharski 696*1b8adde7SWilliam Kucharski dev->disable = davicom_disable; 697*1b8adde7SWilliam Kucharski nic->poll = davicom_poll; 698*1b8adde7SWilliam Kucharski nic->transmit = davicom_transmit; 699*1b8adde7SWilliam Kucharski nic->irq = davicom_irq; 700*1b8adde7SWilliam Kucharski 701*1b8adde7SWilliam Kucharski return 1; 702*1b8adde7SWilliam Kucharski } 703*1b8adde7SWilliam Kucharski 704*1b8adde7SWilliam Kucharski static struct pci_id davicom_nics[] = { 705*1b8adde7SWilliam Kucharski PCI_ROM(0x1282, 0x9100, "davicom9100", "Davicom 9100"), 706*1b8adde7SWilliam Kucharski PCI_ROM(0x1282, 0x9102, "davicom9102", "Davicom 9102"), 707*1b8adde7SWilliam Kucharski PCI_ROM(0x1282, 0x9009, "davicom9009", "Davicom 9009"), 708*1b8adde7SWilliam Kucharski PCI_ROM(0x1282, 0x9132, "davicom9132", "Davicom 9132"), /* Needs probably some fixing */ 709*1b8adde7SWilliam Kucharski }; 710*1b8adde7SWilliam Kucharski 711*1b8adde7SWilliam Kucharski struct pci_driver davicom_driver = { 712*1b8adde7SWilliam Kucharski .type = NIC_DRIVER, 713*1b8adde7SWilliam Kucharski .name = "DAVICOM", 714*1b8adde7SWilliam Kucharski .probe = davicom_probe, 715*1b8adde7SWilliam Kucharski .ids = davicom_nics, 716*1b8adde7SWilliam Kucharski .id_count = sizeof(davicom_nics)/sizeof(davicom_nics[0]), 717*1b8adde7SWilliam Kucharski .class = 0, 718*1b8adde7SWilliam Kucharski }; 719