1 // Author: Xianjun Jiao, Michael Mehari, Wei Liu
2 // SPDX-FileCopyrightText: 2019 UGent
3 // SPDX-License-Identifier: AGPL-3.0-or-later
4
openwifi_testmode_cmd(struct ieee80211_hw * hw,struct ieee80211_vif * vif,void * data,int len)5 static int openwifi_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void *data, int len)
6 {
7 struct openwifi_priv *priv = hw->priv;
8 struct nlattr *tb[OPENWIFI_ATTR_MAX + 1];
9 struct sk_buff *skb;
10 int err;
11 u32 tmp=-1, reg_cat, reg_addr, reg_val, reg_addr_idx, tsft_high, tsft_low;
12 int tmp_int;
13
14 err = nla_parse(tb, OPENWIFI_ATTR_MAX, data, len, openwifi_testmode_policy, NULL);
15 if (err)
16 return err;
17
18 if (!tb[OPENWIFI_ATTR_CMD])
19 return -EINVAL;
20
21 switch (nla_get_u32(tb[OPENWIFI_ATTR_CMD])) {
22 case OPENWIFI_CMD_SET_GAP:
23 if (!tb[OPENWIFI_ATTR_GAP])
24 return -EINVAL;
25 tmp = nla_get_u32(tb[OPENWIFI_ATTR_GAP]);
26 printk("%s XPU_REG_CSMA_CFG_write %08x (Check openwifi_conf_tx() in sdr.c to understand)\n", sdr_compatible_str, tmp);
27 xpu_api->XPU_REG_CSMA_CFG_write(tmp); // unit us
28 return 0;
29 case OPENWIFI_CMD_GET_GAP:
30 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
31 if (!skb)
32 return -ENOMEM;
33 tmp = xpu_api->XPU_REG_CSMA_CFG_read();
34 if (nla_put_u32(skb, OPENWIFI_ATTR_GAP, tmp))
35 goto nla_put_failure;
36 return cfg80211_testmode_reply(skb);
37 case OPENWIFI_CMD_SET_SLICE_IDX:
38 if (!tb[OPENWIFI_ATTR_SLICE_IDX])
39 return -EINVAL;
40 tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_IDX]);
41 printk("%s set openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp);
42 if (tmp == MAX_NUM_HW_QUEUE) {
43 printk("%s set openwifi slice_idx reset all queue counter.\n", sdr_compatible_str);
44 xpu_api->XPU_REG_MULTI_RST_write(1<<7); //bit7 reset the counter for all queues at the same time
45 xpu_api->XPU_REG_MULTI_RST_write(0<<7);
46 } else {
47 priv->slice_idx = tmp;
48 }
49 return 0;
50 case OPENWIFI_CMD_GET_SLICE_IDX:
51 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
52 if (!skb)
53 return -ENOMEM;
54 tmp = priv->slice_idx;
55 if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_IDX, tmp))
56 goto nla_put_failure;
57 printk("%s get openwifi slice_idx in hex: %08x\n", sdr_compatible_str, tmp);
58 return cfg80211_testmode_reply(skb);
59 case OPENWIFI_CMD_SET_ADDR:
60 if (!tb[OPENWIFI_ATTR_ADDR])
61 return -EINVAL;
62 tmp = nla_get_u32(tb[OPENWIFI_ATTR_ADDR]);
63 if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
64 printk("%s set openwifi slice_target_mac_addr(low32) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
65 return -EOPNOTSUPP;
66 } else {
67 printk("%s set openwifi slice_target_mac_addr(low32) in hex: %08x to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
68 priv->dest_mac_addr_queue_map[priv->slice_idx] = reverse32(tmp);
69 }
70 return 0;
71 case OPENWIFI_CMD_GET_ADDR:
72 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
73 if (!skb)
74 return -ENOMEM;
75 if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
76 tmp = -1;
77 } else {
78 tmp = reverse32(priv->dest_mac_addr_queue_map[priv->slice_idx]);
79 }
80 if (nla_put_u32(skb, OPENWIFI_ATTR_ADDR, tmp))
81 goto nla_put_failure;
82 printk("%s get openwifi slice_target_mac_addr(low32) in hex: %08x of slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
83 return cfg80211_testmode_reply(skb);
84
85 case OPENWIFI_CMD_SET_SLICE_TOTAL:
86 if (!tb[OPENWIFI_ATTR_SLICE_TOTAL])
87 return -EINVAL;
88 tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL]);
89 if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
90 printk("%s set SLICE_TOTAL(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
91 return -EOPNOTSUPP;
92 } else {
93 printk("%s set SLICE_TOTAL(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
94 xpu_api->XPU_REG_SLICE_COUNT_TOTAL_write((priv->slice_idx<<20)|tmp);
95 }
96 return 0;
97 case OPENWIFI_CMD_GET_SLICE_TOTAL:
98 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
99 if (!skb)
100 return -ENOMEM;
101 tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL_read());
102 printk("%s get SLICE_TOTAL(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20);
103 if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL, tmp))
104 goto nla_put_failure;
105 return cfg80211_testmode_reply(skb);
106
107 case OPENWIFI_CMD_SET_SLICE_START:
108 if (!tb[OPENWIFI_ATTR_SLICE_START])
109 return -EINVAL;
110 tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START]);
111 if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
112 printk("%s set SLICE_START(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
113 return -EOPNOTSUPP;
114 } else {
115 printk("%s set SLICE_START(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
116 xpu_api->XPU_REG_SLICE_COUNT_START_write((priv->slice_idx<<20)|tmp);
117 }
118 return 0;
119 case OPENWIFI_CMD_GET_SLICE_START:
120 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
121 if (!skb)
122 return -ENOMEM;
123 tmp = (xpu_api->XPU_REG_SLICE_COUNT_START_read());
124 printk("%s get SLICE_START(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20);
125 if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START, tmp))
126 goto nla_put_failure;
127 return cfg80211_testmode_reply(skb);
128
129 case OPENWIFI_CMD_SET_SLICE_END:
130 if (!tb[OPENWIFI_ATTR_SLICE_END])
131 return -EINVAL;
132 tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END]);
133 if (priv->slice_idx>=MAX_NUM_HW_QUEUE) {
134 printk("%s set SLICE_END(duration) WARNING: current slice idx %d is invalid!\n", sdr_compatible_str, priv->slice_idx);
135 return -EOPNOTSUPP;
136 } else {
137 printk("%s set SLICE_END(duration) %d usec to slice %d\n", sdr_compatible_str, tmp, priv->slice_idx);
138 xpu_api->XPU_REG_SLICE_COUNT_END_write((priv->slice_idx<<20)|tmp);
139 }
140 return 0;
141 case OPENWIFI_CMD_GET_SLICE_END:
142 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
143 if (!skb)
144 return -ENOMEM;
145 tmp = (xpu_api->XPU_REG_SLICE_COUNT_END_read());
146 printk("%s get SLICE_END(duration) %d usec of slice %d\n", sdr_compatible_str, tmp&0xFFFFF, tmp>>20);
147 if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END, tmp))
148 goto nla_put_failure;
149 return cfg80211_testmode_reply(skb);
150
151 // case OPENWIFI_CMD_SET_SLICE_TOTAL1:
152 // if (!tb[OPENWIFI_ATTR_SLICE_TOTAL1])
153 // return -EINVAL;
154 // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_TOTAL1]);
155 // printk("%s set SLICE_TOTAL1(duration) to %d usec\n", sdr_compatible_str, tmp);
156 // // xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_write(tmp);
157 // return 0;
158 // case OPENWIFI_CMD_GET_SLICE_TOTAL1:
159 // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
160 // if (!skb)
161 // return -ENOMEM;
162 // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_TOTAL1_read());
163 // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_TOTAL1, tmp))
164 // goto nla_put_failure;
165 // return cfg80211_testmode_reply(skb);
166
167 // case OPENWIFI_CMD_SET_SLICE_START1:
168 // if (!tb[OPENWIFI_ATTR_SLICE_START1])
169 // return -EINVAL;
170 // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_START1]);
171 // printk("%s set SLICE_START1(duration) to %d usec\n", sdr_compatible_str, tmp);
172 // // xpu_api->XPU_REG_SLICE_COUNT_START1_write(tmp);
173 // return 0;
174 // case OPENWIFI_CMD_GET_SLICE_START1:
175 // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
176 // if (!skb)
177 // return -ENOMEM;
178 // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_START1_read());
179 // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_START1, tmp))
180 // goto nla_put_failure;
181 // return cfg80211_testmode_reply(skb);
182
183 // case OPENWIFI_CMD_SET_SLICE_END1:
184 // if (!tb[OPENWIFI_ATTR_SLICE_END1])
185 // return -EINVAL;
186 // tmp = nla_get_u32(tb[OPENWIFI_ATTR_SLICE_END1]);
187 // printk("%s set SLICE_END1(duration) to %d usec\n", sdr_compatible_str, tmp);
188 // // xpu_api->XPU_REG_SLICE_COUNT_END1_write(tmp);
189 // return 0;
190 // case OPENWIFI_CMD_GET_SLICE_END1:
191 // skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
192 // if (!skb)
193 // return -ENOMEM;
194 // // tmp = (xpu_api->XPU_REG_SLICE_COUNT_END1_read());
195 // if (nla_put_u32(skb, OPENWIFI_ATTR_SLICE_END1, tmp))
196 // goto nla_put_failure;
197 // return cfg80211_testmode_reply(skb);
198
199 case OPENWIFI_CMD_SET_RSSI_TH:
200 if (!tb[OPENWIFI_ATTR_RSSI_TH])
201 return -EINVAL;
202 tmp = nla_get_u32(tb[OPENWIFI_ATTR_RSSI_TH]);
203 // printk("%s set RSSI_TH to %d\n", sdr_compatible_str, tmp);
204 // xpu_api->XPU_REG_LBT_TH_write(tmp);
205 // return 0;
206 printk("%s WARNING Please use command: sdrctl dev sdr0 set reg drv_xpu 0 reg_value! (1~2047, 0 means AUTO)!\n", sdr_compatible_str);
207 return -EOPNOTSUPP;
208 case OPENWIFI_CMD_GET_RSSI_TH:
209 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
210 if (!skb)
211 return -ENOMEM;
212 tmp_int = rssi_half_db_to_rssi_dbm(xpu_api->XPU_REG_LBT_TH_read(), priv->rssi_correction); //rssi_dbm
213 tmp = (-tmp_int);
214 if (nla_put_u32(skb, OPENWIFI_ATTR_RSSI_TH, tmp))
215 goto nla_put_failure;
216 return cfg80211_testmode_reply(skb);
217
218 case OPENWIFI_CMD_SET_TSF:
219 printk("openwifi_set_tsf_1");
220 if ( (!tb[OPENWIFI_ATTR_HIGH_TSF]) || (!tb[OPENWIFI_ATTR_LOW_TSF]) )
221 return -EINVAL;
222 printk("openwifi_set_tsf_2");
223 tsft_high = nla_get_u32(tb[OPENWIFI_ATTR_HIGH_TSF]);
224 tsft_low = nla_get_u32(tb[OPENWIFI_ATTR_LOW_TSF]);
225 xpu_api->XPU_REG_TSF_LOAD_VAL_write(tsft_high,tsft_low);
226 printk("%s openwifi_set_tsf: %08x%08x\n", sdr_compatible_str,tsft_high,tsft_low);
227 return 0;
228
229 case REG_CMD_SET:
230 if ( (!tb[REG_ATTR_ADDR]) || (!tb[REG_ATTR_VAL]) )
231 return -EINVAL;
232 reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]);
233 reg_val = nla_get_u32(tb[REG_ATTR_VAL]);
234 reg_cat = ((reg_addr>>16)&0xFFFF);
235 reg_addr = (reg_addr&0xFFFF);
236 reg_addr_idx = (reg_addr>>2);
237 printk("%s recv set cmd reg cat %d addr %08x val %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_val, reg_addr_idx);
238 if (reg_cat==SDRCTL_REG_CAT_RF) {
239 // printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str);
240 // return -EOPNOTSUPP;
241 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_RF_REG) {
242 priv->rf_reg_val[reg_addr_idx]=reg_val;
243 if (reg_addr_idx==RF_TX_REG_IDX_ATT) {//change the tx ON att (if a RF chain is ON)
244 tmp = ad9361_get_tx_atten(priv->ad9361_phy, 1);
245 printk("%s ad9361_get_tx_atten ant0 %d\n",sdr_compatible_str, tmp);
246 if (tmp<AD9361_RADIO_OFF_TX_ATT) {
247 err = ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT+reg_val, true, false, true);
248 if (err < 0) {
249 printk("%s WARNING ad9361_set_tx_atten ant0 %d FAIL!\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val);
250 return -EIO;
251 } else {
252 printk("%s ad9361_set_tx_atten ant0 %d OK\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val);
253 }
254 }
255 tmp = ad9361_get_tx_atten(priv->ad9361_phy, 2);
256 printk("%s ad9361_get_tx_atten ant1 %d\n",sdr_compatible_str, tmp);
257 if (tmp<AD9361_RADIO_OFF_TX_ATT) {
258 err = ad9361_set_tx_atten(priv->ad9361_phy, AD9361_RADIO_ON_TX_ATT+reg_val, false, true, true);
259 if (err < 0) {
260 printk("%s WARNING ad9361_set_tx_atten ant1 %d FAIL!\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val);
261 return -EIO;
262 } else {
263 printk("%s ad9361_set_tx_atten ant1 %d OK\n",sdr_compatible_str, AD9361_RADIO_ON_TX_ATT+reg_val);
264 }
265 }
266 } else if (reg_addr_idx==RF_TX_REG_IDX_FREQ_MHZ) { // apply the tx fo
267 clk_set_rate(priv->ad9361_phy->clks[TX_RFPLL], ( ((u64)1000000ull)*((u64)priv->rf_reg_val[RF_TX_REG_IDX_FREQ_MHZ]) )>>1 );
268 ad9361_tx_calibration(priv, priv->rf_reg_val[RF_TX_REG_IDX_FREQ_MHZ]);
269 printk("%s clk_set_rate TX_RFPLL %dMHz done\n",sdr_compatible_str, priv->rf_reg_val[RF_TX_REG_IDX_FREQ_MHZ]);
270 } else if (reg_addr_idx==RF_RX_REG_IDX_FREQ_MHZ) { // apply the rx fo
271 clk_set_rate(priv->ad9361_phy->clks[RX_RFPLL], ( ((u64)1000000ull)*((u64)priv->rf_reg_val[RF_RX_REG_IDX_FREQ_MHZ]) )>>1 );
272 openwifi_rf_rx_update_after_tuning(priv, priv->rf_reg_val[RF_RX_REG_IDX_FREQ_MHZ]);
273 printk("%s clk_set_rate RX_RFPLL %dMHz done\n",sdr_compatible_str, priv->rf_reg_val[RF_RX_REG_IDX_FREQ_MHZ]);
274 }
275 } else {
276 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
277 return -EOPNOTSUPP;
278 }
279 }
280 else if (reg_cat==SDRCTL_REG_CAT_RX_INTF)
281 rx_intf_api->reg_write(reg_addr,reg_val);
282 else if (reg_cat==SDRCTL_REG_CAT_TX_INTF)
283 tx_intf_api->reg_write(reg_addr,reg_val);
284 else if (reg_cat==SDRCTL_REG_CAT_RX)
285 openofdm_rx_api->reg_write(reg_addr,reg_val);
286 else if (reg_cat==SDRCTL_REG_CAT_TX)
287 openofdm_tx_api->reg_write(reg_addr,reg_val);
288 else if (reg_cat==SDRCTL_REG_CAT_XPU)
289 xpu_api->reg_write(reg_addr,reg_val);
290 else if (reg_cat==SDRCTL_REG_CAT_DRV_RX) {
291 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
292 if (reg_addr_idx==DRV_RX_REG_IDX_ANT_CFG) {
293 tmp = openwifi_set_antenna(hw, (priv->drv_tx_reg_val[reg_addr_idx]==0?1:2), (reg_val==0?1:2));
294 if (tmp) {
295 printk("%s WARNING openwifi_set_antenna return %d!\n", sdr_compatible_str, tmp);
296 return -EIO;
297 } else {
298 priv->drv_rx_reg_val[reg_addr_idx]=reg_val;
299 }
300 } else {
301 priv->drv_rx_reg_val[reg_addr_idx]=reg_val;
302 if (reg_addr_idx==DRV_RX_REG_IDX_DEMOD_TH) {
303 openofdm_rx_api->OPENOFDM_RX_REG_POWER_THRES_write((OPENOFDM_RX_DC_RUNNING_SUM_TH_INIT<<16)|rssi_dbm_to_rssi_half_db((reg_val==0?OPENOFDM_RX_RSSI_DBM_TH_DEFAULT:(-reg_val)), priv->rssi_correction));
304 }
305 }
306 } else {
307 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
308 return -EOPNOTSUPP;
309 }
310 }
311 else if (reg_cat==SDRCTL_REG_CAT_DRV_TX) {
312 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
313 if ((reg_addr_idx == DRV_TX_REG_IDX_RATE || reg_addr_idx == DRV_TX_REG_IDX_RATE_HT) &&
314 (reg_val != 0 && (!((reg_val&0xF)>=4 && (reg_val&0xF)<=11)) ) ) {
315 printk("%s WARNING rate override value should be 0 or 4~11!\n", sdr_compatible_str);
316 return -EOPNOTSUPP;
317 } else {
318 if (reg_addr_idx==DRV_TX_REG_IDX_ANT_CFG) {
319 tmp = openwifi_set_antenna(hw, reg_val+1, priv->drv_rx_reg_val[reg_addr_idx]+1);
320 if (tmp) {
321 printk("%s WARNING openwifi_set_antenna return %d!\n", sdr_compatible_str, tmp);
322 return -EIO;
323 } else {
324 priv->drv_tx_reg_val[reg_addr_idx]=reg_val;
325 }
326 } else {
327 priv->drv_tx_reg_val[reg_addr_idx]=reg_val;
328 }
329 }
330 } else {
331 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
332 return -EOPNOTSUPP;
333 }
334 }
335 else if (reg_cat==SDRCTL_REG_CAT_DRV_XPU) {
336 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
337 priv->drv_xpu_reg_val[reg_addr_idx]=reg_val;
338 if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) {
339 if (reg_val) {
340 tmp_int = (-reg_val); // rssi_dbm
341 tmp = rssi_dbm_to_rssi_half_db(tmp_int, priv->rssi_correction);
342 xpu_api->XPU_REG_LBT_TH_write( tmp );
343 printk("%s override FPGA LBT threshold to %d(%ddBm). The last_auto_fpga_lbt_th %d(%ddBm). rssi corr %d (%d/%dMHz)\n", sdr_compatible_str, tmp, tmp_int, priv->last_auto_fpga_lbt_th, rssi_half_db_to_rssi_dbm(priv->last_auto_fpga_lbt_th, priv->rssi_correction), priv->rssi_correction, priv->actual_tx_lo, priv->actual_rx_lo);
344 } else {
345 xpu_api->XPU_REG_LBT_TH_write(priv->last_auto_fpga_lbt_th);
346 printk("%s Restore last_auto_fpga_lbt_th %d(%ddBm) to FPGA. ad9361_rf_set_channel will take control. rssi corr %d (%d/%dMHz)\n", sdr_compatible_str, priv->last_auto_fpga_lbt_th, rssi_half_db_to_rssi_dbm(priv->last_auto_fpga_lbt_th, priv->rssi_correction), priv->rssi_correction, priv->actual_tx_lo, priv->actual_rx_lo);
347 }
348 }
349 } else {
350 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
351 return -EOPNOTSUPP;
352 }
353 }
354 else {
355 printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat);
356 return -EOPNOTSUPP;
357 }
358
359 return 0;
360 case REG_CMD_GET:
361 skb = (struct sk_buff *)cfg80211_testmode_alloc_reply_skb(hw->wiphy, nla_total_size(sizeof(u32)));
362 if (!skb)
363 return -ENOMEM;
364 reg_addr = nla_get_u32(tb[REG_ATTR_ADDR]);
365 reg_cat = ((reg_addr>>16)&0xFFFF);
366 reg_addr = (reg_addr&0xFFFF);
367 reg_addr_idx = (reg_addr>>2);
368 printk("%s recv get cmd reg cat %d addr %08x idx %d\n", sdr_compatible_str, reg_cat, reg_addr, reg_addr_idx);
369 if (reg_cat==SDRCTL_REG_CAT_RF) {
370 // printk("%s WARNING reg cat 1 (rf) is not supported yet!\n", sdr_compatible_str);
371 // tmp = 0xFFFFFFFF;
372 // return -EOPNOTSUPP;
373 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_RF_REG) {
374 tmp = priv->rf_reg_val[reg_addr_idx];
375 } else {
376 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
377 return -EOPNOTSUPP;
378 }
379 }
380 else if (reg_cat==SDRCTL_REG_CAT_RX_INTF)
381 tmp = rx_intf_api->reg_read(reg_addr);
382 else if (reg_cat==SDRCTL_REG_CAT_TX_INTF)
383 tmp = tx_intf_api->reg_read(reg_addr);
384 else if (reg_cat==SDRCTL_REG_CAT_RX)
385 tmp = openofdm_rx_api->reg_read(reg_addr);
386 else if (reg_cat==SDRCTL_REG_CAT_TX)
387 tmp = openofdm_tx_api->reg_read(reg_addr);
388 else if (reg_cat==SDRCTL_REG_CAT_XPU)
389 tmp = xpu_api->reg_read(reg_addr);
390 else if (reg_cat==SDRCTL_REG_CAT_DRV_RX) {
391 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
392 tmp = priv->drv_rx_reg_val[reg_addr_idx];
393 if (reg_addr_idx==DRV_RX_REG_IDX_ANT_CFG)
394 openwifi_get_antenna(hw, &tsft_high, &tsft_low);
395 } else {
396 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
397 return -EOPNOTSUPP;
398 }
399 }
400 else if (reg_cat==SDRCTL_REG_CAT_DRV_TX) {
401 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
402 tmp = priv->drv_tx_reg_val[reg_addr_idx];
403 if (reg_addr_idx==DRV_TX_REG_IDX_ANT_CFG)
404 openwifi_get_antenna(hw, &tsft_high, &tsft_low);
405 } else {
406 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
407 return -EOPNOTSUPP;
408 }
409 }
410 else if (reg_cat==SDRCTL_REG_CAT_DRV_XPU) {
411 if (reg_addr_idx>=0 && reg_addr_idx<MAX_NUM_DRV_REG) {
412 if (reg_addr_idx==DRV_XPU_REG_IDX_LBT_TH) {
413 tmp = xpu_api->XPU_REG_LBT_TH_read();//rssi_half_db
414 tmp_int = rssi_half_db_to_rssi_dbm(tmp, priv->rssi_correction); //rssi_dbm
415 printk("%s FPGA LBT threshold %d(%ddBm). The last_auto_fpga_lbt_th %d(%ddBm). rssi corr %d (%d/%dMHz)\n", sdr_compatible_str, tmp, tmp_int, priv->last_auto_fpga_lbt_th, rssi_half_db_to_rssi_dbm(priv->last_auto_fpga_lbt_th, priv->rssi_correction), priv->rssi_correction, priv->actual_tx_lo, priv->actual_rx_lo);
416 }
417 tmp = priv->drv_xpu_reg_val[reg_addr_idx];
418 } else {
419 printk("%s WARNING reg_addr_idx %d is out of range!\n", sdr_compatible_str, reg_addr_idx);
420 return -EOPNOTSUPP;
421 }
422 }
423 else {
424 printk("%s WARNING reg cat %d is not supported yet!\n", sdr_compatible_str, reg_cat);
425 return -EOPNOTSUPP;
426 }
427
428 if (nla_put_u32(skb, REG_ATTR_VAL, tmp))
429 goto nla_put_failure;
430 return cfg80211_testmode_reply(skb);
431
432 default:
433 return -EOPNOTSUPP;
434 }
435
436 nla_put_failure:
437 dev_kfree_skb(skb);
438 return -ENOBUFS;
439 }
440