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 qcfg
.valf1
=RXBUFFERNO
;
219 /* sets the beginning of the tx descriptor queue */
220 pDc
->ui32ACXTxQueueStart
= MemMap
.queue_start
;
221 qcfg
.TxQueueStart
= pDc
->ui32ACXTxQueueStart
;
223 qcfg
.valk
= TXBUFFERNO
;
225 /* sets the beginning of the rx descriptor queue */
226 pDc
->ui32ACXRxQueueStart
= wlandev
->TxQueueNo
* sizeof(struct txdescriptor
) + MemMap
.queue_start
;
227 qcfg
.RxQueueStart
= pDc
->ui32ACXRxQueueStart
;
230 /* sets the end of the rx descriptor queue */
231 qcfg
.QueueEnd
= wlandev
->RxQueueNo
* sizeof(struct rxdescriptor
) + pDc
->ui32ACXRxQueueStart
;
233 /* sets the beginning of the next queue */
234 qcfg
.QueueEnd2
= qcfg
.QueueEnd
+ 8;
236 acxlog(L_BINDEBUG
, "<== Initialize the Queue Indicator\n");
238 if (!acx100_configure_length(wlandev
, &qcfg
, ACX100_RID_QUEUE_CONFIG
, sizeof(QueueConfig_t
)-4)){ //0x14 + (qcfg.vale * 8))) {
239 acxlog(L_BINSTD
, "ctlQueueConfigurationWrite returns error\n");
243 if (acx100_create_tx_host_desc_queue(pDc
)) {
244 acxlog(L_BINSTD
, "acx100_create_tx_host_desc_queue returns error\n");
247 if (acx100_create_rx_host_desc_queue(pDc
)) {
248 acxlog(L_BINSTD
, "acx100_create_rx_host_desc_queue returns error\n");
251 acx100_create_tx_desc_queue(pDc
);
252 acx100_create_rx_desc_queue(pDc
);
253 if (!acx100_interrogate(wlandev
, &MemMap
, ACX100_RID_MEMORY_MAP
)) {
254 acxlog(L_BINSTD
, "Failed to read memory map\n");
258 #if (WLAN_HOSTIF==WLAN_USB)
259 acxlog(L_DEBUG
,"Memory Map before configure 1\n");
260 acx100usb_dump_bytes(&MemMap
,44);
262 if (!acx100_configure(wlandev
,&MemMap
,ACX100_RID_MEMORY_MAP
)) {
263 acxlog(L_BINSTD
,"Failed to write memory map\n");
268 /* FIXME: what does this do? name the fields */
269 /* start at least 4 bytes away from the end of the last pool */
270 MemMap
.val0x24
= (MemMap
.val0x20
+ 0x1F + 4) & 0xffffffe0;
271 #if (WLAN_HOSTIF==WLAN_USB)
273 acxlog(L_DEBUG
,"Memory map before configure:\n");
274 acx100usb_dump_bytes(&MemMap
,44);
278 if (!acx100_configure(wlandev
, &MemMap
, ACX100_RID_MEMORY_MAP
)) {
279 acxlog(L_BINSTD
, "ctlMemoryMapWrite returns error\n");
283 if (!acx100_init_memory_pools(wlandev
, (memmap_t
*) &MemMap
)) {
284 acxlog(L_BINSTD
, "acx100_init_memory_pools returns error\n");
288 #if THIS_IS_BOGUS_ISNT_IT
289 acx100_set_defaults(wlandev
);
296 acx100_free_desc_queues(pDc
);
302 /*----------------------------------------------------------------
303 * acx100_delete_dma_region
318 *----------------------------------------------------------------*/
320 int acx100_delete_dma_region(wlandevice_t
* wlandev
)
323 #if (WLAN_HOSTIF!=WLAN_USB)
324 acx100_write_reg16(wlandev
, wlandev
->io
[IO_ACX_ENABLE
], 0);
326 /* used to be a for loop 1000, do scheduled delay instead */
327 acx100_schedule(HZ
/ 10);
329 acx100_free_desc_queues(&wlandev
->dc
);
335 /*----------------------------------------------------------------
351 *----------------------------------------------------------------*/
353 void acx100_dma_tx_data(wlandevice_t
*wlandev
, struct txdescriptor
*tx_desc
)
355 struct txhostdescriptor
*header
;
356 struct txhostdescriptor
*payload
;
361 #if (WLAN_HOSTIF!=WLAN_USB)
362 /* header and payload are located in adjacent descriptors */
363 header
= tx_desc
->host_desc
;
364 payload
= tx_desc
->host_desc
+ 1;
366 tx_desc
->tx_time
= jiffies
;
368 tx_desc
->Ctl
|= wlandev
->preamble_flag
; /* set Preamble */
369 /* It seems as if the Preamble setting was actually REVERSED:
370 * bit 0 should most likely actually be ACTIVATED
371 * for Short Preamble, not the other way around as before!
372 * This caused many Tx error 0x20 errors with APs
373 * that don't support Long Preamble, since we were
374 * thinking we are setting Long Preamble, when in fact
375 * it was Short Preamble.
376 * The flag reversal theory has been sort of confirmed
377 * by throughput measurements:
378 * ~ 680K/s with flag disabled
379 * ~ 760K/s with flag enabled
382 /* set autodma and reclaim and 1st mpdu */
383 tx_desc
->Ctl
|= DESC_CTL_AUTODMA
| DESC_CTL_RECLAIM
| DESC_CTL_FIRST_MPDU
;
386 if (WLAN_GET_FC_FTYPE(((p80211_hdr_t
*)header
->data
)->a3
.fc
) == WLAN_FTYPE_MGMT
) {
387 tx_desc
->rate
= 20; /* 2Mbps for MGMT pkt compatibility */
389 tx_desc
->rate
= wlandev
->bitrateval
;
392 acxlog(L_XFER
| L_DATA
,
393 "Tx pkt (%s): len %i, hdr_len %i, pyld_len %i, mode %d, status %d\n",
394 acx100_get_packet_type_string(((p80211_hdr_t
*)header
->data
)->a3
.fc
),
395 tx_desc
->total_length
,
401 acxlog(L_DATA
, "802.11 header[%d]: ", header
->length
);
402 for (i
= 0; i
< header
->length
; i
++)
403 acxlog(L_DATA
, "%02x ", ((UINT8
*) header
->data
)[i
]);
404 acxlog(L_DATA
, "\n");
405 acxlog(L_DATA
, "802.11 payload[%d]: ", payload
->length
);
406 for (i
= 0; i
< payload
->length
; i
++)
407 acxlog(L_DATA
, "%02x ", ((UINT8
*) payload
->data
)[i
]);
408 acxlog(L_DATA
, "\n");
410 spin_lock_irqsave(&tx_lock
, flags
);
412 /* sets Ctl DESC_CTL_FREE to zero telling that the descriptors are now owned by the acx100 */
413 header
->Ctl
&= (UINT16
) ~DESC_CTL_FREE
;
414 payload
->Ctl
&= (UINT16
) ~DESC_CTL_FREE
;
415 tx_desc
->Ctl
&= (UINT16
) ~DESC_CTL_FREE
;
417 acx100_write_reg16(wlandev
, wlandev
->io
[IO_ACX_INT_TRIG
], 0x4);
419 spin_unlock_irqrestore(&tx_lock
, flags
);
424 /*----------------------------------------------------------------
425 * acx100_log_txbuffer
440 *----------------------------------------------------------------*/
442 void acx100_log_txbuffer(TIWLAN_DC
*pDc
)
448 for (i
= 0; i
< pDc
->tx_pool_count
; i
++)
450 pTxDesc
= &pDc
->pTxDescQPool
[i
];
452 if ((pTxDesc
->Ctl
& DESC_CTL_DONE
) == DESC_CTL_DONE
)
453 acxlog(L_BUF
, "txbuf %d done\n", i
);
458 /*----------------------------------------------------------------
459 * acx100_clean_tx_desc
473 * This function probably resets the txdescs' status when the ACX100
474 * signals the TX done IRQ (txdescs have been processed), starting with
475 * the pool index of the descriptor which we would use next,
476 * in order to make sure that we can be as fast as possible
477 * in filling new txdescs.
478 * Oops, now we have our own index, so everytime we get called we know
479 * where the next packet to be cleaned is.
480 * Hmm, still need to loop through the whole ring buffer now,
481 * since we lost sync for some reason when ping flooding or so...
482 * (somehow we don't get the IRQ for acx100_clean_tx_desc any more when
483 * too many packets are being sent!)
484 * FIXME: currently we only process one packet, but this gets out of
485 * sync for some reason when ping flooding, so we need to loop,
486 * but the previous smart loop implementation causes the ping latency
487 * to rise dramatically (~3000 ms), at least on CardBus PheeNet WL-0022.
488 * Dunno what to do :-\
490 *----------------------------------------------------------------*/
492 void acx100_clean_tx_desc(wlandevice_t
*wlandev
)
494 TIWLAN_DC
*pDc
= &wlandev
->dc
;
501 acx100_log_txbuffer(pDc
);
502 acxlog(L_BUF
, "cleaning up Tx bufs from %d\n", pDc
->tx_tail
);
504 spin_lock_irqsave(&tx_lock
, flags
);
506 finger
= pDc
->tx_tail
;
510 pTxDesc
= &pDc
->pTxDescQPool
[finger
];
512 /* check if txdesc is marked as "Tx finished" and "owned" */
513 if ((pTxDesc
->Ctl
& DESC_CTL_DONE
) == DESC_CTL_DONE
) {
515 acxlog(L_BUF
, "cleaning %d\n", finger
);
517 if (pTxDesc
->error
!= 0) {
520 switch(pTxDesc
->error
) {
522 err
= "MSDU lifetime timeout? - change 'iwconfig retry lifetime XXX'";
525 err
= "maybe distance too high? - change 'iwconfig txpower XXX'";
528 err
= "unknown error";
531 acxlog(L_STD
, "Tx error occurred (error 0x%02X)!! (%s)\n", pTxDesc
->error
, err
);
532 wlandev
->stats
.tx_carrier_errors
++;
533 wlandev
->stats
.tx_errors
++;
537 pTxDesc
->Ctl
= DESC_CTL_FREE
;
539 wlandev
->TxQueueFree
++;
541 if ((wlandev
->TxQueueFree
>= MINFREE_TX
+ 3)
542 && (wlandev
->status
== ISTATUS_4_ASSOCIATED
)
543 && (netif_queue_stopped(wlandev
->netdev
)))
545 /* FIXME: if construct is ugly:
546 * should have functions acx100_stop_queue
547 * etc. which set flag wlandev->tx_stopped
548 * to be checked here. */
549 acxlog(L_XFER
, "wake queue (avail. Tx desc %d).\n", wlandev
->TxQueueFree
);
550 netif_wake_queue(wlandev
->netdev
);
556 /* update pointer for descr to be cleaned next */
557 finger
= (finger
+ 1) % pDc
->tx_pool_count
;
558 } while (watch
!= finger
);
560 /* remember last position */
561 pDc
->tx_tail
= finger
;
563 spin_unlock_irqrestore(&tx_lock
, flags
);
568 /*----------------------------------------------------------------
584 *----------------------------------------------------------------*/
586 void acx100_rxmonitor(wlandevice_t
* wlandev
, struct rxbuffer
*buf
)
588 unsigned long *data
= (unsigned long *)buf
;
589 unsigned int packet_len
= data
[0] & 0xFFF;
590 int sig_strength
= (data
[1] >> 16) & 0xFF;
591 int sig_quality
= (data
[1] >> 24) & 0xFF;
592 p80211msg_lnxind_wlansniffrm_t
*msg
;
594 int payload_offset
= 0;
595 unsigned int skb_len
;
601 if (!(wlandev
->rx_config_1
& RX_CFG1_PLUS_ADDIT_HDR
))
603 printk("rx_config_1 misses RX_CFG1_PLUS_ADDIT_HDR\n");
608 if (wlandev
->rx_config_1
& RX_CFG1_PLUS_ADDIT_HDR
)
610 payload_offset
+= 3*4; /* status words */
611 packet_len
+= 3*4; /* length is w/o status */
614 if (wlandev
->rx_config_1
& RX_CFG1_INCLUDE_ADDIT_HDR
)
615 payload_offset
+= 4; /* phy header */
617 /* we are in big luck: the acx100 doesn't modify any of the fields */
618 /* in the 802.11-frame. just pass this packet into the PF_PACKET- */
619 /* subsystem. yeah. */
621 skb_len
= packet_len
- payload_offset
;
623 if (wlandev
->netdev
->type
== ARPHRD_IEEE80211_PRISM
)
624 skb_len
+= sizeof(p80211msg_lnxind_wlansniffrm_t
);
627 if (skb_len
> (WLAN_HDR_A4_LEN
+ WLAN_DATA_MAXLEN
+ WLAN_CRC_LEN
))
629 printk("monitor mode panic: oversized frame!\n");
635 if ( (skb
= dev_alloc_skb(skb_len
)) == NULL
)
637 printk("alloc_skb failed trying to allocate %d bytes\n", skb_len
);
642 skb_put(skb
, skb_len
);
644 /* when in raw 802.11 mode, just copy frame as-is */
645 if (wlandev
->netdev
->type
== ARPHRD_IEEE80211
)
647 else /* otherwise, emulate prism header */
649 msg
= (p80211msg_lnxind_wlansniffrm_t
*)skb
->data
;
652 msg
->msgcode
= DIDmsg_lnxind_wlansniffrm
;
653 msg
->msglen
= sizeof(p80211msg_lnxind_wlansniffrm_t
);
654 strcpy(msg
->devname
, wlandev
->netdev
->name
);
656 msg
->hosttime
.did
= DIDmsg_lnxind_wlansniffrm_hosttime
;
657 msg
->hosttime
.status
= 0;
658 msg
->hosttime
.len
= 4;
659 msg
->hosttime
.data
= jiffies
;
661 msg
->mactime
.did
= DIDmsg_lnxind_wlansniffrm_mactime
;
662 msg
->mactime
.status
= 0;
663 msg
->mactime
.len
= 4;
664 msg
->mactime
.data
= data
[2];
666 msg
->channel
.did
= DIDmsg_lnxind_wlansniffrm_channel
;
667 msg
->channel
.status
= P80211ENUM_msgitem_status_no_value
;
668 msg
->channel
.len
= 4;
669 msg
->channel
.data
= 0;
671 msg
->rssi
.did
= DIDmsg_lnxind_wlansniffrm_rssi
;
672 msg
->rssi
.status
= P80211ENUM_msgitem_status_no_value
;
676 msg
->sq
.did
= DIDmsg_lnxind_wlansniffrm_sq
;
677 msg
->sq
.status
= P80211ENUM_msgitem_status_no_value
;
681 msg
->signal
.did
= DIDmsg_lnxind_wlansniffrm_signal
;
682 msg
->signal
.status
= 0;
684 msg
->signal
.data
= sig_quality
;
686 msg
->noise
.did
= DIDmsg_lnxind_wlansniffrm_noise
;
687 msg
->noise
.status
= 0;
689 msg
->noise
.data
= sig_strength
;
691 msg
->rate
.did
= DIDmsg_lnxind_wlansniffrm_rate
;
692 msg
->rate
.status
= P80211ENUM_msgitem_status_no_value
;
696 msg
->istx
.did
= DIDmsg_lnxind_wlansniffrm_istx
;
697 msg
->istx
.status
= 0;
699 msg
->istx
.data
= P80211ENUM_truth_false
;
701 skb_len
-= sizeof(p80211msg_lnxind_wlansniffrm_t
);
703 msg
->frmlen
.did
= DIDmsg_lnxind_wlansniffrm_signal
;
704 msg
->frmlen
.status
= 0;
706 msg
->frmlen
.data
= skb_len
;
709 memcpy(datap
, ((unsigned char*)buf
)+payload_offset
, skb_len
);
711 skb
->dev
= wlandev
->netdev
;
712 skb
->dev
->last_rx
= jiffies
;
714 skb
->mac
.raw
= skb
->data
;
715 skb
->ip_summed
= CHECKSUM_NONE
;
716 skb
->pkt_type
= PACKET_OTHERHOST
;
717 skb
->protocol
= htons(ETH_P_80211_RAW
);
719 wlandev
->stats
.rx_packets
++;
720 wlandev
->stats
.rx_bytes
+= skb
->len
;
726 /*----------------------------------------------------------------
727 * acx100_log_rxbuffer
742 *----------------------------------------------------------------*/
744 void acx100_log_rxbuffer(TIWLAN_DC
*pDc
)
747 struct rxhostdescriptor
*pDesc
;
750 for (i
= 0; i
< pDc
->rx_pool_count
; i
++)
752 pDesc
= &pDc
->pRxHostDescQPool
[i
];
753 #if (WLAN_HOSTIF==WLAN_USB)
754 acxlog(L_DEBUG
,"rxbuf %d Ctl=%X val0x14=%X\n",i
,pDesc
->Ctl
,pDesc
->val0x14
);
756 if ((pDesc
->Ctl
& DESC_CTL_FREE
) && (pDesc
->val0x14
< 0))
757 acxlog(L_BUF
, "rxbuf %d full\n", i
);
762 /*------------------------------------------------------------------------------
763 * acx100_process_rx_desc
765 * RX path top level entry point called directly and only from the IRQ handler
773 * Call context: Hard IRQ
779 *----------------------------------------------------------------------------*/
780 void acx100_process_rx_desc(wlandevice_t
*wlandev
)
782 struct rxhostdescriptor
*RxPool
;
784 struct rxhostdescriptor
*pDesc
;
788 unsigned int count
= 0;
794 acx100_log_rxbuffer(pDc
);
796 /* there used to be entry count code here, but because this function is called
797 * by the interrupt handler, we are sure that this will only be entered once
798 * because the kernel locks the interrupt handler */
800 RxPool
= pDc
->pRxHostDescQPool
;
802 /* First, have a loop to determine the first descriptor that's
803 * full, just in case there's a mismatch between our current
804 * rx_tail and the full descriptor we're supposed to handle. */
805 spin_lock_irqsave(&rx_lock
, flags
);
808 if (count
> pDc
->rx_pool_count
)
809 { /* hmm, no luck: all descriptors empty, bail out */
810 spin_unlock_irqrestore(&rx_lock
, flags
);
814 curr_idx
= pDc
->rx_tail
;
815 pDesc
= &RxPool
[pDc
->rx_tail
];
816 pDc
->rx_tail
= (pDc
->rx_tail
+ 1) % pDc
->rx_pool_count
;
818 /* "pDesc->val0x14 < 0" is there to check whether MSB
820 while (!((pDesc
->Ctl
& DESC_CTL_FREE
) && (pDesc
->val0x14
< 0))); /* check whether descriptor full, advance to next one if not */
821 spin_unlock_irqrestore(&rx_lock
, flags
);
825 acxlog(L_BUF
, "%s: using curr_idx %d, rx_tail is now %d\n", __func__
, curr_idx
, pDc
->rx_tail
);
827 buf
= (p80211_hdr_t
*)&pDesc
->data
->buf
;
828 if (wlandev
->rx_config_1
& RX_CFG1_INCLUDE_ADDIT_HDR
) {
829 /* take into account additional header in front of packet */
830 buf
= (p80211_hdr_t
*)((UINT8
*)buf
+ 4);
833 buf_len
= pDesc
->data
->status
& 0xfff; /* somelength */
834 if ((WLAN_GET_FC_FSTYPE(buf
->a3
.fc
) != WLAN_FSTYPE_BEACON
)
835 || (debug
& L_XFER_BEACON
))
836 acxlog(L_XFER
|L_DATA
, "Rx pkt %02d (%s): time %lu, len %i, signal %d, SNR %d, mode %d, status %d\n",
838 acx100_get_packet_type_string(buf
->a3
.fc
),
846 /* I tried to figure out how to map these levels to dBm
847 * values, but for the life of me I really didn't
848 * manage to get it. Either these values are not meant to
849 * be expressed in dBm, or it's some pretty complicated
851 wlandev
->wstats
.qual
.level
= pDesc
->data
->level
* 100 / 255;
852 wlandev
->wstats
.qual
.noise
= pDesc
->data
->snr
* 100 / 255;
853 wlandev
->wstats
.qual
.qual
=
854 (wlandev
->wstats
.qual
.noise
<= 100) ?
855 100 - wlandev
->wstats
.qual
.noise
: 0;
856 wlandev
->wstats
.qual
.updated
= 7;
858 if (wlandev
->monitor
) {
859 acx100_rxmonitor(wlandev
, pDesc
->data
);
860 } else if (buf_len
>= 14) {
861 acx100_rx_ieee802_11_frame(wlandev
, pDesc
);
863 acxlog(L_DEBUG
| L_XFER
| L_DATA
,
864 "NOT receiving packet (%s): size too small (%d)\n",
865 acx100_get_packet_type_string(buf
->a3
.fc
), buf_len
);
868 pDesc
->Ctl
&= ~DESC_CTL_FREE
; /* Host no longer owns this */
871 /* ok, descriptor is handled, now check the next descriptor */
872 spin_lock_irqsave(&rx_lock
, flags
);
873 curr_idx
= pDc
->rx_tail
;
874 pDesc
= &RxPool
[pDc
->rx_tail
];
876 /* if next descriptor is empty, then bail out */
877 if (!((pDesc
->Ctl
& DESC_CTL_FREE
) && (pDesc
->val0x14
< 0)))
879 spin_unlock_irqrestore(&rx_lock
, flags
);
884 pDc
->rx_tail
= (pDc
->rx_tail
+ 1) % pDc
->rx_pool_count
;
885 spin_unlock_irqrestore(&rx_lock
, flags
);
891 /*----------------------------------------------------------------
892 * acx100_create_tx_host_desc_queue
907 *----------------------------------------------------------------*/
909 int acx100_create_tx_host_desc_queue(TIWLAN_DC
* pDc
)
911 wlandevice_t
*wlandev
;
917 struct framehdr
*frame_hdr
;
918 struct framehdr
*frame_hdr_phy
;
920 UINT8
*frame_payload
;
921 UINT8
*frame_payload_phy
;
923 struct txhostdescriptor
*host_desc
;
924 struct txhostdescriptor
*host_desc_phy
;
928 wlandev
= pDc
->wlandev
;
930 /* allocate TX header pool */
931 pDc
->FrameHdrQPoolSize
= (wlandev
->TxQueueNo
* sizeof(struct framehdr
));
932 #if (WLAN_HOSTIF!=WLAN_USB)
933 if (!(pDc
->pFrameHdrQPool
=
934 pci_alloc_consistent(0, pDc
->FrameHdrQPoolSize
, &pDc
->FrameHdrQPoolPhyAddr
))) {
935 acxlog(L_BINSTD
, "pDc->pFrameHdrQPool memory allocation error\n");
939 acxlog(L_BINDEBUG
, "pDc->pFrameHdrQPool = 0x%8x\n", (UINT
) pDc
->pFrameHdrQPool
);
940 acxlog(L_BINDEBUG
, "pDc->pFrameHdrQPoolPhyAddr = 0x%8x\n", (UINT
) pDc
->FrameHdrQPoolPhyAddr
);
942 if ((pDc
->pFrameHdrQPool
=kmalloc(pDc
->FrameHdrQPoolSize
,GFP_KERNEL
))==NULL
) {
943 acxlog(L_STD
,"pDc->pFrameHdrQPool memory allocation error\n");
947 memset(pDc
->pFrameHdrQPool
,0,pDc
->FrameHdrQPoolSize
);
950 /* allocate TX payload pool */
951 pDc
->TxBufferPoolSize
= wlandev
->TxQueueNo
*2 * (WLAN_MAX_ETHFRM_LEN
- WLAN_ETHHDR_LEN
);
952 #if (WLAN_HOSTIF!=WLAN_USB)
953 if (!(pDc
->pTxBufferPool
=
954 pci_alloc_consistent(0, pDc
->TxBufferPoolSize
, &pDc
->TxBufferPoolPhyAddr
))) {
955 acxlog(L_BINSTD
, "pDc->pTxBufferPool memory allocation error\n");
956 pci_free_consistent(0, pDc
->FrameHdrQPoolSize
,
958 pDc
->FrameHdrQPoolPhyAddr
);
962 acxlog(L_BINDEBUG
, "pDc->TxBufferPool = 0x%8x\n", (UINT
) pDc
->pTxBufferPool
);
963 acxlog(L_BINDEBUG
, "pDc->TxBufferPoolPhyAddr = 0x%8x\n", (UINT
) pDc
->TxBufferPoolPhyAddr
);
965 if ((pDc
->pTxBufferPool
=kmalloc(pDc
->TxBufferPoolSize
,GFP_KERNEL
))==NULL
) {
966 acxlog(L_STD
,"pDc->pTxBufferPool memory allocation error\n");
967 kfree(pDc
->pFrameHdrQPool
);
971 memset(pDc
->pTxBufferPool
,0,pDc
->TxBufferPoolSize
);
974 /* allocate the TX host descriptor queue pool */
975 pDc
->TxHostDescQPoolSize
= wlandev
->TxQueueNo
*2 * sizeof(struct txhostdescriptor
) + 3;
976 #if (WLAN_HOSTIF!=WLAN_USB)
977 if (!(pDc
->pTxHostDescQPool
=
978 pci_alloc_consistent(0, pDc
->TxHostDescQPoolSize
,
979 &pDc
->TxHostDescQPoolPhyAddr
))) {
980 acxlog(L_BINSTD
, "Failed to allocate shared memory for TxHostDesc queue\n");
981 pci_free_consistent(0, pDc
->FrameHdrQPoolSize
,
983 pDc
->FrameHdrQPoolPhyAddr
);
984 pci_free_consistent(0, pDc
->TxBufferPoolSize
,
986 pDc
->TxBufferPoolPhyAddr
);
990 acxlog(L_BINDEBUG
, "pDc->pTxHostDescQPool = 0x%8x\n", (UINT
) pDc
->pTxHostDescQPool
);
991 acxlog(L_BINDEBUG
, "pDc->TxHostDescQPoolPhyAddr = 0x%8x\n", pDc
->TxHostDescQPoolPhyAddr
);
993 if ((pDc
->pTxHostDescQPool
=kmalloc(pDc
->TxHostDescQPoolSize
,GFP_KERNEL
))==NULL
) {
994 acxlog(L_STD
,"Failed to allocate memory for TxHostDesc queue\n");
995 kfree(pDc
->pFrameHdrQPool
);
996 kfree(pDc
->pTxBufferPool
);
1000 memset(pDc
->pTxHostDescQPool
,0,pDc
->TxHostDescQPoolSize
);
1003 #if (WLAN_HOSTIF!=WLAN_USB)
1004 /* check for proper alignment of TX host descriptor pool */
1005 alignment
= (UINT
) pDc
->pTxHostDescQPool
& 3;
1007 acxlog(L_BINSTD
, "%s: TxHostDescQPool not aligned properly\n", __func__
);
1008 align_offs
= 4 - alignment
;
1013 host_desc
= (struct txhostdescriptor
*) ((UINT8
*) pDc
->pTxHostDescQPool
+ align_offs
);
1014 host_desc_phy
= (struct txhostdescriptor
*) ((UINT8
*) pDc
->TxHostDescQPoolPhyAddr
+ align_offs
);
1016 host_desc
=(struct txhostdescriptor
*)pDc
->pTxHostDescQPool
;
1018 frame_hdr
= (struct framehdr
*) pDc
->pFrameHdrQPool
;
1019 #if (WLAN_HOSTIF!=WLAN_USB)
1020 frame_hdr_phy
= (struct framehdr
*) pDc
->FrameHdrQPoolPhyAddr
;
1023 frame_payload
= (UINT8
*) pDc
->pTxBufferPool
;
1024 #if (WLAN_HOSTIF!=WLAN_USB)
1025 frame_payload_phy
= (UINT8
*) pDc
->TxBufferPoolPhyAddr
;
1028 for (i
= 0; i
< wlandev
->TxQueueNo
*2 - 1; i
++)
1031 #if (WLAN_HOSTIF!=WLAN_USB)
1032 host_desc
->data_phy
= (UINT8
*) frame_hdr_phy
;
1034 host_desc
->data
= (UINT8
*) frame_hdr
;
1035 #if (WLAN_HOSTIF!=WLAN_USB)
1039 #if (WLAN_HOSTIF!=WLAN_USB)
1040 host_desc
->val0x10
= (struct txhostdescriptor
*)((UINT8
*) host_desc_phy
+ sizeof(struct txhostdescriptor
));
1043 #if (WLAN_HOSTIF!=WLAN_USB)
1044 host_desc
->data_phy
= (UINT8
*) frame_payload_phy
;
1046 host_desc
->data
= (UINT8
*) frame_payload
;
1047 #if (WLAN_HOSTIF!=WLAN_USB)
1048 frame_payload_phy
+= WLAN_MAX_ETHFRM_LEN
- WLAN_ETHHDR_LEN
;
1050 frame_payload
+= WLAN_MAX_ETHFRM_LEN
- WLAN_ETHHDR_LEN
;
1052 host_desc
->val0x10
= NULL
;
1055 host_desc
->Ctl
|= DESC_CTL_FREE
;
1056 #if (WLAN_HOSTIF!=WLAN_USB)
1057 host_desc
->desc_phy
= host_desc_phy
;
1058 host_desc
->desc_phy_next
= (struct txhostdescriptor
*)((UINT8
*) host_desc_phy
+ sizeof(struct txhostdescriptor
));
1062 #if (WLAN_HOSTIF!=WLAN_USB)
1066 #if (WLAN_HOSTIF!=WLAN_USB)
1067 host_desc
->data_phy
= (UINT8
*) frame_payload_phy
;
1069 host_desc
->data
= (UINT8
*) frame_payload
;
1070 host_desc
->val0x10
= 0;
1072 host_desc
->Ctl
|= DESC_CTL_FREE
;
1073 #if (WLAN_HOSTIF!=WLAN_USB)
1074 host_desc
->desc_phy
= host_desc_phy
;
1075 host_desc
->desc_phy_next
= (struct txhostdescriptor
*)((UINT8
*) pDc
->TxHostDescQPoolPhyAddr
+ align_offs
);
1082 /*----------------------------------------------------------------
1083 * acx100_create_rx_host_desc_queue
1098 *----------------------------------------------------------------*/
1100 int acx100_create_rx_host_desc_queue(TIWLAN_DC
* pDc
)
1102 wlandevice_t
*wlandev
;
1108 struct rxbuffer
*data
;
1109 struct rxbuffer
*data_phy
;
1111 struct rxhostdescriptor
*host_desc
;
1112 struct rxhostdescriptor
*host_desc_phy
;
1118 wlandev
= pDc
->wlandev
;
1120 /* allocate the RX host descriptor queue pool */
1121 pDc
->RxHostDescQPoolSize
= (wlandev
->RxQueueNo
* sizeof(struct rxhostdescriptor
)) + 0x3;
1122 #if (WLAN_HOSTIF!=WLAN_USB)
1123 if ((pDc
->pRxHostDescQPool
=
1124 pci_alloc_consistent(0, pDc
->RxHostDescQPoolSize
,
1125 &pDc
->RxHostDescQPoolPhyAddr
)) == NULL
) {
1127 "Failed to allocate shared memory for RxHostDesc queue\n");
1132 if ((pDc
->pRxHostDescQPool
= kmalloc(pDc
->RxHostDescQPoolSize
,GFP_KERNEL
))==NULL
) {
1133 acxlog(L_STD
,"Failed to allocate memory for RxHostDesc queue\n");
1137 memset(pDc
->pRxHostDescQPool
,0,pDc
->RxHostDescQPoolSize
);
1140 /* allocate RX buffer pool */
1141 pDc
->RxBufferPoolSize
= (wlandev
->RxQueueNo
* sizeof(struct rxbuffer
));
1142 #if (WLAN_HOSTIF!=WLAN_USB)
1143 if ((pDc
->pRxBufferPool
=
1144 pci_alloc_consistent(0, pDc
->RxBufferPoolSize
,
1145 &pDc
->RxBufferPoolPhyAddr
)) == NULL
) {
1146 acxlog(L_BINSTD
, "Failed to allocate shared memory for Rx buffer\n");
1147 pci_free_consistent(0, pDc
->RxHostDescQPoolSize
,
1148 pDc
->pRxHostDescQPool
,
1149 pDc
->RxHostDescQPoolPhyAddr
);
1154 if ((pDc
->pRxBufferPool
= kmalloc(pDc
->RxBufferPoolSize
,GFP_KERNEL
))==NULL
) {
1155 acxlog(L_STD
,"Failed to allocate memory for Rx buffer\n");
1159 memset(pDc
->pRxBufferPool
,0,pDc
->RxBufferPoolSize
);
1162 acxlog(L_BINDEBUG
, "pDc->pRxHostDescQPool = 0x%8x\n", (UINT
) pDc
->pRxHostDescQPool
);
1163 #if (WLAN_HOSTIF!=WLAN_USB)
1164 acxlog(L_BINDEBUG
, "pDc->RxHostDescQPoolPhyAddr = 0x%8x\n", (UINT
) pDc
->RxHostDescQPoolPhyAddr
);
1166 acxlog(L_BINDEBUG
, "pDc->pRxBufferPool = 0x%8x\n", (UINT
) pDc
->pRxBufferPool
);
1167 #if (WLAN_HOSTIF!=WLAN_USB)
1168 acxlog(L_BINDEBUG
, "pDc->RxBufferPoolPhyAddr = 0x%8x\n", (UINT
) pDc
->RxBufferPoolPhyAddr
);
1170 #if (WLAN_HOSTIF!=WLAN_USB)
1171 /* check for proper alignment of RX host descriptor pool */
1172 if ((alignment
= ((UINT
) pDc
->pRxHostDescQPool
) & 3)) {
1173 acxlog(L_BINSTD
, "acx100_create_rx_host_desc_queue: RxHostDescQPool not aligned properly\n");
1174 align_offs
= 4 - alignment
;
1179 host_desc
= (struct rxhostdescriptor
*) ((UINT8
*) pDc
->pRxHostDescQPool
+ align_offs
);
1180 host_desc_phy
= (struct rxhostdescriptor
*) ((UINT8
*) pDc
->RxHostDescQPoolPhyAddr
+ align_offs
);
1182 wlandev
->RxHostDescPoolStart
= host_desc_phy
;
1184 host_desc
= (struct rxhostdescriptor
*)pDc
->pRxHostDescQPool
;
1186 data
= (struct rxbuffer
*) pDc
->pRxBufferPool
;
1187 #if (WLAN_HOSTIF!=WLAN_USB)
1188 data_phy
= (struct rxbuffer
*) pDc
->RxBufferPoolPhyAddr
;
1191 if (wlandev
->RxQueueNo
!= 1) {
1192 for (i
= 0; i
< wlandev
->RxQueueNo
- 1; i
++) {
1193 host_desc
->data
= data
;
1194 #if (WLAN_HOSTIF!=WLAN_USB)
1195 host_desc
->data_phy
= data_phy
;
1197 host_desc
->length
= sizeof(struct rxbuffer
);
1200 #if (WLAN_HOSTIF!=WLAN_USB)
1204 /* FIXME: what do these mean ? */
1205 host_desc
->val0x28
= 2;
1206 host_desc
->Ctl
&= ~0x80;
1207 #if (WLAN_HOSTIF!=WLAN_USB)
1208 host_desc
->desc_phy
= host_desc_phy
;
1209 host_desc
->desc_phy_next
= (struct rxhostdescriptor
*)((UINT8
*) host_desc_phy
+ sizeof(struct rxhostdescriptor
));
1212 #if (WLAN_HOSTIF!=WLAN_USB)
1217 host_desc
->data
= data
;
1218 #if (WLAN_HOSTIF!=WLAN_USB)
1219 host_desc
->data_phy
= data_phy
;
1221 host_desc
->length
= sizeof(struct rxbuffer
);
1223 host_desc
->val0x28
= 2;
1224 host_desc
->Ctl
&= 0xff7f;
1225 #if (WLAN_HOSTIF!=WLAN_USB)
1226 host_desc
->desc_phy
= host_desc_phy
;
1227 host_desc
->desc_phy_next
= (struct rxhostdescriptor
*)((UINT8
*) pDc
->RxHostDescQPoolPhyAddr
+ align_offs
);
1235 /*----------------------------------------------------------------
1236 * acx100_create_tx_desc_queue
1251 *----------------------------------------------------------------*/
1253 void acx100_create_tx_desc_queue(TIWLAN_DC
* pDc
)
1255 wlandevice_t
*wlandev
;
1260 struct txdescriptor
*tx_desc
;
1261 struct txhostdescriptor
*tx_hostdesc
;
1267 wlandev
= pDc
->wlandev
;
1268 pDc
->tx_pool_count
= wlandev
->TxQueueNo
;
1269 #if (WLAN_HOSTIF!=WLAN_USB)
1271 pDc
->pTxDescQPool
= (struct txdescriptor
*) (wlandev
->iobase2
+
1272 pDc
->ui32ACXTxQueueStart
);
1274 acxlog(L_BINDEBUG
, "wlandev->iobase2 = 0x%08x\n", wlandev
->iobase2
);
1275 acxlog(L_BINDEBUG
, "pDc->ui32ACXTxQueueStart = 0x%08x\n",
1276 pDc
->ui32ACXTxQueueStart
);
1277 acxlog(L_BINDEBUG
, "pDc->pTxDescQPool = 0x%08x\n",
1278 (UINT
) pDc
->pTxDescQPool
);
1280 wlandev
->TxQueueFree
= wlandev
->TxQueueNo
;
1283 #if (WLAN_HOSTIF!=WLAN_USB)
1284 mem_offs
= pDc
->ui32ACXTxQueueStart
;
1285 tx_desc
= pDc
->pTxDescQPool
;
1287 hostmemptr
= pDc
->TxHostDescQPoolPhyAddr
;
1288 tx_hostdesc
= (struct txhostdescriptor
*) pDc
->pTxHostDescQPool
;
1290 /* loop over complete send pool */
1291 for (i
= 0; i
< pDc
->tx_pool_count
; i
++) {
1292 memset(tx_desc
, 0, sizeof(struct txdescriptor
));
1293 /* pointer to hostdesc memory */
1294 tx_desc
->HostMemPtr
= hostmemptr
;
1295 /* initialise ctl */
1296 tx_desc
->Ctl
= DESC_CTL_INIT
;
1297 tx_desc
->something2
= 0;
1298 /* point to next txdesc */
1299 tx_desc
->pNextDesc
= mem_offs
+ sizeof(struct txdescriptor
);
1300 /* pointer to first txhostdesc */
1301 tx_desc
->host_desc
= tx_hostdesc
;
1303 /* reserve two (hdr desc and payload desc) */
1305 hostmemptr
+= 2 * sizeof(struct txhostdescriptor
);
1306 /* go to the next */
1307 mem_offs
+= sizeof(struct txdescriptor
);
1310 /* go to the last one */
1312 /* and point to the first making it a ring buffer */
1313 tx_desc
->pNextDesc
= pDc
->ui32ACXTxQueueStart
;
1318 /*----------------------------------------------------------------
1319 * acx100_create_rx_desc_queue
1334 *----------------------------------------------------------------*/
1336 void acx100_create_rx_desc_queue(TIWLAN_DC
* pDc
)
1338 wlandevice_t
*wlandev
;
1343 struct rxdescriptor
*rx_desc
;
1346 wlandev
= pDc
->wlandev
;
1347 #if (WLAN_HOSTIF!=WLAN_USB)
1348 /* WHY IS IT "TxQueueNo" ? */
1349 pDc
->pRxDescQPool
= (struct rxdescriptor
*) ((wlandev
->TxQueueNo
* sizeof(struct txdescriptor
)) + (UINT8
*) pDc
->pTxDescQPool
);
1351 pDc
->rx_pool_count
= wlandev
->RxQueueNo
;
1353 #if (WLAN_HOSTIF!=WLAN_USB)
1354 mem_offs
= pDc
->ui32ACXRxQueueStart
;
1355 rx_desc
= (struct rxdescriptor
*) pDc
->pRxDescQPool
;
1357 /* loop over complete receive pool */
1358 for (i
= 0; i
< pDc
->rx_pool_count
; i
++) {
1359 memset(rx_desc
, 0, sizeof(struct rxdescriptor
));
1361 /* FIXME: what is this? is it a ctl field ? */
1362 rx_desc
->val0x28
= 0xc;
1364 /* point to next rxdesc */
1365 rx_desc
->pNextDesc
= mem_offs
+ sizeof(struct rxdescriptor
); // next rxdesc pNextDesc
1367 /* go to the next */
1368 mem_offs
+= sizeof(struct rxdescriptor
);
1371 /* go to the last one */
1373 /* and point to the first making it a ring buffer */
1374 rx_desc
->pNextDesc
= pDc
->ui32ACXRxQueueStart
;
1379 /*----------------------------------------------------------------
1380 * acx100_free_desc_queues
1382 * Releases the queues that have been allocated, the
1383 * others have been initialised to NULL in acx100.c so this
1384 * function can be used if only part of the queues where
1399 *----------------------------------------------------------------*/
1401 void acx100_free_desc_queues(TIWLAN_DC
* pDc
)
1404 if (pDc
->pRxHostDescQPool
) {
1405 pci_free_consistent(0,
1406 pDc
->TxHostDescQPoolSize
,
1407 pDc
->pTxHostDescQPool
,
1408 pDc
->TxHostDescQPoolPhyAddr
);
1409 pDc
->pTxHostDescQPool
= NULL
;
1410 pDc
->TxHostDescQPoolSize
= 0;
1412 if (pDc
->pFrameHdrQPool
) {
1413 pci_free_consistent(0, pDc
->FrameHdrQPoolSize
,
1414 pDc
->pFrameHdrQPool
,
1415 pDc
->FrameHdrQPoolPhyAddr
);
1416 pDc
->pFrameHdrQPool
= NULL
;
1417 pDc
->FrameHdrQPoolSize
= 0;
1419 if (pDc
->pTxBufferPool
) {
1420 pci_free_consistent(0, pDc
->TxBufferPoolSize
,
1422 pDc
->TxBufferPoolPhyAddr
);
1423 pDc
->pTxBufferPool
= NULL
;
1424 pDc
->TxBufferPoolSize
= 0;
1427 pDc
->pTxDescQPool
= NULL
;
1428 pDc
->tx_pool_count
= 0;
1430 if (pDc
->pRxHostDescQPool
) {
1431 pci_free_consistent(0, pDc
->RxHostDescQPoolSize
,
1432 pDc
->pRxHostDescQPool
,
1433 pDc
->RxHostDescQPoolPhyAddr
);
1434 pDc
->pRxHostDescQPool
= NULL
;
1435 pDc
->RxHostDescQPoolSize
= 0;
1437 if (pDc
->pRxBufferPool
) {
1438 pci_free_consistent(0, pDc
->RxBufferPoolSize
,
1440 pDc
->RxBufferPoolPhyAddr
);
1441 pDc
->pRxBufferPool
= NULL
;
1442 pDc
->RxBufferPoolSize
= 0;
1445 pDc
->pRxDescQPool
= NULL
;
1446 pDc
->rx_pool_count
= 0;
1450 /*----------------------------------------------------------------
1451 * acx100_init_memory_pools
1465 * FIXME: This function still needs a cleanup
1466 *----------------------------------------------------------------*/
1468 int acx100_init_memory_pools(wlandevice_t
* wlandev
, memmap_t
* mmt
)
1470 #if (WLAN_HOSTIF==WLAN_USB)
1471 UINT TotalMemoryBlocks
; // var_40
1472 acx100usb_memmap_t
*map
;
1473 /* FIXME: is a memmap_t with ConfigWrite3 union type in it.
1474 * This ConfigWrite3 is specially made for this function
1475 * because vali and valj need to be UINT16's. Or am I
1477 * Actually, I think there needs to be 2 memmaps in this function- one
1478 * for the sizewrite and one for optionswrite
1483 UINT16 size
; // val0x4
1485 UINT32 val0x8; It's size only 4 + ACX100RID_BLOCK_SIZE_LEN = 6
1487 } MemoryBlockSize
; // var_3c
1492 UINT DMA_config
; // val0x4
1493 struct rxhostdescriptor
*val0x8
;
1494 UINT val0xc
; /* rx memory */
1495 UINT val0x10
; /* tx memory */
1496 UINT16 TxBlockNum
; // val0x14
1497 UINT16 RxBlockNum
; // val0x16;
1498 } MemoryConfigOption
; // var_2c
1501 map
= (acx100usb_memmap_t
*)mmt
;
1503 acxlog(L_DEBUG
,"Dump of Memory Map:\n");
1504 acx100usb_dump_bytes(mmt
,44);
1506 /* Let's see if we can follow this:
1507 first we select our memory block size (which I think is
1508 completely arbitrary) */
1509 MemoryBlockSize
.size
= wlandev
->memblocksize
;
1511 /* Then we alert the card to our decision of block size */
1512 if (!acx100_configure(wlandev
, &MemoryBlockSize
, ACX100_RID_BLOCK_SIZE
)) {
1513 acxlog(L_BINSTD
, "Ctl: MemoryBlockSizeWrite failed\n");
1517 /* We figure out how many total blocks we can create, using
1518 the block size we chose, and the beginning and ending
1519 memory pointers. IE. end-start/size */
1520 TotalMemoryBlocks
= (map
->PoolEnd
-map
->PoolStart
) / wlandev
->memblocksize
;
1521 acxlog(L_DEBUG
,"TotalMemoryBlocks=%d (%d bytes)\n",TotalMemoryBlocks
,TotalMemoryBlocks
*wlandev
->memblocksize
);
1523 /* This one I have no idea on */
1524 /* block-transfer=0x20000
1525 * indirect descriptors=0x10000
1527 MemoryConfigOption
.DMA_config
= 0x20000; //dma config
1528 /* Declare start of the Rx host pool */
1529 MemoryConfigOption
.val0x8
= wlandev
->RxHostDescPoolStart
;
1531 /* 50% of the allotment of memory blocks go to tx descriptors */
1532 MemoryConfigOption
.TxBlockNum
= TotalMemoryBlocks
/ 2;
1533 /* and 50% go to the rx descriptors */
1534 MemoryConfigOption
.RxBlockNum
= TotalMemoryBlocks
- MemoryConfigOption
.TxBlockNum
;
1536 /* in this block, we save the information we gleaned from the
1537 card into our wlandevice structure; # of tx desc blocks */
1538 wlandev
->val0x24fc
= MemoryConfigOption
.TxBlockNum
;
1539 /* # of rx desc blocks */
1540 wlandev
->val0x24e4
= MemoryConfigOption
.RxBlockNum
;
1541 /* size of the tx and rx descriptor queues */
1542 wlandev
->val0x2500
= MemoryConfigOption
.TxBlockNum
* wlandev
->memblocksize
;
1543 wlandev
->val0x24e8
= MemoryConfigOption
.RxBlockNum
* wlandev
->memblocksize
;
1545 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1546 MemoryConfigOption
.val0xc
= (map
->PoolStart
+ 0x1f) & 0xffffffe0;
1547 /* align the rx descriptor queue to units of 0x20 and offset it
1548 by the tx descriptor queue */
1549 MemoryConfigOption
.val0x10
=
1550 (0x1f + map
->PoolStart
+ wlandev
->val0x2500
) & 0xffffffe0;
1552 /* alert the device to our decision */
1553 if (!acx100_configure(wlandev
, &MemoryConfigOption
, ACX100_RID_MEMORY_CONFIG_OPTIONS
)) {
1556 /* and tell the device to kick it into gear */
1557 if (!acx100_issue_cmd(wlandev
, ACX100_CMD_INIT_MEMORY
, 0, 0, 5000)) {
1563 /* the default PCI code */
1564 UINT TotalMemoryBlocks
; // var_40
1565 /* FIXME: is a memmap_t with ConfigWrite3 union type in it.
1566 * This ConfigWrite3 is specially made for this function
1567 * because vali and valj need to be UINT16's. Or am I
1569 * Actually, I think there needs to be 2 memmaps in this function- one
1570 * for the sizewrite and one for optionswrite
1575 UINT16 size
; // val0x4
1577 UINT32 val0x8; It's size only 4 + ACX100RID_BLOCK_SIZE_LEN = 6
1579 } MemoryBlockSize
; // var_3c
1584 UINT DMA_config
; // val0x4
1585 struct rxhostdescriptor
*val0x8
;
1588 UINT16 TxBlockNum
; // val0x14
1589 UINT16 RxBlockNum
; // val0x16;
1590 } MemoryConfigOption
; // var_2c
1594 /* Let's see if we can follow this:
1595 first we select our memory block size (which I think is
1596 completely arbitrary) */
1597 MemoryBlockSize
.size
= wlandev
->memblocksize
;
1599 /* Then we alert the card to our decision of block size */
1600 if (!acx100_configure(wlandev
, &MemoryBlockSize
, ACX100_RID_BLOCK_SIZE
)) {
1601 acxlog(L_BINSTD
, "Ctl: MemoryBlockSizeWrite failed\n");
1606 /* We figure out how many total blocks we can create, using
1607 the block size we chose, and the beginning and ending
1608 memory pointers. IE. end-start/size */
1609 TotalMemoryBlocks
= (mmt
->m
.cw2
.val0x28
- mmt
->m
.cw2
.vali
) / wlandev
->memblocksize
;
1611 /* This one I have no idea on */
1612 MemoryConfigOption
.DMA_config
= 0x30000; //dma config
1613 /* Declare start of the Rx host pool */
1614 MemoryConfigOption
.val0x8
= wlandev
->RxHostDescPoolStart
;
1616 /* 50% of the allotment of memory blocks go to tx descriptors */
1617 MemoryConfigOption
.TxBlockNum
= TotalMemoryBlocks
/ 2;
1618 /* and 50% go to the rx descriptors */
1619 MemoryConfigOption
.RxBlockNum
= TotalMemoryBlocks
- MemoryConfigOption
.TxBlockNum
;
1621 /* in this block, we save the information we gleaned from the
1622 card into our wlandevice structure; # of tx desc blocks */
1623 wlandev
->val0x24fc
= MemoryConfigOption
.TxBlockNum
;
1624 /* # of rx desc blocks */
1625 wlandev
->val0x24e4
= MemoryConfigOption
.RxBlockNum
;
1626 /* size of the tx and rx descriptor queues */
1627 wlandev
->val0x2500
= MemoryConfigOption
.TxBlockNum
* wlandev
->memblocksize
;
1628 wlandev
->val0x24e8
= MemoryConfigOption
.RxBlockNum
* wlandev
->memblocksize
;
1630 /* align the tx descriptor queue to an alignment of 0x20 (32 bytes) */
1631 MemoryConfigOption
.val0xc
= (mmt
->m
.cw2
.vali
+ 0x1f) & 0xffffffe0;
1632 /* align the rx descriptor queue to units of 0x20 and offset it
1633 by the tx descriptor queue */
1634 MemoryConfigOption
.val0x10
=
1635 (0x1f + mmt
->m
.cw2
.vali
+ wlandev
->val0x2500
) & 0xffffffe0;
1637 /* alert the device to our decision */
1638 if (!acx100_configure(wlandev
, &MemoryConfigOption
, ACX100_RID_MEMORY_CONFIG_OPTIONS
)) {
1642 /* and tell the device to kick it into gear */
1643 if (!acx100_issue_cmd(wlandev
, ACX100_CMD_INIT_MEMORY
, 0, 0, 5000)) {
1653 /*----------------------------------------------------------------
1654 * acx100_get_tx_desc
1669 *----------------------------------------------------------------*/
1671 struct txdescriptor
*acx100_get_tx_desc(wlandevice_t
* wlandev
)
1673 struct TIWLAN_DC
* pDc
= &wlandev
->dc
;
1674 struct txdescriptor
*tx_desc
;
1675 unsigned long flags
;
1679 spin_lock_irqsave(&tx_lock
, flags
);
1681 tx_desc
= &pDc
->pTxDescQPool
[pDc
->tx_head
];
1683 if ((tx_desc
->Ctl
& DESC_CTL_FREE
) == 0) {
1684 /* whoops, descr at current index is not free, so probably
1685 * ring buffer already full */
1690 wlandev
->TxQueueFree
--;
1691 acxlog(L_BUF
, "got Tx desc %d, %d remain.\n", pDc
->tx_head
, wlandev
->TxQueueFree
);
1694 * This comment is probably not entirely correct, needs further discussion
1695 * (restored commented-out code below to fix Tx ring buffer overflow,
1696 * since it's much better to have a slightly less efficiently used ring
1697 * buffer rather than one which easily overflows):
1699 * This doesn't do anything other than limit our maximum number of
1700 * buffers used at a single time (we might as well just declare
1701 * MINFREE_TX less descriptors when we open up.) We should just let it
1702 * slide here, and back off MINFREE_TX in acx100_clean_tx_desc, when given the
1703 * opportunity to let the queue start back up.
1705 if (wlandev
->TxQueueFree
< MINFREE_TX
)
1707 acxlog(L_XFER
, "stop queue (avail. Tx desc %d).\n", wlandev
->TxQueueFree
);
1708 netif_stop_queue(wlandev
->netdev
);
1711 /* returning current descriptor, so advance to next free one */
1712 pDc
->tx_head
= (pDc
->tx_head
+ 1) % pDc
->tx_pool_count
;
1714 spin_unlock_irqrestore(&tx_lock
, flags
);
1716 FN_EXIT(0, (int)tx_desc
);
1720 static char type_string
[32]; /* I *really* don't care that this is static,
1721 so don't complain, else... ;-) */
1723 /*----------------------------------------------------------------
1724 * acx100_get_packet_type_string
1739 *----------------------------------------------------------------*/
1741 char *acx100_get_packet_type_string(UINT16 fc
)
1743 char *ftype
= "UNKNOWN", *fstype
= "UNKNOWN";
1746 switch (WLAN_GET_FC_FTYPE(fc
)) {
1747 case WLAN_FTYPE_MGMT
:
1749 switch (WLAN_GET_FC_FSTYPE(fc
)) {
1750 case WLAN_FSTYPE_ASSOCREQ
:
1751 fstype
= "AssocReq";
1753 case WLAN_FSTYPE_ASSOCRESP
:
1754 fstype
= "AssocResp";
1756 case WLAN_FSTYPE_REASSOCREQ
:
1757 fstype
= "ReassocReq";
1759 case WLAN_FSTYPE_REASSOCRESP
:
1760 fstype
= "ReassocResp";
1762 case WLAN_FSTYPE_PROBEREQ
:
1763 fstype
= "ProbeReq";
1765 case WLAN_FSTYPE_PROBERESP
:
1766 fstype
= "ProbeResp";
1768 case WLAN_FSTYPE_BEACON
:
1771 case WLAN_FSTYPE_ATIM
:
1774 case WLAN_FSTYPE_DISASSOC
:
1775 fstype
= "Disassoc";
1777 case WLAN_FSTYPE_AUTHEN
:
1780 case WLAN_FSTYPE_DEAUTHEN
:
1781 fstype
= "Deauthen";
1785 case WLAN_FTYPE_CTL
:
1787 switch (WLAN_GET_FC_FSTYPE(fc
)) {
1788 case WLAN_FSTYPE_PSPOLL
:
1791 case WLAN_FSTYPE_RTS
:
1794 case WLAN_FSTYPE_CTS
:
1797 case WLAN_FSTYPE_ACK
:
1800 case WLAN_FSTYPE_CFEND
:
1803 case WLAN_FSTYPE_CFENDCFACK
:
1804 fstype
= "CFEndCFAck";
1808 case WLAN_FTYPE_DATA
:
1810 switch (WLAN_GET_FC_FSTYPE(fc
)) {
1811 case WLAN_FSTYPE_DATAONLY
:
1812 fstype
= "DataOnly";
1814 case WLAN_FSTYPE_DATA_CFACK
:
1815 fstype
= "Data CFAck";
1817 case WLAN_FSTYPE_DATA_CFPOLL
:
1818 fstype
= "Data CFPoll";
1820 case WLAN_FSTYPE_DATA_CFACK_CFPOLL
:
1821 fstype
= "Data CFAck/CFPoll";
1823 case WLAN_FSTYPE_NULL
:
1826 case WLAN_FSTYPE_CFACK
:
1829 case WLAN_FSTYPE_CFPOLL
:
1832 case WLAN_FSTYPE_CFACK_CFPOLL
:
1833 fstype
= "CFAck/CFPoll";
1838 sprintf(type_string
, "%s/%s", ftype
, fstype
);
1839 FN_EXIT(1, (int)type_string
);