Import 2.3.10pre5
[davej-history.git] / net / lapb / lapb_iface.c
blob23a721567dbcf52f6cf4c8d6916e6a2604013356
1 /*
2 * LAPB release 002
4 * This code REQUIRES 2.1.15 or higher/ NET3.038
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.
12 * History
13 * LAPB 001 Jonathan Naylor Started Coding
14 * LAPB 002 Jonathan Naylor New timer architecture.
17 #include <linux/config.h>
18 #if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
19 #include <linux/module.h>
20 #include <linux/errno.h>
21 #include <linux/types.h>
22 #include <linux/socket.h>
23 #include <linux/in.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/timer.h>
27 #include <linux/string.h>
28 #include <linux/sockios.h>
29 #include <linux/net.h>
30 #include <linux/inet.h>
31 #include <linux/if_arp.h>
32 #include <linux/skbuff.h>
33 #include <net/sock.h>
34 #include <asm/uaccess.h>
35 #include <asm/system.h>
36 #include <linux/fcntl.h>
37 #include <linux/mm.h>
38 #include <linux/interrupt.h>
39 #include <linux/stat.h>
40 #include <linux/init.h>
41 #include <net/lapb.h>
43 static lapb_cb *volatile lapb_list = NULL;
46 * Free an allocated lapb control block. This is done to centralise
47 * the MOD count code.
49 static void lapb_free_cb(lapb_cb *lapb)
51 kfree(lapb);
53 MOD_DEC_USE_COUNT;
57 * Socket removal during an interrupt is now safe.
59 static void lapb_remove_cb(lapb_cb *lapb)
61 lapb_cb *s;
62 unsigned long flags;
64 save_flags(flags); cli();
66 if ((s = lapb_list) == lapb) {
67 lapb_list = s->next;
68 restore_flags(flags);
69 return;
72 while (s != NULL && s->next != NULL) {
73 if (s->next == lapb) {
74 s->next = lapb->next;
75 restore_flags(flags);
76 return;
79 s = s->next;
82 restore_flags(flags);
86 * Add a socket to the bound sockets list.
88 static void lapb_insert_cb(lapb_cb *lapb)
90 unsigned long flags;
92 save_flags(flags); cli();
94 lapb->next = lapb_list;
95 lapb_list = lapb;
97 restore_flags(flags);
101 * Convert the integer token used by the device driver into a pointer
102 * to a LAPB control structure.
104 static lapb_cb *lapb_tokentostruct(void *token)
106 lapb_cb *lapb;
108 for (lapb = lapb_list; lapb != NULL; lapb = lapb->next)
109 if (lapb->token == token)
110 return lapb;
112 return NULL;
116 * Create an empty LAPB control block.
118 static lapb_cb *lapb_create_cb(void)
120 lapb_cb *lapb;
122 if ((lapb = kmalloc(sizeof(*lapb), GFP_ATOMIC)) == NULL)
123 return NULL;
125 MOD_INC_USE_COUNT;
127 memset(lapb, 0x00, sizeof(*lapb));
129 skb_queue_head_init(&lapb->write_queue);
130 skb_queue_head_init(&lapb->ack_queue);
132 init_timer(&lapb->t1timer);
133 init_timer(&lapb->t2timer);
135 lapb->t1 = LAPB_DEFAULT_T1;
136 lapb->t2 = LAPB_DEFAULT_T2;
137 lapb->n2 = LAPB_DEFAULT_N2;
138 lapb->mode = LAPB_DEFAULT_MODE;
139 lapb->window = LAPB_DEFAULT_WINDOW;
140 lapb->state = LAPB_STATE_0;
142 return lapb;
145 int lapb_register(void *token, struct lapb_register_struct *callbacks)
147 lapb_cb *lapb;
149 if (lapb_tokentostruct(token) != NULL)
150 return LAPB_BADTOKEN;
152 if ((lapb = lapb_create_cb()) == NULL)
153 return LAPB_NOMEM;
155 lapb->token = token;
156 lapb->callbacks = *callbacks;
158 lapb_insert_cb(lapb);
160 lapb_start_t1timer(lapb);
162 return LAPB_OK;
165 int lapb_unregister(void *token)
167 lapb_cb *lapb;
169 if ((lapb = lapb_tokentostruct(token)) == NULL)
170 return LAPB_BADTOKEN;
172 lapb_stop_t1timer(lapb);
173 lapb_stop_t2timer(lapb);
175 lapb_clear_queues(lapb);
177 lapb_remove_cb(lapb);
179 lapb_free_cb(lapb);
181 return LAPB_OK;
184 int lapb_getparms(void *token, struct lapb_parms_struct *parms)
186 lapb_cb *lapb;
188 if ((lapb = lapb_tokentostruct(token)) == NULL)
189 return LAPB_BADTOKEN;
191 parms->t1 = lapb->t1 / HZ;
192 parms->t2 = lapb->t2 / HZ;
193 parms->n2 = lapb->n2;
194 parms->n2count = lapb->n2count;
195 parms->state = lapb->state;
196 parms->window = lapb->window;
197 parms->mode = lapb->mode;
199 if (lapb->t1timer.prev == NULL && lapb->t1timer.next == NULL)
200 parms->t1timer = 0;
201 else
202 parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
204 if (lapb->t2timer.prev == NULL && lapb->t2timer.next == NULL)
205 parms->t2timer = 0;
206 else
207 parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
209 return LAPB_OK;
212 int lapb_setparms(void *token, struct lapb_parms_struct *parms)
214 lapb_cb *lapb;
216 if ((lapb = lapb_tokentostruct(token)) == NULL)
217 return LAPB_BADTOKEN;
219 if (parms->t1 < 1)
220 return LAPB_INVALUE;
222 if (parms->t2 < 1)
223 return LAPB_INVALUE;
225 if (parms->n2 < 1)
226 return LAPB_INVALUE;
228 if (lapb->state == LAPB_STATE_0) {
229 if (parms->mode & LAPB_EXTENDED) {
230 if (parms->window < 1 || parms->window > 127)
231 return LAPB_INVALUE;
232 } else {
233 if (parms->window < 1 || parms->window > 7)
234 return LAPB_INVALUE;
237 lapb->mode = parms->mode;
238 lapb->window = parms->window;
241 lapb->t1 = parms->t1 * HZ;
242 lapb->t2 = parms->t2 * HZ;
243 lapb->n2 = parms->n2;
245 return LAPB_OK;
248 int lapb_connect_request(void *token)
250 lapb_cb *lapb;
252 if ((lapb = lapb_tokentostruct(token)) == NULL)
253 return LAPB_BADTOKEN;
255 switch (lapb->state) {
256 case LAPB_STATE_1:
257 return LAPB_OK;
258 case LAPB_STATE_3:
259 case LAPB_STATE_4:
260 return LAPB_CONNECTED;
263 lapb_establish_data_link(lapb);
265 #if LAPB_DEBUG > 0
266 printk(KERN_DEBUG "lapb: (%p) S0 -> S1\n", lapb->token);
267 #endif
269 lapb->state = LAPB_STATE_1;
271 return LAPB_OK;
274 int lapb_disconnect_request(void *token)
276 lapb_cb *lapb;
278 if ((lapb = lapb_tokentostruct(token)) == NULL)
279 return LAPB_BADTOKEN;
281 switch (lapb->state) {
282 case LAPB_STATE_0:
283 return LAPB_NOTCONNECTED;
285 case LAPB_STATE_1:
286 #if LAPB_DEBUG > 1
287 printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)\n", lapb->token);
288 #endif
289 #if LAPB_DEBUG > 0
290 printk(KERN_DEBUG "lapb: (%p) S1 -> S0\n", lapb->token);
291 #endif
292 lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
293 lapb->state = LAPB_STATE_0;
294 lapb_start_t1timer(lapb);
295 return LAPB_NOTCONNECTED;
297 case LAPB_STATE_2:
298 return LAPB_OK;
301 lapb_clear_queues(lapb);
302 lapb->n2count = 0;
303 lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
304 lapb_start_t1timer(lapb);
305 lapb_stop_t2timer(lapb);
306 lapb->state = LAPB_STATE_2;
308 #if LAPB_DEBUG > 1
309 printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)\n", lapb->token);
310 #endif
311 #if LAPB_DEBUG > 0
312 printk(KERN_DEBUG "lapb: (%p) S3 -> S2\n", lapb->token);
313 #endif
315 return LAPB_OK;
318 int lapb_data_request(void *token, struct sk_buff *skb)
320 lapb_cb *lapb;
322 if ((lapb = lapb_tokentostruct(token)) == NULL)
323 return LAPB_BADTOKEN;
325 if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
326 return LAPB_NOTCONNECTED;
328 skb_queue_tail(&lapb->write_queue, skb);
330 lapb_kick(lapb);
332 return LAPB_OK;
335 int lapb_data_received(void *token, struct sk_buff *skb)
337 lapb_cb *lapb;
339 if ((lapb = lapb_tokentostruct(token)) == NULL)
340 return LAPB_BADTOKEN;
342 lapb_data_input(lapb, skb);
344 return LAPB_OK;
347 void lapb_connect_confirmation(lapb_cb *lapb, int reason)
349 if (lapb->callbacks.connect_confirmation != NULL)
350 (lapb->callbacks.connect_confirmation)(lapb->token, reason);
353 void lapb_connect_indication(lapb_cb *lapb, int reason)
355 if (lapb->callbacks.connect_indication != NULL)
356 (lapb->callbacks.connect_indication)(lapb->token, reason);
359 void lapb_disconnect_confirmation(lapb_cb *lapb, int reason)
361 if (lapb->callbacks.disconnect_confirmation != NULL)
362 (lapb->callbacks.disconnect_confirmation)(lapb->token, reason);
365 void lapb_disconnect_indication(lapb_cb *lapb, int reason)
367 if (lapb->callbacks.disconnect_indication != NULL)
368 (lapb->callbacks.disconnect_indication)(lapb->token, reason);
371 int lapb_data_indication(lapb_cb *lapb, struct sk_buff *skb)
373 int used = 0;
375 if (lapb->callbacks.data_indication != NULL) {
376 (lapb->callbacks.data_indication)(lapb->token, skb);
377 used = 1;
380 return used;
383 int lapb_data_transmit(lapb_cb *lapb, struct sk_buff *skb)
385 int used = 0;
387 if (lapb->callbacks.data_transmit != NULL) {
388 (lapb->callbacks.data_transmit)(lapb->token, skb);
389 used = 1;
392 return used;
395 EXPORT_SYMBOL(lapb_register);
396 EXPORT_SYMBOL(lapb_unregister);
397 EXPORT_SYMBOL(lapb_getparms);
398 EXPORT_SYMBOL(lapb_setparms);
399 EXPORT_SYMBOL(lapb_connect_request);
400 EXPORT_SYMBOL(lapb_disconnect_request);
401 EXPORT_SYMBOL(lapb_data_request);
402 EXPORT_SYMBOL(lapb_data_received);
404 __initfunc(void lapb_proto_init(struct net_proto *pro))
406 printk(KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n");
409 #ifdef MODULE
410 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
411 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
413 int init_module(void)
415 lapb_proto_init(NULL);
417 return 0;
420 void cleanup_module(void)
423 #endif
425 #endif