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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [isdn/] [isdn_x25iface.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/* $Id: isdn_x25iface.c,v 1.1.1.1 2004-04-15 02:03:50 phoenix Exp $
2
 *
3
 * Linux ISDN subsystem, X.25 related functions
4
 *
5
 * This software may be used and distributed according to the terms
6
 * of the GNU General Public License, incorporated herein by reference.
7
 *
8
 * stuff needed to support the Linux X.25 PLP code on top of devices that
9
 * can provide a lab_b service using the concap_proto mechanism.
10
 * This module supports a network interface wich provides lapb_sematics
11
 * -- as defined in ../../Documentation/networking/x25-iface.txt -- to
12
 * the upper layer and assumes that the lower layer provides a reliable
13
 * data link service by means of the concap_device_ops callbacks.
14
 *
15
 * Only protocol specific stuff goes here. Device specific stuff
16
 * goes to another -- device related -- concap_proto support source file.
17
 *
18
 */
19
 
20
/* #include <linux/isdn.h> */
21
#include <linux/netdevice.h>
22
#include <linux/concap.h>
23
#include <linux/wanrouter.h>
24
#include "isdn_x25iface.h"
25
 
26
/* for debugging messages not to cause an oops when device pointer is NULL*/
27
#define MY_DEVNAME(dev)  ( (dev) ? (dev)->name : "DEVICE UNSPECIFIED" )
28
 
29
 
30
typedef struct isdn_x25iface_proto_data {
31
        int magic;
32
        enum wan_states state;
33
        /* Private stuff, not to be accessed via proto_data. We provide the
34
           other storage for the concap_proto instance here as well,
35
           enabling us to allocate both with just one kmalloc(): */
36
        struct concap_proto priv;
37
} ix25_pdata_t;
38
 
39
 
40
 
41
/* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */
42
void isdn_x25iface_proto_del( struct concap_proto * );
43
int isdn_x25iface_proto_close( struct concap_proto * );
44
int isdn_x25iface_proto_restart( struct concap_proto *,
45
                                 struct net_device *,
46
                                 struct concap_device_ops *);
47
int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
48
int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
49
int isdn_x25iface_connect_ind( struct concap_proto * );
50
int isdn_x25iface_disconn_ind( struct concap_proto * );
51
 
52
 
53
static struct concap_proto_ops ix25_pops = {
54
        &isdn_x25iface_proto_new,
55
        &isdn_x25iface_proto_del,
56
        &isdn_x25iface_proto_restart,
57
        &isdn_x25iface_proto_close,
58
        &isdn_x25iface_xmit,
59
        &isdn_x25iface_receive,
60
        &isdn_x25iface_connect_ind,
61
        &isdn_x25iface_disconn_ind
62
};
63
 
64
/* error message helper function */
65
static void illegal_state_warn( unsigned state, unsigned char firstbyte)
66
{
67
        printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
68
                "current state %d\n",firstbyte, state );
69
}
70
 
71
/* check protocol data field for consistency */
72
static int pdata_is_bad( ix25_pdata_t * pda ){
73
 
74
        if( pda  &&  pda -> magic == ISDN_X25IFACE_MAGIC ) return 0;
75
        printk( KERN_WARNING
76
                "isdn_x25iface_xxx: illegal pointer to proto data\n" );
77
        return 1;
78
}
79
 
80
/* create a new x25 interface protocol instance
81
 */
82
struct concap_proto * isdn_x25iface_proto_new()
83
{
84
        ix25_pdata_t * tmp = kmalloc(sizeof(ix25_pdata_t),GFP_KERNEL);
85
        IX25DEBUG("isdn_x25iface_proto_new\n");
86
        if( tmp ){
87
                tmp -> magic = ISDN_X25IFACE_MAGIC;
88
                tmp -> state = WAN_UNCONFIGURED;
89
                /* private data space used to hold the concap_proto data.
90
                   Only to be accessed via the returned pointer */
91
                tmp -> priv.dops       = NULL;
92
                tmp -> priv.net_dev    = NULL;
93
                tmp -> priv.pops       = &ix25_pops;
94
                tmp -> priv.flags      = 0;
95
                tmp -> priv.proto_data = tmp;
96
                return( &(tmp -> priv) );
97
        }
98
        return NULL;
99
};
100
 
101
/* close the x25iface encapsulation protocol
102
 */
