linux/drivers/net/wireless/intersil/hostap/hostap_download.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2static 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
  87static 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
 118static 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
 149static 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
 180struct prism2_download_aux_dump {
 181        local_info_t *local;
 182        u16 page[0x80];
 183};
 184
 185static 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
 194static 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
 203static 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
 211static 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
 217static 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
 224static 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
 235static const struct proc_ops prism2_download_aux_dump_proc_ops = {
 236        .proc_open              = prism2_download_aux_dump_proc_open,
 237        .proc_read              = seq_read,
 238        .proc_lseek             = seq_lseek,
 239        .proc_release           = seq_release_private,
 240};
 241
 242
 243static 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
 291static 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
 388static 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
 417static 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
 436static 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
 547static 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
 590static 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
 705static 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
 718static 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}
 812