MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / net / moxacpu_mac.c
blob061aaec6cc138984a8c9046817dbc4c99ea3826e
2 /*
3 * This program is the Moxa CPU ethernet device driver.
5 * History:
6 * Date Author Comment
7 * 06-15-2005 Victor Yu. Create it. Make it for Faraday demo board.
8 * 11-04-2005 Victor Yu. Modify it to support Moxa CPU demo board.
9 */
11 #include <linux/config.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/fcntl.h>
16 #include <linux/interrupt.h>
17 #include <linux/ioport.h>
18 #include <linux/in.h>
19 #include <linux/slab.h>
20 #include <linux/string.h>
21 #include <linux/errno.h>
22 #include <linux/init.h>
23 #include <linux/netdevice.h>
24 #include <linux/etherdevice.h>
25 #include <linux/spinlock.h>
26 #include <linux/skbuff.h>
27 #include <linux/device.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/delay.h>
30 #include <linux/workqueue.h>
31 #include <asm/uaccess.h>
32 #include <asm/system.h>
33 #include <asm/bitops.h>
34 #include <asm/io.h>
35 #include <asm/irq.h>
36 #include <asm/dma.h>
37 #include "moxacpu_mac.h"
39 //#define MCPU_MAC_DEBUG
40 //#define USE_SCHEDULE_WORK
42 #if (defined CONFIG_ARCH_IA241_32128)||(defined CONFIG_ARCH_IA241_16128)// add by Victor Yu. 05-22-2007
43 #define CONFIG_ARCH_IA241
44 #endif
46 #if (defined CONFIG_ARCH_UC_7112_LX_PLUS_LITON)
47 #define CONFIG_ARCH_UC_7112_LX_PLUS
48 #endif
50 #ifdef MCPU_MAC_DEBUG
51 #define dbg_printk(x...) printk(x)
52 #else // MCPU_MAC_DEBUG
53 #define dbg_printk(x...)
54 #endif // MCPU_MAC_DEBUG
56 #define TX_DESC_NUM 64
57 #define TX_DESC_NUM_MASK (TX_DESC_NUM-1)
58 #define RX_DESC_NUM 64
59 #define RX_DESC_NUM_MASK (RX_DESC_NUM-1)
60 #define TX_BUF_SIZE 1600
61 #define RX_BUF_SIZE 1600
62 #if TX_BUF_SIZE >= TXBUF_SIZE_MAX
63 #error Moxa CPU ethernet device driver Tx buffer size too large !
64 #endif
65 #if RX_BUF_SIZE >= RXBUF_SIZE_MAX
66 #error Moxa CPU ethernet device driver Rx buffer size too large !
67 #endif
69 static mcpu_mac_priv_t mcpu_mac_priv;
70 #ifdef CONFIG_ARCH_MOXACPU
72 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
73 static mcpu_mac_priv_t mcpu_mac_priv2;
74 #endif
76 #endif // CONFIG_ARCH_MOXACPU
79 #ifdef HAVE_MULTICAST
80 static int crc32( char * s, int length )
82 /* indices */
83 int perByte;
84 int perBit;
85 /* crc polynomial for Ethernet */
86 const unsigned long poly=0xedb88320;
87 /* crc value - preinitialized to all 1's */
88 unsigned long crc_value=0xffffffff;
90 for ( perByte = 0; perByte < length; perByte ++ ) {
91 unsigned char c;
93 c = *(s++);
94 for ( perBit = 0; perBit < 8; perBit++ ) {
95 crc_value = (crc_value>>1)^
96 (((crc_value^c)&0x01)?poly:0);
97 c >>= 1;
100 return crc_value;
103 static void mcpu_mac_setmulticast(unsigned int ioaddr, int count, struct dev_mc_list * addrs )
105 struct dev_mc_list *cur_addr;
106 int crc_val;
108 for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next ) {
109 if ( !( *cur_addr->dmi_addr & 1 ) )
110 continue;
111 crc_val = crc32( cur_addr->dmi_addr, 6 );
112 crc_val = (crc_val>>26)&0x3f; // ยจรบ MSB 6 bit
113 if (crc_val >= 32)
114 outl(inl(ioaddr+MATH1_REG_OFFSET) | (1UL<<(crc_val-32)), ioaddr+MATH1_REG_OFFSET);
115 else
116 outl(inl(ioaddr+MATH0_REG_OFFSET) | (1UL<<crc_val), ioaddr+MATH0_REG_OFFSET);
120 static void mcpu_mac_set_multicast_list(struct net_device *dev)
122 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
123 unsigned long flags;
125 save_flags(flags);
126 cli();
127 #ifdef USE_SCHEDULE_WORK
128 spin_lock(&priv->rxlock);
129 #endif
130 spin_lock(&priv->txlock);
132 if ( dev->flags & IFF_PROMISC )
133 priv->maccr |= RCV_ALL;
134 else
135 priv->maccr &= ~RCV_ALL;
137 if ( dev->flags & IFF_ALLMULTI )
138 priv->maccr |= RX_MULTIPKT;
139 else
140 priv->maccr &= ~RX_MULTIPKT;
142 if ( dev->mc_count ) {
143 priv->maccr |= RX_MULTIPKT; //add by Johnson.Liu 2007/07/06
144 priv->maccr |= HT_MULTI_EN;
145 mcpu_mac_setmulticast(dev->base_addr, dev->mc_count, dev->mc_list);
146 } else {
147 priv->maccr &= ~RX_MULTIPKT; //add by Johnson.Liu 2007/07/06
148 priv->maccr &= ~HT_MULTI_EN;
151 outl(priv->maccr, dev->base_addr+MACCR_REG_OFFSET);
153 spin_unlock(&priv->txlock);
154 #ifdef USE_SCHEDULE_WORK
155 spin_unlock(&priv->rxlock);
156 #endif
157 restore_flags(flags);
159 #endif // HAVE_MULTICAST
161 #if 1 // add by Victor Yu. 07-04-2005
162 static void mywordcopy(void *dest, void *source, int len)
164 unsigned short *pd=(unsigned short *)dest;
165 unsigned short *ps=(unsigned short *)source;
166 int wlen=len>>1;
168 while ( wlen > 0 ) {
169 *pd++=*ps++;
170 wlen--;
172 if ( len & 1 )
173 *(unsigned char *)pd = *(unsigned char *)ps;
175 #endif // 07-04-2005
177 static void mcpu_mac_recv(void *ptr)
179 struct net_device *dev=(struct net_device *)ptr;
180 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
181 rx_desc_t *rxdesc;
182 int len;
183 struct sk_buff *skb;
185 unsigned char *data;
186 #if 1 // add by Victor Yu. 07-04-2005
187 unsigned int ui;
188 int rxnow=priv->RxDescNow;
189 #endif // 07-04-2005
190 #ifndef USE_SCHEDULE_WORK
191 int loops=RX_DESC_NUM;
192 #endif // USE_SCHEDULE_WORK
194 dbg_printk("mcpu_mac_recv test01\n");
197 #if 0
198 dbg_printk("RxDescNow=%d, desc phy=0x%x, virt=0x%x, buf phy=0x%x, virt=0x%x\n", priv->RxDescNow, priv->phyRxDescBaseAddr+(priv->RxDescNow*sizeof(rx_desc_t)), (unsigned int)&priv->virtRxDescBaseAddr[priv->RxDescNow], priv->virtRxDescBaseAddr[priv->RxDescNow].rxdes2.phyRxBufBaseAddr, (unsigned int)priv->virtRxDescBaseAddr[priv->RxDescNow].rxdes2.virtRxBufBaseAddr);
199 dbg_printk("Now Rx desc des0=0x%x, des1=0x%x\n", priv->virtRxDescBaseAddr[priv->RxDescNow].rxdes0.ui, priv->virtRxDescBaseAddr[priv->RxDescNow].rxdes1.ui);
200 #endif
204 #ifdef USE_SCHEDULE_WORK
205 spin_lock(&priv->rxlock);
206 #endif // USE_SCHEDULE_WORK
207 repeat_recv:
208 rxdesc = &priv->virtRxDescBaseAddr[rxnow];
209 #if 0 // mask by Victor Yu. 07-04-2005
210 if ( rxdesc->rxdes0.ubit.RxDMAOwn ) {
211 #else // add by Victor Yu. 07-04-2005
212 ui = rxdesc->rxdes0.ui;
213 if ( ui & RXDMA_OWN ) {
214 #endif // 07-04-2005
215 #ifdef USE_SCHEDULE_WORK
216 spin_unlock(&priv->rxlock);
217 #else
218 #ifdef MCPU_MAC_DEBUG
219 if ( loops == RX_DESC_NUM )
220 printk("Bad receive packet !\n");
221 #endif // MCPU_MAC_DEBUG
222 #endif // USE_SCHEDULE_WORK
223 return;
225 #if 0 // mask by Victor Yu. 07-04-2005
226 if ( rxdesc->rxdes0.ubit.RxErr ||
227 rxdesc->rxdes0.ubit.CRCErr ||
228 rxdesc->rxdes0.ubit.Ftl ||
229 rxdesc->rxdes0.ubit.Runt ||
230 rxdesc->rxdes0.ubit.RxOddNb ) {
231 #else // add by Victor Yu. 07-04-2005
232 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
233 if ( ui & (RX_ERR|CRC_ERR|RUNT|RX_ODD_NB) ) {
234 #else
235 if ( ui & (RX_ERR|CRC_ERR|FTL|RUNT|RX_ODD_NB) ) {
236 #endif
237 #endif // 07-04-2005
238 dbg_printk("Ethernet receive packet error !\n");
239 priv->stats.rx_dropped++;
240 priv->stats.rx_errors++;
241 goto recv_finish;
243 #if 0 // mask by Victor Yu. 07-04-2005
244 len = rxdesc->rxdes0.ubit.RecvFrameLen > RX_BUF_SIZE ? RX_BUF_SIZE : rxdesc->rxdes0.ubit.RecvFrameLen;
245 #else // add by Victor Yu. 07-04-2005
246 len = ui & RFL_MASK;
247 if ( len > RX_BUF_SIZE )
248 len = RX_BUF_SIZE;
249 #endif // 07-04-2005
250 skb = dev_alloc_skb(len+2);
251 if ( skb == NULL ) {
252 dbg_printk("Allocate memory fail !\n");
253 priv->stats.rx_dropped++;
254 goto recv_finish;
256 skb_reserve(skb, 2);
257 skb->dev = dev;
258 data = skb_put(skb, len);
259 dbg_printk("receive data pointer = 0x%x\n", (unsigned long)data);
260 #if 0 // mask by Victor Yu. 07-04-2005
261 memcpy(data, rxdesc->rxdes2.virtRxBufBaseAddr, len);
262 #else // add by Victor Yu. 07-04-2005
263 mywordcopy((void *)data, (void *)rxdesc->rxdes2.virtRxBufBaseAddr, len);
264 #endif // 07-04-2005
265 skb->protocol = eth_type_trans(skb, dev);
266 netif_rx(skb);
267 priv->stats.rx_packets++;
268 priv->stats.rx_bytes += len;
269 if ( ui & MULTICAST_RXDES0 )
270 priv->stats.multicast++;
271 dbg_printk("Receive a good packet.\n");
275 recv_finish:
276 #if 0 // mask by Victor Yu. 07-04-2005
277 rxdesc->rxdes0.ui = 0;
278 rxdesc->rxdes0.ubit.RxDMAOwn = 1;
279 rxdesc->rxdes1.ubit.RxBufSize = RX_BUF_SIZE;
280 #else // add by Victor Yu. 07-04-2005
281 rxdesc->rxdes0.ui = RXDMA_OWN;
282 #endif // 07-04-2005
283 rxnow++;
284 rxnow &= RX_DESC_NUM_MASK;
285 priv->RxDescNow = rxnow;
287 #ifdef USE_SCHEDULE_WORK
288 goto repeat_recv;
289 #else // USE_SCHEDULE_WORK
290 if ( loops-- > 0 )
291 goto repeat_recv;
292 #endif // USE_SCHEDULE_WORK
294 #ifdef USE_SCHEDULE_WORK
295 spin_unlock(&priv->rxlock);
296 #endif // USE_SCHEDULE_WORK
302 static void mcpu_mac_free_memory(struct net_device *dev)
304 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
306 if ( priv->virtTxDescBaseAddr )
307 dma_free_coherent(NULL, sizeof(tx_desc_t)*TX_DESC_NUM, priv->virtTxDescBaseAddr, priv->phyTxDescBaseAddr);
308 if ( priv->virtRxDescBaseAddr )
309 dma_free_coherent(NULL, sizeof(rx_desc_t)*RX_DESC_NUM, priv->virtRxDescBaseAddr, priv->phyRxDescBaseAddr);
310 if ( priv->virtTxBufBaseAddr )
311 dma_free_coherent(NULL, TX_BUF_SIZE*TX_DESC_NUM, priv->virtTxBufBaseAddr, priv->phyTxBufBaseAddr);
312 if ( priv->virtRxBufBaseAddr )
313 dma_free_coherent(NULL, RX_BUF_SIZE*RX_DESC_NUM, priv->virtRxBufBaseAddr, priv->phyRxBufBaseAddr);
316 static void mcpu_mac_setup_desc_ring(struct net_device *dev)
318 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
319 int i;
320 tx_desc_t *txdesc;
321 rx_desc_t *rxdesc;
322 unsigned char *virtbuf;
323 unsigned int phybuf;
325 virtbuf = priv->virtTxBufBaseAddr;
326 phybuf = priv->phyTxBufBaseAddr;
327 for ( i=0; i<TX_DESC_NUM; i++, virtbuf+=TX_BUF_SIZE, phybuf+=TX_BUF_SIZE ) {
328 txdesc = &priv->virtTxDescBaseAddr[i];
329 memset(txdesc, 0, sizeof(tx_desc_t));
330 txdesc->txdes2.phyTxBufBaseAddr = phybuf;
331 txdesc->txdes2.virtTxBufBaseAddr = virtbuf;
333 priv->virtTxDescBaseAddr[TX_DESC_NUM-1].txdes1.ubit.Edotr = 1;
335 virtbuf = priv->virtRxBufBaseAddr;
336 phybuf = priv->phyRxBufBaseAddr;
337 for ( i=0; i<RX_DESC_NUM; i++, virtbuf+=RX_BUF_SIZE, phybuf+=RX_BUF_SIZE ) {
338 rxdesc = &priv->virtRxDescBaseAddr[i];
339 memset(rxdesc, 0, sizeof(rx_desc_t));
340 rxdesc->rxdes0.ubit.RxDMAOwn = 1;
341 rxdesc->rxdes1.ubit.RxBufSize = RX_BUF_SIZE;
342 rxdesc->rxdes2.phyRxBufBaseAddr = phybuf;
343 rxdesc->rxdes2.virtRxBufBaseAddr = virtbuf;
345 priv->virtRxDescBaseAddr[RX_DESC_NUM-1].rxdes1.ubit.Edorr = 1;
346 //dbg_printk("First Rx desc des0=0x%x, des1=%x\n", priv->virtRxDescBaseAddr[0].rxdes0.ui, priv->virtRxDescBaseAddr[0].rxdes1.ui);
348 priv->TxDescNow = priv->RxDescNow = 0;
350 // reset the MAC controler Tx/Rx desciptor base address
351 outl(priv->phyTxDescBaseAddr, dev->base_addr+TXR_BADR_REG_OFFSET);
352 outl(priv->phyRxDescBaseAddr, dev->base_addr+RXR_BADR_REG_OFFSET);
353 #if 0
354 dbg_printk("Tx/Rx desc phy=0x%x,0x%x, virt=0x%x,0x%x\n", priv->phyTxDescBaseAddr, priv->phyRxDescBaseAddr, (unsigned int)priv->virtTxDescBaseAddr, (unsigned int)priv->virtRxDescBaseAddr);
355 dbg_printk("set Tx desc base address=0x%x, Rx=0x%x\n", inl(dev->base_addr+TXR_BADR_REG_OFFSET), inl(dev->base_addr+RXR_BADR_REG_OFFSET));
356 #endif
359 static void mcpu_mac_reset(struct net_device *dev)
361 unsigned int reg=dev->base_addr+MACCR_REG_OFFSET;
363 outl(SW_RST, reg); // software reset
364 while ( inl(reg) & SW_RST ) mdelay(10);
365 // maybe we need to disable the all interrupt
366 outl(0, dev->base_addr+IMR_REG_OFFSET);
367 // ((mcpu_mac_priv_t *)dev->priv)->maccr = RX_BROADPKT | FULLDUP | CRC_APD;
368 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) //johnson modify for 802.1Q support 2008-11-14
369 ((mcpu_mac_priv_t *)dev->priv)->maccr = RX_BROADPKT | ENRX_IN_HALFTX | CRC_APD | RX_FTL;
370 #else
371 ((mcpu_mac_priv_t *)dev->priv)->maccr = RX_BROADPKT | ENRX_IN_HALFTX | CRC_APD;
372 #endif
375 static void mcpu_mac_set_mac_address(unsigned int base, unsigned char *macaddr)
377 unsigned int val;
379 val = (((u32)macaddr[0] << 8) &0xff00) | ((u32)macaddr[1] & 0xff);
380 outl(val, base);
381 val = (((u32)macaddr[2]<<24) & 0xff000000) |
382 (((u32)macaddr[3]<<16) & 0x00ff0000) |
383 (((u32)macaddr[4]<<8) & 0x0000ff00) |
384 (((u32)macaddr[5]) & 0x000000ff);
385 outl(val, base+4);
388 #ifdef MCPU_MAC_DEBUG // add by Victor Yu. 03-14-2006
389 static void mcpu_mac_get_mac_address(unsigned int base, unsigned char *macaddr)
391 unsigned int val;
393 val = inl(base);
394 macaddr[0] = (val >> 8) & 0xff;
395 macaddr[1] = val & 0xff;
396 val = inl(base+4);
397 macaddr[2] = (val >> 24) & 0xff;
398 macaddr[3] = (val >> 16) & 0xff;
399 macaddr[4] = (val >> 8) & 0xff;
400 macaddr[5] = val & 0xff;
402 #endif
404 static void mcpu_mac_enable(struct net_device *dev)
406 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
407 unsigned int base=dev->base_addr;
409 outl(0x00001010, base+ITC_REG_OFFSET);
410 outl(0x00000001, base+APTC_REG_OFFSET);
411 outl(0x00000390, base+DBLAC_REG_OFFSET);
412 #ifdef MCPU_MAC_DEBUG
413 outl(RPKT_FINISH_M|NORXBUF_M|AHB_ERR_M, base+IMR_REG_OFFSET);
414 #else
415 outl(RPKT_FINISH_M, base+IMR_REG_OFFSET);
416 #endif
417 priv->maccr |= (RCV_EN | XMT_EN | RDMA_EN | XDMA_EN);
418 outl(priv->maccr, base+MACCR_REG_OFFSET);
421 static void mcpu_mac_tx_timeout(struct net_device *dev)
423 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
424 unsigned long flags;
426 dbg_printk("mcpu_mac_tx_timeout test01\n");
427 save_flags(flags);
428 cli();
429 #ifdef USE_SCHEDULE_WORK
430 spin_lock(&priv->rxlock);
431 #endif
432 spin_lock(&priv->txlock);
433 mcpu_mac_reset(dev);
434 mcpu_mac_set_mac_address(dev->base_addr+MAC_MADR_REG_OFFSET, dev->dev_addr);
435 mcpu_mac_setup_desc_ring(dev);
436 mcpu_mac_enable(dev);
437 spin_unlock(&priv->txlock);
438 #ifdef USE_SCHEDULE_WORK
439 spin_unlock(&priv->rxlock);
440 #endif
441 restore_flags(flags);
442 netif_wake_queue(dev);
443 dev->trans_start = jiffies;
446 static int mcpu_mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
448 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
449 tx_desc_t *txdesc;
450 int len;
451 int txnow=priv->TxDescNow;
453 dbg_printk("mcpu_mac_hard_start_xmit test01\n");
454 spin_lock(&priv->txlock);
456 // first check the Tx buffer is enough or not
457 txdesc = &priv->virtTxDescBaseAddr[txnow];
458 if ( txdesc->txdes0.ubit.TxDMAOwn ) {
459 dbg_printk("No Tx space to transmit the packet !\n");
460 priv->stats.tx_dropped++;
461 goto xmit_final;
464 // fill the data
465 #if 0 // mask by Victor Yu. 07-04-2005
466 len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
467 len = len > TX_BUF_SIZE ? TX_BUF_SIZE : len;
468 #else // add by Victor Yu. 07-04-2005
469 len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len;
470 #endif
471 #if 0 // mask by Victor Yu. 07-04-2005
472 memcpy(txdesc->txdes2.virtTxBufBaseAddr, skb->data, len);
473 #else // add by Victor Yu. 07-04-2005
474 mywordcopy((void *)txdesc->txdes2.virtTxBufBaseAddr, (void *)skb->data, len);
475 #endif
476 dbg_printk("transmit data pointer = 0x%x\n", (unsigned long)skb->data);
477 #if 1 // add by Victor Yu. 07-04-2005
478 if ( skb->len < ETH_ZLEN ) {
479 memset(&txdesc->txdes2.virtTxBufBaseAddr[skb->len], 0, ETH_ZLEN-skb->len);
480 len = ETH_ZLEN;
482 #endif
483 txdesc->txdes1.ubit.Lts = 1;
484 txdesc->txdes1.ubit.Fts = 1;
485 txdesc->txdes1.ubit.Tx2fic = 0;
486 txdesc->txdes1.ubit.Txic = 0;
487 txdesc->txdes1.ubit.TxBufSize = len;
488 #if 0 // mask by Victor Yu. 07-04-2005
489 txdesc->txdes0.ui = 0;
490 txdesc->txdes0.ubit.TxDMAOwn = 1;
491 #else // add by Victor Yu. 07-04-2005
492 txdesc->txdes0.ui = TXDMA_OWN;
493 #endif
495 outl(0xffffffff, dev->base_addr+TXPD_REG_OFFSET); // start to send packet
496 #if 0
497 dbg_printk("TxDescNow=%d, address=0x%x, des0=0x%x, des1=0x%x\n", priv->TxDescNow, (unsigned int)&priv->virtTxDescBaseAddr[priv->TxDescNow], txdesc->txdes0.ui, txdesc->txdes1.ui);
498 dbg_printk("Buffer phy address=0x%x, virt=0x%x\n", txdesc->txdes2.phyTxBufBaseAddr, (unsigned int)txdesc->txdes2.virtTxBufBaseAddr);
499 dbg_printk("TxDescNow-1=%d, address=0x%x, des0=0x%x\n", (priv->TxDescNow-1)&TX_DESC_NUM_MASK, (unsigned int)&priv->virtTxDescBaseAddr[(priv->TxDescNow-1)&TX_DESC_NUM_MASK], priv->virtTxDescBaseAddr[(priv->TxDescNow-1)&TX_DESC_NUM_MASK].txdes0.ui);
500 #endif
501 txnow++;
502 txnow &= TX_DESC_NUM_MASK;
503 priv->TxDescNow = txnow;
504 dev->trans_start = jiffies;
505 priv->stats.tx_packets++;
506 priv->stats.tx_bytes += len;
508 xmit_final:
509 spin_unlock(&priv->txlock);
510 dev_kfree_skb_any(skb);
512 return 0;
515 static int mcpu_mac_open(struct net_device *dev)
517 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
518 unsigned long flags;
520 dbg_printk("mcpu_mac_open test01\n");
522 save_flags(flags);
523 cli();
524 #ifdef USE_SCHEDULE_WORK
525 spin_lock(&priv->rxlock);
526 #endif
527 spin_lock(&priv->txlock);
528 mcpu_mac_reset(dev);
529 mcpu_mac_set_mac_address(dev->base_addr+MAC_MADR_REG_OFFSET, dev->dev_addr);
530 mcpu_mac_setup_desc_ring(dev);
531 mcpu_mac_enable(dev);
532 spin_unlock(&priv->txlock);
533 #ifdef USE_SCHEDULE_WORK
534 spin_unlock(&priv->rxlock);
535 #endif
536 restore_flags(flags);
537 netif_start_queue(dev);
538 dbg_printk("IMR=0x%x, MACCR=0x%x\n", inl(dev->base_addr+IMR_REG_OFFSET), inl(dev->base_addr+MACCR_REG_OFFSET));
539 #ifdef MCPU_MAC_DEBUG
541 unsigned char macaddr[6];
542 int i;
543 mcpu_mac_get_mac_address(dev->base_addr+MAC_MADR_REG_OFFSET, macaddr);
544 printk("Get MAC address = ");
545 for ( i=0; i<6; i++ )
546 printk("%02X ", macaddr[i]);
547 printk("\n");
549 #endif
551 return 0;
554 static int mcpu_mac_stop(struct net_device *dev)
556 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
557 unsigned long flags;
559 dbg_printk("mcpu_mac_stop test01\n");
560 netif_stop_queue(dev);
561 save_flags(flags);
562 cli();
563 #ifdef USE_SCHEDULE_WORK
564 spin_lock(&priv->rxlock);
565 #endif
566 spin_lock(&priv->txlock);
567 outl(0, dev->base_addr+IMR_REG_OFFSET); // disable all interrupt
568 outl(0, dev->base_addr+MACCR_REG_OFFSET); // disable all function
569 spin_unlock(&priv->txlock);
570 #ifdef USE_SCHEDULE_WORK
571 spin_unlock(&priv->rxlock);
572 #endif
573 restore_flags(flags);
575 return 0;
578 static struct net_device_stats *mcpu_mac_get_stats(struct net_device *dev)
580 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
582 dbg_printk("mcpu_mac_get_stats test01\n");
583 #if 0
585 unsigned int base=dev->base_addr;
586 int desc=priv->RxDescNow;
587 dbg_printk("RxDescNow=%d, desc phy=0x%x, virt=0x%x, buf phy=0x%x, virt=0x%x\n", desc, priv->phyRxDescBaseAddr+(desc*sizeof(rx_desc_t)), (unsigned int)&priv->virtRxDescBaseAddr[desc], priv->virtRxDescBaseAddr[desc].rxdes2.phyRxBufBaseAddr, (unsigned int)priv->virtRxDescBaseAddr[desc].rxdes2.virtRxBufBaseAddr);
588 dbg_printk("Now Rx desc des0=0x%x, des1=0x%x\n", priv->virtRxDescBaseAddr[desc].rxdes0.ui, priv->virtRxDescBaseAddr[desc].rxdes1.ui);
589 desc++;
590 desc &= RX_DESC_NUM_MASK;
591 dbg_printk("Next RxDescNow=%d, desc phy=0x%x, virt=0x%x, buf phy=0x%x, virt=0x%x\n", desc, priv->phyRxDescBaseAddr+(desc*sizeof(rx_desc_t)), (unsigned int)&priv->virtRxDescBaseAddr[desc], priv->virtRxDescBaseAddr[desc].rxdes2.phyRxBufBaseAddr, (unsigned int)priv->virtRxDescBaseAddr[desc].rxdes2.virtRxBufBaseAddr);
592 dbg_printk("Next Now Rx desc des0=0x%x, des1=0x%x\n", priv->virtRxDescBaseAddr[desc].rxdes0.ui, priv->virtRxDescBaseAddr[desc].rxdes1.ui);
593 printk("TX_MCOL_TX_SCOL register = 0x%x\n", inl(base+TX_MCOL_TX_SCOL_REG_OFFSET));
594 printk("RPF_AEP register = 0x%x\n", inl(base+RPF_AEP_REG_OFFSET));
595 printk("XM_PG register = 0x%x\n", inl(base+XM_PG_REG_OFFSET));
596 printk("RUNT_CNT_TLCC register = 0x%x\n", inl(base+RUNT_CNT_TLCC_REG_OFFSET));
597 printk("CRCER_CNT_FTL_CNT register = 0x%x\n", inl(base+CRCER_CNT_FTL_CNT_REG_OFFSET));
598 printk("RLC_RCC register = 0x%x\n", inl(base+RLC_RCC_REG_OFFSET));
599 printk("BROC register = 0x%x\n", inl(base+BROC_REG_OFFSET));
600 printk("MUCLA register = 0x%x\n", inl(base+MULCA_REG_OFFSET));
601 printk("RP register = 0x%x\n", inl(base+RP_REG_OFFSET));
602 printk("XP register = 0x%x\n", inl(base+XP_REG_OFFSET));
604 #endif
606 return &priv->stats;
610 static irqreturn_t mcpu_mac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
612 struct net_device *dev=(struct net_device *)dev_id;
613 unsigned int ists;
614 #ifdef USE_SCHEDULE_WORK
615 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
616 #endif
619 //dbg_printk("mcpu_mac_interrupt test01\n");
620 ists = inl(dev->base_addr+ISR_REG_OFFSET);
621 if ( ists & RPKT_FINISH ) {
622 #ifdef USE_SCHEDULE_WORK
623 schedule_work(&priv->rqueue);
624 #else
625 mcpu_mac_recv((void *)dev);
626 #endif
627 } else {
628 #ifdef MCPU_MAC_DEBUG
629 if ( ists & NORXBUF ) {
630 printk("Receiver no Rx buffer interrupt\n");
631 outl(inl(dev->base_addr+IMR_REG_OFFSET)&~NORXBUF_M, dev->base_addr+IMR_REG_OFFSET);
632 //return IRQ_HANDLED;
634 if ( ists & AHB_ERR ) {
635 printk("Receiver AHB error interrupt.\n");
636 //return IRQ_HANDLED;
638 #endif
639 //return IRQ_NONE;
642 return IRQ_HANDLED;
645 static int mcpu_mac_init(struct net_device *dev)
647 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
649 dbg_printk("mcpu_mac_init test01\n");
651 // first initialize the private variable to zero
652 memset((void *)priv, 0, sizeof(mcpu_mac_priv_t));
653 spin_lock_init(&priv->txlock);
655 #ifdef USE_SCHEDULE_WORK
657 //#if 1 // add by Victor Yu. 07-04-2005
658 spin_lock_init(&priv->rxlock);
659 INIT_WORK(&priv->rqueue, &mcpu_mac_recv, (void *)dev);
660 #endif
662 // allocate the descriptor and buffer memory
663 priv->virtTxDescBaseAddr = (tx_desc_t *)dma_alloc_coherent(NULL, sizeof(tx_desc_t)*TX_DESC_NUM, (dma_addr_t *)&priv->phyTxDescBaseAddr, GFP_DMA|GFP_KERNEL);
664 if ( priv->virtTxDescBaseAddr == NULL || (priv->phyTxDescBaseAddr & 0x0f) ) {
665 dbg_printk("Allocate the Tx descriptor memory fail !\n");
666 goto init_fail;
668 priv->virtRxDescBaseAddr = (rx_desc_t *)dma_alloc_coherent(NULL, sizeof(rx_desc_t)*RX_DESC_NUM, (dma_addr_t *)&priv->phyRxDescBaseAddr, GFP_DMA|GFP_KERNEL);
669 if ( priv->virtRxDescBaseAddr == NULL || (priv->phyRxDescBaseAddr & 0x0f) ) {
670 dbg_printk("Allocate the Rx descriptor memory fail !\n");
671 goto init_fail;
673 priv->virtTxBufBaseAddr = (unsigned char *)dma_alloc_coherent(NULL, TX_BUF_SIZE*TX_DESC_NUM, (dma_addr_t *)&priv->phyTxBufBaseAddr, GFP_DMA|GFP_KERNEL);
674 if ( priv->virtTxBufBaseAddr == NULL || (priv->phyTxBufBaseAddr & 0x03) ) {
675 dbg_printk("Allocate the Tx buffer memory fail !\n");
676 goto init_fail;
678 priv->virtRxBufBaseAddr = (unsigned char *)dma_alloc_coherent(NULL, RX_BUF_SIZE*RX_DESC_NUM, (dma_addr_t *)&priv->phyRxBufBaseAddr, GFP_DMA|GFP_KERNEL);
679 if ( priv->virtRxBufBaseAddr == NULL || (priv->phyRxBufBaseAddr & 0x03) ) {
680 dbg_printk("Allocate the Rx buffer memory fail !\n");
681 goto init_fail;
684 // setup the thernet basic
685 ether_setup(dev);
687 // reset the MAC
688 mcpu_mac_reset(dev);
689 mcpu_mac_setup_desc_ring(dev);
691 // we need to get the MAC address from the hardware and set to the device
692 #ifdef CONFIG_ARCH_CPE
693 dev->dev_addr[0] = 0x00;
694 dev->dev_addr[1] = 0x90;
695 dev->dev_addr[2] = 0xE8;
696 dev->dev_addr[3] = 0x72;
697 dev->dev_addr[4] = 0x20;
698 dev->dev_addr[5] = 0x01;
699 #endif // CONFIG_ARCH_CPE
700 #ifdef CONFIG_ARCH_MOXACPU
702 #include <linux/mtd/mtd.h>
703 struct mtd_info *mtd;
704 int len;
705 mtd = get_mtd_device(NULL, 0);
706 if ( priv == (void *)&mcpu_mac_priv ) { // LAN 1
707 if ( mtd == NULL ) {
708 #if 0 // mask by Victor Yu. 03-21-2006
709 dev->dev_addr[0] = 0x00;
710 dev->dev_addr[1] = 0x90;
711 dev->dev_addr[2] = 0xe8;
712 dev->dev_addr[3] = 0x10;
713 dev->dev_addr[4] = 0x02;
714 dev->dev_addr[5] = 0x40;
715 #else // add by Victor Yu. 021-2006
716 #if ( defined CONFIG_ARCH_W341 ) || ( defined CONFIG_ARCH_W345 ) || ( defined CONFIG_ARCH_W345_IMP1 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) || ( defined CONFIG_ARCH_W311 ) || ( defined CONFIG_ARCH_W321 ) || ( defined CONFIG_ARCH_W315 ) || ( defined CONFIG_ARCH_W325 )
717 memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x50), 6);
718 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
719 memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x56), 6);
721 #endif
723 #endif
724 } else {
725 #if ( defined CONFIG_ARCH_W341 ) || ( defined CONFIG_ARCH_W345 ) || ( defined CONFIG_ARCH_W345_IMP1 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) || ( defined CONFIG_ARCH_W311 ) || ( defined CONFIG_ARCH_W321 ) || ( defined CONFIG_ARCH_W315 ) || ( defined CONFIG_ARCH_W325 )
727 mtd->read(mtd, 0x50, 6, &len, dev->dev_addr);
728 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
729 mtd->read(mtd, 0x56, 6, &len, dev->dev_addr);
731 #endif
734 } else { // LAN2
735 if ( mtd == NULL ) {
736 #if 0 // mask by Victor Yu. 03-21-2006
737 dev->dev_addr[0] = 0x00;
738 dev->dev_addr[1] = 0x90;
739 dev->dev_addr[2] = 0xe8;
740 dev->dev_addr[3] = 0x10;
741 dev->dev_addr[4] = 0x02;
742 dev->dev_addr[5] = 0x41;
743 #else // add by Victor Yu. 03-21-2006
745 #if ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
746 memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x56), 6);
747 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
748 memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x50), 6);
749 #endif
751 #endif
753 } else {
754 #if ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
755 mtd->read(mtd, 0x56, 6, &len, dev->dev_addr);
756 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
757 mtd->read(mtd, 0x50, 6, &len, dev->dev_addr);
758 #endif
762 #endif // CONFIG_ARCH_MOXACPU
764 // setup the low lever interrupt for Moxa CPU
765 #include <asm/arch/cpe_int.h>
766 cpe_int_set_irq(dev->irq, LEVEL, H_ACTIVE);
767 if ( request_irq(dev->irq, &mcpu_mac_interrupt, SA_INTERRUPT, dev->name, dev) ) {
768 dbg_printk("Request interrupt service fail !\n");
769 goto init_fail;
772 return 0;
774 init_fail:
775 mcpu_mac_free_memory(dev);
776 return -ENOMEM;
779 #if 1 // Add by Jared 12-04-2008
781 #include <linux/ethtool.h>
782 #include <linux/mii.h>
784 #define PHY_CNTL_REG 0x00
785 #define PHY_STATUS_REG 0x01
786 #define PHY_ID_REG1 0x02
787 #define PHY_ID_REG2 0x03
788 #define PHY_ANA_REG 0x04
789 #define PHY_ANLPAR_REG 0x05
790 #define PHY_ANE_REG 0x06
791 #define PHY_ECNTL_REG1 0x10
792 #define PHY_QPDS_REG 0x11
793 #define PHY_10BOP_REG 0x12
794 #define PHY_ECNTL_REG2 0x13
795 /* PHY Status register */
796 #define AN_COMPLETE 0x0020
797 #define Link_Status 0x0004
798 //FTMAC100 register definition => 90/94: PHY register
799 #define FTMAC100_REG_PHY_WRITE 0x08000000
800 #define FTMAC100_REG_PHY_READ 0x04000000
802 static DECLARE_MUTEX(miiAccessMutex);
804 int flib_FTMAC100_PHY_Read_Waiting(struct net_device *dev) {
805 u32 wResult;
806 unsigned long t;
808 for(t = jiffies;;) {
809 if((jiffies - t) > (HZ/100) ) {
810 printk("<1>%s[%d]timeout\n",__FUNCTION__,__LINE__);
811 return (-1);
813 wResult = inl(dev->base_addr+PHYCR_REG_OFFSET);
814 if( (wResult & FTMAC100_REG_PHY_READ) == 0 )
815 break;
817 return 0;
820 int flib_FTMAC100_PHY_Write_Waiting(struct net_device *dev) {
821 u32 wResult;
822 unsigned long t;
824 for(t = jiffies;;) {
825 if((jiffies - t) > (HZ/100) ) {
826 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
827 return (-1);
829 wResult = inl(dev->base_addr+PHYCR_REG_OFFSET);
830 if( (wResult & FTMAC100_REG_PHY_WRITE) == 0 )
831 break;
833 return 0;
836 u32 PhyMiiReadRtn (struct net_device *dev, u8 phyAddr, u8 phyReg, u16 *value) {
837 u32 dwTemp;
839 dwTemp= (phyAddr<<16) | ((phyReg & 0x1f) << 21) | FTMAC100_REG_PHY_READ;
840 outl(dwTemp, dev->base_addr + PHYCR_REG_OFFSET);
842 if(flib_FTMAC100_PHY_Read_Waiting(dev) != 0){
843 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
844 return (-1);
847 *value = inw(dev->base_addr + PHYCR_REG_OFFSET);
849 return 0;
852 u32 PhyMiiWriteRtn (struct net_device *dev, u8 phyAddr, u8 phyReg, u16 value) {
853 u32 dwTemp, miiTimeout;
855 dwTemp = (phyAddr<<16) | ((phyReg & 0x1f) << 21) | FTMAC100_REG_PHY_WRITE;
856 outl(value, dev->base_addr + PHYWDATA_REG_OFFSET);
857 udelay(10) ;
859 if(flib_FTMAC100_PHY_Write_Waiting(dev) != 0){
860 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
861 return (-1);
864 for(miiTimeout=10; miiTimeout>0; miiTimeout-- ) {
865 set_current_state(TASK_INTERRUPTIBLE);
866 schedule_timeout( (1*HZ)/1000 );
869 outl(dwTemp, dev->base_addr + PHYCR_REG_OFFSET);
871 if(flib_FTMAC100_PHY_Read_Waiting(dev) != 0){
872 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
873 return (-2);
876 for(miiTimeout=10; miiTimeout>0; miiTimeout-- ) {
877 set_current_state(TASK_INTERRUPTIBLE);
878 schedule_timeout( (1*HZ)/1000 );
881 return 0;
884 #include <linux/ethtool.h>
885 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
887 u32 dwTemp;
888 int ethcmd, res = 0;
890 if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
891 return -EFAULT;
893 switch (ethcmd) {
894 case ETHTOOL_GLINK: {
895 struct ethtool_value edata = {ETHTOOL_GLINK};
897 dwTemp= (1<<16) | ((PHY_STATUS_REG & 0x1f) << 21) | FTMAC100_REG_PHY_READ;
898 outl(dwTemp, dev->base_addr + PHYCR_REG_OFFSET);
899 if(flib_FTMAC100_PHY_Read_Waiting(dev) != 0){
900 res = -1;
902 dwTemp = inw(dev->base_addr + PHYCR_REG_OFFSET);
903 #if 0
904 printk("%s[%d]ETHTOOL_GLINK 0x%x-",__FUNCTION__,__LINE__, dwTemp) ;
906 dwTemp= (1<<16) | ((PHY_STATUS_REG & 0x1f) << 21) | FTMAC100_REG_PHY_READ;
907 outl(dwTemp, dev->base_addr + PHYCR_REG_OFFSET);
908 if(flib_FTMAC100_PHY_Read_Waiting(dev) != 0){
909 res = -1;
911 dwTemp = inw(dev->base_addr + PHYCR_REG_OFFSET);
912 printk("%s[%d]ETHTOOL_GLINK 0x%x-",__FUNCTION__,__LINE__, dwTemp) ;
913 #endif
914 if ( (dwTemp & Link_Status) == Link_Status)
915 edata.data= 1;
916 else
917 edata.data= 0;
919 if (copy_to_user( useraddr, &edata, sizeof(edata)))
920 res= -EFAULT;
922 return res;
925 default:
926 return -EOPNOTSUPP;
930 static int mcpu_do_dev_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
932 struct mii_ioctl_data *data = (struct mii_ioctl_data *) & req->ifr_data;
933 int res=0;
935 switch (cmd)
937 /* Get address of MII PHY in use */
938 case SIOCGMIIPHY:
939 case SIOCDEVPRIVATE:
940 #ifdef ONE_MII_Interface
941 if(port){
942 data->phy_id = 0x2;
943 }else{
944 data->phy_id = 0x10;
946 #else
947 data->phy_id = 1;
948 #endif
949 break;
950 /* Read MII PHY register */
951 case SIOCGMIIREG:
952 case SIOCDEVPRIVATE+1:
953 down (&miiAccessMutex); /* lock the MII register access mutex */
954 if ((res = PhyMiiReadRtn (dev, data->phy_id, data->reg_num, &data->val_out)))
956 printk("Error reading MII reg %d on phy %d\n",
957 data->reg_num, data->phy_id);
958 res = -1;
960 up (&miiAccessMutex); /* release the MII register access mutex */
961 break;
962 /* Write MII PHY register */
963 case SIOCSMIIREG:
964 case SIOCDEVPRIVATE+2:
965 down (&miiAccessMutex); /* lock the MII register access mutex */
966 if ((res = PhyMiiWriteRtn (dev, data->phy_id, data->reg_num, data->val_in)))
968 printk("Error writing MII reg %d on phy %d\n",
969 data->reg_num, data->phy_id);
970 res = -1;
972 up (&miiAccessMutex); /* release the MII register access mutex */
973 break;
974 case SIOCETHTOOL:
975 return netdev_ethtool_ioctl(dev, req->ifr_data);
976 default:
977 res = -EOPNOTSUPP;
980 return res;
983 #endif // end of add by Jared 12-04-2008
985 static struct net_device mcpu_mac_dev = {
986 #ifdef CONFIG_ARCH_MOXACPU
988 #if ( defined CONFIG_ARCH_W341 ) || ( defined CONFIG_ARCH_W345 ) || ( defined CONFIG_ARCH_W345_IMP1 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) || ( defined CONFIG_ARCH_W311 ) || ( defined CONFIG_ARCH_W321 ) || ( defined CONFIG_ARCH_W315 ) || ( defined CONFIG_ARCH_W325 )
989 .name = "eth0",
990 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
991 .name = "eth1",
992 #endif
994 #endif
995 .base_addr = IO_ADDRESS(CPE_FTMAC_BASE),
996 .irq = IRQ_MAC,
997 .init = &mcpu_mac_init,
998 .get_stats = &mcpu_mac_get_stats,
999 .open = &mcpu_mac_open,
1000 .stop = &mcpu_mac_stop,
1001 .hard_start_xmit= &mcpu_mac_hard_start_xmit,
1002 .priv = (void *)&mcpu_mac_priv,
1003 .tx_timeout = &mcpu_mac_tx_timeout,
1004 #ifdef HAVE_MULTICAST
1005 .set_multicast_list = &mcpu_mac_set_multicast_list,
1006 #endif
1007 #if 1 // Add by Jared 12-04-2008
1008 .do_ioctl = mcpu_do_dev_ioctl,
1009 #endif // end of add by Jared 12-04-2008
1012 #ifdef CONFIG_ARCH_MOXACPU
1015 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
1016 static struct net_device mcpu_mac_dev2 = {
1017 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
1018 .name = "eth0",
1019 #elif ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
1020 .name = "eth1",
1021 #endif
1022 .base_addr = IO_ADDRESS(CPE_FTMAC2_BASE),
1023 .irq = IRQ_MAC2,
1024 .init = &mcpu_mac_init,
1025 .get_stats = &mcpu_mac_get_stats,
1026 .open = &mcpu_mac_open,
1027 .stop = &mcpu_mac_stop,
1028 .hard_start_xmit= &mcpu_mac_hard_start_xmit,
1029 .priv = (void *)&mcpu_mac_priv2,
1030 .tx_timeout = &mcpu_mac_tx_timeout,
1031 #ifdef HAVE_MULTICAST
1032 .set_multicast_list = &mcpu_mac_set_multicast_list,
1033 #endif
1034 #if 1 // Add by Jared 12-04-2008
1035 .do_ioctl = mcpu_do_dev_ioctl,
1036 #endif // end of add by Jared 12-04-2008
1038 #endif
1040 #endif // CONFIG_ARCH_MOXACPU
1042 static int __init mcpu_mac_init_module(void)
1044 int ret;
1045 printk("Moxa CPU Ethernet Device Driver Version 1.0 load ");
1046 ret = register_netdev(&mcpu_mac_dev);
1047 if ( ret ) {
1048 printk("fail !\n");
1049 return ret;
1052 #ifdef CONFIG_ARCH_MOXACPU
1055 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
1057 ret = register_netdev(&mcpu_mac_dev2);
1058 if ( ret ) {
1059 mcpu_mac_free_memory(&mcpu_mac_dev);
1060 free_irq(mcpu_mac_dev.irq, &mcpu_mac_dev);
1061 unregister_netdev(&mcpu_mac_dev);
1062 printk("fail !\n");
1063 return ret;
1065 #endif
1068 #endif // CONFIG_ARCH_MOXACPU
1070 printk("OK.\n");
1072 return 0;
1075 static void __exit mcpu_mac_cleanup_module(void)
1077 printk("Moxa CPU Ethernet Device Driver unload.\n");
1078 mcpu_mac_free_memory(&mcpu_mac_dev);
1079 free_irq(mcpu_mac_dev.irq, &mcpu_mac_dev);
1080 unregister_netdev(&mcpu_mac_dev);
1082 #ifdef CONFIG_ARCH_MOXACPU
1084 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )|| ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
1085 mcpu_mac_free_memory(&mcpu_mac_dev2);
1086 free_irq(mcpu_mac_dev2.irq, &mcpu_mac_dev2);
1087 unregister_netdev(&mcpu_mac_dev2);
1088 #endif
1090 #endif // CONFIG_ARCH_MOXACPU
1093 module_init(mcpu_mac_init_module);
1094 module_exit(mcpu_mac_cleanup_module);