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

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [lapb/] [lapb_iface.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 *      LAPB release 002
3
 *
4
 *      This code REQUIRES 2.1.15 or higher/ NET3.038
5
 *
6
 *      This module:
7
 *              This module is free software; you can redistribute it and/or
8
 *              modify it under the terms of the GNU General Public License
9
 *              as published by the Free Software Foundation; either version
10
 *              2 of the License, or (at your option) any later version.
11
 *
12
 *      History
13
 *      LAPB 001        Jonathan Naylor Started Coding
14
 *      LAPB 002        Jonathan Naylor New timer architecture.
15
 *      2000-10-29      Henner Eisen    lapb_data_indication() return status.
16
 */
17
 
18
#include <linux/module.h>
19
#include <linux/errno.h>
20
#include <linux/types.h>
21
#include <linux/socket.h>
22
#include <linux/in.h>
23
#include <linux/kernel.h>
24
#include <linux/jiffies.h>
25
#include <linux/timer.h>
26
#include <linux/string.h>
27
#include <linux/sockios.h>
28
#include <linux/net.h>
29
#include <linux/inet.h>
30
#include <linux/if_arp.h>
31
#include <linux/skbuff.h>
32
#include <net/sock.h>
33
#include <asm/uaccess.h>
34
#include <asm/system.h>
35
#include <linux/fcntl.h>
36
#include <linux/mm.h>
37
#include <linux/interrupt.h>
38
#include <linux/stat.h>
39
#include <linux/init.h>
40
#include <net/lapb.h>
41
 
42
static struct list_head lapb_list = LIST_HEAD_INIT(lapb_list);
43
static DEFINE_RWLOCK(lapb_list_lock);
44
 
45
/*
46
 *      Free an allocated lapb control block.
47
 */
48
static void lapb_free_cb(struct lapb_cb *lapb)
49
{
50
        kfree(lapb);
51
}
52
 
53
static __inline__ void lapb_hold(struct lapb_cb *lapb)
54
{
55
        atomic_inc(&lapb->refcnt);
56
}
57
 
58
static __inline__ void lapb_put(struct lapb_cb *lapb)
59
{
60
        if (atomic_dec_and_test(&lapb->refcnt))
61
                lapb_free_cb(lapb);
62
}
63
 
64
/*
65
 *      Socket removal during an interrupt is now safe.
66
 */
67
static void __lapb_remove_cb(struct lapb_cb *lapb)
68
{
69
        if (lapb->node.next) {
70
                list_del(&lapb->node);
71
                lapb_put(lapb);
72
        }
73
}
74
 
75
/*
76
 *      Add a socket to the bound sockets list.
77
 */
78
static void __lapb_insert_cb(struct lapb_cb *lapb)
79
{
80
        list_add(&lapb->node, &lapb_list);
81
        lapb_hold(lapb);
82
}
83
 
84
static struct lapb_cb *__lapb_devtostruct(struct net_device *dev)
85
{
86
        struct list_head *entry;
87
        struct lapb_cb *lapb, *use = NULL;
88
 
89
        list_for_each(entry, &lapb_list) {
90
                lapb = list_entry(entry, struct lapb_cb, node);
91
                if (lapb->dev == dev) {
92
                        use = lapb;
93
                        break;
94
                }
95
        }
96
 
97
        if (use)
98
                lapb_hold(use);
99
 
100
        return use;
101
}
102
 
103
static struct lapb_cb *lapb_devtostruct(struct net_device *dev)
104
{
105
        struct lapb_cb *rc;
106
 
107
        read_lock_bh(&lapb_list_lock);
108
        rc = __lapb_devtostruct(dev);
109
        read_unlock_bh(&lapb_list_lock);
110
 
111
        return rc;
112
}
113
/*
114
 *      Create an empty LAPB control block.
115
 */
116
static struct lapb_cb *lapb_create_cb(void)
117
{
118
        struct lapb_cb *lapb = kzalloc(sizeof(*lapb), GFP_ATOMIC);
119
 
120
 
121
        if (!lapb)
122
                goto out;
123
 
124
        skb_queue_head_init(&lapb->write_queue);
125
        skb_queue_head_init(&lapb->ack_queue);
126
 
127
        init_timer(&lapb->t1timer);
128
        init_timer(&lapb->t2timer);
129
 
130
        lapb->t1      = LAPB_DEFAULT_T1;
131
        lapb->t2      = LAPB_DEFAULT_T2;
132
        lapb->n2      = LAPB_DEFAULT_N2;
133
        lapb->mode    = LAPB_DEFAULT_MODE;
134
        lapb->window  = LAPB_DEFAULT_WINDOW;
135
        lapb->state   = LAPB_STATE_0;
136
        atomic_set(&lapb->refcnt, 1);
137
out:
138
        return lapb;
139
}
140
 
141
int lapb_register(struct net_device *dev, struct lapb_register_struct *callbacks)
142
{
143
        struct lapb_cb *lapb;
144
        int rc = LAPB_BADTOKEN;
145
 
146
        write_lock_bh(&lapb_list_lock);
147
 
148
        lapb = __lapb_devtostruct(dev);
149
        if (lapb) {
150
                lapb_put(lapb);
151
                goto out;
152
        }
153
 
154
        lapb = lapb_create_cb();
155
        rc = LAPB_NOMEM;
156
        if (!lapb)
157
                goto out;
158
 
159
        lapb->dev       = dev;
160
        lapb->callbacks = *callbacks;
161
 
162
        __lapb_insert_cb(lapb);
163
 
164
        lapb_start_t1timer(lapb);
165
 
166
        rc = LAPB_OK;
167
out:
168
        write_unlock_bh(&lapb_list_lock);
169
        return rc;
170
}
171
 
172
int lapb_unregister(struct net_device *dev)
173
{
174
        struct lapb_cb *lapb;
175
        int rc = LAPB_BADTOKEN;
176
 
177
        write_lock_bh(&lapb_list_lock);
178
        lapb = __lapb_devtostruct(dev);
179
        if (!lapb)
180
                goto out;
181
 
182
        lapb_stop_t1timer(lapb);
183
        lapb_stop_t2timer(lapb);
184
 
185
        lapb_clear_queues(lapb);
186
 
187
        __lapb_remove_cb(lapb);
188
 
189
        lapb_put(lapb);
190
        rc = LAPB_OK;
191
out:
192
        write_unlock_bh(&lapb_list_lock);
193
        return rc;
194
}
195
 
196
int lapb_getparms(struct net_device *dev, struct lapb_parms_struct *parms)
197
{
198
        int rc = LAPB_BADTOKEN;
199
        struct lapb_cb *lapb = lapb_devtostruct(dev);
200
 
201
        if (!lapb)
202
                goto out;
203
 
204
        parms->t1      = lapb->t1 / HZ;
205
        parms->t2      = lapb->t2 / HZ;
206
        parms->n2      = lapb->n2;
207
        parms->n2count = lapb->n2count;
208
        parms->state   = lapb->state;
209
        parms->window  = lapb->window;
210
        parms->mode    = lapb->mode;
211
 
212
        if (!timer_pending(&lapb->t1timer))
213
                parms->t1timer = 0;
214
        else
215
                parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
216
 
217
        if (!timer_pending(&lapb->t2timer))
218
                parms->t2timer = 0;
219
        else
220
                parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
221
 
222
        lapb_put(lapb);
223
        rc = LAPB_OK;
224
out:
225
        return rc;
226
}
227
 
228
int lapb_setparms(struct net_device *dev, struct lapb_parms_struct *parms)
229
{
230
        int rc = LAPB_BADTOKEN;
231
        struct lapb_cb *lapb = lapb_devtostruct(dev);
232
 
233
        if (!lapb)
234
                goto out;
235
 
236
        rc = LAPB_INVALUE;
237
        if (parms->t1 < 1 || parms->t2 < 1 || parms->n2 < 1)
238
                goto out_put;
239
 
240
        if (lapb->state == LAPB_STATE_0) {
241
                if (parms->mode & LAPB_EXTENDED) {
242
                        if (parms->window < 1 || parms->window > 127)
243
                                goto out_put;
244
                } else {
245
                        if (parms->window < 1 || parms->window > 7)
246
                                goto out_put;
247
                }
248
                lapb->mode    = parms->mode;
249
                lapb->window  = parms->window;
250
        }
251
 
252
        lapb->t1    = parms->t1 * HZ;
253
        lapb->t2    = parms->t2 * HZ;
254
        lapb->n2    = parms->n2;
255
 
256
        rc = LAPB_OK;
257
out_put:
258
        lapb_put(lapb);
259
out:
260
        return rc;
261
}
262
 
263
int lapb_connect_request(struct net_device *dev)
264
{
265
        struct lapb_cb *lapb = lapb_devtostruct(dev);
266
        int rc = LAPB_BADTOKEN;
267
 
268
        if (!lapb)
269
                goto out;
270
 
271
        rc = LAPB_OK;
272
        if (lapb->state == LAPB_STATE_1)
273
                goto out_put;
274
 
275
        rc = LAPB_CONNECTED;
276
        if (lapb->state == LAPB_STATE_3 || lapb->state == LAPB_STATE_4)
277
                goto out_put;
278
 
279
        lapb_establish_data_link(lapb);
280
 
281
#if LAPB_DEBUG > 0
282
        printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->dev);
283
#endif
284
        lapb->state = LAPB_STATE_1;
285
 
286
        rc = LAPB_OK;
287
out_put:
288
        lapb_put(lapb);
289
out:
290
        return rc;
291
}
292
 
