]>
Commit | Line | Data |
---|---|---|
d8b99645 | 1 | --- linux-2.4.orig/Documentation/networking/generic-hdlc.txt 2003-07-29 23:24:56.000000000 +0200 |
2 | +++ linux-2.4/Documentation/networking/generic-hdlc.txt 2003-07-29 23:32:23.000000000 +0200 | |
3 | @@ -1,11 +1,13 @@ | |
4 | -Generic HDLC layer for Linux kernel 2.4/2.5 | |
5 | +Generic HDLC layer | |
6 | Krzysztof Halasa <khc@pm.waw.pl> | |
7 | -May, 2001 | |
8 | +January, 2003 | |
9 | ||
10 | ||
11 | Generic HDLC layer currently supports: | |
12 | -- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP), | |
13 | -- raw HDLC (IPv4 only), | |
14 | +- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP). | |
15 | + Normal (routed) and Ethernet-bridged (Ethernet device emulation) | |
16 | + interfaces can share a single PVC. | |
17 | +- raw HDLC - either IP (IPv4) interface or Ethernet device emulation. | |
18 | - Cisco HDLC, | |
19 | - PPP (uses syncppp.c), | |
20 | - X.25 (uses X.25 routines). | |
21 | @@ -15,6 +17,10 @@ | |
22 | - RISCom/N2 by SDL Communications Inc. | |
23 | - and others, some not in the official kernel. | |
24 | ||
25 | +Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible | |
26 | +with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging). | |
27 | + | |
28 | + | |
29 | Make sure the hdlc.o and the hardware driver are loaded. It should | |
30 | create a number of "hdlc" (hdlc0 etc) network devices, one for each | |
31 | WAN port. You'll need the "sethdlc" utility, get it from: | |
32 | @@ -32,8 +38,10 @@ | |
33 | sethdlc hdlc0 cisco interval 10 timeout 25 | |
34 | or | |
35 | sethdlc hdlc0 rs232 clock ext | |
36 | - sethdlc fr lmi ansi | |
37 | - sethdlc create 99 | |
38 | + sethdlc hdlc0 fr lmi ansi | |
39 | + sethdlc hdlc0 create 99 | |
40 | + ifconfig hdlc0 up | |
41 | + ifconfig pvc0 localIP pointopoint remoteIP | |
42 | ||
43 | In Frame Relay mode, ifconfig master hdlc device up (without assigning | |
44 | any IP address to it) before using pvc devices. | |
45 | @@ -58,6 +66,9 @@ | |
46 | no-parity / crc16 / crc16-pr0 (CRC16 with preset zeros) / crc32-itu | |
47 | crc16-itu (CRC16 with ITU-T polynomial) / crc16-itu-pr0 - sets parity | |
48 | ||
49 | +* hdlc-eth - Ethernet device emulation using HDLC. Parity and encoding | |
50 | + as above. | |
51 | + | |
52 | * cisco - sets Cisco HDLC mode (IP, IPv6 and IPX supported) | |
53 | interval - time in seconds between keepalive packets | |
54 | timeout - time in seconds after last received keepalive packet before | |
55 | @@ -77,7 +88,12 @@ | |
56 | n392 - error threshold - both user and network | |
57 | n393 - monitored events count - both user and network | |
58 | ||
59 | -* create | delete n - FR only - adds / deletes PVC interface with DLCI #n. | |
60 | +Frame-Relay only: | |
61 | +* create n | delete n - adds / deletes PVC interface with DLCI #n. | |
62 | + Newly created interface will be named pvc0, pvc1 etc. | |
63 | + | |
64 | +* create ether n | delete ether n - adds a device for Ethernet-bridged | |
65 | + frames. The device will be named pvceth0, pvceth1 etc. | |
66 | ||
67 | ||
68 | ||
69 | @@ -104,11 +120,11 @@ | |
70 | ||
71 | ||
72 | If you have a problem with N2 or C101 card, you can issue the "private" | |
73 | -command to see port's packet descriptor rings: | |
74 | +command to see port's packet descriptor rings (in kernel logs): | |
75 | ||
76 | sethdlc hdlc0 private | |
77 | ||
78 | -The hardware driver have to be build with CONFIG_HDLC_DEBUG_RINGS. | |
79 | +The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS. | |
80 | Attaching this info to bug reports would be helpful. Anyway, let me know | |
81 | if you have problems using this. | |
82 | ||
83 | --- linux-2.4.orig/include/linux/if.h 2003-07-29 23:25:12.000000000 +0200 | |
84 | +++ linux-2.4/include/linux/if.h 2003-07-29 23:32:23.000000000 +0200 | |
85 | @@ -21,6 +21,8 @@ | |
86 | ||
87 | #include <linux/types.h> /* for "__kernel_caddr_t" et al */ | |
88 | #include <linux/socket.h> /* for "struct sockaddr" et al */ | |
89 | + | |
90 | +#define IFNAMSIZ 16 | |
91 | #include <linux/hdlc/ioctl.h> | |
92 | ||
93 | /* Standard interface flags (netdevice->flags). */ | |
94 | @@ -59,7 +61,7 @@ | |
95 | #define IF_IFACE_X21 0x1002 /* X.21 serial interface */ | |
96 | #define IF_IFACE_T1 0x1003 /* T1 telco serial interface */ | |
97 | #define IF_IFACE_E1 0x1004 /* E1 telco serial interface */ | |
98 | -#define IF_IFACE_SYNC_SERIAL 0x1005 /* cant'b be set by software */ | |
99 | +#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */ | |
100 | ||
101 | /* For definitions see hdlc.h */ | |
102 | #define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */ | |
103 | @@ -69,7 +71,11 @@ | |
104 | #define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */ | |
105 | #define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */ | |
106 | #define IF_PROTO_X25 0x2006 /* X.25 */ | |
107 | - | |
108 | +#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */ | |
109 | +#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */ | |
110 | +#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */ | |
111 | +#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */ | |
112 | +#define IF_PROTO_FR_ETH_PVC 0x200B | |
113 | ||
114 | ||
115 | /* | |
116 | @@ -103,6 +109,7 @@ | |
117 | cisco_proto *cisco; | |
118 | fr_proto *fr; | |
119 | fr_proto_pvc *fr_pvc; | |
120 | + fr_proto_pvc_info *fr_pvc_info; | |
121 | ||
122 | /* interface settings */ | |
123 | sync_serial_settings *sync; | |
124 | @@ -120,7 +127,6 @@ | |
125 | struct ifreq | |
126 | { | |
127 | #define IFHWADDRLEN 6 | |
128 | -#define IFNAMSIZ 16 | |
129 | union | |
130 | { | |
131 | char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ | |
132 | --- linux-2.4.orig/include/linux/hdlc.h 2003-07-29 23:25:12.000000000 +0200 | |
133 | +++ linux-2.4/include/linux/hdlc.h 2003-07-29 23:32:23.000000000 +0200 | |
134 | @@ -1,12 +1,11 @@ | |
135 | /* | |
136 | * Generic HDLC support routines for Linux | |
137 | * | |
138 | - * Copyright (C) 1999-2002 Krzysztof Halasa <khc@pm.waw.pl> | |
139 | + * Copyright (C) 1999-2003 Krzysztof Halasa <khc@pm.waw.pl> | |
140 | * | |
141 | * This program is free software; you can redistribute it and/or modify it | |
142 | - * under the terms of the GNU General Public License as published by | |
143 | - * the Free Software Foundation; either version 2 of the License, or | |
144 | - * (at your option) any later version. | |
145 | + * under the terms of version 2 of the GNU General Public License | |
146 | + * as published by the Free Software Foundation. | |
147 | */ | |
148 | ||
149 | #ifndef __HDLC_H | |
150 | @@ -52,7 +51,7 @@ | |
151 | #include <linux/hdlc/ioctl.h> | |
152 | ||
153 | #define HDLC_MAX_MTU 1500 /* Ethernet 1500 bytes */ | |
154 | -#define HDLC_MAX_MRU (HDLC_MAX_MTU + 10) /* max 10 bytes for FR */ | |
155 | +#define HDLC_MAX_MRU (HDLC_MAX_MTU + 10 + 14 + 4) /* for ETH+VLAN over FR */ | |
156 | ||
157 | #define MAXLEN_LMISTAT 20 /* max size of status enquiry frame */ | |
158 | ||
159 | @@ -145,17 +144,20 @@ | |
160 | ||
161 | ||
162 | typedef struct pvc_device_struct { | |
163 | - struct net_device netdev; /* PVC net device - must be first */ | |
164 | - struct net_device_stats stats; | |
165 | struct hdlc_device_struct *master; | |
166 | - struct pvc_device_struct *next; | |
167 | + struct net_device *main; | |
168 | + struct net_device *ether; /* bridged Ethernet interface */ | |
169 | + struct pvc_device_struct *next; /* Sorted in ascending DLCI order */ | |
170 | + int dlci; | |
171 | + int open_count; | |
172 | ||
173 | struct { | |
174 | - int active; | |
175 | - int new; | |
176 | - int deleted; | |
177 | - int fecn; | |
178 | - int becn; | |
179 | + unsigned int new: 1; | |
180 | + unsigned int active: 1; | |
181 | + unsigned int exist: 1; | |
182 | + unsigned int deleted: 1; | |
183 | + unsigned int fecn: 1; | |
184 | + unsigned int becn: 1; | |
185 | }state; | |
186 | }pvc_device; | |
187 | ||
188 | @@ -180,18 +182,20 @@ | |
189 | void (*stop)(struct hdlc_device_struct *hdlc); | |
190 | void (*proto_detach)(struct hdlc_device_struct *hdlc); | |
191 | void (*netif_rx)(struct sk_buff *skb); | |
192 | + unsigned short (*type_trans)(struct sk_buff *skb, | |
193 | + struct net_device *dev); | |
194 | int proto; /* IF_PROTO_HDLC/CISCO/FR/etc. */ | |
195 | ||
196 | union { | |
197 | struct { | |
198 | fr_proto settings; | |
199 | pvc_device *first_pvc; | |
200 | - int pvc_count; | |
201 | + int dce_pvc_count; | |
202 | ||
203 | struct timer_list timer; | |
204 | int last_poll; | |
205 | int reliable; | |
206 | - int changed; | |
207 | + int dce_changed; | |
208 | int request; | |
209 | int fullrep_sent; | |
210 | u32 last_errors; /* last errors bit list */ | |
211 | @@ -226,6 +230,7 @@ | |
212 | ||
213 | ||
214 | int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr); | |
215 | +int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr); | |
216 | int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr); | |
217 | int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr); | |
218 | int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr); | |
219 | @@ -254,15 +259,9 @@ | |
220 | } | |
221 | ||
222 | ||
223 | -static __inline__ struct net_device* pvc_to_dev(pvc_device *pvc) | |
224 | -{ | |
225 | - return &pvc->netdev; | |
226 | -} | |
227 | - | |
228 | - | |
229 | static __inline__ pvc_device* dev_to_pvc(struct net_device *dev) | |
230 | { | |
231 | - return (pvc_device*)dev; | |
232 | + return (pvc_device*)dev->priv; | |
233 | } | |
234 | ||
235 | ||
236 | @@ -272,19 +271,6 @@ | |
237 | } | |
238 | ||
239 | ||
240 | -static __inline__ const char *pvc_to_name(pvc_device *pvc) | |
241 | -{ | |
242 | - return pvc_to_dev(pvc)->name; | |
243 | -} | |
244 | - | |
245 | - | |
246 | -static __inline__ u16 netdev_dlci(struct net_device *dev) | |
247 | -{ | |
248 | - return ntohs(*(u16*)dev->dev_addr); | |
249 | -} | |
250 | - | |
251 | - | |
252 | - | |
253 | static __inline__ u16 q922_to_dlci(u8 *hdr) | |
254 | { | |
255 | return ((hdr[0] & 0xFC) << 2) | ((hdr[1] & 0xF0) >> 4); | |
256 | @@ -345,5 +331,15 @@ | |
257 | } | |
258 | ||
259 | ||
260 | +static __inline__ unsigned short hdlc_type_trans(struct sk_buff *skb, | |
261 | + struct net_device *dev) | |
262 | +{ | |
263 | + hdlc_device *hdlc = dev_to_hdlc(skb->dev); | |
264 | + if (hdlc->type_trans) | |
265 | + return hdlc->type_trans(skb, dev); | |
266 | + else | |
267 | + return __constant_htons(ETH_P_HDLC); | |
268 | +} | |
269 | + | |
270 | #endif /* __KERNEL */ | |
271 | #endif /* __HDLC_H */ | |
272 | --- linux-2.4.orig/include/linux/hdlc/ioctl.h 2003-07-29 23:25:12.000000000 +0200 | |
273 | +++ linux-2.4/include/linux/hdlc/ioctl.h 2003-07-29 23:32:23.000000000 +0200 | |
274 | @@ -34,22 +34,15 @@ | |
275 | } fr_proto_pvc; /* for creating/deleting FR PVCs */ | |
276 | ||
277 | typedef struct { | |
278 | + unsigned int dlci; | |
279 | + char master[IFNAMSIZ]; /* Name of master FRAD device */ | |
280 | +}fr_proto_pvc_info; /* for returning PVC information only */ | |
281 | + | |
282 | +typedef struct { | |
283 | unsigned int interval; | |
284 | unsigned int timeout; | |
285 | } cisco_proto; | |
286 | ||
287 | /* PPP doesn't need any info now - supply length = 0 to ioctl */ | |
288 | ||
289 | -union hdlc_settings { | |
290 | - raw_hdlc_proto raw_hdlc; | |
291 | - cisco_proto cisco; | |
292 | - fr_proto fr; | |
293 | - fr_proto_pvc fr_pvc; | |
294 | -}; | |
295 | - | |
296 | -union line_settings { | |
297 | - sync_serial_settings sync; | |
298 | - te1_settings te1; | |
299 | -}; | |
300 | - | |
301 | #endif /* __HDLC_IOCTL_H__ */ | |
302 | --- linux-2.4.orig/drivers/net/wan/Makefile 2003-07-29 23:25:03.000000000 +0200 | |
303 | +++ linux-2.4/drivers/net/wan/Makefile 2003-07-29 23:32:23.000000000 +0200 | |
304 | @@ -24,6 +24,7 @@ | |
305 | ||
306 | hdlc-y := hdlc_generic.o | |
307 | hdlc-$(CONFIG_HDLC_RAW) += hdlc_raw.o | |
308 | +hdlc-$(CONFIG_HDLC_RAW_ETH) += hdlc_raw_eth.o | |
309 | hdlc-$(CONFIG_HDLC_CISCO) += hdlc_cisco.o | |
310 | hdlc-$(CONFIG_HDLC_FR) += hdlc_fr.o | |
311 | hdlc-$(CONFIG_HDLC_PPP) += hdlc_ppp.o | |
312 | --- linux-2.4.orig/drivers/net/wan/hdlc_cisco.c 2003-07-29 23:25:03.000000000 +0200 | |
313 | +++ linux-2.4/drivers/net/wan/hdlc_cisco.c 2003-07-29 23:32:23.000000000 +0200 | |
314 | @@ -2,12 +2,11 @@ | |
315 | * Generic HDLC support routines for Linux | |
316 | * Cisco HDLC support | |
317 | * | |
318 | - * Copyright (C) 2000 - 2001 Krzysztof Halasa <khc@pm.waw.pl> | |
319 | + * Copyright (C) 2000 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | |
320 | * | |
321 | * This program is free software; you can redistribute it and/or modify it | |
322 | - * under the terms of the GNU General Public License as published by | |
323 | - * the Free Software Foundation; either version 2 of the License, or | |
324 | - * (at your option) any later version. | |
325 | + * under the terms of version 2 of the GNU General Public License | |
326 | + * as published by the Free Software Foundation. | |
327 | */ | |
328 | ||
329 | #include <linux/config.h> | |
330 | @@ -80,17 +79,43 @@ | |
331 | data->par1 = htonl(par1); | |
332 | data->par2 = htonl(par2); | |
333 | data->rel = 0xFFFF; | |
334 | - data->time = htonl(jiffies * 1000 / HZ); | |
335 | + /* we will need do_div here if 1000 % HZ != 0 */ | |
336 | + data->time = htonl(jiffies * (1000 / HZ)); | |
337 | ||
338 | skb_put(skb, sizeof(cisco_packet)); | |
339 | skb->priority = TC_PRIO_CONTROL; | |
340 | skb->dev = hdlc_to_dev(hdlc); | |
341 | + skb->nh.raw = skb->data; | |
342 | ||
343 | dev_queue_xmit(skb); | |
344 | } | |
345 | ||
346 | ||
347 | ||
348 | +static unsigned short cisco_type_trans(struct sk_buff *skb, | |
349 | + struct net_device *dev) | |
350 | +{ | |
351 | + hdlc_header *data = (hdlc_header*)skb->data; | |
352 | + | |
353 | + if (skb->len < sizeof(hdlc_header)) | |
354 | + return __constant_htons(ETH_P_HDLC); | |
355 | + | |
356 | + if (data->address != CISCO_MULTICAST && | |
357 | + data->address != CISCO_UNICAST) | |
358 | + return __constant_htons(ETH_P_HDLC); | |
359 | + | |
360 | + switch(data->protocol) { | |
361 | + case __constant_htons(ETH_P_IP): | |
362 | + case __constant_htons(ETH_P_IPX): | |
363 | + case __constant_htons(ETH_P_IPV6): | |
364 | + skb_pull(skb, sizeof(hdlc_header)); | |
365 | + return data->protocol; | |
366 | + default: | |
367 | + return __constant_htons(ETH_P_HDLC); | |
368 | + } | |
369 | +} | |
370 | + | |
371 | + | |
372 | static void cisco_rx(struct sk_buff *skb) | |
373 | { | |
374 | hdlc_device *hdlc = dev_to_hdlc(skb->dev); | |
375 | @@ -109,14 +134,6 @@ | |
376 | skb_pull(skb, sizeof(hdlc_header)); | |
377 | ||
378 | switch(ntohs(data->protocol)) { | |
379 | - case ETH_P_IP: | |
380 | - case ETH_P_IPX: | |
381 | - case ETH_P_IPV6: | |
382 | - skb->protocol = data->protocol; | |
383 | - skb->dev = hdlc_to_dev(hdlc); | |
384 | - netif_rx(skb); | |
385 | - return; | |
386 | - | |
387 | case CISCO_SYS_INFO: | |
388 | /* Packet is not needed, drop it. */ | |
389 | dev_kfree_skb_any(skb); | |
390 | @@ -288,6 +305,7 @@ | |
391 | hdlc->open = cisco_open; | |
392 | hdlc->stop = cisco_close; | |
393 | hdlc->netif_rx = cisco_rx; | |
394 | + hdlc->type_trans = cisco_type_trans; | |
395 | hdlc->proto = IF_PROTO_CISCO; | |
396 | dev->hard_start_xmit = hdlc->xmit; | |
397 | dev->hard_header = cisco_hard_header; | |
398 | --- linux-2.4.orig/drivers/net/wan/hdlc_fr.c 2003-07-29 23:25:03.000000000 +0200 | |
399 | +++ linux-2.4/drivers/net/wan/hdlc_fr.c 2003-07-29 23:32:23.000000000 +0200 | |
400 | @@ -2,13 +2,22 @@ | |
401 | * Generic HDLC support routines for Linux | |
402 | * Frame Relay support | |
403 | * | |
404 | - * Copyright (C) 1999 - 2001 Krzysztof Halasa <khc@pm.waw.pl> | |
405 | + * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | |
406 | * | |
407 | * This program is free software; you can redistribute it and/or modify it | |
408 | - * under the terms of the GNU General Public License as published by | |
409 | - * the Free Software Foundation; either version 2 of the License, or | |
410 | - * (at your option) any later version. | |
411 | - */ | |
412 | + * under the terms of version 2 of the GNU General Public License | |
413 | + * as published by the Free Software Foundation. | |
414 | + * | |
415 | + | |
416 | + Theory of PVC state in DCE mode: | |
417 | + | |
418 | + (exist,new) -> 0,0 when "PVC create" or if "link unreliable" | |
419 | + 0,x -> 1,1 if "link reliable" when sending FULL STATUS | |
420 | + 1,1 -> 1,0 if received FULL STATUS ACK | |
421 | + | |
422 | + (active) -> 0 when "ifconfig PVC down" or "link unreliable" or "PVC create" | |
423 | + -> 1 when "PVC up" and (exist,new) = 1,0 | |
424 | +*/ | |
425 | ||
426 | #include <linux/config.h> | |
427 | #include <linux/module.h> | |
428 | @@ -20,19 +29,23 @@ | |
429 | #include <linux/init.h> | |
430 | #include <linux/skbuff.h> | |
431 | #include <linux/pkt_sched.h> | |
432 | +#include <linux/random.h> | |
433 | #include <linux/inetdevice.h> | |
434 | #include <linux/lapb.h> | |
435 | #include <linux/rtnetlink.h> | |
436 | +#include <linux/etherdevice.h> | |
437 | #include <linux/hdlc.h> | |
438 | ||
439 | ||
440 | __inline__ pvc_device* find_pvc(hdlc_device *hdlc, u16 dlci) | |
441 | { | |
442 | - pvc_device *pvc=hdlc->state.fr.first_pvc; | |
443 | - | |
444 | - while (pvc) { | |
445 | - if (netdev_dlci(&pvc->netdev) == dlci) | |
446 | + pvc_device *pvc = hdlc->state.fr.first_pvc; | |
447 | + | |
448 | + while(pvc) { | |
449 | + if (pvc->dlci == dlci) | |
450 | return pvc; | |
451 | + if (pvc->dlci > dlci) | |
452 | + return NULL; /* the listed is sorted */ | |
453 | pvc = pvc->next; | |
454 | } | |
455 | ||
456 | @@ -40,18 +53,72 @@ | |
457 | } | |
458 | ||
459 | ||
460 | +__inline__ pvc_device* add_pvc(hdlc_device *hdlc, u16 dlci) | |
461 | +{ | |
462 | + pvc_device *pvc, **pvc_p = &hdlc->state.fr.first_pvc; | |
463 | + | |
464 | + while(*pvc_p) { | |
465 | + if ((*pvc_p)->dlci == dlci) | |
466 | + return *pvc_p; | |
467 | + if ((*pvc_p)->dlci > dlci) | |
468 | + break; /* the listed is sorted */ | |
469 | + pvc_p = &(*pvc_p)->next; | |
470 | + } | |
471 | + | |
472 | + pvc = kmalloc(sizeof(pvc_device), GFP_ATOMIC); | |
473 | + if (!pvc) | |
474 | + return NULL; | |
475 | + | |
476 | + memset(pvc, 0, sizeof(pvc_device)); | |
477 | + pvc->dlci = dlci; | |
478 | + pvc->master = hdlc; | |
479 | + pvc->next = *pvc_p; /* Put it in the chain */ | |
480 | + *pvc_p = pvc; | |
481 | + return pvc; | |
482 | +} | |
483 | + | |
484 | + | |
485 | +__inline__ int pvc_is_used(pvc_device *pvc) | |
486 | +{ | |
487 | + return pvc->main != NULL || pvc->ether != NULL; | |
488 | +} | |
489 | + | |
490 | + | |
491 | +__inline__ void delete_unused_pvcs(hdlc_device *hdlc) | |
492 | +{ | |
493 | + pvc_device **pvc_p = &hdlc->state.fr.first_pvc; | |
494 | + | |
495 | + while(*pvc_p) { | |
496 | + if (!pvc_is_used(*pvc_p)) { | |
497 | + pvc_device *pvc = *pvc_p; | |
498 | + *pvc_p = pvc->next; | |
499 | + kfree(pvc); | |
500 | + continue; | |
501 | + } | |
502 | + pvc_p = &(*pvc_p)->next; | |
503 | + } | |
504 | +} | |
505 | ||
506 | -__inline__ u16 status_to_dlci(hdlc_device *hdlc, u8 *status, | |
507 | - int *active, int *new) | |
508 | + | |
509 | +__inline__ struct net_device** get_dev_p(pvc_device *pvc, int type) | |
510 | { | |
511 | - *new = (status[2] & 0x08); | |
512 | - *active = (!*new && (status[2] & 0x02)); | |
513 | + if (type == ARPHRD_ETHER) | |
514 | + return &pvc->ether; | |
515 | + else | |
516 | + return &pvc->main; | |
517 | +} | |
518 | + | |
519 | + | |
520 | +__inline__ u16 status_to_dlci(u8 *status, int *active, int *new) | |
521 | +{ | |
522 | + *new = (status[2] & 0x08) ? 1 : 0; | |
523 | + *active = (status[2] & 0x02) ? 1 : 0; | |
524 | ||
525 | return ((status[0] & 0x3F)<<4) | ((status[1] & 0x78)>>3); | |
526 | } | |
527 | ||
528 | ||
529 | -__inline__ void dlci_to_status(hdlc_device *hdlc, u16 dlci, u8 *status, | |
530 | +__inline__ void dlci_to_status(u16 dlci, u8 *status, | |
531 | int active, int new) | |
532 | { | |
533 | status[0] = (dlci>>4) & 0x3F; | |
534 | @@ -66,37 +133,50 @@ | |
535 | ||
536 | ||
537 | ||
538 | -static int fr_hard_header(struct sk_buff *skb, struct net_device *dev, | |
539 | - u16 type, void *daddr, void *saddr, unsigned int len) | |
540 | +static int fr_hard_header(struct sk_buff **skb_p, u16 dlci) | |
541 | { | |
542 | u16 head_len; | |
543 | + struct sk_buff *skb = *skb_p; | |
544 | ||
545 | - if (!daddr) | |
546 | - daddr = dev->broadcast; | |
547 | - | |
548 | -#ifdef CONFIG_HDLC_DEBUG_HARD_HEADER | |
549 | - printk(KERN_DEBUG "%s: fr_hard_header called\n", dev->name); | |
550 | -#endif | |
551 | - | |
552 | - switch(type) { | |
553 | - case ETH_P_IP: | |
554 | + switch(skb->protocol) { | |
555 | + case __constant_ntohs(ETH_P_IP): | |
556 | head_len = 4; | |
557 | skb_push(skb, head_len); | |
558 | skb->data[3] = NLPID_IP; | |
559 | break; | |
560 | ||
561 | - case ETH_P_IPV6: | |
562 | + case __constant_ntohs(ETH_P_IPV6): | |
563 | head_len = 4; | |
564 | skb_push(skb, head_len); | |
565 | skb->data[3] = NLPID_IPV6; | |
566 | break; | |
567 | ||
568 | - case LMI_PROTO: | |
569 | + case __constant_ntohs(LMI_PROTO): | |
570 | head_len = 4; | |
571 | skb_push(skb, head_len); | |
572 | skb->data[3] = LMI_PROTO; | |
573 | break; | |
574 | ||
575 | + case __constant_ntohs(ETH_P_802_3): | |
576 | + head_len = 10; | |
577 | + if (skb_headroom(skb) < head_len) { | |
578 | + struct sk_buff *skb2 = skb_realloc_headroom(skb, | |
579 | + head_len); | |
580 | + if (!skb2) | |
581 | + return -ENOBUFS; | |
582 | + dev_kfree_skb(skb); | |
583 | + skb = *skb_p = skb2; | |
584 | + } | |
585 | + skb_push(skb, head_len); | |
586 | + skb->data[3] = FR_PAD; | |
587 | + skb->data[4] = NLPID_SNAP; | |
588 | + skb->data[5] = FR_PAD; | |
589 | + skb->data[6] = 0x80; | |
590 | + skb->data[7] = 0xC2; | |
591 | + skb->data[8] = 0x00; | |
592 | + skb->data[9] = 0x07; /* bridged Ethernet frame w/out FCS */ | |
593 | + break; | |
594 | + | |
595 | default: | |
596 | head_len = 10; | |
597 | skb_push(skb, head_len); | |
598 | @@ -105,14 +185,12 @@ | |
599 | skb->data[5] = FR_PAD; | |
600 | skb->data[6] = FR_PAD; | |
601 | skb->data[7] = FR_PAD; | |
602 | - skb->data[8] = type>>8; | |
603 | - skb->data[9] = (u8)type; | |
604 | + *(u16*)(skb->data + 8) = skb->protocol; | |
605 | } | |
606 | ||
607 | - memcpy(skb->data, daddr, 2); | |
608 | + dlci_to_q922(skb->data, dlci); | |
609 | skb->data[2] = FR_UI; | |
610 | - | |
611 | - return head_len; | |
612 | + return 0; | |
613 | } | |
614 | ||
615 | ||
616 | @@ -124,13 +202,12 @@ | |
617 | if ((hdlc_to_dev(pvc->master)->flags & IFF_UP) == 0) | |
618 | return -EIO; /* Master must be UP in order to activate PVC */ | |
619 | ||
620 | - if (pvc->master->state.fr.settings.lmi != LMI_NONE) | |
621 | - pvc->state.active = 0; | |
622 | - else | |
623 | - pvc->state.active = 1; | |
624 | + if (pvc->open_count++ == 0) { | |
625 | + if (pvc->master->state.fr.settings.lmi == LMI_NONE) | |
626 | + pvc->state.active = 1; | |
627 | ||
628 | - pvc->state.new = 0; | |
629 | - pvc->master->state.fr.changed = 1; | |
630 | + pvc->master->state.fr.dce_changed = 1; | |
631 | + } | |
632 | return 0; | |
633 | } | |
634 | ||
635 | @@ -139,38 +216,94 @@ | |
636 | static int pvc_close(struct net_device *dev) | |
637 | { | |
638 | pvc_device *pvc = dev_to_pvc(dev); | |
639 | - pvc->state.active = pvc->state.new = 0; | |
640 | - pvc->master->state.fr.changed = 1; | |
641 | + | |
642 | + if (--pvc->open_count == 0) { | |
643 | + if (pvc->master->state.fr.settings.lmi == LMI_NONE) | |
644 | + pvc->state.active = 0; | |
645 | + | |
646 | + if (pvc->master->state.fr.settings.dce) { | |
647 | + pvc->master->state.fr.dce_changed = 1; | |
648 | + pvc->state.active = 0; | |
649 | + } | |
650 | + } | |
651 | return 0; | |
652 | } | |
653 | ||
654 | ||
655 | ||
656 | -static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) | |
657 | +int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |
658 | { | |
659 | pvc_device *pvc = dev_to_pvc(dev); | |
660 | + fr_proto_pvc_info info; | |
661 | ||
662 | - if (pvc->state.active) { | |
663 | - skb->dev = hdlc_to_dev(pvc->master); | |
664 | - pvc->stats.tx_bytes += skb->len; | |
665 | - pvc->stats.tx_packets++; | |
666 | - if (pvc->state.fecn) | |
667 | - pvc->stats.tx_compressed++; /* TX Congestion counter */ | |
668 | - dev_queue_xmit(skb); | |
669 | - } else { | |
670 | - pvc->stats.tx_dropped++; | |
671 | - dev_kfree_skb(skb); | |
672 | + if (ifr->ifr_settings.type == IF_GET_PROTO) { | |
673 | + if (dev->type == ARPHRD_ETHER) | |
674 | + ifr->ifr_settings.type = IF_PROTO_FR_ETH_PVC; | |
675 | + else | |
676 | + ifr->ifr_settings.type = IF_PROTO_FR_PVC; | |
677 | + | |
678 | + if (ifr->ifr_settings.size < sizeof(info)) { | |
679 | + /* data size wanted */ | |
680 | + ifr->ifr_settings.size = sizeof(info); | |
681 | + return -ENOBUFS; | |
682 | + } | |
683 | + | |
684 | + info.dlci = pvc->dlci; | |
685 | + memcpy(info.master, hdlc_to_name(pvc->master), IFNAMSIZ); | |
686 | + if (copy_to_user(ifr->ifr_settings.ifs_ifsu.fr_pvc_info, | |
687 | + &info, sizeof(info))) | |
688 | + return -EFAULT; | |
689 | + return 0; | |
690 | } | |
691 | ||
692 | - return 0; | |
693 | + return -EINVAL; | |
694 | +} | |
695 | + | |
696 | + | |
697 | +__inline__ struct net_device_stats *pvc_get_stats(struct net_device *dev) | |
698 | +{ | |
699 | + return (struct net_device_stats *) | |
700 | + ((char *)dev + sizeof(struct net_device)); | |
701 | } | |
702 | ||
703 | ||
704 | ||
705 | -static struct net_device_stats *pvc_get_stats(struct net_device *dev) | |
706 | +static int pvc_xmit(struct sk_buff *skb, struct net_device *dev) | |
707 | { | |
708 | pvc_device *pvc = dev_to_pvc(dev); | |
709 | - return &pvc->stats; | |
710 | + struct net_device_stats *stats = pvc_get_stats(dev); | |
711 | + | |
712 | + if (pvc->state.active) { | |
713 | + if (dev->type == ARPHRD_ETHER) { | |
714 | + int pad = ETH_ZLEN - skb->len; | |
715 | + if (pad > 0) { /* Pad the frame with zeros */ | |
716 | + int len = skb->len; | |
717 | + if (skb_tailroom(skb) < pad) | |
718 | + if (pskb_expand_head(skb, 0, pad, | |
719 | + GFP_ATOMIC)) { | |
720 | + stats->tx_dropped++; | |
721 | + dev_kfree_skb(skb); | |
722 | + return 0; | |
723 | + } | |
724 | + skb_put(skb, pad); | |
725 | + memset(skb->data + len, 0, pad); | |
726 | + } | |
727 | + skb->protocol = __constant_htons(ETH_P_802_3); | |
728 | + } | |
729 | + if (!fr_hard_header(&skb, pvc->dlci)) { | |
730 | + stats->tx_bytes += skb->len; | |
731 | + stats->tx_packets++; | |
732 | + if (pvc->state.fecn) /* TX Congestion counter */ | |
733 | + stats->tx_compressed++; | |
734 | + skb->dev = hdlc_to_dev(pvc->master); | |
735 | + dev_queue_xmit(skb); | |
736 | + return 0; | |
737 | + } | |
738 | + } | |
739 | + | |
740 | + stats->tx_dropped++; | |
741 | + dev_kfree_skb(skb); | |
742 | + return 0; | |
743 | } | |
744 | ||
745 | ||
746 | @@ -187,9 +320,15 @@ | |
747 | ||
748 | static inline void fr_log_dlci_active(pvc_device *pvc) | |
749 | { | |
750 | - printk(KERN_INFO "%s: %sactive%s\n", pvc_to_name(pvc), | |
751 | - pvc->state.active ? "" : "in", | |
752 | - pvc->state.new ? " new" : ""); | |
753 | + printk(KERN_INFO "%s: DLCI %d [%s%s%s]%s %s\n", | |
754 | + hdlc_to_name(pvc->master), | |
755 | + pvc->dlci, | |
756 | + pvc->main ? pvc->main->name : "", | |
757 | + pvc->main && pvc->ether ? " " : "", | |
758 | + pvc->ether ? pvc->ether->name : "", | |
759 | + pvc->state.new ? " new" : "", | |
760 | + !pvc->state.exist ? "deleted" : | |
761 | + pvc->state.active ? "active" : "inactive"); | |
762 | } | |
763 | ||
764 | ||
765 | @@ -213,8 +352,8 @@ | |
766 | int i = 0; | |
767 | ||
768 | if (hdlc->state.fr.settings.dce && fullrep) { | |
769 | - len += hdlc->state.fr.pvc_count * (2 + stat_len); | |
770 | - if (len > HDLC_MAX_MTU) { | |
771 | + len += hdlc->state.fr.dce_pvc_count * (2 + stat_len); | |
772 | + if (len > HDLC_MAX_MRU) { | |
773 | printk(KERN_WARNING "%s: Too many PVCs while sending " | |
774 | "LMI full report\n", hdlc_to_name(hdlc)); | |
775 | return; | |
776 | @@ -224,12 +363,13 @@ | |
777 | skb = dev_alloc_skb(len); | |
778 | if (!skb) { | |
779 | printk(KERN_WARNING "%s: Memory squeeze on fr_lmi_send()\n", | |
780 | - hdlc_to_name(hdlc)); | |
781 | + hdlc_to_name(hdlc)); | |
782 | return; | |
783 | } | |
784 | memset(skb->data, 0, len); | |
785 | skb_reserve(skb, 4); | |
786 | - fr_hard_header(skb, hdlc_to_dev(hdlc), LMI_PROTO, NULL, NULL, 0); | |
787 | + skb->protocol = __constant_htons(LMI_PROTO); | |
788 | + fr_hard_header(&skb, LMI_DLCI); | |
789 | data = skb->tail; | |
790 | data[i++] = LMI_CALLREF; | |
791 | data[i++] = hdlc->state.fr.settings.dce | |
792 | @@ -253,16 +393,20 @@ | |
793 | ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT; | |
794 | data[i++] = stat_len; | |
795 | ||
796 | - if (hdlc->state.fr.reliable && | |
797 | - (pvc->netdev.flags & IFF_UP) && | |
798 | - !pvc->state.active && | |
799 | - !pvc->state.new) { | |
800 | - pvc->state.new = 1; | |
801 | + /* LMI start/restart */ | |
802 | + if (hdlc->state.fr.reliable && !pvc->state.exist) { | |
803 | + pvc->state.exist = pvc->state.new = 1; | |
804 | + fr_log_dlci_active(pvc); | |
805 | + } | |
806 | + | |
807 | + /* ifconfig PVC up */ | |
808 | + if (pvc->open_count && !pvc->state.active && | |
809 | + pvc->state.exist && !pvc->state.new) { | |
810 | + pvc->state.active = 1; | |
811 | fr_log_dlci_active(pvc); | |
812 | } | |
813 | ||
814 | - dlci_to_status(hdlc, netdev_dlci(&pvc->netdev), | |
815 | - data + i, | |
816 | + dlci_to_status(pvc->dlci, data + i, | |
817 | pvc->state.active, pvc->state.new); | |
818 | i += stat_len; | |
819 | pvc = pvc->next; | |
820 | @@ -272,6 +416,7 @@ | |
821 | skb_put(skb, i); | |
822 | skb->priority = TC_PRIO_CONTROL; | |
823 | skb->dev = hdlc_to_dev(hdlc); | |
824 | + skb->nh.raw = skb->data; | |
825 | ||
826 | dev_queue_xmit(skb); | |
827 | } | |
828 | @@ -312,10 +457,11 @@ | |
829 | ||
830 | if (reliable) { | |
831 | hdlc->state.fr.n391cnt = 0; /* Request full status */ | |
832 | - hdlc->state.fr.changed = 1; | |
833 | + hdlc->state.fr.dce_changed = 1; | |
834 | } else { | |
835 | while (pvc) { /* Deactivate all PVCs */ | |
836 | - pvc->state.new = pvc->state.active = 0; | |
837 | + pvc->state.exist = 0; | |
838 | + pvc->state.active = pvc->state.new = 0; | |
839 | pvc = pvc->next; | |
840 | } | |
841 | } | |
842 | @@ -346,7 +492,7 @@ | |
843 | { | |
844 | int stat_len; | |
845 | pvc_device *pvc; | |
846 | - int reptype = -1, error; | |
847 | + int reptype = -1, error, no_ram; | |
848 | u8 rxseq, txseq; | |
849 | int i; | |
850 | ||
851 | @@ -420,20 +566,18 @@ | |
852 | while (pvc) { | |
853 | if (pvc->state.new) { | |
854 | pvc->state.new = 0; | |
855 | - pvc->state.active = 1; | |
856 | - fr_log_dlci_active(pvc); | |
857 | ||
858 | /* Tell DTE that new PVC is now active */ | |
859 | - hdlc->state.fr.changed = 1; | |
860 | + hdlc->state.fr.dce_changed = 1; | |
861 | } | |
862 | pvc = pvc->next; | |
863 | } | |
864 | } | |
865 | ||
866 | - if (hdlc->state.fr.changed) { | |
867 | + if (hdlc->state.fr.dce_changed) { | |
868 | reptype = LMI_FULLREP; | |
869 | hdlc->state.fr.fullrep_sent = 1; | |
870 | - hdlc->state.fr.changed = 0; | |
871 | + hdlc->state.fr.dce_changed = 0; | |
872 | } | |
873 | ||
874 | fr_lmi_send(hdlc, reptype == LMI_FULLREP ? 1 : 0); | |
875 | @@ -449,13 +593,14 @@ | |
876 | pvc = hdlc->state.fr.first_pvc; | |
877 | ||
878 | while (pvc) { | |
879 | - pvc->state.deleted = pvc->state.active; /* mark active PVCs */ | |
880 | + pvc->state.deleted = 1; | |
881 | pvc = pvc->next; | |
882 | } | |
883 | ||
884 | + no_ram = 0; | |
885 | while (skb->len >= i + 2 + stat_len) { | |
886 | u16 dlci; | |
887 | - int active, new; | |
888 | + unsigned int active, new; | |
889 | ||
890 | if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT) | |
891 | ? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) { | |
892 | @@ -472,21 +617,28 @@ | |
893 | } | |
894 | i++; | |
895 | ||
896 | - dlci = status_to_dlci(hdlc, skb->data + i, &active, &new); | |
897 | - pvc = find_pvc(hdlc, dlci); | |
898 | + dlci = status_to_dlci(skb->data + i, &active, &new); | |
899 | + | |
900 | + pvc = add_pvc(hdlc, dlci); | |
901 | + | |
902 | + if (!pvc && !no_ram) { | |
903 | + printk(KERN_WARNING | |
904 | + "%s: Memory squeeze on fr_lmi_recv()\n", | |
905 | + hdlc_to_name(hdlc)); | |
906 | + no_ram = 1; | |
907 | + } | |
908 | ||
909 | - active |= new; | |
910 | if (pvc) { | |
911 | - if (active && !pvc->state.active && | |
912 | - (pvc->netdev.flags & IFF_UP)) { | |
913 | + pvc->state.exist = 1; | |
914 | + pvc->state.deleted = 0; | |
915 | + if (active != pvc->state.active || | |
916 | + new != pvc->state.new || | |
917 | + !pvc->state.exist) { | |
918 | + pvc->state.new = new; | |
919 | pvc->state.active = active; | |
920 | fr_log_dlci_active(pvc); | |
921 | } | |
922 | - pvc->state.deleted = 0; | |
923 | } | |
924 | - else if (new) | |
925 | - printk(KERN_INFO "%s: new PVC available, DLCI=%u\n", | |
926 | - hdlc_to_name(hdlc), dlci); | |
927 | ||
928 | i += stat_len; | |
929 | } | |
930 | @@ -494,10 +646,10 @@ | |
931 | pvc = hdlc->state.fr.first_pvc; | |
932 | ||
933 | while (pvc) { | |
934 | - if (pvc->state.deleted) { | |
935 | + if (pvc->state.deleted && pvc->state.exist) { | |
936 | pvc->state.active = pvc->state.new = 0; | |
937 | + pvc->state.exist = 0; | |
938 | fr_log_dlci_active(pvc); | |
939 | - pvc->state.deleted = 0; | |
940 | } | |
941 | pvc = pvc->next; | |
942 | } | |
943 | @@ -517,8 +669,9 @@ | |
944 | u8 *data = skb->data; | |
945 | u16 dlci; | |
946 | pvc_device *pvc; | |
947 | + struct net_device *dev = NULL; | |
948 | ||
949 | - if (skb->len<4 || fh->ea1 || data[2] != FR_UI) | |
950 | + if (skb->len <= 4 || fh->ea1 || data[2] != FR_UI) | |
951 | goto rx_error; | |
952 | ||
953 | dlci = q922_to_dlci(skb->data); | |
954 | @@ -550,57 +703,39 @@ | |
955 | printk(KERN_INFO "%s: No PVC for received frame's DLCI %d\n", | |
956 | hdlc_to_name(hdlc), dlci); | |
957 | #endif | |
958 | - goto rx_error; | |
959 | - } | |
960 | - | |
961 | - if ((pvc->netdev.flags & IFF_UP) == 0) { | |
962 | -#ifdef CONFIG_HDLC_DEBUG_PKT | |
963 | - printk(KERN_INFO "%s: PVC for received frame's DLCI %d is down\n", | |
964 | - hdlc_to_name(hdlc), dlci); | |
965 | -#endif | |
966 | - goto rx_error; | |
967 | + dev_kfree_skb_any(skb); | |
968 | + return; | |
969 | } | |
970 | ||
971 | - pvc->stats.rx_packets++; /* PVC traffic */ | |
972 | - pvc->stats.rx_bytes += skb->len; | |
973 | - | |
974 | - if (pvc->state.fecn != (fh->fecn ? PVC_STATE_FECN : 0)) { | |
975 | + if (pvc->state.fecn != fh->fecn) { | |
976 | #ifdef CONFIG_HDLC_DEBUG_ECN | |
977 | - printk(KERN_DEBUG "%s: FECN O%s\n", pvc_to_name(pvc), | |
978 | - fh->fecn ? "N" : "FF"); | |
979 | + printk(KERN_DEBUG "%s: DLCI %d FECN O%s\n", hdlc_to_name(pvc), | |
980 | + dlci, fh->fecn ? "N" : "FF"); | |
981 | #endif | |
982 | pvc->state.fecn ^= 1; | |
983 | } | |
984 | ||
985 | - if (pvc->state.becn != (fh->becn ? PVC_STATE_BECN : 0)) { | |
986 | + if (pvc->state.becn != fh->becn) { | |
987 | #ifdef CONFIG_HDLC_DEBUG_ECN | |
988 | - printk(KERN_DEBUG "%s: BECN O%s\n", pvc_to_name(pvc), | |
989 | - fh->becn ? "N" : "FF"); | |
990 | + printk(KERN_DEBUG "%s: DLCI %d BECN O%s\n", hdlc_to_name(pvc), | |
991 | + dlci, fh->becn ? "N" : "FF"); | |
992 | #endif | |
993 | pvc->state.becn ^= 1; | |
994 | } | |
995 | ||
996 | - if (pvc->state.becn) | |
997 | - pvc->stats.rx_compressed++; | |
998 | - | |
999 | - skb->dev = &pvc->netdev; | |
1000 | ||
1001 | if (data[3] == NLPID_IP) { | |
1002 | skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ | |
1003 | + dev = pvc->main; | |
1004 | skb->protocol = htons(ETH_P_IP); | |
1005 | - netif_rx(skb); | |
1006 | - return; | |
1007 | - } | |
1008 | - | |
1009 | ||
1010 | - if (data[3] == NLPID_IPV6) { | |
1011 | + } else if (data[3] == NLPID_IPV6) { | |
1012 | skb_pull(skb, 4); /* Remove 4-byte header (hdr, UI, NLPID) */ | |
1013 | + dev = pvc->main; | |
1014 | skb->protocol = htons(ETH_P_IPV6); | |
1015 | - netif_rx(skb); | |
1016 | - return; | |
1017 | - } | |
1018 | ||
1019 | - if (data[3] == FR_PAD && data[4] == NLPID_SNAP && data[5] == FR_PAD) { | |
1020 | + } else if (skb->len > 10 && data[3] == FR_PAD && | |
1021 | + data[4] == NLPID_SNAP && data[5] == FR_PAD) { | |
1022 | u16 oui = ntohs(*(u16*)(data + 6)); | |
1023 | u16 pid = ntohs(*(u16*)(data + 8)); | |
1024 | skb_pull(skb, 10); | |
1025 | @@ -610,23 +745,39 @@ | |
1026 | case ETH_P_IPX: | |
1027 | case ETH_P_IP: /* a long variant */ | |
1028 | case ETH_P_IPV6: | |
1029 | + dev = pvc->main; | |
1030 | skb->protocol = htons(pid); | |
1031 | break; | |
1032 | ||
1033 | + case 0x80C20007: /* bridged Ethernet frame */ | |
1034 | + if ((dev = pvc->ether) != NULL) | |
1035 | + skb->protocol = eth_type_trans(skb, dev); | |
1036 | + break; | |
1037 | + | |
1038 | default: | |
1039 | printk(KERN_INFO "%s: Unsupported protocol, OUI=%x " | |
1040 | "PID=%x\n", hdlc_to_name(hdlc), oui, pid); | |
1041 | dev_kfree_skb_any(skb); | |
1042 | return; | |
1043 | } | |
1044 | - | |
1045 | - netif_rx(skb); | |
1046 | + } else { | |
1047 | + printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x " | |
1048 | + "length = %i\n", hdlc_to_name(hdlc), data[3], skb->len); | |
1049 | + dev_kfree_skb_any(skb); | |
1050 | return; | |
1051 | } | |
1052 | ||
1053 | - printk(KERN_INFO "%s: Unsupported protocol, NLPID=%x\n", | |
1054 | - hdlc_to_name(hdlc), data[3]); | |
1055 | - dev_kfree_skb_any(skb); | |
1056 | + if (dev) { | |
1057 | + struct net_device_stats *stats = pvc_get_stats(dev); | |
1058 | + stats->rx_packets++; /* PVC traffic */ | |
1059 | + stats->rx_bytes += skb->len; | |
1060 | + if (pvc->state.becn) | |
1061 | + stats->rx_compressed++; | |
1062 | + skb->dev = dev; | |
1063 | + netif_rx(skb); | |
1064 | + } else | |
1065 | + dev_kfree_skb_any(skb); | |
1066 | + | |
1067 | return; | |
1068 | ||
1069 | rx_error: | |
1070 | @@ -641,7 +792,7 @@ | |
1071 | if (hdlc->state.fr.settings.lmi != LMI_NONE) { | |
1072 | hdlc->state.fr.last_poll = 0; | |
1073 | hdlc->state.fr.reliable = 0; | |
1074 | - hdlc->state.fr.changed = 1; | |
1075 | + hdlc->state.fr.dce_changed = 1; | |
1076 | hdlc->state.fr.request = 0; | |
1077 | hdlc->state.fr.fullrep_sent = 0; | |
1078 | hdlc->state.fr.last_errors = 0xFFFFFFFF; | |
1079 | @@ -669,90 +820,119 @@ | |
1080 | if (hdlc->state.fr.settings.lmi != LMI_NONE) | |
1081 | del_timer_sync(&hdlc->state.fr.timer); | |
1082 | ||
1083 | - while(pvc) { | |
1084 | - dev_close(&pvc->netdev); /* Shutdown all PVCs for this FRAD */ | |
1085 | + while(pvc) { /* Shutdown all PVCs for this FRAD */ | |
1086 | + if (pvc->main) | |
1087 | + dev_close(pvc->main); | |
1088 | + if (pvc->ether) | |
1089 | + dev_close(pvc->ether); | |
1090 | + pvc->state.active = pvc->state.new = pvc->state.fecn = | |
1091 | + pvc->state.becn = 0; | |
1092 | + pvc->state.exist = 0; | |
1093 | pvc = pvc->next; | |
1094 | } | |
1095 | } | |
1096 | ||
1097 | ||
1098 | - | |
1099 | -static int fr_pvc(hdlc_device *hdlc, unsigned int dlci, int create) | |
1100 | +static int fr_add_pvc(hdlc_device *hdlc, unsigned int dlci, int type) | |
1101 | { | |
1102 | - pvc_device **pvc_p = &hdlc->state.fr.first_pvc; | |
1103 | - pvc_device *pvc; | |
1104 | - int result; | |
1105 | + pvc_device *pvc = NULL; | |
1106 | + struct net_device *dev; | |
1107 | + int result, used; | |
1108 | + char * prefix = "pvc%d"; | |
1109 | ||
1110 | - if(dlci <= 0 || dlci >= 1024) | |
1111 | - return -EINVAL; /* Only 10 bits for DLCI, DLCI 0 reserved */ | |
1112 | + if (type == ARPHRD_ETHER) | |
1113 | + prefix = "pvceth%d"; | |
1114 | ||
1115 | - while(*pvc_p) { | |
1116 | - if (netdev_dlci(&(*pvc_p)->netdev) == dlci) | |
1117 | - break; | |
1118 | - pvc_p = &(*pvc_p)->next; | |
1119 | + if ((pvc = add_pvc(hdlc, dlci)) == NULL) { | |
1120 | + printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", | |
1121 | + hdlc_to_name(hdlc)); | |
1122 | + return -ENOBUFS; | |
1123 | } | |
1124 | ||
1125 | - if (create) { /* Create PVC */ | |
1126 | - if (*pvc_p != NULL) | |
1127 | - return -EEXIST; | |
1128 | - | |
1129 | - pvc = *pvc_p = kmalloc(sizeof(pvc_device), GFP_KERNEL); | |
1130 | - if (!pvc) { | |
1131 | - printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", | |
1132 | - hdlc_to_name(hdlc)); | |
1133 | - return -ENOBUFS; | |
1134 | - } | |
1135 | - memset(pvc, 0, sizeof(pvc_device)); | |
1136 | + if (*get_dev_p(pvc, type)) | |
1137 | + return -EEXIST; | |
1138 | ||
1139 | - pvc->netdev.hard_start_xmit = pvc_xmit; | |
1140 | - pvc->netdev.get_stats = pvc_get_stats; | |
1141 | - pvc->netdev.open = pvc_open; | |
1142 | - pvc->netdev.stop = pvc_close; | |
1143 | - pvc->netdev.change_mtu = pvc_change_mtu; | |
1144 | - pvc->netdev.mtu = HDLC_MAX_MTU; | |
1145 | - | |
1146 | - pvc->netdev.type = ARPHRD_DLCI; | |
1147 | - pvc->netdev.hard_header_len = 16; | |
1148 | - pvc->netdev.hard_header = fr_hard_header; | |
1149 | - pvc->netdev.tx_queue_len = 0; | |
1150 | - pvc->netdev.flags = IFF_POINTOPOINT; | |
1151 | - | |
1152 | - pvc->master = hdlc; | |
1153 | - *(u16*)pvc->netdev.dev_addr = htons(dlci); | |
1154 | - dlci_to_q922(pvc->netdev.broadcast, dlci); | |
1155 | - pvc->netdev.addr_len = 2; | |
1156 | + used = pvc_is_used(pvc); | |
1157 | ||
1158 | - result = dev_alloc_name(&pvc->netdev, "pvc%d"); | |
1159 | - if (result < 0) { | |
1160 | - kfree(pvc); | |
1161 | - *pvc_p = NULL; | |
1162 | - return result; | |
1163 | - } | |
1164 | - | |
1165 | - if (register_netdevice(&pvc->netdev) != 0) { | |
1166 | - kfree(pvc); | |
1167 | - *pvc_p = NULL; | |
1168 | - return -EIO; | |
1169 | - } | |
1170 | + dev = kmalloc(sizeof(struct net_device) + | |
1171 | + sizeof(struct net_device_stats), GFP_KERNEL); | |
1172 | + if (!dev) { | |
1173 | + printk(KERN_WARNING "%s: Memory squeeze on fr_pvc()\n", | |
1174 | + hdlc_to_name(hdlc)); | |
1175 | + delete_unused_pvcs(hdlc); | |
1176 | + return -ENOBUFS; | |
1177 | + } | |
1178 | + memset(dev, 0, sizeof(struct net_device) + | |
1179 | + sizeof(struct net_device_stats)); | |
1180 | ||
1181 | - hdlc->state.fr.changed = 1; | |
1182 | - hdlc->state.fr.pvc_count++; | |
1183 | - return 0; | |
1184 | + if (type == ARPHRD_ETHER) { | |
1185 | + ether_setup(dev); | |
1186 | + memcpy(dev->dev_addr, "\x00\x01", 2); | |
1187 | + get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); | |
1188 | + } else { | |
1189 | + dev->type = ARPHRD_DLCI; | |
1190 | + dev->flags = IFF_POINTOPOINT; | |
1191 | + dev->hard_header_len = 10; | |
1192 | + dev->addr_len = 2; | |
1193 | + *(u16*)dev->dev_addr = htons(dlci); | |
1194 | + dlci_to_q922(dev->broadcast, dlci); | |
1195 | + } | |
1196 | + dev->hard_start_xmit = pvc_xmit; | |
1197 | + dev->get_stats = pvc_get_stats; | |
1198 | + dev->open = pvc_open; | |
1199 | + dev->stop = pvc_close; | |
1200 | + dev->do_ioctl = pvc_ioctl; | |
1201 | + dev->change_mtu = pvc_change_mtu; | |
1202 | + dev->mtu = HDLC_MAX_MTU; | |
1203 | + dev->tx_queue_len = 0; | |
1204 | + dev->priv = pvc; | |
1205 | + | |
1206 | + result = dev_alloc_name(dev, prefix); | |
1207 | + if (result < 0) { | |
1208 | + kfree(dev); | |
1209 | + delete_unused_pvcs(hdlc); | |
1210 | + return result; | |
1211 | + } | |
1212 | + | |
1213 | + if (register_netdevice(dev) != 0) { | |
1214 | + kfree(dev); | |
1215 | + delete_unused_pvcs(hdlc); | |
1216 | + return -EIO; | |
1217 | + } | |
1218 | + | |
1219 | + *get_dev_p(pvc, type) = dev; | |
1220 | + if (!used) { | |
1221 | + hdlc->state.fr.dce_changed = 1; | |
1222 | + hdlc->state.fr.dce_pvc_count++; | |
1223 | } | |
1224 | + return 0; | |
1225 | +} | |
1226 | + | |
1227 | + | |
1228 | ||
1229 | - if (*pvc_p == NULL) /* Delete PVC */ | |
1230 | +static int fr_del_pvc(hdlc_device *hdlc, unsigned int dlci, int type) | |
1231 | +{ | |
1232 | + pvc_device *pvc; | |
1233 | + struct net_device *dev; | |
1234 | + | |
1235 | + if ((pvc = find_pvc(hdlc, dlci)) == NULL) | |
1236 | return -ENOENT; | |
1237 | ||
1238 | - pvc = *pvc_p; | |
1239 | + if ((dev = *get_dev_p(pvc, type)) == NULL) | |
1240 | + return -ENOENT; | |
1241 | ||
1242 | - if (pvc->netdev.flags & IFF_UP) | |
1243 | + if (dev->flags & IFF_UP) | |
1244 | return -EBUSY; /* PVC in use */ | |
1245 | ||
1246 | - hdlc->state.fr.changed = 1; | |
1247 | - hdlc->state.fr.pvc_count--; | |
1248 | - *pvc_p = pvc->next; | |
1249 | - unregister_netdevice(&pvc->netdev); | |
1250 | - kfree(pvc); | |
1251 | + unregister_netdevice(dev); | |
1252 | + kfree(dev); | |
1253 | + *get_dev_p(pvc, type) = NULL; | |
1254 | + | |
1255 | + if (!pvc_is_used(pvc)) { | |
1256 | + hdlc->state.fr.dce_pvc_count--; | |
1257 | + hdlc->state.fr.dce_changed = 1; | |
1258 | + } | |
1259 | + delete_unused_pvcs(hdlc); | |
1260 | return 0; | |
1261 | } | |
1262 | ||
1263 | @@ -763,14 +943,21 @@ | |
1264 | pvc_device *pvc = hdlc->state.fr.first_pvc; | |
1265 | while(pvc) { | |
1266 | pvc_device *next = pvc->next; | |
1267 | - unregister_netdev(&pvc->netdev); | |
1268 | + if (pvc->main) { | |
1269 | + unregister_netdevice(pvc->main); | |
1270 | + kfree(pvc->main); | |
1271 | + } | |
1272 | + if (pvc->ether) { | |
1273 | + unregister_netdevice(pvc->ether); | |
1274 | + kfree(pvc->ether); | |
1275 | + } | |
1276 | kfree(pvc); | |
1277 | pvc = next; | |
1278 | } | |
1279 | ||
1280 | hdlc->state.fr.first_pvc = NULL; /* All PVCs destroyed */ | |
1281 | - hdlc->state.fr.pvc_count = 0; | |
1282 | - hdlc->state.fr.changed = 1; | |
1283 | + hdlc->state.fr.dce_pvc_count = 0; | |
1284 | + hdlc->state.fr.dce_changed = 1; | |
1285 | } | |
1286 | ||
1287 | ||
1288 | @@ -828,25 +1015,27 @@ | |
1289 | if (hdlc->proto != IF_PROTO_FR) { | |
1290 | hdlc_proto_detach(hdlc); | |
1291 | hdlc->state.fr.first_pvc = NULL; | |
1292 | - hdlc->state.fr.pvc_count = 0; | |
1293 | + hdlc->state.fr.dce_pvc_count = 0; | |
1294 | } | |
1295 | memcpy(&hdlc->state.fr.settings, &new_settings, size); | |
1296 | ||
1297 | hdlc->open = fr_open; | |
1298 | hdlc->stop = fr_close; | |
1299 | hdlc->netif_rx = fr_rx; | |
1300 | + hdlc->type_trans = NULL; | |
1301 | hdlc->proto_detach = fr_destroy; | |
1302 | hdlc->proto = IF_PROTO_FR; | |
1303 | dev->hard_start_xmit = hdlc->xmit; | |
1304 | - dev->hard_header = fr_hard_header; | |
1305 | + dev->hard_header = NULL; | |
1306 | dev->type = ARPHRD_FRAD; | |
1307 | - dev->addr_len = 2; | |
1308 | - *(u16*)dev->dev_addr = htons(LMI_DLCI); | |
1309 | - dlci_to_q922(dev->broadcast, LMI_DLCI); | |
1310 | + dev->flags = IFF_POINTOPOINT | IFF_NOARP; | |
1311 | + dev->addr_len = 0; | |
1312 | return 0; | |
1313 | ||
1314 | case IF_PROTO_FR_ADD_PVC: | |
1315 | case IF_PROTO_FR_DEL_PVC: | |
1316 | + case IF_PROTO_FR_ADD_ETH_PVC: | |
1317 | + case IF_PROTO_FR_DEL_ETH_PVC: | |
1318 | if(!capable(CAP_NET_ADMIN)) | |
1319 | return -EPERM; | |
1320 | ||
1321 | @@ -854,8 +1043,20 @@ | |
1322 | sizeof(fr_proto_pvc))) | |
1323 | return -EFAULT; | |
1324 | ||
1325 | - return fr_pvc(hdlc, pvc.dlci, | |
1326 | - ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC); | |
1327 | + if (pvc.dlci <= 0 || pvc.dlci >= 1024) | |
1328 | + return -EINVAL; /* Only 10 bits, DLCI 0 reserved */ | |
1329 | + | |
1330 | + if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC || | |
1331 | + ifr->ifr_settings.type == IF_PROTO_FR_DEL_ETH_PVC) | |
1332 | + result = ARPHRD_ETHER; /* bridged Ethernet device */ | |
1333 | + else | |
1334 | + result = ARPHRD_DLCI; | |
1335 | + | |
1336 | + if (ifr->ifr_settings.type == IF_PROTO_FR_ADD_PVC || | |
1337 | + ifr->ifr_settings.type == IF_PROTO_FR_ADD_ETH_PVC) | |
1338 | + return fr_add_pvc(hdlc, pvc.dlci, result); | |
1339 | + else | |
1340 | + return fr_del_pvc(hdlc, pvc.dlci, result); | |
1341 | } | |
1342 | ||
1343 | return -EINVAL; | |
1344 | --- linux-2.4.orig/drivers/net/wan/hdlc_generic.c 2003-07-29 23:25:03.000000000 +0200 | |
1345 | +++ linux-2.4/drivers/net/wan/hdlc_generic.c 2003-07-29 23:32:23.000000000 +0200 | |
1346 | @@ -1,17 +1,13 @@ | |
1347 | /* | |
1348 | * Generic HDLC support routines for Linux | |
1349 | * | |
1350 | - * Copyright (C) 1999 - 2001 Krzysztof Halasa <khc@pm.waw.pl> | |
1351 | + * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | |
1352 | * | |
1353 | * This program is free software; you can redistribute it and/or modify it | |
1354 | - * under the terms of the GNU General Public License as published by | |
1355 | - * the Free Software Foundation; either version 2 of the License, or | |
1356 | - * (at your option) any later version. | |
1357 | + * under the terms of version 2 of the GNU General Public License | |
1358 | + * as published by the Free Software Foundation. | |
1359 | * | |
1360 | - * Current status: | |
1361 | - * - this is work in progress | |
1362 | - * - not heavily tested on SMP | |
1363 | - * - currently supported: | |
1364 | + * Currently supported: | |
1365 | * * raw IP-in-HDLC | |
1366 | * * Cisco HDLC | |
1367 | * * Frame Relay with ANSI or CCITT LMI (both user and network side) | |
1368 | @@ -37,7 +33,7 @@ | |
1369 | #include <linux/hdlc.h> | |
1370 | ||
1371 | ||
1372 | -static const char* version = "HDLC support module revision 1.11"; | |
1373 | +static const char* version = "HDLC support module revision 1.14"; | |
1374 | ||
1375 | ||
1376 | static int hdlc_change_mtu(struct net_device *dev, int new_mtu) | |
1377 | @@ -60,7 +56,13 @@ | |
1378 | static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, | |
1379 | struct packet_type *p) | |
1380 | { | |
1381 | - dev_to_hdlc(dev)->netif_rx(skb); | |
1382 | + hdlc_device *hdlc = dev_to_hdlc(dev); | |
1383 | + if (hdlc->netif_rx) | |
1384 | + hdlc->netif_rx(skb); | |
1385 | + else { | |
1386 | + hdlc->stats.rx_dropped++; /* Shouldn't happen */ | |
1387 | + dev_kfree_skb(skb); | |
1388 | + } | |
1389 | return 0; | |
1390 | } | |
1391 | ||
1392 | @@ -69,6 +71,10 @@ | |
1393 | #define hdlc_raw_ioctl(hdlc, ifr) -ENOSYS | |
1394 | #endif | |
1395 | ||
1396 | +#ifndef CONFIG_HDLC_RAW_ETH | |
1397 | +#define hdlc_raw_eth_ioctl(hdlc, ifr) -ENOSYS | |
1398 | +#endif | |
1399 | + | |
1400 | #ifndef CONFIG_HDLC_PPP | |
1401 | #define hdlc_ppp_ioctl(hdlc, ifr) -ENOSYS | |
1402 | #endif | |
1403 | @@ -96,6 +102,7 @@ | |
1404 | ||
1405 | switch(ifr->ifr_settings.type) { | |
1406 | case IF_PROTO_HDLC: | |
1407 | + case IF_PROTO_HDLC_ETH: | |
1408 | case IF_PROTO_PPP: | |
1409 | case IF_PROTO_CISCO: | |
1410 | case IF_PROTO_FR: | |
1411 | @@ -109,6 +116,7 @@ | |
1412 | ||
1413 | switch(proto) { | |
1414 | case IF_PROTO_HDLC: return hdlc_raw_ioctl(hdlc, ifr); | |
1415 | + case IF_PROTO_HDLC_ETH: return hdlc_raw_eth_ioctl(hdlc, ifr); | |
1416 | case IF_PROTO_PPP: return hdlc_ppp_ioctl(hdlc, ifr); | |
1417 | case IF_PROTO_CISCO: return hdlc_cisco_ioctl(hdlc, ifr); | |
1418 | case IF_PROTO_FR: return hdlc_fr_ioctl(hdlc, ifr); | |
1419 | @@ -152,9 +160,10 @@ | |
1420 | ||
1421 | void unregister_hdlc_device(hdlc_device *hdlc) | |
1422 | { | |
1423 | + rtnl_lock(); | |
1424 | hdlc_proto_detach(hdlc); | |
1425 | - | |
1426 | - unregister_netdev(hdlc_to_dev(hdlc)); | |
1427 | + unregister_netdevice(hdlc_to_dev(hdlc)); | |
1428 | + rtnl_unlock(); | |
1429 | MOD_DEC_USE_COUNT; | |
1430 | } | |
1431 | ||
1432 | @@ -162,7 +171,7 @@ | |
1433 | ||
1434 | MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); | |
1435 | MODULE_DESCRIPTION("HDLC support module"); | |
1436 | -MODULE_LICENSE("GPL"); | |
1437 | +MODULE_LICENSE("GPL v2"); | |
1438 | ||
1439 | EXPORT_SYMBOL(hdlc_ioctl); | |
1440 | EXPORT_SYMBOL(register_hdlc_device); | |
1441 | --- linux-2.4.orig/drivers/net/wan/hdlc_ppp.c 2003-07-29 23:25:03.000000000 +0200 | |
1442 | +++ linux-2.4/drivers/net/wan/hdlc_ppp.c 2003-07-29 23:32:23.000000000 +0200 | |
1443 | @@ -2,12 +2,11 @@ | |
1444 | * Generic HDLC support routines for Linux | |
1445 | * Point-to-point protocol support | |
1446 | * | |
1447 | - * Copyright (C) 1999 - 2001 Krzysztof Halasa <khc@pm.waw.pl> | |
1448 | + * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | |
1449 | * | |
1450 | * This program is free software; you can redistribute it and/or modify it | |
1451 | - * under the terms of the GNU General Public License as published by | |
1452 | - * the Free Software Foundation; either version 2 of the License, or | |
1453 | - * (at your option) any later version. | |
1454 | + * under the terms of version 2 of the GNU General Public License | |
1455 | + * as published by the Free Software Foundation. | |
1456 | */ | |
1457 | ||
1458 | #include <linux/config.h> | |
1459 | @@ -68,10 +67,10 @@ | |
1460 | ||
1461 | ||
1462 | ||
1463 | -static void ppp_rx(struct sk_buff *skb) | |
1464 | +static unsigned short ppp_type_trans(struct sk_buff *skb, | |
1465 | + struct net_device *dev) | |
1466 | { | |
1467 | - skb->protocol = htons(ETH_P_WAN_PPP); | |
1468 | - netif_rx(skb); | |
1469 | + return __constant_htons(ETH_P_WAN_PPP); | |
1470 | } | |
1471 | ||
1472 | ||
1473 | @@ -103,7 +102,8 @@ | |
1474 | ||
1475 | hdlc->open = ppp_open; | |
1476 | hdlc->stop = ppp_close; | |
1477 | - hdlc->netif_rx = ppp_rx; | |
1478 | + hdlc->netif_rx = NULL; | |
1479 | + hdlc->type_trans = ppp_type_trans; | |
1480 | hdlc->proto = IF_PROTO_PPP; | |
1481 | dev->hard_start_xmit = hdlc->xmit; | |
1482 | dev->hard_header = NULL; | |
1483 | --- linux-2.4.orig/drivers/net/wan/hdlc_x25.c 2003-07-29 23:25:03.000000000 +0200 | |
1484 | +++ linux-2.4/drivers/net/wan/hdlc_x25.c 2003-07-29 23:32:23.000000000 +0200 | |
1485 | @@ -2,12 +2,11 @@ | |
1486 | * Generic HDLC support routines for Linux | |
1487 | * X.25 support | |
1488 | * | |
1489 | - * Copyright (C) 1999 - 2001 Krzysztof Halasa <khc@pm.waw.pl> | |
1490 | + * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | |
1491 | * | |
1492 | * This program is free software; you can redistribute it and/or modify it | |
1493 | - * under the terms of the GNU General Public License as published by | |
1494 | - * the Free Software Foundation; either version 2 of the License, or | |
1495 | - * (at your option) any later version. | |
1496 | + * under the terms of version 2 of the GNU General Public License | |
1497 | + * as published by the Free Software Foundation. | |
1498 | */ | |
1499 | ||
1500 | #include <linux/config.h> | |
1501 | @@ -204,6 +203,7 @@ | |
1502 | hdlc->open = x25_open; | |
1503 | hdlc->stop = x25_close; | |
1504 | hdlc->netif_rx = x25_rx; | |
1505 | + hdlc->type_trans = NULL; | |
1506 | hdlc->proto = IF_PROTO_X25; | |
1507 | dev->hard_start_xmit = x25_xmit; | |
1508 | dev->hard_header = NULL; | |
1509 | --- linux-2.4.orig/drivers/net/wan/hdlc_raw.c 2003-07-29 23:25:03.000000000 +0200 | |
1510 | +++ linux-2.4/drivers/net/wan/hdlc_raw.c 2003-07-29 23:32:23.000000000 +0200 | |
1511 | @@ -2,12 +2,11 @@ | |
1512 | * Generic HDLC support routines for Linux | |
1513 | * HDLC support | |
1514 | * | |
1515 | - * Copyright (C) 1999 - 2001 Krzysztof Halasa <khc@pm.waw.pl> | |
1516 | + * Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl> | |
1517 | * | |
1518 | * This program is free software; you can redistribute it and/or modify it | |
1519 | - * under the terms of the GNU General Public License as published by | |
1520 | - * the Free Software Foundation; either version 2 of the License, or | |
1521 | - * (at your option) any later version. | |
1522 | + * under the terms of version 2 of the GNU General Public License | |
1523 | + * as published by the Free Software Foundation. | |
1524 | */ | |
1525 | ||
1526 | #include <linux/config.h> | |
1527 | @@ -26,10 +25,10 @@ | |
1528 | #include <linux/hdlc.h> | |
1529 | ||
1530 | ||
1531 | -static void raw_rx(struct sk_buff *skb) | |
1532 | +static unsigned short raw_type_trans(struct sk_buff *skb, | |
1533 | + struct net_device *dev) | |
1534 | { | |
1535 | - skb->protocol = htons(ETH_P_IP); | |
1536 | - netif_rx(skb); | |
1537 | + return __constant_htons(ETH_P_IP); | |
1538 | } | |
1539 | ||
1540 | ||
1541 | @@ -67,7 +66,7 @@ | |
1542 | new_settings.encoding = ENCODING_NRZ; | |
1543 | ||
1544 | if (new_settings.parity == PARITY_DEFAULT) | |
1545 | - new_settings.parity = PARITY_NONE; | |
1546 | + new_settings.parity = PARITY_CRC16_PR1_CCITT; | |
1547 | ||
1548 | result = hdlc->attach(hdlc, new_settings.encoding, | |
1549 | new_settings.parity); | |
1550 | @@ -79,11 +78,13 @@ | |
1551 | ||
1552 | hdlc->open = NULL; | |
1553 | hdlc->stop = NULL; | |
1554 | - hdlc->netif_rx = raw_rx; | |
1555 | + hdlc->netif_rx = NULL; | |
1556 | + hdlc->type_trans = raw_type_trans; | |
1557 | hdlc->proto = IF_PROTO_HDLC; | |
1558 | dev->hard_start_xmit = hdlc->xmit; | |
1559 | dev->hard_header = NULL; | |
1560 | dev->type = ARPHRD_RAWHDLC; | |
1561 | + dev->flags = IFF_POINTOPOINT | IFF_NOARP; | |
1562 | dev->addr_len = 0; | |
1563 | return 0; | |
1564 | } | |
1565 | --- linux-2.4.orig/drivers/net/wan/hdlc_raw_eth.c 2003-07-29 23:34:24.000000000 +0200 | |
1566 | +++ linux-2.4/drivers/net/wan/hdlc_raw_eth.c 2003-07-29 23:32:23.000000000 +0200 | |
1567 | @@ -0,0 +1,110 @@ | |
1568 | +/* | |
1569 | + * Generic HDLC support routines for Linux | |
1570 | + * HDLC Ethernet emulation support | |
1571 | + * | |
1572 | + * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl> | |
1573 | + * | |
1574 | + * This program is free software; you can redistribute it and/or modify it | |
1575 | + * under the terms of version 2 of the GNU General Public License | |
1576 | + * as published by the Free Software Foundation. | |
1577 | + */ | |
1578 | + | |
1579 | +#include <linux/config.h> | |
1580 | +#include <linux/module.h> | |
1581 | +#include <linux/kernel.h> | |
1582 | +#include <linux/slab.h> | |
1583 | +#include <linux/poll.h> | |
1584 | +#include <linux/errno.h> | |
1585 | +#include <linux/if_arp.h> | |
1586 | +#include <linux/init.h> | |
1587 | +#include <linux/skbuff.h> | |
1588 | +#include <linux/pkt_sched.h> | |
1589 | +#include <linux/random.h> | |
1590 | +#include <linux/inetdevice.h> | |
1591 | +#include <linux/lapb.h> | |
1592 | +#include <linux/rtnetlink.h> | |
1593 | +#include <linux/etherdevice.h> | |
1594 | +#include <linux/hdlc.h> | |
1595 | + | |
1596 | + | |
1597 | +static int eth_tx(struct sk_buff *skb, struct net_device *dev) | |
1598 | +{ | |
1599 | + int pad = ETH_ZLEN - skb->len; | |
1600 | + if (pad > 0) { /* Pad the frame with zeros */ | |
1601 | + int len = skb->len; | |
1602 | + if (skb_tailroom(skb) < pad) | |
1603 | + if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) { | |
1604 | + dev_to_hdlc(dev)->stats.tx_dropped++; | |
1605 | + dev_kfree_skb(skb); | |
1606 | + return 0; | |
1607 | + } | |
1608 | + skb_put(skb, pad); | |
1609 | + memset(skb->data + len, 0, pad); | |
1610 | + } | |
1611 | + return dev_to_hdlc(dev)->xmit(skb, dev); | |
1612 | +} | |
1613 | + | |
1614 | + | |
1615 | +int hdlc_raw_eth_ioctl(hdlc_device *hdlc, struct ifreq *ifr) | |
1616 | +{ | |
1617 | + raw_hdlc_proto *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc; | |
1618 | + const size_t size = sizeof(raw_hdlc_proto); | |
1619 | + raw_hdlc_proto new_settings; | |
1620 | + struct net_device *dev = hdlc_to_dev(hdlc); | |
1621 | + int result; | |
1622 | + void *old_ch_mtu; | |
1623 | + int old_qlen; | |
1624 | + | |
1625 | + switch (ifr->ifr_settings.type) { | |
1626 | + case IF_GET_PROTO: | |
1627 | + ifr->ifr_settings.type = IF_PROTO_HDLC_ETH; | |
1628 | + if (ifr->ifr_settings.size < size) { | |
1629 | + ifr->ifr_settings.size = size; /* data size wanted */ | |
1630 | + return -ENOBUFS; | |
1631 | + } | |
1632 | + if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) | |
1633 | + return -EFAULT; | |
1634 | + return 0; | |
1635 | + | |
1636 | + case IF_PROTO_HDLC_ETH: | |
1637 | + if (!capable(CAP_NET_ADMIN)) | |
1638 | + return -EPERM; | |
1639 | + | |
1640 | + if (dev->flags & IFF_UP) | |
1641 | + return -EBUSY; | |
1642 | + | |
1643 | + if (copy_from_user(&new_settings, raw_s, size)) | |
1644 | + return -EFAULT; | |
1645 | + | |
1646 | + if (new_settings.encoding == ENCODING_DEFAULT) | |
1647 | + new_settings.encoding = ENCODING_NRZ; | |
1648 | + | |
1649 | + if (new_settings.parity == PARITY_DEFAULT) | |
1650 | + new_settings.parity = PARITY_CRC16_PR1_CCITT; | |
1651 | + | |
1652 | + result = hdlc->attach(hdlc, new_settings.encoding, | |
1653 | + new_settings.parity); | |
1654 | + if (result) | |
1655 | + return result; | |
1656 | + | |
1657 | + hdlc_proto_detach(hdlc); | |
1658 | + memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size); | |
1659 | + | |
1660 | + hdlc->open = NULL; | |
1661 | + hdlc->stop = NULL; | |
1662 | + hdlc->netif_rx = NULL; | |
1663 | + hdlc->type_trans = eth_type_trans; | |
1664 | + hdlc->proto = IF_PROTO_HDLC_ETH; | |
1665 | + dev->hard_start_xmit = eth_tx; | |
1666 | + old_ch_mtu = dev->change_mtu; | |
1667 | + old_qlen = dev->tx_queue_len; | |
1668 | + ether_setup(dev); | |
1669 | + dev->change_mtu = old_ch_mtu; | |
1670 | + dev->tx_queue_len = old_qlen; | |
1671 | + memcpy(dev->dev_addr, "\x00\x01", 2); | |
1672 | + get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2); | |
1673 | + return 0; | |
1674 | + } | |
1675 | + | |
1676 | + return -EINVAL; | |
1677 | +} | |
1678 | --- linux-2.4.orig/drivers/net/wan/hd6457x.c 2003-07-29 23:25:03.000000000 +0200 | |
1679 | +++ linux-2.4/drivers/net/wan/hd6457x.c 2003-07-29 23:32:44.000000000 +0200 | |
1680 | @@ -1,16 +1,29 @@ | |
1681 | /* | |
1682 | * Hitachi SCA HD64570 and HD64572 common driver for Linux | |
1683 | * | |
1684 | - * Copyright (C) 1998-2000 Krzysztof Halasa <khc@pm.waw.pl> | |
1685 | + * Copyright (C) 1998-2003 Krzysztof Halasa <khc@pm.waw.pl> | |
1686 | * | |
1687 | * This program is free software; you can redistribute it and/or modify it | |
1688 | - * under the terms of the GNU General Public License as published by | |
1689 | - * the Free Software Foundation; either version 2 of the License, or | |
1690 | - * (at your option) any later version. | |
1691 | + * under the terms of version 2 of the GNU General Public License | |
1692 | + * as published by the Free Software Foundation. | |
1693 | * | |
1694 | * Sources of information: | |
1695 | * Hitachi HD64570 SCA User's Manual | |
1696 | * Hitachi HD64572 SCA-II User's Manual | |
1697 | + * | |
1698 | + * We use the following SCA memory map: | |
1699 | + * | |
1700 | + * Packet buffer descriptor rings - starting from winbase or win0base: | |
1701 | + * rx_ring_buffers * sizeof(pkt_desc) = logical channel #0 RX ring | |
1702 | + * tx_ring_buffers * sizeof(pkt_desc) = logical channel #0 TX ring | |
1703 | + * rx_ring_buffers * sizeof(pkt_desc) = logical channel #1 RX ring (if used) | |
1704 | + * tx_ring_buffers * sizeof(pkt_desc) = logical channel #1 TX ring (if used) | |
1705 | + * | |
1706 | + * Packet data buffers - starting from winbase + buff_offset: | |
1707 | + * rx_ring_buffers * HDLC_MAX_MRU = logical channel #0 RX buffers | |
1708 | + * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers | |
1709 | + * rx_ring_buffers * HDLC_MAX_MRU = logical channel #0 RX buffers (if used) | |
1710 | + * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers (if used) | |
1711 | */ | |
1712 | ||
1713 | #include <linux/module.h> | |
1714 | @@ -42,8 +55,6 @@ | |
1715 | #error Either hd64570.h or hd64572.h must be included | |
1716 | #endif | |
1717 | ||
1718 | -static char sca_version[]="1.09"; | |
1719 | - | |
1720 | #define get_msci(port) (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) | |
1721 | #define get_dmac_rx(port) (phy_node(port) ? DMAC1RX_OFFSET : DMAC0RX_OFFSET) | |
1722 | #define get_dmac_tx(port) (phy_node(port) ? DMAC1TX_OFFSET : DMAC0TX_OFFSET) | |
1723 | @@ -116,24 +127,35 @@ | |
1724 | ||
1725 | ||
1726 | ||
1727 | -static inline u8 next_desc(port_t *port, u8 desc) | |
1728 | +static inline u16 next_desc(port_t *port, u16 desc, int transmit) | |
1729 | +{ | |
1730 | + return (desc + 1) % (transmit ? port_to_card(port)->tx_ring_buffers | |
1731 | + : port_to_card(port)->rx_ring_buffers); | |
1732 | +} | |
1733 | + | |
1734 | + | |
1735 | + | |
1736 | +static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit) | |
1737 | { | |
1738 | - return (desc + 1) % port_to_card(port)->ring_buffers; | |
1739 | + u16 rx_buffs = port_to_card(port)->rx_ring_buffers; | |
1740 | + u16 tx_buffs = port_to_card(port)->tx_ring_buffers; | |
1741 | + | |
1742 | + desc %= (transmit ? tx_buffs : rx_buffs); // called with "X + 1" etc. | |
1743 | + return log_node(port) * (rx_buffs + tx_buffs) + | |
1744 | + transmit * rx_buffs + desc; | |
1745 | } | |
1746 | ||
1747 | ||
1748 | ||
1749 | -static inline u16 desc_offset(port_t *port, u8 desc, u8 transmit) | |
1750 | +static inline u16 desc_offset(port_t *port, u16 desc, int transmit) | |
1751 | { | |
1752 | /* Descriptor offset always fits in 16 bytes */ | |
1753 | - u8 buffs = port_to_card(port)->ring_buffers; | |
1754 | - return ((log_node(port) * 2 + transmit) * buffs + (desc % buffs)) * | |
1755 | - sizeof(pkt_desc); | |
1756 | + return desc_abs_number(port, desc, transmit) * sizeof(pkt_desc); | |
1757 | } | |
1758 | ||
1759 | ||
1760 | ||
1761 | -static inline pkt_desc* desc_address(port_t *port, u8 desc, u8 transmit) | |
1762 | +static inline pkt_desc* desc_address(port_t *port, u16 desc, int transmit) | |
1763 | { | |
1764 | #ifdef PAGE0_ALWAYS_MAPPED | |
1765 | return (pkt_desc*)(win0base(port_to_card(port)) | |
1766 | @@ -146,12 +168,10 @@ | |
1767 | ||
1768 | ||
1769 | ||
1770 | -static inline u32 buffer_offset(port_t *port, u8 desc, u8 transmit) | |
1771 | +static inline u32 buffer_offset(port_t *port, u16 desc, int transmit) | |
1772 | { | |
1773 | - u8 buffs = port_to_card(port)->ring_buffers; | |
1774 | return port_to_card(port)->buff_offset + | |
1775 | - ((log_node(port) * 2 + transmit) * buffs + (desc % buffs)) * | |
1776 | - (u32)HDLC_MAX_MRU; | |
1777 | + desc_abs_number(port, desc, transmit) * (u32)HDLC_MAX_MRU; | |
1778 | } | |
1779 | ||
1780 | ||
1781 | @@ -159,8 +179,7 @@ | |
1782 | static void sca_init_sync_port(port_t *port) | |
1783 | { | |
1784 | card_t *card = port_to_card(port); | |
1785 | - u8 transmit, i; | |
1786 | - u16 dmac, buffs = card->ring_buffers; | |
1787 | + int transmit, i; | |
1788 | ||
1789 | port->rxin = 0; | |
1790 | port->txin = 0; | |
1791 | @@ -171,6 +190,10 @@ | |
1792 | #endif | |
1793 | ||
1794 | for (transmit = 0; transmit < 2; transmit++) { | |
1795 | + u16 dmac = transmit ? get_dmac_tx(port) : get_dmac_rx(port); | |
1796 | + u16 buffs = transmit ? card->tx_ring_buffers | |
1797 | + : card->rx_ring_buffers; | |
1798 | + | |
1799 | for (i = 0; i < buffs; i++) { | |
1800 | pkt_desc* desc = desc_address(port, i, transmit); | |
1801 | u16 chain_off = desc_offset(port, i + 1, transmit); | |
1802 | @@ -182,7 +205,6 @@ | |
1803 | writeb(0, &desc->stat); | |
1804 | } | |
1805 | ||
1806 | - dmac = transmit ? get_dmac_tx(port) : get_dmac_rx(port); | |
1807 | /* DMA disable - to halt state */ | |
1808 | sca_out(0, transmit ? DSR_TX(phy_node(port)) : | |
1809 | DSR_RX(phy_node(port)), card); | |
1810 | @@ -247,7 +269,7 @@ | |
1811 | ||
1812 | ||
1813 | ||
1814 | -static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u8 rxin) | |
1815 | +static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin) | |
1816 | { | |
1817 | struct sk_buff *skb; | |
1818 | u16 len; | |
1819 | @@ -294,7 +316,7 @@ | |
1820 | skb->mac.raw = skb->data; | |
1821 | skb->dev = hdlc_to_dev(&port->hdlc); | |
1822 | skb->dev->last_rx = jiffies; | |
1823 | - skb->protocol = htons(ETH_P_HDLC); | |
1824 | + skb->protocol = hdlc_type_trans(skb, hdlc_to_dev(&port->hdlc)); | |
1825 | netif_rx(skb); | |
1826 | } | |
1827 | ||
1828 | @@ -341,7 +363,7 @@ | |
1829 | ||
1830 | /* Set new error descriptor address */ | |
1831 | sca_outa(desc_off, dmac + EDAL, card); | |
1832 | - port->rxin = next_desc(port, port->rxin); | |
1833 | + port->rxin = next_desc(port, port->rxin, 0); | |
1834 | } | |
1835 | ||
1836 | /* make sure RX DMA is enabled */ | |
1837 | @@ -377,8 +399,7 @@ | |
1838 | port->hdlc.stats.tx_packets++; | |
1839 | port->hdlc.stats.tx_bytes += readw(&desc->len); | |
1840 | writeb(0, &desc->stat); /* Free descriptor */ | |
1841 | - port->txlast = (port->txlast + 1) % | |
1842 | - port_to_card(port)->ring_buffers; | |
1843 | + port->txlast = next_desc(port, port->txlast, 1); | |
1844 | } | |
1845 | ||
1846 | netif_wake_queue(hdlc_to_dev(&port->hdlc)); | |
1847 | @@ -390,8 +411,6 @@ | |
1848 | static void sca_intr(int irq, void* dev_id, struct pt_regs *regs) | |
1849 | { | |
1850 | card_t *card = dev_id; | |
1851 | -/* Maximum events to handle at each interrupt - should I increase it? */ | |
1852 | - int boguscnt = 4; | |
1853 | int i; | |
1854 | u8 stat; | |
1855 | ||
1856 | @@ -412,23 +431,12 @@ | |
1857 | if (stat & SCA_INTR_DMAC_TX(i)) | |
1858 | sca_tx_intr(port); | |
1859 | } | |
1860 | - | |
1861 | - if (--boguscnt < 0) { | |
1862 | -#if 0 | |
1863 | - printk(KERN_ERR "%s: too much work at " | |
1864 | - "interrupt\n", | |
1865 | - hdlc_to_name(&port->hdlc)); | |
1866 | -#endif | |
1867 | - goto exit; | |
1868 | - } | |
1869 | } | |
1870 | } | |
1871 | ||
1872 | - exit: | |
1873 | #ifndef ALL_PAGES_ALWAYS_MAPPED | |
1874 | openwin(card, page); /* Restore original page */ | |
1875 | #endif | |
1876 | - return; | |
1877 | } | |
1878 | ||
1879 | ||
1880 | @@ -436,7 +444,7 @@ | |
1881 | static void sca_set_port(port_t *port) | |
1882 | { | |
1883 | card_t* card = port_to_card(port); | |
1884 | - u8 msci = get_msci(port); | |
1885 | + u16 msci = get_msci(port); | |
1886 | u8 md2 = sca_in(msci + MD2, card); | |
1887 | unsigned int tmc, br = 10, brv = 1024; | |
1888 | ||
1889 | @@ -496,7 +504,7 @@ | |
1890 | { | |
1891 | port_t *port = hdlc_to_port(hdlc); | |
1892 | card_t* card = port_to_card(port); | |
1893 | - u8 msci = get_msci(port); | |
1894 | + u16 msci = get_msci(port); | |
1895 | u8 md0, md2; | |
1896 | ||
1897 | switch(port->encoding) { | |
1898 | @@ -517,7 +525,7 @@ | |
1899 | case PARITY_CRC16_PR0_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU_0; break; | |
1900 | #else | |
1901 | case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break; | |
1902 | -#endif | |
1903 | +#endif | |
1904 | case PARITY_CRC16_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU; break; | |
1905 | default: md0 = MD0_HDLC | MD0_CRC_NONE; | |
1906 | } | |
1907 | @@ -566,7 +574,7 @@ | |
1908 | /* MSCI TX INT IRQ enable */ | |
1909 | sca_outl(IE0_TXINT | IE0_UDRN, msci + IE0, card); | |
1910 | /* DMA & MSCI IRQ enable */ | |
1911 | - sca_outl(sca_in(IER0, card) | | |
1912 | + sca_outl(sca_inl(IER0, card) | | |
1913 | (phy_node(port) ? 0x02006600 : 0x00020066), IER0, card); | |
1914 | #endif | |
1915 | ||
1916 | @@ -614,7 +622,7 @@ | |
1917 | parity != PARITY_CRC16_PR0_CCITT && | |
1918 | #else | |
1919 | parity != PARITY_CRC32_PR1_CCITT && | |
1920 | -#endif | |
1921 | +#endif | |
1922 | parity != PARITY_CRC16_PR1_CCITT) | |
1923 | return -EINVAL; | |
1924 | ||
1925 | @@ -640,14 +648,13 @@ | |
1926 | openwin(card, 0); | |
1927 | #endif | |
1928 | ||
1929 | - printk(KERN_ERR "RX ring: CDA=%u EDA=%u DSR=%02X in=%u " | |
1930 | - "%sactive", | |
1931 | + printk(KERN_ERR "RX ring: CDA=%u EDA=%u DSR=%02X in=%u %sactive", | |
1932 | sca_ina(get_dmac_rx(port) + CDAL, card), | |
1933 | sca_ina(get_dmac_rx(port) + EDAL, card), | |
1934 | sca_in(DSR_RX(phy_node(port)), card), | |
1935 | port->rxin, | |
1936 | sca_in(DSR_RX(phy_node(port)), card) & DSR_DE?"":"in"); | |
1937 | - for (cnt = 0; cnt<port_to_card(port)->ring_buffers; cnt++) | |
1938 | + for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++) | |
1939 | printk(" %02X", | |
1940 | readb(&(desc_address(port, cnt, 0)->stat))); | |
1941 | ||
1942 | @@ -659,7 +666,7 @@ | |
1943 | port->txlast, | |
1944 | sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in"); | |
1945 | ||
1946 | - for (cnt = 0; cnt<port_to_card(port)->ring_buffers; cnt++) | |
1947 | + for (cnt = 0; cnt < port_to_card(port)->tx_ring_buffers; cnt++) | |
1948 | printk(" %02X", | |
1949 | readb(&(desc_address(port, cnt, 1)->stat))); | |
1950 | printk("\n"); | |
1951 | @@ -751,7 +758,7 @@ | |
1952 | writeb(ST_TX_EOM, &desc->stat); | |
1953 | dev->trans_start = jiffies; | |
1954 | ||
1955 | - port->txin = next_desc(port, port->txin); | |
1956 | + port->txin = next_desc(port, port->txin, 1); | |
1957 | sca_outa(desc_offset(port, port->txin, 1), | |
1958 | get_dmac_tx(port) + EDAL, card); | |
1959 | ||
1960 | @@ -768,7 +775,49 @@ | |
1961 | } | |
1962 | ||
1963 | ||
1964 | -static void sca_init(card_t *card, int wait_states) | |
1965 | + | |
1966 | +#ifdef NEED_DETECT_RAM | |
1967 | +static u32 __devinit sca_detect_ram(card_t *card, u8 *rambase, u32 ramsize) | |
1968 | +{ | |
1969 | + /* Round RAM size to 32 bits, fill from end to start */ | |
1970 | + u32 i = ramsize &= ~3; | |
1971 | + | |
1972 | +#ifndef ALL_PAGES_ALWAYS_MAPPED | |
1973 | + u32 size = winsize(card); | |
1974 | + | |
1975 | + openwin(card, (i - 4) / size); /* select last window */ | |
1976 | +#endif | |
1977 | + do { | |
1978 | + i -= 4; | |
1979 | +#ifndef ALL_PAGES_ALWAYS_MAPPED | |
1980 | + if ((i + 4) % size == 0) | |
1981 | + openwin(card, i / size); | |
1982 | + writel(i ^ 0x12345678, rambase + i % size); | |
1983 | +#else | |
1984 | + writel(i ^ 0x12345678, rambase + i); | |
1985 | +#endif | |
1986 | + }while (i > 0); | |
1987 | + | |
1988 | + for (i = 0; i < ramsize ; i += 4) { | |
1989 | +#ifndef ALL_PAGES_ALWAYS_MAPPED | |
1990 | + if (i % size == 0) | |
1991 | + openwin(card, i / size); | |
1992 | + | |
1993 | + if (readl(rambase + i % size) != (i ^ 0x12345678)) | |
1994 | + break; | |
1995 | +#else | |
1996 | + if (readl(rambase + i) != (i ^ 0x12345678)) | |
1997 | + break; | |
1998 | +#endif | |
1999 | + } | |
2000 | + | |
2001 | + return i; | |
2002 | +} | |
2003 | +#endif /* NEED_DETECT_RAM */ | |
2004 | + | |
2005 | + | |
2006 | + | |
2007 | +static void __devinit sca_init(card_t *card, int wait_states) | |
2008 | { | |
2009 | sca_out(wait_states, WCRL, card); /* Wait Control */ | |
2010 | sca_out(wait_states, WCRM, card); | |
2011 | --- linux-2.4.orig/drivers/net/wan/n2.c 2003-07-29 23:25:03.000000000 +0200 | |
2012 | +++ linux-2.4/drivers/net/wan/n2.c 2003-07-29 23:32:23.000000000 +0200 | |
2013 | @@ -1,12 +1,11 @@ | |
2014 | /* | |
2015 | * SDL Inc. RISCom/N2 synchronous serial card driver for Linux | |
2016 | * | |
2017 | - * Copyright (C) 1998-2002 Krzysztof Halasa <khc@pm.waw.pl> | |
2018 | + * Copyright (C) 1998-2003 Krzysztof Halasa <khc@pm.waw.pl> | |
2019 | * | |
2020 | * This program is free software; you can redistribute it and/or modify it | |
2021 | - * under the terms of the GNU General Public License as published by | |
2022 | - * the Free Software Foundation; either version 2 of the License, or | |
2023 | - * (at your option) any later version. | |
2024 | + * under the terms of version 2 of the GNU General Public License | |
2025 | + * as published by the Free Software Foundation. | |
2026 | * | |
2027 | * For information see http://hq.pm.waw.pl/hdlc/ | |
2028 | * | |
2029 | @@ -34,14 +33,21 @@ | |
2030 | #include "hd64570.h" | |
2031 | ||
2032 | ||
2033 | -static const char* version = "SDL RISCom/N2 driver version: 1.10"; | |
2034 | +static const char* version = "SDL RISCom/N2 driver version: 1.14"; | |
2035 | static const char* devname = "RISCom/N2"; | |
2036 | ||
2037 | #define USE_WINDOWSIZE 16384 | |
2038 | #define USE_BUS16BITS 1 | |
2039 | #define CLOCK_BASE 9830400 /* 9.8304 MHz */ | |
2040 | - | |
2041 | +#define MAX_PAGES 16 /* 16 RAM pages at max */ | |
2042 | +#define MAX_RAM_SIZE 0x80000 /* 512 KB */ | |
2043 | +#if MAX_RAM_SIZE > MAX_PAGES * USE_WINDOWSIZE | |
2044 | +#undef MAX_RAM_SIZE | |
2045 | +#define MAX_RAM_SIZE (MAX_PAGES * USE_WINDOWSIZE) | |
2046 | +#endif | |
2047 | #define N2_IOPORTS 0x10 | |
2048 | +#define NEED_DETECT_RAM | |
2049 | +#define MAX_TX_BUFFERS 10 | |
2050 | ||
2051 | static char *hw = NULL; /* pointer to hw=xxx command line string */ | |
2052 | ||
2053 | @@ -86,16 +92,16 @@ | |
2054 | struct card_s *card; | |
2055 | spinlock_t lock; /* TX lock */ | |
2056 | sync_serial_settings settings; | |
2057 | + int valid; /* port enabled */ | |
2058 | + int rxpart; /* partial frame received, next frame invalid*/ | |
2059 | unsigned short encoding; | |
2060 | unsigned short parity; | |
2061 | + u16 rxin; /* rx ring buffer 'in' pointer */ | |
2062 | + u16 txin; /* tx ring buffer 'in' and 'last' pointers */ | |
2063 | + u16 txlast; | |
2064 | u8 rxs, txs, tmc; /* SCA registers */ | |
2065 | - u8 valid; /* port enabled */ | |
2066 | u8 phy_node; /* physical port # - 0 or 1 */ | |
2067 | u8 log_node; /* logical port # */ | |
2068 | - u8 rxin; /* rx ring buffer 'in' pointer */ | |
2069 | - u8 txin; /* tx ring buffer 'in' and 'last' pointers */ | |
2070 | - u8 txlast; | |
2071 | - u8 rxpart; /* partial frame received, next frame invalid*/ | |
2072 | }port_t; | |
2073 | ||
2074 | ||
2075 | @@ -106,8 +112,9 @@ | |
2076 | u32 ram_size; /* number of bytes */ | |
2077 | u16 io; /* IO Base address */ | |
2078 | u16 buff_offset; /* offset of first buffer of first channel */ | |
2079 | + u16 rx_ring_buffers; /* number of buffers in a ring */ | |
2080 | + u16 tx_ring_buffers; | |
2081 | u8 irq; /* IRQ (3-15) */ | |
2082 | - u8 ring_buffers; /* number of buffers in a ring */ | |
2083 | ||
2084 | port_t ports[2]; | |
2085 | struct card_s *next_card; | |
2086 | @@ -216,7 +223,7 @@ | |
2087 | MOD_INC_USE_COUNT; | |
2088 | mcr &= port->phy_node ? ~DTR_PORT1 : ~DTR_PORT0; /* set DTR ON */ | |
2089 | outb(mcr, io + N2_MCR); | |
2090 | - | |
2091 | + | |
2092 | outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */ | |
2093 | outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */ | |
2094 | sca_open(hdlc); | |
2095 | @@ -297,62 +304,6 @@ | |
2096 | ||
2097 | ||
2098 | ||
2099 | -static u8 n2_count_page(card_t *card) | |
2100 | -{ | |
2101 | - u8 page; | |
2102 | - int i, bcount = USE_WINDOWSIZE, wcount = USE_WINDOWSIZE/2; | |
2103 | - u16 *dp = (u16*)card->winbase; | |
2104 | - u8 *bp = (u8*)card->winbase; | |
2105 | - u8 psr = inb(card->io + N2_PSR) & PSR_WINBITS; | |
2106 | - | |
2107 | - | |
2108 | - for (page = 0; page < 16; page++) { | |
2109 | - outb(psr | page, card->io + N2_PSR); /* select a page */ | |
2110 | - writeb(page, dp); | |
2111 | - if (readb(dp) != page) | |
2112 | - break; /* If can't read back, no good memory */ | |
2113 | - | |
2114 | - outb(psr, card->io + N2_PSR); /* goto page 0 */ | |
2115 | - if (readb(dp)) | |
2116 | - break; /* If page 0 changed, then wrapped around */ | |
2117 | - | |
2118 | - outb(psr | page, card->io + N2_PSR); /* select page again */ | |
2119 | - | |
2120 | - /* first do byte tests */ | |
2121 | - for (i = 0; i < bcount; i++) | |
2122 | - writeb(i, bp + i); | |
2123 | - for (i = 0; i < bcount; i++) | |
2124 | - if (readb(bp + i) != (i & 0xff)) | |
2125 | - return 0; | |
2126 | - | |
2127 | - for (i = 0; i < bcount; i++) | |
2128 | - writeb(~i, bp + i); | |
2129 | - for (i = 0; i < bcount; i++) | |
2130 | - if (readb(bp + i) != (~i & 0xff)) | |
2131 | - return 0; | |
2132 | - | |
2133 | - /* next do 16-bit tests */ | |
2134 | - for (i = 0; i < wcount; i++) | |
2135 | - writew(0x55AA, dp + i); | |
2136 | - for (i = 0; i < wcount; i++) | |
2137 | - if (readw(dp + i) != 0x55AA) | |
2138 | - return 0; | |
2139 | - | |
2140 | - for (i = 0; i < wcount; i++) | |
2141 | - writew(0xAA55, dp + i); | |
2142 | - for (i = 0; i < wcount; i++) | |
2143 | - if (readw(dp + i) != 0xAA55) | |
2144 | - return 0; | |
2145 | - | |
2146 | - for (i = 0; i < wcount; i++) | |
2147 | - writew(page, dp + i); | |
2148 | - } | |
2149 | - | |
2150 | - return page; | |
2151 | -} | |
2152 | - | |
2153 | - | |
2154 | - | |
2155 | static void n2_destroy_card(card_t *card) | |
2156 | { | |
2157 | int cnt; | |
2158 | @@ -376,11 +327,12 @@ | |
2159 | ||
2160 | ||
2161 | ||
2162 | -static int n2_run(unsigned long io, unsigned long irq, unsigned long winbase, | |
2163 | - long valid0, long valid1) | |
2164 | +static int __init n2_run(unsigned long io, unsigned long irq, | |
2165 | + unsigned long winbase, long valid0, long valid1) | |
2166 | { | |
2167 | card_t *card; | |
2168 | u8 cnt, pcr; | |
2169 | + int i; | |
2170 | ||
2171 | if (io < 0x200 || io > 0x3FF || (io % N2_IOPORTS) != 0) { | |
2172 | printk(KERN_ERR "n2: invalid I/O port value\n"); | |
2173 | @@ -391,7 +343,7 @@ | |
2174 | printk(KERN_ERR "n2: invalid IRQ value\n"); | |
2175 | return -ENODEV; | |
2176 | } | |
2177 | - | |
2178 | + | |
2179 | if (winbase < 0xA0000 || winbase > 0xFFFFF || (winbase & 0xFFF) != 0) { | |
2180 | printk(KERN_ERR "n2: invalid RAM value\n"); | |
2181 | return -ENODEV; | |
2182 | @@ -451,25 +403,27 @@ | |
2183 | pcr = PCR_ENWIN | PCR_VPM | (USE_BUS16BITS ? PCR_BUS16 : 0); | |
2184 | outb(pcr, io + N2_PCR); | |
2185 | ||
2186 | - cnt = n2_count_page(card); | |
2187 | - if (!cnt) { | |
2188 | - printk(KERN_ERR "n2: memory test failed.\n"); | |
2189 | - n2_destroy_card(card); | |
2190 | - return -EIO; | |
2191 | - } | |
2192 | + card->ram_size = sca_detect_ram(card, card->winbase, MAX_RAM_SIZE); | |
2193 | ||
2194 | - card->ram_size = cnt * USE_WINDOWSIZE; | |
2195 | + /* number of TX + RX buffers for one port */ | |
2196 | + i = card->ram_size / ((valid0 + valid1) * (sizeof(pkt_desc) + | |
2197 | + HDLC_MAX_MRU)); | |
2198 | ||
2199 | - /* 4 rings required for 2 ports, 2 rings for one port */ | |
2200 | - card->ring_buffers = card->ram_size / | |
2201 | - ((valid0 + valid1) * 2 * (sizeof(pkt_desc) + HDLC_MAX_MRU)); | |
2202 | + card->tx_ring_buffers = min(i / 2, MAX_TX_BUFFERS); | |
2203 | + card->rx_ring_buffers = i - card->tx_ring_buffers; | |
2204 | ||
2205 | - card->buff_offset = (valid0 + valid1) * 2 * (sizeof(pkt_desc)) | |
2206 | - * card->ring_buffers; | |
2207 | + card->buff_offset = (valid0 + valid1) * sizeof(pkt_desc) * | |
2208 | + (card->tx_ring_buffers + card->rx_ring_buffers); | |
2209 | ||
2210 | printk(KERN_DEBUG "n2: RISCom/N2 %u KB RAM, IRQ%u, " | |
2211 | - "using %u packets rings\n", card->ram_size / 1024, card->irq, | |
2212 | - card->ring_buffers); | |
2213 | + "using %u TX + %u RX packets rings\n", card->ram_size / 1024, | |
2214 | + card->irq, card->tx_ring_buffers, card->rx_ring_buffers); | |
2215 | + | |
2216 | + if (card->tx_ring_buffers < 1) { | |
2217 | + printk(KERN_ERR "n2: RAM test failed\n"); | |
2218 | + n2_destroy_card(card); | |
2219 | + return -EIO; | |
2220 | + } | |
2221 | ||
2222 | pcr |= PCR_RUNSCA; /* run SCA */ | |
2223 | outb(pcr, io + N2_PCR); | |
2224 | @@ -531,7 +485,7 @@ | |
2225 | return -ENOSYS; /* no parameters specified, abort */ | |
2226 | } | |
2227 | ||
2228 | - printk(KERN_INFO "%s (SCA-%s)\n", version, sca_version); | |
2229 | + printk(KERN_INFO "%s\n", version); | |
2230 | ||
2231 | do { | |
2232 | unsigned long io, irq, ram; | |
2233 | @@ -558,7 +512,7 @@ | |
2234 | break; | |
2235 | hw++; | |
2236 | } | |
2237 | - | |
2238 | + | |
2239 | if (!valid[0] && !valid[1]) | |
2240 | break; /* at least one port must be used */ | |
2241 | ||
2242 | @@ -566,7 +520,7 @@ | |
2243 | n2_run(io, irq, ram, valid[0], valid[1]); | |
2244 | ||
2245 | if (*hw == '\x0') | |
2246 | - return 0; | |
2247 | + return first_card ? 0 : -ENOSYS; | |
2248 | }while(*hw++ == ':'); | |
2249 | ||
2250 | printk(KERN_ERR "n2: invalid hardware parameters\n"); | |
2251 | @@ -602,6 +556,6 @@ | |
2252 | ||
2253 | MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); | |
2254 | MODULE_DESCRIPTION("RISCom/N2 serial port driver"); | |
2255 | -MODULE_LICENSE("GPL"); | |
2256 | +MODULE_LICENSE("GPL v2"); | |
2257 | MODULE_PARM(hw, "s"); /* hw=io,irq,ram,ports:io,irq,... */ | |
2258 | EXPORT_NO_SYMBOLS; | |
2259 | --- linux-2.4.orig/drivers/net/wan/c101.c 2003-07-29 23:25:03.000000000 +0200 | |
2260 | +++ linux-2.4/drivers/net/wan/c101.c 2003-07-29 23:32:23.000000000 +0200 | |
2261 | @@ -1,12 +1,11 @@ | |
2262 | /* | |
2263 | * Moxa C101 synchronous serial card driver for Linux | |
2264 | * | |
2265 | - * Copyright (C) 2000-2002 Krzysztof Halasa <khc@pm.waw.pl> | |
2266 | + * Copyright (C) 2000-2003 Krzysztof Halasa <khc@pm.waw.pl> | |
2267 | * | |
2268 | * This program is free software; you can redistribute it and/or modify it | |
2269 | - * under the terms of the GNU General Public License as published by | |
2270 | - * the Free Software Foundation; either version 2 of the License, or | |
2271 | - * (at your option) any later version. | |
2272 | + * under the terms of version 2 of the GNU General Public License | |
2273 | + * as published by the Free Software Foundation. | |
2274 | * | |
2275 | * For information see http://hq.pm.waw.pl/hdlc/ | |
2276 | * | |
2277 | @@ -31,7 +30,7 @@ | |
2278 | #include "hd64570.h" | |
2279 | ||
2280 | ||
2281 | -static const char* version = "Moxa C101 driver version: 1.10"; | |
2282 | +static const char* version = "Moxa C101 driver version: 1.14"; | |
2283 | static const char* devname = "C101"; | |
2284 | ||
2285 | #define C101_PAGE 0x1D00 | |
2286 | @@ -41,6 +40,10 @@ | |
2287 | #define C101_MAPPED_RAM_SIZE 0x4000 | |
2288 | ||
2289 | #define RAM_SIZE (256 * 1024) | |
2290 | +#define TX_RING_BUFFERS 10 | |
2291 | +#define RX_RING_BUFFERS ((RAM_SIZE - C101_WINDOW_SIZE) / \ | |
2292 | + (sizeof(pkt_desc) + HDLC_MAX_MRU) - TX_RING_BUFFERS) | |
2293 | + | |
2294 | #define CLOCK_BASE 9830400 /* 9.8304 MHz */ | |
2295 | #define PAGE0_ALWAYS_MAPPED | |
2296 | ||
2297 | @@ -52,20 +55,20 @@ | |
2298 | spinlock_t lock; /* TX lock */ | |
2299 | u8 *win0base; /* ISA window base address */ | |
2300 | u32 phy_winbase; /* ISA physical base address */ | |
2301 | - u16 buff_offset; /* offset of first buffer of first channel */ | |
2302 | sync_serial_settings settings; | |
2303 | + int rxpart; /* partial frame received, next frame invalid*/ | |
2304 | unsigned short encoding; | |
2305 | unsigned short parity; | |
2306 | + u16 rx_ring_buffers; /* number of buffers in a ring */ | |
2307 | + u16 tx_ring_buffers; | |
2308 | + u16 buff_offset; /* offset of first buffer of first channel */ | |
2309 | + u16 rxin; /* rx ring buffer 'in' pointer */ | |
2310 | + u16 txin; /* tx ring buffer 'in' and 'last' pointers */ | |
2311 | + u16 txlast; | |
2312 | u8 rxs, txs, tmc; /* SCA registers */ | |
2313 | u8 irq; /* IRQ (3-15) */ | |
2314 | - u8 ring_buffers; /* number of buffers in a ring */ | |
2315 | u8 page; | |
2316 | ||
2317 | - u8 rxin; /* rx ring buffer 'in' pointer */ | |
2318 | - u8 txin; /* tx ring buffer 'in' and 'last' pointers */ | |
2319 | - u8 txlast; | |
2320 | - u8 rxpart; /* partial frame received, next frame invalid*/ | |
2321 | - | |
2322 | struct card_s *next_card; | |
2323 | }card_t; | |
2324 | ||
2325 | @@ -78,7 +81,12 @@ | |
2326 | #define sca_in(reg, card) readb((card)->win0base + C101_SCA + (reg)) | |
2327 | #define sca_out(value, reg, card) writeb(value, (card)->win0base + C101_SCA + (reg)) | |
2328 | #define sca_inw(reg, card) readw((card)->win0base + C101_SCA + (reg)) | |
2329 | -#define sca_outw(value, reg, card) writew(value, (card)->win0base + C101_SCA + (reg)) | |
2330 | + | |
2331 | +/* EDA address register must be set in EDAL, EDAH order - 8 bit ISA bus */ | |
2332 | +#define sca_outw(value, reg, card) do { \ | |
2333 | + writeb(value & 0xFF, (card)->win0base + C101_SCA + (reg)); \ | |
2334 | + writeb((value >> 8 ) & 0xFF, (card)->win0base + C101_SCA + (reg+1));\ | |
2335 | +} while(0) | |
2336 | ||
2337 | #define port_to_card(port) (port) | |
2338 | #define log_node(port) (0) | |
2339 | @@ -229,6 +237,8 @@ | |
2340 | ||
2341 | static void c101_destroy_card(card_t *card) | |
2342 | { | |
2343 | + readb(card->win0base + C101_PAGE); /* Resets SCA? */ | |
2344 | + | |
2345 | if (card->irq) | |
2346 | free_irq(card->irq, card); | |
2347 | ||
2348 | @@ -242,7 +252,7 @@ | |
2349 | ||
2350 | ||
2351 | ||
2352 | -static int c101_run(unsigned long irq, unsigned long winbase) | |
2353 | +static int __init c101_run(unsigned long irq, unsigned long winbase) | |
2354 | { | |
2355 | struct net_device *dev; | |
2356 | card_t *card; | |
2357 | @@ -285,9 +295,10 @@ | |
2358 | return -EBUSY; | |
2359 | } | |
2360 | ||
2361 | - /* 2 rings required for 1 port */ | |
2362 | - card->ring_buffers = (RAM_SIZE -C101_WINDOW_SIZE) / (2 * HDLC_MAX_MRU); | |
2363 | - printk(KERN_DEBUG "c101: using %u packets rings\n",card->ring_buffers); | |
2364 | + card->tx_ring_buffers = TX_RING_BUFFERS; | |
2365 | + card->rx_ring_buffers = RX_RING_BUFFERS; | |
2366 | + printk(KERN_DEBUG "c101: using %u TX + %u RX packets rings\n", | |
2367 | + card->tx_ring_buffers, card->rx_ring_buffers); | |
2368 | ||
2369 | card->buff_offset = C101_WINDOW_SIZE; /* Bytes 1D00-1FFF reserved */ | |
2370 | ||
2371 | @@ -337,7 +348,7 @@ | |
2372 | return -ENOSYS; /* no parameters specified, abort */ | |
2373 | } | |
2374 | ||
2375 | - printk(KERN_INFO "%s (SCA-%s)\n", version, sca_version); | |
2376 | + printk(KERN_INFO "%s\n", version); | |
2377 | ||
2378 | do { | |
2379 | unsigned long irq, ram; | |
2380 | @@ -352,7 +363,7 @@ | |
2381 | c101_run(irq, ram); | |
2382 | ||
2383 | if (*hw == '\x0') | |
2384 | - return 0; | |
2385 | + return first_card ? 0 : -ENOSYS; | |
2386 | }while(*hw++ == ':'); | |
2387 | ||
2388 | printk(KERN_ERR "c101: invalid hardware parameters\n"); | |
2389 | @@ -389,6 +400,6 @@ | |
2390 | ||
2391 | MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>"); | |
2392 | MODULE_DESCRIPTION("Moxa C101 serial port driver"); | |
2393 | -MODULE_LICENSE("GPL"); | |
2394 | +MODULE_LICENSE("GPL v2"); | |
2395 | MODULE_PARM(hw, "s"); /* hw=irq,ram:irq,... */ | |
2396 | EXPORT_NO_SYMBOLS; | |
2397 | --- linux-2.4.orig/drivers/net/wan/farsync.c 2003-07-29 23:25:03.000000000 +0200 | |
2398 | +++ linux-2.4/drivers/net/wan/farsync.c 2003-07-29 23:32:23.000000000 +0200 | |
2399 | @@ -764,7 +764,7 @@ | |
2400 | /* Push upstream */ | |
2401 | skb->mac.raw = skb->data; | |
2402 | skb->dev = hdlc_to_dev ( &port->hdlc ); | |
2403 | - skb->protocol = htons ( ETH_P_HDLC ); | |
2404 | + skb->protocol = hdlc_type_trans(skb, skb->dev); | |
2405 | netif_rx ( skb ); | |
2406 | ||
2407 | port_to_dev ( port )->last_rx = jiffies; | |
2408 | --- linux-2.4.orig/drivers/net/wan/dscc4.c 2003-07-29 23:25:03.000000000 +0200 | |
2409 | +++ linux-2.4/drivers/net/wan/dscc4.c 2003-07-29 23:32:23.000000000 +0200 | |
2410 | @@ -488,7 +488,7 @@ | |
2411 | dpriv->rx_skbuff[dirty] = skb; | |
2412 | if (skb) { | |
2413 | skb->dev = dev; | |
2414 | - skb->protocol = htons(ETH_P_HDLC); | |
2415 | + skb->protocol = hdlc_type_trans(skb, dev); | |
2416 | skb->mac.raw = skb->data; | |
2417 | rx_fd->data = pci_map_single(dpriv->pci_priv->pdev, skb->data, | |
2418 | len, PCI_DMA_FROMDEVICE); | |
2419 | --- linux-2.4.orig/Documentation/Configure.help 2003-07-29 23:24:56.000000000 +0200 | |
2420 | +++ linux-2.4/Documentation/Configure.help 2003-07-29 23:32:23.000000000 +0200 | |
2421 | @@ -9674,14 +9674,15 @@ | |
2422 | This driver supports the FarSync T-Series X.21 (and V.35/V.24) cards | |
2423 | from FarSite Communications Ltd. | |
2424 | Synchronous communication is supported on all ports at speeds up to | |
2425 | - 8Mb/s (128K on V.24) using synchronous PPP or Cisco HDLC. | |
2426 | + 8Mb/s (128K on V.24) using synchronous PPP, Cisco HDLC, raw HDLC, | |
2427 | + Frame Relay or X.25/LAPB. | |
2428 | ||
2429 | If you want to compile this driver as a module ( = code which can be | |
2430 | inserted in and removed from the running kernel whenever you want) | |
2431 | say M here and read <file:Documentation/modules.txt>. | |
2432 | The module will be called farsync.o and if you want the module to be | |
2433 | automatically loaded when the interface is referenced then you | |
2434 | - should add "alias syncX farsync" to /etc/modules.conf for each | |
2435 | + should add "alias hdlcX farsync" to /etc/modules.conf for each | |
2436 | interface, where X is 0, 1, 2, ... | |
2437 | ||
2438 | CONFIG_HDLC_DEBUG_PKT | |
2439 | @@ -10576,6 +10577,15 @@ | |
2440 | ||
2441 | If unsure, say N here. | |
2442 | ||
2443 | +Raw HDLC Ethernet device support | |
2444 | +CONFIG_HDLC_RAW_ETH | |
2445 | + Say Y to this option if you want generic HDLC driver to support | |
2446 | + raw HDLC Ethernet device emulation over WAN (Wide Area Network) | |
2447 | + connections. | |
2448 | + You will need it for Ethernet over HDLC bridges. | |
2449 | + | |
2450 | + If unsure, say N here. | |
2451 | + | |
2452 | Cisco HDLC support | |
2453 | CONFIG_HDLC_CISCO | |
2454 | Say Y to this option if you want generic HDLC driver to support | |
2455 | @@ -10590,13 +10600,6 @@ | |
2456 | ||
2457 | If unsure, say N here. | |
2458 | ||
2459 | -Frame-Relay bridging support | |
2460 | -CONFIG_HDLC_FR_BRIDGE | |
2461 | - Say Y to this option if you want generic HDLC driver to support | |
2462 | - bridging LAN frames over Frame-Relay links. | |
2463 | - | |
2464 | - If unsure, say N here. | |
2465 | - | |
2466 | Synchronous Point-to-Point Protocol (PPP) support | |
2467 | CONFIG_HDLC_PPP | |
2468 | Say Y to this option if you want generic HDLC driver to support | |
2469 | @@ -10639,6 +10642,25 @@ | |
2470 | ||
2471 | If unsure, say N here. | |
2472 | ||
2473 | +CONFIG_HDLC_DEBUG_PKT | |
2474 | + This option is for developers only - do NOT use on production | |
2475 | + systems. | |
2476 | + | |
2477 | +CONFIG_HDLC_DEBUG_HARD_HEADER | |
2478 | + This option is for developers only - do NOT use on production | |
2479 | + systems. | |
2480 | + | |
2481 | +CONFIG_HDLC_DEBUG_ECN | |
2482 | + This option is for developers only - do NOT use on production | |
2483 | + systems. | |
2484 | + | |
2485 | +CONFIG_HDLC_DEBUG_RINGS | |
2486 | + If you answer Y here you will be able to get a diagnostic dump of | |
2487 | + port's TX and RX packet rings, using "sethdlc hdlcX private" | |
2488 | + command. It does not affect normal operations. | |
2489 | + | |
2490 | + If unsure, say Y here. | |
2491 | + | |
2492 | Ethernet (10 or 100Mbit) | |
2493 | CONFIG_NET_ETHERNET | |
2494 | Ethernet (also called IEEE 802.3 or ISO 8802-2) is the most common | |
2495 | --- linux-2.4.orig/drivers/net/wan/Config.in 2003-07-29 23:25:03.000000000 +0200 | |
2496 | +++ linux-2.4/drivers/net/wan/Config.in 2003-07-29 23:32:23.000000000 +0200 | |
2497 | @@ -68,6 +68,7 @@ | |
2498 | tristate ' Generic HDLC layer' CONFIG_HDLC | |
2499 | if [ "$CONFIG_HDLC" != "n" ]; then | |
2500 | bool ' Raw HDLC support' CONFIG_HDLC_RAW | |
2501 | + bool ' Raw HDLC Ethernet device support' CONFIG_HDLC_RAW_ETH | |
2502 | bool ' Cisco HDLC support' CONFIG_HDLC_CISCO | |
2503 | bool ' Frame Relay support' CONFIG_HDLC_FR | |
2504 | bool ' Synchronous Point-to-Point Protocol (PPP) support' CONFIG_HDLC_PPP |