dde1f2e0cf32c4b1eb7d2634e0ce410938088ca4
[deliverable/linux.git] / drivers / staging / rtl8187se / ieee80211 / ieee80211_tx.c
1 /******************************************************************************
2
3 Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of version 2 of the GNU General Public License as
7 published by the Free Software Foundation.
8
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details.
13
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18 The full GNU General Public License is included in this distribution in the
19 file called LICENSE.
20
21 Contact Information:
22 James P. Ketrenos <ipw2100-admin@linux.intel.com>
23 Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
24
25 ******************************************************************************
26
27 Few modifications for Realtek's Wi-Fi drivers by
28 Andrea Merello <andreamrl@tiscali.it>
29
30 A special thanks goes to Realtek for their support !
31
32 ******************************************************************************/
33
34 #include <linux/compiler.h>
35 //#include <linux/config.h>
36 #include <linux/errno.h>
37 #include <linux/if_arp.h>
38 #include <linux/in6.h>
39 #include <linux/in.h>
40 #include <linux/ip.h>
41 #include <linux/kernel.h>
42 #include <linux/module.h>
43 #include <linux/netdevice.h>
44 #include <linux/pci.h>
45 #include <linux/proc_fs.h>
46 #include <linux/skbuff.h>
47 #include <linux/slab.h>
48 #include <linux/tcp.h>
49 #include <linux/types.h>
50 #include <linux/wireless.h>
51 #include <linux/etherdevice.h>
52 #include <asm/uaccess.h>
53 #include <linux/if_vlan.h>
54
55 #include "ieee80211.h"
56
57
58 /*
59
60
61 802.11 Data Frame
62
63
64 802.11 frame_contorl for data frames - 2 bytes
65 ,-----------------------------------------------------------------------------------------.
66 bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e |
67 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
68 val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x |
69 |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------|
70 desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep |
71 | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | |
72 '-----------------------------------------------------------------------------------------'
73 /\
74 |
75 802.11 Data Frame |
76 ,--------- 'ctrl' expands to >-----------'
77 |
78 ,--'---,-------------------------------------------------------------.
79 Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
80 |------|------|---------|---------|---------|------|---------|------|
81 Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
82 | | tion | (BSSID) | | | ence | data | |
83 `--------------------------------------------------| |------'
84 Total: 28 non-data bytes `----.----'
85 |
86 .- 'Frame data' expands to <---------------------------'
87 |
88 V
89 ,---------------------------------------------------.
90 Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
91 |------|------|---------|----------|------|---------|
92 Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
93 | DSAP | SSAP | | | | Packet |
94 | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
95 `-----------------------------------------| |
96 Total: 8 non-data bytes `----.----'
97 |
98 .- 'IP Packet' expands, if WEP enabled, to <--'
99 |
100 V
101 ,-----------------------.
102 Bytes | 4 | 0-2296 | 4 |
103 |-----|-----------|-----|
104 Desc. | IV | Encrypted | ICV |
105 | | IP Packet | |
106 `-----------------------'
107 Total: 8 non-data bytes
108
109
110 802.3 Ethernet Data Frame
111
112 ,-----------------------------------------.
113 Bytes | 6 | 6 | 2 | Variable | 4 |
114 |-------|-------|------|-----------|------|
115 Desc. | Dest. | Source| Type | IP Packet | fcs |
116 | MAC | MAC | | | |
117 `-----------------------------------------'
118 Total: 18 non-data bytes
119
120 In the event that fragmentation is required, the incoming payload is split into
121 N parts of size ieee->fts. The first fragment contains the SNAP header and the
122 remaining packets are just data.
123
124 If encryption is enabled, each fragment payload size is reduced by enough space
125 to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
126 So if you have 1500 bytes of payload with ieee->fts set to 500 without
127 encryption it will take 3 frames. With WEP it will take 4 frames as the
128 payload of each frame is reduced to 492 bytes.
129
130 * SKB visualization
131 *
132 * ,- skb->data
133 * |
134 * | ETHERNET HEADER ,-<-- PAYLOAD
135 * | | 14 bytes from skb->data
136 * | 2 bytes for Type --> ,T. | (sizeof ethhdr)
137 * | | | |
138 * |,-Dest.--. ,--Src.---. | | |
139 * | 6 bytes| | 6 bytes | | | |
140 * v | | | | | |
141 * 0 | v 1 | v | v 2
142 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
143 * ^ | ^ | ^ |
144 * | | | | | |
145 * | | | | `T' <---- 2 bytes for Type
146 * | | | |
147 * | | '---SNAP--' <-------- 6 bytes for SNAP
148 * | |
149 * `-IV--' <-------------------- 4 bytes for IV (WEP)
150 *
151 * SNAP HEADER
152 *
153 */
154
155 static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
156 static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
157
158 static inline int ieee80211_put_snap(u8 *data, u16 h_proto)
159 {
160 struct ieee80211_snap_hdr *snap;
161 u8 *oui;
162
163 snap = (struct ieee80211_snap_hdr *)data;
164 snap->dsap = 0xaa;
165 snap->ssap = 0xaa;
166 snap->ctrl = 0x03;
167
168 if (h_proto == 0x8137 || h_proto == 0x80f3)
169 oui = P802_1H_OUI;
170 else
171 oui = RFC1042_OUI;
172 snap->oui[0] = oui[0];
173 snap->oui[1] = oui[1];
174 snap->oui[2] = oui[2];
175
176 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
177
178 return SNAP_SIZE + sizeof(u16);
179 }
180
181 int ieee80211_encrypt_fragment(
182 struct ieee80211_device *ieee,
183 struct sk_buff *frag,
184 int hdr_len)
185 {
186 struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx];
187 int res;
188
189 /*added to care about null crypt condition, to solve that system hangs when shared keys error*/
190 if (!crypt || !crypt->ops)
191 return -1;
192
193 #ifdef CONFIG_IEEE80211_CRYPT_TKIP
194 struct ieee80211_hdr_4addr *header;
195
196 if (ieee->tkip_countermeasures &&
197 crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) {
198 header = (struct ieee80211_hdr_4addr *)frag->data;
199 if (net_ratelimit()) {
200 printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
201 "TX packet to " MAC_FMT "\n",
202 ieee->dev->name, MAC_ARG(header->addr1));
203 }
204 return -1;
205 }
206 #endif
207 /* To encrypt, frame format is:
208 * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
209
210 // PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU encryption.
211 /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so
212 * call both MSDU and MPDU encryption functions from here. */
213 atomic_inc(&crypt->refcnt);
214 res = 0;
215 if (crypt->ops->encrypt_msdu)
216 res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv);
217 if (res == 0 && crypt->ops->encrypt_mpdu)
218 res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
219
220 atomic_dec(&crypt->refcnt);
221 if (res < 0) {
222 printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
223 ieee->dev->name, frag->len);
224 ieee->ieee_stats.tx_discards++;
225 return -1;
226 }
227
228 return 0;
229 }
230
231
232 void ieee80211_txb_free(struct ieee80211_txb *txb) {
233 int i;
234 if (unlikely(!txb))
235 return;
236 for (i = 0; i < txb->nr_frags; i++)
237 if (txb->fragments[i])
238 dev_kfree_skb_any(txb->fragments[i]);
239 kfree(txb);
240 }
241
242 struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
243 int gfp_mask)
244 {
245 struct ieee80211_txb *txb;
246 int i;
247 txb = kmalloc(
248 sizeof(struct ieee80211_txb) + (sizeof(u8*) * nr_frags),
249 gfp_mask);
250 if (!txb)
251 return NULL;
252
253 memset(txb, 0, sizeof(struct ieee80211_txb));
254 txb->nr_frags = nr_frags;
255 txb->frag_size = txb_size;
256
257 for (i = 0; i < nr_frags; i++) {
258 txb->fragments[i] = dev_alloc_skb(txb_size);
259 if (unlikely(!txb->fragments[i])) {
260 i--;
261 break;
262 }
263 }
264 if (unlikely(i != nr_frags)) {
265 while (i >= 0)
266 dev_kfree_skb_any(txb->fragments[i--]);
267 kfree(txb);
268 return NULL;
269 }
270 return txb;
271 }
272
273 // Classify the to-be send data packet
274 // Need to acquire the sent queue index.
275 static int
276 ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network)
277 {
278 struct ether_header *eh = (struct ether_header*)skb->data;
279 unsigned int wme_UP = 0;
280
281 if(!network->QoS_Enable) {
282 skb->priority = 0;
283 return(wme_UP);
284 }
285
286 if(eh->ether_type == __constant_htons(ETHERTYPE_IP)) {
287 const struct iphdr *ih = (struct iphdr*)(skb->data + \
288 sizeof(struct ether_header));
289 wme_UP = (ih->tos >> 5)&0x07;
290 } else if (vlan_tx_tag_present(skb)) {//vtag packet
291 #ifndef VLAN_PRI_SHIFT
292 #define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */
293 #define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */
294 #endif
295 u32 tag = vlan_tx_tag_get(skb);
296 wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK;
297 } else if(ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) {
298 //printk(KERN_WARNING "type = normal packet\n");
299 wme_UP = 7;
300 }
301
302 skb->priority = wme_UP;
303 return(wme_UP);
304 }
305
306 /* SKBs are added to the ieee->tx_queue. */
307 int ieee80211_xmit(struct sk_buff *skb,
308 struct net_device *dev)
309 {
310 struct ieee80211_device *ieee = netdev_priv(dev);
311 struct ieee80211_txb *txb = NULL;
312 struct ieee80211_hdr_3addrqos *frag_hdr;
313 int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size;
314 unsigned long flags;
315 struct net_device_stats *stats = &ieee->stats;
316 int ether_type, encrypt;
317 int bytes, fc, qos_ctl, hdr_len;
318 struct sk_buff *skb_frag;
319 struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */
320 .duration_id = 0,
321 .seq_ctl = 0,
322 .qos_ctl = 0
323 };
324 u8 dest[ETH_ALEN], src[ETH_ALEN];
325
326 struct ieee80211_crypt_data* crypt;
327
328 //printk(KERN_WARNING "upper layer packet!\n");
329 spin_lock_irqsave(&ieee->lock, flags);
330
331 /* If there is no driver handler to take the TXB, dont' bother
332 * creating it... */
333 if ((!ieee->hard_start_xmit && !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE))||
334 ((!ieee->softmac_data_hard_start_xmit && (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) {
335 printk(KERN_WARNING "%s: No xmit handler.\n",
336 ieee->dev->name);
337 goto success;
338 }
339
340 ieee80211_classify(skb,&ieee->current_network);
341 if(likely(ieee->raw_tx == 0)){
342
343 if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
344 printk(KERN_WARNING "%s: skb too small (%d).\n",
345 ieee->dev->name, skb->len);
346 goto success;
347 }
348
349 ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto);
350
351 crypt = ieee->crypt[ieee->tx_keyidx];
352
353 encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) &&
354 ieee->host_encrypt && crypt && crypt->ops;
355
356 if (!encrypt && ieee->ieee802_1x &&
357 ieee->drop_unencrypted && ether_type != ETH_P_PAE) {
358 stats->tx_dropped++;
359 goto success;
360 }
361
362 #ifdef CONFIG_IEEE80211_DEBUG
363 if (crypt && !encrypt && ether_type == ETH_P_PAE) {
364 struct eapol *eap = (struct eapol *)(skb->data +
365 sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16));
366 IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n",
367 eap_get_type(eap->type));
368 }
369 #endif
370
371 /* Save source and destination addresses */
372 memcpy(&dest, skb->data, ETH_ALEN);
373 memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN);
374
375 /* Advance the SKB to the start of the payload */
376 skb_pull(skb, sizeof(struct ethhdr));
377
378 /* Determine total amount of storage required for TXB packets */
379 bytes = skb->len + SNAP_SIZE + sizeof(u16);
380
381 if(ieee->current_network.QoS_Enable) {
382 if (encrypt)
383 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA |
384 IEEE80211_FCTL_WEP;
385 else
386 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
387
388 } else {
389 if (encrypt)
390 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
391 IEEE80211_FCTL_WEP;
392 else
393 fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
394 }
395
396 if (ieee->iw_mode == IW_MODE_INFRA) {
397 fc |= IEEE80211_FCTL_TODS;
398 /* To DS: Addr1 = BSSID, Addr2 = SA,
399 Addr3 = DA */
400 memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN);
401 memcpy(&header.addr2, &src, ETH_ALEN);
402 memcpy(&header.addr3, &dest, ETH_ALEN);
403 } else if (ieee->iw_mode == IW_MODE_ADHOC) {
404 /* not From/To DS: Addr1 = DA, Addr2 = SA,
405 Addr3 = BSSID */
406 memcpy(&header.addr1, dest, ETH_ALEN);
407 memcpy(&header.addr2, src, ETH_ALEN);
408 memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN);
409 }
410 // printk(KERN_WARNING "essid MAC address is "MAC_FMT, MAC_ARG(&header.addr1));
411 header.frame_ctl = cpu_to_le16(fc);
412 //hdr_len = IEEE80211_3ADDR_LEN;
413
414 /* Determine fragmentation size based on destination (multicast
415 * and broadcast are not fragmented) */
416 // if (is_multicast_ether_addr(dest) ||
417 // is_broadcast_ether_addr(dest)) {
418 if (is_multicast_ether_addr(header.addr1) ||
419 is_broadcast_ether_addr(header.addr1)) {
420 frag_size = MAX_FRAG_THRESHOLD;
421 qos_ctl = QOS_CTL_NOTCONTAIN_ACK;
422 }
423 else {
424 //printk(KERN_WARNING "&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&frag_size = %d\n", frag_size);
425 frag_size = ieee->fts;//default:392
426 qos_ctl = 0;
427 }
428
429 if (ieee->current_network.QoS_Enable) {
430 hdr_len = IEEE80211_3ADDR_LEN + 2;
431 /* skb->priority is set in the ieee80211_classify() */
432 qos_ctl |= skb->priority;
433 header.qos_ctl = cpu_to_le16(qos_ctl);
434 } else {
435 hdr_len = IEEE80211_3ADDR_LEN;
436 }
437
438 /* Determine amount of payload per fragment. Regardless of if
439 * this stack is providing the full 802.11 header, one will
440 * eventually be affixed to this fragment -- so we must account for
441 * it when determining the amount of payload space. */
442 //bytes_per_frag = frag_size - (IEEE80211_3ADDR_LEN + (ieee->current_network->QoS_Enable ? 2:0));
443 bytes_per_frag = frag_size - hdr_len;
444 if (ieee->config &
445 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
446 bytes_per_frag -= IEEE80211_FCS_LEN;
447
448 /* Each fragment may need to have room for encryptiong pre/postfix */
449 if (encrypt)
450 bytes_per_frag -= crypt->ops->extra_prefix_len +
451 crypt->ops->extra_postfix_len;
452
453 /* Number of fragments is the total bytes_per_frag /
454 * payload_per_fragment */
455 nr_frags = bytes / bytes_per_frag;
456 bytes_last_frag = bytes % bytes_per_frag;
457 if (bytes_last_frag)
458 nr_frags++;
459 else
460 bytes_last_frag = bytes_per_frag;
461
462 /* When we allocate the TXB we allocate enough space for the reserve
463 * and full fragment bytes (bytes_per_frag doesn't include prefix,
464 * postfix, header, FCS, etc.) */
465 txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC);
466 if (unlikely(!txb)) {
467 printk(KERN_WARNING "%s: Could not allocate TXB\n",
468 ieee->dev->name);
469 goto failed;
470 }
471 txb->encrypted = encrypt;
472 txb->payload_size = bytes;
473
474 for (i = 0; i < nr_frags; i++) {
475 skb_frag = txb->fragments[i];
476 skb_frag->priority = UP2AC(skb->priority);
477 if (encrypt)
478 skb_reserve(skb_frag, crypt->ops->extra_prefix_len);
479
480 frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
481 memcpy(frag_hdr, &header, hdr_len);
482
483 /* If this is not the last fragment, then add the MOREFRAGS
484 * bit to the frame control */
485 if (i != nr_frags - 1) {
486 frag_hdr->frame_ctl = cpu_to_le16(
487 fc | IEEE80211_FCTL_MOREFRAGS);
488 bytes = bytes_per_frag;
489
490 } else {
491 /* The last fragment takes the remaining length */
492 bytes = bytes_last_frag;
493 }
494 if(ieee->current_network.QoS_Enable) {
495 // add 1 only indicate to corresponding seq number control 2006/7/12
496 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i);
497 //printk(KERN_WARNING "skb->priority = %d,", skb->priority);
498 //printk(KERN_WARNING "type:%d: seq = %d\n",UP2AC(skb->priority),ieee->seq_ctrl[UP2AC(skb->priority)+1]);
499 } else {
500 frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4 | i);
501 }
502 //frag_hdr->seq_ctl = cpu_to_le16(ieee->seq_ctrl<<4 | i);
503 //
504
505 /* Put a SNAP header on the first fragment */
506 if (i == 0) {
507 ieee80211_put_snap(
508 skb_put(skb_frag, SNAP_SIZE + sizeof(u16)),
509 ether_type);
510 bytes -= SNAP_SIZE + sizeof(u16);
511 }
512
513 memcpy(skb_put(skb_frag, bytes), skb->data, bytes);
514
515 /* Advance the SKB... */
516 skb_pull(skb, bytes);
517
518 /* Encryption routine will move the header forward in order
519 * to insert the IV between the header and the payload */
520 if (encrypt)
521 ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
522 if (ieee->config &
523 (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
524 skb_put(skb_frag, 4);
525 }
526 // Advance sequence number in data frame.
527 //printk(KERN_WARNING "QoS Enalbed? %s\n", ieee->current_network.QoS_Enable?"Y":"N");
528 if (ieee->current_network.QoS_Enable) {
529 if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF)
530 ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0;
531 else
532 ieee->seq_ctrl[UP2AC(skb->priority) + 1]++;
533 } else {
534 if (ieee->seq_ctrl[0] == 0xFFF)
535 ieee->seq_ctrl[0] = 0;
536 else
537 ieee->seq_ctrl[0]++;
538 }
539 //---
540 }else{
541 if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) {
542 printk(KERN_WARNING "%s: skb too small (%d).\n",
543 ieee->dev->name, skb->len);
544 goto success;
545 }
546
547 txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC);
548 if(!txb){
549 printk(KERN_WARNING "%s: Could not allocate TXB\n",
550 ieee->dev->name);
551 goto failed;
552 }
553
554 txb->encrypted = 0;
555 txb->payload_size = skb->len;
556 memcpy(skb_put(txb->fragments[0],skb->len), skb->data, skb->len);
557 }
558
559 success:
560 spin_unlock_irqrestore(&ieee->lock, flags);
561 dev_kfree_skb_any(skb);
562 if (txb) {
563 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE){
564 ieee80211_softmac_xmit(txb, ieee);
565 }else{
566 if ((*ieee->hard_start_xmit)(txb, dev) == 0) {
567 stats->tx_packets++;
568 stats->tx_bytes += txb->payload_size;
569 return NETDEV_TX_OK;
570 }
571 ieee80211_txb_free(txb);
572 }
573 }
574
575 return NETDEV_TX_OK;
576
577 failed:
578 spin_unlock_irqrestore(&ieee->lock, flags);
579 netif_stop_queue(dev);
580 stats->tx_errors++;
581 return NETDEV_TX_BUSY;
582
583 }
This page took 0.044796 seconds and 4 git commands to generate.