Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / wlan / ah.c
1 #include "opt_ah.h"
2 #include "ah.h"
3 #include "ah_internal.h"
4 #include <asf_bitmap.h>
5
6 extern struct ath_hal *ar5416Attach(a_uint32_t devid,HAL_SOFTC sc, adf_os_device_t dev,
7                                     HAL_BUS_HANDLE sh, a_uint32_t flags, HAL_STATUS *status);
8
9 struct ath_hal*
10 ath_hal_attach_tgt(a_uint32_t devid,HAL_SOFTC sc,
11                    adf_os_device_t dev, HAL_BUS_HANDLE sh,
12                    a_uint32_t flags, HAL_STATUS *error)
13 {
14         struct ath_hal *ah = AH_NULL;
15
16         devid = AR5416_DEVID_PCIE;
17         ah = ar5416Attach(devid, sc, dev, sh, flags, error);
18
19         return ah;
20 }
21
22 HAL_STATUS
23 ath_hal_getcapability(struct ath_hal *ah, HAL_CAPABILITY_TYPE type,
24                       a_uint32_t capability, a_uint32_t *result)
25
26 {
27         const HAL_CAPABILITIES *pCap = &AH_PRIVATE(ah)->ah_caps;
28         switch (type) {
29         case HAL_CAP_TSF_ADJUST:
30                 return HAL_ENOTSUPP;
31         case HAL_CAP_BSSIDMASK:
32                 return pCap->halBssIdMaskSupport ? HAL_OK : HAL_ENOTSUPP;
33         case HAL_CAP_VEOL:
34                 return pCap->halVEOLSupport ? HAL_OK : HAL_ENOTSUPP;
35 #ifdef MAGPIE_MERLIN
36         case HAL_CAP_RX_STBC:
37                 return HAL_ENOTSUPP;
38         case HAL_CAP_TX_STBC:
39                 return HAL_ENOTSUPP;
40 #endif
41         default:
42                 return HAL_EINVAL;
43         }
44 }
45
46 void
47 ath_hal_setupratetable(struct ath_hal *ah, HAL_RATE_TABLE *rt)
48 {
49         a_int32_t i;
50
51         if (rt->rateCodeToIndex[0] != 0)
52                 return;
53
54         for (i = 0; i < 32; i++)
55                 rt->rateCodeToIndex[i] = (a_uint8_t) -1;
56         for (i = 0; i < rt->rateCount; i++) {
57                 a_uint8_t code = rt->info[i].rateCode;
58                 a_uint8_t cix = rt->info[i].controlRate;
59
60                 rt->rateCodeToIndex[code] = i;
61                 rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
62                 rt->info[i].lpAckDuration = ath_hal_computetxtime(ah, rt,
63                                           WLAN_CTRL_FRAME_SIZE, cix, AH_FALSE);
64                 rt->info[i].spAckDuration = ath_hal_computetxtime(ah, rt,
65                                           WLAN_CTRL_FRAME_SIZE, cix, AH_TRUE);
66         }
67 }
68
69 #define CCK_SIFS_TIME        10
70 #define CCK_PREAMBLE_BITS   144
71 #define CCK_PLCP_BITS        48
72
73 #define OFDM_SIFS_TIME        16
74 #define OFDM_PREAMBLE_TIME    20
75 #define OFDM_PLCP_BITS        22
76 #define OFDM_SYMBOL_TIME       4
77
78 #define OFDM_SIFS_TIME_HALF     32
79 #define OFDM_PREAMBLE_TIME_HALF 40
80 #define OFDM_PLCP_BITS_HALF     22
81 #define OFDM_SYMBOL_TIME_HALF   8
82
83 #define OFDM_SIFS_TIME_QUARTER      64
84 #define OFDM_PREAMBLE_TIME_QUARTER  80
85 #define OFDM_PLCP_BITS_QUARTER      22
86 #define OFDM_SYMBOL_TIME_QUARTER    16
87
88 a_uint16_t
89 ath_hal_computetxtime(struct ath_hal *ah,
90                       const HAL_RATE_TABLE *rates, a_uint32_t frameLen, a_uint16_t rateix,
91                       HAL_BOOL shortPreamble)
92 {
93         a_uint32_t bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
94         a_uint32_t kbps;
95
96         kbps = rates->info[rateix].rateKbps;
97
98         /*
99          * index can be invalid duting dynamic Turbo transitions.
100          */
101         if(kbps == 0) return 0;
102         switch (rates->info[rateix].phy) {
103
104         case IEEE80211_T_CCK:
105                 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
106                 if (shortPreamble && rates->info[rateix].shortPreamble)
107                         phyTime >>= 1;
108                 numBits = frameLen << 3;
109                 txTime = phyTime + ((numBits * 1000)/kbps);
110                 /* TODO: make sure the same value of txTime can use in all device */
111                 if (ath_hal_getcapability(ah, HAL_CAP_HT, 0, AH_NULL) != HAL_OK)
112                         txTime = txTime + CCK_SIFS_TIME;
113                 break;
114         case IEEE80211_T_OFDM:
115                 /* full rate channel */
116                 bitsPerSymbol   = (kbps * OFDM_SYMBOL_TIME) / 1000;
117                 HALASSERT(bitsPerSymbol != 0);
118
119                 numBits = OFDM_PLCP_BITS + (frameLen << 3);
120                 numSymbols = asf_howmany(numBits, bitsPerSymbol);
121                 txTime = OFDM_PREAMBLE_TIME + (numSymbols * OFDM_SYMBOL_TIME);
122                 /* TODO: make sure the same value of txTime can use in all device */
123                 if (ath_hal_getcapability(ah, HAL_CAP_HT, 0, AH_NULL) != HAL_OK)
124                         txTime = txTime + OFDM_SIFS_TIME;
125                 break;
126         default:
127                 txTime = 0;
128                 break;
129         }
130         return txTime;
131 }
132
133 #undef CCK_SIFS_TIME
134 #undef CCK_PREAMBLE_BITS
135 #undef CCK_PLCP_BITS
136
137 #undef OFDM_SIFS_TIME
138 #undef OFDM_PREAMBLE_TIME
139 #undef OFDM_PLCP_BITS
140 #undef OFDM_SYMBOL_TIME
141
142 #ifdef MAGPIE_MERLIN
143 a_uint32_t 
144 ath_hal_get_curmode(struct ath_hal *ah, HAL_CHANNEL_INTERNAL *chan)
145 {
146         if (!chan)
147                 return HAL_MODE_11NG;
148
149         if (IS_CHAN_NA(chan))
150                 return HAL_MODE_11NA; 
151
152         if (IS_CHAN_A(chan))
153                 return HAL_MODE_11A;
154
155         if (IS_CHAN_NG(chan))
156                 return HAL_MODE_11NG;
157
158         if (IS_CHAN_G(chan))
159                 return HAL_MODE_11G;
160
161         if (IS_CHAN_B(chan))
162                 return HAL_MODE_11B;
163
164         HALASSERT(0);
165         return HAL_MODE_11NG;
166 }
167
168 #endif
169
170 HAL_BOOL
171 ath_hal_wait(struct ath_hal *ah, a_uint32_t reg, a_uint32_t mask, a_uint32_t val)
172 {
173 #define AH_TIMEOUT_11N 100000
174 #define AH_TIMEOUT_11G  1000
175
176         a_int32_t i;
177
178         if (ath_hal_getcapability(ah, HAL_CAP_HT, 0, AH_NULL) == HAL_OK) {
179                 for (i = 0; i < AH_TIMEOUT_11N; i++) {
180                         if ((OS_REG_READ(ah, reg) & mask) == val)
181                                 return AH_TRUE;
182                         OS_DELAY(10);
183                 }
184         } else {
185                 for (i = 0; i < AH_TIMEOUT_11G; i++) {
186                         if ((OS_REG_READ(ah, reg) & mask) == val)
187                                 return AH_TRUE;
188                         OS_DELAY(10);
189                 }
190         }
191         return AH_FALSE;
192
193 #undef AH_TIMEOUT_11N
194 #undef AH_TIMEOUT_11G
195 }