Linux Audio

Check our new training course

Loading...
v3.1
   1/* Encapsulate basic setting changes and retrieval on Hermes hardware
   2 *
   3 * See copyright notice in main.c
   4 */
   5#include <linux/kernel.h>
   6#include <linux/device.h>
   7#include <linux/if_arp.h>
   8#include <linux/ieee80211.h>
   9#include <linux/wireless.h>
  10#include <net/cfg80211.h>
  11#include "hermes.h"
  12#include "hermes_rid.h"
  13#include "orinoco.h"
  14
  15#include "hw.h"
  16
  17#define SYMBOL_MAX_VER_LEN	(14)
  18
  19/* Symbol firmware has a bug allocating buffers larger than this */
  20#define TX_NICBUF_SIZE_BUG	1585
  21
  22/********************************************************************/
  23/* Data tables                                                      */
  24/********************************************************************/
  25
  26/* This tables gives the actual meanings of the bitrate IDs returned
  27 * by the firmware. */
  28static const struct {
  29	int bitrate; /* in 100s of kilobits */
  30	int automatic;
  31	u16 agere_txratectrl;
  32	u16 intersil_txratectrl;
  33} bitrate_table[] = {
  34	{110, 1,  3, 15}, /* Entry 0 is the default */
  35	{10,  0,  1,  1},
  36	{10,  1,  1,  1},
  37	{20,  0,  2,  2},
  38	{20,  1,  6,  3},
  39	{55,  0,  4,  4},
  40	{55,  1,  7,  7},
  41	{110, 0,  5,  8},
  42};
  43#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
  44
  45/* Firmware version encoding */
  46struct comp_id {
  47	u16 id, variant, major, minor;
  48} __packed;
  49
  50static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
  51{
  52	if (nic_id->id < 0x8000)
  53		return FIRMWARE_TYPE_AGERE;
  54	else if (nic_id->id == 0x8000 && nic_id->major == 0)
  55		return FIRMWARE_TYPE_SYMBOL;
  56	else
  57		return FIRMWARE_TYPE_INTERSIL;
  58}
  59
  60/* Set priv->firmware type, determine firmware properties
  61 * This function can be called before we have registerred with netdev,
  62 * so all errors go out with dev_* rather than printk
  63 *
  64 * If non-NULL stores a firmware description in fw_name.
  65 * If non-NULL stores a HW version in hw_ver
  66 *
  67 * These are output via generic cfg80211 ethtool support.
  68 */
  69int determine_fw_capabilities(struct orinoco_private *priv,
  70			      char *fw_name, size_t fw_name_len,
  71			      u32 *hw_ver)
  72{
  73	struct device *dev = priv->dev;
  74	struct hermes *hw = &priv->hw;
  75	int err;
  76	struct comp_id nic_id, sta_id;
  77	unsigned int firmver;
  78	char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
  79
  80	/* Get the hardware version */
  81	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
  82	if (err) {
  83		dev_err(dev, "Cannot read hardware identity: error %d\n",
  84			err);
  85		return err;
  86	}
  87
  88	le16_to_cpus(&nic_id.id);
  89	le16_to_cpus(&nic_id.variant);
  90	le16_to_cpus(&nic_id.major);
  91	le16_to_cpus(&nic_id.minor);
  92	dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
  93		 nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
  94
  95	if (hw_ver)
  96		*hw_ver = (((nic_id.id & 0xff) << 24) |
  97			   ((nic_id.variant & 0xff) << 16) |
  98			   ((nic_id.major & 0xff) << 8) |
  99			   (nic_id.minor & 0xff));
 100
 101	priv->firmware_type = determine_firmware_type(&nic_id);
 102
 103	/* Get the firmware version */
 104	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
 105	if (err) {
 106		dev_err(dev, "Cannot read station identity: error %d\n",
 107			err);
 108		return err;
 109	}
 110
 111	le16_to_cpus(&sta_id.id);
 112	le16_to_cpus(&sta_id.variant);
 113	le16_to_cpus(&sta_id.major);
 114	le16_to_cpus(&sta_id.minor);
 115	dev_info(dev, "Station identity  %04x:%04x:%04x:%04x\n",
 116		 sta_id.id, sta_id.variant, sta_id.major, sta_id.minor);
 117
 118	switch (sta_id.id) {
 119	case 0x15:
 120		dev_err(dev, "Primary firmware is active\n");
 121		return -ENODEV;
 122	case 0x14b:
 123		dev_err(dev, "Tertiary firmware is active\n");
 124		return -ENODEV;
 125	case 0x1f:	/* Intersil, Agere, Symbol Spectrum24 */
 126	case 0x21:	/* Symbol Spectrum24 Trilogy */
 127		break;
 128	default:
 129		dev_notice(dev, "Unknown station ID, please report\n");
 130		break;
 131	}
 132
 133	/* Default capabilities */
 134	priv->has_sensitivity = 1;
 135	priv->has_mwo = 0;
 136	priv->has_preamble = 0;
 137	priv->has_port3 = 1;
 138	priv->has_ibss = 1;
 139	priv->has_wep = 0;
 140	priv->has_big_wep = 0;
 141	priv->has_alt_txcntl = 0;
 142	priv->has_ext_scan = 0;
 143	priv->has_wpa = 0;
 144	priv->do_fw_download = 0;
 145
 146	/* Determine capabilities from the firmware version */
 147	switch (priv->firmware_type) {
 148	case FIRMWARE_TYPE_AGERE:
 149		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
 150		   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
 151		if (fw_name)
 152			snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d",
 153				 sta_id.major, sta_id.minor);
 154
 155		firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
 156
 157		priv->has_ibss = (firmver >= 0x60006);
 158		priv->has_wep = (firmver >= 0x40020);
 159		priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
 160					  Gold cards from the others? */
 161		priv->has_mwo = (firmver >= 0x60000);
 162		priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
 163		priv->ibss_port = 1;
 164		priv->has_hostscan = (firmver >= 0x8000a);
 165		priv->do_fw_download = 1;
 166		priv->broken_monitor = (firmver >= 0x80000);
 167		priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
 168		priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
 169		priv->has_wpa = (firmver >= 0x9002a);
 170		/* Tested with Agere firmware :
 171		 *	1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
 172		 * Tested CableTron firmware : 4.32 => Anton */
 173		break;
 174	case FIRMWARE_TYPE_SYMBOL:
 175		/* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
 176		/* Intel MAC : 00:02:B3:* */
 177		/* 3Com MAC : 00:50:DA:* */
 178		memset(tmp, 0, sizeof(tmp));
 179		/* Get the Symbol firmware version */
 180		err = hw->ops->read_ltv(hw, USER_BAP,
 181					HERMES_RID_SECONDARYVERSION_SYMBOL,
 182					SYMBOL_MAX_VER_LEN, NULL, &tmp);
 183		if (err) {
 184			dev_warn(dev, "Error %d reading Symbol firmware info. "
 185				 "Wildly guessing capabilities...\n", err);
 186			firmver = 0;
 187			tmp[0] = '\0';
 188		} else {
 189			/* The firmware revision is a string, the format is
 190			 * something like : "V2.20-01".
 191			 * Quick and dirty parsing... - Jean II
 192			 */
 193			firmver = ((tmp[1] - '0') << 16)
 194				| ((tmp[3] - '0') << 12)
 195				| ((tmp[4] - '0') << 8)
 196				| ((tmp[6] - '0') << 4)
 197				| (tmp[7] - '0');
 198
 199			tmp[SYMBOL_MAX_VER_LEN] = '\0';
 200		}
 201
 202		if (fw_name)
 203			snprintf(fw_name, fw_name_len, "Symbol %s", tmp);
 204
 205		priv->has_ibss = (firmver >= 0x20000);
 206		priv->has_wep = (firmver >= 0x15012);
 207		priv->has_big_wep = (firmver >= 0x20000);
 208		priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
 209			       (firmver >= 0x29000 && firmver < 0x30000) ||
 210			       firmver >= 0x31000;
 211		priv->has_preamble = (firmver >= 0x20000);
 212		priv->ibss_port = 4;
 213
 214		/* Symbol firmware is found on various cards, but
 215		 * there has been no attempt to check firmware
 216		 * download on non-spectrum_cs based cards.
 217		 *
 218		 * Given that the Agere firmware download works
 219		 * differently, we should avoid doing a firmware
 220		 * download with the Symbol algorithm on non-spectrum
 221		 * cards.
 222		 *
 223		 * For now we can identify a spectrum_cs based card
 224		 * because it has a firmware reset function.
 225		 */
 226		priv->do_fw_download = (priv->stop_fw != NULL);
 227
 228		priv->broken_disableport = (firmver == 0x25013) ||
 229				(firmver >= 0x30000 && firmver <= 0x31000);
 230		priv->has_hostscan = (firmver >= 0x31001) ||
 231				     (firmver >= 0x29057 && firmver < 0x30000);
 232		/* Tested with Intel firmware : 0x20015 => Jean II */
 233		/* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
 234		break;
 235	case FIRMWARE_TYPE_INTERSIL:
 236		/* D-Link, Linksys, Adtron, ZoomAir, and many others...
 237		 * Samsung, Compaq 100/200 and Proxim are slightly
 238		 * different and less well tested */
 239		/* D-Link MAC : 00:40:05:* */
 240		/* Addtron MAC : 00:90:D1:* */
 241		if (fw_name)
 242			snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d",
 243				 sta_id.major, sta_id.minor, sta_id.variant);
 244
 245		firmver = ((unsigned long)sta_id.major << 16) |
 246			((unsigned long)sta_id.minor << 8) | sta_id.variant;
 247
 248		priv->has_ibss = (firmver >= 0x000700); /* FIXME */
 249		priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
 250		priv->has_pm = (firmver >= 0x000700);
 251		priv->has_hostscan = (firmver >= 0x010301);
 252
 253		if (firmver >= 0x000800)
 254			priv->ibss_port = 0;
 255		else {
 256			dev_notice(dev, "Intersil firmware earlier than v0.8.x"
 257				   " - several features not supported\n");
 258			priv->ibss_port = 1;
 259		}
 260		break;
 261	}
 262	if (fw_name)
 263		dev_info(dev, "Firmware determined as %s\n", fw_name);
 264
 265#ifndef CONFIG_HERMES_PRISM
 266	if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
 267		dev_err(dev, "Support for Prism chipset is not enabled\n");
 268		return -ENODEV;
 269	}
 270#endif
 271
 272	return 0;
 273}
 274
 275/* Read settings from EEPROM into our private structure.
 276 * MAC address gets dropped into callers buffer
 277 * Can be called before netdev registration.
 278 */
 279int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
 280{
 281	struct device *dev = priv->dev;
 282	struct hermes_idstring nickbuf;
 283	struct hermes *hw = &priv->hw;
 284	int len;
 285	int err;
 286	u16 reclen;
 287
 288	/* Get the MAC address */
 289	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
 290				ETH_ALEN, NULL, dev_addr);
 291	if (err) {
 292		dev_warn(dev, "Failed to read MAC address!\n");
 293		goto out;
 294	}
 295
 296	dev_dbg(dev, "MAC address %pM\n", dev_addr);
 297
 298	/* Get the station name */
 299	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
 300				sizeof(nickbuf), &reclen, &nickbuf);
 301	if (err) {
 302		dev_err(dev, "failed to read station name\n");
 303		goto out;
 304	}
 305	if (nickbuf.len)
 306		len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
 307	else
 308		len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
 309	memcpy(priv->nick, &nickbuf.val, len);
 310	priv->nick[len] = '\0';
 311
 312	dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
 313
 314	/* Get allowed channels */
 315	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
 316				  &priv->channel_mask);
 317	if (err) {
 318		dev_err(dev, "Failed to read channel list!\n");
 319		goto out;
 320	}
 321
 322	/* Get initial AP density */
 323	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
 324				  &priv->ap_density);
 325	if (err || priv->ap_density < 1 || priv->ap_density > 3)
 326		priv->has_sensitivity = 0;
 327
 328	/* Get initial RTS threshold */
 329	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
 330				  &priv->rts_thresh);
 331	if (err) {
 332		dev_err(dev, "Failed to read RTS threshold!\n");
 333		goto out;
 334	}
 335
 336	/* Get initial fragmentation settings */
 337	if (priv->has_mwo)
 338		err = hermes_read_wordrec(hw, USER_BAP,
 339					  HERMES_RID_CNFMWOROBUST_AGERE,
 340					  &priv->mwo_robust);
 341	else
 342		err = hermes_read_wordrec(hw, USER_BAP,
 343					  HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 344					  &priv->frag_thresh);
 345	if (err) {
 346		dev_err(dev, "Failed to read fragmentation settings!\n");
 347		goto out;
 348	}
 349
 350	/* Power management setup */
 351	if (priv->has_pm) {
 352		priv->pm_on = 0;
 353		priv->pm_mcast = 1;
 354		err = hermes_read_wordrec(hw, USER_BAP,
 355					  HERMES_RID_CNFMAXSLEEPDURATION,
 356					  &priv->pm_period);
 357		if (err) {
 358			dev_err(dev, "Failed to read power management "
 359				"period!\n");
 360			goto out;
 361		}
 362		err = hermes_read_wordrec(hw, USER_BAP,
 363					  HERMES_RID_CNFPMHOLDOVERDURATION,
 364					  &priv->pm_timeout);
 365		if (err) {
 366			dev_err(dev, "Failed to read power management "
 367				"timeout!\n");
 368			goto out;
 369		}
 370	}
 371
 372	/* Preamble setup */
 373	if (priv->has_preamble) {
 374		err = hermes_read_wordrec(hw, USER_BAP,
 375					  HERMES_RID_CNFPREAMBLE_SYMBOL,
 376					  &priv->preamble);
 377		if (err) {
 378			dev_err(dev, "Failed to read preamble setup\n");
 379			goto out;
 380		}
 381	}
 382
 383	/* Retry settings */
 384	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
 385				  &priv->short_retry_limit);
 386	if (err) {
 387		dev_err(dev, "Failed to read short retry limit\n");
 388		goto out;
 389	}
 390
 391	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
 392				  &priv->long_retry_limit);
 393	if (err) {
 394		dev_err(dev, "Failed to read long retry limit\n");
 395		goto out;
 396	}
 397
 398	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
 399				  &priv->retry_lifetime);
 400	if (err) {
 401		dev_err(dev, "Failed to read max retry lifetime\n");
 402		goto out;
 403	}
 404
 405out:
 406	return err;
 407}
 408
 409/* Can be called before netdev registration */
 410int orinoco_hw_allocate_fid(struct orinoco_private *priv)
 411{
 412	struct device *dev = priv->dev;
 413	struct hermes *hw = &priv->hw;
 414	int err;
 415
 416	err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
 417	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
 418		/* Try workaround for old Symbol firmware bug */
 419		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
 420		err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
 421
 422		dev_warn(dev, "Firmware ALLOC bug detected "
 423			 "(old Symbol firmware?). Work around %s\n",
 424			 err ? "failed!" : "ok.");
 425	}
 426
 427	return err;
 428}
 429
 430int orinoco_get_bitratemode(int bitrate, int automatic)
 431{
 432	int ratemode = -1;
 433	int i;
 434
 435	if ((bitrate != 10) && (bitrate != 20) &&
 436	    (bitrate != 55) && (bitrate != 110))
 437		return ratemode;
 438
 439	for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
 440		if ((bitrate_table[i].bitrate == bitrate) &&
 441		    (bitrate_table[i].automatic == automatic)) {
 442			ratemode = i;
 443			break;
 444		}
 445	}
 446	return ratemode;
 447}
 448
 449void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
 450{
 451	BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
 452
 453	*bitrate = bitrate_table[ratemode].bitrate * 100000;
 454	*automatic = bitrate_table[ratemode].automatic;
 455}
 456
 457int orinoco_hw_program_rids(struct orinoco_private *priv)
 458{
 459	struct net_device *dev = priv->ndev;
 460	struct wireless_dev *wdev = netdev_priv(dev);
 461	struct hermes *hw = &priv->hw;
 462	int err;
 463	struct hermes_idstring idbuf;
 464
 465	/* Set the MAC address */
 466	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
 467				 HERMES_BYTES_TO_RECLEN(ETH_ALEN),
 468				 dev->dev_addr);
 469	if (err) {
 470		printk(KERN_ERR "%s: Error %d setting MAC address\n",
 471		       dev->name, err);
 472		return err;
 473	}
 474
 475	/* Set up the link mode */
 476	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
 477				   priv->port_type);
 478	if (err) {
 479		printk(KERN_ERR "%s: Error %d setting port type\n",
 480		       dev->name, err);
 481		return err;
 482	}
 483	/* Set the channel/frequency */
 484	if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) {
 485		err = hermes_write_wordrec(hw, USER_BAP,
 486					   HERMES_RID_CNFOWNCHANNEL,
 487					   priv->channel);
 488		if (err) {
 489			printk(KERN_ERR "%s: Error %d setting channel %d\n",
 490			       dev->name, err, priv->channel);
 491			return err;
 492		}
 493	}
 494
 495	if (priv->has_ibss) {
 496		u16 createibss;
 497
 498		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
 499			printk(KERN_WARNING "%s: This firmware requires an "
 500			       "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
 501			/* With wvlan_cs, in this case, we would crash.
 502			 * hopefully, this driver will behave better...
 503			 * Jean II */
 504			createibss = 0;
 505		} else {
 506			createibss = priv->createibss;
 507		}
 508
 509		err = hermes_write_wordrec(hw, USER_BAP,
 510					   HERMES_RID_CNFCREATEIBSS,
 511					   createibss);
 512		if (err) {
 513			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
 514			       dev->name, err);
 515			return err;
 516		}
 517	}
 518
 519	/* Set the desired BSSID */
 520	err = __orinoco_hw_set_wap(priv);
 521	if (err) {
 522		printk(KERN_ERR "%s: Error %d setting AP address\n",
 523		       dev->name, err);
 524		return err;
 525	}
 526
 527	/* Set the desired ESSID */
 528	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
 529	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
 530	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
 531	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
 532			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
 533			&idbuf);
 534	if (err) {
 535		printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
 536		       dev->name, err);
 537		return err;
 538	}
 539	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
 540			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
 541			&idbuf);
 542	if (err) {
 543		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
 544		       dev->name, err);
 545		return err;
 546	}
 547
 548	/* Set the station name */
 549	idbuf.len = cpu_to_le16(strlen(priv->nick));
 550	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
 551	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
 552				 HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
 553				 &idbuf);
 554	if (err) {
 555		printk(KERN_ERR "%s: Error %d setting nickname\n",
 556		       dev->name, err);
 557		return err;
 558	}
 559
 560	/* Set AP density */
 561	if (priv->has_sensitivity) {
 562		err = hermes_write_wordrec(hw, USER_BAP,
 563					   HERMES_RID_CNFSYSTEMSCALE,
 564					   priv->ap_density);
 565		if (err) {
 566			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
 567			       "Disabling sensitivity control\n",
 568			       dev->name, err);
 569
 570			priv->has_sensitivity = 0;
 571		}
 572	}
 573
 574	/* Set RTS threshold */
 575	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
 576				   priv->rts_thresh);
 577	if (err) {
 578		printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
 579		       dev->name, err);
 580		return err;
 581	}
 582
 583	/* Set fragmentation threshold or MWO robustness */
 584	if (priv->has_mwo)
 585		err = hermes_write_wordrec(hw, USER_BAP,
 586					   HERMES_RID_CNFMWOROBUST_AGERE,
 587					   priv->mwo_robust);
 588	else
 589		err = hermes_write_wordrec(hw, USER_BAP,
 590					   HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 591					   priv->frag_thresh);
 592	if (err) {
 593		printk(KERN_ERR "%s: Error %d setting fragmentation\n",
 594		       dev->name, err);
 595		return err;
 596	}
 597
 598	/* Set bitrate */
 599	err = __orinoco_hw_set_bitrate(priv);
 600	if (err) {
 601		printk(KERN_ERR "%s: Error %d setting bitrate\n",
 602		       dev->name, err);
 603		return err;
 604	}
 605
 606	/* Set power management */
 607	if (priv->has_pm) {
 608		err = hermes_write_wordrec(hw, USER_BAP,
 609					   HERMES_RID_CNFPMENABLED,
 610					   priv->pm_on);
 611		if (err) {
 612			printk(KERN_ERR "%s: Error %d setting up PM\n",
 613			       dev->name, err);
 614			return err;
 615		}
 616
 617		err = hermes_write_wordrec(hw, USER_BAP,
 618					   HERMES_RID_CNFMULTICASTRECEIVE,
 619					   priv->pm_mcast);
 620		if (err) {
 621			printk(KERN_ERR "%s: Error %d setting up PM\n",
 622			       dev->name, err);
 623			return err;
 624		}
 625		err = hermes_write_wordrec(hw, USER_BAP,
 626					   HERMES_RID_CNFMAXSLEEPDURATION,
 627					   priv->pm_period);
 628		if (err) {
 629			printk(KERN_ERR "%s: Error %d setting up PM\n",
 630			       dev->name, err);
 631			return err;
 632		}
 633		err = hermes_write_wordrec(hw, USER_BAP,
 634					   HERMES_RID_CNFPMHOLDOVERDURATION,
 635					   priv->pm_timeout);
 636		if (err) {
 637			printk(KERN_ERR "%s: Error %d setting up PM\n",
 638			       dev->name, err);
 639			return err;
 640		}
 641	}
 642
 643	/* Set preamble - only for Symbol so far... */
 644	if (priv->has_preamble) {
 645		err = hermes_write_wordrec(hw, USER_BAP,
 646					   HERMES_RID_CNFPREAMBLE_SYMBOL,
 647					   priv->preamble);
 648		if (err) {
 649			printk(KERN_ERR "%s: Error %d setting preamble\n",
 650			       dev->name, err);
 651			return err;
 652		}
 653	}
 654
 655	/* Set up encryption */
 656	if (priv->has_wep || priv->has_wpa) {
 657		err = __orinoco_hw_setup_enc(priv);
 658		if (err) {
 659			printk(KERN_ERR "%s: Error %d activating encryption\n",
 660			       dev->name, err);
 661			return err;
 662		}
 663	}
 664
 665	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 666		/* Enable monitor mode */
 667		dev->type = ARPHRD_IEEE80211;
 668		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 669					    HERMES_TEST_MONITOR, 0, NULL);
 670	} else {
 671		/* Disable monitor mode */
 672		dev->type = ARPHRD_ETHER;
 673		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 674					    HERMES_TEST_STOP, 0, NULL);
 675	}
 676	if (err)
 677		return err;
 678
 679	/* Reset promiscuity / multicast*/
 680	priv->promiscuous = 0;
 681	priv->mc_count = 0;
 682
 683	/* Record mode change */
 684	wdev->iftype = priv->iw_mode;
 685
 686	return 0;
 687}
 688
 689/* Get tsc from the firmware */
 690int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
 691{
 692	struct hermes *hw = &priv->hw;
 693	int err = 0;
 694	u8 tsc_arr[4][ORINOCO_SEQ_LEN];
 695
 696	if ((key < 0) || (key >= 4))
 697		return -EINVAL;
 698
 699	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
 700				sizeof(tsc_arr), NULL, &tsc_arr);
 701	if (!err)
 702		memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
 703
 704	return err;
 705}
 706
 707int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 708{
 709	struct hermes *hw = &priv->hw;
 710	int ratemode = priv->bitratemode;
 711	int err = 0;
 712
 713	if (ratemode >= BITRATE_TABLE_SIZE) {
 714		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
 715		       priv->ndev->name, ratemode);
 716		return -EINVAL;
 717	}
 718
 719	switch (priv->firmware_type) {
 720	case FIRMWARE_TYPE_AGERE:
 721		err = hermes_write_wordrec(hw, USER_BAP,
 722				HERMES_RID_CNFTXRATECONTROL,
 723				bitrate_table[ratemode].agere_txratectrl);
 724		break;
 725	case FIRMWARE_TYPE_INTERSIL:
 726	case FIRMWARE_TYPE_SYMBOL:
 727		err = hermes_write_wordrec(hw, USER_BAP,
 728				HERMES_RID_CNFTXRATECONTROL,
 729				bitrate_table[ratemode].intersil_txratectrl);
 730		break;
 731	default:
 732		BUG();
 733	}
 734
 735	return err;
 736}
 737
 738int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
 739{
 740	struct hermes *hw = &priv->hw;
 741	int i;
 742	int err = 0;
 743	u16 val;
 744
 745	err = hermes_read_wordrec(hw, USER_BAP,
 746				  HERMES_RID_CURRENTTXRATE, &val);
 747	if (err)
 748		return err;
 749
 750	switch (priv->firmware_type) {
 751	case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
 752		/* Note : in Lucent firmware, the return value of
 753		 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
 754		 * and therefore is totally different from the
 755		 * encoding of HERMES_RID_CNFTXRATECONTROL.
 756		 * Don't forget that 6Mb/s is really 5.5Mb/s */
 757		if (val == 6)
 758			*bitrate = 5500000;
 759		else
 760			*bitrate = val * 1000000;
 761		break;
 762	case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
 763	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
 764		for (i = 0; i < BITRATE_TABLE_SIZE; i++)
 765			if (bitrate_table[i].intersil_txratectrl == val) {
 766				*bitrate = bitrate_table[i].bitrate * 100000;
 767				break;
 768			}
 769
 770		if (i >= BITRATE_TABLE_SIZE) {
 771			printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
 772			       priv->ndev->name, val);
 773			err = -EIO;
 774		}
 775
 776		break;
 777	default:
 778		BUG();
 779	}
 780
 781	return err;
 782}
 783
 784/* Set fixed AP address */
 785int __orinoco_hw_set_wap(struct orinoco_private *priv)
 786{
 787	int roaming_flag;
 788	int err = 0;
 789	struct hermes *hw = &priv->hw;
 790
 791	switch (priv->firmware_type) {
 792	case FIRMWARE_TYPE_AGERE:
 793		/* not supported */
 794		break;
 795	case FIRMWARE_TYPE_INTERSIL:
 796		if (priv->bssid_fixed)
 797			roaming_flag = 2;
 798		else
 799			roaming_flag = 1;
 800
 801		err = hermes_write_wordrec(hw, USER_BAP,
 802					   HERMES_RID_CNFROAMINGMODE,
 803					   roaming_flag);
 804		break;
 805	case FIRMWARE_TYPE_SYMBOL:
 806		err = HERMES_WRITE_RECORD(hw, USER_BAP,
 807					  HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
 808					  &priv->desired_bssid);
 809		break;
 810	}
 811	return err;
 812}
 813
 814/* Change the WEP keys and/or the current keys.  Can be called
 815 * either from __orinoco_hw_setup_enc() or directly from
 816 * orinoco_ioctl_setiwencode().  In the later case the association
 817 * with the AP is not broken (if the firmware can handle it),
 818 * which is needed for 802.1x implementations. */
 819int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 820{
 821	struct hermes *hw = &priv->hw;
 822	int err = 0;
 823	int i;
 824
 825	switch (priv->firmware_type) {
 826	case FIRMWARE_TYPE_AGERE:
 827	{
 828		struct orinoco_key keys[ORINOCO_MAX_KEYS];
 829
 830		memset(&keys, 0, sizeof(keys));
 831		for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
 832			int len = min(priv->keys[i].key_len,
 833				      ORINOCO_MAX_KEY_SIZE);
 834			memcpy(&keys[i].data, priv->keys[i].key, len);
 835			if (len > SMALL_KEY_SIZE)
 836				keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
 837			else if (len > 0)
 838				keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
 839			else
 840				keys[i].len = cpu_to_le16(0);
 841		}
 842
 843		err = HERMES_WRITE_RECORD(hw, USER_BAP,
 844					  HERMES_RID_CNFWEPKEYS_AGERE,
 845					  &keys);
 846		if (err)
 847			return err;
 848		err = hermes_write_wordrec(hw, USER_BAP,
 849					   HERMES_RID_CNFTXKEY_AGERE,
 850					   priv->tx_key);
 851		if (err)
 852			return err;
 853		break;
 854	}
 855	case FIRMWARE_TYPE_INTERSIL:
 856	case FIRMWARE_TYPE_SYMBOL:
 857		{
 858			int keylen;
 859
 860			/* Force uniform key length to work around
 861			 * firmware bugs */
 862			keylen = priv->keys[priv->tx_key].key_len;
 863
 864			if (keylen > LARGE_KEY_SIZE) {
 865				printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
 866				       priv->ndev->name, priv->tx_key, keylen);
 867				return -E2BIG;
 868			} else if (keylen > SMALL_KEY_SIZE)
 869				keylen = LARGE_KEY_SIZE;
 870			else if (keylen > 0)
 871				keylen = SMALL_KEY_SIZE;
 872			else
 873				keylen = 0;
 874
 875			/* Write all 4 keys */
 876			for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
 877				u8 key[LARGE_KEY_SIZE] = { 0 };
 878
 879				memcpy(key, priv->keys[i].key,
 880				       priv->keys[i].key_len);
 881
 882				err = hw->ops->write_ltv(hw, USER_BAP,
 883						HERMES_RID_CNFDEFAULTKEY0 + i,
 884						HERMES_BYTES_TO_RECLEN(keylen),
 885						key);
 886				if (err)
 887					return err;
 888			}
 889
 890			/* Write the index of the key used in transmission */
 891			err = hermes_write_wordrec(hw, USER_BAP,
 892						HERMES_RID_CNFWEPDEFAULTKEYID,
 893						priv->tx_key);
 894			if (err)
 895				return err;
 896		}
 897		break;
 898	}
 899
 900	return 0;
 901}
 902
 903int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 904{
 905	struct hermes *hw = &priv->hw;
 906	int err = 0;
 907	int master_wep_flag;
 908	int auth_flag;
 909	int enc_flag;
 910
 911	/* Setup WEP keys */
 912	if (priv->encode_alg == ORINOCO_ALG_WEP)
 913		__orinoco_hw_setup_wepkeys(priv);
 914
 915	if (priv->wep_restrict)
 916		auth_flag = HERMES_AUTH_SHARED_KEY;
 917	else
 918		auth_flag = HERMES_AUTH_OPEN;
 919
 920	if (priv->wpa_enabled)
 921		enc_flag = 2;
 922	else if (priv->encode_alg == ORINOCO_ALG_WEP)
 923		enc_flag = 1;
 924	else
 925		enc_flag = 0;
 926
 927	switch (priv->firmware_type) {
 928	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
 929		if (priv->encode_alg == ORINOCO_ALG_WEP) {
 930			/* Enable the shared-key authentication. */
 931			err = hermes_write_wordrec(hw, USER_BAP,
 932					HERMES_RID_CNFAUTHENTICATION_AGERE,
 933					auth_flag);
 934		}
 935		err = hermes_write_wordrec(hw, USER_BAP,
 936					   HERMES_RID_CNFWEPENABLED_AGERE,
 937					   enc_flag);
 938		if (err)
 939			return err;
 940
 941		if (priv->has_wpa) {
 942			/* Set WPA key management */
 943			err = hermes_write_wordrec(hw, USER_BAP,
 944				  HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
 945				  priv->key_mgmt);
 946			if (err)
 947				return err;
 948		}
 949
 950		break;
 951
 952	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
 953	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
 954		if (priv->encode_alg == ORINOCO_ALG_WEP) {
 955			if (priv->wep_restrict ||
 956			    (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
 957				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
 958						  HERMES_WEP_EXCL_UNENCRYPTED;
 959			else
 960				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
 961
 962			err = hermes_write_wordrec(hw, USER_BAP,
 963						   HERMES_RID_CNFAUTHENTICATION,
 964						   auth_flag);
 965			if (err)
 966				return err;
 967		} else
 968			master_wep_flag = 0;
 969
 970		if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
 971			master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
 972
 973		/* Master WEP setting : on/off */
 974		err = hermes_write_wordrec(hw, USER_BAP,
 975					   HERMES_RID_CNFWEPFLAGS_INTERSIL,
 976					   master_wep_flag);
 977		if (err)
 978			return err;
 979
 980		break;
 981	}
 982
 983	return 0;
 984}
 985
 986/* key must be 32 bytes, including the tx and rx MIC keys.
 987 * rsc must be NULL or up to 8 bytes
 988 * tsc must be NULL or up to 8 bytes
 989 */
 990int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
 991			      int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
 992			      u8 *tsc, size_t tsc_len)
 993{
 994	struct {
 995		__le16 idx;
 996		u8 rsc[ORINOCO_SEQ_LEN];
 997		u8 key[TKIP_KEYLEN];
 998		u8 tx_mic[MIC_KEYLEN];
 999		u8 rx_mic[MIC_KEYLEN];
1000		u8 tsc[ORINOCO_SEQ_LEN];
1001	} __packed buf;
1002	struct hermes *hw = &priv->hw;
1003	int ret;
1004	int err;
1005	int k;
1006	u16 xmitting;
1007
1008	key_idx &= 0x3;
1009
1010	if (set_tx)
1011		key_idx |= 0x8000;
1012
1013	buf.idx = cpu_to_le16(key_idx);
1014	memcpy(buf.key, key,
1015	       sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
1016
1017	if (rsc_len > sizeof(buf.rsc))
1018		rsc_len = sizeof(buf.rsc);
1019
1020	if (tsc_len > sizeof(buf.tsc))
1021		tsc_len = sizeof(buf.tsc);
1022
1023	memset(buf.rsc, 0, sizeof(buf.rsc));
1024	memset(buf.tsc, 0, sizeof(buf.tsc));
1025
1026	if (rsc != NULL)
1027		memcpy(buf.rsc, rsc, rsc_len);
1028
1029	if (tsc != NULL)
1030		memcpy(buf.tsc, tsc, tsc_len);
1031	else
1032		buf.tsc[4] = 0x10;
1033
1034	/* Wait up to 100ms for tx queue to empty */
1035	for (k = 100; k > 0; k--) {
1036		udelay(1000);
1037		ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
1038					  &xmitting);
1039		if (ret || !xmitting)
1040			break;
1041	}
1042
1043	if (k == 0)
1044		ret = -ETIMEDOUT;
1045
1046	err = HERMES_WRITE_RECORD(hw, USER_BAP,
1047				  HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
1048				  &buf);
1049
1050	return ret ? ret : err;
1051}
1052
1053int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
1054{
1055	struct hermes *hw = &priv->hw;
1056	int err;
1057
1058	err = hermes_write_wordrec(hw, USER_BAP,
1059				   HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
1060				   key_idx);
1061	if (err)
1062		printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
1063		       priv->ndev->name, err, key_idx);
1064	return err;
1065}
1066
1067int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
1068				    struct net_device *dev,
1069				    int mc_count, int promisc)
1070{
1071	struct hermes *hw = &priv->hw;
1072	int err = 0;
1073
1074	if (promisc != priv->promiscuous) {
1075		err = hermes_write_wordrec(hw, USER_BAP,
1076					   HERMES_RID_CNFPROMISCUOUSMODE,
1077					   promisc);
1078		if (err) {
1079			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
1080			       priv->ndev->name, err);
1081		} else
1082			priv->promiscuous = promisc;
1083	}
1084
1085	/* If we're not in promiscuous mode, then we need to set the
1086	 * group address if either we want to multicast, or if we were
1087	 * multicasting and want to stop */
1088	if (!promisc && (mc_count || priv->mc_count)) {
1089		struct netdev_hw_addr *ha;
1090		struct hermes_multicast mclist;
1091		int i = 0;
1092
1093		netdev_for_each_mc_addr(ha, dev) {
1094			if (i == mc_count)
1095				break;
1096			memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
1097		}
1098
1099		err = hw->ops->write_ltv(hw, USER_BAP,
1100				   HERMES_RID_CNFGROUPADDRESSES,
1101				   HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
1102				   &mclist);
1103		if (err)
1104			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
1105			       priv->ndev->name, err);
1106		else
1107			priv->mc_count = mc_count;
1108	}
1109	return err;
1110}
1111
1112/* Return : < 0 -> error code ; >= 0 -> length */
1113int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
1114			 char buf[IW_ESSID_MAX_SIZE + 1])
1115{
1116	struct hermes *hw = &priv->hw;
1117	int err = 0;
1118	struct hermes_idstring essidbuf;
1119	char *p = (char *)(&essidbuf.val);
1120	int len;
1121	unsigned long flags;
1122
1123	if (orinoco_lock(priv, &flags) != 0)
1124		return -EBUSY;
1125
1126	if (strlen(priv->desired_essid) > 0) {
1127		/* We read the desired SSID from the hardware rather
1128		   than from priv->desired_essid, just in case the
1129		   firmware is allowed to change it on us. I'm not
1130		   sure about this */
1131		/* My guess is that the OWNSSID should always be whatever
1132		 * we set to the card, whereas CURRENT_SSID is the one that
1133		 * may change... - Jean II */
1134		u16 rid;
1135
1136		*active = 1;
1137
1138		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
1139			HERMES_RID_CNFDESIREDSSID;
1140
1141		err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
1142					NULL, &essidbuf);
1143		if (err)
1144			goto fail_unlock;
1145	} else {
1146		*active = 0;
1147
1148		err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
1149					sizeof(essidbuf), NULL, &essidbuf);
1150		if (err)
1151			goto fail_unlock;
1152	}
1153
1154	len = le16_to_cpu(essidbuf.len);
1155	BUG_ON(len > IW_ESSID_MAX_SIZE);
1156
1157	memset(buf, 0, IW_ESSID_MAX_SIZE);
1158	memcpy(buf, p, len);
1159	err = len;
1160
1161 fail_unlock:
1162	orinoco_unlock(priv, &flags);
1163
1164	return err;
1165}
1166
1167int orinoco_hw_get_freq(struct orinoco_private *priv)
1168{
1169	struct hermes *hw = &priv->hw;
1170	int err = 0;
1171	u16 channel;
1172	int freq = 0;
1173	unsigned long flags;
1174
1175	if (orinoco_lock(priv, &flags) != 0)
1176		return -EBUSY;
1177
1178	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
1179				  &channel);
1180	if (err)
1181		goto out;
1182
1183	/* Intersil firmware 1.3.5 returns 0 when the interface is down */
1184	if (channel == 0) {
1185		err = -EBUSY;
1186		goto out;
1187	}
1188
1189	if ((channel < 1) || (channel > NUM_CHANNELS)) {
1190		printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
1191		       priv->ndev->name, channel);
1192		err = -EBUSY;
1193		goto out;
1194
1195	}
1196	freq = ieee80211_dsss_chan_to_freq(channel);
1197
1198 out:
1199	orinoco_unlock(priv, &flags);
1200
1201	if (err > 0)
1202		err = -EBUSY;
1203	return err ? err : freq;
1204}
1205
1206int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
1207			       int *numrates, s32 *rates, int max)
1208{
1209	struct hermes *hw = &priv->hw;
1210	struct hermes_idstring list;
1211	unsigned char *p = (unsigned char *)&list.val;
1212	int err = 0;
1213	int num;
1214	int i;
1215	unsigned long flags;
1216
1217	if (orinoco_lock(priv, &flags) != 0)
1218		return -EBUSY;
1219
1220	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
1221				sizeof(list), NULL, &list);
1222	orinoco_unlock(priv, &flags);
1223
1224	if (err)
1225		return err;
1226
1227	num = le16_to_cpu(list.len);
1228	*numrates = num;
1229	num = min(num, max);
1230
1231	for (i = 0; i < num; i++)
1232		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
1233
1234	return 0;
1235}
1236
1237int orinoco_hw_trigger_scan(struct orinoco_private *priv,
1238			    const struct cfg80211_ssid *ssid)
1239{
1240	struct net_device *dev = priv->ndev;
1241	struct hermes *hw = &priv->hw;
1242	unsigned long flags;
1243	int err = 0;
1244
1245	if (orinoco_lock(priv, &flags) != 0)
1246		return -EBUSY;
1247
1248	/* Scanning with port 0 disabled would fail */
1249	if (!netif_running(dev)) {
1250		err = -ENETDOWN;
1251		goto out;
1252	}
1253
1254	/* In monitor mode, the scan results are always empty.
1255	 * Probe responses are passed to the driver as received
1256	 * frames and could be processed in software. */
1257	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
1258		err = -EOPNOTSUPP;
1259		goto out;
1260	}
1261
1262	if (priv->has_hostscan) {
1263		switch (priv->firmware_type) {
1264		case FIRMWARE_TYPE_SYMBOL:
1265			err = hermes_write_wordrec(hw, USER_BAP,
1266						HERMES_RID_CNFHOSTSCAN_SYMBOL,
1267						HERMES_HOSTSCAN_SYMBOL_ONCE |
1268						HERMES_HOSTSCAN_SYMBOL_BCAST);
1269			break;
1270		case FIRMWARE_TYPE_INTERSIL: {
1271			__le16 req[3];
1272
1273			req[0] = cpu_to_le16(0x3fff);	/* All channels */
1274			req[1] = cpu_to_le16(0x0001);	/* rate 1 Mbps */
1275			req[2] = 0;			/* Any ESSID */
1276			err = HERMES_WRITE_RECORD(hw, USER_BAP,
1277						  HERMES_RID_CNFHOSTSCAN, &req);
1278			break;
1279		}
1280		case FIRMWARE_TYPE_AGERE:
1281			if (ssid->ssid_len > 0) {
1282				struct hermes_idstring idbuf;
1283				size_t len = ssid->ssid_len;
1284
1285				idbuf.len = cpu_to_le16(len);
1286				memcpy(idbuf.val, ssid->ssid, len);
1287
1288				err = hw->ops->write_ltv(hw, USER_BAP,
1289					       HERMES_RID_CNFSCANSSID_AGERE,
1290					       HERMES_BYTES_TO_RECLEN(len + 2),
1291					       &idbuf);
1292			} else
1293				err = hermes_write_wordrec(hw, USER_BAP,
1294						   HERMES_RID_CNFSCANSSID_AGERE,
1295						   0);	/* Any ESSID */
1296			if (err)
1297				break;
1298
1299			if (priv->has_ext_scan) {
1300				err = hermes_write_wordrec(hw, USER_BAP,
1301						HERMES_RID_CNFSCANCHANNELS2GHZ,
1302						0x7FFF);
1303				if (err)
1304					goto out;
1305
1306				err = hermes_inquire(hw,
1307						     HERMES_INQ_CHANNELINFO);
1308			} else
1309				err = hermes_inquire(hw, HERMES_INQ_SCAN);
1310
1311			break;
1312		}
1313	} else
1314		err = hermes_inquire(hw, HERMES_INQ_SCAN);
1315
1316 out:
1317	orinoco_unlock(priv, &flags);
1318
1319	return err;
1320}
1321
1322/* Disassociate from node with BSSID addr */
1323int orinoco_hw_disassociate(struct orinoco_private *priv,
1324			    u8 *addr, u16 reason_code)
1325{
1326	struct hermes *hw = &priv->hw;
1327	int err;
1328
1329	struct {
1330		u8 addr[ETH_ALEN];
1331		__le16 reason_code;
1332	} __packed buf;
1333
1334	/* Currently only supported by WPA enabled Agere fw */
1335	if (!priv->has_wpa)
1336		return -EOPNOTSUPP;
1337
1338	memcpy(buf.addr, addr, ETH_ALEN);
1339	buf.reason_code = cpu_to_le16(reason_code);
1340	err = HERMES_WRITE_RECORD(hw, USER_BAP,
1341				  HERMES_RID_CNFDISASSOCIATE,
1342				  &buf);
1343	return err;
1344}
1345
1346int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
1347				 u8 *addr)
1348{
1349	struct hermes *hw = &priv->hw;
1350	int err;
1351
1352	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
1353				ETH_ALEN, NULL, addr);
1354
1355	return err;
1356}
v3.5.6
   1/* Encapsulate basic setting changes and retrieval on Hermes hardware
   2 *
   3 * See copyright notice in main.c
   4 */
   5#include <linux/kernel.h>
   6#include <linux/device.h>
   7#include <linux/if_arp.h>
   8#include <linux/ieee80211.h>
   9#include <linux/wireless.h>
  10#include <net/cfg80211.h>
  11#include "hermes.h"
  12#include "hermes_rid.h"
  13#include "orinoco.h"
  14
  15#include "hw.h"
  16
  17#define SYMBOL_MAX_VER_LEN	(14)
  18
  19/* Symbol firmware has a bug allocating buffers larger than this */
  20#define TX_NICBUF_SIZE_BUG	1585
  21
  22/********************************************************************/
  23/* Data tables                                                      */
  24/********************************************************************/
  25
  26/* This tables gives the actual meanings of the bitrate IDs returned
  27 * by the firmware. */
  28static const struct {
  29	int bitrate; /* in 100s of kilobits */
  30	int automatic;
  31	u16 agere_txratectrl;
  32	u16 intersil_txratectrl;
  33} bitrate_table[] = {
  34	{110, 1,  3, 15}, /* Entry 0 is the default */
  35	{10,  0,  1,  1},
  36	{10,  1,  1,  1},
  37	{20,  0,  2,  2},
  38	{20,  1,  6,  3},
  39	{55,  0,  4,  4},
  40	{55,  1,  7,  7},
  41	{110, 0,  5,  8},
  42};
  43#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
  44
  45/* Firmware version encoding */
  46struct comp_id {
  47	u16 id, variant, major, minor;
  48} __packed;
  49
  50static inline enum fwtype determine_firmware_type(struct comp_id *nic_id)
  51{
  52	if (nic_id->id < 0x8000)
  53		return FIRMWARE_TYPE_AGERE;
  54	else if (nic_id->id == 0x8000 && nic_id->major == 0)
  55		return FIRMWARE_TYPE_SYMBOL;
  56	else
  57		return FIRMWARE_TYPE_INTERSIL;
  58}
  59
  60/* Set priv->firmware type, determine firmware properties
  61 * This function can be called before we have registerred with netdev,
  62 * so all errors go out with dev_* rather than printk
  63 *
  64 * If non-NULL stores a firmware description in fw_name.
  65 * If non-NULL stores a HW version in hw_ver
  66 *
  67 * These are output via generic cfg80211 ethtool support.
  68 */
  69int determine_fw_capabilities(struct orinoco_private *priv,
  70			      char *fw_name, size_t fw_name_len,
  71			      u32 *hw_ver)
  72{
  73	struct device *dev = priv->dev;
  74	struct hermes *hw = &priv->hw;
  75	int err;
  76	struct comp_id nic_id, sta_id;
  77	unsigned int firmver;
  78	char tmp[SYMBOL_MAX_VER_LEN + 1] __attribute__((aligned(2)));
  79
  80	/* Get the hardware version */
  81	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
  82	if (err) {
  83		dev_err(dev, "Cannot read hardware identity: error %d\n",
  84			err);
  85		return err;
  86	}
  87
  88	le16_to_cpus(&nic_id.id);
  89	le16_to_cpus(&nic_id.variant);
  90	le16_to_cpus(&nic_id.major);
  91	le16_to_cpus(&nic_id.minor);
  92	dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n",
  93		 nic_id.id, nic_id.variant, nic_id.major, nic_id.minor);
  94
  95	if (hw_ver)
  96		*hw_ver = (((nic_id.id & 0xff) << 24) |
  97			   ((nic_id.variant & 0xff) << 16) |
  98			   ((nic_id.major & 0xff) << 8) |
  99			   (nic_id.minor & 0xff));
 100
 101	priv->firmware_type = determine_firmware_type(&nic_id);
 102
 103	/* Get the firmware version */
 104	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
 105	if (err) {
 106		dev_err(dev, "Cannot read station identity: error %d\n",
 107			err);
 108		return err;
 109	}
 110
 111	le16_to_cpus(&sta_id.id);
 112	le16_to_cpus(&sta_id.variant);
 113	le16_to_cpus(&sta_id.major);
 114	le16_to_cpus(&sta_id.minor);
 115	dev_info(dev, "Station identity  %04x:%04x:%04x:%04x\n",
 116		 sta_id.id, sta_id.variant, sta_id.major, sta_id.minor);
 117
 118	switch (sta_id.id) {
 119	case 0x15:
 120		dev_err(dev, "Primary firmware is active\n");
 121		return -ENODEV;
 122	case 0x14b:
 123		dev_err(dev, "Tertiary firmware is active\n");
 124		return -ENODEV;
 125	case 0x1f:	/* Intersil, Agere, Symbol Spectrum24 */
 126	case 0x21:	/* Symbol Spectrum24 Trilogy */
 127		break;
 128	default:
 129		dev_notice(dev, "Unknown station ID, please report\n");
 130		break;
 131	}
 132
 133	/* Default capabilities */
 134	priv->has_sensitivity = 1;
 135	priv->has_mwo = 0;
 136	priv->has_preamble = 0;
 137	priv->has_port3 = 1;
 138	priv->has_ibss = 1;
 139	priv->has_wep = 0;
 140	priv->has_big_wep = 0;
 141	priv->has_alt_txcntl = 0;
 142	priv->has_ext_scan = 0;
 143	priv->has_wpa = 0;
 144	priv->do_fw_download = 0;
 145
 146	/* Determine capabilities from the firmware version */
 147	switch (priv->firmware_type) {
 148	case FIRMWARE_TYPE_AGERE:
 149		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
 150		   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
 151		if (fw_name)
 152			snprintf(fw_name, fw_name_len, "Lucent/Agere %d.%02d",
 153				 sta_id.major, sta_id.minor);
 154
 155		firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
 156
 157		priv->has_ibss = (firmver >= 0x60006);
 158		priv->has_wep = (firmver >= 0x40020);
 159		priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
 160					  Gold cards from the others? */
 161		priv->has_mwo = (firmver >= 0x60000);
 162		priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
 163		priv->ibss_port = 1;
 164		priv->has_hostscan = (firmver >= 0x8000a);
 165		priv->do_fw_download = 1;
 166		priv->broken_monitor = (firmver >= 0x80000);
 167		priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
 168		priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
 169		priv->has_wpa = (firmver >= 0x9002a);
 170		/* Tested with Agere firmware :
 171		 *	1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
 172		 * Tested CableTron firmware : 4.32 => Anton */
 173		break;
 174	case FIRMWARE_TYPE_SYMBOL:
 175		/* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
 176		/* Intel MAC : 00:02:B3:* */
 177		/* 3Com MAC : 00:50:DA:* */
 178		memset(tmp, 0, sizeof(tmp));
 179		/* Get the Symbol firmware version */
 180		err = hw->ops->read_ltv(hw, USER_BAP,
 181					HERMES_RID_SECONDARYVERSION_SYMBOL,
 182					SYMBOL_MAX_VER_LEN, NULL, &tmp);
 183		if (err) {
 184			dev_warn(dev, "Error %d reading Symbol firmware info. "
 185				 "Wildly guessing capabilities...\n", err);
 186			firmver = 0;
 187			tmp[0] = '\0';
 188		} else {
 189			/* The firmware revision is a string, the format is
 190			 * something like : "V2.20-01".
 191			 * Quick and dirty parsing... - Jean II
 192			 */
 193			firmver = ((tmp[1] - '0') << 16)
 194				| ((tmp[3] - '0') << 12)
 195				| ((tmp[4] - '0') << 8)
 196				| ((tmp[6] - '0') << 4)
 197				| (tmp[7] - '0');
 198
 199			tmp[SYMBOL_MAX_VER_LEN] = '\0';
 200		}
 201
 202		if (fw_name)
 203			snprintf(fw_name, fw_name_len, "Symbol %s", tmp);
 204
 205		priv->has_ibss = (firmver >= 0x20000);
 206		priv->has_wep = (firmver >= 0x15012);
 207		priv->has_big_wep = (firmver >= 0x20000);
 208		priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
 209			       (firmver >= 0x29000 && firmver < 0x30000) ||
 210			       firmver >= 0x31000;
 211		priv->has_preamble = (firmver >= 0x20000);
 212		priv->ibss_port = 4;
 213
 214		/* Symbol firmware is found on various cards, but
 215		 * there has been no attempt to check firmware
 216		 * download on non-spectrum_cs based cards.
 217		 *
 218		 * Given that the Agere firmware download works
 219		 * differently, we should avoid doing a firmware
 220		 * download with the Symbol algorithm on non-spectrum
 221		 * cards.
 222		 *
 223		 * For now we can identify a spectrum_cs based card
 224		 * because it has a firmware reset function.
 225		 */
 226		priv->do_fw_download = (priv->stop_fw != NULL);
 227
 228		priv->broken_disableport = (firmver == 0x25013) ||
 229				(firmver >= 0x30000 && firmver <= 0x31000);
 230		priv->has_hostscan = (firmver >= 0x31001) ||
 231				     (firmver >= 0x29057 && firmver < 0x30000);
 232		/* Tested with Intel firmware : 0x20015 => Jean II */
 233		/* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
 234		break;
 235	case FIRMWARE_TYPE_INTERSIL:
 236		/* D-Link, Linksys, Adtron, ZoomAir, and many others...
 237		 * Samsung, Compaq 100/200 and Proxim are slightly
 238		 * different and less well tested */
 239		/* D-Link MAC : 00:40:05:* */
 240		/* Addtron MAC : 00:90:D1:* */
 241		if (fw_name)
 242			snprintf(fw_name, fw_name_len, "Intersil %d.%d.%d",
 243				 sta_id.major, sta_id.minor, sta_id.variant);
 244
 245		firmver = ((unsigned long)sta_id.major << 16) |
 246			((unsigned long)sta_id.minor << 8) | sta_id.variant;
 247
 248		priv->has_ibss = (firmver >= 0x000700); /* FIXME */
 249		priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
 250		priv->has_pm = (firmver >= 0x000700);
 251		priv->has_hostscan = (firmver >= 0x010301);
 252
 253		if (firmver >= 0x000800)
 254			priv->ibss_port = 0;
 255		else {
 256			dev_notice(dev, "Intersil firmware earlier than v0.8.x"
 257				   " - several features not supported\n");
 258			priv->ibss_port = 1;
 259		}
 260		break;
 261	}
 262	if (fw_name)
 263		dev_info(dev, "Firmware determined as %s\n", fw_name);
 264
 265#ifndef CONFIG_HERMES_PRISM
 266	if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
 267		dev_err(dev, "Support for Prism chipset is not enabled\n");
 268		return -ENODEV;
 269	}
 270#endif
 271
 272	return 0;
 273}
 274
 275/* Read settings from EEPROM into our private structure.
 276 * MAC address gets dropped into callers buffer
 277 * Can be called before netdev registration.
 278 */
 279int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr)
 280{
 281	struct device *dev = priv->dev;
 282	struct hermes_idstring nickbuf;
 283	struct hermes *hw = &priv->hw;
 284	int len;
 285	int err;
 286	u16 reclen;
 287
 288	/* Get the MAC address */
 289	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
 290				ETH_ALEN, NULL, dev_addr);
 291	if (err) {
 292		dev_warn(dev, "Failed to read MAC address!\n");
 293		goto out;
 294	}
 295
 296	dev_dbg(dev, "MAC address %pM\n", dev_addr);
 297
 298	/* Get the station name */
 299	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
 300				sizeof(nickbuf), &reclen, &nickbuf);
 301	if (err) {
 302		dev_err(dev, "failed to read station name\n");
 303		goto out;
 304	}
 305	if (nickbuf.len)
 306		len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
 307	else
 308		len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
 309	memcpy(priv->nick, &nickbuf.val, len);
 310	priv->nick[len] = '\0';
 311
 312	dev_dbg(dev, "Station name \"%s\"\n", priv->nick);
 313
 314	/* Get allowed channels */
 315	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
 316				  &priv->channel_mask);
 317	if (err) {
 318		dev_err(dev, "Failed to read channel list!\n");
 319		goto out;
 320	}
 321
 322	/* Get initial AP density */
 323	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
 324				  &priv->ap_density);
 325	if (err || priv->ap_density < 1 || priv->ap_density > 3)
 326		priv->has_sensitivity = 0;
 327
 328	/* Get initial RTS threshold */
 329	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
 330				  &priv->rts_thresh);
 331	if (err) {
 332		dev_err(dev, "Failed to read RTS threshold!\n");
 333		goto out;
 334	}
 335
 336	/* Get initial fragmentation settings */
 337	if (priv->has_mwo)
 338		err = hermes_read_wordrec(hw, USER_BAP,
 339					  HERMES_RID_CNFMWOROBUST_AGERE,
 340					  &priv->mwo_robust);
 341	else
 342		err = hermes_read_wordrec(hw, USER_BAP,
 343					  HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 344					  &priv->frag_thresh);
 345	if (err) {
 346		dev_err(dev, "Failed to read fragmentation settings!\n");
 347		goto out;
 348	}
 349
 350	/* Power management setup */
 351	if (priv->has_pm) {
 352		priv->pm_on = 0;
 353		priv->pm_mcast = 1;
 354		err = hermes_read_wordrec(hw, USER_BAP,
 355					  HERMES_RID_CNFMAXSLEEPDURATION,
 356					  &priv->pm_period);
 357		if (err) {
 358			dev_err(dev, "Failed to read power management "
 359				"period!\n");
 360			goto out;
 361		}
 362		err = hermes_read_wordrec(hw, USER_BAP,
 363					  HERMES_RID_CNFPMHOLDOVERDURATION,
 364					  &priv->pm_timeout);
 365		if (err) {
 366			dev_err(dev, "Failed to read power management "
 367				"timeout!\n");
 368			goto out;
 369		}
 370	}
 371
 372	/* Preamble setup */
 373	if (priv->has_preamble) {
 374		err = hermes_read_wordrec(hw, USER_BAP,
 375					  HERMES_RID_CNFPREAMBLE_SYMBOL,
 376					  &priv->preamble);
 377		if (err) {
 378			dev_err(dev, "Failed to read preamble setup\n");
 379			goto out;
 380		}
 381	}
 382
 383	/* Retry settings */
 384	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
 385				  &priv->short_retry_limit);
 386	if (err) {
 387		dev_err(dev, "Failed to read short retry limit\n");
 388		goto out;
 389	}
 390
 391	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
 392				  &priv->long_retry_limit);
 393	if (err) {
 394		dev_err(dev, "Failed to read long retry limit\n");
 395		goto out;
 396	}
 397
 398	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
 399				  &priv->retry_lifetime);
 400	if (err) {
 401		dev_err(dev, "Failed to read max retry lifetime\n");
 402		goto out;
 403	}
 404
 405out:
 406	return err;
 407}
 408
 409/* Can be called before netdev registration */
 410int orinoco_hw_allocate_fid(struct orinoco_private *priv)
 411{
 412	struct device *dev = priv->dev;
 413	struct hermes *hw = &priv->hw;
 414	int err;
 415
 416	err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
 417	if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
 418		/* Try workaround for old Symbol firmware bug */
 419		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
 420		err = hw->ops->allocate(hw, priv->nicbuf_size, &priv->txfid);
 421
 422		dev_warn(dev, "Firmware ALLOC bug detected "
 423			 "(old Symbol firmware?). Work around %s\n",
 424			 err ? "failed!" : "ok.");
 425	}
 426
 427	return err;
 428}
 429
 430int orinoco_get_bitratemode(int bitrate, int automatic)
 431{
 432	int ratemode = -1;
 433	int i;
 434
 435	if ((bitrate != 10) && (bitrate != 20) &&
 436	    (bitrate != 55) && (bitrate != 110))
 437		return ratemode;
 438
 439	for (i = 0; i < BITRATE_TABLE_SIZE; i++) {
 440		if ((bitrate_table[i].bitrate == bitrate) &&
 441		    (bitrate_table[i].automatic == automatic)) {
 442			ratemode = i;
 443			break;
 444		}
 445	}
 446	return ratemode;
 447}
 448
 449void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic)
 450{
 451	BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
 452
 453	*bitrate = bitrate_table[ratemode].bitrate * 100000;
 454	*automatic = bitrate_table[ratemode].automatic;
 455}
 456
 457int orinoco_hw_program_rids(struct orinoco_private *priv)
 458{
 459	struct net_device *dev = priv->ndev;
 460	struct wireless_dev *wdev = netdev_priv(dev);
 461	struct hermes *hw = &priv->hw;
 462	int err;
 463	struct hermes_idstring idbuf;
 464
 465	/* Set the MAC address */
 466	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
 467				 HERMES_BYTES_TO_RECLEN(ETH_ALEN),
 468				 dev->dev_addr);
 469	if (err) {
 470		printk(KERN_ERR "%s: Error %d setting MAC address\n",
 471		       dev->name, err);
 472		return err;
 473	}
 474
 475	/* Set up the link mode */
 476	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
 477				   priv->port_type);
 478	if (err) {
 479		printk(KERN_ERR "%s: Error %d setting port type\n",
 480		       dev->name, err);
 481		return err;
 482	}
 483	/* Set the channel/frequency */
 484	if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) {
 485		err = hermes_write_wordrec(hw, USER_BAP,
 486					   HERMES_RID_CNFOWNCHANNEL,
 487					   priv->channel);
 488		if (err) {
 489			printk(KERN_ERR "%s: Error %d setting channel %d\n",
 490			       dev->name, err, priv->channel);
 491			return err;
 492		}
 493	}
 494
 495	if (priv->has_ibss) {
 496		u16 createibss;
 497
 498		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
 499			printk(KERN_WARNING "%s: This firmware requires an "
 500			       "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
 501			/* With wvlan_cs, in this case, we would crash.
 502			 * hopefully, this driver will behave better...
 503			 * Jean II */
 504			createibss = 0;
 505		} else {
 506			createibss = priv->createibss;
 507		}
 508
 509		err = hermes_write_wordrec(hw, USER_BAP,
 510					   HERMES_RID_CNFCREATEIBSS,
 511					   createibss);
 512		if (err) {
 513			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
 514			       dev->name, err);
 515			return err;
 516		}
 517	}
 518
 519	/* Set the desired BSSID */
 520	err = __orinoco_hw_set_wap(priv);
 521	if (err) {
 522		printk(KERN_ERR "%s: Error %d setting AP address\n",
 523		       dev->name, err);
 524		return err;
 525	}
 526
 527	/* Set the desired ESSID */
 528	idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
 529	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
 530	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
 531	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
 532			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
 533			&idbuf);
 534	if (err) {
 535		printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
 536		       dev->name, err);
 537		return err;
 538	}
 539	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
 540			HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid) + 2),
 541			&idbuf);
 542	if (err) {
 543		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
 544		       dev->name, err);
 545		return err;
 546	}
 547
 548	/* Set the station name */
 549	idbuf.len = cpu_to_le16(strlen(priv->nick));
 550	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
 551	err = hw->ops->write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
 552				 HERMES_BYTES_TO_RECLEN(strlen(priv->nick) + 2),
 553				 &idbuf);
 554	if (err) {
 555		printk(KERN_ERR "%s: Error %d setting nickname\n",
 556		       dev->name, err);
 557		return err;
 558	}
 559
 560	/* Set AP density */
 561	if (priv->has_sensitivity) {
 562		err = hermes_write_wordrec(hw, USER_BAP,
 563					   HERMES_RID_CNFSYSTEMSCALE,
 564					   priv->ap_density);
 565		if (err) {
 566			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
 567			       "Disabling sensitivity control\n",
 568			       dev->name, err);
 569
 570			priv->has_sensitivity = 0;
 571		}
 572	}
 573
 574	/* Set RTS threshold */
 575	err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
 576				   priv->rts_thresh);
 577	if (err) {
 578		printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
 579		       dev->name, err);
 580		return err;
 581	}
 582
 583	/* Set fragmentation threshold or MWO robustness */
 584	if (priv->has_mwo)
 585		err = hermes_write_wordrec(hw, USER_BAP,
 586					   HERMES_RID_CNFMWOROBUST_AGERE,
 587					   priv->mwo_robust);
 588	else
 589		err = hermes_write_wordrec(hw, USER_BAP,
 590					   HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
 591					   priv->frag_thresh);
 592	if (err) {
 593		printk(KERN_ERR "%s: Error %d setting fragmentation\n",
 594		       dev->name, err);
 595		return err;
 596	}
 597
 598	/* Set bitrate */
 599	err = __orinoco_hw_set_bitrate(priv);
 600	if (err) {
 601		printk(KERN_ERR "%s: Error %d setting bitrate\n",
 602		       dev->name, err);
 603		return err;
 604	}
 605
 606	/* Set power management */
 607	if (priv->has_pm) {
 608		err = hermes_write_wordrec(hw, USER_BAP,
 609					   HERMES_RID_CNFPMENABLED,
 610					   priv->pm_on);
 611		if (err) {
 612			printk(KERN_ERR "%s: Error %d setting up PM\n",
 613			       dev->name, err);
 614			return err;
 615		}
 616
 617		err = hermes_write_wordrec(hw, USER_BAP,
 618					   HERMES_RID_CNFMULTICASTRECEIVE,
 619					   priv->pm_mcast);
 620		if (err) {
 621			printk(KERN_ERR "%s: Error %d setting up PM\n",
 622			       dev->name, err);
 623			return err;
 624		}
 625		err = hermes_write_wordrec(hw, USER_BAP,
 626					   HERMES_RID_CNFMAXSLEEPDURATION,
 627					   priv->pm_period);
 628		if (err) {
 629			printk(KERN_ERR "%s: Error %d setting up PM\n",
 630			       dev->name, err);
 631			return err;
 632		}
 633		err = hermes_write_wordrec(hw, USER_BAP,
 634					   HERMES_RID_CNFPMHOLDOVERDURATION,
 635					   priv->pm_timeout);
 636		if (err) {
 637			printk(KERN_ERR "%s: Error %d setting up PM\n",
 638			       dev->name, err);
 639			return err;
 640		}
 641	}
 642
 643	/* Set preamble - only for Symbol so far... */
 644	if (priv->has_preamble) {
 645		err = hermes_write_wordrec(hw, USER_BAP,
 646					   HERMES_RID_CNFPREAMBLE_SYMBOL,
 647					   priv->preamble);
 648		if (err) {
 649			printk(KERN_ERR "%s: Error %d setting preamble\n",
 650			       dev->name, err);
 651			return err;
 652		}
 653	}
 654
 655	/* Set up encryption */
 656	if (priv->has_wep || priv->has_wpa) {
 657		err = __orinoco_hw_setup_enc(priv);
 658		if (err) {
 659			printk(KERN_ERR "%s: Error %d activating encryption\n",
 660			       dev->name, err);
 661			return err;
 662		}
 663	}
 664
 665	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
 666		/* Enable monitor mode */
 667		dev->type = ARPHRD_IEEE80211;
 668		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 669					    HERMES_TEST_MONITOR, 0, NULL);
 670	} else {
 671		/* Disable monitor mode */
 672		dev->type = ARPHRD_ETHER;
 673		err = hw->ops->cmd_wait(hw, HERMES_CMD_TEST |
 674					    HERMES_TEST_STOP, 0, NULL);
 675	}
 676	if (err)
 677		return err;
 678
 679	/* Reset promiscuity / multicast*/
 680	priv->promiscuous = 0;
 681	priv->mc_count = 0;
 682
 683	/* Record mode change */
 684	wdev->iftype = priv->iw_mode;
 685
 686	return 0;
 687}
 688
 689/* Get tsc from the firmware */
 690int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc)
 691{
 692	struct hermes *hw = &priv->hw;
 693	int err = 0;
 694	u8 tsc_arr[4][ORINOCO_SEQ_LEN];
 695
 696	if ((key < 0) || (key >= 4))
 697		return -EINVAL;
 698
 699	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
 700				sizeof(tsc_arr), NULL, &tsc_arr);
 701	if (!err)
 702		memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
 703
 704	return err;
 705}
 706
 707int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
 708{
 709	struct hermes *hw = &priv->hw;
 710	int ratemode = priv->bitratemode;
 711	int err = 0;
 712
 713	if (ratemode >= BITRATE_TABLE_SIZE) {
 714		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
 715		       priv->ndev->name, ratemode);
 716		return -EINVAL;
 717	}
 718
 719	switch (priv->firmware_type) {
 720	case FIRMWARE_TYPE_AGERE:
 721		err = hermes_write_wordrec(hw, USER_BAP,
 722				HERMES_RID_CNFTXRATECONTROL,
 723				bitrate_table[ratemode].agere_txratectrl);
 724		break;
 725	case FIRMWARE_TYPE_INTERSIL:
 726	case FIRMWARE_TYPE_SYMBOL:
 727		err = hermes_write_wordrec(hw, USER_BAP,
 728				HERMES_RID_CNFTXRATECONTROL,
 729				bitrate_table[ratemode].intersil_txratectrl);
 730		break;
 731	default:
 732		BUG();
 733	}
 734
 735	return err;
 736}
 737
 738int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate)
 739{
 740	struct hermes *hw = &priv->hw;
 741	int i;
 742	int err = 0;
 743	u16 val;
 744
 745	err = hermes_read_wordrec(hw, USER_BAP,
 746				  HERMES_RID_CURRENTTXRATE, &val);
 747	if (err)
 748		return err;
 749
 750	switch (priv->firmware_type) {
 751	case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
 752		/* Note : in Lucent firmware, the return value of
 753		 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
 754		 * and therefore is totally different from the
 755		 * encoding of HERMES_RID_CNFTXRATECONTROL.
 756		 * Don't forget that 6Mb/s is really 5.5Mb/s */
 757		if (val == 6)
 758			*bitrate = 5500000;
 759		else
 760			*bitrate = val * 1000000;
 761		break;
 762	case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
 763	case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
 764		for (i = 0; i < BITRATE_TABLE_SIZE; i++)
 765			if (bitrate_table[i].intersil_txratectrl == val) {
 766				*bitrate = bitrate_table[i].bitrate * 100000;
 767				break;
 768			}
 769
 770		if (i >= BITRATE_TABLE_SIZE) {
 771			printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
 772			       priv->ndev->name, val);
 773			err = -EIO;
 774		}
 775
 776		break;
 777	default:
 778		BUG();
 779	}
 780
 781	return err;
 782}
 783
 784/* Set fixed AP address */
 785int __orinoco_hw_set_wap(struct orinoco_private *priv)
 786{
 787	int roaming_flag;
 788	int err = 0;
 789	struct hermes *hw = &priv->hw;
 790
 791	switch (priv->firmware_type) {
 792	case FIRMWARE_TYPE_AGERE:
 793		/* not supported */
 794		break;
 795	case FIRMWARE_TYPE_INTERSIL:
 796		if (priv->bssid_fixed)
 797			roaming_flag = 2;
 798		else
 799			roaming_flag = 1;
 800
 801		err = hermes_write_wordrec(hw, USER_BAP,
 802					   HERMES_RID_CNFROAMINGMODE,
 803					   roaming_flag);
 804		break;
 805	case FIRMWARE_TYPE_SYMBOL:
 806		err = HERMES_WRITE_RECORD(hw, USER_BAP,
 807					  HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
 808					  &priv->desired_bssid);
 809		break;
 810	}
 811	return err;
 812}
 813
 814/* Change the WEP keys and/or the current keys.  Can be called
 815 * either from __orinoco_hw_setup_enc() or directly from
 816 * orinoco_ioctl_setiwencode().  In the later case the association
 817 * with the AP is not broken (if the firmware can handle it),
 818 * which is needed for 802.1x implementations. */
 819int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 820{
 821	struct hermes *hw = &priv->hw;
 822	int err = 0;
 823	int i;
 824
 825	switch (priv->firmware_type) {
 826	case FIRMWARE_TYPE_AGERE:
 827	{
 828		struct orinoco_key keys[ORINOCO_MAX_KEYS];
 829
 830		memset(&keys, 0, sizeof(keys));
 831		for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
 832			int len = min(priv->keys[i].key_len,
 833				      ORINOCO_MAX_KEY_SIZE);
 834			memcpy(&keys[i].data, priv->keys[i].key, len);
 835			if (len > SMALL_KEY_SIZE)
 836				keys[i].len = cpu_to_le16(LARGE_KEY_SIZE);
 837			else if (len > 0)
 838				keys[i].len = cpu_to_le16(SMALL_KEY_SIZE);
 839			else
 840				keys[i].len = cpu_to_le16(0);
 841		}
 842
 843		err = HERMES_WRITE_RECORD(hw, USER_BAP,
 844					  HERMES_RID_CNFWEPKEYS_AGERE,
 845					  &keys);
 846		if (err)
 847			return err;
 848		err = hermes_write_wordrec(hw, USER_BAP,
 849					   HERMES_RID_CNFTXKEY_AGERE,
 850					   priv->tx_key);
 851		if (err)
 852			return err;
 853		break;
 854	}
 855	case FIRMWARE_TYPE_INTERSIL:
 856	case FIRMWARE_TYPE_SYMBOL:
 857		{
 858			int keylen;
 859
 860			/* Force uniform key length to work around
 861			 * firmware bugs */
 862			keylen = priv->keys[priv->tx_key].key_len;
 863
 864			if (keylen > LARGE_KEY_SIZE) {
 865				printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
 866				       priv->ndev->name, priv->tx_key, keylen);
 867				return -E2BIG;
 868			} else if (keylen > SMALL_KEY_SIZE)
 869				keylen = LARGE_KEY_SIZE;
 870			else if (keylen > 0)
 871				keylen = SMALL_KEY_SIZE;
 872			else
 873				keylen = 0;
 874
 875			/* Write all 4 keys */
 876			for (i = 0; i < ORINOCO_MAX_KEYS; i++) {
 877				u8 key[LARGE_KEY_SIZE] = { 0 };
 878
 879				memcpy(key, priv->keys[i].key,
 880				       priv->keys[i].key_len);
 881
 882				err = hw->ops->write_ltv(hw, USER_BAP,
 883						HERMES_RID_CNFDEFAULTKEY0 + i,
 884						HERMES_BYTES_TO_RECLEN(keylen),
 885						key);
 886				if (err)
 887					return err;
 888			}
 889
 890			/* Write the index of the key used in transmission */
 891			err = hermes_write_wordrec(hw, USER_BAP,
 892						HERMES_RID_CNFWEPDEFAULTKEYID,
 893						priv->tx_key);
 894			if (err)
 895				return err;
 896		}
 897		break;
 898	}
 899
 900	return 0;
 901}
 902
 903int __orinoco_hw_setup_enc(struct orinoco_private *priv)
 904{
 905	struct hermes *hw = &priv->hw;
 906	int err = 0;
 907	int master_wep_flag;
 908	int auth_flag;
 909	int enc_flag;
 910
 911	/* Setup WEP keys */
 912	if (priv->encode_alg == ORINOCO_ALG_WEP)
 913		__orinoco_hw_setup_wepkeys(priv);
 914
 915	if (priv->wep_restrict)
 916		auth_flag = HERMES_AUTH_SHARED_KEY;
 917	else
 918		auth_flag = HERMES_AUTH_OPEN;
 919
 920	if (priv->wpa_enabled)
 921		enc_flag = 2;
 922	else if (priv->encode_alg == ORINOCO_ALG_WEP)
 923		enc_flag = 1;
 924	else
 925		enc_flag = 0;
 926
 927	switch (priv->firmware_type) {
 928	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
 929		if (priv->encode_alg == ORINOCO_ALG_WEP) {
 930			/* Enable the shared-key authentication. */
 931			err = hermes_write_wordrec(hw, USER_BAP,
 932					HERMES_RID_CNFAUTHENTICATION_AGERE,
 933					auth_flag);
 934		}
 935		err = hermes_write_wordrec(hw, USER_BAP,
 936					   HERMES_RID_CNFWEPENABLED_AGERE,
 937					   enc_flag);
 938		if (err)
 939			return err;
 940
 941		if (priv->has_wpa) {
 942			/* Set WPA key management */
 943			err = hermes_write_wordrec(hw, USER_BAP,
 944				  HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
 945				  priv->key_mgmt);
 946			if (err)
 947				return err;
 948		}
 949
 950		break;
 951
 952	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
 953	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
 954		if (priv->encode_alg == ORINOCO_ALG_WEP) {
 955			if (priv->wep_restrict ||
 956			    (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
 957				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
 958						  HERMES_WEP_EXCL_UNENCRYPTED;
 959			else
 960				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
 961
 962			err = hermes_write_wordrec(hw, USER_BAP,
 963						   HERMES_RID_CNFAUTHENTICATION,
 964						   auth_flag);
 965			if (err)
 966				return err;
 967		} else
 968			master_wep_flag = 0;
 969
 970		if (priv->iw_mode == NL80211_IFTYPE_MONITOR)
 971			master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
 972
 973		/* Master WEP setting : on/off */
 974		err = hermes_write_wordrec(hw, USER_BAP,
 975					   HERMES_RID_CNFWEPFLAGS_INTERSIL,
 976					   master_wep_flag);
 977		if (err)
 978			return err;
 979
 980		break;
 981	}
 982
 983	return 0;
 984}
 985
 986/* key must be 32 bytes, including the tx and rx MIC keys.
 987 * rsc must be NULL or up to 8 bytes
 988 * tsc must be NULL or up to 8 bytes
 989 */
 990int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
 991			      int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
 992			      u8 *tsc, size_t tsc_len)
 993{
 994	struct {
 995		__le16 idx;
 996		u8 rsc[ORINOCO_SEQ_LEN];
 997		u8 key[TKIP_KEYLEN];
 998		u8 tx_mic[MIC_KEYLEN];
 999		u8 rx_mic[MIC_KEYLEN];
1000		u8 tsc[ORINOCO_SEQ_LEN];
1001	} __packed buf;
1002	struct hermes *hw = &priv->hw;
1003	int ret;
1004	int err;
1005	int k;
1006	u16 xmitting;
1007
1008	key_idx &= 0x3;
1009
1010	if (set_tx)
1011		key_idx |= 0x8000;
1012
1013	buf.idx = cpu_to_le16(key_idx);
1014	memcpy(buf.key, key,
1015	       sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
1016
1017	if (rsc_len > sizeof(buf.rsc))
1018		rsc_len = sizeof(buf.rsc);
1019
1020	if (tsc_len > sizeof(buf.tsc))
1021		tsc_len = sizeof(buf.tsc);
1022
1023	memset(buf.rsc, 0, sizeof(buf.rsc));
1024	memset(buf.tsc, 0, sizeof(buf.tsc));
1025
1026	if (rsc != NULL)
1027		memcpy(buf.rsc, rsc, rsc_len);
1028
1029	if (tsc != NULL)
1030		memcpy(buf.tsc, tsc, tsc_len);
1031	else
1032		buf.tsc[4] = 0x10;
1033
1034	/* Wait up to 100ms for tx queue to empty */
1035	for (k = 100; k > 0; k--) {
1036		udelay(1000);
1037		ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
1038					  &xmitting);
1039		if (ret || !xmitting)
1040			break;
1041	}
1042
1043	if (k == 0)
1044		ret = -ETIMEDOUT;
1045
1046	err = HERMES_WRITE_RECORD(hw, USER_BAP,
1047				  HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
1048				  &buf);
1049
1050	return ret ? ret : err;
1051}
1052
1053int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx)
1054{
1055	struct hermes *hw = &priv->hw;
1056	int err;
1057
1058	err = hermes_write_wordrec(hw, USER_BAP,
1059				   HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
1060				   key_idx);
1061	if (err)
1062		printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
1063		       priv->ndev->name, err, key_idx);
1064	return err;
1065}
1066
1067int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
1068				    struct net_device *dev,
1069				    int mc_count, int promisc)
1070{
1071	struct hermes *hw = &priv->hw;
1072	int err = 0;
1073
1074	if (promisc != priv->promiscuous) {
1075		err = hermes_write_wordrec(hw, USER_BAP,
1076					   HERMES_RID_CNFPROMISCUOUSMODE,
1077					   promisc);
1078		if (err) {
1079			printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
1080			       priv->ndev->name, err);
1081		} else
1082			priv->promiscuous = promisc;
1083	}
1084
1085	/* If we're not in promiscuous mode, then we need to set the
1086	 * group address if either we want to multicast, or if we were
1087	 * multicasting and want to stop */
1088	if (!promisc && (mc_count || priv->mc_count)) {
1089		struct netdev_hw_addr *ha;
1090		struct hermes_multicast mclist;
1091		int i = 0;
1092
1093		netdev_for_each_mc_addr(ha, dev) {
1094			if (i == mc_count)
1095				break;
1096			memcpy(mclist.addr[i++], ha->addr, ETH_ALEN);
1097		}
1098
1099		err = hw->ops->write_ltv(hw, USER_BAP,
1100				   HERMES_RID_CNFGROUPADDRESSES,
1101				   HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
1102				   &mclist);
1103		if (err)
1104			printk(KERN_ERR "%s: Error %d setting multicast list.\n",
1105			       priv->ndev->name, err);
1106		else
1107			priv->mc_count = mc_count;
1108	}
1109	return err;
1110}
1111
1112/* Return : < 0 -> error code ; >= 0 -> length */
1113int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
1114			 char buf[IW_ESSID_MAX_SIZE + 1])
1115{
1116	struct hermes *hw = &priv->hw;
1117	int err = 0;
1118	struct hermes_idstring essidbuf;
1119	char *p = (char *)(&essidbuf.val);
1120	int len;
1121	unsigned long flags;
1122
1123	if (orinoco_lock(priv, &flags) != 0)
1124		return -EBUSY;
1125
1126	if (strlen(priv->desired_essid) > 0) {
1127		/* We read the desired SSID from the hardware rather
1128		   than from priv->desired_essid, just in case the
1129		   firmware is allowed to change it on us. I'm not
1130		   sure about this */
1131		/* My guess is that the OWNSSID should always be whatever
1132		 * we set to the card, whereas CURRENT_SSID is the one that
1133		 * may change... - Jean II */
1134		u16 rid;
1135
1136		*active = 1;
1137
1138		rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
1139			HERMES_RID_CNFDESIREDSSID;
1140
1141		err = hw->ops->read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
1142					NULL, &essidbuf);
1143		if (err)
1144			goto fail_unlock;
1145	} else {
1146		*active = 0;
1147
1148		err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
1149					sizeof(essidbuf), NULL, &essidbuf);
1150		if (err)
1151			goto fail_unlock;
1152	}
1153
1154	len = le16_to_cpu(essidbuf.len);
1155	BUG_ON(len > IW_ESSID_MAX_SIZE);
1156
1157	memset(buf, 0, IW_ESSID_MAX_SIZE);
1158	memcpy(buf, p, len);
1159	err = len;
1160
1161 fail_unlock:
1162	orinoco_unlock(priv, &flags);
1163
1164	return err;
1165}
1166
1167int orinoco_hw_get_freq(struct orinoco_private *priv)
1168{
1169	struct hermes *hw = &priv->hw;
1170	int err = 0;
1171	u16 channel;
1172	int freq = 0;
1173	unsigned long flags;
1174
1175	if (orinoco_lock(priv, &flags) != 0)
1176		return -EBUSY;
1177
1178	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL,
1179				  &channel);
1180	if (err)
1181		goto out;
1182
1183	/* Intersil firmware 1.3.5 returns 0 when the interface is down */
1184	if (channel == 0) {
1185		err = -EBUSY;
1186		goto out;
1187	}
1188
1189	if ((channel < 1) || (channel > NUM_CHANNELS)) {
1190		printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
1191		       priv->ndev->name, channel);
1192		err = -EBUSY;
1193		goto out;
1194
1195	}
1196	freq = ieee80211_dsss_chan_to_freq(channel);
1197
1198 out:
1199	orinoco_unlock(priv, &flags);
1200
1201	if (err > 0)
1202		err = -EBUSY;
1203	return err ? err : freq;
1204}
1205
1206int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
1207			       int *numrates, s32 *rates, int max)
1208{
1209	struct hermes *hw = &priv->hw;
1210	struct hermes_idstring list;
1211	unsigned char *p = (unsigned char *)&list.val;
1212	int err = 0;
1213	int num;
1214	int i;
1215	unsigned long flags;
1216
1217	if (orinoco_lock(priv, &flags) != 0)
1218		return -EBUSY;
1219
1220	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
1221				sizeof(list), NULL, &list);
1222	orinoco_unlock(priv, &flags);
1223
1224	if (err)
1225		return err;
1226
1227	num = le16_to_cpu(list.len);
1228	*numrates = num;
1229	num = min(num, max);
1230
1231	for (i = 0; i < num; i++)
1232		rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
1233
1234	return 0;
1235}
1236
1237int orinoco_hw_trigger_scan(struct orinoco_private *priv,
1238			    const struct cfg80211_ssid *ssid)
1239{
1240	struct net_device *dev = priv->ndev;
1241	struct hermes *hw = &priv->hw;
1242	unsigned long flags;
1243	int err = 0;
1244
1245	if (orinoco_lock(priv, &flags) != 0)
1246		return -EBUSY;
1247
1248	/* Scanning with port 0 disabled would fail */
1249	if (!netif_running(dev)) {
1250		err = -ENETDOWN;
1251		goto out;
1252	}
1253
1254	/* In monitor mode, the scan results are always empty.
1255	 * Probe responses are passed to the driver as received
1256	 * frames and could be processed in software. */
1257	if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
1258		err = -EOPNOTSUPP;
1259		goto out;
1260	}
1261
1262	if (priv->has_hostscan) {
1263		switch (priv->firmware_type) {
1264		case FIRMWARE_TYPE_SYMBOL:
1265			err = hermes_write_wordrec(hw, USER_BAP,
1266						HERMES_RID_CNFHOSTSCAN_SYMBOL,
1267						HERMES_HOSTSCAN_SYMBOL_ONCE |
1268						HERMES_HOSTSCAN_SYMBOL_BCAST);
1269			break;
1270		case FIRMWARE_TYPE_INTERSIL: {
1271			__le16 req[3];
1272
1273			req[0] = cpu_to_le16(0x3fff);	/* All channels */
1274			req[1] = cpu_to_le16(0x0001);	/* rate 1 Mbps */
1275			req[2] = 0;			/* Any ESSID */
1276			err = HERMES_WRITE_RECORD(hw, USER_BAP,
1277						  HERMES_RID_CNFHOSTSCAN, &req);
1278			break;
1279		}
1280		case FIRMWARE_TYPE_AGERE:
1281			if (ssid->ssid_len > 0) {
1282				struct hermes_idstring idbuf;
1283				size_t len = ssid->ssid_len;
1284
1285				idbuf.len = cpu_to_le16(len);
1286				memcpy(idbuf.val, ssid->ssid, len);
1287
1288				err = hw->ops->write_ltv(hw, USER_BAP,
1289					       HERMES_RID_CNFSCANSSID_AGERE,
1290					       HERMES_BYTES_TO_RECLEN(len + 2),
1291					       &idbuf);
1292			} else
1293				err = hermes_write_wordrec(hw, USER_BAP,
1294						   HERMES_RID_CNFSCANSSID_AGERE,
1295						   0);	/* Any ESSID */
1296			if (err)
1297				break;
1298
1299			if (priv->has_ext_scan) {
1300				err = hermes_write_wordrec(hw, USER_BAP,
1301						HERMES_RID_CNFSCANCHANNELS2GHZ,
1302						0x7FFF);
1303				if (err)
1304					goto out;
1305
1306				err = hermes_inquire(hw,
1307						     HERMES_INQ_CHANNELINFO);
1308			} else
1309				err = hermes_inquire(hw, HERMES_INQ_SCAN);
1310
1311			break;
1312		}
1313	} else
1314		err = hermes_inquire(hw, HERMES_INQ_SCAN);
1315
1316 out:
1317	orinoco_unlock(priv, &flags);
1318
1319	return err;
1320}
1321
1322/* Disassociate from node with BSSID addr */
1323int orinoco_hw_disassociate(struct orinoco_private *priv,
1324			    u8 *addr, u16 reason_code)
1325{
1326	struct hermes *hw = &priv->hw;
1327	int err;
1328
1329	struct {
1330		u8 addr[ETH_ALEN];
1331		__le16 reason_code;
1332	} __packed buf;
1333
1334	/* Currently only supported by WPA enabled Agere fw */
1335	if (!priv->has_wpa)
1336		return -EOPNOTSUPP;
1337
1338	memcpy(buf.addr, addr, ETH_ALEN);
1339	buf.reason_code = cpu_to_le16(reason_code);
1340	err = HERMES_WRITE_RECORD(hw, USER_BAP,
1341				  HERMES_RID_CNFDISASSOCIATE,
1342				  &buf);
1343	return err;
1344}
1345
1346int orinoco_hw_get_current_bssid(struct orinoco_private *priv,
1347				 u8 *addr)
1348{
1349	struct hermes *hw = &priv->hw;
1350	int err;
1351
1352	err = hw->ops->read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
1353				ETH_ALEN, NULL, addr);
1354
1355	return err;
1356}