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