Commit | Line | Data |
---|---|---|
5449c685 FB |
1 | /* |
2 | * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc. | |
3 | * All rights reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License as published by | |
7 | * the Free Software Foundation; either version 2 of the License, or | |
8 | * (at your option) any later version. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | * GNU General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along | |
16 | * with this program; if not, write to the Free Software Foundation, Inc., | |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 | * | |
19 | * File: device_main.c | |
20 | * | |
21 | * Purpose: driver entry for initial, open, close, tx and rx. | |
22 | * | |
23 | * Author: Lyndon Chen | |
24 | * | |
25 | * Date: Jan 8, 2003 | |
26 | * | |
27 | * Functions: | |
28 | * | |
013a468c CC |
29 | * vt6655_probe - module initial (insmod) driver entry |
30 | * vt6655_remove - module remove entry | |
31 | * vt6655_init_info - device structure resource allocation function | |
5449c685 FB |
32 | * device_free_info - device structure resource free function |
33 | * device_get_pci_info - get allocated pci io/mem resource | |
34 | * device_print_info - print out resource | |
5449c685 | 35 | * device_intr - interrupt handle function |
5449c685 | 36 | * device_rx_srv - rx service function |
5449c685 | 37 | * device_alloc_rx_buf - rx buffer pre-allocated function |
5449c685 | 38 | * device_free_tx_buf - free tx buffer function |
5449c685 FB |
39 | * device_init_rd0_ring- initial rd dma0 ring |
40 | * device_init_rd1_ring- initial rd dma1 ring | |
41 | * device_init_td0_ring- initial tx dma0 ring buffer | |
42 | * device_init_td1_ring- initial tx dma1 ring buffer | |
43 | * device_init_registers- initial MAC & BBP & RF internal registers. | |
44 | * device_init_rings- initial tx/rx ring buffer | |
5449c685 FB |
45 | * device_free_rings- free all allocated ring buffer |
46 | * device_tx_srv- tx interrupt service function | |
47 | * | |
48 | * Revision History: | |
49 | */ | |
50 | #undef __NO_VERSION__ | |
51 | ||
f805442e | 52 | #include <linux/file.h> |
5449c685 | 53 | #include "device.h" |
5449c685 | 54 | #include "card.h" |
79566eb2 | 55 | #include "channel.h" |
5449c685 | 56 | #include "baseband.h" |
5449c685 | 57 | #include "mac.h" |
5449c685 | 58 | #include "power.h" |
5449c685 | 59 | #include "rxtx.h" |
5449c685 | 60 | #include "dpc.h" |
5449c685 | 61 | #include "rf.h" |
5449c685 FB |
62 | #include <linux/delay.h> |
63 | #include <linux/kthread.h> | |
5a0e3ad6 | 64 | #include <linux/slab.h> |
5449c685 | 65 | |
5449c685 | 66 | /*--------------------- Static Definitions -------------------------*/ |
5449c685 FB |
67 | // |
68 | // Define module options | |
69 | // | |
5449c685 FB |
70 | MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"); |
71 | MODULE_LICENSE("GPL"); | |
72 | MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"); | |
5449c685 | 73 | |
915006cd | 74 | #define DEVICE_PARAM(N, D) |
5449c685 FB |
75 | |
76 | #define RX_DESC_MIN0 16 | |
77 | #define RX_DESC_MAX0 128 | |
78 | #define RX_DESC_DEF0 32 | |
915006cd | 79 | DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0"); |
5449c685 FB |
80 | |
81 | #define RX_DESC_MIN1 16 | |
82 | #define RX_DESC_MAX1 128 | |
83 | #define RX_DESC_DEF1 32 | |
915006cd | 84 | DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1"); |
5449c685 FB |
85 | |
86 | #define TX_DESC_MIN0 16 | |
87 | #define TX_DESC_MAX0 128 | |
88 | #define TX_DESC_DEF0 32 | |
915006cd | 89 | DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0"); |
5449c685 FB |
90 | |
91 | #define TX_DESC_MIN1 16 | |
92 | #define TX_DESC_MAX1 128 | |
93 | #define TX_DESC_DEF1 64 | |
915006cd | 94 | DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1"); |
5449c685 | 95 | |
5449c685 FB |
96 | #define INT_WORKS_DEF 20 |
97 | #define INT_WORKS_MIN 10 | |
98 | #define INT_WORKS_MAX 64 | |
99 | ||
915006cd | 100 | DEVICE_PARAM(int_works, "Number of packets per interrupt services"); |
5449c685 | 101 | |
5449c685 FB |
102 | #define RTS_THRESH_DEF 2347 |
103 | ||
5449c685 FB |
104 | #define FRAG_THRESH_DEF 2346 |
105 | ||
5449c685 FB |
106 | #define SHORT_RETRY_MIN 0 |
107 | #define SHORT_RETRY_MAX 31 | |
108 | #define SHORT_RETRY_DEF 8 | |
109 | ||
5449c685 FB |
110 | DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits"); |
111 | ||
112 | #define LONG_RETRY_MIN 0 | |
113 | #define LONG_RETRY_MAX 15 | |
114 | #define LONG_RETRY_DEF 4 | |
115 | ||
5449c685 FB |
116 | DEVICE_PARAM(LongRetryLimit, "long frame retry limits"); |
117 | ||
5449c685 FB |
118 | /* BasebandType[] baseband type selected |
119 | 0: indicate 802.11a type | |
120 | 1: indicate 802.11b type | |
121 | 2: indicate 802.11g type | |
122 | */ | |
123 | #define BBP_TYPE_MIN 0 | |
124 | #define BBP_TYPE_MAX 2 | |
125 | #define BBP_TYPE_DEF 2 | |
126 | ||
127 | DEVICE_PARAM(BasebandType, "baseband type"); | |
128 | ||
5449c685 FB |
129 | #define DIVERSITY_ANT_DEF 0 |
130 | ||
131 | DEVICE_PARAM(bDiversityANTEnable, "ANT diversity mode"); | |
132 | ||
5449c685 FB |
133 | // |
134 | // Static vars definitions | |
135 | // | |
915006cd JP |
136 | static CHIP_INFO chip_info_table[] = { |
137 | { VT3253, "VIA Networking Solomon-A/B/G Wireless LAN Adapter ", | |
138 | 256, 1, DEVICE_FLAGS_IP_ALIGN|DEVICE_FLAGS_TX_ALIGN }, | |
139 | {0, NULL} | |
5449c685 FB |
140 | }; |
141 | ||
9e4c5c28 | 142 | static const struct pci_device_id vt6655_pci_id_table[] = { |
db6cb903 JL |
143 | { PCI_VDEVICE(VIA, 0x3253), (kernel_ulong_t)chip_info_table}, |
144 | { 0, } | |
5449c685 | 145 | }; |
5449c685 FB |
146 | |
147 | /*--------------------- Static Functions --------------------------*/ | |
148 | ||
013a468c | 149 | static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent); |
3f8597f4 MP |
150 | static void vt6655_init_info(struct pci_dev *pcid, |
151 | struct vnt_private **ppDevice, PCHIP_INFO); | |
152 | static void device_free_info(struct vnt_private *pDevice); | |
153 | static bool device_get_pci_info(struct vnt_private *, struct pci_dev *pcid); | |
154 | static void device_print_info(struct vnt_private *pDevice); | |
3f8597f4 | 155 | static void device_init_diversity_timer(struct vnt_private *pDevice); |
915006cd | 156 | static irqreturn_t device_intr(int irq, void *dev_instance); |
5449c685 | 157 | |
5449c685 FB |
158 | #ifdef CONFIG_PM |
159 | static int device_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); | |
9e4c5c28 | 160 | static struct notifier_block device_notifier = { |
34381c22 PH |
161 | .notifier_call = device_notify_reboot, |
162 | .next = NULL, | |
163 | .priority = 0, | |
5449c685 FB |
164 | }; |
165 | #endif | |
5449c685 | 166 | |
3f8597f4 MP |
167 | static void device_init_rd0_ring(struct vnt_private *pDevice); |
168 | static void device_init_rd1_ring(struct vnt_private *pDevice); | |
3f8597f4 MP |
169 | static void device_init_td0_ring(struct vnt_private *pDevice); |
170 | static void device_init_td1_ring(struct vnt_private *pDevice); | |
5449c685 | 171 | |
3f8597f4 MP |
172 | static int device_rx_srv(struct vnt_private *pDevice, unsigned int uIdx); |
173 | static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx); | |
174 | static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pDesc); | |
175 | static void device_init_registers(struct vnt_private *pDevice); | |
176 | static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc); | |
177 | static void device_free_td0_ring(struct vnt_private *pDevice); | |
178 | static void device_free_td1_ring(struct vnt_private *pDevice); | |
179 | static void device_free_rd0_ring(struct vnt_private *pDevice); | |
180 | static void device_free_rd1_ring(struct vnt_private *pDevice); | |
181 | static void device_free_rings(struct vnt_private *pDevice); | |
5449c685 | 182 | |
5449c685 FB |
183 | /*--------------------- Export Variables --------------------------*/ |
184 | ||
185 | /*--------------------- Export Functions --------------------------*/ | |
186 | ||
915006cd | 187 | static char *get_chip_name(int chip_id) |
3ac9e0fd DN |
188 | { |
189 | int i; | |
6b711271 | 190 | |
3ac9e0fd DN |
191 | for (i = 0; chip_info_table[i].name != NULL; i++) |
192 | if (chip_info_table[i].chip_id == chip_id) | |
193 | break; | |
194 | return chip_info_table[i].name; | |
5449c685 FB |
195 | } |
196 | ||
f4e1b7c8 | 197 | static void vt6655_remove(struct pci_dev *pcid) |
5449c685 | 198 | { |
3f8597f4 | 199 | struct vnt_private *pDevice = pci_get_drvdata(pcid); |
5449c685 | 200 | |
3ac9e0fd DN |
201 | if (pDevice == NULL) |
202 | return; | |
203 | device_free_info(pDevice); | |
5449c685 FB |
204 | } |
205 | ||
46fa0ec0 | 206 | static void device_get_options(struct vnt_private *pDevice) |
bf76ebd9 DN |
207 | { |
208 | POPTIONS pOpts = &(pDevice->sOpts); | |
209 | ||
210 | pOpts->nRxDescs0 = RX_DESC_DEF0; | |
211 | pOpts->nRxDescs1 = RX_DESC_DEF1; | |
212 | pOpts->nTxDescs[0] = TX_DESC_DEF0; | |
213 | pOpts->nTxDescs[1] = TX_DESC_DEF1; | |
bf76ebd9 | 214 | pOpts->int_works = INT_WORKS_DEF; |
bf76ebd9 | 215 | |
bf76ebd9 DN |
216 | pOpts->short_retry = SHORT_RETRY_DEF; |
217 | pOpts->long_retry = LONG_RETRY_DEF; | |
218 | pOpts->bbp_type = BBP_TYPE_DEF; | |
bf76ebd9 | 219 | pOpts->flags |= DEVICE_FLAGS_DiversityANT; |
5449c685 FB |
220 | } |
221 | ||
222 | static void | |
3f8597f4 MP |
223 | device_set_options(struct vnt_private *pDevice) |
224 | { | |
915006cd JP |
225 | pDevice->byShortRetryLimit = pDevice->sOpts.short_retry; |
226 | pDevice->byLongRetryLimit = pDevice->sOpts.long_retry; | |
915006cd | 227 | pDevice->bDiversityRegCtlON = (pDevice->sOpts.flags & DEVICE_FLAGS_DiversityANT) ? 1 : 0; |
915006cd | 228 | pDevice->byBBType = pDevice->sOpts.bbp_type; |
a793b2d8 | 229 | pDevice->byPacketType = (VIA_PKT_TYPE)pDevice->byBBType; |
5449c685 | 230 | pDevice->byAutoFBCtrl = AUTO_FB_0; |
915006cd | 231 | pDevice->bUpdateBBVGA = true; |
915006cd JP |
232 | pDevice->byPreambleType = 0; |
233 | ||
48caf5a0 JP |
234 | pr_debug(" byShortRetryLimit= %d\n", (int)pDevice->byShortRetryLimit); |
235 | pr_debug(" byLongRetryLimit= %d\n", (int)pDevice->byLongRetryLimit); | |
236 | pr_debug(" byPreambleType= %d\n", (int)pDevice->byPreambleType); | |
237 | pr_debug(" byShortPreamble= %d\n", (int)pDevice->byShortPreamble); | |
48caf5a0 | 238 | pr_debug(" byBBType= %d\n", (int)pDevice->byBBType); |
48caf5a0 JP |
239 | pr_debug(" pDevice->bDiversityRegCtlON= %d\n", |
240 | (int)pDevice->bDiversityRegCtlON); | |
5449c685 FB |
241 | } |
242 | ||
5449c685 | 243 | // |
789d1aef | 244 | // Initialisation of MAC & BBP registers |
5449c685 FB |
245 | // |
246 | ||
3f8597f4 | 247 | static void device_init_registers(struct vnt_private *pDevice) |
5449c685 | 248 | { |
10d6f1b7 | 249 | unsigned long flags; |
915006cd JP |
250 | unsigned int ii; |
251 | unsigned char byValue; | |
252 | unsigned char byValue1; | |
253 | unsigned char byCCKPwrdBm = 0; | |
254 | unsigned char byOFDMPwrdBm = 0; | |
6b711271 | 255 | |
915006cd | 256 | MACbShutdown(pDevice->PortOffset); |
a5f0eef3 | 257 | BBvSoftwareReset(pDevice); |
915006cd | 258 | |
9f34de35 MP |
259 | /* Do MACbSoftwareReset in MACvInitialize */ |
260 | MACbSoftwareReset(pDevice->PortOffset); | |
915006cd | 261 | |
9f34de35 | 262 | pDevice->bAES = false; |
915006cd | 263 | |
9f34de35 MP |
264 | /* Only used in 11g type, sync with ERP IE */ |
265 | pDevice->bProtectMode = false; | |
915006cd | 266 | |
9f34de35 MP |
267 | pDevice->bNonERPPresent = false; |
268 | pDevice->bBarkerPreambleMd = false; | |
269 | pDevice->wCurrentRate = RATE_1M; | |
270 | pDevice->byTopOFDMBasicRate = RATE_24M; | |
271 | pDevice->byTopCCKBasicRate = RATE_1M; | |
915006cd | 272 | |
9f34de35 MP |
273 | /* Target to IF pin while programming to RF chip. */ |
274 | pDevice->byRevId = 0; | |
915006cd | 275 | |
9f34de35 MP |
276 | /* init MAC */ |
277 | MACvInitialize(pDevice->PortOffset); | |
278 | ||
279 | /* Get Local ID */ | |
280 | VNSvInPortB(pDevice->PortOffset + MAC_REG_LOCALID, &pDevice->byLocalID); | |
915006cd | 281 | |
10d6f1b7 | 282 | spin_lock_irqsave(&pDevice->lock, flags); |
915006cd | 283 | |
9f34de35 | 284 | SROMvReadAllContents(pDevice->PortOffset, pDevice->abyEEPROM); |
915006cd | 285 | |
10d6f1b7 | 286 | spin_unlock_irqrestore(&pDevice->lock, flags); |
915006cd | 287 | |
9f34de35 MP |
288 | /* Get Channel range */ |
289 | pDevice->byMinChannel = 1; | |
290 | pDevice->byMaxChannel = CB_MAX_CHANNEL; | |
915006cd | 291 | |
9f34de35 MP |
292 | /* Get Antena */ |
293 | byValue = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_ANTENNA); | |
294 | if (byValue & EEP_ANTINV) | |
295 | pDevice->bTxRxAntInv = true; | |
296 | else | |
297 | pDevice->bTxRxAntInv = false; | |
298 | ||
299 | byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); | |
300 | /* if not set default is All */ | |
301 | if (byValue == 0) | |
302 | byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN); | |
303 | ||
304 | pDevice->ulDiversityNValue = 100*260; | |
305 | pDevice->ulDiversityMValue = 100*16; | |
306 | pDevice->byTMax = 1; | |
307 | pDevice->byTMax2 = 4; | |
308 | pDevice->ulSQ3TH = 0; | |
309 | pDevice->byTMax3 = 64; | |
310 | ||
311 | if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) { | |
312 | pDevice->byAntennaCount = 2; | |
313 | pDevice->byTxAntennaMode = ANT_B; | |
314 | pDevice->dwTxAntennaSel = 1; | |
315 | pDevice->dwRxAntennaSel = 1; | |
316 | ||
317 | if (pDevice->bTxRxAntInv) | |
318 | pDevice->byRxAntennaMode = ANT_A; | |
915006cd | 319 | else |
9f34de35 | 320 | pDevice->byRxAntennaMode = ANT_B; |
5449c685 | 321 | |
9f34de35 MP |
322 | byValue1 = SROMbyReadEmbedded(pDevice->PortOffset, |
323 | EEP_OFS_ANTENNA); | |
f2046f93 | 324 | |
9f34de35 MP |
325 | if ((byValue1 & 0x08) == 0) |
326 | pDevice->bDiversityEnable = false; | |
327 | else | |
328 | pDevice->bDiversityEnable = true; | |
329 | } else { | |
330 | pDevice->bDiversityEnable = false; | |
331 | pDevice->byAntennaCount = 1; | |
332 | pDevice->dwTxAntennaSel = 0; | |
333 | pDevice->dwRxAntennaSel = 0; | |
915006cd | 334 | |
9f34de35 MP |
335 | if (byValue & EEP_ANTENNA_AUX) { |
336 | pDevice->byTxAntennaMode = ANT_A; | |
915006cd | 337 | |
9f34de35 MP |
338 | if (pDevice->bTxRxAntInv) |
339 | pDevice->byRxAntennaMode = ANT_B; | |
340 | else | |
341 | pDevice->byRxAntennaMode = ANT_A; | |
342 | } else { | |
915006cd | 343 | pDevice->byTxAntennaMode = ANT_B; |
9f34de35 | 344 | |
1208f14a | 345 | if (pDevice->bTxRxAntInv) |
915006cd JP |
346 | pDevice->byRxAntennaMode = ANT_A; |
347 | else | |
348 | pDevice->byRxAntennaMode = ANT_B; | |
915006cd | 349 | } |
9f34de35 | 350 | } |
5449c685 | 351 | |
48caf5a0 JP |
352 | pr_debug("bDiversityEnable=[%d],NValue=[%d],MValue=[%d],TMax=[%d],TMax2=[%d]\n", |
353 | pDevice->bDiversityEnable, (int)pDevice->ulDiversityNValue, | |
354 | (int)pDevice->ulDiversityMValue, pDevice->byTMax, | |
355 | pDevice->byTMax2); | |
9f34de35 MP |
356 | |
357 | /* zonetype initial */ | |
358 | pDevice->byOriginalZonetype = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; | |
915006cd | 359 | |
9f34de35 MP |
360 | /* Get RFType */ |
361 | pDevice->byRFType = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_RFTYPE); | |
915006cd | 362 | |
9f34de35 MP |
363 | /* force change RevID for VT3253 emu */ |
364 | if ((pDevice->byRFType & RF_EMU) != 0) | |
915006cd | 365 | pDevice->byRevId = 0x80; |
915006cd | 366 | |
9f34de35 | 367 | pDevice->byRFType &= RF_MASK; |
48caf5a0 | 368 | pr_debug("pDevice->byRFType = %x\n", pDevice->byRFType); |
915006cd | 369 | |
9f34de35 MP |
370 | if (!pDevice->bZoneRegExist) |
371 | pDevice->byZoneType = pDevice->abyEEPROM[EEP_OFS_ZONETYPE]; | |
bc5cf656 | 372 | |
48caf5a0 | 373 | pr_debug("pDevice->byZoneType = %x\n", pDevice->byZoneType); |
915006cd | 374 | |
9f34de35 MP |
375 | /* Init RF module */ |
376 | RFbInit(pDevice); | |
915006cd | 377 | |
9f34de35 MP |
378 | /* Get Desire Power Value */ |
379 | pDevice->byCurPwr = 0xFF; | |
380 | pDevice->byCCKPwr = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_CCK); | |
381 | pDevice->byOFDMPwrG = SROMbyReadEmbedded(pDevice->PortOffset, EEP_OFS_PWR_OFDMG); | |
f2046f93 | 382 | |
9f34de35 MP |
383 | /* Load power Table */ |
384 | for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) { | |
385 | pDevice->abyCCKPwrTbl[ii + 1] = | |
386 | SROMbyReadEmbedded(pDevice->PortOffset, | |
387 | (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL)); | |
388 | if (pDevice->abyCCKPwrTbl[ii + 1] == 0) | |
389 | pDevice->abyCCKPwrTbl[ii+1] = pDevice->byCCKPwr; | |
5449c685 | 390 | |
9f34de35 MP |
391 | pDevice->abyOFDMPwrTbl[ii + 1] = |
392 | SROMbyReadEmbedded(pDevice->PortOffset, | |
393 | (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL)); | |
394 | if (pDevice->abyOFDMPwrTbl[ii + 1] == 0) | |
395 | pDevice->abyOFDMPwrTbl[ii + 1] = pDevice->byOFDMPwrG; | |
bc5cf656 | 396 | |
9f34de35 MP |
397 | pDevice->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm; |
398 | pDevice->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm; | |
399 | } | |
bc5cf656 | 400 | |
9f34de35 | 401 | /* recover 12,13 ,14channel for EUROPE by 11 channel */ |
f4cf678f MP |
402 | for (ii = 11; ii < 14; ii++) { |
403 | pDevice->abyCCKPwrTbl[ii] = pDevice->abyCCKPwrTbl[10]; | |
404 | pDevice->abyOFDMPwrTbl[ii] = pDevice->abyOFDMPwrTbl[10]; | |
9f34de35 | 405 | } |
5449c685 | 406 | |
9f34de35 MP |
407 | /* Load OFDM A Power Table */ |
408 | for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) { | |
409 | pDevice->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] = | |
410 | SROMbyReadEmbedded(pDevice->PortOffset, | |
411 | (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL)); | |
5449c685 | 412 | |
9f34de35 MP |
413 | pDevice->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] = |
414 | SROMbyReadEmbedded(pDevice->PortOffset, | |
415 | (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm)); | |
416 | } | |
5449c685 | 417 | |
9f34de35 MP |
418 | if (pDevice->byLocalID > REV_ID_VT3253_B1) { |
419 | MACvSelectPage1(pDevice->PortOffset); | |
5449c685 | 420 | |
9f34de35 MP |
421 | VNSvOutPortB(pDevice->PortOffset + MAC_REG_MSRCTL + 1, |
422 | (MSRCTL1_TXPWR | MSRCTL1_CSAPAREN)); | |
5449c685 | 423 | |
9f34de35 MP |
424 | MACvSelectPage0(pDevice->PortOffset); |
425 | } | |
5449c685 | 426 | |
9f34de35 MP |
427 | /* use relative tx timeout and 802.11i D4 */ |
428 | MACvWordRegBitsOn(pDevice->PortOffset, | |
429 | MAC_REG_CFG, (CFG_TKIPOPT | CFG_NOTXTIMEOUT)); | |
5449c685 | 430 | |
9f34de35 MP |
431 | /* set performance parameter by registry */ |
432 | MACvSetShortRetryLimit(pDevice->PortOffset, pDevice->byShortRetryLimit); | |
433 | MACvSetLongRetryLimit(pDevice->PortOffset, pDevice->byLongRetryLimit); | |
5449c685 | 434 | |
9f34de35 MP |
435 | /* reset TSF counter */ |
436 | VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); | |
437 | /* enable TSF counter */ | |
438 | VNSvOutPortB(pDevice->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
5449c685 | 439 | |
9f34de35 MP |
440 | /* initialize BBP registers */ |
441 | BBbVT3253Init(pDevice); | |
5449c685 | 442 | |
9f34de35 MP |
443 | if (pDevice->bUpdateBBVGA) { |
444 | pDevice->byBBVGACurrent = pDevice->abyBBVGA[0]; | |
445 | pDevice->byBBVGANew = pDevice->byBBVGACurrent; | |
446 | BBvSetVGAGainOffset(pDevice, pDevice->abyBBVGA[0]); | |
447 | } | |
5449c685 | 448 | |
a5f0eef3 MP |
449 | BBvSetRxAntennaMode(pDevice, pDevice->byRxAntennaMode); |
450 | BBvSetTxAntennaMode(pDevice, pDevice->byTxAntennaMode); | |
5449c685 | 451 | |
9f34de35 MP |
452 | /* Set BB and packet type at the same time. */ |
453 | /* Set Short Slot Time, xIFS, and RSPINF. */ | |
bfa4b0fe | 454 | pDevice->wCurrentRate = RATE_54M; |
bc5cf656 | 455 | |
9f34de35 | 456 | pDevice->bRadioOff = false; |
5449c685 | 457 | |
9f34de35 MP |
458 | pDevice->byRadioCtl = SROMbyReadEmbedded(pDevice->PortOffset, |
459 | EEP_OFS_RADIOCTL); | |
460 | pDevice->bHWRadioOff = false; | |
5449c685 | 461 | |
9f34de35 MP |
462 | if (pDevice->byRadioCtl & EEP_RADIOCTL_ENABLE) { |
463 | /* Get GPIO */ | |
464 | MACvGPIOIn(pDevice->PortOffset, &pDevice->byGPIO); | |
465 | ||
466 | if (((pDevice->byGPIO & GPIO0_DATA) && | |
467 | !(pDevice->byRadioCtl & EEP_RADIOCTL_INV)) || | |
468 | (!(pDevice->byGPIO & GPIO0_DATA) && | |
469 | (pDevice->byRadioCtl & EEP_RADIOCTL_INV))) | |
915006cd | 470 | pDevice->bHWRadioOff = true; |
915006cd | 471 | } |
9f34de35 | 472 | |
bc5cf656 | 473 | if (pDevice->bHWRadioOff || pDevice->bRadioControlOff) |
915006cd | 474 | CARDbRadioPowerOff(pDevice); |
5449c685 | 475 | |
3500a1da MP |
476 | /* get Permanent network address */ |
477 | SROMvReadEtherAddress(pDevice->PortOffset, pDevice->abyCurrentNetAddr); | |
48caf5a0 | 478 | pr_debug("Network address = %pM\n", pDevice->abyCurrentNetAddr); |
915006cd | 479 | |
3500a1da MP |
480 | /* reset Tx pointer */ |
481 | CARDvSafeResetRx(pDevice); | |
482 | /* reset Rx pointer */ | |
483 | CARDvSafeResetTx(pDevice); | |
5449c685 | 484 | |
3500a1da MP |
485 | if (pDevice->byLocalID <= REV_ID_VT3253_A1) |
486 | MACvRegBitsOn(pDevice->PortOffset, MAC_REG_RCR, RCR_WPAERR); | |
5449c685 | 487 | |
3500a1da MP |
488 | /* Turn On Rx DMA */ |
489 | MACvReceive0(pDevice->PortOffset); | |
490 | MACvReceive1(pDevice->PortOffset); | |
5449c685 | 491 | |
3500a1da MP |
492 | /* start the adapter */ |
493 | MACvStart(pDevice->PortOffset); | |
5449c685 FB |
494 | } |
495 | ||
3f8597f4 | 496 | static void device_init_diversity_timer(struct vnt_private *pDevice) |
84b50762 | 497 | { |
915006cd JP |
498 | init_timer(&pDevice->TimerSQ3Tmax1); |
499 | pDevice->TimerSQ3Tmax1.data = (unsigned long) pDevice; | |
e11cdc39 | 500 | pDevice->TimerSQ3Tmax1.function = TimerSQ3CallBack; |
915006cd | 501 | pDevice->TimerSQ3Tmax1.expires = RUN_AT(HZ); |
5449c685 | 502 | |
915006cd JP |
503 | init_timer(&pDevice->TimerSQ3Tmax2); |
504 | pDevice->TimerSQ3Tmax2.data = (unsigned long) pDevice; | |
e11cdc39 | 505 | pDevice->TimerSQ3Tmax2.function = TimerSQ3CallBack; |
915006cd | 506 | pDevice->TimerSQ3Tmax2.expires = RUN_AT(HZ); |
5449c685 | 507 | |
915006cd JP |
508 | init_timer(&pDevice->TimerSQ3Tmax3); |
509 | pDevice->TimerSQ3Tmax3.data = (unsigned long) pDevice; | |
e11cdc39 | 510 | pDevice->TimerSQ3Tmax3.function = TimerState1CallBack; |
915006cd | 511 | pDevice->TimerSQ3Tmax3.expires = RUN_AT(HZ); |
5449c685 FB |
512 | } |
513 | ||
3f8597f4 | 514 | static void device_print_info(struct vnt_private *pDevice) |
5449c685 | 515 | { |
bc5d431c | 516 | dev_info(&pDevice->pcid->dev, "%s\n", get_chip_name(pDevice->chip_id)); |
5449c685 | 517 | |
bc5d431c MP |
518 | dev_info(&pDevice->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n", |
519 | pDevice->abyCurrentNetAddr, (unsigned long)pDevice->ioaddr, | |
520 | (unsigned long)pDevice->PortOffset, pDevice->pcid->irq); | |
5449c685 FB |
521 | } |
522 | ||
3f8597f4 MP |
523 | static void vt6655_init_info(struct pci_dev *pcid, |
524 | struct vnt_private **ppDevice, | |
525 | PCHIP_INFO pChip_info) | |
526 | { | |
1bd63757 | 527 | memset(*ppDevice, 0, sizeof(**ppDevice)); |
5449c685 | 528 | |
915006cd JP |
529 | (*ppDevice)->pcid = pcid; |
530 | (*ppDevice)->chip_id = pChip_info->chip_id; | |
531 | (*ppDevice)->io_size = pChip_info->io_size; | |
532 | (*ppDevice)->nTxQueues = pChip_info->nTxQueue; | |
533 | (*ppDevice)->multicast_limit = 32; | |
5449c685 | 534 | |
915006cd | 535 | spin_lock_init(&((*ppDevice)->lock)); |
5449c685 FB |
536 | } |
537 | ||
3f8597f4 MP |
538 | static bool device_get_pci_info(struct vnt_private *pDevice, |
539 | struct pci_dev *pcid) | |
84b50762 | 540 | { |
915006cd JP |
541 | u16 pci_cmd; |
542 | u8 b; | |
543 | unsigned int cis_addr; | |
5449c685 | 544 | |
915006cd JP |
545 | pci_read_config_byte(pcid, PCI_REVISION_ID, &pDevice->byRevId); |
546 | pci_read_config_word(pcid, PCI_SUBSYSTEM_ID, &pDevice->SubSystemID); | |
547 | pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pDevice->SubVendorID); | |
548 | pci_read_config_word(pcid, PCI_COMMAND, (u16 *)&(pci_cmd)); | |
5449c685 | 549 | |
915006cd | 550 | pci_set_master(pcid); |
5449c685 | 551 | |
915006cd JP |
552 | pDevice->memaddr = pci_resource_start(pcid, 0); |
553 | pDevice->ioaddr = pci_resource_start(pcid, 1); | |
5449c685 | 554 | |
915006cd | 555 | cis_addr = pci_resource_start(pcid, 2); |
5449c685 | 556 | |
915006cd | 557 | pDevice->pcid = pcid; |
5449c685 | 558 | |
915006cd JP |
559 | pci_read_config_byte(pcid, PCI_COMMAND, &b); |
560 | pci_write_config_byte(pcid, PCI_COMMAND, (b|PCI_COMMAND_MASTER)); | |
5449c685 | 561 | |
915006cd | 562 | return true; |
5449c685 FB |
563 | } |
564 | ||
3f8597f4 | 565 | static void device_free_info(struct vnt_private *pDevice) |
84b50762 | 566 | { |
14e53006 MP |
567 | if (!pDevice) |
568 | return; | |
5449c685 | 569 | |
14e53006 MP |
570 | if (pDevice->mac_hw) |
571 | ieee80211_unregister_hw(pDevice->hw); | |
5449c685 | 572 | |
915006cd | 573 | if (pDevice->PortOffset) |
16834405 | 574 | iounmap(pDevice->PortOffset); |
5449c685 | 575 | |
915006cd JP |
576 | if (pDevice->pcid) |
577 | pci_release_regions(pDevice->pcid); | |
14e53006 MP |
578 | |
579 | if (pDevice->hw) | |
580 | ieee80211_free_hw(pDevice->hw); | |
5449c685 | 581 | } |
5449c685 | 582 | |
3f8597f4 | 583 | static bool device_init_rings(struct vnt_private *pDevice) |
84b50762 | 584 | { |
915006cd | 585 | void *vir_pool; |
5449c685 | 586 | |
915006cd | 587 | /*allocate all RD/TD rings a single pool*/ |
8b983be5 JP |
588 | vir_pool = pci_zalloc_consistent(pDevice->pcid, |
589 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + | |
590 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + | |
591 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + | |
592 | pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), | |
593 | &pDevice->pool_dma); | |
915006cd | 594 | if (vir_pool == NULL) { |
42f709ef | 595 | dev_err(&pDevice->pcid->dev, "allocate desc dma memory failed\n"); |
915006cd JP |
596 | return false; |
597 | } | |
5449c685 | 598 | |
915006cd JP |
599 | pDevice->aRD0Ring = vir_pool; |
600 | pDevice->aRD1Ring = vir_pool + | |
601 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); | |
602 | ||
915006cd JP |
603 | pDevice->rd0_pool_dma = pDevice->pool_dma; |
604 | pDevice->rd1_pool_dma = pDevice->rd0_pool_dma + | |
605 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc); | |
606 | ||
8b983be5 JP |
607 | pDevice->tx0_bufs = pci_zalloc_consistent(pDevice->pcid, |
608 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + | |
609 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + | |
610 | CB_BEACON_BUF_SIZE + | |
611 | CB_MAX_BUF_SIZE, | |
612 | &pDevice->tx_bufs_dma0); | |
915006cd | 613 | if (pDevice->tx0_bufs == NULL) { |
42f709ef MP |
614 | dev_err(&pDevice->pcid->dev, "allocate buf dma memory failed\n"); |
615 | ||
915006cd JP |
616 | pci_free_consistent(pDevice->pcid, |
617 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + | |
618 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + | |
619 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + | |
620 | pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc), | |
621 | vir_pool, pDevice->pool_dma | |
622 | ); | |
623 | return false; | |
624 | } | |
5449c685 | 625 | |
915006cd JP |
626 | pDevice->td0_pool_dma = pDevice->rd1_pool_dma + |
627 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); | |
5449c685 | 628 | |
915006cd JP |
629 | pDevice->td1_pool_dma = pDevice->td0_pool_dma + |
630 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc); | |
5449c685 | 631 | |
915006cd JP |
632 | // vir_pool: pvoid type |
633 | pDevice->apTD0Rings = vir_pool | |
634 | + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) | |
635 | + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc); | |
5449c685 | 636 | |
915006cd JP |
637 | pDevice->apTD1Rings = vir_pool |
638 | + pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) | |
639 | + pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) | |
640 | + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc); | |
5449c685 | 641 | |
915006cd JP |
642 | pDevice->tx1_bufs = pDevice->tx0_bufs + |
643 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ; | |
5449c685 | 644 | |
915006cd JP |
645 | pDevice->tx_beacon_bufs = pDevice->tx1_bufs + |
646 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ; | |
5449c685 | 647 | |
915006cd JP |
648 | pDevice->pbyTmpBuff = pDevice->tx_beacon_bufs + |
649 | CB_BEACON_BUF_SIZE; | |
5449c685 | 650 | |
915006cd JP |
651 | pDevice->tx_bufs_dma1 = pDevice->tx_bufs_dma0 + |
652 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ; | |
5449c685 | 653 | |
915006cd JP |
654 | pDevice->tx_beacon_dma = pDevice->tx_bufs_dma1 + |
655 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ; | |
5449c685 | 656 | |
915006cd | 657 | return true; |
5449c685 FB |
658 | } |
659 | ||
3f8597f4 | 660 | static void device_free_rings(struct vnt_private *pDevice) |
84b50762 | 661 | { |
915006cd JP |
662 | pci_free_consistent(pDevice->pcid, |
663 | pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) + | |
664 | pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) + | |
665 | pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) + | |
666 | pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc) | |
667 | , | |
668 | pDevice->aRD0Ring, pDevice->pool_dma | |
669 | ); | |
670 | ||
671 | if (pDevice->tx0_bufs) | |
672 | pci_free_consistent(pDevice->pcid, | |
673 | pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ + | |
674 | pDevice->sOpts.nTxDescs[1] * PKT_BUF_SZ + | |
675 | CB_BEACON_BUF_SIZE + | |
676 | CB_MAX_BUF_SIZE, | |
677 | pDevice->tx0_bufs, pDevice->tx_bufs_dma0 | |
678 | ); | |
5449c685 FB |
679 | } |
680 | ||
3f8597f4 | 681 | static void device_init_rd0_ring(struct vnt_private *pDevice) |
84b50762 | 682 | { |
915006cd JP |
683 | int i; |
684 | dma_addr_t curr = pDevice->rd0_pool_dma; | |
685 | PSRxDesc pDesc; | |
686 | ||
687 | /* Init the RD0 ring entries */ | |
688 | for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) { | |
689 | pDesc = &(pDevice->aRD0Ring[i]); | |
690 | pDesc->pRDInfo = alloc_rd_info(); | |
691 | ASSERT(pDesc->pRDInfo); | |
42f709ef MP |
692 | if (!device_alloc_rx_buf(pDevice, pDesc)) |
693 | dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n"); | |
694 | ||
915006cd JP |
695 | pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]); |
696 | pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); | |
697 | pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); | |
698 | } | |
699 | ||
700 | if (i > 0) | |
701 | pDevice->aRD0Ring[i-1].next_desc = cpu_to_le32(pDevice->rd0_pool_dma); | |
702 | pDevice->pCurrRD[0] = &(pDevice->aRD0Ring[0]); | |
5449c685 FB |
703 | } |
704 | ||
3f8597f4 | 705 | static void device_init_rd1_ring(struct vnt_private *pDevice) |
84b50762 | 706 | { |
915006cd JP |
707 | int i; |
708 | dma_addr_t curr = pDevice->rd1_pool_dma; | |
709 | PSRxDesc pDesc; | |
710 | ||
711 | /* Init the RD1 ring entries */ | |
712 | for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) { | |
713 | pDesc = &(pDevice->aRD1Ring[i]); | |
714 | pDesc->pRDInfo = alloc_rd_info(); | |
715 | ASSERT(pDesc->pRDInfo); | |
42f709ef MP |
716 | if (!device_alloc_rx_buf(pDevice, pDesc)) |
717 | dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n"); | |
718 | ||
915006cd JP |
719 | pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]); |
720 | pDesc->pRDInfo->curr_desc = cpu_to_le32(curr); | |
721 | pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc)); | |
722 | } | |
723 | ||
724 | if (i > 0) | |
725 | pDevice->aRD1Ring[i-1].next_desc = cpu_to_le32(pDevice->rd1_pool_dma); | |
726 | pDevice->pCurrRD[1] = &(pDevice->aRD1Ring[0]); | |
5449c685 FB |
727 | } |
728 | ||
3f8597f4 | 729 | static void device_free_rd0_ring(struct vnt_private *pDevice) |
84b50762 | 730 | { |
915006cd | 731 | int i; |
5449c685 | 732 | |
915006cd JP |
733 | for (i = 0; i < pDevice->sOpts.nRxDescs0; i++) { |
734 | PSRxDesc pDesc = &(pDevice->aRD0Ring[i]); | |
735 | PDEVICE_RD_INFO pRDInfo = pDesc->pRDInfo; | |
5449c685 | 736 | |
915006cd JP |
737 | pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma, |
738 | pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); | |
5449c685 | 739 | |
915006cd | 740 | dev_kfree_skb(pRDInfo->skb); |
5449c685 | 741 | |
61d566a5 | 742 | kfree(pDesc->pRDInfo); |
915006cd | 743 | } |
5449c685 FB |
744 | } |
745 | ||
3f8597f4 | 746 | static void device_free_rd1_ring(struct vnt_private *pDevice) |
84b50762 | 747 | { |
915006cd | 748 | int i; |
5449c685 | 749 | |
915006cd JP |
750 | for (i = 0; i < pDevice->sOpts.nRxDescs1; i++) { |
751 | PSRxDesc pDesc = &(pDevice->aRD1Ring[i]); | |
752 | PDEVICE_RD_INFO pRDInfo = pDesc->pRDInfo; | |
5449c685 | 753 | |
915006cd JP |
754 | pci_unmap_single(pDevice->pcid, pRDInfo->skb_dma, |
755 | pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); | |
5449c685 | 756 | |
915006cd | 757 | dev_kfree_skb(pRDInfo->skb); |
5449c685 | 758 | |
61d566a5 | 759 | kfree(pDesc->pRDInfo); |
915006cd | 760 | } |
5449c685 FB |
761 | } |
762 | ||
3f8597f4 | 763 | static void device_init_td0_ring(struct vnt_private *pDevice) |
84b50762 | 764 | { |
915006cd JP |
765 | int i; |
766 | dma_addr_t curr; | |
767 | PSTxDesc pDesc; | |
768 | ||
769 | curr = pDevice->td0_pool_dma; | |
770 | for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) { | |
771 | pDesc = &(pDevice->apTD0Rings[i]); | |
772 | pDesc->pTDInfo = alloc_td_info(); | |
773 | ASSERT(pDesc->pTDInfo); | |
774 | if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { | |
775 | pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ; | |
776 | pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ; | |
777 | } | |
778 | pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]); | |
779 | pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); | |
780 | pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); | |
781 | } | |
782 | ||
783 | if (i > 0) | |
784 | pDevice->apTD0Rings[i-1].next_desc = cpu_to_le32(pDevice->td0_pool_dma); | |
785 | pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]); | |
5449c685 FB |
786 | } |
787 | ||
3f8597f4 | 788 | static void device_init_td1_ring(struct vnt_private *pDevice) |
84b50762 | 789 | { |
915006cd JP |
790 | int i; |
791 | dma_addr_t curr; | |
792 | PSTxDesc pDesc; | |
793 | ||
794 | /* Init the TD ring entries */ | |
795 | curr = pDevice->td1_pool_dma; | |
796 | for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) { | |
797 | pDesc = &(pDevice->apTD1Rings[i]); | |
798 | pDesc->pTDInfo = alloc_td_info(); | |
799 | ASSERT(pDesc->pTDInfo); | |
800 | if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) { | |
801 | pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ; | |
802 | pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ; | |
803 | } | |
804 | pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]); | |
805 | pDesc->pTDInfo->curr_desc = cpu_to_le32(curr); | |
806 | pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc)); | |
807 | } | |
808 | ||
809 | if (i > 0) | |
810 | pDevice->apTD1Rings[i-1].next_desc = cpu_to_le32(pDevice->td1_pool_dma); | |
811 | pDevice->apTailTD[1] = pDevice->apCurrTD[1] = &(pDevice->apTD1Rings[0]); | |
5449c685 FB |
812 | } |
813 | ||
3f8597f4 | 814 | static void device_free_td0_ring(struct vnt_private *pDevice) |
84b50762 | 815 | { |
915006cd | 816 | int i; |
6b711271 | 817 | |
915006cd JP |
818 | for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) { |
819 | PSTxDesc pDesc = &(pDevice->apTD0Rings[i]); | |
820 | PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; | |
5449c685 | 821 | |
915006cd JP |
822 | if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) |
823 | pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, | |
824 | pTDInfo->skb->len, PCI_DMA_TODEVICE); | |
5449c685 | 825 | |
915006cd JP |
826 | if (pTDInfo->skb) |
827 | dev_kfree_skb(pTDInfo->skb); | |
5449c685 | 828 | |
61d566a5 | 829 | kfree(pDesc->pTDInfo); |
915006cd | 830 | } |
5449c685 FB |
831 | } |
832 | ||
3f8597f4 | 833 | static void device_free_td1_ring(struct vnt_private *pDevice) |
84b50762 | 834 | { |
915006cd | 835 | int i; |
5449c685 | 836 | |
915006cd JP |
837 | for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) { |
838 | PSTxDesc pDesc = &(pDevice->apTD1Rings[i]); | |
839 | PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; | |
5449c685 | 840 | |
915006cd JP |
841 | if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) |
842 | pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, | |
843 | pTDInfo->skb->len, PCI_DMA_TODEVICE); | |
5449c685 | 844 | |
915006cd JP |
845 | if (pTDInfo->skb) |
846 | dev_kfree_skb(pTDInfo->skb); | |
5449c685 | 847 | |
61d566a5 | 848 | kfree(pDesc->pTDInfo); |
915006cd | 849 | } |
5449c685 FB |
850 | } |
851 | ||
5449c685 FB |
852 | /*-----------------------------------------------------------------*/ |
853 | ||
3f8597f4 | 854 | static int device_rx_srv(struct vnt_private *pDevice, unsigned int uIdx) |
84b50762 | 855 | { |
915006cd JP |
856 | PSRxDesc pRD; |
857 | int works = 0; | |
5449c685 | 858 | |
915006cd JP |
859 | for (pRD = pDevice->pCurrRD[uIdx]; |
860 | pRD->m_rd0RD0.f1Owner == OWNED_BY_HOST; | |
861 | pRD = pRD->next) { | |
915006cd JP |
862 | if (works++ > 15) |
863 | break; | |
33b1c8c1 | 864 | if (vnt_receive_frame(pDevice, pRD)) { |
915006cd | 865 | if (!device_alloc_rx_buf(pDevice, pRD)) { |
42f709ef MP |
866 | dev_err(&pDevice->pcid->dev, |
867 | "can not allocate rx buf\n"); | |
915006cd JP |
868 | break; |
869 | } | |
870 | } | |
871 | pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC; | |
915006cd JP |
872 | } |
873 | ||
874 | pDevice->pCurrRD[uIdx] = pRD; | |
875 | ||
876 | return works; | |
5449c685 FB |
877 | } |
878 | ||
3f8597f4 | 879 | static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pRD) |
84b50762 | 880 | { |
915006cd | 881 | PDEVICE_RD_INFO pRDInfo = pRD->pRDInfo; |
5449c685 | 882 | |
915006cd | 883 | pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz); |
915006cd JP |
884 | if (pRDInfo->skb == NULL) |
885 | return false; | |
886 | ASSERT(pRDInfo->skb); | |
33b1c8c1 MP |
887 | |
888 | pRDInfo->skb_dma = | |
889 | pci_map_single(pDevice->pcid, | |
890 | skb_put(pRDInfo->skb, skb_tailroom(pRDInfo->skb)), | |
891 | pDevice->rx_buf_sz, PCI_DMA_FROMDEVICE); | |
892 | ||
915006cd JP |
893 | *((unsigned int *)&(pRD->m_rd0RD0)) = 0; /* FIX cast */ |
894 | ||
895 | pRD->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz); | |
896 | pRD->m_rd0RD0.f1Owner = OWNED_BY_NIC; | |
897 | pRD->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz); | |
898 | pRD->buff_addr = cpu_to_le32(pRDInfo->skb_dma); | |
899 | ||
900 | return true; | |
5449c685 FB |
901 | } |
902 | ||
59918bea MP |
903 | static const u8 fallback_rate0[5][5] = { |
904 | {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M}, | |
905 | {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M}, | |
906 | {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M}, | |
907 | {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M}, | |
908 | {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M} | |
909 | }; | |
910 | ||
911 | static const u8 fallback_rate1[5][5] = { | |
912 | {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M}, | |
913 | {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M}, | |
914 | {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M}, | |
915 | {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M}, | |
916 | {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M} | |
917 | }; | |
918 | ||
919 | static int vnt_int_report_rate(struct vnt_private *priv, | |
920 | PDEVICE_TD_INFO context, u8 tsr0, u8 tsr1) | |
921 | { | |
922 | struct vnt_tx_fifo_head *fifo_head; | |
923 | struct ieee80211_tx_info *info; | |
924 | struct ieee80211_rate *rate; | |
925 | u16 fb_option; | |
926 | u8 tx_retry = (tsr0 & TSR0_NCR); | |
927 | s8 idx; | |
928 | ||
929 | if (!context) | |
930 | return -ENOMEM; | |
931 | ||
932 | if (!context->skb) | |
933 | return -EINVAL; | |
934 | ||
935 | fifo_head = (struct vnt_tx_fifo_head *)context->buf; | |
936 | fb_option = (le16_to_cpu(fifo_head->fifo_ctl) & | |
937 | (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1)); | |
938 | ||
939 | info = IEEE80211_SKB_CB(context->skb); | |
940 | idx = info->control.rates[0].idx; | |
941 | ||
942 | if (fb_option && !(tsr1 & TSR1_TERR)) { | |
943 | u8 tx_rate; | |
944 | u8 retry = tx_retry; | |
945 | ||
946 | rate = ieee80211_get_tx_rate(priv->hw, info); | |
947 | tx_rate = rate->hw_value - RATE_18M; | |
948 | ||
949 | if (retry > 4) | |
950 | retry = 4; | |
951 | ||
952 | if (fb_option & FIFOCTL_AUTO_FB_0) | |
953 | tx_rate = fallback_rate0[tx_rate][retry]; | |
954 | else if (fb_option & FIFOCTL_AUTO_FB_1) | |
955 | tx_rate = fallback_rate1[tx_rate][retry]; | |
956 | ||
957 | if (info->band == IEEE80211_BAND_5GHZ) | |
958 | idx = tx_rate - RATE_6M; | |
959 | else | |
960 | idx = tx_rate; | |
961 | } | |
962 | ||
963 | ieee80211_tx_info_clear_status(info); | |
964 | ||
965 | info->status.rates[0].count = tx_retry; | |
966 | ||
967 | if (!(tsr1 & TSR1_TERR)) { | |
968 | info->status.rates[0].idx = idx; | |
969 | info->flags |= IEEE80211_TX_STAT_ACK; | |
970 | } | |
971 | ||
972 | return 0; | |
973 | } | |
974 | ||
3f8597f4 | 975 | static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx) |
84b50762 | 976 | { |
915006cd | 977 | PSTxDesc pTD; |
915006cd JP |
978 | int works = 0; |
979 | unsigned char byTsr0; | |
980 | unsigned char byTsr1; | |
915006cd | 981 | |
915006cd | 982 | for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) { |
915006cd JP |
983 | if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC) |
984 | break; | |
985 | if (works++ > 15) | |
986 | break; | |
987 | ||
988 | byTsr0 = pTD->m_td0TD0.byTSR0; | |
989 | byTsr1 = pTD->m_td0TD0.byTSR1; | |
990 | ||
991 | //Only the status of first TD in the chain is correct | |
992 | if (pTD->m_td1TD1.byTCR & TCR_STP) { | |
915006cd | 993 | if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) { |
59918bea MP |
994 | |
995 | vnt_int_report_rate(pDevice, pTD->pTDInfo, byTsr0, byTsr1); | |
915006cd JP |
996 | |
997 | if (!(byTsr1 & TSR1_TERR)) { | |
998 | if (byTsr0 != 0) { | |
48caf5a0 JP |
999 | pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n", |
1000 | (int)uIdx, byTsr1, | |
1001 | byTsr0); | |
915006cd | 1002 | } |
5e0cc8a2 | 1003 | } else { |
48caf5a0 JP |
1004 | pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n", |
1005 | (int)uIdx, byTsr1, byTsr0); | |
915006cd JP |
1006 | } |
1007 | } | |
1008 | ||
1009 | if (byTsr1 & TSR1_TERR) { | |
1010 | if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) { | |
48caf5a0 JP |
1011 | pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n", |
1012 | (int)uIdx, byTsr1, byTsr0); | |
915006cd | 1013 | } |
915006cd JP |
1014 | } |
1015 | device_free_tx_buf(pDevice, pTD); | |
1016 | pDevice->iTDUsed[uIdx]--; | |
915006cd | 1017 | } |
915006cd JP |
1018 | } |
1019 | ||
915006cd JP |
1020 | pDevice->apTailTD[uIdx] = pTD; |
1021 | ||
1022 | return works; | |
5449c685 FB |
1023 | } |
1024 | ||
3f8597f4 | 1025 | static void device_error(struct vnt_private *pDevice, unsigned short status) |
84b50762 | 1026 | { |
915006cd | 1027 | if (status & ISR_FETALERR) { |
42f709ef MP |
1028 | dev_err(&pDevice->pcid->dev, "Hardware fatal error\n"); |
1029 | ||
915006cd JP |
1030 | MACbShutdown(pDevice->PortOffset); |
1031 | return; | |
1032 | } | |
5449c685 FB |
1033 | } |
1034 | ||
3f8597f4 | 1035 | static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc) |
84b50762 | 1036 | { |
915006cd JP |
1037 | PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo; |
1038 | struct sk_buff *skb = pTDInfo->skb; | |
5449c685 | 1039 | |
915006cd JP |
1040 | // pre-allocated buf_dma can't be unmapped. |
1041 | if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) { | |
1042 | pci_unmap_single(pDevice->pcid, pTDInfo->skb_dma, skb->len, | |
1043 | PCI_DMA_TODEVICE); | |
1044 | } | |
5449c685 | 1045 | |
59918bea MP |
1046 | if (pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) |
1047 | ieee80211_tx_status_irqsafe(pDevice->hw, skb); | |
1048 | else | |
915006cd | 1049 | dev_kfree_skb_irq(skb); |
5449c685 | 1050 | |
915006cd | 1051 | pTDInfo->skb_dma = 0; |
70ae543b | 1052 | pTDInfo->skb = NULL; |
915006cd | 1053 | pTDInfo->byFlags = 0; |
5449c685 FB |
1054 | } |
1055 | ||
84b50762 GC |
1056 | static irqreturn_t device_intr(int irq, void *dev_instance) |
1057 | { | |
e70abceb | 1058 | struct vnt_private *pDevice = dev_instance; |
915006cd JP |
1059 | int max_count = 0; |
1060 | unsigned long dwMIBCounter = 0; | |
915006cd JP |
1061 | unsigned char byOrgPageSel = 0; |
1062 | int handled = 0; | |
915006cd | 1063 | int ii = 0; |
6cff1f6a | 1064 | unsigned long flags; |
915006cd | 1065 | |
915006cd JP |
1066 | MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); |
1067 | ||
1068 | if (pDevice->dwIsr == 0) | |
1069 | return IRQ_RETVAL(handled); | |
1070 | ||
1071 | if (pDevice->dwIsr == 0xffffffff) { | |
48caf5a0 | 1072 | pr_debug("dwIsr = 0xffff\n"); |
915006cd JP |
1073 | return IRQ_RETVAL(handled); |
1074 | } | |
915006cd JP |
1075 | |
1076 | handled = 1; | |
1077 | MACvIntDisable(pDevice->PortOffset); | |
6cff1f6a MP |
1078 | |
1079 | spin_lock_irqsave(&pDevice->lock, flags); | |
915006cd JP |
1080 | |
1081 | //Make sure current page is 0 | |
1082 | VNSvInPortB(pDevice->PortOffset + MAC_REG_PAGE1SEL, &byOrgPageSel); | |
bc5cf656 | 1083 | if (byOrgPageSel == 1) |
915006cd | 1084 | MACvSelectPage0(pDevice->PortOffset); |
bc5cf656 | 1085 | else |
915006cd JP |
1086 | byOrgPageSel = 0; |
1087 | ||
1088 | MACvReadMIBCounter(pDevice->PortOffset, &dwMIBCounter); | |
1089 | // TBD.... | |
1090 | // Must do this after doing rx/tx, cause ISR bit is slow | |
1091 | // than RD/TD write back | |
1092 | // update ISR counter | |
1093 | STAvUpdate802_11Counter(&pDevice->s802_11Counter, &pDevice->scStatistic , dwMIBCounter); | |
1094 | while (pDevice->dwIsr != 0) { | |
915006cd JP |
1095 | STAvUpdateIsrStatCounter(&pDevice->scStatistic, pDevice->dwIsr); |
1096 | MACvWriteISR(pDevice->PortOffset, pDevice->dwIsr); | |
1097 | ||
1098 | if (pDevice->dwIsr & ISR_FETALERR) { | |
48caf5a0 | 1099 | pr_debug(" ISR_FETALERR\n"); |
915006cd JP |
1100 | VNSvOutPortB(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, 0); |
1101 | VNSvOutPortW(pDevice->PortOffset + MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPECTI); | |
1102 | device_error(pDevice, pDevice->dwIsr); | |
1103 | } | |
1104 | ||
915006cd | 1105 | if (pDevice->dwIsr & ISR_TBTT) { |
59918bea MP |
1106 | if (pDevice->vif && |
1107 | pDevice->op_mode != NL80211_IFTYPE_ADHOC) { | |
1108 | if (pDevice->bUpdateBBVGA && | |
d855802b | 1109 | !(pDevice->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) && |
59918bea MP |
1110 | pDevice->vif->bss_conf.assoc && |
1111 | pDevice->uCurrRSSI) { | |
915006cd JP |
1112 | long ldBm; |
1113 | ||
1114 | RFvRSSITodBm(pDevice, (unsigned char) pDevice->uCurrRSSI, &ldBm); | |
1115 | for (ii = 0; ii < BB_VGA_LEVEL; ii++) { | |
1116 | if (ldBm < pDevice->ldBmThreshold[ii]) { | |
1117 | pDevice->byBBVGANew = pDevice->abyBBVGA[ii]; | |
1118 | break; | |
1119 | } | |
1120 | } | |
1121 | if (pDevice->byBBVGANew != pDevice->byBBVGACurrent) { | |
1122 | pDevice->uBBVGADiffCount++; | |
1123 | if (pDevice->uBBVGADiffCount == 1) { | |
1124 | // first VGA diff gain | |
1125 | BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); | |
48caf5a0 JP |
1126 | pr_debug("First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", |
1127 | (int)ldBm, | |
1128 | pDevice->byBBVGANew, | |
1129 | pDevice->byBBVGACurrent, | |
1130 | (int)pDevice->uBBVGADiffCount); | |
915006cd JP |
1131 | } |
1132 | if (pDevice->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) { | |
48caf5a0 JP |
1133 | pr_debug("RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n", |
1134 | (int)ldBm, | |
1135 | pDevice->byBBVGANew, | |
1136 | pDevice->byBBVGACurrent, | |
1137 | (int)pDevice->uBBVGADiffCount); | |
915006cd JP |
1138 | BBvSetVGAGainOffset(pDevice, pDevice->byBBVGANew); |
1139 | } | |
1140 | } else { | |
1141 | pDevice->uBBVGADiffCount = 1; | |
1142 | } | |
1143 | } | |
1144 | } | |
1145 | ||
1146 | pDevice->bBeaconSent = false; | |
bc5cf656 | 1147 | if (pDevice->bEnablePSMode) |
915006cd | 1148 | PSbIsNextTBTTWakeUp((void *)pDevice); |
915006cd | 1149 | |
e70abceb MP |
1150 | if ((pDevice->op_mode == NL80211_IFTYPE_AP || |
1151 | pDevice->op_mode == NL80211_IFTYPE_ADHOC) && | |
1152 | pDevice->vif->bss_conf.enable_beacon) { | |
915006cd | 1153 | MACvOneShotTimer1MicroSec(pDevice->PortOffset, |
e70abceb | 1154 | (pDevice->vif->bss_conf.beacon_int - MAKE_BEACON_RESERVED) << 10); |
915006cd JP |
1155 | } |
1156 | ||
4e8a7e5f | 1157 | /* TODO: adhoc PS mode */ |
915006cd JP |
1158 | |
1159 | } | |
1160 | ||
1161 | if (pDevice->dwIsr & ISR_BNTX) { | |
a9873673 | 1162 | if (pDevice->op_mode == NL80211_IFTYPE_ADHOC) { |
915006cd JP |
1163 | pDevice->bIsBeaconBufReadySet = false; |
1164 | pDevice->cbBeaconBufReadySetCnt = 0; | |
1165 | } | |
1166 | ||
915006cd | 1167 | pDevice->bBeaconSent = true; |
915006cd JP |
1168 | } |
1169 | ||
bc5cf656 | 1170 | if (pDevice->dwIsr & ISR_RXDMA0) |
915006cd | 1171 | max_count += device_rx_srv(pDevice, TYPE_RXDMA0); |
bc5cf656 GM |
1172 | |
1173 | if (pDevice->dwIsr & ISR_RXDMA1) | |
915006cd | 1174 | max_count += device_rx_srv(pDevice, TYPE_RXDMA1); |
bc5cf656 GM |
1175 | |
1176 | if (pDevice->dwIsr & ISR_TXDMA0) | |
915006cd | 1177 | max_count += device_tx_srv(pDevice, TYPE_TXDMA0); |
bc5cf656 GM |
1178 | |
1179 | if (pDevice->dwIsr & ISR_AC0DMA) | |
915006cd | 1180 | max_count += device_tx_srv(pDevice, TYPE_AC0DMA); |
bc5cf656 | 1181 | |
915006cd | 1182 | if (pDevice->dwIsr & ISR_SOFTTIMER1) { |
e70abceb MP |
1183 | if (pDevice->vif) { |
1184 | if (pDevice->vif->bss_conf.enable_beacon) | |
1185 | vnt_beacon_make(pDevice, pDevice->vif); | |
915006cd | 1186 | } |
915006cd JP |
1187 | } |
1188 | ||
54fbb2da MP |
1189 | /* If both buffers available wake the queue */ |
1190 | if (pDevice->vif) { | |
1191 | if (AVAIL_TD(pDevice, TYPE_TXDMA0) && | |
1192 | AVAIL_TD(pDevice, TYPE_AC0DMA) && | |
1193 | ieee80211_queue_stopped(pDevice->hw, 0)) | |
1194 | ieee80211_wake_queues(pDevice->hw); | |
1195 | } | |
1196 | ||
915006cd JP |
1197 | MACvReadISR(pDevice->PortOffset, &pDevice->dwIsr); |
1198 | ||
1199 | MACvReceive0(pDevice->PortOffset); | |
1200 | MACvReceive1(pDevice->PortOffset); | |
1201 | ||
1202 | if (max_count > pDevice->sOpts.int_works) | |
1203 | break; | |
1204 | } | |
1205 | ||
bc5cf656 | 1206 | if (byOrgPageSel == 1) |
915006cd | 1207 | MACvSelectPage1(pDevice->PortOffset); |
915006cd | 1208 | |
6cff1f6a MP |
1209 | spin_unlock_irqrestore(&pDevice->lock, flags); |
1210 | ||
915006cd JP |
1211 | MACvIntEnable(pDevice->PortOffset, IMR_MASK_VALUE); |
1212 | ||
1213 | return IRQ_RETVAL(handled); | |
5449c685 | 1214 | } |
915006cd | 1215 | |
67013f2c MP |
1216 | static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb) |
1217 | { | |
1218 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | |
1219 | PSTxDesc head_td; | |
1220 | u32 dma_idx = TYPE_AC0DMA; | |
1221 | unsigned long flags; | |
1222 | ||
1223 | spin_lock_irqsave(&priv->lock, flags); | |
1224 | ||
1225 | if (!ieee80211_is_data(hdr->frame_control)) | |
1226 | dma_idx = TYPE_TXDMA0; | |
1227 | ||
1228 | if (AVAIL_TD(priv, dma_idx) < 1) { | |
1229 | spin_unlock_irqrestore(&priv->lock, flags); | |
1230 | return -ENOMEM; | |
1231 | } | |
1232 | ||
1233 | head_td = priv->apCurrTD[dma_idx]; | |
1234 | ||
1235 | head_td->m_td1TD1.byTCR = (TCR_EDP|TCR_STP); | |
1236 | ||
1237 | head_td->pTDInfo->skb = skb; | |
1238 | ||
1239 | priv->iTDUsed[dma_idx]++; | |
1240 | ||
1241 | /* Take ownership */ | |
1242 | wmb(); | |
1243 | head_td->m_td0TD0.f1Owner = OWNED_BY_NIC; | |
1244 | ||
1245 | /* get Next */ | |
1246 | wmb(); | |
1247 | priv->apCurrTD[dma_idx] = head_td->next; | |
1248 | ||
1249 | spin_unlock_irqrestore(&priv->lock, flags); | |
1250 | ||
1251 | vnt_generate_fifo_header(priv, dma_idx, head_td, skb); | |
1252 | ||
1253 | if (MACbIsRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PS)) | |
1254 | MACbPSWakeup(priv->PortOffset); | |
1255 | ||
1256 | spin_lock_irqsave(&priv->lock, flags); | |
1257 | ||
1258 | priv->bPWBitOn = false; | |
1259 | ||
1260 | head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB; | |
1261 | ||
1262 | if (dma_idx == TYPE_AC0DMA) | |
1263 | MACvTransmitAC0(priv->PortOffset); | |
1264 | else | |
1265 | MACvTransmit0(priv->PortOffset); | |
1266 | ||
1267 | spin_unlock_irqrestore(&priv->lock, flags); | |
1268 | ||
1269 | return 0; | |
1270 | } | |
1271 | ||
1272 | static void vnt_tx_80211(struct ieee80211_hw *hw, | |
1273 | struct ieee80211_tx_control *control, | |
1274 | struct sk_buff *skb) | |
1275 | { | |
1276 | struct vnt_private *priv = hw->priv; | |
1277 | ||
1278 | ieee80211_stop_queues(hw); | |
1279 | ||
1280 | if (vnt_tx_packet(priv, skb)) { | |
1281 | ieee80211_free_txskb(hw, skb); | |
1282 | ||
1283 | ieee80211_wake_queues(hw); | |
1284 | } | |
1285 | } | |
1286 | ||
1287 | static int vnt_start(struct ieee80211_hw *hw) | |
1288 | { | |
1289 | struct vnt_private *priv = hw->priv; | |
1290 | int ret; | |
1291 | ||
1292 | priv->rx_buf_sz = PKT_BUF_SZ; | |
1293 | if (!device_init_rings(priv)) | |
1294 | return -ENOMEM; | |
1295 | ||
1296 | ret = request_irq(priv->pcid->irq, &device_intr, | |
1297 | IRQF_SHARED, "vt6655", priv); | |
1298 | if (ret) { | |
1299 | dev_dbg(&priv->pcid->dev, "failed to start irq\n"); | |
1300 | return ret; | |
1301 | } | |
1302 | ||
1303 | dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n"); | |
1304 | device_init_rd0_ring(priv); | |
1305 | device_init_rd1_ring(priv); | |
67013f2c MP |
1306 | device_init_td0_ring(priv); |
1307 | device_init_td1_ring(priv); | |
1308 | ||
1309 | device_init_registers(priv); | |
1310 | ||
1311 | dev_dbg(&priv->pcid->dev, "call MACvIntEnable\n"); | |
1312 | MACvIntEnable(priv->PortOffset, IMR_MASK_VALUE); | |
1313 | ||
1314 | ieee80211_wake_queues(hw); | |
1315 | ||
1316 | return 0; | |
1317 | } | |
1318 | ||
1319 | static void vnt_stop(struct ieee80211_hw *hw) | |
1320 | { | |
1321 | struct vnt_private *priv = hw->priv; | |
1322 | ||
1323 | ieee80211_stop_queues(hw); | |
1324 | ||
1325 | MACbShutdown(priv->PortOffset); | |
1326 | MACbSoftwareReset(priv->PortOffset); | |
1327 | CARDbRadioPowerOff(priv); | |
1328 | ||
1329 | device_free_td0_ring(priv); | |
1330 | device_free_td1_ring(priv); | |
1331 | device_free_rd0_ring(priv); | |
1332 | device_free_rd1_ring(priv); | |
67013f2c MP |
1333 | device_free_rings(priv); |
1334 | ||
1335 | free_irq(priv->pcid->irq, priv); | |
1336 | } | |
1337 | ||
1338 | static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1339 | { | |
1340 | struct vnt_private *priv = hw->priv; | |
1341 | ||
1342 | priv->vif = vif; | |
1343 | ||
1344 | switch (vif->type) { | |
1345 | case NL80211_IFTYPE_STATION: | |
1346 | if (priv->bDiversityRegCtlON) | |
1347 | device_init_diversity_timer(priv); | |
1348 | break; | |
1349 | case NL80211_IFTYPE_ADHOC: | |
1350 | MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST); | |
1351 | ||
1352 | MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC); | |
1353 | ||
1354 | break; | |
1355 | case NL80211_IFTYPE_AP: | |
1356 | MACvRegBitsOff(priv->PortOffset, MAC_REG_RCR, RCR_UNICAST); | |
1357 | ||
1358 | MACvRegBitsOn(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP); | |
1359 | ||
1360 | break; | |
1361 | default: | |
1362 | return -EOPNOTSUPP; | |
1363 | } | |
1364 | ||
1365 | priv->op_mode = vif->type; | |
1366 | ||
1367 | return 0; | |
1368 | } | |
1369 | ||
1370 | static void vnt_remove_interface(struct ieee80211_hw *hw, | |
1371 | struct ieee80211_vif *vif) | |
1372 | { | |
1373 | struct vnt_private *priv = hw->priv; | |
1374 | ||
1375 | switch (vif->type) { | |
1376 | case NL80211_IFTYPE_STATION: | |
1377 | if (priv->bDiversityRegCtlON) { | |
1378 | del_timer(&priv->TimerSQ3Tmax1); | |
1379 | del_timer(&priv->TimerSQ3Tmax2); | |
1380 | del_timer(&priv->TimerSQ3Tmax3); | |
1381 | } | |
1382 | break; | |
1383 | case NL80211_IFTYPE_ADHOC: | |
1384 | MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1385 | MACvRegBitsOff(priv->PortOffset, | |
1386 | MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
1387 | MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_ADHOC); | |
1388 | break; | |
1389 | case NL80211_IFTYPE_AP: | |
1390 | MACvRegBitsOff(priv->PortOffset, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1391 | MACvRegBitsOff(priv->PortOffset, | |
1392 | MAC_REG_TFTCTL, TFTCTL_TSFCNTREN); | |
1393 | MACvRegBitsOff(priv->PortOffset, MAC_REG_HOSTCR, HOSTCR_AP); | |
1394 | break; | |
1395 | default: | |
1396 | break; | |
1397 | } | |
1398 | ||
1399 | priv->op_mode = NL80211_IFTYPE_UNSPECIFIED; | |
1400 | } | |
1401 | ||
1402 | ||
1403 | static int vnt_config(struct ieee80211_hw *hw, u32 changed) | |
1404 | { | |
1405 | struct vnt_private *priv = hw->priv; | |
1406 | struct ieee80211_conf *conf = &hw->conf; | |
1407 | u8 bb_type; | |
1408 | ||
1409 | if (changed & IEEE80211_CONF_CHANGE_PS) { | |
1410 | if (conf->flags & IEEE80211_CONF_PS) | |
1411 | PSvEnablePowerSaving(priv, conf->listen_interval); | |
1412 | else | |
1413 | PSvDisablePowerSaving(priv); | |
1414 | } | |
1415 | ||
1416 | if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || | |
1417 | (conf->flags & IEEE80211_CONF_OFFCHANNEL)) { | |
1418 | set_channel(priv, conf->chandef.chan->hw_value); | |
1419 | ||
1420 | if (conf->chandef.chan->band == IEEE80211_BAND_5GHZ) | |
1421 | bb_type = BB_TYPE_11A; | |
1422 | else | |
1423 | bb_type = BB_TYPE_11G; | |
1424 | ||
1425 | if (priv->byBBType != bb_type) { | |
1426 | priv->byBBType = bb_type; | |
1427 | ||
bfb6c863 | 1428 | CARDbSetPhyParameter(priv, priv->byBBType); |
67013f2c MP |
1429 | } |
1430 | } | |
1431 | ||
1432 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | |
1433 | if (priv->byBBType == BB_TYPE_11B) | |
1434 | priv->wCurrentRate = RATE_1M; | |
1435 | else | |
1436 | priv->wCurrentRate = RATE_54M; | |
1437 | ||
1438 | RFbSetPower(priv, priv->wCurrentRate, | |
1439 | conf->chandef.chan->hw_value); | |
1440 | } | |
1441 | ||
1442 | return 0; | |
1443 | } | |
1444 | ||
1445 | static void vnt_bss_info_changed(struct ieee80211_hw *hw, | |
1446 | struct ieee80211_vif *vif, struct ieee80211_bss_conf *conf, | |
1447 | u32 changed) | |
1448 | { | |
1449 | struct vnt_private *priv = hw->priv; | |
1450 | ||
1451 | priv->current_aid = conf->aid; | |
1452 | ||
1453 | if (changed & BSS_CHANGED_BSSID) | |
1454 | MACvWriteBSSIDAddress(priv->PortOffset, (u8 *)conf->bssid); | |
1455 | ||
1456 | if (changed & BSS_CHANGED_BASIC_RATES) { | |
1457 | priv->basic_rates = conf->basic_rates; | |
1458 | ||
1459 | CARDvUpdateBasicTopRate(priv); | |
1460 | ||
1461 | dev_dbg(&priv->pcid->dev, | |
1462 | "basic rates %x\n", conf->basic_rates); | |
1463 | } | |
1464 | ||
1465 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | |
1466 | if (conf->use_short_preamble) { | |
1467 | MACvEnableBarkerPreambleMd(priv->PortOffset); | |
1468 | priv->byPreambleType = true; | |
1469 | } else { | |
1470 | MACvDisableBarkerPreambleMd(priv->PortOffset); | |
1471 | priv->byPreambleType = false; | |
1472 | } | |
1473 | } | |
1474 | ||
1475 | if (changed & BSS_CHANGED_ERP_CTS_PROT) { | |
1476 | if (conf->use_cts_prot) | |
1477 | MACvEnableProtectMD(priv->PortOffset); | |
1478 | else | |
1479 | MACvDisableProtectMD(priv->PortOffset); | |
1480 | } | |
1481 | ||
1482 | if (changed & BSS_CHANGED_ERP_SLOT) { | |
1483 | if (conf->use_short_slot) | |
1484 | priv->bShortSlotTime = true; | |
1485 | else | |
1486 | priv->bShortSlotTime = false; | |
1487 | ||
1488 | vUpdateIFS(priv); | |
bfb6c863 | 1489 | CARDbSetPhyParameter(priv, priv->byBBType); |
67013f2c MP |
1490 | BBvSetVGAGainOffset(priv, priv->abyBBVGA[0]); |
1491 | } | |
1492 | ||
1493 | if (changed & BSS_CHANGED_TXPOWER) | |
1494 | RFbSetPower(priv, priv->wCurrentRate, | |
1495 | conf->chandef.chan->hw_value); | |
1496 | ||
1497 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | |
1498 | dev_dbg(&priv->pcid->dev, | |
1499 | "Beacon enable %d\n", conf->enable_beacon); | |
1500 | ||
1501 | if (conf->enable_beacon) { | |
1502 | vnt_beacon_enable(priv, vif, conf); | |
1503 | ||
1504 | MACvRegBitsOn(priv, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1505 | } else { | |
1506 | MACvRegBitsOff(priv, MAC_REG_TCR, TCR_AUTOBCNTX); | |
1507 | } | |
1508 | } | |
1509 | ||
1510 | if (changed & BSS_CHANGED_ASSOC && priv->op_mode != NL80211_IFTYPE_AP) { | |
1511 | if (conf->assoc) { | |
1512 | CARDbUpdateTSF(priv, conf->beacon_rate->hw_value, | |
1513 | conf->sync_device_ts, conf->sync_tsf); | |
1514 | ||
1515 | CARDbSetBeaconPeriod(priv, conf->beacon_int); | |
1516 | ||
1517 | CARDvSetFirstNextTBTT(priv->PortOffset, | |
1518 | conf->beacon_int); | |
c7b14ea0 MP |
1519 | } else { |
1520 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, | |
1521 | TFTCTL_TSFCNTRST); | |
1522 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, | |
1523 | TFTCTL_TSFCNTREN); | |
67013f2c MP |
1524 | } |
1525 | } | |
1526 | } | |
1527 | ||
1528 | static u64 vnt_prepare_multicast(struct ieee80211_hw *hw, | |
1529 | struct netdev_hw_addr_list *mc_list) | |
1530 | { | |
1531 | struct vnt_private *priv = hw->priv; | |
1532 | struct netdev_hw_addr *ha; | |
1533 | u64 mc_filter = 0; | |
1534 | u32 bit_nr = 0; | |
1535 | ||
1536 | netdev_hw_addr_list_for_each(ha, mc_list) { | |
1537 | bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; | |
1538 | ||
1539 | mc_filter |= 1ULL << (bit_nr & 0x3f); | |
1540 | } | |
1541 | ||
1542 | priv->mc_list_count = mc_list->count; | |
1543 | ||
1544 | return mc_filter; | |
1545 | } | |
1546 | ||
1547 | static void vnt_configure(struct ieee80211_hw *hw, | |
1548 | unsigned int changed_flags, unsigned int *total_flags, u64 multicast) | |
1549 | { | |
1550 | struct vnt_private *priv = hw->priv; | |
1551 | u8 rx_mode = 0; | |
1552 | ||
1553 | *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_PROMISC_IN_BSS | | |
1554 | FIF_BCN_PRBRESP_PROMISC; | |
1555 | ||
1556 | VNSvInPortB(priv->PortOffset + MAC_REG_RCR, &rx_mode); | |
1557 | ||
1558 | dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode); | |
1559 | ||
1560 | if (changed_flags & FIF_PROMISC_IN_BSS) { | |
1561 | /* unconditionally log net taps */ | |
1562 | if (*total_flags & FIF_PROMISC_IN_BSS) | |
1563 | rx_mode |= RCR_UNICAST; | |
1564 | else | |
1565 | rx_mode &= ~RCR_UNICAST; | |
1566 | } | |
1567 | ||
1568 | if (changed_flags & FIF_ALLMULTI) { | |
1569 | if (*total_flags & FIF_ALLMULTI) { | |
1570 | if (priv->mc_list_count > 2) { | |
1571 | MACvSelectPage1(priv->PortOffset); | |
1572 | ||
1573 | VNSvOutPortD(priv->PortOffset + | |
1574 | MAC_REG_MAR0, 0xffffffff); | |
1575 | VNSvOutPortD(priv->PortOffset + | |
1576 | MAC_REG_MAR0 + 4, 0xffffffff); | |
1577 | ||
1578 | MACvSelectPage0(priv->PortOffset); | |
1579 | } else { | |
1580 | MACvSelectPage1(priv->PortOffset); | |
1581 | ||
1582 | VNSvOutPortD(priv->PortOffset + | |
1583 | MAC_REG_MAR0, (u32)multicast); | |
1584 | VNSvOutPortD(priv->PortOffset + | |
1585 | MAC_REG_MAR0 + 4, | |
1586 | (u32)(multicast >> 32)); | |
1587 | ||
1588 | MACvSelectPage0(priv->PortOffset); | |
1589 | } | |
1590 | ||
1591 | rx_mode |= RCR_MULTICAST | RCR_BROADCAST; | |
1592 | } else { | |
1593 | rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST); | |
1594 | } | |
1595 | } | |
1596 | ||
1597 | if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) { | |
1598 | rx_mode |= RCR_MULTICAST | RCR_BROADCAST; | |
1599 | ||
1600 | if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) | |
1601 | rx_mode &= ~RCR_BSSID; | |
1602 | else | |
1603 | rx_mode |= RCR_BSSID; | |
1604 | } | |
1605 | ||
1606 | VNSvOutPortB(priv->PortOffset + MAC_REG_RCR, rx_mode); | |
1607 | ||
1608 | dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode); | |
1609 | } | |
1610 | ||
1611 | static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |
1612 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | |
1613 | struct ieee80211_key_conf *key) | |
1614 | { | |
1615 | struct vnt_private *priv = hw->priv; | |
1616 | ||
1617 | switch (cmd) { | |
1618 | case SET_KEY: | |
1619 | if (vnt_set_keys(hw, sta, vif, key)) | |
1620 | return -EOPNOTSUPP; | |
1621 | break; | |
1622 | case DISABLE_KEY: | |
1623 | if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) | |
1624 | clear_bit(key->hw_key_idx, &priv->key_entry_inuse); | |
1625 | default: | |
1626 | break; | |
1627 | } | |
1628 | ||
1629 | return 0; | |
1630 | } | |
1631 | ||
1632 | static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1633 | { | |
1634 | struct vnt_private *priv = hw->priv; | |
1635 | u64 tsf; | |
1636 | ||
1637 | CARDbGetCurrentTSF(priv->PortOffset, &tsf); | |
1638 | ||
1639 | return tsf; | |
1640 | } | |
1641 | ||
1642 | static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |
1643 | u64 tsf) | |
1644 | { | |
1645 | struct vnt_private *priv = hw->priv; | |
1646 | ||
1647 | CARDvUpdateNextTBTT(priv->PortOffset, tsf, vif->bss_conf.beacon_int); | |
1648 | } | |
1649 | ||
1650 | static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |
1651 | { | |
1652 | struct vnt_private *priv = hw->priv; | |
1653 | ||
1654 | /* reset TSF counter */ | |
1655 | VNSvOutPortB(priv->PortOffset + MAC_REG_TFTCTL, TFTCTL_TSFCNTRST); | |
1656 | } | |
1657 | ||
1658 | static const struct ieee80211_ops vnt_mac_ops = { | |
1659 | .tx = vnt_tx_80211, | |
1660 | .start = vnt_start, | |
1661 | .stop = vnt_stop, | |
1662 | .add_interface = vnt_add_interface, | |
1663 | .remove_interface = vnt_remove_interface, | |
1664 | .config = vnt_config, | |
1665 | .bss_info_changed = vnt_bss_info_changed, | |
1666 | .prepare_multicast = vnt_prepare_multicast, | |
1667 | .configure_filter = vnt_configure, | |
1668 | .set_key = vnt_set_key, | |
1669 | .get_tsf = vnt_get_tsf, | |
1670 | .set_tsf = vnt_set_tsf, | |
1671 | .reset_tsf = vnt_reset_tsf, | |
1672 | }; | |
1673 | ||
1674 | int vnt_init(struct vnt_private *priv) | |
1675 | { | |
1676 | SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr); | |
1677 | ||
3d75b9e2 MP |
1678 | vnt_init_bands(priv); |
1679 | ||
67013f2c MP |
1680 | if (ieee80211_register_hw(priv->hw)) |
1681 | return -ENODEV; | |
1682 | ||
1683 | priv->mac_hw = true; | |
1684 | ||
1685 | CARDbRadioPowerOff(priv); | |
1686 | ||
1687 | return 0; | |
1688 | } | |
1689 | ||
1690 | static int | |
1691 | vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent) | |
1692 | { | |
1693 | PCHIP_INFO pChip_info = (PCHIP_INFO)ent->driver_data; | |
1694 | struct vnt_private *priv; | |
1695 | struct ieee80211_hw *hw; | |
1696 | struct wiphy *wiphy; | |
1697 | int rc; | |
1698 | ||
1699 | dev_notice(&pcid->dev, | |
1700 | "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION); | |
1701 | ||
1702 | dev_notice(&pcid->dev, | |
1703 | "Copyright (c) 2003 VIA Networking Technologies, Inc.\n"); | |
1704 | ||
1705 | hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops); | |
1706 | if (!hw) { | |
1707 | dev_err(&pcid->dev, "could not register ieee80211_hw\n"); | |
1708 | return -ENOMEM; | |
1709 | } | |
1710 | ||
1711 | priv = hw->priv; | |
1712 | ||
1713 | vt6655_init_info(pcid, &priv, pChip_info); | |
1714 | ||
1715 | priv->hw = hw; | |
1716 | ||
1717 | SET_IEEE80211_DEV(priv->hw, &pcid->dev); | |
1718 | ||
1719 | if (pci_enable_device(pcid)) { | |
1720 | device_free_info(priv); | |
1721 | return -ENODEV; | |
1722 | } | |
1723 | ||
1724 | dev_dbg(&pcid->dev, | |
1725 | "Before get pci_info memaddr is %x\n", priv->memaddr); | |
1726 | ||
1727 | if (!device_get_pci_info(priv, pcid)) { | |
1728 | dev_err(&pcid->dev, ": Failed to find PCI device.\n"); | |
1729 | device_free_info(priv); | |
1730 | return -ENODEV; | |
1731 | } | |
1732 | ||
1733 | #ifdef DEBUG | |
1734 | dev_dbg(&pcid->dev, | |
1735 | "after get pci_info memaddr is %x, io addr is %x,io_size is %d\n", | |
1736 | priv->memaddr, priv->ioaddr, priv->io_size); | |
1737 | { | |
1738 | int i; | |
1739 | u32 bar, len; | |
1740 | u32 address[] = { | |
1741 | PCI_BASE_ADDRESS_0, | |
1742 | PCI_BASE_ADDRESS_1, | |
1743 | PCI_BASE_ADDRESS_2, | |
1744 | PCI_BASE_ADDRESS_3, | |
1745 | PCI_BASE_ADDRESS_4, | |
1746 | PCI_BASE_ADDRESS_5, | |
1747 | 0}; | |
1748 | for (i = 0; address[i]; i++) { | |
1749 | pci_read_config_dword(pcid, address[i], &bar); | |
1750 | ||
1751 | dev_dbg(&pcid->dev, "bar %d is %x\n", i, bar); | |
1752 | ||
1753 | if (!bar) { | |
1754 | dev_dbg(&pcid->dev, | |
1755 | "bar %d not implemented\n", i); | |
1756 | continue; | |
1757 | } | |
1758 | ||
1759 | if (bar & PCI_BASE_ADDRESS_SPACE_IO) { | |
1760 | /* This is IO */ | |
1761 | ||
1762 | len = bar & (PCI_BASE_ADDRESS_IO_MASK & 0xffff); | |
1763 | len = len & ~(len - 1); | |
1764 | ||
1765 | dev_dbg(&pcid->dev, | |
1766 | "IO space: len in IO %x, BAR %d\n", | |
1767 | len, i); | |
1768 | } else { | |
1769 | len = bar & 0xfffffff0; | |
1770 | len = ~len + 1; | |
1771 | ||
1772 | dev_dbg(&pcid->dev, | |
1773 | "len in MEM %x, BAR %d\n", len, i); | |
1774 | } | |
1775 | } | |
1776 | } | |
1777 | #endif | |
1778 | ||
1779 | priv->PortOffset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK, | |
1780 | priv->io_size); | |
1781 | if (!priv->PortOffset) { | |
1782 | dev_err(&pcid->dev, ": Failed to IO remapping ..\n"); | |
1783 | device_free_info(priv); | |
1784 | return -ENODEV; | |
1785 | } | |
1786 | ||
1787 | rc = pci_request_regions(pcid, DEVICE_NAME); | |
1788 | if (rc) { | |
1789 | dev_err(&pcid->dev, ": Failed to find PCI device\n"); | |
1790 | device_free_info(priv); | |
1791 | return -ENODEV; | |
1792 | } | |
1793 | ||
1794 | /* do reset */ | |
1795 | if (!MACbSoftwareReset(priv->PortOffset)) { | |
1796 | dev_err(&pcid->dev, ": Failed to access MAC hardware..\n"); | |
1797 | device_free_info(priv); | |
1798 | return -ENODEV; | |
1799 | } | |
1800 | /* initial to reload eeprom */ | |
1801 | MACvInitialize(priv->PortOffset); | |
1802 | MACvReadEtherAddress(priv->PortOffset, priv->abyCurrentNetAddr); | |
1803 | ||
1804 | device_get_options(priv); | |
1805 | device_set_options(priv); | |
1806 | /* Mask out the options cannot be set to the chip */ | |
1807 | priv->sOpts.flags &= pChip_info->flags; | |
1808 | ||
1809 | /* Enable the chip specified capabilities */ | |
1810 | priv->flags = priv->sOpts.flags | (pChip_info->flags & 0xff000000UL); | |
67013f2c MP |
1811 | |
1812 | wiphy = priv->hw->wiphy; | |
1813 | ||
1814 | wiphy->frag_threshold = FRAG_THRESH_DEF; | |
1815 | wiphy->rts_threshold = RTS_THRESH_DEF; | |
1816 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | |
1817 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); | |
1818 | ||
1819 | priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | |
1820 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | |
1821 | IEEE80211_HW_SIGNAL_DBM | | |
1822 | IEEE80211_HW_TIMING_BEACON_ONLY; | |
1823 | ||
1824 | priv->hw->max_signal = 100; | |
1825 | ||
1826 | if (vnt_init(priv)) | |
1827 | return -ENODEV; | |
1828 | ||
1829 | device_print_info(priv); | |
1830 | pci_set_drvdata(pcid, priv); | |
1831 | ||
1832 | return 0; | |
1833 | } | |
1834 | ||
5449c685 | 1835 | /*------------------------------------------------------------------*/ |
5449c685 | 1836 | |
000fe0f5 MP |
1837 | #ifdef CONFIG_PM |
1838 | static int vt6655_suspend(struct pci_dev *pcid, pm_message_t state) | |
1839 | { | |
1840 | struct vnt_private *priv = pci_get_drvdata(pcid); | |
1841 | unsigned long flags; | |
1842 | ||
1843 | spin_lock_irqsave(&priv->lock, flags); | |
1844 | ||
1845 | pci_save_state(pcid); | |
1846 | ||
1847 | MACbShutdown(priv->PortOffset); | |
1848 | ||
1849 | pci_disable_device(pcid); | |
1850 | pci_set_power_state(pcid, pci_choose_state(pcid, state)); | |
1851 | ||
1852 | spin_unlock_irqrestore(&priv->lock, flags); | |
1853 | ||
1854 | return 0; | |
1855 | } | |
1856 | ||
1857 | static int vt6655_resume(struct pci_dev *pcid) | |
1858 | { | |
1859 | ||
1860 | pci_set_power_state(pcid, PCI_D0); | |
1861 | pci_enable_wake(pcid, PCI_D0, 0); | |
1862 | pci_restore_state(pcid); | |
1863 | ||
1864 | return 0; | |
1865 | } | |
1866 | #endif | |
1867 | ||
013a468c | 1868 | MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table); |
5449c685 FB |
1869 | |
1870 | static struct pci_driver device_driver = { | |
34381c22 PH |
1871 | .name = DEVICE_NAME, |
1872 | .id_table = vt6655_pci_id_table, | |
1873 | .probe = vt6655_probe, | |
1874 | .remove = vt6655_remove, | |
5449c685 | 1875 | #ifdef CONFIG_PM |
000fe0f5 MP |
1876 | .suspend = vt6655_suspend, |
1877 | .resume = vt6655_resume, | |
5449c685 | 1878 | #endif |
5449c685 FB |
1879 | }; |
1880 | ||
013a468c | 1881 | static int __init vt6655_init_module(void) |
5449c685 | 1882 | { |
915006cd | 1883 | int ret; |
5449c685 | 1884 | |
5449c685 | 1885 | ret = pci_register_driver(&device_driver); |
5449c685 | 1886 | #ifdef CONFIG_PM |
915006cd JP |
1887 | if (ret >= 0) |
1888 | register_reboot_notifier(&device_notifier); | |
5449c685 FB |
1889 | #endif |
1890 | ||
915006cd | 1891 | return ret; |
5449c685 FB |
1892 | } |
1893 | ||
013a468c | 1894 | static void __exit vt6655_cleanup_module(void) |
5449c685 | 1895 | { |
5449c685 | 1896 | #ifdef CONFIG_PM |
915006cd | 1897 | unregister_reboot_notifier(&device_notifier); |
5449c685 | 1898 | #endif |
915006cd | 1899 | pci_unregister_driver(&device_driver); |
5449c685 FB |
1900 | } |
1901 | ||
013a468c CC |
1902 | module_init(vt6655_init_module); |
1903 | module_exit(vt6655_cleanup_module); | |
5449c685 | 1904 | |
5449c685 FB |
1905 | #ifdef CONFIG_PM |
1906 | static int | |
1907 | device_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) | |
1908 | { | |
915006cd | 1909 | struct pci_dev *pdev = NULL; |
6b711271 | 1910 | |
915006cd JP |
1911 | switch (event) { |
1912 | case SYS_DOWN: | |
1913 | case SYS_HALT: | |
1914 | case SYS_POWER_OFF: | |
1915 | for_each_pci_dev(pdev) { | |
1916 | if (pci_dev_driver(pdev) == &device_driver) { | |
1917 | if (pci_get_drvdata(pdev)) | |
000fe0f5 | 1918 | vt6655_suspend(pdev, PMSG_HIBERNATE); |
915006cd JP |
1919 | } |
1920 | } | |
1921 | } | |
1922 | return NOTIFY_DONE; | |
5449c685 | 1923 | } |
5449c685 | 1924 | #endif |