p54common.c 29.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

/*
 * Common code for mac80211 Prism54 drivers
 *
 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
 * Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
 *
 * Based on the islsm (softmac prism54) driver, which is:
 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/init.h>
#include <linux/firmware.h>
#include <linux/etherdevice.h>

#include <net/mac80211.h>

#include "p54.h"
#include "p54common.h"

MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54common");

30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
static struct ieee80211_rate p54_rates[] = {
	{ .bitrate = 10, .hw_value = 0, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
	{ .bitrate = 60, .hw_value = 4, },
	{ .bitrate = 90, .hw_value = 5, },
	{ .bitrate = 120, .hw_value = 6, },
	{ .bitrate = 180, .hw_value = 7, },
	{ .bitrate = 240, .hw_value = 8, },
	{ .bitrate = 360, .hw_value = 9, },
	{ .bitrate = 480, .hw_value = 10, },
	{ .bitrate = 540, .hw_value = 11, },
};

static struct ieee80211_channel p54_channels[] = {
	{ .center_freq = 2412, .hw_value = 1, },
	{ .center_freq = 2417, .hw_value = 2, },
	{ .center_freq = 2422, .hw_value = 3, },
	{ .center_freq = 2427, .hw_value = 4, },
	{ .center_freq = 2432, .hw_value = 5, },
	{ .center_freq = 2437, .hw_value = 6, },
	{ .center_freq = 2442, .hw_value = 7, },
	{ .center_freq = 2447, .hw_value = 8, },
	{ .center_freq = 2452, .hw_value = 9, },
	{ .center_freq = 2457, .hw_value = 10, },
	{ .center_freq = 2462, .hw_value = 11, },
	{ .center_freq = 2467, .hw_value = 12, },
	{ .center_freq = 2472, .hw_value = 13, },
	{ .center_freq = 2484, .hw_value = 14, },
};

J
Johannes Berg 已提交
62
static struct ieee80211_supported_band band_2GHz = {
63 64 65 66 67 68 69
	.channels = p54_channels,
	.n_channels = ARRAY_SIZE(p54_channels),
	.bitrates = p54_rates,
	.n_bitrates = ARRAY_SIZE(p54_rates),
};


70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
void p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
{
	struct p54_common *priv = dev->priv;
	struct bootrec_exp_if *exp_if;
	struct bootrec *bootrec;
	u32 *data = (u32 *)fw->data;
	u32 *end_data = (u32 *)fw->data + (fw->size >> 2);
	u8 *fw_version = NULL;
	size_t len;
	int i;

	if (priv->rx_start)
		return;

	while (data < end_data && *data)
		data++;

	while (data < end_data && !*data)
		data++;

	bootrec = (struct bootrec *) data;

	while (bootrec->data <= end_data &&
	       (bootrec->data + (len = le32_to_cpu(bootrec->len))) <= end_data) {
		u32 code = le32_to_cpu(bootrec->code);
		switch (code) {
		case BR_CODE_COMPONENT_ID:
A
Al Viro 已提交
97
			switch (be32_to_cpu(*(__be32 *)bootrec->data)) {
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
			case FW_FMAC:
				printk(KERN_INFO "p54: FreeMAC firmware\n");
				break;
			case FW_LM20:
				printk(KERN_INFO "p54: LM20 firmware\n");
				break;
			case FW_LM86:
				printk(KERN_INFO "p54: LM86 firmware\n");
				break;
			case FW_LM87:
				printk(KERN_INFO "p54: LM87 firmware - not supported yet!\n");
				break;
			default:
				printk(KERN_INFO "p54: unknown firmware\n");
				break;
			}
			break;
		case BR_CODE_COMPONENT_VERSION:
			/* 24 bytes should be enough for all firmwares */
			if (strnlen((unsigned char*)bootrec->data, 24) < 24)
				fw_version = (unsigned char*)bootrec->data;
			break;
		case BR_CODE_DESCR:
A
Al Viro 已提交
121
			priv->rx_start = le32_to_cpu(((__le32 *)bootrec->data)[1]);
122
			/* FIXME add sanity checking */
A
Al Viro 已提交
123
			priv->rx_end = le32_to_cpu(((__le32 *)bootrec->data)[2]) - 0x3500;
