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