3 * This program is the Moxa CPU ethernet device driver.
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 * 02-09-2007 Victor Yu. Porting to kernel 2.6.19.
11 #if 1 // add by Victor Yu. 02-09-2007
12 #include <linux/version.h>
14 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) // add by Victor Yu. 02-09-2007
15 #include <linux/config.h>
17 #include <asm/arch/moxa.h>
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/types.h>
21 #include <linux/fcntl.h>
22 #include <linux/interrupt.h>
23 #include <linux/ioport.h>
25 #include <linux/slab.h>
26 #include <linux/string.h>
27 #include <linux/errno.h>
28 #include <linux/init.h>
29 #include <linux/netdevice.h>
30 #include <linux/etherdevice.h>
31 #include <linux/spinlock.h>
32 #include <linux/skbuff.h>
33 #include <linux/device.h>
34 #include <linux/dma-mapping.h>
35 #include <linux/delay.h>
36 #include <linux/workqueue.h>
37 #include <asm/uaccess.h>
38 #include <asm/system.h>
39 #include <asm/bitops.h>
45 //#define MCPU_MAC_DEBUG
47 //#define USE_SCHEDULE_WORK
48 /* Jimmy_chen@moxa.com.tw: get mac from flash */
49 #define ETH1_OFFSET 0x50
50 #define ETH2_OFFSET 0x56
53 #define dbg_printk(x...) printk(x)
54 #else // MCPU_MAC_DEBUG
55 #define dbg_printk(x...)
56 #endif // MCPU_MAC_DEBUG
58 #define TX_DESC_NUM 64
59 #define TX_DESC_NUM_MASK (TX_DESC_NUM-1)
60 #define RX_DESC_NUM 64
61 #define RX_DESC_NUM_MASK (RX_DESC_NUM-1)
62 #define TX_BUF_SIZE 1600
63 #define RX_BUF_SIZE 1600
64 #if TX_BUF_SIZE >= TXBUF_SIZE_MAX
65 #error Moxa CPU ethernet device driver Tx buffer size too large !
67 #if RX_BUF_SIZE >= RXBUF_SIZE_MAX
68 #error Moxa CPU ethernet device driver Rx buffer size too large !
71 static mcpu_mac_priv_t mcpu_mac_priv
;
72 #ifdef CONFIG_ARCH_MOXART
73 #if !defined(CONFIG_ARCH_W325_EC) && !defined(CONFIG_ARCH_EM1220_APIT)
74 static mcpu_mac_priv_t mcpu_mac_priv2
;
76 #endif // CONFIG_ARCH_MOXART
79 static int crc32( char * s
, int length
)
84 /* crc polynomial for Ethernet */
85 const unsigned long poly
=0xedb88320;
86 /* crc value - preinitialized to all 1's */
87 unsigned long crc_value
=0xffffffff;
89 for ( perByte
= 0; perByte
< length
; perByte
++ ) {
93 for ( perBit
= 0; perBit
< 8; perBit
++ ) {
94 crc_value
= (crc_value
>>1)^
95 (((crc_value
^c
)&0x01)?poly
:0);
102 static void mcpu_mac_setmulticast(unsigned int ioaddr
, int count
, struct dev_mc_list
* addrs
)
104 struct dev_mc_list
*cur_addr
;
107 for (cur_addr
= addrs
; cur_addr
!=NULL
; cur_addr
= cur_addr
->next
) {
108 if ( !( *cur_addr
->dmi_addr
& 1 ) )
110 crc_val
= crc32( cur_addr
->dmi_addr
, 6 );
111 crc_val
= (crc_val
>>26)&0x3f; // ยจรบ MSB 6 bit
113 outl(inl(ioaddr
+MATH1_REG_OFFSET
) | (1UL<<(crc_val
-32)), ioaddr
+MATH1_REG_OFFSET
);
115 outl(inl(ioaddr
+MATH0_REG_OFFSET
) | (1UL<<crc_val
), ioaddr
+MATH0_REG_OFFSET
);
119 static void mcpu_mac_set_multicast_list(struct net_device
*dev
)
121 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
124 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
125 local_irq_save(flags
);
129 #endif // LINUX_VERSION_CODE
130 #ifdef USE_SCHEDULE_WORK
131 spin_lock(&priv
->rxlock
);
133 spin_lock(&priv
->txlock
);
135 if ( dev
->flags
& IFF_PROMISC
)
136 priv
->maccr
|= RCV_ALL
;
138 priv
->maccr
&= ~RCV_ALL
;
140 if ( dev
->flags
& IFF_ALLMULTI
)
141 priv
->maccr
|= RX_MULTIPKT
;
143 priv
->maccr
&= ~RX_MULTIPKT
;
145 if ( dev
->mc_count
) {
146 priv
->maccr
|= HT_MULTI_EN
;
147 mcpu_mac_setmulticast(dev
->base_addr
, dev
->mc_count
, dev
->mc_list
);
149 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
);
157 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
158 local_irq_restore(flags
);
160 restore_flags(flags
);
161 #endif // LINUX_VERSION_CODE
163 #endif // HAVE_MULTICAST
165 #if 1 // add by Victor Yu. 07-04-2005
166 static void mywordcopy(void *dest
, void *source
, int len
)
168 unsigned short *pd
=(unsigned short *)dest
;
169 unsigned short *ps
=(unsigned short *)source
;
177 *(unsigned char *)pd
= *(unsigned char *)ps
;
181 static void mcpu_mac_recv(void *ptr
)
183 struct net_device
*dev
=(struct net_device
*)ptr
;
184 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
189 #if 1 // add by Victor Yu. 07-04-2005
191 int rxnow
=priv
->RxDescNow
;
193 #ifndef USE_SCHEDULE_WORK
194 int loops
=RX_DESC_NUM
;
195 #endif // USE_SCHEDULE_WORK
197 dbg_printk("mcpu_mac_recv test01\n");
199 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
);
200 dbg_printk("Now Rx desc des0=0x%x, des1=0x%x\n", priv
->virtRxDescBaseAddr
[priv
->RxDescNow
].rxdes0
.ui
, priv
->virtRxDescBaseAddr
[priv
->RxDescNow
].rxdes1
.ui
);
202 #ifdef USE_SCHEDULE_WORK
203 spin_lock(&priv
->rxlock
);
204 #endif // USE_SCHEDULE_WORK
206 rxdesc
= &priv
->virtRxDescBaseAddr
[rxnow
];
207 #if 0 // mask by Victor Yu. 07-04-2005
208 if ( rxdesc
->rxdes0
.ubit
.RxDMAOwn
) {
209 #else // add by Victor Yu. 07-04-2005
210 ui
= rxdesc
->rxdes0
.ui
;
211 if ( ui
& RXDMA_OWN
) {
213 #ifdef USE_SCHEDULE_WORK
214 spin_unlock(&priv
->rxlock
);
216 #ifdef MCPU_MAC_DEBUG
217 if ( loops
== RX_DESC_NUM
)
218 printk("Bad receive packet !\n");
219 #endif // MCPU_MAC_DEBUG
220 #endif // USE_SCHEDULE_WORK
223 #if 0 // mask by Victor Yu. 07-04-2005
224 if ( rxdesc
->rxdes0
.ubit
.RxErr
||
225 rxdesc
->rxdes0
.ubit
.CRCErr
||
226 rxdesc
->rxdes0
.ubit
.Ftl
||
227 rxdesc
->rxdes0
.ubit
.Runt
||
228 rxdesc
->rxdes0
.ubit
.RxOddNb
) {
229 #else // add by Victor Yu. 07-04-2005
230 if ( ui
& (RX_ERR
|CRC_ERR
|FTL
|RUNT
|RX_ODD_NB
) ) {
232 dbg_printk("Ethernet receive packet error !\n");
233 priv
->stats
.rx_dropped
++;
234 priv
->stats
.rx_errors
++;
237 #if 0 // mask by Victor Yu. 07-04-2005
238 len
= rxdesc
->rxdes0
.ubit
.RecvFrameLen
> RX_BUF_SIZE
? RX_BUF_SIZE
: rxdesc
->rxdes0
.ubit
.RecvFrameLen
;
239 #else // add by Victor Yu. 07-04-2005
241 if ( len
> RX_BUF_SIZE
)
244 skb
= dev_alloc_skb(len
+2);
246 dbg_printk("Allocate memory fail !\n");
247 priv
->stats
.rx_dropped
++;
252 data
= skb_put(skb
, len
);
253 dbg_printk("receive data pointer = 0x%x\n", (unsigned long)data
);
254 #if 0 // mask by Victor Yu. 07-04-2005
255 memcpy(data
, rxdesc
->rxdes2
.virtRxBufBaseAddr
, len
);
256 #else // add by Victor Yu. 07-04-2005
257 mywordcopy((void *)data
, (void *)rxdesc
->rxdes2
.virtRxBufBaseAddr
, len
);
259 skb
->protocol
= eth_type_trans(skb
, dev
);
261 /* Jimmy_chen@moxa.com.tw :This is need by bonding driver to replace miion */
262 dev
->last_rx
= jiffies
;
263 priv
->stats
.rx_packets
++;
264 priv
->stats
.rx_bytes
+= len
;
265 if ( ui
& MULTICAST_RXDES0
)
266 priv
->stats
.multicast
++;
267 dbg_printk("Receive a good packet.\n");
270 #if 0 // mask by Victor Yu. 07-04-2005
271 rxdesc
->rxdes0
.ui
= 0;
272 rxdesc
->rxdes0
.ubit
.RxDMAOwn
= 1;
273 rxdesc
->rxdes1
.ubit
.RxBufSize
= RX_BUF_SIZE
;
274 #else // add by Victor Yu. 07-04-2005
275 rxdesc
->rxdes0
.ui
= RXDMA_OWN
;
278 rxnow
&= RX_DESC_NUM_MASK
;
279 priv
->RxDescNow
= rxnow
;
281 #ifdef USE_SCHEDULE_WORK
283 #else // USE_SCHEDULE_WORK
286 #endif // USE_SCHEDULE_WORK
288 #ifdef USE_SCHEDULE_WORK
289 spin_unlock(&priv
->rxlock
);
290 #endif // USE_SCHEDULE_WORK
293 static void mcpu_mac_free_memory(struct net_device
*dev
)
295 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
297 if ( priv
->virtTxDescBaseAddr
) {
298 kfree(priv
->virtTxDescBaseAddr
);
299 priv
->virtTxDescBaseAddr
= NULL
;
301 if ( priv
->virtRxDescBaseAddr
) {
302 kfree(priv
->virtRxDescBaseAddr
);
303 priv
->virtRxDescBaseAddr
= NULL
;
305 if ( priv
->virtTxBufBaseAddr
) {
306 kfree(priv
->virtTxBufBaseAddr
);
307 priv
->virtTxBufBaseAddr
= NULL
;
309 if ( priv
->virtRxBufBaseAddr
) {
310 kfree(priv
->virtRxBufBaseAddr
);
311 priv
->virtRxBufBaseAddr
= NULL
;
315 static void mcpu_mac_setup_desc_ring(struct net_device
*dev
)
317 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
321 unsigned char *virtbuf
;
324 virtbuf
= priv
->virtTxBufBaseAddr
;
325 phybuf
= priv
->phyTxBufBaseAddr
;
326 for ( i
=0; i
<TX_DESC_NUM
; i
++, virtbuf
+=TX_BUF_SIZE
, phybuf
+=TX_BUF_SIZE
) {
327 txdesc
= &priv
->virtTxDescBaseAddr
[i
];
328 memset(txdesc
, 0, sizeof(tx_desc_t
));
329 txdesc
->txdes2
.phyTxBufBaseAddr
= phybuf
;
330 txdesc
->txdes2
.virtTxBufBaseAddr
= virtbuf
;
332 priv
->virtTxDescBaseAddr
[TX_DESC_NUM
-1].txdes1
.ubit
.Edotr
= 1;
334 virtbuf
= priv
->virtRxBufBaseAddr
;
335 phybuf
= priv
->phyRxBufBaseAddr
;
336 for ( i
=0; i
<RX_DESC_NUM
; i
++, virtbuf
+=RX_BUF_SIZE
, phybuf
+=RX_BUF_SIZE
) {
337 rxdesc
= &priv
->virtRxDescBaseAddr
[i
];
338 memset(rxdesc
, 0, sizeof(rx_desc_t
));
339 rxdesc
->rxdes0
.ubit
.RxDMAOwn
= 1;
340 rxdesc
->rxdes1
.ubit
.RxBufSize
= RX_BUF_SIZE
;
341 rxdesc
->rxdes2
.phyRxBufBaseAddr
= phybuf
;
342 rxdesc
->rxdes2
.virtRxBufBaseAddr
= virtbuf
;
344 priv
->virtRxDescBaseAddr
[RX_DESC_NUM
-1].rxdes1
.ubit
.Edorr
= 1;
345 //dbg_printk("First Rx desc des0=0x%x, des1=%x\n", priv->virtRxDescBaseAddr[0].rxdes0.ui, priv->virtRxDescBaseAddr[0].rxdes1.ui);
347 priv
->TxDescNow
= priv
->RxDescNow
= 0;
349 // reset the MAC controler Tx/Rx desciptor base address
350 outl(priv
->phyTxDescBaseAddr
, dev
->base_addr
+TXR_BADR_REG_OFFSET
);
351 outl(priv
->phyRxDescBaseAddr
, dev
->base_addr
+RXR_BADR_REG_OFFSET
);
353 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
);
354 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
));
358 static void mcpu_mac_reset(struct net_device
*dev
)
360 unsigned int reg
=dev
->base_addr
+MACCR_REG_OFFSET
;
362 outl(SW_RST
, reg
); // software reset
363 while ( inl(reg
) & SW_RST
) mdelay(10);
364 // maybe we need to disable the all interrupt
365 outl(0, dev
->base_addr
+IMR_REG_OFFSET
);
366 #if 0 // mask by Victor Yu. 02-09-2007
367 ((mcpu_mac_priv_t
*)dev
->priv
)->maccr
= RX_BROADPKT
| FULLDUP
| CRC_APD
;
368 #else // to support 10M hub
369 ((mcpu_mac_priv_t
*)dev
->priv
)->maccr
= RX_BROADPKT
| FULLDUP
| CRC_APD
| ENRX_IN_HALFTX
;
373 static void mcpu_mac_set_mac_address(unsigned int base
, unsigned char *macaddr
)
377 val
= (((u32
)macaddr
[0] << 8) &0xff00) | ((u32
)macaddr
[1] & 0xff);
379 val
= (((u32
)macaddr
[2]<<24) & 0xff000000) |
380 (((u32
)macaddr
[3]<<16) & 0x00ff0000) |
381 (((u32
)macaddr
[4]<<8) & 0x0000ff00) |
382 (((u32
)macaddr
[5]) & 0x000000ff);
386 #ifdef MCPU_MAC_DEBUG // add by Victor Yu. 03-14-2006
387 static void mcpu_mac_get_mac_address(unsigned int base
, unsigned char *macaddr
)
392 macaddr
[0] = (val
>> 8) & 0xff;
393 macaddr
[1] = val
& 0xff;
395 macaddr
[2] = (val
>> 24) & 0xff;
396 macaddr
[3] = (val
>> 16) & 0xff;
397 macaddr
[4] = (val
>> 8) & 0xff;
398 macaddr
[5] = val
& 0xff;
402 static void mcpu_mac_enable(struct net_device
*dev
)
404 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
405 unsigned int base
=dev
->base_addr
;
407 outl(0x00001010, base
+ITC_REG_OFFSET
);
408 outl(0x00000001, base
+APTC_REG_OFFSET
);
409 outl(0x00000390, base
+DBLAC_REG_OFFSET
);
410 #ifdef MCPU_MAC_DEBUG
411 outl(RPKT_FINISH_M
|NORXBUF_M
|AHB_ERR_M
, base
+IMR_REG_OFFSET
);
413 outl(RPKT_FINISH_M
, base
+IMR_REG_OFFSET
);
415 priv
->maccr
|= (RCV_EN
| XMT_EN
| RDMA_EN
| XDMA_EN
);
416 outl(priv
->maccr
, base
+MACCR_REG_OFFSET
);
419 static void mcpu_mac_tx_timeout(struct net_device
*dev
)
421 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
424 dbg_printk("mcpu_mac_tx_timeout test01\n");
425 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
426 local_irq_save(flags
);
430 #endif // LINUX_VERSION_CODE
431 #ifdef USE_SCHEDULE_WORK
432 spin_lock(&priv
->rxlock
);
434 spin_lock(&priv
->txlock
);
436 mcpu_mac_set_mac_address(dev
->base_addr
+MAC_MADR_REG_OFFSET
, dev
->dev_addr
);
437 mcpu_mac_setup_desc_ring(dev
);
438 mcpu_mac_enable(dev
);
439 spin_unlock(&priv
->txlock
);
440 #ifdef USE_SCHEDULE_WORK
441 spin_unlock(&priv
->rxlock
);
443 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
444 local_irq_restore(flags
);
446 restore_flags(flags
);
447 #endif // LINUX_VERSION_CODE
448 netif_wake_queue(dev
);
449 dev
->trans_start
= jiffies
;
452 #include <linux/ethtool.h>
453 static int netdev_ethtool_ioctl(struct net_device
*dev
, void __user
*useraddr
)
456 static struct ethtool_value edata
= {ETHTOOL_GLINK
};
458 if (copy_from_user(ðcmd
, useraddr
, sizeof(ethcmd
)))
463 case ETHTOOL_GLINK
: {
464 u32 phycrw_value
= 0 ;
465 u16 phycrr_value
= 0 ;
467 /* Jimmy_chen@moxa.com.tw : RTL8201CP 15 pages */
468 /* Here is bug not fix yet, why i need do twice? */
469 phycrw_value
= (1<<16)|((PHY_STATUS_REG
&0x1f)<<21)|FTMAC100_REG_PHY_READ
;
470 outl(phycrw_value
,dev
->base_addr
+PHYCR_REG_OFFSET
) ;
472 phycrr_value
= inw(dev
->base_addr
+PHYCR_REG_OFFSET
);
473 printk("ETHTOOL_GLINK 0x%x-",phycrr_value
) ;
475 phycrw_value
= (1<<16)|((PHY_STATUS_REG
&0x1f)<<21)|FTMAC100_REG_PHY_READ
;
476 outl(phycrw_value
,dev
->base_addr
+PHYCR_REG_OFFSET
) ;
478 phycrr_value
= inw(dev
->base_addr
+PHYCR_REG_OFFSET
);
479 printk("0x%x\n",phycrr_value
) ;
480 /* Jimmy_chen@moxa.com.tw : emulate mii_link_ok function */
481 if((phycrr_value
&Link_Status
)==Link_Status
)
485 if (copy_to_user(useraddr
, &edata
, sizeof(edata
)))
493 static int mcpu_mac_iotcl(struct net_device
*dev
, struct ifreq
*rq
, int cmd
)
495 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
496 struct mii_ioctl_data
*data
= (struct mii_ioctl_data
*)rq
;
500 return netdev_ethtool_ioctl(dev
, rq
->ifr_data
);
502 value = (1<<16)|(PHY_STATUS_REG&0x1f<<21)|FTMAC100_REG_PHY_READ ;
503 outl(value,dev->base_addr+PHYCR_REG_OFFSET) ;
505 value = inl(dev->base_addr+PHYCR_REG_OFFSET);
512 static int mcpu_mac_hard_start_xmit(struct sk_buff
*skb
, struct net_device
*dev
)
514 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
517 int txnow
=priv
->TxDescNow
;
519 dbg_printk("mcpu_mac_hard_start_xmit test01\n");
520 spin_lock(&priv
->txlock
);
522 // first check the Tx buffer is enough or not
523 txdesc
= &priv
->virtTxDescBaseAddr
[txnow
];
524 if ( txdesc
->txdes0
.ubit
.TxDMAOwn
) {
525 dbg_printk("No Tx space to transmit the packet !\n");
526 priv
->stats
.tx_dropped
++;
531 #if 0 // mask by Victor Yu. 07-04-2005
532 len
= skb
->len
< ETH_ZLEN
? ETH_ZLEN
: skb
->len
;
533 len
= len
> TX_BUF_SIZE
? TX_BUF_SIZE
: len
;
534 #else // add by Victor Yu. 07-04-2005
535 len
= skb
->len
> TX_BUF_SIZE
? TX_BUF_SIZE
: skb
->len
;
537 #if 0 // mask by Victor Yu. 07-04-2005
538 memcpy(txdesc
->txdes2
.virtTxBufBaseAddr
, skb
->data
, len
);
539 #else // add by Victor Yu. 07-04-2005
540 mywordcopy((void *)txdesc
->txdes2
.virtTxBufBaseAddr
, (void *)skb
->data
, len
);
542 dbg_printk("transmit data pointer = 0x%x\n", (unsigned long)skb
->data
);
543 #if 1 // add by Victor Yu. 07-04-2005
544 if ( skb
->len
< ETH_ZLEN
) {
545 memset(&txdesc
->txdes2
.virtTxBufBaseAddr
[skb
->len
], 0, ETH_ZLEN
-skb
->len
);
549 txdesc
->txdes1
.ubit
.Lts
= 1;
550 txdesc
->txdes1
.ubit
.Fts
= 1;
551 txdesc
->txdes1
.ubit
.Tx2fic
= 0;
552 txdesc
->txdes1
.ubit
.Txic
= 0;
553 txdesc
->txdes1
.ubit
.TxBufSize
= len
;
554 #if 0 // mask by Victor Yu. 07-04-2005
555 txdesc
->txdes0
.ui
= 0;
556 txdesc
->txdes0
.ubit
.TxDMAOwn
= 1;
557 #else // add by Victor Yu. 07-04-2005
558 txdesc
->txdes0
.ui
= TXDMA_OWN
;
561 outl(0xffffffff, dev
->base_addr
+TXPD_REG_OFFSET
); // start to send packet
563 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
);
564 dbg_printk("Buffer phy address=0x%x, virt=0x%x\n", txdesc
->txdes2
.phyTxBufBaseAddr
, (unsigned int)txdesc
->txdes2
.virtTxBufBaseAddr
);
565 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
);
568 txnow
&= TX_DESC_NUM_MASK
;
569 priv
->TxDescNow
= txnow
;
570 dev
->trans_start
= jiffies
;
571 priv
->stats
.tx_packets
++;
572 priv
->stats
.tx_bytes
+= len
;
575 spin_unlock(&priv
->txlock
);
576 dev_kfree_skb_any(skb
);
581 static int mcpu_mac_open(struct net_device
*dev
)
583 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
586 dbg_printk("mcpu_mac_open test01\n");
588 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
589 local_irq_save(flags
);
593 #endif // LINUX_VERSION_CODE
594 #ifdef USE_SCHEDULE_WORK
595 spin_lock(&priv
->rxlock
);
597 spin_lock(&priv
->txlock
);
599 mcpu_mac_set_mac_address(dev
->base_addr
+MAC_MADR_REG_OFFSET
, dev
->dev_addr
);
600 mcpu_mac_setup_desc_ring(dev
);
601 mcpu_mac_enable(dev
);
602 spin_unlock(&priv
->txlock
);
603 #ifdef USE_SCHEDULE_WORK
604 spin_unlock(&priv
->rxlock
);
606 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
607 local_irq_restore(flags
);
609 restore_flags(flags
);
610 #endif // LINUX_VERSION_CODE
611 netif_start_queue(dev
);
612 dbg_printk("IMR=0x%x, MACCR=0x%x\n", inl(dev
->base_addr
+IMR_REG_OFFSET
), inl(dev
->base_addr
+MACCR_REG_OFFSET
));
613 #ifdef MCPU_MAC_DEBUG
615 unsigned char macaddr
[6];
617 mcpu_mac_get_mac_address(dev
->base_addr
+MAC_MADR_REG_OFFSET
, macaddr
);
618 printk("Get MAC address = ");
619 for ( i
=0; i
<6; i
++ )
620 printk("%02X ", macaddr
[i
]);
628 static int mcpu_mac_stop(struct net_device
*dev
)
630 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
633 dbg_printk("mcpu_mac_stop test01\n");
634 netif_stop_queue(dev
);
635 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
636 local_irq_save(flags
);
640 #endif // LINUX_VERSION_CODE
641 #ifdef USE_SCHEDULE_WORK
642 spin_lock(&priv
->rxlock
);
644 spin_lock(&priv
->txlock
);
645 outl(0, dev
->base_addr
+IMR_REG_OFFSET
); // disable all interrupt
646 outl(0, dev
->base_addr
+MACCR_REG_OFFSET
); // disable all function
647 spin_unlock(&priv
->txlock
);
648 #ifdef USE_SCHEDULE_WORK
649 spin_unlock(&priv
->rxlock
);
651 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
652 local_irq_restore(flags
);
654 restore_flags(flags
);
655 #endif // LINUX_VERSION_CODE
660 static struct net_device_stats
*mcpu_mac_get_stats(struct net_device
*dev
)
662 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
664 dbg_printk("mcpu_mac_get_stats test01\n");
667 unsigned int base
=dev
->base_addr
;
668 int desc
=priv
->RxDescNow
;
669 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
);
670 dbg_printk("Now Rx desc des0=0x%x, des1=0x%x\n", priv
->virtRxDescBaseAddr
[desc
].rxdes0
.ui
, priv
->virtRxDescBaseAddr
[desc
].rxdes1
.ui
);
672 desc
&= RX_DESC_NUM_MASK
;
673 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
);
674 dbg_printk("Next Now Rx desc des0=0x%x, des1=0x%x\n", priv
->virtRxDescBaseAddr
[desc
].rxdes0
.ui
, priv
->virtRxDescBaseAddr
[desc
].rxdes1
.ui
);
675 printk("TX_MCOL_TX_SCOL register = 0x%x\n", inl(base
+TX_MCOL_TX_SCOL_REG_OFFSET
));
676 printk("RPF_AEP register = 0x%x\n", inl(base
+RPF_AEP_REG_OFFSET
));
677 printk("XM_PG register = 0x%x\n", inl(base
+XM_PG_REG_OFFSET
));
678 printk("RUNT_CNT_TLCC register = 0x%x\n", inl(base
+RUNT_CNT_TLCC_REG_OFFSET
));
679 printk("CRCER_CNT_FTL_CNT register = 0x%x\n", inl(base
+CRCER_CNT_FTL_CNT_REG_OFFSET
));
680 printk("RLC_RCC register = 0x%x\n", inl(base
+RLC_RCC_REG_OFFSET
));
681 printk("BROC register = 0x%x\n", inl(base
+BROC_REG_OFFSET
));
682 printk("MUCLA register = 0x%x\n", inl(base
+MULCA_REG_OFFSET
));
683 printk("RP register = 0x%x\n", inl(base
+RP_REG_OFFSET
));
684 printk("XP register = 0x%x\n", inl(base
+XP_REG_OFFSET
));
691 static irqreturn_t
mcpu_mac_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
693 struct net_device
*dev
=(struct net_device
*)dev_id
;
695 #ifdef USE_SCHEDULE_WORK
696 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
699 //dbg_printk("mcpu_mac_interrupt test01\n");
700 ists
= inl(dev
->base_addr
+ISR_REG_OFFSET
);
701 if ( ists
& RPKT_FINISH
) {
702 #ifdef USE_SCHEDULE_WORK
703 schedule_work(&priv
->rqueue
);
705 mcpu_mac_recv((void *)dev
);
708 #ifdef MCPU_MAC_DEBUG
709 if ( ists
& NORXBUF
) {
710 printk("Receiver no Rx buffer interrupt\n");
711 outl(inl(dev
->base_addr
+IMR_REG_OFFSET
)&~NORXBUF_M
, dev
->base_addr
+IMR_REG_OFFSET
);
712 //return IRQ_HANDLED;
714 if ( ists
& AHB_ERR
) {
715 printk("Receiver AHB error interrupt.\n");
716 //return IRQ_HANDLED;
725 static int mcpu_mac_init(struct net_device
*dev
)
727 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
729 dbg_printk("mcpu_mac_init test01\n");
731 // first initialize the private variable to zero
732 memset((void *)priv
, 0, sizeof(mcpu_mac_priv_t
));
733 spin_lock_init(&priv
->txlock
);
734 spin_lock_init(&priv
->rxlock
);
735 #if 1 // add by Victor Yu. 07-04-2005
736 INIT_WORK(&priv
->rqueue
, &mcpu_mac_recv
, (void *)dev
);
739 // allocate the descriptor and buffer memory
740 priv
->virtTxDescBaseAddr
= (tx_desc_t
*)kmalloc(sizeof(tx_desc_t
)*TX_DESC_NUM
, GFP_KERNEL
);
741 if ( priv
->virtTxDescBaseAddr
== NULL
|| ((unsigned int)priv
->virtTxDescBaseAddr
& 0x0f) ) {
742 dbg_printk("Allocate the Tx descriptor memory fail !\n");
745 priv
->phyTxDescBaseAddr
= (unsigned int)priv
->virtTxDescBaseAddr
;
747 priv
->virtRxDescBaseAddr
= (rx_desc_t
*)kmalloc(sizeof(rx_desc_t
)*RX_DESC_NUM
, GFP_KERNEL
);
748 if ( priv
->virtRxDescBaseAddr
== NULL
|| ((unsigned int)priv
->virtRxDescBaseAddr
& 0x0f) ) {
749 dbg_printk("Allocate the Rx descriptor memory fail !\n");
752 priv
->phyRxDescBaseAddr
= (unsigned int)priv
->virtRxDescBaseAddr
;
754 priv
->virtTxBufBaseAddr
= (unsigned char *)kmalloc(TX_BUF_SIZE
*TX_DESC_NUM
, GFP_KERNEL
);
755 if ( priv
->virtTxBufBaseAddr
== NULL
|| ((unsigned int)priv
->virtTxBufBaseAddr
& 0x03) ) {
756 dbg_printk("Allocate the Tx buffer memory fail !\n");
759 priv
->phyTxBufBaseAddr
= (unsigned int)priv
->virtTxBufBaseAddr
;
761 priv
->virtRxBufBaseAddr
= (unsigned char *)kmalloc(RX_BUF_SIZE
*RX_DESC_NUM
, GFP_KERNEL
);
762 if ( priv
->virtRxBufBaseAddr
== NULL
|| ((unsigned int)priv
->virtRxBufBaseAddr
& 0x03) ) {
763 dbg_printk("Allocate the Rx buffer memory fail !\n");
766 priv
->phyRxBufBaseAddr
= (unsigned int)priv
->virtRxBufBaseAddr
;
768 // setup the thernet basic
773 mcpu_mac_setup_desc_ring(dev
);
775 // we need to get the MAC address from the hardware and set to the device
777 dev
->dev_addr
[0] = 0x00;
778 dev
->dev_addr
[1] = 0x90;
779 dev
->dev_addr
[2] = 0xE8;
780 dev
->dev_addr
[3] = 0x92;
781 dev
->dev_addr
[4] = 0x20;
782 if ( priv
== (void *)&mcpu_mac_priv
) { // LAN 1
783 dev
->dev_addr
[5] = 0x70;
785 dev
->dev_addr
[5] = 0x71;
788 /* Jimmy_chen@moxa.com.tw : get mac from flash */
789 if ( priv
== (void *)&mcpu_mac_priv
) { // LAN 1
790 dev
->dev_addr
[0] = inb(CONFIG_FLASH_MEM_BASE
+ETH1_OFFSET
);
791 dev
->dev_addr
[1] = inb(CONFIG_FLASH_MEM_BASE
+ETH1_OFFSET
+1);
792 dev
->dev_addr
[2] = inb(CONFIG_FLASH_MEM_BASE
+ETH1_OFFSET
+2);
793 dev
->dev_addr
[3] = inb(CONFIG_FLASH_MEM_BASE
+ETH1_OFFSET
+3);
794 dev
->dev_addr
[4] = inb(CONFIG_FLASH_MEM_BASE
+ETH1_OFFSET
+4);
795 dev
->dev_addr
[5] = inb(CONFIG_FLASH_MEM_BASE
+ETH1_OFFSET
+5);
797 dev
->dev_addr
[0] = inb(CONFIG_FLASH_MEM_BASE
+ETH2_OFFSET
);
798 dev
->dev_addr
[1] = inb(CONFIG_FLASH_MEM_BASE
+ETH2_OFFSET
+1);
799 dev
->dev_addr
[2] = inb(CONFIG_FLASH_MEM_BASE
+ETH2_OFFSET
+2);
800 dev
->dev_addr
[3] = inb(CONFIG_FLASH_MEM_BASE
+ETH2_OFFSET
+3);
801 dev
->dev_addr
[4] = inb(CONFIG_FLASH_MEM_BASE
+ETH2_OFFSET
+4);
802 dev
->dev_addr
[5] = inb(CONFIG_FLASH_MEM_BASE
+ETH2_OFFSET
+5);
806 // setup the low lever interrupt for Moxa CPU
807 cpe_int_set_irq(dev
->irq
, LEVEL
, H_ACTIVE
);
808 if ( request_irq(dev
->irq
, &mcpu_mac_interrupt
, SA_INTERRUPT
, dev
->name
, dev
) ) {
809 dbg_printk("Request interrupt service fail !\n");
816 mcpu_mac_free_memory(dev
);
820 static struct net_device mcpu_mac_dev
= {
822 .base_addr
= IO_ADDRESS(CPE_FTMAC_BASE
),
824 .init
= &mcpu_mac_init
,
825 .get_stats
= &mcpu_mac_get_stats
,
826 .open
= &mcpu_mac_open
,
827 .stop
= &mcpu_mac_stop
,
828 .hard_start_xmit
= &mcpu_mac_hard_start_xmit
,
829 .priv
= (void *)&mcpu_mac_priv
,
830 .tx_timeout
= &mcpu_mac_tx_timeout
,
831 .do_ioctl
= &mcpu_mac_iotcl
,
832 #ifdef HAVE_MULTICAST
833 .set_multicast_list
= &mcpu_mac_set_multicast_list
,
837 #ifdef CONFIG_ARCH_MOXART
838 #if !defined(CONFIG_ARCH_W325_EC) && !defined(CONFIG_ARCH_EM1220_APIT)
839 static struct net_device mcpu_mac_dev2
= {
841 .base_addr
= IO_ADDRESS(CPE_FTMAC2_BASE
),
843 .init
= &mcpu_mac_init
,
844 .get_stats
= &mcpu_mac_get_stats
,
845 .open
= &mcpu_mac_open
,
846 .stop
= &mcpu_mac_stop
,
847 .hard_start_xmit
= &mcpu_mac_hard_start_xmit
,
848 .priv
= (void *)&mcpu_mac_priv2
,
849 .tx_timeout
= &mcpu_mac_tx_timeout
,
850 .do_ioctl
= &mcpu_mac_iotcl
,
851 #ifdef HAVE_MULTICAST
852 .set_multicast_list
= &mcpu_mac_set_multicast_list
,
853 #endif // HAVE_MULTICAST
856 #endif // CONFIG_ARCH_MOXART
858 static int __init
mcpu_mac_init_module(void)
862 printk("Moxa CPU Ethernet Device Driver Version 1.0 load ");
863 ret
= register_netdev(&mcpu_mac_dev
);
869 #ifdef CONFIG_ARCH_MOXART
870 #if !defined(CONFIG_ARCH_W325_EC) && !defined(CONFIG_ARCH_EM1220_APIT)
871 ret
= register_netdev(&mcpu_mac_dev2
);
873 mcpu_mac_free_memory(&mcpu_mac_dev
);
874 free_irq(mcpu_mac_dev
.irq
, &mcpu_mac_dev
);
875 unregister_netdev(&mcpu_mac_dev
);
880 #endif // CONFIG_ARCH_MOXART
887 static void __exit
mcpu_mac_cleanup_module(void)
889 printk("Moxa CPU Ethernet Device Driver unload.\n");
890 mcpu_mac_free_memory(&mcpu_mac_dev
);
891 free_irq(mcpu_mac_dev
.irq
, &mcpu_mac_dev
);
892 unregister_netdev(&mcpu_mac_dev
);
894 #ifdef CONFIG_ARCH_MOXART
895 #if !defined(CONFIG_ARCH_W325_EC) && !defined(CONFIG_ARCH_EM1220_APIT)
896 mcpu_mac_free_memory(&mcpu_mac_dev2
);
897 free_irq(mcpu_mac_dev2
.irq
, &mcpu_mac_dev2
);
898 unregister_netdev(&mcpu_mac_dev2
);
900 #endif // CONFIG_ARCH_MOXART
903 module_init(mcpu_mac_init_module
);
904 module_exit(mcpu_mac_cleanup_module
);