Browse Source

[ath5k] Add support for non-802.11n Atheros wireless NICs

Signed-off-by: Michael Brown <mcb30@etherboot.org>
tags/v0.9.8
Joshua Oreman 14 years ago
parent
commit
ce68f587e2

+ 1
- 0
src/Makefile View File

@@ -62,6 +62,7 @@ SRCDIRS		+= drivers/net
62 62
 SRCDIRS		+= drivers/net/e1000
63 63
 SRCDIRS		+= drivers/net/phantom
64 64
 SRCDIRS		+= drivers/net/rtl818x
65
+SRCDIRS		+= drivers/net/ath5k
65 66
 SRCDIRS		+= drivers/block
66 67
 SRCDIRS		+= drivers/nvs
67 68
 SRCDIRS		+= drivers/bitbash

+ 1694
- 0
src/drivers/net/ath5k/ath5k.c
File diff suppressed because it is too large
View File


+ 1275
- 0
src/drivers/net/ath5k/ath5k.h
File diff suppressed because it is too large
View File


+ 340
- 0
src/drivers/net/ath5k/ath5k_attach.c View File

@@ -0,0 +1,340 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ *
5
+ * Modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
6
+ * Original from Linux kernel 2.6.30.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ *
20
+ */
21
+
22
+FILE_LICENCE ( MIT );
23
+
24
+/*************************************\
25
+* Attach/Detach Functions and helpers *
26
+\*************************************/
27
+
28
+#include <gpxe/pci.h>
29
+#include <unistd.h>
30
+#include <stdlib.h>
31
+#include "ath5k.h"
32
+#include "reg.h"
33
+#include "base.h"
34
+
35
+/**
36
+ * ath5k_hw_post - Power On Self Test helper function
37
+ *
38
+ * @ah: The &struct ath5k_hw
39
+ */
40
+static int ath5k_hw_post(struct ath5k_hw *ah)
41
+{
42
+
43
+	static const u32 static_pattern[4] = {
44
+		0x55555555,	0xaaaaaaaa,
45
+		0x66666666,	0x99999999
46
+	};
47
+	static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) };
48
+	int i, c;
49
+	u16 cur_reg;
50
+	u32 var_pattern;
51
+	u32 init_val;
52
+	u32 cur_val;
53
+
54
+	for (c = 0; c < 2; c++) {
55
+
56
+		cur_reg = regs[c];
57
+
58
+		/* Save previous value */
59
+		init_val = ath5k_hw_reg_read(ah, cur_reg);
60
+
61
+		for (i = 0; i < 256; i++) {
62
+			var_pattern = i << 16 | i;
63
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
64
+			cur_val = ath5k_hw_reg_read(ah, cur_reg);
65
+
66
+			if (cur_val != var_pattern) {
67
+				DBG("ath5k: POST failed!\n");
68
+				return -EAGAIN;
69
+			}
70
+
71
+			/* Found on ndiswrapper dumps */
72
+			var_pattern = 0x0039080f;
73
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
74
+		}
75
+
76
+		for (i = 0; i < 4; i++) {
77
+			var_pattern = static_pattern[i];
78
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
79
+			cur_val = ath5k_hw_reg_read(ah, cur_reg);
80
+
81
+			if (cur_val != var_pattern) {
82
+				DBG("ath5k: POST failed!\n");
83
+				return -EAGAIN;
84
+			}
85
+
86
+			/* Found on ndiswrapper dumps */
87
+			var_pattern = 0x003b080f;
88
+			ath5k_hw_reg_write(ah, var_pattern, cur_reg);
89
+		}
90
+
91
+		/* Restore previous value */
92
+		ath5k_hw_reg_write(ah, init_val, cur_reg);
93
+
94
+	}
95
+
96
+	return 0;
97
+
98
+}
99
+
100
+/**
101
+ * ath5k_hw_attach - Check if hw is supported and init the needed structs
102
+ *
103
+ * @sc: The &struct ath5k_softc we got from the driver's attach function
104
+ * @mac_version: The mac version id (check out ath5k.h) based on pci id
105
+ * @hw: Returned newly allocated hardware structure, on success
106
+ *
107
+ * Check if the device is supported, perform a POST and initialize the needed
108
+ * structs. Returns -ENOMEM if we don't have memory for the needed structs,
109
+ * -ENODEV if the device is not supported or prints an error msg if something
110
+ * else went wrong.
111
+ */
112
+int ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version,
113
+		    struct ath5k_hw **hw)
114
+{
115
+	struct ath5k_hw *ah;
116
+	struct pci_device *pdev = sc->pdev;
117
+	int ret;
118
+	u32 srev;
119
+
120
+	ah = zalloc(sizeof(struct ath5k_hw));
121
+	if (ah == NULL) {
122
+		ret = -ENOMEM;
123
+		DBG("ath5k: out of memory\n");
124
+		goto err;
125
+	}
126
+
127
+	ah->ah_sc = sc;
128
+	ah->ah_iobase = sc->iobase;
129
+
130
+	/*
131
+	 * HW information
132
+	 */
133
+	ah->ah_turbo = 0;
134
+	ah->ah_txpower.txp_tpc = 0;
135
+	ah->ah_imr = 0;
136
+	ah->ah_atim_window = 0;
137
+	ah->ah_aifs = AR5K_TUNE_AIFS;
138
+	ah->ah_cw_min = AR5K_TUNE_CWMIN;
139
+	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
140
+	ah->ah_software_retry = 0;
141
+	ah->ah_ant_diversity = AR5K_TUNE_ANT_DIVERSITY;
142
+
143
+	/*
144
+	 * Set the mac version based on the pci id
145
+	 */
146
+	ah->ah_version = mac_version;
147
+
148
+	/*Fill the ath5k_hw struct with the needed functions*/
149
+	ret = ath5k_hw_init_desc_functions(ah);
150
+	if (ret)
151
+		goto err_free;
152
+
153
+	/* Bring device out of sleep and reset it's units */
154
+	ret = ath5k_hw_nic_wakeup(ah, CHANNEL_B, 1);
155
+	if (ret)
156
+		goto err_free;
157
+
158
+	/* Get MAC, PHY and RADIO revisions */
159
+	srev = ath5k_hw_reg_read(ah, AR5K_SREV);
160
+	ah->ah_mac_srev = srev;
161
+	ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
162
+	ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
163
+	ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID);
164
+	ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, CHANNEL_5GHZ);
165
+	ah->ah_phy = AR5K_PHY(0);
166
+
167
+	/* Try to identify radio chip based on it's srev */
168
+	switch (ah->ah_radio_5ghz_revision & 0xf0) {
169
+	case AR5K_SREV_RAD_5111:
170
+		ah->ah_radio = AR5K_RF5111;
171
+		ah->ah_single_chip = 0;
172
+		ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
173
+							CHANNEL_2GHZ);
174
+		break;
175
+	case AR5K_SREV_RAD_5112:
176
+	case AR5K_SREV_RAD_2112:
177
+		ah->ah_radio = AR5K_RF5112;
178
+		ah->ah_single_chip = 0;
179
+		ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
180
+							CHANNEL_2GHZ);
181
+		break;
182
+	case AR5K_SREV_RAD_2413:
183
+		ah->ah_radio = AR5K_RF2413;
184
+		ah->ah_single_chip = 1;
185
+		break;
186
+	case AR5K_SREV_RAD_5413:
187
+		ah->ah_radio = AR5K_RF5413;
188
+		ah->ah_single_chip = 1;
189
+		break;
190
+	case AR5K_SREV_RAD_2316:
191
+		ah->ah_radio = AR5K_RF2316;
192
+		ah->ah_single_chip = 1;
193
+		break;
194
+	case AR5K_SREV_RAD_2317:
195
+		ah->ah_radio = AR5K_RF2317;
196
+		ah->ah_single_chip = 1;
197
+		break;
198
+	case AR5K_SREV_RAD_5424:
199
+		if (ah->ah_mac_version == AR5K_SREV_AR2425 ||
200
+		    ah->ah_mac_version == AR5K_SREV_AR2417) {
201
+			ah->ah_radio = AR5K_RF2425;
202
+		} else {
203
+			ah->ah_radio = AR5K_RF5413;
204
+		}
205
+		ah->ah_single_chip = 1;
206
+		break;
207
+	default:
208
+		/* Identify radio based on mac/phy srev */
209
+		if (ah->ah_version == AR5K_AR5210) {
210
+			ah->ah_radio = AR5K_RF5110;
211
+			ah->ah_single_chip = 0;
212
+		} else if (ah->ah_version == AR5K_AR5211) {
213
+			ah->ah_radio = AR5K_RF5111;
214
+			ah->ah_single_chip = 0;
215
+			ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
216
+								CHANNEL_2GHZ);
217
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
218
+			   ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
219
+			   ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
220
+			ah->ah_radio = AR5K_RF2425;
221
+			ah->ah_single_chip = 1;
222
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425;
223
+		} else if (srev == AR5K_SREV_AR5213A &&
224
+			   ah->ah_phy_revision == AR5K_SREV_PHY_5212B) {
225
+			ah->ah_radio = AR5K_RF5112;
226
+			ah->ah_single_chip = 0;
227
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B;
228
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) {
229
+			ah->ah_radio = AR5K_RF2316;
230
+			ah->ah_single_chip = 1;
231
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
232
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) ||
233
+			   ah->ah_phy_revision == AR5K_SREV_PHY_5413) {
234
+			ah->ah_radio = AR5K_RF5413;
235
+			ah->ah_single_chip = 1;
236
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413;
237
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) ||
238
+			   ah->ah_phy_revision == AR5K_SREV_PHY_2413) {
239
+			ah->ah_radio = AR5K_RF2413;
240
+			ah->ah_single_chip = 1;
241
+			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413;
242
+		} else {
243
+			DBG("ath5k: Couldn't identify radio revision.\n");
244
+			ret = -ENOTSUP;
245
+			goto err_free;
246
+		}
247
+	}
248
+
249
+	/* Return on unsuported chips (unsupported eeprom etc) */
250
+	if ((srev >= AR5K_SREV_AR5416) &&
251
+	    (srev < AR5K_SREV_AR2425)) {
252
+		DBG("ath5k: Device not yet supported.\n");
253
+		ret = -ENOTSUP;
254
+		goto err_free;
255
+	}
256
+
257
+	/*
258
+	 * Write PCI-E power save settings
259
+	 */
260
+	if ((ah->ah_version == AR5K_AR5212) &&
261
+	    pci_find_capability(pdev, PCI_CAP_ID_EXP)) {
262
+		ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES);
263
+		ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES);
264
+		/* Shut off RX when elecidle is asserted */
265
+		ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES);
266
+		ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES);
267
+		/* TODO: EEPROM work */
268
+		ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES);
269
+		/* Shut off PLL and CLKREQ active in L1 */
270
+		ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES);
271
+		/* Preserce other settings */
272
+		ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES);
273
+		ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES);
274
+		ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES);
275
+		/* Reset SERDES to load new settings */
276
+		ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET);
277
+		mdelay(1);
278
+	}
279
+
280
+	/*
281
+	 * POST
282
+	 */
283
+	ret = ath5k_hw_post(ah);
284
+	if (ret)
285
+		goto err_free;
286
+
287
+	/* Enable pci core retry fix on Hainan (5213A) and later chips */
288
+	if (srev >= AR5K_SREV_AR5213A)
289
+		ath5k_hw_reg_write(ah, AR5K_PCICFG_RETRY_FIX, AR5K_PCICFG);
290
+
291
+	/*
292
+	 * Get card capabilities, calibration values etc
293
+	 * TODO: EEPROM work
294
+	 */
295
+	ret = ath5k_eeprom_init(ah);
296
+	if (ret) {
297
+		DBG("ath5k: unable to init EEPROM\n");
298
+		goto err_free;
299
+	}
300
+
301
+	/* Get misc capabilities */
302
+	ret = ath5k_hw_set_capabilities(ah);
303
+	if (ret) {
304
+		DBG("ath5k: unable to get device capabilities: 0x%04x\n",
305
+		    sc->pdev->device);
306
+		goto err_free;
307
+	}
308
+
309
+	if (srev >= AR5K_SREV_AR2414) {
310
+		ah->ah_combined_mic = 1;
311
+		AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
312
+				     AR5K_MISC_MODE_COMBINED_MIC);
313
+	}
314
+
315
+	/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
316
+	memset(ah->ah_bssid, 0xff, ETH_ALEN);
317
+	ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
318
+	ath5k_hw_set_opmode(ah);
319
+
320
+	ath5k_hw_rfgain_opt_init(ah);
321
+
322
+	*hw = ah;
323
+	return 0;
324
+err_free:
325
+	free(ah);
326
+err:
327
+	return ret;
328
+}
329
+
330
+/**
331
+ * ath5k_hw_detach - Free the ath5k_hw struct
332
+ *
333
+ * @ah: The &struct ath5k_hw
334
+ */
335
+void ath5k_hw_detach(struct ath5k_hw *ah)
336
+{
337
+	free(ah->ah_rf_banks);
338
+	ath5k_eeprom_detach(ah);
339
+	free(ah);
340
+}

+ 154
- 0
src/drivers/net/ath5k/ath5k_caps.c View File

@@ -0,0 +1,154 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
5
+ *
6
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ *
20
+ */
21
+
22
+FILE_LICENCE ( MIT );
23
+
24
+/**************\
25
+* Capabilities *
26
+\**************/
27
+
28
+#include "ath5k.h"
29
+#include "reg.h"
30
+#include "base.h"
31
+
32
+/*
33
+ * Fill the capabilities struct
34
+ * TODO: Merge this with EEPROM code when we are done with it
35
+ */
36
+int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
37
+{
38
+	u16 ee_header;
39
+
40
+	/* Capabilities stored in the EEPROM */
41
+	ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
42
+
43
+	if (ah->ah_version == AR5K_AR5210) {
44
+		/*
45
+		 * Set radio capabilities
46
+		 * (The AR5110 only supports the middle 5GHz band)
47
+		 */
48
+		ah->ah_capabilities.cap_range.range_5ghz_min = 5120;
49
+		ah->ah_capabilities.cap_range.range_5ghz_max = 5430;
50
+		ah->ah_capabilities.cap_range.range_2ghz_min = 0;
51
+		ah->ah_capabilities.cap_range.range_2ghz_max = 0;
52
+
53
+		/* Set supported modes */
54
+		ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A;
55
+		ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A_TURBO;
56
+	} else {
57
+		/*
58
+		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
59
+		 * XXX and from 2312 to 2732GHz. There are problems with the
60
+		 * XXX current ieee80211 implementation because the IEEE
61
+		 * XXX channel mapping does not support negative channel
62
+		 * XXX numbers (2312MHz is channel -19). Of course, this
63
+		 * XXX doesn't matter because these channels are out of range
64
+		 * XXX but some regulation domains like MKK (Japan) will
65
+		 * XXX support frequencies somewhere around 4.8GHz.
66
+		 */
67
+
68
+		/*
69
+		 * Set radio capabilities
70
+		 */
71
+
72
+		if (AR5K_EEPROM_HDR_11A(ee_header)) {
73
+			/* 4920 */
74
+			ah->ah_capabilities.cap_range.range_5ghz_min = 5005;
75
+			ah->ah_capabilities.cap_range.range_5ghz_max = 6100;
76
+
77
+			/* Set supported modes */
78
+			ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A;
79
+			ah->ah_capabilities.cap_mode |= AR5K_MODE_BIT_11A_TURBO;
80
+			if (ah->ah_version == AR5K_AR5212)
81
+				ah->ah_capabilities.cap_mode |=
82
+					AR5K_MODE_BIT_11G_TURBO;
83
+		}
84
+
85
+		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
86
+		 * connected */
87
+		if (AR5K_EEPROM_HDR_11B(ee_header) ||
88
+		    (AR5K_EEPROM_HDR_11G(ee_header) &&
89
+		     ah->ah_version != AR5K_AR5211)) {
90
+			/* 2312 */
91
+			ah->ah_capabilities.cap_range.range_2ghz_min = 2412;
92
+			ah->ah_capabilities.cap_range.range_2ghz_max = 2732;
93
+
94
+			if (AR5K_EEPROM_HDR_11B(ee_header))
95
+				ah->ah_capabilities.cap_mode |=
96
+					AR5K_MODE_BIT_11B;
97
+
98
+			if (AR5K_EEPROM_HDR_11G(ee_header) &&
99
+			    ah->ah_version != AR5K_AR5211)
100
+				ah->ah_capabilities.cap_mode |=
101
+					AR5K_MODE_BIT_11G;
102
+		}
103
+	}
104
+
105
+	/* GPIO */
106
+	ah->ah_gpio_npins = AR5K_NUM_GPIO;
107
+
108
+	/* Set number of supported TX queues */
109
+	ah->ah_capabilities.cap_queues.q_tx_num = 1;
110
+
111
+	return 0;
112
+}
113
+
114
+/* Main function used by the driver part to check caps */
115
+int ath5k_hw_get_capability(struct ath5k_hw *ah,
116
+		enum ath5k_capability_type cap_type,
117
+		u32 capability __unused, u32 *result)
118
+{
119
+	switch (cap_type) {
120
+	case AR5K_CAP_NUM_TXQUEUES:
121
+		if (result) {
122
+			*result = 1;
123
+			goto yes;
124
+		}
125
+	case AR5K_CAP_VEOL:
126
+		goto yes;
127
+	case AR5K_CAP_COMPRESSION:
128
+		if (ah->ah_version == AR5K_AR5212)
129
+			goto yes;
130
+		else
131
+			goto no;
132
+	case AR5K_CAP_BURST:
133
+		goto yes;
134
+	case AR5K_CAP_TPC:
135
+		goto yes;
136
+	case AR5K_CAP_BSSIDMASK:
137
+		if (ah->ah_version == AR5K_AR5212)
138
+			goto yes;
139
+		else
140
+			goto no;
141
+	case AR5K_CAP_XR:
142
+		if (ah->ah_version == AR5K_AR5212)
143
+			goto yes;
144
+		else
145
+			goto no;
146
+	default:
147
+		goto no;
148
+	}
149
+
150
+no:
151
+	return -EINVAL;
152
+yes:
153
+	return 0;
154
+}

+ 554
- 0
src/drivers/net/ath5k/ath5k_desc.c View File

