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