f508c62606430aa554658f62628c1e5e6e3e12a9
[safe/jmp/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 "r8192U.h"
15 #include "r8192S_firmware.h"
16 #include <linux/unistd.h>
17
18 #include "r8192S_hw.h"
19 #include "r8192SU_HWImg.h"
20 //#include "r8192S_FwImgDTM.h"
21
22 #include <linux/firmware.h>
23
24 #define   byte(x,n)  ( (x >> (8 * n)) & 0xff  )
25
26 //
27 // Description:   This routine will intialize firmware. If any error occurs during the initialization
28 //                              process, the routine shall terminate immediately and return fail.
29 //
30 // Arguments:   The pointer of the adapter
31 //                         Code address (Virtual address, should fill descriptor with physical address)
32 //                         Code size
33 // Created by Roger, 2008.04.10.
34 //
35 bool FirmwareDownloadCode(struct net_device *dev, u8 *  code_virtual_address,u32 buffer_len)
36 {
37         struct r8192_priv   *priv = ieee80211_priv(dev);
38         bool                rt_status = true;
39         u16                 frag_threshold = MAX_FIRMWARE_CODE_SIZE; //Fragmentation might be required in 90/92 but not in 92S
40         u16                 frag_length, frag_offset = 0;
41         struct sk_buff      *skb;
42         unsigned char       *seg_ptr;
43         cb_desc             *tcb_desc;
44         u8                          bLastIniPkt = 0;
45         u16                         ExtraDescOffset = 0;
46
47
48         RT_TRACE(COMP_FIRMWARE, "--->FirmwareDownloadCode()\n" );
49
50         //MAX_TRANSMIT_BUFFER_SIZE
51         if(buffer_len >= MAX_FIRMWARE_CODE_SIZE-USB_HWDESC_HEADER_LEN)
52         {
53                 RT_TRACE(COMP_ERR, "Size over MAX_FIRMWARE_CODE_SIZE! \n");
54                 goto cmdsend_downloadcode_fail;
55         }
56
57         ExtraDescOffset = USB_HWDESC_HEADER_LEN;
58
59         do {
60                 if((buffer_len-frag_offset) > frag_threshold)
61                 {
62                         frag_length = frag_threshold + ExtraDescOffset;
63                 }
64                 else
65                 {
66                         frag_length = (u16)(buffer_len - frag_offset + ExtraDescOffset);
67                 bLastIniPkt = 1;
68                 }
69
70                 /* Allocate skb buffer to contain firmware info and tx descriptor info. */
71                 skb  = dev_alloc_skb(frag_length);
72                 memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
73
74                 tcb_desc = (cb_desc*)(skb->cb + MAX_DEV_ADDR_SIZE);
75                 tcb_desc->queue_index = TXCMD_QUEUE;
76                 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
77                 tcb_desc->bLastIniPkt = bLastIniPkt;
78
79                 skb_reserve(skb, ExtraDescOffset);
80                 seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length-ExtraDescOffset));
81                 memcpy(seg_ptr, code_virtual_address+frag_offset, (u32)(frag_length-ExtraDescOffset));
82
83                 tcb_desc->txbuf_size= frag_length;
84
85                 if(!priv->ieee80211->check_nic_enough_desc(dev,tcb_desc->queue_index)||
86                         (!skb_queue_empty(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index]))||\
87                         (priv->ieee80211->queue_stop) )
88                 {
89                         RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
90                         skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
91                 }
92                 else
93                 {
94                         priv->ieee80211->softmac_hard_start_xmit(skb,dev);
95                 }
96
97                 frag_offset += (frag_length - ExtraDescOffset);
98
99         }while(frag_offset < buffer_len);
100
101         return rt_status ;
102
103
104 cmdsend_downloadcode_fail:
105         rt_status = false;
106         RT_TRACE(COMP_ERR, "CmdSendDownloadCode fail !!\n");
107         return rt_status;
108
109 }
110
111
112 RT_STATUS
113 FirmwareEnableCPU(struct net_device *dev)
114 {
115
116         RT_STATUS       rtStatus = RT_STATUS_SUCCESS;
117         u8              tmpU1b, CPUStatus = 0;
118         u16             tmpU2b;
119         u32             iCheckTime = 200;
120
121         RT_TRACE(COMP_FIRMWARE, "-->FirmwareEnableCPU()\n" );
122         // Enable CPU.
123         tmpU1b = read_nic_byte(dev, SYS_CLKR);
124         write_nic_byte(dev,  SYS_CLKR, (tmpU1b|SYS_CPU_CLKSEL)); //AFE source
125
126         tmpU2b = read_nic_word(dev, SYS_FUNC_EN);
127         write_nic_word(dev, SYS_FUNC_EN, (tmpU2b|FEN_CPUEN));
128
129         //Polling IMEM Ready after CPU has refilled.
130         do
131         {
132                 CPUStatus = read_nic_byte(dev, TCR);
133                 if(CPUStatus& IMEM_RDY)
134                 {
135                         RT_TRACE(COMP_FIRMWARE, "IMEM Ready after CPU has refilled.\n");
136                         break;
137                 }
138
139                 //usleep(100);
140                 udelay(100);
141         }while(iCheckTime--);
142
143         if(!(CPUStatus & IMEM_RDY))
144                 return RT_STATUS_FAILURE;
145
146         RT_TRACE(COMP_FIRMWARE, "<--FirmwareEnableCPU(): rtStatus(%#x)\n", rtStatus);
147         return rtStatus;
148 }
149
150 FIRMWARE_8192S_STATUS
151 FirmwareGetNextStatus(FIRMWARE_8192S_STATUS FWCurrentStatus)
152 {
153         FIRMWARE_8192S_STATUS   NextFWStatus = 0;
154
155         switch(FWCurrentStatus)
156         {
157                 case FW_STATUS_INIT:
158                         NextFWStatus = FW_STATUS_LOAD_IMEM;
159                         break;
160
161                 case FW_STATUS_LOAD_IMEM:
162                         NextFWStatus = FW_STATUS_LOAD_EMEM;
163                         break;
164
165                 case FW_STATUS_LOAD_EMEM:
166                         NextFWStatus = FW_STATUS_LOAD_DMEM;
167                         break;
168
169                 case FW_STATUS_LOAD_DMEM:
170                         NextFWStatus = FW_STATUS_READY;
171                         break;
172
173                 default:
174                         RT_TRACE(COMP_ERR,"Invalid FW Status(%#x)!!\n", FWCurrentStatus);
175                         break;
176         }
177         return  NextFWStatus;
178 }
179
180 bool
181 FirmwareCheckReady(struct net_device *dev,      u8 LoadFWStatus)
182 {
183         struct r8192_priv       *priv = ieee80211_priv(dev);
184         RT_STATUS       rtStatus = RT_STATUS_SUCCESS;
185         rt_firmware     *pFirmware = priv->pFirmware;
186         int                     PollingCnt = 1000;
187         //u8            tmpU1b, CPUStatus = 0;
188         u8              CPUStatus = 0;
189         u32             tmpU4b;
190         //bool          bOrgIMREnable;
191
192         RT_TRACE(COMP_FIRMWARE, "--->FirmwareCheckReady(): LoadStaus(%d),", LoadFWStatus);
193
194         pFirmware->FWStatus = (FIRMWARE_8192S_STATUS)LoadFWStatus;
195         if( LoadFWStatus == FW_STATUS_LOAD_IMEM)
196         {
197                 do
198                 {//Polling IMEM code done.
199                         CPUStatus = read_nic_byte(dev, TCR);
200                         if(CPUStatus& IMEM_CODE_DONE)
201                                 break;
202
203                         udelay(5);
204                 }while(PollingCnt--);
205                 if(!(CPUStatus & IMEM_CHK_RPT) || PollingCnt <= 0)
206                 {
207                         RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\r\n", CPUStatus);
208                         return false;
209                 }
210         }
211         else if( LoadFWStatus == FW_STATUS_LOAD_EMEM)
212         {//Check Put Code OK and Turn On CPU
213                 do
214                 {//Polling EMEM code done.
215                         CPUStatus = read_nic_byte(dev, TCR);
216                         if(CPUStatus& EMEM_CODE_DONE)
217                                 break;
218
219                         udelay(5);
220                 }while(PollingCnt--);
221                 if(!(CPUStatus & EMEM_CHK_RPT))
222                 {
223                         RT_TRACE(COMP_ERR, "FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\r\n", CPUStatus);
224                         return false;
225                 }
226
227                 // Turn On CPU
228                 rtStatus = FirmwareEnableCPU(dev);
229                 if(rtStatus != RT_STATUS_SUCCESS)
230                 {
231                         RT_TRACE(COMP_ERR, "Enable CPU fail ! \n" );
232                         return false;
233                 }
234         }
235         else if( LoadFWStatus == FW_STATUS_LOAD_DMEM)
236         {
237                 do
238                 {//Polling DMEM code done
239                         CPUStatus = read_nic_byte(dev, TCR);
240                         if(CPUStatus& DMEM_CODE_DONE)
241                                 break;
242
243                         udelay(5);
244                 }while(PollingCnt--);
245
246                 if(!(CPUStatus & DMEM_CODE_DONE))
247                 {
248                         RT_TRACE(COMP_ERR, "Polling  DMEM code done fail ! CPUStatus(%#x)\n", CPUStatus);
249                         return false;
250                 }
251
252                 RT_TRACE(COMP_FIRMWARE, "DMEM code download success, CPUStatus(%#x)\n", CPUStatus);
253
254 //              PollingCnt = 100; // Set polling cycle to 10ms.
255               PollingCnt = 10000; // Set polling cycle to 10ms.
256
257                 do
258                 {//Polling Load Firmware ready
259                         CPUStatus = read_nic_byte(dev, TCR);
260                         if(CPUStatus & FWRDY)
261                                 break;
262
263                         udelay(100);
264                 }while(PollingCnt--);
265
266                 RT_TRACE(COMP_FIRMWARE, "Polling Load Firmware ready, CPUStatus(%x)\n", CPUStatus);
267
268                 //if(!(CPUStatus & LOAD_FW_READY))
269                 //if((CPUStatus & LOAD_FW_READY) != 0xff)
270                 if((CPUStatus & LOAD_FW_READY) != LOAD_FW_READY)
271                 {
272                         RT_TRACE(COMP_ERR, "Polling Load Firmware ready fail ! CPUStatus(%x)\n", CPUStatus);
273                         return false;
274                 }
275
276                //
277               // <Roger_Notes> USB interface will update reserved followings parameters later!!
278               // 2008.08.28.
279               //
280
281                //
282               // <Roger_Notes> If right here, we can set TCR/RCR to desired value
283               // and config MAC lookback mode to normal mode. 2008.08.28.
284               //
285               tmpU4b = read_nic_dword(dev,TCR);
286                 write_nic_dword(dev, TCR, (tmpU4b&(~TCR_ICV)));
287
288                 tmpU4b = read_nic_dword(dev, RCR);
289                 write_nic_dword(dev, RCR,
290                         (tmpU4b|RCR_APPFCS|RCR_APP_ICV|RCR_APP_MIC));
291
292                 RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current RCR settings(%#x)\n", tmpU4b);
293
294 #ifdef NOT_YET   //YJ,TMP
295                 priv->TransmitConfig = read_nic_dword(dev, TCR);
296                 RT_TRACE(COMP_FIRMWARE, "FirmwareCheckReady(): Current TCR settings(%x)\n", priv->TransmitConfig);
297                 pHalData->FwRsvdTxPageCfg = read_nic_byte(dev, FW_RSVD_PG_CRTL);
298 #endif
299
300                 // Set to normal mode.
301                 write_nic_byte(dev, LBKMD_SEL, LBK_NORMAL);
302
303         }
304
305         RT_TRACE(COMP_FIRMWARE, "<---FirmwareCheckReady(): LoadFWStatus(%d), rtStatus(%x)\n", LoadFWStatus, rtStatus);
306         return (rtStatus == RT_STATUS_SUCCESS) ? true:false;
307 }
308
309 //
310 // Description:   This routine is to update the RF types in FW header partially.
311 //
312 // Created by Roger, 2008.12.24.
313 //
314 u8 FirmwareHeaderMapRfType(struct net_device *dev)
315 {
316         struct r8192_priv       *priv = ieee80211_priv(dev);
317         switch(priv->rf_type)
318         {
319                 case RF_1T1R:   return 0x11;
320                 case RF_1T2R:   return 0x12;
321                 case RF_2T2R:   return 0x22;
322                 case RF_2T2R_GREEN:     return 0x92;
323                 default:
324                         RT_TRACE(COMP_INIT, "Unknown RF type(%x)\n",priv->rf_type);
325                         break;
326         }
327         return 0x22;
328 }
329
330
331 //
332 // Description:   This routine is to update the private parts in FW header partially.
333 //
334 // Created by Roger, 2008.12.18.
335 //
336 void FirmwareHeaderPriveUpdate(struct net_device *dev, PRT_8192S_FIRMWARE_PRIV  pFwPriv)
337 {
338         struct r8192_priv       *priv = ieee80211_priv(dev);
339         // Update USB endpoint number for RQPN settings.
340         pFwPriv->usb_ep_num = priv->EEPROMUsbEndPointNumber; // endpoint number: 4, 6 and 11.
341         RT_TRACE(COMP_INIT, "FirmwarePriveUpdate(): usb_ep_num(%#x)\n", pFwPriv->usb_ep_num);
342
343         // Update RF types for RATR settings.
344         pFwPriv->rf_config = FirmwareHeaderMapRfType(dev);
345 }
346
347
348
349 bool FirmwareDownload92S(struct net_device *dev)
350 {
351         struct r8192_priv       *priv = ieee80211_priv(dev);
352         bool                            rtStatus = true;
353         const char              *pFwImageFileName[1] = {"RTL8192SU/rtl8192sfw.bin"};
354         u8                              *pucMappedFile = NULL;
355         u32                             ulFileLength, ulInitStep = 0;
356         u8                              FwHdrSize = RT_8192S_FIRMWARE_HDR_SIZE;
357         rt_firmware             *pFirmware = priv->pFirmware;
358         u8                              FwStatus = FW_STATUS_INIT;
359         PRT_8192S_FIRMWARE_HDR          pFwHdr = NULL;
360         PRT_8192S_FIRMWARE_PRIV         pFwPriv = NULL;
361         int                             rc;
362         const struct firmware   *fw_entry;
363         u32                             file_length = 0;
364
365         pFirmware->FWStatus = FW_STATUS_INIT;
366
367         RT_TRACE(COMP_FIRMWARE, " --->FirmwareDownload92S()\n");
368
369         //3//
370         //3 //<1> Open Image file, and map file to contineous memory if open file success.
371         //3  //        or read image file from array. Default load from BIN file
372         //3//
373         priv->firmware_source = FW_SOURCE_IMG_FILE;// We should decided by Reg.
374
375         switch( priv->firmware_source )
376         {
377                 case FW_SOURCE_IMG_FILE:
378                         if(pFirmware->szFwTmpBufferLen == 0)
379                         {
380
381                                 rc = request_firmware(&fw_entry, pFwImageFileName[ulInitStep],&priv->udev->dev);//===>1
382                                 if(rc < 0 ) {
383                                         RT_TRACE(COMP_ERR, "request firmware fail!\n");
384                                         goto DownloadFirmware_Fail;
385                                 }
386
387                                 if(fw_entry->size > sizeof(pFirmware->szFwTmpBuffer))
388                                 {
389                                         RT_TRACE(COMP_ERR, "img file size exceed the container buffer fail!\n");
390                                         release_firmware(fw_entry);
391                                         goto DownloadFirmware_Fail;
392                                 }
393
394                                 memcpy(pFirmware->szFwTmpBuffer,fw_entry->data,fw_entry->size);
395                                 pFirmware->szFwTmpBufferLen = fw_entry->size;
396                                 release_firmware(fw_entry);
397
398                                 pucMappedFile = pFirmware->szFwTmpBuffer;
399                                 file_length = pFirmware->szFwTmpBufferLen;
400
401                                 //Retrieve FW header.
402                                 pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
403                                 pFwHdr = pFirmware->pFwHeader;
404                                 RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
405                                                 pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
406                                                 pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
407                                 pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);
408                                 if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
409                                 {
410                                         RT_TRACE(COMP_ERR, "%s: memory for data image is less than IMEM required\n",\
411                                                         __FUNCTION__);
412                                         goto DownloadFirmware_Fail;
413                                 } else {
414                                         pucMappedFile+=FwHdrSize;
415
416                                         //Retrieve IMEM image.
417                                         memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
418                                         pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
419                                 }
420
421                                 if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
422                                 {
423                                         RT_TRACE(COMP_ERR, "%s: memory for data image is less than EMEM required\n",\
424                                                         __FUNCTION__);
425                                         goto DownloadFirmware_Fail;
426                                 } else {
427                                         pucMappedFile += pFirmware->FwIMEMLen;
428
429                                         /* Retriecve EMEM image */
430                                         memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);//===>6
431                                         pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
432                                 }
433
434
435                         }
436                         break;
437
438                 case FW_SOURCE_HEADER_FILE:
439 #if 1
440 #define Rtl819XFwImageArray Rtl8192SUFwImgArray
441                         //2008.11.10 Add by tynli.
442                         pucMappedFile = Rtl819XFwImageArray;
443                         ulFileLength = ImgArrayLength;
444
445                         RT_TRACE(COMP_INIT,"Fw download from header.\n");
446                         /* Retrieve FW header*/
447                         pFirmware->pFwHeader = (PRT_8192S_FIRMWARE_HDR) pucMappedFile;
448                         pFwHdr = pFirmware->pFwHeader;
449                         RT_TRACE(COMP_FIRMWARE,"signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n", \
450                                         pFwHdr->Signature, pFwHdr->Version, pFwHdr->DMEMSize, \
451                                         pFwHdr->IMG_IMEM_SIZE, pFwHdr->IMG_SRAM_SIZE);
452                         pFirmware->FirmwareVersion =  byte(pFwHdr->Version ,0);
453
454                         if ((pFwHdr->IMG_IMEM_SIZE==0) || (pFwHdr->IMG_IMEM_SIZE > sizeof(pFirmware->FwIMEM)))
455                         {
456                                 printk("FirmwareDownload92S(): memory for data image is less than IMEM required\n");
457                                 goto DownloadFirmware_Fail;
458                         } else {
459                                 pucMappedFile+=FwHdrSize;
460                                 //Retrieve IMEM image.
461                                 memcpy(pFirmware->FwIMEM, pucMappedFile, pFwHdr->IMG_IMEM_SIZE);
462                                 pFirmware->FwIMEMLen = pFwHdr->IMG_IMEM_SIZE;
463                         }
464
465                         if (pFwHdr->IMG_SRAM_SIZE > sizeof(pFirmware->FwEMEM))
466                         {
467                                 printk(" FirmwareDownload92S(): memory for data image is less than EMEM required\n");
468                                 goto DownloadFirmware_Fail;
469                         } else {
470                                 pucMappedFile+= pFirmware->FwIMEMLen;
471
472                                 //Retriecve EMEM image.
473                                 memcpy(pFirmware->FwEMEM, pucMappedFile, pFwHdr->IMG_SRAM_SIZE);
474                                 pFirmware->FwEMEMLen = pFwHdr->IMG_SRAM_SIZE;
475                         }
476 #endif
477                         break;
478                 default:
479                         break;
480         }
481
482         FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
483         while(FwStatus!= FW_STATUS_READY)
484         {
485                 // Image buffer redirection.
486                 switch(FwStatus)
487                 {
488                         case FW_STATUS_LOAD_IMEM:
489                                 pucMappedFile = pFirmware->FwIMEM;
490                                 ulFileLength = pFirmware->FwIMEMLen;
491                                 break;
492
493                         case FW_STATUS_LOAD_EMEM:
494                                 pucMappedFile = pFirmware->FwEMEM;
495                                 ulFileLength = pFirmware->FwEMEMLen;
496                                 break;
497
498                         case FW_STATUS_LOAD_DMEM:
499                                 /* <Roger_Notes> Partial update the content of header private. 2008.12.18 */
500                                 pFwHdr = pFirmware->pFwHeader;
501                                 pFwPriv = (PRT_8192S_FIRMWARE_PRIV)&pFwHdr->FWPriv;
502                                 FirmwareHeaderPriveUpdate(dev, pFwPriv);
503                                 pucMappedFile = (u8*)(pFirmware->pFwHeader)+RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
504                                 ulFileLength = FwHdrSize-RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE;
505                                 break;
506
507                         default:
508                                 RT_TRACE(COMP_ERR, "Unexpected Download step!!\n");
509                                 goto DownloadFirmware_Fail;
510                                 break;
511                 }
512
513                 //3//
514                 //3// <2> Download image file
515         //3     //
516                 rtStatus = FirmwareDownloadCode(dev, pucMappedFile, ulFileLength);
517
518                 if(rtStatus != true)
519                 {
520                         RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n" );
521                         goto DownloadFirmware_Fail;
522                 }
523
524                 //3//
525                 //3// <3> Check whether load FW process is ready
526         //3     //
527                 rtStatus = FirmwareCheckReady(dev, FwStatus);
528
529                 if(rtStatus != true)
530                 {
531                         RT_TRACE(COMP_ERR, "FirmwareDownloadCode() fail ! \n");
532                         goto DownloadFirmware_Fail;
533                 }
534
535                 FwStatus = FirmwareGetNextStatus(pFirmware->FWStatus);
536         }
537
538         RT_TRACE(COMP_FIRMWARE, "Firmware Download Success!!\n");
539         return rtStatus;
540
541         DownloadFirmware_Fail:
542         RT_TRACE(COMP_ERR, "Firmware Download Fail!!%x\n",read_nic_word(dev, TCR));
543         rtStatus = false;
544         return rtStatus;
545 }
546