1 /* $Id: hysdn_net.c,v 1.3 2000/02/14 19:24:12 werner Exp $
3 * Linux driver for HYSDN cards, net (ethernet type) handling routines.
5 * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
7 * Copyright 1999 by Werner Cornelius (werner@titro.de)
9 * This net module has been inspired by the skeleton driver from
10 * Donald Becker (becker@CESDIS.gsfc.nasa.gov)
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2, or (at your option)
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 * $Log: hysdn_net.c,v $
27 * Revision 1.3 2000/02/14 19:24:12 werner
29 * Removed superflous file
31 * Revision 1.2 2000/02/13 17:32:19 werner
33 * Added support for new network layer of 2.3.43 and 44 kernels and tested driver.
35 * Revision 1.1 2000/02/10 19:45:18 werner
42 #define __NO_VERSION__
43 #include <linux/module.h>
44 #include <linux/version.h>
45 #include <linux/signal.h>
46 #include <linux/kernel.h>
47 #include <linux/netdevice.h>
48 #include <linux/etherdevice.h>
49 #include <linux/skbuff.h>
50 #include <linux/inetdevice.h>
52 #include "hysdn_defs.h"
54 /* store the actual version for log reporting */
55 char *hysdn_net_revision
= "$Revision: 1.3 $";
57 #define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */
59 /****************************************************************************/
60 /* structure containing the complete network data. The structure is aligned */
61 /* in a way that both, the device and statistics are kept inside it. */
62 /* for proper access, the device structure MUST be the first var/struct */
63 /* inside the definition. */
64 /****************************************************************************/
66 struct net_device netdev
; /* the network device */
67 struct net_device_stats stats
;
68 /* additional vars may be added here */
69 char dev_name
[9]; /* our own device name */
71 /* Tx control lock. This protects the transmit buffer ring
72 * state along with the "tx full" state of the driver. This
73 * means all netif_queue flow control actions are protected
74 * by this lock as well.
77 struct sk_buff
*skbs
[MAX_SKB_BUFFERS
]; /* pointers to tx-skbs */
78 int in_idx
, out_idx
; /* indexes to buffer ring */
79 int sk_count
; /* number of buffers currently in ring */
81 int is_open
; /* flag controlling module locking */
85 /*****************************************************/
86 /* Get the current statistics for this card. */
87 /* This may be called with the card open or closed ! */
88 /*****************************************************/
89 static struct net_device_stats
*
90 net_get_stats(struct net_device
*dev
)
92 return (&((struct net_local
*) dev
)->stats
);
93 } /* net_device_stats */
95 /*********************************************************************/
96 /* Open/initialize the board. This is called (in the current kernel) */
97 /* sometime after booting when the 'ifconfig' program is run. */
98 /* This routine should set everything up anew at each open, even */
99 /* registers that "should" only need to be set once at boot, so that */
100 /* there is non-reboot way to recover if something goes wrong. */
101 /*********************************************************************/
103 net_open(struct net_device
*dev
)
105 struct in_device
*in_dev
;
106 hysdn_card
*card
= dev
->priv
;
109 if (!((struct net_local
*) dev
)->is_open
)
110 MOD_INC_USE_COUNT
; /* increment only if interface is actually down */
111 ((struct net_local
*) dev
)->is_open
= 1; /* device actually open */
113 netif_start_queue(dev
); /* start tx-queueing */
115 /* Fill in the MAC-level header (if not already set) */
116 if (!card
->mac_addr
[0]) {
117 for (i
= 0; i
< ETH_ALEN
- sizeof(ulong
); i
++)
118 dev
->dev_addr
[i
] = 0xfc;
119 if ((in_dev
= dev
->ip_ptr
) != NULL
) {
120 struct in_ifaddr
*ifa
= in_dev
->ifa_list
;
122 memcpy(dev
->dev_addr
+ (ETH_ALEN
- sizeof(ulong
)), &ifa
->ifa_local
, sizeof(ulong
));
125 memcpy(dev
->dev_addr
, card
->mac_addr
, ETH_ALEN
);
130 /*******************************************/
131 /* flush the currently occupied tx-buffers */
132 /* must only be called when device closed */
133 /*******************************************/
135 flush_tx_buffers(struct net_local
*nl
)
138 while (nl
->sk_count
) {
139 dev_kfree_skb(nl
->skbs
[nl
->out_idx
++]); /* free skb */
140 if (nl
->out_idx
>= MAX_SKB_BUFFERS
)
141 nl
->out_idx
= 0; /* wrap around */
144 } /* flush_tx_buffers */
147 /*********************************************************************/
148 /* close/decativate the device. The device is not removed, but only */
150 /*********************************************************************/
152 net_close(struct net_device
*dev
)
155 netif_stop_queue(dev
); /* disable queueing */
157 if (((struct net_local
*) dev
)->is_open
)
158 MOD_DEC_USE_COUNT
; /* adjust module counter */
159 ((struct net_local
*) dev
)->is_open
= 0;
160 flush_tx_buffers((struct net_local
*) dev
);
162 return (0); /* success */
165 /************************************/
166 /* send a packet on this interface. */
167 /* new style for kernel >= 2.3.33 */
168 /************************************/
170 net_send_packet(struct sk_buff
*skb
, struct net_device
*dev
)
172 struct net_local
*lp
= (struct net_local
*) dev
;
174 spin_lock_irq(&lp
->lock
);
176 lp
->skbs
[lp
->in_idx
++] = skb
; /* add to buffer list */
177 if (lp
->in_idx
>= MAX_SKB_BUFFERS
)
178 lp
->in_idx
= 0; /* wrap around */
179 lp
->sk_count
++; /* adjust counter */
180 dev
->trans_start
= jiffies
;
182 /* If we just used up the very last entry in the
183 * TX ring on this device, tell the queueing
184 * layer to send no more.
186 if (lp
->sk_count
>= MAX_SKB_BUFFERS
)
187 netif_stop_queue(dev
);
189 /* When the TX completion hw interrupt arrives, this
190 * is when the transmit statistics are updated.
193 spin_unlock_irq(&lp
->lock
);
195 if (lp
->sk_count
<= 3) {
196 queue_task(&((hysdn_card
*) dev
->priv
)->irq_queue
, &tq_immediate
);
197 mark_bh(IMMEDIATE_BH
);
199 return (0); /* success */
200 } /* net_send_packet */
204 /***********************************************************************/
205 /* acknowlegde a packet send. The network layer will be informed about */
207 /***********************************************************************/
209 hysdn_tx_netack(hysdn_card
* card
)
211 struct net_local
*lp
= card
->netif
;
214 return; /* non existing device */
218 return; /* error condition */
220 lp
->stats
.tx_packets
++;
221 lp
->stats
.tx_bytes
+= lp
->skbs
[lp
->out_idx
]->len
;
223 dev_kfree_skb(lp
->skbs
[lp
->out_idx
++]); /* free skb */
224 if (lp
->out_idx
>= MAX_SKB_BUFFERS
)
225 lp
->out_idx
= 0; /* wrap around */
227 if (lp
->sk_count
-- == MAX_SKB_BUFFERS
) /* dec usage count */
228 netif_start_queue((struct net_device
*) lp
);
229 } /* hysdn_tx_netack */
231 /*****************************************************/
232 /* we got a packet from the network, go and queue it */
233 /*****************************************************/
235 hysdn_rx_netpkt(hysdn_card
* card
, uchar
* buf
, word len
)
237 struct net_local
*lp
= card
->netif
;
241 return; /* non existing device */
243 lp
->stats
.rx_bytes
+= len
;
245 skb
= dev_alloc_skb(len
);
247 printk(KERN_NOTICE
"%s: Memory squeeze, dropping packet.\n",
249 lp
->stats
.rx_dropped
++;
252 skb
->dev
= &lp
->netdev
;
255 memcpy(skb_put(skb
, len
), buf
, len
);
257 /* determine the used protocol */
258 skb
->protocol
= eth_type_trans(skb
, &lp
->netdev
);
261 lp
->stats
.rx_packets
++; /* adjust packet count */
263 } /* hysdn_rx_netpkt */
265 /*****************************************************/
266 /* return the pointer to a network packet to be send */
267 /*****************************************************/
269 hysdn_tx_netget(hysdn_card
* card
)
271 struct net_local
*lp
= card
->netif
;
274 return (NULL
); /* non existing device */
277 return (NULL
); /* nothing available */
279 return (lp
->skbs
[lp
->out_idx
]); /* next packet to send */
280 } /* hysdn_tx_netget */
283 /*******************************************/
284 /* init function called by register device */
285 /*******************************************/
287 net_init(struct net_device
*dev
)
289 /* setup the function table */
290 dev
->open
= net_open
;
291 dev
->stop
= net_close
;
292 dev
->hard_start_xmit
= net_send_packet
;
293 dev
->get_stats
= net_get_stats
;
295 /* Fill in the fields of the device structure with ethernet values. */
298 return (0); /* success */
301 /*****************************************************************************/
302 /* hysdn_net_create creates a new net device for the given card. If a device */
303 /* already exists, it will be deleted and created a new one. The return value */
304 /* 0 announces success, else a negative error code will be returned. */
305 /*****************************************************************************/
307 hysdn_net_create(hysdn_card
* card
)
309 struct net_device
*dev
;
312 hysdn_net_release(card
); /* release an existing net device */
313 if ((dev
= kmalloc(sizeof(struct net_local
), GFP_KERNEL
)) == NULL
) {
314 printk(KERN_WARNING
"HYSDN: unable to allocate mem\n");
315 if (card
->debug_flags
& LOG_NET_INIT
)
318 memset(dev
, 0, sizeof(struct net_local
)); /* clean the structure */
320 spin_lock_init(&((struct net_local
*) dev
)->lock
);
322 /* initialise necessary or informing fields */
323 dev
->base_addr
= card
->iobase
; /* IO address */
324 dev
->irq
= card
->irq
; /* irq */
325 dev
->init
= net_init
; /* the init function of the device */
326 dev
->name
= ((struct net_local
*) dev
)->dev_name
; /* device name */
327 if ((i
= register_netdev(dev
))) {
328 printk(KERN_WARNING
"HYSDN: unable to create network device\n");
332 dev
->priv
= card
; /* remember pointer to own data structure */
333 card
->netif
= dev
; /* setup the local pointer */
335 if (card
->debug_flags
& LOG_NET_INIT
)
336 hysdn_addlog(card
, "network device created");
337 return (0); /* and return success */
338 } /* hysdn_net_create */
340 /***************************************************************************/
341 /* hysdn_net_release deletes the net device for the given card. The return */
342 /* value 0 announces success, else a negative error code will be returned. */
343 /***************************************************************************/
345 hysdn_net_release(hysdn_card
* card
)
347 struct net_device
*dev
= card
->netif
;
350 return (0); /* non existing */
352 card
->netif
= NULL
; /* clear out pointer */
353 dev
->stop(dev
); /* close the device */
355 flush_tx_buffers((struct net_local
*) dev
); /* empty buffers */
357 unregister_netdev(dev
); /* release the device */
358 kfree(dev
); /* release the memory allocated */
359 if (card
->debug_flags
& LOG_NET_INIT
)
360 hysdn_addlog(card
, "network device deleted");
362 return (0); /* always successfull */
363 } /* hysdn_net_release */
365 /*****************************************************************************/
366 /* hysdn_net_getname returns a pointer to the name of the network interface. */
367 /* if the interface is not existing, a "-" is returned. */
368 /*****************************************************************************/
370 hysdn_net_getname(hysdn_card
* card
)
372 struct net_device
*dev
= card
->netif
;
375 return ("-"); /* non existing */
378 } /* hysdn_net_getname */