]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/ft1000/ft1000-usb/ft1000_download.c
staging: ft1000: Remove unused variables.
[mirror_ubuntu-artful-kernel.git] / drivers / staging / ft1000 / ft1000-usb / ft1000_download.c
CommitLineData
f7c1be0c
MB
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
f7c1be0c
MB
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
bf3146c8 49#define REQUEST_MAILBOX_DATA 0x0007
f7c1be0c
MB
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
bf3146c8 74#define HANDSHAKE_MAG_DRV_READY 0xFFFF0000 /* Driver writes this to indicate ready to download */
f7c1be0c
MB
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
13da8f0d 87struct dsp_file_hdr {
f7c1be0c
MB
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.
13da8f0d 99};
f7c1be0c 100
13da8f0d
MB
101#pragma pack(1)
102struct dsp_image_info {
f7c1be0c
MB
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;
13da8f0d
MB
111};
112
f7c1be0c 113
f7c1be0c
MB
114//---------------------------------------------------------------------------
115// Function: check_usb_db
116//
117// Parameters: struct ft1000_device - device structure
bf3146c8 118//
f7c1be0c
MB
119// Returns: 0 - success
120//
121// Description: This function checks if the doorbell register is cleared
122//
123// Notes:
124//
125//---------------------------------------------------------------------------
84b7801d 126static u32 check_usb_db (struct ft1000_device *ft1000dev)
f7c1be0c 127{
c5d680c0
MB
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;
f7c1be0c
MB
170}
171
172//---------------------------------------------------------------------------
173// Function: get_handshake
174//
175// Parameters: struct ft1000_device - device structure
fc549a05 176// u16 expected_value - the handshake value expected
bf3146c8 177//
f7c1be0c
MB
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//---------------------------------------------------------------------------
fc549a05 186static u16 get_handshake(struct ft1000_device *ft1000dev, u16 expected_value)
f7c1be0c 187{
d7a7318b
MB
188 u16 handshake;
189 int loopcnt;
190 u32 status = 0;
1a88a068 191 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
f7c1be0c 192
d7a7318b
MB
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;
f7c1be0c
MB
231}
232
233//---------------------------------------------------------------------------
234// Function: put_handshake
235//
236// Parameters: struct ft1000_device - device structure
fc549a05 237// u16 handshake_value - handshake to be written
bf3146c8 238//
f7c1be0c
MB
239// Returns: none
240//
241// Description: This function write the handshake value to the handshake location
242// in DPRAM
243//
244// Notes:
245//
246//---------------------------------------------------------------------------
fc549a05 247static void put_handshake(struct ft1000_device *ft1000dev,u16 handshake_value)
f7c1be0c 248{
a8d4d198
MB
249 u32 tempx;
250 u16 tempword;
251 u32 status;
f7c1be0c 252
a8d4d198
MB
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);
f7c1be0c
MB
264}
265
fc549a05 266static u16 get_handshake_usb(struct ft1000_device *ft1000dev, u16 expected_value)
f7c1be0c 267{
5865a18e
MB
268 u16 handshake;
269 int loopcnt;
270 u16 temp;
271 u32 status = 0;
f7c1be0c 272
1a88a068 273 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
5865a18e
MB
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 }
f7c1be0c 302
5865a18e
MB
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;
f7c1be0c
MB
312}
313
fc549a05 314static void put_handshake_usb(struct ft1000_device *ft1000dev,u16 handshake_value)
f7c1be0c 315{
5acc5396 316 int i;
f7c1be0c
MB
317
318 for (i=0; i<1000; i++);
319}
320
321//---------------------------------------------------------------------------
322// Function: get_request_type
323//
324// Parameters: struct ft1000_device - device structure
bf3146c8 325//
f7c1be0c
MB
326// Returns: request type - success
327//
328// Description: This function returns the request type
329//
330// Notes:
331//
332//---------------------------------------------------------------------------
fc549a05 333static u16 get_request_type(struct ft1000_device *ft1000dev)
f7c1be0c 334{
9b43f374
MB
335 u16 request_type;
336 u32 status;
337 u16 tempword;
338 u32 tempx;
1a88a068 339 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
f7c1be0c 340
9b43f374
MB
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;
f7c1be0c 353
9b43f374 354 return request_type;
f7c1be0c
MB
355}
356
fc549a05 357static u16 get_request_type_usb(struct ft1000_device *ft1000dev)
f7c1be0c 358{
c3ed5d2f
MB
359 u16 request_type;
360 u32 status;
361 u16 tempword;
362 u32 tempx;
1a88a068 363 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
f7c1be0c 364
c3ed5d2f
MB
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;
f7c1be0c 383
c3ed5d2f 384 return request_type;
f7c1be0c
MB
385}
386
387//---------------------------------------------------------------------------
388// Function: get_request_value
389//
390// Parameters: struct ft1000_device - device structure
bf3146c8 391//
f7c1be0c
MB
392// Returns: request value - success
393//
394// Description: This function returns the request value
395//
396// Notes:
397//
398//---------------------------------------------------------------------------
2a953cfd 399static long get_request_value(struct ft1000_device *ft1000dev)
f7c1be0c 400{
114a06ae
MB
401 u32 value;
402 u16 tempword;
403 u32 status;
1a88a068 404 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
f7c1be0c 405
114a06ae
MB
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 }
f7c1be0c 419
114a06ae 420 return value;
f7c1be0c
MB
421}
422
f7c1be0c
MB
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
bf3146c8 429//
f7c1be0c
MB
430// Returns: none
431//
432// Description: This function writes a value to DWNLD_MAG1_SIZE_LOC
433//
434// Notes:
435//
436//---------------------------------------------------------------------------
2a953cfd 437static void put_request_value(struct ft1000_device *ft1000dev, long lvalue)
f7c1be0c 438{
cc4f65bf
MB
439 u32 tempx;
440 u32 status;
f7c1be0c 441
cc4f65bf
MB
442 tempx = ntohl(lvalue);
443 status = fix_ft1000_write_dpram32(ft1000dev, DWNLD_MAG1_SIZE_LOC,
444 (u8 *)&tempx);
f7c1be0c
MB
445}
446
447
448
449//---------------------------------------------------------------------------
450// Function: hdr_checksum
451//
b13e39b2 452// Parameters: struct pseudo_hdr *pHdr - Pseudo header pointer
bf3146c8 453//
f7c1be0c
MB
454// Returns: checksum - success
455//
456// Description: This function returns the checksum of the pseudo header
457//
458// Notes:
459//
460//---------------------------------------------------------------------------
fc549a05 461static u16 hdr_checksum(struct pseudo_hdr *pHdr)
f7c1be0c 462{
78395f67
MB
463 u16 *usPtr = (u16 *)pHdr;
464 u16 chksum;
f7c1be0c 465
bf3146c8 466
78395f67
MB
467 chksum = ((((((usPtr[0] ^ usPtr[1]) ^ usPtr[2]) ^ usPtr[3]) ^
468 usPtr[4]) ^ usPtr[5]) ^ usPtr[6]);
f7c1be0c 469
78395f67 470 return chksum;
f7c1be0c
MB
471}
472
473
474//---------------------------------------------------------------------------
475// Function: write_blk
476//
477// Parameters: struct ft1000_device - device structure
fc549a05 478// u16 **pUsFile - DSP image file pointer in u16
c8f775c8 479// u8 **pUcFile - DSP image file pointer in u8
f7c1be0c
MB
480// long word_length - lenght of the buffer to be written
481// to DPRAM
bf3146c8 482//
f7c1be0c
MB
483// Returns: STATUS_SUCCESS - success
484// STATUS_FAILURE - failure
485//
486// Description: This function writes a block of DSP image to DPRAM
487//
488// Notes:
489//
490//---------------------------------------------------------------------------
84b7801d 491static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length)
f7c1be0c 492{
84b7801d 493 u32 Status = STATUS_SUCCESS;
fc549a05 494 u16 dpram;
f7c1be0c 495 int loopcnt, i, j;
fc549a05
MB
496 u16 tempword;
497 u16 tempbuffer[64];
498 u16 resultbuffer[64];
1a88a068 499 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
f7c1be0c
MB
500
501 //DEBUG("FT1000:download:start word_length = %d\n",(int)word_length);
fc549a05 502 dpram = (u16)DWNLD_MAG1_PS_HDR_LOC;
f7c1be0c
MB
503 tempword = *(*pUsFile);
504 (*pUsFile)++;
505 Status = ft1000_write_dpram16(ft1000dev, dpram, tempword, 0);
506 tempword = *(*pUsFile);
507 (*pUsFile)++;
508 Status = ft1000_write_dpram16(ft1000dev, dpram++, tempword, 1);
509
510 *pUcFile = *pUcFile + 4;
511 word_length--;
fc549a05 512 tempword = (u16)word_length;
f7c1be0c 513 word_length = (word_length / 16) + 1;
f7c1be0c
MB
514 for (; word_length > 0; word_length--) /* In words */
515 {
516 loopcnt = 0;
517
bf3146c8 518 for (i=0; i<32; i++)
f7c1be0c 519 {
bf3146c8 520 if (tempword != 0)
f7c1be0c
MB
521 {
522 tempbuffer[i++] = *(*pUsFile);
523 (*pUsFile)++;
524 tempbuffer[i] = *(*pUsFile);
525 (*pUsFile)++;
526 *pUcFile = *pUcFile + 4;
527 loopcnt++;
528 tempword--;
529 }
bf3146c8 530 else
f7c1be0c
MB
531 {
532 tempbuffer[i++] = 0;
533 tempbuffer[i] = 0;
534 }
535 }
bf3146c8 536
f7c1be0c
MB
537 //DEBUG("write_blk: loopcnt is %d\n", loopcnt);
538 //DEBUG("write_blk: bootmode = %d\n", bootmode);
539 //DEBUG("write_blk: dpram = %x\n", dpram);
bf3146c8
GKH
540 if (pft1000info->bootmode == 0)
541 {
542 if (dpram >= 0x3F4)
e2cb7da1 543 Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 8);
bf3146c8 544 else
e2cb7da1 545 Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64);
f7c1be0c 546 }
bf3146c8 547 else
f7c1be0c 548 {
bf3146c8 549 for (j=0; j<10; j++)
f7c1be0c 550 {
e2cb7da1 551 Status = ft1000_write_dpram32 (ft1000dev, dpram, (u8 *)&tempbuffer[0], 64);
bf3146c8 552 if (Status == STATUS_SUCCESS)
f7c1be0c
MB
553 {
554 // Work around for ASIC bit stuffing problem.
bf3146c8 555 if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
f7c1be0c 556 {
e2cb7da1 557 Status = ft1000_write_dpram32(ft1000dev, dpram+12, (u8 *)&tempbuffer[24], 64);
f7c1be0c
MB
558 }
559 // Let's check the data written
e2cb7da1 560 Status = ft1000_read_dpram32 (ft1000dev, dpram, (u8 *)&resultbuffer[0], 64);
bf3146c8 561 if ( (tempbuffer[31] & 0xfe00) == 0xfe00)
f7c1be0c 562 {
bf3146c8 563 for (i=0; i<28; i++)
f7c1be0c 564 {
bf3146c8 565 if (resultbuffer[i] != tempbuffer[i])
f7c1be0c
MB
566 {
567 //NdisMSleep (100);
568 DEBUG("FT1000:download:DPRAM write failed 1 during bootloading\n");
569 msleep(10);
570 Status = STATUS_FAILURE;
571 break;
572 }
573 }
e2cb7da1 574 Status = ft1000_read_dpram32 (ft1000dev, dpram+12, (u8 *)&resultbuffer[0], 64);
bf3146c8 575 for (i=0; i<16; i++)
f7c1be0c
MB
576 {
577 if (resultbuffer[i] != tempbuffer[i+24])
578 {
579 //NdisMSleep (100);
580 DEBUG("FT1000:download:DPRAM write failed 2 during bootloading\n");
581 msleep(10);
582 Status = STATUS_FAILURE;
583 break;
584 }
585 }
586 }
bf3146c8 587 else
f7c1be0c 588 {
bf3146c8 589 for (i=0; i<32; i++)
f7c1be0c 590 {
bf3146c8 591 if (resultbuffer[i] != tempbuffer[i])
f7c1be0c
MB
592 {
593 //NdisMSleep (100);
594 DEBUG("FT1000:download:DPRAM write failed 3 during bootloading\n");
595 msleep(10);
596 Status = STATUS_FAILURE;
597 break;
598 }
599 }
600 }
601
bf3146c8 602 if (Status == STATUS_SUCCESS)
f7c1be0c 603 break;
bf3146c8 604
f7c1be0c
MB
605 }
606 }
bf3146c8
GKH
607
608 if (Status != STATUS_SUCCESS)
f7c1be0c
MB
609 {
610 DEBUG("FT1000:download:Write failed tempbuffer[31] = 0x%x\n", tempbuffer[31]);
611 break;
612 }
613
614 }
615 dpram = dpram + loopcnt;
616 }
bf3146c8 617
f7c1be0c
MB
618 return Status;
619}
620
621static void usb_dnld_complete (struct urb *urb)
622{
623 //DEBUG("****** usb_dnld_complete\n");
624}
625
626//---------------------------------------------------------------------------
627// Function: write_blk_fifo
628//
629// Parameters: struct ft1000_device - device structure
fc549a05 630// u16 **pUsFile - DSP image file pointer in u16
c8f775c8 631// u8 **pUcFile - DSP image file pointer in u8
f7c1be0c
MB
632// long word_length - lenght of the buffer to be written
633// to DPRAM
bf3146c8 634//
f7c1be0c
MB
635// Returns: STATUS_SUCCESS - success
636// STATUS_FAILURE - failure
637//
638// Description: This function writes a block of DSP image to DPRAM
639//
640// Notes:
641//
642//---------------------------------------------------------------------------
857af455
MB
643static u32 write_blk_fifo(struct ft1000_device *ft1000dev, u16 **pUsFile,
644 u8 **pUcFile, long word_length)
f7c1be0c 645{
857af455
MB
646 u32 Status = STATUS_SUCCESS;
647 int byte_length;
648 long aligncnt;
f7c1be0c 649
857af455 650 byte_length = word_length * 4;
f7c1be0c 651
857af455
MB
652 if (byte_length % 4)
653 aligncnt = 4 - (byte_length % 4);
654 else
655 aligncnt = 0;
656 byte_length += aligncnt;
f7c1be0c 657
857af455
MB
658 if (byte_length && ((byte_length % 64) == 0))
659 byte_length += 4;
f7c1be0c 660
857af455
MB
661 if (byte_length < 64)
662 byte_length = 68;
f7c1be0c 663
857af455
MB
664 usb_init_urb(ft1000dev->tx_urb);
665 memcpy(ft1000dev->tx_buf, *pUcFile, byte_length);
666 usb_fill_bulk_urb(ft1000dev->tx_urb,
667 ft1000dev->dev,
668 usb_sndbulkpipe(ft1000dev->dev,
669 ft1000dev->bulk_out_endpointAddr),
670 ft1000dev->tx_buf, byte_length, usb_dnld_complete,
671 (void *)ft1000dev);
bf3146c8 672
857af455 673 usb_submit_urb(ft1000dev->tx_urb, GFP_ATOMIC);
f7c1be0c 674
857af455
MB
675 *pUsFile = *pUsFile + (word_length << 1);
676 *pUcFile = *pUcFile + (word_length << 2);
f7c1be0c 677
857af455 678 return Status;
f7c1be0c
MB
679}
680
681//---------------------------------------------------------------------------
682//
683// Function: scram_dnldr
684//
685// Synopsis: Scramble downloader for Harley based ASIC via USB interface
686//
687// Arguments: pFileStart - pointer to start of file
688// FileLength - file length
689//
690// Returns: status - return code
691//---------------------------------------------------------------------------
692
6f953fbb
MB
693u16 scram_dnldr(struct ft1000_device *ft1000dev, void *pFileStart,
694 u32 FileLength)
f7c1be0c 695{
6f953fbb
MB
696 u16 status = STATUS_SUCCESS;
697 u32 state;
698 u16 handshake;
0ce72ea3 699 struct pseudo_hdr *pseudo_header;
6f953fbb
MB
700 u16 pseudo_header_len;
701 long word_length;
702 u16 request;
703 u16 temp;
704 u16 tempword;
f7c1be0c 705
0ce72ea3
MB
706 struct dsp_file_hdr *file_hdr;
707 struct dsp_image_info *dsp_img_info = NULL;
6f953fbb
MB
708 long requested_version;
709 bool correct_version;
0ce72ea3 710 struct drv_msg *mailbox_data;
6f953fbb
MB
711 u16 *data = NULL;
712 u16 *s_file = NULL;
713 u8 *c_file = NULL;
714 u8 *boot_end = NULL, *code_end = NULL;
715 int image;
716 long loader_code_address, loader_code_size = 0;
717 long run_address = 0, run_size = 0;
718
719 u32 templong;
720 u32 image_chksum = 0;
721
722 u16 dpram = 0;
723 u8 *pbuffer;
e27d96dd 724 struct prov_record *pprov_record;
1a88a068 725 struct ft1000_info *pft1000info = netdev_priv(ft1000dev->net);
bf3146c8 726
6f953fbb
MB
727 DEBUG("Entered scram_dnldr...\n");
728
729 pft1000info->fcodeldr = 0;
730 pft1000info->usbboot = 0;
731 pft1000info->dspalive = 0xffff;
f7c1be0c 732
6f953fbb
MB
733 //
734 // Get version id of file, at first 4 bytes of file, for newer files.
735 //
f7c1be0c 736
6f953fbb 737 state = STATE_START_DWNLD;
f7c1be0c 738
6f953fbb 739 file_hdr = (struct dsp_file_hdr *)pFileStart;
f7c1be0c 740
6f953fbb 741 ft1000_write_register(ft1000dev, 0x800, FT1000_REG_MAG_WATERMARK);
f7c1be0c 742
6f953fbb
MB
743 s_file = (u16 *) (pFileStart + file_hdr->loader_offset);
744 c_file = (u8 *) (pFileStart + file_hdr->loader_offset);
f7c1be0c 745
6f953fbb 746 boot_end = (u8 *) (pFileStart + file_hdr->loader_code_end);
f7c1be0c 747
6f953fbb
MB
748 loader_code_address = file_hdr->loader_code_address;
749 loader_code_size = file_hdr->loader_code_size;
750 correct_version = FALSE;
751
752 while ((status == STATUS_SUCCESS) && (state != STATE_DONE_FILE)) {
753 switch (state) {
754 case STATE_START_DWNLD:
755 DEBUG("FT1000:STATE_START_DWNLD\n");
756 if (pft1000info->usbboot)
757 handshake =
758 get_handshake_usb(ft1000dev,
759 HANDSHAKE_DSP_BL_READY);
760 else
761 handshake =
762 get_handshake(ft1000dev,
763 HANDSHAKE_DSP_BL_READY);
764
765 if (handshake == HANDSHAKE_DSP_BL_READY) {
766 DEBUG
767 ("scram_dnldr: handshake is HANDSHAKE_DSP_BL_READY, call put_handshake(HANDSHAKE_DRIVER_READY)\n");
768 put_handshake(ft1000dev,
769 HANDSHAKE_DRIVER_READY);
770 } else {
771 DEBUG
772 ("FT1000:download:Download error: Handshake failed\n");
773 status = STATUS_FAILURE;
774 }
f7c1be0c 775
6f953fbb 776 state = STATE_BOOT_DWNLD;
f7c1be0c 777
6f953fbb 778 break;
f7c1be0c 779
6f953fbb
MB
780 case STATE_BOOT_DWNLD:
781 DEBUG("FT1000:STATE_BOOT_DWNLD\n");
782 pft1000info->bootmode = 1;
783 handshake = get_handshake(ft1000dev, HANDSHAKE_REQUEST);
784 if (handshake == HANDSHAKE_REQUEST) {
785 /*
786 * Get type associated with the request.
787 */
788 request = get_request_type(ft1000dev);
789 switch (request) {
790 case REQUEST_RUN_ADDRESS:
791 DEBUG("FT1000:REQUEST_RUN_ADDRESS\n");
792 put_request_value(ft1000dev,
793 loader_code_address);
794 break;
795 case REQUEST_CODE_LENGTH:
796 DEBUG("FT1000:REQUEST_CODE_LENGTH\n");
797 put_request_value(ft1000dev,
798 loader_code_size);
799 break;
800 case REQUEST_DONE_BL:
801 DEBUG("FT1000:REQUEST_DONE_BL\n");
802 /* Reposition ptrs to beginning of code section */
803 s_file = (u16 *) (boot_end);
804 c_file = (u8 *) (boot_end);
805 //DEBUG("FT1000:download:s_file = 0x%8x\n", (int)s_file);
806 //DEBUG("FT1000:download:c_file = 0x%8x\n", (int)c_file);
807 state = STATE_CODE_DWNLD;
808 pft1000info->fcodeldr = 1;
809 break;
810 case REQUEST_CODE_SEGMENT:
811 //DEBUG("FT1000:REQUEST_CODE_SEGMENT\n");
812 word_length =
813 get_request_value(ft1000dev);
814 //DEBUG("FT1000:word_length = 0x%x\n", (int)word_length);
815 //NdisMSleep (100);
816 if (word_length > MAX_LENGTH) {
817 DEBUG
818 ("FT1000:download:Download error: Max length exceeded\n");
819 status = STATUS_FAILURE;
820 break;
821 }
822 if ((word_length * 2 + c_file) >
823 boot_end) {
824 /*
825 * Error, beyond boot code range.
826 */
827 DEBUG
828 ("FT1000:download:Download error: Requested len=%d exceeds BOOT code boundry.\n",
829 (int)word_length);
830 status = STATUS_FAILURE;
831 break;
832 }
833 /*
834 * Position ASIC DPRAM auto-increment pointer.
835 */
836 dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
f7c1be0c
MB
837 if (word_length & 0x1)
838 word_length++;
839 word_length = word_length / 2;
840
6f953fbb
MB
841 status =
842 write_blk(ft1000dev, &s_file,
843 &c_file, word_length);
844 //DEBUG("write_blk returned %d\n", status);
845 break;
846 default:
847 DEBUG
848 ("FT1000:download:Download error: Bad request type=%d in BOOT download state.\n",
849 request);
850 status = STATUS_FAILURE;
851 break;
852 }
853 if (pft1000info->usbboot)
854 put_handshake_usb(ft1000dev,
855 HANDSHAKE_RESPONSE);
856 else
857 put_handshake(ft1000dev,
858 HANDSHAKE_RESPONSE);
859 } else {
860 DEBUG
861 ("FT1000:download:Download error: Handshake failed\n");
862 status = STATUS_FAILURE;
863 }
864
865 break;
866
867 case STATE_CODE_DWNLD:
868 //DEBUG("FT1000:STATE_CODE_DWNLD\n");
869 pft1000info->bootmode = 0;
870 if (pft1000info->usbboot)
871 handshake =
872 get_handshake_usb(ft1000dev,
873 HANDSHAKE_REQUEST);
874 else
875 handshake =
876 get_handshake(ft1000dev, HANDSHAKE_REQUEST);
877 if (handshake == HANDSHAKE_REQUEST) {
878 /*
879 * Get type associated with the request.
880 */
881 if (pft1000info->usbboot)
882 request =
883 get_request_type_usb(ft1000dev);
884 else
885 request = get_request_type(ft1000dev);
886 switch (request) {
887 case REQUEST_FILE_CHECKSUM:
888 DEBUG
889 ("FT1000:download:image_chksum = 0x%8x\n",
890 image_chksum);
891 put_request_value(ft1000dev,
892 image_chksum);
893 break;
894 case REQUEST_RUN_ADDRESS:
895 DEBUG
896 ("FT1000:download: REQUEST_RUN_ADDRESS\n");
897 if (correct_version) {
898 DEBUG
899 ("FT1000:download:run_address = 0x%8x\n",
900 (int)run_address);
901 put_request_value(ft1000dev,
902 run_address);
903 } else {
904 DEBUG
905 ("FT1000:download:Download error: Got Run address request before image offset request.\n");
906 status = STATUS_FAILURE;
907 break;
908 }
909 break;
910 case REQUEST_CODE_LENGTH:
911 DEBUG
912 ("FT1000:download:REQUEST_CODE_LENGTH\n");
913 if (correct_version) {
914 DEBUG
915 ("FT1000:download:run_size = 0x%8x\n",
916 (int)run_size);
917 put_request_value(ft1000dev,
918 run_size);
919 } else {
920 DEBUG
921 ("FT1000:download:Download error: Got Size request before image offset request.\n");
922 status = STATUS_FAILURE;
923 break;
924 }
925 break;
926 case REQUEST_DONE_CL:
927 pft1000info->usbboot = 3;
928 /* Reposition ptrs to beginning of provisioning section */
929 s_file =
930 (u16 *) (pFileStart +
931 file_hdr->commands_offset);
932 c_file =
933 (u8 *) (pFileStart +
934 file_hdr->commands_offset);
935 state = STATE_DONE_DWNLD;
936 break;
937 case REQUEST_CODE_SEGMENT:
938 //DEBUG("FT1000:download: REQUEST_CODE_SEGMENT - CODELOADER\n");
939 if (!correct_version) {
940 DEBUG
941 ("FT1000:download:Download error: Got Code Segment request before image offset request.\n");
942 status = STATUS_FAILURE;
943 break;
944 }
945
946 word_length =
947 get_request_value(ft1000dev);
948 //DEBUG("FT1000:download:word_length = %d\n", (int)word_length);
949 if (word_length > MAX_LENGTH) {
950 DEBUG
951 ("FT1000:download:Download error: Max length exceeded\n");
952 status = STATUS_FAILURE;
953 break;
954 }
955 if ((word_length * 2 + c_file) >
956 code_end) {
957 /*
958 * Error, beyond boot code range.
959 */
960 DEBUG
961 ("FT1000:download:Download error: Requested len=%d exceeds DSP code boundry.\n",
962 (int)word_length);
963 status = STATUS_FAILURE;
964 break;
965 }
966 /*
967 * Position ASIC DPRAM auto-increment pointer.
968 */
969 dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
970 if (word_length & 0x1)
971 word_length++;
972 word_length = word_length / 2;
973
974 write_blk_fifo(ft1000dev, &s_file,
975 &c_file, word_length);
976 if (pft1000info->usbboot == 0)
977 pft1000info->usbboot++;
978 if (pft1000info->usbboot == 1) {
979 tempword = 0;
980 ft1000_write_dpram16(ft1000dev,
981 DWNLD_MAG1_PS_HDR_LOC,
982 tempword,
983 0);
984 }
985
986 break;
987
988 case REQUEST_MAILBOX_DATA:
989 DEBUG
990 ("FT1000:download: REQUEST_MAILBOX_DATA\n");
991 // Convert length from byte count to word count. Make sure we round up.
992 word_length =
993 (long)(pft1000info->DSPInfoBlklen +
994 1) / 2;
995 put_request_value(ft1000dev,
996 word_length);
997 mailbox_data =
998 (struct drv_msg *)&(pft1000info->
999 DSPInfoBlk[0]);
1000 /*
1001 * Position ASIC DPRAM auto-increment pointer.
1002 */
1003
1004 data = (u16 *) & mailbox_data->data[0];
1005 dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
1006 if (word_length & 0x1)
1007 word_length++;
1008
1009 word_length = (word_length / 2);
1010
1011 for (; word_length > 0; word_length--) { /* In words */
1012
1013 templong = *data++;
1014 templong |= (*data++ << 16);
1015 status =
1016 fix_ft1000_write_dpram32
1017 (ft1000dev, dpram++,
1018 (u8 *) & templong);
1019
1020 }
1021 break;
1022
1023 case REQUEST_VERSION_INFO:
1024 DEBUG
1025 ("FT1000:download:REQUEST_VERSION_INFO\n");
1026 word_length =
1027 file_hdr->version_data_size;
1028 put_request_value(ft1000dev,
1029 word_length);
1030 /*
1031 * Position ASIC DPRAM auto-increment pointer.
1032 */
1033
1034 s_file =
1035 (u16 *) (pFileStart +
1036 file_hdr->
1037 version_data_offset);
1038
1039 dpram = (u16) DWNLD_MAG1_PS_HDR_LOC;
1040 if (word_length & 0x1)
1041 word_length++;
1042
1043 word_length = (word_length / 2);
1044
1045 for (; word_length > 0; word_length--) { /* In words */
1046
1047 templong = ntohs(*s_file++);
1048 temp = ntohs(*s_file++);
1049 templong |= (temp << 16);
1050 status =
1051 fix_ft1000_write_dpram32
1052 (ft1000dev, dpram++,
1053 (u8 *) & templong);
1054
1055 }
1056 break;
1057
1058 case REQUEST_CODE_BY_VERSION:
1059 DEBUG
1060 ("FT1000:download:REQUEST_CODE_BY_VERSION\n");
1061 correct_version = FALSE;
1062 requested_version =
1063 get_request_value(ft1000dev);
1064
1065 dsp_img_info =
1066 (struct dsp_image_info *)(pFileStart
1067 +
1068 sizeof
1069 (struct
1070 dsp_file_hdr));
1071
1072 for (image = 0;
1073 image < file_hdr->nDspImages;
1074 image++) {
1075
1076 temp =
1077 (u16) (dsp_img_info->
1078 version);
1079 templong = temp;
1080 temp =
1081 (u16) (dsp_img_info->
1082 version >> 16);
1083 templong |= (temp << 16);
1084 if (templong ==
1085 (u32) requested_version) {
1086 correct_version = TRUE;
1087 DEBUG
1088 ("FT1000:download: correct_version is TRUE\n");
1089 s_file =
1090 (u16 *) (pFileStart
1091 +
1092 dsp_img_info->
1093 begin_offset);
1094 c_file =
1095 (u8 *) (pFileStart +
1096 dsp_img_info->
1097 begin_offset);
1098 code_end =
1099 (u8 *) (pFileStart +
1100 dsp_img_info->
1101 end_offset);
1102 run_address =
1103 dsp_img_info->
1104 run_address;
1105 run_size =
1106 dsp_img_info->
1107 image_size;
1108 image_chksum =
1109 (u32) dsp_img_info->
1110 checksum;
1111 break;
1112 }
1113 dsp_img_info++;
1114
1115 } //end of for
1116
1117 if (!correct_version) {
1118 /*
1119 * Error, beyond boot code range.
1120 */
1121 DEBUG
1122 ("FT1000:download:Download error: Bad Version Request = 0x%x.\n",
1123 (int)requested_version);
1124 status = STATUS_FAILURE;
1125 break;
1126 }
1127 break;
1128
1129 default:
1130 DEBUG
1131 ("FT1000:download:Download error: Bad request type=%d in CODE download state.\n",
1132 request);
1133 status = STATUS_FAILURE;
1134 break;
1135 }
1136 if (pft1000info->usbboot)
1137 put_handshake_usb(ft1000dev,
1138 HANDSHAKE_RESPONSE);
1139 else
1140 put_handshake(ft1000dev,
1141 HANDSHAKE_RESPONSE);
1142 } else {
1143 DEBUG
1144 ("FT1000:download:Download error: Handshake failed\n");
1145 status = STATUS_FAILURE;
1146 }
1147
1148 break;
1149
1150 case STATE_DONE_DWNLD:
1151 DEBUG("FT1000:download:Code loader is done...\n");
1152 state = STATE_SECTION_PROV;
1153 break;
1154
1155 case STATE_SECTION_PROV:
1156 DEBUG("FT1000:download:STATE_SECTION_PROV\n");
1157 pseudo_header = (struct pseudo_hdr *)c_file;
1158
1159 if (pseudo_header->checksum ==
1160 hdr_checksum(pseudo_header)) {
1161 if (pseudo_header->portdest !=
1162 0x80 /* Dsp OAM */ ) {
1163 state = STATE_DONE_PROV;
1164 break;
1165 }
1166 pseudo_header_len = ntohs(pseudo_header->length); /* Byte length for PROV records */
1167
1168 // Get buffer for provisioning data
1169 pbuffer =
1170 kmalloc((pseudo_header_len +
1171 sizeof(struct pseudo_hdr)),
1172 GFP_ATOMIC);
1173 if (pbuffer) {
1174 memcpy(pbuffer, (void *)c_file,
1175 (u32) (pseudo_header_len +
1176 sizeof(struct
1177 pseudo_hdr)));
1178 // link provisioning data
1179 pprov_record =
1180 kmalloc(sizeof(struct prov_record),
1181 GFP_ATOMIC);
1182 if (pprov_record) {
1183 pprov_record->pprov_data =
1184 pbuffer;
1185 list_add_tail(&pprov_record->
1186 list,
1187 &pft1000info->
1188 prov_list);
1189 // Move to next entry if available
1190 c_file =
1191 (u8 *) ((unsigned long)
1192 c_file +
1193 (u32) ((pseudo_header_len + 1) & 0xFFFFFFFE) + sizeof(struct pseudo_hdr));
1194 if ((unsigned long)(c_file) -
1195 (unsigned long)(pFileStart)
1196 >=
1197 (unsigned long)FileLength) {
1198 state = STATE_DONE_FILE;
1199 }
1200 } else {
1201 kfree(pbuffer);
1202 status = STATUS_FAILURE;
1203 }
1204 } else {
1205 status = STATUS_FAILURE;
1206 }
1207 } else {
1208 /* Checksum did not compute */
1209 status = STATUS_FAILURE;
1210 }
1211 DEBUG
1212 ("ft1000:download: after STATE_SECTION_PROV, state = %d, status= %d\n",
1213 state, status);
1214 break;
1215
1216 case STATE_DONE_PROV:
1217 DEBUG("FT1000:download:STATE_DONE_PROV\n");
1218 state = STATE_DONE_FILE;
1219 break;
1220
1221 default:
1222 status = STATUS_FAILURE;
1223 break;
1224 } /* End Switch */
1225
1226 if (status != STATUS_SUCCESS) {
1227 break;
1228 }
f7c1be0c
MB
1229
1230/****
1231 // Check if Card is present
0ce72ea3
MB
1232 status = Harley_Read_Register(&temp, FT1000_REG_SUP_IMASK);
1233 if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0x0000) ) {
f7c1be0c
MB
1234 break;
1235 }
1236
0ce72ea3
MB
1237 status = Harley_Read_Register(&temp, FT1000_REG_ASIC_ID);
1238 if ( (status != NDIS_STATUS_SUCCESS) || (temp == 0xffff) ) {
f7c1be0c
MB
1239 break;
1240 }
1241****/
1242
6f953fbb 1243 } /* End while */
bf3146c8 1244
6f953fbb
MB
1245 DEBUG("Download exiting with status = 0x%8x\n", status);
1246 ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
1247 FT1000_REG_DOORBELL);
f7c1be0c 1248
6f953fbb 1249 return status;
f7c1be0c
MB
1250}
1251