summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/intersil/p54/p54.h
blob: 3356ea708d81632732312e6f49add55847f1bdab (plain)
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
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
62
63
64
65
66
67
68
69
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
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
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Shared defines for all mac80211 Prism54 code
 *
 * Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
 *
 * Based on the islsm (softmac prism54) driver, which is:
 * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
 */

#ifndef P54_H
#define P54_H

#ifdef CONFIG_P54_LEDS
#include <linux/leds.h>
#endif /* CONFIG_P54_LEDS */

#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000

#define BR_CODE_MIN			0x80000000
#define BR_CODE_COMPONENT_ID		0x80000001
#define BR_CODE_COMPONENT_VERSION	0x80000002
#define BR_CODE_DEPENDENT_IF		0x80000003
#define BR_CODE_EXPOSED_IF		0x80000004
#define BR_CODE_DESCR			0x80000101
#define BR_CODE_MAX			0x8FFFFFFF
#define BR_CODE_END_OF_BRA		0xFF0000FF
#define LEGACY_BR_CODE_END_OF_BRA	0xFFFFFFFF

struct bootrec {
	__le32 code;
	__le32 len;
	u32 data[10];
} __packed;

/* Interface role definitions */
#define BR_INTERFACE_ROLE_SERVER	0x0000
#define BR_INTERFACE_ROLE_CLIENT	0x8000

#define BR_DESC_PRIV_CAP_WEP		BIT(0)
#define BR_DESC_PRIV_CAP_TKIP		BIT(1)
#define BR_DESC_PRIV_CAP_MICHAEL	BIT(2)
#define BR_DESC_PRIV_CAP_CCX_CP		BIT(3)
#define BR_DESC_PRIV_CAP_CCX_MIC	BIT(4)
#define BR_DESC_PRIV_CAP_AESCCMP	BIT(5)

struct bootrec_desc {
	__le16 modes;
	__le16 flags;
	__le32 rx_start;
	__le32 rx_end;
	u8 headroom;
	u8 tailroom;
	u8 tx_queues;
	u8 tx_depth;
	u8 privacy_caps;
	u8 rx_keycache_size;
	u8 time_size;
	u8 padding;
	u8 rates[16];
	u8 padding2[4];
	__le16 rx_mtu;
} __packed;

#define FW_FMAC 0x464d4143
#define FW_LM86 0x4c4d3836
#define FW_LM87 0x4c4d3837
#define FW_LM20 0x4c4d3230

struct bootrec_comp_id {
	__le32 fw_variant;
} __packed;

struct bootrec_comp_ver {
	char fw_version[24];
} __packed;

struct bootrec_end {
	__le16 crc;
	u8 padding[2];
	u8 md5[16];
} __packed;

/* provide 16 bytes for the transport back-end */
#define P54_TX_INFO_DATA_SIZE		16

/* stored in ieee80211_tx_info's rate_driver_data */
struct p54_tx_info {
	u32 start_addr;
	u32 end_addr;
	union {
		void *data[P54_TX_INFO_DATA_SIZE / sizeof(void *)];
		struct {
			u32 extra_len;
		};
	};
};

#define P54_MAX_CTRL_FRAME_LEN		0x1000

#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop)	\
do {								\
	queue.aifs = cpu_to_le16(ai_fs);			\
	queue.cwmin = cpu_to_le16(cw_min);			\
	queue.cwmax = cpu_to_le16(cw_max);			\
	queue.txop = cpu_to_le16(_txop);			\
} while (0)

struct p54_edcf_queue_param {
	__le16 aifs;
	__le16 cwmin;
	__le16 cwmax;
	__le16 txop;
} __packed;

struct p54_rssi_db_entry {
	u16 freq;
	s16 mul;
	s16 add;
	s16 longbow_unkn;
	s16 longbow_unk2;
};

struct p54_cal_database {
	size_t entries;
	size_t entry_size;
	size_t offset;
	size_t len;
	u8 data[];
};

#define EEPROM_READBACK_LEN 0x3fc

enum fw_state {
	FW_STATE_OFF,
	FW_STATE_BOOTING,
	FW_STATE_READY,
	FW_STATE_RESET,
	FW_STATE_RESETTING,
};

