/***********************************************************************
** 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_