root/drivers/net/wireless/intersil/hostap/hostap_download.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prism2_enable_aux_port
  2. hfa384x_from_aux
  3. hfa384x_to_aux
  4. prism2_pda_ok
  5. prism2_download_aux_dump_proc_show
  6. prism2_download_aux_dump_proc_start
  7. prism2_download_aux_dump_proc_next
  8. prism2_download_aux_dump_proc_stop
  9. prism2_download_aux_dump_proc_open
  10. prism2_read_pda
  11. prism2_download_volatile
  12. prism2_enable_genesis
  13. prism2_get_ram_size
  14. prism2_download_genesis
  15. prism2_download_block
  16. prism2_download_nonvolatile
  17. prism2_download_free_data
  18. prism2_download

   1 // SPDX-License-Identifier: GPL-2.0
   2 static int prism2_enable_aux_port(struct net_device *dev, int enable)
   3 {
   4         u16 val, reg;
   5         int i, tries;
   6         unsigned long flags;
   7         struct hostap_interface *iface;
   8         local_info_t *local;
   9 
  10         iface = netdev_priv(dev);
  11         local = iface->local;
  12 
  13         if (local->no_pri) {
  14                 if (enable) {
  15                         PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux "
  16                                "port is already enabled\n", dev->name);
  17                 }
  18                 return 0;
  19         }
  20 
  21         spin_lock_irqsave(&local->cmdlock, flags);
  22 
  23         /* wait until busy bit is clear */
  24         tries = HFA384X_CMD_BUSY_TIMEOUT;
  25         while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) {
  26                 tries--;
  27                 udelay(1);
  28         }
  29         if (tries == 0) {
  30                 reg = HFA384X_INW(HFA384X_CMD_OFF);
  31                 spin_unlock_irqrestore(&local->cmdlock, flags);
  32                 printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n",
  33                        dev->name, reg);
  34                 return -ETIMEDOUT;
  35         }
  36 
  37         val = HFA384X_INW(HFA384X_CONTROL_OFF);
  38 
  39         if (enable) {
  40                 HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF);
  41                 HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF);
  42                 HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF);
  43 
  44                 if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED)
  45                         printk("prism2_enable_aux_port: was not disabled!?\n");
  46                 val &= ~HFA384X_AUX_PORT_MASK;
  47                 val |= HFA384X_AUX_PORT_ENABLE;
  48         } else {
  49                 HFA384X_OUTW(0, HFA384X_PARAM0_OFF);
  50                 HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
  51                 HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
  52 
  53                 if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED)
  54                         printk("prism2_enable_aux_port: was not enabled!?\n");
  55                 val &= ~HFA384X_AUX_PORT_MASK;
  56                 val |= HFA384X_AUX_PORT_DISABLE;
  57         }
  58         HFA384X_OUTW(val, HFA384X_CONTROL_OFF);
  59 
  60         udelay(5);
  61 
  62         i = 10000;
  63         while (i > 0) {
  64                 val = HFA384X_INW(HFA384X_CONTROL_OFF);
  65                 val &= HFA384X_AUX_PORT_MASK;
  66 
  67                 if ((enable && val == HFA384X_AUX_PORT_ENABLED) ||
  68                     (!enable && val == HFA384X_AUX_PORT_DISABLED))
  69                         break;
  70 
  71                 udelay(10);
  72                 i--;
  73         }
  74 
  75         spin_unlock_irqrestore(&local->cmdlock, flags);
  76 
  77         if (i == 0) {
  78                 printk("prism2_enable_aux_port(%d) timed out\n",
  79                        enable);
  80                 return -ETIMEDOUT;
  81         }
  82 
  83         return 0;
  84 }
  85 
  86 
  87 static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len,
  88                             void *buf)
  89 {
  90         u16 page, offset;
  91         if (addr & 1 || len & 1)
  92                 return -1;
  93 
  94         page = addr >> 7;
  95         offset = addr & 0x7f;
  96 
  97         HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
  98         HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
  99 
 100         udelay(5);
 101 
 102 #ifdef PRISM2_PCI
 103         {
 104                 __le16 *pos = (__le16 *) buf;
 105                 while (len > 0) {
 106                         *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF);
 107                         len -= 2;
 108                 }
 109         }
 110 #else /* PRISM2_PCI */
 111         HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2);
 112 #endif /* PRISM2_PCI */
 113 
 114         return 0;
 115 }
 116 
 117 
 118 static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len,
 119                           void *buf)
 120 {
 121         u16 page, offset;
 122         if (addr & 1 || len & 1)
 123                 return -1;
 124 
 125         page = addr >> 7;
 126         offset = addr & 0x7f;
 127 
 128         HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF);
 129         HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF);
 130 
 131         udelay(5);
 132 
 133 #ifdef PRISM2_PCI
 134         {
 135                 __le16 *pos = (__le16 *) buf;
 136                 while (len > 0) {
 137                         HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF);
 138                         len -= 2;
 139                 }
 140         }
 141 #else /* PRISM2_PCI */
 142         HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2);
 143 #endif /* PRISM2_PCI */
 144 
 145         return 0;
 146 }
 147 
 148 
 149 static int prism2_pda_ok(u8 *buf)
 150 {
 151         __le16 *pda = (__le16 *) buf;
 152         int pos;
 153         u16 len, pdr;
 154 
 155         if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff &&
 156             buf[3] == 0x00)
 157                 return 0;
 158 
 159         pos = 0;
 160         while (pos + 1 < PRISM2_PDA_SIZE / 2) {
 161                 len = le16_to_cpu(pda[pos]);
 162                 pdr = le16_to_cpu(pda[pos + 1]);
 163                 if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2)
 164                         return 0;
 165 
 166                 if (pdr == 0x0000 && len == 2) {
 167                         /* PDA end found */
 168                         return 1;
 169                 }
 170 
 171                 pos += len + 1;
 172         }
 173 
 174         return 0;
 175 }
 176 
 177 
 178 #define prism2_download_aux_dump_npages 65536
 179 
 180 struct prism2_download_aux_dump {
 181         local_info_t *local;
 182         u16 page[0x80];
 183 };
 184 
 185 static int prism2_download_aux_dump_proc_show(struct seq_file *m, void *v)
 186 {
 187         struct prism2_download_aux_dump *ctx = m->private;
 188 
 189         hfa384x_from_aux(ctx->local->dev, (unsigned long)v - 1, 0x80, ctx->page);
 190         seq_write(m, ctx->page, 0x80);
 191         return 0;
 192 }
 193 
 194 static void *prism2_download_aux_dump_proc_start(struct seq_file *m, loff_t *_pos)
 195 {
 196         struct prism2_download_aux_dump *ctx = m->private;
 197         prism2_enable_aux_port(ctx->local->dev, 1);
 198         if (*_pos >= prism2_download_aux_dump_npages)
 199                 return NULL;
 200         return (void *)((unsigned long)*_pos + 1);
 201 }
 202 
 203 static void *prism2_download_aux_dump_proc_next(struct seq_file *m, void *v, loff_t *_pos)
 204 {
 205         ++*_pos;
 206         if (*_pos >= prism2_download_aux_dump_npages)
 207                 return NULL;
 208         return (void *)((unsigned long)*_pos + 1);
 209 }
 210 
 211 static void prism2_download_aux_dump_proc_stop(struct seq_file *m, void *v)
 212 {
 213         struct prism2_download_aux_dump *ctx = m->private;
 214         prism2_enable_aux_port(ctx->local->dev, 0);
 215 }
 216 
 217 static const struct seq_operations prism2_download_aux_dump_proc_seqops = {
 218         .start  = prism2_download_aux_dump_proc_start,
 219         .next   = prism2_download_aux_dump_proc_next,
 220         .stop   = prism2_download_aux_dump_proc_stop,
 221         .show   = prism2_download_aux_dump_proc_show,
 222 };
 223 
 224 static int prism2_download_aux_dump_proc_open(struct inode *inode, struct file *file)
 225 {
 226         int ret = seq_open_private(file, &prism2_download_aux_dump_proc_seqops,
 227                                    sizeof(struct prism2_download_aux_dump));
 228         if (ret == 0) {
 229                 struct seq_file *m = file->private_data;
 230                 m->private = PDE_DATA(inode);
 231         }
 232         return ret;
 233 }
 234 
 235 static const struct file_operations prism2_download_aux_dump_proc_fops = {
 236         .open           = prism2_download_aux_dump_proc_open,
 237         .read           = seq_read,
 238         .llseek         = seq_lseek,
 239         .release        = seq_release_private,
 240 };
 241 
 242 
 243 static u8 * prism2_read_pda(struct net_device *dev)
 244 {
 245         u8 *buf;
 246         int res, i, found = 0;
 247 #define NUM_PDA_ADDRS 4
 248         unsigned int pda_addr[NUM_PDA_ADDRS] = {
 249                 0x7f0000 /* others than HFA3841 */,
 250                 0x3f0000 /* HFA3841 */,
 251                 0x390000 /* apparently used in older cards */,
 252                 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */,
 253         };
 254 
 255         buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL);
 256         if (buf == NULL)
 257                 return NULL;
 258 
 259         /* Note: wlan card should be in initial state (just after init cmd)
 260          * and no other operations should be performed concurrently. */
 261 
 262         prism2_enable_aux_port(dev, 1);
 263 
 264         for (i = 0; i < NUM_PDA_ADDRS; i++) {
 265                 PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x",
 266                        dev->name, pda_addr[i]);
 267                 res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf);
 268                 if (res)
 269                         continue;
 270                 if (res == 0 && prism2_pda_ok(buf)) {
 271                         PDEBUG2(DEBUG_EXTRA2, ": OK\n");
 272                         found = 1;
 273                         break;
 274                 } else {
 275                         PDEBUG2(DEBUG_EXTRA2, ": failed\n");
 276                 }
 277         }
 278 
 279         prism2_enable_aux_port(dev, 0);
 280 
 281         if (!found) {
 282                 printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name);
 283                 kfree(buf);
 284                 buf = NULL;
 285         }
 286 
 287         return buf;
 288 }
 289 
 290 
 291 static int prism2_download_volatile(local_info_t *local,
 292                                     struct prism2_download_data *param)
 293 {
 294         struct net_device *dev = local->dev;
 295         int ret = 0, i;
 296         u16 param0, param1;
 297 
 298         if (local->hw_downloading) {
 299                 printk(KERN_WARNING "%s: Already downloading - aborting new "
 300                        "request\n", dev->name);
 301                 return -1;
 302         }
 303 
 304         local->hw_downloading = 1;
 305         if (local->pri_only) {
 306                 hfa384x_disable_interrupts(dev);
 307         } else {
 308                 prism2_hw_shutdown(dev, 0);
 309 
 310                 if (prism2_hw_init(dev, 0)) {
 311                         printk(KERN_WARNING "%s: Could not initialize card for"
 312                                " download\n", dev->name);
 313                         ret = -1;
 314                         goto out;
 315                 }
 316         }
 317 
 318         if (prism2_enable_aux_port(dev, 1)) {
 319                 printk(KERN_WARNING "%s: Could not enable AUX port\n",
 320                        dev->name);
 321                 ret = -1;
 322                 goto out;
 323         }
 324 
 325         param0 = param->start_addr & 0xffff;
 326         param1 = param->start_addr >> 16;
 327 
 328         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 329         HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
 330         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 331                              (HFA384X_PROGMODE_ENABLE_VOLATILE << 8),
 332                              param0)) {
 333                 printk(KERN_WARNING "%s: Download command execution failed\n",
 334                        dev->name);
 335                 ret = -1;
 336                 goto out;
 337         }
 338 
 339         for (i = 0; i < param->num_areas; i++) {
 340                 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
 341                        dev->name, param->data[i].len, param->data[i].addr);
 342                 if (hfa384x_to_aux(dev, param->data[i].addr,
 343                                    param->data[i].len, param->data[i].data)) {
 344                         printk(KERN_WARNING "%s: RAM download at 0x%08x "
 345                                "(len=%d) failed\n", dev->name,
 346                                param->data[i].addr, param->data[i].len);
 347                         ret = -1;
 348                         goto out;
 349                 }
 350         }
 351 
 352         HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
 353         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 354         if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 355                                 (HFA384X_PROGMODE_DISABLE << 8), param0)) {
 356                 printk(KERN_WARNING "%s: Download command execution failed\n",
 357                        dev->name);
 358                 ret = -1;
 359                 goto out;
 360         }
 361         /* ProgMode disable causes the hardware to restart itself from the
 362          * given starting address. Give hw some time and ACK command just in
 363          * case restart did not happen. */
 364         mdelay(5);
 365         HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF);
 366 
 367         if (prism2_enable_aux_port(dev, 0)) {
 368                 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
 369                        dev->name);
 370                 /* continue anyway.. restart should have taken care of this */
 371         }
 372 
 373         mdelay(5);
 374         local->hw_downloading = 0;
 375         if (prism2_hw_config(dev, 2)) {
 376                 printk(KERN_WARNING "%s: Card configuration after RAM "
 377                        "download failed\n", dev->name);
 378                 ret = -1;
 379                 goto out;
 380         }
 381 
 382  out:
 383         local->hw_downloading = 0;
 384         return ret;
 385 }
 386 
 387 
 388 static int prism2_enable_genesis(local_info_t *local, int hcr)
 389 {
 390         struct net_device *dev = local->dev;
 391         u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff };
 392         u8 readbuf[4];
 393 
 394         printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n",
 395                dev->name, hcr);
 396         local->func->cor_sreset(local);
 397         hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
 398         local->func->genesis_reset(local, hcr);
 399 
 400         /* Readback test */
 401         hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
 402         hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq);
 403         hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf);
 404 
 405         if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) {
 406                 printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n",
 407                        hcr);
 408                 return 0;
 409         } else {
 410                 printk(KERN_DEBUG "Readback test failed, HCR 0x%02x write %4ph read %4ph\n",
 411                        hcr, initseq, readbuf);
 412                 return 1;
 413         }
 414 }
 415 
 416 
 417 static int prism2_get_ram_size(local_info_t *local)
 418 {
 419         int ret;
 420 
 421         /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
 422         if (prism2_enable_genesis(local, 0x1f) == 0)
 423                 ret = 8;
 424         else if (prism2_enable_genesis(local, 0x0f) == 0)
 425                 ret = 16;
 426         else
 427                 ret = -1;
 428 
 429         /* Disable genesis mode */
 430         local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
 431 
 432         return ret;
 433 }
 434 
 435 
 436 static int prism2_download_genesis(local_info_t *local,
 437                                    struct prism2_download_data *param)
 438 {
 439         struct net_device *dev = local->dev;
 440         int ram16 = 0, i;
 441         int ret = 0;
 442 
 443         if (local->hw_downloading) {
 444                 printk(KERN_WARNING "%s: Already downloading - aborting new "
 445                        "request\n", dev->name);
 446                 return -EBUSY;
 447         }
 448 
 449         if (!local->func->genesis_reset || !local->func->cor_sreset) {
 450                 printk(KERN_INFO "%s: Genesis mode downloading not supported "
 451                        "with this hwmodel\n", dev->name);
 452                 return -EOPNOTSUPP;
 453         }
 454 
 455         local->hw_downloading = 1;
 456 
 457         if (prism2_enable_aux_port(dev, 1)) {
 458                 printk(KERN_DEBUG "%s: failed to enable AUX port\n",
 459                        dev->name);
 460                 ret = -EIO;
 461                 goto out;
 462         }
 463 
 464         if (local->sram_type == -1) {
 465                 /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
 466                 if (prism2_enable_genesis(local, 0x1f) == 0) {
 467                         ram16 = 0;
 468                         PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
 469                                "SRAM\n", dev->name);
 470                 } else if (prism2_enable_genesis(local, 0x0f) == 0) {
 471                         ram16 = 1;
 472                         PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
 473                                "SRAM\n", dev->name);
 474                 } else {
 475                         printk(KERN_DEBUG "%s: Could not initiate genesis "
 476                                "mode\n", dev->name);
 477                         ret = -EIO;
 478                         goto out;
 479                 }
 480         } else {
 481                 if (prism2_enable_genesis(local, local->sram_type == 8 ?
 482                                           0x1f : 0x0f)) {
 483                         printk(KERN_DEBUG "%s: Failed to set Genesis "
 484                                "mode (sram_type=%d)\n", dev->name,
 485                                local->sram_type);
 486                         ret = -EIO;
 487                         goto out;
 488                 }
 489                 ram16 = local->sram_type != 8;
 490         }
 491 
 492         for (i = 0; i < param->num_areas; i++) {
 493                 PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
 494                        dev->name, param->data[i].len, param->data[i].addr);
 495                 if (hfa384x_to_aux(dev, param->data[i].addr,
 496                                    param->data[i].len, param->data[i].data)) {
 497                         printk(KERN_WARNING "%s: RAM download at 0x%08x "
 498                                "(len=%d) failed\n", dev->name,
 499                                param->data[i].addr, param->data[i].len);
 500                         ret = -EIO;
 501                         goto out;
 502                 }
 503         }
 504 
 505         PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
 506         local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
 507         if (prism2_enable_aux_port(dev, 0)) {
 508                 printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
 509                        dev->name);
 510         }
 511 
 512         mdelay(5);
 513         local->hw_downloading = 0;
 514 
 515         PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
 516         /*
 517          * Make sure the INIT command does not generate a command completion
 518          * event by disabling interrupts.
 519          */
 520         hfa384x_disable_interrupts(dev);
 521         if (prism2_hw_init(dev, 1)) {
 522                 printk(KERN_DEBUG "%s: Initialization after genesis mode "
 523                        "download failed\n", dev->name);
 524                 ret = -EIO;
 525                 goto out;
 526         }
 527 
 528         PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
 529         if (prism2_hw_init2(dev, 1)) {
 530                 printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
 531                        "download failed\n", dev->name);
 532                 ret = -EIO;
 533                 goto out;
 534         }
 535 
 536  out:
 537         local->hw_downloading = 0;
 538         return ret;
 539 }
 540 
 541 
 542 #ifdef PRISM2_NON_VOLATILE_DOWNLOAD
 543 /* Note! Non-volatile downloading functionality has not yet been tested
 544  * thoroughly and it may corrupt flash image and effectively kill the card that
 545  * is being updated. You have been warned. */
 546 
 547 static inline int prism2_download_block(struct net_device *dev,
 548                                         u32 addr, u8 *data,
 549                                         u32 bufaddr, int rest_len)
 550 {
 551         u16 param0, param1;
 552         int block_len;
 553 
 554         block_len = rest_len < 4096 ? rest_len : 4096;
 555 
 556         param0 = addr & 0xffff;
 557         param1 = addr >> 16;
 558 
 559         HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
 560         HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
 561 
 562         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 563                              (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
 564                              param0)) {
 565                 printk(KERN_WARNING "%s: Flash download command execution "
 566                        "failed\n", dev->name);
 567                 return -1;
 568         }
 569 
 570         if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
 571                 printk(KERN_WARNING "%s: flash download at 0x%08x "
 572                        "(len=%d) failed\n", dev->name, addr, block_len);
 573                 return -1;
 574         }
 575 
 576         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 577         HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
 578         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 579                              (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
 580                              0)) {
 581                 printk(KERN_WARNING "%s: Flash write command execution "
 582                        "failed\n", dev->name);
 583                 return -1;
 584         }
 585 
 586         return block_len;
 587 }
 588 
 589 
 590 static int prism2_download_nonvolatile(local_info_t *local,
 591                                        struct prism2_download_data *dl)
 592 {
 593         struct net_device *dev = local->dev;
 594         int ret = 0, i;
 595         struct {
 596                 __le16 page;
 597                 __le16 offset;
 598                 __le16 len;
 599         } dlbuffer;
 600         u32 bufaddr;
 601 
 602         if (local->hw_downloading) {
 603                 printk(KERN_WARNING "%s: Already downloading - aborting new "
 604                        "request\n", dev->name);
 605                 return -1;
 606         }
 607 
 608         ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
 609                                    &dlbuffer, 6, 0);
 610 
 611         if (ret < 0) {
 612                 printk(KERN_WARNING "%s: Could not read download buffer "
 613                        "parameters\n", dev->name);
 614                 goto out;
 615         }
 616 
 617         printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
 618                le16_to_cpu(dlbuffer.len),
 619                le16_to_cpu(dlbuffer.page),
 620                le16_to_cpu(dlbuffer.offset));
 621 
 622         bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
 623 
 624         local->hw_downloading = 1;
 625 
 626         if (!local->pri_only) {
 627                 prism2_hw_shutdown(dev, 0);
 628 
 629                 if (prism2_hw_init(dev, 0)) {
 630                         printk(KERN_WARNING "%s: Could not initialize card for"
 631                                " download\n", dev->name);
 632                         ret = -1;
 633                         goto out;
 634                 }
 635         }
 636 
 637         hfa384x_disable_interrupts(dev);
 638 
 639         if (prism2_enable_aux_port(dev, 1)) {
 640                 printk(KERN_WARNING "%s: Could not enable AUX port\n",
 641                        dev->name);
 642                 ret = -1;
 643                 goto out;
 644         }
 645 
 646         printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
 647         for (i = 0; i < dl->num_areas; i++) {
 648                 int rest_len = dl->data[i].len;
 649                 int data_off = 0;
 650 
 651                 while (rest_len > 0) {
 652                         int block_len;
 653 
 654                         block_len = prism2_download_block(
 655                                 dev, dl->data[i].addr + data_off,
 656                                 dl->data[i].data + data_off, bufaddr,
 657                                 rest_len);
 658 
 659                         if (block_len < 0) {
 660                                 ret = -1;
 661                                 goto out;
 662                         }
 663 
 664                         rest_len -= block_len;
 665                         data_off += block_len;
 666                 }
 667         }
 668 
 669         HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
 670         HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 671         if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 672                                 (HFA384X_PROGMODE_DISABLE << 8), 0)) {
 673                 printk(KERN_WARNING "%s: Download command execution failed\n",
 674                        dev->name);
 675                 ret = -1;
 676                 goto out;
 677         }
 678 
 679         if (prism2_enable_aux_port(dev, 0)) {
 680                 printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
 681                        dev->name);
 682                 /* continue anyway.. restart should have taken care of this */
 683         }
 684 
 685         mdelay(5);
 686 
 687         local->func->hw_reset(dev);
 688         local->hw_downloading = 0;
 689         if (prism2_hw_config(dev, 2)) {
 690                 printk(KERN_WARNING "%s: Card configuration after flash "
 691                        "download failed\n", dev->name);
 692                 ret = -1;
 693         } else {
 694                 printk(KERN_INFO "%s: Card initialized successfully after "
 695                        "flash download\n", dev->name);
 696         }
 697 
 698  out:
 699         local->hw_downloading = 0;
 700         return ret;
 701 }
 702 #endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
 703 
 704 
 705 static void prism2_download_free_data(struct prism2_download_data *dl)
 706 {
 707         int i;
 708 
 709         if (dl == NULL)
 710                 return;
 711 
 712         for (i = 0; i < dl->num_areas; i++)
 713                 kfree(dl->data[i].data);
 714         kfree(dl);
 715 }
 716 
 717 
 718 static int prism2_download(local_info_t *local,
 719                            struct prism2_download_param *param)
 720 {
 721         int ret = 0;
 722         int i;
 723         u32 total_len = 0;
 724         struct prism2_download_data *dl = NULL;
 725 
 726         printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
 727                "num_areas=%d\n",
 728                param->dl_cmd, param->start_addr, param->num_areas);
 729 
 730         if (param->num_areas > 100) {
 731                 ret = -EINVAL;
 732                 goto out;
 733         }
 734 
 735         dl = kzalloc(sizeof(*dl) + param->num_areas *
 736                      sizeof(struct prism2_download_data_area), GFP_KERNEL);
 737         if (dl == NULL) {
 738                 ret = -ENOMEM;
 739                 goto out;
 740         }
 741         dl->dl_cmd = param->dl_cmd;
 742         dl->start_addr = param->start_addr;
 743         dl->num_areas = param->num_areas;
 744         for (i = 0; i < param->num_areas; i++) {
 745                 PDEBUG(DEBUG_EXTRA2,
 746                        "  area %d: addr=0x%08x len=%d ptr=0x%p\n",
 747                        i, param->data[i].addr, param->data[i].len,
 748                        param->data[i].ptr);
 749 
 750                 dl->data[i].addr = param->data[i].addr;
 751                 dl->data[i].len = param->data[i].len;
 752 
 753                 total_len += param->data[i].len;
 754                 if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
 755                     total_len > PRISM2_MAX_DOWNLOAD_LEN) {
 756                         ret = -E2BIG;
 757                         goto out;
 758                 }
 759 
 760                 dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
 761                 if (dl->data[i].data == NULL) {
 762                         ret = -ENOMEM;
 763                         goto out;
 764                 }
 765 
 766                 if (copy_from_user(dl->data[i].data, param->data[i].ptr,
 767                                    param->data[i].len)) {
 768                         ret = -EFAULT;
 769                         goto out;
 770                 }
 771         }
 772 
 773         switch (param->dl_cmd) {
 774         case PRISM2_DOWNLOAD_VOLATILE:
 775         case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
 776                 ret = prism2_download_volatile(local, dl);
 777                 break;
 778         case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
 779         case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
 780                 ret = prism2_download_genesis(local, dl);
 781                 break;
 782         case PRISM2_DOWNLOAD_NON_VOLATILE:
 783 #ifdef PRISM2_NON_VOLATILE_DOWNLOAD
 784                 ret = prism2_download_nonvolatile(local, dl);
 785 #else /* PRISM2_NON_VOLATILE_DOWNLOAD */
 786                 printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
 787                        local->dev->name);
 788                 ret = -EOPNOTSUPP;
 789 #endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
 790                 break;
 791         default:
 792                 printk(KERN_DEBUG "%s: unsupported download command %d\n",
 793                        local->dev->name, param->dl_cmd);
 794                 ret = -EINVAL;
 795                 break;
 796         }
 797 
 798  out:
 799         if (ret == 0 && dl &&
 800             param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
 801                 prism2_download_free_data(local->dl_pri);
 802                 local->dl_pri = dl;
 803         } else if (ret == 0 && dl &&
 804                    param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
 805                 prism2_download_free_data(local->dl_sec);
 806                 local->dl_sec = dl;
 807         } else
 808                 prism2_download_free_data(dl);
 809 
 810         return ret;
 811 }

/* [<][>][^][v][top][bottom][index][help] */