1 /**************************************************************************************************
2 * Procedure: Init boot code/firmware code/data session
4 * Description: This routine will intialize firmware. If any error occurs during the initialization
5 * process, the routine shall terminate immediately and return fail.
6 * NIC driver should call NdisOpenFile only from MiniportInitialize.
8 * Arguments: The pointer of the adapter
11 * NDIS_STATUS_FAILURE - the following initialization process should be terminated
12 * NDIS_STATUS_SUCCESS - if firmware initialization process success
13 **************************************************************************************************/
14 //#include "ieee80211.h"
16 #include "r8192U_hw.h"
17 #include "r819xU_firmware_img.h"
18 #include "r819xU_firmware.h"
19 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
20 #include <linux/firmware.h>
22 void firmware_init_param(struct net_device
*dev
)
24 struct r8192_priv
*priv
= ieee80211_priv(dev
);
25 rt_firmware
*pfirmware
= priv
->pFirmware
;
27 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE
);
31 * segment the img and use the ptr and length to remember info on each segment
34 bool fw_download_code(struct net_device
*dev
, u8
*code_virtual_address
, u32 buffer_len
)
36 struct r8192_priv
*priv
= ieee80211_priv(dev
);
37 bool rt_status
= true;
39 u16 frag_length
, frag_offset
= 0;
43 rt_firmware
*pfirmware
= priv
->pFirmware
;
45 unsigned char *seg_ptr
;
49 firmware_init_param(dev
);
50 //Fragmentation might be required
51 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
53 if((buffer_len
- frag_offset
) > frag_threshold
) {
54 frag_length
= frag_threshold
;
58 frag_length
= buffer_len
- frag_offset
;
63 /* Allocate skb buffer to contain firmware info and tx descriptor info
64 * add 4 to avoid packet appending overflow.
67 skb
= dev_alloc_skb(USB_HWDESC_HEADER_LEN
+ frag_length
+ 4);
69 skb
= dev_alloc_skb(frag_length
+ 4);
71 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
72 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
73 tcb_desc
->queue_index
= TXCMD_QUEUE
;
74 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
75 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
78 skb_reserve(skb
, USB_HWDESC_HEADER_LEN
);
82 * Transform from little endian to big endian
85 for(i
=0 ; i
< frag_length
; i
+=4) {
86 *seg_ptr
++ = ((i
+0)<frag_length
)?code_virtual_address
[i
+3]:0;
87 *seg_ptr
++ = ((i
+1)<frag_length
)?code_virtual_address
[i
+2]:0;
88 *seg_ptr
++ = ((i
+2)<frag_length
)?code_virtual_address
[i
+1]:0;
89 *seg_ptr
++ = ((i
+3)<frag_length
)?code_virtual_address
[i
+0]:0;
91 tcb_desc
->txbuf_size
= (u16
)i
;
94 if(!priv
->ieee80211
->check_nic_enough_desc(dev
,tcb_desc
->queue_index
)||
95 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
]))||\
96 (priv
->ieee80211
->queue_stop
) ) {
97 RT_TRACE(COMP_FIRMWARE
,"=====================================================> tx full!\n");
98 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
100 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
103 code_virtual_address
+= frag_length
;
104 frag_offset
+= frag_length
;
106 }while(frag_offset
< buffer_len
);
111 cmdsend_downloadcode_fail
:
113 RT_TRACE(COMP_ERR
, "CmdSendDownloadCode fail !!\n");
120 struct net_device
*dev
,
124 bool rtStatus
= true;
125 struct r8192_priv
*priv
= ieee80211_priv(dev
);
128 unsigned char *ptr_buf
;
129 bool bLastInitPacket
= false;
131 //PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
133 //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
134 skb
= dev_alloc_skb(Length
+ 4);
135 memcpy((unsigned char *)(skb
->cb
),&dev
,sizeof(dev
));
136 tcb_desc
= (cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
137 tcb_desc
->queue_index
= TXCMD_QUEUE
;
138 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
139 tcb_desc
->bLastIniPkt
= bLastInitPacket
;
140 ptr_buf
= skb_put(skb
, Length
);
141 memset(ptr_buf
,0,Length
);
142 tcb_desc
->txbuf_size
= (u16
)Length
;
144 if(!priv
->ieee80211
->check_nic_enough_desc(dev
,tcb_desc
->queue_index
)||
145 (!skb_queue_empty(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
]))||\
146 (priv
->ieee80211
->queue_stop
) ) {
147 RT_TRACE(COMP_FIRMWARE
,"===================NULL packet==================================> tx full!\n");
148 skb_queue_tail(&priv
->ieee80211
->skb_waitQ
[tcb_desc
->queue_index
], skb
);
150 priv
->ieee80211
->softmac_hard_start_xmit(skb
,dev
);
153 //PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
159 * Procedure : Download code into IMEM or DMEM
160 * Description: This routine will intialize firmware. If any error occurs during the initialization
161 * process, the routine shall terminate immediately and return fail.
162 * The routine copy virtual address get from opening of file into shared memory
163 * allocated during initialization. If code size larger than a conitneous shared
164 * memory may contain, the code should be divided into several section.
165 * !!!NOTES This finction should only be called during MPInitialization because
166 * A NIC driver should call NdisOpenFile only from MiniportInitialize.
167 * Arguments : The pointer of the adapter
168 * Code address (Virtual address, should fill descriptor with physical address)
171 * RT_STATUS_FAILURE - the following initialization process should be terminated
172 * RT_STATUS_SUCCESS - if firmware initialization process success
174 bool fwsend_download_code(struct net_device
*dev
)
176 struct r8192_priv
*priv
= ieee80211_priv(dev
);
177 rt_firmware
*pfirmware
= (rt_firmware
*)(&priv
->firmware
);
179 bool rt_status
= true;
183 bool last_init_packet
= false;
184 u32 check_txcmdwait_queueemptytime
= 100000;
188 /* reset to 0 for first segment of img download */
189 pfirmware
->firmware_seg_index
= 1;
191 if(pfirmware
->firmware_seg_index
== pfirmware
->firmware_seg_maxnum
) {
192 last_init_packet
= 1;
195 cmd_buf_len
= pfirmware
->firmware_seg_container
[pfirmware
->firmware_seg_index
-1].seg_size
;
196 ptr_cmd_buf
= pfirmware
->firmware_seg_container
[pfirmware
->firmware_seg_index
-1].seg_ptr
;
197 rtl819xU_tx_cmd(dev
, ptr_cmd_buf
, cmd_buf_len
, last_init_packet
, DESC_PACKET_TYPE_INIT
);
204 //-----------------------------------------------------------------------------
205 // Procedure: Check whether main code is download OK. If OK, turn on CPU
207 // Description: CPU register locates in different page against general register.
208 // Switch to CPU register in the begin and switch back before return
211 // Arguments: The pointer of the adapter
214 // NDIS_STATUS_FAILURE - the following initialization process should be terminated
215 // NDIS_STATUS_SUCCESS - if firmware initialization process success
216 //-----------------------------------------------------------------------------
217 bool CPUcheck_maincodeok_turnonCPU(struct net_device
*dev
)
219 struct r8192_priv
*priv
= ieee80211_priv(dev
);
220 bool rt_status
= true;
221 int check_putcodeOK_time
= 200000, check_bootOk_time
= 200000;
224 /* Check whether put code OK */
226 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
228 if((CPU_status
&CPU_GEN_PUT_CODE_OK
) || (priv
->usb_error
==true))
231 }while(check_putcodeOK_time
--);
233 if(!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
234 RT_TRACE(COMP_ERR
, "Download Firmware: Put code fail!\n");
235 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
237 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
241 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
242 write_nic_byte(dev
, CPU_GEN
, (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
245 /* Check whether CPU boot OK */
247 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
249 if((CPU_status
&CPU_GEN_BOOT_RDY
)||(priv
->usb_error
== true))
251 }while(check_bootOk_time
--);
253 if(!(CPU_status
&CPU_GEN_BOOT_RDY
)) {
254 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
256 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
261 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
262 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
267 bool CPUcheck_firmware_ready(struct net_device
*dev
)
269 struct r8192_priv
*priv
= ieee80211_priv(dev
);
270 bool rt_status
= true;
271 int check_time
= 200000;
274 /* Check Firmware Ready */
276 CPU_status
= read_nic_dword(dev
, CPU_GEN
);
278 if((CPU_status
&CPU_GEN_FIRM_RDY
)||(priv
->usb_error
== true))
281 }while(check_time
--);
283 if(!(CPU_status
&CPU_GEN_FIRM_RDY
))
284 goto CPUCheckFirmwareReady_Fail
;
286 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
290 CPUCheckFirmwareReady_Fail
:
291 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
297 bool init_firmware(struct net_device
*dev
)
299 struct r8192_priv
*priv
= ieee80211_priv(dev
);
300 bool rt_status
= TRUE
;
302 u8
*firmware_img_buf
[3] = { &rtl8190_fwboot_array
[0],
303 &rtl8190_fwmain_array
[0],
304 &rtl8190_fwdata_array
[0]};
306 u32 firmware_img_len
[3] = { sizeof(rtl8190_fwboot_array
),
307 sizeof(rtl8190_fwmain_array
),
308 sizeof(rtl8190_fwdata_array
)};
310 u8
*mapped_file
= NULL
;
312 opt_rst_type_e rst_opt
= OPT_SYSTEM_RESET
;
313 firmware_init_step_e starting_state
= FW_INIT_STEP0_BOOT
;
315 rt_firmware
*pfirmware
= priv
->pFirmware
;
316 const struct firmware
*fw_entry
;
317 const char *fw_name
[3] = { "RTL8192U/boot.img",
319 "RTL8192U/data.img"};
322 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
324 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
325 /* it is called by reset */
326 rst_opt
= OPT_SYSTEM_RESET
;
327 starting_state
= FW_INIT_STEP0_BOOT
;
328 // TODO: system reset
330 }else if(pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
331 /* it is called by Initialize */
332 rst_opt
= OPT_FIRMWARE_RESET
;
333 starting_state
= FW_INIT_STEP2_DATA
;
335 RT_TRACE(COMP_FIRMWARE
, "PlatformInitFirmware: undefined firmware state\n");
339 * Download boot, main, and data image for System reset.
340 * Download data image for firmware reseta
342 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
343 priv
->firmware_source
= FW_SOURCE_HEADER_FILE
;
345 priv
->firmware_source
= FW_SOURCE_IMG_FILE
;
347 for(init_step
= starting_state
; init_step
<= FW_INIT_STEP2_DATA
; init_step
++) {
349 * Open Image file, and map file to contineous memory if open file success.
350 * or read image file from array. Default load from IMG file
352 if(rst_opt
== OPT_SYSTEM_RESET
) {
353 switch(priv
->firmware_source
) {
354 case FW_SOURCE_IMG_FILE
:
355 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
356 if(pfirmware
->firmware_buf_size
[init_step
] == 0) {
357 rc
= request_firmware(&fw_entry
, fw_name
[init_step
],&priv
->udev
->dev
);
359 RT_TRACE(COMP_ERR
, "request firmware fail!\n");
360 goto download_firmware_fail
;
363 if(fw_entry
->size
> sizeof(pfirmware
->firmware_buf
[init_step
])) {
364 //RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
365 RT_TRACE(COMP_FIRMWARE
, "img file size exceed the container buffer fail!, entry_size = %d, buf_size = %d\n",fw_entry
->size
,sizeof(pfirmware
->firmware_buf
[init_step
]));
367 goto download_firmware_fail
;
370 if(init_step
!= FW_INIT_STEP1_MAIN
) {
371 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
372 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
375 memcpy(pfirmware
->firmware_buf
[init_step
],fw_entry
->data
,fw_entry
->size
);
376 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
;
378 memset(pfirmware
->firmware_buf
[init_step
],0,128);
379 memcpy(&pfirmware
->firmware_buf
[init_step
][128],fw_entry
->data
,fw_entry
->size
);
380 mapped_file
= pfirmware
->firmware_buf
[init_step
];
381 pfirmware
->firmware_buf_size
[init_step
] = fw_entry
->size
+128;
384 //pfirmware->firmware_buf_size = file_length;
386 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
387 if(rst_opt
== OPT_SYSTEM_RESET
) {
388 release_firmware(fw_entry
);
392 mapped_file
= pfirmware
->firmware_buf
[init_step
];
393 file_length
= pfirmware
->firmware_buf_size
[init_step
];
398 case FW_SOURCE_HEADER_FILE
:
399 mapped_file
= firmware_img_buf
[init_step
];
400 file_length
= firmware_img_len
[init_step
];
401 if(init_step
== FW_INIT_STEP2_DATA
) {
402 memcpy(pfirmware
->firmware_buf
[init_step
], mapped_file
, file_length
);
403 pfirmware
->firmware_buf_size
[init_step
] = file_length
;
412 }else if(rst_opt
== OPT_FIRMWARE_RESET
) {
413 /* we only need to download data.img here */
414 mapped_file
= pfirmware
->firmware_buf
[init_step
];
415 file_length
= pfirmware
->firmware_buf_size
[init_step
];
418 /* Download image file */
419 /* The firmware download process is just as following,
420 * 1. that is each packet will be segmented and inserted to the wait queue.
421 * 2. each packet segment will be put in the skb_buff packet.
422 * 3. each skb_buff packet data content will already include the firmware info
423 * and Tx descriptor info
425 rt_status
= fw_download_code(dev
,mapped_file
,file_length
);
427 if(rt_status
!= TRUE
) {
428 goto download_firmware_fail
;
432 case FW_INIT_STEP0_BOOT
:
434 * initialize command descriptor.
435 * will set polling bit when firmware code is also configured
437 pfirmware
->firmware_status
= FW_STATUS_1_MOVE_BOOT_CODE
;
439 // To initialize IMEM, CPU move code from 0x80000080, hence, we send 0x80 byte packet
440 rt_status
= fwSendNullPacket(dev
, RTL8190_CPU_START_OFFSET
);
441 if(rt_status
!= true)
443 RT_TRACE(COMP_INIT
, "fwSendNullPacket() fail ! \n");
444 goto download_firmware_fail
;
449 * To initialize IMEM, CPU move code from 0x80000080,
450 * hence, we send 0x80 byte packet
454 case FW_INIT_STEP1_MAIN
:
455 /* Download firmware code. Wait until Boot Ready and Turn on CPU */
456 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
458 /* Check Put Code OK and Turn On CPU */
459 rt_status
= CPUcheck_maincodeok_turnonCPU(dev
);
460 if(rt_status
!= TRUE
) {
461 RT_TRACE(COMP_ERR
, "CPUcheck_maincodeok_turnonCPU fail!\n");
462 goto download_firmware_fail
;
465 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
468 case FW_INIT_STEP2_DATA
:
469 /* download initial data code */
470 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
473 rt_status
= CPUcheck_firmware_ready(dev
);
474 if(rt_status
!= TRUE
) {
475 RT_TRACE(COMP_ERR
, "CPUcheck_firmware_ready fail(%d)!\n",rt_status
);
476 goto download_firmware_fail
;
479 /* wait until data code is initialized ready.*/
480 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
485 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
486 //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
490 download_firmware_fail
:
491 RT_TRACE(COMP_ERR
, "ERR in %s()\n", __FUNCTION__
);
499 * Procedure: (1) Transform firmware code from little endian to big endian if required.
500 * (2) Number of bytes in Firmware downloading should be multiple
501 * of 4 bytes. If length is not multiple of 4 bytes, appending of zeros is required
504 void CmdAppendZeroAndEndianTransform(
510 u2Byte ulAppendBytes
= 0, i
;
511 u2Byte ulLength
= *pLength
;
514 //memset(pDst, 0xcc, 12);
517 /* Transform from little endian to big endian */
518 //#if DEV_BUS_TYPE==PCI_INTERFACE
520 for( i
=0 ; i
<(*pLength
) ; i
+=4)
522 if((i
+3) < (*pLength
)) pDst
[i
+0] = pSrc
[i
+3];
523 if((i
+2) < (*pLength
)) pDst
[i
+1] = pSrc
[i
+2];
524 if((i
+1) < (*pLength
)) pDst
[i
+2] = pSrc
[i
+1];
525 if((i
+0) < (*pLength
)) pDst
[i
+3] = pSrc
[i
+0];
528 pDst
+= USB_HWDESC_HEADER_LEN
;
529 ulLength
-= USB_HWDESC_HEADER_LEN
;
531 for( i
=0 ; i
<ulLength
; i
+=4) {
532 if((i
+3) < ulLength
) pDst
[i
+0] = pSrc
[i
+3];
533 if((i
+2) < ulLength
) pDst
[i
+1] = pSrc
[i
+2];
534 if((i
+1) < ulLength
) pDst
[i
+2] = pSrc
[i
+1];
535 if((i
+0) < ulLength
) pDst
[i
+3] = pSrc
[i
+0];
541 if( ((*pLength
) % 4) >0)
543 ulAppendBytes
= 4-((*pLength
) % 4);
545 for(i
=0 ; i
<ulAppendBytes
; i
++)
546 pDst
[ 4*((*pLength
)/4) + i
] = 0x0;
548 *pLength
+= ulAppendBytes
;
558 PRT_TX_LOCAL_BUFFER pBuf
,
561 BOOLEAN bLastInitPacket
566 u2Byte firstDesc
,curDesc
= 0;
567 u2Byte FragIndex
=0, FragBufferIndex
=0;
569 RT_STATUS rtStatus
= RT_STATUS_SUCCESS
;
571 CmdInitTCB(Adapter
, pTcb
, pBuf
, BufferLen
);
574 if(CmdCheckFragment(Adapter
, pTcb
, pBuf
))
575 CmdFragmentTCB(Adapter
, pTcb
);
577 pTcb
->FragLength
[0] = (u2Byte
)pTcb
->BufferList
[0].Length
;
579 QueueID
=pTcb
->SpecifiedQueueID
;
580 #if DEV_BUS_TYPE!=USB_INTERFACE
581 firstDesc
=curDesc
=Adapter
->NextTxDescToFill
[QueueID
];
584 #if DEV_BUS_TYPE!=USB_INTERFACE
585 if(VacancyTxDescNum(Adapter
, QueueID
) > pTcb
->BufferCount
)
587 if(PlatformIsTxQueueAvailable(Adapter
, QueueID
, pTcb
->BufferCount
) &&
588 RTIsListEmpty(&Adapter
->TcbWaitQueue
[QueueID
]))
593 for(i
=0 ; i
<pTcb
->BufferCount
; i
++)
595 Adapter
->HalFunc
.TxFillCmdDescHandler(
598 QueueID
, //QueueIndex
600 FragBufferIndex
==0, //bFirstSeg
601 FragBufferIndex
==(pTcb
->FragBufCount
[FragIndex
]-1), //bLastSeg
602 pTcb
->BufferList
[i
].VirtualAddress
, //VirtualAddress
603 pTcb
->BufferList
[i
].PhysicalAddressLow
, //PhyAddressLow
604 pTcb
->BufferList
[i
].Length
, //BufferLen
606 (i
==(pTcb
->BufferCount
-1)) && bLastInitPacket
, //bLastInitPacket
607 PacketType
, //DescPacketType
608 pTcb
->FragLength
[FragIndex
] //PktLen
611 if(FragBufferIndex
==(pTcb
->FragBufCount
[FragIndex
]-1))
612 { // Last segment of the fragment.
617 if(FragBufferIndex
==pTcb
->FragBufCount
[FragIndex
])
623 #if DEV_BUS_TYPE!=USB_INTERFACE
624 curDesc
=(curDesc
+1)%Adapter
->NumTxDesc
[QueueID
];
629 #if DEV_BUS_TYPE!=USB_INTERFACE
630 RTInsertTailList(&Adapter
->TcbBusyQueue
[QueueID
], &pTcb
->List
);
631 IncrementTxDescToFill(Adapter
, QueueID
, pTcb
->nDescUsed
);
632 Adapter
->HalFunc
.SetTxDescOWNHandler(Adapter
, QueueID
, firstDesc
);
633 // TODO: should call poll use QueueID
634 Adapter
->HalFunc
.TxPollingHandler(Adapter
, TXCMD_QUEUE
);
638 #if DEV_BUS_TYPE!=USB_INTERFACE
639 goto CmdSendPacket_Fail
;
642 pTcb
->bLastInitPacket
= bLastInitPacket
;
643 RTInsertTailList(&Adapter
->TcbWaitQueue
[pTcb
->SpecifiedQueueID
], &pTcb
->List
);
649 #if DEV_BUS_TYPE!=USB_INTERFACE
651 rtStatus
= RT_STATUS_FAILURE
;
668 RT_STATUS rtStatus
= RT_STATUS_SUCCESS
;
672 PRT_TX_LOCAL_BUFFER pBuf
;
673 BOOLEAN bLastInitPacket
= FALSE
;
675 PlatformAcquireSpinLock(Adapter
, RT_TX_SPINLOCK
);
677 #if DEV_BUS_TYPE==USB_INTERFACE
678 Length
+= USB_HWDESC_HEADER_LEN
;
681 //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
682 if(MgntGetBuffer(Adapter
, &pTcb
, &pBuf
))
684 PlatformZeroMemory(pBuf
->Buffer
.VirtualAddress
, Length
);
685 rtStatus
= CmdSendPacket(Adapter
, pTcb
, pBuf
, Length
, DESC_PACKET_TYPE_INIT
, bLastInitPacket
); //0 : always set LastInitPacket to zero
686 //#if HAL_CODE_BASE != RTL8190HW
687 // // TODO: for test only
688 // ReturnTCB(Adapter, pTcb, RT_STATUS_SUCCESS);
690 if(rtStatus
== RT_STATUS_FAILURE
)
691 goto CmdSendNullPacket_Fail
;
693 goto CmdSendNullPacket_Fail
;
695 PlatformReleaseSpinLock(Adapter
, RT_TX_SPINLOCK
);
699 CmdSendNullPacket_Fail
:
700 PlatformReleaseSpinLock(Adapter
, RT_TX_SPINLOCK
);
701 rtStatus
= RT_STATUS_FAILURE
;
702 RT_ASSERT(rtStatus
== RT_STATUS_SUCCESS
, ("CmdSendDownloadCode fail !!\n"));