@@ -0,0 +1,554 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
5
+ *
6
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
7
+ *
8
+ * Permission to use, copy, modify, and distribute this software for any
9
+ * purpose with or without fee is hereby granted, provided that the above
10
+ * copyright notice and this permission notice appear in all copies.
11
+ *
12
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
+ *
20
+ */
21
+
22
+FILE_LICENCE ( MIT );
23
+
24
+/******************************\
25
+ Hardware Descriptor Functions
26
+\******************************/
27
+
28
+#include "ath5k.h"
29
+#include "reg.h"
30
+#include "base.h"
31
+
32
+/*
33
+ * TX Descriptors
34
+ */
35
+
36
+#define FCS_LEN	4
37
+
38
+/*
39
+ * Initialize the 2-word tx control descriptor on 5210/5211
40
+ */
41
+static int
42
+ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
43
+	unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type,
44
+	unsigned int tx_power __unused, unsigned int tx_rate0, unsigned int tx_tries0,
45
+	unsigned int key_index __unused, unsigned int antenna_mode, unsigned int flags,
46
+	unsigned int rtscts_rate __unused, unsigned int rtscts_duration)
47
+{
48
+	u32 frame_type;
49
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
50
+	unsigned int frame_len;
51
+
52
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
53
+
54
+	/*
55
+	 * Validate input
56
+	 * - Zero retries don't make sense.
57
+	 * - A zero rate will put the HW into a mode where it continously sends
58
+	 *   noise on the channel, so it is important to avoid this.
59
+	 */
60
+	if (tx_tries0 == 0) {
61
+		DBG("ath5k: zero retries\n");
62
+		return -EINVAL;
63
+	}
64
+	if (tx_rate0 == 0) {
65
+		DBG("ath5k: zero rate\n");
66
+		return -EINVAL;
67
+	}
68
+
69
+	/* Clear descriptor */
70
+	memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc));
71
+
72
+	/* Setup control descriptor */
73
+
74
+	/* Verify and set frame length */
75
+
76
+	frame_len = pkt_len + FCS_LEN;
77
+
78
+	if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
79
+		return -EINVAL;
80
+
81
+	tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
82
+
83
+	/* Verify and set buffer length */
84
+
85
+	if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
86
+		return -EINVAL;
87
+
88
+	tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
89
+
90
+	/*
91
+	 * Verify and set header length
92
+	 * XXX: I only found that on 5210 code, does it work on 5211 ?
93
+	 */
94
+	if (ah->ah_version == AR5K_AR5210) {
95
+		if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN)
96
+			return -EINVAL;
97
+		tx_ctl->tx_control_0 |=
98
+			AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN);
99
+	}
100
+
101
+	/*Diferences between 5210-5211*/
102
+	if (ah->ah_version == AR5K_AR5210) {
103
+		switch (type) {
104
+		case AR5K_PKT_TYPE_BEACON:
105
+		case AR5K_PKT_TYPE_PROBE_RESP:
106
+			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY;
107
+		case AR5K_PKT_TYPE_PIFS:
108
+			frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS;
109
+		default:
110
+			frame_type = type /*<< 2 ?*/;
111
+		}
112
+
113
+		tx_ctl->tx_control_0 |=
114
+		AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) |
115
+		AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
116
+
117
+	} else {
118
+		tx_ctl->tx_control_0 |=
119
+			AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) |
120
+			AR5K_REG_SM(antenna_mode,
121
+				AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT);
122
+		tx_ctl->tx_control_1 |=
123
+			AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE);
124
+	}
125
+#define _TX_FLAGS(_c, _flag)					\
126
+	if (flags & AR5K_TXDESC_##_flag) {			\
127
+		tx_ctl->tx_control_##_c |=			\
128
+			AR5K_2W_TX_DESC_CTL##_c##_##_flag;	\
129
+	}
130
+
131
+	_TX_FLAGS(0, CLRDMASK);
132
+	_TX_FLAGS(0, VEOL);
133
+	_TX_FLAGS(0, INTREQ);
134
+	_TX_FLAGS(0, RTSENA);
135
+	_TX_FLAGS(1, NOACK);
136
+
137
+#undef _TX_FLAGS
138
+
139
+	/*
140
+	 * RTS/CTS Duration [5210 ?]
141
+	 */
142
+	if ((ah->ah_version == AR5K_AR5210) &&
143
+			(flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)))
144
+		tx_ctl->tx_control_1 |= rtscts_duration &
145
+				AR5K_2W_TX_DESC_CTL1_RTS_DURATION;
146
+
147
+	return 0;
148
+}
149
+
150
+/*
151
+ * Initialize the 4-word tx control descriptor on 5212
152
+ */
153
+static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
154
+	struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len __unused,
155
+	enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0,
156
+	unsigned int tx_tries0, unsigned int key_index __unused,
157
+	unsigned int antenna_mode, unsigned int flags,
158
+	unsigned int rtscts_rate,
159
+	unsigned int rtscts_duration)
160
+{
161
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
162
+	unsigned int frame_len;
163
+
164
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
165
+
166
+	/*
167
+	 * Validate input
168
+	 * - Zero retries don't make sense.
169
+	 * - A zero rate will put the HW into a mode where it continously sends
170
+	 *   noise on the channel, so it is important to avoid this.
171
+	 */
172
+	if (tx_tries0 == 0) {
173
+		DBG("ath5k: zero retries\n");
174
+		return -EINVAL;
175
+	}
176
+	if (tx_rate0 == 0) {
177
+		DBG("ath5k: zero rate\n");
178
+		return -EINVAL;
179
+	}
180
+
181
+	tx_power += ah->ah_txpower.txp_offset;
182
+	if (tx_power > AR5K_TUNE_MAX_TXPOWER)
183
+		tx_power = AR5K_TUNE_MAX_TXPOWER;
184
+
185
+	/* Clear descriptor */
186
+	memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc));
187
+
188
+	/* Setup control descriptor */
189
+
190
+	/* Verify and set frame length */
191
+
192
+	frame_len = pkt_len + FCS_LEN;
193
+
194
+	if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
195
+		return -EINVAL;
196
+
197
+	tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
198
+
199
+	/* Verify and set buffer length */
200
+
201
+	if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
202
+		return -EINVAL;
203
+
204
+	tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
205
+
206
+	tx_ctl->tx_control_0 |=
207
+		AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
208
+		AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT);
209
+	tx_ctl->tx_control_1 |= AR5K_REG_SM(type,
210
+					AR5K_4W_TX_DESC_CTL1_FRAME_TYPE);
211
+	tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES,
212
+					AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0);
213
+	tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
214
+
215
+#define _TX_FLAGS(_c, _flag)					\
216
+	if (flags & AR5K_TXDESC_##_flag) {			\
217
+		tx_ctl->tx_control_##_c |=			\
218
+			AR5K_4W_TX_DESC_CTL##_c##_##_flag;	\
219
+	}
220
+
221
+	_TX_FLAGS(0, CLRDMASK);
222
+	_TX_FLAGS(0, VEOL);
223
+	_TX_FLAGS(0, INTREQ);
224
+	_TX_FLAGS(0, RTSENA);
225
+	_TX_FLAGS(0, CTSENA);
226
+	_TX_FLAGS(1, NOACK);
227
+
228
+#undef _TX_FLAGS
229
+
230
+	/*
231
+	 * RTS/CTS
232
+	 */
233
+	if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) {
234
+		if ((flags & AR5K_TXDESC_RTSENA) &&
235
+				(flags & AR5K_TXDESC_CTSENA))
236
+			return -EINVAL;
237
+		tx_ctl->tx_control_2 |= rtscts_duration &
238
+				AR5K_4W_TX_DESC_CTL2_RTS_DURATION;
239
+		tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate,
240
+				AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE);
241
+	}
242
+
243
+	return 0;
244
+}
245
+
246
+/*
247
+ * Proccess the tx status descriptor on 5210/5211
248
+ */
249
+static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah __unused,
250
+		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
251
+{
252
+	struct ath5k_hw_2w_tx_ctl *tx_ctl;
253
+	struct ath5k_hw_tx_status *tx_status;
254
+
255
+	tx_ctl = &desc->ud.ds_tx5210.tx_ctl;
256
+	tx_status = &desc->ud.ds_tx5210.tx_stat;
257
+
258
+	/* No frame has been send or error */
259
+	if ((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)
260
+		return -EINPROGRESS;
261
+
262
+	/*
263
+	 * Get descriptor status
264
+	 */
265
+	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
266
+		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
267
+	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
268
+		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
269
+	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
270
+		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
271
+	/*TODO: ts->ts_virtcol + test*/
272
+	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
273
+		AR5K_DESC_TX_STATUS1_SEQ_NUM);
274
+	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
275
+		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
276
+	ts->ts_antenna = 1;
277
+	ts->ts_status = 0;
278
+	ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0,
279
+		AR5K_2W_TX_DESC_CTL0_XMIT_RATE);
280
+	ts->ts_retry[0] = ts->ts_longretry;
281
+	ts->ts_final_idx = 0;
282
+
283
+	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
284
+		if (tx_status->tx_status_0 &
285
+				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
286
+			ts->ts_status |= AR5K_TXERR_XRETRY;
287
+
288
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
289
+			ts->ts_status |= AR5K_TXERR_FIFO;
290
+
291
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
292
+			ts->ts_status |= AR5K_TXERR_FILT;
293
+	}
294
+
295
+	return 0;
296
+}
297
+
298
+/*
299
+ * Proccess a tx status descriptor on 5212
300
+ */
301
+static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah __unused,
302
+		struct ath5k_desc *desc, struct ath5k_tx_status *ts)
303
+{
304
+	struct ath5k_hw_4w_tx_ctl *tx_ctl;
305
+	struct ath5k_hw_tx_status *tx_status;
306
+
307
+	tx_ctl = &desc->ud.ds_tx5212.tx_ctl;
308
+	tx_status = &desc->ud.ds_tx5212.tx_stat;
309
+
310
+	/* No frame has been send or error */
311
+	if (!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))
312
+		return -EINPROGRESS;
313
+
314
+	/*
315
+	 * Get descriptor status
316
+	 */
317
+	ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0,
318
+		AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP);
319
+	ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0,
320
+		AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT);
321
+	ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0,
322
+		AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT);
323
+	ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1,
324
+		AR5K_DESC_TX_STATUS1_SEQ_NUM);
325
+	ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1,
326
+		AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH);
327
+	ts->ts_antenna = (tx_status->tx_status_1 &
328
+		AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1;
329
+	ts->ts_status = 0;
330
+
331
+	ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1,
332
+			AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX);
333
+
334
+	ts->ts_retry[0] = ts->ts_longretry;
335
+	ts->ts_rate[0] = tx_ctl->tx_control_3 &
336
+		AR5K_4W_TX_DESC_CTL3_XMIT_RATE0;
337
+
338
+	/* TX error */
339
+	if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) {
340
+		if (tx_status->tx_status_0 &
341
+				AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES)
342
+			ts->ts_status |= AR5K_TXERR_XRETRY;
343
+
344
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN)
345
+			ts->ts_status |= AR5K_TXERR_FIFO;
346
+
347
+		if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED)
348
+			ts->ts_status |= AR5K_TXERR_FILT;
349
+	}
350
+
351
+	return 0;
352
+}
353
+
354
+/*
355
+ * RX Descriptors
356
+ */
357
+
358
+/*
359
+ * Initialize an rx control descriptor
360
+ */
361
+static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah __unused,
362
+				  struct ath5k_desc *desc,
363
+				  u32 size, unsigned int flags)
364
+{
365
+	struct ath5k_hw_rx_ctl *rx_ctl;
366
+
367
+	rx_ctl = &desc->ud.ds_rx.rx_ctl;
368
+
369
+	/*
370
+	 * Clear the descriptor
371
+	 * If we don't clean the status descriptor,
372
+	 * while scanning we get too many results,
373
+	 * most of them virtual, after some secs
374
+	 * of scanning system hangs. M.F.
375
+	*/
376
+	memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc));
377
+
378
+	/* Setup descriptor */
379
+	rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN;
380
+	if (rx_ctl->rx_control_1 != size)
381
+		return -EINVAL;
382
+
383
+	if (flags & AR5K_RXDESC_INTREQ)
384
+		rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ;
385
+
386
+	if (desc->ds_link < ah->ah_sc->desc_daddr ||
387
+	    desc->ds_link + sizeof(struct ath5k_desc) > ah->ah_sc->desc_daddr + ah->ah_sc->desc_len ||
388
+	    size != 2400 ||
389
+	    *(void **)bus_to_virt(desc->ds_data + 2408) != bus_to_virt(desc->ds_data)) {
390
+		DBG("ath5k! set rx desc %p for %d bytes at %p (%08x) link to %p (%08x)\n",
391
+		    desc, size, bus_to_virt(desc->ds_data), desc->ds_data,
392
+		    bus_to_virt(desc->ds_link), desc->ds_link);
393
+		asm("cli;hlt");
394
+	}
395
+
396
+	return 0;
397
+}
398
+
399
+/*
400
+ * Proccess the rx status descriptor on 5210/5211
401
+ */
402
+static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah __unused,
403
+		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
404
+{
405
+	struct ath5k_hw_rx_status *rx_status;
406
+
407
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
408
+
409
+	/* No frame received / not ready */
410
+	if (!(rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_DONE))
411
+		return -EINPROGRESS;
412
+
413
+	/*
414
+	 * Frame receive status
415
+	 */
416
+	rs->rs_datalen = rx_status->rx_status_0 &
417
+		AR5K_5210_RX_DESC_STATUS0_DATA_LEN;
418
+	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
419
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL);
420
+	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
421
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE);
422
+	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
423
+		AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA);
424
+	rs->rs_more = !!(rx_status->rx_status_0 &
425
+		AR5K_5210_RX_DESC_STATUS0_MORE);
426
+	/* TODO: this timestamp is 13 bit, later on we assume 15 bit */
427
+	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
428
+		AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
429
+	rs->rs_status = 0;
430
+	rs->rs_phyerr = 0;
431
+	rs->rs_keyix = AR5K_RXKEYIX_INVALID;
432
+
433
+	/*
434
+	 * Receive/descriptor errors
435
+	 */
436
+	if (!(rx_status->rx_status_1 &
437
+	      AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
438
+		if (rx_status->rx_status_1 &
439
+				AR5K_5210_RX_DESC_STATUS1_CRC_ERROR)
440
+			rs->rs_status |= AR5K_RXERR_CRC;
441
+
442
+		if (rx_status->rx_status_1 &
443
+				AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN)
444
+			rs->rs_status |= AR5K_RXERR_FIFO;
445
+
446
+		if (rx_status->rx_status_1 &
447
+				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) {
448
+			rs->rs_status |= AR5K_RXERR_PHY;
449
+			rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1,
450
+				AR5K_5210_RX_DESC_STATUS1_PHY_ERROR);
451
+		}
452
+
453
+		if (rx_status->rx_status_1 &
454
+				AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
455
+			rs->rs_status |= AR5K_RXERR_DECRYPT;
456
+	}
457
+
458
+	return 0;
459
+}
460
+
461
+/*
462
+ * Proccess the rx status descriptor on 5212
463
+ */
464
+static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah __unused,
465
+		struct ath5k_desc *desc, struct ath5k_rx_status *rs)
466
+{
467
+	struct ath5k_hw_rx_status *rx_status;
468
+	struct ath5k_hw_rx_error *rx_err;
469
+
470
+	rx_status = &desc->ud.ds_rx.u.rx_stat;
471
+
472
+	/* Overlay on error */
473
+	rx_err = &desc->ud.ds_rx.u.rx_err;
474
+
475
+	/* No frame received / not ready */
476
+	if (!(rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_DONE))
477
+		return -EINPROGRESS;
478
+
479
+	/*
480
+	 * Frame receive status
481
+	 */
482
+	rs->rs_datalen = rx_status->rx_status_0 &
483
+		AR5K_5212_RX_DESC_STATUS0_DATA_LEN;
484
+	rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0,
485
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL);
486
+	rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0,
487
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE);
488
+	rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0,
489
+		AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA);
490
+	rs->rs_more = !!(rx_status->rx_status_0 &
491
+		AR5K_5212_RX_DESC_STATUS0_MORE);
492
+	rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1,
493
+		AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP);
494
+	rs->rs_status = 0;
495
+	rs->rs_phyerr = 0;
496
+	rs->rs_keyix = AR5K_RXKEYIX_INVALID;
497
+
498
+	/*
499
+	 * Receive/descriptor errors
500
+	 */
501
+	if (!(rx_status->rx_status_1 &
502
+	      AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) {
503
+		if (rx_status->rx_status_1 &
504
+				AR5K_5212_RX_DESC_STATUS1_CRC_ERROR)
505
+			rs->rs_status |= AR5K_RXERR_CRC;
506
+
507
+		if (rx_status->rx_status_1 &
508
+				AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) {
509
+			rs->rs_status |= AR5K_RXERR_PHY;
510
+			rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1,
511
+					   AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE);
512
+		}
513
+
514
+		if (rx_status->rx_status_1 &
515
+				AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR)
516
+			rs->rs_status |= AR5K_RXERR_DECRYPT;
517
+
518
+		if (rx_status->rx_status_1 &
519
+				AR5K_5212_RX_DESC_STATUS1_MIC_ERROR)
520
+			rs->rs_status |= AR5K_RXERR_MIC;
521
+	}
522
+
523
+	return 0;
524
+}
525
+
526
+/*
527
+ * Init function pointers inside ath5k_hw struct
528
+ */
529
+int ath5k_hw_init_desc_functions(struct ath5k_hw *ah)
530
+{
531
+
532
+	if (ah->ah_version != AR5K_AR5210 &&
533
+	    ah->ah_version != AR5K_AR5211 &&
534
+	    ah->ah_version != AR5K_AR5212)
535
+		return -ENOTSUP;
536
+
537
+	if (ah->ah_version == AR5K_AR5212) {
538
+		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
539
+		ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc;
540
+		ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status;
541
+	} else {
542
+		ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc;
543
+		ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc;
544
+		ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status;
545
+	}
546
+
547
+	if (ah->ah_version == AR5K_AR5212)
548
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status;
549
+	else if (ah->ah_version <= AR5K_AR5211)
550
+		ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status;
551
+
552
+	return 0;
553
+}
554
+

+ 631
- 0
src/drivers/net/ath5k/ath5k_dma.c View File

