make oldconfig will rebuild these...
[linux-2.4.21-pre4.git] / drivers / net / npnet.c
1 /* @(#)27 1.6 linux405/drivers/net/npnet.c, linux, np 2/7/02 15:06:29 */
2
3 /*************************************************************************
4  * (C) Copyright IBM Corp. 2001
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License (GPL) version 2.0
8  * or (at your option) any later version.
9  * 
10  **************************************************************************/
11
12 #include <linux/module.h>
13 #include <linux/malloc.h> /* kmalloc() */
14 #include <linux/netdevice.h>   /* struct device, and other headers */
15 #include <linux/etherdevice.h> /* eth_type_trans */
16 #include <linux/ip.h>          /* struct iphdr */
17 #include <linux/init.h>
18
19 #include "npnet.h"
20
21 #include <asm/checksum.h>
22 #include <asm/io.h>
23
24 MODULE_AUTHOR("John F. Davis");
25 // This code was modeled after Alessandro Rubini's 
26 // Linux Device Driver book.
27
28 /////////////////////////////////////////////////////
29 /////////////////////////////////////////////////////
30
31 /////////////////////////////////////////////////////
32 // #DEFINES
33 /////////////////////////////////////////////////////
34
35 #define NP_NET_VERSION          "1.0"
36 #define NP_PAGE                 0x1004          //4100bytes
37 #define MB_405                  0x00000018
38 #define H2P_MSG_ADDR_ALT        0x00000050
39 #define H2P_MSG_ADDR_PRI        0x00000060
40 #define NP_INT_ENB              0x00000008
41 #define P2H_MSG                 1               /*enable P2H message interrupt*/
42 #define ENV_405                 (ENV_750 + NP_PAGE)
43 #define ENV_750                 0x00000000
44 #define MAC_405                 "\0\0\4\0\5\0"
45 #define MAC_750                 "\0\0\7\5\0\0"
46
47 #ifdef CONFIG_RAINIER
48 #define MB_BASE_ADDR            0x78010000
49 #define ENV_BASE_ADDR           0x03F00000
50 #define MYENVELOPE              ENV_405
51 #define HISENVELOPE             ENV_750
52 #define IRQ                     4
53 #define MY_MAC                  MAC_405
54 #define HIS_MAC                 MAC_750
55 #else
56 #define MB_BASE_ADDR            0xB8010000
57 #define ENV_BASE_ADDR           0xB3F00000
58 #define MYENVELOPE              ENV_750
59 #define HISENVELOPE             ENV_405
60 #define IRQ                     11
61 #define MY_MAC                  MAC_750
62 #define HIS_MAC                 MAC_405
63 #endif
64
65 #define TX_TIMEOUT              (2*HZ)            // In jiffies
66 #define TX_COUNT                50
67
68 /////////////////////////////////////////////////////
69 // Types
70 /////////////////////////////////////////////////////
71
72 struct shared_buffer {
73         volatile int iBusy;             // If 1, its busy.
74         volatile int iSize;   // If 1, its valid.
75         u8 pData[2048];// Was 4096
76 };
77
78 /*
79  * This structure is private to each device. It is used to pass
80  * packets in and out, so there is place for a packet
81  */
82
83 struct npnet_priv {
84     struct net_device_stats stats;
85     int status;
86     int tx_packetlen;
87     u8 *tx_packetdata;
88     struct sk_buff *skb;
89     spinlock_t lock;
90 };
91
92 /////////////////////////////////////////////////////
93 // Prototypes
94 /////////////////////////////////////////////////////
95 static int npnet_init(struct net_device *dev);
96 static void npnet_int_handler(int irq, void *dev_id, struct pt_regs *regs);
97 static int npnet_header(struct sk_buff *skb, struct net_device *dev,
98                  unsigned short type, void *daddr, void *saddr, 
99                  unsigned len);
100
101 /////////////////////////////////////////////////////
102 // Globals
103 /////////////////////////////////////////////////////
104 static volatile void *pvMailboxPage;
105 static volatile void *pvEnvelopePage;
106
107 /*
108  * The devices
109  */
110 static struct net_device npnet_devs= {
111     init: npnet_init  /* init, nothing more */
112 };
113
114 /////////////////////////////////////////////////////
115 // Notes
116 /////////////////////////////////////////////////////
117
118 void DumpSkbStruct(struct sk_buff *skb) {
119         int i;
120         printk("Dump sk_buff \n");
121         printk("skb addy %p\n",skb);
122
123         printk( KERN_ERR "skb: len is %i\n",skb->len);
124         printk( KERN_ERR "skb : data:\n");
125         for (i=0 ; i<skb->len; i++) {
126                 printk(" %02x",skb->data[i]&0xff);
127         }
128         printk("\n");
129         printk("net_device pointer addy %p\n",skb->dev);
130         printk("    Dump sk_buff END\n");
131 }
132
133 void DumpDevStruct(struct net_device *dev) {
134
135         int i;
136
137         printk("Dump net_device\n");
138         printk("dev addy %p\n",dev);
139
140         printk("priv pointer addy = %p\n",dev->priv);
141
142         printk("dev_addr: (len = %d)\n",dev->addr_len);
143         for (i=0 ; i<dev->addr_len; i++) {
144                 printk(" %02x",dev->dev_addr[i]);
145         }
146         printk("\n");
147
148         printk("    Dump net_device END\n");
149 }
150
151 /*********************************************************************
152  *
153  * The Prototypes.
154  *
155  *
156  *
157  ********************************************************************/
158
159 /*
160  * Receive a packet: retrieve, encapsulate and pass over to upper levels
161  */
162
163 void npnet_rx(struct net_device *dev, int len, unsigned char *buf)
164 {
165     struct sk_buff *skb;
166     struct npnet_priv *privp = (struct npnet_priv *)dev->priv;
167
168     /*
169      * The packet has been retrieved from the transmission
170      * medium. Build an skb around it, so upper layers can handle it
171      */
172     skb = dev_alloc_skb(len+2);
173     if (!skb) {
174         printk("snull rx: low on mem - packet dropped\n");
175         privp->stats.rx_dropped++;
176         return;
177     }
178     skb_reserve(skb, 2); /* align IP on 16B boundary */  
179     memcpy(skb_put(skb, len), buf, len);
180
181     /* Write metadata, and then pass to the receive level */
182     skb->dev = dev;
183     skb->protocol = eth_type_trans(skb, dev); // this strips off the mac.
184
185     skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
186     skb->pkt_type = PACKET_HOST;
187
188     netif_rx(skb);
189     return;
190 }
191
192 /*********************************************************************
193  *
194  * The Interrupt Handler.
195  *
196  *
197  ********************************************************************/
198 void npnet_int_handler(int irq, void *dev_id, struct pt_regs *regs)
199 {
200     volatile unsigned *pvBuffer;
201     volatile int iSize;
202 #ifndef CONFIG_RAINIER
203     volatile int iStatus;
204 #endif
205     volatile struct shared_buffer *pSharedBuffer;
206     struct net_device *dev = (struct net_device *)dev_id;
207
208     /* Lock the device */
209     //privptr = (struct npnet_priv *)(dev->priv);
210     //nospin spin_lock(&privptr->lock);
211     
212 #ifndef CONFIG_RAINIER
213     // this is a hack to see if the int status has been cleared.
214     pvBuffer = pvMailboxPage + 0; // Read the status register.
215     iStatus = *pvBuffer;
216     if ((iStatus & P2H_MSG) == 0) {
217         // We have already service this interrupt.
218         //printk(KERN_ERR "The hw hasn't cleared the interrupt yet.\n");
219         // The hardware just hasn't cleared it yet.
220         goto out;
221     }
222 #endif
223
224     // So, we have a valid interrupt which we haven't cleared yet.
225     // Maybe we need to do this last!!!!!
226     // This read will __eventually__ reset the msg busy bit in the status
227     // register. 
228
229 #ifdef CONFIG_RAINIER
230     pvBuffer = pvMailboxPage + H2P_MSG_ADDR_PRI;
231 #else
232     pvBuffer = pvMailboxPage + MB_405;
233 #endif
234     iSize = *pvBuffer;
235
236     // Determine if this is a 750 interupt when it initializes.
237     if (iSize == 0) {
238         // This looks like a interupt generated when the 750 is initializing.
239         printk("This is just a 750 initializing interrupt..\n");
240         goto out;
241     }
242     // Verify that we have a good buffer.
243     pSharedBuffer = pvEnvelopePage + HISENVELOPE;
244     if (iSize != pSharedBuffer->iSize) {
245         // Size Mismatch.
246         printk("int handler size mismatch iS= %d pS= %d\n", iSize,pSharedBuffer->iSize);
247         goto out;
248     } 
249     // Save it to the device.
250     npnet_rx(dev, iSize, (unsigned char*)pSharedBuffer->pData);
251
252     // We have the data free the buffer..
253     pSharedBuffer->iBusy = 0;
254
255  out:
256     /* Unlock the device and we are done */
257     //nospin    spin_unlock(&privptr->lock);
258     return;
259 }
260
261 /*********************************************************************
262  * 
263  * Open
264  * This is called when you do:
265  * # ifconfig np0 local0
266  *   
267  ********************************************************************/
268 int npnet_open(struct net_device *dev)
269 {
270
271     MOD_INC_USE_COUNT;
272     
273     /* 
274      * Assign the hardware address of the board: use "\0SNULx", where
275      * x is 0 or 1. The first byte is '\0' to avoid being a multicast
276      * address (the first byte of multicast addrs is odd).
277      */
278
279     memcpy(dev->dev_addr, MY_MAC, ETH_ALEN);  // ETH_ALEN = 6;
280     netif_start_queue(dev);
281
282     return 0;
283 }
284
285 /*********************************************************************
286  * 
287  * Release
288  * This is called when you do:
289  * # ifconfig np0 down
290  *   
291  ********************************************************************/
292 int npnet_release(struct net_device *dev)
293 {
294
295     /* release ports, irq and such -- like fops->close */
296
297         // Stop the queue when closed.
298     netif_stop_queue(dev); /* can't transmit any more */
299
300     MOD_DEC_USE_COUNT;
301
302     return 0;
303 }
304
305 /*********************************************************************
306  * 
307  * Transmit a packet (low level interface)
308  * The routine is called after the tx routine.
309  *  
310  *   
311  ********************************************************************/
312
313 static struct timer_list timer;
314
315 void npnet_hw_tx(unsigned long idev)
316 {
317     /*
318      * This function deals with hw details. 
319      * This function implements the npnet behaviour,
320      * while all other procedures are rather device-independent
321      */
322
323     struct iphdr *ih;
324     struct net_device *dev = (struct net_device*) idev;
325     struct npnet_priv *priv = (struct npnet_priv *)dev->priv;
326     volatile struct shared_buffer *pSharedBuffer;
327     volatile unsigned *pvBuffer;
328     static int iLoop = 0;
329     struct timer_list *ptimer = &timer;
330     char * buf;
331     int len;
332
333     len = priv->tx_packetlen;
334     buf = priv->tx_packetdata;
335     /*
336      * Ethhdr is 14 bytes, but the kernel arranges for iphdr
337      * to be aligned (i.e., ethhdr is unaligned)
338      */
339     ih = (struct iphdr *)(buf+sizeof(struct ethhdr));
340     ih->check = 0;         /* and rebuild the checksum (ip needs it) */
341     ih->check = ip_fast_csum((unsigned char *)ih,ih->ihl);
342
343     // Hardware says we can do a write.  Now, we need to check to 
344     //  make sure we don't use a buffer that's in use.
345     pSharedBuffer = pvEnvelopePage + MYENVELOPE;
346     if (pSharedBuffer->iBusy) {
347         if (++iLoop < TX_COUNT){
348             ptimer->expires = jiffies;
349             ptimer->data = (unsigned long) dev;
350             ptimer->function = npnet_hw_tx;
351             init_timer (ptimer);
352             add_timer(ptimer);
353         //printk("We did not restart the queue in tx. \n");
354             return ;
355         }
356         else{
357             printk("We looped more than TX_COUNT times\n");
358             iLoop = 0;
359             return;
360         }
361     }
362     iLoop = 0;
363     pSharedBuffer->iBusy = 1;  // Take the buffer so its no longer free.
364     // Place in data in D6 buffer.
365     memcpy((char *)pSharedBuffer->pData,buf,len);
366     // Complete header in D6 buffer.
367     pSharedBuffer->iSize = len;
368
369     // Place in mailbox.
370 #ifdef CONFIG_RAINIER
371     pvBuffer = pvMailboxPage + MB_405;
372 #else
373     pvBuffer = pvMailboxPage + H2P_MSG_ADDR_PRI;
374 #endif
375     *pvBuffer = len;
376
377     dev_kfree_skb(priv->skb);        
378     priv->skb = NULL;
379     priv->stats.tx_packets++;
380     priv->stats.tx_bytes += len;
381     netif_wake_queue(dev);
382     return;
383 }
384
385 /*********************************************************************
386  * 
387  * Transmit a packet 
388  *   
389  ********************************************************************/
390 int npnet_xmit(struct sk_buff *skb, struct net_device *dev)
391 {
392     int len;
393     struct npnet_priv *priv = (struct npnet_priv *)dev->priv;
394
395     /* Lock the device */
396     //nospin spin_lock(&priv->lock);
397
398     // Stop the queue
399     netif_stop_queue(dev);        
400
401     len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
402     dev->trans_start = jiffies; // save the timestamp
403
404     // Remember the skb, so we can free it at interrupt time
405     priv->skb = skb;
406     priv->tx_packetdata= skb->data;
407     priv->tx_packetlen = len;
408     npnet_hw_tx((int)dev);
409
410     /* Unlock the device and we are done */
411     //nospin spin_unlock(&priv->lock);
412     return 0;
413 }
414
415 /*********************************************************************
416  * 
417  * Return statistics to the caller
418  *  
419  ********************************************************************/
420 struct net_device_stats *npnet_stats(struct net_device *dev)
421 {
422     struct npnet_priv *priv = (struct npnet_priv *)dev->priv;
423     return &priv->stats;
424 }
425
426 /*********************************************************************
427  *
428  * This function is called to fill up an eth header, since arp is not
429  * available on the interface
430  *  
431  * This doesn't seem to be called.
432  *  
433  ********************************************************************/
434 int npnet_rebuild_header(struct sk_buff *skb)
435 {
436     struct ethhdr *eth = (struct ethhdr *) skb->data;
437     struct net_device *dev = skb->dev;
438
439     memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
440     memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
441     eth->h_dest[ETH_ALEN-1]   ^= 0x01;   /* dest is us xor 1 */
442     return 0;
443 }
444
445 /*********************************************************************
446  * 
447  * I think I can do without this function.  I just keep it around
448  * so that I can see the call.
449  *   
450  ********************************************************************/
451 int npnet_header(struct sk_buff *skb, struct net_device *dev,
452                  unsigned short type, void *daddr, void *saddr, 
453                  unsigned len)
454 {
455
456         struct ethhdr *eth = (struct ethhdr *) skb_push(skb,ETH_HLEN);
457
458         eth->h_proto = htons(type);
459
460         memcpy(eth->h_source,MY_MAC,6);
461         memcpy(eth->h_dest,HIS_MAC,6);
462         return (dev->hard_header_len);
463 }
464
465 /*********************************************************************
466  *   
467  ********************************************************************/
468 void npnet_tx_timeout(struct net_device *dev) {
469
470     struct npnet_priv *priv = (struct npnet_priv *)dev->priv;
471
472     printk(KERN_NOTICE "***npnet_tx_timeout ***\n");
473
474     /* Lock the device */
475     //nospin spin_lock(&priv->lock);
476
477     priv->stats.tx_errors++;
478
479     /* Unlock the device and we are done */
480     //nospin spin_unlock(&priv->lock);
481
482     // Wake the queue
483     netif_wake_queue(dev);
484 }
485
486 /*********************************************************************
487  * 
488  * The init function (sometimes called probe).
489  * It is invoked by register_netdev()
490  *  
491  *   
492  ********************************************************************/
493 int npnet_init(struct net_device *dev)
494 {
495
496     /*
497      * Make the usual checks: check_region(), probe irq, ...  -ENODEV
498      * should be returned if no device found.  No resource should be
499      * grabbed: this is done on open(). 
500      */
501
502         /* 
503          * Then, assign other fields in dev, using ether_setup() and some
504          * hand assignments
505          */
506         ether_setup(dev); /* assign some of the fields */
507
508         dev->open            = npnet_open;
509         dev->stop            = npnet_release;
510         dev->hard_start_xmit = npnet_xmit;
511         dev->hard_header     = npnet_header;
512         dev->rebuild_header  = npnet_rebuild_header;
513         dev->tx_timeout = npnet_tx_timeout;
514         dev->watchdog_timeo = TX_TIMEOUT;     
515         dev->get_stats       = npnet_stats;
516         dev->flags           |= IFF_NOARP;
517         dev->hard_header_cache = NULL;      /* Disable caching */
518         /*
519          * Then, allocate the priv field. This encloses the statistics
520          * and a few private fields.
521          */
522         dev->priv = kmalloc(sizeof(struct npnet_priv), GFP_KERNEL);
523         if (dev->priv == NULL) {
524                 printk("kmalloc in init failed.\n");
525                 return -ENOMEM;
526         }
527         memset(dev->priv, 0, sizeof(struct npnet_priv));
528
529         //nospin spin_lock_init(& ((struct npnet_priv *) dev->priv)->lock);
530
531         // Register the interrupt
532         request_irq(IRQ,npnet_int_handler,SA_INTERRUPT,"np_net_int",dev);
533         return 0;
534 }
535
536 /*********************************************************************
537  * 
538  * This is called when you do:
539  * # insmod npnet
540  *  
541  *   
542  ********************************************************************/
543 static int __init npnet_init_module(void) {
544
545     int result, device_present = 0;
546     volatile unsigned *pvMailboxInt;
547     volatile int dontcare;
548     volatile struct shared_buffer *pSharedBuffer;
549
550     strcpy(npnet_devs.name, "np0");
551     printk(KERN_INFO "NP Net memory driver v" NP_NET_VERSION "\n");
552
553     // Remap the memory for the MB and Envelope pages.
554     pvMailboxPage =  ioremap(MB_BASE_ADDR,0x256); 
555     if (pvMailboxPage == NULL) {
556                 printk(KERN_ERR "Mailbox: We're screwed.\n");
557     }
558     pvEnvelopePage = ioremap(ENV_BASE_ADDR,(NP_PAGE*2)); 
559     if (pvEnvelopePage == NULL) {
560                 printk(KERN_ERR "Envelope: We're screwed.\n");
561     }
562     //printk("npnet: pvMailboxPage = %p\n", pvMailboxPage);
563     //printk("npnet: pvEnvelopePage = %p\n",  pvEnvelopePage);
564
565     // Clear the incoming mailbox so we don't get
566     // and interrupt as soon as we register the handler.
567     dontcare = *(volatile unsigned *) (pvMailboxPage + H2P_MSG_ADDR_PRI);
568
569     result = register_netdev(&npnet_devs);
570     if ( result ) { 
571         printk("npnet: error %i registering device \"%s\"\n",
572                            result, npnet_devs.name);
573     } else {
574         device_present++;
575     }
576
577     // Clear the shared area (D6).  Do this first so that when
578     // we clear the outgoing mailbox, the other end will be interrupted
579     // but we will have a clear envelope area. (Busy flag cleared also.)
580     pSharedBuffer = pvEnvelopePage + MYENVELOPE;
581     memset((void*)pSharedBuffer,0,sizeof(struct shared_buffer));
582     //pSharedBuffer = pvEnvelopePage+HISENVELOPE;/*BMS only if necessary*/
583     //pSharedBuffer->iBusy = 0;                  /*BMS only if necessary*/
584
585     // Clear the outgoing mailbox.  This will generate a interrupt to far end.
586 #ifdef CONFIG_RAINIER
587     *(volatile unsigned *)(pvMailboxPage + MB_405) = 0;
588 #else
589     *(volatile unsigned*)(pvMailboxPage+H2P_MSG_ADDR_PRI) = 0x489;
590 #endif
591
592     // Enable interrupts  to K2 in hardware.
593     pvMailboxInt = pvMailboxPage + NP_INT_ENB;
594     dontcare = *pvMailboxInt;
595     *pvMailboxInt = dontcare | P2H_MSG;
596
597 #ifndef NPNET_DEBUG
598     EXPORT_NO_SYMBOLS;
599 #endif
600     return device_present ? 0 : -ENODEV;
601 }
602
603 /*********************************************************************
604  * 
605  * This is called when you do:
606  * # rmmod npnet
607  *  
608  *   
609  ********************************************************************/
610 static void __exit npnet_cleanup(void)
611 {
612     free_irq(IRQ,&npnet_devs);
613     kfree(npnet_devs.priv);
614     unregister_netdev(&npnet_devs);
615     return;
616 }
617
618 module_init(npnet_init_module);
619 module_exit(npnet_cleanup);