Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux...
[linux-2.6] / drivers / staging / rtl8192su / r8192S_firmware.c
1 /**************************************************************************************************
2  * Procedure:    Init boot code/firmware code/data session
3  *
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.
7  *
8  * Arguments:   The pointer of the adapter
9
10  * Returns:
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"
15 #if defined(RTL8192SE)||defined(RTL8192SU)
16 #include "r8192U.h"
17 #include "r8192S_firmware.h"
18 #include <linux/unistd.h>
19
20 #ifdef RTL8192SU
21 #include "r8192S_hw.h"
22 #include "r8192SU_HWImg.h"
23 //#include "r8192S_FwImgDTM.h"
24 #else
25 //#include "r8192U_hw.h"
26 #include "r8192xU_firmware_img.h"
27 #endif
28
29 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
30 #include <linux/firmware.h>
31 #endif
32
33 #define   byte(x,n)  ( (x >> (8 * n)) & 0xff  )
34
35 //
36 // Description:   This routine will intialize firmware. If any error occurs during the initialization
37 //                              process, the routine shall terminate immediately and return fail.
38 //
39 // Arguments:   The pointer of the adapter
40 //                         Code address (Virtual address, should fill descriptor with physical address)
41 //                         Code size
42 // Created by Roger, 2008.04.10.
43 //
44 bool FirmwareDownloadCode(struct net_device *dev, u8 *  code_virtual_address,u32 buffer_len)
45 {
46         struct r8192_priv   *priv = ieee80211_priv(dev);
47         bool                rt_status = true;
48         u16                 frag_threshold = MAX_FIRMWARE_CODE_SIZE; //Fragmentation might be required in 90/92 but not in 92S
49         u16                 frag_length, frag_offset = 0;
50         struct sk_buff      *skb;
51         unsigned char       *seg_ptr;
52         cb_desc             *tcb_desc;
53         u8                          bLastIniPkt = 0;
54         u16                         ExtraDescOffset = 0;
55
56 #ifdef RTL8192SE
57         fw_SetRQPN(dev);        // For 92SE only
58 #endif
59
60         RT_TRACE(COMP_FIRMWARE, "--->FirmwareDownloadCode()\n" );
61
62         //MAX_TRANSMIT_BUFFER_SIZE
63         if(buffer_len >= MAX_FIRMWARE_CODE_SIZE-USB_HWDESC_HEADER_LEN)
64         {
65                 RT_TRACE(COMP_ERR, "Size over MAX_FIRMWARE_CODE_SIZE! \n");
66                 goto cmdsend_downloadcode_fail;
67         }
68
69         ExtraDescOffset = USB_HWDESC_HEADER_LEN;
70
71         do {
72                 if((buffer_len-frag_offset) > frag_threshold)
73                 {
74                         frag_length = frag_threshold + ExtraDescOffset;
75                 }
76                 else
77                 {
78                         frag_length = (u16)(buffer_len - frag_offset + ExtraDescOffset);
79                 bLastIniPkt = 1;
80                 }
81
82                 /* Allocate skb buffer to contain firmware info and tx descriptor info. */
83                 skb  = dev_alloc_skb(frag_length);
84                 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
85
86                 tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
87                 tcb_desc->queue_index = TXCMD_QUEUE;
88                 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
89                 tcb_desc->bLastIniPkt = bLastIniPkt;
90
91                 skb_reserve(skb, ExtraDescOffset);
92                 seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length-ExtraDescOffset));
93                 memcpy(seg_ptr, code_virtual_address+frag_offset, (u32)(frag_length-ExtraDescOffset));
94
95                 tcb_desc->txbuf_size= frag_length;
96
97                 if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
98                         (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
99                         (priv->ieee80211->queue_stop) )
100                 {
101                         RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
102                         skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
103                 }
104                 else
105                 {
106                         priv->ieee80211->softmac_hard_start_xmit(skb,dev);
107                 }
108
109                 frag_offset += (frag_length - ExtraDescOffset);
110
111         }while(frag_offset < buffer_len);
112
113         return rt_status ;
114
115
116 cmdsend_downloadcode_fail:
117         rt_status = false;
118         RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n");
119         return rt_status;
120
121 }
122
123 #ifdef RTL8192SE
124 static void fw_SetRQPN(struct net_device *dev)
125 {
126         // Only for 92SE HW bug, we have to set RAPN before every FW download
127         // We can remove the code later.
128         write_nic_dword(dev,  RQPN, 0xffffffff);
129         write_nic_dword(dev,  RQPN+4, 0xffffffff);
130         write_nic_byte(dev,  RQPN+8, 0xff);
131         write_nic_byte(dev,  RQPN+0xB, 0x80);
132         //#if ((HAL_CODE_BASE ==  RTL8192_S) && (PLATFORM != PLATFORM_WINDOWS_USB))
133
134 }       /* fw_SetRQPN */
135 #endif
136
137 RT_STATUS
138 FirmwareEnableCPU(struct net_device *dev)
139 {
140
141         RT_STATUS       rtStatus = RT_STATUS_SUCCESS;
142         u8              tmpU1b, CPUStatus = 0;
143         u16             tmpU2b;
144         u32             iCheckTime = 200;
145
146         RT_TRACE(COMP_FIRMWARE, "-->FirmwareEnableCPU()\n" );
147 #ifdef RTL8192SE
148         fw_SetRQPN(dev);        // For 92SE only
149 #endif
150         // Enable CPU.
151         tmpU1b = read_nic_byte(dev, SYS_CLKR);
152         write_nic_byte(dev,  SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL)); //AFE source
153
154         tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
155         write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN));
156
157         //Polling IMEM Ready after CPU has refilled.
158         do
159         {
160                 CPUStatus = read_nic_byte(dev, TCR);
161                 if(CPUStatus& IMEM_RDY)
162                 {
163                         RT_TRACE(COMP_FIRMWARE, "IMEM Ready after CPU has refilled.\n");
164                         break;
165                 }
166
167                 //usleep(100);
168                 udelay(100);
169         }while(iCheckTime--);
170
171         if(!(CPUStatus & IMEM_RDY))
172                 return RT_STATUS_FAILURE;
173
174         RT_TRACE(COMP_FIRMWARE, "<--FirmwareEnableCPU(): rtStatus(%#x)\n", rtStatus);
175         return rtStatus;
176 }
177
178 FIRMWARE_8192S_STATUS
179 FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus)
180 {
181         FIRMWARE_8192S_STATUS   NextFWStatus = 0;
182
183         switch(FWCurrentStatus)
184         {
185                 case FW_STATUS_INIT:
186                         NextFWStatus = FW_STATUS_LOAD_IMEM;
187                         break;
188
189                 case FW_STATUS_LOAD_IMEM:
190                         NextFWStatus = FW_STATUS_LOAD_EMEM;
191                         break;
192
193                 case FW_STATUS_LOAD_EMEM:
194                         NextFWStatus = FW_STATUS_LOAD_DMEM;
195                         break;
196
197                 case FW_STATUS_LOAD_DMEM:
198                         NextFWStatus = FW_STATUS_READY;
199                         break;
200
201                 default:
202                         RT_TRACE(COMP_ERR,"Invalid FW Status(%#x)!!\n", FWCurrentStatus);
203                         break;
204         }
205         return  NextFWStatus;
206 }
207
208 bool
209 FirmwareCheckReady(struct net_device *dev,      u8 LoadFWStatus)
210 {
211         struct r8192_priv       *priv = ieee80211_priv(dev);
212         RT_STATUS       rtStatus = RT_STATUS_SUCCESS;
213         rt_firmware     *pFirmware = priv->pFirmware;
214         int                     PollingCnt = 1000;
215         //u8            tmpU1b, CPUStatus = 0;
216         u8              CPUStatus = 0;
217         u32             tmpU4b;
218         //bool          bOrgIMREnable;
219
220         RT_TRACE(COMP_FIRMWARE, "--->FirmwareCheckReady(): LoadStaus(%d),", LoadFWStatus);
221
222         pFirmware->FWStatus = (FIRMWARE_8192S_STATUS)LoadFWStatus;
223         if( LoadFWStatus == FW_STATUS_LOAD_IMEM)
224         {
225                 do
226                 {//Polling IMEM code done.
227                         CPUStatus = read_nic_byte(dev, TCR);
228                         if(CPUStatus& IMEM_CODE_DONE)
229                                 break;
230
231                         udelay(5);
232                 }while(PollingCnt--);
233                 if(!(CPUStatus & IMEM_CHK_RPT) || PollingCnt <= 0)
234                 {
235                         RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus);
236                         return false;
237                 }
238         }
239         else if( LoadFWStatus == FW_STATUS_LOAD_EMEM)
240         {//Check Put Code OK and Turn On CPU
241                 do
242                 {//Polling EMEM code done.
243                         CPUStatus = read_nic_byte(dev, TCR);
244                         if(CPUStatus& EMEM_CODE_DONE)
245                                 break;
246
247                         udelay(5);
248                 }while(PollingCnt--);
249                 if(!(CPUStatus & EMEM_CHK_RPT))
250                 {
251                         RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus);
252                         return false;
253                 }
254
255                 // Turn On CPU
256                 rtStatus = FirmwareEnableCPU(dev);
257                 if(rtStatus != RT_STATUS_SUCCESS)
258                 {
259                         RT_TRACE(COMP_ERR, "Enable CPU fail ! \n" );
260                         return false;
261                 }
262         }
263         else if( LoadFWStatus == FW_STATUS_LOAD_DMEM)
264         {
265                 do
266                 {//Polling DMEM code done
267                         CPUStatus = read_nic_byte(dev, TCR);
268                         if(CPUStatus& DMEM_CODE_DONE)
269                                 break;
270
271                         udelay(5);
272                 }while(PollingCnt--);
273
274                 if(!(CPUStatus & DMEM_CODE_DONE))
275                 {
276                         RT_TRACE(COMP_ERR, "Polling  DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus);
277                         return false;
278                 }
279
280                 RT_TRACE(COMP_FIRMWARE, "DMEM code download success, CPUStatus(%#x)\n", CPUStatus);
281
282 //              PollingCnt = 100; // Set polling cycle to 10ms.
283               PollingCnt = 10000; // Set polling cycle to 10ms.
284
285                 do
286                 {//Polling Load Firmware ready
287                         CPUStatus = read_nic_byte(dev, TCR);
288                         if(CPUStatus & FWRDY)
289                                 break;
290
291                         udelay(100);
292                 }while(PollingCnt--);
293
294                 RT_TRACE(COMP_FIRMWARE, "Polling Load Firmware ready, CPUStatus(%x)\n", CPUStatus);
295
296                 //if(!(CPUStatus & LOAD_FW_READY))
297                 //if((CPUStatus & LOAD_FW_READY) != 0xff)
298                 if((CPUStatus & LOAD_FW_READY) != LOAD_FW_READY)
299                 {
300                         RT_TRACE(COMP_ERR, "Polling Load Firmware ready fail ! CPUStatus(%x)\n", CPUStatus);
301                         return false;
302                 }
303
304                //
305               // <Roger_Notes> USB interface will update reserved followings parameters later!!
306               // 2008.08.28.
307               //
308 #ifdef RTL8192SE
309                 //write_nic_dword(dev, RQPN, 0x10101010);
310                 //write_nic_byte(dev,  0xAB, 0x80);
311 #endif
312
313                //
314               // <Roger_Notes> If right here, we can set TCR/RCR to desired value
315               // and config MAC lookback mode to normal mode. 2008.08.28.
316               //
317               tmpU4b = read_nic_dword(dev,TCR);
318                 write_nic_dword(dev, TCR, (tmpU4b&(~TCR_ICV)));
319
320                 tmpU4b = read_nic_dword(dev, RCR);
321                 write_nic_dword(dev, RCR,
322                         (tmpU4b|RCR_APPFCS|RCR_APP_ICV|RCR_APP_MIC));
323
324                 RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current RCR settings(%#x)\n", tmpU4b);
325
326 #if (defined (RTL8192SU_FPGA_2MAC_VERIFICATION) ||defined (RTL8192SU_ASIC_VERIFICATION))
327 #ifdef NOT_YET   //YJ,TMP
328                 priv->TransmitConfig = read_nic_dword(dev, TCR);
329                 RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current TCR settings(%x)\n", priv->TransmitConfig);
330                 pHalData->FwRsvdTxPageCfg = read_nic_byte(dev, FW_RSVD_PG_CRTL);
331 #endif
332 #endif
333
334                 // Set to normal mode.
335                 write_nic_byte(dev, LBKMD_SEL, LBK_NORMAL);
336
337         }
338
339         RT_TRACE(COMP_FIRMWARE, "<---FirmwareCheckReady(): LoadFWStatus(%d), rtStatus(%x)\n", LoadFWStatus, rtStatus);
340         return (rtStatus == RT_STATUS_SUCCESS) ? true:false;
341 }
342
343 //
344 // Description:   This routine is to update the RF types in FW header partially.
345 //
346 // Created by Roger, 2008.12.24.
347 //
348 u8 FirmwareHeaderMapRfType(struct net_device *dev)
349 {
350         struct r8192_priv       *priv = ieee80211_priv(dev);
351         switch(priv->rf_type)
352         {
353                 case RF_1T1R:   return 0x11;
354                 case RF_1T2R:   return 0x12;
355                 case RF_2T2R:   return 0x22;
356                 case RF_2T2R_GREEN:     return 0x92;
357                 default:
358                         RT_TRACE(COMP_INIT, "Unknown RF type(%x)\n",priv->rf_type);
359                         break;
360         }
361         return 0x22;
362 }
363
364
365 //
366 // Description:   This routine is to update the private parts in FW header partially.
367 //
368 // Created by Roger, 2008.12.18.
369 //
370 void FirmwareHeaderPriveUpdate(struct net_device *dev, PRT_8192S_FIRMWARE_PRIV  pFwPriv)
371 {
372         struct r8192_priv       *priv = ieee80211_priv(dev);
373 #ifdef RTL8192SU
374         // Update USB endpoint number for RQPN settings.
375         pFwPriv->usb_ep_num = priv->EEPROMUsbEndPointNumber; // endpoint number: 4, 6 and 11.
376         RT_TRACE(COMP_INIT, "FirmwarePriveUpdate(): usb_ep_num(%#x)\n", pFwPriv->usb_ep_num);
377 #endif
378
379         // Update RF types for RATR settings.
380         pFwPriv->rf_config = FirmwareHeaderMapRfType(dev);
381 }
382
383
384
385 bool FirmwareDownload92S(struct net_device *dev)
386 {
387         struct r8192_priv       *priv = ieee80211_priv(dev);
388         bool                            rtStatus = true;
389         const char              *pFwImageFileName[1] = {"RTL8192SU/rtl8192sfw.bin"};
390         u8                              *pucMappedFile = NULL;
391         u32                             ulFileLength, ulInitStep = 0;
392         u8                              FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;
393         rt_firmware             *pFirmware = priv->pFirmware;
394         u8                              FwStatus = FW_STATUS_INIT;
395         PRT_8192S_FIRMWARE_HDR          pFwHdr = NULL;
396         PRT_8192S_FIRMWARE_PRIV         pFwPriv = NULL;
397         int                             rc;
398         const struct firmware   *fw_entry;
399         u32                             file_length = 0;
400
401         pFirmware->FWStatus = FW_STATUS_INIT;
402
403         RT_TRACE(COMP_FIRMWARE, " --->FirmwareDownload92S()\n");
404
405         //3//
406         //3 //<1> Open Image file, and map file to contineous memory if open file success.
407         //3  //        or read image file from array. Default load from BIN file
408         //3//
409 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
410         priv->firmware_source = FW_SOURCE_HEADER_FILE;
411 #else
412         priv->firmware_source = FW_SOURCE_IMG_FILE;// We should decided by Reg.
413 #endif
414
415         switch( priv->firmware_source )
416         {
417                 case FW_SOURCE_IMG_FILE:
418 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
419                         if(pFirmware->szFwTmpBufferLen == 0)
420                         {
421
422                                 rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->udev->dev);//===>1
423                                 if(rc < 0 ) {
424                                         RT_TRACE(COMP_ERR, "request firmware fail!\n");
425                                         goto DownloadFirmware_Fail;
426                                 }
427
428                                 if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer))
429                                 {
430                                         RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
431                                         release_firmware(fw_entry);
432                                         goto DownloadFirmware_Fail;
433                                 }
434
435                                 memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
436                                 pFirmware->szFwTmpBufferLen = fw_entry->size;
437                                 release_firmware(fw_entry);
438
439                                 pucMappedFile = pFirmware->szFwTmpBuffer;
440                                 file_length = pFirmware->szFwTmpBufferLen;
441
442                                 //Retrieve FW header.
443                                 pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
444                                 pFwHdr = pFirmware->pFwHeader;
445                                 RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
446                                                 pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
447                                                 pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
448                                 pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);
449                                 if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
450                                 {
451                                         RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
452                                                         __FUNCTION__);
453                                         goto DownloadFirmware_Fail;
454                                 } else {
455                                         pucMappedFile+=FwHdrSize;
456
457                                         //Retrieve IMEM image.
458                                         memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
459                                         pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
460                                 }
461
462                                 if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
463                                 {
464                                         RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
465                                                         __FUNCTION__);
466                                         goto DownloadFirmware_Fail;
467                                 } else {
468                                         pucMappedFile += pFirmware->FwIMEMLen;
469
470                                         /* Retriecve EMEM image */
471                                         memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);//===>6
472                                         pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
473                                 }
474
475
476                         }
477 #endif
478                         break;
479
480                 case FW_SOURCE_HEADER_FILE:
481 #if 1
482 #define Rtl819XFwImageArray Rtl8192SUFwImgArray
483                         //2008.11.10 Add by tynli.
484                         pucMappedFile = Rtl819XFwImageArray;
485                         ulFileLength = ImgArrayLength;
486
487                         RT_TRACE(COMP_INIT,"Fw download from header.\n");
488                         /* Retrieve FW header*/
489                         pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
490                         pFwHdr = pFirmware->pFwHeader;
491                         RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
492                                         pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
493                                         pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
494                         pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);
495
496                         if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
497                         {
498                                 printk("FirmwareDownload92S(): memory for data image is less than IMEM required\n");
499                                 goto DownloadFirmware_Fail;
500                         } else {
501                                 pucMappedFile+=FwHdrSize;
502                                 //Retrieve IMEM image.
503                                 memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
504                                 pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
505                         }
506
507                         if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
508                         {
509                                 printk(" FirmwareDownload92S(): memory for data image is less than EMEM required\n");
510                                 goto DownloadFirmware_Fail;
511                         } else {
512                                 pucMappedFile+= pFirmware->FwIMEMLen;
513
514                                 //Retriecve EMEM image.
515                                 memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
516                                 pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
517                         }
518 #endif
519                         break;
520                 default:
521                         break;
522         }
523
524         FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
525         while(FwStatus!= FW_STATUS_READY)
526         {
527                 // Image buffer redirection.
528                 switch(FwStatus)
529                 {
530                         case FW_STATUS_LOAD_IMEM:
531                                 pucMappedFile = pFirmware->FwIMEM;
532                                 ulFileLength = pFirmware->FwIMEMLen;
533                                 break;
534
535                         case FW_STATUS_LOAD_EMEM:
536                                 pucMappedFile = pFirmware->FwEMEM;
537                                 ulFileLength = pFirmware->FwEMEMLen;
538                                 break;
539
540                         case FW_STATUS_LOAD_DMEM:
541                                 /* <Roger_Notes> Partial update the content of header private. 2008.12.18 */
542                                 pFwHdr = pFirmware->pFwHeader;
543                                 pFwPriv = (PRT_8192S_FIRMWARE_PRIV)&pFwHdr->FWPriv;
544                                 FirmwareHeaderPriveUpdate(dev, pFwPriv);
545                                 pucMappedFile = (u8*)(pFirmware->pFwHeader)+RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
546                                 ulFileLength = FwHdrSize-RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
547                                 break;
548
549                         default:
550                                 RT_TRACE(COMP_ERR, "Unexpected Download step!!\n");
551                                 goto DownloadFirmware_Fail;
552                                 break;
553                 }
554
555                 //3//
556                 //3// <2> Download image file
557         //3     //
558                 rtStatus = FirmwareDownloadCode(dev, pucMappedFile, ulFileLength);
559
560                 if(rtStatus != true)
561                 {
562                         RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n" );
563                         goto DownloadFirmware_Fail;
564                 }
565
566                 //3//
567                 //3// <3> Check whether load FW process is ready
568         //3     //
569                 rtStatus = FirmwareCheckReady(dev, FwStatus);
570
571                 if(rtStatus != true)
572                 {
573                         RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n");
574                         goto DownloadFirmware_Fail;
575                 }
576
577                 FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
578         }
579
580         RT_TRACE(COMP_FIRMWARE, "Firmware Download Success!!\n");
581         return rtStatus;
582
583         DownloadFirmware_Fail:
584         RT_TRACE(COMP_ERR, "Firmware Download Fail!!%x\n",read_nic_word(dev, TCR));
585         rtStatus = false;
586         return rtStatus;
587 }
588 #else
589 void firmware_init_param(struct net_device *dev)
590 {
591         struct r8192_priv       *priv = ieee80211_priv(dev);
592         rt_firmware             *pfirmware = priv->pFirmware;
593
594         pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
595 }
596
597 /*
598  * segment the img and use the ptr and length to remember info on each segment
599  *
600  */
601 bool fw_download_code(struct net_device *dev, u8 *code_virtual_address, u32 buffer_len)
602 {
603         struct r8192_priv   *priv = ieee80211_priv(dev);
604         bool                rt_status = true;
605         //u16               frag_threshold;
606         u16                 frag_length, frag_offset = 0;
607         //u16               total_size;
608         int                 i;
609
610         //rt_firmware       *pfirmware = priv->pFirmware;
611         struct sk_buff      *skb;
612         unsigned char       *seg_ptr;
613         cb_desc             *tcb_desc;
614         u8                  bLastIniPkt;
615 #ifdef RTL8192SE
616         fw_SetRQPN(dev);        // For 92SE only
617 #endif
618
619 #ifndef RTL8192SU
620         if(buffer_len >= 64000-USB_HWDESC_HEADER_LEN)
621         {
622                 return rt_status;
623         }
624         firmware_init_param(dev);
625         //Fragmentation might be required
626         frag_threshold = pfirmware->cmdpacket_frag_thresold;
627 #endif
628
629         do {
630 #ifndef RTL8192SU
631                 if((buffer_len - frag_offset) > frag_threshold) {
632                         frag_length = frag_threshold ;
633                         bLastIniPkt = 0;
634
635                 } else
636 #endif
637                 {
638                         frag_length = buffer_len - frag_offset;
639                         bLastIniPkt = 1;
640
641                 }
642
643                 /* Allocate skb buffer to contain firmware info and tx descriptor info
644                  * add 4 to avoid packet appending overflow.
645                  * */
646                 #ifdef RTL8192U
647                 skb  = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
648                 #else
649                 skb  = dev_alloc_skb(frag_length + 4);
650                 #endif
651                 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
652                 tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
653                 tcb_desc->queue_index = TXCMD_QUEUE;
654                 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
655                 tcb_desc->bLastIniPkt = bLastIniPkt;
656
657                 #ifdef RTL8192U
658                 skb_reserve(skb, USB_HWDESC_HEADER_LEN);
659                 #endif
660                 seg_ptr = skb->data;
661                 /*
662                  * Transform from little endian to big endian
663                  * and pending  zero
664                  */
665                 for(i=0 ; i < frag_length; i+=4) {
666                         *seg_ptr++ = ((i+0)<frag_length)?code_virtual_address[i+3]:0;
667                         *seg_ptr++ = ((i+1)<frag_length)?code_virtual_address[i+2]:0;
668                         *seg_ptr++ = ((i+2)<frag_length)?code_virtual_address[i+1]:0;
669                         *seg_ptr++ = ((i+3)<frag_length)?code_virtual_address[i+0]:0;
670                 }
671                 tcb_desc->txbuf_size= (u16)i;
672                 skb_put(skb, i);
673
674                 if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
675                         (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
676                         (priv->ieee80211->queue_stop) ) {
677                         RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
678                         skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
679                 } else {
680                         priv->ieee80211->softmac_hard_start_xmit(skb,dev);
681                 }
682
683                 code_virtual_address += frag_length;
684                 frag_offset += frag_length;
685
686         }while(frag_offset < buffer_len);
687
688         return rt_status;
689
690 #if 0
691 cmdsend_downloadcode_fail:
692         rt_status = false;
693         RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n");
694         return rt_status;
695 #endif
696 }
697
698 bool
699 fwSendNullPacket(
700         struct net_device *dev,
701         u32                     Length
702 )
703 {
704         bool    rtStatus = true;
705         struct r8192_priv   *priv = ieee80211_priv(dev);
706         struct sk_buff      *skb;
707         cb_desc             *tcb_desc;
708         unsigned char       *ptr_buf;
709         bool    bLastInitPacket = false;
710
711         //PlatformAcquireSpinLock(dev, RT_TX_SPINLOCK);
712
713         //Get TCB and local buffer from common pool. (It is shared by CmdQ, MgntQ, and USB coalesce DataQ)
714         skb  = dev_alloc_skb(Length+ 4);
715         memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
716         tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
717         tcb_desc->queue_index = TXCMD_QUEUE;
718         tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
719         tcb_desc->bLastIniPkt = bLastInitPacket;
720         ptr_buf = skb_put(skb, Length);
721         memset(ptr_buf,0,Length);
722         tcb_desc->txbuf_size= (u16)Length;
723
724         if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
725                         (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
726                         (priv->ieee80211->queue_stop) ) {
727                         RT_TRACE(COMP_FIRMWARE,"===================NULL packet==================================> tx full!\n");
728                         skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
729                 } else {
730                         priv->ieee80211->softmac_hard_start_xmit(skb,dev);
731                 }
732
733         //PlatformReleaseSpinLock(dev, RT_TX_SPINLOCK);
734         return rtStatus;
735 }
736
737 //-----------------------------------------------------------------------------
738 // Procedure:    Check whether main code is download OK. If OK, turn on CPU
739 //
740 // Description:   CPU register locates in different page against general register.
741 //                          Switch to CPU register in the begin and switch back before return
742 //
743 //
744 // Arguments:   The pointer of the dev
745 //
746 // Returns:
747 //        NDIS_STATUS_FAILURE - the following initialization process should be terminated
748 //        NDIS_STATUS_SUCCESS - if firmware initialization process success
749 //-----------------------------------------------------------------------------
750 bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
751 {
752         bool            rt_status = true;
753         int             check_putcodeOK_time = 200000, check_bootOk_time = 200000;
754         u32             CPU_status = 0;
755
756         /* Check whether put code OK */
757         do {
758                 CPU_status = read_nic_dword(dev, CPU_GEN);
759
760                 if(CPU_status&CPU_GEN_PUT_CODE_OK)
761                         break;
762
763         }while(check_putcodeOK_time--);
764
765         if(!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
766                 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
767                 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
768         } else {
769                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
770         }
771
772         /* Turn On CPU */
773         CPU_status = read_nic_dword(dev, CPU_GEN);
774         write_nic_byte(dev, CPU_GEN, (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
775         mdelay(1000);
776
777         /* Check whether CPU boot OK */
778         do {
779                 CPU_status = read_nic_dword(dev, CPU_GEN);
780
781                 if(CPU_status&CPU_GEN_BOOT_RDY)
782                         break;
783         }while(check_bootOk_time--);
784
785         if(!(CPU_status&CPU_GEN_BOOT_RDY)) {
786                 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
787         } else {
788                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
789         }
790
791         return rt_status;
792
793 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
794         RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__);
795         rt_status = FALSE;
796         return rt_status;
797 }
798
799 bool CPUcheck_firmware_ready(struct net_device *dev)
800 {
801
802         bool            rt_status = true;
803         int             check_time = 200000;
804         u32             CPU_status = 0;
805
806         /* Check Firmware Ready */
807         do {
808                 CPU_status = read_nic_dword(dev, CPU_GEN);
809
810                 if(CPU_status&CPU_GEN_FIRM_RDY)
811                         break;
812
813         }while(check_time--);
814
815         if(!(CPU_status&CPU_GEN_FIRM_RDY))
816                 goto CPUCheckFirmwareReady_Fail;
817         else
818                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
819
820         return rt_status;
821
822 CPUCheckFirmwareReady_Fail:
823         RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__);
824         rt_status = false;
825         return rt_status;
826
827 }
828
829 bool init_firmware(struct net_device *dev)
830 {
831         struct r8192_priv       *priv = ieee80211_priv(dev);
832         bool                    rt_status = TRUE;
833
834         u8                      *firmware_img_buf[3] = { &rtl8190_fwboot_array[0],
835                                                          &rtl8190_fwmain_array[0],
836                                                          &rtl8190_fwdata_array[0]};
837
838         u32                     firmware_img_len[3] = { sizeof(rtl8190_fwboot_array),
839                                                         sizeof(rtl8190_fwmain_array),
840                                                         sizeof(rtl8190_fwdata_array)};
841         u32                     file_length = 0;
842         u8                      *mapped_file = NULL;
843         u32                     init_step = 0;
844         opt_rst_type_e  rst_opt = OPT_SYSTEM_RESET;
845         firmware_init_step_e    starting_state = FW_INIT_STEP0_BOOT;
846
847         rt_firmware             *pfirmware = priv->pFirmware;
848         const struct firmware   *fw_entry;
849         const char *fw_name[3] = { "RTL8192U/boot.img",
850                            "RTL8192U/main.img",
851                            "RTL8192U/data.img"};
852         int rc;
853
854         RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
855
856         if (pfirmware->firmware_status == FW_STATUS_0_INIT ) {
857                 /* it is called by reset */
858                 rst_opt = OPT_SYSTEM_RESET;
859                 starting_state = FW_INIT_STEP0_BOOT;
860                 // TODO: system reset
861
862         }else if(pfirmware->firmware_status == FW_STATUS_5_READY) {
863                 /* it is called by Initialize */
864                 rst_opt = OPT_FIRMWARE_RESET;
865                 starting_state = FW_INIT_STEP2_DATA;
866         }else {
867                  RT_TRACE(COMP_FIRMWARE, "PlatformInitFirmware: undefined firmware state\n");
868         }
869
870         /*
871          * Download boot, main, and data image for System reset.
872          * Download data image for firmware reseta
873          */
874 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
875         priv->firmware_source = FW_SOURCE_HEADER_FILE;
876 #else
877         priv->firmware_source = FW_SOURCE_IMG_FILE;
878 #endif
879         for(init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
880                 /*
881                  * Open Image file, and map file to contineous memory if open file success.
882                  * or read image file from array. Default load from IMG file
883                  */
884                 if(rst_opt == OPT_SYSTEM_RESET) {
885                         switch(priv->firmware_source) {
886                                 case FW_SOURCE_IMG_FILE:
887                                 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
888                                         rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
889                                         if(rc < 0 ) {
890                                                 RT_TRACE(COMP_ERR, "request firmware fail!\n");
891                                                 goto download_firmware_fail;
892                                         }
893
894                                         if(fw_entry->size > sizeof(pfirmware->firmware_buf)) {
895                                                 RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
896                                                 goto download_firmware_fail;
897                                         }
898
899                                         if(init_step != FW_INIT_STEP1_MAIN) {
900                                                 memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
901                                                 mapped_file = pfirmware->firmware_buf;
902                                                 file_length = fw_entry->size;
903                                         } else {
904                                         #ifdef RTL8190P
905                                                 memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
906                                                 mapped_file = pfirmware->firmware_buf;
907                                                 file_length = fw_entry->size;
908                                         #else
909                                                 memset(pfirmware->firmware_buf,0,128);
910                                                 memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
911                                                 mapped_file = pfirmware->firmware_buf;
912                                                 file_length = fw_entry->size + 128;
913                                         #endif
914                                         }
915                                         pfirmware->firmware_buf_size = file_length;
916                                         #endif
917                                         break;
918
919                                 case FW_SOURCE_HEADER_FILE:
920                                         mapped_file =  firmware_img_buf[init_step];
921                                         file_length  = firmware_img_len[init_step];
922                                         if(init_step == FW_INIT_STEP2_DATA) {
923                                                 memcpy(pfirmware->firmware_buf, mapped_file, file_length);
924                                                 pfirmware->firmware_buf_size = file_length;
925                                         }
926                                         break;
927
928                                 default:
929                                         break;
930                         }
931
932
933                 }else if(rst_opt == OPT_FIRMWARE_RESET ) {
934                         /* we only need to download data.img here */
935                         mapped_file = pfirmware->firmware_buf;
936                         file_length = pfirmware->firmware_buf_size;
937                 }
938
939                 /* Download image file */
940                 /* The firmware download process is just as following,
941                  * 1. that is each packet will be segmented and inserted to the wait queue.
942                  * 2. each packet segment will be put in the skb_buff packet.
943                  * 3. each skb_buff packet data content will already include the firmware info
944                  *   and Tx descriptor info
945                  * */
946                 rt_status = fw_download_code(dev,mapped_file,file_length);
947                 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
948                 if(rst_opt == OPT_SYSTEM_RESET) {
949                         release_firmware(fw_entry);
950                 }
951                 #endif
952
953                 if(rt_status != TRUE) {
954                         goto download_firmware_fail;
955                 }
956
957                 switch(init_step) {
958                         case FW_INIT_STEP0_BOOT:
959                                 /* Download boot
960                                  * initialize command descriptor.
961                                  * will set polling bit when firmware code is also configured
962                                  */
963                                 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
964 #ifdef RTL8190P
965                                 // To initialize IMEM, CPU move code  from 0x80000080, hence, we send 0x80 byte packet
966                                 rt_status = fwSendNullPacket(dev, RTL8190_CPU_START_OFFSET);
967                                 if(rt_status != true)
968                                 {
969                                         RT_TRACE(COMP_INIT, "fwSendNullPacket() fail ! \n");
970                                         goto  download_firmware_fail;
971                                 }
972 #endif
973                                 //mdelay(1000);
974                                 /*
975                                  * To initialize IMEM, CPU move code  from 0x80000080,
976                                  * hence, we send 0x80 byte packet
977                                  */
978                                 break;
979
980                         case FW_INIT_STEP1_MAIN:
981                                 /* Download firmware code. Wait until Boot Ready and Turn on CPU */
982                                 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
983
984                                 /* Check Put Code OK and Turn On CPU */
985                                 rt_status = CPUcheck_maincodeok_turnonCPU(dev);
986                                 if(rt_status != TRUE) {
987                                         RT_TRACE(COMP_ERR, "CPUcheck_maincodeok_turnonCPU fail!\n");
988                                         goto download_firmware_fail;
989                                 }
990
991                                 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
992                                 break;
993
994                         case FW_INIT_STEP2_DATA:
995                                 /* download initial data code */
996                                 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
997                                 mdelay(1);
998
999                                 rt_status = CPUcheck_firmware_ready(dev);
1000                                 if(rt_status != TRUE) {
1001                                         RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status);
1002                                         goto download_firmware_fail;
1003                                 }
1004
1005                                 /* wait until data code is initialized ready.*/
1006                                 pfirmware->firmware_status = FW_STATUS_5_READY;
1007                                 break;
1008                 }
1009         }
1010
1011         RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
1012         //assert(pfirmware->firmware_status == FW_STATUS_5_READY, ("Firmware Download Fail\n"));
1013
1014         return rt_status;
1015
1016 download_firmware_fail:
1017         RT_TRACE(COMP_ERR, "ERR in %s()\n", __FUNCTION__);
1018         rt_status = FALSE;
1019         return rt_status;
1020
1021 }
1022 #endif
1023