OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [net/] [irda/] [irlan/] [irlan_eth.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*********************************************************************
2
 *
3
 * Filename:      irlan_eth.c
4
 * Version:
5
 * Description:
6
 * Status:        Experimental.
7
 * Author:        Dag Brattli <dagb@cs.uit.no>
8
 * Created at:    Thu Oct 15 08:37:58 1998
9
 * Modified at:   Tue Mar 21 09:06:41 2000
10
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
11
 * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
12
 *                slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
13
 *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
14
 *
15
 *     Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
16
 *
17
 *     This program is free software; you can redistribute it and/or
18
 *     modify it under the terms of the GNU General Public License as
19
 *     published by the Free Software Foundation; either version 2 of
20
 *     the License, or (at your option) any later version.
21
 *
22
 *     Neither Dag Brattli nor University of Tromsø admit liability nor
23
 *     provide warranty for any of this software. This material is
24
 *     provided "AS-IS" and at no charge.
25
 *
26
 ********************************************************************/
27
 
28
#include <linux/netdevice.h>
29
#include <linux/etherdevice.h>
30
#include <linux/inetdevice.h>
31
#include <linux/if_arp.h>
32
#include <linux/module.h>
33
#include <net/arp.h>
34
 
35
#include <net/irda/irda.h>
36
#include <net/irda/irmod.h>
37
#include <net/irda/irlan_common.h>
38
#include <net/irda/irlan_client.h>
39
#include <net/irda/irlan_event.h>
40
#include <net/irda/irlan_eth.h>
41
 
42
static int  irlan_eth_open(struct net_device *dev);
43
static int  irlan_eth_close(struct net_device *dev);
44
static int  irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev);
45
static void irlan_eth_set_multicast_list( struct net_device *dev);
46
static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev);
47
 
48
/*
49
 * Function irlan_eth_setup (dev)
50
 *
51
 *    The network device initialization function.
52
 *
53
 */
54
static void irlan_eth_setup(struct net_device *dev)
55
{
56
        dev->open               = irlan_eth_open;
57
        dev->stop               = irlan_eth_close;
58
        dev->hard_start_xmit    = irlan_eth_xmit;
59
        dev->get_stats          = irlan_eth_get_stats;
60
        dev->set_multicast_list = irlan_eth_set_multicast_list;
61
        dev->destructor         = free_netdev;
62
 
63
        ether_setup(dev);
64
 
65
        /*
66
         * Lets do all queueing in IrTTP instead of this device driver.
67
         * Queueing here as well can introduce some strange latency
68
         * problems, which we will avoid by setting the queue size to 0.
69
         */
70
        /*
71
         * The bugs in IrTTP and IrLAN that created this latency issue
72
         * have now been fixed, and we can propagate flow control properly
73
         * to the network layer. However, this requires a minimal queue of
74
         * packets for the device.
75
         * Without flow control, the Tx Queue is 14 (ttp) + 0 (dev) = 14
76
         * With flow control, the Tx Queue is 7 (ttp) + 4 (dev) = 11
77
         * See irlan_eth_flow_indication()...
78
         * Note : this number was randomly selected and would need to
79
         * be adjusted.
80
         * Jean II */
81
        dev->tx_queue_len = 4;
82
}
83
 
84
/*
85
 * Function alloc_irlandev
86
 *
87
 *    Allocate network device and control block
88
 *
89
 */
90
struct net_device *alloc_irlandev(const char *name)
91
{
92
        return alloc_netdev(sizeof(struct irlan_cb), name,
93
                            irlan_eth_setup);
94
}
95
 
96
/*
97
 * Function irlan_eth_open (dev)
98
 *
99
 *    Network device has been opened by user
100
 *
101
 */
102
static int irlan_eth_open(struct net_device *dev)
103
{
104
        struct irlan_cb *self = netdev_priv(dev);
105
 
106
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
107
 
108
        /* Ready to play! */
109
        netif_stop_queue(dev); /* Wait until data link is ready */
110
 
111
        /* We are now open, so time to do some work */
112
        self->disconnect_reason = 0;
113
        irlan_client_wakeup(self, self->saddr, self->daddr);
114
 
115
        /* Make sure we have a hardware address before we return,
116
           so DHCP clients gets happy */
117
        return wait_event_interruptible(self->open_wait,
118
                                        !self->tsap_data->connected);
119
}
120
 
121
/*
122
 * Function irlan_eth_close (dev)
123
 *
124
 *    Stop the ether network device, his function will usually be called by
125
 *    ifconfig down. We should now disconnect the link, We start the
126
 *    close timer, so that the instance will be removed if we are unable
127
 *    to discover the remote device after the disconnect.
128
 */