@@ -0,0 +1,631 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ *
5
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ *
19
+ */
20
+
21
+FILE_LICENCE ( MIT );
22
+
23
+/*************************************\
24
+* DMA and interrupt masking functions *
25
+\*************************************/
26
+
27
+/*
28
+ * dma.c - DMA and interrupt masking functions
29
+ *
30
+ * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and
31
+ * handle queue setup for 5210 chipset (rest are handled on qcu.c).
32
+ * Also we setup interrupt mask register (IMR) and read the various iterrupt
33
+ * status registers (ISR).
34
+ *
35
+ * TODO: Handle SISR on 5211+ and introduce a function to return the queue
36
+ * number that resulted the interrupt.
37
+ */
38
+
39
+#include <unistd.h>
40
+
41
+#include "ath5k.h"
42
+#include "reg.h"
43
+#include "base.h"
44
+
45
+/*********\
46
+* Receive *
47
+\*********/
48
+
49
+/**
50
+ * ath5k_hw_start_rx_dma - Start DMA receive
51
+ *
52
+ * @ah:	The &struct ath5k_hw
53
+ */
54
+void ath5k_hw_start_rx_dma(struct ath5k_hw *ah)
55
+{
56
+	ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR);
57
+	ath5k_hw_reg_read(ah, AR5K_CR);
58
+}
59
+
60
+/**
61
+ * ath5k_hw_stop_rx_dma - Stop DMA receive
62
+ *
63
+ * @ah:	The &struct ath5k_hw
64
+ */
65
+int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah)
66
+{
67
+	unsigned int i;
68
+
69
+	ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR);
70
+
71
+	/*
72
+	 * It may take some time to disable the DMA receive unit
73
+	 */
74
+	for (i = 1000; i > 0 &&
75
+			(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0;
76
+			i--)
77
+		udelay(10);
78
+
79
+	return i ? 0 : -EBUSY;
80
+}
81
+
82
+/**
83
+ * ath5k_hw_get_rxdp - Get RX Descriptor's address
84
+ *
85
+ * @ah: The &struct ath5k_hw
86
+ *
87
+ * XXX: Is RXDP read and clear ?
88
+ */
89
+u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah)
90
+{
91
+	return ath5k_hw_reg_read(ah, AR5K_RXDP);
92
+}
93
+
94
+/**
95
+ * ath5k_hw_set_rxdp - Set RX Descriptor's address
96
+ *
97
+ * @ah: The &struct ath5k_hw
98
+ * @phys_addr: RX descriptor address
99
+ *
100
+ * XXX: Should we check if rx is enabled before setting rxdp ?
101
+ */
102
+void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr)
103
+{
104
+	ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP);
105
+}
106
+
107
+
108
+/**********\
109
+* Transmit *
110
+\**********/
111
+
112
+/**
113
+ * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue
114
+ *
115
+ * @ah: The &struct ath5k_hw
116
+ * @queue: The hw queue number
117
+ *
118
+ * Start DMA transmit for a specific queue and since 5210 doesn't have
119
+ * QCU/DCU, set up queue parameters for 5210 here based on queue type (one
120
+ * queue for normal data and one queue for beacons). For queue setup
121
+ * on newer chips check out qcu.c. Returns -EINVAL if queue number is out
122
+ * of range or if queue is already disabled.
123
+ *
124
+ * NOTE: Must be called after setting up tx control descriptor for that
125
+ * queue (see below).
126
+ */
127
+int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue)
128
+{
129
+	u32 tx_queue;
130
+
131
+	/* Return if queue is declared inactive */
132
+	if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
133
+		return -EIO;
134
+
135
+	if (ah->ah_version == AR5K_AR5210) {
136
+		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
137
+
138
+		/* Assume always a data queue */
139
+		tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0;
140
+
141
+		/* Start queue */
142
+		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
143
+		ath5k_hw_reg_read(ah, AR5K_CR);
144
+	} else {
145
+		/* Return if queue is disabled */
146
+		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue))
147
+			return -EIO;
148
+
149
+		/* Start queue */
150
+		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue);
151
+	}
152
+
153
+	return 0;
154
+}
155
+
156
+/**
157
+ * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue
158
+ *
159
+ * @ah: The &struct ath5k_hw
160
+ * @queue: The hw queue number
161
+ *
162
+ * Stop DMA transmit on a specific hw queue and drain queue so we don't
163
+ * have any pending frames. Returns -EBUSY if we still have pending frames,
164
+ * -EINVAL if queue number is out of range.
165
+ *
166
+ */
167
+int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue)
168
+{
169
+	unsigned int i = 40;
170
+	u32 tx_queue, pending;
171
+
172
+	/* Return if queue is declared inactive */
173
+	if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
174
+		return -EIO;
175
+
176
+	if (ah->ah_version == AR5K_AR5210) {
177
+		tx_queue = ath5k_hw_reg_read(ah, AR5K_CR);
178
+
179
+		/* Assume a data queue */
180
+		tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0;
181
+
182
+		/* Stop queue */
183
+		ath5k_hw_reg_write(ah, tx_queue, AR5K_CR);
184
+		ath5k_hw_reg_read(ah, AR5K_CR);
185
+	} else {
186
+		/*
187
+		 * Schedule TX disable and wait until queue is empty
188
+		 */
189
+		AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue);
190
+
191
+		/*Check for pending frames*/
192
+		do {
193
+			pending = ath5k_hw_reg_read(ah,
194
+				AR5K_QUEUE_STATUS(queue)) &
195
+				AR5K_QCU_STS_FRMPENDCNT;
196
+			udelay(100);
197
+		} while (--i && pending);
198
+
199
+		/* For 2413+ order PCU to drop packets using
200
+		 * QUIET mechanism */
201
+		if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && pending) {
202
+			/* Set periodicity and duration */
203
+			ath5k_hw_reg_write(ah,
204
+				AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)|
205
+				AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR),
206
+				AR5K_QUIET_CTL2);
207
+
208
+			/* Enable quiet period for current TSF */
209
+			ath5k_hw_reg_write(ah,
210
+				AR5K_QUIET_CTL1_QT_EN |
211
+				AR5K_REG_SM(ath5k_hw_reg_read(ah,
212
+						AR5K_TSF_L32_5211) >> 10,
213
+						AR5K_QUIET_CTL1_NEXT_QT_TSF),
214
+				AR5K_QUIET_CTL1);
215
+
216
+			/* Force channel idle high */
217
+			AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211,
218
+					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
219
+
220
+			/* Wait a while and disable mechanism */
221
+			udelay(200);
222
+			AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1,
223
+						AR5K_QUIET_CTL1_QT_EN);
224
+
225
+			/* Re-check for pending frames */
226
+			i = 40;
227
+			do {
228
+				pending = ath5k_hw_reg_read(ah,
229
+					AR5K_QUEUE_STATUS(queue)) &
230
+					AR5K_QCU_STS_FRMPENDCNT;
231
+				udelay(100);
232
+			} while (--i && pending);
233
+
234
+			AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211,
235
+					AR5K_DIAG_SW_CHANEL_IDLE_HIGH);
236
+		}
237
+
238
+		/* Clear register */
239
+		ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD);
240
+		if (pending)
241
+			return -EBUSY;
242
+	}
243
+
244
+	/* TODO: Check for success on 5210 else return error */
245
+	return 0;
246
+}
247
+
248
+/**
249
+ * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue
250
+ *
251
+ * @ah: The &struct ath5k_hw
252
+ * @queue: The hw queue number
253
+ *
254
+ * Get TX descriptor's address for a specific queue. For 5210 we ignore
255
+ * the queue number and use tx queue type since we only have 2 queues.
256
+ * We use TXDP0 for normal data queue and TXDP1 for beacon queue.
257
+ * For newer chips with QCU/DCU we just read the corresponding TXDP register.
258
+ *
259
+ * XXX: Is TXDP read and clear ?
260
+ */
261
+u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue)
262
+{
263
+	u16 tx_reg;
264
+
265
+	/*
266
+	 * Get the transmit queue descriptor pointer from the selected queue
267
+	 */
268
+	/*5210 doesn't have QCU*/
269
+	if (ah->ah_version == AR5K_AR5210) {
270
+		/* Assume a data queue */
271
+		tx_reg = AR5K_NOQCU_TXDP0;
272
+	} else {
273
+		tx_reg = AR5K_QUEUE_TXDP(queue);
274
+	}
275
+
276
+	return ath5k_hw_reg_read(ah, tx_reg);
277
+}
278
+
279
+/**
280
+ * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue
281
+ *
282
+ * @ah: The &struct ath5k_hw
283
+ * @queue: The hw queue number
284
+ *
285
+ * Set TX descriptor's address for a specific queue. For 5210 we ignore
286
+ * the queue number and we use tx queue type since we only have 2 queues
287
+ * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue.
288
+ * For newer chips with QCU/DCU we just set the corresponding TXDP register.
289
+ * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still
290
+ * active.
291
+ */
292
+int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr)
293
+{
294
+	u16 tx_reg;
295
+
296
+	/*
297
+	 * Set the transmit queue descriptor pointer register by type
298
+	 * on 5210
299
+	 */
300
+	if (ah->ah_version == AR5K_AR5210) {
301
+		/* Assume a data queue */
302
+		tx_reg = AR5K_NOQCU_TXDP0;
303
+	} else {
304
+		/*
305
+		 * Set the transmit queue descriptor pointer for
306
+		 * the selected queue on QCU for 5211+
307
+		 * (this won't work if the queue is still active)
308
+		 */
309
+		if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue))
310
+			return -EIO;
311
+
312
+		tx_reg = AR5K_QUEUE_TXDP(queue);
313
+	}
314
+
315
+	/* Set descriptor pointer */
316
+	ath5k_hw_reg_write(ah, phys_addr, tx_reg);
317
+
318
+	return 0;
319
+}
320
+
321
+/**
322
+ * ath5k_hw_update_tx_triglevel - Update tx trigger level
323
+ *
324
+ * @ah: The &struct ath5k_hw
325
+ * @increase: Flag to force increase of trigger level
326
+ *
327
+ * This function increases/decreases the tx trigger level for the tx fifo
328
+ * buffer (aka FIFO threshold) that is used to indicate when PCU flushes
329
+ * the buffer and transmits it's data. Lowering this results sending small
330
+ * frames more quickly but can lead to tx underruns, raising it a lot can
331
+ * result other problems (i think bmiss is related). Right now we start with
332
+ * the lowest possible (64Bytes) and if we get tx underrun we increase it using
333
+ * the increase flag. Returns -EIO if we have have reached maximum/minimum.
334
+ *
335
+ * XXX: Link this with tx DMA size ?
336
+ * XXX: Use it to save interrupts ?
337
+ * TODO: Needs testing, i think it's related to bmiss...
338
+ */
339
+int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, int increase)
340
+{
341
+	u32 trigger_level, imr;
342
+	int ret = -EIO;
343
+
344
+	/*
345
+	 * Disable interrupts by setting the mask
346
+	 */
347
+	imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL);
348
+
349
+	trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG),
350
+			AR5K_TXCFG_TXFULL);
351
+
352
+	if (!increase) {
353
+		if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES)
354
+			goto done;
355
+	} else
356
+		trigger_level +=
357
+			((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2);
358
+
359
+	/*
360
+	 * Update trigger level on success
361
+	 */
362
+	if (ah->ah_version == AR5K_AR5210)
363
+		ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL);
364
+	else
365
+		AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG,
366
+				AR5K_TXCFG_TXFULL, trigger_level);
367
+
368
+	ret = 0;
369
+
370
+done:
371
+	/*
372
+	 * Restore interrupt mask
373
+	 */
374
+	ath5k_hw_set_imr(ah, imr);
375
+
376
+	return ret;
377
+}
378
+
379
+/*******************\
380
+* Interrupt masking *
381
+\*******************/
382
+
383
+/**
384
+ * ath5k_hw_is_intr_pending - Check if we have pending interrupts
385
+ *
386
+ * @ah: The &struct ath5k_hw
387
+ *
388
+ * Check if we have pending interrupts to process. Returns 1 if we
389
+ * have pending interrupts and 0 if we haven't.
390
+ */
391
+int ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
392
+{
393
+	return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0;
394
+}
395
+
396
+/**
397
+ * ath5k_hw_get_isr - Get interrupt status
398
+ *
399
+ * @ah: The @struct ath5k_hw
400
+ * @interrupt_mask: Driver's interrupt mask used to filter out
401
+ * interrupts in sw.
402
+ *
403
+ * This function is used inside our interrupt handler to determine the reason
404
+ * for the interrupt by reading Primary Interrupt Status Register. Returns an
405
+ * abstract interrupt status mask which is mostly ISR with some uncommon bits
406
+ * being mapped on some standard non hw-specific positions
407
+ * (check out &ath5k_int).
408
+ *
409
+ * NOTE: We use read-and-clear register, so after this function is called ISR
410
+ * is zeroed.
411
+ */
412
+int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
413
+{
414
+	u32 data;
415
+
416
+	/*
417
+	 * Read interrupt status from the Interrupt Status register
418
+	 * on 5210
419
+	 */
420
+	if (ah->ah_version == AR5K_AR5210) {
421
+		data = ath5k_hw_reg_read(ah, AR5K_ISR);
422
+		if (data == AR5K_INT_NOCARD) {
423
+			*interrupt_mask = data;
424
+			return -ENODEV;
425
+		}
426
+	} else {
427
+		/*
428
+		 * Read interrupt status from Interrupt
429
+		 * Status Register shadow copy (Read And Clear)
430
+		 *
431
+		 * Note: PISR/SISR Not available on 5210
432
+		 */
433
+		data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
434
+		if (data == AR5K_INT_NOCARD) {
435
+			*interrupt_mask = data;
436
+			return -ENODEV;
437
+		}
438
+	}
439
+
440
+	/*
441
+	 * Get abstract interrupt mask (driver-compatible)
442
+	 */
443
+	*interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
444
+
445
+	if (ah->ah_version != AR5K_AR5210) {
446
+		u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
447
+
448
+		/*HIU = Host Interface Unit (PCI etc)*/
449
+		if (data & (AR5K_ISR_HIUERR))
450
+			*interrupt_mask |= AR5K_INT_FATAL;
451
+
452
+		/*Beacon Not Ready*/
453
+		if (data & (AR5K_ISR_BNR))
454
+			*interrupt_mask |= AR5K_INT_BNR;
455
+
456
+		if (sisr2 & (AR5K_SISR2_SSERR | AR5K_SISR2_DPERR |
457
+			     AR5K_SISR2_MCABT))
458
+			*interrupt_mask |= AR5K_INT_FATAL;
459
+
460
+		if (data & AR5K_ISR_TIM)
461
+			*interrupt_mask |= AR5K_INT_TIM;
462
+
463
+		if (data & AR5K_ISR_BCNMISC) {
464
+			if (sisr2 & AR5K_SISR2_TIM)
465
+				*interrupt_mask |= AR5K_INT_TIM;
466
+			if (sisr2 & AR5K_SISR2_DTIM)
467
+				*interrupt_mask |= AR5K_INT_DTIM;
468
+			if (sisr2 & AR5K_SISR2_DTIM_SYNC)
469
+				*interrupt_mask |= AR5K_INT_DTIM_SYNC;
470
+			if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
471
+				*interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
472
+			if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
473
+				*interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
474
+		}
475
+
476
+		if (data & AR5K_ISR_RXDOPPLER)
477
+			*interrupt_mask |= AR5K_INT_RX_DOPPLER;
478
+		if (data & AR5K_ISR_QCBRORN) {
479
+			*interrupt_mask |= AR5K_INT_QCBRORN;
480
+			ah->ah_txq_isr |= AR5K_REG_MS(
481
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
482
+					AR5K_SISR3_QCBRORN);
483
+		}
484
+		if (data & AR5K_ISR_QCBRURN) {
485
+			*interrupt_mask |= AR5K_INT_QCBRURN;
486
+			ah->ah_txq_isr |= AR5K_REG_MS(
487
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
488
+					AR5K_SISR3_QCBRURN);
489
+		}
490
+		if (data & AR5K_ISR_QTRIG) {
491
+			*interrupt_mask |= AR5K_INT_QTRIG;
492
+			ah->ah_txq_isr |= AR5K_REG_MS(
493
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
494
+					AR5K_SISR4_QTRIG);
495
+		}
496
+
497
+		if (data & AR5K_ISR_TXOK)
498
+			ah->ah_txq_isr |= AR5K_REG_MS(
499
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
500
+					AR5K_SISR0_QCU_TXOK);
501
+
502
+		if (data & AR5K_ISR_TXDESC)
503
+			ah->ah_txq_isr |= AR5K_REG_MS(
504
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
505
+					AR5K_SISR0_QCU_TXDESC);
506
+
507
+		if (data & AR5K_ISR_TXERR)
508
+			ah->ah_txq_isr |= AR5K_REG_MS(
509
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
510
+					AR5K_SISR1_QCU_TXERR);
511
+
512
+		if (data & AR5K_ISR_TXEOL)
513
+			ah->ah_txq_isr |= AR5K_REG_MS(
514
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
515
+					AR5K_SISR1_QCU_TXEOL);
516
+
517
+		if (data & AR5K_ISR_TXURN)
518
+			ah->ah_txq_isr |= AR5K_REG_MS(
519
+					ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
520
+					AR5K_SISR2_QCU_TXURN);
521
+	} else {
522
+		if (data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT |
523
+			    AR5K_ISR_HIUERR | AR5K_ISR_DPERR))
524
+			*interrupt_mask |= AR5K_INT_FATAL;
525
+
526
+		/*
527
+		 * XXX: BMISS interrupts may occur after association.
528
+		 * I found this on 5210 code but it needs testing. If this is
529
+		 * true we should disable them before assoc and re-enable them
530
+		 * after a successful assoc + some jiffies.
531
+			interrupt_mask &= ~AR5K_INT_BMISS;
532
+		 */
533
+	}
534
+
535
+	return 0;
536
+}
537
+
538
+/**
539
+ * ath5k_hw_set_imr - Set interrupt mask
540
+ *
541
+ * @ah: The &struct ath5k_hw
542
+ * @new_mask: The new interrupt mask to be set
543
+ *
544
+ * Set the interrupt mask in hw to save interrupts. We do that by mapping
545
+ * ath5k_int bits to hw-specific bits to remove abstraction and writing
546
+ * Interrupt Mask Register.
547
+ */
548
+enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
549
+{
550
+	enum ath5k_int old_mask, int_mask;
551
+
552
+	old_mask = ah->ah_imr;
553
+
554
+	/*
555
+	 * Disable card interrupts to prevent any race conditions
556
+	 * (they will be re-enabled afterwards if AR5K_INT GLOBAL
557
+	 * is set again on the new mask).
558
+	 */
559
+	if (old_mask & AR5K_INT_GLOBAL) {
560
+		ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
561
+		ath5k_hw_reg_read(ah, AR5K_IER);
562
+	}
563
+
564
+	/*
565
+	 * Add additional, chipset-dependent interrupt mask flags
566
+	 * and write them to the IMR (interrupt mask register).
567
+	 */
568
+	int_mask = new_mask & AR5K_INT_COMMON;
569
+
570
+	if (ah->ah_version != AR5K_AR5210) {
571
+		/* Preserve per queue TXURN interrupt mask */
572
+		u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
573
+				& AR5K_SIMR2_QCU_TXURN;
574
+
575
+		if (new_mask & AR5K_INT_FATAL) {
576
+			int_mask |= AR5K_IMR_HIUERR;
577
+			simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
578
+				| AR5K_SIMR2_DPERR);
579
+		}
580
+
581
+		/*Beacon Not Ready*/
582
+		if (new_mask & AR5K_INT_BNR)
583
+			int_mask |= AR5K_INT_BNR;
584
+
585
+		if (new_mask & AR5K_INT_TIM)
586
+			int_mask |= AR5K_IMR_TIM;
587
+
588
+		if (new_mask & AR5K_INT_TIM)
589
+			simr2 |= AR5K_SISR2_TIM;
590
+		if (new_mask & AR5K_INT_DTIM)
591
+			simr2 |= AR5K_SISR2_DTIM;
592
+		if (new_mask & AR5K_INT_DTIM_SYNC)
593
+			simr2 |= AR5K_SISR2_DTIM_SYNC;
594
+		if (new_mask & AR5K_INT_BCN_TIMEOUT)
595
+			simr2 |= AR5K_SISR2_BCN_TIMEOUT;
596
+		if (new_mask & AR5K_INT_CAB_TIMEOUT)
597
+			simr2 |= AR5K_SISR2_CAB_TIMEOUT;
598
+
599
+		if (new_mask & AR5K_INT_RX_DOPPLER)
600
+			int_mask |= AR5K_IMR_RXDOPPLER;
601
+
602
+		/* Note: Per queue interrupt masks
603
+		 * are set via reset_tx_queue (qcu.c) */
604
+		ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
605
+		ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
606
+
607
+	} else {
608
+		if (new_mask & AR5K_INT_FATAL)
609
+			int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
610
+				| AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
611
+
612
+		ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
613
+	}
614
+
615
+	/* If RXNOFRM interrupt is masked disable it
616
+	 * by setting AR5K_RXNOFRM to zero */
617
+	if (!(new_mask & AR5K_INT_RXNOFRM))
618
+		ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
619
+
620
+	/* Store new interrupt mask */
621
+	ah->ah_imr = new_mask;
622
+
623
+	/* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
624
+	if (new_mask & AR5K_INT_GLOBAL) {
625
+		ath5k_hw_reg_write(ah, ah->ah_ier, AR5K_IER);
626
+		ath5k_hw_reg_read(ah, AR5K_IER);
627
+	}
628
+
629
+	return old_mask;
630
+}
631
+

+ 1749
- 0
src/drivers/net/ath5k/ath5k_eeprom.c
File diff suppressed because it is too large
View File


+ 122
- 0
src/drivers/net/ath5k/ath5k_gpio.c View File

@@ -0,0 +1,122 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ *
5
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ *
19
+ */
20
+
21
+FILE_LICENCE ( MIT );
22
+
23
+/****************\
24
+  GPIO Functions
25
+\****************/
26
+
27
+#include "ath5k.h"
28
+#include "reg.h"
29
+#include "base.h"
30
+
31
+/*
32
+ * Set GPIO inputs
33
+ */
34
+int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio)
35
+{
36
+	if (gpio >= AR5K_NUM_GPIO)
37
+		return -EINVAL;
38
+
39
+	ath5k_hw_reg_write(ah,
40
+		(ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
41
+		| AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR);
42
+
43
+	return 0;
44
+}
45
+
46
+/*
47
+ * Set GPIO outputs
48
+ */
49
+int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio)
50
+{
51
+	if (gpio >= AR5K_NUM_GPIO)
52
+		return -EINVAL;
53
+
54
+	ath5k_hw_reg_write(ah,
55
+		(ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio))
56
+		| AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR);
57
+
58
+	return 0;
59
+}
60
+
61
+/*
62
+ * Get GPIO state
63
+ */
64
+u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio)
65
+{
66
+	if (gpio >= AR5K_NUM_GPIO)
67
+		return 0xffffffff;
68
+
69
+	/* GPIO input magic */
70
+	return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) &
71
+		0x1;
72
+}
73
+
74
+/*
75
+ * Set GPIO state
76
+ */
77
+int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val)
78
+{
79
+	u32 data;
80
+
81
+	if (gpio >= AR5K_NUM_GPIO)
82
+		return -EINVAL;
83
+
84
+	/* GPIO output magic */
85
+	data = ath5k_hw_reg_read(ah, AR5K_GPIODO);
86
+
87
+	data &= ~(1 << gpio);
88
+	data |= (val & 1) << gpio;
89
+
90
+	ath5k_hw_reg_write(ah, data, AR5K_GPIODO);
91
+
92
+	return 0;
93
+}
94
+
95
+/*
96
+ * Initialize the GPIO interrupt (RFKill switch)
97
+ */
98
+void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio,
99
+		u32 interrupt_level)
100
+{
101
+	u32 data;
102
+
103
+	if (gpio >= AR5K_NUM_GPIO)
104
+		return;
105
+
106
+	/*
107
+	 * Set the GPIO interrupt
108
+	 */
109
+	data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) &
110
+		~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH |
111
+		AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) |
112
+		(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA);
113
+
114
+	ath5k_hw_reg_write(ah, interrupt_level ? data :
115
+		(data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR);
116
+
117
+	ah->ah_imr |= AR5K_IMR_GPIO;
118
+
119
+	/* Enable GPIO interrupts */
120
+	AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO);
121
+}
122
+

+ 1560
- 0
src/drivers/net/ath5k/ath5k_initvals.c
File diff suppressed because it is too large
View File


+ 534
- 0
src/drivers/net/ath5k/ath5k_pcu.c View File

