/* * segment the img and use the ptr and length to remember info on each segment * */ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buffer_len) { struct r8192_priv *priv = ieee80211_priv(dev); bool rt_status = true; u16 frag_threshold; u16 frag_length, frag_offset = 0; //u16 total_size; int i; rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; cb_desc *tcb_desc; u8 bLastIniPkt; firmware_init_param(dev); //Fragmentation might be required frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold ; bLastIniPkt = 0; } else { frag_length = buffer_len - frag_offset; bLastIniPkt = 1; } /* Allocate skb buffer to contain firmware info and tx descriptor info * add 4 to avoid packet appending overflow. * */ skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); if (!skb) return false; memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; tcb_desc->bLastIniPkt = bLastIniPkt; skb_reserve(skb, USB_HWDESC_HEADER_LEN); seg_ptr = skb->data; /* * Transform from little endian to big endian * and pending zero */ for(i=0 ; i < frag_length; i+=4) { *seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0; *seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0; *seg_ptr++ = ((i+2)<frag_length)?code_virtual_address[i+1]:0; *seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0; } tcb_desc->txbuf_size= (u16)i; skb_put(skb, i); if (!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ (priv->ieee80211->queue_stop) ) { RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); } else { priv->ieee80211->softmac_hard_start_xmit(skb,dev); } code_virtual_address += frag_length; frag_offset += frag_length; }while(frag_offset < buffer_len); return rt_status; }
bool cmpk_message_handle_tx( struct net_device *dev, u8 *code_virtual_address, u32 packettype, u32 buffer_len) { bool rt_status = true; struct r8192_priv *priv = rtllib_priv(dev); u16 frag_threshold; u16 frag_length = 0, frag_offset = 0; struct rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; struct cb_desc *tcb_desc; u8 bLastIniPkt; struct tx_fwinfo_8190pci *pTxFwInfo = NULL; RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len); firmware_init_param(dev); frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold; bLastIniPkt = 0; } else { frag_length = (u16)(buffer_len - frag_offset); bLastIniPkt = 1; } skb = dev_alloc_skb(frag_length + priv->rtllib->tx_headroom + 4); if (skb == NULL) { rt_status = false; goto Failed; } memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_NORMAL; tcb_desc->bLastIniPkt = bLastIniPkt; tcb_desc->pkt_size = frag_length; seg_ptr = skb_put(skb, priv->rtllib->tx_headroom); pTxFwInfo = (struct tx_fwinfo_8190pci *)seg_ptr; memset(pTxFwInfo, 0, sizeof(struct tx_fwinfo_8190pci)); memset(pTxFwInfo, 0x12, 8); seg_ptr = skb_put(skb, frag_length); memcpy(seg_ptr, code_virtual_address, (u32)frag_length); priv->rtllib->softmac_hard_start_xmit(skb, dev); code_virtual_address += frag_length; frag_offset += frag_length; } while (frag_offset < buffer_len); write_nic_byte(dev, TPPoll, TPPoll_CQ); Failed: return rt_status; }
/*----------------------------------------------------------------------------- * Function: cmpk_message_handle_tx() * * Overview: Driver internal module can call the API to send message to * firmware side. For example, you can send a debug command packet. * Or you can send a request for FW to modify RLX4181 LBUS HW bank. * Otherwise, you can change MAC/PHT/RF register by firmware at * run time. We do not support message more than one segment now. * * Input: NONE * * Output: NONE * * Return: NONE * * Revised History: * When Who Remark * 05/06/2008 amy porting from windows code. * *---------------------------------------------------------------------------*/ extern rt_status cmpk_message_handle_tx( struct net_device *dev, u8* codevirtualaddress, u32 packettype, u32 buffer_len) { bool rt_status = true; #ifdef RTL8192U return rt_status; #else struct r8192_priv *priv = ieee80211_priv(dev); u16 frag_threshold; u16 frag_length, frag_offset = 0; //u16 total_size; //int i; rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; cb_desc *tcb_desc; u8 bLastIniPkt; firmware_init_param(dev); //Fragmentation might be required frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold ; bLastIniPkt = 0; } else { frag_length = buffer_len - frag_offset; bLastIniPkt = 1; } /* Allocate skb buffer to contain firmware info and tx descriptor info * add 4 to avoid packet appending overflow. * */ #ifdef RTL8192U skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); #else skb = dev_alloc_skb(frag_length + 4); #endif memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = packettype; tcb_desc->bLastIniPkt = bLastIniPkt; #ifdef RTL8192U skb_reserve(skb, USB_HWDESC_HEADER_LEN); #endif seg_ptr = skb_put(skb, buffer_len); /* * Transform from little endian to big endian * and pending zero */ memcpy(seg_ptr,codevirtualaddress,buffer_len); tcb_desc->txbuf_size= (u16)buffer_len; if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)|| (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\ (priv->ieee80211->queue_stop) ) { RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n"); skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb); } else { priv->ieee80211->softmac_hard_start_xmit(skb,dev); } codevirtualaddress += frag_length; frag_offset += frag_length; }while(frag_offset < buffer_len); return rt_status; #endif } /* CMPK_Message_Handle_Tx */
static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buffer_len) { struct r8192_priv *priv = rtllib_priv(dev); u16 frag_threshold; u16 frag_length, frag_offset = 0; int i; struct rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; struct cb_desc *tcb_desc; u8 bLastIniPkt; firmware_init_param(dev); frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold; bLastIniPkt = 0; } else { frag_length = buffer_len - frag_offset; bLastIniPkt = 1; } skb = dev_alloc_skb(frag_length + 4); memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (struct cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; tcb_desc->bLastIniPkt = bLastIniPkt; seg_ptr = skb->data; for (i = 0; i < frag_length; i += 4) { *seg_ptr++ = ((i+0) < frag_length) ? code_virtual_address[i+3] : 0; *seg_ptr++ = ((i+1) < frag_length) ? code_virtual_address[i+2] : 0; *seg_ptr++ = ((i+2) < frag_length) ? code_virtual_address[i+1] : 0; *seg_ptr++ = ((i+3) < frag_length) ? code_virtual_address[i+0] : 0; } tcb_desc->txbuf_size = (u16)i; skb_put(skb, i); if (!priv->rtllib->check_nic_enough_desc(dev, tcb_desc->queue_index) || (!skb_queue_empty(&priv->rtllib->skb_waitQ[tcb_desc->queue_index])) || (priv->rtllib->queue_stop)) { RT_TRACE(COMP_FIRMWARE, "===================> tx full!\n"); skb_queue_tail(&priv->rtllib->skb_waitQ [tcb_desc->queue_index], skb); } else { priv->rtllib->softmac_hard_start_xmit(skb, dev); } code_virtual_address += frag_length; frag_offset += frag_length; } while (frag_offset < buffer_len); write_nic_byte(dev, TPPoll, TPPoll_CQ); return true; }
/* * segment the img and use the ptr and length to remember info on each segment */ static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buffer_len) { struct r8192_priv *priv = ieee80211_priv(dev); bool rt_status = true; u16 frag_threshold; u16 frag_length, frag_offset = 0; int i; rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; cb_desc *tcb_desc; u8 bLastIniPkt; firmware_init_param(dev); /* Fragmentation might be required */ frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if ((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold ; bLastIniPkt = 0; } else { frag_length = buffer_len - frag_offset; bLastIniPkt = 1; } /* * Allocate skb buffer to contain firmware info and tx * descriptor info add 4 to avoid packet appending overflow. */ skb = dev_alloc_skb(frag_length + 4); memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev)); tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT; tcb_desc->bLastIniPkt = bLastIniPkt; seg_ptr = skb->data; /* * Transform from little endian to big endian and pending zero */ for (i = 0; i < frag_length; i += 4) { *seg_ptr++ = ((i+0) < frag_length) ? code_virtual_address[i+3] : 0; *seg_ptr++ = ((i+1) < frag_length) ? code_virtual_address[i+2] : 0; *seg_ptr++ = ((i+2) < frag_length) ? code_virtual_address[i+1] : 0; *seg_ptr++ = ((i+3) < frag_length) ? code_virtual_address[i+0] : 0; } tcb_desc->txbuf_size = (u16)i; skb_put(skb, i); priv->ieee80211->softmac_hard_start_xmit(skb, dev); code_virtual_address += frag_length; frag_offset += frag_length; } while (frag_offset < buffer_len); return rt_status; }
/*----------------------------------------------------------------------------- * Function: cmpk_message_handle_tx() * * Overview: Driver internal module can call the API to send message to * firmware side. For example, you can send a debug command packet. * Or you can send a request for FW to modify RLX4181 LBUS HW bank. * Otherwise, you can change MAC/PHT/RF register by firmware at * run time. We do not support message more than one segment now. * * Input: NONE * * Output: NONE * * Return: NONE * * Revised History: * When Who Remark * 05/06/2008 amy porting from windows code. * *---------------------------------------------------------------------------*/ RT_STATUS cmpk_message_handle_tx( struct net_device *dev, u8* code_virtual_address, u32 packettype, u32 buffer_len) { RT_STATUS rt_status = RT_STATUS_SUCCESS; #ifdef RTL8192U return rt_status; #else struct r8192_priv *priv = ieee80211_priv(dev); u16 frag_threshold; u16 frag_length = 0, frag_offset = 0; rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; cb_desc *tcb_desc; u8 bLastIniPkt; PTX_FWINFO_8190PCI pTxFwInfo = NULL; int i; //spin_lock_irqsave(&priv->tx_lock,flags); RT_TRACE(COMP_CMDPKT,"%s(),buffer_len is %d\n",__FUNCTION__,buffer_len); firmware_init_param(dev); //Fragmentation might be required frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold ; bLastIniPkt = 0; } else { frag_length =(u16)(buffer_len - frag_offset); bLastIniPkt = 1; } /* Allocate skb buffer to contain firmware info and tx descriptor info * add 4 to avoid packet appending overflow. * */ #ifdef RTL8192U skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); #else skb = dev_alloc_skb(frag_length + priv->ieee80211->tx_headroom + 4); #endif if(skb == NULL) { rt_status = RT_STATUS_FAILURE; goto Failed; } memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = packettype; tcb_desc->bLastIniPkt = bLastIniPkt; tcb_desc->pkt_size = frag_length; #ifdef RTL8192U skb_reserve(skb, USB_HWDESC_HEADER_LEN); #endif //seg_ptr = skb_put(skb, frag_length + priv->ieee80211->tx_headroom); seg_ptr = skb_put(skb, priv->ieee80211->tx_headroom); pTxFwInfo = (PTX_FWINFO_8190PCI)seg_ptr; memset(pTxFwInfo,0,sizeof(TX_FWINFO_8190PCI)); memset(pTxFwInfo,0x12,8); seg_ptr +=sizeof(TX_FWINFO_8190PCI); /* * Transform from little endian to big endian * and pending zero */ seg_ptr = skb->tail; for(i=0 ; i < frag_length; i+=4) { *seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0; *seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0; *seg_ptr++ = ((i+2)<frag_length)?code_virtual_address[i+1]:0; *seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0; } skb_put(skb, i); priv->ieee80211->softmac_hard_start_xmit(skb,dev); code_virtual_address += frag_length; frag_offset += frag_length; }while(frag_offset < buffer_len); Failed: //spin_unlock_irqrestore(&priv->tx_lock,flags); return rt_status; #endif } /* CMPK_Message_Handle_Tx */
/*----------------------------------------------------------------------------- * Function: cmpk_message_handle_tx() * * Overview: Driver internal module can call the API to send message to * firmware side. For example, you can send a debug command packet. * Or you can send a request for FW to modify RLX4181 LBUS HW bank. * Otherwise, you can change MAC/PHT/RF register by firmware at * run time. We do not support message more than one segment now. * * Input: NONE * * Output: NONE * * Return: NONE * * Revised History: * When Who Remark * 05/06/2008 amy porting from windows code. * *---------------------------------------------------------------------------*/ extern RT_STATUS cmpk_message_handle_tx( struct net_device *dev, u8* codevirtualaddress, u32 packettype, u32 buffer_len) { RT_STATUS rt_status = RT_STATUS_SUCCESS; #ifdef RTL8192U return rt_status; #else struct r8192_priv *priv = ieee80211_priv(dev); u16 frag_threshold; u16 frag_length = 0, frag_offset = 0; //u16 total_size; //int i; unsigned int flags; rt_firmware *pfirmware = priv->pFirmware; struct sk_buff *skb; unsigned char *seg_ptr; cb_desc *tcb_desc; u8 bLastIniPkt; PTX_FWINFO_8190PCI pTxFwInfo = NULL; struct buffer* buflist; tx_desc_819x_pci *pdesc = NULL; ptx_ring tail; ptx_ring begin; u32 *buf; int count; int i; int remain; int buflen; spin_lock_irqsave(&priv->tx_lock,flags); RT_TRACE(COMP_CMDPKT,"%s(),buffer_len is %d\n",__FUNCTION__,buffer_len); firmware_init_param(dev); //Fragmentation might be required frag_threshold = pfirmware->cmdpacket_frag_thresold; do { if((buffer_len - frag_offset) > frag_threshold) { frag_length = frag_threshold ; bLastIniPkt = 0; } else { frag_length =(u16)(buffer_len - frag_offset); bLastIniPkt = 1; } tail=priv->txcmdringtail; begin=priv->txcmdring; buflist = priv->txcmdbufstail; count = priv->txringcount; pdesc = (tx_desc_819x_pci *)(tail->desc); if(!buflist){ printk("TX CMD buffer error, cannot TX CMD frames. \n"); rt_status = RT_STATUS_FAILURE; goto Failed; } buf=buflist->buf; buflen=priv->txfwbuffersize; if(pdesc->OWN) { printk("No more TX desc, returning \n"); priv->stats.txrdu++; rt_status = RT_STATUS_FAILURE; goto Failed; } /* Allocate skb buffer to contain firmware info and tx descriptor info * add 4 to avoid packet appending overflow. * */ #ifdef RTL8192U skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4); #else skb = dev_alloc_skb(frag_length + priv->ieee80211->tx_headroom + 4); #endif if(skb == NULL) { rt_status = RT_STATUS_FAILURE; goto Failed; } memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev)); tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE); tcb_desc->queue_index = TXCMD_QUEUE; tcb_desc->bCmdOrInit = packettype; tcb_desc->bLastIniPkt = bLastIniPkt; #ifdef RTL8192U skb_reserve(skb, USB_HWDESC_HEADER_LEN); #endif seg_ptr = skb_put(skb, frag_length + priv->ieee80211->tx_headroom); remain=skb->len; pTxFwInfo = (PTX_FWINFO_8190PCI)seg_ptr; memset(pTxFwInfo,0,sizeof(TX_FWINFO_8190PCI)); memset(pTxFwInfo,0x12,8); seg_ptr +=sizeof(TX_FWINFO_8190PCI); memset(pdesc,0,12); pdesc->LINIP = tcb_desc->bLastIniPkt; pdesc->FirstSeg = 1;//first segment; pdesc->LastSeg = 1;//first segment; pdesc->CmdInit = DESC_PACKET_TYPE_NORMAL; pdesc->Offset = sizeof(TX_FWINFO_8190PCI) + 8; pdesc->PktSize = (u16)(frag_length+pdesc->Offset); pdesc->QueueSelect = QSLT_CMD; pdesc->TxFWInfoSize = 0x08; pdesc->RATid = (u8)DESC_PACKET_TYPE_INIT; pdesc->TxBufferSize = skb->len; pdesc->TxBuffAddr = buflist->dma; pdesc->OWN = 1; /* * Transform from little endian to big endian * and pending zero */ memcpy(seg_ptr,codevirtualaddress,frag_length); for(i=0;i<buflen&& remain >0;i++,remain--){ ((u8*)buf)[i]=skb->data[i]; //copy data into descriptor pointed DMAble buffer if(remain == 4 && i+4 >= buflen) break; /* ensure the last desc has at least 4 bytes payload */ } if(remain == 0) dev_kfree_skb_any(skb); #if 0 { int k; printk("------------tx cmd------------\n"); for(k = 0; k<i; k++) printk(" 0x%x",((u8*)buf)[k]); printk("\n"); } { int m; printk("-------------cmd desc----------\n"); for(m=0;m<32;m++) printk(" 0x%x",((u8*)pdesc)[m]); printk("\n"); } #endif if(((tail->desc) - (begin->desc))/8 == count-1) tail=begin; else tail=tail->next; buflist=buflist->next; mb(); priv->txcmdringtail=tail; priv->txcmdbufstail=buflist; codevirtualaddress += frag_length; frag_offset += frag_length; write_nic_word(dev,TPPoll,TPPoll_CQ); }while(frag_offset < buffer_len); Failed: spin_unlock_irqrestore(&priv->tx_lock,flags); return rt_status; #endif } /* CMPK_Message_Handle_Tx */