129
static int irlan_eth_close(struct net_device *dev)
130
{
131
        struct irlan_cb *self = netdev_priv(dev);
132
 
133
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
134
 
135
        /* Stop device */
136
        netif_stop_queue(dev);
137
 
138
        irlan_close_data_channel(self);
139
        irlan_close_tsaps(self);
140
 
141
        irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
142
        irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
143
 
144
        /* Remove frames queued on the control channel */
145
        skb_queue_purge(&self->client.txq);
146
 
147
        self->client.tx_busy = 0;
148
 
149
        return 0;
150
}
151
 
152
/*
153
 * Function irlan_eth_tx (skb)
154
 *
155
 *    Transmits ethernet frames over IrDA link.
156
 *
157
 */
158
static int irlan_eth_xmit(struct sk_buff *skb, struct net_device *dev)
159
{
160
        struct irlan_cb *self = netdev_priv(dev);
161
        int ret;
162
 
163
        /* skb headroom large enough to contain all IrDA-headers? */
164
        if ((skb_headroom(skb) < self->max_header_size) || (skb_shared(skb))) {
165
                struct sk_buff *new_skb =
166
                        skb_realloc_headroom(skb, self->max_header_size);
167
 
168
                /*  We have to free the original skb anyway */
169
                dev_kfree_skb(skb);
170
 
171
                /* Did the realloc succeed? */
172
                if (new_skb == NULL)
173
                        return 0;
174
 
175
                /* Use the new skb instead */
176
                skb = new_skb;
177
        }
178
 
179
        dev->trans_start = jiffies;
180
 
181
        /* Now queue the packet in the transport layer */
182
        if (self->use_udata)
183
                ret = irttp_udata_request(self->tsap_data, skb);
184
        else
185
                ret = irttp_data_request(self->tsap_data, skb);
186
 
187
        if (ret < 0) {
188
                /*
189
                 * IrTTPs tx queue is full, so we just have to
190
                 * drop the frame! You might think that we should
191
                 * just return -1 and don't deallocate the frame,
192
                 * but that is dangerous since it's possible that
193
                 * we have replaced the original skb with a new
194
                 * one with larger headroom, and that would really
195
                 * confuse do_dev_queue_xmit() in dev.c! I have
196
                 * tried :-) DB
197
                 */
198
                /* irttp_data_request already free the packet */
199
                self->stats.tx_dropped++;
200
        } else {
201
                self->stats.tx_packets++;
202
                self->stats.tx_bytes += skb->len;
203
        }
204
 
205
        return 0;
206
}
207
 
208
/*
209
 * Function irlan_eth_receive (handle, skb)
210
 *
211
 *    This function gets the data that is received on the data channel
212
 *
213
 */
214
int irlan_eth_receive(void *instance, void *sap, struct sk_buff *skb)
215
{
216
        struct irlan_cb *self = instance;
217
 
218
        if (skb == NULL) {
219
                ++self->stats.rx_dropped;
220
                return 0;
221
        }
222
        if (skb->len < ETH_HLEN) {
223
                IRDA_DEBUG(0, "%s() : IrLAN frame too short (%d)\n",
224
                           __FUNCTION__, skb->len);
225
                ++self->stats.rx_dropped;
226
                dev_kfree_skb(skb);
227
                return 0;
228
        }
229
 
230
        /*
231
         * Adopt this frame! Important to set all these fields since they
232
         * might have been previously set by the low level IrDA network
233
         * device driver
234
         */
235
        skb->protocol = eth_type_trans(skb, self->dev); /* Remove eth header */
236
 
237
        self->stats.rx_packets++;
238
        self->stats.rx_bytes += skb->len;
239
 
240
        netif_rx(skb);   /* Eat it! */
241
 
242
        return 0;
243
}
244
 
245
/*
246
 * Function irlan_eth_flow (status)
247
 *
248
 *    Do flow control between IP/Ethernet and IrLAN/IrTTP. This is done by
249
 *    controlling the queue stop/start.
250
 *
251
 * The IrDA link layer has the advantage to have flow control, and
252
 * IrTTP now properly handles that. Flow controlling the higher layers
253
 * prevent us to drop Tx packets in here (up to 15% for a TCP socket,
254
 * more for UDP socket).
255
 * Also, this allow us to reduce the overall transmit queue, which means
256
 * less latency in case of mixed traffic.
257
 * Jean II
258
 */
