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