124 125 126 127
			break;
		case BR_CODE_EXPOSED_IF:
			exp_if = (struct bootrec_exp_if *) bootrec->data;
			for (i = 0; i < (len * sizeof(*exp_if) / 4); i++)
A
Al Viro 已提交
128
				if (exp_if[i].if_id == cpu_to_le16(0x1a))
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
					priv->fw_var = le16_to_cpu(exp_if[i].variant);
			break;
		case BR_CODE_DEPENDENT_IF:
			break;
		case BR_CODE_END_OF_BRA:
		case LEGACY_BR_CODE_END_OF_BRA:
			end_data = NULL;
			break;
		default:
			break;
		}
		bootrec = (struct bootrec *)&bootrec->data[len];
	}

	if (fw_version)
		printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
			fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);

	if (priv->fw_var >= 0x300) {
		/* Firmware supports QoS, use it! */
149 150 151 152
		priv->tx_stats[0].limit = 3;
		priv->tx_stats[1].limit = 4;
		priv->tx_stats[2].limit = 3;
		priv->tx_stats[3].limit = 1;
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
		dev->queues = 4;
	}
}
EXPORT_SYMBOL_GPL(p54_parse_firmware);

static int p54_convert_rev0_to_rev1(struct ieee80211_hw *dev,
				    struct pda_pa_curve_data *curve_data)
{
	struct p54_common *priv = dev->priv;
	struct pda_pa_curve_data_sample_rev1 *rev1;
	struct pda_pa_curve_data_sample_rev0 *rev0;
	size_t cd_len = sizeof(*curve_data) +
		(curve_data->points_per_channel*sizeof(*rev1) + 2) *
		 curve_data->channels;
	unsigned int i, j;
	void *source, *target;

	priv->curve_data = kmalloc(cd_len, GFP_KERNEL);
	if (!priv->curve_data)
		return -ENOMEM;

	memcpy(priv->curve_data, curve_data, sizeof(*curve_data));
	source = curve_data->data;
	target = priv->curve_data->data;
	for (i = 0; i < curve_data->channels; i++) {
		__le16 *freq = source;
		source += sizeof(__le16);
		*((__le16 *)target) = *freq;
		target += sizeof(__le16);
		for (j = 0; j < curve_data->points_per_channel; j++) {
			rev1 = target;
			rev0 = source;

			rev1->rf_power = rev0->rf_power;
			rev1->pa_detector = rev0->pa_detector;
			rev1->data_64qam = rev0->pcv;
			/* "invent" the points for the other modulations */
#define SUB(x,y) (u8)((x) - (y)) > (x) ? 0 : (x) - (y)
			rev1->data_16qam = SUB(rev0->pcv, 12);
			rev1->data_qpsk  = SUB(rev1->data_16qam, 12);
			rev1->data_bpsk  = SUB(rev1->data_qpsk, 12);
			rev1->data_barker= SUB(rev1->data_bpsk, 14);
#undef SUB
			target += sizeof(*rev1);
			source += sizeof(*rev0);
		}
	}

	return 0;
}