259
void irlan_eth_flow_indication(void *instance, void *sap, LOCAL_FLOW flow)
260
{
261
        struct irlan_cb *self;
262
        struct net_device *dev;
263
 
264
        self = (struct irlan_cb *) instance;
265
 
266
        IRDA_ASSERT(self != NULL, return;);
267
        IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
268
 
269
        dev = self->dev;
270
 
271
        IRDA_ASSERT(dev != NULL, return;);
272
 
273
        IRDA_DEBUG(0, "%s() : flow %s ; running %d\n", __FUNCTION__,
274
                   flow == FLOW_STOP ? "FLOW_STOP" : "FLOW_START",
275
                   netif_running(dev));
276
 
277
        switch (flow) {
278
        case FLOW_STOP:
279
                /* IrTTP is full, stop higher layers */
280
                netif_stop_queue(dev);
281
                break;
282
        case FLOW_START:
283
        default:
284
                /* Tell upper layers that its time to transmit frames again */
285
                /* Schedule network layer */
286
                netif_wake_queue(dev);
287
                break;
288
        }
289
}
290
 
291
/*
292
 * Function irlan_etc_send_gratuitous_arp (dev)
293
 *
294
 *    Send gratuitous ARP to announce that we have changed
295
 *    hardware address, so that all peers updates their ARP tables
296
 */
297
void irlan_eth_send_gratuitous_arp(struct net_device *dev)
298
{
299
#ifdef CONFIG_INET
300
        struct in_device *in_dev;
301
 
302
        /*
303
         * When we get a new MAC address do a gratuitous ARP. This
304
         * is useful if we have changed access points on the same
305
         * subnet.
306
         */
307
        IRDA_DEBUG(4, "IrLAN: Sending gratuitous ARP\n");
308
        rcu_read_lock();
309
        in_dev = __in_dev_get_rcu(dev);
310
        if (in_dev == NULL)
311
                goto out;
312
        if (in_dev->ifa_list)
313
 
314
        arp_send(ARPOP_REQUEST, ETH_P_ARP,
315
                 in_dev->ifa_list->ifa_address,
316
                 dev,
317
                 in_dev->ifa_list->ifa_address,
318
                 NULL, dev->dev_addr, NULL);
319
out:
320
        rcu_read_unlock();
321
#endif /* CONFIG_INET */
322
}
323
 
324
/*
325
 * Function set_multicast_list (dev)
326
 *
327
 *    Configure the filtering of the device
328
 *
329
 */
330
#define HW_MAX_ADDRS 4 /* Must query to get it! */
331
static void irlan_eth_set_multicast_list(struct net_device *dev)
332
{
333
        struct irlan_cb *self = netdev_priv(dev);
334
 
335
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
336
 
337
        /* Check if data channel has been connected yet */
338
        if (self->client.state != IRLAN_DATA) {
339
                IRDA_DEBUG(1, "%s(), delaying!\n", __FUNCTION__ );
340
                return;
341
        }
342
 
343
        if (dev->flags & IFF_PROMISC) {
344
                /* Enable promiscuous mode */
345
                IRDA_WARNING("Promiscuous mode not implemented by IrLAN!\n");
346
        }
347
        else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > HW_MAX_ADDRS) {
348
                /* Disable promiscuous mode, use normal mode. */
349
                IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
350
                /* hardware_set_filter(NULL); */
351
 
352
                irlan_set_multicast_filter(self, TRUE);
353
        }
354
        else if (dev->mc_count) {
355
                IRDA_DEBUG(4, "%s(), Setting multicast filter\n", __FUNCTION__ );
356
                /* Walk the address list, and load the filter */
357
                /* hardware_set_filter(dev->mc_list); */
358
 
359
                irlan_set_multicast_filter(self, TRUE);
360
        }
361
        else {
362
                IRDA_DEBUG(4, "%s(), Clearing multicast filter\n", __FUNCTION__ );
363
                irlan_set_multicast_filter(self, FALSE);
364
        }
365
 
366
        if (dev->flags & IFF_BROADCAST)
367
                irlan_set_broadcast_filter(self, TRUE);
368
        else
369
                irlan_set_broadcast_filter(self, FALSE);
370
}
371
 
372
/*
373
 * Function irlan_get_stats (dev)
374
 *
375
 *    Get the current statistics for this device
376
 *
377
 */
378
static struct net_device_stats *irlan_eth_get_stats(struct net_device *dev)
379
{
380
        struct irlan_cb *self = netdev_priv(dev);
381
 
382
        return &self->stats;
383
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.