1 //=====================================================
2 // CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved.
5 // This file is part of Express Card USB Driver
8 //====================================================
9 // 20090926; aelias; removed compiler warnings; ubuntu 9.04; 2.6.28-15-generic
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"
22 #define DWNLD_HANDSHAKE_LOC 0x02
23 #define DWNLD_TYPE_LOC 0x04
24 #define DWNLD_SIZE_MSW_LOC 0x06
25 #define DWNLD_SIZE_LSW_LOC 0x08
26 #define DWNLD_PS_HDR_LOC 0x0A
28 #define MAX_DSP_WAIT_LOOPS 40
29 #define DSP_WAIT_SLEEP_TIME 1000 /* 1 millisecond */
30 #define DSP_WAIT_DISPATCH_LVL 50 /* 50 usec */
32 #define HANDSHAKE_TIMEOUT_VALUE 0xF1F1
33 #define HANDSHAKE_RESET_VALUE 0xFEFE /* When DSP requests startover */
34 #define HANDSHAKE_RESET_VALUE_USB 0xFE7E /* When DSP requests startover */
35 #define HANDSHAKE_DSP_BL_READY 0xFEFE /* At start DSP writes this when bootloader ready */
36 #define HANDSHAKE_DSP_BL_READY_USB 0xFE7E /* At start DSP writes this when bootloader ready */
37 #define HANDSHAKE_DRIVER_READY 0xFFFF /* Driver writes after receiving 0xFEFE */
38 #define HANDSHAKE_SEND_DATA 0x0000 /* DSP writes this when ready for more data */
40 #define HANDSHAKE_REQUEST 0x0001 /* Request from DSP */
41 #define HANDSHAKE_RESPONSE 0x0000 /* Satisfied DSP request */
43 #define REQUEST_CODE_LENGTH 0x0000
44 #define REQUEST_RUN_ADDRESS 0x0001
45 #define REQUEST_CODE_SEGMENT 0x0002 /* In WORD count */
46 #define REQUEST_DONE_BL 0x0003
47 #define REQUEST_DONE_CL 0x0004
48 #define REQUEST_VERSION_INFO 0x0005
49 #define REQUEST_CODE_BY_VERSION 0x0006
50 #define REQUEST_MAILBOX_DATA 0x0007
51 #define REQUEST_FILE_CHECKSUM 0x0008
53 #define STATE_START_DWNLD 0x01
54 #define STATE_BOOT_DWNLD 0x02
55 #define STATE_CODE_DWNLD 0x03
56 #define STATE_DONE_DWNLD 0x04
57 #define STATE_SECTION_PROV 0x05
58 #define STATE_DONE_PROV 0x06
59 #define STATE_DONE_FILE 0x07
61 #define MAX_LENGTH 0x7f0
63 // Temporary download mechanism for Magnemite
64 #define DWNLD_MAG_TYPE_LOC 0x00
65 #define DWNLD_MAG_LEN_LOC 0x01
66 #define DWNLD_MAG_ADDR_LOC 0x02
67 #define DWNLD_MAG_CHKSUM_LOC 0x03
68 #define DWNLD_MAG_VAL_LOC 0x04
70 #define HANDSHAKE_MAG_DSP_BL_READY 0xFEFE0000 /* At start DSP writes this when bootloader ready */
71 #define HANDSHAKE_MAG_DSP_ENTRY 0x01000000 /* Dsp writes this to request for entry address */
72 #define HANDSHAKE_MAG_DSP_DATA 0x02000000 /* Dsp writes this to request for data block */
73 #define HANDSHAKE_MAG_DSP_DONE 0x03000000 /* Dsp writes this to indicate download done */
75 #define HANDSHAKE_MAG_DRV_READY 0xFFFF0000 /* Driver writes this to indicate ready to download */
76 #define HANDSHAKE_MAG_DRV_DATA 0x02FECDAB /* Driver writes this to indicate data available to DSP */
77 #define HANDSHAKE_MAG_DRV_ENTRY 0x01FECDAB /* Driver writes this to indicate entry point to DSP */
79 #define HANDSHAKE_MAG_TIMEOUT_VALUE 0xF1F1
82 // New Magnemite downloader
83 #define DWNLD_MAG1_HANDSHAKE_LOC 0x00
84 #define DWNLD_MAG1_TYPE_LOC 0x01
85 #define DWNLD_MAG1_SIZE_LOC 0x02
86 #define DWNLD_MAG1_PS_HDR_LOC 0x03
88 #pragma pack (push, pack_save, 1)
89 typedef struct _DSP_FILE_HDR
{
92 long loader_code_address
;
93 long loader_code_size
;
95 long dsp_code_address
;
99 } DSP_FILE_HDR
, *PDSP_FILE_HDR
;
101 typedef struct _DSP_FILE_HDR_5
{
102 long version_id
; // Version ID of this image format.
103 long package_id
; // Package ID of code release.
104 long build_date
; // Date/time stamp when file was built.
105 long commands_offset
; // Offset to attached commands in Pseudo Hdr format.
106 long loader_offset
; // Offset to bootloader code.
107 long loader_code_address
; // Start address of bootloader.
108 long loader_code_end
; // Where bootloader code ends.
109 long loader_code_size
;
110 long version_data_offset
; // Offset were scrambled version data begins.
111 long version_data_size
; // Size, in words, of scrambled version data.
112 long nDspImages
; // Number of DSP images in file.
113 } DSP_FILE_HDR_5
, * PDSP_FILE_HDR_5
;
115 typedef struct _DSP_IMAGE_INFO
{
116 long coff_date
; // Date/time when DSP Coff image was built.
117 long begin_offset
; // Offset in file where image begins.
118 long end_offset
; // Offset in file where image begins.
119 long run_address
; // On chip Start address of DSP code.
120 long image_size
; // Size of image.
121 long version
; // Embedded version # of DSP code.
122 } DSP_IMAGE_INFO
, *PDSP_IMAGE_INFO
;
124 typedef struct _DSP_IMAGE_INFO_V6
{
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 unsigned short checksum
; // DSP File checksum
133 } DSP_IMAGE_INFO_V6
, *PDSP_IMAGE_INFO_V6
;
136 //---------------------------------------------------------------------------
139 // Parameters: char *fn - input DSP image file name
140 // int *pimgsz - output DSP image file size
141 // Returns: DSP image buffer
143 // Description: Read the DSP image file into a char buffer
147 //---------------------------------------------------------------------------
148 char *getfw (char *fn
, size_t *pimgsz
)
151 mm_segment_t fs
= get_fs();
158 fd
= filp_open(fn
, 0, 0);
161 DEBUG("FT1000:%s:can not open dsp image\n", __FUNCTION__
);
166 fwimgsz
= i_size_read(fd
->f_dentry
->d_inode
);
171 DEBUG("FT1000:%s:invalid file size\n", __FUNCTION__
);
172 filp_close(fd
, current
->files
);
176 pfwimg
= (char*)vmalloc ( fwimgsz
);
177 if (pfwimg
== NULL
) {
178 DEBUG("FT1000:%s:can not allocate memory for dsp image\n", __FUNCTION__
);
179 filp_close(fd
, current
->files
);
184 if (vfs_read(fd
, (void __user __force
*)pfwimg
, fwimgsz
, &pos
) != fwimgsz
) {
186 DEBUG("FT1000:%s:failed to read firmware image\n",__FUNCTION__
);
187 filp_close(fd
, current
->files
);
192 filp_close(fd
, current
->files
);
198 //---------------------------------------------------------------------------
199 // Function: check_usb_db
201 // Parameters: struct ft1000_device - device structure
203 // Returns: 0 - success
205 // Description: This function checks if the doorbell register is cleared
209 //---------------------------------------------------------------------------
210 static ULONG
check_usb_db (struct ft1000_device
*ft1000dev
)
220 status
= ft1000_read_register (ft1000dev
, &temp
, FT1000_REG_DOORBELL
);
221 DEBUG("check_usb_db: read FT1000_REG_DOORBELL value is %x\n", temp
);
224 DEBUG("FT1000:Got checkusb doorbell\n");
225 status
= ft1000_write_register (ft1000dev
, 0x0080, FT1000_REG_DOORBELL
);
227 status
= ft1000_write_register (ft1000dev
, 0x0100, FT1000_REG_DOORBELL
);
229 status
= ft1000_write_register (ft1000dev
, 0x8000, FT1000_REG_DOORBELL
);
245 status
= ft1000_read_register (ft1000dev
, &temp
, FT1000_REG_DOORBELL
);
246 DEBUG("FT1000:check_usb_db:Doorbell = 0x%x\n", temp
);
254 DEBUG("check_usb_db: door bell is cleared, return 0\n");
258 // Check if Card is present
259 status
= ft1000_read_register (ft1000dev
, &temp
, FT1000_REG_SUP_IMASK
);
260 if (temp
== 0x0000) {
264 status
= ft1000_read_register (ft1000dev
, &temp
, FT1000_REG_ASIC_ID
);
265 if (temp
== 0xffff) {
271 return HANDSHAKE_MAG_TIMEOUT_VALUE
;
275 //---------------------------------------------------------------------------
276 // Function: get_handshake
278 // Parameters: struct ft1000_device - device structure
279 // USHORT expected_value - the handshake value expected
281 // Returns: handshakevalue - success
282 // HANDSHAKE_TIMEOUT_VALUE - failure
284 // Description: This function gets the handshake and compare with the expected value
288 //---------------------------------------------------------------------------
289 static USHORT
get_handshake(struct ft1000_device
*ft1000dev
, USHORT expected_value
)
294 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
297 while (loopcnt
< 100)
301 // Need to clear downloader doorbell if Hartley ASIC
302 status
= ft1000_write_register (ft1000dev
, FT1000_DB_DNLD_RX
, FT1000_REG_DOORBELL
);
303 //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp);
304 if (pft1000info
->fcodeldr
)
306 DEBUG(" get_handshake: fcodeldr is %d\n", pft1000info
->fcodeldr
);
307 pft1000info
->fcodeldr
= 0;
308 status
= check_usb_db(ft1000dev
);
309 if (status
!= STATUS_SUCCESS
)
311 DEBUG("get_handshake: check_usb_db failed\n");
312 status
= STATUS_FAILURE
;
315 status
= ft1000_write_register (ft1000dev
, FT1000_DB_DNLD_RX
, FT1000_REG_DOORBELL
);
318 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_HANDSHAKE_LOC
, (PUCHAR
)&handshake
, 1);
319 //DEBUG("get_handshake: handshake is %x\n", tempx);
320 handshake
= ntohs(handshake
);
321 //DEBUG("get_handshake: after swap, handshake is %x\n", handshake);
323 // Need to clear downloader doorbell if Hartley ASIC
324 status
= ft1000_read_register (ft1000dev
, &temp
, FT1000_REG_DOORBELL
);
325 //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp);
328 if (temp
& FT1000_DB_DNLD_RX
)
330 //DEBUG("get_handshake: write FT1000_DB_DNLD_RX to doorbell register\n");
331 status
= ft1000_write_register(ft1000dev
, FT1000_DB_DNLD_RX
, FT1000_REG_DOORBELL
);
334 if (pft1000info
->fcodeldr
)
336 DEBUG(" get_handshake: fcodeldr is %d\n", pft1000info
->fcodeldr
);
337 pft1000info
->fcodeldr
= 0;
338 status
= check_usb_db(ft1000dev
);
339 if (status
!= STATUS_SUCCESS
)
341 DEBUG("get_handshake: check_usb_db failed\n");
342 status
= STATUS_FAILURE
;
346 status
= ft1000_read_register (ft1000dev
, &temp
, FT1000_REG_DOORBELL
);
347 //DEBUG("FT1000:get_handshake:doorbell = 0x%x\n", temp);
350 if (temp
& FT1000_DB_DNLD_RX
)
351 status
= ft1000_write_register(ft1000dev
,FT1000_DB_DNLD_RX
, FT1000_REG_DOORBELL
);
355 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_HANDSHAKE_LOC
, (PUCHAR
)&handshake
, 1);
356 //DEBUG("get_handshake: handshake is %x\n", tempx);
357 handshake
= ntohs(handshake
);
358 //DEBUG("get_handshake: after swap, handshake is %x\n", handshake);
365 return HANDSHAKE_TIMEOUT_VALUE
;
367 //DEBUG("get_handshake: handshake= %x\n", handshake);
368 if ((handshake
== expected_value
) || (handshake
== HANDSHAKE_RESET_VALUE_USB
))
370 //DEBUG("get_handshake: return handshake %x\n", handshake);
378 //DEBUG("HANDSHKE LOOP: %d\n", loopcnt);
382 //DEBUG("get_handshake: return handshake time out\n");
383 return HANDSHAKE_TIMEOUT_VALUE
;
386 //---------------------------------------------------------------------------
387 // Function: put_handshake
389 // Parameters: struct ft1000_device - device structure
390 // USHORT handshake_value - handshake to be written
394 // Description: This function write the handshake value to the handshake location
399 //---------------------------------------------------------------------------
400 static void put_handshake(struct ft1000_device
*ft1000dev
,USHORT handshake_value
)
409 tempx
= (ULONG
)handshake_value
;
410 tempx
= ntohl(tempx
);
412 tempword
= (USHORT
)(tempx
& 0xffff);
413 status
= ft1000_write_dpram16 (ft1000dev
, DWNLD_MAG1_HANDSHAKE_LOC
, tempword
, 0);
414 tempword
= (USHORT
)(tempx
>> 16);
415 status
= ft1000_write_dpram16 (ft1000dev
, DWNLD_MAG1_HANDSHAKE_LOC
, tempword
, 1);
416 status
= ft1000_write_register(ft1000dev
, FT1000_DB_DNLD_TX
, FT1000_REG_DOORBELL
);
418 for (i
=0; i
<1000; i
++);
422 status
= ft1000_read_register (ft1000dev
, &tempword
, FT1000_REG_DOORBELL
);
423 if ((tempword
& FT1000_DB_DNLD_TX
) == 0)
428 DEBUG("FT1000:put_handshake could not clear Tx doorbell\n");
429 status
= ft1000_read_register (ft1000dev
, &tempword
, FT1000_REG_DOORBELL
);
430 DEBUG("FT1000:put_handshake:doorbell = 0x%x\n",tempword
);
436 static USHORT
get_handshake_usb(struct ft1000_device
*ft1000dev
, USHORT expected_value
)
443 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
446 while (loopcnt
< 100)
448 if (pft1000info
->usbboot
== 2) {
449 status
= ft1000_read_dpram32 (ft1000dev
, 0, (PUCHAR
)&(pft1000info
->tempbuf
[0]), 64);
450 for (temp
=0; temp
<16; temp
++)
451 DEBUG("tempbuf %d = 0x%x\n", temp
, pft1000info
->tempbuf
[temp
]);
452 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_HANDSHAKE_LOC
, (PUCHAR
)&handshake
, 1);
453 DEBUG("handshake from read_dpram16 = 0x%x\n", handshake
);
454 if (pft1000info
->dspalive
== pft1000info
->tempbuf
[6])
457 handshake
= pft1000info
->tempbuf
[1];
458 pft1000info
->dspalive
= pft1000info
->tempbuf
[6];
462 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_HANDSHAKE_LOC
, (PUCHAR
)&handshake
, 1);
466 handshake
= ntohs(handshake
);
467 if ((handshake
== expected_value
) || (handshake
== HANDSHAKE_RESET_VALUE_USB
))
473 return HANDSHAKE_TIMEOUT_VALUE
;
476 static void put_handshake_usb(struct ft1000_device
*ft1000dev
,USHORT handshake_value
)
480 for (i
=0; i
<1000; i
++);
483 //---------------------------------------------------------------------------
484 // Function: get_request_type
486 // Parameters: struct ft1000_device - device structure
488 // Returns: request type - success
490 // Description: This function returns the request type
494 //---------------------------------------------------------------------------
495 static USHORT
get_request_type(struct ft1000_device
*ft1000dev
)
501 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
503 if ( pft1000info
->bootmode
== 1)
505 status
= fix_ft1000_read_dpram32 (ft1000dev
, DWNLD_MAG1_TYPE_LOC
, (PUCHAR
)&tempx
);
506 tempx
= ntohl(tempx
);
513 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_TYPE_LOC
, (PUCHAR
)&tempword
, 0);
516 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_TYPE_LOC
, (PUCHAR
)&tempword
, 1);
517 tempx
|= (tempword
<< 16);
518 tempx
= ntohl(tempx
);
520 request_type
= (USHORT
)tempx
;
522 //DEBUG("get_request_type: request_type is %x\n", request_type);
527 static USHORT
get_request_type_usb(struct ft1000_device
*ft1000dev
)
533 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
534 if ( pft1000info
->bootmode
== 1)
536 status
= fix_ft1000_read_dpram32 (ft1000dev
, DWNLD_MAG1_TYPE_LOC
, (PUCHAR
)&tempx
);
537 tempx
= ntohl(tempx
);
541 if (pft1000info
->usbboot
== 2) {
542 tempx
= pft1000info
->tempbuf
[2];
543 tempword
= pft1000info
->tempbuf
[3];
547 status
= ft1000_read_dpram16 (ft1000dev
, DWNLD_MAG1_TYPE_LOC
, (PUCHAR
)&tempword
, 1);
549 tempx
|= (tempword
<< 16);
550 tempx
= ntohl(tempx
);
552 request_type
= (USHORT
)tempx
;
554 //DEBUG("get_request_type: request_type is %x\n", request_type);
559 //---------------------------------------------------------------------------
560 // Function: get_request_value
562 // Parameters: struct ft1000_device - device structure
564 // Returns: request value - success
566 // Description: This function returns the request value
570 //---------------------------------------------------------------------------
571 static long get_request_value(struct ft1000_device
*ft1000dev
)
576 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
579 if ( pft1000info
->bootmode
== 1)
581 status
= fix_ft1000_read_dpram32(ft1000dev
, DWNLD_MAG1_SIZE_LOC
, (PUCHAR
)&value
);
582 value
= ntohl(value
);
586 status
= ft1000_read_dpram16(ft1000dev
, DWNLD_MAG1_SIZE_LOC
, (PUCHAR
)&tempword
, 0);
588 status
= ft1000_read_dpram16(ft1000dev
, DWNLD_MAG1_SIZE_LOC
, (PUCHAR
)&tempword
, 1);
589 value
|= (tempword
<< 16);
590 value
= ntohl(value
);
594 //DEBUG("get_request_value: value is %x\n", value);
600 static long get_request_value_usb(struct ft1000_device
*ft1000dev
)
605 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
607 if (pft1000info
->usbboot
== 2) {
608 value
= pft1000info
->tempbuf
[4];
609 tempword
= pft1000info
->tempbuf
[5];
613 status
= ft1000_read_dpram16(ft1000dev
, DWNLD_MAG1_SIZE_LOC
, (PUCHAR
)&tempword
, 1);
616 value
|= (tempword
<< 16);
617 value
= ntohl(value
);
620 if (pft1000info
->usbboot
== 1)
621 pft1000info
->usbboot
= 2;
624 //DEBUG("get_request_value_usb: value is %x\n", value);
630 //---------------------------------------------------------------------------
631 // Function: put_request_value
633 // Parameters: struct ft1000_device - device structure
634 // long lvalue - value to be put into DPRAM location DWNLD_MAG1_SIZE_LOC
638 // Description: This function writes a value to DWNLD_MAG1_SIZE_LOC
642 //---------------------------------------------------------------------------
643 static void put_request_value(struct ft1000_device
*ft1000dev
, long lvalue
)
648 tempx
= ntohl(lvalue
);
649 status
= fix_ft1000_write_dpram32(ft1000dev
, DWNLD_MAG1_SIZE_LOC
, (PUCHAR
)&tempx
);
653 //DEBUG("put_request_value: value is %x\n", lvalue);
659 //---------------------------------------------------------------------------
660 // Function: hdr_checksum
662 // Parameters: PPSEUDO_HDR pHdr - Pseudo header pointer
664 // Returns: checksum - success
666 // Description: This function returns the checksum of the pseudo header
670 //---------------------------------------------------------------------------
671 static USHORT
hdr_checksum(PPSEUDO_HDR pHdr
)
673 USHORT
*usPtr
= (USHORT
*)pHdr
;
677 chksum
= ((((((usPtr
[0] ^ usPtr
[1]) ^ usPtr
[2]) ^ usPtr
[3]) ^
678 usPtr
[4]) ^ usPtr
[5]) ^ usPtr
[6]);
684 //---------------------------------------------------------------------------
685 // Function: write_blk
687 // Parameters: struct ft1000_device - device structure
688 // USHORT **pUsFile - DSP image file pointer in USHORT
689 // UCHAR **pUcFile - DSP image file pointer in UCHAR
690 // long word_length - lenght of the buffer to be written
693 // Returns: STATUS_SUCCESS - success
694 // STATUS_FAILURE - failure
696 // Description: This function writes a block of DSP image to DPRAM
700 //---------------------------------------------------------------------------
701 static ULONG
write_blk (struct ft1000_device
*ft1000dev
, USHORT
**pUsFile
, UCHAR
**pUcFile
, long word_length
)
703 ULONG Status
= STATUS_SUCCESS
;
705 long temp_word_length
;
709 USHORT tempbuffer
[64];
710 USHORT resultbuffer
[64];
711 PFT1000_INFO pft1000info
= netdev_priv(ft1000dev
->net
);
713 //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length);
714 dpram
= (USHORT
)DWNLD_MAG1_PS_HDR_LOC
;
715 tempword
= *(*pUsFile
);
717 Status
= ft1000_write_dpram16(ft1000dev
, dpram
, tempword
, 0);
718 tempword
= *(*pUsFile
);
720 Status
= ft1000_write_dpram16(ft1000dev
, dpram
++, tempword
, 1);
722 *pUcFile
= *pUcFile
+ 4;
724 tempword
= (USHORT
)word_length
;
725 word_length
= (word_length
/ 16) + 1;
726 pTempFile
= *pUsFile
;
727 temp_word_length
= word_length
;
728 for (; word_length
> 0; word_length
--) /* In words */
736 tempbuffer
[i
++] = *(*pUsFile
);
738 tempbuffer
[i
] = *(*pUsFile
);
740 *pUcFile
= *pUcFile
+ 4;
751 //DEBUG("write_blk: loopcnt is %d\n", loopcnt);
752 //DEBUG("write_blk: bootmode = %d\n", bootmode);
753 //DEBUG("write_blk: dpram = %x\n", dpram);
754 if (pft1000info
->bootmode
== 0)
757 Status
= ft1000_write_dpram32 (ft1000dev
, dpram
, (PUCHAR
)&tempbuffer
[0], 8);
759 Status
= ft1000_write_dpram32 (ft1000dev
, dpram
, (PUCHAR
)&tempbuffer
[0], 64);
765 Status
= ft1000_write_dpram32 (ft1000dev
, dpram
, (PUCHAR
)&tempbuffer
[0], 64);
766 if (Status
== STATUS_SUCCESS
)
768 // Work around for ASIC bit stuffing problem.
769 if ( (tempbuffer
[31] & 0xfe00) == 0xfe00)
771 Status
= ft1000_write_dpram32(ft1000dev
, dpram
+12, (PUCHAR
)&tempbuffer
[24], 64);
773 // Let's check the data written
774 Status
= ft1000_read_dpram32 (ft1000dev
, dpram
, (PUCHAR
)&resultbuffer
[0], 64);
775 if ( (tempbuffer
[31] & 0xfe00) == 0xfe00)
779 if (resultbuffer
[i
] != tempbuffer
[i
])
782 DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
784 Status
= STATUS_FAILURE
;
788 Status
= ft1000_read_dpram32 (ft1000dev
, dpram
+12, (PUCHAR
)&resultbuffer
[0], 64);
791 if (resultbuffer
[i
] != tempbuffer
[i
+24])
794 DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
796 Status
= STATUS_FAILURE
;
805 if (resultbuffer
[i
] != tempbuffer
[i
])
808 DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
810 Status
= STATUS_FAILURE
;
816 if (Status
== STATUS_SUCCESS
)
822 if (Status
!= STATUS_SUCCESS
)
824 DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer
[31]);
829 dpram
= dpram
+ loopcnt
;
835 static void usb_dnld_complete (struct urb
*urb
)
837 //DEBUG("****** usb_dnld_complete\n");
840 //---------------------------------------------------------------------------
841 // Function: write_blk_fifo
843 // Parameters: struct ft1000_device - device structure
844 // USHORT **pUsFile - DSP image file pointer in USHORT
845 // UCHAR **pUcFile - DSP image file pointer in UCHAR
846 // long word_length - lenght of the buffer to be written
849 // Returns: STATUS_SUCCESS - success
850 // STATUS_FAILURE - failure
852 // Description: This function writes a block of DSP image to DPRAM
856 //---------------------------------------------------------------------------
857 static ULONG
write_blk_fifo (struct ft1000_device
*ft1000dev
, USHORT
**pUsFile
, UCHAR
**pUcFile
, long word_length
)
859 ULONG Status
= STATUS_SUCCESS
;
863 byte_length
= word_length
* 4;
866 aligncnt
= 4 - (byte_length
% 4);
869 byte_length
+= aligncnt
;
871 if (byte_length
&& ((byte_length
% 64) == 0)) {
875 if (byte_length
< 64)
879 pblk
= kzalloc(byte_length
, GFP_KERNEL
);
880 memcpy (pblk
, *pUcFile
, byte_length
);
882 pipe
= usb_sndbulkpipe (ft1000dev
->dev
, ft1000dev
->bulk_out_endpointAddr
);
884 Status
= usb_bulk_msg (ft1000dev
->dev
,
890 DEBUG("write_blk_fifo Status = 0x%8x Bytes Transfer = %d Data = 0x%x\n", Status
, cnt
, *pblk
);
894 usb_init_urb(ft1000dev
->tx_urb
);
895 memcpy (ft1000dev
->tx_buf
, *pUcFile
, byte_length
);
896 usb_fill_bulk_urb(ft1000dev
->tx_urb
,
898 usb_sndbulkpipe(ft1000dev
->dev
, ft1000dev
->bulk_out_endpointAddr
),
904 usb_submit_urb(ft1000dev
->tx_urb
, GFP_ATOMIC
);
907 *pUsFile
= *pUsFile
+ (word_length
<< 1);
908 *pUcFile
= *pUcFile
+ (word_length
<< 2);
913 //---------------------------------------------------------------------------
915 // Function: scram_dnldr
917 // Synopsis: Scramble downloader for Harley based ASIC via USB interface
919 // Arguments: pFileStart - pointer to start of file
920 // FileLength - file length
922 // Returns: status - return code
923 //---------------------------------------------------------------------------
925 u16
scram_dnldr(struct ft1000_device
*ft1000dev
, void *pFileStart
, ULONG FileLength
)
927 u16 Status
= STATUS_SUCCESS
;
932 //PPROV_RECORD pProvRecord;
933 PDSP_FILE_HDR pFileHdr
;
939 PDSP_FILE_HDR_5 pFileHdr5
;
940 PDSP_IMAGE_INFO_V6 pDspImageInfoV6
= NULL
;
941 long requested_version
;
942 BOOLEAN bGoodVersion
;
943 PDRVMSG pMailBoxData
;
944 USHORT
*pUsData
= NULL
;
945 USHORT
*pUsFile
= NULL
;
946 UCHAR
*pUcFile
= NULL
;
947 UCHAR
*pBootEnd
= NULL
, *pCodeEnd
= NULL
;
949 long loader_code_address
, loader_code_size
= 0;
950 long run_address
= 0, run_size
= 0;
953 ULONG image_chksum
= 0;
957 PPROV_RECORD pprov_record
;
958 FT1000_INFO
*pft1000info
= netdev_priv(ft1000dev
->net
);
960 DEBUG("Entered scram_dnldr...\n");
962 pft1000info
->fcodeldr
= 0;
963 pft1000info
->usbboot
= 0;
964 pft1000info
->dspalive
= 0xffff;
968 // Get version id of file, at first 4 bytes of file, for newer files.
971 uiState
= STATE_START_DWNLD
;
973 pFileHdr
= (PDSP_FILE_HDR
)pFileStart
;
974 pFileHdr5
= (PDSP_FILE_HDR_5
)pFileStart
;
976 ft1000_write_register (ft1000dev
, 0x800, FT1000_REG_MAG_WATERMARK
);
978 pUsFile
= (USHORT
*)(pFileStart
+ pFileHdr5
->loader_offset
);
979 pUcFile
= (UCHAR
*)(pFileStart
+ pFileHdr5
->loader_offset
);
981 pBootEnd
= (UCHAR
*)(pFileStart
+ pFileHdr5
->loader_code_end
);
983 loader_code_address
= pFileHdr5
->loader_code_address
;
984 loader_code_size
= pFileHdr5
->loader_code_size
;
985 bGoodVersion
= FALSE
;
987 while ((Status
== STATUS_SUCCESS
) && (uiState
!= STATE_DONE_FILE
))
991 case STATE_START_DWNLD
:
992 DEBUG("FT1000:STATE_START_DWNLD\n");
993 if (pft1000info
->usbboot
)
994 handshake
= get_handshake_usb(ft1000dev
, HANDSHAKE_DSP_BL_READY
);
996 handshake
= get_handshake(ft1000dev
, HANDSHAKE_DSP_BL_READY
);
998 if (handshake
== HANDSHAKE_DSP_BL_READY
)
1000 DEBUG("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
1001 put_handshake(ft1000dev
, HANDSHAKE_DRIVER_READY
);
1005 DEBUG("FT1000:download:Download error: Handshake failed\n");
1006 Status
= STATUS_FAILURE
;
1009 uiState
= STATE_BOOT_DWNLD
;
1013 case STATE_BOOT_DWNLD
:
1014 DEBUG("FT1000:STATE_BOOT_DWNLD\n");
1015 pft1000info
->bootmode
= 1;
1016 handshake
= get_handshake(ft1000dev
, HANDSHAKE_REQUEST
);
1017 if (handshake
== HANDSHAKE_REQUEST
)
1020 * Get type associated with the request.
1022 request
= get_request_type(ft1000dev
);
1025 case REQUEST_RUN_ADDRESS
:
1026 DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
1027 put_request_value(ft1000dev
, loader_code_address
);
1029 case REQUEST_CODE_LENGTH
:
1030 DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
1031 put_request_value(ft1000dev
, loader_code_size
);
1033 case REQUEST_DONE_BL
:
1034 DEBUG("FT1000:REQUEST_DONE_BL\n");
1035 /* Reposition ptrs to beginning of code section */
1036 pUsFile
= (USHORT
*)(pBootEnd
);
1037 pUcFile
= (UCHAR
*)(pBootEnd
);
1038 //DEBUG("FT1000:download:pUsFile = 0x%8x\n", (int)pUsFile);
1039 //DEBUG("FT1000:download:pUcFile = 0x%8x\n", (int)pUcFile);
1040 uiState
= STATE_CODE_DWNLD
;
1041 pft1000info
->fcodeldr
= 1;
1043 case REQUEST_CODE_SEGMENT
:
1044 //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");
1045 word_length
= get_request_value(ft1000dev
);
1046 //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length);
1048 if (word_length
> MAX_LENGTH
)
1050 DEBUG("FT1000:download:Download error: Max length exceeded\n");
1051 Status
= STATUS_FAILURE
;
1054 if ( (word_length
*2 + pUcFile
) > pBootEnd
)
1057 * Error, beyond boot code range.
1059 DEBUG("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundry.\n",
1061 Status
= STATUS_FAILURE
;
1065 * Position ASIC DPRAM auto-increment pointer.
1067 dpram
= (USHORT
)DWNLD_MAG1_PS_HDR_LOC
;
1068 if (word_length
& 0x1)
1070 word_length
= word_length
/ 2;
1072 Status
= write_blk(ft1000dev
, &pUsFile
, &pUcFile
, word_length
);
1073 //DEBUG("write_blk returned %d\n", Status);
1076 DEBUG("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",request
);
1077 Status
= STATUS_FAILURE
;
1080 if (pft1000info
->usbboot
)
1081 put_handshake_usb(ft1000dev
, HANDSHAKE_RESPONSE
);
1083 put_handshake(ft1000dev
, HANDSHAKE_RESPONSE
);
1087 DEBUG("FT1000:download:Download error: Handshake failed\n");
1088 Status
= STATUS_FAILURE
;
1093 case STATE_CODE_DWNLD
:
1094 //DEBUG("FT1000:STATE_CODE_DWNLD\n");
1095 pft1000info
->bootmode
= 0;
1096 if (pft1000info
->usbboot
)
1097 handshake
= get_handshake_usb(ft1000dev
, HANDSHAKE_REQUEST
);
1099 handshake
= get_handshake(ft1000dev
, HANDSHAKE_REQUEST
);
1100 if (handshake
== HANDSHAKE_REQUEST
)
1103 * Get type associated with the request.
1105 if (pft1000info
->usbboot
)
1106 request
= get_request_type_usb(ft1000dev
);
1108 request
= get_request_type(ft1000dev
);
1111 case REQUEST_FILE_CHECKSUM
:
1112 DEBUG("FT1000:download:image_chksum = 0x%8x\n", image_chksum
);
1113 put_request_value(ft1000dev
, image_chksum
);
1115 case REQUEST_RUN_ADDRESS
:
1116 DEBUG("FT1000:download: REQUEST_RUN_ADDRESS\n");
1119 DEBUG("FT1000:download:run_address = 0x%8x\n", (int)run_address
);
1120 put_request_value(ft1000dev
, run_address
);
1124 DEBUG("FT1000:download:Download error: Got Run address request before image offset request.\n");
1125 Status
= STATUS_FAILURE
;
1129 case REQUEST_CODE_LENGTH
:
1130 DEBUG("FT1000:download:REQUEST_CODE_LENGTH\n");
1133 DEBUG("FT1000:download:run_size = 0x%8x\n", (int)run_size
);
1134 put_request_value(ft1000dev
, run_size
);
1138 DEBUG("FT1000:download:Download error: Got Size request before image offset request.\n");
1139 Status
= STATUS_FAILURE
;
1143 case REQUEST_DONE_CL
:
1145 pft1000info
->usbboot
= 3;
1147 /* Reposition ptrs to beginning of provisioning section */
1148 pUsFile
= (USHORT
*)(pFileStart
+ pFileHdr5
->commands_offset
);
1149 pUcFile
= (UCHAR
*)(pFileStart
+ pFileHdr5
->commands_offset
);
1150 uiState
= STATE_DONE_DWNLD
;
1152 case REQUEST_CODE_SEGMENT
:
1153 //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n");
1156 DEBUG("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
1157 Status
= STATUS_FAILURE
;
1161 word_length
= get_request_value_usb(ft1000dev
);
1162 //DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
1163 if (word_length
> MAX_LENGTH
/2)
1165 word_length
= get_request_value(ft1000dev
);
1166 //DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
1167 if (word_length
> MAX_LENGTH
)
1170 DEBUG("FT1000:download:Download error: Max length exceeded\n");
1171 Status
= STATUS_FAILURE
;
1174 if ( (word_length
*2 + pUcFile
) > pCodeEnd
)
1177 * Error, beyond boot code range.
1179 DEBUG("FT1000:download:Download error: Requested len=%d exceeds DSP code boundry.\n",
1181 Status
= STATUS_FAILURE
;
1185 * Position ASIC DPRAM auto-increment pointer.
1187 dpram
= (USHORT
)DWNLD_MAG1_PS_HDR_LOC
;
1188 if (word_length
& 0x1)
1190 word_length
= word_length
/ 2;
1193 write_blk_fifo (ft1000dev
, &pUsFile
, &pUcFile
, word_length
);
1194 if (pft1000info
->usbboot
== 0)
1195 pft1000info
->usbboot
++;
1196 if (pft1000info
->usbboot
== 1) {
1198 ft1000_write_dpram16 (ft1000dev
, DWNLD_MAG1_PS_HDR_LOC
, tempword
, 0);
1201 write_blk (ft1000dev
, &pUsFile
, &pUcFile
, word_length
);
1202 //ft1000_write_dpram32 (ft1000dev, dpram, (PUCHAR)pUcFile, word_length);
1206 case REQUEST_MAILBOX_DATA
:
1207 DEBUG("FT1000:download: REQUEST_MAILBOX_DATA\n");
1208 // Convert length from byte count to word count. Make sure we round up.
1209 word_length
= (long)(pft1000info
->DSPInfoBlklen
+ 1)/2;
1210 put_request_value(ft1000dev
, word_length
);
1211 pMailBoxData
= (PDRVMSG
)&(pft1000info
->DSPInfoBlk
[0]);
1213 * Position ASIC DPRAM auto-increment pointer.
1217 pUsData
= (USHORT
*)&pMailBoxData
->data
[0];
1218 dpram
= (USHORT
)DWNLD_MAG1_PS_HDR_LOC
;
1219 if (word_length
& 0x1)
1222 word_length
= (word_length
/ 2);
1225 for (; word_length
> 0; word_length
--) /* In words */
1228 templong
= *pUsData
++;
1229 templong
|= (*pUsData
++ << 16);
1230 Status
= fix_ft1000_write_dpram32 (ft1000dev
, dpram
++, (PUCHAR
)&templong
);
1235 case REQUEST_VERSION_INFO
:
1236 DEBUG("FT1000:download:REQUEST_VERSION_INFO\n");
1237 word_length
= pFileHdr5
->version_data_size
;
1238 put_request_value(ft1000dev
, word_length
);
1240 * Position ASIC DPRAM auto-increment pointer.
1243 pUsFile
= (USHORT
*)(pFileStart
+ pFileHdr5
->version_data_offset
);
1246 dpram
= (USHORT
)DWNLD_MAG1_PS_HDR_LOC
;
1247 if (word_length
& 0x1)
1250 word_length
= (word_length
/ 2);
1253 for (; word_length
> 0; word_length
--) /* In words */
1256 templong
= ntohs(*pUsFile
++);
1257 temp
= ntohs(*pUsFile
++);
1258 templong
|= (temp
<< 16);
1259 Status
= fix_ft1000_write_dpram32 (ft1000dev
, dpram
++, (PUCHAR
)&templong
);
1264 case REQUEST_CODE_BY_VERSION
:
1265 DEBUG("FT1000:download:REQUEST_CODE_BY_VERSION\n");
1266 bGoodVersion
= FALSE
;
1267 requested_version
= get_request_value(ft1000dev
);
1269 pDspImageInfoV6
= (PDSP_IMAGE_INFO_V6
)(pFileStart
+ sizeof(DSP_FILE_HDR_5
));
1271 for (imageN
= 0; imageN
< pFileHdr5
->nDspImages
; imageN
++)
1274 temp
= (USHORT
)(pDspImageInfoV6
->version
);
1276 temp
= (USHORT
)(pDspImageInfoV6
->version
>> 16);
1277 templong
|= (temp
<< 16);
1278 if (templong
== (ULONG
)requested_version
)
1280 bGoodVersion
= TRUE
;
1281 DEBUG("FT1000:download: bGoodVersion is TRUE\n");
1282 pUsFile
= (USHORT
*)(pFileStart
+ pDspImageInfoV6
->begin_offset
);
1283 pUcFile
= (UCHAR
*)(pFileStart
+ pDspImageInfoV6
->begin_offset
);
1284 pCodeEnd
= (UCHAR
*)(pFileStart
+ pDspImageInfoV6
->end_offset
);
1285 run_address
= pDspImageInfoV6
->run_address
;
1286 run_size
= pDspImageInfoV6
->image_size
;
1287 image_chksum
= (ULONG
)pDspImageInfoV6
->checksum
;
1298 * Error, beyond boot code range.
1300 DEBUG("FT1000:download:Download error: Bad Version Request = 0x%x.\n",(int)requested_version
);
1301 Status
= STATUS_FAILURE
;
1307 DEBUG("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",request
);
1308 Status
= STATUS_FAILURE
;
1311 if (pft1000info
->usbboot
)
1312 put_handshake_usb(ft1000dev
, HANDSHAKE_RESPONSE
);
1314 put_handshake(ft1000dev
, HANDSHAKE_RESPONSE
);
1318 DEBUG("FT1000:download:Download error: Handshake failed\n");
1319 Status
= STATUS_FAILURE
;
1324 case STATE_DONE_DWNLD
:
1325 DEBUG("FT1000:download:Code loader is done...\n");
1326 uiState
= STATE_SECTION_PROV
;
1329 case STATE_SECTION_PROV
:
1330 DEBUG("FT1000:download:STATE_SECTION_PROV\n");
1331 pHdr
= (PPSEUDO_HDR
)pUcFile
;
1333 if (pHdr
->checksum
== hdr_checksum(pHdr
))
1335 if (pHdr
->portdest
!= 0x80 /* Dsp OAM */)
1337 uiState
= STATE_DONE_PROV
;
1340 usHdrLength
= ntohs(pHdr
->length
); /* Byte length for PROV records */
1342 // Get buffer for provisioning data
1343 pbuffer
= kmalloc ( (usHdrLength
+ sizeof(PSEUDO_HDR
) ), GFP_ATOMIC
);
1345 memcpy(pbuffer
, (void *)pUcFile
, (UINT
)(usHdrLength
+ sizeof(PSEUDO_HDR
)));
1346 // link provisioning data
1347 pprov_record
= kmalloc( sizeof(PROV_RECORD
), GFP_ATOMIC
);
1349 pprov_record
->pprov_data
= pbuffer
;
1350 list_add_tail (&pprov_record
->list
, &pft1000info
->prov_list
);
1351 // Move to next entry if available
1352 pUcFile
= (UCHAR
*)((unsigned long)pUcFile
+ (UINT
)((usHdrLength
+ 1) & 0xFFFFFFFE) + sizeof(PSEUDO_HDR
));
1353 if ( (unsigned long)(pUcFile
) - (unsigned long)(pFileStart
) >= (unsigned long)FileLength
) {
1354 uiState
= STATE_DONE_FILE
;
1359 Status
= STATUS_FAILURE
;
1363 Status
= STATUS_FAILURE
;
1368 /* Checksum did not compute */
1369 Status
= STATUS_FAILURE
;
1371 DEBUG("ft1000:download: after STATE_SECTION_PROV, uiState = %d, Status= %d\n", uiState
, Status
);
1374 case STATE_DONE_PROV
:
1375 DEBUG("FT1000:download:STATE_DONE_PROV\n");
1376 uiState
= STATE_DONE_FILE
;
1381 Status
= STATUS_FAILURE
;
1385 if (Status
!= STATUS_SUCCESS
) {
1390 // Check if Card is present
1391 Status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK);
1392 if ( (Status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) {
1396 Status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID);
1397 if ( (Status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) {
1404 DEBUG("Download exiting with status = 0x%8x\n", Status
);
1405 ft1000_write_register(ft1000dev
, FT1000_DB_DNLD_TX
, FT1000_REG_DOORBELL
);