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.
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>
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>
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
46 #if (defined CONFIG_ARCH_UC_7112_LX_PLUS_LITON)
47 #define CONFIG_ARCH_UC_7112_LX_PLUS
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 !
65 #if RX_BUF_SIZE >= RXBUF_SIZE_MAX
66 #error Moxa CPU ethernet device driver Rx buffer size too large !
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
;
76 #endif // CONFIG_ARCH_MOXACPU
80 static int crc32( char * s
, int length
)
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
++ ) {
94 for ( perBit
= 0; perBit
< 8; perBit
++ ) {
95 crc_value
= (crc_value
>>1)^
96 (((crc_value
^c
)&0x01)?poly
:0);
103 static void mcpu_mac_setmulticast(unsigned int ioaddr
, int count
, struct dev_mc_list
* addrs
)
105 struct dev_mc_list
*cur_addr
;
108 for (cur_addr
= addrs
; cur_addr
!=NULL
; cur_addr
= cur_addr
->next
) {
109 if ( !( *cur_addr
->dmi_addr
& 1 ) )
111 crc_val
= crc32( cur_addr
->dmi_addr
, 6 );
112 crc_val
= (crc_val
>>26)&0x3f; // ยจรบ MSB 6 bit
114 outl(inl(ioaddr
+MATH1_REG_OFFSET
) | (1UL<<(crc_val
-32)), ioaddr
+MATH1_REG_OFFSET
);
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
;
127 #ifdef USE_SCHEDULE_WORK
128 spin_lock(&priv
->rxlock
);
130 spin_lock(&priv
->txlock
);
132 if ( dev
->flags
& IFF_PROMISC
)
133 priv
->maccr
|= RCV_ALL
;
135 priv
->maccr
&= ~RCV_ALL
;
137 if ( dev
->flags
& IFF_ALLMULTI
)
138 priv
->maccr
|= RX_MULTIPKT
;
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
);
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
);
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
;
173 *(unsigned char *)pd
= *(unsigned char *)ps
;
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
;
186 #if 1 // add by Victor Yu. 07-04-2005
188 int rxnow
=priv
->RxDescNow
;
190 #ifndef USE_SCHEDULE_WORK
191 int loops
=RX_DESC_NUM
;
192 #endif // USE_SCHEDULE_WORK
194 dbg_printk("mcpu_mac_recv test01\n");
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
);
204 #ifdef USE_SCHEDULE_WORK
205 spin_lock(&priv
->rxlock
);
206 #endif // USE_SCHEDULE_WORK
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
) {
215 #ifdef USE_SCHEDULE_WORK
216 spin_unlock(&priv
->rxlock
);
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
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
) ) {
235 if ( ui
& (RX_ERR
|CRC_ERR
|FTL
|RUNT
|RX_ODD_NB
) ) {
238 dbg_printk("Ethernet receive packet error !\n");
239 priv
->stats
.rx_dropped
++;
240 priv
->stats
.rx_errors
++;
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
247 if ( len
> RX_BUF_SIZE
)
250 skb
= dev_alloc_skb(len
+2);
252 dbg_printk("Allocate memory fail !\n");
253 priv
->stats
.rx_dropped
++;
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
);
265 skb
->protocol
= eth_type_trans(skb
, dev
);
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");
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
;
284 rxnow
&= RX_DESC_NUM_MASK
;
285 priv
->RxDescNow
= rxnow
;
287 #ifdef USE_SCHEDULE_WORK
289 #else // USE_SCHEDULE_WORK
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
;
322 unsigned char *virtbuf
;
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
);
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
));
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
;
371 ((mcpu_mac_priv_t
*)dev
->priv
)->maccr
= RX_BROADPKT
| ENRX_IN_HALFTX
| CRC_APD
;
375 static void mcpu_mac_set_mac_address(unsigned int base
, unsigned char *macaddr
)
379 val
= (((u32
)macaddr
[0] << 8) &0xff00) | ((u32
)macaddr
[1] & 0xff);
381 val
= (((u32
)macaddr
[2]<<24) & 0xff000000) |
382 (((u32
)macaddr
[3]<<16) & 0x00ff0000) |
383 (((u32
)macaddr
[4]<<8) & 0x0000ff00) |
384 (((u32
)macaddr
[5]) & 0x000000ff);
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
)
394 macaddr
[0] = (val
>> 8) & 0xff;
395 macaddr
[1] = val
& 0xff;
397 macaddr
[2] = (val
>> 24) & 0xff;
398 macaddr
[3] = (val
>> 16) & 0xff;
399 macaddr
[4] = (val
>> 8) & 0xff;
400 macaddr
[5] = val
& 0xff;
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
);
415 outl(RPKT_FINISH_M
, base
+IMR_REG_OFFSET
);
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
;
426 dbg_printk("mcpu_mac_tx_timeout test01\n");
429 #ifdef USE_SCHEDULE_WORK
430 spin_lock(&priv
->rxlock
);
432 spin_lock(&priv
->txlock
);
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
);
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
;
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
++;
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
;
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
);
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
);
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
;
495 outl(0xffffffff, dev
->base_addr
+TXPD_REG_OFFSET
); // start to send packet
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
);
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
;
509 spin_unlock(&priv
->txlock
);
510 dev_kfree_skb_any(skb
);
515 static int mcpu_mac_open(struct net_device
*dev
)
517 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
520 dbg_printk("mcpu_mac_open test01\n");
524 #ifdef USE_SCHEDULE_WORK
525 spin_lock(&priv
->rxlock
);
527 spin_lock(&priv
->txlock
);
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
);
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];
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
]);
554 static int mcpu_mac_stop(struct net_device
*dev
)
556 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
559 dbg_printk("mcpu_mac_stop test01\n");
560 netif_stop_queue(dev
);
563 #ifdef USE_SCHEDULE_WORK
564 spin_lock(&priv
->rxlock
);
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
);
573 restore_flags(flags
);
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");
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
);
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
));
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
;
614 #ifdef USE_SCHEDULE_WORK
615 mcpu_mac_priv_t
*priv
=(mcpu_mac_priv_t
*)dev
->priv
;
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
);
625 mcpu_mac_recv((void *)dev
);
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;
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
);
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");
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");
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");
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");
684 // setup the thernet basic
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
;
705 mtd
= get_mtd_device(NULL
, 0);
706 if ( priv
== (void *)&mcpu_mac_priv
) { // LAN 1
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);
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
);
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);
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
);
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");
775 mcpu_mac_free_memory(dev
);
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
) {
809 if((jiffies
- t
) > (HZ
/100) ) {
810 printk("<1>%s[%d]timeout\n",__FUNCTION__
,__LINE__
);
813 wResult
= inl(dev
->base_addr
+PHYCR_REG_OFFSET
);
814 if( (wResult
& FTMAC100_REG_PHY_READ
) == 0 )
820 int flib_FTMAC100_PHY_Write_Waiting(struct net_device
*dev
) {
825 if((jiffies
- t
) > (HZ
/100) ) {
826 printk("<1>%s[%d]\n",__FUNCTION__
,__LINE__
);
829 wResult
= inl(dev
->base_addr
+PHYCR_REG_OFFSET
);
830 if( (wResult
& FTMAC100_REG_PHY_WRITE
) == 0 )
836 u32
PhyMiiReadRtn (struct net_device
*dev
, u8 phyAddr
, u8 phyReg
, u16
*value
) {
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__
);
847 *value
= inw(dev
->base_addr
+ PHYCR_REG_OFFSET
);
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
);
859 if(flib_FTMAC100_PHY_Write_Waiting(dev
) != 0){
860 printk("<1>%s[%d]\n",__FUNCTION__
,__LINE__
);
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__
);
876 for(miiTimeout
=10; miiTimeout
>0; miiTimeout
-- ) {
877 set_current_state(TASK_INTERRUPTIBLE
);
878 schedule_timeout( (1*HZ
)/1000 );
884 #include <linux/ethtool.h>
885 static int netdev_ethtool_ioctl(struct net_device
*dev
, void *useraddr
)
890 if (copy_from_user (ðcmd
, useraddr
, sizeof (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){
902 dwTemp
= inw(dev
->base_addr
+ PHYCR_REG_OFFSET
);
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){
911 dwTemp
= inw(dev
->base_addr
+ PHYCR_REG_OFFSET
);
912 printk("%s[%d]ETHTOOL_GLINK 0x%x-",__FUNCTION__
,__LINE__
, dwTemp
) ;
914 if ( (dwTemp
& Link_Status
) == Link_Status
)
919 if (copy_to_user( useraddr
, &edata
, sizeof(edata
)))
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
;
937 /* Get address of MII PHY in use */
940 #ifdef ONE_MII_Interface
950 /* Read MII PHY register */
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
);
960 up (&miiAccessMutex
); /* release the MII register access mutex */
962 /* Write MII PHY register */
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
);
972 up (&miiAccessMutex
); /* release the MII register access mutex */
975 return netdev_ethtool_ioctl(dev
, req
->ifr_data
);
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 )
990 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
995 .base_addr
= IO_ADDRESS(CPE_FTMAC_BASE
),
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
,
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 )
1019 #elif ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
1022 .base_addr
= IO_ADDRESS(CPE_FTMAC2_BASE
),
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
,
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
1040 #endif // CONFIG_ARCH_MOXACPU
1042 static int __init
mcpu_mac_init_module(void)
1045 printk("Moxa CPU Ethernet Device Driver Version 1.0 load ");
1046 ret
= register_netdev(&mcpu_mac_dev
);
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
);
1059 mcpu_mac_free_memory(&mcpu_mac_dev
);
1060 free_irq(mcpu_mac_dev
.irq
, &mcpu_mac_dev
);
1061 unregister_netdev(&mcpu_mac_dev
);
1068 #endif // CONFIG_ARCH_MOXACPU
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
);
1090 #endif // CONFIG_ARCH_MOXACPU
1093 module_init(mcpu_mac_init_module
);
1094 module_exit(mcpu_mac_cleanup_module
);