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