int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
{
	struct p54_common *priv = dev->priv;
	struct eeprom_pda_wrap *wrap = NULL;
	struct pda_entry *entry;
	unsigned int data_len, entry_len;
	void *tmp;
	int err;
212
	u8 *end = (u8 *)eeprom + len;
213 214

	wrap = (struct eeprom_pda_wrap *) eeprom;
215
	entry = (void *)wrap->data + le16_to_cpu(wrap->len);
216 217 218

	/* verify that at least the entry length/code fits */
	while ((u8 *)entry <= end - sizeof(*entry)) {
219 220
		entry_len = le16_to_cpu(entry->len);
		data_len = ((entry_len - 1) << 1);
221 222 223 224 225

		/* abort if entry exceeds whole structure */
		if ((u8 *)entry + sizeof(*entry) + data_len > end)
			break;

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
		switch (le16_to_cpu(entry->code)) {
		case PDR_MAC_ADDRESS:
			SET_IEEE80211_PERM_ADDR(dev, entry->data);
			break;
		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS:
			if (data_len < 2) {
				err = -EINVAL;
				goto err;
			}

			if (2 + entry->data[1]*sizeof(*priv->output_limit) > data_len) {
				err = -EINVAL;
				goto err;
			}

			priv->output_limit = kmalloc(entry->data[1] *
				sizeof(*priv->output_limit), GFP_KERNEL);

			if (!priv->output_limit) {
				err = -ENOMEM;
				goto err;
			}

			memcpy(priv->output_limit, &entry->data[2],
			       entry->data[1]*sizeof(*priv->output_limit));
			priv->output_limit_len = entry->data[1];
			break;
		case PDR_PRISM_PA_CAL_CURVE_DATA:
			if (data_len < sizeof(struct pda_pa_curve_data)) {
				err = -EINVAL;
				goto err;
			}

			if (((struct pda_pa_curve_data *)entry->data)->cal_method_rev) {
				priv->curve_data = kmalloc(data_len, GFP_KERNEL);
				if (!priv->curve_data) {
					err = -ENOMEM;
					goto err;
				}

				memcpy(priv->curve_data, entry->data, data_len);
			} else {
				err = p54_convert_rev0_to_rev1(dev, (struct pda_pa_curve_data *)entry->data);
				if (err)
					goto err;
			}

			break;
		case PDR_PRISM_ZIF_TX_IQ_CALIBRATION:
			priv->iq_autocal = kmalloc(data_len, GFP_KERNEL);
			if (!priv->iq_autocal) {
				err = -ENOMEM;
				goto err;
			}

			memcpy(priv->iq_autocal, entry->data, data_len);
			priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry);
			break;
		case PDR_INTERFACE_LIST:
			tmp = entry->data;
			while ((u8 *)tmp < entry->data + data_len) {
				struct bootrec_exp_if *exp_if = tmp;
				if (le16_to_cpu(exp_if->if_id) == 0xF)
					priv->rxhw = exp_if->variant & cpu_to_le16(0x07);
				tmp += sizeof(struct bootrec_exp_if);
			}
			break;
		case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
			priv->version = *(u8 *)(entry->data + 1);
			break;
		case PDR_END:
297 298
			/* make it overrun */
			entry_len = len;
299
			break;
300 301 302 303
		default:
			printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
				le16_to_cpu(entry->code));
			break;
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
		}

		entry = (void *)entry + (entry_len + 1)*2;
	}

	if (!priv->iq_autocal || !priv->output_limit || !priv->curve_data) {
		printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
		err = -EINVAL;
		goto err;
	}

	return 0;

  err:
	if (priv->iq_autocal) {
		kfree(priv->iq_autocal);
		priv->iq_autocal = NULL;
	}

	if (priv->output_limit) {
		kfree(priv->output_limit);
		priv->output_limit = NULL;
	}

	if (priv->curve_data) {
		kfree(priv->curve_data);
		priv->curve_data = NULL;
	}

	printk(KERN_ERR "p54: eeprom parse failed!\n");
	return err;
}
EXPORT_SYMBOL_GPL(p54_parse_eeprom);

void p54_fill_eeprom_readback(struct p54_control_hdr *hdr)
{
	struct p54_eeprom_lm86 *eeprom_hdr;

	hdr->magic1 = cpu_to_le16(0x8000);
	hdr->len = cpu_to_le16(sizeof(*eeprom_hdr) + 0x2000);
	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
	hdr->retry1 = hdr->retry2 = 0;
	eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
	eeprom_hdr->offset = 0x0;
	eeprom_hdr->len = cpu_to_le16(0x2000);
}
EXPORT_SYMBOL_GPL(p54_fill_eeprom_readback);

static void p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
	struct ieee80211_rx_status rx_status = {0};
	u16 freq = le16_to_cpu(hdr->freq);

358
	rx_status.signal = hdr->rssi;
359
	/* XX correct? */
360
	rx_status.qual = (100 * hdr->rssi) / 127;
361
	rx_status.rate_idx = hdr->rate & 0xf;
362
	rx_status.freq = freq;
363
	rx_status.band = IEEE80211_BAND_2GHZ;
364 365
	rx_status.antenna = hdr->antenna;
	rx_status.mactime = le64_to_cpu(hdr->timestamp);
366
	rx_status.flag |= RX_FLAG_TSFT;
367 368 369 370 371 372 373 374 375 376 377 378 379

	skb_pull(skb, sizeof(*hdr));
	skb_trim(skb, le16_to_cpu(hdr->len));

	ieee80211_rx_irqsafe(dev, skb, &rx_status);
}

static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	int i;

	for (i = 0; i < dev->queues; i++)
