carl9170 firmware: Support multiple CAB queues
[carl9170fw.git] / carlfw / include / wl.h
1 /*
2  * carl9170 firmware - used by the ar9170 wireless device
3  *
4  * WLAN
5  *
6  * Copyright (c) 2000-2005 ZyDAS Technology Corporation
7  * Copyright (c) 2007-2009 Atheros Communications, Inc.
8  * Copyright    2009    Johannes Berg <johannes@sipsolutions.net>
9  * Copyright 2009, 2010 Christian Lamparter <chunkeey@googlemail.com>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  */
25
26 #ifndef __CARL9170FW_WLAN_H
27 #define __CARL9170FW_WLAN_H
28
29 #include "config.h"
30 #include "carl9170.h"
31 #include "io.h"
32
33 struct ieee80211_hdr;
34
35 static inline __inline void set_wlan_txq_dma_addr(const unsigned int q, const uint32_t v)
36 {
37         set(AR9170_MAC_REG_DMA_TXQ_ADDR + (q << 3), v);
38 }
39
40 static inline __inline void set_wlan_txq_dma_curr_addr(const unsigned int q, const uint32_t v)
41 {
42         set(AR9170_MAC_REG_DMA_TXQ_CURR_ADDR + (q << 3), v);
43 }
44
45 static inline __inline struct dma_desc *get_wlan_txq_dma_addr(const unsigned int q)
46 {
47         return getp(AR9170_MAC_REG_DMA_TXQ_ADDR + (q << 3));
48 }
49
50 static inline __inline struct dma_desc *get_wlan_txq_addr(const unsigned int q)
51 {
52         return getp(AR9170_MAC_REG_DMA_TXQ_CURR_ADDR + (q << 3));
53 }
54
55 static inline __inline void _wlan_trigger(const uint32_t queue_bit)
56 {
57         set(AR9170_MAC_REG_DMA_TRIGGER, queue_bit);
58 }
59
60 #ifdef CONFIG_CARL9170FW_DELAYED_TX
61 static inline __inline void wlan_trigger(const uint32_t queue_bit)
62 {
63         fw.wlan.tx_trigger |= queue_bit;
64 }
65 #else
66 static inline __inline void wlan_trigger(const uint32_t queue_bit)
67 {
68         _wlan_trigger(queue_bit);
69 }
70 #endif /* CONFIG_CARL9170FW_DELAYED_TX */
71
72 static inline __inline uint8_t ar9170_get_rx_macstatus_status(struct dma_desc *desc)
73 {
74         return *((uint8_t *) DESC_PAYLOAD_OFF(desc->lastAddr,
75                 (unsigned int) desc->lastAddr->dataSize - 1));
76 }
77
78 static inline __inline uint8_t ar9170_get_rx_macstatus_error(struct dma_desc *desc)
79 {
80         unsigned int offset;
81
82         if (desc->lastAddr->dataSize == 1) {
83                 while (desc->lastAddr != desc->nextAddr)
84                         desc = desc->nextAddr;
85
86                 offset = (unsigned int) (desc->dataSize - 1);
87         } else {
88                 desc = desc->lastAddr;
89                 offset = desc->dataSize -
90                         (sizeof(struct ar9170_rx_macstatus) -
91                          offsetof(struct ar9170_rx_macstatus, error));
92         }
93
94         return *((uint8_t *) DESC_PAYLOAD_OFF(desc, offset));
95 }
96
97 static inline __inline struct ieee80211_hdr *ar9170_get_rx_i3e(struct dma_desc *desc)
98 {
99         if (!((ar9170_get_rx_macstatus_status(desc) &
100                 AR9170_RX_STATUS_MPDU) & AR9170_RX_STATUS_MPDU_LAST)) {
101                 return (void *)(DESC_PAYLOAD_OFF(desc,
102                         offsetof(struct ar9170_rx_frame_head, i3e)));
103         } else {
104                 return (void *)(DESC_PAYLOAD_OFF(desc,
105                         offsetof(struct ar9170_rx_frame_tail, i3e)));
106         }
107 }
108
109 static inline __inline struct ar9170_rx_head *ar9170_get_rx_head(struct dma_desc *desc)
110 {
111         if (!((ar9170_get_rx_macstatus_status(desc) &
112                 AR9170_RX_STATUS_MPDU) & AR9170_RX_STATUS_MPDU_LAST)) {
113                 return (void *)((uint8_t *)DESC_PAYLOAD(desc) +
114                         offsetof(struct ar9170_rx_frame_head, phy_head));
115         } else {
116                 return (void *) NULL;
117         }
118 }
119
120 static inline __inline uint32_t ar9170_rx_to_phy(struct dma_desc *rx)
121 {
122         struct ar9170_tx_hw_phy_control phy;
123         struct ar9170_rx_head *head;
124         uint8_t mac_status;
125
126         phy.set = 0;
127
128         head = ar9170_get_rx_head(rx);
129         if (!head)
130                 return le32_to_cpu(phy.set);
131
132         mac_status = ar9170_get_rx_macstatus_status(rx);
133
134         phy.modulation = mac_status & AR9170_RX_STATUS_MODULATION;
135         phy.chains = AR9170_TX_PHY_TXCHAIN_1;
136
137         switch (phy.modulation) {
138         case AR9170_RX_STATUS_MODULATION_CCK:
139                 if (mac_status & AR9170_RX_STATUS_SHORT_PREAMBLE)
140                         phy.preamble = 1;
141
142                 switch (head->plcp[0]) {
143                 case AR9170_RX_PHY_RATE_CCK_2M:
144                         phy.mcs = AR9170_TX_PHY_RATE_CCK_2M;
145                         break;
146
147                 case AR9170_RX_PHY_RATE_CCK_5M:
148                         phy.mcs = AR9170_TX_PHY_RATE_CCK_5M;
149                         break;
150
151                 case AR9170_RX_PHY_RATE_CCK_11M:
152                         phy.mcs = AR9170_TX_PHY_RATE_CCK_11M;
153                         break;
154
155                 case AR9170_RX_PHY_RATE_CCK_1M:
156                 default:
157                         phy.mcs = AR9170_TX_PHY_RATE_CCK_1M;
158                         break;
159
160                 }
161                 break;
162
163         case AR9170_RX_STATUS_MODULATION_DUPOFDM:
164         case AR9170_RX_STATUS_MODULATION_OFDM:
165                 phy.mcs = head->plcp[0] & 0xf;
166                 break;
167
168         case AR9170_RX_STATUS_MODULATION_HT:
169                 if (head->plcp[3] & 0x80)
170                         phy.bandwidth = 2;
171
172                 if (head->plcp[6] & 0x80)
173                         phy.short_gi = 1;
174
175                 /* TODO: Enable both chains for MCS > 7 */
176                 phy.mcs = head->plcp[6] & 0x7;
177                 break;
178         }
179
180         return le32_to_cpu(phy.set);
181 }
182
183 static inline __inline unsigned int ar9170_get_rx_mpdu_len(struct dma_desc *desc)
184 {
185         /*
186          * WARNING: you have to check the error bits in macstatus first!
187          */
188
189         unsigned int mpdu_len = desc->totalLen;
190
191         mpdu_len -= sizeof(struct ar9170_rx_macstatus);
192
193         switch (ar9170_get_rx_macstatus_status(desc) & AR9170_RX_STATUS_MPDU) {
194         case AR9170_RX_STATUS_MPDU_LAST:
195                 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
196                 break;
197
198         case AR9170_RX_STATUS_MPDU_SINGLE:
199                 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
200
201         case AR9170_RX_STATUS_MPDU_FIRST:
202                 mpdu_len -= sizeof(struct ar9170_rx_head);
203                 break;
204
205         case AR9170_RX_STATUS_MPDU_MIDDLE:
206         default:
207                 break;
208         }
209
210         return mpdu_len;
211 }
212
213 static inline __inline bool ar9170_tx_length_check(const uint16_t len)
214 {
215         return len > (sizeof(struct carl9170_tx_superframe) + 24 +
216                          FCS_LEN);
217 }
218
219 static inline __inline struct carl9170_tx_superframe *get_super(struct dma_desc *desc)
220 {
221         return container_of(DESC_PAYLOAD(desc), struct carl9170_tx_superframe,
222                             f);
223 }
224
225 static inline __inline void hide_super(struct dma_desc *desc)
226 {
227         desc->dataAddr = (uint8_t *)
228                 (((unsigned long)(DESC_PAYLOAD(desc)) +
229                 offsetof(struct carl9170_tx_superframe, f)));
230
231         desc->dataSize -= sizeof(struct carl9170_tx_superdesc);
232         desc->totalLen -= sizeof(struct carl9170_tx_superdesc);
233 }
234
235 static inline __inline void unhide_super(struct dma_desc *desc)
236 {
237         desc->dataAddr = (uint8_t *) get_super(desc);
238         desc->dataSize += sizeof(struct carl9170_tx_superdesc);
239         desc->totalLen += sizeof(struct carl9170_tx_superdesc);
240 }
241
242 static inline __inline __hot void read_tsf(uint32_t *tsf)
243 {
244         /*
245          * "According to the [hardware] documentation:
246          *  > when TSF_LOW is read, TSF_HI is automatically concurrently
247          *  > copied into a temporary register so that an immediate read
248          *  > of TSF_HI will get the value that was present when TSF_LOW
249          *  > was read. "
250          *
251          * (David H. Lynch Jr. - mail from 2010-05-22)
252          * http://permalink.gmane.org/gmane.linux.kernel.wireless.general/51249
253          */
254
255         tsf[0] = get(AR9170_MAC_REG_TSF_L);
256         tsf[1] = get(AR9170_MAC_REG_TSF_H);
257 }
258
259 void wlan_tx(struct dma_desc *desc);
260 void wlan_timer(void);
261 void handle_wlan(void);
262 void wlan_tx_stuck(const struct carl9170_cmd *cmd, struct carl9170_rsp *rsp);
263
264 void wlan_cab_flush_queue(const unsigned int vif);
265 void wlan_cab_modify_dtim_beacon(const unsigned int vif);
266
267 static inline void __check_wlantx(void)
268 {
269         BUILD_BUG_ON(sizeof(struct carl9170_tx_superdesc) != CARL9170_TX_SUPERDESC_LEN);
270         BUILD_BUG_ON((offsetof(struct carl9170_tx_superframe, f) & 3) != 0);
271         BUILD_BUG_ON(sizeof(struct ar9170_tx_hwdesc) != AR9170_TX_HWDESC_LEN);
272         BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
273         BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
274         BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
275 }
276
277 #endif /* __CARL9170FW_WLAN_H */