Original 0.2.0pre7_plus_fixes_2 tarball
[acx-mac80211.git] / src / idma.c
blob571661e480465d0e65ef9ede11aeb9cd9be9cedd
1 /* src/idma.c - low level rx and tx management
3 * --------------------------------------------------------------------
5 * Copyright (C) 2003 ACX100 Open Source Project
7 * The contents of this file are subject to the Mozilla Public
8 * License Version 1.1 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy of
10 * the License at http://www.mozilla.org/MPL/
12 * Software distributed under the License is distributed on an "AS
13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * rights and limitations under the License.
17 * Alternatively, the contents of this file may be used under the
18 * terms of the GNU Public License version 2 (the "GPL"), in which
19 * case the provisions of the GPL are applicable instead of the
20 * above. If you wish to allow the use of your version of this file
21 * only under the terms of the GPL and not to allow others to use
22 * your version of this file under the MPL, indicate your decision
23 * by deleting the provisions above and replace them with the notice
24 * and other provisions required by the GPL. If you do not delete
25 * the provisions above, a recipient may use your version of this
26 * file under either the MPL or the GPL.
28 * --------------------------------------------------------------------
30 * Inquiries regarding the ACX100 Open Source Project can be
31 * made directly to:
33 * acx100-users@lists.sf.net
34 * http://acx100.sf.net
36 * --------------------------------------------------------------------
39 #include <linux/config.h>
40 #include <linux/version.h>
42 #include <linux/module.h>
43 #include <linux/kernel.h>
45 #include <linux/sched.h>
46 #include <linux/types.h>
47 #include <linux/skbuff.h>
48 #include <linux/slab.h>
49 #include <linux/proc_fs.h>
50 #include <linux/if_arp.h>
51 #include <linux/rtnetlink.h>
52 #include <linux/wireless.h>
53 #include <linux/netdevice.h>
55 #include <wlan_compat.h>
57 #include <linux/ioport.h>
58 #include <linux/pci.h>
59 #include <linux/pm.h>
61 #include <linux/dcache.h>
62 #include <linux/highmem.h>
63 #include <linux/sched.h>
64 #include <linux/skbuff.h>
65 #include <linux/etherdevice.h>
68 /*================================================================*/
69 /* Project Includes */
71 #include <version.h>
72 #include <p80211hdr.h>
73 #include <p80211mgmt.h>
74 #include <acx100_conv.h>
75 #include <acx100.h>
76 #include <p80211types.h>
77 #include <acx100_helper.h>
78 #include <acx100_helper2.h>
79 #include <idma.h>
80 #include <ihw.h>
81 #include <monitor.h>
83 /* these used to be increased to 32 each,
84 * but several people had memory allocation issues,
85 * so back to 16 again... */
86 #if (WLAN_HOSTIF==WLAN_USB)
87 #define TXBUFFERNO 10
88 #define RXBUFFERNO 10
89 #else
90 #define RXBUFFERNO 16
91 #define TXBUFFERNO 16
92 #endif
94 #define MINFREE_TX 3
95 spinlock_t tx_lock;
96 spinlock_t rx_lock;
98 #ifdef ACX_DEBUG
99 #if (WLAN_HOSTIF==WLAN_USB)
100 extern void acx100usb_dump_bytes(void *,int);
101 #endif
102 #endif
105 /*----------------------------------------------------------------
106 * acx100_enable_irq
109 * Arguments:
111 * Returns:
113 * Side effects:
115 * Call context:
117 * STATUS:
119 * Comment:
121 *----------------------------------------------------------------*/
123 void acx100_enable_irq(wlandevice_t * wlandev)
125 FN_ENTER;
126 #if (WLAN_HOSTIF!=WLAN_USB)
127 acx100_write_reg16(wlandev, wlandev->io[IO_ACX_IRQ_MASK], wlandev->irq_mask);
128 acx100_write_reg16(wlandev, wlandev->io[IO_ACX_FEMR], 0x8000);
129 #endif
130 FN_EXIT(0, 0);
133 /*----------------------------------------------------------------
134 * acx100_disable_irq
137 * Arguments:
139 * Returns:
141 * Side effects:
143 * Call context:
145 * STATUS:
147 * Comment:
149 *----------------------------------------------------------------*/
151 void acx100_disable_irq(wlandevice_t * wlandev)
153 FN_ENTER;
154 #if (WLAN_HOSTIF!=WLAN_USB)
155 acx100_write_reg16(wlandev, wlandev->io[IO_ACX_IRQ_MASK], 0x7fff);
156 acx100_write_reg16(wlandev, wlandev->io[IO_ACX_FEMR], 0x0);
157 #endif
158 FN_EXIT(0, 0);
161 /*----------------------------------------------------------------
162 * acx100_create_dma_regions
165 * Arguments:
167 * Returns:
169 * Side effects:
171 * Call context:
173 * STATUS:
175 * Comment:
177 *----------------------------------------------------------------*/
179 int acx100_create_dma_regions(wlandevice_t * wlandev)
181 QueueConfig_t qcfg;
182 /* FIXME: way too big to reside on the stack */
183 struct {
184 UINT16 val0x0[14];
185 UINT queue_start;
186 UINT val0x20;
187 UINT val0x24;
188 UINT val0x28;
189 UINT val0x2c;
190 } MemMap;
191 struct TIWLAN_DC *pDc;
193 FN_ENTER;
195 spin_lock_init(&rx_lock);
196 spin_lock_init(&tx_lock);
198 pDc = &wlandev->dc;
199 pDc->wlandev = wlandev;
201 /* FIXME: which memmap is read here, acx100_init_memory_pools did not get called yet ? */
202 /* read out the acx100 physical start address for the queues */
203 if (!acx100_interrogate(wlandev, &MemMap, ACX100_RID_MEMORY_MAP)) {
204 acxlog(L_BINSTD, "ctlMemoryMapRead returns error\n");
205 FN_EXIT(1, 2);
206 return 2;
209 /* # of items in Rx and Tx queues */
210 wlandev->TxQueueNo = TXBUFFERNO;
211 wlandev->RxQueueNo = RXBUFFERNO;
213 /* calculate size of queues */
214 qcfg.AreaSize = (sizeof(struct txdescriptor) * TXBUFFERNO +
215 sizeof(struct rxdescriptor) * RXBUFFERNO + 8);
216 qcfg.vale = 1; /* number of tx queues */
217 #if (WLAN_HOSTIF==WLAN_USB)
218 qcfg.valf1=RXBUFFERNO;
219 #endif
221 /* sets the beginning of the tx descriptor queue */
222 pDc->ui32ACXTxQueueStart = MemMap.queue_start;
223 qcfg.TxQueueStart = pDc->ui32ACXTxQueueStart;
224 qcfg.valj = 0;
225 #if (WLAN_HOSTIF==WLAN_USB)
226 qcfg.valk = TXBUFFERNO;
227 #endif
229 /* sets the beginning of the rx descriptor queue */
230 pDc->ui32ACXRxQueueStart = wlandev->TxQueueNo * sizeof(struct txdescriptor) + MemMap.queue_start;
231 qcfg.RxQueueStart = pDc->ui32ACXRxQueueStart;
232 qcfg.vald = 1;
234 /* sets the end of the rx descriptor queue */
235 qcfg.QueueEnd = wlandev->RxQueueNo * sizeof(struct rxdescriptor) + pDc->ui32ACXRxQueueStart;
237 /* sets the beginning of the next queue */
238 qcfg.QueueEnd2 = qcfg.QueueEnd + 8;
240 acxlog(L_BINDEBUG, "<== Initialize the Queue Indicator\n");
242 if (!acx100_configure_length(wlandev, &qcfg, ACX100_RID_QUEUE_CONFIG, sizeof(QueueConfig_t)-4)){ //0x14 + (qcfg.vale * 8))) {
243 acxlog(L_BINSTD, "ctlQueueConfigurationWrite returns error\n");
244 goto error;
247 if (acx100_create_tx_host_desc_queue(pDc)) {
248 acxlog(L_BINSTD, "acx100_create_tx_host_desc_queue returns error\n");
249 goto error;
251 if (acx100_create_rx_host_desc_queue(pDc)) {
252 acxlog(L_BINSTD, "acx100_create_rx_host_desc_queue returns error\n");
253 goto error;
255 acx100_create_tx_desc_queue(pDc);
256 acx100_create_rx_desc_queue(pDc);
257 if (!acx100_interrogate(wlandev, &MemMap, ACX100_RID_MEMORY_MAP)) {
258 acxlog(L_BINSTD, "Failed to read memory map\n");
259 goto error;
262 #if (WLAN_HOSTIF==WLAN_USB)
263 acxlog(L_DEBUG,"Memory Map before configure 1\n");
264 acx100usb_dump_bytes(&MemMap,44);
265 if (!acx100_configure(wlandev,&MemMap,ACX100_RID_MEMORY_MAP)) {
266 acxlog(L_BINSTD,"Failed to write memory map\n");
267 goto error;
269 #endif
271 /* FIXME: what does this do? name the fields */
272 /* start at least 4 bytes away from the end of the last pool */
273 MemMap.val0x24 = (MemMap.val0x20 + 0x1F + 4) & 0xffffffe0;
274 #if (WLAN_HOSTIF==WLAN_USB)
275 #ifdef ACX_DEBUG
276 acxlog(L_DEBUG,"Memory map before configure:\n");
277 acx100usb_dump_bytes(&MemMap,44);
278 #endif
279 #endif
281 if (!acx100_configure(wlandev, &MemMap, ACX100_RID_MEMORY_MAP)) {
282 acxlog(L_BINSTD, "ctlMemoryMapWrite returns error\n");
283 goto error;
286 if (!acx100_init_memory_pools(wlandev, (memmap_t *) &MemMap)) {
287 acxlog(L_BINSTD, "acx100_init_memory_pools returns error\n");
288 goto error;
291 #if THIS_IS_BOGUS_ISNT_IT
292 acx100_set_defaults(wlandev);
293 #endif
295 FN_EXIT(1, 0);
296 return 0;
298 error:
299 acx100_free_desc_queues(pDc);
301 FN_EXIT(1, 1);
302 return 1;
308 int acx111_create_dma_regions(wlandevice_t * wlandev)
312 struct ACX111_RX_CONFIG_BLOCK;
314 /* TODO make a cool struct an pace it in the wlandev struct ? */
315 /* This struct is specific for the ACX111 !!! */
316 struct ACX111MemoryConfiguration {
318 UINT16 id;
319 UINT16 length;
320 UINT16 no_of_stations;
321 UINT16 memory_block_size;
322 UINT8 tx_rx_memory_block_allocation;
323 UINT8 count_rx_queues;
324 UINT8 count_tx_queues;
325 UINT8 options;
326 UINT8 fragmentation;
327 UINT16 reserved1;
328 UINT8 reserved2;
330 /* start of rx1 block */
331 UINT8 rx_queue1_count_descs;
332 UINT8 rx_queue1_reserved1;
333 UINT8 rx_queue1_reserved2; /* must be set to 7 */
334 UINT8 rx_queue1_reserved3; /* must be set to 0 */
335 UINT32 rx_queue1_host_rx_start;
336 /* end of rx1 block */
338 /* start of tx1 block */
339 UINT8 tx_queue1_count_descs;
340 UINT8 tx_queue1_reserved1;
341 UINT8 tx_queue1_reserved2;
342 UINT8 tx_queue1_attributes;
343 /* end of tx1 block */
345 #ifdef COMMENT
346 /* start init struct */
347 pt->m.gp.bytes[0x00] = 0x3; /* id */
348 pt->m.gp.bytes[0x01] = 0x0; /* id */
349 pt->m.gp.bytes[0x02] = 16; /* length */
350 pt->m.gp.bytes[0x03] = 0; /* length */
351 pt->m.gp.bytes[0x04] = 0; /* number of sta's */
352 pt->m.gp.bytes[0x05] = 0; /* number of sta's */
353 pt->m.gp.bytes[0x06] = 0x00; /* memory block size */
354 pt->m.gp.bytes[0x07] = 0x01; /* memory block size */
355 pt->m.gp.bytes[0x08] = 10; /* tx/rx memory block allocation */
356 pt->m.gp.bytes[0x09] = 0; /* number of Rx Descriptor Queues */
357 pt->m.gp.bytes[0x0a] = 0; /* number of Tx Descriptor Queues */
358 pt->m.gp.bytes[0x0b] = 0; /* options */
359 pt->m.gp.bytes[0x0c] = 0x0c; /* Tx memory/fragment memory pool allocation */
360 pt->m.gp.bytes[0x0d] = 0; /* reserved */
361 pt->m.gp.bytes[0x0e] = 0; /* reserved */
362 pt->m.gp.bytes[0x0f] = 0; /* reserved */
363 /* end init struct */
364 #endif
366 } __WLAN_ATTRIB_PACK__ memconf;
368 /* FIXME: way too big to reside on the stack */
369 struct {
370 UINT16 val0x0[14];
371 UINT queue_start;
372 UINT val0x20;
373 UINT val0x24;
374 UINT val0x28;
375 UINT val0x2c;
376 } MemMap;
377 struct TIWLAN_DC *pDc;
378 QueueConfig_t qcfg;
380 FN_ENTER;
382 pDc = &wlandev->dc;
383 pDc->wlandev = wlandev;
385 spin_lock_init(&rx_lock);
386 spin_lock_init(&tx_lock);
388 /* FIXME: which memmap is read here, acx100_init_memory_pools did not get called yet ? */
389 /* read out the acx100 physical start address for the queues */
390 if (!acx100_interrogate(wlandev, &MemMap, ACX100_RID_MEMORY_MAP)) {
391 acxlog(L_BINSTD, "ctlMemoryMapRead returns error\n");
392 FN_EXIT(1, 2);
393 return 2;
396 /* ### Calculate memory positions and queue sizes #### */
398 /* calculate size of queues */
399 qcfg.AreaSize = (sizeof(struct txdescriptor) * TXBUFFERNO +
400 sizeof(struct rxdescriptor) * RXBUFFERNO + 8);
401 qcfg.vale = 1; /* number of tx queues */
402 qcfg.valf1=RXBUFFERNO;
404 /* sets the beginning of the tx descriptor queue */
405 pDc->ui32ACXTxQueueStart = MemMap.queue_start;
406 qcfg.TxQueueStart = pDc->ui32ACXTxQueueStart;
407 qcfg.valj = 0;
408 qcfg.valk = TXBUFFERNO;
410 /* sets the beginning of the rx descriptor queue */
411 pDc->ui32ACXRxQueueStart = wlandev->TxQueueNo * sizeof(struct txdescriptor) + MemMap.queue_start;
412 qcfg.RxQueueStart = pDc->ui32ACXRxQueueStart;
413 qcfg.vald = 1;
415 /* sets the end of the rx descriptor queue */
416 qcfg.QueueEnd = wlandev->RxQueueNo * sizeof(struct rxdescriptor) + pDc->ui32ACXRxQueueStart;
418 /* sets the beginning of the next queue */
419 qcfg.QueueEnd2 = qcfg.QueueEnd + 8;
421 acxlog(L_BINDEBUG, "<== Initialize the Queue Indicator\n");
424 /* ### Set up the card #### */
426 memset(&memconf, 0, sizeof(memconf));
428 /* set command (ACXMemoryConfiguration) */
429 memconf.id = 0x03;
430 memconf.length = sizeof(memconf);
432 /* hm, I hope this is correct */
433 memconf.no_of_stations = 1;
435 /* specify the memory block size. Default is 256 */
436 memconf.memory_block_size = wlandev->memblocksize;
438 /* let's use 50%/50% for tx/rx */
439 memconf.tx_rx_memory_block_allocation = 10;
442 /* set the count of our queues */
443 memconf.count_rx_queues = 1; // TODO place this in constants
444 memconf.count_tx_queues = 1;
446 if(memconf.count_rx_queues != 1 || memconf.count_tx_queues != 1) {
447 acxlog(L_STD,
448 "%s: Requested more buffers than supported. Please adapt the structure! rxbuffers:%d txbuffers:%d\n",
449 __func__, memconf.count_rx_queues, memconf.count_tx_queues);
450 goto error;
452 wlandev->TxQueueNo = TXBUFFERNO;
453 wlandev->RxQueueNo = RXBUFFERNO;
455 /* uhoh, hope this is correct-> BusMaster Indirect Memory Organization */
456 memconf.options = 1;
458 /* let's use 25% for fragmentations and 75% for frame transfers */
459 memconf.fragmentation = 0x0f;
461 /* RX queue config */
462 memconf.rx_queue1_count_descs = RXBUFFERNO;
463 memconf.rx_queue1_reserved2 = 7; /* must be set to 7 */
464 memconf.rx_queue1_host_rx_start = qcfg.RxQueueStart;
466 /* TX queue config */
467 memconf.tx_queue1_count_descs = TXBUFFERNO;
468 /* memconf.tx_queue1_host_tx_start = qcfg.TxQueueStart; */
471 if (acx100_create_tx_host_desc_queue(pDc)) {
472 acxlog(L_BINSTD, "acx100_create_tx_host_desc_queue returns error\n");
473 goto error;
475 if (acx100_create_rx_host_desc_queue(pDc)) {
476 acxlog(L_BINSTD, "acx100_create_rx_host_desc_queue returns error\n");
477 goto error;
479 acx100_create_tx_desc_queue(pDc);
480 acx100_create_rx_desc_queue(pDc);
482 acxlog(L_STD, "%s: set up acx111 queue memory configuration (queue configs + descriptors)\n", __func__);
483 if (acx100_configure(wlandev, &memconf, 0x03) == 0) {
484 acxlog(L_STD, "setting up the memory configuration failed!\n");
485 goto error;
489 #if THIS_IS_BOGUS_ISNT_IT
490 acx100_set_defaults(wlandev);
491 #endif
493 FN_EXIT(1, 0);
494 return 0;
496 error:
497 acx100_free_desc_queues(pDc);
499 FN_EXIT(1, 1);
500 return 1;
507 /*----------------------------------------------------------------
508 * acx100_delete_dma_region
511 * Arguments:
513 * Returns:
515 * Side effects:
517 * Call context:
519 * STATUS:
521 * Comment:
523 *----------------------------------------------------------------*/
525 int acx100_delete_dma_region(wlandevice_t * wlandev)
527 FN_ENTER;
528 #if (WLAN_HOSTIF!=WLAN_USB)
529 acx100_write_reg16(wlandev, wlandev->io[IO_ACX_ENABLE], 0);
531 /* used to be a for loop 1000, do scheduled delay instead */
532 acx100_schedule(HZ / 10);
533 #endif
534 acx100_free_desc_queues(&wlandev->dc);
536 FN_EXIT(0, 0);
537 return 0;
540 /*----------------------------------------------------------------
541 * acx100_dma_tx_data
544 * Arguments:
546 * Returns:
548 * Side effects:
550 * Call context:
552 * STATUS:
554 * Comment:
556 *----------------------------------------------------------------*/
558 void acx100_dma_tx_data(wlandevice_t *wlandev, struct txdescriptor *tx_desc)
560 struct txhostdescriptor *header;
561 struct txhostdescriptor *payload;
562 unsigned long flags;
563 int i;
565 FN_ENTER;
566 #if (WLAN_HOSTIF!=WLAN_USB)
567 /* header and payload are located in adjacent descriptors */
568 header = tx_desc->host_desc;
569 payload = tx_desc->host_desc + 1;
571 tx_desc->tx_time = jiffies;
573 tx_desc->Ctl |= wlandev->preamble_flag; /* set Preamble */
574 /* It seems as if the Preamble setting was actually REVERSED:
575 * bit 0 should most likely actually be ACTIVATED
576 * for Short Preamble, not the other way around as before!
577 * This caused many Tx error 0x20 errors with APs
578 * that don't support Long Preamble, since we were
579 * thinking we are setting Long Preamble, when in fact
580 * it was Short Preamble.
581 * The flag reversal theory has been sort of confirmed
582 * by throughput measurements:
583 * ~ 680K/s with flag disabled
584 * ~ 760K/s with flag enabled
587 /* set autodma and reclaim and 1st mpdu */
588 tx_desc->Ctl |= DESC_CTL_AUTODMA | DESC_CTL_RECLAIM | DESC_CTL_FIRST_MPDU;
590 /* let chip do RTS/CTS handshaking before sending
591 * in case packet size exceeds threshold */
592 if (tx_desc->total_length > wlandev->rts_threshold)
593 tx_desc->Ctl2 |= DESC_CTL2_RTS;
595 /* set rate */
596 if (WLAN_GET_FC_FTYPE(((p80211_hdr_t*)header->data)->a3.fc) == WLAN_FTYPE_MGMT) {
597 tx_desc->rate = 20; /* 2Mbps for MGMT pkt compatibility */
598 } else {
599 tx_desc->rate = wlandev->bitrateval;
602 acxlog(L_XFER | L_DATA,
603 "Tx pkt (%s): len %i, hdr_len %i, pyld_len %i, mode %d, status %d\n",
604 acx100_get_packet_type_string(((p80211_hdr_t*)header->data)->a3.fc),
605 tx_desc->total_length,
606 header->length,
607 payload->length,
608 wlandev->mode,
609 wlandev->status);
611 acxlog(L_DATA, "802.11 header[%d]: ", header->length);
612 for (i = 0; i < header->length; i++)
613 acxlog(L_DATA, "%02x ", ((UINT8 *) header->data)[i]);
614 acxlog(L_DATA, "\n");
615 acxlog(L_DATA, "802.11 payload[%d]: ", payload->length);
616 for (i = 0; i < payload->length; i++)
617 acxlog(L_DATA, "%02x ", ((UINT8 *) payload->data)[i]);
618 acxlog(L_DATA, "\n");
620 spin_lock_irqsave(&tx_lock, flags);
622 /* sets Ctl DESC_CTL_FREE to zero telling that the descriptors are now owned by the acx100 */
623 header->Ctl &= (UINT16) ~DESC_CTL_FREE;
624 payload->Ctl &= (UINT16) ~DESC_CTL_FREE;
625 tx_desc->Ctl &= (UINT16) ~DESC_CTL_FREE;
627 acx100_write_reg16(wlandev, wlandev->io[IO_ACX_INT_TRIG], 0x4);
629 spin_unlock_irqrestore(&tx_lock, flags);
630 #endif
631 FN_EXIT(0, 0);
634 /*----------------------------------------------------------------
635 * acx100_log_txbuffer
638 * Arguments:
640 * Returns:
642 * Side effects:
644 * Call context:
646 * STATUS:
648 * Comment:
650 *----------------------------------------------------------------*/
652 void acx100_log_txbuffer(TIWLAN_DC *pDc)
654 unsigned int i;
655 txdesc_t *pTxDesc;
657 FN_ENTER;
658 for (i = 0; i < pDc->tx_pool_count; i++)
660 pTxDesc = &pDc->pTxDescQPool[i];
662 if ((pTxDesc->Ctl & DESC_CTL_DONE) == DESC_CTL_DONE)
663 acxlog(L_BUF, "txbuf %d done\n", i);
665 FN_EXIT(0, 0);
668 /*----------------------------------------------------------------
669 * acx100_clean_tx_desc
672 * Arguments:
674 * Returns:
676 * Side effects:
678 * Call context:
680 * STATUS:
682 * Comment:
683 * This function probably resets the txdescs' status when the ACX100
684 * signals the TX done IRQ (txdescs have been processed), starting with
685 * the pool index of the descriptor which we would use next,
686 * in order to make sure that we can be as fast as possible
687 * in filling new txdescs.
688 * Oops, now we have our own index, so everytime we get called we know
689 * where the next packet to be cleaned is.
690 * Hmm, still need to loop through the whole ring buffer now,
691 * since we lost sync for some reason when ping flooding or so...
692 * (somehow we don't get the IRQ for acx100_clean_tx_desc any more when
693 * too many packets are being sent!)
694 * FIXME: currently we only process one packet, but this gets out of
695 * sync for some reason when ping flooding, so we need to loop,
696 * but the previous smart loop implementation causes the ping latency
697 * to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
698 * Dunno what to do :-\
700 *----------------------------------------------------------------*/
702 void acx100_clean_tx_desc(wlandevice_t *wlandev)
704 TIWLAN_DC *pDc = &wlandev->dc;
705 txdesc_t *pTxDesc;
706 UINT finger, watch;
707 unsigned long flags;
709 FN_ENTER;
711 acx100_log_txbuffer(pDc);
712 acxlog(L_BUF, "cleaning up Tx bufs from %d\n", pDc->tx_tail);
714 spin_lock_irqsave(&tx_lock, flags);
716 finger = pDc->tx_tail;
717 watch = finger;
719 do {
720 pTxDesc = &pDc->pTxDescQPool[finger];
722 /* check if txdesc is marked as "Tx finished" and "owned" */
723 if ((pTxDesc->Ctl & DESC_CTL_DONE) == DESC_CTL_DONE) {
725 acxlog(L_BUF, "cleaning %d\n", finger);
727 if (pTxDesc->error != 0) {
728 char *err;
730 switch(pTxDesc->error) {
731 case 0x10:
732 err = "MSDU lifetime timeout? - change 'iwconfig retry lifetime XXX'";
733 break;
734 case 0x20:
735 err = "maybe distance too high? - change 'iwconfig txpower XXX'";
736 break;
737 default:
738 err = "unknown error";
739 break;
741 acxlog(L_STD, "Tx error occurred (error 0x%02X)!! (%s)\n", pTxDesc->error, err);
742 wlandev->stats.tx_carrier_errors++;
743 wlandev->stats.tx_errors++;
746 /* free it */
747 pTxDesc->Ctl = DESC_CTL_FREE;
749 wlandev->TxQueueFree++;
751 if ((wlandev->TxQueueFree >= MINFREE_TX + 3)
752 && (wlandev->status == ISTATUS_4_ASSOCIATED)
753 && (netif_queue_stopped(wlandev->netdev)))
755 /* FIXME: if construct is ugly:
756 * should have functions acx100_stop_queue
757 * etc. which set flag wlandev->tx_stopped
758 * to be checked here. */
759 acxlog(L_XFER, "wake queue (avail. Tx desc %d).\n", wlandev->TxQueueFree);
760 netif_wake_queue(wlandev->netdev);
763 else
764 break;
766 /* update pointer for descr to be cleaned next */
767 finger = (finger + 1) % pDc->tx_pool_count;
768 } while (watch != finger);
770 /* remember last position */
771 pDc->tx_tail = finger;
773 spin_unlock_irqrestore(&tx_lock, flags);
775 FN_EXIT(0, 0);
776 return;
778 /*----------------------------------------------------------------
779 * acx100_rxmonitor
782 * Arguments:
784 * Returns:
786 * Side effects:
788 * Call context:
790 * STATUS:
792 * Comment:
794 *----------------------------------------------------------------*/
796 void acx100_rxmonitor(wlandevice_t * wlandev, struct rxbuffer *buf)
798 unsigned long *data = (unsigned long *)buf;
799 unsigned int packet_len = data[0] & 0xFFF;
800 int sig_strength = (data[1] >> 16) & 0xFF;
801 int sig_quality = (data[1] >> 24) & 0xFF;
802 p80211msg_lnxind_wlansniffrm_t *msg;
804 int payload_offset = 0;
805 unsigned int skb_len;
806 struct sk_buff *skb;
807 void *datap;
809 FN_ENTER;
811 if (!(wlandev->rx_config_1 & RX_CFG1_PLUS_ADDIT_HDR))
813 printk("rx_config_1 misses RX_CFG1_PLUS_ADDIT_HDR\n");
814 FN_EXIT(0, 0);
815 return;
818 if (wlandev->rx_config_1 & RX_CFG1_PLUS_ADDIT_HDR)
820 payload_offset += 3*4; /* status words */
821 packet_len += 3*4; /* length is w/o status */
824 if (wlandev->rx_config_1 & RX_CFG1_INCLUDE_ADDIT_HDR)
825 payload_offset += 4; /* phy header */
827 /* we are in big luck: the acx100 doesn't modify any of the fields */
828 /* in the 802.11-frame. just pass this packet into the PF_PACKET- */
829 /* subsystem. yeah. */
831 skb_len = packet_len - payload_offset;
833 if (wlandev->netdev->type == ARPHRD_IEEE80211_PRISM)
834 skb_len += sizeof(p80211msg_lnxind_wlansniffrm_t);
836 /* sanity check */
837 if (skb_len > (WLAN_HDR_A4_LEN + WLAN_DATA_MAXLEN + WLAN_CRC_LEN))
839 printk("monitor mode panic: oversized frame!\n");
840 FN_EXIT(0, 0);
841 return;
844 /* allocate skb */
845 if ( (skb = dev_alloc_skb(skb_len)) == NULL)
847 printk("alloc_skb failed trying to allocate %d bytes\n", skb_len);
848 FN_EXIT(0, 0);
849 return;
852 skb_put(skb, skb_len);
854 /* when in raw 802.11 mode, just copy frame as-is */
855 if (wlandev->netdev->type == ARPHRD_IEEE80211)
856 datap = skb->data;
857 else /* otherwise, emulate prism header */
859 msg = (p80211msg_lnxind_wlansniffrm_t*)skb->data;
860 datap = msg + 1;
862 msg->msgcode = DIDmsg_lnxind_wlansniffrm;
863 msg->msglen = sizeof(p80211msg_lnxind_wlansniffrm_t);
864 strcpy(msg->devname, wlandev->netdev->name);
866 msg->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
867 msg->hosttime.status = 0;
868 msg->hosttime.len = 4;
869 msg->hosttime.data = jiffies;
871 msg->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
872 msg->mactime.status = 0;
873 msg->mactime.len = 4;
874 msg->mactime.data = data[2];
876 msg->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
877 msg->channel.status = P80211ENUM_msgitem_status_no_value;
878 msg->channel.len = 4;
879 msg->channel.data = 0;
881 msg->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
882 msg->rssi.status = P80211ENUM_msgitem_status_no_value;
883 msg->rssi.len = 4;
884 msg->rssi.data = 0;
886 msg->sq.did = DIDmsg_lnxind_wlansniffrm_sq;
887 msg->sq.status = P80211ENUM_msgitem_status_no_value;
888 msg->sq.len = 4;
889 msg->sq.data = 0;
891 msg->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
892 msg->signal.status = 0;
893 msg->signal.len = 4;
894 msg->signal.data = sig_quality;
896 msg->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
897 msg->noise.status = 0;
898 msg->noise.len = 4;
899 msg->noise.data = sig_strength;
901 msg->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
902 msg->rate.status = P80211ENUM_msgitem_status_no_value;
903 msg->rate.len = 4;
904 msg->rate.data = 0;
906 msg->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
907 msg->istx.status = 0;
908 msg->istx.len = 4;
909 msg->istx.data = P80211ENUM_truth_false;
911 skb_len -= sizeof(p80211msg_lnxind_wlansniffrm_t);
913 msg->frmlen.did = DIDmsg_lnxind_wlansniffrm_signal;
914 msg->frmlen.status = 0;
915 msg->frmlen.len = 4;
916 msg->frmlen.data = skb_len;
919 memcpy(datap, ((unsigned char*)buf)+payload_offset, skb_len);
921 skb->dev = wlandev->netdev;
922 skb->dev->last_rx = jiffies;
924 skb->mac.raw = skb->data;
925 skb->ip_summed = CHECKSUM_NONE;
926 skb->pkt_type = PACKET_OTHERHOST;
927 skb->protocol = htons(ETH_P_80211_RAW);
929 wlandev->stats.rx_packets++;
930 wlandev->stats.rx_bytes += skb->len;
932 netif_rx(skb);
933 FN_EXIT(0, 0);
936 /*----------------------------------------------------------------
937 * acx100_log_rxbuffer
940 * Arguments:
942 * Returns:
944 * Side effects:
946 * Call context:
948 * STATUS:
950 * Comment:
952 *----------------------------------------------------------------*/
954 void acx100_log_rxbuffer(TIWLAN_DC *pDc)
956 unsigned int i;
957 struct rxhostdescriptor *pDesc;
959 FN_ENTER;
960 for (i = 0; i < pDc->rx_pool_count; i++)
962 pDesc = &pDc->pRxHostDescQPool[i];
963 #if (WLAN_HOSTIF==WLAN_USB)
964 acxlog(L_DEBUG,"rxbuf %d Ctl=%X val0x14=%X\n",i,pDesc->Ctl,pDesc->val0x14);
965 #endif
966 if ((pDesc->Ctl & DESC_CTL_FREE) && (pDesc->val0x14 < 0))
967 acxlog(L_BUF, "rxbuf %d full\n", i);
969 FN_EXIT(0, 0);
972 /*------------------------------------------------------------------------------
973 * acx100_process_rx_desc
975 * RX path top level entry point called directly and only from the IRQ handler
977 * Arguments:
979 * Returns:
981 * Side effects:
983 * Call context: Hard IRQ
985 * STATUS:
987 * Comment:
989 *----------------------------------------------------------------------------*/
990 void acx100_process_rx_desc(wlandevice_t *wlandev)
992 struct rxhostdescriptor *RxPool;
993 TIWLAN_DC *pDc;
994 struct rxhostdescriptor *pDesc;
995 UINT16 buf_len;
996 unsigned long flags;
997 int curr_idx;
998 unsigned int count = 0;
999 p80211_hdr_t *buf;
1001 FN_ENTER;
1003 pDc = &wlandev->dc;
1004 acx100_log_rxbuffer(pDc);
1006 /* there used to be entry count code here, but because this function is called
1007 * by the interrupt handler, we are sure that this will only be entered once
1008 * because the kernel locks the interrupt handler */
1010 RxPool = pDc->pRxHostDescQPool;
1012 /* First, have a loop to determine the first descriptor that's
1013 * full, just in case there's a mismatch between our current
1014 * rx_tail and the full descriptor we're supposed to handle. */
1015 spin_lock_irqsave(&rx_lock, flags);
1016 do {
1017 count++;
1018 if (count > pDc->rx_pool_count)
1019 { /* hmm, no luck: all descriptors empty, bail out */
1020 spin_unlock_irqrestore(&rx_lock, flags);
1021 FN_EXIT(0, 0);
1022 return;
1024 curr_idx = pDc->rx_tail;
1025 pDesc = &RxPool[pDc->rx_tail];
1026 pDc->rx_tail = (pDc->rx_tail + 1) % pDc->rx_pool_count;
1028 /* "pDesc->val0x14 < 0" is there to check whether MSB
1029 * is set or not */
1030 while (!((pDesc->Ctl & DESC_CTL_FREE) && (pDesc->val0x14 < 0))); /* check whether descriptor full, advance to next one if not */
1031 spin_unlock_irqrestore(&rx_lock, flags);
1033 while (1)
1035 acxlog(L_BUF, "%s: using curr_idx %d, rx_tail is now %d\n", __func__, curr_idx, pDc->rx_tail);
1037 buf = (p80211_hdr_t *)&pDesc->data->buf;
1038 if (wlandev->rx_config_1 & RX_CFG1_INCLUDE_ADDIT_HDR) {
1039 /* take into account additional header in front of packet */
1040 buf = (p80211_hdr_t*)((UINT8*)buf + 4);
1043 buf_len = pDesc->data->status & 0xfff; /* somelength */
1044 if ((WLAN_GET_FC_FSTYPE(buf->a3.fc) != WLAN_FSTYPE_BEACON)
1045 || (debug & L_XFER_BEACON))
1046 acxlog(L_XFER|L_DATA, "Rx pkt %02d (%s): time %lu, len %i, signal %d, SNR %d, mode %d, status %d\n",
1047 curr_idx,
1048 acx100_get_packet_type_string(buf->a3.fc),
1049 pDesc->data->time,
1050 buf_len,
1051 pDesc->data->level,
1052 pDesc->data->snr,
1053 wlandev->mode,
1054 wlandev->status);
1056 /* I tried to figure out how to map these levels to dBm
1057 * values, but for the life of me I really didn't
1058 * manage to get it. Either these values are not meant to
1059 * be expressed in dBm, or it's some pretty complicated
1060 * calculation. */
1061 wlandev->wstats.qual.level = pDesc->data->level * 100 / 255;
1062 wlandev->wstats.qual.noise = pDesc->data->snr * 100 / 255;
1063 wlandev->wstats.qual.qual =
1064 (wlandev->wstats.qual.noise <= 100) ?
1065 100 - wlandev->wstats.qual.noise : 0;
1066 wlandev->wstats.qual.updated = 7;
1068 if (wlandev->monitor) {
1069 acx100_rxmonitor(wlandev, pDesc->data);
1070 } else if (buf_len >= 14) {
1071 acx100_rx_ieee802_11_frame(wlandev, pDesc);
1072 } else {
1073 acxlog(L_DEBUG | L_XFER | L_DATA,
1074 "NOT receiving packet (%s): size too small (%d)\n",
1075 acx100_get_packet_type_string(buf->a3.fc), buf_len);
1078 pDesc->Ctl &= ~DESC_CTL_FREE; /* Host no longer owns this */
1079 pDesc->val0x14 = 0;
1081 /* ok, descriptor is handled, now check the next descriptor */
1082 spin_lock_irqsave(&rx_lock, flags);
1083 curr_idx = pDc->rx_tail;
1084 pDesc = &RxPool[pDc->rx_tail];
1086 /* if next descriptor is empty, then bail out */
1087 if (!((pDesc->Ctl & DESC_CTL_FREE) && (pDesc->val0x14 < 0)))
1089 spin_unlock_irqrestore(&rx_lock, flags);
1090 break;
1092 else
1094 pDc->rx_tail = (pDc->rx_tail + 1) % pDc->rx_pool_count;
1095 spin_unlock_irqrestore(&rx_lock, flags);
1098 FN_EXIT(0, 0);
1101 /*----------------------------------------------------------------
1102 * acx100_create_tx_host_desc_queue
1105 * Arguments:
1107 * Returns:
1109 * Side effects:
1111 * Call context:
1113 * STATUS:
1115 * Comment:
1117 *----------------------------------------------------------------*/
1119 int acx100_create_tx_host_desc_queue(TIWLAN_DC * pDc)
1121 wlandevice_t *wlandev;
1123 UINT i;
1124 UINT align_offs;
1125 UINT alignment;
1127 struct framehdr *frame_hdr;
1128 struct framehdr *frame_hdr_phy;
1130 UINT8 *frame_payload;
1131 UINT8 *frame_payload_phy;
1133 struct txhostdescriptor *host_desc;
1134 struct txhostdescriptor *host_desc_phy;
1136 FN_ENTER;
1138 wlandev = pDc->wlandev;
1140 /* allocate TX header pool */
1141 pDc->FrameHdrQPoolSize = (wlandev->TxQueueNo * sizeof(struct framehdr));
1142 #if (WLAN_HOSTIF!=WLAN_USB)
1143 if (!(pDc->pFrameHdrQPool =
1144 pci_alloc_consistent(0, pDc->FrameHdrQPoolSize, &pDc->FrameHdrQPoolPhyAddr))) {
1145 acxlog(L_BINSTD, "pDc->pFrameHdrQPool memory allocation error\n");
1146 FN_EXIT(1, 2);
1147 return 2;
1149 acxlog(L_BINDEBUG, "pDc->pFrameHdrQPool = 0x%8x\n", (UINT) pDc->pFrameHdrQPool);
1150 acxlog(L_BINDEBUG, "pDc->pFrameHdrQPoolPhyAddr = 0x%8x\n", (UINT) pDc->FrameHdrQPoolPhyAddr);
1151 #else
1152 if ((pDc->pFrameHdrQPool=kmalloc(pDc->FrameHdrQPoolSize,GFP_KERNEL))==NULL) {
1153 acxlog(L_STD,"pDc->pFrameHdrQPool memory allocation error\n");
1154 FN_EXIT(1,2);
1155 return(2);
1157 memset(pDc->pFrameHdrQPool,0,pDc->FrameHdrQPoolSize);
1158 #endif
1160 /* allocate TX payload pool */
1161 pDc->TxBufferPoolSize = wlandev->TxQueueNo*2 * (WLAN_MAX_ETHFRM_LEN - WLAN_ETHHDR_LEN);
1162 #if (WLAN_HOSTIF!=WLAN_USB)
1163 if (!(pDc->pTxBufferPool =
1164 pci_alloc_consistent(0, pDc->TxBufferPoolSize, &pDc->TxBufferPoolPhyAddr))) {
1165 acxlog(L_BINSTD, "pDc->pTxBufferPool memory allocation error\n");
1166 pci_free_consistent(0, pDc->FrameHdrQPoolSize,
1167 pDc->pFrameHdrQPool,
1168 pDc->FrameHdrQPoolPhyAddr);
1169 FN_EXIT(1, 2);
1170 return 2;
1172 acxlog(L_BINDEBUG, "pDc->TxBufferPool = 0x%8x\n", (UINT) pDc->pTxBufferPool);
1173 acxlog(L_BINDEBUG, "pDc->TxBufferPoolPhyAddr = 0x%8x\n", (UINT) pDc->TxBufferPoolPhyAddr);
1174 #else
1175 if ((pDc->pTxBufferPool=kmalloc(pDc->TxBufferPoolSize,GFP_KERNEL))==NULL) {
1176 acxlog(L_STD,"pDc->pTxBufferPool memory allocation error\n");
1177 kfree(pDc->pFrameHdrQPool);
1178 FN_EXIT(1,2);
1179 return(2);
1181 memset(pDc->pTxBufferPool,0,pDc->TxBufferPoolSize);
1182 #endif
1184 /* allocate the TX host descriptor queue pool */
1185 pDc->TxHostDescQPoolSize = wlandev->TxQueueNo*2 * sizeof(struct txhostdescriptor) + 3;
1186 #if (WLAN_HOSTIF!=WLAN_USB)
1187 if (!(pDc->pTxHostDescQPool =
1188 pci_alloc_consistent(0, pDc->TxHostDescQPoolSize,
1189 &pDc->TxHostDescQPoolPhyAddr))) {
1190 acxlog(L_BINSTD, "Failed to allocate shared memory for TxHostDesc queue\n");
1191 pci_free_consistent(0, pDc->FrameHdrQPoolSize,
1192 pDc->pFrameHdrQPool,
1193 pDc->FrameHdrQPoolPhyAddr);
1194 pci_free_consistent(0, pDc->TxBufferPoolSize,
1195 pDc->pTxBufferPool,
1196 pDc->TxBufferPoolPhyAddr);
1197 FN_EXIT(1, 2);
1198 return 2;
1200 acxlog(L_BINDEBUG, "pDc->pTxHostDescQPool = 0x%8x\n", (UINT) pDc->pTxHostDescQPool);
1201 acxlog(L_BINDEBUG, "pDc->TxHostDescQPoolPhyAddr = 0x%8x\n", pDc->TxHostDescQPoolPhyAddr);
1202 #else
1203 if ((pDc->pTxHostDescQPool=kmalloc(pDc->TxHostDescQPoolSize,GFP_KERNEL))==NULL) {
1204 acxlog(L_STD,"Failed to allocate memory for TxHostDesc queue\n");
1205 kfree(pDc->pFrameHdrQPool);
1206 kfree(pDc->pTxBufferPool);
1207 FN_EXIT(1,2);
1208 return(2);
1210 memset(pDc->pTxHostDescQPool,0,pDc->TxHostDescQPoolSize);
1211 #endif
1213 #if (WLAN_HOSTIF!=WLAN_USB)
1214 /* check for proper alignment of TX host descriptor pool */
1215 alignment = (UINT) pDc->pTxHostDescQPool & 3;
1216 if (alignment) {
1217 acxlog(L_BINSTD, "%s: TxHostDescQPool not aligned properly\n", __func__);
1218 align_offs = 4 - alignment;
1219 } else {
1220 align_offs = 0;
1223 host_desc = (struct txhostdescriptor *) ((UINT8 *) pDc->pTxHostDescQPool + align_offs);
1224 host_desc_phy = (struct txhostdescriptor *) ((UINT8 *) pDc->TxHostDescQPoolPhyAddr + align_offs);
1225 #else
1226 host_desc=(struct txhostdescriptor *)pDc->pTxHostDescQPool;
1227 #endif
1228 frame_hdr = (struct framehdr *) pDc->pFrameHdrQPool;
1229 #if (WLAN_HOSTIF!=WLAN_USB)
1230 frame_hdr_phy = (struct framehdr *) pDc->FrameHdrQPoolPhyAddr;
1231 #endif
1233 frame_payload = (UINT8 *) pDc->pTxBufferPool;
1234 #if (WLAN_HOSTIF!=WLAN_USB)
1235 frame_payload_phy = (UINT8 *) pDc->TxBufferPoolPhyAddr;
1236 #endif
1238 for (i = 0; i < wlandev->TxQueueNo*2 - 1; i++)
1240 if (!(i & 1)) {
1241 #if (WLAN_HOSTIF!=WLAN_USB)
1242 host_desc->data_phy = (UINT8 *) frame_hdr_phy;
1243 #endif
1244 host_desc->data = (UINT8 *) frame_hdr;
1245 #if (WLAN_HOSTIF!=WLAN_USB)
1246 frame_hdr_phy++;
1247 #endif
1248 frame_hdr++;
1249 #if (WLAN_HOSTIF!=WLAN_USB)
1250 host_desc->val0x10 = (struct txhostdescriptor *)((UINT8 *) host_desc_phy + sizeof(struct txhostdescriptor));
1251 #endif
1252 } else {
1253 #if (WLAN_HOSTIF!=WLAN_USB)
1254 host_desc->data_phy = (UINT8 *) frame_payload_phy;
1255 #endif
1256 host_desc->data = (UINT8 *) frame_payload;
1257 #if (WLAN_HOSTIF!=WLAN_USB)
1258 frame_payload_phy += WLAN_MAX_ETHFRM_LEN - WLAN_ETHHDR_LEN;
1259 #endif
1260 frame_payload += WLAN_MAX_ETHFRM_LEN - WLAN_ETHHDR_LEN;
1262 host_desc->val0x10 = NULL;
1265 host_desc->Ctl |= DESC_CTL_FREE;
1266 #if (WLAN_HOSTIF!=WLAN_USB)
1267 host_desc->desc_phy = host_desc_phy;
1268 host_desc->desc_phy_next = (struct txhostdescriptor *)((UINT8 *) host_desc_phy + sizeof(struct txhostdescriptor));
1269 #endif
1271 host_desc++;
1272 #if (WLAN_HOSTIF!=WLAN_USB)
1273 host_desc_phy++;
1274 #endif
1276 #if (WLAN_HOSTIF!=WLAN_USB)
1277 host_desc->data_phy = (UINT8 *) frame_payload_phy;
1278 #endif
1279 host_desc->data = (UINT8 *) frame_payload;
1280 host_desc->val0x10 = 0;
1282 host_desc->Ctl |= DESC_CTL_FREE;
1283 #if (WLAN_HOSTIF!=WLAN_USB)
1284 host_desc->desc_phy = host_desc_phy;
1285 host_desc->desc_phy_next = (struct txhostdescriptor *)((UINT8 *) pDc->TxHostDescQPoolPhyAddr + align_offs);
1286 #endif
1288 FN_EXIT(0, 0);
1289 return 0;
1292 /*----------------------------------------------------------------
1293 * acx100_create_rx_host_desc_queue
1296 * Arguments:
1298 * Returns:
1300 * Side effects:
1302 * Call context:
1304 * STATUS:
1306 * Comment:
1308 *----------------------------------------------------------------*/
1310 int acx100_create_rx_host_desc_queue(TIWLAN_DC * pDc)
1312 wlandevice_t *wlandev;
1314 UINT i;
1315 UINT align_offs;
1316 UINT alignment;
1318 struct rxbuffer *data;
1319 struct rxbuffer *data_phy;
1321 struct rxhostdescriptor *host_desc;
1322 struct rxhostdescriptor *host_desc_phy;
1324 int result = 0;
1326 FN_ENTER;
1328 wlandev = pDc->wlandev;
1330 /* allocate the RX host descriptor queue pool */
1331 pDc->RxHostDescQPoolSize = (wlandev->RxQueueNo * sizeof(struct rxhostdescriptor)) + 0x3;
1332 #if (WLAN_HOSTIF!=WLAN_USB)
1333 if ((pDc->pRxHostDescQPool =
1334 pci_alloc_consistent(0, pDc->RxHostDescQPoolSize,
1335 &pDc->RxHostDescQPoolPhyAddr)) == NULL) {
1336 acxlog(L_BINSTD,
1337 "Failed to allocate shared memory for RxHostDesc queue\n");
1338 result = 2;
1339 goto fail;
1341 #else
1342 if ((pDc->pRxHostDescQPool = kmalloc(pDc->RxHostDescQPoolSize,GFP_KERNEL))==NULL) {
1343 acxlog(L_STD,"Failed to allocate memory for RxHostDesc queue\n");
1344 result=2;
1345 goto fail;
1347 memset(pDc->pRxHostDescQPool,0,pDc->RxHostDescQPoolSize);
1348 #endif
1350 /* allocate RX buffer pool */
1351 pDc->RxBufferPoolSize = (wlandev->RxQueueNo * sizeof(struct rxbuffer));
1352 #if (WLAN_HOSTIF!=WLAN_USB)
1353 if ((pDc->pRxBufferPool =
1354 pci_alloc_consistent(0, pDc->RxBufferPoolSize,
1355 &pDc->RxBufferPoolPhyAddr)) == NULL) {
1356 acxlog(L_BINSTD, "Failed to allocate shared memory for Rx buffer\n");
1357 pci_free_consistent(0, pDc->RxHostDescQPoolSize,
1358 pDc->pRxHostDescQPool,
1359 pDc->RxHostDescQPoolPhyAddr);
1360 result = 2;
1361 goto fail;
1363 #else
1364 if ((pDc->pRxBufferPool = kmalloc(pDc->RxBufferPoolSize,GFP_KERNEL))==NULL) {
1365 acxlog(L_STD,"Failed to allocate memory for Rx buffer\n");
1366 result=2;
1367 goto fail;
1369 memset(pDc->pRxBufferPool,0,pDc->RxBufferPoolSize);
1370 #endif
1372 acxlog(L_BINDEBUG, "pDc->pRxHostDescQPool = 0x%8x\n", (UINT) pDc->pRxHostDescQPool);
1373 #if (WLAN_HOSTIF!=WLAN_USB)
1374 acxlog(L_BINDEBUG, "pDc->RxHostDescQPoolPhyAddr = 0x%8x\n", (UINT) pDc->RxHostDescQPoolPhyAddr);
1375 #endif
1376 acxlog(L_BINDEBUG, "pDc->pRxBufferPool = 0x%8x\n", (UINT) pDc->pRxBufferPool);
1377 #if (WLAN_HOSTIF!=WLAN_USB)
1378 acxlog(L_BINDEBUG, "pDc->RxBufferPoolPhyAddr = 0x%8x\n", (UINT) pDc->RxBufferPoolPhyAddr);
1379 #endif
1380 #if (WLAN_HOSTIF!=WLAN_USB)
1381 /* check for proper alignment of RX host descriptor pool */
1382 if ((alignment = ((UINT) pDc->pRxHostDescQPool) & 3)) {
1383 acxlog(L_BINSTD, "acx100_create_rx_host_desc_queue: RxHostDescQPool not aligned properly\n");
1384 align_offs = 4 - alignment;
1385 } else {
1386 align_offs = 0;
1389 host_desc = (struct rxhostdescriptor *) ((UINT8 *) pDc->pRxHostDescQPool + align_offs);
1390 host_desc_phy = (struct rxhostdescriptor *) ((UINT8 *) pDc->RxHostDescQPoolPhyAddr + align_offs);
1392 wlandev->RxHostDescPoolStart = host_desc_phy;
1393 #else
1394 host_desc = (struct rxhostdescriptor *)pDc->pRxHostDescQPool;
1395 #endif
1396 data = (struct rxbuffer *) pDc->pRxBufferPool;
1397 #if (WLAN_HOSTIF!=WLAN_USB)
1398 data_phy = (struct rxbuffer *) pDc->RxBufferPoolPhyAddr;
1399 #endif
1401 if (wlandev->RxQueueNo != 1) {
1402 for (i = 0; i < wlandev->RxQueueNo - 1; i++) {
1403 host_desc->data = data;
1404 #if (WLAN_HOSTIF!=WLAN_USB)
1405 host_desc->data_phy = data_phy;
1406 #endif
1407 host_desc->length = sizeof(struct rxbuffer);
1409 data++;
1410 #if (WLAN_HOSTIF!=WLAN_USB)
1411 data_phy++;
1412 #endif
1414 /* FIXME: what do these mean ? */
1415 host_desc->val0x28 = 2;
1416 host_desc->Ctl &= ~0x80;
1417 #if (WLAN_HOSTIF!=WLAN_USB)
1418 host_desc->desc_phy = host_desc_phy;
1419 host_desc->desc_phy_next = (struct rxhostdescriptor *)((UINT8 *) host_desc_phy + sizeof(struct rxhostdescriptor));
1420 #endif
1421 host_desc++;
1422 #if (WLAN_HOSTIF!=WLAN_USB)
1423 host_desc_phy++;
1424 #endif
1427 host_desc->data = data;
1428 #if (WLAN_HOSTIF!=WLAN_USB)
1429 host_desc->data_phy = data_phy;
1430 #endif
1431 host_desc->length = sizeof(struct rxbuffer);
1433 host_desc->val0x28 = 2;
1434 host_desc->Ctl &= 0xff7f;
1435 #if (WLAN_HOSTIF!=WLAN_USB)
1436 host_desc->desc_phy = host_desc_phy;
1437 host_desc->desc_phy_next = (struct rxhostdescriptor *)((UINT8 *) pDc->RxHostDescQPoolPhyAddr + align_offs);
1438 #endif
1439 result = 0;
1440 fail:
1441 FN_EXIT(1, result);
1442 return result;
1445 /*----------------------------------------------------------------
1446 * acx100_create_tx_desc_queue
1449 * Arguments:
1451 * Returns:
1453 * Side effects:
1455 * Call context:
1457 * STATUS:
1459 * Comment:
1461 *----------------------------------------------------------------*/
1463 void acx100_create_tx_desc_queue(TIWLAN_DC * pDc)
1465 wlandevice_t *wlandev;
1467 UINT32 mem_offs;
1468 UINT32 i;
1470 struct txdescriptor *tx_desc;
1471 struct txhostdescriptor *tx_hostdesc;
1473 UINT hostmemptr;
1475 FN_ENTER;
1477 wlandev = pDc->wlandev;
1478 pDc->tx_pool_count = wlandev->TxQueueNo;
1479 #if (WLAN_HOSTIF!=WLAN_USB)
1481 pDc->pTxDescQPool = (struct txdescriptor *) (wlandev->iobase2 +
1482 pDc->ui32ACXTxQueueStart);
1484 acxlog(L_BINDEBUG, "wlandev->iobase2 = 0x%08x\n", wlandev->iobase2);
1485 acxlog(L_BINDEBUG, "pDc->ui32ACXTxQueueStart = 0x%08x\n",
1486 pDc->ui32ACXTxQueueStart);
1487 acxlog(L_BINDEBUG, "pDc->pTxDescQPool = 0x%08x\n",
1488 (UINT) pDc->pTxDescQPool);
1489 #endif
1490 wlandev->TxQueueFree = wlandev->TxQueueNo;
1491 pDc->tx_head = 0;
1492 pDc->tx_tail = 0;
1493 #if (WLAN_HOSTIF!=WLAN_USB)
1494 mem_offs = pDc->ui32ACXTxQueueStart;
1495 tx_desc = pDc->pTxDescQPool;
1497 hostmemptr = pDc->TxHostDescQPoolPhyAddr;
1498 tx_hostdesc = (struct txhostdescriptor *) pDc->pTxHostDescQPool;
1500 /* loop over complete send pool */
1501 for (i = 0; i < pDc->tx_pool_count; i++) {
1502 memset(tx_desc, 0, sizeof(struct txdescriptor));
1503 /* pointer to hostdesc memory */
1504 tx_desc->HostMemPtr = hostmemptr;
1505 /* initialise ctl */
1506 tx_desc->Ctl = DESC_CTL_INIT;
1507 tx_desc->Ctl2 = 0;
1508 /* point to next txdesc */
1509 tx_desc->pNextDesc = mem_offs + sizeof(struct txdescriptor);
1510 /* pointer to first txhostdesc */
1511 tx_desc->host_desc = tx_hostdesc;
1513 /* reserve two (hdr desc and payload desc) */
1514 tx_hostdesc += 2;
1515 hostmemptr += 2 * sizeof(struct txhostdescriptor);
1516 /* go to the next */
1517 mem_offs += sizeof(struct txdescriptor);
1518 tx_desc++;
1520 /* go to the last one */
1521 tx_desc--;
1522 /* and point to the first making it a ring buffer */
1523 tx_desc->pNextDesc = pDc->ui32ACXTxQueueStart;
1524 #endif
1525 FN_EXIT(0, 0);
1528 /*----------------------------------------------------------------
1529 * acx100_create_rx_desc_queue
1532 * Arguments:
1534 * Returns:
1536 * Side effects:
1538 * Call context:
1540 * STATUS:
1542 * Comment:
1544 *----------------------------------------------------------------*/
1546 void acx100_create_rx_desc_queue(TIWLAN_DC * pDc)
1548 wlandevice_t *wlandev;
1550 UINT32 mem_offs;
1551 UINT32 i;
1553 struct rxdescriptor *rx_desc;
1555 FN_ENTER;
1556 wlandev = pDc->wlandev;
1557 #if (WLAN_HOSTIF!=WLAN_USB)
1558 /* WHY IS IT "TxQueueNo" ? */
1559 pDc->pRxDescQPool = (struct rxdescriptor *) ((wlandev->TxQueueNo * sizeof(struct txdescriptor)) + (UINT8 *) pDc->pTxDescQPool);
1560 #endif
1561 pDc->rx_pool_count = wlandev->RxQueueNo;
1562 pDc->rx_tail = 0;
1563 #if (WLAN_HOSTIF!=WLAN_USB)
1564 mem_offs = pDc->ui32ACXRxQueueStart;
1565 rx_desc = (struct rxdescriptor *) pDc->pRxDescQPool;
1567 /* loop over complete receive pool */
1568 for (i = 0; i < pDc->rx_pool_count; i++) {
1569 memset(rx_desc, 0, sizeof(struct rxdescriptor));
1571 /* FIXME: what is this? is it a ctl field ? */
1572 rx_desc->val0x28 = 0xc;
1574 /* point to next rxdesc */
1575 rx_desc->pNextDesc = mem_offs + sizeof(struct rxdescriptor); // next rxdesc pNextDesc
1577 /* go to the next */
1578 mem_offs += sizeof(struct rxdescriptor);
1579 rx_desc++;
1581 /* go to the last one */
1582 rx_desc--;
1583 /* and point to the first making it a ring buffer */
1584 rx_desc->pNextDesc = pDc->ui32ACXRxQueueStart;
1585 #endif
1586 FN_EXIT(0, 0);
1589 /*----------------------------------------------------------------
1590 * acx100_free_desc_queues
1592 * Releases the queues that have been allocated, the
1593 * others have been initialised to NULL in acx100.c so this
1594 * function can be used if only part of the queues where
1595 * allocated.
1597 * Arguments:
1599 * Returns:
1601 * Side effects:
1603 * Call context:
1605 * STATUS:
1607 * Comment:
1609 *----------------------------------------------------------------*/
1611 void acx100_free_desc_queues(TIWLAN_DC * pDc)
1613 FN_ENTER;
1614 if (pDc->pRxHostDescQPool) {
1615 pci_free_consistent(0,
1616 pDc->TxHostDescQPoolSize,
1617 pDc->pTxHostDescQPool,
1618 pDc->TxHostDescQPoolPhyAddr);
1619 pDc->pTxHostDescQPool = NULL;
1620 pDc->TxHostDescQPoolSize = 0;
1622 if (pDc->pFrameHdrQPool) {
1623 pci_free_consistent(0, pDc->FrameHdrQPoolSize,
1624 pDc->pFrameHdrQPool,
1625 pDc->FrameHdrQPoolPhyAddr);
1626 pDc->pFrameHdrQPool = NULL;
1627 pDc->FrameHdrQPoolSize = 0;
1629 if (pDc->pTxBufferPool) {
1630 pci_free_consistent(0, pDc->TxBufferPoolSize,
1631 pDc->pTxBufferPool,
1632 pDc->TxBufferPoolPhyAddr);
1633 pDc->pTxBufferPool = NULL;
1634 pDc->TxBufferPoolSize = 0;
1637 pDc->pTxDescQPool = NULL;
1638 pDc->tx_pool_count = 0;
1640 if (pDc->pRxHostDescQPool) {
1641 pci_free_consistent(0, pDc->RxHostDescQPoolSize,
1642 pDc->pRxHostDescQPool,
1643 pDc->RxHostDescQPoolPhyAddr);
1644 pDc->pRxHostDescQPool = NULL;
1645 pDc->RxHostDescQPoolSize = 0;
1647 if (pDc->pRxBufferPool) {
1648 pci_free_consistent(0, pDc->RxBufferPoolSize,
1649 pDc->pRxBufferPool,
1650 pDc->RxBufferPoolPhyAddr);
1651 pDc->pRxBufferPool = NULL;
1652 pDc->RxBufferPoolSize = 0;
1655 pDc->pRxDescQPool = NULL;
1656 pDc->rx_pool_count = 0;
1657 FN_EXIT(0, 0);
1660 /*----------------------------------------------------------------
1661 * acx100_init_memory_pools
1664 * Arguments:
1666 * Returns:
1668 * Side effects:
1670 * Call context:
1672 * STATUS:
1674 * Comment:
1675 * FIXME: This function still needs a cleanup
1676 *----------------------------------------------------------------*/
1678 int acx100_init_memory_pools(wlandevice_t * wlandev, memmap_t * mmt)
1680 #if (WLAN_HOSTIF==WLAN_USB)
1681 UINT TotalMemoryBlocks; // var_40
1682 acx100usb_memmap_t *map;
1683 /* FIXME: is a memmap_t with ConfigWrite3 union type in it.
1684 * This ConfigWrite3 is specially made for this function
1685 * because vali and valj need to be UINT16's. Or am I
1686 * completely wrong
1687 * Actually, I think there needs to be 2 memmaps in this function- one
1688 * for the sizewrite and one for optionswrite
1690 struct {
1691 UINT16 val0x0;
1692 UINT16 val0x2;
1693 UINT16 size; // val0x4
1694 /* UINT16 val0x6;
1695 UINT32 val0x8; It's size only 4 + ACX100RID_BLOCK_SIZE_LEN = 6
1696 UINT32 val0xc; */
1697 } MemoryBlockSize; // var_3c
1699 struct {
1700 UINT16 rid;
1701 UINT16 length;
1702 UINT DMA_config; // val0x4
1703 struct rxhostdescriptor *val0x8;
1704 UINT val0xc; /* rx memory */
1705 UINT val0x10; /* tx memory */
1706 UINT16 TxBlockNum; // val0x14
1707 UINT16 RxBlockNum; // val0x16;
1708 } MemoryConfigOption; // var_2c
1710 FN_ENTER;
1711 map = (acx100usb_memmap_t *)mmt;
1712 #ifdef ACX_DEBUG
1713 acxlog(L_DEBUG,"Dump of Memory Map:\n");
1714 acx100usb_dump_bytes(mmt,44);
1715 #endif
1716 /* Let's see if we can follow this:
1717 first we select our memory block size (which I think is
1718 completely arbitrary) */
1719 MemoryBlockSize.size = wlandev->memblocksize;
1721 /* Then we alert the card to our decision of block size */
1722 if (!acx100_configure(wlandev, &MemoryBlockSize, ACX100_RID_BLOCK_SIZE)) {
1723 acxlog(L_BINSTD, "Ctl: MemoryBlockSizeWrite failed\n");
1724 return 0;
1727 /* We figure out how many total blocks we can create, using
1728 the block size we chose, and the beginning and ending
1729 memory pointers. IE. end-start/size */
1730 TotalMemoryBlocks = (map->PoolEnd-map->PoolStart) / wlandev->memblocksize;
1731 acxlog(L_DEBUG,"TotalMemoryBlocks=%d (%d bytes)\n",TotalMemoryBlocks,TotalMemoryBlocks*wlandev->memblocksize);
1733 /* This one I have no idea on */
1734 /* block-transfer=0x20000
1735 * indirect descriptors=0x10000
1737 MemoryConfigOption.DMA_config = 0x20000; //dma config
1738 /* Declare start of the Rx host pool */
1739 MemoryConfigOption.val0x8 = wlandev->RxHostDescPoolStart;
1741 /* 50% of the allotment of memory blocks go to tx descriptors */
1742 MemoryConfigOption.TxBlockNum = TotalMemoryBlocks / 2;
1743 /* and 50% go to the rx descriptors */
1744 MemoryConfigOption.RxBlockNum = TotalMemoryBlocks - MemoryConfigOption.TxBlockNum;
1746 /* in this block, we save the information we gleaned from the
1747 card into our wlandevice structure; # of tx desc blocks */
1748 wlandev->val0x24fc = MemoryConfigOption.TxBlockNum;
1749 /* # of rx desc blocks */
1750 wlandev->val0x24e4 = MemoryConfigOption.RxBlockNum;
1751 /* size of the tx and rx descriptor queues */
1752 wlandev->val0x2500 = MemoryConfigOption.TxBlockNum * wlandev->memblocksize;
1753 wlandev->val0x24e8 = MemoryConfigOption.RxBlockNum * wlandev->memblocksize;
1755 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1756 MemoryConfigOption.val0xc = (map->PoolStart + 0x1f) & 0xffffffe0;
1757 /* align the rx descriptor queue to units of 0x20 and offset it
1758 by the tx descriptor queue */
1759 MemoryConfigOption.val0x10 =
1760 (0x1f + map->PoolStart + wlandev->val0x2500) & 0xffffffe0;
1762 /* alert the device to our decision */
1763 if (!acx100_configure(wlandev, &MemoryConfigOption, ACX100_RID_MEMORY_CONFIG_OPTIONS)) {
1764 acxlog(L_DEBUG,"%s: configure memory config options failed!", __func__);
1765 return 0;
1767 /* and tell the device to kick it into gear */
1768 if (!acx100_issue_cmd(wlandev, ACX100_CMD_INIT_MEMORY, 0, 0, 5000)) {
1769 acxlog(L_DEBUG,"%s: init memory failed!", __func__);
1770 return 0;
1772 FN_EXIT(0, 0);
1773 return(1);
1774 #else
1775 /* the default PCI code */
1776 UINT TotalMemoryBlocks; // var_40
1777 /* FIXME: is a memmap_t with ConfigWrite3 union type in it.
1778 * This ConfigWrite3 is specially made for this function
1779 * because vali and valj need to be UINT16's. Or am I
1780 * completely wrong
1781 * Actually, I think there needs to be 2 memmaps in this function- one
1782 * for the sizewrite and one for optionswrite
1784 struct {
1785 UINT16 val0x0;
1786 UINT16 val0x2;
1787 UINT16 size; // val0x4
1788 /* UINT16 val0x6;
1789 UINT32 val0x8; It's size only 4 + ACX100RID_BLOCK_SIZE_LEN = 6
1790 UINT32 val0xc; */
1791 } MemoryBlockSize; // var_3c
1793 struct {
1794 UINT16 val0x0;
1795 UINT16 val0x2;
1796 UINT DMA_config; // val0x4
1797 struct rxhostdescriptor *val0x8;
1798 UINT val0xc;
1799 UINT val0x10;
1800 UINT16 TxBlockNum; // val0x14
1801 UINT16 RxBlockNum; // val0x16;
1802 } MemoryConfigOption; // var_2c
1804 FN_ENTER;
1806 /* Let's see if we can follow this:
1807 first we select our memory block size (which I think is
1808 completely arbitrary) */
1809 MemoryBlockSize.size = wlandev->memblocksize;
1811 /* Then we alert the card to our decision of block size */
1812 if (!acx100_configure(wlandev, &MemoryBlockSize, ACX100_RID_BLOCK_SIZE)) {
1813 acxlog(L_BINSTD, "Ctl: MemoryBlockSizeWrite failed\n");
1814 FN_EXIT(1, 0);
1815 return 0;
1818 /* We figure out how many total blocks we can create, using
1819 the block size we chose, and the beginning and ending
1820 memory pointers. IE. end-start/size */
1821 TotalMemoryBlocks = (mmt->m.cw2.val0x28 - mmt->m.cw2.vali) / wlandev->memblocksize;
1823 /* This one I have no idea on */
1824 MemoryConfigOption.DMA_config = 0x30000; //dma config
1825 /* Declare start of the Rx host pool */
1826 MemoryConfigOption.val0x8 = wlandev->RxHostDescPoolStart;
1828 /* 50% of the allotment of memory blocks go to tx descriptors */
1829 MemoryConfigOption.TxBlockNum = TotalMemoryBlocks / 2;
1830 /* and 50% go to the rx descriptors */
1831 MemoryConfigOption.RxBlockNum = TotalMemoryBlocks - MemoryConfigOption.TxBlockNum;
1833 /* in this block, we save the information we gleaned from the
1834 card into our wlandevice structure; # of tx desc blocks */
1835 wlandev->val0x24fc = MemoryConfigOption.TxBlockNum;
1836 /* # of rx desc blocks */
1837 wlandev->val0x24e4 = MemoryConfigOption.RxBlockNum;
1838 /* size of the tx and rx descriptor queues */
1839 wlandev->val0x2500 = MemoryConfigOption.TxBlockNum * wlandev->memblocksize;
1840 wlandev->val0x24e8 = MemoryConfigOption.RxBlockNum * wlandev->memblocksize;
1842 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1843 MemoryConfigOption.val0xc = (mmt->m.cw2.vali + 0x1f) & 0xffffffe0;
1844 /* align the rx descriptor queue to units of 0x20 and offset it
1845 by the tx descriptor queue */
1846 MemoryConfigOption.val0x10 =
1847 (0x1f + mmt->m.cw2.vali + wlandev->val0x2500) & 0xffffffe0;
1849 /* alert the device to our decision */
1850 if (!acx100_configure(wlandev, &MemoryConfigOption, ACX100_RID_MEMORY_CONFIG_OPTIONS)) {
1851 FN_EXIT(1, 0);
1852 return 0;
1854 /* and tell the device to kick it into gear */
1855 if (!acx100_issue_cmd(wlandev, ACX100_CMD_INIT_MEMORY, 0, 0, 5000)) {
1856 FN_EXIT(1, 0);
1857 return 0;
1860 FN_EXIT(1, 1);
1861 return 1;
1862 #endif
1865 /*----------------------------------------------------------------
1866 * acx100_get_tx_desc
1869 * Arguments:
1871 * Returns:
1873 * Side effects:
1875 * Call context:
1877 * STATUS:
1879 * Comment:
1881 *----------------------------------------------------------------*/
1883 struct txdescriptor *acx100_get_tx_desc(wlandevice_t * wlandev)
1885 struct TIWLAN_DC * pDc = &wlandev->dc;
1886 struct txdescriptor *tx_desc;
1887 unsigned long flags;
1889 FN_ENTER;
1891 spin_lock_irqsave(&tx_lock, flags);
1893 tx_desc = &pDc->pTxDescQPool[pDc->tx_head];
1895 if ((tx_desc->Ctl & DESC_CTL_FREE) == 0) {
1896 /* whoops, descr at current index is not free, so probably
1897 * ring buffer already full */
1898 tx_desc = NULL;
1899 goto error;
1902 wlandev->TxQueueFree--;
1903 acxlog(L_BUF, "got Tx desc %d, %d remain.\n", pDc->tx_head, wlandev->TxQueueFree);
1906 * This comment is probably not entirely correct, needs further discussion
1907 * (restored commented-out code below to fix Tx ring buffer overflow,
1908 * since it's much better to have a slightly less efficiently used ring
1909 * buffer rather than one which easily overflows):
1911 * This doesn't do anything other than limit our maximum number of
1912 * buffers used at a single time (we might as well just declare
1913 * MINFREE_TX less descriptors when we open up.) We should just let it
1914 * slide here, and back off MINFREE_TX in acx100_clean_tx_desc, when given the
1915 * opportunity to let the queue start back up.
1917 if (wlandev->TxQueueFree < MINFREE_TX)
1919 acxlog(L_XFER, "stop queue (avail. Tx desc %d).\n", wlandev->TxQueueFree);
1920 netif_stop_queue(wlandev->netdev);
1923 /* returning current descriptor, so advance to next free one */
1924 pDc->tx_head = (pDc->tx_head + 1) % pDc->tx_pool_count;
1925 error:
1926 spin_unlock_irqrestore(&tx_lock, flags);
1928 FN_EXIT(0, (int)tx_desc);
1929 return tx_desc;
1932 static char type_string[32]; /* I *really* don't care that this is static,
1933 so don't complain, else... ;-) */
1935 /*----------------------------------------------------------------
1936 * acx100_get_packet_type_string
1939 * Arguments:
1941 * Returns:
1943 * Side effects:
1945 * Call context:
1947 * STATUS:
1949 * Comment:
1951 *----------------------------------------------------------------*/
1953 char *acx100_get_packet_type_string(UINT16 fc)
1955 char *ftype = "UNKNOWN", *fstype = "UNKNOWN";
1957 FN_ENTER;
1958 switch (WLAN_GET_FC_FTYPE(fc)) {
1959 case WLAN_FTYPE_MGMT:
1960 ftype = "MGMT";
1961 switch (WLAN_GET_FC_FSTYPE(fc)) {
1962 case WLAN_FSTYPE_ASSOCREQ:
1963 fstype = "AssocReq";
1964 break;
1965 case WLAN_FSTYPE_ASSOCRESP:
1966 fstype = "AssocResp";
1967 break;
1968 case WLAN_FSTYPE_REASSOCREQ:
1969 fstype = "ReassocReq";
1970 break;
1971 case WLAN_FSTYPE_REASSOCRESP:
1972 fstype = "ReassocResp";
1973 break;
1974 case WLAN_FSTYPE_PROBEREQ:
1975 fstype = "ProbeReq";
1976 break;
1977 case WLAN_FSTYPE_PROBERESP:
1978 fstype = "ProbeResp";
1979 break;
1980 case WLAN_FSTYPE_BEACON:
1981 fstype = "Beacon";
1982 break;
1983 case WLAN_FSTYPE_ATIM:
1984 fstype = "ATIM";
1985 break;
1986 case WLAN_FSTYPE_DISASSOC:
1987 fstype = "Disassoc";
1988 break;
1989 case WLAN_FSTYPE_AUTHEN:
1990 fstype = "Authen";
1991 break;
1992 case WLAN_FSTYPE_DEAUTHEN:
1993 fstype = "Deauthen";
1994 break;
1996 break;
1997 case WLAN_FTYPE_CTL:
1998 ftype = "CTL";
1999 switch (WLAN_GET_FC_FSTYPE(fc)) {
2000 case WLAN_FSTYPE_PSPOLL:
2001 fstype = "PSPoll";
2002 break;
2003 case WLAN_FSTYPE_RTS:
2004 fstype = "RTS";
2005 break;
2006 case WLAN_FSTYPE_CTS:
2007 fstype = "CTS";
2008 break;
2009 case WLAN_FSTYPE_ACK:
2010 fstype = "Ack";
2011 break;
2012 case WLAN_FSTYPE_CFEND:
2013 fstype = "CFEnd";
2014 break;
2015 case WLAN_FSTYPE_CFENDCFACK:
2016 fstype = "CFEndCFAck";
2017 break;
2019 break;
2020 case WLAN_FTYPE_DATA:
2021 ftype = "DATA";
2022 switch (WLAN_GET_FC_FSTYPE(fc)) {
2023 case WLAN_FSTYPE_DATAONLY:
2024 fstype = "DataOnly";
2025 break;
2026 case WLAN_FSTYPE_DATA_CFACK:
2027 fstype = "Data CFAck";
2028 break;
2029 case WLAN_FSTYPE_DATA_CFPOLL:
2030 fstype = "Data CFPoll";
2031 break;
2032 case WLAN_FSTYPE_DATA_CFACK_CFPOLL:
2033 fstype = "Data CFAck/CFPoll";
2034 break;
2035 case WLAN_FSTYPE_NULL:
2036 fstype = "Null";
2037 break;
2038 case WLAN_FSTYPE_CFACK:
2039 fstype = "CFAck";
2040 break;
2041 case WLAN_FSTYPE_CFPOLL:
2042 fstype = "CFPoll";
2043 break;
2044 case WLAN_FSTYPE_CFACK_CFPOLL:
2045 fstype = "CFAck/CFPoll";
2046 break;
2048 break;
2050 sprintf(type_string, "%s/%s", ftype, fstype);
2051 FN_EXIT(1, (int)type_string);
2052 return type_string;