dfu.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * Intel Wireless UWB Link 1480
  3. * Main driver
  4. *
  5. * Copyright (C) 2005-2006 Intel Corporation
  6. * Inaky Perez-Gonzalez <inaky.perez-gonzalez@intel.com>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License version
  10. * 2 as published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  20. * 02110-1301, USA.
  21. *
  22. *
  23. * Common code for firmware upload used by the USB and PCI version;
  24. * i1480_fw_upload() takes a device descriptor and uses the function
  25. * pointers it provides to upload firmware and prepare the PHY.
  26. *
  27. * As well, provides common functions used by the rest of the code.
  28. */
  29. #include "i1480-dfu.h"
  30. #include <linux/errno.h>
  31. #include <linux/delay.h>
  32. #include <linux/pci.h>
  33. #include <linux/device.h>
  34. #include <linux/uwb.h>
  35. #include <linux/random.h>
  36. #define D_LOCAL 0
  37. #include <linux/uwb/debug.h>
  38. /**
  39. * i1480_rceb_check - Check RCEB for expected field values
  40. * @i1480: pointer to device for which RCEB is being checked
  41. * @rceb: RCEB being checked
  42. * @cmd: which command the RCEB is related to
  43. * @context: expected context
  44. * @expected_type: expected event type
  45. * @expected_event: expected event
  46. *
  47. * If @cmd is NULL, do not print error messages, but still return an error
  48. * code.
  49. *
  50. * Return 0 if @rceb matches the expected values, -EINVAL otherwise.
  51. */
  52. int i1480_rceb_check(const struct i1480 *i1480, const struct uwb_rceb *rceb,
  53. const char *cmd, u8 context, u8 expected_type,
  54. unsigned expected_event)
  55. {
  56. int result = 0;
  57. struct device *dev = i1480->dev;
  58. if (rceb->bEventContext != context) {
  59. if (cmd)
  60. dev_err(dev, "%s: unexpected context id 0x%02x "
  61. "(expected 0x%02x)\n", cmd,
  62. rceb->bEventContext, context);
  63. result = -EINVAL;
  64. }
  65. if (rceb->bEventType != expected_type) {
  66. if (cmd)
  67. dev_err(dev, "%s: unexpected event type 0x%02x "
  68. "(expected 0x%02x)\n", cmd,
  69. rceb->bEventType, expected_type);
  70. result = -EINVAL;
  71. }
  72. if (le16_to_cpu(rceb->wEvent) != expected_event) {
  73. if (cmd)
  74. dev_err(dev, "%s: unexpected event 0x%04x "
  75. "(expected 0x%04x)\n", cmd,
  76. le16_to_cpu(rceb->wEvent), expected_event);
  77. result = -EINVAL;
  78. }
  79. return result;
  80. }
  81. EXPORT_SYMBOL_GPL(i1480_rceb_check);
  82. /**
  83. * Execute a Radio Control Command
  84. *
  85. * Command data has to be in i1480->cmd_buf.
  86. *
  87. * @returns size of the reply data filled in i1480->evt_buf or < 0 errno
  88. * code on error.
  89. */
  90. ssize_t i1480_cmd(struct i1480 *i1480, const char *cmd_name, size_t cmd_size,
  91. size_t reply_size)
  92. {
  93. ssize_t result;
  94. struct uwb_rceb *reply = i1480->evt_buf;
  95. struct uwb_rccb *cmd = i1480->cmd_buf;
  96. u16 expected_event = reply->wEvent;
  97. u8 expected_type = reply->bEventType;
  98. u8 context;
  99. d_fnstart(3, i1480->dev, "(%p, %s, %zu)\n", i1480, cmd_name, cmd_size);
  100. init_completion(&i1480->evt_complete);
  101. i1480->evt_result = -EINPROGRESS;
  102. do {
  103. get_random_bytes(&context, 1);
  104. } while (context == 0x00 || context == 0xff);
  105. cmd->bCommandContext = context;
  106. result = i1480->cmd(i1480, cmd_name, cmd_size);
  107. if (result < 0)
  108. goto error;
  109. /* wait for the callback to report a event was received */
  110. result = wait_for_completion_interruptible_timeout(
  111. &i1480->evt_complete, HZ);
  112. if (result == 0) {
  113. result = -ETIMEDOUT;
  114. goto error;
  115. }
  116. if (result < 0)
  117. goto error;
  118. result = i1480->evt_result;
  119. if (result < 0) {
  120. dev_err(i1480->dev, "%s: command reply reception failed: %zd\n",
  121. cmd_name, result);
  122. goto error;
  123. }
  124. /*
  125. * Firmware versions >= 1.4.12224 for IOGear GUWA100U generate a
  126. * spurious notification after firmware is downloaded. So check whether
  127. * the receibed RCEB is such notification before assuming that the
  128. * command has failed.
  129. */
  130. if (i1480_rceb_check(i1480, i1480->evt_buf, NULL,
  131. 0, 0xfd, 0x0022) == 0) {
  132. /* Now wait for the actual RCEB for this command. */
  133. result = i1480->wait_init_done(i1480);
  134. if (result < 0)
  135. goto error;
  136. result = i1480->evt_result;
  137. }
  138. if (result != reply_size) {
  139. dev_err(i1480->dev, "%s returned only %zu bytes, %zu expected\n",
  140. cmd_name, result, reply_size);
  141. result = -EINVAL;
  142. goto error;
  143. }
  144. /* Verify we got the right event in response */
  145. result = i1480_rceb_check(i1480, i1480->evt_buf, cmd_name, context,
  146. expected_type, expected_event);
  147. error:
  148. d_fnend(3, i1480->dev, "(%p, %s, %zu) = %zd\n",
  149. i1480, cmd_name, cmd_size, result);
  150. return result;
  151. }
  152. EXPORT_SYMBOL_GPL(i1480_cmd);
  153. static
  154. int i1480_print_state(struct i1480 *i1480)
  155. {
  156. int result;
  157. u32 *buf = (u32 *) i1480->cmd_buf;
  158. result = i1480->read(i1480, 0x80080000, 2 * sizeof(*buf));
  159. if (result < 0) {
  160. dev_err(i1480->dev, "cannot read U & L states: %d\n", result);
  161. goto error;
  162. }
  163. dev_info(i1480->dev, "state U 0x%08x, L 0x%08x\n", buf[0], buf[1]);
  164. error:
  165. return result;
  166. }
  167. /*
  168. * PCI probe, firmware uploader
  169. *
  170. * _mac_fw_upload() will call rc_setup(), which needs an rc_release().
  171. */
  172. int i1480_fw_upload(struct i1480 *i1480)
  173. {
  174. int result;
  175. result = i1480_pre_fw_upload(i1480); /* PHY pre fw */
  176. if (result < 0 && result != -ENOENT) {
  177. i1480_print_state(i1480);
  178. goto error;
  179. }
  180. result = i1480_mac_fw_upload(i1480); /* MAC fw */
  181. if (result < 0) {
  182. if (result == -ENOENT)
  183. dev_err(i1480->dev, "Cannot locate MAC FW file '%s'\n",
  184. i1480->mac_fw_name);
  185. else
  186. i1480_print_state(i1480);
  187. goto error;
  188. }
  189. result = i1480_phy_fw_upload(i1480); /* PHY fw */
  190. if (result < 0 && result != -ENOENT) {
  191. i1480_print_state(i1480);
  192. goto error_rc_release;
  193. }
  194. /*
  195. * FIXME: find some reliable way to check whether firmware is running
  196. * properly. Maybe use some standard request that has no side effects?
  197. */
  198. dev_info(i1480->dev, "firmware uploaded successfully\n");
  199. error_rc_release:
  200. if (i1480->rc_release)
  201. i1480->rc_release(i1480);
  202. result = 0;
  203. error:
  204. return result;
  205. }
  206. EXPORT_SYMBOL_GPL(i1480_fw_upload);