Initial commit
[kernel/linux-3.0.git] / drivers / staging / ft1000 / ft1000-usb / ft1000_download.c
1 //=====================================================
2 // CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
3 //
4 //
5 // This file is part of Express Card USB Driver
6 //
7 // $Id:
8 //====================================================
9 // 20090926; aelias; removed compiler warnings; ubuntu 9.04; 2.6.28-15-generic
10
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/netdevice.h>
15 #include <linux/etherdevice.h>
16 #include <linux/usb.h>
17 #include <linux/vmalloc.h>
18 #include "ft1000_usb.h"
19
20
21 #define  DWNLD_HANDSHAKE_LOC     0x02
22 #define  DWNLD_TYPE_LOC          0x04
23 #define  DWNLD_SIZE_MSW_LOC      0x06
24 #define  DWNLD_SIZE_LSW_LOC      0x08
25 #define  DWNLD_PS_HDR_LOC        0x0A
26
27 #define  MAX_DSP_WAIT_LOOPS      40
28 #define  DSP_WAIT_SLEEP_TIME     1000       /* 1 millisecond */
29 #define  DSP_WAIT_DISPATCH_LVL   50         /* 50 usec */
30
31 #define  HANDSHAKE_TIMEOUT_VALUE 0xF1F1
32 #define  HANDSHAKE_RESET_VALUE   0xFEFE   /* When DSP requests startover */
33 #define  HANDSHAKE_RESET_VALUE_USB   0xFE7E   /* When DSP requests startover */
34 #define  HANDSHAKE_DSP_BL_READY  0xFEFE   /* At start DSP writes this when bootloader ready */
35 #define  HANDSHAKE_DSP_BL_READY_USB  0xFE7E   /* At start DSP writes this when bootloader ready */
36 #define  HANDSHAKE_DRIVER_READY  0xFFFF   /* Driver writes after receiving 0xFEFE */
37 #define  HANDSHAKE_SEND_DATA     0x0000   /* DSP writes this when ready for more data */
38
39 #define  HANDSHAKE_REQUEST       0x0001   /* Request from DSP */
40 #define  HANDSHAKE_RESPONSE      0x0000   /* Satisfied DSP request */
41
42 #define  REQUEST_CODE_LENGTH     0x0000
43 #define  REQUEST_RUN_ADDRESS     0x0001
44 #define  REQUEST_CODE_SEGMENT    0x0002   /* In WORD count */
45 #define  REQUEST_DONE_BL         0x0003
46 #define  REQUEST_DONE_CL         0x0004
47 #define  REQUEST_VERSION_INFO    0x0005
48 #define  REQUEST_CODE_BY_VERSION 0x0006
49 #define  REQUEST_MAILBOX_DATA    0x0007
50 #define  REQUEST_FILE_CHECKSUM   0x0008
51
52 #define  STATE_START_DWNLD       0x01
53 #define  STATE_BOOT_DWNLD        0x02
54 #define  STATE_CODE_DWNLD        0x03
55 #define  STATE_DONE_DWNLD        0x04
56 #define  STATE_SECTION_PROV      0x05
57 #define  STATE_DONE_PROV         0x06
58 #define  STATE_DONE_FILE         0x07
59
60 #define  MAX_LENGTH              0x7f0
61
62 // Temporary download mechanism for Magnemite
63 #define  DWNLD_MAG_TYPE_LOC          0x00
64 #define  DWNLD_MAG_LEN_LOC           0x01
65 #define  DWNLD_MAG_ADDR_LOC          0x02
66 #define  DWNLD_MAG_CHKSUM_LOC        0x03
67 #define  DWNLD_MAG_VAL_LOC           0x04
68
69 #define  HANDSHAKE_MAG_DSP_BL_READY  0xFEFE0000   /* At start DSP writes this when bootloader ready */
70 #define  HANDSHAKE_MAG_DSP_ENTRY     0x01000000   /* Dsp writes this to request for entry address */
71 #define  HANDSHAKE_MAG_DSP_DATA      0x02000000   /* Dsp writes this to request for data block */
72 #define  HANDSHAKE_MAG_DSP_DONE      0x03000000   /* Dsp writes this to indicate download done */
73
74 #define  HANDSHAKE_MAG_DRV_READY     0xFFFF0000   /* Driver writes this to indicate ready to download */
75 #define  HANDSHAKE_MAG_DRV_DATA      0x02FECDAB   /* Driver writes this to indicate data available to DSP */
76 #define  HANDSHAKE_MAG_DRV_ENTRY     0x01FECDAB   /* Driver writes this to indicate entry point to DSP */
77
78 #define  HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1
79
80
81 // New Magnemite downloader
82 #define  DWNLD_MAG1_HANDSHAKE_LOC     0x00
83 #define  DWNLD_MAG1_TYPE_LOC          0x01
84 #define  DWNLD_MAG1_SIZE_LOC          0x02
85 #define  DWNLD_MAG1_PS_HDR_LOC        0x03
86
87 struct dsp_file_hdr {
88    long              version_id;          // Version ID of this image format.
89    long              package_id;          // Package ID of code release.
90    long              build_date;          // Date/time stamp when file was built.
91    long              commands_offset;     // Offset to attached commands in Pseudo Hdr format.
92    long              loader_offset;       // Offset to bootloader code.
93    long              loader_code_address; // Start address of bootloader.
94    long              loader_code_end;     // Where bootloader code ends.
95    long              loader_code_size;
96    long              version_data_offset; // Offset were scrambled version data begins.
97    long              version_data_size;   // Size, in words, of scrambled version data.
98    long              nDspImages;          // Number of DSP images in file.
99 };
100
101 #pragma pack(1)
102 struct dsp_image_info {
103    long              coff_date;           // Date/time when DSP Coff image was built.
104    long              begin_offset;        // Offset in file where image begins.
105    long              end_offset;          // Offset in file where image begins.
106    long              run_address;         // On chip Start address of DSP code.
107    long              image_size;          // Size of image.
108    long              version;             // Embedded version # of DSP code.
109    unsigned short    checksum;            // DSP File checksum
110    unsigned short    pad1;
111 };
112
113
114 //---------------------------------------------------------------------------
115 // Function:    check_usb_db
116 //
117 // Parameters:  struct ft1000_device  - device structure
118 //
119 // Returns:     0 - success
120 //
121 // Description: This function checks if the doorbell register is cleared
122 //
123 // Notes:
124 //
125 //---------------------------------------------------------------------------
126 static u32 check_usb_db (struct ft1000_device *ft1000dev)
127 {
128         int loopcnt;
129         u16 temp;
130         u32 status;
131
132         loopcnt = 0;
133
134         while (loopcnt < 10) {
135                 status = ft1000_read_register(ft1000dev, &temp,
136                                                FT1000_REG_DOORBELL);
137                 DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n",
138                        temp);
139                 if (temp & 0x0080) {
140                         DEBUG("FT1000:Got checkusb doorbell\n");
141                         status = ft1000_write_register(ft1000dev, 0x0080,
142                                                 FT1000_REG_DOORBELL);
143                         status = ft1000_write_register(ft1000dev, 0x0100,
144                                                 FT1000_REG_DOORBELL);
145                         status = ft1000_write_register(ft1000dev,  0x8000,
146                                                 FT1000_REG_DOORBELL);
147                         break;
148                 } else {
149                         loopcnt++;
150                         msleep(10);
151                 }
152
153         }
154
155         loopcnt = 0;
156         while (loopcnt < 20) {
157                 status = ft1000_read_register(ft1000dev, &temp,
158                                                FT1000_REG_DOORBELL);
159                 DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp);
160                 if (temp & 0x8000) {
161                         loopcnt++;
162                         msleep(10);
163                 } else  {
164                         DEBUG("check_usb_db: door bell is cleared, return 0\n");
165                         return 0;
166                 }
167         }
168
169         return HANDSHAKE_MAG_TIMEOUT_VALUE;
170 }
171
172 //---------------------------------------------------------------------------
173 // Function:    get_handshake
174 //
175 // Parameters:  struct ft1000_device  - device structure
176 //              u16 expected_value - the handshake value expected
177 //
178 // Returns:     handshakevalue - success
179 //              HANDSHAKE_TIMEOUT_VALUE - failure
180 //
181 // Description: This function gets the handshake and compare with the expected value
182 //
183 // Notes:
184 //
185 //---------------------------------------------------------------------------
186 static u16 get_handshake(struct ft1000_device *ft1000dev, u16 expected_value)
187 {
188         u16 handshake;
189         int loopcnt;
190         u32 status = 0;
191         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
192
193         loopcnt = 0;
194
195         while (loopcnt < 100) {
196                 /* Need to clear downloader doorbell if Hartley ASIC */
197                 status = ft1000_write_register(ft1000dev,  FT1000_DB_DNLD_RX,
198                                                 FT1000_REG_DOORBELL);
199                 if (pft1000info->fcodeldr) {
200                         DEBUG(" get_handshake: fcodeldr is %d\n",
201                                 pft1000info->fcodeldr);
202                         pft1000info->fcodeldr = 0;
203                         status = check_usb_db(ft1000dev);
204                         if (status != STATUS_SUCCESS) {
205                                 DEBUG("get_handshake: check_usb_db failed\n");
206                                 status = STATUS_FAILURE;
207                                 break;
208                         }
209                         status = ft1000_write_register(ft1000dev,
210                                         FT1000_DB_DNLD_RX,
211                                         FT1000_REG_DOORBELL);
212                 }
213
214                 status = ft1000_read_dpram16(ft1000dev,
215                                 DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
216                 handshake = ntohs(handshake);
217
218                 if (status)
219                         return HANDSHAKE_TIMEOUT_VALUE;
220
221                 if ((handshake == expected_value) ||
222                     (handshake == HANDSHAKE_RESET_VALUE_USB)) {
223                         return handshake;
224                 } else  {
225                         loopcnt++;
226                         msleep(10);
227                 }
228         }
229
230         return HANDSHAKE_TIMEOUT_VALUE;
231 }
232
233 //---------------------------------------------------------------------------
234 // Function:    put_handshake
235 //
236 // Parameters:  struct ft1000_device  - device structure
237 //              u16 handshake_value - handshake to be written
238 //
239 // Returns:     none
240 //
241 // Description: This function write the handshake value to the handshake location
242 //              in DPRAM
243 //
244 // Notes:
245 //
246 //---------------------------------------------------------------------------
247 static void put_handshake(struct ft1000_device *ft1000dev,u16 handshake_value)
248 {
249         u32 tempx;
250         u16 tempword;
251         u32 status;
252
253         tempx = (u32)handshake_value;
254         tempx = ntohl(tempx);
255
256         tempword = (u16)(tempx & 0xffff);
257         status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
258                                         tempword, 0);
259         tempword = (u16)(tempx >> 16);
260         status = ft1000_write_dpram16(ft1000dev, DWNLD_MAG1_HANDSHAKE_LOC,
261                                         tempword, 1);
262         status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
263                                         FT1000_REG_DOORBELL);
264 }
265
266 static u16 get_handshake_usb(struct ft1000_device *ft1000dev, u16 expected_value)
267 {
268         u16 handshake;
269         int loopcnt;
270         u16 temp;
271         u32 status = 0;
272
273         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
274         loopcnt = 0;
275         handshake = 0;
276
277         while (loopcnt < 100) {
278                 if (pft1000info->usbboot == 2) {
279                         status = ft1000_read_dpram32(ft1000dev, 0,
280                                         (u8 *)&(pft1000info->tempbuf[0]), 64);
281                         for (temp = 0; temp < 16; temp++) {
282                                 DEBUG("tempbuf %d = 0x%x\n", temp,
283                                         pft1000info->tempbuf[temp]);
284                         }
285                         status = ft1000_read_dpram16(ft1000dev,
286                                                 DWNLD_MAG1_HANDSHAKE_LOC,
287                                                 (u8 *)&handshake, 1);
288                         DEBUG("handshake from read_dpram16 = 0x%x\n",
289                                 handshake);
290                         if (pft1000info->dspalive == pft1000info->tempbuf[6]) {
291                                 handshake = 0;
292                         } else {
293                                 handshake = pft1000info->tempbuf[1];
294                                 pft1000info->dspalive =
295                                                 pft1000info->tempbuf[6];
296                         }
297                 } else {
298                         status = ft1000_read_dpram16(ft1000dev,
299                                                 DWNLD_MAG1_HANDSHAKE_LOC,
300                                                 (u8 *)&handshake, 1);
301                 }
302
303                 loopcnt++;
304                 msleep(10);
305                 handshake = ntohs(handshake);
306                 if ((handshake == expected_value) ||
307                     (handshake == HANDSHAKE_RESET_VALUE_USB))
308                         return handshake;
309         }
310
311         return HANDSHAKE_TIMEOUT_VALUE;
312 }
313
314 static void put_handshake_usb(struct ft1000_device *ft1000dev,u16 handshake_value)
315 {
316         int i;
317
318         for (i=0; i<1000; i++);
319 }
320
321 //---------------------------------------------------------------------------
322 // Function:    get_request_type
323 //
324 // Parameters:  struct ft1000_device  - device structure
325 //
326 // Returns:     request type - success
327 //
328 // Description: This function returns the request type
329 //
330 // Notes:
331 //
332 //---------------------------------------------------------------------------
333 static u16 get_request_type(struct ft1000_device *ft1000dev)
334 {
335         u16 request_type;
336         u32 status;
337         u16 tempword;
338         u32 tempx;
339         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
340
341         if (pft1000info->bootmode == 1) {
342                 status = fix_ft1000_read_dpram32(ft1000dev,
343                                 DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
344                 tempx = ntohl(tempx);
345         } else {
346                 tempx = 0;
347                 status = ft1000_read_dpram16(ft1000dev,
348                                 DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
349                 tempx |= (tempword << 16);
350                 tempx = ntohl(tempx);
351         }
352         request_type = (u16)tempx;
353
354         return request_type;
355 }
356
357 static u16 get_request_type_usb(struct ft1000_device *ft1000dev)
358 {
359         u16 request_type;
360         u32 status;
361         u16 tempword;
362         u32 tempx;
363         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
364
365         if (pft1000info->bootmode == 1) {
366                 status = fix_ft1000_read_dpram32(ft1000dev,
367                                 DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
368                 tempx = ntohl(tempx);
369         } else {
370                 if (pft1000info->usbboot == 2) {
371                         tempx = pft1000info->tempbuf[2];
372                         tempword = pft1000info->tempbuf[3];
373                 } else {
374                         tempx = 0;
375                         status = ft1000_read_dpram16(ft1000dev,
376                                         DWNLD_MAG1_TYPE_LOC,
377                                         (u8 *)&tempword, 1);
378                 }
379                 tempx |= (tempword << 16);
380                 tempx = ntohl(tempx);
381         }
382         request_type = (u16)tempx;
383
384         return request_type;
385 }
386
387 //---------------------------------------------------------------------------
388 // Function:    get_request_value
389 //
390 // Parameters:  struct ft1000_device  - device structure
391 //
392 // Returns:     request value - success
393 //
394 // Description: This function returns the request value
395 //
396 // Notes:
397 //
398 //---------------------------------------------------------------------------
399 static long get_request_value(struct ft1000_device *ft1000dev)
400 {
401         u32 value;
402         u16 tempword;
403         u32 status;
404         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
405
406         if (pft1000info->bootmode == 1) {
407                 status = fix_ft1000_read_dpram32(ft1000dev,
408                                 DWNLD_MAG1_SIZE_LOC, (u8 *)&value);
409                 value = ntohl(value);
410         } else  {
411                 status = ft1000_read_dpram16(ft1000dev,
412                                 DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0);
413                 value = tempword;
414                 status = ft1000_read_dpram16(ft1000dev,
415                                 DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
416                 value |= (tempword << 16);
417                 value = ntohl(value);
418         }
419
420         return value;
421 }
422
423
424 //---------------------------------------------------------------------------
425 // Function:    put_request_value
426 //
427 // Parameters:  struct ft1000_device  - device structure
428 //              long lvalue - value to be put into DPRAM location DWNLD_MAG1_SIZE_LOC
429 //
430 // Returns:     none
431 //
432 // Description: This function writes a value to DWNLD_MAG1_SIZE_LOC
433 //
434 // Notes:
435 //
436 //---------------------------------------------------------------------------
437 static void put_request_value(struct ft1000_device *ft1000dev, long lvalue)
438 {
439         u32    tempx;
440         u32    status;
441
442         tempx = ntohl(lvalue);
443         status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
444                                           (u8 *)&tempx);
445 }
446
447
448
449 //---------------------------------------------------------------------------
450 // Function:    hdr_checksum
451 //
452 // Parameters:  struct pseudo_hdr *pHdr - Pseudo header pointer
453 //
454 // Returns:     checksum - success
455 //
456 // Description: This function returns the checksum of the pseudo header
457 //
458 // Notes:
459 //
460 //---------------------------------------------------------------------------
461 static u16 hdr_checksum(struct pseudo_hdr *pHdr)
462 {
463         u16   *usPtr = (u16 *)pHdr;
464         u16   chksum;
465
466
467         chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
468         usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
469
470         return chksum;
471 }
472
473 static int check_buffers(u16 *buff_w, u16 *buff_r, int len, int offset)
474 {
475         int i;
476
477         for (i = 0; i < len; i++) {
478                 if (buff_w[i] != buff_r[i + offset])
479                         return -1;
480         }
481
482         return 0;
483 }
484
485 //---------------------------------------------------------------------------
486 // Function:    write_blk
487 //
488 // Parameters:  struct ft1000_device  - device structure
489 //              u16 **pUsFile - DSP image file pointer in u16
490 //              u8  **pUcFile - DSP image file pointer in u8
491 //              long   word_length - length of the buffer to be written
492 //                                   to DPRAM
493 //
494 // Returns:     STATUS_SUCCESS - success
495 //              STATUS_FAILURE - failure
496 //
497 // Description: This function writes a block of DSP image to DPRAM
498 //
499 // Notes:
500 //
501 //---------------------------------------------------------------------------
502 static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length)
503 {
504    u32 Status = STATUS_SUCCESS;
505    u16 dpram;
506    int loopcnt, i, j;
507    u16 tempword;
508    u16 tempbuffer[64];
509    u16 resultbuffer[64];
510         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
511
512    //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length);
513    dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
514    tempword = *(*pUsFile);
515    (*pUsFile)++;
516    Status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
517    tempword = *(*pUsFile);
518    (*pUsFile)++;
519    Status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
520
521    *pUcFile = *pUcFile + 4;
522    word_length--;
523    tempword = (u16)word_length;
524    word_length = (word_length / 16) + 1;
525    for (; word_length > 0; word_length--) /* In words */
526    {
527            loopcnt = 0;
528
529               for (i=0; i<32; i++)
530               {
531                        if (tempword != 0)
532                        {
533                            tempbuffer[i++] = *(*pUsFile);
534                            (*pUsFile)++;
535                            tempbuffer[i] = *(*pUsFile);
536                            (*pUsFile)++;
537                            *pUcFile = *pUcFile + 4;
538                            loopcnt++;
539                            tempword--;
540                        }
541                        else
542                        {
543                            tempbuffer[i++] = 0;
544                            tempbuffer[i] = 0;
545                        }
546               }
547
548               //DEBUG("write_blk: loopcnt is %d\n", loopcnt);
549               //DEBUG("write_blk: bootmode = %d\n", bootmode);
550               //DEBUG("write_blk: dpram = %x\n", dpram);
551               if (pft1000info->bootmode == 0)
552               {
553                  if (dpram >= 0x3F4)
554                      Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 8);
555                  else
556                     Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64);
557               }
558               else
559               {
560                  for (j=0; j<10; j++)
561                  {
562                    Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64);
563                    if (Status == STATUS_SUCCESS)
564                    {
565                        // Work around for ASIC bit stuffing problem.
566                        if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
567                        {
568                            Status = ft1000_write_dpram32(ft1000dev, dpram+12, (u8 *)&tempbuffer[24], 64);
569                        }
570                        // Let's check the data written
571                        Status = ft1000_read_dpram32 (ft1000dev, dpram, (u8 *)&resultbuffer[0], 64);
572                        if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
573                        {
574                                 if (check_buffers(tempbuffer, resultbuffer, 28, 0)) {
575                                         DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
576                                         msleep(10);
577                                         Status = STATUS_FAILURE;
578                                         break;
579                                 }
580                            Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (u8 *)&resultbuffer[0], 64);
581
582                                 if (check_buffers(tempbuffer, resultbuffer, 16, 24)) {
583                                         DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
584                                         msleep(10);
585                                         Status = STATUS_FAILURE;
586                                         break;
587                                 }
588                            
589                         }
590                         else
591                         {
592                                 if (check_buffers(tempbuffer, resultbuffer, 32, 0)) {
593                                         DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
594                                         msleep(10);
595                                         Status = STATUS_FAILURE;
596                                         break;
597                                 }
598                             
599                         }
600
601                         if (Status == STATUS_SUCCESS)
602                             break;
603
604                     }
605                 }
606
607                 if (Status != STATUS_SUCCESS)
608                 {
609                     DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]);
610                     break;
611                 }
612
613              }
614              dpram = dpram + loopcnt;
615    }
616
617    return Status;
618 }
619
620 static void usb_dnld_complete (struct urb *urb)
621 {
622     //DEBUG("****** usb_dnld_complete\n");
623 }
624
625 //---------------------------------------------------------------------------
626 // Function:    write_blk_fifo
627 //
628 // Parameters:  struct ft1000_device  - device structure
629 //              u16 **pUsFile - DSP image file pointer in u16
630 //              u8  **pUcFile - DSP image file pointer in u8
631 //              long   word_length - length of the buffer to be written
632 //                                   to DPRAM
633 //
634 // Returns:     STATUS_SUCCESS - success
635 //              STATUS_FAILURE - failure
636 //
637 // Description: This function writes a block of DSP image to DPRAM
638 //
639 // Notes:
640 //
641 //---------------------------------------------------------------------------
642 static u32 write_blk_fifo(struct ft1000_device *ft1000dev, u16 **pUsFile,
643                           u8 **pUcFile, long word_length)
644 {
645         u32 Status = STATUS_SUCCESS;
646         int byte_length;
647
648         byte_length = word_length * 4;
649
650         if (byte_length && ((byte_length % 64) == 0))
651                 byte_length += 4;
652
653         if (byte_length < 64)
654                 byte_length = 68;
655
656         usb_init_urb(ft1000dev->tx_urb);
657         memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
658         usb_fill_bulk_urb(ft1000dev->tx_urb,
659                           ft1000dev->dev,
660                           usb_sndbulkpipe(ft1000dev->dev,
661                                           ft1000dev->bulk_out_endpointAddr),
662                           ft1000dev->tx_buf, byte_length, usb_dnld_complete,
663                           (void *)ft1000dev);
664
665         usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
666
667         *pUsFile = *pUsFile + (word_length << 1);
668         *pUcFile = *pUcFile + (word_length << 2);
669
670         return Status;
671 }
672
673 //---------------------------------------------------------------------------
674 //
675 //  Function:   scram_dnldr
676 //
677 //  Synopsis:   Scramble downloader for Harley based ASIC via USB interface
678 //
679 //  Arguments:  pFileStart              - pointer to start of file
680 //              FileLength              - file length
681 //
682 //  Returns:    status                  - return code
683 //---------------------------------------------------------------------------
684
685 u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart,
686                 u32 FileLength)
687 {
688         u16 status = STATUS_SUCCESS;
689         u32 state;
690         u16 handshake;
691         struct pseudo_hdr *pseudo_header;
692         u16 pseudo_header_len;
693         long word_length;
694         u16 request;
695         u16 temp;
696         u16 tempword;
697
698         struct dsp_file_hdr *file_hdr;
699         struct dsp_image_info *dsp_img_info = NULL;
700         long requested_version;
701         bool correct_version;
702         struct drv_msg *mailbox_data;
703         u16 *data = NULL;
704         u16 *s_file = NULL;
705         u8 *c_file = NULL;
706         u8 *boot_end = NULL, *code_end = NULL;
707         int image;
708         long loader_code_address, loader_code_size = 0;
709         long run_address = 0, run_size = 0;
710
711         u32 templong;
712         u32 image_chksum = 0;
713
714         u16 dpram = 0;
715         u8 *pbuffer;
716         struct prov_record *pprov_record;
717         struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
718
719         DEBUG("Entered   scram_dnldr...\n");
720
721         pft1000info->fcodeldr = 0;
722         pft1000info->usbboot = 0;
723         pft1000info->dspalive = 0xffff;
724
725         //
726         // Get version id of file, at first 4 bytes of file, for newer files.
727         //
728
729         state = STATE_START_DWNLD;
730
731         file_hdr = (struct dsp_file_hdr *)pFileStart;
732
733         ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
734
735         s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
736         c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
737
738         boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
739
740         loader_code_address = file_hdr->loader_code_address;
741         loader_code_size = file_hdr->loader_code_size;
742         correct_version = FALSE;
743
744         while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) {
745                 switch (state) {
746                 case STATE_START_DWNLD:
747                         DEBUG("FT1000:STATE_START_DWNLD\n");
748                         if (pft1000info->usbboot)
749                                 handshake =
750                                     get_handshake_usb(ft1000dev,
751                                                       HANDSHAKE_DSP_BL_READY);
752                         else
753                                 handshake =
754                                     get_handshake(ft1000dev,
755                                                   HANDSHAKE_DSP_BL_READY);
756
757                         if (handshake == HANDSHAKE_DSP_BL_READY) {
758                                 DEBUG
759                                     ("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
760                                 put_handshake(ft1000dev,
761                                               HANDSHAKE_DRIVER_READY);
762                         } else {
763                                 DEBUG
764                                     ("FT1000:download:Download error: Handshake failed\n");
765                                 status = STATUS_FAILURE;
766                         }
767
768                         state = STATE_BOOT_DWNLD;
769
770                         break;
771
772                 case STATE_BOOT_DWNLD:
773                         DEBUG("FT1000:STATE_BOOT_DWNLD\n");
774                         pft1000info->bootmode = 1;
775                         handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
776                         if (handshake == HANDSHAKE_REQUEST) {
777                                 /*
778                                  * Get type associated with the request.
779                                  */
780                                 request = get_request_type(ft1000dev);
781                                 switch (request) {
782                                 case REQUEST_RUN_ADDRESS:
783                                         DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
784                                         put_request_value(ft1000dev,
785                                                           loader_code_address);
786                                         break;
787                                 case REQUEST_CODE_LENGTH:
788                                         DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
789                                         put_request_value(ft1000dev,
790                                                           loader_code_size);
791                                         break;
792                                 case REQUEST_DONE_BL:
793                                         DEBUG("FT1000:REQUEST_DONE_BL\n");
794                                         /* Reposition ptrs to beginning of code section */
795                                         s_file = (u16 *) (boot_end);
796                                         c_file = (u8 *) (boot_end);
797                                         //DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file);
798                                         //DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file);
799                                         state = STATE_CODE_DWNLD;
800                                         pft1000info->fcodeldr = 1;
801                                         break;
802                                 case REQUEST_CODE_SEGMENT:
803                                         //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");
804                                         word_length =
805                                             get_request_value(ft1000dev);
806                                         //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length);
807                                         //NdisMSleep (100);
808                                         if (word_length > MAX_LENGTH) {
809                                                 DEBUG
810                                                     ("FT1000:download:Download error: Max length exceeded\n");
811                                                 status = STATUS_FAILURE;
812                                                 break;
813                                         }
814                                         if ((word_length * 2 + c_file) >
815                                             boot_end) {
816                                                 /*
817                                                  * Error, beyond boot code range.
818                                                  */
819                                                 DEBUG
820                                                     ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n",
821                                                      (int)word_length);
822                                                 status = STATUS_FAILURE;
823                                                 break;
824                                         }
825                                         /*
826                                          * Position ASIC DPRAM auto-increment pointer.
827                                          */
828                                         dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
829                                         if (word_length & 0x1)
830                                                 word_length++;
831                                         word_length = word_length / 2;
832
833                                         status =
834                                             write_blk(ft1000dev, &s_file,
835                                                       &c_file, word_length);
836                                         //DEBUG("write_blk returned %d\n", status);
837                                         break;
838                                 default:
839                                         DEBUG
840                                             ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",
841                                              request);
842                                         status = STATUS_FAILURE;
843                                         break;
844                                 }
845                                 if (pft1000info->usbboot)
846                                         put_handshake_usb(ft1000dev,
847                                                           HANDSHAKE_RESPONSE);
848                                 else
849                                         put_handshake(ft1000dev,
850                                                       HANDSHAKE_RESPONSE);
851                         } else {
852                                 DEBUG
853                                     ("FT1000:download:Download error: Handshake failed\n");
854                                 status = STATUS_FAILURE;
855                         }
856
857                         break;
858
859                 case STATE_CODE_DWNLD:
860                         //DEBUG("FT1000:STATE_CODE_DWNLD\n");
861                         pft1000info->bootmode = 0;
862                         if (pft1000info->usbboot)
863                                 handshake =
864                                     get_handshake_usb(ft1000dev,
865                                                       HANDSHAKE_REQUEST);
866                         else
867                                 handshake =
868                                     get_handshake(ft1000dev, HANDSHAKE_REQUEST);
869                         if (handshake == HANDSHAKE_REQUEST) {
870                                 /*
871                                  * Get type associated with the request.
872                                  */
873                                 if (pft1000info->usbboot)
874                                         request =
875                                             get_request_type_usb(ft1000dev);
876                                 else
877                                         request = get_request_type(ft1000dev);
878                                 switch (request) {
879                                 case REQUEST_FILE_CHECKSUM:
880                                         DEBUG
881                                             ("FT1000:download:image_chksum = 0x%8x\n",
882                                              image_chksum);
883                                         put_request_value(ft1000dev,
884                                                           image_chksum);
885                                         break;
886                                 case REQUEST_RUN_ADDRESS:
887                                         DEBUG
888                                             ("FT1000:download:  REQUEST_RUN_ADDRESS\n");
889                                         if (correct_version) {
890                                                 DEBUG
891                                                     ("FT1000:download:run_address = 0x%8x\n",
892                                                      (int)run_address);
893                                                 put_request_value(ft1000dev,
894                                                                   run_address);
895                                         } else {
896                                                 DEBUG
897                                                     ("FT1000:download:Download error: Got Run address request before image offset request.\n");
898                                                 status = STATUS_FAILURE;
899                                                 break;
900                                         }
901                                         break;
902                                 case REQUEST_CODE_LENGTH:
903                                         DEBUG
904                                             ("FT1000:download:REQUEST_CODE_LENGTH\n");
905                                         if (correct_version) {
906                                                 DEBUG
907                                                     ("FT1000:download:run_size = 0x%8x\n",
908                                                      (int)run_size);
909                                                 put_request_value(ft1000dev,
910                                                                   run_size);
911                                         } else {
912                                                 DEBUG
913                                                     ("FT1000:download:Download error: Got Size request before image offset request.\n");
914                                                 status = STATUS_FAILURE;
915                                                 break;
916                                         }
917                                         break;
918                                 case REQUEST_DONE_CL:
919                                         pft1000info->usbboot = 3;
920                                         /* Reposition ptrs to beginning of provisioning section */
921                                         s_file =
922                                             (u16 *) (pFileStart +
923                                                      file_hdr->commands_offset);
924                                         c_file =
925                                             (u8 *) (pFileStart +
926                                                     file_hdr->commands_offset);
927                                         state = STATE_DONE_DWNLD;
928                                         break;
929                                 case REQUEST_CODE_SEGMENT:
930                                         //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n");
931                                         if (!correct_version) {
932                                                 DEBUG
933                                                     ("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
934                                                 status = STATUS_FAILURE;
935                                                 break;
936                                         }
937
938                                         word_length =
939                                             get_request_value(ft1000dev);
940                                         //DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
941                                         if (word_length > MAX_LENGTH) {
942                                                 DEBUG
943                                                     ("FT1000:download:Download error: Max length exceeded\n");
944                                                 status = STATUS_FAILURE;
945                                                 break;
946                                         }
947                                         if ((word_length * 2 + c_file) >
948                                             code_end) {
949                                                 /*
950                                                  * Error, beyond boot code range.
951                                                  */
952                                                 DEBUG
953                                                     ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundary.\n",
954                                                      (int)word_length);
955                                                 status = STATUS_FAILURE;
956                                                 break;
957                                         }
958                                         /*
959                                          * Position ASIC DPRAM auto-increment pointer.
960                                          */
961                                         dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
962                                         if (word_length & 0x1)
963                                                 word_length++;
964                                         word_length = word_length / 2;
965
966                                         write_blk_fifo(ft1000dev, &s_file,
967                                                        &c_file, word_length);
968                                         if (pft1000info->usbboot == 0)
969                                                 pft1000info->usbboot++;
970                                         if (pft1000info->usbboot == 1) {
971                                                 tempword = 0;
972                                                 ft1000_write_dpram16(ft1000dev,
973                                                                      DWNLD_MAG1_PS_HDR_LOC,
974                                                                      tempword,
975                                                                      0);
976                                         }
977
978                                         break;
979
980                                 case REQUEST_MAILBOX_DATA:
981                                         DEBUG
982                                             ("FT1000:download: REQUEST_MAILBOX_DATA\n");
983                                         // Convert length from byte count to word count. Make sure we round up.
984                                         word_length =
985                                             (long)(pft1000info->DSPInfoBlklen +
986                                                    1) / 2;
987                                         put_request_value(ft1000dev,
988                                                           word_length);
989                                         mailbox_data =
990                                             (struct drv_msg *)&(pft1000info->
991                                                                 DSPInfoBlk[0]);
992                                         /*
993                                          * Position ASIC DPRAM auto-increment pointer.
994                                          */
995
996                                         data = (u16 *) & mailbox_data->data[0];
997                                         dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
998                                         if (word_length & 0x1)
999                                                 word_length++;
1000
1001                                         word_length = (word_length / 2);
1002
1003                                         for (; word_length > 0; word_length--) {        /* In words */
1004
1005                                                 templong = *data++;
1006                                                 templong |= (*data++ << 16);
1007                                                 status =
1008                                                     fix_ft1000_write_dpram32
1009                                                     (ft1000dev, dpram++,
1010                                                      (u8 *) & templong);
1011
1012                                         }
1013                                         break;
1014
1015                                 case REQUEST_VERSION_INFO:
1016                                         DEBUG
1017                                             ("FT1000:download:REQUEST_VERSION_INFO\n");
1018                                         word_length =
1019                                             file_hdr->version_data_size;
1020                                         put_request_value(ft1000dev,
1021                                                           word_length);
1022                                         /*
1023                                          * Position ASIC DPRAM auto-increment pointer.
1024                                          */
1025
1026                                         s_file =
1027                                             (u16 *) (pFileStart +
1028                                                      file_hdr->
1029                                                      version_data_offset);
1030
1031                                         dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
1032                                         if (word_length & 0x1)
1033                                                 word_length++;
1034
1035                                         word_length = (word_length / 2);
1036
1037                                         for (; word_length > 0; word_length--) {        /* In words */
1038
1039                                                 templong = ntohs(*s_file++);
1040                                                 temp = ntohs(*s_file++);
1041                                                 templong |= (temp << 16);
1042                                                 status =
1043                                                     fix_ft1000_write_dpram32
1044                                                     (ft1000dev, dpram++,
1045                                                      (u8 *) & templong);
1046
1047                                         }
1048                                         break;
1049
1050                                 case REQUEST_CODE_BY_VERSION:
1051                                         DEBUG
1052                                             ("FT1000:download:REQUEST_CODE_BY_VERSION\n");
1053                                         correct_version = FALSE;
1054                                         requested_version =
1055                                             get_request_value(ft1000dev);
1056
1057                                         dsp_img_info =
1058                                             (struct dsp_image_info *)(pFileStart
1059                                                                       +
1060                                                                       sizeof
1061                                                                       (struct
1062                                                                        dsp_file_hdr));
1063
1064                                         for (image = 0;
1065                                              image < file_hdr->nDspImages;
1066                                              image++) {
1067
1068                                                 if (dsp_img_info->version ==
1069                                                     requested_version) {
1070                                                         correct_version = TRUE;
1071                                                         DEBUG
1072                                                             ("FT1000:download: correct_version is TRUE\n");
1073                                                         s_file =
1074                                                             (u16 *) (pFileStart
1075                                                                      +
1076                                                                      dsp_img_info->
1077                                                                      begin_offset);
1078                                                         c_file =
1079                                                             (u8 *) (pFileStart +
1080                                                                     dsp_img_info->
1081                                                                     begin_offset);
1082                                                         code_end =
1083                                                             (u8 *) (pFileStart +
1084                                                                     dsp_img_info->
1085                                                                     end_offset);
1086                                                         run_address =
1087                                                             dsp_img_info->
1088                                                             run_address;
1089                                                         run_size =
1090                                                             dsp_img_info->
1091                                                             image_size;
1092                                                         image_chksum =
1093                                                             (u32) dsp_img_info->
1094                                                             checksum;
1095                                                         break;
1096                                                 }
1097                                                 dsp_img_info++;
1098
1099                                         }       //end of for
1100
1101                                         if (!correct_version) {
1102                                                 /*
1103                                                  * Error, beyond boot code range.
1104                                                  */
1105                                                 DEBUG
1106                                                     ("FT1000:download:Download error: Bad Version Request = 0x%x.\n",
1107                                                      (int)requested_version);
1108                                                 status = STATUS_FAILURE;
1109                                                 break;
1110                                         }
1111                                         break;
1112
1113                                 default:
1114                                         DEBUG
1115                                             ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",
1116                                              request);
1117                                         status = STATUS_FAILURE;
1118                                         break;
1119                                 }
1120                                 if (pft1000info->usbboot)
1121                                         put_handshake_usb(ft1000dev,
1122                                                           HANDSHAKE_RESPONSE);
1123                                 else
1124                                         put_handshake(ft1000dev,
1125                                                       HANDSHAKE_RESPONSE);
1126                         } else {
1127                                 DEBUG
1128                                     ("FT1000:download:Download error: Handshake failed\n");
1129                                 status = STATUS_FAILURE;
1130                         }
1131
1132                         break;
1133
1134                 case STATE_DONE_DWNLD:
1135                         DEBUG("FT1000:download:Code loader is done...\n");
1136                         state = STATE_SECTION_PROV;
1137                         break;
1138
1139                 case STATE_SECTION_PROV:
1140                         DEBUG("FT1000:download:STATE_SECTION_PROV\n");
1141                         pseudo_header = (struct pseudo_hdr *)c_file;
1142
1143                         if (pseudo_header->checksum ==
1144                             hdr_checksum(pseudo_header)) {
1145                                 if (pseudo_header->portdest !=
1146                                     0x80 /* Dsp OAM */ ) {
1147                                         state = STATE_DONE_PROV;
1148                                         break;
1149                                 }
1150                                 pseudo_header_len = ntohs(pseudo_header->length);       /* Byte length for PROV records */
1151
1152                                 // Get buffer for provisioning data
1153                                 pbuffer =
1154                                     kmalloc((pseudo_header_len +
1155                                              sizeof(struct pseudo_hdr)),
1156                                             GFP_ATOMIC);
1157                                 if (pbuffer) {
1158                                         memcpy(pbuffer, (void *)c_file,
1159                                                (u32) (pseudo_header_len +
1160                                                       sizeof(struct
1161                                                              pseudo_hdr)));
1162                                         // link provisioning data
1163                                         pprov_record =
1164                                             kmalloc(sizeof(struct prov_record),
1165                                                     GFP_ATOMIC);
1166                                         if (pprov_record) {
1167                                                 pprov_record->pprov_data =
1168                                                     pbuffer;
1169                                                 list_add_tail(&pprov_record->
1170                                                               list,
1171                                                               &pft1000info->
1172                                                               prov_list);
1173                                                 // Move to next entry if available
1174                                                 c_file =
1175                                                     (u8 *) ((unsigned long)
1176                                                             c_file +
1177                                                             (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
1178                                                 if ((unsigned long)(c_file) -
1179                                                     (unsigned long)(pFileStart)
1180                                                     >=
1181                                                     (unsigned long)FileLength) {
1182                                                         state = STATE_DONE_FILE;
1183                                                 }
1184                                         } else {
1185                                                 kfree(pbuffer);
1186                                                 status = STATUS_FAILURE;
1187                                         }
1188                                 } else {
1189                                         status = STATUS_FAILURE;
1190                                 }
1191                         } else {
1192                                 /* Checksum did not compute */
1193                                 status = STATUS_FAILURE;
1194                         }
1195                         DEBUG
1196                             ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n",
1197                              state, status);
1198                         break;
1199
1200                 case STATE_DONE_PROV:
1201                         DEBUG("FT1000:download:STATE_DONE_PROV\n");
1202                         state = STATE_DONE_FILE;
1203                         break;
1204
1205                 default:
1206                         status = STATUS_FAILURE;
1207                         break;
1208                 }               /* End Switch */
1209
1210                 if (status != STATUS_SUCCESS) {
1211                         break;
1212                 }
1213
1214 /****
1215       // Check if Card is present
1216       status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK);
1217       if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) {
1218           break;
1219       }
1220
1221       status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID);
1222       if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) {
1223           break;
1224       }
1225 ****/
1226
1227         }                       /* End while */
1228
1229         DEBUG("Download exiting with status = 0x%8x\n", status);
1230         ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
1231                               FT1000_REG_DOORBELL);
1232
1233         return status;
1234 }
1235