103
int isdn_x25iface_proto_close(struct concap_proto *cprot){
104
 
105
        ix25_pdata_t *tmp;
106
        int ret = 0;
107
        ulong flags;
108
 
109
        if( ! cprot ){
110
                printk( KERN_ERR "isdn_x25iface_proto_close: "
111
                        "invalid concap_proto pointer\n" );
112
                return -1;
113
        }
114
        IX25DEBUG( "isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot -> net_dev) );
115
        save_flags(flags);
116
        cli();  /* avoid races with incoming events calling pops methods while
117
                 cprot members are inconsistent */
118
        cprot -> dops    = NULL;
119
        cprot -> net_dev = NULL;
120
        tmp = cprot -> proto_data;
121
        if( pdata_is_bad( tmp ) ){
122
                ret = -1;
123
        } else {
124
                tmp -> state = WAN_UNCONFIGURED;
125
        }
126
        restore_flags(flags);
127
 
128
        return ret;
129
}
130
 
131
/* Delete the x25iface encapsulation protocol instance
132
 */
133
void isdn_x25iface_proto_del(struct concap_proto *cprot){
134
 
135
        ix25_pdata_t * tmp;
136
 
137
        IX25DEBUG( "isdn_x25iface_proto_del \n" );
138
        if( ! cprot ){
139
                printk( KERN_ERR "isdn_x25iface_proto_del: "
140
                        "concap_proto pointer is NULL\n" );
141
                return;
142
        }
143
        tmp = cprot -> proto_data;
144
        if( tmp == NULL ){
145
                printk( KERN_ERR "isdn_x25iface_proto_del: inconsistent "
146
                        "proto_data pointer (maybe already deleted?)\n");
147
                return;
148
        }
149
        /* close if the protocol is still open */
150
        if( cprot -> dops ) isdn_x25iface_proto_close(cprot);
151
        /* freeing the storage should be sufficient now. But some additional
152
           settings might help to catch wild pointer bugs */
153
        tmp -> magic = 0;
154
        cprot -> proto_data = NULL;
155
 
156
        kfree( tmp );
157
        return;
158
}
159
 
160
/* (re-)initialize the data structures for x25iface encapsulation
161
 */
162
int isdn_x25iface_proto_restart(struct concap_proto *cprot,
163
                                struct net_device *ndev,
164
                                struct concap_device_ops *dops)
165
{
166
        ix25_pdata_t * pda = cprot -> proto_data ;
167
        ulong flags;
168
 
169
        IX25DEBUG( "isdn_x25iface_proto_restart %s \n", MY_DEVNAME(ndev) );
170
 
171
        if ( pdata_is_bad( pda ) ) return -1;
172
 
173
        if( !( dops  && dops -> data_req && dops -> connect_req
174
               && dops -> disconn_req )  ){
175
                printk( KERN_WARNING "isdn_x25iface_restart: required dops"
176
                        " missing\n" );
177
                isdn_x25iface_proto_close(cprot);
178
                return -1;
179
        }
180
        save_flags(flags);
181
        cli();  /* avoid races with incoming events calling pops methods while
182
                 cprot members are inconsistent */
183
        cprot -> net_dev = ndev;
184
        cprot -> pops = &ix25_pops;
185
        cprot -> dops = dops;
186
        pda -> state = WAN_DISCONNECTED;
187
        restore_flags(flags);
188
        return 0;
189
}
190
 
191
/* deliver a dl_data frame received from i4l HL driver to the network layer
192
 */
193
int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
194
{
195
        IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) );
196
        if ( ( (ix25_pdata_t*) (cprot->proto_data) )
197
             -> state == WAN_CONNECTED ){
198
                skb -> dev = cprot -> net_dev;
199
                skb -> protocol = htons(ETH_P_X25);
200
                skb -> pkt_type = PACKET_HOST;
201
                if( skb_push(skb, 1)){
202
                        skb -> data[0]=0x00;
203
                        skb -> mac.raw = skb -> data;
204
                        netif_rx(skb);
205
                        return 0;
206
                }
207
        }
208
        printk(KERN_WARNING "isdn_x25iface_receive %s: not connected, skb dropped\n", MY_DEVNAME(cprot->net_dev) );
209
        dev_kfree_skb(skb);
210
        return -1;
211
}
212
 
213
/* a connection set up is indicated by lower layer
214
 */
215
int isdn_x25iface_connect_ind(struct concap_proto *cprot)
216
{
217
        struct sk_buff * skb = dev_alloc_skb(1);
218
        enum wan_states *state_p
219
          = &( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state);
220
        IX25DEBUG( "isdn_x25iface_connect_ind %s \n"
221
                   , MY_DEVNAME(cprot->net_dev) );
222
        if( *state_p == WAN_UNCONFIGURED ){
223
                printk(KERN_WARNING
224
                       "isdn_x25iface_connect_ind while unconfigured %s\n"
225
                       , MY_DEVNAME(cprot->net_dev) );
226
                return -1;
227
        }
228
        *state_p = WAN_CONNECTED;
229
        if( skb ){
230
                *( skb_put(skb, 1) ) = 0x01;
231
                skb -> mac.raw = skb -> data;
232
                skb -> dev  = cprot -> net_dev;
233
                skb -> protocol = htons(ETH_P_X25);
234
                skb -> pkt_type = PACKET_HOST;
235
                netif_rx(skb);
236
                return 0;
237
        } else {
238
                printk(KERN_WARNING "isdn_x25iface_connect_ind: "
239
                       " out of memory -- disconnecting\n");
240
                cprot -> dops -> disconn_req(cprot);
241
                return -1;
242
        }
243
}
244
 