293
int lapb_disconnect_request(struct net_device *dev)
294
{
295
        struct lapb_cb *lapb = lapb_devtostruct(dev);
296
        int rc = LAPB_BADTOKEN;
297
 
298
        if (!lapb)
299
                goto out;
300
 
301
        switch (lapb->state) {
302
                case LAPB_STATE_0:
303
                        rc = LAPB_NOTCONNECTED;
304
                        goto out_put;
305
 
306
                case LAPB_STATE_1:
307
#if LAPB_DEBUG > 1
308
                        printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->dev);
309
#endif
310
#if LAPB_DEBUG > 0
311
                        printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->dev);
312
#endif
313
                        lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
314
                        lapb->state = LAPB_STATE_0;
315
                        lapb_start_t1timer(lapb);
316
                        rc = LAPB_NOTCONNECTED;
317
                        goto out_put;
318
 
319
                case LAPB_STATE_2:
320
                        rc = LAPB_OK;
321
                        goto out_put;
322
        }
323
 
324
        lapb_clear_queues(lapb);
325
        lapb->n2count = 0;
326
        lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
327
        lapb_start_t1timer(lapb);
328
        lapb_stop_t2timer(lapb);
329
        lapb->state = LAPB_STATE_2;
330
 
331
#if LAPB_DEBUG > 1
332
        printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->dev);
