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 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
 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 "
 411                       "write %02x %02x %02x %02x read %02x %02x %02x %02x\n",
 412                       hcr, initseq[0], initseq[1], initseq[2], initseq[3],
 413                       readbuf[0], readbuf[1], readbuf[2], readbuf[3]);
 414                return 1;
 415        }
 416}
 417
 418
 419static int prism2_get_ram_size(local_info_t *local)
 420{
 421        int ret;
 422
 423        /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */
 424        if (prism2_enable_genesis(local, 0x1f) == 0)
 425                ret = 8;
 426        else if (prism2_enable_genesis(local, 0x0f) == 0)
 427                ret = 16;
 428        else
 429                ret = -1;
 430
 431        /* Disable genesis mode */
 432        local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17);
 433
 434        return ret;
 435}
 436
 437
 438static int prism2_download_genesis(local_info_t *local,
 439                                   struct prism2_download_data *param)
 440{
 441        struct net_device *dev = local->dev;
 442        int ram16 = 0, i;
 443        int ret = 0;
 444
 445        if (local->hw_downloading) {
 446                printk(KERN_WARNING "%s: Already downloading - aborting new "
 447                       "request\n", dev->name);
 448                return -EBUSY;
 449        }
 450
 451        if (!local->func->genesis_reset || !local->func->cor_sreset) {
 452                printk(KERN_INFO "%s: Genesis mode downloading not supported "
 453                       "with this hwmodel\n", dev->name);
 454                return -EOPNOTSUPP;
 455        }
 456
 457        local->hw_downloading = 1;
 458
 459        if (prism2_enable_aux_port(dev, 1)) {
 460                printk(KERN_DEBUG "%s: failed to enable AUX port\n",
 461                       dev->name);
 462                ret = -EIO;
 463                goto out;
 464        }
 465
 466        if (local->sram_type == -1) {
 467                /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */
 468                if (prism2_enable_genesis(local, 0x1f) == 0) {
 469                        ram16 = 0;
 470                        PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 "
 471                               "SRAM\n", dev->name);
 472                } else if (prism2_enable_genesis(local, 0x0f) == 0) {
 473                        ram16 = 1;
 474                        PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 "
 475                               "SRAM\n", dev->name);
 476                } else {
 477                        printk(KERN_DEBUG "%s: Could not initiate genesis "
 478                               "mode\n", dev->name);
 479                        ret = -EIO;
 480                        goto out;
 481                }
 482        } else {
 483                if (prism2_enable_genesis(local, local->sram_type == 8 ?
 484                                          0x1f : 0x0f)) {
 485                        printk(KERN_DEBUG "%s: Failed to set Genesis "
 486                               "mode (sram_type=%d)\n", dev->name,
 487                               local->sram_type);
 488                        ret = -EIO;
 489                        goto out;
 490                }
 491                ram16 = local->sram_type != 8;
 492        }
 493
 494        for (i = 0; i < param->num_areas; i++) {
 495                PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n",
 496                       dev->name, param->data[i].len, param->data[i].addr);
 497                if (hfa384x_to_aux(dev, param->data[i].addr,
 498                                   param->data[i].len, param->data[i].data)) {
 499                        printk(KERN_WARNING "%s: RAM download at 0x%08x "
 500                               "(len=%d) failed\n", dev->name,
 501                               param->data[i].addr, param->data[i].len);
 502                        ret = -EIO;
 503                        goto out;
 504                }
 505        }
 506
 507        PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n");
 508        local->func->genesis_reset(local, ram16 ? 0x07 : 0x17);
 509        if (prism2_enable_aux_port(dev, 0)) {
 510                printk(KERN_DEBUG "%s: Failed to disable AUX port\n",
 511                       dev->name);
 512        }
 513
 514        mdelay(5);
 515        local->hw_downloading = 0;
 516
 517        PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n");
 518        /*
 519         * Make sure the INIT command does not generate a command completion
 520         * event by disabling interrupts.
 521         */
 522        hfa384x_disable_interrupts(dev);
 523        if (prism2_hw_init(dev, 1)) {
 524                printk(KERN_DEBUG "%s: Initialization after genesis mode "
 525                       "download failed\n", dev->name);
 526                ret = -EIO;
 527                goto out;
 528        }
 529
 530        PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n");
 531        if (prism2_hw_init2(dev, 1)) {
 532                printk(KERN_DEBUG "%s: Initialization(2) after genesis mode "
 533                       "download failed\n", dev->name);
 534                ret = -EIO;
 535                goto out;
 536        }
 537
 538 out:
 539        local->hw_downloading = 0;
 540        return ret;
 541}
 542
 543
 544#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
 545/* Note! Non-volatile downloading functionality has not yet been tested
 546 * thoroughly and it may corrupt flash image and effectively kill the card that
 547 * is being updated. You have been warned. */
 548
 549static inline int prism2_download_block(struct net_device *dev,
 550                                        u32 addr, u8 *data,
 551                                        u32 bufaddr, int rest_len)
 552{
 553        u16 param0, param1;
 554        int block_len;
 555
 556        block_len = rest_len < 4096 ? rest_len : 4096;
 557
 558        param0 = addr & 0xffff;
 559        param1 = addr >> 16;
 560
 561        HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF);
 562        HFA384X_OUTW(param1, HFA384X_PARAM1_OFF);
 563
 564        if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 565                             (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8),
 566                             param0)) {
 567                printk(KERN_WARNING "%s: Flash download command execution "
 568                       "failed\n", dev->name);
 569                return -1;
 570        }
 571
 572        if (hfa384x_to_aux(dev, bufaddr, block_len, data)) {
 573                printk(KERN_WARNING "%s: flash download at 0x%08x "
 574                       "(len=%d) failed\n", dev->name, addr, block_len);
 575                return -1;
 576        }
 577
 578        HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 579        HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
 580        if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 581                             (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8),
 582                             0)) {
 583                printk(KERN_WARNING "%s: Flash write command execution "
 584                       "failed\n", dev->name);
 585                return -1;
 586        }
 587
 588        return block_len;
 589}
 590
 591
 592static int prism2_download_nonvolatile(local_info_t *local,
 593                                       struct prism2_download_data *dl)
 594{
 595        struct net_device *dev = local->dev;
 596        int ret = 0, i;
 597        struct {
 598                __le16 page;
 599                __le16 offset;
 600                __le16 len;
 601        } dlbuffer;
 602        u32 bufaddr;
 603
 604        if (local->hw_downloading) {
 605                printk(KERN_WARNING "%s: Already downloading - aborting new "
 606                       "request\n", dev->name);
 607                return -1;
 608        }
 609
 610        ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER,
 611                                   &dlbuffer, 6, 0);
 612
 613        if (ret < 0) {
 614                printk(KERN_WARNING "%s: Could not read download buffer "
 615                       "parameters\n", dev->name);
 616                goto out;
 617        }
 618
 619        printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n",
 620               le16_to_cpu(dlbuffer.len),
 621               le16_to_cpu(dlbuffer.page),
 622               le16_to_cpu(dlbuffer.offset));
 623
 624        bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset);
 625
 626        local->hw_downloading = 1;
 627
 628        if (!local->pri_only) {
 629                prism2_hw_shutdown(dev, 0);
 630
 631                if (prism2_hw_init(dev, 0)) {
 632                        printk(KERN_WARNING "%s: Could not initialize card for"
 633                               " download\n", dev->name);
 634                        ret = -1;
 635                        goto out;
 636                }
 637        }
 638
 639        hfa384x_disable_interrupts(dev);
 640
 641        if (prism2_enable_aux_port(dev, 1)) {
 642                printk(KERN_WARNING "%s: Could not enable AUX port\n",
 643                       dev->name);
 644                ret = -1;
 645                goto out;
 646        }
 647
 648        printk(KERN_DEBUG "%s: starting flash download\n", dev->name);
 649        for (i = 0; i < dl->num_areas; i++) {
 650                int rest_len = dl->data[i].len;
 651                int data_off = 0;
 652
 653                while (rest_len > 0) {
 654                        int block_len;
 655
 656                        block_len = prism2_download_block(
 657                                dev, dl->data[i].addr + data_off,
 658                                dl->data[i].data + data_off, bufaddr,
 659                                rest_len);
 660
 661                        if (block_len < 0) {
 662                                ret = -1;
 663                                goto out;
 664                        }
 665
 666                        rest_len -= block_len;
 667                        data_off += block_len;
 668                }
 669        }
 670
 671        HFA384X_OUTW(0, HFA384X_PARAM1_OFF);
 672        HFA384X_OUTW(0, HFA384X_PARAM2_OFF);
 673        if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD |
 674                                (HFA384X_PROGMODE_DISABLE << 8), 0)) {
 675                printk(KERN_WARNING "%s: Download command execution failed\n",
 676                       dev->name);
 677                ret = -1;
 678                goto out;
 679        }
 680
 681        if (prism2_enable_aux_port(dev, 0)) {
 682                printk(KERN_DEBUG "%s: Disabling AUX port failed\n",
 683                       dev->name);
 684                /* continue anyway.. restart should have taken care of this */
 685        }
 686
 687        mdelay(5);
 688
 689        local->func->hw_reset(dev);
 690        local->hw_downloading = 0;
 691        if (prism2_hw_config(dev, 2)) {
 692                printk(KERN_WARNING "%s: Card configuration after flash "
 693                       "download failed\n", dev->name);
 694                ret = -1;
 695        } else {
 696                printk(KERN_INFO "%s: Card initialized successfully after "
 697                       "flash download\n", dev->name);
 698        }
 699
 700 out:
 701        local->hw_downloading = 0;
 702        return ret;
 703}
 704#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
 705
 706
 707static void prism2_download_free_data(struct prism2_download_data *dl)
 708{
 709        int i;
 710
 711        if (dl == NULL)
 712                return;
 713
 714        for (i = 0; i < dl->num_areas; i++)
 715                kfree(dl->data[i].data);
 716        kfree(dl);
 717}
 718
 719
 720static int prism2_download(local_info_t *local,
 721                           struct prism2_download_param *param)
 722{
 723        int ret = 0;
 724        int i;
 725        u32 total_len = 0;
 726        struct prism2_download_data *dl = NULL;
 727
 728        printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x "
 729               "num_areas=%d\n",
 730               param->dl_cmd, param->start_addr, param->num_areas);
 731
 732        if (param->num_areas > 100) {
 733                ret = -EINVAL;
 734                goto out;
 735        }
 736
 737        dl = kzalloc(sizeof(*dl) + param->num_areas *
 738                     sizeof(struct prism2_download_data_area), GFP_KERNEL);
 739        if (dl == NULL) {
 740                ret = -ENOMEM;
 741                goto out;
 742        }
 743        dl->dl_cmd = param->dl_cmd;
 744        dl->start_addr = param->start_addr;
 745        dl->num_areas = param->num_areas;
 746        for (i = 0; i < param->num_areas; i++) {
 747                PDEBUG(DEBUG_EXTRA2,
 748                       "  area %d: addr=0x%08x len=%d ptr=0x%p\n",
 749                       i, param->data[i].addr, param->data[i].len,
 750                       param->data[i].ptr);
 751
 752                dl->data[i].addr = param->data[i].addr;
 753                dl->data[i].len = param->data[i].len;
 754
 755                total_len += param->data[i].len;
 756                if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN ||
 757                    total_len > PRISM2_MAX_DOWNLOAD_LEN) {
 758                        ret = -E2BIG;
 759                        goto out;
 760                }
 761
 762                dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL);
 763                if (dl->data[i].data == NULL) {
 764                        ret = -ENOMEM;
 765                        goto out;
 766                }
 767
 768                if (copy_from_user(dl->data[i].data, param->data[i].ptr,
 769                                   param->data[i].len)) {
 770                        ret = -EFAULT;
 771                        goto out;
 772                }
 773        }
 774
 775        switch (param->dl_cmd) {
 776        case PRISM2_DOWNLOAD_VOLATILE:
 777        case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT:
 778                ret = prism2_download_volatile(local, dl);
 779                break;
 780        case PRISM2_DOWNLOAD_VOLATILE_GENESIS:
 781        case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT:
 782                ret = prism2_download_genesis(local, dl);
 783                break;
 784        case PRISM2_DOWNLOAD_NON_VOLATILE:
 785#ifdef PRISM2_NON_VOLATILE_DOWNLOAD
 786                ret = prism2_download_nonvolatile(local, dl);
 787#else /* PRISM2_NON_VOLATILE_DOWNLOAD */
 788                printk(KERN_INFO "%s: non-volatile downloading not enabled\n",
 789                       local->dev->name);
 790                ret = -EOPNOTSUPP;
 791#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */
 792                break;
 793        default:
 794                printk(KERN_DEBUG "%s: unsupported download command %d\n",
 795                       local->dev->name, param->dl_cmd);
 796                ret = -EINVAL;
 797                break;
 798        }
 799
 800 out:
 801        if (ret == 0 && dl &&
 802            param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) {
 803                prism2_download_free_data(local->dl_pri);
 804                local->dl_pri = dl;
 805        } else if (ret == 0 && dl &&
 806                   param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) {
 807                prism2_download_free_data(local->dl_sec);
 808                local->dl_sec = dl;
 809        } else
 810                prism2_download_free_data(dl);
 811
 812        return ret;
 813}
 814