diff options
author | Arnd Bergmann <arnd@arndb.de> | 2011-01-25 17:17:27 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-31 16:38:16 -0500 |
commit | a6238f21736af3f47bdebf3895f477f5f23f1af9 (patch) | |
tree | 6adcff1f9fdae33641697aee58a5ba206b6e5244 /drivers/staging/appletalk | |
parent | 939cbe5af5fb04de1a53942a8c4a6e0160f4f38b (diff) |
appletalk: move to staging
For all I know, Appletalk is dead, the only reasonable
use right now would be nostalgia, and that can be served
well enough by old kernels. The code is largely not
in a bad shape, but it still uses the big kernel lock,
and nobody seems motivated to change that.
FWIW, the last release of MacOS that supported Appletalk
was MacOS X 10.5, made in 2007, and it has been abandoned
by Apple with 10.6. Using TCP/IP instead of Appletalk has
been supported since MacOS 7.6, which was released in
1997 and is able to run on most of the legacy hardware.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: netdev@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging/appletalk')
-rw-r--r-- | drivers/staging/appletalk/Kconfig | 126 | ||||
-rw-r--r-- | drivers/staging/appletalk/Makefile | 12 | ||||
-rw-r--r-- | drivers/staging/appletalk/aarp.c | 1063 | ||||
-rw-r--r-- | drivers/staging/appletalk/atalk.h | 208 | ||||
-rw-r--r-- | drivers/staging/appletalk/atalk_proc.c | 301 | ||||
-rw-r--r-- | drivers/staging/appletalk/cops.c | 1013 | ||||
-rw-r--r-- | drivers/staging/appletalk/cops.h | 60 | ||||
-rw-r--r-- | drivers/staging/appletalk/cops_ffdrv.h | 532 | ||||
-rw-r--r-- | drivers/staging/appletalk/cops_ltdrv.h | 241 | ||||
-rw-r--r-- | drivers/staging/appletalk/ddp.c | 1981 | ||||
-rw-r--r-- | drivers/staging/appletalk/dev.c | 44 | ||||
-rw-r--r-- | drivers/staging/appletalk/ipddp.c | 335 | ||||
-rw-r--r-- | drivers/staging/appletalk/ipddp.h | 27 | ||||
-rw-r--r-- | drivers/staging/appletalk/ltpc.c | 1288 | ||||
-rw-r--r-- | drivers/staging/appletalk/ltpc.h | 73 | ||||
-rw-r--r-- | drivers/staging/appletalk/sysctl_net_atalk.c | 61 |
16 files changed, 7365 insertions, 0 deletions
diff --git a/drivers/staging/appletalk/Kconfig b/drivers/staging/appletalk/Kconfig new file mode 100644 index 00000000000..0b376a99097 --- /dev/null +++ b/drivers/staging/appletalk/Kconfig | |||
@@ -0,0 +1,126 @@ | |||
1 | # | ||
2 | # Appletalk driver configuration | ||
3 | # | ||
4 | config ATALK | ||
5 | tristate "Appletalk protocol support" | ||
6 | depends on BKL # waiting to be removed from net/appletalk/ddp.c | ||
7 | select LLC | ||
8 | ---help--- | ||
9 | AppleTalk is the protocol that Apple computers can use to communicate | ||
10 | on a network. If your Linux box is connected to such a network and you | ||
11 | wish to connect to it, say Y. You will need to use the netatalk package | ||
12 | so that your Linux box can act as a print and file server for Macs as | ||
13 | well as access AppleTalk printers. Check out | ||
14 | <http://www.zettabyte.net/netatalk/> on the WWW for details. | ||
15 | EtherTalk is the name used for AppleTalk over Ethernet and the | ||
16 | cheaper and slower LocalTalk is AppleTalk over a proprietary Apple | ||
17 | network using serial links. EtherTalk and LocalTalk are fully | ||
18 | supported by Linux. | ||
19 | |||
20 | General information about how to connect Linux, Windows machines and | ||
21 | Macs is on the WWW at <http://www.eats.com/linux_mac_win.html>. The | ||
22 | NET3-4-HOWTO, available from | ||
23 | <http://www.tldp.org/docs.html#howto>, contains valuable | ||
24 | information as well. | ||
25 | |||
26 | To compile this driver as a module, choose M here: the module will be | ||
27 | called appletalk. You almost certainly want to compile it as a | ||
28 | module so you can restart your AppleTalk stack without rebooting | ||
29 | your machine. I hear that the GNU boycott of Apple is over, so | ||
30 | even politically correct people are allowed to say Y here. | ||
31 | |||
32 | config DEV_APPLETALK | ||
33 | tristate "Appletalk interfaces support" | ||
34 | depends on ATALK | ||
35 | help | ||
36 | AppleTalk is the protocol that Apple computers can use to communicate | ||
37 | on a network. If your Linux box is connected to such a network, and wish | ||
38 | to do IP over it, or you have a LocalTalk card and wish to use it to | ||
39 | connect to the AppleTalk network, say Y. | ||
40 | |||
41 | |||
42 | config LTPC | ||
43 | tristate "Apple/Farallon LocalTalk PC support" | ||
44 | depends on DEV_APPLETALK && (ISA || EISA) && ISA_DMA_API | ||
45 | help | ||
46 | This allows you to use the AppleTalk PC card to connect to LocalTalk | ||
47 | networks. The card is also known as the Farallon PhoneNet PC card. | ||
48 | If you are in doubt, this card is the one with the 65C02 chip on it. | ||
49 | You also need version 1.3.3 or later of the netatalk package. | ||
50 | This driver is experimental, which means that it may not work. | ||
51 | See the file <file:Documentation/networking/ltpc.txt>. | ||
52 | |||
53 | config COPS | ||
54 | tristate "COPS LocalTalk PC support" | ||
55 | depends on DEV_APPLETALK && (ISA || EISA) | ||
56 | help | ||
57 | This allows you to use COPS AppleTalk cards to connect to LocalTalk | ||
58 | networks. You also need version 1.3.3 or later of the netatalk | ||
59 | package. This driver is experimental, which means that it may not | ||
60 | work. This driver will only work if you choose "AppleTalk DDP" | ||
61 | networking support, above. | ||
62 | Please read the file <file:Documentation/networking/cops.txt>. | ||
63 | |||
64 | config COPS_DAYNA | ||
65 | bool "Dayna firmware support" | ||
66 | depends on COPS | ||
67 | help | ||
68 | Support COPS compatible cards with Dayna style firmware (Dayna | ||
69 | DL2000/ Daynatalk/PC (half length), COPS LT-95, Farallon PhoneNET PC | ||
70 | III, Farallon PhoneNET PC II). | ||
71 | |||
72 | config COPS_TANGENT | ||
73 | bool "Tangent firmware support" | ||
74 | depends on COPS | ||
75 | help | ||
76 | Support COPS compatible cards with Tangent style firmware (Tangent | ||
77 | ATB_II, Novell NL-1000, Daystar Digital LT-200. | ||
78 | |||
79 | config IPDDP | ||
80 | tristate "Appletalk-IP driver support" | ||
81 | depends on DEV_APPLETALK && ATALK | ||
82 | ---help--- | ||
83 | This allows IP networking for users who only have AppleTalk | ||
84 | networking available. This feature is experimental. With this | ||
85 | driver, you can encapsulate IP inside AppleTalk (e.g. if your Linux | ||
86 | box is stuck on an AppleTalk only network) or decapsulate (e.g. if | ||
87 | you want your Linux box to act as an Internet gateway for a zoo of | ||
88 | AppleTalk connected Macs). Please see the file | ||
89 | <file:Documentation/networking/ipddp.txt> for more information. | ||
90 | |||
91 | If you say Y here, the AppleTalk-IP support will be compiled into | ||
92 | the kernel. In this case, you can either use encapsulation or | ||
93 | decapsulation, but not both. With the following two questions, you | ||
94 | decide which one you want. | ||
95 | |||
96 | To compile the AppleTalk-IP support as a module, choose M here: the | ||
97 | module will be called ipddp. | ||
98 | In this case, you will be able to use both encapsulation and | ||
99 | decapsulation simultaneously, by loading two copies of the module | ||
100 | and specifying different values for the module option ipddp_mode. | ||
101 | |||
102 | config IPDDP_ENCAP | ||
103 | bool "IP to Appletalk-IP Encapsulation support" | ||
104 | depends on IPDDP | ||
105 | help | ||
106 | If you say Y here, the AppleTalk-IP code will be able to encapsulate | ||
107 | IP packets inside AppleTalk frames; this is useful if your Linux box | ||
108 | is stuck on an AppleTalk network (which hopefully contains a | ||
109 | decapsulator somewhere). Please see | ||
110 | <file:Documentation/networking/ipddp.txt> for more information. If | ||
111 | you said Y to "AppleTalk-IP driver support" above and you say Y | ||
112 | here, then you cannot say Y to "AppleTalk-IP to IP Decapsulation | ||
113 | support", below. | ||
114 | |||
115 | config IPDDP_DECAP | ||
116 | bool "Appletalk-IP to IP Decapsulation support" | ||
117 | depends on IPDDP | ||
118 | help | ||
119 | If you say Y here, the AppleTalk-IP code will be able to decapsulate | ||
120 | AppleTalk-IP frames to IP packets; this is useful if you want your | ||
121 | Linux box to act as an Internet gateway for an AppleTalk network. | ||
122 | Please see <file:Documentation/networking/ipddp.txt> for more | ||
123 | information. If you said Y to "AppleTalk-IP driver support" above | ||
124 | and you say Y here, then you cannot say Y to "IP to AppleTalk-IP | ||
125 | Encapsulation support", above. | ||
126 | |||
diff --git a/drivers/staging/appletalk/Makefile b/drivers/staging/appletalk/Makefile new file mode 100644 index 00000000000..2a5129a5c6b --- /dev/null +++ b/drivers/staging/appletalk/Makefile | |||
@@ -0,0 +1,12 @@ | |||
1 | # | ||
2 | # Makefile for drivers/staging/appletalk | ||
3 | # | ||
4 | obj-$(CONFIG_ATALK) += appletalk.o | ||
5 | |||
6 | appletalk-y := aarp.o ddp.o dev.o | ||
7 | appletalk-$(CONFIG_PROC_FS) += atalk_proc.o | ||
8 | appletalk-$(CONFIG_SYSCTL) += sysctl_net_atalk.o | ||
9 | |||
10 | obj-$(CONFIG_IPDDP) += ipddp.o | ||
11 | obj-$(CONFIG_COPS) += cops.o | ||
12 | obj-$(CONFIG_LTPC) += ltpc.o | ||
diff --git a/drivers/staging/appletalk/aarp.c b/drivers/staging/appletalk/aarp.c new file mode 100644 index 00000000000..7163a1dd501 --- /dev/null +++ b/drivers/staging/appletalk/aarp.c | |||
@@ -0,0 +1,1063 @@ | |||
1 | /* | ||
2 | * AARP: An implementation of the AppleTalk AARP protocol for | ||
3 | * Ethernet 'ELAP'. | ||
4 | * | ||
5 | * Alan Cox <Alan.Cox@linux.org> | ||
6 | * | ||
7 | * This doesn't fit cleanly with the IP arp. Potentially we can use | ||
8 | * the generic neighbour discovery code to clean this up. | ||
9 | * | ||
10 | * FIXME: | ||
11 | * We ought to handle the retransmits with a single list and a | ||
12 | * separate fast timer for when it is needed. | ||
13 | * Use neighbour discovery code. | ||
14 | * Token Ring Support. | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License | ||
18 | * as published by the Free Software Foundation; either version | ||
19 | * 2 of the License, or (at your option) any later version. | ||
20 | * | ||
21 | * | ||
22 | * References: | ||
23 | * Inside AppleTalk (2nd Ed). | ||
24 | * Fixes: | ||
25 | * Jaume Grau - flush caches on AARP_PROBE | ||
26 | * Rob Newberry - Added proxy AARP and AARP proc fs, | ||
27 | * moved probing from DDP module. | ||
28 | * Arnaldo C. Melo - don't mangle rx packets | ||
29 | * | ||
30 | */ | ||
31 | |||
32 | #include <linux/if_arp.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <net/sock.h> | ||
35 | #include <net/datalink.h> | ||
36 | #include <net/psnap.h> | ||
37 | #include "atalk.h" | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/init.h> | ||
40 | #include <linux/proc_fs.h> | ||
41 | #include <linux/seq_file.h> | ||
42 | |||
43 | int sysctl_aarp_expiry_time = AARP_EXPIRY_TIME; | ||
44 | int sysctl_aarp_tick_time = AARP_TICK_TIME; | ||
45 | int sysctl_aarp_retransmit_limit = AARP_RETRANSMIT_LIMIT; | ||
46 | int sysctl_aarp_resolve_time = AARP_RESOLVE_TIME; | ||
47 | |||
48 | /* Lists of aarp entries */ | ||
49 | /** | ||
50 | * struct aarp_entry - AARP entry | ||
51 | * @last_sent - Last time we xmitted the aarp request | ||
52 | * @packet_queue - Queue of frames wait for resolution | ||
53 | * @status - Used for proxy AARP | ||
54 | * expires_at - Entry expiry time | ||
55 | * target_addr - DDP Address | ||
56 | * dev - Device to use | ||
57 | * hwaddr - Physical i/f address of target/router | ||
58 | * xmit_count - When this hits 10 we give up | ||
59 | * next - Next entry in chain | ||
60 | */ | ||
61 | struct aarp_entry { | ||
62 | /* These first two are only used for unresolved entries */ | ||
63 | unsigned long last_sent; | ||
64 | struct sk_buff_head packet_queue; | ||
65 | int status; | ||
66 | unsigned long expires_at; | ||
67 | struct atalk_addr target_addr; | ||
68 | struct net_device *dev; | ||
69 | char hwaddr[6]; | ||
70 | unsigned short xmit_count; | ||
71 | struct aarp_entry *next; | ||
72 | }; | ||
73 | |||
74 | /* Hashed list of resolved, unresolved and proxy entries */ | ||
75 | static struct aarp_entry *resolved[AARP_HASH_SIZE]; | ||
76 | static struct aarp_entry *unresolved[AARP_HASH_SIZE]; | ||
77 | static struct aarp_entry *proxies[AARP_HASH_SIZE]; | ||
78 | static int unresolved_count; | ||
79 | |||
80 | /* One lock protects it all. */ | ||
81 | static DEFINE_RWLOCK(aarp_lock); | ||
82 | |||
83 | /* Used to walk the list and purge/kick entries. */ | ||
84 | static struct timer_list aarp_timer; | ||
85 | |||
86 | /* | ||
87 | * Delete an aarp queue | ||
88 | * | ||
89 | * Must run under aarp_lock. | ||
90 | */ | ||
91 | static void __aarp_expire(struct aarp_entry *a) | ||
92 | { | ||
93 | skb_queue_purge(&a->packet_queue); | ||
94 | kfree(a); | ||
95 | } | ||
96 | |||
97 | /* | ||
98 | * Send an aarp queue entry request | ||
99 | * | ||
100 | * Must run under aarp_lock. | ||
101 | */ | ||
102 | static void __aarp_send_query(struct aarp_entry *a) | ||
103 | { | ||
104 | static unsigned char aarp_eth_multicast[ETH_ALEN] = | ||
105 | { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; | ||
106 | struct net_device *dev = a->dev; | ||
107 | struct elapaarp *eah; | ||
108 | int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length; | ||
109 | struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); | ||
110 | struct atalk_addr *sat = atalk_find_dev_addr(dev); | ||
111 | |||
112 | if (!skb) | ||
113 | return; | ||
114 | |||
115 | if (!sat) { | ||
116 | kfree_skb(skb); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | /* Set up the buffer */ | ||
121 | skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); | ||
122 | skb_reset_network_header(skb); | ||
123 | skb_reset_transport_header(skb); | ||
124 | skb_put(skb, sizeof(*eah)); | ||
125 | skb->protocol = htons(ETH_P_ATALK); | ||
126 | skb->dev = dev; | ||
127 | eah = aarp_hdr(skb); | ||
128 | |||
129 | /* Set up the ARP */ | ||
130 | eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); | ||
131 | eah->pa_type = htons(ETH_P_ATALK); | ||
132 | eah->hw_len = ETH_ALEN; | ||
133 | eah->pa_len = AARP_PA_ALEN; | ||
134 | eah->function = htons(AARP_REQUEST); | ||
135 | |||
136 | memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); | ||
137 | |||
138 | eah->pa_src_zero = 0; | ||
139 | eah->pa_src_net = sat->s_net; | ||
140 | eah->pa_src_node = sat->s_node; | ||
141 | |||
142 | memset(eah->hw_dst, '\0', ETH_ALEN); | ||
143 | |||
144 | eah->pa_dst_zero = 0; | ||
145 | eah->pa_dst_net = a->target_addr.s_net; | ||
146 | eah->pa_dst_node = a->target_addr.s_node; | ||
147 | |||
148 | /* Send it */ | ||
149 | aarp_dl->request(aarp_dl, skb, aarp_eth_multicast); | ||
150 | /* Update the sending count */ | ||
151 | a->xmit_count++; | ||
152 | a->last_sent = jiffies; | ||
153 | } | ||
154 | |||
155 | /* This runs under aarp_lock and in softint context, so only atomic memory | ||
156 | * allocations can be used. */ | ||
157 | static void aarp_send_reply(struct net_device *dev, struct atalk_addr *us, | ||
158 | struct atalk_addr *them, unsigned char *sha) | ||
159 | { | ||
160 | struct elapaarp *eah; | ||
161 | int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length; | ||
162 | struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); | ||
163 | |||
164 | if (!skb) | ||
165 | return; | ||
166 | |||
167 | /* Set up the buffer */ | ||
168 | skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); | ||
169 | skb_reset_network_header(skb); | ||
170 | skb_reset_transport_header(skb); | ||
171 | skb_put(skb, sizeof(*eah)); | ||
172 | skb->protocol = htons(ETH_P_ATALK); | ||
173 | skb->dev = dev; | ||
174 | eah = aarp_hdr(skb); | ||
175 | |||
176 | /* Set up the ARP */ | ||
177 | eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); | ||
178 | eah->pa_type = htons(ETH_P_ATALK); | ||
179 | eah->hw_len = ETH_ALEN; | ||
180 | eah->pa_len = AARP_PA_ALEN; | ||
181 | eah->function = htons(AARP_REPLY); | ||
182 | |||
183 | memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); | ||
184 | |||
185 | eah->pa_src_zero = 0; | ||
186 | eah->pa_src_net = us->s_net; | ||
187 | eah->pa_src_node = us->s_node; | ||
188 | |||
189 | if (!sha) | ||
190 | memset(eah->hw_dst, '\0', ETH_ALEN); | ||
191 | else | ||
192 | memcpy(eah->hw_dst, sha, ETH_ALEN); | ||
193 | |||
194 | eah->pa_dst_zero = 0; | ||
195 | eah->pa_dst_net = them->s_net; | ||
196 | eah->pa_dst_node = them->s_node; | ||
197 | |||
198 | /* Send it */ | ||
199 | aarp_dl->request(aarp_dl, skb, sha); | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * Send probe frames. Called from aarp_probe_network and | ||
204 | * aarp_proxy_probe_network. | ||
205 | */ | ||
206 | |||
207 | static void aarp_send_probe(struct net_device *dev, struct atalk_addr *us) | ||
208 | { | ||
209 | struct elapaarp *eah; | ||
210 | int len = dev->hard_header_len + sizeof(*eah) + aarp_dl->header_length; | ||
211 | struct sk_buff *skb = alloc_skb(len, GFP_ATOMIC); | ||
212 | static unsigned char aarp_eth_multicast[ETH_ALEN] = | ||
213 | { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; | ||
214 | |||
215 | if (!skb) | ||
216 | return; | ||
217 | |||
218 | /* Set up the buffer */ | ||
219 | skb_reserve(skb, dev->hard_header_len + aarp_dl->header_length); | ||
220 | skb_reset_network_header(skb); | ||
221 | skb_reset_transport_header(skb); | ||
222 | skb_put(skb, sizeof(*eah)); | ||
223 | skb->protocol = htons(ETH_P_ATALK); | ||
224 | skb->dev = dev; | ||
225 | eah = aarp_hdr(skb); | ||
226 | |||
227 | /* Set up the ARP */ | ||
228 | eah->hw_type = htons(AARP_HW_TYPE_ETHERNET); | ||
229 | eah->pa_type = htons(ETH_P_ATALK); | ||
230 | eah->hw_len = ETH_ALEN; | ||
231 | eah->pa_len = AARP_PA_ALEN; | ||
232 | eah->function = htons(AARP_PROBE); | ||
233 | |||
234 | memcpy(eah->hw_src, dev->dev_addr, ETH_ALEN); | ||
235 | |||
236 | eah->pa_src_zero = 0; | ||
237 | eah->pa_src_net = us->s_net; | ||
238 | eah->pa_src_node = us->s_node; | ||
239 | |||
240 | memset(eah->hw_dst, '\0', ETH_ALEN); | ||
241 | |||
242 | eah->pa_dst_zero = 0; | ||
243 | eah->pa_dst_net = us->s_net; | ||
244 | eah->pa_dst_node = us->s_node; | ||
245 | |||
246 | /* Send it */ | ||
247 | aarp_dl->request(aarp_dl, skb, aarp_eth_multicast); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Handle an aarp timer expire | ||
252 | * | ||
253 | * Must run under the aarp_lock. | ||
254 | */ | ||
255 | |||
256 | static void __aarp_expire_timer(struct aarp_entry **n) | ||
257 | { | ||
258 | struct aarp_entry *t; | ||
259 | |||
260 | while (*n) | ||
261 | /* Expired ? */ | ||
262 | if (time_after(jiffies, (*n)->expires_at)) { | ||
263 | t = *n; | ||
264 | *n = (*n)->next; | ||
265 | __aarp_expire(t); | ||
266 | } else | ||
267 | n = &((*n)->next); | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * Kick all pending requests 5 times a second. | ||
272 | * | ||
273 | * Must run under the aarp_lock. | ||
274 | */ | ||
275 | static void __aarp_kick(struct aarp_entry **n) | ||
276 | { | ||
277 | struct aarp_entry *t; | ||
278 | |||
279 | while (*n) | ||
280 | /* Expired: if this will be the 11th tx, we delete instead. */ | ||
281 | if ((*n)->xmit_count >= sysctl_aarp_retransmit_limit) { | ||
282 | t = *n; | ||
283 | *n = (*n)->next; | ||
284 | __aarp_expire(t); | ||
285 | } else { | ||
286 | __aarp_send_query(*n); | ||
287 | n = &((*n)->next); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * A device has gone down. Take all entries referring to the device | ||
293 | * and remove them. | ||
294 | * | ||
295 | * Must run under the aarp_lock. | ||
296 | */ | ||
297 | static void __aarp_expire_device(struct aarp_entry **n, struct net_device *dev) | ||
298 | { | ||
299 | struct aarp_entry *t; | ||
300 | |||
301 | while (*n) | ||
302 | if ((*n)->dev == dev) { | ||
303 | t = *n; | ||
304 | *n = (*n)->next; | ||
305 | __aarp_expire(t); | ||
306 | } else | ||
307 | n = &((*n)->next); | ||
308 | } | ||
309 | |||
310 | /* Handle the timer event */ | ||
311 | static void aarp_expire_timeout(unsigned long unused) | ||
312 | { | ||
313 | int ct; | ||
314 | |||
315 | write_lock_bh(&aarp_lock); | ||
316 | |||
317 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { | ||
318 | __aarp_expire_timer(&resolved[ct]); | ||
319 | __aarp_kick(&unresolved[ct]); | ||
320 | __aarp_expire_timer(&unresolved[ct]); | ||
321 | __aarp_expire_timer(&proxies[ct]); | ||
322 | } | ||
323 | |||
324 | write_unlock_bh(&aarp_lock); | ||
325 | mod_timer(&aarp_timer, jiffies + | ||
326 | (unresolved_count ? sysctl_aarp_tick_time : | ||
327 | sysctl_aarp_expiry_time)); | ||
328 | } | ||
329 | |||
330 | /* Network device notifier chain handler. */ | ||
331 | static int aarp_device_event(struct notifier_block *this, unsigned long event, | ||
332 | void *ptr) | ||
333 | { | ||
334 | struct net_device *dev = ptr; | ||
335 | int ct; | ||
336 | |||
337 | if (!net_eq(dev_net(dev), &init_net)) | ||
338 | return NOTIFY_DONE; | ||
339 | |||
340 | if (event == NETDEV_DOWN) { | ||
341 | write_lock_bh(&aarp_lock); | ||
342 | |||
343 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { | ||
344 | __aarp_expire_device(&resolved[ct], dev); | ||
345 | __aarp_expire_device(&unresolved[ct], dev); | ||
346 | __aarp_expire_device(&proxies[ct], dev); | ||
347 | } | ||
348 | |||
349 | write_unlock_bh(&aarp_lock); | ||
350 | } | ||
351 | return NOTIFY_DONE; | ||
352 | } | ||
353 | |||
354 | /* Expire all entries in a hash chain */ | ||
355 | static void __aarp_expire_all(struct aarp_entry **n) | ||
356 | { | ||
357 | struct aarp_entry *t; | ||
358 | |||
359 | while (*n) { | ||
360 | t = *n; | ||
361 | *n = (*n)->next; | ||
362 | __aarp_expire(t); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /* Cleanup all hash chains -- module unloading */ | ||
367 | static void aarp_purge(void) | ||
368 | { | ||
369 | int ct; | ||
370 | |||
371 | write_lock_bh(&aarp_lock); | ||
372 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { | ||
373 | __aarp_expire_all(&resolved[ct]); | ||
374 | __aarp_expire_all(&unresolved[ct]); | ||
375 | __aarp_expire_all(&proxies[ct]); | ||
376 | } | ||
377 | write_unlock_bh(&aarp_lock); | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Create a new aarp entry. This must use GFP_ATOMIC because it | ||
382 | * runs while holding spinlocks. | ||
383 | */ | ||
384 | static struct aarp_entry *aarp_alloc(void) | ||
385 | { | ||
386 | struct aarp_entry *a = kmalloc(sizeof(*a), GFP_ATOMIC); | ||
387 | |||
388 | if (a) | ||
389 | skb_queue_head_init(&a->packet_queue); | ||
390 | return a; | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Find an entry. We might return an expired but not yet purged entry. We | ||
395 | * don't care as it will do no harm. | ||
396 | * | ||
397 | * This must run under the aarp_lock. | ||
398 | */ | ||
399 | static struct aarp_entry *__aarp_find_entry(struct aarp_entry *list, | ||
400 | struct net_device *dev, | ||
401 | struct atalk_addr *sat) | ||
402 | { | ||
403 | while (list) { | ||
404 | if (list->target_addr.s_net == sat->s_net && | ||
405 | list->target_addr.s_node == sat->s_node && | ||
406 | list->dev == dev) | ||
407 | break; | ||
408 | list = list->next; | ||
409 | } | ||
410 | |||
411 | return list; | ||
412 | } | ||
413 | |||
414 | /* Called from the DDP code, and thus must be exported. */ | ||
415 | void aarp_proxy_remove(struct net_device *dev, struct atalk_addr *sa) | ||
416 | { | ||
417 | int hash = sa->s_node % (AARP_HASH_SIZE - 1); | ||
418 | struct aarp_entry *a; | ||
419 | |||
420 | write_lock_bh(&aarp_lock); | ||
421 | |||
422 | a = __aarp_find_entry(proxies[hash], dev, sa); | ||
423 | if (a) | ||
424 | a->expires_at = jiffies - 1; | ||
425 | |||
426 | write_unlock_bh(&aarp_lock); | ||
427 | } | ||
428 | |||
429 | /* This must run under aarp_lock. */ | ||
430 | static struct atalk_addr *__aarp_proxy_find(struct net_device *dev, | ||
431 | struct atalk_addr *sa) | ||
432 | { | ||
433 | int hash = sa->s_node % (AARP_HASH_SIZE - 1); | ||
434 | struct aarp_entry *a = __aarp_find_entry(proxies[hash], dev, sa); | ||
435 | |||
436 | return a ? sa : NULL; | ||
437 | } | ||
438 | |||
439 | /* | ||
440 | * Probe a Phase 1 device or a device that requires its Net:Node to | ||
441 | * be set via an ioctl. | ||
442 | */ | ||
443 | static void aarp_send_probe_phase1(struct atalk_iface *iface) | ||
444 | { | ||
445 | struct ifreq atreq; | ||
446 | struct sockaddr_at *sa = (struct sockaddr_at *)&atreq.ifr_addr; | ||
447 | const struct net_device_ops *ops = iface->dev->netdev_ops; | ||
448 | |||
449 | sa->sat_addr.s_node = iface->address.s_node; | ||
450 | sa->sat_addr.s_net = ntohs(iface->address.s_net); | ||
451 | |||
452 | /* We pass the Net:Node to the drivers/cards by a Device ioctl. */ | ||
453 | if (!(ops->ndo_do_ioctl(iface->dev, &atreq, SIOCSIFADDR))) { | ||
454 | ops->ndo_do_ioctl(iface->dev, &atreq, SIOCGIFADDR); | ||
455 | if (iface->address.s_net != htons(sa->sat_addr.s_net) || | ||
456 | iface->address.s_node != sa->sat_addr.s_node) | ||
457 | iface->status |= ATIF_PROBE_FAIL; | ||
458 | |||
459 | iface->address.s_net = htons(sa->sat_addr.s_net); | ||
460 | iface->address.s_node = sa->sat_addr.s_node; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | |||
465 | void aarp_probe_network(struct atalk_iface *atif) | ||
466 | { | ||
467 | if (atif->dev->type == ARPHRD_LOCALTLK || | ||
468 | atif->dev->type == ARPHRD_PPP) | ||
469 | aarp_send_probe_phase1(atif); | ||
470 | else { | ||
471 | unsigned int count; | ||
472 | |||
473 | for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { | ||
474 | aarp_send_probe(atif->dev, &atif->address); | ||
475 | |||
476 | /* Defer 1/10th */ | ||
477 | msleep(100); | ||
478 | |||
479 | if (atif->status & ATIF_PROBE_FAIL) | ||
480 | break; | ||
481 | } | ||
482 | } | ||
483 | } | ||
484 | |||
485 | int aarp_proxy_probe_network(struct atalk_iface *atif, struct atalk_addr *sa) | ||
486 | { | ||
487 | int hash, retval = -EPROTONOSUPPORT; | ||
488 | struct aarp_entry *entry; | ||
489 | unsigned int count; | ||
490 | |||
491 | /* | ||
492 | * we don't currently support LocalTalk or PPP for proxy AARP; | ||
493 | * if someone wants to try and add it, have fun | ||
494 | */ | ||
495 | if (atif->dev->type == ARPHRD_LOCALTLK || | ||
496 | atif->dev->type == ARPHRD_PPP) | ||
497 | goto out; | ||
498 | |||
499 | /* | ||
500 | * create a new AARP entry with the flags set to be published -- | ||
501 | * we need this one to hang around even if it's in use | ||
502 | */ | ||
503 | entry = aarp_alloc(); | ||
504 | retval = -ENOMEM; | ||
505 | if (!entry) | ||
506 | goto out; | ||
507 | |||
508 | entry->expires_at = -1; | ||
509 | entry->status = ATIF_PROBE; | ||
510 | entry->target_addr.s_node = sa->s_node; | ||
511 | entry->target_addr.s_net = sa->s_net; | ||
512 | entry->dev = atif->dev; | ||
513 | |||
514 | write_lock_bh(&aarp_lock); | ||
515 | |||
516 | hash = sa->s_node % (AARP_HASH_SIZE - 1); | ||
517 | entry->next = proxies[hash]; | ||
518 | proxies[hash] = entry; | ||
519 | |||
520 | for (count = 0; count < AARP_RETRANSMIT_LIMIT; count++) { | ||
521 | aarp_send_probe(atif->dev, sa); | ||
522 | |||
523 | /* Defer 1/10th */ | ||
524 | write_unlock_bh(&aarp_lock); | ||
525 | msleep(100); | ||
526 | write_lock_bh(&aarp_lock); | ||
527 | |||
528 | if (entry->status & ATIF_PROBE_FAIL) | ||
529 | break; | ||
530 | } | ||
531 | |||
532 | if (entry->status & ATIF_PROBE_FAIL) { | ||
533 | entry->expires_at = jiffies - 1; /* free the entry */ | ||
534 | retval = -EADDRINUSE; /* return network full */ | ||
535 | } else { /* clear the probing flag */ | ||
536 | entry->status &= ~ATIF_PROBE; | ||
537 | retval = 1; | ||
538 | } | ||
539 | |||
540 | write_unlock_bh(&aarp_lock); | ||
541 | out: | ||
542 | return retval; | ||
543 | } | ||
544 | |||
545 | /* Send a DDP frame */ | ||
546 | int aarp_send_ddp(struct net_device *dev, struct sk_buff *skb, | ||
547 | struct atalk_addr *sa, void *hwaddr) | ||
548 | { | ||
549 | static char ddp_eth_multicast[ETH_ALEN] = | ||
550 | { 0x09, 0x00, 0x07, 0xFF, 0xFF, 0xFF }; | ||
551 | int hash; | ||
552 | struct aarp_entry *a; | ||
553 | |||
554 | skb_reset_network_header(skb); | ||
555 | |||
556 | /* Check for LocalTalk first */ | ||
557 | if (dev->type == ARPHRD_LOCALTLK) { | ||
558 | struct atalk_addr *at = atalk_find_dev_addr(dev); | ||
559 | struct ddpehdr *ddp = (struct ddpehdr *)skb->data; | ||
560 | int ft = 2; | ||
561 | |||
562 | /* | ||
563 | * Compressible ? | ||
564 | * | ||
565 | * IFF: src_net == dest_net == device_net | ||
566 | * (zero matches anything) | ||
567 | */ | ||
568 | |||
569 | if ((!ddp->deh_snet || at->s_net == ddp->deh_snet) && | ||
570 | (!ddp->deh_dnet || at->s_net == ddp->deh_dnet)) { | ||
571 | skb_pull(skb, sizeof(*ddp) - 4); | ||
572 | |||
573 | /* | ||
574 | * The upper two remaining bytes are the port | ||
575 | * numbers we just happen to need. Now put the | ||
576 | * length in the lower two. | ||
577 | */ | ||
578 | *((__be16 *)skb->data) = htons(skb->len); | ||
579 | ft = 1; | ||
580 | } | ||
581 | /* | ||
582 | * Nice and easy. No AARP type protocols occur here so we can | ||
583 | * just shovel it out with a 3 byte LLAP header | ||
584 | */ | ||
585 | |||
586 | skb_push(skb, 3); | ||
587 | skb->data[0] = sa->s_node; | ||
588 | skb->data[1] = at->s_node; | ||
589 | skb->data[2] = ft; | ||
590 | skb->dev = dev; | ||
591 | goto sendit; | ||
592 | } | ||
593 | |||
594 | /* On a PPP link we neither compress nor aarp. */ | ||
595 | if (dev->type == ARPHRD_PPP) { | ||
596 | skb->protocol = htons(ETH_P_PPPTALK); | ||
597 | skb->dev = dev; | ||
598 | goto sendit; | ||
599 | } | ||
600 | |||
601 | /* Non ELAP we cannot do. */ | ||
602 | if (dev->type != ARPHRD_ETHER) | ||
603 | goto free_it; | ||
604 | |||
605 | skb->dev = dev; | ||
606 | skb->protocol = htons(ETH_P_ATALK); | ||
607 | hash = sa->s_node % (AARP_HASH_SIZE - 1); | ||
608 | |||
609 | /* Do we have a resolved entry? */ | ||
610 | if (sa->s_node == ATADDR_BCAST) { | ||
611 | /* Send it */ | ||
612 | ddp_dl->request(ddp_dl, skb, ddp_eth_multicast); | ||
613 | goto sent; | ||
614 | } | ||
615 | |||
616 | write_lock_bh(&aarp_lock); | ||
617 | a = __aarp_find_entry(resolved[hash], dev, sa); | ||
618 | |||
619 | if (a) { /* Return 1 and fill in the address */ | ||
620 | a->expires_at = jiffies + (sysctl_aarp_expiry_time * 10); | ||
621 | ddp_dl->request(ddp_dl, skb, a->hwaddr); | ||
622 | write_unlock_bh(&aarp_lock); | ||
623 | goto sent; | ||
624 | } | ||
625 | |||
626 | /* Do we have an unresolved entry: This is the less common path */ | ||
627 | a = __aarp_find_entry(unresolved[hash], dev, sa); | ||
628 | if (a) { /* Queue onto the unresolved queue */ | ||
629 | skb_queue_tail(&a->packet_queue, skb); | ||
630 | goto out_unlock; | ||
631 | } | ||
632 | |||
633 | /* Allocate a new entry */ | ||
634 | a = aarp_alloc(); | ||
635 | if (!a) { | ||
636 | /* Whoops slipped... good job it's an unreliable protocol 8) */ | ||
637 | write_unlock_bh(&aarp_lock); | ||
638 | goto free_it; | ||
639 | } | ||
640 | |||
641 | /* Set up the queue */ | ||
642 | skb_queue_tail(&a->packet_queue, skb); | ||
643 | a->expires_at = jiffies + sysctl_aarp_resolve_time; | ||
644 | a->dev = dev; | ||
645 | a->next = unresolved[hash]; | ||
646 | a->target_addr = *sa; | ||
647 | a->xmit_count = 0; | ||
648 | unresolved[hash] = a; | ||
649 | unresolved_count++; | ||
650 | |||
651 | /* Send an initial request for the address */ | ||
652 | __aarp_send_query(a); | ||
653 | |||
654 | /* | ||
655 | * Switch to fast timer if needed (That is if this is the first | ||
656 | * unresolved entry to get added) | ||
657 | */ | ||
658 | |||
659 | if (unresolved_count == 1) | ||
660 | mod_timer(&aarp_timer, jiffies + sysctl_aarp_tick_time); | ||
661 | |||
662 | /* Now finally, it is safe to drop the lock. */ | ||
663 | out_unlock: | ||
664 | write_unlock_bh(&aarp_lock); | ||
665 | |||
666 | /* Tell the ddp layer we have taken over for this frame. */ | ||
667 | goto sent; | ||
668 | |||
669 | sendit: | ||
670 | if (skb->sk) | ||
671 | skb->priority = skb->sk->sk_priority; | ||
672 | if (dev_queue_xmit(skb)) | ||
673 | goto drop; | ||
674 | sent: | ||
675 | return NET_XMIT_SUCCESS; | ||
676 | free_it: | ||
677 | kfree_skb(skb); | ||
678 | drop: | ||
679 | return NET_XMIT_DROP; | ||
680 | } | ||
681 | EXPORT_SYMBOL(aarp_send_ddp); | ||
682 | |||
683 | /* | ||
684 | * An entry in the aarp unresolved queue has become resolved. Send | ||
685 | * all the frames queued under it. | ||
686 | * | ||
687 | * Must run under aarp_lock. | ||
688 | */ | ||
689 | static void __aarp_resolved(struct aarp_entry **list, struct aarp_entry *a, | ||
690 | int hash) | ||
691 | { | ||
692 | struct sk_buff *skb; | ||
693 | |||
694 | while (*list) | ||
695 | if (*list == a) { | ||
696 | unresolved_count--; | ||
697 | *list = a->next; | ||
698 | |||
699 | /* Move into the resolved list */ | ||
700 | a->next = resolved[hash]; | ||
701 | resolved[hash] = a; | ||
702 | |||
703 | /* Kick frames off */ | ||
704 | while ((skb = skb_dequeue(&a->packet_queue)) != NULL) { | ||
705 | a->expires_at = jiffies + | ||
706 | sysctl_aarp_expiry_time * 10; | ||
707 | ddp_dl->request(ddp_dl, skb, a->hwaddr); | ||
708 | } | ||
709 | } else | ||
710 | list = &((*list)->next); | ||
711 | } | ||
712 | |||
713 | /* | ||
714 | * This is called by the SNAP driver whenever we see an AARP SNAP | ||
715 | * frame. We currently only support Ethernet. | ||
716 | */ | ||
717 | static int aarp_rcv(struct sk_buff *skb, struct net_device *dev, | ||
718 | struct packet_type *pt, struct net_device *orig_dev) | ||
719 | { | ||
720 | struct elapaarp *ea = aarp_hdr(skb); | ||
721 | int hash, ret = 0; | ||
722 | __u16 function; | ||
723 | struct aarp_entry *a; | ||
724 | struct atalk_addr sa, *ma, da; | ||
725 | struct atalk_iface *ifa; | ||
726 | |||
727 | if (!net_eq(dev_net(dev), &init_net)) | ||
728 | goto out0; | ||
729 | |||
730 | /* We only do Ethernet SNAP AARP. */ | ||
731 | if (dev->type != ARPHRD_ETHER) | ||
732 | goto out0; | ||
733 | |||
734 | /* Frame size ok? */ | ||
735 | if (!skb_pull(skb, sizeof(*ea))) | ||
736 | goto out0; | ||
737 | |||
738 | function = ntohs(ea->function); | ||
739 | |||
740 | /* Sanity check fields. */ | ||
741 | if (function < AARP_REQUEST || function > AARP_PROBE || | ||
742 | ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN || | ||
743 | ea->pa_src_zero || ea->pa_dst_zero) | ||
744 | goto out0; | ||
745 | |||
746 | /* Looks good. */ | ||
747 | hash = ea->pa_src_node % (AARP_HASH_SIZE - 1); | ||
748 | |||
749 | /* Build an address. */ | ||
750 | sa.s_node = ea->pa_src_node; | ||
751 | sa.s_net = ea->pa_src_net; | ||
752 | |||
753 | /* Process the packet. Check for replies of me. */ | ||
754 | ifa = atalk_find_dev(dev); | ||
755 | if (!ifa) | ||
756 | goto out1; | ||
757 | |||
758 | if (ifa->status & ATIF_PROBE && | ||
759 | ifa->address.s_node == ea->pa_dst_node && | ||
760 | ifa->address.s_net == ea->pa_dst_net) { | ||
761 | ifa->status |= ATIF_PROBE_FAIL; /* Fail the probe (in use) */ | ||
762 | goto out1; | ||
763 | } | ||
764 | |||
765 | /* Check for replies of proxy AARP entries */ | ||
766 | da.s_node = ea->pa_dst_node; | ||
767 | da.s_net = ea->pa_dst_net; | ||
768 | |||
769 | write_lock_bh(&aarp_lock); | ||
770 | a = __aarp_find_entry(proxies[hash], dev, &da); | ||
771 | |||
772 | if (a && a->status & ATIF_PROBE) { | ||
773 | a->status |= ATIF_PROBE_FAIL; | ||
774 | /* | ||
775 | * we do not respond to probe or request packets for | ||
776 | * this address while we are probing this address | ||
777 | */ | ||
778 | goto unlock; | ||
779 | } | ||
780 | |||
781 | switch (function) { | ||
782 | case AARP_REPLY: | ||
783 | if (!unresolved_count) /* Speed up */ | ||
784 | break; | ||
785 | |||
786 | /* Find the entry. */ | ||
787 | a = __aarp_find_entry(unresolved[hash], dev, &sa); | ||
788 | if (!a || dev != a->dev) | ||
789 | break; | ||
790 | |||
791 | /* We can fill one in - this is good. */ | ||
792 | memcpy(a->hwaddr, ea->hw_src, ETH_ALEN); | ||
793 | __aarp_resolved(&unresolved[hash], a, hash); | ||
794 | if (!unresolved_count) | ||
795 | mod_timer(&aarp_timer, | ||
796 | jiffies + sysctl_aarp_expiry_time); | ||
797 | break; | ||
798 | |||
799 | case AARP_REQUEST: | ||
800 | case AARP_PROBE: | ||
801 | |||
802 | /* | ||
803 | * If it is my address set ma to my address and reply. | ||
804 | * We can treat probe and request the same. Probe | ||
805 | * simply means we shouldn't cache the querying host, | ||
806 | * as in a probe they are proposing an address not | ||
807 | * using one. | ||
808 | * | ||
809 | * Support for proxy-AARP added. We check if the | ||
810 | * address is one of our proxies before we toss the | ||
811 | * packet out. | ||
812 | */ | ||
813 | |||
814 | sa.s_node = ea->pa_dst_node; | ||
815 | sa.s_net = ea->pa_dst_net; | ||
816 | |||
817 | /* See if we have a matching proxy. */ | ||
818 | ma = __aarp_proxy_find(dev, &sa); | ||
819 | if (!ma) | ||
820 | ma = &ifa->address; | ||
821 | else { /* We need to make a copy of the entry. */ | ||
822 | da.s_node = sa.s_node; | ||
823 | da.s_net = sa.s_net; | ||
824 | ma = &da; | ||
825 | } | ||
826 | |||
827 | if (function == AARP_PROBE) { | ||
828 | /* | ||
829 | * A probe implies someone trying to get an | ||
830 | * address. So as a precaution flush any | ||
831 | * entries we have for this address. | ||
832 | */ | ||
833 | a = __aarp_find_entry(resolved[sa.s_node % | ||
834 | (AARP_HASH_SIZE - 1)], | ||
835 | skb->dev, &sa); | ||
836 | |||
837 | /* | ||
838 | * Make it expire next tick - that avoids us | ||
839 | * getting into a probe/flush/learn/probe/ | ||
840 | * flush/learn cycle during probing of a slow | ||
841 | * to respond host addr. | ||
842 | */ | ||
843 | if (a) { | ||
844 | a->expires_at = jiffies - 1; | ||
845 | mod_timer(&aarp_timer, jiffies + | ||
846 | sysctl_aarp_tick_time); | ||
847 | } | ||
848 | } | ||
849 | |||
850 | if (sa.s_node != ma->s_node) | ||
851 | break; | ||
852 | |||
853 | if (sa.s_net && ma->s_net && sa.s_net != ma->s_net) | ||
854 | break; | ||
855 | |||
856 | sa.s_node = ea->pa_src_node; | ||
857 | sa.s_net = ea->pa_src_net; | ||
858 | |||
859 | /* aarp_my_address has found the address to use for us. | ||
860 | */ | ||
861 | aarp_send_reply(dev, ma, &sa, ea->hw_src); | ||
862 | break; | ||
863 | } | ||
864 | |||
865 | unlock: | ||
866 | write_unlock_bh(&aarp_lock); | ||
867 | out1: | ||
868 | ret = 1; | ||
869 | out0: | ||
870 | kfree_skb(skb); | ||
871 | return ret; | ||
872 | } | ||
873 | |||
874 | static struct notifier_block aarp_notifier = { | ||
875 | .notifier_call = aarp_device_event, | ||
876 | }; | ||
877 | |||
878 | static unsigned char aarp_snap_id[] = { 0x00, 0x00, 0x00, 0x80, 0xF3 }; | ||
879 | |||
880 | void __init aarp_proto_init(void) | ||
881 | { | ||
882 | aarp_dl = register_snap_client(aarp_snap_id, aarp_rcv); | ||
883 | if (!aarp_dl) | ||
884 | printk(KERN_CRIT "Unable to register AARP with SNAP.\n"); | ||
885 | setup_timer(&aarp_timer, aarp_expire_timeout, 0); | ||
886 | aarp_timer.expires = jiffies + sysctl_aarp_expiry_time; | ||
887 | add_timer(&aarp_timer); | ||
888 | register_netdevice_notifier(&aarp_notifier); | ||
889 | } | ||
890 | |||
891 | /* Remove the AARP entries associated with a device. */ | ||
892 | void aarp_device_down(struct net_device *dev) | ||
893 | { | ||
894 | int ct; | ||
895 | |||
896 | write_lock_bh(&aarp_lock); | ||
897 | |||
898 | for (ct = 0; ct < AARP_HASH_SIZE; ct++) { | ||
899 | __aarp_expire_device(&resolved[ct], dev); | ||
900 | __aarp_expire_device(&unresolved[ct], dev); | ||
901 | __aarp_expire_device(&proxies[ct], dev); | ||
902 | } | ||
903 | |||
904 | write_unlock_bh(&aarp_lock); | ||
905 | } | ||
906 | |||
907 | #ifdef CONFIG_PROC_FS | ||
908 | struct aarp_iter_state { | ||
909 | int bucket; | ||
910 | struct aarp_entry **table; | ||
911 | }; | ||
912 | |||
913 | /* | ||
914 | * Get the aarp entry that is in the chain described | ||
915 | * by the iterator. | ||
916 | * If pos is set then skip till that index. | ||
917 | * pos = 1 is the first entry | ||
918 | */ | ||
919 | static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos) | ||
920 | { | ||
921 | int ct = iter->bucket; | ||
922 | struct aarp_entry **table = iter->table; | ||
923 | loff_t off = 0; | ||
924 | struct aarp_entry *entry; | ||
925 | |||
926 | rescan: | ||
927 | while(ct < AARP_HASH_SIZE) { | ||
928 | for (entry = table[ct]; entry; entry = entry->next) { | ||
929 | if (!pos || ++off == *pos) { | ||
930 | iter->table = table; | ||
931 | iter->bucket = ct; | ||
932 | return entry; | ||
933 | } | ||
934 | } | ||
935 | ++ct; | ||
936 | } | ||
937 | |||
938 | if (table == resolved) { | ||
939 | ct = 0; | ||
940 | table = unresolved; | ||
941 | goto rescan; | ||
942 | } | ||
943 | if (table == unresolved) { | ||
944 | ct = 0; | ||
945 | table = proxies; | ||
946 | goto rescan; | ||
947 | } | ||
948 | return NULL; | ||
949 | } | ||
950 | |||
951 | static void *aarp_seq_start(struct seq_file *seq, loff_t *pos) | ||
952 | __acquires(aarp_lock) | ||
953 | { | ||
954 | struct aarp_iter_state *iter = seq->private; | ||
955 | |||
956 | read_lock_bh(&aarp_lock); | ||
957 | iter->table = resolved; | ||
958 | iter->bucket = 0; | ||
959 | |||
960 | return *pos ? iter_next(iter, pos) : SEQ_START_TOKEN; | ||
961 | } | ||
962 | |||
963 | static void *aarp_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
964 | { | ||
965 | struct aarp_entry *entry = v; | ||
966 | struct aarp_iter_state *iter = seq->private; | ||
967 | |||
968 | ++*pos; | ||
969 | |||
970 | /* first line after header */ | ||
971 | if (v == SEQ_START_TOKEN) | ||
972 | entry = iter_next(iter, NULL); | ||
973 | |||
974 | /* next entry in current bucket */ | ||
975 | else if (entry->next) | ||
976 | entry = entry->next; | ||
977 | |||
978 | /* next bucket or table */ | ||
979 | else { | ||
980 | ++iter->bucket; | ||
981 | entry = iter_next(iter, NULL); | ||
982 | } | ||
983 | return entry; | ||
984 | } | ||
985 | |||
986 | static void aarp_seq_stop(struct seq_file *seq, void *v) | ||
987 | __releases(aarp_lock) | ||
988 | { | ||
989 | read_unlock_bh(&aarp_lock); | ||
990 | } | ||
991 | |||
992 | static const char *dt2str(unsigned long ticks) | ||
993 | { | ||
994 | static char buf[32]; | ||
995 | |||
996 | sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ); | ||
997 | |||
998 | return buf; | ||
999 | } | ||
1000 | |||
1001 | static int aarp_seq_show(struct seq_file *seq, void *v) | ||
1002 | { | ||
1003 | struct aarp_iter_state *iter = seq->private; | ||
1004 | struct aarp_entry *entry = v; | ||
1005 | unsigned long now = jiffies; | ||
1006 | |||
1007 | if (v == SEQ_START_TOKEN) | ||
1008 | seq_puts(seq, | ||
1009 | "Address Interface Hardware Address" | ||
1010 | " Expires LastSend Retry Status\n"); | ||
1011 | else { | ||
1012 | seq_printf(seq, "%04X:%02X %-12s", | ||
1013 | ntohs(entry->target_addr.s_net), | ||
1014 | (unsigned int) entry->target_addr.s_node, | ||
1015 | entry->dev ? entry->dev->name : "????"); | ||
1016 | seq_printf(seq, "%pM", entry->hwaddr); | ||
1017 | seq_printf(seq, " %8s", | ||
1018 | dt2str((long)entry->expires_at - (long)now)); | ||
1019 | if (iter->table == unresolved) | ||
1020 | seq_printf(seq, " %8s %6hu", | ||
1021 | dt2str(now - entry->last_sent), | ||
1022 | entry->xmit_count); | ||
1023 | else | ||
1024 | seq_puts(seq, " "); | ||
1025 | seq_printf(seq, " %s\n", | ||
1026 | (iter->table == resolved) ? "resolved" | ||
1027 | : (iter->table == unresolved) ? "unresolved" | ||
1028 | : (iter->table == proxies) ? "proxies" | ||
1029 | : "unknown"); | ||
1030 | } | ||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | static const struct seq_operations aarp_seq_ops = { | ||
1035 | .start = aarp_seq_start, | ||
1036 | .next = aarp_seq_next, | ||
1037 | .stop = aarp_seq_stop, | ||
1038 | .show = aarp_seq_show, | ||
1039 | }; | ||
1040 | |||
1041 | static int aarp_seq_open(struct inode *inode, struct file *file) | ||
1042 | { | ||
1043 | return seq_open_private(file, &aarp_seq_ops, | ||
1044 | sizeof(struct aarp_iter_state)); | ||
1045 | } | ||
1046 | |||
1047 | const struct file_operations atalk_seq_arp_fops = { | ||
1048 | .owner = THIS_MODULE, | ||
1049 | .open = aarp_seq_open, | ||
1050 | .read = seq_read, | ||
1051 | .llseek = seq_lseek, | ||
1052 | .release = seq_release_private, | ||
1053 | }; | ||
1054 | #endif | ||
1055 | |||
1056 | /* General module cleanup. Called from cleanup_module() in ddp.c. */ | ||
1057 | void aarp_cleanup_module(void) | ||
1058 | { | ||
1059 | del_timer_sync(&aarp_timer); | ||
1060 | unregister_netdevice_notifier(&aarp_notifier); | ||
1061 | unregister_snap_client(aarp_dl); | ||
1062 | aarp_purge(); | ||
1063 | } | ||
diff --git a/drivers/staging/appletalk/atalk.h b/drivers/staging/appletalk/atalk.h new file mode 100644 index 00000000000..d34c187432e --- /dev/null +++ b/drivers/staging/appletalk/atalk.h | |||
@@ -0,0 +1,208 @@ | |||
1 | #ifndef __LINUX_ATALK_H__ | ||
2 | #define __LINUX_ATALK_H__ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <asm/byteorder.h> | ||
6 | |||
7 | /* | ||
8 | * AppleTalk networking structures | ||
9 | * | ||
10 | * The following are directly referenced from the University Of Michigan | ||
11 | * netatalk for compatibility reasons. | ||
12 | */ | ||
13 | #define ATPORT_FIRST 1 | ||
14 | #define ATPORT_RESERVED 128 | ||
15 | #define ATPORT_LAST 254 /* 254 is only legal on localtalk */ | ||
16 | #define ATADDR_ANYNET (__u16)0 | ||
17 | #define ATADDR_ANYNODE (__u8)0 | ||
18 | #define ATADDR_ANYPORT (__u8)0 | ||
19 | #define ATADDR_BCAST (__u8)255 | ||
20 | #define DDP_MAXSZ 587 | ||
21 | #define DDP_MAXHOPS 15 /* 4 bits of hop counter */ | ||
22 | |||
23 | #define SIOCATALKDIFADDR (SIOCPROTOPRIVATE + 0) | ||
24 | |||
25 | struct atalk_addr { | ||
26 | __be16 s_net; | ||
27 | __u8 s_node; | ||
28 | }; | ||
29 | |||
30 | struct sockaddr_at { | ||
31 | sa_family_t sat_family; | ||
32 | __u8 sat_port; | ||
33 | struct atalk_addr sat_addr; | ||
34 | char sat_zero[8]; | ||
35 | }; | ||
36 | |||
37 | struct atalk_netrange { | ||
38 | __u8 nr_phase; | ||
39 | __be16 nr_firstnet; | ||
40 | __be16 nr_lastnet; | ||
41 | }; | ||
42 | |||
43 | #ifdef __KERNEL__ | ||
44 | |||
45 | #include <net/sock.h> | ||
46 | |||
47 | struct atalk_route { | ||
48 | struct net_device *dev; | ||
49 | struct atalk_addr target; | ||
50 | struct atalk_addr gateway; | ||
51 | int flags; | ||
52 | struct atalk_route *next; | ||
53 | }; | ||
54 | |||
55 | /** | ||
56 | * struct atalk_iface - AppleTalk Interface | ||
57 | * @dev - Network device associated with this interface | ||
58 | * @address - Our address | ||
59 | * @status - What are we doing? | ||
60 | * @nets - Associated direct netrange | ||
61 | * @next - next element in the list of interfaces | ||
62 | */ | ||
63 | struct atalk_iface { | ||
64 | struct net_device *dev; | ||
65 | struct atalk_addr address; | ||
66 | int status; | ||
67 | #define ATIF_PROBE 1 /* Probing for an address */ | ||
68 | #define ATIF_PROBE_FAIL 2 /* Probe collided */ | ||
69 | struct atalk_netrange nets; | ||
70 | struct atalk_iface *next; | ||
71 | }; | ||
72 | |||
73 | struct atalk_sock { | ||
74 | /* struct sock has to be the first member of atalk_sock */ | ||
75 | struct sock sk; | ||
76 | __be16 dest_net; | ||
77 | __be16 src_net; | ||
78 | unsigned char dest_node; | ||
79 | unsigned char src_node; | ||
80 | unsigned char dest_port; | ||
81 | unsigned char src_port; | ||
82 | }; | ||
83 | |||
84 | static inline struct atalk_sock *at_sk(struct sock *sk) | ||
85 | { | ||
86 | return (struct atalk_sock *)sk; | ||
87 | } | ||
88 | |||
89 | struct ddpehdr { | ||
90 | __be16 deh_len_hops; /* lower 10 bits are length, next 4 - hops */ | ||
91 | __be16 deh_sum; | ||
92 | __be16 deh_dnet; | ||
93 | __be16 deh_snet; | ||
94 | __u8 deh_dnode; | ||
95 | __u8 deh_snode; | ||
96 | __u8 deh_dport; | ||
97 | __u8 deh_sport; | ||
98 | /* And netatalk apps expect to stick the type in themselves */ | ||
99 | }; | ||
100 | |||
101 | static __inline__ struct ddpehdr *ddp_hdr(struct sk_buff *skb) | ||
102 | { | ||
103 | return (struct ddpehdr *)skb_transport_header(skb); | ||
104 | } | ||
105 | |||
106 | /* AppleTalk AARP headers */ | ||
107 | struct elapaarp { | ||
108 | __be16 hw_type; | ||
109 | #define AARP_HW_TYPE_ETHERNET 1 | ||
110 | #define AARP_HW_TYPE_TOKENRING 2 | ||
111 | __be16 pa_type; | ||
112 | __u8 hw_len; | ||
113 | __u8 pa_len; | ||
114 | #define AARP_PA_ALEN 4 | ||
115 | __be16 function; | ||
116 | #define AARP_REQUEST 1 | ||
117 | #define AARP_REPLY 2 | ||
118 | #define AARP_PROBE 3 | ||
119 | __u8 hw_src[ETH_ALEN]; | ||
120 | __u8 pa_src_zero; | ||
121 | __be16 pa_src_net; | ||
122 | __u8 pa_src_node; | ||
123 | __u8 hw_dst[ETH_ALEN]; | ||
124 | __u8 pa_dst_zero; | ||
125 | __be16 pa_dst_net; | ||
126 | __u8 pa_dst_node; | ||
127 | } __attribute__ ((packed)); | ||
128 | |||
129 | static __inline__ struct elapaarp *aarp_hdr(struct sk_buff *skb) | ||
130 | { | ||
131 | return (struct elapaarp *)skb_transport_header(skb); | ||
132 | } | ||
133 | |||
134 | /* Not specified - how long till we drop a resolved entry */ | ||
135 | #define AARP_EXPIRY_TIME (5 * 60 * HZ) | ||
136 | /* Size of hash table */ | ||
137 | #define AARP_HASH_SIZE 16 | ||
138 | /* Fast retransmission timer when resolving */ | ||
139 | #define AARP_TICK_TIME (HZ / 5) | ||
140 | /* Send 10 requests then give up (2 seconds) */ | ||
141 | #define AARP_RETRANSMIT_LIMIT 10 | ||
142 | /* | ||
143 | * Some value bigger than total retransmit time + a bit for last reply to | ||
144 | * appear and to stop continual requests | ||
145 | */ | ||
146 | #define AARP_RESOLVE_TIME (10 * HZ) | ||
147 | |||
148 | extern struct datalink_proto *ddp_dl, *aarp_dl; | ||
149 | extern void aarp_proto_init(void); | ||
150 | |||
151 | /* Inter module exports */ | ||
152 | |||
153 | /* Give a device find its atif control structure */ | ||
154 | static inline struct atalk_iface *atalk_find_dev(struct net_device *dev) | ||
155 | { | ||
156 | return dev->atalk_ptr; | ||
157 | } | ||
158 | |||
159 | extern struct atalk_addr *atalk_find_dev_addr(struct net_device *dev); | ||
160 | extern struct net_device *atrtr_get_dev(struct atalk_addr *sa); | ||
161 | extern int aarp_send_ddp(struct net_device *dev, | ||
162 | struct sk_buff *skb, | ||
163 | struct atalk_addr *sa, void *hwaddr); | ||
164 | extern void aarp_device_down(struct net_device *dev); | ||
165 | extern void aarp_probe_network(struct atalk_iface *atif); | ||
166 | extern int aarp_proxy_probe_network(struct atalk_iface *atif, | ||
167 | struct atalk_addr *sa); | ||
168 | extern void aarp_proxy_remove(struct net_device *dev, | ||
169 | struct atalk_addr *sa); | ||
170 | |||
171 | extern void aarp_cleanup_module(void); | ||
172 | |||
173 | extern struct hlist_head atalk_sockets; | ||
174 | extern rwlock_t atalk_sockets_lock; | ||
175 | |||
176 | extern struct atalk_route *atalk_routes; | ||
177 | extern rwlock_t atalk_routes_lock; | ||
178 | |||
179 | extern struct atalk_iface *atalk_interfaces; | ||
180 | extern rwlock_t atalk_interfaces_lock; | ||
181 | |||
182 | extern struct atalk_route atrtr_default; | ||
183 | |||
184 | extern const struct file_operations atalk_seq_arp_fops; | ||
185 | |||
186 | extern int sysctl_aarp_expiry_time; | ||
187 | extern int sysctl_aarp_tick_time; | ||
188 | extern int sysctl_aarp_retransmit_limit; | ||
189 | extern int sysctl_aarp_resolve_time; | ||
190 | |||
191 | #ifdef CONFIG_SYSCTL | ||
192 | extern void atalk_register_sysctl(void); | ||
193 | extern void atalk_unregister_sysctl(void); | ||
194 | #else | ||
195 | #define atalk_register_sysctl() do { } while(0) | ||
196 | #define atalk_unregister_sysctl() do { } while(0) | ||
197 | #endif | ||
198 | |||
199 | #ifdef CONFIG_PROC_FS | ||
200 | extern int atalk_proc_init(void); | ||
201 | extern void atalk_proc_exit(void); | ||
202 | #else | ||
203 | #define atalk_proc_init() ({ 0; }) | ||
204 | #define atalk_proc_exit() do { } while(0) | ||
205 | #endif /* CONFIG_PROC_FS */ | ||
206 | |||
207 | #endif /* __KERNEL__ */ | ||
208 | #endif /* __LINUX_ATALK_H__ */ | ||
diff --git a/drivers/staging/appletalk/atalk_proc.c b/drivers/staging/appletalk/atalk_proc.c new file mode 100644 index 00000000000..d012ba2e67d --- /dev/null +++ b/drivers/staging/appletalk/atalk_proc.c | |||
@@ -0,0 +1,301 @@ | |||
1 | /* | ||
2 | * atalk_proc.c - proc support for Appletalk | ||
3 | * | ||
4 | * Copyright(c) Arnaldo Carvalho de Melo <acme@conectiva.com.br> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation, version 2. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/proc_fs.h> | ||
13 | #include <linux/seq_file.h> | ||
14 | #include <net/net_namespace.h> | ||
15 | #include <net/sock.h> | ||
16 | #include "atalk.h" | ||
17 | |||
18 | |||
19 | static __inline__ struct atalk_iface *atalk_get_interface_idx(loff_t pos) | ||
20 | { | ||
21 | struct atalk_iface *i; | ||
22 | |||
23 | for (i = atalk_interfaces; pos && i; i = i->next) | ||
24 | --pos; | ||
25 | |||
26 | return i; | ||
27 | } | ||
28 | |||
29 | static void *atalk_seq_interface_start(struct seq_file *seq, loff_t *pos) | ||
30 | __acquires(atalk_interfaces_lock) | ||
31 | { | ||
32 | loff_t l = *pos; | ||
33 | |||
34 | read_lock_bh(&atalk_interfaces_lock); | ||
35 | return l ? atalk_get_interface_idx(--l) : SEQ_START_TOKEN; | ||
36 | } | ||
37 | |||
38 | static void *atalk_seq_interface_next(struct seq_file *seq, void *v, loff_t *pos) | ||
39 | { | ||
40 | struct atalk_iface *i; | ||
41 | |||
42 | ++*pos; | ||
43 | if (v == SEQ_START_TOKEN) { | ||
44 | i = NULL; | ||
45 | if (atalk_interfaces) | ||
46 | i = atalk_interfaces; | ||
47 | goto out; | ||
48 | } | ||
49 | i = v; | ||
50 | i = i->next; | ||
51 | out: | ||
52 | return i; | ||
53 | } | ||
54 | |||
55 | static void atalk_seq_interface_stop(struct seq_file *seq, void *v) | ||
56 | __releases(atalk_interfaces_lock) | ||
57 | { | ||
58 | read_unlock_bh(&atalk_interfaces_lock); | ||
59 | } | ||
60 | |||
61 | static int atalk_seq_interface_show(struct seq_file *seq, void *v) | ||
62 | { | ||
63 | struct atalk_iface *iface; | ||
64 | |||
65 | if (v == SEQ_START_TOKEN) { | ||
66 | seq_puts(seq, "Interface Address Networks " | ||
67 | "Status\n"); | ||
68 | goto out; | ||
69 | } | ||
70 | |||
71 | iface = v; | ||
72 | seq_printf(seq, "%-16s %04X:%02X %04X-%04X %d\n", | ||
73 | iface->dev->name, ntohs(iface->address.s_net), | ||
74 | iface->address.s_node, ntohs(iface->nets.nr_firstnet), | ||
75 | ntohs(iface->nets.nr_lastnet), iface->status); | ||
76 | out: | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static __inline__ struct atalk_route *atalk_get_route_idx(loff_t pos) | ||
81 | { | ||
82 | struct atalk_route *r; | ||
83 | |||
84 | for (r = atalk_routes; pos && r; r = r->next) | ||
85 | --pos; | ||
86 | |||
87 | return r; | ||
88 | } | ||
89 | |||
90 | static void *atalk_seq_route_start(struct seq_file *seq, loff_t *pos) | ||
91 | __acquires(atalk_routes_lock) | ||
92 | { | ||
93 | loff_t l = *pos; | ||
94 | |||
95 | read_lock_bh(&atalk_routes_lock); | ||
96 | return l ? atalk_get_route_idx(--l) : SEQ_START_TOKEN; | ||
97 | } | ||
98 | |||
99 | static void *atalk_seq_route_next(struct seq_file *seq, void *v, loff_t *pos) | ||
100 | { | ||
101 | struct atalk_route *r; | ||
102 | |||
103 | ++*pos; | ||
104 | if (v == SEQ_START_TOKEN) { | ||
105 | r = NULL; | ||
106 | if (atalk_routes) | ||
107 | r = atalk_routes; | ||
108 | goto out; | ||
109 | } | ||
110 | r = v; | ||
111 | r = r->next; | ||
112 | out: | ||
113 | return r; | ||
114 | } | ||
115 | |||
116 | static void atalk_seq_route_stop(struct seq_file *seq, void *v) | ||
117 | __releases(atalk_routes_lock) | ||
118 | { | ||
119 | read_unlock_bh(&atalk_routes_lock); | ||
120 | } | ||
121 | |||
122 | static int atalk_seq_route_show(struct seq_file *seq, void *v) | ||
123 | { | ||
124 | struct atalk_route *rt; | ||
125 | |||
126 | if (v == SEQ_START_TOKEN) { | ||
127 | seq_puts(seq, "Target Router Flags Dev\n"); | ||
128 | goto out; | ||
129 | } | ||
130 | |||
131 | if (atrtr_default.dev) { | ||
132 | rt = &atrtr_default; | ||
133 | seq_printf(seq, "Default %04X:%02X %-4d %s\n", | ||
134 | ntohs(rt->gateway.s_net), rt->gateway.s_node, | ||
135 | rt->flags, rt->dev->name); | ||
136 | } | ||
137 | |||
138 | rt = v; | ||
139 | seq_printf(seq, "%04X:%02X %04X:%02X %-4d %s\n", | ||
140 | ntohs(rt->target.s_net), rt->target.s_node, | ||
141 | ntohs(rt->gateway.s_net), rt->gateway.s_node, | ||
142 | rt->flags, rt->dev->name); | ||
143 | out: | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static void *atalk_seq_socket_start(struct seq_file *seq, loff_t *pos) | ||
148 | __acquires(atalk_sockets_lock) | ||
149 | { | ||
150 | read_lock_bh(&atalk_sockets_lock); | ||
151 | return seq_hlist_start_head(&atalk_sockets, *pos); | ||
152 | } | ||
153 | |||
154 | static void *atalk_seq_socket_next(struct seq_file *seq, void *v, loff_t *pos) | ||
155 | { | ||
156 | return seq_hlist_next(v, &atalk_sockets, pos); | ||
157 | } | ||
158 | |||
159 | static void atalk_seq_socket_stop(struct seq_file *seq, void *v) | ||
160 | __releases(atalk_sockets_lock) | ||
161 | { | ||
162 | read_unlock_bh(&atalk_sockets_lock); | ||
163 | } | ||
164 | |||
165 | static int atalk_seq_socket_show(struct seq_file *seq, void *v) | ||
166 | { | ||
167 | struct sock *s; | ||
168 | struct atalk_sock *at; | ||
169 | |||
170 | if (v == SEQ_START_TOKEN) { | ||
171 | seq_printf(seq, "Type Local_addr Remote_addr Tx_queue " | ||
172 | "Rx_queue St UID\n"); | ||
173 | goto out; | ||
174 | } | ||
175 | |||
176 | s = sk_entry(v); | ||
177 | at = at_sk(s); | ||
178 | |||
179 | seq_printf(seq, "%02X %04X:%02X:%02X %04X:%02X:%02X %08X:%08X " | ||
180 | "%02X %d\n", | ||
181 | s->sk_type, ntohs(at->src_net), at->src_node, at->src_port, | ||
182 | ntohs(at->dest_net), at->dest_node, at->dest_port, | ||
183 | sk_wmem_alloc_get(s), | ||
184 | sk_rmem_alloc_get(s), | ||
185 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | ||
186 | out: | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static const struct seq_operations atalk_seq_interface_ops = { | ||
191 | .start = atalk_seq_interface_start, | ||
192 | .next = atalk_seq_interface_next, | ||
193 | .stop = atalk_seq_interface_stop, | ||
194 | .show = atalk_seq_interface_show, | ||
195 | }; | ||
196 | |||
197 | static const struct seq_operations atalk_seq_route_ops = { | ||
198 | .start = atalk_seq_route_start, | ||
199 | .next = atalk_seq_route_next, | ||
200 | .stop = atalk_seq_route_stop, | ||
201 | .show = atalk_seq_route_show, | ||
202 | }; | ||
203 | |||
204 | static const struct seq_operations atalk_seq_socket_ops = { | ||
205 | .start = atalk_seq_socket_start, | ||
206 | .next = atalk_seq_socket_next, | ||
207 | .stop = atalk_seq_socket_stop, | ||
208 | .show = atalk_seq_socket_show, | ||
209 | }; | ||
210 | |||
211 | static int atalk_seq_interface_open(struct inode *inode, struct file *file) | ||
212 | { | ||
213 | return seq_open(file, &atalk_seq_interface_ops); | ||
214 | } | ||
215 | |||
216 | static int atalk_seq_route_open(struct inode *inode, struct file *file) | ||
217 | { | ||
218 | return seq_open(file, &atalk_seq_route_ops); | ||
219 | } | ||
220 | |||
221 | static int atalk_seq_socket_open(struct inode *inode, struct file *file) | ||
222 | { | ||
223 | return seq_open(file, &atalk_seq_socket_ops); | ||
224 | } | ||
225 | |||
226 | static const struct file_operations atalk_seq_interface_fops = { | ||
227 | .owner = THIS_MODULE, | ||
228 | .open = atalk_seq_interface_open, | ||
229 | .read = seq_read, | ||
230 | .llseek = seq_lseek, | ||
231 | .release = seq_release, | ||
232 | }; | ||
233 | |||
234 | static const struct file_operations atalk_seq_route_fops = { | ||
235 | .owner = THIS_MODULE, | ||
236 | .open = atalk_seq_route_open, | ||
237 | .read = seq_read, | ||
238 | .llseek = seq_lseek, | ||
239 | .release = seq_release, | ||
240 | }; | ||
241 | |||
242 | static const struct file_operations atalk_seq_socket_fops = { | ||
243 | .owner = THIS_MODULE, | ||
244 | .open = atalk_seq_socket_open, | ||
245 | .read = seq_read, | ||
246 | .llseek = seq_lseek, | ||
247 | .release = seq_release, | ||
248 | }; | ||
249 | |||
250 | static struct proc_dir_entry *atalk_proc_dir; | ||
251 | |||
252 | int __init atalk_proc_init(void) | ||
253 | { | ||
254 | struct proc_dir_entry *p; | ||
255 | int rc = -ENOMEM; | ||
256 | |||
257 | atalk_proc_dir = proc_mkdir("atalk", init_net.proc_net); | ||
258 | if (!atalk_proc_dir) | ||
259 | goto out; | ||
260 | |||
261 | p = proc_create("interface", S_IRUGO, atalk_proc_dir, | ||
262 | &atalk_seq_interface_fops); | ||
263 | if (!p) | ||
264 | goto out_interface; | ||
265 | |||
266 | p = proc_create("route", S_IRUGO, atalk_proc_dir, | ||
267 | &atalk_seq_route_fops); | ||
268 | if (!p) | ||
269 | goto out_route; | ||
270 | |||
271 | p = proc_create("socket", S_IRUGO, atalk_proc_dir, | ||
272 | &atalk_seq_socket_fops); | ||
273 | if (!p) | ||
274 | goto out_socket; | ||
275 | |||
276 | p = proc_create("arp", S_IRUGO, atalk_proc_dir, &atalk_seq_arp_fops); | ||
277 | if (!p) | ||
278 | goto out_arp; | ||
279 | |||
280 | rc = 0; | ||
281 | out: | ||
282 | return rc; | ||
283 | out_arp: | ||
284 | remove_proc_entry("socket", atalk_proc_dir); | ||
285 | out_socket: | ||
286 | remove_proc_entry("route", atalk_proc_dir); | ||
287 | out_route: | ||
288 | remove_proc_entry("interface", atalk_proc_dir); | ||
289 | out_interface: | ||
290 | remove_proc_entry("atalk", init_net.proc_net); | ||
291 | goto out; | ||
292 | } | ||
293 | |||
294 | void __exit atalk_proc_exit(void) | ||
295 | { | ||
296 | remove_proc_entry("interface", atalk_proc_dir); | ||
297 | remove_proc_entry("route", atalk_proc_dir); | ||
298 | remove_proc_entry("socket", atalk_proc_dir); | ||
299 | remove_proc_entry("arp", atalk_proc_dir); | ||
300 | remove_proc_entry("atalk", init_net.proc_net); | ||
301 | } | ||
diff --git a/drivers/staging/appletalk/cops.c b/drivers/staging/appletalk/cops.c new file mode 100644 index 00000000000..661d42eff7d --- /dev/null +++ b/drivers/staging/appletalk/cops.c | |||
@@ -0,0 +1,1013 @@ | |||
1 | /* cops.c: LocalTalk driver for Linux. | ||
2 | * | ||
3 | * Authors: | ||
4 | * - Jay Schulist <jschlst@samba.org> | ||
5 | * | ||
6 | * With more than a little help from; | ||
7 | * - Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
8 | * | ||
9 | * Derived from: | ||
10 | * - skeleton.c: A network driver outline for linux. | ||
11 | * Written 1993-94 by Donald Becker. | ||
12 | * - ltpc.c: A driver for the LocalTalk PC card. | ||
13 | * Written by Bradford W. Johnson. | ||
14 | * | ||
15 | * Copyright 1993 United States Government as represented by the | ||
16 | * Director, National Security Agency. | ||
17 | * | ||
18 | * This software may be used and distributed according to the terms | ||
19 | * of the GNU General Public License, incorporated herein by reference. | ||
20 | * | ||
21 | * Changes: | ||
22 | * 19970608 Alan Cox Allowed dual card type support | ||
23 | * Can set board type in insmod | ||
24 | * Hooks for cops_setup routine | ||
25 | * (not yet implemented). | ||
26 | * 19971101 Jay Schulist Fixes for multiple lt* devices. | ||
27 | * 19980607 Steven Hirsch Fixed the badly broken support | ||
28 | * for Tangent type cards. Only | ||
29 | * tested on Daystar LT200. Some | ||
30 | * cleanup of formatting and program | ||
31 | * logic. Added emacs 'local-vars' | ||
32 | * setup for Jay's brace style. | ||
33 | * 20000211 Alan Cox Cleaned up for softnet | ||
34 | */ | ||
35 | |||
36 | static const char *version = | ||
37 | "cops.c:v0.04 6/7/98 Jay Schulist <jschlst@samba.org>\n"; | ||
38 | /* | ||
39 | * Sources: | ||
40 | * COPS Localtalk SDK. This provides almost all of the information | ||
41 | * needed. | ||
42 | */ | ||
43 | |||
44 | /* | ||
45 | * insmod/modprobe configurable stuff. | ||
46 | * - IO Port, choose one your card supports or 0 if you dare. | ||
47 | * - IRQ, also choose one your card supports or nothing and let | ||
48 | * the driver figure it out. | ||
49 | */ | ||
50 | |||
51 | #include <linux/module.h> | ||
52 | #include <linux/kernel.h> | ||
53 | #include <linux/types.h> | ||
54 | #include <linux/fcntl.h> | ||
55 | #include <linux/interrupt.h> | ||
56 | #include <linux/ptrace.h> | ||
57 | #include <linux/ioport.h> | ||
58 | #include <linux/in.h> | ||
59 | #include <linux/string.h> | ||
60 | #include <linux/errno.h> | ||
61 | #include <linux/init.h> | ||
62 | #include <linux/netdevice.h> | ||
63 | #include <linux/etherdevice.h> | ||
64 | #include <linux/skbuff.h> | ||
65 | #include <linux/if_arp.h> | ||
66 | #include <linux/if_ltalk.h> | ||
67 | #include <linux/delay.h> /* For udelay() */ | ||
68 | #include <linux/spinlock.h> | ||
69 | #include <linux/bitops.h> | ||
70 | #include <linux/jiffies.h> | ||
71 | |||
72 | #include <asm/system.h> | ||
73 | #include <asm/io.h> | ||
74 | #include <asm/dma.h> | ||
75 | |||
76 | #include "atalk.h" | ||
77 | #include "cops.h" /* Our Stuff */ | ||
78 | #include "cops_ltdrv.h" /* Firmware code for Tangent type cards. */ | ||
79 | #include "cops_ffdrv.h" /* Firmware code for Dayna type cards. */ | ||
80 | |||
81 | /* | ||
82 | * The name of the card. Is used for messages and in the requests for | ||
83 | * io regions, irqs and dma channels | ||
84 | */ | ||
85 | |||
86 | static const char *cardname = "cops"; | ||
87 | |||
88 | #ifdef CONFIG_COPS_DAYNA | ||
89 | static int board_type = DAYNA; /* Module exported */ | ||
90 | #else | ||
91 | static int board_type = TANGENT; | ||
92 | #endif | ||
93 | |||
94 | static int io = 0x240; /* Default IO for Dayna */ | ||
95 | static int irq = 5; /* Default IRQ */ | ||
96 | |||
97 | /* | ||
98 | * COPS Autoprobe information. | ||
99 | * Right now if port address is right but IRQ is not 5 this will | ||
100 | * return a 5 no matter what since we will still get a status response. | ||
101 | * Need one more additional check to narrow down after we have gotten | ||
102 | * the ioaddr. But since only other possible IRQs is 3 and 4 so no real | ||
103 | * hurry on this. I *STRONGLY* recommend using IRQ 5 for your card with | ||
104 | * this driver. | ||
105 | * | ||
106 | * This driver has 2 modes and they are: Dayna mode and Tangent mode. | ||
107 | * Each mode corresponds with the type of card. It has been found | ||
108 | * that there are 2 main types of cards and all other cards are | ||
109 | * the same and just have different names or only have minor differences | ||
110 | * such as more IO ports. As this driver is tested it will | ||
111 | * become more clear on exactly what cards are supported. The driver | ||
112 | * defaults to using Dayna mode. To change the drivers mode, simply | ||
113 | * select Dayna or Tangent mode when configuring the kernel. | ||
114 | * | ||
115 | * This driver should support: | ||
116 | * TANGENT driver mode: | ||
117 | * Tangent ATB-II, Novell NL-1000, Daystar Digital LT-200, | ||
118 | * COPS LT-1 | ||
119 | * DAYNA driver mode: | ||
120 | * Dayna DL2000/DaynaTalk PC (Half Length), COPS LT-95, | ||
121 | * Farallon PhoneNET PC III, Farallon PhoneNET PC II | ||
122 | * Other cards possibly supported mode unknown though: | ||
123 | * Dayna DL2000 (Full length), COPS LT/M (Micro-Channel) | ||
124 | * | ||
125 | * Cards NOT supported by this driver but supported by the ltpc.c | ||
126 | * driver written by Bradford W. Johnson <johns393@maroon.tc.umn.edu> | ||
127 | * Farallon PhoneNET PC | ||
128 | * Original Apple LocalTalk PC card | ||
129 | * | ||
130 | * N.B. | ||
131 | * | ||
132 | * The Daystar Digital LT200 boards do not support interrupt-driven | ||
133 | * IO. You must specify 'irq=0xff' as a module parameter to invoke | ||
134 | * polled mode. I also believe that the port probing logic is quite | ||
135 | * dangerous at best and certainly hopeless for a polled card. Best to | ||
136 | * specify both. - Steve H. | ||
137 | * | ||
138 | */ | ||
139 | |||
140 | /* | ||
141 | * Zero terminated list of IO ports to probe. | ||
142 | */ | ||
143 | |||
144 | static unsigned int ports[] = { | ||
145 | 0x240, 0x340, 0x200, 0x210, 0x220, 0x230, 0x260, | ||
146 | 0x2A0, 0x300, 0x310, 0x320, 0x330, 0x350, 0x360, | ||
147 | 0 | ||
148 | }; | ||
149 | |||
150 | /* | ||
151 | * Zero terminated list of IRQ ports to probe. | ||
152 | */ | ||
153 | |||
154 | static int cops_irqlist[] = { | ||
155 | 5, 4, 3, 0 | ||
156 | }; | ||
157 | |||
158 | static struct timer_list cops_timer; | ||
159 | |||
160 | /* use 0 for production, 1 for verification, 2 for debug, 3 for verbose debug */ | ||
161 | #ifndef COPS_DEBUG | ||
162 | #define COPS_DEBUG 1 | ||
163 | #endif | ||
164 | static unsigned int cops_debug = COPS_DEBUG; | ||
165 | |||
166 | /* The number of low I/O ports used by the card. */ | ||
167 | #define COPS_IO_EXTENT 8 | ||
168 | |||
169 | /* Information that needs to be kept for each board. */ | ||
170 | |||
171 | struct cops_local | ||
172 | { | ||
173 | int board; /* Holds what board type is. */ | ||
174 | int nodeid; /* Set to 1 once have nodeid. */ | ||
175 | unsigned char node_acquire; /* Node ID when acquired. */ | ||
176 | struct atalk_addr node_addr; /* Full node address */ | ||
177 | spinlock_t lock; /* RX/TX lock */ | ||
178 | }; | ||
179 | |||
180 | /* Index to functions, as function prototypes. */ | ||
181 | static int cops_probe1 (struct net_device *dev, int ioaddr); | ||
182 | static int cops_irq (int ioaddr, int board); | ||
183 | |||
184 | static int cops_open (struct net_device *dev); | ||
185 | static int cops_jumpstart (struct net_device *dev); | ||
186 | static void cops_reset (struct net_device *dev, int sleep); | ||
187 | static void cops_load (struct net_device *dev); | ||
188 | static int cops_nodeid (struct net_device *dev, int nodeid); | ||
189 | |||
190 | static irqreturn_t cops_interrupt (int irq, void *dev_id); | ||
191 | static void cops_poll (unsigned long ltdev); | ||
192 | static void cops_timeout(struct net_device *dev); | ||
193 | static void cops_rx (struct net_device *dev); | ||
194 | static netdev_tx_t cops_send_packet (struct sk_buff *skb, | ||
195 | struct net_device *dev); | ||
196 | static void set_multicast_list (struct net_device *dev); | ||
197 | static int cops_ioctl (struct net_device *dev, struct ifreq *rq, int cmd); | ||
198 | static int cops_close (struct net_device *dev); | ||
199 | |||
200 | static void cleanup_card(struct net_device *dev) | ||
201 | { | ||
202 | if (dev->irq) | ||
203 | free_irq(dev->irq, dev); | ||
204 | release_region(dev->base_addr, COPS_IO_EXTENT); | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Check for a network adaptor of this type, and return '0' iff one exists. | ||
209 | * If dev->base_addr == 0, probe all likely locations. | ||
210 | * If dev->base_addr in [1..0x1ff], always return failure. | ||
211 | * otherwise go with what we pass in. | ||
212 | */ | ||
213 | struct net_device * __init cops_probe(int unit) | ||
214 | { | ||
215 | struct net_device *dev; | ||
216 | unsigned *port; | ||
217 | int base_addr; | ||
218 | int err = 0; | ||
219 | |||
220 | dev = alloc_ltalkdev(sizeof(struct cops_local)); | ||
221 | if (!dev) | ||
222 | return ERR_PTR(-ENOMEM); | ||
223 | |||
224 | if (unit >= 0) { | ||
225 | sprintf(dev->name, "lt%d", unit); | ||
226 | netdev_boot_setup_check(dev); | ||
227 | irq = dev->irq; | ||
228 | base_addr = dev->base_addr; | ||
229 | } else { | ||
230 | base_addr = dev->base_addr = io; | ||
231 | } | ||
232 | |||
233 | if (base_addr > 0x1ff) { /* Check a single specified location. */ | ||
234 | err = cops_probe1(dev, base_addr); | ||
235 | } else if (base_addr != 0) { /* Don't probe at all. */ | ||
236 | err = -ENXIO; | ||
237 | } else { | ||
238 | /* FIXME Does this really work for cards which generate irq? | ||
239 | * It's definitely N.G. for polled Tangent. sh | ||
240 | * Dayna cards don't autoprobe well at all, but if your card is | ||
241 | * at IRQ 5 & IO 0x240 we find it every time. ;) JS | ||
242 | */ | ||
243 | for (port = ports; *port && cops_probe1(dev, *port) < 0; port++) | ||
244 | ; | ||
245 | if (!*port) | ||
246 | err = -ENODEV; | ||
247 | } | ||
248 | if (err) | ||
249 | goto out; | ||
250 | err = register_netdev(dev); | ||
251 | if (err) | ||
252 | goto out1; | ||
253 | return dev; | ||
254 | out1: | ||
255 | cleanup_card(dev); | ||
256 | out: | ||
257 | free_netdev(dev); | ||
258 | return ERR_PTR(err); | ||
259 | } | ||
260 | |||
261 | static const struct net_device_ops cops_netdev_ops = { | ||
262 | .ndo_open = cops_open, | ||
263 | .ndo_stop = cops_close, | ||
264 | .ndo_start_xmit = cops_send_packet, | ||
265 | .ndo_tx_timeout = cops_timeout, | ||
266 | .ndo_do_ioctl = cops_ioctl, | ||
267 | .ndo_set_multicast_list = set_multicast_list, | ||
268 | }; | ||
269 | |||
270 | /* | ||
271 | * This is the real probe routine. Linux has a history of friendly device | ||
272 | * probes on the ISA bus. A good device probes avoids doing writes, and | ||
273 | * verifies that the correct device exists and functions. | ||
274 | */ | ||
275 | static int __init cops_probe1(struct net_device *dev, int ioaddr) | ||
276 | { | ||
277 | struct cops_local *lp; | ||
278 | static unsigned version_printed; | ||
279 | int board = board_type; | ||
280 | int retval; | ||
281 | |||
282 | if(cops_debug && version_printed++ == 0) | ||
283 | printk("%s", version); | ||
284 | |||
285 | /* Grab the region so no one else tries to probe our ioports. */ | ||
286 | if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name)) | ||
287 | return -EBUSY; | ||
288 | |||
289 | /* | ||
290 | * Since this board has jumpered interrupts, allocate the interrupt | ||
291 | * vector now. There is no point in waiting since no other device | ||
292 | * can use the interrupt, and this marks the irq as busy. Jumpered | ||
293 | * interrupts are typically not reported by the boards, and we must | ||
294 | * used AutoIRQ to find them. | ||
295 | */ | ||
296 | dev->irq = irq; | ||
297 | switch (dev->irq) | ||
298 | { | ||
299 | case 0: | ||
300 | /* COPS AutoIRQ routine */ | ||
301 | dev->irq = cops_irq(ioaddr, board); | ||
302 | if (dev->irq) | ||
303 | break; | ||
304 | /* No IRQ found on this port, fallthrough */ | ||
305 | case 1: | ||
306 | retval = -EINVAL; | ||
307 | goto err_out; | ||
308 | |||
309 | /* Fixup for users that don't know that IRQ 2 is really | ||
310 | * IRQ 9, or don't know which one to set. | ||
311 | */ | ||
312 | case 2: | ||
313 | dev->irq = 9; | ||
314 | break; | ||
315 | |||
316 | /* Polled operation requested. Although irq of zero passed as | ||
317 | * a parameter tells the init routines to probe, we'll | ||
318 | * overload it to denote polled operation at runtime. | ||
319 | */ | ||
320 | case 0xff: | ||
321 | dev->irq = 0; | ||
322 | break; | ||
323 | |||
324 | default: | ||
325 | break; | ||
326 | } | ||
327 | |||
328 | /* Reserve any actual interrupt. */ | ||
329 | if (dev->irq) { | ||
330 | retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev); | ||
331 | if (retval) | ||
332 | goto err_out; | ||
333 | } | ||
334 | |||
335 | dev->base_addr = ioaddr; | ||
336 | |||
337 | lp = netdev_priv(dev); | ||
338 | spin_lock_init(&lp->lock); | ||
339 | |||
340 | /* Copy local board variable to lp struct. */ | ||
341 | lp->board = board; | ||
342 | |||
343 | dev->netdev_ops = &cops_netdev_ops; | ||
344 | dev->watchdog_timeo = HZ * 2; | ||
345 | |||
346 | |||
347 | /* Tell the user where the card is and what mode we're in. */ | ||
348 | if(board==DAYNA) | ||
349 | printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n", | ||
350 | dev->name, cardname, ioaddr, dev->irq); | ||
351 | if(board==TANGENT) { | ||
352 | if(dev->irq) | ||
353 | printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n", | ||
354 | dev->name, cardname, ioaddr, dev->irq); | ||
355 | else | ||
356 | printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n", | ||
357 | dev->name, cardname, ioaddr); | ||
358 | |||
359 | } | ||
360 | return 0; | ||
361 | |||
362 | err_out: | ||
363 | release_region(ioaddr, COPS_IO_EXTENT); | ||
364 | return retval; | ||
365 | } | ||
366 | |||
367 | static int __init cops_irq (int ioaddr, int board) | ||
368 | { /* | ||
369 | * This does not use the IRQ to determine where the IRQ is. We just | ||
370 | * assume that when we get a correct status response that it's the IRQ. | ||
371 | * This really just verifies the IO port but since we only have access | ||
372 | * to such a small number of IRQs (5, 4, 3) this is not bad. | ||
373 | * This will probably not work for more than one card. | ||
374 | */ | ||
375 | int irqaddr=0; | ||
376 | int i, x, status; | ||
377 | |||
378 | if(board==DAYNA) | ||
379 | { | ||
380 | outb(0, ioaddr+DAYNA_RESET); | ||
381 | inb(ioaddr+DAYNA_RESET); | ||
382 | mdelay(333); | ||
383 | } | ||
384 | if(board==TANGENT) | ||
385 | { | ||
386 | inb(ioaddr); | ||
387 | outb(0, ioaddr); | ||
388 | outb(0, ioaddr+TANG_RESET); | ||
389 | } | ||
390 | |||
391 | for(i=0; cops_irqlist[i] !=0; i++) | ||
392 | { | ||
393 | irqaddr = cops_irqlist[i]; | ||
394 | for(x = 0xFFFF; x>0; x --) /* wait for response */ | ||
395 | { | ||
396 | if(board==DAYNA) | ||
397 | { | ||
398 | status = (inb(ioaddr+DAYNA_CARD_STATUS)&3); | ||
399 | if(status == 1) | ||
400 | return irqaddr; | ||
401 | } | ||
402 | if(board==TANGENT) | ||
403 | { | ||
404 | if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0) | ||
405 | return irqaddr; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | return 0; /* no IRQ found */ | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Open/initialize the board. This is called (in the current kernel) | ||
414 | * sometime after booting when the 'ifconfig' program is run. | ||
415 | */ | ||
416 | static int cops_open(struct net_device *dev) | ||
417 | { | ||
418 | struct cops_local *lp = netdev_priv(dev); | ||
419 | |||
420 | if(dev->irq==0) | ||
421 | { | ||
422 | /* | ||
423 | * I don't know if the Dayna-style boards support polled | ||
424 | * operation. For now, only allow it for Tangent. | ||
425 | */ | ||
426 | if(lp->board==TANGENT) /* Poll 20 times per second */ | ||
427 | { | ||
428 | init_timer(&cops_timer); | ||
429 | cops_timer.function = cops_poll; | ||
430 | cops_timer.data = (unsigned long)dev; | ||
431 | cops_timer.expires = jiffies + HZ/20; | ||
432 | add_timer(&cops_timer); | ||
433 | } | ||
434 | else | ||
435 | { | ||
436 | printk(KERN_WARNING "%s: No irq line set\n", dev->name); | ||
437 | return -EAGAIN; | ||
438 | } | ||
439 | } | ||
440 | |||
441 | cops_jumpstart(dev); /* Start the card up. */ | ||
442 | |||
443 | netif_start_queue(dev); | ||
444 | return 0; | ||
445 | } | ||
446 | |||
447 | /* | ||
448 | * This allows for a dynamic start/restart of the entire card. | ||
449 | */ | ||
450 | static int cops_jumpstart(struct net_device *dev) | ||
451 | { | ||
452 | struct cops_local *lp = netdev_priv(dev); | ||
453 | |||
454 | /* | ||
455 | * Once the card has the firmware loaded and has acquired | ||
456 | * the nodeid, if it is reset it will lose it all. | ||
457 | */ | ||
458 | cops_reset(dev,1); /* Need to reset card before load firmware. */ | ||
459 | cops_load(dev); /* Load the firmware. */ | ||
460 | |||
461 | /* | ||
462 | * If atalkd already gave us a nodeid we will use that | ||
463 | * one again, else we wait for atalkd to give us a nodeid | ||
464 | * in cops_ioctl. This may cause a problem if someone steals | ||
465 | * our nodeid while we are resetting. | ||
466 | */ | ||
467 | if(lp->nodeid == 1) | ||
468 | cops_nodeid(dev,lp->node_acquire); | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static void tangent_wait_reset(int ioaddr) | ||
474 | { | ||
475 | int timeout=0; | ||
476 | |||
477 | while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) | ||
478 | mdelay(1); /* Wait 1 second */ | ||
479 | } | ||
480 | |||
481 | /* | ||
482 | * Reset the LocalTalk board. | ||
483 | */ | ||
484 | static void cops_reset(struct net_device *dev, int sleep) | ||
485 | { | ||
486 | struct cops_local *lp = netdev_priv(dev); | ||
487 | int ioaddr=dev->base_addr; | ||
488 | |||
489 | if(lp->board==TANGENT) | ||
490 | { | ||
491 | inb(ioaddr); /* Clear request latch. */ | ||
492 | outb(0,ioaddr); /* Clear the TANG_TX_READY flop. */ | ||
493 | outb(0, ioaddr+TANG_RESET); /* Reset the adapter. */ | ||
494 | |||
495 | tangent_wait_reset(ioaddr); | ||
496 | outb(0, ioaddr+TANG_CLEAR_INT); | ||
497 | } | ||
498 | if(lp->board==DAYNA) | ||
499 | { | ||
500 | outb(0, ioaddr+DAYNA_RESET); /* Assert the reset port */ | ||
501 | inb(ioaddr+DAYNA_RESET); /* Clear the reset */ | ||
502 | if (sleep) | ||
503 | msleep(333); | ||
504 | else | ||
505 | mdelay(333); | ||
506 | } | ||
507 | |||
508 | netif_wake_queue(dev); | ||
509 | } | ||
510 | |||
511 | static void cops_load (struct net_device *dev) | ||
512 | { | ||
513 | struct ifreq ifr; | ||
514 | struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_ifru; | ||
515 | struct cops_local *lp = netdev_priv(dev); | ||
516 | int ioaddr=dev->base_addr; | ||
517 | int length, i = 0; | ||
518 | |||
519 | strcpy(ifr.ifr_name,"lt0"); | ||
520 | |||
521 | /* Get card's firmware code and do some checks on it. */ | ||
522 | #ifdef CONFIG_COPS_DAYNA | ||
523 | if(lp->board==DAYNA) | ||
524 | { | ||
525 | ltf->length=sizeof(ffdrv_code); | ||
526 | ltf->data=ffdrv_code; | ||
527 | } | ||
528 | else | ||
529 | #endif | ||
530 | #ifdef CONFIG_COPS_TANGENT | ||
531 | if(lp->board==TANGENT) | ||
532 | { | ||
533 | ltf->length=sizeof(ltdrv_code); | ||
534 | ltf->data=ltdrv_code; | ||
535 | } | ||
536 | else | ||
537 | #endif | ||
538 | { | ||
539 | printk(KERN_INFO "%s; unsupported board type.\n", dev->name); | ||
540 | return; | ||
541 | } | ||
542 | |||
543 | /* Check to make sure firmware is correct length. */ | ||
544 | if(lp->board==DAYNA && ltf->length!=5983) | ||
545 | { | ||
546 | printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name); | ||
547 | return; | ||
548 | } | ||
549 | if(lp->board==TANGENT && ltf->length!=2501) | ||
550 | { | ||
551 | printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name); | ||
552 | return; | ||
553 | } | ||
554 | |||
555 | if(lp->board==DAYNA) | ||
556 | { | ||
557 | /* | ||
558 | * We must wait for a status response | ||
559 | * with the DAYNA board. | ||
560 | */ | ||
561 | while(++i<65536) | ||
562 | { | ||
563 | if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1) | ||
564 | break; | ||
565 | } | ||
566 | |||
567 | if(i==65536) | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | /* | ||
572 | * Upload the firmware and kick. Byte-by-byte works nicely here. | ||
573 | */ | ||
574 | i=0; | ||
575 | length = ltf->length; | ||
576 | while(length--) | ||
577 | { | ||
578 | outb(ltf->data[i], ioaddr); | ||
579 | i++; | ||
580 | } | ||
581 | |||
582 | if(cops_debug > 1) | ||
583 | printk("%s: Uploaded firmware - %d bytes of %d bytes.\n", | ||
584 | dev->name, i, ltf->length); | ||
585 | |||
586 | if(lp->board==DAYNA) /* Tell Dayna to run the firmware code. */ | ||
587 | outb(1, ioaddr+DAYNA_INT_CARD); | ||
588 | else /* Tell Tang to run the firmware code. */ | ||
589 | inb(ioaddr); | ||
590 | |||
591 | if(lp->board==TANGENT) | ||
592 | { | ||
593 | tangent_wait_reset(ioaddr); | ||
594 | inb(ioaddr); /* Clear initial ready signal. */ | ||
595 | } | ||
596 | } | ||
597 | |||
598 | /* | ||
599 | * Get the LocalTalk Nodeid from the card. We can suggest | ||
600 | * any nodeid 1-254. The card will try and get that exact | ||
601 | * address else we can specify 0 as the nodeid and the card | ||
602 | * will autoprobe for a nodeid. | ||
603 | */ | ||
604 | static int cops_nodeid (struct net_device *dev, int nodeid) | ||
605 | { | ||
606 | struct cops_local *lp = netdev_priv(dev); | ||
607 | int ioaddr = dev->base_addr; | ||
608 | |||
609 | if(lp->board == DAYNA) | ||
610 | { | ||
611 | /* Empty any pending adapter responses. */ | ||
612 | while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0) | ||
613 | { | ||
614 | outb(0, ioaddr+COPS_CLEAR_INT); /* Clear interrupts. */ | ||
615 | if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST) | ||
616 | cops_rx(dev); /* Kick any packets waiting. */ | ||
617 | schedule(); | ||
618 | } | ||
619 | |||
620 | outb(2, ioaddr); /* Output command packet length as 2. */ | ||
621 | outb(0, ioaddr); | ||
622 | outb(LAP_INIT, ioaddr); /* Send LAP_INIT command byte. */ | ||
623 | outb(nodeid, ioaddr); /* Suggest node address. */ | ||
624 | } | ||
625 | |||
626 | if(lp->board == TANGENT) | ||
627 | { | ||
628 | /* Empty any pending adapter responses. */ | ||
629 | while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) | ||
630 | { | ||
631 | outb(0, ioaddr+COPS_CLEAR_INT); /* Clear interrupt. */ | ||
632 | cops_rx(dev); /* Kick out packets waiting. */ | ||
633 | schedule(); | ||
634 | } | ||
635 | |||
636 | /* Not sure what Tangent does if nodeid picked is used. */ | ||
637 | if(nodeid == 0) /* Seed. */ | ||
638 | nodeid = jiffies&0xFF; /* Get a random try */ | ||
639 | outb(2, ioaddr); /* Command length LSB */ | ||
640 | outb(0, ioaddr); /* Command length MSB */ | ||
641 | outb(LAP_INIT, ioaddr); /* Send LAP_INIT byte */ | ||
642 | outb(nodeid, ioaddr); /* LAP address hint. */ | ||
643 | outb(0xFF, ioaddr); /* Int. level to use */ | ||
644 | } | ||
645 | |||
646 | lp->node_acquire=0; /* Set nodeid holder to 0. */ | ||
647 | while(lp->node_acquire==0) /* Get *True* nodeid finally. */ | ||
648 | { | ||
649 | outb(0, ioaddr+COPS_CLEAR_INT); /* Clear any interrupt. */ | ||
650 | |||
651 | if(lp->board == DAYNA) | ||
652 | { | ||
653 | if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST) | ||
654 | cops_rx(dev); /* Grab the nodeid put in lp->node_acquire. */ | ||
655 | } | ||
656 | if(lp->board == TANGENT) | ||
657 | { | ||
658 | if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY) | ||
659 | cops_rx(dev); /* Grab the nodeid put in lp->node_acquire. */ | ||
660 | } | ||
661 | schedule(); | ||
662 | } | ||
663 | |||
664 | if(cops_debug > 1) | ||
665 | printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", | ||
666 | dev->name, lp->node_acquire); | ||
667 | |||
668 | lp->nodeid=1; /* Set got nodeid to 1. */ | ||
669 | |||
670 | return 0; | ||
671 | } | ||
672 | |||
673 | /* | ||
674 | * Poll the Tangent type cards to see if we have work. | ||
675 | */ | ||
676 | |||
677 | static void cops_poll(unsigned long ltdev) | ||
678 | { | ||
679 | int ioaddr, status; | ||
680 | int boguscount = 0; | ||
681 | |||
682 | struct net_device *dev = (struct net_device *)ltdev; | ||
683 | |||
684 | del_timer(&cops_timer); | ||
685 | |||
686 | if(dev == NULL) | ||
687 | return; /* We've been downed */ | ||
688 | |||
689 | ioaddr = dev->base_addr; | ||
690 | do { | ||
691 | status=inb(ioaddr+TANG_CARD_STATUS); | ||
692 | if(status & TANG_RX_READY) | ||
693 | cops_rx(dev); | ||
694 | if(status & TANG_TX_READY) | ||
695 | netif_wake_queue(dev); | ||
696 | status = inb(ioaddr+TANG_CARD_STATUS); | ||
697 | } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); | ||
698 | |||
699 | /* poll 20 times per second */ | ||
700 | cops_timer.expires = jiffies + HZ/20; | ||
701 | add_timer(&cops_timer); | ||
702 | } | ||
703 | |||
704 | /* | ||
705 | * The typical workload of the driver: | ||
706 | * Handle the network interface interrupts. | ||
707 | */ | ||
708 | static irqreturn_t cops_interrupt(int irq, void *dev_id) | ||
709 | { | ||
710 | struct net_device *dev = dev_id; | ||
711 | struct cops_local *lp; | ||
712 | int ioaddr, status; | ||
713 | int boguscount = 0; | ||
714 | |||
715 | ioaddr = dev->base_addr; | ||
716 | lp = netdev_priv(dev); | ||
717 | |||
718 | if(lp->board==DAYNA) | ||
719 | { | ||
720 | do { | ||
721 | outb(0, ioaddr + COPS_CLEAR_INT); | ||
722 | status=inb(ioaddr+DAYNA_CARD_STATUS); | ||
723 | if((status&0x03)==DAYNA_RX_REQUEST) | ||
724 | cops_rx(dev); | ||
725 | netif_wake_queue(dev); | ||
726 | } while(++boguscount < 20); | ||
727 | } | ||
728 | else | ||
729 | { | ||
730 | do { | ||
731 | status=inb(ioaddr+TANG_CARD_STATUS); | ||
732 | if(status & TANG_RX_READY) | ||
733 | cops_rx(dev); | ||
734 | if(status & TANG_TX_READY) | ||
735 | netif_wake_queue(dev); | ||
736 | status=inb(ioaddr+TANG_CARD_STATUS); | ||
737 | } while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY))); | ||
738 | } | ||
739 | |||
740 | return IRQ_HANDLED; | ||
741 | } | ||
742 | |||
743 | /* | ||
744 | * We have a good packet(s), get it/them out of the buffers. | ||
745 | */ | ||
746 | static void cops_rx(struct net_device *dev) | ||
747 | { | ||
748 | int pkt_len = 0; | ||
749 | int rsp_type = 0; | ||
750 | struct sk_buff *skb = NULL; | ||
751 | struct cops_local *lp = netdev_priv(dev); | ||
752 | int ioaddr = dev->base_addr; | ||
753 | int boguscount = 0; | ||
754 | unsigned long flags; | ||
755 | |||
756 | |||
757 | spin_lock_irqsave(&lp->lock, flags); | ||
758 | |||
759 | if(lp->board==DAYNA) | ||
760 | { | ||
761 | outb(0, ioaddr); /* Send out Zero length. */ | ||
762 | outb(0, ioaddr); | ||
763 | outb(DATA_READ, ioaddr); /* Send read command out. */ | ||
764 | |||
765 | /* Wait for DMA to turn around. */ | ||
766 | while(++boguscount<1000000) | ||
767 | { | ||
768 | barrier(); | ||
769 | if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY) | ||
770 | break; | ||
771 | } | ||
772 | |||
773 | if(boguscount==1000000) | ||
774 | { | ||
775 | printk(KERN_WARNING "%s: DMA timed out.\n",dev->name); | ||
776 | spin_unlock_irqrestore(&lp->lock, flags); | ||
777 | return; | ||
778 | } | ||
779 | } | ||
780 | |||
781 | /* Get response length. */ | ||
782 | if(lp->board==DAYNA) | ||
783 | pkt_len = inb(ioaddr) & 0xFF; | ||
784 | else | ||
785 | pkt_len = inb(ioaddr) & 0x00FF; | ||
786 | pkt_len |= (inb(ioaddr) << 8); | ||
787 | /* Input IO code. */ | ||
788 | rsp_type=inb(ioaddr); | ||
789 | |||
790 | /* Malloc up new buffer. */ | ||
791 | skb = dev_alloc_skb(pkt_len); | ||
792 | if(skb == NULL) | ||
793 | { | ||
794 | printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", | ||
795 | dev->name); | ||
796 | dev->stats.rx_dropped++; | ||
797 | while(pkt_len--) /* Discard packet */ | ||
798 | inb(ioaddr); | ||
799 | spin_unlock_irqrestore(&lp->lock, flags); | ||
800 | return; | ||
801 | } | ||
802 | skb->dev = dev; | ||
803 | skb_put(skb, pkt_len); | ||
804 | skb->protocol = htons(ETH_P_LOCALTALK); | ||
805 | |||
806 | insb(ioaddr, skb->data, pkt_len); /* Eat the Data */ | ||
807 | |||
808 | if(lp->board==DAYNA) | ||
809 | outb(1, ioaddr+DAYNA_INT_CARD); /* Interrupt the card */ | ||
810 | |||
811 | spin_unlock_irqrestore(&lp->lock, flags); /* Restore interrupts. */ | ||
812 | |||
813 | /* Check for bad response length */ | ||
814 | if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE) | ||
815 | { | ||
816 | printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", | ||
817 | dev->name, pkt_len); | ||
818 | dev->stats.tx_errors++; | ||
819 | dev_kfree_skb_any(skb); | ||
820 | return; | ||
821 | } | ||
822 | |||
823 | /* Set nodeid and then get out. */ | ||
824 | if(rsp_type == LAP_INIT_RSP) | ||
825 | { /* Nodeid taken from received packet. */ | ||
826 | lp->node_acquire = skb->data[0]; | ||
827 | dev_kfree_skb_any(skb); | ||
828 | return; | ||
829 | } | ||
830 | |||
831 | /* One last check to make sure we have a good packet. */ | ||
832 | if(rsp_type != LAP_RESPONSE) | ||
833 | { | ||
834 | printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type); | ||
835 | dev->stats.tx_errors++; | ||
836 | dev_kfree_skb_any(skb); | ||
837 | return; | ||
838 | } | ||
839 | |||
840 | skb_reset_mac_header(skb); /* Point to entire packet. */ | ||
841 | skb_pull(skb,3); | ||
842 | skb_reset_transport_header(skb); /* Point to data (Skip header). */ | ||
843 | |||
844 | /* Update the counters. */ | ||
845 | dev->stats.rx_packets++; | ||
846 | dev->stats.rx_bytes += skb->len; | ||
847 | |||
848 | /* Send packet to a higher place. */ | ||
849 | netif_rx(skb); | ||
850 | } | ||
851 | |||
852 | static void cops_timeout(struct net_device *dev) | ||
853 | { | ||
854 | struct cops_local *lp = netdev_priv(dev); | ||
855 | int ioaddr = dev->base_addr; | ||
856 | |||
857 | dev->stats.tx_errors++; | ||
858 | if(lp->board==TANGENT) | ||
859 | { | ||
860 | if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) | ||
861 | printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name); | ||
862 | } | ||
863 | printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name); | ||
864 | cops_jumpstart(dev); /* Restart the card. */ | ||
865 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
866 | netif_wake_queue(dev); | ||
867 | } | ||
868 | |||
869 | |||
870 | /* | ||
871 | * Make the card transmit a LocalTalk packet. | ||
872 | */ | ||
873 | |||
874 | static netdev_tx_t cops_send_packet(struct sk_buff *skb, | ||
875 | struct net_device *dev) | ||
876 | { | ||
877 | struct cops_local *lp = netdev_priv(dev); | ||
878 | int ioaddr = dev->base_addr; | ||
879 | unsigned long flags; | ||
880 | |||
881 | /* | ||
882 | * Block a timer-based transmit from overlapping. | ||
883 | */ | ||
884 | |||
885 | netif_stop_queue(dev); | ||
886 | |||
887 | spin_lock_irqsave(&lp->lock, flags); | ||
888 | if(lp->board == DAYNA) /* Wait for adapter transmit buffer. */ | ||
889 | while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0) | ||
890 | cpu_relax(); | ||
891 | if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */ | ||
892 | while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0) | ||
893 | cpu_relax(); | ||
894 | |||
895 | /* Output IO length. */ | ||
896 | outb(skb->len, ioaddr); | ||
897 | if(lp->board == DAYNA) | ||
898 | outb(skb->len >> 8, ioaddr); | ||
899 | else | ||
900 | outb((skb->len >> 8)&0x0FF, ioaddr); | ||
901 | |||
902 | /* Output IO code. */ | ||
903 | outb(LAP_WRITE, ioaddr); | ||
904 | |||
905 | if(lp->board == DAYNA) /* Check the transmit buffer again. */ | ||
906 | while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0); | ||
907 | |||
908 | outsb(ioaddr, skb->data, skb->len); /* Send out the data. */ | ||
909 | |||
910 | if(lp->board==DAYNA) /* Dayna requires you kick the card */ | ||
911 | outb(1, ioaddr+DAYNA_INT_CARD); | ||
912 | |||
913 | spin_unlock_irqrestore(&lp->lock, flags); /* Restore interrupts. */ | ||
914 | |||
915 | /* Done sending packet, update counters and cleanup. */ | ||
916 | dev->stats.tx_packets++; | ||
917 | dev->stats.tx_bytes += skb->len; | ||
918 | dev_kfree_skb (skb); | ||
919 | return NETDEV_TX_OK; | ||
920 | } | ||
921 | |||
922 | /* | ||
923 | * Dummy function to keep the Appletalk layer happy. | ||
924 | */ | ||
925 | |||
926 | static void set_multicast_list(struct net_device *dev) | ||
927 | { | ||
928 | if(cops_debug >= 3) | ||
929 | printk("%s: set_multicast_list executed\n", dev->name); | ||
930 | } | ||
931 | |||
932 | /* | ||
933 | * System ioctls for the COPS LocalTalk card. | ||
934 | */ | ||
935 | |||
936 | static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||
937 | { | ||
938 | struct cops_local *lp = netdev_priv(dev); | ||
939 | struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr; | ||
940 | struct atalk_addr *aa = (struct atalk_addr *)&lp->node_addr; | ||
941 | |||
942 | switch(cmd) | ||
943 | { | ||
944 | case SIOCSIFADDR: | ||
945 | /* Get and set the nodeid and network # atalkd wants. */ | ||
946 | cops_nodeid(dev, sa->sat_addr.s_node); | ||
947 | aa->s_net = sa->sat_addr.s_net; | ||
948 | aa->s_node = lp->node_acquire; | ||
949 | |||
950 | /* Set broardcast address. */ | ||
951 | dev->broadcast[0] = 0xFF; | ||
952 | |||
953 | /* Set hardware address. */ | ||
954 | dev->dev_addr[0] = aa->s_node; | ||
955 | dev->addr_len = 1; | ||
956 | return 0; | ||
957 | |||
958 | case SIOCGIFADDR: | ||
959 | sa->sat_addr.s_net = aa->s_net; | ||
960 | sa->sat_addr.s_node = aa->s_node; | ||
961 | return 0; | ||
962 | |||
963 | default: | ||
964 | return -EOPNOTSUPP; | ||
965 | } | ||
966 | } | ||
967 | |||
968 | /* | ||
969 | * The inverse routine to cops_open(). | ||
970 | */ | ||
971 | |||
972 | static int cops_close(struct net_device *dev) | ||
973 | { | ||
974 | struct cops_local *lp = netdev_priv(dev); | ||
975 | |||
976 | /* If we were running polled, yank the timer. | ||
977 | */ | ||
978 | if(lp->board==TANGENT && dev->irq==0) | ||
979 | del_timer(&cops_timer); | ||
980 | |||
981 | netif_stop_queue(dev); | ||
982 | return 0; | ||
983 | } | ||
984 | |||
985 | |||
986 | #ifdef MODULE | ||
987 | static struct net_device *cops_dev; | ||
988 | |||
989 | MODULE_LICENSE("GPL"); | ||
990 | module_param(io, int, 0); | ||
991 | module_param(irq, int, 0); | ||
992 | module_param(board_type, int, 0); | ||
993 | |||
994 | static int __init cops_module_init(void) | ||
995 | { | ||
996 | if (io == 0) | ||
997 | printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n", | ||
998 | cardname); | ||
999 | cops_dev = cops_probe(-1); | ||
1000 | if (IS_ERR(cops_dev)) | ||
1001 | return PTR_ERR(cops_dev); | ||
1002 | return 0; | ||
1003 | } | ||
1004 | |||
1005 | static void __exit cops_module_exit(void) | ||
1006 | { | ||
1007 | unregister_netdev(cops_dev); | ||
1008 | cleanup_card(cops_dev); | ||
1009 | free_netdev(cops_dev); | ||
1010 | } | ||
1011 | module_init(cops_module_init); | ||
1012 | module_exit(cops_module_exit); | ||
1013 | #endif /* MODULE */ | ||
diff --git a/drivers/staging/appletalk/cops.h b/drivers/staging/appletalk/cops.h new file mode 100644 index 00000000000..fd2750b269c --- /dev/null +++ b/drivers/staging/appletalk/cops.h | |||
@@ -0,0 +1,60 @@ | |||
1 | /* cops.h: LocalTalk driver for Linux. | ||
2 | * | ||
3 | * Authors: | ||
4 | * - Jay Schulist <jschlst@samba.org> | ||
5 | */ | ||
6 | |||
7 | #ifndef __LINUX_COPSLTALK_H | ||
8 | #define __LINUX_COPSLTALK_H | ||
9 | |||
10 | #ifdef __KERNEL__ | ||
11 | |||
12 | /* Max LLAP size we will accept. */ | ||
13 | #define MAX_LLAP_SIZE 603 | ||
14 | |||
15 | /* Tangent */ | ||
16 | #define TANG_CARD_STATUS 1 | ||
17 | #define TANG_CLEAR_INT 1 | ||
18 | #define TANG_RESET 3 | ||
19 | |||
20 | #define TANG_TX_READY 1 | ||
21 | #define TANG_RX_READY 2 | ||
22 | |||
23 | /* Dayna */ | ||
24 | #define DAYNA_CMD_DATA 0 | ||
25 | #define DAYNA_CLEAR_INT 1 | ||
26 | #define DAYNA_CARD_STATUS 2 | ||
27 | #define DAYNA_INT_CARD 3 | ||
28 | #define DAYNA_RESET 4 | ||
29 | |||
30 | #define DAYNA_RX_READY 0 | ||
31 | #define DAYNA_TX_READY 1 | ||
32 | #define DAYNA_RX_REQUEST 3 | ||
33 | |||
34 | /* Same on both card types */ | ||
35 | #define COPS_CLEAR_INT 1 | ||
36 | |||
37 | /* LAP response codes received from the cards. */ | ||
38 | #define LAP_INIT 1 /* Init cmd */ | ||
39 | #define LAP_INIT_RSP 2 /* Init response */ | ||
40 | #define LAP_WRITE 3 /* Write cmd */ | ||
41 | #define DATA_READ 4 /* Data read */ | ||
42 | #define LAP_RESPONSE 4 /* Received ALAP frame response */ | ||
43 | #define LAP_GETSTAT 5 /* Get LAP and HW status */ | ||
44 | #define LAP_RSPSTAT 6 /* Status response */ | ||
45 | |||
46 | #endif | ||
47 | |||
48 | /* | ||
49 | * Structure to hold the firmware information. | ||
50 | */ | ||
51 | struct ltfirmware | ||
52 | { | ||
53 | unsigned int length; | ||
54 | const unsigned char *data; | ||
55 | }; | ||
56 | |||
57 | #define DAYNA 1 | ||
58 | #define TANGENT 2 | ||
59 | |||
60 | #endif | ||
diff --git a/drivers/staging/appletalk/cops_ffdrv.h b/drivers/staging/appletalk/cops_ffdrv.h new file mode 100644 index 00000000000..b02005087c1 --- /dev/null +++ b/drivers/staging/appletalk/cops_ffdrv.h | |||
@@ -0,0 +1,532 @@ | |||
1 | |||
2 | /* | ||
3 | * The firmware this driver downloads into the Localtalk card is a | ||
4 | * separate program and is not GPL'd source code, even though the Linux | ||
5 | * side driver and the routine that loads this data into the card are. | ||
6 | * | ||
7 | * It is taken from the COPS SDK and is under the following license | ||
8 | * | ||
9 | * This material is licensed to you strictly for use in conjunction with | ||
10 | * the use of COPS LocalTalk adapters. | ||
11 | * There is no charge for this SDK. And no waranty express or implied | ||
12 | * about its fitness for any purpose. However, we will cheerefully | ||
13 | * refund every penny you paid for this SDK... | ||
14 | * Regards, | ||
15 | * | ||
16 | * Thomas F. Divine | ||
17 | * Chief Scientist | ||
18 | */ | ||
19 | |||
20 | |||
21 | /* cops_ffdrv.h: LocalTalk driver firmware dump for Linux. | ||
22 | * | ||
23 | * Authors: | ||
24 | * - Jay Schulist <jschlst@samba.org> | ||
25 | */ | ||
26 | |||
27 | |||
28 | #ifdef CONFIG_COPS_DAYNA | ||
29 | |||
30 | static const unsigned char ffdrv_code[] = { | ||
31 | 58,3,0,50,228,149,33,255,255,34,226,149, | ||
32 | 249,17,40,152,33,202,154,183,237,82,77,68, | ||
33 | 11,107,98,19,54,0,237,176,175,50,80,0, | ||
34 | 62,128,237,71,62,32,237,57,51,62,12,237, | ||
35 | 57,50,237,57,54,62,6,237,57,52,62,12, | ||
36 | 237,57,49,33,107,137,34,32,128,33,83,130, | ||
37 | 34,40,128,33,86,130,34,42,128,33,112,130, | ||
38 | 34,36,128,33,211,130,34,38,128,62,0,237, | ||
39 | 57,16,33,63,148,34,34,128,237,94,205,15, | ||
40 | 130,251,205,168,145,24,141,67,111,112,121,114, | ||
41 | 105,103,104,116,32,40,67,41,32,49,57,56, | ||
42 | 56,32,45,32,68,97,121,110,97,32,67,111, | ||
43 | 109,109,117,110,105,99,97,116,105,111,110,115, | ||
44 | 32,32,32,65,108,108,32,114,105,103,104,116, | ||
45 | 115,32,114,101,115,101,114,118,101,100,46,32, | ||
46 | 32,40,68,40,68,7,16,8,34,7,22,6, | ||
47 | 16,5,12,4,8,3,6,140,0,16,39,128, | ||
48 | 0,4,96,10,224,6,0,7,126,2,64,11, | ||
49 | 118,12,6,13,0,14,193,15,0,5,96,3, | ||
50 | 192,1,64,9,8,62,9,211,66,62,192,211, | ||
51 | 66,62,100,61,32,253,6,28,33,205,129,14, | ||
52 | 66,237,163,194,253,129,6,28,33,205,129,14, | ||
53 | 64,237,163,194,9,130,201,62,47,50,71,152, | ||
54 | 62,47,211,68,58,203,129,237,57,20,58,204, | ||
55 | 129,237,57,21,33,77,152,54,132,205,233,129, | ||
56 | 58,228,149,254,209,40,6,56,4,62,0,24, | ||
57 | 2,219,96,33,233,149,119,230,62,33,232,149, | ||
58 | 119,213,33,8,152,17,7,0,25,119,19,25, | ||
59 | 119,209,201,251,237,77,245,197,213,229,221,229, | ||
60 | 205,233,129,62,1,50,106,137,205,158,139,221, | ||
61 | 225,225,209,193,241,251,237,77,245,197,213,219, | ||
62 | 72,237,56,16,230,46,237,57,16,237,56,12, | ||
63 | 58,72,152,183,32,26,6,20,17,128,2,237, | ||
64 | 56,46,187,32,35,237,56,47,186,32,29,219, | ||
65 | 72,230,1,32,3,5,32,232,175,50,72,152, | ||
66 | 229,221,229,62,1,50,106,137,205,158,139,221, | ||
67 | 225,225,24,25,62,1,50,72,152,58,201,129, | ||
68 | 237,57,12,58,202,129,237,57,13,237,56,16, | ||
69 | 246,17,237,57,16,209,193,241,251,237,77,245, | ||
70 | 197,229,213,221,229,237,56,16,230,17,237,57, | ||
71 | 16,237,56,20,58,34,152,246,16,246,8,211, | ||
72 | 68,62,6,61,32,253,58,34,152,246,8,211, | ||
73 | 68,58,203,129,237,57,20,58,204,129,237,57, | ||
74 | 21,237,56,16,246,34,237,57,16,221,225,209, | ||
75 | 225,193,241,251,237,77,33,2,0,57,126,230, | ||
76 | 3,237,100,1,40,2,246,128,230,130,245,62, | ||
77 | 5,211,64,241,211,64,201,229,213,243,237,56, | ||
78 | 16,230,46,237,57,16,237,56,12,251,70,35, | ||
79 | 35,126,254,175,202,77,133,254,129,202,15,133, | ||
80 | 230,128,194,191,132,43,58,44,152,119,33,76, | ||
81 | 152,119,35,62,132,119,120,254,255,40,4,58, | ||
82 | 49,152,119,219,72,43,43,112,17,3,0,237, | ||
83 | 56,52,230,248,237,57,52,219,72,230,1,194, | ||
84 | 141,131,209,225,237,56,52,246,6,237,57,52, | ||
85 | 62,1,55,251,201,62,3,211,66,62,192,211, | ||
86 | 66,62,48,211,66,0,0,219,66,230,1,40, | ||
87 | 4,219,67,24,240,205,203,135,58,75,152,254, | ||
88 | 255,202,128,132,58,49,152,254,161,250,207,131, | ||
89 | 58,34,152,211,68,62,10,211,66,62,128,211, | ||
90 | 66,62,11,211,66,62,6,211,66,24,0,62, | ||
91 | 14,211,66,62,33,211,66,62,1,211,66,62, | ||
92 | 64,211,66,62,3,211,66,62,209,211,66,62, | ||
93 | 100,71,219,66,230,1,32,6,5,32,247,195, | ||
94 | 248,132,219,67,71,58,44,152,184,194,248,132, | ||
95 | 62,100,71,219,66,230,1,32,6,5,32,247, | ||
96 | 195,248,132,219,67,62,100,71,219,66,230,1, | ||
97 | 32,6,5,32,247,195,248,132,219,67,254,133, | ||
98 | 32,7,62,0,50,74,152,24,17,254,173,32, | ||
99 | 7,62,1,50,74,152,24,6,254,141,194,248, | ||
100 | 132,71,209,225,58,49,152,254,132,32,10,62, | ||
101 | 50,205,2,134,205,144,135,24,27,254,140,32, | ||
102 | 15,62,110,205,2,134,62,141,184,32,5,205, | ||
103 | 144,135,24,8,62,10,205,2,134,205,8,134, | ||
104 | 62,1,50,106,137,205,158,139,237,56,52,246, | ||
105 | 6,237,57,52,175,183,251,201,62,20,135,237, | ||
106 | 57,20,175,237,57,21,237,56,16,246,2,237, | ||
107 | 57,16,237,56,20,95,237,56,21,123,254,10, | ||
108 | 48,244,237,56,16,230,17,237,57,16,209,225, | ||
109 | 205,144,135,62,1,50,106,137,205,158,139,237, | ||
110 | 56,52,246,6,237,57,52,175,183,251,201,209, | ||
111 | 225,243,219,72,230,1,40,13,62,10,211,66, | ||
112 | 0,0,219,66,230,192,202,226,132,237,56,52, | ||
113 | 246,6,237,57,52,62,1,55,251,201,205,203, | ||
114 | 135,62,1,50,106,137,205,158,139,237,56,52, | ||
115 | 246,6,237,57,52,183,251,201,209,225,62,1, | ||
116 | 50,106,137,205,158,139,237,56,52,246,6,237, | ||
117 | 57,52,62,2,55,251,201,209,225,243,219,72, | ||
118 | 230,1,202,213,132,62,10,211,66,0,0,219, | ||
119 | 66,230,192,194,213,132,229,62,1,50,106,137, | ||
120 | 42,40,152,205,65,143,225,17,3,0,205,111, | ||
121 | 136,62,6,211,66,58,44,152,211,66,237,56, | ||
122 | 52,246,6,237,57,52,183,251,201,209,197,237, | ||
123 | 56,52,230,248,237,57,52,219,72,230,1,32, | ||
124 | 15,193,225,237,56,52,246,6,237,57,52,62, | ||
125 | 1,55,251,201,14,23,58,37,152,254,0,40, | ||
126 | 14,14,2,254,1,32,5,62,140,119,24,3, | ||
127 | 62,132,119,43,43,197,205,203,135,193,62,1, | ||
128 | 211,66,62,64,211,66,62,3,211,66,62,193, | ||
129 | 211,66,62,100,203,39,71,219,66,230,1,32, | ||
130 | 6,5,32,247,195,229,133,33,238,151,219,67, | ||
131 | 71,58,44,152,184,194,229,133,119,62,100,71, | ||
132 | 219,66,230,1,32,6,5,32,247,195,229,133, | ||
133 | 219,67,35,119,13,32,234,193,225,62,1,50, | ||
134 | 106,137,205,158,139,237,56,52,246,6,237,57, | ||
135 | 52,175,183,251,201,33,234,151,35,35,62,255, | ||
136 | 119,193,225,62,1,50,106,137,205,158,139,237, | ||
137 | 56,52,246,6,237,57,52,175,251,201,243,61, | ||
138 | 32,253,251,201,62,3,211,66,62,192,211,66, | ||
139 | 58,49,152,254,140,32,19,197,229,213,17,181, | ||
140 | 129,33,185,129,1,2,0,237,176,209,225,193, | ||
141 | 24,27,229,213,33,187,129,58,49,152,230,15, | ||
142 | 87,30,2,237,92,25,17,181,129,126,18,19, | ||
143 | 35,126,18,209,225,58,34,152,246,8,211,68, | ||
144 | 58,49,152,254,165,40,14,254,164,40,10,62, | ||
145 | 10,211,66,62,224,211,66,24,25,58,74,152, | ||
146 | 254,0,40,10,62,10,211,66,62,160,211,66, | ||
147 | 24,8,62,10,211,66,62,128,211,66,62,11, | ||
148 | 211,66,62,6,211,66,205,147,143,62,5,211, | ||
149 | 66,62,224,211,66,62,5,211,66,62,96,211, | ||
150 | 66,62,5,61,32,253,62,5,211,66,62,224, | ||
151 | 211,66,62,14,61,32,253,62,5,211,66,62, | ||
152 | 233,211,66,62,128,211,66,58,181,129,61,32, | ||
153 | 253,62,1,211,66,62,192,211,66,1,254,19, | ||
154 | 237,56,46,187,32,6,13,32,247,195,226,134, | ||
155 | 62,192,211,66,0,0,219,66,203,119,40,250, | ||
156 | 219,66,203,87,40,250,243,237,56,16,230,17, | ||
157 | 237,57,16,237,56,20,251,62,5,211,66,62, | ||
158 | 224,211,66,58,182,129,61,32,253,229,33,181, | ||
159 | 129,58,183,129,203,63,119,35,58,184,129,119, | ||
160 | 225,62,10,211,66,62,224,211,66,62,11,211, | ||
161 | 66,62,118,211,66,62,47,211,68,62,5,211, | ||
162 | 66,62,233,211,66,58,181,129,61,32,253,62, | ||
163 | 5,211,66,62,224,211,66,58,182,129,61,32, | ||
164 | 253,62,5,211,66,62,96,211,66,201,229,213, | ||
165 | 58,50,152,230,15,87,30,2,237,92,33,187, | ||
166 | 129,25,17,181,129,126,18,35,19,126,18,209, | ||
167 | 225,58,71,152,246,8,211,68,58,50,152,254, | ||
168 | 165,40,14,254,164,40,10,62,10,211,66,62, | ||
169 | 224,211,66,24,8,62,10,211,66,62,128,211, | ||
170 | 66,62,11,211,66,62,6,211,66,195,248,135, | ||
171 | 62,3,211,66,62,192,211,66,197,229,213,17, | ||
172 | 181,129,33,183,129,1,2,0,237,176,209,225, | ||
173 | 193,62,47,211,68,62,10,211,66,62,224,211, | ||
174 | 66,62,11,211,66,62,118,211,66,62,1,211, | ||
175 | 66,62,0,211,66,205,147,143,195,16,136,62, | ||
176 | 3,211,66,62,192,211,66,197,229,213,17,181, | ||
177 | 129,33,183,129,1,2,0,237,176,209,225,193, | ||
178 | 62,47,211,68,62,10,211,66,62,224,211,66, | ||
179 | 62,11,211,66,62,118,211,66,205,147,143,62, | ||
180 | 5,211,66,62,224,211,66,62,5,211,66,62, | ||
181 | 96,211,66,62,5,61,32,253,62,5,211,66, | ||
182 | 62,224,211,66,62,14,61,32,253,62,5,211, | ||
183 | 66,62,233,211,66,62,128,211,66,58,181,129, | ||
184 | 61,32,253,62,1,211,66,62,192,211,66,1, | ||
185 | 254,19,237,56,46,187,32,6,13,32,247,195, | ||
186 | 88,136,62,192,211,66,0,0,219,66,203,119, | ||
187 | 40,250,219,66,203,87,40,250,62,5,211,66, | ||
188 | 62,224,211,66,58,182,129,61,32,253,62,5, | ||
189 | 211,66,62,96,211,66,201,197,14,67,6,0, | ||
190 | 62,3,211,66,62,192,211,66,62,48,211,66, | ||
191 | 0,0,219,66,230,1,40,4,219,67,24,240, | ||
192 | 62,5,211,66,62,233,211,66,62,128,211,66, | ||
193 | 58,181,129,61,32,253,237,163,29,62,192,211, | ||
194 | 66,219,66,230,4,40,250,237,163,29,32,245, | ||
195 | 219,66,230,4,40,250,62,255,71,219,66,230, | ||
196 | 4,40,3,5,32,247,219,66,230,4,40,250, | ||
197 | 62,5,211,66,62,224,211,66,58,182,129,61, | ||
198 | 32,253,62,5,211,66,62,96,211,66,58,71, | ||
199 | 152,254,1,202,18,137,62,16,211,66,62,56, | ||
200 | 211,66,62,14,211,66,62,33,211,66,62,1, | ||
201 | 211,66,62,248,211,66,237,56,48,246,153,230, | ||
202 | 207,237,57,48,62,3,211,66,62,221,211,66, | ||
203 | 193,201,58,71,152,211,68,62,10,211,66,62, | ||
204 | 128,211,66,62,11,211,66,62,6,211,66,62, | ||
205 | 6,211,66,58,44,152,211,66,62,16,211,66, | ||
206 | 62,56,211,66,62,48,211,66,0,0,62,14, | ||
207 | 211,66,62,33,211,66,62,1,211,66,62,248, | ||
208 | 211,66,237,56,48,246,145,246,8,230,207,237, | ||
209 | 57,48,62,3,211,66,62,221,211,66,193,201, | ||
210 | 44,3,1,0,70,69,1,245,197,213,229,175, | ||
211 | 50,72,152,237,56,16,230,46,237,57,16,237, | ||
212 | 56,12,62,1,211,66,0,0,219,66,95,230, | ||
213 | 160,32,3,195,20,139,123,230,96,194,72,139, | ||
214 | 62,48,211,66,62,1,211,66,62,64,211,66, | ||
215 | 237,91,40,152,205,207,143,25,43,55,237,82, | ||
216 | 218,70,139,34,42,152,98,107,58,44,152,190, | ||
217 | 194,210,138,35,35,62,130,190,194,200,137,62, | ||
218 | 1,50,48,152,62,175,190,202,82,139,62,132, | ||
219 | 190,32,44,50,50,152,62,47,50,71,152,229, | ||
220 | 175,50,106,137,42,40,152,205,65,143,225,54, | ||
221 | 133,43,70,58,44,152,119,43,112,17,3,0, | ||
222 | 62,10,205,2,134,205,111,136,195,158,138,62, | ||
223 | 140,190,32,19,50,50,152,58,233,149,230,4, | ||
224 | 202,222,138,62,1,50,71,152,195,219,137,126, | ||
225 | 254,160,250,185,138,254,166,242,185,138,50,50, | ||
226 | 152,43,126,35,229,213,33,234,149,95,22,0, | ||
227 | 25,126,254,132,40,18,254,140,40,14,58,50, | ||
228 | 152,230,15,87,126,31,21,242,65,138,56,2, | ||
229 | 175,119,58,50,152,230,15,87,58,233,149,230, | ||
230 | 62,31,21,242,85,138,218,98,138,209,225,195, | ||
231 | 20,139,58,50,152,33,100,137,230,15,95,22, | ||
232 | 0,25,126,50,71,152,209,225,58,50,152,254, | ||
233 | 164,250,135,138,58,73,152,254,0,40,4,54, | ||
234 | 173,24,2,54,133,43,70,58,44,152,119,43, | ||
235 | 112,17,3,0,205,70,135,175,50,106,137,205, | ||
236 | 208,139,58,199,129,237,57,12,58,200,129,237, | ||
237 | 57,13,237,56,16,246,17,237,57,16,225,209, | ||
238 | 193,241,251,237,77,62,129,190,194,227,138,54, | ||
239 | 130,43,70,58,44,152,119,43,112,17,3,0, | ||
240 | 205,144,135,195,20,139,35,35,126,254,132,194, | ||
241 | 227,138,175,50,106,137,205,158,139,24,42,58, | ||
242 | 201,154,254,1,40,7,62,1,50,106,137,24, | ||
243 | 237,58,106,137,254,1,202,222,138,62,128,166, | ||
244 | 194,222,138,221,229,221,33,67,152,205,127,142, | ||
245 | 205,109,144,221,225,225,209,193,241,251,237,77, | ||
246 | 58,106,137,254,1,202,44,139,58,50,152,254, | ||
247 | 164,250,44,139,58,73,152,238,1,50,73,152, | ||
248 | 221,229,221,33,51,152,205,127,142,221,225,62, | ||
249 | 1,50,106,137,205,158,139,195,13,139,24,208, | ||
250 | 24,206,24,204,230,64,40,3,195,20,139,195, | ||
251 | 20,139,43,126,33,8,152,119,35,58,44,152, | ||
252 | 119,43,237,91,35,152,205,203,135,205,158,139, | ||
253 | 195,13,139,175,50,78,152,62,3,211,66,62, | ||
254 | 192,211,66,201,197,33,4,0,57,126,35,102, | ||
255 | 111,62,1,50,106,137,219,72,205,141,139,193, | ||
256 | 201,62,1,50,78,152,34,40,152,54,0,35, | ||
257 | 35,54,0,195,163,139,58,78,152,183,200,229, | ||
258 | 33,181,129,58,183,129,119,35,58,184,129,119, | ||
259 | 225,62,47,211,68,62,14,211,66,62,193,211, | ||
260 | 66,62,10,211,66,62,224,211,66,62,11,211, | ||
261 | 66,62,118,211,66,195,3,140,58,78,152,183, | ||
262 | 200,58,71,152,211,68,254,69,40,4,254,70, | ||
263 | 32,17,58,73,152,254,0,40,10,62,10,211, | ||
264 | 66,62,160,211,66,24,8,62,10,211,66,62, | ||
265 | 128,211,66,62,11,211,66,62,6,211,66,62, | ||
266 | 6,211,66,58,44,152,211,66,62,16,211,66, | ||
267 | 62,56,211,66,62,48,211,66,0,0,219,66, | ||
268 | 230,1,40,4,219,67,24,240,62,14,211,66, | ||
269 | 62,33,211,66,42,40,152,205,65,143,62,1, | ||
270 | 211,66,62,248,211,66,237,56,48,246,145,246, | ||
271 | 8,230,207,237,57,48,62,3,211,66,62,221, | ||
272 | 211,66,201,62,16,211,66,62,56,211,66,62, | ||
273 | 48,211,66,0,0,219,66,230,1,40,4,219, | ||
274 | 67,24,240,62,14,211,66,62,33,211,66,62, | ||
275 | 1,211,66,62,248,211,66,237,56,48,246,153, | ||
276 | 230,207,237,57,48,62,3,211,66,62,221,211, | ||
277 | 66,201,229,213,33,234,149,95,22,0,25,126, | ||
278 | 254,132,40,4,254,140,32,2,175,119,123,209, | ||
279 | 225,201,6,8,14,0,31,48,1,12,16,250, | ||
280 | 121,201,33,4,0,57,94,35,86,33,2,0, | ||
281 | 57,126,35,102,111,221,229,34,89,152,237,83, | ||
282 | 91,152,221,33,63,152,205,127,142,58,81,152, | ||
283 | 50,82,152,58,80,152,135,50,80,152,205,162, | ||
284 | 140,254,3,56,16,58,81,152,135,60,230,15, | ||
285 | 50,81,152,175,50,80,152,24,23,58,79,152, | ||
286 | 205,162,140,254,3,48,13,58,81,152,203,63, | ||
287 | 50,81,152,62,255,50,79,152,58,81,152,50, | ||
288 | 82,152,58,79,152,135,50,79,152,62,32,50, | ||
289 | 83,152,50,84,152,237,56,16,230,17,237,57, | ||
290 | 16,219,72,62,192,50,93,152,62,93,50,94, | ||
291 | 152,58,93,152,61,50,93,152,32,9,58,94, | ||
292 | 152,61,50,94,152,40,44,62,170,237,57,20, | ||
293 | 175,237,57,21,237,56,16,246,2,237,57,16, | ||
294 | 219,72,230,1,202,29,141,237,56,20,71,237, | ||
295 | 56,21,120,254,10,48,237,237,56,16,230,17, | ||
296 | 237,57,16,243,62,14,211,66,62,65,211,66, | ||
297 | 251,58,39,152,23,23,60,50,39,152,71,58, | ||
298 | 82,152,160,230,15,40,22,71,14,10,219,66, | ||
299 | 230,16,202,186,141,219,72,230,1,202,186,141, | ||
300 | 13,32,239,16,235,42,89,152,237,91,91,152, | ||
301 | 205,47,131,48,7,61,202,186,141,195,227,141, | ||
302 | 221,225,33,0,0,201,221,33,55,152,205,127, | ||
303 | 142,58,84,152,61,50,84,152,40,19,58,82, | ||
304 | 152,246,1,50,82,152,58,79,152,246,1,50, | ||
305 | 79,152,195,29,141,221,225,33,1,0,201,221, | ||
306 | 33,59,152,205,127,142,58,80,152,246,1,50, | ||
307 | 80,152,58,82,152,135,246,1,50,82,152,58, | ||
308 | 83,152,61,50,83,152,194,29,141,221,225,33, | ||
309 | 2,0,201,221,229,33,0,0,57,17,4,0, | ||
310 | 25,126,50,44,152,230,128,50,85,152,58,85, | ||
311 | 152,183,40,6,221,33,88,2,24,4,221,33, | ||
312 | 150,0,58,44,152,183,40,53,60,40,50,60, | ||
313 | 40,47,61,61,33,86,152,119,35,119,35,54, | ||
314 | 129,175,50,48,152,221,43,221,229,225,124,181, | ||
315 | 40,42,33,86,152,17,3,0,205,189,140,17, | ||
316 | 232,3,27,123,178,32,251,58,48,152,183,40, | ||
317 | 224,58,44,152,71,62,7,128,230,127,71,58, | ||
318 | 85,152,176,50,44,152,24,162,221,225,201,183, | ||
319 | 221,52,0,192,221,52,1,192,221,52,2,192, | ||
320 | 221,52,3,192,55,201,245,62,1,211,100,241, | ||
321 | 201,245,62,1,211,96,241,201,33,2,0,57, | ||
322 | 126,35,102,111,237,56,48,230,175,237,57,48, | ||
323 | 62,48,237,57,49,125,237,57,32,124,237,57, | ||
324 | 33,62,0,237,57,34,62,88,237,57,35,62, | ||
325 | 0,237,57,36,237,57,37,33,128,2,125,237, | ||
326 | 57,38,124,237,57,39,237,56,48,246,97,230, | ||
327 | 207,237,57,48,62,0,237,57,0,62,0,211, | ||
328 | 96,211,100,201,33,2,0,57,126,35,102,111, | ||
329 | 237,56,48,230,175,237,57,48,62,12,237,57, | ||
330 | 49,62,76,237,57,32,62,0,237,57,33,237, | ||
331 | 57,34,125,237,57,35,124,237,57,36,62,0, | ||
332 | 237,57,37,33,128,2,125,237,57,38,124,237, | ||
333 | 57,39,237,56,48,246,97,230,207,237,57,48, | ||
334 | 62,1,211,96,201,33,2,0,57,126,35,102, | ||
335 | 111,229,237,56,48,230,87,237,57,48,125,237, | ||
336 | 57,40,124,237,57,41,62,0,237,57,42,62, | ||
337 | 67,237,57,43,62,0,237,57,44,58,106,137, | ||
338 | 254,1,32,5,33,6,0,24,3,33,128,2, | ||
339 | 125,237,57,46,124,237,57,47,237,56,50,230, | ||
340 | 252,246,2,237,57,50,225,201,33,4,0,57, | ||
341 | 94,35,86,33,2,0,57,126,35,102,111,237, | ||
342 | 56,48,230,87,237,57,48,125,237,57,40,124, | ||
343 | 237,57,41,62,0,237,57,42,62,67,237,57, | ||
344 | 43,62,0,237,57,44,123,237,57,46,122,237, | ||
345 | 57,47,237,56,50,230,244,246,0,237,57,50, | ||
346 | 237,56,48,246,145,230,207,237,57,48,201,213, | ||
347 | 237,56,46,95,237,56,47,87,237,56,46,111, | ||
348 | 237,56,47,103,183,237,82,32,235,33,128,2, | ||
349 | 183,237,82,209,201,213,237,56,38,95,237,56, | ||
350 | 39,87,237,56,38,111,237,56,39,103,183,237, | ||
351 | 82,32,235,33,128,2,183,237,82,209,201,245, | ||
352 | 197,1,52,0,237,120,230,253,237,121,193,241, | ||
353 | 201,245,197,1,52,0,237,120,246,2,237,121, | ||
354 | 193,241,201,33,2,0,57,126,35,102,111,126, | ||
355 | 35,110,103,201,33,0,0,34,102,152,34,96, | ||
356 | 152,34,98,152,33,202,154,34,104,152,237,91, | ||
357 | 104,152,42,226,149,183,237,82,17,0,255,25, | ||
358 | 34,100,152,203,124,40,6,33,0,125,34,100, | ||
359 | 152,42,104,152,35,35,35,229,205,120,139,193, | ||
360 | 201,205,186,149,229,42,40,152,35,35,35,229, | ||
361 | 205,39,144,193,124,230,3,103,221,117,254,221, | ||
362 | 116,255,237,91,42,152,35,35,35,183,237,82, | ||
363 | 32,12,17,5,0,42,42,152,205,171,149,242, | ||
364 | 169,144,42,40,152,229,205,120,139,193,195,198, | ||
365 | 149,237,91,42,152,42,98,152,25,34,98,152, | ||
366 | 19,19,19,42,102,152,25,34,102,152,237,91, | ||
367 | 100,152,33,158,253,25,237,91,102,152,205,171, | ||
368 | 149,242,214,144,33,0,0,34,102,152,62,1, | ||
369 | 50,95,152,205,225,144,195,198,149,58,95,152, | ||
370 | 183,200,237,91,96,152,42,102,152,205,171,149, | ||
371 | 242,5,145,237,91,102,152,33,98,2,25,237, | ||
372 | 91,96,152,205,171,149,250,37,145,237,91,96, | ||
373 | 152,42,102,152,183,237,82,32,7,42,98,152, | ||
374 | 125,180,40,13,237,91,102,152,42,96,152,205, | ||
375 | 171,149,242,58,145,237,91,104,152,42,102,152, | ||
376 | 25,35,35,35,229,205,120,139,193,175,50,95, | ||
377 | 152,201,195,107,139,205,206,149,250,255,243,205, | ||
378 | 225,144,251,58,230,149,183,194,198,149,17,1, | ||
379 | 0,42,98,152,205,171,149,250,198,149,62,1, | ||
380 | 50,230,149,237,91,96,152,42,104,152,25,221, | ||
381 | 117,252,221,116,253,237,91,104,152,42,96,152, | ||
382 | 25,35,35,35,221,117,254,221,116,255,35,35, | ||
383 | 35,229,205,39,144,124,230,3,103,35,35,35, | ||
384 | 221,117,250,221,116,251,235,221,110,252,221,102, | ||
385 | 253,115,35,114,35,54,4,62,1,211,100,211, | ||
386 | 84,195,198,149,33,0,0,34,102,152,34,96, | ||
387 | 152,34,98,152,33,202,154,34,104,152,237,91, | ||
388 | 104,152,42,226,149,183,237,82,17,0,255,25, | ||
389 | 34,100,152,33,109,152,54,0,33,107,152,229, | ||
390 | 205,240,142,193,62,47,50,34,152,62,132,50, | ||
391 | 49,152,205,241,145,205,61,145,58,39,152,60, | ||
392 | 50,39,152,24,241,205,206,149,251,255,33,109, | ||
393 | 152,126,183,202,198,149,110,221,117,251,33,109, | ||
394 | 152,54,0,221,126,251,254,1,40,28,254,3, | ||
395 | 40,101,254,4,202,190,147,254,5,202,147,147, | ||
396 | 254,8,40,87,33,107,152,229,205,240,142,195, | ||
397 | 198,149,58,201,154,183,32,21,33,111,152,126, | ||
398 | 50,229,149,205,52,144,33,110,152,110,38,0, | ||
399 | 229,205,11,142,193,237,91,96,152,42,104,152, | ||
400 | 25,221,117,254,221,116,255,35,35,54,2,17, | ||
401 | 2,0,43,43,115,35,114,58,44,152,35,35, | ||
402 | 119,58,228,149,35,119,62,1,211,100,211,84, | ||
403 | 62,1,50,201,154,24,169,205,153,142,58,231, | ||
404 | 149,183,40,250,175,50,231,149,33,110,152,126, | ||
405 | 254,255,40,91,58,233,149,230,63,183,40,83, | ||
406 | 94,22,0,33,234,149,25,126,183,40,13,33, | ||
407 | 110,152,94,33,234,150,25,126,254,3,32,36, | ||
408 | 205,81,148,125,180,33,110,152,94,22,0,40, | ||
409 | 17,33,234,149,25,54,0,33,107,152,229,205, | ||
410 | 240,142,193,195,198,149,33,234,150,25,54,0, | ||
411 | 33,110,152,94,22,0,33,234,149,25,126,50, | ||
412 | 49,152,254,132,32,37,62,47,50,34,152,42, | ||
413 | 107,152,229,33,110,152,229,205,174,140,193,193, | ||
414 | 125,180,33,110,152,94,22,0,33,234,150,202, | ||
415 | 117,147,25,52,195,120,147,58,49,152,254,140, | ||
416 | 32,7,62,1,50,34,152,24,210,62,32,50, | ||
417 | 106,152,24,19,58,49,152,95,58,106,152,163, | ||
418 | 183,58,106,152,32,11,203,63,50,106,152,58, | ||
419 | 106,152,183,32,231,254,2,40,51,254,4,40, | ||
420 | 38,254,8,40,26,254,16,40,13,254,32,32, | ||
421 | 158,62,165,50,49,152,62,69,24,190,62,164, | ||
422 | 50,49,152,62,70,24,181,62,163,50,49,152, | ||
423 | 175,24,173,62,162,50,49,152,62,1,24,164, | ||
424 | 62,161,50,49,152,62,3,24,155,25,54,0, | ||
425 | 221,126,251,254,8,40,7,58,230,149,183,202, | ||
426 | 32,146,33,107,152,229,205,240,142,193,211,84, | ||
427 | 195,198,149,237,91,96,152,42,104,152,25,221, | ||
428 | 117,254,221,116,255,35,35,54,6,17,2,0, | ||
429 | 43,43,115,35,114,58,228,149,35,35,119,58, | ||
430 | 233,149,35,119,205,146,142,195,32,146,237,91, | ||
431 | 96,152,42,104,152,25,229,205,160,142,193,58, | ||
432 | 231,149,183,40,250,175,50,231,149,243,237,91, | ||
433 | 96,152,42,104,152,25,221,117,254,221,116,255, | ||
434 | 78,35,70,221,113,252,221,112,253,89,80,42, | ||
435 | 98,152,183,237,82,34,98,152,203,124,40,19, | ||
436 | 33,0,0,34,98,152,34,102,152,34,96,152, | ||
437 | 62,1,50,95,152,24,40,221,94,252,221,86, | ||
438 | 253,19,19,19,42,96,152,25,34,96,152,237, | ||
439 | 91,100,152,33,158,253,25,237,91,96,152,205, | ||
440 | 171,149,242,55,148,33,0,0,34,96,152,175, | ||
441 | 50,230,149,251,195,32,146,245,62,1,50,231, | ||
442 | 149,62,16,237,57,0,211,80,241,251,237,77, | ||
443 | 201,205,186,149,229,229,33,0,0,34,37,152, | ||
444 | 33,110,152,126,50,234,151,58,44,152,33,235, | ||
445 | 151,119,221,54,253,0,221,54,254,0,195,230, | ||
446 | 148,33,236,151,54,175,33,3,0,229,33,234, | ||
447 | 151,229,205,174,140,193,193,33,236,151,126,254, | ||
448 | 255,40,74,33,245,151,110,221,117,255,33,249, | ||
449 | 151,126,221,166,255,221,119,255,33,253,151,126, | ||
450 | 221,166,255,221,119,255,58,232,149,95,221,126, | ||
451 | 255,163,221,119,255,183,40,15,230,191,33,110, | ||
452 | 152,94,22,0,33,234,149,25,119,24,12,33, | ||
453 | 110,152,94,22,0,33,234,149,25,54,132,33, | ||
454 | 0,0,195,198,149,221,110,253,221,102,254,35, | ||
455 | 221,117,253,221,116,254,17,32,0,221,110,253, | ||
456 | 221,102,254,205,171,149,250,117,148,58,233,149, | ||
457 | 203,87,40,84,33,1,0,34,37,152,221,54, | ||
458 | 253,0,221,54,254,0,24,53,33,236,151,54, | ||
459 | 175,33,3,0,229,33,234,151,229,205,174,140, | ||
460 | 193,193,33,236,151,126,254,255,40,14,33,110, | ||
461 | 152,94,22,0,33,234,149,25,54,140,24,159, | ||
462 | 221,110,253,221,102,254,35,221,117,253,221,116, | ||
463 | 254,17,32,0,221,110,253,221,102,254,205,171, | ||
464 | 149,250,12,149,33,2,0,34,37,152,221,54, | ||
465 | 253,0,221,54,254,0,24,54,33,236,151,54, | ||
466 | 175,33,3,0,229,33,234,151,229,205,174,140, | ||
467 | 193,193,33,236,151,126,254,255,40,15,33,110, | ||
468 | 152,94,22,0,33,234,149,25,54,132,195,211, | ||
469 | 148,221,110,253,221,102,254,35,221,117,253,221, | ||
470 | 116,254,17,32,0,221,110,253,221,102,254,205, | ||
471 | 171,149,250,96,149,33,1,0,195,198,149,124, | ||
472 | 170,250,179,149,237,82,201,124,230,128,237,82, | ||
473 | 60,201,225,253,229,221,229,221,33,0,0,221, | ||
474 | 57,233,221,249,221,225,253,225,201,233,225,253, | ||
475 | 229,221,229,221,33,0,0,221,57,94,35,86, | ||
476 | 35,235,57,249,235,233,0,0,0,0,0,0, | ||
477 | 62,0,0,0,0,0,0,0,0,0,0,0, | ||
478 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
479 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
480 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
481 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
482 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
483 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
484 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
485 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
486 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
487 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
488 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
489 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
490 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
491 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
492 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
493 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
494 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
495 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
496 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
497 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
498 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
499 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
500 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
501 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
502 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
503 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
504 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
505 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
506 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
507 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
508 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
509 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
510 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
511 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
512 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
513 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
514 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
515 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
516 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
517 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
518 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
519 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
520 | 175,0,0,0,0,0,0,0,0,0,0,0, | ||
521 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
522 | 0,0,0,0,0,0,133,1,0,0,0,63, | ||
523 | 255,255,255,255,0,0,0,63,0,0,0,0, | ||
524 | 0,0,0,0,0,0,0,24,0,0,0,0, | ||
525 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
526 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
527 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
528 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
529 | 0,0,0,0,0,0,0 | ||
530 | } ; | ||
531 | |||
532 | #endif | ||
diff --git a/drivers/staging/appletalk/cops_ltdrv.h b/drivers/staging/appletalk/cops_ltdrv.h new file mode 100644 index 00000000000..c699b1ad31d --- /dev/null +++ b/drivers/staging/appletalk/cops_ltdrv.h | |||
@@ -0,0 +1,241 @@ | |||
1 | /* | ||
2 | * The firmware this driver downloads into the Localtalk card is a | ||
3 | * separate program and is not GPL'd source code, even though the Linux | ||
4 | * side driver and the routine that loads this data into the card are. | ||
5 | * | ||
6 | * It is taken from the COPS SDK and is under the following license | ||
7 | * | ||
8 | * This material is licensed to you strictly for use in conjunction with | ||
9 | * the use of COPS LocalTalk adapters. | ||
10 | * There is no charge for this SDK. And no waranty express or implied | ||
11 | * about its fitness for any purpose. However, we will cheerefully | ||
12 | * refund every penny you paid for this SDK... | ||
13 | * Regards, | ||
14 | * | ||
15 | * Thomas F. Divine | ||
16 | * Chief Scientist | ||
17 | */ | ||
18 | |||
19 | |||
20 | /* cops_ltdrv.h: LocalTalk driver firmware dump for Linux. | ||
21 | * | ||
22 | * Authors: | ||
23 | * - Jay Schulist <jschlst@samba.org> | ||
24 | */ | ||
25 | |||
26 | |||
27 | #ifdef CONFIG_COPS_TANGENT | ||
28 | |||
29 | static const unsigned char ltdrv_code[] = { | ||
30 | 58,3,0,50,148,10,33,143,15,62,85,119, | ||
31 | 190,32,9,62,170,119,190,32,3,35,24,241, | ||
32 | 34,146,10,249,17,150,10,33,143,15,183,237, | ||
33 | 82,77,68,11,107,98,19,54,0,237,176,62, | ||
34 | 16,237,57,51,62,0,237,57,50,237,57,54, | ||
35 | 62,12,237,57,49,62,195,33,39,2,50,56, | ||
36 | 0,34,57,0,237,86,205,30,2,251,205,60, | ||
37 | 10,24,169,67,111,112,121,114,105,103,104,116, | ||
38 | 32,40,99,41,32,49,57,56,56,45,49,57, | ||
39 | 57,50,44,32,80,114,105,110,116,105,110,103, | ||
40 | 32,67,111,109,109,117,110,105,99,97,116,105, | ||
41 | 111,110,115,32,65,115,115,111,99,105,97,116, | ||
42 | 101,115,44,32,73,110,99,46,65,108,108,32, | ||
43 | 114,105,103,104,116,115,32,114,101,115,101,114, | ||
44 | 118,101,100,46,32,32,4,4,22,40,255,60, | ||
45 | 4,96,10,224,6,0,7,126,2,64,11,246, | ||
46 | 12,6,13,0,14,193,15,0,5,96,3,192, | ||
47 | 1,0,9,8,62,3,211,82,62,192,211,82, | ||
48 | 201,62,3,211,82,62,213,211,82,201,62,5, | ||
49 | 211,82,62,224,211,82,201,62,5,211,82,62, | ||
50 | 224,211,82,201,62,5,211,82,62,96,211,82, | ||
51 | 201,6,28,33,180,1,14,82,237,163,194,4, | ||
52 | 2,33,39,2,34,64,0,58,3,0,230,1, | ||
53 | 192,62,11,237,121,62,118,237,121,201,33,182, | ||
54 | 10,54,132,205,253,1,201,245,197,213,229,42, | ||
55 | 150,10,14,83,17,98,2,67,20,237,162,58, | ||
56 | 179,1,95,219,82,230,1,32,6,29,32,247, | ||
57 | 195,17,3,62,1,211,82,219,82,95,230,160, | ||
58 | 32,10,237,162,32,225,21,32,222,195,15,3, | ||
59 | 237,162,123,230,96,194,21,3,62,48,211,82, | ||
60 | 62,1,211,82,175,211,82,237,91,150,10,43, | ||
61 | 55,237,82,218,19,3,34,152,10,98,107,58, | ||
62 | 154,10,190,32,81,62,1,50,158,10,35,35, | ||
63 | 62,132,190,32,44,54,133,43,70,58,154,10, | ||
64 | 119,43,112,17,3,0,205,137,3,62,16,211, | ||
65 | 82,62,56,211,82,205,217,1,42,150,10,14, | ||
66 | 83,17,98,2,67,20,58,178,1,95,195,59, | ||
67 | 2,62,129,190,194,227,2,54,130,43,70,58, | ||
68 | 154,10,119,43,112,17,3,0,205,137,3,195, | ||
69 | 254,2,35,35,126,254,132,194,227,2,205,61, | ||
70 | 3,24,20,62,128,166,194,222,2,221,229,221, | ||
71 | 33,175,10,205,93,6,205,144,7,221,225,225, | ||
72 | 209,193,241,251,237,77,221,229,221,33,159,10, | ||
73 | 205,93,6,221,225,205,61,3,195,247,2,24, | ||
74 | 237,24,235,24,233,230,64,40,2,24,227,24, | ||
75 | 225,175,50,179,10,205,208,1,201,197,33,4, | ||
76 | 0,57,126,35,102,111,205,51,3,193,201,62, | ||
77 | 1,50,179,10,34,150,10,54,0,58,179,10, | ||
78 | 183,200,62,14,211,82,62,193,211,82,62,10, | ||
79 | 211,82,62,224,211,82,62,6,211,82,58,154, | ||
80 | 10,211,82,62,16,211,82,62,56,211,82,62, | ||
81 | 48,211,82,219,82,230,1,40,4,219,83,24, | ||
82 | 242,62,14,211,82,62,33,211,82,62,1,211, | ||
83 | 82,62,9,211,82,62,32,211,82,205,217,1, | ||
84 | 201,14,83,205,208,1,24,23,14,83,205,208, | ||
85 | 1,205,226,1,58,174,1,61,32,253,205,244, | ||
86 | 1,58,174,1,61,32,253,205,226,1,58,175, | ||
87 | 1,61,32,253,62,5,211,82,62,233,211,82, | ||
88 | 62,128,211,82,58,176,1,61,32,253,237,163, | ||
89 | 27,62,192,211,82,219,82,230,4,40,250,237, | ||
90 | 163,27,122,179,32,243,219,82,230,4,40,250, | ||
91 | 58,178,1,71,219,82,230,4,40,3,5,32, | ||
92 | 247,219,82,230,4,40,250,205,235,1,58,177, | ||
93 | 1,61,32,253,205,244,1,201,229,213,35,35, | ||
94 | 126,230,128,194,145,4,43,58,154,10,119,43, | ||
95 | 70,33,181,10,119,43,112,17,3,0,243,62, | ||
96 | 10,211,82,219,82,230,128,202,41,4,209,225, | ||
97 | 62,1,55,251,201,205,144,3,58,180,10,254, | ||
98 | 255,202,127,4,205,217,1,58,178,1,71,219, | ||
99 | 82,230,1,32,6,5,32,247,195,173,4,219, | ||
100 | 83,71,58,154,10,184,194,173,4,58,178,1, | ||
101 | 71,219,82,230,1,32,6,5,32,247,195,173, | ||
102 | 4,219,83,58,178,1,71,219,82,230,1,32, | ||
103 | 6,5,32,247,195,173,4,219,83,254,133,194, | ||
104 | 173,4,58,179,1,24,4,58,179,1,135,61, | ||
105 | 32,253,209,225,205,137,3,205,61,3,183,251, | ||
106 | 201,209,225,243,62,10,211,82,219,82,230,128, | ||
107 | 202,164,4,62,1,55,251,201,205,144,3,205, | ||
108 | 61,3,183,251,201,209,225,62,2,55,251,201, | ||
109 | 243,62,14,211,82,62,33,211,82,251,201,33, | ||
110 | 4,0,57,94,35,86,33,2,0,57,126,35, | ||
111 | 102,111,221,229,34,193,10,237,83,195,10,221, | ||
112 | 33,171,10,205,93,6,58,185,10,50,186,10, | ||
113 | 58,184,10,135,50,184,10,205,112,6,254,3, | ||
114 | 56,16,58,185,10,135,60,230,15,50,185,10, | ||
115 | 175,50,184,10,24,23,58,183,10,205,112,6, | ||
116 | 254,3,48,13,58,185,10,203,63,50,185,10, | ||
117 | 62,255,50,183,10,58,185,10,50,186,10,58, | ||
118 | 183,10,135,50,183,10,62,32,50,187,10,50, | ||
119 | 188,10,6,255,219,82,230,16,32,3,5,32, | ||
120 | 247,205,180,4,6,40,219,82,230,16,40,3, | ||
121 | 5,32,247,62,10,211,82,219,82,230,128,194, | ||
122 | 46,5,219,82,230,16,40,214,237,95,71,58, | ||
123 | 186,10,160,230,15,40,32,71,14,10,62,10, | ||
124 | 211,82,219,82,230,128,202,119,5,205,180,4, | ||
125 | 195,156,5,219,82,230,16,202,156,5,13,32, | ||
126 | 229,16,225,42,193,10,237,91,195,10,205,252, | ||
127 | 3,48,7,61,202,156,5,195,197,5,221,225, | ||
128 | 33,0,0,201,221,33,163,10,205,93,6,58, | ||
129 | 188,10,61,50,188,10,40,19,58,186,10,246, | ||
130 | 1,50,186,10,58,183,10,246,1,50,183,10, | ||
131 | 195,46,5,221,225,33,1,0,201,221,33,167, | ||
132 | 10,205,93,6,58,184,10,246,1,50,184,10, | ||
133 | 58,186,10,135,246,1,50,186,10,58,187,10, | ||
134 | 61,50,187,10,194,46,5,221,225,33,2,0, | ||
135 | 201,221,229,33,0,0,57,17,4,0,25,126, | ||
136 | 50,154,10,230,128,50,189,10,58,189,10,183, | ||
137 | 40,6,221,33,88,2,24,4,221,33,150,0, | ||
138 | 58,154,10,183,40,49,60,40,46,61,33,190, | ||
139 | 10,119,35,119,35,54,129,175,50,158,10,221, | ||
140 | 43,221,229,225,124,181,40,42,33,190,10,17, | ||
141 | 3,0,205,206,4,17,232,3,27,123,178,32, | ||
142 | 251,58,158,10,183,40,224,58,154,10,71,62, | ||
143 | 7,128,230,127,71,58,189,10,176,50,154,10, | ||
144 | 24,166,221,225,201,183,221,52,0,192,221,52, | ||
145 | 1,192,221,52,2,192,221,52,3,192,55,201, | ||
146 | 6,8,14,0,31,48,1,12,16,250,121,201, | ||
147 | 33,2,0,57,94,35,86,35,78,35,70,35, | ||
148 | 126,35,102,105,79,120,68,103,237,176,201,33, | ||
149 | 2,0,57,126,35,102,111,62,17,237,57,48, | ||
150 | 125,237,57,40,124,237,57,41,62,0,237,57, | ||
151 | 42,62,64,237,57,43,62,0,237,57,44,33, | ||
152 | 128,2,125,237,57,46,124,237,57,47,62,145, | ||
153 | 237,57,48,211,68,58,149,10,211,66,201,33, | ||
154 | 2,0,57,126,35,102,111,62,33,237,57,48, | ||
155 | 62,64,237,57,32,62,0,237,57,33,237,57, | ||
156 | 34,125,237,57,35,124,237,57,36,62,0,237, | ||
157 | 57,37,33,128,2,125,237,57,38,124,237,57, | ||
158 | 39,62,97,237,57,48,211,67,58,149,10,211, | ||
159 | 66,201,237,56,46,95,237,56,47,87,237,56, | ||
160 | 46,111,237,56,47,103,183,237,82,32,235,33, | ||
161 | 128,2,183,237,82,201,237,56,38,95,237,56, | ||
162 | 39,87,237,56,38,111,237,56,39,103,183,237, | ||
163 | 82,32,235,33,128,2,183,237,82,201,205,106, | ||
164 | 10,221,110,6,221,102,7,126,35,110,103,195, | ||
165 | 118,10,205,106,10,33,0,0,34,205,10,34, | ||
166 | 198,10,34,200,10,33,143,15,34,207,10,237, | ||
167 | 91,207,10,42,146,10,183,237,82,17,0,255, | ||
168 | 25,34,203,10,203,124,40,6,33,0,125,34, | ||
169 | 203,10,42,207,10,229,205,37,3,195,118,10, | ||
170 | 205,106,10,229,42,150,10,35,35,35,229,205, | ||
171 | 70,7,193,124,230,3,103,221,117,254,221,116, | ||
172 | 255,237,91,152,10,35,35,35,183,237,82,32, | ||
173 | 12,17,5,0,42,152,10,205,91,10,242,203, | ||
174 | 7,42,150,10,229,205,37,3,195,118,10,237, | ||
175 | 91,152,10,42,200,10,25,34,200,10,42,205, | ||
176 | 10,25,34,205,10,237,91,203,10,33,158,253, | ||
177 | 25,237,91,205,10,205,91,10,242,245,7,33, | ||
178 | 0,0,34,205,10,62,1,50,197,10,205,5, | ||
179 | 8,33,0,0,57,249,195,118,10,205,106,10, | ||
180 | 58,197,10,183,202,118,10,237,91,198,10,42, | ||
181 | 205,10,205,91,10,242,46,8,237,91,205,10, | ||
182 | 33,98,2,25,237,91,198,10,205,91,10,250, | ||
183 | 78,8,237,91,198,10,42,205,10,183,237,82, | ||
184 | 32,7,42,200,10,125,180,40,13,237,91,205, | ||
185 | 10,42,198,10,205,91,10,242,97,8,237,91, | ||
186 | 207,10,42,205,10,25,229,205,37,3,175,50, | ||
187 | 197,10,195,118,10,205,29,3,33,0,0,57, | ||
188 | 249,195,118,10,205,106,10,58,202,10,183,40, | ||
189 | 22,205,14,7,237,91,209,10,19,19,19,205, | ||
190 | 91,10,242,139,8,33,1,0,195,118,10,33, | ||
191 | 0,0,195,118,10,205,126,10,252,255,205,108, | ||
192 | 8,125,180,194,118,10,237,91,200,10,33,0, | ||
193 | 0,205,91,10,242,118,10,237,91,207,10,42, | ||
194 | 198,10,25,221,117,254,221,116,255,35,35,35, | ||
195 | 229,205,70,7,193,124,230,3,103,35,35,35, | ||
196 | 221,117,252,221,116,253,229,221,110,254,221,102, | ||
197 | 255,229,33,212,10,229,205,124,6,193,193,221, | ||
198 | 110,252,221,102,253,34,209,10,33,211,10,54, | ||
199 | 4,33,209,10,227,205,147,6,193,62,1,50, | ||
200 | 202,10,243,221,94,252,221,86,253,42,200,10, | ||
201 | 183,237,82,34,200,10,203,124,40,17,33,0, | ||
202 | 0,34,200,10,34,205,10,34,198,10,50,197, | ||
203 | 10,24,37,221,94,252,221,86,253,42,198,10, | ||
204 | 25,34,198,10,237,91,203,10,33,158,253,25, | ||
205 | 237,91,198,10,205,91,10,242,68,9,33,0, | ||
206 | 0,34,198,10,205,5,8,33,0,0,57,249, | ||
207 | 251,195,118,10,205,106,10,33,49,13,126,183, | ||
208 | 40,16,205,42,7,237,91,47,13,19,19,19, | ||
209 | 205,91,10,242,117,9,58,142,15,198,1,50, | ||
210 | 142,15,195,118,10,33,49,13,126,254,1,40, | ||
211 | 25,254,3,202,7,10,254,5,202,21,10,33, | ||
212 | 49,13,54,0,33,47,13,229,205,207,6,195, | ||
213 | 118,10,58,141,15,183,32,72,33,51,13,126, | ||
214 | 50,149,10,205,86,7,33,50,13,126,230,127, | ||
215 | 183,32,40,58,142,15,230,127,50,142,15,183, | ||
216 | 32,5,198,1,50,142,15,33,50,13,126,111, | ||
217 | 23,159,103,203,125,58,142,15,40,5,198,128, | ||
218 | 50,142,15,33,50,13,119,33,50,13,126,111, | ||
219 | 23,159,103,229,205,237,5,193,33,211,10,54, | ||
220 | 2,33,2,0,34,209,10,58,154,10,33,212, | ||
221 | 10,119,58,148,10,33,213,10,119,33,209,10, | ||
222 | 229,205,147,6,193,24,128,42,47,13,229,33, | ||
223 | 50,13,229,205,191,4,193,24,239,33,211,10, | ||
224 | 54,6,33,3,0,34,209,10,58,154,10,33, | ||
225 | 212,10,119,58,148,10,33,213,10,119,33,214, | ||
226 | 10,54,5,33,209,10,229,205,147,6,24,200, | ||
227 | 205,106,10,33,49,13,54,0,33,47,13,229, | ||
228 | 205,207,6,33,209,10,227,205,147,6,193,205, | ||
229 | 80,9,205,145,8,24,248,124,170,250,99,10, | ||
230 | 237,82,201,124,230,128,237,82,60,201,225,253, | ||
231 | 229,221,229,221,33,0,0,221,57,233,221,249, | ||
232 | 221,225,253,225,201,233,225,253,229,221,229,221, | ||
233 | 33,0,0,221,57,94,35,86,35,235,57,249, | ||
234 | 235,233,0,0,0,0,0,0,0,0,0,0, | ||
235 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
236 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
237 | 0,0,0,0,0,0,0,0,0,0,0,0, | ||
238 | 0,0,0,0,0 | ||
239 | } ; | ||
240 | |||
241 | #endif | ||
diff --git a/drivers/staging/appletalk/ddp.c b/drivers/staging/appletalk/ddp.c new file mode 100644 index 00000000000..940dd190833 --- /dev/null +++ b/drivers/staging/appletalk/ddp.c | |||
@@ -0,0 +1,1981 @@ | |||
1 | /* | ||
2 | * DDP: An implementation of the AppleTalk DDP protocol for | ||
3 | * Ethernet 'ELAP'. | ||
4 | * | ||
5 | * Alan Cox <alan@lxorguk.ukuu.org.uk> | ||
6 | * | ||
7 | * With more than a little assistance from | ||
8 | * | ||
9 | * Wesley Craig <netatalk@umich.edu> | ||
10 | * | ||
11 | * Fixes: | ||
12 | * Neil Horman : Added missing device ioctls | ||
13 | * Michael Callahan : Made routing work | ||
14 | * Wesley Craig : Fix probing to listen to a | ||
15 | * passed node id. | ||
16 | * Alan Cox : Added send/recvmsg support | ||
17 | * Alan Cox : Moved at. to protinfo in | ||
18 | * socket. | ||
19 | * Alan Cox : Added firewall hooks. | ||
20 | * Alan Cox : Supports new ARPHRD_LOOPBACK | ||
21 | * Christer Weinigel : Routing and /proc fixes. | ||
22 | * Bradford Johnson : LocalTalk. | ||
23 | * Tom Dyas : Module support. | ||
24 | * Alan Cox : Hooks for PPP (based on the | ||
25 | * LocalTalk hook). | ||
26 | * Alan Cox : Posix bits | ||
27 | * Alan Cox/Mike Freeman : Possible fix to NBP problems | ||
28 | * Bradford Johnson : IP-over-DDP (experimental) | ||
29 | * Jay Schulist : Moved IP-over-DDP to its own | ||
30 | * driver file. (ipddp.c & ipddp.h) | ||
31 | * Jay Schulist : Made work as module with | ||
32 | * AppleTalk drivers, cleaned it. | ||
33 | * Rob Newberry : Added proxy AARP and AARP | ||
34 | * procfs, moved probing to AARP | ||
35 | * module. | ||
36 | * Adrian Sun/ | ||
37 | * Michael Zuelsdorff : fix for net.0 packets. don't | ||
38 | * allow illegal ether/tokentalk | ||
39 | * port assignment. we lose a | ||
40 | * valid localtalk port as a | ||
41 | * result. | ||
42 | * Arnaldo C. de Melo : Cleanup, in preparation for | ||
43 | * shared skb support 8) | ||
44 | * Arnaldo C. de Melo : Move proc stuff to atalk_proc.c, | ||
45 | * use seq_file | ||
46 | * | ||
47 | * This program is free software; you can redistribute it and/or | ||
48 | * modify it under the terms of the GNU General Public License | ||
49 | * as published by the Free Software Foundation; either version | ||
50 | * 2 of the License, or (at your option) any later version. | ||
51 | * | ||
52 | */ | ||
53 | |||
54 | #include <linux/capability.h> | ||
55 | #include <linux/module.h> | ||
56 | #include <linux/if_arp.h> | ||
57 | #include <linux/smp_lock.h> | ||
58 | #include <linux/termios.h> /* For TIOCOUTQ/INQ */ | ||
59 | #include <linux/compat.h> | ||
60 | #include <linux/slab.h> | ||
61 | #include <net/datalink.h> | ||
62 | #include <net/psnap.h> | ||
63 | #include <net/sock.h> | ||
64 | #include <net/tcp_states.h> | ||
65 | #include <net/route.h> | ||
66 | #include "atalk.h" | ||
67 | #include "../../net/core/kmap_skb.h" | ||
68 | |||
69 | struct datalink_proto *ddp_dl, *aarp_dl; | ||
70 | static const struct proto_ops atalk_dgram_ops; | ||
71 | |||
72 | /**************************************************************************\ | ||
73 | * * | ||
74 | * Handlers for the socket list. * | ||
75 | * * | ||
76 | \**************************************************************************/ | ||
77 | |||
78 | HLIST_HEAD(atalk_sockets); | ||
79 | DEFINE_RWLOCK(atalk_sockets_lock); | ||
80 | |||
81 | static inline void __atalk_insert_socket(struct sock *sk) | ||
82 | { | ||
83 | sk_add_node(sk, &atalk_sockets); | ||
84 | } | ||
85 | |||
86 | static inline void atalk_remove_socket(struct sock *sk) | ||
87 | { | ||
88 | write_lock_bh(&atalk_sockets_lock); | ||
89 | sk_del_node_init(sk); | ||
90 | write_unlock_bh(&atalk_sockets_lock); | ||
91 | } | ||
92 | |||
93 | static struct sock *atalk_search_socket(struct sockaddr_at *to, | ||
94 | struct atalk_iface *atif) | ||
95 | { | ||
96 | struct sock *s; | ||
97 | struct hlist_node *node; | ||
98 | |||
99 | read_lock_bh(&atalk_sockets_lock); | ||
100 | sk_for_each(s, node, &atalk_sockets) { | ||
101 | struct atalk_sock *at = at_sk(s); | ||
102 | |||
103 | if (to->sat_port != at->src_port) | ||
104 | continue; | ||
105 | |||
106 | if (to->sat_addr.s_net == ATADDR_ANYNET && | ||
107 | to->sat_addr.s_node == ATADDR_BCAST) | ||
108 | goto found; | ||
109 | |||
110 | if (to->sat_addr.s_net == at->src_net && | ||
111 | (to->sat_addr.s_node == at->src_node || | ||
112 | to->sat_addr.s_node == ATADDR_BCAST || | ||
113 | to->sat_addr.s_node == ATADDR_ANYNODE)) | ||
114 | goto found; | ||
115 | |||
116 | /* XXXX.0 -- we got a request for this router. make sure | ||
117 | * that the node is appropriately set. */ | ||
118 | if (to->sat_addr.s_node == ATADDR_ANYNODE && | ||
119 | to->sat_addr.s_net != ATADDR_ANYNET && | ||
120 | atif->address.s_node == at->src_node) { | ||
121 | to->sat_addr.s_node = atif->address.s_node; | ||
122 | goto found; | ||
123 | } | ||
124 | } | ||
125 | s = NULL; | ||
126 | found: | ||
127 | read_unlock_bh(&atalk_sockets_lock); | ||
128 | return s; | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * atalk_find_or_insert_socket - Try to find a socket matching ADDR | ||
133 | * @sk - socket to insert in the list if it is not there already | ||
134 | * @sat - address to search for | ||
135 | * | ||
136 | * Try to find a socket matching ADDR in the socket list, if found then return | ||
137 | * it. If not, insert SK into the socket list. | ||
138 | * | ||
139 | * This entire operation must execute atomically. | ||
140 | */ | ||
141 | static struct sock *atalk_find_or_insert_socket(struct sock *sk, | ||
142 | struct sockaddr_at *sat) | ||
143 | { | ||
144 | struct sock *s; | ||
145 | struct hlist_node *node; | ||
146 | struct atalk_sock *at; | ||
147 | |||
148 | write_lock_bh(&atalk_sockets_lock); | ||
149 | sk_for_each(s, node, &atalk_sockets) { | ||
150 | at = at_sk(s); | ||
151 | |||
152 | if (at->src_net == sat->sat_addr.s_net && | ||
153 | at->src_node == sat->sat_addr.s_node && | ||
154 | at->src_port == sat->sat_port) | ||
155 | goto found; | ||
156 | } | ||
157 | s = NULL; | ||
158 | __atalk_insert_socket(sk); /* Wheee, it's free, assign and insert. */ | ||
159 | found: | ||
160 | write_unlock_bh(&atalk_sockets_lock); | ||
161 | return s; | ||
162 | } | ||
163 | |||
164 | static void atalk_destroy_timer(unsigned long data) | ||
165 | { | ||
166 | struct sock *sk = (struct sock *)data; | ||
167 | |||
168 | if (sk_has_allocations(sk)) { | ||
169 | sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME; | ||
170 | add_timer(&sk->sk_timer); | ||
171 | } else | ||
172 | sock_put(sk); | ||
173 | } | ||
174 | |||
175 | static inline void atalk_destroy_socket(struct sock *sk) | ||
176 | { | ||
177 | atalk_remove_socket(sk); | ||
178 | skb_queue_purge(&sk->sk_receive_queue); | ||
179 | |||
180 | if (sk_has_allocations(sk)) { | ||
181 | setup_timer(&sk->sk_timer, atalk_destroy_timer, | ||
182 | (unsigned long)sk); | ||
183 | sk->sk_timer.expires = jiffies + SOCK_DESTROY_TIME; | ||
184 | add_timer(&sk->sk_timer); | ||
185 | } else | ||
186 | sock_put(sk); | ||
187 | } | ||
188 | |||
189 | /**************************************************************************\ | ||
190 | * * | ||
191 | * Routing tables for the AppleTalk socket layer. * | ||
192 | * * | ||
193 | \**************************************************************************/ | ||
194 | |||
195 | /* Anti-deadlock ordering is atalk_routes_lock --> iface_lock -DaveM */ | ||
196 | struct atalk_route *atalk_routes; | ||
197 | DEFINE_RWLOCK(atalk_routes_lock); | ||
198 | |||
199 | struct atalk_iface *atalk_interfaces; | ||
200 | DEFINE_RWLOCK(atalk_interfaces_lock); | ||
201 | |||
202 | /* For probing devices or in a routerless network */ | ||
203 | struct atalk_route atrtr_default; | ||
204 | |||
205 | /* AppleTalk interface control */ | ||
206 | /* | ||
207 | * Drop a device. Doesn't drop any of its routes - that is the caller's | ||
208 | * problem. Called when we down the interface or delete the address. | ||
209 | */ | ||
210 | static void atif_drop_device(struct net_device *dev) | ||
211 | { | ||
212 | struct atalk_iface **iface = &atalk_interfaces; | ||
213 | struct atalk_iface *tmp; | ||
214 | |||
215 | write_lock_bh(&atalk_interfaces_lock); | ||
216 | while ((tmp = *iface) != NULL) { | ||
217 | if (tmp->dev == dev) { | ||
218 | *iface = tmp->next; | ||
219 | dev_put(dev); | ||
220 | kfree(tmp); | ||
221 | dev->atalk_ptr = NULL; | ||
222 | } else | ||
223 | iface = &tmp->next; | ||
224 | } | ||
225 | write_unlock_bh(&atalk_interfaces_lock); | ||
226 | } | ||
227 | |||
228 | static struct atalk_iface *atif_add_device(struct net_device *dev, | ||
229 | struct atalk_addr *sa) | ||
230 | { | ||
231 | struct atalk_iface *iface = kzalloc(sizeof(*iface), GFP_KERNEL); | ||
232 | |||
233 | if (!iface) | ||
234 | goto out; | ||
235 | |||
236 | dev_hold(dev); | ||
237 | iface->dev = dev; | ||
238 | dev->atalk_ptr = iface; | ||
239 | iface->address = *sa; | ||
240 | iface->status = 0; | ||
241 | |||
242 | write_lock_bh(&atalk_interfaces_lock); | ||
243 | iface->next = atalk_interfaces; | ||
244 | atalk_interfaces = iface; | ||
245 | write_unlock_bh(&atalk_interfaces_lock); | ||
246 | out: | ||
247 | return iface; | ||
248 | } | ||
249 | |||
250 | /* Perform phase 2 AARP probing on our tentative address */ | ||
251 | static int atif_probe_device(struct atalk_iface *atif) | ||
252 | { | ||
253 | int netrange = ntohs(atif->nets.nr_lastnet) - | ||
254 | ntohs(atif->nets.nr_firstnet) + 1; | ||
255 | int probe_net = ntohs(atif->address.s_net); | ||
256 | int probe_node = atif->address.s_node; | ||
257 | int netct, nodect; | ||
258 | |||
259 | /* Offset the network we start probing with */ | ||
260 | if (probe_net == ATADDR_ANYNET) { | ||
261 | probe_net = ntohs(atif->nets.nr_firstnet); | ||
262 | if (netrange) | ||
263 | probe_net += jiffies % netrange; | ||
264 | } | ||
265 | if (probe_node == ATADDR_ANYNODE) | ||
266 | probe_node = jiffies & 0xFF; | ||
267 | |||
268 | /* Scan the networks */ | ||
269 | atif->status |= ATIF_PROBE; | ||
270 | for (netct = 0; netct <= netrange; netct++) { | ||
271 | /* Sweep the available nodes from a given start */ | ||
272 | atif->address.s_net = htons(probe_net); | ||
273 | for (nodect = 0; nodect < 256; nodect++) { | ||
274 | atif->address.s_node = (nodect + probe_node) & 0xFF; | ||
275 | if (atif->address.s_node > 0 && | ||
276 | atif->address.s_node < 254) { | ||
277 | /* Probe a proposed address */ | ||
278 | aarp_probe_network(atif); | ||
279 | |||
280 | if (!(atif->status & ATIF_PROBE_FAIL)) { | ||
281 | atif->status &= ~ATIF_PROBE; | ||
282 | return 0; | ||
283 | } | ||
284 | } | ||
285 | atif->status &= ~ATIF_PROBE_FAIL; | ||
286 | } | ||
287 | probe_net++; | ||
288 | if (probe_net > ntohs(atif->nets.nr_lastnet)) | ||
289 | probe_net = ntohs(atif->nets.nr_firstnet); | ||
290 | } | ||
291 | atif->status &= ~ATIF_PROBE; | ||
292 | |||
293 | return -EADDRINUSE; /* Network is full... */ | ||
294 | } | ||
295 | |||
296 | |||
297 | /* Perform AARP probing for a proxy address */ | ||
298 | static int atif_proxy_probe_device(struct atalk_iface *atif, | ||
299 | struct atalk_addr* proxy_addr) | ||
300 | { | ||
301 | int netrange = ntohs(atif->nets.nr_lastnet) - | ||
302 | ntohs(atif->nets.nr_firstnet) + 1; | ||
303 | /* we probe the interface's network */ | ||
304 | int probe_net = ntohs(atif->address.s_net); | ||
305 | int probe_node = ATADDR_ANYNODE; /* we'll take anything */ | ||
306 | int netct, nodect; | ||
307 | |||
308 | /* Offset the network we start probing with */ | ||
309 | if (probe_net == ATADDR_ANYNET) { | ||
310 | probe_net = ntohs(atif->nets.nr_firstnet); | ||
311 | if (netrange) | ||
312 | probe_net += jiffies % netrange; | ||
313 | } | ||
314 | |||
315 | if (probe_node == ATADDR_ANYNODE) | ||
316 | probe_node = jiffies & 0xFF; | ||
317 | |||
318 | /* Scan the networks */ | ||
319 | for (netct = 0; netct <= netrange; netct++) { | ||
320 | /* Sweep the available nodes from a given start */ | ||
321 | proxy_addr->s_net = htons(probe_net); | ||
322 | for (nodect = 0; nodect < 256; nodect++) { | ||
323 | proxy_addr->s_node = (nodect + probe_node) & 0xFF; | ||
324 | if (proxy_addr->s_node > 0 && | ||
325 | proxy_addr->s_node < 254) { | ||
326 | /* Tell AARP to probe a proposed address */ | ||
327 | int ret = aarp_proxy_probe_network(atif, | ||
328 | proxy_addr); | ||
329 | |||
330 | if (ret != -EADDRINUSE) | ||
331 | return ret; | ||
332 | } | ||
333 | } | ||
334 | probe_net++; | ||
335 | if (probe_net > ntohs(atif->nets.nr_lastnet)) | ||
336 | probe_net = ntohs(atif->nets.nr_firstnet); | ||
337 | } | ||
338 | |||
339 | return -EADDRINUSE; /* Network is full... */ | ||
340 | } | ||
341 | |||
342 | |||
343 | struct atalk_addr *atalk_find_dev_addr(struct net_device *dev) | ||
344 | { | ||
345 | struct atalk_iface *iface = dev->atalk_ptr; | ||
346 | return iface ? &iface->address : NULL; | ||
347 | } | ||
348 | |||
349 | static struct atalk_addr *atalk_find_primary(void) | ||
350 | { | ||
351 | struct atalk_iface *fiface = NULL; | ||
352 | struct atalk_addr *retval; | ||
353 | struct atalk_iface *iface; | ||
354 | |||
355 | /* | ||
356 | * Return a point-to-point interface only if | ||
357 | * there is no non-ptp interface available. | ||
358 | */ | ||
359 | read_lock_bh(&atalk_interfaces_lock); | ||
360 | for (iface = atalk_interfaces; iface; iface = iface->next) { | ||
361 | if (!fiface && !(iface->dev->flags & IFF_LOOPBACK)) | ||
362 | fiface = iface; | ||
363 | if (!(iface->dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT))) { | ||
364 | retval = &iface->address; | ||
365 | goto out; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | if (fiface) | ||
370 | retval = &fiface->address; | ||
371 | else if (atalk_interfaces) | ||
372 | retval = &atalk_interfaces->address; | ||
373 | else | ||
374 | retval = NULL; | ||
375 | out: | ||
376 | read_unlock_bh(&atalk_interfaces_lock); | ||
377 | return retval; | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * Find a match for 'any network' - ie any of our interfaces with that | ||
382 | * node number will do just nicely. | ||
383 | */ | ||
384 | static struct atalk_iface *atalk_find_anynet(int node, struct net_device *dev) | ||
385 | { | ||
386 | struct atalk_iface *iface = dev->atalk_ptr; | ||
387 | |||
388 | if (!iface || iface->status & ATIF_PROBE) | ||
389 | goto out_err; | ||
390 | |||
391 | if (node != ATADDR_BCAST && | ||
392 | iface->address.s_node != node && | ||
393 | node != ATADDR_ANYNODE) | ||
394 | goto out_err; | ||
395 | out: | ||
396 | return iface; | ||
397 | out_err: | ||
398 | iface = NULL; | ||
399 | goto out; | ||
400 | } | ||
401 | |||
402 | /* Find a match for a specific network:node pair */ | ||
403 | static struct atalk_iface *atalk_find_interface(__be16 net, int node) | ||
404 | { | ||
405 | struct atalk_iface *iface; | ||
406 | |||
407 | read_lock_bh(&atalk_interfaces_lock); | ||
408 | for (iface = atalk_interfaces; iface; iface = iface->next) { | ||
409 | if ((node == ATADDR_BCAST || | ||
410 | node == ATADDR_ANYNODE || | ||
411 | iface->address.s_node == node) && | ||
412 | iface->address.s_net == net && | ||
413 | !(iface->status & ATIF_PROBE)) | ||
414 | break; | ||
415 | |||
416 | /* XXXX.0 -- net.0 returns the iface associated with net */ | ||
417 | if (node == ATADDR_ANYNODE && net != ATADDR_ANYNET && | ||
418 | ntohs(iface->nets.nr_firstnet) <= ntohs(net) && | ||
419 | ntohs(net) <= ntohs(iface->nets.nr_lastnet)) | ||
420 | break; | ||
421 | } | ||
422 | read_unlock_bh(&atalk_interfaces_lock); | ||
423 | return iface; | ||
424 | } | ||
425 | |||
426 | |||
427 | /* | ||
428 | * Find a route for an AppleTalk packet. This ought to get cached in | ||
429 | * the socket (later on...). We know about host routes and the fact | ||
430 | * that a route must be direct to broadcast. | ||
431 | */ | ||
432 | static struct atalk_route *atrtr_find(struct atalk_addr *target) | ||
433 | { | ||
434 | /* | ||
435 | * we must search through all routes unless we find a | ||
436 | * host route, because some host routes might overlap | ||
437 | * network routes | ||
438 | */ | ||
439 | struct atalk_route *net_route = NULL; | ||
440 | struct atalk_route *r; | ||
441 | |||
442 | read_lock_bh(&atalk_routes_lock); | ||
443 | for (r = atalk_routes; r; r = r->next) { | ||
444 | if (!(r->flags & RTF_UP)) | ||
445 | continue; | ||
446 | |||
447 | if (r->target.s_net == target->s_net) { | ||
448 | if (r->flags & RTF_HOST) { | ||
449 | /* | ||
450 | * if this host route is for the target, | ||
451 | * the we're done | ||
452 | */ | ||
453 | if (r->target.s_node == target->s_node) | ||
454 | goto out; | ||
455 | } else | ||
456 | /* | ||
457 | * this route will work if there isn't a | ||
458 | * direct host route, so cache it | ||
459 | */ | ||
460 | net_route = r; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * if we found a network route but not a direct host | ||
466 | * route, then return it | ||
467 | */ | ||
468 | if (net_route) | ||
469 | r = net_route; | ||
470 | else if (atrtr_default.dev) | ||
471 | r = &atrtr_default; | ||
472 | else /* No route can be found */ | ||
473 | r = NULL; | ||
474 | out: | ||
475 | read_unlock_bh(&atalk_routes_lock); | ||
476 | return r; | ||
477 | } | ||
478 | |||
479 | |||
480 | /* | ||
481 | * Given an AppleTalk network, find the device to use. This can be | ||
482 | * a simple lookup. | ||
483 | */ | ||
484 | struct net_device *atrtr_get_dev(struct atalk_addr *sa) | ||
485 | { | ||
486 | struct atalk_route *atr = atrtr_find(sa); | ||
487 | return atr ? atr->dev : NULL; | ||
488 | } | ||
489 | |||
490 | /* Set up a default router */ | ||
491 | static void atrtr_set_default(struct net_device *dev) | ||
492 | { | ||
493 | atrtr_default.dev = dev; | ||
494 | atrtr_default.flags = RTF_UP; | ||
495 | atrtr_default.gateway.s_net = htons(0); | ||
496 | atrtr_default.gateway.s_node = 0; | ||
497 | } | ||
498 | |||
499 | /* | ||
500 | * Add a router. Basically make sure it looks valid and stuff the | ||
501 | * entry in the list. While it uses netranges we always set them to one | ||
502 | * entry to work like netatalk. | ||
503 | */ | ||
504 | static int atrtr_create(struct rtentry *r, struct net_device *devhint) | ||
505 | { | ||
506 | struct sockaddr_at *ta = (struct sockaddr_at *)&r->rt_dst; | ||
507 | struct sockaddr_at *ga = (struct sockaddr_at *)&r->rt_gateway; | ||
508 | struct atalk_route *rt; | ||
509 | struct atalk_iface *iface, *riface; | ||
510 | int retval = -EINVAL; | ||
511 | |||
512 | /* | ||
513 | * Fixme: Raise/Lower a routing change semaphore for these | ||
514 | * operations. | ||
515 | */ | ||
516 | |||
517 | /* Validate the request */ | ||
518 | if (ta->sat_family != AF_APPLETALK || | ||
519 | (!devhint && ga->sat_family != AF_APPLETALK)) | ||
520 | goto out; | ||
521 | |||
522 | /* Now walk the routing table and make our decisions */ | ||
523 | write_lock_bh(&atalk_routes_lock); | ||
524 | for (rt = atalk_routes; rt; rt = rt->next) { | ||
525 | if (r->rt_flags != rt->flags) | ||
526 | continue; | ||
527 | |||
528 | if (ta->sat_addr.s_net == rt->target.s_net) { | ||
529 | if (!(rt->flags & RTF_HOST)) | ||
530 | break; | ||
531 | if (ta->sat_addr.s_node == rt->target.s_node) | ||
532 | break; | ||
533 | } | ||
534 | } | ||
535 | |||
536 | if (!devhint) { | ||
537 | riface = NULL; | ||
538 | |||
539 | read_lock_bh(&atalk_interfaces_lock); | ||
540 | for (iface = atalk_interfaces; iface; iface = iface->next) { | ||
541 | if (!riface && | ||
542 | ntohs(ga->sat_addr.s_net) >= | ||
543 | ntohs(iface->nets.nr_firstnet) && | ||
544 | ntohs(ga->sat_addr.s_net) <= | ||
545 | ntohs(iface->nets.nr_lastnet)) | ||
546 | riface = iface; | ||
547 | |||
548 | if (ga->sat_addr.s_net == iface->address.s_net && | ||
549 | ga->sat_addr.s_node == iface->address.s_node) | ||
550 | riface = iface; | ||
551 | } | ||
552 | read_unlock_bh(&atalk_interfaces_lock); | ||
553 | |||
554 | retval = -ENETUNREACH; | ||
555 | if (!riface) | ||
556 | goto out_unlock; | ||
557 | |||
558 | devhint = riface->dev; | ||
559 | } | ||
560 | |||
561 | if (!rt) { | ||
562 | rt = kzalloc(sizeof(*rt), GFP_ATOMIC); | ||
563 | |||
564 | retval = -ENOBUFS; | ||
565 | if (!rt) | ||
566 | goto out_unlock; | ||
567 | |||
568 | rt->next = atalk_routes; | ||
569 | atalk_routes = rt; | ||
570 | } | ||
571 | |||
572 | /* Fill in the routing entry */ | ||
573 | rt->target = ta->sat_addr; | ||
574 | dev_hold(devhint); | ||
575 | rt->dev = devhint; | ||
576 | rt->flags = r->rt_flags; | ||
577 | rt->gateway = ga->sat_addr; | ||
578 | |||
579 | retval = 0; | ||
580 | out_unlock: | ||
581 | write_unlock_bh(&atalk_routes_lock); | ||
582 | out: | ||
583 | return retval; | ||
584 | } | ||
585 | |||
586 | /* Delete a route. Find it and discard it */ | ||
587 | static int atrtr_delete(struct atalk_addr * addr) | ||
588 | { | ||
589 | struct atalk_route **r = &atalk_routes; | ||
590 | int retval = 0; | ||
591 | struct atalk_route *tmp; | ||
592 | |||
593 | write_lock_bh(&atalk_routes_lock); | ||
594 | while ((tmp = *r) != NULL) { | ||
595 | if (tmp->target.s_net == addr->s_net && | ||
596 | (!(tmp->flags&RTF_GATEWAY) || | ||
597 | tmp->target.s_node == addr->s_node)) { | ||
598 | *r = tmp->next; | ||
599 | dev_put(tmp->dev); | ||
600 | kfree(tmp); | ||
601 | goto out; | ||
602 | } | ||
603 | r = &tmp->next; | ||
604 | } | ||
605 | retval = -ENOENT; | ||
606 | out: | ||
607 | write_unlock_bh(&atalk_routes_lock); | ||
608 | return retval; | ||
609 | } | ||
610 | |||
611 | /* | ||
612 | * Called when a device is downed. Just throw away any routes | ||
613 | * via it. | ||
614 | */ | ||
615 | static void atrtr_device_down(struct net_device *dev) | ||
616 | { | ||
617 | struct atalk_route **r = &atalk_routes; | ||
618 | struct atalk_route *tmp; | ||
619 | |||
620 | write_lock_bh(&atalk_routes_lock); | ||
621 | while ((tmp = *r) != NULL) { | ||
622 | if (tmp->dev == dev) { | ||
623 | *r = tmp->next; | ||
624 | dev_put(dev); | ||
625 | kfree(tmp); | ||
626 | } else | ||
627 | r = &tmp->next; | ||
628 | } | ||
629 | write_unlock_bh(&atalk_routes_lock); | ||
630 | |||
631 | if (atrtr_default.dev == dev) | ||
632 | atrtr_set_default(NULL); | ||
633 | } | ||
634 | |||
635 | /* Actually down the interface */ | ||
636 | static inline void atalk_dev_down(struct net_device *dev) | ||
637 | { | ||
638 | atrtr_device_down(dev); /* Remove all routes for the device */ | ||
639 | aarp_device_down(dev); /* Remove AARP entries for the device */ | ||
640 | atif_drop_device(dev); /* Remove the device */ | ||
641 | } | ||
642 | |||
643 | /* | ||
644 | * A device event has occurred. Watch for devices going down and | ||
645 | * delete our use of them (iface and route). | ||
646 | */ | ||
647 | static int ddp_device_event(struct notifier_block *this, unsigned long event, | ||
648 | void *ptr) | ||
649 | { | ||
650 | struct net_device *dev = ptr; | ||
651 | |||
652 | if (!net_eq(dev_net(dev), &init_net)) | ||
653 | return NOTIFY_DONE; | ||
654 | |||
655 | if (event == NETDEV_DOWN) | ||
656 | /* Discard any use of this */ | ||
657 | atalk_dev_down(dev); | ||
658 | |||
659 | return NOTIFY_DONE; | ||
660 | } | ||
661 | |||
662 | /* ioctl calls. Shouldn't even need touching */ | ||
663 | /* Device configuration ioctl calls */ | ||
664 | static int atif_ioctl(int cmd, void __user *arg) | ||
665 | { | ||
666 | static char aarp_mcast[6] = { 0x09, 0x00, 0x00, 0xFF, 0xFF, 0xFF }; | ||
667 | struct ifreq atreq; | ||
668 | struct atalk_netrange *nr; | ||
669 | struct sockaddr_at *sa; | ||
670 | struct net_device *dev; | ||
671 | struct atalk_iface *atif; | ||
672 | int ct; | ||
673 | int limit; | ||
674 | struct rtentry rtdef; | ||
675 | int add_route; | ||
676 | |||
677 | if (copy_from_user(&atreq, arg, sizeof(atreq))) | ||
678 | return -EFAULT; | ||
679 | |||
680 | dev = __dev_get_by_name(&init_net, atreq.ifr_name); | ||
681 | if (!dev) | ||
682 | return -ENODEV; | ||
683 | |||
684 | sa = (struct sockaddr_at *)&atreq.ifr_addr; | ||
685 | atif = atalk_find_dev(dev); | ||
686 | |||
687 | switch (cmd) { | ||
688 | case SIOCSIFADDR: | ||
689 | if (!capable(CAP_NET_ADMIN)) | ||
690 | return -EPERM; | ||
691 | if (sa->sat_family != AF_APPLETALK) | ||
692 | return -EINVAL; | ||
693 | if (dev->type != ARPHRD_ETHER && | ||
694 | dev->type != ARPHRD_LOOPBACK && | ||
695 | dev->type != ARPHRD_LOCALTLK && | ||
696 | dev->type != ARPHRD_PPP) | ||
697 | return -EPROTONOSUPPORT; | ||
698 | |||
699 | nr = (struct atalk_netrange *)&sa->sat_zero[0]; | ||
700 | add_route = 1; | ||
701 | |||
702 | /* | ||
703 | * if this is a point-to-point iface, and we already | ||
704 | * have an iface for this AppleTalk address, then we | ||
705 | * should not add a route | ||
706 | */ | ||
707 | if ((dev->flags & IFF_POINTOPOINT) && | ||
708 | atalk_find_interface(sa->sat_addr.s_net, | ||
709 | sa->sat_addr.s_node)) { | ||
710 | printk(KERN_DEBUG "AppleTalk: point-to-point " | ||
711 | "interface added with " | ||
712 | "existing address\n"); | ||
713 | add_route = 0; | ||
714 | } | ||
715 | |||
716 | /* | ||
717 | * Phase 1 is fine on LocalTalk but we don't do | ||
718 | * EtherTalk phase 1. Anyone wanting to add it go ahead. | ||
719 | */ | ||
720 | if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2) | ||
721 | return -EPROTONOSUPPORT; | ||
722 | if (sa->sat_addr.s_node == ATADDR_BCAST || | ||
723 | sa->sat_addr.s_node == 254) | ||
724 | return -EINVAL; | ||
725 | if (atif) { | ||
726 | /* Already setting address */ | ||
727 | if (atif->status & ATIF_PROBE) | ||
728 | return -EBUSY; | ||
729 | |||
730 | atif->address.s_net = sa->sat_addr.s_net; | ||
731 | atif->address.s_node = sa->sat_addr.s_node; | ||
732 | atrtr_device_down(dev); /* Flush old routes */ | ||
733 | } else { | ||
734 | atif = atif_add_device(dev, &sa->sat_addr); | ||
735 | if (!atif) | ||
736 | return -ENOMEM; | ||
737 | } | ||
738 | atif->nets = *nr; | ||
739 | |||
740 | /* | ||
741 | * Check if the chosen address is used. If so we | ||
742 | * error and atalkd will try another. | ||
743 | */ | ||
744 | |||
745 | if (!(dev->flags & IFF_LOOPBACK) && | ||
746 | !(dev->flags & IFF_POINTOPOINT) && | ||
747 | atif_probe_device(atif) < 0) { | ||
748 | atif_drop_device(dev); | ||
749 | return -EADDRINUSE; | ||
750 | } | ||
751 | |||
752 | /* Hey it worked - add the direct routes */ | ||
753 | sa = (struct sockaddr_at *)&rtdef.rt_gateway; | ||
754 | sa->sat_family = AF_APPLETALK; | ||
755 | sa->sat_addr.s_net = atif->address.s_net; | ||
756 | sa->sat_addr.s_node = atif->address.s_node; | ||
757 | sa = (struct sockaddr_at *)&rtdef.rt_dst; | ||
758 | rtdef.rt_flags = RTF_UP; | ||
759 | sa->sat_family = AF_APPLETALK; | ||
760 | sa->sat_addr.s_node = ATADDR_ANYNODE; | ||
761 | if (dev->flags & IFF_LOOPBACK || | ||
762 | dev->flags & IFF_POINTOPOINT) | ||
763 | rtdef.rt_flags |= RTF_HOST; | ||
764 | |||
765 | /* Routerless initial state */ | ||
766 | if (nr->nr_firstnet == htons(0) && | ||
767 | nr->nr_lastnet == htons(0xFFFE)) { | ||
768 | sa->sat_addr.s_net = atif->address.s_net; | ||
769 | atrtr_create(&rtdef, dev); | ||
770 | atrtr_set_default(dev); | ||
771 | } else { | ||
772 | limit = ntohs(nr->nr_lastnet); | ||
773 | if (limit - ntohs(nr->nr_firstnet) > 4096) { | ||
774 | printk(KERN_WARNING "Too many routes/" | ||
775 | "iface.\n"); | ||
776 | return -EINVAL; | ||
777 | } | ||
778 | if (add_route) | ||
779 | for (ct = ntohs(nr->nr_firstnet); | ||
780 | ct <= limit; ct++) { | ||
781 | sa->sat_addr.s_net = htons(ct); | ||
782 | atrtr_create(&rtdef, dev); | ||
783 | } | ||
784 | } | ||
785 | dev_mc_add_global(dev, aarp_mcast); | ||
786 | return 0; | ||
787 | |||
788 | case SIOCGIFADDR: | ||
789 | if (!atif) | ||
790 | return -EADDRNOTAVAIL; | ||
791 | |||
792 | sa->sat_family = AF_APPLETALK; | ||
793 | sa->sat_addr = atif->address; | ||
794 | break; | ||
795 | |||
796 | case SIOCGIFBRDADDR: | ||
797 | if (!atif) | ||
798 | return -EADDRNOTAVAIL; | ||
799 | |||
800 | sa->sat_family = AF_APPLETALK; | ||
801 | sa->sat_addr.s_net = atif->address.s_net; | ||
802 | sa->sat_addr.s_node = ATADDR_BCAST; | ||
803 | break; | ||
804 | |||
805 | case SIOCATALKDIFADDR: | ||
806 | case SIOCDIFADDR: | ||
807 | if (!capable(CAP_NET_ADMIN)) | ||
808 | return -EPERM; | ||
809 | if (sa->sat_family != AF_APPLETALK) | ||
810 | return -EINVAL; | ||
811 | atalk_dev_down(dev); | ||
812 | break; | ||
813 | |||
814 | case SIOCSARP: | ||
815 | if (!capable(CAP_NET_ADMIN)) | ||
816 | return -EPERM; | ||
817 | if (sa->sat_family != AF_APPLETALK) | ||
818 | return -EINVAL; | ||
819 | /* | ||
820 | * for now, we only support proxy AARP on ELAP; | ||
821 | * we should be able to do it for LocalTalk, too. | ||
822 | */ | ||
823 | if (dev->type != ARPHRD_ETHER) | ||
824 | return -EPROTONOSUPPORT; | ||
825 | |||
826 | /* | ||
827 | * atif points to the current interface on this network; | ||
828 | * we aren't concerned about its current status (at | ||
829 | * least for now), but it has all the settings about | ||
830 | * the network we're going to probe. Consequently, it | ||
831 | * must exist. | ||
832 | */ | ||
833 | if (!atif) | ||
834 | return -EADDRNOTAVAIL; | ||
835 | |||
836 | nr = (struct atalk_netrange *)&(atif->nets); | ||
837 | /* | ||
838 | * Phase 1 is fine on Localtalk but we don't do | ||
839 | * Ethertalk phase 1. Anyone wanting to add it go ahead. | ||
840 | */ | ||
841 | if (dev->type == ARPHRD_ETHER && nr->nr_phase != 2) | ||
842 | return -EPROTONOSUPPORT; | ||
843 | |||
844 | if (sa->sat_addr.s_node == ATADDR_BCAST || | ||
845 | sa->sat_addr.s_node == 254) | ||
846 | return -EINVAL; | ||
847 | |||
848 | /* | ||
849 | * Check if the chosen address is used. If so we | ||
850 | * error and ATCP will try another. | ||
851 | */ | ||
852 | if (atif_proxy_probe_device(atif, &(sa->sat_addr)) < 0) | ||
853 | return -EADDRINUSE; | ||
854 | |||
855 | /* | ||
856 | * We now have an address on the local network, and | ||
857 | * the AARP code will defend it for us until we take it | ||
858 | * down. We don't set up any routes right now, because | ||
859 | * ATCP will install them manually via SIOCADDRT. | ||
860 | */ | ||
861 | break; | ||
862 | |||
863 | case SIOCDARP: | ||
864 | if (!capable(CAP_NET_ADMIN)) | ||
865 | return -EPERM; | ||
866 | if (sa->sat_family != AF_APPLETALK) | ||
867 | return -EINVAL; | ||
868 | if (!atif) | ||
869 | return -EADDRNOTAVAIL; | ||
870 | |||
871 | /* give to aarp module to remove proxy entry */ | ||
872 | aarp_proxy_remove(atif->dev, &(sa->sat_addr)); | ||
873 | return 0; | ||
874 | } | ||
875 | |||
876 | return copy_to_user(arg, &atreq, sizeof(atreq)) ? -EFAULT : 0; | ||
877 | } | ||
878 | |||
879 | /* Routing ioctl() calls */ | ||
880 | static int atrtr_ioctl(unsigned int cmd, void __user *arg) | ||
881 | { | ||
882 | struct rtentry rt; | ||
883 | |||
884 | if (copy_from_user(&rt, arg, sizeof(rt))) | ||
885 | return -EFAULT; | ||
886 | |||
887 | switch (cmd) { | ||
888 | case SIOCDELRT: | ||
889 | if (rt.rt_dst.sa_family != AF_APPLETALK) | ||
890 | return -EINVAL; | ||
891 | return atrtr_delete(&((struct sockaddr_at *) | ||
892 | &rt.rt_dst)->sat_addr); | ||
893 | |||
894 | case SIOCADDRT: { | ||
895 | struct net_device *dev = NULL; | ||
896 | if (rt.rt_dev) { | ||
897 | char name[IFNAMSIZ]; | ||
898 | if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1)) | ||
899 | return -EFAULT; | ||
900 | name[IFNAMSIZ-1] = '\0'; | ||
901 | dev = __dev_get_by_name(&init_net, name); | ||
902 | if (!dev) | ||
903 | return -ENODEV; | ||
904 | } | ||
905 | return atrtr_create(&rt, dev); | ||
906 | } | ||
907 | } | ||
908 | return -EINVAL; | ||
909 | } | ||
910 | |||
911 | /**************************************************************************\ | ||
912 | * * | ||
913 | * Handling for system calls applied via the various interfaces to an * | ||
914 | * AppleTalk socket object. * | ||
915 | * * | ||
916 | \**************************************************************************/ | ||
917 | |||
918 | /* | ||
919 | * Checksum: This is 'optional'. It's quite likely also a good | ||
920 | * candidate for assembler hackery 8) | ||
921 | */ | ||
922 | static unsigned long atalk_sum_partial(const unsigned char *data, | ||
923 | int len, unsigned long sum) | ||
924 | { | ||
925 | /* This ought to be unwrapped neatly. I'll trust gcc for now */ | ||
926 | while (len--) { | ||
927 | sum += *data++; | ||
928 | sum = rol16(sum, 1); | ||
929 | } | ||
930 | return sum; | ||
931 | } | ||
932 | |||
933 | /* Checksum skb data -- similar to skb_checksum */ | ||
934 | static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, | ||
935 | int len, unsigned long sum) | ||
936 | { | ||
937 | int start = skb_headlen(skb); | ||
938 | struct sk_buff *frag_iter; | ||
939 | int i, copy; | ||
940 | |||
941 | /* checksum stuff in header space */ | ||
942 | if ( (copy = start - offset) > 0) { | ||
943 | if (copy > len) | ||
944 | copy = len; | ||
945 | sum = atalk_sum_partial(skb->data + offset, copy, sum); | ||
946 | if ( (len -= copy) == 0) | ||
947 | return sum; | ||
948 | |||
949 | offset += copy; | ||
950 | } | ||
951 | |||
952 | /* checksum stuff in frags */ | ||
953 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
954 | int end; | ||
955 | |||
956 | WARN_ON(start > offset + len); | ||
957 | |||
958 | end = start + skb_shinfo(skb)->frags[i].size; | ||
959 | if ((copy = end - offset) > 0) { | ||
960 | u8 *vaddr; | ||
961 | skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; | ||
962 | |||
963 | if (copy > len) | ||
964 | copy = len; | ||
965 | vaddr = kmap_skb_frag(frag); | ||
966 | sum = atalk_sum_partial(vaddr + frag->page_offset + | ||
967 | offset - start, copy, sum); | ||
968 | kunmap_skb_frag(vaddr); | ||
969 | |||
970 | if (!(len -= copy)) | ||
971 | return sum; | ||
972 | offset += copy; | ||
973 | } | ||
974 | start = end; | ||
975 | } | ||
976 | |||
977 | skb_walk_frags(skb, frag_iter) { | ||
978 | int end; | ||
979 | |||
980 | WARN_ON(start > offset + len); | ||
981 | |||
982 | end = start + frag_iter->len; | ||
983 | if ((copy = end - offset) > 0) { | ||
984 | if (copy > len) | ||
985 | copy = len; | ||
986 | sum = atalk_sum_skb(frag_iter, offset - start, | ||
987 | copy, sum); | ||
988 | if ((len -= copy) == 0) | ||
989 | return sum; | ||
990 | offset += copy; | ||
991 | } | ||
992 | start = end; | ||
993 | } | ||
994 | |||
995 | BUG_ON(len > 0); | ||
996 | |||
997 | return sum; | ||
998 | } | ||
999 | |||
1000 | static __be16 atalk_checksum(const struct sk_buff *skb, int len) | ||
1001 | { | ||
1002 | unsigned long sum; | ||
1003 | |||
1004 | /* skip header 4 bytes */ | ||
1005 | sum = atalk_sum_skb(skb, 4, len-4, 0); | ||
1006 | |||
1007 | /* Use 0xFFFF for 0. 0 itself means none */ | ||
1008 | return sum ? htons((unsigned short)sum) : htons(0xFFFF); | ||
1009 | } | ||
1010 | |||
1011 | static struct proto ddp_proto = { | ||
1012 | .name = "DDP", | ||
1013 | .owner = THIS_MODULE, | ||
1014 | .obj_size = sizeof(struct atalk_sock), | ||
1015 | }; | ||
1016 | |||
1017 | /* | ||
1018 | * Create a socket. Initialise the socket, blank the addresses | ||
1019 | * set the state. | ||
1020 | */ | ||
1021 | static int atalk_create(struct net *net, struct socket *sock, int protocol, | ||
1022 | int kern) | ||
1023 | { | ||
1024 | struct sock *sk; | ||
1025 | int rc = -ESOCKTNOSUPPORT; | ||
1026 | |||
1027 | if (!net_eq(net, &init_net)) | ||
1028 | return -EAFNOSUPPORT; | ||
1029 | |||
1030 | /* | ||
1031 | * We permit SOCK_DGRAM and RAW is an extension. It is trivial to do | ||
1032 | * and gives you the full ELAP frame. Should be handy for CAP 8) | ||
1033 | */ | ||
1034 | if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM) | ||
1035 | goto out; | ||
1036 | rc = -ENOMEM; | ||
1037 | sk = sk_alloc(net, PF_APPLETALK, GFP_KERNEL, &ddp_proto); | ||
1038 | if (!sk) | ||
1039 | goto out; | ||
1040 | rc = 0; | ||
1041 | sock->ops = &atalk_dgram_ops; | ||
1042 | sock_init_data(sock, sk); | ||
1043 | |||
1044 | /* Checksums on by default */ | ||
1045 | sock_set_flag(sk, SOCK_ZAPPED); | ||
1046 | out: | ||
1047 | return rc; | ||
1048 | } | ||
1049 | |||
1050 | /* Free a socket. No work needed */ | ||
1051 | static int atalk_release(struct socket *sock) | ||
1052 | { | ||
1053 | struct sock *sk = sock->sk; | ||
1054 | |||
1055 | lock_kernel(); | ||
1056 | if (sk) { | ||
1057 | sock_orphan(sk); | ||
1058 | sock->sk = NULL; | ||
1059 | atalk_destroy_socket(sk); | ||
1060 | } | ||
1061 | unlock_kernel(); | ||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | /** | ||
1066 | * atalk_pick_and_bind_port - Pick a source port when one is not given | ||
1067 | * @sk - socket to insert into the tables | ||
1068 | * @sat - address to search for | ||
1069 | * | ||
1070 | * Pick a source port when one is not given. If we can find a suitable free | ||
1071 | * one, we insert the socket into the tables using it. | ||
1072 | * | ||
1073 | * This whole operation must be atomic. | ||
1074 | */ | ||
1075 | static int atalk_pick_and_bind_port(struct sock *sk, struct sockaddr_at *sat) | ||
1076 | { | ||
1077 | int retval; | ||
1078 | |||
1079 | write_lock_bh(&atalk_sockets_lock); | ||
1080 | |||
1081 | for (sat->sat_port = ATPORT_RESERVED; | ||
1082 | sat->sat_port < ATPORT_LAST; | ||
1083 | sat->sat_port++) { | ||
1084 | struct sock *s; | ||
1085 | struct hlist_node *node; | ||
1086 | |||
1087 | sk_for_each(s, node, &atalk_sockets) { | ||
1088 | struct atalk_sock *at = at_sk(s); | ||
1089 | |||
1090 | if (at->src_net == sat->sat_addr.s_net && | ||
1091 | at->src_node == sat->sat_addr.s_node && | ||
1092 | at->src_port == sat->sat_port) | ||
1093 | goto try_next_port; | ||
1094 | } | ||
1095 | |||
1096 | /* Wheee, it's free, assign and insert. */ | ||
1097 | __atalk_insert_socket(sk); | ||
1098 | at_sk(sk)->src_port = sat->sat_port; | ||
1099 | retval = 0; | ||
1100 | goto out; | ||
1101 | |||
1102 | try_next_port:; | ||
1103 | } | ||
1104 | |||
1105 | retval = -EBUSY; | ||
1106 | out: | ||
1107 | write_unlock_bh(&atalk_sockets_lock); | ||
1108 | return retval; | ||
1109 | } | ||
1110 | |||
1111 | static int atalk_autobind(struct sock *sk) | ||
1112 | { | ||
1113 | struct atalk_sock *at = at_sk(sk); | ||
1114 | struct sockaddr_at sat; | ||
1115 | struct atalk_addr *ap = atalk_find_primary(); | ||
1116 | int n = -EADDRNOTAVAIL; | ||
1117 | |||
1118 | if (!ap || ap->s_net == htons(ATADDR_ANYNET)) | ||
1119 | goto out; | ||
1120 | |||
1121 | at->src_net = sat.sat_addr.s_net = ap->s_net; | ||
1122 | at->src_node = sat.sat_addr.s_node = ap->s_node; | ||
1123 | |||
1124 | n = atalk_pick_and_bind_port(sk, &sat); | ||
1125 | if (!n) | ||
1126 | sock_reset_flag(sk, SOCK_ZAPPED); | ||
1127 | out: | ||
1128 | return n; | ||
1129 | } | ||
1130 | |||
1131 | /* Set the address 'our end' of the connection */ | ||
1132 | static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | ||
1133 | { | ||
1134 | struct sockaddr_at *addr = (struct sockaddr_at *)uaddr; | ||
1135 | struct sock *sk = sock->sk; | ||
1136 | struct atalk_sock *at = at_sk(sk); | ||
1137 | int err; | ||
1138 | |||
1139 | if (!sock_flag(sk, SOCK_ZAPPED) || | ||
1140 | addr_len != sizeof(struct sockaddr_at)) | ||
1141 | return -EINVAL; | ||
1142 | |||
1143 | if (addr->sat_family != AF_APPLETALK) | ||
1144 | return -EAFNOSUPPORT; | ||
1145 | |||
1146 | lock_kernel(); | ||
1147 | if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) { | ||
1148 | struct atalk_addr *ap = atalk_find_primary(); | ||
1149 | |||
1150 | err = -EADDRNOTAVAIL; | ||
1151 | if (!ap) | ||
1152 | goto out; | ||
1153 | |||
1154 | at->src_net = addr->sat_addr.s_net = ap->s_net; | ||
1155 | at->src_node = addr->sat_addr.s_node= ap->s_node; | ||
1156 | } else { | ||
1157 | err = -EADDRNOTAVAIL; | ||
1158 | if (!atalk_find_interface(addr->sat_addr.s_net, | ||
1159 | addr->sat_addr.s_node)) | ||
1160 | goto out; | ||
1161 | |||
1162 | at->src_net = addr->sat_addr.s_net; | ||
1163 | at->src_node = addr->sat_addr.s_node; | ||
1164 | } | ||
1165 | |||
1166 | if (addr->sat_port == ATADDR_ANYPORT) { | ||
1167 | err = atalk_pick_and_bind_port(sk, addr); | ||
1168 | |||
1169 | if (err < 0) | ||
1170 | goto out; | ||
1171 | } else { | ||
1172 | at->src_port = addr->sat_port; | ||
1173 | |||
1174 | err = -EADDRINUSE; | ||
1175 | if (atalk_find_or_insert_socket(sk, addr)) | ||
1176 | goto out; | ||
1177 | } | ||
1178 | |||
1179 | sock_reset_flag(sk, SOCK_ZAPPED); | ||
1180 | err = 0; | ||
1181 | out: | ||
1182 | unlock_kernel(); | ||
1183 | return err; | ||
1184 | } | ||
1185 | |||
1186 | /* Set the address we talk to */ | ||
1187 | static int atalk_connect(struct socket *sock, struct sockaddr *uaddr, | ||
1188 | int addr_len, int flags) | ||
1189 | { | ||
1190 | struct sock *sk = sock->sk; | ||
1191 | struct atalk_sock *at = at_sk(sk); | ||
1192 | struct sockaddr_at *addr; | ||
1193 | int err; | ||
1194 | |||
1195 | sk->sk_state = TCP_CLOSE; | ||
1196 | sock->state = SS_UNCONNECTED; | ||
1197 | |||
1198 | if (addr_len != sizeof(*addr)) | ||
1199 | return -EINVAL; | ||
1200 | |||
1201 | addr = (struct sockaddr_at *)uaddr; | ||
1202 | |||
1203 | if (addr->sat_family != AF_APPLETALK) | ||
1204 | return -EAFNOSUPPORT; | ||
1205 | |||
1206 | if (addr->sat_addr.s_node == ATADDR_BCAST && | ||
1207 | !sock_flag(sk, SOCK_BROADCAST)) { | ||
1208 | #if 1 | ||
1209 | printk(KERN_WARNING "%s is broken and did not set " | ||
1210 | "SO_BROADCAST. It will break when 2.2 is " | ||
1211 | "released.\n", | ||
1212 | current->comm); | ||
1213 | #else | ||
1214 | return -EACCES; | ||
1215 | #endif | ||
1216 | } | ||
1217 | |||
1218 | lock_kernel(); | ||
1219 | err = -EBUSY; | ||
1220 | if (sock_flag(sk, SOCK_ZAPPED)) | ||
1221 | if (atalk_autobind(sk) < 0) | ||
1222 | goto out; | ||
1223 | |||
1224 | err = -ENETUNREACH; | ||
1225 | if (!atrtr_get_dev(&addr->sat_addr)) | ||
1226 | goto out; | ||
1227 | |||
1228 | at->dest_port = addr->sat_port; | ||
1229 | at->dest_net = addr->sat_addr.s_net; | ||
1230 | at->dest_node = addr->sat_addr.s_node; | ||
1231 | |||
1232 | sock->state = SS_CONNECTED; | ||
1233 | sk->sk_state = TCP_ESTABLISHED; | ||
1234 | err = 0; | ||
1235 | out: | ||
1236 | unlock_kernel(); | ||
1237 | return err; | ||
1238 | } | ||
1239 | |||
1240 | /* | ||
1241 | * Find the name of an AppleTalk socket. Just copy the right | ||
1242 | * fields into the sockaddr. | ||
1243 | */ | ||
1244 | static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, | ||
1245 | int *uaddr_len, int peer) | ||
1246 | { | ||
1247 | struct sockaddr_at sat; | ||
1248 | struct sock *sk = sock->sk; | ||
1249 | struct atalk_sock *at = at_sk(sk); | ||
1250 | int err; | ||
1251 | |||
1252 | lock_kernel(); | ||
1253 | err = -ENOBUFS; | ||
1254 | if (sock_flag(sk, SOCK_ZAPPED)) | ||
1255 | if (atalk_autobind(sk) < 0) | ||
1256 | goto out; | ||
1257 | |||
1258 | *uaddr_len = sizeof(struct sockaddr_at); | ||
1259 | memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); | ||
1260 | |||
1261 | if (peer) { | ||
1262 | err = -ENOTCONN; | ||
1263 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1264 | goto out; | ||
1265 | |||
1266 | sat.sat_addr.s_net = at->dest_net; | ||
1267 | sat.sat_addr.s_node = at->dest_node; | ||
1268 | sat.sat_port = at->dest_port; | ||
1269 | } else { | ||
1270 | sat.sat_addr.s_net = at->src_net; | ||
1271 | sat.sat_addr.s_node = at->src_node; | ||
1272 | sat.sat_port = at->src_port; | ||
1273 | } | ||
1274 | |||
1275 | err = 0; | ||
1276 | sat.sat_family = AF_APPLETALK; | ||
1277 | memcpy(uaddr, &sat, sizeof(sat)); | ||
1278 | |||
1279 | out: | ||
1280 | unlock_kernel(); | ||
1281 | return err; | ||
1282 | } | ||
1283 | |||
1284 | static unsigned int atalk_poll(struct file *file, struct socket *sock, | ||
1285 | poll_table *wait) | ||
1286 | { | ||
1287 | int err; | ||
1288 | lock_kernel(); | ||
1289 | err = datagram_poll(file, sock, wait); | ||
1290 | unlock_kernel(); | ||
1291 | return err; | ||
1292 | } | ||
1293 | |||
1294 | #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE) | ||
1295 | static __inline__ int is_ip_over_ddp(struct sk_buff *skb) | ||
1296 | { | ||
1297 | return skb->data[12] == 22; | ||
1298 | } | ||
1299 | |||
1300 | static int handle_ip_over_ddp(struct sk_buff *skb) | ||
1301 | { | ||
1302 | struct net_device *dev = __dev_get_by_name(&init_net, "ipddp0"); | ||
1303 | struct net_device_stats *stats; | ||
1304 | |||
1305 | /* This needs to be able to handle ipddp"N" devices */ | ||
1306 | if (!dev) { | ||
1307 | kfree_skb(skb); | ||
1308 | return NET_RX_DROP; | ||
1309 | } | ||
1310 | |||
1311 | skb->protocol = htons(ETH_P_IP); | ||
1312 | skb_pull(skb, 13); | ||
1313 | skb->dev = dev; | ||
1314 | skb_reset_transport_header(skb); | ||
1315 | |||
1316 | stats = netdev_priv(dev); | ||
1317 | stats->rx_packets++; | ||
1318 | stats->rx_bytes += skb->len + 13; | ||
1319 | return netif_rx(skb); /* Send the SKB up to a higher place. */ | ||
1320 | } | ||
1321 | #else | ||
1322 | /* make it easy for gcc to optimize this test out, i.e. kill the code */ | ||
1323 | #define is_ip_over_ddp(skb) 0 | ||
1324 | #define handle_ip_over_ddp(skb) 0 | ||
1325 | #endif | ||
1326 | |||
1327 | static int atalk_route_packet(struct sk_buff *skb, struct net_device *dev, | ||
1328 | struct ddpehdr *ddp, __u16 len_hops, int origlen) | ||
1329 | { | ||
1330 | struct atalk_route *rt; | ||
1331 | struct atalk_addr ta; | ||
1332 | |||
1333 | /* | ||
1334 | * Don't route multicast, etc., packets, or packets sent to "this | ||
1335 | * network" | ||
1336 | */ | ||
1337 | if (skb->pkt_type != PACKET_HOST || !ddp->deh_dnet) { | ||
1338 | /* | ||
1339 | * FIXME: | ||
1340 | * | ||
1341 | * Can it ever happen that a packet is from a PPP iface and | ||
1342 | * needs to be broadcast onto the default network? | ||
1343 | */ | ||
1344 | if (dev->type == ARPHRD_PPP) | ||
1345 | printk(KERN_DEBUG "AppleTalk: didn't forward broadcast " | ||
1346 | "packet received from PPP iface\n"); | ||
1347 | goto free_it; | ||
1348 | } | ||
1349 | |||
1350 | ta.s_net = ddp->deh_dnet; | ||
1351 | ta.s_node = ddp->deh_dnode; | ||
1352 | |||
1353 | /* Route the packet */ | ||
1354 | rt = atrtr_find(&ta); | ||
1355 | /* increment hops count */ | ||
1356 | len_hops += 1 << 10; | ||
1357 | if (!rt || !(len_hops & (15 << 10))) | ||
1358 | goto free_it; | ||
1359 | |||
1360 | /* FIXME: use skb->cb to be able to use shared skbs */ | ||
1361 | |||
1362 | /* | ||
1363 | * Route goes through another gateway, so set the target to the | ||
1364 | * gateway instead. | ||
1365 | */ | ||
1366 | |||
1367 | if (rt->flags & RTF_GATEWAY) { | ||
1368 | ta.s_net = rt->gateway.s_net; | ||
1369 | ta.s_node = rt->gateway.s_node; | ||
1370 | } | ||
1371 | |||
1372 | /* Fix up skb->len field */ | ||
1373 | skb_trim(skb, min_t(unsigned int, origlen, | ||
1374 | (rt->dev->hard_header_len + | ||
1375 | ddp_dl->header_length + (len_hops & 1023)))); | ||
1376 | |||
1377 | /* FIXME: use skb->cb to be able to use shared skbs */ | ||
1378 | ddp->deh_len_hops = htons(len_hops); | ||
1379 | |||
1380 | /* | ||
1381 | * Send the buffer onwards | ||
1382 | * | ||
1383 | * Now we must always be careful. If it's come from LocalTalk to | ||
1384 | * EtherTalk it might not fit | ||
1385 | * | ||
1386 | * Order matters here: If a packet has to be copied to make a new | ||
1387 | * headroom (rare hopefully) then it won't need unsharing. | ||
1388 | * | ||
1389 | * Note. ddp-> becomes invalid at the realloc. | ||
1390 | */ | ||
1391 | if (skb_headroom(skb) < 22) { | ||
1392 | /* 22 bytes - 12 ether, 2 len, 3 802.2 5 snap */ | ||
1393 | struct sk_buff *nskb = skb_realloc_headroom(skb, 32); | ||
1394 | kfree_skb(skb); | ||
1395 | skb = nskb; | ||
1396 | } else | ||
1397 | skb = skb_unshare(skb, GFP_ATOMIC); | ||
1398 | |||
1399 | /* | ||
1400 | * If the buffer didn't vanish into the lack of space bitbucket we can | ||
1401 | * send it. | ||
1402 | */ | ||
1403 | if (skb == NULL) | ||
1404 | goto drop; | ||
1405 | |||
1406 | if (aarp_send_ddp(rt->dev, skb, &ta, NULL) == NET_XMIT_DROP) | ||
1407 | return NET_RX_DROP; | ||
1408 | return NET_RX_SUCCESS; | ||
1409 | free_it: | ||
1410 | kfree_skb(skb); | ||
1411 | drop: | ||
1412 | return NET_RX_DROP; | ||
1413 | } | ||
1414 | |||
1415 | /** | ||
1416 | * atalk_rcv - Receive a packet (in skb) from device dev | ||
1417 | * @skb - packet received | ||
1418 | * @dev - network device where the packet comes from | ||
1419 | * @pt - packet type | ||
1420 | * | ||
1421 | * Receive a packet (in skb) from device dev. This has come from the SNAP | ||
1422 | * decoder, and on entry skb->transport_header is the DDP header, skb->len | ||
1423 | * is the DDP header, skb->len is the DDP length. The physical headers | ||
1424 | * have been extracted. PPP should probably pass frames marked as for this | ||
1425 | * layer. [ie ARPHRD_ETHERTALK] | ||
1426 | */ | ||
1427 | static int atalk_rcv(struct sk_buff *skb, struct net_device *dev, | ||
1428 | struct packet_type *pt, struct net_device *orig_dev) | ||
1429 | { | ||
1430 | struct ddpehdr *ddp; | ||
1431 | struct sock *sock; | ||
1432 | struct atalk_iface *atif; | ||
1433 | struct sockaddr_at tosat; | ||
1434 | int origlen; | ||
1435 | __u16 len_hops; | ||
1436 | |||
1437 | if (!net_eq(dev_net(dev), &init_net)) | ||
1438 | goto drop; | ||
1439 | |||
1440 | /* Don't mangle buffer if shared */ | ||
1441 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) | ||
1442 | goto out; | ||
1443 | |||
1444 | /* Size check and make sure header is contiguous */ | ||
1445 | if (!pskb_may_pull(skb, sizeof(*ddp))) | ||
1446 | goto drop; | ||
1447 | |||
1448 | ddp = ddp_hdr(skb); | ||
1449 | |||
1450 | len_hops = ntohs(ddp->deh_len_hops); | ||
1451 | |||
1452 | /* Trim buffer in case of stray trailing data */ | ||
1453 | origlen = skb->len; | ||
1454 | skb_trim(skb, min_t(unsigned int, skb->len, len_hops & 1023)); | ||
1455 | |||
1456 | /* | ||
1457 | * Size check to see if ddp->deh_len was crap | ||
1458 | * (Otherwise we'll detonate most spectacularly | ||
1459 | * in the middle of atalk_checksum() or recvmsg()). | ||
1460 | */ | ||
1461 | if (skb->len < sizeof(*ddp) || skb->len < (len_hops & 1023)) { | ||
1462 | pr_debug("AppleTalk: dropping corrupted frame (deh_len=%u, " | ||
1463 | "skb->len=%u)\n", len_hops & 1023, skb->len); | ||
1464 | goto drop; | ||
1465 | } | ||
1466 | |||
1467 | /* | ||
1468 | * Any checksums. Note we don't do htons() on this == is assumed to be | ||
1469 | * valid for net byte orders all over the networking code... | ||
1470 | */ | ||
1471 | if (ddp->deh_sum && | ||
1472 | atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum) | ||
1473 | /* Not a valid AppleTalk frame - dustbin time */ | ||
1474 | goto drop; | ||
1475 | |||
1476 | /* Check the packet is aimed at us */ | ||
1477 | if (!ddp->deh_dnet) /* Net 0 is 'this network' */ | ||
1478 | atif = atalk_find_anynet(ddp->deh_dnode, dev); | ||
1479 | else | ||
1480 | atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); | ||
1481 | |||
1482 | if (!atif) { | ||
1483 | /* Not ours, so we route the packet via the correct | ||
1484 | * AppleTalk iface | ||
1485 | */ | ||
1486 | return atalk_route_packet(skb, dev, ddp, len_hops, origlen); | ||
1487 | } | ||
1488 | |||
1489 | /* if IP over DDP is not selected this code will be optimized out */ | ||
1490 | if (is_ip_over_ddp(skb)) | ||
1491 | return handle_ip_over_ddp(skb); | ||
1492 | /* | ||
1493 | * Which socket - atalk_search_socket() looks for a *full match* | ||
1494 | * of the <net, node, port> tuple. | ||
1495 | */ | ||
1496 | tosat.sat_addr.s_net = ddp->deh_dnet; | ||
1497 | tosat.sat_addr.s_node = ddp->deh_dnode; | ||
1498 | tosat.sat_port = ddp->deh_dport; | ||
1499 | |||
1500 | sock = atalk_search_socket(&tosat, atif); | ||
1501 | if (!sock) /* But not one of our sockets */ | ||
1502 | goto drop; | ||
1503 | |||
1504 | /* Queue packet (standard) */ | ||
1505 | skb->sk = sock; | ||
1506 | |||
1507 | if (sock_queue_rcv_skb(sock, skb) < 0) | ||
1508 | goto drop; | ||
1509 | |||
1510 | return NET_RX_SUCCESS; | ||
1511 | |||
1512 | drop: | ||
1513 | kfree_skb(skb); | ||
1514 | out: | ||
1515 | return NET_RX_DROP; | ||
1516 | |||
1517 | } | ||
1518 | |||
1519 | /* | ||
1520 | * Receive a LocalTalk frame. We make some demands on the caller here. | ||
1521 | * Caller must provide enough headroom on the packet to pull the short | ||
1522 | * header and append a long one. | ||
1523 | */ | ||
1524 | static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev, | ||
1525 | struct packet_type *pt, struct net_device *orig_dev) | ||
1526 | { | ||
1527 | if (!net_eq(dev_net(dev), &init_net)) | ||
1528 | goto freeit; | ||
1529 | |||
1530 | /* Expand any short form frames */ | ||
1531 | if (skb_mac_header(skb)[2] == 1) { | ||
1532 | struct ddpehdr *ddp; | ||
1533 | /* Find our address */ | ||
1534 | struct atalk_addr *ap = atalk_find_dev_addr(dev); | ||
1535 | |||
1536 | if (!ap || skb->len < sizeof(__be16) || skb->len > 1023) | ||
1537 | goto freeit; | ||
1538 | |||
1539 | /* Don't mangle buffer if shared */ | ||
1540 | if (!(skb = skb_share_check(skb, GFP_ATOMIC))) | ||
1541 | return 0; | ||
1542 | |||
1543 | /* | ||
1544 | * The push leaves us with a ddephdr not an shdr, and | ||
1545 | * handily the port bytes in the right place preset. | ||
1546 | */ | ||
1547 | ddp = (struct ddpehdr *) skb_push(skb, sizeof(*ddp) - 4); | ||
1548 | |||
1549 | /* Now fill in the long header */ | ||
1550 | |||
1551 | /* | ||
1552 | * These two first. The mac overlays the new source/dest | ||
1553 | * network information so we MUST copy these before | ||
1554 | * we write the network numbers ! | ||
1555 | */ | ||
1556 | |||
1557 | ddp->deh_dnode = skb_mac_header(skb)[0]; /* From physical header */ | ||
1558 | ddp->deh_snode = skb_mac_header(skb)[1]; /* From physical header */ | ||
1559 | |||
1560 | ddp->deh_dnet = ap->s_net; /* Network number */ | ||
1561 | ddp->deh_snet = ap->s_net; | ||
1562 | ddp->deh_sum = 0; /* No checksum */ | ||
1563 | /* | ||
1564 | * Not sure about this bit... | ||
1565 | */ | ||
1566 | /* Non routable, so force a drop if we slip up later */ | ||
1567 | ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10)); | ||
1568 | } | ||
1569 | skb_reset_transport_header(skb); | ||
1570 | |||
1571 | return atalk_rcv(skb, dev, pt, orig_dev); | ||
1572 | freeit: | ||
1573 | kfree_skb(skb); | ||
1574 | return 0; | ||
1575 | } | ||
1576 | |||
1577 | static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | ||
1578 | size_t len) | ||
1579 | { | ||
1580 | struct sock *sk = sock->sk; | ||
1581 | struct atalk_sock *at = at_sk(sk); | ||
1582 | struct sockaddr_at *usat = (struct sockaddr_at *)msg->msg_name; | ||
1583 | int flags = msg->msg_flags; | ||
1584 | int loopback = 0; | ||
1585 | struct sockaddr_at local_satalk, gsat; | ||
1586 | struct sk_buff *skb; | ||
1587 | struct net_device *dev; | ||
1588 | struct ddpehdr *ddp; | ||
1589 | int size; | ||
1590 | struct atalk_route *rt; | ||
1591 | int err; | ||
1592 | |||
1593 | if (flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT)) | ||
1594 | return -EINVAL; | ||
1595 | |||
1596 | if (len > DDP_MAXSZ) | ||
1597 | return -EMSGSIZE; | ||
1598 | |||
1599 | lock_kernel(); | ||
1600 | if (usat) { | ||
1601 | err = -EBUSY; | ||
1602 | if (sock_flag(sk, SOCK_ZAPPED)) | ||
1603 | if (atalk_autobind(sk) < 0) | ||
1604 | goto out; | ||
1605 | |||
1606 | err = -EINVAL; | ||
1607 | if (msg->msg_namelen < sizeof(*usat) || | ||
1608 | usat->sat_family != AF_APPLETALK) | ||
1609 | goto out; | ||
1610 | |||
1611 | err = -EPERM; | ||
1612 | /* netatalk didn't implement this check */ | ||
1613 | if (usat->sat_addr.s_node == ATADDR_BCAST && | ||
1614 | !sock_flag(sk, SOCK_BROADCAST)) { | ||
1615 | goto out; | ||
1616 | } | ||
1617 | } else { | ||
1618 | err = -ENOTCONN; | ||
1619 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1620 | goto out; | ||
1621 | usat = &local_satalk; | ||
1622 | usat->sat_family = AF_APPLETALK; | ||
1623 | usat->sat_port = at->dest_port; | ||
1624 | usat->sat_addr.s_node = at->dest_node; | ||
1625 | usat->sat_addr.s_net = at->dest_net; | ||
1626 | } | ||
1627 | |||
1628 | /* Build a packet */ | ||
1629 | SOCK_DEBUG(sk, "SK %p: Got address.\n", sk); | ||
1630 | |||
1631 | /* For headers */ | ||
1632 | size = sizeof(struct ddpehdr) + len + ddp_dl->header_length; | ||
1633 | |||
1634 | if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { | ||
1635 | rt = atrtr_find(&usat->sat_addr); | ||
1636 | } else { | ||
1637 | struct atalk_addr at_hint; | ||
1638 | |||
1639 | at_hint.s_node = 0; | ||
1640 | at_hint.s_net = at->src_net; | ||
1641 | |||
1642 | rt = atrtr_find(&at_hint); | ||
1643 | } | ||
1644 | err = ENETUNREACH; | ||
1645 | if (!rt) | ||
1646 | goto out; | ||
1647 | |||
1648 | dev = rt->dev; | ||
1649 | |||
1650 | SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", | ||
1651 | sk, size, dev->name); | ||
1652 | |||
1653 | size += dev->hard_header_len; | ||
1654 | skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err); | ||
1655 | if (!skb) | ||
1656 | goto out; | ||
1657 | |||
1658 | skb->sk = sk; | ||
1659 | skb_reserve(skb, ddp_dl->header_length); | ||
1660 | skb_reserve(skb, dev->hard_header_len); | ||
1661 | skb->dev = dev; | ||
1662 | |||
1663 | SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); | ||
1664 | |||
1665 | ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr)); | ||
1666 | ddp->deh_len_hops = htons(len + sizeof(*ddp)); | ||
1667 | ddp->deh_dnet = usat->sat_addr.s_net; | ||
1668 | ddp->deh_snet = at->src_net; | ||
1669 | ddp->deh_dnode = usat->sat_addr.s_node; | ||
1670 | ddp->deh_snode = at->src_node; | ||
1671 | ddp->deh_dport = usat->sat_port; | ||
1672 | ddp->deh_sport = at->src_port; | ||
1673 | |||
1674 | SOCK_DEBUG(sk, "SK %p: Copy user data (%Zd bytes).\n", sk, len); | ||
1675 | |||
1676 | err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); | ||
1677 | if (err) { | ||
1678 | kfree_skb(skb); | ||
1679 | err = -EFAULT; | ||
1680 | goto out; | ||
1681 | } | ||
1682 | |||
1683 | if (sk->sk_no_check == 1) | ||
1684 | ddp->deh_sum = 0; | ||
1685 | else | ||
1686 | ddp->deh_sum = atalk_checksum(skb, len + sizeof(*ddp)); | ||
1687 | |||
1688 | /* | ||
1689 | * Loopback broadcast packets to non gateway targets (ie routes | ||
1690 | * to group we are in) | ||
1691 | */ | ||
1692 | if (ddp->deh_dnode == ATADDR_BCAST && | ||
1693 | !(rt->flags & RTF_GATEWAY) && !(dev->flags & IFF_LOOPBACK)) { | ||
1694 | struct sk_buff *skb2 = skb_copy(skb, GFP_KERNEL); | ||
1695 | |||
1696 | if (skb2) { | ||
1697 | loopback = 1; | ||
1698 | SOCK_DEBUG(sk, "SK %p: send out(copy).\n", sk); | ||
1699 | /* | ||
1700 | * If it fails it is queued/sent above in the aarp queue | ||
1701 | */ | ||
1702 | aarp_send_ddp(dev, skb2, &usat->sat_addr, NULL); | ||
1703 | } | ||
1704 | } | ||
1705 | |||
1706 | if (dev->flags & IFF_LOOPBACK || loopback) { | ||
1707 | SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); | ||
1708 | /* loop back */ | ||
1709 | skb_orphan(skb); | ||
1710 | if (ddp->deh_dnode == ATADDR_BCAST) { | ||
1711 | struct atalk_addr at_lo; | ||
1712 | |||
1713 | at_lo.s_node = 0; | ||
1714 | at_lo.s_net = 0; | ||
1715 | |||
1716 | rt = atrtr_find(&at_lo); | ||
1717 | if (!rt) { | ||
1718 | kfree_skb(skb); | ||
1719 | err = -ENETUNREACH; | ||
1720 | goto out; | ||
1721 | } | ||
1722 | dev = rt->dev; | ||
1723 | skb->dev = dev; | ||
1724 | } | ||
1725 | ddp_dl->request(ddp_dl, skb, dev->dev_addr); | ||
1726 | } else { | ||
1727 | SOCK_DEBUG(sk, "SK %p: send out.\n", sk); | ||
1728 | if (rt->flags & RTF_GATEWAY) { | ||
1729 | gsat.sat_addr = rt->gateway; | ||
1730 | usat = &gsat; | ||
1731 | } | ||
1732 | |||
1733 | /* | ||
1734 | * If it fails it is queued/sent above in the aarp queue | ||
1735 | */ | ||
1736 | aarp_send_ddp(dev, skb, &usat->sat_addr, NULL); | ||
1737 | } | ||
1738 | SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len); | ||
1739 | |||
1740 | out: | ||
1741 | unlock_kernel(); | ||
1742 | return err ? : len; | ||
1743 | } | ||
1744 | |||
1745 | static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, | ||
1746 | size_t size, int flags) | ||
1747 | { | ||
1748 | struct sock *sk = sock->sk; | ||
1749 | struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; | ||
1750 | struct ddpehdr *ddp; | ||
1751 | int copied = 0; | ||
1752 | int offset = 0; | ||
1753 | int err = 0; | ||
1754 | struct sk_buff *skb; | ||
1755 | |||
1756 | lock_kernel(); | ||
1757 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | ||
1758 | flags & MSG_DONTWAIT, &err); | ||
1759 | if (!skb) | ||
1760 | goto out; | ||
1761 | |||
1762 | /* FIXME: use skb->cb to be able to use shared skbs */ | ||
1763 | ddp = ddp_hdr(skb); | ||
1764 | copied = ntohs(ddp->deh_len_hops) & 1023; | ||
1765 | |||
1766 | if (sk->sk_type != SOCK_RAW) { | ||
1767 | offset = sizeof(*ddp); | ||
1768 | copied -= offset; | ||
1769 | } | ||
1770 | |||
1771 | if (copied > size) { | ||
1772 | copied = size; | ||
1773 | msg->msg_flags |= MSG_TRUNC; | ||
1774 | } | ||
1775 | err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied); | ||
1776 | |||
1777 | if (!err) { | ||
1778 | if (sat) { | ||
1779 | sat->sat_family = AF_APPLETALK; | ||
1780 | sat->sat_port = ddp->deh_sport; | ||
1781 | sat->sat_addr.s_node = ddp->deh_snode; | ||
1782 | sat->sat_addr.s_net = ddp->deh_snet; | ||
1783 | } | ||
1784 | msg->msg_namelen = sizeof(*sat); | ||
1785 | } | ||
1786 | |||
1787 | skb_free_datagram(sk, skb); /* Free the datagram. */ | ||
1788 | |||
1789 | out: | ||
1790 | unlock_kernel(); | ||
1791 | return err ? : copied; | ||
1792 | } | ||
1793 | |||
1794 | |||
1795 | /* | ||
1796 | * AppleTalk ioctl calls. | ||
1797 | */ | ||
1798 | static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
1799 | { | ||
1800 | int rc = -ENOIOCTLCMD; | ||
1801 | struct sock *sk = sock->sk; | ||
1802 | void __user *argp = (void __user *)arg; | ||
1803 | |||
1804 | switch (cmd) { | ||
1805 | /* Protocol layer */ | ||
1806 | case TIOCOUTQ: { | ||
1807 | long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | ||
1808 | |||
1809 | if (amount < 0) | ||
1810 | amount = 0; | ||
1811 | rc = put_user(amount, (int __user *)argp); | ||
1812 | break; | ||
1813 | } | ||
1814 | case TIOCINQ: { | ||
1815 | /* | ||
1816 | * These two are safe on a single CPU system as only | ||
1817 | * user tasks fiddle here | ||
1818 | */ | ||
1819 | struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); | ||
1820 | long amount = 0; | ||
1821 | |||
1822 | if (skb) | ||
1823 | amount = skb->len - sizeof(struct ddpehdr); | ||
1824 | rc = put_user(amount, (int __user *)argp); | ||
1825 | break; | ||
1826 | } | ||
1827 | case SIOCGSTAMP: | ||
1828 | rc = sock_get_timestamp(sk, argp); | ||
1829 | break; | ||
1830 | case SIOCGSTAMPNS: | ||
1831 | rc = sock_get_timestampns(sk, argp); | ||
1832 | break; | ||
1833 | /* Routing */ | ||
1834 | case SIOCADDRT: | ||
1835 | case SIOCDELRT: | ||
1836 | rc = -EPERM; | ||
1837 | if (capable(CAP_NET_ADMIN)) | ||
1838 | rc = atrtr_ioctl(cmd, argp); | ||
1839 | break; | ||
1840 | /* Interface */ | ||
1841 | case SIOCGIFADDR: | ||
1842 | case SIOCSIFADDR: | ||
1843 | case SIOCGIFBRDADDR: | ||
1844 | case SIOCATALKDIFADDR: | ||
1845 | case SIOCDIFADDR: | ||
1846 | case SIOCSARP: /* proxy AARP */ | ||
1847 | case SIOCDARP: /* proxy AARP */ | ||
1848 | rtnl_lock(); | ||
1849 | rc = atif_ioctl(cmd, argp); | ||
1850 | rtnl_unlock(); | ||
1851 | break; | ||
1852 | } | ||
1853 | |||
1854 | return rc; | ||
1855 | } | ||
1856 | |||
1857 | |||
1858 | #ifdef CONFIG_COMPAT | ||
1859 | static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||
1860 | { | ||
1861 | /* | ||
1862 | * SIOCATALKDIFADDR is a SIOCPROTOPRIVATE ioctl number, so we | ||
1863 | * cannot handle it in common code. The data we access if ifreq | ||
1864 | * here is compatible, so we can simply call the native | ||
1865 | * handler. | ||
1866 | */ | ||
1867 | if (cmd == SIOCATALKDIFADDR) | ||
1868 | return atalk_ioctl(sock, cmd, (unsigned long)compat_ptr(arg)); | ||
1869 | |||
1870 | return -ENOIOCTLCMD; | ||
1871 | } | ||
1872 | #endif | ||
1873 | |||
1874 | |||
1875 | static const struct net_proto_family atalk_family_ops = { | ||
1876 | .family = PF_APPLETALK, | ||
1877 | .create = atalk_create, | ||
1878 | .owner = THIS_MODULE, | ||
1879 | }; | ||
1880 | |||
1881 | static const struct proto_ops atalk_dgram_ops = { | ||
1882 | .family = PF_APPLETALK, | ||
1883 | .owner = THIS_MODULE, | ||
1884 | .release = atalk_release, | ||
1885 | .bind = atalk_bind, | ||
1886 | .connect = atalk_connect, | ||
1887 | .socketpair = sock_no_socketpair, | ||
1888 | .accept = sock_no_accept, | ||
1889 | .getname = atalk_getname, | ||
1890 | .poll = atalk_poll, | ||
1891 | .ioctl = atalk_ioctl, | ||
1892 | #ifdef CONFIG_COMPAT | ||
1893 | .compat_ioctl = atalk_compat_ioctl, | ||
1894 | #endif | ||
1895 | .listen = sock_no_listen, | ||
1896 | .shutdown = sock_no_shutdown, | ||
1897 | .setsockopt = sock_no_setsockopt, | ||
1898 | .getsockopt = sock_no_getsockopt, | ||
1899 | .sendmsg = atalk_sendmsg, | ||
1900 | .recvmsg = atalk_recvmsg, | ||
1901 | .mmap = sock_no_mmap, | ||
1902 | .sendpage = sock_no_sendpage, | ||
1903 | }; | ||
1904 | |||
1905 | static struct notifier_block ddp_notifier = { | ||
1906 | .notifier_call = ddp_device_event, | ||
1907 | }; | ||
1908 | |||
1909 | static struct packet_type ltalk_packet_type __read_mostly = { | ||
1910 | .type = cpu_to_be16(ETH_P_LOCALTALK), | ||
1911 | .func = ltalk_rcv, | ||
1912 | }; | ||
1913 | |||
1914 | static struct packet_type ppptalk_packet_type __read_mostly = { | ||
1915 | .type = cpu_to_be16(ETH_P_PPPTALK), | ||
1916 | .func = atalk_rcv, | ||
1917 | }; | ||
1918 | |||
1919 | static unsigned char ddp_snap_id[] = { 0x08, 0x00, 0x07, 0x80, 0x9B }; | ||
1920 | |||
1921 | /* Export symbols for use by drivers when AppleTalk is a module */ | ||
1922 | EXPORT_SYMBOL(atrtr_get_dev); | ||
1923 | EXPORT_SYMBOL(atalk_find_dev_addr); | ||
1924 | |||
1925 | static const char atalk_err_snap[] __initconst = | ||
1926 | KERN_CRIT "Unable to register DDP with SNAP.\n"; | ||
1927 | |||
1928 | /* Called by proto.c on kernel start up */ | ||
1929 | static int __init atalk_init(void) | ||
1930 | { | ||
1931 | int rc = proto_register(&ddp_proto, 0); | ||
1932 | |||
1933 | if (rc != 0) | ||
1934 | goto out; | ||
1935 | |||
1936 | (void)sock_register(&atalk_family_ops); | ||
1937 | ddp_dl = register_snap_client(ddp_snap_id, atalk_rcv); | ||
1938 | if (!ddp_dl) | ||
1939 | printk(atalk_err_snap); | ||
1940 | |||
1941 | dev_add_pack(<alk_packet_type); | ||
1942 | dev_add_pack(&ppptalk_packet_type); | ||
1943 | |||
1944 | register_netdevice_notifier(&ddp_notifier); | ||
1945 | aarp_proto_init(); | ||
1946 | atalk_proc_init(); | ||
1947 | atalk_register_sysctl(); | ||
1948 | out: | ||
1949 | return rc; | ||
1950 | } | ||
1951 | module_init(atalk_init); | ||
1952 | |||
1953 | /* | ||
1954 | * No explicit module reference count manipulation is needed in the | ||
1955 | * protocol. Socket layer sets module reference count for us | ||
1956 | * and interfaces reference counting is done | ||
1957 | * by the network device layer. | ||
1958 | * | ||
1959 | * Ergo, before the AppleTalk module can be removed, all AppleTalk | ||
1960 | * sockets be closed from user space. | ||
1961 | */ | ||
1962 | static void __exit atalk_exit(void) | ||
1963 | { | ||
1964 | #ifdef CONFIG_SYSCTL | ||
1965 | atalk_unregister_sysctl(); | ||
1966 | #endif /* CONFIG_SYSCTL */ | ||
1967 | atalk_proc_exit(); | ||
1968 | aarp_cleanup_module(); /* General aarp clean-up. */ | ||
1969 | unregister_netdevice_notifier(&ddp_notifier); | ||
1970 | dev_remove_pack(<alk_packet_type); | ||
1971 | dev_remove_pack(&ppptalk_packet_type); | ||
1972 | unregister_snap_client(ddp_dl); | ||
1973 | sock_unregister(PF_APPLETALK); | ||
1974 | proto_unregister(&ddp_proto); | ||
1975 | } | ||
1976 | module_exit(atalk_exit); | ||
1977 | |||
1978 | MODULE_LICENSE("GPL"); | ||
1979 | MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>"); | ||
1980 | MODULE_DESCRIPTION("AppleTalk 0.20\n"); | ||
1981 | MODULE_ALIAS_NETPROTO(PF_APPLETALK); | ||
diff --git a/drivers/staging/appletalk/dev.c b/drivers/staging/appletalk/dev.c new file mode 100644 index 00000000000..6c8016f6186 --- /dev/null +++ b/drivers/staging/appletalk/dev.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Moved here from drivers/net/net_init.c, which is: | ||
3 | * Written 1993,1994,1995 by Donald Becker. | ||
4 | */ | ||
5 | |||
6 | #include <linux/errno.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <linux/if_arp.h> | ||
10 | #include <linux/if_ltalk.h> | ||
11 | |||
12 | static void ltalk_setup(struct net_device *dev) | ||
13 | { | ||
14 | /* Fill in the fields of the device structure with localtalk-generic values. */ | ||
15 | |||
16 | dev->type = ARPHRD_LOCALTLK; | ||
17 | dev->hard_header_len = LTALK_HLEN; | ||
18 | dev->mtu = LTALK_MTU; | ||
19 | dev->addr_len = LTALK_ALEN; | ||
20 | dev->tx_queue_len = 10; | ||
21 | |||
22 | dev->broadcast[0] = 0xFF; | ||
23 | |||
24 | dev->flags = IFF_BROADCAST|IFF_MULTICAST|IFF_NOARP; | ||
25 | } | ||
26 | |||
27 | /** | ||
28 | * alloc_ltalkdev - Allocates and sets up an localtalk device | ||
29 | * @sizeof_priv: Size of additional driver-private structure to be allocated | ||
30 | * for this localtalk device | ||
31 | * | ||
32 | * Fill in the fields of the device structure with localtalk-generic | ||
33 | * values. Basically does everything except registering the device. | ||
34 | * | ||
35 | * Constructs a new net device, complete with a private data area of | ||
36 | * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for | ||
37 | * this private data area. | ||
38 | */ | ||
39 | |||
40 | struct net_device *alloc_ltalkdev(int sizeof_priv) | ||
41 | { | ||
42 | return alloc_netdev(sizeof_priv, "lt%d", ltalk_setup); | ||
43 | } | ||
44 | EXPORT_SYMBOL(alloc_ltalkdev); | ||
diff --git a/drivers/staging/appletalk/ipddp.c b/drivers/staging/appletalk/ipddp.c new file mode 100644 index 00000000000..58b4e6098ad --- /dev/null +++ b/drivers/staging/appletalk/ipddp.c | |||
@@ -0,0 +1,335 @@ | |||
1 | /* | ||
2 | * ipddp.c: IP to Appletalk-IP Encapsulation driver for Linux | ||
3 | * Appletalk-IP to IP Decapsulation driver for Linux | ||
4 | * | ||
5 | * Authors: | ||
6 | * - DDP-IP Encap by: Bradford W. Johnson <johns393@maroon.tc.umn.edu> | ||
7 | * - DDP-IP Decap by: Jay Schulist <jschlst@samba.org> | ||
8 | * | ||
9 | * Derived from: | ||
10 | * - Almost all code already existed in net/appletalk/ddp.c I just | ||
11 | * moved/reorginized it into a driver file. Original IP-over-DDP code | ||
12 | * was done by Bradford W. Johnson <johns393@maroon.tc.umn.edu> | ||
13 | * - skeleton.c: A network driver outline for linux. | ||
14 | * Written 1993-94 by Donald Becker. | ||
15 | * - dummy.c: A dummy net driver. By Nick Holloway. | ||
16 | * - MacGate: A user space Daemon for Appletalk-IP Decap for | ||
17 | * Linux by Jay Schulist <jschlst@samba.org> | ||
18 | * | ||
19 | * Copyright 1993 United States Government as represented by the | ||
20 | * Director, National Security Agency. | ||
21 | * | ||
22 | * This software may be used and distributed according to the terms | ||
23 | * of the GNU General Public License, incorporated herein by reference. | ||
24 | */ | ||
25 | |||
26 | #include <linux/module.h> | ||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/netdevice.h> | ||
30 | #include <linux/etherdevice.h> | ||
31 | #include <linux/ip.h> | ||
32 | #include <linux/if_arp.h> | ||
33 | #include <linux/slab.h> | ||
34 | #include <net/route.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | |||
37 | #include "atalk.h" | ||
38 | #include "ipddp.h" /* Our stuff */ | ||
39 | |||
40 | static const char version[] = KERN_INFO "ipddp.c:v0.01 8/28/97 Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n"; | ||
41 | |||
42 | static struct ipddp_route *ipddp_route_list; | ||
43 | static DEFINE_SPINLOCK(ipddp_route_lock); | ||
44 | |||
45 | #ifdef CONFIG_IPDDP_ENCAP | ||
46 | static int ipddp_mode = IPDDP_ENCAP; | ||
47 | #else | ||
48 | static int ipddp_mode = IPDDP_DECAP; | ||
49 | #endif | ||
50 | |||
51 | /* Index to functions, as function prototypes. */ | ||
52 | static netdev_tx_t ipddp_xmit(struct sk_buff *skb, | ||
53 | struct net_device *dev); | ||
54 | static int ipddp_create(struct ipddp_route *new_rt); | ||
55 | static int ipddp_delete(struct ipddp_route *rt); | ||
56 | static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt); | ||
57 | static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); | ||
58 | |||
59 | static const struct net_device_ops ipddp_netdev_ops = { | ||
60 | .ndo_start_xmit = ipddp_xmit, | ||
61 | .ndo_do_ioctl = ipddp_ioctl, | ||
62 | .ndo_change_mtu = eth_change_mtu, | ||
63 | .ndo_set_mac_address = eth_mac_addr, | ||
64 | .ndo_validate_addr = eth_validate_addr, | ||
65 | }; | ||
66 | |||
67 | static struct net_device * __init ipddp_init(void) | ||
68 | { | ||
69 | static unsigned version_printed; | ||
70 | struct net_device *dev; | ||
71 | int err; | ||
72 | |||
73 | dev = alloc_etherdev(0); | ||
74 | if (!dev) | ||
75 | return ERR_PTR(-ENOMEM); | ||
76 | |||
77 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | ||
78 | strcpy(dev->name, "ipddp%d"); | ||
79 | |||
80 | if (version_printed++ == 0) | ||
81 | printk(version); | ||
82 | |||
83 | /* Initialize the device structure. */ | ||
84 | dev->netdev_ops = &ipddp_netdev_ops; | ||
85 | |||
86 | dev->type = ARPHRD_IPDDP; /* IP over DDP tunnel */ | ||
87 | dev->mtu = 585; | ||
88 | dev->flags |= IFF_NOARP; | ||
89 | |||
90 | /* | ||
91 | * The worst case header we will need is currently a | ||
92 | * ethernet header (14 bytes) and a ddp header (sizeof ddpehdr+1) | ||
93 | * We send over SNAP so that takes another 8 bytes. | ||
94 | */ | ||
95 | dev->hard_header_len = 14+8+sizeof(struct ddpehdr)+1; | ||
96 | |||
97 | err = register_netdev(dev); | ||
98 | if (err) { | ||
99 | free_netdev(dev); | ||
100 | return ERR_PTR(err); | ||
101 | } | ||
102 | |||
103 | /* Let the user now what mode we are in */ | ||
104 | if(ipddp_mode == IPDDP_ENCAP) | ||
105 | printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n", | ||
106 | dev->name); | ||
107 | if(ipddp_mode == IPDDP_DECAP) | ||
108 | printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@samba.org>\n", | ||
109 | dev->name); | ||
110 | |||
111 | return dev; | ||
112 | } | ||
113 | |||
114 | |||
115 | /* | ||
116 | * Transmit LLAP/ELAP frame using aarp_send_ddp. | ||
117 | */ | ||
118 | static netdev_tx_t ipddp_xmit(struct sk_buff *skb, struct net_device *dev) | ||
119 | { | ||
120 | __be32 paddr = skb_rtable(skb)->rt_gateway; | ||
121 | struct ddpehdr *ddp; | ||
122 | struct ipddp_route *rt; | ||
123 | struct atalk_addr *our_addr; | ||
124 | |||
125 | spin_lock(&ipddp_route_lock); | ||
126 | |||
127 | /* | ||
128 | * Find appropriate route to use, based only on IP number. | ||
129 | */ | ||
130 | for(rt = ipddp_route_list; rt != NULL; rt = rt->next) | ||
131 | { | ||
132 | if(rt->ip == paddr) | ||
133 | break; | ||
134 | } | ||
135 | if(rt == NULL) { | ||
136 | spin_unlock(&ipddp_route_lock); | ||
137 | return NETDEV_TX_OK; | ||
138 | } | ||
139 | |||
140 | our_addr = atalk_find_dev_addr(rt->dev); | ||
141 | |||
142 | if(ipddp_mode == IPDDP_DECAP) | ||
143 | /* | ||
144 | * Pull off the excess room that should not be there. | ||
145 | * This is due to a hard-header problem. This is the | ||
146 | * quick fix for now though, till it breaks. | ||
147 | */ | ||
148 | skb_pull(skb, 35-(sizeof(struct ddpehdr)+1)); | ||
149 | |||
150 | /* Create the Extended DDP header */ | ||
151 | ddp = (struct ddpehdr *)skb->data; | ||
152 | ddp->deh_len_hops = htons(skb->len + (1<<10)); | ||
153 | ddp->deh_sum = 0; | ||
154 | |||
155 | /* | ||
156 | * For Localtalk we need aarp_send_ddp to strip the | ||
157 | * long DDP header and place a shot DDP header on it. | ||
158 | */ | ||
159 | if(rt->dev->type == ARPHRD_LOCALTLK) | ||
160 | { | ||
161 | ddp->deh_dnet = 0; /* FIXME more hops?? */ | ||
162 | ddp->deh_snet = 0; | ||
163 | } | ||
164 | else | ||
165 | { | ||
166 | ddp->deh_dnet = rt->at.s_net; /* FIXME more hops?? */ | ||
167 | ddp->deh_snet = our_addr->s_net; | ||
168 | } | ||
169 | ddp->deh_dnode = rt->at.s_node; | ||
170 | ddp->deh_snode = our_addr->s_node; | ||
171 | ddp->deh_dport = 72; | ||
172 | ddp->deh_sport = 72; | ||
173 | |||
174 | *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ | ||
175 | |||
176 | skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ | ||
177 | |||
178 | dev->stats.tx_packets++; | ||
179 | dev->stats.tx_bytes += skb->len; | ||
180 | |||
181 | aarp_send_ddp(rt->dev, skb, &rt->at, NULL); | ||
182 | |||
183 | spin_unlock(&ipddp_route_lock); | ||
184 | |||
185 | return NETDEV_TX_OK; | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Create a routing entry. We first verify that the | ||
190 | * record does not already exist. If it does we return -EEXIST | ||
191 | */ | ||
192 | static int ipddp_create(struct ipddp_route *new_rt) | ||
193 | { | ||
194 | struct ipddp_route *rt = kmalloc(sizeof(*rt), GFP_KERNEL); | ||
195 | |||
196 | if (rt == NULL) | ||
197 | return -ENOMEM; | ||
198 | |||
199 | rt->ip = new_rt->ip; | ||
200 | rt->at = new_rt->at; | ||
201 | rt->next = NULL; | ||
202 | if ((rt->dev = atrtr_get_dev(&rt->at)) == NULL) { | ||
203 | kfree(rt); | ||
204 | return -ENETUNREACH; | ||
205 | } | ||
206 | |||
207 | spin_lock_bh(&ipddp_route_lock); | ||
208 | if (__ipddp_find_route(rt)) { | ||
209 | spin_unlock_bh(&ipddp_route_lock); | ||
210 | kfree(rt); | ||
211 | return -EEXIST; | ||
212 | } | ||
213 | |||
214 | rt->next = ipddp_route_list; | ||
215 | ipddp_route_list = rt; | ||
216 | |||
217 | spin_unlock_bh(&ipddp_route_lock); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * Delete a route, we only delete a FULL match. | ||
224 | * If route does not exist we return -ENOENT. | ||
225 | */ | ||
226 | static int ipddp_delete(struct ipddp_route *rt) | ||
227 | { | ||
228 | struct ipddp_route **r = &ipddp_route_list; | ||
229 | struct ipddp_route *tmp; | ||
230 | |||
231 | spin_lock_bh(&ipddp_route_lock); | ||
232 | while((tmp = *r) != NULL) | ||
233 | { | ||
234 | if(tmp->ip == rt->ip && | ||
235 | tmp->at.s_net == rt->at.s_net && | ||
236 | tmp->at.s_node == rt->at.s_node) | ||
237 | { | ||
238 | *r = tmp->next; | ||
239 | spin_unlock_bh(&ipddp_route_lock); | ||
240 | kfree(tmp); | ||
241 | return 0; | ||
242 | } | ||
243 | r = &tmp->next; | ||
244 | } | ||
245 | |||
246 | spin_unlock_bh(&ipddp_route_lock); | ||
247 | return -ENOENT; | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Find a routing entry, we only return a FULL match | ||
252 | */ | ||
253 | static struct ipddp_route* __ipddp_find_route(struct ipddp_route *rt) | ||
254 | { | ||
255 | struct ipddp_route *f; | ||
256 | |||
257 | for(f = ipddp_route_list; f != NULL; f = f->next) | ||
258 | { | ||
259 | if(f->ip == rt->ip && | ||
260 | f->at.s_net == rt->at.s_net && | ||
261 | f->at.s_node == rt->at.s_node) | ||
262 | return f; | ||
263 | } | ||
264 | |||
265 | return NULL; | ||
266 | } | ||
267 | |||
268 | static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||
269 | { | ||
270 | struct ipddp_route __user *rt = ifr->ifr_data; | ||
271 | struct ipddp_route rcp, rcp2, *rp; | ||
272 | |||
273 | if(!capable(CAP_NET_ADMIN)) | ||
274 | return -EPERM; | ||
275 | |||
276 | if(copy_from_user(&rcp, rt, sizeof(rcp))) | ||
277 | return -EFAULT; | ||
278 | |||
279 | switch(cmd) | ||
280 | { | ||
281 | case SIOCADDIPDDPRT: | ||
282 | return ipddp_create(&rcp); | ||
283 | |||
284 | case SIOCFINDIPDDPRT: | ||
285 | spin_lock_bh(&ipddp_route_lock); | ||
286 | rp = __ipddp_find_route(&rcp); | ||
287 | if (rp) | ||
288 | memcpy(&rcp2, rp, sizeof(rcp2)); | ||
289 | spin_unlock_bh(&ipddp_route_lock); | ||
290 | |||
291 | if (rp) { | ||
292 | if (copy_to_user(rt, &rcp2, | ||
293 | sizeof(struct ipddp_route))) | ||
294 | return -EFAULT; | ||
295 | return 0; | ||
296 | } else | ||
297 | return -ENOENT; | ||
298 | |||
299 | case SIOCDELIPDDPRT: | ||
300 | return ipddp_delete(&rcp); | ||
301 | |||
302 | default: | ||
303 | return -EINVAL; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | static struct net_device *dev_ipddp; | ||
308 | |||
309 | MODULE_LICENSE("GPL"); | ||
310 | module_param(ipddp_mode, int, 0); | ||
311 | |||
312 | static int __init ipddp_init_module(void) | ||
313 | { | ||
314 | dev_ipddp = ipddp_init(); | ||
315 | if (IS_ERR(dev_ipddp)) | ||
316 | return PTR_ERR(dev_ipddp); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | static void __exit ipddp_cleanup_module(void) | ||
321 | { | ||
322 | struct ipddp_route *p; | ||
323 | |||
324 | unregister_netdev(dev_ipddp); | ||
325 | free_netdev(dev_ipddp); | ||
326 | |||
327 | while (ipddp_route_list) { | ||
328 | p = ipddp_route_list->next; | ||
329 | kfree(ipddp_route_list); | ||
330 | ipddp_route_list = p; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | module_init(ipddp_init_module); | ||
335 | module_exit(ipddp_cleanup_module); | ||
diff --git a/drivers/staging/appletalk/ipddp.h b/drivers/staging/appletalk/ipddp.h new file mode 100644 index 00000000000..531519da99a --- /dev/null +++ b/drivers/staging/appletalk/ipddp.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * ipddp.h: Header for IP-over-DDP driver for Linux. | ||
3 | */ | ||
4 | |||
5 | #ifndef __LINUX_IPDDP_H | ||
6 | #define __LINUX_IPDDP_H | ||
7 | |||
8 | #ifdef __KERNEL__ | ||
9 | |||
10 | #define SIOCADDIPDDPRT (SIOCDEVPRIVATE) | ||
11 | #define SIOCDELIPDDPRT (SIOCDEVPRIVATE+1) | ||
12 | #define SIOCFINDIPDDPRT (SIOCDEVPRIVATE+2) | ||
13 | |||
14 | struct ipddp_route | ||
15 | { | ||
16 | struct net_device *dev; /* Carrier device */ | ||
17 | __be32 ip; /* IP address */ | ||
18 | struct atalk_addr at; /* Gateway appletalk address */ | ||
19 | int flags; | ||
20 | struct ipddp_route *next; | ||
21 | }; | ||
22 | |||
23 | #define IPDDP_ENCAP 1 | ||
24 | #define IPDDP_DECAP 2 | ||
25 | |||
26 | #endif /* __KERNEL__ */ | ||
27 | #endif /* __LINUX_IPDDP_H */ | ||
diff --git a/drivers/staging/appletalk/ltpc.c b/drivers/staging/appletalk/ltpc.c new file mode 100644 index 00000000000..60caf892695 --- /dev/null +++ b/drivers/staging/appletalk/ltpc.c | |||
@@ -0,0 +1,1288 @@ | |||
1 | /*** ltpc.c -- a driver for the LocalTalk PC card. | ||
2 | * | ||
3 | * Copyright (c) 1995,1996 Bradford W. Johnson <johns393@maroon.tc.umn.edu> | ||
4 | * | ||
5 | * This software may be used and distributed according to the terms | ||
6 | * of the GNU General Public License, incorporated herein by reference. | ||
7 | * | ||
8 | * This is ALPHA code at best. It may not work for you. It may | ||
9 | * damage your equipment. It may damage your relations with other | ||
10 | * users of your network. Use it at your own risk! | ||
11 | * | ||
12 | * Based in part on: | ||
13 | * skeleton.c by Donald Becker | ||
14 | * dummy.c by Nick Holloway and Alan Cox | ||
15 | * loopback.c by Ross Biro, Fred van Kampen, Donald Becker | ||
16 | * the netatalk source code (UMICH) | ||
17 | * lots of work on the card... | ||
18 | * | ||
19 | * I do not have access to the (proprietary) SDK that goes with the card. | ||
20 | * If you do, I don't want to know about it, and you can probably write | ||
21 | * a better driver yourself anyway. This does mean that the pieces that | ||
22 | * talk to the card are guesswork on my part, so use at your own risk! | ||
23 | * | ||
24 | * This is my first try at writing Linux networking code, and is also | ||
25 | * guesswork. Again, use at your own risk! (Although on this part, I'd | ||
26 | * welcome suggestions) | ||
27 | * | ||
28 | * This is a loadable kernel module which seems to work at my site | ||
29 | * consisting of a 1.2.13 linux box running netatalk 1.3.3, and with | ||
30 | * the kernel support from 1.3.3b2 including patches routing.patch | ||
31 | * and ddp.disappears.from.chooser. In order to run it, you will need | ||
32 | * to patch ddp.c and aarp.c in the kernel, but only a little... | ||
33 | * | ||
34 | * I'm fairly confident that while this is arguably badly written, the | ||
35 | * problems that people experience will be "higher level", that is, with | ||
36 | * complications in the netatalk code. The driver itself doesn't do | ||
37 | * anything terribly complicated -- it pretends to be an ether device | ||
38 | * as far as netatalk is concerned, strips the DDP data out of the ether | ||
39 | * frame and builds a LLAP packet to send out the card. In the other | ||
40 | * direction, it receives LLAP frames from the card and builds a fake | ||
41 | * ether packet that it then tosses up to the networking code. You can | ||
42 | * argue (correctly) that this is an ugly way to do things, but it | ||
43 | * requires a minimal amount of fooling with the code in ddp.c and aarp.c. | ||
44 | * | ||
45 | * The card will do a lot more than is used here -- I *think* it has the | ||
46 | * layers up through ATP. Even if you knew how that part works (which I | ||
47 | * don't) it would be a big job to carve up the kernel ddp code to insert | ||
48 | * things at a higher level, and probably a bad idea... | ||
49 | * | ||
50 | * There are a number of other cards that do LocalTalk on the PC. If | ||
51 | * nobody finds any insurmountable (at the netatalk level) problems | ||
52 | * here, this driver should encourage people to put some work into the | ||
53 | * other cards (some of which I gather are still commercially available) | ||
54 | * and also to put hooks for LocalTalk into the official ddp code. | ||
55 | * | ||
56 | * I welcome comments and suggestions. This is my first try at Linux | ||
57 | * networking stuff, and there are probably lots of things that I did | ||
58 | * suboptimally. | ||
59 | * | ||
60 | ***/ | ||
61 | |||
62 | /*** | ||
63 | * | ||
64 | * $Log: ltpc.c,v $ | ||
65 | * Revision 1.1.2.1 2000/03/01 05:35:07 jgarzik | ||
66 | * at and tr cleanup | ||
67 | * | ||
68 | * Revision 1.8 1997/01/28 05:44:54 bradford | ||
69 | * Clean up for non-module a little. | ||
70 | * Hacked about a bit to clean things up - Alan Cox | ||
71 | * Probably broken it from the origina 1.8 | ||
72 | * | ||
73 | |||
74 | * 1998/11/09: David Huggins-Daines <dhd@debian.org> | ||
75 | * Cleaned up the initialization code to use the standard autoirq methods, | ||
76 | and to probe for things in the standard order of i/o, irq, dma. This | ||
77 | removes the "reset the reset" hack, because I couldn't figure out an | ||
78 | easy way to get the card to trigger an interrupt after it. | ||
79 | * Added support for passing configuration parameters on the kernel command | ||
80 | line and through insmod | ||
81 | * Changed the device name from "ltalk0" to "lt0", both to conform with the | ||
82 | other localtalk driver, and to clear up the inconsistency between the | ||
83 | module and the non-module versions of the driver :-) | ||
84 | * Added a bunch of comments (I was going to make some enums for the state | ||
85 | codes and the register offsets, but I'm still not sure exactly what their | ||
86 | semantics are) | ||
87 | * Don't poll anymore in interrupt-driven mode | ||
88 | * It seems to work as a module now (as of 2.1.127), but I don't think | ||
89 | I'm responsible for that... | ||
90 | |||
91 | * | ||
92 | * Revision 1.7 1996/12/12 03:42:33 bradford | ||
93 | * DMA alloc cribbed from 3c505.c. | ||
94 | * | ||
95 | * Revision 1.6 1996/12/12 03:18:58 bradford | ||
96 | * Added virt_to_bus; works in 2.1.13. | ||
97 | * | ||
98 | * Revision 1.5 1996/12/12 03:13:22 root | ||
99 | * xmitQel initialization -- think through better though. | ||
100 | * | ||
101 | * Revision 1.4 1996/06/18 14:55:55 root | ||
102 | * Change names to ltpc. Tabs. Took a shot at dma alloc, | ||
103 | * although more needs to be done eventually. | ||
104 | * | ||
105 | * Revision 1.3 1996/05/22 14:59:39 root | ||
106 | * Change dev->open, dev->close to track dummy.c in 1.99.(around 7) | ||
107 | * | ||
108 | * Revision 1.2 1996/05/22 14:58:24 root | ||
109 | * Change tabs mostly. | ||
110 | * | ||
111 | * Revision 1.1 1996/04/23 04:45:09 root | ||
112 | * Initial revision | ||
113 | * | ||
114 | * Revision 0.16 1996/03/05 15:59:56 root | ||
115 | * Change ARPHRD_LOCALTLK definition to the "real" one. | ||
116 | * | ||
117 | * Revision 0.15 1996/03/05 06:28:30 root | ||
118 | * Changes for kernel 1.3.70. Still need a few patches to kernel, but | ||
119 | * it's getting closer. | ||
120 | * | ||
121 | * Revision 0.14 1996/02/25 17:38:32 root | ||
122 | * More cleanups. Removed query to card on get_stats. | ||
123 | * | ||
124 | * Revision 0.13 1996/02/21 16:27:40 root | ||
125 | * Refix debug_print_skb. Fix mac.raw gotcha that appeared in 1.3.65. | ||
126 | * Clean up receive code a little. | ||
127 | * | ||
128 | * Revision 0.12 1996/02/19 16:34:53 root | ||
129 | * Fix debug_print_skb. Kludge outgoing snet to 0 when using startup | ||
130 | * range. Change debug to mask: 1 for verbose, 2 for higher level stuff | ||
131 | * including packet printing, 4 for lower level (card i/o) stuff. | ||
132 | * | ||
133 | * Revision 0.11 1996/02/12 15:53:38 root | ||
134 | * Added router sends (requires new aarp.c patch) | ||
135 | * | ||
136 | * Revision 0.10 1996/02/11 00:19:35 root | ||
137 | * Change source LTALK_LOGGING debug switch to insmod ... debug=2. | ||
138 | * | ||
139 | * Revision 0.9 1996/02/10 23:59:35 root | ||
140 | * Fixed those fixes for 1.2 -- DANGER! The at.h that comes with netatalk | ||
141 | * has a *different* definition of struct sockaddr_at than the Linux kernel | ||
142 | * does. This is an "insidious and invidious" bug... | ||
143 | * (Actually the preceding comment is false -- it's the atalk.h in the | ||
144 | * ancient atalk-0.06 that's the problem) | ||
145 | * | ||
146 | * Revision 0.8 1996/02/10 19:09:00 root | ||
147 | * Merge 1.3 changes. Tested OK under 1.3.60. | ||
148 | * | ||
149 | * Revision 0.7 1996/02/10 17:56:56 root | ||
150 | * Added debug=1 parameter on insmod for debugging prints. Tried | ||
151 | * to fix timer unload on rmmod, but I don't think that's the problem. | ||
152 | * | ||
153 | * Revision 0.6 1995/12/31 19:01:09 root | ||
154 | * Clean up rmmod, irq comments per feedback from Corin Anderson (Thanks Corey!) | ||
155 | * Clean up initial probing -- sometimes the card wakes up latched in reset. | ||
156 | * | ||
157 | * Revision 0.5 1995/12/22 06:03:44 root | ||
158 | * Added comments in front and cleaned up a bit. | ||
159 | * This version sent out to people. | ||
160 | * | ||
161 | * Revision 0.4 1995/12/18 03:46:44 root | ||
162 | * Return shortDDP to longDDP fake to 0/0. Added command structs. | ||
163 | * | ||
164 | ***/ | ||
165 | |||
166 | /* ltpc jumpers are: | ||
167 | * | ||
168 | * Interrupts -- set at most one. If none are set, the driver uses | ||
169 | * polled mode. Because the card was developed in the XT era, the | ||
170 | * original documentation refers to IRQ2. Since you'll be running | ||
171 | * this on an AT (or later) class machine, that really means IRQ9. | ||
172 | * | ||
173 | * SW1 IRQ 4 | ||
174 | * SW2 IRQ 3 | ||
175 | * SW3 IRQ 9 (2 in original card documentation only applies to XT) | ||
176 | * | ||
177 | * | ||
178 | * DMA -- choose DMA 1 or 3, and set both corresponding switches. | ||
179 | * | ||
180 | * SW4 DMA 3 | ||
181 | * SW5 DMA 1 | ||
182 | * SW6 DMA 3 | ||
183 | * SW7 DMA 1 | ||
184 | * | ||
185 | * | ||
186 | * I/O address -- choose one. | ||
187 | * | ||
188 | * SW8 220 / 240 | ||
189 | */ | ||
190 | |||
191 | /* To have some stuff logged, do | ||
192 | * insmod ltpc.o debug=1 | ||
193 | * | ||
194 | * For a whole bunch of stuff, use higher numbers. | ||
195 | * | ||
196 | * The default is 0, i.e. no messages except for the probe results. | ||
197 | */ | ||
198 | |||
199 | /* insmod-tweakable variables */ | ||
200 | static int debug; | ||
201 | #define DEBUG_VERBOSE 1 | ||
202 | #define DEBUG_UPPER 2 | ||
203 | #define DEBUG_LOWER 4 | ||
204 | |||
205 | static int io; | ||
206 | static int irq; | ||
207 | static int dma; | ||
208 | |||
209 | #include <linux/module.h> | ||
210 | #include <linux/kernel.h> | ||
211 | #include <linux/types.h> | ||
212 | #include <linux/fcntl.h> | ||
213 | #include <linux/interrupt.h> | ||
214 | #include <linux/ptrace.h> | ||
215 | #include <linux/ioport.h> | ||
216 | #include <linux/spinlock.h> | ||
217 | #include <linux/in.h> | ||
218 | #include <linux/string.h> | ||
219 | #include <linux/errno.h> | ||
220 | #include <linux/init.h> | ||
221 | #include <linux/netdevice.h> | ||
222 | #include <linux/etherdevice.h> | ||
223 | #include <linux/skbuff.h> | ||
224 | #include <linux/if_arp.h> | ||
225 | #include <linux/if_ltalk.h> | ||
226 | #include <linux/delay.h> | ||
227 | #include <linux/timer.h> | ||
228 | #include <linux/bitops.h> | ||
229 | #include <linux/gfp.h> | ||
230 | |||
231 | #include <asm/system.h> | ||
232 | #include <asm/dma.h> | ||
233 | #include <asm/io.h> | ||
234 | |||
235 | /* our stuff */ | ||
236 | #include "atalk.h" | ||
237 | #include "ltpc.h" | ||
238 | |||
239 | static DEFINE_SPINLOCK(txqueue_lock); | ||
240 | static DEFINE_SPINLOCK(mbox_lock); | ||
241 | |||
242 | /* function prototypes */ | ||
243 | static int do_read(struct net_device *dev, void *cbuf, int cbuflen, | ||
244 | void *dbuf, int dbuflen); | ||
245 | static int sendup_buffer (struct net_device *dev); | ||
246 | |||
247 | /* Dma Memory related stuff, cribbed directly from 3c505.c */ | ||
248 | |||
249 | static unsigned long dma_mem_alloc(int size) | ||
250 | { | ||
251 | int order = get_order(size); | ||
252 | |||
253 | return __get_dma_pages(GFP_KERNEL, order); | ||
254 | } | ||
255 | |||
256 | /* DMA data buffer, DMA command buffer */ | ||
257 | static unsigned char *ltdmabuf; | ||
258 | static unsigned char *ltdmacbuf; | ||
259 | |||
260 | /* private struct, holds our appletalk address */ | ||
261 | |||
262 | struct ltpc_private | ||
263 | { | ||
264 | struct atalk_addr my_addr; | ||
265 | }; | ||
266 | |||
267 | /* transmit queue element struct */ | ||
268 | |||
269 | struct xmitQel { | ||
270 | struct xmitQel *next; | ||
271 | /* command buffer */ | ||
272 | unsigned char *cbuf; | ||
273 | short cbuflen; | ||
274 | /* data buffer */ | ||
275 | unsigned char *dbuf; | ||
276 | short dbuflen; | ||
277 | unsigned char QWrite; /* read or write data */ | ||
278 | unsigned char mailbox; | ||
279 | }; | ||
280 | |||
281 | /* the transmit queue itself */ | ||
282 | |||
283 | static struct xmitQel *xmQhd, *xmQtl; | ||
284 | |||
285 | static void enQ(struct xmitQel *qel) | ||
286 | { | ||
287 | unsigned long flags; | ||
288 | qel->next = NULL; | ||
289 | |||
290 | spin_lock_irqsave(&txqueue_lock, flags); | ||
291 | if (xmQtl) { | ||
292 | xmQtl->next = qel; | ||
293 | } else { | ||
294 | xmQhd = qel; | ||
295 | } | ||
296 | xmQtl = qel; | ||
297 | spin_unlock_irqrestore(&txqueue_lock, flags); | ||
298 | |||
299 | if (debug & DEBUG_LOWER) | ||
300 | printk("enqueued a 0x%02x command\n",qel->cbuf[0]); | ||
301 | } | ||
302 | |||
303 | static struct xmitQel *deQ(void) | ||
304 | { | ||
305 | unsigned long flags; | ||
306 | int i; | ||
307 | struct xmitQel *qel=NULL; | ||
308 | |||
309 | spin_lock_irqsave(&txqueue_lock, flags); | ||
310 | if (xmQhd) { | ||
311 | qel = xmQhd; | ||
312 | xmQhd = qel->next; | ||
313 | if(!xmQhd) xmQtl = NULL; | ||
314 | } | ||
315 | spin_unlock_irqrestore(&txqueue_lock, flags); | ||
316 | |||
317 | if ((debug & DEBUG_LOWER) && qel) { | ||
318 | int n; | ||
319 | printk(KERN_DEBUG "ltpc: dequeued command "); | ||
320 | n = qel->cbuflen; | ||
321 | if (n>100) n=100; | ||
322 | for(i=0;i<n;i++) printk("%02x ",qel->cbuf[i]); | ||
323 | printk("\n"); | ||
324 | } | ||
325 | |||
326 | return qel; | ||
327 | } | ||
328 | |||
329 | /* and... the queue elements we'll be using */ | ||
330 | static struct xmitQel qels[16]; | ||
331 | |||
332 | /* and their corresponding mailboxes */ | ||
333 | static unsigned char mailbox[16]; | ||
334 | static unsigned char mboxinuse[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | ||
335 | |||
336 | static int wait_timeout(struct net_device *dev, int c) | ||
337 | { | ||
338 | /* returns true if it stayed c */ | ||
339 | /* this uses base+6, but it's ok */ | ||
340 | int i; | ||
341 | |||
342 | /* twenty second or so total */ | ||
343 | |||
344 | for(i=0;i<200000;i++) { | ||
345 | if ( c != inb_p(dev->base_addr+6) ) return 0; | ||
346 | udelay(100); | ||
347 | } | ||
348 | return 1; /* timed out */ | ||
349 | } | ||
350 | |||
351 | /* get the first free mailbox */ | ||
352 | |||
353 | static int getmbox(void) | ||
354 | { | ||
355 | unsigned long flags; | ||
356 | int i; | ||
357 | |||
358 | spin_lock_irqsave(&mbox_lock, flags); | ||
359 | for(i=1;i<16;i++) if(!mboxinuse[i]) { | ||
360 | mboxinuse[i]=1; | ||
361 | spin_unlock_irqrestore(&mbox_lock, flags); | ||
362 | return i; | ||
363 | } | ||
364 | spin_unlock_irqrestore(&mbox_lock, flags); | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | /* read a command from the card */ | ||
369 | static void handlefc(struct net_device *dev) | ||
370 | { | ||
371 | /* called *only* from idle, non-reentrant */ | ||
372 | int dma = dev->dma; | ||
373 | int base = dev->base_addr; | ||
374 | unsigned long flags; | ||
375 | |||
376 | |||
377 | flags=claim_dma_lock(); | ||
378 | disable_dma(dma); | ||
379 | clear_dma_ff(dma); | ||
380 | set_dma_mode(dma,DMA_MODE_READ); | ||
381 | set_dma_addr(dma,virt_to_bus(ltdmacbuf)); | ||
382 | set_dma_count(dma,50); | ||
383 | enable_dma(dma); | ||
384 | release_dma_lock(flags); | ||
385 | |||
386 | inb_p(base+3); | ||
387 | inb_p(base+2); | ||
388 | |||
389 | if ( wait_timeout(dev,0xfc) ) printk("timed out in handlefc\n"); | ||
390 | } | ||
391 | |||
392 | /* read data from the card */ | ||
393 | static void handlefd(struct net_device *dev) | ||
394 | { | ||
395 | int dma = dev->dma; | ||
396 | int base = dev->base_addr; | ||
397 | unsigned long flags; | ||
398 | |||
399 | flags=claim_dma_lock(); | ||
400 | disable_dma(dma); | ||
401 | clear_dma_ff(dma); | ||
402 | set_dma_mode(dma,DMA_MODE_READ); | ||
403 | set_dma_addr(dma,virt_to_bus(ltdmabuf)); | ||
404 | set_dma_count(dma,800); | ||
405 | enable_dma(dma); | ||
406 | release_dma_lock(flags); | ||
407 | |||
408 | inb_p(base+3); | ||
409 | inb_p(base+2); | ||
410 | |||
411 | if ( wait_timeout(dev,0xfd) ) printk("timed out in handlefd\n"); | ||
412 | sendup_buffer(dev); | ||
413 | } | ||
414 | |||
415 | static void handlewrite(struct net_device *dev) | ||
416 | { | ||
417 | /* called *only* from idle, non-reentrant */ | ||
418 | /* on entry, 0xfb and ltdmabuf holds data */ | ||
419 | int dma = dev->dma; | ||
420 | int base = dev->base_addr; | ||
421 | unsigned long flags; | ||
422 | |||
423 | flags=claim_dma_lock(); | ||
424 | disable_dma(dma); | ||
425 | clear_dma_ff(dma); | ||
426 | set_dma_mode(dma,DMA_MODE_WRITE); | ||
427 | set_dma_addr(dma,virt_to_bus(ltdmabuf)); | ||
428 | set_dma_count(dma,800); | ||
429 | enable_dma(dma); | ||
430 | release_dma_lock(flags); | ||
431 | |||
432 | inb_p(base+3); | ||
433 | inb_p(base+2); | ||
434 | |||
435 | if ( wait_timeout(dev,0xfb) ) { | ||
436 | flags=claim_dma_lock(); | ||
437 | printk("timed out in handlewrite, dma res %d\n", | ||
438 | get_dma_residue(dev->dma) ); | ||
439 | release_dma_lock(flags); | ||
440 | } | ||
441 | } | ||
442 | |||
443 | static void handleread(struct net_device *dev) | ||
444 | { | ||
445 | /* on entry, 0xfb */ | ||
446 | /* on exit, ltdmabuf holds data */ | ||
447 | int dma = dev->dma; | ||
448 | int base = dev->base_addr; | ||
449 | unsigned long flags; | ||
450 | |||
451 | |||
452 | flags=claim_dma_lock(); | ||
453 | disable_dma(dma); | ||
454 | clear_dma_ff(dma); | ||
455 | set_dma_mode(dma,DMA_MODE_READ); | ||
456 | set_dma_addr(dma,virt_to_bus(ltdmabuf)); | ||
457 | set_dma_count(dma,800); | ||
458 | enable_dma(dma); | ||
459 | release_dma_lock(flags); | ||
460 | |||
461 | inb_p(base+3); | ||
462 | inb_p(base+2); | ||
463 | if ( wait_timeout(dev,0xfb) ) printk("timed out in handleread\n"); | ||
464 | } | ||
465 | |||
466 | static void handlecommand(struct net_device *dev) | ||
467 | { | ||
468 | /* on entry, 0xfa and ltdmacbuf holds command */ | ||
469 | int dma = dev->dma; | ||
470 | int base = dev->base_addr; | ||
471 | unsigned long flags; | ||
472 | |||
473 | flags=claim_dma_lock(); | ||
474 | disable_dma(dma); | ||
475 | clear_dma_ff(dma); | ||
476 | set_dma_mode(dma,DMA_MODE_WRITE); | ||
477 | set_dma_addr(dma,virt_to_bus(ltdmacbuf)); | ||
478 | set_dma_count(dma,50); | ||
479 | enable_dma(dma); | ||
480 | release_dma_lock(flags); | ||
481 | inb_p(base+3); | ||
482 | inb_p(base+2); | ||
483 | if ( wait_timeout(dev,0xfa) ) printk("timed out in handlecommand\n"); | ||
484 | } | ||
485 | |||
486 | /* ready made command for getting the result from the card */ | ||
487 | static unsigned char rescbuf[2] = {LT_GETRESULT,0}; | ||
488 | static unsigned char resdbuf[2]; | ||
489 | |||
490 | static int QInIdle; | ||
491 | |||
492 | /* idle expects to be called with the IRQ line high -- either because of | ||
493 | * an interrupt, or because the line is tri-stated | ||
494 | */ | ||
495 | |||
496 | static void idle(struct net_device *dev) | ||
497 | { | ||
498 | unsigned long flags; | ||
499 | int state; | ||
500 | /* FIXME This is initialized to shut the warning up, but I need to | ||
501 | * think this through again. | ||
502 | */ | ||
503 | struct xmitQel *q = NULL; | ||
504 | int oops; | ||
505 | int i; | ||
506 | int base = dev->base_addr; | ||
507 | |||
508 | spin_lock_irqsave(&txqueue_lock, flags); | ||
509 | if(QInIdle) { | ||
510 | spin_unlock_irqrestore(&txqueue_lock, flags); | ||
511 | return; | ||
512 | } | ||
513 | QInIdle = 1; | ||
514 | spin_unlock_irqrestore(&txqueue_lock, flags); | ||
515 | |||
516 | /* this tri-states the IRQ line */ | ||
517 | (void) inb_p(base+6); | ||
518 | |||
519 | oops = 100; | ||
520 | |||
521 | loop: | ||
522 | if (0>oops--) { | ||
523 | printk("idle: looped too many times\n"); | ||
524 | goto done; | ||
525 | } | ||
526 | |||
527 | state = inb_p(base+6); | ||
528 | if (state != inb_p(base+6)) goto loop; | ||
529 | |||
530 | switch(state) { | ||
531 | case 0xfc: | ||
532 | /* incoming command */ | ||
533 | if (debug & DEBUG_LOWER) printk("idle: fc\n"); | ||
534 | handlefc(dev); | ||
535 | break; | ||
536 | case 0xfd: | ||
537 | /* incoming data */ | ||
538 | if(debug & DEBUG_LOWER) printk("idle: fd\n"); | ||
539 | handlefd(dev); | ||
540 | break; | ||
541 | case 0xf9: | ||
542 | /* result ready */ | ||
543 | if (debug & DEBUG_LOWER) printk("idle: f9\n"); | ||
544 | if(!mboxinuse[0]) { | ||
545 | mboxinuse[0] = 1; | ||
546 | qels[0].cbuf = rescbuf; | ||
547 | qels[0].cbuflen = 2; | ||
548 | qels[0].dbuf = resdbuf; | ||
549 | qels[0].dbuflen = 2; | ||
550 | qels[0].QWrite = 0; | ||
551 | qels[0].mailbox = 0; | ||
552 | enQ(&qels[0]); | ||
553 | } | ||
554 | inb_p(dev->base_addr+1); | ||
555 | inb_p(dev->base_addr+0); | ||
556 | if( wait_timeout(dev,0xf9) ) | ||
557 | printk("timed out idle f9\n"); | ||
558 | break; | ||
559 | case 0xf8: | ||
560 | /* ?? */ | ||
561 | if (xmQhd) { | ||
562 | inb_p(dev->base_addr+1); | ||
563 | inb_p(dev->base_addr+0); | ||
564 | if(wait_timeout(dev,0xf8) ) | ||
565 | printk("timed out idle f8\n"); | ||
566 | } else { | ||
567 | goto done; | ||
568 | } | ||
569 | break; | ||
570 | case 0xfa: | ||
571 | /* waiting for command */ | ||
572 | if(debug & DEBUG_LOWER) printk("idle: fa\n"); | ||
573 | if (xmQhd) { | ||
574 | q=deQ(); | ||
575 | memcpy(ltdmacbuf,q->cbuf,q->cbuflen); | ||
576 | ltdmacbuf[1] = q->mailbox; | ||
577 | if (debug>1) { | ||
578 | int n; | ||
579 | printk("ltpc: sent command "); | ||
580 | n = q->cbuflen; | ||
581 | if (n>100) n=100; | ||
582 | for(i=0;i<n;i++) | ||
583 | printk("%02x ",ltdmacbuf[i]); | ||
584 | printk("\n"); | ||
585 | } | ||
586 | handlecommand(dev); | ||
587 | if(0xfa==inb_p(base+6)) { | ||
588 | /* we timed out, so return */ | ||
589 | goto done; | ||
590 | } | ||
591 | } else { | ||
592 | /* we don't seem to have a command */ | ||
593 | if (!mboxinuse[0]) { | ||
594 | mboxinuse[0] = 1; | ||
595 | qels[0].cbuf = rescbuf; | ||
596 | qels[0].cbuflen = 2; | ||
597 | qels[0].dbuf = resdbuf; | ||
598 | qels[0].dbuflen = 2; | ||
599 | qels[0].QWrite = 0; | ||
600 | qels[0].mailbox = 0; | ||
601 | enQ(&qels[0]); | ||
602 | } else { | ||
603 | printk("trouble: response command already queued\n"); | ||
604 | goto done; | ||
605 | } | ||
606 | } | ||
607 | break; | ||
608 | case 0Xfb: | ||
609 | /* data transfer ready */ | ||
610 | if(debug & DEBUG_LOWER) printk("idle: fb\n"); | ||
611 | if(q->QWrite) { | ||
612 | memcpy(ltdmabuf,q->dbuf,q->dbuflen); | ||
613 | handlewrite(dev); | ||
614 | } else { | ||
615 | handleread(dev); | ||
616 | /* non-zero mailbox numbers are for | ||
617 | commmands, 0 is for GETRESULT | ||
618 | requests */ | ||
619 | if(q->mailbox) { | ||
620 | memcpy(q->dbuf,ltdmabuf,q->dbuflen); | ||
621 | } else { | ||
622 | /* this was a result */ | ||
623 | mailbox[ 0x0f & ltdmabuf[0] ] = ltdmabuf[1]; | ||
624 | mboxinuse[0]=0; | ||
625 | } | ||
626 | } | ||
627 | break; | ||
628 | } | ||
629 | goto loop; | ||
630 | |||
631 | done: | ||
632 | QInIdle=0; | ||
633 | |||
634 | /* now set the interrupts back as appropriate */ | ||
635 | /* the first read takes it out of tri-state (but still high) */ | ||
636 | /* the second resets it */ | ||
637 | /* note that after this point, any read of base+6 will | ||
638 | trigger an interrupt */ | ||
639 | |||
640 | if (dev->irq) { | ||
641 | inb_p(base+7); | ||
642 | inb_p(base+7); | ||
643 | } | ||
644 | } | ||
645 | |||
646 | |||
647 | static int do_write(struct net_device *dev, void *cbuf, int cbuflen, | ||
648 | void *dbuf, int dbuflen) | ||
649 | { | ||
650 | |||
651 | int i = getmbox(); | ||
652 | int ret; | ||
653 | |||
654 | if(i) { | ||
655 | qels[i].cbuf = (unsigned char *) cbuf; | ||
656 | qels[i].cbuflen = cbuflen; | ||
657 | qels[i].dbuf = (unsigned char *) dbuf; | ||
658 | qels[i].dbuflen = dbuflen; | ||
659 | qels[i].QWrite = 1; | ||
660 | qels[i].mailbox = i; /* this should be initted rather */ | ||
661 | enQ(&qels[i]); | ||
662 | idle(dev); | ||
663 | ret = mailbox[i]; | ||
664 | mboxinuse[i]=0; | ||
665 | return ret; | ||
666 | } | ||
667 | printk("ltpc: could not allocate mbox\n"); | ||
668 | return -1; | ||
669 | } | ||
670 | |||
671 | static int do_read(struct net_device *dev, void *cbuf, int cbuflen, | ||
672 | void *dbuf, int dbuflen) | ||
673 | { | ||
674 | |||
675 | int i = getmbox(); | ||
676 | int ret; | ||
677 | |||
678 | if(i) { | ||
679 | qels[i].cbuf = (unsigned char *) cbuf; | ||
680 | qels[i].cbuflen = cbuflen; | ||
681 | qels[i].dbuf = (unsigned char *) dbuf; | ||
682 | qels[i].dbuflen = dbuflen; | ||
683 | qels[i].QWrite = 0; | ||
684 | qels[i].mailbox = i; /* this should be initted rather */ | ||
685 | enQ(&qels[i]); | ||
686 | idle(dev); | ||
687 | ret = mailbox[i]; | ||
688 | mboxinuse[i]=0; | ||
689 | return ret; | ||
690 | } | ||
691 | printk("ltpc: could not allocate mbox\n"); | ||
692 | return -1; | ||
693 | } | ||
694 | |||
695 | /* end of idle handlers -- what should be seen is do_read, do_write */ | ||
696 | |||
697 | static struct timer_list ltpc_timer; | ||
698 | |||
699 | static netdev_tx_t ltpc_xmit(struct sk_buff *skb, struct net_device *dev); | ||
700 | |||
701 | static int read_30 ( struct net_device *dev) | ||
702 | { | ||
703 | lt_command c; | ||
704 | c.getflags.command = LT_GETFLAGS; | ||
705 | return do_read(dev, &c, sizeof(c.getflags),&c,0); | ||
706 | } | ||
707 | |||
708 | static int set_30 (struct net_device *dev,int x) | ||
709 | { | ||
710 | lt_command c; | ||
711 | c.setflags.command = LT_SETFLAGS; | ||
712 | c.setflags.flags = x; | ||
713 | return do_write(dev, &c, sizeof(c.setflags),&c,0); | ||
714 | } | ||
715 | |||
716 | /* LLAP to DDP translation */ | ||
717 | |||
718 | static int sendup_buffer (struct net_device *dev) | ||
719 | { | ||
720 | /* on entry, command is in ltdmacbuf, data in ltdmabuf */ | ||
721 | /* called from idle, non-reentrant */ | ||
722 | |||
723 | int dnode, snode, llaptype, len; | ||
724 | int sklen; | ||
725 | struct sk_buff *skb; | ||
726 | struct lt_rcvlap *ltc = (struct lt_rcvlap *) ltdmacbuf; | ||
727 | |||
728 | if (ltc->command != LT_RCVLAP) { | ||
729 | printk("unknown command 0x%02x from ltpc card\n",ltc->command); | ||
730 | return -1; | ||
731 | } | ||
732 | dnode = ltc->dnode; | ||
733 | snode = ltc->snode; | ||
734 | llaptype = ltc->laptype; | ||
735 | len = ltc->length; | ||
736 | |||
737 | sklen = len; | ||
738 | if (llaptype == 1) | ||
739 | sklen += 8; /* correct for short ddp */ | ||
740 | if(sklen > 800) { | ||
741 | printk(KERN_INFO "%s: nonsense length in ltpc command 0x14: 0x%08x\n", | ||
742 | dev->name,sklen); | ||
743 | return -1; | ||
744 | } | ||
745 | |||
746 | if ( (llaptype==0) || (llaptype>2) ) { | ||
747 | printk(KERN_INFO "%s: unknown LLAP type: %d\n",dev->name,llaptype); | ||
748 | return -1; | ||
749 | } | ||
750 | |||
751 | |||
752 | skb = dev_alloc_skb(3+sklen); | ||
753 | if (skb == NULL) | ||
754 | { | ||
755 | printk("%s: dropping packet due to memory squeeze.\n", | ||
756 | dev->name); | ||
757 | return -1; | ||
758 | } | ||
759 | skb->dev = dev; | ||
760 | |||
761 | if (sklen > len) | ||
762 | skb_reserve(skb,8); | ||
763 | skb_put(skb,len+3); | ||
764 | skb->protocol = htons(ETH_P_LOCALTALK); | ||
765 | /* add LLAP header */ | ||
766 | skb->data[0] = dnode; | ||
767 | skb->data[1] = snode; | ||
768 | skb->data[2] = llaptype; | ||
769 | skb_reset_mac_header(skb); /* save pointer to llap header */ | ||
770 | skb_pull(skb,3); | ||
771 | |||
772 | /* copy ddp(s,e)hdr + contents */ | ||
773 | skb_copy_to_linear_data(skb, ltdmabuf, len); | ||
774 | |||
775 | skb_reset_transport_header(skb); | ||
776 | |||
777 | dev->stats.rx_packets++; | ||
778 | dev->stats.rx_bytes += skb->len; | ||
779 | |||
780 | /* toss it onwards */ | ||
781 | netif_rx(skb); | ||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | /* the handler for the board interrupt */ | ||
786 | |||
787 | static irqreturn_t | ||
788 | ltpc_interrupt(int irq, void *dev_id) | ||
789 | { | ||
790 | struct net_device *dev = dev_id; | ||
791 | |||
792 | if (dev==NULL) { | ||
793 | printk("ltpc_interrupt: unknown device.\n"); | ||
794 | return IRQ_NONE; | ||
795 | } | ||
796 | |||
797 | inb_p(dev->base_addr+6); /* disable further interrupts from board */ | ||
798 | |||
799 | idle(dev); /* handle whatever is coming in */ | ||
800 | |||
801 | /* idle re-enables interrupts from board */ | ||
802 | |||
803 | return IRQ_HANDLED; | ||
804 | } | ||
805 | |||
806 | /*** | ||
807 | * | ||
808 | * The ioctls that the driver responds to are: | ||
809 | * | ||
810 | * SIOCSIFADDR -- do probe using the passed node hint. | ||
811 | * SIOCGIFADDR -- return net, node. | ||
812 | * | ||
813 | * some of this stuff should be done elsewhere. | ||
814 | * | ||
815 | ***/ | ||
816 | |||
817 | static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | ||
818 | { | ||
819 | struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr; | ||
820 | /* we'll keep the localtalk node address in dev->pa_addr */ | ||
821 | struct ltpc_private *ltpc_priv = netdev_priv(dev); | ||
822 | struct atalk_addr *aa = <pc_priv->my_addr; | ||
823 | struct lt_init c; | ||
824 | int ltflags; | ||
825 | |||
826 | if(debug & DEBUG_VERBOSE) printk("ltpc_ioctl called\n"); | ||
827 | |||
828 | switch(cmd) { | ||
829 | case SIOCSIFADDR: | ||
830 | |||
831 | aa->s_net = sa->sat_addr.s_net; | ||
832 | |||
833 | /* this does the probe and returns the node addr */ | ||
834 | c.command = LT_INIT; | ||
835 | c.hint = sa->sat_addr.s_node; | ||
836 | |||
837 | aa->s_node = do_read(dev,&c,sizeof(c),&c,0); | ||
838 | |||
839 | /* get all llap frames raw */ | ||
840 | ltflags = read_30(dev); | ||
841 | ltflags |= LT_FLAG_ALLLAP; | ||
842 | set_30 (dev,ltflags); | ||
843 | |||
844 | dev->broadcast[0] = 0xFF; | ||
845 | dev->dev_addr[0] = aa->s_node; | ||
846 | |||
847 | dev->addr_len=1; | ||
848 | |||
849 | return 0; | ||
850 | |||
851 | case SIOCGIFADDR: | ||
852 | |||
853 | sa->sat_addr.s_net = aa->s_net; | ||
854 | sa->sat_addr.s_node = aa->s_node; | ||
855 | |||
856 | return 0; | ||
857 | |||
858 | default: | ||
859 | return -EINVAL; | ||
860 | } | ||
861 | } | ||
862 | |||
863 | static void set_multicast_list(struct net_device *dev) | ||
864 | { | ||
865 | /* This needs to be present to keep netatalk happy. */ | ||
866 | /* Actually netatalk needs fixing! */ | ||
867 | } | ||
868 | |||
869 | static int ltpc_poll_counter; | ||
870 | |||
871 | static void ltpc_poll(unsigned long l) | ||
872 | { | ||
873 | struct net_device *dev = (struct net_device *) l; | ||
874 | |||
875 | del_timer(<pc_timer); | ||
876 | |||
877 | if(debug & DEBUG_VERBOSE) { | ||
878 | if (!ltpc_poll_counter) { | ||
879 | ltpc_poll_counter = 50; | ||
880 | printk("ltpc poll is alive\n"); | ||
881 | } | ||
882 | ltpc_poll_counter--; | ||
883 | } | ||
884 | |||
885 | if (!dev) | ||
886 | return; /* we've been downed */ | ||
887 | |||
888 | /* poll 20 times per second */ | ||
889 | idle(dev); | ||
890 | ltpc_timer.expires = jiffies + HZ/20; | ||
891 | |||
892 | add_timer(<pc_timer); | ||
893 | } | ||
894 | |||
895 | /* DDP to LLAP translation */ | ||
896 | |||
897 | static netdev_tx_t ltpc_xmit(struct sk_buff *skb, struct net_device *dev) | ||
898 | { | ||
899 | /* in kernel 1.3.xx, on entry skb->data points to ddp header, | ||
900 | * and skb->len is the length of the ddp data + ddp header | ||
901 | */ | ||
902 | int i; | ||
903 | struct lt_sendlap cbuf; | ||
904 | unsigned char *hdr; | ||
905 | |||
906 | cbuf.command = LT_SENDLAP; | ||
907 | cbuf.dnode = skb->data[0]; | ||
908 | cbuf.laptype = skb->data[2]; | ||
909 | skb_pull(skb,3); /* skip past LLAP header */ | ||
910 | cbuf.length = skb->len; /* this is host order */ | ||
911 | skb_reset_transport_header(skb); | ||
912 | |||
913 | if(debug & DEBUG_UPPER) { | ||
914 | printk("command "); | ||
915 | for(i=0;i<6;i++) | ||
916 | printk("%02x ",((unsigned char *)&cbuf)[i]); | ||
917 | printk("\n"); | ||
918 | } | ||
919 | |||
920 | hdr = skb_transport_header(skb); | ||
921 | do_write(dev, &cbuf, sizeof(cbuf), hdr, skb->len); | ||
922 | |||
923 | if(debug & DEBUG_UPPER) { | ||
924 | printk("sent %d ddp bytes\n",skb->len); | ||
925 | for (i = 0; i < skb->len; i++) | ||
926 | printk("%02x ", hdr[i]); | ||
927 | printk("\n"); | ||
928 | } | ||
929 | |||
930 | dev->stats.tx_packets++; | ||
931 | dev->stats.tx_bytes += skb->len; | ||
932 | |||
933 | dev_kfree_skb(skb); | ||
934 | return NETDEV_TX_OK; | ||
935 | } | ||
936 | |||
937 | /* initialization stuff */ | ||
938 | |||
939 | static int __init ltpc_probe_dma(int base, int dma) | ||
940 | { | ||
941 | int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3; | ||
942 | unsigned long timeout; | ||
943 | unsigned long f; | ||
944 | |||
945 | if (want & 1) { | ||
946 | if (request_dma(1,"ltpc")) { | ||
947 | want &= ~1; | ||
948 | } else { | ||
949 | f=claim_dma_lock(); | ||
950 | disable_dma(1); | ||
951 | clear_dma_ff(1); | ||
952 | set_dma_mode(1,DMA_MODE_WRITE); | ||
953 | set_dma_addr(1,virt_to_bus(ltdmabuf)); | ||
954 | set_dma_count(1,sizeof(struct lt_mem)); | ||
955 | enable_dma(1); | ||
956 | release_dma_lock(f); | ||
957 | } | ||
958 | } | ||
959 | if (want & 2) { | ||
960 | if (request_dma(3,"ltpc")) { | ||
961 | want &= ~2; | ||
962 | } else { | ||
963 | f=claim_dma_lock(); | ||
964 | disable_dma(3); | ||
965 | clear_dma_ff(3); | ||
966 | set_dma_mode(3,DMA_MODE_WRITE); | ||
967 | set_dma_addr(3,virt_to_bus(ltdmabuf)); | ||
968 | set_dma_count(3,sizeof(struct lt_mem)); | ||
969 | enable_dma(3); | ||
970 | release_dma_lock(f); | ||
971 | } | ||
972 | } | ||
973 | /* set up request */ | ||
974 | |||
975 | /* FIXME -- do timings better! */ | ||
976 | |||
977 | ltdmabuf[0] = LT_READMEM; | ||
978 | ltdmabuf[1] = 1; /* mailbox */ | ||
979 | ltdmabuf[2] = 0; ltdmabuf[3] = 0; /* address */ | ||
980 | ltdmabuf[4] = 0; ltdmabuf[5] = 1; /* read 0x0100 bytes */ | ||
981 | ltdmabuf[6] = 0; /* dunno if this is necessary */ | ||
982 | |||
983 | inb_p(io+1); | ||
984 | inb_p(io+0); | ||
985 | timeout = jiffies+100*HZ/100; | ||
986 | while(time_before(jiffies, timeout)) { | ||
987 | if ( 0xfa == inb_p(io+6) ) break; | ||
988 | } | ||
989 | |||
990 | inb_p(io+3); | ||
991 | inb_p(io+2); | ||
992 | while(time_before(jiffies, timeout)) { | ||
993 | if ( 0xfb == inb_p(io+6) ) break; | ||
994 | } | ||
995 | |||
996 | /* release the other dma channel (if we opened both of them) */ | ||
997 | |||
998 | if ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) { | ||
999 | want &= ~2; | ||
1000 | free_dma(3); | ||
1001 | } | ||
1002 | |||
1003 | if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) { | ||
1004 | want &= ~1; | ||
1005 | free_dma(1); | ||
1006 | } | ||
1007 | |||
1008 | if (!want) | ||
1009 | return 0; | ||
1010 | |||
1011 | return (want & 2) ? 3 : 1; | ||
1012 | } | ||
1013 | |||
1014 | static const struct net_device_ops ltpc_netdev = { | ||
1015 | .ndo_start_xmit = ltpc_xmit, | ||
1016 | .ndo_do_ioctl = ltpc_ioctl, | ||
1017 | .ndo_set_multicast_list = set_multicast_list, | ||
1018 | }; | ||
1019 | |||
1020 | struct net_device * __init ltpc_probe(void) | ||
1021 | { | ||
1022 | struct net_device *dev; | ||
1023 | int err = -ENOMEM; | ||
1024 | int x=0,y=0; | ||
1025 | int autoirq; | ||
1026 | unsigned long f; | ||
1027 | unsigned long timeout; | ||
1028 | |||
1029 | dev = alloc_ltalkdev(sizeof(struct ltpc_private)); | ||
1030 | if (!dev) | ||
1031 | goto out; | ||
1032 | |||
1033 | /* probe for the I/O port address */ | ||
1034 | |||
1035 | if (io != 0x240 && request_region(0x220,8,"ltpc")) { | ||
1036 | x = inb_p(0x220+6); | ||
1037 | if ( (x!=0xff) && (x>=0xf0) ) { | ||
1038 | io = 0x220; | ||
1039 | goto got_port; | ||
1040 | } | ||
1041 | release_region(0x220,8); | ||
1042 | } | ||
1043 | if (io != 0x220 && request_region(0x240,8,"ltpc")) { | ||
1044 | y = inb_p(0x240+6); | ||
1045 | if ( (y!=0xff) && (y>=0xf0) ){ | ||
1046 | io = 0x240; | ||
1047 | goto got_port; | ||
1048 | } | ||
1049 | release_region(0x240,8); | ||
1050 | } | ||
1051 | |||
1052 | /* give up in despair */ | ||
1053 | printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y); | ||
1054 | err = -ENODEV; | ||
1055 | goto out1; | ||
1056 | |||
1057 | got_port: | ||
1058 | /* probe for the IRQ line */ | ||
1059 | if (irq < 2) { | ||
1060 | unsigned long irq_mask; | ||
1061 | |||
1062 | irq_mask = probe_irq_on(); | ||
1063 | /* reset the interrupt line */ | ||
1064 | inb_p(io+7); | ||
1065 | inb_p(io+7); | ||
1066 | /* trigger an interrupt (I hope) */ | ||
1067 | inb_p(io+6); | ||
1068 | mdelay(2); | ||
1069 | autoirq = probe_irq_off(irq_mask); | ||
1070 | |||
1071 | if (autoirq == 0) { | ||
1072 | printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io); | ||
1073 | } else { | ||
1074 | irq = autoirq; | ||
1075 | } | ||
1076 | } | ||
1077 | |||
1078 | /* allocate a DMA buffer */ | ||
1079 | ltdmabuf = (unsigned char *) dma_mem_alloc(1000); | ||
1080 | if (!ltdmabuf) { | ||
1081 | printk(KERN_ERR "ltpc: mem alloc failed\n"); | ||
1082 | err = -ENOMEM; | ||
1083 | goto out2; | ||
1084 | } | ||
1085 | |||
1086 | ltdmacbuf = <dmabuf[800]; | ||
1087 | |||
1088 | if(debug & DEBUG_VERBOSE) { | ||
1089 | printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf); | ||
1090 | } | ||
1091 | |||
1092 | /* reset the card */ | ||
1093 | |||
1094 | inb_p(io+1); | ||
1095 | inb_p(io+3); | ||
1096 | |||
1097 | msleep(20); | ||
1098 | |||
1099 | inb_p(io+0); | ||
1100 | inb_p(io+2); | ||
1101 | inb_p(io+7); /* clear reset */ | ||
1102 | inb_p(io+4); | ||
1103 | inb_p(io+5); | ||
1104 | inb_p(io+5); /* enable dma */ | ||
1105 | inb_p(io+6); /* tri-state interrupt line */ | ||
1106 | |||
1107 | ssleep(1); | ||
1108 | |||
1109 | /* now, figure out which dma channel we're using, unless it's | ||
1110 | already been specified */ | ||
1111 | /* well, 0 is a legal DMA channel, but the LTPC card doesn't | ||
1112 | use it... */ | ||
1113 | dma = ltpc_probe_dma(io, dma); | ||
1114 | if (!dma) { /* no dma channel */ | ||
1115 | printk(KERN_ERR "No DMA channel found on ltpc card.\n"); | ||
1116 | err = -ENODEV; | ||
1117 | goto out3; | ||
1118 | } | ||
1119 | |||
1120 | /* print out friendly message */ | ||
1121 | if(irq) | ||
1122 | printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma); | ||
1123 | else | ||
1124 | printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d. Using polled mode.\n",io,dma); | ||
1125 | |||
1126 | dev->netdev_ops = <pc_netdev; | ||
1127 | dev->base_addr = io; | ||
1128 | dev->irq = irq; | ||
1129 | dev->dma = dma; | ||
1130 | |||
1131 | /* the card will want to send a result at this point */ | ||
1132 | /* (I think... leaving out this part makes the kernel crash, | ||
1133 | so I put it back in...) */ | ||
1134 | |||
1135 | f=claim_dma_lock(); | ||
1136 | disable_dma(dma); | ||
1137 | clear_dma_ff(dma); | ||
1138 | set_dma_mode(dma,DMA_MODE_READ); | ||
1139 | set_dma_addr(dma,virt_to_bus(ltdmabuf)); | ||
1140 | set_dma_count(dma,0x100); | ||
1141 | enable_dma(dma); | ||
1142 | release_dma_lock(f); | ||
1143 | |||
1144 | (void) inb_p(io+3); | ||
1145 | (void) inb_p(io+2); | ||
1146 | timeout = jiffies+100*HZ/100; | ||
1147 | |||
1148 | while(time_before(jiffies, timeout)) { | ||
1149 | if( 0xf9 == inb_p(io+6)) | ||
1150 | break; | ||
1151 | schedule(); | ||
1152 | } | ||
1153 | |||
1154 | if(debug & DEBUG_VERBOSE) { | ||
1155 | printk("setting up timer and irq\n"); | ||
1156 | } | ||
1157 | |||
1158 | /* grab it and don't let go :-) */ | ||
1159 | if (irq && request_irq( irq, ltpc_interrupt, 0, "ltpc", dev) >= 0) | ||
1160 | { | ||
1161 | (void) inb_p(io+7); /* enable interrupts from board */ | ||
1162 | (void) inb_p(io+7); /* and reset irq line */ | ||
1163 | } else { | ||
1164 | if( irq ) | ||
1165 | printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n"); | ||
1166 | dev->irq = 0; | ||
1167 | /* polled mode -- 20 times per second */ | ||
1168 | /* this is really, really slow... should it poll more often? */ | ||
1169 | init_timer(<pc_timer); | ||
1170 | ltpc_timer.function=ltpc_poll; | ||
1171 | ltpc_timer.data = (unsigned long) dev; | ||
1172 | |||
1173 | ltpc_timer.expires = jiffies + HZ/20; | ||
1174 | add_timer(<pc_timer); | ||
1175 | } | ||
1176 | err = register_netdev(dev); | ||
1177 | if (err) | ||
1178 | goto out4; | ||
1179 | |||
1180 | return NULL; | ||
1181 | out4: | ||
1182 | del_timer_sync(<pc_timer); | ||
1183 | if (dev->irq) | ||
1184 | free_irq(dev->irq, dev); | ||
1185 | out3: | ||
1186 | free_pages((unsigned long)ltdmabuf, get_order(1000)); | ||
1187 | out2: | ||
1188 | release_region(io, 8); | ||
1189 | out1: | ||
1190 | free_netdev(dev); | ||
1191 | out: | ||
1192 | return ERR_PTR(err); | ||
1193 | } | ||
1194 | |||
1195 | #ifndef MODULE | ||
1196 | /* handles "ltpc=io,irq,dma" kernel command lines */ | ||
1197 | static int __init ltpc_setup(char *str) | ||
1198 | { | ||
1199 | int ints[5]; | ||
1200 | |||
1201 | str = get_options(str, ARRAY_SIZE(ints), ints); | ||
1202 | |||
1203 | if (ints[0] == 0) { | ||
1204 | if (str && !strncmp(str, "auto", 4)) { | ||
1205 | /* do nothing :-) */ | ||
1206 | } | ||
1207 | else { | ||
1208 | /* usage message */ | ||
1209 | printk (KERN_ERR | ||
1210 | "ltpc: usage: ltpc=auto|iobase[,irq[,dma]]\n"); | ||
1211 | return 0; | ||
1212 | } | ||
1213 | } else { | ||
1214 | io = ints[1]; | ||
1215 | if (ints[0] > 1) { | ||
1216 | irq = ints[2]; | ||
1217 | } | ||
1218 | if (ints[0] > 2) { | ||
1219 | dma = ints[3]; | ||
1220 | } | ||
1221 | /* ignore any other parameters */ | ||
1222 | } | ||
1223 | return 1; | ||
1224 | } | ||
1225 | |||
1226 | __setup("ltpc=", ltpc_setup); | ||
1227 | #endif /* MODULE */ | ||
1228 | |||
1229 | static struct net_device *dev_ltpc; | ||
1230 | |||
1231 | #ifdef MODULE | ||
1232 | |||
1233 | MODULE_LICENSE("GPL"); | ||
1234 | module_param(debug, int, 0); | ||
1235 | module_param(io, int, 0); | ||
1236 | module_param(irq, int, 0); | ||
1237 | module_param(dma, int, 0); | ||
1238 | |||
1239 | |||
1240 | static int __init ltpc_module_init(void) | ||
1241 | { | ||
1242 | if(io == 0) | ||
1243 | printk(KERN_NOTICE | ||
1244 | "ltpc: Autoprobing is not recommended for modules\n"); | ||
1245 | |||
1246 | dev_ltpc = ltpc_probe(); | ||
1247 | if (IS_ERR(dev_ltpc)) | ||
1248 | return PTR_ERR(dev_ltpc); | ||
1249 | return 0; | ||
1250 | } | ||
1251 | module_init(ltpc_module_init); | ||
1252 | #endif | ||
1253 | |||
1254 | static void __exit ltpc_cleanup(void) | ||
1255 | { | ||
1256 | |||
1257 | if(debug & DEBUG_VERBOSE) printk("unregister_netdev\n"); | ||
1258 | unregister_netdev(dev_ltpc); | ||
1259 | |||
1260 | ltpc_timer.data = 0; /* signal the poll routine that we're done */ | ||
1261 | |||
1262 | del_timer_sync(<pc_timer); | ||
1263 | |||
1264 | if(debug & DEBUG_VERBOSE) printk("freeing irq\n"); | ||
1265 | |||
1266 | if (dev_ltpc->irq) | ||
1267 | free_irq(dev_ltpc->irq, dev_ltpc); | ||
1268 | |||
1269 | if(debug & DEBUG_VERBOSE) printk("freeing dma\n"); | ||
1270 | |||
1271 | if (dev_ltpc->dma) | ||
1272 | free_dma(dev_ltpc->dma); | ||
1273 | |||
1274 | if(debug & DEBUG_VERBOSE) printk("freeing ioaddr\n"); | ||
1275 | |||
1276 | if (dev_ltpc->base_addr) | ||
1277 | release_region(dev_ltpc->base_addr,8); | ||
1278 | |||
1279 | free_netdev(dev_ltpc); | ||
1280 | |||
1281 | if(debug & DEBUG_VERBOSE) printk("free_pages\n"); | ||
1282 | |||
1283 | free_pages( (unsigned long) ltdmabuf, get_order(1000)); | ||
1284 | |||
1285 | if(debug & DEBUG_VERBOSE) printk("returning from cleanup_module\n"); | ||
1286 | } | ||
1287 | |||
1288 | module_exit(ltpc_cleanup); | ||
diff --git a/drivers/staging/appletalk/ltpc.h b/drivers/staging/appletalk/ltpc.h new file mode 100644 index 00000000000..cd30544a372 --- /dev/null +++ b/drivers/staging/appletalk/ltpc.h | |||
@@ -0,0 +1,73 @@ | |||
1 | /*** ltpc.h | ||
2 | * | ||
3 | * | ||
4 | ***/ | ||
5 | |||
6 | #define LT_GETRESULT 0x00 | ||
7 | #define LT_WRITEMEM 0x01 | ||
8 | #define LT_READMEM 0x02 | ||
9 | #define LT_GETFLAGS 0x04 | ||
10 | #define LT_SETFLAGS 0x05 | ||
11 | #define LT_INIT 0x10 | ||
12 | #define LT_SENDLAP 0x13 | ||
13 | #define LT_RCVLAP 0x14 | ||
14 | |||
15 | /* the flag that we care about */ | ||
16 | #define LT_FLAG_ALLLAP 0x04 | ||
17 | |||
18 | struct lt_getresult { | ||
19 | unsigned char command; | ||
20 | unsigned char mailbox; | ||
21 | }; | ||
22 | |||
23 | struct lt_mem { | ||
24 | unsigned char command; | ||
25 | unsigned char mailbox; | ||
26 | unsigned short addr; /* host order */ | ||
27 | unsigned short length; /* host order */ | ||
28 | }; | ||
29 | |||
30 | struct lt_setflags { | ||
31 | unsigned char command; | ||
32 | unsigned char mailbox; | ||
33 | unsigned char flags; | ||
34 | }; | ||
35 | |||
36 | struct lt_getflags { | ||
37 | unsigned char command; | ||
38 | unsigned char mailbox; | ||
39 | }; | ||
40 | |||
41 | struct lt_init { | ||
42 | unsigned char command; | ||
43 | unsigned char mailbox; | ||
44 | unsigned char hint; | ||
45 | }; | ||
46 | |||
47 | struct lt_sendlap { | ||
48 | unsigned char command; | ||
49 | unsigned char mailbox; | ||
50 | unsigned char dnode; | ||
51 | unsigned char laptype; | ||
52 | unsigned short length; /* host order */ | ||
53 | }; | ||
54 | |||
55 | struct lt_rcvlap { | ||
56 | unsigned char command; | ||
57 | unsigned char dnode; | ||
58 | unsigned char snode; | ||
59 | unsigned char laptype; | ||
60 | unsigned short length; /* host order */ | ||
61 | }; | ||
62 | |||
63 | union lt_command { | ||
64 | struct lt_getresult getresult; | ||
65 | struct lt_mem mem; | ||
66 | struct lt_setflags setflags; | ||
67 | struct lt_getflags getflags; | ||
68 | struct lt_init init; | ||
69 | struct lt_sendlap sendlap; | ||
70 | struct lt_rcvlap rcvlap; | ||
71 | }; | ||
72 | typedef union lt_command lt_command; | ||
73 | |||
diff --git a/drivers/staging/appletalk/sysctl_net_atalk.c b/drivers/staging/appletalk/sysctl_net_atalk.c new file mode 100644 index 00000000000..4c896b625b2 --- /dev/null +++ b/drivers/staging/appletalk/sysctl_net_atalk.c | |||
@@ -0,0 +1,61 @@ | |||
1 | /* | ||
2 | * sysctl_net_atalk.c: sysctl interface to net AppleTalk subsystem. | ||
3 | * | ||
4 | * Begun April 1, 1996, Mike Shaver. | ||
5 | * Added /proc/sys/net/atalk directory entry (empty =) ). [MS] | ||
6 | * Dynamic registration, added aarp entries. (5/30/97 Chris Horn) | ||
7 | */ | ||
8 | |||
9 | #include <linux/sysctl.h> | ||
10 | #include <net/sock.h> | ||
11 | #include "atalk.h" | ||
12 | |||
13 | static struct ctl_table atalk_table[] = { | ||
14 | { | ||
15 | .procname = "aarp-expiry-time", | ||
16 | .data = &sysctl_aarp_expiry_time, | ||
17 | .maxlen = sizeof(int), | ||
18 | .mode = 0644, | ||
19 | .proc_handler = proc_dointvec_jiffies, | ||
20 | }, | ||
21 | { | ||
22 | .procname = "aarp-tick-time", | ||
23 | .data = &sysctl_aarp_tick_time, | ||
24 | .maxlen = sizeof(int), | ||
25 | .mode = 0644, | ||
26 | .proc_handler = proc_dointvec_jiffies, | ||
27 | }, | ||
28 | { | ||
29 | .procname = "aarp-retransmit-limit", | ||
30 | .data = &sysctl_aarp_retransmit_limit, | ||
31 | .maxlen = sizeof(int), | ||
32 | .mode = 0644, | ||
33 | .proc_handler = proc_dointvec, | ||
34 | }, | ||
35 | { | ||
36 | .procname = "aarp-resolve-time", | ||
37 | .data = &sysctl_aarp_resolve_time, | ||
38 | .maxlen = sizeof(int), | ||
39 | .mode = 0644, | ||
40 | .proc_handler = proc_dointvec_jiffies, | ||
41 | }, | ||
42 | { }, | ||
43 | }; | ||
44 | |||
45 | static struct ctl_path atalk_path[] = { | ||
46 | { .procname = "net", }, | ||
47 | { .procname = "appletalk", }, | ||
48 | { } | ||
49 | }; | ||
50 | |||
51 | static struct ctl_table_header *atalk_table_header; | ||
52 | |||
53 | void atalk_register_sysctl(void) | ||
54 | { | ||
55 | atalk_table_header = register_sysctl_paths(atalk_path, atalk_table); | ||
56 | } | ||
57 | |||
58 | void atalk_unregister_sysctl(void) | ||
59 | { | ||
60 | unregister_sysctl_table(atalk_table_header); | ||
61 | } | ||