Commit | Line | Data |
---|---|---|
5a6a256e TW |
1 | /****************************************************************************** |
2 | * | |
3 | * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
17 | * | |
18 | * The full GNU General Public License is included in this distribution in the | |
19 | * file called LICENSE. | |
20 | * | |
21 | * Contact Information: | |
22 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | |
23 | * | |
24 | *****************************************************************************/ | |
25 | ||
26 | #include <linux/kernel.h> | |
27 | #include <linux/module.h> | |
28 | #include <linux/version.h> | |
29 | #include <linux/init.h> | |
30 | #include <linux/pci.h> | |
31 | #include <linux/dma-mapping.h> | |
32 | #include <linux/delay.h> | |
33 | #include <linux/skbuff.h> | |
34 | #include <linux/netdevice.h> | |
35 | #include <linux/wireless.h> | |
36 | #include <net/mac80211.h> | |
37 | #include <linux/etherdevice.h> | |
38 | #include <asm/unaligned.h> | |
39 | ||
40 | #include "iwl-eeprom.h" | |
3e0d4cb1 | 41 | #include "iwl-dev.h" |
5a6a256e TW |
42 | #include "iwl-core.h" |
43 | #include "iwl-io.h" | |
44 | #include "iwl-helpers.h" | |
45 | #include "iwl-5000-hw.h" | |
46 | ||
47 | #define IWL5000_UCODE_API "-1" | |
48 | ||
30d59260 TW |
49 | static int iwl5000_apm_init(struct iwl_priv *priv) |
50 | { | |
51 | int ret = 0; | |
52 | ||
53 | iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, | |
54 | CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); | |
55 | ||
56 | iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); | |
57 | ||
58 | /* set "initialization complete" bit to move adapter | |
59 | * D0U* --> D0A* state */ | |
60 | iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); | |
61 | ||
62 | /* wait for clock stabilization */ | |
63 | ret = iwl_poll_bit(priv, CSR_GP_CNTRL, | |
64 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, | |
65 | CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); | |
66 | if (ret < 0) { | |
67 | IWL_DEBUG_INFO("Failed to init the card\n"); | |
68 | return ret; | |
69 | } | |
70 | ||
71 | ret = iwl_grab_nic_access(priv); | |
72 | if (ret) | |
73 | return ret; | |
74 | ||
75 | /* enable DMA */ | |
76 | iwl_write_prph(priv, APMG_CLK_EN_REG, | |
77 | APMG_CLK_VAL_DMA_CLK_RQT); | |
78 | ||
79 | udelay(20); | |
80 | ||
81 | iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, | |
82 | APMG_PCIDEV_STT_VAL_L1_ACT_DIS); | |
83 | ||
84 | iwl_release_nic_access(priv); | |
85 | ||
86 | return ret; | |
87 | } | |
88 | ||
5a835353 | 89 | static void iwl5000_nic_config(struct iwl_priv *priv) |
e86fe9f6 TW |
90 | { |
91 | unsigned long flags; | |
92 | u16 radio_cfg; | |
93 | u8 val_link; | |
94 | ||
95 | spin_lock_irqsave(&priv->lock, flags); | |
96 | ||
97 | pci_read_config_byte(priv->pci_dev, PCI_LINK_CTRL, &val_link); | |
98 | ||
99 | /* disable L1 entry -- workaround for pre-B1 */ | |
100 | pci_write_config_byte(priv->pci_dev, PCI_LINK_CTRL, val_link & ~0x02); | |
101 | ||
102 | radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); | |
103 | ||
104 | /* write radio config values to register */ | |
105 | if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_5000_RF_CFG_TYPE_MAX) | |
106 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | |
107 | EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | | |
108 | EEPROM_RF_CFG_STEP_MSK(radio_cfg) | | |
109 | EEPROM_RF_CFG_DASH_MSK(radio_cfg)); | |
110 | ||
111 | /* set CSR_HW_CONFIG_REG for uCode use */ | |
112 | iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, | |
113 | CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | | |
114 | CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); | |
115 | ||
116 | spin_unlock_irqrestore(&priv->lock, flags); | |
117 | } | |
118 | ||
119 | ||
120 | ||
25ae3986 TW |
121 | /* |
122 | * EEPROM | |
123 | */ | |
124 | static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) | |
125 | { | |
126 | u16 offset = 0; | |
127 | ||
128 | if ((address & INDIRECT_ADDRESS) == 0) | |
129 | return address; | |
130 | ||
131 | switch (address & INDIRECT_TYPE_MSK) { | |
132 | case INDIRECT_HOST: | |
133 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); | |
134 | break; | |
135 | case INDIRECT_GENERAL: | |
136 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); | |
137 | break; | |
138 | case INDIRECT_REGULATORY: | |
139 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); | |
140 | break; | |
141 | case INDIRECT_CALIBRATION: | |
142 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); | |
143 | break; | |
144 | case INDIRECT_PROCESS_ADJST: | |
145 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); | |
146 | break; | |
147 | case INDIRECT_OTHERS: | |
148 | offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); | |
149 | break; | |
150 | default: | |
151 | IWL_ERROR("illegal indirect type: 0x%X\n", | |
152 | address & INDIRECT_TYPE_MSK); | |
153 | break; | |
154 | } | |
155 | ||
156 | /* translate the offset from words to byte */ | |
157 | return (address & ADDRESS_MSK) + (offset << 1); | |
158 | } | |
159 | ||
f1f69415 TW |
160 | static int iwl5000_eeprom_check_version(struct iwl_priv *priv) |
161 | { | |
162 | u16 eeprom_ver; | |
163 | struct iwl_eeprom_calib_hdr { | |
164 | u8 version; | |
165 | u8 pa_type; | |
166 | u16 voltage; | |
167 | } *hdr; | |
168 | ||
169 | eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); | |
170 | ||
171 | hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, | |
172 | EEPROM_5000_CALIB_ALL); | |
173 | ||
174 | if (eeprom_ver < EEPROM_5000_EEPROM_VERSION || | |
175 | hdr->version < EEPROM_5000_TX_POWER_VERSION) | |
176 | goto err; | |
177 | ||
178 | return 0; | |
179 | err: | |
180 | IWL_ERROR("Unsuported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", | |
181 | eeprom_ver, EEPROM_5000_EEPROM_VERSION, | |
182 | hdr->version, EEPROM_5000_TX_POWER_VERSION); | |
183 | return -EINVAL; | |
184 | ||
185 | } | |
186 | ||
33fd5033 EG |
187 | #ifdef CONFIG_IWL5000_RUN_TIME_CALIB |
188 | ||
189 | static void iwl5000_gain_computation(struct iwl_priv *priv, | |
190 | u32 average_noise[NUM_RX_CHAINS], | |
191 | u16 min_average_noise_antenna_i, | |
192 | u32 min_average_noise) | |
193 | { | |
194 | int i; | |
195 | s32 delta_g; | |
196 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | |
197 | ||
198 | /* Find Gain Code for the antennas B and C */ | |
199 | for (i = 1; i < NUM_RX_CHAINS; i++) { | |
200 | if ((data->disconn_array[i])) { | |
201 | data->delta_gain_code[i] = 0; | |
202 | continue; | |
203 | } | |
204 | delta_g = (1000 * ((s32)average_noise[0] - | |
205 | (s32)average_noise[i])) / 1500; | |
206 | /* bound gain by 2 bits value max, 3rd bit is sign */ | |
207 | data->delta_gain_code[i] = | |
208 | min(abs(delta_g), CHAIN_NOISE_MAX_DELTA_GAIN_CODE); | |
209 | ||
210 | if (delta_g < 0) | |
211 | /* set negative sign */ | |
212 | data->delta_gain_code[i] |= (1 << 2); | |
213 | } | |
214 | ||
215 | IWL_DEBUG_CALIB("Delta gains: ANT_B = %d ANT_C = %d\n", | |
216 | data->delta_gain_code[1], data->delta_gain_code[2]); | |
217 | ||
218 | if (!data->radio_write) { | |
219 | struct iwl5000_calibration_chain_noise_gain_cmd cmd; | |
220 | memset(&cmd, 0, sizeof(cmd)); | |
221 | ||
222 | cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; | |
223 | cmd.delta_gain_1 = data->delta_gain_code[1]; | |
224 | cmd.delta_gain_2 = data->delta_gain_code[2]; | |
225 | iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, | |
226 | sizeof(cmd), &cmd, NULL); | |
227 | ||
228 | data->radio_write = 1; | |
229 | data->state = IWL_CHAIN_NOISE_CALIBRATED; | |
230 | } | |
231 | ||
232 | data->chain_noise_a = 0; | |
233 | data->chain_noise_b = 0; | |
234 | data->chain_noise_c = 0; | |
235 | data->chain_signal_a = 0; | |
236 | data->chain_signal_b = 0; | |
237 | data->chain_signal_c = 0; | |
238 | data->beacon_count = 0; | |
239 | } | |
240 | ||
f1f69415 | 241 | |
33fd5033 EG |
242 | static void iwl5000_chain_noise_reset(struct iwl_priv *priv) |
243 | { | |
244 | struct iwl_chain_noise_data *data = &priv->chain_noise_data; | |
245 | ||
246 | if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { | |
247 | struct iwl5000_calibration_chain_noise_reset_cmd cmd; | |
248 | ||
249 | memset(&cmd, 0, sizeof(cmd)); | |
250 | cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; | |
251 | if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, | |
252 | sizeof(cmd), &cmd)) | |
253 | IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n"); | |
254 | data->state = IWL_CHAIN_NOISE_ACCUMULATE; | |
255 | IWL_DEBUG_CALIB("Run chain_noise_calibrate\n"); | |
256 | } | |
257 | } | |
258 | ||
259 | static struct iwl_sensitivity_ranges iwl5000_sensitivity = { | |
260 | .min_nrg_cck = 95, | |
261 | .max_nrg_cck = 0, | |
262 | .auto_corr_min_ofdm = 90, | |
263 | .auto_corr_min_ofdm_mrc = 170, | |
264 | .auto_corr_min_ofdm_x1 = 120, | |
265 | .auto_corr_min_ofdm_mrc_x1 = 240, | |
266 | ||
267 | .auto_corr_max_ofdm = 120, | |
268 | .auto_corr_max_ofdm_mrc = 210, | |
269 | .auto_corr_max_ofdm_x1 = 155, | |
270 | .auto_corr_max_ofdm_mrc_x1 = 290, | |
271 | ||
272 | .auto_corr_min_cck = 125, | |
273 | .auto_corr_max_cck = 200, | |
274 | .auto_corr_min_cck_mrc = 170, | |
275 | .auto_corr_max_cck_mrc = 400, | |
276 | .nrg_th_cck = 95, | |
277 | .nrg_th_ofdm = 95, | |
278 | }; | |
279 | ||
280 | #endif /* CONFIG_IWL5000_RUN_TIME_CALIB */ | |
281 | ||
25ae3986 TW |
282 | static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, |
283 | size_t offset) | |
284 | { | |
285 | u32 address = eeprom_indirect_address(priv, offset); | |
286 | BUG_ON(address >= priv->cfg->eeprom_size); | |
287 | return &priv->eeprom[address]; | |
288 | } | |
289 | ||
fdd3e8a4 TW |
290 | static int iwl5000_hw_set_hw_params(struct iwl_priv *priv) |
291 | { | |
292 | if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || | |
293 | (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { | |
294 | IWL_ERROR("invalid queues_num, should be between %d and %d\n", | |
295 | IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); | |
296 | return -EINVAL; | |
297 | } | |
25ae3986 | 298 | |
fdd3e8a4 TW |
299 | priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; |
300 | priv->hw_params.sw_crypto = priv->cfg->mod_params->sw_crypto; | |
fdd3e8a4 TW |
301 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; |
302 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | |
303 | if (priv->cfg->mod_params->amsdu_size_8K) | |
304 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; | |
305 | else | |
306 | priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; | |
307 | priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; | |
308 | priv->hw_params.max_stations = IWL5000_STATION_COUNT; | |
309 | priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; | |
310 | priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; | |
311 | priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; | |
312 | priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; | |
313 | priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | | |
314 | BIT(IEEE80211_BAND_5GHZ); | |
33fd5033 EG |
315 | #ifdef CONFIG_IWL5000_RUN_TIME_CALIB |
316 | priv->hw_params.sens = &iwl5000_sensitivity; | |
317 | #endif | |
fdd3e8a4 TW |
318 | |
319 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | |
320 | case CSR_HW_REV_TYPE_5100: | |
321 | case CSR_HW_REV_TYPE_5150: | |
322 | priv->hw_params.tx_chains_num = 1; | |
323 | priv->hw_params.rx_chains_num = 2; | |
324 | /* FIXME: move to ANT_A, ANT_B, ANT_C enum */ | |
1179f18d TW |
325 | priv->hw_params.valid_tx_ant = ANT_A; |
326 | priv->hw_params.valid_rx_ant = ANT_AB; | |
fdd3e8a4 TW |
327 | break; |
328 | case CSR_HW_REV_TYPE_5300: | |
329 | case CSR_HW_REV_TYPE_5350: | |
330 | priv->hw_params.tx_chains_num = 3; | |
331 | priv->hw_params.rx_chains_num = 3; | |
1179f18d TW |
332 | priv->hw_params.valid_tx_ant = ANT_ABC; |
333 | priv->hw_params.valid_rx_ant = ANT_ABC; | |
fdd3e8a4 TW |
334 | break; |
335 | } | |
c031bf80 EG |
336 | |
337 | switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { | |
338 | case CSR_HW_REV_TYPE_5100: | |
339 | case CSR_HW_REV_TYPE_5300: | |
340 | /* 5X00 wants in Celsius */ | |
341 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | |
342 | break; | |
343 | case CSR_HW_REV_TYPE_5150: | |
344 | case CSR_HW_REV_TYPE_5350: | |
345 | /* 5X50 wants in Kelvin */ | |
346 | priv->hw_params.ct_kill_threshold = | |
347 | CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); | |
348 | break; | |
349 | } | |
350 | ||
fdd3e8a4 TW |
351 | return 0; |
352 | } | |
d4100dd9 RR |
353 | |
354 | static int iwl5000_alloc_shared_mem(struct iwl_priv *priv) | |
355 | { | |
356 | priv->shared_virt = pci_alloc_consistent(priv->pci_dev, | |
357 | sizeof(struct iwl5000_shared), | |
358 | &priv->shared_phys); | |
359 | if (!priv->shared_virt) | |
360 | return -ENOMEM; | |
361 | ||
362 | memset(priv->shared_virt, 0, sizeof(struct iwl5000_shared)); | |
363 | ||
d67f5489 RR |
364 | priv->rb_closed_offset = offsetof(struct iwl5000_shared, rb_closed); |
365 | ||
d4100dd9 RR |
366 | return 0; |
367 | } | |
368 | ||
369 | static void iwl5000_free_shared_mem(struct iwl_priv *priv) | |
370 | { | |
371 | if (priv->shared_virt) | |
372 | pci_free_consistent(priv->pci_dev, | |
373 | sizeof(struct iwl5000_shared), | |
374 | priv->shared_virt, | |
375 | priv->shared_phys); | |
376 | } | |
377 | ||
d67f5489 RR |
378 | static int iwl5000_shared_mem_rx_idx(struct iwl_priv *priv) |
379 | { | |
380 | struct iwl5000_shared *s = priv->shared_virt; | |
381 | return le32_to_cpu(s->rb_closed) & 0xFFF; | |
382 | } | |
383 | ||
7839fc03 EG |
384 | /** |
385 | * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | |
386 | */ | |
387 | static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |
16466903 | 388 | struct iwl_tx_queue *txq, |
7839fc03 EG |
389 | u16 byte_cnt) |
390 | { | |
391 | struct iwl5000_shared *shared_data = priv->shared_virt; | |
392 | int txq_id = txq->q.id; | |
393 | u8 sec_ctl = 0; | |
394 | u8 sta = 0; | |
395 | int len; | |
396 | ||
397 | len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; | |
398 | ||
399 | if (txq_id != IWL_CMD_QUEUE_NUM) { | |
400 | sta = txq->cmd[txq->q.write_ptr].cmd.tx.sta_id; | |
401 | sec_ctl = txq->cmd[txq->q.write_ptr].cmd.tx.sec_ctl; | |
402 | ||
403 | switch (sec_ctl & TX_CMD_SEC_MSK) { | |
404 | case TX_CMD_SEC_CCM: | |
405 | len += CCMP_MIC_LEN; | |
406 | break; | |
407 | case TX_CMD_SEC_TKIP: | |
408 | len += TKIP_ICV_LEN; | |
409 | break; | |
410 | case TX_CMD_SEC_WEP: | |
411 | len += WEP_IV_LEN + WEP_ICV_LEN; | |
412 | break; | |
413 | } | |
414 | } | |
415 | ||
416 | IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. | |
417 | tfd_offset[txq->q.write_ptr], byte_cnt, len); | |
418 | ||
419 | IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. | |
420 | tfd_offset[txq->q.write_ptr], sta_id, sta); | |
421 | ||
422 | if (txq->q.write_ptr < IWL50_MAX_WIN_SIZE) { | |
423 | IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. | |
424 | tfd_offset[IWL50_QUEUE_SIZE + txq->q.write_ptr], | |
425 | byte_cnt, len); | |
426 | IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id]. | |
427 | tfd_offset[IWL50_QUEUE_SIZE + txq->q.write_ptr], | |
428 | sta_id, sta); | |
429 | } | |
430 | } | |
431 | ||
2469bf2e TW |
432 | static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) |
433 | { | |
434 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | |
435 | memcpy(data, cmd, size); | |
436 | return size; | |
437 | } | |
438 | ||
439 | ||
5a676bbe RR |
440 | static int iwl5000_disable_tx_fifo(struct iwl_priv *priv) |
441 | { | |
442 | unsigned long flags; | |
443 | int ret; | |
444 | ||
445 | spin_lock_irqsave(&priv->lock, flags); | |
446 | ||
447 | ret = iwl_grab_nic_access(priv); | |
448 | if (unlikely(ret)) { | |
449 | IWL_ERROR("Tx fifo reset failed"); | |
450 | spin_unlock_irqrestore(&priv->lock, flags); | |
451 | return ret; | |
452 | } | |
453 | ||
454 | iwl_write_prph(priv, IWL50_SCD_TXFACT, 0); | |
455 | iwl_release_nic_access(priv); | |
456 | spin_unlock_irqrestore(&priv->lock, flags); | |
457 | ||
458 | return 0; | |
459 | } | |
460 | ||
c1adf9fb GG |
461 | /* Currently 5000 is the supperset of everything */ |
462 | static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) | |
463 | { | |
464 | return len; | |
465 | } | |
466 | ||
b600e4e1 RR |
467 | static void iwl5000_rx_handler_setup(struct iwl_priv *priv) |
468 | { | |
469 | } | |
470 | ||
da8dec29 TW |
471 | static struct iwl_hcmd_ops iwl5000_hcmd = { |
472 | }; | |
473 | ||
474 | static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { | |
c1adf9fb | 475 | .get_hcmd_size = iwl5000_get_hcmd_size, |
2469bf2e | 476 | .build_addsta_hcmd = iwl5000_build_addsta_hcmd, |
33fd5033 EG |
477 | #ifdef CONFIG_IWL5000_RUN_TIME_CALIB |
478 | .gain_computation = iwl5000_gain_computation, | |
479 | .chain_noise_reset = iwl5000_chain_noise_reset, | |
480 | #endif | |
da8dec29 TW |
481 | }; |
482 | ||
483 | static struct iwl_lib_ops iwl5000_lib = { | |
fdd3e8a4 | 484 | .set_hw_params = iwl5000_hw_set_hw_params, |
d4100dd9 RR |
485 | .alloc_shared_mem = iwl5000_alloc_shared_mem, |
486 | .free_shared_mem = iwl5000_free_shared_mem, | |
d67f5489 | 487 | .shared_mem_rx_idx = iwl5000_shared_mem_rx_idx, |
7839fc03 | 488 | .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, |
5a676bbe | 489 | .disable_tx_fifo = iwl5000_disable_tx_fifo, |
b600e4e1 | 490 | .rx_handler_setup = iwl5000_rx_handler_setup, |
30d59260 TW |
491 | .apm_ops = { |
492 | .init = iwl5000_apm_init, | |
5a835353 | 493 | .config = iwl5000_nic_config, |
88acbd3b | 494 | .set_pwr_src = iwl4965_set_pwr_src, |
30d59260 | 495 | }, |
da8dec29 | 496 | .eeprom_ops = { |
25ae3986 TW |
497 | .regulatory_bands = { |
498 | EEPROM_5000_REG_BAND_1_CHANNELS, | |
499 | EEPROM_5000_REG_BAND_2_CHANNELS, | |
500 | EEPROM_5000_REG_BAND_3_CHANNELS, | |
501 | EEPROM_5000_REG_BAND_4_CHANNELS, | |
502 | EEPROM_5000_REG_BAND_5_CHANNELS, | |
503 | EEPROM_5000_REG_BAND_24_FAT_CHANNELS, | |
504 | EEPROM_5000_REG_BAND_52_FAT_CHANNELS | |
505 | }, | |
da8dec29 TW |
506 | .verify_signature = iwlcore_eeprom_verify_signature, |
507 | .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, | |
508 | .release_semaphore = iwlcore_eeprom_release_semaphore, | |
f1f69415 | 509 | .check_version = iwl5000_eeprom_check_version, |
25ae3986 | 510 | .query_addr = iwl5000_eeprom_query_addr, |
da8dec29 TW |
511 | }, |
512 | }; | |
513 | ||
514 | static struct iwl_ops iwl5000_ops = { | |
515 | .lib = &iwl5000_lib, | |
516 | .hcmd = &iwl5000_hcmd, | |
517 | .utils = &iwl5000_hcmd_utils, | |
518 | }; | |
519 | ||
5a6a256e TW |
520 | static struct iwl_mod_params iwl50_mod_params = { |
521 | .num_of_queues = IWL50_NUM_QUEUES, | |
522 | .enable_qos = 1, | |
523 | .amsdu_size_8K = 1, | |
3a1081e8 | 524 | .restart_fw = 1, |
5a6a256e TW |
525 | /* the rest are 0 by default */ |
526 | }; | |
527 | ||
528 | ||
529 | struct iwl_cfg iwl5300_agn_cfg = { | |
530 | .name = "5300AGN", | |
531 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", | |
532 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | |
da8dec29 | 533 | .ops = &iwl5000_ops, |
25ae3986 | 534 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
5a6a256e TW |
535 | .mod_params = &iwl50_mod_params, |
536 | }; | |
537 | ||
538 | struct iwl_cfg iwl5100_agn_cfg = { | |
539 | .name = "5100AGN", | |
540 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", | |
541 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | |
da8dec29 | 542 | .ops = &iwl5000_ops, |
25ae3986 | 543 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
5a6a256e TW |
544 | .mod_params = &iwl50_mod_params, |
545 | }; | |
546 | ||
547 | struct iwl_cfg iwl5350_agn_cfg = { | |
548 | .name = "5350AGN", | |
549 | .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode", | |
550 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | |
da8dec29 | 551 | .ops = &iwl5000_ops, |
25ae3986 | 552 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
5a6a256e TW |
553 | .mod_params = &iwl50_mod_params, |
554 | }; | |
555 | ||
556 | module_param_named(disable50, iwl50_mod_params.disable, int, 0444); | |
557 | MODULE_PARM_DESC(disable50, | |
558 | "manually disable the 50XX radio (default 0 [radio on])"); | |
559 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); | |
560 | MODULE_PARM_DESC(swcrypto50, | |
561 | "using software crypto engine (default 0 [hardware])\n"); | |
562 | module_param_named(debug50, iwl50_mod_params.debug, int, 0444); | |
563 | MODULE_PARM_DESC(debug50, "50XX debug output mask"); | |
564 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); | |
565 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | |
566 | module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444); | |
567 | MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality"); | |
568 | module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444); | |
569 | MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); | |
3a1081e8 EK |
570 | module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444); |
571 | MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); |