Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
csr_wifi_hip_download.c
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  (c) Cambridge Silicon Radio Limited 2012
4  All rights reserved and confidential information of CSR
5 
6  Refer to LICENSE.txt included with this source for details
7  on the license terms.
8 
9 *****************************************************************************/
10 
11 /*
12  * ---------------------------------------------------------------------------
13  * FILE: csr_wifi_hip_download.c
14  *
15  * PURPOSE:
16  * Routines for downloading firmware to UniFi.
17  *
18  * ---------------------------------------------------------------------------
19  */
20 #include <linux/slab.h>
21 #include "csr_wifi_hip_unifi.h"
23 #include "csr_wifi_hip_card.h"
24 #include "csr_wifi_hip_xbv.h"
25 
26 #undef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
27 
28 static CsrResult do_patch_download(card_t *card, void *dlpriv,
29  xbv1_t *pfwinfo, u32 boot_ctrl_addr);
30 
31 static CsrResult do_patch_convert_download(card_t *card,
32  void *dlpriv, xbv1_t *pfwinfo);
33 
34 /*
35  * ---------------------------------------------------------------------------
36  * _find_in_slut
37  *
38  * Find the offset of the appropriate object in the SLUT of a card
39  *
40  * Arguments:
41  * card Pointer to card struct
42  * psym Pointer to symbol object.
43  * id set up by caller
44  * obj will be set up by this function
45  * pslut Pointer to SLUT address, if 0xffffffff then it must be
46  * read from the chip.
47  * Returns:
48  * CSR_RESULT_SUCCESS on success
49  * Non-zero on error,
50  * CSR_WIFI_HIP_RESULT_NOT_FOUND if not found
51  * ---------------------------------------------------------------------------
52  */
53 static CsrResult _find_in_slut(card_t *card, symbol_t *psym, u32 *pslut)
54 {
55  u32 slut_address;
56  u16 finger_print;
57  CsrResult r;
58  CsrResult csrResult;
59 
60  /* Get SLUT address */
61  if (*pslut == 0xffffffff)
62  {
63  r = card_wait_for_firmware_to_start(card, &slut_address);
65  {
66  return r;
67  }
68  if (r != CSR_RESULT_SUCCESS)
69  {
70  unifi_error(card->ospriv, "Firmware hasn't started\n");
71  func_exit_r(r);
72  return r;
73  }
74  *pslut = slut_address;
75 
76  /*
77  * Firmware has started so set the SDIO bus clock to the initial speed,
78  * faster than UNIFI_SDIO_CLOCK_SAFE_HZ, to speed up the f/w download.
79  */
80  csrResult = CsrSdioMaxBusClockFrequencySet(card->sdio_if, UNIFI_SDIO_CLOCK_INIT_HZ);
81  if (csrResult != CSR_RESULT_SUCCESS)
82  {
83  r = ConvertCsrSdioToCsrHipResult(card, csrResult);
84  func_exit_r(r);
85  return r;
86  }
87  card->sdio_clock_speed = UNIFI_SDIO_CLOCK_INIT_HZ;
88  }
89  else
90  {
91  slut_address = *pslut; /* Use previously discovered address */
92  }
93  unifi_trace(card->ospriv, UDBG4, "SLUT addr: 0x%lX\n", slut_address);
94 
95  /*
96  * Check the SLUT fingerprint.
97  * The slut_address is a generic pointer so we must use unifi_card_read16().
98  */
99  unifi_trace(card->ospriv, UDBG4, "Looking for SLUT finger print\n");
100  finger_print = 0;
101  r = unifi_card_read16(card, slut_address, &finger_print);
103  {
104  return r;
105  }
106  if (r != CSR_RESULT_SUCCESS)
107  {
108  unifi_error(card->ospriv, "Failed to read SLUT finger print\n");
109  func_exit_r(r);
110  return r;
111  }
112 
113  if (finger_print != SLUT_FINGERPRINT)
114  {
115  unifi_error(card->ospriv, "Failed to find SLUT fingerprint\n");
117  return CSR_RESULT_FAILURE;
118  }
119 
120  /* Symbol table starts imedately after the fingerprint */
121  slut_address += 2;
122 
123  while (1)
124  {
125  u16 id;
126  u32 obj;
127 
128  r = unifi_card_read16(card, slut_address, &id);
129  if (r != CSR_RESULT_SUCCESS)
130  {
131  func_exit_r(r);
132  return r;
133  }
134  slut_address += 2;
135 
136  if (id == CSR_SLT_END)
137  {
138  /* End of table reached: not found */
140  break;
141  }
142 
143  r = unifi_read32(card, slut_address, &obj);
144  if (r != CSR_RESULT_SUCCESS)
145  {
146  func_exit_r(r);
147  return r;
148  }
149  slut_address += 4;
150 
151  unifi_trace(card->ospriv, UDBG3, " found SLUT id %02d.%08lx\n", id, obj);
152 
154  /* Found search term? */
155  if (id == psym->id)
156  {
157  unifi_trace(card->ospriv, UDBG1, " matched SLUT id %02d.%08lx\n", id, obj);
158  psym->obj = obj;
159  r = CSR_RESULT_SUCCESS;
160  break;
161  }
162  }
163 
164  func_exit_r(r);
165  return r;
166 }
167 
168 
169 /*
170  * ---------------------------------------------------------------------------
171  * do_patch_convert_download
172  *
173  * Download the given firmware image to the UniFi, converting from FWDL
174  * to PTDL XBV format.
175  *
176  * Arguments:
177  * card Pointer to card struct
178  * dlpriv Pointer to source firmware image
179  * fwinfo Pointer to source firmware info struct
180  *
181  * Returns:
182  * CSR_RESULT_SUCCESS on success, CSR error code on error
183  *
184  * Notes:
185  * ---------------------------------------------------------------------------
186  */
187 static CsrResult do_patch_convert_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo)
188 {
189  CsrResult r;
190  u32 slut_base = 0xffffffff;
191  void *pfw;
192  u32 psize;
193  symbol_t sym;
194 
195  /* Reset the chip to guarantee that the ROM loader is running */
196  r = unifi_init(card);
197  if (r != CSR_RESULT_SUCCESS)
198  {
199  unifi_error(card->ospriv,
200  "do_patch_convert_download: failed to re-init UniFi\n");
201  return r;
202  }
203 
204  /* If no unifi_helper is running, the firmware version must be read */
205  if (card->build_id == 0)
206  {
207  u32 ver = 0;
208  sym.id = CSR_SLT_BUILD_ID_NUMBER;
209  sym.obj = 0; /* To be updated by _find_in_slut() */
210 
211  unifi_trace(card->ospriv, UDBG1, "Need f/w version\n");
212 
213  /* Find chip build id entry in SLUT */
214  r = _find_in_slut(card, &sym, &slut_base);
215  if (r != CSR_RESULT_SUCCESS)
216  {
217  unifi_error(card->ospriv, "Failed to find CSR_SLT_BUILD_ID_NUMBER\n");
218  return CSR_RESULT_FAILURE;
219  }
220 
221  /* Read running f/w version */
222  r = unifi_read32(card, sym.obj, &ver);
224  {
225  return r;
226  }
227  if (r != CSR_RESULT_SUCCESS)
228  {
229  unifi_error(card->ospriv, "Failed to read f/w id\n");
230  return CSR_RESULT_FAILURE;
231  }
232  card->build_id = ver;
233  }
234 
235  /* Convert the ptest firmware to a patch against the running firmware */
236  pfw = xbv_to_patch(card, unifi_fw_read, dlpriv, pfwinfo, &psize);
237  if (!pfw)
238  {
239  unifi_error(card->ospriv, "Failed to convert f/w to patch");
241  }
242  else
243  {
244  void *desc;
246  sym.obj = 0; /* To be updated by _find_in_slut() */
247 
248  /* Find boot loader control entry in SLUT */
249  r = _find_in_slut(card, &sym, &slut_base);
250  if (r != CSR_RESULT_SUCCESS)
251  {
252  unifi_error(card->ospriv, "Failed to find BOOT_LOADER_CONTROL\n");
253  kfree(pfw);
254  return CSR_RESULT_FAILURE;
255  }
256 
258  if (r != CSR_RESULT_SUCCESS)
259  {
260  unifi_error(card->ospriv, "Failed to wake UniFi\n");
261  }
262 
263  /* Get a dlpriv for the patch buffer so that unifi_fw_read() can
264  * access it.
265  */
266  desc = unifi_fw_open_buffer(card->ospriv, pfw, psize);
267  if (!desc)
268  {
269  kfree(pfw);
271  }
272 
273  /* Download the patch */
274  unifi_info(card->ospriv, "Downloading converted f/w as patch\n");
275  r = unifi_dl_patch(card, desc, sym.obj);
276  kfree(pfw);
277  unifi_fw_close_buffer(card->ospriv, desc);
278 
279  if (r != CSR_RESULT_SUCCESS)
280  {
281  unifi_error(card->ospriv, "Converted patch download failed\n");
282  func_exit_r(r);
283  return r;
284  }
285  else
286  {
287  unifi_trace(card->ospriv, UDBG1, "Converted patch downloaded\n");
288  }
289 
290  /* This command starts the firmware */
291  r = unifi_do_loader_op(card, sym.obj + 6, UNIFI_BOOT_LOADER_RESTART);
292  if (r != CSR_RESULT_SUCCESS)
293  {
294  unifi_error(card->ospriv, "Failed to write loader restart cmd\n");
295  }
296 
297  func_exit_r(r);
298  return r;
299  }
300 }
301 
302 
303 /*
304  * ---------------------------------------------------------------------------
305  * unifi_dl_firmware
306  *
307  * Download the given firmware image to the UniFi.
308  *
309  * Arguments:
310  * card Pointer to card struct
311  * dlpriv A context pointer from the calling function to be
312  * passed when calling unifi_fw_read().
313  *
314  * Returns:
315  * CSR_RESULT_SUCCESS on success,
316  * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
317  * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
318  * CSR_RESULT_FAILURE SDIO error
319  *
320  * Notes:
321  * Stops and resets the chip, does the download and runs the new
322  * firmware.
323  * ---------------------------------------------------------------------------
324  */
325 CsrResult unifi_dl_firmware(card_t *card, void *dlpriv)
326 {
327  xbv1_t *fwinfo;
328  CsrResult r;
329 
330  func_enter();
331 
332  fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
333  if (fwinfo == NULL)
334  {
335  unifi_error(card->ospriv, "Failed to allocate memory for firmware\n");
337  }
338 
339  /*
340  * Scan the firmware file to find the TLVs we are interested in.
341  * These are:
342  * - check we support the file format version in VERF
343  * - SLTP Symbol Lookup Table Pointer
344  * - FWDL firmware download segments
345  * - FWOV firmware overlay segment
346  * - VMEQ Register probe tests to verify matching h/w
347  */
348  r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
349  if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_firmware)
350  {
351  unifi_error(card->ospriv, "File type is %s, expected firmware.\n",
352  fwinfo->mode == xbv_patch?"patch" : "unknown");
353  kfree(fwinfo);
355  }
356 
357  /* UF6xxx doesn't accept firmware, only patches. Therefore we convert
358  * the file to patch format with version numbers matching the current
359  * running firmware, and then download via the patch mechanism.
360  * The sole purpose of this is to support production test firmware across
361  * different ROM releases, the test firmware being provided in non-patch
362  * format.
363  */
364  if (card->chip_id > SDIO_CARD_ID_UNIFI_2)
365  {
366  unifi_info(card->ospriv, "Must convert f/w to patch format\n");
367  r = do_patch_convert_download(card, dlpriv, fwinfo);
368  }
369  else
370  {
371  /* Older UniFi chips allowed firmware to be directly loaded onto the
372  * chip, which is no longer supported.
373  */
374  unifi_error(card->ospriv, "Only patch downloading supported\n");
376  }
377 
378  kfree(fwinfo);
379  func_exit_r(r);
380  return r;
381 } /* unifi_dl_firmware() */
382 
383 
384 /*
385  * ---------------------------------------------------------------------------
386  * unifi_dl_patch
387  *
388  * Load the given patch set into UniFi.
389  *
390  * Arguments:
391  * card Pointer to card struct
392  * dlpriv The os specific handle to the firmware file.
393  * boot_ctrl The address of the boot loader control structure.
394  *
395  * Returns:
396  * CSR_RESULT_SUCCESS on success,
397  * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
398  * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
399  * CSR_RESULT_FAILURE SDIO error
400  *
401  * Notes:
402  * This ends up telling UniFi to restart.
403  * ---------------------------------------------------------------------------
404  */
405 CsrResult unifi_dl_patch(card_t *card, void *dlpriv, u32 boot_ctrl)
406 {
407  xbv1_t *fwinfo;
408  CsrResult r;
409 
410  func_enter();
411 
412  unifi_info(card->ospriv, "unifi_dl_patch %p %08x\n", dlpriv, boot_ctrl);
413 
414  fwinfo = kmalloc(sizeof(xbv1_t), GFP_KERNEL);
415  if (fwinfo == NULL)
416  {
417  unifi_error(card->ospriv, "Failed to allocate memory for patches\n");
418  func_exit();
420  }
421 
422  /*
423  * Scan the firmware file to find the TLVs we are interested in.
424  * These are:
425  * - check we support the file format version in VERF
426  * - FWID The build ID of the ROM that we can patch
427  * - PTDL patch download segments
428  */
429  r = xbv1_parse(card, unifi_fw_read, dlpriv, fwinfo);
430  if (r != CSR_RESULT_SUCCESS || fwinfo->mode != xbv_patch)
431  {
432  kfree(fwinfo);
433  unifi_error(card->ospriv, "Failed to read in patch file\n");
434  func_exit();
436  }
437 
438  /*
439  * We have to check the build id read from the SLUT against that
440  * for the patch file. They have to match exactly.
441  * "card->build_id" == XBV1.PTCH.FWID
442  */
443  if (card->build_id != fwinfo->build_id)
444  {
445  unifi_error(card->ospriv, "Wrong patch file for chip (chip = %lu, file = %lu)\n",
446  card->build_id, fwinfo->build_id);
447  kfree(fwinfo);
448 #ifndef CSR_WIFI_IGNORE_PATCH_VERSION_MISMATCH
449  func_exit();
451 #else
452  fwinfo = NULL;
453  dlpriv = NULL;
454  return CSR_RESULT_SUCCESS;
455 #endif
456  }
457 
458  r = do_patch_download(card, dlpriv, fwinfo, boot_ctrl);
459  if (r != CSR_RESULT_SUCCESS)
460  {
461  unifi_error(card->ospriv, "Failed to patch image\n");
462  }
463 
464  kfree(fwinfo);
465 
466  func_exit_r(r);
467  return r;
468 } /* unifi_dl_patch() */
469 
470 
471 void* unifi_dl_fw_read_start(card_t *card, s8 is_fw)
472 {
474 
475  unifi_card_info(card, &card_info);
476  unifi_trace(card->ospriv, UDBG5,
477  "id=%d, ver=0x%x, fw_build=%u, fw_hip=0x%x, block_size=%d\n",
478  card_info.chip_id, card_info.chip_version,
479  card_info.fw_build, card_info.fw_hip_version,
480  card_info.sdio_block_size);
481 
482  return unifi_fw_read_start(card->ospriv, is_fw, &card_info);
483 }
484 
485 
486 /*
487  * ---------------------------------------------------------------------------
488  * safe_read_shared_location
489  *
490  * Read a shared memory location repeatedly until we get two readings
491  * the same.
492  *
493  * Arguments:
494  * card Pointer to card context struct.
495  * unifi_addr UniFi shared-data-memory address to access.
496  * pdata Pointer to a byte variable for the value read.
497  *
498  *
499  * Returns:
500  * CSR_RESULT_SUCCESS on success, CSR error code on failure
501  * ---------------------------------------------------------------------------
502  */
503 static CsrResult safe_read_shared_location(card_t *card, u32 address, u8 *pdata)
504 {
505  CsrResult r;
506  u16 limit = 1000;
507  u8 b, b2;
508 
509  *pdata = 0;
510 
511  r = unifi_read_8_or_16(card, address, &b);
512  if (r != CSR_RESULT_SUCCESS)
513  {
514  return r;
515  }
516 
517  while (limit--)
518  {
519  r = unifi_read_8_or_16(card, address, &b2);
520  if (r != CSR_RESULT_SUCCESS)
521  {
522  return r;
523  }
524 
525  /* When we have a stable value, return it */
526  if (b == b2)
527  {
528  *pdata = b;
529  return CSR_RESULT_SUCCESS;
530  }
531 
532  b = b2;
533  }
534 
535  return CSR_RESULT_FAILURE;
536 } /* safe_read_shared_location() */
537 
538 
539 /*
540  * ---------------------------------------------------------------------------
541  * unifi_do_loader_op
542  *
543  * Send a loader / boot_loader command to the UniFi and wait for
544  * it to complete.
545  *
546  * Arguments:
547  * card Pointer to card context struct.
548  * op_addr The address of the loader operation control word.
549  * opcode The operation to perform.
550  *
551  * Returns:
552  * CSR_RESULT_SUCCESS on success
553  * CSR_RESULT_FAILURE SDIO error or SDIO/XAP timeout
554  * ---------------------------------------------------------------------------
555  */
556 
557 /*
558  * Ideally instead of sleeping, we want to busy wait.
559  * Currently there is no framework API to do this. When it becomes available,
560  * we can use it to busy wait using usecs
561  */
562 #define OPERATION_TIMEOUT_LOOPS (100) /* when OPERATION_TIMEOUT_DELAY==1, (500) otherwise */
563 #define OPERATION_TIMEOUT_DELAY 1 /* msec, or 200usecs */
564 
566 {
567  CsrResult r;
568  s16 op_retries;
569 
570  unifi_trace(card->ospriv, UDBG4, "Loader cmd 0x%0x -> 0x%08x\n", opcode, op_addr);
571 
572  /* Set the Operation command byte to the opcode */
573  r = unifi_write_8_or_16(card, op_addr, opcode);
574  if (r != CSR_RESULT_SUCCESS)
575  {
576  unifi_error(card->ospriv, "Failed to write loader copy command\n");
577  return r;
578  }
579 
580  /* Wait for Operation command byte to be Idle */
581  /* Typically takes ~100us */
582  op_retries = 0;
583  r = CSR_RESULT_SUCCESS;
584  while (1)
585  {
586  u8 op;
587 
588  /*
589  * Read the memory location until two successive reads give
590  * the same value.
591  * Then handle it.
592  */
593  r = safe_read_shared_location(card, op_addr, &op);
594  if (r != CSR_RESULT_SUCCESS)
595  {
596  unifi_error(card->ospriv, "Failed to read loader status\n");
597  break;
598  }
599 
600  if (op == UNIFI_LOADER_IDLE)
601  {
602  /* Success */
603  break;
604  }
605 
606  if (op != opcode)
607  {
608  unifi_error(card->ospriv, "Error reported by loader: 0x%X\n", op);
609  r = CSR_RESULT_FAILURE;
610  break;
611  }
612 
613  /* Allow 500us timeout */
614  if (++op_retries >= OPERATION_TIMEOUT_LOOPS)
615  {
616  unifi_error(card->ospriv, "Timeout waiting for loader to ack transfer\n");
617  /* Stop XAPs to aid post-mortem */
619  if (r != CSR_RESULT_SUCCESS)
620  {
621  unifi_error(card->ospriv, "Failed to stop UniFi processors\n");
622  }
623  else
624  {
625  r = CSR_RESULT_FAILURE;
626  }
627  break;
628  }
630  } /* Loop exits with r != CSR_RESULT_SUCCESS on error */
631 
632  return r;
633 } /* unifi_do_loader_op() */
634 
635 
636 /*
637  * ---------------------------------------------------------------------------
638  * send_ptdl_to_unifi
639  *
640  * Copy a patch block from userland to the UniFi.
641  * This function reads data, 2K at a time, from userland and writes
642  * it to the UniFi.
643  *
644  * Arguments:
645  * card A pointer to the card structure
646  * dlpriv The os specific handle for the firmware file
647  * ptdl A pointer ot the PTDL block
648  * handle The buffer handle to use for the xfer
649  * op_addr The address of the loader operation control word
650  *
651  * Returns:
652  * Number of bytes sent (Positive) or negative value indicating
653  * error code:
654  * CSR_WIFI_HIP_RESULT_NO_MEMORY memory allocation failed
655  * CSR_WIFI_HIP_RESULT_INVALID_VALUE error in XBV file
656  * CSR_RESULT_FAILURE SDIO error
657  * ---------------------------------------------------------------------------
658  */
659 static CsrResult send_ptdl_to_unifi(card_t *card, void *dlpriv,
660  const struct PTDL *ptdl, u32 handle,
661  u32 op_addr)
662 {
663  u32 offset;
664  u8 *buf;
665  s32 data_len;
666  u32 write_len;
667  CsrResult r;
668  const u16 buf_size = 2 * 1024;
669 
670  offset = ptdl->dl_offset;
671  data_len = ptdl->dl_size;
672 
673  if (data_len > buf_size)
674  {
675  unifi_error(card->ospriv, "PTDL block is too large (%u)\n",
676  ptdl->dl_size);
678  }
679 
680  buf = kmalloc(buf_size, GFP_KERNEL);
681  if (buf == NULL)
682  {
683  unifi_error(card->ospriv, "Failed to allocate transfer buffer for firmware download\n");
685  }
686 
687  r = CSR_RESULT_SUCCESS;
688 
689  if (unifi_fw_read(card->ospriv, dlpriv, offset, buf, data_len) != data_len)
690  {
691  unifi_error(card->ospriv, "Failed to read from file\n");
692  }
693  else
694  {
695  /* We can always round these if the host wants to */
696  if (card->sdio_io_block_pad)
697  {
698  write_len = (data_len + (card->sdio_io_block_size - 1)) &
699  ~(card->sdio_io_block_size - 1);
700 
701  /* Zero out the rest of the buffer (This isn't needed, but it
702  * makes debugging things later much easier). */
703  memset(buf + data_len, 0, write_len - data_len);
704  }
705  else
706  {
707  write_len = data_len;
708  }
709 
710  r = unifi_bulk_rw_noretry(card, handle, buf, write_len, UNIFI_SDIO_WRITE);
711  if (r != CSR_RESULT_SUCCESS)
712  {
713  unifi_error(card->ospriv, "CMD53 failed writing %d bytes to handle %ld\n",
714  data_len, handle);
715  }
716  else
717  {
718  /*
719  * Can change the order of things to overlap read from file
720  * with copy to unifi
721  */
722  r = unifi_do_loader_op(card, op_addr, UNIFI_BOOT_LOADER_PATCH);
723  }
724  }
725 
726  kfree(buf);
727 
729  {
730  unifi_error(card->ospriv, "Failed to copy block of %u bytes to UniFi\n",
731  ptdl->dl_size);
732  }
733 
734  return r;
735 } /* send_ptdl_to_unifi() */
736 
737 
738 /*
739  * ---------------------------------------------------------------------------
740  * do_patch_download
741  *
742  * This function downloads a set of patches to UniFi and then
743  * causes it to restart.
744  *
745  * Arguments:
746  * card Pointer to card struct.
747  * dlpriv A context pointer from the calling function to be
748  * used when reading the XBV file. This can be NULL
749  * in which case not patches are applied.
750  * pfwinfo Pointer to a fwinfo struct describing the f/w
751  * XBV file.
752  * boot_ctrl_addr The address of the boot loader control structure.
753  *
754  * Returns:
755  * 0 on success, or an error code
756  * CSR_WIFI_HIP_RESULT_INVALID_VALUE for a bad laoader version number
757  * ---------------------------------------------------------------------------
758  */
759 static CsrResult do_patch_download(card_t *card, void *dlpriv, xbv1_t *pfwinfo, u32 boot_ctrl_addr)
760 {
761  CsrResult r;
762  s32 i;
763  u16 loader_version;
764  u16 handle;
766 
767  /*
768  * Read info from the SDIO Loader Control Data Structure
769  */
770  /* Check the loader version */
771  r = unifi_card_read16(card, boot_ctrl_addr, &loader_version);
772  if (r != CSR_RESULT_SUCCESS)
773  {
774  unifi_error(card->ospriv, "Patch download: Failed to read loader version\n");
775  return r;
776  }
777  unifi_trace(card->ospriv, UDBG2, "Patch download: boot loader version 0x%04X\n", loader_version);
778  switch (loader_version)
779  {
780  case 0x0000:
781  break;
782 
783  default:
784  unifi_error(card->ospriv, "Patch loader version (0x%04X) is not supported by this driver\n",
785  loader_version);
787  }
788 
789  /* Retrieve the handle to use with CMD53 */
790  r = unifi_card_read16(card, boot_ctrl_addr + 4, &handle);
791  if (r != CSR_RESULT_SUCCESS)
792  {
793  unifi_error(card->ospriv, "Patch download: Failed to read loader handle\n");
794  return r;
795  }
796 
797  /* Set the mask of LEDs to flash */
798  if (card->loader_led_mask)
799  {
800  r = unifi_card_write16(card, boot_ctrl_addr + 2,
801  (u16)card->loader_led_mask);
802  if (r != CSR_RESULT_SUCCESS)
803  {
804  unifi_error(card->ospriv, "Patch download: Failed to write LED mask\n");
805  return r;
806  }
807  }
808 
809  total_bytes = 0;
810 
811  /* Copy download data to UniFi memory */
812  for (i = 0; i < pfwinfo->num_ptdl; i++)
813  {
814  unifi_trace(card->ospriv, UDBG3, "Patch download: %d Downloading for %d from offset %d\n",
815  i,
816  pfwinfo->ptdl[i].dl_size,
817  pfwinfo->ptdl[i].dl_offset);
818 
819  r = send_ptdl_to_unifi(card, dlpriv, &pfwinfo->ptdl[i],
820  handle, boot_ctrl_addr + 6);
822  {
823  return r;
824  }
825  if (r != CSR_RESULT_SUCCESS)
826  {
827  unifi_error(card->ospriv, "Patch failed after %u bytes\n",
828  total_bytes);
829  return r;
830  }
831  total_bytes += pfwinfo->ptdl[i].dl_size;
832  }
833 
834  return CSR_RESULT_SUCCESS;
835 } /* do_patch_download() */
836 
837