@@ -0,0 +1,534 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ * Copyright (c) 2007-2008 Matthew W. S. Bell  <mentor@madwifi.org>
5
+ * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu>
6
+ * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org>
7
+ * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com>
8
+ *
9
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
10
+ *
11
+ * Permission to use, copy, modify, and distribute this software for any
12
+ * purpose with or without fee is hereby granted, provided that the above
13
+ * copyright notice and this permission notice appear in all copies.
14
+ *
15
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
+ *
23
+ */
24
+
25
+FILE_LICENCE ( MIT );
26
+
27
+/*********************************\
28
+* Protocol Control Unit Functions *
29
+\*********************************/
30
+
31
+#include "ath5k.h"
32
+#include "reg.h"
33
+#include "base.h"
34
+
35
+/*******************\
36
+* Generic functions *
37
+\*******************/
38
+
39
+/**
40
+ * ath5k_hw_set_opmode - Set PCU operating mode
41
+ *
42
+ * @ah: The &struct ath5k_hw
43
+ *
44
+ * Initialize PCU for the various operating modes (AP/STA etc)
45
+ *
46
+ * For gPXE we always assume STA mode.
47
+ */
48
+int ath5k_hw_set_opmode(struct ath5k_hw *ah)
49
+{
50
+	u32 pcu_reg, beacon_reg, low_id, high_id;
51
+
52
+
53
+	/* Preserve rest settings */
54
+	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
55
+	pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
56
+			| AR5K_STA_ID1_KEYSRCH_MODE
57
+			| (ah->ah_version == AR5K_AR5210 ?
58
+			(AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
59
+
60
+	beacon_reg = 0;
61
+
62
+	pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
63
+		| (ah->ah_version == AR5K_AR5210 ?
64
+		   AR5K_STA_ID1_PWR_SV : 0);
65
+
66
+	/*
67
+	 * Set PCU registers
68
+	 */
69
+	low_id = AR5K_LOW_ID(ah->ah_sta_id);
70
+	high_id = AR5K_HIGH_ID(ah->ah_sta_id);
71
+	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
72
+	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
73
+
74
+	/*
75
+	 * Set Beacon Control Register on 5210
76
+	 */
77
+	if (ah->ah_version == AR5K_AR5210)
78
+		ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR);
79
+
80
+	return 0;
81
+}
82
+
83
+/**
84
+ * ath5k_hw_set_ack_bitrate - set bitrate for ACKs
85
+ *
86
+ * @ah: The &struct ath5k_hw
87
+ * @high: Flag to determine if we want to use high transmition rate
88
+ * for ACKs or not
89
+ *
90
+ * If high flag is set, we tell hw to use a set of control rates based on
91
+ * the current transmition rate (check out control_rates array inside reset.c).
92
+ * If not hw just uses the lowest rate available for the current modulation
93
+ * scheme being used (1Mbit for CCK and 6Mbits for OFDM).
94
+ */
95
+void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, int high)
96
+{
97
+	if (ah->ah_version != AR5K_AR5212)
98
+		return;
99
+	else {
100
+		u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB;
101
+		if (high)
102
+			AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val);
103
+		else
104
+			AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val);
105
+	}
106
+}
107
+
108
+
109
+/******************\
110
+* ACK/CTS Timeouts *
111
+\******************/
112
+
113
+/**
114
+ * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec
115
+ *
116
+ * @ah: The &struct ath5k_hw
117
+ */
118
+unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah)
119
+{
120
+	return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
121
+			AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo);
122
+}
123
+
124
+/**
125
+ * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU
126
+ *
127
+ * @ah: The &struct ath5k_hw
128
+ * @timeout: Timeout in usec
129
+ */
130
+int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout)
131
+{
132
+	if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK),
133
+			ah->ah_turbo) <= timeout)
134
+		return -EINVAL;
135
+
136
+	AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK,
137
+		ath5k_hw_htoclock(timeout, ah->ah_turbo));
138
+
139
+	return 0;
140
+}
141
+
142
+/**
143
+ * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec
144
+ *
145
+ * @ah: The &struct ath5k_hw
146
+ */
147
+unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah)
148
+{
149
+	return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah,
150
+			AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo);
151
+}
152
+
153
+/**
154
+ * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU
155
+ *
156
+ * @ah: The &struct ath5k_hw
157
+ * @timeout: Timeout in usec
158
+ */
159
+int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout)
160
+{
161
+	if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS),
162
+			ah->ah_turbo) <= timeout)
163
+		return -EINVAL;
164
+
165
+	AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS,
166
+			ath5k_hw_htoclock(timeout, ah->ah_turbo));
167
+
168
+	return 0;
169
+}
170
+
171
+
172
+/****************\
173
+* BSSID handling *
174
+\****************/
175
+
176
+/**
177
+ * ath5k_hw_get_lladdr - Get station id
178
+ *
179
+ * @ah: The &struct ath5k_hw
180
+ * @mac: The card's mac address
181
+ *
182
+ * Initialize ah->ah_sta_id using the mac address provided
183
+ * (just a memcpy).
184
+ *
185
+ * TODO: Remove it once we merge ath5k_softc and ath5k_hw
186
+ */
187
+void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
188
+{
189
+	memcpy(mac, ah->ah_sta_id, ETH_ALEN);
190
+}
191
+
192
+/**
193
+ * ath5k_hw_set_lladdr - Set station id
194
+ *
195
+ * @ah: The &struct ath5k_hw
196
+ * @mac: The card's mac address
197
+ *
198
+ * Set station id on hw using the provided mac address
199
+ */
200
+int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
201
+{
202
+	u32 low_id, high_id;
203
+	u32 pcu_reg;
204
+
205
+	/* Set new station ID */
206
+	memcpy(ah->ah_sta_id, mac, ETH_ALEN);
207
+
208
+	pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
209
+
210
+	low_id = AR5K_LOW_ID(mac);
211
+	high_id = AR5K_HIGH_ID(mac);
212
+
213
+	ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
214
+	ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
215
+
216
+	return 0;
217
+}
218
+
219
+/**
220
+ * ath5k_hw_set_associd - Set BSSID for association
221
+ *
222
+ * @ah: The &struct ath5k_hw
223
+ * @bssid: BSSID
224
+ * @assoc_id: Assoc id
225
+ *
226
+ * Sets the BSSID which trigers the "SME Join" operation
227
+ */
228
+void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
229
+{
230
+	u32 low_id, high_id;
231
+
232
+	/*
233
+	 * Set simple BSSID mask on 5212
234
+	 */
235
+	if (ah->ah_version == AR5K_AR5212) {
236
+		ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
237
+							AR5K_BSS_IDM0);
238
+		ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
239
+							AR5K_BSS_IDM1);
240
+	}
241
+
242
+	/*
243
+	 * Set BSSID which triggers the "SME Join" operation
244
+	 */
245
+	low_id = AR5K_LOW_ID(bssid);
246
+	high_id = AR5K_HIGH_ID(bssid);
247
+	ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0);
248
+	ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) <<
249
+				AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1);
250
+}
251
+
252
+/**
253
+ * ath5k_hw_set_bssid_mask - filter out bssids we listen
254
+ *
255
+ * @ah: the &struct ath5k_hw
256
+ * @mask: the bssid_mask, a u8 array of size ETH_ALEN
257
+ *
258
+ * BSSID masking is a method used by AR5212 and newer hardware to inform PCU
259
+ * which bits of the interface's MAC address should be looked at when trying
260
+ * to decide which packets to ACK. In station mode and AP mode with a single
261
+ * BSS every bit matters since we lock to only one BSS. In AP mode with
262
+ * multiple BSSes (virtual interfaces) not every bit matters because hw must
263
+ * accept frames for all BSSes and so we tweak some bits of our mac address
264
+ * in order to have multiple BSSes.
265
+ *
266
+ * NOTE: This is a simple filter and does *not* filter out all
267
+ * relevant frames. Some frames that are not for us might get ACKed from us
268
+ * by PCU because they just match the mask.
269
+ *
270
+ * When handling multiple BSSes you can get the BSSID mask by computing the
271
+ * set of  ~ ( MAC XOR BSSID ) for all bssids we handle.
272
+ *
273
+ * When you do this you are essentially computing the common bits of all your
274
+ * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with
275
+ * the MAC address to obtain the relevant bits and compare the result with
276
+ * (frame's BSSID & mask) to see if they match.
277
+ */
278
+/*
279
+ * Simple example: on your card you have have two BSSes you have created with
280
+ * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address.
281
+ * There is another BSSID-03 but you are not part of it. For simplicity's sake,
282
+ * assuming only 4 bits for a mac address and for BSSIDs you can then have:
283
+ *
284
+ *                  \
285
+ * MAC:                0001 |
286
+ * BSSID-01:   0100 | --> Belongs to us
287
+ * BSSID-02:   1001 |
288
+ *                  /
289
+ * -------------------
290
+ * BSSID-03:   0110  | --> External
291
+ * -------------------
292
+ *
293
+ * Our bssid_mask would then be:
294
+ *
295
+ *             On loop iteration for BSSID-01:
296
+ *             ~(0001 ^ 0100)  -> ~(0101)
297
+ *                             ->   1010
298
+ *             bssid_mask      =    1010
299
+ *
300
+ *             On loop iteration for BSSID-02:
301
+ *             bssid_mask &= ~(0001   ^   1001)
302
+ *             bssid_mask =   (1010)  & ~(0001 ^ 1001)
303
+ *             bssid_mask =   (1010)  & ~(1001)
304
+ *             bssid_mask =   (1010)  &  (0110)
305
+ *             bssid_mask =   0010
306
+ *
307
+ * A bssid_mask of 0010 means "only pay attention to the second least
308
+ * significant bit". This is because its the only bit common
309
+ * amongst the MAC and all BSSIDs we support. To findout what the real
310
+ * common bit is we can simply "&" the bssid_mask now with any BSSID we have
311
+ * or our MAC address (we assume the hardware uses the MAC address).
312
+ *
313
+ * Now, suppose there's an incoming frame for BSSID-03:
314
+ *
315
+ * IFRAME-01:  0110
316
+ *
317
+ * An easy eye-inspeciton of this already should tell you that this frame
318
+ * will not pass our check. This is beacuse the bssid_mask tells the
319
+ * hardware to only look at the second least significant bit and the
320
+ * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB
321
+ * as 1, which does not match 0.
322
+ *
323
+ * So with IFRAME-01 we *assume* the hardware will do:
324
+ *
325
+ *     allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
326
+ *  --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0;
327
+ *  --> allow = (0010) == 0000 ? 1 : 0;
328
+ *  --> allow = 0
329
+ *
330
+ *  Lets now test a frame that should work:
331
+ *
332
+ * IFRAME-02:  0001 (we should allow)
333
+ *
334
+ *     allow = (0001 & 1010) == 1010
335
+ *
336
+ *     allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0;
337
+ *  --> allow = (0001 & 0010) ==  (0010 & 0001) ? 1 :0;
338
+ *  --> allow = (0010) == (0010)
339
+ *  --> allow = 1
340
+ *
341
+ * Other examples:
342
+ *
343
+ * IFRAME-03:  0100 --> allowed
344
+ * IFRAME-04:  1001 --> allowed
345
+ * IFRAME-05:  1101 --> allowed but its not for us!!!
346
+ *
347
+ */
348
+int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
349
+{
350
+	u32 low_id, high_id;
351
+
352
+	/* Cache bssid mask so that we can restore it
353
+	 * on reset */
354
+	memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
355
+	if (ah->ah_version == AR5K_AR5212) {
356
+		low_id = AR5K_LOW_ID(mask);
357
+		high_id = AR5K_HIGH_ID(mask);
358
+
359
+		ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0);
360
+		ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1);
361
+
362
+		return 0;
363
+	}
364
+
365
+	return -EIO;
366
+}
367
+
368
+
369
+/************\
370
+* RX Control *
371
+\************/
372
+
373
+/**
374
+ * ath5k_hw_start_rx_pcu - Start RX engine
375
+ *
376
+ * @ah: The &struct ath5k_hw
377
+ *
378
+ * Starts RX engine on PCU so that hw can process RXed frames
379
+ * (ACK etc).
380
+ *
381
+ * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma
382
+ * TODO: Init ANI here
383
+ */
384
+void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah)
385
+{
386
+	AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
387
+}
388
+
389
+/**
390
+ * at5k_hw_stop_rx_pcu - Stop RX engine
391
+ *
392
+ * @ah: The &struct ath5k_hw
393
+ *
394
+ * Stops RX engine on PCU
395
+ *
396
+ * TODO: Detach ANI here
397
+ */
398
+void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah)
399
+{
400
+	AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX);
401
+}
402
+
403
+/*
404
+ * Set multicast filter
405
+ */
406
+void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1)
407
+{
408
+	/* Set the multicat filter */
409
+	ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0);
410
+	ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1);
411
+}
412
+
413
+/**
414
+ * ath5k_hw_get_rx_filter - Get current rx filter
415
+ *
416
+ * @ah: The &struct ath5k_hw
417
+ *
418
+ * Returns the RX filter by reading rx filter and
419
+ * phy error filter registers. RX filter is used
420
+ * to set the allowed frame types that PCU will accept
421
+ * and pass to the driver. For a list of frame types
422
+ * check out reg.h.
423
+ */
424
+u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah)
425
+{
426
+	u32 data, filter = 0;
427
+
428
+	filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER);
429
+
430
+	/*Radar detection for 5212*/
431
+	if (ah->ah_version == AR5K_AR5212) {
432
+		data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL);
433
+
434
+		if (data & AR5K_PHY_ERR_FIL_RADAR)
435
+			filter |= AR5K_RX_FILTER_RADARERR;
436
+		if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK))
437
+			filter |= AR5K_RX_FILTER_PHYERR;
438
+	}
439
+
440
+	return filter;
441
+}
442
+
443
+/**
444
+ * ath5k_hw_set_rx_filter - Set rx filter
445
+ *
446
+ * @ah: The &struct ath5k_hw
447
+ * @filter: RX filter mask (see reg.h)
448
+ *
449
+ * Sets RX filter register and also handles PHY error filter
450
+ * register on 5212 and newer chips so that we have proper PHY
451
+ * error reporting.
452
+ */
453
+void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
454
+{
455
+	u32 data = 0;
456
+
457
+	/* Set PHY error filter register on 5212*/
458
+	if (ah->ah_version == AR5K_AR5212) {
459
+		if (filter & AR5K_RX_FILTER_RADARERR)
460
+			data |= AR5K_PHY_ERR_FIL_RADAR;
461
+		if (filter & AR5K_RX_FILTER_PHYERR)
462
+			data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK;
463
+	}
464
+
465
+	/*
466
+	 * The AR5210 uses promiscous mode to detect radar activity
467
+	 */
468
+	if (ah->ah_version == AR5K_AR5210 &&
469
+			(filter & AR5K_RX_FILTER_RADARERR)) {
470
+		filter &= ~AR5K_RX_FILTER_RADARERR;
471
+		filter |= AR5K_RX_FILTER_PROM;
472
+	}
473
+
474
+	/*Zero length DMA (phy error reporting) */
475
+	if (data)
476
+		AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
477
+	else
478
+		AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
479
+
480
+	/*Write RX Filter register*/
481
+	ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER);
482
+
483
+	/*Write PHY error filter register on 5212*/
484
+	if (ah->ah_version == AR5K_AR5212)
485
+		ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL);
486
+
487
+}
488
+
489
+/*********************\
490
+* Key table functions *
491
+\*********************/
492
+
493
+/*
494
+ * Reset a key entry on the table
495
+ */
496
+int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
497
+{
498
+	unsigned int i, type;
499
+	u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
500
+
501
+	type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
502
+
503
+	for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
504
+		ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
505
+
506
+	/* Reset associated MIC entry if TKIP
507
+	 * is enabled located at offset (entry + 64) */
508
+	if (type == AR5K_KEYTABLE_TYPE_TKIP) {
509
+		for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
510
+			ath5k_hw_reg_write(ah, 0,
511
+				AR5K_KEYTABLE_OFF(micentry, i));
512
+	}
513
+
514
+	/*
515
+	 * Set NULL encryption on AR5212+
516
+	 *
517
+	 * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5)
518
+	 *       AR5K_KEYTABLE_TYPE_NULL -> 0x00000007
519
+	 *
520
+	 * Note2: Windows driver (ndiswrapper) sets this to
521
+	 *        0x00000714 instead of 0x00000007
522
+	 */
523
+	if (ah->ah_version > AR5K_AR5211) {
524
+		ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
525
+				AR5K_KEYTABLE_TYPE(entry));
526
+
527
+		if (type == AR5K_KEYTABLE_TYPE_TKIP) {
528
+			ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
529
+				AR5K_KEYTABLE_TYPE(micentry));
530
+		}
531
+	}
532
+
533
+	return 0;
534
+}

+ 2586
- 0
src/drivers/net/ath5k/ath5k_phy.c
File diff suppressed because it is too large
View File


+ 394
- 0
src/drivers/net/ath5k/ath5k_qcu.c View File

@@ -0,0 +1,394 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ *
5
+ * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ *
19
+ */
20
+
21
+FILE_LICENCE ( MIT );
22
+
23
+/********************************************\
24
+Queue Control Unit, DFS Control Unit Functions
25
+\********************************************/
26
+
27
+#include "ath5k.h"
28
+#include "reg.h"
29
+#include "base.h"
30
+
31
+/*
32
+ * Set properties for a transmit queue
33
+ */
34
+int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah,
35
+				const struct ath5k_txq_info *queue_info)
36
+{
37
+	if (ah->ah_txq.tqi_type == AR5K_TX_QUEUE_INACTIVE)
38
+		return -EIO;
39
+
40
+	memcpy(&ah->ah_txq, queue_info, sizeof(struct ath5k_txq_info));
41
+
42
+	/*XXX: Is this supported on 5210 ?*/
43
+	if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA &&
44
+			((queue_info->tqi_subtype == AR5K_WME_AC_VI) ||
45
+			(queue_info->tqi_subtype == AR5K_WME_AC_VO))) ||
46
+			queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD)
47
+		ah->ah_txq.tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS;
48
+
49
+	return 0;
50
+}
51
+
52
+/*
53
+ * Initialize a transmit queue
54
+ */
55
+int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
56
+		struct ath5k_txq_info *queue_info)
57
+{
58
+	unsigned int queue;
59
+	int ret;
60
+
61
+	/* We only use one queue */
62
+	queue = 0;
63
+
64
+	/*
65
+	 * Setup internal queue structure
66
+	 */
67
+	memset(&ah->ah_txq, 0, sizeof(struct ath5k_txq_info));
68
+	ah->ah_txq.tqi_type = queue_type;
69
+
70
+	if (queue_info != NULL) {
71
+		queue_info->tqi_type = queue_type;
72
+		ret = ath5k_hw_set_tx_queueprops(ah, queue_info);
73
+		if (ret)
74
+			return ret;
75
+	}
76
+
77
+	/*
78
+	 * We use ah_txq_status to hold a temp value for
79
+	 * the Secondary interrupt mask registers on 5211+
80
+	 * check out ath5k_hw_reset_tx_queue
81
+	 */
82
+	AR5K_Q_ENABLE_BITS(ah->ah_txq_status, 0);
83
+
84
+	return 0;
85
+}
86
+
87
+/*
88
+ * Set a transmit queue inactive
89
+ */
90
+void ath5k_hw_release_tx_queue(struct ath5k_hw *ah)
91
+{
92
+	/* This queue will be skipped in further operations */
93
+	ah->ah_txq.tqi_type = AR5K_TX_QUEUE_INACTIVE;
94
+	/*For SIMR setup*/
95
+	AR5K_Q_DISABLE_BITS(ah->ah_txq_status, 0);
96
+}
97
+
98
+/*
99
+ * Set DFS properties for a transmit queue on DCU
100
+ */
101
+int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah)
102
+{
103
+	u32 cw_min, cw_max, retry_lg, retry_sh;
104
+	struct ath5k_txq_info *tq = &ah->ah_txq;
105
+	const int queue = 0;
106
+
107
+	tq = &ah->ah_txq;
108
+
109
+	if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE)
110
+		return 0;
111
+
112
+	if (ah->ah_version == AR5K_AR5210) {
113
+		/* Only handle data queues, others will be ignored */
114
+		if (tq->tqi_type != AR5K_TX_QUEUE_DATA)
115
+			return 0;
116
+
117
+		/* Set Slot time */
118
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
119
+			AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME,
120
+			AR5K_SLOT_TIME);
121
+		/* Set ACK_CTS timeout */
122
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
123
+			AR5K_INIT_ACK_CTS_TIMEOUT_TURBO :
124
+			AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME);
125
+		/* Set Transmit Latency */
126
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
127
+			AR5K_INIT_TRANSMIT_LATENCY_TURBO :
128
+			AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210);
129
+
130
+		/* Set IFS0 */
131
+		if (ah->ah_turbo) {
132
+			 ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO +
133
+				(ah->ah_aifs + tq->tqi_aifs) *
134
+				AR5K_INIT_SLOT_TIME_TURBO) <<
135
+				AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO,
136
+				AR5K_IFS0);
137
+		} else {
138
+			ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS +
139
+				(ah->ah_aifs + tq->tqi_aifs) *
140
+				AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) |
141
+				AR5K_INIT_SIFS, AR5K_IFS0);
142
+		}
143
+
144
+		/* Set IFS1 */
145
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
146
+			AR5K_INIT_PROTO_TIME_CNTRL_TURBO :
147
+			AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1);
148
+		/* Set AR5K_PHY_SETTLING */
149
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
150
+			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
151
+			| 0x38 :
152
+			(ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F)
153
+			| 0x1C,
154
+			AR5K_PHY_SETTLING);
155
+		/* Set Frame Control Register */
156
+		ath5k_hw_reg_write(ah, ah->ah_turbo ?
157
+			(AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE |
158
+			AR5K_PHY_TURBO_SHORT | 0x2020) :
159
+			(AR5K_PHY_FRAME_CTL_INI | 0x1020),
160
+			AR5K_PHY_FRAME_CTL_5210);
161
+	}
162
+
163
+	/*
164
+	 * Calculate cwmin/max by channel mode
165
+	 */
166
+	cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN;
167
+	cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX;
168
+	ah->ah_aifs = AR5K_TUNE_AIFS;
169
+	/*XR is only supported on 5212*/
170
+	if (IS_CHAN_XR(ah->ah_current_channel) &&
171
+			ah->ah_version == AR5K_AR5212) {
172
+		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR;
173
+		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR;
174
+		ah->ah_aifs = AR5K_TUNE_AIFS_XR;
175
+	/*B mode is not supported on 5210*/
176
+	} else if (IS_CHAN_B(ah->ah_current_channel) &&
177
+			ah->ah_version != AR5K_AR5210) {
178
+		cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B;
179
+		cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B;
180
+		ah->ah_aifs = AR5K_TUNE_AIFS_11B;
181
+	}
182
+
183
+	cw_min = 1;
184
+	while (cw_min < ah->ah_cw_min)
185
+		cw_min = (cw_min << 1) | 1;
186
+
187
+	cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) :
188
+		((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1);
189
+	cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) :
190
+		((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1);
191
+
192
+	/*
193
+	 * Calculate and set retry limits
194
+	 */
195
+	if (ah->ah_software_retry) {
196
+		/* XXX Need to test this */
197
+		retry_lg = ah->ah_limit_tx_retries;
198
+		retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ?
199
+			AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg;
200
+	} else {
201
+		retry_lg = AR5K_INIT_LG_RETRY;
202
+		retry_sh = AR5K_INIT_SH_RETRY;
203
+	}
204
+
205
+	/*No QCU/DCU [5210]*/
206
+	if (ah->ah_version == AR5K_AR5210) {
207
+		ath5k_hw_reg_write(ah,
208
+			(cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S)
209
+			| AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
210
+				AR5K_NODCU_RETRY_LMT_SLG_RETRY)
211
+			| AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
212
+				AR5K_NODCU_RETRY_LMT_SSH_RETRY)
213
+			| AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY)
214
+			| AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY),
215
+			AR5K_NODCU_RETRY_LMT);
216
+	} else {
217
+		/*QCU/DCU [5211+]*/
218
+		ath5k_hw_reg_write(ah,
219
+			AR5K_REG_SM(AR5K_INIT_SLG_RETRY,
220
+				AR5K_DCU_RETRY_LMT_SLG_RETRY) |
221
+			AR5K_REG_SM(AR5K_INIT_SSH_RETRY,
222
+				AR5K_DCU_RETRY_LMT_SSH_RETRY) |
223
+			AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) |
224
+			AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY),
225
+			AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
226
+
227
+	/*===Rest is also for QCU/DCU only [5211+]===*/
228
+
229
+		/*
230
+		 * Set initial content window (cw_min/cw_max)
231
+		 * and arbitrated interframe space (aifs)...
232
+		 */
233
+		ath5k_hw_reg_write(ah,
234
+			AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) |
235
+			AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) |
236
+			AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs,
237
+				AR5K_DCU_LCL_IFS_AIFS),
238
+			AR5K_QUEUE_DFS_LOCAL_IFS(queue));
239
+
240
+		/*
241
+		 * Set misc registers
242
+		 */
243
+		/* Enable DCU early termination for this queue */
244
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
245
+					AR5K_QCU_MISC_DCU_EARLY);
246
+
247
+		/* Enable DCU to wait for next fragment from QCU */
248
+		AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
249
+					AR5K_DCU_MISC_FRAG_WAIT);
250
+
251
+		/* On Maui and Spirit use the global seqnum on DCU */
252
+		if (ah->ah_mac_version < AR5K_SREV_AR5211)
253
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue),
254
+						AR5K_DCU_MISC_SEQNUM_CTL);
255
+
256
+		if (tq->tqi_cbr_period) {
257
+			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period,
258
+				AR5K_QCU_CBRCFG_INTVAL) |
259
+				AR5K_REG_SM(tq->tqi_cbr_overflow_limit,
260
+				AR5K_QCU_CBRCFG_ORN_THRES),
261
+				AR5K_QUEUE_CBRCFG(queue));
262
+			AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue),
263
+				AR5K_QCU_MISC_FRSHED_CBR);
264
+			if (tq->tqi_cbr_overflow_limit)
265
+				AR5K_REG_ENABLE_BITS(ah,
266
+					AR5K_QUEUE_MISC(queue),
267
+					AR5K_QCU_MISC_CBR_THRES_ENABLE);
268
+		}
269
+
270
+		if (tq->tqi_ready_time &&
271
+		(tq->tqi_type != AR5K_TX_QUEUE_ID_CAB))
272
+			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time,
273
+				AR5K_QCU_RDYTIMECFG_INTVAL) |
274
+				AR5K_QCU_RDYTIMECFG_ENABLE,
275
+				AR5K_QUEUE_RDYTIMECFG(queue));
276
+
277
+		if (tq->tqi_burst_time) {
278
+			ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time,
279
+				AR5K_DCU_CHAN_TIME_DUR) |
280
+				AR5K_DCU_CHAN_TIME_ENABLE,
281
+				AR5K_QUEUE_DFS_CHANNEL_TIME(queue));
282
+
283
+			if (tq->tqi_flags
284
+			& AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)
285
+				AR5K_REG_ENABLE_BITS(ah,
286
+					AR5K_QUEUE_MISC(queue),
287
+					AR5K_QCU_MISC_RDY_VEOL_POLICY);
288
+		}
289
+
290
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE)
291
+			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS,
292
+				AR5K_QUEUE_DFS_MISC(queue));
293
+
294
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE)
295
+			ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG,
296
+				AR5K_QUEUE_DFS_MISC(queue));
297
+
298
+		/* TODO: Handle frame compression */
299
+
300
+		/*
301
+		 * Enable interrupts for this tx queue
302
+		 * in the secondary interrupt mask registers
303
+		 */
304
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE)
305
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue);
306
+
307
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE)
308
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue);
309
+
310
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE)
311
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue);
312
+
313
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE)
314
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue);
315
+
316
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
317
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
318
+
319
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
320
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
321
+
322
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
323
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
324
+
325
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
326
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
327
+
328
+		if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
329
+			AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
330
+
331
+		/* Update secondary interrupt mask registers */
332
+
333
+		/* Filter out inactive queues */
334
+		ah->ah_txq_imr_txok &= ah->ah_txq_status;
335
+		ah->ah_txq_imr_txerr &= ah->ah_txq_status;
336
+		ah->ah_txq_imr_txurn &= ah->ah_txq_status;
337
+		ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
338
+		ah->ah_txq_imr_txeol &= ah->ah_txq_status;
339
+		ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
340
+		ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
341
+		ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
342
+		ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
343
+
344
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
345
+			AR5K_SIMR0_QCU_TXOK) |
346
+			AR5K_REG_SM(ah->ah_txq_imr_txdesc,
347
+			AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0);
348
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr,
349
+			AR5K_SIMR1_QCU_TXERR) |
350
+			AR5K_REG_SM(ah->ah_txq_imr_txeol,
351
+			AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
352
+		/* Update simr2 but don't overwrite rest simr2 settings */
353
+		AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
354
+		AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
355
+			AR5K_REG_SM(ah->ah_txq_imr_txurn,
356
+			AR5K_SIMR2_QCU_TXURN));
357
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
358
+			AR5K_SIMR3_QCBRORN) |
359
+			AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
360
+			AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
361
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
362
+			AR5K_SIMR4_QTRIG), AR5K_SIMR4);
363
+		/* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
364
+		ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
365
+			AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
366
+		/* No queue has TXNOFRM enabled, disable the interrupt
367
+		 * by setting AR5K_TXNOFRM to zero */
368
+		if (ah->ah_txq_imr_nofrm == 0)
369
+			ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
370
+
371
+		/* Set QCU mask for this DCU to save power */
372
+		AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue);
373
+	}
374
+
375
+	return 0;
376
+}
377
+
378
+/*
379
+ * Set slot time on DCU
380
+ */
381
+int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time)
382
+{
383
+	if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX)
384
+		return -EINVAL;
385
+
386
+	if (ah->ah_version == AR5K_AR5210)
387
+		ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time,
388
+				ah->ah_turbo), AR5K_SLOT_TIME);
389
+	else
390
+		ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT);
391
+
392
+	return 0;
393
+}
394
+

