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.skbdma
blob32d86421a1646ca2ffe32b25552e537811d46337
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  */
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 <linux/skbuff.h>
38 #include "moxacpu_mac.h"
40 //#define MCPU_MAC_DEBUG
41 //#define USE_SCHEDULE_WORK
43 #ifdef MCPU_MAC_DEBUG
44 #define dbg_printk(x...)        printk(x)
45 #else   // MCPU_MAC_DEBUG
46 #define dbg_printk(x...)
47 #endif  // MCPU_MAC_DEBUG
49 #define TX_DESC_NUM             64
50 #define TX_DESC_NUM_MASK        (TX_DESC_NUM-1)
51 //#define RX_DESC_NUM           64
52 #define RX_DESC_NUM_MASK        (RX_DESC_NUM-1)
53 #define TX_BUF_SIZE             1600
54 #define RX_BUF_SIZE             1600
55 #if TX_BUF_SIZE >= TXBUF_SIZE_MAX
56 #error Moxa CPU ethernet device driver Tx buffer size too large !
57 #endif
58 #if RX_BUF_SIZE >= RXBUF_SIZE_MAX
59 #error Moxa CPU ethernet device driver Rx buffer size too large !
60 #endif
62 static mcpu_mac_priv_t  mcpu_mac_priv;
63 #ifdef CONFIG_ARCH_MOXACPU
65 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
66 static mcpu_mac_priv_t  mcpu_mac_priv2;
67 #endif
69 #endif  // CONFIG_ARCH_MOXACPU
72 #ifdef HAVE_MULTICAST
73 static int crc32( char * s, int length )
75         /* indices */
76         int                     perByte;
77         int                     perBit;
78         /* crc polynomial for Ethernet */
79         const unsigned long     poly=0xedb88320;
80         /* crc value - preinitialized to all 1's */
81         unsigned long           crc_value=0xffffffff;
83         for ( perByte = 0; perByte < length; perByte ++ ) {
84                 unsigned char   c;
86                 c = *(s++);
87                 for ( perBit = 0; perBit < 8; perBit++ ) {
88                         crc_value = (crc_value>>1)^
89                                 (((crc_value^c)&0x01)?poly:0);
90                         c >>= 1;
91                 }
92         }
93         return  crc_value;
96 static void mcpu_mac_setmulticast(unsigned int ioaddr, int count, struct dev_mc_list * addrs )
98         struct dev_mc_list      *cur_addr;
99         int                     crc_val;
101         for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next ) {
102                 if ( !( *cur_addr->dmi_addr & 1 ) )
103                         continue;
104                 crc_val = crc32( cur_addr->dmi_addr, 6 );
105                 crc_val = (crc_val>>26)&0x3f;                   // ยจรบ MSB 6 bit
106                 if (crc_val >= 32)
107                         outl(inl(ioaddr+MATH1_REG_OFFSET) | (1UL<<(crc_val-32)), ioaddr+MATH1_REG_OFFSET);
108                 else
109                         outl(inl(ioaddr+MATH0_REG_OFFSET) | (1UL<<crc_val), ioaddr+MATH0_REG_OFFSET);
110         }
113 static void mcpu_mac_set_multicast_list(struct net_device *dev)
115         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
116         unsigned long           flags;
118         save_flags(flags);
119         cli();
120 #ifdef USE_SCHEDULE_WORK
121         spin_lock(&priv->rxlock);
122 #endif
123         spin_lock(&priv->txlock);
125         if ( dev->flags & IFF_PROMISC )
126                 priv->maccr |= RCV_ALL;
127         else
128                 priv->maccr &= ~RCV_ALL;
130         if ( dev->flags & IFF_ALLMULTI )
131                 priv->maccr |= RX_MULTIPKT;
132         else
133                 priv->maccr &= ~RX_MULTIPKT;
135         if ( dev->mc_count ) {
136                 priv->maccr |= RX_MULTIPKT; //add by Johnson.Liu 2007/07/06
137                 priv->maccr |= HT_MULTI_EN;
138                 mcpu_mac_setmulticast(dev->base_addr, dev->mc_count, dev->mc_list);
139         } else {
140                 priv->maccr &= ~RX_MULTIPKT; //add by Johnson.Liu 2007/07/06
141                 priv->maccr &= ~HT_MULTI_EN;
142         }
144         outl(priv->maccr, dev->base_addr+MACCR_REG_OFFSET);
146         spin_unlock(&priv->txlock);
147 #ifdef USE_SCHEDULE_WORK
148         spin_unlock(&priv->rxlock);
149 #endif
150         restore_flags(flags);
152 #endif  // HAVE_MULTICAST
154 #if 1   // add by Victor Yu. 07-04-2005
155 static void mywordcopy(void *dest, void *source, int len)
157         unsigned short  *pd=(unsigned short *)dest;
158         unsigned short  *ps=(unsigned short *)source;
159         int             wlen=len>>1;
161         while ( wlen > 0 ) {
162                 *pd++=*ps++;
163                 wlen--;
164         }
165         if ( len & 1 )
166                 *(unsigned char *)pd = *(unsigned char *)ps;
168 #endif  // 07-04-2005
170 static void mcpu_mac_recv(void *ptr)
172         struct net_device       *dev=(struct net_device *)ptr;
173         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
174         rx_desc_t               *rxdesc;
175         int                     len;
176         //struct sk_buff                *skb;
178         unsigned char           *data;
179 #if 1   // add by Victor Yu. 07-04-2005
180         unsigned int            ui;
181         int                     rxnow=priv->RxDescNow;
182 #endif  // 07-04-2005
183 #ifndef USE_SCHEDULE_WORK
184         int                     loops=RX_DESC_NUM;
185 #endif  // USE_SCHEDULE_WORK
187         dbg_printk("mcpu_mac_recv test01\n");
190 #if 0
191         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);
192         dbg_printk("Now Rx desc des0=0x%x, des1=0x%x\n", priv->virtRxDescBaseAddr[priv->RxDescNow].rxdes0.ui, priv->virtRxDescBaseAddr[priv->RxDescNow].rxdes1.ui);
193 #endif
196         
197 #ifdef USE_SCHEDULE_WORK
198         spin_lock(&priv->rxlock);
199 #endif  // USE_SCHEDULE_WORK
200 repeat_recv:
201         rxdesc = &priv->virtRxDescBaseAddr[rxnow];
202 #if 0   // mask by Victor Yu. 07-04-2005
203         if ( rxdesc->rxdes0.ubit.RxDMAOwn ) {
204 #else   // add by Victor Yu. 07-04-2005
205         ui = rxdesc->rxdes0.ui;
206         if ( ui & RXDMA_OWN ) {
207 #endif  // 07-04-2005
208 #ifdef USE_SCHEDULE_WORK
209                 spin_unlock(&priv->rxlock);
210 #else
211 #ifdef MCPU_MAC_DEBUG
212                 if ( loops == RX_DESC_NUM )
213                         printk("Bad receive packet !\n");
214 #endif  // MCPU_MAC_DEBUG
215 #endif  // USE_SCHEDULE_WORK
216                 return;
217         }
218 #if 0   // mask by Victor Yu. 07-04-2005
219         if ( rxdesc->rxdes0.ubit.RxErr ||
220              rxdesc->rxdes0.ubit.CRCErr ||
221              rxdesc->rxdes0.ubit.Ftl ||
222              rxdesc->rxdes0.ubit.Runt ||
223              rxdesc->rxdes0.ubit.RxOddNb ) {
224 #else   // add by Victor Yu. 07-04-2005
225         if ( ui & (RX_ERR|CRC_ERR|FTL|RUNT|RX_ODD_NB) ) {
226 #endif  // 07-04-2005
227                 dbg_printk("Ethernet receive packet error !\n");
228                 priv->stats.rx_dropped++;
229                 priv->stats.rx_errors++;
230                 goto recv_finish;
231         }
232 #if 0   // mask by Victor Yu. 07-04-2005
233         len = rxdesc->rxdes0.ubit.RecvFrameLen > RX_BUF_SIZE ? RX_BUF_SIZE : rxdesc->rxdes0.ubit.RecvFrameLen;
234 #else   // add by Victor Yu. 07-04-2005
235         len = ui & RFL_MASK;
236         if ( len > RX_BUF_SIZE )
237                 len = RX_BUF_SIZE;
238 #endif  // 07-04-2005
239         
240         data=skb_put(priv->virtRxBufBaseAddr[rxnow], len);
241         priv->virtRxBufBaseAddr[rxnow]->dev=dev;
243         skb = dev_alloc_skb(len+2);
244         if ( skb == NULL ) {
245                 dbg_printk("Allocate memory fail !\n");
246                 priv->stats.rx_dropped++;
247                 goto recv_finish;
248         }
249         skb_reserve(skb, 2);
250         skb->dev = dev;
251         data = skb_put(skb, len);
252 */      
253         dbg_printk/*printk*/("receive data pointer = 0x%x:%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", (unsigned int)data, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13], data[14], data[15]);
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         priv->virtRxBufBaseAddr[rxnow]->protocol = eth_type_trans(priv->virtRxBufBaseAddr[rxnow], dev);
261         //netif_rx(skb);
262         if(netif_rx(priv->virtRxBufBaseAddr[rxnow])==NET_RX_DROP)
263                 printk("netif_rx recv error.\n");
264         priv->stats.rx_packets++;
265         priv->stats.rx_bytes += len;
266         if ( ui & MULTICAST_RXDES0 )
267                 priv->stats.multicast++;
268         dbg_printk("Receive a good packet.\n");
269         
270         priv->virtRxBufBaseAddr[rxnow]=dev_alloc_skb(RX_BUF_SIZE+2);
271         if (priv->virtRxBufBaseAddr[rxnow]){
272                 //skb_reserve(priv->virtRxBufBaseAddr[rxnow], 2); /* align IP on 16B boundary */
273                 rxdesc->rxdes2.phyRxBufBaseAddr = (unsigned int)__virt_to_phys(priv->virtRxBufBaseAddr[rxnow]->data);
274                 rxdesc->rxdes2.virtRxBufBaseAddr = (unsigned char *)priv->virtRxBufBaseAddr[rxnow]->data;
275         }else goto recv_finish1;
277 recv_finish:
278 #if 0   // mask by Victor Yu. 07-04-2005
279         rxdesc->rxdes0.ui = 0;
280         rxdesc->rxdes0.ubit.RxDMAOwn = 1;
281         rxdesc->rxdes1.ubit.RxBufSize = RX_BUF_SIZE;
282 #else   // add by Victor Yu. 07-04-2005
283         rxdesc->rxdes0.ui = RXDMA_OWN;
284 #endif  // 07-04-2005
286 recv_finish1:
287         rxnow++;
288         rxnow &= RX_DESC_NUM_MASK;
289         priv->RxDescNow = rxnow;
291 #ifdef USE_SCHEDULE_WORK
292         goto repeat_recv;
293 #else   // USE_SCHEDULE_WORK
294         if ( loops-- > 0 )
295                 goto repeat_recv;
296 #endif  // USE_SCHEDULE_WORK
298 #ifdef USE_SCHEDULE_WORK
299         spin_unlock(&priv->rxlock);
300 #endif  // USE_SCHEDULE_WORK
306 static void mcpu_mac_free_memory(struct net_device *dev)
308         int i;
309         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
311         if ( priv->virtTxDescBaseAddr )
312                 dma_free_coherent(NULL, sizeof(tx_desc_t)*TX_DESC_NUM, priv->virtTxDescBaseAddr, priv->phyTxDescBaseAddr);
313         if ( priv->virtRxDescBaseAddr )
314                 dma_free_coherent(NULL, sizeof(rx_desc_t)*RX_DESC_NUM, priv->virtRxDescBaseAddr, priv->phyRxDescBaseAddr);
315         if ( priv->virtTxBufBaseAddr )
316                 dma_free_coherent(NULL, TX_BUF_SIZE*TX_DESC_NUM, priv->virtTxBufBaseAddr, priv->phyTxBufBaseAddr);
317         for(i=0;i<RX_DESC_NUM;i++){
318                 if (priv->virtRxBufBaseAddr[i])
319                         //dma_free_coherent(NULL, RX_BUF_SIZE, priv->virtRxBufBaseAddr[i], priv->phyRxBufBaseAddr[i]);
320                         kfree_skb(priv->virtRxBufBaseAddr[i]);
321         }
324 static void mcpu_mac_setup_desc_ring(struct net_device *dev)
326         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
327         int                     i;
328         tx_desc_t               *txdesc;
329         rx_desc_t               *rxdesc;
330         unsigned char           *virtbuf;
331         unsigned int            phybuf;
333         virtbuf = priv->virtTxBufBaseAddr;
334         phybuf = priv->phyTxBufBaseAddr;
335         for ( i=0; i<TX_DESC_NUM; i++, virtbuf+=TX_BUF_SIZE, phybuf+=TX_BUF_SIZE ) {
336                 txdesc = &priv->virtTxDescBaseAddr[i];
337                 memset(txdesc, 0, sizeof(tx_desc_t));
338                 txdesc->txdes2.phyTxBufBaseAddr = phybuf;
339                 txdesc->txdes2.virtTxBufBaseAddr = virtbuf;
340         }
341         priv->virtTxDescBaseAddr[TX_DESC_NUM-1].txdes1.ubit.Edotr = 1;
342         
343         //virtbuf = priv->virtRxBufBaseAddr;
344         //phybuf = priv->phyRxBufBaseAddr;
345         for ( i=0; i<RX_DESC_NUM; i++/*, virtbuf+=RX_BUF_SIZE, phybuf+=RX_BUF_SIZE*/ ) {
346                 rxdesc = &priv->virtRxDescBaseAddr[i];
347                 memset(rxdesc, 0, sizeof(rx_desc_t));
348                 rxdesc->rxdes0.ubit.RxDMAOwn = 1;
349                 rxdesc->rxdes1.ubit.RxBufSize = RX_BUF_SIZE;
350                 rxdesc->rxdes2.phyRxBufBaseAddr = (unsigned int)__virt_to_phys(priv->virtRxBufBaseAddr[i]->data);
351                 rxdesc->rxdes2.virtRxBufBaseAddr = (unsigned char *)priv->virtRxBufBaseAddr[i]->data;
352         }
353         priv->virtRxDescBaseAddr[RX_DESC_NUM-1].rxdes1.ubit.Edorr = 1;
354         //dbg_printk("First Rx desc des0=0x%x, des1=%x\n", priv->virtRxDescBaseAddr[0].rxdes0.ui, priv->virtRxDescBaseAddr[0].rxdes1.ui);
356         priv->TxDescNow = priv->RxDescNow = 0;
357         
358         // reset the MAC controler Tx/Rx desciptor base address
359         outl(priv->phyTxDescBaseAddr, dev->base_addr+TXR_BADR_REG_OFFSET);
360         outl(priv->phyRxDescBaseAddr, dev->base_addr+RXR_BADR_REG_OFFSET);
361 #if 0
362         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);
363         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));
364 #endif
367 static void mcpu_mac_reset(struct net_device *dev)
369         unsigned int    reg=dev->base_addr+MACCR_REG_OFFSET;
371         outl(SW_RST, reg);      // software reset
372         while ( inl(reg) & SW_RST ) mdelay(10);
373         // maybe we need to disable the all interrupt
374         outl(0, dev->base_addr+IMR_REG_OFFSET);
375 //      ((mcpu_mac_priv_t *)dev->priv)->maccr = RX_BROADPKT | FULLDUP | CRC_APD;
376         ((mcpu_mac_priv_t *)dev->priv)->maccr = RX_BROADPKT | ENRX_IN_HALFTX | CRC_APD;
380 static void mcpu_mac_set_mac_address(unsigned int base, unsigned char *macaddr)
382         unsigned int    val;
384         val = (((u32)macaddr[0] << 8) &0xff00) | ((u32)macaddr[1] & 0xff);
385         outl(val, base);
386         val = (((u32)macaddr[2]<<24) & 0xff000000) |
387               (((u32)macaddr[3]<<16) & 0x00ff0000) |
388               (((u32)macaddr[4]<<8)  & 0x0000ff00) |
389               (((u32)macaddr[5]) & 0x000000ff);
390         outl(val, base+4);
393 #ifdef MCPU_MAC_DEBUG   // add by Victor Yu. 03-14-2006
394 static void mcpu_mac_get_mac_address(unsigned int base, unsigned char *macaddr)
396         unsigned int    val;
398         val = inl(base);
399         macaddr[0] = (val >> 8) & 0xff;
400         macaddr[1] = val & 0xff;
401         val = inl(base+4);
402         macaddr[2] = (val >> 24) & 0xff;
403         macaddr[3] = (val >> 16) & 0xff;
404         macaddr[4] = (val >> 8) & 0xff;
405         macaddr[5] = val & 0xff;
407 #endif
409 static void mcpu_mac_enable(struct net_device *dev)
411         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
412         unsigned int            base=dev->base_addr;
414         outl(0x00001010, base+ITC_REG_OFFSET);
415         outl(0x00000001, base+APTC_REG_OFFSET);
416         outl(0x00000390, base+DBLAC_REG_OFFSET);
417 #ifdef MCPU_MAC_DEBUG
418         outl(RPKT_FINISH_M|NORXBUF_M|AHB_ERR_M, base+IMR_REG_OFFSET);
419 #else
420         outl(RPKT_FINISH_M, base+IMR_REG_OFFSET);
421 #endif
422         priv->maccr |= (RCV_EN | XMT_EN | RDMA_EN | XDMA_EN);
423         outl(priv->maccr, base+MACCR_REG_OFFSET);
426 static void mcpu_mac_tx_timeout(struct net_device *dev)
428         mcpu_mac_priv_t *priv=(mcpu_mac_priv_t *)dev->priv;
429         unsigned long   flags;
431         dbg_printk("mcpu_mac_tx_timeout test01\n");
432         save_flags(flags);
433         cli();
434 #ifdef USE_SCHEDULE_WORK
435         spin_lock(&priv->rxlock);
436 #endif
437         spin_lock(&priv->txlock);
438         mcpu_mac_reset(dev);
439         mcpu_mac_set_mac_address(dev->base_addr+MAC_MADR_REG_OFFSET, dev->dev_addr);
440         mcpu_mac_setup_desc_ring(dev);
441         mcpu_mac_enable(dev);
442         spin_unlock(&priv->txlock);
443 #ifdef USE_SCHEDULE_WORK
444         spin_unlock(&priv->rxlock);
445 #endif
446         restore_flags(flags);
447         netif_wake_queue(dev);
448         dev->trans_start = jiffies;
451 static int mcpu_mac_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
453         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
454         tx_desc_t               *txdesc;
455         int                     len;
456         int                     txnow=priv->TxDescNow;
458         dbg_printk("mcpu_mac_hard_start_xmit test01\n");
459         spin_lock(&priv->txlock);
461         // first check the Tx buffer is enough or not
462         txdesc = &priv->virtTxDescBaseAddr[txnow];
463         if ( txdesc->txdes0.ubit.TxDMAOwn ) {
464                 dbg_printk("No Tx space to transmit the packet !\n");
465                 priv->stats.tx_dropped++;
466                 goto xmit_final;
467         }
469         // fill the data
470 #if 0   // mask by Victor Yu. 07-04-2005
471         len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
472         len = len > TX_BUF_SIZE ? TX_BUF_SIZE : len;
473 #else   // add by Victor Yu. 07-04-2005
474         len = skb->len > TX_BUF_SIZE ? TX_BUF_SIZE : skb->len;
475 #endif
476 #if 0   // mask by Victor Yu. 07-04-2005
477         memcpy(txdesc->txdes2.virtTxBufBaseAddr, skb->data, len);
478 #else   // add by Victor Yu. 07-04-2005
479         mywordcopy((void *)txdesc->txdes2.virtTxBufBaseAddr, (void *)skb->data, len);
480 #endif
481         dbg_printk("transmit data pointer = 0x%x\n", (unsigned long)skb->data);
482 #if 1   // add by Victor Yu. 07-04-2005
483         if ( skb->len < ETH_ZLEN ) {
484                 memset(&txdesc->txdes2.virtTxBufBaseAddr[skb->len], 0, ETH_ZLEN-skb->len);
485                 len = ETH_ZLEN;
486         }
487 #endif
488         txdesc->txdes1.ubit.Lts = 1;
489         txdesc->txdes1.ubit.Fts = 1;
490         txdesc->txdes1.ubit.Tx2fic = 0;
491         txdesc->txdes1.ubit.Txic = 0;
492         txdesc->txdes1.ubit.TxBufSize = len;
493 #if 0   // mask by Victor Yu. 07-04-2005
494         txdesc->txdes0.ui = 0;
495         txdesc->txdes0.ubit.TxDMAOwn = 1;
496 #else   // add by Victor Yu. 07-04-2005
497         txdesc->txdes0.ui = TXDMA_OWN;
498 #endif
500         outl(0xffffffff, dev->base_addr+TXPD_REG_OFFSET);       // start to send packet
501 #if 0
502         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);
503         dbg_printk("Buffer phy address=0x%x, virt=0x%x\n", txdesc->txdes2.phyTxBufBaseAddr, (unsigned int)txdesc->txdes2.virtTxBufBaseAddr);
504         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);
505 #endif
506         txnow++;
507         txnow &= TX_DESC_NUM_MASK;
508         priv->TxDescNow = txnow;
509         dev->trans_start = jiffies;
510         priv->stats.tx_packets++;
511         priv->stats.tx_bytes += len;
513 xmit_final:
514         spin_unlock(&priv->txlock);
515         dev_kfree_skb_any(skb);
517         return 0;
520 static int mcpu_mac_open(struct net_device *dev)
522         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
523         unsigned long           flags;
525         dbg_printk("mcpu_mac_open test01\n");
527         save_flags(flags);
528         cli();
529 #ifdef USE_SCHEDULE_WORK
530         spin_lock(&priv->rxlock);
531 #endif
532         spin_lock(&priv->txlock);
533         mcpu_mac_reset(dev);
534         mcpu_mac_set_mac_address(dev->base_addr+MAC_MADR_REG_OFFSET, dev->dev_addr);
535         mcpu_mac_setup_desc_ring(dev);
536         mcpu_mac_enable(dev);
537         spin_unlock(&priv->txlock);
538 #ifdef USE_SCHEDULE_WORK
539         spin_unlock(&priv->rxlock);
540 #endif
541         restore_flags(flags);
542         netif_start_queue(dev);
543         dbg_printk("IMR=0x%x, MACCR=0x%x\n", inl(dev->base_addr+IMR_REG_OFFSET), inl(dev->base_addr+MACCR_REG_OFFSET));
544 #ifdef MCPU_MAC_DEBUG
545         {
546         unsigned char   macaddr[6];
547         int             i;
548         mcpu_mac_get_mac_address(dev->base_addr+MAC_MADR_REG_OFFSET, macaddr);
549         printk("Get MAC address = ");
550         for ( i=0; i<6; i++ )
551                 printk("%02X ", macaddr[i]);
552         printk("\n");
553         }
554 #endif
556         return 0;
559 static int mcpu_mac_stop(struct net_device *dev)
561         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
562         unsigned long           flags;
564         dbg_printk("mcpu_mac_stop test01\n");
565         netif_stop_queue(dev);
566         save_flags(flags);
567         cli();
568 #ifdef USE_SCHEDULE_WORK
569         spin_lock(&priv->rxlock);
570 #endif
571         spin_lock(&priv->txlock);
572         outl(0, dev->base_addr+IMR_REG_OFFSET);         // disable all interrupt
573         outl(0, dev->base_addr+MACCR_REG_OFFSET);       // disable all function
574         spin_unlock(&priv->txlock);
575 #ifdef USE_SCHEDULE_WORK
576         spin_unlock(&priv->rxlock);
577 #endif
578         restore_flags(flags);
580         return 0;
583 static struct net_device_stats *mcpu_mac_get_stats(struct net_device *dev)
585         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
587         dbg_printk("mcpu_mac_get_stats test01\n");
588 #if 0
589         {
590         unsigned int    base=dev->base_addr;
591         int             desc=priv->RxDescNow;
592         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);
593         dbg_printk("Now Rx desc des0=0x%x, des1=0x%x\n", priv->virtRxDescBaseAddr[desc].rxdes0.ui, priv->virtRxDescBaseAddr[desc].rxdes1.ui);
594         desc++;
595         desc &= RX_DESC_NUM_MASK;
596         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);
597         dbg_printk("Next Now Rx desc des0=0x%x, des1=0x%x\n", priv->virtRxDescBaseAddr[desc].rxdes0.ui, priv->virtRxDescBaseAddr[desc].rxdes1.ui);
598         printk("TX_MCOL_TX_SCOL register = 0x%x\n", inl(base+TX_MCOL_TX_SCOL_REG_OFFSET));
599         printk("RPF_AEP register = 0x%x\n", inl(base+RPF_AEP_REG_OFFSET));
600         printk("XM_PG register = 0x%x\n", inl(base+XM_PG_REG_OFFSET));
601         printk("RUNT_CNT_TLCC register = 0x%x\n", inl(base+RUNT_CNT_TLCC_REG_OFFSET));
602         printk("CRCER_CNT_FTL_CNT register = 0x%x\n", inl(base+CRCER_CNT_FTL_CNT_REG_OFFSET));
603         printk("RLC_RCC register = 0x%x\n", inl(base+RLC_RCC_REG_OFFSET));
604         printk("BROC register = 0x%x\n", inl(base+BROC_REG_OFFSET));
605         printk("MUCLA register = 0x%x\n", inl(base+MULCA_REG_OFFSET));
606         printk("RP register = 0x%x\n", inl(base+RP_REG_OFFSET));
607         printk("XP register = 0x%x\n", inl(base+XP_REG_OFFSET));
608         }
609 #endif
611         return &priv->stats;
615 static irqreturn_t mcpu_mac_interrupt(int irq, void *dev_id, struct pt_regs *regs)
617         struct net_device       *dev=(struct net_device *)dev_id;
618         unsigned int            ists;
619 #ifdef USE_SCHEDULE_WORK
620         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
621 #endif
623         
624         //dbg_printk("mcpu_mac_interrupt test01\n");
625         ists = inl(dev->base_addr+ISR_REG_OFFSET);
626         if ( ists & RPKT_FINISH ) {
627 #ifdef USE_SCHEDULE_WORK
628                 schedule_work(&priv->rqueue);
629 #else
630                 mcpu_mac_recv((void *)dev);
631 #endif
632         } else {
633 #ifdef MCPU_MAC_DEBUG
634                 if ( ists & NORXBUF ) {
635                         printk("Receiver no Rx buffer interrupt\n");
636                         outl(inl(dev->base_addr+IMR_REG_OFFSET)&~NORXBUF_M, dev->base_addr+IMR_REG_OFFSET);
637                         //return IRQ_HANDLED;
638                 }
639                 if ( ists & AHB_ERR ) {
640                         printk("Receiver AHB error interrupt.\n");
641                         //return IRQ_HANDLED;
642                 }
643 #endif
644                 //return IRQ_NONE;
645         }
647         return IRQ_HANDLED;
650 static int mcpu_mac_init(struct net_device *dev)
652         int i;
653         mcpu_mac_priv_t         *priv=(mcpu_mac_priv_t *)dev->priv;
655         dbg_printk("mcpu_mac_init test01\n");
657         // first initialize the private variable to zero 
658         memset((void *)priv, 0, sizeof(mcpu_mac_priv_t));
659         spin_lock_init(&priv->txlock);
660         spin_lock_init(&priv->rxlock);
662 #ifdef USE_SCHEDULE_WORK
664 //#if 1 // add by Victor Yu. 07-04-2005
665         INIT_WORK(&priv->rqueue, &mcpu_mac_recv, (void *)dev);
666 #endif
668         // allocate the descriptor and buffer memory
669         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);    
670         if ( priv->virtTxDescBaseAddr == NULL || (priv->phyTxDescBaseAddr & 0x0f) ) {
671                 dbg_printk("Allocate the Tx descriptor memory fail !\n");
672                 goto init_fail;
673         }
674         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);
675         if ( priv->virtRxDescBaseAddr == NULL || (priv->phyRxDescBaseAddr & 0x0f) ) {
676                 dbg_printk("Allocate the Rx descriptor memory fail !\n");
677                 goto init_fail;
678         }
679         priv->virtTxBufBaseAddr = (unsigned char *)dma_alloc_coherent(NULL, TX_BUF_SIZE*TX_DESC_NUM, (dma_addr_t *)&priv->phyTxBufBaseAddr, GFP_DMA|GFP_KERNEL);
680         if ( priv->virtTxBufBaseAddr == NULL || (priv->phyTxBufBaseAddr & 0x03) ) {
681                 dbg_printk("Allocate the Tx buffer memory fail !\n");
682                 goto init_fail;
683         }
684         for(i=0;i<RX_DESC_NUM;i++){
685                 //priv->virtRxBufBaseAddr[i]= (unsigned char *)dma_alloc_coherent(NULL, RX_BUF_SIZE, (dma_addr_t *)&priv->phyRxBufBaseAddr[i], GFP_DMA|GFP_KERNEL);
686                 priv->virtRxBufBaseAddr[i]=dev_alloc_skb(RX_BUF_SIZE+2);
687                 if ( priv->virtRxBufBaseAddr[i] == NULL /*|| (priv->phyRxBufBaseAddr[i] & 0x03)*/ ) {
688                         dbg_printk("Allocate the Rx buffer memory fail !\n");
689                         goto init_fail;
690                 }
691                 //skb_reserve(priv->virtRxBufBaseAddr[i], 2); /* align IP on 16B boundary */
692         }
694         // setup the thernet basic
695         ether_setup(dev);
697         // reset the MAC
698         mcpu_mac_reset(dev);
699         mcpu_mac_setup_desc_ring(dev);
701         // we need to get the MAC address from the hardware and set to the device
702 #ifdef CONFIG_ARCH_CPE
703 dev->dev_addr[0] = 0x00;
704 dev->dev_addr[1] = 0x90;
705 dev->dev_addr[2] = 0xE8;
706 dev->dev_addr[3] = 0x72;
707 dev->dev_addr[4] = 0x20;
708 dev->dev_addr[5] = 0x01;
709 #endif  // CONFIG_ARCH_CPE
710 #ifdef CONFIG_ARCH_MOXACPU
712 #include        <linux/mtd/mtd.h>
713         struct mtd_info *mtd;
714         int             len;
715         mtd = get_mtd_device(NULL, 0);
716         if ( priv == (void *)&mcpu_mac_priv ) { // LAN 1
717                 if ( mtd == NULL ) {
718 #if 0   // mask by Victor Yu. 03-21-2006
719                         dev->dev_addr[0] = 0x00;
720                         dev->dev_addr[1] = 0x90; 
721                         dev->dev_addr[2] = 0xe8; 
722                         dev->dev_addr[3] = 0x10; 
723                         dev->dev_addr[4] = 0x02; 
724                         dev->dev_addr[5] = 0x40; 
725 #else   // add by Victor Yu. 03-21-2006
726 #if ( defined CONFIG_ARCH_W341 ) || ( defined CONFIG_ARCH_W345 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) || ( defined CONFIG_ARCH_W311 ) ||   ( defined CONFIG_ARCH_W321 ) ||  ( defined CONFIG_ARCH_W315 ) ||   ( defined CONFIG_ARCH_W325 )         
727                         memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x50), 6);
728 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
729                         memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x56), 6);
730         
731 #endif
732                         
733 #endif
734                 } else {
735 #if ( defined CONFIG_ARCH_W341 ) || ( defined CONFIG_ARCH_W345 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) || ( defined CONFIG_ARCH_W311 ) ||   ( defined CONFIG_ARCH_W321 ) ||  ( defined CONFIG_ARCH_W315 ) ||   ( defined CONFIG_ARCH_W325 )         
736                  
737                          mtd->read(mtd, 0x50, 6, &len, dev->dev_addr);
738 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
739                          mtd->read(mtd, 0x56, 6, &len, dev->dev_addr);
741 #endif
743                 }
744         } else {        // LAN2
745                 if ( mtd == NULL ) {
746 #if 0   // mask by Victor Yu. 03-21-2006
747                         dev->dev_addr[0] = 0x00;
748                         dev->dev_addr[1] = 0x90; 
749                         dev->dev_addr[2] = 0xe8; 
750                         dev->dev_addr[3] = 0x10; 
751                         dev->dev_addr[4] = 0x02; 
752                         dev->dev_addr[5] = 0x41; 
753 #else   // add by Victor Yu. 03-21-2006
755 #if ( defined CONFIG_ARCH_UC_7112_LX_PLUS )      
756                         memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x56), 6);
757 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
758                         memcpy(dev->dev_addr, (char *)(CPE_FLASH_VA_BASE+0x50), 6);
759 #endif
761 #endif
763                 } else {
764 #if ( defined CONFIG_ARCH_UC_7112_LX_PLUS )      
765                         mtd->read(mtd, 0x56, 6, &len, dev->dev_addr);
766 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
767                         mtd->read(mtd, 0x50, 6, &len, dev->dev_addr);
768 #endif
769                 }
770         }
772 #endif  // CONFIG_ARCH_MOXACPU
774         // setup the low lever interrupt for Moxa CPU
775 #include <asm/arch/cpe_int.h>
776         cpe_int_set_irq(dev->irq, LEVEL, H_ACTIVE);
777         if ( request_irq(dev->irq, &mcpu_mac_interrupt, SA_INTERRUPT, dev->name, dev) ) {
778                 dbg_printk("Request interrupt service fail !\n");
779                 goto init_fail;
780         }
782         return 0;
784 init_fail:
785         mcpu_mac_free_memory(dev);
786         return -ENOMEM;
789 static struct net_device        mcpu_mac_dev = {
790 #ifdef CONFIG_ARCH_MOXACPU
791         
792 #if ( defined CONFIG_ARCH_W341 ) || ( defined CONFIG_ARCH_W345 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) || ( defined CONFIG_ARCH_W311 ) ||   ( defined CONFIG_ARCH_W321 ) ||  ( defined CONFIG_ARCH_W315 ) ||   ( defined CONFIG_ARCH_W325 )         
793         .name           = "eth0",
794 #elif ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
795         .name           = "eth1",
796 #endif
798 #endif  
799         .base_addr      = IO_ADDRESS(CPE_FTMAC_BASE),
800         .irq            = IRQ_MAC,
801         .init           = &mcpu_mac_init,
802         .get_stats      = &mcpu_mac_get_stats,
803         .open           = &mcpu_mac_open,
804         .stop           = &mcpu_mac_stop,
805         .hard_start_xmit= &mcpu_mac_hard_start_xmit,
806         .priv           = (void *)&mcpu_mac_priv,
807         .tx_timeout     = &mcpu_mac_tx_timeout,
808 #ifdef HAVE_MULTICAST
809         .set_multicast_list = &mcpu_mac_set_multicast_list,
810 #endif
813 #ifdef CONFIG_ARCH_MOXACPU
816 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS ) 
817 static struct net_device        mcpu_mac_dev2 = {
818 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )
819         .name           = "eth0",
820 #elif ( defined CONFIG_ARCH_UC_7112_LX_PLUS )
821         .name           = "eth1",
822 #endif
823         .base_addr      = IO_ADDRESS(CPE_FTMAC2_BASE),
824         .irq            = IRQ_MAC2,
825         .init           = &mcpu_mac_init,
826         .get_stats      = &mcpu_mac_get_stats,
827         .open           = &mcpu_mac_open,
828         .stop           = &mcpu_mac_stop,
829         .hard_start_xmit= &mcpu_mac_hard_start_xmit,
830         .priv           = (void *)&mcpu_mac_priv2,
831         .tx_timeout     = &mcpu_mac_tx_timeout,
832 #ifdef HAVE_MULTICAST
833         .set_multicast_list = &mcpu_mac_set_multicast_list,
834 #endif
836 #endif
838 #endif  // CONFIG_ARCH_MOXACPU
840 static int __init mcpu_mac_init_module(void)
842         int     ret;
843         printk("Moxa CPU Ethernet Device Driver Version 1.0 load ");
844         ret = register_netdev(&mcpu_mac_dev);
845         if ( ret ) {
846                 printk("fail !\n");
847                 return ret;
848         }
850 #ifdef CONFIG_ARCH_MOXACPU
853 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 ) || ( defined CONFIG_ARCH_UC_7112_LX_PLUS )            
855         ret = register_netdev(&mcpu_mac_dev2);
856         if ( ret ) {
857                 mcpu_mac_free_memory(&mcpu_mac_dev);
858                 free_irq(mcpu_mac_dev.irq, &mcpu_mac_dev);
859                 unregister_netdev(&mcpu_mac_dev);
860                 printk("fail !\n");
861                 return ret;
862         }
863 #endif
866 #endif  // CONFIG_ARCH_MOXACPU
868         printk("OK.\n");
870         return 0;
873 static void __exit mcpu_mac_cleanup_module(void)
875         printk("Moxa CPU Ethernet Device Driver unload.\n");
876         mcpu_mac_free_memory(&mcpu_mac_dev);
877         free_irq(mcpu_mac_dev.irq, &mcpu_mac_dev);
878         unregister_netdev(&mcpu_mac_dev);
880 #ifdef CONFIG_ARCH_MOXACPU
882 #if ( defined CONFIG_ARCH_IA240 ) || ( defined CONFIG_ARCH_IA241 )|| ( defined CONFIG_ARCH_UC_7112_LX_PLUS )     
883         mcpu_mac_free_memory(&mcpu_mac_dev2);
884         free_irq(mcpu_mac_dev2.irq, &mcpu_mac_dev2);
885         unregister_netdev(&mcpu_mac_dev2);
886 #endif
888 #endif  // CONFIG_ARCH_MOXACPU
891 module_init(mcpu_mac_init_module);
892 module_exit(mcpu_mac_cleanup_module);