1 /* $Id: hysdn_net.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
2  *
3  * Linux driver for HYSDN cards, net (ethernet type) handling routines.
4  *
5  * Author    Werner Cornelius (werner@titro.de) for Hypercope GmbH
6  * Copyright 1999 by Werner Cornelius (werner@titro.de)
7  *
8  * This software may be used and distributed according to the terms
9  * of the GNU General Public License, incorporated herein by reference.
10  *
11  * This net module has been inspired by the skeleton driver from
12  * Donald Becker (becker@CESDIS.gsfc.nasa.gov)
13  *
14  */
15 
16 #define __NO_VERSION__
17 #include <linux/module.h>
18 #include <linux/version.h>
19 #include <linux/signal.h>
20 #include <linux/kernel.h>
21 #include <linux/netdevice.h>
22 #include <linux/etherdevice.h>
23 #include <linux/skbuff.h>
24 #include <linux/inetdevice.h>
25 
26 #include "hysdn_defs.h"
27 
28 unsigned int hynet_enable = 0xffffffff;
29 MODULE_PARM(hynet_enable, "i");
30 
31 /* store the actual version for log reporting */
32 char *hysdn_net_revision = "$Revision: 1.1.4.1 $";
33 
34 #define MAX_SKB_BUFFERS 20	/* number of buffers for keeping TX-data */
35 
36 /****************************************************************************/
37 /* structure containing the complete network data. The structure is aligned */
38 /* in a way that both, the device and statistics are kept inside it.        */
39 /* for proper access, the device structure MUST be the first var/struct     */
40 /* inside the definition.                                                   */
41 /****************************************************************************/
42 struct net_local {
43 	struct net_device netdev;	/* the network device */
44 	struct net_device_stats stats;
45 	/* additional vars may be added here */
46 	char dev_name[9];	/* our own device name */
47 
48 	/* Tx control lock.  This protects the transmit buffer ring
49 	 * state along with the "tx full" state of the driver.  This
50 	 * means all netif_queue flow control actions are protected
51 	 * by this lock as well.
52 	 */
53 	spinlock_t lock;
54 	struct sk_buff *skbs[MAX_SKB_BUFFERS];	/* pointers to tx-skbs */
55 	int in_idx, out_idx;	/* indexes to buffer ring */
56 	int sk_count;		/* number of buffers currently in ring */
57 
58 	int is_open;		/* flag controlling module locking */
59 };				/* net_local */
60 
61 
62 /*****************************************************/
63 /* Get the current statistics for this card.         */
64 /* This may be called with the card open or closed ! */
65 /*****************************************************/
66 static struct net_device_stats *
net_get_stats(struct net_device * dev)67 net_get_stats(struct net_device *dev)
68 {
69 	return (&((struct net_local *) dev)->stats);
70 }				/* net_device_stats */
71 
72 /*********************************************************************/
73 /* Open/initialize the board. This is called (in the current kernel) */
74 /* sometime after booting when the 'ifconfig' program is run.        */
75 /* This routine should set everything up anew at each open, even     */
76 /* registers that "should" only need to be set once at boot, so that */
77 /* there is non-reboot way to recover if something goes wrong.       */
78 /*********************************************************************/
79 static int
net_open(struct net_device * dev)80 net_open(struct net_device *dev)
81 {
82 	struct in_device *in_dev;
83 	hysdn_card *card = dev->priv;
84 	int i;
85 
86 	if (!((struct net_local *) dev)->is_open)
87 		MOD_INC_USE_COUNT;	/* increment only if interface is actually down */
88 	((struct net_local *) dev)->is_open = 1;	/* device actually open */
89 
90 	netif_start_queue(dev);	/* start tx-queueing */
91 
92 	/* Fill in the MAC-level header (if not already set) */
93 	if (!card->mac_addr[0]) {
94 		for (i = 0; i < ETH_ALEN - sizeof(ulong); i++)
95 			dev->dev_addr[i] = 0xfc;
96 		if ((in_dev = dev->ip_ptr) != NULL) {
97 			struct in_ifaddr *ifa = in_dev->ifa_list;
98 			if (ifa != NULL)
99 				memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ulong)), &ifa->ifa_local, sizeof(ulong));
100 		}
101 	} else
102 		memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN);
103 
104 	return (0);
105 }				/* net_open */
106 
107 /*******************************************/
108 /* flush the currently occupied tx-buffers */
109 /* must only be called when device closed  */
110 /*******************************************/
111 static void
flush_tx_buffers(struct net_local * nl)112 flush_tx_buffers(struct net_local *nl)
113 {
114 
115 	while (nl->sk_count) {
116 		dev_kfree_skb(nl->skbs[nl->out_idx++]);		/* free skb */
117 		if (nl->out_idx >= MAX_SKB_BUFFERS)
118 			nl->out_idx = 0;	/* wrap around */
119 		nl->sk_count--;
120 	}
121 }				/* flush_tx_buffers */
122 
123 
124 /*********************************************************************/
125 /* close/decativate the device. The device is not removed, but only  */
126 /* deactivated.                                                      */
127 /*********************************************************************/
128 static int
net_close(struct net_device * dev)129 net_close(struct net_device *dev)
130 {
131 
132 	netif_stop_queue(dev);	/* disable queueing */
133 
134 	if (((struct net_local *) dev)->is_open)
135 		MOD_DEC_USE_COUNT;	/* adjust module counter */
136 	((struct net_local *) dev)->is_open = 0;
137 	flush_tx_buffers((struct net_local *) dev);
138 
139 	return (0);		/* success */
140 }				/* net_close */
141 
142 /************************************/
143 /* send a packet on this interface. */
144 /* new style for kernel >= 2.3.33   */
145 /************************************/
146 static int
net_send_packet(struct sk_buff * skb,struct net_device * dev)147 net_send_packet(struct sk_buff *skb, struct net_device *dev)
148 {
149 	struct net_local *lp = (struct net_local *) dev;
150 
151 	spin_lock_irq(&lp->lock);
152 
153 	lp->skbs[lp->in_idx++] = skb;	/* add to buffer list */
154 	if (lp->in_idx >= MAX_SKB_BUFFERS)
155 		lp->in_idx = 0;	/* wrap around */
156 	lp->sk_count++;		/* adjust counter */
157 	dev->trans_start = jiffies;
158 
159 	/* If we just used up the very last entry in the
160 	 * TX ring on this device, tell the queueing
161 	 * layer to send no more.
162 	 */
163 	if (lp->sk_count >= MAX_SKB_BUFFERS)
164 		netif_stop_queue(dev);
165 
166 	/* When the TX completion hw interrupt arrives, this
167 	 * is when the transmit statistics are updated.
168 	 */
169 
170 	spin_unlock_irq(&lp->lock);
171 
172 	if (lp->sk_count <= 3) {
173 		queue_task(&((hysdn_card *) dev->priv)->irq_queue, &tq_immediate);
174 		mark_bh(IMMEDIATE_BH);
175 	}
176 	return (0);		/* success */
177 }				/* net_send_packet */
178 
179 
180 
181 /***********************************************************************/
182 /* acknowlegde a packet send. The network layer will be informed about */
183 /* completion                                                          */
184 /***********************************************************************/
185 void
hysdn_tx_netack(hysdn_card * card)186 hysdn_tx_netack(hysdn_card * card)
187 {
188 	struct net_local *lp = card->netif;
189 
190 	if (!lp)
191 		return;		/* non existing device */
192 
193 
194 	if (!lp->sk_count)
195 		return;		/* error condition */
196 
197 	lp->stats.tx_packets++;
198 	lp->stats.tx_bytes += lp->skbs[lp->out_idx]->len;
199 
200 	dev_kfree_skb(lp->skbs[lp->out_idx++]);		/* free skb */
201 	if (lp->out_idx >= MAX_SKB_BUFFERS)
202 		lp->out_idx = 0;	/* wrap around */
203 
204 	if (lp->sk_count-- == MAX_SKB_BUFFERS)	/* dec usage count */
205 		netif_start_queue((struct net_device *) lp);
206 }				/* hysdn_tx_netack */
207 
208 /*****************************************************/
209 /* we got a packet from the network, go and queue it */
210 /*****************************************************/
211 void
hysdn_rx_netpkt(hysdn_card * card,uchar * buf,word len)212 hysdn_rx_netpkt(hysdn_card * card, uchar * buf, word len)
213 {
214 	struct net_local *lp = card->netif;
215 	struct sk_buff *skb;
216 
217 	if (!lp)
218 		return;		/* non existing device */
219 
220 	lp->stats.rx_bytes += len;
221 
222 	skb = dev_alloc_skb(len);
223 	if (skb == NULL) {
224 		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
225 		       lp->netdev.name);
226 		lp->stats.rx_dropped++;
227 		return;
228 	}
229 	skb->dev = &lp->netdev;
230 
231 	/* copy the data */
232 	memcpy(skb_put(skb, len), buf, len);
233 
234 	/* determine the used protocol */
235 	skb->protocol = eth_type_trans(skb, &lp->netdev);
236 
237 	netif_rx(skb);
238 	lp->stats.rx_packets++;	/* adjust packet count */
239 
240 }				/* hysdn_rx_netpkt */
241 
242 /*****************************************************/
243 /* return the pointer to a network packet to be send */
244 /*****************************************************/
245 struct sk_buff *
hysdn_tx_netget(hysdn_card * card)246 hysdn_tx_netget(hysdn_card * card)
247 {
248 	struct net_local *lp = card->netif;
249 
250 	if (!lp)
251 		return (NULL);	/* non existing device */
252 
253 	if (!lp->sk_count)
254 		return (NULL);	/* nothing available */
255 
256 	return (lp->skbs[lp->out_idx]);		/* next packet to send */
257 }				/* hysdn_tx_netget */
258 
259 
260 /*******************************************/
261 /* init function called by register device */
262 /*******************************************/
263 static int
net_init(struct net_device * dev)264 net_init(struct net_device *dev)
265 {
266 	/* setup the function table */
267 	dev->open = net_open;
268 	dev->stop = net_close;
269 	dev->hard_start_xmit = net_send_packet;
270 	dev->get_stats = net_get_stats;
271 
272 	/* Fill in the fields of the device structure with ethernet values. */
273 	ether_setup(dev);
274 
275 	return (0);		/* success */
276 }				/* net_init */
277 
278 /*****************************************************************************/
279 /* hysdn_net_create creates a new net device for the given card. If a device */
280 /* already exists, it will be deleted and created a new one. The return value */
281 /* 0 announces success, else a negative error code will be returned.         */
282 /*****************************************************************************/
283 int
hysdn_net_create(hysdn_card * card)284 hysdn_net_create(hysdn_card * card)
285 {
286 	struct net_device *dev;
287 	int i;
288 	if(!card) {
289 		printk(KERN_WARNING "No card-pt in hysdn_net_create!\n");
290 		return (-ENOMEM);
291 	}
292 	hysdn_net_release(card);	/* release an existing net device */
293 	if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) {
294 		printk(KERN_WARNING "HYSDN: unable to allocate mem\n");
295 		return (-ENOMEM);
296 	}
297 	memset(dev, 0, sizeof(struct net_local));	/* clean the structure */
298 
299 	spin_lock_init(&((struct net_local *) dev)->lock);
300 
301 	/* initialise necessary or informing fields */
302 	dev->base_addr = card->iobase;	/* IO address */
303 	dev->irq = card->irq;	/* irq */
304 	dev->init = net_init;	/* the init function of the device */
305 	if(dev->name) {
306 		strcpy(dev->name, ((struct net_local *) dev)->dev_name);
307 	}
308 	if ((i = register_netdev(dev))) {
309 		printk(KERN_WARNING "HYSDN: unable to create network device\n");
310 		kfree(dev);
311 		return (i);
312 	}
313 	dev->priv = card;	/* remember pointer to own data structure */
314 	card->netif = dev;	/* setup the local pointer */
315 
316 	if (card->debug_flags & LOG_NET_INIT)
317 		hysdn_addlog(card, "network device created");
318 	return (0);		/* and return success */
319 }				/* hysdn_net_create */
320 
321 /***************************************************************************/
322 /* hysdn_net_release deletes the net device for the given card. The return */
323 /* value 0 announces success, else a negative error code will be returned. */
324 /***************************************************************************/
325 int
hysdn_net_release(hysdn_card * card)326 hysdn_net_release(hysdn_card * card)
327 {
328 	struct net_device *dev = card->netif;
329 
330 	if (!dev)
331 		return (0);	/* non existing */
332 
333 	card->netif = NULL;	/* clear out pointer */
334 	dev->stop(dev);		/* close the device */
335 
336 	flush_tx_buffers((struct net_local *) dev);	/* empty buffers */
337 
338 	unregister_netdev(dev);	/* release the device */
339 	kfree(dev);		/* release the memory allocated */
340 	if (card->debug_flags & LOG_NET_INIT)
341 		hysdn_addlog(card, "network device deleted");
342 
343 	return (0);		/* always successful */
344 }				/* hysdn_net_release */
345 
346 /*****************************************************************************/
347 /* hysdn_net_getname returns a pointer to the name of the network interface. */
348 /* if the interface is not existing, a "-" is returned.                      */
349 /*****************************************************************************/
350 char *
hysdn_net_getname(hysdn_card * card)351 hysdn_net_getname(hysdn_card * card)
352 {
353 	struct net_device *dev = card->netif;
354 
355 	if (!dev)
356 		return ("-");	/* non existing */
357 
358 	return (dev->name);
359 }				/* hysdn_net_getname */
360