380
		if (priv->tx_stats[i].len < priv->tx_stats[i].limit)
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
			ieee80211_wake_queue(dev, i);
}

static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
	struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
	struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
	u32 addr = le32_to_cpu(hdr->req_id) - 0x70;
	struct memrecord *range = NULL;
	u32 freed = 0;
	u32 last_addr = priv->rx_start;

	while (entry != (struct sk_buff *)&priv->tx_queue) {
396 397
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
		range = (void *)info->driver_data;
398 399 400 401 402
		if (range->start_addr == addr) {
			struct p54_control_hdr *entry_hdr;
			struct p54_tx_control_allocdata *entry_data;
			int pad = 0;

403 404 405 406 407 408 409 410
			if (entry->next != (struct sk_buff *)&priv->tx_queue) {
				struct ieee80211_tx_info *ni;
				struct memrecord *mr;

				ni = IEEE80211_SKB_CB(entry->next);
				mr = (struct memrecord *)ni->driver_data;
				freed = mr->start_addr - last_addr;
			} else
411 412 413 414
				freed = priv->rx_end - last_addr;

			last_addr = range->end_addr;
			__skb_unlink(entry, &priv->tx_queue);
415
			memset(&info->status, 0, sizeof(info->status));
416
			priv->tx_stats[skb_get_queue_mapping(skb)].len--;
417 418 419 420 421
			entry_hdr = (struct p54_control_hdr *) entry->data;
			entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
			if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
				pad = entry_data->align[0];

422
			if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
423
				if (!(payload->status & 0x01))
424
					info->flags |= IEEE80211_TX_STAT_ACK;
425
				else
426
					info->status.excessive_retries = 1;
427
			}
428 429
			info->status.retry_count = payload->retries - 1;
			info->status.ack_signal = le16_to_cpu(payload->ack_rssi);
430
			skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
431
			ieee80211_tx_status_irqsafe(dev, entry);
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
			break;
		} else
			last_addr = range->end_addr;
		entry = entry->next;
	}

	if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
	    sizeof(struct p54_control_hdr))
		p54_wake_free_queues(dev);
}

static void p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;

	switch (le16_to_cpu(hdr->type)) {
	case P54_CONTROL_TYPE_TXDONE:
		p54_rx_frame_sent(dev, skb);
		break;
	case P54_CONTROL_TYPE_BBP:
		break;
	default:
		printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n",
		       wiphy_name(dev->wiphy), le16_to_cpu(hdr->type));
		break;
	}
}

/* returns zero if skb can be reused */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
	u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
	switch (type) {
	case 0x00:
	case 0x01:
		p54_rx_data(dev, skb);
		return -1;
	case 0x4d:
		/* TODO: do something better... but then again, I've never seen this happen */
		printk(KERN_ERR "%s: Received fault. Probably need to restart hardware now..\n",
		       wiphy_name(dev->wiphy));
		break;
	case 0x80:
		p54_rx_control(dev, skb);
		break;
	default:
		printk(KERN_ERR "%s: unknown frame RXed (0x%02x)\n",
		       wiphy_name(dev->wiphy), type);
		break;
	}
	return 0;
}
EXPORT_SYMBOL_GPL(p54_rx);

/*
 * So, the firmware is somewhat stupid and doesn't know what places in its
 * memory incoming data should go to. By poking around in the firmware, we
 * can find some unused memory to upload our packets to. However, data that we
 * want the card to TX needs to stay intact until the card has told us that
 * it is done with it. This function finds empty places we can upload to and
 * marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
 * allocated areas.
 */
