diff options
Diffstat (limited to 'drivers/net/wan/sdla_ppp.c')
-rw-r--r-- | drivers/net/wan/sdla_ppp.c | 3430 |
1 files changed, 0 insertions, 3430 deletions
diff --git a/drivers/net/wan/sdla_ppp.c b/drivers/net/wan/sdla_ppp.c deleted file mode 100644 index a4b489cccbbf..000000000000 --- a/drivers/net/wan/sdla_ppp.c +++ /dev/null | |||
@@ -1,3430 +0,0 @@ | |||
1 | /***************************************************************************** | ||
2 | * sdla_ppp.c WANPIPE(tm) Multiprotocol WAN Link Driver. PPP module. | ||
3 | * | ||
4 | * Author: Nenad Corbic <ncorbic@sangoma.com> | ||
5 | * | ||
6 | * Copyright: (c) 1995-2001 Sangoma Technologies Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * ============================================================================ | ||
13 | * Feb 28, 2001 Nenad Corbic o Updated if_tx_timeout() routine for | ||
14 | * 2.4.X kernels. | ||
15 | * Nov 29, 2000 Nenad Corbic o Added the 2.4.x kernel support: | ||
16 | * get_ip_address() function has moved | ||
17 | * into the ppp_poll() routine. It cannot | ||
18 | * be called from an interrupt. | ||
19 | * Nov 07, 2000 Nenad Corbic o Added security features for UDP debugging: | ||
20 | * Deny all and specify allowed requests. | ||
21 | * May 02, 2000 Nenad Corbic o Added the dynamic interface shutdown | ||
22 | * option. When the link goes down, the | ||
23 | * network interface IFF_UP flag is reset. | ||
24 | * Mar 06, 2000 Nenad Corbic o Bug Fix: corrupted mbox recovery. | ||
25 | * Feb 25, 2000 Nenad Corbic o Fixed the FT1 UDP debugger problem. | ||
26 | * Feb 09, 2000 Nenad Coribc o Shutdown bug fix. update() was called | ||
27 | * with NULL dev pointer: no check. | ||
28 | * Jan 24, 2000 Nenad Corbic o Disabled use of CMD complete inter. | ||
29 | * Dev 15, 1999 Nenad Corbic o Fixed up header files for 2.0.X kernels | ||
30 | * Oct 25, 1999 Nenad Corbic o Support for 2.0.X kernels | ||
31 | * Moved dynamic route processing into | ||
32 | * a polling routine. | ||
33 | * Oct 07, 1999 Nenad Corbic o Support for S514 PCI card. | ||
34 | * Gideon Hack o UPD and Updates executed using timer interrupt | ||
35 | * Sep 10, 1999 Nenad Corbic o Fixed up the /proc statistics | ||
36 | * Jul 20, 1999 Nenad Corbic o Remove the polling routines and use | ||
37 | * interrupts instead. | ||
38 | * Sep 17, 1998 Jaspreet Singh o Updates for 2.2.X Kernels. | ||
39 | * Aug 13, 1998 Jaspreet Singh o Improved Line Tracing. | ||
40 | * Jun 22, 1998 David Fong o Added remote IP address assignment | ||
41 | * Mar 15, 1998 Alan Cox o 2.1.8x basic port. | ||
42 | * Apr 16, 1998 Jaspreet Singh o using htons() for the IPX protocol. | ||
43 | * Dec 09, 1997 Jaspreet Singh o Added PAP and CHAP. | ||
44 | * o Implemented new routines like | ||
45 | * ppp_set_inbnd_auth(), ppp_set_outbnd_auth(), | ||
46 | * tokenize() and strstrip(). | ||
47 | * Nov 27, 1997 Jaspreet Singh o Added protection against enabling of irqs | ||
48 | * while they have been disabled. | ||
49 | * Nov 24, 1997 Jaspreet Singh o Fixed another RACE condition caused by | ||
50 | * disabling and enabling of irqs. | ||
51 | * o Added new counters for stats on disable/enable | ||
52 | * IRQs. | ||
53 | * Nov 10, 1997 Jaspreet Singh o Initialized 'skb->mac.raw' to 'skb->data' | ||
54 | * before every netif_rx(). | ||
55 | * o Free up the device structure in del_if(). | ||
56 | * Nov 07, 1997 Jaspreet Singh o Changed the delay to zero for Line tracing | ||
57 | * command. | ||
58 | * Oct 20, 1997 Jaspreet Singh o Added hooks in for Router UP time. | ||
59 | * Oct 16, 1997 Jaspreet Singh o The critical flag is used to maintain flow | ||
60 | * control by avoiding RACE conditions. The | ||
61 | * cli() and restore_flags() are taken out. | ||
62 | * A new structure, "ppp_private_area", is added | ||
63 | * to provide Driver Statistics. | ||
64 | * Jul 21, 1997 Jaspreet Singh o Protected calls to sdla_peek() by adding | ||
65 | * save_flags(), cli() and restore_flags(). | ||
66 | * Jul 07, 1997 Jaspreet Singh o Added configurable TTL for UDP packets | ||
67 | * o Added ability to discard mulitcast and | ||
68 | * broacast source addressed packets. | ||
69 | * Jun 27, 1997 Jaspreet Singh o Added FT1 monitor capabilities | ||
70 | * New case (0x25) statement in if_send routine. | ||
71 | * Added a global variable rCount to keep track | ||
72 | * of FT1 status enabled on the board. | ||
73 | * May 22, 1997 Jaspreet Singh o Added change in the PPP_SET_CONFIG command for | ||
74 | * 508 card to reflect changes in the new | ||
75 | * ppp508.sfm for supporting:continous transmission | ||
76 | * of Configure-Request packets without receiving a | ||
77 | * reply | ||
78 | * OR-ed 0x300 to conf_flags | ||
79 | * o Changed connect_tmout from 900 to 0 | ||
80 | * May 21, 1997 Jaspreet Singh o Fixed UDP Management for multiple boards | ||
81 | * Apr 25, 1997 Farhan Thawar o added UDP Management stuff | ||
82 | * Mar 11, 1997 Farhan Thawar Version 3.1.1 | ||
83 | * o fixed (+1) bug in rx_intr() | ||
84 | * o changed if_send() to return 0 if | ||
85 | * wandev.critical() is true | ||
86 | * o free socket buffer in if_send() if | ||
87 | * returning 0 | ||
88 | * Jan 15, 1997 Gene Kozin Version 3.1.0 | ||
89 | * o implemented exec() entry point | ||
90 | * Jan 06, 1997 Gene Kozin Initial version. | ||
91 | *****************************************************************************/ | ||
92 | |||
93 | #include <linux/module.h> | ||
94 | #include <linux/kernel.h> /* printk(), and other useful stuff */ | ||
95 | #include <linux/stddef.h> /* offsetof(), etc. */ | ||
96 | #include <linux/errno.h> /* return codes */ | ||
97 | #include <linux/string.h> /* inline memset(), etc. */ | ||
98 | #include <linux/slab.h> /* kmalloc(), kfree() */ | ||
99 | #include <linux/wanrouter.h> /* WAN router definitions */ | ||
100 | #include <linux/wanpipe.h> /* WANPIPE common user API definitions */ | ||
101 | #include <linux/if_arp.h> /* ARPHRD_* defines */ | ||
102 | #include <asm/byteorder.h> /* htons(), etc. */ | ||
103 | #include <linux/in.h> /* sockaddr_in */ | ||
104 | #include <linux/jiffies.h> /* time_after() macro */ | ||
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 | } | ||
486 | if (time_after(jiffies, timeout + 1 * HZ)){ | ||
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 *****************************************************************/ | ||