1*644570b8SJeff Kirsher /* 2*644570b8SJeff Kirsher * linux/drivers/acorn/net/etherh.c 3*644570b8SJeff Kirsher * 4*644570b8SJeff Kirsher * Copyright (C) 2000-2002 Russell King 5*644570b8SJeff Kirsher * 6*644570b8SJeff Kirsher * This program is free software; you can redistribute it and/or modify 7*644570b8SJeff Kirsher * it under the terms of the GNU General Public License version 2 as 8*644570b8SJeff Kirsher * published by the Free Software Foundation. 9*644570b8SJeff Kirsher * 10*644570b8SJeff Kirsher * NS8390 I-cubed EtherH and ANT EtherM specific driver 11*644570b8SJeff Kirsher * Thanks to I-Cubed for information on their cards. 12*644570b8SJeff Kirsher * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton 13*644570b8SJeff Kirsher * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan) 14*644570b8SJeff Kirsher * EtherM integration re-engineered by Russell King. 15*644570b8SJeff Kirsher * 16*644570b8SJeff Kirsher * Changelog: 17*644570b8SJeff Kirsher * 08-12-1996 RMK 1.00 Created 18*644570b8SJeff Kirsher * RMK 1.03 Added support for EtherLan500 cards 19*644570b8SJeff Kirsher * 23-11-1997 RMK 1.04 Added media autodetection 20*644570b8SJeff Kirsher * 16-04-1998 RMK 1.05 Improved media autodetection 21*644570b8SJeff Kirsher * 10-02-2000 RMK 1.06 Updated for 2.3.43 22*644570b8SJeff Kirsher * 13-05-2000 RMK 1.07 Updated for 2.3.99-pre8 23*644570b8SJeff Kirsher * 12-10-1999 CK/TEW EtherM driver first release 24*644570b8SJeff Kirsher * 21-12-2000 TTC EtherH/EtherM integration 25*644570b8SJeff Kirsher * 25-12-2000 RMK 1.08 Clean integration of EtherM into this driver. 26*644570b8SJeff Kirsher * 03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot. 27*644570b8SJeff Kirsher */ 28*644570b8SJeff Kirsher 29*644570b8SJeff Kirsher #include <linux/module.h> 30*644570b8SJeff Kirsher #include <linux/kernel.h> 31*644570b8SJeff Kirsher #include <linux/types.h> 32*644570b8SJeff Kirsher #include <linux/fcntl.h> 33*644570b8SJeff Kirsher #include <linux/interrupt.h> 34*644570b8SJeff Kirsher #include <linux/ioport.h> 35*644570b8SJeff Kirsher #include <linux/in.h> 36*644570b8SJeff Kirsher #include <linux/string.h> 37*644570b8SJeff Kirsher #include <linux/errno.h> 38*644570b8SJeff Kirsher #include <linux/netdevice.h> 39*644570b8SJeff Kirsher #include <linux/etherdevice.h> 40*644570b8SJeff Kirsher #include <linux/ethtool.h> 41*644570b8SJeff Kirsher #include <linux/skbuff.h> 42*644570b8SJeff Kirsher #include <linux/delay.h> 43*644570b8SJeff Kirsher #include <linux/device.h> 44*644570b8SJeff Kirsher #include <linux/init.h> 45*644570b8SJeff Kirsher #include <linux/bitops.h> 46*644570b8SJeff Kirsher #include <linux/jiffies.h> 47*644570b8SJeff Kirsher 48*644570b8SJeff Kirsher #include <asm/system.h> 49*644570b8SJeff Kirsher #include <asm/ecard.h> 50*644570b8SJeff Kirsher #include <asm/io.h> 51*644570b8SJeff Kirsher 52*644570b8SJeff Kirsher #define EI_SHIFT(x) (ei_local->reg_offset[x]) 53*644570b8SJeff Kirsher 54*644570b8SJeff Kirsher #define ei_inb(_p) readb((void __iomem *)_p) 55*644570b8SJeff Kirsher #define ei_outb(_v,_p) writeb(_v,(void __iomem *)_p) 56*644570b8SJeff Kirsher #define ei_inb_p(_p) readb((void __iomem *)_p) 57*644570b8SJeff Kirsher #define ei_outb_p(_v,_p) writeb(_v,(void __iomem *)_p) 58*644570b8SJeff Kirsher 59*644570b8SJeff Kirsher #define NET_DEBUG 0 60*644570b8SJeff Kirsher #define DEBUG_INIT 2 61*644570b8SJeff Kirsher 62*644570b8SJeff Kirsher #define DRV_NAME "etherh" 63*644570b8SJeff Kirsher #define DRV_VERSION "1.11" 64*644570b8SJeff Kirsher 65*644570b8SJeff Kirsher static char version[] __initdata = 66*644570b8SJeff Kirsher "EtherH/EtherM Driver (c) 2002-2004 Russell King " DRV_VERSION "\n"; 67*644570b8SJeff Kirsher 68*644570b8SJeff Kirsher #include "lib8390.c" 69*644570b8SJeff Kirsher 70*644570b8SJeff Kirsher static unsigned int net_debug = NET_DEBUG; 71*644570b8SJeff Kirsher 72*644570b8SJeff Kirsher struct etherh_priv { 73*644570b8SJeff Kirsher void __iomem *ioc_fast; 74*644570b8SJeff Kirsher void __iomem *memc; 75*644570b8SJeff Kirsher void __iomem *dma_base; 76*644570b8SJeff Kirsher unsigned int id; 77*644570b8SJeff Kirsher void __iomem *ctrl_port; 78*644570b8SJeff Kirsher unsigned char ctrl; 79*644570b8SJeff Kirsher u32 supported; 80*644570b8SJeff Kirsher }; 81*644570b8SJeff Kirsher 82*644570b8SJeff Kirsher struct etherh_data { 83*644570b8SJeff Kirsher unsigned long ns8390_offset; 84*644570b8SJeff Kirsher unsigned long dataport_offset; 85*644570b8SJeff Kirsher unsigned long ctrlport_offset; 86*644570b8SJeff Kirsher int ctrl_ioc; 87*644570b8SJeff Kirsher const char name[16]; 88*644570b8SJeff Kirsher u32 supported; 89*644570b8SJeff Kirsher unsigned char tx_start_page; 90*644570b8SJeff Kirsher unsigned char stop_page; 91*644570b8SJeff Kirsher }; 92*644570b8SJeff Kirsher 93*644570b8SJeff Kirsher MODULE_AUTHOR("Russell King"); 94*644570b8SJeff Kirsher MODULE_DESCRIPTION("EtherH/EtherM driver"); 95*644570b8SJeff Kirsher MODULE_LICENSE("GPL"); 96*644570b8SJeff Kirsher 97*644570b8SJeff Kirsher #define ETHERH500_DATAPORT 0x800 /* MEMC */ 98*644570b8SJeff Kirsher #define ETHERH500_NS8390 0x000 /* MEMC */ 99*644570b8SJeff Kirsher #define ETHERH500_CTRLPORT 0x800 /* IOC */ 100*644570b8SJeff Kirsher 101*644570b8SJeff Kirsher #define ETHERH600_DATAPORT 0x040 /* MEMC */ 102*644570b8SJeff Kirsher #define ETHERH600_NS8390 0x800 /* MEMC */ 103*644570b8SJeff Kirsher #define ETHERH600_CTRLPORT 0x200 /* MEMC */ 104*644570b8SJeff Kirsher 105*644570b8SJeff Kirsher #define ETHERH_CP_IE 1 106*644570b8SJeff Kirsher #define ETHERH_CP_IF 2 107*644570b8SJeff Kirsher #define ETHERH_CP_HEARTBEAT 2 108*644570b8SJeff Kirsher 109*644570b8SJeff Kirsher #define ETHERH_TX_START_PAGE 1 110*644570b8SJeff Kirsher #define ETHERH_STOP_PAGE 127 111*644570b8SJeff Kirsher 112*644570b8SJeff Kirsher /* 113*644570b8SJeff Kirsher * These came from CK/TEW 114*644570b8SJeff Kirsher */ 115*644570b8SJeff Kirsher #define ETHERM_DATAPORT 0x200 /* MEMC */ 116*644570b8SJeff Kirsher #define ETHERM_NS8390 0x800 /* MEMC */ 117*644570b8SJeff Kirsher #define ETHERM_CTRLPORT 0x23c /* MEMC */ 118*644570b8SJeff Kirsher 119*644570b8SJeff Kirsher #define ETHERM_TX_START_PAGE 64 120*644570b8SJeff Kirsher #define ETHERM_STOP_PAGE 127 121*644570b8SJeff Kirsher 122*644570b8SJeff Kirsher /* ------------------------------------------------------------------------ */ 123*644570b8SJeff Kirsher 124*644570b8SJeff Kirsher #define etherh_priv(dev) \ 125*644570b8SJeff Kirsher ((struct etherh_priv *)(((char *)netdev_priv(dev)) + sizeof(struct ei_device))) 126*644570b8SJeff Kirsher 127*644570b8SJeff Kirsher static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned char mask) 128*644570b8SJeff Kirsher { 129*644570b8SJeff Kirsher unsigned char ctrl = eh->ctrl | mask; 130*644570b8SJeff Kirsher eh->ctrl = ctrl; 131*644570b8SJeff Kirsher writeb(ctrl, eh->ctrl_port); 132*644570b8SJeff Kirsher } 133*644570b8SJeff Kirsher 134*644570b8SJeff Kirsher static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned char mask) 135*644570b8SJeff Kirsher { 136*644570b8SJeff Kirsher unsigned char ctrl = eh->ctrl & ~mask; 137*644570b8SJeff Kirsher eh->ctrl = ctrl; 138*644570b8SJeff Kirsher writeb(ctrl, eh->ctrl_port); 139*644570b8SJeff Kirsher } 140*644570b8SJeff Kirsher 141*644570b8SJeff Kirsher static inline unsigned int etherh_get_stat(struct etherh_priv *eh) 142*644570b8SJeff Kirsher { 143*644570b8SJeff Kirsher return readb(eh->ctrl_port); 144*644570b8SJeff Kirsher } 145*644570b8SJeff Kirsher 146*644570b8SJeff Kirsher 147*644570b8SJeff Kirsher 148*644570b8SJeff Kirsher 149*644570b8SJeff Kirsher static void etherh_irq_enable(ecard_t *ec, int irqnr) 150*644570b8SJeff Kirsher { 151*644570b8SJeff Kirsher struct etherh_priv *eh = ec->irq_data; 152*644570b8SJeff Kirsher 153*644570b8SJeff Kirsher etherh_set_ctrl(eh, ETHERH_CP_IE); 154*644570b8SJeff Kirsher } 155*644570b8SJeff Kirsher 156*644570b8SJeff Kirsher static void etherh_irq_disable(ecard_t *ec, int irqnr) 157*644570b8SJeff Kirsher { 158*644570b8SJeff Kirsher struct etherh_priv *eh = ec->irq_data; 159*644570b8SJeff Kirsher 160*644570b8SJeff Kirsher etherh_clr_ctrl(eh, ETHERH_CP_IE); 161*644570b8SJeff Kirsher } 162*644570b8SJeff Kirsher 163*644570b8SJeff Kirsher static expansioncard_ops_t etherh_ops = { 164*644570b8SJeff Kirsher .irqenable = etherh_irq_enable, 165*644570b8SJeff Kirsher .irqdisable = etherh_irq_disable, 166*644570b8SJeff Kirsher }; 167*644570b8SJeff Kirsher 168*644570b8SJeff Kirsher 169*644570b8SJeff Kirsher 170*644570b8SJeff Kirsher 171*644570b8SJeff Kirsher static void 172*644570b8SJeff Kirsher etherh_setif(struct net_device *dev) 173*644570b8SJeff Kirsher { 174*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 175*644570b8SJeff Kirsher unsigned long flags; 176*644570b8SJeff Kirsher void __iomem *addr; 177*644570b8SJeff Kirsher 178*644570b8SJeff Kirsher local_irq_save(flags); 179*644570b8SJeff Kirsher 180*644570b8SJeff Kirsher /* set the interface type */ 181*644570b8SJeff Kirsher switch (etherh_priv(dev)->id) { 182*644570b8SJeff Kirsher case PROD_I3_ETHERLAN600: 183*644570b8SJeff Kirsher case PROD_I3_ETHERLAN600A: 184*644570b8SJeff Kirsher addr = (void __iomem *)dev->base_addr + EN0_RCNTHI; 185*644570b8SJeff Kirsher 186*644570b8SJeff Kirsher switch (dev->if_port) { 187*644570b8SJeff Kirsher case IF_PORT_10BASE2: 188*644570b8SJeff Kirsher writeb((readb(addr) & 0xf8) | 1, addr); 189*644570b8SJeff Kirsher break; 190*644570b8SJeff Kirsher case IF_PORT_10BASET: 191*644570b8SJeff Kirsher writeb((readb(addr) & 0xf8), addr); 192*644570b8SJeff Kirsher break; 193*644570b8SJeff Kirsher } 194*644570b8SJeff Kirsher break; 195*644570b8SJeff Kirsher 196*644570b8SJeff Kirsher case PROD_I3_ETHERLAN500: 197*644570b8SJeff Kirsher switch (dev->if_port) { 198*644570b8SJeff Kirsher case IF_PORT_10BASE2: 199*644570b8SJeff Kirsher etherh_clr_ctrl(etherh_priv(dev), ETHERH_CP_IF); 200*644570b8SJeff Kirsher break; 201*644570b8SJeff Kirsher 202*644570b8SJeff Kirsher case IF_PORT_10BASET: 203*644570b8SJeff Kirsher etherh_set_ctrl(etherh_priv(dev), ETHERH_CP_IF); 204*644570b8SJeff Kirsher break; 205*644570b8SJeff Kirsher } 206*644570b8SJeff Kirsher break; 207*644570b8SJeff Kirsher 208*644570b8SJeff Kirsher default: 209*644570b8SJeff Kirsher break; 210*644570b8SJeff Kirsher } 211*644570b8SJeff Kirsher 212*644570b8SJeff Kirsher local_irq_restore(flags); 213*644570b8SJeff Kirsher } 214*644570b8SJeff Kirsher 215*644570b8SJeff Kirsher static int 216*644570b8SJeff Kirsher etherh_getifstat(struct net_device *dev) 217*644570b8SJeff Kirsher { 218*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 219*644570b8SJeff Kirsher void __iomem *addr; 220*644570b8SJeff Kirsher int stat = 0; 221*644570b8SJeff Kirsher 222*644570b8SJeff Kirsher switch (etherh_priv(dev)->id) { 223*644570b8SJeff Kirsher case PROD_I3_ETHERLAN600: 224*644570b8SJeff Kirsher case PROD_I3_ETHERLAN600A: 225*644570b8SJeff Kirsher addr = (void __iomem *)dev->base_addr + EN0_RCNTHI; 226*644570b8SJeff Kirsher switch (dev->if_port) { 227*644570b8SJeff Kirsher case IF_PORT_10BASE2: 228*644570b8SJeff Kirsher stat = 1; 229*644570b8SJeff Kirsher break; 230*644570b8SJeff Kirsher case IF_PORT_10BASET: 231*644570b8SJeff Kirsher stat = readb(addr) & 4; 232*644570b8SJeff Kirsher break; 233*644570b8SJeff Kirsher } 234*644570b8SJeff Kirsher break; 235*644570b8SJeff Kirsher 236*644570b8SJeff Kirsher case PROD_I3_ETHERLAN500: 237*644570b8SJeff Kirsher switch (dev->if_port) { 238*644570b8SJeff Kirsher case IF_PORT_10BASE2: 239*644570b8SJeff Kirsher stat = 1; 240*644570b8SJeff Kirsher break; 241*644570b8SJeff Kirsher case IF_PORT_10BASET: 242*644570b8SJeff Kirsher stat = etherh_get_stat(etherh_priv(dev)) & ETHERH_CP_HEARTBEAT; 243*644570b8SJeff Kirsher break; 244*644570b8SJeff Kirsher } 245*644570b8SJeff Kirsher break; 246*644570b8SJeff Kirsher 247*644570b8SJeff Kirsher default: 248*644570b8SJeff Kirsher stat = 0; 249*644570b8SJeff Kirsher break; 250*644570b8SJeff Kirsher } 251*644570b8SJeff Kirsher 252*644570b8SJeff Kirsher return stat != 0; 253*644570b8SJeff Kirsher } 254*644570b8SJeff Kirsher 255*644570b8SJeff Kirsher /* 256*644570b8SJeff Kirsher * Configure the interface. Note that we ignore the other 257*644570b8SJeff Kirsher * parts of ifmap, since its mostly meaningless for this driver. 258*644570b8SJeff Kirsher */ 259*644570b8SJeff Kirsher static int etherh_set_config(struct net_device *dev, struct ifmap *map) 260*644570b8SJeff Kirsher { 261*644570b8SJeff Kirsher switch (map->port) { 262*644570b8SJeff Kirsher case IF_PORT_10BASE2: 263*644570b8SJeff Kirsher case IF_PORT_10BASET: 264*644570b8SJeff Kirsher /* 265*644570b8SJeff Kirsher * If the user explicitly sets the interface 266*644570b8SJeff Kirsher * media type, turn off automedia detection. 267*644570b8SJeff Kirsher */ 268*644570b8SJeff Kirsher dev->flags &= ~IFF_AUTOMEDIA; 269*644570b8SJeff Kirsher dev->if_port = map->port; 270*644570b8SJeff Kirsher break; 271*644570b8SJeff Kirsher 272*644570b8SJeff Kirsher default: 273*644570b8SJeff Kirsher return -EINVAL; 274*644570b8SJeff Kirsher } 275*644570b8SJeff Kirsher 276*644570b8SJeff Kirsher etherh_setif(dev); 277*644570b8SJeff Kirsher 278*644570b8SJeff Kirsher return 0; 279*644570b8SJeff Kirsher } 280*644570b8SJeff Kirsher 281*644570b8SJeff Kirsher /* 282*644570b8SJeff Kirsher * Reset the 8390 (hard reset). Note that we can't actually do this. 283*644570b8SJeff Kirsher */ 284*644570b8SJeff Kirsher static void 285*644570b8SJeff Kirsher etherh_reset(struct net_device *dev) 286*644570b8SJeff Kirsher { 287*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 288*644570b8SJeff Kirsher void __iomem *addr = (void __iomem *)dev->base_addr; 289*644570b8SJeff Kirsher 290*644570b8SJeff Kirsher writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr); 291*644570b8SJeff Kirsher 292*644570b8SJeff Kirsher /* 293*644570b8SJeff Kirsher * See if we need to change the interface type. 294*644570b8SJeff Kirsher * Note that we use 'interface_num' as a flag 295*644570b8SJeff Kirsher * to indicate that we need to change the media. 296*644570b8SJeff Kirsher */ 297*644570b8SJeff Kirsher if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) { 298*644570b8SJeff Kirsher ei_local->interface_num = 0; 299*644570b8SJeff Kirsher 300*644570b8SJeff Kirsher if (dev->if_port == IF_PORT_10BASET) 301*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASE2; 302*644570b8SJeff Kirsher else 303*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASET; 304*644570b8SJeff Kirsher 305*644570b8SJeff Kirsher etherh_setif(dev); 306*644570b8SJeff Kirsher } 307*644570b8SJeff Kirsher } 308*644570b8SJeff Kirsher 309*644570b8SJeff Kirsher /* 310*644570b8SJeff Kirsher * Write a block of data out to the 8390 311*644570b8SJeff Kirsher */ 312*644570b8SJeff Kirsher static void 313*644570b8SJeff Kirsher etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page) 314*644570b8SJeff Kirsher { 315*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 316*644570b8SJeff Kirsher unsigned long dma_start; 317*644570b8SJeff Kirsher void __iomem *dma_base, *addr; 318*644570b8SJeff Kirsher 319*644570b8SJeff Kirsher if (ei_local->dmaing) { 320*644570b8SJeff Kirsher printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " 321*644570b8SJeff Kirsher " DMAstat %d irqlock %d\n", dev->name, 322*644570b8SJeff Kirsher ei_local->dmaing, ei_local->irqlock); 323*644570b8SJeff Kirsher return; 324*644570b8SJeff Kirsher } 325*644570b8SJeff Kirsher 326*644570b8SJeff Kirsher /* 327*644570b8SJeff Kirsher * Make sure we have a round number of bytes if we're in word mode. 328*644570b8SJeff Kirsher */ 329*644570b8SJeff Kirsher if (count & 1 && ei_local->word16) 330*644570b8SJeff Kirsher count++; 331*644570b8SJeff Kirsher 332*644570b8SJeff Kirsher ei_local->dmaing = 1; 333*644570b8SJeff Kirsher 334*644570b8SJeff Kirsher addr = (void __iomem *)dev->base_addr; 335*644570b8SJeff Kirsher dma_base = etherh_priv(dev)->dma_base; 336*644570b8SJeff Kirsher 337*644570b8SJeff Kirsher count = (count + 1) & ~1; 338*644570b8SJeff Kirsher writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); 339*644570b8SJeff Kirsher 340*644570b8SJeff Kirsher writeb (0x42, addr + EN0_RCNTLO); 341*644570b8SJeff Kirsher writeb (0x00, addr + EN0_RCNTHI); 342*644570b8SJeff Kirsher writeb (0x42, addr + EN0_RSARLO); 343*644570b8SJeff Kirsher writeb (0x00, addr + EN0_RSARHI); 344*644570b8SJeff Kirsher writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); 345*644570b8SJeff Kirsher 346*644570b8SJeff Kirsher udelay (1); 347*644570b8SJeff Kirsher 348*644570b8SJeff Kirsher writeb (ENISR_RDC, addr + EN0_ISR); 349*644570b8SJeff Kirsher writeb (count, addr + EN0_RCNTLO); 350*644570b8SJeff Kirsher writeb (count >> 8, addr + EN0_RCNTHI); 351*644570b8SJeff Kirsher writeb (0, addr + EN0_RSARLO); 352*644570b8SJeff Kirsher writeb (start_page, addr + EN0_RSARHI); 353*644570b8SJeff Kirsher writeb (E8390_RWRITE | E8390_START, addr + E8390_CMD); 354*644570b8SJeff Kirsher 355*644570b8SJeff Kirsher if (ei_local->word16) 356*644570b8SJeff Kirsher writesw (dma_base, buf, count >> 1); 357*644570b8SJeff Kirsher else 358*644570b8SJeff Kirsher writesb (dma_base, buf, count); 359*644570b8SJeff Kirsher 360*644570b8SJeff Kirsher dma_start = jiffies; 361*644570b8SJeff Kirsher 362*644570b8SJeff Kirsher while ((readb (addr + EN0_ISR) & ENISR_RDC) == 0) 363*644570b8SJeff Kirsher if (time_after(jiffies, dma_start + 2*HZ/100)) { /* 20ms */ 364*644570b8SJeff Kirsher printk(KERN_ERR "%s: timeout waiting for TX RDC\n", 365*644570b8SJeff Kirsher dev->name); 366*644570b8SJeff Kirsher etherh_reset (dev); 367*644570b8SJeff Kirsher __NS8390_init (dev, 1); 368*644570b8SJeff Kirsher break; 369*644570b8SJeff Kirsher } 370*644570b8SJeff Kirsher 371*644570b8SJeff Kirsher writeb (ENISR_RDC, addr + EN0_ISR); 372*644570b8SJeff Kirsher ei_local->dmaing = 0; 373*644570b8SJeff Kirsher } 374*644570b8SJeff Kirsher 375*644570b8SJeff Kirsher /* 376*644570b8SJeff Kirsher * Read a block of data from the 8390 377*644570b8SJeff Kirsher */ 378*644570b8SJeff Kirsher static void 379*644570b8SJeff Kirsher etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) 380*644570b8SJeff Kirsher { 381*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 382*644570b8SJeff Kirsher unsigned char *buf; 383*644570b8SJeff Kirsher void __iomem *dma_base, *addr; 384*644570b8SJeff Kirsher 385*644570b8SJeff Kirsher if (ei_local->dmaing) { 386*644570b8SJeff Kirsher printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: " 387*644570b8SJeff Kirsher " DMAstat %d irqlock %d\n", dev->name, 388*644570b8SJeff Kirsher ei_local->dmaing, ei_local->irqlock); 389*644570b8SJeff Kirsher return; 390*644570b8SJeff Kirsher } 391*644570b8SJeff Kirsher 392*644570b8SJeff Kirsher ei_local->dmaing = 1; 393*644570b8SJeff Kirsher 394*644570b8SJeff Kirsher addr = (void __iomem *)dev->base_addr; 395*644570b8SJeff Kirsher dma_base = etherh_priv(dev)->dma_base; 396*644570b8SJeff Kirsher 397*644570b8SJeff Kirsher buf = skb->data; 398*644570b8SJeff Kirsher writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); 399*644570b8SJeff Kirsher writeb (count, addr + EN0_RCNTLO); 400*644570b8SJeff Kirsher writeb (count >> 8, addr + EN0_RCNTHI); 401*644570b8SJeff Kirsher writeb (ring_offset, addr + EN0_RSARLO); 402*644570b8SJeff Kirsher writeb (ring_offset >> 8, addr + EN0_RSARHI); 403*644570b8SJeff Kirsher writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); 404*644570b8SJeff Kirsher 405*644570b8SJeff Kirsher if (ei_local->word16) { 406*644570b8SJeff Kirsher readsw (dma_base, buf, count >> 1); 407*644570b8SJeff Kirsher if (count & 1) 408*644570b8SJeff Kirsher buf[count - 1] = readb (dma_base); 409*644570b8SJeff Kirsher } else 410*644570b8SJeff Kirsher readsb (dma_base, buf, count); 411*644570b8SJeff Kirsher 412*644570b8SJeff Kirsher writeb (ENISR_RDC, addr + EN0_ISR); 413*644570b8SJeff Kirsher ei_local->dmaing = 0; 414*644570b8SJeff Kirsher } 415*644570b8SJeff Kirsher 416*644570b8SJeff Kirsher /* 417*644570b8SJeff Kirsher * Read a header from the 8390 418*644570b8SJeff Kirsher */ 419*644570b8SJeff Kirsher static void 420*644570b8SJeff Kirsher etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) 421*644570b8SJeff Kirsher { 422*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 423*644570b8SJeff Kirsher void __iomem *dma_base, *addr; 424*644570b8SJeff Kirsher 425*644570b8SJeff Kirsher if (ei_local->dmaing) { 426*644570b8SJeff Kirsher printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: " 427*644570b8SJeff Kirsher " DMAstat %d irqlock %d\n", dev->name, 428*644570b8SJeff Kirsher ei_local->dmaing, ei_local->irqlock); 429*644570b8SJeff Kirsher return; 430*644570b8SJeff Kirsher } 431*644570b8SJeff Kirsher 432*644570b8SJeff Kirsher ei_local->dmaing = 1; 433*644570b8SJeff Kirsher 434*644570b8SJeff Kirsher addr = (void __iomem *)dev->base_addr; 435*644570b8SJeff Kirsher dma_base = etherh_priv(dev)->dma_base; 436*644570b8SJeff Kirsher 437*644570b8SJeff Kirsher writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD); 438*644570b8SJeff Kirsher writeb (sizeof (*hdr), addr + EN0_RCNTLO); 439*644570b8SJeff Kirsher writeb (0, addr + EN0_RCNTHI); 440*644570b8SJeff Kirsher writeb (0, addr + EN0_RSARLO); 441*644570b8SJeff Kirsher writeb (ring_page, addr + EN0_RSARHI); 442*644570b8SJeff Kirsher writeb (E8390_RREAD | E8390_START, addr + E8390_CMD); 443*644570b8SJeff Kirsher 444*644570b8SJeff Kirsher if (ei_local->word16) 445*644570b8SJeff Kirsher readsw (dma_base, hdr, sizeof (*hdr) >> 1); 446*644570b8SJeff Kirsher else 447*644570b8SJeff Kirsher readsb (dma_base, hdr, sizeof (*hdr)); 448*644570b8SJeff Kirsher 449*644570b8SJeff Kirsher writeb (ENISR_RDC, addr + EN0_ISR); 450*644570b8SJeff Kirsher ei_local->dmaing = 0; 451*644570b8SJeff Kirsher } 452*644570b8SJeff Kirsher 453*644570b8SJeff Kirsher /* 454*644570b8SJeff Kirsher * Open/initialize the board. This is called (in the current kernel) 455*644570b8SJeff Kirsher * sometime after booting when the 'ifconfig' program is run. 456*644570b8SJeff Kirsher * 457*644570b8SJeff Kirsher * This routine should set everything up anew at each open, even 458*644570b8SJeff Kirsher * registers that "should" only need to be set once at boot, so that 459*644570b8SJeff Kirsher * there is non-reboot way to recover if something goes wrong. 460*644570b8SJeff Kirsher */ 461*644570b8SJeff Kirsher static int 462*644570b8SJeff Kirsher etherh_open(struct net_device *dev) 463*644570b8SJeff Kirsher { 464*644570b8SJeff Kirsher struct ei_device *ei_local = netdev_priv(dev); 465*644570b8SJeff Kirsher 466*644570b8SJeff Kirsher if (!is_valid_ether_addr(dev->dev_addr)) { 467*644570b8SJeff Kirsher printk(KERN_WARNING "%s: invalid ethernet MAC address\n", 468*644570b8SJeff Kirsher dev->name); 469*644570b8SJeff Kirsher return -EINVAL; 470*644570b8SJeff Kirsher } 471*644570b8SJeff Kirsher 472*644570b8SJeff Kirsher if (request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev)) 473*644570b8SJeff Kirsher return -EAGAIN; 474*644570b8SJeff Kirsher 475*644570b8SJeff Kirsher /* 476*644570b8SJeff Kirsher * Make sure that we aren't going to change the 477*644570b8SJeff Kirsher * media type on the next reset - we are about to 478*644570b8SJeff Kirsher * do automedia manually now. 479*644570b8SJeff Kirsher */ 480*644570b8SJeff Kirsher ei_local->interface_num = 0; 481*644570b8SJeff Kirsher 482*644570b8SJeff Kirsher /* 483*644570b8SJeff Kirsher * If we are doing automedia detection, do it now. 484*644570b8SJeff Kirsher * This is more reliable than the 8390's detection. 485*644570b8SJeff Kirsher */ 486*644570b8SJeff Kirsher if (dev->flags & IFF_AUTOMEDIA) { 487*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASET; 488*644570b8SJeff Kirsher etherh_setif(dev); 489*644570b8SJeff Kirsher mdelay(1); 490*644570b8SJeff Kirsher if (!etherh_getifstat(dev)) { 491*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASE2; 492*644570b8SJeff Kirsher etherh_setif(dev); 493*644570b8SJeff Kirsher } 494*644570b8SJeff Kirsher } else 495*644570b8SJeff Kirsher etherh_setif(dev); 496*644570b8SJeff Kirsher 497*644570b8SJeff Kirsher etherh_reset(dev); 498*644570b8SJeff Kirsher __ei_open(dev); 499*644570b8SJeff Kirsher 500*644570b8SJeff Kirsher return 0; 501*644570b8SJeff Kirsher } 502*644570b8SJeff Kirsher 503*644570b8SJeff Kirsher /* 504*644570b8SJeff Kirsher * The inverse routine to etherh_open(). 505*644570b8SJeff Kirsher */ 506*644570b8SJeff Kirsher static int 507*644570b8SJeff Kirsher etherh_close(struct net_device *dev) 508*644570b8SJeff Kirsher { 509*644570b8SJeff Kirsher __ei_close (dev); 510*644570b8SJeff Kirsher free_irq (dev->irq, dev); 511*644570b8SJeff Kirsher return 0; 512*644570b8SJeff Kirsher } 513*644570b8SJeff Kirsher 514*644570b8SJeff Kirsher /* 515*644570b8SJeff Kirsher * Initialisation 516*644570b8SJeff Kirsher */ 517*644570b8SJeff Kirsher 518*644570b8SJeff Kirsher static void __init etherh_banner(void) 519*644570b8SJeff Kirsher { 520*644570b8SJeff Kirsher static int version_printed; 521*644570b8SJeff Kirsher 522*644570b8SJeff Kirsher if (net_debug && version_printed++ == 0) 523*644570b8SJeff Kirsher printk(KERN_INFO "%s", version); 524*644570b8SJeff Kirsher } 525*644570b8SJeff Kirsher 526*644570b8SJeff Kirsher /* 527*644570b8SJeff Kirsher * Read the ethernet address string from the on board rom. 528*644570b8SJeff Kirsher * This is an ascii string... 529*644570b8SJeff Kirsher */ 530*644570b8SJeff Kirsher static int __devinit etherh_addr(char *addr, struct expansion_card *ec) 531*644570b8SJeff Kirsher { 532*644570b8SJeff Kirsher struct in_chunk_dir cd; 533*644570b8SJeff Kirsher char *s; 534*644570b8SJeff Kirsher 535*644570b8SJeff Kirsher if (!ecard_readchunk(&cd, ec, 0xf5, 0)) { 536*644570b8SJeff Kirsher printk(KERN_ERR "%s: unable to read podule description string\n", 537*644570b8SJeff Kirsher dev_name(&ec->dev)); 538*644570b8SJeff Kirsher goto no_addr; 539*644570b8SJeff Kirsher } 540*644570b8SJeff Kirsher 541*644570b8SJeff Kirsher s = strchr(cd.d.string, '('); 542*644570b8SJeff Kirsher if (s) { 543*644570b8SJeff Kirsher int i; 544*644570b8SJeff Kirsher 545*644570b8SJeff Kirsher for (i = 0; i < 6; i++) { 546*644570b8SJeff Kirsher addr[i] = simple_strtoul(s + 1, &s, 0x10); 547*644570b8SJeff Kirsher if (*s != (i == 5? ')' : ':')) 548*644570b8SJeff Kirsher break; 549*644570b8SJeff Kirsher } 550*644570b8SJeff Kirsher 551*644570b8SJeff Kirsher if (i == 6) 552*644570b8SJeff Kirsher return 0; 553*644570b8SJeff Kirsher } 554*644570b8SJeff Kirsher 555*644570b8SJeff Kirsher printk(KERN_ERR "%s: unable to parse MAC address: %s\n", 556*644570b8SJeff Kirsher dev_name(&ec->dev), cd.d.string); 557*644570b8SJeff Kirsher 558*644570b8SJeff Kirsher no_addr: 559*644570b8SJeff Kirsher return -ENODEV; 560*644570b8SJeff Kirsher } 561*644570b8SJeff Kirsher 562*644570b8SJeff Kirsher /* 563*644570b8SJeff Kirsher * Create an ethernet address from the system serial number. 564*644570b8SJeff Kirsher */ 565*644570b8SJeff Kirsher static int __init etherm_addr(char *addr) 566*644570b8SJeff Kirsher { 567*644570b8SJeff Kirsher unsigned int serial; 568*644570b8SJeff Kirsher 569*644570b8SJeff Kirsher if (system_serial_low == 0 && system_serial_high == 0) 570*644570b8SJeff Kirsher return -ENODEV; 571*644570b8SJeff Kirsher 572*644570b8SJeff Kirsher serial = system_serial_low | system_serial_high; 573*644570b8SJeff Kirsher 574*644570b8SJeff Kirsher addr[0] = 0; 575*644570b8SJeff Kirsher addr[1] = 0; 576*644570b8SJeff Kirsher addr[2] = 0xa4; 577*644570b8SJeff Kirsher addr[3] = 0x10 + (serial >> 24); 578*644570b8SJeff Kirsher addr[4] = serial >> 16; 579*644570b8SJeff Kirsher addr[5] = serial >> 8; 580*644570b8SJeff Kirsher return 0; 581*644570b8SJeff Kirsher } 582*644570b8SJeff Kirsher 583*644570b8SJeff Kirsher static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) 584*644570b8SJeff Kirsher { 585*644570b8SJeff Kirsher strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); 586*644570b8SJeff Kirsher strlcpy(info->version, DRV_VERSION, sizeof(info->version)); 587*644570b8SJeff Kirsher strlcpy(info->bus_info, dev_name(dev->dev.parent), 588*644570b8SJeff Kirsher sizeof(info->bus_info)); 589*644570b8SJeff Kirsher } 590*644570b8SJeff Kirsher 591*644570b8SJeff Kirsher static int etherh_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) 592*644570b8SJeff Kirsher { 593*644570b8SJeff Kirsher cmd->supported = etherh_priv(dev)->supported; 594*644570b8SJeff Kirsher ethtool_cmd_speed_set(cmd, SPEED_10); 595*644570b8SJeff Kirsher cmd->duplex = DUPLEX_HALF; 596*644570b8SJeff Kirsher cmd->port = dev->if_port == IF_PORT_10BASET ? PORT_TP : PORT_BNC; 597*644570b8SJeff Kirsher cmd->autoneg = (dev->flags & IFF_AUTOMEDIA ? 598*644570b8SJeff Kirsher AUTONEG_ENABLE : AUTONEG_DISABLE); 599*644570b8SJeff Kirsher return 0; 600*644570b8SJeff Kirsher } 601*644570b8SJeff Kirsher 602*644570b8SJeff Kirsher static int etherh_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) 603*644570b8SJeff Kirsher { 604*644570b8SJeff Kirsher switch (cmd->autoneg) { 605*644570b8SJeff Kirsher case AUTONEG_ENABLE: 606*644570b8SJeff Kirsher dev->flags |= IFF_AUTOMEDIA; 607*644570b8SJeff Kirsher break; 608*644570b8SJeff Kirsher 609*644570b8SJeff Kirsher case AUTONEG_DISABLE: 610*644570b8SJeff Kirsher switch (cmd->port) { 611*644570b8SJeff Kirsher case PORT_TP: 612*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASET; 613*644570b8SJeff Kirsher break; 614*644570b8SJeff Kirsher 615*644570b8SJeff Kirsher case PORT_BNC: 616*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASE2; 617*644570b8SJeff Kirsher break; 618*644570b8SJeff Kirsher 619*644570b8SJeff Kirsher default: 620*644570b8SJeff Kirsher return -EINVAL; 621*644570b8SJeff Kirsher } 622*644570b8SJeff Kirsher dev->flags &= ~IFF_AUTOMEDIA; 623*644570b8SJeff Kirsher break; 624*644570b8SJeff Kirsher 625*644570b8SJeff Kirsher default: 626*644570b8SJeff Kirsher return -EINVAL; 627*644570b8SJeff Kirsher } 628*644570b8SJeff Kirsher 629*644570b8SJeff Kirsher etherh_setif(dev); 630*644570b8SJeff Kirsher 631*644570b8SJeff Kirsher return 0; 632*644570b8SJeff Kirsher } 633*644570b8SJeff Kirsher 634*644570b8SJeff Kirsher static const struct ethtool_ops etherh_ethtool_ops = { 635*644570b8SJeff Kirsher .get_settings = etherh_get_settings, 636*644570b8SJeff Kirsher .set_settings = etherh_set_settings, 637*644570b8SJeff Kirsher .get_drvinfo = etherh_get_drvinfo, 638*644570b8SJeff Kirsher }; 639*644570b8SJeff Kirsher 640*644570b8SJeff Kirsher static const struct net_device_ops etherh_netdev_ops = { 641*644570b8SJeff Kirsher .ndo_open = etherh_open, 642*644570b8SJeff Kirsher .ndo_stop = etherh_close, 643*644570b8SJeff Kirsher .ndo_set_config = etherh_set_config, 644*644570b8SJeff Kirsher .ndo_start_xmit = __ei_start_xmit, 645*644570b8SJeff Kirsher .ndo_tx_timeout = __ei_tx_timeout, 646*644570b8SJeff Kirsher .ndo_get_stats = __ei_get_stats, 647*644570b8SJeff Kirsher .ndo_set_multicast_list = __ei_set_multicast_list, 648*644570b8SJeff Kirsher .ndo_validate_addr = eth_validate_addr, 649*644570b8SJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 650*644570b8SJeff Kirsher .ndo_change_mtu = eth_change_mtu, 651*644570b8SJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 652*644570b8SJeff Kirsher .ndo_poll_controller = __ei_poll, 653*644570b8SJeff Kirsher #endif 654*644570b8SJeff Kirsher }; 655*644570b8SJeff Kirsher 656*644570b8SJeff Kirsher static u32 etherh_regoffsets[16]; 657*644570b8SJeff Kirsher static u32 etherm_regoffsets[16]; 658*644570b8SJeff Kirsher 659*644570b8SJeff Kirsher static int __devinit 660*644570b8SJeff Kirsher etherh_probe(struct expansion_card *ec, const struct ecard_id *id) 661*644570b8SJeff Kirsher { 662*644570b8SJeff Kirsher const struct etherh_data *data = id->data; 663*644570b8SJeff Kirsher struct ei_device *ei_local; 664*644570b8SJeff Kirsher struct net_device *dev; 665*644570b8SJeff Kirsher struct etherh_priv *eh; 666*644570b8SJeff Kirsher int ret; 667*644570b8SJeff Kirsher 668*644570b8SJeff Kirsher etherh_banner(); 669*644570b8SJeff Kirsher 670*644570b8SJeff Kirsher ret = ecard_request_resources(ec); 671*644570b8SJeff Kirsher if (ret) 672*644570b8SJeff Kirsher goto out; 673*644570b8SJeff Kirsher 674*644570b8SJeff Kirsher dev = ____alloc_ei_netdev(sizeof(struct etherh_priv)); 675*644570b8SJeff Kirsher if (!dev) { 676*644570b8SJeff Kirsher ret = -ENOMEM; 677*644570b8SJeff Kirsher goto release; 678*644570b8SJeff Kirsher } 679*644570b8SJeff Kirsher 680*644570b8SJeff Kirsher SET_NETDEV_DEV(dev, &ec->dev); 681*644570b8SJeff Kirsher 682*644570b8SJeff Kirsher dev->netdev_ops = ðerh_netdev_ops; 683*644570b8SJeff Kirsher dev->irq = ec->irq; 684*644570b8SJeff Kirsher dev->ethtool_ops = ðerh_ethtool_ops; 685*644570b8SJeff Kirsher 686*644570b8SJeff Kirsher if (data->supported & SUPPORTED_Autoneg) 687*644570b8SJeff Kirsher dev->flags |= IFF_AUTOMEDIA; 688*644570b8SJeff Kirsher if (data->supported & SUPPORTED_TP) { 689*644570b8SJeff Kirsher dev->flags |= IFF_PORTSEL; 690*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASET; 691*644570b8SJeff Kirsher } else if (data->supported & SUPPORTED_BNC) { 692*644570b8SJeff Kirsher dev->flags |= IFF_PORTSEL; 693*644570b8SJeff Kirsher dev->if_port = IF_PORT_10BASE2; 694*644570b8SJeff Kirsher } else 695*644570b8SJeff Kirsher dev->if_port = IF_PORT_UNKNOWN; 696*644570b8SJeff Kirsher 697*644570b8SJeff Kirsher eh = etherh_priv(dev); 698*644570b8SJeff Kirsher eh->supported = data->supported; 699*644570b8SJeff Kirsher eh->ctrl = 0; 700*644570b8SJeff Kirsher eh->id = ec->cid.product; 701*644570b8SJeff Kirsher eh->memc = ecardm_iomap(ec, ECARD_RES_MEMC, 0, PAGE_SIZE); 702*644570b8SJeff Kirsher if (!eh->memc) { 703*644570b8SJeff Kirsher ret = -ENOMEM; 704*644570b8SJeff Kirsher goto free; 705*644570b8SJeff Kirsher } 706*644570b8SJeff Kirsher 707*644570b8SJeff Kirsher eh->ctrl_port = eh->memc; 708*644570b8SJeff Kirsher if (data->ctrl_ioc) { 709*644570b8SJeff Kirsher eh->ioc_fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, PAGE_SIZE); 710*644570b8SJeff Kirsher if (!eh->ioc_fast) { 711*644570b8SJeff Kirsher ret = -ENOMEM; 712*644570b8SJeff Kirsher goto free; 713*644570b8SJeff Kirsher } 714*644570b8SJeff Kirsher eh->ctrl_port = eh->ioc_fast; 715*644570b8SJeff Kirsher } 716*644570b8SJeff Kirsher 717*644570b8SJeff Kirsher dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset; 718*644570b8SJeff Kirsher eh->dma_base = eh->memc + data->dataport_offset; 719*644570b8SJeff Kirsher eh->ctrl_port += data->ctrlport_offset; 720*644570b8SJeff Kirsher 721*644570b8SJeff Kirsher /* 722*644570b8SJeff Kirsher * IRQ and control port handling - only for non-NIC slot cards. 723*644570b8SJeff Kirsher */ 724*644570b8SJeff Kirsher if (ec->slot_no != 8) { 725*644570b8SJeff Kirsher ecard_setirq(ec, ðerh_ops, eh); 726*644570b8SJeff Kirsher } else { 727*644570b8SJeff Kirsher /* 728*644570b8SJeff Kirsher * If we're in the NIC slot, make sure the IRQ is enabled 729*644570b8SJeff Kirsher */ 730*644570b8SJeff Kirsher etherh_set_ctrl(eh, ETHERH_CP_IE); 731*644570b8SJeff Kirsher } 732*644570b8SJeff Kirsher 733*644570b8SJeff Kirsher ei_local = netdev_priv(dev); 734*644570b8SJeff Kirsher spin_lock_init(&ei_local->page_lock); 735*644570b8SJeff Kirsher 736*644570b8SJeff Kirsher if (ec->cid.product == PROD_ANT_ETHERM) { 737*644570b8SJeff Kirsher etherm_addr(dev->dev_addr); 738*644570b8SJeff Kirsher ei_local->reg_offset = etherm_regoffsets; 739*644570b8SJeff Kirsher } else { 740*644570b8SJeff Kirsher etherh_addr(dev->dev_addr, ec); 741*644570b8SJeff Kirsher ei_local->reg_offset = etherh_regoffsets; 742*644570b8SJeff Kirsher } 743*644570b8SJeff Kirsher 744*644570b8SJeff Kirsher ei_local->name = dev->name; 745*644570b8SJeff Kirsher ei_local->word16 = 1; 746*644570b8SJeff Kirsher ei_local->tx_start_page = data->tx_start_page; 747*644570b8SJeff Kirsher ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES; 748*644570b8SJeff Kirsher ei_local->stop_page = data->stop_page; 749*644570b8SJeff Kirsher ei_local->reset_8390 = etherh_reset; 750*644570b8SJeff Kirsher ei_local->block_input = etherh_block_input; 751*644570b8SJeff Kirsher ei_local->block_output = etherh_block_output; 752*644570b8SJeff Kirsher ei_local->get_8390_hdr = etherh_get_header; 753*644570b8SJeff Kirsher ei_local->interface_num = 0; 754*644570b8SJeff Kirsher 755*644570b8SJeff Kirsher etherh_reset(dev); 756*644570b8SJeff Kirsher __NS8390_init(dev, 0); 757*644570b8SJeff Kirsher 758*644570b8SJeff Kirsher ret = register_netdev(dev); 759*644570b8SJeff Kirsher if (ret) 760*644570b8SJeff Kirsher goto free; 761*644570b8SJeff Kirsher 762*644570b8SJeff Kirsher printk(KERN_INFO "%s: %s in slot %d, %pM\n", 763*644570b8SJeff Kirsher dev->name, data->name, ec->slot_no, dev->dev_addr); 764*644570b8SJeff Kirsher 765*644570b8SJeff Kirsher ecard_set_drvdata(ec, dev); 766*644570b8SJeff Kirsher 767*644570b8SJeff Kirsher return 0; 768*644570b8SJeff Kirsher 769*644570b8SJeff Kirsher free: 770*644570b8SJeff Kirsher free_netdev(dev); 771*644570b8SJeff Kirsher release: 772*644570b8SJeff Kirsher ecard_release_resources(ec); 773*644570b8SJeff Kirsher out: 774*644570b8SJeff Kirsher return ret; 775*644570b8SJeff Kirsher } 776*644570b8SJeff Kirsher 777*644570b8SJeff Kirsher static void __devexit etherh_remove(struct expansion_card *ec) 778*644570b8SJeff Kirsher { 779*644570b8SJeff Kirsher struct net_device *dev = ecard_get_drvdata(ec); 780*644570b8SJeff Kirsher 781*644570b8SJeff Kirsher ecard_set_drvdata(ec, NULL); 782*644570b8SJeff Kirsher 783*644570b8SJeff Kirsher unregister_netdev(dev); 784*644570b8SJeff Kirsher 785*644570b8SJeff Kirsher free_netdev(dev); 786*644570b8SJeff Kirsher 787*644570b8SJeff Kirsher ecard_release_resources(ec); 788*644570b8SJeff Kirsher } 789*644570b8SJeff Kirsher 790*644570b8SJeff Kirsher static struct etherh_data etherm_data = { 791*644570b8SJeff Kirsher .ns8390_offset = ETHERM_NS8390, 792*644570b8SJeff Kirsher .dataport_offset = ETHERM_NS8390 + ETHERM_DATAPORT, 793*644570b8SJeff Kirsher .ctrlport_offset = ETHERM_NS8390 + ETHERM_CTRLPORT, 794*644570b8SJeff Kirsher .name = "ANT EtherM", 795*644570b8SJeff Kirsher .supported = SUPPORTED_10baseT_Half, 796*644570b8SJeff Kirsher .tx_start_page = ETHERM_TX_START_PAGE, 797*644570b8SJeff Kirsher .stop_page = ETHERM_STOP_PAGE, 798*644570b8SJeff Kirsher }; 799*644570b8SJeff Kirsher 800*644570b8SJeff Kirsher static struct etherh_data etherlan500_data = { 801*644570b8SJeff Kirsher .ns8390_offset = ETHERH500_NS8390, 802*644570b8SJeff Kirsher .dataport_offset = ETHERH500_NS8390 + ETHERH500_DATAPORT, 803*644570b8SJeff Kirsher .ctrlport_offset = ETHERH500_CTRLPORT, 804*644570b8SJeff Kirsher .ctrl_ioc = 1, 805*644570b8SJeff Kirsher .name = "i3 EtherH 500", 806*644570b8SJeff Kirsher .supported = SUPPORTED_10baseT_Half, 807*644570b8SJeff Kirsher .tx_start_page = ETHERH_TX_START_PAGE, 808*644570b8SJeff Kirsher .stop_page = ETHERH_STOP_PAGE, 809*644570b8SJeff Kirsher }; 810*644570b8SJeff Kirsher 811*644570b8SJeff Kirsher static struct etherh_data etherlan600_data = { 812*644570b8SJeff Kirsher .ns8390_offset = ETHERH600_NS8390, 813*644570b8SJeff Kirsher .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, 814*644570b8SJeff Kirsher .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, 815*644570b8SJeff Kirsher .name = "i3 EtherH 600", 816*644570b8SJeff Kirsher .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, 817*644570b8SJeff Kirsher .tx_start_page = ETHERH_TX_START_PAGE, 818*644570b8SJeff Kirsher .stop_page = ETHERH_STOP_PAGE, 819*644570b8SJeff Kirsher }; 820*644570b8SJeff Kirsher 821*644570b8SJeff Kirsher static struct etherh_data etherlan600a_data = { 822*644570b8SJeff Kirsher .ns8390_offset = ETHERH600_NS8390, 823*644570b8SJeff Kirsher .dataport_offset = ETHERH600_NS8390 + ETHERH600_DATAPORT, 824*644570b8SJeff Kirsher .ctrlport_offset = ETHERH600_NS8390 + ETHERH600_CTRLPORT, 825*644570b8SJeff Kirsher .name = "i3 EtherH 600A", 826*644570b8SJeff Kirsher .supported = SUPPORTED_10baseT_Half | SUPPORTED_TP | SUPPORTED_BNC | SUPPORTED_Autoneg, 827*644570b8SJeff Kirsher .tx_start_page = ETHERH_TX_START_PAGE, 828*644570b8SJeff Kirsher .stop_page = ETHERH_STOP_PAGE, 829*644570b8SJeff Kirsher }; 830*644570b8SJeff Kirsher 831*644570b8SJeff Kirsher static const struct ecard_id etherh_ids[] = { 832*644570b8SJeff Kirsher { MANU_ANT, PROD_ANT_ETHERM, ðerm_data }, 833*644570b8SJeff Kirsher { MANU_I3, PROD_I3_ETHERLAN500, ðerlan500_data }, 834*644570b8SJeff Kirsher { MANU_I3, PROD_I3_ETHERLAN600, ðerlan600_data }, 835*644570b8SJeff Kirsher { MANU_I3, PROD_I3_ETHERLAN600A, ðerlan600a_data }, 836*644570b8SJeff Kirsher { 0xffff, 0xffff } 837*644570b8SJeff Kirsher }; 838*644570b8SJeff Kirsher 839*644570b8SJeff Kirsher static struct ecard_driver etherh_driver = { 840*644570b8SJeff Kirsher .probe = etherh_probe, 841*644570b8SJeff Kirsher .remove = __devexit_p(etherh_remove), 842*644570b8SJeff Kirsher .id_table = etherh_ids, 843*644570b8SJeff Kirsher .drv = { 844*644570b8SJeff Kirsher .name = DRV_NAME, 845*644570b8SJeff Kirsher }, 846*644570b8SJeff Kirsher }; 847*644570b8SJeff Kirsher 848*644570b8SJeff Kirsher static int __init etherh_init(void) 849*644570b8SJeff Kirsher { 850*644570b8SJeff Kirsher int i; 851*644570b8SJeff Kirsher 852*644570b8SJeff Kirsher for (i = 0; i < 16; i++) { 853*644570b8SJeff Kirsher etherh_regoffsets[i] = i << 2; 854*644570b8SJeff Kirsher etherm_regoffsets[i] = i << 5; 855*644570b8SJeff Kirsher } 856*644570b8SJeff Kirsher 857*644570b8SJeff Kirsher return ecard_register_driver(ðerh_driver); 858*644570b8SJeff Kirsher } 859*644570b8SJeff Kirsher 860*644570b8SJeff Kirsher static void __exit etherh_exit(void) 861*644570b8SJeff Kirsher { 862*644570b8SJeff Kirsher ecard_remove_driver(ðerh_driver); 863*644570b8SJeff Kirsher } 864*644570b8SJeff Kirsher 865*644570b8SJeff Kirsher module_init(etherh_init); 866*644570b8SJeff Kirsher module_exit(etherh_exit); 867