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