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