Staging: ft1000: fix build
[deliverable/linux.git] / drivers / staging / ft1000 / ft1000-pcmcia / ft1000_dnld.c
CommitLineData
f7c1be0c
MB
1/*---------------------------------------------------------------------------
2 FT1000 driver for Flarion Flash OFDM NIC Device
3
4 Copyright (C) 2002 Flarion Technologies, All rights reserved.
5
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 --------------------------------------------------------------------------
17
18 Description: This module will handshake with the DSP bootloader to
19 download the DSP runtime image.
20
21---------------------------------------------------------------------------*/
22
23#define __KERNEL_SYSCALLS__
24
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>
37
38#include "ft1000_dev.h"
39#include "ft1000.h"
40#include "boot.h"
41
42#ifdef FT_DEBUG
43#define DEBUG(n, args...) printk(KERN_DEBUG args);
44#else
45#define DEBUG(n, args...)
46#endif
47
48#define MAX_DSP_WAIT_LOOPS 100
49#define DSP_WAIT_SLEEP_TIME 1 /* 1 millisecond */
50
51#define MAX_LENGTH 0x7f0
52
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
57
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
63
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 */
69
70#define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
71#define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
72
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
82
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
90
91USHORT get_handshake(struct net_device *dev, USHORT expected_value);
92void put_handshake(struct net_device *dev, USHORT handshake_value);
93USHORT get_request_type(struct net_device *dev);
94long get_request_value(struct net_device *dev);
95void put_request_value(struct net_device *dev, long lvalue);
96USHORT hdr_checksum(PPSEUDO_HDR pHdr);
97
98typedef 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;
109
110typedef 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;
123
124typedef 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;
132
133typedef 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;
143
144void card_bootload(struct net_device *dev)
145{
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;
152
153 DEBUG(0, "card_bootload is called\n");
154
155 pdata = (PULONG) bootimage;
156 size = sizeof(bootimage);
157
158 // check for odd word
159 if (size & 0x0003) {
160 size += 4;
161 }
162 // Provide mutual exclusive access while reading ASIC registers.
163 spin_lock_irqsave(&info->dpram_lock, flags);
164
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);
171 }
172
173 spin_unlock_irqrestore(&info->dpram_lock, flags);
174}
175
176USHORT get_handshake(struct net_device *dev, USHORT expected_value)
177{
178 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
179 USHORT handshake;
180 ULONG tempx;
181 int loopcnt;
182
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);
188
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;
195 }
196
197 if ((handshake == expected_value)
198 || (handshake == HANDSHAKE_RESET_VALUE)) {
199 return handshake;
200 } else {
201 loopcnt++;
202 mdelay(DSP_WAIT_SLEEP_TIME);
203 }
204
205 }
206
207 return HANDSHAKE_TIMEOUT_VALUE;
208
209}
210
211void put_handshake(struct net_device *dev, USHORT handshake_value)
212{
213 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
214 ULONG tempx;
215
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 */
224 }
225}
226
227USHORT get_request_type(struct net_device *dev)
228{
229 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
230 USHORT request_type;
231 ULONG tempx;
232
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;
240 }
241
242 return request_type;
243
244}
245
246long get_request_value(struct net_device *dev)
247{
248 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
249 long value;
250 USHORT w_val;
251
252 if (info->AsicID == ELECTRABUZZ_ID) {
253 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
254 DWNLD_SIZE_MSW_LOC);
255
256 w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
257
258 value = (long)(w_val << 16);
259
260 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
261 DWNLD_SIZE_LSW_LOC);
262
263 w_val = ft1000_read_reg(dev, FT1000_REG_DPRAM_DATA);
264
265 value = (long)(value | w_val);
266 } else {
267 value = ft1000_read_dpram_mag_32(dev, DWNLD_MAG_SIZE_LOC);
268 value = ntohl(value);
269 }
270
271 return value;
272
273}
274
275void put_request_value(struct net_device *dev, long lvalue)
276{
277 FT1000_INFO *info = (PFT1000_INFO) netdev_priv(dev);
278 USHORT size;
279 ULONG tempx;
280
281 if (info->AsicID == ELECTRABUZZ_ID) {
282 size = (USHORT) (lvalue >> 16);
283
284 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
285 DWNLD_SIZE_MSW_LOC);
286
287 ft1000_write_reg(dev, FT1000_REG_DPRAM_DATA, size);
288
289 size = (USHORT) (lvalue);
290
291 ft1000_write_reg(dev, FT1000_REG_DPRAM_ADDR,
292 DWNLD_SIZE_LSW_LOC);
293
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 */
298 }
299
300}
301
302USHORT hdr_checksum(PPSEUDO_HDR pHdr)
303{
304 USHORT *usPtr = (USHORT *) pHdr;
305 USHORT chksum;
306
307 chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
308 usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
309
310 return chksum;
311}
312
313int card_download(struct net_device *dev, void *pFileStart, UINT FileLength)
314{
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;
348
349 //
350 // Get version id of file, at first 4 bytes of file, for newer files.
351 //
352 file_version = *(long *)pFileStart;
353
354 uiState = STATE_START_DWNLD;
355
356 pFileHdr = (PDSP_FILE_HDR) pFileStart;
357 pFileHdr5 = (PDSP_FILE_HDR_5) pFileStart;
358
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);
366
367 pBootEnd =
368 (UCHAR *) ((long)pFileStart + pFileHdr5->loader_code_end);
369
370 loader_code_address = pFileHdr5->loader_code_address;
371 loader_code_size = pFileHdr5->loader_code_size;
372 bGoodVersion = FALSE;
373 break;
374
375 default:
376 Status = FAILURE;
377 break;
378 }
379
380 while ((Status == SUCCESS) && (uiState != STATE_DONE_FILE)) {
381
382 switch (uiState) {
383 case STATE_START_DWNLD:
384
385 handshake = get_handshake(dev, HANDSHAKE_DSP_BL_READY);
386
387 if (handshake == HANDSHAKE_DSP_BL_READY) {
388 put_handshake(dev, HANDSHAKE_DRIVER_READY);
389 } else {
390 Status = FAILURE;
391 }
392
393 uiState = STATE_BOOT_DWNLD;
394
395 break;
396
397 case STATE_BOOT_DWNLD:
398 handshake = get_handshake(dev, HANDSHAKE_REQUEST);
399 if (handshake == HANDSHAKE_REQUEST) {
400 /*
401 * Get type associated with the request.
402 */
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;
424 }
425 if ((word_length * 2 + (long)pUcFile) >
426 (long)pBootEnd) {
427 /*
428 * Error, beyond boot code range.
429 */
430 Status = FAILURE;
431 break;
432 }
433 // Provide mutual exclusive access while reading ASIC registers.
434 spin_lock_irqsave(&info->dpram_lock,
435 flags);
436 if (file_version == 5) {
437 /*
438 * Position ASIC DPRAM auto-increment pointer.
439 */
440 ft1000_write_reg(dev,
441 FT1000_REG_DPRAM_ADDR,
442 DWNLD_PS_HDR_LOC);
443
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++;
453 }
454 } else {
455 /*
456 * Position ASIC DPRAM auto-increment pointer.
457 */
458 outw(DWNLD_MAG_PS_HDR_LOC,
459 dev->base_addr +
460 FT1000_REG_DPRAM_ADDR);
461 if (word_length & 0x01) {
462 word_length++;
463 }
464 word_length = word_length / 2;
465
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);
474 }
475 }
476 spin_unlock_irqrestore(&info->
477 dpram_lock,
478 flags);
479 break;
480 default:
481 Status = FAILURE;
482 break;
483 }
484 put_handshake(dev, HANDSHAKE_RESPONSE);
485 } else {
486 Status = FAILURE;
487 }
488
489 break;
490
491 case STATE_CODE_DWNLD:
492 handshake = get_handshake(dev, HANDSHAKE_REQUEST);
493 if (handshake == HANDSHAKE_REQUEST) {
494 /*
495 * Get type associated with the request.
496 */
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;
511 }
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;
520 }
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
529 +
530 pFileHdr5->
531 commands_offset);
532 pUcFile =
533 (UCHAR *) ((long)pFileStart
534 +
535 pFileHdr5->
536 commands_offset);
537 break;
538 default:
539 Status = FAILURE;
540 break;
541 }
542 uiState = STATE_DONE_DWNLD;
543 break;
544 case REQUEST_CODE_SEGMENT:
545 if (!bGoodVersion) {
546 Status = FAILURE;
547 break;
548 }
549 word_length = get_request_value(dev);
550 if (word_length > MAX_LENGTH) {
551 Status = FAILURE;
552 break;
553 }
554 if ((word_length * 2 + (long)pUcFile) >
555 (long)pCodeEnd) {
556 /*
557 * Error, beyond boot code range.
558 */
559 Status = FAILURE;
560 break;
561 }
562 if (file_version == 5) {
563 /*
564 * Position ASIC DPRAM auto-increment pointer.
565 */
566 ft1000_write_reg(dev,
567 FT1000_REG_DPRAM_ADDR,
568 DWNLD_PS_HDR_LOC);
569
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++;
579 }
580 } else {
581 /*
582 * Position ASIC DPRAM auto-increment pointer.
583 */
584 outw(DWNLD_MAG_PS_HDR_LOC,
585 dev->base_addr +
586 FT1000_REG_DPRAM_ADDR);
587 if (word_length & 0x01) {
588 word_length++;
589 }
590 word_length = word_length / 2;
591
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);
600 }
601 }
602 break;
603
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) {
617 /*
618 * Position ASIC DPRAM auto-increment pointer.
619 */
620 ft1000_write_reg(dev,
621 FT1000_REG_DPRAM_ADDR,
622 DWNLD_PS_HDR_LOC);
623
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++;
630 }
631 } else {
632 /*
633 * Position ASIC DPRAM auto-increment pointer.
634 */
635 outw(DWNLD_MAG_PS_HDR_LOC,
636 dev->base_addr +
637 FT1000_REG_DPRAM_ADDR);
638 if (word_length & 0x01) {
639 word_length++;
640 }
641 word_length = word_length / 2;
642
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);
650 }
651 }
652 spin_unlock_irqrestore(&info->
653 dpram_lock,
654 flags);
655 break;
656
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) {
669 /*
670 * Position ASIC DPRAM auto-increment pointer.
671 */
672 ft1000_write_reg(dev,
673 FT1000_REG_DPRAM_ADDR,
674 DWNLD_PS_HDR_LOC);
675
676 for (; word_length > 0; word_length--) { /* In words */
677 ft1000_write_reg(dev,
678 FT1000_REG_DPRAM_DATA,
679 *pUsFile
680 /*temp */
681 );
682 pUsFile++;
683 }
684 } else {
685 /*
686 * Position ASIC DPRAM auto-increment pointer.
687 */
688 outw(DWNLD_MAG_PS_HDR_LOC,
689 dev->base_addr +
690 FT1000_REG_DPRAM_ADDR);
691 if (word_length & 0x01) {
692 word_length++;
693 }
694 word_length = word_length / 2;
695
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);
706 }
707 }
708 spin_unlock_irqrestore(&info->
709 dpram_lock,
710 flags);
711 break;
712
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
721 +
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
737 +
738 pDspImageInfo->
739 begin_offset);
740 pUcFile =
741 (UCHAR
742 *) ((long)
743 pFileStart
744 +
745 pDspImageInfo->
746 begin_offset);
747 pCodeEnd =
748 (UCHAR
749 *) ((long)
750 pFileStart
751 +
752 pDspImageInfo->
753 end_offset);
754 run_address =
755 pDspImageInfo->
756 run_address;
757 run_size =
758 pDspImageInfo->
759 image_size;
760 break;
761 }
762 pDspImageInfo++;
763 }
764 } else {
765 pDspImageInfoV6 =
766 (PDSP_IMAGE_INFO_V6) ((long)
767 pFileStart
768 +
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
792 +
793 pDspImageInfoV6->
794 begin_offset);
795 pUcFile =
796 (UCHAR
797 *) ((long)
798 pFileStart
799 +
800 pDspImageInfoV6->
801 begin_offset);
802 pCodeEnd =
803 (UCHAR
804 *) ((long)
805 pFileStart
806 +
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;
825 }
826 pDspImageInfoV6++;
827 }
828 }
829 if (!bGoodVersion) {
830 /*
831 * Error, beyond boot code range.
832 */
833 Status = FAILURE;
834 break;
835 }
836 break;
837
838 default:
839 Status = FAILURE;
840 break;
841 }
842 put_handshake(dev, HANDSHAKE_RESPONSE);
843 } else {
844 Status = FAILURE;
845 }
846
847 break;
848
849 case STATE_DONE_DWNLD:
850 if (((UINT) (pUcFile) - (UINT) pFileStart) >=
851 (UINT) FileLength) {
852 uiState = STATE_DONE_FILE;
853 break;
854 }
855
856 pHdr = (PPSEUDO_HDR) pUsFile;
857
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;
870 }
871
872 break;
873
874 case STATE_SECTION_PROV:
875
876 pHdr = (PPSEUDO_HDR) pUcFile;
877
878 if (pHdr->checksum == hdr_checksum(pHdr)) {
879 if (pHdr->portdest != 0x80 /* Dsp OAM */ ) {
880 uiState = STATE_DONE_PROV;
881 break;
882 }
883 usHdrLength = ntohs(pHdr->length); /* Byte length for PROV records */
884
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;
912 }
913 } else {
914 kfree(pbuffer);
915 Status = FAILURE;
916 }
917 } else {
918 Status = FAILURE;
919 }
920 } else {
921 /* Checksum did not compute */
922 Status = FAILURE;
923 }
924
925 break;
926
927 case STATE_DONE_PROV:
928 uiState = STATE_DONE_FILE;
929 break;
930
931 default:
932 Status = FAILURE;
933 break;
934 } /* End Switch */
935
936 } /* End while */
937
938 return Status;
939
940}
This page took 0.060773 seconds and 5 git commands to generate.