#ifdef CONFIG_P54_LEDS

#define P54_LED_MAX_NAME_LEN 31

struct p54_led_dev {
	struct ieee80211_hw *hw_dev;
	struct led_classdev led_dev;
	char name[P54_LED_MAX_NAME_LEN + 1];

	unsigned int toggled;
	unsigned int index;
	unsigned int registered;
};

#endif /* CONFIG_P54_LEDS */

struct p54_tx_queue_stats {
	unsigned int len;
	unsigned int limit;
	unsigned int count;
};

struct p54_common {
	struct ieee80211_hw *hw;
	struct ieee80211_vif *vif;
	void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb);
	int (*open)(struct ieee80211_hw *dev);
	void (*stop)(struct ieee80211_hw *dev);
	struct sk_buff_head tx_pending;
	struct sk_buff_head tx_queue;
	struct mutex conf_mutex;
	bool registered;

	/* memory management (as seen by the firmware) */
	u32 rx_start;
	u32 rx_end;
	u16 rx_mtu;
	u8 headroom;
	u8 tailroom;

	/* firmware/hardware info */
	unsigned int tx_hdr_len;
	unsigned int fw_var;
	unsigned int fw_interface;
	u8 version;

	/* (e)DCF / QOS state */
	bool use_short_slot;
	spinlock_t tx_stats_lock;
	struct p54_tx_queue_stats tx_stats[8];
	struct p54_edcf_queue_param qos_params[8];

	/* Radio data */
	u16 rxhw;
	u8 rx_diversity_mask;
	u8 tx_diversity_mask;
	unsigned int output_power;
	struct p54_rssi_db_entry *cur_rssi;
	struct ieee80211_channel *curchan;
	struct survey_info *survey;
	unsigned int chan_num;
	struct completion stat_comp;
	bool update_stats;
	struct {
		unsigned int timestamp;
		unsigned int cached_cca;
		unsigned int cached_tx;
		unsigned int cached_rssi;
		u64 active;
		u64 cca;
		u64 tx;
		u64 rssi;
	} survey_raw;

	int noise;
	/* calibration, output power limit and rssi<->dBm conversation data */
	struct pda_iq_autocal_entry *iq_autocal;
	unsigned int iq_autocal_len;
	struct p54_cal_database *curve_data;
	struct p54_cal_database *output_limit;
	struct p54_cal_database *rssi_db;
	struct ieee80211_supported_band *band_table[NUM_NL80211_BANDS];

	/* BBP/MAC state */
	u8 mac_addr[ETH_ALEN];
	u8 bssid[ETH_ALEN];
	u8 mc_maclist[4][ETH_ALEN];
	u16 wakeup_timer;
	unsigned int filter_flags;
	int mc_maclist_num;
	int mode;
	u32 tsf_low32, tsf_high32;
	u32 basic_rate_mask;
	u16 aid;
	u8 coverage_class;
	bool phy_idle;
	bool phy_ps;
	bool powersave_override;
	__le32 beacon_req_id;
	struct completion beacon_comp;

	/* cryptographic engine information */
	u8 privacy_caps;
	u8 rx_keycache_size;
	unsigned long *used_rxkeys;

	/* LED management */
#ifdef CONFIG_P54_LEDS
	struct p54_led_dev leds[4];
	struct delayed_work led_work;
#endif /* CONFIG_P54_LEDS */
	u16 softled_state;		/* bit field of glowing LEDs */

	/* statistics */
	struct ieee80211_low_level_stats stats;
	struct delayed_work work;

	/* eeprom handling */
	void *eeprom;
	struct completion eeprom_comp;
	struct mutex eeprom_mutex;
};

/* interfaces for the drivers */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb);
int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len);
int p54_read_eeprom(struct ieee80211_hw *dev);

struct ieee80211_hw *p54_init_common(size_t priv_data_len);
int p54_register_common(struct ieee80211_hw *dev, struct device *pdev);
void p54_free_common(struct ieee80211_hw *dev);

void p54_unregister_common(struct ieee80211_hw *dev);

#endif /* P54_H */