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