static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
496
			       struct p54_control_hdr *data, u32 len)
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *entry = priv->tx_queue.next;
	struct sk_buff *target_skb = NULL;
	u32 last_addr = priv->rx_start;
	u32 largest_hole = 0;
	u32 target_addr = priv->rx_start;
	unsigned long flags;
	unsigned int left;
	len = (len + 0x170 + 3) & ~0x3; /* 0x70 headroom, 0x100 tailroom */

	spin_lock_irqsave(&priv->tx_queue.lock, flags);
	left = skb_queue_len(&priv->tx_queue);
	while (left--) {
		u32 hole_size;
512 513
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
		struct memrecord *range = (void *)info->driver_data;
514 515 516 517 518 519 520 521 522 523 524 525 526 527
		hole_size = range->start_addr - last_addr;
		if (!target_skb && hole_size >= len) {
			target_skb = entry->prev;
			hole_size -= len;
			target_addr = last_addr;
		}
		largest_hole = max(largest_hole, hole_size);
		last_addr = range->end_addr;
		entry = entry->next;
	}
	if (!target_skb && priv->rx_end - last_addr >= len) {
		target_skb = priv->tx_queue.prev;
		largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
		if (!skb_queue_empty(&priv->tx_queue)) {
528 529
			struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb);
			struct memrecord *range = (void *)info->driver_data;
530 531 532 533 534 535
			target_addr = range->end_addr;
		}
	} else
		largest_hole = max(largest_hole, priv->rx_end - last_addr);

	if (skb) {
536 537
		struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
		struct memrecord *range = (void *)info->driver_data;
538 539 540 541 542 543 544 545 546 547 548 549
		range->start_addr = target_addr;
		range->end_addr = target_addr + len;
		__skb_queue_after(&priv->tx_queue, target_skb, skb);
		if (largest_hole < IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
				   sizeof(struct p54_control_hdr))
			ieee80211_stop_queues(dev);
	}
	spin_unlock_irqrestore(&priv->tx_queue.lock, flags);

	data->req_id = cpu_to_le32(target_addr + 0x70);
}

550
static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
551
{
552
	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
553
	struct ieee80211_tx_queue_stats *current_queue;
554 555
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr;
556
	struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
557 558 559 560
	struct p54_tx_control_allocdata *txhdr;
	size_t padding, len;
	u8 rate;

561
	current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)];
562 563 564 565 566
	if (unlikely(current_queue->len > current_queue->limit))
		return NETDEV_TX_BUSY;
	current_queue->len++;
	current_queue->count++;
	if (current_queue->len == current_queue->limit)
567
		ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
568 569 570 571 572 573 574 575 576 577 578 579 580

	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
	len = skb->len;

	txhdr = (struct p54_tx_control_allocdata *)
			skb_push(skb, sizeof(*txhdr) + padding);
	hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));

	if (padding)
		hdr->magic1 = cpu_to_le16(0x4010);
	else
		hdr->magic1 = cpu_to_le16(0x0010);
	hdr->len = cpu_to_le16(len);
581 582
	hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1);
	hdr->retry1 = hdr->retry2 = info->control.retry_limit;
583 584 585 586 587 588

	memset(txhdr->wep_key, 0x0, 16);
	txhdr->padding = 0;
	txhdr->padding2 = 0;

	/* TODO: add support for alternate retry TX rates */
589 590
	rate = ieee80211_get_tx_rate(dev, info)->hw_value;
	if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
591
		rate |= 0x10;
592
	if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
593
		rate |= 0x40;
594
	else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
595 596 597 598
		rate |= 0x20;
	memset(txhdr->rateset, rate, 8);
	txhdr->wep_key_present = 0;
	txhdr->wep_key_len = 0;
599
	txhdr->frame_type = cpu_to_le32(skb_get_queue_mapping(skb) + 4);
600
	txhdr->magic4 = 0;
601 602
	txhdr->antenna = (info->antenna_sel_tx == 0) ?
		2 : info->antenna_sel_tx - 1;
603
	txhdr->output_power = 0x7f; // HW Maximum
604
	txhdr->magic5 = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
605 606 607 608
		0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23));
	if (padding)
		txhdr->align[0] = padding;

609 610 611 612 613 614 615 616 617 618 619 620 621
	/* FIXME: The sequence that follows is needed for this driver to
	 * work with mac80211 since "mac80211: fix TX sequence numbers".
	 * As with the temporary code in rt2x00, changes will be needed
	 * to get proper sequence numbers on beacons. In addition, this
	 * patch places the sequence number in the hardware state, which
	 * limits us to a single virtual state.
	 */
	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
		if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
			priv->seqno += 0x10;
		ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
		ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
	}
622 623 624
	/* modifies skb->cb and with it info, so must be last! */
	p54_assign_address(dev, skb, hdr, skb->len);

625 626 627 628 629 630 631 632 633 634 635 636 637
	priv->tx(dev, hdr, skb->len, 0);
	return 0;
}

static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
			  const u8 *dst, const u8 *src, u8 antenna,
			  u32 magic3, u32 magic8, u32 magic9)
{
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr;
	struct p54_tx_control_filter *filter;

	hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
638
		      priv->tx_hdr_len, GFP_ATOMIC);
