/*********************************************************************** ** acxpci_l_tx_data ** ** Can be called from IRQ (rx -> (AP bridging or mgmt response) -> tx). ** Can be called from acx_i_start_xmit (data frames from net core). ** ** FIXME: in case of fragments, should loop over the number of ** pre-allocated tx descrs, properly setting up transfer data and ** CTL_xxx flags according to fragment number. */ void acxpci_l_tx_data(acx_device_t * adev, tx_t * tx_opaque, int len, struct ieee80211_tx_control *ieeectl,struct sk_buff* skb) { txdesc_t *txdesc = (txdesc_t *) tx_opaque; struct ieee80211_hdr *wireless_header; txhostdesc_t *hostdesc1, *hostdesc2; int rate_cur; u8 Ctl_8; u8 Ctl2_8; int wlhdr_len; unsigned long flags; FN_ENTER; acx_lock(adev, flags); /* fw doesn't tx such packets anyhow */ /* if (unlikely(len < WLAN_HDR_A3_LEN)) goto end; */ // printk("1\n"); hostdesc1 = get_txhostdesc(adev, txdesc); wireless_header = (struct ieee80211_hdr *)hostdesc1->data; /* modify flag status in separate variable to be able to write it back * in one big swoop later (also in order to have less device memory * accesses) */ Ctl_8 = txdesc->Ctl_8; Ctl2_8 = 0; /* really need to init it to 0, not txdesc->Ctl2_8, it seems */ // printk("2\n"); hostdesc2 = hostdesc1 + 1; /* DON'T simply set Ctl field to 0 here globally, * it needs to maintain a consistent flag status (those are state flags!!), * otherwise it may lead to severe disruption. Only set or reset particular * flags at the exact moment this is needed... */ /* let chip do RTS/CTS handshaking before sending * in case packet size exceeds threshold */ if (ieeectl->flags & IEEE80211_TXCTL_USE_RTS_CTS) SET_BIT(Ctl2_8, DESC_CTL2_RTS); else CLEAR_BIT(Ctl2_8, DESC_CTL2_RTS); // printk("3\n"); rate_cur = ieeectl->tx_rate; if (unlikely(!rate_cur)) { // printk("acx: driver bug! bad ratemask\n"); acx_unlock(adev, flags); goto end; } printk("4\n"); /* used in tx cleanup routine for auto rate and accounting: */ /* put_txcr(adev, txdesc, clt, rate_cur); deprecated by mac80211 */ txdesc->total_length = cpu_to_le16(len); printk("f.1\n"); wlhdr_len = ieee80211_get_hdrlen(le16_to_cpu(wireless_header->frame_control)); printk("f.2\n"); hostdesc2->length = cpu_to_le16(len - wlhdr_len); printk("5\n"); /* if (!ieeectl->do_not_encrypt && ieeectl->key_idx>= 0) { u16 key_idx = (u16)(ieeectl->key_idx); struct acx_key* key = &(adev->key[key_idx]); int wlhdr_len; if (key->enabled) { memcpy(ieeehdr->wep_iv, ((u8*)wireless_header) + wlhdr_len, 4); } } */ acx_unlock(adev, flags); printk("unlocking failed, just as bush did!\n"); _CODE_WILL_CONTINUE_HERE_