fw.c revision 37a2e566f82de9a88fe119479162f9984af2180d
1/* Firmware file reading and download helpers 2 * 3 * See copyright notice in main.c 4 */ 5#include <linux/kernel.h> 6#include <linux/firmware.h> 7 8#include "hermes.h" 9#include "hermes_dld.h" 10#include "orinoco.h" 11 12#include "fw.h" 13 14/* End markers (for Symbol firmware only) */ 15#define TEXT_END 0x1A /* End of text header */ 16 17struct fw_info { 18 char *pri_fw; 19 char *sta_fw; 20 char *ap_fw; 21 u32 pda_addr; 22 u16 pda_size; 23}; 24 25const static struct fw_info orinoco_fw[] = { 26 { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 }, 27 { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 }, 28 { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 } 29}; 30 31/* Structure used to access fields in FW 32 * Make sure LE decoding macros are used 33 */ 34struct orinoco_fw_header { 35 char hdr_vers[6]; /* ASCII string for header version */ 36 __le16 headersize; /* Total length of header */ 37 __le32 entry_point; /* NIC entry point */ 38 __le32 blocks; /* Number of blocks to program */ 39 __le32 block_offset; /* Offset of block data from eof header */ 40 __le32 pdr_offset; /* Offset to PDR data from eof header */ 41 __le32 pri_offset; /* Offset to primary plug data */ 42 __le32 compat_offset; /* Offset to compatibility data*/ 43 char signature[0]; /* FW signature length headersize-20 */ 44} __attribute__ ((packed)); 45 46/* Download either STA or AP firmware into the card. */ 47static int 48orinoco_dl_firmware(struct orinoco_private *priv, 49 const struct fw_info *fw, 50 int ap) 51{ 52 /* Plug Data Area (PDA) */ 53 __le16 *pda; 54 55 hermes_t *hw = &priv->hw; 56 const struct firmware *fw_entry; 57 const struct orinoco_fw_header *hdr; 58 const unsigned char *first_block; 59 const unsigned char *end; 60 const char *firmware; 61 struct net_device *dev = priv->ndev; 62 int err = 0; 63 64 pda = kzalloc(fw->pda_size, GFP_KERNEL); 65 if (!pda) 66 return -ENOMEM; 67 68 if (ap) 69 firmware = fw->ap_fw; 70 else 71 firmware = fw->sta_fw; 72 73 printk(KERN_DEBUG "%s: Attempting to download firmware %s\n", 74 dev->name, firmware); 75 76 /* Read current plug data */ 77 err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0); 78 printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err); 79 if (err) 80 goto free; 81 82 if (!priv->cached_fw) { 83 err = request_firmware(&fw_entry, firmware, priv->dev); 84 85 if (err) { 86 printk(KERN_ERR "%s: Cannot find firmware %s\n", 87 dev->name, firmware); 88 err = -ENOENT; 89 goto free; 90 } 91 } else 92 fw_entry = priv->cached_fw; 93 94 hdr = (const struct orinoco_fw_header *) fw_entry->data; 95 96 /* Enable aux port to allow programming */ 97 err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); 98 printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err); 99 if (err != 0) 100 goto abort; 101 102 /* Program data */ 103 first_block = (fw_entry->data + 104 le16_to_cpu(hdr->headersize) + 105 le32_to_cpu(hdr->block_offset)); 106 end = fw_entry->data + fw_entry->size; 107 108 err = hermes_program(hw, first_block, end); 109 printk(KERN_DEBUG "%s: Program returned %d\n", dev->name, err); 110 if (err != 0) 111 goto abort; 112 113 /* Update production data */ 114 first_block = (fw_entry->data + 115 le16_to_cpu(hdr->headersize) + 116 le32_to_cpu(hdr->pdr_offset)); 117 118 err = hermes_apply_pda_with_defaults(hw, first_block, pda); 119 printk(KERN_DEBUG "%s: Apply PDA returned %d\n", dev->name, err); 120 if (err) 121 goto abort; 122 123 /* Tell card we've finished */ 124 err = hermesi_program_end(hw); 125 printk(KERN_DEBUG "%s: Program end returned %d\n", dev->name, err); 126 if (err != 0) 127 goto abort; 128 129 /* Check if we're running */ 130 printk(KERN_DEBUG "%s: hermes_present returned %d\n", 131 dev->name, hermes_present(hw)); 132 133abort: 134 /* If we requested the firmware, release it. */ 135 if (!priv->cached_fw) 136 release_firmware(fw_entry); 137 138free: 139 kfree(pda); 140 return err; 141} 142 143/* 144 * Process a firmware image - stop the card, load the firmware, reset 145 * the card and make sure it responds. For the secondary firmware take 146 * care of the PDA - read it and then write it on top of the firmware. 147 */ 148static int 149symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw, 150 const unsigned char *image, const unsigned char *end, 151 int secondary) 152{ 153 hermes_t *hw = &priv->hw; 154 int ret = 0; 155 const unsigned char *ptr; 156 const unsigned char *first_block; 157 158 /* Plug Data Area (PDA) */ 159 __le16 *pda = NULL; 160 161 /* Binary block begins after the 0x1A marker */ 162 ptr = image; 163 while (*ptr++ != TEXT_END); 164 first_block = ptr; 165 166 /* Read the PDA from EEPROM */ 167 if (secondary) { 168 pda = kzalloc(fw->pda_size, GFP_KERNEL); 169 if (!pda) 170 return -ENOMEM; 171 172 ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1); 173 if (ret) 174 goto free; 175 } 176 177 /* Stop the firmware, so that it can be safely rewritten */ 178 if (priv->stop_fw) { 179 ret = priv->stop_fw(priv, 1); 180 if (ret) 181 goto free; 182 } 183 184 /* Program the adapter with new firmware */ 185 ret = hermes_program(hw, first_block, end); 186 if (ret) 187 goto free; 188 189 /* Write the PDA to the adapter */ 190 if (secondary) { 191 size_t len = hermes_blocks_length(first_block); 192 ptr = first_block + len; 193 ret = hermes_apply_pda(hw, ptr, pda); 194 kfree(pda); 195 if (ret) 196 return ret; 197 } 198 199 /* Run the firmware */ 200 if (priv->stop_fw) { 201 ret = priv->stop_fw(priv, 0); 202 if (ret) 203 return ret; 204 } 205 206 /* Reset hermes chip and make sure it responds */ 207 ret = hermes_init(hw); 208 209 /* hermes_reset() should return 0 with the secondary firmware */ 210 if (secondary && ret != 0) 211 return -ENODEV; 212 213 /* And this should work with any firmware */ 214 if (!hermes_present(hw)) 215 return -ENODEV; 216 217 return 0; 218 219free: 220 kfree(pda); 221 return ret; 222} 223 224 225/* 226 * Download the firmware into the card, this also does a PCMCIA soft 227 * reset on the card, to make sure it's in a sane state. 228 */ 229static int 230symbol_dl_firmware(struct orinoco_private *priv, 231 const struct fw_info *fw) 232{ 233 struct net_device *dev = priv->ndev; 234 int ret; 235 const struct firmware *fw_entry; 236 237 if (!priv->cached_pri_fw) { 238 if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { 239 printk(KERN_ERR "%s: Cannot find firmware: %s\n", 240 dev->name, fw->pri_fw); 241 return -ENOENT; 242 } 243 } else 244 fw_entry = priv->cached_pri_fw; 245 246 /* Load primary firmware */ 247 ret = symbol_dl_image(priv, fw, fw_entry->data, 248 fw_entry->data + fw_entry->size, 0); 249 250 if (!priv->cached_pri_fw) 251 release_firmware(fw_entry); 252 if (ret) { 253 printk(KERN_ERR "%s: Primary firmware download failed\n", 254 dev->name); 255 return ret; 256 } 257 258 if (!priv->cached_fw) { 259 if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { 260 printk(KERN_ERR "%s: Cannot find firmware: %s\n", 261 dev->name, fw->sta_fw); 262 return -ENOENT; 263 } 264 } else 265 fw_entry = priv->cached_fw; 266 267 /* Load secondary firmware */ 268 ret = symbol_dl_image(priv, fw, fw_entry->data, 269 fw_entry->data + fw_entry->size, 1); 270 if (!priv->cached_fw) 271 release_firmware(fw_entry); 272 if (ret) { 273 printk(KERN_ERR "%s: Secondary firmware download failed\n", 274 dev->name); 275 } 276 277 return ret; 278} 279 280int orinoco_download(struct orinoco_private *priv) 281{ 282 int err = 0; 283 /* Reload firmware */ 284 switch (priv->firmware_type) { 285 case FIRMWARE_TYPE_AGERE: 286 /* case FIRMWARE_TYPE_INTERSIL: */ 287 err = orinoco_dl_firmware(priv, 288 &orinoco_fw[priv->firmware_type], 0); 289 break; 290 291 case FIRMWARE_TYPE_SYMBOL: 292 err = symbol_dl_firmware(priv, 293 &orinoco_fw[priv->firmware_type]); 294 break; 295 case FIRMWARE_TYPE_INTERSIL: 296 break; 297 } 298 /* TODO: if we fail we probably need to reinitialise 299 * the driver */ 300 301 return err; 302} 303 304void orinoco_cache_fw(struct orinoco_private *priv, int ap) 305{ 306#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) 307 const struct firmware *fw_entry = NULL; 308 const char *pri_fw; 309 const char *fw; 310 311 pri_fw = orinoco_fw[priv->firmware_type].pri_fw; 312 if (ap) 313 fw = orinoco_fw[priv->firmware_type].ap_fw; 314 else 315 fw = orinoco_fw[priv->firmware_type].sta_fw; 316 317 if (pri_fw) { 318 if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0) 319 priv->cached_pri_fw = fw_entry; 320 } 321 322 if (fw) { 323 if (request_firmware(&fw_entry, fw, priv->dev) == 0) 324 priv->cached_fw = fw_entry; 325 } 326#endif 327} 328 329void orinoco_uncache_fw(struct orinoco_private *priv) 330{ 331#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) 332 if (priv->cached_pri_fw) 333 release_firmware(priv->cached_pri_fw); 334 if (priv->cached_fw) 335 release_firmware(priv->cached_fw); 336 337 priv->cached_pri_fw = NULL; 338 priv->cached_fw = NULL; 339#endif 340} 341