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