+ 1176
- 0
src/drivers/net/ath5k/ath5k_reset.c
File diff suppressed because it is too large
View File


+ 140
- 0
src/drivers/net/ath5k/base.h View File

@@ -0,0 +1,140 @@
1
+/*-
2
+ * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
3
+ * All rights reserved.
4
+ *
5
+ * Modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>
6
+ * Original from Linux kernel 2.6.30.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions
10
+ * are met:
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ *    notice, this list of conditions and the following disclaimer,
13
+ *    without modification.
14
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
15
+ *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
16
+ *    redistribution must be conditioned upon including a substantially
17
+ *    similar Disclaimer requirement for further binary redistribution.
18
+ * 3. Neither the names of the above-listed copyright holders nor the names
19
+ *    of any contributors may be used to endorse or promote products derived
20
+ *    from this software without specific prior written permission.
21
+ *
22
+ * Alternatively, this software may be distributed under the terms of the
23
+ * GNU General Public License ("GPL") version 2 as published by the Free
24
+ * Software Foundation.
25
+ *
26
+ * NO WARRANTY
27
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
28
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
29
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
30
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
31
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
32
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
35
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
37
+ * THE POSSIBILITY OF SUCH DAMAGES.
38
+ *
39
+ */
40
+
41
+/*
42
+ * Defintions for the Atheros Wireless LAN controller driver.
43
+ */
44
+#ifndef _DEV_ATH_ATHVAR_H
45
+#define _DEV_ATH_ATHVAR_H
46
+
47
+FILE_LICENCE ( BSD3 );
48
+
49
+#include "ath5k.h"
50
+#include <gpxe/iobuf.h>
51
+
52
+#define	ATH_RXBUF	16		/* number of RX buffers */
53
+#define	ATH_TXBUF	16		/* number of TX buffers */
54
+
55
+struct ath5k_buf {
56
+	struct list_head	list;
57
+	unsigned int		flags;	/* rx descriptor flags */
58
+	struct ath5k_desc	*desc;	/* virtual addr of desc */
59
+	u32			daddr;	/* physical addr of desc */
60
+	struct io_buffer	*iob;	/* I/O buffer for buf */
61
+	u32			iobaddr;/* physical addr of iob data */
62
+};
63
+
64
+/*
65
+ * Data transmit queue state.  One of these exists for each
66
+ * hardware transmit queue.  Packets sent to us from above
67
+ * are assigned to queues based on their priority.  Not all
68
+ * devices support a complete set of hardware transmit queues.
69
+ * For those devices the array sc_ac2q will map multiple
70
+ * priorities to fewer hardware queues (typically all to one
71
+ * hardware queue).
72
+ */
73
+struct ath5k_txq {
74
+	unsigned int		qnum;	/* hardware q number */
75
+	u32			*link;	/* link ptr in last TX desc */
76
+	struct list_head	q;	/* transmit queue */
77
+	int			setup;
78
+};
79
+
80
+#if CHAN_DEBUG
81
+#define ATH_CHAN_MAX	(26+26+26+200+200)
82
+#else
83
+#define ATH_CHAN_MAX	(14+14+14+252+20)
84
+#endif
85
+
86
+/* Software Carrier, keeps track of the driver state
87
+ * associated with an instance of a device */
88
+struct ath5k_softc {
89
+	struct pci_device	*pdev;		/* for dma mapping */
90
+	void			*iobase;	/* address of the device */
91
+	struct net80211_device	*dev;		/* IEEE 802.11 common */
92
+	struct ath5k_hw		*ah;		/* Atheros HW */
93
+	struct net80211_hw_info	*hwinfo;
94
+	int			curband;
95
+	int			irq_ena; 	/* interrupts enabled */
96
+
97
+	struct ath5k_buf	*bufptr;	/* allocated buffer ptr */
98
+	struct ath5k_desc	*desc;		/* TX/RX descriptors */
99
+	u32			desc_daddr;	/* DMA (physical) address */
100
+	size_t			desc_len;	/* size of TX/RX descriptors */
101
+	u16			cachelsz;	/* cache line size */
102
+
103
+	int			status;
104
+#define ATH_STAT_INVALID	0x01		/* disable hardware accesses */
105
+#define ATH_STAT_MRRETRY	0x02		/* multi-rate retry support */
106
+#define ATH_STAT_PROMISC	0x04
107
+#define ATH_STAT_LEDSOFT	0x08		/* enable LED gpio status */
108
+#define ATH_STAT_STARTED	0x10		/* opened & irqs enabled */
109
+
110
+	unsigned int		filter_flags;	/* HW flags, AR5K_RX_FILTER_* */
111
+	unsigned int		curmode;	/* current phy mode */
112
+	struct net80211_channel	*curchan;	/* current h/w channel */
113
+
114
+	enum ath5k_int		imask;		/* interrupt mask copy */
115
+
116
+	u8			bssidmask[ETH_ALEN];
117
+
118
+	unsigned int		rxbufsize;	/* rx size based on mtu */
119
+	struct list_head	rxbuf;		/* receive buffer */
120
+	u32			*rxlink;	/* link ptr in last RX desc */
121
+
122
+	struct list_head	txbuf;		/* transmit buffer */
123
+	unsigned int		txbuf_len;	/* buf count in txbuf list */
124
+	struct ath5k_txq	txq;		/* tx queue */
125
+
126
+	int			last_calib_ticks;
127
+
128
+	int 			power_level;	/* Requested tx power in dbm */
129
+	int			assoc;		/* assocate state */
130
+
131
+	int			hw_rate;	/* Hardware tx rate code */
132
+	int			hw_rtscts_rate;	/* Hardware rts/cts rate code */
133
+};
134
+
135
+#define ath5k_hw_hasbssidmask(_ah) \
136
+	(ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
137
+#define ath5k_hw_hasveol(_ah) \
138
+	(ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0)
139
+
140
+#endif

+ 332
- 0
src/drivers/net/ath5k/desc.h View File

@@ -0,0 +1,332 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ *
17
+ */
18
+
19
+/*
20
+ * Internal RX/TX descriptor structures
21
+ * (rX: reserved fields possibily used by future versions of the ar5k chipset)
22
+ */
23
+
24
+/*
25
+ * common hardware RX control descriptor
26
+ */
27
+struct ath5k_hw_rx_ctl {
28
+	u32	rx_control_0; /* RX control word 0 */
29
+	u32	rx_control_1; /* RX control word 1 */
30
+} __attribute__ ((packed));
31
+
32
+/* RX control word 0 field/sflags */
33
+#define AR5K_DESC_RX_CTL0			0x00000000
34
+
35
+/* RX control word 1 fields/flags */
36
+#define AR5K_DESC_RX_CTL1_BUF_LEN		0x00000fff
37
+#define AR5K_DESC_RX_CTL1_INTREQ		0x00002000
38
+
39
+/*
40
+ * common hardware RX status descriptor
41
+ * 5210/11 and 5212 differ only in the flags defined below
42
+ */
43
+struct ath5k_hw_rx_status {
44
+	u32	rx_status_0; /* RX status word 0 */
45
+	u32	rx_status_1; /* RX status word 1 */
46
+} __attribute__ ((packed));
47
+
48
+/* 5210/5211 */
49
+/* RX status word 0 fields/flags */
50
+#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN		0x00000fff
51
+#define AR5K_5210_RX_DESC_STATUS0_MORE			0x00001000
52
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE		0x00078000
53
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S	15
54
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x07f80000
55
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	19
56
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA	0x38000000
57
+#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	27
58
+
59
+/* RX status word 1 fields/flags */
60
+#define AR5K_5210_RX_DESC_STATUS1_DONE			0x00000001
61
+#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
62
+#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR		0x00000004
63
+#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN		0x00000008
64
+#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000010
65
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR		0x000000e0
66
+#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S		5
67
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
68
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX		0x00007e00
69
+#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S		9
70
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x0fff8000
71
+#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	15
72
+#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS	0x10000000
73
+
74
+/* 5212 */
75
+/* RX status word 0 fields/flags */
76
+#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN		0x00000fff
77
+#define AR5K_5212_RX_DESC_STATUS0_MORE			0x00001000
78
+#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR	0x00002000
79
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE		0x000f8000
80
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S	15
81
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL	0x0ff00000
82
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S	20
83
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA	0xf0000000
84
+#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S	28
85
+
86
+/* RX status word 1 fields/flags */
87
+#define AR5K_5212_RX_DESC_STATUS1_DONE			0x00000001
88
+#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK	0x00000002
89
+#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR		0x00000004
90
+#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR	0x00000008
91
+#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR		0x00000010
92
+#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR		0x00000020
93
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID	0x00000100
94
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX		0x0000fe00
95
+#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S		9
96
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP	0x7fff0000
97
+#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S	16
98
+#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS	0x80000000
99
+
100
+/*
101
+ * common hardware RX error descriptor
102
+ */
103
+struct ath5k_hw_rx_error {
104
+	u32	rx_error_0; /* RX status word 0 */
105
+	u32	rx_error_1; /* RX status word 1 */
106
+} __attribute__ ((packed));
107
+
108
+/* RX error word 0 fields/flags */
109
+#define AR5K_RX_DESC_ERROR0			0x00000000
110
+
111
+/* RX error word 1 fields/flags */
112
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE	0x0000ff00
113
+#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S	8
114
+
115
+/* PHY Error codes */
116
+#define AR5K_DESC_RX_PHY_ERROR_NONE		0x00
117
+#define AR5K_DESC_RX_PHY_ERROR_TIMING		0x20
118
+#define AR5K_DESC_RX_PHY_ERROR_PARITY		0x40
119
+#define AR5K_DESC_RX_PHY_ERROR_RATE		0x60
120
+#define AR5K_DESC_RX_PHY_ERROR_LENGTH		0x80
121
+#define AR5K_DESC_RX_PHY_ERROR_64QAM		0xa0
122
+#define AR5K_DESC_RX_PHY_ERROR_SERVICE		0xc0
123
+#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR	0xe0
124
+
125
+/*
126
+ * 5210/5211 hardware 2-word TX control descriptor
127
+ */
128
+struct ath5k_hw_2w_tx_ctl {
129
+	u32	tx_control_0; /* TX control word 0 */
130
+	u32	tx_control_1; /* TX control word 1 */
131
+} __attribute__ ((packed));
132
+
133
+/* TX control word 0 fields/flags */
134
+#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
135
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN		0x0003f000 /*[5210 ?]*/
136
+#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S	12
137
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE		0x003c0000
138
+#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S	18
139
+#define AR5K_2W_TX_DESC_CTL0_RTSENA		0x00400000
140
+#define AR5K_2W_TX_DESC_CTL0_CLRDMASK		0x01000000
141
+#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET	0x00800000 /*[5210]*/
142
+#define AR5K_2W_TX_DESC_CTL0_VEOL		0x00800000 /*[5211]*/
143
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE		0x1c000000 /*[5210]*/
144
+#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S	26
145
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210	0x02000000
146
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211	0x1e000000
147
+
148
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT			\
149
+		(ah->ah_version == AR5K_AR5210 ?		\
150
+		AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 :	\
151
+		AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211)
152
+
153
+#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S	25
154
+#define AR5K_2W_TX_DESC_CTL0_INTREQ		0x20000000
155
+#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID	0x40000000
156
+
157
+/* TX control word 1 fields/flags */
158
+#define AR5K_2W_TX_DESC_CTL1_BUF_LEN		0x00000fff
159
+#define AR5K_2W_TX_DESC_CTL1_MORE		0x00001000
160
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210	0x0007e000
161
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211	0x000fe000
162
+
163
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX				\
164
+			(ah->ah_version == AR5K_AR5210 ?		\
165
+			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 :	\
166
+			AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211)
167
+
168
+#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S	13
169
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE		0x00700000 /*[5211]*/
170
+#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S	20
171
+#define AR5K_2W_TX_DESC_CTL1_NOACK		0x00800000 /*[5211]*/
172
+#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION	0xfff80000 /*[5210 ?]*/
173
+
174
+/* Frame types */
175
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL   0x00
176
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM     0x04
177
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL   0x08
178
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c
179
+#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS     0x10
180
+
181
+/*
182
+ * 5212 hardware 4-word TX control descriptor
183
+ */
184
+struct ath5k_hw_4w_tx_ctl {
185
+	u32	tx_control_0; /* TX control word 0 */
186
+
187
+#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN		0x00000fff
188
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER		0x003f0000
189
+#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S	16
190
+#define AR5K_4W_TX_DESC_CTL0_RTSENA		0x00400000
191
+#define AR5K_4W_TX_DESC_CTL0_VEOL		0x00800000
192
+#define AR5K_4W_TX_DESC_CTL0_CLRDMASK		0x01000000
193
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT	0x1e000000
194
+#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S	25
195
+#define AR5K_4W_TX_DESC_CTL0_INTREQ		0x20000000
196
+#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID	0x40000000
197
+#define AR5K_4W_TX_DESC_CTL0_CTSENA		0x80000000
198
+
199
+	u32	tx_control_1; /* TX control word 1 */
200
+
201
+#define AR5K_4W_TX_DESC_CTL1_BUF_LEN		0x00000fff
202
+#define AR5K_4W_TX_DESC_CTL1_MORE		0x00001000
203
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX	0x000fe000
204
+#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S	13
205
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE		0x00f00000
206
+#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S	20
207
+#define AR5K_4W_TX_DESC_CTL1_NOACK		0x01000000
208
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC		0x06000000
209
+#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S	25
210
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN	0x18000000
211
+#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S	27
212
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN	0x60000000
213
+#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S	29
214
+
215
+	u32	tx_control_2; /* TX control word 2 */
216
+
217
+#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION		0x00007fff
218
+#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE	0x00008000
219
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0		0x000f0000
220
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S		16
221
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1		0x00f00000
222
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S		20
223
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2		0x0f000000
224
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S		24
225
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3		0xf0000000
226
+#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S		28
227
+
228
+	u32	tx_control_3; /* TX control word 3 */
229
+
230
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0		0x0000001f
231
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1		0x000003e0
232
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S	5
233
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2		0x00007c00
234
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S	10
235
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3		0x000f8000
236
+#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S	15
237
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE	0x01f00000
238
+#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S	20
239
+} __attribute__ ((packed));
240
+
241
+/*
242
+ * Common TX status descriptor
243
+ */
244
+struct ath5k_hw_tx_status {
245
+	u32	tx_status_0; /* TX status word 0 */
246
+	u32	tx_status_1; /* TX status word 1 */
247
+} __attribute__ ((packed));
248
+
249
+/* TX status word 0 fields/flags */
250
+#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK	0x00000001
251
+#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES	0x00000002
252
+#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN	0x00000004
253
+#define AR5K_DESC_TX_STATUS0_FILTERED		0x00000008
254
+/*???
255
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT	0x000000f0
256
+#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S	4
257
+*/
258
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT	0x000000f0
259
+#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S	4
260
+/*???
261
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT	0x00000f00
262
+#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S	8
263
+*/
264
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT	0x00000f00
265
+#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S	8
266
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT	0x0000f000
267
+#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S	12
268
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP	0xffff0000
269
+#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S	16
270
+
271
+/* TX status word 1 fields/flags */
272
+#define AR5K_DESC_TX_STATUS1_DONE		0x00000001
273
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM		0x00001ffe
274
+#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S		1
275
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH	0x001fe000
276
+#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S	13
277
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX	0x00600000
278
+#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S	21
279
+#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS	0x00800000
280
+#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA	0x01000000
281
+
282
+/*
283
+ * 5210/5211 hardware TX descriptor
284
+ */
285
+struct ath5k_hw_5210_tx_desc {
286
+	struct ath5k_hw_2w_tx_ctl	tx_ctl;
287
+	struct ath5k_hw_tx_status	tx_stat;
288
+} __attribute__ ((packed));
289
+
290
+/*
291
+ * 5212 hardware TX descriptor
292
+ */
293
+struct ath5k_hw_5212_tx_desc {
294
+	struct ath5k_hw_4w_tx_ctl	tx_ctl;
295
+	struct ath5k_hw_tx_status	tx_stat;
296
+} __attribute__ ((packed));
297
+
298
+/*
299
+ * common hardware RX descriptor
300
+ */
301
+struct ath5k_hw_all_rx_desc {
302
+	struct ath5k_hw_rx_ctl			rx_ctl;
303
+	union {
304
+		struct ath5k_hw_rx_status	rx_stat;
305
+		struct ath5k_hw_rx_error	rx_err;
306
+	} u;
307
+} __attribute__ ((packed));
308
+
309
+/*
310
+ * Atheros hardware descriptor
311
+ * This is read and written to by the hardware
312
+ */
313
+struct ath5k_desc {
314
+	u32	ds_link;	/* physical address of the next descriptor */
315
+	u32	ds_data;	/* physical address of data buffer (skb) */
316
+
317
+	union {
318
+		struct ath5k_hw_5210_tx_desc	ds_tx5210;
319
+		struct ath5k_hw_5212_tx_desc	ds_tx5212;
320
+		struct ath5k_hw_all_rx_desc	ds_rx;
321
+	} ud;
322
+} __attribute__ ((packed));
323
+
324
+#define AR5K_RXDESC_INTREQ	0x0020
325
+
326
+#define AR5K_TXDESC_CLRDMASK	0x0001
327
+#define AR5K_TXDESC_NOACK	0x0002	/*[5211+]*/
328
+#define AR5K_TXDESC_RTSENA	0x0004
329
+#define AR5K_TXDESC_CTSENA	0x0008
330
+#define AR5K_TXDESC_INTREQ	0x0010
331
+#define AR5K_TXDESC_VEOL	0x0020	/*[5211+]*/
332
+

+ 441
- 0
src/drivers/net/ath5k/eeprom.h View File

@@ -0,0 +1,441 @@
1
+/*
2
+ * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3
+ * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4
+ *
5
+ * Permission to use, copy, modify, and distribute this software for any
6
+ * purpose with or without fee is hereby granted, provided that the above
7
+ * copyright notice and this permission notice appear in all copies.
8
+ *
9
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
+ *
17
+ */
18
+
19
+/*
20
+ * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE)
21
+ */
22
+#define AR5K_EEPROM_MAGIC		0x003d	/* EEPROM Magic number */
23
+#define AR5K_EEPROM_MAGIC_VALUE		0x5aa5	/* Default - found on EEPROM */
24
+#define AR5K_EEPROM_MAGIC_5212		0x0000145c /* 5212 */
25
+#define AR5K_EEPROM_MAGIC_5211		0x0000145b /* 5211 */
26
+#define AR5K_EEPROM_MAGIC_5210		0x0000145a /* 5210 */
27
+
28
+#define	AR5K_EEPROM_IS_HB63		0x000b	/* Talon detect */
29
+#define AR5K_EEPROM_REG_DOMAIN		0x00bf	/* EEPROM regdom */
30
+#define AR5K_EEPROM_CHECKSUM		0x00c0	/* EEPROM checksum */
31
+#define AR5K_EEPROM_INFO_BASE		0x00c0	/* EEPROM header */
32
+#define AR5K_EEPROM_INFO_MAX		(0x400 - AR5K_EEPROM_INFO_BASE)
33
+#define AR5K_EEPROM_INFO_CKSUM		0xffff
34
+#define AR5K_EEPROM_INFO(_n)		(AR5K_EEPROM_INFO_BASE + (_n))
35
+
36
+#define AR5K_EEPROM_VERSION		AR5K_EEPROM_INFO(1)	/* EEPROM Version */
37
+#define AR5K_EEPROM_VERSION_3_0		0x3000	/* No idea what's going on before this version */
38
+#define AR5K_EEPROM_VERSION_3_1		0x3001	/* ob/db values for 2Ghz (ar5211_rfregs) */
39
+#define AR5K_EEPROM_VERSION_3_2		0x3002	/* different frequency representation (eeprom_bin2freq) */
40
+#define AR5K_EEPROM_VERSION_3_3		0x3003	/* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
41
+#define AR5K_EEPROM_VERSION_3_4		0x3004	/* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
42
+#define AR5K_EEPROM_VERSION_4_0		0x4000	/* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
43
+#define AR5K_EEPROM_VERSION_4_1		0x4001	/* has ee_margin_tx_rx (eeprom_init) */
44
+#define AR5K_EEPROM_VERSION_4_2		0x4002	/* has ee_cck_ofdm_gain_delta (eeprom_init) */
45
+#define AR5K_EEPROM_VERSION_4_3		0x4003	/* power calibration changes */
46
+#define AR5K_EEPROM_VERSION_4_4		0x4004
47
+#define AR5K_EEPROM_VERSION_4_5		0x4005
48
+#define AR5K_EEPROM_VERSION_4_6		0x4006	/* has ee_scaled_cck_delta */
49
+#define AR5K_EEPROM_VERSION_4_7		0x3007	/* 4007 ? */
50
+#define AR5K_EEPROM_VERSION_4_9		0x4009	/* EAR futureproofing */
51
+#define AR5K_EEPROM_VERSION_5_0		0x5000	/* Has 2413 PDADC calibration etc */
52
+#define AR5K_EEPROM_VERSION_5_1		0x5001	/* Has capability values */
53
+#define AR5K_EEPROM_VERSION_5_3		0x5003	/* Has spur mitigation tables */
54
+
55
+#define AR5K_EEPROM_MODE_11A		0
56
+#define AR5K_EEPROM_MODE_11B		1
57
+#define AR5K_EEPROM_MODE_11G		2
58
+
59
+#define AR5K_EEPROM_HDR			AR5K_EEPROM_INFO(2)	/* Header that contains the device caps */
60
+#define AR5K_EEPROM_HDR_11A(_v)		(((_v) >> AR5K_EEPROM_MODE_11A) & 0x1)
61
+#define AR5K_EEPROM_HDR_11B(_v)		(((_v) >> AR5K_EEPROM_MODE_11B) & 0x1)
62
+#define AR5K_EEPROM_HDR_11G(_v)		(((_v) >> AR5K_EEPROM_MODE_11G) & 0x1)
63
+#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v)	(((_v) >> 3) & 0x1)	/* Disable turbo for 2Ghz (?) */
64
+#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v)	(((_v) >> 4) & 0x7f)	/* Max turbo power for a/XR mode (eeprom_init) */
65
+#define AR5K_EEPROM_HDR_DEVICE(_v)	(((_v) >> 11) & 0x7)
66
+#define AR5K_EEPROM_HDR_RFKILL(_v)	(((_v) >> 14) & 0x1)	/* Device has RFKill support */
67
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v)	(((_v) >> 15) & 0x1)	/* Disable turbo for 5Ghz */
68
+
69
+#define AR5K_EEPROM_RFKILL_GPIO_SEL	0x0000001c
70
+#define AR5K_EEPROM_RFKILL_GPIO_SEL_S	2
71
+#define AR5K_EEPROM_RFKILL_POLARITY	0x00000002
72
+#define AR5K_EEPROM_RFKILL_POLARITY_S	1
73
+
74
+/* Newer EEPROMs are using a different offset */
75
+#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \
76
+	(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
77
+
78
+#define AR5K_EEPROM_ANT_GAIN(_v)	AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
79
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v)	((s8)(((_v) >> 8) & 0xff))
80
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v)	((s8)((_v) & 0xff))
81
+
82
+/* Misc values available since EEPROM 4.0 */
83
+#define AR5K_EEPROM_MISC0		AR5K_EEPROM_INFO(4)
84
+#define AR5K_EEPROM_EARSTART(_v)	((_v) & 0xfff)
85
+#define AR5K_EEPROM_HDR_XR2_DIS(_v)	(((_v) >> 12) & 0x1)
86
+#define AR5K_EEPROM_HDR_XR5_DIS(_v)	(((_v) >> 13) & 0x1)
87
+#define AR5K_EEPROM_EEMAP(_v)		(((_v) >> 14) & 0x3)
88
+
89
+#define AR5K_EEPROM_MISC1			AR5K_EEPROM_INFO(5)
90
+#define AR5K_EEPROM_TARGET_PWRSTART(_v)		((_v) & 0xfff)
91
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v)		(((_v) >> 14) & 0x1)
92
+#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v)	(((_v) >> 15) & 0x1)
93
+
94
+#define AR5K_EEPROM_MISC2			AR5K_EEPROM_INFO(6)
95
+#define AR5K_EEPROM_EEP_FILE_VERSION(_v)	(((_v) >> 8) & 0xff)
96
+#define AR5K_EEPROM_EAR_FILE_VERSION(_v)	((_v) & 0xff)
97
+
98
+#define AR5K_EEPROM_MISC3		AR5K_EEPROM_INFO(7)
99
+#define AR5K_EEPROM_ART_BUILD_NUM(_v)	(((_v) >> 10) & 0x3f)
100
+#define AR5K_EEPROM_EAR_FILE_ID(_v)	((_v) & 0xff)
101
+
102
+#define AR5K_EEPROM_MISC4		AR5K_EEPROM_INFO(8)
103
+#define AR5K_EEPROM_CAL_DATA_START(_v)	(((_v) >> 4) & 0xfff)
104
+#define AR5K_EEPROM_MASK_R0(_v)		(((_v) >> 2) & 0x3)
105
+#define AR5K_EEPROM_MASK_R1(_v)		((_v) & 0x3)
106
+
107
+#define AR5K_EEPROM_MISC5		AR5K_EEPROM_INFO(9)
108
+#define AR5K_EEPROM_COMP_DIS(_v)	((_v) & 0x1)
109
+#define AR5K_EEPROM_AES_DIS(_v)		(((_v) >> 1) & 0x1)
110
+#define AR5K_EEPROM_FF_DIS(_v)		(((_v) >> 2) & 0x1)
111
+#define AR5K_EEPROM_BURST_DIS(_v)	(((_v) >> 3) & 0x1)
112
+#define AR5K_EEPROM_MAX_QCU(_v)		(((_v) >> 4) & 0xf)
113
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v)	(((_v) >> 8) & 0x1)
114
+#define AR5K_EEPROM_KEY_CACHE_SIZE(_v)	(((_v) >> 12) & 0xf)
115
+
116
+#define AR5K_EEPROM_MISC6		AR5K_EEPROM_INFO(10)
117
+#define AR5K_EEPROM_TX_CHAIN_DIS	((_v) & 0x8)
118
+#define AR5K_EEPROM_RX_CHAIN_DIS	(((_v) >> 3) & 0x8)
119
+#define AR5K_EEPROM_FCC_MID_EN		(((_v) >> 6) & 0x1)
120
+#define AR5K_EEPROM_JAP_U1EVEN_EN	(((_v) >> 7) & 0x1)
121
+#define AR5K_EEPROM_JAP_U2_EN		(((_v) >> 8) & 0x1)
122
+#define AR5K_EEPROM_JAP_U1ODD_EN	(((_v) >> 9) & 0x1)
123
+#define AR5K_EEPROM_JAP_11A_NEW_EN	(((_v) >> 10) & 0x1)
124
+
125
+/* calibration settings */
126
+#define AR5K_EEPROM_MODES_11A(_v)	AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
127
+#define AR5K_EEPROM_MODES_11B(_v)	AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
128
+#define AR5K_EEPROM_MODES_11G(_v)	AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
129
+#define AR5K_EEPROM_CTL(_v)		AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128)	/* Conformance test limits */
130
+#define AR5K_EEPROM_GROUPS_START(_v)	AR5K_EEPROM_OFF(_v, 0x0100, 0x0150)	/* Start of Groups */
131
+#define AR5K_EEPROM_GROUP1_OFFSET	0x0
132
+#define AR5K_EEPROM_GROUP2_OFFSET	0x5
133
+#define AR5K_EEPROM_GROUP3_OFFSET	0x37
134
+#define AR5K_EEPROM_GROUP4_OFFSET	0x46
135
+#define AR5K_EEPROM_GROUP5_OFFSET	0x55
136
+#define AR5K_EEPROM_GROUP6_OFFSET	0x65
137
+#define AR5K_EEPROM_GROUP7_OFFSET	0x69
138
+#define AR5K_EEPROM_GROUP8_OFFSET	0x6f
139
+
140
+#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
141
+								AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
142
+#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
143
+								AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
144
+#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v)	AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
145
+								AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
146
+
147
+/* [3.1 - 3.3] */
148
+#define AR5K_EEPROM_OBDB0_2GHZ		0x00ec
149
+#define AR5K_EEPROM_OBDB1_2GHZ		0x00ed
150
+
151
+#define AR5K_EEPROM_PROTECT		0x003f	/* EEPROM protect status */
152
+#define AR5K_EEPROM_PROTECT_RD_0_31	0x0001	/* Read protection bit for offsets 0x0 - 0x1f */
153
+#define AR5K_EEPROM_PROTECT_WR_0_31	0x0002	/* Write protection bit for offsets 0x0 - 0x1f */
154
+#define AR5K_EEPROM_PROTECT_RD_32_63	0x0004	/* 0x20 - 0x3f */
155
+#define AR5K_EEPROM_PROTECT_WR_32_63	0x0008
156
+#define AR5K_EEPROM_PROTECT_RD_64_127	0x0010	/* 0x40 - 0x7f */
157
+#define AR5K_EEPROM_PROTECT_WR_64_127	0x0020
158
+#define AR5K_EEPROM_PROTECT_RD_128_191	0x0040	/* 0x80 - 0xbf (regdom) */
159
+#define AR5K_EEPROM_PROTECT_WR_128_191	0x0080
160
+#define AR5K_EEPROM_PROTECT_RD_192_207	0x0100	/* 0xc0 - 0xcf */
161
+#define AR5K_EEPROM_PROTECT_WR_192_207	0x0200
162
+#define AR5K_EEPROM_PROTECT_RD_208_223	0x0400	/* 0xd0 - 0xdf */
163
+#define AR5K_EEPROM_PROTECT_WR_208_223	0x0800
164
+#define AR5K_EEPROM_PROTECT_RD_224_239	0x1000	/* 0xe0 - 0xef */
165
+#define AR5K_EEPROM_PROTECT_WR_224_239	0x2000
166
+#define AR5K_EEPROM_PROTECT_RD_240_255	0x4000	/* 0xf0 - 0xff */
167
+#define AR5K_EEPROM_PROTECT_WR_240_255	0x8000
168
+
169
+/* Some EEPROM defines */
170
+#define AR5K_EEPROM_EEP_SCALE		100
171
+#define AR5K_EEPROM_EEP_DELTA		10
172
+#define AR5K_EEPROM_N_MODES		3
173
+#define AR5K_EEPROM_N_5GHZ_CHAN		10
174
+#define AR5K_EEPROM_N_2GHZ_CHAN		3
175
+#define AR5K_EEPROM_N_2GHZ_CHAN_2413	4
176
+#define	AR5K_EEPROM_N_2GHZ_CHAN_MAX	4
177
+#define AR5K_EEPROM_MAX_CHAN		10
178
+#define AR5K_EEPROM_N_PWR_POINTS_5111	11
179
+#define AR5K_EEPROM_N_PCDAC		11
180
+#define AR5K_EEPROM_N_PHASE_CAL		5
181
+#define AR5K_EEPROM_N_TEST_FREQ		8
182
+#define AR5K_EEPROM_N_EDGES		8
183
+#define AR5K_EEPROM_N_INTERCEPTS	11
184
+#define AR5K_EEPROM_FREQ_M(_v)		AR5K_EEPROM_OFF(_v, 0x7f, 0xff)
185
+#define AR5K_EEPROM_PCDAC_M		0x3f
186
+#define AR5K_EEPROM_PCDAC_START		1
187
+#define AR5K_EEPROM_PCDAC_STOP		63
188
+#define AR5K_EEPROM_PCDAC_STEP		1
189
+#define AR5K_EEPROM_NON_EDGE_M		0x40
190
+#define AR5K_EEPROM_CHANNEL_POWER	8
191
+#define AR5K_EEPROM_N_OBDB		4
192
+#define AR5K_EEPROM_OBDB_DIS		0xffff
193
+#define AR5K_EEPROM_CHANNEL_DIS		0xff
194
+#define AR5K_EEPROM_SCALE_OC_DELTA(_x)	(((_x) * 2) / 10)
195
+#define AR5K_EEPROM_N_CTLS(_v)		AR5K_EEPROM_OFF(_v, 16, 32)
196
+#define AR5K_EEPROM_MAX_CTLS		32
197
+#define AR5K_EEPROM_N_PD_CURVES		4
198
+#define AR5K_EEPROM_N_XPD0_POINTS	4
199
+#define AR5K_EEPROM_N_XPD3_POINTS	3
200
+#define AR5K_EEPROM_N_PD_GAINS		4
201
+#define AR5K_EEPROM_N_PD_POINTS		5
202
+#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ	35
203
+#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ	55
204
+#define AR5K_EEPROM_POWER_M		0x3f
205
+#define AR5K_EEPROM_POWER_MIN		0
206
+#define AR5K_EEPROM_POWER_MAX		3150
207
+#define AR5K_EEPROM_POWER_STEP		50
208
+#define AR5K_EEPROM_POWER_TABLE_SIZE	64
209
+#define AR5K_EEPROM_N_POWER_LOC_11B	4
210
+#define AR5K_EEPROM_N_POWER_LOC_11G	6
211
+#define AR5K_EEPROM_I_GAIN		10
212
+#define AR5K_EEPROM_CCK_OFDM_DELTA	15
213
+#define AR5K_EEPROM_N_IQ_CAL		2
214
+
215
+#define AR5K_EEPROM_READ(_o, _v) do {			\
216
+	ret = ath5k_hw_eeprom_read(ah, (_o), &(_v));	\
217
+	if (ret)					\
218
+		return ret;				\
219
+} while (0)
220
+
221
+#define AR5K_EEPROM_READ_HDR(_o, _v)					\
222
+	AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v);	\
223
+
224
+enum ath5k_ant_setting {
225
+	AR5K_ANT_VARIABLE	= 0,	/* variable by programming */
226
+	AR5K_ANT_FIXED_A	= 1,	/* fixed to 11a frequencies */
227
+	AR5K_ANT_FIXED_B	= 2,	/* fixed to 11b frequencies */
228
+	AR5K_ANT_MAX		= 3,
229
+};
230
+
231
+enum ath5k_ctl_mode {
232
+	AR5K_CTL_11A = 0,
233
+	AR5K_CTL_11B = 1,
234
+	AR5K_CTL_11G = 2,
235
+	AR5K_CTL_TURBO = 3,
236
+	AR5K_CTL_TURBOG = 4,
237
+	AR5K_CTL_2GHT20 = 5,
238
+	AR5K_CTL_5GHT20 = 6,
239
+	AR5K_CTL_2GHT40 = 7,
240
+	AR5K_CTL_5GHT40 = 8,
241
+	AR5K_CTL_MODE_M = 15,
242
+};
243
+
244
+/* Default CTL ids for the 3 main reg domains.
245
+ * Atheros only uses these by default but vendors
246
+ * can have up to 32 different CTLs for different
247
+ * scenarios. Note that theese values are ORed with
248
+ * the mode id (above) so we can have up to 24 CTL
249
+ * datasets out of these 3 main regdomains. That leaves
250
+ * 8 ids that can be used by vendors and since 0x20 is
251
+ * missing from HAL sources i guess this is the set of
252
+ * custom CTLs vendors can use. */
253
+#define	AR5K_CTL_FCC	0x10
254
+#define	AR5K_CTL_CUSTOM	0x20
255
+#define	AR5K_CTL_ETSI	0x30
256
+#define	AR5K_CTL_MKK	0x40
257
+
258
+/* Indicates a CTL with only mode set and
259
+ * no reg domain mapping, such CTLs are used
260
+ * for world roaming domains or simply when
261
+ * a reg domain is not set */
262
+#define	AR5K_CTL_NO_REGDOMAIN	0xf0
263
+
264
+/* Indicates an empty (invalid) CTL */
265
+#define AR5K_CTL_NO_CTL		0xff
266
+
267
+/* Per channel calibration data, used for power table setup */
268
+struct ath5k_chan_pcal_info_rf5111 {
269
+	/* Power levels in half dbm units
270
+	 * for one power curve. */
271
+	u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
272
+	/* PCDAC table steps
273
+	 * for the above values */
274
+	u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
275
+	/* Starting PCDAC step */
276
+	u8 pcdac_min;
277
+	/* Final PCDAC step */
278
+	u8 pcdac_max;
279
+};
280
+
281
+struct ath5k_chan_pcal_info_rf5112 {
282
+	/* Power levels in quarter dBm units
283
+	 * for lower (0) and higher (3)
284
+	 * level curves in 0.25dB units */
285
+	s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
286
+	s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
287
+	/* PCDAC table steps
288
+	 * for the above values */
289
+	u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
290
+	u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
291
+};
292
+
293
+struct ath5k_chan_pcal_info_rf2413 {
294
+	/* Starting pwr/pddac values */
295
+	s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
296
+	u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
297
+	/* (pwr,pddac) points
298
+	 * power levels in 0.5dB units */
299
+	s8 pwr[AR5K_EEPROM_N_PD_GAINS]
300
+		[AR5K_EEPROM_N_PD_POINTS];
301
+	u8 pddac[AR5K_EEPROM_N_PD_GAINS]
302
+		[AR5K_EEPROM_N_PD_POINTS];
303
+};
304
+
305
+enum ath5k_powertable_type {
306
+	AR5K_PWRTABLE_PWR_TO_PCDAC = 0,
307
+	AR5K_PWRTABLE_LINEAR_PCDAC = 1,
308
+	AR5K_PWRTABLE_PWR_TO_PDADC = 2,
309
+};
310
+
311
+struct ath5k_pdgain_info {
312
+	u8 pd_points;
313
+	u8 *pd_step;
314
+	/* Power values are in
315
+	 * 0.25dB units */
316
+	s16 *pd_pwr;
317
+};
318
+
319
+struct ath5k_chan_pcal_info {
320
+	/* Frequency */
321
+	u16	freq;
322
+	/* Tx power boundaries */
323
+	s16	max_pwr;
324
+	s16	min_pwr;
325
+	union {
326
+		struct ath5k_chan_pcal_info_rf5111 rf5111_info;
327
+		struct ath5k_chan_pcal_info_rf5112 rf5112_info;
328
+		struct ath5k_chan_pcal_info_rf2413 rf2413_info;
329
+	};
330
+	/* Raw values used by phy code
331
+	 * Curves are stored in order from lower
332
+	 * gain to higher gain (max txpower -> min txpower) */
333
+	struct ath5k_pdgain_info *pd_curves;
334
+};
335
+
336
+/* Per rate calibration data for each mode,
337
+ * used for rate power table setup.
338
+ * Note: Values in 0.5dB units */
339
+struct ath5k_rate_pcal_info {
340
+	u16	freq; /* Frequency */
341
+	/* Power level for 6-24Mbit/s rates or
342
+	 * 1Mb rate */
343
+	u16	target_power_6to24;
344
+	/* Power level for 36Mbit rate or
345
+	 * 2Mb rate */
346
+	u16	target_power_36;
347
+	/* Power level for 48Mbit rate or
348
+	 * 5.5Mbit rate */
349
+	u16	target_power_48;
350
+	/* Power level for 54Mbit rate or
351
+	 * 11Mbit rate */
352
+	u16	target_power_54;
353
+};
354
+
355
+/* Power edges for conformance test limits */
356
+struct ath5k_edge_power {
357
+	u16 freq;
358
+	u16 edge; /* in half dBm */
359
+	int flag;
360
+};
361
+
362
+/* EEPROM calibration data */
363
+struct ath5k_eeprom_info {
364
+
365
+	/* Header information */
366
+	u16	ee_magic;
367
+	u16	ee_protect;
368
+	u16	ee_regdomain;
369
+	u16	ee_version;
370
+	u16	ee_header;
371
+	u16	ee_ant_gain;
372
+	u16	ee_misc0;
373
+	u16	ee_misc1;
374
+	u16	ee_misc2;
375
+	u16	ee_misc3;
376
+	u16	ee_misc4;
377
+	u16	ee_misc5;
378
+	u16	ee_misc6;
379
+	u16	ee_cck_ofdm_gain_delta;
380
+	u16	ee_cck_ofdm_power_delta;
381
+	u16	ee_scaled_cck_delta;
382
+
383
+	/* RF Calibration settings (reset, rfregs) */
384
+	u16	ee_i_cal[AR5K_EEPROM_N_MODES];
385
+	u16	ee_q_cal[AR5K_EEPROM_N_MODES];
386
+	u16	ee_fixed_bias[AR5K_EEPROM_N_MODES];
387
+	u16	ee_turbo_max_power[AR5K_EEPROM_N_MODES];
388
+	u16	ee_xr_power[AR5K_EEPROM_N_MODES];
389
+	u16	ee_switch_settling[AR5K_EEPROM_N_MODES];
390
+	u16	ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
391
+	u16	ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
392
+	u16	ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
393
+	u16	ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
394
+	u16	ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES];
395
+	u16	ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES];
396
+	u16	ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES];
397
+	u16	ee_thr_62[AR5K_EEPROM_N_MODES];
398
+	u16	ee_xlna_gain[AR5K_EEPROM_N_MODES];
399
+	u16	ee_xpd[AR5K_EEPROM_N_MODES];
400
+	u16	ee_x_gain[AR5K_EEPROM_N_MODES];
401
+	u16	ee_i_gain[AR5K_EEPROM_N_MODES];
402
+	u16	ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
403
+	u16	ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
404
+	u16	ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
405
+	u16	ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
406
+
407
+	/* Power calibration data */
408
+	u16	ee_false_detect[AR5K_EEPROM_N_MODES];
409
+
410
+	/* Number of pd gain curves per mode */
411
+	u8	ee_pd_gains[AR5K_EEPROM_N_MODES];
412
+	/* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */
413
+	u8	ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS];
414
+
415
+	u8	ee_n_piers[AR5K_EEPROM_N_MODES];
416
+	struct ath5k_chan_pcal_info	ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
417
+	struct ath5k_chan_pcal_info	ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
418
+	struct ath5k_chan_pcal_info	ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
419
+
420
+	/* Per rate target power levels */
421
+	u8	ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
422
+	struct ath5k_rate_pcal_info	ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
423
+	struct ath5k_rate_pcal_info	ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
424
+	struct ath5k_rate_pcal_info	ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX];
425
+
426
+	/* Conformance test limits (Unused) */
427
+	u8	ee_ctls;
428
+	u8	ee_ctl[AR5K_EEPROM_MAX_CTLS];
429
+	struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
430
+
431
+	/* Noise Floor Calibration settings */
432
+	s16	ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
433
+	s8	ee_adc_desired_size[AR5K_EEPROM_N_MODES];
434
+	s8	ee_pga_desired_size[AR5K_EEPROM_N_MODES];
435
+	s8	ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
436
+	s8	ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
437
+	s8	ee_pd_gain_overlap;
438
+
439
+	u32	ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
440
+};
441
+

