1 | /* |
2 | * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting |
3 | * Copyright (c) 2002-2004 Atheros Communications, Inc. |
4 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. |
8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | * |
17 | * $Id: ar5210_misc.c,v 1.2 2011/03/07 11:25:42 cegger Exp $ |
18 | */ |
19 | #include "opt_ah.h" |
20 | |
21 | #include "ah.h" |
22 | #include "ah_internal.h" |
23 | |
24 | #include "ar5210/ar5210.h" |
25 | #include "ar5210/ar5210reg.h" |
26 | #include "ar5210/ar5210phy.h" |
27 | |
28 | #include "ah_eeprom_v1.h" |
29 | |
30 | #define AR_NUM_GPIO 6 /* 6 GPIO bits */ |
31 | #define AR_GPIOD_MASK 0x2f /* 6-bit mask */ |
32 | |
33 | void |
34 | ar5210GetMacAddress(struct ath_hal *ah, uint8_t *mac) |
35 | { |
36 | struct ath_hal_5210 *ahp = AH5210(ah); |
37 | |
38 | OS_MEMCPY(mac, ahp->ah_macaddr, IEEE80211_ADDR_LEN); |
39 | } |
40 | |
41 | HAL_BOOL |
42 | ar5210SetMacAddress(struct ath_hal *ah, const uint8_t *mac) |
43 | { |
44 | struct ath_hal_5210 *ahp = AH5210(ah); |
45 | |
46 | OS_MEMCPY(ahp->ah_macaddr, mac, IEEE80211_ADDR_LEN); |
47 | return AH_TRUE; |
48 | } |
49 | |
50 | void |
51 | ar5210GetBssIdMask(struct ath_hal *ah, uint8_t *mask) |
52 | { |
53 | static const uint8_t ones[IEEE80211_ADDR_LEN] = |
54 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
55 | OS_MEMCPY(mask, ones, IEEE80211_ADDR_LEN); |
56 | } |
57 | |
58 | HAL_BOOL |
59 | ar5210SetBssIdMask(struct ath_hal *ah, const uint8_t *mask) |
60 | { |
61 | return AH_FALSE; |
62 | } |
63 | |
64 | /* |
65 | * Read 16 bits of data from the specified EEPROM offset. |
66 | */ |
67 | HAL_BOOL |
68 | ar5210EepromRead(struct ath_hal *ah, u_int off, uint16_t *data) |
69 | { |
70 | (void) OS_REG_READ(ah, AR_EP_AIR(off)); /* activate read op */ |
71 | if (!ath_hal_wait(ah, AR_EP_STA, |
72 | AR_EP_STA_RDCMPLT | AR_EP_STA_RDERR, AR_EP_STA_RDCMPLT)) { |
73 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: read failed for entry 0x%x\n" , |
74 | __func__, AR_EP_AIR(off)); |
75 | return AH_FALSE; |
76 | } |
77 | *data = OS_REG_READ(ah, AR_EP_RDATA) & 0xffff; |
78 | return AH_TRUE; |
79 | } |
80 | |
81 | #ifdef AH_SUPPORT_WRITE_EEPROM |
82 | /* |
83 | * Write 16 bits of data to the specified EEPROM offset. |
84 | */ |
85 | HAL_BOOL |
86 | ar5210EepromWrite(struct ath_hal *ah, u_int off, uint16_t data) |
87 | { |
88 | return AH_FALSE; |
89 | } |
90 | #endif /* AH_SUPPORT_WRITE_EEPROM */ |
91 | |
92 | /* |
93 | * Attempt to change the cards operating regulatory domain to the given value |
94 | */ |
95 | HAL_BOOL |
96 | ar5210SetRegulatoryDomain(struct ath_hal *ah, |
97 | uint16_t regDomain, HAL_STATUS *status) |
98 | { |
99 | HAL_STATUS ecode; |
100 | |
101 | if (AH_PRIVATE(ah)->ah_currentRD == regDomain) { |
102 | ecode = HAL_EINVAL; |
103 | goto bad; |
104 | } |
105 | /* |
106 | * Check if EEPROM is configured to allow this; must |
107 | * be a proper version and the protection bits must |
108 | * permit re-writing that segment of the EEPROM. |
109 | */ |
110 | if (ath_hal_eepromGetFlag(ah, AR_EEP_WRITEPROTECT)) { |
111 | ecode = HAL_EEWRITE; |
112 | goto bad; |
113 | } |
114 | ecode = HAL_EIO; /* disallow all writes */ |
115 | bad: |
116 | if (status) |
117 | *status = ecode; |
118 | return AH_FALSE; |
119 | } |
120 | |
121 | /* |
122 | * Return the wireless modes (a,b,g,t) supported by hardware. |
123 | * |
124 | * This value is what is actually supported by the hardware |
125 | * and is unaffected by regulatory/country code settings. |
126 | * |
127 | */ |
128 | u_int |
129 | ar5210GetWirelessModes(struct ath_hal *ah) |
130 | { |
131 | /* XXX could enable turbo mode but can't do all rates */ |
132 | return HAL_MODE_11A; |
133 | } |
134 | |
135 | /* |
136 | * Called if RfKill is supported (according to EEPROM). Set the interrupt and |
137 | * GPIO values so the ISR and can disable RF on a switch signal |
138 | */ |
139 | void |
140 | ar5210EnableRfKill(struct ath_hal *ah) |
141 | { |
142 | uint16_t rfsilent = AH_PRIVATE(ah)->ah_rfsilent; |
143 | int select = MS(rfsilent, AR_EEPROM_RFSILENT_GPIO_SEL); |
144 | int polarity = MS(rfsilent, AR_EEPROM_RFSILENT_POLARITY); |
145 | |
146 | /* |
147 | * If radio disable switch connection to GPIO bit 0 is enabled |
148 | * program GPIO interrupt. |
149 | * If rfkill bit on eeprom is 1, setupeeprommap routine has already |
150 | * verified that it is a later version of eeprom, it has a place for |
151 | * rfkill bit and it is set to 1, indicating that GPIO bit 0 hardware |
152 | * connection is present. |
153 | */ |
154 | ar5210Gpio0SetIntr(ah, select, (ar5210GpioGet(ah, select) == polarity)); |
155 | } |
156 | |
157 | /* |
158 | * Configure GPIO Output lines |
159 | */ |
160 | HAL_BOOL |
161 | ar5210GpioCfgOutput(struct ath_hal *ah, uint32_t gpio, HAL_GPIO_MUX_TYPE type) |
162 | { |
163 | HALASSERT(gpio < AR_NUM_GPIO); |
164 | |
165 | OS_REG_WRITE(ah, AR_GPIOCR, |
166 | (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) |
167 | | AR_GPIOCR_OUT1(gpio)); |
168 | |
169 | return AH_TRUE; |
170 | } |
171 | |
172 | /* |
173 | * Configure GPIO Input lines |
174 | */ |
175 | HAL_BOOL |
176 | ar5210GpioCfgInput(struct ath_hal *ah, uint32_t gpio) |
177 | { |
178 | HALASSERT(gpio < AR_NUM_GPIO); |
179 | |
180 | OS_REG_WRITE(ah, AR_GPIOCR, |
181 | (OS_REG_READ(ah, AR_GPIOCR) &~ AR_GPIOCR_ALL(gpio)) |
182 | | AR_GPIOCR_IN(gpio)); |
183 | |
184 | return AH_TRUE; |
185 | } |
186 | |
187 | /* |
188 | * Once configured for I/O - set output lines |
189 | */ |
190 | HAL_BOOL |
191 | ar5210GpioSet(struct ath_hal *ah, uint32_t gpio, uint32_t val) |
192 | { |
193 | uint32_t reg; |
194 | |
195 | HALASSERT(gpio < AR_NUM_GPIO); |
196 | |
197 | reg = OS_REG_READ(ah, AR_GPIODO); |
198 | reg &= ~(1 << gpio); |
199 | reg |= (val&1) << gpio; |
200 | |
201 | OS_REG_WRITE(ah, AR_GPIODO, reg); |
202 | return AH_TRUE; |
203 | } |
204 | |
205 | /* |
206 | * Once configured for I/O - get input lines |
207 | */ |
208 | uint32_t |
209 | ar5210GpioGet(struct ath_hal *ah, uint32_t gpio) |
210 | { |
211 | if (gpio < AR_NUM_GPIO) { |
212 | uint32_t val = OS_REG_READ(ah, AR_GPIODI); |
213 | val = ((val & AR_GPIOD_MASK) >> gpio) & 0x1; |
214 | return val; |
215 | } else { |
216 | return 0xffffffff; |
217 | } |
218 | } |
219 | |
220 | /* |
221 | * Set the GPIO 0 Interrupt |
222 | */ |
223 | void |
224 | ar5210Gpio0SetIntr(struct ath_hal *ah, u_int gpio, uint32_t ilevel) |
225 | { |
226 | uint32_t val = OS_REG_READ(ah, AR_GPIOCR); |
227 | |
228 | /* Clear the bits that we will modify. */ |
229 | val &= ~(AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_SELH | AR_GPIOCR_INT_ENA | |
230 | AR_GPIOCR_ALL(gpio)); |
231 | |
232 | val |= AR_GPIOCR_INT_SEL(gpio) | AR_GPIOCR_INT_ENA; |
233 | if (ilevel) |
234 | val |= AR_GPIOCR_INT_SELH; |
235 | |
236 | /* Don't need to change anything for low level interrupt. */ |
237 | OS_REG_WRITE(ah, AR_GPIOCR, val); |
238 | |
239 | /* Change the interrupt mask. */ |
240 | ar5210SetInterrupts(ah, AH5210(ah)->ah_maskReg | HAL_INT_GPIO); |
241 | } |
242 | |
243 | /* |
244 | * Change the LED blinking pattern to correspond to the connectivity |
245 | */ |
246 | void |
247 | ar5210SetLedState(struct ath_hal *ah, HAL_LED_STATE state) |
248 | { |
249 | uint32_t val; |
250 | |
251 | val = OS_REG_READ(ah, AR_PCICFG); |
252 | switch (state) { |
253 | case HAL_LED_INIT: |
254 | val &= ~(AR_PCICFG_LED_PEND | AR_PCICFG_LED_ACT); |
255 | break; |
256 | case HAL_LED_RUN: |
257 | /* normal blink when connected */ |
258 | val &= ~AR_PCICFG_LED_PEND; |
259 | val |= AR_PCICFG_LED_ACT; |
260 | break; |
261 | default: |
262 | val |= AR_PCICFG_LED_PEND; |
263 | val &= ~AR_PCICFG_LED_ACT; |
264 | break; |
265 | } |
266 | OS_REG_WRITE(ah, AR_PCICFG, val); |
267 | } |
268 | |
269 | /* |
270 | * Return 1 or 2 for the corresponding antenna that is in use |
271 | */ |
272 | u_int |
273 | ar5210GetDefAntenna(struct ath_hal *ah) |
274 | { |
275 | uint32_t val = OS_REG_READ(ah, AR_STA_ID1); |
276 | return (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1); |
277 | } |
278 | |
279 | void |
280 | ar5210SetDefAntenna(struct ath_hal *ah, u_int antenna) |
281 | { |
282 | uint32_t val = OS_REG_READ(ah, AR_STA_ID1); |
283 | |
284 | if (antenna != (val & AR_STA_ID1_DEFAULT_ANTENNA ? 2 : 1)) { |
285 | /* |
286 | * Antenna change requested, force a toggle of the default. |
287 | */ |
288 | OS_REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_DEFAULT_ANTENNA); |
289 | } |
290 | } |
291 | |
292 | HAL_ANT_SETTING |
293 | ar5210GetAntennaSwitch(struct ath_hal *ah) |
294 | { |
295 | return HAL_ANT_VARIABLE; |
296 | } |
297 | |
298 | HAL_BOOL |
299 | ar5210SetAntennaSwitch(struct ath_hal *ah, HAL_ANT_SETTING settings) |
300 | { |
301 | /* XXX not sure how to fix antenna */ |
302 | return (settings == HAL_ANT_VARIABLE); |
303 | } |
304 | |
305 | /* |
306 | * Change association related fields programmed into the hardware. |
307 | * Writing a valid BSSID to the hardware effectively enables the hardware |
308 | * to synchronize its TSF to the correct beacons and receive frames coming |
309 | * from that BSSID. It is called by the SME JOIN operation. |
310 | */ |
311 | void |
312 | ar5210WriteAssocid(struct ath_hal *ah, const uint8_t *bssid, uint16_t assocId) |
313 | { |
314 | struct ath_hal_5210 *ahp = AH5210(ah); |
315 | |
316 | /* XXX save bssid for possible re-use on reset */ |
317 | OS_MEMCPY(ahp->ah_bssid, bssid, IEEE80211_ADDR_LEN); |
318 | OS_REG_WRITE(ah, AR_BSS_ID0, LE_READ_4(ahp->ah_bssid)); |
319 | OS_REG_WRITE(ah, AR_BSS_ID1, LE_READ_2(ahp->ah_bssid+4) | |
320 | ((assocId & 0x3fff)<<AR_BSS_ID1_AID_S)); |
321 | if (assocId == 0) |
322 | OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL); |
323 | else |
324 | OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_NO_PSPOLL); |
325 | } |
326 | |
327 | /* |
328 | * Get the current hardware tsf for stamlme. |
329 | */ |
330 | uint64_t |
331 | ar5210GetTsf64(struct ath_hal *ah) |
332 | { |
333 | uint32_t low1, low2, u32; |
334 | |
335 | /* sync multi-word read */ |
336 | low1 = OS_REG_READ(ah, AR_TSF_L32); |
337 | u32 = OS_REG_READ(ah, AR_TSF_U32); |
338 | low2 = OS_REG_READ(ah, AR_TSF_L32); |
339 | if (low2 < low1) { /* roll over */ |
340 | /* |
341 | * If we are not preempted this will work. If we are |
342 | * then we re-reading AR_TSF_U32 does no good as the |
343 | * low bits will be meaningless. Likewise reading |
344 | * L32, U32, U32, then comparing the last two reads |
345 | * to check for rollover doesn't help if preempted--so |
346 | * we take this approach as it costs one less PCI |
347 | * read which can be noticeable when doing things |
348 | * like timestamping packets in monitor mode. |
349 | */ |
350 | u32++; |
351 | } |
352 | return (((uint64_t) u32) << 32) | ((uint64_t) low2); |
353 | } |
354 | |
355 | /* |
356 | * Get the current hardware tsf for stamlme. |
357 | */ |
358 | uint32_t |
359 | ar5210GetTsf32(struct ath_hal *ah) |
360 | { |
361 | return OS_REG_READ(ah, AR_TSF_L32); |
362 | } |
363 | |
364 | /* |
365 | * Reset the current hardware tsf for stamlme |
366 | */ |
367 | void |
368 | ar5210ResetTsf(struct ath_hal *ah) |
369 | { |
370 | uint32_t val = OS_REG_READ(ah, AR_BEACON); |
371 | |
372 | OS_REG_WRITE(ah, AR_BEACON, val | AR_BEACON_RESET_TSF); |
373 | } |
374 | |
375 | /* |
376 | * Grab a semi-random value from hardware registers - may not |
377 | * change often |
378 | */ |
379 | uint32_t |
380 | ar5210GetRandomSeed(struct ath_hal *ah) |
381 | { |
382 | uint32_t nf; |
383 | |
384 | nf = (OS_REG_READ(ah, AR_PHY_BASE + (25 << 2)) >> 19) & 0x1ff; |
385 | if (nf & 0x100) |
386 | nf = 0 - ((nf ^ 0x1ff) + 1); |
387 | return (OS_REG_READ(ah, AR_TSF_U32) ^ |
388 | OS_REG_READ(ah, AR_TSF_L32) ^ nf); |
389 | } |
390 | |
391 | /* |
392 | * Detect if our card is present |
393 | */ |
394 | HAL_BOOL |
395 | ar5210DetectCardPresent(struct ath_hal *ah) |
396 | { |
397 | /* |
398 | * Read the Silicon Revision register and compare that |
399 | * to what we read at attach time. If the same, we say |
400 | * a card/device is present. |
401 | */ |
402 | return (AH_PRIVATE(ah)->ah_macRev == (OS_REG_READ(ah, AR_SREV) & 0xff)); |
403 | } |
404 | |
405 | /* |
406 | * Update MIB Counters |
407 | */ |
408 | void |
409 | ar5210UpdateMibCounters(struct ath_hal *ah, HAL_MIB_STATS *stats) |
410 | { |
411 | stats->ackrcv_bad += OS_REG_READ(ah, AR_ACK_FAIL); |
412 | stats->rts_bad += OS_REG_READ(ah, AR_RTS_FAIL); |
413 | stats->fcs_bad += OS_REG_READ(ah, AR_FCS_FAIL); |
414 | stats->rts_good += OS_REG_READ(ah, AR_RTS_OK); |
415 | stats->beacons += OS_REG_READ(ah, AR_BEACON_CNT); |
416 | } |
417 | |
418 | HAL_BOOL |
419 | ar5210SetSifsTime(struct ath_hal *ah, u_int us) |
420 | { |
421 | struct ath_hal_5210 *ahp = AH5210(ah); |
422 | |
423 | if (us > ath_hal_mac_usec(ah, 0x7ff)) { |
424 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad SIFS time %u\n" , |
425 | __func__, us); |
426 | ahp->ah_sifstime = (u_int) -1; /* restore default handling */ |
427 | return AH_FALSE; |
428 | } else { |
429 | /* convert to system clocks */ |
430 | OS_REG_RMW_FIELD(ah, AR_IFS0, AR_IFS0_SIFS, |
431 | ath_hal_mac_clks(ah, us)); |
432 | ahp->ah_sifstime = us; |
433 | return AH_TRUE; |
434 | } |
435 | } |
436 | |
437 | u_int |
438 | ar5210GetSifsTime(struct ath_hal *ah) |
439 | { |
440 | u_int clks = OS_REG_READ(ah, AR_IFS0) & 0x7ff; |
441 | return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ |
442 | } |
443 | |
444 | HAL_BOOL |
445 | ar5210SetSlotTime(struct ath_hal *ah, u_int us) |
446 | { |
447 | struct ath_hal_5210 *ahp = AH5210(ah); |
448 | |
449 | if (us < HAL_SLOT_TIME_9 || us > ath_hal_mac_usec(ah, 0xffff)) { |
450 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad slot time %u\n" , |
451 | __func__, us); |
452 | ahp->ah_slottime = (u_int) -1; /* restore default handling */ |
453 | return AH_FALSE; |
454 | } else { |
455 | /* convert to system clocks */ |
456 | OS_REG_WRITE(ah, AR_SLOT_TIME, ath_hal_mac_clks(ah, us)); |
457 | ahp->ah_slottime = us; |
458 | return AH_TRUE; |
459 | } |
460 | } |
461 | |
462 | u_int |
463 | ar5210GetSlotTime(struct ath_hal *ah) |
464 | { |
465 | u_int clks = OS_REG_READ(ah, AR_SLOT_TIME) & 0xffff; |
466 | return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ |
467 | } |
468 | |
469 | HAL_BOOL |
470 | ar5210SetAckTimeout(struct ath_hal *ah, u_int us) |
471 | { |
472 | struct ath_hal_5210 *ahp = AH5210(ah); |
473 | |
474 | if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { |
475 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad ack timeout %u\n" , |
476 | __func__, us); |
477 | ahp->ah_acktimeout = (u_int) -1; /* restore default handling */ |
478 | return AH_FALSE; |
479 | } else { |
480 | /* convert to system clocks */ |
481 | OS_REG_RMW_FIELD(ah, AR_TIME_OUT, |
482 | AR_TIME_OUT_ACK, ath_hal_mac_clks(ah, us)); |
483 | ahp->ah_acktimeout = us; |
484 | return AH_TRUE; |
485 | } |
486 | } |
487 | |
488 | u_int |
489 | ar5210GetAckTimeout(struct ath_hal *ah) |
490 | { |
491 | u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_ACK); |
492 | return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ |
493 | } |
494 | |
495 | u_int |
496 | ar5210GetAckCTSRate(struct ath_hal *ah) |
497 | { |
498 | return ((AH5210(ah)->ah_staId1Defaults & AR_STA_ID1_ACKCTS_6MB) == 0); |
499 | } |
500 | |
501 | HAL_BOOL |
502 | ar5210SetAckCTSRate(struct ath_hal *ah, u_int high) |
503 | { |
504 | struct ath_hal_5210 *ahp = AH5210(ah); |
505 | |
506 | if (high) { |
507 | OS_REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); |
508 | ahp->ah_staId1Defaults &= ~AR_STA_ID1_ACKCTS_6MB; |
509 | } else { |
510 | OS_REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_ACKCTS_6MB); |
511 | ahp->ah_staId1Defaults |= AR_STA_ID1_ACKCTS_6MB; |
512 | } |
513 | return AH_TRUE; |
514 | } |
515 | |
516 | HAL_BOOL |
517 | ar5210SetCTSTimeout(struct ath_hal *ah, u_int us) |
518 | { |
519 | struct ath_hal_5210 *ahp = AH5210(ah); |
520 | |
521 | if (us > ath_hal_mac_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { |
522 | HALDEBUG(ah, HAL_DEBUG_ANY, "%s: bad cts timeout %u\n" , |
523 | __func__, us); |
524 | ahp->ah_ctstimeout = (u_int) -1; /* restore default handling */ |
525 | return AH_FALSE; |
526 | } else { |
527 | /* convert to system clocks */ |
528 | OS_REG_RMW_FIELD(ah, AR_TIME_OUT, |
529 | AR_TIME_OUT_CTS, ath_hal_mac_clks(ah, us)); |
530 | ahp->ah_ctstimeout = us; |
531 | return AH_TRUE; |
532 | } |
533 | } |
534 | |
535 | u_int |
536 | ar5210GetCTSTimeout(struct ath_hal *ah) |
537 | { |
538 | u_int clks = MS(OS_REG_READ(ah, AR_TIME_OUT), AR_TIME_OUT_CTS); |
539 | return ath_hal_mac_usec(ah, clks); /* convert from system clocks */ |
540 | } |
541 | |
542 | HAL_BOOL |
543 | ar5210SetDecompMask(struct ath_hal *ah, uint16_t keyidx, int en) |
544 | { |
545 | /* nothing to do */ |
546 | return AH_TRUE; |
547 | } |
548 | |
549 | void |
550 | ar5210SetCoverageClass(struct ath_hal *ah, uint8_t coverageclass, int now) |
551 | { |
552 | } |
553 | |
554 | /* |
555 | * Control Adaptive Noise Immunity Parameters |
556 | */ |
557 | HAL_BOOL |
558 | ar5210AniControl(struct ath_hal *ah, HAL_ANI_CMD cmd, int param) |
559 | { |
560 | return AH_FALSE; |
561 | } |
562 | |
563 | void |
564 | ar5210AniPoll(struct ath_hal *ah, const HAL_NODE_STATS *stats, HAL_CHANNEL *chan) |
565 | { |
566 | } |
567 | |
568 | void |
569 | ar5210MibEvent(struct ath_hal *ah, const HAL_NODE_STATS *stats) |
570 | { |
571 | } |
572 | |
573 | #define AR_DIAG_SW_DIS_CRYPTO (AR_DIAG_SW_DIS_ENC | AR_DIAG_SW_DIS_DEC) |
574 | |
575 | HAL_STATUS |
576 | ar5210GetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, |
577 | uint32_t capability, uint32_t *result) |
578 | { |
579 | |
580 | switch (type) { |
581 | case HAL_CAP_CIPHER: /* cipher handled in hardware */ |
582 | return (capability == HAL_CIPHER_WEP ? HAL_OK : HAL_ENOTSUPP); |
583 | default: |
584 | return ath_hal_getcapability(ah, type, capability, result); |
585 | } |
586 | } |
587 | |
588 | HAL_BOOL |
589 | ar5210SetCapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type, |
590 | uint32_t capability, uint32_t setting, HAL_STATUS *status) |
591 | { |
592 | |
593 | switch (type) { |
594 | case HAL_CAP_DIAG: /* hardware diagnostic support */ |
595 | /* |
596 | * NB: could split this up into virtual capabilities, |
597 | * (e.g. 1 => ACK, 2 => CTS, etc.) but it hardly |
598 | * seems worth the additional complexity. |
599 | */ |
600 | #ifdef AH_DEBUG |
601 | AH_PRIVATE(ah)->ah_diagreg = setting; |
602 | #else |
603 | AH_PRIVATE(ah)->ah_diagreg = setting & 0x6; /* ACK+CTS */ |
604 | #endif |
605 | OS_REG_WRITE(ah, AR_DIAG_SW, AH_PRIVATE(ah)->ah_diagreg); |
606 | return AH_TRUE; |
607 | case HAL_CAP_RXORN_FATAL: /* HAL_INT_RXORN treated as fatal */ |
608 | return AH_FALSE; /* NB: disallow */ |
609 | default: |
610 | return ath_hal_setcapability(ah, type, capability, |
611 | setting, status); |
612 | } |
613 | } |
614 | |
615 | HAL_BOOL |
616 | ar5210GetDiagState(struct ath_hal *ah, int request, |
617 | const void *args, uint32_t argsize, |
618 | void **result, uint32_t *resultsize) |
619 | { |
620 | #ifdef AH_PRIVATE_DIAG |
621 | uint32_t pcicfg; |
622 | HAL_BOOL ok; |
623 | |
624 | switch (request) { |
625 | case HAL_DIAG_EEPROM: |
626 | /* XXX */ |
627 | break; |
628 | case HAL_DIAG_EEREAD: |
629 | if (argsize != sizeof(uint16_t)) |
630 | return AH_FALSE; |
631 | pcicfg = OS_REG_READ(ah, AR_PCICFG); |
632 | OS_REG_WRITE(ah, AR_PCICFG, pcicfg | AR_PCICFG_EEPROMSEL); |
633 | ok = ath_hal_eepromRead(ah, *(const uint16_t *)args, *result); |
634 | OS_REG_WRITE(ah, AR_PCICFG, pcicfg); |
635 | if (ok) |
636 | *resultsize = sizeof(uint16_t); |
637 | return ok; |
638 | } |
639 | #endif |
640 | return ath_hal_getdiagstate(ah, request, |
641 | args, argsize, result, resultsize); |
642 | } |
643 | |