etherh.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/acorn/net/etherh.c
  3.  *
  4.  *  Copyright (C) 2000-2002 Russell King
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License version 2 as
  8.  * published by the Free Software Foundation.
  9.  *
  10.  * NS8390 I-cubed EtherH and ANT EtherM specific driver
  11.  * Thanks to I-Cubed for information on their cards.
  12.  * EtherM conversion (C) 1999 Chris Kemp and Tim Watterton
  13.  * EtherM integration (C) 2000 Aleph One Ltd (Tak-Shing Chan)
  14.  * EtherM integration re-engineered by Russell King.
  15.  *
  16.  * Changelog:
  17.  *  08-12-1996 RMK 1.00 Created
  18.  * RMK 1.03 Added support for EtherLan500 cards
  19.  *  23-11-1997 RMK 1.04 Added media autodetection
  20.  *  16-04-1998 RMK 1.05 Improved media autodetection
  21.  *  10-02-2000 RMK 1.06 Updated for 2.3.43
  22.  *  13-05-2000 RMK 1.07 Updated for 2.3.99-pre8
  23.  *  12-10-1999  CK/TEW EtherM driver first release
  24.  *  21-12-2000 TTC EtherH/EtherM integration
  25.  *  25-12-2000 RMK 1.08 Clean integration of EtherM into this driver.
  26.  *  03-01-2002 RMK 1.09 Always enable IRQs if we're in the nic slot.
  27.  */
  28. #include <linux/module.h>
  29. #include <linux/kernel.h>
  30. #include <linux/sched.h>
  31. #include <linux/types.h>
  32. #include <linux/fcntl.h>
  33. #include <linux/interrupt.h>
  34. #include <linux/ptrace.h>
  35. #include <linux/ioport.h>
  36. #include <linux/in.h>
  37. #include <linux/slab.h>
  38. #include <linux/string.h>
  39. #include <linux/errno.h>
  40. #include <linux/netdevice.h>
  41. #include <linux/etherdevice.h>
  42. #include <linux/skbuff.h>
  43. #include <linux/delay.h>
  44. #include <linux/init.h>
  45. #include <asm/system.h>
  46. #include <asm/bitops.h>
  47. #include <asm/ecard.h>
  48. #include <asm/io.h>
  49. #include <asm/irq.h>
  50. #include "../../net/8390.h"
  51. #define NET_DEBUG  0
  52. #define DEBUG_INIT 2
  53. static unsigned int net_debug = NET_DEBUG;
  54. static const card_ids __init etherh_cids[] = {
  55. { MANU_ANT, PROD_ANT_ETHERM      },
  56. { MANU_I3,  PROD_I3_ETHERLAN500  },
  57. { MANU_I3,  PROD_I3_ETHERLAN600  },
  58. { MANU_I3,  PROD_I3_ETHERLAN600A },
  59. { 0xffff,   0xffff }
  60. };
  61. struct etherh_priv {
  62. unsigned int id;
  63. unsigned int ctrl_port;
  64. unsigned int ctrl;
  65. };
  66. MODULE_AUTHOR("Russell King");
  67. MODULE_DESCRIPTION("EtherH/EtherM driver");
  68. MODULE_LICENSE("GPL");
  69. static char version[] __initdata =
  70. "EtherH/EtherM Driver (c) 2002 Russell King v1.09n";
  71. #define ETHERH500_DATAPORT 0x200 /* MEMC */
  72. #define ETHERH500_NS8390 0x000 /* MEMC */
  73. #define ETHERH500_CTRLPORT 0x200 /* IOC  */
  74. #define ETHERH600_DATAPORT 16 /* MEMC */
  75. #define ETHERH600_NS8390 0x200 /* MEMC */
  76. #define ETHERH600_CTRLPORT 0x080 /* MEMC */
  77. #define ETHERH_CP_IE 1
  78. #define ETHERH_CP_IF 2
  79. #define ETHERH_CP_HEARTBEAT 2
  80. #define ETHERH_TX_START_PAGE 1
  81. #define ETHERH_STOP_PAGE 127
  82. /*
  83.  * These came from CK/TEW
  84.  */
  85. #define ETHERM_DATAPORT 0x080 /* MEMC */
  86. #define ETHERM_NS8390 0x200 /* MEMC */
  87. #define ETHERM_CTRLPORT 0x08f /* MEMC */
  88. #define ETHERM_TX_START_PAGE 64
  89. #define ETHERM_STOP_PAGE 127
  90. /* ------------------------------------------------------------------------ */
  91. static inline void etherh_set_ctrl(struct etherh_priv *eh, unsigned int mask)
  92. {
  93. eh->ctrl |= mask;
  94. outb(eh->ctrl, eh->ctrl_port);
  95. }
  96. static inline void etherh_clr_ctrl(struct etherh_priv *eh, unsigned int mask)
  97. {
  98. eh->ctrl &= ~mask;
  99. outb(eh->ctrl, eh->ctrl_port);
  100. }
  101. static inline unsigned int etherh_get_stat(struct etherh_priv *eh)
  102. {
  103. return inb(eh->ctrl_port);
  104. }
  105. static void etherh_irq_enable(ecard_t *ec, int irqnr)
  106. {
  107. struct etherh_priv *eh = ec->irq_data;
  108. etherh_set_ctrl(eh, ETHERH_CP_IE);
  109. }
  110. static void etherh_irq_disable(ecard_t *ec, int irqnr)
  111. {
  112. struct etherh_priv *eh = ec->irq_data;
  113. etherh_clr_ctrl(eh, ETHERH_CP_IE);
  114. }
  115. static expansioncard_ops_t etherh_ops = {
  116. irqenable: etherh_irq_enable,
  117. irqdisable: etherh_irq_disable,
  118. };
  119. static void
  120. etherh_setif(struct net_device *dev)
  121. {
  122. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  123. struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
  124. unsigned long addr, flags;
  125. save_flags_cli(flags);
  126. /* set the interface type */
  127. switch (eh->id) {
  128. case PROD_I3_ETHERLAN600:
  129. case PROD_I3_ETHERLAN600A:
  130. addr = dev->base_addr + EN0_RCNTHI;
  131. switch (dev->if_port) {
  132. case IF_PORT_10BASE2:
  133. outb((inb(addr) & 0xf8) | 1, addr);
  134. break;
  135. case IF_PORT_10BASET:
  136. outb((inb(addr) & 0xf8), addr);
  137. break;
  138. }
  139. break;
  140. case PROD_I3_ETHERLAN500:
  141. switch (dev->if_port) {
  142. case IF_PORT_10BASE2:
  143. etherh_clr_ctrl(eh, ETHERH_CP_IF);
  144. break;
  145. case IF_PORT_10BASET:
  146. etherh_set_ctrl(eh, ETHERH_CP_IF);
  147. break;
  148. }
  149. break;
  150. default:
  151. break;
  152. }
  153. restore_flags(flags);
  154. }
  155. static int
  156. etherh_getifstat(struct net_device *dev)
  157. {
  158. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  159. struct etherh_priv *eh = (struct etherh_priv *)dev->rmem_start;
  160. int stat = 0;
  161. switch (eh->id) {
  162. case PROD_I3_ETHERLAN600:
  163. case PROD_I3_ETHERLAN600A:
  164. switch (dev->if_port) {
  165. case IF_PORT_10BASE2:
  166. stat = 1;
  167. break;
  168. case IF_PORT_10BASET:
  169. stat = inb(dev->base_addr+EN0_RCNTHI) & 4;
  170. break;
  171. }
  172. break;
  173. case PROD_I3_ETHERLAN500:
  174. switch (dev->if_port) {
  175. case IF_PORT_10BASE2:
  176. stat = 1;
  177. break;
  178. case IF_PORT_10BASET:
  179. stat = etherh_get_stat(eh) & ETHERH_CP_HEARTBEAT;
  180. break;
  181. }
  182. break;
  183. default:
  184. stat = 0;
  185. break;
  186. }
  187. return stat != 0;
  188. }
  189. /*
  190.  * Configure the interface.  Note that we ignore the other
  191.  * parts of ifmap, since its mostly meaningless for this driver.
  192.  */
  193. static int etherh_set_config(struct net_device *dev, struct ifmap *map)
  194. {
  195. switch (map->port) {
  196. case IF_PORT_10BASE2:
  197. case IF_PORT_10BASET:
  198. /*
  199.  * If the user explicitly sets the interface
  200.  * media type, turn off automedia detection.
  201.  */
  202. dev->flags &= ~IFF_AUTOMEDIA;
  203. dev->if_port = map->port;
  204. break;
  205. default:
  206. return -EINVAL;
  207. }
  208. etherh_setif(dev);
  209. return 0;
  210. }
  211. /*
  212.  * Reset the 8390 (hard reset).  Note that we can't actually do this.
  213.  */
  214. static void
  215. etherh_reset(struct net_device *dev)
  216. {
  217. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  218. outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
  219. /*
  220.  * See if we need to change the interface type.
  221.  * Note that we use 'interface_num' as a flag
  222.  * to indicate that we need to change the media.
  223.  */
  224. if (dev->flags & IFF_AUTOMEDIA && ei_local->interface_num) {
  225. ei_local->interface_num = 0;
  226. if (dev->if_port == IF_PORT_10BASET)
  227. dev->if_port = IF_PORT_10BASE2;
  228. else
  229. dev->if_port = IF_PORT_10BASET;
  230. etherh_setif(dev);
  231. }
  232. }
  233. /*
  234.  * Write a block of data out to the 8390
  235.  */
  236. static void
  237. etherh_block_output (struct net_device *dev, int count, const unsigned char *buf, int start_page)
  238. {
  239. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  240. unsigned int addr, dma_addr;
  241. unsigned long dma_start;
  242. if (ei_local->dmaing) {
  243. printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
  244. " DMAstat %d irqlock %dn", dev->name,
  245. ei_local->dmaing, ei_local->irqlock);
  246. return;
  247. }
  248. /*
  249.  * Make sure we have a round number of bytes if we're in word mode.
  250.  */
  251. if (count & 1 && ei_local->word16)
  252. count++;
  253. ei_local->dmaing = 1;
  254. addr = dev->base_addr;
  255. dma_addr = dev->mem_start;
  256. count = (count + 1) & ~1;
  257. outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
  258. outb (0x42, addr + EN0_RCNTLO);
  259. outb (0x00, addr + EN0_RCNTHI);
  260. outb (0x42, addr + EN0_RSARLO);
  261. outb (0x00, addr + EN0_RSARHI);
  262. outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
  263. udelay (1);
  264. outb (ENISR_RDC, addr + EN0_ISR);
  265. outb (count, addr + EN0_RCNTLO);
  266. outb (count >> 8, addr + EN0_RCNTHI);
  267. outb (0, addr + EN0_RSARLO);
  268. outb (start_page, addr + EN0_RSARHI);
  269. outb (E8390_RWRITE | E8390_START, addr + E8390_CMD);
  270. if (ei_local->word16)
  271. outsw (dma_addr, buf, count >> 1);
  272. else
  273. outsb (dma_addr, buf, count);
  274. dma_start = jiffies;
  275. while ((inb (addr + EN0_ISR) & ENISR_RDC) == 0)
  276. if (jiffies - dma_start > 2*HZ/100) { /* 20ms */
  277. printk(KERN_ERR "%s: timeout waiting for TX RDCn",
  278. dev->name);
  279. etherh_reset (dev);
  280. NS8390_init (dev, 1);
  281. break;
  282. }
  283. outb (ENISR_RDC, addr + EN0_ISR);
  284. ei_local->dmaing = 0;
  285. }
  286. /*
  287.  * Read a block of data from the 8390
  288.  */
  289. static void
  290. etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
  291. {
  292. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  293. unsigned int addr, dma_addr;
  294. unsigned char *buf;
  295. if (ei_local->dmaing) {
  296. printk(KERN_ERR "%s: DMAing conflict in etherh_block_input: "
  297. " DMAstat %d irqlock %dn", dev->name,
  298. ei_local->dmaing, ei_local->irqlock);
  299. return;
  300. }
  301. ei_local->dmaing = 1;
  302. addr = dev->base_addr;
  303. dma_addr = dev->mem_start;
  304. buf = skb->data;
  305. outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
  306. outb (count, addr + EN0_RCNTLO);
  307. outb (count >> 8, addr + EN0_RCNTHI);
  308. outb (ring_offset, addr + EN0_RSARLO);
  309. outb (ring_offset >> 8, addr + EN0_RSARHI);
  310. outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
  311. if (ei_local->word16) {
  312. insw (dma_addr, buf, count >> 1);
  313. if (count & 1)
  314. buf[count - 1] = inb (dma_addr);
  315. } else
  316. insb (dma_addr, buf, count);
  317. outb (ENISR_RDC, addr + EN0_ISR);
  318. ei_local->dmaing = 0;
  319. }
  320. /*
  321.  * Read a header from the 8390
  322.  */
  323. static void
  324. etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
  325. {
  326. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  327. unsigned int addr, dma_addr;
  328. if (ei_local->dmaing) {
  329. printk(KERN_ERR "%s: DMAing conflict in etherh_get_header: "
  330. " DMAstat %d irqlock %dn", dev->name,
  331. ei_local->dmaing, ei_local->irqlock);
  332. return;
  333. }
  334. ei_local->dmaing = 1;
  335. addr = dev->base_addr;
  336. dma_addr = dev->mem_start;
  337. outb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
  338. outb (sizeof (*hdr), addr + EN0_RCNTLO);
  339. outb (0, addr + EN0_RCNTHI);
  340. outb (0, addr + EN0_RSARLO);
  341. outb (ring_page, addr + EN0_RSARHI);
  342. outb (E8390_RREAD | E8390_START, addr + E8390_CMD);
  343. if (ei_local->word16)
  344. insw (dma_addr, hdr, sizeof (*hdr) >> 1);
  345. else
  346. insb (dma_addr, hdr, sizeof (*hdr));
  347. outb (ENISR_RDC, addr + EN0_ISR);
  348. ei_local->dmaing = 0;
  349. }
  350. /*
  351.  * Open/initialize the board.  This is called (in the current kernel)
  352.  * sometime after booting when the 'ifconfig' program is run.
  353.  *
  354.  * This routine should set everything up anew at each open, even
  355.  * registers that "should" only need to be set once at boot, so that
  356.  * there is non-reboot way to recover if something goes wrong.
  357.  */
  358. static int
  359. etherh_open(struct net_device *dev)
  360. {
  361. struct ei_device *ei_local = (struct ei_device *) dev->priv;
  362. if (request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))
  363. return -EAGAIN;
  364. /*
  365.  * Make sure that we aren't going to change the
  366.  * media type on the next reset - we are about to
  367.  * do automedia manually now.
  368.  */
  369. ei_local->interface_num = 0;
  370. /*
  371.  * If we are doing automedia detection, do it now.
  372.  * This is more reliable than the 8390's detection.
  373.  */
  374. if (dev->flags & IFF_AUTOMEDIA) {
  375. dev->if_port = IF_PORT_10BASET;
  376. etherh_setif(dev);
  377. mdelay(1);
  378. if (!etherh_getifstat(dev)) {
  379. dev->if_port = IF_PORT_10BASE2;
  380. etherh_setif(dev);
  381. }
  382. } else
  383. etherh_setif(dev);
  384. etherh_reset(dev);
  385. ei_open(dev);
  386. return 0;
  387. }
  388. /*
  389.  * The inverse routine to etherh_open().
  390.  */
  391. static int
  392. etherh_close(struct net_device *dev)
  393. {
  394. ei_close (dev);
  395. free_irq (dev->irq, dev);
  396. return 0;
  397. }
  398. /*
  399.  * Initialisation
  400.  */
  401. static void __init etherh_banner(void)
  402. {
  403. static int version_printed;
  404. if (net_debug && version_printed++ == 0)
  405. printk(KERN_INFO "%s", version);
  406. }
  407. /*
  408.  * Read the ethernet address string from the on board rom.
  409.  * This is an ascii string...
  410.  */
  411. static int __init etherh_addr(char *addr, struct expansion_card *ec)
  412. {
  413. struct in_chunk_dir cd;
  414. char *s;
  415. if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
  416. int i;
  417. for (i = 0; i < 6; i++) {
  418. addr[i] = simple_strtoul(s + 1, &s, 0x10);
  419. if (*s != (i == 5? ')' : ':'))
  420. break;
  421. }
  422. if (i == 6)
  423. return 0;
  424. }
  425. return ENODEV;
  426. }
  427. /*
  428.  * Create an ethernet address from the system serial number.
  429.  */
  430. static int __init etherm_addr(char *addr)
  431. {
  432. unsigned int serial;
  433. if (system_serial_low == 0 && system_serial_high == 0)
  434. return ENODEV;
  435. serial = system_serial_low | system_serial_high;
  436. addr[0] = 0;
  437. addr[1] = 0;
  438. addr[2] = 0xa4;
  439. addr[3] = 0x10 + (serial >> 24);
  440. addr[4] = serial >> 16;
  441. addr[5] = serial >> 8;
  442. return 0;
  443. }
  444. static u32 etherh_regoffsets[16];
  445. static u32 etherm_regoffsets[16];
  446. static struct net_device * __init etherh_init_one(struct expansion_card *ec)
  447. {
  448. struct ei_device *ei_local;
  449. struct net_device *dev;
  450. struct etherh_priv *eh;
  451. const char *dev_type;
  452. int i, size;
  453. etherh_banner();
  454. ecard_claim(ec);
  455. dev = init_etherdev(NULL, 0);
  456. if (!dev)
  457. goto out;
  458. eh = kmalloc(sizeof(struct etherh_priv), GFP_KERNEL);
  459. if (!eh)
  460. goto out_nopriv;
  461. SET_MODULE_OWNER(dev);
  462. dev->open = etherh_open;
  463. dev->stop = etherh_close;
  464. dev->set_config = etherh_set_config;
  465. dev->irq = ec->irq;
  466. dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
  467. dev->rmem_start = (unsigned long)eh;
  468. /*
  469.  * IRQ and control port handling
  470.  */
  471. ec->ops = &etherh_ops;
  472. ec->irq_data = eh;
  473. eh->ctrl = 0;
  474. eh->id = ec->cid.product;
  475. switch (ec->cid.product) {
  476. case PROD_ANT_ETHERM:
  477. if (etherm_addr(dev->dev_addr))
  478. goto free;
  479. dev->base_addr += ETHERM_NS8390;
  480. dev->mem_start  = dev->base_addr + ETHERM_DATAPORT;
  481. eh->ctrl_port   = dev->base_addr + ETHERM_CTRLPORT;
  482. break;
  483. case PROD_I3_ETHERLAN500:
  484. if (etherh_addr(dev->dev_addr, ec))
  485. goto free;
  486. dev->base_addr += ETHERH500_NS8390;
  487. dev->mem_start  = dev->base_addr + ETHERH500_DATAPORT;
  488. eh->ctrl_port   = ecard_address (ec, ECARD_IOC, ECARD_FAST)
  489.   + ETHERH500_CTRLPORT;
  490. break;
  491. case PROD_I3_ETHERLAN600:
  492. case PROD_I3_ETHERLAN600A:
  493. if (etherh_addr(dev->dev_addr, ec))
  494. goto free;
  495. dev->base_addr += ETHERH600_NS8390;
  496. dev->mem_start  = dev->base_addr + ETHERH600_DATAPORT;
  497. eh->ctrl_port   = dev->base_addr + ETHERH600_CTRLPORT;
  498. break;
  499. default:
  500. printk(KERN_ERR "%s: unknown card type %xn",
  501.        dev->name, ec->cid.product);
  502. goto free;
  503. }
  504. size = 16;
  505. if (ec->cid.product == PROD_ANT_ETHERM)
  506. size <<= 3;
  507. if (!request_region(dev->base_addr, size, dev->name))
  508. goto free;
  509. if (ethdev_init(dev))
  510. goto release;
  511. /*
  512.  * If we're in the NIC slot, make sure the IRQ is enabled
  513.  */
  514. if (dev->irq == 11)
  515. etherh_set_ctrl(eh, ETHERH_CP_IE);
  516. /*
  517.  * Unfortunately, ethdev_init eventually calls
  518.  * ether_setup, which re-writes dev->flags.
  519.  */
  520. switch (ec->cid.product) {
  521. case PROD_ANT_ETHERM:
  522. dev_type = "ANT EtherM";
  523. dev->if_port = IF_PORT_UNKNOWN;
  524. break;
  525. case PROD_I3_ETHERLAN500:
  526. dev_type = "i3 EtherH 500";
  527. dev->if_port = IF_PORT_UNKNOWN;
  528. break;
  529. case PROD_I3_ETHERLAN600:
  530. dev_type = "i3 EtherH 600";
  531. dev->flags  |= IFF_PORTSEL | IFF_AUTOMEDIA;
  532. dev->if_port = IF_PORT_10BASET;
  533. break;
  534. case PROD_I3_ETHERLAN600A:
  535. dev_type = "i3 EtherH 600A";
  536. dev->flags  |= IFF_PORTSEL | IFF_AUTOMEDIA;
  537. dev->if_port = IF_PORT_10BASET;
  538. break;
  539. default:
  540. dev_type = "unknown";
  541. break;
  542. }
  543. printk(KERN_INFO "%s: %s in slot %d, ",
  544. dev->name, dev_type, ec->slot_no);
  545. for (i = 0; i < 6; i++)
  546. printk("%2.2x%c", dev->dev_addr[i], i == 5 ? 'n' : ':');
  547. ei_local = (struct ei_device *) dev->priv;
  548. if (ec->cid.product == PROD_ANT_ETHERM) {
  549. ei_local->tx_start_page = ETHERM_TX_START_PAGE;
  550. ei_local->stop_page     = ETHERM_STOP_PAGE;
  551. ei_local->reg_offset    = etherm_regoffsets;
  552. } else {
  553. ei_local->tx_start_page = ETHERH_TX_START_PAGE;
  554. ei_local->stop_page     = ETHERH_STOP_PAGE;
  555. ei_local->reg_offset    = etherh_regoffsets;
  556. }
  557. ei_local->name          = dev->name;
  558. ei_local->word16        = 1;
  559. ei_local->rx_start_page = ei_local->tx_start_page + TX_PAGES;
  560. ei_local->reset_8390    = etherh_reset;
  561. ei_local->block_input   = etherh_block_input;
  562. ei_local->block_output  = etherh_block_output;
  563. ei_local->get_8390_hdr  = etherh_get_header;
  564. ei_local->interface_num = 0;
  565. etherh_reset(dev);
  566. NS8390_init(dev, 0);
  567. return dev;
  568. release:
  569. release_region(dev->base_addr, 16);
  570. free:
  571. kfree(eh);
  572. out_nopriv:
  573. unregister_netdev(dev);
  574. kfree(dev);
  575. out:
  576. ecard_release(ec);
  577. return NULL;
  578. }
  579. #define MAX_ETHERH_CARDS 2
  580. static struct net_device *e_dev[MAX_ETHERH_CARDS];
  581. static struct expansion_card *e_card[MAX_ETHERH_CARDS];
  582. static int __init etherh_init(void)
  583. {
  584. int i, ret = -ENODEV;
  585. for (i = 0; i < 16; i++) {
  586. etherh_regoffsets[i] = i;
  587. etherm_regoffsets[i] = i << 3;
  588. }
  589. ecard_startfind();
  590. for (i = 0; i < MAX_ECARDS; i++) {
  591. struct expansion_card *ec;
  592. struct net_device *dev;
  593. ec = ecard_find(0, etherh_cids);
  594. if (!ec)
  595. break;
  596. dev = etherh_init_one(ec);
  597. if (!dev)
  598. break;
  599. e_card[i] = ec;
  600. e_dev[i]  = dev;
  601. ret = 0;
  602. }
  603. return ret;
  604. }
  605. static void __exit etherh_exit(void)
  606. {
  607. int i;
  608. for (i = 0; i < MAX_ETHERH_CARDS; i++) {
  609. if (e_dev[i]) {
  610. int size;
  611. unregister_netdev(e_dev[i]);
  612. size = 16;
  613. if (e_card[i]->cid.product == PROD_ANT_ETHERM)
  614. size <<= 3;
  615. release_region(e_dev[i]->base_addr, size);
  616. kfree(e_dev[i]);
  617. e_dev[i] = NULL;
  618. }
  619. if (e_card[i]) {
  620. e_card[i]->ops = NULL;
  621. kfree(e_card[i]->irq_data);
  622. ecard_release(e_card[i]);
  623. e_card[i] = NULL;
  624. }
  625. }
  626. }
  627. module_init(etherh_init);
  628. module_exit(etherh_exit);