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