lapb_iface.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:8k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  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/sched.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. static lapb_cb *volatile lapb_list /* = NULL initially */;
  42. /*
  43.  * Free an allocated lapb control block. This is done to centralise
  44.  * the MOD count code.
  45.  */
  46. static void lapb_free_cb(lapb_cb *lapb)
  47. {
  48. kfree(lapb);
  49. MOD_DEC_USE_COUNT;
  50. }
  51. /*
  52.  * Socket removal during an interrupt is now safe.
  53.  */
  54. static void lapb_remove_cb(lapb_cb *lapb)
  55. {
  56. lapb_cb *s;
  57. unsigned long flags;
  58. save_flags(flags); cli();
  59. if ((s = lapb_list) == lapb) {
  60. lapb_list = s->next;
  61. restore_flags(flags);
  62. return;
  63. }
  64. while (s != NULL && s->next != NULL) {
  65. if (s->next == lapb) {
  66. s->next = lapb->next;
  67. restore_flags(flags);
  68. return;
  69. }
  70. s = s->next;
  71. }
  72. restore_flags(flags);
  73. }
  74. /*
  75.  * Add a socket to the bound sockets list.
  76.  */
  77. static void lapb_insert_cb(lapb_cb *lapb)
  78. {
  79. unsigned long flags;
  80. save_flags(flags); cli();
  81. lapb->next = lapb_list;
  82. lapb_list  = lapb;
  83. restore_flags(flags);
  84. }
  85. /*
  86.  * Convert the integer token used by the device driver into a pointer
  87.  * to a LAPB control structure.
  88.  */
  89. static lapb_cb *lapb_tokentostruct(void *token)
  90. {
  91. lapb_cb *lapb;
  92. for (lapb = lapb_list; lapb != NULL; lapb = lapb->next)
  93. if (lapb->token == token)
  94. return lapb;
  95. return NULL;
  96. }
  97. /*
  98.  * Create an empty LAPB control block.
  99.  */
  100. static lapb_cb *lapb_create_cb(void)
  101. {
  102. lapb_cb *lapb;
  103. if ((lapb = kmalloc(sizeof(*lapb), GFP_ATOMIC)) == NULL)
  104. return NULL;
  105. MOD_INC_USE_COUNT;
  106. memset(lapb, 0x00, sizeof(*lapb));
  107. skb_queue_head_init(&lapb->write_queue);
  108. skb_queue_head_init(&lapb->ack_queue);
  109. init_timer(&lapb->t1timer);
  110. init_timer(&lapb->t2timer);
  111. lapb->t1      = LAPB_DEFAULT_T1;
  112. lapb->t2      = LAPB_DEFAULT_T2;
  113. lapb->n2      = LAPB_DEFAULT_N2;
  114. lapb->mode    = LAPB_DEFAULT_MODE;
  115. lapb->window  = LAPB_DEFAULT_WINDOW;
  116. lapb->state   = LAPB_STATE_0;
  117. return lapb;
  118. }
  119. int lapb_register(void *token, struct lapb_register_struct *callbacks)
  120. {
  121. lapb_cb *lapb;
  122. if (lapb_tokentostruct(token) != NULL)
  123. return LAPB_BADTOKEN;
  124. if ((lapb = lapb_create_cb()) == NULL)
  125. return LAPB_NOMEM;
  126. lapb->token     = token;
  127. lapb->callbacks = *callbacks;
  128. lapb_insert_cb(lapb);
  129. lapb_start_t1timer(lapb);
  130. return LAPB_OK;
  131. }
  132. int lapb_unregister(void *token)
  133. {
  134. lapb_cb *lapb;
  135. if ((lapb = lapb_tokentostruct(token)) == NULL)
  136. return LAPB_BADTOKEN;
  137. lapb_stop_t1timer(lapb);
  138. lapb_stop_t2timer(lapb);
  139. lapb_clear_queues(lapb);
  140. lapb_remove_cb(lapb);
  141. lapb_free_cb(lapb);
  142. return LAPB_OK;
  143. }
  144. int lapb_getparms(void *token, struct lapb_parms_struct *parms)
  145. {
  146. lapb_cb *lapb;
  147. if ((lapb = lapb_tokentostruct(token)) == NULL)
  148. return LAPB_BADTOKEN;
  149. parms->t1      = lapb->t1 / HZ;
  150. parms->t2      = lapb->t2 / HZ;
  151. parms->n2      = lapb->n2;
  152. parms->n2count = lapb->n2count;
  153. parms->state   = lapb->state;
  154. parms->window  = lapb->window;
  155. parms->mode    = lapb->mode;
  156. if (!timer_pending(&lapb->t1timer))
  157. parms->t1timer = 0;
  158. else
  159. parms->t1timer = (lapb->t1timer.expires - jiffies) / HZ;
  160. if (!timer_pending(&lapb->t2timer))
  161. parms->t2timer = 0;
  162. else
  163. parms->t2timer = (lapb->t2timer.expires - jiffies) / HZ;
  164. return LAPB_OK;
  165. }
  166. int lapb_setparms(void *token, struct lapb_parms_struct *parms)
  167. {
  168. lapb_cb *lapb;
  169. if ((lapb = lapb_tokentostruct(token)) == NULL)
  170. return LAPB_BADTOKEN;
  171. if (parms->t1 < 1)
  172. return LAPB_INVALUE;
  173. if (parms->t2 < 1)
  174. return LAPB_INVALUE;
  175. if (parms->n2 < 1)
  176. return LAPB_INVALUE;
  177. if (lapb->state == LAPB_STATE_0) {
  178. if (parms->mode & LAPB_EXTENDED) {
  179. if (parms->window < 1 || parms->window > 127)
  180. return LAPB_INVALUE;
  181. } else {
  182. if (parms->window < 1 || parms->window > 7)
  183. return LAPB_INVALUE;
  184. }
  185. lapb->mode    = parms->mode;
  186. lapb->window  = parms->window;
  187. }
  188. lapb->t1    = parms->t1 * HZ;
  189. lapb->t2    = parms->t2 * HZ;
  190. lapb->n2    = parms->n2;
  191. return LAPB_OK;
  192. }
  193. int lapb_connect_request(void *token)
  194. {
  195. lapb_cb *lapb;
  196. if ((lapb = lapb_tokentostruct(token)) == NULL)
  197. return LAPB_BADTOKEN;
  198. switch (lapb->state) {
  199. case LAPB_STATE_1:
  200. return LAPB_OK;
  201. case LAPB_STATE_3:
  202. case LAPB_STATE_4:
  203. return LAPB_CONNECTED;
  204. }
  205. lapb_establish_data_link(lapb);
  206. #if LAPB_DEBUG > 0
  207. printk(KERN_DEBUG "lapb: (%p) S0 -> S1n", lapb->token);
  208. #endif
  209. lapb->state = LAPB_STATE_1;
  210. return LAPB_OK;
  211. }
  212. int lapb_disconnect_request(void *token)
  213. {
  214. lapb_cb *lapb;
  215. if ((lapb = lapb_tokentostruct(token)) == NULL)
  216. return LAPB_BADTOKEN;
  217. switch (lapb->state) {
  218. case LAPB_STATE_0:
  219. return LAPB_NOTCONNECTED;
  220. case LAPB_STATE_1:
  221. #if LAPB_DEBUG > 1
  222. printk(KERN_DEBUG "lapb: (%p) S1 TX DISC(1)n", lapb->token);
  223. #endif
  224. #if LAPB_DEBUG > 0
  225. printk(KERN_DEBUG "lapb: (%p) S1 -> S0n", lapb->token);
  226. #endif
  227. lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
  228. lapb->state = LAPB_STATE_0;
  229. lapb_start_t1timer(lapb);
  230. return LAPB_NOTCONNECTED;
  231. case LAPB_STATE_2:
  232. return LAPB_OK;
  233. }
  234. lapb_clear_queues(lapb);
  235. lapb->n2count = 0;
  236. lapb_send_control(lapb, LAPB_DISC, LAPB_POLLON, LAPB_COMMAND);
  237. lapb_start_t1timer(lapb);
  238. lapb_stop_t2timer(lapb);
  239. lapb->state = LAPB_STATE_2;
  240. #if LAPB_DEBUG > 1
  241. printk(KERN_DEBUG "lapb: (%p) S3 DISC(1)n", lapb->token);
  242. #endif
  243. #if LAPB_DEBUG > 0
  244. printk(KERN_DEBUG "lapb: (%p) S3 -> S2n", lapb->token);
  245. #endif
  246. return LAPB_OK;
  247. }
  248. int lapb_data_request(void *token, struct sk_buff *skb)
  249. {
  250. lapb_cb *lapb;
  251. if ((lapb = lapb_tokentostruct(token)) == NULL)
  252. return LAPB_BADTOKEN;
  253. if (lapb->state != LAPB_STATE_3 && lapb->state != LAPB_STATE_4)
  254. return LAPB_NOTCONNECTED;
  255. skb_queue_tail(&lapb->write_queue, skb);
  256. lapb_kick(lapb);
  257. return LAPB_OK;
  258. }
  259. int lapb_data_received(void *token, struct sk_buff *skb)
  260. {
  261. lapb_cb *lapb;
  262. if ((lapb = lapb_tokentostruct(token)) == NULL)
  263. return LAPB_BADTOKEN;
  264. lapb_data_input(lapb, skb);
  265. return LAPB_OK;
  266. }
  267. void lapb_connect_confirmation(lapb_cb *lapb, int reason)
  268. {
  269. if (lapb->callbacks.connect_confirmation != NULL)
  270. (lapb->callbacks.connect_confirmation)(lapb->token, reason);
  271. }
  272. void lapb_connect_indication(lapb_cb *lapb, int reason)
  273. {
  274. if (lapb->callbacks.connect_indication != NULL)
  275. (lapb->callbacks.connect_indication)(lapb->token, reason);
  276. }
  277. void lapb_disconnect_confirmation(lapb_cb *lapb, int reason)
  278. {
  279. if (lapb->callbacks.disconnect_confirmation != NULL)
  280. (lapb->callbacks.disconnect_confirmation)(lapb->token, reason);
  281. }
  282. void lapb_disconnect_indication(lapb_cb *lapb, int reason)
  283. {
  284. if (lapb->callbacks.disconnect_indication != NULL)
  285. (lapb->callbacks.disconnect_indication)(lapb->token, reason);
  286. }
  287. int lapb_data_indication(lapb_cb *lapb, struct sk_buff *skb)
  288. {
  289. if (lapb->callbacks.data_indication != NULL) {
  290. return (lapb->callbacks.data_indication)(lapb->token, skb);
  291. }
  292. kfree_skb(skb);
  293. return NET_RX_CN_HIGH; /* For now; must be != NET_RX_DROP */ 
  294. }
  295. int lapb_data_transmit(lapb_cb *lapb, struct sk_buff *skb)
  296. {
  297. int used = 0;
  298. if (lapb->callbacks.data_transmit != NULL) {
  299. (lapb->callbacks.data_transmit)(lapb->token, skb);
  300. used = 1;
  301. }
  302. return used;
  303. }
  304. EXPORT_SYMBOL(lapb_register);
  305. EXPORT_SYMBOL(lapb_unregister);
  306. EXPORT_SYMBOL(lapb_getparms);
  307. EXPORT_SYMBOL(lapb_setparms);
  308. EXPORT_SYMBOL(lapb_connect_request);
  309. EXPORT_SYMBOL(lapb_disconnect_request);
  310. EXPORT_SYMBOL(lapb_data_request);
  311. EXPORT_SYMBOL(lapb_data_received);
  312. static char banner[] __initdata = KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0n";
  313. static int __init lapb_init(void)
  314. {
  315. printk(banner);
  316. return 0;
  317. }
  318. MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
  319. MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
  320. module_init(lapb_init);