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
1
2 /*
3  * This program is the Moxa CPU ethernet device driver.
4  *
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  */
10
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"
38
39 //#define MCPU_MAC_DEBUG
40 //#define USE_SCHEDULE_WORK
41
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
45
46 #if (defined CONFIG_ARCH_UC_7112_LX_PLUS_LITON)
47 #define CONFIG_ARCH_UC_7112_LX_PLUS
48 #endif
49
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
55
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
68
69 static mcpu_mac_priv_t  mcpu_mac_priv;
70 #ifdef CONFIG_ARCH_MOXACPU
71
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
75
76 #endif  // CONFIG_ARCH_MOXACPU
77
78
79 #ifdef HAVE_MULTICAST
80 static int crc32( char * s, int length )
81 {
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;
89
90         for ( perByte = 0; perByte < length; perByte ++ ) {
91                 unsigned char   c;
92
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;
98                 }
99         }
100         return  crc_value;
101 }
102
103 static void mcpu_mac_setmulticast(unsigned int ioaddr, int count, struct dev_mc_list * addrs )
104 {
105         struct dev_mc_list      *cur_addr;
106         int                     crc_val;
107
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);
117         }
118 }
119
120 static void mcpu_mac_set_multicast_list(struct net_device *dev)
121 {
122         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
123         unsigned long           flags;
124
125         save_flags(flags);
126         cli();
127 #ifdef USE_SCHEDULE_WORK
128         spin_lock(&priv->rxlock);
129 #endif
130         spin_lock(&priv->txlock);
131
132         if ( dev->flags & IFF_PROMISC )
133                 priv->maccr |= RCV_ALL;
134         else
135                 priv->maccr &= ~RCV_ALL;
136
137         if ( dev->flags & IFF_ALLMULTI )
138                 priv->maccr |= RX_MULTIPKT;
139         else
140                 priv->maccr &= ~RX_MULTIPKT;
141
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;
149         }               
150
151         outl(priv->maccr, dev->base_addr+MACCR_REG_OFFSET);
152
153         spin_unlock(&priv->txlock);
154 #ifdef USE_SCHEDULE_WORK
155         spin_unlock(&priv->rxlock);
156 #endif
157         restore_flags(flags);
158 }
159 #endif  // HAVE_MULTICAST
160
161 #if 1   // add by Victor Yu. 07-04-2005
162 static void mywordcopy(void *dest, void *source, int len)
163 {
164         unsigned short  *pd=(unsigned short *)dest;
165         unsigned short  *ps=(unsigned short *)source;
166         int             wlen=len>>1;
167
168         while ( wlen > 0 ) {
169                 *pd++=*ps++;
170                 wlen--;
171         }
172         if ( len & 1 )
173                 *(unsigned char *)pd = *(unsigned char *)ps;
174 }
175 #endif  // 07-04-2005
176
177 static void mcpu_mac_recv(void *ptr)
178 {
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;
184
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
193
194         dbg_printk("mcpu_mac_recv test01\n");
195
196
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
201
202
203         
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;
224         }
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;
242         }
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;
255         }
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");
272
273
274
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;
286
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
293
294 #ifdef USE_SCHEDULE_WORK
295         spin_unlock(&priv->rxlock);
296 #endif  // USE_SCHEDULE_WORK
297
298
299 }
300
301
302 static void mcpu_mac_free_memory(struct net_device *dev)
303 {
304         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
305
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);
314 }
315
316 static void mcpu_mac_setup_desc_ring(struct net_device *dev)
317 {
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;
324
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;
332         }
333         priv->virtTxDescBaseAddr[TX_DESC_NUM-1].txdes1.ubit.Edotr = 1;
334         
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;
344         }
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);
347
348         priv->TxDescNow = priv->RxDescNow = 0;
349         
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
357 }
358
359 static void mcpu_mac_reset(struct net_device *dev)
360 {
361         unsigned int    reg=dev->base_addr+MACCR_REG_OFFSET;
362
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
373 }
374
375 static void mcpu_mac_set_mac_address(unsigned int base, unsigned char *macaddr)
376 {
377         unsigned int    val;
378
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);
386 }
387
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)
390 {
391         unsigned int    val;
392
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;
401 }
402 #endif
403
404 static void mcpu_mac_enable(struct net_device *dev)
405 {
406         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
407         unsigned int            base=dev->base_addr;
408
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);
419 }
420
421 static void mcpu_mac_tx_timeout(struct net_device *dev)
422 {
423         mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
424         unsigned long   flags;
425
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;
444 }
445
446 static int mcpu_mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
447 {
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;
452
453         dbg_printk("mcpu_mac_hard_start_xmit test01\n");
454         spin_lock(&priv->txlock);
455
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;
462         }
463
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;
481         }
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
494
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;
507
508 xmit_final:
509         spin_unlock(&priv->txlock);
510         dev_kfree_skb_any(skb);
511
512         return 0;
513 }
514
515 static int mcpu_mac_open(struct net_device *dev)
516 {
517         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
518         unsigned long           flags;
519
520         dbg_printk("mcpu_mac_open test01\n");
521
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
540         {
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");
548         }
549 #endif
550
551         return 0;
552 }
553
554 static int mcpu_mac_stop(struct net_device *dev)
555 {
556         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
557         unsigned long           flags;
558
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);
574
575         return 0;
576 }
577
578 static struct net_device_stats *mcpu_mac_get_stats(struct net_device *dev)
579 {
580         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
581
582         dbg_printk("mcpu_mac_get_stats test01\n");
583 #if 0
584         {
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));
603         }
604 #endif
605
606         return &priv->stats;
607 }
608
609
610 static irqreturn_t mcpu_mac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
611 {
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
617
618         
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;
633                 }
634                 if ( ists & AHB_ERR ) {
635                         printk("Receiver AHB error interrupt.\n");
636                         //return IRQ_HANDLED;
637                 }
638 #endif
639                 //return IRQ_NONE;
640         }
641
642         return IRQ_HANDLED;
643 }
644
645 static int mcpu_mac_init(struct net_device *dev)
646 {
647         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
648
649         dbg_printk("mcpu_mac_init test01\n");
650
651         // first initialize the private variable to zero 
652         memset((void *)priv, 0, sizeof(mcpu_mac_priv_t));
653         spin_lock_init(&priv->txlock);
654
655 #ifdef USE_SCHEDULE_WORK
656
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
661
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;
667         }
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;
672         }
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;
677         }
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;
682         }
683
684         // setup the thernet basic
685         ether_setup(dev);
686
687         // reset the MAC
688         mcpu_mac_reset(dev);
689         mcpu_mac_setup_desc_ring(dev);
690
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
701 {
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);
720         
721 #endif
722                         
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 )    
726                  
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);
730
731 #endif
732
733                 }
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
744
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
750
751 #endif
752
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
759                 }
760         }
761 }
762 #endif  // CONFIG_ARCH_MOXACPU
763
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;
770         }
771
772         return 0;
773
774 init_fail:
775         mcpu_mac_free_memory(dev);
776         return -ENOMEM;
777 }
778
779 #if 1  // Add by Jared 12-04-2008
780
781 #include <linux/ethtool.h>
782 #include <linux/mii.h>
783
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
801
802 static DECLARE_MUTEX(miiAccessMutex);
803
804 int flib_FTMAC100_PHY_Read_Waiting(struct net_device *dev) {
805         u32 wResult;
806         unsigned long t;
807
808         for(t = jiffies;;) {
809                 if((jiffies - t) > (HZ/100) ) {
810                         printk("<1>%s[%d]timeout\n",__FUNCTION__,__LINE__);
811                         return (-1);
812                 }
813                 wResult = inl(dev->base_addr+PHYCR_REG_OFFSET);
814                 if( (wResult & FTMAC100_REG_PHY_READ) == 0 )
815                         break;
816         }
817         return 0;
818 }
819
820 int flib_FTMAC100_PHY_Write_Waiting(struct net_device *dev) {
821         u32 wResult;
822         unsigned long t;
823
824         for(t = jiffies;;) {
825                 if((jiffies - t) > (HZ/100) ) {
826                         printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
827                         return (-1);
828                 }
829                 wResult = inl(dev->base_addr+PHYCR_REG_OFFSET);
830                 if( (wResult & FTMAC100_REG_PHY_WRITE) == 0 )
831                         break;
832         }
833         return 0;
834 }
835
836 u32 PhyMiiReadRtn (struct net_device *dev, u8 phyAddr, u8 phyReg, u16 *value) {
837         u32 dwTemp;
838
839         dwTemp= (phyAddr<<16) | ((phyReg & 0x1f) << 21) | FTMAC100_REG_PHY_READ;
840         outl(dwTemp, dev->base_addr + PHYCR_REG_OFFSET);
841
842         if(flib_FTMAC100_PHY_Read_Waiting(dev) != 0){
843                 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
844                 return (-1);
845         }
846
847         *value = inw(dev->base_addr + PHYCR_REG_OFFSET);
848
849         return 0;
850 }
851
852 u32 PhyMiiWriteRtn (struct net_device *dev,  u8 phyAddr, u8 phyReg, u16 value) {
853         u32 dwTemp, miiTimeout;
854
855         dwTemp = (phyAddr<<16) | ((phyReg & 0x1f) << 21) | FTMAC100_REG_PHY_WRITE;
856         outl(value, dev->base_addr + PHYWDATA_REG_OFFSET);
857         udelay(10) ;
858
859         if(flib_FTMAC100_PHY_Write_Waiting(dev) != 0){
860                 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
861                 return (-1);
862         }
863
864         for(miiTimeout=10; miiTimeout>0; miiTimeout-- ) {
865                 set_current_state(TASK_INTERRUPTIBLE);
866                 schedule_timeout( (1*HZ)/1000 );
867         }
868
869         outl(dwTemp, dev->base_addr + PHYCR_REG_OFFSET);
870
871         if(flib_FTMAC100_PHY_Read_Waiting(dev) != 0){
872                 printk("<1>%s[%d]\n",__FUNCTION__,__LINE__);
873                 return (-2);
874         }
875
876         for(miiTimeout=10; miiTimeout>0; miiTimeout-- ) {
877                 set_current_state(TASK_INTERRUPTIBLE);
878                 schedule_timeout( (1*HZ)/1000 );
879         }
880
881         return 0;
882 }
883
884 #include <linux/ethtool.h>
885 static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
886 {
887     u32 dwTemp;
888     int ethcmd, res = 0;
889
890     if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
891       return -EFAULT;
892
893     switch (ethcmd) {
894       case ETHTOOL_GLINK: {
895         struct ethtool_value edata = {ETHTOOL_GLINK};
896         
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;
901         }
902         dwTemp = inw(dev->base_addr + PHYCR_REG_OFFSET);
903 #if 0
904         printk("%s[%d]ETHTOOL_GLINK 0x%x-",__FUNCTION__,__LINE__, dwTemp) ;
905
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;
910         }
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;
918
919         if (copy_to_user( useraddr, &edata, sizeof(edata)))
920           res= -EFAULT;
921
922         return res;
923       }
924
925       default:
926         return -EOPNOTSUPP;
927     }
928 }
929
930 static int mcpu_do_dev_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
931 {
932         struct mii_ioctl_data *data = (struct mii_ioctl_data *) & req->ifr_data;
933         int res=0;
934
935         switch (cmd)
936         {
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;
945                         }
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)))
955             {
956                                 printk("Error reading MII reg %d on phy %d\n",
957                                         data->reg_num, data->phy_id);
958                                 res = -1;
959                         }
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)))
967             {
968                                 printk("Error writing MII reg %d on phy %d\n",
969                                         data->reg_num, data->phy_id);
970                                 res = -1;
971                         }
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;
978         }
979
980         return res;
981 }
982
983 #endif // end of add by Jared 12-04-2008
984
985 static struct net_device        mcpu_mac_dev = {
986 #ifdef CONFIG_ARCH_MOXACPU
987         
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
993
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
1010 };
1011
1012 #ifdef CONFIG_ARCH_MOXACPU
1013
1014
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
1037 };
1038 #endif
1039
1040 #endif  // CONFIG_ARCH_MOXACPU
1041
1042 static int __init mcpu_mac_init_module(void)
1043 {
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;
1050         }
1051
1052 #ifdef CONFIG_ARCH_MOXACPU
1053
1054
1055 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS )            
1056
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;
1064         }
1065 #endif
1066
1067
1068 #endif  // CONFIG_ARCH_MOXACPU
1069
1070         printk("OK.\n");
1071
1072         return 0;
1073 }
1074
1075 static void __exit mcpu_mac_cleanup_module(void)
1076 {
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);
1081
1082 #ifdef CONFIG_ARCH_MOXACPU
1083
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
1089
1090 #endif  // CONFIG_ARCH_MOXACPU
1091 }
1092
1093 module_init(mcpu_mac_init_module);
1094 module_exit(mcpu_mac_cleanup_module);