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