This source file includes following definitions.
- ath_activate
- ath_enable
- ath_disable
- ath_attach
- ath_detach
- ath_power
- ath_suspend
- ath_resume
- ath_shutdown
- ath_intr
- ath_intr1
- ath_fatal_proc
- ath_rxorn_proc
- ath_bmiss_proc
- ath_chan2flags
- ath_init
- ath_init1
- ath_stop
- ath_reset
- ath_start
- ath_media_change
- ath_watchdog
- ath_ioctl
- ath_initkeytable
- ath_mcastfilter_accum
- ath_mcastfilter_compute
- ath_calcrxfilter
- ath_mode_init
- ath_getmbuf
- ath_beacon_alloc
- ath_beacon_proc
- ath_beacon_free
- ath_beacon_config
- ath_desc_alloc
- ath_desc_free
- ath_node_alloc
- ath_node_free
- ath_node_copy
- ath_node_getrssi
- ath_rxbuf_init
- ath_rx_proc
- ath_tx_start
- ath_tx_proc
- ath_draintxq
- ath_stoprecv
- ath_startrecv
- ath_chan_set
- ath_next_scan
- ath_set_slot_time
- ath_calibrate
- ath_ledstate
- ath_newstate
- ath_recv_mgmt
- ath_newassoc
- ath_getchannels
- ath_rate_setup
- ath_setcurmode
- ath_rssadapt_updatenode
- ath_rssadapt_updatestats
- ath_printrxbuf
- ath_printtxbuf
- ath_gpio_attach
- ath_gpio_pin_read
- ath_gpio_pin_write
- ath_gpio_pin_ctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 #include "bpfilter.h"
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/sysctl.h>
49 #include <sys/mbuf.h>
50 #include <sys/malloc.h>
51 #include <sys/lock.h>
52 #include <sys/kernel.h>
53 #include <sys/socket.h>
54 #include <sys/sockio.h>
55 #include <sys/device.h>
56 #include <sys/errno.h>
57 #include <sys/timeout.h>
58 #include <sys/gpio.h>
59
60 #include <machine/endian.h>
61 #include <machine/bus.h>
62
63 #include <net/if.h>
64 #include <net/if_dl.h>
65 #include <net/if_media.h>
66 #include <net/if_arp.h>
67 #include <net/if_llc.h>
68 #if NBPFILTER > 0
69 #include <net/bpf.h>
70 #endif
71 #ifdef INET
72 #include <netinet/in.h>
73 #include <netinet/if_ether.h>
74 #endif
75
76 #include <net80211/ieee80211_var.h>
77 #include <net80211/ieee80211_rssadapt.h>
78
79 #include <dev/pci/pcidevs.h>
80 #include <dev/gpio/gpiovar.h>
81 #include <dev/ic/athvar.h>
82
83 int ath_init(struct ifnet *);
84 int ath_init1(struct ath_softc *);
85 int ath_intr1(struct ath_softc *);
86 void ath_stop(struct ifnet *);
87 void ath_start(struct ifnet *);
88 void ath_reset(struct ath_softc *, int);
89 int ath_media_change(struct ifnet *);
90 void ath_watchdog(struct ifnet *);
91 int ath_ioctl(struct ifnet *, u_long, caddr_t);
92 void ath_fatal_proc(void *, int);
93 void ath_rxorn_proc(void *, int);
94 void ath_bmiss_proc(void *, int);
95 u_int ath_chan2flags(struct ieee80211com *, struct ieee80211_channel *);
96 int ath_initkeytable(struct ath_softc *);
97 void ath_mcastfilter_accum(caddr_t, u_int32_t (*)[2]);
98 void ath_mcastfilter_compute(struct ath_softc *, u_int32_t (*)[2]);
99 u_int32_t ath_calcrxfilter(struct ath_softc *);
100 void ath_mode_init(struct ath_softc *);
101 int ath_beacon_alloc(struct ath_softc *, struct ieee80211_node *);
102 void ath_beacon_proc(void *, int);
103 void ath_beacon_free(struct ath_softc *);
104 void ath_beacon_config(struct ath_softc *);
105 int ath_desc_alloc(struct ath_softc *);
106 void ath_desc_free(struct ath_softc *);
107 struct ieee80211_node *ath_node_alloc(struct ieee80211com *);
108 struct mbuf *ath_getmbuf(int, int, u_int);
109 void ath_node_free(struct ieee80211com *, struct ieee80211_node *);
110 void ath_node_copy(struct ieee80211com *,
111 struct ieee80211_node *, const struct ieee80211_node *);
112 u_int8_t ath_node_getrssi(struct ieee80211com *,
113 const struct ieee80211_node *);
114 int ath_rxbuf_init(struct ath_softc *, struct ath_buf *);
115 void ath_rx_proc(void *, int);
116 int ath_tx_start(struct ath_softc *, struct ieee80211_node *,
117 struct ath_buf *, struct mbuf *);
118 void ath_tx_proc(void *, int);
119 int ath_chan_set(struct ath_softc *, struct ieee80211_channel *);
120 void ath_draintxq(struct ath_softc *);
121 void ath_stoprecv(struct ath_softc *);
122 int ath_startrecv(struct ath_softc *);
123 void ath_next_scan(void *);
124 int ath_set_slot_time(struct ath_softc *);
125 void ath_calibrate(void *);
126 void ath_ledstate(struct ath_softc *, enum ieee80211_state);
127 int ath_newstate(struct ieee80211com *, enum ieee80211_state, int);
128 void ath_newassoc(struct ieee80211com *,
129 struct ieee80211_node *, int);
130 int ath_getchannels(struct ath_softc *, HAL_BOOL outdoor,
131 HAL_BOOL xchanmode);
132 int ath_rate_setup(struct ath_softc *sc, u_int mode);
133 void ath_setcurmode(struct ath_softc *, enum ieee80211_phymode);
134 void ath_rssadapt_updatenode(void *, struct ieee80211_node *);
135 void ath_rssadapt_updatestats(void *);
136 void ath_recv_mgmt(struct ieee80211com *, struct mbuf *,
137 struct ieee80211_node *, int, int, u_int32_t);
138 void ath_disable(struct ath_softc *);
139 void ath_power(int, void *);
140
141 int ath_gpio_attach(struct ath_softc *, u_int16_t);
142 int ath_gpio_pin_read(void *, int);
143 void ath_gpio_pin_write(void *, int, int);
144 void ath_gpio_pin_ctl(void *, int, int);
145
146 #ifdef AR_DEBUG
147 void ath_printrxbuf(struct ath_buf *, int);
148 void ath_printtxbuf(struct ath_buf *, int);
149 int ath_debug = 0;
150 #endif
151
152 int ath_dwelltime = 200;
153 int ath_calinterval = 30;
154 int ath_outdoor = AH_TRUE;
155 int ath_xchanmode = AH_TRUE;
156
157 struct cfdriver ath_cd = {
158 NULL, "ath", DV_IFNET
159 };
160
161 #if 0
162 int
163 ath_activate(struct device *self, enum devact act)
164 {
165 struct ath_softc *sc = (struct ath_softc *)self;
166 int rv = 0, s;
167
168 s = splnet();
169 switch (act) {
170 case DVACT_ACTIVATE:
171 break;
172 case DVACT_DEACTIVATE:
173 if_deactivate(&sc->sc_ic.ic_if);
174 break;
175 }
176 splx(s);
177 return rv;
178 }
179 #endif
180
181 int
182 ath_enable(struct ath_softc *sc)
183 {
184 if (ATH_IS_ENABLED(sc) == 0) {
185 if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
186 printf("%s: device enable failed\n",
187 sc->sc_dev.dv_xname);
188 return (EIO);
189 }
190 sc->sc_flags |= ATH_ENABLED;
191 }
192 return (0);
193 }
194
195 void
196 ath_disable(struct ath_softc *sc)
197 {
198 if (!ATH_IS_ENABLED(sc))
199 return;
200 if (sc->sc_disable != NULL)
201 (*sc->sc_disable)(sc);
202 sc->sc_flags &= ~ATH_ENABLED;
203 }
204
205 int
206 ath_attach(u_int16_t devid, struct ath_softc *sc)
207 {
208 struct ieee80211com *ic = &sc->sc_ic;
209 struct ifnet *ifp = &ic->ic_if;
210 struct ath_hal *ah;
211 HAL_STATUS status;
212 HAL_TXQ_INFO qinfo;
213 int error = 0, i;
214
215 DPRINTF(ATH_DEBUG_ANY, ("%s: devid 0x%x\n", __func__, devid));
216
217 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
218 sc->sc_flags &= ~ATH_ATTACHED;
219
220 ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, sc->sc_64bit,
221 &status);
222 if (ah == NULL) {
223 printf("%s: unable to attach hardware; HAL status %d\n",
224 ifp->if_xname, status);
225 error = ENXIO;
226 goto bad;
227 }
228 if (ah->ah_abi != HAL_ABI_VERSION) {
229 printf("%s: HAL ABI mismatch detected (0x%x != 0x%x)\n",
230 ifp->if_xname, ah->ah_abi, HAL_ABI_VERSION);
231 error = ENXIO;
232 goto bad;
233 }
234
235 if (ah->ah_single_chip == AH_TRUE) {
236 printf("%s: AR%s %u.%u phy %u.%u rf %u.%u", ifp->if_xname,
237 ar5k_printver(AR5K_VERSION_DEV, devid),
238 ah->ah_mac_version, ah->ah_mac_revision,
239 ah->ah_phy_revision >> 4, ah->ah_phy_revision & 0xf,
240 ah->ah_radio_5ghz_revision >> 4,
241 ah->ah_radio_5ghz_revision & 0xf);
242 } else {
243 printf("%s: AR%s %u.%u phy %u.%u", ifp->if_xname,
244 ar5k_printver(AR5K_VERSION_VER, ah->ah_mac_srev),
245 ah->ah_mac_version, ah->ah_mac_revision,
246 ah->ah_phy_revision >> 4, ah->ah_phy_revision & 0xf);
247 printf(" rf%s %u.%u",
248 ar5k_printver(AR5K_VERSION_RAD, ah->ah_radio_5ghz_revision),
249 ah->ah_radio_5ghz_revision >> 4,
250 ah->ah_radio_5ghz_revision & 0xf);
251 if (ah->ah_radio_2ghz_revision != 0) {
252 printf(" rf%s %u.%u",
253 ar5k_printver(AR5K_VERSION_RAD,
254 ah->ah_radio_2ghz_revision),
255 ah->ah_radio_2ghz_revision >> 4,
256 ah->ah_radio_2ghz_revision & 0xf);
257 }
258 }
259
260 #if 0
261 if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_UNSUPP ||
262 ah->ah_radio_2ghz_revision >= AR5K_SREV_RAD_UNSUPP) {
263 printf(": RF radio not supported\n");
264 error = EOPNOTSUPP;
265 goto bad;
266 }
267 #endif
268
269 sc->sc_ah = ah;
270 sc->sc_invalid = 0;
271
272
273
274
275
276
277 ath_hal_get_regdomain(ah, &ah->ah_regdomain);
278
279
280
281
282 error = ath_getchannels(sc, ath_outdoor, ath_xchanmode);
283 if (error != 0)
284 goto bad;
285
286
287
288
289 ath_rate_setup(sc, IEEE80211_MODE_11A);
290 ath_rate_setup(sc, IEEE80211_MODE_11B);
291 ath_rate_setup(sc, IEEE80211_MODE_11G);
292 ath_rate_setup(sc, IEEE80211_MODE_TURBO);
293
294 error = ath_desc_alloc(sc);
295 if (error != 0) {
296 printf(": failed to allocate descriptors: %d\n", error);
297 goto bad;
298 }
299 timeout_set(&sc->sc_scan_to, ath_next_scan, sc);
300 timeout_set(&sc->sc_cal_to, ath_calibrate, sc);
301 timeout_set(&sc->sc_rssadapt_to, ath_rssadapt_updatestats, sc);
302
303 #ifdef __FreeBSD__
304 ATH_TXBUF_LOCK_INIT(sc);
305 ATH_TXQ_LOCK_INIT(sc);
306 #endif
307
308 ATH_TASK_INIT(&sc->sc_txtask, ath_tx_proc, sc);
309 ATH_TASK_INIT(&sc->sc_rxtask, ath_rx_proc, sc);
310 ATH_TASK_INIT(&sc->sc_rxorntask, ath_rxorn_proc, sc);
311 ATH_TASK_INIT(&sc->sc_fataltask, ath_fatal_proc, sc);
312 ATH_TASK_INIT(&sc->sc_bmisstask, ath_bmiss_proc, sc);
313 ATH_TASK_INIT(&sc->sc_swbatask, ath_beacon_proc, sc);
314
315
316
317
318
319
320
321
322 sc->sc_bhalq = ath_hal_setup_tx_queue(ah, HAL_TX_QUEUE_BEACON, NULL);
323 if (sc->sc_bhalq == (u_int) -1) {
324 printf(": unable to setup a beacon xmit queue!\n");
325 goto bad2;
326 }
327
328 for (i = 0; i <= HAL_TX_QUEUE_ID_DATA_MAX; i++) {
329 bzero(&qinfo, sizeof(qinfo));
330 qinfo.tqi_type = HAL_TX_QUEUE_DATA;
331 qinfo.tqi_subtype = i;
332 sc->sc_txhalq[i] = ath_hal_setup_tx_queue(ah,
333 HAL_TX_QUEUE_DATA, &qinfo);
334 if (sc->sc_txhalq[i] == (u_int) -1) {
335 printf(": unable to setup a data xmit queue %u!\n", i);
336 goto bad2;
337 }
338 }
339
340 ifp->if_softc = sc;
341 ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST
342 | IFF_NOTRAILERS;
343 ifp->if_start = ath_start;
344 ifp->if_watchdog = ath_watchdog;
345 ifp->if_ioctl = ath_ioctl;
346 #ifndef __OpenBSD__
347 ifp->if_init = ath_init;
348 ifp->if_stop = ath_stop;
349 #endif
350 IFQ_SET_MAXLEN(&ifp->if_snd, ATH_TXBUF * ATH_TXDESC);
351 IFQ_SET_READY(&ifp->if_snd);
352
353 ic->ic_softc = sc;
354 ic->ic_newassoc = ath_newassoc;
355
356 ic->ic_phytype = IEEE80211_T_OFDM;
357 ic->ic_opmode = IEEE80211_M_STA;
358 ic->ic_caps = IEEE80211_C_WEP
359 | IEEE80211_C_PMGT
360 | IEEE80211_C_IBSS
361 | IEEE80211_C_HOSTAP
362 | IEEE80211_C_MONITOR
363 | IEEE80211_C_SHSLOT
364 | IEEE80211_C_SHPREAMBLE;
365
366
367
368
369
370 sc->sc_veol = ath_hal_has_veol(ah);
371
372
373 ath_hal_get_lladdr(ah, ic->ic_myaddr);
374
375 if_attach(ifp);
376
377
378 ieee80211_ifattach(ifp);
379
380
381 ic->ic_node_alloc = ath_node_alloc;
382 sc->sc_node_free = ic->ic_node_free;
383 ic->ic_node_free = ath_node_free;
384 sc->sc_node_copy = ic->ic_node_copy;
385 ic->ic_node_copy = ath_node_copy;
386 ic->ic_node_getrssi = ath_node_getrssi;
387 sc->sc_newstate = ic->ic_newstate;
388 ic->ic_newstate = ath_newstate;
389 sc->sc_recv_mgmt = ic->ic_recv_mgmt;
390 ic->ic_recv_mgmt = ath_recv_mgmt;
391 ic->ic_max_rssi = AR5K_MAX_RSSI;
392 bcopy(etherbroadcastaddr, sc->sc_broadcast_addr, IEEE80211_ADDR_LEN);
393
394
395 ieee80211_media_init(ifp, ath_media_change, ieee80211_media_status);
396
397 #if NBPFILTER > 0
398 bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
399 sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN);
400
401 sc->sc_rxtap_len = sizeof(sc->sc_rxtapu);
402 bzero(&sc->sc_rxtapu, sc->sc_rxtap_len);
403 sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len);
404 sc->sc_rxtap.wr_ihdr.it_present = htole32(ATH_RX_RADIOTAP_PRESENT);
405
406 sc->sc_txtap_len = sizeof(sc->sc_txtapu);
407 bzero(&sc->sc_txtapu, sc->sc_txtap_len);
408 sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len);
409 sc->sc_txtap.wt_ihdr.it_present = htole32(ATH_TX_RADIOTAP_PRESENT);
410 #endif
411
412 sc->sc_flags |= ATH_ATTACHED;
413
414
415
416 sc->sc_sdhook = shutdownhook_establish(ath_shutdown, sc);
417 if (sc->sc_sdhook == NULL)
418 printf(": WARNING: unable to establish shutdown hook\n");
419 sc->sc_powerhook = powerhook_establish(ath_power, sc);
420 if (sc->sc_powerhook == NULL)
421 printf(": WARNING: unable to establish power hook\n");
422
423
424
425
426
427 printf(", %s%s, address %s\n",
428 ieee80211_regdomain2name(ah->ah_regdomain),
429 ah->ah_regdomain != ah->ah_regdomain_hw ? "*" : "",
430 ether_sprintf(ic->ic_myaddr));
431
432 if (ath_gpio_attach(sc, devid) == 0)
433 sc->sc_flags |= ATH_GPIO;
434
435 return 0;
436 bad2:
437 ath_desc_free(sc);
438 bad:
439 if (ah)
440 ath_hal_detach(ah);
441 sc->sc_invalid = 1;
442 return error;
443 }
444
445 int
446 ath_detach(struct ath_softc *sc, int flags)
447 {
448 struct ifnet *ifp = &sc->sc_ic.ic_if;
449 int s;
450
451 if ((sc->sc_flags & ATH_ATTACHED) == 0)
452 return (0);
453
454 config_detach_children(&sc->sc_dev, flags);
455
456 DPRINTF(ATH_DEBUG_ANY, ("%s: if_flags %x\n", __func__, ifp->if_flags));
457
458 timeout_del(&sc->sc_scan_to);
459 timeout_del(&sc->sc_cal_to);
460 timeout_del(&sc->sc_rssadapt_to);
461
462 s = splnet();
463 ath_stop(ifp);
464 ath_desc_free(sc);
465 ath_hal_detach(sc->sc_ah);
466
467 ieee80211_ifdetach(ifp);
468 if_detach(ifp);
469
470 splx(s);
471 if (sc->sc_powerhook != NULL)
472 powerhook_disestablish(sc->sc_powerhook);
473 if (sc->sc_sdhook != NULL)
474 shutdownhook_disestablish(sc->sc_sdhook);
475 #ifdef __FreeBSD__
476 ATH_TXBUF_LOCK_DESTROY(sc);
477 ATH_TXQ_LOCK_DESTROY(sc);
478 #endif
479
480 return 0;
481 }
482
483 void
484 ath_power(int why, void *arg)
485 {
486 struct ath_softc *sc = arg;
487 int s;
488
489 DPRINTF(ATH_DEBUG_ANY, ("ath_power(%d)\n", why));
490
491 s = splnet();
492 switch (why) {
493 case PWR_SUSPEND:
494 case PWR_STANDBY:
495 ath_suspend(sc, why);
496 break;
497 case PWR_RESUME:
498 ath_resume(sc, why);
499 break;
500 #if !defined(__OpenBSD__)
501 case PWR_SOFTSUSPEND:
502 case PWR_SOFTSTANDBY:
503 case PWR_SOFTRESUME:
504 break;
505 #endif
506 }
507 splx(s);
508 }
509
510 void
511 ath_suspend(struct ath_softc *sc, int why)
512 {
513 struct ifnet *ifp = &sc->sc_ic.ic_if;
514
515 DPRINTF(ATH_DEBUG_ANY, ("%s: if_flags %x\n", __func__, ifp->if_flags));
516
517 ath_stop(ifp);
518 if (sc->sc_power != NULL)
519 (*sc->sc_power)(sc, why);
520 }
521
522 void
523 ath_resume(struct ath_softc *sc, int why)
524 {
525 struct ifnet *ifp = &sc->sc_ic.ic_if;
526
527 DPRINTF(ATH_DEBUG_ANY, ("%s: if_flags %x\n", __func__, ifp->if_flags));
528
529 if (ifp->if_flags & IFF_UP) {
530 ath_init(ifp);
531 #if 0
532 (void)ath_intr(sc);
533 #endif
534 if (sc->sc_power != NULL)
535 (*sc->sc_power)(sc, why);
536 if (ifp->if_flags & IFF_RUNNING)
537 ath_start(ifp);
538 }
539 }
540
541 void
542 ath_shutdown(void *arg)
543 {
544 struct ath_softc *sc = arg;
545
546 ath_stop(&sc->sc_ic.ic_if);
547 }
548
549 int
550 ath_intr(void *arg)
551 {
552 return ath_intr1((struct ath_softc *)arg);
553 }
554
555 int
556 ath_intr1(struct ath_softc *sc)
557 {
558 struct ieee80211com *ic = &sc->sc_ic;
559 struct ifnet *ifp = &ic->ic_if;
560 struct ath_hal *ah = sc->sc_ah;
561 HAL_INT status;
562
563 if (sc->sc_invalid) {
564
565
566
567
568 DPRINTF(ATH_DEBUG_ANY, ("%s: invalid; ignored\n", __func__));
569 return 0;
570 }
571 if (!ath_hal_is_intr_pending(ah))
572 return 0;
573 if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP)) {
574 DPRINTF(ATH_DEBUG_ANY, ("%s: if_flags 0x%x\n",
575 __func__, ifp->if_flags));
576 ath_hal_get_isr(ah, &status);
577 ath_hal_set_intr(ah, 0);
578 return 1;
579 }
580 ath_hal_get_isr(ah, &status);
581 DPRINTF(ATH_DEBUG_INTR, ("%s: status 0x%x\n", __func__, status));
582 status &= sc->sc_imask;
583 if (status & HAL_INT_FATAL) {
584 sc->sc_stats.ast_hardware++;
585 ath_hal_set_intr(ah, 0);
586 ATH_TASK_RUN_OR_ENQUEUE(&sc->sc_fataltask);
587 } else if (status & HAL_INT_RXORN) {
588 sc->sc_stats.ast_rxorn++;
589 ath_hal_set_intr(ah, 0);
590 ATH_TASK_RUN_OR_ENQUEUE(&sc->sc_rxorntask);
591 } else if (status & HAL_INT_MIB) {
592 DPRINTF(ATH_DEBUG_INTR,
593 ("%s: resetting MIB counters\n", __func__));
594 sc->sc_stats.ast_mib++;
595 ath_hal_update_mib_counters(ah, &sc->sc_mib_stats);
596 } else {
597 if (status & HAL_INT_RXEOL) {
598
599
600
601
602
603 sc->sc_stats.ast_rxeol++;
604 sc->sc_rxlink = NULL;
605 }
606 if (status & HAL_INT_TXURN) {
607 sc->sc_stats.ast_txurn++;
608
609 ath_hal_update_tx_triglevel(ah, AH_TRUE);
610 }
611 if (status & HAL_INT_RX)
612 ATH_TASK_RUN_OR_ENQUEUE(&sc->sc_rxtask);
613 if (status & HAL_INT_TX)
614 ATH_TASK_RUN_OR_ENQUEUE(&sc->sc_txtask);
615 if (status & HAL_INT_SWBA)
616 ATH_TASK_RUN_OR_ENQUEUE(&sc->sc_swbatask);
617 if (status & HAL_INT_BMISS) {
618 sc->sc_stats.ast_bmiss++;
619 ATH_TASK_RUN_OR_ENQUEUE(&sc->sc_bmisstask);
620 }
621 }
622 return 1;
623 }
624
625 void
626 ath_fatal_proc(void *arg, int pending)
627 {
628 struct ath_softc *sc = arg;
629 struct ieee80211com *ic = &sc->sc_ic;
630 struct ifnet *ifp = &ic->ic_if;
631
632 if (ifp->if_flags & IFF_DEBUG)
633 printf("%s: hardware error; resetting\n", ifp->if_xname);
634 ath_reset(sc, 1);
635 }
636
637 void
638 ath_rxorn_proc(void *arg, int pending)
639 {
640 struct ath_softc *sc = arg;
641 struct ieee80211com *ic = &sc->sc_ic;
642 struct ifnet *ifp = &ic->ic_if;
643
644 if (ifp->if_flags & IFF_DEBUG)
645 printf("%s: rx FIFO overrun; resetting\n", ifp->if_xname);
646 ath_reset(sc, 1);
647 }
648
649 void
650 ath_bmiss_proc(void *arg, int pending)
651 {
652 struct ath_softc *sc = arg;
653 struct ieee80211com *ic = &sc->sc_ic;
654
655 DPRINTF(ATH_DEBUG_ANY, ("%s: pending %u\n", __func__, pending));
656 if (ic->ic_opmode != IEEE80211_M_STA)
657 return;
658 if (ic->ic_state == IEEE80211_S_RUN) {
659
660
661
662
663
664
665 ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1);
666 }
667 }
668
669 u_int
670 ath_chan2flags(struct ieee80211com *ic, struct ieee80211_channel *chan)
671 {
672 enum ieee80211_phymode mode = ieee80211_chan2mode(ic, chan);
673
674 switch (mode) {
675 case IEEE80211_MODE_AUTO:
676 return 0;
677 case IEEE80211_MODE_11A:
678 return CHANNEL_A;
679 case IEEE80211_MODE_11B:
680 return CHANNEL_B;
681 case IEEE80211_MODE_11G:
682 return CHANNEL_G;
683 case IEEE80211_MODE_TURBO:
684 return CHANNEL_T;
685 default:
686 panic("%s: unsupported mode %d", __func__, mode);
687 return 0;
688 }
689 }
690
691 int
692 ath_init(struct ifnet *ifp)
693 {
694 return ath_init1((struct ath_softc *)ifp->if_softc);
695 }
696
697 int
698 ath_init1(struct ath_softc *sc)
699 {
700 struct ieee80211com *ic = &sc->sc_ic;
701 struct ifnet *ifp = &ic->ic_if;
702 struct ieee80211_node *ni;
703 enum ieee80211_phymode mode;
704 struct ath_hal *ah = sc->sc_ah;
705 HAL_STATUS status;
706 HAL_CHANNEL hchan;
707 int error = 0, s;
708
709 DPRINTF(ATH_DEBUG_ANY, ("%s: if_flags 0x%x\n",
710 __func__, ifp->if_flags));
711
712 if ((error = ath_enable(sc)) != 0)
713 return error;
714
715 s = splnet();
716
717
718
719
720 ath_stop(ifp);
721
722
723
724
725 IEEE80211_ADDR_COPY(ic->ic_myaddr, LLADDR(ifp->if_sadl));
726 ath_hal_set_lladdr(ah, ic->ic_myaddr);
727
728
729
730
731
732
733
734
735 hchan.channel = ic->ic_ibss_chan->ic_freq;
736 hchan.channelFlags = ath_chan2flags(ic, ic->ic_ibss_chan);
737 if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE, &status)) {
738 printf("%s: unable to reset hardware; hal status %u\n",
739 ifp->if_xname, status);
740 error = EIO;
741 goto done;
742 }
743 ath_set_slot_time(sc);
744
745
746
747
748
749
750
751 if (ic->ic_flags & IEEE80211_F_WEPON) {
752 if ((error = ath_initkeytable(sc)) != 0) {
753 printf("%s: unable to initialize the key cache\n",
754 ifp->if_xname);
755 goto done;
756 }
757 }
758 if ((error = ath_startrecv(sc)) != 0) {
759 printf("%s: unable to start recv logic\n", ifp->if_xname);
760 goto done;
761 }
762
763
764
765
766 sc->sc_imask = HAL_INT_RX | HAL_INT_TX
767 | HAL_INT_RXEOL | HAL_INT_RXORN
768 | HAL_INT_FATAL | HAL_INT_GLOBAL;
769 if (ic->ic_opmode == IEEE80211_M_HOSTAP)
770 sc->sc_imask |= HAL_INT_MIB;
771 ath_hal_set_intr(ah, sc->sc_imask);
772
773 ifp->if_flags |= IFF_RUNNING;
774 ic->ic_state = IEEE80211_S_INIT;
775
776
777
778
779
780
781 ni = ic->ic_bss;
782 ni->ni_chan = ic->ic_ibss_chan;
783 mode = ieee80211_chan2mode(ic, ni->ni_chan);
784 if (mode != sc->sc_curmode)
785 ath_setcurmode(sc, mode);
786 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
787 ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
788 } else {
789 ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
790 }
791 done:
792 splx(s);
793 return error;
794 }
795
796 void
797 ath_stop(struct ifnet *ifp)
798 {
799 struct ieee80211com *ic = (struct ieee80211com *) ifp;
800 struct ath_softc *sc = ifp->if_softc;
801 struct ath_hal *ah = sc->sc_ah;
802 int s;
803
804 DPRINTF(ATH_DEBUG_ANY, ("%s: invalid %u if_flags 0x%x\n",
805 __func__, sc->sc_invalid, ifp->if_flags));
806
807 s = splnet();
808 if (ifp->if_flags & IFF_RUNNING) {
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823 ifp->if_flags &= ~IFF_RUNNING;
824 ifp->if_timer = 0;
825 if (!sc->sc_invalid)
826 ath_hal_set_intr(ah, 0);
827 ath_draintxq(sc);
828 if (!sc->sc_invalid) {
829 ath_stoprecv(sc);
830 } else {
831 sc->sc_rxlink = NULL;
832 }
833 IFQ_PURGE(&ifp->if_snd);
834 ath_beacon_free(sc);
835 ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
836 if (!sc->sc_invalid) {
837 ath_hal_set_power(ah, HAL_PM_FULL_SLEEP, 0);
838 }
839 ath_disable(sc);
840 }
841 splx(s);
842 }
843
844
845
846
847
848
849
850
851 void
852 ath_reset(struct ath_softc *sc, int full)
853 {
854 struct ieee80211com *ic = &sc->sc_ic;
855 struct ifnet *ifp = &ic->ic_if;
856 struct ath_hal *ah = sc->sc_ah;
857 struct ieee80211_channel *c;
858 HAL_STATUS status;
859 HAL_CHANNEL hchan;
860
861
862
863
864
865 c = ic->ic_ibss_chan;
866 hchan.channel = c->ic_freq;
867 hchan.channelFlags = ath_chan2flags(ic, c);
868
869 ath_hal_set_intr(ah, 0);
870 ath_draintxq(sc);
871 ath_stoprecv(sc);
872
873 if (!ath_hal_reset(ah, ic->ic_opmode, &hchan,
874 full ? AH_TRUE : AH_FALSE, &status)) {
875 printf("%s: %s: unable to reset hardware; hal status %u\n",
876 ifp->if_xname, __func__, status);
877 }
878 ath_set_slot_time(sc);
879
880 ic->ic_bss->ni_chan = ic->ic_ibss_chan;
881 ath_hal_set_intr(ah, sc->sc_imask);
882 if (ath_startrecv(sc) != 0)
883 printf("%s: %s: unable to start recv logic\n", ifp->if_xname,
884 __func__);
885 ath_start(ifp);
886 if (ic->ic_state == IEEE80211_S_RUN)
887 ath_beacon_config(sc);
888 }
889
890 void
891 ath_start(struct ifnet *ifp)
892 {
893 struct ath_softc *sc = ifp->if_softc;
894 struct ath_hal *ah = sc->sc_ah;
895 struct ieee80211com *ic = &sc->sc_ic;
896 struct ieee80211_node *ni;
897 struct ath_buf *bf;
898 struct mbuf *m;
899 struct ieee80211_frame *wh;
900 int s;
901
902 if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING ||
903 sc->sc_invalid)
904 return;
905 for (;;) {
906
907
908
909 s = splnet();
910 bf = TAILQ_FIRST(&sc->sc_txbuf);
911 if (bf != NULL)
912 TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list);
913 splx(s);
914 if (bf == NULL) {
915 DPRINTF(ATH_DEBUG_ANY, ("%s: out of xmit buffers\n",
916 __func__));
917 sc->sc_stats.ast_tx_qstop++;
918 ifp->if_flags |= IFF_OACTIVE;
919 break;
920 }
921
922
923
924
925 IF_DEQUEUE(&ic->ic_mgtq, m);
926 if (m == NULL) {
927
928
929
930 if (ic->ic_state != IEEE80211_S_RUN) {
931 DPRINTF(ATH_DEBUG_ANY,
932 ("%s: ignore data packet, state %u\n",
933 __func__, ic->ic_state));
934 sc->sc_stats.ast_tx_discard++;
935 s = splnet();
936 TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
937 splx(s);
938 break;
939 }
940 IFQ_DEQUEUE(&ifp->if_snd, m);
941 if (m == NULL) {
942 s = splnet();
943 TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
944 splx(s);
945 break;
946 }
947 ifp->if_opackets++;
948
949 #if NBPFILTER > 0
950 if (ifp->if_bpf)
951 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
952 #endif
953
954
955
956
957 m = ieee80211_encap(ifp, m, &ni);
958 if (m == NULL) {
959 DPRINTF(ATH_DEBUG_ANY,
960 ("%s: encapsulation failure\n",
961 __func__));
962 sc->sc_stats.ast_tx_encap++;
963 goto bad;
964 }
965 wh = mtod(m, struct ieee80211_frame *);
966 } else {
967
968
969
970
971
972
973
974
975
976 ni = (struct ieee80211_node *) m->m_pkthdr.rcvif;
977 m->m_pkthdr.rcvif = NULL;
978
979 wh = mtod(m, struct ieee80211_frame *);
980 if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
981 IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
982
983 u_int64_t tsf;
984 u_int32_t *tstamp;
985
986 tsf = ath_hal_get_tsf64(ah);
987
988 tsf += 100;
989 tstamp = (u_int32_t *)&wh[1];
990 tstamp[0] = htole32(tsf & 0xffffffff);
991 tstamp[1] = htole32(tsf >> 32);
992 }
993 sc->sc_stats.ast_tx_mgmt++;
994 }
995
996 if (ath_tx_start(sc, ni, bf, m)) {
997 bad:
998 s = splnet();
999 TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
1000 splx(s);
1001 ifp->if_oerrors++;
1002 if (ni != NULL)
1003 ieee80211_release_node(ic, ni);
1004 continue;
1005 }
1006
1007 sc->sc_tx_timer = 5;
1008 ifp->if_timer = 1;
1009 }
1010 }
1011
1012 int
1013 ath_media_change(struct ifnet *ifp)
1014 {
1015 int error;
1016
1017 error = ieee80211_media_change(ifp);
1018 if (error == ENETRESET) {
1019 if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
1020 (IFF_RUNNING|IFF_UP))
1021 ath_init(ifp);
1022 error = 0;
1023 }
1024 return error;
1025 }
1026
1027 void
1028 ath_watchdog(struct ifnet *ifp)
1029 {
1030 struct ath_softc *sc = ifp->if_softc;
1031
1032 ifp->if_timer = 0;
1033 if ((ifp->if_flags & IFF_RUNNING) == 0 || sc->sc_invalid)
1034 return;
1035 if (sc->sc_tx_timer) {
1036 if (--sc->sc_tx_timer == 0) {
1037 printf("%s: device timeout\n", ifp->if_xname);
1038 ath_reset(sc, 1);
1039 ifp->if_oerrors++;
1040 sc->sc_stats.ast_watchdog++;
1041 return;
1042 }
1043 ifp->if_timer = 1;
1044 }
1045
1046 ieee80211_watchdog(ifp);
1047 }
1048
1049 int
1050 ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1051 {
1052 struct ath_softc *sc = ifp->if_softc;
1053 struct ieee80211com *ic = &sc->sc_ic;
1054 struct ifreq *ifr = (struct ifreq *)data;
1055 struct ifaddr *ifa = (struct ifaddr *)data;
1056 int error = 0, s;
1057
1058 s = splnet();
1059 switch (cmd) {
1060 case SIOCSIFADDR:
1061 ifp->if_flags |= IFF_UP;
1062 #ifdef INET
1063 if (ifa->ifa_addr->sa_family == AF_INET) {
1064 arp_ifinit(&ic->ic_ac, ifa);
1065 }
1066 #endif
1067
1068 case SIOCSIFFLAGS:
1069 if (ifp->if_flags & IFF_UP) {
1070 if (ifp->if_flags & IFF_RUNNING) {
1071
1072
1073
1074
1075
1076 ath_mode_init(sc);
1077 } else {
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087 if (!sc->sc_invalid)
1088 ath_init(ifp);
1089 }
1090 } else
1091 ath_stop(ifp);
1092 break;
1093 case SIOCADDMULTI:
1094 case SIOCDELMULTI:
1095 #ifdef __FreeBSD__
1096
1097
1098
1099
1100
1101 if (ifp->if_flags & IFF_RUNNING)
1102 ath_mode_init(sc);
1103 #endif
1104 error = (cmd == SIOCADDMULTI) ?
1105 ether_addmulti(ifr, &sc->sc_ic.ic_ac) :
1106 ether_delmulti(ifr, &sc->sc_ic.ic_ac);
1107 if (error == ENETRESET) {
1108 if (ifp->if_flags & IFF_RUNNING)
1109 ath_mode_init(sc);
1110 error = 0;
1111 }
1112 break;
1113 case SIOCGATHSTATS:
1114 error = copyout(&sc->sc_stats,
1115 ifr->ifr_data, sizeof (sc->sc_stats));
1116 break;
1117 default:
1118 error = ieee80211_ioctl(ifp, cmd, data);
1119 if (error == ENETRESET) {
1120 if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
1121 (IFF_RUNNING|IFF_UP)) {
1122 struct ieee80211com *ic = &sc->sc_ic;
1123
1124 if (ic->ic_opmode != IEEE80211_M_MONITOR)
1125 ath_init(ifp);
1126 else
1127 ath_reset(sc, 1);
1128 }
1129 error = 0;
1130 }
1131 break;
1132 }
1133 splx(s);
1134 return error;
1135 }
1136
1137
1138
1139
1140 int
1141 ath_initkeytable(struct ath_softc *sc)
1142 {
1143 struct ieee80211com *ic = &sc->sc_ic;
1144 struct ath_hal *ah = sc->sc_ah;
1145 int i;
1146
1147
1148 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
1149 struct ieee80211_key *k = &ic->ic_nw_keys[i];
1150 if (k->k_len == 0)
1151 ath_hal_reset_key(ah, i);
1152 else {
1153 HAL_KEYVAL hk;
1154
1155 bzero(&hk, sizeof(hk));
1156
1157
1158
1159
1160
1161
1162
1163 if (k->k_cipher == IEEE80211_CIPHER_WEP40)
1164 hk.wk_len = AR5K_KEYVAL_LENGTH_40;
1165 else if (k->k_cipher == IEEE80211_CIPHER_WEP104)
1166 hk.wk_len = AR5K_KEYVAL_LENGTH_104;
1167 else
1168 return (EINVAL);
1169 bcopy(k->k_key, hk.wk_key, hk.wk_len);
1170
1171 if (ath_hal_set_key(ah, i, &hk) != AH_TRUE)
1172 return (EINVAL);
1173 }
1174 }
1175
1176 return (0);
1177 }
1178
1179 void
1180 ath_mcastfilter_accum(caddr_t dl, u_int32_t (*mfilt)[2])
1181 {
1182 u_int32_t val;
1183 u_int8_t pos;
1184
1185 val = LE_READ_4(dl + 0);
1186 pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
1187 val = LE_READ_4(dl + 3);
1188 pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val;
1189 pos &= 0x3f;
1190 (*mfilt)[pos / 32] |= (1 << (pos % 32));
1191 }
1192
1193 void
1194 ath_mcastfilter_compute(struct ath_softc *sc, u_int32_t (*mfilt)[2])
1195 {
1196 struct ifnet *ifp = &sc->sc_ic.ic_if;
1197 struct ether_multi *enm;
1198 struct ether_multistep estep;
1199
1200 ETHER_FIRST_MULTI(estep, &sc->sc_ic.ic_ac, enm);
1201 while (enm != NULL) {
1202
1203 if (!IEEE80211_ADDR_EQ(enm->enm_addrlo, enm->enm_addrhi)) {
1204 (*mfilt)[0] = (*mfilt)[1] = ~((u_int32_t)0);
1205 ifp->if_flags |= IFF_ALLMULTI;
1206 return;
1207 }
1208 ath_mcastfilter_accum(enm->enm_addrlo, mfilt);
1209 ETHER_NEXT_MULTI(estep, enm);
1210 }
1211 ifp->if_flags &= ~IFF_ALLMULTI;
1212 }
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230 u_int32_t
1231 ath_calcrxfilter(struct ath_softc *sc)
1232 {
1233 struct ieee80211com *ic = &sc->sc_ic;
1234 struct ath_hal *ah = sc->sc_ah;
1235 struct ifnet *ifp = &ic->ic_if;
1236 u_int32_t rfilt;
1237
1238 rfilt = (ath_hal_get_rx_filter(ah) & HAL_RX_FILTER_PHYERR)
1239 | HAL_RX_FILTER_UCAST | HAL_RX_FILTER_BCAST | HAL_RX_FILTER_MCAST;
1240 if (ic->ic_opmode != IEEE80211_M_STA)
1241 rfilt |= HAL_RX_FILTER_PROBEREQ;
1242 if (ic->ic_opmode != IEEE80211_M_AHDEMO)
1243 rfilt |= HAL_RX_FILTER_BEACON;
1244 if (ifp->if_flags & IFF_PROMISC)
1245 rfilt |= HAL_RX_FILTER_PROM;
1246 return rfilt;
1247 }
1248
1249 void
1250 ath_mode_init(struct ath_softc *sc)
1251 {
1252 struct ath_hal *ah = sc->sc_ah;
1253 u_int32_t rfilt, mfilt[2];
1254
1255
1256 rfilt = ath_calcrxfilter(sc);
1257 ath_hal_set_rx_filter(ah, rfilt);
1258
1259
1260 ath_hal_set_opmode(ah);
1261
1262
1263 mfilt[0] = mfilt[1] = 0;
1264 ath_mcastfilter_compute(sc, &mfilt);
1265 ath_hal_set_mcast_filter(ah, mfilt[0], mfilt[1]);
1266 DPRINTF(ATH_DEBUG_MODE, ("%s: RX filter 0x%x, MC filter %08x:%08x\n",
1267 __func__, rfilt, mfilt[0], mfilt[1]));
1268 }
1269
1270 struct mbuf *
1271 ath_getmbuf(int flags, int type, u_int pktlen)
1272 {
1273 struct mbuf *m;
1274
1275 KASSERT(pktlen <= MCLBYTES, ("802.11 packet too large: %u", pktlen));
1276 #ifdef __FreeBSD__
1277 if (pktlen <= MHLEN) {
1278 MGETHDR(m, flags, type);
1279 } else {
1280 m = m_getcl(flags, type, M_PKTHDR);
1281 }
1282 #else
1283 MGETHDR(m, flags, type);
1284 if (m != NULL && pktlen > MHLEN) {
1285 MCLGET(m, flags);
1286 if ((m->m_flags & M_EXT) == 0) {
1287 m_free(m);
1288 m = NULL;
1289 }
1290 }
1291 #endif
1292 return m;
1293 }
1294
1295 int
1296 ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_node *ni)
1297 {
1298 struct ieee80211com *ic = &sc->sc_ic;
1299 struct ath_hal *ah = sc->sc_ah;
1300 struct ath_buf *bf;
1301 struct ath_desc *ds;
1302 struct mbuf *m;
1303 int error;
1304 u_int8_t rate;
1305 const HAL_RATE_TABLE *rt;
1306 u_int flags = 0;
1307
1308 bf = sc->sc_bcbuf;
1309 if (bf->bf_m != NULL) {
1310 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
1311 m_freem(bf->bf_m);
1312 bf->bf_m = NULL;
1313 bf->bf_node = NULL;
1314 }
1315
1316
1317
1318
1319
1320 m = ieee80211_beacon_alloc(ic, ni);
1321 if (m == NULL) {
1322 DPRINTF(ATH_DEBUG_BEACON, ("%s: cannot get mbuf/cluster\n",
1323 __func__));
1324 sc->sc_stats.ast_be_nombuf++;
1325 return ENOMEM;
1326 }
1327
1328 DPRINTF(ATH_DEBUG_BEACON, ("%s: m %p len %u\n", __func__, m, m->m_len));
1329 error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
1330 BUS_DMA_NOWAIT);
1331 if (error != 0) {
1332 m_freem(m);
1333 return error;
1334 }
1335 KASSERT(bf->bf_nseg == 1,
1336 ("%s: multi-segment packet; nseg %u", __func__, bf->bf_nseg));
1337 bf->bf_m = m;
1338
1339
1340 ds = bf->bf_desc;
1341 bzero(ds, sizeof(struct ath_desc));
1342
1343 if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_veol) {
1344 ds->ds_link = bf->bf_daddr;
1345 flags |= HAL_TXDESC_VEOL;
1346 } else {
1347 ds->ds_link = 0;
1348 }
1349 ds->ds_data = bf->bf_segs[0].ds_addr;
1350
1351 DPRINTF(ATH_DEBUG_ANY, ("%s: segaddr %p seglen %u\n", __func__,
1352 (caddr_t)bf->bf_segs[0].ds_addr, (u_int)bf->bf_segs[0].ds_len));
1353
1354
1355
1356
1357
1358 rt = sc->sc_currates;
1359 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
1360 if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) {
1361 rate = rt->info[0].rateCode | rt->info[0].shortPreamble;
1362 } else {
1363 rate = rt->info[0].rateCode;
1364 }
1365
1366 flags = HAL_TXDESC_NOACK;
1367 if (ic->ic_opmode == IEEE80211_M_IBSS)
1368 flags |= HAL_TXDESC_VEOL;
1369
1370 if (!ath_hal_setup_tx_desc(ah, ds
1371 , m->m_pkthdr.len + IEEE80211_CRC_LEN
1372 , sizeof(struct ieee80211_frame)
1373 , HAL_PKT_TYPE_BEACON
1374 , 60
1375 , rate, 1
1376 , HAL_TXKEYIX_INVALID
1377 , 0
1378 , flags
1379 , 0
1380 , 0
1381 )) {
1382 printf("%s: ath_hal_setup_tx_desc failed\n", __func__);
1383 return -1;
1384 }
1385
1386
1387 if (!ath_hal_fill_tx_desc(ah, ds
1388 , roundup(bf->bf_segs[0].ds_len, 4)
1389 , AH_TRUE
1390 , AH_TRUE
1391 )) {
1392 printf("%s: ath_hal_fill_tx_desc failed\n", __func__);
1393 return -1;
1394 }
1395
1396
1397
1398 return 0;
1399 }
1400
1401 void
1402 ath_beacon_proc(void *arg, int pending)
1403 {
1404 struct ath_softc *sc = arg;
1405 struct ieee80211com *ic = &sc->sc_ic;
1406 struct ath_buf *bf = sc->sc_bcbuf;
1407 struct ath_hal *ah = sc->sc_ah;
1408
1409 DPRINTF(ATH_DEBUG_BEACON_PROC, ("%s: pending %u\n", __func__, pending));
1410 if (ic->ic_opmode == IEEE80211_M_STA ||
1411 bf == NULL || bf->bf_m == NULL) {
1412 DPRINTF(ATH_DEBUG_ANY, ("%s: ic_flags=%x bf=%p bf_m=%p\n",
1413 __func__, ic->ic_flags, bf, bf ? bf->bf_m : NULL));
1414 return;
1415 }
1416
1417 if (!ath_hal_stop_tx_dma(ah, sc->sc_bhalq)) {
1418 DPRINTF(ATH_DEBUG_ANY, ("%s: beacon queue %u did not stop?\n",
1419 __func__, sc->sc_bhalq));
1420 }
1421 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, 0,
1422 bf->bf_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
1423
1424 ath_hal_put_tx_buf(ah, sc->sc_bhalq, bf->bf_daddr);
1425 ath_hal_tx_start(ah, sc->sc_bhalq);
1426 DPRINTF(ATH_DEBUG_BEACON_PROC,
1427 ("%s: TXDP%u = %p (%p)\n", __func__,
1428 sc->sc_bhalq, (caddr_t)bf->bf_daddr, bf->bf_desc));
1429 }
1430
1431 void
1432 ath_beacon_free(struct ath_softc *sc)
1433 {
1434 struct ath_buf *bf = sc->sc_bcbuf;
1435
1436 if (bf->bf_m != NULL) {
1437 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
1438 m_freem(bf->bf_m);
1439 bf->bf_m = NULL;
1440 bf->bf_node = NULL;
1441 }
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459 void
1460 ath_beacon_config(struct ath_softc *sc)
1461 {
1462 #define MS_TO_TU(x) (((x) * 1000) / 1024)
1463 struct ath_hal *ah = sc->sc_ah;
1464 struct ieee80211com *ic = &sc->sc_ic;
1465 struct ieee80211_node *ni = ic->ic_bss;
1466 u_int32_t nexttbtt, intval;
1467
1468 nexttbtt = (LE_READ_4(ni->ni_tstamp + 4) << 22) |
1469 (LE_READ_4(ni->ni_tstamp) >> 10);
1470 intval = MAX(1, ni->ni_intval) & HAL_BEACON_PERIOD;
1471 if (nexttbtt == 0) {
1472 nexttbtt = intval;
1473 } else if (intval) {
1474 nexttbtt = roundup(nexttbtt, intval);
1475 }
1476 DPRINTF(ATH_DEBUG_BEACON, ("%s: intval %u nexttbtt %u\n",
1477 __func__, ni->ni_intval, nexttbtt));
1478 if (ic->ic_opmode == IEEE80211_M_STA) {
1479 HAL_BEACON_STATE bs;
1480 u_int32_t bmisstime;
1481
1482
1483 bzero(&bs, sizeof(bs));
1484 bs.bs_intval = intval;
1485 bs.bs_nexttbtt = nexttbtt;
1486 bs.bs_dtimperiod = bs.bs_intval;
1487 bs.bs_nextdtim = nexttbtt;
1488
1489
1490
1491
1492
1493
1494
1495 bmisstime = MAX(7, ic->ic_bmisstimeout);
1496 bs.bs_bmissthreshold = howmany(bmisstime, intval);
1497 if (bs.bs_bmissthreshold > 7) {
1498 bs.bs_bmissthreshold = 7;
1499 } else if (bs.bs_bmissthreshold <= 0) {
1500 bs.bs_bmissthreshold = 1;
1501 }
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512 bs.bs_sleepduration =
1513 roundup(MS_TO_TU(100), bs.bs_intval);
1514 if (bs.bs_sleepduration > bs.bs_dtimperiod) {
1515 bs.bs_sleepduration =
1516 roundup(bs.bs_sleepduration, bs.bs_dtimperiod);
1517 }
1518
1519 DPRINTF(ATH_DEBUG_BEACON,
1520 ("%s: intval %u nexttbtt %u dtim %u nextdtim %u bmiss %u"
1521 " sleep %u\n"
1522 , __func__
1523 , bs.bs_intval
1524 , bs.bs_nexttbtt
1525 , bs.bs_dtimperiod
1526 , bs.bs_nextdtim
1527 , bs.bs_bmissthreshold
1528 , bs.bs_sleepduration
1529 ));
1530 ath_hal_set_intr(ah, 0);
1531 ath_hal_set_beacon_timers(ah, &bs, 0, 0, 0);
1532 sc->sc_imask |= HAL_INT_BMISS;
1533 ath_hal_set_intr(ah, sc->sc_imask);
1534 } else {
1535 ath_hal_set_intr(ah, 0);
1536 if (nexttbtt == intval)
1537 intval |= HAL_BEACON_RESET_TSF;
1538 if (ic->ic_opmode == IEEE80211_M_IBSS) {
1539
1540
1541
1542
1543
1544
1545
1546 intval |= HAL_BEACON_ENA;
1547 if (!sc->sc_veol)
1548 sc->sc_imask |= HAL_INT_SWBA;
1549 } else if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
1550
1551
1552
1553
1554 intval |= HAL_BEACON_ENA;
1555 sc->sc_imask |= HAL_INT_SWBA;
1556 }
1557 ath_hal_init_beacon(ah, nexttbtt, intval);
1558 ath_hal_set_intr(ah, sc->sc_imask);
1559
1560
1561
1562
1563 if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_veol)
1564 ath_beacon_proc(sc, 0);
1565 }
1566 }
1567
1568 int
1569 ath_desc_alloc(struct ath_softc *sc)
1570 {
1571 int i, bsize, error = -1;
1572 struct ath_desc *ds;
1573 struct ath_buf *bf;
1574
1575
1576 sc->sc_desc_len = sizeof(struct ath_desc) *
1577 (ATH_TXBUF * ATH_TXDESC + ATH_RXBUF + 1);
1578 if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_desc_len, PAGE_SIZE,
1579 0, &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) {
1580 printf("%s: unable to allocate control data, error = %d\n",
1581 sc->sc_dev.dv_xname, error);
1582 goto fail0;
1583 }
1584
1585 if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg,
1586 sc->sc_desc_len, (caddr_t *)&sc->sc_desc, BUS_DMA_COHERENT)) != 0) {
1587 printf("%s: unable to map control data, error = %d\n",
1588 sc->sc_dev.dv_xname, error);
1589 goto fail1;
1590 }
1591
1592 if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_desc_len, 1,
1593 sc->sc_desc_len, 0, 0, &sc->sc_ddmamap)) != 0) {
1594 printf("%s: unable to create control data DMA map, "
1595 "error = %d\n", sc->sc_dev.dv_xname, error);
1596 goto fail2;
1597 }
1598
1599 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, sc->sc_desc,
1600 sc->sc_desc_len, NULL, 0)) != 0) {
1601 printf("%s: unable to load control data DMA map, error = %d\n",
1602 sc->sc_dev.dv_xname, error);
1603 goto fail3;
1604 }
1605
1606 ds = sc->sc_desc;
1607 sc->sc_desc_paddr = sc->sc_ddmamap->dm_segs[0].ds_addr;
1608
1609 DPRINTF(ATH_DEBUG_XMIT_DESC|ATH_DEBUG_RECV_DESC,
1610 ("ath_desc_alloc: DMA map: %p (%lu) -> %p (%lu)\n",
1611 ds, (u_long)sc->sc_desc_len,
1612 (caddr_t) sc->sc_desc_paddr, (u_long) sc->sc_desc_len));
1613
1614
1615 bsize = sizeof(struct ath_buf) * (ATH_TXBUF + ATH_RXBUF + 1);
1616 bf = malloc(bsize, M_DEVBUF, M_NOWAIT);
1617 if (bf == NULL) {
1618 printf("%s: unable to allocate Tx/Rx buffers\n",
1619 sc->sc_dev.dv_xname);
1620 error = ENOMEM;
1621 goto fail3;
1622 }
1623 bzero(bf, bsize);
1624 sc->sc_bufptr = bf;
1625
1626 TAILQ_INIT(&sc->sc_rxbuf);
1627 for (i = 0; i < ATH_RXBUF; i++, bf++, ds++) {
1628 bf->bf_desc = ds;
1629 bf->bf_daddr = sc->sc_desc_paddr +
1630 ((caddr_t)ds - (caddr_t)sc->sc_desc);
1631 if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1,
1632 MCLBYTES, 0, 0, &bf->bf_dmamap)) != 0) {
1633 printf("%s: unable to create Rx dmamap, error = %d\n",
1634 sc->sc_dev.dv_xname, error);
1635 goto fail4;
1636 }
1637 TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
1638 }
1639
1640 TAILQ_INIT(&sc->sc_txbuf);
1641 for (i = 0; i < ATH_TXBUF; i++, bf++, ds += ATH_TXDESC) {
1642 bf->bf_desc = ds;
1643 bf->bf_daddr = sc->sc_desc_paddr +
1644 ((caddr_t)ds - (caddr_t)sc->sc_desc);
1645 if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES,
1646 ATH_TXDESC, MCLBYTES, 0, 0, &bf->bf_dmamap)) != 0) {
1647 printf("%s: unable to create Tx dmamap, error = %d\n",
1648 sc->sc_dev.dv_xname, error);
1649 goto fail5;
1650 }
1651 TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
1652 }
1653 TAILQ_INIT(&sc->sc_txq);
1654
1655
1656 bf->bf_desc = ds;
1657 bf->bf_daddr = sc->sc_desc_paddr + ((caddr_t)ds - (caddr_t)sc->sc_desc);
1658 if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, 0,
1659 &bf->bf_dmamap)) != 0) {
1660 printf("%s: unable to create beacon dmamap, error = %d\n",
1661 sc->sc_dev.dv_xname, error);
1662 goto fail5;
1663 }
1664 sc->sc_bcbuf = bf;
1665 return 0;
1666
1667 fail5:
1668 for (i = ATH_RXBUF; i < ATH_RXBUF + ATH_TXBUF; i++) {
1669 if (sc->sc_bufptr[i].bf_dmamap == NULL)
1670 continue;
1671 bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufptr[i].bf_dmamap);
1672 }
1673 fail4:
1674 for (i = 0; i < ATH_RXBUF; i++) {
1675 if (sc->sc_bufptr[i].bf_dmamap == NULL)
1676 continue;
1677 bus_dmamap_destroy(sc->sc_dmat, sc->sc_bufptr[i].bf_dmamap);
1678 }
1679 fail3:
1680 bus_dmamap_unload(sc->sc_dmat, sc->sc_ddmamap);
1681 fail2:
1682 bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
1683 sc->sc_ddmamap = NULL;
1684 fail1:
1685 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, sc->sc_desc_len);
1686 fail0:
1687 bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg);
1688 return error;
1689 }
1690
1691 void
1692 ath_desc_free(struct ath_softc *sc)
1693 {
1694 struct ath_buf *bf;
1695
1696 bus_dmamap_unload(sc->sc_dmat, sc->sc_ddmamap);
1697 bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
1698 bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg);
1699
1700 TAILQ_FOREACH(bf, &sc->sc_txq, bf_list) {
1701 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
1702 bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
1703 m_freem(bf->bf_m);
1704 }
1705 TAILQ_FOREACH(bf, &sc->sc_txbuf, bf_list)
1706 bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
1707 TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
1708 if (bf->bf_m) {
1709 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
1710 bus_dmamap_destroy(sc->sc_dmat, bf->bf_dmamap);
1711 m_freem(bf->bf_m);
1712 bf->bf_m = NULL;
1713 }
1714 }
1715 if (sc->sc_bcbuf != NULL) {
1716 bus_dmamap_unload(sc->sc_dmat, sc->sc_bcbuf->bf_dmamap);
1717 bus_dmamap_destroy(sc->sc_dmat, sc->sc_bcbuf->bf_dmamap);
1718 sc->sc_bcbuf = NULL;
1719 }
1720
1721 TAILQ_INIT(&sc->sc_rxbuf);
1722 TAILQ_INIT(&sc->sc_txbuf);
1723 TAILQ_INIT(&sc->sc_txq);
1724 free(sc->sc_bufptr, M_DEVBUF);
1725 sc->sc_bufptr = NULL;
1726 }
1727
1728 struct ieee80211_node *
1729 ath_node_alloc(struct ieee80211com *ic)
1730 {
1731 struct ath_node *an =
1732 malloc(sizeof(struct ath_node), M_DEVBUF, M_NOWAIT);
1733 if (an) {
1734 int i;
1735 bzero(an, sizeof(struct ath_node));
1736 for (i = 0; i < ATH_RHIST_SIZE; i++)
1737 an->an_rx_hist[i].arh_ticks = ATH_RHIST_NOTIME;
1738 an->an_rx_hist_next = ATH_RHIST_SIZE-1;
1739 return &an->an_node;
1740 } else
1741 return NULL;
1742 }
1743
1744 void
1745 ath_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
1746 {
1747 struct ath_softc *sc = ic->ic_if.if_softc;
1748 struct ath_buf *bf;
1749
1750 TAILQ_FOREACH(bf, &sc->sc_txq, bf_list) {
1751 if (bf->bf_node == ni)
1752 bf->bf_node = NULL;
1753 }
1754 (*sc->sc_node_free)(ic, ni);
1755 }
1756
1757 void
1758 ath_node_copy(struct ieee80211com *ic,
1759 struct ieee80211_node *dst, const struct ieee80211_node *src)
1760 {
1761 struct ath_softc *sc = ic->ic_if.if_softc;
1762
1763 bcopy(&src[1], &dst[1],
1764 sizeof(struct ath_node) - sizeof(struct ieee80211_node));
1765 (*sc->sc_node_copy)(ic, dst, src);
1766 }
1767
1768 u_int8_t
1769 ath_node_getrssi(struct ieee80211com *ic, const struct ieee80211_node *ni)
1770 {
1771 const struct ath_node *an = ATH_NODE(ni);
1772 int i, now, nsamples, rssi;
1773
1774
1775
1776
1777 now = ATH_TICKS();
1778 nsamples = 0;
1779 rssi = 0;
1780 i = an->an_rx_hist_next;
1781 do {
1782 const struct ath_recv_hist *rh = &an->an_rx_hist[i];
1783 if (rh->arh_ticks == ATH_RHIST_NOTIME)
1784 goto done;
1785 if (now - rh->arh_ticks > hz)
1786 goto done;
1787 rssi += rh->arh_rssi;
1788 nsamples++;
1789 if (i == 0) {
1790 i = ATH_RHIST_SIZE-1;
1791 } else {
1792 i--;
1793 }
1794 } while (i != an->an_rx_hist_next);
1795 done:
1796
1797
1798
1799
1800 return (nsamples ? rssi / nsamples : an->an_rx_hist[i].arh_rssi);
1801 }
1802
1803 int
1804 ath_rxbuf_init(struct ath_softc *sc, struct ath_buf *bf)
1805 {
1806 struct ath_hal *ah = sc->sc_ah;
1807 struct ieee80211com *ic = &sc->sc_ic;
1808 int error;
1809 struct mbuf *m;
1810 struct ath_desc *ds;
1811
1812 m = bf->bf_m;
1813 if (m == NULL) {
1814
1815
1816
1817
1818
1819
1820
1821 m = ath_getmbuf(M_DONTWAIT, MT_DATA, MCLBYTES);
1822 if (m == NULL) {
1823 DPRINTF(ATH_DEBUG_ANY,
1824 ("%s: no mbuf/cluster\n", __func__));
1825 sc->sc_stats.ast_rx_nombuf++;
1826 return ENOMEM;
1827 }
1828 bf->bf_m = m;
1829 m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
1830
1831 error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m,
1832 BUS_DMA_NOWAIT);
1833 if (error != 0) {
1834 DPRINTF(ATH_DEBUG_ANY,
1835 ("%s: ath_bus_dmamap_load_mbuf failed;"
1836 " error %d\n", __func__, error));
1837 sc->sc_stats.ast_rx_busdma++;
1838 return error;
1839 }
1840 KASSERT(bf->bf_nseg == 1,
1841 ("ath_rxbuf_init: multi-segment packet; nseg %u",
1842 bf->bf_nseg));
1843 }
1844 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, 0,
1845 bf->bf_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862 ds = bf->bf_desc;
1863 bzero(ds, sizeof(struct ath_desc));
1864 if (ic->ic_opmode != IEEE80211_M_HOSTAP)
1865 ds->ds_link = bf->bf_daddr;
1866 ds->ds_data = bf->bf_segs[0].ds_addr;
1867 ath_hal_setup_rx_desc(ah, ds
1868 , m->m_len
1869 , 0
1870 );
1871
1872 if (sc->sc_rxlink != NULL)
1873 *sc->sc_rxlink = bf->bf_daddr;
1874 sc->sc_rxlink = &ds->ds_link;
1875 return 0;
1876 }
1877
1878 void
1879 ath_rx_proc(void *arg, int npending)
1880 {
1881 #define PA2DESC(_sc, _pa) \
1882 ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
1883 ((_pa) - (_sc)->sc_desc_paddr)))
1884 struct ath_softc *sc = arg;
1885 struct ath_buf *bf;
1886 struct ieee80211com *ic = &sc->sc_ic;
1887 struct ifnet *ifp = &ic->ic_if;
1888 struct ath_hal *ah = sc->sc_ah;
1889 struct ath_desc *ds;
1890 struct mbuf *m;
1891 struct ieee80211_frame *wh, whbuf;
1892 struct ieee80211_node *ni;
1893 struct ath_node *an;
1894 struct ath_recv_hist *rh;
1895 int len;
1896 u_int phyerr;
1897 HAL_STATUS status;
1898
1899 DPRINTF(ATH_DEBUG_RX_PROC, ("%s: pending %u\n", __func__, npending));
1900 do {
1901 bf = TAILQ_FIRST(&sc->sc_rxbuf);
1902 if (bf == NULL) {
1903 printf("%s: ath_rx_proc: no buffer!\n", ifp->if_xname);
1904 break;
1905 }
1906 ds = bf->bf_desc;
1907 if (ds->ds_link == bf->bf_daddr) {
1908
1909 break;
1910 }
1911 m = bf->bf_m;
1912 if (m == NULL) {
1913 printf("%s: ath_rx_proc: no mbuf!\n", ifp->if_xname);
1914 continue;
1915 }
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928 status = ath_hal_proc_rx_desc(ah, ds,
1929 bf->bf_daddr, PA2DESC(sc, ds->ds_link));
1930 #ifdef AR_DEBUG
1931 if (ath_debug & ATH_DEBUG_RECV_DESC)
1932 ath_printrxbuf(bf, status == HAL_OK);
1933 #endif
1934 if (status == HAL_EINPROGRESS)
1935 break;
1936 TAILQ_REMOVE(&sc->sc_rxbuf, bf, bf_list);
1937
1938 if (ds->ds_rxstat.rs_more) {
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950 #ifdef ERROR_FRAMES
1951 if (ic->ic_opmode != IEEE80211_M_MONITOR) {
1952
1953 goto rx_next;
1954 }
1955 #endif
1956
1957
1958 } else if (ds->ds_rxstat.rs_status != 0) {
1959 if (ds->ds_rxstat.rs_status & HAL_RXERR_CRC)
1960 sc->sc_stats.ast_rx_crcerr++;
1961 if (ds->ds_rxstat.rs_status & HAL_RXERR_FIFO)
1962 sc->sc_stats.ast_rx_fifoerr++;
1963 if (ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT)
1964 sc->sc_stats.ast_rx_badcrypt++;
1965 if (ds->ds_rxstat.rs_status & HAL_RXERR_PHY) {
1966 sc->sc_stats.ast_rx_phyerr++;
1967 phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
1968 sc->sc_stats.ast_rx_phy[phyerr]++;
1969 }
1970
1971
1972
1973
1974
1975 if ((ds->ds_rxstat.rs_status & HAL_RXERR_DECRYPT ) ||
1976 (ds->ds_rxstat.rs_status & HAL_RXERR_PHY))
1977 goto rx_next;
1978
1979
1980
1981
1982
1983 if ((ds->ds_rxstat.rs_status & ~HAL_RXERR_DECRYPT) ||
1984 sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
1985 goto rx_next;
1986 }
1987
1988 len = ds->ds_rxstat.rs_datalen;
1989 if (len < IEEE80211_MIN_LEN) {
1990 DPRINTF(ATH_DEBUG_RECV, ("%s: short packet %d\n",
1991 __func__, len));
1992 sc->sc_stats.ast_rx_tooshort++;
1993 goto rx_next;
1994 }
1995
1996 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, 0,
1997 bf->bf_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
1998
1999 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2000 bf->bf_m = NULL;
2001 m->m_pkthdr.rcvif = ifp;
2002 m->m_pkthdr.len = m->m_len = len;
2003
2004 #if NBPFILTER > 0
2005 if (sc->sc_drvbpf) {
2006 struct mbuf mb;
2007
2008 sc->sc_rxtap.wr_rate =
2009 sc->sc_hwmap[ds->ds_rxstat.rs_rate] &
2010 IEEE80211_RATE_VAL;
2011 sc->sc_rxtap.wr_antenna = ds->ds_rxstat.rs_antenna;
2012 sc->sc_rxtap.wr_rssi = ds->ds_rxstat.rs_rssi;
2013 sc->sc_rxtap.wr_max_rssi = ic->ic_max_rssi;
2014
2015 mb.m_data = (caddr_t)&sc->sc_rxtap;
2016 mb.m_len = sc->sc_rxtap_len;
2017 mb.m_next = m;
2018 mb.m_nextpkt = NULL;
2019 mb.m_type = 0;
2020 mb.m_flags = 0;
2021 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_IN);
2022 }
2023 #endif
2024
2025 m_adj(m, -IEEE80211_CRC_LEN);
2026 wh = mtod(m, struct ieee80211_frame *);
2027 if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
2028
2029
2030
2031
2032 wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
2033 bcopy(wh, &whbuf, sizeof(whbuf));
2034 m_adj(m, IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN);
2035 wh = mtod(m, struct ieee80211_frame *);
2036 bcopy(&whbuf, wh, sizeof(whbuf));
2037
2038
2039
2040 m_adj(m, -IEEE80211_WEP_CRCLEN);
2041
2042
2043
2044 wh = mtod(m, struct ieee80211_frame *);
2045 }
2046
2047
2048
2049
2050
2051
2052 ni = ieee80211_find_rxnode(ic, wh);
2053
2054
2055
2056
2057 an = ATH_NODE(ni);
2058 if (++(an->an_rx_hist_next) == ATH_RHIST_SIZE)
2059 an->an_rx_hist_next = 0;
2060 rh = &an->an_rx_hist[an->an_rx_hist_next];
2061 rh->arh_ticks = ATH_TICKS();
2062 rh->arh_rssi = ds->ds_rxstat.rs_rssi;
2063 rh->arh_antenna = ds->ds_rxstat.rs_antenna;
2064
2065
2066
2067
2068 ieee80211_input(ifp, m, ni,
2069 ds->ds_rxstat.rs_rssi, ds->ds_rxstat.rs_tstamp);
2070
2071
2072 ieee80211_rssadapt_input(ic, ni, &an->an_rssadapt,
2073 ds->ds_rxstat.rs_rssi);
2074
2075
2076
2077
2078
2079
2080 ieee80211_release_node(ic, ni);
2081
2082 rx_next:
2083 TAILQ_INSERT_TAIL(&sc->sc_rxbuf, bf, bf_list);
2084 } while (ath_rxbuf_init(sc, bf) == 0);
2085
2086 ath_hal_set_rx_signal(ah);
2087 ath_hal_start_rx(ah);
2088
2089 if ((ifp->if_flags & IFF_OACTIVE) == 0 && !IFQ_IS_EMPTY(&ifp->if_snd))
2090 ath_start(ifp);
2091 #undef PA2DESC
2092 }
2093
2094
2095
2096
2097 #define IEEE80211_ACK_SIZE (2+2+IEEE80211_ADDR_LEN+4)
2098
2099 int
2100 ath_tx_start(struct ath_softc *sc, struct ieee80211_node *ni,
2101 struct ath_buf *bf, struct mbuf *m0)
2102 {
2103 struct ieee80211com *ic = &sc->sc_ic;
2104 struct ath_hal *ah = sc->sc_ah;
2105 struct ifnet *ifp = &sc->sc_ic.ic_if;
2106 int i, error, iswep, hdrlen, pktlen, len, s;
2107 u_int8_t rix, cix, txrate, ctsrate;
2108 struct ath_desc *ds;
2109 struct mbuf *m;
2110 struct ieee80211_frame *wh;
2111 u_int32_t iv;
2112 u_int8_t *ivp;
2113 u_int8_t hdrbuf[sizeof(struct ieee80211_frame) +
2114 IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN];
2115 u_int subtype, flags, ctsduration, antenna;
2116 HAL_PKT_TYPE atype;
2117 const HAL_RATE_TABLE *rt;
2118 HAL_BOOL shortPreamble;
2119 struct ath_node *an;
2120 u_int8_t hwqueue = HAL_TX_QUEUE_ID_DATA_MIN;
2121
2122 wh = mtod(m0, struct ieee80211_frame *);
2123 iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
2124 hdrlen = sizeof(struct ieee80211_frame);
2125 pktlen = m0->m_pkthdr.len;
2126
2127 if (iswep) {
2128 bcopy(mtod(m0, caddr_t), hdrbuf, hdrlen);
2129 m_adj(m0, hdrlen);
2130 M_PREPEND(m0, sizeof(hdrbuf), M_DONTWAIT);
2131 if (m0 == NULL) {
2132 sc->sc_stats.ast_tx_nombuf++;
2133 return ENOMEM;
2134 }
2135 ivp = hdrbuf + hdrlen;
2136 wh = mtod(m0, struct ieee80211_frame *);
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156 iv = ic->ic_iv;
2157 if ((iv & 0xff00) == 0xff00) {
2158 int B = (iv & 0xff0000) >> 16;
2159 if (3 <= B && B < 16)
2160 iv = (B+1) << 16;
2161 }
2162 ic->ic_iv = iv + 1;
2163
2164
2165
2166
2167
2168 #if AH_BYTE_ORDER == AH_BIG_ENDIAN
2169 ivp[0] = iv >> 0;
2170 ivp[1] = iv >> 8;
2171 ivp[2] = iv >> 16;
2172 #else
2173 ivp[2] = iv >> 0;
2174 ivp[1] = iv >> 8;
2175 ivp[0] = iv >> 16;
2176 #endif
2177 ivp[3] = ic->ic_wep_txkey << 6;
2178 bcopy(hdrbuf, mtod(m0, caddr_t), sizeof(hdrbuf));
2179
2180
2181
2182 len = IEEE80211_WEP_IVLEN +
2183 IEEE80211_WEP_KIDLEN +
2184 IEEE80211_WEP_CRCLEN;
2185 hdrlen += len;
2186 pktlen += len;
2187 }
2188 pktlen += IEEE80211_CRC_LEN;
2189
2190
2191
2192
2193
2194 error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m0,
2195 BUS_DMA_NOWAIT);
2196
2197
2198
2199
2200
2201 if (error == EFBIG) {
2202 sc->sc_stats.ast_tx_linear++;
2203 MGETHDR(m, M_DONTWAIT, MT_DATA);
2204 if (m == NULL) {
2205 sc->sc_stats.ast_tx_nombuf++;
2206 m_freem(m0);
2207 return ENOMEM;
2208 }
2209
2210 M_DUP_PKTHDR(m, m0);
2211 MCLGET(m, M_DONTWAIT);
2212 if ((m->m_flags & M_EXT) == 0) {
2213 sc->sc_stats.ast_tx_nomcl++;
2214 m_freem(m0);
2215 m_free(m);
2216 return ENOMEM;
2217 }
2218 m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
2219 m_freem(m0);
2220 m->m_len = m->m_pkthdr.len;
2221 m0 = m;
2222 error = bus_dmamap_load_mbuf(sc->sc_dmat, bf->bf_dmamap, m0,
2223 BUS_DMA_NOWAIT);
2224 if (error != 0) {
2225 sc->sc_stats.ast_tx_busdma++;
2226 m_freem(m0);
2227 return error;
2228 }
2229 KASSERT(bf->bf_nseg == 1,
2230 ("ath_tx_start: packet not one segment; nseg %u",
2231 bf->bf_nseg));
2232 } else if (error != 0) {
2233 sc->sc_stats.ast_tx_busdma++;
2234 m_freem(m0);
2235 return error;
2236 } else if (bf->bf_nseg == 0) {
2237 sc->sc_stats.ast_tx_nodata++;
2238 m_freem(m0);
2239 return EIO;
2240 }
2241 DPRINTF(ATH_DEBUG_XMIT, ("%s: m %p len %u\n", __func__, m0, pktlen));
2242 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, 0,
2243 bf->bf_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
2244 bf->bf_m = m0;
2245 bf->bf_node = ni;
2246 an = ATH_NODE(ni);
2247
2248
2249 ds = bf->bf_desc;
2250 rt = sc->sc_currates;
2251 KASSERT(rt != NULL, ("no rate table, mode %u", sc->sc_curmode));
2252
2253
2254
2255
2256
2257 bf->bf_id.id_node = NULL;
2258 atype = HAL_PKT_TYPE_NORMAL;
2259 switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
2260 case IEEE80211_FC0_TYPE_MGT:
2261 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2262 if (subtype == IEEE80211_FC0_SUBTYPE_BEACON) {
2263 atype = HAL_PKT_TYPE_BEACON;
2264 } else if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) {
2265 atype = HAL_PKT_TYPE_PROBE_RESP;
2266 } else if (subtype == IEEE80211_FC0_SUBTYPE_ATIM) {
2267 atype = HAL_PKT_TYPE_ATIM;
2268 }
2269 rix = 0;
2270 break;
2271 case IEEE80211_FC0_TYPE_CTL:
2272 subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
2273 if (subtype == IEEE80211_FC0_SUBTYPE_PS_POLL)
2274 atype = HAL_PKT_TYPE_PSPOLL;
2275 rix = 0;
2276 break;
2277 default:
2278
2279 if (ic->ic_fixed_rate == -1) {
2280 bf->bf_id.id_len = m0->m_pkthdr.len;
2281 bf->bf_id.id_rateidx = ni->ni_txrate;
2282 bf->bf_id.id_node = ni;
2283 bf->bf_id.id_rssi = ath_node_getrssi(ic, ni);
2284 }
2285 ni->ni_txrate = ieee80211_rssadapt_choose(&an->an_rssadapt,
2286 &ni->ni_rates, wh, m0->m_pkthdr.len, ic->ic_fixed_rate,
2287 ifp->if_xname, 0);
2288 rix = sc->sc_rixmap[ni->ni_rates.rs_rates[ni->ni_txrate] &
2289 IEEE80211_RATE_VAL];
2290 if (rix == 0xff) {
2291 printf("%s: bogus xmit rate 0x%x (idx 0x%x)\n",
2292 ifp->if_xname, ni->ni_rates.rs_rates[ni->ni_txrate],
2293 ni->ni_txrate);
2294 sc->sc_stats.ast_tx_badrate++;
2295 m_freem(m0);
2296 return EIO;
2297 }
2298 break;
2299 }
2300
2301
2302
2303
2304
2305
2306 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
2307 (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
2308 txrate = rt->info[rix].rateCode | rt->info[rix].shortPreamble;
2309 shortPreamble = AH_TRUE;
2310 sc->sc_stats.ast_tx_shortpre++;
2311 } else {
2312 txrate = rt->info[rix].rateCode;
2313 shortPreamble = AH_FALSE;
2314 }
2315
2316
2317
2318
2319 flags = HAL_TXDESC_CLRDMASK;
2320 if (IEEE80211_IS_MULTICAST(wh->i_addr1)) {
2321 flags |= HAL_TXDESC_NOACK;
2322 sc->sc_stats.ast_tx_noack++;
2323 } else if (pktlen > ic->ic_rtsthreshold) {
2324 flags |= HAL_TXDESC_RTSENA;
2325 sc->sc_stats.ast_tx_rts++;
2326 }
2327
2328
2329
2330
2331
2332 if ((flags & HAL_TXDESC_NOACK) == 0 &&
2333 (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
2334 u_int16_t dur;
2335
2336
2337
2338 dur = ath_hal_computetxtime(ah, rt, IEEE80211_ACK_SIZE,
2339 rix, shortPreamble);
2340 *((u_int16_t*) wh->i_dur) = htole16(dur);
2341 }
2342
2343
2344
2345
2346 ctsduration = 0;
2347 if (flags & (HAL_TXDESC_RTSENA|HAL_TXDESC_CTSENA)) {
2348
2349
2350
2351
2352
2353 cix = rt->info[rix].controlRate;
2354 ctsrate = rt->info[cix].rateCode;
2355 if (shortPreamble)
2356 ctsrate |= rt->info[cix].shortPreamble;
2357
2358
2359
2360
2361
2362
2363 if (flags & HAL_TXDESC_RTSENA) {
2364 ctsduration += ath_hal_computetxtime(ah,
2365 rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
2366 }
2367
2368 ctsduration += ath_hal_computetxtime(ah,
2369 rt, pktlen, rix, shortPreamble);
2370 if ((flags & HAL_TXDESC_NOACK) == 0) {
2371 ctsduration += ath_hal_computetxtime(ah,
2372 rt, IEEE80211_ACK_SIZE, cix, shortPreamble);
2373 }
2374 } else
2375 ctsrate = 0;
2376
2377
2378
2379
2380
2381
2382
2383 if (an->an_tx_antenna) {
2384 antenna = an->an_tx_antenna;
2385 } else {
2386 antenna = an->an_rx_hist[an->an_rx_hist_next].arh_antenna;
2387 }
2388
2389 #if NBPFILTER > 0
2390 if (ic->ic_rawbpf)
2391 bpf_mtap(ic->ic_rawbpf, m0, BPF_DIRECTION_OUT);
2392
2393 if (sc->sc_drvbpf) {
2394 struct mbuf mb;
2395
2396 sc->sc_txtap.wt_flags = 0;
2397 if (shortPreamble)
2398 sc->sc_txtap.wt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE;
2399 if (iswep)
2400 sc->sc_txtap.wt_flags |= IEEE80211_RADIOTAP_F_WEP;
2401 sc->sc_txtap.wt_rate = ni->ni_rates.rs_rates[ni->ni_txrate] &
2402 IEEE80211_RATE_VAL;
2403 sc->sc_txtap.wt_txpower = 30;
2404 sc->sc_txtap.wt_antenna = antenna;
2405 sc->sc_txtap.wt_hwqueue = hwqueue;
2406
2407 mb.m_data = (caddr_t)&sc->sc_txtap;
2408 mb.m_len = sc->sc_txtap_len;
2409 mb.m_next = m0;
2410 mb.m_nextpkt = NULL;
2411 mb.m_type = 0;
2412 mb.m_flags = 0;
2413 bpf_mtap(sc->sc_drvbpf, &mb, BPF_DIRECTION_OUT);
2414 }
2415 #endif
2416
2417
2418
2419
2420
2421 ath_hal_setup_tx_desc(ah, ds
2422 , pktlen
2423 , hdrlen
2424 , atype
2425 , 60
2426 , txrate, 1+10
2427 , iswep ? sc->sc_ic.ic_wep_txkey : HAL_TXKEYIX_INVALID
2428 , antenna
2429 , flags
2430 , ctsrate
2431 , ctsduration
2432 );
2433 #ifdef notyet
2434 ath_hal_setup_xtx_desc(ah, ds
2435 , AH_FALSE
2436 , 0, 0
2437 , 0, 0
2438 , 0, 0
2439 );
2440 #endif
2441
2442
2443
2444 for (i = 0; i < bf->bf_nseg; i++, ds++) {
2445 ds->ds_data = bf->bf_segs[i].ds_addr;
2446 if (i == bf->bf_nseg - 1) {
2447 ds->ds_link = 0;
2448 } else {
2449 ds->ds_link = bf->bf_daddr + sizeof(*ds) * (i + 1);
2450 }
2451 ath_hal_fill_tx_desc(ah, ds
2452 , bf->bf_segs[i].ds_len
2453 , i == 0
2454 , i == bf->bf_nseg - 1
2455 );
2456 DPRINTF(ATH_DEBUG_XMIT,
2457 ("%s: %d: %08x %08x %08x %08x %08x %08x\n",
2458 __func__, i, ds->ds_link, ds->ds_data,
2459 ds->ds_ctl0, ds->ds_ctl1, ds->ds_hw[0], ds->ds_hw[1]));
2460 }
2461
2462
2463
2464
2465
2466 s = splnet();
2467 TAILQ_INSERT_TAIL(&sc->sc_txq, bf, bf_list);
2468 if (sc->sc_txlink == NULL) {
2469 ath_hal_put_tx_buf(ah, sc->sc_txhalq[hwqueue], bf->bf_daddr);
2470 DPRINTF(ATH_DEBUG_XMIT, ("%s: TXDP0 = %p (%p)\n", __func__,
2471 (caddr_t)bf->bf_daddr, bf->bf_desc));
2472 } else {
2473 *sc->sc_txlink = bf->bf_daddr;
2474 DPRINTF(ATH_DEBUG_XMIT, ("%s: link(%p)=%p (%p)\n", __func__,
2475 sc->sc_txlink, (caddr_t)bf->bf_daddr, bf->bf_desc));
2476 }
2477 sc->sc_txlink = &bf->bf_desc[bf->bf_nseg - 1].ds_link;
2478 splx(s);
2479
2480 ath_hal_tx_start(ah, sc->sc_txhalq[hwqueue]);
2481 return 0;
2482 }
2483
2484 void
2485 ath_tx_proc(void *arg, int npending)
2486 {
2487 struct ath_softc *sc = arg;
2488 struct ath_hal *ah = sc->sc_ah;
2489 struct ath_buf *bf;
2490 struct ieee80211com *ic = &sc->sc_ic;
2491 struct ifnet *ifp = &ic->ic_if;
2492 struct ath_desc *ds;
2493 struct ieee80211_node *ni;
2494 struct ath_node *an;
2495 int sr, lr, s;
2496 HAL_STATUS status;
2497
2498 for (;;) {
2499 s = splnet();
2500 bf = TAILQ_FIRST(&sc->sc_txq);
2501 if (bf == NULL) {
2502 sc->sc_txlink = NULL;
2503 splx(s);
2504 break;
2505 }
2506
2507 ds = &bf->bf_desc[bf->bf_nseg - 1];
2508 status = ath_hal_proc_tx_desc(ah, ds);
2509 #ifdef AR_DEBUG
2510 if (ath_debug & ATH_DEBUG_XMIT_DESC)
2511 ath_printtxbuf(bf, status == HAL_OK);
2512 #endif
2513 if (status == HAL_EINPROGRESS) {
2514 splx(s);
2515 break;
2516 }
2517 TAILQ_REMOVE(&sc->sc_txq, bf, bf_list);
2518 splx(s);
2519
2520 ni = bf->bf_node;
2521 if (ni != NULL) {
2522 an = (struct ath_node *) ni;
2523 if (ds->ds_txstat.ts_status == 0) {
2524 if (bf->bf_id.id_node != NULL)
2525 ieee80211_rssadapt_raise_rate(ic,
2526 &an->an_rssadapt, &bf->bf_id);
2527 an->an_tx_antenna = ds->ds_txstat.ts_antenna;
2528 } else {
2529 if (bf->bf_id.id_node != NULL)
2530 ieee80211_rssadapt_lower_rate(ic, ni,
2531 &an->an_rssadapt, &bf->bf_id);
2532 ifp->if_oerrors++;
2533 if (ds->ds_txstat.ts_status & HAL_TXERR_XRETRY)
2534 sc->sc_stats.ast_tx_xretries++;
2535 if (ds->ds_txstat.ts_status & HAL_TXERR_FIFO)
2536 sc->sc_stats.ast_tx_fifoerr++;
2537 if (ds->ds_txstat.ts_status & HAL_TXERR_FILT)
2538 sc->sc_stats.ast_tx_filtered++;
2539 an->an_tx_antenna = 0;
2540 }
2541 sr = ds->ds_txstat.ts_shortretry;
2542 lr = ds->ds_txstat.ts_longretry;
2543 sc->sc_stats.ast_tx_shortretry += sr;
2544 sc->sc_stats.ast_tx_longretry += lr;
2545
2546
2547
2548
2549
2550
2551
2552 ieee80211_release_node(ic, ni);
2553 }
2554 bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap, 0,
2555 bf->bf_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
2556 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2557 m_freem(bf->bf_m);
2558 bf->bf_m = NULL;
2559 bf->bf_node = NULL;
2560
2561 s = splnet();
2562 TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
2563 splx(s);
2564 }
2565 ifp->if_flags &= ~IFF_OACTIVE;
2566 sc->sc_tx_timer = 0;
2567
2568 ath_start(ifp);
2569 }
2570
2571
2572
2573
2574 void
2575 ath_draintxq(struct ath_softc *sc)
2576 {
2577 struct ath_hal *ah = sc->sc_ah;
2578 struct ieee80211com *ic = &sc->sc_ic;
2579 struct ifnet *ifp = &ic->ic_if;
2580 struct ieee80211_node *ni;
2581 struct ath_buf *bf;
2582 int s, i;
2583
2584
2585 if (!sc->sc_invalid) {
2586 for (i = 0; i <= HAL_TX_QUEUE_ID_DATA_MAX; i++) {
2587
2588 (void) ath_hal_stop_tx_dma(ah, sc->sc_txhalq[i]);
2589 DPRINTF(ATH_DEBUG_RESET,
2590 ("%s: tx queue %d (%p), link %p\n", __func__, i,
2591 (caddr_t)(u_intptr_t)ath_hal_get_tx_buf(ah,
2592 sc->sc_txhalq[i]), sc->sc_txlink));
2593 }
2594 (void) ath_hal_stop_tx_dma(ah, sc->sc_bhalq);
2595 DPRINTF(ATH_DEBUG_RESET,
2596 ("%s: beacon queue (%p)\n", __func__,
2597 (caddr_t)(u_intptr_t)ath_hal_get_tx_buf(ah, sc->sc_bhalq)));
2598 }
2599 for (;;) {
2600 s = splnet();
2601 bf = TAILQ_FIRST(&sc->sc_txq);
2602 if (bf == NULL) {
2603 sc->sc_txlink = NULL;
2604 splx(s);
2605 break;
2606 }
2607 TAILQ_REMOVE(&sc->sc_txq, bf, bf_list);
2608 splx(s);
2609 #ifdef AR_DEBUG
2610 if (ath_debug & ATH_DEBUG_RESET) {
2611 ath_printtxbuf(bf,
2612 ath_hal_proc_tx_desc(ah, bf->bf_desc) == HAL_OK);
2613 }
2614 #endif
2615 bus_dmamap_unload(sc->sc_dmat, bf->bf_dmamap);
2616 m_freem(bf->bf_m);
2617 bf->bf_m = NULL;
2618 ni = bf->bf_node;
2619 bf->bf_node = NULL;
2620 s = splnet();
2621 if (ni != NULL) {
2622
2623
2624
2625 ieee80211_release_node(ic, ni);
2626 }
2627 TAILQ_INSERT_TAIL(&sc->sc_txbuf, bf, bf_list);
2628 splx(s);
2629 }
2630 ifp->if_flags &= ~IFF_OACTIVE;
2631 sc->sc_tx_timer = 0;
2632 }
2633
2634
2635
2636
2637 void
2638 ath_stoprecv(struct ath_softc *sc)
2639 {
2640 #define PA2DESC(_sc, _pa) \
2641 ((struct ath_desc *)((caddr_t)(_sc)->sc_desc + \
2642 ((_pa) - (_sc)->sc_desc_paddr)))
2643 struct ath_hal *ah = sc->sc_ah;
2644
2645 ath_hal_stop_pcu_recv(ah);
2646 ath_hal_set_rx_filter(ah, 0);
2647 ath_hal_stop_rx_dma(ah);
2648 #ifdef AR_DEBUG
2649 if (ath_debug & ATH_DEBUG_RESET) {
2650 struct ath_buf *bf;
2651
2652 printf("%s: rx queue %p, link %p\n", __func__,
2653 (caddr_t)(u_intptr_t)ath_hal_get_rx_buf(ah), sc->sc_rxlink);
2654 TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
2655 struct ath_desc *ds = bf->bf_desc;
2656 if (ath_hal_proc_rx_desc(ah, ds, bf->bf_daddr,
2657 PA2DESC(sc, ds->ds_link)) == HAL_OK)
2658 ath_printrxbuf(bf, 1);
2659 }
2660 }
2661 #endif
2662 sc->sc_rxlink = NULL;
2663 #undef PA2DESC
2664 }
2665
2666
2667
2668
2669 int
2670 ath_startrecv(struct ath_softc *sc)
2671 {
2672 struct ath_hal *ah = sc->sc_ah;
2673 struct ath_buf *bf;
2674
2675 sc->sc_rxlink = NULL;
2676 TAILQ_FOREACH(bf, &sc->sc_rxbuf, bf_list) {
2677 int error = ath_rxbuf_init(sc, bf);
2678 if (error != 0) {
2679 DPRINTF(ATH_DEBUG_RECV,
2680 ("%s: ath_rxbuf_init failed %d\n",
2681 __func__, error));
2682 return error;
2683 }
2684 }
2685
2686 bf = TAILQ_FIRST(&sc->sc_rxbuf);
2687 ath_hal_put_rx_buf(ah, bf->bf_daddr);
2688 ath_hal_start_rx(ah);
2689 ath_mode_init(sc);
2690 ath_hal_start_rx_pcu(ah);
2691 return 0;
2692 }
2693
2694
2695
2696
2697
2698
2699
2700 int
2701 ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan)
2702 {
2703 struct ath_hal *ah = sc->sc_ah;
2704 struct ieee80211com *ic = &sc->sc_ic;
2705 struct ifnet *ifp = &ic->ic_if;
2706
2707 DPRINTF(ATH_DEBUG_ANY, ("%s: %u (%u MHz) -> %u (%u MHz)\n", __func__,
2708 ieee80211_chan2ieee(ic, ic->ic_ibss_chan),
2709 ic->ic_ibss_chan->ic_freq,
2710 ieee80211_chan2ieee(ic, chan), chan->ic_freq));
2711 if (chan != ic->ic_ibss_chan) {
2712 HAL_STATUS status;
2713 HAL_CHANNEL hchan;
2714 enum ieee80211_phymode mode;
2715
2716
2717
2718
2719
2720
2721
2722 ath_hal_set_intr(ah, 0);
2723 ath_draintxq(sc);
2724 ath_stoprecv(sc);
2725
2726
2727
2728
2729
2730 hchan.channel = chan->ic_freq;
2731 hchan.channelFlags = ath_chan2flags(ic, chan);
2732 if (!ath_hal_reset(ah, ic->ic_opmode, &hchan, AH_TRUE,
2733 &status)) {
2734 printf("%s: ath_chan_set: unable to reset "
2735 "channel %u (%u MHz)\n", ifp->if_xname,
2736 ieee80211_chan2ieee(ic, chan), chan->ic_freq);
2737 return EIO;
2738 }
2739 ath_set_slot_time(sc);
2740
2741
2742
2743 if (ath_startrecv(sc) != 0) {
2744 printf("%s: ath_chan_set: unable to restart recv "
2745 "logic\n", ifp->if_xname);
2746 return EIO;
2747 }
2748
2749 #if NBPFILTER > 0
2750
2751
2752
2753 sc->sc_txtap.wt_chan_freq = sc->sc_rxtap.wr_chan_freq =
2754 htole16(chan->ic_freq);
2755 sc->sc_txtap.wt_chan_flags = sc->sc_rxtap.wr_chan_flags =
2756 htole16(chan->ic_flags);
2757 #endif
2758
2759
2760
2761
2762
2763 ic->ic_ibss_chan = chan;
2764 mode = ieee80211_chan2mode(ic, chan);
2765 if (mode != sc->sc_curmode)
2766 ath_setcurmode(sc, mode);
2767
2768
2769
2770
2771 ath_hal_set_intr(ah, sc->sc_imask);
2772 }
2773 return 0;
2774 }
2775
2776 void
2777 ath_next_scan(void *arg)
2778 {
2779 struct ath_softc *sc = arg;
2780 struct ieee80211com *ic = &sc->sc_ic;
2781 struct ifnet *ifp = &ic->ic_if;
2782 int s;
2783
2784
2785 s = splnet();
2786
2787 if (ic->ic_state == IEEE80211_S_SCAN)
2788 ieee80211_next_scan(ifp);
2789 splx(s);
2790 }
2791
2792 int
2793 ath_set_slot_time(struct ath_softc *sc)
2794 {
2795 struct ath_hal *ah = sc->sc_ah;
2796 struct ieee80211com *ic = &sc->sc_ic;
2797
2798 if (ic->ic_flags & IEEE80211_F_SHSLOT)
2799 return (ath_hal_set_slot_time(ah, HAL_SLOT_TIME_9));
2800
2801 return (0);
2802 }
2803
2804
2805
2806
2807
2808 void
2809 ath_calibrate(void *arg)
2810 {
2811 struct ath_softc *sc = arg;
2812 struct ath_hal *ah = sc->sc_ah;
2813 struct ieee80211com *ic = &sc->sc_ic;
2814 struct ieee80211_channel *c;
2815 HAL_CHANNEL hchan;
2816 int s;
2817
2818 sc->sc_stats.ast_per_cal++;
2819
2820
2821
2822
2823
2824 c = ic->ic_ibss_chan;
2825 hchan.channel = c->ic_freq;
2826 hchan.channelFlags = ath_chan2flags(ic, c);
2827
2828 s = splnet();
2829 DPRINTF(ATH_DEBUG_CALIBRATE,
2830 ("%s: channel %u/%x\n", __func__, c->ic_freq, c->ic_flags));
2831
2832 if (ath_hal_get_rf_gain(ah) == HAL_RFGAIN_NEED_CHANGE) {
2833
2834
2835
2836
2837 sc->sc_stats.ast_per_rfgain++;
2838 ath_reset(sc, 1);
2839 }
2840 if (!ath_hal_calibrate(ah, &hchan)) {
2841 DPRINTF(ATH_DEBUG_ANY,
2842 ("%s: calibration of channel %u failed\n",
2843 __func__, c->ic_freq));
2844 sc->sc_stats.ast_per_calfail++;
2845 }
2846 timeout_add(&sc->sc_cal_to, hz * ath_calinterval);
2847 splx(s);
2848 }
2849
2850 void
2851 ath_ledstate(struct ath_softc *sc, enum ieee80211_state state)
2852 {
2853 HAL_LED_STATE led = HAL_LED_INIT;
2854 u_int32_t softled = AR5K_SOFTLED_OFF;
2855
2856 switch (state) {
2857 case IEEE80211_S_INIT:
2858 break;
2859 case IEEE80211_S_SCAN:
2860 led = HAL_LED_SCAN;
2861 break;
2862 case IEEE80211_S_AUTH:
2863 led = HAL_LED_AUTH;
2864 break;
2865 case IEEE80211_S_ASSOC:
2866 led = HAL_LED_ASSOC;
2867 softled = AR5K_SOFTLED_ON;
2868 break;
2869 case IEEE80211_S_RUN:
2870 led = HAL_LED_RUN;
2871 softled = AR5K_SOFTLED_ON;
2872 break;
2873 }
2874
2875 ath_hal_set_ledstate(sc->sc_ah, led);
2876 if (sc->sc_softled) {
2877 ath_hal_set_gpio_output(sc->sc_ah, AR5K_SOFTLED_PIN);
2878 ath_hal_set_gpio(sc->sc_ah, AR5K_SOFTLED_PIN, softled);
2879 }
2880 }
2881
2882 int
2883 ath_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
2884 {
2885 struct ifnet *ifp = &ic->ic_if;
2886 struct ath_softc *sc = ifp->if_softc;
2887 struct ath_hal *ah = sc->sc_ah;
2888 struct ieee80211_node *ni;
2889 const u_int8_t *bssid;
2890 int i, error;
2891 u_int32_t rfilt;
2892
2893 DPRINTF(ATH_DEBUG_ANY, ("%s: %s -> %s\n", __func__,
2894 ieee80211_state_name[ic->ic_state],
2895 ieee80211_state_name[nstate]));
2896
2897 timeout_del(&sc->sc_scan_to);
2898 timeout_del(&sc->sc_cal_to);
2899 ath_ledstate(sc, nstate);
2900
2901 if (nstate == IEEE80211_S_INIT) {
2902 timeout_del(&sc->sc_rssadapt_to);
2903 sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
2904 ath_hal_set_intr(ah, sc->sc_imask);
2905 return (*sc->sc_newstate)(ic, nstate, arg);
2906 }
2907 ni = ic->ic_bss;
2908 error = ath_chan_set(sc, ni->ni_chan);
2909 if (error != 0)
2910 goto bad;
2911 rfilt = ath_calcrxfilter(sc);
2912 if (nstate == IEEE80211_S_SCAN ||
2913 ic->ic_opmode == IEEE80211_M_MONITOR) {
2914 bssid = sc->sc_broadcast_addr;
2915 } else {
2916 bssid = ni->ni_bssid;
2917 }
2918 ath_hal_set_rx_filter(ah, rfilt);
2919 DPRINTF(ATH_DEBUG_ANY, ("%s: RX filter 0x%x bssid %s\n",
2920 __func__, rfilt, ether_sprintf((u_char*)bssid)));
2921
2922 if (nstate == IEEE80211_S_RUN && ic->ic_opmode == IEEE80211_M_STA) {
2923 ath_hal_set_associd(ah, bssid, ni->ni_associd);
2924 } else {
2925 ath_hal_set_associd(ah, bssid, 0);
2926 }
2927
2928 if (ic->ic_flags & IEEE80211_F_WEPON) {
2929 for (i = 0; i < IEEE80211_WEP_NKID; i++) {
2930 if (ath_hal_is_key_valid(ah, i))
2931 ath_hal_set_key_lladdr(ah, i, bssid);
2932 }
2933 }
2934
2935 if (ic->ic_opmode == IEEE80211_M_MONITOR) {
2936
2937 } else if (nstate == IEEE80211_S_RUN) {
2938 DPRINTF(ATH_DEBUG_ANY, ("%s(RUN): "
2939 "ic_flags=0x%08x iv=%d bssid=%s "
2940 "capinfo=0x%04x chan=%d\n",
2941 __func__,
2942 ic->ic_flags,
2943 ni->ni_intval,
2944 ether_sprintf(ni->ni_bssid),
2945 ni->ni_capinfo,
2946 ieee80211_chan2ieee(ic, ni->ni_chan)));
2947
2948
2949
2950
2951 if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
2952 ic->ic_opmode == IEEE80211_M_IBSS) {
2953 error = ath_beacon_alloc(sc, ni);
2954 if (error != 0)
2955 goto bad;
2956 }
2957
2958
2959
2960
2961 ath_beacon_config(sc);
2962 } else {
2963 sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
2964 ath_hal_set_intr(ah, sc->sc_imask);
2965 }
2966
2967
2968
2969
2970 error = (*sc->sc_newstate)(ic, nstate, arg);
2971
2972 if (nstate == IEEE80211_S_RUN) {
2973
2974 timeout_add(&sc->sc_cal_to, hz * ath_calinterval);
2975
2976 if (ic->ic_opmode != IEEE80211_M_MONITOR)
2977 timeout_add(&sc->sc_rssadapt_to, hz / 10);
2978 } else if (nstate == IEEE80211_S_SCAN) {
2979
2980 timeout_add(&sc->sc_scan_to, (hz * ath_dwelltime) / 1000);
2981 }
2982 bad:
2983 return error;
2984 }
2985
2986 void
2987 ath_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
2988 struct ieee80211_node *ni, int subtype, int rssi, u_int32_t rstamp)
2989 {
2990 struct ath_softc *sc = (struct ath_softc*)ic->ic_softc;
2991 struct ath_hal *ah = sc->sc_ah;
2992
2993 (*sc->sc_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
2994
2995 switch (subtype) {
2996 case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
2997 case IEEE80211_FC0_SUBTYPE_BEACON:
2998 if (ic->ic_opmode != IEEE80211_M_IBSS ||
2999 ic->ic_state != IEEE80211_S_RUN)
3000 break;
3001 if (ieee80211_ibss_merge(ic, ni, ath_hal_get_tsf64(ah)) ==
3002 ENETRESET)
3003 ath_hal_set_associd(ah, ic->ic_bss->ni_bssid, 0);
3004 break;
3005 default:
3006 break;
3007 }
3008 return;
3009 }
3010
3011
3012
3013
3014
3015
3016 void
3017 ath_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni, int isnew)
3018 {
3019 if (ic->ic_opmode == IEEE80211_M_MONITOR)
3020 return;
3021 }
3022
3023 int
3024 ath_getchannels(struct ath_softc *sc, HAL_BOOL outdoor, HAL_BOOL xchanmode)
3025 {
3026 struct ieee80211com *ic = &sc->sc_ic;
3027 struct ifnet *ifp = &ic->ic_if;
3028 struct ath_hal *ah = sc->sc_ah;
3029 HAL_CHANNEL *chans;
3030 int i, ix, nchan;
3031
3032 sc->sc_nchan = 0;
3033 chans = malloc(IEEE80211_CHAN_MAX * sizeof(HAL_CHANNEL),
3034 M_TEMP, M_NOWAIT);
3035 if (chans == NULL) {
3036 printf("%s: unable to allocate channel table\n", ifp->if_xname);
3037 return ENOMEM;
3038 }
3039 if (!ath_hal_init_channels(ah, chans, IEEE80211_CHAN_MAX, &nchan,
3040 HAL_MODE_ALL, outdoor, xchanmode)) {
3041 printf("%s: unable to collect channel list from hal\n",
3042 ifp->if_xname);
3043 free(chans, M_TEMP);
3044 return EINVAL;
3045 }
3046
3047
3048
3049
3050
3051 for (i = 0; i < nchan; i++) {
3052 HAL_CHANNEL *c = &chans[i];
3053 ix = ieee80211_mhz2ieee(c->channel, c->channelFlags);
3054 if (ix > IEEE80211_CHAN_MAX) {
3055 printf("%s: bad hal channel %u (%u/%x) ignored\n",
3056 ifp->if_xname, ix, c->channel, c->channelFlags);
3057 continue;
3058 }
3059 DPRINTF(ATH_DEBUG_ANY,
3060 ("%s: HAL channel %d/%d freq %d flags %#04x idx %d\n",
3061 sc->sc_dev.dv_xname, i, nchan, c->channel, c->channelFlags,
3062 ix));
3063
3064 if (ic->ic_channels[ix].ic_freq == 0) {
3065 ic->ic_channels[ix].ic_freq = c->channel;
3066 ic->ic_channels[ix].ic_flags = c->channelFlags;
3067 } else {
3068
3069 ic->ic_channels[ix].ic_flags |= c->channelFlags;
3070 }
3071
3072 sc->sc_nchan++;
3073 }
3074 free(chans, M_TEMP);
3075
3076 if (sc->sc_nchan < 1) {
3077 printf("%s: no valid channels for regdomain %s(%u)\n",
3078 ifp->if_xname, ieee80211_regdomain2name(ah->ah_regdomain),
3079 ah->ah_regdomain);
3080 return ENOENT;
3081 }
3082
3083
3084 ic->ic_ibss_chan = &ic->ic_channels[0];
3085
3086 return 0;
3087 }
3088
3089 int
3090 ath_rate_setup(struct ath_softc *sc, u_int mode)
3091 {
3092 struct ath_hal *ah = sc->sc_ah;
3093 struct ieee80211com *ic = &sc->sc_ic;
3094 const HAL_RATE_TABLE *rt;
3095 struct ieee80211_rateset *rs;
3096 int i, maxrates;
3097
3098 switch (mode) {
3099 case IEEE80211_MODE_11A:
3100 sc->sc_rates[mode] = ath_hal_get_rate_table(ah, HAL_MODE_11A);
3101 break;
3102 case IEEE80211_MODE_11B:
3103 sc->sc_rates[mode] = ath_hal_get_rate_table(ah, HAL_MODE_11B);
3104 break;
3105 case IEEE80211_MODE_11G:
3106 sc->sc_rates[mode] = ath_hal_get_rate_table(ah, HAL_MODE_11G);
3107 break;
3108 case IEEE80211_MODE_TURBO:
3109 sc->sc_rates[mode] = ath_hal_get_rate_table(ah, HAL_MODE_TURBO);
3110 break;
3111 default:
3112 DPRINTF(ATH_DEBUG_ANY,
3113 ("%s: invalid mode %u\n", __func__, mode));
3114 return 0;
3115 }
3116 rt = sc->sc_rates[mode];
3117 if (rt == NULL)
3118 return 0;
3119 if (rt->rateCount > IEEE80211_RATE_MAXSIZE) {
3120 DPRINTF(ATH_DEBUG_ANY,
3121 ("%s: rate table too small (%u > %u)\n",
3122 __func__, rt->rateCount, IEEE80211_RATE_MAXSIZE));
3123 maxrates = IEEE80211_RATE_MAXSIZE;
3124 } else {
3125 maxrates = rt->rateCount;
3126 }
3127 rs = &ic->ic_sup_rates[mode];
3128 for (i = 0; i < maxrates; i++)
3129 rs->rs_rates[i] = rt->info[i].dot11Rate;
3130 rs->rs_nrates = maxrates;
3131 return 1;
3132 }
3133
3134 void
3135 ath_setcurmode(struct ath_softc *sc, enum ieee80211_phymode mode)
3136 {
3137 const HAL_RATE_TABLE *rt;
3138 int i;
3139
3140 memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
3141 rt = sc->sc_rates[mode];
3142 KASSERT(rt != NULL, ("no h/w rate set for phy mode %u", mode));
3143 for (i = 0; i < rt->rateCount; i++)
3144 sc->sc_rixmap[rt->info[i].dot11Rate & IEEE80211_RATE_VAL] = i;
3145 bzero(sc->sc_hwmap, sizeof(sc->sc_hwmap));
3146 for (i = 0; i < 32; i++)
3147 sc->sc_hwmap[i] = rt->info[rt->rateCodeToIndex[i]].dot11Rate;
3148 sc->sc_currates = rt;
3149 sc->sc_curmode = mode;
3150 }
3151
3152 void
3153 ath_rssadapt_updatenode(void *arg, struct ieee80211_node *ni)
3154 {
3155 struct ath_node *an = ATH_NODE(ni);
3156
3157 ieee80211_rssadapt_updatestats(&an->an_rssadapt);
3158 }
3159
3160 void
3161 ath_rssadapt_updatestats(void *arg)
3162 {
3163 struct ath_softc *sc = (struct ath_softc *)arg;
3164 struct ieee80211com *ic = &sc->sc_ic;
3165
3166 if (ic->ic_opmode == IEEE80211_M_STA) {
3167 ath_rssadapt_updatenode(arg, ic->ic_bss);
3168 } else {
3169 ieee80211_iterate_nodes(ic, ath_rssadapt_updatenode, arg);
3170 }
3171
3172 timeout_add(&sc->sc_rssadapt_to, hz / 10);
3173 }
3174
3175 #ifdef AR_DEBUG
3176 void
3177 ath_printrxbuf(struct ath_buf *bf, int done)
3178 {
3179 struct ath_desc *ds;
3180 int i;
3181
3182 for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) {
3183 printf("R%d (%p %p) %08x %08x %08x %08x %08x %08x %c\n",
3184 i, ds, (struct ath_desc *)bf->bf_daddr + i,
3185 ds->ds_link, ds->ds_data,
3186 ds->ds_ctl0, ds->ds_ctl1,
3187 ds->ds_hw[0], ds->ds_hw[1],
3188 !done ? ' ' : (ds->ds_rxstat.rs_status == 0) ? '*' : '!');
3189 }
3190 }
3191
3192 void
3193 ath_printtxbuf(struct ath_buf *bf, int done)
3194 {
3195 struct ath_desc *ds;
3196 int i;
3197
3198 for (i = 0, ds = bf->bf_desc; i < bf->bf_nseg; i++, ds++) {
3199 printf("T%d (%p %p) "
3200 "%08x %08x %08x %08x %08x %08x %08x %08x %c\n",
3201 i, ds, (struct ath_desc *)bf->bf_daddr + i,
3202 ds->ds_link, ds->ds_data,
3203 ds->ds_ctl0, ds->ds_ctl1,
3204 ds->ds_hw[0], ds->ds_hw[1], ds->ds_hw[2], ds->ds_hw[3],
3205 !done ? ' ' : (ds->ds_txstat.ts_status == 0) ? '*' : '!');
3206 }
3207 }
3208 #endif
3209
3210 int
3211 ath_gpio_attach(struct ath_softc *sc, u_int16_t devid)
3212 {
3213 struct ath_hal *ah = sc->sc_ah;
3214 struct gpiobus_attach_args gba;
3215 int i;
3216
3217 if (ah->ah_gpio_npins < 1)
3218 return 0;
3219
3220
3221 for (i = 0; i < ah->ah_gpio_npins && i < AR5K_MAX_GPIO; i++) {
3222 sc->sc_gpio_pins[i].pin_num = i;
3223 sc->sc_gpio_pins[i].pin_caps = GPIO_PIN_INPUT |
3224 GPIO_PIN_OUTPUT;
3225
3226
3227 ath_hal_set_gpio_input(ah, i);
3228 sc->sc_gpio_pins[i].pin_flags = GPIO_PIN_INPUT;
3229
3230
3231 sc->sc_gpio_pins[i].pin_state = ath_hal_get_gpio(ah, i) ?
3232 GPIO_PIN_HIGH : GPIO_PIN_LOW;
3233 }
3234
3235
3236 if ((ah->ah_version == AR5K_AR5211) ||
3237 (devid == PCI_PRODUCT_ATHEROS_AR5212_IBM)) {
3238 sc->sc_softled = 1;
3239 ath_hal_set_gpio_output(ah, AR5K_SOFTLED_PIN);
3240 ath_hal_set_gpio(ah, AR5K_SOFTLED_PIN, AR5K_SOFTLED_OFF);
3241 }
3242
3243
3244 sc->sc_gpio_gc.gp_cookie = sc;
3245 sc->sc_gpio_gc.gp_pin_read = ath_gpio_pin_read;
3246 sc->sc_gpio_gc.gp_pin_write = ath_gpio_pin_write;
3247 sc->sc_gpio_gc.gp_pin_ctl = ath_gpio_pin_ctl;
3248
3249 gba.gba_name = "gpio";
3250 gba.gba_gc = &sc->sc_gpio_gc;
3251 gba.gba_pins = sc->sc_gpio_pins;
3252 gba.gba_npins = ah->ah_gpio_npins;
3253
3254 #ifdef notyet
3255 #if NGPIO > 0
3256 if (config_found(&sc->sc_dev, &gba, gpiobus_print) == NULL)
3257 return (ENODEV);
3258 #endif
3259 #endif
3260
3261 return (0);
3262 }
3263
3264 int
3265 ath_gpio_pin_read(void *arg, int pin)
3266 {
3267 struct ath_softc *sc = arg;
3268 struct ath_hal *ah = sc->sc_ah;
3269 return (ath_hal_get_gpio(ah, pin) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
3270 }
3271
3272 void
3273 ath_gpio_pin_write(void *arg, int pin, int value)
3274 {
3275 struct ath_softc *sc = arg;
3276 struct ath_hal *ah = sc->sc_ah;
3277 ath_hal_set_gpio(ah, pin, value ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
3278 }
3279
3280 void
3281 ath_gpio_pin_ctl(void *arg, int pin, int flags)
3282 {
3283 struct ath_softc *sc = arg;
3284 struct ath_hal *ah = sc->sc_ah;
3285
3286 if (flags & GPIO_PIN_INPUT) {
3287 ath_hal_set_gpio_input(ah, pin);
3288 } else if (flags & GPIO_PIN_OUTPUT) {
3289 ath_hal_set_gpio_output(ah, pin);
3290 }
3291 }