diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/net/wan/sdla_ppp.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/net/wan/sdla_ppp.c')
-rw-r--r-- | drivers/net/wan/sdla_ppp.c | 3429 |
1 files changed, 3429 insertions, 0 deletions
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c new file mode 100644 index 000000000000..1761cb68ab48 --- /dev/null +++ b/drivers/net/wan/sdla_ppp.c | |||
@@ -0,0 +1,3429 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module. | ||
3 | * | ||
4 | * Author: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * | ||
6 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * ============================================================================ | ||
13 | * Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for | ||
14 | * 2.4.X kernels. | ||
15 | * Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support: | ||
16 | * get_ip_address() function has moved | ||
17 | * into the ppp_poll() routine. It cannot | ||
18 | * be called from an interrupt. | ||
19 | * Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: | ||
20 | * Deny all and specify allowed requests. | ||
21 | * May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown | ||
22 | * option. When the link goes down, the | ||
23 | * network interface IFF_UP flag is reset. | ||
24 | * Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. | ||
25 | * Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem. | ||
26 | * Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called | ||
27 | * with NULL dev pointer: no check. | ||
28 | * Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter. | ||
29 | * Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels | ||
30 | * Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels | ||
31 | * Moved dynamic route processing into | ||
32 | * a polling routine. | ||
33 | * Oct 07, 1999 Nenad Corbic o Support for S514 PCI card. | ||
34 | * Gideon Hack o UPD and Updates executed using timer interrupt | ||
35 | * Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics | ||
36 | * Jul 20, 1999 Nenad Corbic o Remove the polling routines and use | ||
37 | * interrupts instead. | ||
38 | * Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels. | ||
39 | * Aug 13, 1998 Jaspreet Singh o Improved Line Tracing. | ||
40 | * Jun 22, 1998 David Fong o Added remote IP address assignment | ||
41 | * Mar 15, 1998 Alan Cox o 2.1.8x basic port. | ||
42 | * Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol. | ||
43 | * Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP. | ||
44 | * o Implemented new routines like | ||
45 | * ppp_set_inbnd_auth(), ppp_set_outbnd_auth(), | ||
46 | * tokenize() and strstrip(). | ||
47 | * Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs | ||
48 | * while they have been disabled. | ||
49 | * Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by | ||
50 | * disabling and enabling of irqs. | ||
51 | * o Added new counters for stats on disable/enable | ||
52 | * IRQs. | ||
53 | * Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data' | ||
54 | * before every netif_rx(). | ||
55 | * o Free up the device structure in del_if(). | ||
56 | * Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing | ||
57 | * command. | ||
58 | * Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time. | ||
59 | * Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow | ||
60 | * control by avoiding RACE conditions. The | ||
61 | * cli() and restore_flags() are taken out. | ||
62 | * A new structure, "ppp_private_area", is added | ||
63 | * to provide Driver Statistics. | ||
64 | * Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding | ||
65 | * save_flags(), cli() and restore_flags(). | ||
66 | * Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets | ||
67 | * o Added ability to discard mulitcast and | ||
68 | * broacast source addressed packets. | ||
69 | * Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities | ||
70 | * New case (0x25) statement in if_send routine. | ||
71 | * Added a global variable rCount to keep track | ||
72 | * of FT1 status enabled on the board. | ||
73 | * May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for | ||
74 | * 508 card to reflect changes in the new | ||
75 | * ppp508.sfm for supporting:continous transmission | ||
76 | * of Configure-Request packets without receiving a | ||
77 | * reply | ||
78 | * OR-ed 0x300 to conf_flags | ||
79 | * o Changed connect_tmout from 900 to 0 | ||
80 | * May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards | ||
81 | * Apr 25, 1997 Farhan Thawar o added UDP Management stuff | ||
82 | * Mar 11, 1997 Farhan Thawar Version 3.1.1 | ||
83 | * o fixed (+1) bug in rx_intr() | ||
84 | * o changed if_send() to return 0 if | ||
85 | * wandev.critical() is true | ||
86 | * o free socket buffer in if_send() if | ||
87 | * returning 0 | ||
88 | * Jan 15, 1997 Gene Kozin Version 3.1.0 | ||
89 | * o implemented exec() entry point | ||
90 | * Jan 06, 1997 Gene Kozin Initial version. | ||
91 | *****************************************************************************/ | ||
92 | |||
93 | #include <linux/module.h> | ||
94 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
95 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
96 | #include <linux/errno.h> /* return codes */ | ||
97 | #include <linux/string.h> /* inline memset(), etc. */ | ||
98 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
99 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
100 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
101 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
102 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
103 | #include <linux/in.h> /* sockaddr_in */ | ||
104 | |||
105 | |||
106 | #include <asm/uaccess.h> | ||
107 | #include <linux/inetdevice.h> | ||
108 | #include <linux/netdevice.h> | ||
109 | |||
110 | #include <linux/if.h> | ||
111 | #include <linux/sdla_ppp.h> /* PPP firmware API definitions */ | ||
112 | #include <linux/sdlasfm.h> /* S514 Type Definition */ | ||
113 | /****** Defines & Macros ****************************************************/ | ||
114 | |||
115 | #define PPP_DFLT_MTU 1500 /* default MTU */ | ||
116 | #define PPP_MAX_MTU 4000 /* maximum MTU */ | ||
117 | #define PPP_HDR_LEN 1 | ||
118 | |||
119 | #define MAX_IP_ERRORS 100 | ||
120 | |||
121 | #define CONNECT_TIMEOUT (90*HZ) /* link connection timeout */ | ||
122 | #define HOLD_DOWN_TIME (5*HZ) /* link hold down time : Changed from 30 to 5 */ | ||
123 | |||
124 | /* For handle_IPXWAN() */ | ||
125 | #define CVHexToAscii(b) (((unsigned char)(b) > (unsigned char)9) ? ((unsigned char)'A' + ((unsigned char)(b) - (unsigned char)10)) : ((unsigned char)'0' + (unsigned char)(b))) | ||
126 | |||
127 | /* Macro for enabling/disabling debugging comments */ | ||
128 | //#define NEX_DEBUG | ||
129 | #ifdef NEX_DEBUG | ||
130 | #define NEX_PRINTK(format, a...) printk(format, ## a) | ||
131 | #else | ||
132 | #define NEX_PRINTK(format, a...) | ||
133 | #endif /* NEX_DEBUG */ | ||
134 | |||
135 | #define DCD(a) ( a & 0x08 ? "HIGH" : "LOW" ) | ||
136 | #define CTS(a) ( a & 0x20 ? "HIGH" : "LOW" ) | ||
137 | #define LCP(a) ( a == 0x09 ? "OPEN" : "CLOSED" ) | ||
138 | #define IP(a) ( a == 0x09 ? "ENABLED" : "DISABLED" ) | ||
139 | |||
140 | #define TMR_INT_ENABLED_UPDATE 0x01 | ||
141 | #define TMR_INT_ENABLED_PPP_EVENT 0x02 | ||
142 | #define TMR_INT_ENABLED_UDP 0x04 | ||
143 | #define TMR_INT_ENABLED_CONFIG 0x20 | ||
144 | |||
145 | /* Set Configuraton Command Definitions */ | ||
146 | #define PERCENT_TX_BUFF 60 | ||
147 | #define TIME_BETWEEN_CONF_REQ 30 | ||
148 | #define TIME_BETWEEN_PAP_CHAP_REQ 30 | ||
149 | #define WAIT_PAP_CHAP_WITHOUT_REPLY 300 | ||
150 | #define WAIT_AFTER_DCD_CTS_LOW 5 | ||
151 | #define TIME_DCD_CTS_LOW_AFTER_LNK_DOWN 10 | ||
152 | #define WAIT_DCD_HIGH_AFTER_ENABLE_COMM 900 | ||
153 | #define MAX_CONF_REQ_WITHOUT_REPLY 10 | ||
154 | #define MAX_TERM_REQ_WITHOUT_REPLY 2 | ||
155 | #define NUM_CONF_NAK_WITHOUT_REPLY 5 | ||
156 | #define NUM_AUTH_REQ_WITHOUT_REPLY 10 | ||
157 | |||
158 | #define END_OFFSET 0x1F0 | ||
159 | |||
160 | |||
161 | /******Data Structures*****************************************************/ | ||
162 | |||
163 | /* This structure is placed in the private data area of the device structure. | ||
164 | * The card structure used to occupy the private area but now the following | ||
165 | * structure will incorporate the card structure along with PPP specific data | ||
166 | */ | ||
167 | |||
168 | typedef struct ppp_private_area | ||
169 | { | ||
170 | struct net_device *slave; | ||
171 | sdla_t* card; | ||
172 | unsigned long router_start_time; /*router start time in sec */ | ||
173 | unsigned long tick_counter; /*used for 5 second counter*/ | ||
174 | unsigned mc; /*multicast support on or off*/ | ||
175 | unsigned char enable_IPX; | ||
176 | unsigned long network_number; | ||
177 | unsigned char pap; | ||
178 | unsigned char chap; | ||
179 | unsigned char sysname[31]; /* system name for in-bnd auth*/ | ||
180 | unsigned char userid[511]; /* list of user ids */ | ||
181 | unsigned char passwd[511]; /* list of passwords */ | ||
182 | unsigned protocol; /* SKB Protocol */ | ||
183 | u32 ip_local; /* Local IP Address */ | ||
184 | u32 ip_remote; /* remote IP Address */ | ||
185 | |||
186 | u32 ip_local_tmp; | ||
187 | u32 ip_remote_tmp; | ||
188 | |||
189 | unsigned char timer_int_enabled; /* Who enabled the timer inter*/ | ||
190 | unsigned char update_comms_stats; /* Used by update function */ | ||
191 | unsigned long curr_trace_addr; /* Trace information */ | ||
192 | unsigned long start_trace_addr; | ||
193 | unsigned long end_trace_addr; | ||
194 | |||
195 | unsigned char interface_down; /* Brind down interface when channel | ||
196 | goes down */ | ||
197 | unsigned long config_wait_timeout; /* After if_open() if in dynamic if mode, | ||
198 | wait a few seconds before configuring */ | ||
199 | |||
200 | unsigned short udp_pkt_lgth; | ||
201 | char udp_pkt_src; | ||
202 | char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT]; | ||
203 | |||
204 | /* PPP specific statistics */ | ||
205 | |||
206 | if_send_stat_t if_send_stat; | ||
207 | rx_intr_stat_t rx_intr_stat; | ||
208 | pipe_mgmt_stat_t pipe_mgmt_stat; | ||
209 | |||
210 | unsigned long router_up_time; | ||
211 | |||
212 | /* Polling work queue entry. Each interface | ||
213 | * has its own work queue entry, which is used | ||
214 | * to defer events from the interrupt */ | ||
215 | struct work_struct poll_work; | ||
216 | struct timer_list poll_delay_timer; | ||
217 | |||
218 | u8 gateway; | ||
219 | u8 config_ppp; | ||
220 | u8 ip_error; | ||
221 | |||
222 | }ppp_private_area_t; | ||
223 | |||
224 | /* variable for keeping track of enabling/disabling FT1 monitor status */ | ||
225 | static int rCount = 0; | ||
226 | |||
227 | extern void disable_irq(unsigned int); | ||
228 | extern void enable_irq(unsigned int); | ||
229 | |||
230 | /****** Function Prototypes *************************************************/ | ||
231 | |||
232 | /* WAN link driver entry points. These are called by the WAN router module. */ | ||
233 | static int update(struct wan_device *wandev); | ||
234 | static int new_if(struct wan_device *wandev, struct net_device *dev, | ||
235 | wanif_conf_t *conf); | ||
236 | static int del_if(struct wan_device *wandev, struct net_device *dev); | ||
237 | |||
238 | /* WANPIPE-specific entry points */ | ||
239 | static int wpp_exec (struct sdla *card, void *u_cmd, void *u_data); | ||
240 | |||
241 | /* Network device interface */ | ||
242 | static int if_init(struct net_device *dev); | ||
243 | static int if_open(struct net_device *dev); | ||
244 | static int if_close(struct net_device *dev); | ||
245 | static int if_header(struct sk_buff *skb, struct net_device *dev, | ||
246 | unsigned short type, | ||
247 | void *daddr, void *saddr, unsigned len); | ||
248 | |||
249 | static void if_tx_timeout(struct net_device *dev); | ||
250 | |||
251 | static int if_rebuild_hdr(struct sk_buff *skb); | ||
252 | static struct net_device_stats *if_stats(struct net_device *dev); | ||
253 | static int if_send(struct sk_buff *skb, struct net_device *dev); | ||
254 | |||
255 | |||
256 | /* PPP firmware interface functions */ | ||
257 | static int ppp_read_version(sdla_t *card, char *str); | ||
258 | static int ppp_set_outbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); | ||
259 | static int ppp_set_inbnd_auth(sdla_t *card, ppp_private_area_t *ppp_priv_area); | ||
260 | static int ppp_configure(sdla_t *card, void *data); | ||
261 | static int ppp_set_intr_mode(sdla_t *card, unsigned char mode); | ||
262 | static int ppp_comm_enable(sdla_t *card); | ||
263 | static int ppp_comm_disable(sdla_t *card); | ||
264 | static int ppp_comm_disable_shutdown(sdla_t *card); | ||
265 | static int ppp_get_err_stats(sdla_t *card); | ||
266 | static int ppp_send(sdla_t *card, void *data, unsigned len, unsigned proto); | ||
267 | static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb); | ||
268 | |||
269 | static void wpp_isr(sdla_t *card); | ||
270 | static void rx_intr(sdla_t *card); | ||
271 | static void event_intr(sdla_t *card); | ||
272 | static void timer_intr(sdla_t *card); | ||
273 | |||
274 | /* Background polling routines */ | ||
275 | static void process_route(sdla_t *card); | ||
276 | static void retrigger_comm(sdla_t *card); | ||
277 | |||
278 | /* Miscellaneous functions */ | ||
279 | static int read_info( sdla_t *card ); | ||
280 | static int read_connection_info (sdla_t *card); | ||
281 | static void remove_route( sdla_t *card ); | ||
282 | static int config508(struct net_device *dev, sdla_t *card); | ||
283 | static void show_disc_cause(sdla_t * card, unsigned cause); | ||
284 | static int reply_udp( unsigned char *data, unsigned int mbox_len ); | ||
285 | static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, | ||
286 | ppp_private_area_t *ppp_priv_area); | ||
287 | static void init_ppp_tx_rx_buff( sdla_t *card ); | ||
288 | static int intr_test( sdla_t *card ); | ||
289 | static int udp_pkt_type( struct sk_buff *skb , sdla_t *card); | ||
290 | static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area); | ||
291 | static void init_global_statistics( sdla_t *card ); | ||
292 | static int tokenize(char *str, char **tokens); | ||
293 | static char* strstrip(char *str, char *s); | ||
294 | static int chk_bcast_mcast_addr(sdla_t* card, struct net_device* dev, | ||
295 | struct sk_buff *skb); | ||
296 | |||
297 | static int config_ppp (sdla_t *); | ||
298 | static void ppp_poll(struct net_device *dev); | ||
299 | static void trigger_ppp_poll(struct net_device *dev); | ||
300 | static void ppp_poll_delay (unsigned long dev_ptr); | ||
301 | |||
302 | |||
303 | static int Read_connection_info; | ||
304 | static int Intr_test_counter; | ||
305 | static unsigned short available_buffer_space; | ||
306 | |||
307 | |||
308 | /* IPX functions */ | ||
309 | static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, | ||
310 | unsigned char incoming); | ||
311 | static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_PX, | ||
312 | unsigned long network_number, unsigned short proto); | ||
313 | |||
314 | /* Lock Functions */ | ||
315 | static void s508_lock (sdla_t *card, unsigned long *smp_flags); | ||
316 | static void s508_unlock (sdla_t *card, unsigned long *smp_flags); | ||
317 | |||
318 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
319 | struct sk_buff *skb, struct net_device* dev, | ||
320 | ppp_private_area_t* ppp_priv_area ); | ||
321 | static unsigned short calc_checksum (char *data, int len); | ||
322 | static void disable_comm (sdla_t *card); | ||
323 | static int detect_and_fix_tx_bug (sdla_t *card); | ||
324 | |||
325 | /****** Public Functions ****************************************************/ | ||
326 | |||
327 | /*============================================================================ | ||
328 | * PPP protocol initialization routine. | ||
329 | * | ||
330 | * This routine is called by the main WANPIPE module during setup. At this | ||
331 | * point adapter is completely initialized and firmware is running. | ||
332 | * o read firmware version (to make sure it's alive) | ||
333 | * o configure adapter | ||
334 | * o initialize protocol-specific fields of the adapter data space. | ||
335 | * | ||
336 | * Return: 0 o.k. | ||
337 | * < 0 failure. | ||
338 | */ | ||
339 | int wpp_init(sdla_t *card, wandev_conf_t *conf) | ||
340 | { | ||
341 | ppp_flags_t *flags; | ||
342 | union | ||
343 | { | ||
344 | char str[80]; | ||
345 | } u; | ||
346 | |||
347 | /* Verify configuration ID */ | ||
348 | if (conf->config_id != WANCONFIG_PPP) { | ||
349 | |||
350 | printk(KERN_INFO "%s: invalid configuration ID %u!\n", | ||
351 | card->devname, conf->config_id); | ||
352 | return -EINVAL; | ||
353 | |||
354 | } | ||
355 | |||
356 | /* Initialize miscellaneous pointers to structures on the adapter */ | ||
357 | switch (card->hw.type) { | ||
358 | |||
359 | case SDLA_S508: | ||
360 | card->mbox =(void*)(card->hw.dpmbase + PPP508_MB_OFFS); | ||
361 | card->flags=(void*)(card->hw.dpmbase + PPP508_FLG_OFFS); | ||
362 | break; | ||
363 | |||
364 | case SDLA_S514: | ||
365 | card->mbox =(void*)(card->hw.dpmbase + PPP514_MB_OFFS); | ||
366 | card->flags=(void*)(card->hw.dpmbase + PPP514_FLG_OFFS); | ||
367 | break; | ||
368 | |||
369 | default: | ||
370 | return -EINVAL; | ||
371 | |||
372 | } | ||
373 | flags = card->flags; | ||
374 | |||
375 | /* Read firmware version. Note that when adapter initializes, it | ||
376 | * clears the mailbox, so it may appear that the first command was | ||
377 | * executed successfully when in fact it was merely erased. To work | ||
378 | * around this, we execute the first command twice. | ||
379 | */ | ||
380 | if (ppp_read_version(card, NULL) || ppp_read_version(card, u.str)) | ||
381 | return -EIO; | ||
382 | |||
383 | printk(KERN_INFO "%s: running PPP firmware v%s\n",card->devname, u.str); | ||
384 | /* Adjust configuration and set defaults */ | ||
385 | card->wandev.mtu = (conf->mtu) ? | ||
386 | min_t(unsigned int, conf->mtu, PPP_MAX_MTU) : PPP_DFLT_MTU; | ||
387 | |||
388 | card->wandev.bps = conf->bps; | ||
389 | card->wandev.interface = conf->interface; | ||
390 | card->wandev.clocking = conf->clocking; | ||
391 | card->wandev.station = conf->station; | ||
392 | card->isr = &wpp_isr; | ||
393 | card->poll = NULL; | ||
394 | card->exec = &wpp_exec; | ||
395 | card->wandev.update = &update; | ||
396 | card->wandev.new_if = &new_if; | ||
397 | card->wandev.del_if = &del_if; | ||
398 | card->wandev.udp_port = conf->udp_port; | ||
399 | card->wandev.ttl = conf->ttl; | ||
400 | card->wandev.state = WAN_DISCONNECTED; | ||
401 | card->disable_comm = &disable_comm; | ||
402 | card->irq_dis_if_send_count = 0; | ||
403 | card->irq_dis_poll_count = 0; | ||
404 | card->u.p.authenticator = conf->u.ppp.authenticator; | ||
405 | card->u.p.ip_mode = conf->u.ppp.ip_mode ? | ||
406 | conf->u.ppp.ip_mode : WANOPT_PPP_STATIC; | ||
407 | card->TracingEnabled = 0; | ||
408 | Read_connection_info = 1; | ||
409 | |||
410 | /* initialize global statistics */ | ||
411 | init_global_statistics( card ); | ||
412 | |||
413 | |||
414 | |||
415 | if (!card->configured){ | ||
416 | int err; | ||
417 | |||
418 | Intr_test_counter = 0; | ||
419 | err = intr_test(card); | ||
420 | |||
421 | if(err || (Intr_test_counter < MAX_INTR_TEST_COUNTER)) { | ||
422 | printk("%s: Interrupt Test Failed, Counter: %i\n", | ||
423 | card->devname, Intr_test_counter); | ||
424 | printk( "%s: Please choose another interrupt\n",card->devname); | ||
425 | return -EIO; | ||
426 | } | ||
427 | |||
428 | printk(KERN_INFO "%s: Interrupt Test Passed, Counter: %i\n", | ||
429 | card->devname, Intr_test_counter); | ||
430 | card->configured = 1; | ||
431 | } | ||
432 | |||
433 | ppp_set_intr_mode(card, PPP_INTR_TIMER); | ||
434 | |||
435 | /* Turn off the transmit and timer interrupt */ | ||
436 | flags->imask &= ~PPP_INTR_TIMER; | ||
437 | |||
438 | printk(KERN_INFO "\n"); | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | /******* WAN Device Driver Entry Points *************************************/ | ||
444 | |||
445 | /*============================================================================ | ||
446 | * Update device status & statistics. | ||
447 | */ | ||
448 | static int update(struct wan_device *wandev) | ||
449 | { | ||
450 | sdla_t* card = wandev->private; | ||
451 | struct net_device* dev; | ||
452 | volatile ppp_private_area_t *ppp_priv_area; | ||
453 | ppp_flags_t *flags = card->flags; | ||
454 | unsigned long timeout; | ||
455 | |||
456 | /* sanity checks */ | ||
457 | if ((wandev == NULL) || (wandev->private == NULL)) | ||
458 | return -EFAULT; | ||
459 | |||
460 | if (wandev->state == WAN_UNCONFIGURED) | ||
461 | return -ENODEV; | ||
462 | |||
463 | /* Shutdown bug fix. This function can be | ||
464 | * called with NULL dev pointer during | ||
465 | * shutdown | ||
466 | */ | ||
467 | if ((dev=card->wandev.dev) == NULL){ | ||
468 | return -ENODEV; | ||
469 | } | ||
470 | |||
471 | if ((ppp_priv_area=dev->priv) == NULL){ | ||
472 | return -ENODEV; | ||
473 | } | ||
474 | |||
475 | ppp_priv_area->update_comms_stats = 2; | ||
476 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE; | ||
477 | flags->imask |= PPP_INTR_TIMER; | ||
478 | |||
479 | /* wait a maximum of 1 second for the statistics to be updated */ | ||
480 | timeout = jiffies; | ||
481 | for(;;) { | ||
482 | if(ppp_priv_area->update_comms_stats == 0){ | ||
483 | break; | ||
484 | } | ||
485 | if ((jiffies - timeout) > (1 * HZ)){ | ||
486 | ppp_priv_area->update_comms_stats = 0; | ||
487 | ppp_priv_area->timer_int_enabled &= | ||
488 | ~TMR_INT_ENABLED_UPDATE; | ||
489 | return -EAGAIN; | ||
490 | } | ||
491 | } | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | /*============================================================================ | ||
497 | * Create new logical channel. | ||
498 | * This routine is called by the router when ROUTER_IFNEW IOCTL is being | ||
499 | * handled. | ||
500 | * o parse media- and hardware-specific configuration | ||
501 | * o make sure that a new channel can be created | ||
502 | * o allocate resources, if necessary | ||
503 | * o prepare network device structure for registaration. | ||
504 | * | ||
505 | * Return: 0 o.k. | ||
506 | * < 0 failure (channel will not be created) | ||
507 | */ | ||
508 | static int new_if(struct wan_device *wandev, struct net_device *dev, | ||
509 | wanif_conf_t *conf) | ||
510 | { | ||
511 | sdla_t *card = wandev->private; | ||
512 | ppp_private_area_t *ppp_priv_area; | ||
513 | |||
514 | if (wandev->ndev) | ||
515 | return -EEXIST; | ||
516 | |||
517 | |||
518 | printk(KERN_INFO "%s: Configuring Interface: %s\n", | ||
519 | card->devname, conf->name); | ||
520 | |||
521 | if ((conf->name[0] == '\0') || (strlen(conf->name) > WAN_IFNAME_SZ)) { | ||
522 | |||
523 | printk(KERN_INFO "%s: Invalid interface name!\n", | ||
524 | card->devname); | ||
525 | return -EINVAL; | ||
526 | |||
527 | } | ||
528 | |||
529 | /* allocate and initialize private data */ | ||
530 | ppp_priv_area = kmalloc(sizeof(ppp_private_area_t), GFP_KERNEL); | ||
531 | |||
532 | if( ppp_priv_area == NULL ) | ||
533 | return -ENOMEM; | ||
534 | |||
535 | memset(ppp_priv_area, 0, sizeof(ppp_private_area_t)); | ||
536 | |||
537 | ppp_priv_area->card = card; | ||
538 | |||
539 | /* initialize data */ | ||
540 | strcpy(card->u.p.if_name, conf->name); | ||
541 | |||
542 | /* initialize data in ppp_private_area structure */ | ||
543 | |||
544 | init_ppp_priv_struct( ppp_priv_area ); | ||
545 | |||
546 | ppp_priv_area->mc = conf->mc; | ||
547 | ppp_priv_area->pap = conf->pap; | ||
548 | ppp_priv_area->chap = conf->chap; | ||
549 | |||
550 | /* Option to bring down the interface when | ||
551 | * the link goes down */ | ||
552 | if (conf->if_down){ | ||
553 | set_bit(DYN_OPT_ON,&ppp_priv_area->interface_down); | ||
554 | printk("%s: Dynamic interface configuration enabled\n", | ||
555 | card->devname); | ||
556 | } | ||
557 | |||
558 | /* If no user ids are specified */ | ||
559 | if(!strlen(conf->userid) && (ppp_priv_area->pap||ppp_priv_area->chap)){ | ||
560 | kfree(ppp_priv_area); | ||
561 | return -EINVAL; | ||
562 | } | ||
563 | |||
564 | /* If no passwords are specified */ | ||
565 | if(!strlen(conf->passwd) && (ppp_priv_area->pap||ppp_priv_area->chap)){ | ||
566 | kfree(ppp_priv_area); | ||
567 | return -EINVAL; | ||
568 | } | ||
569 | |||
570 | if(strlen(conf->sysname) > 31){ | ||
571 | kfree(ppp_priv_area); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | |||
575 | /* If no system name is specified */ | ||
576 | if(!strlen(conf->sysname) && (card->u.p.authenticator)){ | ||
577 | kfree(ppp_priv_area); | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | /* copy the data into the ppp private structure */ | ||
582 | memcpy(ppp_priv_area->userid, conf->userid, strlen(conf->userid)); | ||
583 | memcpy(ppp_priv_area->passwd, conf->passwd, strlen(conf->passwd)); | ||
584 | memcpy(ppp_priv_area->sysname, conf->sysname, strlen(conf->sysname)); | ||
585 | |||
586 | |||
587 | ppp_priv_area->enable_IPX = conf->enable_IPX; | ||
588 | if (conf->network_number){ | ||
589 | ppp_priv_area->network_number = conf->network_number; | ||
590 | }else{ | ||
591 | ppp_priv_area->network_number = 0xDEADBEEF; | ||
592 | } | ||
593 | |||
594 | /* Tells us that if this interface is a | ||
595 | * gateway or not */ | ||
596 | if ((ppp_priv_area->gateway = conf->gateway) == WANOPT_YES){ | ||
597 | printk(KERN_INFO "%s: Interface %s is set as a gateway.\n", | ||
598 | card->devname,card->u.p.if_name); | ||
599 | } | ||
600 | |||
601 | /* prepare network device data space for registration */ | ||
602 | strcpy(dev->name,card->u.p.if_name); | ||
603 | |||
604 | dev->init = &if_init; | ||
605 | dev->priv = ppp_priv_area; | ||
606 | dev->mtu = min_t(unsigned int, dev->mtu, card->wandev.mtu); | ||
607 | |||
608 | /* Initialize the polling work routine */ | ||
609 | INIT_WORK(&ppp_priv_area->poll_work, (void*)(void*)ppp_poll, dev); | ||
610 | |||
611 | /* Initialize the polling delay timer */ | ||
612 | init_timer(&ppp_priv_area->poll_delay_timer); | ||
613 | ppp_priv_area->poll_delay_timer.data = (unsigned long)dev; | ||
614 | ppp_priv_area->poll_delay_timer.function = ppp_poll_delay; | ||
615 | |||
616 | |||
617 | /* Since we start with dummy IP addresses we can say | ||
618 | * that route exists */ | ||
619 | printk(KERN_INFO "\n"); | ||
620 | |||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | /*============================================================================ | ||
625 | * Delete logical channel. | ||
626 | */ | ||
627 | static int del_if(struct wan_device *wandev, struct net_device *dev) | ||
628 | { | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static void disable_comm (sdla_t *card) | ||
633 | { | ||
634 | ppp_comm_disable_shutdown(card); | ||
635 | return; | ||
636 | } | ||
637 | |||
638 | /****** WANPIPE-specific entry points ***************************************/ | ||
639 | |||
640 | /*============================================================================ | ||
641 | * Execute adapter interface command. | ||
642 | */ | ||
643 | |||
644 | //FIXME: Why do we need this ???? | ||
645 | static int wpp_exec(struct sdla *card, void *u_cmd, void *u_data) | ||
646 | { | ||
647 | ppp_mbox_t *mbox = card->mbox; | ||
648 | int len; | ||
649 | |||
650 | if (copy_from_user((void*)&mbox->cmd, u_cmd, sizeof(ppp_cmd_t))) | ||
651 | return -EFAULT; | ||
652 | |||
653 | len = mbox->cmd.length; | ||
654 | |||
655 | if (len) { | ||
656 | |||
657 | if( copy_from_user((void*)&mbox->data, u_data, len)) | ||
658 | return -EFAULT; | ||
659 | |||
660 | } | ||
661 | |||
662 | /* execute command */ | ||
663 | if (!sdla_exec(mbox)) | ||
664 | return -EIO; | ||
665 | |||
666 | /* return result */ | ||
667 | if( copy_to_user(u_cmd, (void*)&mbox->cmd, sizeof(ppp_cmd_t))) | ||
668 | return -EFAULT; | ||
669 | len = mbox->cmd.length; | ||
670 | |||
671 | if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)) | ||
672 | return -EFAULT; | ||
673 | |||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | /****** Network Device Interface ********************************************/ | ||
678 | |||
679 | /*============================================================================ | ||
680 | * Initialize Linux network interface. | ||
681 | * | ||
682 | * This routine is called only once for each interface, during Linux network | ||
683 | * interface registration. Returning anything but zero will fail interface | ||
684 | * registration. | ||
685 | */ | ||
686 | static int if_init(struct net_device *dev) | ||
687 | { | ||
688 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
689 | sdla_t *card = ppp_priv_area->card; | ||
690 | struct wan_device *wandev = &card->wandev; | ||
691 | |||
692 | /* Initialize device driver entry points */ | ||
693 | dev->open = &if_open; | ||
694 | dev->stop = &if_close; | ||
695 | dev->hard_header = &if_header; | ||
696 | dev->rebuild_header = &if_rebuild_hdr; | ||
697 | dev->hard_start_xmit = &if_send; | ||
698 | dev->get_stats = &if_stats; | ||
699 | dev->tx_timeout = &if_tx_timeout; | ||
700 | dev->watchdog_timeo = TX_TIMEOUT; | ||
701 | |||
702 | /* Initialize media-specific parameters */ | ||
703 | dev->type = ARPHRD_PPP; /* ARP h/w type */ | ||
704 | dev->flags |= IFF_POINTOPOINT; | ||
705 | dev->flags |= IFF_NOARP; | ||
706 | |||
707 | /* Enable Mulitcasting if specified by user*/ | ||
708 | if (ppp_priv_area->mc == WANOPT_YES){ | ||
709 | dev->flags |= IFF_MULTICAST; | ||
710 | } | ||
711 | |||
712 | dev->mtu = wandev->mtu; | ||
713 | dev->hard_header_len = PPP_HDR_LEN; /* media header length */ | ||
714 | |||
715 | /* Initialize hardware parameters (just for reference) */ | ||
716 | dev->irq = wandev->irq; | ||
717 | dev->dma = wandev->dma; | ||
718 | dev->base_addr = wandev->ioport; | ||
719 | dev->mem_start = wandev->maddr; | ||
720 | dev->mem_end = wandev->maddr + wandev->msize - 1; | ||
721 | |||
722 | /* Set transmit buffer queue length */ | ||
723 | dev->tx_queue_len = 100; | ||
724 | SET_MODULE_OWNER(dev); | ||
725 | |||
726 | return 0; | ||
727 | } | ||
728 | |||
729 | /*============================================================================ | ||
730 | * Open network interface. | ||
731 | * o enable communications and interrupts. | ||
732 | * o prevent module from unloading by incrementing use count | ||
733 | * | ||
734 | * Return 0 if O.k. or errno. | ||
735 | */ | ||
736 | static int if_open(struct net_device *dev) | ||
737 | { | ||
738 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
739 | sdla_t *card = ppp_priv_area->card; | ||
740 | struct timeval tv; | ||
741 | //unsigned long smp_flags; | ||
742 | |||
743 | if (netif_running(dev)) | ||
744 | return -EBUSY; | ||
745 | |||
746 | wanpipe_open(card); | ||
747 | |||
748 | netif_start_queue(dev); | ||
749 | |||
750 | do_gettimeofday( &tv ); | ||
751 | ppp_priv_area->router_start_time = tv.tv_sec; | ||
752 | |||
753 | /* We cannot configure the card here because we don't | ||
754 | * have access to the interface IP addresses. | ||
755 | * Once the interface initilization is complete, we will be | ||
756 | * able to access the IP addresses. Therefore, | ||
757 | * configure the ppp link in the poll routine */ | ||
758 | set_bit(0,&ppp_priv_area->config_ppp); | ||
759 | ppp_priv_area->config_wait_timeout=jiffies; | ||
760 | |||
761 | /* Start the PPP configuration after 1sec delay. | ||
762 | * This will give the interface initilization time | ||
763 | * to finish its configuration */ | ||
764 | mod_timer(&ppp_priv_area->poll_delay_timer, jiffies + HZ); | ||
765 | return 0; | ||
766 | } | ||
767 | |||
768 | /*============================================================================ | ||
769 | * Close network interface. | ||
770 | * o if this is the last open, then disable communications and interrupts. | ||
771 | * o reset flags. | ||
772 | */ | ||
773 | static int if_close(struct net_device *dev) | ||
774 | { | ||
775 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
776 | sdla_t *card = ppp_priv_area->card; | ||
777 | |||
778 | netif_stop_queue(dev); | ||
779 | wanpipe_close(card); | ||
780 | |||
781 | del_timer (&ppp_priv_area->poll_delay_timer); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /*============================================================================ | ||
786 | * Build media header. | ||
787 | * | ||
788 | * The trick here is to put packet type (Ethertype) into 'protocol' field of | ||
789 | * the socket buffer, so that we don't forget it. If packet type is not | ||
790 | * supported, set skb->protocol to 0 and discard packet later. | ||
791 | * | ||
792 | * Return: media header length. | ||
793 | */ | ||
794 | static int if_header(struct sk_buff *skb, struct net_device *dev, | ||
795 | unsigned short type, void *daddr, void *saddr, unsigned len) | ||
796 | { | ||
797 | switch (type) | ||
798 | { | ||
799 | case ETH_P_IP: | ||
800 | case ETH_P_IPX: | ||
801 | skb->protocol = htons(type); | ||
802 | break; | ||
803 | |||
804 | default: | ||
805 | skb->protocol = 0; | ||
806 | } | ||
807 | |||
808 | return PPP_HDR_LEN; | ||
809 | } | ||
810 | |||
811 | /*============================================================================ | ||
812 | * Re-build media header. | ||
813 | * | ||
814 | * Return: 1 physical address resolved. | ||
815 | * 0 physical address not resolved | ||
816 | */ | ||
817 | static int if_rebuild_hdr (struct sk_buff *skb) | ||
818 | { | ||
819 | struct net_device *dev = skb->dev; | ||
820 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
821 | sdla_t *card = ppp_priv_area->card; | ||
822 | |||
823 | printk(KERN_INFO "%s: rebuild_header() called for interface %s!\n", | ||
824 | card->devname, dev->name); | ||
825 | return 1; | ||
826 | } | ||
827 | |||
828 | /*============================================================================ | ||
829 | * Handle transmit timeout event from netif watchdog | ||
830 | */ | ||
831 | static void if_tx_timeout(struct net_device *dev) | ||
832 | { | ||
833 | ppp_private_area_t* chan = dev->priv; | ||
834 | sdla_t *card = chan->card; | ||
835 | |||
836 | /* If our device stays busy for at least 5 seconds then we will | ||
837 | * kick start the device by making dev->tbusy = 0. We expect | ||
838 | * that our device never stays busy more than 5 seconds. So this | ||
839 | * is only used as a last resort. | ||
840 | */ | ||
841 | |||
842 | ++ chan->if_send_stat.if_send_tbusy; | ||
843 | ++card->wandev.stats.collisions; | ||
844 | |||
845 | printk (KERN_INFO "%s: Transmit timed out on %s\n", card->devname,dev->name); | ||
846 | ++chan->if_send_stat.if_send_tbusy_timeout; | ||
847 | netif_wake_queue (dev); | ||
848 | } | ||
849 | |||
850 | |||
851 | |||
852 | /*============================================================================ | ||
853 | * Send a packet on a network interface. | ||
854 | * o set tbusy flag (marks start of the transmission) to block a timer-based | ||
855 | * transmit from overlapping. | ||
856 | * o check link state. If link is not up, then drop the packet. | ||
857 | * o execute adapter send command. | ||
858 | * o free socket buffer | ||
859 | * | ||
860 | * Return: 0 complete (socket buffer must be freed) | ||
861 | * non-0 packet may be re-transmitted (tbusy must be set) | ||
862 | * | ||
863 | * Notes: | ||
864 | * 1. This routine is called either by the protocol stack or by the "net | ||
865 | * bottom half" (with interrupts enabled). | ||
866 | * 2. Setting tbusy flag will inhibit further transmit requests from the | ||
867 | * protocol stack and can be used for flow control with protocol layer. | ||
868 | */ | ||
869 | static int if_send (struct sk_buff *skb, struct net_device *dev) | ||
870 | { | ||
871 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
872 | sdla_t *card = ppp_priv_area->card; | ||
873 | unsigned char *sendpacket; | ||
874 | unsigned long smp_flags; | ||
875 | ppp_flags_t *flags = card->flags; | ||
876 | int udp_type; | ||
877 | int err=0; | ||
878 | |||
879 | ++ppp_priv_area->if_send_stat.if_send_entry; | ||
880 | |||
881 | netif_stop_queue(dev); | ||
882 | |||
883 | if (skb == NULL) { | ||
884 | |||
885 | /* If we get here, some higher layer thinks we've missed an | ||
886 | * tx-done interrupt. | ||
887 | */ | ||
888 | printk(KERN_INFO "%s: interface %s got kicked!\n", | ||
889 | card->devname, dev->name); | ||
890 | |||
891 | ++ppp_priv_area->if_send_stat.if_send_skb_null; | ||
892 | |||
893 | netif_wake_queue(dev); | ||
894 | return 0; | ||
895 | } | ||
896 | |||
897 | sendpacket = skb->data; | ||
898 | |||
899 | udp_type = udp_pkt_type( skb, card ); | ||
900 | |||
901 | |||
902 | if (udp_type == UDP_PTPIPE_TYPE){ | ||
903 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_STACK, card, skb, dev, | ||
904 | ppp_priv_area)){ | ||
905 | flags->imask |= PPP_INTR_TIMER; | ||
906 | } | ||
907 | ++ppp_priv_area->if_send_stat.if_send_PIPE_request; | ||
908 | netif_start_queue(dev); | ||
909 | return 0; | ||
910 | } | ||
911 | |||
912 | /* Check for broadcast and multicast addresses | ||
913 | * If found, drop (deallocate) a packet and return. | ||
914 | */ | ||
915 | if(chk_bcast_mcast_addr(card, dev, skb)){ | ||
916 | ++card->wandev.stats.tx_dropped; | ||
917 | dev_kfree_skb_any(skb); | ||
918 | netif_start_queue(dev); | ||
919 | return 0; | ||
920 | } | ||
921 | |||
922 | |||
923 | if(card->hw.type != SDLA_S514){ | ||
924 | s508_lock(card,&smp_flags); | ||
925 | } | ||
926 | |||
927 | if (test_and_set_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
928 | |||
929 | printk(KERN_INFO "%s: Critical in if_send: %lx\n", | ||
930 | card->wandev.name,card->wandev.critical); | ||
931 | |||
932 | ++card->wandev.stats.tx_dropped; | ||
933 | ++ppp_priv_area->if_send_stat.if_send_critical_non_ISR; | ||
934 | netif_start_queue(dev); | ||
935 | goto if_send_exit_crit; | ||
936 | } | ||
937 | |||
938 | if (card->wandev.state != WAN_CONNECTED) { | ||
939 | |||
940 | ++ppp_priv_area->if_send_stat.if_send_wan_disconnected; | ||
941 | ++card->wandev.stats.tx_dropped; | ||
942 | netif_start_queue(dev); | ||
943 | |||
944 | } else if (!skb->protocol) { | ||
945 | ++ppp_priv_area->if_send_stat.if_send_protocol_error; | ||
946 | ++card->wandev.stats.tx_errors; | ||
947 | netif_start_queue(dev); | ||
948 | |||
949 | } else { | ||
950 | |||
951 | /*If it's IPX change the network numbers to 0 if they're ours.*/ | ||
952 | if( skb->protocol == htons(ETH_P_IPX) ) { | ||
953 | if(ppp_priv_area->enable_IPX) { | ||
954 | switch_net_numbers( skb->data, | ||
955 | ppp_priv_area->network_number, 0); | ||
956 | } else { | ||
957 | ++card->wandev.stats.tx_dropped; | ||
958 | netif_start_queue(dev); | ||
959 | goto if_send_exit_crit; | ||
960 | } | ||
961 | } | ||
962 | |||
963 | if (ppp_send(card, skb->data, skb->len, skb->protocol)) { | ||
964 | netif_stop_queue(dev); | ||
965 | ++ppp_priv_area->if_send_stat.if_send_adptr_bfrs_full; | ||
966 | ++ppp_priv_area->if_send_stat.if_send_tx_int_enabled; | ||
967 | } else { | ||
968 | ++ppp_priv_area->if_send_stat.if_send_bfr_passed_to_adptr; | ||
969 | ++card->wandev.stats.tx_packets; | ||
970 | card->wandev.stats.tx_bytes += skb->len; | ||
971 | netif_start_queue(dev); | ||
972 | dev->trans_start = jiffies; | ||
973 | } | ||
974 | } | ||
975 | |||
976 | if_send_exit_crit: | ||
977 | |||
978 | if (!(err=netif_queue_stopped(dev))){ | ||
979 | dev_kfree_skb_any(skb); | ||
980 | }else{ | ||
981 | ppp_priv_area->tick_counter = jiffies; | ||
982 | flags->imask |= PPP_INTR_TXRDY; /* unmask Tx interrupts */ | ||
983 | } | ||
984 | |||
985 | clear_bit(SEND_CRIT,&card->wandev.critical); | ||
986 | if(card->hw.type != SDLA_S514){ | ||
987 | s508_unlock(card,&smp_flags); | ||
988 | } | ||
989 | |||
990 | return err; | ||
991 | } | ||
992 | |||
993 | |||
994 | /*============================================================================= | ||
995 | * Store a UDP management packet for later processing. | ||
996 | */ | ||
997 | |||
998 | static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card, | ||
999 | struct sk_buff *skb, struct net_device* dev, | ||
1000 | ppp_private_area_t* ppp_priv_area ) | ||
1001 | { | ||
1002 | int udp_pkt_stored = 0; | ||
1003 | |||
1004 | if(!ppp_priv_area->udp_pkt_lgth && (skb->len<=MAX_LGTH_UDP_MGNT_PKT)){ | ||
1005 | ppp_priv_area->udp_pkt_lgth = skb->len; | ||
1006 | ppp_priv_area->udp_pkt_src = udp_pkt_src; | ||
1007 | memcpy(ppp_priv_area->udp_pkt_data, skb->data, skb->len); | ||
1008 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UDP; | ||
1009 | ppp_priv_area->protocol = skb->protocol; | ||
1010 | udp_pkt_stored = 1; | ||
1011 | }else{ | ||
1012 | if (skb->len > MAX_LGTH_UDP_MGNT_PKT){ | ||
1013 | printk(KERN_INFO "%s: PIPEMON UDP request too long : %i\n", | ||
1014 | card->devname, skb->len); | ||
1015 | }else{ | ||
1016 | printk(KERN_INFO "%s: PIPEMON UPD request already pending\n", | ||
1017 | card->devname); | ||
1018 | } | ||
1019 | ppp_priv_area->udp_pkt_lgth = 0; | ||
1020 | } | ||
1021 | |||
1022 | if(udp_pkt_src == UDP_PKT_FRM_STACK){ | ||
1023 | dev_kfree_skb_any(skb); | ||
1024 | }else{ | ||
1025 | dev_kfree_skb_any(skb); | ||
1026 | } | ||
1027 | |||
1028 | return(udp_pkt_stored); | ||
1029 | } | ||
1030 | |||
1031 | |||
1032 | |||
1033 | /*============================================================================ | ||
1034 | * Reply to UDP Management system. | ||
1035 | * Return length of reply. | ||
1036 | */ | ||
1037 | static int reply_udp( unsigned char *data, unsigned int mbox_len ) | ||
1038 | { | ||
1039 | unsigned short len, udp_length, temp, ip_length; | ||
1040 | unsigned long ip_temp; | ||
1041 | int even_bound = 0; | ||
1042 | ppp_udp_pkt_t *p_udp_pkt = (ppp_udp_pkt_t *)data; | ||
1043 | |||
1044 | /* Set length of packet */ | ||
1045 | len = sizeof(ip_pkt_t)+ | ||
1046 | sizeof(udp_pkt_t)+ | ||
1047 | sizeof(wp_mgmt_t)+ | ||
1048 | sizeof(cblock_t)+ | ||
1049 | mbox_len; | ||
1050 | |||
1051 | /* fill in UDP reply */ | ||
1052 | p_udp_pkt->wp_mgmt.request_reply = UDPMGMT_REPLY; | ||
1053 | |||
1054 | /* fill in UDP length */ | ||
1055 | udp_length = sizeof(udp_pkt_t)+ | ||
1056 | sizeof(wp_mgmt_t)+ | ||
1057 | sizeof(cblock_t)+ | ||
1058 | mbox_len; | ||
1059 | |||
1060 | |||
1061 | /* put it on an even boundary */ | ||
1062 | if ( udp_length & 0x0001 ) { | ||
1063 | udp_length += 1; | ||
1064 | len += 1; | ||
1065 | even_bound=1; | ||
1066 | } | ||
1067 | |||
1068 | temp = (udp_length<<8)|(udp_length>>8); | ||
1069 | p_udp_pkt->udp_pkt.udp_length = temp; | ||
1070 | |||
1071 | |||
1072 | /* swap UDP ports */ | ||
1073 | temp = p_udp_pkt->udp_pkt.udp_src_port; | ||
1074 | p_udp_pkt->udp_pkt.udp_src_port = | ||
1075 | p_udp_pkt->udp_pkt.udp_dst_port; | ||
1076 | p_udp_pkt->udp_pkt.udp_dst_port = temp; | ||
1077 | |||
1078 | |||
1079 | /* add UDP pseudo header */ | ||
1080 | temp = 0x1100; | ||
1081 | *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound)) = temp; | ||
1082 | temp = (udp_length<<8)|(udp_length>>8); | ||
1083 | *((unsigned short *)(p_udp_pkt->data+mbox_len+even_bound+2)) = temp; | ||
1084 | |||
1085 | /* calculate UDP checksum */ | ||
1086 | p_udp_pkt->udp_pkt.udp_checksum = 0; | ||
1087 | p_udp_pkt->udp_pkt.udp_checksum = | ||
1088 | calc_checksum(&data[UDP_OFFSET],udp_length+UDP_OFFSET); | ||
1089 | |||
1090 | /* fill in IP length */ | ||
1091 | ip_length = udp_length + sizeof(ip_pkt_t); | ||
1092 | temp = (ip_length<<8)|(ip_length>>8); | ||
1093 | p_udp_pkt->ip_pkt.total_length = temp; | ||
1094 | |||
1095 | /* swap IP addresses */ | ||
1096 | ip_temp = p_udp_pkt->ip_pkt.ip_src_address; | ||
1097 | p_udp_pkt->ip_pkt.ip_src_address = p_udp_pkt->ip_pkt.ip_dst_address; | ||
1098 | p_udp_pkt->ip_pkt.ip_dst_address = ip_temp; | ||
1099 | |||
1100 | /* fill in IP checksum */ | ||
1101 | p_udp_pkt->ip_pkt.hdr_checksum = 0; | ||
1102 | p_udp_pkt->ip_pkt.hdr_checksum = calc_checksum(data,sizeof(ip_pkt_t)); | ||
1103 | |||
1104 | return len; | ||
1105 | |||
1106 | } /* reply_udp */ | ||
1107 | |||
1108 | unsigned short calc_checksum (char *data, int len) | ||
1109 | { | ||
1110 | unsigned short temp; | ||
1111 | unsigned long sum=0; | ||
1112 | int i; | ||
1113 | |||
1114 | for( i = 0; i <len; i+=2 ) { | ||
1115 | memcpy(&temp,&data[i],2); | ||
1116 | sum += (unsigned long)temp; | ||
1117 | } | ||
1118 | |||
1119 | while (sum >> 16 ) { | ||
1120 | sum = (sum & 0xffffUL) + (sum >> 16); | ||
1121 | } | ||
1122 | |||
1123 | temp = (unsigned short)sum; | ||
1124 | temp = ~temp; | ||
1125 | |||
1126 | if( temp == 0 ) | ||
1127 | temp = 0xffff; | ||
1128 | |||
1129 | return temp; | ||
1130 | } | ||
1131 | |||
1132 | /* | ||
1133 | If incoming is 0 (outgoing)- if the net numbers is ours make it 0 | ||
1134 | if incoming is 1 - if the net number is 0 make it ours | ||
1135 | |||
1136 | */ | ||
1137 | static void switch_net_numbers(unsigned char *sendpacket, unsigned long network_number, unsigned char incoming) | ||
1138 | { | ||
1139 | unsigned long pnetwork_number; | ||
1140 | |||
1141 | pnetwork_number = (unsigned long)((sendpacket[6] << 24) + | ||
1142 | (sendpacket[7] << 16) + (sendpacket[8] << 8) + | ||
1143 | sendpacket[9]); | ||
1144 | |||
1145 | if (!incoming) { | ||
1146 | //If the destination network number is ours, make it 0 | ||
1147 | if( pnetwork_number == network_number) { | ||
1148 | sendpacket[6] = sendpacket[7] = sendpacket[8] = | ||
1149 | sendpacket[9] = 0x00; | ||
1150 | } | ||
1151 | } else { | ||
1152 | //If the incoming network is 0, make it ours | ||
1153 | if( pnetwork_number == 0) { | ||
1154 | sendpacket[6] = (unsigned char)(network_number >> 24); | ||
1155 | sendpacket[7] = (unsigned char)((network_number & | ||
1156 | 0x00FF0000) >> 16); | ||
1157 | sendpacket[8] = (unsigned char)((network_number & | ||
1158 | 0x0000FF00) >> 8); | ||
1159 | sendpacket[9] = (unsigned char)(network_number & | ||
1160 | 0x000000FF); | ||
1161 | } | ||
1162 | } | ||
1163 | |||
1164 | |||
1165 | pnetwork_number = (unsigned long)((sendpacket[18] << 24) + | ||
1166 | (sendpacket[19] << 16) + (sendpacket[20] << 8) + | ||
1167 | sendpacket[21]); | ||
1168 | |||
1169 | if( !incoming ) { | ||
1170 | //If the source network is ours, make it 0 | ||
1171 | if( pnetwork_number == network_number) { | ||
1172 | sendpacket[18] = sendpacket[19] = sendpacket[20] = | ||
1173 | sendpacket[21] = 0x00; | ||
1174 | } | ||
1175 | } else { | ||
1176 | //If the source network is 0, make it ours | ||
1177 | if( pnetwork_number == 0 ) { | ||
1178 | sendpacket[18] = (unsigned char)(network_number >> 24); | ||
1179 | sendpacket[19] = (unsigned char)((network_number & | ||
1180 | 0x00FF0000) >> 16); | ||
1181 | sendpacket[20] = (unsigned char)((network_number & | ||
1182 | 0x0000FF00) >> 8); | ||
1183 | sendpacket[21] = (unsigned char)(network_number & | ||
1184 | 0x000000FF); | ||
1185 | } | ||
1186 | } | ||
1187 | } /* switch_net_numbers */ | ||
1188 | |||
1189 | /*============================================================================ | ||
1190 | * Get ethernet-style interface statistics. | ||
1191 | * Return a pointer to struct net_device_stats. | ||
1192 | */ | ||
1193 | static struct net_device_stats *if_stats(struct net_device *dev) | ||
1194 | { | ||
1195 | |||
1196 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
1197 | sdla_t* card; | ||
1198 | |||
1199 | if( ppp_priv_area == NULL ) | ||
1200 | return NULL; | ||
1201 | |||
1202 | card = ppp_priv_area->card; | ||
1203 | return &card->wandev.stats; | ||
1204 | } | ||
1205 | |||
1206 | /****** PPP Firmware Interface Functions ************************************/ | ||
1207 | |||
1208 | /*============================================================================ | ||
1209 | * Read firmware code version. | ||
1210 | * Put code version as ASCII string in str. | ||
1211 | */ | ||
1212 | static int ppp_read_version(sdla_t *card, char *str) | ||
1213 | { | ||
1214 | ppp_mbox_t *mb = card->mbox; | ||
1215 | int err; | ||
1216 | |||
1217 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1218 | mb->cmd.command = PPP_READ_CODE_VERSION; | ||
1219 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1220 | |||
1221 | if (err != CMD_OK) | ||
1222 | |||
1223 | ppp_error(card, err, mb); | ||
1224 | |||
1225 | else if (str) { | ||
1226 | |||
1227 | int len = mb->cmd.length; | ||
1228 | |||
1229 | memcpy(str, mb->data, len); | ||
1230 | str[len] = '\0'; | ||
1231 | |||
1232 | } | ||
1233 | |||
1234 | return err; | ||
1235 | } | ||
1236 | /*=========================================================================== | ||
1237 | * Set Out-Bound Authentication. | ||
1238 | */ | ||
1239 | static int ppp_set_outbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area) | ||
1240 | { | ||
1241 | ppp_mbox_t *mb = card->mbox; | ||
1242 | int err; | ||
1243 | |||
1244 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1245 | memset(&mb->data, 0, (strlen(ppp_priv_area->userid) + | ||
1246 | strlen(ppp_priv_area->passwd) + 2 ) ); | ||
1247 | memcpy(mb->data, ppp_priv_area->userid, strlen(ppp_priv_area->userid)); | ||
1248 | memcpy((mb->data + strlen(ppp_priv_area->userid) + 1), | ||
1249 | ppp_priv_area->passwd, strlen(ppp_priv_area->passwd)); | ||
1250 | |||
1251 | mb->cmd.length = strlen(ppp_priv_area->userid) + | ||
1252 | strlen(ppp_priv_area->passwd) + 2 ; | ||
1253 | |||
1254 | mb->cmd.command = PPP_SET_OUTBOUND_AUTH; | ||
1255 | |||
1256 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1257 | |||
1258 | if (err != CMD_OK) | ||
1259 | ppp_error(card, err, mb); | ||
1260 | |||
1261 | return err; | ||
1262 | } | ||
1263 | |||
1264 | /*=========================================================================== | ||
1265 | * Set In-Bound Authentication. | ||
1266 | */ | ||
1267 | static int ppp_set_inbnd_auth (sdla_t *card, ppp_private_area_t *ppp_priv_area) | ||
1268 | { | ||
1269 | ppp_mbox_t *mb = card->mbox; | ||
1270 | int err, i; | ||
1271 | char* user_tokens[32]; | ||
1272 | char* pass_tokens[32]; | ||
1273 | int userids, passwds; | ||
1274 | int add_ptr; | ||
1275 | |||
1276 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1277 | memset(&mb->data, 0, 1008); | ||
1278 | memcpy(mb->data, ppp_priv_area->sysname, | ||
1279 | strlen(ppp_priv_area->sysname)); | ||
1280 | |||
1281 | /* Parse the userid string and the password string and build a string | ||
1282 | to copy it to the data area of the command structure. The string | ||
1283 | will look like "SYS_NAME<NULL>USER1<NULL>PASS1<NULL>USER2<NULL>PASS2 | ||
1284 | ....<NULL> " | ||
1285 | */ | ||
1286 | userids = tokenize( ppp_priv_area->userid, user_tokens); | ||
1287 | passwds = tokenize( ppp_priv_area->passwd, pass_tokens); | ||
1288 | |||
1289 | if (userids != passwds){ | ||
1290 | printk(KERN_INFO "%s: Number of passwords does not equal the number of user ids\n", card->devname); | ||
1291 | return 1; | ||
1292 | } | ||
1293 | |||
1294 | add_ptr = strlen(ppp_priv_area->sysname) + 1; | ||
1295 | for (i=0; i<userids; i++){ | ||
1296 | memcpy((mb->data + add_ptr), user_tokens[i], | ||
1297 | strlen(user_tokens[i])); | ||
1298 | memcpy((mb->data + add_ptr + strlen(user_tokens[i]) + 1), | ||
1299 | pass_tokens[i], strlen(pass_tokens[i])); | ||
1300 | add_ptr = add_ptr + strlen(user_tokens[i]) + 1 + | ||
1301 | strlen(pass_tokens[i]) + 1; | ||
1302 | } | ||
1303 | |||
1304 | mb->cmd.length = add_ptr + 1; | ||
1305 | mb->cmd.command = PPP_SET_INBOUND_AUTH; | ||
1306 | |||
1307 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1308 | |||
1309 | if (err != CMD_OK) | ||
1310 | ppp_error(card, err, mb); | ||
1311 | |||
1312 | return err; | ||
1313 | } | ||
1314 | |||
1315 | |||
1316 | /*============================================================================ | ||
1317 | * Tokenize string. | ||
1318 | * Parse a string of the following syntax: | ||
1319 | * <arg1>,<arg2>,... | ||
1320 | * and fill array of tokens with pointers to string elements. | ||
1321 | * | ||
1322 | */ | ||
1323 | static int tokenize (char *str, char **tokens) | ||
1324 | { | ||
1325 | int cnt = 0; | ||
1326 | |||
1327 | tokens[0] = strsep(&str, "/"); | ||
1328 | while (tokens[cnt] && (cnt < 32 - 1)) | ||
1329 | { | ||
1330 | tokens[cnt] = strstrip(tokens[cnt], " \t"); | ||
1331 | tokens[++cnt] = strsep(&str, "/"); | ||
1332 | } | ||
1333 | return cnt; | ||
1334 | } | ||
1335 | |||
1336 | /*============================================================================ | ||
1337 | * Strip leading and trailing spaces off the string str. | ||
1338 | */ | ||
1339 | static char* strstrip (char *str, char* s) | ||
1340 | { | ||
1341 | char *eos = str + strlen(str); /* -> end of string */ | ||
1342 | |||
1343 | while (*str && strchr(s, *str)) | ||
1344 | ++str /* strip leading spaces */ | ||
1345 | ; | ||
1346 | while ((eos > str) && strchr(s, *(eos - 1))) | ||
1347 | --eos /* strip trailing spaces */ | ||
1348 | ; | ||
1349 | *eos = '\0'; | ||
1350 | return str; | ||
1351 | } | ||
1352 | /*============================================================================ | ||
1353 | * Configure PPP firmware. | ||
1354 | */ | ||
1355 | static int ppp_configure(sdla_t *card, void *data) | ||
1356 | { | ||
1357 | ppp_mbox_t *mb = card->mbox; | ||
1358 | int data_len = sizeof(ppp508_conf_t); | ||
1359 | int err; | ||
1360 | |||
1361 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1362 | memcpy(mb->data, data, data_len); | ||
1363 | mb->cmd.length = data_len; | ||
1364 | mb->cmd.command = PPP_SET_CONFIG; | ||
1365 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1366 | |||
1367 | if (err != CMD_OK) | ||
1368 | ppp_error(card, err, mb); | ||
1369 | |||
1370 | return err; | ||
1371 | } | ||
1372 | |||
1373 | /*============================================================================ | ||
1374 | * Set interrupt mode. | ||
1375 | */ | ||
1376 | static int ppp_set_intr_mode(sdla_t *card, unsigned char mode) | ||
1377 | { | ||
1378 | ppp_mbox_t *mb = card->mbox; | ||
1379 | ppp_intr_info_t *ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; | ||
1380 | int err; | ||
1381 | |||
1382 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1383 | ppp_intr_data->i_enable = mode; | ||
1384 | |||
1385 | ppp_intr_data->irq = card->hw.irq; | ||
1386 | mb->cmd.length = 2; | ||
1387 | |||
1388 | /* If timer has been enabled, set the timer delay to 1sec */ | ||
1389 | if (mode & 0x80){ | ||
1390 | ppp_intr_data->timer_len = 250; //5;//100; //250; | ||
1391 | mb->cmd.length = 4; | ||
1392 | } | ||
1393 | |||
1394 | mb->cmd.command = PPP_SET_INTR_FLAGS; | ||
1395 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1396 | |||
1397 | if (err != CMD_OK) | ||
1398 | ppp_error(card, err, mb); | ||
1399 | |||
1400 | |||
1401 | return err; | ||
1402 | } | ||
1403 | |||
1404 | /*============================================================================ | ||
1405 | * Enable communications. | ||
1406 | */ | ||
1407 | static int ppp_comm_enable(sdla_t *card) | ||
1408 | { | ||
1409 | ppp_mbox_t *mb = card->mbox; | ||
1410 | int err; | ||
1411 | |||
1412 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1413 | mb->cmd.command = PPP_COMM_ENABLE; | ||
1414 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1415 | |||
1416 | if (err != CMD_OK) | ||
1417 | ppp_error(card, err, mb); | ||
1418 | else | ||
1419 | card->u.p.comm_enabled = 1; | ||
1420 | |||
1421 | return err; | ||
1422 | } | ||
1423 | |||
1424 | /*============================================================================ | ||
1425 | * Disable communications. | ||
1426 | */ | ||
1427 | static int ppp_comm_disable(sdla_t *card) | ||
1428 | { | ||
1429 | ppp_mbox_t *mb = card->mbox; | ||
1430 | int err; | ||
1431 | |||
1432 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1433 | mb->cmd.command = PPP_COMM_DISABLE; | ||
1434 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1435 | if (err != CMD_OK) | ||
1436 | ppp_error(card, err, mb); | ||
1437 | else | ||
1438 | card->u.p.comm_enabled = 0; | ||
1439 | |||
1440 | return err; | ||
1441 | } | ||
1442 | |||
1443 | static int ppp_comm_disable_shutdown(sdla_t *card) | ||
1444 | { | ||
1445 | ppp_mbox_t *mb = card->mbox; | ||
1446 | ppp_intr_info_t *ppp_intr_data; | ||
1447 | int err; | ||
1448 | |||
1449 | if (!mb){ | ||
1450 | return 1; | ||
1451 | } | ||
1452 | |||
1453 | ppp_intr_data = (ppp_intr_info_t *) &mb->data[0]; | ||
1454 | |||
1455 | /* Disable all interrupts */ | ||
1456 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1457 | ppp_intr_data->i_enable = 0; | ||
1458 | |||
1459 | ppp_intr_data->irq = card->hw.irq; | ||
1460 | mb->cmd.length = 2; | ||
1461 | |||
1462 | mb->cmd.command = PPP_SET_INTR_FLAGS; | ||
1463 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1464 | |||
1465 | /* Disable communicatinons */ | ||
1466 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1467 | mb->cmd.command = PPP_COMM_DISABLE; | ||
1468 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1469 | |||
1470 | card->u.p.comm_enabled = 0; | ||
1471 | |||
1472 | return 0; | ||
1473 | } | ||
1474 | |||
1475 | |||
1476 | |||
1477 | /*============================================================================ | ||
1478 | * Get communications error statistics. | ||
1479 | */ | ||
1480 | static int ppp_get_err_stats(sdla_t *card) | ||
1481 | { | ||
1482 | ppp_mbox_t *mb = card->mbox; | ||
1483 | int err; | ||
1484 | |||
1485 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
1486 | mb->cmd.command = PPP_READ_ERROR_STATS; | ||
1487 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
1488 | |||
1489 | if (err == CMD_OK) { | ||
1490 | |||
1491 | ppp_err_stats_t* stats = (void*)mb->data; | ||
1492 | card->wandev.stats.rx_over_errors = stats->rx_overrun; | ||
1493 | card->wandev.stats.rx_crc_errors = stats->rx_bad_crc; | ||
1494 | card->wandev.stats.rx_missed_errors = stats->rx_abort; | ||
1495 | card->wandev.stats.rx_length_errors = stats->rx_lost; | ||
1496 | card->wandev.stats.tx_aborted_errors = stats->tx_abort; | ||
1497 | |||
1498 | } else | ||
1499 | ppp_error(card, err, mb); | ||
1500 | |||
1501 | return err; | ||
1502 | } | ||
1503 | |||
1504 | /*============================================================================ | ||
1505 | * Send packet. | ||
1506 | * Return: 0 - o.k. | ||
1507 | * 1 - no transmit buffers available | ||
1508 | */ | ||
1509 | static int ppp_send (sdla_t *card, void *data, unsigned len, unsigned proto) | ||
1510 | { | ||
1511 | ppp_buf_ctl_t *txbuf = card->u.p.txbuf; | ||
1512 | |||
1513 | if (txbuf->flag) | ||
1514 | return 1; | ||
1515 | |||
1516 | sdla_poke(&card->hw, txbuf->buf.ptr, data, len); | ||
1517 | |||
1518 | txbuf->length = len; /* frame length */ | ||
1519 | |||
1520 | if (proto == htons(ETH_P_IPX)) | ||
1521 | txbuf->proto = 0x01; /* protocol ID */ | ||
1522 | else | ||
1523 | txbuf->proto = 0x00; /* protocol ID */ | ||
1524 | |||
1525 | txbuf->flag = 1; /* start transmission */ | ||
1526 | |||
1527 | /* Update transmit buffer control fields */ | ||
1528 | card->u.p.txbuf = ++txbuf; | ||
1529 | |||
1530 | if ((void*)txbuf > card->u.p.txbuf_last) | ||
1531 | card->u.p.txbuf = card->u.p.txbuf_base; | ||
1532 | |||
1533 | return 0; | ||
1534 | } | ||
1535 | |||
1536 | /****** Firmware Error Handler **********************************************/ | ||
1537 | |||
1538 | /*============================================================================ | ||
1539 | * Firmware error handler. | ||
1540 | * This routine is called whenever firmware command returns non-zero | ||
1541 | * return code. | ||
1542 | * | ||
1543 | * Return zero if previous command has to be cancelled. | ||
1544 | */ | ||
1545 | static int ppp_error(sdla_t *card, int err, ppp_mbox_t *mb) | ||
1546 | { | ||
1547 | unsigned cmd = mb->cmd.command; | ||
1548 | |||
1549 | switch (err) { | ||
1550 | |||
1551 | case CMD_TIMEOUT: | ||
1552 | printk(KERN_ERR "%s: command 0x%02X timed out!\n", | ||
1553 | card->devname, cmd); | ||
1554 | break; | ||
1555 | |||
1556 | default: | ||
1557 | printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n" | ||
1558 | , card->devname, cmd, err); | ||
1559 | } | ||
1560 | |||
1561 | return 0; | ||
1562 | } | ||
1563 | |||
1564 | /****** Interrupt Handlers **************************************************/ | ||
1565 | |||
1566 | /*============================================================================ | ||
1567 | * PPP interrupt service routine. | ||
1568 | */ | ||
1569 | static void wpp_isr (sdla_t *card) | ||
1570 | { | ||
1571 | ppp_flags_t *flags = card->flags; | ||
1572 | char *ptr = &flags->iflag; | ||
1573 | struct net_device *dev = card->wandev.dev; | ||
1574 | int i; | ||
1575 | |||
1576 | card->in_isr = 1; | ||
1577 | ++card->statistics.isr_entry; | ||
1578 | |||
1579 | if (!dev && flags->iflag != PPP_INTR_CMD){ | ||
1580 | card->in_isr = 0; | ||
1581 | flags->iflag = 0; | ||
1582 | return; | ||
1583 | } | ||
1584 | |||
1585 | if (test_bit(PERI_CRIT, (void*)&card->wandev.critical)) { | ||
1586 | card->in_isr = 0; | ||
1587 | flags->iflag = 0; | ||
1588 | return; | ||
1589 | } | ||
1590 | |||
1591 | |||
1592 | if(card->hw.type != SDLA_S514){ | ||
1593 | if (test_bit(SEND_CRIT, (void*)&card->wandev.critical)) { | ||
1594 | ++card->statistics.isr_already_critical; | ||
1595 | printk (KERN_INFO "%s: Critical while in ISR!\n", | ||
1596 | card->devname); | ||
1597 | card->in_isr = 0; | ||
1598 | flags->iflag = 0; | ||
1599 | return; | ||
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | switch (flags->iflag) { | ||
1604 | |||
1605 | case PPP_INTR_RXRDY: /* receive interrupt 0x01 (bit 0)*/ | ||
1606 | ++card->statistics.isr_rx; | ||
1607 | rx_intr(card); | ||
1608 | break; | ||
1609 | |||
1610 | case PPP_INTR_TXRDY: /* transmit interrupt 0x02 (bit 1)*/ | ||
1611 | ++card->statistics.isr_tx; | ||
1612 | flags->imask &= ~PPP_INTR_TXRDY; | ||
1613 | netif_wake_queue(dev); | ||
1614 | break; | ||
1615 | |||
1616 | case PPP_INTR_CMD: /* interface command completed */ | ||
1617 | ++Intr_test_counter; | ||
1618 | ++card->statistics.isr_intr_test; | ||
1619 | break; | ||
1620 | |||
1621 | case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ | ||
1622 | case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ | ||
1623 | case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ | ||
1624 | case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ | ||
1625 | event_intr(card); | ||
1626 | break; | ||
1627 | |||
1628 | case PPP_INTR_TIMER: | ||
1629 | timer_intr(card); | ||
1630 | break; | ||
1631 | |||
1632 | default: /* unexpected interrupt */ | ||
1633 | ++card->statistics.isr_spurious; | ||
1634 | printk(KERN_INFO "%s: spurious interrupt 0x%02X!\n", | ||
1635 | card->devname, flags->iflag); | ||
1636 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
1637 | for(i = 0; i < 8; i ++) | ||
1638 | printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); | ||
1639 | printk(KERN_INFO "\n"); | ||
1640 | } | ||
1641 | |||
1642 | card->in_isr = 0; | ||
1643 | flags->iflag = 0; | ||
1644 | return; | ||
1645 | } | ||
1646 | |||
1647 | /*============================================================================ | ||
1648 | * Receive interrupt handler. | ||
1649 | */ | ||
1650 | static void rx_intr(sdla_t *card) | ||
1651 | { | ||
1652 | ppp_buf_ctl_t *rxbuf = card->rxmb; | ||
1653 | struct net_device *dev = card->wandev.dev; | ||
1654 | ppp_private_area_t *ppp_priv_area; | ||
1655 | struct sk_buff *skb; | ||
1656 | unsigned len; | ||
1657 | void *buf; | ||
1658 | int i; | ||
1659 | ppp_flags_t *flags = card->flags; | ||
1660 | char *ptr = &flags->iflag; | ||
1661 | int udp_type; | ||
1662 | |||
1663 | |||
1664 | if (rxbuf->flag != 0x01) { | ||
1665 | |||
1666 | printk(KERN_INFO | ||
1667 | "%s: corrupted Rx buffer @ 0x%X, flag = 0x%02X!\n", | ||
1668 | card->devname, (unsigned)rxbuf, rxbuf->flag); | ||
1669 | |||
1670 | printk(KERN_INFO "%s: ID Bytes = ",card->devname); | ||
1671 | |||
1672 | for(i = 0; i < 8; i ++) | ||
1673 | printk(KERN_INFO "0x%02X ", *(ptr + 0x28 + i)); | ||
1674 | printk(KERN_INFO "\n"); | ||
1675 | |||
1676 | ++card->statistics.rx_intr_corrupt_rx_bfr; | ||
1677 | |||
1678 | |||
1679 | /* Bug Fix: Mar 6 2000 | ||
1680 | * If we get a corrupted mailbox, it means that driver | ||
1681 | * is out of sync with the firmware. There is no recovery. | ||
1682 | * If we don't turn off all interrupts for this card | ||
1683 | * the machine will crash. | ||
1684 | */ | ||
1685 | printk(KERN_INFO "%s: Critical router failure ...!!!\n", card->devname); | ||
1686 | printk(KERN_INFO "Please contact Sangoma Technologies !\n"); | ||
1687 | ppp_set_intr_mode(card,0); | ||
1688 | return; | ||
1689 | } | ||
1690 | |||
1691 | if (dev && netif_running(dev) && dev->priv){ | ||
1692 | |||
1693 | len = rxbuf->length; | ||
1694 | ppp_priv_area = dev->priv; | ||
1695 | |||
1696 | /* Allocate socket buffer */ | ||
1697 | skb = dev_alloc_skb(len); | ||
1698 | |||
1699 | if (skb != NULL) { | ||
1700 | |||
1701 | /* Copy data to the socket buffer */ | ||
1702 | unsigned addr = rxbuf->buf.ptr; | ||
1703 | |||
1704 | if ((addr + len) > card->u.p.rx_top + 1) { | ||
1705 | |||
1706 | unsigned tmp = card->u.p.rx_top - addr + 1; | ||
1707 | buf = skb_put(skb, tmp); | ||
1708 | sdla_peek(&card->hw, addr, buf, tmp); | ||
1709 | addr = card->u.p.rx_base; | ||
1710 | len -= tmp; | ||
1711 | } | ||
1712 | buf = skb_put(skb, len); | ||
1713 | sdla_peek(&card->hw, addr, buf, len); | ||
1714 | |||
1715 | /* Decapsulate packet */ | ||
1716 | switch (rxbuf->proto) { | ||
1717 | |||
1718 | case 0x00: | ||
1719 | skb->protocol = htons(ETH_P_IP); | ||
1720 | break; | ||
1721 | |||
1722 | case 0x01: | ||
1723 | skb->protocol = htons(ETH_P_IPX); | ||
1724 | break; | ||
1725 | } | ||
1726 | |||
1727 | udp_type = udp_pkt_type( skb, card ); | ||
1728 | |||
1729 | if (udp_type == UDP_PTPIPE_TYPE){ | ||
1730 | |||
1731 | /* Handle a UDP Request in Timer Interrupt */ | ||
1732 | if(store_udp_mgmt_pkt(UDP_PKT_FRM_NETWORK, card, skb, dev, | ||
1733 | ppp_priv_area)){ | ||
1734 | flags->imask |= PPP_INTR_TIMER; | ||
1735 | } | ||
1736 | ++ppp_priv_area->rx_intr_stat.rx_intr_PIPE_request; | ||
1737 | |||
1738 | |||
1739 | } else if (handle_IPXWAN(skb->data,card->devname, | ||
1740 | ppp_priv_area->enable_IPX, | ||
1741 | ppp_priv_area->network_number, | ||
1742 | skb->protocol)) { | ||
1743 | |||
1744 | /* Handle an IPXWAN packet */ | ||
1745 | if( ppp_priv_area->enable_IPX) { | ||
1746 | |||
1747 | /* Make sure we are not already sending */ | ||
1748 | if (!test_bit(SEND_CRIT, &card->wandev.critical)){ | ||
1749 | ppp_send(card, skb->data, skb->len, htons(ETH_P_IPX)); | ||
1750 | } | ||
1751 | dev_kfree_skb_any(skb); | ||
1752 | |||
1753 | } else { | ||
1754 | ++card->wandev.stats.rx_dropped; | ||
1755 | } | ||
1756 | } else { | ||
1757 | /* Pass data up the protocol stack */ | ||
1758 | skb->dev = dev; | ||
1759 | skb->mac.raw = skb->data; | ||
1760 | |||
1761 | ++card->wandev.stats.rx_packets; | ||
1762 | card->wandev.stats.rx_bytes += skb->len; | ||
1763 | ++ppp_priv_area->rx_intr_stat.rx_intr_bfr_passed_to_stack; | ||
1764 | netif_rx(skb); | ||
1765 | dev->last_rx = jiffies; | ||
1766 | } | ||
1767 | |||
1768 | } else { | ||
1769 | |||
1770 | if (net_ratelimit()){ | ||
1771 | printk(KERN_INFO "%s: no socket buffers available!\n", | ||
1772 | card->devname); | ||
1773 | } | ||
1774 | ++card->wandev.stats.rx_dropped; | ||
1775 | ++ppp_priv_area->rx_intr_stat.rx_intr_no_socket; | ||
1776 | } | ||
1777 | |||
1778 | } else { | ||
1779 | ++card->statistics.rx_intr_dev_not_started; | ||
1780 | } | ||
1781 | |||
1782 | /* Release buffer element and calculate a pointer to the next one */ | ||
1783 | rxbuf->flag = 0x00; | ||
1784 | card->rxmb = ++rxbuf; | ||
1785 | if ((void*)rxbuf > card->u.p.rxbuf_last) | ||
1786 | card->rxmb = card->u.p.rxbuf_base; | ||
1787 | } | ||
1788 | |||
1789 | |||
1790 | void event_intr (sdla_t *card) | ||
1791 | { | ||
1792 | |||
1793 | struct net_device* dev = card->wandev.dev; | ||
1794 | ppp_private_area_t* ppp_priv_area = dev->priv; | ||
1795 | volatile ppp_flags_t *flags = card->flags; | ||
1796 | |||
1797 | switch (flags->iflag){ | ||
1798 | |||
1799 | case PPP_INTR_MODEM: /* modem status change (DCD, CTS) 0x04 (bit 2)*/ | ||
1800 | |||
1801 | if (net_ratelimit()){ | ||
1802 | printk (KERN_INFO "%s: Modem status: DCD=%s CTS=%s\n", | ||
1803 | card->devname, DCD(flags->mstatus), CTS(flags->mstatus)); | ||
1804 | } | ||
1805 | break; | ||
1806 | |||
1807 | case PPP_INTR_DISC: /* Data link disconnected 0x10 (bit 4)*/ | ||
1808 | |||
1809 | NEX_PRINTK (KERN_INFO "Data link disconnected intr Cause %X\n", | ||
1810 | flags->disc_cause); | ||
1811 | |||
1812 | if (flags->disc_cause & | ||
1813 | (PPP_LOCAL_TERMINATION | PPP_DCD_CTS_DROP | | ||
1814 | PPP_REMOTE_TERMINATION)) { | ||
1815 | |||
1816 | if (card->u.p.ip_mode == WANOPT_PPP_PEER) { | ||
1817 | set_bit(0,&Read_connection_info); | ||
1818 | } | ||
1819 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
1820 | |||
1821 | show_disc_cause(card, flags->disc_cause); | ||
1822 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; | ||
1823 | flags->imask |= PPP_INTR_TIMER; | ||
1824 | trigger_ppp_poll(dev); | ||
1825 | } | ||
1826 | break; | ||
1827 | |||
1828 | case PPP_INTR_OPEN: /* Data link open 0x20 (bit 5)*/ | ||
1829 | |||
1830 | NEX_PRINTK (KERN_INFO "%s: PPP Link Open, LCP=%s IP=%s\n", | ||
1831 | card->devname,LCP(flags->lcp_state), | ||
1832 | IP(flags->ip_state)); | ||
1833 | |||
1834 | if (flags->lcp_state == 0x09 && | ||
1835 | (flags->ip_state == 0x09 || flags->ipx_state == 0x09)){ | ||
1836 | |||
1837 | /* Initialize the polling timer and set the state | ||
1838 | * to WAN_CONNNECTED */ | ||
1839 | |||
1840 | |||
1841 | /* BUG FIX: When the protocol restarts, during heavy | ||
1842 | * traffic, board tx buffers and driver tx buffers | ||
1843 | * can go out of sync. This checks the condition | ||
1844 | * and if the tx buffers are out of sync, the | ||
1845 | * protocols are restarted. | ||
1846 | * I don't know why the board tx buffer is out | ||
1847 | * of sync. It could be that a packets is tx | ||
1848 | * while the link is down, but that is not | ||
1849 | * possible. The other possiblility is that the | ||
1850 | * firmware doesn't reinitialize properly. | ||
1851 | * FIXME: A better fix should be found. | ||
1852 | */ | ||
1853 | if (detect_and_fix_tx_bug(card)){ | ||
1854 | |||
1855 | ppp_comm_disable(card); | ||
1856 | |||
1857 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
1858 | |||
1859 | ppp_priv_area->timer_int_enabled |= | ||
1860 | TMR_INT_ENABLED_PPP_EVENT; | ||
1861 | flags->imask |= PPP_INTR_TIMER; | ||
1862 | break; | ||
1863 | } | ||
1864 | |||
1865 | card->state_tick = jiffies; | ||
1866 | wanpipe_set_state(card, WAN_CONNECTED); | ||
1867 | |||
1868 | NEX_PRINTK(KERN_INFO "CON: L Tx: %lx B Tx: %lx || L Rx %lx B Rx %lx\n", | ||
1869 | (unsigned long)card->u.p.txbuf, *card->u.p.txbuf_next, | ||
1870 | (unsigned long)card->rxmb, *card->u.p.rxbuf_next); | ||
1871 | |||
1872 | /* Tell timer interrupt that PPP event occurred */ | ||
1873 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; | ||
1874 | flags->imask |= PPP_INTR_TIMER; | ||
1875 | |||
1876 | /* If we are in PEER mode, we must first obtain the | ||
1877 | * IP information and then go into the poll routine */ | ||
1878 | if (card->u.p.ip_mode != WANOPT_PPP_PEER){ | ||
1879 | trigger_ppp_poll(dev); | ||
1880 | } | ||
1881 | } | ||
1882 | break; | ||
1883 | |||
1884 | case PPP_INTR_DROP_DTR: /* DTR drop timeout expired 0x40 bit 6 */ | ||
1885 | |||
1886 | NEX_PRINTK(KERN_INFO "DTR Drop Timeout Interrrupt \n"); | ||
1887 | |||
1888 | if (card->u.p.ip_mode == WANOPT_PPP_PEER) { | ||
1889 | set_bit(0,&Read_connection_info); | ||
1890 | } | ||
1891 | |||
1892 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
1893 | |||
1894 | show_disc_cause(card, flags->disc_cause); | ||
1895 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_PPP_EVENT; | ||
1896 | flags->imask |= PPP_INTR_TIMER; | ||
1897 | trigger_ppp_poll(dev); | ||
1898 | break; | ||
1899 | |||
1900 | default: | ||
1901 | printk(KERN_INFO "%s: Error, Invalid PPP Event\n",card->devname); | ||
1902 | } | ||
1903 | } | ||
1904 | |||
1905 | |||
1906 | |||
1907 | /* TIMER INTERRUPT */ | ||
1908 | |||
1909 | void timer_intr (sdla_t *card) | ||
1910 | { | ||
1911 | |||
1912 | struct net_device* dev = card->wandev.dev; | ||
1913 | ppp_private_area_t* ppp_priv_area = dev->priv; | ||
1914 | ppp_flags_t *flags = card->flags; | ||
1915 | |||
1916 | |||
1917 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_CONFIG){ | ||
1918 | if (!config_ppp(card)){ | ||
1919 | ppp_priv_area->timer_int_enabled &= | ||
1920 | ~TMR_INT_ENABLED_CONFIG; | ||
1921 | } | ||
1922 | } | ||
1923 | |||
1924 | /* Update statistics */ | ||
1925 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UPDATE){ | ||
1926 | ppp_get_err_stats(card); | ||
1927 | if(!(--ppp_priv_area->update_comms_stats)){ | ||
1928 | ppp_priv_area->timer_int_enabled &= | ||
1929 | ~TMR_INT_ENABLED_UPDATE; | ||
1930 | } | ||
1931 | } | ||
1932 | |||
1933 | /* PPIPEMON UDP request */ | ||
1934 | |||
1935 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_UDP){ | ||
1936 | process_udp_mgmt_pkt(card,dev, ppp_priv_area); | ||
1937 | ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_UDP; | ||
1938 | } | ||
1939 | |||
1940 | /* PPP Event */ | ||
1941 | if (ppp_priv_area->timer_int_enabled & TMR_INT_ENABLED_PPP_EVENT){ | ||
1942 | |||
1943 | if (card->wandev.state == WAN_DISCONNECTED){ | ||
1944 | retrigger_comm(card); | ||
1945 | } | ||
1946 | |||
1947 | /* If the state is CONNECTING, it means that communicatins were | ||
1948 | * enabled. When the remote side enables its comminication we | ||
1949 | * should get an interrupt PPP_INTR_OPEN, thus turn off polling | ||
1950 | */ | ||
1951 | |||
1952 | else if (card->wandev.state == WAN_CONNECTING){ | ||
1953 | /* Turn off the timer interrupt */ | ||
1954 | ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; | ||
1955 | } | ||
1956 | |||
1957 | /* If state is connected and we are in PEER mode | ||
1958 | * poll for an IP address which will be provided by remote end. | ||
1959 | */ | ||
1960 | else if ((card->wandev.state == WAN_CONNECTED && | ||
1961 | card->u.p.ip_mode == WANOPT_PPP_PEER) && | ||
1962 | test_bit(0,&Read_connection_info)){ | ||
1963 | |||
1964 | card->state_tick = jiffies; | ||
1965 | if (read_connection_info (card)){ | ||
1966 | printk(KERN_INFO "%s: Failed to read PEER IP Addresses\n", | ||
1967 | card->devname); | ||
1968 | }else{ | ||
1969 | clear_bit(0,&Read_connection_info); | ||
1970 | set_bit(1,&Read_connection_info); | ||
1971 | trigger_ppp_poll(dev); | ||
1972 | } | ||
1973 | }else{ | ||
1974 | //FIXME Put the comment back int | ||
1975 | ppp_priv_area->timer_int_enabled &= ~TMR_INT_ENABLED_PPP_EVENT; | ||
1976 | } | ||
1977 | |||
1978 | }/* End of PPP_EVENT */ | ||
1979 | |||
1980 | |||
1981 | /* Only disable the timer interrupt if there are no udp, statistic */ | ||
1982 | /* updates or events pending */ | ||
1983 | if(!ppp_priv_area->timer_int_enabled) { | ||
1984 | flags->imask &= ~PPP_INTR_TIMER; | ||
1985 | } | ||
1986 | } | ||
1987 | |||
1988 | |||
1989 | static int handle_IPXWAN(unsigned char *sendpacket, char *devname, unsigned char enable_IPX, unsigned long network_number, unsigned short proto) | ||
1990 | { | ||
1991 | int i; | ||
1992 | |||
1993 | if( proto == htons(ETH_P_IPX) ) { | ||
1994 | //It's an IPX packet | ||
1995 | if(!enable_IPX) { | ||
1996 | //Return 1 so we don't pass it up the stack. | ||
1997 | return 1; | ||
1998 | } | ||
1999 | } else { | ||
2000 | //It's not IPX so pass it up the stack. | ||
2001 | return 0; | ||
2002 | } | ||
2003 | |||
2004 | if( sendpacket[16] == 0x90 && | ||
2005 | sendpacket[17] == 0x04) | ||
2006 | { | ||
2007 | //It's IPXWAN | ||
2008 | |||
2009 | if( sendpacket[2] == 0x02 && | ||
2010 | sendpacket[34] == 0x00) | ||
2011 | { | ||
2012 | //It's a timer request packet | ||
2013 | printk(KERN_INFO "%s: Received IPXWAN Timer Request packet\n",devname); | ||
2014 | |||
2015 | //Go through the routing options and answer no to every | ||
2016 | //option except Unnumbered RIP/SAP | ||
2017 | for(i = 41; sendpacket[i] == 0x00; i += 5) | ||
2018 | { | ||
2019 | //0x02 is the option for Unnumbered RIP/SAP | ||
2020 | if( sendpacket[i + 4] != 0x02) | ||
2021 | { | ||
2022 | sendpacket[i + 1] = 0; | ||
2023 | } | ||
2024 | } | ||
2025 | |||
2026 | //Skip over the extended Node ID option | ||
2027 | if( sendpacket[i] == 0x04 ) | ||
2028 | { | ||
2029 | i += 8; | ||
2030 | } | ||
2031 | |||
2032 | //We also want to turn off all header compression opt. | ||
2033 | for(; sendpacket[i] == 0x80 ;) | ||
2034 | { | ||
2035 | sendpacket[i + 1] = 0; | ||
2036 | i += (sendpacket[i + 2] << 8) + (sendpacket[i + 3]) + 4; | ||
2037 | } | ||
2038 | |||
2039 | //Set the packet type to timer response | ||
2040 | sendpacket[34] = 0x01; | ||
2041 | |||
2042 | printk(KERN_INFO "%s: Sending IPXWAN Timer Response\n",devname); | ||
2043 | } | ||
2044 | else if( sendpacket[34] == 0x02 ) | ||
2045 | { | ||
2046 | //This is an information request packet | ||
2047 | printk(KERN_INFO "%s: Received IPXWAN Information Request packet\n",devname); | ||
2048 | |||
2049 | //Set the packet type to information response | ||
2050 | sendpacket[34] = 0x03; | ||
2051 | |||
2052 | //Set the router name | ||
2053 | sendpacket[51] = 'P'; | ||
2054 | sendpacket[52] = 'T'; | ||
2055 | sendpacket[53] = 'P'; | ||
2056 | sendpacket[54] = 'I'; | ||
2057 | sendpacket[55] = 'P'; | ||
2058 | sendpacket[56] = 'E'; | ||
2059 | sendpacket[57] = '-'; | ||
2060 | sendpacket[58] = CVHexToAscii(network_number >> 28); | ||
2061 | sendpacket[59] = CVHexToAscii((network_number & 0x0F000000)>> 24); | ||
2062 | sendpacket[60] = CVHexToAscii((network_number & 0x00F00000)>> 20); | ||
2063 | sendpacket[61] = CVHexToAscii((network_number & 0x000F0000)>> 16); | ||
2064 | sendpacket[62] = CVHexToAscii((network_number & 0x0000F000)>> 12); | ||
2065 | sendpacket[63] = CVHexToAscii((network_number & 0x00000F00)>> 8); | ||
2066 | sendpacket[64] = CVHexToAscii((network_number & 0x000000F0)>> 4); | ||
2067 | sendpacket[65] = CVHexToAscii(network_number & 0x0000000F); | ||
2068 | for(i = 66; i < 99; i+= 1) | ||
2069 | { | ||
2070 | sendpacket[i] = 0; | ||
2071 | } | ||
2072 | |||
2073 | printk(KERN_INFO "%s: Sending IPXWAN Information Response packet\n",devname); | ||
2074 | } | ||
2075 | else | ||
2076 | { | ||
2077 | printk(KERN_INFO "%s: Unknown IPXWAN packet!\n",devname); | ||
2078 | return 0; | ||
2079 | } | ||
2080 | |||
2081 | //Set the WNodeID to our network address | ||
2082 | sendpacket[35] = (unsigned char)(network_number >> 24); | ||
2083 | sendpacket[36] = (unsigned char)((network_number & 0x00FF0000) >> 16); | ||
2084 | sendpacket[37] = (unsigned char)((network_number & 0x0000FF00) >> 8); | ||
2085 | sendpacket[38] = (unsigned char)(network_number & 0x000000FF); | ||
2086 | |||
2087 | return 1; | ||
2088 | } else { | ||
2089 | //If we get here it's an IPX-data packet, so it'll get passed up the stack. | ||
2090 | |||
2091 | //switch the network numbers | ||
2092 | switch_net_numbers(sendpacket, network_number, 1); | ||
2093 | return 0; | ||
2094 | } | ||
2095 | } | ||
2096 | |||
2097 | /****** Background Polling Routines ****************************************/ | ||
2098 | |||
2099 | /* All polling functions are invoked by the TIMER interrupt in the wpp_isr | ||
2100 | * routine. | ||
2101 | */ | ||
2102 | |||
2103 | /*============================================================================ | ||
2104 | * Monitor active link phase. | ||
2105 | */ | ||
2106 | static void process_route (sdla_t *card) | ||
2107 | { | ||
2108 | ppp_flags_t *flags = card->flags; | ||
2109 | struct net_device *dev = card->wandev.dev; | ||
2110 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
2111 | |||
2112 | if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && | ||
2113 | (flags->ip_state == 0x09)){ | ||
2114 | |||
2115 | /* We get ip_local from the firmware in PEER mode. | ||
2116 | * Therefore, if ip_local is 0, we failed to obtain | ||
2117 | * the remote IP address. */ | ||
2118 | if (ppp_priv_area->ip_local == 0) | ||
2119 | return; | ||
2120 | |||
2121 | printk(KERN_INFO "%s: IPCP State Opened.\n", card->devname); | ||
2122 | if (read_info( card )) { | ||
2123 | printk(KERN_INFO | ||
2124 | "%s: An error occurred in IP assignment.\n", | ||
2125 | card->devname); | ||
2126 | } else { | ||
2127 | struct in_device *in_dev = dev->ip_ptr; | ||
2128 | if (in_dev != NULL ) { | ||
2129 | struct in_ifaddr *ifa = in_dev->ifa_list; | ||
2130 | |||
2131 | printk(KERN_INFO "%s: Assigned Lcl. Addr: %u.%u.%u.%u\n", | ||
2132 | card->devname, NIPQUAD(ifa->ifa_local)); | ||
2133 | printk(KERN_INFO "%s: Assigned Rmt. Addr: %u.%u.%u.%u\n", | ||
2134 | card->devname, NIPQUAD(ifa->ifa_address)); | ||
2135 | }else{ | ||
2136 | printk(KERN_INFO | ||
2137 | "%s: Error: Failed to add a route for PPP interface %s\n", | ||
2138 | card->devname,dev->name); | ||
2139 | } | ||
2140 | } | ||
2141 | } | ||
2142 | } | ||
2143 | |||
2144 | /*============================================================================ | ||
2145 | * Monitor physical link disconnected phase. | ||
2146 | * o if interface is up and the hold-down timeout has expired, then retry | ||
2147 | * connection. | ||
2148 | */ | ||
2149 | static void retrigger_comm(sdla_t *card) | ||
2150 | { | ||
2151 | struct net_device *dev = card->wandev.dev; | ||
2152 | |||
2153 | if (dev && ((jiffies - card->state_tick) > HOLD_DOWN_TIME)) { | ||
2154 | |||
2155 | wanpipe_set_state(card, WAN_CONNECTING); | ||
2156 | |||
2157 | if(ppp_comm_enable(card) == CMD_OK){ | ||
2158 | init_ppp_tx_rx_buff( card ); | ||
2159 | } | ||
2160 | } | ||
2161 | } | ||
2162 | |||
2163 | /****** Miscellaneous Functions *********************************************/ | ||
2164 | |||
2165 | /*============================================================================ | ||
2166 | * Configure S508 adapter. | ||
2167 | */ | ||
2168 | static int config508(struct net_device *dev, sdla_t *card) | ||
2169 | { | ||
2170 | ppp508_conf_t cfg; | ||
2171 | struct in_device *in_dev = dev->ip_ptr; | ||
2172 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
2173 | |||
2174 | /* Prepare PPP configuration structure */ | ||
2175 | memset(&cfg, 0, sizeof(ppp508_conf_t)); | ||
2176 | |||
2177 | if (card->wandev.clocking) | ||
2178 | cfg.line_speed = card->wandev.bps; | ||
2179 | |||
2180 | if (card->wandev.interface == WANOPT_RS232) | ||
2181 | cfg.conf_flags |= INTERFACE_LEVEL_RS232; | ||
2182 | |||
2183 | |||
2184 | cfg.conf_flags |= DONT_TERMINATE_LNK_MAX_CONFIG; /*send Configure-Request packets forever*/ | ||
2185 | cfg.txbuf_percent = PERCENT_TX_BUFF; /* % of Tx bufs */ | ||
2186 | cfg.mtu_local = card->wandev.mtu; | ||
2187 | cfg.mtu_remote = card->wandev.mtu; /* Default */ | ||
2188 | cfg.restart_tmr = TIME_BETWEEN_CONF_REQ; /* 30 = 3sec */ | ||
2189 | cfg.auth_rsrt_tmr = TIME_BETWEEN_PAP_CHAP_REQ; /* 30 = 3sec */ | ||
2190 | cfg.auth_wait_tmr = WAIT_PAP_CHAP_WITHOUT_REPLY; /* 300 = 30s */ | ||
2191 | cfg.mdm_fail_tmr = WAIT_AFTER_DCD_CTS_LOW; /* 5 = 0.5s */ | ||
2192 | cfg.dtr_drop_tmr = TIME_DCD_CTS_LOW_AFTER_LNK_DOWN; /* 10 = 1s */ | ||
2193 | cfg.connect_tmout = WAIT_DCD_HIGH_AFTER_ENABLE_COMM; /* 900 = 90s */ | ||
2194 | cfg.conf_retry = MAX_CONF_REQ_WITHOUT_REPLY; /* 10 = 1s */ | ||
2195 | cfg.term_retry = MAX_TERM_REQ_WITHOUT_REPLY; /* 2 times */ | ||
2196 | cfg.fail_retry = NUM_CONF_NAK_WITHOUT_REPLY; /* 5 times */ | ||
2197 | cfg.auth_retry = NUM_AUTH_REQ_WITHOUT_REPLY; /* 10 times */ | ||
2198 | |||
2199 | |||
2200 | if( !card->u.p.authenticator ) { | ||
2201 | printk(KERN_INFO "%s: Device is not configured as an authenticator\n", | ||
2202 | card->devname); | ||
2203 | cfg.auth_options = NO_AUTHENTICATION; | ||
2204 | }else{ | ||
2205 | printk(KERN_INFO "%s: Device is configured as an authenticator\n", | ||
2206 | card->devname); | ||
2207 | cfg.auth_options = INBOUND_AUTH; | ||
2208 | } | ||
2209 | |||
2210 | if( ppp_priv_area->pap == WANOPT_YES){ | ||
2211 | cfg.auth_options |=PAP_AUTH; | ||
2212 | printk(KERN_INFO "%s: Pap enabled\n", card->devname); | ||
2213 | } | ||
2214 | if( ppp_priv_area->chap == WANOPT_YES){ | ||
2215 | cfg.auth_options |= CHAP_AUTH; | ||
2216 | printk(KERN_INFO "%s: Chap enabled\n", card->devname); | ||
2217 | } | ||
2218 | |||
2219 | |||
2220 | if (ppp_priv_area->enable_IPX == WANOPT_YES){ | ||
2221 | printk(KERN_INFO "%s: Enabling IPX Protocol\n",card->devname); | ||
2222 | cfg.ipx_options = ENABLE_IPX | ROUTING_PROT_DEFAULT; | ||
2223 | }else{ | ||
2224 | cfg.ipx_options = DISABLE_IPX; | ||
2225 | } | ||
2226 | |||
2227 | switch (card->u.p.ip_mode) { | ||
2228 | |||
2229 | case WANOPT_PPP_STATIC: | ||
2230 | |||
2231 | printk(KERN_INFO "%s: PPP IP Mode: STATIC\n",card->devname); | ||
2232 | cfg.ip_options = L_AND_R_IP_NO_ASSIG | | ||
2233 | ENABLE_IP; | ||
2234 | cfg.ip_local = in_dev->ifa_list->ifa_local; | ||
2235 | cfg.ip_remote = in_dev->ifa_list->ifa_address; | ||
2236 | /* Debugging code used to check that IP addresses | ||
2237 | * obtained from the kernel are correct */ | ||
2238 | |||
2239 | NEX_PRINTK(KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", | ||
2240 | NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name); | ||
2241 | break; | ||
2242 | |||
2243 | case WANOPT_PPP_HOST: | ||
2244 | |||
2245 | printk(KERN_INFO "%s: PPP IP Mode: HOST\n",card->devname); | ||
2246 | cfg.ip_options = L_IP_LOCAL_ASSIG | | ||
2247 | R_IP_LOCAL_ASSIG | | ||
2248 | ENABLE_IP; | ||
2249 | cfg.ip_local = in_dev->ifa_list->ifa_local; | ||
2250 | cfg.ip_remote = in_dev->ifa_list->ifa_address; | ||
2251 | /* Debugging code used to check that IP addresses | ||
2252 | * obtained from the kernel are correct */ | ||
2253 | NEX_PRINTK (KERN_INFO "Local %u.%u.%u.%u Remote %u.%u.%u.%u Name %s\n", | ||
2254 | NIPQUAD(ip_local),NIPQUAD(ip_remote), dev->name); | ||
2255 | |||
2256 | break; | ||
2257 | |||
2258 | case WANOPT_PPP_PEER: | ||
2259 | |||
2260 | printk(KERN_INFO "%s: PPP IP Mode: PEER\n",card->devname); | ||
2261 | cfg.ip_options = L_IP_REMOTE_ASSIG | | ||
2262 | R_IP_REMOTE_ASSIG | | ||
2263 | ENABLE_IP; | ||
2264 | cfg.ip_local = 0x00; | ||
2265 | cfg.ip_remote = 0x00; | ||
2266 | break; | ||
2267 | |||
2268 | default: | ||
2269 | printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n", | ||
2270 | card->devname); | ||
2271 | printk(KERN_INFO "%s: PPP IP Modes: STATIC, PEER or HOST\n", | ||
2272 | card->devname); | ||
2273 | return 1; | ||
2274 | } | ||
2275 | |||
2276 | return ppp_configure(card, &cfg); | ||
2277 | } | ||
2278 | |||
2279 | /*============================================================================ | ||
2280 | * Show disconnection cause. | ||
2281 | */ | ||
2282 | static void show_disc_cause(sdla_t *card, unsigned cause) | ||
2283 | { | ||
2284 | if (cause & 0x0802) | ||
2285 | |||
2286 | printk(KERN_INFO "%s: link terminated by peer\n", | ||
2287 | card->devname); | ||
2288 | |||
2289 | else if (cause & 0x0004) | ||
2290 | |||
2291 | printk(KERN_INFO "%s: link terminated by user\n", | ||
2292 | card->devname); | ||
2293 | |||
2294 | else if (cause & 0x0008) | ||
2295 | |||
2296 | printk(KERN_INFO "%s: authentication failed\n", card->devname); | ||
2297 | |||
2298 | else if (cause & 0x0010) | ||
2299 | |||
2300 | printk(KERN_INFO | ||
2301 | "%s: authentication protocol negotiation failed\n", | ||
2302 | card->devname); | ||
2303 | |||
2304 | else if (cause & 0x0020) | ||
2305 | |||
2306 | printk(KERN_INFO | ||
2307 | "%s: peer's request for authentication rejected\n", | ||
2308 | card->devname); | ||
2309 | |||
2310 | else if (cause & 0x0040) | ||
2311 | |||
2312 | printk(KERN_INFO "%s: MRU option rejected by peer\n", | ||
2313 | card->devname); | ||
2314 | |||
2315 | else if (cause & 0x0080) | ||
2316 | |||
2317 | printk(KERN_INFO "%s: peer's MRU was too small\n", | ||
2318 | card->devname); | ||
2319 | |||
2320 | else if (cause & 0x0100) | ||
2321 | |||
2322 | printk(KERN_INFO "%s: failed to negotiate peer's LCP options\n", | ||
2323 | card->devname); | ||
2324 | |||
2325 | else if (cause & 0x0200) | ||
2326 | |||
2327 | printk(KERN_INFO "%s: failed to negotiate peer's IPCP options\n" | ||
2328 | , card->devname); | ||
2329 | |||
2330 | else if (cause & 0x0400) | ||
2331 | |||
2332 | printk(KERN_INFO | ||
2333 | "%s: failed to negotiate peer's IPXCP options\n", | ||
2334 | card->devname); | ||
2335 | } | ||
2336 | |||
2337 | /*============================================================================= | ||
2338 | * Process UDP call of type PTPIPEAB. | ||
2339 | */ | ||
2340 | static void process_udp_mgmt_pkt(sdla_t *card, struct net_device *dev, | ||
2341 | ppp_private_area_t *ppp_priv_area ) | ||
2342 | { | ||
2343 | unsigned char buf2[5]; | ||
2344 | unsigned char *buf; | ||
2345 | unsigned int frames, len; | ||
2346 | struct sk_buff *new_skb; | ||
2347 | unsigned short data_length, buffer_length, real_len; | ||
2348 | unsigned long data_ptr; | ||
2349 | int udp_mgmt_req_valid = 1; | ||
2350 | ppp_mbox_t *mbox = card->mbox; | ||
2351 | struct timeval tv; | ||
2352 | int err; | ||
2353 | ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t*)&ppp_priv_area->udp_pkt_data; | ||
2354 | |||
2355 | memcpy(&buf2, &card->wandev.udp_port, 2 ); | ||
2356 | |||
2357 | |||
2358 | if(ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
2359 | |||
2360 | switch(ppp_udp_pkt->cblock.command) { | ||
2361 | |||
2362 | case PPIPE_GET_IBA_DATA: | ||
2363 | case PPP_READ_CONFIG: | ||
2364 | case PPP_GET_CONNECTION_INFO: | ||
2365 | case PPIPE_ROUTER_UP_TIME: | ||
2366 | case PPP_READ_STATISTICS: | ||
2367 | case PPP_READ_ERROR_STATS: | ||
2368 | case PPP_READ_PACKET_STATS: | ||
2369 | case PPP_READ_LCP_STATS: | ||
2370 | case PPP_READ_IPCP_STATS: | ||
2371 | case PPP_READ_IPXCP_STATS: | ||
2372 | case PPP_READ_PAP_STATS: | ||
2373 | case PPP_READ_CHAP_STATS: | ||
2374 | case PPP_READ_CODE_VERSION: | ||
2375 | udp_mgmt_req_valid = 1; | ||
2376 | break; | ||
2377 | |||
2378 | default: | ||
2379 | udp_mgmt_req_valid = 0; | ||
2380 | break; | ||
2381 | } | ||
2382 | } | ||
2383 | |||
2384 | if(!udp_mgmt_req_valid) { | ||
2385 | |||
2386 | /* set length to 0 */ | ||
2387 | ppp_udp_pkt->cblock.length = 0x00; | ||
2388 | |||
2389 | /* set return code */ | ||
2390 | ppp_udp_pkt->cblock.result = 0xCD; | ||
2391 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_direction_err; | ||
2392 | |||
2393 | if (net_ratelimit()){ | ||
2394 | printk(KERN_INFO | ||
2395 | "%s: Warning, Illegal UDP command attempted from network: %x\n", | ||
2396 | card->devname,ppp_udp_pkt->cblock.command); | ||
2397 | } | ||
2398 | } else { | ||
2399 | /* Initialize the trace element */ | ||
2400 | trace_element_t trace_element; | ||
2401 | |||
2402 | switch (ppp_udp_pkt->cblock.command){ | ||
2403 | |||
2404 | /* PPIPE_ENABLE_TRACING */ | ||
2405 | case PPIPE_ENABLE_TRACING: | ||
2406 | if (!card->TracingEnabled) { | ||
2407 | |||
2408 | /* OPERATE_DATALINE_MONITOR */ | ||
2409 | mbox->cmd.command = PPP_DATALINE_MONITOR; | ||
2410 | mbox->cmd.length = 0x01; | ||
2411 | mbox->data[0] = ppp_udp_pkt->data[0]; | ||
2412 | err = sdla_exec(mbox) ? | ||
2413 | mbox->cmd.result : CMD_TIMEOUT; | ||
2414 | |||
2415 | if (err != CMD_OK) { | ||
2416 | |||
2417 | ppp_error(card, err, mbox); | ||
2418 | card->TracingEnabled = 0; | ||
2419 | |||
2420 | /* set the return code */ | ||
2421 | |||
2422 | ppp_udp_pkt->cblock.result = mbox->cmd.result; | ||
2423 | mbox->cmd.length = 0; | ||
2424 | break; | ||
2425 | } | ||
2426 | |||
2427 | sdla_peek(&card->hw, 0xC000, &buf2, 2); | ||
2428 | |||
2429 | ppp_priv_area->curr_trace_addr = 0; | ||
2430 | memcpy(&ppp_priv_area->curr_trace_addr, &buf2, 2); | ||
2431 | ppp_priv_area->start_trace_addr = | ||
2432 | ppp_priv_area->curr_trace_addr; | ||
2433 | ppp_priv_area->end_trace_addr = | ||
2434 | ppp_priv_area->start_trace_addr + END_OFFSET; | ||
2435 | |||
2436 | /* MAX_SEND_BUFFER_SIZE - 28 (IP header) | ||
2437 | - 32 (ppipemon CBLOCK) */ | ||
2438 | available_buffer_space = MAX_LGTH_UDP_MGNT_PKT - | ||
2439 | sizeof(ip_pkt_t)- | ||
2440 | sizeof(udp_pkt_t)- | ||
2441 | sizeof(wp_mgmt_t)- | ||
2442 | sizeof(cblock_t); | ||
2443 | } | ||
2444 | ppp_udp_pkt->cblock.result = 0; | ||
2445 | mbox->cmd.length = 0; | ||
2446 | card->TracingEnabled = 1; | ||
2447 | break; | ||
2448 | |||
2449 | /* PPIPE_DISABLE_TRACING */ | ||
2450 | case PPIPE_DISABLE_TRACING: | ||
2451 | |||
2452 | if(card->TracingEnabled) { | ||
2453 | |||
2454 | /* OPERATE_DATALINE_MONITOR */ | ||
2455 | mbox->cmd.command = 0x33; | ||
2456 | mbox->cmd.length = 1; | ||
2457 | mbox->data[0] = 0x00; | ||
2458 | err = sdla_exec(mbox) ? | ||
2459 | mbox->cmd.result : CMD_TIMEOUT; | ||
2460 | |||
2461 | } | ||
2462 | |||
2463 | /*set return code*/ | ||
2464 | ppp_udp_pkt->cblock.result = 0; | ||
2465 | mbox->cmd.length = 0; | ||
2466 | card->TracingEnabled = 0; | ||
2467 | break; | ||
2468 | |||
2469 | /* PPIPE_GET_TRACE_INFO */ | ||
2470 | case PPIPE_GET_TRACE_INFO: | ||
2471 | |||
2472 | if(!card->TracingEnabled) { | ||
2473 | /* set return code */ | ||
2474 | ppp_udp_pkt->cblock.result = 1; | ||
2475 | mbox->cmd.length = 0; | ||
2476 | } | ||
2477 | |||
2478 | buffer_length = 0; | ||
2479 | |||
2480 | /* frames < 62, where 62 is the number of trace | ||
2481 | information elements. There is in total 496 | ||
2482 | bytes of space and each trace information | ||
2483 | element is 8 bytes. | ||
2484 | */ | ||
2485 | for ( frames=0; frames<62; frames++) { | ||
2486 | |||
2487 | trace_pkt_t *trace_pkt = (trace_pkt_t *) | ||
2488 | &ppp_udp_pkt->data[buffer_length]; | ||
2489 | |||
2490 | /* Read the whole trace packet */ | ||
2491 | sdla_peek(&card->hw, ppp_priv_area->curr_trace_addr, | ||
2492 | &trace_element, sizeof(trace_element_t)); | ||
2493 | |||
2494 | /* no data on board so exit */ | ||
2495 | if( trace_element.opp_flag == 0x00 ) | ||
2496 | break; | ||
2497 | |||
2498 | data_ptr = trace_element.trace_data_ptr; | ||
2499 | |||
2500 | /* See if there is actual data on the trace buffer */ | ||
2501 | if (data_ptr){ | ||
2502 | data_length = trace_element.trace_length; | ||
2503 | }else{ | ||
2504 | data_length = 0; | ||
2505 | ppp_udp_pkt->data[0] |= 0x02; | ||
2506 | } | ||
2507 | |||
2508 | //FIXME: Do we need this check | ||
2509 | if ((available_buffer_space - buffer_length) | ||
2510 | < (sizeof(trace_element_t)+1)){ | ||
2511 | |||
2512 | /*indicate we have more frames | ||
2513 | * on board and exit | ||
2514 | */ | ||
2515 | ppp_udp_pkt->data[0] |= 0x02; | ||
2516 | break; | ||
2517 | } | ||
2518 | |||
2519 | trace_pkt->status = trace_element.trace_type; | ||
2520 | trace_pkt->time_stamp = trace_element.trace_time_stamp; | ||
2521 | trace_pkt->real_length = trace_element.trace_length; | ||
2522 | |||
2523 | real_len = trace_element.trace_length; | ||
2524 | |||
2525 | if(data_ptr == 0){ | ||
2526 | trace_pkt->data_avail = 0x00; | ||
2527 | }else{ | ||
2528 | /* we can take it next time */ | ||
2529 | if ((available_buffer_space - buffer_length)< | ||
2530 | (real_len + sizeof(trace_pkt_t))){ | ||
2531 | |||
2532 | ppp_udp_pkt->data[0] |= 0x02; | ||
2533 | break; | ||
2534 | } | ||
2535 | trace_pkt->data_avail = 0x01; | ||
2536 | |||
2537 | /* get the data */ | ||
2538 | sdla_peek(&card->hw, data_ptr, | ||
2539 | &trace_pkt->data, | ||
2540 | real_len); | ||
2541 | } | ||
2542 | /* zero the opp flag to | ||
2543 | show we got the frame */ | ||
2544 | buf2[0] = 0x00; | ||
2545 | sdla_poke(&card->hw, ppp_priv_area->curr_trace_addr, | ||
2546 | &buf2, 1); | ||
2547 | |||
2548 | /* now move onto the next | ||
2549 | frame */ | ||
2550 | ppp_priv_area->curr_trace_addr += 8; | ||
2551 | |||
2552 | /* check if we passed the last address */ | ||
2553 | if ( ppp_priv_area->curr_trace_addr >= | ||
2554 | ppp_priv_area->end_trace_addr){ | ||
2555 | |||
2556 | ppp_priv_area->curr_trace_addr = | ||
2557 | ppp_priv_area->start_trace_addr; | ||
2558 | } | ||
2559 | |||
2560 | /* update buffer length and make sure its even */ | ||
2561 | |||
2562 | if ( trace_pkt->data_avail == 0x01 ) { | ||
2563 | buffer_length += real_len - 1; | ||
2564 | } | ||
2565 | |||
2566 | /* for the header */ | ||
2567 | buffer_length += 8; | ||
2568 | |||
2569 | if( buffer_length & 0x0001 ) | ||
2570 | buffer_length += 1; | ||
2571 | } | ||
2572 | |||
2573 | /* ok now set the total number of frames passed | ||
2574 | in the high 5 bits */ | ||
2575 | ppp_udp_pkt->data[0] |= (frames << 2); | ||
2576 | |||
2577 | /* set the data length */ | ||
2578 | mbox->cmd.length = buffer_length; | ||
2579 | ppp_udp_pkt->cblock.length = buffer_length; | ||
2580 | |||
2581 | /* set return code */ | ||
2582 | ppp_udp_pkt->cblock.result = 0; | ||
2583 | break; | ||
2584 | |||
2585 | /* PPIPE_GET_IBA_DATA */ | ||
2586 | case PPIPE_GET_IBA_DATA: | ||
2587 | |||
2588 | mbox->cmd.length = 0x09; | ||
2589 | |||
2590 | sdla_peek(&card->hw, 0xF003, &ppp_udp_pkt->data, | ||
2591 | mbox->cmd.length); | ||
2592 | |||
2593 | /* set the length of the data */ | ||
2594 | ppp_udp_pkt->cblock.length = 0x09; | ||
2595 | |||
2596 | /* set return code */ | ||
2597 | ppp_udp_pkt->cblock.result = 0x00; | ||
2598 | ppp_udp_pkt->cblock.result = 0; | ||
2599 | break; | ||
2600 | |||
2601 | /* PPIPE_FT1_READ_STATUS */ | ||
2602 | case PPIPE_FT1_READ_STATUS: | ||
2603 | sdla_peek(&card->hw, 0xF020, &ppp_udp_pkt->data[0], 2); | ||
2604 | ppp_udp_pkt->cblock.length = mbox->cmd.length = 2; | ||
2605 | ppp_udp_pkt->cblock.result = 0; | ||
2606 | break; | ||
2607 | |||
2608 | case PPIPE_FLUSH_DRIVER_STATS: | ||
2609 | init_ppp_priv_struct( ppp_priv_area ); | ||
2610 | init_global_statistics( card ); | ||
2611 | mbox->cmd.length = 0; | ||
2612 | ppp_udp_pkt->cblock.result = 0; | ||
2613 | break; | ||
2614 | |||
2615 | |||
2616 | case PPIPE_ROUTER_UP_TIME: | ||
2617 | |||
2618 | do_gettimeofday( &tv ); | ||
2619 | ppp_priv_area->router_up_time = tv.tv_sec - | ||
2620 | ppp_priv_area->router_start_time; | ||
2621 | *(unsigned long *)&ppp_udp_pkt->data = ppp_priv_area->router_up_time; | ||
2622 | mbox->cmd.length = 4; | ||
2623 | ppp_udp_pkt->cblock.result = 0; | ||
2624 | break; | ||
2625 | |||
2626 | /* PPIPE_DRIVER_STATISTICS */ | ||
2627 | case PPIPE_DRIVER_STAT_IFSEND: | ||
2628 | memcpy(&ppp_udp_pkt->data, &ppp_priv_area->if_send_stat, | ||
2629 | sizeof(if_send_stat_t)); | ||
2630 | |||
2631 | |||
2632 | ppp_udp_pkt->cblock.result = 0; | ||
2633 | ppp_udp_pkt->cblock.length = sizeof(if_send_stat_t); | ||
2634 | mbox->cmd.length = sizeof(if_send_stat_t); | ||
2635 | break; | ||
2636 | |||
2637 | case PPIPE_DRIVER_STAT_INTR: | ||
2638 | memcpy(&ppp_udp_pkt->data, &card->statistics, | ||
2639 | sizeof(global_stats_t)); | ||
2640 | |||
2641 | memcpy(&ppp_udp_pkt->data+sizeof(global_stats_t), | ||
2642 | &ppp_priv_area->rx_intr_stat, | ||
2643 | sizeof(rx_intr_stat_t)); | ||
2644 | |||
2645 | ppp_udp_pkt->cblock.result = 0; | ||
2646 | ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+ | ||
2647 | sizeof(rx_intr_stat_t); | ||
2648 | mbox->cmd.length = ppp_udp_pkt->cblock.length; | ||
2649 | break; | ||
2650 | |||
2651 | case PPIPE_DRIVER_STAT_GEN: | ||
2652 | memcpy( &ppp_udp_pkt->data, | ||
2653 | &ppp_priv_area->pipe_mgmt_stat, | ||
2654 | sizeof(pipe_mgmt_stat_t)); | ||
2655 | |||
2656 | memcpy(&ppp_udp_pkt->data+sizeof(pipe_mgmt_stat_t), | ||
2657 | &card->statistics, sizeof(global_stats_t)); | ||
2658 | |||
2659 | ppp_udp_pkt->cblock.result = 0; | ||
2660 | ppp_udp_pkt->cblock.length = sizeof(global_stats_t)+ | ||
2661 | sizeof(rx_intr_stat_t); | ||
2662 | mbox->cmd.length = ppp_udp_pkt->cblock.length; | ||
2663 | break; | ||
2664 | |||
2665 | |||
2666 | /* FT1 MONITOR STATUS */ | ||
2667 | case FT1_MONITOR_STATUS_CTRL: | ||
2668 | |||
2669 | /* Enable FT1 MONITOR STATUS */ | ||
2670 | if( ppp_udp_pkt->data[0] == 1) { | ||
2671 | |||
2672 | if( rCount++ != 0 ) { | ||
2673 | ppp_udp_pkt->cblock.result = 0; | ||
2674 | mbox->cmd.length = 1; | ||
2675 | break; | ||
2676 | } | ||
2677 | } | ||
2678 | |||
2679 | /* Disable FT1 MONITOR STATUS */ | ||
2680 | if( ppp_udp_pkt->data[0] == 0) { | ||
2681 | |||
2682 | if( --rCount != 0) { | ||
2683 | ppp_udp_pkt->cblock.result = 0; | ||
2684 | mbox->cmd.length = 1; | ||
2685 | break; | ||
2686 | } | ||
2687 | } | ||
2688 | goto udp_dflt_cmd; | ||
2689 | |||
2690 | /* WARNING: FIXME: This should be fixed. | ||
2691 | * The FT1 Status Ctrl doesn't have a break | ||
2692 | * statment. Thus, no code must be inserted | ||
2693 | * HERE: between default and above case statement */ | ||
2694 | |||
2695 | default: | ||
2696 | udp_dflt_cmd: | ||
2697 | |||
2698 | /* it's a board command */ | ||
2699 | mbox->cmd.command = ppp_udp_pkt->cblock.command; | ||
2700 | mbox->cmd.length = ppp_udp_pkt->cblock.length; | ||
2701 | |||
2702 | if(mbox->cmd.length) { | ||
2703 | memcpy(&mbox->data,(unsigned char *)ppp_udp_pkt->data, | ||
2704 | mbox->cmd.length); | ||
2705 | } | ||
2706 | |||
2707 | /* run the command on the board */ | ||
2708 | err = sdla_exec(mbox) ? mbox->cmd.result : CMD_TIMEOUT; | ||
2709 | |||
2710 | if (err != CMD_OK) { | ||
2711 | |||
2712 | ppp_error(card, err, mbox); | ||
2713 | ++ppp_priv_area->pipe_mgmt_stat. | ||
2714 | UDP_PIPE_mgmt_adptr_cmnd_timeout; | ||
2715 | break; | ||
2716 | } | ||
2717 | |||
2718 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_adptr_cmnd_OK; | ||
2719 | |||
2720 | /* copy the result back to our buffer */ | ||
2721 | memcpy(&ppp_udp_pkt->cblock,mbox, sizeof(cblock_t)); | ||
2722 | |||
2723 | if(mbox->cmd.length) { | ||
2724 | memcpy(&ppp_udp_pkt->data,&mbox->data,mbox->cmd.length); | ||
2725 | } | ||
2726 | |||
2727 | } /* end of switch */ | ||
2728 | } /* end of else */ | ||
2729 | |||
2730 | /* Fill UDP TTL */ | ||
2731 | ppp_udp_pkt->ip_pkt.ttl = card->wandev.ttl; | ||
2732 | len = reply_udp(ppp_priv_area->udp_pkt_data, mbox->cmd.length); | ||
2733 | |||
2734 | if (ppp_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK) { | ||
2735 | |||
2736 | /* Make sure we are not already sending */ | ||
2737 | if (!test_bit(SEND_CRIT,&card->wandev.critical)){ | ||
2738 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_adptr; | ||
2739 | ppp_send(card,ppp_priv_area->udp_pkt_data,len,ppp_priv_area->protocol); | ||
2740 | } | ||
2741 | |||
2742 | } else { | ||
2743 | |||
2744 | /* Pass it up the stack | ||
2745 | Allocate socket buffer */ | ||
2746 | if ((new_skb = dev_alloc_skb(len)) != NULL) { | ||
2747 | |||
2748 | /* copy data into new_skb */ | ||
2749 | |||
2750 | buf = skb_put(new_skb, len); | ||
2751 | memcpy(buf,ppp_priv_area->udp_pkt_data, len); | ||
2752 | |||
2753 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_passed_to_stack; | ||
2754 | |||
2755 | /* Decapsulate packet and pass it up the protocol | ||
2756 | stack */ | ||
2757 | new_skb->protocol = htons(ETH_P_IP); | ||
2758 | new_skb->dev = dev; | ||
2759 | new_skb->mac.raw = new_skb->data; | ||
2760 | netif_rx(new_skb); | ||
2761 | dev->last_rx = jiffies; | ||
2762 | |||
2763 | } else { | ||
2764 | |||
2765 | ++ppp_priv_area->pipe_mgmt_stat.UDP_PIPE_mgmt_no_socket; | ||
2766 | printk(KERN_INFO "no socket buffers available!\n"); | ||
2767 | } | ||
2768 | } | ||
2769 | |||
2770 | ppp_priv_area->udp_pkt_lgth = 0; | ||
2771 | |||
2772 | return; | ||
2773 | } | ||
2774 | |||
2775 | /*============================================================================= | ||
2776 | * Initial the ppp_private_area structure. | ||
2777 | */ | ||
2778 | static void init_ppp_priv_struct( ppp_private_area_t *ppp_priv_area ) | ||
2779 | { | ||
2780 | |||
2781 | memset(&ppp_priv_area->if_send_stat, 0, sizeof(if_send_stat_t)); | ||
2782 | memset(&ppp_priv_area->rx_intr_stat, 0, sizeof(rx_intr_stat_t)); | ||
2783 | memset(&ppp_priv_area->pipe_mgmt_stat, 0, sizeof(pipe_mgmt_stat_t)); | ||
2784 | } | ||
2785 | |||
2786 | /*============================================================================ | ||
2787 | * Initialize Global Statistics | ||
2788 | */ | ||
2789 | static void init_global_statistics( sdla_t *card ) | ||
2790 | { | ||
2791 | memset(&card->statistics, 0, sizeof(global_stats_t)); | ||
2792 | } | ||
2793 | |||
2794 | /*============================================================================ | ||
2795 | * Initialize Receive and Transmit Buffers. | ||
2796 | */ | ||
2797 | static void init_ppp_tx_rx_buff( sdla_t *card ) | ||
2798 | { | ||
2799 | ppp508_buf_info_t* info; | ||
2800 | |||
2801 | if (card->hw.type == SDLA_S514) { | ||
2802 | |||
2803 | info = (void*)(card->hw.dpmbase + PPP514_BUF_OFFS); | ||
2804 | |||
2805 | card->u.p.txbuf_base = (void*)(card->hw.dpmbase + | ||
2806 | info->txb_ptr); | ||
2807 | |||
2808 | card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base + | ||
2809 | (info->txb_num - 1); | ||
2810 | |||
2811 | card->u.p.rxbuf_base = (void*)(card->hw.dpmbase + | ||
2812 | info->rxb_ptr); | ||
2813 | |||
2814 | card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base + | ||
2815 | (info->rxb_num - 1); | ||
2816 | |||
2817 | } else { | ||
2818 | |||
2819 | info = (void*)(card->hw.dpmbase + PPP508_BUF_OFFS); | ||
2820 | |||
2821 | card->u.p.txbuf_base = (void*)(card->hw.dpmbase + | ||
2822 | (info->txb_ptr - PPP508_MB_VECT)); | ||
2823 | |||
2824 | card->u.p.txbuf_last = (ppp_buf_ctl_t*)card->u.p.txbuf_base + | ||
2825 | (info->txb_num - 1); | ||
2826 | |||
2827 | card->u.p.rxbuf_base = (void*)(card->hw.dpmbase + | ||
2828 | (info->rxb_ptr - PPP508_MB_VECT)); | ||
2829 | |||
2830 | card->u.p.rxbuf_last = (ppp_buf_ctl_t*)card->u.p.rxbuf_base + | ||
2831 | (info->rxb_num - 1); | ||
2832 | } | ||
2833 | |||
2834 | card->u.p.txbuf_next = (unsigned long*)&info->txb_nxt; | ||
2835 | card->u.p.rxbuf_next = (unsigned long*)&info->rxb1_ptr; | ||
2836 | |||
2837 | card->u.p.rx_base = info->rxb_base; | ||
2838 | card->u.p.rx_top = info->rxb_end; | ||
2839 | |||
2840 | card->u.p.txbuf = card->u.p.txbuf_base; | ||
2841 | card->rxmb = card->u.p.rxbuf_base; | ||
2842 | |||
2843 | } | ||
2844 | |||
2845 | /*============================================================================= | ||
2846 | * Read Connection Information (ie for Remote IP address assginment). | ||
2847 | * Called when ppp interface connected. | ||
2848 | */ | ||
2849 | static int read_info( sdla_t *card ) | ||
2850 | { | ||
2851 | struct net_device *dev = card->wandev.dev; | ||
2852 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
2853 | int err; | ||
2854 | |||
2855 | struct ifreq if_info; | ||
2856 | struct sockaddr_in *if_data1, *if_data2; | ||
2857 | mm_segment_t fs; | ||
2858 | |||
2859 | /* Set Local and remote addresses */ | ||
2860 | memset(&if_info, 0, sizeof(if_info)); | ||
2861 | strcpy(if_info.ifr_name, dev->name); | ||
2862 | |||
2863 | |||
2864 | fs = get_fs(); | ||
2865 | set_fs(get_ds()); /* get user space block */ | ||
2866 | |||
2867 | /* Change the local and remote ip address of the interface. | ||
2868 | * This will also add in the destination route. | ||
2869 | */ | ||
2870 | if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; | ||
2871 | if_data1->sin_addr.s_addr = ppp_priv_area->ip_local; | ||
2872 | if_data1->sin_family = AF_INET; | ||
2873 | err = devinet_ioctl( SIOCSIFADDR, &if_info ); | ||
2874 | if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr; | ||
2875 | if_data2->sin_addr.s_addr = ppp_priv_area->ip_remote; | ||
2876 | if_data2->sin_family = AF_INET; | ||
2877 | err = devinet_ioctl( SIOCSIFDSTADDR, &if_info ); | ||
2878 | |||
2879 | set_fs(fs); /* restore old block */ | ||
2880 | |||
2881 | if (err) { | ||
2882 | printk (KERN_INFO "%s: Adding of route failed: %i\n", | ||
2883 | card->devname,err); | ||
2884 | printk (KERN_INFO "%s: Local : %u.%u.%u.%u\n", | ||
2885 | card->devname,NIPQUAD(ppp_priv_area->ip_local)); | ||
2886 | printk (KERN_INFO "%s: Remote: %u.%u.%u.%u\n", | ||
2887 | card->devname,NIPQUAD(ppp_priv_area->ip_remote)); | ||
2888 | } | ||
2889 | return err; | ||
2890 | } | ||
2891 | |||
2892 | /*============================================================================= | ||
2893 | * Remove Dynamic Route. | ||
2894 | * Called when ppp interface disconnected. | ||
2895 | */ | ||
2896 | |||
2897 | static void remove_route( sdla_t *card ) | ||
2898 | { | ||
2899 | |||
2900 | struct net_device *dev = card->wandev.dev; | ||
2901 | long ip_addr; | ||
2902 | int err; | ||
2903 | |||
2904 | mm_segment_t fs; | ||
2905 | struct ifreq if_info; | ||
2906 | struct sockaddr_in *if_data1; | ||
2907 | struct in_device *in_dev = dev->ip_ptr; | ||
2908 | struct in_ifaddr *ifa = in_dev->ifa_list; | ||
2909 | |||
2910 | ip_addr = ifa->ifa_local; | ||
2911 | |||
2912 | /* Set Local and remote addresses */ | ||
2913 | memset(&if_info, 0, sizeof(if_info)); | ||
2914 | strcpy(if_info.ifr_name, dev->name); | ||
2915 | |||
2916 | fs = get_fs(); | ||
2917 | set_fs(get_ds()); /* get user space block */ | ||
2918 | |||
2919 | /* Change the local ip address of the interface to 0. | ||
2920 | * This will also delete the destination route. | ||
2921 | */ | ||
2922 | if_data1 = (struct sockaddr_in *)&if_info.ifr_addr; | ||
2923 | if_data1->sin_addr.s_addr = 0; | ||
2924 | if_data1->sin_family = AF_INET; | ||
2925 | err = devinet_ioctl( SIOCSIFADDR, &if_info ); | ||
2926 | |||
2927 | set_fs(fs); /* restore old block */ | ||
2928 | |||
2929 | |||
2930 | if (err) { | ||
2931 | printk (KERN_INFO "%s: Deleting dynamic route failed %d!\n", | ||
2932 | card->devname, err); | ||
2933 | return; | ||
2934 | }else{ | ||
2935 | printk (KERN_INFO "%s: PPP Deleting dynamic route %u.%u.%u.%u successfuly\n", | ||
2936 | card->devname, NIPQUAD(ip_addr)); | ||
2937 | } | ||
2938 | return; | ||
2939 | } | ||
2940 | |||
2941 | /*============================================================================= | ||
2942 | * Perform the Interrupt Test by running the READ_CODE_VERSION command MAX_INTR | ||
2943 | * _TEST_COUNTER times. | ||
2944 | */ | ||
2945 | static int intr_test( sdla_t *card ) | ||
2946 | { | ||
2947 | ppp_mbox_t *mb = card->mbox; | ||
2948 | int err,i; | ||
2949 | |||
2950 | err = ppp_set_intr_mode( card, 0x08 ); | ||
2951 | |||
2952 | if (err == CMD_OK) { | ||
2953 | |||
2954 | for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) { | ||
2955 | /* Run command READ_CODE_VERSION */ | ||
2956 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
2957 | mb->cmd.length = 0; | ||
2958 | mb->cmd.command = PPP_READ_CODE_VERSION; | ||
2959 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
2960 | if (err != CMD_OK) | ||
2961 | ppp_error(card, err, mb); | ||
2962 | } | ||
2963 | } | ||
2964 | else return err; | ||
2965 | |||
2966 | err = ppp_set_intr_mode( card, 0 ); | ||
2967 | if (err != CMD_OK) | ||
2968 | return err; | ||
2969 | |||
2970 | return 0; | ||
2971 | } | ||
2972 | |||
2973 | /*============================================================================== | ||
2974 | * Determine what type of UDP call it is. DRVSTATS or PTPIPEAB ? | ||
2975 | */ | ||
2976 | static int udp_pkt_type( struct sk_buff *skb, sdla_t *card ) | ||
2977 | { | ||
2978 | unsigned char *sendpacket; | ||
2979 | unsigned char buf2[5]; | ||
2980 | ppp_udp_pkt_t *ppp_udp_pkt = (ppp_udp_pkt_t *)skb->data; | ||
2981 | |||
2982 | sendpacket = skb->data; | ||
2983 | memcpy(&buf2, &card->wandev.udp_port, 2); | ||
2984 | |||
2985 | if( ppp_udp_pkt->ip_pkt.ver_inet_hdr_length == 0x45 && /* IP packet */ | ||
2986 | sendpacket[9] == 0x11 && /* UDP packet */ | ||
2987 | sendpacket[22] == buf2[1] && /* UDP Port */ | ||
2988 | sendpacket[23] == buf2[0] && | ||
2989 | sendpacket[36] == 0x01 ) { | ||
2990 | |||
2991 | if ( sendpacket[28] == 0x50 && /* PTPIPEAB: Signature */ | ||
2992 | sendpacket[29] == 0x54 && | ||
2993 | sendpacket[30] == 0x50 && | ||
2994 | sendpacket[31] == 0x49 && | ||
2995 | sendpacket[32] == 0x50 && | ||
2996 | sendpacket[33] == 0x45 && | ||
2997 | sendpacket[34] == 0x41 && | ||
2998 | sendpacket[35] == 0x42 ){ | ||
2999 | |||
3000 | return UDP_PTPIPE_TYPE; | ||
3001 | |||
3002 | } else if(sendpacket[28] == 0x44 && /* DRVSTATS: Signature */ | ||
3003 | sendpacket[29] == 0x52 && | ||
3004 | sendpacket[30] == 0x56 && | ||
3005 | sendpacket[31] == 0x53 && | ||
3006 | sendpacket[32] == 0x54 && | ||
3007 | sendpacket[33] == 0x41 && | ||
3008 | sendpacket[34] == 0x54 && | ||
3009 | sendpacket[35] == 0x53 ){ | ||
3010 | |||
3011 | return UDP_DRVSTATS_TYPE; | ||
3012 | |||
3013 | } else | ||
3014 | return UDP_INVALID_TYPE; | ||
3015 | |||
3016 | } else | ||
3017 | return UDP_INVALID_TYPE; | ||
3018 | |||
3019 | } | ||
3020 | |||
3021 | /*============================================================================ | ||
3022 | * Check to see if the packet to be transmitted contains a broadcast or | ||
3023 | * multicast source IP address. | ||
3024 | */ | ||
3025 | |||
3026 | static int chk_bcast_mcast_addr(sdla_t *card, struct net_device* dev, | ||
3027 | struct sk_buff *skb) | ||
3028 | { | ||
3029 | u32 src_ip_addr; | ||
3030 | u32 broadcast_ip_addr = 0; | ||
3031 | struct in_device *in_dev; | ||
3032 | |||
3033 | /* read the IP source address from the outgoing packet */ | ||
3034 | src_ip_addr = *(u32 *)(skb->data + 12); | ||
3035 | |||
3036 | /* read the IP broadcast address for the device */ | ||
3037 | in_dev = dev->ip_ptr; | ||
3038 | if(in_dev != NULL) { | ||
3039 | struct in_ifaddr *ifa= in_dev->ifa_list; | ||
3040 | if(ifa != NULL) | ||
3041 | broadcast_ip_addr = ifa->ifa_broadcast; | ||
3042 | else | ||
3043 | return 0; | ||
3044 | } | ||
3045 | |||
3046 | /* check if the IP Source Address is a Broadcast address */ | ||
3047 | if((dev->flags & IFF_BROADCAST) && (src_ip_addr == broadcast_ip_addr)) { | ||
3048 | printk(KERN_INFO "%s: Broadcast Source Address silently discarded\n", | ||
3049 | card->devname); | ||
3050 | return 1; | ||
3051 | } | ||
3052 | |||
3053 | /* check if the IP Source Address is a Multicast address */ | ||
3054 | if((ntohl(src_ip_addr) >= 0xE0000001) && | ||
3055 | (ntohl(src_ip_addr) <= 0xFFFFFFFE)) { | ||
3056 | printk(KERN_INFO "%s: Multicast Source Address silently discarded\n", | ||
3057 | card->devname); | ||
3058 | return 1; | ||
3059 | } | ||
3060 | |||
3061 | return 0; | ||
3062 | } | ||
3063 | |||
3064 | void s508_lock (sdla_t *card, unsigned long *smp_flags) | ||
3065 | { | ||
3066 | spin_lock_irqsave(&card->wandev.lock, *smp_flags); | ||
3067 | } | ||
3068 | |||
3069 | void s508_unlock (sdla_t *card, unsigned long *smp_flags) | ||
3070 | { | ||
3071 | spin_unlock_irqrestore(&card->wandev.lock, *smp_flags); | ||
3072 | } | ||
3073 | |||
3074 | static int read_connection_info (sdla_t *card) | ||
3075 | { | ||
3076 | ppp_mbox_t *mb = card->mbox; | ||
3077 | struct net_device *dev = card->wandev.dev; | ||
3078 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
3079 | ppp508_connect_info_t *ppp508_connect_info; | ||
3080 | int err; | ||
3081 | |||
3082 | memset(&mb->cmd, 0, sizeof(ppp_cmd_t)); | ||
3083 | mb->cmd.length = 0; | ||
3084 | mb->cmd.command = PPP_GET_CONNECTION_INFO; | ||
3085 | err = sdla_exec(mb) ? mb->cmd.result : CMD_TIMEOUT; | ||
3086 | |||
3087 | if (err != CMD_OK) { | ||
3088 | ppp_error(card, err, mb); | ||
3089 | ppp_priv_area->ip_remote = 0; | ||
3090 | ppp_priv_area->ip_local = 0; | ||
3091 | } | ||
3092 | else { | ||
3093 | ppp508_connect_info = (ppp508_connect_info_t *)mb->data; | ||
3094 | ppp_priv_area->ip_remote = ppp508_connect_info->ip_remote; | ||
3095 | ppp_priv_area->ip_local = ppp508_connect_info->ip_local; | ||
3096 | |||
3097 | NEX_PRINTK(KERN_INFO "READ CONNECTION GOT IP ADDRESS %x, %x\n", | ||
3098 | ppp_priv_area->ip_remote, | ||
3099 | ppp_priv_area->ip_local); | ||
3100 | } | ||
3101 | |||
3102 | return err; | ||
3103 | } | ||
3104 | |||
3105 | /*=============================================================================== | ||
3106 | * config_ppp | ||
3107 | * | ||
3108 | * Configure the ppp protocol and enable communications. | ||
3109 | * | ||
3110 | * The if_open function binds this function to the poll routine. | ||
3111 | * Therefore, this function will run every time the ppp interface | ||
3112 | * is brought up. | ||
3113 | * | ||
3114 | * If the communications are not enabled, proceed to configure | ||
3115 | * the card and enable communications. | ||
3116 | * | ||
3117 | * If the communications are enabled, it means that the interface | ||
3118 | * was shutdown by ether the user or driver. In this case, we | ||
3119 | * have to check that the IP addresses have not changed. If | ||
3120 | * the IP addresses changed, we have to reconfigure the firmware | ||
3121 | * and update the changed IP addresses. Otherwise, just exit. | ||
3122 | */ | ||
3123 | static int config_ppp (sdla_t *card) | ||
3124 | { | ||
3125 | |||
3126 | struct net_device *dev = card->wandev.dev; | ||
3127 | ppp_flags_t *flags = card->flags; | ||
3128 | ppp_private_area_t *ppp_priv_area = dev->priv; | ||
3129 | |||
3130 | if (card->u.p.comm_enabled){ | ||
3131 | |||
3132 | if (ppp_priv_area->ip_local_tmp != ppp_priv_area->ip_local || | ||
3133 | ppp_priv_area->ip_remote_tmp != ppp_priv_area->ip_remote){ | ||
3134 | |||
3135 | /* The IP addersses have changed, we must | ||
3136 | * stop the communications and reconfigure | ||
3137 | * the card. Reason: the firmware must know | ||
3138 | * the local and remote IP addresses. */ | ||
3139 | disable_comm(card); | ||
3140 | wanpipe_set_state(card, WAN_DISCONNECTED); | ||
3141 | printk(KERN_INFO | ||
3142 | "%s: IP addresses changed!\n", | ||
3143 | card->devname); | ||
3144 | printk(KERN_INFO "%s: Restarting communications ...\n", | ||
3145 | card->devname); | ||
3146 | }else{ | ||
3147 | /* IP addresses are the same and the link is up, | ||
3148 | * we don't have to do anything here. Therefore, exit */ | ||
3149 | return 0; | ||
3150 | } | ||
3151 | } | ||
3152 | |||
3153 | /* Record the new IP addreses */ | ||
3154 | ppp_priv_area->ip_local = ppp_priv_area->ip_local_tmp; | ||
3155 | ppp_priv_area->ip_remote = ppp_priv_area->ip_remote_tmp; | ||
3156 | |||
3157 | if (config508(dev, card)){ | ||
3158 | printk(KERN_INFO "%s: Failed to configure PPP device\n", | ||
3159 | card->devname); | ||
3160 | return 0; | ||
3161 | } | ||
3162 | |||
3163 | if (ppp_set_intr_mode(card, PPP_INTR_RXRDY| | ||
3164 | PPP_INTR_TXRDY| | ||
3165 | PPP_INTR_MODEM| | ||
3166 | PPP_INTR_DISC | | ||
3167 | PPP_INTR_OPEN | | ||
3168 | PPP_INTR_DROP_DTR | | ||
3169 | PPP_INTR_TIMER)) { | ||
3170 | |||
3171 | printk(KERN_INFO "%s: Failed to configure board interrupts !\n", | ||
3172 | card->devname); | ||
3173 | return 0; | ||
3174 | } | ||
3175 | |||
3176 | /* Turn off the transmit and timer interrupt */ | ||
3177 | flags->imask &= ~(PPP_INTR_TXRDY | PPP_INTR_TIMER) ; | ||
3178 | |||
3179 | |||
3180 | /* If you are not the authenticator and any one of the protocol is | ||
3181 | * enabled then we call the set_out_bound_authentication. | ||
3182 | */ | ||
3183 | if ( !card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)) { | ||
3184 | if ( ppp_set_outbnd_auth(card, ppp_priv_area) ){ | ||
3185 | printk(KERN_INFO "%s: Outbound authentication failed !\n", | ||
3186 | card->devname); | ||
3187 | return 0; | ||
3188 | } | ||
3189 | } | ||
3190 | |||
3191 | /* If you are the authenticator and any one of the protocol is enabled | ||
3192 | * then we call the set_in_bound_authentication. | ||
3193 | */ | ||
3194 | if (card->u.p.authenticator && (ppp_priv_area->pap || ppp_priv_area->chap)){ | ||
3195 | if (ppp_set_inbnd_auth(card, ppp_priv_area)){ | ||
3196 | printk(KERN_INFO "%s: Inbound authentication failed !\n", | ||
3197 | card->devname); | ||
3198 | return 0; | ||
3199 | } | ||
3200 | } | ||
3201 | |||
3202 | /* If we fail to enable communications here it's OK, | ||
3203 | * since the DTR timer will cause a disconnected, which | ||
3204 | * will retrigger communication in timer_intr() */ | ||
3205 | if (ppp_comm_enable(card) == CMD_OK) { | ||
3206 | wanpipe_set_state(card, WAN_CONNECTING); | ||
3207 | init_ppp_tx_rx_buff(card); | ||
3208 | } | ||
3209 | |||
3210 | return 0; | ||
3211 | } | ||
3212 | |||
3213 | /*============================================================ | ||
3214 | * ppp_poll | ||
3215 | * | ||
3216 | * Rationale: | ||
3217 | * We cannot manipulate the routing tables, or | ||
3218 | * ip addresses withing the interrupt. Therefore | ||
3219 | * we must perform such actons outside an interrupt | ||
3220 | * at a later time. | ||
3221 | * | ||
3222 | * Description: | ||
3223 | * PPP polling routine, responsible for | ||
3224 | * shutting down interfaces upon disconnect | ||
3225 | * and adding/removing routes. | ||
3226 | * | ||
3227 | * Usage: | ||
3228 | * This function is executed for each ppp | ||
3229 | * interface through a tq_schedule bottom half. | ||
3230 | * | ||
3231 | * trigger_ppp_poll() function is used to kick | ||
3232 | * the ppp_poll routine. | ||
3233 | */ | ||
3234 | static void ppp_poll(struct net_device *dev) | ||
3235 | { | ||
3236 | ppp_private_area_t *ppp_priv_area; | ||
3237 | sdla_t *card; | ||
3238 | u8 check_gateway=0; | ||
3239 | ppp_flags_t *flags; | ||
3240 | |||
3241 | if (!dev || (ppp_priv_area = dev->priv) == NULL) | ||
3242 | return; | ||
3243 | |||
3244 | card = ppp_priv_area->card; | ||
3245 | flags = card->flags; | ||
3246 | |||
3247 | /* Shutdown is in progress, stop what you are | ||
3248 | * doing and get out */ | ||
3249 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
3250 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3251 | return; | ||
3252 | } | ||
3253 | |||
3254 | /* if_open() function has triggered the polling routine | ||
3255 | * to determine the configured IP addresses. Once the | ||
3256 | * addresses are found, trigger the chdlc configuration */ | ||
3257 | if (test_bit(0,&ppp_priv_area->config_ppp)){ | ||
3258 | |||
3259 | ppp_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP); | ||
3260 | ppp_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP); | ||
3261 | |||
3262 | if (ppp_priv_area->ip_local_tmp == ppp_priv_area->ip_remote_tmp && | ||
3263 | card->u.p.ip_mode == WANOPT_PPP_HOST){ | ||
3264 | |||
3265 | if (++ppp_priv_area->ip_error > MAX_IP_ERRORS){ | ||
3266 | printk(KERN_INFO "\n%s: --- WARNING ---\n", | ||
3267 | card->devname); | ||
3268 | printk(KERN_INFO "%s: The local IP address is the same as the\n", | ||
3269 | card->devname); | ||
3270 | printk(KERN_INFO "%s: Point-to-Point IP address.\n", | ||
3271 | card->devname); | ||
3272 | printk(KERN_INFO "%s: --- WARNING ---\n\n", | ||
3273 | card->devname); | ||
3274 | }else{ | ||
3275 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3276 | ppp_priv_area->poll_delay_timer.expires = jiffies+HZ; | ||
3277 | add_timer(&ppp_priv_area->poll_delay_timer); | ||
3278 | return; | ||
3279 | } | ||
3280 | } | ||
3281 | |||
3282 | ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG; | ||
3283 | flags->imask |= PPP_INTR_TIMER; | ||
3284 | ppp_priv_area->ip_error=0; | ||
3285 | |||
3286 | clear_bit(0,&ppp_priv_area->config_ppp); | ||
3287 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3288 | return; | ||
3289 | } | ||
3290 | |||
3291 | /* Dynamic interface implementation, as well as dynamic | ||
3292 | * routing. */ | ||
3293 | |||
3294 | switch (card->wandev.state) { | ||
3295 | |||
3296 | case WAN_DISCONNECTED: | ||
3297 | |||
3298 | /* If the dynamic interface configuration is on, and interface | ||
3299 | * is up, then bring down the netowrk interface */ | ||
3300 | |||
3301 | if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) && | ||
3302 | !test_bit(DEV_DOWN,&ppp_priv_area->interface_down) && | ||
3303 | card->wandev.dev->flags & IFF_UP){ | ||
3304 | |||
3305 | printk(KERN_INFO "%s: Interface %s down.\n", | ||
3306 | card->devname,card->wandev.dev->name); | ||
3307 | change_dev_flags(card->wandev.dev, | ||
3308 | (card->wandev.dev->flags&~IFF_UP)); | ||
3309 | set_bit(DEV_DOWN,&ppp_priv_area->interface_down); | ||
3310 | }else{ | ||
3311 | /* We need to check if the local IP address is | ||
3312 | * zero. If it is, we shouldn't try to remove it. | ||
3313 | * For some reason the kernel crashes badly if | ||
3314 | * we try to remove the route twice */ | ||
3315 | |||
3316 | if (card->wandev.dev->flags & IFF_UP && | ||
3317 | get_ip_address(card->wandev.dev,WAN_LOCAL_IP) && | ||
3318 | card->u.p.ip_mode == WANOPT_PPP_PEER){ | ||
3319 | |||
3320 | remove_route(card); | ||
3321 | } | ||
3322 | } | ||
3323 | break; | ||
3324 | |||
3325 | case WAN_CONNECTED: | ||
3326 | |||
3327 | /* In SMP machine this code can execute before the interface | ||
3328 | * comes up. In this case, we must make sure that we do not | ||
3329 | * try to bring up the interface before dev_open() is finished */ | ||
3330 | |||
3331 | |||
3332 | /* DEV_DOWN will be set only when we bring down the interface | ||
3333 | * for the very first time. This way we know that it was us | ||
3334 | * that brought the interface down */ | ||
3335 | |||
3336 | if (test_bit(DYN_OPT_ON,&ppp_priv_area->interface_down) && | ||
3337 | test_bit(DEV_DOWN, &ppp_priv_area->interface_down) && | ||
3338 | !(card->wandev.dev->flags & IFF_UP)){ | ||
3339 | |||
3340 | printk(KERN_INFO "%s: Interface %s up.\n", | ||
3341 | card->devname,card->wandev.dev->name); | ||
3342 | |||
3343 | change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP)); | ||
3344 | clear_bit(DEV_DOWN,&ppp_priv_area->interface_down); | ||
3345 | check_gateway=1; | ||
3346 | } | ||
3347 | |||
3348 | if ((card->u.p.ip_mode == WANOPT_PPP_PEER) && | ||
3349 | test_bit(1,&Read_connection_info)) { | ||
3350 | |||
3351 | process_route(card); | ||
3352 | clear_bit(1,&Read_connection_info); | ||
3353 | check_gateway=1; | ||
3354 | } | ||
3355 | |||
3356 | if (ppp_priv_area->gateway && check_gateway) | ||
3357 | add_gateway(card,dev); | ||
3358 | |||
3359 | break; | ||
3360 | } | ||
3361 | clear_bit(POLL_CRIT,&card->wandev.critical); | ||
3362 | return; | ||
3363 | } | ||
3364 | |||
3365 | /*============================================================ | ||
3366 | * trigger_ppp_poll | ||
3367 | * | ||
3368 | * Description: | ||
3369 | * Add a ppp_poll() task into a tq_scheduler bh handler | ||
3370 | * for a specific interface. This will kick | ||
3371 | * the ppp_poll() routine at a later time. | ||
3372 | * | ||
3373 | * Usage: | ||
3374 | * Interrupts use this to defer a taks to | ||
3375 | * a polling routine. | ||
3376 | * | ||
3377 | */ | ||
3378 | |||
3379 | static void trigger_ppp_poll(struct net_device *dev) | ||
3380 | { | ||
3381 | ppp_private_area_t *ppp_priv_area; | ||
3382 | if ((ppp_priv_area=dev->priv) != NULL){ | ||
3383 | |||
3384 | sdla_t *card = ppp_priv_area->card; | ||
3385 | |||
3386 | if (test_bit(PERI_CRIT,&card->wandev.critical)){ | ||
3387 | return; | ||
3388 | } | ||
3389 | |||
3390 | if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){ | ||
3391 | return; | ||
3392 | } | ||
3393 | |||
3394 | schedule_work(&ppp_priv_area->poll_work); | ||
3395 | } | ||
3396 | return; | ||
3397 | } | ||
3398 | |||
3399 | static void ppp_poll_delay (unsigned long dev_ptr) | ||
3400 | { | ||
3401 | struct net_device *dev = (struct net_device *)dev_ptr; | ||
3402 | trigger_ppp_poll(dev); | ||
3403 | } | ||
3404 | |||
3405 | /*============================================================ | ||
3406 | * detect_and_fix_tx_bug | ||
3407 | * | ||
3408 | * Description: | ||
3409 | * On connect, if the board tx buffer ptr is not the same | ||
3410 | * as the driver tx buffer ptr, we found a firmware bug. | ||
3411 | * Report the bug to the above layer. To fix the | ||
3412 | * error restart communications again. | ||
3413 | * | ||
3414 | * Usage: | ||
3415 | * | ||
3416 | */ | ||
3417 | |||
3418 | static int detect_and_fix_tx_bug (sdla_t *card) | ||
3419 | { | ||
3420 | if (((unsigned long)card->u.p.txbuf_base&0xFFF) != ((*card->u.p.txbuf_next)&0xFFF)){ | ||
3421 | NEX_PRINTK(KERN_INFO "Major Error, Fix the bug\n"); | ||
3422 | return 1; | ||
3423 | } | ||
3424 | return 0; | ||
3425 | } | ||
3426 | |||
3427 | MODULE_LICENSE("GPL"); | ||
3428 | |||
3429 | /****** End *****************************************************************/ | ||