xref: /openwifi/doc/README.md (revision 10d539bee3e76d8d1b6bc8ab52e13f9947492f3e)
1*10d539beSJiao Xianjun# openwifi document
22ee67178SXianjun Jiao<img src="./openwifi-detail.jpg" width="1100">
32ee67178SXianjun Jiao
42ee67178SXianjun JiaoAbove figure shows software and hardware/FPGA modules that compose the openwifi design. The module name is equal/similar to the source code file name. Driver modules source code are in openwifi/driver/. FPGA modules source code are in openwifi-hw repository. The user space tool sdrctl source code are in openwifi/user_space/sdrctl_src/.
52ee67178SXianjun Jiao
65f436b3cSJiao Xianjun- [driver and software overall principle](#driver-and-software-overall-principle)
7*10d539beSJiao Xianjun- [sdrctl command](#sdrctl-command)
85f436b3cSJiao Xianjun- [rx packet flow and filtering config](#rx-packet-flow-and-filtering-config)
95f436b3cSJiao Xianjun- [tx packet flow and config](#tx-packet-flow-and-config)
105f436b3cSJiao Xianjun
115f436b3cSJiao Xianjun## driver and software overall principle
125f436b3cSJiao Xianjun
135f436b3cSJiao Xianjun[Linux mac80211 subsystem](https://www.kernel.org/doc/html/v4.16/driver-api/80211/mac80211.html), as a part of [Linux wireless](https://wireless.wiki.kernel.org/en/developers/documentation/mac80211) defines a set of APIs ([ieee80211_ops](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#c.ieee80211_ops)) to rule the Wi-Fi chip driver behavior. SoftMAC Wi-Fi chip driver implements (part of) APIs. That is why Linux can support so many types of Wi-Fi chip.
145f436b3cSJiao Xianjun
155f436b3cSJiao Xianjunopenwifi driver (sdr.c) implements following APIs of ieee80211_ops:
165f436b3cSJiao Xianjun-	**tx**. It is called when upper layer has a packet to send
175f436b3cSJiao Xianjun-	**start**. It is called when NIC up. (ifconfig sdr0 up)
185f436b3cSJiao Xianjun-	**stop**. It is called when NIC down. (ifconfig sdr0 down)
195f436b3cSJiao Xianjun-	**add_interface**. It is called when NIC is created
205f436b3cSJiao Xianjun-	**remove_interface**. It is called when NIC is deleted
215f436b3cSJiao Xianjun-	**config**. It is called when upper layer wants to change channel/frequency (like the scan operation)
225f436b3cSJiao Xianjun-	**bss_info_changed**. It is called when upper layer believe some BSS parameters need to be changed (BSSID, TX power, beacon interval, etc)
235f436b3cSJiao Xianjun-	**conf_tx**. It is called when upper layer needs to config/change some tx parameters (AIFS, CW_MIN, CW_MAX, TXOP, etc)
245f436b3cSJiao Xianjun-	**prepare_multicast**.
255f436b3cSJiao Xianjun-	**configure_filter**. It is called when upper layer wants to config/change the [frame filtering](https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#frame-filtering) rule in FPGA.
265f436b3cSJiao Xianjun-	**rfkill_poll**. It is called when upper layer wants to know the RF status (ON/OFF).
275f436b3cSJiao Xianjun-	**get_tsf**. It is called when upper layer wants to get 64bit FPGA timer value (TSF - Timing synchronization function)
285f436b3cSJiao Xianjun-	**set_tsf**. It is called when upper layer wants to set 64bit FPGA timer value
295f436b3cSJiao Xianjun-	**reset_tsf**. It is called when upper layer wants to reset 64bit FPGA timer value
305f436b3cSJiao Xianjun-	**set_rts_threshold**. It is called when upper layer wants to change the threshold (packet length) for turning on RTS mechanism
315f436b3cSJiao Xianjun-	**testmode_cmd**. It is called when upper layer has test command for us. [sdrctl command](#sdrctl-command) message is handled by this function.
325f436b3cSJiao Xianjun
335f436b3cSJiao XianjunAbove APIs are called actively by upper layer. When they are called, the driver (sdr.c) will do necessary job over SDR platform. If necessary the driver will call other component drivers (tx_intf_api/rx_intf_api/openofdm_tx_api/openofdm_rx_api/xpu_api) for helping.
345f436b3cSJiao Xianjun
35*10d539beSJiao XianjunFor receiving a packet from the air, FPGA will raise interrupt (if the frame filtering rule allows) to Linux, then the function openwifi_rx_interrupt() of openwifi driver (sdr.c) will be triggered. In that function, ieee80211_rx_irqsafe() API is used to give the packet to upper layer.
36*10d539beSJiao Xianjun
37*10d539beSJiao XianjunThe packet sending is initiated by upper layer. After the packet is sent by the driver to FPGA, the upper layer will expect a sending report from the driver. Each time FPGA send a packet, an interrupt will be raised to Linux and trigger openwifi_tx_interrupt(). This function will report the sending result (fail? succeed? number of retransmissions, etc.) to upper layer via ieee80211_tx_status_irqsafe() API.
385f436b3cSJiao Xianjun
395f436b3cSJiao Xianjun## sdrctl command
402ee67178SXianjun Jiao
412ee67178SXianjun JiaoBesides the Linux native Wi-Fi control programs, such as ifconfig/iw/iwconfig/iwlist/wpa_supplicant/hostapd/etc, openwifi offers a user space tool sdrctl to access openwifi specific functionalities. sdrctl is implemented as nl80211 testmode command and communicates with openwifi driver (function openwifi_testmode_cmd in sdr.c) via Linux nl80211--cfg80211--mac80211 path
422ee67178SXianjun Jiao
435f436b3cSJiao Xianjun### get and set a parameter
442ee67178SXianjun Jiao```
452ee67178SXianjun Jiaosdrctl dev sdr0 get para_name
462ee67178SXianjun Jiaosdrctl dev sdr0 set para_name value
472ee67178SXianjun Jiao```
482ee67178SXianjun Jiaopara_name|meaning|example
492ee67178SXianjun Jiao---------|-------|----
50*10d539beSJiao Xianjunaddr0|target MAC address of tx slice 0|32bit. for address 6c:fd:b9:4c:b1:c1, you set b94cb1c1
512ee67178SXianjun Jiaoslice_total0|tx slice 0 cycle length in us|for length 50ms, you set 49999
522ee67178SXianjun Jiaoslice_start0|tx slice 0 cycle start time in us|for start at 10ms, you set 10000
532ee67178SXianjun Jiaoslice_end0|  tx slice 0 cycle end   time in us|for end   at 40ms, you set 39999
54*10d539beSJiao Xianjunaddr1|target MAC address of tx slice 1|32bit. for address 6c:fd:b9:4c:b1:c1, you set b94cb1c1
552ee67178SXianjun Jiaoslice_total1|tx slice 1 cycle length in us|for length 50ms, you set 49999
562ee67178SXianjun Jiaoslice_start1|tx slice 1 cycle start time in us|for start at 10ms, you set 10000
572ee67178SXianjun Jiaoslice_end1|  tx slice 1 cycle end   time in us|for end   at 40ms, you set 39999
582ee67178SXianjun Jiao
595f436b3cSJiao Xianjun### get and set a register of a module
602ee67178SXianjun Jiao```
612ee67178SXianjun Jiaosdrctl dev sdr0 get reg module_name reg_idx
622ee67178SXianjun Jiaosdrctl dev sdr0 set reg module_name reg_idx reg_value
632ee67178SXianjun Jiao```
642ee67178SXianjun Jiaomodule_name drv_rx/drv_tx/drv_xpu refer to driver modules. Related registers are defined in sdr.h (drv_rx_reg_val/drv_tx_reg_val/drv_xpu_reg_val)
652ee67178SXianjun Jiao
662ee67178SXianjun Jiaomodule_name rf/rx_intf/tx_intf/rx/tx/xpu refer to RF (ad9xxx front-end) and FPGA (rx_intf/tx_intf/openofdm_rx/openofdm_tx/xpu) modules. Related register addresses are defined in hw_def.h.
672ee67178SXianjun Jiao
682ee67178SXianjun Jiaomodule_name: drv_rx
692ee67178SXianjun Jiao
702ee67178SXianjun Jiaoreg_idx|meaning|example
712ee67178SXianjun Jiao-------|-------|----
722ee67178SXianjun Jiao1|rx antenna selection|0:rx1, 1:rx2. After this command, you should down and up sdr0 by ifconfig, but not reload sdr0 driver via ./wgd.sh
732ee67178SXianjun Jiao
742ee67178SXianjun Jiaomodule_name: drv_tx
752ee67178SXianjun Jiao
762ee67178SXianjun Jiaoreg_idx|meaning|example
772ee67178SXianjun Jiao-------|-------|----
782ee67178SXianjun Jiao0|override Linux rate control of tx unicast data packet|4:6M, 5:9M, 6:12M, 7:18M, 8:24M, 9:36M, 10:48M, 11:54M
792ee67178SXianjun Jiao1|tx antenna selection|0:tx1, 1:tx2. After this command, you should down and up sdr0 by ifconfig, but not reload sdr0 driver via ./wgd.sh
802ee67178SXianjun Jiao
812ee67178SXianjun Jiaomodule_name: drv_xpu
822ee67178SXianjun Jiao
832ee67178SXianjun Jiaoreg_idx|meaning|example
842ee67178SXianjun Jiao-------|-------|----
852ee67178SXianjun Jiaox|x|x
862ee67178SXianjun Jiao
872ee67178SXianjun Jiaomodule_name: rf
882ee67178SXianjun Jiao
892ee67178SXianjun Jiaoreg_idx|meaning|example
902ee67178SXianjun Jiao-------|-------|----
912ee67178SXianjun Jiaox|x|x
922ee67178SXianjun Jiao
932ee67178SXianjun Jiaomodule_name: rx_intf
942ee67178SXianjun Jiao
952ee67178SXianjun Jiaoreg_idx|meaning|example
962ee67178SXianjun Jiao-------|-------|----
972ee67178SXianjun Jiao2|enable/disable rx interrupt|256(0x100):disable, 0:enable
982ee67178SXianjun Jiao
992ee67178SXianjun Jiaomodule_name: tx_intf
1002ee67178SXianjun Jiao
1012ee67178SXianjun Jiaoreg_idx|meaning|example
1022ee67178SXianjun Jiao-------|-------|----
1032ee67178SXianjun Jiao13|tx I/Q digital gain before DUC|current optimal value: 237
1042ee67178SXianjun Jiao14|enable/disable tx interrupt|196672(0x30040):disable, 64(0x40):enable
1052ee67178SXianjun Jiao
1062ee67178SXianjun Jiaomodule_name: rx
1072ee67178SXianjun Jiao
1082ee67178SXianjun Jiaoreg_idx|meaning|example
1092ee67178SXianjun Jiao-------|-------|----
1102ee67178SXianjun Jiao20|history of PHY rx state|read only. If the last digit readback is always 3, it means the Viterbi decoder stops working
1112ee67178SXianjun Jiao
1122ee67178SXianjun Jiaomodule_name: tx
1132ee67178SXianjun Jiao
1142ee67178SXianjun Jiaoreg_idx|meaning|example
1152ee67178SXianjun Jiao-------|-------|----
1162ee67178SXianjun Jiao1|pilot scrambler initial state|lowest 7 bits are used. 0x7E by default in openofdm_tx.c
1172ee67178SXianjun Jiao2|data  scrambler initial state|lowest 7 bits are used. 0x7F by default in openofdm_tx.c
1182ee67178SXianjun Jiao
1192ee67178SXianjun Jiaomodule_name: xpu
1202ee67178SXianjun Jiao
1212ee67178SXianjun Jiaoreg_idx|meaning|example
1222ee67178SXianjun Jiao-------|-------|----
1232ee67178SXianjun Jiao2|TSF timer low  32bit write|only write this register won't trigger the TSF timer reload. should use together with register for high 32bit
1242ee67178SXianjun Jiao3|TSF timer high 32bit write|falling edge of MSB will trigger the TSF timer reload, which means write '1' then '0' to MSB
1252ee67178SXianjun Jiao4|band and channel number setting|see enum openwifi_band in hw_def.h. it will be set automatically by Linux. normally you shouldn't set it
126*10d539beSJiao Xianjun11|max number of retransmission in FPGA|normally number of retransmissions controlled by Linux in real-time. If you write non-zeros value to this register, it will override Linux real-time setting
1272ee67178SXianjun Jiao19|CSMA enable/disable|3758096384(0xe0000000): disable, 3:enable
1282ee67178SXianjun Jiao20|tx slice 0 cycle length in us|for length 50ms, you set 49999
1292ee67178SXianjun Jiao21|tx slice 0 cycle start time in us|for start at 10ms, you set 10000
1302ee67178SXianjun Jiao22|tx slice 0 cycle end   time in us|for end   at 40ms, you set 39999
1312ee67178SXianjun Jiao23|tx slice 1 cycle length in us|for length 50ms, you set 49999
1322ee67178SXianjun Jiao24|tx slice 1 cycle start time in us|for start at 10ms, you set 10000
1332ee67178SXianjun Jiao25|tx slice 1 cycle end   time in us|for end   at 40ms, you set 39999
1342ee67178SXianjun Jiao27|FPGA packet filter config|check openwifi_configure_filter in sdr.c. also: https://www.kernel.org/doc/html/v4.9/80211/mac80211.html#frame-filtering
1352ee67178SXianjun Jiao28|BSSID address low  32bit for BSSID filtering|normally it is set by Linux in real-time automatically
1362ee67178SXianjun Jiao29|BSSID address high 32bit for BSSID filtering|normally it is set by Linux in real-time automatically
1372ee67178SXianjun Jiao30|openwifi MAC address low  32bit|
1382ee67178SXianjun Jiao31|openwifi MAC address high 32bit|check XPU_REG_MAC_ADDR_write in sdr.c to see how we set MAC address to FPGA when NIC start
1392ee67178SXianjun Jiao58|TSF runtime value low  32bit|read only
1402ee67178SXianjun Jiao59|TSF runtime value high 32bit|read only
1415f436b3cSJiao Xianjun
1425f436b3cSJiao Xianjun## rx packet flow and filtering config
1435f436b3cSJiao Xianjun
144*10d539beSJiao XianjunWhen FPGA received a packet, no matter the FCS/CRC is correct or not it will raise interrupt to Linux if the frame filtering full is met. openwifi_rx_interrupt() function in sdr.c will be triggered to do necessary operation and give the content to upper layer (Linux mac80211 subsystem).
1455f436b3cSJiao Xianjun
146*10d539beSJiao Xianjun- frame filtering
147*10d539beSJiao Xianjun
148*10d539beSJiao XianjunBecause the FPGA frame filtering configuration is done in real-time by function openwifi_configure_filter() in sdr.c, you may not have all packet type you want even if you put your sdr0 to sniffing mode. But you do have the chance to do so by changing the filter_flag in openwifi_configure_filter() to override the frame filtering in FPGA with MONITOR_ALL. The filter_flag together with HIGH_PRIORITY_DISCARD_FLAG finally go to pkt_filter_ctl.v of xpu module in FPGA, and control how FPGA does frame filtering.
149*10d539beSJiao Xianjun
150*10d539beSJiao Xianjun- main rx interrupt operations in openwifi_rx_interrupt()
151*10d539beSJiao Xianjun  - get raw content from DMA buffer. When Linux receives interrupt from FPGA rx_intf module, that means the content has been ready in Linux DMA buffer
152*10d539beSJiao Xianjun  - parse extra information inserted by FPGA in the DMA buffer
153*10d539beSJiao Xianjun    - TSF timer value
154*10d539beSJiao Xianjun    - raw RSSI value that will be converted to actual RSSI in dBm by different correction in different band
155*10d539beSJiao Xianjun    - packet length and MCS
156*10d539beSJiao Xianjun    - FCS is valid or not
157*10d539beSJiao Xianjun  - send packet content and necessary extra information to upper layer via ieee80211_rx_irqsafe()
1585f436b3cSJiao Xianjun
1595f436b3cSJiao Xianjun## tx packet flow and config
1605f436b3cSJiao Xianjun
161*10d539beSJiao XianjunLinux mac80211 subsystem calls openwifi_tx() to initiate a packet sending.
162*10d539beSJiao Xianjun
163*10d539beSJiao Xianjun- main operations in openwifi_tx()
164*10d539beSJiao Xianjun  - get necessary information from the packet header (struct ieee80211_hdr) for future FPGA configuration use
165*10d539beSJiao Xianjun    - packet length and MCS
166*10d539beSJiao Xianjun    - unicast or broadcast? does it need ACK? how many retransmissions are needed to be done by FPGA in case ACK is not received in time?
167*10d539beSJiao Xianjun    - which time slice in FPGA the packet should go?
168*10d539beSJiao Xianjun    - should RTS-CTS be used? (Send RTS and wait for CTS before actually send the data packet)
169*10d539beSJiao Xianjun    - should CTS-to-self be used? (Send CTS-to-self packet before sending the data packet. You can force this on by force_use_cts_protect = true;)
170*10d539beSJiao Xianjun    - should a sequence number be set for this packet?
171*10d539beSJiao Xianjun  - generate SIGNAL field according to length and MCS information. Insert it before the packet for the future openofdm_tx use
172*10d539beSJiao Xianjun  - generate FPGA/PHY sequence number (priv->phy_tx_sn) for internal use (between Linux and FPGA)
173*10d539beSJiao Xianjun  - config FPGA register according to the above information to make sure FPGA do correct service according to the packet specific requirement.
174*10d539beSJiao Xianjun  - fire DMA transmission from Linux to one of FPGA tx queues. The packet may not be sent immediately if there are still some packets in FPGA tx queue (FPGA does the queue packet transmission according to channel and low MAC state)
175*10d539beSJiao Xianjun
176*10d539beSJiao XianjunEach time when FPGA send a packet, an interrupt will be raised to Linux reporting the packet sending result. This interrupt handler is openwifi_tx_interrupt().
177*10d539beSJiao Xianjun
178*10d539beSJiao Xianjun- main operations in openwifi_tx_interrupt()
179*10d539beSJiao Xianjun  - get necessary information from the FPGA of the packet just sent
180*10d539beSJiao Xianjun    - packet length and sequence number
181*10d539beSJiao Xianjun    - packet sending result: packet is sent successfully (FPGA receive ACK for this packet) or not. How many retransmissions are used for the packet sending (in case FPGA doesn't receive ACK for several times)
182*10d539beSJiao Xianjun  - send above information to upper layer (Linux mac80211 subsystem) via ieee80211_tx_status_irqsafe()
183