root/drivers/net/wireless/intersil/orinoco/hermes.c

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

DEFINITIONS

This source file includes following definitions.
  1. hermes_issue_cmd
  2. hermes_doicmd_wait
  3. hermes_struct_init
  4. hermes_init
  5. hermes_docmd_wait
  6. hermes_allocate
  7. hermes_bap_seek
  8. hermes_bap_pread
  9. hermes_bap_pwrite
  10. hermes_read_ltv
  11. hermes_write_ltv
  12. hermes_aux_setaddr
  13. hermes_aux_control
  14. hermesi_program_init
  15. hermesi_program_end
  16. hermes_program_bytes
  17. hermes_read_pda
  18. hermes_lock_irqsave
  19. hermes_unlock_irqrestore
  20. hermes_lock_irq
  21. hermes_unlock_irq

   1 /* hermes.c
   2  *
   3  * Driver core for the "Hermes" wireless MAC controller, as used in
   4  * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
   5  * work on the hfa3841 and hfa3842 MAC controller chips used in the
   6  * Prism II chipsets.
   7  *
   8  * This is not a complete driver, just low-level access routines for
   9  * the MAC controller itself.
  10  *
  11  * Based on the prism2 driver from Absolute Value Systems' linux-wlan
  12  * project, the Linux wvlan_cs driver, Lucent's HCF-Light
  13  * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
  14  * particular order).
  15  *
  16  * Copyright (C) 2000, David Gibson, Linuxcare Australia.
  17  * (C) Copyright David Gibson, IBM Corp. 2001-2003.
  18  *
  19  * The contents of this file are subject to the Mozilla Public License
  20  * Version 1.1 (the "License"); you may not use this file except in
  21  * compliance with the License. You may obtain a copy of the License
  22  * at http://www.mozilla.org/MPL/
  23  *
  24  * Software distributed under the License is distributed on an "AS IS"
  25  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  26  * the License for the specific language governing rights and
  27  * limitations under the License.
  28  *
  29  * Alternatively, the contents of this file may be used under the
  30  * terms of the GNU General Public License version 2 (the "GPL"), in
  31  * which case the provisions of the GPL are applicable instead of the
  32  * above.  If you wish to allow the use of your version of this file
  33  * only under the terms of the GPL and not to allow others to use your
  34  * version of this file under the MPL, indicate your decision by
  35  * deleting the provisions above and replace them with the notice and
  36  * other provisions required by the GPL.  If you do not delete the
  37  * provisions above, a recipient may use your version of this file
  38  * under either the MPL or the GPL.
  39  */
  40 
  41 #include <linux/module.h>
  42 #include <linux/kernel.h>
  43 #include <linux/delay.h>
  44 
  45 #include "hermes.h"
  46 
  47 /* These are maximum timeouts. Most often, card wil react much faster */
  48 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
  49 #define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
  50 #define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
  51 #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
  52 
  53 /*
  54  * AUX port access.  To unlock the AUX port write the access keys to the
  55  * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
  56  * register.  Then read it and make sure it's HERMES_AUX_ENABLED.
  57  */
  58 #define HERMES_AUX_ENABLE       0x8000  /* Enable auxiliary port access */
  59 #define HERMES_AUX_DISABLE      0x4000  /* Disable to auxiliary port access */
  60 #define HERMES_AUX_ENABLED      0xC000  /* Auxiliary port is open */
  61 #define HERMES_AUX_DISABLED     0x0000  /* Auxiliary port is closed */
  62 
  63 #define HERMES_AUX_PW0  0xFE01
  64 #define HERMES_AUX_PW1  0xDC23
  65 #define HERMES_AUX_PW2  0xBA45
  66 
  67 /* HERMES_CMD_DOWNLD */
  68 #define HERMES_PROGRAM_DISABLE             (0x0000 | HERMES_CMD_DOWNLD)
  69 #define HERMES_PROGRAM_ENABLE_VOLATILE     (0x0100 | HERMES_CMD_DOWNLD)
  70 #define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
  71 #define HERMES_PROGRAM_NON_VOLATILE        (0x0300 | HERMES_CMD_DOWNLD)
  72 
  73 /*
  74  * Debugging helpers
  75  */
  76 
  77 #define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
  78                         printk(stuff); } while (0)
  79 
  80 #undef HERMES_DEBUG
  81 #ifdef HERMES_DEBUG
  82 #include <stdarg.h>
  83 
  84 #define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff)
  85 
  86 #else /* ! HERMES_DEBUG */
  87 
  88 #define DEBUG(lvl, stuff...) do { } while (0)
  89 
  90 #endif /* ! HERMES_DEBUG */
  91 
  92 static const struct hermes_ops hermes_ops_local;
  93 
  94 /*
  95  * Internal functions
  96  */
  97 
  98 /* Issue a command to the chip. Waiting for it to complete is the caller's
  99    problem.
 100 
 101    Returns -EBUSY if the command register is busy, 0 on success.
 102 
 103    Callable from any context.
 104 */
 105 static int hermes_issue_cmd(struct hermes *hw, u16 cmd, u16 param0,
 106                             u16 param1, u16 param2)
 107 {
 108         int k = CMD_BUSY_TIMEOUT;
 109         u16 reg;
 110 
 111         /* First wait for the command register to unbusy */
 112         reg = hermes_read_regn(hw, CMD);
 113         while ((reg & HERMES_CMD_BUSY) && k) {
 114                 k--;
 115                 udelay(1);
 116                 reg = hermes_read_regn(hw, CMD);
 117         }
 118         if (reg & HERMES_CMD_BUSY)
 119                 return -EBUSY;
 120 
 121         hermes_write_regn(hw, PARAM2, param2);
 122         hermes_write_regn(hw, PARAM1, param1);
 123         hermes_write_regn(hw, PARAM0, param0);
 124         hermes_write_regn(hw, CMD, cmd);
 125 
 126         return 0;
 127 }
 128 
 129 /*
 130  * Function definitions
 131  */
 132 
 133 /* For doing cmds that wipe the magic constant in SWSUPPORT0 */
 134 static int hermes_doicmd_wait(struct hermes *hw, u16 cmd,
 135                               u16 parm0, u16 parm1, u16 parm2,
 136                               struct hermes_response *resp)
 137 {
 138         int err = 0;
 139         int k;
 140         u16 status, reg;
 141 
 142         err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
 143         if (err)
 144                 return err;
 145 
 146         reg = hermes_read_regn(hw, EVSTAT);
 147         k = CMD_INIT_TIMEOUT;
 148         while ((!(reg & HERMES_EV_CMD)) && k) {
 149                 k--;
 150                 udelay(10);
 151                 reg = hermes_read_regn(hw, EVSTAT);
 152         }
 153 
 154         hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
 155 
 156         if (!hermes_present(hw)) {
 157                 DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
 158                        hw->iobase);
 159                 err = -ENODEV;
 160                 goto out;
 161         }
 162 
 163         if (!(reg & HERMES_EV_CMD)) {
 164                 printk(KERN_ERR "hermes @ %p: "
 165                        "Timeout waiting for card to reset (reg=0x%04x)!\n",
 166                        hw->iobase, reg);
 167                 err = -ETIMEDOUT;
 168                 goto out;
 169         }
 170 
 171         status = hermes_read_regn(hw, STATUS);
 172         if (resp) {
 173                 resp->status = status;
 174                 resp->resp0 = hermes_read_regn(hw, RESP0);
 175                 resp->resp1 = hermes_read_regn(hw, RESP1);
 176                 resp->resp2 = hermes_read_regn(hw, RESP2);
 177         }
 178 
 179         hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
 180 
 181         if (status & HERMES_STATUS_RESULT)
 182                 err = -EIO;
 183 out:
 184         return err;
 185 }
 186 
 187 void hermes_struct_init(struct hermes *hw, void __iomem *address,
 188                         int reg_spacing)
 189 {
 190         hw->iobase = address;
 191         hw->reg_spacing = reg_spacing;
 192         hw->inten = 0x0;
 193         hw->eeprom_pda = false;
 194         hw->ops = &hermes_ops_local;
 195 }
 196 EXPORT_SYMBOL(hermes_struct_init);
 197 
 198 static int hermes_init(struct hermes *hw)
 199 {
 200         u16 reg;
 201         int err = 0;
 202         int k;
 203 
 204         /* We don't want to be interrupted while resetting the chipset */
 205         hw->inten = 0x0;
 206         hermes_write_regn(hw, INTEN, 0);
 207         hermes_write_regn(hw, EVACK, 0xffff);
 208 
 209         /* Normally it's a "can't happen" for the command register to
 210            be busy when we go to issue a command because we are
 211            serializing all commands.  However we want to have some
 212            chance of resetting the card even if it gets into a stupid
 213            state, so we actually wait to see if the command register
 214            will unbusy itself here. */
 215         k = CMD_BUSY_TIMEOUT;
 216         reg = hermes_read_regn(hw, CMD);
 217         while (k && (reg & HERMES_CMD_BUSY)) {
 218                 if (reg == 0xffff) /* Special case - the card has probably been
 219                                       removed, so don't wait for the timeout */
 220                         return -ENODEV;
 221 
 222                 k--;
 223                 udelay(1);
 224                 reg = hermes_read_regn(hw, CMD);
 225         }
 226 
 227         /* No need to explicitly handle the timeout - if we've timed
 228            out hermes_issue_cmd() will probably return -EBUSY below */
 229 
 230         /* According to the documentation, EVSTAT may contain
 231            obsolete event occurrence information.  We have to acknowledge
 232            it by writing EVACK. */
 233         reg = hermes_read_regn(hw, EVSTAT);
 234         hermes_write_regn(hw, EVACK, reg);
 235 
 236         /* We don't use hermes_docmd_wait here, because the reset wipes
 237            the magic constant in SWSUPPORT0 away, and it gets confused */
 238         err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL);
 239 
 240         return err;
 241 }
 242 
 243 /* Issue a command to the chip, and (busy!) wait for it to
 244  * complete.
 245  *
 246  * Returns:
 247  *     < 0 on internal error
 248  *       0 on success
 249  *     > 0 on error returned by the firmware
 250  *
 251  * Callable from any context, but locking is your problem. */
 252 static int hermes_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
 253                              struct hermes_response *resp)
 254 {
 255         int err;
 256         int k;
 257         u16 reg;
 258         u16 status;
 259 
 260         err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
 261         if (err) {
 262                 if (!hermes_present(hw)) {
 263                         if (net_ratelimit())
 264                                 printk(KERN_WARNING "hermes @ %p: "
 265                                        "Card removed while issuing command "
 266                                        "0x%04x.\n", hw->iobase, cmd);
 267                         err = -ENODEV;
 268                 } else
 269                         if (net_ratelimit())
 270                                 printk(KERN_ERR "hermes @ %p: "
 271                                        "Error %d issuing command 0x%04x.\n",
 272                                        hw->iobase, err, cmd);
 273                 goto out;
 274         }
 275 
 276         reg = hermes_read_regn(hw, EVSTAT);
 277         k = CMD_COMPL_TIMEOUT;
 278         while ((!(reg & HERMES_EV_CMD)) && k) {
 279                 k--;
 280                 udelay(10);
 281                 reg = hermes_read_regn(hw, EVSTAT);
 282         }
 283 
 284         if (!hermes_present(hw)) {
 285                 printk(KERN_WARNING "hermes @ %p: Card removed "
 286                        "while waiting for command 0x%04x completion.\n",
 287                        hw->iobase, cmd);
 288                 err = -ENODEV;
 289                 goto out;
 290         }
 291 
 292         if (!(reg & HERMES_EV_CMD)) {
 293                 printk(KERN_ERR "hermes @ %p: Timeout waiting for "
 294                        "command 0x%04x completion.\n", hw->iobase, cmd);
 295                 err = -ETIMEDOUT;
 296                 goto out;
 297         }
 298 
 299         status = hermes_read_regn(hw, STATUS);
 300         if (resp) {
 301                 resp->status = status;
 302                 resp->resp0 = hermes_read_regn(hw, RESP0);
 303                 resp->resp1 = hermes_read_regn(hw, RESP1);
 304                 resp->resp2 = hermes_read_regn(hw, RESP2);
 305         }
 306 
 307         hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
 308 
 309         if (status & HERMES_STATUS_RESULT)
 310                 err = -EIO;
 311 
 312  out:
 313         return err;
 314 }
 315 
 316 static int hermes_allocate(struct hermes *hw, u16 size, u16 *fid)
 317 {
 318         int err = 0;
 319         int k;
 320         u16 reg;
 321 
 322         if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX))
 323                 return -EINVAL;
 324 
 325         err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL);
 326         if (err)
 327                 return err;
 328 
 329         reg = hermes_read_regn(hw, EVSTAT);
 330         k = ALLOC_COMPL_TIMEOUT;
 331         while ((!(reg & HERMES_EV_ALLOC)) && k) {
 332                 k--;
 333                 udelay(10);
 334                 reg = hermes_read_regn(hw, EVSTAT);
 335         }
 336 
 337         if (!hermes_present(hw)) {
 338                 printk(KERN_WARNING "hermes @ %p: "
 339                        "Card removed waiting for frame allocation.\n",
 340                        hw->iobase);
 341                 return -ENODEV;
 342         }
 343 
 344         if (!(reg & HERMES_EV_ALLOC)) {
 345                 printk(KERN_ERR "hermes @ %p: "
 346                        "Timeout waiting for frame allocation\n",
 347                        hw->iobase);
 348                 return -ETIMEDOUT;
 349         }
 350 
 351         *fid = hermes_read_regn(hw, ALLOCFID);
 352         hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
 353 
 354         return 0;
 355 }
 356 
 357 /* Set up a BAP to read a particular chunk of data from card's internal buffer.
 358  *
 359  * Returns:
 360  *     < 0 on internal failure (errno)
 361  *       0 on success
 362  *     > 0 on error
 363  * from firmware
 364  *
 365  * Callable from any context */
 366 static int hermes_bap_seek(struct hermes *hw, int bap, u16 id, u16 offset)
 367 {
 368         int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
 369         int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
 370         int k;
 371         u16 reg;
 372 
 373         /* Paranoia.. */
 374         if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2))
 375                 return -EINVAL;
 376 
 377         k = HERMES_BAP_BUSY_TIMEOUT;
 378         reg = hermes_read_reg(hw, oreg);
 379         while ((reg & HERMES_OFFSET_BUSY) && k) {
 380                 k--;
 381                 udelay(1);
 382                 reg = hermes_read_reg(hw, oreg);
 383         }
 384 
 385         if (reg & HERMES_OFFSET_BUSY)
 386                 return -ETIMEDOUT;
 387 
 388         /* Now we actually set up the transfer */
 389         hermes_write_reg(hw, sreg, id);
 390         hermes_write_reg(hw, oreg, offset);
 391 
 392         /* Wait for the BAP to be ready */
 393         k = HERMES_BAP_BUSY_TIMEOUT;
 394         reg = hermes_read_reg(hw, oreg);
 395         while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
 396                 k--;
 397                 udelay(1);
 398                 reg = hermes_read_reg(hw, oreg);
 399         }
 400 
 401         if (reg != offset) {
 402                 printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
 403                        "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
 404                        (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
 405                        reg, id, offset);
 406 
 407                 if (reg & HERMES_OFFSET_BUSY)
 408                         return -ETIMEDOUT;
 409 
 410                 return -EIO;            /* error or wrong offset */
 411         }
 412 
 413         return 0;
 414 }
 415 
 416 /* Read a block of data from the chip's buffer, via the
 417  * BAP. Synchronization/serialization is the caller's problem.  len
 418  * must be even.
 419  *
 420  * Returns:
 421  *     < 0 on internal failure (errno)
 422  *       0 on success
 423  *     > 0 on error from firmware
 424  */
 425 static int hermes_bap_pread(struct hermes *hw, int bap, void *buf, int len,
 426                             u16 id, u16 offset)
 427 {
 428         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 429         int err = 0;
 430 
 431         if ((len < 0) || (len % 2))
 432                 return -EINVAL;
 433 
 434         err = hermes_bap_seek(hw, bap, id, offset);
 435         if (err)
 436                 goto out;
 437 
 438         /* Actually do the transfer */
 439         hermes_read_words(hw, dreg, buf, len / 2);
 440 
 441  out:
 442         return err;
 443 }
 444 
 445 /* Write a block of data to the chip's buffer, via the
 446  * BAP. Synchronization/serialization is the caller's problem.
 447  *
 448  * Returns:
 449  *     < 0 on internal failure (errno)
 450  *       0 on success
 451  *     > 0 on error from firmware
 452  */
 453 static int hermes_bap_pwrite(struct hermes *hw, int bap, const void *buf,
 454                              int len, u16 id, u16 offset)
 455 {
 456         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 457         int err = 0;
 458 
 459         if (len < 0)
 460                 return -EINVAL;
 461 
 462         err = hermes_bap_seek(hw, bap, id, offset);
 463         if (err)
 464                 goto out;
 465 
 466         /* Actually do the transfer */
 467         hermes_write_bytes(hw, dreg, buf, len);
 468 
 469  out:
 470         return err;
 471 }
 472 
 473 /* Read a Length-Type-Value record from the card.
 474  *
 475  * If length is NULL, we ignore the length read from the card, and
 476  * read the entire buffer regardless. This is useful because some of
 477  * the configuration records appear to have incorrect lengths in
 478  * practice.
 479  *
 480  * Callable from user or bh context.  */
 481 static int hermes_read_ltv(struct hermes *hw, int bap, u16 rid,
 482                            unsigned bufsize, u16 *length, void *buf)
 483 {
 484         int err = 0;
 485         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 486         u16 rlength, rtype;
 487         unsigned nwords;
 488 
 489         if (bufsize % 2)
 490                 return -EINVAL;
 491 
 492         err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
 493         if (err)
 494                 return err;
 495 
 496         err = hermes_bap_seek(hw, bap, rid, 0);
 497         if (err)
 498                 return err;
 499 
 500         rlength = hermes_read_reg(hw, dreg);
 501 
 502         if (!rlength)
 503                 return -ENODATA;
 504 
 505         rtype = hermes_read_reg(hw, dreg);
 506 
 507         if (length)
 508                 *length = rlength;
 509 
 510         if (rtype != rid)
 511                 printk(KERN_WARNING "hermes @ %p: %s(): "
 512                        "rid (0x%04x) does not match type (0x%04x)\n",
 513                        hw->iobase, __func__, rid, rtype);
 514         if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
 515                 printk(KERN_WARNING "hermes @ %p: "
 516                        "Truncating LTV record from %d to %d bytes. "
 517                        "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
 518                        HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
 519 
 520         nwords = min((unsigned)rlength - 1, bufsize / 2);
 521         hermes_read_words(hw, dreg, buf, nwords);
 522 
 523         return 0;
 524 }
 525 
 526 static int hermes_write_ltv(struct hermes *hw, int bap, u16 rid,
 527                             u16 length, const void *value)
 528 {
 529         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
 530         int err = 0;
 531         unsigned count;
 532 
 533         if (length == 0)
 534                 return -EINVAL;
 535 
 536         err = hermes_bap_seek(hw, bap, rid, 0);
 537         if (err)
 538                 return err;
 539 
 540         hermes_write_reg(hw, dreg, length);
 541         hermes_write_reg(hw, dreg, rid);
 542 
 543         count = length - 1;
 544 
 545         hermes_write_bytes(hw, dreg, value, count << 1);
 546 
 547         err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
 548                                 rid, NULL);
 549 
 550         return err;
 551 }
 552 
 553 /*** Hermes AUX control ***/
 554 
 555 static inline void
 556 hermes_aux_setaddr(struct hermes *hw, u32 addr)
 557 {
 558         hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
 559         hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
 560 }
 561 
 562 static inline int
 563 hermes_aux_control(struct hermes *hw, int enabled)
 564 {
 565         int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
 566         int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
 567         int i;
 568 
 569         /* Already open? */
 570         if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
 571                 return 0;
 572 
 573         hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
 574         hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
 575         hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
 576         hermes_write_reg(hw, HERMES_CONTROL, action);
 577 
 578         for (i = 0; i < 20; i++) {
 579                 udelay(10);
 580                 if (hermes_read_reg(hw, HERMES_CONTROL) ==
 581                     desired_state)
 582                         return 0;
 583         }
 584 
 585         return -EBUSY;
 586 }
 587 
 588 /*** Hermes programming ***/
 589 
 590 /* About to start programming data (Hermes I)
 591  * offset is the entry point
 592  *
 593  * Spectrum_cs' Symbol fw does not require this
 594  * wl_lkm Agere fw does
 595  * Don't know about intersil
 596  */
 597 static int hermesi_program_init(struct hermes *hw, u32 offset)
 598 {
 599         int err;
 600 
 601         /* Disable interrupts?*/
 602         /*hw->inten = 0x0;*/
 603         /*hermes_write_regn(hw, INTEN, 0);*/
 604         /*hermes_set_irqmask(hw, 0);*/
 605 
 606         /* Acknowledge any outstanding command */
 607         hermes_write_regn(hw, EVACK, 0xFFFF);
 608 
 609         /* Using init_cmd_wait rather than cmd_wait */
 610         err = hw->ops->init_cmd_wait(hw,
 611                                      0x0100 | HERMES_CMD_INIT,
 612                                      0, 0, 0, NULL);
 613         if (err)
 614                 return err;
 615 
 616         err = hw->ops->init_cmd_wait(hw,
 617                                      0x0000 | HERMES_CMD_INIT,
 618                                      0, 0, 0, NULL);
 619         if (err)
 620                 return err;
 621 
 622         err = hermes_aux_control(hw, 1);
 623         pr_debug("AUX enable returned %d\n", err);
 624 
 625         if (err)
 626                 return err;
 627 
 628         pr_debug("Enabling volatile, EP 0x%08x\n", offset);
 629         err = hw->ops->init_cmd_wait(hw,
 630                                      HERMES_PROGRAM_ENABLE_VOLATILE,
 631                                      offset & 0xFFFFu,
 632                                      offset >> 16,
 633                                      0,
 634                                      NULL);
 635         pr_debug("PROGRAM_ENABLE returned %d\n", err);
 636 
 637         return err;
 638 }
 639 
 640 /* Done programming data (Hermes I)
 641  *
 642  * Spectrum_cs' Symbol fw does not require this
 643  * wl_lkm Agere fw does
 644  * Don't know about intersil
 645  */
 646 static int hermesi_program_end(struct hermes *hw)
 647 {
 648         struct hermes_response resp;
 649         int rc = 0;
 650         int err;
 651 
 652         rc = hw->ops->cmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
 653 
 654         pr_debug("PROGRAM_DISABLE returned %d, "
 655                  "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
 656                  rc, resp.resp0, resp.resp1, resp.resp2);
 657 
 658         if ((rc == 0) &&
 659             ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
 660                 rc = -EIO;
 661 
 662         err = hermes_aux_control(hw, 0);
 663         pr_debug("AUX disable returned %d\n", err);
 664 
 665         /* Acknowledge any outstanding command */
 666         hermes_write_regn(hw, EVACK, 0xFFFF);
 667 
 668         /* Reinitialise, ignoring return */
 669         (void) hw->ops->init_cmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
 670                                       0, 0, 0, NULL);
 671 
 672         return rc ? rc : err;
 673 }
 674 
 675 static int hermes_program_bytes(struct hermes *hw, const char *data,
 676                                 u32 addr, u32 len)
 677 {
 678         /* wl lkm splits the programming into chunks of 2000 bytes.
 679          * This restriction appears to come from USB. The PCMCIA
 680          * adapters can program the whole lot in one go */
 681         hermes_aux_setaddr(hw, addr);
 682         hermes_write_bytes(hw, HERMES_AUXDATA, data, len);
 683         return 0;
 684 }
 685 
 686 /* Read PDA from the adapter */
 687 static int hermes_read_pda(struct hermes *hw, __le16 *pda, u32 pda_addr,
 688                            u16 pda_len)
 689 {
 690         int ret;
 691         u16 pda_size;
 692         u16 data_len = pda_len;
 693         __le16 *data = pda;
 694 
 695         if (hw->eeprom_pda) {
 696                 /* PDA of spectrum symbol is in eeprom */
 697 
 698                 /* Issue command to read EEPROM */
 699                 ret = hw->ops->cmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
 700                 if (ret)
 701                         return ret;
 702         } else {
 703                 /* wl_lkm does not include PDA size in the PDA area.
 704                  * We will pad the information into pda, so other routines
 705                  * don't have to be modified */
 706                 pda[0] = cpu_to_le16(pda_len - 2);
 707                         /* Includes CFG_PROD_DATA but not itself */
 708                 pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
 709                 data_len = pda_len - 4;
 710                 data = pda + 2;
 711         }
 712 
 713         /* Open auxiliary port */
 714         ret = hermes_aux_control(hw, 1);
 715         pr_debug("AUX enable returned %d\n", ret);
 716         if (ret)
 717                 return ret;
 718 
 719         /* Read PDA */
 720         hermes_aux_setaddr(hw, pda_addr);
 721         hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
 722 
 723         /* Close aux port */
 724         ret = hermes_aux_control(hw, 0);
 725         pr_debug("AUX disable returned %d\n", ret);
 726 
 727         /* Check PDA length */
 728         pda_size = le16_to_cpu(pda[0]);
 729         pr_debug("Actual PDA length %d, Max allowed %d\n",
 730                  pda_size, pda_len);
 731         if (pda_size > pda_len)
 732                 return -EINVAL;
 733 
 734         return 0;
 735 }
 736 
 737 static void hermes_lock_irqsave(spinlock_t *lock,
 738                                 unsigned long *flags) __acquires(lock)
 739 {
 740         spin_lock_irqsave(lock, *flags);
 741 }
 742 
 743 static void hermes_unlock_irqrestore(spinlock_t *lock,
 744                                      unsigned long *flags) __releases(lock)
 745 {
 746         spin_unlock_irqrestore(lock, *flags);
 747 }
 748 
 749 static void hermes_lock_irq(spinlock_t *lock) __acquires(lock)
 750 {
 751         spin_lock_irq(lock);
 752 }
 753 
 754 static void hermes_unlock_irq(spinlock_t *lock) __releases(lock)
 755 {
 756         spin_unlock_irq(lock);
 757 }
 758 
 759 /* Hermes operations for local buses */
 760 static const struct hermes_ops hermes_ops_local = {
 761         .init = hermes_init,
 762         .cmd_wait = hermes_docmd_wait,
 763         .init_cmd_wait = hermes_doicmd_wait,
 764         .allocate = hermes_allocate,
 765         .read_ltv = hermes_read_ltv,
 766         .write_ltv = hermes_write_ltv,
 767         .bap_pread = hermes_bap_pread,
 768         .bap_pwrite = hermes_bap_pwrite,
 769         .read_pda = hermes_read_pda,
 770         .program_init = hermesi_program_init,
 771         .program_end = hermesi_program_end,
 772         .program = hermes_program_bytes,
 773         .lock_irqsave = hermes_lock_irqsave,
 774         .unlock_irqrestore = hermes_unlock_irqrestore,
 775         .lock_irq = hermes_lock_irq,
 776         .unlock_irq = hermes_unlock_irq,
 777 };

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