333
#endif
334
#if LAPB_DEBUG > 0
335
        printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->dev);
336
#endif
337
 
338
        rc = LAPB_OK;
339
out_put:
340
        lapb_put(lapb);
341
out:
342
        return rc;
343
}
344
 
345
int lapb_data_request(struct net_device *dev, struct sk_buff *skb)
346
{
347
        struct lapb_cb *lapb = lapb_devtostruct(dev);
348
        int rc = LAPB_BADTOKEN;
349
 
350
        if (!lapb)
351
                goto out;
352
 
353
        rc = LAPB_NOTCONNECTED;
354
        if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
355
                goto out_put;
356
 
357
        skb_queue_tail(&lapb->write_queue, skb);
358
        lapb_kick(lapb);
359
        rc = LAPB_OK;
360
out_put:
361
        lapb_put(lapb);
362
out:
363
        return rc;
364
}
365
 
366
int lapb_data_received(struct net_device *dev, struct sk_buff *skb)
367
{
368
        struct lapb_cb *lapb = lapb_devtostruct(dev);
369
        int rc = LAPB_BADTOKEN;
370
 
371
        if (lapb) {
372
                lapb_data_input(lapb, skb);
373
                lapb_put(lapb);
374
                rc = LAPB_OK;
375
        }
376
 
377
        return rc;
378
}
379
 
380
void lapb_connect_confirmation(struct lapb_cb *lapb, int reason)
381
{
382
        if (lapb->callbacks.connect_confirmation)
383
                lapb->callbacks.connect_confirmation(lapb->dev, reason);
384
}
385
 
386
void lapb_connect_indication(struct lapb_cb *lapb, int reason)
387
{
388
        if (lapb->callbacks.connect_indication)
389
                lapb->callbacks.connect_indication(lapb->dev, reason);
390
}
391
 
392
void lapb_disconnect_confirmation(struct lapb_cb *lapb, int reason)
393
{
394
        if (lapb->callbacks.disconnect_confirmation)
395
                lapb->callbacks.disconnect_confirmation(lapb->dev, reason);
396
}
397
 
398
void lapb_disconnect_indication(struct lapb_cb *lapb, int reason)
399
{
400
        if (lapb->callbacks.disconnect_indication)
401
                lapb->callbacks.disconnect_indication(lapb->dev, reason);
402
}
403
 
404
int lapb_data_indication(struct lapb_cb *lapb, struct sk_buff *skb)
405
{
406
        if (lapb->callbacks.data_indication)
407
                return lapb->callbacks.data_indication(lapb->dev, skb);
408
 
409
        kfree_skb(skb);
410
        return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */
411
}
412
 
413
int lapb_data_transmit(struct lapb_cb *lapb, struct sk_buff *skb)
414
{
415
        int used = 0;
416
 
417
        if (lapb->callbacks.data_transmit) {
418
                lapb->callbacks.data_transmit(lapb->dev, skb);
419
                used = 1;
420
        }
421
 
422
        return used;
423
}
424
 
425
EXPORT_SYMBOL(lapb_register);
426
EXPORT_SYMBOL(lapb_unregister);
427
EXPORT_SYMBOL(lapb_getparms);
428
EXPORT_SYMBOL(lapb_setparms);
429
EXPORT_SYMBOL(lapb_connect_request);
430
EXPORT_SYMBOL(lapb_disconnect_request);
431
EXPORT_SYMBOL(lapb_data_request);
432
EXPORT_SYMBOL(lapb_data_received);
433
 
434
static int __init lapb_init(void)
435
{
436
        return 0;
437
}
438
 
439
static void __exit lapb_exit(void)
440
{
441
        WARN_ON(!list_empty(&lapb_list));
442
}
443
 
444
MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
445
MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
446
MODULE_LICENSE("GPL");
447
 
448
module_init(lapb_init);
449
module_exit(lapb_exit);

powered by: WebSVN 2.1.0

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