| @@ -1,1050 +1,1050 @@ | | | @@ -1,1050 +1,1050 @@ |
1 | /* $NetBSD: bwi.c,v 1.18 2011/10/10 11:15:24 njoly Exp $ */ | | 1 | /* $NetBSD: bwi.c,v 1.18.8.1 2017/08/19 03:15:56 snj Exp $ */ |
2 | /* $OpenBSD: bwi.c,v 1.74 2008/02/25 21:13:30 mglocker Exp $ */ | | 2 | /* $OpenBSD: bwi.c,v 1.74 2008/02/25 21:13:30 mglocker Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 2007 The DragonFly Project. All rights reserved. | | 5 | * Copyright (c) 2007 The DragonFly Project. All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The DragonFly Project | | 7 | * This code is derived from software contributed to The DragonFly Project |
8 | * by Sepherosa Ziehau <sepherosa@gmail.com> | | 8 | * by Sepherosa Ziehau <sepherosa@gmail.com> |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * | | 13 | * |
14 | * 1. Redistributions of source code must retain the above copyright | | 14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions and the following disclaimer. | | 15 | * notice, this list of conditions and the following disclaimer. |
16 | * 2. Redistributions in binary form must reproduce the above copyright | | 16 | * 2. Redistributions in binary form must reproduce the above copyright |
17 | * notice, this list of conditions and the following disclaimer in | | 17 | * notice, this list of conditions and the following disclaimer in |
18 | * the documentation and/or other materials provided with the | | 18 | * the documentation and/or other materials provided with the |
19 | * distribution. | | 19 | * distribution. |
20 | * 3. Neither the name of The DragonFly Project nor the names of its | | 20 | * 3. Neither the name of The DragonFly Project nor the names of its |
21 | * contributors may be used to endorse or promote products derived | | 21 | * contributors may be used to endorse or promote products derived |
22 | * from this software without specific, prior written permission. | | 22 | * from this software without specific, prior written permission. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | | 24 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
25 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | | 25 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | | 26 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
27 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | | 27 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
28 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | | 28 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
29 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | | 29 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, |
30 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | | 30 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
31 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | | 31 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED |
32 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | | 32 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
33 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | | 33 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
34 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 34 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
35 | * SUCH DAMAGE. | | 35 | * SUCH DAMAGE. |
36 | * | | 36 | * |
37 | * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.1 2007/09/08 06:15:54 sephe Exp $ | | 37 | * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.1 2007/09/08 06:15:54 sephe Exp $ |
38 | */ | | 38 | */ |
39 | | | 39 | |
40 | /* | | 40 | /* |
41 | * Broadcom AirForce BCM43xx IEEE 802.11b/g wireless network driver | | 41 | * Broadcom AirForce BCM43xx IEEE 802.11b/g wireless network driver |
42 | * Generic back end | | 42 | * Generic back end |
43 | */ | | 43 | */ |
44 | | | 44 | |
45 | /* [TRC: XXX Names beginning with `bwi_ieee80211_*' are those that I | | 45 | /* [TRC: XXX Names beginning with `bwi_ieee80211_*' are those that I |
46 | think should be in NetBSD's generic 802.11 code, not in this | | 46 | think should be in NetBSD's generic 802.11 code, not in this |
47 | driver.] */ | | 47 | driver.] */ |
48 | | | 48 | |
49 | | | 49 | |
50 | #include <sys/cdefs.h> | | 50 | #include <sys/cdefs.h> |
51 | __KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.18 2011/10/10 11:15:24 njoly Exp $"); | | 51 | __KERNEL_RCSID(0, "$NetBSD: bwi.c,v 1.18.8.1 2017/08/19 03:15:56 snj Exp $"); |
52 | | | 52 | |
53 | #include <sys/param.h> | | 53 | #include <sys/param.h> |
54 | #include <sys/callout.h> | | 54 | #include <sys/callout.h> |
55 | #include <sys/device.h> | | 55 | #include <sys/device.h> |
56 | #include <sys/kernel.h> | | 56 | #include <sys/kernel.h> |
57 | #include <sys/malloc.h> | | 57 | #include <sys/malloc.h> |
58 | #include <sys/mbuf.h> | | 58 | #include <sys/mbuf.h> |
59 | #include <sys/socket.h> | | 59 | #include <sys/socket.h> |
60 | #include <sys/sockio.h> | | 60 | #include <sys/sockio.h> |
61 | #include <sys/sysctl.h> | | 61 | #include <sys/sysctl.h> |
62 | #include <sys/systm.h> | | 62 | #include <sys/systm.h> |
63 | #include <sys/bus.h> | | 63 | #include <sys/bus.h> |
64 | | | 64 | |
65 | #include <machine/endian.h> | | 65 | #include <machine/endian.h> |
66 | | | 66 | |
67 | #include <dev/firmload.h> | | 67 | #include <dev/firmload.h> |
68 | | | 68 | |
69 | #include <net/if.h> | | 69 | #include <net/if.h> |
70 | #include <net/if_dl.h> | | 70 | #include <net/if_dl.h> |
71 | #include <net/if_ether.h> | | 71 | #include <net/if_ether.h> |
72 | #include <net/if_media.h> | | 72 | #include <net/if_media.h> |
73 | | | 73 | |
74 | #include <net/bpf.h> | | 74 | #include <net/bpf.h> |
75 | | | 75 | |
76 | #include <net80211/ieee80211_var.h> | | 76 | #include <net80211/ieee80211_var.h> |
77 | /* [TRC: XXX amrr] */ | | 77 | /* [TRC: XXX amrr] */ |
78 | #include <net80211/ieee80211_amrr.h> | | 78 | #include <net80211/ieee80211_amrr.h> |
79 | #include <net80211/ieee80211_radiotap.h> | | 79 | #include <net80211/ieee80211_radiotap.h> |
80 | | | 80 | |
81 | #include <dev/ic/bwireg.h> | | 81 | #include <dev/ic/bwireg.h> |
82 | #include <dev/ic/bwivar.h> | | 82 | #include <dev/ic/bwivar.h> |
83 | | | 83 | |
84 | #ifdef BWI_DEBUG | | 84 | #ifdef BWI_DEBUG |
85 | int bwi_debug = 0; | | 85 | int bwi_debug = 0; |
86 | | | 86 | |
87 | #define DPRINTF(sc, dbg, fmt, ...) \ | | 87 | #define DPRINTF(sc, dbg, fmt, ...) \ |
88 | do { \ | | 88 | do { \ |
89 | if ((sc)->sc_debug & (dbg)) \ | | 89 | if ((sc)->sc_debug & (dbg)) \ |
90 | aprint_debug_dev((sc)->sc_dev, fmt, ##__VA_ARGS__); \ | | 90 | aprint_debug_dev((sc)->sc_dev, fmt, ##__VA_ARGS__); \ |
91 | } while (0) | | 91 | } while (0) |
92 | | | 92 | |
93 | #else /* !BWI_DEBUG */ | | 93 | #else /* !BWI_DEBUG */ |
94 | | | 94 | |
95 | #define DPRINTF(sc, dbg, fmt, ...) ((void)0) | | 95 | #define DPRINTF(sc, dbg, fmt, ...) ((void)0) |
96 | | | 96 | |
97 | #endif /* BWI_DEBUG */ | | 97 | #endif /* BWI_DEBUG */ |
98 | | | 98 | |
99 | /* XXX temporary porting goop */ | | 99 | /* XXX temporary porting goop */ |
100 | #include <dev/pci/pcireg.h> | | 100 | #include <dev/pci/pcireg.h> |
101 | #include <dev/pci/pcivar.h> | | 101 | #include <dev/pci/pcivar.h> |
102 | #include <dev/pci/pcidevs.h> | | 102 | #include <dev/pci/pcidevs.h> |
103 | | | 103 | |
104 | /* XXX does not belong here */ | | 104 | /* XXX does not belong here */ |
105 | #define IEEE80211_OFDM_PLCP_RATE_MASK 0x0000000f | | 105 | #define IEEE80211_OFDM_PLCP_RATE_MASK 0x0000000f |
106 | #define IEEE80211_OFDM_PLCP_LEN_MASK 0x0001ffe0 | | 106 | #define IEEE80211_OFDM_PLCP_LEN_MASK 0x0001ffe0 |
107 | | | 107 | |
108 | /* | | 108 | /* |
109 | * Contention window (slots). [TRC: dfly/net80211/80211.h] | | 109 | * Contention window (slots). [TRC: dfly/net80211/80211.h] |
110 | */ | | 110 | */ |
111 | #define IEEE80211_CW_MAX 1023 /* aCWmax */ | | 111 | #define IEEE80211_CW_MAX 1023 /* aCWmax */ |
112 | #define IEEE80211_CW_MIN_0 31 /* DS/CCK aCWmin, ERP aCWmin(0) */ | | 112 | #define IEEE80211_CW_MIN_0 31 /* DS/CCK aCWmin, ERP aCWmin(0) */ |
113 | #define IEEE80211_CW_MIN_1 15 /* OFDM aCWmin, ERP aCWmin(1) */ | | 113 | #define IEEE80211_CW_MIN_1 15 /* OFDM aCWmin, ERP aCWmin(1) */ |
114 | | | 114 | |
115 | /* | | 115 | /* |
116 | * Slot time (microseconds). [TRC: dfly/net80211/80211.h] | | 116 | * Slot time (microseconds). [TRC: dfly/net80211/80211.h] |
117 | */ | | 117 | */ |
118 | #define IEEE80211_DUR_SLOT 20 /* DS/CCK slottime, ERP long slottime */ | | 118 | #define IEEE80211_DUR_SLOT 20 /* DS/CCK slottime, ERP long slottime */ |
119 | #define IEEE80211_DUR_SHSLOT 9 /* ERP short slottime */ | | 119 | #define IEEE80211_DUR_SHSLOT 9 /* ERP short slottime */ |
120 | #define IEEE80211_DUR_OFDM_SLOT 9 /* OFDM slottime */ | | 120 | #define IEEE80211_DUR_OFDM_SLOT 9 /* OFDM slottime */ |
121 | | | 121 | |
122 | /* XXX end porting goop */ | | 122 | /* XXX end porting goop */ |
123 | | | 123 | |
124 | /* MAC */ | | 124 | /* MAC */ |
125 | struct bwi_retry_lim { | | 125 | struct bwi_retry_lim { |
126 | uint16_t shretry; | | 126 | uint16_t shretry; |
127 | uint16_t shretry_fb; | | 127 | uint16_t shretry_fb; |
128 | uint16_t lgretry; | | 128 | uint16_t lgretry; |
129 | uint16_t lgretry_fb; | | 129 | uint16_t lgretry_fb; |
130 | }; | | 130 | }; |
131 | | | 131 | |
132 | struct bwi_clock_freq { | | 132 | struct bwi_clock_freq { |
133 | uint clkfreq_min; | | 133 | uint clkfreq_min; |
134 | uint clkfreq_max; | | 134 | uint clkfreq_max; |
135 | }; | | 135 | }; |
136 | | | 136 | |
137 | /* XXX does not belong here */ | | 137 | /* XXX does not belong here */ |
138 | struct ieee80211_ds_plcp_hdr { | | 138 | struct ieee80211_ds_plcp_hdr { |
139 | uint8_t i_signal; | | 139 | uint8_t i_signal; |
140 | uint8_t i_service; | | 140 | uint8_t i_service; |
141 | uint16_t i_length; | | 141 | uint16_t i_length; |
142 | uint16_t i_crc; | | 142 | uint16_t i_crc; |
143 | } __packed; | | 143 | } __packed; |
144 | | | 144 | |
145 | static void bwi_sysctlattach(struct bwi_softc *); | | 145 | static void bwi_sysctlattach(struct bwi_softc *); |
146 | | | 146 | |
147 | /* MAC */ | | 147 | /* MAC */ |
148 | static void bwi_tmplt_write_4(struct bwi_mac *, uint32_t, uint32_t); | | 148 | static void bwi_tmplt_write_4(struct bwi_mac *, uint32_t, uint32_t); |
149 | static void bwi_hostflags_write(struct bwi_mac *, uint64_t); | | 149 | static void bwi_hostflags_write(struct bwi_mac *, uint64_t); |
150 | static uint64_t bwi_hostflags_read(struct bwi_mac *); | | 150 | static uint64_t bwi_hostflags_read(struct bwi_mac *); |
151 | static uint16_t bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t); | | 151 | static uint16_t bwi_memobj_read_2(struct bwi_mac *, uint16_t, uint16_t); |
152 | static uint32_t bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t); | | 152 | static uint32_t bwi_memobj_read_4(struct bwi_mac *, uint16_t, uint16_t); |
153 | static void bwi_memobj_write_2(struct bwi_mac *, uint16_t, uint16_t, | | 153 | static void bwi_memobj_write_2(struct bwi_mac *, uint16_t, uint16_t, |
154 | uint16_t); | | 154 | uint16_t); |
155 | static void bwi_memobj_write_4(struct bwi_mac *, uint16_t, uint16_t, | | 155 | static void bwi_memobj_write_4(struct bwi_mac *, uint16_t, uint16_t, |
156 | uint32_t); | | 156 | uint32_t); |
157 | static int bwi_mac_lateattach(struct bwi_mac *); | | 157 | static int bwi_mac_lateattach(struct bwi_mac *); |
158 | static int bwi_mac_init(struct bwi_mac *); | | 158 | static int bwi_mac_init(struct bwi_mac *); |
159 | static void bwi_mac_reset(struct bwi_mac *, int); | | 159 | static void bwi_mac_reset(struct bwi_mac *, int); |
160 | static void bwi_mac_set_tpctl_11bg(struct bwi_mac *, | | 160 | static void bwi_mac_set_tpctl_11bg(struct bwi_mac *, |
161 | const struct bwi_tpctl *); | | 161 | const struct bwi_tpctl *); |
162 | static int bwi_mac_test(struct bwi_mac *); | | 162 | static int bwi_mac_test(struct bwi_mac *); |
163 | static void bwi_mac_setup_tpctl(struct bwi_mac *); | | 163 | static void bwi_mac_setup_tpctl(struct bwi_mac *); |
164 | static void bwi_mac_dummy_xmit(struct bwi_mac *); | | 164 | static void bwi_mac_dummy_xmit(struct bwi_mac *); |
165 | static void bwi_mac_init_tpctl_11bg(struct bwi_mac *); | | 165 | static void bwi_mac_init_tpctl_11bg(struct bwi_mac *); |
166 | static void bwi_mac_detach(struct bwi_mac *); | | 166 | static void bwi_mac_detach(struct bwi_mac *); |
167 | static int bwi_mac_fw_alloc(struct bwi_mac *); | | 167 | static int bwi_mac_fw_alloc(struct bwi_mac *); |
168 | static void bwi_mac_fw_free(struct bwi_mac *); | | 168 | static void bwi_mac_fw_free(struct bwi_mac *); |
169 | static int bwi_mac_fw_image_alloc(struct bwi_mac *, const char *, | | 169 | static int bwi_mac_fw_image_alloc(struct bwi_mac *, const char *, |
170 | int idx, struct bwi_fw_image *, uint8_t); | | 170 | int idx, struct bwi_fw_image *, uint8_t); |
171 | static void bwi_mac_fw_image_free(struct bwi_mac *, struct bwi_fw_image *); | | 171 | static void bwi_mac_fw_image_free(struct bwi_mac *, struct bwi_fw_image *); |
172 | static int bwi_mac_fw_load(struct bwi_mac *); | | 172 | static int bwi_mac_fw_load(struct bwi_mac *); |
173 | static int bwi_mac_gpio_init(struct bwi_mac *); | | 173 | static int bwi_mac_gpio_init(struct bwi_mac *); |
174 | static int bwi_mac_gpio_fini(struct bwi_mac *); | | 174 | static int bwi_mac_gpio_fini(struct bwi_mac *); |
175 | static int bwi_mac_fw_load_iv(struct bwi_mac *, | | 175 | static int bwi_mac_fw_load_iv(struct bwi_mac *, |
176 | const struct bwi_fw_image *); | | 176 | const struct bwi_fw_image *); |
177 | static int bwi_mac_fw_init(struct bwi_mac *); | | 177 | static int bwi_mac_fw_init(struct bwi_mac *); |
178 | static void bwi_mac_opmode_init(struct bwi_mac *); | | 178 | static void bwi_mac_opmode_init(struct bwi_mac *); |
179 | static void bwi_mac_hostflags_init(struct bwi_mac *); | | 179 | static void bwi_mac_hostflags_init(struct bwi_mac *); |
180 | static void bwi_mac_bss_param_init(struct bwi_mac *); | | 180 | static void bwi_mac_bss_param_init(struct bwi_mac *); |
181 | static void bwi_mac_set_retry_lim(struct bwi_mac *, | | 181 | static void bwi_mac_set_retry_lim(struct bwi_mac *, |
182 | const struct bwi_retry_lim *); | | 182 | const struct bwi_retry_lim *); |
183 | static void bwi_mac_set_ackrates(struct bwi_mac *, | | 183 | static void bwi_mac_set_ackrates(struct bwi_mac *, |
184 | const struct ieee80211_rateset *); | | 184 | const struct ieee80211_rateset *); |
185 | static int bwi_mac_start(struct bwi_mac *); | | 185 | static int bwi_mac_start(struct bwi_mac *); |
186 | static int bwi_mac_stop(struct bwi_mac *); | | 186 | static int bwi_mac_stop(struct bwi_mac *); |
187 | static int bwi_mac_config_ps(struct bwi_mac *); | | 187 | static int bwi_mac_config_ps(struct bwi_mac *); |
188 | static void bwi_mac_reset_hwkeys(struct bwi_mac *); | | 188 | static void bwi_mac_reset_hwkeys(struct bwi_mac *); |
189 | static void bwi_mac_shutdown(struct bwi_mac *); | | 189 | static void bwi_mac_shutdown(struct bwi_mac *); |
190 | static int bwi_mac_get_property(struct bwi_mac *); | | 190 | static int bwi_mac_get_property(struct bwi_mac *); |
191 | static void bwi_mac_updateslot(struct bwi_mac *, int); | | 191 | static void bwi_mac_updateslot(struct bwi_mac *, int); |
192 | static int bwi_mac_attach(struct bwi_softc *, int, uint8_t); | | 192 | static int bwi_mac_attach(struct bwi_softc *, int, uint8_t); |
193 | static void bwi_mac_balance_atten(int *, int *); | | 193 | static void bwi_mac_balance_atten(int *, int *); |
194 | static void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int); | | 194 | static void bwi_mac_adjust_tpctl(struct bwi_mac *, int, int); |
195 | static void bwi_mac_calibrate_txpower(struct bwi_mac *, | | 195 | static void bwi_mac_calibrate_txpower(struct bwi_mac *, |
196 | enum bwi_txpwrcb_type); | | 196 | enum bwi_txpwrcb_type); |
197 | static void bwi_mac_lock(struct bwi_mac *); | | 197 | static void bwi_mac_lock(struct bwi_mac *); |
198 | static void bwi_mac_unlock(struct bwi_mac *); | | 198 | static void bwi_mac_unlock(struct bwi_mac *); |
199 | static void bwi_mac_set_promisc(struct bwi_mac *, int); | | 199 | static void bwi_mac_set_promisc(struct bwi_mac *, int); |
200 | | | 200 | |
201 | /* PHY */ | | 201 | /* PHY */ |
202 | static void bwi_phy_write(struct bwi_mac *, uint16_t, uint16_t); | | 202 | static void bwi_phy_write(struct bwi_mac *, uint16_t, uint16_t); |
203 | static uint16_t bwi_phy_read(struct bwi_mac *, uint16_t); | | 203 | static uint16_t bwi_phy_read(struct bwi_mac *, uint16_t); |
204 | static int bwi_phy_attach(struct bwi_mac *); | | 204 | static int bwi_phy_attach(struct bwi_mac *); |
205 | static void bwi_phy_set_bbp_atten(struct bwi_mac *, uint16_t); | | 205 | static void bwi_phy_set_bbp_atten(struct bwi_mac *, uint16_t); |
206 | static int bwi_phy_calibrate(struct bwi_mac *); | | 206 | static int bwi_phy_calibrate(struct bwi_mac *); |
207 | static void bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t); | | 207 | static void bwi_tbl_write_2(struct bwi_mac *mac, uint16_t, uint16_t); |
208 | static void bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t); | | 208 | static void bwi_tbl_write_4(struct bwi_mac *mac, uint16_t, uint32_t); |
209 | static void bwi_nrssi_write(struct bwi_mac *, uint16_t, int16_t); | | 209 | static void bwi_nrssi_write(struct bwi_mac *, uint16_t, int16_t); |
210 | static int16_t bwi_nrssi_read(struct bwi_mac *, uint16_t); | | 210 | static int16_t bwi_nrssi_read(struct bwi_mac *, uint16_t); |
211 | static void bwi_phy_init_11a(struct bwi_mac *); | | 211 | static void bwi_phy_init_11a(struct bwi_mac *); |
212 | static void bwi_phy_init_11g(struct bwi_mac *); | | 212 | static void bwi_phy_init_11g(struct bwi_mac *); |
213 | static void bwi_phy_init_11b_rev2(struct bwi_mac *); | | 213 | static void bwi_phy_init_11b_rev2(struct bwi_mac *); |
214 | static void bwi_phy_init_11b_rev4(struct bwi_mac *); | | 214 | static void bwi_phy_init_11b_rev4(struct bwi_mac *); |
215 | static void bwi_phy_init_11b_rev5(struct bwi_mac *); | | 215 | static void bwi_phy_init_11b_rev5(struct bwi_mac *); |
216 | static void bwi_phy_init_11b_rev6(struct bwi_mac *); | | 216 | static void bwi_phy_init_11b_rev6(struct bwi_mac *); |
217 | static void bwi_phy_config_11g(struct bwi_mac *); | | 217 | static void bwi_phy_config_11g(struct bwi_mac *); |
218 | static void bwi_phy_config_agc(struct bwi_mac *); | | 218 | static void bwi_phy_config_agc(struct bwi_mac *); |
219 | static void bwi_set_gains(struct bwi_mac *, const struct bwi_gains *); | | 219 | static void bwi_set_gains(struct bwi_mac *, const struct bwi_gains *); |
220 | static void bwi_phy_clear_state(struct bwi_phy *); | | 220 | static void bwi_phy_clear_state(struct bwi_phy *); |
221 | | | 221 | |
222 | /* RF */ | | 222 | /* RF */ |
223 | static int16_t bwi_nrssi_11g(struct bwi_mac *); | | 223 | static int16_t bwi_nrssi_11g(struct bwi_mac *); |
224 | static struct bwi_rf_lo | | 224 | static struct bwi_rf_lo |
225 | *bwi_get_rf_lo(struct bwi_mac *, uint16_t, uint16_t); | | 225 | *bwi_get_rf_lo(struct bwi_mac *, uint16_t, uint16_t); |
226 | static int bwi_rf_lo_isused(struct bwi_mac *, const struct bwi_rf_lo *); | | 226 | static int bwi_rf_lo_isused(struct bwi_mac *, const struct bwi_rf_lo *); |
227 | static void bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t); | | 227 | static void bwi_rf_write(struct bwi_mac *, uint16_t, uint16_t); |
228 | static uint16_t bwi_rf_read(struct bwi_mac *, uint16_t); | | 228 | static uint16_t bwi_rf_read(struct bwi_mac *, uint16_t); |
229 | static int bwi_rf_attach(struct bwi_mac *); | | 229 | static int bwi_rf_attach(struct bwi_mac *); |
230 | static void bwi_rf_set_chan(struct bwi_mac *, uint, int); | | 230 | static void bwi_rf_set_chan(struct bwi_mac *, uint, int); |
231 | static void bwi_rf_get_gains(struct bwi_mac *); | | 231 | static void bwi_rf_get_gains(struct bwi_mac *); |
232 | static void bwi_rf_init(struct bwi_mac *); | | 232 | static void bwi_rf_init(struct bwi_mac *); |
233 | static void bwi_rf_off_11a(struct bwi_mac *); | | 233 | static void bwi_rf_off_11a(struct bwi_mac *); |
234 | static void bwi_rf_off_11bg(struct bwi_mac *); | | 234 | static void bwi_rf_off_11bg(struct bwi_mac *); |
235 | static void bwi_rf_off_11g_rev5(struct bwi_mac *); | | 235 | static void bwi_rf_off_11g_rev5(struct bwi_mac *); |
236 | static void bwi_rf_workaround(struct bwi_mac *, uint); | | 236 | static void bwi_rf_workaround(struct bwi_mac *, uint); |
237 | static struct bwi_rf_lo | | 237 | static struct bwi_rf_lo |
238 | *bwi_rf_lo_find(struct bwi_mac *, const struct bwi_tpctl *); | | 238 | *bwi_rf_lo_find(struct bwi_mac *, const struct bwi_tpctl *); |
239 | static void bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *); | | 239 | static void bwi_rf_lo_adjust(struct bwi_mac *, const struct bwi_tpctl *); |
240 | static void bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *); | | 240 | static void bwi_rf_lo_write(struct bwi_mac *, const struct bwi_rf_lo *); |
241 | static int bwi_rf_gain_max_reached(struct bwi_mac *, int); | | 241 | static int bwi_rf_gain_max_reached(struct bwi_mac *, int); |
242 | static uint16_t bwi_bitswap4(uint16_t); | | 242 | static uint16_t bwi_bitswap4(uint16_t); |
243 | static uint16_t bwi_phy812_value(struct bwi_mac *, uint16_t); | | 243 | static uint16_t bwi_phy812_value(struct bwi_mac *, uint16_t); |
244 | static void bwi_rf_init_bcm2050(struct bwi_mac *); | | 244 | static void bwi_rf_init_bcm2050(struct bwi_mac *); |
245 | static uint16_t bwi_rf_calibval(struct bwi_mac *); | | 245 | static uint16_t bwi_rf_calibval(struct bwi_mac *); |
246 | static int32_t _bwi_adjust_devide(int32_t, int32_t); | | 246 | static int32_t _bwi_adjust_devide(int32_t, int32_t); |
247 | static int bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]); | | 247 | static int bwi_rf_calc_txpower(int8_t *, uint8_t, const int16_t[]); |
248 | static int bwi_rf_map_txpower(struct bwi_mac *); | | 248 | static int bwi_rf_map_txpower(struct bwi_mac *); |
249 | static void bwi_rf_lo_update_11g(struct bwi_mac *); | | 249 | static void bwi_rf_lo_update_11g(struct bwi_mac *); |
250 | static uint32_t bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t); | | 250 | static uint32_t bwi_rf_lo_devi_measure(struct bwi_mac *, uint16_t); |
251 | static uint16_t bwi_rf_get_tp_ctrl2(struct bwi_mac *); | | 251 | static uint16_t bwi_rf_get_tp_ctrl2(struct bwi_mac *); |
252 | static uint8_t _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t); | | 252 | static uint8_t _bwi_rf_lo_update_11g(struct bwi_mac *, uint16_t); |
253 | static void bwi_rf_lo_measure_11g(struct bwi_mac *, | | 253 | static void bwi_rf_lo_measure_11g(struct bwi_mac *, |
254 | const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t); | | 254 | const struct bwi_rf_lo *, struct bwi_rf_lo *, uint8_t); |
255 | static void bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *); | | 255 | static void bwi_rf_calc_nrssi_slope_11b(struct bwi_mac *); |
256 | static void bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *); | | 256 | static void bwi_rf_set_nrssi_ofs_11g(struct bwi_mac *); |
257 | static void bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *); | | 257 | static void bwi_rf_calc_nrssi_slope_11g(struct bwi_mac *); |
258 | static void bwi_rf_init_sw_nrssi_table(struct bwi_mac *); | | 258 | static void bwi_rf_init_sw_nrssi_table(struct bwi_mac *); |
259 | static void bwi_rf_init_hw_nrssi_table(struct bwi_mac *, uint16_t); | | 259 | static void bwi_rf_init_hw_nrssi_table(struct bwi_mac *, uint16_t); |
260 | static void bwi_rf_set_nrssi_thr_11b(struct bwi_mac *); | | 260 | static void bwi_rf_set_nrssi_thr_11b(struct bwi_mac *); |
261 | static int32_t _nrssi_threshold(const struct bwi_rf *, int32_t); | | 261 | static int32_t _nrssi_threshold(const struct bwi_rf *, int32_t); |
262 | static void bwi_rf_set_nrssi_thr_11g(struct bwi_mac *); | | 262 | static void bwi_rf_set_nrssi_thr_11g(struct bwi_mac *); |
263 | static void bwi_rf_clear_tssi(struct bwi_mac *); | | 263 | static void bwi_rf_clear_tssi(struct bwi_mac *); |
264 | static void bwi_rf_clear_state(struct bwi_rf *); | | 264 | static void bwi_rf_clear_state(struct bwi_rf *); |
265 | static void bwi_rf_on_11a(struct bwi_mac *); | | 265 | static void bwi_rf_on_11a(struct bwi_mac *); |
266 | static void bwi_rf_on_11bg(struct bwi_mac *); | | 266 | static void bwi_rf_on_11bg(struct bwi_mac *); |
267 | static void bwi_rf_set_ant_mode(struct bwi_mac *, int); | | 267 | static void bwi_rf_set_ant_mode(struct bwi_mac *, int); |
268 | static int bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t); | | 268 | static int bwi_rf_get_latest_tssi(struct bwi_mac *, int8_t[], uint16_t); |
269 | static int bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *); | | 269 | static int bwi_rf_tssi2dbm(struct bwi_mac *, int8_t, int8_t *); |
270 | static int bwi_rf_calc_rssi_bcm2050(struct bwi_mac *, | | 270 | static int bwi_rf_calc_rssi_bcm2050(struct bwi_mac *, |
271 | const struct bwi_rxbuf_hdr *); | | 271 | const struct bwi_rxbuf_hdr *); |
272 | static int bwi_rf_calc_rssi_bcm2053(struct bwi_mac *, | | 272 | static int bwi_rf_calc_rssi_bcm2053(struct bwi_mac *, |
273 | const struct bwi_rxbuf_hdr *); | | 273 | const struct bwi_rxbuf_hdr *); |
274 | static int bwi_rf_calc_rssi_bcm2060(struct bwi_mac *, | | 274 | static int bwi_rf_calc_rssi_bcm2060(struct bwi_mac *, |
275 | const struct bwi_rxbuf_hdr *); | | 275 | const struct bwi_rxbuf_hdr *); |
276 | static uint16_t bwi_rf_lo_measure_11b(struct bwi_mac *); | | 276 | static uint16_t bwi_rf_lo_measure_11b(struct bwi_mac *); |
277 | static void bwi_rf_lo_update_11b(struct bwi_mac *); | | 277 | static void bwi_rf_lo_update_11b(struct bwi_mac *); |
278 | | | 278 | |
279 | /* INTERFACE */ | | 279 | /* INTERFACE */ |
280 | static uint16_t bwi_read_sprom(struct bwi_softc *, uint16_t); | | 280 | static uint16_t bwi_read_sprom(struct bwi_softc *, uint16_t); |
281 | static void bwi_setup_desc32(struct bwi_softc *, struct bwi_desc32 *, int, | | 281 | static void bwi_setup_desc32(struct bwi_softc *, struct bwi_desc32 *, int, |
282 | int, bus_addr_t, int, int); | | 282 | int, bus_addr_t, int, int); |
283 | static void bwi_power_on(struct bwi_softc *, int); | | 283 | static void bwi_power_on(struct bwi_softc *, int); |
284 | static int bwi_power_off(struct bwi_softc *, int); | | 284 | static int bwi_power_off(struct bwi_softc *, int); |
285 | static int bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *, | | 285 | static int bwi_regwin_switch(struct bwi_softc *, struct bwi_regwin *, |
286 | struct bwi_regwin **); | | 286 | struct bwi_regwin **); |
287 | static int bwi_regwin_select(struct bwi_softc *, int); | | 287 | static int bwi_regwin_select(struct bwi_softc *, int); |
288 | static void bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *); | | 288 | static void bwi_regwin_info(struct bwi_softc *, uint16_t *, uint8_t *); |
289 | static void bwi_led_attach(struct bwi_softc *); | | 289 | static void bwi_led_attach(struct bwi_softc *); |
290 | static void bwi_led_newstate(struct bwi_softc *, enum ieee80211_state); | | 290 | static void bwi_led_newstate(struct bwi_softc *, enum ieee80211_state); |
291 | static uint16_t bwi_led_onoff(const struct bwi_led *, uint16_t, int); | | 291 | static uint16_t bwi_led_onoff(const struct bwi_led *, uint16_t, int); |
292 | static void bwi_led_event(struct bwi_softc *, int); | | 292 | static void bwi_led_event(struct bwi_softc *, int); |
293 | static void bwi_led_blink_start(struct bwi_softc *, int, int); | | 293 | static void bwi_led_blink_start(struct bwi_softc *, int, int); |
294 | static void bwi_led_blink_next(void *); | | 294 | static void bwi_led_blink_next(void *); |
295 | static void bwi_led_blink_end(void *); | | 295 | static void bwi_led_blink_end(void *); |
296 | static int bwi_bbp_attach(struct bwi_softc *); | | 296 | static int bwi_bbp_attach(struct bwi_softc *); |
297 | static int bwi_bus_init(struct bwi_softc *, struct bwi_mac *); | | 297 | static int bwi_bus_init(struct bwi_softc *, struct bwi_mac *); |
298 | static void bwi_get_card_flags(struct bwi_softc *); | | 298 | static void bwi_get_card_flags(struct bwi_softc *); |
299 | static void bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *); | | 299 | static void bwi_get_eaddr(struct bwi_softc *, uint16_t, uint8_t *); |
300 | static void bwi_get_clock_freq(struct bwi_softc *, | | 300 | static void bwi_get_clock_freq(struct bwi_softc *, |
301 | struct bwi_clock_freq *); | | 301 | struct bwi_clock_freq *); |
302 | static int bwi_set_clock_mode(struct bwi_softc *, enum bwi_clock_mode); | | 302 | static int bwi_set_clock_mode(struct bwi_softc *, enum bwi_clock_mode); |
303 | static int bwi_set_clock_delay(struct bwi_softc *); | | 303 | static int bwi_set_clock_delay(struct bwi_softc *); |
304 | static int bwi_init(struct ifnet *); | | 304 | static int bwi_init(struct ifnet *); |
305 | static void bwi_init_statechg(struct bwi_softc *, int); | | 305 | static void bwi_init_statechg(struct bwi_softc *, int); |
306 | static int bwi_ioctl(struct ifnet *, u_long, void *); | | 306 | static int bwi_ioctl(struct ifnet *, u_long, void *); |
307 | static void bwi_start(struct ifnet *); | | 307 | static void bwi_start(struct ifnet *); |
308 | static void bwi_watchdog(struct ifnet *); | | 308 | static void bwi_watchdog(struct ifnet *); |
309 | static void bwi_stop(struct ifnet *, int); | | 309 | static void bwi_stop(struct ifnet *, int); |
310 | static void bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state); | | 310 | static void bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state); |
311 | static int bwi_newstate(struct ieee80211com *, enum ieee80211_state, int); | | 311 | static int bwi_newstate(struct ieee80211com *, enum ieee80211_state, int); |
312 | static int bwi_media_change(struct ifnet *); | | 312 | static int bwi_media_change(struct ifnet *); |
313 | /* [TRC: XXX amrr] */ | | 313 | /* [TRC: XXX amrr] */ |
314 | static void bwi_iter_func(void *, struct ieee80211_node *); | | 314 | static void bwi_iter_func(void *, struct ieee80211_node *); |
315 | static void bwi_amrr_timeout(void *); | | 315 | static void bwi_amrr_timeout(void *); |
316 | static void bwi_newassoc(struct ieee80211_node *, int); | | 316 | static void bwi_newassoc(struct ieee80211_node *, int); |
317 | static struct ieee80211_node * | | 317 | static struct ieee80211_node * |
318 | bwi_node_alloc(struct ieee80211_node_table *); | | 318 | bwi_node_alloc(struct ieee80211_node_table *); |
319 | static int bwi_dma_alloc(struct bwi_softc *); | | 319 | static int bwi_dma_alloc(struct bwi_softc *); |
320 | static void bwi_dma_free(struct bwi_softc *); | | 320 | static void bwi_dma_free(struct bwi_softc *); |
321 | static void bwi_ring_data_free(struct bwi_ring_data *, struct bwi_softc *); | | 321 | static void bwi_ring_data_free(struct bwi_ring_data *, struct bwi_softc *); |
322 | static int bwi_dma_ring_alloc(struct bwi_softc *, | | 322 | static int bwi_dma_ring_alloc(struct bwi_softc *, |
323 | struct bwi_ring_data *, bus_size_t, uint32_t); | | 323 | struct bwi_ring_data *, bus_size_t, uint32_t); |
324 | static int bwi_dma_txstats_alloc(struct bwi_softc *, uint32_t, | | 324 | static int bwi_dma_txstats_alloc(struct bwi_softc *, uint32_t, |
325 | bus_size_t); | | 325 | bus_size_t); |
326 | static void bwi_dma_txstats_free(struct bwi_softc *); | | 326 | static void bwi_dma_txstats_free(struct bwi_softc *); |
327 | static int bwi_dma_mbuf_create(struct bwi_softc *); | | 327 | static int bwi_dma_mbuf_create(struct bwi_softc *); |
328 | static void bwi_dma_mbuf_destroy(struct bwi_softc *, int, int); | | 328 | static void bwi_dma_mbuf_destroy(struct bwi_softc *, int, int); |
329 | static void bwi_enable_intrs(struct bwi_softc *, uint32_t); | | 329 | static void bwi_enable_intrs(struct bwi_softc *, uint32_t); |
330 | static void bwi_disable_intrs(struct bwi_softc *, uint32_t); | | 330 | static void bwi_disable_intrs(struct bwi_softc *, uint32_t); |
331 | static int bwi_init_tx_ring32(struct bwi_softc *, int); | | 331 | static int bwi_init_tx_ring32(struct bwi_softc *, int); |
332 | static void bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t, | | 332 | static void bwi_init_rxdesc_ring32(struct bwi_softc *, uint32_t, |
333 | bus_addr_t, int, int); | | 333 | bus_addr_t, int, int); |
334 | static int bwi_init_rx_ring32(struct bwi_softc *); | | 334 | static int bwi_init_rx_ring32(struct bwi_softc *); |
335 | static int bwi_init_txstats32(struct bwi_softc *); | | 335 | static int bwi_init_txstats32(struct bwi_softc *); |
336 | static void bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int); | | 336 | static void bwi_setup_rx_desc32(struct bwi_softc *, int, bus_addr_t, int); |
337 | static void bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *, | | 337 | static void bwi_setup_tx_desc32(struct bwi_softc *, struct bwi_ring_data *, |
338 | int, bus_addr_t, int); | | 338 | int, bus_addr_t, int); |
339 | static int bwi_init_tx_ring64(struct bwi_softc *, int); | | 339 | static int bwi_init_tx_ring64(struct bwi_softc *, int); |
340 | static int bwi_init_rx_ring64(struct bwi_softc *); | | 340 | static int bwi_init_rx_ring64(struct bwi_softc *); |
341 | static int bwi_init_txstats64(struct bwi_softc *); | | 341 | static int bwi_init_txstats64(struct bwi_softc *); |
342 | static void bwi_setup_rx_desc64(struct bwi_softc *, int, bus_addr_t, int); | | 342 | static void bwi_setup_rx_desc64(struct bwi_softc *, int, bus_addr_t, int); |
343 | static void bwi_setup_tx_desc64(struct bwi_softc *, struct bwi_ring_data *, | | 343 | static void bwi_setup_tx_desc64(struct bwi_softc *, struct bwi_ring_data *, |
344 | int, bus_addr_t, int); | | 344 | int, bus_addr_t, int); |
345 | static int bwi_newbuf(struct bwi_softc *, int, int); | | 345 | static int bwi_newbuf(struct bwi_softc *, int, int); |
346 | static void bwi_set_addr_filter(struct bwi_softc *, uint16_t, | | 346 | static void bwi_set_addr_filter(struct bwi_softc *, uint16_t, |
347 | const uint8_t *); | | 347 | const uint8_t *); |
348 | static int bwi_set_chan(struct bwi_softc *, struct ieee80211_channel *); | | 348 | static int bwi_set_chan(struct bwi_softc *, struct ieee80211_channel *); |
349 | static void bwi_next_scan(void *); | | 349 | static void bwi_next_scan(void *); |
350 | static int bwi_rxeof(struct bwi_softc *, int); | | 350 | static int bwi_rxeof(struct bwi_softc *, int); |
351 | static int bwi_rxeof32(struct bwi_softc *); | | 351 | static int bwi_rxeof32(struct bwi_softc *); |
352 | static int bwi_rxeof64(struct bwi_softc *); | | 352 | static int bwi_rxeof64(struct bwi_softc *); |
353 | static void bwi_reset_rx_ring32(struct bwi_softc *, uint32_t); | | 353 | static void bwi_reset_rx_ring32(struct bwi_softc *, uint32_t); |
354 | static void bwi_free_txstats32(struct bwi_softc *); | | 354 | static void bwi_free_txstats32(struct bwi_softc *); |
355 | static void bwi_free_rx_ring32(struct bwi_softc *); | | 355 | static void bwi_free_rx_ring32(struct bwi_softc *); |
356 | static void bwi_free_tx_ring32(struct bwi_softc *, int); | | 356 | static void bwi_free_tx_ring32(struct bwi_softc *, int); |
357 | static void bwi_free_txstats64(struct bwi_softc *); | | 357 | static void bwi_free_txstats64(struct bwi_softc *); |
358 | static void bwi_free_rx_ring64(struct bwi_softc *); | | 358 | static void bwi_free_rx_ring64(struct bwi_softc *); |
359 | static void bwi_free_tx_ring64(struct bwi_softc *, int); | | 359 | static void bwi_free_tx_ring64(struct bwi_softc *, int); |
360 | static uint8_t bwi_ieee80211_rate2plcp(uint8_t rate, enum ieee80211_phymode); | | 360 | static uint8_t bwi_ieee80211_rate2plcp(uint8_t rate, enum ieee80211_phymode); |
361 | static uint8_t bwi_ieee80211_plcp2rate(uint8_t rate, enum ieee80211_phymode); | | 361 | static uint8_t bwi_ieee80211_plcp2rate(uint8_t rate, enum ieee80211_phymode); |
362 | static enum bwi_ieee80211_modtype | | 362 | static enum bwi_ieee80211_modtype |
363 | bwi_ieee80211_rate2modtype(uint8_t rate); | | 363 | bwi_ieee80211_rate2modtype(uint8_t rate); |
364 | static uint8_t bwi_ofdm_plcp2rate(const uint32_t *); | | 364 | static uint8_t bwi_ofdm_plcp2rate(const uint32_t *); |
365 | static uint8_t bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *); | | 365 | static uint8_t bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *); |
366 | static void bwi_ofdm_plcp_header(uint32_t *, int, uint8_t); | | 366 | static void bwi_ofdm_plcp_header(uint32_t *, int, uint8_t); |
367 | static void bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *, int, | | 367 | static void bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *, int, |
368 | uint8_t); | | 368 | uint8_t); |
369 | static void bwi_plcp_header(void *, int, uint8_t); | | 369 | static void bwi_plcp_header(void *, int, uint8_t); |
370 | static int bwi_encap(struct bwi_softc *, int, struct mbuf *, | | 370 | static int bwi_encap(struct bwi_softc *, int, struct mbuf *, |
371 | struct ieee80211_node **, int); | | 371 | struct ieee80211_node **, int); |
372 | static void bwi_start_tx32(struct bwi_softc *, uint32_t, int); | | 372 | static void bwi_start_tx32(struct bwi_softc *, uint32_t, int); |
373 | static void bwi_start_tx64(struct bwi_softc *, uint32_t, int); | | 373 | static void bwi_start_tx64(struct bwi_softc *, uint32_t, int); |
374 | static void bwi_txeof_status32(struct bwi_softc *); | | 374 | static void bwi_txeof_status32(struct bwi_softc *); |
375 | static void bwi_txeof_status64(struct bwi_softc *); | | 375 | static void bwi_txeof_status64(struct bwi_softc *); |
376 | static void _bwi_txeof(struct bwi_softc *, uint16_t); | | 376 | static void _bwi_txeof(struct bwi_softc *, uint16_t); |
377 | static void bwi_txeof_status(struct bwi_softc *, int); | | 377 | static void bwi_txeof_status(struct bwi_softc *, int); |
378 | static void bwi_txeof(struct bwi_softc *); | | 378 | static void bwi_txeof(struct bwi_softc *); |
379 | static int bwi_bbp_power_on(struct bwi_softc *, enum bwi_clock_mode); | | 379 | static int bwi_bbp_power_on(struct bwi_softc *, enum bwi_clock_mode); |
380 | static void bwi_bbp_power_off(struct bwi_softc *); | | 380 | static void bwi_bbp_power_off(struct bwi_softc *); |
381 | static int bwi_get_pwron_delay(struct bwi_softc *sc); | | 381 | static int bwi_get_pwron_delay(struct bwi_softc *sc); |
382 | static int bwi_bus_attach(struct bwi_softc *); | | 382 | static int bwi_bus_attach(struct bwi_softc *); |
383 | static const char | | 383 | static const char |
384 | *bwi_regwin_name(const struct bwi_regwin *); | | 384 | *bwi_regwin_name(const struct bwi_regwin *); |
385 | static int bwi_regwin_is_enabled(struct bwi_softc *, struct bwi_regwin *); | | 385 | static int bwi_regwin_is_enabled(struct bwi_softc *, struct bwi_regwin *); |
386 | static uint32_t bwi_regwin_disable_bits(struct bwi_softc *); | | 386 | static uint32_t bwi_regwin_disable_bits(struct bwi_softc *); |
387 | static void bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *, | | 387 | static void bwi_regwin_enable(struct bwi_softc *, struct bwi_regwin *, |
388 | uint32_t); | | 388 | uint32_t); |
389 | static void bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *, | | 389 | static void bwi_regwin_disable(struct bwi_softc *, struct bwi_regwin *, |
390 | uint32_t); | | 390 | uint32_t); |
391 | static void bwi_set_bssid(struct bwi_softc *, const uint8_t *); | | 391 | static void bwi_set_bssid(struct bwi_softc *, const uint8_t *); |
392 | static void bwi_updateslot(struct ifnet *); | | 392 | static void bwi_updateslot(struct ifnet *); |
393 | static void bwi_calibrate(void *); | | 393 | static void bwi_calibrate(void *); |
394 | static int bwi_calc_rssi(struct bwi_softc *, | | 394 | static int bwi_calc_rssi(struct bwi_softc *, |
395 | const struct bwi_rxbuf_hdr *); | | 395 | const struct bwi_rxbuf_hdr *); |
396 | static uint8_t bwi_ieee80211_ack_rate(struct ieee80211_node *, uint8_t); | | 396 | static uint8_t bwi_ieee80211_ack_rate(struct ieee80211_node *, uint8_t); |
397 | static uint16_t bwi_ieee80211_txtime(struct ieee80211com *, | | 397 | static uint16_t bwi_ieee80211_txtime(struct ieee80211com *, |
398 | struct ieee80211_node *, uint, uint8_t, uint32_t); | | 398 | struct ieee80211_node *, uint, uint8_t, uint32_t); |
399 | | | 399 | |
400 | /* MAC */ | | 400 | /* MAC */ |
401 | static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10, 12 }; | | 401 | static const uint8_t bwi_sup_macrev[] = { 2, 4, 5, 6, 7, 9, 10, 12 }; |
402 | | | 402 | |
403 | /* PHY */ | | 403 | /* PHY */ |
404 | #define SUP_BPHY(num) { .rev = num, .init = bwi_phy_init_11b_rev##num } | | 404 | #define SUP_BPHY(num) { .rev = num, .init = bwi_phy_init_11b_rev##num } |
405 | | | 405 | |
406 | static const struct { | | 406 | static const struct { |
407 | uint8_t rev; | | 407 | uint8_t rev; |
408 | void (*init)(struct bwi_mac *); | | 408 | void (*init)(struct bwi_mac *); |
409 | } bwi_sup_bphy[] = { | | 409 | } bwi_sup_bphy[] = { |
410 | SUP_BPHY(2), | | 410 | SUP_BPHY(2), |
411 | SUP_BPHY(4), | | 411 | SUP_BPHY(4), |
412 | SUP_BPHY(5), | | 412 | SUP_BPHY(5), |
413 | SUP_BPHY(6) | | 413 | SUP_BPHY(6) |
414 | }; | | 414 | }; |
415 | | | 415 | |
416 | #undef SUP_BPHY | | 416 | #undef SUP_BPHY |
417 | | | 417 | |
418 | #define BWI_PHYTBL_WRSSI 0x1000 | | 418 | #define BWI_PHYTBL_WRSSI 0x1000 |
419 | #define BWI_PHYTBL_NOISE_SCALE 0x1400 | | 419 | #define BWI_PHYTBL_NOISE_SCALE 0x1400 |
420 | #define BWI_PHYTBL_NOISE 0x1800 | | 420 | #define BWI_PHYTBL_NOISE 0x1800 |
421 | #define BWI_PHYTBL_ROTOR 0x2000 | | 421 | #define BWI_PHYTBL_ROTOR 0x2000 |
422 | #define BWI_PHYTBL_DELAY 0x2400 | | 422 | #define BWI_PHYTBL_DELAY 0x2400 |
423 | #define BWI_PHYTBL_RSSI 0x4000 | | 423 | #define BWI_PHYTBL_RSSI 0x4000 |
424 | #define BWI_PHYTBL_SIGMA_SQ 0x5000 | | 424 | #define BWI_PHYTBL_SIGMA_SQ 0x5000 |
425 | #define BWI_PHYTBL_WRSSI_REV1 0x5400 | | 425 | #define BWI_PHYTBL_WRSSI_REV1 0x5400 |
426 | #define BWI_PHYTBL_FREQ 0x5800 | | 426 | #define BWI_PHYTBL_FREQ 0x5800 |
427 | | | 427 | |
428 | static const uint16_t bwi_phy_freq_11g_rev1[] = | | 428 | static const uint16_t bwi_phy_freq_11g_rev1[] = |
429 | { BWI_PHY_FREQ_11G_REV1 }; | | 429 | { BWI_PHY_FREQ_11G_REV1 }; |
430 | static const uint16_t bwi_phy_noise_11g_rev1[] = | | 430 | static const uint16_t bwi_phy_noise_11g_rev1[] = |
431 | { BWI_PHY_NOISE_11G_REV1 }; | | 431 | { BWI_PHY_NOISE_11G_REV1 }; |
432 | static const uint16_t bwi_phy_noise_11g[] = | | 432 | static const uint16_t bwi_phy_noise_11g[] = |
433 | { BWI_PHY_NOISE_11G }; | | 433 | { BWI_PHY_NOISE_11G }; |
434 | static const uint32_t bwi_phy_rotor_11g_rev1[] = | | 434 | static const uint32_t bwi_phy_rotor_11g_rev1[] = |
435 | { BWI_PHY_ROTOR_11G_REV1 }; | | 435 | { BWI_PHY_ROTOR_11G_REV1 }; |
436 | static const uint16_t bwi_phy_noise_scale_11g_rev2[] = | | 436 | static const uint16_t bwi_phy_noise_scale_11g_rev2[] = |
437 | { BWI_PHY_NOISE_SCALE_11G_REV2 }; | | 437 | { BWI_PHY_NOISE_SCALE_11G_REV2 }; |
438 | static const uint16_t bwi_phy_noise_scale_11g_rev7[] = | | 438 | static const uint16_t bwi_phy_noise_scale_11g_rev7[] = |
439 | { BWI_PHY_NOISE_SCALE_11G_REV7 }; | | 439 | { BWI_PHY_NOISE_SCALE_11G_REV7 }; |
440 | static const uint16_t bwi_phy_noise_scale_11g[] = | | 440 | static const uint16_t bwi_phy_noise_scale_11g[] = |
441 | { BWI_PHY_NOISE_SCALE_11G }; | | 441 | { BWI_PHY_NOISE_SCALE_11G }; |
442 | static const uint16_t bwi_phy_sigma_sq_11g_rev2[] = | | 442 | static const uint16_t bwi_phy_sigma_sq_11g_rev2[] = |
443 | { BWI_PHY_SIGMA_SQ_11G_REV2 }; | | 443 | { BWI_PHY_SIGMA_SQ_11G_REV2 }; |
444 | static const uint16_t bwi_phy_sigma_sq_11g_rev7[] = | | 444 | static const uint16_t bwi_phy_sigma_sq_11g_rev7[] = |
445 | { BWI_PHY_SIGMA_SQ_11G_REV7 }; | | 445 | { BWI_PHY_SIGMA_SQ_11G_REV7 }; |
446 | static const uint32_t bwi_phy_delay_11g_rev1[] = | | 446 | static const uint32_t bwi_phy_delay_11g_rev1[] = |
447 | { BWI_PHY_DELAY_11G_REV1 }; | | 447 | { BWI_PHY_DELAY_11G_REV1 }; |
448 | | | 448 | |
449 | /* RF */ | | 449 | /* RF */ |
450 | #define RF_LO_WRITE(mac, lo) bwi_rf_lo_write((mac), (lo)) | | 450 | #define RF_LO_WRITE(mac, lo) bwi_rf_lo_write((mac), (lo)) |
451 | | | 451 | |
452 | #define BWI_RF_2GHZ_CHAN(chan) \ | | 452 | #define BWI_RF_2GHZ_CHAN(chan) \ |
453 | (ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400) | | 453 | (ieee80211_ieee2mhz((chan), IEEE80211_CHAN_2GHZ) - 2400) |
454 | | | 454 | |
455 | #define BWI_DEFAULT_IDLE_TSSI 52 | | 455 | #define BWI_DEFAULT_IDLE_TSSI 52 |
456 | | | 456 | |
457 | struct rf_saveregs { | | 457 | struct rf_saveregs { |
458 | uint16_t phy_01; | | 458 | uint16_t phy_01; |
459 | uint16_t phy_03; | | 459 | uint16_t phy_03; |
460 | uint16_t phy_0a; | | 460 | uint16_t phy_0a; |
461 | uint16_t phy_15; | | 461 | uint16_t phy_15; |
462 | uint16_t phy_2a; | | 462 | uint16_t phy_2a; |
463 | uint16_t phy_30; | | 463 | uint16_t phy_30; |
464 | uint16_t phy_35; | | 464 | uint16_t phy_35; |
465 | uint16_t phy_60; | | 465 | uint16_t phy_60; |
466 | uint16_t phy_429; | | 466 | uint16_t phy_429; |
467 | uint16_t phy_802; | | 467 | uint16_t phy_802; |
468 | uint16_t phy_811; | | 468 | uint16_t phy_811; |
469 | uint16_t phy_812; | | 469 | uint16_t phy_812; |
470 | uint16_t phy_814; | | 470 | uint16_t phy_814; |
471 | uint16_t phy_815; | | 471 | uint16_t phy_815; |
472 | | | 472 | |
473 | uint16_t rf_43; | | 473 | uint16_t rf_43; |
474 | uint16_t rf_52; | | 474 | uint16_t rf_52; |
475 | uint16_t rf_7a; | | 475 | uint16_t rf_7a; |
476 | }; | | 476 | }; |
477 | | | 477 | |
478 | #define SAVE_RF_REG(mac, regs, n) (regs)->rf_##n = RF_READ((mac), 0x##n) | | 478 | #define SAVE_RF_REG(mac, regs, n) (regs)->rf_##n = RF_READ((mac), 0x##n) |
479 | #define RESTORE_RF_REG(mac, regs, n) RF_WRITE((mac), 0x##n, (regs)->rf_##n) | | 479 | #define RESTORE_RF_REG(mac, regs, n) RF_WRITE((mac), 0x##n, (regs)->rf_##n) |
480 | | | 480 | |
481 | #define SAVE_PHY_REG(mac, regs, n) (regs)->phy_##n = PHY_READ((mac), 0x##n) | | 481 | #define SAVE_PHY_REG(mac, regs, n) (regs)->phy_##n = PHY_READ((mac), 0x##n) |
482 | #define RESTORE_PHY_REG(mac, regs, n) PHY_WRITE((mac), 0x##n, (regs)->phy_##n) | | 482 | #define RESTORE_PHY_REG(mac, regs, n) PHY_WRITE((mac), 0x##n, (regs)->phy_##n) |
483 | | | 483 | |
484 | static const int8_t bwi_txpower_map_11b[BWI_TSSI_MAX] = | | 484 | static const int8_t bwi_txpower_map_11b[BWI_TSSI_MAX] = |
485 | { BWI_TXPOWER_MAP_11B }; | | 485 | { BWI_TXPOWER_MAP_11B }; |
486 | static const int8_t bwi_txpower_map_11g[BWI_TSSI_MAX] = | | 486 | static const int8_t bwi_txpower_map_11g[BWI_TSSI_MAX] = |
487 | { BWI_TXPOWER_MAP_11G }; | | 487 | { BWI_TXPOWER_MAP_11G }; |
488 | | | 488 | |
489 | /* INTERFACE */ | | 489 | /* INTERFACE */ |
490 | | | 490 | |
491 | struct bwi_myaddr_bssid { | | 491 | struct bwi_myaddr_bssid { |
492 | uint8_t myaddr[IEEE80211_ADDR_LEN]; | | 492 | uint8_t myaddr[IEEE80211_ADDR_LEN]; |
493 | uint8_t bssid[IEEE80211_ADDR_LEN]; | | 493 | uint8_t bssid[IEEE80211_ADDR_LEN]; |
494 | } __packed; | | 494 | } __packed; |
495 | | | 495 | |
496 | /* [TRC: XXX What are these about?] */ | | 496 | /* [TRC: XXX What are these about?] */ |
497 | | | 497 | |
498 | #define IEEE80211_DS_PLCP_SERVICE_LOCKED 0x04 | | 498 | #define IEEE80211_DS_PLCP_SERVICE_LOCKED 0x04 |
499 | #define IEEE80211_DS_PLCL_SERVICE_PBCC 0x08 | | 499 | #define IEEE80211_DS_PLCL_SERVICE_PBCC 0x08 |
500 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT5 0x20 | | 500 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT5 0x20 |
501 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT6 0x40 | | 501 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT6 0x40 |
502 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT7 0x80 | | 502 | #define IEEE80211_DS_PLCP_SERVICE_LENEXT7 0x80 |
503 | | | 503 | |
504 | static const struct { | | 504 | static const struct { |
505 | uint16_t did_min; | | 505 | uint16_t did_min; |
506 | uint16_t did_max; | | 506 | uint16_t did_max; |
507 | uint16_t bbp_id; | | 507 | uint16_t bbp_id; |
508 | } bwi_bbpid_map[] = { | | 508 | } bwi_bbpid_map[] = { |
509 | { 0x4301, 0x4301, 0x4301 }, | | 509 | { 0x4301, 0x4301, 0x4301 }, |
510 | { 0x4305, 0x4307, 0x4307 }, | | 510 | { 0x4305, 0x4307, 0x4307 }, |
511 | { 0x4403, 0x4403, 0x4402 }, | | 511 | { 0x4403, 0x4403, 0x4402 }, |
512 | { 0x4610, 0x4615, 0x4610 }, | | 512 | { 0x4610, 0x4615, 0x4610 }, |
513 | { 0x4710, 0x4715, 0x4710 }, | | 513 | { 0x4710, 0x4715, 0x4710 }, |
514 | { 0x4720, 0x4725, 0x4309 } | | 514 | { 0x4720, 0x4725, 0x4309 } |
515 | }; | | 515 | }; |
516 | | | 516 | |
517 | static const struct { | | 517 | static const struct { |
518 | uint16_t bbp_id; | | 518 | uint16_t bbp_id; |
519 | int nregwin; | | 519 | int nregwin; |
520 | } bwi_regwin_count[] = { | | 520 | } bwi_regwin_count[] = { |
521 | { 0x4301, 5 }, | | 521 | { 0x4301, 5 }, |
522 | { 0x4306, 6 }, | | 522 | { 0x4306, 6 }, |
523 | { 0x4307, 5 }, | | 523 | { 0x4307, 5 }, |
524 | { 0x4310, 8 }, | | 524 | { 0x4310, 8 }, |
525 | { 0x4401, 3 }, | | 525 | { 0x4401, 3 }, |
526 | { 0x4402, 3 }, | | 526 | { 0x4402, 3 }, |
527 | { 0x4610, 9 }, | | 527 | { 0x4610, 9 }, |
528 | { 0x4704, 9 }, | | 528 | { 0x4704, 9 }, |
529 | { 0x4710, 9 }, | | 529 | { 0x4710, 9 }, |
530 | { 0x5365, 7 } | | 530 | { 0x5365, 7 } |
531 | }; | | 531 | }; |
532 | | | 532 | |
533 | #define CLKSRC(src) \ | | 533 | #define CLKSRC(src) \ |
534 | [BWI_CLKSRC_ ## src] = { \ | | 534 | [BWI_CLKSRC_ ## src] = { \ |
535 | .freq_min = BWI_CLKSRC_ ##src## _FMIN, \ | | 535 | .freq_min = BWI_CLKSRC_ ##src## _FMIN, \ |
536 | .freq_max = BWI_CLKSRC_ ##src## _FMAX \ | | 536 | .freq_max = BWI_CLKSRC_ ##src## _FMAX \ |
537 | } | | 537 | } |
538 | | | 538 | |
539 | static const struct { | | 539 | static const struct { |
540 | uint freq_min; | | 540 | uint freq_min; |
541 | uint freq_max; | | 541 | uint freq_max; |
542 | } bwi_clkfreq[BWI_CLKSRC_MAX] = { | | 542 | } bwi_clkfreq[BWI_CLKSRC_MAX] = { |
543 | CLKSRC(LP_OSC), | | 543 | CLKSRC(LP_OSC), |
544 | CLKSRC(CS_OSC), | | 544 | CLKSRC(CS_OSC), |
545 | CLKSRC(PCI) | | 545 | CLKSRC(PCI) |
546 | }; | | 546 | }; |
547 | | | 547 | |
548 | #undef CLKSRC | | 548 | #undef CLKSRC |
549 | | | 549 | |
550 | #define VENDOR_LED_ACT(vendor) \ | | 550 | #define VENDOR_LED_ACT(vendor) \ |
551 | { \ | | 551 | { \ |
552 | .vid = PCI_VENDOR_##vendor, \ | | 552 | .vid = PCI_VENDOR_##vendor, \ |
553 | .led_act = { BWI_VENDOR_LED_ACT_##vendor } \ | | 553 | .led_act = { BWI_VENDOR_LED_ACT_##vendor } \ |
554 | } | | 554 | } |
555 | | | 555 | |
556 | static const struct { | | 556 | static const struct { |
557 | uint16_t vid; | | 557 | uint16_t vid; |
558 | uint8_t led_act[BWI_LED_MAX]; | | 558 | uint8_t led_act[BWI_LED_MAX]; |
559 | } bwi_vendor_led_act[] = { | | 559 | } bwi_vendor_led_act[] = { |
560 | VENDOR_LED_ACT(COMPAQ), | | 560 | VENDOR_LED_ACT(COMPAQ), |
561 | VENDOR_LED_ACT(LINKSYS) | | 561 | VENDOR_LED_ACT(LINKSYS) |
562 | }; | | 562 | }; |
563 | | | 563 | |
564 | static const uint8_t bwi_default_led_act[BWI_LED_MAX] = | | 564 | static const uint8_t bwi_default_led_act[BWI_LED_MAX] = |
565 | { BWI_VENDOR_LED_ACT_DEFAULT }; | | 565 | { BWI_VENDOR_LED_ACT_DEFAULT }; |
566 | | | 566 | |
567 | #undef VENDOR_LED_ACT | | 567 | #undef VENDOR_LED_ACT |
568 | | | 568 | |
569 | static const struct { | | 569 | static const struct { |
570 | int on_dur; | | 570 | int on_dur; |
571 | int off_dur; | | 571 | int off_dur; |
572 | } bwi_led_duration[109] = { | | 572 | } bwi_led_duration[109] = { |
573 | [0] = { 400, 100 }, | | 573 | [0] = { 400, 100 }, |
574 | [2] = { 150, 75 }, | | 574 | [2] = { 150, 75 }, |
575 | [4] = { 90, 45 }, | | 575 | [4] = { 90, 45 }, |
576 | [11] = { 66, 34 }, | | 576 | [11] = { 66, 34 }, |
577 | [12] = { 53, 26 }, | | 577 | [12] = { 53, 26 }, |
578 | [18] = { 42, 21 }, | | 578 | [18] = { 42, 21 }, |
579 | [22] = { 35, 17 }, | | 579 | [22] = { 35, 17 }, |
580 | [24] = { 32, 16 }, | | 580 | [24] = { 32, 16 }, |
581 | [36] = { 21, 10 }, | | 581 | [36] = { 21, 10 }, |
582 | [48] = { 16, 8 }, | | 582 | [48] = { 16, 8 }, |
583 | [72] = { 11, 5 }, | | 583 | [72] = { 11, 5 }, |
584 | [96] = { 9, 4 }, | | 584 | [96] = { 9, 4 }, |
585 | [108] = { 7, 3 } | | 585 | [108] = { 7, 3 } |
586 | }; | | 586 | }; |
587 | | | 587 | |
588 | /* [TRC: XXX Should this be zeroed?] */ | | 588 | /* [TRC: XXX Should this be zeroed?] */ |
589 | | | 589 | |
590 | static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN]; | | 590 | static const uint8_t bwi_zero_addr[IEEE80211_ADDR_LEN]; |
591 | | | 591 | |
592 | /* [TRC: Derived from DragonFly's src/sys/netproto/802_11/_ieee80211.h */ | | 592 | /* [TRC: Derived from DragonFly's src/sys/netproto/802_11/_ieee80211.h */ |
593 | | | 593 | |
594 | enum bwi_ieee80211_modtype { | | 594 | enum bwi_ieee80211_modtype { |
595 | IEEE80211_MODTYPE_DS = 0, /* DS/CCK modulation */ | | 595 | IEEE80211_MODTYPE_DS = 0, /* DS/CCK modulation */ |
596 | IEEE80211_MODTYPE_PBCC = 1, /* PBCC modulation */ | | 596 | IEEE80211_MODTYPE_PBCC = 1, /* PBCC modulation */ |
597 | IEEE80211_MODTYPE_OFDM = 2 /* OFDM modulation */ | | 597 | IEEE80211_MODTYPE_OFDM = 2 /* OFDM modulation */ |
598 | }; | | 598 | }; |
599 | #define IEEE80211_MODTYPE_CCK IEEE80211_MODTYPE_DS | | 599 | #define IEEE80211_MODTYPE_CCK IEEE80211_MODTYPE_DS |
600 | | | 600 | |
601 | /* | | 601 | /* |
602 | * Setup sysctl(3) MIB, hw.bwi.* and hw.bwiN.* | | 602 | * Setup sysctl(3) MIB, hw.bwi.* and hw.bwiN.* |
603 | */ | | 603 | */ |
604 | | | 604 | |
605 | #ifdef BWI_DEBUG | | 605 | #ifdef BWI_DEBUG |
606 | SYSCTL_SETUP(sysctl_bwi, "sysctl bwi(4) subtree setup") | | 606 | SYSCTL_SETUP(sysctl_bwi, "sysctl bwi(4) subtree setup") |
607 | { | | 607 | { |
608 | int rc; | | 608 | int rc; |
609 | const struct sysctlnode *rnode; | | 609 | const struct sysctlnode *rnode; |
610 | const struct sysctlnode *cnode; | | 610 | const struct sysctlnode *cnode; |
611 | | | 611 | |
612 | if ((rc = sysctl_createv(clog, 0, NULL, &rnode, | | 612 | if ((rc = sysctl_createv(clog, 0, NULL, &rnode, |
613 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, | | 613 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, |
614 | NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) | | 614 | NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) |
615 | goto err; | | 615 | goto err; |
616 | | | 616 | |
617 | if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, | | 617 | if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, |
618 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "bwi", | | 618 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "bwi", |
619 | SYSCTL_DESCR("bwi global controls"), | | 619 | SYSCTL_DESCR("bwi global controls"), |
620 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | | 620 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) |
621 | goto err; | | 621 | goto err; |
622 | | | 622 | |
623 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 623 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
624 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 624 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
625 | "debug", SYSCTL_DESCR("default debug flags"), | | 625 | "debug", SYSCTL_DESCR("default debug flags"), |
626 | NULL, 0, &bwi_debug, 0, CTL_CREATE, CTL_EOL)) != 0) | | 626 | NULL, 0, &bwi_debug, 0, CTL_CREATE, CTL_EOL)) != 0) |
627 | goto err; | | 627 | goto err; |
628 | | | 628 | |
629 | return; | | 629 | return; |
630 | | | 630 | |
631 | err: | | 631 | err: |
632 | aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); | | 632 | aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); |
633 | } | | 633 | } |
634 | #endif /* BWI_DEBUG */ | | 634 | #endif /* BWI_DEBUG */ |
635 | | | 635 | |
636 | static void | | 636 | static void |
637 | bwi_sysctlattach(struct bwi_softc *sc) | | 637 | bwi_sysctlattach(struct bwi_softc *sc) |
638 | { | | 638 | { |
639 | int rc; | | 639 | int rc; |
640 | const struct sysctlnode *rnode; | | 640 | const struct sysctlnode *rnode; |
641 | const struct sysctlnode *cnode; | | 641 | const struct sysctlnode *cnode; |
642 | | | 642 | |
643 | struct sysctllog **clog = &sc->sc_sysctllog; | | 643 | struct sysctllog **clog = &sc->sc_sysctllog; |
644 | | | 644 | |
645 | if ((rc = sysctl_createv(clog, 0, NULL, &rnode, | | 645 | if ((rc = sysctl_createv(clog, 0, NULL, &rnode, |
646 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, | | 646 | CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL, |
647 | NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) | | 647 | NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0) |
648 | goto err; | | 648 | goto err; |
649 | | | 649 | |
650 | if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, | | 650 | if ((rc = sysctl_createv(clog, 0, &rnode, &rnode, |
651 | CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(sc->sc_dev), | | 651 | CTLFLAG_PERMANENT, CTLTYPE_NODE, device_xname(sc->sc_dev), |
652 | SYSCTL_DESCR("bwi controls and statistics"), | | 652 | SYSCTL_DESCR("bwi controls and statistics"), |
653 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) | | 653 | NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0) |
654 | goto err; | | 654 | goto err; |
655 | | | 655 | |
656 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 656 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
657 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 657 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
658 | "fw_version", SYSCTL_DESCR("firmware version"), | | 658 | "fw_version", SYSCTL_DESCR("firmware version"), |
659 | NULL, 0, &sc->sc_fw_version, 0, CTL_CREATE, CTL_EOL)) != 0) | | 659 | NULL, 0, &sc->sc_fw_version, 0, CTL_CREATE, CTL_EOL)) != 0) |
660 | goto err; | | 660 | goto err; |
661 | | | 661 | |
662 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 662 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
663 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 663 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
664 | "dwell_time", SYSCTL_DESCR("channel dwell time during scan (msec)"), | | 664 | "dwell_time", SYSCTL_DESCR("channel dwell time during scan (msec)"), |
665 | NULL, 0, &sc->sc_dwell_time, 0, CTL_CREATE, CTL_EOL)) != 0) | | 665 | NULL, 0, &sc->sc_dwell_time, 0, CTL_CREATE, CTL_EOL)) != 0) |
666 | goto err; | | 666 | goto err; |
667 | | | 667 | |
668 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 668 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
669 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 669 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
670 | "led_idle", SYSCTL_DESCR("# ticks before LED enters idle state"), | | 670 | "led_idle", SYSCTL_DESCR("# ticks before LED enters idle state"), |
671 | NULL, 0, &sc->sc_led_idle, 0, CTL_CREATE, CTL_EOL)) != 0) | | 671 | NULL, 0, &sc->sc_led_idle, 0, CTL_CREATE, CTL_EOL)) != 0) |
672 | goto err; | | 672 | goto err; |
673 | | | 673 | |
674 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 674 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
675 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 675 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
676 | "led_blink", SYSCTL_DESCR("allow LED to blink"), | | 676 | "led_blink", SYSCTL_DESCR("allow LED to blink"), |
677 | NULL, 0, &sc->sc_led_blink, 0, CTL_CREATE, CTL_EOL)) != 0) | | 677 | NULL, 0, &sc->sc_led_blink, 0, CTL_CREATE, CTL_EOL)) != 0) |
678 | goto err; | | 678 | goto err; |
679 | | | 679 | |
680 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 680 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
681 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 681 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
682 | "txpwr_calib", SYSCTL_DESCR("enable software TX power calibration"), | | 682 | "txpwr_calib", SYSCTL_DESCR("enable software TX power calibration"), |
683 | NULL, 0, &sc->sc_txpwr_calib, 0, CTL_CREATE, CTL_EOL)) != 0) | | 683 | NULL, 0, &sc->sc_txpwr_calib, 0, CTL_CREATE, CTL_EOL)) != 0) |
684 | goto err; | | 684 | goto err; |
685 | | | 685 | |
686 | #ifdef BWI_DEBUG | | 686 | #ifdef BWI_DEBUG |
687 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, | | 687 | if ((rc = sysctl_createv(clog, 0, &rnode, &cnode, |
688 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, | | 688 | CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, |
689 | "debug", SYSCTL_DESCR("debug flags"), | | 689 | "debug", SYSCTL_DESCR("debug flags"), |
690 | NULL, 0, &sc->sc_debug, 0, CTL_CREATE, CTL_EOL)) != 0) | | 690 | NULL, 0, &sc->sc_debug, 0, CTL_CREATE, CTL_EOL)) != 0) |
691 | goto err; | | 691 | goto err; |
692 | #endif | | 692 | #endif |
693 | | | 693 | |
694 | return; | | 694 | return; |
695 | | | 695 | |
696 | err: | | 696 | err: |
697 | aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); | | 697 | aprint_error("%s: sysctl_createv failed (rc = %d)\n", __func__, rc); |
698 | } | | 698 | } |
699 | | | 699 | |
700 | /* CODE */ | | 700 | /* CODE */ |
701 | | | 701 | |
702 | int | | 702 | int |
703 | bwi_intr(void *arg) | | 703 | bwi_intr(void *arg) |
704 | { | | 704 | { |
705 | struct bwi_softc *sc = arg; | | 705 | struct bwi_softc *sc = arg; |
706 | struct bwi_mac *mac; | | 706 | struct bwi_mac *mac; |
707 | struct ifnet *ifp = &sc->sc_if; | | 707 | struct ifnet *ifp = &sc->sc_if; |
708 | uint32_t intr_status; | | 708 | uint32_t intr_status; |
709 | uint32_t txrx_intr_status[BWI_TXRX_NRING]; | | 709 | uint32_t txrx_intr_status[BWI_TXRX_NRING]; |
710 | int i, txrx_error, tx = 0, rx_data = -1; | | 710 | int i, txrx_error, tx = 0, rx_data = -1; |
711 | | | 711 | |
712 | if (!device_is_active(sc->sc_dev) || | | 712 | if (!device_is_active(sc->sc_dev) || |
713 | (ifp->if_flags & IFF_RUNNING) == 0) | | 713 | (ifp->if_flags & IFF_RUNNING) == 0) |
714 | return (0); | | 714 | return (0); |
715 | | | 715 | |
716 | /* | | 716 | /* |
717 | * Get interrupt status | | 717 | * Get interrupt status |
718 | */ | | 718 | */ |
719 | intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); | | 719 | intr_status = CSR_READ_4(sc, BWI_MAC_INTR_STATUS); |
720 | if (intr_status == 0xffffffff) /* Not for us */ | | 720 | if (intr_status == 0xffffffff) /* Not for us */ |
721 | return (0); | | 721 | return (0); |
722 | | | 722 | |
723 | intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK); | | 723 | intr_status &= CSR_READ_4(sc, BWI_MAC_INTR_MASK); |
724 | if (intr_status == 0) /* Nothing is interesting */ | | 724 | if (intr_status == 0) /* Nothing is interesting */ |
725 | return (0); | | 725 | return (0); |
726 | | | 726 | |
727 | DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status); | | 727 | DPRINTF(sc, BWI_DBG_INTR, "intr status 0x%08x\n", intr_status); |
728 | | | 728 | |
729 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); | | 729 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); |
730 | mac = (struct bwi_mac *)sc->sc_cur_regwin; | | 730 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
731 | | | 731 | |
732 | txrx_error = 0; | | 732 | txrx_error = 0; |
733 | | | 733 | |
734 | for (i = 0; i < BWI_TXRX_NRING; ++i) { | | 734 | for (i = 0; i < BWI_TXRX_NRING; ++i) { |
735 | uint32_t mask; | | 735 | uint32_t mask; |
736 | | | 736 | |
737 | if (BWI_TXRX_IS_RX(i)) | | 737 | if (BWI_TXRX_IS_RX(i)) |
738 | mask = BWI_TXRX_RX_INTRS; | | 738 | mask = BWI_TXRX_RX_INTRS; |
739 | else | | 739 | else |
740 | mask = BWI_TXRX_TX_INTRS; | | 740 | mask = BWI_TXRX_TX_INTRS; |
741 | | | 741 | |
742 | txrx_intr_status[i] = | | 742 | txrx_intr_status[i] = |
743 | CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask; | | 743 | CSR_READ_4(sc, BWI_TXRX_INTR_STATUS(i)) & mask; |
744 | | | 744 | |
745 | if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { | | 745 | if (txrx_intr_status[i] & BWI_TXRX_INTR_ERROR) { |
746 | aprint_error_dev(sc->sc_dev, | | 746 | aprint_error_dev(sc->sc_dev, |
747 | "intr fatal TX/RX (%d) error 0x%08x\n", | | 747 | "intr fatal TX/RX (%d) error 0x%08x\n", |
748 | i, txrx_intr_status[i]); | | 748 | i, txrx_intr_status[i]); |
749 | txrx_error = 1; | | 749 | txrx_error = 1; |
750 | } | | 750 | } |
751 | } | | 751 | } |
752 | | | 752 | |
753 | /* | | 753 | /* |
754 | * Acknowledge interrupt | | 754 | * Acknowledge interrupt |
755 | */ | | 755 | */ |
756 | CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status); | | 756 | CSR_WRITE_4(sc, BWI_MAC_INTR_STATUS, intr_status); |
757 | | | 757 | |
758 | for (i = 0; i < BWI_TXRX_NRING; ++i) | | 758 | for (i = 0; i < BWI_TXRX_NRING; ++i) |
759 | CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), txrx_intr_status[i]); | | 759 | CSR_WRITE_4(sc, BWI_TXRX_INTR_STATUS(i), txrx_intr_status[i]); |
760 | | | 760 | |
761 | /* Disable all interrupts */ | | 761 | /* Disable all interrupts */ |
762 | bwi_disable_intrs(sc, BWI_ALL_INTRS); | | 762 | bwi_disable_intrs(sc, BWI_ALL_INTRS); |
763 | | | 763 | |
764 | if (intr_status & BWI_INTR_PHY_TXERR) { | | 764 | if (intr_status & BWI_INTR_PHY_TXERR) { |
765 | if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { | | 765 | if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) { |
766 | aprint_error_dev(sc->sc_dev, "intr PHY TX error\n"); | | 766 | aprint_error_dev(sc->sc_dev, "intr PHY TX error\n"); |
767 | /* XXX to netisr0? */ | | 767 | /* XXX to netisr0? */ |
768 | bwi_init_statechg(sc, 0); | | 768 | bwi_init_statechg(sc, 0); |
769 | return (0); | | 769 | return (0); |
770 | } | | 770 | } |
771 | } | | 771 | } |
772 | | | 772 | |
773 | if (txrx_error) { | | 773 | if (txrx_error) { |
774 | /* TODO: reset device */ | | 774 | /* TODO: reset device */ |
775 | } | | 775 | } |
776 | | | 776 | |
777 | if (intr_status & BWI_INTR_TBTT) | | 777 | if (intr_status & BWI_INTR_TBTT) |
778 | bwi_mac_config_ps(mac); | | 778 | bwi_mac_config_ps(mac); |
779 | | | 779 | |
780 | if (intr_status & BWI_INTR_EO_ATIM) | | 780 | if (intr_status & BWI_INTR_EO_ATIM) |
781 | aprint_normal_dev(sc->sc_dev, "EO_ATIM\n"); | | 781 | aprint_normal_dev(sc->sc_dev, "EO_ATIM\n"); |
782 | | | 782 | |
783 | if (intr_status & BWI_INTR_PMQ) { | | 783 | if (intr_status & BWI_INTR_PMQ) { |
784 | for (;;) { | | 784 | for (;;) { |
785 | if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8) == 0) | | 785 | if ((CSR_READ_4(sc, BWI_MAC_PS_STATUS) & 0x8) == 0) |
786 | break; | | 786 | break; |
787 | } | | 787 | } |
788 | CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2); | | 788 | CSR_WRITE_2(sc, BWI_MAC_PS_STATUS, 0x2); |
789 | } | | 789 | } |
790 | | | 790 | |
791 | if (intr_status & BWI_INTR_NOISE) | | 791 | if (intr_status & BWI_INTR_NOISE) |
792 | aprint_normal_dev(sc->sc_dev, "intr noise\n"); | | 792 | aprint_normal_dev(sc->sc_dev, "intr noise\n"); |
793 | | | 793 | |
794 | if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) | | 794 | if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) |
795 | rx_data = (sc->sc_rxeof)(sc); | | 795 | rx_data = (sc->sc_rxeof)(sc); |
796 | | | 796 | |
797 | if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) { | | 797 | if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) { |
798 | (sc->sc_txeof_status)(sc); | | 798 | (sc->sc_txeof_status)(sc); |
799 | tx = 1; | | 799 | tx = 1; |
800 | } | | 800 | } |
801 | | | 801 | |
802 | if (intr_status & BWI_INTR_TX_DONE) { | | 802 | if (intr_status & BWI_INTR_TX_DONE) { |
803 | bwi_txeof(sc); | | 803 | bwi_txeof(sc); |
804 | tx = 1; | | 804 | tx = 1; |
805 | } | | 805 | } |
806 | | | 806 | |
807 | /* Re-enable interrupts */ | | 807 | /* Re-enable interrupts */ |
808 | bwi_enable_intrs(sc, BWI_INIT_INTRS); | | 808 | bwi_enable_intrs(sc, BWI_INIT_INTRS); |
809 | | | 809 | |
810 | if (sc->sc_blink_led != NULL && sc->sc_led_blink) { | | 810 | if (sc->sc_blink_led != NULL && sc->sc_led_blink) { |
811 | int evt = BWI_LED_EVENT_NONE; | | 811 | int evt = BWI_LED_EVENT_NONE; |
812 | | | 812 | |
813 | if (tx && rx_data > 0) { | | 813 | if (tx && rx_data > 0) { |
814 | if (sc->sc_rx_rate > sc->sc_tx_rate) | | 814 | if (sc->sc_rx_rate > sc->sc_tx_rate) |
815 | evt = BWI_LED_EVENT_RX; | | 815 | evt = BWI_LED_EVENT_RX; |
816 | else | | 816 | else |
817 | evt = BWI_LED_EVENT_TX; | | 817 | evt = BWI_LED_EVENT_TX; |
818 | } else if (tx) { | | 818 | } else if (tx) { |
819 | evt = BWI_LED_EVENT_TX; | | 819 | evt = BWI_LED_EVENT_TX; |
820 | } else if (rx_data > 0) { | | 820 | } else if (rx_data > 0) { |
821 | evt = BWI_LED_EVENT_RX; | | 821 | evt = BWI_LED_EVENT_RX; |
822 | } else if (rx_data == 0) { | | 822 | } else if (rx_data == 0) { |
823 | evt = BWI_LED_EVENT_POLL; | | 823 | evt = BWI_LED_EVENT_POLL; |
824 | } | | 824 | } |
825 | | | 825 | |
826 | if (evt != BWI_LED_EVENT_NONE) | | 826 | if (evt != BWI_LED_EVENT_NONE) |
827 | bwi_led_event(sc, evt); | | 827 | bwi_led_event(sc, evt); |
828 | } | | 828 | } |
829 | | | 829 | |
830 | return (1); | | 830 | return (1); |
831 | } | | 831 | } |
832 | | | 832 | |
833 | int | | 833 | int |
834 | bwi_attach(struct bwi_softc *sc) | | 834 | bwi_attach(struct bwi_softc *sc) |
835 | { | | 835 | { |
836 | struct ieee80211com *ic = &sc->sc_ic; | | 836 | struct ieee80211com *ic = &sc->sc_ic; |
837 | struct ifnet *ifp = &sc->sc_if; | | 837 | struct ifnet *ifp = &sc->sc_if; |
838 | struct bwi_mac *mac; | | 838 | struct bwi_mac *mac; |
839 | struct bwi_phy *phy; | | 839 | struct bwi_phy *phy; |
840 | int s, i, error; | | 840 | int s, i, error; |
841 | | | 841 | |
842 | /* [TRC: XXX Is this necessary?] */ | | 842 | /* [TRC: XXX Is this necessary?] */ |
843 | s = splnet(); | | 843 | s = splnet(); |
844 | | | 844 | |
845 | /* | | 845 | /* |
846 | * Initialize sysctl variables | | 846 | * Initialize sysctl variables |
847 | */ | | 847 | */ |
848 | sc->sc_fw_version = BWI_FW_VERSION3; | | 848 | sc->sc_fw_version = BWI_FW_VERSION3; |
849 | sc->sc_dwell_time = 200; | | 849 | sc->sc_dwell_time = 200; |
850 | sc->sc_led_idle = (2350 * hz) / 1000; | | 850 | sc->sc_led_idle = (2350 * hz) / 1000; |
851 | sc->sc_led_blink = 1; | | 851 | sc->sc_led_blink = 1; |
852 | sc->sc_txpwr_calib = 1; | | 852 | sc->sc_txpwr_calib = 1; |
853 | #ifdef BWI_DEBUG | | 853 | #ifdef BWI_DEBUG |
854 | sc->sc_debug = bwi_debug; | | 854 | sc->sc_debug = bwi_debug; |
855 | #endif | | 855 | #endif |
856 | | | 856 | |
857 | DPRINTF(sc, BWI_DBG_ATTACH, "%s\n", __func__); | | 857 | DPRINTF(sc, BWI_DBG_ATTACH, "%s\n", __func__); |
858 | | | 858 | |
859 | /* [TRC: XXX amrr] */ | | 859 | /* [TRC: XXX amrr] */ |
860 | /* AMRR rate control */ | | 860 | /* AMRR rate control */ |
861 | sc->sc_amrr.amrr_min_success_threshold = 1; | | 861 | sc->sc_amrr.amrr_min_success_threshold = 1; |
862 | sc->sc_amrr.amrr_max_success_threshold = 15; | | 862 | sc->sc_amrr.amrr_max_success_threshold = 15; |
863 | callout_init(&sc->sc_amrr_ch, 0); | | 863 | callout_init(&sc->sc_amrr_ch, 0); |
864 | callout_setfunc(&sc->sc_amrr_ch, bwi_amrr_timeout, sc); | | 864 | callout_setfunc(&sc->sc_amrr_ch, bwi_amrr_timeout, sc); |
865 | | | 865 | |
866 | callout_init(&sc->sc_scan_ch, 0); | | 866 | callout_init(&sc->sc_scan_ch, 0); |
867 | callout_setfunc(&sc->sc_scan_ch, bwi_next_scan, sc); | | 867 | callout_setfunc(&sc->sc_scan_ch, bwi_next_scan, sc); |
868 | callout_init(&sc->sc_calib_ch, 0); | | 868 | callout_init(&sc->sc_calib_ch, 0); |
869 | callout_setfunc(&sc->sc_calib_ch, bwi_calibrate, sc); | | 869 | callout_setfunc(&sc->sc_calib_ch, bwi_calibrate, sc); |
870 | | | 870 | |
871 | bwi_sysctlattach(sc); | | 871 | bwi_sysctlattach(sc); |
872 | | | 872 | |
873 | bwi_power_on(sc, 1); | | 873 | bwi_power_on(sc, 1); |
874 | | | 874 | |
875 | error = bwi_bbp_attach(sc); | | 875 | error = bwi_bbp_attach(sc); |
876 | if (error) | | 876 | if (error) |
877 | goto fail; | | 877 | goto fail; |
878 | | | 878 | |
879 | error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); | | 879 | error = bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST); |
880 | if (error) | | 880 | if (error) |
881 | goto fail; | | 881 | goto fail; |
882 | | | 882 | |
883 | if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)) { | | 883 | if (BWI_REGWIN_EXIST(&sc->sc_com_regwin)) { |
884 | error = bwi_set_clock_delay(sc); | | 884 | error = bwi_set_clock_delay(sc); |
885 | if (error) | | 885 | if (error) |
886 | goto fail; | | 886 | goto fail; |
887 | | | 887 | |
888 | error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST); | | 888 | error = bwi_set_clock_mode(sc, BWI_CLOCK_MODE_FAST); |
889 | if (error) | | 889 | if (error) |
890 | goto fail; | | 890 | goto fail; |
891 | | | 891 | |
892 | error = bwi_get_pwron_delay(sc); | | 892 | error = bwi_get_pwron_delay(sc); |
893 | if (error) | | 893 | if (error) |
894 | goto fail; | | 894 | goto fail; |
895 | } | | 895 | } |
896 | | | 896 | |
897 | error = bwi_bus_attach(sc); | | 897 | error = bwi_bus_attach(sc); |
898 | if (error) | | 898 | if (error) |
899 | goto fail; | | 899 | goto fail; |
900 | | | 900 | |
901 | bwi_get_card_flags(sc); | | 901 | bwi_get_card_flags(sc); |
902 | | | 902 | |
903 | bwi_led_attach(sc); | | 903 | bwi_led_attach(sc); |
904 | | | 904 | |
905 | for (i = 0; i < sc->sc_nmac; ++i) { | | 905 | for (i = 0; i < sc->sc_nmac; ++i) { |
906 | struct bwi_regwin *old; | | 906 | struct bwi_regwin *old; |
907 | | | 907 | |
908 | mac = &sc->sc_mac[i]; | | 908 | mac = &sc->sc_mac[i]; |
909 | error = bwi_regwin_switch(sc, &mac->mac_regwin, &old); | | 909 | error = bwi_regwin_switch(sc, &mac->mac_regwin, &old); |
910 | if (error) | | 910 | if (error) |
911 | goto fail; | | 911 | goto fail; |
912 | | | 912 | |
913 | error = bwi_mac_lateattach(mac); | | 913 | error = bwi_mac_lateattach(mac); |
914 | if (error) | | 914 | if (error) |
915 | goto fail; | | 915 | goto fail; |
916 | | | 916 | |
917 | error = bwi_regwin_switch(sc, old, NULL); | | 917 | error = bwi_regwin_switch(sc, old, NULL); |
918 | if (error) | | 918 | if (error) |
919 | goto fail; | | 919 | goto fail; |
920 | } | | 920 | } |
921 | | | 921 | |
922 | /* | | 922 | /* |
923 | * XXX First MAC is known to exist | | 923 | * XXX First MAC is known to exist |
924 | * TODO2 | | 924 | * TODO2 |
925 | */ | | 925 | */ |
926 | mac = &sc->sc_mac[0]; | | 926 | mac = &sc->sc_mac[0]; |
927 | phy = &mac->mac_phy; | | 927 | phy = &mac->mac_phy; |
928 | | | 928 | |
929 | bwi_bbp_power_off(sc); | | 929 | bwi_bbp_power_off(sc); |
930 | | | 930 | |
931 | error = bwi_dma_alloc(sc); | | 931 | error = bwi_dma_alloc(sc); |
932 | if (error) | | 932 | if (error) |
933 | goto fail; | | 933 | goto fail; |
934 | | | 934 | |
935 | /* setup interface */ | | 935 | /* setup interface */ |
936 | ifp->if_softc = sc; | | 936 | ifp->if_softc = sc; |
937 | ifp->if_init = bwi_init; | | 937 | ifp->if_init = bwi_init; |
938 | ifp->if_ioctl = bwi_ioctl; | | 938 | ifp->if_ioctl = bwi_ioctl; |
939 | ifp->if_start = bwi_start; | | 939 | ifp->if_start = bwi_start; |
940 | ifp->if_watchdog = bwi_watchdog; | | 940 | ifp->if_watchdog = bwi_watchdog; |
941 | ifp->if_stop = bwi_stop; | | 941 | ifp->if_stop = bwi_stop; |
942 | ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; | | 942 | ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST; |
943 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); | | 943 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); |
944 | IFQ_SET_READY(&ifp->if_snd); | | 944 | IFQ_SET_READY(&ifp->if_snd); |
945 | | | 945 | |
946 | /* Get locale */ | | 946 | /* Get locale */ |
947 | sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO), | | 947 | sc->sc_locale = __SHIFTOUT(bwi_read_sprom(sc, BWI_SPROM_CARD_INFO), |
948 | BWI_SPROM_CARD_INFO_LOCALE); | | 948 | BWI_SPROM_CARD_INFO_LOCALE); |
949 | DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale); | | 949 | DPRINTF(sc, BWI_DBG_ATTACH, "locale: %d\n", sc->sc_locale); |
950 | | | 950 | |
951 | /* | | 951 | /* |
952 | * Setup ratesets, phytype, channels and get MAC address | | 952 | * Setup ratesets, phytype, channels and get MAC address |
953 | */ | | 953 | */ |
954 | if (phy->phy_mode == IEEE80211_MODE_11B || | | 954 | if (phy->phy_mode == IEEE80211_MODE_11B || |
955 | phy->phy_mode == IEEE80211_MODE_11G) { | | 955 | phy->phy_mode == IEEE80211_MODE_11G) { |
956 | uint16_t chan_flags; | | 956 | uint16_t chan_flags; |
957 | | | 957 | |
958 | ic->ic_sup_rates[IEEE80211_MODE_11B] = | | 958 | ic->ic_sup_rates[IEEE80211_MODE_11B] = |
959 | ieee80211_std_rateset_11b; | | 959 | ieee80211_std_rateset_11b; |
960 | | | 960 | |
961 | if (phy->phy_mode == IEEE80211_MODE_11B) { | | 961 | if (phy->phy_mode == IEEE80211_MODE_11B) { |
962 | chan_flags = IEEE80211_CHAN_B; | | 962 | chan_flags = IEEE80211_CHAN_B; |
963 | ic->ic_phytype = IEEE80211_T_DS; | | 963 | ic->ic_phytype = IEEE80211_T_DS; |
964 | } else { | | 964 | } else { |
965 | chan_flags = IEEE80211_CHAN_CCK | | | 965 | chan_flags = IEEE80211_CHAN_CCK | |
966 | IEEE80211_CHAN_OFDM | | | 966 | IEEE80211_CHAN_OFDM | |
967 | IEEE80211_CHAN_DYN | | | 967 | IEEE80211_CHAN_DYN | |
968 | IEEE80211_CHAN_2GHZ; | | 968 | IEEE80211_CHAN_2GHZ; |
969 | ic->ic_phytype = IEEE80211_T_OFDM; | | 969 | ic->ic_phytype = IEEE80211_T_OFDM; |
970 | ic->ic_sup_rates[IEEE80211_MODE_11G] = | | 970 | ic->ic_sup_rates[IEEE80211_MODE_11G] = |
971 | ieee80211_std_rateset_11g; | | 971 | ieee80211_std_rateset_11g; |
972 | } | | 972 | } |
973 | | | 973 | |
974 | /* XXX depend on locale */ | | 974 | /* XXX depend on locale */ |
975 | for (i = 1; i <= 14; ++i) { | | 975 | for (i = 1; i <= 14; ++i) { |
976 | ic->ic_channels[i].ic_freq = | | 976 | ic->ic_channels[i].ic_freq = |
977 | ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); | | 977 | ieee80211_ieee2mhz(i, IEEE80211_CHAN_2GHZ); |
978 | ic->ic_channels[i].ic_flags = chan_flags; | | 978 | ic->ic_channels[i].ic_flags = chan_flags; |
979 | } | | 979 | } |
980 | | | 980 | |
981 | bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr); | | 981 | bwi_get_eaddr(sc, BWI_SPROM_11BG_EADDR, ic->ic_myaddr); |
982 | if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) { | | 982 | if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) { |
983 | bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr); | | 983 | bwi_get_eaddr(sc, BWI_SPROM_11A_EADDR, ic->ic_myaddr); |
984 | if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) | | 984 | if (IEEE80211_IS_MULTICAST(ic->ic_myaddr)) |
985 | aprint_error_dev(sc->sc_dev, | | 985 | aprint_error_dev(sc->sc_dev, |
986 | "invalid MAC address: %s\n", | | 986 | "invalid MAC address: %s\n", |
987 | ether_sprintf(ic->ic_myaddr)); | | 987 | ether_sprintf(ic->ic_myaddr)); |
988 | } | | 988 | } |
989 | } else if (phy->phy_mode == IEEE80211_MODE_11A) { | | 989 | } else if (phy->phy_mode == IEEE80211_MODE_11A) { |
990 | /* TODO: 11A */ | | 990 | /* TODO: 11A */ |
991 | error = ENXIO; | | 991 | error = ENXIO; |
992 | goto fail; | | 992 | goto fail; |
993 | } else | | 993 | } else |
994 | panic("unknown phymode %d\n", phy->phy_mode); | | 994 | panic("unknown phymode %d\n", phy->phy_mode); |
995 | | | 995 | |
996 | ic->ic_ifp = ifp; | | 996 | ic->ic_ifp = ifp; |
997 | ic->ic_caps = IEEE80211_C_SHSLOT | | | 997 | ic->ic_caps = IEEE80211_C_SHSLOT | |
998 | IEEE80211_C_SHPREAMBLE | | | 998 | IEEE80211_C_SHPREAMBLE | |
999 | IEEE80211_C_IBSS | | | 999 | IEEE80211_C_IBSS | |
1000 | IEEE80211_C_HOSTAP | | | 1000 | IEEE80211_C_HOSTAP | |
1001 | IEEE80211_C_MONITOR; | | 1001 | IEEE80211_C_MONITOR; |
1002 | ic->ic_state = IEEE80211_S_INIT; | | 1002 | ic->ic_state = IEEE80211_S_INIT; |
1003 | ic->ic_opmode = IEEE80211_M_STA; | | 1003 | ic->ic_opmode = IEEE80211_M_STA; |
1004 | | | 1004 | |
1005 | ic->ic_updateslot = bwi_updateslot; | | 1005 | ic->ic_updateslot = bwi_updateslot; |
1006 | | | 1006 | |
1007 | if_attach(ifp); | | 1007 | if_attach(ifp); |
1008 | ieee80211_ifattach(ic); | | 1008 | ieee80211_ifattach(ic); |
1009 | | | 1009 | |
1010 | /* [TRC: XXX Not supported on NetBSD?] */ | | 1010 | /* [TRC: XXX Not supported on NetBSD?] */ |
1011 | /* ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; */ | | 1011 | /* ic->ic_flags_ext |= IEEE80211_FEXT_SWBMISS; */ |
1012 | | | 1012 | |
1013 | sc->sc_newstate = ic->ic_newstate; | | 1013 | sc->sc_newstate = ic->ic_newstate; |
1014 | ic->ic_newstate = bwi_newstate; | | 1014 | ic->ic_newstate = bwi_newstate; |
1015 | /* [TRC: XXX amrr] */ | | 1015 | /* [TRC: XXX amrr] */ |
1016 | ic->ic_newassoc = bwi_newassoc; | | 1016 | ic->ic_newassoc = bwi_newassoc; |
1017 | ic->ic_node_alloc = bwi_node_alloc; | | 1017 | ic->ic_node_alloc = bwi_node_alloc; |
1018 | | | 1018 | |
1019 | ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status); | | 1019 | ieee80211_media_init(ic, bwi_media_change, ieee80211_media_status); |
1020 | | | 1020 | |
1021 | bpf_attach2(ifp, DLT_IEEE802_11_RADIO, | | 1021 | bpf_attach2(ifp, DLT_IEEE802_11_RADIO, |
1022 | sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN, | | 1022 | sizeof(struct ieee80211_frame) + IEEE80211_RADIOTAP_HDRLEN, |
1023 | &sc->sc_drvbpf); | | 1023 | &sc->sc_drvbpf); |
1024 | | | 1024 | |
1025 | /* [TRC: XXX DragonFlyBSD rounds this up to a multiple of | | 1025 | /* [TRC: XXX DragonFlyBSD rounds this up to a multiple of |
1026 | sizeof(uint32_t). Should we?] */ | | 1026 | sizeof(uint32_t). Should we?] */ |
1027 | sc->sc_rxtap_len = sizeof(sc->sc_rxtapu); | | 1027 | sc->sc_rxtap_len = sizeof(sc->sc_rxtapu); |
1028 | sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); | | 1028 | sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); |
1029 | sc->sc_rxtap.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT); | | 1029 | sc->sc_rxtap.wr_ihdr.it_present = htole32(BWI_RX_RADIOTAP_PRESENT); |
1030 | | | 1030 | |
1031 | sc->sc_txtap_len = sizeof(sc->sc_txtapu); | | 1031 | sc->sc_txtap_len = sizeof(sc->sc_txtapu); |
1032 | sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); | | 1032 | sc->sc_txtap.wt_ihdr.it_len = htole16(sc->sc_txtap_len); |
1033 | sc->sc_txtap.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT); | | 1033 | sc->sc_txtap.wt_ihdr.it_present = htole32(BWI_TX_RADIOTAP_PRESENT); |
1034 | | | 1034 | |
1035 | splx(s); | | 1035 | splx(s); |
1036 | ieee80211_announce(ic); | | 1036 | ieee80211_announce(ic); |
1037 | return (0); | | 1037 | return (0); |
1038 | fail: | | 1038 | fail: |
1039 | /* [TRC: XXX DragonFlyBSD detaches the device here. Should we?] */ | | 1039 | /* [TRC: XXX DragonFlyBSD detaches the device here. Should we?] */ |
1040 | return (error); | | 1040 | return (error); |
1041 | } | | 1041 | } |
1042 | | | 1042 | |
1043 | void | | 1043 | void |
1044 | bwi_detach(struct bwi_softc *sc) | | 1044 | bwi_detach(struct bwi_softc *sc) |
1045 | { | | 1045 | { |
1046 | struct ifnet *ifp = &sc->sc_if; | | 1046 | struct ifnet *ifp = &sc->sc_if; |
1047 | int i, s; | | 1047 | int i, s; |
1048 | | | 1048 | |
1049 | s = splnet(); | | 1049 | s = splnet(); |
1050 | | | 1050 | |
| @@ -7319,1999 +7319,1999 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, | | | @@ -7319,1999 +7319,1999 @@ bwi_ioctl(struct ifnet *ifp, u_long cmd, |
7319 | error = ieee80211_ioctl(ic, cmd, data); | | 7319 | error = ieee80211_ioctl(ic, cmd, data); |
7320 | if (error == ENETRESET && | | 7320 | if (error == ENETRESET && |
7321 | ic->ic_opmode == IEEE80211_M_MONITOR) { | | 7321 | ic->ic_opmode == IEEE80211_M_MONITOR) { |
7322 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == | | 7322 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == |
7323 | (IFF_UP | IFF_RUNNING)) { | | 7323 | (IFF_UP | IFF_RUNNING)) { |
7324 | /* [TRC: XXX ????] */ | | 7324 | /* [TRC: XXX ????] */ |
7325 | ic->ic_bss->ni_chan = ic->ic_ibss_chan; | | 7325 | ic->ic_bss->ni_chan = ic->ic_ibss_chan; |
7326 | ic->ic_curchan = ic->ic_ibss_chan; | | 7326 | ic->ic_curchan = ic->ic_ibss_chan; |
7327 | bwi_set_chan(sc, ic->ic_bss->ni_chan); | | 7327 | bwi_set_chan(sc, ic->ic_bss->ni_chan); |
7328 | } | | 7328 | } |
7329 | error = 0; | | 7329 | error = 0; |
7330 | } | | 7330 | } |
7331 | break; | | 7331 | break; |
7332 | | | 7332 | |
7333 | default: | | 7333 | default: |
7334 | error = ieee80211_ioctl(ic, cmd, data); | | 7334 | error = ieee80211_ioctl(ic, cmd, data); |
7335 | break; | | 7335 | break; |
7336 | } | | 7336 | } |
7337 | | | 7337 | |
7338 | if (error == ENETRESET) { | | 7338 | if (error == ENETRESET) { |
7339 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == | | 7339 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == |
7340 | (IFF_UP | IFF_RUNNING) && | | 7340 | (IFF_UP | IFF_RUNNING) && |
7341 | /* [TRC: XXX Superstitiously cargo-culted from iwi(4). */ | | 7341 | /* [TRC: XXX Superstitiously cargo-culted from iwi(4). */ |
7342 | (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)) | | 7342 | (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)) |
7343 | bwi_init(ifp); | | 7343 | bwi_init(ifp); |
7344 | error = 0; | | 7344 | error = 0; |
7345 | } | | 7345 | } |
7346 | | | 7346 | |
7347 | splx(s); | | 7347 | splx(s); |
7348 | | | 7348 | |
7349 | return (error); | | 7349 | return (error); |
7350 | } | | 7350 | } |
7351 | | | 7351 | |
7352 | static void | | 7352 | static void |
7353 | bwi_start(struct ifnet *ifp) | | 7353 | bwi_start(struct ifnet *ifp) |
7354 | { | | 7354 | { |
7355 | struct bwi_softc *sc = ifp->if_softc; | | 7355 | struct bwi_softc *sc = ifp->if_softc; |
7356 | struct ieee80211com *ic = &sc->sc_ic; | | 7356 | struct ieee80211com *ic = &sc->sc_ic; |
7357 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | | 7357 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; |
7358 | int trans, idx; | | 7358 | int trans, idx; |
7359 | | | 7359 | |
7360 | /* [TRC: XXX I'm not sure under which conditions we're actually | | 7360 | /* [TRC: XXX I'm not sure under which conditions we're actually |
7361 | supposed to refuse to start, so I'm copying what OpenBSD and | | 7361 | supposed to refuse to start, so I'm copying what OpenBSD and |
7362 | DragonFlyBSD do, even if no one else on NetBSD does it. */ | | 7362 | DragonFlyBSD do, even if no one else on NetBSD does it. */ |
7363 | if ((ifp->if_flags & IFF_OACTIVE) || | | 7363 | if ((ifp->if_flags & IFF_OACTIVE) || |
7364 | (ifp->if_flags & IFF_RUNNING) == 0) | | 7364 | (ifp->if_flags & IFF_RUNNING) == 0) |
7365 | return; | | 7365 | return; |
7366 | | | 7366 | |
7367 | trans = 0; | | 7367 | trans = 0; |
7368 | idx = tbd->tbd_idx; | | 7368 | idx = tbd->tbd_idx; |
7369 | | | 7369 | |
7370 | while (tbd->tbd_buf[idx].tb_mbuf == NULL) { | | 7370 | while (tbd->tbd_buf[idx].tb_mbuf == NULL) { |
7371 | struct ieee80211_frame *wh; | | 7371 | struct ieee80211_frame *wh; |
7372 | struct ieee80211_node *ni; | | 7372 | struct ieee80211_node *ni; |
7373 | struct mbuf *m; | | 7373 | struct mbuf *m; |
7374 | int mgt_pkt = 0; | | 7374 | int mgt_pkt = 0; |
7375 | | | 7375 | |
7376 | IF_DEQUEUE(&ic->ic_mgtq, m); | | 7376 | IF_DEQUEUE(&ic->ic_mgtq, m); |
7377 | if (m != NULL) { | | 7377 | if (m != NULL) { |
7378 | ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; | | 7378 | ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; |
7379 | m->m_pkthdr.rcvif = NULL; | | 7379 | m->m_pkthdr.rcvif = NULL; |
7380 | | | 7380 | |
7381 | mgt_pkt = 1; | | 7381 | mgt_pkt = 1; |
7382 | } else { | | 7382 | } else { |
7383 | struct ether_header *eh; | | 7383 | struct ether_header *eh; |
7384 | | | 7384 | |
7385 | if (ic->ic_state != IEEE80211_S_RUN) | | 7385 | if (ic->ic_state != IEEE80211_S_RUN) |
7386 | break; | | 7386 | break; |
7387 | | | 7387 | |
7388 | IFQ_DEQUEUE(&ifp->if_snd, m); | | 7388 | IFQ_DEQUEUE(&ifp->if_snd, m); |
7389 | if (m == NULL) | | 7389 | if (m == NULL) |
7390 | break; | | 7390 | break; |
7391 | | | 7391 | |
7392 | if (m->m_len < sizeof(*eh)) { | | 7392 | if (m->m_len < sizeof(*eh)) { |
7393 | m = m_pullup(m, sizeof(*eh)); | | 7393 | m = m_pullup(m, sizeof(*eh)); |
7394 | if (m == NULL) { | | 7394 | if (m == NULL) { |
7395 | ifp->if_oerrors++; | | 7395 | ifp->if_oerrors++; |
7396 | continue; | | 7396 | continue; |
7397 | } | | 7397 | } |
7398 | } | | 7398 | } |
7399 | eh = mtod(m, struct ether_header *); | | 7399 | eh = mtod(m, struct ether_header *); |
7400 | | | 7400 | |
7401 | ni = ieee80211_find_txnode(ic, eh->ether_dhost); | | 7401 | ni = ieee80211_find_txnode(ic, eh->ether_dhost); |
7402 | if (ni == NULL) { | | 7402 | if (ni == NULL) { |
7403 | ifp->if_oerrors++; | | 7403 | ifp->if_oerrors++; |
7404 | m_freem(m); | | 7404 | m_freem(m); |
7405 | continue; | | 7405 | continue; |
7406 | } | | 7406 | } |
7407 | | | 7407 | |
7408 | /* [TRC: XXX Superstitiously cargo-culted from | | 7408 | /* [TRC: XXX Superstitiously cargo-culted from |
7409 | ath(4) and wi(4).] */ | | 7409 | ath(4) and wi(4).] */ |
7410 | if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && | | 7410 | if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) && |
7411 | (m->m_flags & M_PWR_SAV) == 0) { | | 7411 | (m->m_flags & M_PWR_SAV) == 0) { |
7412 | ieee80211_pwrsave(ic, ni, m); | | 7412 | ieee80211_pwrsave(ic, ni, m); |
7413 | ieee80211_free_node(ni); | | 7413 | ieee80211_free_node(ni); |
7414 | continue; | | 7414 | continue; |
7415 | } | | 7415 | } |
7416 | | | 7416 | |
7417 | /* [TRC: XXX I *think* we're supposed to do | | 7417 | /* [TRC: XXX I *think* we're supposed to do |
7418 | this, but honestly I have no clue. We don't | | 7418 | this, but honestly I have no clue. We don't |
7419 | use M_WME_GETAC, so...] */ | | 7419 | use M_WME_GETAC, so...] */ |
7420 | if (ieee80211_classify(ic, m, ni)) { | | 7420 | if (ieee80211_classify(ic, m, ni)) { |
7421 | /* [TRC: XXX What debug flag?] */ | | 7421 | /* [TRC: XXX What debug flag?] */ |
7422 | DPRINTF(sc, BWI_DBG_MISC, | | 7422 | DPRINTF(sc, BWI_DBG_MISC, |
7423 | "%s: discard, classification failure\n", | | 7423 | "%s: discard, classification failure\n", |
7424 | __func__); | | 7424 | __func__); |
7425 | ifp->if_oerrors++; | | 7425 | ifp->if_oerrors++; |
7426 | m_freem(m); | | 7426 | m_freem(m); |
7427 | ieee80211_free_node(ni); | | 7427 | ieee80211_free_node(ni); |
7428 | continue; | | 7428 | continue; |
7429 | } | | 7429 | } |
7430 | | | 7430 | |
7431 | /* [TRC: XXX wi(4) and awi(4) do this; iwi(4) | | 7431 | /* [TRC: XXX wi(4) and awi(4) do this; iwi(4) |
7432 | doesn't.] */ | | 7432 | doesn't.] */ |
7433 | ifp->if_opackets++; | | 7433 | ifp->if_opackets++; |
7434 | | | 7434 | |
7435 | /* [TRC: XXX When should the packet be | | 7435 | /* [TRC: XXX When should the packet be |
7436 | filtered? Different drivers appear to do it | | 7436 | filtered? Different drivers appear to do it |
7437 | at different times.] */ | | 7437 | at different times.] */ |
7438 | /* TODO: PS */ | | 7438 | /* TODO: PS */ |
7439 | bpf_mtap(ifp, m); | | 7439 | bpf_mtap(ifp, m); |
7440 | m = ieee80211_encap(ic, m, ni); | | 7440 | m = ieee80211_encap(ic, m, ni); |
7441 | if (m == NULL) { | | 7441 | if (m == NULL) { |
7442 | ifp->if_oerrors++; | | 7442 | ifp->if_oerrors++; |
7443 | ieee80211_free_node(ni); | | 7443 | ieee80211_free_node(ni); |
7444 | continue; | | 7444 | continue; |
7445 | } | | 7445 | } |
7446 | } | | 7446 | } |
7447 | bpf_mtap3(ic->ic_rawbpf, m); | | 7447 | bpf_mtap3(ic->ic_rawbpf, m); |
7448 | | | 7448 | |
7449 | wh = mtod(m, struct ieee80211_frame *); | | 7449 | wh = mtod(m, struct ieee80211_frame *); |
7450 | /* [TRC: XXX What about ic->ic_flags & IEEE80211_F_PRIVACY?] */ | | 7450 | /* [TRC: XXX What about ic->ic_flags & IEEE80211_F_PRIVACY?] */ |
7451 | if (wh->i_fc[1] & IEEE80211_FC1_WEP) { | | 7451 | if (wh->i_fc[1] & IEEE80211_FC1_WEP) { |
7452 | if (ieee80211_crypto_encap(ic, ni, m) == NULL) { | | 7452 | if (ieee80211_crypto_encap(ic, ni, m) == NULL) { |
7453 | ifp->if_oerrors++; | | 7453 | ifp->if_oerrors++; |
7454 | m_freem(m); | | 7454 | m_freem(m); |
7455 | ieee80211_free_node(ni); | | 7455 | ieee80211_free_node(ni); |
7456 | continue; | | 7456 | continue; |
7457 | } | | 7457 | } |
7458 | } | | 7458 | } |
7459 | wh = NULL; /* [TRC: XXX Huh?] */ | | 7459 | wh = NULL; /* [TRC: XXX Huh?] */ |
7460 | | | 7460 | |
7461 | if (bwi_encap(sc, idx, m, &ni, mgt_pkt) != 0) { | | 7461 | if (bwi_encap(sc, idx, m, &ni, mgt_pkt) != 0) { |
7462 | /* 'm' is freed in bwi_encap() if we reach here */ | | 7462 | /* 'm' is freed in bwi_encap() if we reach here */ |
7463 | ifp->if_oerrors++; | | 7463 | ifp->if_oerrors++; |
7464 | if (ni != NULL) | | 7464 | if (ni != NULL) |
7465 | ieee80211_free_node(ni); | | 7465 | ieee80211_free_node(ni); |
7466 | continue; | | 7466 | continue; |
7467 | } | | 7467 | } |
7468 | | | 7468 | |
7469 | trans = 1; | | 7469 | trans = 1; |
7470 | tbd->tbd_used++; | | 7470 | tbd->tbd_used++; |
7471 | idx = (idx + 1) % BWI_TX_NDESC; | | 7471 | idx = (idx + 1) % BWI_TX_NDESC; |
7472 | | | 7472 | |
7473 | if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) { | | 7473 | if (tbd->tbd_used + BWI_TX_NSPRDESC >= BWI_TX_NDESC) { |
7474 | ifp->if_flags |= IFF_OACTIVE; | | 7474 | ifp->if_flags |= IFF_OACTIVE; |
7475 | break; | | 7475 | break; |
7476 | } | | 7476 | } |
7477 | } | | 7477 | } |
7478 | tbd->tbd_idx = idx; | | 7478 | tbd->tbd_idx = idx; |
7479 | | | 7479 | |
7480 | if (trans) | | 7480 | if (trans) |
7481 | sc->sc_tx_timer = 5; | | 7481 | sc->sc_tx_timer = 5; |
7482 | ifp->if_timer = 1; | | 7482 | ifp->if_timer = 1; |
7483 | } | | 7483 | } |
7484 | | | 7484 | |
7485 | static void | | 7485 | static void |
7486 | bwi_watchdog(struct ifnet *ifp) | | 7486 | bwi_watchdog(struct ifnet *ifp) |
7487 | { | | 7487 | { |
7488 | struct bwi_softc *sc = ifp->if_softc; | | 7488 | struct bwi_softc *sc = ifp->if_softc; |
7489 | | | 7489 | |
7490 | ifp->if_timer = 0; | | 7490 | ifp->if_timer = 0; |
7491 | | | 7491 | |
7492 | if ((ifp->if_flags & IFF_RUNNING) == 0 || | | 7492 | if ((ifp->if_flags & IFF_RUNNING) == 0 || |
7493 | !device_is_active(sc->sc_dev)) | | 7493 | !device_is_active(sc->sc_dev)) |
7494 | return; | | 7494 | return; |
7495 | | | 7495 | |
7496 | if (sc->sc_tx_timer) { | | 7496 | if (sc->sc_tx_timer) { |
7497 | if (--sc->sc_tx_timer == 0) { | | 7497 | if (--sc->sc_tx_timer == 0) { |
7498 | aprint_error_dev(sc->sc_dev, "device timeout\n"); | | 7498 | aprint_error_dev(sc->sc_dev, "device timeout\n"); |
7499 | ifp->if_oerrors++; | | 7499 | ifp->if_oerrors++; |
7500 | /* TODO */ | | 7500 | /* TODO */ |
7501 | /* [TRC: XXX TODO what? Stop the device? | | 7501 | /* [TRC: XXX TODO what? Stop the device? |
7502 | Bring it down? iwi(4) does this.] */ | | 7502 | Bring it down? iwi(4) does this.] */ |
7503 | } else | | 7503 | } else |
7504 | ifp->if_timer = 1; | | 7504 | ifp->if_timer = 1; |
7505 | } | | 7505 | } |
7506 | | | 7506 | |
7507 | ieee80211_watchdog(&sc->sc_ic); | | 7507 | ieee80211_watchdog(&sc->sc_ic); |
7508 | } | | 7508 | } |
7509 | | | 7509 | |
7510 | static void | | 7510 | static void |
7511 | bwi_stop(struct ifnet *ifp, int state_chg) | | 7511 | bwi_stop(struct ifnet *ifp, int state_chg) |
7512 | { | | 7512 | { |
7513 | struct bwi_softc *sc = ifp->if_softc; | | 7513 | struct bwi_softc *sc = ifp->if_softc; |
7514 | struct ieee80211com *ic = &sc->sc_ic; | | 7514 | struct ieee80211com *ic = &sc->sc_ic; |
7515 | struct bwi_mac *mac; | | 7515 | struct bwi_mac *mac; |
7516 | int i, error, pwr_off = 0; | | 7516 | int i, error, pwr_off = 0; |
7517 | | | 7517 | |
7518 | DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__); | | 7518 | DPRINTF(sc, BWI_DBG_MISC, "%s\n", __func__); |
7519 | | | 7519 | |
7520 | if (state_chg) | | 7520 | if (state_chg) |
7521 | ieee80211_new_state(ic, IEEE80211_S_INIT, -1); | | 7521 | ieee80211_new_state(ic, IEEE80211_S_INIT, -1); |
7522 | else | | 7522 | else |
7523 | bwi_newstate_begin(sc, IEEE80211_S_INIT); | | 7523 | bwi_newstate_begin(sc, IEEE80211_S_INIT); |
7524 | | | 7524 | |
7525 | if (ifp->if_flags & IFF_RUNNING) { | | 7525 | if (ifp->if_flags & IFF_RUNNING) { |
7526 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); | | 7526 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); |
7527 | mac = (struct bwi_mac *)sc->sc_cur_regwin; | | 7527 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
7528 | | | 7528 | |
7529 | bwi_disable_intrs(sc, BWI_ALL_INTRS); | | 7529 | bwi_disable_intrs(sc, BWI_ALL_INTRS); |
7530 | CSR_READ_4(sc, BWI_MAC_INTR_MASK); | | 7530 | CSR_READ_4(sc, BWI_MAC_INTR_MASK); |
7531 | bwi_mac_stop(mac); | | 7531 | bwi_mac_stop(mac); |
7532 | } | | 7532 | } |
7533 | | | 7533 | |
7534 | for (i = 0; i < sc->sc_nmac; ++i) { | | 7534 | for (i = 0; i < sc->sc_nmac; ++i) { |
7535 | struct bwi_regwin *old_rw; | | 7535 | struct bwi_regwin *old_rw; |
7536 | | | 7536 | |
7537 | mac = &sc->sc_mac[i]; | | 7537 | mac = &sc->sc_mac[i]; |
7538 | if ((mac->mac_flags & BWI_MAC_F_INITED) == 0) | | 7538 | if ((mac->mac_flags & BWI_MAC_F_INITED) == 0) |
7539 | continue; | | 7539 | continue; |
7540 | | | 7540 | |
7541 | error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw); | | 7541 | error = bwi_regwin_switch(sc, &mac->mac_regwin, &old_rw); |
7542 | if (error) | | 7542 | if (error) |
7543 | continue; | | 7543 | continue; |
7544 | | | 7544 | |
7545 | bwi_mac_shutdown(mac); | | 7545 | bwi_mac_shutdown(mac); |
7546 | pwr_off = 1; | | 7546 | pwr_off = 1; |
7547 | | | 7547 | |
7548 | bwi_regwin_switch(sc, old_rw, NULL); | | 7548 | bwi_regwin_switch(sc, old_rw, NULL); |
7549 | } | | 7549 | } |
7550 | | | 7550 | |
7551 | if (pwr_off) | | 7551 | if (pwr_off) |
7552 | bwi_bbp_power_off(sc); | | 7552 | bwi_bbp_power_off(sc); |
7553 | | | 7553 | |
7554 | sc->sc_tx_timer = 0; | | 7554 | sc->sc_tx_timer = 0; |
7555 | ifp->if_timer = 0; | | 7555 | ifp->if_timer = 0; |
7556 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); | | 7556 | ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); |
7557 | | | 7557 | |
7558 | /* power off cardbus socket */ | | 7558 | /* power off cardbus socket */ |
7559 | if (sc->sc_disable) | | 7559 | if (sc->sc_disable) |
7560 | (sc->sc_disable)(sc); | | 7560 | (sc->sc_disable)(sc); |
7561 | | | 7561 | |
7562 | return; | | 7562 | return; |
7563 | } | | 7563 | } |
7564 | | | 7564 | |
7565 | static void | | 7565 | static void |
7566 | bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate) | | 7566 | bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate) |
7567 | { | | 7567 | { |
7568 | callout_stop(&sc->sc_scan_ch); | | 7568 | callout_stop(&sc->sc_scan_ch); |
7569 | callout_stop(&sc->sc_calib_ch); | | 7569 | callout_stop(&sc->sc_calib_ch); |
7570 | | | 7570 | |
7571 | bwi_led_newstate(sc, nstate); | | 7571 | bwi_led_newstate(sc, nstate); |
7572 | | | 7572 | |
7573 | if (nstate == IEEE80211_S_INIT) | | 7573 | if (nstate == IEEE80211_S_INIT) |
7574 | sc->sc_txpwrcb_type = BWI_TXPWR_INIT; | | 7574 | sc->sc_txpwrcb_type = BWI_TXPWR_INIT; |
7575 | } | | 7575 | } |
7576 | | | 7576 | |
7577 | static int | | 7577 | static int |
7578 | bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) | | 7578 | bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg) |
7579 | { | | 7579 | { |
7580 | struct bwi_softc *sc = ic->ic_ifp->if_softc; | | 7580 | struct bwi_softc *sc = ic->ic_ifp->if_softc; |
7581 | struct ieee80211_node *ni; | | 7581 | struct ieee80211_node *ni; |
7582 | int error; | | 7582 | int error; |
7583 | | | 7583 | |
7584 | /* [TRC: XXX amrr] */ | | 7584 | /* [TRC: XXX amrr] */ |
7585 | callout_stop(&sc->sc_amrr_ch); | | 7585 | callout_stop(&sc->sc_amrr_ch); |
7586 | | | 7586 | |
7587 | bwi_newstate_begin(sc, nstate); | | 7587 | bwi_newstate_begin(sc, nstate); |
7588 | | | 7588 | |
7589 | if (nstate == IEEE80211_S_INIT) | | 7589 | if (nstate == IEEE80211_S_INIT) |
7590 | goto back; | | 7590 | goto back; |
7591 | | | 7591 | |
7592 | /* [TRC: XXX What channel do we set this to? */ | | 7592 | /* [TRC: XXX What channel do we set this to? */ |
7593 | error = bwi_set_chan(sc, ic->ic_curchan); | | 7593 | error = bwi_set_chan(sc, ic->ic_curchan); |
7594 | if (error) { | | 7594 | if (error) { |
7595 | aprint_error_dev(sc->sc_dev, "can't set channel to %u\n", | | 7595 | aprint_error_dev(sc->sc_dev, "can't set channel to %u\n", |
7596 | ieee80211_chan2ieee(ic, ic->ic_curchan)); | | 7596 | ieee80211_chan2ieee(ic, ic->ic_curchan)); |
7597 | return (error); | | 7597 | return (error); |
7598 | } | | 7598 | } |
7599 | | | 7599 | |
7600 | if (ic->ic_opmode == IEEE80211_M_MONITOR) { | | 7600 | if (ic->ic_opmode == IEEE80211_M_MONITOR) { |
7601 | /* Nothing to do */ | | 7601 | /* Nothing to do */ |
7602 | } else if (nstate == IEEE80211_S_RUN) { | | 7602 | } else if (nstate == IEEE80211_S_RUN) { |
7603 | struct bwi_mac *mac; | | 7603 | struct bwi_mac *mac; |
7604 | | | 7604 | |
7605 | ni = ic->ic_bss; | | 7605 | ni = ic->ic_bss; |
7606 | | | 7606 | |
7607 | bwi_set_bssid(sc, ic->ic_bss->ni_bssid); | | 7607 | bwi_set_bssid(sc, ic->ic_bss->ni_bssid); |
7608 | | | 7608 | |
7609 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); | | 7609 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); |
7610 | mac = (struct bwi_mac *)sc->sc_cur_regwin; | | 7610 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
7611 | | | 7611 | |
7612 | /* Initial TX power calibration */ | | 7612 | /* Initial TX power calibration */ |
7613 | bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT); | | 7613 | bwi_mac_calibrate_txpower(mac, BWI_TXPWR_INIT); |
7614 | #ifdef notyet | | 7614 | #ifdef notyet |
7615 | sc->sc_txpwrcb_type = BWI_TXPWR_FORCE; | | 7615 | sc->sc_txpwrcb_type = BWI_TXPWR_FORCE; |
7616 | #else | | 7616 | #else |
7617 | sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; | | 7617 | sc->sc_txpwrcb_type = BWI_TXPWR_CALIB; |
7618 | #endif | | 7618 | #endif |
7619 | /* [TRC: XXX amrr] */ | | 7619 | /* [TRC: XXX amrr] */ |
7620 | if (ic->ic_opmode == IEEE80211_M_STA) { | | 7620 | if (ic->ic_opmode == IEEE80211_M_STA) { |
7621 | /* fake a join to init the tx rate */ | | 7621 | /* fake a join to init the tx rate */ |
7622 | bwi_newassoc(ni, 1); | | 7622 | bwi_newassoc(ni, 1); |
7623 | } | | 7623 | } |
7624 | | | 7624 | |
7625 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { | | 7625 | if (ic->ic_opmode != IEEE80211_M_MONITOR) { |
7626 | /* start automatic rate control timer */ | | 7626 | /* start automatic rate control timer */ |
7627 | if (ic->ic_fixed_rate == -1) | | 7627 | if (ic->ic_fixed_rate == -1) |
7628 | callout_schedule(&sc->sc_amrr_ch, hz / 2); | | 7628 | callout_schedule(&sc->sc_amrr_ch, hz / 2); |
7629 | } | | 7629 | } |
7630 | } else | | 7630 | } else |
7631 | bwi_set_bssid(sc, bwi_zero_addr); | | 7631 | bwi_set_bssid(sc, bwi_zero_addr); |
7632 | | | 7632 | |
7633 | back: | | 7633 | back: |
7634 | error = (sc->sc_newstate)(ic, nstate, arg); | | 7634 | error = (sc->sc_newstate)(ic, nstate, arg); |
7635 | | | 7635 | |
7636 | if (nstate == IEEE80211_S_SCAN) { | | 7636 | if (nstate == IEEE80211_S_SCAN) { |
7637 | callout_schedule(&sc->sc_scan_ch, | | 7637 | callout_schedule(&sc->sc_scan_ch, |
7638 | (sc->sc_dwell_time * hz) / 1000); | | 7638 | (sc->sc_dwell_time * hz) / 1000); |
7639 | } else if (nstate == IEEE80211_S_RUN) { | | 7639 | } else if (nstate == IEEE80211_S_RUN) { |
7640 | /* XXX 15 seconds */ | | 7640 | /* XXX 15 seconds */ |
7641 | callout_schedule(&sc->sc_calib_ch, hz); | | 7641 | callout_schedule(&sc->sc_calib_ch, hz); |
7642 | } | | 7642 | } |
7643 | | | 7643 | |
7644 | return (error); | | 7644 | return (error); |
7645 | } | | 7645 | } |
7646 | | | 7646 | |
7647 | static int | | 7647 | static int |
7648 | bwi_media_change(struct ifnet *ifp) | | 7648 | bwi_media_change(struct ifnet *ifp) |
7649 | { | | 7649 | { |
7650 | int error; | | 7650 | int error; |
7651 | | | 7651 | |
7652 | error = ieee80211_media_change(ifp); | | 7652 | error = ieee80211_media_change(ifp); |
7653 | if (error != ENETRESET) | | 7653 | if (error != ENETRESET) |
7654 | return (error); | | 7654 | return (error); |
7655 | | | 7655 | |
7656 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) | | 7656 | if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == (IFF_UP | IFF_RUNNING)) |
7657 | bwi_init(ifp); | | 7657 | bwi_init(ifp); |
7658 | | | 7658 | |
7659 | return (0); | | 7659 | return (0); |
7660 | } | | 7660 | } |
7661 | | | 7661 | |
7662 | /* [TRC: XXX amrr] */ | | 7662 | /* [TRC: XXX amrr] */ |
7663 | static void | | 7663 | static void |
7664 | bwi_iter_func(void *arg, struct ieee80211_node *ni) | | 7664 | bwi_iter_func(void *arg, struct ieee80211_node *ni) |
7665 | { | | 7665 | { |
7666 | struct bwi_softc *sc = arg; | | 7666 | struct bwi_softc *sc = arg; |
7667 | struct bwi_node *bn = (struct bwi_node *)ni; | | 7667 | struct bwi_node *bn = (struct bwi_node *)ni; |
7668 | | | 7668 | |
7669 | ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn); | | 7669 | ieee80211_amrr_choose(&sc->sc_amrr, ni, &bn->amn); |
7670 | } | | 7670 | } |
7671 | | | 7671 | |
7672 | static void | | 7672 | static void |
7673 | bwi_amrr_timeout(void *arg) | | 7673 | bwi_amrr_timeout(void *arg) |
7674 | { | | 7674 | { |
7675 | struct bwi_softc *sc = arg; | | 7675 | struct bwi_softc *sc = arg; |
7676 | struct ieee80211com *ic = &sc->sc_ic; | | 7676 | struct ieee80211com *ic = &sc->sc_ic; |
7677 | | | 7677 | |
7678 | if (ic->ic_opmode == IEEE80211_M_STA) | | 7678 | if (ic->ic_opmode == IEEE80211_M_STA) |
7679 | bwi_iter_func(sc, ic->ic_bss); | | 7679 | bwi_iter_func(sc, ic->ic_bss); |
7680 | else | | 7680 | else |
7681 | /* [TRC: XXX I'm making a wild guess about what to | | 7681 | /* [TRC: XXX I'm making a wild guess about what to |
7682 | supply for the node table.] */ | | 7682 | supply for the node table.] */ |
7683 | ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc); | | 7683 | ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc); |
7684 | | | 7684 | |
7685 | callout_schedule(&sc->sc_amrr_ch, hz / 2); | | 7685 | callout_schedule(&sc->sc_amrr_ch, hz / 2); |
7686 | } | | 7686 | } |
7687 | | | 7687 | |
7688 | static void | | 7688 | static void |
7689 | bwi_newassoc(struct ieee80211_node *ni, int isnew) | | 7689 | bwi_newassoc(struct ieee80211_node *ni, int isnew) |
7690 | { | | 7690 | { |
7691 | struct ieee80211com *ic = ni->ni_ic; | | 7691 | struct ieee80211com *ic = ni->ni_ic; |
7692 | struct bwi_softc *sc = ic->ic_ifp->if_softc; | | 7692 | struct bwi_softc *sc = ic->ic_ifp->if_softc; |
7693 | int i; | | 7693 | int i; |
7694 | | | 7694 | |
7695 | DPRINTF(sc, BWI_DBG_STATION, "%s\n", __func__); | | 7695 | DPRINTF(sc, BWI_DBG_STATION, "%s\n", __func__); |
7696 | | | 7696 | |
7697 | ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn); | | 7697 | ieee80211_amrr_node_init(&sc->sc_amrr, &((struct bwi_node *)ni)->amn); |
7698 | | | 7698 | |
7699 | /* set rate to some reasonable initial value */ | | 7699 | /* set rate to some reasonable initial value */ |
7700 | for (i = ni->ni_rates.rs_nrates - 1; | | 7700 | for (i = ni->ni_rates.rs_nrates - 1; |
7701 | i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72; | | 7701 | i > 0 && (ni->ni_rates.rs_rates[i] & IEEE80211_RATE_VAL) > 72; |
7702 | i--); | | 7702 | i--); |
7703 | | | 7703 | |
7704 | ni->ni_txrate = i; | | 7704 | ni->ni_txrate = i; |
7705 | } | | 7705 | } |
7706 | | | 7706 | |
7707 | static struct ieee80211_node * | | 7707 | static struct ieee80211_node * |
7708 | bwi_node_alloc(struct ieee80211_node_table *nt) | | 7708 | bwi_node_alloc(struct ieee80211_node_table *nt) |
7709 | { | | 7709 | { |
7710 | struct bwi_node *bn; | | 7710 | struct bwi_node *bn; |
7711 | | | 7711 | |
7712 | bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO); | | 7712 | bn = malloc(sizeof(struct bwi_node), M_80211_NODE, M_NOWAIT | M_ZERO); |
7713 | | | 7713 | |
7714 | return ((struct ieee80211_node *)bn); | | 7714 | return ((struct ieee80211_node *)bn); |
7715 | } | | 7715 | } |
7716 | /* [TRC: XXX amrr end] */ | | 7716 | /* [TRC: XXX amrr end] */ |
7717 | | | 7717 | |
7718 | static int | | 7718 | static int |
7719 | bwi_dma_alloc(struct bwi_softc *sc) | | 7719 | bwi_dma_alloc(struct bwi_softc *sc) |
7720 | { | | 7720 | { |
7721 | int error, i, has_txstats; | | 7721 | int error, i, has_txstats; |
7722 | /* [TRC: XXX DragonFlyBSD adjusts the low address for different | | 7722 | /* [TRC: XXX DragonFlyBSD adjusts the low address for different |
7723 | bus spaces. Should we?] */ | | 7723 | bus spaces. Should we?] */ |
7724 | bus_size_t tx_ring_sz, rx_ring_sz, desc_sz = 0; | | 7724 | bus_size_t tx_ring_sz, rx_ring_sz, desc_sz = 0; |
7725 | uint32_t txrx_ctrl_step = 0; | | 7725 | uint32_t txrx_ctrl_step = 0; |
7726 | | | 7726 | |
7727 | has_txstats = 0; | | 7727 | has_txstats = 0; |
7728 | for (i = 0; i < sc->sc_nmac; ++i) { | | 7728 | for (i = 0; i < sc->sc_nmac; ++i) { |
7729 | if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS) { | | 7729 | if (sc->sc_mac[i].mac_flags & BWI_MAC_F_HAS_TXSTATS) { |
7730 | has_txstats = 1; | | 7730 | has_txstats = 1; |
7731 | break; | | 7731 | break; |
7732 | } | | 7732 | } |
7733 | } | | 7733 | } |
7734 | | | 7734 | |
7735 | switch (sc->sc_bus_space) { | | 7735 | switch (sc->sc_bus_space) { |
7736 | case BWI_BUS_SPACE_30BIT: | | 7736 | case BWI_BUS_SPACE_30BIT: |
7737 | case BWI_BUS_SPACE_32BIT: | | 7737 | case BWI_BUS_SPACE_32BIT: |
7738 | desc_sz = sizeof(struct bwi_desc32); | | 7738 | desc_sz = sizeof(struct bwi_desc32); |
7739 | txrx_ctrl_step = 0x20; | | 7739 | txrx_ctrl_step = 0x20; |
7740 | | | 7740 | |
7741 | sc->sc_init_tx_ring = bwi_init_tx_ring32; | | 7741 | sc->sc_init_tx_ring = bwi_init_tx_ring32; |
7742 | sc->sc_free_tx_ring = bwi_free_tx_ring32; | | 7742 | sc->sc_free_tx_ring = bwi_free_tx_ring32; |
7743 | sc->sc_init_rx_ring = bwi_init_rx_ring32; | | 7743 | sc->sc_init_rx_ring = bwi_init_rx_ring32; |
7744 | sc->sc_free_rx_ring = bwi_free_rx_ring32; | | 7744 | sc->sc_free_rx_ring = bwi_free_rx_ring32; |
7745 | sc->sc_setup_rxdesc = bwi_setup_rx_desc32; | | 7745 | sc->sc_setup_rxdesc = bwi_setup_rx_desc32; |
7746 | sc->sc_setup_txdesc = bwi_setup_tx_desc32; | | 7746 | sc->sc_setup_txdesc = bwi_setup_tx_desc32; |
7747 | sc->sc_rxeof = bwi_rxeof32; | | 7747 | sc->sc_rxeof = bwi_rxeof32; |
7748 | sc->sc_start_tx = bwi_start_tx32; | | 7748 | sc->sc_start_tx = bwi_start_tx32; |
7749 | if (has_txstats) { | | 7749 | if (has_txstats) { |
7750 | sc->sc_init_txstats = bwi_init_txstats32; | | 7750 | sc->sc_init_txstats = bwi_init_txstats32; |
7751 | sc->sc_free_txstats = bwi_free_txstats32; | | 7751 | sc->sc_free_txstats = bwi_free_txstats32; |
7752 | sc->sc_txeof_status = bwi_txeof_status32; | | 7752 | sc->sc_txeof_status = bwi_txeof_status32; |
7753 | } | | 7753 | } |
7754 | break; | | 7754 | break; |
7755 | | | 7755 | |
7756 | case BWI_BUS_SPACE_64BIT: | | 7756 | case BWI_BUS_SPACE_64BIT: |
7757 | desc_sz = sizeof(struct bwi_desc64); | | 7757 | desc_sz = sizeof(struct bwi_desc64); |
7758 | txrx_ctrl_step = 0x40; | | 7758 | txrx_ctrl_step = 0x40; |
7759 | | | 7759 | |
7760 | sc->sc_init_tx_ring = bwi_init_tx_ring64; | | 7760 | sc->sc_init_tx_ring = bwi_init_tx_ring64; |
7761 | sc->sc_free_tx_ring = bwi_free_tx_ring64; | | 7761 | sc->sc_free_tx_ring = bwi_free_tx_ring64; |
7762 | sc->sc_init_rx_ring = bwi_init_rx_ring64; | | 7762 | sc->sc_init_rx_ring = bwi_init_rx_ring64; |
7763 | sc->sc_free_rx_ring = bwi_free_rx_ring64; | | 7763 | sc->sc_free_rx_ring = bwi_free_rx_ring64; |
7764 | sc->sc_setup_rxdesc = bwi_setup_rx_desc64; | | 7764 | sc->sc_setup_rxdesc = bwi_setup_rx_desc64; |
7765 | sc->sc_setup_txdesc = bwi_setup_tx_desc64; | | 7765 | sc->sc_setup_txdesc = bwi_setup_tx_desc64; |
7766 | sc->sc_rxeof = bwi_rxeof64; | | 7766 | sc->sc_rxeof = bwi_rxeof64; |
7767 | sc->sc_start_tx = bwi_start_tx64; | | 7767 | sc->sc_start_tx = bwi_start_tx64; |
7768 | if (has_txstats) { | | 7768 | if (has_txstats) { |
7769 | sc->sc_init_txstats = bwi_init_txstats64; | | 7769 | sc->sc_init_txstats = bwi_init_txstats64; |
7770 | sc->sc_free_txstats = bwi_free_txstats64; | | 7770 | sc->sc_free_txstats = bwi_free_txstats64; |
7771 | sc->sc_txeof_status = bwi_txeof_status64; | | 7771 | sc->sc_txeof_status = bwi_txeof_status64; |
7772 | } | | 7772 | } |
7773 | break; | | 7773 | break; |
7774 | } | | 7774 | } |
7775 | | | 7775 | |
7776 | KASSERT(desc_sz != 0); | | 7776 | KASSERT(desc_sz != 0); |
7777 | KASSERT(txrx_ctrl_step != 0); | | 7777 | KASSERT(txrx_ctrl_step != 0); |
7778 | | | 7778 | |
7779 | tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN); | | 7779 | tx_ring_sz = roundup(desc_sz * BWI_TX_NDESC, BWI_RING_ALIGN); |
7780 | rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN); | | 7780 | rx_ring_sz = roundup(desc_sz * BWI_RX_NDESC, BWI_RING_ALIGN); |
7781 | | | 7781 | |
7782 | /* [TRC: XXX Using OpenBSD's code, which is rather different | | 7782 | /* [TRC: XXX Using OpenBSD's code, which is rather different |
7783 | from DragonFlyBSD's.] */ | | 7783 | from DragonFlyBSD's.] */ |
7784 | #define TXRX_CTRL(idx) (BWI_TXRX_CTRL_BASE + (idx) * txrx_ctrl_step) | | 7784 | #define TXRX_CTRL(idx) (BWI_TXRX_CTRL_BASE + (idx) * txrx_ctrl_step) |
7785 | /* | | 7785 | /* |
7786 | * Create TX ring DMA stuffs | | 7786 | * Create TX ring DMA stuffs |
7787 | */ | | 7787 | */ |
7788 | for (i = 0; i < BWI_TX_NRING; ++i) { | | 7788 | for (i = 0; i < BWI_TX_NRING; ++i) { |
7789 | error = bus_dmamap_create(sc->sc_dmat, tx_ring_sz, 1, | | 7789 | error = bus_dmamap_create(sc->sc_dmat, tx_ring_sz, 1, |
7790 | tx_ring_sz, 0, BUS_DMA_NOWAIT, | | 7790 | tx_ring_sz, 0, BUS_DMA_NOWAIT, |
7791 | &sc->sc_tx_rdata[i].rdata_dmap); | | 7791 | &sc->sc_tx_rdata[i].rdata_dmap); |
7792 | if (error) { | | 7792 | if (error) { |
7793 | aprint_error_dev(sc->sc_dev, | | 7793 | aprint_error_dev(sc->sc_dev, |
7794 | "%dth TX ring DMA create failed\n", i); | | 7794 | "%dth TX ring DMA create failed\n", i); |
7795 | return (error); | | 7795 | return (error); |
7796 | } | | 7796 | } |
7797 | error = bwi_dma_ring_alloc(sc, | | 7797 | error = bwi_dma_ring_alloc(sc, |
7798 | &sc->sc_tx_rdata[i], tx_ring_sz, TXRX_CTRL(i)); | | 7798 | &sc->sc_tx_rdata[i], tx_ring_sz, TXRX_CTRL(i)); |
7799 | if (error) { | | 7799 | if (error) { |
7800 | aprint_error_dev(sc->sc_dev, | | 7800 | aprint_error_dev(sc->sc_dev, |
7801 | "%dth TX ring DMA alloc failed\n", i); | | 7801 | "%dth TX ring DMA alloc failed\n", i); |
7802 | return (error); | | 7802 | return (error); |
7803 | } | | 7803 | } |
7804 | } | | 7804 | } |
7805 | | | 7805 | |
7806 | /* | | 7806 | /* |
7807 | * Create RX ring DMA stuffs | | 7807 | * Create RX ring DMA stuffs |
7808 | */ | | 7808 | */ |
7809 | error = bus_dmamap_create(sc->sc_dmat, rx_ring_sz, 1, | | 7809 | error = bus_dmamap_create(sc->sc_dmat, rx_ring_sz, 1, |
7810 | rx_ring_sz, 0, BUS_DMA_NOWAIT, | | 7810 | rx_ring_sz, 0, BUS_DMA_NOWAIT, |
7811 | &sc->sc_rx_rdata.rdata_dmap); | | 7811 | &sc->sc_rx_rdata.rdata_dmap); |
7812 | if (error) { | | 7812 | if (error) { |
7813 | aprint_error_dev(sc->sc_dev, "RX ring DMA create failed\n"); | | 7813 | aprint_error_dev(sc->sc_dev, "RX ring DMA create failed\n"); |
7814 | return (error); | | 7814 | return (error); |
7815 | } | | 7815 | } |
7816 | | | 7816 | |
7817 | error = bwi_dma_ring_alloc(sc, &sc->sc_rx_rdata, | | 7817 | error = bwi_dma_ring_alloc(sc, &sc->sc_rx_rdata, |
7818 | rx_ring_sz, TXRX_CTRL(0)); | | 7818 | rx_ring_sz, TXRX_CTRL(0)); |
7819 | if (error) { | | 7819 | if (error) { |
7820 | aprint_error_dev(sc->sc_dev, "RX ring DMA alloc failed\n"); | | 7820 | aprint_error_dev(sc->sc_dev, "RX ring DMA alloc failed\n"); |
7821 | return (error); | | 7821 | return (error); |
7822 | } | | 7822 | } |
7823 | | | 7823 | |
7824 | if (has_txstats) { | | 7824 | if (has_txstats) { |
7825 | error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz); | | 7825 | error = bwi_dma_txstats_alloc(sc, TXRX_CTRL(3), desc_sz); |
7826 | if (error) { | | 7826 | if (error) { |
7827 | aprint_error_dev(sc->sc_dev, | | 7827 | aprint_error_dev(sc->sc_dev, |
7828 | "TX stats DMA alloc failed\n"); | | 7828 | "TX stats DMA alloc failed\n"); |
7829 | return (error); | | 7829 | return (error); |
7830 | } | | 7830 | } |
7831 | } | | 7831 | } |
7832 | #undef TXRX_CTRL | | 7832 | #undef TXRX_CTRL |
7833 | | | 7833 | |
7834 | return (bwi_dma_mbuf_create(sc)); | | 7834 | return (bwi_dma_mbuf_create(sc)); |
7835 | } | | 7835 | } |
7836 | | | 7836 | |
7837 | static void | | 7837 | static void |
7838 | bwi_dma_free(struct bwi_softc *sc) | | 7838 | bwi_dma_free(struct bwi_softc *sc) |
7839 | { | | 7839 | { |
7840 | int i; | | 7840 | int i; |
7841 | | | 7841 | |
7842 | for (i = 0; i < BWI_TX_NRING; ++i) | | 7842 | for (i = 0; i < BWI_TX_NRING; ++i) |
7843 | bwi_ring_data_free(&sc->sc_tx_rdata[i], sc); | | 7843 | bwi_ring_data_free(&sc->sc_tx_rdata[i], sc); |
7844 | | | 7844 | |
7845 | bwi_ring_data_free(&sc->sc_rx_rdata, sc); | | 7845 | bwi_ring_data_free(&sc->sc_rx_rdata, sc); |
7846 | bwi_dma_txstats_free(sc); | | 7846 | bwi_dma_txstats_free(sc); |
7847 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1); | | 7847 | bwi_dma_mbuf_destroy(sc, BWI_TX_NRING, 1); |
7848 | } | | 7848 | } |
7849 | | | 7849 | |
7850 | static void | | 7850 | static void |
7851 | bwi_ring_data_free(struct bwi_ring_data *rd, struct bwi_softc *sc) | | 7851 | bwi_ring_data_free(struct bwi_ring_data *rd, struct bwi_softc *sc) |
7852 | { | | 7852 | { |
7853 | if (rd->rdata_desc != NULL) { | | 7853 | if (rd->rdata_desc != NULL) { |
7854 | bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap); | | 7854 | bus_dmamap_unload(sc->sc_dmat, rd->rdata_dmap); |
7855 | bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, 1); | | 7855 | bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, 1); |
7856 | } | | 7856 | } |
7857 | } | | 7857 | } |
7858 | | | 7858 | |
7859 | static int | | 7859 | static int |
7860 | bwi_dma_ring_alloc(struct bwi_softc *sc, | | 7860 | bwi_dma_ring_alloc(struct bwi_softc *sc, |
7861 | struct bwi_ring_data *rd, bus_size_t size, uint32_t txrx_ctrl) | | 7861 | struct bwi_ring_data *rd, bus_size_t size, uint32_t txrx_ctrl) |
7862 | { | | 7862 | { |
7863 | int error, nsegs; | | 7863 | int error, nsegs; |
7864 | | | 7864 | |
7865 | error = bus_dmamem_alloc(sc->sc_dmat, size, BWI_ALIGN, 0, | | 7865 | error = bus_dmamem_alloc(sc->sc_dmat, size, BWI_ALIGN, 0, |
7866 | &rd->rdata_seg, 1, &nsegs, BUS_DMA_NOWAIT); | | 7866 | &rd->rdata_seg, 1, &nsegs, BUS_DMA_NOWAIT); |
7867 | if (error) { | | 7867 | if (error) { |
7868 | aprint_error_dev(sc->sc_dev, "can't allocate DMA mem\n"); | | 7868 | aprint_error_dev(sc->sc_dev, "can't allocate DMA mem\n"); |
7869 | return (error); | | 7869 | return (error); |
7870 | } | | 7870 | } |
7871 | | | 7871 | |
7872 | error = bus_dmamem_map(sc->sc_dmat, &rd->rdata_seg, nsegs, | | 7872 | error = bus_dmamem_map(sc->sc_dmat, &rd->rdata_seg, nsegs, |
7873 | size, (void **)&rd->rdata_desc, BUS_DMA_NOWAIT); | | 7873 | size, (void **)&rd->rdata_desc, BUS_DMA_NOWAIT); |
7874 | if (error) { | | 7874 | if (error) { |
7875 | aprint_error_dev(sc->sc_dev, "can't map DMA mem\n"); | | 7875 | aprint_error_dev(sc->sc_dev, "can't map DMA mem\n"); |
7876 | return (error); | | 7876 | return (error); |
7877 | } | | 7877 | } |
7878 | | | 7878 | |
7879 | error = bus_dmamap_load(sc->sc_dmat, rd->rdata_dmap, rd->rdata_desc, | | 7879 | error = bus_dmamap_load(sc->sc_dmat, rd->rdata_dmap, rd->rdata_desc, |
7880 | size, NULL, BUS_DMA_WAITOK); | | 7880 | size, NULL, BUS_DMA_WAITOK); |
7881 | if (error) { | | 7881 | if (error) { |
7882 | aprint_error_dev(sc->sc_dev, "can't load DMA mem\n"); | | 7882 | aprint_error_dev(sc->sc_dev, "can't load DMA mem\n"); |
7883 | bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, nsegs); | | 7883 | bus_dmamem_free(sc->sc_dmat, &rd->rdata_seg, nsegs); |
7884 | rd->rdata_desc = NULL; | | 7884 | rd->rdata_desc = NULL; |
7885 | return (error); | | 7885 | return (error); |
7886 | } | | 7886 | } |
7887 | | | 7887 | |
7888 | rd->rdata_paddr = rd->rdata_dmap->dm_segs[0].ds_addr; | | 7888 | rd->rdata_paddr = rd->rdata_dmap->dm_segs[0].ds_addr; |
7889 | rd->rdata_txrx_ctrl = txrx_ctrl; | | 7889 | rd->rdata_txrx_ctrl = txrx_ctrl; |
7890 | | | 7890 | |
7891 | return (0); | | 7891 | return (0); |
7892 | } | | 7892 | } |
7893 | | | 7893 | |
7894 | static int | | 7894 | static int |
7895 | bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, | | 7895 | bwi_dma_txstats_alloc(struct bwi_softc *sc, uint32_t ctrl_base, |
7896 | bus_size_t desc_sz) | | 7896 | bus_size_t desc_sz) |
7897 | { | | 7897 | { |
7898 | struct bwi_txstats_data *st; | | 7898 | struct bwi_txstats_data *st; |
7899 | bus_size_t dma_size; | | 7899 | bus_size_t dma_size; |
7900 | int error, nsegs; | | 7900 | int error, nsegs; |
7901 | | | 7901 | |
7902 | st = malloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO); | | 7902 | st = malloc(sizeof(*st), M_DEVBUF, M_WAITOK | M_ZERO); |
7903 | sc->sc_txstats = st; | | 7903 | sc->sc_txstats = st; |
7904 | | | 7904 | |
7905 | /* | | 7905 | /* |
7906 | * Create TX stats descriptor DMA stuffs | | 7906 | * Create TX stats descriptor DMA stuffs |
7907 | */ | | 7907 | */ |
7908 | dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN); | | 7908 | dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN); |
7909 | | | 7909 | |
7910 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0, | | 7910 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0, |
7911 | BUS_DMA_NOWAIT, &st->stats_ring_dmap); | | 7911 | BUS_DMA_NOWAIT, &st->stats_ring_dmap); |
7912 | if (error) { | | 7912 | if (error) { |
7913 | aprint_error_dev(sc->sc_dev, | | 7913 | aprint_error_dev(sc->sc_dev, |
7914 | "can't create txstats ring DMA mem\n"); | | 7914 | "can't create txstats ring DMA mem\n"); |
7915 | return (error); | | 7915 | return (error); |
7916 | } | | 7916 | } |
7917 | | | 7917 | |
7918 | /* | | 7918 | /* |
7919 | * Create TX stats descriptor DMA stuffs | | 7919 | * Create TX stats descriptor DMA stuffs |
7920 | */ | | 7920 | */ |
7921 | dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN); | | 7921 | dma_size = roundup(desc_sz * BWI_TXSTATS_NDESC, BWI_RING_ALIGN); |
7922 | | | 7922 | |
7923 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0, | | 7923 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0, |
7924 | BUS_DMA_NOWAIT, &st->stats_ring_dmap); | | 7924 | BUS_DMA_NOWAIT, &st->stats_ring_dmap); |
7925 | if (error) { | | 7925 | if (error) { |
7926 | aprint_error_dev(sc->sc_dev, | | 7926 | aprint_error_dev(sc->sc_dev, |
7927 | "can't create txstats ring DMA mem\n"); | | 7927 | "can't create txstats ring DMA mem\n"); |
7928 | return (error); | | 7928 | return (error); |
7929 | } | | 7929 | } |
7930 | | | 7930 | |
7931 | error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_RING_ALIGN, 0, | | 7931 | error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_RING_ALIGN, 0, |
7932 | &st->stats_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT); | | 7932 | &st->stats_ring_seg, 1, &nsegs, BUS_DMA_NOWAIT); |
7933 | if (error) { | | 7933 | if (error) { |
7934 | aprint_error_dev(sc->sc_dev, | | 7934 | aprint_error_dev(sc->sc_dev, |
7935 | "can't allocate txstats ring DMA mem\n"); | | 7935 | "can't allocate txstats ring DMA mem\n"); |
7936 | return (error); | | 7936 | return (error); |
7937 | } | | 7937 | } |
7938 | | | 7938 | |
7939 | error = bus_dmamem_map(sc->sc_dmat, &st->stats_ring_seg, nsegs, | | 7939 | error = bus_dmamem_map(sc->sc_dmat, &st->stats_ring_seg, nsegs, |
7940 | dma_size, (void **)&st->stats_ring, BUS_DMA_NOWAIT); | | 7940 | dma_size, (void **)&st->stats_ring, BUS_DMA_NOWAIT); |
7941 | if (error) { | | 7941 | if (error) { |
7942 | aprint_error_dev(sc->sc_dev, | | 7942 | aprint_error_dev(sc->sc_dev, |
7943 | "can't map txstats ring DMA mem\n"); | | 7943 | "can't map txstats ring DMA mem\n"); |
7944 | return (error); | | 7944 | return (error); |
7945 | } | | 7945 | } |
7946 | | | 7946 | |
7947 | error = bus_dmamap_load(sc->sc_dmat, st->stats_ring_dmap, | | 7947 | error = bus_dmamap_load(sc->sc_dmat, st->stats_ring_dmap, |
7948 | st->stats_ring, dma_size, NULL, BUS_DMA_WAITOK); | | 7948 | st->stats_ring, dma_size, NULL, BUS_DMA_WAITOK); |
7949 | if (error) { | | 7949 | if (error) { |
7950 | aprint_error_dev(sc->sc_dev, | | 7950 | aprint_error_dev(sc->sc_dev, |
7951 | "can't load txstats ring DMA mem\n"); | | 7951 | "can't load txstats ring DMA mem\n"); |
7952 | bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, nsegs); | | 7952 | bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, nsegs); |
7953 | return (error); | | 7953 | return (error); |
7954 | } | | 7954 | } |
7955 | | | 7955 | |
7956 | memset(st->stats_ring, 0, dma_size); | | 7956 | memset(st->stats_ring, 0, dma_size); |
7957 | st->stats_ring_paddr = st->stats_ring_dmap->dm_segs[0].ds_addr; | | 7957 | st->stats_ring_paddr = st->stats_ring_dmap->dm_segs[0].ds_addr; |
7958 | | | 7958 | |
7959 | /* | | 7959 | /* |
7960 | * Create TX stats DMA stuffs | | 7960 | * Create TX stats DMA stuffs |
7961 | */ | | 7961 | */ |
7962 | dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC, | | 7962 | dma_size = roundup(sizeof(struct bwi_txstats) * BWI_TXSTATS_NDESC, |
7963 | BWI_ALIGN); | | 7963 | BWI_ALIGN); |
7964 | | | 7964 | |
7965 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0, | | 7965 | error = bus_dmamap_create(sc->sc_dmat, dma_size, 1, dma_size, 0, |
7966 | BUS_DMA_NOWAIT, &st->stats_dmap); | | 7966 | BUS_DMA_NOWAIT, &st->stats_dmap); |
7967 | if (error) { | | 7967 | if (error) { |
7968 | aprint_error_dev(sc->sc_dev, | | 7968 | aprint_error_dev(sc->sc_dev, |
7969 | "can't create txstats ring DMA mem\n"); | | 7969 | "can't create txstats ring DMA mem\n"); |
7970 | return (error); | | 7970 | return (error); |
7971 | } | | 7971 | } |
7972 | | | 7972 | |
7973 | error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_ALIGN, 0, | | 7973 | error = bus_dmamem_alloc(sc->sc_dmat, dma_size, BWI_ALIGN, 0, |
7974 | &st->stats_seg, 1, &nsegs, BUS_DMA_NOWAIT); | | 7974 | &st->stats_seg, 1, &nsegs, BUS_DMA_NOWAIT); |
7975 | if (error) { | | 7975 | if (error) { |
7976 | aprint_error_dev(sc->sc_dev, | | 7976 | aprint_error_dev(sc->sc_dev, |
7977 | "can't allocate txstats DMA mem\n"); | | 7977 | "can't allocate txstats DMA mem\n"); |
7978 | return (error); | | 7978 | return (error); |
7979 | } | | 7979 | } |
7980 | | | 7980 | |
7981 | error = bus_dmamem_map(sc->sc_dmat, &st->stats_seg, nsegs, | | 7981 | error = bus_dmamem_map(sc->sc_dmat, &st->stats_seg, nsegs, |
7982 | dma_size, (void **)&st->stats, BUS_DMA_NOWAIT); | | 7982 | dma_size, (void **)&st->stats, BUS_DMA_NOWAIT); |
7983 | if (error) { | | 7983 | if (error) { |
7984 | aprint_error_dev(sc->sc_dev, "can't map txstats DMA mem\n"); | | 7984 | aprint_error_dev(sc->sc_dev, "can't map txstats DMA mem\n"); |
7985 | return (error); | | 7985 | return (error); |
7986 | } | | 7986 | } |
7987 | | | 7987 | |
7988 | error = bus_dmamap_load(sc->sc_dmat, st->stats_dmap, st->stats, | | 7988 | error = bus_dmamap_load(sc->sc_dmat, st->stats_dmap, st->stats, |
7989 | dma_size, NULL, BUS_DMA_WAITOK); | | 7989 | dma_size, NULL, BUS_DMA_WAITOK); |
7990 | if (error) { | | 7990 | if (error) { |
7991 | aprint_error_dev(sc->sc_dev, "can't load txstats DMA mem\n"); | | 7991 | aprint_error_dev(sc->sc_dev, "can't load txstats DMA mem\n"); |
7992 | bus_dmamem_free(sc->sc_dmat, &st->stats_seg, nsegs); | | 7992 | bus_dmamem_free(sc->sc_dmat, &st->stats_seg, nsegs); |
7993 | return (error); | | 7993 | return (error); |
7994 | } | | 7994 | } |
7995 | | | 7995 | |
7996 | memset(st->stats, 0, dma_size); | | 7996 | memset(st->stats, 0, dma_size); |
7997 | st->stats_paddr = st->stats_dmap->dm_segs[0].ds_addr; | | 7997 | st->stats_paddr = st->stats_dmap->dm_segs[0].ds_addr; |
7998 | st->stats_ctrl_base = ctrl_base; | | 7998 | st->stats_ctrl_base = ctrl_base; |
7999 | | | 7999 | |
8000 | return (0); | | 8000 | return (0); |
8001 | } | | 8001 | } |
8002 | | | 8002 | |
8003 | static void | | 8003 | static void |
8004 | bwi_dma_txstats_free(struct bwi_softc *sc) | | 8004 | bwi_dma_txstats_free(struct bwi_softc *sc) |
8005 | { | | 8005 | { |
8006 | struct bwi_txstats_data *st; | | 8006 | struct bwi_txstats_data *st; |
8007 | | | 8007 | |
8008 | if (sc->sc_txstats == NULL) | | 8008 | if (sc->sc_txstats == NULL) |
8009 | return; | | 8009 | return; |
8010 | st = sc->sc_txstats; | | 8010 | st = sc->sc_txstats; |
8011 | | | 8011 | |
8012 | bus_dmamap_unload(sc->sc_dmat, st->stats_ring_dmap); | | 8012 | bus_dmamap_unload(sc->sc_dmat, st->stats_ring_dmap); |
8013 | bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, 1); | | 8013 | bus_dmamem_free(sc->sc_dmat, &st->stats_ring_seg, 1); |
8014 | | | 8014 | |
8015 | bus_dmamap_unload(sc->sc_dmat, st->stats_dmap); | | 8015 | bus_dmamap_unload(sc->sc_dmat, st->stats_dmap); |
8016 | bus_dmamem_free(sc->sc_dmat, &st->stats_seg, 1); | | 8016 | bus_dmamem_free(sc->sc_dmat, &st->stats_seg, 1); |
8017 | | | 8017 | |
8018 | free(st, M_DEVBUF); | | 8018 | free(st, M_DEVBUF); |
8019 | } | | 8019 | } |
8020 | | | 8020 | |
8021 | static int | | 8021 | static int |
8022 | bwi_dma_mbuf_create(struct bwi_softc *sc) | | 8022 | bwi_dma_mbuf_create(struct bwi_softc *sc) |
8023 | { | | 8023 | { |
8024 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | | 8024 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
8025 | int i, j, k, ntx, error; | | 8025 | int i, j, k, ntx, error; |
8026 | | | 8026 | |
8027 | ntx = 0; | | 8027 | ntx = 0; |
8028 | | | 8028 | |
8029 | /* | | 8029 | /* |
8030 | * Create TX mbuf DMA map | | 8030 | * Create TX mbuf DMA map |
8031 | */ | | 8031 | */ |
8032 | for (i = 0; i < BWI_TX_NRING; ++i) { | | 8032 | for (i = 0; i < BWI_TX_NRING; ++i) { |
8033 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; | | 8033 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; |
8034 | | | 8034 | |
8035 | for (j = 0; j < BWI_TX_NDESC; ++j) { | | 8035 | for (j = 0; j < BWI_TX_NDESC; ++j) { |
8036 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, | | 8036 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, |
8037 | 0, BUS_DMA_NOWAIT, &tbd->tbd_buf[j].tb_dmap); | | 8037 | 0, BUS_DMA_NOWAIT, &tbd->tbd_buf[j].tb_dmap); |
8038 | if (error) { | | 8038 | if (error) { |
8039 | aprint_error_dev(sc->sc_dev, | | 8039 | aprint_error_dev(sc->sc_dev, |
8040 | "can't create %dth tbd, %dth DMA map\n", | | 8040 | "can't create %dth tbd, %dth DMA map\n", |
8041 | i, j); | | 8041 | i, j); |
8042 | ntx = i; | | 8042 | ntx = i; |
8043 | for (k = 0; k < j; ++k) { | | 8043 | for (k = 0; k < j; ++k) { |
8044 | bus_dmamap_destroy(sc->sc_dmat, | | 8044 | bus_dmamap_destroy(sc->sc_dmat, |
8045 | tbd->tbd_buf[k].tb_dmap); | | 8045 | tbd->tbd_buf[k].tb_dmap); |
8046 | } | | 8046 | } |
8047 | goto fail; | | 8047 | goto fail; |
8048 | } | | 8048 | } |
8049 | } | | 8049 | } |
8050 | } | | 8050 | } |
8051 | ntx = BWI_TX_NRING; | | 8051 | ntx = BWI_TX_NRING; |
8052 | | | 8052 | |
8053 | /* | | 8053 | /* |
8054 | * Create RX mbuf DMA map and a spare DMA map | | 8054 | * Create RX mbuf DMA map and a spare DMA map |
8055 | */ | | 8055 | */ |
8056 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, | | 8056 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, |
8057 | BUS_DMA_NOWAIT, &rbd->rbd_tmp_dmap); | | 8057 | BUS_DMA_NOWAIT, &rbd->rbd_tmp_dmap); |
8058 | if (error) { | | 8058 | if (error) { |
8059 | aprint_error_dev(sc->sc_dev, | | 8059 | aprint_error_dev(sc->sc_dev, |
8060 | "can't create spare RX buf DMA map\n"); | | 8060 | "can't create spare RX buf DMA map\n"); |
8061 | goto fail; | | 8061 | goto fail; |
8062 | } | | 8062 | } |
8063 | | | 8063 | |
8064 | for (j = 0; j < BWI_RX_NDESC; ++j) { | | 8064 | for (j = 0; j < BWI_RX_NDESC; ++j) { |
8065 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, | | 8065 | error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0, |
8066 | BUS_DMA_NOWAIT, &rbd->rbd_buf[j].rb_dmap); | | 8066 | BUS_DMA_NOWAIT, &rbd->rbd_buf[j].rb_dmap); |
8067 | if (error) { | | 8067 | if (error) { |
8068 | aprint_error_dev(sc->sc_dev, | | 8068 | aprint_error_dev(sc->sc_dev, |
8069 | "can't create %dth RX buf DMA map\n", j); | | 8069 | "can't create %dth RX buf DMA map\n", j); |
8070 | | | 8070 | |
8071 | for (k = 0; k < j; ++k) { | | 8071 | for (k = 0; k < j; ++k) { |
8072 | bus_dmamap_destroy(sc->sc_dmat, | | 8072 | bus_dmamap_destroy(sc->sc_dmat, |
8073 | rbd->rbd_buf[j].rb_dmap); | | 8073 | rbd->rbd_buf[j].rb_dmap); |
8074 | } | | 8074 | } |
8075 | bus_dmamap_destroy(sc->sc_dmat, | | 8075 | bus_dmamap_destroy(sc->sc_dmat, |
8076 | rbd->rbd_tmp_dmap); | | 8076 | rbd->rbd_tmp_dmap); |
8077 | goto fail; | | 8077 | goto fail; |
8078 | } | | 8078 | } |
8079 | } | | 8079 | } |
8080 | | | 8080 | |
8081 | return (0); | | 8081 | return (0); |
8082 | fail: | | 8082 | fail: |
8083 | bwi_dma_mbuf_destroy(sc, ntx, 0); | | 8083 | bwi_dma_mbuf_destroy(sc, ntx, 0); |
8084 | | | 8084 | |
8085 | return (error); | | 8085 | return (error); |
8086 | } | | 8086 | } |
8087 | | | 8087 | |
8088 | static void | | 8088 | static void |
8089 | bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx) | | 8089 | bwi_dma_mbuf_destroy(struct bwi_softc *sc, int ntx, int nrx) |
8090 | { | | 8090 | { |
8091 | int i, j; | | 8091 | int i, j; |
8092 | | | 8092 | |
8093 | for (i = 0; i < ntx; ++i) { | | 8093 | for (i = 0; i < ntx; ++i) { |
8094 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; | | 8094 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[i]; |
8095 | | | 8095 | |
8096 | for (j = 0; j < BWI_TX_NDESC; ++j) { | | 8096 | for (j = 0; j < BWI_TX_NDESC; ++j) { |
8097 | struct bwi_txbuf *tb = &tbd->tbd_buf[j]; | | 8097 | struct bwi_txbuf *tb = &tbd->tbd_buf[j]; |
8098 | | | 8098 | |
8099 | if (tb->tb_mbuf != NULL) { | | 8099 | if (tb->tb_mbuf != NULL) { |
8100 | bus_dmamap_unload(sc->sc_dmat, | | 8100 | bus_dmamap_unload(sc->sc_dmat, |
8101 | tb->tb_dmap); | | 8101 | tb->tb_dmap); |
8102 | m_freem(tb->tb_mbuf); | | 8102 | m_freem(tb->tb_mbuf); |
8103 | } | | 8103 | } |
8104 | if (tb->tb_ni != NULL) | | 8104 | if (tb->tb_ni != NULL) |
8105 | ieee80211_free_node(tb->tb_ni); | | 8105 | ieee80211_free_node(tb->tb_ni); |
8106 | bus_dmamap_destroy(sc->sc_dmat, tb->tb_dmap); | | 8106 | bus_dmamap_destroy(sc->sc_dmat, tb->tb_dmap); |
8107 | } | | 8107 | } |
8108 | } | | 8108 | } |
8109 | | | 8109 | |
8110 | if (nrx) { | | 8110 | if (nrx) { |
8111 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | | 8111 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
8112 | | | 8112 | |
8113 | bus_dmamap_destroy(sc->sc_dmat, rbd->rbd_tmp_dmap); | | 8113 | bus_dmamap_destroy(sc->sc_dmat, rbd->rbd_tmp_dmap); |
8114 | for (j = 0; j < BWI_RX_NDESC; ++j) { | | 8114 | for (j = 0; j < BWI_RX_NDESC; ++j) { |
8115 | struct bwi_rxbuf *rb = &rbd->rbd_buf[j]; | | 8115 | struct bwi_rxbuf *rb = &rbd->rbd_buf[j]; |
8116 | | | 8116 | |
8117 | if (rb->rb_mbuf != NULL) { | | 8117 | if (rb->rb_mbuf != NULL) { |
8118 | bus_dmamap_unload(sc->sc_dmat, | | 8118 | bus_dmamap_unload(sc->sc_dmat, |
8119 | rb->rb_dmap); | | 8119 | rb->rb_dmap); |
8120 | m_freem(rb->rb_mbuf); | | 8120 | m_freem(rb->rb_mbuf); |
8121 | } | | 8121 | } |
8122 | bus_dmamap_destroy(sc->sc_dmat, rb->rb_dmap); | | 8122 | bus_dmamap_destroy(sc->sc_dmat, rb->rb_dmap); |
8123 | } | | 8123 | } |
8124 | } | | 8124 | } |
8125 | } | | 8125 | } |
8126 | | | 8126 | |
8127 | static void | | 8127 | static void |
8128 | bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs) | | 8128 | bwi_enable_intrs(struct bwi_softc *sc, uint32_t enable_intrs) |
8129 | { | | 8129 | { |
8130 | CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs); | | 8130 | CSR_SETBITS_4(sc, BWI_MAC_INTR_MASK, enable_intrs); |
8131 | } | | 8131 | } |
8132 | | | 8132 | |
8133 | static void | | 8133 | static void |
8134 | bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs) | | 8134 | bwi_disable_intrs(struct bwi_softc *sc, uint32_t disable_intrs) |
8135 | { | | 8135 | { |
8136 | CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs); | | 8136 | CSR_CLRBITS_4(sc, BWI_MAC_INTR_MASK, disable_intrs); |
8137 | } | | 8137 | } |
8138 | | | 8138 | |
8139 | static int | | 8139 | static int |
8140 | bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx) | | 8140 | bwi_init_tx_ring32(struct bwi_softc *sc, int ring_idx) |
8141 | { | | 8141 | { |
8142 | struct bwi_ring_data *rd; | | 8142 | struct bwi_ring_data *rd; |
8143 | struct bwi_txbuf_data *tbd; | | 8143 | struct bwi_txbuf_data *tbd; |
8144 | uint32_t val, addr_hi, addr_lo; | | 8144 | uint32_t val, addr_hi, addr_lo; |
8145 | | | 8145 | |
8146 | KASSERT(ring_idx < BWI_TX_NRING); | | 8146 | KASSERT(ring_idx < BWI_TX_NRING); |
8147 | rd = &sc->sc_tx_rdata[ring_idx]; | | 8147 | rd = &sc->sc_tx_rdata[ring_idx]; |
8148 | tbd = &sc->sc_tx_bdata[ring_idx]; | | 8148 | tbd = &sc->sc_tx_bdata[ring_idx]; |
8149 | | | 8149 | |
8150 | tbd->tbd_idx = 0; | | 8150 | tbd->tbd_idx = 0; |
8151 | tbd->tbd_used = 0; | | 8151 | tbd->tbd_used = 0; |
8152 | | | 8152 | |
8153 | memset(rd->rdata_desc, 0, sizeof(struct bwi_desc32) * BWI_TX_NDESC); | | 8153 | memset(rd->rdata_desc, 0, sizeof(struct bwi_desc32) * BWI_TX_NDESC); |
8154 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, | | 8154 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, |
8155 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 8155 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
8156 | | | 8156 | |
8157 | addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK); | | 8157 | addr_lo = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_ADDR_MASK); |
8158 | addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK); | | 8158 | addr_hi = __SHIFTOUT(rd->rdata_paddr, BWI_TXRX32_RINGINFO_FUNC_MASK); |
8159 | | | 8159 | |
8160 | val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) | | | 8160 | val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) | |
8161 | __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX, | | 8161 | __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX, |
8162 | BWI_TXRX32_RINGINFO_FUNC_MASK); | | 8162 | BWI_TXRX32_RINGINFO_FUNC_MASK); |
8163 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val); | | 8163 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, val); |
8164 | | | 8164 | |
8165 | val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) | | | 8165 | val = __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) | |
8166 | BWI_TXRX32_CTRL_ENABLE; | | 8166 | BWI_TXRX32_CTRL_ENABLE; |
8167 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val); | | 8167 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, val); |
8168 | | | 8168 | |
8169 | return (0); | | 8169 | return (0); |
8170 | } | | 8170 | } |
8171 | | | 8171 | |
8172 | static void | | 8172 | static void |
8173 | bwi_init_rxdesc_ring32(struct bwi_softc *sc, uint32_t ctrl_base, | | 8173 | bwi_init_rxdesc_ring32(struct bwi_softc *sc, uint32_t ctrl_base, |
8174 | bus_addr_t paddr, int hdr_size, int ndesc) | | 8174 | bus_addr_t paddr, int hdr_size, int ndesc) |
8175 | { | | 8175 | { |
8176 | uint32_t val, addr_hi, addr_lo; | | 8176 | uint32_t val, addr_hi, addr_lo; |
8177 | | | 8177 | |
8178 | addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK); | | 8178 | addr_lo = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_ADDR_MASK); |
8179 | addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK); | | 8179 | addr_hi = __SHIFTOUT(paddr, BWI_TXRX32_RINGINFO_FUNC_MASK); |
8180 | | | 8180 | |
8181 | val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) | | | 8181 | val = __SHIFTIN(addr_lo, BWI_TXRX32_RINGINFO_ADDR_MASK) | |
8182 | __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX, | | 8182 | __SHIFTIN(BWI_TXRX32_RINGINFO_FUNC_TXRX, |
8183 | BWI_TXRX32_RINGINFO_FUNC_MASK); | | 8183 | BWI_TXRX32_RINGINFO_FUNC_MASK); |
8184 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val); | | 8184 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_RINGINFO, val); |
8185 | | | 8185 | |
8186 | val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK) | | | 8186 | val = __SHIFTIN(hdr_size, BWI_RX32_CTRL_HDRSZ_MASK) | |
8187 | __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) | | | 8187 | __SHIFTIN(addr_hi, BWI_TXRX32_CTRL_ADDRHI_MASK) | |
8188 | BWI_TXRX32_CTRL_ENABLE; | | 8188 | BWI_TXRX32_CTRL_ENABLE; |
8189 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val); | | 8189 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_CTRL, val); |
8190 | | | 8190 | |
8191 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, | | 8191 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, |
8192 | (ndesc - 1) * sizeof(struct bwi_desc32)); | | 8192 | (ndesc - 1) * sizeof(struct bwi_desc32)); |
8193 | } | | 8193 | } |
8194 | | | 8194 | |
8195 | static int | | 8195 | static int |
8196 | bwi_init_rx_ring32(struct bwi_softc *sc) | | 8196 | bwi_init_rx_ring32(struct bwi_softc *sc) |
8197 | { | | 8197 | { |
8198 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; | | 8198 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
8199 | int i, error; | | 8199 | int i, error; |
8200 | | | 8200 | |
8201 | sc->sc_rx_bdata.rbd_idx = 0; | | 8201 | sc->sc_rx_bdata.rbd_idx = 0; |
8202 | | | 8202 | |
8203 | for (i = 0; i < BWI_RX_NDESC; ++i) { | | 8203 | for (i = 0; i < BWI_RX_NDESC; ++i) { |
8204 | error = bwi_newbuf(sc, i, 1); | | 8204 | error = bwi_newbuf(sc, i, 1); |
8205 | if (error) { | | 8205 | if (error) { |
8206 | aprint_error_dev(sc->sc_dev, | | 8206 | aprint_error_dev(sc->sc_dev, |
8207 | "can't allocate %dth RX buffer\n", i); | | 8207 | "can't allocate %dth RX buffer\n", i); |
8208 | return (error); | | 8208 | return (error); |
8209 | } | | 8209 | } |
8210 | } | | 8210 | } |
8211 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, | | 8211 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, |
8212 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 8212 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
8213 | | | 8213 | |
8214 | bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr, | | 8214 | bwi_init_rxdesc_ring32(sc, rd->rdata_txrx_ctrl, rd->rdata_paddr, |
8215 | sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC); | | 8215 | sizeof(struct bwi_rxbuf_hdr), BWI_RX_NDESC); |
8216 | return (0); | | 8216 | return (0); |
8217 | } | | 8217 | } |
8218 | | | 8218 | |
8219 | static int | | 8219 | static int |
8220 | bwi_init_txstats32(struct bwi_softc *sc) | | 8220 | bwi_init_txstats32(struct bwi_softc *sc) |
8221 | { | | 8221 | { |
8222 | struct bwi_txstats_data *st = sc->sc_txstats; | | 8222 | struct bwi_txstats_data *st = sc->sc_txstats; |
8223 | bus_addr_t stats_paddr; | | 8223 | bus_addr_t stats_paddr; |
8224 | int i; | | 8224 | int i; |
8225 | | | 8225 | |
8226 | memset(st->stats, 0, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats)); | | 8226 | memset(st->stats, 0, BWI_TXSTATS_NDESC * sizeof(struct bwi_txstats)); |
8227 | bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0, | | 8227 | bus_dmamap_sync(sc->sc_dmat, st->stats_dmap, 0, |
8228 | st->stats_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 8228 | st->stats_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
8229 | | | 8229 | |
8230 | st->stats_idx = 0; | | 8230 | st->stats_idx = 0; |
8231 | | | 8231 | |
8232 | stats_paddr = st->stats_paddr; | | 8232 | stats_paddr = st->stats_paddr; |
8233 | for (i = 0; i < BWI_TXSTATS_NDESC; ++i) { | | 8233 | for (i = 0; i < BWI_TXSTATS_NDESC; ++i) { |
8234 | bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC, i, | | 8234 | bwi_setup_desc32(sc, st->stats_ring, BWI_TXSTATS_NDESC, i, |
8235 | stats_paddr, sizeof(struct bwi_txstats), 0); | | 8235 | stats_paddr, sizeof(struct bwi_txstats), 0); |
8236 | stats_paddr += sizeof(struct bwi_txstats); | | 8236 | stats_paddr += sizeof(struct bwi_txstats); |
8237 | } | | 8237 | } |
8238 | bus_dmamap_sync(sc->sc_dmat, st->stats_ring_dmap, 0, | | 8238 | bus_dmamap_sync(sc->sc_dmat, st->stats_ring_dmap, 0, |
8239 | st->stats_ring_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 8239 | st->stats_ring_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
8240 | | | 8240 | |
8241 | bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base, | | 8241 | bwi_init_rxdesc_ring32(sc, st->stats_ctrl_base, |
8242 | st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC); | | 8242 | st->stats_ring_paddr, 0, BWI_TXSTATS_NDESC); |
8243 | | | 8243 | |
8244 | return (0); | | 8244 | return (0); |
8245 | } | | 8245 | } |
8246 | | | 8246 | |
8247 | static void | | 8247 | static void |
8248 | bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, | | 8248 | bwi_setup_rx_desc32(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, |
8249 | int buf_len) | | 8249 | int buf_len) |
8250 | { | | 8250 | { |
8251 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; | | 8251 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
8252 | | | 8252 | |
8253 | KASSERT(buf_idx < BWI_RX_NDESC); | | 8253 | KASSERT(buf_idx < BWI_RX_NDESC); |
8254 | bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx, | | 8254 | bwi_setup_desc32(sc, rd->rdata_desc, BWI_RX_NDESC, buf_idx, |
8255 | paddr, buf_len, 0); | | 8255 | paddr, buf_len, 0); |
8256 | } | | 8256 | } |
8257 | | | 8257 | |
8258 | static void | | 8258 | static void |
8259 | bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd, | | 8259 | bwi_setup_tx_desc32(struct bwi_softc *sc, struct bwi_ring_data *rd, |
8260 | int buf_idx, bus_addr_t paddr, int buf_len) | | 8260 | int buf_idx, bus_addr_t paddr, int buf_len) |
8261 | { | | 8261 | { |
8262 | KASSERT(buf_idx < BWI_TX_NDESC); | | 8262 | KASSERT(buf_idx < BWI_TX_NDESC); |
8263 | bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx, | | 8263 | bwi_setup_desc32(sc, rd->rdata_desc, BWI_TX_NDESC, buf_idx, |
8264 | paddr, buf_len, 1); | | 8264 | paddr, buf_len, 1); |
8265 | } | | 8265 | } |
8266 | static int | | 8266 | static int |
8267 | bwi_init_tx_ring64(struct bwi_softc *sc, int ring_idx) | | 8267 | bwi_init_tx_ring64(struct bwi_softc *sc, int ring_idx) |
8268 | { | | 8268 | { |
8269 | /* TODO: 64 */ | | 8269 | /* TODO: 64 */ |
8270 | return (EOPNOTSUPP); | | 8270 | return (EOPNOTSUPP); |
8271 | } | | 8271 | } |
8272 | | | 8272 | |
8273 | static int | | 8273 | static int |
8274 | bwi_init_rx_ring64(struct bwi_softc *sc) | | 8274 | bwi_init_rx_ring64(struct bwi_softc *sc) |
8275 | { | | 8275 | { |
8276 | /* TODO: 64 */ | | 8276 | /* TODO: 64 */ |
8277 | return (EOPNOTSUPP); | | 8277 | return (EOPNOTSUPP); |
8278 | } | | 8278 | } |
8279 | | | 8279 | |
8280 | static int | | 8280 | static int |
8281 | bwi_init_txstats64(struct bwi_softc *sc) | | 8281 | bwi_init_txstats64(struct bwi_softc *sc) |
8282 | { | | 8282 | { |
8283 | /* TODO: 64 */ | | 8283 | /* TODO: 64 */ |
8284 | return (EOPNOTSUPP); | | 8284 | return (EOPNOTSUPP); |
8285 | } | | 8285 | } |
8286 | | | 8286 | |
8287 | static void | | 8287 | static void |
8288 | bwi_setup_rx_desc64(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, | | 8288 | bwi_setup_rx_desc64(struct bwi_softc *sc, int buf_idx, bus_addr_t paddr, |
8289 | int buf_len) | | 8289 | int buf_len) |
8290 | { | | 8290 | { |
8291 | /* TODO: 64 */ | | 8291 | /* TODO: 64 */ |
8292 | } | | 8292 | } |
8293 | | | 8293 | |
8294 | static void | | 8294 | static void |
8295 | bwi_setup_tx_desc64(struct bwi_softc *sc, struct bwi_ring_data *rd, | | 8295 | bwi_setup_tx_desc64(struct bwi_softc *sc, struct bwi_ring_data *rd, |
8296 | int buf_idx, bus_addr_t paddr, int buf_len) | | 8296 | int buf_idx, bus_addr_t paddr, int buf_len) |
8297 | { | | 8297 | { |
8298 | /* TODO: 64 */ | | 8298 | /* TODO: 64 */ |
8299 | } | | 8299 | } |
8300 | | | 8300 | |
8301 | static int | | 8301 | static int |
8302 | bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init) | | 8302 | bwi_newbuf(struct bwi_softc *sc, int buf_idx, int init) |
8303 | { | | 8303 | { |
8304 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | | 8304 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
8305 | struct bwi_rxbuf *rxbuf = &rbd->rbd_buf[buf_idx]; | | 8305 | struct bwi_rxbuf *rxbuf = &rbd->rbd_buf[buf_idx]; |
8306 | struct bwi_rxbuf_hdr *hdr; | | 8306 | struct bwi_rxbuf_hdr *hdr; |
8307 | bus_dmamap_t map; | | 8307 | bus_dmamap_t map; |
8308 | bus_addr_t paddr; | | 8308 | bus_addr_t paddr; |
8309 | struct mbuf *m; | | 8309 | struct mbuf *m; |
8310 | int error; | | 8310 | int error; |
8311 | | | 8311 | |
8312 | KASSERT(buf_idx < BWI_RX_NDESC); | | 8312 | KASSERT(buf_idx < BWI_RX_NDESC); |
8313 | | | 8313 | |
8314 | MGETHDR(m, init ? M_WAITOK : M_DONTWAIT, MT_DATA); | | 8314 | MGETHDR(m, init ? M_WAITOK : M_DONTWAIT, MT_DATA); |
8315 | if (m == NULL) | | 8315 | if (m == NULL) |
8316 | return (ENOBUFS); | | 8316 | return (ENOBUFS); |
8317 | MCLGET(m, init ? M_WAITOK : M_DONTWAIT); | | 8317 | MCLGET(m, init ? M_WAITOK : M_DONTWAIT); |
8318 | if (m == NULL) { | | 8318 | if ((m->m_flags & M_EXT) == 0) { |
8319 | error = ENOBUFS; | | 8319 | error = ENOBUFS; |
8320 | | | 8320 | |
8321 | /* | | 8321 | /* |
8322 | * If the NIC is up and running, we need to: | | 8322 | * If the NIC is up and running, we need to: |
8323 | * - Clear RX buffer's header. | | 8323 | * - Clear RX buffer's header. |
8324 | * - Restore RX descriptor settings. | | 8324 | * - Restore RX descriptor settings. |
8325 | */ | | 8325 | */ |
8326 | if (init) | | 8326 | if (init) |
8327 | return error; | | 8327 | return error; |
8328 | else | | 8328 | else |
8329 | goto back; | | 8329 | goto back; |
8330 | } | | 8330 | } |
8331 | m->m_len = m->m_pkthdr.len = MCLBYTES; | | 8331 | m->m_len = m->m_pkthdr.len = MCLBYTES; |
8332 | | | 8332 | |
8333 | /* | | 8333 | /* |
8334 | * Try to load RX buf into temporary DMA map | | 8334 | * Try to load RX buf into temporary DMA map |
8335 | */ | | 8335 | */ |
8336 | error = bus_dmamap_load_mbuf(sc->sc_dmat, rbd->rbd_tmp_dmap, m, | | 8336 | error = bus_dmamap_load_mbuf(sc->sc_dmat, rbd->rbd_tmp_dmap, m, |
8337 | init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); | | 8337 | init ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); |
8338 | if (error) { | | 8338 | if (error) { |
8339 | m_freem(m); | | 8339 | m_freem(m); |
8340 | | | 8340 | |
8341 | /* | | 8341 | /* |
8342 | * See the comment above | | 8342 | * See the comment above |
8343 | */ | | 8343 | */ |
8344 | if (init) | | 8344 | if (init) |
8345 | return error; | | 8345 | return error; |
8346 | else | | 8346 | else |
8347 | goto back; | | 8347 | goto back; |
8348 | } | | 8348 | } |
8349 | | | 8349 | |
8350 | if (!init) | | 8350 | if (!init) |
8351 | bus_dmamap_unload(sc->sc_dmat, rxbuf->rb_dmap); | | 8351 | bus_dmamap_unload(sc->sc_dmat, rxbuf->rb_dmap); |
8352 | rxbuf->rb_mbuf = m; | | 8352 | rxbuf->rb_mbuf = m; |
8353 | | | 8353 | |
8354 | /* | | 8354 | /* |
8355 | * Swap RX buf's DMA map with the loaded temporary one | | 8355 | * Swap RX buf's DMA map with the loaded temporary one |
8356 | */ | | 8356 | */ |
8357 | map = rxbuf->rb_dmap; | | 8357 | map = rxbuf->rb_dmap; |
8358 | rxbuf->rb_dmap = rbd->rbd_tmp_dmap; | | 8358 | rxbuf->rb_dmap = rbd->rbd_tmp_dmap; |
8359 | rbd->rbd_tmp_dmap = map; | | 8359 | rbd->rbd_tmp_dmap = map; |
8360 | paddr = rxbuf->rb_dmap->dm_segs[0].ds_addr; | | 8360 | paddr = rxbuf->rb_dmap->dm_segs[0].ds_addr; |
8361 | rxbuf->rb_paddr = paddr; | | 8361 | rxbuf->rb_paddr = paddr; |
8362 | | | 8362 | |
8363 | back: | | 8363 | back: |
8364 | /* | | 8364 | /* |
8365 | * Clear RX buf header | | 8365 | * Clear RX buf header |
8366 | */ | | 8366 | */ |
8367 | hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *); | | 8367 | hdr = mtod(rxbuf->rb_mbuf, struct bwi_rxbuf_hdr *); |
8368 | memset(hdr, 0, sizeof(*hdr)); | | 8368 | memset(hdr, 0, sizeof(*hdr)); |
8369 | bus_dmamap_sync(sc->sc_dmat, rxbuf->rb_dmap, 0, | | 8369 | bus_dmamap_sync(sc->sc_dmat, rxbuf->rb_dmap, 0, |
8370 | rxbuf->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 8370 | rxbuf->rb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
8371 | | | 8371 | |
8372 | /* | | 8372 | /* |
8373 | * Setup RX buf descriptor | | 8373 | * Setup RX buf descriptor |
8374 | */ | | 8374 | */ |
8375 | (sc->sc_setup_rxdesc)(sc, buf_idx, rxbuf->rb_paddr, | | 8375 | (sc->sc_setup_rxdesc)(sc, buf_idx, rxbuf->rb_paddr, |
8376 | rxbuf->rb_mbuf->m_len - sizeof(*hdr)); | | 8376 | rxbuf->rb_mbuf->m_len - sizeof(*hdr)); |
8377 | return error; | | 8377 | return error; |
8378 | } | | 8378 | } |
8379 | | | 8379 | |
8380 | static void | | 8380 | static void |
8381 | bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs, | | 8381 | bwi_set_addr_filter(struct bwi_softc *sc, uint16_t addr_ofs, |
8382 | const uint8_t *addr) | | 8382 | const uint8_t *addr) |
8383 | { | | 8383 | { |
8384 | int i; | | 8384 | int i; |
8385 | | | 8385 | |
8386 | CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL, | | 8386 | CSR_WRITE_2(sc, BWI_ADDR_FILTER_CTRL, |
8387 | BWI_ADDR_FILTER_CTRL_SET | addr_ofs); | | 8387 | BWI_ADDR_FILTER_CTRL_SET | addr_ofs); |
8388 | | | 8388 | |
8389 | for (i = 0; i < (IEEE80211_ADDR_LEN / 2); ++i) { | | 8389 | for (i = 0; i < (IEEE80211_ADDR_LEN / 2); ++i) { |
8390 | uint16_t addr_val; | | 8390 | uint16_t addr_val; |
8391 | | | 8391 | |
8392 | addr_val = (uint16_t)addr[i * 2] | | | 8392 | addr_val = (uint16_t)addr[i * 2] | |
8393 | (((uint16_t)addr[(i * 2) + 1]) << 8); | | 8393 | (((uint16_t)addr[(i * 2) + 1]) << 8); |
8394 | CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val); | | 8394 | CSR_WRITE_2(sc, BWI_ADDR_FILTER_DATA, addr_val); |
8395 | } | | 8395 | } |
8396 | } | | 8396 | } |
8397 | | | 8397 | |
8398 | static int | | 8398 | static int |
8399 | bwi_set_chan(struct bwi_softc *sc, struct ieee80211_channel *c) | | 8399 | bwi_set_chan(struct bwi_softc *sc, struct ieee80211_channel *c) |
8400 | { | | 8400 | { |
8401 | struct ieee80211com *ic = &sc->sc_ic; | | 8401 | struct ieee80211com *ic = &sc->sc_ic; |
8402 | struct bwi_mac *mac; | | 8402 | struct bwi_mac *mac; |
8403 | /* uint16_t flags; */ /* [TRC: XXX See below.] */ | | 8403 | /* uint16_t flags; */ /* [TRC: XXX See below.] */ |
8404 | uint chan; | | 8404 | uint chan; |
8405 | | | 8405 | |
8406 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); | | 8406 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); |
8407 | mac = (struct bwi_mac *)sc->sc_cur_regwin; | | 8407 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
8408 | | | 8408 | |
8409 | chan = ieee80211_chan2ieee(ic, c); | | 8409 | chan = ieee80211_chan2ieee(ic, c); |
8410 | | | 8410 | |
8411 | bwi_rf_set_chan(mac, chan, 0); | | 8411 | bwi_rf_set_chan(mac, chan, 0); |
8412 | | | 8412 | |
8413 | /* [TRC: XXX DragonFlyBSD sets up radio tap channel frequency | | 8413 | /* [TRC: XXX DragonFlyBSD sets up radio tap channel frequency |
8414 | and flags here. OpenBSD does not, and appears to do so | | 8414 | and flags here. OpenBSD does not, and appears to do so |
8415 | later (in bwi_rxeof and bwi_encap).] */ | | 8415 | later (in bwi_rxeof and bwi_encap).] */ |
8416 | | | 8416 | |
8417 | return (0); | | 8417 | return (0); |
8418 | } | | 8418 | } |
8419 | | | 8419 | |
8420 | static void | | 8420 | static void |
8421 | bwi_next_scan(void *xsc) | | 8421 | bwi_next_scan(void *xsc) |
8422 | { | | 8422 | { |
8423 | struct bwi_softc *sc = xsc; | | 8423 | struct bwi_softc *sc = xsc; |
8424 | struct ieee80211com *ic = &sc->sc_ic; | | 8424 | struct ieee80211com *ic = &sc->sc_ic; |
8425 | int s; | | 8425 | int s; |
8426 | | | 8426 | |
8427 | s = splnet(); | | 8427 | s = splnet(); |
8428 | | | 8428 | |
8429 | if (ic->ic_state == IEEE80211_S_SCAN) | | 8429 | if (ic->ic_state == IEEE80211_S_SCAN) |
8430 | ieee80211_next_scan(ic); | | 8430 | ieee80211_next_scan(ic); |
8431 | | | 8431 | |
8432 | splx(s); | | 8432 | splx(s); |
8433 | } | | 8433 | } |
8434 | | | 8434 | |
8435 | static int | | 8435 | static int |
8436 | bwi_rxeof(struct bwi_softc *sc, int end_idx) | | 8436 | bwi_rxeof(struct bwi_softc *sc, int end_idx) |
8437 | { | | 8437 | { |
8438 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; | | 8438 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
8439 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | | 8439 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
8440 | struct ieee80211com *ic = &sc->sc_ic; | | 8440 | struct ieee80211com *ic = &sc->sc_ic; |
8441 | struct ifnet *ifp = &sc->sc_if; | | 8441 | struct ifnet *ifp = &sc->sc_if; |
8442 | int idx, rx_data = 0; | | 8442 | int idx, rx_data = 0; |
8443 | | | 8443 | |
8444 | idx = rbd->rbd_idx; | | 8444 | idx = rbd->rbd_idx; |
8445 | while (idx != end_idx) { | | 8445 | while (idx != end_idx) { |
8446 | struct bwi_rxbuf *rb = &rbd->rbd_buf[idx]; | | 8446 | struct bwi_rxbuf *rb = &rbd->rbd_buf[idx]; |
8447 | struct bwi_rxbuf_hdr *hdr; | | 8447 | struct bwi_rxbuf_hdr *hdr; |
8448 | struct ieee80211_frame_min *wh; | | 8448 | struct ieee80211_frame_min *wh; |
8449 | struct ieee80211_node *ni; | | 8449 | struct ieee80211_node *ni; |
8450 | struct mbuf *m; | | 8450 | struct mbuf *m; |
8451 | const void *plcp; | | 8451 | const void *plcp; |
8452 | uint16_t flags2; | | 8452 | uint16_t flags2; |
8453 | int buflen, wh_ofs, hdr_extra, rssi, type, rate; | | 8453 | int buflen, wh_ofs, hdr_extra, rssi, type, rate; |
8454 | | | 8454 | |
8455 | m = rb->rb_mbuf; | | 8455 | m = rb->rb_mbuf; |
8456 | bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0, | | 8456 | bus_dmamap_sync(sc->sc_dmat, rb->rb_dmap, 0, |
8457 | rb->rb_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD); | | 8457 | rb->rb_dmap->dm_mapsize, BUS_DMASYNC_POSTREAD); |
8458 | | | 8458 | |
8459 | if (bwi_newbuf(sc, idx, 0)) { | | 8459 | if (bwi_newbuf(sc, idx, 0)) { |
8460 | ifp->if_ierrors++; | | 8460 | ifp->if_ierrors++; |
8461 | goto next; | | 8461 | goto next; |
8462 | } | | 8462 | } |
8463 | | | 8463 | |
8464 | hdr = mtod(m, struct bwi_rxbuf_hdr *); | | 8464 | hdr = mtod(m, struct bwi_rxbuf_hdr *); |
8465 | flags2 = le16toh(hdr->rxh_flags2); | | 8465 | flags2 = le16toh(hdr->rxh_flags2); |
8466 | | | 8466 | |
8467 | hdr_extra = 0; | | 8467 | hdr_extra = 0; |
8468 | if (flags2 & BWI_RXH_F2_TYPE2FRAME) | | 8468 | if (flags2 & BWI_RXH_F2_TYPE2FRAME) |
8469 | hdr_extra = 2; | | 8469 | hdr_extra = 2; |
8470 | wh_ofs = hdr_extra + 6; /* XXX magic number */ | | 8470 | wh_ofs = hdr_extra + 6; /* XXX magic number */ |
8471 | | | 8471 | |
8472 | buflen = le16toh(hdr->rxh_buflen); | | 8472 | buflen = le16toh(hdr->rxh_buflen); |
8473 | if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) { | | 8473 | if (buflen < BWI_FRAME_MIN_LEN(wh_ofs)) { |
8474 | aprint_error_dev(sc->sc_dev, "short frame %d," | | 8474 | aprint_error_dev(sc->sc_dev, "short frame %d," |
8475 | " hdr_extra %d\n", buflen, hdr_extra); | | 8475 | " hdr_extra %d\n", buflen, hdr_extra); |
8476 | ifp->if_ierrors++; | | 8476 | ifp->if_ierrors++; |
8477 | m_freem(m); | | 8477 | m_freem(m); |
8478 | goto next; | | 8478 | goto next; |
8479 | } | | 8479 | } |
8480 | | | 8480 | |
8481 | plcp = ((const uint8_t *)(hdr + 1) + hdr_extra); | | 8481 | plcp = ((const uint8_t *)(hdr + 1) + hdr_extra); |
8482 | rssi = bwi_calc_rssi(sc, hdr); | | 8482 | rssi = bwi_calc_rssi(sc, hdr); |
8483 | | | 8483 | |
8484 | m->m_pkthdr.rcvif = ifp; | | 8484 | m->m_pkthdr.rcvif = ifp; |
8485 | m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr); | | 8485 | m->m_len = m->m_pkthdr.len = buflen + sizeof(*hdr); |
8486 | m_adj(m, sizeof(*hdr) + wh_ofs); | | 8486 | m_adj(m, sizeof(*hdr) + wh_ofs); |
8487 | | | 8487 | |
8488 | if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM) | | 8488 | if (htole16(hdr->rxh_flags1) & BWI_RXH_F1_OFDM) |
8489 | rate = bwi_ofdm_plcp2rate(plcp); | | 8489 | rate = bwi_ofdm_plcp2rate(plcp); |
8490 | else | | 8490 | else |
8491 | rate = bwi_ds_plcp2rate(plcp); | | 8491 | rate = bwi_ds_plcp2rate(plcp); |
8492 | | | 8492 | |
8493 | /* RX radio tap */ | | 8493 | /* RX radio tap */ |
8494 | if (sc->sc_drvbpf != NULL) { | | 8494 | if (sc->sc_drvbpf != NULL) { |
8495 | struct mbuf mb; | | 8495 | struct mbuf mb; |
8496 | struct bwi_rx_radiotap_hdr *tap = &sc->sc_rxtap; | | 8496 | struct bwi_rx_radiotap_hdr *tap = &sc->sc_rxtap; |
8497 | | | 8497 | |
8498 | tap->wr_tsf = hdr->rxh_tsf; | | 8498 | tap->wr_tsf = hdr->rxh_tsf; |
8499 | tap->wr_flags = 0; | | 8499 | tap->wr_flags = 0; |
8500 | tap->wr_rate = rate; | | 8500 | tap->wr_rate = rate; |
8501 | tap->wr_chan_freq = | | 8501 | tap->wr_chan_freq = |
8502 | htole16(ic->ic_bss->ni_chan->ic_freq); | | 8502 | htole16(ic->ic_bss->ni_chan->ic_freq); |
8503 | tap->wr_chan_flags = | | 8503 | tap->wr_chan_flags = |
8504 | htole16(ic->ic_bss->ni_chan->ic_flags); | | 8504 | htole16(ic->ic_bss->ni_chan->ic_flags); |
8505 | tap->wr_antsignal = rssi; | | 8505 | tap->wr_antsignal = rssi; |
8506 | tap->wr_antnoise = BWI_NOISE_FLOOR; | | 8506 | tap->wr_antnoise = BWI_NOISE_FLOOR; |
8507 | | | 8507 | |
8508 | mb.m_data = (void *)tap; | | 8508 | mb.m_data = (void *)tap; |
8509 | mb.m_len = sc->sc_rxtap_len; | | 8509 | mb.m_len = sc->sc_rxtap_len; |
8510 | mb.m_next = m; | | 8510 | mb.m_next = m; |
8511 | mb.m_nextpkt = NULL; | | 8511 | mb.m_nextpkt = NULL; |
8512 | mb.m_type = 0; | | 8512 | mb.m_type = 0; |
8513 | mb.m_flags = 0; | | 8513 | mb.m_flags = 0; |
8514 | bpf_mtap3(sc->sc_drvbpf, &mb); | | 8514 | bpf_mtap3(sc->sc_drvbpf, &mb); |
8515 | } | | 8515 | } |
8516 | | | 8516 | |
8517 | m_adj(m, -IEEE80211_CRC_LEN); | | 8517 | m_adj(m, -IEEE80211_CRC_LEN); |
8518 | | | 8518 | |
8519 | wh = mtod(m, struct ieee80211_frame_min *); | | 8519 | wh = mtod(m, struct ieee80211_frame_min *); |
8520 | ni = ieee80211_find_rxnode(ic, wh); | | 8520 | ni = ieee80211_find_rxnode(ic, wh); |
8521 | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; | | 8521 | type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; |
8522 | | | 8522 | |
8523 | ieee80211_input(ic, m, ni, hdr->rxh_rssi, | | 8523 | ieee80211_input(ic, m, ni, hdr->rxh_rssi, |
8524 | le16toh(hdr->rxh_tsf)); | | 8524 | le16toh(hdr->rxh_tsf)); |
8525 | | | 8525 | |
8526 | ieee80211_free_node(ni); | | 8526 | ieee80211_free_node(ni); |
8527 | | | 8527 | |
8528 | if (type == IEEE80211_FC0_TYPE_DATA) { | | 8528 | if (type == IEEE80211_FC0_TYPE_DATA) { |
8529 | rx_data = 1; | | 8529 | rx_data = 1; |
8530 | sc->sc_rx_rate = rate; | | 8530 | sc->sc_rx_rate = rate; |
8531 | } | | 8531 | } |
8532 | next: | | 8532 | next: |
8533 | idx = (idx + 1) % BWI_RX_NDESC; | | 8533 | idx = (idx + 1) % BWI_RX_NDESC; |
8534 | } | | 8534 | } |
8535 | | | 8535 | |
8536 | rbd->rbd_idx = idx; | | 8536 | rbd->rbd_idx = idx; |
8537 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, | | 8537 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, |
8538 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 8538 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
8539 | | | 8539 | |
8540 | return (rx_data); | | 8540 | return (rx_data); |
8541 | } | | 8541 | } |
8542 | | | 8542 | |
8543 | static int | | 8543 | static int |
8544 | bwi_rxeof32(struct bwi_softc *sc) | | 8544 | bwi_rxeof32(struct bwi_softc *sc) |
8545 | { | | 8545 | { |
8546 | uint32_t val, rx_ctrl; | | 8546 | uint32_t val, rx_ctrl; |
8547 | int end_idx, rx_data; | | 8547 | int end_idx, rx_data; |
8548 | | | 8548 | |
8549 | rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl; | | 8549 | rx_ctrl = sc->sc_rx_rdata.rdata_txrx_ctrl; |
8550 | | | 8550 | |
8551 | val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS); | | 8551 | val = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS); |
8552 | end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / | | 8552 | end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / |
8553 | sizeof(struct bwi_desc32); | | 8553 | sizeof(struct bwi_desc32); |
8554 | | | 8554 | |
8555 | rx_data = bwi_rxeof(sc, end_idx); | | 8555 | rx_data = bwi_rxeof(sc, end_idx); |
8556 | | | 8556 | |
8557 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX, | | 8557 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX, |
8558 | end_idx * sizeof(struct bwi_desc32)); | | 8558 | end_idx * sizeof(struct bwi_desc32)); |
8559 | | | 8559 | |
8560 | return (rx_data); | | 8560 | return (rx_data); |
8561 | } | | 8561 | } |
8562 | | | 8562 | |
8563 | static int | | 8563 | static int |
8564 | bwi_rxeof64(struct bwi_softc *sc) | | 8564 | bwi_rxeof64(struct bwi_softc *sc) |
8565 | { | | 8565 | { |
8566 | /* TODO: 64 */ | | 8566 | /* TODO: 64 */ |
8567 | return (0); | | 8567 | return (0); |
8568 | } | | 8568 | } |
8569 | | | 8569 | |
8570 | static void | | 8570 | static void |
8571 | bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl) | | 8571 | bwi_reset_rx_ring32(struct bwi_softc *sc, uint32_t rx_ctrl) |
8572 | { | | 8572 | { |
8573 | int i; | | 8573 | int i; |
8574 | | | 8574 | |
8575 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0); | | 8575 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_CTRL, 0); |
8576 | | | 8576 | |
8577 | #define NRETRY 10 | | 8577 | #define NRETRY 10 |
8578 | for (i = 0; i < NRETRY; ++i) { | | 8578 | for (i = 0; i < NRETRY; ++i) { |
8579 | uint32_t status; | | 8579 | uint32_t status; |
8580 | | | 8580 | |
8581 | status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS); | | 8581 | status = CSR_READ_4(sc, rx_ctrl + BWI_RX32_STATUS); |
8582 | if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK) == | | 8582 | if (__SHIFTOUT(status, BWI_RX32_STATUS_STATE_MASK) == |
8583 | BWI_RX32_STATUS_STATE_DISABLED) | | 8583 | BWI_RX32_STATUS_STATE_DISABLED) |
8584 | break; | | 8584 | break; |
8585 | | | 8585 | |
8586 | DELAY(1000); | | 8586 | DELAY(1000); |
8587 | } | | 8587 | } |
8588 | if (i == NRETRY) | | 8588 | if (i == NRETRY) |
8589 | aprint_error_dev(sc->sc_dev, "reset rx ring timedout\n"); | | 8589 | aprint_error_dev(sc->sc_dev, "reset rx ring timedout\n"); |
8590 | #undef NRETRY | | 8590 | #undef NRETRY |
8591 | | | 8591 | |
8592 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0); | | 8592 | CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_RINGINFO, 0); |
8593 | } | | 8593 | } |
8594 | | | 8594 | |
8595 | static void | | 8595 | static void |
8596 | bwi_free_txstats32(struct bwi_softc *sc) | | 8596 | bwi_free_txstats32(struct bwi_softc *sc) |
8597 | { | | 8597 | { |
8598 | bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base); | | 8598 | bwi_reset_rx_ring32(sc, sc->sc_txstats->stats_ctrl_base); |
8599 | } | | 8599 | } |
8600 | | | 8600 | |
8601 | static void | | 8601 | static void |
8602 | bwi_free_rx_ring32(struct bwi_softc *sc) | | 8602 | bwi_free_rx_ring32(struct bwi_softc *sc) |
8603 | { | | 8603 | { |
8604 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; | | 8604 | struct bwi_ring_data *rd = &sc->sc_rx_rdata; |
8605 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; | | 8605 | struct bwi_rxbuf_data *rbd = &sc->sc_rx_bdata; |
8606 | int i; | | 8606 | int i; |
8607 | | | 8607 | |
8608 | bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl); | | 8608 | bwi_reset_rx_ring32(sc, rd->rdata_txrx_ctrl); |
8609 | | | 8609 | |
8610 | for (i = 0; i < BWI_RX_NDESC; ++i) { | | 8610 | for (i = 0; i < BWI_RX_NDESC; ++i) { |
8611 | struct bwi_rxbuf *rb = &rbd->rbd_buf[i]; | | 8611 | struct bwi_rxbuf *rb = &rbd->rbd_buf[i]; |
8612 | | | 8612 | |
8613 | if (rb->rb_mbuf != NULL) { | | 8613 | if (rb->rb_mbuf != NULL) { |
8614 | bus_dmamap_unload(sc->sc_dmat, rb->rb_dmap); | | 8614 | bus_dmamap_unload(sc->sc_dmat, rb->rb_dmap); |
8615 | m_freem(rb->rb_mbuf); | | 8615 | m_freem(rb->rb_mbuf); |
8616 | rb->rb_mbuf = NULL; | | 8616 | rb->rb_mbuf = NULL; |
8617 | } | | 8617 | } |
8618 | } | | 8618 | } |
8619 | } | | 8619 | } |
8620 | | | 8620 | |
8621 | static void | | 8621 | static void |
8622 | bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx) | | 8622 | bwi_free_tx_ring32(struct bwi_softc *sc, int ring_idx) |
8623 | { | | 8623 | { |
8624 | struct bwi_ring_data *rd; | | 8624 | struct bwi_ring_data *rd; |
8625 | struct bwi_txbuf_data *tbd; | | 8625 | struct bwi_txbuf_data *tbd; |
8626 | uint32_t state, val; | | 8626 | uint32_t state, val; |
8627 | int i; | | 8627 | int i; |
8628 | | | 8628 | |
8629 | KASSERT(ring_idx < BWI_TX_NRING); | | 8629 | KASSERT(ring_idx < BWI_TX_NRING); |
8630 | rd = &sc->sc_tx_rdata[ring_idx]; | | 8630 | rd = &sc->sc_tx_rdata[ring_idx]; |
8631 | tbd = &sc->sc_tx_bdata[ring_idx]; | | 8631 | tbd = &sc->sc_tx_bdata[ring_idx]; |
8632 | | | 8632 | |
8633 | #define NRETRY 10 | | 8633 | #define NRETRY 10 |
8634 | for (i = 0; i < NRETRY; ++i) { | | 8634 | for (i = 0; i < NRETRY; ++i) { |
8635 | val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS); | | 8635 | val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS); |
8636 | state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK); | | 8636 | state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK); |
8637 | if (state == BWI_TX32_STATUS_STATE_DISABLED || | | 8637 | if (state == BWI_TX32_STATUS_STATE_DISABLED || |
8638 | state == BWI_TX32_STATUS_STATE_IDLE || | | 8638 | state == BWI_TX32_STATUS_STATE_IDLE || |
8639 | state == BWI_TX32_STATUS_STATE_STOPPED) | | 8639 | state == BWI_TX32_STATUS_STATE_STOPPED) |
8640 | break; | | 8640 | break; |
8641 | | | 8641 | |
8642 | DELAY(1000); | | 8642 | DELAY(1000); |
8643 | } | | 8643 | } |
8644 | if (i == NRETRY) | | 8644 | if (i == NRETRY) |
8645 | aprint_error_dev(sc->sc_dev, | | 8645 | aprint_error_dev(sc->sc_dev, |
8646 | "wait for TX ring(%d) stable timed out\n", ring_idx); | | 8646 | "wait for TX ring(%d) stable timed out\n", ring_idx); |
8647 | | | 8647 | |
8648 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0); | | 8648 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_CTRL, 0); |
8649 | for (i = 0; i < NRETRY; ++i) { | | 8649 | for (i = 0; i < NRETRY; ++i) { |
8650 | val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS); | | 8650 | val = CSR_READ_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_STATUS); |
8651 | state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK); | | 8651 | state = __SHIFTOUT(val, BWI_TX32_STATUS_STATE_MASK); |
8652 | if (state == BWI_TX32_STATUS_STATE_DISABLED) | | 8652 | if (state == BWI_TX32_STATUS_STATE_DISABLED) |
8653 | break; | | 8653 | break; |
8654 | | | 8654 | |
8655 | DELAY(1000); | | 8655 | DELAY(1000); |
8656 | } | | 8656 | } |
8657 | if (i == NRETRY) | | 8657 | if (i == NRETRY) |
8658 | aprint_error_dev(sc->sc_dev, "reset TX ring (%d) timed out\n", | | 8658 | aprint_error_dev(sc->sc_dev, "reset TX ring (%d) timed out\n", |
8659 | ring_idx); | | 8659 | ring_idx); |
8660 | #undef NRETRY | | 8660 | #undef NRETRY |
8661 | | | 8661 | |
8662 | DELAY(1000); | | 8662 | DELAY(1000); |
8663 | | | 8663 | |
8664 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0); | | 8664 | CSR_WRITE_4(sc, rd->rdata_txrx_ctrl + BWI_TX32_RINGINFO, 0); |
8665 | | | 8665 | |
8666 | for (i = 0; i < BWI_TX_NDESC; ++i) { | | 8666 | for (i = 0; i < BWI_TX_NDESC; ++i) { |
8667 | struct bwi_txbuf *tb = &tbd->tbd_buf[i]; | | 8667 | struct bwi_txbuf *tb = &tbd->tbd_buf[i]; |
8668 | | | 8668 | |
8669 | if (tb->tb_mbuf != NULL) { | | 8669 | if (tb->tb_mbuf != NULL) { |
8670 | bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap); | | 8670 | bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap); |
8671 | m_freem(tb->tb_mbuf); | | 8671 | m_freem(tb->tb_mbuf); |
8672 | tb->tb_mbuf = NULL; | | 8672 | tb->tb_mbuf = NULL; |
8673 | } | | 8673 | } |
8674 | if (tb->tb_ni != NULL) { | | 8674 | if (tb->tb_ni != NULL) { |
8675 | ieee80211_free_node(tb->tb_ni); | | 8675 | ieee80211_free_node(tb->tb_ni); |
8676 | tb->tb_ni = NULL; | | 8676 | tb->tb_ni = NULL; |
8677 | } | | 8677 | } |
8678 | } | | 8678 | } |
8679 | } | | 8679 | } |
8680 | | | 8680 | |
8681 | static void | | 8681 | static void |
8682 | bwi_free_txstats64(struct bwi_softc *sc) | | 8682 | bwi_free_txstats64(struct bwi_softc *sc) |
8683 | { | | 8683 | { |
8684 | /* TODO: 64 */ | | 8684 | /* TODO: 64 */ |
8685 | } | | 8685 | } |
8686 | | | 8686 | |
8687 | static void | | 8687 | static void |
8688 | bwi_free_rx_ring64(struct bwi_softc *sc) | | 8688 | bwi_free_rx_ring64(struct bwi_softc *sc) |
8689 | { | | 8689 | { |
8690 | /* TODO: 64 */ | | 8690 | /* TODO: 64 */ |
8691 | } | | 8691 | } |
8692 | | | 8692 | |
8693 | static void | | 8693 | static void |
8694 | bwi_free_tx_ring64(struct bwi_softc *sc, int ring_idx) | | 8694 | bwi_free_tx_ring64(struct bwi_softc *sc, int ring_idx) |
8695 | { | | 8695 | { |
8696 | /* TODO: 64 */ | | 8696 | /* TODO: 64 */ |
8697 | } | | 8697 | } |
8698 | | | 8698 | |
8699 | /* XXX does not belong here */ | | 8699 | /* XXX does not belong here */ |
8700 | /* [TRC: Begin pilferage from OpenBSD.] */ | | 8700 | /* [TRC: Begin pilferage from OpenBSD.] */ |
8701 | | | 8701 | |
8702 | /* | | 8702 | /* |
8703 | * Convert bit rate (in 0.5Mbps units) to PLCP signal (R4-R1) and vice versa. | | 8703 | * Convert bit rate (in 0.5Mbps units) to PLCP signal (R4-R1) and vice versa. |
8704 | */ | | 8704 | */ |
8705 | uint8_t | | 8705 | uint8_t |
8706 | bwi_ieee80211_rate2plcp(u_int8_t rate, enum ieee80211_phymode mode) | | 8706 | bwi_ieee80211_rate2plcp(u_int8_t rate, enum ieee80211_phymode mode) |
8707 | { | | 8707 | { |
8708 | rate &= IEEE80211_RATE_VAL; | | 8708 | rate &= IEEE80211_RATE_VAL; |
8709 | | | 8709 | |
8710 | if (mode == IEEE80211_MODE_11B) { | | 8710 | if (mode == IEEE80211_MODE_11B) { |
8711 | /* IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3 */ | | 8711 | /* IEEE Std 802.11b-1999 page 15, subclause 18.2.3.3 */ |
8712 | switch (rate) { | | 8712 | switch (rate) { |
8713 | case 2: return 10; | | 8713 | case 2: return 10; |
8714 | case 4: return 20; | | 8714 | case 4: return 20; |
8715 | case 11: return 55; | | 8715 | case 11: return 55; |
8716 | case 22: return 110; | | 8716 | case 22: return 110; |
8717 | /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */ | | 8717 | /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */ |
8718 | case 44: return 220; | | 8718 | case 44: return 220; |
8719 | } | | 8719 | } |
8720 | } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) { | | 8720 | } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) { |
8721 | /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */ | | 8721 | /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */ |
8722 | switch (rate) { | | 8722 | switch (rate) { |
8723 | case 12: return 0x0b; | | 8723 | case 12: return 0x0b; |
8724 | case 18: return 0x0f; | | 8724 | case 18: return 0x0f; |
8725 | case 24: return 0x0a; | | 8725 | case 24: return 0x0a; |
8726 | case 36: return 0x0e; | | 8726 | case 36: return 0x0e; |
8727 | case 48: return 0x09; | | 8727 | case 48: return 0x09; |
8728 | case 72: return 0x0d; | | 8728 | case 72: return 0x0d; |
8729 | case 96: return 0x08; | | 8729 | case 96: return 0x08; |
8730 | case 108: return 0x0c; | | 8730 | case 108: return 0x0c; |
8731 | } | | 8731 | } |
8732 | } else | | 8732 | } else |
8733 | panic("Unexpected mode %u", mode); | | 8733 | panic("Unexpected mode %u", mode); |
8734 | | | 8734 | |
8735 | return 0; | | 8735 | return 0; |
8736 | } | | 8736 | } |
8737 | | | 8737 | |
8738 | static uint8_t | | 8738 | static uint8_t |
8739 | bwi_ieee80211_plcp2rate(uint8_t plcp, enum ieee80211_phymode mode) | | 8739 | bwi_ieee80211_plcp2rate(uint8_t plcp, enum ieee80211_phymode mode) |
8740 | { | | 8740 | { |
8741 | if (mode == IEEE80211_MODE_11B) { | | 8741 | if (mode == IEEE80211_MODE_11B) { |
8742 | /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */ | | 8742 | /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */ |
8743 | switch (plcp) { | | 8743 | switch (plcp) { |
8744 | case 10: return 2; | | 8744 | case 10: return 2; |
8745 | case 20: return 4; | | 8745 | case 20: return 4; |
8746 | case 55: return 11; | | 8746 | case 55: return 11; |
8747 | case 110: return 22; | | 8747 | case 110: return 22; |
8748 | /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */ | | 8748 | /* IEEE Std 802.11g-2003 page 19, subclause 19.3.2.1 */ |
8749 | case 220: return 44; | | 8749 | case 220: return 44; |
8750 | } | | 8750 | } |
8751 | } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) { | | 8751 | } else if (mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_11A) { |
8752 | /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */ | | 8752 | /* IEEE Std 802.11a-1999 page 14, subclause 17.3.4.1 */ |
8753 | switch (plcp) { | | 8753 | switch (plcp) { |
8754 | case 0x0b: return 12; | | 8754 | case 0x0b: return 12; |
8755 | case 0x0f: return 18; | | 8755 | case 0x0f: return 18; |
8756 | case 0x0a: return 24; | | 8756 | case 0x0a: return 24; |
8757 | case 0x0e: return 36; | | 8757 | case 0x0e: return 36; |
8758 | case 0x09: return 48; | | 8758 | case 0x09: return 48; |
8759 | case 0x0d: return 72; | | 8759 | case 0x0d: return 72; |
8760 | case 0x08: return 96; | | 8760 | case 0x08: return 96; |
8761 | case 0x0c: return 108; | | 8761 | case 0x0c: return 108; |
8762 | } | | 8762 | } |
8763 | } else | | 8763 | } else |
8764 | panic("Unexpected mode %u", mode); | | 8764 | panic("Unexpected mode %u", mode); |
8765 | | | 8765 | |
8766 | return 0; | | 8766 | return 0; |
8767 | } | | 8767 | } |
8768 | /* [TRC: End pilferage from OpenBSD.] */ | | 8768 | /* [TRC: End pilferage from OpenBSD.] */ |
8769 | | | 8769 | |
8770 | static enum bwi_ieee80211_modtype | | 8770 | static enum bwi_ieee80211_modtype |
8771 | bwi_ieee80211_rate2modtype(uint8_t rate) | | 8771 | bwi_ieee80211_rate2modtype(uint8_t rate) |
8772 | { | | 8772 | { |
8773 | rate &= IEEE80211_RATE_VAL; | | 8773 | rate &= IEEE80211_RATE_VAL; |
8774 | | | 8774 | |
8775 | if (rate == 44) | | 8775 | if (rate == 44) |
8776 | return (IEEE80211_MODTYPE_PBCC); | | 8776 | return (IEEE80211_MODTYPE_PBCC); |
8777 | else if (rate == 22 || rate < 12) | | 8777 | else if (rate == 22 || rate < 12) |
8778 | return (IEEE80211_MODTYPE_DS); | | 8778 | return (IEEE80211_MODTYPE_DS); |
8779 | else | | 8779 | else |
8780 | return (IEEE80211_MODTYPE_OFDM); | | 8780 | return (IEEE80211_MODTYPE_OFDM); |
8781 | } | | 8781 | } |
8782 | | | 8782 | |
8783 | static uint8_t | | 8783 | static uint8_t |
8784 | bwi_ofdm_plcp2rate(const uint32_t *plcp0) | | 8784 | bwi_ofdm_plcp2rate(const uint32_t *plcp0) |
8785 | { | | 8785 | { |
8786 | uint32_t plcp; | | 8786 | uint32_t plcp; |
8787 | uint8_t plcp_rate; | | 8787 | uint8_t plcp_rate; |
8788 | | | 8788 | |
8789 | plcp = le32toh(*plcp0); | | 8789 | plcp = le32toh(*plcp0); |
8790 | plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK); | | 8790 | plcp_rate = __SHIFTOUT(plcp, IEEE80211_OFDM_PLCP_RATE_MASK); |
8791 | | | 8791 | |
8792 | return (bwi_ieee80211_plcp2rate(plcp_rate, IEEE80211_MODE_11G)); | | 8792 | return (bwi_ieee80211_plcp2rate(plcp_rate, IEEE80211_MODE_11G)); |
8793 | } | | 8793 | } |
8794 | | | 8794 | |
8795 | static uint8_t | | 8795 | static uint8_t |
8796 | bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr) | | 8796 | bwi_ds_plcp2rate(const struct ieee80211_ds_plcp_hdr *hdr) |
8797 | { | | 8797 | { |
8798 | return (bwi_ieee80211_plcp2rate(hdr->i_signal, IEEE80211_MODE_11B)); | | 8798 | return (bwi_ieee80211_plcp2rate(hdr->i_signal, IEEE80211_MODE_11B)); |
8799 | } | | 8799 | } |
8800 | | | 8800 | |
8801 | static void | | 8801 | static void |
8802 | bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate) | | 8802 | bwi_ofdm_plcp_header(uint32_t *plcp0, int pkt_len, uint8_t rate) |
8803 | { | | 8803 | { |
8804 | uint32_t plcp; | | 8804 | uint32_t plcp; |
8805 | | | 8805 | |
8806 | plcp = __SHIFTIN(bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11G), | | 8806 | plcp = __SHIFTIN(bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11G), |
8807 | IEEE80211_OFDM_PLCP_RATE_MASK) | | | 8807 | IEEE80211_OFDM_PLCP_RATE_MASK) | |
8808 | __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK); | | 8808 | __SHIFTIN(pkt_len, IEEE80211_OFDM_PLCP_LEN_MASK); |
8809 | *plcp0 = htole32(plcp); | | 8809 | *plcp0 = htole32(plcp); |
8810 | } | | 8810 | } |
8811 | | | 8811 | |
8812 | static void | | 8812 | static void |
8813 | bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len, | | 8813 | bwi_ds_plcp_header(struct ieee80211_ds_plcp_hdr *plcp, int pkt_len, |
8814 | uint8_t rate) | | 8814 | uint8_t rate) |
8815 | { | | 8815 | { |
8816 | int len, service, pkt_bitlen; | | 8816 | int len, service, pkt_bitlen; |
8817 | | | 8817 | |
8818 | pkt_bitlen = pkt_len * NBBY; | | 8818 | pkt_bitlen = pkt_len * NBBY; |
8819 | len = howmany(pkt_bitlen * 2, rate); | | 8819 | len = howmany(pkt_bitlen * 2, rate); |
8820 | | | 8820 | |
8821 | service = IEEE80211_DS_PLCP_SERVICE_LOCKED; | | 8821 | service = IEEE80211_DS_PLCP_SERVICE_LOCKED; |
8822 | if (rate == (11 * 2)) { | | 8822 | if (rate == (11 * 2)) { |
8823 | int pkt_bitlen1; | | 8823 | int pkt_bitlen1; |
8824 | | | 8824 | |
8825 | /* | | 8825 | /* |
8826 | * PLCP service field needs to be adjusted, | | 8826 | * PLCP service field needs to be adjusted, |
8827 | * if TX rate is 11Mbytes/s | | 8827 | * if TX rate is 11Mbytes/s |
8828 | */ | | 8828 | */ |
8829 | pkt_bitlen1 = len * 11; | | 8829 | pkt_bitlen1 = len * 11; |
8830 | if (pkt_bitlen1 - pkt_bitlen >= NBBY) | | 8830 | if (pkt_bitlen1 - pkt_bitlen >= NBBY) |
8831 | service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7; | | 8831 | service |= IEEE80211_DS_PLCP_SERVICE_LENEXT7; |
8832 | } | | 8832 | } |
8833 | | | 8833 | |
8834 | plcp->i_signal = bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11B); | | 8834 | plcp->i_signal = bwi_ieee80211_rate2plcp(rate, IEEE80211_MODE_11B); |
8835 | plcp->i_service = service; | | 8835 | plcp->i_service = service; |
8836 | plcp->i_length = htole16(len); | | 8836 | plcp->i_length = htole16(len); |
8837 | /* NOTE: do NOT touch i_crc */ | | 8837 | /* NOTE: do NOT touch i_crc */ |
8838 | } | | 8838 | } |
8839 | | | 8839 | |
8840 | static void | | 8840 | static void |
8841 | bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate) | | 8841 | bwi_plcp_header(void *plcp, int pkt_len, uint8_t rate) |
8842 | { | | 8842 | { |
8843 | enum bwi_ieee80211_modtype modtype; | | 8843 | enum bwi_ieee80211_modtype modtype; |
8844 | | | 8844 | |
8845 | /* | | 8845 | /* |
8846 | * Assume caller has zeroed 'plcp' | | 8846 | * Assume caller has zeroed 'plcp' |
8847 | */ | | 8847 | */ |
8848 | | | 8848 | |
8849 | modtype = bwi_ieee80211_rate2modtype(rate); | | 8849 | modtype = bwi_ieee80211_rate2modtype(rate); |
8850 | if (modtype == IEEE80211_MODTYPE_OFDM) | | 8850 | if (modtype == IEEE80211_MODTYPE_OFDM) |
8851 | bwi_ofdm_plcp_header(plcp, pkt_len, rate); | | 8851 | bwi_ofdm_plcp_header(plcp, pkt_len, rate); |
8852 | else if (modtype == IEEE80211_MODTYPE_DS) | | 8852 | else if (modtype == IEEE80211_MODTYPE_DS) |
8853 | bwi_ds_plcp_header(plcp, pkt_len, rate); | | 8853 | bwi_ds_plcp_header(plcp, pkt_len, rate); |
8854 | else | | 8854 | else |
8855 | panic("unsupport modulation type %u\n", modtype); | | 8855 | panic("unsupport modulation type %u\n", modtype); |
8856 | } | | 8856 | } |
8857 | | | 8857 | |
8858 | static uint8_t | | 8858 | static uint8_t |
8859 | bwi_ieee80211_ack_rate(struct ieee80211_node *ni, uint8_t rate) | | 8859 | bwi_ieee80211_ack_rate(struct ieee80211_node *ni, uint8_t rate) |
8860 | { | | 8860 | { |
8861 | const struct ieee80211_rateset *rs = &ni->ni_rates; | | 8861 | const struct ieee80211_rateset *rs = &ni->ni_rates; |
8862 | uint8_t ack_rate = 0; | | 8862 | uint8_t ack_rate = 0; |
8863 | enum bwi_ieee80211_modtype modtype; | | 8863 | enum bwi_ieee80211_modtype modtype; |
8864 | int i; | | 8864 | int i; |
8865 | | | 8865 | |
8866 | rate &= IEEE80211_RATE_VAL; | | 8866 | rate &= IEEE80211_RATE_VAL; |
8867 | | | 8867 | |
8868 | modtype = bwi_ieee80211_rate2modtype(rate); | | 8868 | modtype = bwi_ieee80211_rate2modtype(rate); |
8869 | | | 8869 | |
8870 | for (i = 0; i < rs->rs_nrates; ++i) { | | 8870 | for (i = 0; i < rs->rs_nrates; ++i) { |
8871 | uint8_t rate1 = rs->rs_rates[i] & IEEE80211_RATE_VAL; | | 8871 | uint8_t rate1 = rs->rs_rates[i] & IEEE80211_RATE_VAL; |
8872 | | | 8872 | |
8873 | if (rate1 > rate) { | | 8873 | if (rate1 > rate) { |
8874 | if (ack_rate != 0) | | 8874 | if (ack_rate != 0) |
8875 | return (ack_rate); | | 8875 | return (ack_rate); |
8876 | else | | 8876 | else |
8877 | break; | | 8877 | break; |
8878 | } | | 8878 | } |
8879 | | | 8879 | |
8880 | if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) && | | 8880 | if ((rs->rs_rates[i] & IEEE80211_RATE_BASIC) && |
8881 | bwi_ieee80211_rate2modtype(rate1) == modtype) | | 8881 | bwi_ieee80211_rate2modtype(rate1) == modtype) |
8882 | ack_rate = rate1; | | 8882 | ack_rate = rate1; |
8883 | } | | 8883 | } |
8884 | | | 8884 | |
8885 | switch (rate) { | | 8885 | switch (rate) { |
8886 | /* CCK */ | | 8886 | /* CCK */ |
8887 | case 2: | | 8887 | case 2: |
8888 | case 4: | | 8888 | case 4: |
8889 | case 11: | | 8889 | case 11: |
8890 | case 22: | | 8890 | case 22: |
8891 | ack_rate = rate; | | 8891 | ack_rate = rate; |
8892 | break; | | 8892 | break; |
8893 | /* PBCC */ | | 8893 | /* PBCC */ |
8894 | case 44: | | 8894 | case 44: |
8895 | ack_rate = 22; | | 8895 | ack_rate = 22; |
8896 | break; | | 8896 | break; |
8897 | | | 8897 | |
8898 | /* OFDM */ | | 8898 | /* OFDM */ |
8899 | case 12: | | 8899 | case 12: |
8900 | case 18: | | 8900 | case 18: |
8901 | ack_rate = 12; | | 8901 | ack_rate = 12; |
8902 | break; | | 8902 | break; |
8903 | case 24: | | 8903 | case 24: |
8904 | case 36: | | 8904 | case 36: |
8905 | ack_rate = 24; | | 8905 | ack_rate = 24; |
8906 | break; | | 8906 | break; |
8907 | case 48: | | 8907 | case 48: |
8908 | case 72: | | 8908 | case 72: |
8909 | case 96: | | 8909 | case 96: |
8910 | case 108: | | 8910 | case 108: |
8911 | ack_rate = 48; | | 8911 | ack_rate = 48; |
8912 | break; | | 8912 | break; |
8913 | default: | | 8913 | default: |
8914 | panic("unsupported rate %d\n", rate); | | 8914 | panic("unsupported rate %d\n", rate); |
8915 | } | | 8915 | } |
8916 | return (ack_rate); | | 8916 | return (ack_rate); |
8917 | } | | 8917 | } |
8918 | | | 8918 | |
8919 | /* [TRC: XXX does not belong here] */ | | 8919 | /* [TRC: XXX does not belong here] */ |
8920 | | | 8920 | |
8921 | #define IEEE80211_OFDM_TXTIME(kbps, frmlen) \ | | 8921 | #define IEEE80211_OFDM_TXTIME(kbps, frmlen) \ |
8922 | (IEEE80211_OFDM_PREAMBLE_TIME + \ | | 8922 | (IEEE80211_OFDM_PREAMBLE_TIME + \ |
8923 | IEEE80211_OFDM_SIGNAL_TIME + \ | | 8923 | IEEE80211_OFDM_SIGNAL_TIME + \ |
8924 | (IEEE80211_OFDM_NSYMS((kbps), (frmlen)) * IEEE80211_OFDM_SYM_TIME)) | | 8924 | (IEEE80211_OFDM_NSYMS((kbps), (frmlen)) * IEEE80211_OFDM_SYM_TIME)) |
8925 | | | 8925 | |
8926 | #define IEEE80211_OFDM_SYM_TIME 4 | | 8926 | #define IEEE80211_OFDM_SYM_TIME 4 |
8927 | #define IEEE80211_OFDM_PREAMBLE_TIME 16 | | 8927 | #define IEEE80211_OFDM_PREAMBLE_TIME 16 |
8928 | #define IEEE80211_OFDM_SIGNAL_EXT_TIME 6 | | 8928 | #define IEEE80211_OFDM_SIGNAL_EXT_TIME 6 |
8929 | #define IEEE80211_OFDM_SIGNAL_TIME 4 | | 8929 | #define IEEE80211_OFDM_SIGNAL_TIME 4 |
8930 | | | 8930 | |
8931 | #define IEEE80211_OFDM_PLCP_SERVICE_NBITS 16 | | 8931 | #define IEEE80211_OFDM_PLCP_SERVICE_NBITS 16 |
8932 | #define IEEE80211_OFDM_TAIL_NBITS 6 | | 8932 | #define IEEE80211_OFDM_TAIL_NBITS 6 |
8933 | | | 8933 | |
8934 | #define IEEE80211_OFDM_NBITS(frmlen) \ | | 8934 | #define IEEE80211_OFDM_NBITS(frmlen) \ |
8935 | (IEEE80211_OFDM_PLCP_SERVICE_NBITS + \ | | 8935 | (IEEE80211_OFDM_PLCP_SERVICE_NBITS + \ |
8936 | ((frmlen) * NBBY) + \ | | 8936 | ((frmlen) * NBBY) + \ |
8937 | IEEE80211_OFDM_TAIL_NBITS) | | 8937 | IEEE80211_OFDM_TAIL_NBITS) |
8938 | | | 8938 | |
8939 | #define IEEE80211_OFDM_NBITS_PER_SYM(kbps) \ | | 8939 | #define IEEE80211_OFDM_NBITS_PER_SYM(kbps) \ |
8940 | (((kbps) * IEEE80211_OFDM_SYM_TIME) / 1000) | | 8940 | (((kbps) * IEEE80211_OFDM_SYM_TIME) / 1000) |
8941 | | | 8941 | |
8942 | #define IEEE80211_OFDM_NSYMS(kbps, frmlen) \ | | 8942 | #define IEEE80211_OFDM_NSYMS(kbps, frmlen) \ |
8943 | howmany(IEEE80211_OFDM_NBITS((frmlen)), \ | | 8943 | howmany(IEEE80211_OFDM_NBITS((frmlen)), \ |
8944 | IEEE80211_OFDM_NBITS_PER_SYM((kbps))) | | 8944 | IEEE80211_OFDM_NBITS_PER_SYM((kbps))) |
8945 | | | 8945 | |
8946 | #define IEEE80211_CCK_TXTIME(kbps, frmlen) \ | | 8946 | #define IEEE80211_CCK_TXTIME(kbps, frmlen) \ |
8947 | (((IEEE80211_CCK_NBITS((frmlen)) * 1000) + (kbps) - 1) / (kbps)) | | 8947 | (((IEEE80211_CCK_NBITS((frmlen)) * 1000) + (kbps) - 1) / (kbps)) |
8948 | | | 8948 | |
8949 | #define IEEE80211_CCK_PREAMBLE_LEN 144 | | 8949 | #define IEEE80211_CCK_PREAMBLE_LEN 144 |
8950 | #define IEEE80211_CCK_PLCP_HDR_TIME 48 | | 8950 | #define IEEE80211_CCK_PLCP_HDR_TIME 48 |
8951 | #define IEEE80211_CCK_SHPREAMBLE_LEN 72 | | 8951 | #define IEEE80211_CCK_SHPREAMBLE_LEN 72 |
8952 | #define IEEE80211_CCK_SHPLCP_HDR_TIME 24 | | 8952 | #define IEEE80211_CCK_SHPLCP_HDR_TIME 24 |
8953 | | | 8953 | |
8954 | #define IEEE80211_CCK_NBITS(frmlen) ((frmlen) * NBBY) | | 8954 | #define IEEE80211_CCK_NBITS(frmlen) ((frmlen) * NBBY) |
8955 | | | 8955 | |
8956 | static uint16_t | | 8956 | static uint16_t |
8957 | bwi_ieee80211_txtime(struct ieee80211com *ic, struct ieee80211_node *ni, | | 8957 | bwi_ieee80211_txtime(struct ieee80211com *ic, struct ieee80211_node *ni, |
8958 | uint len, uint8_t rs_rate, uint32_t flags) | | 8958 | uint len, uint8_t rs_rate, uint32_t flags) |
8959 | { | | 8959 | { |
8960 | enum bwi_ieee80211_modtype modtype; | | 8960 | enum bwi_ieee80211_modtype modtype; |
8961 | uint16_t txtime; | | 8961 | uint16_t txtime; |
8962 | int rate; | | 8962 | int rate; |
8963 | | | 8963 | |
8964 | rs_rate &= IEEE80211_RATE_VAL; | | 8964 | rs_rate &= IEEE80211_RATE_VAL; |
8965 | | | 8965 | |
8966 | rate = rs_rate * 500; /* ieee80211 rate -> kbps */ | | 8966 | rate = rs_rate * 500; /* ieee80211 rate -> kbps */ |
8967 | | | 8967 | |
8968 | modtype = bwi_ieee80211_rate2modtype(rs_rate); | | 8968 | modtype = bwi_ieee80211_rate2modtype(rs_rate); |
8969 | if (modtype == IEEE80211_MODTYPE_OFDM) { | | 8969 | if (modtype == IEEE80211_MODTYPE_OFDM) { |
8970 | /* | | 8970 | /* |
8971 | * IEEE Std 802.11a-1999, page 37, equation (29) | | 8971 | * IEEE Std 802.11a-1999, page 37, equation (29) |
8972 | * IEEE Std 802.11g-2003, page 44, equation (42) | | 8972 | * IEEE Std 802.11g-2003, page 44, equation (42) |
8973 | */ | | 8973 | */ |
8974 | txtime = IEEE80211_OFDM_TXTIME(rate, len); | | 8974 | txtime = IEEE80211_OFDM_TXTIME(rate, len); |
8975 | if (ic->ic_curmode == IEEE80211_MODE_11G) | | 8975 | if (ic->ic_curmode == IEEE80211_MODE_11G) |
8976 | txtime += IEEE80211_OFDM_SIGNAL_EXT_TIME; | | 8976 | txtime += IEEE80211_OFDM_SIGNAL_EXT_TIME; |
8977 | } else { | | 8977 | } else { |
8978 | /* | | 8978 | /* |
8979 | * IEEE Std 802.11b-1999, page 28, subclause 18.3.4 | | 8979 | * IEEE Std 802.11b-1999, page 28, subclause 18.3.4 |
8980 | * IEEE Std 802.11g-2003, page 45, equation (43) | | 8980 | * IEEE Std 802.11g-2003, page 45, equation (43) |
8981 | */ | | 8981 | */ |
8982 | if (modtype == IEEE80211_MODTYPE_PBCC) | | 8982 | if (modtype == IEEE80211_MODTYPE_PBCC) |
8983 | ++len; | | 8983 | ++len; |
8984 | txtime = IEEE80211_CCK_TXTIME(rate, len); | | 8984 | txtime = IEEE80211_CCK_TXTIME(rate, len); |
8985 | | | 8985 | |
8986 | /* | | 8986 | /* |
8987 | * Short preamble is not applicable for DS 1Mbits/s | | 8987 | * Short preamble is not applicable for DS 1Mbits/s |
8988 | */ | | 8988 | */ |
8989 | if (rs_rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) { | | 8989 | if (rs_rate != 2 && (flags & IEEE80211_F_SHPREAMBLE)) { |
8990 | txtime += IEEE80211_CCK_SHPREAMBLE_LEN + | | 8990 | txtime += IEEE80211_CCK_SHPREAMBLE_LEN + |
8991 | IEEE80211_CCK_SHPLCP_HDR_TIME; | | 8991 | IEEE80211_CCK_SHPLCP_HDR_TIME; |
8992 | } else { | | 8992 | } else { |
8993 | txtime += IEEE80211_CCK_PREAMBLE_LEN + | | 8993 | txtime += IEEE80211_CCK_PREAMBLE_LEN + |
8994 | IEEE80211_CCK_PLCP_HDR_TIME; | | 8994 | IEEE80211_CCK_PLCP_HDR_TIME; |
8995 | } | | 8995 | } |
8996 | } | | 8996 | } |
8997 | return (txtime); | | 8997 | return (txtime); |
8998 | } | | 8998 | } |
8999 | | | 8999 | |
9000 | static int | | 9000 | static int |
9001 | bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m, | | 9001 | bwi_encap(struct bwi_softc *sc, int idx, struct mbuf *m, |
9002 | struct ieee80211_node **nip, int mgt_pkt) | | 9002 | struct ieee80211_node **nip, int mgt_pkt) |
9003 | { | | 9003 | { |
9004 | struct ieee80211com *ic = &sc->sc_ic; | | 9004 | struct ieee80211com *ic = &sc->sc_ic; |
9005 | struct ieee80211_node *ni = *nip; | | 9005 | struct ieee80211_node *ni = *nip; |
9006 | struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; | | 9006 | struct bwi_ring_data *rd = &sc->sc_tx_rdata[BWI_TX_DATA_RING]; |
9007 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; | | 9007 | struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING]; |
9008 | struct bwi_txbuf *tb = &tbd->tbd_buf[idx]; | | 9008 | struct bwi_txbuf *tb = &tbd->tbd_buf[idx]; |
9009 | struct bwi_mac *mac; | | 9009 | struct bwi_mac *mac; |
9010 | struct bwi_txbuf_hdr *hdr; | | 9010 | struct bwi_txbuf_hdr *hdr; |
9011 | struct ieee80211_frame *wh; | | 9011 | struct ieee80211_frame *wh; |
9012 | uint8_t rate; /* [TRC: XXX Use a fallback rate?] */ | | 9012 | uint8_t rate; /* [TRC: XXX Use a fallback rate?] */ |
9013 | uint32_t mac_ctrl; | | 9013 | uint32_t mac_ctrl; |
9014 | uint16_t phy_ctrl; | | 9014 | uint16_t phy_ctrl; |
9015 | bus_addr_t paddr; | | 9015 | bus_addr_t paddr; |
9016 | int pkt_len, error, mcast_pkt = 0; | | 9016 | int pkt_len, error, mcast_pkt = 0; |
9017 | #if 0 | | 9017 | #if 0 |
9018 | const uint8_t *p; | | 9018 | const uint8_t *p; |
9019 | int i; | | 9019 | int i; |
9020 | #endif | | 9020 | #endif |
9021 | | | 9021 | |
9022 | KASSERT(ni != NULL); | | 9022 | KASSERT(ni != NULL); |
9023 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); | | 9023 | KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC); |
9024 | mac = (struct bwi_mac *)sc->sc_cur_regwin; | | 9024 | mac = (struct bwi_mac *)sc->sc_cur_regwin; |
9025 | | | 9025 | |
9026 | wh = mtod(m, struct ieee80211_frame *); | | 9026 | wh = mtod(m, struct ieee80211_frame *); |
9027 | | | 9027 | |
9028 | /* Get 802.11 frame len before prepending TX header */ | | 9028 | /* Get 802.11 frame len before prepending TX header */ |
9029 | pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN; | | 9029 | pkt_len = m->m_pkthdr.len + IEEE80211_CRC_LEN; |
9030 | | | 9030 | |
9031 | /* | | 9031 | /* |
9032 | * Find TX rate | | 9032 | * Find TX rate |
9033 | */ | | 9033 | */ |
9034 | memset(tb->tb_rate_idx, 0, sizeof(tb->tb_rate_idx)); | | 9034 | memset(tb->tb_rate_idx, 0, sizeof(tb->tb_rate_idx)); |
9035 | if (!mgt_pkt) { | | 9035 | if (!mgt_pkt) { |
9036 | if (ic->ic_fixed_rate != -1) { | | 9036 | if (ic->ic_fixed_rate != -1) { |
9037 | rate = ic->ic_sup_rates[ic->ic_curmode]. | | 9037 | rate = ic->ic_sup_rates[ic->ic_curmode]. |
9038 | rs_rates[ic->ic_fixed_rate]; | | 9038 | rs_rates[ic->ic_fixed_rate]; |
9039 | /* [TRC: XXX Set fallback rate.] */ | | 9039 | /* [TRC: XXX Set fallback rate.] */ |
9040 | } else { | | 9040 | } else { |
9041 | /* AMRR rate control */ | | 9041 | /* AMRR rate control */ |
9042 | /* [TRC: XXX amrr] */ | | 9042 | /* [TRC: XXX amrr] */ |
9043 | /* rate = ni->ni_rates.rs_rates[ni->ni_txrate]; */ | | 9043 | /* rate = ni->ni_rates.rs_rates[ni->ni_txrate]; */ |
9044 | rate = (1 * 2); | | 9044 | rate = (1 * 2); |
9045 | /* [TRC: XXX Set fallback rate.] */ | | 9045 | /* [TRC: XXX Set fallback rate.] */ |
9046 | } | | 9046 | } |
9047 | } else { | | 9047 | } else { |
9048 | /* Fixed at 1Mbits/s for mgt frames */ | | 9048 | /* Fixed at 1Mbits/s for mgt frames */ |
9049 | /* [TRC: XXX Set fallback rate.] */ | | 9049 | /* [TRC: XXX Set fallback rate.] */ |
9050 | rate = (1 * 2); | | 9050 | rate = (1 * 2); |
9051 | } | | 9051 | } |
9052 | | | 9052 | |
9053 | rate &= IEEE80211_RATE_VAL; | | 9053 | rate &= IEEE80211_RATE_VAL; |
9054 | | | 9054 | |
9055 | if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { | | 9055 | if (IEEE80211_IS_MULTICAST(wh->i_addr1)) { |
9056 | /* [TRC: XXX Set fallback rate.] */ | | 9056 | /* [TRC: XXX Set fallback rate.] */ |
9057 | rate = ic->ic_mcast_rate; | | 9057 | rate = ic->ic_mcast_rate; |
9058 | mcast_pkt = 1; | | 9058 | mcast_pkt = 1; |
9059 | } | | 9059 | } |
9060 | | | 9060 | |
9061 | /* [TRC: XXX Check fallback rate.] */ | | 9061 | /* [TRC: XXX Check fallback rate.] */ |
9062 | if (rate == 0) { | | 9062 | if (rate == 0) { |
9063 | aprint_error_dev(sc->sc_dev, "invalid rate %u", rate); | | 9063 | aprint_error_dev(sc->sc_dev, "invalid rate %u", rate); |
9064 | /* [TRC: In the margin of the following line, | | 9064 | /* [TRC: In the margin of the following line, |
9065 | DragonFlyBSD writes `Force 1Mbits/s', whereas | | 9065 | DragonFlyBSD writes `Force 1Mbits/s', whereas |
9066 | OpenBSD writes `Force 1Mbytes/s'.] */ | | 9066 | OpenBSD writes `Force 1Mbytes/s'.] */ |
9067 | rate = (1 * 2); | | 9067 | rate = (1 * 2); |
9068 | /* [TRC: XXX Set fallback rate.] */ | | 9068 | /* [TRC: XXX Set fallback rate.] */ |
9069 | } | | 9069 | } |
9070 | sc->sc_tx_rate = rate; | | 9070 | sc->sc_tx_rate = rate; |
9071 | | | 9071 | |
9072 | /* TX radio tap */ | | 9072 | /* TX radio tap */ |
9073 | if (sc->sc_drvbpf != NULL) { | | 9073 | if (sc->sc_drvbpf != NULL) { |
9074 | struct mbuf mb; | | 9074 | struct mbuf mb; |
9075 | struct bwi_tx_radiotap_hdr *tap = &sc->sc_txtap; | | 9075 | struct bwi_tx_radiotap_hdr *tap = &sc->sc_txtap; |
9076 | | | 9076 | |
9077 | tap->wt_flags = 0; | | 9077 | tap->wt_flags = 0; |
9078 | tap->wt_rate = rate; | | 9078 | tap->wt_rate = rate; |
9079 | tap->wt_chan_freq = | | 9079 | tap->wt_chan_freq = |
9080 | htole16(ic->ic_bss->ni_chan->ic_freq); | | 9080 | htole16(ic->ic_bss->ni_chan->ic_freq); |
9081 | tap->wt_chan_flags = | | 9081 | tap->wt_chan_flags = |
9082 | htole16(ic->ic_bss->ni_chan->ic_flags); | | 9082 | htole16(ic->ic_bss->ni_chan->ic_flags); |
9083 | | | 9083 | |
9084 | mb.m_data = (void *)tap; | | 9084 | mb.m_data = (void *)tap; |
9085 | mb.m_len = sc->sc_txtap_len; | | 9085 | mb.m_len = sc->sc_txtap_len; |
9086 | mb.m_next = m; | | 9086 | mb.m_next = m; |
9087 | mb.m_nextpkt = NULL; | | 9087 | mb.m_nextpkt = NULL; |
9088 | mb.m_type = 0; | | 9088 | mb.m_type = 0; |
9089 | mb.m_flags = 0; | | 9089 | mb.m_flags = 0; |
9090 | bpf_mtap3(sc->sc_drvbpf, &mb); | | 9090 | bpf_mtap3(sc->sc_drvbpf, &mb); |
9091 | } | | 9091 | } |
9092 | | | 9092 | |
9093 | /* | | 9093 | /* |
9094 | * Setup the embedded TX header | | 9094 | * Setup the embedded TX header |
9095 | */ | | 9095 | */ |
9096 | M_PREPEND(m, sizeof(*hdr), M_DONTWAIT); | | 9096 | M_PREPEND(m, sizeof(*hdr), M_DONTWAIT); |
9097 | if (m == NULL) { | | 9097 | if (m == NULL) { |
9098 | aprint_error_dev(sc->sc_dev, "prepend TX header failed\n"); | | 9098 | aprint_error_dev(sc->sc_dev, "prepend TX header failed\n"); |
9099 | return (ENOBUFS); | | 9099 | return (ENOBUFS); |
9100 | } | | 9100 | } |
9101 | hdr = mtod(m, struct bwi_txbuf_hdr *); | | 9101 | hdr = mtod(m, struct bwi_txbuf_hdr *); |
9102 | | | 9102 | |
9103 | memset(hdr, 0, sizeof(*hdr)); | | 9103 | memset(hdr, 0, sizeof(*hdr)); |
9104 | | | 9104 | |
9105 | memcpy(hdr->txh_fc, wh->i_fc, sizeof(hdr->txh_fc)); | | 9105 | memcpy(hdr->txh_fc, wh->i_fc, sizeof(hdr->txh_fc)); |
9106 | memcpy(hdr->txh_addr1, wh->i_addr1, sizeof(hdr->txh_addr1)); | | 9106 | memcpy(hdr->txh_addr1, wh->i_addr1, sizeof(hdr->txh_addr1)); |
9107 | | | 9107 | |
9108 | if (!mcast_pkt) { | | 9108 | if (!mcast_pkt) { |
9109 | uint16_t dur; | | 9109 | uint16_t dur; |
9110 | uint8_t ack_rate; | | 9110 | uint8_t ack_rate; |
9111 | | | 9111 | |
9112 | /* [TRC: XXX Set fallback rate.] */ | | 9112 | /* [TRC: XXX Set fallback rate.] */ |
9113 | ack_rate = bwi_ieee80211_ack_rate(ni, rate); | | 9113 | ack_rate = bwi_ieee80211_ack_rate(ni, rate); |
9114 | dur = bwi_ieee80211_txtime(ic, ni, | | 9114 | dur = bwi_ieee80211_txtime(ic, ni, |
9115 | sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN, | | 9115 | sizeof(struct ieee80211_frame_ack) + IEEE80211_CRC_LEN, |
9116 | ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); | | 9116 | ack_rate, ic->ic_flags & IEEE80211_F_SHPREAMBLE); |
9117 | | | 9117 | |
9118 | hdr->txh_fb_duration = htole16(dur); | | 9118 | hdr->txh_fb_duration = htole16(dur); |
9119 | } | | 9119 | } |
9120 | | | 9120 | |
9121 | hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) | | | 9121 | hdr->txh_id = __SHIFTIN(BWI_TX_DATA_RING, BWI_TXH_ID_RING_MASK) | |
9122 | __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK); | | 9122 | __SHIFTIN(idx, BWI_TXH_ID_IDX_MASK); |
9123 | | | 9123 | |
9124 | bwi_plcp_header(hdr->txh_plcp, pkt_len, rate); | | 9124 | bwi_plcp_header(hdr->txh_plcp, pkt_len, rate); |
9125 | /* [TRC: XXX Use fallback rate.] */ | | 9125 | /* [TRC: XXX Use fallback rate.] */ |
9126 | bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate); | | 9126 | bwi_plcp_header(hdr->txh_fb_plcp, pkt_len, rate); |
9127 | | | 9127 | |
9128 | phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode, | | 9128 | phy_ctrl = __SHIFTIN(mac->mac_rf.rf_ant_mode, |
9129 | BWI_TXH_PHY_C_ANTMODE_MASK); | | 9129 | BWI_TXH_PHY_C_ANTMODE_MASK); |
9130 | if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) | | 9130 | if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) |
9131 | phy_ctrl |= BWI_TXH_PHY_C_OFDM; | | 9131 | phy_ctrl |= BWI_TXH_PHY_C_OFDM; |
9132 | else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1)) | | 9132 | else if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && rate != (2 * 1)) |
9133 | phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE; | | 9133 | phy_ctrl |= BWI_TXH_PHY_C_SHPREAMBLE; |
9134 | | | 9134 | |
9135 | mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG; | | 9135 | mac_ctrl = BWI_TXH_MAC_C_HWSEQ | BWI_TXH_MAC_C_FIRST_FRAG; |
9136 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) | | 9136 | if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) |
9137 | mac_ctrl |= BWI_TXH_MAC_C_ACK; | | 9137 | mac_ctrl |= BWI_TXH_MAC_C_ACK; |
9138 | if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) | | 9138 | if (bwi_ieee80211_rate2modtype(rate) == IEEE80211_MODTYPE_OFDM) |
9139 | mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM; | | 9139 | mac_ctrl |= BWI_TXH_MAC_C_FB_OFDM; |
9140 | | | 9140 | |
9141 | hdr->txh_mac_ctrl = htole32(mac_ctrl); | | 9141 | hdr->txh_mac_ctrl = htole32(mac_ctrl); |
9142 | hdr->txh_phy_ctrl = htole16(phy_ctrl); | | 9142 | hdr->txh_phy_ctrl = htole16(phy_ctrl); |
9143 | | | 9143 | |
9144 | /* Catch any further usage */ | | 9144 | /* Catch any further usage */ |
9145 | hdr = NULL; | | 9145 | hdr = NULL; |
9146 | wh = NULL; | | 9146 | wh = NULL; |
9147 | | | 9147 | |
9148 | /* DMA load */ | | 9148 | /* DMA load */ |
9149 | error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m, | | 9149 | error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m, |
9150 | BUS_DMA_NOWAIT); | | 9150 | BUS_DMA_NOWAIT); |
9151 | if (error && error != EFBIG) { | | 9151 | if (error && error != EFBIG) { |
9152 | aprint_error_dev(sc->sc_dev, "can't load TX buffer (1) %d\n", | | 9152 | aprint_error_dev(sc->sc_dev, "can't load TX buffer (1) %d\n", |
9153 | error); | | 9153 | error); |
9154 | goto back; | | 9154 | goto back; |
9155 | } | | 9155 | } |
9156 | | | 9156 | |
9157 | if (error) { /* error == EFBIG */ | | 9157 | if (error) { /* error == EFBIG */ |
9158 | struct mbuf *m_new; | | 9158 | struct mbuf *m_new; |
9159 | | | 9159 | |
9160 | error = 0; | | 9160 | error = 0; |
9161 | | | 9161 | |
9162 | MGETHDR(m_new, M_DONTWAIT, MT_DATA); | | 9162 | MGETHDR(m_new, M_DONTWAIT, MT_DATA); |
9163 | if (m_new == NULL) { | | 9163 | if (m_new == NULL) { |
9164 | m_freem(m); | | 9164 | m_freem(m); |
9165 | error = ENOBUFS; | | 9165 | error = ENOBUFS; |
9166 | aprint_error_dev(sc->sc_dev, | | 9166 | aprint_error_dev(sc->sc_dev, |
9167 | "can't defrag TX buffer (1)\n"); | | 9167 | "can't defrag TX buffer (1)\n"); |
9168 | goto back; | | 9168 | goto back; |
9169 | } | | 9169 | } |
9170 | | | 9170 | |
9171 | M_COPY_PKTHDR(m_new, m); | | 9171 | M_COPY_PKTHDR(m_new, m); |
9172 | if (m->m_pkthdr.len > MHLEN) { | | 9172 | if (m->m_pkthdr.len > MHLEN) { |
9173 | MCLGET(m_new, M_DONTWAIT); | | 9173 | MCLGET(m_new, M_DONTWAIT); |
9174 | if (!(m_new->m_flags & M_EXT)) { | | 9174 | if (!(m_new->m_flags & M_EXT)) { |
9175 | m_freem(m); | | 9175 | m_freem(m); |
9176 | m_freem(m_new); | | 9176 | m_freem(m_new); |
9177 | error = ENOBUFS; | | 9177 | error = ENOBUFS; |
9178 | } | | 9178 | } |
9179 | } | | 9179 | } |
9180 | | | 9180 | |
9181 | if (error) { | | 9181 | if (error) { |
9182 | aprint_error_dev(sc->sc_dev, | | 9182 | aprint_error_dev(sc->sc_dev, |
9183 | "can't defrag TX buffer (2)\n"); | | 9183 | "can't defrag TX buffer (2)\n"); |
9184 | goto back; | | 9184 | goto back; |
9185 | } | | 9185 | } |
9186 | | | 9186 | |
9187 | m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, void *)); | | 9187 | m_copydata(m, 0, m->m_pkthdr.len, mtod(m_new, void *)); |
9188 | m_freem(m); | | 9188 | m_freem(m); |
9189 | m_new->m_len = m_new->m_pkthdr.len; | | 9189 | m_new->m_len = m_new->m_pkthdr.len; |
9190 | m = m_new; | | 9190 | m = m_new; |
9191 | | | 9191 | |
9192 | error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m, | | 9192 | error = bus_dmamap_load_mbuf(sc->sc_dmat, tb->tb_dmap, m, |
9193 | BUS_DMA_NOWAIT); | | 9193 | BUS_DMA_NOWAIT); |
9194 | if (error) { | | 9194 | if (error) { |
9195 | aprint_error_dev(sc->sc_dev, | | 9195 | aprint_error_dev(sc->sc_dev, |
9196 | "can't load TX buffer (2) %d\n", error); | | 9196 | "can't load TX buffer (2) %d\n", error); |
9197 | goto back; | | 9197 | goto back; |
9198 | } | | 9198 | } |
9199 | } | | 9199 | } |
9200 | error = 0; | | 9200 | error = 0; |
9201 | | | 9201 | |
9202 | bus_dmamap_sync(sc->sc_dmat, tb->tb_dmap, 0, | | 9202 | bus_dmamap_sync(sc->sc_dmat, tb->tb_dmap, 0, |
9203 | tb->tb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 9203 | tb->tb_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
9204 | | | 9204 | |
9205 | if (mgt_pkt || mcast_pkt) { | | 9205 | if (mgt_pkt || mcast_pkt) { |
9206 | /* Don't involve mcast/mgt packets into TX rate control */ | | 9206 | /* Don't involve mcast/mgt packets into TX rate control */ |
9207 | ieee80211_free_node(ni); | | 9207 | ieee80211_free_node(ni); |
9208 | *nip = ni = NULL; | | 9208 | *nip = ni = NULL; |
9209 | } | | 9209 | } |
9210 | | | 9210 | |
9211 | tb->tb_mbuf = m; | | 9211 | tb->tb_mbuf = m; |
9212 | tb->tb_ni = ni; | | 9212 | tb->tb_ni = ni; |
9213 | | | 9213 | |
9214 | #if 0 | | 9214 | #if 0 |
9215 | p = mtod(m, const uint8_t *); | | 9215 | p = mtod(m, const uint8_t *); |
9216 | for (i = 0; i < m->m_pkthdr.len; ++i) { | | 9216 | for (i = 0; i < m->m_pkthdr.len; ++i) { |
9217 | if (i % 8 == 0) { | | 9217 | if (i % 8 == 0) { |
9218 | if (i != 0) | | 9218 | if (i != 0) |
9219 | aprint_debug("\n"); | | 9219 | aprint_debug("\n"); |
9220 | aprint_debug_dev(sc->sc_dev, ""); | | 9220 | aprint_debug_dev(sc->sc_dev, ""); |
9221 | } | | 9221 | } |
9222 | aprint_debug(" %02x", p[i]); | | 9222 | aprint_debug(" %02x", p[i]); |
9223 | } | | 9223 | } |
9224 | aprint_debug("\n"); | | 9224 | aprint_debug("\n"); |
9225 | #endif | | 9225 | #endif |
9226 | | | 9226 | |
9227 | DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n", | | 9227 | DPRINTF(sc, BWI_DBG_TX, "idx %d, pkt_len %d, buflen %d\n", |
9228 | idx, pkt_len, m->m_pkthdr.len); | | 9228 | idx, pkt_len, m->m_pkthdr.len); |
9229 | | | 9229 | |
9230 | /* Setup TX descriptor */ | | 9230 | /* Setup TX descriptor */ |
9231 | paddr = tb->tb_dmap->dm_segs[0].ds_addr; | | 9231 | paddr = tb->tb_dmap->dm_segs[0].ds_addr; |
9232 | (sc->sc_setup_txdesc)(sc, rd, idx, paddr, m->m_pkthdr.len); | | 9232 | (sc->sc_setup_txdesc)(sc, rd, idx, paddr, m->m_pkthdr.len); |
9233 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, | | 9233 | bus_dmamap_sync(sc->sc_dmat, rd->rdata_dmap, 0, |
9234 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); | | 9234 | rd->rdata_dmap->dm_mapsize, BUS_DMASYNC_PREWRITE); |
9235 | | | 9235 | |
9236 | /* Kick start */ | | 9236 | /* Kick start */ |
9237 | (sc->sc_start_tx)(sc, rd->rdata_txrx_ctrl, idx); | | 9237 | (sc->sc_start_tx)(sc, rd->rdata_txrx_ctrl, idx); |
9238 | | | 9238 | |
9239 | back: | | 9239 | back: |
9240 | if (error) | | 9240 | if (error) |
9241 | m_freem(m); | | 9241 | m_freem(m); |
9242 | return (error); | | 9242 | return (error); |
9243 | } | | 9243 | } |
9244 | | | 9244 | |
9245 | static void | | 9245 | static void |
9246 | bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) | | 9246 | bwi_start_tx32(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) |
9247 | { | | 9247 | { |
9248 | idx = (idx + 1) % BWI_TX_NDESC; | | 9248 | idx = (idx + 1) % BWI_TX_NDESC; |
9249 | CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX, | | 9249 | CSR_WRITE_4(sc, tx_ctrl + BWI_TX32_INDEX, |
9250 | idx * sizeof(struct bwi_desc32)); | | 9250 | idx * sizeof(struct bwi_desc32)); |
9251 | } | | 9251 | } |
9252 | | | 9252 | |
9253 | static void | | 9253 | static void |
9254 | bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) | | 9254 | bwi_start_tx64(struct bwi_softc *sc, uint32_t tx_ctrl, int idx) |
9255 | { | | 9255 | { |
9256 | /* TODO: 64 */ | | 9256 | /* TODO: 64 */ |
9257 | } | | 9257 | } |
9258 | | | 9258 | |
9259 | static void | | 9259 | static void |
9260 | bwi_txeof_status32(struct bwi_softc *sc) | | 9260 | bwi_txeof_status32(struct bwi_softc *sc) |
9261 | { | | 9261 | { |
9262 | struct ifnet *ifp = &sc->sc_if; | | 9262 | struct ifnet *ifp = &sc->sc_if; |
9263 | uint32_t val, ctrl_base; | | 9263 | uint32_t val, ctrl_base; |
9264 | int end_idx; | | 9264 | int end_idx; |
9265 | | | 9265 | |
9266 | ctrl_base = sc->sc_txstats->stats_ctrl_base; | | 9266 | ctrl_base = sc->sc_txstats->stats_ctrl_base; |
9267 | | | 9267 | |
9268 | val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS); | | 9268 | val = CSR_READ_4(sc, ctrl_base + BWI_RX32_STATUS); |
9269 | end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / | | 9269 | end_idx = __SHIFTOUT(val, BWI_RX32_STATUS_INDEX_MASK) / |
9270 | sizeof(struct bwi_desc32); | | 9270 | sizeof(struct bwi_desc32); |
9271 | | | 9271 | |
9272 | bwi_txeof_status(sc, end_idx); | | 9272 | bwi_txeof_status(sc, end_idx); |
9273 | | | 9273 | |
9274 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, | | 9274 | CSR_WRITE_4(sc, ctrl_base + BWI_RX32_INDEX, |
9275 | end_idx * sizeof(struct bwi_desc32)); | | 9275 | end_idx * sizeof(struct bwi_desc32)); |
9276 | | | 9276 | |
9277 | if ((ifp->if_flags & IFF_OACTIVE) == 0) | | 9277 | if ((ifp->if_flags & IFF_OACTIVE) == 0) |
9278 | ifp->if_start(ifp); /* [TRC: XXX Why not bwi_start?] */ | | 9278 | ifp->if_start(ifp); /* [TRC: XXX Why not bwi_start?] */ |
9279 | } | | 9279 | } |
9280 | | | 9280 | |
9281 | static void | | 9281 | static void |
9282 | bwi_txeof_status64(struct bwi_softc *sc) | | 9282 | bwi_txeof_status64(struct bwi_softc *sc) |
9283 | { | | 9283 | { |
9284 | /* TODO: 64 */ | | 9284 | /* TODO: 64 */ |
9285 | } | | 9285 | } |
9286 | | | 9286 | |
9287 | static void | | 9287 | static void |
9288 | _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id) | | 9288 | _bwi_txeof(struct bwi_softc *sc, uint16_t tx_id) |
9289 | { | | 9289 | { |
9290 | struct ifnet *ifp = &sc->sc_if; | | 9290 | struct ifnet *ifp = &sc->sc_if; |
9291 | struct bwi_txbuf_data *tbd; | | 9291 | struct bwi_txbuf_data *tbd; |
9292 | struct bwi_txbuf *tb; | | 9292 | struct bwi_txbuf *tb; |
9293 | int ring_idx, buf_idx; | | 9293 | int ring_idx, buf_idx; |
9294 | | | 9294 | |
9295 | if (tx_id == 0) { | | 9295 | if (tx_id == 0) { |
9296 | /* [TRC: XXX What is the severity of this message?] */ | | 9296 | /* [TRC: XXX What is the severity of this message?] */ |
9297 | aprint_normal_dev(sc->sc_dev, "zero tx id\n"); | | 9297 | aprint_normal_dev(sc->sc_dev, "zero tx id\n"); |
9298 | return; | | 9298 | return; |
9299 | } | | 9299 | } |
9300 | | | 9300 | |
9301 | ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK); | | 9301 | ring_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_RING_MASK); |
9302 | buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK); | | 9302 | buf_idx = __SHIFTOUT(tx_id, BWI_TXH_ID_IDX_MASK); |
9303 | | | 9303 | |
9304 | KASSERT(ring_idx == BWI_TX_DATA_RING); | | 9304 | KASSERT(ring_idx == BWI_TX_DATA_RING); |
9305 | KASSERT(buf_idx < BWI_TX_NDESC); | | 9305 | KASSERT(buf_idx < BWI_TX_NDESC); |
9306 | tbd = &sc->sc_tx_bdata[ring_idx]; | | 9306 | tbd = &sc->sc_tx_bdata[ring_idx]; |
9307 | KASSERT(tbd->tbd_used > 0); | | 9307 | KASSERT(tbd->tbd_used > 0); |
9308 | tbd->tbd_used--; | | 9308 | tbd->tbd_used--; |
9309 | | | 9309 | |
9310 | tb = &tbd->tbd_buf[buf_idx]; | | 9310 | tb = &tbd->tbd_buf[buf_idx]; |
9311 | | | 9311 | |
9312 | bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap); | | 9312 | bus_dmamap_unload(sc->sc_dmat, tb->tb_dmap); |
9313 | m_freem(tb->tb_mbuf); | | 9313 | m_freem(tb->tb_mbuf); |
9314 | tb->tb_mbuf = NULL; | | 9314 | tb->tb_mbuf = NULL; |
9315 | | | 9315 | |
9316 | if (tb->tb_ni != NULL) { | | 9316 | if (tb->tb_ni != NULL) { |
9317 | ieee80211_free_node(tb->tb_ni); | | 9317 | ieee80211_free_node(tb->tb_ni); |