639 640 641 642 643 644 645 646
	if (!hdr)
		return -ENOMEM;

	hdr = (void *)hdr + priv->tx_hdr_len;

	filter = (struct p54_tx_control_filter *) hdr->data;
	hdr->magic1 = cpu_to_le16(0x8001);
	hdr->len = cpu_to_le16(sizeof(*filter));
647
	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*filter));
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);

	filter->filter_type = cpu_to_le16(filter_type);
	memcpy(filter->dst, dst, ETH_ALEN);
	if (!src)
		memset(filter->src, ~0, ETH_ALEN);
	else
		memcpy(filter->src, src, ETH_ALEN);
	filter->antenna = antenna;
	filter->magic3 = cpu_to_le32(magic3);
	filter->rx_addr = cpu_to_le32(priv->rx_end);
	filter->max_rx = cpu_to_le16(0x0620);	/* FIXME: for usb ver 1.. maybe */
	filter->rxhw = priv->rxhw;
	filter->magic8 = cpu_to_le16(magic8);
	filter->magic9 = cpu_to_le16(magic9);

	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*filter), 1);
	return 0;
}

static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
{
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr;
	struct p54_tx_control_channel *chan;
	unsigned int i;
	size_t payload_len = sizeof(*chan) + sizeof(u32)*2 +
			     sizeof(*chan->curve_data) *
			     priv->curve_data->points_per_channel;
	void *entry;

	hdr = kzalloc(sizeof(*hdr) + payload_len +
		      priv->tx_hdr_len, GFP_KERNEL);
	if (!hdr)
		return -ENOMEM;

	hdr = (void *)hdr + priv->tx_hdr_len;

	chan = (struct p54_tx_control_channel *) hdr->data;

	hdr->magic1 = cpu_to_le16(0x8001);
	hdr->len = cpu_to_le16(sizeof(*chan));
	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
691
	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + payload_len);
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763

	chan->magic1 = cpu_to_le16(0x1);
	chan->magic2 = cpu_to_le16(0x0);

	for (i = 0; i < priv->iq_autocal_len; i++) {
		if (priv->iq_autocal[i].freq != freq)
			continue;

		memcpy(&chan->iq_autocal, &priv->iq_autocal[i],
		       sizeof(*priv->iq_autocal));
		break;
	}
	if (i == priv->iq_autocal_len)
		goto err;

	for (i = 0; i < priv->output_limit_len; i++) {
		if (priv->output_limit[i].freq != freq)
			continue;

		chan->val_barker = 0x38;
		chan->val_bpsk = priv->output_limit[i].val_bpsk;
		chan->val_qpsk = priv->output_limit[i].val_qpsk;
		chan->val_16qam = priv->output_limit[i].val_16qam;
		chan->val_64qam = priv->output_limit[i].val_64qam;
		break;
	}
	if (i == priv->output_limit_len)
		goto err;

	chan->pa_points_per_curve = priv->curve_data->points_per_channel;

	entry = priv->curve_data->data;
	for (i = 0; i < priv->curve_data->channels; i++) {
		if (*((__le16 *)entry) != freq) {
			entry += sizeof(__le16);
			entry += sizeof(struct pda_pa_curve_data_sample_rev1) *
				 chan->pa_points_per_curve;
			continue;
		}

		entry += sizeof(__le16);
		memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
		       chan->pa_points_per_curve);
		break;
	}

	memcpy(hdr->data + payload_len - 4, &chan->val_bpsk, 4);

	priv->tx(dev, hdr, sizeof(*hdr) + payload_len, 1);
	return 0;

 err:
	printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
	kfree(hdr);
	return -EINVAL;
}

static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
{
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr;
	struct p54_tx_control_led *led;

	hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
		      priv->tx_hdr_len, GFP_KERNEL);
	if (!hdr)
		return -ENOMEM;

	hdr = (void *)hdr + priv->tx_hdr_len;
	hdr->magic1 = cpu_to_le16(0x8001);
	hdr->len = cpu_to_le16(sizeof(*led));
	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
764
	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led));