+ 2589
- 0
src/drivers/net/ath5k/reg.h
File diff suppressed because it is too large
View File


+ 1181
- 0
src/drivers/net/ath5k/rfbuffer.h
File diff suppressed because it is too large
View File


+ 516
- 0
src/drivers/net/ath5k/rfgain.h View File

@@ -0,0 +1,516 @@
1
+/*
2
+ * RF Gain optimization
3
+ *
4
+ * Copyright (c) 2004-2009 Reyk Floeter <reyk@openbsd.org>
5
+ * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
6
+ *
7
+ * Permission to use, copy, modify, and distribute this software for any
8
+ * purpose with or without fee is hereby granted, provided that the above
9
+ * copyright notice and this permission notice appear in all copies.
10
+ *
11
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18
+ *
19
+ */
20
+
21
+/*
22
+ * Mode-specific RF Gain table (64bytes) for RF5111/5112
23
+ * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial
24
+ * RF Gain values are included in AR5K_AR5210_INI)
25
+ */
26
+struct ath5k_ini_rfgain {
27
+	u16	rfg_register;	/* RF Gain register address */
28
+	u32	rfg_value[2];	/* [freq (see below)] */
29
+};
30
+
31
+/* Initial RF Gain settings for RF5111 */
32
+static const struct ath5k_ini_rfgain rfgain_5111[] = {
33
+	/*			      5Ghz	2Ghz	*/
34
+	{ AR5K_RF_GAIN(0),	{ 0x000001a9, 0x00000000 } },
35
+	{ AR5K_RF_GAIN(1),	{ 0x000001e9, 0x00000040 } },
36
+	{ AR5K_RF_GAIN(2),	{ 0x00000029, 0x00000080 } },
37
+	{ AR5K_RF_GAIN(3),	{ 0x00000069, 0x00000150 } },
38
+	{ AR5K_RF_GAIN(4),	{ 0x00000199, 0x00000190 } },
39
+	{ AR5K_RF_GAIN(5),	{ 0x000001d9, 0x000001d0 } },
40
+	{ AR5K_RF_GAIN(6),	{ 0x00000019, 0x00000010 } },
41
+	{ AR5K_RF_GAIN(7),	{ 0x00000059, 0x00000044 } },
42
+	{ AR5K_RF_GAIN(8),	{ 0x00000099, 0x00000084 } },
43
+	{ AR5K_RF_GAIN(9),	{ 0x000001a5, 0x00000148 } },
44
+	{ AR5K_RF_GAIN(10),	{ 0x000001e5, 0x00000188 } },
45
+	{ AR5K_RF_GAIN(11),	{ 0x00000025, 0x000001c8 } },
46
+	{ AR5K_RF_GAIN(12),	{ 0x000001c8, 0x00000014 } },
47
+	{ AR5K_RF_GAIN(13),	{ 0x00000008, 0x00000042 } },
48
+	{ AR5K_RF_GAIN(14),	{ 0x00000048, 0x00000082 } },
49
+	{ AR5K_RF_GAIN(15),	{ 0x00000088, 0x00000178 } },
50
+	{ AR5K_RF_GAIN(16),	{ 0x00000198, 0x000001b8 } },
51
+	{ AR5K_RF_GAIN(17),	{ 0x000001d8, 0x000001f8 } },
52
+	{ AR5K_RF_GAIN(18),	{ 0x00000018, 0x00000012 } },
53
+	{ AR5K_RF_GAIN(19),	{ 0x00000058, 0x00000052 } },
54
+	{ AR5K_RF_GAIN(20),	{ 0x00000098, 0x00000092 } },
55
+	{ AR5K_RF_GAIN(21),	{ 0x000001a4, 0x0000017c } },
56
+	{ AR5K_RF_GAIN(22),	{ 0x000001e4, 0x000001bc } },
57
+	{ AR5K_RF_GAIN(23),	{ 0x00000024, 0x000001fc } },
58
+	{ AR5K_RF_GAIN(24),	{ 0x00000064, 0x0000000a } },
59
+	{ AR5K_RF_GAIN(25),	{ 0x000000a4, 0x0000004a } },
60
+	{ AR5K_RF_GAIN(26),	{ 0x000000e4, 0x0000008a } },
61
+	{ AR5K_RF_GAIN(27),	{ 0x0000010a, 0x0000015a } },
62
+	{ AR5K_RF_GAIN(28),	{ 0x0000014a, 0x0000019a } },
63
+	{ AR5K_RF_GAIN(29),	{ 0x0000018a, 0x000001da } },
64
+	{ AR5K_RF_GAIN(30),	{ 0x000001ca, 0x0000000e } },
65
+	{ AR5K_RF_GAIN(31),	{ 0x0000000a, 0x0000004e } },
66
+	{ AR5K_RF_GAIN(32),	{ 0x0000004a, 0x0000008e } },
67
+	{ AR5K_RF_GAIN(33),	{ 0x0000008a, 0x0000015e } },
68
+	{ AR5K_RF_GAIN(34),	{ 0x000001ba, 0x0000019e } },
69
+	{ AR5K_RF_GAIN(35),	{ 0x000001fa, 0x000001de } },
70
+	{ AR5K_RF_GAIN(36),	{ 0x0000003a, 0x00000009 } },
71
+	{ AR5K_RF_GAIN(37),	{ 0x0000007a, 0x00000049 } },
72
+	{ AR5K_RF_GAIN(38),	{ 0x00000186, 0x00000089 } },
73
+	{ AR5K_RF_GAIN(39),	{ 0x000001c6, 0x00000179 } },
74
+	{ AR5K_RF_GAIN(40),	{ 0x00000006, 0x000001b9 } },
75
+	{ AR5K_RF_GAIN(41),	{ 0x00000046, 0x000001f9 } },
76
+	{ AR5K_RF_GAIN(42),	{ 0x00000086, 0x00000039 } },
77
+	{ AR5K_RF_GAIN(43),	{ 0x000000c6, 0x00000079 } },
78
+	{ AR5K_RF_GAIN(44),	{ 0x000000c6, 0x000000b9 } },
79
+	{ AR5K_RF_GAIN(45),	{ 0x000000c6, 0x000001bd } },
80
+	{ AR5K_RF_GAIN(46),	{ 0x000000c6, 0x000001fd } },
81
+	{ AR5K_RF_GAIN(47),	{ 0x000000c6, 0x0000003d } },
82
+	{ AR5K_RF_GAIN(48),	{ 0x000000c6, 0x0000007d } },
83
+	{ AR5K_RF_GAIN(49),	{ 0x000000c6, 0x000000bd } },
84
+	{ AR5K_RF_GAIN(50),	{ 0x000000c6, 0x000000fd } },
85
+	{ AR5K_RF_GAIN(51),	{ 0x000000c6, 0x000000fd } },
86
+	{ AR5K_RF_GAIN(52),	{ 0x000000c6, 0x000000fd } },
87
+	{ AR5K_RF_GAIN(53),	{ 0x000000c6, 0x000000fd } },
88
+	{ AR5K_RF_GAIN(54),	{ 0x000000c6, 0x000000fd } },
89
+	{ AR5K_RF_GAIN(55),	{ 0x000000c6, 0x000000fd } },
90
+	{ AR5K_RF_GAIN(56),	{ 0x000000c6, 0x000000fd } },
91
+	{ AR5K_RF_GAIN(57),	{ 0x000000c6, 0x000000fd } },
92
+	{ AR5K_RF_GAIN(58),	{ 0x000000c6, 0x000000fd } },
93
+	{ AR5K_RF_GAIN(59),	{ 0x000000c6, 0x000000fd } },
94
+	{ AR5K_RF_GAIN(60),	{ 0x000000c6, 0x000000fd } },
95
+	{ AR5K_RF_GAIN(61),	{ 0x000000c6, 0x000000fd } },
96
+	{ AR5K_RF_GAIN(62),	{ 0x000000c6, 0x000000fd } },
97
+	{ AR5K_RF_GAIN(63),	{ 0x000000c6, 0x000000fd } },
98
+};
99
+
100
+/* Initial RF Gain settings for RF5112 */
101
+static const struct ath5k_ini_rfgain rfgain_5112[] = {
102
+	/*			      5Ghz	2Ghz	*/
103
+	{ AR5K_RF_GAIN(0),	{ 0x00000007, 0x00000007 } },
104
+	{ AR5K_RF_GAIN(1),	{ 0x00000047, 0x00000047 } },
105
+	{ AR5K_RF_GAIN(2),	{ 0x00000087, 0x00000087 } },
106
+	{ AR5K_RF_GAIN(3),	{ 0x000001a0, 0x000001a0 } },
107
+	{ AR5K_RF_GAIN(4),	{ 0x000001e0, 0x000001e0 } },
108
+	{ AR5K_RF_GAIN(5),	{ 0x00000020, 0x00000020 } },
109
+	{ AR5K_RF_GAIN(6),	{ 0x00000060, 0x00000060 } },
110
+	{ AR5K_RF_GAIN(7),	{ 0x000001a1, 0x000001a1 } },
111
+	{ AR5K_RF_GAIN(8),	{ 0x000001e1, 0x000001e1 } },
112
+	{ AR5K_RF_GAIN(9),	{ 0x00000021, 0x00000021 } },
113
+	{ AR5K_RF_GAIN(10),	{ 0x00000061, 0x00000061 } },
114
+	{ AR5K_RF_GAIN(11),	{ 0x00000162, 0x00000162 } },
115
+	{ AR5K_RF_GAIN(12),	{ 0x000001a2, 0x000001a2 } },
116
+	{ AR5K_RF_GAIN(13),	{ 0x000001e2, 0x000001e2 } },
117
+	{ AR5K_RF_GAIN(14),	{ 0x00000022, 0x00000022 } },
118
+	{ AR5K_RF_GAIN(15),	{ 0x00000062, 0x00000062 } },
119
+	{ AR5K_RF_GAIN(16),	{ 0x00000163, 0x00000163 } },
120
+	{ AR5K_RF_GAIN(17),	{ 0x000001a3, 0x000001a3 } },
121
+	{ AR5K_RF_GAIN(18),	{ 0x000001e3, 0x000001e3 } },
122
+	{ AR5K_RF_GAIN(19),	{ 0x00000023, 0x00000023 } },
123
+	{ AR5K_RF_GAIN(20),	{ 0x00000063, 0x00000063 } },
124
+	{ AR5K_RF_GAIN(21),	{ 0x00000184, 0x00000184 } },
125
+	{ AR5K_RF_GAIN(22),	{ 0x000001c4, 0x000001c4 } },
126
+	{ AR5K_RF_GAIN(23),	{ 0x00000004, 0x00000004 } },
127
+	{ AR5K_RF_GAIN(24),	{ 0x000001ea, 0x0000000b } },
128
+	{ AR5K_RF_GAIN(25),	{ 0x0000002a, 0x0000004b } },
129
+	{ AR5K_RF_GAIN(26),	{ 0x0000006a, 0x0000008b } },
130
+	{ AR5K_RF_GAIN(27),	{ 0x000000aa, 0x000001ac } },
131
+	{ AR5K_RF_GAIN(28),	{ 0x000001ab, 0x000001ec } },
132
+	{ AR5K_RF_GAIN(29),	{ 0x000001eb, 0x0000002c } },
133
+	{ AR5K_RF_GAIN(30),	{ 0x0000002b, 0x00000012 } },
134
+	{ AR5K_RF_GAIN(31),	{ 0x0000006b, 0x00000052 } },
135
+	{ AR5K_RF_GAIN(32),	{ 0x000000ab, 0x00000092 } },
136
+	{ AR5K_RF_GAIN(33),	{ 0x000001ac, 0x00000193 } },
137
+	{ AR5K_RF_GAIN(34),	{ 0x000001ec, 0x000001d3 } },
138
+	{ AR5K_RF_GAIN(35),	{ 0x0000002c, 0x00000013 } },
139
+	{ AR5K_RF_GAIN(36),	{ 0x0000003a, 0x00000053 } },
140
+	{ AR5K_RF_GAIN(37),	{ 0x0000007a, 0x00000093 } },
141
+	{ AR5K_RF_GAIN(38),	{ 0x000000ba, 0x00000194 } },
142
+	{ AR5K_RF_GAIN(39),	{ 0x000001bb, 0x000001d4 } },
143
+	{ AR5K_RF_GAIN(40),	{ 0x000001fb, 0x00000014 } },
144
+	{ AR5K_RF_GAIN(41),	{ 0x0000003b, 0x0000003a } },
145
+	{ AR5K_RF_GAIN(42),	{ 0x0000007b, 0x0000007a } },
146
+	{ AR5K_RF_GAIN(43),	{ 0x000000bb, 0x000000ba } },
147
+	{ AR5K_RF_GAIN(44),	{ 0x000001bc, 0x000001bb } },
148
+	{ AR5K_RF_GAIN(45),	{ 0x000001fc, 0x000001fb } },
149
+	{ AR5K_RF_GAIN(46),	{ 0x0000003c, 0x0000003b } },
150
+	{ AR5K_RF_GAIN(47),	{ 0x0000007c, 0x0000007b } },
151
+	{ AR5K_RF_GAIN(48),	{ 0x000000bc, 0x000000bb } },
152
+	{ AR5K_RF_GAIN(49),	{ 0x000000fc, 0x000001bc } },
153
+	{ AR5K_RF_GAIN(50),	{ 0x000000fc, 0x000001fc } },
154
+	{ AR5K_RF_GAIN(51),	{ 0x000000fc, 0x0000003c } },
155
+	{ AR5K_RF_GAIN(52),	{ 0x000000fc, 0x0000007c } },
156
+	{ AR5K_RF_GAIN(53),	{ 0x000000fc, 0x000000bc } },
157
+	{ AR5K_RF_GAIN(54),	{ 0x000000fc, 0x000000fc } },
158
+	{ AR5K_RF_GAIN(55),	{ 0x000000fc, 0x000000fc } },
159
+	{ AR5K_RF_GAIN(56),	{ 0x000000fc, 0x000000fc } },
160
+	{ AR5K_RF_GAIN(57),	{ 0x000000fc, 0x000000fc } },
161
+	{ AR5K_RF_GAIN(58),	{ 0x000000fc, 0x000000fc } },
162
+	{ AR5K_RF_GAIN(59),	{ 0x000000fc, 0x000000fc } },
163
+	{ AR5K_RF_GAIN(60),	{ 0x000000fc, 0x000000fc } },
164
+	{ AR5K_RF_GAIN(61),	{ 0x000000fc, 0x000000fc } },
165
+	{ AR5K_RF_GAIN(62),	{ 0x000000fc, 0x000000fc } },
166
+	{ AR5K_RF_GAIN(63),	{ 0x000000fc, 0x000000fc } },
167
+};
168
+
169
+/* Initial RF Gain settings for RF2413 */
170
+static const struct ath5k_ini_rfgain rfgain_2413[] = {
171
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
172
+	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
173
+	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
174
+	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x00000181 } },
175
+	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000001c1 } },
176
+	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x00000001 } },
177
+	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000041 } },
178
+	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000081 } },
179
+	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000168 } },
180
+	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x000001a8 } },
181
+	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x000001e8 } },
182
+	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x00000028 } },
183
+	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000068 } },
184
+	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000189 } },
185
+	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000001c9 } },
186
+	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x00000009 } },
187
+	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x00000049 } },
188
+	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000089 } },
189
+	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x00000190 } },
190
+	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x000001d0 } },
191
+	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x00000010 } },
192
+	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x00000050 } },
193
+	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000090 } },
194
+	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x00000191 } },
195
+	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000001d1 } },
196
+	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x00000011 } },
197
+	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x00000051 } },
198
+	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x00000091 } },
199
+	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x00000178 } },
200
+	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x000001b8 } },
201
+	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x000001f8 } },
202
+	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x00000038 } },
203
+	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x00000078 } },
204
+	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x00000199 } },
205
+	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x000001d9 } },
206
+	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x00000019 } },
207
+	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x00000059 } },
208
+	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x00000099 } },
209
+	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000d9 } },
210
+	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f9 } },
211
+	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f9 } },
212
+	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f9 } },
213
+	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f9 } },
214
+	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f9 } },
215
+	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f9 } },
216
+	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f9 } },
217
+	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f9 } },
218
+	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f9 } },
219
+	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f9 } },
220
+	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f9 } },
221
+	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f9 } },
222
+	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f9 } },
223
+	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f9 } },
224
+	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f9 } },
225
+	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f9 } },
226
+	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f9 } },
227
+	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f9 } },
228
+	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f9 } },
229
+	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f9 } },
230
+	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f9 } },
231
+	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f9 } },
232
+	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f9 } },
233
+	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f9 } },
234
+	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f9 } },
235
+};
236
+
237
+/* Initial RF Gain settings for AR2316 */
238
+static const struct ath5k_ini_rfgain rfgain_2316[] = {
239
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
240
+	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
241
+	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
242
+	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x000000c0 } },
243
+	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000000e0 } },
244
+	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x000000e0 } },
245
+	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000128 } },
246
+	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000128 } },
247
+	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000128 } },
248
+	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x00000168 } },
249
+	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x000001a8 } },
250
+	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x000001e8 } },
251
+	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000028 } },
252
+	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000068 } },
253
+	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000000a8 } },
254
+	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x000000e8 } },
255
+	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x000000e8 } },
256
+	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000130 } },
257
+	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x00000130 } },
258
+	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x00000170 } },
259
+	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x000001b0 } },
260
+	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x000001f0 } },
261
+	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000030 } },
262
+	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x00000070 } },
263
+	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000000b0 } },
264
+	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x000000f0 } },
265
+	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x000000f0 } },
266
+	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x000000f0 } },
267
+	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x000000f0 } },
268
+	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x000000f0 } },
269
+	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x000000f0 } },
270
+	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x000000f0 } },
271
+	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x000000f0 } },
272
+	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x000000f0 } },
273
+	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x000000f0 } },
274
+	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x000000f0 } },
275
+	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x000000f0 } },
276
+	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x000000f0 } },
277
+	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000f0 } },
278
+	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f0 } },
279
+	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f0 } },
280
+	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f0 } },
281
+	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f0 } },
282
+	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f0 } },
283
+	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f0 } },
284
+	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f0 } },
285
+	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f0 } },
286
+	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f0 } },
287
+	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f0 } },
288
+	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f0 } },
289
+	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f0 } },
290
+	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f0 } },
291
+	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f0 } },
292
+	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f0 } },
293
+	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f0 } },
294
+	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f0 } },
295
+	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f0 } },
296
+	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f0 } },
297
+	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f0 } },
298
+	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f0 } },
299
+	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f0 } },
300
+	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f0 } },
301
+	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f0 } },
302
+	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f0 } },
303
+};
304
+
305
+
306
+/* Initial RF Gain settings for RF5413 */
307
+static const struct ath5k_ini_rfgain rfgain_5413[] = {
308
+	/*			      5Ghz	2Ghz	*/
309
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
310
+	{ AR5K_RF_GAIN(1),	{ 0x00000040, 0x00000040 } },
311
+	{ AR5K_RF_GAIN(2),	{ 0x00000080, 0x00000080 } },
312
+	{ AR5K_RF_GAIN(3),	{ 0x000001a1, 0x00000161 } },
313
+	{ AR5K_RF_GAIN(4),	{ 0x000001e1, 0x000001a1 } },
314
+	{ AR5K_RF_GAIN(5),	{ 0x00000021, 0x000001e1 } },
315
+	{ AR5K_RF_GAIN(6),	{ 0x00000061, 0x00000021 } },
316
+	{ AR5K_RF_GAIN(7),	{ 0x00000188, 0x00000061 } },
317
+	{ AR5K_RF_GAIN(8),	{ 0x000001c8, 0x00000188 } },
318
+	{ AR5K_RF_GAIN(9),	{ 0x00000008, 0x000001c8 } },
319
+	{ AR5K_RF_GAIN(10),	{ 0x00000048, 0x00000008 } },
320
+	{ AR5K_RF_GAIN(11),	{ 0x00000088, 0x00000048 } },
321
+	{ AR5K_RF_GAIN(12),	{ 0x000001a9, 0x00000088 } },
322
+	{ AR5K_RF_GAIN(13),	{ 0x000001e9, 0x00000169 } },
323
+	{ AR5K_RF_GAIN(14),	{ 0x00000029, 0x000001a9 } },
324
+	{ AR5K_RF_GAIN(15),	{ 0x00000069, 0x000001e9 } },
325
+	{ AR5K_RF_GAIN(16),	{ 0x000001d0, 0x00000029 } },
326
+	{ AR5K_RF_GAIN(17),	{ 0x00000010, 0x00000069 } },
327
+	{ AR5K_RF_GAIN(18),	{ 0x00000050, 0x00000190 } },
328
+	{ AR5K_RF_GAIN(19),	{ 0x00000090, 0x000001d0 } },
329
+	{ AR5K_RF_GAIN(20),	{ 0x000001b1, 0x00000010 } },
330
+	{ AR5K_RF_GAIN(21),	{ 0x000001f1, 0x00000050 } },
331
+	{ AR5K_RF_GAIN(22),	{ 0x00000031, 0x00000090 } },
332
+	{ AR5K_RF_GAIN(23),	{ 0x00000071, 0x00000171 } },
333
+	{ AR5K_RF_GAIN(24),	{ 0x000001b8, 0x000001b1 } },
334
+	{ AR5K_RF_GAIN(25),	{ 0x000001f8, 0x000001f1 } },
335
+	{ AR5K_RF_GAIN(26),	{ 0x00000038, 0x00000031 } },
336
+	{ AR5K_RF_GAIN(27),	{ 0x00000078, 0x00000071 } },
337
+	{ AR5K_RF_GAIN(28),	{ 0x00000199, 0x00000198 } },
338
+	{ AR5K_RF_GAIN(29),	{ 0x000001d9, 0x000001d8 } },
339
+	{ AR5K_RF_GAIN(30),	{ 0x00000019, 0x00000018 } },
340
+	{ AR5K_RF_GAIN(31),	{ 0x00000059, 0x00000058 } },
341
+	{ AR5K_RF_GAIN(32),	{ 0x00000099, 0x00000098 } },
342
+	{ AR5K_RF_GAIN(33),	{ 0x000000d9, 0x00000179 } },
343
+	{ AR5K_RF_GAIN(34),	{ 0x000000f9, 0x000001b9 } },
344
+	{ AR5K_RF_GAIN(35),	{ 0x000000f9, 0x000001f9 } },
345
+	{ AR5K_RF_GAIN(36),	{ 0x000000f9, 0x00000039 } },
346
+	{ AR5K_RF_GAIN(37),	{ 0x000000f9, 0x00000079 } },
347
+	{ AR5K_RF_GAIN(38),	{ 0x000000f9, 0x000000b9 } },
348
+	{ AR5K_RF_GAIN(39),	{ 0x000000f9, 0x000000f9 } },
349
+	{ AR5K_RF_GAIN(40),	{ 0x000000f9, 0x000000f9 } },
350
+	{ AR5K_RF_GAIN(41),	{ 0x000000f9, 0x000000f9 } },
351
+	{ AR5K_RF_GAIN(42),	{ 0x000000f9, 0x000000f9 } },
352
+	{ AR5K_RF_GAIN(43),	{ 0x000000f9, 0x000000f9 } },
353
+	{ AR5K_RF_GAIN(44),	{ 0x000000f9, 0x000000f9 } },
354
+	{ AR5K_RF_GAIN(45),	{ 0x000000f9, 0x000000f9 } },
355
+	{ AR5K_RF_GAIN(46),	{ 0x000000f9, 0x000000f9 } },
356
+	{ AR5K_RF_GAIN(47),	{ 0x000000f9, 0x000000f9 } },
357
+	{ AR5K_RF_GAIN(48),	{ 0x000000f9, 0x000000f9 } },
358
+	{ AR5K_RF_GAIN(49),	{ 0x000000f9, 0x000000f9 } },
359
+	{ AR5K_RF_GAIN(50),	{ 0x000000f9, 0x000000f9 } },
360
+	{ AR5K_RF_GAIN(51),	{ 0x000000f9, 0x000000f9 } },
361
+	{ AR5K_RF_GAIN(52),	{ 0x000000f9, 0x000000f9 } },
362
+	{ AR5K_RF_GAIN(53),	{ 0x000000f9, 0x000000f9 } },
363
+	{ AR5K_RF_GAIN(54),	{ 0x000000f9, 0x000000f9 } },
364
+	{ AR5K_RF_GAIN(55),	{ 0x000000f9, 0x000000f9 } },
365
+	{ AR5K_RF_GAIN(56),	{ 0x000000f9, 0x000000f9 } },
366
+	{ AR5K_RF_GAIN(57),	{ 0x000000f9, 0x000000f9 } },
367
+	{ AR5K_RF_GAIN(58),	{ 0x000000f9, 0x000000f9 } },
368
+	{ AR5K_RF_GAIN(59),	{ 0x000000f9, 0x000000f9 } },
369
+	{ AR5K_RF_GAIN(60),	{ 0x000000f9, 0x000000f9 } },
370
+	{ AR5K_RF_GAIN(61),	{ 0x000000f9, 0x000000f9 } },
371
+	{ AR5K_RF_GAIN(62),	{ 0x000000f9, 0x000000f9 } },
372
+	{ AR5K_RF_GAIN(63),	{ 0x000000f9, 0x000000f9 } },
373
+};
374
+
375
+
376
+/* Initial RF Gain settings for RF2425 */
377
+static const struct ath5k_ini_rfgain rfgain_2425[] = {
378
+	{ AR5K_RF_GAIN(0),	{ 0x00000000, 0x00000000 } },
379
+	{ AR5K_RF_GAIN(1),	{ 0x00000000, 0x00000040 } },
380
+	{ AR5K_RF_GAIN(2),	{ 0x00000000, 0x00000080 } },
381
+	{ AR5K_RF_GAIN(3),	{ 0x00000000, 0x00000181 } },
382
+	{ AR5K_RF_GAIN(4),	{ 0x00000000, 0x000001c1 } },
383
+	{ AR5K_RF_GAIN(5),	{ 0x00000000, 0x00000001 } },
384
+	{ AR5K_RF_GAIN(6),	{ 0x00000000, 0x00000041 } },
385
+	{ AR5K_RF_GAIN(7),	{ 0x00000000, 0x00000081 } },
386
+	{ AR5K_RF_GAIN(8),	{ 0x00000000, 0x00000188 } },
387
+	{ AR5K_RF_GAIN(9),	{ 0x00000000, 0x000001c8 } },
388
+	{ AR5K_RF_GAIN(10),	{ 0x00000000, 0x00000008 } },
389
+	{ AR5K_RF_GAIN(11),	{ 0x00000000, 0x00000048 } },
390
+	{ AR5K_RF_GAIN(12),	{ 0x00000000, 0x00000088 } },
391
+	{ AR5K_RF_GAIN(13),	{ 0x00000000, 0x00000189 } },
392
+	{ AR5K_RF_GAIN(14),	{ 0x00000000, 0x000001c9 } },
393
+	{ AR5K_RF_GAIN(15),	{ 0x00000000, 0x00000009 } },
394
+	{ AR5K_RF_GAIN(16),	{ 0x00000000, 0x00000049 } },
395
+	{ AR5K_RF_GAIN(17),	{ 0x00000000, 0x00000089 } },
396
+	{ AR5K_RF_GAIN(18),	{ 0x00000000, 0x000001b0 } },
397
+	{ AR5K_RF_GAIN(19),	{ 0x00000000, 0x000001f0 } },
398
+	{ AR5K_RF_GAIN(20),	{ 0x00000000, 0x00000030 } },
399
+	{ AR5K_RF_GAIN(21),	{ 0x00000000, 0x00000070 } },
400
+	{ AR5K_RF_GAIN(22),	{ 0x00000000, 0x00000171 } },
401
+	{ AR5K_RF_GAIN(23),	{ 0x00000000, 0x000001b1 } },
402
+	{ AR5K_RF_GAIN(24),	{ 0x00000000, 0x000001f1 } },
403
+	{ AR5K_RF_GAIN(25),	{ 0x00000000, 0x00000031 } },
404
+	{ AR5K_RF_GAIN(26),	{ 0x00000000, 0x00000071 } },
405
+	{ AR5K_RF_GAIN(27),	{ 0x00000000, 0x000001b8 } },
406
+	{ AR5K_RF_GAIN(28),	{ 0x00000000, 0x000001f8 } },
407
+	{ AR5K_RF_GAIN(29),	{ 0x00000000, 0x00000038 } },
408
+	{ AR5K_RF_GAIN(30),	{ 0x00000000, 0x00000078 } },
409
+	{ AR5K_RF_GAIN(31),	{ 0x00000000, 0x000000b8 } },
410
+	{ AR5K_RF_GAIN(32),	{ 0x00000000, 0x000001b9 } },
411
+	{ AR5K_RF_GAIN(33),	{ 0x00000000, 0x000001f9 } },
412
+	{ AR5K_RF_GAIN(34),	{ 0x00000000, 0x00000039 } },
413
+	{ AR5K_RF_GAIN(35),	{ 0x00000000, 0x00000079 } },
414
+	{ AR5K_RF_GAIN(36),	{ 0x00000000, 0x000000b9 } },
415
+	{ AR5K_RF_GAIN(37),	{ 0x00000000, 0x000000f9 } },
416
+	{ AR5K_RF_GAIN(38),	{ 0x00000000, 0x000000f9 } },
417
+	{ AR5K_RF_GAIN(39),	{ 0x00000000, 0x000000f9 } },
418
+	{ AR5K_RF_GAIN(40),	{ 0x00000000, 0x000000f9 } },
419
+	{ AR5K_RF_GAIN(41),	{ 0x00000000, 0x000000f9 } },
420
+	{ AR5K_RF_GAIN(42),	{ 0x00000000, 0x000000f9 } },
421
+	{ AR5K_RF_GAIN(43),	{ 0x00000000, 0x000000f9 } },
422
+	{ AR5K_RF_GAIN(44),	{ 0x00000000, 0x000000f9 } },
423
+	{ AR5K_RF_GAIN(45),	{ 0x00000000, 0x000000f9 } },
424
+	{ AR5K_RF_GAIN(46),	{ 0x00000000, 0x000000f9 } },
425
+	{ AR5K_RF_GAIN(47),	{ 0x00000000, 0x000000f9 } },
426
+	{ AR5K_RF_GAIN(48),	{ 0x00000000, 0x000000f9 } },
427
+	{ AR5K_RF_GAIN(49),	{ 0x00000000, 0x000000f9 } },
428
+	{ AR5K_RF_GAIN(50),	{ 0x00000000, 0x000000f9 } },
429
+	{ AR5K_RF_GAIN(51),	{ 0x00000000, 0x000000f9 } },
430
+	{ AR5K_RF_GAIN(52),	{ 0x00000000, 0x000000f9 } },
431
+	{ AR5K_RF_GAIN(53),	{ 0x00000000, 0x000000f9 } },
432
+	{ AR5K_RF_GAIN(54),	{ 0x00000000, 0x000000f9 } },
433
+	{ AR5K_RF_GAIN(55),	{ 0x00000000, 0x000000f9 } },
434
+	{ AR5K_RF_GAIN(56),	{ 0x00000000, 0x000000f9 } },
435
+	{ AR5K_RF_GAIN(57),	{ 0x00000000, 0x000000f9 } },
436
+	{ AR5K_RF_GAIN(58),	{ 0x00000000, 0x000000f9 } },
437
+	{ AR5K_RF_GAIN(59),	{ 0x00000000, 0x000000f9 } },
438
+	{ AR5K_RF_GAIN(60),	{ 0x00000000, 0x000000f9 } },
439
+	{ AR5K_RF_GAIN(61),	{ 0x00000000, 0x000000f9 } },
440
+	{ AR5K_RF_GAIN(62),	{ 0x00000000, 0x000000f9 } },
441
+	{ AR5K_RF_GAIN(63),	{ 0x00000000, 0x000000f9 } },
442
+};
443
+
444
+#define AR5K_GAIN_CRN_FIX_BITS_5111		4
445
+#define AR5K_GAIN_CRN_FIX_BITS_5112		7
446
+#define AR5K_GAIN_CRN_MAX_FIX_BITS		AR5K_GAIN_CRN_FIX_BITS_5112
447
+#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN		15
448
+#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN		20
449
+#define AR5K_GAIN_CCK_PROBE_CORR		5
450
+#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA		15
451
+#define AR5K_GAIN_STEP_COUNT			10
452
+
453
+/* Check if our current measurement is inside our
454
+ * current variable attenuation window */
455
+#define AR5K_GAIN_CHECK_ADJUST(_g) 		\
456
+	((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high)
457
+
458
+struct ath5k_gain_opt_step {
459
+	s8				gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS];
460
+	s8				gos_gain;
461
+};
462
+
463
+struct ath5k_gain_opt {
464
+	u8				go_default;
465
+	u8				go_steps_count;
466
+	const struct ath5k_gain_opt_step	go_step[AR5K_GAIN_STEP_COUNT];
467
+};
468
+
469
+/*
470
+ * Parameters on gos_param:
471
+ * 1) Tx clip PHY register
472
+ * 2) PWD 90 RF register
473
+ * 3) PWD 84 RF register
474
+ * 4) RFGainSel RF register
475
+ */
476
+static const struct ath5k_gain_opt rfgain_opt_5111 = {
477
+	4,
478
+	9,
479
+	{
480
+		{ { 4, 1, 1, 1 }, 6 },
481
+		{ { 4, 0, 1, 1 }, 4 },
482
+		{ { 3, 1, 1, 1 }, 3 },
483
+		{ { 4, 0, 0, 1 }, 1 },
484
+		{ { 4, 1, 1, 0 }, 0 },
485
+		{ { 4, 0, 1, 0 }, -2 },
486
+		{ { 3, 1, 1, 0 }, -3 },
487
+		{ { 4, 0, 0, 0 }, -4 },
488
+		{ { 2, 1, 1, 0 }, -6 }
489
+	}
490
+};
491
+
492
+/*
493
+ * Parameters on gos_param:
494
+ * 1) Mixgain ovr RF register
495
+ * 2) PWD 138 RF register
496
+ * 3) PWD 137 RF register
497
+ * 4) PWD 136 RF register
498
+ * 5) PWD 132 RF register
499
+ * 6) PWD 131 RF register
500
+ * 7) PWD 130 RF register
501
+ */
502
+static const struct ath5k_gain_opt rfgain_opt_5112 = {
503
+	1,
504
+	8,
505
+	{
506
+		{ { 3, 0, 0, 0, 0, 0, 0 }, 6 },
507
+		{ { 2, 0, 0, 0, 0, 0, 0 }, 0 },
508
+		{ { 1, 0, 0, 0, 0, 0, 0 }, -3 },
509
+		{ { 0, 0, 0, 0, 0, 0, 0 }, -6 },
510
+		{ { 0, 1, 1, 0, 0, 0, 0 }, -8 },
511
+		{ { 0, 1, 1, 0, 1, 1, 0 }, -10 },
512
+		{ { 0, 1, 0, 1, 1, 1, 0 }, -13 },
513
+		{ { 0, 1, 0, 1, 1, 0, 1 }, -16 },
514
+	}
515
+};
516
+

+ 1
- 0
src/include/gpxe/errfile.h View File

@@ -112,6 +112,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
112 112
 #define ERRFILE_b44		     ( ERRFILE_DRIVER | 0x004d0000 )
113 113
 #define ERRFILE_rtl818x		     ( ERRFILE_DRIVER | 0x004e0000 )
114 114
 #define ERRFILE_sky2                 ( ERRFILE_DRIVER | 0x004f0000 )
115
+#define ERRFILE_ath5k		     ( ERRFILE_DRIVER | 0x00500000 )
115 116
 
116 117
 #define ERRFILE_scsi		     ( ERRFILE_DRIVER | 0x00700000 )
117 118
 #define ERRFILE_arbel		     ( ERRFILE_DRIVER | 0x00710000 )

Loading…
Cancel
Save