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