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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [wan/] [hdlc_x25.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Generic HDLC support routines for Linux
3
 * X.25 support
4
 *
5
 * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of version 2 of the GNU General Public License
9
 * as published by the Free Software Foundation.
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/kernel.h>
14
#include <linux/slab.h>
15
#include <linux/poll.h>
16
#include <linux/errno.h>
17
#include <linux/if_arp.h>
18
#include <linux/init.h>
19
#include <linux/skbuff.h>
20
#include <linux/pkt_sched.h>
21
#include <linux/inetdevice.h>
22
#include <linux/lapb.h>
23
#include <linux/rtnetlink.h>
24
#include <linux/hdlc.h>
25
 
26
#include <net/x25device.h>
27
 
28
static int x25_ioctl(struct net_device *dev, struct ifreq *ifr);
29
 
30
/* These functions are callbacks called by LAPB layer */
31
 
32
static void x25_connect_disconnect(struct net_device *dev, int reason, int code)
33
{
34
        struct sk_buff *skb;
35
        unsigned char *ptr;
36
 
37
        if ((skb = dev_alloc_skb(1)) == NULL) {
38
                printk(KERN_ERR "%s: out of memory\n", dev->name);
39
                return;
40
        }
41
 
42
        ptr = skb_put(skb, 1);
43
        *ptr = code;
44
 
45
        skb->protocol = x25_type_trans(skb, dev);
46
        netif_rx(skb);
47
}
48
 
49
 
50
 
51
static void x25_connected(struct net_device *dev, int reason)
52
{
53
        x25_connect_disconnect(dev, reason, 1);
54
}
55
 
56
 
57
 
58
static void x25_disconnected(struct net_device *dev, int reason)
59
{
60
        x25_connect_disconnect(dev, reason, 2);
61
}
62
 
63
 
64
 
65
static int x25_data_indication(struct net_device *dev, struct sk_buff *skb)
66
{
67
        unsigned char *ptr;
68
 
69
        skb_push(skb, 1);
70
 
71
        if (skb_cow(skb, 1))
72
                return NET_RX_DROP;
73
 
74
        ptr  = skb->data;
75
        *ptr = 0;
76
 
77
        skb->protocol = x25_type_trans(skb, dev);
78
        return netif_rx(skb);
79
}
80
 
81
 
82
 
83
static void x25_data_transmit(struct net_device *dev, struct sk_buff *skb)
84
{
85
        hdlc_device *hdlc = dev_to_hdlc(dev);
86
        hdlc->xmit(skb, dev); /* Ignore return value :-( */
87
}
88
 
89
 
90
 
91
static int x25_xmit(struct sk_buff *skb, struct net_device *dev)
92
{
93
        int result;
94
 
95
 
96
        /* X.25 to LAPB */
97
        switch (skb->data[0]) {
98
        case 0:          /* Data to be transmitted */
99
                skb_pull(skb, 1);
100
                if ((result = lapb_data_request(dev, skb)) != LAPB_OK)
101
                        dev_kfree_skb(skb);
102
                return 0;
103
 
104
        case 1:
105
                if ((result = lapb_connect_request(dev))!= LAPB_OK) {
106
                        if (result == LAPB_CONNECTED)
107
                                /* Send connect confirm. msg to level 3 */
108
                                x25_connected(dev, 0);
109
                        else
110
                                printk(KERN_ERR "%s: LAPB connect request "
111
                                       "failed, error code = %i\n",
112
                                       dev->name, result);
113
                }
114
                break;
115
 
116
        case 2:
117
                if ((result = lapb_disconnect_request(dev)) != LAPB_OK) {
118
                        if (result == LAPB_NOTCONNECTED)
119
                                /* Send disconnect confirm. msg to level 3 */
120
                                x25_disconnected(dev, 0);
121
                        else
122
                                printk(KERN_ERR "%s: LAPB disconnect request "
123
                                       "failed, error code = %i\n",
124
                                       dev->name, result);
125
                }
126
                break;
127
 
128
        default:                /* to be defined */
129
                break;
130
        }
131
 
132
        dev_kfree_skb(skb);
133
        return 0;
134
}
135
 
136
 
137
 
138
static int x25_open(struct net_device *dev)
139
{
140
        struct lapb_register_struct cb;
141
        int result;
142
 
143
        cb.connect_confirmation = x25_connected;
144
        cb.connect_indication = x25_connected;
145
        cb.disconnect_confirmation = x25_disconnected;
146
        cb.disconnect_indication = x25_disconnected;
147
        cb.data_indication = x25_data_indication;
148
        cb.data_transmit = x25_data_transmit;
149
 
150
        result = lapb_register(dev, &cb);
151
        if (result != LAPB_OK)
152
                return result;
153
        return 0;
154
}
155
 
156
 
157
 
158
static void x25_close(struct net_device *dev)
159
{
160
        lapb_unregister(dev);
161
}
162
 
163
 
164
 
165
static int x25_rx(struct sk_buff *skb)
166
{
167
        struct hdlc_device_desc *desc = dev_to_desc(skb->dev);
168
 
169
        if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) {
170
                desc->stats.rx_dropped++;
171
                return NET_RX_DROP;
172
        }
173
 
174
        if (lapb_data_received(skb->dev, skb) == LAPB_OK)
175
                return NET_RX_SUCCESS;
176
 
177
        desc->stats.rx_errors++;
178
        dev_kfree_skb_any(skb);
179
        return NET_RX_DROP;
180
}
181
 
182
 
183
static struct hdlc_proto proto = {
184
        .open           = x25_open,
185
        .close          = x25_close,
186
        .ioctl          = x25_ioctl,
187
        .module         = THIS_MODULE,
188
};
189
 
190
 
191
static int x25_ioctl(struct net_device *dev, struct ifreq *ifr)
192
{
193
        hdlc_device *hdlc = dev_to_hdlc(dev);
194
        int result;
195
 
196
        switch (ifr->ifr_settings.type) {
197
        case IF_GET_PROTO:
198
                if (dev_to_hdlc(dev)->proto != &proto)
199
                        return -EINVAL;
200
                ifr->ifr_settings.type = IF_PROTO_X25;
201
                return 0; /* return protocol only, no settable parameters */
202
 
203
        case IF_PROTO_X25:
204
                if(!capable(CAP_NET_ADMIN))
205
                        return -EPERM;
206
 
207
                if(dev->flags & IFF_UP)
208
                        return -EBUSY;
209
 
210
                result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
211
                if (result)
212
                        return result;
213
 
214
                if ((result = attach_hdlc_protocol(dev, &proto,
215
                                                   x25_rx, 0)) != 0)
216
                        return result;
217
                dev->hard_start_xmit = x25_xmit;
218
                dev->type = ARPHRD_X25;
219
                netif_dormant_off(dev);
220
                return 0;
221
        }
222
 
223
        return -EINVAL;
224
}
225
 
226
 
227
static int __init mod_init(void)
228
{
229
        register_hdlc_protocol(&proto);
230
        return 0;
231
}
232
 
233
 
234
 
235
static void __exit mod_exit(void)
236
{
237
        unregister_hdlc_protocol(&proto);
238
}
239
 
240
 
241
module_init(mod_init);
242
module_exit(mod_exit);
243
 
244
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
245
MODULE_DESCRIPTION("X.25 protocol support for generic HDLC");
246
MODULE_LICENSE("GPL v2");

powered by: WebSVN 2.1.0

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