Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

orinoco: Move firmware download functionality into new module

Move the functionality from spectrum_cs to hermes_dld in preparation for
making it more generic and usable by other orinoco drivers.

Signed-off-by: David Kilroy <kilroyd@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

David Kilroy and committed by
John W. Linville
f482eb79 fc5a62d8

+385 -274
+1 -1
drivers/net/wireless/Makefile
··· 16 16 obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o 17 17 obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o 18 18 19 - obj-$(CONFIG_HERMES) += orinoco.o hermes.o 19 + obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o 20 20 obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o 21 21 obj-$(CONFIG_APPLE_AIRPORT) += airport.o 22 22 obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
+338
drivers/net/wireless/hermes_dld.c
··· 1 + /* 2 + * Hermes download helper driver. 3 + * 4 + * This could be entirely merged into hermes.c. 5 + * 6 + * I'm keeping it separate to minimise the amount of merging between 7 + * kernel upgrades. It also means the memory overhead for drivers that 8 + * don't need firmware download low. 9 + * 10 + * This driver: 11 + * - is capable of writing to the volatile area of the hermes device 12 + * - is currently not capable of writing to non-volatile areas 13 + * - provide helpers to identify and update plugin data 14 + * - is not capable of interpreting a fw image directly. That is up to 15 + * the main card driver. 16 + * - deals with Hermes I devices. It can probably be modified to deal 17 + * with Hermes II devices 18 + * 19 + * Copyright (C) 2007, David Kilroy 20 + * 21 + * Plug data code slightly modified from spectrum_cs driver 22 + * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org> 23 + * Portions based on information in wl_lkm_718 Agere driver 24 + * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved 25 + * 26 + * The contents of this file are subject to the Mozilla Public License 27 + * Version 1.1 (the "License"); you may not use this file except in 28 + * compliance with the License. You may obtain a copy of the License 29 + * at http://www.mozilla.org/MPL/ 30 + * 31 + * Software distributed under the License is distributed on an "AS IS" 32 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 33 + * the License for the specific language governing rights and 34 + * limitations under the License. 35 + * 36 + * Alternatively, the contents of this file may be used under the 37 + * terms of the GNU General Public License version 2 (the "GPL"), in 38 + * which case the provisions of the GPL are applicable instead of the 39 + * above. If you wish to allow the use of your version of this file 40 + * only under the terms of the GPL and not to allow others to use your 41 + * version of this file under the MPL, indicate your decision by 42 + * deleting the provisions above and replace them with the notice and 43 + * other provisions required by the GPL. If you do not delete the 44 + * provisions above, a recipient may use your version of this file 45 + * under either the MPL or the GPL. 46 + */ 47 + 48 + #include <linux/module.h> 49 + #include <linux/delay.h> 50 + #include "hermes.h" 51 + #include "hermes_dld.h" 52 + 53 + MODULE_DESCRIPTION("Download helper for Lucent Hermes chipset"); 54 + MODULE_AUTHOR("David Kilroy <kilroyd@gmail.com>"); 55 + MODULE_LICENSE("Dual MPL/GPL"); 56 + 57 + #define PFX "hermes_dld: " 58 + 59 + /* 60 + * AUX port access. To unlock the AUX port write the access keys to the 61 + * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL 62 + * register. Then read it and make sure it's HERMES_AUX_ENABLED. 63 + */ 64 + #define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ 65 + #define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ 66 + #define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ 67 + 68 + #define HERMES_AUX_PW0 0xFE01 69 + #define HERMES_AUX_PW1 0xDC23 70 + #define HERMES_AUX_PW2 0xBA45 71 + 72 + /* End markers */ 73 + #define PDI_END 0x00000000 /* End of PDA */ 74 + #define BLOCK_END 0xFFFFFFFF /* Last image block */ 75 + 76 + /* 77 + * The following structures have little-endian fields denoted by 78 + * the leading underscore. Don't access them directly - use inline 79 + * functions defined below. 80 + */ 81 + 82 + /* 83 + * The binary image to be downloaded consists of series of data blocks. 84 + * Each block has the following structure. 85 + */ 86 + struct dblock { 87 + __le32 addr; /* adapter address where to write the block */ 88 + __le16 len; /* length of the data only, in bytes */ 89 + char data[0]; /* data to be written */ 90 + } __attribute__ ((packed)); 91 + 92 + /* 93 + * Plug Data References are located in in the image after the last data 94 + * block. They refer to areas in the adapter memory where the plug data 95 + * items with matching ID should be written. 96 + */ 97 + struct pdr { 98 + __le32 id; /* record ID */ 99 + __le32 addr; /* adapter address where to write the data */ 100 + __le32 len; /* expected length of the data, in bytes */ 101 + char next[0]; /* next PDR starts here */ 102 + } __attribute__ ((packed)); 103 + 104 + /* 105 + * Plug Data Items are located in the EEPROM read from the adapter by 106 + * primary firmware. They refer to the device-specific data that should 107 + * be plugged into the secondary firmware. 108 + */ 109 + struct pdi { 110 + __le16 len; /* length of ID and data, in words */ 111 + __le16 id; /* record ID */ 112 + char data[0]; /* plug data */ 113 + } __attribute__ ((packed)); 114 + 115 + /* Functions for access to little-endian data */ 116 + static inline u32 117 + dblock_addr(const struct dblock *blk) 118 + { 119 + return le32_to_cpu(blk->addr); 120 + } 121 + 122 + static inline u32 123 + dblock_len(const struct dblock *blk) 124 + { 125 + return le16_to_cpu(blk->len); 126 + } 127 + 128 + static inline u32 129 + pdr_id(const struct pdr *pdr) 130 + { 131 + return le32_to_cpu(pdr->id); 132 + } 133 + 134 + static inline u32 135 + pdr_addr(const struct pdr *pdr) 136 + { 137 + return le32_to_cpu(pdr->addr); 138 + } 139 + 140 + static inline u32 141 + pdr_len(const struct pdr *pdr) 142 + { 143 + return le32_to_cpu(pdr->len); 144 + } 145 + 146 + static inline u32 147 + pdi_id(const struct pdi *pdi) 148 + { 149 + return le16_to_cpu(pdi->id); 150 + } 151 + 152 + /* Return length of the data only, in bytes */ 153 + static inline u32 154 + pdi_len(const struct pdi *pdi) 155 + { 156 + return 2 * (le16_to_cpu(pdi->len) - 1); 157 + } 158 + 159 + /* Set address of the auxiliary port */ 160 + static inline void 161 + spectrum_aux_setaddr(hermes_t *hw, u32 addr) 162 + { 163 + hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); 164 + hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); 165 + } 166 + 167 + /* Open access to the auxiliary port */ 168 + static int 169 + spectrum_aux_open(hermes_t *hw) 170 + { 171 + int i; 172 + 173 + /* Already open? */ 174 + if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED) 175 + return 0; 176 + 177 + hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); 178 + hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); 179 + hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); 180 + hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE); 181 + 182 + for (i = 0; i < 20; i++) { 183 + udelay(10); 184 + if (hermes_read_reg(hw, HERMES_CONTROL) == 185 + HERMES_AUX_ENABLED) 186 + return 0; 187 + } 188 + 189 + return -EBUSY; 190 + } 191 + 192 + /* 193 + * Scan PDR for the record with the specified RECORD_ID. 194 + * If it's not found, return NULL. 195 + */ 196 + static struct pdr * 197 + spectrum_find_pdr(struct pdr *first_pdr, u32 record_id) 198 + { 199 + struct pdr *pdr = first_pdr; 200 + 201 + while (pdr_id(pdr) != PDI_END) { 202 + /* 203 + * PDR area is currently not terminated by PDI_END. 204 + * It's followed by CRC records, which have the type 205 + * field where PDR has length. The type can be 0 or 1. 206 + */ 207 + if (pdr_len(pdr) < 2) 208 + return NULL; 209 + 210 + /* If the record ID matches, we are done */ 211 + if (pdr_id(pdr) == record_id) 212 + return pdr; 213 + 214 + pdr = (struct pdr *) pdr->next; 215 + } 216 + return NULL; 217 + } 218 + 219 + /* Process one Plug Data Item - find corresponding PDR and plug it */ 220 + static int 221 + spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) 222 + { 223 + struct pdr *pdr; 224 + 225 + /* Find the PDI corresponding to this PDR */ 226 + pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi)); 227 + 228 + /* No match is found, safe to ignore */ 229 + if (!pdr) 230 + return 0; 231 + 232 + /* Lengths of the data in PDI and PDR must match */ 233 + if (pdi_len(pdi) != pdr_len(pdr)) 234 + return -EINVAL; 235 + 236 + /* do the actual plugging */ 237 + spectrum_aux_setaddr(hw, pdr_addr(pdr)); 238 + hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); 239 + 240 + return 0; 241 + } 242 + 243 + /* Read PDA from the adapter */ 244 + int 245 + spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len) 246 + { 247 + int ret; 248 + int pda_size; 249 + 250 + /* Issue command to read EEPROM */ 251 + ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); 252 + if (ret) 253 + return ret; 254 + 255 + /* Open auxiliary port */ 256 + ret = spectrum_aux_open(hw); 257 + if (ret) 258 + return ret; 259 + 260 + /* read PDA from EEPROM */ 261 + spectrum_aux_setaddr(hw, PDA_ADDR); 262 + hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2); 263 + 264 + /* Check PDA length */ 265 + pda_size = le16_to_cpu(pda[0]); 266 + if (pda_size > pda_len) 267 + return -EINVAL; 268 + 269 + return 0; 270 + } 271 + EXPORT_SYMBOL(spectrum_read_pda); 272 + 273 + /* Parse PDA and write the records into the adapter */ 274 + int 275 + spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, 276 + __le16 *pda) 277 + { 278 + int ret; 279 + struct pdi *pdi; 280 + struct pdr *first_pdr; 281 + const struct dblock *blk = first_block; 282 + 283 + /* Skip all blocks to locate Plug Data References */ 284 + while (dblock_addr(blk) != BLOCK_END) 285 + blk = (struct dblock *) &blk->data[dblock_len(blk)]; 286 + 287 + first_pdr = (struct pdr *) blk; 288 + 289 + /* Go through every PDI and plug them into the adapter */ 290 + pdi = (struct pdi *) (pda + 2); 291 + while (pdi_id(pdi) != PDI_END) { 292 + ret = spectrum_plug_pdi(hw, first_pdr, pdi); 293 + if (ret) 294 + return ret; 295 + 296 + /* Increment to the next PDI */ 297 + pdi = (struct pdi *) &pdi->data[pdi_len(pdi)]; 298 + } 299 + return 0; 300 + } 301 + EXPORT_SYMBOL(spectrum_apply_pda); 302 + 303 + /* Load firmware blocks into the adapter */ 304 + int 305 + spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) 306 + { 307 + const struct dblock *blk; 308 + u32 blkaddr; 309 + u32 blklen; 310 + 311 + blk = first_block; 312 + blkaddr = dblock_addr(blk); 313 + blklen = dblock_len(blk); 314 + 315 + while (dblock_addr(blk) != BLOCK_END) { 316 + spectrum_aux_setaddr(hw, blkaddr); 317 + hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, 318 + blklen); 319 + 320 + blk = (struct dblock *) &blk->data[blklen]; 321 + blkaddr = dblock_addr(blk); 322 + blklen = dblock_len(blk); 323 + } 324 + return 0; 325 + } 326 + EXPORT_SYMBOL(spectrum_load_blocks); 327 + 328 + static int __init init_hermes_dld(void) 329 + { 330 + return 0; 331 + } 332 + 333 + static void __exit exit_hermes_dld(void) 334 + { 335 + } 336 + 337 + module_init(init_hermes_dld); 338 + module_exit(exit_hermes_dld);
+45
drivers/net/wireless/hermes_dld.h
··· 1 + /* 2 + * Copyright (C) 2007, David Kilroy 3 + * 4 + * The contents of this file are subject to the Mozilla Public License 5 + * Version 1.1 (the "License"); you may not use this file except in 6 + * compliance with the License. You may obtain a copy of the License 7 + * at http://www.mozilla.org/MPL/ 8 + * 9 + * Software distributed under the License is distributed on an "AS IS" 10 + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11 + * the License for the specific language governing rights and 12 + * limitations under the License. 13 + * 14 + * Alternatively, the contents of this file may be used under the 15 + * terms of the GNU General Public License version 2 (the "GPL"), in 16 + * which case the provisions of the GPL are applicable instead of the 17 + * above. If you wish to allow the use of your version of this file 18 + * only under the terms of the GPL and not to allow others to use your 19 + * version of this file under the MPL, indicate your decision by 20 + * deleting the provisions above and replace them with the notice and 21 + * other provisions required by the GPL. If you do not delete the 22 + * provisions above, a recipient may use your version of this file 23 + * under either the MPL or the GPL. 24 + */ 25 + #ifndef _HERMES_DLD_H 26 + #define _HERMES_DLD_H 27 + 28 + #include "hermes.h" 29 + 30 + /* Position of PDA in the adapter memory */ 31 + #define EEPROM_ADDR 0x3000 32 + #define EEPROM_LEN 0x200 33 + #define PDA_OFFSET 0x100 34 + 35 + #define PDA_ADDR (EEPROM_ADDR + PDA_OFFSET) 36 + #define PDA_WORDS ((EEPROM_LEN - PDA_OFFSET) / 2) 37 + 38 + struct dblock; 39 + 40 + int spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len); 41 + int spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, 42 + __le16 *pda); 43 + int spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block); 44 + 45 + #endif /* _HERMES_DLD_H */
+1 -273
drivers/net/wireless/spectrum_cs.c
··· 33 33 #include <pcmcia/ds.h> 34 34 35 35 #include "orinoco.h" 36 + #include "hermes_dld.h" 36 37 37 38 static const char primary_fw_name[] = "symbol_sp24t_prim_fw"; 38 39 static const char secondary_fw_name[] = "symbol_sp24t_sec_fw"; ··· 89 88 #define HCR_IDLE 0x0E /* don't run firmware after reset */ 90 89 #define HCR_MEM16 0x10 /* memory width bit, should be preserved */ 91 90 92 - /* 93 - * AUX port access. To unlock the AUX port write the access keys to the 94 - * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL 95 - * register. Then read it and make sure it's HERMES_AUX_ENABLED. 96 - */ 97 - #define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ 98 - #define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ 99 - #define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ 100 - 101 - #define HERMES_AUX_PW0 0xFE01 102 - #define HERMES_AUX_PW1 0xDC23 103 - #define HERMES_AUX_PW2 0xBA45 104 - 105 91 /* End markers */ 106 - #define PDI_END 0x00000000 /* End of PDA */ 107 - #define BLOCK_END 0xFFFFFFFF /* Last image block */ 108 92 #define TEXT_END 0x1A /* End of text header */ 109 - 110 - /* 111 - * The following structures have little-endian fields denoted by 112 - * the leading underscore. Don't access them directly - use inline 113 - * functions defined below. 114 - */ 115 - 116 - /* 117 - * The binary image to be downloaded consists of series of data blocks. 118 - * Each block has the following structure. 119 - */ 120 - struct dblock { 121 - __le32 addr; /* adapter address where to write the block */ 122 - __le16 len; /* length of the data only, in bytes */ 123 - char data[0]; /* data to be written */ 124 - } __attribute__ ((packed)); 125 - 126 - /* 127 - * Plug Data References are located in in the image after the last data 128 - * block. They refer to areas in the adapter memory where the plug data 129 - * items with matching ID should be written. 130 - */ 131 - struct pdr { 132 - __le32 id; /* record ID */ 133 - __le32 addr; /* adapter address where to write the data */ 134 - __le32 len; /* expected length of the data, in bytes */ 135 - char next[0]; /* next PDR starts here */ 136 - } __attribute__ ((packed)); 137 - 138 - 139 - /* 140 - * Plug Data Items are located in the EEPROM read from the adapter by 141 - * primary firmware. They refer to the device-specific data that should 142 - * be plugged into the secondary firmware. 143 - */ 144 - struct pdi { 145 - __le16 len; /* length of ID and data, in words */ 146 - __le16 id; /* record ID */ 147 - char data[0]; /* plug data */ 148 - } __attribute__ ((packed)); 149 - 150 - 151 - /* Functions for access to little-endian data */ 152 - static inline u32 153 - dblock_addr(const struct dblock *blk) 154 - { 155 - return le32_to_cpu(blk->addr); 156 - } 157 - 158 - static inline u32 159 - dblock_len(const struct dblock *blk) 160 - { 161 - return le16_to_cpu(blk->len); 162 - } 163 - 164 - static inline u32 165 - pdr_id(const struct pdr *pdr) 166 - { 167 - return le32_to_cpu(pdr->id); 168 - } 169 - 170 - static inline u32 171 - pdr_addr(const struct pdr *pdr) 172 - { 173 - return le32_to_cpu(pdr->addr); 174 - } 175 - 176 - static inline u32 177 - pdr_len(const struct pdr *pdr) 178 - { 179 - return le32_to_cpu(pdr->len); 180 - } 181 - 182 - static inline u32 183 - pdi_id(const struct pdi *pdi) 184 - { 185 - return le16_to_cpu(pdi->id); 186 - } 187 - 188 - /* Return length of the data only, in bytes */ 189 - static inline u32 190 - pdi_len(const struct pdi *pdi) 191 - { 192 - return 2 * (le16_to_cpu(pdi->len) - 1); 193 - } 194 - 195 - 196 - /* Set address of the auxiliary port */ 197 - static inline void 198 - spectrum_aux_setaddr(hermes_t *hw, u32 addr) 199 - { 200 - hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); 201 - hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); 202 - } 203 - 204 - 205 - /* Open access to the auxiliary port */ 206 - static int 207 - spectrum_aux_open(hermes_t *hw) 208 - { 209 - int i; 210 - 211 - /* Already open? */ 212 - if (hermes_read_reg(hw, HERMES_CONTROL) == HERMES_AUX_ENABLED) 213 - return 0; 214 - 215 - hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); 216 - hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); 217 - hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); 218 - hermes_write_reg(hw, HERMES_CONTROL, HERMES_AUX_ENABLE); 219 - 220 - for (i = 0; i < 20; i++) { 221 - udelay(10); 222 - if (hermes_read_reg(hw, HERMES_CONTROL) == 223 - HERMES_AUX_ENABLED) 224 - return 0; 225 - } 226 - 227 - return -EBUSY; 228 - } 229 93 230 94 231 95 #define CS_CHECK(fn, ret) \ ··· 156 290 cs_failed: 157 291 cs_error(link, last_fn, last_ret); 158 292 return -ENODEV; 159 - } 160 - 161 - 162 - /* 163 - * Scan PDR for the record with the specified RECORD_ID. 164 - * If it's not found, return NULL. 165 - */ 166 - static struct pdr * 167 - spectrum_find_pdr(struct pdr *first_pdr, u32 record_id) 168 - { 169 - struct pdr *pdr = first_pdr; 170 - 171 - while (pdr_id(pdr) != PDI_END) { 172 - /* 173 - * PDR area is currently not terminated by PDI_END. 174 - * It's followed by CRC records, which have the type 175 - * field where PDR has length. The type can be 0 or 1. 176 - */ 177 - if (pdr_len(pdr) < 2) 178 - return NULL; 179 - 180 - /* If the record ID matches, we are done */ 181 - if (pdr_id(pdr) == record_id) 182 - return pdr; 183 - 184 - pdr = (struct pdr *) pdr->next; 185 - } 186 - return NULL; 187 - } 188 - 189 - 190 - /* Process one Plug Data Item - find corresponding PDR and plug it */ 191 - static int 192 - spectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi) 193 - { 194 - struct pdr *pdr; 195 - 196 - /* Find the PDI corresponding to this PDR */ 197 - pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi)); 198 - 199 - /* No match is found, safe to ignore */ 200 - if (!pdr) 201 - return 0; 202 - 203 - /* Lengths of the data in PDI and PDR must match */ 204 - if (pdi_len(pdi) != pdr_len(pdr)) 205 - return -EINVAL; 206 - 207 - /* do the actual plugging */ 208 - spectrum_aux_setaddr(hw, pdr_addr(pdr)); 209 - hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); 210 - 211 - return 0; 212 - } 213 - 214 - 215 - /* Read PDA from the adapter */ 216 - static int 217 - spectrum_read_pda(hermes_t *hw, __le16 *pda, int pda_len) 218 - { 219 - int ret; 220 - int pda_size; 221 - 222 - /* Issue command to read EEPROM */ 223 - ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); 224 - if (ret) 225 - return ret; 226 - 227 - /* Open auxiliary port */ 228 - ret = spectrum_aux_open(hw); 229 - if (ret) 230 - return ret; 231 - 232 - /* read PDA from EEPROM */ 233 - spectrum_aux_setaddr(hw, PDA_ADDR); 234 - hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2); 235 - 236 - /* Check PDA length */ 237 - pda_size = le16_to_cpu(pda[0]); 238 - if (pda_size > pda_len) 239 - return -EINVAL; 240 - 241 - return 0; 242 - } 243 - 244 - 245 - /* Parse PDA and write the records into the adapter */ 246 - static int 247 - spectrum_apply_pda(hermes_t *hw, const struct dblock *first_block, 248 - __le16 *pda) 249 - { 250 - int ret; 251 - struct pdi *pdi; 252 - struct pdr *first_pdr; 253 - const struct dblock *blk = first_block; 254 - 255 - /* Skip all blocks to locate Plug Data References */ 256 - while (dblock_addr(blk) != BLOCK_END) 257 - blk = (struct dblock *) &blk->data[dblock_len(blk)]; 258 - 259 - first_pdr = (struct pdr *) blk; 260 - 261 - /* Go through every PDI and plug them into the adapter */ 262 - pdi = (struct pdi *) (pda + 2); 263 - while (pdi_id(pdi) != PDI_END) { 264 - ret = spectrum_plug_pdi(hw, first_pdr, pdi); 265 - if (ret) 266 - return ret; 267 - 268 - /* Increment to the next PDI */ 269 - pdi = (struct pdi *) &pdi->data[pdi_len(pdi)]; 270 - } 271 - return 0; 272 - } 273 - 274 - 275 - /* Load firmware blocks into the adapter */ 276 - static int 277 - spectrum_load_blocks(hermes_t *hw, const struct dblock *first_block) 278 - { 279 - const struct dblock *blk; 280 - u32 blkaddr; 281 - u32 blklen; 282 - 283 - blk = first_block; 284 - blkaddr = dblock_addr(blk); 285 - blklen = dblock_len(blk); 286 - 287 - while (dblock_addr(blk) != BLOCK_END) { 288 - spectrum_aux_setaddr(hw, blkaddr); 289 - hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, 290 - blklen); 291 - 292 - blk = (struct dblock *) &blk->data[blklen]; 293 - blkaddr = dblock_addr(blk); 294 - blklen = dblock_len(blk); 295 - } 296 - return 0; 297 293 } 298 294 299 295