1
2
3
4
5
6
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
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
24#define DSP_WAIT_DISPATCH_LVL 50
25
26#define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
27#define HANDSHAKE_RESET_VALUE 0xFEFE
28#define HANDSHAKE_RESET_VALUE_USB 0xFE7E
29#define HANDSHAKE_DSP_BL_READY 0xFEFE
30#define HANDSHAKE_DSP_BL_READY_USB 0xFE7E
31#define HANDSHAKE_DRIVER_READY 0xFFFF
32#define HANDSHAKE_SEND_DATA 0x0000
33
34#define HANDSHAKE_REQUEST 0x0001
35#define HANDSHAKE_RESPONSE 0x0000
36
37#define REQUEST_CODE_LENGTH 0x0000
38#define REQUEST_RUN_ADDRESS 0x0001
39#define REQUEST_CODE_SEGMENT 0x0002
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
44#define REQUEST_MAILBOX_DATA 0x0007
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
57
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
65#define HANDSHAKE_MAG_DSP_ENTRY 0x01000000
66#define HANDSHAKE_MAG_DSP_DATA 0x02000000
67#define HANDSHAKE_MAG_DSP_DONE 0x03000000
68
69#define HANDSHAKE_MAG_DRV_READY 0xFFFF0000
70#define HANDSHAKE_MAG_DRV_DATA 0x02FECDAB
71#define HANDSHAKE_MAG_DRV_ENTRY 0x01FECDAB
72
73#define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1
74
75
76
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
82struct dsp_file_hdr {
83 long version_id;
84 long package_id;
85 long build_date;
86 long commands_offset;
87 long loader_offset;
88 long loader_code_address;
89 long loader_code_end;
90 long loader_code_size;
91 long version_data_offset;
92 long version_data_size;
93 long nDspImages;
94};
95
96#pragma pack(1)
97struct dsp_image_info {
98 long coff_date;
99 long begin_offset;
100 long end_offset;
101 long run_address;
102 long image_size;
103 long version;
104 unsigned short checksum;
105 unsigned short pad1;
106};
107
108
109
110static int check_usb_db(struct ft1000_usb *ft1000dev)
111{
112 int loopcnt;
113 u16 temp;
114 int status;
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
153 return -1;
154}
155
156
157static 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
167 status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_RX,
168 FT1000_REG_DOORBELL);
169 if (ft1000dev->fcodeldr) {
170 DEBUG(" get_handshake: fcodeldr is %d\n",
171 ft1000dev->fcodeldr);
172 ft1000dev->fcodeldr = 0;
173 status = check_usb_db(ft1000dev);
174 if (status != 0) {
175 DEBUG("get_handshake: check_usb_db failed\n");
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;
200}
201
202
203static void put_handshake(struct ft1000_usb *ft1000dev, u16 handshake_value)
204{
205 u32 tempx;
206 u16 tempword;
207 int status;
208
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);
220}
221
222static u16 get_handshake_usb(struct ft1000_usb *ft1000dev, u16 expected_value)
223{
224 u16 handshake;
225 int loopcnt;
226 u16 temp;
227 int status = 0;
228
229 loopcnt = 0;
230 handshake = 0;
231
232 while (loopcnt < 100) {
233 if (ft1000dev->usbboot == 2) {
234 status = ft1000_read_dpram32(ft1000dev, 0,
235 (u8 *)&(ft1000dev->tempbuf[0]), 64);
236 for (temp = 0; temp < 16; temp++) {
237 DEBUG("tempbuf %d = 0x%x\n", temp,
238 ft1000dev->tempbuf[temp]);
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);
245 if (ft1000dev->dspalive == ft1000dev->tempbuf[6]) {
246 handshake = 0;
247 } else {
248 handshake = ft1000dev->tempbuf[1];
249 ft1000dev->dspalive =
250 ft1000dev->tempbuf[6];
251 }
252 } else {
253 status = ft1000_read_dpram16(ft1000dev,
254 DWNLD_MAG1_HANDSHAKE_LOC,
255 (u8 *)&handshake, 1);
256 }
257
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;
267}
268
269static void put_handshake_usb(struct ft1000_usb *ft1000dev, u16 handshake_value)
270{
271 int i;
272
273 for (i = 0; i < 1000; i++)
274 ;
275}
276
277static u16 get_request_type(struct ft1000_usb *ft1000dev)
278{
279 u16 request_type;
280 int status;
281 u16 tempword;
282 u32 tempx;
283
284 if (ft1000dev->bootmode == 1) {
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;
296
297 return request_type;
298}
299
300static u16 get_request_type_usb(struct ft1000_usb *ft1000dev)
301{
302 u16 request_type;
303 int status;
304 u16 tempword;
305 u32 tempx;
306
307 if (ft1000dev->bootmode == 1) {
308 status = fix_ft1000_read_dpram32(ft1000dev,
309 DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
310 tempx = ntohl(tempx);
311 } else {
312 if (ft1000dev->usbboot == 2) {
313 tempx = ft1000dev->tempbuf[2];
314 tempword = ft1000dev->tempbuf[3];
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;
325
326 return request_type;
327}
328
329static long get_request_value(struct ft1000_usb *ft1000dev)
330{
331 u32 value;
332 u16 tempword;
333 int status;
334
335 if (ft1000dev->bootmode == 1) {
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 }
348
349 return value;
350}
351
352
353
354static void put_request_value(struct ft1000_usb *ft1000dev, long lvalue)
355{
356 u32 tempx;
357 int status;
358
359 tempx = ntohl(lvalue);
360 status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
361 (u8 *)&tempx);
362}
363
364
365
366
367static u16 hdr_checksum(struct pseudo_hdr *pHdr)
368{
369 u16 *usPtr = (u16 *)pHdr;
370 u16 chksum;
371
372
373 chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
374 usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
375
376 return chksum;
377}
378
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])
385 return -EREMOTEIO;
386 }
387
388 return 0;
389}
390
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);
401 if (status == 0) {
402
403 if ((tempbuffer[31] & 0xfe00) == 0xfe00) {
404 status = ft1000_write_dpram32(ft1000dev,
405 dpram+12, (u8 *)&tempbuffer[24],
406 64);
407 }
408
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);
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);
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);
433 break;
434 }
435 }
436 if (status == 0)
437 break;
438 }
439 }
440 return status;
441}
442
443
444
445
446
447
448
449static int write_blk(struct ft1000_usb *ft1000dev, u16 **pUsFile, u8 **pUcFile,
450 long word_length)
451{
452 int status = 0;
453 u16 dpram;
454 int loopcnt, i;
455 u16 tempword;
456 u16 tempbuffer[64];
457
458
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--) {
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 }
486 }
487
488
489
490
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);
501 if (status != 0) {
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;
509}
510
511static void usb_dnld_complete(struct urb *urb)
512{
513
514}
515
516
517
518
519
520
521
522static int write_blk_fifo(struct ft1000_usb *ft1000dev, u16 **pUsFile,
523 u8 **pUcFile, long word_length)
524{
525 int byte_length;
526
527 byte_length = word_length * 4;
528
529 if (byte_length && ((byte_length % 64) == 0))
530 byte_length += 4;
531
532 if (byte_length < 64)
533 byte_length = 68;
534
535 usb_init_urb(ft1000dev->tx_urb);
536 memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
537 usb_fill_bulk_urb(ft1000dev->tx_urb,
538 ft1000dev->dev,
539 usb_sndbulkpipe(ft1000dev->dev,
540 ft1000dev->bulk_out_endpointAddr),
541 ft1000dev->tx_buf, byte_length, usb_dnld_complete,
542 (void *)ft1000dev);
543
544 usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
545
546 *pUsFile = *pUsFile + (word_length << 1);
547 *pUcFile = *pUcFile + (word_length << 2);
548
549 return 0;
550}
551
552static int scram_start_dwnld(struct ft1000_usb *ft1000dev, u16 *hshake,
553 u32 *state)
554{
555 int status = 0;
556
557 DEBUG("FT1000:STATE_START_DWNLD\n");
558 if (ft1000dev->usbboot)
559 *hshake = get_handshake_usb(ft1000dev, HANDSHAKE_DSP_BL_READY);
560 else
561 *hshake = get_handshake(ft1000dev, HANDSHAKE_DSP_BL_READY);
562 if (*hshake == HANDSHAKE_DSP_BL_READY) {
563 DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
564 put_handshake(ft1000dev, HANDSHAKE_DRIVER_READY);
565 } else if (*hshake == HANDSHAKE_TIMEOUT_VALUE) {
566 status = -ETIMEDOUT;
567 } else {
568 DEBUG("FT1000:download:Download error: Handshake failed\n");
569 status = -ENETRESET;
570 }
571 *state = STATE_BOOT_DWNLD;
572 return status;
573}
574
575static int request_code_segment(struct ft1000_usb *ft1000dev, u16 **s_file,
576 u8 **c_file, const u8 *endpoint, bool boot_case)
577{
578 long word_length;
579 int status = 0;
580
581
582 word_length = get_request_value(ft1000dev);
583
584
585 if (word_length > MAX_LENGTH) {
586 DEBUG("FT1000:download:Download error: Max length exceeded\n");
587 return -1;
588 }
589 if ((word_length * 2 + (long)c_file) > (long)endpoint) {
590
591 DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundary.\n", (int)word_length);
592 return -1;
593 }
594 if (word_length & 0x1)
595 word_length++;
596 word_length = word_length / 2;
597
598 if (boot_case) {
599 status = write_blk(ft1000dev, s_file, c_file, word_length);
600
601 } else {
602 status = write_blk_fifo(ft1000dev, s_file, c_file, word_length);
603 if (ft1000dev->usbboot == 0)
604 ft1000dev->usbboot++;
605 if (ft1000dev->usbboot == 1)
606 status |= ft1000_write_dpram16(ft1000dev,
607 DWNLD_MAG1_PS_HDR_LOC, 0, 0);
608 }
609 return status;
610}
611
612
613int scram_dnldr(struct ft1000_usb *ft1000dev, void *pFileStart,
614 u32 FileLength)
615{
616 int status = 0;
617 u32 state;
618 u16 handshake;
619 struct pseudo_hdr *pseudo_header;
620 u16 pseudo_header_len;
621 long word_length;
622 u16 request;
623 u16 temp;
624
625 struct dsp_file_hdr *file_hdr;
626 struct dsp_image_info *dsp_img_info = NULL;
627 long requested_version;
628 bool correct_version;
629 struct drv_msg *mailbox_data;
630 u16 *data = NULL;
631 u16 *s_file = NULL;
632 u8 *c_file = NULL;
633 u8 *boot_end = NULL, *code_end = NULL;
634 int image;
635 long loader_code_address, loader_code_size = 0;
636 long run_address = 0, run_size = 0;
637
638 u32 templong;
639 u32 image_chksum = 0;
640
641 u16 dpram = 0;
642 u8 *pbuffer;
643 struct prov_record *pprov_record;
644 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
645
646 DEBUG("Entered scram_dnldr...\n");
647
648 ft1000dev->fcodeldr = 0;
649 ft1000dev->usbboot = 0;
650 ft1000dev->dspalive = 0xffff;
651
652
653
654
655
656 state = STATE_START_DWNLD;
657
658 file_hdr = (struct dsp_file_hdr *)pFileStart;
659
660 ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
661
662 s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
663 c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
664
665 boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
666
667 loader_code_address = file_hdr->loader_code_address;
668 loader_code_size = file_hdr->loader_code_size;
669 correct_version = false;
670
671 while ((status == 0) && (state != STATE_DONE_FILE)) {
672 switch (state) {
673 case STATE_START_DWNLD:
674 status = scram_start_dwnld(ft1000dev, &handshake,
675 &state);
676 break;
677
678 case STATE_BOOT_DWNLD:
679 DEBUG("FT1000:STATE_BOOT_DWNLD\n");
680 ft1000dev->bootmode = 1;
681 handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
682 if (handshake == HANDSHAKE_REQUEST) {
683
684
685
686 request = get_request_type(ft1000dev);
687 switch (request) {
688 case REQUEST_RUN_ADDRESS:
689 DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
690 put_request_value(ft1000dev,
691 loader_code_address);
692 break;
693 case REQUEST_CODE_LENGTH:
694 DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
695 put_request_value(ft1000dev,
696 loader_code_size);
697 break;
698 case REQUEST_DONE_BL:
699 DEBUG("FT1000:REQUEST_DONE_BL\n");
700
701 s_file = (u16 *) (boot_end);
702 c_file = (u8 *) (boot_end);
703
704
705 state = STATE_CODE_DWNLD;
706 ft1000dev->fcodeldr = 1;
707 break;
708 case REQUEST_CODE_SEGMENT:
709 status = request_code_segment(ft1000dev,
710 &s_file, &c_file,
711 (const u8 *)boot_end,
712 true);
713 break;
714 default:
715 DEBUG
716 ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",
717 request);
718 status = -1;
719 break;
720 }
721 if (ft1000dev->usbboot)
722 put_handshake_usb(ft1000dev,
723 HANDSHAKE_RESPONSE);
724 else
725 put_handshake(ft1000dev,
726 HANDSHAKE_RESPONSE);
727 } else {
728 DEBUG
729 ("FT1000:download:Download error: Handshake failed\n");
730 status = -1;
731 }
732
733 break;
734
735 case STATE_CODE_DWNLD:
736
737 ft1000dev->bootmode = 0;
738 if (ft1000dev->usbboot)
739 handshake =
740 get_handshake_usb(ft1000dev,
741 HANDSHAKE_REQUEST);
742 else
743 handshake =
744 get_handshake(ft1000dev, HANDSHAKE_REQUEST);
745 if (handshake == HANDSHAKE_REQUEST) {
746
747
748
749 if (ft1000dev->usbboot)
750 request =
751 get_request_type_usb(ft1000dev);
752 else
753 request = get_request_type(ft1000dev);
754 switch (request) {
755 case REQUEST_FILE_CHECKSUM:
756 DEBUG
757 ("FT1000:download:image_chksum = 0x%8x\n",
758 image_chksum);
759 put_request_value(ft1000dev,
760 image_chksum);
761 break;
762 case REQUEST_RUN_ADDRESS:
763 DEBUG
764 ("FT1000:download: REQUEST_RUN_ADDRESS\n");
765 if (correct_version) {
766 DEBUG
767 ("FT1000:download:run_address = 0x%8x\n",
768 (int)run_address);
769 put_request_value(ft1000dev,
770 run_address);
771 } else {
772 DEBUG
773 ("FT1000:download:Download error: Got Run address request before image offset request.\n");
774 status = -1;
775 break;
776 }
777 break;
778 case REQUEST_CODE_LENGTH:
779 DEBUG
780 ("FT1000:download:REQUEST_CODE_LENGTH\n");
781 if (correct_version) {
782 DEBUG
783 ("FT1000:download:run_size = 0x%8x\n",
784 (int)run_size);
785 put_request_value(ft1000dev,
786 run_size);
787 } else {
788 DEBUG
789 ("FT1000:download:Download error: Got Size request before image offset request.\n");
790 status = -1;
791 break;
792 }
793 break;
794 case REQUEST_DONE_CL:
795 ft1000dev->usbboot = 3;
796
797 s_file =
798 (u16 *) (pFileStart +
799 file_hdr->commands_offset);
800 c_file =
801 (u8 *) (pFileStart +
802 file_hdr->commands_offset);
803 state = STATE_DONE_DWNLD;
804 break;
805 case REQUEST_CODE_SEGMENT:
806
807 if (!correct_version) {
808 DEBUG
809 ("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
810 status = -1;
811 break;
812 }
813
814 status = request_code_segment(ft1000dev,
815 &s_file, &c_file,
816 (const u8 *)code_end,
817 false);
818
819 break;
820
821 case REQUEST_MAILBOX_DATA:
822 DEBUG
823 ("FT1000:download: REQUEST_MAILBOX_DATA\n");
824
825 word_length =
826 (long)(pft1000info->DSPInfoBlklen +
827 1) / 2;
828 put_request_value(ft1000dev,
829 word_length);
830 mailbox_data =
831 (struct drv_msg *)&(pft1000info->
832 DSPInfoBlk[0]);
833
834
835
836
837 data = (u16 *) &mailbox_data->data[0];
838 dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
839 if (word_length & 0x1)
840 word_length++;
841
842 word_length = (word_length / 2);
843
844 for (; word_length > 0; word_length--) {
845
846 templong = *data++;
847 templong |= (*data++ << 16);
848 status =
849 fix_ft1000_write_dpram32
850 (ft1000dev, dpram++,
851 (u8 *) &templong);
852
853 }
854 break;
855
856 case REQUEST_VERSION_INFO:
857 DEBUG
858 ("FT1000:download:REQUEST_VERSION_INFO\n");
859 word_length =
860 file_hdr->version_data_size;
861 put_request_value(ft1000dev,
862 word_length);
863
864
865
866
867 s_file =
868 (u16 *) (pFileStart +
869 file_hdr->
870 version_data_offset);
871
872 dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
873 if (word_length & 0x1)
874 word_length++;
875
876 word_length = (word_length / 2);
877
878 for (; word_length > 0; word_length--) {
879
880 templong = ntohs(*s_file++);
881 temp = ntohs(*s_file++);
882 templong |= (temp << 16);
883 status =
884 fix_ft1000_write_dpram32
885 (ft1000dev, dpram++,
886 (u8 *) &templong);
887
888 }
889 break;
890
891 case REQUEST_CODE_BY_VERSION:
892 DEBUG
893 ("FT1000:download:REQUEST_CODE_BY_VERSION\n");
894 correct_version = false;
895 requested_version =
896 get_request_value(ft1000dev);
897
898 dsp_img_info =
899 (struct dsp_image_info *)(pFileStart
900 +
901 sizeof
902 (struct
903 dsp_file_hdr));
904
905 for (image = 0;
906 image < file_hdr->nDspImages;
907 image++) {
908
909 if (dsp_img_info->version ==
910 requested_version) {
911 correct_version = true;
912 DEBUG
913 ("FT1000:download: correct_version is TRUE\n");
914 s_file =
915 (u16 *) (pFileStart
916 +
917 dsp_img_info->
918 begin_offset);
919 c_file =
920 (u8 *) (pFileStart +
921 dsp_img_info->
922 begin_offset);
923 code_end =
924 (u8 *) (pFileStart +
925 dsp_img_info->
926 end_offset);
927 run_address =
928 dsp_img_info->
929 run_address;
930 run_size =
931 dsp_img_info->
932 image_size;
933 image_chksum =
934 (u32) dsp_img_info->
935 checksum;
936 break;
937 }
938 dsp_img_info++;
939
940 }
941
942 if (!correct_version) {
943
944
945
946 DEBUG
947 ("FT1000:download:Download error: Bad Version Request = 0x%x.\n",
948 (int)requested_version);
949 status = -1;
950 break;
951 }
952 break;
953
954 default:
955 DEBUG
956 ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",
957 request);
958 status = -1;
959 break;
960 }
961 if (ft1000dev->usbboot)
962 put_handshake_usb(ft1000dev,
963 HANDSHAKE_RESPONSE);
964 else
965 put_handshake(ft1000dev,
966 HANDSHAKE_RESPONSE);
967 } else {
968 DEBUG
969 ("FT1000:download:Download error: Handshake failed\n");
970 status = -1;
971 }
972
973 break;
974
975 case STATE_DONE_DWNLD:
976 DEBUG("FT1000:download:Code loader is done...\n");
977 state = STATE_SECTION_PROV;
978 break;
979
980 case STATE_SECTION_PROV:
981 DEBUG("FT1000:download:STATE_SECTION_PROV\n");
982 pseudo_header = (struct pseudo_hdr *)c_file;
983
984 if (pseudo_header->checksum ==
985 hdr_checksum(pseudo_header)) {
986 if (pseudo_header->portdest !=
987 0x80 ) {
988 state = STATE_DONE_PROV;
989 break;
990 }
991 pseudo_header_len = ntohs(pseudo_header->length);
992
993
994 pbuffer =
995 kmalloc((pseudo_header_len +
996 sizeof(struct pseudo_hdr)),
997 GFP_ATOMIC);
998 if (pbuffer) {
999 memcpy(pbuffer, (void *)c_file,
1000 (u32) (pseudo_header_len +
1001 sizeof(struct
1002 pseudo_hdr)));
1003
1004 pprov_record =
1005 kmalloc(sizeof(struct prov_record),
1006 GFP_ATOMIC);
1007 if (pprov_record) {
1008 pprov_record->pprov_data =
1009 pbuffer;
1010 list_add_tail(&pprov_record->
1011 list,
1012 &pft1000info->
1013 prov_list);
1014
1015 c_file =
1016 (u8 *) ((unsigned long)
1017 c_file +
1018 (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
1019 if ((unsigned long)(c_file) -
1020 (unsigned long)(pFileStart)
1021 >=
1022 (unsigned long)FileLength) {
1023 state = STATE_DONE_FILE;
1024 }
1025 } else {
1026 kfree(pbuffer);
1027 status = -1;
1028 }
1029 } else {
1030 status = -1;
1031 }
1032 } else {
1033
1034 status = -1;
1035 }
1036 DEBUG
1037 ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n",
1038 state, status);
1039 break;
1040
1041 case STATE_DONE_PROV:
1042 DEBUG("FT1000:download:STATE_DONE_PROV\n");
1043 state = STATE_DONE_FILE;
1044 break;
1045
1046 default:
1047 status = -1;
1048 break;
1049 }
1050
1051 if (status != 0)
1052 break;
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067 }
1068
1069 DEBUG("Download exiting with status = 0x%8x\n", status);
1070 ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
1071 FT1000_REG_DOORBELL);
1072
1073 return status;
1074}
1075