MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / net / arm / eth_moxa.c
blob20c6e4240bd99a2a4103a98197beea7a02a70c23
2 /*
3 * This program is the Moxa CPU ethernet device driver.
5 * History:
6 * Date Author Comment
7 * 06-15-2005 Victor Yu. Create it. Make it for Faraday demo board.
8 * 11-04-2005 Victor Yu. Modify it to support Moxa CPU demo board.
9 * 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>
13 #endif
14 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) // add by Victor Yu. 02-09-2007
15 #include <linux/config.h>
16 #endif
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>
24 #include <linux/in.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>
40 #include <asm/io.h>
41 #include <asm/irq.h>
42 #include <asm/dma.h>
43 #include "eth_moxa.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
52 #ifdef MCPU_MAC_DEBUG
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 !
66 #endif
67 #if RX_BUF_SIZE >= RXBUF_SIZE_MAX
68 #error Moxa CPU ethernet device driver Rx buffer size too large !
69 #endif
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;
75 #endif
76 #endif // CONFIG_ARCH_MOXART
78 #ifdef HAVE_MULTICAST
79 static int crc32( char * s, int length )
81 /* indices */
82 int perByte;
83 int perBit;
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 ++ ) {
90 unsigned char c;
92 c = *(s++);
93 for ( perBit = 0; perBit < 8; perBit++ ) {
94 crc_value = (crc_value>>1)^
95 (((crc_value^c)&0x01)?poly:0);
96 c >>= 1;
99 return crc_value;
102 static void mcpu_mac_setmulticast(unsigned int ioaddr, int count, struct dev_mc_list * addrs )
104 struct dev_mc_list *cur_addr;
105 int crc_val;
107 for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next ) {
108 if ( !( *cur_addr->dmi_addr & 1 ) )
109 continue;
110 crc_val = crc32( cur_addr->dmi_addr, 6 );
111 crc_val = (crc_val>>26)&0x3f; // ยจรบ MSB 6 bit
112 if (crc_val >= 32)
113 outl(inl(ioaddr+MATH1_REG_OFFSET) | (1UL<<(crc_val-32)), ioaddr+MATH1_REG_OFFSET);
114 else
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;
122 unsigned long flags;
124 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
125 local_irq_save(flags);
126 #else
127 save_flags(flags);
128 cli();
129 #endif // LINUX_VERSION_CODE
130 #ifdef USE_SCHEDULE_WORK
131 spin_lock(&priv->rxlock);
132 #endif
133 spin_lock(&priv->txlock);
135 if ( dev->flags & IFF_PROMISC )
136 priv->maccr |= RCV_ALL;
137 else
138 priv->maccr &= ~RCV_ALL;
140 if ( dev->flags & IFF_ALLMULTI )
141 priv->maccr |= RX_MULTIPKT;
142 else
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);
148 } else
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);
156 #endif
157 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
158 local_irq_restore(flags);
159 #else
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;
170 int wlen=len>>1;
172 while ( wlen > 0 ) {
173 *pd++=*ps++;
174 wlen--;
176 if ( len & 1 )
177 *(unsigned char *)pd = *(unsigned char *)ps;
179 #endif // 07-04-2005
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;
185 rx_desc_t *rxdesc;
186 int len;
187 struct sk_buff *skb;
188 unsigned char *data;
189 #if 1 // add by Victor Yu. 07-04-2005
190 unsigned int ui;
191 int rxnow=priv->RxDescNow;
192 #endif // 07-04-2005
193 #ifndef USE_SCHEDULE_WORK
194 int loops=RX_DESC_NUM;
195 #endif // USE_SCHEDULE_WORK
197 dbg_printk("mcpu_mac_recv test01\n");
198 #if 0
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);
201 #endif
202 #ifdef USE_SCHEDULE_WORK
203 spin_lock(&priv->rxlock);
204 #endif // USE_SCHEDULE_WORK
205 repeat_recv:
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 ) {
212 #endif // 07-04-2005
213 #ifdef USE_SCHEDULE_WORK
214 spin_unlock(&priv->rxlock);
215 #else
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
221 return;
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) ) {
231 #endif // 07-04-2005
232 dbg_printk("Ethernet receive packet error !\n");
233 priv->stats.rx_dropped++;
234 priv->stats.rx_errors++;
235 goto recv_finish;
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
240 len = ui & RFL_MASK;
241 if ( len > RX_BUF_SIZE )
242 len = RX_BUF_SIZE;
243 #endif // 07-04-2005
244 skb = dev_alloc_skb(len+2);
245 if ( skb == NULL ) {
246 dbg_printk("Allocate memory fail !\n");
247 priv->stats.rx_dropped++;
248 goto recv_finish;
250 skb_reserve(skb, 2);
251 skb->dev = dev;
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);
258 #endif // 07-04-2005
259 skb->protocol = eth_type_trans(skb, dev);
260 netif_rx(skb);
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");
269 recv_finish:
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;
276 #endif // 07-04-2005
277 rxnow++;
278 rxnow &= RX_DESC_NUM_MASK;
279 priv->RxDescNow = rxnow;
281 #ifdef USE_SCHEDULE_WORK
282 goto repeat_recv;
283 #else // USE_SCHEDULE_WORK
284 if ( loops-- > 0 )
285 goto repeat_recv;
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;
318 int i;
319 tx_desc_t *txdesc;
320 rx_desc_t *rxdesc;
321 unsigned char *virtbuf;
322 unsigned int phybuf;
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);
352 #if 0
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));
355 #endif
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;
370 #endif
373 static void mcpu_mac_set_mac_address(unsigned int base, unsigned char *macaddr)
375 unsigned int val;
377 val = (((u32)macaddr[0] << 8) &0xff00) | ((u32)macaddr[1] & 0xff);
378 outl(val, base);
379 val = (((u32)macaddr[2]<<24) & 0xff000000) |
380 (((u32)macaddr[3]<<16) & 0x00ff0000) |
381 (((u32)macaddr[4]<<8) & 0x0000ff00) |
382 (((u32)macaddr[5]) & 0x000000ff);
383 outl(val, base+4);
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)
389 unsigned int val;
391 val = inl(base);
392 macaddr[0] = (val >> 8) & 0xff;
393 macaddr[1] = val & 0xff;
394 val = inl(base+4);
395 macaddr[2] = (val >> 24) & 0xff;
396 macaddr[3] = (val >> 16) & 0xff;
397 macaddr[4] = (val >> 8) & 0xff;
398 macaddr[5] = val & 0xff;
400 #endif
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);
412 #else
413 outl(RPKT_FINISH_M, base+IMR_REG_OFFSET);
414 #endif
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;
422 unsigned long flags;
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);
427 #else
428 save_flags(flags);
429 cli();
430 #endif // LINUX_VERSION_CODE
431 #ifdef USE_SCHEDULE_WORK
432 spin_lock(&priv->rxlock);
433 #endif
434 spin_lock(&priv->txlock);
435 mcpu_mac_reset(dev);
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);
442 #endif
443 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
444 local_irq_restore(flags);
445 #else
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)
455 static u32 ethcmd;
456 static struct ethtool_value edata = {ETHTOOL_GLINK};
458 if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
459 return -EFAULT;
461 switch (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) ;
471 udelay(10) ;
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) ;
477 udelay(10) ;
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)
482 edata.data = 1 ;
483 else
484 edata.data = 0 ;
485 if (copy_to_user(useraddr, &edata, sizeof(edata)))
486 return -EFAULT;
487 return 0;
489 default:
490 return -EOPNOTSUPP;
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;
498 switch(cmd) {
499 case SIOCETHTOOL:
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) ;
504 udelay(10) ;
505 value = inl(dev->base_addr+PHYCR_REG_OFFSET);
506 return 0 ;
508 default:
509 return -EOPNOTSUPP;
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;
515 tx_desc_t *txdesc;
516 int len;
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++;
527 goto xmit_final;
530 // fill the data
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;
536 #endif
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);
541 #endif
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);
546 len = ETH_ZLEN;
548 #endif
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;
559 #endif
561 outl(0xffffffff, dev->base_addr+TXPD_REG_OFFSET); // start to send packet
562 #if 0
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);
566 #endif
567 txnow++;
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;
574 xmit_final:
575 spin_unlock(&priv->txlock);
576 dev_kfree_skb_any(skb);
578 return 0;
581 static int mcpu_mac_open(struct net_device *dev)
583 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
584 unsigned long flags;
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);
590 #else
591 save_flags(flags);
592 cli();
593 #endif // LINUX_VERSION_CODE
594 #ifdef USE_SCHEDULE_WORK
595 spin_lock(&priv->rxlock);
596 #endif
597 spin_lock(&priv->txlock);
598 mcpu_mac_reset(dev);
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);
605 #endif
606 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
607 local_irq_restore(flags);
608 #else
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];
616 int i;
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]);
621 printk("\n");
623 #endif
625 return 0;
628 static int mcpu_mac_stop(struct net_device *dev)
630 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
631 unsigned long flags;
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);
637 #else
638 save_flags(flags);
639 cli();
640 #endif // LINUX_VERSION_CODE
641 #ifdef USE_SCHEDULE_WORK
642 spin_lock(&priv->rxlock);
643 #endif
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);
650 #endif
651 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9) // add by Victor Yu. 02-09-2007
652 local_irq_restore(flags);
653 #else
654 restore_flags(flags);
655 #endif // LINUX_VERSION_CODE
657 return 0;
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");
665 #if 0
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);
671 desc++;
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));
686 #endif
688 return &priv->stats;
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;
694 unsigned int ists;
695 #ifdef USE_SCHEDULE_WORK
696 mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
697 #endif
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);
704 #else
705 mcpu_mac_recv((void *)dev);
706 #endif
707 } else {
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;
718 #endif
719 //return IRQ_NONE;
722 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);
737 #endif
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");
743 goto init_fail;
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");
750 goto init_fail;
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");
757 goto init_fail;
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");
764 goto init_fail;
766 priv->phyRxBufBaseAddr = (unsigned int)priv->virtRxBufBaseAddr;
768 // setup the thernet basic
769 ether_setup(dev);
771 // reset the MAC
772 mcpu_mac_reset(dev);
773 mcpu_mac_setup_desc_ring(dev);
775 // we need to get the MAC address from the hardware and set to the device
776 #if 0
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;
784 } else { // LAN2
785 dev->dev_addr[5] = 0x71;
787 #else
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);
796 } else { // LAN2
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);
804 #endif
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");
810 goto init_fail;
813 return 0;
815 init_fail:
816 mcpu_mac_free_memory(dev);
817 return -ENOMEM;
820 static struct net_device mcpu_mac_dev = {
821 .name = "eth0",
822 .base_addr = IO_ADDRESS(CPE_FTMAC_BASE),
823 .irq = IRQ_MAC,
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,
834 #endif
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 = {
840 .name = "eth1",
841 .base_addr = IO_ADDRESS(CPE_FTMAC2_BASE),
842 .irq = IRQ_MAC2,
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
855 #endif
856 #endif // CONFIG_ARCH_MOXART
858 static int __init mcpu_mac_init_module(void)
860 int ret;
862 printk("Moxa CPU Ethernet Device Driver Version 1.0 load ");
863 ret = register_netdev(&mcpu_mac_dev);
864 if ( ret ) {
865 printk("fail !\n");
866 return ret;
869 #ifdef CONFIG_ARCH_MOXART
870 #if !defined(CONFIG_ARCH_W325_EC) && !defined(CONFIG_ARCH_EM1220_APIT)
871 ret = register_netdev(&mcpu_mac_dev2);
872 if ( ret ) {
873 mcpu_mac_free_memory(&mcpu_mac_dev);
874 free_irq(mcpu_mac_dev.irq, &mcpu_mac_dev);
875 unregister_netdev(&mcpu_mac_dev);
876 printk("fail !\n");
877 return ret;
879 #endif
880 #endif // CONFIG_ARCH_MOXART
882 printk("OK.\n");
884 return 0;
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);
899 #endif
900 #endif // CONFIG_ARCH_MOXART
903 module_init(mcpu_mac_init_module);
904 module_exit(mcpu_mac_cleanup_module);