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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Synchronous PPP / Cisco-HDLC driver for the COMX boards
  3.  *
  4.  * Author: Gergely Madarasz <gorgo@itc.hu>
  5.  *
  6.  * based on skeleton code by Tivadar Szemethy <tiv@itc.hu>
  7.  *
  8.  * Copyright (C) 1999 ITConsult-Pro Co. <info@itc.hu>
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License
  12.  * as published by the Free Software Foundation; either version
  13.  * 2 of the License, or (at your option) any later version.
  14.  *
  15.  *
  16.  * Version 0.10 (99/06/10):
  17.  * - written the first code :)
  18.  *
  19.  * Version 0.20 (99/06/16):
  20.  * - added hdlc protocol 
  21.  * - protocol up is IFF_RUNNING
  22.  *
  23.  * Version 0.21 (99/07/15):
  24.  * - some small fixes with the line status
  25.  *
  26.  * Version 0.22 (99/08/05):
  27.  * - don't test IFF_RUNNING but the pp_link_state of the sppp
  28.  * 
  29.  * Version 0.23 (99/12/02):
  30.  * - tbusy fixes
  31.  *
  32.  */
  33. #define VERSION "0.23"
  34. #include <linux/module.h>
  35. #include <linux/version.h>
  36. #include <linux/types.h>
  37. #include <linux/sched.h>
  38. #include <linux/netdevice.h>
  39. #include <linux/proc_fs.h>
  40. #include <linux/if_arp.h>
  41. #include <linux/inetdevice.h>
  42. #include <asm/uaccess.h>
  43. #include <linux/init.h>
  44. #include <net/syncppp.h>
  45. #include "comx.h"
  46. MODULE_AUTHOR("Author: Gergely Madarasz <gorgo@itc.hu>");
  47. MODULE_DESCRIPTION("Cisco-HDLC / Synchronous PPP driver for the COMX sync serial boards");
  48. MODULE_LICENSE("GPL");
  49. static struct comx_protocol syncppp_protocol;
  50. static struct comx_protocol hdlc_protocol;
  51. struct syncppp_data {
  52. struct timer_list status_timer;
  53. };
  54. static void syncppp_status_timerfun(unsigned long d) {
  55. struct net_device *dev=(struct net_device *)d;
  56. struct comx_channel *ch=dev->priv;
  57. struct syncppp_data *spch=ch->LINE_privdata;
  58. struct sppp *sp = (struct sppp *)sppp_of(dev);
  59.         
  60. if(!(ch->line_status & PROTO_UP) && 
  61.     (sp->pp_link_state==SPPP_LINK_UP)) {
  62.      comx_status(dev, ch->line_status | PROTO_UP);
  63. }
  64. if((ch->line_status & PROTO_UP) &&
  65.     (sp->pp_link_state==SPPP_LINK_DOWN)) {
  66.      comx_status(dev, ch->line_status & ~PROTO_UP);
  67. }
  68. mod_timer(&spch->status_timer,jiffies + HZ*3);
  69. }
  70. static int syncppp_tx(struct net_device *dev) 
  71. {
  72. struct comx_channel *ch=dev->priv;
  73. if(ch->line_status & LINE_UP) {
  74. netif_wake_queue(dev);
  75. }
  76. return 0;
  77. }
  78. static void syncppp_status(struct net_device *dev, unsigned short status)
  79. {
  80. status &= ~(PROTO_UP | PROTO_LOOP);
  81. if(status & LINE_UP) {
  82. netif_wake_queue(dev);
  83. sppp_open(dev);
  84. } else  {
  85. /* Line went down */
  86. netif_stop_queue(dev);
  87. sppp_close(dev);
  88. }
  89. comx_status(dev, status);
  90. }
  91. static int syncppp_open(struct net_device *dev)
  92. {
  93. struct comx_channel *ch = dev->priv;
  94. struct syncppp_data *spch = ch->LINE_privdata;
  95. if (!(ch->init_status & HW_OPEN)) return -ENODEV;
  96. ch->init_status |= LINE_OPEN;
  97. ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
  98. if(ch->line_status & LINE_UP) {
  99. sppp_open(dev);
  100. }
  101. init_timer(&spch->status_timer);
  102. spch->status_timer.function=syncppp_status_timerfun;
  103. spch->status_timer.data=(unsigned long)dev;
  104. spch->status_timer.expires=jiffies + HZ*3;
  105. add_timer(&spch->status_timer);
  106. return 0;
  107. }
  108. static int syncppp_close(struct net_device *dev)
  109. {
  110. struct comx_channel *ch = dev->priv;
  111. struct syncppp_data *spch = ch->LINE_privdata;
  112. if (!(ch->init_status & HW_OPEN)) return -ENODEV;
  113. del_timer(&spch->status_timer);
  114. sppp_close(dev);
  115. ch->init_status &= ~LINE_OPEN;
  116. ch->line_status &= ~(PROTO_UP | PROTO_LOOP);
  117. return 0;
  118. }
  119. static int syncppp_xmit(struct sk_buff *skb, struct net_device *dev)
  120. {
  121. struct comx_channel *ch = dev->priv;
  122. netif_stop_queue(dev);
  123. switch(ch->HW_send_packet(dev, skb)) {
  124. case FRAME_QUEUED:
  125. netif_wake_queue(dev);
  126. break;
  127. case FRAME_ACCEPTED:
  128. case FRAME_DROPPED:
  129. break;
  130. case FRAME_ERROR:
  131. printk(KERN_ERR "%s: Transmit frame error (len %d)n", 
  132. dev->name, skb->len);
  133. break;
  134. }
  135. return 0;
  136. }
  137. static int syncppp_statistics(struct net_device *dev, char *page) 
  138. {
  139. int len = 0;
  140. len += sprintf(page + len, " ");
  141. return len;
  142. }
  143. static int syncppp_exit(struct net_device *dev) 
  144. {
  145. struct comx_channel *ch = dev->priv;
  146. sppp_detach(dev);
  147. dev->flags = 0;
  148. dev->type = 0;
  149. dev->mtu = 0;
  150. ch->LINE_rx = NULL;
  151. ch->LINE_tx = NULL;
  152. ch->LINE_status = NULL;
  153. ch->LINE_open = NULL;
  154. ch->LINE_close = NULL;
  155. ch->LINE_xmit = NULL;
  156. ch->LINE_header = NULL;
  157. ch->LINE_rebuild_header = NULL;
  158. ch->LINE_statistics = NULL;
  159. kfree(ch->LINE_privdata);
  160. ch->LINE_privdata = NULL;
  161. MOD_DEC_USE_COUNT;
  162. return 0;
  163. }
  164. static int syncppp_init(struct net_device *dev)
  165. {
  166. struct comx_channel *ch = dev->priv;
  167. struct ppp_device *pppdev = (struct ppp_device *)ch->if_ptr;
  168. ch->LINE_privdata = kmalloc(sizeof(struct syncppp_data), GFP_KERNEL);
  169. if (!ch->LINE_privdata)
  170. return -ENOMEM;
  171. pppdev->dev = dev;
  172. sppp_attach(pppdev);
  173. if(ch->protocol == &hdlc_protocol) {
  174. pppdev->sppp.pp_flags |= PP_CISCO;
  175. dev->type = ARPHRD_HDLC;
  176. } else {
  177. pppdev->sppp.pp_flags &= ~PP_CISCO;
  178. dev->type = ARPHRD_PPP;
  179. }
  180. ch->LINE_rx = sppp_input;
  181. ch->LINE_tx = syncppp_tx;
  182. ch->LINE_status = syncppp_status;
  183. ch->LINE_open = syncppp_open;
  184. ch->LINE_close = syncppp_close;
  185. ch->LINE_xmit = syncppp_xmit;
  186. ch->LINE_header = NULL;
  187. ch->LINE_statistics = syncppp_statistics;
  188. MOD_INC_USE_COUNT;
  189. return 0;
  190. }
  191. static struct comx_protocol syncppp_protocol = {
  192. "ppp", 
  193. VERSION,
  194. ARPHRD_PPP, 
  195. syncppp_init, 
  196. syncppp_exit, 
  197. NULL 
  198. };
  199. static struct comx_protocol hdlc_protocol = {
  200. "hdlc", 
  201. VERSION,
  202. ARPHRD_PPP, 
  203. syncppp_init, 
  204. syncppp_exit, 
  205. NULL 
  206. };
  207. #ifdef MODULE
  208. #define comx_proto_ppp_init init_module
  209. #endif
  210. int __init comx_proto_ppp_init(void)
  211. {
  212. int ret;
  213. if(0!=(ret=comx_register_protocol(&hdlc_protocol))) {
  214. return ret;
  215. }
  216. return comx_register_protocol(&syncppp_protocol);
  217. }
  218. #ifdef MODULE
  219. void cleanup_module(void)
  220. {
  221. comx_unregister_protocol(syncppp_protocol.name);
  222. comx_unregister_protocol(hdlc_protocol.name);
  223. }
  224. #endif /* MODULE */