765 766 767 768 769 770 771 772 773 774 775 776

	led = (struct p54_tx_control_led *) hdr->data;
	led->mode = cpu_to_le16(mode);
	led->led_permanent = cpu_to_le16(link);
	led->led_temporary = cpu_to_le16(act);
	led->duration = cpu_to_le16(1000);

	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);

	return 0;
}

777
#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop)	\
778 779 780 781
do {	 							\
	queue.aifs = cpu_to_le16(ai_fs);			\
	queue.cwmin = cpu_to_le16(cw_min);			\
	queue.cwmax = cpu_to_le16(cw_max);			\
782
	queue.txop = cpu_to_le16(_txop);			\
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
} while(0)

static void p54_init_vdcf(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr;
	struct p54_tx_control_vdcf *vdcf;

	/* all USB V1 adapters need a extra headroom */
	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
	hdr->magic1 = cpu_to_le16(0x8001);
	hdr->len = cpu_to_le16(sizeof(*vdcf));
	hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
	hdr->req_id = cpu_to_le32(priv->rx_start);

	vdcf = (struct p54_tx_control_vdcf *) hdr->data;

800 801
	P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
	P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
802
	P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
803
	P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
804 805 806 807 808 809 810 811 812 813
}

static void p54_set_vdcf(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	struct p54_control_hdr *hdr;
	struct p54_tx_control_vdcf *vdcf;

	hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;

814
	p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf));
815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833

	vdcf = (struct p54_tx_control_vdcf *) hdr->data;

	if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
		vdcf->slottime = 9;
		vdcf->magic1 = 0x00;
		vdcf->magic2 = 0x10;
	} else {
		vdcf->slottime = 20;
		vdcf->magic1 = 0x0a;
		vdcf->magic2 = 0x06;
	}

	/* (see prism54/isl_oid.h for further details) */
	vdcf->frameburst = cpu_to_le16(0);

	priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
}

834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
static int p54_start(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	int err;

	err = priv->open(dev);
	if (!err)
		priv->mode = IEEE80211_IF_TYPE_MNTR;

	return err;
}

static void p54_stop(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	struct sk_buff *skb;
850
	while ((skb = skb_dequeue(&priv->tx_queue)))
851 852
		kfree_skb(skb);
	priv->stop(dev);
853
	priv->mode = IEEE80211_IF_TYPE_INVALID;
854 855
}

856 857 858 859 860
static int p54_add_interface(struct ieee80211_hw *dev,
			     struct ieee80211_if_init_conf *conf)
{
	struct p54_common *priv = dev->priv;

861 862
	if (priv->mode != IEEE80211_IF_TYPE_MNTR)
		return -EOPNOTSUPP;
863 864 865 866 867 868 869 870 871

	switch (conf->type) {
	case IEEE80211_IF_TYPE_STA:
		priv->mode = conf->type;
		break;
	default:
		return -EOPNOTSUPP;
	}

872
	memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
873 874 875 876 877 878 879 880

	p54_set_filter(dev, 0, priv->mac_addr, NULL, 0, 1, 0, 0xF642);
	p54_set_filter(dev, 0, priv->mac_addr, NULL, 1, 0, 0, 0xF642);

	switch (conf->type) {
	case IEEE80211_IF_TYPE_STA:
		p54_set_filter(dev, 1, priv->mac_addr, NULL, 0, 0x15F, 0x1F4, 0);
		break;
881 882 883
	default:
		BUG();	/* impossible */
		break;
884 885 886 887 888 889 890 891 892 893 894
	}

	p54_set_leds(dev, 1, 0, 0);

	return 0;
}

static void p54_remove_interface(struct ieee80211_hw *dev,
				 struct ieee80211_if_init_conf *conf)
{
	struct p54_common *priv = dev->priv;
895 896 897
	priv->mode = IEEE80211_IF_TYPE_MNTR;
	memset(priv->mac_addr, 0, ETH_ALEN);
	p54_set_filter(dev, 0, priv->mac_addr, NULL, 2, 0, 0, 0);
898 899 900 901 902
}

static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
{
	int ret;
903
	struct p54_common *priv = dev->priv;
904

905
	mutex_lock(&priv->conf_mutex);
906
	ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
907
	p54_set_vdcf(dev);
908
	mutex_unlock(&priv->conf_mutex);
909 910 911
	return ret;
}

