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
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>
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 */
72 #include <p80211hdr.h>
73 #include <p80211mgmt.h>
74 #include <acx100_conv.h>
76 #include <p80211types.h>
77 #include <acx100_helper.h>
78 #include <acx100_helper2.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)
99 #if (WLAN_HOSTIF==WLAN_USB)
100 extern void acx100usb_dump_bytes(void *,int);
105 /*----------------------------------------------------------------
121 *----------------------------------------------------------------*/
123 void acx100_enable_irq(wlandevice_t
* wlandev
)
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);
133 /*----------------------------------------------------------------
149 *----------------------------------------------------------------*/
151 void acx100_disable_irq(wlandevice_t
* wlandev
)
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);
161 /*----------------------------------------------------------------
162 * acx100_create_dma_regions
177 *----------------------------------------------------------------*/
179 int acx100_create_dma_regions(wlandevice_t
* wlandev
)
182 /* FIXME: way too big to reside on the stack */
191 struct TIWLAN_DC
*pDc
;
195 spin_lock_init(&rx_lock
);
196 spin_lock_init(&tx_lock
);
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");
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
;
221 /* sets the beginning of the tx descriptor queue */
222 pDc
->ui32ACXTxQueueStart
= MemMap
.queue_start
;
223 qcfg
.TxQueueStart
= pDc
->ui32ACXTxQueueStart
;
225 #if (WLAN_HOSTIF==WLAN_USB)
226 qcfg
.valk
= TXBUFFERNO
;
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
;
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");
247 if (acx100_create_tx_host_desc_queue(pDc
)) {
248 acxlog(L_BINSTD
, "acx100_create_tx_host_desc_queue returns error\n");
251 if (acx100_create_rx_host_desc_queue(pDc
)) {
252 acxlog(L_BINSTD
, "acx100_create_rx_host_desc_queue returns error\n");
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");
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");
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)
276 acxlog(L_DEBUG
,"Memory map before configure:\n");
277 acx100usb_dump_bytes(&MemMap
,44);
281 if (!acx100_configure(wlandev
, &MemMap
, ACX100_RID_MEMORY_MAP
)) {
282 acxlog(L_BINSTD
, "ctlMemoryMapWrite returns error\n");
286 if (!acx100_init_memory_pools(wlandev
, (memmap_t
*) &MemMap
)) {
287 acxlog(L_BINSTD
, "acx100_init_memory_pools returns error\n");
291 #if THIS_IS_BOGUS_ISNT_IT
292 acx100_set_defaults(wlandev
);
299 acx100_free_desc_queues(pDc
);
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
{
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
;
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 */
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 */
366 } __WLAN_ATTRIB_PACK__ memconf
;
368 /* FIXME: way too big to reside on the stack */
377 struct TIWLAN_DC
*pDc
;
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");
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
;
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
;
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) */
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) {
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
);
452 wlandev
->TxQueueNo
= TXBUFFERNO
;
453 wlandev
->RxQueueNo
= RXBUFFERNO
;
455 /* uhoh, hope this is correct-> BusMaster Indirect Memory Organization */
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");
475 if (acx100_create_rx_host_desc_queue(pDc
)) {
476 acxlog(L_BINSTD
, "acx100_create_rx_host_desc_queue returns error\n");
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");
489 #if THIS_IS_BOGUS_ISNT_IT
490 acx100_set_defaults(wlandev
);
497 acx100_free_desc_queues(pDc
);
507 /*----------------------------------------------------------------
508 * acx100_delete_dma_region
523 *----------------------------------------------------------------*/
525 int acx100_delete_dma_region(wlandevice_t
* wlandev
)
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);
534 acx100_free_desc_queues(&wlandev
->dc
);
540 /*----------------------------------------------------------------
556 *----------------------------------------------------------------*/
558 void acx100_dma_tx_data(wlandevice_t
*wlandev
, struct txdescriptor
*tx_desc
)
560 struct txhostdescriptor
*header
;
561 struct txhostdescriptor
*payload
;
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
;
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 */
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
,
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
);
634 /*----------------------------------------------------------------
635 * acx100_log_txbuffer
650 *----------------------------------------------------------------*/
652 void acx100_log_txbuffer(TIWLAN_DC
*pDc
)
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
);
668 /*----------------------------------------------------------------
669 * acx100_clean_tx_desc
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
;
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
;
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) {
730 switch(pTxDesc
->error
) {
732 err
= "MSDU lifetime timeout? - change 'iwconfig retry lifetime XXX'";
735 err
= "maybe distance too high? - change 'iwconfig txpower XXX'";
738 err
= "unknown error";
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
++;
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
);
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
);
778 /*----------------------------------------------------------------
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
;
811 if (!(wlandev
->rx_config_1
& RX_CFG1_PLUS_ADDIT_HDR
))
813 printk("rx_config_1 misses RX_CFG1_PLUS_ADDIT_HDR\n");
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
);
837 if (skb_len
> (WLAN_HDR_A4_LEN
+ WLAN_DATA_MAXLEN
+ WLAN_CRC_LEN
))
839 printk("monitor mode panic: oversized frame!\n");
845 if ( (skb
= dev_alloc_skb(skb_len
)) == NULL
)
847 printk("alloc_skb failed trying to allocate %d bytes\n", skb_len
);
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
)
857 else /* otherwise, emulate prism header */
859 msg
= (p80211msg_lnxind_wlansniffrm_t
*)skb
->data
;
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
;
886 msg
->sq
.did
= DIDmsg_lnxind_wlansniffrm_sq
;
887 msg
->sq
.status
= P80211ENUM_msgitem_status_no_value
;
891 msg
->signal
.did
= DIDmsg_lnxind_wlansniffrm_signal
;
892 msg
->signal
.status
= 0;
894 msg
->signal
.data
= sig_quality
;
896 msg
->noise
.did
= DIDmsg_lnxind_wlansniffrm_noise
;
897 msg
->noise
.status
= 0;
899 msg
->noise
.data
= sig_strength
;
901 msg
->rate
.did
= DIDmsg_lnxind_wlansniffrm_rate
;
902 msg
->rate
.status
= P80211ENUM_msgitem_status_no_value
;
906 msg
->istx
.did
= DIDmsg_lnxind_wlansniffrm_istx
;
907 msg
->istx
.status
= 0;
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;
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
;
936 /*----------------------------------------------------------------
937 * acx100_log_rxbuffer
952 *----------------------------------------------------------------*/
954 void acx100_log_rxbuffer(TIWLAN_DC
*pDc
)
957 struct rxhostdescriptor
*pDesc
;
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
);
966 if ((pDesc
->Ctl
& DESC_CTL_FREE
) && (pDesc
->val0x14
< 0))
967 acxlog(L_BUF
, "rxbuf %d full\n", i
);
972 /*------------------------------------------------------------------------------
973 * acx100_process_rx_desc
975 * RX path top level entry point called directly and only from the IRQ handler
983 * Call context: Hard IRQ
989 *----------------------------------------------------------------------------*/
990 void acx100_process_rx_desc(wlandevice_t
*wlandev
)
992 struct rxhostdescriptor
*RxPool
;
994 struct rxhostdescriptor
*pDesc
;
998 unsigned int count
= 0;
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
);
1018 if (count
> pDc
->rx_pool_count
)
1019 { /* hmm, no luck: all descriptors empty, bail out */
1020 spin_unlock_irqrestore(&rx_lock
, flags
);
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
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
);
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",
1048 acx100_get_packet_type_string(buf
->a3
.fc
),
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
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
);
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 */
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
);
1094 pDc
->rx_tail
= (pDc
->rx_tail
+ 1) % pDc
->rx_pool_count
;
1095 spin_unlock_irqrestore(&rx_lock
, flags
);
1101 /*----------------------------------------------------------------
1102 * acx100_create_tx_host_desc_queue
1117 *----------------------------------------------------------------*/
1119 int acx100_create_tx_host_desc_queue(TIWLAN_DC
* pDc
)
1121 wlandevice_t
*wlandev
;
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
;
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");
1149 acxlog(L_BINDEBUG
, "pDc->pFrameHdrQPool = 0x%8x\n", (UINT
) pDc
->pFrameHdrQPool
);
1150 acxlog(L_BINDEBUG
, "pDc->pFrameHdrQPoolPhyAddr = 0x%8x\n", (UINT
) pDc
->FrameHdrQPoolPhyAddr
);
1152 if ((pDc
->pFrameHdrQPool
=kmalloc(pDc
->FrameHdrQPoolSize
,GFP_KERNEL
))==NULL
) {
1153 acxlog(L_STD
,"pDc->pFrameHdrQPool memory allocation error\n");
1157 memset(pDc
->pFrameHdrQPool
,0,pDc
->FrameHdrQPoolSize
);
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
);
1172 acxlog(L_BINDEBUG
, "pDc->TxBufferPool = 0x%8x\n", (UINT
) pDc
->pTxBufferPool
);
1173 acxlog(L_BINDEBUG
, "pDc->TxBufferPoolPhyAddr = 0x%8x\n", (UINT
) pDc
->TxBufferPoolPhyAddr
);
1175 if ((pDc
->pTxBufferPool
=kmalloc(pDc
->TxBufferPoolSize
,GFP_KERNEL
))==NULL
) {
1176 acxlog(L_STD
,"pDc->pTxBufferPool memory allocation error\n");
1177 kfree(pDc
->pFrameHdrQPool
);
1181 memset(pDc
->pTxBufferPool
,0,pDc
->TxBufferPoolSize
);
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
,
1196 pDc
->TxBufferPoolPhyAddr
);
1200 acxlog(L_BINDEBUG
, "pDc->pTxHostDescQPool = 0x%8x\n", (UINT
) pDc
->pTxHostDescQPool
);
1201 acxlog(L_BINDEBUG
, "pDc->TxHostDescQPoolPhyAddr = 0x%8x\n", pDc
->TxHostDescQPoolPhyAddr
);
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
);
1210 memset(pDc
->pTxHostDescQPool
,0,pDc
->TxHostDescQPoolSize
);
1213 #if (WLAN_HOSTIF!=WLAN_USB)
1214 /* check for proper alignment of TX host descriptor pool */
1215 alignment
= (UINT
) pDc
->pTxHostDescQPool
& 3;
1217 acxlog(L_BINSTD
, "%s: TxHostDescQPool not aligned properly\n", __func__
);
1218 align_offs
= 4 - alignment
;
1223 host_desc
= (struct txhostdescriptor
*) ((UINT8
*) pDc
->pTxHostDescQPool
+ align_offs
);
1224 host_desc_phy
= (struct txhostdescriptor
*) ((UINT8
*) pDc
->TxHostDescQPoolPhyAddr
+ align_offs
);
1226 host_desc
=(struct txhostdescriptor
*)pDc
->pTxHostDescQPool
;
1228 frame_hdr
= (struct framehdr
*) pDc
->pFrameHdrQPool
;
1229 #if (WLAN_HOSTIF!=WLAN_USB)
1230 frame_hdr_phy
= (struct framehdr
*) pDc
->FrameHdrQPoolPhyAddr
;
1233 frame_payload
= (UINT8
*) pDc
->pTxBufferPool
;
1234 #if (WLAN_HOSTIF!=WLAN_USB)
1235 frame_payload_phy
= (UINT8
*) pDc
->TxBufferPoolPhyAddr
;
1238 for (i
= 0; i
< wlandev
->TxQueueNo
*2 - 1; i
++)
1241 #if (WLAN_HOSTIF!=WLAN_USB)
1242 host_desc
->data_phy
= (UINT8
*) frame_hdr_phy
;
1244 host_desc
->data
= (UINT8
*) frame_hdr
;
1245 #if (WLAN_HOSTIF!=WLAN_USB)
1249 #if (WLAN_HOSTIF!=WLAN_USB)
1250 host_desc
->val0x10
= (struct txhostdescriptor
*)((UINT8
*) host_desc_phy
+ sizeof(struct txhostdescriptor
));
1253 #if (WLAN_HOSTIF!=WLAN_USB)
1254 host_desc
->data_phy
= (UINT8
*) frame_payload_phy
;
1256 host_desc
->data
= (UINT8
*) frame_payload
;
1257 #if (WLAN_HOSTIF!=WLAN_USB)
1258 frame_payload_phy
+= WLAN_MAX_ETHFRM_LEN
- WLAN_ETHHDR_LEN
;
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
));
1272 #if (WLAN_HOSTIF!=WLAN_USB)
1276 #if (WLAN_HOSTIF!=WLAN_USB)
1277 host_desc
->data_phy
= (UINT8
*) frame_payload_phy
;
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
);
1292 /*----------------------------------------------------------------
1293 * acx100_create_rx_host_desc_queue
1308 *----------------------------------------------------------------*/
1310 int acx100_create_rx_host_desc_queue(TIWLAN_DC
* pDc
)
1312 wlandevice_t
*wlandev
;
1318 struct rxbuffer
*data
;
1319 struct rxbuffer
*data_phy
;
1321 struct rxhostdescriptor
*host_desc
;
1322 struct rxhostdescriptor
*host_desc_phy
;
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
) {
1337 "Failed to allocate shared memory for RxHostDesc queue\n");
1342 if ((pDc
->pRxHostDescQPool
= kmalloc(pDc
->RxHostDescQPoolSize
,GFP_KERNEL
))==NULL
) {
1343 acxlog(L_STD
,"Failed to allocate memory for RxHostDesc queue\n");
1347 memset(pDc
->pRxHostDescQPool
,0,pDc
->RxHostDescQPoolSize
);
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
);
1364 if ((pDc
->pRxBufferPool
= kmalloc(pDc
->RxBufferPoolSize
,GFP_KERNEL
))==NULL
) {
1365 acxlog(L_STD
,"Failed to allocate memory for Rx buffer\n");
1369 memset(pDc
->pRxBufferPool
,0,pDc
->RxBufferPoolSize
);
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
);
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
);
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
;
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
;
1394 host_desc
= (struct rxhostdescriptor
*)pDc
->pRxHostDescQPool
;
1396 data
= (struct rxbuffer
*) pDc
->pRxBufferPool
;
1397 #if (WLAN_HOSTIF!=WLAN_USB)
1398 data_phy
= (struct rxbuffer
*) pDc
->RxBufferPoolPhyAddr
;
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
;
1407 host_desc
->length
= sizeof(struct rxbuffer
);
1410 #if (WLAN_HOSTIF!=WLAN_USB)
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
));
1422 #if (WLAN_HOSTIF!=WLAN_USB)
1427 host_desc
->data
= data
;
1428 #if (WLAN_HOSTIF!=WLAN_USB)
1429 host_desc
->data_phy
= data_phy
;
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
);
1445 /*----------------------------------------------------------------
1446 * acx100_create_tx_desc_queue
1461 *----------------------------------------------------------------*/
1463 void acx100_create_tx_desc_queue(TIWLAN_DC
* pDc
)
1465 wlandevice_t
*wlandev
;
1470 struct txdescriptor
*tx_desc
;
1471 struct txhostdescriptor
*tx_hostdesc
;
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
);
1490 wlandev
->TxQueueFree
= wlandev
->TxQueueNo
;
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
;
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) */
1515 hostmemptr
+= 2 * sizeof(struct txhostdescriptor
);
1516 /* go to the next */
1517 mem_offs
+= sizeof(struct txdescriptor
);
1520 /* go to the last one */
1522 /* and point to the first making it a ring buffer */
1523 tx_desc
->pNextDesc
= pDc
->ui32ACXTxQueueStart
;
1528 /*----------------------------------------------------------------
1529 * acx100_create_rx_desc_queue
1544 *----------------------------------------------------------------*/
1546 void acx100_create_rx_desc_queue(TIWLAN_DC
* pDc
)
1548 wlandevice_t
*wlandev
;
1553 struct rxdescriptor
*rx_desc
;
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
);
1561 pDc
->rx_pool_count
= wlandev
->RxQueueNo
;
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
);
1581 /* go to the last one */
1583 /* and point to the first making it a ring buffer */
1584 rx_desc
->pNextDesc
= pDc
->ui32ACXRxQueueStart
;
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
1609 *----------------------------------------------------------------*/
1611 void acx100_free_desc_queues(TIWLAN_DC
* pDc
)
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
,
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
,
1650 pDc
->RxBufferPoolPhyAddr
);
1651 pDc
->pRxBufferPool
= NULL
;
1652 pDc
->RxBufferPoolSize
= 0;
1655 pDc
->pRxDescQPool
= NULL
;
1656 pDc
->rx_pool_count
= 0;
1660 /*----------------------------------------------------------------
1661 * acx100_init_memory_pools
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
1687 * Actually, I think there needs to be 2 memmaps in this function- one
1688 * for the sizewrite and one for optionswrite
1693 UINT16 size
; // val0x4
1695 UINT32 val0x8; It's size only 4 + ACX100RID_BLOCK_SIZE_LEN = 6
1697 } MemoryBlockSize
; // var_3c
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
1711 map
= (acx100usb_memmap_t
*)mmt
;
1713 acxlog(L_DEBUG
,"Dump of Memory Map:\n");
1714 acx100usb_dump_bytes(mmt
,44);
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");
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__
);
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__
);
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
1781 * Actually, I think there needs to be 2 memmaps in this function- one
1782 * for the sizewrite and one for optionswrite
1787 UINT16 size
; // val0x4
1789 UINT32 val0x8; It's size only 4 + ACX100RID_BLOCK_SIZE_LEN = 6
1791 } MemoryBlockSize
; // var_3c
1796 UINT DMA_config
; // val0x4
1797 struct rxhostdescriptor
*val0x8
;
1800 UINT16 TxBlockNum
; // val0x14
1801 UINT16 RxBlockNum
; // val0x16;
1802 } MemoryConfigOption
; // var_2c
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");
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
)) {
1854 /* and tell the device to kick it into gear */
1855 if (!acx100_issue_cmd(wlandev
, ACX100_CMD_INIT_MEMORY
, 0, 0, 5000)) {
1865 /*----------------------------------------------------------------
1866 * acx100_get_tx_desc
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
;
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 */
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
;
1926 spin_unlock_irqrestore(&tx_lock
, flags
);
1928 FN_EXIT(0, (int)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
1951 *----------------------------------------------------------------*/
1953 char *acx100_get_packet_type_string(UINT16 fc
)
1955 char *ftype
= "UNKNOWN", *fstype
= "UNKNOWN";
1958 switch (WLAN_GET_FC_FTYPE(fc
)) {
1959 case WLAN_FTYPE_MGMT
:
1961 switch (WLAN_GET_FC_FSTYPE(fc
)) {
1962 case WLAN_FSTYPE_ASSOCREQ
:
1963 fstype
= "AssocReq";
1965 case WLAN_FSTYPE_ASSOCRESP
:
1966 fstype
= "AssocResp";
1968 case WLAN_FSTYPE_REASSOCREQ
:
1969 fstype
= "ReassocReq";
1971 case WLAN_FSTYPE_REASSOCRESP
:
1972 fstype
= "ReassocResp";
1974 case WLAN_FSTYPE_PROBEREQ
:
1975 fstype
= "ProbeReq";
1977 case WLAN_FSTYPE_PROBERESP
:
1978 fstype
= "ProbeResp";
1980 case WLAN_FSTYPE_BEACON
:
1983 case WLAN_FSTYPE_ATIM
:
1986 case WLAN_FSTYPE_DISASSOC
:
1987 fstype
= "Disassoc";
1989 case WLAN_FSTYPE_AUTHEN
:
1992 case WLAN_FSTYPE_DEAUTHEN
:
1993 fstype
= "Deauthen";
1997 case WLAN_FTYPE_CTL
:
1999 switch (WLAN_GET_FC_FSTYPE(fc
)) {
2000 case WLAN_FSTYPE_PSPOLL
:
2003 case WLAN_FSTYPE_RTS
:
2006 case WLAN_FSTYPE_CTS
:
2009 case WLAN_FSTYPE_ACK
:
2012 case WLAN_FSTYPE_CFEND
:
2015 case WLAN_FSTYPE_CFENDCFACK
:
2016 fstype
= "CFEndCFAck";
2020 case WLAN_FTYPE_DATA
:
2022 switch (WLAN_GET_FC_FSTYPE(fc
)) {
2023 case WLAN_FSTYPE_DATAONLY
:
2024 fstype
= "DataOnly";
2026 case WLAN_FSTYPE_DATA_CFACK
:
2027 fstype
= "Data CFAck";
2029 case WLAN_FSTYPE_DATA_CFPOLL
:
2030 fstype
= "Data CFPoll";
2032 case WLAN_FSTYPE_DATA_CFACK_CFPOLL
:
2033 fstype
= "Data CFAck/CFPoll";
2035 case WLAN_FSTYPE_NULL
:
2038 case WLAN_FSTYPE_CFACK
:
2041 case WLAN_FSTYPE_CFPOLL
:
2044 case WLAN_FSTYPE_CFACK_CFPOLL
:
2045 fstype
= "CFAck/CFPoll";
2050 sprintf(type_string
, "%s/%s", ftype
, fstype
);
2051 FN_EXIT(1, (int)type_string
);