brintos

brintos / linux-shallow public Read only

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