912 913
static int p54_config_interface(struct ieee80211_hw *dev,
				struct ieee80211_vif *vif,
914 915 916 917
				struct ieee80211_if_conf *conf)
{
	struct p54_common *priv = dev->priv;

918
	mutex_lock(&priv->conf_mutex);
919 920 921
	p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 0, 1, 0, 0xF642);
	p54_set_filter(dev, 0, priv->mac_addr, conf->bssid, 2, 0, 0, 0);
	p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
922
	memcpy(priv->bssid, conf->bssid, ETH_ALEN);
923
	mutex_unlock(&priv->conf_mutex);
924 925 926
	return 0;
}

927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
static void p54_configure_filter(struct ieee80211_hw *dev,
				 unsigned int changed_flags,
				 unsigned int *total_flags,
				 int mc_count, struct dev_mc_list *mclist)
{
	struct p54_common *priv = dev->priv;

	*total_flags &= FIF_BCN_PRBRESP_PROMISC;

	if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
		if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
			p54_set_filter(dev, 0, priv->mac_addr,
				       NULL, 2, 0, 0, 0);
		else
			p54_set_filter(dev, 0, priv->mac_addr,
				       priv->bssid, 2, 0, 0, 0);
	}
}

J
Johannes Berg 已提交
946
static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
947 948 949 950 951 952 953 954
		       const struct ieee80211_tx_queue_params *params)
{
	struct p54_common *priv = dev->priv;
	struct p54_tx_control_vdcf *vdcf;

	vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
		((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);

955
	if ((params) && !(queue > 4)) {
956
		P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
957
			params->cw_min, params->cw_max, params->txop);
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977
	} else
		return -EINVAL;

	p54_set_vdcf(dev);

	return 0;
}

static int p54_get_stats(struct ieee80211_hw *dev,
			 struct ieee80211_low_level_stats *stats)
{
	/* TODO */
	return 0;
}

static int p54_get_tx_stats(struct ieee80211_hw *dev,
			    struct ieee80211_tx_queue_stats *stats)
{
	struct p54_common *priv = dev->priv;

978
	memcpy(stats, &priv->tx_stats, sizeof(stats[0]) * dev->queues);
979 980 981 982 983 984

	return 0;
}

static const struct ieee80211_ops p54_ops = {
	.tx			= p54_tx,
985 986
	.start			= p54_start,
	.stop			= p54_stop,
987 988 989 990
	.add_interface		= p54_add_interface,
	.remove_interface	= p54_remove_interface,
	.config			= p54_config,
	.config_interface	= p54_config_interface,
991
	.configure_filter	= p54_configure_filter,
992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
	.conf_tx		= p54_conf_tx,
	.get_stats		= p54_get_stats,
	.get_tx_stats		= p54_get_tx_stats
};

struct ieee80211_hw *p54_init_common(size_t priv_data_len)
{
	struct ieee80211_hw *dev;
	struct p54_common *priv;

	dev = ieee80211_alloc_hw(priv_data_len, &p54_ops);
	if (!dev)
		return NULL;

	priv = dev->priv;
1007
	priv->mode = IEEE80211_IF_TYPE_INVALID;
1008
	skb_queue_head_init(&priv->tx_queue);
1009
	dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
1010
	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
1011 1012
		     IEEE80211_HW_RX_INCLUDES_FCS |
		     IEEE80211_HW_SIGNAL_UNSPEC;
1013
	dev->channel_change_time = 1000;	/* TODO: find actual value */
1014
	dev->max_signal = 127;
1015

1016
	priv->tx_stats[0].limit = 5;
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030
	dev->queues = 1;

	dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
				 sizeof(struct p54_tx_control_allocdata);

        priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) +
              priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL);

	if (!priv->cached_vdcf) {
		ieee80211_free_hw(dev);
		return NULL;
	}

	p54_init_vdcf(dev);
1031
	mutex_init(&priv->conf_mutex);
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057

	return dev;
}
EXPORT_SYMBOL_GPL(p54_init_common);

void p54_free_common(struct ieee80211_hw *dev)
{
	struct p54_common *priv = dev->priv;
	kfree(priv->iq_autocal);
	kfree(priv->output_limit);
	kfree(priv->curve_data);
	kfree(priv->cached_vdcf);
}
EXPORT_SYMBOL_GPL(p54_free_common);

static int __init p54_init(void)
{
	return 0;
}

static void __exit p54_exit(void)
{
}

module_init(p54_init);
module_exit(p54_exit);