245
/* a disconnect is indicated by lower layer
246
 */
247
int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
248
{
249
        struct sk_buff *skb;
250
        enum wan_states *state_p
251
          = &( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state);
252
        IX25DEBUG( "isdn_x25iface_disconn_ind %s \n", MY_DEVNAME(cprot -> net_dev) );
253
        if( *state_p == WAN_UNCONFIGURED ){
254
                printk(KERN_WARNING
255
                       "isdn_x25iface_disconn_ind while unconfigured\n");
256
                return -1;
257
        }
258
        if(! cprot -> net_dev) return -1;
259
        *state_p = WAN_DISCONNECTED;
260
        skb = dev_alloc_skb(1);
261
        if( skb ){
262
                *( skb_put(skb, 1) ) = 0x02;
263
                skb -> mac.raw = skb -> data;
264
                skb -> dev  = cprot -> net_dev;
265
                skb -> protocol = htons(ETH_P_X25);
266
                skb -> pkt_type = PACKET_HOST;
267
                netif_rx(skb);
268
                return 0;
269
        } else {
270
                printk(KERN_WARNING "isdn_x25iface_disconn_ind:"
271
                       " out of memory\n");
272
                return -1;
273
        }
274
}
275
 
276
/* process a frame handed over to us from linux network layer. First byte
277
   semantics as defined in ../../Documentation/networking/x25-iface.txt
278
   */
279
int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
280
{
281
        unsigned char firstbyte = skb->data[0];
282
        unsigned *state =
283
                &( ( (ix25_pdata_t*) (cprot -> proto_data) ) -> state  );
284
        int ret = 0;
285
        IX25DEBUG( "isdn_x25iface_xmit: %s first=%x state=%d \n", MY_DEVNAME(cprot -> net_dev), firstbyte, *state );
286
        switch ( firstbyte ){
287
        case 0x00: /* dl_data request */
288
                if( *state == WAN_CONNECTED ){
289
                        skb_pull(skb, 1);
290
                        cprot -> net_dev -> trans_start = jiffies;
291
                        ret = ( cprot -> dops -> data_req(cprot, skb) );
292
                        /* prepare for future retransmissions */
293
                        if( ret ) skb_push(skb,1);
294
                        return ret;
295
                }
296
                illegal_state_warn( *state, firstbyte );
297
                break;
298
        case 0x01: /* dl_connect request */
299
                if( *state == WAN_DISCONNECTED ){
300
                        *state = WAN_CONNECTING;
301
                        ret = cprot -> dops -> connect_req(cprot);
302
                        if(ret){
303
                                /* reset state and notify upper layer about
304
                                 * immidiatly failed attempts */
305
                                isdn_x25iface_disconn_ind(cprot);
306
                        }
307
                } else {
308
                        illegal_state_warn( *state, firstbyte );
309
                }
310
                break;
311
        case 0x02: /* dl_disconnect request */
312
                switch ( *state ){
313
                case WAN_DISCONNECTED:
314
                        /* Should not happen. However, give upper layer a
315
                           chance to recover from inconstistency  but don't
316
                           trust the lower layer sending the disconn_confirm
317
                           when already disconnected */
318
                        printk(KERN_WARNING "isdn_x25iface_xmit: disconnect "
319
                               " requested while disconnected\n" );
320
                        isdn_x25iface_disconn_ind(cprot);
321
                        break; /* prevent infinite loops */
322
                case WAN_CONNECTING:
323
                case WAN_CONNECTED:
324
                        *state = WAN_DISCONNECTED;
325
                        cprot -> dops -> disconn_req(cprot);
326
                        break;
327
                default:
328
                        illegal_state_warn( *state, firstbyte );
329
                }
330
                break;
331
        case 0x03: /* changing lapb parameters requested */
332
                printk(KERN_WARNING "isdn_x25iface_xmit: setting of lapb"
333
                       " options not yet supported\n");
334
                break;
335
        default:
336
                printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal"
337
                       " first byte %x ignored:\n", firstbyte);
338
        }
339
        dev_kfree_skb(skb);
340
        return 0;
341
}

powered by: WebSVN 2.1.0

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