Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ft1000_download.c
Go to the documentation of this file.
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.
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 //---------------------------------------------------------------------------
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,
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,
143  status = ft1000_write_register(ft1000dev, 0x0100,
145  status = ft1000_write_register(ft1000dev, 0x8000,
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,
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 
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 //---------------------------------------------------------------------------
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,
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,
212  }
213 
214  status = ft1000_read_dpram16(ft1000dev,
215  DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
216  handshake = ntohs(handshake);
217 
218  if (status)
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 
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 //---------------------------------------------------------------------------
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);
258  tempword, 0);
259  tempword = (u16)(tempx >> 16);
261  tempword, 1);
262  status = ft1000_write_register(ft1000dev, FT1000_DB_DNLD_TX,
264 }
265 
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,
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,
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 
312 }
313 
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 //---------------------------------------------------------------------------
333 static u16 get_request_type(struct ft1000_device *ft1000dev)
334 {
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 
357 static u16 get_request_type_usb(struct ft1000_device *ft1000dev)
358 {
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,
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 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
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 //---------------------------------------------------------------------------
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 
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 //---------------------------------------------------------------------------
502 static u32 write_blk (struct ft1000_device *ft1000dev, u16 **pUsFile, u8 **pUcFile, long word_length)
503 {
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 
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 //---------------------------------------------------------------------------
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 
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;
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 
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,
752  else
753  handshake =
754  get_handshake(ft1000dev,
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,
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;
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,
848  else
849  put_handshake(ft1000dev,
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,
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) {
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;
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,
974  tempword,
975  0);
976  }
977 
978  break;
979 
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 =
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->
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 =
1044  (ft1000dev, dpram++,
1045  (u8 *) & templong);
1046 
1047  }
1048  break;
1049 
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,
1123  else
1124  put_handshake(ft1000dev,
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);
1232 
1233  return status;
1234 }
1235