Staging: ft1000: remove trailing whitespace
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / ft1000 / ft1000-pcmcia / ft1000_dnld.c
blob0bf398d570dcaa1c814e62e742f8f547992d5b9d
1 /*---------------------------------------------------------------------------
2 FT1000 driver for Flarion Flash OFDM NIC Device
4 Copyright (C) 2002 Flarion Technologies, All rights reserved.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 2 of the License, or (at your option) any
9 later version. This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 more details. You should have received a copy of the GNU General Public
13 License along with this program; if not, write to the
14 Free Software Foundation, Inc., 59 Temple Place -
15 Suite 330, Boston, MA 02111-1307, USA.
16 --------------------------------------------------------------------------
18 Description: This module will handshake with the DSP bootloader to
19 download the DSP runtime image.
21 ---------------------------------------------------------------------------*/
23 #define __KERNEL_SYSCALLS__
25 #include <linux/module.h>
26 #include <linux/fs.h>
27 #include <linux/mm.h>
28 #include <linux/slab.h>
29 #include <linux/unistd.h>
30 #include <linux/netdevice.h>
31 #include <linux/timer.h>
32 #include <linux/delay.h>
33 #include <linux/slab.h>
34 #include <asm/io.h>
35 #include <asm/uaccess.h>
36 #include <linux/vmalloc.h>
38 #include "ft1000_dev.h"
39 #include "ft1000.h"
40 #include "boot.h"
42 #ifdef FT_DEBUG
43 #define DEBUG(n, args...) printk(KERN_DEBUG args);
44 #else
45 #define DEBUG(n, args...)
46 #endif
48 #define MAX_DSP_WAIT_LOOPS 100
49 #define DSP_WAIT_SLEEP_TIME 1 /* 1 millisecond */
51 #define MAX_LENGTH 0x7f0
53 #define DWNLD_MAG_HANDSHAKE_LOC 0x00
54 #define DWNLD_MAG_TYPE_LOC 0x01
55 #define DWNLD_MAG_SIZE_LOC 0x02
56 #define DWNLD_MAG_PS_HDR_LOC 0x03
58 #define DWNLD_HANDSHAKE_LOC 0x02
59 #define DWNLD_TYPE_LOC 0x04
60 #define DWNLD_SIZE_MSW_LOC 0x06
61 #define DWNLD_SIZE_LSW_LOC 0x08
62 #define DWNLD_PS_HDR_LOC 0x0A
64 #define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
65 #define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */
66 #define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */
67 #define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */
68 #define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */
70 #define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
71 #define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
73 #define REQUEST_CODE_LENGTH 0x0000
74 #define REQUEST_RUN_ADDRESS 0x0001
75 #define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */
76 #define REQUEST_DONE_BL 0x0003
77 #define REQUEST_DONE_CL 0x0004
78 #define REQUEST_VERSION_INFO 0x0005
79 #define REQUEST_CODE_BY_VERSION 0x0006
80 #define REQUEST_MAILBOX_DATA 0x0007
81 #define REQUEST_FILE_CHECKSUM 0x0008
83 #define STATE_START_DWNLD 0x01
84 #define STATE_BOOT_DWNLD 0x02
85 #define STATE_CODE_DWNLD 0x03
86 #define STATE_DONE_DWNLD 0x04
87 #define STATE_SECTION_PROV 0x05
88 #define STATE_DONE_PROV 0x06
89 #define STATE_DONE_FILE 0x07
91 USHORT get_handshake(struct net_device *dev, USHORT expected_value);
92 void put_handshake(struct net_device *dev, USHORT handshake_value);
93 USHORT get_request_type(struct net_device *dev);
94 long get_request_value(struct net_device *dev);
95 void put_request_value(struct net_device *dev, long lvalue);
96 USHORT hdr_checksum(PPSEUDO_HDR pHdr);
98 typedef struct _DSP_FILE_HDR {
99 long build_date;
100 long dsp_coff_date;
101 long loader_code_address;
102 long loader_code_size;
103 long loader_code_end;
104 long dsp_code_address;
105 long dsp_code_size;
106 long dsp_code_end;
107 long reserved[8];
108 } __attribute__ ((packed)) DSP_FILE_HDR, *PDSP_FILE_HDR;
110 typedef struct _DSP_FILE_HDR_5 {
111 long version_id; // Version ID of this image format.
112 long package_id; // Package ID of code release.
113 long build_date; // Date/time stamp when file was built.
114 long commands_offset; // Offset to attached commands in Pseudo Hdr format.
115 long loader_offset; // Offset to bootloader code.
116 long loader_code_address; // Start address of bootloader.
117 long loader_code_end; // Where bootloader code ends.
118 long loader_code_size;
119 long version_data_offset; // Offset were scrambled version data begins.
120 long version_data_size; // Size, in words, of scrambled version data.
121 long nDspImages; // Number of DSP images in file.
122 } __attribute__ ((packed)) DSP_FILE_HDR_5, *PDSP_FILE_HDR_5;
124 typedef struct _DSP_IMAGE_INFO {
125 long coff_date; // Date/time when DSP Coff image was built.
126 long begin_offset; // Offset in file where image begins.
127 long end_offset; // Offset in file where image begins.
128 long run_address; // On chip Start address of DSP code.
129 long image_size; // Size of image.
130 long version; // Embedded version # of DSP code.
131 } __attribute__ ((packed)) DSP_IMAGE_INFO, *PDSP_IMAGE_INFO;
133 typedef struct _DSP_IMAGE_INFO_V6 {
134 long coff_date; // Date/time when DSP Coff image was built.
135 long begin_offset; // Offset in file where image begins.
136 long end_offset; // Offset in file where image begins.
137 long run_address; // On chip Start address of DSP code.
138 long image_size; // Size of image.
139 long version; // Embedded version # of DSP code.
140 unsigned short checksum; // Dsp File checksum
141 unsigned short pad1;
142 } __attribute__ ((packed)) DSP_IMAGE_INFO_V6, *PDSP_IMAGE_INFO_V6;
144 void card_bootload(struct net_device *dev)
146 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
147 unsigned long flags;
148 PULONG pdata;
149 UINT size;
150 UINT i;
151 ULONG templong;
153 DEBUG(0, "card_bootload is called\n");
155 pdata = (PULONG) bootimage;
156 size = sizeof(bootimage);
158 // check for odd word
159 if (size & 0x0003) {
160 size += 4;
162 // Provide mutual exclusive access while reading ASIC registers.
163 spin_lock_irqsave(&info->dpram_lock, flags);
165 // need to set i/o base address initially and hardware will autoincrement
166 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, FT1000_DPRAM_BASE);
167 // write bytes
168 for (i = 0; i < (size >> 2); i++) {
169 templong = *pdata++;
170 outl(templong, dev->base_addr + FT1000_REG_MAG_DPDATA);
173 spin_unlock_irqrestore(&info->dpram_lock, flags);
176 USHORT get_handshake(struct net_device *dev, USHORT expected_value)
178 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
179 USHORT handshake;
180 ULONG tempx;
181 int loopcnt;
183 loopcnt = 0;
184 while (loopcnt < MAX_DSP_WAIT_LOOPS) {
185 if (info->AsicID == ELECTRABUZZ_ID) {
186 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
187 DWNLD_HANDSHAKE_LOC);
189 handshake = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
190 } else {
191 tempx =
192 ntohl(ft1000_read_dpram_mag_32
193 (dev, DWNLD_MAG_HANDSHAKE_LOC));
194 handshake = (USHORT) tempx;
197 if ((handshake == expected_value)
198 || (handshake == HANDSHAKE_RESET_VALUE)) {
199 return handshake;
200 } else {
201 loopcnt++;
202 mdelay(DSP_WAIT_SLEEP_TIME);
207 return HANDSHAKE_TIMEOUT_VALUE;
211 void put_handshake(struct net_device *dev, USHORT handshake_value)
213 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
214 ULONG tempx;
216 if (info->AsicID == ELECTRABUZZ_ID) {
217 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
218 DWNLD_HANDSHAKE_LOC);
219 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, handshake_value); /* Handshake */
220 } else {
221 tempx = (ULONG) handshake_value;
222 tempx = ntohl(tempx);
223 ft1000_write_dpram_mag_32(dev, DWNLD_MAG_HANDSHAKE_LOC, tempx); /* Handshake */
227 USHORT get_request_type(struct net_device *dev)
229 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
230 USHORT request_type;
231 ULONG tempx;
233 if (info->AsicID == ELECTRABUZZ_ID) {
234 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR, DWNLD_TYPE_LOC);
235 request_type = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
236 } else {
237 tempx = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_TYPE_LOC);
238 tempx = ntohl(tempx);
239 request_type = (USHORT) tempx;
242 return request_type;
246 long get_request_value(struct net_device *dev)
248 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
249 long value;
250 USHORT w_val;
252 if (info->AsicID == ELECTRABUZZ_ID) {
253 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
254 DWNLD_SIZE_MSW_LOC);
256 w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
258 value = (long)(w_val << 16);
260 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
261 DWNLD_SIZE_LSW_LOC);
263 w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
265 value = (long)(value | w_val);
266 } else {
267 value = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC);
268 value = ntohl(value);
271 return value;
275 void put_request_value(struct net_device *dev, long lvalue)
277 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
278 USHORT size;
279 ULONG tempx;
281 if (info->AsicID == ELECTRABUZZ_ID) {
282 size = (USHORT) (lvalue >> 16);
284 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
285 DWNLD_SIZE_MSW_LOC);
287 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
289 size = (USHORT) (lvalue);
291 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
292 DWNLD_SIZE_LSW_LOC);
294 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
295 } else {
296 tempx = ntohl(lvalue);
297 ft1000_write_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC, tempx); /* Handshake */
302 USHORT hdr_checksum(PPSEUDO_HDR pHdr)
304 USHORT *usPtr = (USHORT *) pHdr;
305 USHORT chksum;
307 chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
308 usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
310 return chksum;
313 int card_download(struct net_device *dev, void *pFileStart, UINT FileLength)
315 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
316 int Status = SUCCESS;
317 USHORT DspWordCnt = 0;
318 UINT uiState;
319 USHORT handshake;
320 PPSEUDO_HDR pHdr;
321 USHORT usHdrLength;
322 PDSP_FILE_HDR pFileHdr;
323 long word_length;
324 USHORT request;
325 USHORT temp;
326 PPROV_RECORD pprov_record;
327 PUCHAR pbuffer;
328 PDSP_FILE_HDR_5 pFileHdr5;
329 PDSP_IMAGE_INFO pDspImageInfo = NULL;
330 PDSP_IMAGE_INFO_V6 pDspImageInfoV6 = NULL;
331 long requested_version;
332 BOOLEAN bGoodVersion = 0;
333 PDRVMSG pMailBoxData;
334 USHORT *pUsData = NULL;
335 USHORT *pUsFile = NULL;
336 UCHAR *pUcFile = NULL;
337 UCHAR *pBootEnd = NULL;
338 UCHAR *pCodeEnd = NULL;
339 int imageN;
340 long file_version;
341 long loader_code_address = 0;
342 long loader_code_size = 0;
343 long run_address = 0;
344 long run_size = 0;
345 unsigned long flags;
346 unsigned long templong;
347 unsigned long image_chksum = 0;
350 // Get version id of file, at first 4 bytes of file, for newer files.
352 file_version = *(long *)pFileStart;
354 uiState = STATE_START_DWNLD;
356 pFileHdr = (PDSP_FILE_HDR) pFileStart;
357 pFileHdr5 = (PDSP_FILE_HDR_5) pFileStart;
359 switch (file_version) {
360 case 5:
361 case 6:
362 pUsFile =
363 (USHORT *) ((long)pFileStart + pFileHdr5->loader_offset);
364 pUcFile =
365 (UCHAR *) ((long)pFileStart + pFileHdr5->loader_offset);
367 pBootEnd =
368 (UCHAR *) ((long)pFileStart + pFileHdr5->loader_code_end);
370 loader_code_address = pFileHdr5->loader_code_address;
371 loader_code_size = pFileHdr5->loader_code_size;
372 bGoodVersion = FALSE;
373 break;
375 default:
376 Status = FAILURE;
377 break;
380 while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) {
382 switch (uiState) {
383 case STATE_START_DWNLD:
385 handshake = get_handshake(dev, HANDSHAKE_DSP_BL_READY);
387 if (handshake == HANDSHAKE_DSP_BL_READY) {
388 put_handshake(dev, HANDSHAKE_DRIVER_READY);
389 } else {
390 Status = FAILURE;
393 uiState = STATE_BOOT_DWNLD;
395 break;
397 case STATE_BOOT_DWNLD:
398 handshake = get_handshake(dev, HANDSHAKE_REQUEST);
399 if (handshake == HANDSHAKE_REQUEST) {
401 * Get type associated with the request.
403 request = get_request_type(dev);
404 switch (request) {
405 case REQUEST_RUN_ADDRESS:
406 put_request_value(dev,
407 loader_code_address);
408 break;
409 case REQUEST_CODE_LENGTH:
410 put_request_value(dev,
411 loader_code_size);
412 break;
413 case REQUEST_DONE_BL:
414 /* Reposition ptrs to beginning of code section */
415 pUsFile = (USHORT *) ((long)pBootEnd);
416 pUcFile = (UCHAR *) ((long)pBootEnd);
417 uiState = STATE_CODE_DWNLD;
418 break;
419 case REQUEST_CODE_SEGMENT:
420 word_length = get_request_value(dev);
421 if (word_length > MAX_LENGTH) {
422 Status = FAILURE;
423 break;
425 if ((word_length * 2 + (long)pUcFile) >
426 (long)pBootEnd) {
428 * Error, beyond boot code range.
430 Status = FAILURE;
431 break;
433 // Provide mutual exclusive access while reading ASIC registers.
434 spin_lock_irqsave(&info->dpram_lock,
435 flags);
436 if (file_version == 5) {
438 * Position ASIC DPRAM auto-increment pointer.
440 ft1000_write_reg(dev,
441 FT1000_REG_DPRAM_ADDR,
442 DWNLD_PS_HDR_LOC);
444 for (; word_length > 0; word_length--) { /* In words */
445 //temp = *pUsFile;
446 //temp = RtlUshortByteSwap(temp);
447 ft1000_write_reg(dev,
448 FT1000_REG_DPRAM_DATA,
449 *pUsFile);
450 pUsFile++;
451 pUcFile += 2;
452 DspWordCnt++;
454 } else {
456 * Position ASIC DPRAM auto-increment pointer.
458 outw(DWNLD_MAG_PS_HDR_LOC,
459 dev->base_addr +
460 FT1000_REG_DPRAM_ADDR);
461 if (word_length & 0x01) {
462 word_length++;
464 word_length = word_length / 2;
466 for (; word_length > 0; word_length--) { /* In words */
467 templong = *pUsFile++;
468 templong |=
469 (*pUsFile++ << 16);
470 pUcFile += 4;
471 outl(templong,
472 dev->base_addr +
473 FT1000_REG_MAG_DPDATAL);
476 spin_unlock_irqrestore(&info->
477 dpram_lock,
478 flags);
479 break;
480 default:
481 Status = FAILURE;
482 break;
484 put_handshake(dev, HANDSHAKE_RESPONSE);
485 } else {
486 Status = FAILURE;
489 break;
491 case STATE_CODE_DWNLD:
492 handshake = get_handshake(dev, HANDSHAKE_REQUEST);
493 if (handshake == HANDSHAKE_REQUEST) {
495 * Get type associated with the request.
497 request = get_request_type(dev);
498 switch (request) {
499 case REQUEST_FILE_CHECKSUM:
500 DEBUG(0,
501 "ft1000_dnld: REQUEST_FOR_CHECKSUM\n");
502 put_request_value(dev, image_chksum);
503 break;
504 case REQUEST_RUN_ADDRESS:
505 if (bGoodVersion) {
506 put_request_value(dev,
507 run_address);
508 } else {
509 Status = FAILURE;
510 break;
512 break;
513 case REQUEST_CODE_LENGTH:
514 if (bGoodVersion) {
515 put_request_value(dev,
516 run_size);
517 } else {
518 Status = FAILURE;
519 break;
521 break;
522 case REQUEST_DONE_CL:
523 /* Reposition ptrs to beginning of provisioning section */
524 switch (file_version) {
525 case 5:
526 case 6:
527 pUsFile =
528 (USHORT *) ((long)pFileStart
530 pFileHdr5->
531 commands_offset);
532 pUcFile =
533 (UCHAR *) ((long)pFileStart
535 pFileHdr5->
536 commands_offset);
537 break;
538 default:
539 Status = FAILURE;
540 break;
542 uiState = STATE_DONE_DWNLD;
543 break;
544 case REQUEST_CODE_SEGMENT:
545 if (!bGoodVersion) {
546 Status = FAILURE;
547 break;
549 word_length = get_request_value(dev);
550 if (word_length > MAX_LENGTH) {
551 Status = FAILURE;
552 break;
554 if ((word_length * 2 + (long)pUcFile) >
555 (long)pCodeEnd) {
557 * Error, beyond boot code range.
559 Status = FAILURE;
560 break;
562 if (file_version == 5) {
564 * Position ASIC DPRAM auto-increment pointer.
566 ft1000_write_reg(dev,
567 FT1000_REG_DPRAM_ADDR,
568 DWNLD_PS_HDR_LOC);
570 for (; word_length > 0; word_length--) { /* In words */
571 //temp = *pUsFile;
572 //temp = RtlUshortByteSwap(temp);
573 ft1000_write_reg(dev,
574 FT1000_REG_DPRAM_DATA,
575 *pUsFile);
576 pUsFile++;
577 pUcFile += 2;
578 DspWordCnt++;
580 } else {
582 * Position ASIC DPRAM auto-increment pointer.
584 outw(DWNLD_MAG_PS_HDR_LOC,
585 dev->base_addr +
586 FT1000_REG_DPRAM_ADDR);
587 if (word_length & 0x01) {
588 word_length++;
590 word_length = word_length / 2;
592 for (; word_length > 0; word_length--) { /* In words */
593 templong = *pUsFile++;
594 templong |=
595 (*pUsFile++ << 16);
596 pUcFile += 4;
597 outl(templong,
598 dev->base_addr +
599 FT1000_REG_MAG_DPDATAL);
602 break;
604 case REQUEST_MAILBOX_DATA:
605 // Convert length from byte count to word count. Make sure we round up.
606 word_length =
607 (long)(info->DSPInfoBlklen + 1) / 2;
608 put_request_value(dev, word_length);
609 pMailBoxData =
610 (PDRVMSG) & info->DSPInfoBlk[0];
611 pUsData =
612 (USHORT *) & pMailBoxData->data[0];
613 // Provide mutual exclusive access while reading ASIC registers.
614 spin_lock_irqsave(&info->dpram_lock,
615 flags);
616 if (file_version == 5) {
618 * Position ASIC DPRAM auto-increment pointer.
620 ft1000_write_reg(dev,
621 FT1000_REG_DPRAM_ADDR,
622 DWNLD_PS_HDR_LOC);
624 for (; word_length > 0; word_length--) { /* In words */
625 temp = ntohs(*pUsData);
626 ft1000_write_reg(dev,
627 FT1000_REG_DPRAM_DATA,
628 temp);
629 pUsData++;
631 } else {
633 * Position ASIC DPRAM auto-increment pointer.
635 outw(DWNLD_MAG_PS_HDR_LOC,
636 dev->base_addr +
637 FT1000_REG_DPRAM_ADDR);
638 if (word_length & 0x01) {
639 word_length++;
641 word_length = word_length / 2;
643 for (; word_length > 0; word_length--) { /* In words */
644 templong = *pUsData++;
645 templong |=
646 (*pUsData++ << 16);
647 outl(templong,
648 dev->base_addr +
649 FT1000_REG_MAG_DPDATAL);
652 spin_unlock_irqrestore(&info->
653 dpram_lock,
654 flags);
655 break;
657 case REQUEST_VERSION_INFO:
658 word_length =
659 pFileHdr5->version_data_size;
660 put_request_value(dev, word_length);
661 pUsFile =
662 (USHORT *) ((long)pFileStart +
663 pFileHdr5->
664 version_data_offset);
665 // Provide mutual exclusive access while reading ASIC registers.
666 spin_lock_irqsave(&info->dpram_lock,
667 flags);
668 if (file_version == 5) {
670 * Position ASIC DPRAM auto-increment pointer.
672 ft1000_write_reg(dev,
673 FT1000_REG_DPRAM_ADDR,
674 DWNLD_PS_HDR_LOC);
676 for (; word_length > 0; word_length--) { /* In words */
677 ft1000_write_reg(dev,
678 FT1000_REG_DPRAM_DATA,
679 *pUsFile
680 /*temp */
682 pUsFile++;
684 } else {
686 * Position ASIC DPRAM auto-increment pointer.
688 outw(DWNLD_MAG_PS_HDR_LOC,
689 dev->base_addr +
690 FT1000_REG_DPRAM_ADDR);
691 if (word_length & 0x01) {
692 word_length++;
694 word_length = word_length / 2;
696 for (; word_length > 0; word_length--) { /* In words */
697 templong =
698 ntohs(*pUsFile++);
699 temp =
700 ntohs(*pUsFile++);
701 templong |=
702 (temp << 16);
703 outl(templong,
704 dev->base_addr +
705 FT1000_REG_MAG_DPDATAL);
708 spin_unlock_irqrestore(&info->
709 dpram_lock,
710 flags);
711 break;
713 case REQUEST_CODE_BY_VERSION:
714 bGoodVersion = FALSE;
715 requested_version =
716 get_request_value(dev);
717 if (file_version == 5) {
718 pDspImageInfo =
719 (PDSP_IMAGE_INFO) ((long)
720 pFileStart
722 sizeof
723 (DSP_FILE_HDR_5));
724 for (imageN = 0;
725 imageN <
726 pFileHdr5->nDspImages;
727 imageN++) {
728 if (pDspImageInfo->
729 version ==
730 requested_version) {
731 bGoodVersion =
732 TRUE;
733 pUsFile =
734 (USHORT
735 *) ((long)
736 pFileStart
738 pDspImageInfo->
739 begin_offset);
740 pUcFile =
741 (UCHAR
742 *) ((long)
743 pFileStart
745 pDspImageInfo->
746 begin_offset);
747 pCodeEnd =
748 (UCHAR
749 *) ((long)
750 pFileStart
752 pDspImageInfo->
753 end_offset);
754 run_address =
755 pDspImageInfo->
756 run_address;
757 run_size =
758 pDspImageInfo->
759 image_size;
760 break;
762 pDspImageInfo++;
764 } else {
765 pDspImageInfoV6 =
766 (PDSP_IMAGE_INFO_V6) ((long)
767 pFileStart
769 sizeof
770 (DSP_FILE_HDR_5));
771 for (imageN = 0;
772 imageN <
773 pFileHdr5->nDspImages;
774 imageN++) {
775 temp = (USHORT)
776 (pDspImageInfoV6->
777 version);
778 templong = temp;
779 temp = (USHORT)
780 (pDspImageInfoV6->
781 version >> 16);
782 templong |=
783 (temp << 16);
784 if (templong ==
785 requested_version) {
786 bGoodVersion =
787 TRUE;
788 pUsFile =
789 (USHORT
790 *) ((long)
791 pFileStart
793 pDspImageInfoV6->
794 begin_offset);
795 pUcFile =
796 (UCHAR
797 *) ((long)
798 pFileStart
800 pDspImageInfoV6->
801 begin_offset);
802 pCodeEnd =
803 (UCHAR
804 *) ((long)
805 pFileStart
807 pDspImageInfoV6->
808 end_offset);
809 run_address =
810 pDspImageInfoV6->
811 run_address;
812 run_size =
813 pDspImageInfoV6->
814 image_size;
815 image_chksum =
816 (ULONG)
817 pDspImageInfoV6->
818 checksum;
819 DEBUG(0,
820 "ft1000_dnld: image_chksum = 0x%8x\n",
821 (unsigned
822 int)
823 image_chksum);
824 break;
826 pDspImageInfoV6++;
829 if (!bGoodVersion) {
831 * Error, beyond boot code range.
833 Status = FAILURE;
834 break;
836 break;
838 default:
839 Status = FAILURE;
840 break;
842 put_handshake(dev, HANDSHAKE_RESPONSE);
843 } else {
844 Status = FAILURE;
847 break;
849 case STATE_DONE_DWNLD:
850 if (((UINT) (pUcFile) - (UINT) pFileStart) >=
851 (UINT) FileLength) {
852 uiState = STATE_DONE_FILE;
853 break;
856 pHdr = (PPSEUDO_HDR) pUsFile;
858 if (pHdr->portdest == 0x80 /* DspOAM */
859 && (pHdr->portsrc == 0x00 /* Driver */
860 || pHdr->portsrc == 0x10 /* FMM */ )) {
861 uiState = STATE_SECTION_PROV;
862 } else {
863 DEBUG(1,
864 "FT1000:download:Download error: Bad Port IDs in Pseudo Record\n");
865 DEBUG(1, "\t Port Source = 0x%2.2x\n",
866 pHdr->portsrc);
867 DEBUG(1, "\t Port Destination = 0x%2.2x\n",
868 pHdr->portdest);
869 Status = FAILURE;
872 break;
874 case STATE_SECTION_PROV:
876 pHdr = (PPSEUDO_HDR) pUcFile;
878 if (pHdr->checksum == hdr_checksum(pHdr)) {
879 if (pHdr->portdest != 0x80 /* Dsp OAM */ ) {
880 uiState = STATE_DONE_PROV;
881 break;
883 usHdrLength = ntohs(pHdr->length); /* Byte length for PROV records */
885 // Get buffer for provisioning data
886 pbuffer =
887 kmalloc((usHdrLength + sizeof(PSEUDO_HDR)),
888 GFP_ATOMIC);
889 if (pbuffer) {
890 memcpy(pbuffer, (void *)pUcFile,
891 (UINT) (usHdrLength +
892 sizeof(PSEUDO_HDR)));
893 // link provisioning data
894 pprov_record =
895 kmalloc(sizeof(PROV_RECORD),
896 GFP_ATOMIC);
897 if (pprov_record) {
898 pprov_record->pprov_data =
899 pbuffer;
900 list_add_tail(&pprov_record->
901 list,
902 &info->prov_list);
903 // Move to next entry if available
904 pUcFile =
905 (UCHAR *) ((UINT) pUcFile +
906 (UINT) ((usHdrLength + 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR));
907 if ((UINT) (pUcFile) -
908 (UINT) (pFileStart) >=
909 (UINT) FileLength) {
910 uiState =
911 STATE_DONE_FILE;
913 } else {
914 kfree(pbuffer);
915 Status = FAILURE;
917 } else {
918 Status = FAILURE;
920 } else {
921 /* Checksum did not compute */
922 Status = FAILURE;
925 break;
927 case STATE_DONE_PROV:
928 uiState = STATE_DONE_FILE;
929 break;
931 default:
932 Status = FAILURE;
933 break;
934 } /* End Switch */
936 } /* End while */
938 return Status;