From 478b2a6ab05175e7c6c5fe7f7b5a8acff93245a3 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 10 Jan 2019 20:43:15 -0500 Subject: [PATCH] realtekwifi: Upgrade to FreeBSD 12. This driver was completely rewritten and merged with its USB counterpart in FreeBSD 12. I've imported the USB code, even though it's not compiled in at all, because it's more than likely I'll get around to USB WiFi support before FreeBSD 13 comes... Untested, because I don't have one of these PCI devices. --- .../drivers/network/wlan/realtekwifi/Jamfile | 42 +- .../wlan/realtekwifi/dev/rtwn/if_rtwn.c | 4587 ++++++----------- .../realtekwifi/dev/rtwn/if_rtwn_beacon.c | 269 + .../realtekwifi/dev/rtwn/if_rtwn_beacon.h | 28 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_calib.c | 128 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_calib.h | 24 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_cam.c | 364 ++ .../wlan/realtekwifi/dev/rtwn/if_rtwn_cam.h | 30 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_debug.h | 58 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.c | 265 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.h | 25 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_fw.c | 224 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_fw.h | 59 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_nop.h | 69 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_ridx.h | 95 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_rx.c | 517 ++ .../wlan/realtekwifi/dev/rtwn/if_rtwn_rx.h | 39 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_task.c | 122 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_task.h | 27 + .../wlan/realtekwifi/dev/rtwn/if_rtwn_tx.c | 340 ++ .../wlan/realtekwifi/dev/rtwn/if_rtwn_tx.h | 31 + .../wlan/realtekwifi/dev/rtwn/if_rtwnreg.h | 2165 +------- .../wlan/realtekwifi/dev/rtwn/if_rtwnvar.h | 635 +++ .../wlan/realtekwifi/dev/rtwn/opt_wlan.h | 1 + .../dev/rtwn/pci/rtwn_pci_attach.c | 793 +++ .../dev/rtwn/pci/rtwn_pci_attach.h | 48 + .../realtekwifi/dev/rtwn/pci/rtwn_pci_reg.c | 123 + .../realtekwifi/dev/rtwn/pci/rtwn_pci_reg.h | 30 + .../realtekwifi/dev/rtwn/pci/rtwn_pci_rx.c | 317 ++ .../realtekwifi/dev/rtwn/pci/rtwn_pci_rx.h | 27 + .../realtekwifi/dev/rtwn/pci/rtwn_pci_tx.c | 272 + .../realtekwifi/dev/rtwn/pci/rtwn_pci_tx.h | 25 + .../realtekwifi/dev/rtwn/pci/rtwn_pci_var.h | 142 + .../wlan/realtekwifi/dev/rtwn/rtl8188e/r88e.h | 96 + .../dev/rtwn/rtl8188e/r88e_beacon.c | 62 + .../dev/rtwn/rtl8188e/r88e_calib.c | 67 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_chan.c | 153 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_fw.c | 225 + .../dev/rtwn/rtl8188e/r88e_fw_cmd.h | 84 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_init.c | 158 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_led.c | 68 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_priv.h | 230 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_reg.h | 91 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_rf.c | 60 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_rom.c | 85 + .../dev/rtwn/rtl8188e/r88e_rom_defs.h | 29 + .../dev/rtwn/rtl8188e/r88e_rom_image.h | 60 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_rx.c | 229 + .../dev/rtwn/rtl8188e/r88e_rx_desc.h | 100 + .../realtekwifi/dev/rtwn/rtl8188e/r88e_tx.c | 79 + .../dev/rtwn/rtl8188e/r88e_tx_desc.h | 38 + .../realtekwifi/dev/rtwn/rtl8188e/usb/r88eu.h | 39 + .../dev/rtwn/rtl8188e/usb/r88eu_attach.c | 218 + .../dev/rtwn/rtl8188e/usb/r88eu_init.c | 224 + .../dev/rtwn/rtl8188e/usb/r88eu_reg.h | 27 + .../dev/rtwn/rtl8188e/usb/r88eu_rx.c | 74 + .../realtekwifi/dev/rtwn/rtl8192c/pci/r92ce.h | 74 + .../dev/rtwn/rtl8192c/pci/r92ce_attach.c | 265 + .../dev/rtwn/rtl8192c/pci/r92ce_calib.c | 386 ++ .../dev/rtwn/rtl8192c/pci/r92ce_fw.c | 75 + .../dev/rtwn/rtl8192c/pci/r92ce_init.c | 323 ++ .../dev/rtwn/rtl8192c/pci/r92ce_led.c | 67 + .../dev/rtwn/rtl8192c/pci/r92ce_priv.h | 182 + .../dev/rtwn/rtl8192c/pci/r92ce_reg.h | 103 + .../dev/rtwn/rtl8192c/pci/r92ce_rx.c | 132 + .../dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h | 41 + .../dev/rtwn/rtl8192c/pci/r92ce_tx.c | 115 + .../dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h | 55 + .../wlan/realtekwifi/dev/rtwn/rtl8192c/r92c.h | 122 + .../dev/rtwn/rtl8192c/r92c_attach.c | 80 + .../dev/rtwn/rtl8192c/r92c_beacon.c | 86 + .../dev/rtwn/rtl8192c/r92c_calib.c | 113 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_chan.c | 351 ++ .../realtekwifi/dev/rtwn/rtl8192c/r92c_fw.c | 520 ++ .../dev/rtwn/rtl8192c/r92c_fw_cmd.h | 148 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_init.c | 343 ++ .../realtekwifi/dev/rtwn/rtl8192c/r92c_llt.c | 73 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_priv.h | 408 ++ .../realtekwifi/dev/rtwn/rtl8192c/r92c_reg.h | 879 ++++ .../realtekwifi/dev/rtwn/rtl8192c/r92c_rf.c | 93 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_rom.c | 139 + .../dev/rtwn/rtl8192c/r92c_rom_defs.h | 57 + .../dev/rtwn/rtl8192c/r92c_rom_image.h | 69 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_rx.c | 147 + .../dev/rtwn/rtl8192c/r92c_rx_desc.h | 100 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_tx.c | 434 ++ .../dev/rtwn/rtl8192c/r92c_tx_desc.h | 122 + .../realtekwifi/dev/rtwn/rtl8192c/r92c_var.h | 83 + .../realtekwifi/dev/rtwn/rtl8192c/usb/r92cu.h | 56 + .../dev/rtwn/rtl8192c/usb/r92cu_attach.c | 247 + .../dev/rtwn/rtl8192c/usb/r92cu_init.c | 391 ++ .../dev/rtwn/rtl8192c/usb/r92cu_led.c | 66 + .../dev/rtwn/rtl8192c/usb/r92cu_priv.h | 322 ++ .../dev/rtwn/rtl8192c/usb/r92cu_reg.h | 65 + .../dev/rtwn/rtl8192c/usb/r92cu_rx.c | 63 + .../dev/rtwn/rtl8192c/usb/r92cu_tx.c | 64 + .../dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h | 45 + .../wlan/realtekwifi/dev/rtwn/rtl8192e/r92e.h | 82 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_chan.c | 233 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_fw.c | 137 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_init.c | 385 ++ .../realtekwifi/dev/rtwn/rtl8192e/r92e_led.c | 69 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_priv.h | 262 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_reg.h | 47 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_rf.c | 88 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_rom.c | 144 + .../dev/rtwn/rtl8192e/r92e_rom_defs.h | 42 + .../dev/rtwn/rtl8192e/r92e_rom_image.h | 87 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_rx.c | 97 + .../realtekwifi/dev/rtwn/rtl8192e/r92e_var.h | 54 + .../realtekwifi/dev/rtwn/rtl8192e/usb/r92eu.h | 43 + .../dev/rtwn/rtl8192e/usb/r92eu_attach.c | 204 + .../dev/rtwn/rtl8192e/usb/r92eu_init.c | 96 + .../dev/rtwn/rtl8192e/usb/r92eu_reg.h | 36 + .../wlan/realtekwifi/dev/rtwn/rtl8812a/r12a.h | 142 + .../dev/rtwn/rtl8812a/r12a_beacon.c | 96 + .../dev/rtwn/rtl8812a/r12a_calib.c | 286 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_caps.c | 120 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_chan.c | 601 +++ .../realtekwifi/dev/rtwn/rtl8812a/r12a_fw.c | 194 + .../dev/rtwn/rtl8812a/r12a_fw_cmd.h | 123 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_init.c | 486 ++ .../realtekwifi/dev/rtwn/rtl8812a/r12a_led.c | 72 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_priv.h | 852 +++ .../realtekwifi/dev/rtwn/rtl8812a/r12a_reg.h | 246 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_rf.c | 110 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_rom.c | 222 + .../dev/rtwn/rtl8812a/r12a_rom_defs.h | 43 + .../dev/rtwn/rtl8812a/r12a_rom_image.h | 134 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_rx.c | 329 ++ .../dev/rtwn/rtl8812a/r12a_rx_desc.h | 87 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_tx.c | 446 ++ .../dev/rtwn/rtl8812a/r12a_tx_desc.h | 149 + .../realtekwifi/dev/rtwn/rtl8812a/r12a_var.h | 126 + .../realtekwifi/dev/rtwn/rtl8812a/usb/r12au.h | 53 + .../dev/rtwn/rtl8812a/usb/r12au_attach.c | 298 ++ .../dev/rtwn/rtl8812a/usb/r12au_init.c | 200 + .../dev/rtwn/rtl8812a/usb/r12au_reg.h | 35 + .../dev/rtwn/rtl8812a/usb/r12au_rx.c | 89 + .../dev/rtwn/rtl8812a/usb/r12au_tx.c | 75 + .../dev/rtwn/rtl8812a/usb/r12au_tx_desc.h | 56 + .../wlan/realtekwifi/dev/rtwn/rtl8821a/r21a.h | 80 + .../dev/rtwn/rtl8821a/r21a_beacon.c | 93 + .../dev/rtwn/rtl8821a/r21a_calib.c | 126 + .../realtekwifi/dev/rtwn/rtl8821a/r21a_chan.c | 153 + .../realtekwifi/dev/rtwn/rtl8821a/r21a_fw.c | 78 + .../realtekwifi/dev/rtwn/rtl8821a/r21a_init.c | 358 ++ .../realtekwifi/dev/rtwn/rtl8821a/r21a_led.c | 67 + .../realtekwifi/dev/rtwn/rtl8821a/r21a_priv.h | 464 ++ .../realtekwifi/dev/rtwn/rtl8821a/r21a_reg.h | 50 + .../realtekwifi/dev/rtwn/rtl8821a/r21a_rom.c | 91 + .../realtekwifi/dev/rtwn/rtl8821a/r21a_rx.c | 88 + .../realtekwifi/dev/rtwn/rtl8821a/usb/r21au.h | 47 + .../dev/rtwn/rtl8821a/usb/r21au_attach.c | 284 + .../dev/rtwn/rtl8821a/usb/r21au_dfs.c | 280 + .../dev/rtwn/rtl8821a/usb/r21au_init.c | 72 + .../dev/rtwn/rtl8821a/usb/r21au_reg.h | 35 + .../dev/rtwn/usb/rtwn_usb_attach.c | 491 ++ .../dev/rtwn/usb/rtwn_usb_attach.h | 174 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_ep.c | 260 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_ep.h | 25 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_reg.c | 179 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_reg.h | 45 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_rx.c | 439 ++ .../realtekwifi/dev/rtwn/usb/rtwn_usb_rx.h | 24 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_tx.c | 285 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_tx.h | 26 + .../realtekwifi/dev/rtwn/usb/rtwn_usb_var.h | 88 + .../drivers/network/wlan/realtekwifi/glue.c | 22 +- 169 files changed, 28981 insertions(+), 5140 deletions(-) create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_debug.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_nop.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_ridx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/opt_wlan.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_var.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_beacon.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_calib.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_chan.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw_cmd.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_led.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rf.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_defs.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_image.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_calib.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_led.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_beacon.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_calib.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_chan.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw_cmd.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_llt.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rf.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_defs.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_image.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_var.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_led.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_chan.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_led.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rf.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_defs.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_image.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_var.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_beacon.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_calib.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_caps.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_chan.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw_cmd.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_led.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rf.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_defs.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_image.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_var.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx_desc.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_beacon.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_calib.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_chan.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_fw.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_led.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_priv.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rom.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_dfs.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_init.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.c create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.h create mode 100644 src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_var.h diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/Jamfile b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/Jamfile index 93ed1f6c3b..f5e26df384 100644 --- a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/Jamfile +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/Jamfile @@ -14,10 +14,50 @@ SubDirCcFlags [ FDefines _KERNEL=1 FBSD_DRIVER=1 _XOPEN_SOURCE ] UseHeaders [ FDirName $(SUBDIR) ] : true ; SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn pci ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn rtl8192c ] ; +SEARCH_SOURCE += [ FDirName $(SUBDIR) dev rtwn rtl8192c pci ] ; KernelAddon realtekwifi : - if_rtwn.c glue.c + + if_rtwn.c + if_rtwn_beacon.c + if_rtwn_calib.c + if_rtwn_cam.c + if_rtwn_efuse.c + if_rtwn_fw.c + if_rtwn_rx.c + if_rtwn_task.c + if_rtwn_tx.c + + # pci/ + rtwn_pci_attach.c + rtwn_pci_reg.c + rtwn_pci_rx.c + rtwn_pci_tx.c + + # rtl8192c/ + r92c_attach.c + r92c_beacon.c + r92c_calib.c + r92c_chan.c + r92c_fw.c + r92c_init.c + r92c_llt.c + r92c_rf.c + r92c_rom.c + r92c_rx.c + r92c_tx.c + + # rtl8192c/pci/ + r92ce_attach.c + r92ce_calib.c + r92ce_fw.c + r92ce_init.c + r92ce_led.c + r92ce_rx.c + r92ce_tx.c : freebsd_wlan.a libfreebsd_network.a diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c index 9b79231627..cf4e96ec3d 100644 --- a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn.c @@ -1,8 +1,9 @@ -/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ /*- * Copyright (c) 2010 Damien Bergamini - * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -18,33 +19,28 @@ */ #include -__FBSDID("$FreeBSD: releng/11.1/sys/dev/rtwn/if_rtwn.c 302035 2016-06-20 22:45:19Z avos $"); +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn.c 327479 2018-01-02 00:07:28Z adrian $"); /* - * Driver for Realtek RTL8188CE + * Driver for Realtek RTL8188CE-VAU/RTL8188CUS/RTL8188EU/RTL8188RU/RTL8192CU/RTL8812AU/RTL8821AU. */ #include -#include #include +#include +#include +#include #include #include #include #include #include -#include -#include #include #include #include +#include #include - -#include -#include -#include - -#include -#include +#include #include #include @@ -55,962 +51,599 @@ __FBSDID("$FreeBSD: releng/11.1/sys/dev/rtwn/if_rtwn.c 302035 2016-06-20 22:45:1 #include #include -#include -#include -#include -#include - #include #include #include -#include #include +#include + +#include +#include +#include +#include #include +#include -#define RTWN_DEBUG -#ifdef RTWN_DEBUG -#define DPRINTF(x) do { if (sc->sc_debug > 0) printf x; } while (0) -#define DPRINTFN(n, x) do { if (sc->sc_debug >= (n)) printf x; } while (0) -#else -#define DPRINTF(x) -#define DPRINTFN(n, x) -#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -/* - * PCI configuration space registers. - */ -#define RTWN_PCI_IOBA 0x10 /* i/o mapped base */ -#define RTWN_PCI_MMBA 0x18 /* memory mapped base */ - -#define RTWN_INT_ENABLE (R92C_IMR_ROK | R92C_IMR_VODOK | R92C_IMR_VIDOK | \ - R92C_IMR_BEDOK | R92C_IMR_BKDOK | R92C_IMR_MGNTDOK | \ - R92C_IMR_HIGHDOK | R92C_IMR_BDOK | R92C_IMR_RDU | \ - R92C_IMR_RXFOVW) - -struct rtwn_ident { - uint16_t vendor; - uint16_t device; - const char *name; -}; +#include -static const struct rtwn_ident rtwn_ident_table[] = { - { 0x10ec, 0x8176, "Realtek RTL8188CE" }, - { 0, 0, NULL } -}; - - -static void rtwn_dma_map_addr(void *, bus_dma_segment_t *, int, int); -static void rtwn_setup_rx_desc(struct rtwn_softc *, struct r92c_rx_desc *, - bus_addr_t, size_t, int); -static int rtwn_alloc_rx_list(struct rtwn_softc *); -static void rtwn_reset_rx_list(struct rtwn_softc *); -static void rtwn_free_rx_list(struct rtwn_softc *); -static int rtwn_alloc_tx_list(struct rtwn_softc *, int); -static void rtwn_reset_tx_list(struct rtwn_softc *, int); -static void rtwn_free_tx_list(struct rtwn_softc *, int); +static void rtwn_radiotap_attach(struct rtwn_softc *); +static void rtwn_vap_decrement_counters(struct rtwn_softc *, + enum ieee80211_opmode, int); +static void rtwn_set_ic_opmode(struct rtwn_softc *); static struct ieee80211vap *rtwn_vap_create(struct ieee80211com *, - const char [IFNAMSIZ], int, enum ieee80211_opmode, int, - const uint8_t [IEEE80211_ADDR_LEN], - const uint8_t [IEEE80211_ADDR_LEN]); -static void rtwn_vap_delete(struct ieee80211vap *); -static void rtwn_write_1(struct rtwn_softc *, uint16_t, uint8_t); -static void rtwn_write_2(struct rtwn_softc *, uint16_t, uint16_t); -void rtwn_write_4(struct rtwn_softc *, uint16_t, uint32_t); -static uint8_t rtwn_read_1(struct rtwn_softc *, uint16_t); -static uint16_t rtwn_read_2(struct rtwn_softc *, uint16_t); -uint32_t rtwn_read_4(struct rtwn_softc *, uint16_t); -static int rtwn_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int); -static void rtwn_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); -static uint32_t rtwn_rf_read(struct rtwn_softc *, int, uint8_t); -static int rtwn_llt_write(struct rtwn_softc *, uint32_t, uint32_t); -static uint8_t rtwn_efuse_read_1(struct rtwn_softc *, uint16_t); -static void rtwn_efuse_read(struct rtwn_softc *); -static int rtwn_read_chipid(struct rtwn_softc *); -static void rtwn_read_rom(struct rtwn_softc *); -static int rtwn_ra_init(struct rtwn_softc *); -static void rtwn_tsf_sync_enable(struct rtwn_softc *); -static void rtwn_set_led(struct rtwn_softc *, int, int); -static void rtwn_calib_to(void *); -static int rtwn_newstate(struct ieee80211vap *, enum ieee80211_state, int); -static int rtwn_updateedca(struct ieee80211com *); -static void rtwn_update_avgrssi(struct rtwn_softc *, int, int8_t); -static int8_t rtwn_get_rssi(struct rtwn_softc *, int, void *); -static void rtwn_rx_frame(struct rtwn_softc *, struct r92c_rx_desc *, - struct rtwn_rx_data *, int); -static int rtwn_tx(struct rtwn_softc *, struct mbuf *, - struct ieee80211_node *); -static void rtwn_tx_done(struct rtwn_softc *, int); -static int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *, - const struct ieee80211_bpf_params *); -static int rtwn_transmit(struct ieee80211com *, struct mbuf *); -static void rtwn_parent(struct ieee80211com *); -static void rtwn_start(struct rtwn_softc *sc); -static void rtwn_watchdog(void *); -static int rtwn_power_on(struct rtwn_softc *); -static int rtwn_llt_init(struct rtwn_softc *); -static void rtwn_fw_reset(struct rtwn_softc *); -static void rtwn_fw_loadpage(struct rtwn_softc *, int, const uint8_t *, - int); -static int rtwn_load_firmware(struct rtwn_softc *); -static int rtwn_dma_init(struct rtwn_softc *); -static void rtwn_mac_init(struct rtwn_softc *); -static void rtwn_bb_init(struct rtwn_softc *); -static void rtwn_rf_init(struct rtwn_softc *); -static void rtwn_cam_init(struct rtwn_softc *); -static void rtwn_pa_bias_init(struct rtwn_softc *); -static void rtwn_rxfilter_init(struct rtwn_softc *); -static void rtwn_edca_init(struct rtwn_softc *); -static void rtwn_write_txpower(struct rtwn_softc *, int, uint16_t[]); -static void rtwn_get_txpower(struct rtwn_softc *, int, - struct ieee80211_channel *, struct ieee80211_channel *, - uint16_t[]); -static void rtwn_set_txpower(struct rtwn_softc *, - struct ieee80211_channel *, struct ieee80211_channel *); -static void rtwn_set_rx_bssid_all(struct rtwn_softc *, int); -static void rtwn_set_gain(struct rtwn_softc *, uint8_t); -static void rtwn_scan_start(struct ieee80211com *); -static void rtwn_scan_end(struct ieee80211com *); -static void rtwn_getradiocaps(struct ieee80211com *, int, int *, - struct ieee80211_channel[]); -static void rtwn_set_channel(struct ieee80211com *); -static void rtwn_update_mcast(struct ieee80211com *); -static void rtwn_set_chan(struct rtwn_softc *, - struct ieee80211_channel *, struct ieee80211_channel *); -static int rtwn_iq_calib_chain(struct rtwn_softc *, int, uint16_t[2], - uint16_t[2]); -static void rtwn_iq_calib_run(struct rtwn_softc *, int, uint16_t[2][2], - uint16_t[2][2]); -static int rtwn_iq_calib_compare_results(uint16_t[2][2], uint16_t[2][2], - uint16_t[2][2], uint16_t[2][2], int); -static void rtwn_iq_calib_write_results(struct rtwn_softc *, uint16_t[2], - uint16_t[2], int); -static void rtwn_iq_calib(struct rtwn_softc *); -static void rtwn_lc_calib(struct rtwn_softc *); -static void rtwn_temp_calib(struct rtwn_softc *); -static int rtwn_init(struct rtwn_softc *); -static void rtwn_stop_locked(struct rtwn_softc *); -static void rtwn_stop(struct rtwn_softc *); -static void rtwn_intr(void *); + const char [IFNAMSIZ], int, enum ieee80211_opmode, + int, const uint8_t [IEEE80211_ADDR_LEN], + const uint8_t [IEEE80211_ADDR_LEN]); +static void rtwn_vap_delete(struct ieee80211vap *); +static int rtwn_read_chipid(struct rtwn_softc *); +static int rtwn_ioctl_reset(struct ieee80211vap *, u_long); +static void rtwn_set_media_status(struct rtwn_softc *, + union sec_param *); +#ifndef RTWN_WITHOUT_UCODE +static int rtwn_tx_fwpkt_check(struct rtwn_softc *, + struct ieee80211vap *); +static int rtwn_construct_nulldata(struct rtwn_softc *, + struct ieee80211vap *, uint8_t *, int); +static int rtwn_push_nulldata(struct rtwn_softc *, + struct ieee80211vap *); +static void rtwn_pwrmode_init(void *); +static void rtwn_set_pwrmode_cb(struct rtwn_softc *, + union sec_param *); +#endif +static void rtwn_tsf_sync_adhoc(void *); +static void rtwn_tsf_sync_adhoc_task(void *, int); +static void rtwn_tsf_sync_enable(struct rtwn_softc *, + struct ieee80211vap *); +static void rtwn_set_ack_preamble(struct rtwn_softc *); +static void rtwn_set_mode(struct rtwn_softc *, uint8_t, int); +static int rtwn_monitor_newstate(struct ieee80211vap *, + enum ieee80211_state, int); +static int rtwn_newstate(struct ieee80211vap *, + enum ieee80211_state, int); +static void rtwn_calc_basicrates(struct rtwn_softc *); +static int rtwn_run(struct rtwn_softc *, + struct ieee80211vap *); +#ifndef D4054 +static void rtwn_watchdog(void *); +#endif +static void rtwn_parent(struct ieee80211com *); +static int rtwn_dma_init(struct rtwn_softc *); +static int rtwn_mac_init(struct rtwn_softc *); +static void rtwn_mrr_init(struct rtwn_softc *); +static void rtwn_scan_start(struct ieee80211com *); +static void rtwn_scan_curchan(struct ieee80211_scan_state *, + unsigned long); +static void rtwn_scan_end(struct ieee80211com *); +static void rtwn_getradiocaps(struct ieee80211com *, int, int *, + struct ieee80211_channel[]); +static void rtwn_update_chw(struct ieee80211com *); +static void rtwn_set_channel(struct ieee80211com *); +static int rtwn_wme_update(struct ieee80211com *); +static void rtwn_update_slot(struct ieee80211com *); +static void rtwn_update_slot_cb(struct rtwn_softc *, + union sec_param *); +static void rtwn_update_aifs(struct rtwn_softc *, uint8_t); +static void rtwn_update_promisc(struct ieee80211com *); +static void rtwn_update_mcast(struct ieee80211com *); +static int rtwn_set_bssid(struct rtwn_softc *, + const uint8_t *, int); +static int rtwn_set_macaddr(struct rtwn_softc *, + const uint8_t *, int); +static struct ieee80211_node *rtwn_node_alloc(struct ieee80211vap *, + const uint8_t mac[IEEE80211_ADDR_LEN]); +static void rtwn_newassoc(struct ieee80211_node *, int); +static void rtwn_node_free(struct ieee80211_node *); +static void rtwn_init_beacon_reg(struct rtwn_softc *); +static int rtwn_init(struct rtwn_softc *); +static void rtwn_stop(struct rtwn_softc *); -/* Aliases. */ -#define rtwn_bb_write rtwn_write_4 -#define rtwn_bb_read rtwn_read_4 - -static int rtwn_probe(device_t); -static int rtwn_attach(device_t); -static int rtwn_detach(device_t); -static int rtwn_shutdown(device_t); -static int rtwn_suspend(device_t); -static int rtwn_resume(device_t); - -static device_method_t rtwn_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, rtwn_probe), - DEVMETHOD(device_attach, rtwn_attach), - DEVMETHOD(device_detach, rtwn_detach), - DEVMETHOD(device_shutdown, rtwn_shutdown), - DEVMETHOD(device_suspend, rtwn_suspend), - DEVMETHOD(device_resume, rtwn_resume), - - DEVMETHOD_END -}; - -static driver_t rtwn_driver = { - "rtwn", - rtwn_methods, - sizeof (struct rtwn_softc) -}; -static devclass_t rtwn_devclass; - -DRIVER_MODULE(rtwn, pci, rtwn_driver, rtwn_devclass, NULL, NULL); - -MODULE_VERSION(rtwn, 1); - -MODULE_DEPEND(rtwn, pci, 1, 1, 1); -MODULE_DEPEND(rtwn, wlan, 1, 1, 1); -MODULE_DEPEND(rtwn, firmware, 1, 1, 1); +MALLOC_DEFINE(M_RTWN_PRIV, "rtwn_priv", "rtwn driver private state"); static const uint8_t rtwn_chan_2ghz[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; -static int -rtwn_probe(device_t dev) -{ - const struct rtwn_ident *ident; +static const uint16_t wme2reg[] = + { R92C_EDCA_BE_PARAM, R92C_EDCA_BK_PARAM, + R92C_EDCA_VI_PARAM, R92C_EDCA_VO_PARAM }; - for (ident = rtwn_ident_table; ident->name != NULL; ident++) { - if (pci_get_vendor(dev) == ident->vendor && - pci_get_device(dev) == ident->device) { - device_set_desc(dev, ident->name); - return (BUS_PROBE_DEFAULT); - } - } - return (ENXIO); -} - -static int -rtwn_attach(device_t dev) +int +rtwn_attach(struct rtwn_softc *sc) { - struct rtwn_softc *sc = device_get_softc(dev); struct ieee80211com *ic = &sc->sc_ic; - uint32_t lcsr; - int i, count, error, rid; + int error; - sc->sc_dev = dev; - sc->sc_debug = 0; + sc->cur_bcnq_id = RTWN_VAP_ID_INVALID; - /* - * Get the offset of the PCI Express Capability Structure in PCI - * Configuration Space. - */ - error = pci_find_cap(dev, PCIY_EXPRESS, &sc->sc_cap_off); - if (error != 0) { - device_printf(dev, "PCIe capability structure not found!\n"); - return (error); - } - - /* Enable bus-mastering. */ - pci_enable_busmaster(dev); - - rid = PCIR_BAR(2); - sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); - if (sc->mem == NULL) { - device_printf(dev, "can't map mem space\n"); - return (ENOMEM); - } - sc->sc_st = rman_get_bustag(sc->mem); - sc->sc_sh = rman_get_bushandle(sc->mem); - - /* Install interrupt handler. */ - count = 1; - rid = 0; - if (pci_alloc_msi(dev, &count) == 0) - rid = 1; - sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | - (rid != 0 ? 0 : RF_SHAREABLE)); - if (sc->irq == NULL) { - device_printf(dev, "can't map interrupt\n"); - return (ENXIO); - } - - RTWN_LOCK_INIT(sc); - callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0); - callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0); + RTWN_NT_LOCK_INIT(sc); + rtwn_cmdq_init(sc); +#ifndef D4054 + callout_init_mtx(&sc->sc_watchdog_to, &sc->sc_mtx, 0); +#endif + callout_init(&sc->sc_calib_to, 0); + callout_init(&sc->sc_pwrmode_init, 0); mbufq_init(&sc->sc_snd, ifqmaxlen); + RTWN_LOCK(sc); error = rtwn_read_chipid(sc); + RTWN_UNLOCK(sc); if (error != 0) { - device_printf(dev, "unsupported test chip\n"); - goto fail; + device_printf(sc->sc_dev, "unsupported test chip\n"); + goto detach; } - /* Disable PCIe Active State Power Management (ASPM). */ - lcsr = pci_read_config(sc->sc_dev, sc->sc_cap_off + PCIER_LINK_CTL, 4); - lcsr &= ~PCIEM_LINK_CTL_ASPMC; - pci_write_config(sc->sc_dev, sc->sc_cap_off + PCIER_LINK_CTL, lcsr, 4); - - /* Allocate Tx/Rx buffers. */ - error = rtwn_alloc_rx_list(sc); + error = rtwn_read_rom(sc); if (error != 0) { - device_printf(dev, "could not allocate Rx buffers\n"); - goto fail; - } - for (i = 0; i < RTWN_NTXQUEUES; i++) { - error = rtwn_alloc_tx_list(sc, i); - if (error != 0) { - device_printf(dev, "could not allocate Tx buffers\n"); - goto fail; - } + device_printf(sc->sc_dev, "%s: cannot read rom, error %d\n", + __func__, error); + goto detach; } - /* Determine number of Tx/Rx chains. */ - if (sc->chip & RTWN_CHIP_92C) { - sc->ntxchains = (sc->chip & RTWN_CHIP_92C_1T2R) ? 1 : 2; - sc->nrxchains = 2; - } else { - sc->ntxchains = 1; - sc->nrxchains = 1; + if (sc->macid_limit > RTWN_MACID_LIMIT) { + device_printf(sc->sc_dev, + "macid limit will be reduced from %d to %d\n", + sc->macid_limit, RTWN_MACID_LIMIT); + sc->macid_limit = RTWN_MACID_LIMIT; + } + if (sc->cam_entry_limit > RTWN_CAM_ENTRY_LIMIT) { + device_printf(sc->sc_dev, + "cam entry limit will be reduced from %d to %d\n", + sc->cam_entry_limit, RTWN_CAM_ENTRY_LIMIT); + sc->cam_entry_limit = RTWN_CAM_ENTRY_LIMIT; + } + if (sc->txdesc_len > RTWN_TX_DESC_SIZE) { + device_printf(sc->sc_dev, + "adjust size for Tx descriptor (current %d, needed %d)\n", + RTWN_TX_DESC_SIZE, sc->txdesc_len); + goto detach; } - rtwn_read_rom(sc); - device_printf(sc->sc_dev, "MAC/BB RTL%s, RF 6052 %dT%dR\n", - (sc->chip & RTWN_CHIP_92C) ? "8192CE" : "8188CE", - sc->ntxchains, sc->nrxchains); + device_printf(sc->sc_dev, "MAC/BB %s, RF 6052 %dT%dR\n", + sc->name, sc->ntxchains, sc->nrxchains); ic->ic_softc = sc; - ic->ic_name = device_get_nameunit(dev); - ic->ic_opmode = IEEE80211_M_STA; - ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ + ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */ + ic->ic_opmode = IEEE80211_M_STA; /* default to BSS mode */ /* set device capabilities */ ic->ic_caps = IEEE80211_C_STA /* station mode */ | IEEE80211_C_MONITOR /* monitor mode */ + | IEEE80211_C_IBSS /* adhoc mode */ + | IEEE80211_C_HOSTAP /* hostap mode */ +#if 0 /* TODO: HRPWM register setup */ +#ifndef RTWN_WITHOUT_UCODE + | IEEE80211_C_PMGT /* Station-side power mgmt */ +#endif +#endif | IEEE80211_C_SHPREAMBLE /* short preamble supported */ | IEEE80211_C_SHSLOT /* short slot time supported */ - | IEEE80211_C_WPA /* capable of WPA1+WPA2 */ +#if 0 | IEEE80211_C_BGSCAN /* capable of bg scanning */ +#endif + | IEEE80211_C_WPA /* 802.11i */ | IEEE80211_C_WME /* 802.11e */ + | IEEE80211_C_SWAMSDUTX /* Do software A-MSDU TX */ + | IEEE80211_C_FF /* Atheros fast-frames */ ; - /* XXX TODO: setup regdomain if R92C_CHANNEL_PLAN_BY_HW bit is set. */ + if (sc->sc_hwcrypto != RTWN_CRYPTO_SW) { + ic->ic_cryptocaps = + IEEE80211_CRYPTO_WEP | + IEEE80211_CRYPTO_TKIP | + IEEE80211_CRYPTO_AES_CCM; + } + + ic->ic_htcaps = + IEEE80211_HTCAP_SHORTGI20 /* short GI in 20MHz */ + | IEEE80211_HTCAP_MAXAMSDU_3839 /* max A-MSDU length */ + | IEEE80211_HTCAP_SMPS_OFF /* SM PS mode disabled */ + /* s/w capabilities */ + | IEEE80211_HTC_HT /* HT operation */ + | IEEE80211_HTC_AMPDU /* A-MPDU tx */ + | IEEE80211_HTC_AMSDU /* A-MSDU tx */ + ; + + if (sc->sc_ht40) { + ic->ic_htcaps |= + IEEE80211_HTCAP_CHWIDTH40 /* 40 MHz channel width */ + | IEEE80211_HTCAP_SHORTGI40 /* short GI in 40MHz */ + ; + } + + ic->ic_txstream = sc->ntxchains; + ic->ic_rxstream = sc->nrxchains; + + /* Enable TX watchdog */ +#ifdef D4054 + ic->ic_flags_ext |= IEEE80211_FEXT_WATCHDOG; +#endif + + /* Adjust capabilities. */ + rtwn_adj_devcaps(sc); rtwn_getradiocaps(ic, IEEE80211_CHAN_MAX, &ic->ic_nchans, ic->ic_channels); - ieee80211_ifattach(ic); + /* XXX TODO: setup regdomain if R92C_CHANNEL_PLAN_BY_HW bit is set. */ - ic->ic_wme.wme_update = rtwn_updateedca; - ic->ic_update_mcast = rtwn_update_mcast; + ieee80211_ifattach(ic); + ic->ic_raw_xmit = rtwn_raw_xmit; ic->ic_scan_start = rtwn_scan_start; + sc->sc_scan_curchan = ic->ic_scan_curchan; + ic->ic_scan_curchan = rtwn_scan_curchan; ic->ic_scan_end = rtwn_scan_end; ic->ic_getradiocaps = rtwn_getradiocaps; + ic->ic_update_chw = rtwn_update_chw; ic->ic_set_channel = rtwn_set_channel; - ic->ic_raw_xmit = rtwn_raw_xmit; ic->ic_transmit = rtwn_transmit; ic->ic_parent = rtwn_parent; ic->ic_vap_create = rtwn_vap_create; ic->ic_vap_delete = rtwn_vap_delete; + ic->ic_wme.wme_update = rtwn_wme_update; + ic->ic_updateslot = rtwn_update_slot; + ic->ic_update_promisc = rtwn_update_promisc; + ic->ic_update_mcast = rtwn_update_mcast; + ic->ic_node_alloc = rtwn_node_alloc; + ic->ic_newassoc = rtwn_newassoc; + sc->sc_node_free = ic->ic_node_free; + ic->ic_node_free = rtwn_node_free; - ieee80211_radiotap_attach(ic, - &sc->sc_txtap.wt_ihdr, sizeof(sc->sc_txtap), - RTWN_TX_RADIOTAP_PRESENT, - &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap), - RTWN_RX_RADIOTAP_PRESENT); - - /* - * Hook our interrupt after all initialization is complete. - */ - error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, - NULL, rtwn_intr, sc, &sc->sc_ih); - if (error != 0) { - device_printf(dev, "can't establish interrupt, error %d\n", - error); - goto fail; - } + rtwn_postattach(sc); + rtwn_radiotap_attach(sc); if (bootverbose) ieee80211_announce(ic); return (0); -fail: - rtwn_detach(dev); - return (error); -} - - -static int -rtwn_detach(device_t dev) -{ - struct rtwn_softc *sc = device_get_softc(dev); - int i; - - if (sc->sc_ic.ic_softc != NULL) { - rtwn_stop(sc); - - callout_drain(&sc->calib_to); - callout_drain(&sc->watchdog_to); - ieee80211_ifdetach(&sc->sc_ic); - mbufq_drain(&sc->sc_snd); - } - - /* Uninstall interrupt handler. */ - if (sc->irq != NULL) { - bus_teardown_intr(dev, sc->irq, sc->sc_ih); - bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(sc->irq), - sc->irq); - pci_release_msi(dev); - } - - /* Free Tx/Rx buffers. */ - for (i = 0; i < RTWN_NTXQUEUES; i++) - rtwn_free_tx_list(sc, i); - rtwn_free_rx_list(sc); - - if (sc->mem != NULL) - bus_release_resource(dev, SYS_RES_MEMORY, - rman_get_rid(sc->mem), sc->mem); - - RTWN_LOCK_DESTROY(sc); - return (0); -} - -static int -rtwn_shutdown(device_t dev) -{ - - return (0); -} - -static int -rtwn_suspend(device_t dev) -{ - return (0); -} - -static int -rtwn_resume(device_t dev) -{ - - return (0); +detach: + return (ENXIO); /* failure */ } static void -rtwn_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +rtwn_radiotap_attach(struct rtwn_softc *sc) { + struct rtwn_rx_radiotap_header *rxtap = &sc->sc_rxtap; + struct rtwn_tx_radiotap_header *txtap = &sc->sc_txtap; - if (error != 0) - return; - KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs)); - *(bus_addr_t *)arg = segs[0].ds_addr; + ieee80211_radiotap_attach(&sc->sc_ic, + &txtap->wt_ihdr, sizeof(*txtap), RTWN_TX_RADIOTAP_PRESENT, + &rxtap->wr_ihdr, sizeof(*rxtap), RTWN_RX_RADIOTAP_PRESENT); +} + +void +rtwn_sysctlattach(struct rtwn_softc *sc) +{ + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + +#if 1 + sc->sc_ht40 = 0; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ht40", CTLFLAG_RDTUN, &sc->sc_ht40, + sc->sc_ht40, "Enable 40 MHz mode support"); +#endif + +#ifdef RTWN_DEBUG + SYSCTL_ADD_U32(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "debug", CTLFLAG_RWTUN, &sc->sc_debug, sc->sc_debug, + "Control debugging printfs"); +#endif + + sc->sc_hwcrypto = RTWN_CRYPTO_PAIR; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "hwcrypto", CTLFLAG_RDTUN, &sc->sc_hwcrypto, + sc->sc_hwcrypto, "Enable h/w crypto: " + "0 - disable, 1 - pairwise keys, 2 - all keys"); + if (sc->sc_hwcrypto >= RTWN_CRYPTO_MAX) + sc->sc_hwcrypto = RTWN_CRYPTO_FULL; + + sc->sc_ratectl_sysctl = RTWN_RATECTL_NET80211; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ratectl", CTLFLAG_RDTUN, &sc->sc_ratectl_sysctl, + sc->sc_ratectl_sysctl, "Select rate control mechanism: " + "0 - disabled, 1 - via net80211, 2 - via firmware"); + if (sc->sc_ratectl_sysctl >= RTWN_RATECTL_MAX) + sc->sc_ratectl_sysctl = RTWN_RATECTL_FW; + + sc->sc_ratectl = sc->sc_ratectl_sysctl; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "ratectl_selected", CTLFLAG_RD, &sc->sc_ratectl, + sc->sc_ratectl, + "Currently selected rate control mechanism (by the driver)"); +} + +void +rtwn_detach(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + if (ic->ic_softc == sc) { + /* Stop command queue. */ + RTWN_CMDQ_LOCK(sc); + sc->sc_detached = 1; + RTWN_CMDQ_UNLOCK(sc); + + ieee80211_draintask(ic, &sc->cmdq_task); + ieee80211_ifdetach(ic); + } + + rtwn_cmdq_destroy(sc); + if (RTWN_NT_LOCK_INITIALIZED(sc)) + RTWN_NT_LOCK_DESTROY(sc); +} + +void +rtwn_suspend(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + ieee80211_suspend_all(ic); +} + +void +rtwn_resume(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + ieee80211_resume_all(ic); } static void -rtwn_setup_rx_desc(struct rtwn_softc *sc, struct r92c_rx_desc *desc, - bus_addr_t addr, size_t len, int idx) +rtwn_vap_decrement_counters(struct rtwn_softc *sc, + enum ieee80211_opmode opmode, int id) { - memset(desc, 0, sizeof(*desc)); - desc->rxdw0 = htole32(SM(R92C_RXDW0_PKTLEN, len) | - ((idx == RTWN_RX_LIST_COUNT - 1) ? R92C_RXDW0_EOR : 0)); - desc->rxbufaddr = htole32(addr); - bus_space_barrier(sc->sc_st, sc->sc_sh, 0, sc->sc_mapsize, - BUS_SPACE_BARRIER_WRITE); - desc->rxdw0 |= htole32(R92C_RXDW0_OWN); -} + RTWN_ASSERT_LOCKED(sc); -static int -rtwn_alloc_rx_list(struct rtwn_softc *sc) -{ - struct rtwn_rx_ring *rx_ring = &sc->rx_ring; - struct rtwn_rx_data *rx_data; - bus_size_t size; - int i, error; - - /* Allocate Rx descriptors. */ - size = sizeof(struct r92c_rx_desc) * RTWN_RX_LIST_COUNT; - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - size, 1, size, 0, NULL, NULL, &rx_ring->desc_dmat); - if (error != 0) { - device_printf(sc->sc_dev, "could not create rx desc DMA tag\n"); - goto fail; + if (id != RTWN_VAP_ID_INVALID) { + KASSERT(id == 0 || id == 1, ("wrong vap id %d!\n", id)); + KASSERT(sc->vaps[id] != NULL, ("vap pointer is NULL\n")); + sc->vaps[id] = NULL; } - error = bus_dmamem_alloc(rx_ring->desc_dmat, (void **)&rx_ring->desc, - BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, - &rx_ring->desc_map); - if (error != 0) { - device_printf(sc->sc_dev, "could not allocate rx desc\n"); - goto fail; - } - error = bus_dmamap_load(rx_ring->desc_dmat, rx_ring->desc_map, - rx_ring->desc, size, rtwn_dma_map_addr, &rx_ring->paddr, 0); - if (error != 0) { - device_printf(sc->sc_dev, "could not load rx desc DMA map\n"); - goto fail; - } - bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map, - BUS_DMASYNC_PREWRITE); - - /* Create RX buffer DMA tag. */ - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, - 1, MCLBYTES, 0, NULL, NULL, &rx_ring->data_dmat); - if (error != 0) { - device_printf(sc->sc_dev, "could not create rx buf DMA tag\n"); - goto fail; + switch (opmode) { + case IEEE80211_M_HOSTAP: + sc->ap_vaps--; + /* FALLTHROUGH */ + case IEEE80211_M_IBSS: + sc->bcn_vaps--; + /* FALLTHROUGH */ + case IEEE80211_M_STA: + sc->nvaps--; + break; + case IEEE80211_M_MONITOR: + sc->mon_vaps--; + break; + default: + KASSERT(0, ("wrong opmode %d\n", opmode)); + break; } - /* Allocate Rx buffers. */ - for (i = 0; i < RTWN_RX_LIST_COUNT; i++) { - rx_data = &rx_ring->rx_data[i]; - error = bus_dmamap_create(rx_ring->data_dmat, 0, &rx_data->map); - if (error != 0) { - device_printf(sc->sc_dev, - "could not create rx buf DMA map\n"); - goto fail; - } + KASSERT(sc->vaps_running >= 0 && sc->monvaps_running >= 0, + ("number of running vaps is negative (vaps %d, monvaps %d)\n", + sc->vaps_running, sc->monvaps_running)); + KASSERT(sc->vaps_running - sc->monvaps_running <= RTWN_PORT_COUNT, + ("number of running vaps is too big (vaps %d, monvaps %d)\n", + sc->vaps_running, sc->monvaps_running)); - rx_data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (rx_data->m == NULL) { - device_printf(sc->sc_dev, - "could not allocate rx mbuf\n"); - error = ENOMEM; - goto fail; - } - - error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map, - mtod(rx_data->m, void *), MCLBYTES, rtwn_dma_map_addr, - &rx_data->paddr, BUS_DMA_NOWAIT); - if (error != 0) { - device_printf(sc->sc_dev, - "could not load rx buf DMA map"); - goto fail; - } - - rtwn_setup_rx_desc(sc, &rx_ring->desc[i], rx_data->paddr, - MCLBYTES, i); - } - return (0); - -fail: - rtwn_free_rx_list(sc); - return (error); + KASSERT(sc->nvaps >= 0 && sc->nvaps <= RTWN_PORT_COUNT, + ("wrong value %d for nvaps\n", sc->nvaps)); + KASSERT(sc->mon_vaps >= 0, ("mon_vaps is negative (%d)\n", + sc->mon_vaps)); + KASSERT(sc->bcn_vaps >= 0 && ((RTWN_CHIP_HAS_BCNQ1(sc) && + sc->bcn_vaps <= RTWN_PORT_COUNT) || sc->bcn_vaps <= 1), + ("bcn_vaps value %d is wrong\n", sc->bcn_vaps)); + KASSERT(sc->ap_vaps >= 0 && ((RTWN_CHIP_HAS_BCNQ1(sc) && + sc->ap_vaps <= RTWN_PORT_COUNT) || sc->ap_vaps <= 1), + ("ap_vaps value %d is wrong\n", sc->ap_vaps)); } static void -rtwn_reset_rx_list(struct rtwn_softc *sc) +rtwn_set_ic_opmode(struct rtwn_softc *sc) { - struct rtwn_rx_ring *rx_ring = &sc->rx_ring; - struct rtwn_rx_data *rx_data; - int i; + struct ieee80211com *ic = &sc->sc_ic; - for (i = 0; i < RTWN_RX_LIST_COUNT; i++) { - rx_data = &rx_ring->rx_data[i]; - rtwn_setup_rx_desc(sc, &rx_ring->desc[i], rx_data->paddr, - MCLBYTES, i); - } + RTWN_ASSERT_LOCKED(sc); + + /* for ieee80211_reset_erp() */ + if (sc->bcn_vaps - sc->ap_vaps > 0) + ic->ic_opmode = IEEE80211_M_IBSS; + else if (sc->ap_vaps > 0) + ic->ic_opmode = IEEE80211_M_HOSTAP; + else if (sc->nvaps > 0) + ic->ic_opmode = IEEE80211_M_STA; + else + ic->ic_opmode = IEEE80211_M_MONITOR; } -static void -rtwn_free_rx_list(struct rtwn_softc *sc) -{ - struct rtwn_rx_ring *rx_ring = &sc->rx_ring; - struct rtwn_rx_data *rx_data; - int i; - - if (rx_ring->desc_dmat != NULL) { - if (rx_ring->desc != NULL) { - bus_dmamap_sync(rx_ring->desc_dmat, - rx_ring->desc_map, - BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(rx_ring->desc_dmat, - rx_ring->desc_map); - bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc, - rx_ring->desc_map); - rx_ring->desc = NULL; - } - bus_dma_tag_destroy(rx_ring->desc_dmat); - rx_ring->desc_dmat = NULL; - } - - for (i = 0; i < RTWN_RX_LIST_COUNT; i++) { - rx_data = &rx_ring->rx_data[i]; - - if (rx_data->m != NULL) { - bus_dmamap_sync(rx_ring->data_dmat, - rx_data->map, BUS_DMASYNC_POSTREAD); - bus_dmamap_unload(rx_ring->data_dmat, rx_data->map); - m_freem(rx_data->m); - rx_data->m = NULL; - } - bus_dmamap_destroy(rx_ring->data_dmat, rx_data->map); - rx_data->map = NULL; - } - if (rx_ring->data_dmat != NULL) { - bus_dma_tag_destroy(rx_ring->data_dmat); - rx_ring->data_dmat = NULL; - } -} - -static int -rtwn_alloc_tx_list(struct rtwn_softc *sc, int qid) -{ - struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; - struct rtwn_tx_data *tx_data; - bus_size_t size; - int i, error; - - size = sizeof(struct r92c_tx_desc) * RTWN_TX_LIST_COUNT; - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), PAGE_SIZE, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - size, 1, size, 0, NULL, NULL, &tx_ring->desc_dmat); - if (error != 0) { - device_printf(sc->sc_dev, "could not create tx ring DMA tag\n"); - goto fail; - } - - error = bus_dmamem_alloc(tx_ring->desc_dmat, (void **)&tx_ring->desc, - BUS_DMA_NOWAIT | BUS_DMA_ZERO, &tx_ring->desc_map); - if (error != 0) { - device_printf(sc->sc_dev, "can't map tx ring DMA memory\n"); - goto fail; - } - error = bus_dmamap_load(tx_ring->desc_dmat, tx_ring->desc_map, - tx_ring->desc, size, rtwn_dma_map_addr, &tx_ring->paddr, - BUS_DMA_NOWAIT); - if (error != 0) { - device_printf(sc->sc_dev, "could not load desc DMA map\n"); - goto fail; - } - bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, - BUS_DMASYNC_PREWRITE); - - error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, - 1, MCLBYTES, 0, NULL, NULL, &tx_ring->data_dmat); - if (error != 0) { - device_printf(sc->sc_dev, "could not create tx buf DMA tag\n"); - goto fail; - } - - for (i = 0; i < RTWN_TX_LIST_COUNT; i++) { - struct r92c_tx_desc *desc = &tx_ring->desc[i]; - - /* setup tx desc */ - desc->nextdescaddr = htole32(tx_ring->paddr + - + sizeof(struct r92c_tx_desc) - * ((i + 1) % RTWN_TX_LIST_COUNT)); - tx_data = &tx_ring->tx_data[i]; - error = bus_dmamap_create(tx_ring->data_dmat, 0, &tx_data->map); - if (error != 0) { - device_printf(sc->sc_dev, - "could not create tx buf DMA map\n"); - goto fail; - } - tx_data->m = NULL; - tx_data->ni = NULL; - } - return (0); - -fail: - rtwn_free_tx_list(sc, qid); - return (error); -} - -static void -rtwn_reset_tx_list(struct rtwn_softc *sc, int qid) -{ - struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; - int i; - - for (i = 0; i < RTWN_TX_LIST_COUNT; i++) { - struct r92c_tx_desc *desc = &tx_ring->desc[i]; - struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i]; - - memset(desc, 0, sizeof(*desc) - - (sizeof(desc->reserved) + sizeof(desc->nextdescaddr64) + - sizeof(desc->nextdescaddr))); - - if (tx_data->m != NULL) { - bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); - m_freem(tx_data->m); - tx_data->m = NULL; - } - if (tx_data->ni != NULL) { - ieee80211_free_node(tx_data->ni); - tx_data->ni = NULL; - } - } - - bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, - BUS_DMASYNC_POSTWRITE); - - sc->qfullmsk &= ~(1 << qid); - tx_ring->queued = 0; - tx_ring->cur = 0; -} - -static void -rtwn_free_tx_list(struct rtwn_softc *sc, int qid) -{ - struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; - struct rtwn_tx_data *tx_data; - int i; - - if (tx_ring->desc_dmat != NULL) { - if (tx_ring->desc != NULL) { - bus_dmamap_sync(tx_ring->desc_dmat, - tx_ring->desc_map, BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(tx_ring->desc_dmat, - tx_ring->desc_map); - bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc, - tx_ring->desc_map); - } - bus_dma_tag_destroy(tx_ring->desc_dmat); - } - - for (i = 0; i < RTWN_TX_LIST_COUNT; i++) { - tx_data = &tx_ring->tx_data[i]; - - if (tx_data->m != NULL) { - bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); - m_freem(tx_data->m); - tx_data->m = NULL; - } - } - if (tx_ring->data_dmat != NULL) { - bus_dma_tag_destroy(tx_ring->data_dmat); - tx_ring->data_dmat = NULL; - } - - sc->qfullmsk &= ~(1 << qid); - tx_ring->queued = 0; - tx_ring->cur = 0; -} - - static struct ieee80211vap * rtwn_vap_create(struct ieee80211com *ic, const char name[IFNAMSIZ], int unit, enum ieee80211_opmode opmode, int flags, const uint8_t bssid[IEEE80211_ADDR_LEN], const uint8_t mac[IEEE80211_ADDR_LEN]) { - struct rtwn_vap *rvp; + struct rtwn_softc *sc = ic->ic_softc; + struct rtwn_vap *uvp; struct ieee80211vap *vap; + int id = RTWN_VAP_ID_INVALID; - if (!TAILQ_EMPTY(&ic->ic_vaps)) - return (NULL); + RTWN_LOCK(sc); + KASSERT(sc->nvaps <= RTWN_PORT_COUNT, + ("nvaps overflow (%d > %d)\n", sc->nvaps, RTWN_PORT_COUNT)); + KASSERT(sc->ap_vaps <= RTWN_PORT_COUNT, + ("ap_vaps overflow (%d > %d)\n", sc->ap_vaps, RTWN_PORT_COUNT)); + KASSERT(sc->bcn_vaps <= RTWN_PORT_COUNT, + ("bcn_vaps overflow (%d > %d)\n", sc->bcn_vaps, RTWN_PORT_COUNT)); + + if (opmode != IEEE80211_M_MONITOR) { + switch (sc->nvaps) { + case 0: + id = 0; + break; + case 1: + if (sc->vaps[1] == NULL) + id = 1; + else if (sc->vaps[0] == NULL) + id = 0; + KASSERT(id != RTWN_VAP_ID_INVALID, + ("no free ports left\n")); + break; + case 2: + default: + goto fail; + } + + if (opmode == IEEE80211_M_IBSS || + opmode == IEEE80211_M_HOSTAP) { + if ((sc->bcn_vaps == 1 && !RTWN_CHIP_HAS_BCNQ1(sc)) || + sc->bcn_vaps == RTWN_PORT_COUNT) + goto fail; + } + } + + switch (opmode) { + case IEEE80211_M_HOSTAP: + sc->ap_vaps++; + /* FALLTHROUGH */ + case IEEE80211_M_IBSS: + sc->bcn_vaps++; + /* FALLTHROUGH */ + case IEEE80211_M_STA: + sc->nvaps++; + break; + case IEEE80211_M_MONITOR: + sc->mon_vaps++; + break; + default: + KASSERT(0, ("unknown opmode %d\n", opmode)); + goto fail; + } + RTWN_UNLOCK(sc); + + uvp = malloc(sizeof(struct rtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO); + uvp->id = id; + if (id != RTWN_VAP_ID_INVALID) { + RTWN_LOCK(sc); + sc->vaps[id] = uvp; + RTWN_UNLOCK(sc); + } + vap = &uvp->vap; + /* enable s/w bmiss handling for sta mode */ - rvp = malloc(sizeof(struct rtwn_vap), M_80211_VAP, M_WAITOK | M_ZERO); - vap = &rvp->vap; if (ieee80211_vap_setup(ic, vap, name, unit, opmode, flags | IEEE80211_CLONE_NOBEACONS, bssid) != 0) { /* out of memory */ - free(rvp, M_80211_VAP); - return (NULL); + free(uvp, M_80211_VAP); + + RTWN_LOCK(sc); + rtwn_vap_decrement_counters(sc, opmode, id); + RTWN_UNLOCK(sc); + + return (NULL); } - /* Override state transition machine. */ - rvp->newstate = vap->iv_newstate; - vap->iv_newstate = rtwn_newstate; + rtwn_beacon_init(sc, &uvp->bcn_desc.txd[0], uvp->id); + rtwn_vap_preattach(sc, vap); - /* Complete setup. */ + /* override state transition machine */ + uvp->newstate = vap->iv_newstate; + if (opmode == IEEE80211_M_MONITOR) + vap->iv_newstate = rtwn_monitor_newstate; + else + vap->iv_newstate = rtwn_newstate; + vap->iv_update_beacon = rtwn_update_beacon; + vap->iv_reset = rtwn_ioctl_reset; + vap->iv_key_alloc = rtwn_key_alloc; + vap->iv_key_set = rtwn_key_set; + vap->iv_key_delete = rtwn_key_delete; + vap->iv_max_aid = sc->macid_limit; + + /* 802.11n parameters */ + vap->iv_ampdu_density = IEEE80211_HTCAP_MPDUDENSITY_16; + vap->iv_ampdu_rxmax = IEEE80211_HTCAP_MAXRXAMPDU_64K; + + TIMEOUT_TASK_INIT(taskqueue_thread, &uvp->tx_beacon_csa, 0, + rtwn_tx_beacon_csa, vap); + if (opmode == IEEE80211_M_IBSS) { + uvp->recv_mgmt = vap->iv_recv_mgmt; + vap->iv_recv_mgmt = rtwn_adhoc_recv_mgmt; + TASK_INIT(&uvp->tsf_sync_adhoc_task, 0, + rtwn_tsf_sync_adhoc_task, vap); + callout_init(&uvp->tsf_sync_adhoc, 0); + } + + /* + * NB: driver can select net80211 RA even when user requests + * another mechanism. + */ + ieee80211_ratectl_init(vap); + + /* complete setup */ ieee80211_vap_attach(vap, ieee80211_media_change, ieee80211_media_status, mac); - ic->ic_opmode = opmode; + + RTWN_LOCK(sc); + rtwn_set_ic_opmode(sc); + if (sc->sc_flags & RTWN_RUNNING) { + if (uvp->id != RTWN_VAP_ID_INVALID) + rtwn_set_macaddr(sc, vap->iv_myaddr, uvp->id); + + rtwn_rxfilter_update(sc); + } + RTWN_UNLOCK(sc); + return (vap); + +fail: + RTWN_UNLOCK(sc); + return (NULL); } static void rtwn_vap_delete(struct ieee80211vap *vap) { - struct rtwn_vap *rvp = RTWN_VAP(vap); + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_softc *sc = ic->ic_softc; + struct rtwn_vap *uvp = RTWN_VAP(vap); + /* Put vap into INIT state + stop device if needed. */ + ieee80211_stop(vap); + ieee80211_draintask(ic, &vap->iv_nstate_task); + ieee80211_draintask(ic, &ic->ic_parent_task); + + RTWN_LOCK(sc); + /* Cancel any unfinished Tx. */ + rtwn_reset_lists(sc, vap); + if (uvp->bcn_mbuf != NULL) + m_freem(uvp->bcn_mbuf); + rtwn_vap_decrement_counters(sc, vap->iv_opmode, uvp->id); + rtwn_set_ic_opmode(sc); + if (sc->sc_flags & RTWN_RUNNING) + rtwn_rxfilter_update(sc); + RTWN_UNLOCK(sc); + + if (vap->iv_opmode == IEEE80211_M_IBSS) { + ieee80211_draintask(ic, &uvp->tsf_sync_adhoc_task); + callout_drain(&uvp->tsf_sync_adhoc); + } + + ieee80211_ratectl_deinit(vap); ieee80211_vap_detach(vap); - free(rvp, M_80211_VAP); -} - -static void -rtwn_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val) -{ - - bus_space_write_1(sc->sc_st, sc->sc_sh, addr, val); -} - -static void -rtwn_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val) -{ - - val = htole16(val); - bus_space_write_2(sc->sc_st, sc->sc_sh, addr, val); -} - -void -rtwn_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val) -{ - - val = htole32(val); - bus_space_write_4(sc->sc_st, sc->sc_sh, addr, val); -} - -static uint8_t -rtwn_read_1(struct rtwn_softc *sc, uint16_t addr) -{ - - return (bus_space_read_1(sc->sc_st, sc->sc_sh, addr)); -} - -static uint16_t -rtwn_read_2(struct rtwn_softc *sc, uint16_t addr) -{ - - return (bus_space_read_2(sc->sc_st, sc->sc_sh, addr)); -} - -uint32_t -rtwn_read_4(struct rtwn_softc *sc, uint16_t addr) -{ - - return (bus_space_read_4(sc->sc_st, sc->sc_sh, addr)); -} - -static int -rtwn_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) -{ - struct r92c_fw_cmd cmd; - int ntries; - - /* Wait for current FW box to be empty. */ - for (ntries = 0; ntries < 100; ntries++) { - if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) - break; - DELAY(1); - } - if (ntries == 100) { - device_printf(sc->sc_dev, - "could not send firmware command %d\n", id); - return (ETIMEDOUT); - } - memset(&cmd, 0, sizeof(cmd)); - cmd.id = id; - if (len > 3) - cmd.id |= R92C_CMD_FLAG_EXT; - KASSERT(len <= sizeof(cmd.msg), ("rtwn_fw_cmd\n")); - memcpy(cmd.msg, buf, len); - - /* Write the first word last since that will trigger the FW. */ - rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), *((uint8_t *)&cmd + 4)); - rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *((uint8_t *)&cmd + 0)); - - sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; - - /* Give firmware some time for processing. */ - DELAY(2000); - - return (0); -} - -static void -rtwn_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val) -{ - rtwn_bb_write(sc, R92C_LSSI_PARAM(chain), - SM(R92C_LSSI_PARAM_ADDR, addr) | - SM(R92C_LSSI_PARAM_DATA, val)); -} - -static uint32_t -rtwn_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) -{ - uint32_t reg[R92C_MAX_CHAINS], val; - - reg[0] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)); - if (chain != 0) - reg[chain] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain)); - - rtwn_bb_write(sc, R92C_HSSI_PARAM2(0), - reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE); - DELAY(1000); - - rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain), - RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) | - R92C_HSSI_PARAM2_READ_EDGE); - DELAY(1000); - - rtwn_bb_write(sc, R92C_HSSI_PARAM2(0), - reg[0] | R92C_HSSI_PARAM2_READ_EDGE); - DELAY(1000); - - if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI) - val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain)); - else - val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain)); - return (MS(val, R92C_LSSI_READBACK_DATA)); -} - -static int -rtwn_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) -{ - int ntries; - - rtwn_write_4(sc, R92C_LLT_INIT, - SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) | - SM(R92C_LLT_INIT_ADDR, addr) | - SM(R92C_LLT_INIT_DATA, data)); - /* Wait for write operation to complete. */ - for (ntries = 0; ntries < 20; ntries++) { - if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) == - R92C_LLT_INIT_OP_NO_ACTIVE) - return (0); - DELAY(5); - } - return (ETIMEDOUT); -} - -static uint8_t -rtwn_efuse_read_1(struct rtwn_softc *sc, uint16_t addr) -{ - uint32_t reg; - int ntries; - - reg = rtwn_read_4(sc, R92C_EFUSE_CTRL); - reg = RW(reg, R92C_EFUSE_CTRL_ADDR, addr); - reg &= ~R92C_EFUSE_CTRL_VALID; - rtwn_write_4(sc, R92C_EFUSE_CTRL, reg); - /* Wait for read operation to complete. */ - for (ntries = 0; ntries < 100; ntries++) { - reg = rtwn_read_4(sc, R92C_EFUSE_CTRL); - if (reg & R92C_EFUSE_CTRL_VALID) - return (MS(reg, R92C_EFUSE_CTRL_DATA)); - DELAY(5); - } - device_printf(sc->sc_dev, - "could not read efuse byte at address 0x%x\n", addr); - return (0xff); -} - -static void -rtwn_efuse_read(struct rtwn_softc *sc) -{ - uint8_t *rom = (uint8_t *)&sc->rom; - uint16_t addr = 0; - uint32_t reg; - uint8_t off, msk; - int i; - - reg = rtwn_read_2(sc, R92C_SYS_ISO_CTRL); - if (!(reg & R92C_SYS_ISO_CTRL_PWC_EV12V)) { - rtwn_write_2(sc, R92C_SYS_ISO_CTRL, - reg | R92C_SYS_ISO_CTRL_PWC_EV12V); - } - reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); - if (!(reg & R92C_SYS_FUNC_EN_ELDR)) { - rtwn_write_2(sc, R92C_SYS_FUNC_EN, - reg | R92C_SYS_FUNC_EN_ELDR); - } - reg = rtwn_read_2(sc, R92C_SYS_CLKR); - if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) != - (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { - rtwn_write_2(sc, R92C_SYS_CLKR, - reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); - } - memset(&sc->rom, 0xff, sizeof(sc->rom)); - while (addr < 512) { - reg = rtwn_efuse_read_1(sc, addr); - if (reg == 0xff) - break; - addr++; - off = reg >> 4; - msk = reg & 0xf; - for (i = 0; i < 4; i++) { - if (msk & (1 << i)) - continue; - rom[off * 8 + i * 2 + 0] = - rtwn_efuse_read_1(sc, addr); - addr++; - rom[off * 8 + i * 2 + 1] = - rtwn_efuse_read_1(sc, addr); - addr++; - } - } -#ifdef RTWN_DEBUG - if (sc->sc_debug >= 2) { - /* Dump ROM content. */ - printf("\n"); - for (i = 0; i < sizeof(sc->rom); i++) - printf("%02x:", rom[i]); - printf("\n"); - } -#endif + free(uvp, M_80211_VAP); } static int @@ -1019,876 +652,703 @@ rtwn_read_chipid(struct rtwn_softc *sc) uint32_t reg; reg = rtwn_read_4(sc, R92C_SYS_CFG); - if (reg & R92C_SYS_CFG_TRP_VAUX_EN) - /* Unsupported test chip. */ - return (EIO); + if (reg & R92C_SYS_CFG_TRP_VAUX_EN) /* test chip */ + return (EOPNOTSUPP); + + rtwn_read_chipid_vendor(sc, reg); - if (reg & R92C_SYS_CFG_TYPE_92C) { - sc->chip |= RTWN_CHIP_92C; - /* Check if it is a castrated 8192C. */ - if (MS(rtwn_read_4(sc, R92C_HPON_FSM), - R92C_HPON_FSM_CHIP_BONDING_ID) == - R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R) - sc->chip |= RTWN_CHIP_92C_1T2R; - } - if (reg & R92C_SYS_CFG_VENDOR_UMC) { - sc->chip |= RTWN_CHIP_UMC; - if (MS(reg, R92C_SYS_CFG_CHIP_VER_RTL) == 0) - sc->chip |= RTWN_CHIP_UMC_A_CUT; - } return (0); } -static void -rtwn_read_rom(struct rtwn_softc *sc) +static int +rtwn_ioctl_reset(struct ieee80211vap *vap, u_long cmd) { - struct r92c_rom *rom = &sc->rom; + int error; - /* Read full ROM image. */ - rtwn_efuse_read(sc); + switch (cmd) { +#ifndef RTWN_WITHOUT_UCODE + case IEEE80211_IOC_POWERSAVE: + case IEEE80211_IOC_POWERSAVESLEEP: + { + struct rtwn_softc *sc = vap->iv_ic->ic_softc; + struct rtwn_vap *uvp = RTWN_VAP(vap); - if (rom->id != 0x8129) - device_printf(sc->sc_dev, "invalid EEPROM ID 0x%x\n", rom->id); + if (vap->iv_opmode == IEEE80211_M_STA && uvp->id == 0) { + RTWN_LOCK(sc); + if (sc->sc_flags & RTWN_RUNNING) + error = rtwn_set_pwrmode(sc, vap, 1); + else + error = 0; + RTWN_UNLOCK(sc); + if (error != 0) + error = ENETRESET; + } else + error = EOPNOTSUPP; + break; + } +#endif + case IEEE80211_IOC_SHORTGI: + case IEEE80211_IOC_RTSTHRESHOLD: + case IEEE80211_IOC_PROTMODE: + case IEEE80211_IOC_HTPROTMODE: + case IEEE80211_IOC_LDPC: + error = 0; + break; + default: + error = ENETRESET; + break; + } - /* XXX Weird but this is what the vendor driver does. */ - sc->pa_setting = rtwn_efuse_read_1(sc, 0x1fa); - DPRINTF(("PA setting=0x%x\n", sc->pa_setting)); - - sc->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE); - - sc->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY); - DPRINTF(("regulatory type=%d\n", sc->regulatory)); - - IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); + return (error); } -static __inline uint8_t -rate2ridx(uint8_t rate) +static void +rtwn_set_media_status(struct rtwn_softc *sc, union sec_param *data) { - switch (rate) { - case 12: return 4; - case 18: return 5; - case 24: return 6; - case 36: return 7; - case 48: return 8; - case 72: return 9; - case 96: return 10; - case 108: return 11; - case 2: return 0; - case 4: return 1; - case 11: return 2; - case 22: return 3; - default: return RTWN_RIDX_UNKNOWN; + sc->sc_set_media_status(sc, data->macid); +} + +#ifndef RTWN_WITHOUT_UCODE +static int +rtwn_tx_fwpkt_check(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + int ntries, error; + + for (ntries = 0; ntries < 5; ntries++) { + error = rtwn_push_nulldata(sc, vap); + if (error == 0) + break; + } + if (ntries == 5) { + device_printf(sc->sc_dev, + "%s: cannot push f/w frames into chip, error %d!\n", + __func__, error); + return (error); + } + + return (0); +} + +static int +rtwn_construct_nulldata(struct rtwn_softc *sc, struct ieee80211vap *vap, + uint8_t *ptr, int qos) +{ + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211com *ic = &sc->sc_ic; + struct rtwn_tx_desc_common *txd; + struct ieee80211_frame *wh; + int pktlen; + + /* XXX obtain from net80211 */ + wh = (struct ieee80211_frame *)(ptr + sc->txdesc_len); + wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; + wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; + IEEE80211_ADDR_COPY(wh->i_addr1, vap->iv_bss->ni_bssid); + IEEE80211_ADDR_COPY(wh->i_addr2, vap->iv_myaddr); + IEEE80211_ADDR_COPY(wh->i_addr3, vap->iv_bss->ni_macaddr); + + txd = (struct rtwn_tx_desc_common *)ptr; + txd->offset = sc->txdesc_len; + pktlen = sc->txdesc_len; + if (qos) { + struct ieee80211_qosframe *qwh; + const int tid = WME_AC_TO_TID(WME_AC_BE); + + qwh = (struct ieee80211_qosframe *)wh; + qwh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_QOS_NULL; + qwh->i_qos[0] = tid & IEEE80211_QOS_TID; + + txd->pktlen = htole16(sizeof(struct ieee80211_qosframe)); + pktlen += sizeof(struct ieee80211_qosframe); + } else { + wh->i_fc[0] |= IEEE80211_FC0_SUBTYPE_NODATA; + + txd->pktlen = htole16(sizeof(struct ieee80211_frame)); + pktlen += sizeof(struct ieee80211_frame); + } + + rtwn_fill_tx_desc_null(sc, ptr, + ic->ic_curmode == IEEE80211_MODE_11B, qos, uvp->id); + + return (pktlen); +} + +static int +rtwn_push_nulldata(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211com *ic = vap->iv_ic; + struct ieee80211_channel *c = ic->ic_curchan; + struct mbuf *m; + uint8_t *ptr; + int required_size, bcn_size, null_size, null_data, error; + + if (!(sc->sc_flags & RTWN_FW_LOADED)) + return (0); /* requires firmware */ + + KASSERT(sc->page_size > 0, ("page size was not set!\n")); + + /* Leave some space for beacon (multi-vap) */ + bcn_size = roundup(RTWN_BCN_MAX_SIZE, sc->page_size); + /* 1 page for Null Data + 1 page for Qos Null Data frames. */ + required_size = bcn_size + sc->page_size * 2; + + m = m_get2(required_size, M_NOWAIT, MT_DATA, M_PKTHDR); + if (m == NULL) + return (ENOMEM); + + /* Setup beacon descriptor. */ + rtwn_beacon_set_rate(sc, &uvp->bcn_desc.txd[0], + IEEE80211_IS_CHAN_5GHZ(c)); + + ptr = mtod(m, uint8_t *); + memset(ptr, 0, required_size - sc->txdesc_len); + + /* Construct Null Data frame. */ + ptr += bcn_size - sc->txdesc_len; + null_size = rtwn_construct_nulldata(sc, vap, ptr, 0); + KASSERT(null_size < sc->page_size, + ("recalculate size for Null Data frame\n")); + + /* Construct Qos Null Data frame. */ + ptr += roundup(null_size, sc->page_size); + null_size = rtwn_construct_nulldata(sc, vap, ptr, 1); + KASSERT(null_size < sc->page_size, + ("recalculate size for Qos Null Data frame\n")); + + /* Do not try to detect a beacon here. */ + rtwn_setbits_1_shift(sc, R92C_CR, 0, R92C_CR_ENSWBCN, 1); + rtwn_setbits_1_shift(sc, R92C_FWHW_TXQ_CTRL, + R92C_FWHW_TXQ_CTRL_REAL_BEACON, 0, 2); + + if (uvp->bcn_mbuf != NULL) { + rtwn_beacon_unload(sc, uvp->id); + m_freem(uvp->bcn_mbuf); + } + + m->m_pkthdr.len = m->m_len = required_size - sc->txdesc_len; + uvp->bcn_mbuf = m; + + error = rtwn_tx_beacon_check(sc, uvp); + if (error != 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON, + "%s: frame was not recognized!\n", __func__); + goto fail; + } + + /* Setup addresses in firmware. */ + null_data = howmany(bcn_size, sc->page_size); + error = rtwn_set_rsvd_page(sc, 0, null_data, null_data + 1); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: CMD_RSVD_PAGE was not sent, error %d\n", + __func__, error); + goto fail; + } + +fail: + /* Re-enable beacon detection. */ + rtwn_setbits_1_shift(sc, R92C_FWHW_TXQ_CTRL, + 0, R92C_FWHW_TXQ_CTRL_REAL_BEACON, 2); + rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSWBCN, 0, 1); + + /* Restore beacon (if present). */ + if (sc->bcn_vaps > 0 && sc->vaps[!uvp->id] != NULL) { + struct rtwn_vap *uvp2 = sc->vaps[!uvp->id]; + + if (uvp2->curr_mode != R92C_MSR_NOLINK) + error = rtwn_tx_beacon_check(sc, uvp2); + } + + return (error); +} + +static void +rtwn_pwrmode_init(void *arg) +{ + struct rtwn_softc *sc = arg; + + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_set_pwrmode_cb); +} + +static void +rtwn_set_pwrmode_cb(struct rtwn_softc *sc, union sec_param *data) +{ + struct ieee80211vap *vap = &sc->vaps[0]->vap; + + if (vap != NULL) + rtwn_set_pwrmode(sc, vap, 1); +} +#endif + +static void +rtwn_tsf_sync_adhoc(void *arg) +{ + struct ieee80211vap *vap = arg; + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_vap *uvp = RTWN_VAP(vap); + + if (uvp->curr_mode != R92C_MSR_NOLINK) { + /* Do it in process context. */ + ieee80211_runtask(ic, &uvp->tsf_sync_adhoc_task); } } /* - * Initialize rate adaptation in firmware. + * Workaround for TSF synchronization: + * when BSSID filter in IBSS mode is not set + * (and TSF synchronization is enabled), then any beacon may update it. + * This routine synchronizes it when BSSID matching is enabled (IBSS merge + * is not possible during this period). + * + * NOTE: there is no race with rtwn_newstate(), since it uses the same + * taskqueue. */ -static int -rtwn_ra_init(struct rtwn_softc *sc) +static void +rtwn_tsf_sync_adhoc_task(void *arg, int pending) +{ + struct ieee80211vap *vap = arg; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct rtwn_softc *sc = vap->iv_ic->ic_softc; + struct ieee80211_node *ni; + + RTWN_LOCK(sc); + ni = ieee80211_ref_node(vap->iv_bss); + + /* Accept beacons with the same BSSID. */ + rtwn_set_rx_bssid_all(sc, 0); + + /* Deny RCR updates. */ + sc->sc_flags |= RTWN_RCR_LOCKED; + + /* Enable synchronization. */ + rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id), + R92C_BCN_CTRL_DIS_TSF_UDT0, 0); + + /* Synchronize. */ + rtwn_delay(sc, ni->ni_intval * 5 * 1000); + + /* Disable synchronization. */ + rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id), + 0, R92C_BCN_CTRL_DIS_TSF_UDT0); + + /* Accept all beacons. */ + sc->sc_flags &= ~RTWN_RCR_LOCKED; + rtwn_set_rx_bssid_all(sc, 1); + + /* Schedule next TSF synchronization. */ + callout_reset(&uvp->tsf_sync_adhoc, 60*hz, rtwn_tsf_sync_adhoc, vap); + + ieee80211_free_node(ni); + RTWN_UNLOCK(sc); +} + +static void +rtwn_tsf_sync_enable(struct rtwn_softc *sc, struct ieee80211vap *vap) { struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = ieee80211_ref_node(vap->iv_bss); - struct ieee80211_rateset *rs = &ni->ni_rates; - struct r92c_fw_cmd_macid_cfg cmd; - uint32_t rates, basicrates; - uint8_t maxrate, maxbasicrate, mode, ridx; - int error, i; + struct rtwn_vap *uvp = RTWN_VAP(vap); - /* Get normal and basic rates mask. */ - rates = basicrates = 0; - maxrate = maxbasicrate = 0; - for (i = 0; i < rs->rs_nrates; i++) { - /* Convert 802.11 rate to HW rate index. */ - ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i])); - if (ridx == RTWN_RIDX_UNKNOWN) /* Unknown rate, skip. */ - continue; - rates |= 1 << ridx; - if (ridx > maxrate) - maxrate = ridx; - if (rs->rs_rates[i] & IEEE80211_RATE_BASIC) { - basicrates |= 1 << ridx; - if (ridx > maxbasicrate) - maxbasicrate = ridx; - } + /* Reset TSF. */ + rtwn_write_1(sc, R92C_DUAL_TSF_RST, R92C_DUAL_TSF_RESET(uvp->id)); + + switch (vap->iv_opmode) { + case IEEE80211_M_STA: + /* Enable TSF synchronization. */ + rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id), + R92C_BCN_CTRL_DIS_TSF_UDT0, 0); + break; + case IEEE80211_M_IBSS: + ieee80211_runtask(ic, &uvp->tsf_sync_adhoc_task); + /* FALLTHROUGH */ + case IEEE80211_M_HOSTAP: + /* Enable beaconing. */ + rtwn_beacon_enable(sc, uvp->id, 1); + break; + default: + device_printf(sc->sc_dev, "undefined opmode %d\n", + vap->iv_opmode); + return; } - if (ic->ic_curmode == IEEE80211_MODE_11B) - mode = R92C_RAID_11B; +} + +static void +rtwn_set_ack_preamble(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t reg; + + reg = rtwn_read_4(sc, R92C_WMAC_TRXPTCL_CTL); + if (ic->ic_flags & IEEE80211_F_SHPREAMBLE) + reg |= R92C_WMAC_TRXPTCL_SHPRE; else - mode = R92C_RAID_11BG; - DPRINTF(("mode=0x%x rates=0x%08x, basicrates=0x%08x\n", - mode, rates, basicrates)); - - /* Set rates mask for group addressed frames. */ - cmd.macid = RTWN_MACID_BC | RTWN_MACID_VALID; - cmd.mask = htole32(mode << 28 | basicrates); - error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); - if (error != 0) { - device_printf(sc->sc_dev, - "could not add broadcast station\n"); - return (error); - } - /* Set initial MRR rate. */ - DPRINTF(("maxbasicrate=%d\n", maxbasicrate)); - rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(RTWN_MACID_BC), - maxbasicrate); - - /* Set rates mask for unicast frames. */ - cmd.macid = RTWN_MACID_BSS | RTWN_MACID_VALID; - cmd.mask = htole32(mode << 28 | rates); - error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); - if (error != 0) { - device_printf(sc->sc_dev, "could not add BSS station\n"); - return (error); - } - /* Set initial MRR rate. */ - DPRINTF(("maxrate=%d\n", maxrate)); - rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(RTWN_MACID_BSS), - maxrate); - - /* Configure Automatic Rate Fallback Register. */ - if (ic->ic_curmode == IEEE80211_MODE_11B) { - if (rates & 0x0c) - rtwn_write_4(sc, R92C_ARFR(0), htole32(rates & 0x0d)); - else - rtwn_write_4(sc, R92C_ARFR(0), htole32(rates & 0x0f)); - } else - rtwn_write_4(sc, R92C_ARFR(0), htole32(rates & 0x0ff5)); - - /* Indicate highest supported rate. */ - ni->ni_txrate = rs->rs_rates[rs->rs_nrates - 1]; - return (0); + reg &= ~R92C_WMAC_TRXPTCL_SHPRE; + rtwn_write_4(sc, R92C_WMAC_TRXPTCL_CTL, reg); } static void -rtwn_tsf_sync_enable(struct rtwn_softc *sc) +rtwn_set_mode(struct rtwn_softc *sc, uint8_t mode, int id) { - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - struct ieee80211_node *ni = vap->iv_bss; - uint64_t tsf; - /* Enable TSF synchronization. */ - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_DIS_TSF_UDT0); - - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) & ~R92C_BCN_CTRL_EN_BCN); - - /* Set initial TSF. */ - memcpy(&tsf, ni->ni_tstamp.data, 8); - tsf = le64toh(tsf); - tsf = tsf - (tsf % (vap->iv_bss->ni_intval * IEEE80211_DUR_TU)); - tsf -= IEEE80211_DUR_TU; - rtwn_write_4(sc, R92C_TSFTR + 0, tsf); - rtwn_write_4(sc, R92C_TSFTR + 4, tsf >> 32); - - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) | R92C_BCN_CTRL_EN_BCN); + rtwn_setbits_1(sc, R92C_MSR, R92C_MSR_MASK << id * 2, mode << id * 2); + if (sc->vaps[id] != NULL) + sc->vaps[id]->curr_mode = mode; } -static void -rtwn_set_led(struct rtwn_softc *sc, int led, int on) +static int +rtwn_monitor_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, + int arg) { - uint8_t reg; + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_softc *sc = ic->ic_softc; + struct rtwn_vap *uvp = RTWN_VAP(vap); - if (led == RTWN_LED_LINK) { - reg = rtwn_read_1(sc, R92C_LEDCFG2) & 0xf0; - if (!on) - reg |= R92C_LEDCFG2_DIS; - else - reg |= R92C_LEDCFG2_EN; - rtwn_write_1(sc, R92C_LEDCFG2, reg); - sc->ledlink = on; /* Save LED state. */ - } -} + RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s -> %s\n", + ieee80211_state_name[vap->iv_state], + ieee80211_state_name[nstate]); -static void -rtwn_calib_to(void *arg) -{ - struct rtwn_softc *sc = arg; - struct r92c_fw_cmd_rssi cmd; + if (vap->iv_state != nstate) { + IEEE80211_UNLOCK(ic); + RTWN_LOCK(sc); - if (sc->avg_pwdb != -1) { - /* Indicate Rx signal strength to FW for rate adaptation. */ - memset(&cmd, 0, sizeof(cmd)); - cmd.macid = 0; /* BSS. */ - cmd.pwdb = sc->avg_pwdb; - DPRINTFN(3, ("sending RSSI command avg=%d\n", sc->avg_pwdb)); - rtwn_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd)); + switch (nstate) { + case IEEE80211_S_INIT: + sc->vaps_running--; + sc->monvaps_running--; + + if (sc->vaps_running == 0) { + /* Turn link LED off. */ + rtwn_set_led(sc, RTWN_LED_LINK, 0); + } + break; + case IEEE80211_S_RUN: + sc->vaps_running++; + sc->monvaps_running++; + + if (sc->vaps_running == 1) { + /* Turn link LED on. */ + rtwn_set_led(sc, RTWN_LED_LINK, 1); + } + break; + default: + /* NOTREACHED */ + break; + } + + RTWN_UNLOCK(sc); + IEEE80211_LOCK(ic); } - /* Do temperature compensation. */ - rtwn_temp_calib(sc); - - callout_reset(&sc->calib_to, hz * 2, rtwn_calib_to, sc); + return (uvp->newstate(vap, nstate, arg)); } static int rtwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) { - struct rtwn_vap *rvp = RTWN_VAP(vap); + struct rtwn_vap *uvp = RTWN_VAP(vap); struct ieee80211com *ic = vap->iv_ic; - struct ieee80211_node *ni = vap->iv_bss; struct rtwn_softc *sc = ic->ic_softc; - uint32_t reg; + enum ieee80211_state ostate; + int error, early_newstate; + ostate = vap->iv_state; + RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s -> %s\n", + ieee80211_state_name[ostate], ieee80211_state_name[nstate]); + + if (vap->iv_bss->ni_chan == IEEE80211_CHAN_ANYC && + ostate == IEEE80211_S_INIT && nstate == IEEE80211_S_RUN) { + /* need to call iv_newstate() firstly */ + error = uvp->newstate(vap, nstate, arg); + if (error != 0) + return (error); + + early_newstate = 1; + } else + early_newstate = 0; + + if (ostate == IEEE80211_S_CSA) { + taskqueue_cancel_timeout(taskqueue_thread, + &uvp->tx_beacon_csa, NULL); + + /* + * In multi-vap case second counter may not be cleared + * properly. + */ + vap->iv_csa_count = 0; + } IEEE80211_UNLOCK(ic); RTWN_LOCK(sc); - if (vap->iv_state == IEEE80211_S_RUN) { - /* Stop calibration. */ - callout_stop(&sc->calib_to); + if (ostate == IEEE80211_S_CSA) { + /* Unblock all queues (multi-vap case). */ + rtwn_write_1(sc, R92C_TXPAUSE, 0); + } - /* Turn link LED off. */ - rtwn_set_led(sc, RTWN_LED_LINK, 0); + if ((ostate == IEEE80211_S_RUN && nstate != IEEE80211_S_CSA) || + ostate == IEEE80211_S_CSA) { + sc->vaps_running--; /* Set media status to 'No Link'. */ - reg = rtwn_read_4(sc, R92C_CR); - reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_NOLINK); - rtwn_write_4(sc, R92C_CR, reg); + rtwn_set_mode(sc, R92C_MSR_NOLINK, uvp->id); - /* Stop Rx of data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0); + if (vap->iv_opmode == IEEE80211_M_IBSS) { + /* Stop periodical TSF synchronization. */ + callout_stop(&uvp->tsf_sync_adhoc); + } - /* Rest TSF. */ - rtwn_write_1(sc, R92C_DUAL_TSF_RST, 0x03); + /* Disable TSF synchronization / beaconing. */ + rtwn_beacon_enable(sc, uvp->id, 0); + rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id), + 0, R92C_BCN_CTRL_DIS_TSF_UDT0); - /* Disable TSF synchronization. */ - rtwn_write_1(sc, R92C_BCN_CTRL, - rtwn_read_1(sc, R92C_BCN_CTRL) | - R92C_BCN_CTRL_DIS_TSF_UDT0); + /* NB: monitor mode vaps are using port 0. */ + if (uvp->id != 0 || sc->monvaps_running == 0) { + /* Reset TSF. */ + rtwn_write_1(sc, R92C_DUAL_TSF_RST, + R92C_DUAL_TSF_RESET(uvp->id)); + } - /* Reset EDCA parameters. */ - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3217); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4317); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x00105320); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a444); +#ifndef RTWN_WITHOUT_UCODE + if ((ic->ic_caps & IEEE80211_C_PMGT) != 0 && uvp->id == 0) { + /* Disable power management. */ + callout_stop(&sc->sc_pwrmode_init); + rtwn_set_pwrmode(sc, vap, 0); + } +#endif + if (sc->vaps_running - sc->monvaps_running > 0) { + /* Recalculate basic rates bitmap. */ + rtwn_calc_basicrates(sc); + } + + if (sc->vaps_running == sc->monvaps_running) { + /* Stop calibration. */ + callout_stop(&sc->sc_calib_to); + + /* Stop Rx of data frames. */ + rtwn_write_2(sc, R92C_RXFLTMAP2, 0); + + /* Reset EDCA parameters. */ + rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3217); + rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4317); + rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x00105320); + rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a444); + + if (sc->vaps_running == 0) { + /* Turn link LED off. */ + rtwn_set_led(sc, RTWN_LED_LINK, 0); + } + } } - switch (nstate) { - case IEEE80211_S_INIT: - /* Turn link LED off. */ - rtwn_set_led(sc, RTWN_LED_LINK, 0); - break; - case IEEE80211_S_SCAN: - /* Make link LED blink during scan. */ - rtwn_set_led(sc, RTWN_LED_LINK, !sc->ledlink); + error = 0; + switch (nstate) { + case IEEE80211_S_SCAN: /* Pause AC Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, - rtwn_read_1(sc, R92C_TXPAUSE) | 0x0f); - break; - case IEEE80211_S_AUTH: - rtwn_set_chan(sc, ic->ic_curchan, NULL); + if (sc->vaps_running == 0) + rtwn_setbits_1(sc, R92C_TXPAUSE, 0, R92C_TX_QUEUE_AC); break; case IEEE80211_S_RUN: - if (ic->ic_opmode == IEEE80211_M_MONITOR) { - /* Enable Rx of data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); - - /* Turn link LED on. */ - rtwn_set_led(sc, RTWN_LED_LINK, 1); + error = rtwn_run(sc, vap); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not move to RUN state\n", __func__); break; } - /* Set media status to 'Associated'. */ - reg = rtwn_read_4(sc, R92C_CR); - reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA); - rtwn_write_4(sc, R92C_CR, reg); + sc->vaps_running++; + break; + case IEEE80211_S_CSA: + /* Block all Tx queues (except beacon queue). */ + rtwn_setbits_1(sc, R92C_TXPAUSE, 0, + R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); + break; + default: + break; + } - /* Set BSSID. */ - rtwn_write_4(sc, R92C_BSSID + 0, le32dec(&ni->ni_bssid[0])); - rtwn_write_4(sc, R92C_BSSID + 4, le16dec(&ni->ni_bssid[4])); + RTWN_UNLOCK(sc); + IEEE80211_LOCK(ic); + if (error != 0) + return (error); - if (ic->ic_curmode == IEEE80211_MODE_11B) - rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 0); - else /* 802.11b/g */ - rtwn_write_1(sc, R92C_INIRTS_RATE_SEL, 3); + return (early_newstate ? 0 : uvp->newstate(vap, nstate, arg)); +} +static void +rtwn_calc_basicrates(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t basicrates; + int i; + + RTWN_ASSERT_LOCKED(sc); + + if (ic->ic_flags & IEEE80211_F_SCAN) + return; /* will be done by rtwn_scan_end(). */ + + basicrates = 0; + for (i = 0; i < nitems(sc->vaps); i++) { + struct rtwn_vap *rvp; + struct ieee80211vap *vap; + struct ieee80211_node *ni; + uint32_t rates; + + rvp = sc->vaps[i]; + if (rvp == NULL || rvp->curr_mode == R92C_MSR_NOLINK) + continue; + + vap = &rvp->vap; + if (vap->iv_bss == NULL) + continue; + + ni = ieee80211_ref_node(vap->iv_bss); + rtwn_get_rates(sc, &ni->ni_rates, NULL, &rates, NULL, 1); + basicrates |= rates; + ieee80211_free_node(ni); + } + + if (basicrates == 0) + return; + + /* XXX initial RTS rate? */ + rtwn_set_basicrates(sc, basicrates); +} + +static int +rtwn_run(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211_node *ni; + uint8_t mode; + int error; + + RTWN_ASSERT_LOCKED(sc); + + error = 0; + ni = ieee80211_ref_node(vap->iv_bss); + + if (ic->ic_bsschan == IEEE80211_CHAN_ANYC || + ni->ni_chan == IEEE80211_CHAN_ANYC) { + error = EINVAL; + goto fail; + } + + switch (vap->iv_opmode) { + case IEEE80211_M_STA: + mode = R92C_MSR_INFRA; + break; + case IEEE80211_M_IBSS: + mode = R92C_MSR_ADHOC; + break; + case IEEE80211_M_HOSTAP: + mode = R92C_MSR_AP; + break; + default: + KASSERT(0, ("undefined opmode %d\n", vap->iv_opmode)); + error = EINVAL; + goto fail; + } + + /* Set media status to 'Associated'. */ + rtwn_set_mode(sc, mode, uvp->id); + + /* Set AssocID. */ + /* XXX multi-vap? */ + rtwn_write_2(sc, R92C_BCN_PSR_RPT, + 0xc000 | IEEE80211_NODE_AID(ni)); + + /* Set BSSID. */ + rtwn_set_bssid(sc, ni->ni_bssid, uvp->id); + + /* Set beacon interval. */ + rtwn_write_2(sc, R92C_BCN_INTERVAL(uvp->id), ni->ni_intval); + + if (sc->vaps_running == sc->monvaps_running) { /* Enable Rx of data frames. */ rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); /* Flush all AC queues. */ rtwn_write_1(sc, R92C_TXPAUSE, 0); - - /* Set beacon interval. */ - rtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval); - - /* Allow Rx from our BSSID only. */ - rtwn_write_4(sc, R92C_RCR, - rtwn_read_4(sc, R92C_RCR) | - R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN); - - /* Enable TSF synchronization. */ - rtwn_tsf_sync_enable(sc); - - rtwn_write_1(sc, R92C_SIFS_CCK + 1, 10); - rtwn_write_1(sc, R92C_SIFS_OFDM + 1, 10); - rtwn_write_1(sc, R92C_SPEC_SIFS + 1, 10); - rtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, 10); - rtwn_write_1(sc, R92C_R2T_SIFS + 1, 10); - rtwn_write_1(sc, R92C_T2T_SIFS + 1, 10); - - /* Intialize rate adaptation. */ - rtwn_ra_init(sc); - /* Turn link LED on. */ - rtwn_set_led(sc, RTWN_LED_LINK, 1); - - sc->avg_pwdb = -1; /* Reset average RSSI. */ - /* Reset temperature calibration state machine. */ - sc->thcal_state = 0; - sc->thcal_lctemp = 0; - /* Start periodic calibration. */ - callout_reset(&sc->calib_to, hz * 2, rtwn_calib_to, sc); - break; - default: - break; } - RTWN_UNLOCK(sc); - IEEE80211_LOCK(ic); - return (rvp->newstate(vap, nstate, arg)); -} -static int -rtwn_updateedca(struct ieee80211com *ic) -{ - struct rtwn_softc *sc = ic->ic_softc; - const uint16_t aci2reg[WME_NUM_AC] = { - R92C_EDCA_BE_PARAM, - R92C_EDCA_BK_PARAM, - R92C_EDCA_VI_PARAM, - R92C_EDCA_VO_PARAM - }; - int aci, aifs, slottime; +#ifndef RTWN_WITHOUT_UCODE + /* Upload (QoS) Null Data frame to firmware. */ + /* Note: do this for port 0 only. */ + if ((ic->ic_caps & IEEE80211_C_PMGT) != 0 && + vap->iv_opmode == IEEE80211_M_STA && uvp->id == 0) { + error = rtwn_tx_fwpkt_check(sc, vap); + if (error != 0) + goto fail; - IEEE80211_LOCK(ic); - slottime = (ic->ic_flags & IEEE80211_F_SHSLOT) ? 9 : 20; - for (aci = 0; aci < WME_NUM_AC; aci++) { - const struct wmeParams *ac = - &ic->ic_wme.wme_chanParams.cap_wmeParams[aci]; - /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */ - aifs = ac->wmep_aifsn * slottime + 10; - rtwn_write_4(sc, aci2reg[aci], - SM(R92C_EDCA_PARAM_TXOP, ac->wmep_txopLimit) | - SM(R92C_EDCA_PARAM_ECWMIN, ac->wmep_logcwmin) | - SM(R92C_EDCA_PARAM_ECWMAX, ac->wmep_logcwmax) | - SM(R92C_EDCA_PARAM_AIFS, aifs)); - } - IEEE80211_UNLOCK(ic); - return (0); -} - -static void -rtwn_update_avgrssi(struct rtwn_softc *sc, int rate, int8_t rssi) -{ - int pwdb; - - /* Convert antenna signal to percentage. */ - if (rssi <= -100 || rssi >= 20) - pwdb = 0; - else if (rssi >= 0) - pwdb = 100; - else - pwdb = 100 + rssi; - if (RTWN_RATE_IS_CCK(rate)) { - /* CCK gain is smaller than OFDM/MCS gain. */ - pwdb += 6; - if (pwdb > 100) - pwdb = 100; - if (pwdb <= 14) - pwdb -= 4; - else if (pwdb <= 26) - pwdb -= 8; - else if (pwdb <= 34) - pwdb -= 6; - else if (pwdb <= 42) - pwdb -= 2; - } - if (sc->avg_pwdb == -1) /* Init. */ - sc->avg_pwdb = pwdb; - else if (sc->avg_pwdb < pwdb) - sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20) + 1; - else - sc->avg_pwdb = ((sc->avg_pwdb * 19 + pwdb) / 20); - DPRINTFN(4, ("PWDB=%d EMA=%d\n", pwdb, sc->avg_pwdb)); -} - -static int8_t -rtwn_get_rssi(struct rtwn_softc *sc, int rate, void *physt) -{ - static const int8_t cckoff[] = { 16, -12, -26, -46 }; - struct r92c_rx_phystat *phy; - struct r92c_rx_cck *cck; - uint8_t rpt; - int8_t rssi; - - if (RTWN_RATE_IS_CCK(rate)) { - cck = (struct r92c_rx_cck *)physt; - if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) { - rpt = (cck->agc_rpt >> 5) & 0x3; - rssi = (cck->agc_rpt & 0x1f) << 1; - } else { - rpt = (cck->agc_rpt >> 6) & 0x3; - rssi = cck->agc_rpt & 0x3e; - } - rssi = cckoff[rpt] - rssi; - } else { /* OFDM/HT. */ - phy = (struct r92c_rx_phystat *)physt; - rssi = ((le32toh(phy->phydw1) >> 1) & 0x7f) - 110; - } - return (rssi); -} - -static void -rtwn_rx_frame(struct rtwn_softc *sc, struct r92c_rx_desc *rx_desc, - struct rtwn_rx_data *rx_data, int desc_idx) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211_frame_min *wh; - struct ieee80211_node *ni; - struct r92c_rx_phystat *phy = NULL; - uint32_t rxdw0, rxdw3; - struct mbuf *m, *m1; - bus_dma_segment_t segs[1]; - bus_addr_t physaddr; - uint8_t rate; - int8_t rssi = 0, nf; - int infosz, nsegs, pktlen, shift, error; - - rxdw0 = le32toh(rx_desc->rxdw0); - rxdw3 = le32toh(rx_desc->rxdw3); - - if (__predict_false(rxdw0 & (R92C_RXDW0_CRCERR | R92C_RXDW0_ICVERR))) { + /* Setup power management. */ /* - * This should not happen since we setup our Rx filter - * to not receive these frames. + * NB: it will be enabled immediately - delay it, + * so 4-Way handshake will not be interrupted. */ - counter_u64_add(ic->ic_ierrors, 1); - return; + callout_reset(&sc->sc_pwrmode_init, 5*hz, + rtwn_pwrmode_init, sc); } +#endif - pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN); - if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) || - pktlen > MCLBYTES)) { - counter_u64_add(ic->ic_ierrors, 1); - return; - } + /* Enable TSF synchronization. */ + rtwn_tsf_sync_enable(sc, vap); - rate = MS(rxdw3, R92C_RXDW3_RATE); - infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8; - if (infosz > sizeof(struct r92c_rx_phystat)) - infosz = sizeof(struct r92c_rx_phystat); - shift = MS(rxdw0, R92C_RXDW0_SHIFT); - - /* Get RSSI from PHY status descriptor if present. */ - if (infosz != 0 && (rxdw0 & R92C_RXDW0_PHYST)) { - phy = mtod(rx_data->m, struct r92c_rx_phystat *); - rssi = rtwn_get_rssi(sc, rate, phy); - /* Update our average RSSI. */ - rtwn_update_avgrssi(sc, rate, rssi); - } - - DPRINTFN(5, ("Rx frame len=%d rate=%d infosz=%d shift=%d rssi=%d\n", - pktlen, rate, infosz, shift, rssi)); - - m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR); - if (m1 == NULL) { - counter_u64_add(ic->ic_ierrors, 1); - return; - } - bus_dmamap_unload(sc->rx_ring.data_dmat, rx_data->map); - - error = bus_dmamap_load(sc->rx_ring.data_dmat, rx_data->map, - mtod(m1, void *), MCLBYTES, rtwn_dma_map_addr, - &physaddr, 0); - if (error != 0) { - m_freem(m1); - - if (bus_dmamap_load_mbuf_sg(sc->rx_ring.data_dmat, - rx_data->map, rx_data->m, segs, &nsegs, 0)) - panic("%s: could not load old RX mbuf", - device_get_name(sc->sc_dev)); - - /* Physical address may have changed. */ - rtwn_setup_rx_desc(sc, rx_desc, physaddr, MCLBYTES, desc_idx); - counter_u64_add(ic->ic_ierrors, 1); - return; - } - - /* Finalize mbuf. */ - m = rx_data->m; - rx_data->m = m1; - m->m_pkthdr.len = m->m_len = pktlen + infosz + shift; - - /* Update RX descriptor. */ - rtwn_setup_rx_desc(sc, rx_desc, physaddr, MCLBYTES, desc_idx); - - /* Get ieee80211 frame header. */ - if (rxdw0 & R92C_RXDW0_PHYST) - m_adj(m, infosz + shift); - else - m_adj(m, shift); - - nf = -95; - if (ieee80211_radiotap_active(ic)) { - struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap; - - tap->wr_flags = 0; - if (!(rxdw3 & R92C_RXDW3_HT)) { - tap->wr_rate = ridx2rate[rate]; - } else if (rate >= 12) { /* MCS0~15. */ - /* Bit 7 set means HT MCS instead of rate. */ - tap->wr_rate = 0x80 | (rate - 12); - } - tap->wr_dbm_antsignal = rssi; - tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); - } - - RTWN_UNLOCK(sc); - wh = mtod(m, struct ieee80211_frame_min *); - if (m->m_len >= sizeof(*wh)) - ni = ieee80211_find_rxnode(ic, wh); - else - ni = NULL; - - /* Send the frame to the 802.11 layer. */ - if (ni != NULL) { - (void)ieee80211_input(ni, m, rssi - nf, nf); - /* Node is no longer needed. */ - ieee80211_free_node(ni); - } else - (void)ieee80211_input_all(ic, m, rssi - nf, nf); - - RTWN_LOCK(sc); -} - -static int -rtwn_tx(struct rtwn_softc *sc, struct mbuf *m, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211vap *vap = ni->ni_vap; - struct ieee80211_frame *wh; - struct ieee80211_key *k = NULL; - struct rtwn_tx_ring *tx_ring; - struct rtwn_tx_data *data; - struct r92c_tx_desc *txd; - bus_dma_segment_t segs[1]; - uint16_t qos; - uint8_t raid, type, tid, qid; - int nsegs, error; - - wh = mtod(m, struct ieee80211_frame *); - type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - - /* Encrypt the frame if need be. */ - if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { - k = ieee80211_crypto_encap(ni, m); - if (k == NULL) { - m_freem(m); - return (ENOBUFS); - } - /* 802.11 header may have moved. */ - wh = mtod(m, struct ieee80211_frame *); - } - - if (IEEE80211_QOS_HAS_SEQ(wh)) { - qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; - tid = qos & IEEE80211_QOS_TID; - } else { - qos = 0; - tid = 0; - } - - switch (type) { - case IEEE80211_FC0_TYPE_CTL: - case IEEE80211_FC0_TYPE_MGT: - qid = RTWN_VO_QUEUE; - break; - default: - qid = M_WME_GETAC(m); - break; - } - - /* Grab a Tx buffer from the ring. */ - tx_ring = &sc->tx_ring[qid]; - data = &tx_ring->tx_data[tx_ring->cur]; - if (data->m != NULL) { - m_freem(m); - return (ENOBUFS); - } - - /* Fill Tx descriptor. */ - txd = &tx_ring->desc[tx_ring->cur]; - if (htole32(txd->txdw0) & R92C_RXDW0_OWN) { - m_freem(m); - return (ENOBUFS); - } - txd->txdw0 = htole32( - SM(R92C_TXDW0_PKTLEN, m->m_pkthdr.len) | - SM(R92C_TXDW0_OFFSET, sizeof(*txd)) | - R92C_TXDW0_FSG | R92C_TXDW0_LSG); - if (IEEE80211_IS_MULTICAST(wh->i_addr1)) - txd->txdw0 |= htole32(R92C_TXDW0_BMCAST); - - txd->txdw1 = 0; - txd->txdw4 = 0; - txd->txdw5 = 0; - - /* XXX TODO: rate control; implement low-rate for EAPOL */ - if (!IEEE80211_IS_MULTICAST(wh->i_addr1) && - type == IEEE80211_FC0_TYPE_DATA) { - if (ic->ic_curmode == IEEE80211_MODE_11B) - raid = R92C_RAID_11B; - else - raid = R92C_RAID_11BG; - txd->txdw1 |= htole32( - SM(R92C_TXDW1_MACID, RTWN_MACID_BSS) | - SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BE) | - SM(R92C_TXDW1_RAID, raid) | - R92C_TXDW1_AGGBK); - - if (ic->ic_flags & IEEE80211_F_USEPROT) { - if (ic->ic_protmode == IEEE80211_PROT_CTSONLY) { - txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF | - R92C_TXDW4_HWRTSEN); - } else if (ic->ic_protmode == IEEE80211_PROT_RTSCTS) { - txd->txdw4 |= htole32(R92C_TXDW4_RTSEN | - R92C_TXDW4_HWRTSEN); - } - } - - /* XXX TODO: implement rate control */ - - /* Send RTS at OFDM24. */ - txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, - RTWN_RIDX_OFDM24)); - txd->txdw5 |= htole32(SM(R92C_TXDW5_RTSRATE_FBLIMIT, 0xf)); - /* Send data at OFDM54. */ - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, - RTWN_RIDX_OFDM54)); - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FBLIMIT, 0x1f)); - - } else { - txd->txdw1 |= htole32( - SM(R92C_TXDW1_MACID, 0) | - SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT) | - SM(R92C_TXDW1_RAID, R92C_RAID_11B)); - - /* Force CCK1. */ - txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); - txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_CCK1)); - } - /* Set sequence number (already little endian). */ - txd->txdseq = htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE); - - if (!qos) { - /* Use HW sequence numbering for non-QoS frames. */ - txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ); - txd->txdseq |= htole16(0x8000); - } else - txd->txdw4 |= htole32(R92C_TXDW4_QOS); - - error = bus_dmamap_load_mbuf_sg(tx_ring->data_dmat, data->map, m, segs, - &nsegs, BUS_DMA_NOWAIT); - if (error != 0 && error != EFBIG) { - device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", error); - m_freem(m); - return (error); - } - if (error != 0) { - struct mbuf *mnew; - - mnew = m_defrag(m, M_NOWAIT); - if (mnew == NULL) { - device_printf(sc->sc_dev, - "can't defragment mbuf\n"); - m_freem(m); - return (ENOBUFS); - } - m = mnew; - - error = bus_dmamap_load_mbuf_sg(tx_ring->data_dmat, data->map, - m, segs, &nsegs, BUS_DMA_NOWAIT); + if (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_IBSS) { + error = rtwn_setup_beacon(sc, ni); if (error != 0) { device_printf(sc->sc_dev, - "can't map mbuf (error %d)\n", error); - m_freem(m); - return (error); + "unable to push beacon into the chip, " + "error %d\n", error); + goto fail; } } - txd->txbufaddr = htole32(segs[0].ds_addr); - txd->txbufsize = htole16(m->m_pkthdr.len); - bus_space_barrier(sc->sc_st, sc->sc_sh, 0, sc->sc_mapsize, - BUS_SPACE_BARRIER_WRITE); - txd->txdw0 |= htole32(R92C_TXDW0_OWN); + /* Set ACK preamble type. */ + rtwn_set_ack_preamble(sc); - bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_sync(tx_ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); + /* Set basic rates mask. */ + rtwn_calc_basicrates(sc); - data->m = m; - data->ni = ni; +#ifdef RTWN_TODO + rtwn_write_1(sc, R92C_SIFS_CCK + 1, 10); + rtwn_write_1(sc, R92C_SIFS_OFDM + 1, 10); + rtwn_write_1(sc, R92C_SPEC_SIFS + 1, 10); + rtwn_write_1(sc, R92C_MAC_SPEC_SIFS + 1, 10); + rtwn_write_1(sc, R92C_R2T_SIFS + 1, 10); + rtwn_write_1(sc, R92C_T2T_SIFS + 1, 10); +#endif - if (ieee80211_radiotap_active_vap(vap)) { - struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; + if (sc->vaps_running == sc->monvaps_running) { + /* Reset temperature calibration state machine. */ + sc->sc_flags &= ~RTWN_TEMP_MEASURED; + sc->thcal_temp = sc->thermal_meter; - tap->wt_flags = 0; - tap->wt_chan_freq = htole16(ic->ic_curchan->ic_freq); - tap->wt_chan_flags = htole16(ic->ic_curchan->ic_flags); + /* Start periodic calibration. */ + callout_reset(&sc->sc_calib_to, 2*hz, rtwn_calib_to, + sc); - ieee80211_radiotap_tx(vap, m); - } - - tx_ring->cur = (tx_ring->cur + 1) % RTWN_TX_LIST_COUNT; - tx_ring->queued++; - - if (tx_ring->queued >= (RTWN_TX_LIST_COUNT - 1)) - sc->qfullmsk |= (1 << qid); - - /* Kick TX. */ - rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid)); - return (0); -} - -static void -rtwn_tx_done(struct rtwn_softc *sc, int qid) -{ - struct rtwn_tx_ring *tx_ring = &sc->tx_ring[qid]; - struct rtwn_tx_data *tx_data; - struct r92c_tx_desc *tx_desc; - int i; - - bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, - BUS_DMASYNC_POSTREAD); - - for (i = 0; i < RTWN_TX_LIST_COUNT; i++) { - tx_data = &tx_ring->tx_data[i]; - if (tx_data->m == NULL) - continue; - - tx_desc = &tx_ring->desc[i]; - if (le32toh(tx_desc->txdw0) & R92C_TXDW0_OWN) - continue; - - /* Unmap and free mbuf. */ - bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); - - /* - * XXX TODO: figure out whether the transmit succeeded or not. - * .. and then notify rate control. - */ - ieee80211_tx_complete(tx_data->ni, tx_data->m, 0); - tx_data->ni = NULL; - tx_data->m = NULL; - - if (--tx_ring->queued) - sc->sc_tx_timer = 5; - else - sc->sc_tx_timer = 0; - } - - if (tx_ring->queued < (RTWN_TX_LIST_COUNT - 1)) - sc->qfullmsk &= ~(1 << qid); - rtwn_start(sc); -} - -static int -rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, - const struct ieee80211_bpf_params *params) -{ - struct ieee80211com *ic = ni->ni_ic; - struct rtwn_softc *sc = ic->ic_softc; - - RTWN_LOCK(sc); - - /* Prevent management frames from being sent if we're not ready. */ - if (!(sc->sc_flags & RTWN_RUNNING)) { - RTWN_UNLOCK(sc); - m_freem(m); - return (ENETDOWN); - } - - if (rtwn_tx(sc, m, ni) != 0) { - RTWN_UNLOCK(sc); - return (EIO); - } - sc->sc_tx_timer = 5; - RTWN_UNLOCK(sc); - return (0); -} - -static int -rtwn_transmit(struct ieee80211com *ic, struct mbuf *m) -{ - struct rtwn_softc *sc = ic->ic_softc; - int error; - - RTWN_LOCK(sc); - if ((sc->sc_flags & RTWN_RUNNING) == 0) { - RTWN_UNLOCK(sc); - return (ENXIO); - } - error = mbufq_enqueue(&sc->sc_snd, m); - if (error) { - RTWN_UNLOCK(sc); - return (error); - } - rtwn_start(sc); - RTWN_UNLOCK(sc); - return (0); -} - -static void -rtwn_parent(struct ieee80211com *ic) -{ - struct rtwn_softc *sc = ic->ic_softc; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - - if (ic->ic_nrunning > 0) { - if (rtwn_init(sc) == 0) - ieee80211_start_all(ic); - else - ieee80211_stop(vap); - } else - rtwn_stop(sc); -} - -static void -rtwn_start(struct rtwn_softc *sc) -{ - struct ieee80211_node *ni; - struct mbuf *m; - - RTWN_LOCK_ASSERT(sc); - - if ((sc->sc_flags & RTWN_RUNNING) == 0) - return; - - while (sc->qfullmsk == 0 && (m = mbufq_dequeue(&sc->sc_snd)) != NULL) { - ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; - if (rtwn_tx(sc, m, ni) != 0) { - if_inc_counter(ni->ni_vap->iv_ifp, - IFCOUNTER_OERRORS, 1); - ieee80211_free_node(ni); - continue; + if (sc->vaps_running == 0) { + /* Turn link LED on. */ + rtwn_set_led(sc, RTWN_LED_LINK, 1); } - sc->sc_tx_timer = 5; } + +fail: + ieee80211_free_node(ni); + + return (error); } +#ifndef D4054 static void rtwn_watchdog(void *arg) { struct rtwn_softc *sc = arg; struct ieee80211com *ic = &sc->sc_ic; - RTWN_LOCK_ASSERT(sc); + RTWN_ASSERT_LOCKED(sc); KASSERT(sc->sc_flags & RTWN_RUNNING, ("not running")); @@ -1897,820 +1357,120 @@ rtwn_watchdog(void *arg) ieee80211_restart_all(ic); return; } - callout_reset(&sc->watchdog_to, hz, rtwn_watchdog, sc); -} - -static int -rtwn_power_on(struct rtwn_softc *sc) -{ - uint32_t reg; - int ntries; - - /* Wait for autoload done bit. */ - for (ntries = 0; ntries < 1000; ntries++) { - if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN) - break; - DELAY(5); - } - if (ntries == 1000) { - device_printf(sc->sc_dev, - "timeout waiting for chip autoload\n"); - return (ETIMEDOUT); - } - - /* Unlock ISO/CLK/Power control register. */ - rtwn_write_1(sc, R92C_RSV_CTRL, 0); - - /* TODO: check if we need this for 8188CE */ - if (sc->board_type != R92C_BOARD_TYPE_DONGLE) { - /* bt coex */ - reg = rtwn_read_4(sc, R92C_APS_FSMCO); - reg |= (R92C_APS_FSMCO_SOP_ABG | - R92C_APS_FSMCO_SOP_AMB | - R92C_APS_FSMCO_XOP_BTCK); - rtwn_write_4(sc, R92C_APS_FSMCO, reg); - } - - /* Move SPS into PWM mode. */ - rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); - - /* Set low byte to 0x0f, leave others unchanged. */ - rtwn_write_4(sc, R92C_AFE_XTAL_CTRL, - (rtwn_read_4(sc, R92C_AFE_XTAL_CTRL) & 0xffffff00) | 0x0f); - - /* TODO: check if we need this for 8188CE */ - if (sc->board_type != R92C_BOARD_TYPE_DONGLE) { - /* bt coex */ - reg = rtwn_read_4(sc, R92C_AFE_XTAL_CTRL); - reg &= (~0x00024800); /* XXX magic from linux */ - rtwn_write_4(sc, R92C_AFE_XTAL_CTRL, reg); - } - - rtwn_write_2(sc, R92C_SYS_ISO_CTRL, - (rtwn_read_2(sc, R92C_SYS_ISO_CTRL) & 0xff) | - R92C_SYS_ISO_CTRL_PWC_EV12V | R92C_SYS_ISO_CTRL_DIOR); - DELAY(200); - - /* TODO: linux does additional btcoex stuff here */ - - /* Auto enable WLAN. */ - rtwn_write_2(sc, R92C_APS_FSMCO, - rtwn_read_2(sc, R92C_APS_FSMCO) | R92C_APS_FSMCO_APFM_ONMAC); - for (ntries = 0; ntries < 1000; ntries++) { - if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & - R92C_APS_FSMCO_APFM_ONMAC)) - break; - DELAY(5); - } - if (ntries == 1000) { - device_printf(sc->sc_dev, "timeout waiting for MAC auto ON\n"); - return (ETIMEDOUT); - } - - /* Enable radio, GPIO and LED functions. */ - rtwn_write_2(sc, R92C_APS_FSMCO, - R92C_APS_FSMCO_AFSM_PCIE | - R92C_APS_FSMCO_PDN_EN | - R92C_APS_FSMCO_PFM_ALDN); - /* Release RF digital isolation. */ - rtwn_write_2(sc, R92C_SYS_ISO_CTRL, - rtwn_read_2(sc, R92C_SYS_ISO_CTRL) & ~R92C_SYS_ISO_CTRL_DIOR); - - if (sc->chip & RTWN_CHIP_92C) - rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x77); - else - rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x22); - - rtwn_write_4(sc, R92C_INT_MIG, 0); - - if (sc->board_type != R92C_BOARD_TYPE_DONGLE) { - /* bt coex */ - reg = rtwn_read_4(sc, R92C_AFE_XTAL_CTRL + 2); - reg &= 0xfd; /* XXX magic from linux */ - rtwn_write_4(sc, R92C_AFE_XTAL_CTRL + 2, reg); - } - - rtwn_write_1(sc, R92C_GPIO_MUXCFG, - rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_RFKILL); - - reg = rtwn_read_1(sc, R92C_GPIO_IO_SEL); - if (!(reg & R92C_GPIO_IO_SEL_RFKILL)) { - device_printf(sc->sc_dev, - "radio is disabled by hardware switch\n"); - return (EPERM); - } - - /* Initialize MAC. */ - reg = rtwn_read_1(sc, R92C_APSD_CTRL); - rtwn_write_1(sc, R92C_APSD_CTRL, - rtwn_read_1(sc, R92C_APSD_CTRL) & ~R92C_APSD_CTRL_OFF); - for (ntries = 0; ntries < 200; ntries++) { - if (!(rtwn_read_1(sc, R92C_APSD_CTRL) & - R92C_APSD_CTRL_OFF_STATUS)) - break; - DELAY(500); - } - if (ntries == 200) { - device_printf(sc->sc_dev, - "timeout waiting for MAC initialization\n"); - return (ETIMEDOUT); - } - - /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ - reg = rtwn_read_2(sc, R92C_CR); - reg |= R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | - R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | - R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | - R92C_CR_ENSEC; - rtwn_write_2(sc, R92C_CR, reg); - - rtwn_write_1(sc, 0xfe10, 0x19); - - return (0); -} - -static int -rtwn_llt_init(struct rtwn_softc *sc) -{ - int i, error; - - /* Reserve pages [0; R92C_TX_PAGE_COUNT]. */ - for (i = 0; i < R92C_TX_PAGE_COUNT; i++) { - if ((error = rtwn_llt_write(sc, i, i + 1)) != 0) - return (error); - } - /* NB: 0xff indicates end-of-list. */ - if ((error = rtwn_llt_write(sc, i, 0xff)) != 0) - return (error); - /* - * Use pages [R92C_TX_PAGE_COUNT + 1; R92C_TXPKTBUF_COUNT - 1] - * as ring buffer. - */ - for (++i; i < R92C_TXPKTBUF_COUNT - 1; i++) { - if ((error = rtwn_llt_write(sc, i, i + 1)) != 0) - return (error); - } - /* Make the last page point to the beginning of the ring buffer. */ - error = rtwn_llt_write(sc, i, R92C_TX_PAGE_COUNT + 1); - return (error); + callout_reset(&sc->sc_watchdog_to, hz, rtwn_watchdog, sc); } +#endif static void -rtwn_fw_reset(struct rtwn_softc *sc) +rtwn_parent(struct ieee80211com *ic) { - uint16_t reg; - int ntries; + struct rtwn_softc *sc = ic->ic_softc; + struct ieee80211vap *vap; - /* Tell 8051 to reset itself. */ - rtwn_write_1(sc, R92C_HMETFR + 3, 0x20); - - /* Wait until 8051 resets by itself. */ - for (ntries = 0; ntries < 100; ntries++) { - reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); - if (!(reg & R92C_SYS_FUNC_EN_CPUEN)) - goto sleep; - DELAY(50); - } - /* Force 8051 reset. */ - rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); -sleep: - /* - * We must sleep for one second to let the firmware settle. - * Accessing registers too early will hang the whole system. - */ - if (msleep(®, &sc->sc_mtx, 0, "rtwnrst", hz)) { - device_printf(sc->sc_dev, "timeout waiting for firmware " - "initialization to complete\n"); - } -} - -static void -rtwn_fw_loadpage(struct rtwn_softc *sc, int page, const uint8_t *buf, int len) -{ - uint32_t reg; - int off, mlen, i; - - reg = rtwn_read_4(sc, R92C_MCUFWDL); - reg = RW(reg, R92C_MCUFWDL_PAGE, page); - rtwn_write_4(sc, R92C_MCUFWDL, reg); - - DELAY(5); - - off = R92C_FW_START_ADDR; - while (len > 0) { - if (len > 196) - mlen = 196; - else if (len > 4) - mlen = 4; - else - mlen = 1; - for (i = 0; i < mlen; i++) - rtwn_write_1(sc, off++, buf[i]); - buf += mlen; - len -= mlen; - } -} - -static int -rtwn_load_firmware(struct rtwn_softc *sc) -{ - const struct firmware *fw; - const struct r92c_fw_hdr *hdr; - const char *name; - const u_char *ptr; - size_t len; - uint32_t reg; - int mlen, ntries, page, error = 0; - - /* Read firmware image from the filesystem. */ - if ((sc->chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) == - RTWN_CHIP_UMC_A_CUT) - name = "rtwn-rtl8192cfwU"; - else - name = "rtwn-rtl8192cfwU_B"; - RTWN_UNLOCK(sc); - fw = firmware_get(name); - RTWN_LOCK(sc); - if (fw == NULL) { - device_printf(sc->sc_dev, - "could not read firmware %s\n", name); - return (ENOENT); - } - len = fw->datasize; - if (len < sizeof(*hdr)) { - device_printf(sc->sc_dev, "firmware too short\n"); - error = EINVAL; - goto fail; - } - ptr = fw->data; - hdr = (const struct r92c_fw_hdr *)ptr; - /* Check if there is a valid FW header and skip it. */ - if ((le16toh(hdr->signature) >> 4) == 0x88c || - (le16toh(hdr->signature) >> 4) == 0x92c) { - DPRINTF(("FW V%d.%d %02d-%02d %02d:%02d\n", - le16toh(hdr->version), le16toh(hdr->subversion), - hdr->month, hdr->date, hdr->hour, hdr->minute)); - ptr += sizeof(*hdr); - len -= sizeof(*hdr); - } - - if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) - rtwn_fw_reset(sc); - - /* Enable FW download. */ - rtwn_write_2(sc, R92C_SYS_FUNC_EN, - rtwn_read_2(sc, R92C_SYS_FUNC_EN) | - R92C_SYS_FUNC_EN_CPUEN); - rtwn_write_1(sc, R92C_MCUFWDL, - rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_EN); - rtwn_write_1(sc, R92C_MCUFWDL + 2, - rtwn_read_1(sc, R92C_MCUFWDL + 2) & ~0x08); - - /* Reset the FWDL checksum. */ - rtwn_write_1(sc, R92C_MCUFWDL, - rtwn_read_1(sc, R92C_MCUFWDL) | R92C_MCUFWDL_CHKSUM_RPT); - - for (page = 0; len > 0; page++) { - mlen = MIN(len, R92C_FW_PAGE_SIZE); - rtwn_fw_loadpage(sc, page, ptr, mlen); - ptr += mlen; - len -= mlen; - } - - /* Disable FW download. */ - rtwn_write_1(sc, R92C_MCUFWDL, - rtwn_read_1(sc, R92C_MCUFWDL) & ~R92C_MCUFWDL_EN); - rtwn_write_1(sc, R92C_MCUFWDL + 1, 0); - - /* Wait for checksum report. */ - for (ntries = 0; ntries < 1000; ntries++) { - if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT) - break; - DELAY(5); - } - if (ntries == 1000) { - device_printf(sc->sc_dev, - "timeout waiting for checksum report\n"); - error = ETIMEDOUT; - goto fail; - } - - reg = rtwn_read_4(sc, R92C_MCUFWDL); - reg = (reg & ~R92C_MCUFWDL_WINTINI_RDY) | R92C_MCUFWDL_RDY; - rtwn_write_4(sc, R92C_MCUFWDL, reg); - /* Wait for firmware readiness. */ - for (ntries = 0; ntries < 2000; ntries++) { - if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY) - break; - DELAY(50); - } - if (ntries == 1000) { - device_printf(sc->sc_dev, - "timeout waiting for firmware readiness\n"); - error = ETIMEDOUT; - goto fail; - } -fail: - firmware_put(fw, FIRMWARE_UNLOAD); - return (error); + if (ic->ic_nrunning > 0) { + if (rtwn_init(sc) != 0) { + IEEE80211_LOCK(ic); + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) + ieee80211_stop_locked(vap); + IEEE80211_UNLOCK(ic); + } else + ieee80211_start_all(ic); + } else + rtwn_stop(sc); } static int rtwn_dma_init(struct rtwn_softc *sc) { - uint32_t reg; +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + uint16_t reg; + uint8_t tx_boundary; int error; /* Initialize LLT table. */ error = rtwn_llt_init(sc); if (error != 0) - return error; + return (error); - /* Set number of pages for normal priority queue. */ - rtwn_write_2(sc, R92C_RQPN_NPQ, 0); - rtwn_write_4(sc, R92C_RQPN, + /* Set the number of pages for each queue. */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "%s: pages per queue: high %d, normal %d, low %d, public %d\n", + __func__, sc->nhqpages, sc->nnqpages, sc->nlqpages, + sc->npubqpages); + + RTWN_CHK(rtwn_write_1(sc, R92C_RQPN_NPQ, sc->nnqpages)); + RTWN_CHK(rtwn_write_4(sc, R92C_RQPN, /* Set number of pages for public queue. */ - SM(R92C_RQPN_PUBQ, R92C_PUBQ_NPAGES) | + SM(R92C_RQPN_PUBQ, sc->npubqpages) | /* Set number of pages for high priority queue. */ - SM(R92C_RQPN_HPQ, R92C_HPQ_NPAGES) | + SM(R92C_RQPN_HPQ, sc->nhqpages) | /* Set number of pages for low priority queue. */ - SM(R92C_RQPN_LPQ, R92C_LPQ_NPAGES) | + SM(R92C_RQPN_LPQ, sc->nlqpages) | /* Load values. */ - R92C_RQPN_LD); + R92C_RQPN_LD)); - rtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TRXFF_BNDY, R92C_TX_PAGE_BOUNDARY); - rtwn_write_1(sc, R92C_TDECTRL + 1, R92C_TX_PAGE_BOUNDARY); + /* Initialize TX buffer boundary. */ + KASSERT(sc->page_count < 255 && sc->page_count > 0, + ("page_count is %d\n", sc->page_count)); + tx_boundary = sc->page_count + 1; + RTWN_CHK(rtwn_write_1(sc, R92C_TXPKTBUF_BCNQ_BDNY, tx_boundary)); + RTWN_CHK(rtwn_write_1(sc, R92C_TXPKTBUF_MGQ_BDNY, tx_boundary)); + RTWN_CHK(rtwn_write_1(sc, R92C_TXPKTBUF_WMAC_LBK_BF_HD, tx_boundary)); + RTWN_CHK(rtwn_write_1(sc, R92C_TRXFF_BNDY, tx_boundary)); + RTWN_CHK(rtwn_write_1(sc, R92C_TDECTRL + 1, tx_boundary)); - reg = rtwn_read_2(sc, R92C_TRXDMA_CTRL); - reg &= ~R92C_TRXDMA_CTRL_QMAP_M; - reg |= 0xF771; - rtwn_write_2(sc, R92C_TRXDMA_CTRL, reg); + error = rtwn_init_bcnq1_boundary(sc); + if (error != 0) + return (error); - rtwn_write_4(sc, R92C_TCR, R92C_TCR_CFENDFORM | (1 << 12) | (1 << 13)); + /* Set queue to USB pipe mapping. */ + /* Note: PCIe devices are using some magic number here. */ + reg = rtwn_get_qmap(sc); + RTWN_CHK(rtwn_setbits_2(sc, R92C_TRXDMA_CTRL, + R92C_TRXDMA_CTRL_QMAP_M, reg)); - /* Configure Tx DMA. */ - rtwn_write_4(sc, R92C_BKQ_DESA, sc->tx_ring[RTWN_BK_QUEUE].paddr); - rtwn_write_4(sc, R92C_BEQ_DESA, sc->tx_ring[RTWN_BE_QUEUE].paddr); - rtwn_write_4(sc, R92C_VIQ_DESA, sc->tx_ring[RTWN_VI_QUEUE].paddr); - rtwn_write_4(sc, R92C_VOQ_DESA, sc->tx_ring[RTWN_VO_QUEUE].paddr); - rtwn_write_4(sc, R92C_BCNQ_DESA, sc->tx_ring[RTWN_BEACON_QUEUE].paddr); - rtwn_write_4(sc, R92C_MGQ_DESA, sc->tx_ring[RTWN_MGNT_QUEUE].paddr); - rtwn_write_4(sc, R92C_HQ_DESA, sc->tx_ring[RTWN_HIGH_QUEUE].paddr); - - /* Configure Rx DMA. */ - rtwn_write_4(sc, R92C_RX_DESA, sc->rx_ring.paddr); + /* Configure Tx/Rx DMA (PCIe). */ + rtwn_set_desc_addr(sc); /* Set Tx/Rx transfer page boundary. */ - rtwn_write_2(sc, R92C_TRXFF_BNDY + 2, 0x27ff); + RTWN_CHK(rtwn_write_2(sc, R92C_TRXFF_BNDY + 2, + sc->rx_dma_size - 1)); /* Set Tx/Rx transfer page size. */ - rtwn_write_1(sc, R92C_PBP, - SM(R92C_PBP_PSRX, R92C_PBP_128) | - SM(R92C_PBP_PSTX, R92C_PBP_128)); + rtwn_set_page_size(sc); + + return (0); +} + +static int +rtwn_mac_init(struct rtwn_softc *sc) +{ + int i, error; + + /* Write MAC initialization values. */ + for (i = 0; i < sc->mac_size; i++) { + error = rtwn_write_1(sc, sc->mac_prog[i].reg, + sc->mac_prog[i].val); + if (error != 0) + return (error); + } + return (0); } static void -rtwn_mac_init(struct rtwn_softc *sc) +rtwn_mrr_init(struct rtwn_softc *sc) { int i; - /* Write MAC initialization values. */ - for (i = 0; i < nitems(rtl8192ce_mac); i++) - rtwn_write_1(sc, rtl8192ce_mac[i].reg, rtl8192ce_mac[i].val); -} - -static void -rtwn_bb_init(struct rtwn_softc *sc) -{ - const struct rtwn_bb_prog *prog; - uint32_t reg; - int i; - - /* Enable BB and RF. */ - rtwn_write_2(sc, R92C_SYS_FUNC_EN, - rtwn_read_2(sc, R92C_SYS_FUNC_EN) | - R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | - R92C_SYS_FUNC_EN_DIO_RF); - - rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); - - rtwn_write_1(sc, R92C_RF_CTRL, - R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); - - rtwn_write_1(sc, R92C_SYS_FUNC_EN, - R92C_SYS_FUNC_EN_DIO_PCIE | R92C_SYS_FUNC_EN_PCIEA | - R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_BB_GLB_RST | - R92C_SYS_FUNC_EN_BBRSTB); - - rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); - - rtwn_write_4(sc, R92C_LEDCFG0, - rtwn_read_4(sc, R92C_LEDCFG0) | 0x00800000); - - /* Select BB programming. */ - prog = (sc->chip & RTWN_CHIP_92C) ? - &rtl8192ce_bb_prog_2t : &rtl8192ce_bb_prog_1t; - - /* Write BB initialization values. */ - for (i = 0; i < prog->count; i++) { - rtwn_bb_write(sc, prog->regs[i], prog->vals[i]); - DELAY(1); + /* Drop rate index by 1 per retry. */ + for (i = 0; i < R92C_DARFRC_SIZE; i++) { + rtwn_write_1(sc, R92C_DARFRC + i, i + 1); + rtwn_write_1(sc, R92C_RARFRC + i, i + 1); } - - if (sc->chip & RTWN_CHIP_92C_1T2R) { - /* 8192C 1T only configuration. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_TXINFO); - reg = (reg & ~0x00000003) | 0x2; - rtwn_bb_write(sc, R92C_FPGA0_TXINFO, reg); - - reg = rtwn_bb_read(sc, R92C_FPGA1_TXINFO); - reg = (reg & ~0x00300033) | 0x00200022; - rtwn_bb_write(sc, R92C_FPGA1_TXINFO, reg); - - reg = rtwn_bb_read(sc, R92C_CCK0_AFESETTING); - reg = (reg & ~0xff000000) | 0x45 << 24; - rtwn_bb_write(sc, R92C_CCK0_AFESETTING, reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); - reg = (reg & ~0x000000ff) | 0x23; - rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCPARAM1); - reg = (reg & ~0x00000030) | 1 << 4; - rtwn_bb_write(sc, R92C_OFDM0_AGCPARAM1, reg); - - reg = rtwn_bb_read(sc, 0xe74); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe74, reg); - reg = rtwn_bb_read(sc, 0xe78); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe78, reg); - reg = rtwn_bb_read(sc, 0xe7c); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe7c, reg); - reg = rtwn_bb_read(sc, 0xe80); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe80, reg); - reg = rtwn_bb_read(sc, 0xe88); - reg = (reg & ~0x0c000000) | 2 << 26; - rtwn_bb_write(sc, 0xe88, reg); - } - - /* Write AGC values. */ - for (i = 0; i < prog->agccount; i++) { - rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, - prog->agcvals[i]); - DELAY(1); - } - - if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & - R92C_HSSI_PARAM2_CCK_HIPWR) - sc->sc_flags |= RTWN_FLAG_CCK_HIPWR; -} - -static void -rtwn_rf_init(struct rtwn_softc *sc) -{ - const struct rtwn_rf_prog *prog; - uint32_t reg, type; - int i, j, idx, off; - - /* Select RF programming based on board type. */ - if (!(sc->chip & RTWN_CHIP_92C)) { - if (sc->board_type == R92C_BOARD_TYPE_MINICARD) - prog = rtl8188ce_rf_prog; - else if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) - prog = rtl8188ru_rf_prog; - else - prog = rtl8188cu_rf_prog; - } else - prog = rtl8192ce_rf_prog; - - for (i = 0; i < sc->nrxchains; i++) { - /* Save RF_ENV control type. */ - idx = i / 2; - off = (i % 2) * 16; - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)); - type = (reg >> off) & 0x10; - - /* Set RF_ENV enable. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); - reg |= 0x100000; - rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); - DELAY(1); - /* Set RF_ENV output high. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(i)); - reg |= 0x10; - rtwn_bb_write(sc, R92C_FPGA0_RFIFACEOE(i), reg); - DELAY(1); - /* Set address and data lengths of RF registers. */ - reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); - reg &= ~R92C_HSSI_PARAM2_ADDR_LENGTH; - rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); - DELAY(1); - reg = rtwn_bb_read(sc, R92C_HSSI_PARAM2(i)); - reg &= ~R92C_HSSI_PARAM2_DATA_LENGTH; - rtwn_bb_write(sc, R92C_HSSI_PARAM2(i), reg); - DELAY(1); - - /* Write RF initialization values for this chain. */ - for (j = 0; j < prog[i].count; j++) { - if (prog[i].regs[j] >= 0xf9 && - prog[i].regs[j] <= 0xfe) { - /* - * These are fake RF registers offsets that - * indicate a delay is required. - */ - DELAY(50); - continue; - } - rtwn_rf_write(sc, i, prog[i].regs[j], - prog[i].vals[j]); - DELAY(1); - } - - /* Restore RF_ENV control type. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)); - reg &= ~(0x10 << off) | (type << off); - rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(idx), reg); - - /* Cache RF register CHNLBW. */ - sc->rf_chnlbw[i] = rtwn_rf_read(sc, i, R92C_RF_CHNLBW); - } - - if ((sc->chip & (RTWN_CHIP_UMC_A_CUT | RTWN_CHIP_92C)) == - RTWN_CHIP_UMC_A_CUT) { - rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255); - rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00); - } -} - -static void -rtwn_cam_init(struct rtwn_softc *sc) -{ - /* Invalidate all CAM entries. */ - rtwn_write_4(sc, R92C_CAMCMD, - R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); -} - -static void -rtwn_pa_bias_init(struct rtwn_softc *sc) -{ - uint8_t reg; - int i; - - for (i = 0; i < sc->nrxchains; i++) { - if (sc->pa_setting & (1 << i)) - continue; - rtwn_rf_write(sc, i, R92C_RF_IPA, 0x0f406); - rtwn_rf_write(sc, i, R92C_RF_IPA, 0x4f406); - rtwn_rf_write(sc, i, R92C_RF_IPA, 0x8f406); - rtwn_rf_write(sc, i, R92C_RF_IPA, 0xcf406); - } - if (!(sc->pa_setting & 0x10)) { - reg = rtwn_read_1(sc, 0x16); - reg = (reg & ~0xf0) | 0x90; - rtwn_write_1(sc, 0x16, reg); - } -} - -static void -rtwn_rxfilter_init(struct rtwn_softc *sc) -{ - /* Initialize Rx filter. */ - /* TODO: use better filter for monitor mode. */ - rtwn_write_4(sc, R92C_RCR, - R92C_RCR_AAP | R92C_RCR_APM | R92C_RCR_AM | R92C_RCR_AB | - R92C_RCR_APP_ICV | R92C_RCR_AMF | R92C_RCR_HTC_LOC_CTRL | - R92C_RCR_APP_MIC | R92C_RCR_APP_PHYSTS); - /* Accept all multicast frames. */ - rtwn_write_4(sc, R92C_MAR + 0, 0xffffffff); - rtwn_write_4(sc, R92C_MAR + 4, 0xffffffff); - /* Accept all management frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP0, 0xffff); - /* Reject all control frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000); - /* Accept all data frames. */ - rtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff); -} - -static void -rtwn_edca_init(struct rtwn_softc *sc) -{ - - rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010); - rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010); - rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010); - rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e); - rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); - rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); - rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322); - rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222); -} - -static void -rtwn_write_txpower(struct rtwn_softc *sc, int chain, - uint16_t power[RTWN_RIDX_COUNT]) -{ - uint32_t reg; - - /* Write per-CCK rate Tx power. */ - if (chain == 0) { - reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32); - reg = RW(reg, R92C_TXAGC_A_CCK1, power[0]); - rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg); - reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); - reg = RW(reg, R92C_TXAGC_A_CCK2, power[1]); - reg = RW(reg, R92C_TXAGC_A_CCK55, power[2]); - reg = RW(reg, R92C_TXAGC_A_CCK11, power[3]); - rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); - } else { - reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32); - reg = RW(reg, R92C_TXAGC_B_CCK1, power[0]); - reg = RW(reg, R92C_TXAGC_B_CCK2, power[1]); - reg = RW(reg, R92C_TXAGC_B_CCK55, power[2]); - rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg); - reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); - reg = RW(reg, R92C_TXAGC_B_CCK11, power[3]); - rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); - } - /* Write per-OFDM rate Tx power. */ - rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain), - SM(R92C_TXAGC_RATE06, power[ 4]) | - SM(R92C_TXAGC_RATE09, power[ 5]) | - SM(R92C_TXAGC_RATE12, power[ 6]) | - SM(R92C_TXAGC_RATE18, power[ 7])); - rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain), - SM(R92C_TXAGC_RATE24, power[ 8]) | - SM(R92C_TXAGC_RATE36, power[ 9]) | - SM(R92C_TXAGC_RATE48, power[10]) | - SM(R92C_TXAGC_RATE54, power[11])); - /* Write per-MCS Tx power. */ - rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain), - SM(R92C_TXAGC_MCS00, power[12]) | - SM(R92C_TXAGC_MCS01, power[13]) | - SM(R92C_TXAGC_MCS02, power[14]) | - SM(R92C_TXAGC_MCS03, power[15])); - rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain), - SM(R92C_TXAGC_MCS04, power[16]) | - SM(R92C_TXAGC_MCS05, power[17]) | - SM(R92C_TXAGC_MCS06, power[18]) | - SM(R92C_TXAGC_MCS07, power[19])); - rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain), - SM(R92C_TXAGC_MCS08, power[20]) | - SM(R92C_TXAGC_MCS09, power[21]) | - SM(R92C_TXAGC_MCS10, power[22]) | - SM(R92C_TXAGC_MCS11, power[23])); - rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain), - SM(R92C_TXAGC_MCS12, power[24]) | - SM(R92C_TXAGC_MCS13, power[25]) | - SM(R92C_TXAGC_MCS14, power[26]) | - SM(R92C_TXAGC_MCS15, power[27])); -} - -static void -rtwn_get_txpower(struct rtwn_softc *sc, int chain, - struct ieee80211_channel *c, struct ieee80211_channel *extc, - uint16_t power[RTWN_RIDX_COUNT]) -{ - struct ieee80211com *ic = &sc->sc_ic; - struct r92c_rom *rom = &sc->rom; - uint16_t cckpow, ofdmpow, htpow, diff, max; - const struct rtwn_txpwr *base; - int ridx, chan, group; - - /* Determine channel group. */ - chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */ - if (chan <= 3) - group = 0; - else if (chan <= 9) - group = 1; - else - group = 2; - - /* Get original Tx power based on board type and RF chain. */ - if (!(sc->chip & RTWN_CHIP_92C)) { - if (sc->board_type == R92C_BOARD_TYPE_HIGHPA) - base = &rtl8188ru_txagc[chain]; - else - base = &rtl8192cu_txagc[chain]; - } else - base = &rtl8192cu_txagc[chain]; - - memset(power, 0, RTWN_RIDX_COUNT * sizeof(power[0])); - if (sc->regulatory == 0) { - for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) - power[ridx] = base->pwr[0][ridx]; - } - for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_COUNT; ridx++) { - if (sc->regulatory == 3) { - power[ridx] = base->pwr[0][ridx]; - /* Apply vendor limits. */ - if (extc != NULL) - max = rom->ht40_max_pwr[group]; - else - max = rom->ht20_max_pwr[group]; - max = (max >> (chain * 4)) & 0xf; - if (power[ridx] > max) - power[ridx] = max; - } else if (sc->regulatory == 1) { - if (extc == NULL) - power[ridx] = base->pwr[group][ridx]; - } else if (sc->regulatory != 2) - power[ridx] = base->pwr[0][ridx]; - } - - /* Compute per-CCK rate Tx power. */ - cckpow = rom->cck_tx_pwr[chain][group]; - for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) { - power[ridx] += cckpow; - if (power[ridx] > R92C_MAX_TX_PWR) - power[ridx] = R92C_MAX_TX_PWR; - } - - htpow = rom->ht40_1s_tx_pwr[chain][group]; - if (sc->ntxchains > 1) { - /* Apply reduction for 2 spatial streams. */ - diff = rom->ht40_2s_tx_pwr_diff[group]; - diff = (diff >> (chain * 4)) & 0xf; - htpow = (htpow > diff) ? htpow - diff : 0; - } - - /* Compute per-OFDM rate Tx power. */ - diff = rom->ofdm_tx_pwr_diff[group]; - diff = (diff >> (chain * 4)) & 0xf; - ofdmpow = htpow + diff; /* HT->OFDM correction. */ - for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) { - power[ridx] += ofdmpow; - if (power[ridx] > R92C_MAX_TX_PWR) - power[ridx] = R92C_MAX_TX_PWR; - } - - /* Compute per-MCS Tx power. */ - if (extc == NULL) { - diff = rom->ht20_tx_pwr_diff[group]; - diff = (diff >> (chain * 4)) & 0xf; - htpow += diff; /* HT40->HT20 correction. */ - } - for (ridx = RTWN_RIDX_MCS0; ridx <= RTWN_RIDX_MCS15; ridx++) { - power[ridx] += htpow; - if (power[ridx] > R92C_MAX_TX_PWR) - power[ridx] = R92C_MAX_TX_PWR; - } -#ifdef RTWN_DEBUG - if (sc->sc_debug >= 4) { - /* Dump per-rate Tx power values. */ - printf("Tx power for chain %d:\n", chain); - for (ridx = RTWN_RIDX_CCK1; ridx < RTWN_RIDX_COUNT; ridx++) - printf("Rate %d = %u\n", ridx, power[ridx]); - } -#endif -} - -static void -rtwn_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c, - struct ieee80211_channel *extc) -{ - uint16_t power[RTWN_RIDX_COUNT]; - int i; - - for (i = 0; i < sc->ntxchains; i++) { - /* Compute per-rate Tx power values. */ - rtwn_get_txpower(sc, i, c, extc, power); - /* Write per-rate Tx power values to hardware. */ - rtwn_write_txpower(sc, i, power); - } -} - -static void -rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable) -{ - uint32_t reg; - - reg = rtwn_read_4(sc, R92C_RCR); - if (enable) - reg &= ~R92C_RCR_CBSSID_BCN; - else - reg |= R92C_RCR_CBSSID_BCN; - rtwn_write_4(sc, R92C_RCR, reg); -} - -static void -rtwn_set_gain(struct rtwn_softc *sc, uint8_t gain) -{ - uint32_t reg; - - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(0)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, gain); - rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCCORE1(1)); - reg = RW(reg, R92C_OFDM0_AGCCORE1_GAIN, gain); - rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(1), reg); } static void @@ -2719,13 +1479,27 @@ rtwn_scan_start(struct ieee80211com *ic) struct rtwn_softc *sc = ic->ic_softc; RTWN_LOCK(sc); + /* Pause beaconing. */ + rtwn_setbits_1(sc, R92C_TXPAUSE, 0, R92C_TX_QUEUE_BCN); /* Receive beacons / probe responses from any BSSID. */ - rtwn_set_rx_bssid_all(sc, 1); - /* Set gain for scanning. */ - rtwn_set_gain(sc, 0x20); + if (sc->bcn_vaps == 0) + rtwn_set_rx_bssid_all(sc, 1); RTWN_UNLOCK(sc); } +static void +rtwn_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell) +{ + struct rtwn_softc *sc = ss->ss_ic->ic_softc; + + /* Make link LED blink during scan. */ + RTWN_LOCK(sc); + rtwn_set_led(sc, RTWN_LED_LINK, !sc->ledlink); + RTWN_UNLOCK(sc); + + sc->sc_scan_curchan(ss, maxdwell); +} + static void rtwn_scan_end(struct ieee80211com *ic) { @@ -2733,9 +1507,17 @@ rtwn_scan_end(struct ieee80211com *ic) RTWN_LOCK(sc); /* Restore limitations. */ - rtwn_set_rx_bssid_all(sc, 0); - /* Set gain under link. */ - rtwn_set_gain(sc, 0x32); + if (ic->ic_promisc == 0 && sc->bcn_vaps == 0) + rtwn_set_rx_bssid_all(sc, 0); + + /* Restore LED state. */ + rtwn_set_led(sc, RTWN_LED_LINK, (sc->vaps_running != 0)); + + /* Restore basic rates mask. */ + rtwn_calc_basicrates(sc); + + /* Resume beaconing. */ + rtwn_setbits_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_BCN, 0); RTWN_UNLOCK(sc); } @@ -2743,791 +1525,442 @@ static void rtwn_getradiocaps(struct ieee80211com *ic, int maxchans, int *nchans, struct ieee80211_channel chans[]) { + struct rtwn_softc *sc = ic->ic_softc; uint8_t bands[IEEE80211_MODE_BYTES]; + int i; memset(bands, 0, sizeof(bands)); setbit(bands, IEEE80211_MODE_11B); setbit(bands, IEEE80211_MODE_11G); + setbit(bands, IEEE80211_MODE_11NG); ieee80211_add_channel_list_2ghz(chans, maxchans, nchans, - rtwn_chan_2ghz, nitems(rtwn_chan_2ghz), bands, 0); + rtwn_chan_2ghz, nitems(rtwn_chan_2ghz), bands, + !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + + /* XXX workaround add_channel_list() limitations */ + setbit(bands, IEEE80211_MODE_11A); + setbit(bands, IEEE80211_MODE_11NA); + for (i = 0; i < nitems(sc->chan_num_5ghz); i++) { + if (sc->chan_num_5ghz[i] == 0) + continue; + + ieee80211_add_channel_list_5ghz(chans, maxchans, nchans, + sc->chan_list_5ghz[i], sc->chan_num_5ghz[i], bands, + !!(ic->ic_htcaps & IEEE80211_HTCAP_CHWIDTH40)); + } +} + +static void +rtwn_update_chw(struct ieee80211com *ic) +{ } static void rtwn_set_channel(struct ieee80211com *ic) { struct rtwn_softc *sc = ic->ic_softc; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); + struct ieee80211_channel *c = ic->ic_curchan; RTWN_LOCK(sc); - if (vap->iv_state == IEEE80211_S_SCAN) { - /* Make link LED blink during scan. */ - rtwn_set_led(sc, RTWN_LED_LINK, !sc->ledlink); + rtwn_set_chan(sc, c); + sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq); + sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags); + sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq); + sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags); + RTWN_UNLOCK(sc); +} + +static int +rtwn_wme_update(struct ieee80211com *ic) +{ + struct chanAccParams chp; + struct ieee80211_channel *c = ic->ic_curchan; + struct rtwn_softc *sc = ic->ic_softc; + struct wmeParams *wmep = sc->cap_wmeParams; + uint8_t aifs, acm, slottime; + int ac; + + ieee80211_wme_ic_getparams(ic, &chp); + + /* Prevent possible races. */ + IEEE80211_LOCK(ic); /* XXX */ + RTWN_LOCK(sc); + memcpy(wmep, chp.cap_wmeParams, sizeof(sc->cap_wmeParams)); + RTWN_UNLOCK(sc); + IEEE80211_UNLOCK(ic); + + acm = 0; + slottime = IEEE80211_GET_SLOTTIME(ic); + + RTWN_LOCK(sc); + for (ac = WME_AC_BE; ac < WME_NUM_AC; ac++) { + /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */ + aifs = wmep[ac].wmep_aifsn * slottime + + (IEEE80211_IS_CHAN_5GHZ(c) ? + IEEE80211_DUR_OFDM_SIFS : IEEE80211_DUR_SIFS); + rtwn_write_4(sc, wme2reg[ac], + SM(R92C_EDCA_PARAM_TXOP, wmep[ac].wmep_txopLimit) | + SM(R92C_EDCA_PARAM_ECWMIN, wmep[ac].wmep_logcwmin) | + SM(R92C_EDCA_PARAM_ECWMAX, wmep[ac].wmep_logcwmax) | + SM(R92C_EDCA_PARAM_AIFS, aifs)); + if (ac != WME_AC_BE) + acm |= wmep[ac].wmep_acm << ac; } - rtwn_set_chan(sc, ic->ic_curchan, NULL); + + if (acm != 0) + acm |= R92C_ACMHWCTRL_EN; + rtwn_setbits_1(sc, R92C_ACMHWCTRL, R92C_ACMHWCTRL_ACM_MASK, acm); + RTWN_UNLOCK(sc); + + return 0; +} + +static void +rtwn_update_slot(struct ieee80211com *ic) +{ + rtwn_cmd_sleepable(ic->ic_softc, NULL, 0, rtwn_update_slot_cb); +} + +static void +rtwn_update_slot_cb(struct rtwn_softc *sc, union sec_param *data) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint8_t slottime; + + slottime = IEEE80211_GET_SLOTTIME(ic); + + RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: setting slot time to %uus\n", + __func__, slottime); + + rtwn_write_1(sc, R92C_SLOT, slottime); + rtwn_update_aifs(sc, slottime); +} + +static void +rtwn_update_aifs(struct rtwn_softc *sc, uint8_t slottime) +{ + struct ieee80211_channel *c = sc->sc_ic.ic_curchan; + const struct wmeParams *wmep = sc->cap_wmeParams; + uint8_t aifs, ac; + + for (ac = WME_AC_BE; ac < WME_NUM_AC; ac++) { + /* AIFS[AC] = AIFSN[AC] * aSlotTime + aSIFSTime. */ + aifs = wmep[ac].wmep_aifsn * slottime + + (IEEE80211_IS_CHAN_5GHZ(c) ? + IEEE80211_DUR_OFDM_SIFS : IEEE80211_DUR_SIFS); + rtwn_write_1(sc, wme2reg[ac], aifs); + } +} + +static void +rtwn_update_promisc(struct ieee80211com *ic) +{ + struct rtwn_softc *sc = ic->ic_softc; + + RTWN_LOCK(sc); + if (sc->sc_flags & RTWN_RUNNING) + rtwn_set_promisc(sc); RTWN_UNLOCK(sc); } static void rtwn_update_mcast(struct ieee80211com *ic) { + struct rtwn_softc *sc = ic->ic_softc; - /* XXX do nothing? */ -} - -static void -rtwn_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c, - struct ieee80211_channel *extc) -{ - struct ieee80211com *ic = &sc->sc_ic; - u_int chan; - int i; - - chan = ieee80211_chan2ieee(ic, c); /* XXX center freq! */ - if (chan == 0 || chan == IEEE80211_CHAN_ANY) { - device_printf(sc->sc_dev, - "%s: invalid channel %x\n", __func__, chan); - return; - } - - /* Set Tx power for this new channel. */ - rtwn_set_txpower(sc, c, extc); - - for (i = 0; i < sc->nrxchains; i++) { - rtwn_rf_write(sc, i, R92C_RF_CHNLBW, - RW(sc->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan)); - } -#ifndef IEEE80211_NO_HT - if (extc != NULL) { - uint32_t reg; - - /* Is secondary channel below or above primary? */ - int prichlo = c->ic_freq < extc->ic_freq; - - rtwn_write_1(sc, R92C_BWOPMODE, - rtwn_read_1(sc, R92C_BWOPMODE) & ~R92C_BWOPMODE_20MHZ); - - reg = rtwn_read_1(sc, R92C_RRSR + 2); - reg = (reg & ~0x6f) | (prichlo ? 1 : 2) << 5; - rtwn_write_1(sc, R92C_RRSR + 2, reg); - - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, - rtwn_bb_read(sc, R92C_FPGA0_RFMOD) | R92C_RFMOD_40MHZ); - rtwn_bb_write(sc, R92C_FPGA1_RFMOD, - rtwn_bb_read(sc, R92C_FPGA1_RFMOD) | R92C_RFMOD_40MHZ); - - /* Set CCK side band. */ - reg = rtwn_bb_read(sc, R92C_CCK0_SYSTEM); - reg = (reg & ~0x00000010) | (prichlo ? 0 : 1) << 4; - rtwn_bb_write(sc, R92C_CCK0_SYSTEM, reg); - - reg = rtwn_bb_read(sc, R92C_OFDM1_LSTF); - reg = (reg & ~0x00000c00) | (prichlo ? 1 : 2) << 10; - rtwn_bb_write(sc, R92C_OFDM1_LSTF, reg); - - rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, - rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) & - ~R92C_FPGA0_ANAPARAM2_CBW20); - - reg = rtwn_bb_read(sc, 0x818); - reg = (reg & ~0x0c000000) | (prichlo ? 2 : 1) << 26; - rtwn_bb_write(sc, 0x818, reg); - - /* Select 40MHz bandwidth. */ - rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - (sc->rf_chnlbw[0] & ~0xfff) | chan); - } else -#endif - { - rtwn_write_1(sc, R92C_BWOPMODE, - rtwn_read_1(sc, R92C_BWOPMODE) | R92C_BWOPMODE_20MHZ); - - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, - rtwn_bb_read(sc, R92C_FPGA0_RFMOD) & ~R92C_RFMOD_40MHZ); - rtwn_bb_write(sc, R92C_FPGA1_RFMOD, - rtwn_bb_read(sc, R92C_FPGA1_RFMOD) & ~R92C_RFMOD_40MHZ); - - rtwn_bb_write(sc, R92C_FPGA0_ANAPARAM2, - rtwn_bb_read(sc, R92C_FPGA0_ANAPARAM2) | - R92C_FPGA0_ANAPARAM2_CBW20); - - /* Select 20MHz bandwidth. */ - rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - (sc->rf_chnlbw[0] & ~0xfff) | R92C_RF_CHNLBW_BW20 | chan); - } + RTWN_LOCK(sc); + if (sc->sc_flags & RTWN_RUNNING) + rtwn_set_multi(sc); + RTWN_UNLOCK(sc); } static int -rtwn_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2], - uint16_t rx[2]) +rtwn_set_bssid(struct rtwn_softc *sc, const uint8_t *bssid, int id) { - uint32_t status; - int offset = chain * 0x20; + int error; - if (chain == 0) { /* IQ calibration for chain 0. */ - /* IQ calibration settings for chain 0. */ - rtwn_bb_write(sc, 0xe30, 0x10008c1f); - rtwn_bb_write(sc, 0xe34, 0x10008c1f); - rtwn_bb_write(sc, 0xe38, 0x82140102); + error = rtwn_write_4(sc, R92C_BSSID(id), le32dec(&bssid[0])); + if (error != 0) + return (error); + error = rtwn_write_2(sc, R92C_BSSID(id) + 4, le16dec(&bssid[4])); - if (sc->ntxchains > 1) { - rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */ - /* IQ calibration settings for chain 1. */ - rtwn_bb_write(sc, 0xe50, 0x10008c22); - rtwn_bb_write(sc, 0xe54, 0x10008c22); - rtwn_bb_write(sc, 0xe58, 0x82140102); - rtwn_bb_write(sc, 0xe5c, 0x28160202); - } else - rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */ - - /* LO calibration settings. */ - rtwn_bb_write(sc, 0xe4c, 0x001028d1); - /* We're doing LO and IQ calibration in one shot. */ - rtwn_bb_write(sc, 0xe48, 0xf9000000); - rtwn_bb_write(sc, 0xe48, 0xf8000000); - - } else { /* IQ calibration for chain 1. */ - /* We're doing LO and IQ calibration in one shot. */ - rtwn_bb_write(sc, 0xe60, 0x00000002); - rtwn_bb_write(sc, 0xe60, 0x00000000); - } - - /* Give LO and IQ calibrations the time to complete. */ - DELAY(1000); - - /* Read IQ calibration status. */ - status = rtwn_bb_read(sc, 0xeac); - - if (status & (1 << (28 + chain * 3))) - return (0); /* Tx failed. */ - /* Read Tx IQ calibration results. */ - tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff; - tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff; - if (tx[0] == 0x142 || tx[1] == 0x042) - return (0); /* Tx failed. */ - - if (status & (1 << (27 + chain * 3))) - return (1); /* Rx failed. */ - /* Read Rx IQ calibration results. */ - rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff; - rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff; - if (rx[0] == 0x132 || rx[1] == 0x036) - return (1); /* Rx failed. */ - - return (3); /* Both Tx and Rx succeeded. */ + return (error); } -static void -rtwn_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2], - uint16_t rx[2][2]) -{ - /* Registers to save and restore during IQ calibration. */ - struct iq_cal_regs { - uint32_t adda[16]; - uint8_t txpause; - uint8_t bcn_ctrl; - uint8_t ustime_tsf; - uint32_t gpio_muxcfg; - uint32_t ofdm0_trxpathena; - uint32_t ofdm0_trmuxpar; - uint32_t fpga0_rfifacesw1; - } iq_cal_regs; - static const uint16_t reg_adda[16] = { - 0x85c, 0xe6c, 0xe70, 0xe74, - 0xe78, 0xe7c, 0xe80, 0xe84, - 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec - }; - int i, chain; - uint32_t hssi_param1; - - if (n == 0) { - for (i = 0; i < nitems(reg_adda); i++) - iq_cal_regs.adda[i] = rtwn_bb_read(sc, reg_adda[i]); - - iq_cal_regs.txpause = rtwn_read_1(sc, R92C_TXPAUSE); - iq_cal_regs.bcn_ctrl = rtwn_read_1(sc, R92C_BCN_CTRL); - iq_cal_regs.ustime_tsf = rtwn_read_1(sc, R92C_USTIME_TSF); - iq_cal_regs.gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); - } - - if (sc->ntxchains == 1) { - rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); - for (i = 1; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); - } else { - for (i = 0; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], 0x04db25a4); - } - - hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0)); - if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { - rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), - hssi_param1 | R92C_HSSI_PARAM1_PI); - rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), - hssi_param1 | R92C_HSSI_PARAM1_PI); - } - - if (n == 0) { - iq_cal_regs.ofdm0_trxpathena = - rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); - iq_cal_regs.ofdm0_trmuxpar = - rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); - iq_cal_regs.fpga0_rfifacesw1 = - rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); - } - - rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600); - rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4); - rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000); - if (sc->ntxchains > 1) { - rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); - rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000); - } - - rtwn_write_1(sc, R92C_TXPAUSE, 0x3f); - rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs.bcn_ctrl & ~(0x08)); - rtwn_write_1(sc, R92C_USTIME_TSF, iq_cal_regs.ustime_tsf & ~(0x08)); - rtwn_write_1(sc, R92C_GPIO_MUXCFG, - iq_cal_regs.gpio_muxcfg & ~(0x20)); - - rtwn_bb_write(sc, 0x0b68, 0x00080000); - if (sc->ntxchains > 1) - rtwn_bb_write(sc, 0x0b6c, 0x00080000); - - rtwn_bb_write(sc, 0x0e28, 0x80800000); - rtwn_bb_write(sc, 0x0e40, 0x01007c00); - rtwn_bb_write(sc, 0x0e44, 0x01004800); - - rtwn_bb_write(sc, 0x0b68, 0x00080000); - - for (chain = 0; chain < sc->ntxchains; chain++) { - if (chain > 0) { - /* Put chain 0 on standby. */ - rtwn_bb_write(sc, 0x0e28, 0x00); - rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); - rtwn_bb_write(sc, 0x0e28, 0x80800000); - - /* Enable chain 1. */ - for (i = 0; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4); - } - - /* Run IQ calibration twice. */ - for (i = 0; i < 2; i++) { - int ret; - - ret = rtwn_iq_calib_chain(sc, chain, - tx[chain], rx[chain]); - if (ret == 0) { - DPRINTF(("%s: chain %d: Tx failed.\n", - __func__, chain)); - tx[chain][0] = 0xff; - tx[chain][1] = 0xff; - rx[chain][0] = 0xff; - rx[chain][1] = 0xff; - } else if (ret == 1) { - DPRINTF(("%s: chain %d: Rx failed.\n", - __func__, chain)); - rx[chain][0] = 0xff; - rx[chain][1] = 0xff; - } else if (ret == 3) { - DPRINTF(("%s: chain %d: Both Tx and Rx " - "succeeded.\n", __func__, chain)); - } - } - - DPRINTF(("%s: results for run %d chain %d: tx[0]=0x%x, " - "tx[1]=0x%x rx[0]=0x%x rx[1]=0x%x\n", __func__, n, chain, - tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1])); - } - - rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, - iq_cal_regs.ofdm0_trxpathena); - rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), - iq_cal_regs.fpga0_rfifacesw1); - rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, iq_cal_regs.ofdm0_trmuxpar); - - rtwn_bb_write(sc, 0x0e28, 0x00); - rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); - if (sc->ntxchains > 1) - rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3); - - if (n != 0) { - if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { - rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1); - rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1); - } - - for (i = 0; i < nitems(reg_adda); i++) - rtwn_bb_write(sc, reg_adda[i], iq_cal_regs.adda[i]); - - rtwn_write_1(sc, R92C_TXPAUSE, iq_cal_regs.txpause); - rtwn_write_1(sc, R92C_BCN_CTRL, iq_cal_regs.bcn_ctrl); - rtwn_write_1(sc, R92C_USTIME_TSF, iq_cal_regs.ustime_tsf); - rtwn_write_4(sc, R92C_GPIO_MUXCFG, iq_cal_regs.gpio_muxcfg); - } -} - -#define RTWN_IQ_CAL_MAX_TOLERANCE 5 static int -rtwn_iq_calib_compare_results(uint16_t tx1[2][2], uint16_t rx1[2][2], - uint16_t tx2[2][2], uint16_t rx2[2][2], int ntxchains) +rtwn_set_macaddr(struct rtwn_softc *sc, const uint8_t *addr, int id) { - int chain, i, tx_ok[2], rx_ok[2]; + int error; - tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0; - for (chain = 0; chain < ntxchains; chain++) { - for (i = 0; i < 2; i++) { - if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff || - rx1[chain][i] == 0xff || rx2[chain][i] == 0xff) - continue; + error = rtwn_write_4(sc, R92C_MACID(id), le32dec(&addr[0])); + if (error != 0) + return (error); + error = rtwn_write_2(sc, R92C_MACID(id) + 4, le16dec(&addr[4])); - tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <= - RTWN_IQ_CAL_MAX_TOLERANCE); - - rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <= - RTWN_IQ_CAL_MAX_TOLERANCE); - } - } - - if (ntxchains > 1) - return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]); - else - return (tx_ok[0] && rx_ok[0]); -} -#undef RTWN_IQ_CAL_MAX_TOLERANCE - -static void -rtwn_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], - uint16_t rx[2], int chain) -{ - uint32_t reg, val, x; - long y, tx_c; - - if (tx[0] == 0xff || tx[1] == 0xff) - return; - - reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); - val = ((reg >> 22) & 0x3ff); - x = tx[0]; - if (x & 0x0200) - x |= 0xfc00; - reg = (((x * val) >> 8) & 0x3ff); - rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD); - if (((x * val) >> 7) & 0x01) - reg |= 0x80000000; - else - reg &= ~0x80000000; - rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg); - - y = tx[1]; - if (y & 0x00000200) - y |= 0xfffffc00; - tx_c = (y * val) >> 8; - reg = rtwn_bb_read(sc, R92C_OFDM0_TXAFE(chain)); - reg |= ((((tx_c & 0x3c0) >> 6) << 24) & 0xf0000000); - rtwn_bb_write(sc, R92C_OFDM0_TXAFE(chain), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); - reg |= (((tx_c & 0x3f) << 16) & 0x003F0000); - rtwn_bb_write(sc, R92C_OFDM0_TXIQIMBALANCE(chain), reg); - - reg = rtwn_bb_read(sc, R92C_OFDM0_ECCATHRESHOLD); - if (((y * val) >> 7) & 0x01) - reg |= 0x20000000; - else - reg &= ~0x20000000; - rtwn_bb_write(sc, R92C_OFDM0_ECCATHRESHOLD, reg); - - if (rx[0] == 0xff || rx[1] == 0xff) - return; - - reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQIMBALANCE(chain)); - reg |= (rx[0] & 0x3ff); - rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg); - reg |= (((rx[1] & 0x03f) << 8) & 0xFC00); - rtwn_bb_write(sc, R92C_OFDM0_RXIQIMBALANCE(chain), reg); - - if (chain == 0) { - reg = rtwn_bb_read(sc, R92C_OFDM0_RXIQEXTANTA); - reg |= (((rx[1] & 0xf) >> 6) & 0x000f); - rtwn_bb_write(sc, R92C_OFDM0_RXIQEXTANTA, reg); - } else { - reg = rtwn_bb_read(sc, R92C_OFDM0_AGCRSSITABLE); - reg |= ((((rx[1] & 0xf) >> 6) << 12) & 0xf000); - rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, reg); - } + return (error); } -#define RTWN_IQ_CAL_NRUN 3 -static void -rtwn_iq_calib(struct rtwn_softc *sc) +static struct ieee80211_node * +rtwn_node_alloc(struct ieee80211vap *vap, + const uint8_t mac[IEEE80211_ADDR_LEN]) { - uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2]; - int n, valid; + struct rtwn_node *un; - valid = 0; - for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { - rtwn_iq_calib_run(sc, n, tx[n], rx[n]); + un = malloc(sizeof (struct rtwn_node), M_80211_NODE, + M_NOWAIT | M_ZERO); - if (n == 0) - continue; + if (un == NULL) + return NULL; - /* Valid results remain stable after consecutive runs. */ - valid = rtwn_iq_calib_compare_results(tx[n - 1], rx[n - 1], - tx[n], rx[n], sc->ntxchains); - if (valid) + un->id = RTWN_MACID_UNDEFINED; + un->avg_pwdb = -1; + + return &un->ni; +} + +static void +rtwn_newassoc(struct ieee80211_node *ni, int isnew __unused) +{ + struct rtwn_softc *sc = ni->ni_ic->ic_softc; + struct rtwn_node *un = RTWN_NODE(ni); + int id; + + if (un->id != RTWN_MACID_UNDEFINED) + return; + + RTWN_NT_LOCK(sc); + for (id = 0; id <= sc->macid_limit; id++) { + if (id != RTWN_MACID_BC && sc->node_list[id] == NULL) { + un->id = id; + sc->node_list[id] = ni; break; - } - - if (valid) { - rtwn_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0); - if (sc->ntxchains > 1) - rtwn_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1); - } -} -#undef RTWN_IQ_CAL_NRUN - -static void -rtwn_lc_calib(struct rtwn_softc *sc) -{ - uint32_t rf_ac[2]; - uint8_t txmode; - int i; - - txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3); - if ((txmode & 0x70) != 0) { - /* Disable all continuous Tx. */ - rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70); - - /* Set RF mode to standby mode. */ - for (i = 0; i < sc->nrxchains; i++) { - rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC); - rtwn_rf_write(sc, i, R92C_RF_AC, - RW(rf_ac[i], R92C_RF_AC_MODE, - R92C_RF_AC_MODE_STANDBY)); } - } else { - /* Block all Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0xff); } - /* Start calibration. */ - rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, - rtwn_rf_read(sc, 0, R92C_RF_CHNLBW) | R92C_RF_CHNLBW_LCSTART); + RTWN_NT_UNLOCK(sc); - /* Give calibration the time to complete. */ - DELAY(100); - - /* Restore configuration. */ - if ((txmode & 0x70) != 0) { - /* Restore Tx mode. */ - rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode); - /* Restore RF mode. */ - for (i = 0; i < sc->nrxchains; i++) - rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]); - } else { - /* Unblock all Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0x00); + if (id > sc->macid_limit) { + device_printf(sc->sc_dev, "%s: node table is full\n", + __func__); + return; } + + /* Notify firmware. */ + id |= RTWN_MACID_VALID; + rtwn_cmd_sleepable(sc, &id, sizeof(id), rtwn_set_media_status); } static void -rtwn_temp_calib(struct rtwn_softc *sc) +rtwn_node_free(struct ieee80211_node *ni) { - int temp; + struct rtwn_softc *sc = ni->ni_ic->ic_softc; + struct rtwn_node *un = RTWN_NODE(ni); - if (sc->thcal_state == 0) { - /* Start measuring temperature. */ - rtwn_rf_write(sc, 0, R92C_RF_T_METER, 0x60); - sc->thcal_state = 1; - return; + RTWN_NT_LOCK(sc); + if (un->id != RTWN_MACID_UNDEFINED) { + sc->node_list[un->id] = NULL; + rtwn_cmd_sleepable(sc, &un->id, sizeof(un->id), + rtwn_set_media_status); } - sc->thcal_state = 0; + RTWN_NT_UNLOCK(sc); - /* Read measured temperature. */ - temp = rtwn_rf_read(sc, 0, R92C_RF_T_METER) & 0x1f; - if (temp == 0) /* Read failed, skip. */ - return; - DPRINTFN(2, ("temperature=%d\n", temp)); + sc->sc_node_free(ni); +} - /* - * Redo IQ and LC calibration if temperature changed significantly - * since last calibration. - */ - if (sc->thcal_lctemp == 0) { - /* First calibration is performed in rtwn_init(). */ - sc->thcal_lctemp = temp; - } else if (abs(temp - sc->thcal_lctemp) > 1) { - DPRINTF(("IQ/LC calib triggered by temp: %d -> %d\n", - sc->thcal_lctemp, temp)); - rtwn_iq_calib(sc); - rtwn_lc_calib(sc); - /* Record temperature of last calibration. */ - sc->thcal_lctemp = temp; - } +static void +rtwn_init_beacon_reg(struct rtwn_softc *sc) +{ + rtwn_write_1(sc, R92C_BCN_CTRL(0), R92C_BCN_CTRL_DIS_TSF_UDT0); + rtwn_write_1(sc, R92C_BCN_CTRL(1), R92C_BCN_CTRL_DIS_TSF_UDT0); + rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404); + rtwn_write_1(sc, R92C_DRVERLYINT, 0x05); + rtwn_write_1(sc, R92C_BCNDMATIM, 0x02); + rtwn_write_2(sc, R92C_BCNTCFG, 0x660f); } static int rtwn_init(struct rtwn_softc *sc) { struct ieee80211com *ic = &sc->sc_ic; - struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); - uint32_t reg; - uint8_t macaddr[IEEE80211_ADDR_LEN]; int i, error; RTWN_LOCK(sc); - if (sc->sc_flags & RTWN_RUNNING) { RTWN_UNLOCK(sc); - return 0; + return (0); } - sc->sc_flags |= RTWN_RUNNING; - - /* Init firmware commands ring. */ - sc->fwcur = 0; + sc->sc_flags |= RTWN_STARTED; /* Power on adapter. */ error = rtwn_power_on(sc); + if (error != 0) + goto fail; + +#ifndef RTWN_WITHOUT_UCODE + /* Load 8051 microcode. */ + error = rtwn_load_firmware(sc); + if (error == 0) + sc->sc_flags |= RTWN_FW_LOADED; + + /* Init firmware commands ring. */ + sc->fwcur = 0; +#endif + + /* Initialize MAC block. */ + error = rtwn_mac_init(sc); if (error != 0) { - device_printf(sc->sc_dev, "could not power on adapter\n"); + device_printf(sc->sc_dev, + "%s: error while initializing MAC block\n", __func__); goto fail; } /* Initialize DMA. */ error = rtwn_dma_init(sc); - if (error != 0) { - device_printf(sc->sc_dev, "could not initialize DMA\n"); + if (error != 0) goto fail; - } + + /* Drop incorrect TX (USB). */ + rtwn_drop_incorrect_tx(sc); /* Set info size in Rx descriptors (in 64-bit words). */ - rtwn_write_1(sc, R92C_RX_DRVINFO_SZ, 4); + rtwn_write_1(sc, R92C_RX_DRVINFO_SZ, R92C_RX_DRVINFO_SZ_DEF); - /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HISR, 0x00000000); - rtwn_write_4(sc, R92C_HIMR, 0x00000000); + /* Init interrupts. */ + rtwn_init_intr(sc); - /* Set MAC address. */ - IEEE80211_ADDR_COPY(macaddr, vap ? vap->iv_myaddr : ic->ic_macaddr); - for (i = 0; i < IEEE80211_ADDR_LEN; i++) - rtwn_write_1(sc, R92C_MACID + i, macaddr[i]); + for (i = 0; i < nitems(sc->vaps); i++) { + struct rtwn_vap *uvp = sc->vaps[i]; - /* Set initial network type. */ - reg = rtwn_read_4(sc, R92C_CR); - reg = RW(reg, R92C_CR_NETTYPE, R92C_CR_NETTYPE_INFRA); - rtwn_write_4(sc, R92C_CR, reg); + /* Set initial network type. */ + rtwn_set_mode(sc, R92C_MSR_NOLINK, i); + if (uvp == NULL) + continue; + + /* Set MAC address. */ + error = rtwn_set_macaddr(sc, uvp->vap.iv_myaddr, uvp->id); + if (error != 0) + goto fail; + } + + /* Initialize Rx filter. */ rtwn_rxfilter_init(sc); - reg = rtwn_read_4(sc, R92C_RRSR); - reg = RW(reg, R92C_RRSR_RATE_BITMAP, R92C_RRSR_RATE_ALL); - rtwn_write_4(sc, R92C_RRSR, reg); - /* Set short/long retry limits. */ rtwn_write_2(sc, R92C_RL, - SM(R92C_RL_SRL, 0x07) | SM(R92C_RL_LRL, 0x07)); + SM(R92C_RL_SRL, 0x30) | SM(R92C_RL_LRL, 0x30)); /* Initialize EDCA parameters. */ - rtwn_edca_init(sc); - - /* Set data and response automatic rate fallback retry counts. */ - rtwn_write_4(sc, R92C_DARFRC + 0, 0x01000000); - rtwn_write_4(sc, R92C_DARFRC + 4, 0x07060504); - rtwn_write_4(sc, R92C_RARFRC + 0, 0x01000000); - rtwn_write_4(sc, R92C_RARFRC + 4, 0x07060504); - - rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL, 0x1f80); + rtwn_init_edca(sc); + rtwn_setbits_1(sc, R92C_FWHW_TXQ_CTRL, 0, + R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW); /* Set ACK timeout. */ - rtwn_write_1(sc, R92C_ACKTO, 0x40); + rtwn_write_1(sc, R92C_ACKTO, sc->ackto); + + /* Setup aggregation. */ + /* Tx aggregation. */ + rtwn_init_tx_agg(sc); + rtwn_init_rx_agg(sc); /* Initialize beacon parameters. */ - rtwn_write_2(sc, R92C_TBTT_PROHIBIT, 0x6404); - rtwn_write_1(sc, R92C_DRVERLYINT, 0x05); - rtwn_write_1(sc, R92C_BCNDMATIM, 0x02); - rtwn_write_2(sc, R92C_BCNTCFG, 0x660f); + rtwn_init_beacon_reg(sc); - /* Setup AMPDU aggregation. */ - rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ - rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); + /* Init A-MPDU parameters. */ + rtwn_init_ampdu(sc); - rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); - rtwn_write_1(sc, R92C_BCN_CTRL, R92C_BCN_CTRL_DIS_TSF_UDT0); + /* Init MACTXEN / MACRXEN after setting RxFF boundary. */ + rtwn_setbits_1(sc, R92C_CR, 0, R92C_CR_MACTXEN | R92C_CR_MACRXEN); - rtwn_write_4(sc, R92C_PIFS, 0x1c); - rtwn_write_4(sc, R92C_MCUTST_1, 0x0); + /* Initialize BB/RF blocks. */ + rtwn_init_bb(sc); + rtwn_init_rf(sc); - /* Load 8051 microcode. */ - error = rtwn_load_firmware(sc); - if (error != 0) - goto fail; - - /* Initialize MAC/BB/RF blocks. */ - rtwn_mac_init(sc); - rtwn_bb_init(sc); - rtwn_rf_init(sc); - - /* Turn CCK and OFDM blocks on. */ - reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD); - reg |= R92C_RFMOD_CCK_EN; - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); - reg = rtwn_bb_read(sc, R92C_FPGA0_RFMOD); - reg |= R92C_RFMOD_OFDM_EN; - rtwn_bb_write(sc, R92C_FPGA0_RFMOD, reg); + /* Initialize wireless band. */ + rtwn_set_chan(sc, ic->ic_curchan); /* Clear per-station keys table. */ - rtwn_cam_init(sc); + rtwn_init_cam(sc); + + /* Enable decryption / encryption. */ + rtwn_init_seccfg(sc); + + /* Install static keys (if any). */ + for (i = 0; i < nitems(sc->vaps); i++) { + if (sc->vaps[i] != NULL) { + error = rtwn_init_static_keys(sc, sc->vaps[i]); + if (error != 0) + goto fail; + } + } + + /* Initialize antenna selection. */ + rtwn_init_antsel(sc); /* Enable hardware sequence numbering. */ - rtwn_write_1(sc, R92C_HWSEQ_CTRL, 0xff); + rtwn_write_1(sc, R92C_HWSEQ_CTRL, R92C_TX_QUEUE_ALL); - /* Perform LO and IQ calibrations. */ - rtwn_iq_calib(sc); - /* Perform LC calibration. */ - rtwn_lc_calib(sc); + /* Disable BAR. */ + rtwn_write_4(sc, R92C_BAR_MODE_CTRL, 0x0201ffff); - rtwn_pa_bias_init(sc); + /* NAV limit. */ + rtwn_write_1(sc, R92C_NAV_UPPER, 0); /* Initialize GPIO setting. */ - rtwn_write_1(sc, R92C_GPIO_MUXCFG, - rtwn_read_1(sc, R92C_GPIO_MUXCFG) & ~R92C_GPIO_MUXCFG_ENBT); + rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, R92C_GPIO_MUXCFG_ENBT, 0); - /* Fix for lower temperature. */ - rtwn_write_1(sc, 0x15, 0xe9); + /* Initialize MRR. */ + rtwn_mrr_init(sc); - /* CLear pending interrupts. */ - rtwn_write_4(sc, R92C_HISR, 0xffffffff); + /* Device-specific post initialization. */ + rtwn_post_init(sc); - /* Enable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); + rtwn_start_xfers(sc); - callout_reset(&sc->watchdog_to, hz, rtwn_watchdog, sc); +#ifndef D4054 + callout_reset(&sc->sc_watchdog_to, hz, rtwn_watchdog, sc); +#endif + sc->sc_flags |= RTWN_RUNNING; fail: - if (error != 0) - rtwn_stop_locked(sc); - RTWN_UNLOCK(sc); - return error; -} - -static void -rtwn_stop_locked(struct rtwn_softc *sc) -{ - uint16_t reg; - int i; - - RTWN_LOCK_ASSERT(sc); - - if (!(sc->sc_flags & RTWN_RUNNING)) - return; - - sc->sc_tx_timer = 0; - callout_stop(&sc->watchdog_to); - callout_stop(&sc->calib_to); - sc->sc_flags &= ~RTWN_RUNNING; - - /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HISR, 0x00000000); - rtwn_write_4(sc, R92C_HIMR, 0x00000000); - - /* Stop hardware. */ - rtwn_write_1(sc, R92C_TXPAUSE, 0xff); - rtwn_write_1(sc, R92C_RF_CTRL, 0x00); - reg = rtwn_read_1(sc, R92C_SYS_FUNC_EN); - reg |= R92C_SYS_FUNC_EN_BB_GLB_RST; - rtwn_write_1(sc, R92C_SYS_FUNC_EN, reg); - reg &= ~R92C_SYS_FUNC_EN_BB_GLB_RST; - rtwn_write_1(sc, R92C_SYS_FUNC_EN, reg); - reg = rtwn_read_2(sc, R92C_CR); - reg &= ~(R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | - R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | - R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | - R92C_CR_ENSEC); - rtwn_write_2(sc, R92C_CR, reg); - if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) - rtwn_fw_reset(sc); - /* TODO: linux does additional btcoex stuff here */ - rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0x80); /* linux magic number */ - rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); /* ditto */ - rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0e); /* different with btcoex */ - rtwn_write_1(sc, R92C_RSV_CTRL, 0x0e); - rtwn_write_1(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_PDN_EN); - - for (i = 0; i < RTWN_NTXQUEUES; i++) - rtwn_reset_tx_list(sc, i); - rtwn_reset_rx_list(sc); + return (error); } static void rtwn_stop(struct rtwn_softc *sc) { - RTWN_LOCK(sc); - rtwn_stop_locked(sc); - RTWN_UNLOCK(sc); -} - -static void -rtwn_intr(void *arg) -{ - struct rtwn_softc *sc = arg; - uint32_t status; - int i; RTWN_LOCK(sc); -#ifndef __HAIKU__ - status = rtwn_read_4(sc, R92C_HISR); - if (status == 0 || status == 0xffffffff) { + if (!(sc->sc_flags & RTWN_STARTED)) { RTWN_UNLOCK(sc); return; } - /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, 0x00000000); -#else - status = atomic_get((int32 *)&sc->sc_intr_status); +#ifndef D4054 + callout_stop(&sc->sc_watchdog_to); + sc->sc_tx_timer = 0; +#endif + sc->sc_flags &= ~(RTWN_STARTED | RTWN_RUNNING | RTWN_FW_LOADED); + sc->sc_flags &= ~RTWN_TEMP_MEASURED; + sc->fwver = 0; + sc->thcal_temp = 0; + sc->cur_bcnq_id = RTWN_VAP_ID_INVALID; + bzero(&sc->last_physt, sizeof(sc->last_physt)); + +#ifdef D4054 + ieee80211_tx_watchdog_stop(&sc->sc_ic); #endif - /* Ack interrupts. */ - rtwn_write_4(sc, R92C_HISR, status); - - /* Vendor driver treats RX errors like ROK... */ - if (status & (R92C_IMR_ROK | R92C_IMR_RXFOVW | R92C_IMR_RDU)) { - bus_dmamap_sync(sc->rx_ring.desc_dmat, sc->rx_ring.desc_map, - BUS_DMASYNC_POSTREAD); - - for (i = 0; i < RTWN_RX_LIST_COUNT; i++) { - struct r92c_rx_desc *rx_desc = &sc->rx_ring.desc[i]; - struct rtwn_rx_data *rx_data = &sc->rx_ring.rx_data[i]; - - if (le32toh(rx_desc->rxdw0) & R92C_RXDW0_OWN) - continue; - - rtwn_rx_frame(sc, rx_desc, rx_data, i); - } - } - - if (status & R92C_IMR_BDOK) - rtwn_tx_done(sc, RTWN_BEACON_QUEUE); - if (status & R92C_IMR_HIGHDOK) - rtwn_tx_done(sc, RTWN_HIGH_QUEUE); - if (status & R92C_IMR_MGNTDOK) - rtwn_tx_done(sc, RTWN_MGNT_QUEUE); - if (status & R92C_IMR_BKDOK) - rtwn_tx_done(sc, RTWN_BK_QUEUE); - if (status & R92C_IMR_BEDOK) - rtwn_tx_done(sc, RTWN_BE_QUEUE); - if (status & R92C_IMR_VIDOK) - rtwn_tx_done(sc, RTWN_VI_QUEUE); - if (status & R92C_IMR_VODOK) - rtwn_tx_done(sc, RTWN_VO_QUEUE); - - /* Enable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, RTWN_INT_ENABLE); - + rtwn_abort_xfers(sc); + rtwn_drain_mbufq(sc); + rtwn_power_off(sc); + rtwn_reset_lists(sc, NULL); RTWN_UNLOCK(sc); } + +MODULE_VERSION(rtwn, 2); +MODULE_DEPEND(rtwn, wlan, 1, 1, 1); +#ifndef RTWN_WITHOUT_UCODE +MODULE_DEPEND(rtwn, firmware, 1, 1, 1); +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.c new file mode 100644 index 0000000000..777b0f4e19 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.c @@ -0,0 +1,269 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_beacon.c 310867 2016-12-30 22:24:01Z avos $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + + +static void +rtwn_reset_beacon_valid(struct rtwn_softc *sc, int id) +{ + + KASSERT (id == 0 || id == 1, ("wrong port id %d\n", id)); + + /* XXX cannot be cleared on RTL8188CE */ + rtwn_setbits_1_shift(sc, sc->bcn_status_reg[id], + R92C_TDECTRL_BCN_VALID, 0, 2); + + RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON, + "%s: 'beacon valid' bit for vap %d was unset\n", + __func__, id); +} + +static int +rtwn_check_beacon_valid(struct rtwn_softc *sc, int id) +{ + uint16_t reg; + int ntries; + + if (id == RTWN_VAP_ID_INVALID) + return (0); + + reg = sc->bcn_status_reg[id]; + for (ntries = 0; ntries < 10; ntries++) { + if (rtwn_read_4(sc, reg) & R92C_TDECTRL_BCN_VALID) { + RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON, + "%s: beacon for vap %d was recognized\n", + __func__, id); + break; + } + rtwn_delay(sc, sc->bcn_check_interval); + } + if (ntries == 10) + return (ETIMEDOUT); + + return (0); +} + +void +rtwn_switch_bcnq(struct rtwn_softc *sc, int id) +{ + + if (sc->cur_bcnq_id != id) { + /* Wait until any previous transmit completes. */ + (void) rtwn_check_beacon_valid(sc, sc->cur_bcnq_id); + + /* Change current port. */ + rtwn_beacon_select(sc, id); + sc->cur_bcnq_id = id; + } + + /* Reset 'beacon valid' bit. */ + rtwn_reset_beacon_valid(sc, id); +} + +int +rtwn_setup_beacon(struct rtwn_softc *sc, struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct mbuf *m; + + RTWN_ASSERT_LOCKED(sc); + + if (ni->ni_chan == IEEE80211_CHAN_ANYC) + return (EINVAL); + + m = ieee80211_beacon_alloc(ni); + if (m == NULL) { + device_printf(sc->sc_dev, + "%s: could not allocate beacon frame\n", __func__); + return (ENOMEM); + } + + if (uvp->bcn_mbuf != NULL) { + rtwn_beacon_unload(sc, uvp->id); + m_freem(uvp->bcn_mbuf); + } + + uvp->bcn_mbuf = m; + + rtwn_beacon_set_rate(sc, &uvp->bcn_desc.txd[0], + IEEE80211_IS_CHAN_5GHZ(ni->ni_chan)); + + return (rtwn_tx_beacon_check(sc, uvp)); +} + +/* + * Push a beacon frame into the chip. Beacon will + * be repeated by the chip every R92C_BCN_INTERVAL. + */ +static int +rtwn_tx_beacon(struct rtwn_softc *sc, struct rtwn_vap *uvp) +{ + int error; + + RTWN_ASSERT_LOCKED(sc); + + RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON, + "%s: sending beacon for vap %d\n", __func__, uvp->id); + + error = rtwn_tx_start(sc, NULL, uvp->bcn_mbuf, &uvp->bcn_desc.txd[0], + IEEE80211_FC0_TYPE_MGT, uvp->id); + + return (error); +} + +void +rtwn_update_beacon(struct ieee80211vap *vap, int item) +{ + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_softc *sc = ic->ic_softc; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211_beacon_offsets *bo = &vap->iv_bcn_off; + struct ieee80211_node *ni = vap->iv_bss; + int mcast = 0; + + RTWN_LOCK(sc); + if (uvp->bcn_mbuf == NULL) { + uvp->bcn_mbuf = ieee80211_beacon_alloc(ni); + if (uvp->bcn_mbuf == NULL) { + device_printf(sc->sc_dev, + "%s: could not allocate beacon frame\n", __func__); + RTWN_UNLOCK(sc); + return; + } + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON, + "%s: vap id %d, iv_csa_count %d, ic_csa_count %d, item %d\n", + __func__, uvp->id, vap->iv_csa_count, ic->ic_csa_count, item); + + switch (item) { + case IEEE80211_BEACON_CSA: + if (vap->iv_csa_count != ic->ic_csa_count) { + /* + * XXX two APs with different beacon intervals + * are not handled properly. + */ + /* XXX check TBTT? */ + taskqueue_enqueue_timeout(taskqueue_thread, + &uvp->tx_beacon_csa, + msecs_to_ticks(ni->ni_intval)); + } + break; + case IEEE80211_BEACON_TIM: + mcast = 1; /* XXX */ + break; + default: + break; + } + + setbit(bo->bo_flags, item); + + rtwn_beacon_update_begin(sc, vap); + RTWN_UNLOCK(sc); + + ieee80211_beacon_update(ni, uvp->bcn_mbuf, mcast); + + /* XXX clear manually */ + clrbit(bo->bo_flags, IEEE80211_BEACON_CSA); + + RTWN_LOCK(sc); + rtwn_tx_beacon(sc, uvp); + rtwn_beacon_update_end(sc, vap); + RTWN_UNLOCK(sc); +} + +void +rtwn_tx_beacon_csa(void *arg, int npending __unused) +{ + struct ieee80211vap *vap = arg; + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_softc *sc = ic->ic_softc; + struct rtwn_vap *rvp = RTWN_VAP(vap); + + KASSERT (rvp->id == 0 || rvp->id == 1, + ("wrong port id %d\n", rvp->id)); + + IEEE80211_LOCK(ic); + if (ic->ic_flags & IEEE80211_F_CSAPENDING) { + RTWN_DPRINTF(sc, RTWN_DEBUG_BEACON, + "%s: vap id %d, iv_csa_count %d, ic_csa_count %d\n", + __func__, rvp->id, vap->iv_csa_count, ic->ic_csa_count); + + rtwn_update_beacon(vap, IEEE80211_BEACON_CSA); + } + IEEE80211_UNLOCK(ic); + + (void) rvp; +} + +int +rtwn_tx_beacon_check(struct rtwn_softc *sc, struct rtwn_vap *uvp) +{ + int ntries, error; + + for (ntries = 0; ntries < 5; ntries++) { + rtwn_reset_beacon_valid(sc, uvp->id); + + error = rtwn_tx_beacon(sc, uvp); + if (error != 0) + continue; + + error = rtwn_check_beacon_valid(sc, uvp->id); + if (error == 0) + break; + } + if (ntries == 5) { + device_printf(sc->sc_dev, + "%s: cannot push beacon into chip, error %d!\n", + __func__, error); + return (error); + } + + return (0); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.h new file mode 100644 index 0000000000..9ec73ea9a3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_beacon.h @@ -0,0 +1,28 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_beacon.h 310867 2016-12-30 22:24:01Z avos $ + */ + +#ifndef IF_RTWN_BEACON_H +#define IF_RTWN_BEACON_H + +void rtwn_switch_bcnq(struct rtwn_softc *, int); +int rtwn_setup_beacon(struct rtwn_softc *, struct ieee80211_node *); +void rtwn_update_beacon(struct ieee80211vap *, int); +void rtwn_tx_beacon_csa(void *arg, int); +int rtwn_tx_beacon_check(struct rtwn_softc *, struct rtwn_vap *); + +#endif /* IF_RTWN_BEACON_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.c new file mode 100644 index 0000000000..966e63ac40 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.c @@ -0,0 +1,128 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_calib.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +static void +rtwn_temp_calib(struct rtwn_softc *sc) +{ + uint8_t temp; + + RTWN_ASSERT_LOCKED(sc); + + if (!(sc->sc_flags & RTWN_TEMP_MEASURED)) { + /* Start measuring temperature. */ + RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP, + "%s: start measuring temperature\n", __func__); + rtwn_temp_measure(sc); + sc->sc_flags |= RTWN_TEMP_MEASURED; + return; + } + sc->sc_flags &= ~RTWN_TEMP_MEASURED; + + /* Read measured temperature. */ + temp = rtwn_temp_read(sc); + if (temp == 0) { /* Read failed, skip. */ + RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP, + "%s: temperature read failed, skipping\n", __func__); + return; + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP, + "temperature: previous %u, current %u\n", + sc->thcal_temp, temp); + + /* + * Redo LC/IQ calibration if temperature changed significantly since + * last calibration. + */ + if (sc->thcal_temp == 0xff) { + /* efuse value is absent; do LCK at initial status. */ + rtwn_lc_calib(sc); + + sc->thcal_temp = temp; + } else if (abs(temp - sc->thcal_temp) > sc->temp_delta) { + RTWN_DPRINTF(sc, RTWN_DEBUG_TEMP, + "%s: LC/IQ calib triggered by temp: %u -> %u\n", + __func__, sc->thcal_temp, temp); + + rtwn_lc_calib(sc); + rtwn_iq_calib(sc); + + /* Record temperature of last calibration. */ + sc->thcal_temp = temp; + } +} + +static void +rtwn_calib_cb(struct rtwn_softc *sc, union sec_param *data) +{ + /* Do temperature compensation. */ + rtwn_temp_calib(sc); + +#ifndef RTWN_WITHOUT_UCODE + if (sc->sc_ratectl == RTWN_RATECTL_FW) { + /* Refresh per-node RSSI. */ + rtwn_set_rssi(sc); + } +#endif + + if (sc->vaps_running > sc->monvaps_running) + callout_reset(&sc->sc_calib_to, 2*hz, rtwn_calib_to, sc); +} + +void +rtwn_calib_to(void *arg) +{ + struct rtwn_softc *sc = arg; + + /* Do it in a process context. */ + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_calib_cb); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.h new file mode 100644 index 0000000000..f0d20c1368 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_calib.h @@ -0,0 +1,24 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_calib.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_CALIB_H +#define IF_RTWN_CALIB_H + +void rtwn_calib_to(void *); + +#endif /* IF_RTWN_CALIB_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.c new file mode 100644 index 0000000000..11f4651227 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.c @@ -0,0 +1,364 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_cam.c 309686 2016-12-07 22:16:07Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + + +void +rtwn_init_cam(struct rtwn_softc *sc) +{ + /* Invalidate all CAM entries. */ + rtwn_write_4(sc, R92C_CAMCMD, + R92C_CAMCMD_POLLING | R92C_CAMCMD_CLR); +} + +static int +rtwn_cam_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) +{ + int error; + + error = rtwn_write_4(sc, R92C_CAMWRITE, data); + if (error != 0) + return (error); + error = rtwn_write_4(sc, R92C_CAMCMD, + R92C_CAMCMD_POLLING | R92C_CAMCMD_WRITE | + SM(R92C_CAMCMD_ADDR, addr)); + + return (error); +} + +void +rtwn_init_seccfg(struct rtwn_softc *sc) +{ + uint16_t seccfg; + + /* Select decryption / encryption flags. */ + seccfg = 0; + switch (sc->sc_hwcrypto) { + case RTWN_CRYPTO_SW: + break; /* nothing to do */ + case RTWN_CRYPTO_PAIR: + /* NB: TXUCKEY_DEF / RXUCKEY_DEF are required for RTL8192C */ + seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | + R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | + R92C_SECCFG_MC_SRCH_DIS; + break; + case RTWN_CRYPTO_FULL: + seccfg = R92C_SECCFG_TXUCKEY_DEF | R92C_SECCFG_RXUCKEY_DEF | + R92C_SECCFG_TXENC_ENA | R92C_SECCFG_RXDEC_ENA | + R92C_SECCFG_TXBCKEY_DEF | R92C_SECCFG_RXBCKEY_DEF; + break; + default: + KASSERT(0, ("%s: case %d was not handled\n", __func__, + sc->sc_hwcrypto)); + break; + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, "%s: seccfg %04X, hwcrypto %d\n", + __func__, seccfg, sc->sc_hwcrypto); + + rtwn_write_2(sc, R92C_SECCFG, seccfg); +} + +int +rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k, + ieee80211_keyix *keyix, ieee80211_keyix *rxkeyix) +{ + struct rtwn_softc *sc = vap->iv_ic->ic_softc; + int i, start; + + if (&vap->iv_nw_keys[0] <= k && + k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { +#if __FreeBSD_version > 1200018 + *keyix = ieee80211_crypto_get_key_wepidx(vap, k); +#else + *keyix = k - vap->iv_nw_keys; +#endif + if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) + k->wk_flags |= IEEE80211_KEY_SWCRYPT; + else { + RTWN_LOCK(sc); + if (isset(sc->keys_bmap, *keyix)) { + device_printf(sc->sc_dev, + "%s: group key slot %d is already used!\n", + __func__, *keyix); + /* XXX recover? */ + RTWN_UNLOCK(sc); + return (0); + } + + setbit(sc->keys_bmap, *keyix); + RTWN_UNLOCK(sc); + } + + goto end; + } + + start = sc->cam_entry_limit; + switch (sc->sc_hwcrypto) { + case RTWN_CRYPTO_SW: + k->wk_flags |= IEEE80211_KEY_SWCRYPT; + *keyix = 0; + goto end; + case RTWN_CRYPTO_PAIR: + /* all slots for pairwise keys. */ + start = 0; + RTWN_LOCK(sc); + if (sc->sc_flags & RTWN_FLAG_CAM_FIXED) + start = 4; + RTWN_UNLOCK(sc); + break; + case RTWN_CRYPTO_FULL: + /* first 4 - for group keys, others for pairwise. */ + start = 4; + break; + default: + KASSERT(0, ("%s: case %d was not handled!\n", + __func__, sc->sc_hwcrypto)); + break; + } + + RTWN_LOCK(sc); + for (i = start; i < sc->cam_entry_limit; i++) { + if (isclr(sc->keys_bmap, i)) { + setbit(sc->keys_bmap, i); + *keyix = i; + break; + } + } + RTWN_UNLOCK(sc); + if (i == sc->cam_entry_limit) { +#if __FreeBSD_version > 1200008 + /* XXX check and remove keys with the same MAC address */ + k->wk_flags |= IEEE80211_KEY_SWCRYPT; + *keyix = 0; +#else + device_printf(sc->sc_dev, + "%s: no free space in the key table\n", __func__); + return (0); +#endif + } + +end: + *rxkeyix = *keyix; + return (1); +} + +static int +rtwn_key_set_cb0(struct rtwn_softc *sc, const struct ieee80211_key *k) +{ + uint8_t algo, keyid; + int i, error; + + if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL && + k->wk_keyix < IEEE80211_WEP_NKID) + keyid = k->wk_keyix; + else + keyid = 0; + + /* Map net80211 cipher to HW crypto algorithm. */ + switch (k->wk_cipher->ic_cipher) { + case IEEE80211_CIPHER_WEP: + if (k->wk_keylen < 8) + algo = R92C_CAM_ALGO_WEP40; + else + algo = R92C_CAM_ALGO_WEP104; + break; + case IEEE80211_CIPHER_TKIP: + algo = R92C_CAM_ALGO_TKIP; + break; + case IEEE80211_CIPHER_AES_CCM: + algo = R92C_CAM_ALGO_AES; + break; + default: + device_printf(sc->sc_dev, "%s: unknown cipher %u\n", + __func__, k->wk_cipher->ic_cipher); + return (EINVAL); + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, + "%s: keyix %u, keyid %u, algo %u/%u, flags %04X, len %u, " + "macaddr %s\n", __func__, k->wk_keyix, keyid, + k->wk_cipher->ic_cipher, algo, k->wk_flags, k->wk_keylen, + ether_sprintf(k->wk_macaddr)); + + /* Clear high bits. */ + rtwn_cam_write(sc, R92C_CAM_CTL6(k->wk_keyix), 0); + rtwn_cam_write(sc, R92C_CAM_CTL7(k->wk_keyix), 0); + + /* Write key. */ + for (i = 0; i < 4; i++) { + error = rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), + le32dec(&k->wk_key[i * 4])); + if (error != 0) + goto fail; + } + + /* Write CTL0 last since that will validate the CAM entry. */ + error = rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), + le32dec(&k->wk_macaddr[2])); + if (error != 0) + goto fail; + error = rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), + SM(R92C_CAM_ALGO, algo) | + SM(R92C_CAM_KEYID, keyid) | + SM(R92C_CAM_MACLO, le16dec(&k->wk_macaddr[0])) | + R92C_CAM_VALID); + if (error != 0) + goto fail; + + return (0); + +fail: + device_printf(sc->sc_dev, "%s fails, error %d\n", __func__, error); + return (error); +} + +static void +rtwn_key_set_cb(struct rtwn_softc *sc, union sec_param *data) +{ + const struct ieee80211_key *k = &data->key; + + (void) rtwn_key_set_cb0(sc, k); +} + +int +rtwn_init_static_keys(struct rtwn_softc *sc, struct rtwn_vap *rvp) +{ + int i, error; + + if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) + return (0); /* nothing to do */ + + for (i = 0; i < IEEE80211_WEP_NKID; i++) { + const struct ieee80211_key *k = rvp->keys[i]; + if (k != NULL) { + error = rtwn_key_set_cb0(sc, k); + if (error != 0) + return (error); + } + } + + return (0); +} + +static void +rtwn_key_del_cb(struct rtwn_softc *sc, union sec_param *data) +{ + struct ieee80211_key *k = &data->key; + int i; + + RTWN_DPRINTF(sc, RTWN_DEBUG_KEY, + "%s: keyix %u, flags %04X, macaddr %s\n", __func__, + k->wk_keyix, k->wk_flags, ether_sprintf(k->wk_macaddr)); + + rtwn_cam_write(sc, R92C_CAM_CTL0(k->wk_keyix), 0); + rtwn_cam_write(sc, R92C_CAM_CTL1(k->wk_keyix), 0); + + /* Clear key. */ + for (i = 0; i < 4; i++) + rtwn_cam_write(sc, R92C_CAM_KEY(k->wk_keyix, i), 0); + clrbit(sc->keys_bmap, k->wk_keyix); +} + +static int +rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k, + int set) +{ + struct rtwn_softc *sc = vap->iv_ic->ic_softc; + + if (k->wk_flags & IEEE80211_KEY_SWCRYPT) { + /* Not for us. */ + return (1); + } + + if (&vap->iv_nw_keys[0] <= k && + k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) { +#if __FreeBSD_version <= 1200008 + struct ieee80211_key *k1 = &vap->iv_nw_keys[k->wk_keyix]; + + if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL) { + k1->wk_flags |= IEEE80211_KEY_SWCRYPT; + return (k->wk_cipher->ic_setkey(k1)); + } else { +#else + if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) { +#endif + struct rtwn_vap *rvp = RTWN_VAP(vap); + + RTWN_LOCK(sc); + rvp->keys[k->wk_keyix] = (set ? k : NULL); + if ((sc->sc_flags & RTWN_RUNNING) == 0) { + if (!set) + clrbit(sc->keys_bmap, k->wk_keyix); + RTWN_UNLOCK(sc); + return (1); + } + RTWN_UNLOCK(sc); + } + } + + return (!rtwn_cmd_sleepable(sc, k, sizeof(*k), + set ? rtwn_key_set_cb : rtwn_key_del_cb)); +} + +int +rtwn_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) +{ + return (rtwn_process_key(vap, k, 1)); +} + +int +rtwn_key_delete(struct ieee80211vap *vap, const struct ieee80211_key *k) +{ + return (rtwn_process_key(vap, k, 0)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.h new file mode 100644 index 0000000000..af07bf7c22 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_cam.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_cam.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_CAM_H +#define IF_RTWN_CAM_H + +void rtwn_init_cam(struct rtwn_softc *); +void rtwn_init_seccfg(struct rtwn_softc *); +int rtwn_key_alloc(struct ieee80211vap *, struct ieee80211_key *, + ieee80211_keyix *, ieee80211_keyix *); +int rtwn_key_set(struct ieee80211vap *, const struct ieee80211_key *); +int rtwn_init_static_keys(struct rtwn_softc *, struct rtwn_vap *); +int rtwn_key_delete(struct ieee80211vap *, const struct ieee80211_key *); + +#endif /* IF_RTWN_CAM_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_debug.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_debug.h new file mode 100644 index 0000000000..98f60f6fbc --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_debug.h @@ -0,0 +1,58 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_debug.h 310867 2016-12-30 22:24:01Z avos $ + */ + +#ifndef IF_RTWN_DEBUG_H +#define IF_RTWN_DEBUG_H + +#ifdef RTWN_DEBUG +enum { + RTWN_DEBUG_XMIT = 0x00000001, /* basic xmit operation */ + RTWN_DEBUG_XMIT_DESC = 0x00000002, /* xmit descriptors */ + RTWN_DEBUG_RECV = 0x00000004, /* basic recv operation */ + RTWN_DEBUG_RECV_DESC = 0x00000008, /* recv descriptors */ + RTWN_DEBUG_STATE = 0x00000010, /* 802.11 state transitions */ + RTWN_DEBUG_RA = 0x00000020, /* f/w rate adaptation setup */ + RTWN_DEBUG_USB = 0x00000040, /* usb requests */ + RTWN_DEBUG_FIRMWARE = 0x00000080, /* firmware(9) loading debug */ + RTWN_DEBUG_BEACON = 0x00000100, /* beacon handling */ + RTWN_DEBUG_INTR = 0x00000200, /* ISR */ + RTWN_DEBUG_TEMP = 0x00000400, /* temperature calibration */ + RTWN_DEBUG_ROM = 0x00000800, /* various ROM info */ + RTWN_DEBUG_KEY = 0x00001000, /* crypto keys management */ + RTWN_DEBUG_TXPWR = 0x00002000, /* dump Tx power values */ + RTWN_DEBUG_RSSI = 0x00004000, /* dump RSSI lookups */ + RTWN_DEBUG_RESET = 0x00008000, /* initialization progress */ + RTWN_DEBUG_CALIB = 0x00010000, /* calibration progress */ + RTWN_DEBUG_RADAR = 0x00020000, /* radar detection status */ + RTWN_DEBUG_ANY = 0xffffffff +}; + +#define RTWN_DPRINTF(_sc, _m, ...) do { \ + if ((_sc)->sc_debug & (_m)) \ + device_printf((_sc)->sc_dev, __VA_ARGS__); \ +} while(0) + +#else +#define RTWN_DPRINTF(_sc, _m, ...) do { (void) _sc; } while (0) +#endif + +#endif /* IF_RTWN_DEBUG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.c new file mode 100644 index 0000000000..039b932bb3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.c @@ -0,0 +1,265 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_efuse.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + + +static int +rtwn_efuse_switch_power(struct rtwn_softc *sc) +{ + uint32_t reg; + int error; + + error = rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_ON); + if (error != 0) + return (error); + + reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); + if (!(reg & R92C_SYS_FUNC_EN_ELDR)) { + error = rtwn_write_2(sc, R92C_SYS_FUNC_EN, + reg | R92C_SYS_FUNC_EN_ELDR); + if (error != 0) + return (error); + } + reg = rtwn_read_2(sc, R92C_SYS_CLKR); + if ((reg & (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) != + (R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M)) { + error = rtwn_write_2(sc, R92C_SYS_CLKR, + reg | R92C_SYS_CLKR_LOADER_EN | R92C_SYS_CLKR_ANA8M); + if (error != 0) + return (error); + } + + return (0); +} + +int +rtwn_efuse_read_next(struct rtwn_softc *sc, uint8_t *val) +{ + uint32_t reg; + int ntries, error; + + if (sc->next_rom_addr >= sc->efuse_maxlen) + return (EFAULT); + + reg = rtwn_read_4(sc, R92C_EFUSE_CTRL); + reg = RW(reg, R92C_EFUSE_CTRL_ADDR, sc->next_rom_addr); + reg &= ~R92C_EFUSE_CTRL_VALID; + + error = rtwn_write_4(sc, R92C_EFUSE_CTRL, reg); + if (error != 0) + return (error); + /* Wait for read operation to complete. */ + for (ntries = 0; ntries < 100; ntries++) { + reg = rtwn_read_4(sc, R92C_EFUSE_CTRL); + if (reg & R92C_EFUSE_CTRL_VALID) + break; + rtwn_delay(sc, 10); + } + if (ntries == 100) { + device_printf(sc->sc_dev, + "could not read efuse byte at address 0x%x\n", + sc->next_rom_addr); + return (ETIMEDOUT); + } + + *val = MS(reg, R92C_EFUSE_CTRL_DATA); + sc->next_rom_addr++; + + return (0); +} + +static int +rtwn_efuse_read_data(struct rtwn_softc *sc, uint8_t *rom, uint8_t off, + uint8_t msk) +{ + uint8_t reg; + int addr, i, error; + + for (i = 0; i < 4; i++) { + if (msk & (1 << i)) + continue; + + addr = off * 8 + i * 2; + if (addr + 1 >= sc->efuse_maplen) + return (EFAULT); + + error = rtwn_efuse_read_next(sc, ®); + if (error != 0) + return (error); + RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n", + addr, reg); + rom[addr] = reg; + + error = rtwn_efuse_read_next(sc, ®); + if (error != 0) + return (error); + RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "rom[0x%03X] == 0x%02X\n", + addr + 1, reg); + rom[addr + 1] = reg; + } + + return (0); +} + +#ifdef RTWN_DEBUG +static void +rtwn_dump_rom_contents(struct rtwn_softc *sc, uint8_t *rom, uint16_t size) +{ + int i; + + /* Dump ROM contents. */ + device_printf(sc->sc_dev, "%s:", __func__); + for (i = 0; i < size; i++) { + if (i % 32 == 0) + printf("\n%03X: ", i); + else if (i % 4 == 0) + printf(" "); + + printf("%02X", rom[i]); + } + printf("\n"); +} +#endif + +static int +rtwn_efuse_read(struct rtwn_softc *sc, uint8_t *rom, uint16_t size) +{ +#define RTWN_CHK(res) do { \ + if ((error = res) != 0) \ + goto end; \ +} while(0) + uint8_t msk, off, reg; + int error; + + /* Read full ROM image. */ + sc->next_rom_addr = 0; + memset(rom, 0xff, size); + + RTWN_CHK(rtwn_efuse_read_next(sc, ®)); + while (reg != 0xff) { + /* check for extended header */ + if ((sc->sc_flags & RTWN_FLAG_EXT_HDR) && + (reg & 0x1f) == 0x0f) { + off = reg >> 5; + RTWN_CHK(rtwn_efuse_read_next(sc, ®)); + + if ((reg & 0x0f) != 0x0f) + off = ((reg & 0xf0) >> 1) | off; + else + continue; + } else + off = reg >> 4; + msk = reg & 0xf; + + RTWN_CHK(rtwn_efuse_read_data(sc, rom, off, msk)); + RTWN_CHK(rtwn_efuse_read_next(sc, ®)); + } + +end: + +#ifdef RTWN_DEBUG + if (sc->sc_debug & RTWN_DEBUG_ROM) + rtwn_dump_rom_contents(sc, rom, size); +#endif + + /* Device-specific. */ + rtwn_efuse_postread(sc); + + if (error != 0) { + device_printf(sc->sc_dev, "%s: error while reading ROM\n", + __func__); + } + + return (error); +#undef RTWN_CHK +} + +static int +rtwn_efuse_read_prepare(struct rtwn_softc *sc, uint8_t *rom, uint16_t size) +{ + int error; + + error = rtwn_efuse_switch_power(sc); + if (error != 0) + goto fail; + + error = rtwn_efuse_read(sc, rom, size); + +fail: + rtwn_write_1(sc, R92C_EFUSE_ACCESS, R92C_EFUSE_ACCESS_OFF); + + return (error); +} + +int +rtwn_read_rom(struct rtwn_softc *sc) +{ + uint8_t *rom; + int error; + + rom = malloc(sc->efuse_maplen, M_TEMP, M_WAITOK); + + /* Read full ROM image. */ + RTWN_LOCK(sc); + error = rtwn_efuse_read_prepare(sc, rom, sc->efuse_maplen); + RTWN_UNLOCK(sc); + if (error != 0) + goto fail; + + /* Parse & save data in softc. */ + rtwn_parse_rom(sc, rom); + +fail: + free(rom, M_TEMP); + + return (error); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.h new file mode 100644 index 0000000000..32f0f217cc --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_efuse.h @@ -0,0 +1,25 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_efuse.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_EFUSE_H +#define IF_RTWN_EFUSE_H + +int rtwn_efuse_read_next(struct rtwn_softc *, uint8_t *); +int rtwn_read_rom(struct rtwn_softc *); + +#endif /* IF_RTWN_EFUSE_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.c new file mode 100644 index 0000000000..036b10af7e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.c @@ -0,0 +1,224 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_fw.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + + +#ifndef RTWN_WITHOUT_UCODE +static int +rtwn_fw_loadpage(struct rtwn_softc *sc, int page, const uint8_t *buf, + int len) +{ + uint32_t reg; + uint16_t off; + int mlen, error; + + reg = rtwn_read_4(sc, R92C_MCUFWDL); + reg = RW(reg, R92C_MCUFWDL_PAGE, page); + rtwn_write_4(sc, R92C_MCUFWDL, reg); + + error = 0; + off = R92C_FW_START_ADDR; + while (len > 0) { + if (len > R92C_FW_MAX_BLOCK_SIZE) + mlen = R92C_FW_MAX_BLOCK_SIZE; + else if (len > 4) + mlen = 4; + else + mlen = 1; + error = rtwn_fw_write_block(sc, buf, off, mlen); + if (error != 0) + break; + off += mlen; + buf += mlen; + len -= mlen; + } + + if (error != 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, + "%s: could not load firmware page %d (offset %u)\n", + __func__, page, off); + } + + return (error); +} + +static int +rtwn_fw_checksum_report(struct rtwn_softc *sc) +{ + int ntries; + + for (ntries = 0; ntries < 25; ntries++) { + if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_CHKSUM_RPT) + break; + rtwn_delay(sc, 10000); + } + if (ntries == 25) { + RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, + "timeout waiting for checksum report\n"); + return (ETIMEDOUT); + } + + return (0); +} + +int +rtwn_load_firmware(struct rtwn_softc *sc) +{ + const struct firmware *fw; + const struct r92c_fw_hdr *hdr; + const u_char *ptr; + size_t len; + int ntries, error; + + /* Read firmware image from the filesystem. */ + RTWN_UNLOCK(sc); + fw = firmware_get(sc->fwname); + RTWN_LOCK(sc); + if (fw == NULL) { + device_printf(sc->sc_dev, + "failed loadfirmware of file %s\n", sc->fwname); + return (ENOENT); + } + + len = fw->datasize; + if (len < sizeof(*hdr) || len > sc->fwsize_limit) { + device_printf(sc->sc_dev, "wrong firmware size (%zu)\n", len); + error = EINVAL; + goto fail; + } + ptr = fw->data; + hdr = (const struct r92c_fw_hdr *)ptr; + /* Check if there is a valid FW header and skip it. */ + if ((le16toh(hdr->signature) >> 4) == sc->fwsig) { + sc->fwver = le16toh(hdr->version); + + RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, + "FW V%u.%u %02u-%02u %02u:%02u\n", + le16toh(hdr->version), le16toh(hdr->subversion), + hdr->month, hdr->date, hdr->hour, hdr->minute); + ptr += sizeof(*hdr); + len -= sizeof(*hdr); + } + + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) { + rtwn_write_1(sc, R92C_MCUFWDL, 0); + rtwn_fw_reset(sc, RTWN_FW_RESET_DOWNLOAD); + } + + /* Enable firmware download. */ + rtwn_fw_download_enable(sc, 1); + + error = 0; /* compiler warning */ + for (ntries = 0; ntries < 3; ntries++) { + const u_char *curr_ptr = ptr; + const int maxpages = len / R92C_FW_PAGE_SIZE; + int page; + + /* Reset the FWDL checksum. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_CHKSUM_RPT); + + for (page = 0; page < maxpages; page++) { + error = rtwn_fw_loadpage(sc, page, curr_ptr, + R92C_FW_PAGE_SIZE); + if (error != 0) + break; + curr_ptr += R92C_FW_PAGE_SIZE; + } + if (page != maxpages) + continue; + + if (len % R92C_FW_PAGE_SIZE != 0) { + error = rtwn_fw_loadpage(sc, page, curr_ptr, + len % R92C_FW_PAGE_SIZE); + if (error != 0) + continue; + } + + /* Wait for checksum report. */ + error = rtwn_fw_checksum_report(sc); + if (error == 0) + break; + } + if (ntries == 3) { + device_printf(sc->sc_dev, + "%s: failed to upload firmware %s (error %d)\n", + __func__, sc->fwname, error); + goto fail; + } + + /* Disable firmware download. */ + rtwn_fw_download_enable(sc, 0); + + rtwn_setbits_4(sc, R92C_MCUFWDL, R92C_MCUFWDL_WINTINI_RDY, + R92C_MCUFWDL_RDY); + + rtwn_fw_reset(sc, RTWN_FW_RESET_CHECKSUM); + + /* Wait for firmware readiness. */ + for (ntries = 0; ntries < 20; ntries++) { + if (rtwn_read_4(sc, R92C_MCUFWDL) & R92C_MCUFWDL_WINTINI_RDY) + break; + rtwn_delay(sc, 10000); + } + if (ntries == 20) { + device_printf(sc->sc_dev, + "timeout waiting for firmware readiness\n"); + error = ETIMEDOUT; + goto fail; + } +fail: + firmware_put(fw, FIRMWARE_UNLOAD); + return (error); +} +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.h new file mode 100644 index 0000000000..0053cd8115 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_fw.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_fw.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_FW_H +#define IF_RTWN_FW_H + +/* + * Firmware base address. + */ +#define R92C_FW_START_ADDR 0x1000 +#define R92C_FW_PAGE_SIZE 4096 +#define R92C_FW_MAX_BLOCK_SIZE 196 + +/* + * Firmware image header. + */ +struct r92c_fw_hdr { + /* QWORD0 */ + uint16_t signature; + uint8_t category; + uint8_t function; + uint16_t version; + uint16_t subversion; + /* QWORD1 */ + uint8_t month; + uint8_t date; + uint8_t hour; + uint8_t minute; + uint16_t ramcodesize; + uint16_t reserved2; + /* QWORD2 */ + uint32_t svnidx; + uint32_t reserved3; + /* QWORD3 */ + uint32_t reserved4; + uint32_t reserved5; +} __packed; + + +int rtwn_load_firmware(struct rtwn_softc *); + +#endif /* IF_RTWN_FW_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_nop.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_nop.h new file mode 100644 index 0000000000..342ab70eb6 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_nop.h @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_nop.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_NOP_H +#define IF_RTWN_NOP_H + +static __inline void +rtwn_nop_softc(struct rtwn_softc *sc) +{ +} + +static __inline int +rtwn_nop_int_softc(struct rtwn_softc *sc) +{ + return (0); +} + +static __inline int +rtwn_nop_int_softc_mbuf(struct rtwn_softc *sc, struct mbuf *m) +{ + return (0); +} + +static __inline void +rtwn_nop_softc_int(struct rtwn_softc *sc, int id) +{ +} + +static __inline void +rtwn_nop_softc_uint32(struct rtwn_softc *sc, uint32_t reg) +{ +} + +static __inline void +rtwn_nop_softc_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ +} + +static __inline void +rtwn_nop_softc_vap(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ +} + +static __inline void +rtwn_nop_softc_uint8_int(struct rtwn_softc *sc, uint8_t *buf, int len) +{ +} + +static __inline void +rtwn_nop_void_int(void *buf, int is5ghz) +{ +} + +#endif /* IF_RTWN_NOP_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_ridx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_ridx.h new file mode 100644 index 0000000000..824feb34b2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_ridx.h @@ -0,0 +1,95 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_ridx.h 331043 2018-03-16 01:03:10Z avos $ + */ + +#ifndef IF_RTWN_RIDX_H +#define IF_RTWN_RIDX_H + +/* HW rate indices. */ +#define RTWN_RIDX_CCK1 0 +#define RTWN_RIDX_CCK2 1 +#define RTWN_RIDX_CCK55 2 +#define RTWN_RIDX_CCK11 3 +#define RTWN_RIDX_OFDM6 4 +#define RTWN_RIDX_OFDM9 5 +#define RTWN_RIDX_OFDM12 6 +#define RTWN_RIDX_OFDM18 7 +#define RTWN_RIDX_OFDM24 8 +#define RTWN_RIDX_OFDM36 9 +#define RTWN_RIDX_OFDM48 10 +#define RTWN_RIDX_OFDM54 11 + +#define RTWN_RIDX_HT_MCS_SHIFT 12 +#define RTWN_RIDX_HT_MCS(i) (RTWN_RIDX_HT_MCS_SHIFT + (i)) + +#define RTWN_RIDX_COUNT 28 +#define RTWN_RIDX_UNKNOWN (uint8_t)-1 + +#define RTWN_RATE_IS_CCK(rate) ((rate) <= RTWN_RIDX_CCK11) +#define RTWN_RATE_IS_OFDM(rate) \ + ((rate) >= RTWN_RIDX_OFDM6 && (rate) != RTWN_RIDX_UNKNOWN) + + +static const uint8_t ridx2rate[] = + { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; + +static __inline uint8_t +rate2ridx(uint8_t rate) +{ + if (rate & IEEE80211_RATE_MCS) { + return ((rate & 0xf) + RTWN_RIDX_HT_MCS_SHIFT); + } + switch (rate) { + /* 11g */ + case 12: return 4; + case 18: return 5; + case 24: return 6; + case 36: return 7; + case 48: return 8; + case 72: return 9; + case 96: return 10; + case 108: return 11; + /* 11b */ + case 2: return 0; + case 4: return 1; + case 11: return 2; + case 22: return 3; + default: return RTWN_RIDX_UNKNOWN; + } +} + +/* XXX move to net80211 */ +static __inline__ uint8_t +rtwn_ctl_mcsrate(const struct ieee80211_rate_table *rt, uint8_t ridx) +{ + uint8_t cix, rate; + + /* Check if we are using MCS rate. */ + KASSERT(ridx >= RTWN_RIDX_HT_MCS(0) && ridx != RTWN_RIDX_UNKNOWN, + ("bad mcs rate index %d", ridx)); + + rate = (ridx - RTWN_RIDX_HT_MCS(0)) | IEEE80211_RATE_MCS; + cix = rt->info[rt->rateCodeToIndex[rate]].ctlRateIndex; + KASSERT(cix != (uint8_t)-1, ("rate %d (%d) has no info", rate, ridx)); + return rt->info[cix].dot11Rate; +} + +#endif /* IF_RTWN_RIDX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.c new file mode 100644 index 0000000000..cade5bd2e3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.c @@ -0,0 +1,517 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_rx.c 333813 2018-05-18 20:13:34Z mmacy $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + + +void +rtwn_get_rates(struct rtwn_softc *sc, const struct ieee80211_rateset *rs, + const struct ieee80211_htrateset *rs_ht, uint32_t *rates_p, + int *maxrate_p, int basic_rates) +{ + uint32_t rates; + uint8_t ridx; + int i, maxrate; + + /* Get rates mask. */ + rates = 0; + maxrate = 0; + + /* This is for 11bg */ + for (i = 0; i < rs->rs_nrates; i++) { + /* Convert 802.11 rate to HW rate index. */ + ridx = rate2ridx(IEEE80211_RV(rs->rs_rates[i])); + if (ridx == RTWN_RIDX_UNKNOWN) /* Unknown rate, skip. */ + continue; + if (((rs->rs_rates[i] & IEEE80211_RATE_BASIC) != 0) || + !basic_rates) { + rates |= 1 << ridx; + if (ridx > maxrate) + maxrate = ridx; + } + } + + /* If we're doing 11n, enable 11n rates */ + if (rs_ht != NULL && !basic_rates) { + for (i = 0; i < rs_ht->rs_nrates; i++) { + if ((rs_ht->rs_rates[i] & 0x7f) > 0xf) + continue; + /* 11n rates start at index 12 */ + ridx = RTWN_RIDX_HT_MCS((rs_ht->rs_rates[i]) & 0xf); + rates |= (1 << ridx); + + /* Guard against the rate table being oddly ordered */ + if (ridx > maxrate) + maxrate = ridx; + } + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_RA, + "%s: rates 0x%08X, maxrate %d\n", __func__, rates, maxrate); + + if (rates_p != NULL) + *rates_p = rates; + if (maxrate_p != NULL) + *maxrate_p = maxrate; +} + +void +rtwn_set_basicrates(struct rtwn_softc *sc, uint32_t rates) +{ + + RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: rates 0x%08X\n", __func__, rates); + + rtwn_setbits_4(sc, R92C_RRSR, R92C_RRSR_RATE_BITMAP_M, rates); +} + +static void +rtwn_update_avgrssi(struct rtwn_softc *sc, struct rtwn_node *un, int8_t rssi, + int is_cck) +{ + int pwdb; + + /* Convert antenna signal to percentage. */ + if (rssi <= -100 || rssi >= 20) + pwdb = 0; + else if (rssi >= 0) + pwdb = 100; + else + pwdb = 100 + rssi; + if (is_cck) { + /* CCK gain is smaller than OFDM/MCS gain. */ + pwdb += 6; + if (pwdb > 100) + pwdb = 100; + if (pwdb <= 14) + pwdb -= 4; + else if (pwdb <= 26) + pwdb -= 8; + else if (pwdb <= 34) + pwdb -= 6; + else if (pwdb <= 42) + pwdb -= 2; + } + + if (un->avg_pwdb == -1) /* Init. */ + un->avg_pwdb = pwdb; + else if (un->avg_pwdb < pwdb) + un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20) + 1; + else + un->avg_pwdb = ((un->avg_pwdb * 19 + pwdb) / 20); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, + "MACID %d, PWDB %d, EMA %d\n", un->id, pwdb, un->avg_pwdb); +} + +static int8_t +rtwn_get_rssi(struct rtwn_softc *sc, void *physt, int is_cck) +{ + int8_t rssi; + + if (is_cck) + rssi = rtwn_get_rssi_cck(sc, physt); + else /* OFDM/HT. */ + rssi = rtwn_get_rssi_ofdm(sc, physt); + + return (rssi); +} + +static uint32_t +rtwn_get_tsf_low(struct rtwn_softc *sc, int id) +{ + return (rtwn_read_4(sc, R92C_TSFTR(id))); +} + +static uint32_t +rtwn_get_tsf_high(struct rtwn_softc *sc, int id) +{ + return (rtwn_read_4(sc, R92C_TSFTR(id) + 4)); +} + +static void +rtwn_get_tsf(struct rtwn_softc *sc, uint64_t *buf, int id) +{ + /* NB: we cannot read it at once. */ + *buf = rtwn_get_tsf_high(sc, id); + *buf <<= 32; + *buf += rtwn_get_tsf_low(sc, id); +} + +static uint64_t +rtwn_extend_rx_tsf(struct rtwn_softc *sc, + const struct rtwn_rx_stat_common *stat) +{ + uint64_t tsft; + uint32_t rxdw3, tsfl, tsfl_curr; + int id; + + rxdw3 = le32toh(stat->rxdw3); + tsfl = le32toh(stat->tsf_low); + id = MS(rxdw3, RTWN_RXDW3_BSSID01_FIT); + + switch (id) { + case 1: + case 2: + id >>= 1; + tsfl_curr = rtwn_get_tsf_low(sc, id); + break; + default: + { + uint32_t tsfl0, tsfl1; + + tsfl0 = rtwn_get_tsf_low(sc, 0); + tsfl1 = rtwn_get_tsf_low(sc, 1); + + if (abs(tsfl0 - tsfl) < abs(tsfl1 - tsfl)) { + id = 0; + tsfl_curr = tsfl0; + } else { + id = 1; + tsfl_curr = tsfl1; + } + break; + } + } + + tsft = rtwn_get_tsf_high(sc, id); + if (tsfl > tsfl_curr && tsfl > 0xffff0000) + tsft--; + tsft <<= 32; + tsft += tsfl; + + return (tsft); +} + +struct ieee80211_node * +rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_node *ni; + struct ieee80211_frame_min *wh; + struct ieee80211_rx_stats rxs; + struct rtwn_node *un; + struct rtwn_rx_stat_common *stat; + void *physt; + uint32_t rxdw0; + int8_t rssi; + int cipher, infosz, is_cck, pktlen, shift; + + stat = desc; + rxdw0 = le32toh(stat->rxdw0); + + cipher = MS(rxdw0, RTWN_RXDW0_CIPHER); + infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8; + pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); + shift = MS(rxdw0, RTWN_RXDW0_SHIFT); + + wh = (struct ieee80211_frame_min *)(mtodo(m, shift + infosz)); + if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) && + cipher != R92C_CAM_ALGO_NONE) + m->m_flags |= M_WEP; + + if (pktlen >= sizeof(*wh)) { + ni = ieee80211_find_rxnode(ic, wh); + if (ni != NULL && (ni->ni_flags & IEEE80211_NODE_HT)) + m->m_flags |= M_AMPDU; + } else + ni = NULL; + un = RTWN_NODE(ni); + + if (infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST)) + physt = (void *)mtodo(m, shift); + else + physt = (un != NULL) ? &un->last_physt : &sc->last_physt; + + bzero(&rxs, sizeof(rxs)); + rtwn_get_rx_stats(sc, &rxs, desc, physt); + if (rxs.c_pktflags & IEEE80211_RX_F_AMPDU) { + /* Next MPDU will come without PHY info. */ + memcpy(&sc->last_physt, physt, sizeof(sc->last_physt)); + if (un != NULL) + memcpy(&un->last_physt, physt, sizeof(sc->last_physt)); + } + + /* Add some common bits. */ + /* NB: should not happen. */ + if (rxdw0 & RTWN_RXDW0_CRCERR) + rxs.c_pktflags |= IEEE80211_RX_F_FAIL_FCSCRC; + + rxs.r_flags |= IEEE80211_R_TSF_START; /* XXX undocumented */ + rxs.r_flags |= IEEE80211_R_TSF64; + rxs.c_rx_tsf = rtwn_extend_rx_tsf(sc, stat); + + /* Get RSSI from PHY status descriptor. */ + is_cck = (rxs.c_pktflags & IEEE80211_RX_F_CCK) != 0; + rssi = rtwn_get_rssi(sc, physt, is_cck); + + /* XXX TODO: we really need a rate-to-string method */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, "%s: rssi %d, rate %d\n", + __func__, rssi, rxs.c_rate); + if (un != NULL && infosz != 0 && (rxdw0 & RTWN_RXDW0_PHYST)) { + /* Update our average RSSI. */ + rtwn_update_avgrssi(sc, un, rssi, is_cck); + } + + rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI; + rxs.c_nf = RTWN_NOISE_FLOOR; + rxs.c_rssi = rssi - rxs.c_nf; + (void) ieee80211_add_rx_params(m, &rxs); + + if (ieee80211_radiotap_active(ic)) { + struct rtwn_rx_radiotap_header *tap = &sc->sc_rxtap; + + tap->wr_flags = rtwn_rx_radiotap_flags(sc, desc); + tap->wr_tsft = htole64(rxs.c_rx_tsf); + tap->wr_rate = rxs.c_rate; + tap->wr_dbm_antsignal = rssi; + tap->wr_dbm_antnoise = rxs.c_nf; + } + + /* Drop PHY descriptor. */ + m_adj(m, infosz + shift); + + return (ni); +} + +void +rtwn_adhoc_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m, int subtype, + const struct ieee80211_rx_stats *rxs, + int rssi, int nf) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct rtwn_softc *sc = vap->iv_ic->ic_softc; + struct rtwn_vap *uvp = RTWN_VAP(vap); + uint64_t ni_tstamp, curr_tstamp; + + uvp->recv_mgmt(ni, m, subtype, rxs, rssi, nf); + + if (vap->iv_state == IEEE80211_S_RUN && + (subtype == IEEE80211_FC0_SUBTYPE_BEACON || + subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)) { + ni_tstamp = le64toh(ni->ni_tstamp.tsf); + RTWN_LOCK(sc); + rtwn_get_tsf(sc, &curr_tstamp, uvp->id); + RTWN_UNLOCK(sc); + + if (ni_tstamp >= curr_tstamp) + (void) ieee80211_ibss_merge(ni); + } +} + +static uint8_t +rtwn_get_multi_pos(const uint8_t maddr[]) +{ + uint64_t mask = 0x00004d101df481b4; + uint8_t pos = 0x27; /* initial value */ + int i, j; + + for (i = 0; i < IEEE80211_ADDR_LEN; i++) + for (j = (i == 0) ? 1 : 0; j < 8; j++) + if ((maddr[i] >> j) & 1) + pos ^= (mask >> (i * 8 + j - 1)); + + pos &= 0x3f; + + return (pos); +} + +void +rtwn_set_multi(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t mfilt[2]; + + RTWN_ASSERT_LOCKED(sc); + + /* general structure was copied from ath(4). */ + if (ic->ic_allmulti == 0) { + struct ieee80211vap *vap; + struct ifnet *ifp; + struct ifmultiaddr *ifma; + + /* + * Merge multicast addresses to form the hardware filter. + */ + mfilt[0] = mfilt[1] = 0; + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + ifp = vap->iv_ifp; + if_maddr_rlock(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + caddr_t dl; + uint8_t pos; + + dl = LLADDR((struct sockaddr_dl *) + ifma->ifma_addr); + pos = rtwn_get_multi_pos(dl); + + mfilt[pos / 32] |= (1 << (pos % 32)); + } + if_maddr_runlock(ifp); + } + } else + mfilt[0] = mfilt[1] = ~0; + + + rtwn_write_4(sc, R92C_MAR + 0, mfilt[0]); + rtwn_write_4(sc, R92C_MAR + 4, mfilt[1]); + + RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, "%s: MC filter %08x:%08x\n", + __func__, mfilt[0], mfilt[1]); +} + +static void +rtwn_rxfilter_update_mgt(struct rtwn_softc *sc) +{ + uint16_t filter; + + filter = 0x7f7f; + if (sc->bcn_vaps == 0) { /* STA and/or MONITOR mode vaps */ + filter &= ~( + R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) | + R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) | + R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ)); + } + if (sc->ap_vaps == sc->nvaps - sc->mon_vaps) { /* AP vaps only */ + filter &= ~( + R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_RESP) | + R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_RESP)); + } + rtwn_write_2(sc, R92C_RXFLTMAP0, filter); +} + +void +rtwn_rxfilter_update(struct rtwn_softc *sc) +{ + + RTWN_ASSERT_LOCKED(sc); + + /* Filter for management frames. */ + rtwn_rxfilter_update_mgt(sc); + + /* Update Rx filter. */ + rtwn_set_promisc(sc); +} + +void +rtwn_rxfilter_init(struct rtwn_softc *sc) +{ + + RTWN_ASSERT_LOCKED(sc); + + /* Setup multicast filter. */ + rtwn_set_multi(sc); + + /* Reject all control frames. */ + rtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000); + + /* Reject all data frames. */ + rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000); + + /* Append generic Rx filter bits. */ + sc->rcr |= R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM | + R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS | + R92C_RCR_APP_ICV | R92C_RCR_APP_MIC; + + /* Update dynamic Rx filter parts. */ + rtwn_rxfilter_update(sc); +} + +void +rtwn_rxfilter_set(struct rtwn_softc *sc) +{ + if (!(sc->sc_flags & RTWN_RCR_LOCKED)) + rtwn_write_4(sc, R92C_RCR, sc->rcr); +} + +void +rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable) +{ + + if (enable) + sc->rcr &= ~R92C_RCR_CBSSID_BCN; + else + sc->rcr |= R92C_RCR_CBSSID_BCN; + rtwn_rxfilter_set(sc); +} + +void +rtwn_set_promisc(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint32_t mask_all, mask_min; + + RTWN_ASSERT_LOCKED(sc); + + mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP; + mask_min = R92C_RCR_APM; + + if (sc->bcn_vaps == 0) + mask_min |= R92C_RCR_CBSSID_BCN; + if (sc->ap_vaps == 0) + mask_min |= R92C_RCR_CBSSID_DATA; + + if (ic->ic_promisc == 0 && sc->mon_vaps == 0) { + if (sc->bcn_vaps != 0) + mask_all |= R92C_RCR_CBSSID_BCN; + if (sc->ap_vaps != 0) /* for Null data frames */ + mask_all |= R92C_RCR_CBSSID_DATA; + + sc->rcr &= ~mask_all; + sc->rcr |= mask_min; + } else { + sc->rcr &= ~mask_min; + sc->rcr |= mask_all; + } + rtwn_rxfilter_set(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.h new file mode 100644 index 0000000000..d027e969ec --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_rx.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_rx.h 312315 2017-01-17 00:35:23Z avos $ + */ + +#ifndef IF_RTWN_RX_H +#define IF_RTWN_RX_H + +#define RTWN_NOISE_FLOOR -95 + + +void rtwn_get_rates(struct rtwn_softc *, const struct ieee80211_rateset *, + const struct ieee80211_htrateset *, uint32_t *, int *, int); +void rtwn_set_basicrates(struct rtwn_softc *, uint32_t); +struct ieee80211_node * rtwn_rx_common(struct rtwn_softc *, struct mbuf *, + void *); +void rtwn_adhoc_recv_mgmt(struct ieee80211_node *, struct mbuf *, int, + const struct ieee80211_rx_stats *, int, int); +void rtwn_set_multi(struct rtwn_softc *); +void rtwn_rxfilter_update(struct rtwn_softc *); +void rtwn_rxfilter_init(struct rtwn_softc *); +void rtwn_rxfilter_set(struct rtwn_softc *); +void rtwn_set_rx_bssid_all(struct rtwn_softc *, int); +void rtwn_set_promisc(struct rtwn_softc *); + +#endif /* IF_RTWN_RX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.c new file mode 100644 index 0000000000..fdda5a533c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.c @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_task.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + + +static void +rtwn_cmdq_cb(void *arg, int pending) +{ + struct rtwn_softc *sc = arg; + struct rtwn_cmdq *item; + + /* + * Device must be powered on (via rtwn_power_on()) + * before any command may be sent. + */ + RTWN_LOCK(sc); + if (!(sc->sc_flags & RTWN_RUNNING)) { + RTWN_UNLOCK(sc); + return; + } + + RTWN_CMDQ_LOCK(sc); + while (sc->cmdq[sc->cmdq_first].func != NULL) { + item = &sc->cmdq[sc->cmdq_first]; + sc->cmdq_first = (sc->cmdq_first + 1) % RTWN_CMDQ_SIZE; + RTWN_CMDQ_UNLOCK(sc); + + item->func(sc, &item->data); + + RTWN_CMDQ_LOCK(sc); + memset(item, 0, sizeof (*item)); + } + RTWN_CMDQ_UNLOCK(sc); + RTWN_UNLOCK(sc); +} + +void +rtwn_cmdq_init(struct rtwn_softc *sc) +{ + RTWN_CMDQ_LOCK_INIT(sc); + TASK_INIT(&sc->cmdq_task, 0, rtwn_cmdq_cb, sc); +} + +void +rtwn_cmdq_destroy(struct rtwn_softc *sc) +{ + if (RTWN_CMDQ_LOCK_INITIALIZED(sc)) + RTWN_CMDQ_LOCK_DESTROY(sc); +} + +int +rtwn_cmd_sleepable(struct rtwn_softc *sc, const void *ptr, size_t len, + CMD_FUNC_PROTO) +{ + struct ieee80211com *ic = &sc->sc_ic; + + KASSERT(len <= sizeof(union sec_param), ("buffer overflow")); + + RTWN_CMDQ_LOCK(sc); + if (sc->sc_detached) { + RTWN_CMDQ_UNLOCK(sc); + return (ESHUTDOWN); + } + + if (sc->cmdq[sc->cmdq_last].func != NULL) { + device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__); + RTWN_CMDQ_UNLOCK(sc); + + return (EAGAIN); + } + + if (ptr != NULL) + memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len); + sc->cmdq[sc->cmdq_last].func = func; + sc->cmdq_last = (sc->cmdq_last + 1) % RTWN_CMDQ_SIZE; + RTWN_CMDQ_UNLOCK(sc); + + ieee80211_runtask(ic, &sc->cmdq_task); + + return (0); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.h new file mode 100644 index 0000000000..fe73111970 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_task.h @@ -0,0 +1,27 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_task.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_TASK_H +#define IF_RTWN_TASK_H + +void rtwn_cmdq_init(struct rtwn_softc *); +void rtwn_cmdq_destroy(struct rtwn_softc *); +int rtwn_cmd_sleepable(struct rtwn_softc *, const void *, size_t, + CMD_FUNC_PROTO); + +#endif /* IF_RTWN_TASK_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.c new file mode 100644 index 0000000000..ab902bd920 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.c @@ -0,0 +1,340 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_tx.c 314315 2017-02-26 20:49:35Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif + +#include +#include + +#include +#include +#include +#include + + +void +rtwn_drain_mbufq(struct rtwn_softc *sc) +{ + struct mbuf *m; + struct ieee80211_node *ni; + RTWN_ASSERT_LOCKED(sc); + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + m->m_pkthdr.rcvif = NULL; + ieee80211_free_node(ni); + m_freem(m); + } +} + +#ifdef IEEE80211_SUPPORT_SUPERG +void +rtwn_ff_flush_all(struct rtwn_softc *sc, union sec_param *data) +{ + struct ieee80211com *ic = &sc->sc_ic; + + RTWN_UNLOCK(sc); + ieee80211_ff_flush_all(ic); + RTWN_LOCK(sc); +} +#endif + +static uint8_t +rtwn_get_cipher(u_int ic_cipher) +{ + uint8_t cipher; + + switch (ic_cipher) { + case IEEE80211_CIPHER_NONE: + cipher = RTWN_TXDW1_CIPHER_NONE; + break; + case IEEE80211_CIPHER_WEP: + case IEEE80211_CIPHER_TKIP: + cipher = RTWN_TXDW1_CIPHER_RC4; + break; + case IEEE80211_CIPHER_AES_CCM: + cipher = RTWN_TXDW1_CIPHER_AES; + break; + default: + KASSERT(0, ("%s: unknown cipher %d\n", __func__, + ic_cipher)); + return (RTWN_TXDW1_CIPHER_SM4); + } + + return (cipher); +} + +static int +rtwn_tx_data(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m) +{ + const struct ieee80211_txparam *tp = ni->ni_txparms; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_key *k = NULL; + struct ieee80211_frame *wh; + struct rtwn_tx_desc_common *txd; + struct rtwn_tx_buf buf; + uint8_t rate, ridx, type; + u_int cipher; + int ismcast; + + RTWN_ASSERT_LOCKED(sc); + + wh = mtod(m, struct ieee80211_frame *); + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + + /* Choose a TX rate index. */ + if (type == IEEE80211_FC0_TYPE_MGT || + type == IEEE80211_FC0_TYPE_CTL || + (m->m_flags & M_EAPOL) != 0) + rate = tp->mgmtrate; + else if (ismcast) + rate = tp->mcastrate; + else if (tp->ucastrate != IEEE80211_FIXED_RATE_NONE) + rate = tp->ucastrate; + else { + if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { + /* XXX pass pktlen */ + (void) ieee80211_ratectl_rate(ni, NULL, 0); + rate = ni->ni_txrate; + } else { + if (ni->ni_flags & IEEE80211_NODE_HT) + rate = IEEE80211_RATE_MCS | 0x4; /* MCS4 */ + else if (ic->ic_curmode != IEEE80211_MODE_11B) + rate = ridx2rate[RTWN_RIDX_OFDM36]; + else + rate = ridx2rate[RTWN_RIDX_CCK55]; + } + } + + ridx = rate2ridx(rate); + + cipher = IEEE80211_CIPHER_NONE; + if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { + k = ieee80211_crypto_encap(ni, m); + if (k == NULL) { + device_printf(sc->sc_dev, + "ieee80211_crypto_encap returns NULL.\n"); + return (ENOBUFS); + } + if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) + cipher = k->wk_cipher->ic_cipher; + + /* in case packet header moved, reset pointer */ + wh = mtod(m, struct ieee80211_frame *); + } + + /* Fill Tx descriptor. */ + txd = (struct rtwn_tx_desc_common *)&buf; + memset(txd, 0, sc->txdesc_len); + txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher))); + + rtwn_fill_tx_desc(sc, ni, m, txd, ridx, tp->maxretry); + + if (ieee80211_radiotap_active_vap(vap)) { + struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; + + tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd); + if (k != NULL) + tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; + ieee80211_radiotap_tx(vap, m); + } + + return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0)); +} + +static int +rtwn_tx_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, const struct ieee80211_bpf_params *params) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_key *k = NULL; + struct ieee80211_frame *wh; + struct rtwn_tx_desc_common *txd; + struct rtwn_tx_buf buf; + uint8_t type; + u_int cipher; + + /* Encrypt the frame if need be. */ + cipher = IEEE80211_CIPHER_NONE; + if (params->ibp_flags & IEEE80211_BPF_CRYPTO) { + /* Retrieve key for TX. */ + k = ieee80211_crypto_encap(ni, m); + if (k == NULL) { + device_printf(sc->sc_dev, + "ieee80211_crypto_encap returns NULL.\n"); + return (ENOBUFS); + } + if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) + cipher = k->wk_cipher->ic_cipher; + } + + wh = mtod(m, struct ieee80211_frame *); + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + + /* Fill Tx descriptor. */ + txd = (struct rtwn_tx_desc_common *)&buf; + memset(txd, 0, sc->txdesc_len); + txd->txdw1 = htole32(SM(RTWN_TXDW1_CIPHER, rtwn_get_cipher(cipher))); + + rtwn_fill_tx_desc_raw(sc, ni, m, txd, params); + + if (ieee80211_radiotap_active_vap(vap)) { + struct rtwn_tx_radiotap_header *tap = &sc->sc_txtap; + + tap->wt_flags = rtwn_tx_radiotap_flags(sc, txd); + if (k != NULL) + tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP; + ieee80211_radiotap_tx(vap, m); + } + + return (rtwn_tx_start(sc, ni, m, (uint8_t *)txd, type, 0)); +} + +int +rtwn_transmit(struct ieee80211com *ic, struct mbuf *m) +{ + struct rtwn_softc *sc = ic->ic_softc; + int error; + + RTWN_LOCK(sc); + if ((sc->sc_flags & RTWN_RUNNING) == 0) { + RTWN_UNLOCK(sc); + return (ENXIO); + } + error = mbufq_enqueue(&sc->sc_snd, m); + if (error) { + RTWN_UNLOCK(sc); + return (error); + } + rtwn_start(sc); + RTWN_UNLOCK(sc); + + return (0); +} + +void +rtwn_start(struct rtwn_softc *sc) +{ + struct ieee80211_node *ni; + struct mbuf *m; + + RTWN_ASSERT_LOCKED(sc); + while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) { + if (sc->qfullmsk != 0) { + mbufq_prepend(&sc->sc_snd, m); + break; + } + ni = (struct ieee80211_node *)m->m_pkthdr.rcvif; + m->m_pkthdr.rcvif = NULL; + + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, + "%s: called; m %p, ni %p\n", __func__, m, ni); + + if (rtwn_tx_data(sc, ni, m) != 0) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); + m_freem(m); +#ifdef D4054 + ieee80211_tx_watchdog_refresh(ni->ni_ic, -1, 0); +#endif + ieee80211_free_node(ni); + break; + } + } +} + +int +rtwn_raw_xmit(struct ieee80211_node *ni, struct mbuf *m, + const struct ieee80211_bpf_params *params) +{ + struct ieee80211com *ic = ni->ni_ic; + struct rtwn_softc *sc = ic->ic_softc; + int error; + + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: called; m %p, ni %p\n", + __func__, m, ni); + + /* prevent management frames from being sent if we're not ready */ + RTWN_LOCK(sc); + if (!(sc->sc_flags & RTWN_RUNNING)) { + error = ENETDOWN; + goto end; + } + + if (sc->qfullmsk != 0) { + error = ENOBUFS; + goto end; + } + + if (params == NULL) { + /* + * Legacy path; interpret frame contents to decide + * precisely how to send the frame. + */ + error = rtwn_tx_data(sc, ni, m); + } else { + /* + * Caller supplied explicit parameters to use in + * sending the frame. + */ + error = rtwn_tx_raw(sc, ni, m, params); + } + +end: + if (error != 0) { + if (m->m_flags & M_TXCB) + ieee80211_process_callback(ni, m, 1); + m_freem(m); + } + + RTWN_UNLOCK(sc); + + return (error); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.h new file mode 100644 index 0000000000..d0ebda5b7e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwn_tx.h @@ -0,0 +1,31 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwn_tx.h 308575 2016-11-12 17:58:37Z avos $ + */ + +#ifndef IF_RTWN_TX_H +#define IF_RTWN_TX_H + +void rtwn_drain_mbufq(struct rtwn_softc *); +#ifdef IEEE80211_SUPPORT_SUPERG +void rtwn_ff_flush_all(struct rtwn_softc *, union sec_param *); +#endif +int rtwn_transmit(struct ieee80211com *, struct mbuf *); +void rtwn_start(struct rtwn_softc *); +int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *, + const struct ieee80211_bpf_params *); + +#endif /* IF_RTWN_TX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnreg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnreg.h index 3287d3b8dc..1673445a70 100644 --- a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnreg.h +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnreg.h @@ -1,8 +1,6 @@ -/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ - /*- * Copyright (c) 2010 Damien Bergamini - * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,884 +14,91 @@ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * - * $FreeBSD: releng/11.1/sys/dev/rtwn/if_rtwnreg.h 300788 2016-05-26 22:43:02Z avos $ + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwnreg.h 321735 2017-07-30 23:35:21Z avos $ */ -#define R92C_MAX_CHAINS 2 - -/* Maximum number of output pipes is 3. */ -#define R92C_MAX_EPOUT 3 - -#define R92C_MAX_TX_PWR 0x3f - -#define R92C_PUBQ_NPAGES 176 -#define R92C_HPQ_NPAGES 41 -#define R92C_LPQ_NPAGES 28 -#define R92C_TXPKTBUF_COUNT 256 -#define R92C_TX_PAGE_COUNT \ - (R92C_PUBQ_NPAGES + R92C_HPQ_NPAGES + R92C_LPQ_NPAGES) -#define R92C_TX_PAGE_BOUNDARY (R92C_TX_PAGE_COUNT + 1) - -#define R92C_H2C_NBOX 4 - -/* USB Requests. */ -#define R92C_REQ_REGS 0x05 - -/* - * MAC registers. - */ -/* System Configuration. */ -#define R92C_SYS_ISO_CTRL 0x000 -#define R92C_SYS_FUNC_EN 0x002 -#define R92C_APS_FSMCO 0x004 -#define R92C_SYS_CLKR 0x008 -#define R92C_AFE_MISC 0x010 -#define R92C_SPS0_CTRL 0x011 -#define R92C_SPS_OCP_CFG 0x018 -#define R92C_RSV_CTRL 0x01c -#define R92C_RF_CTRL 0x01f -#define R92C_LDOA15_CTRL 0x020 -#define R92C_LDOV12D_CTRL 0x021 -#define R92C_LDOHCI12_CTRL 0x022 -#define R92C_LPLDO_CTRL 0x023 -#define R92C_AFE_XTAL_CTRL 0x024 -#define R92C_AFE_PLL_CTRL 0x028 -#define R92C_EFUSE_CTRL 0x030 -#define R92C_EFUSE_TEST 0x034 -#define R92C_PWR_DATA 0x038 -#define R92C_CAL_TIMER 0x03c -#define R92C_ACLK_MON 0x03e -#define R92C_GPIO_MUXCFG 0x040 -#define R92C_GPIO_IO_SEL 0x042 -#define R92C_MAC_PINMUX_CFG 0x043 -#define R92C_GPIO_PIN_CTRL 0x044 -#define R92C_GPIO_INTM 0x048 -#define R92C_LEDCFG0 0x04c -#define R92C_LEDCFG1 0x04d -#define R92C_LEDCFG2 0x04e -#define R92C_LEDCFG3 0x04f -#define R92C_FSIMR 0x050 -#define R92C_FSISR 0x054 -#define R92C_HSIMR 0x058 -#define R92C_HSISR 0x05c -#define R92C_MCUFWDL 0x080 -#define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2) -#define R92C_BIST_SCAN 0x0d0 -#define R92C_BIST_RPT 0x0d4 -#define R92C_BIST_ROM_RPT 0x0d8 -#define R92C_USB_SIE_INTF 0x0e0 -#define R92C_PCIE_MIO_INTF 0x0e4 -#define R92C_PCIE_MIO_INTD 0x0e8 -#define R92C_HPON_FSM 0x0ec -#define R92C_SYS_CFG 0x0f0 -/* MAC General Configuration. */ -#define R92C_CR 0x100 -#define R92C_PBP 0x104 -#define R92C_TRXDMA_CTRL 0x10c -#define R92C_TRXFF_BNDY 0x114 -#define R92C_TRXFF_STATUS 0x118 -#define R92C_RXFF_PTR 0x11c -#define R92C_HIMR 0x120 -#define R92C_HISR 0x124 -#define R92C_HIMRE 0x128 -#define R92C_HISRE 0x12c -#define R92C_CPWM 0x12f -#define R92C_FWIMR 0x130 -#define R92C_FWISR 0x134 -#define R92C_PKTBUF_DBG_CTRL 0x140 -#define R92C_PKTBUF_DBG_DATA_L 0x144 -#define R92C_PKTBUF_DBG_DATA_H 0x148 -#define R92C_TC0_CTRL(i) (0x150 + (i) * 4) -#define R92C_TCUNIT_BASE 0x164 -#define R92C_MBIST_START 0x174 -#define R92C_MBIST_DONE 0x178 -#define R92C_MBIST_FAIL 0x17c -#define R92C_C2HEVT_MSG_NORMAL 0x1a0 -#define R92C_C2HEVT_MSG_TEST 0x1b8 -#define R92C_C2HEVT_CLEAR 0x1bf -#define R92C_MCUTST_1 0x1c0 -#define R92C_FMETHR 0x1c8 -#define R92C_HMETFR 0x1cc -#define R92C_HMEBOX(idx) (0x1d0 + (idx) * 4) -#define R92C_LLT_INIT 0x1e0 -#define R92C_BB_ACCESS_CTRL 0x1e8 -#define R92C_BB_ACCESS_DATA 0x1ec -/* Tx DMA Configuration. */ -#define R92C_RQPN 0x200 -#define R92C_FIFOPAGE 0x204 -#define R92C_TDECTRL 0x208 -#define R92C_TXDMA_OFFSET_CHK 0x20c -#define R92C_TXDMA_STATUS 0x210 -#define R92C_RQPN_NPQ 0x214 -/* Rx DMA Configuration. */ -#define R92C_RXDMA_AGG_PG_TH 0x280 -#define R92C_RXPKT_NUM 0x284 -#define R92C_RXDMA_STATUS 0x288 - -#define R92C_PCIE_CTRL_REG 0x300 -#define R92C_INT_MIG 0x304 -#define R92C_BCNQ_DESA 0x308 -#define R92C_HQ_DESA 0x310 -#define R92C_MGQ_DESA 0x318 -#define R92C_VOQ_DESA 0x320 -#define R92C_VIQ_DESA 0x328 -#define R92C_BEQ_DESA 0x330 -#define R92C_BKQ_DESA 0x338 -#define R92C_RX_DESA 0x340 -#define R92C_DBI 0x348 -#define R92C_MDIO 0x354 -#define R92C_DBG_SEL 0x360 -#define R92C_PCIE_HRPWM 0x361 -#define R92C_PCIE_HCPWM 0x363 -#define R92C_UART_CTRL 0x364 -#define R92C_UART_TX_DES 0x370 -#define R92C_UART_RX_DES 0x378 - -#define R92C_VOQ_INFORMATION 0x0400 -#define R92C_VIQ_INFORMATION 0x0404 -#define R92C_BEQ_INFORMATION 0x0408 -#define R92C_BKQ_INFORMATION 0x040C -#define R92C_MGQ_INFORMATION 0x0410 -#define R92C_HGQ_INFORMATION 0x0414 -#define R92C_BCNQ_INFORMATION 0x0418 -#define R92C_CPU_MGQ_INFORMATION 0x041C - -/* Protocol Configuration. */ -#define R92C_FWHW_TXQ_CTRL 0x420 -#define R92C_HWSEQ_CTRL 0x423 -#define R92C_TXPKTBUF_BCNQ_BDNY 0x424 -#define R92C_TXPKTBUF_MGQ_BDNY 0x425 -#define R92C_SPEC_SIFS 0x428 -#define R92C_RL 0x42a -#define R92C_DARFRC 0x430 -#define R92C_RARFRC 0x438 -#define R92C_RRSR 0x440 -#define R92C_ARFR(i) (0x444 + (i) * 4) -#define R92C_AGGLEN_LMT 0x458 -#define R92C_AMPDU_MIN_SPACE 0x45c -#define R92C_TXPKTBUF_WMAC_LBK_BF_HD 0x45d -#define R92C_FAST_EDCA_CTRL 0x460 -#define R92C_RD_RESP_PKT_TH 0x463 -#define R92C_INIRTS_RATE_SEL 0x480 -#define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid)) -/* EDCA Configuration. */ -#define R92C_EDCA_VO_PARAM 0x500 -#define R92C_EDCA_VI_PARAM 0x504 -#define R92C_EDCA_BE_PARAM 0x508 -#define R92C_EDCA_BK_PARAM 0x50c -#define R92C_BCNTCFG 0x510 -#define R92C_PIFS 0x512 -#define R92C_RDG_PIFS 0x513 -#define R92C_SIFS_CCK 0x514 -#define R92C_SIFS_OFDM 0x516 -#define R92C_AGGR_BREAK_TIME 0x51a -#define R92C_SLOT 0x51b -#define R92C_TX_PTCL_CTRL 0x520 -#define R92C_TXPAUSE 0x522 -#define R92C_DIS_TXREQ_CLR 0x523 -#define R92C_RD_CTRL 0x524 -#define R92C_TBTT_PROHIBIT 0x540 -#define R92C_RD_NAV_NXT 0x544 -#define R92C_NAV_PROT_LEN 0x546 -#define R92C_BCN_CTRL 0x550 -#define R92C_USTIME_TSF 0x551 -#define R92C_MBID_NUM 0x552 -#define R92C_DUAL_TSF_RST 0x553 -#define R92C_BCN_INTERVAL 0x554 -#define R92C_DRVERLYINT 0x558 -#define R92C_BCNDMATIM 0x559 -#define R92C_ATIMWND 0x55a -#define R92C_BCN_MAX_ERR 0x55d -#define R92C_RXTSF_OFFSET_CCK 0x55e -#define R92C_RXTSF_OFFSET_OFDM 0x55f -#define R92C_TSFTR 0x560 -#define R92C_INIT_TSFTR 0x564 -#define R92C_PSTIMER 0x580 -#define R92C_TIMER0 0x584 -#define R92C_TIMER1 0x588 -#define R92C_ACMHWCTRL 0x5c0 -#define R92C_ACMRSTCTRL 0x5c1 -#define R92C_ACMAVG 0x5c2 -#define R92C_VO_ADMTIME 0x5c4 -#define R92C_VI_ADMTIME 0x5c6 -#define R92C_BE_ADMTIME 0x5c8 -#define R92C_EDCA_RANDOM_GEN 0x5cc -#define R92C_SCH_TXCMD 0x5d0 -/* WMAC Configuration. */ -#define R92C_APSD_CTRL 0x600 -#define R92C_BWOPMODE 0x603 -#define R92C_TCR 0x604 -#define R92C_RCR 0x608 -#define R92C_RX_DRVINFO_SZ 0x60f -#define R92C_MACID 0x610 -#define R92C_BSSID 0x618 -#define R92C_MAR 0x620 -#define R92C_MAC_SPEC_SIFS 0x63a -#define R92C_R2T_SIFS 0x63c -#define R92C_T2T_SIFS 0x63e -#define R92C_ACKTO 0x640 -#define R92C_CAMCMD 0x670 -#define R92C_CAMWRITE 0x674 -#define R92C_CAMREAD 0x678 -#define R92C_CAMDBG 0x67c -#define R92C_SECCFG 0x680 -#define R92C_RXFLTMAP0 0x6a0 -#define R92C_RXFLTMAP1 0x6a2 -#define R92C_RXFLTMAP2 0x6a4 - -/* Bits for R92C_SYS_ISO_CTRL. */ -#define R92C_SYS_ISO_CTRL_MD2PP 0x0001 -#define R92C_SYS_ISO_CTRL_UA2USB 0x0002 -#define R92C_SYS_ISO_CTRL_UD2CORE 0x0004 -#define R92C_SYS_ISO_CTRL_PA2PCIE 0x0008 -#define R92C_SYS_ISO_CTRL_PD2CORE 0x0010 -#define R92C_SYS_ISO_CTRL_IP2MAC 0x0020 -#define R92C_SYS_ISO_CTRL_DIOP 0x0040 -#define R92C_SYS_ISO_CTRL_DIOE 0x0080 -#define R92C_SYS_ISO_CTRL_EB2CORE 0x0100 -#define R92C_SYS_ISO_CTRL_DIOR 0x0200 -#define R92C_SYS_ISO_CTRL_PWC_EV25V 0x4000 -#define R92C_SYS_ISO_CTRL_PWC_EV12V 0x8000 - -/* Bits for R92C_SYS_FUNC_EN. */ -#define R92C_SYS_FUNC_EN_BBRSTB 0x0001 -#define R92C_SYS_FUNC_EN_BB_GLB_RST 0x0002 -#define R92C_SYS_FUNC_EN_USBA 0x0004 -#define R92C_SYS_FUNC_EN_UPLL 0x0008 -#define R92C_SYS_FUNC_EN_USBD 0x0010 -#define R92C_SYS_FUNC_EN_DIO_PCIE 0x0020 -#define R92C_SYS_FUNC_EN_PCIEA 0x0040 -#define R92C_SYS_FUNC_EN_PPLL 0x0080 -#define R92C_SYS_FUNC_EN_PCIED 0x0100 -#define R92C_SYS_FUNC_EN_DIOE 0x0200 -#define R92C_SYS_FUNC_EN_CPUEN 0x0400 -#define R92C_SYS_FUNC_EN_DCORE 0x0800 -#define R92C_SYS_FUNC_EN_ELDR 0x1000 -#define R92C_SYS_FUNC_EN_DIO_RF 0x2000 -#define R92C_SYS_FUNC_EN_HWPDN 0x4000 -#define R92C_SYS_FUNC_EN_MREGEN 0x8000 - -/* Bits for R92C_APS_FSMCO. */ -#define R92C_APS_FSMCO_PFM_LDALL 0x00000001 -#define R92C_APS_FSMCO_PFM_ALDN 0x00000002 -#define R92C_APS_FSMCO_PFM_LDKP 0x00000004 -#define R92C_APS_FSMCO_PFM_WOWL 0x00000008 -#define R92C_APS_FSMCO_PDN_EN 0x00000010 -#define R92C_APS_FSMCO_PDN_PL 0x00000020 -#define R92C_APS_FSMCO_APFM_ONMAC 0x00000100 -#define R92C_APS_FSMCO_APFM_OFF 0x00000200 -#define R92C_APS_FSMCO_APFM_RSM 0x00000400 -#define R92C_APS_FSMCO_AFSM_HSUS 0x00000800 -#define R92C_APS_FSMCO_AFSM_PCIE 0x00001000 -#define R92C_APS_FSMCO_APDM_MAC 0x00002000 -#define R92C_APS_FSMCO_APDM_HOST 0x00004000 -#define R92C_APS_FSMCO_APDM_HPDN 0x00008000 -#define R92C_APS_FSMCO_RDY_MACON 0x00010000 -#define R92C_APS_FSMCO_SUS_HOST 0x00020000 -#define R92C_APS_FSMCO_ROP_ALD 0x00100000 -#define R92C_APS_FSMCO_ROP_PWR 0x00200000 -#define R92C_APS_FSMCO_ROP_SPS 0x00400000 -#define R92C_APS_FSMCO_SOP_MRST 0x02000000 -#define R92C_APS_FSMCO_SOP_FUSE 0x04000000 -#define R92C_APS_FSMCO_SOP_ABG 0x08000000 -#define R92C_APS_FSMCO_SOP_AMB 0x10000000 -#define R92C_APS_FSMCO_SOP_RCK 0x20000000 -#define R92C_APS_FSMCO_SOP_A8M 0x40000000 -#define R92C_APS_FSMCO_XOP_BTCK 0x80000000 - -/* Bits for R92C_SYS_CLKR. */ -#define R92C_SYS_CLKR_ANAD16V_EN 0x00000001 -#define R92C_SYS_CLKR_ANA8M 0x00000002 -#define R92C_SYS_CLKR_MACSLP 0x00000010 -#define R92C_SYS_CLKR_LOADER_EN 0x00000020 -#define R92C_SYS_CLKR_80M_SSC_DIS 0x00000080 -#define R92C_SYS_CLKR_80M_SSC_EN_HO 0x00000100 -#define R92C_SYS_CLKR_PHY_SSC_RSTB 0x00000200 -#define R92C_SYS_CLKR_SEC_EN 0x00000400 -#define R92C_SYS_CLKR_MAC_EN 0x00000800 -#define R92C_SYS_CLKR_SYS_EN 0x00001000 -#define R92C_SYS_CLKR_RING_EN 0x00002000 - -/* Bits for R92C_RF_CTRL. */ -#define R92C_RF_CTRL_EN 0x01 -#define R92C_RF_CTRL_RSTB 0x02 -#define R92C_RF_CTRL_SDMRSTB 0x04 - -/* Bits for R92C_LDOV12D_CTRL. */ -#define R92C_LDOV12D_CTRL_LDV12_EN 0x01 - -/* Bits for R92C_EFUSE_CTRL. */ -#define R92C_EFUSE_CTRL_DATA_M 0x000000ff -#define R92C_EFUSE_CTRL_DATA_S 0 -#define R92C_EFUSE_CTRL_ADDR_M 0x0003ff00 -#define R92C_EFUSE_CTRL_ADDR_S 8 -#define R92C_EFUSE_CTRL_VALID 0x80000000 - -/* Bits for R92C_GPIO_MUXCFG. */ -#define R92C_GPIO_MUXCFG_RFKILL 0x0008 -#define R92C_GPIO_MUXCFG_ENBT 0x0020 - -/* Bits for R92C_GPIO_IO_SEL. */ -#define R92C_GPIO_IO_SEL_RFKILL 0x0008 - -/* Bits for R92C_LEDCFG0. */ -#define R92C_LEDCFG0_DIS 0x08 - -/* Bits for R92C_LEDCFG2. */ -#define R92C_LEDCFG2_EN 0x60 -#define R92C_LEDCFG2_DIS 0x68 - -/* Bits for R92C_MCUFWDL. */ -#define R92C_MCUFWDL_EN 0x00000001 -#define R92C_MCUFWDL_RDY 0x00000002 -#define R92C_MCUFWDL_CHKSUM_RPT 0x00000004 -#define R92C_MCUFWDL_MACINI_RDY 0x00000008 -#define R92C_MCUFWDL_BBINI_RDY 0x00000010 -#define R92C_MCUFWDL_RFINI_RDY 0x00000020 -#define R92C_MCUFWDL_WINTINI_RDY 0x00000040 -#define R92C_MCUFWDL_RAM_DL_SEL 0x00000080 /* 1: RAM, 0: ROM */ -#define R92C_MCUFWDL_PAGE_M 0x00070000 -#define R92C_MCUFWDL_PAGE_S 16 -#define R92C_MCUFWDL_CPRST 0x00800000 - -/* Bits for R92C_HPON_FSM. */ -#define R92C_HPON_FSM_CHIP_BONDING_ID_S 22 -#define R92C_HPON_FSM_CHIP_BONDING_ID_M 0x00c00000 -#define R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R 1 - -/* Bits for R92C_SYS_CFG. */ -#define R92C_SYS_CFG_XCLK_VLD 0x00000001 -#define R92C_SYS_CFG_ACLK_VLD 0x00000002 -#define R92C_SYS_CFG_UCLK_VLD 0x00000004 -#define R92C_SYS_CFG_PCLK_VLD 0x00000008 -#define R92C_SYS_CFG_PCIRSTB 0x00000010 -#define R92C_SYS_CFG_V15_VLD 0x00000020 -#define R92C_SYS_CFG_TRP_B15V_EN 0x00000080 -#define R92C_SYS_CFG_SIC_IDLE 0x00000100 -#define R92C_SYS_CFG_BD_MAC2 0x00000200 -#define R92C_SYS_CFG_BD_MAC1 0x00000400 -#define R92C_SYS_CFG_IC_MACPHY_MODE 0x00000800 -#define R92C_SYS_CFG_CHIP_VER_RTL_M 0x0000f000 -#define R92C_SYS_CFG_CHIP_VER_RTL_S 12 -#define R92C_SYS_CFG_BT_FUNC 0x00010000 -#define R92C_SYS_CFG_VENDOR_UMC 0x00080000 -#define R92C_SYS_CFG_PAD_HWPD_IDN 0x00400000 -#define R92C_SYS_CFG_TRP_VAUX_EN 0x00800000 -#define R92C_SYS_CFG_TRP_BT_EN 0x01000000 -#define R92C_SYS_CFG_BD_PKG_SEL 0x02000000 -#define R92C_SYS_CFG_BD_HCI_SEL 0x04000000 -#define R92C_SYS_CFG_TYPE_92C 0x08000000 - -/* Bits for R92C_CR. */ -#define R92C_CR_HCI_TXDMA_EN 0x00000001 -#define R92C_CR_HCI_RXDMA_EN 0x00000002 -#define R92C_CR_TXDMA_EN 0x00000004 -#define R92C_CR_RXDMA_EN 0x00000008 -#define R92C_CR_PROTOCOL_EN 0x00000010 -#define R92C_CR_SCHEDULE_EN 0x00000020 -#define R92C_CR_MACTXEN 0x00000040 -#define R92C_CR_MACRXEN 0x00000080 -#define R92C_CR_ENSEC 0x00000200 -#define R92C_CR_NETTYPE_S 16 -#define R92C_CR_NETTYPE_M 0x00030000 -#define R92C_CR_NETTYPE_NOLINK 0 -#define R92C_CR_NETTYPE_ADHOC 1 -#define R92C_CR_NETTYPE_INFRA 2 -#define R92C_CR_NETTYPE_AP 3 - -/* Bits for R92C_PBP. */ -#define R92C_PBP_PSRX_M 0x0f -#define R92C_PBP_PSRX_S 0 -#define R92C_PBP_PSTX_M 0xf0 -#define R92C_PBP_PSTX_S 4 -#define R92C_PBP_64 0 -#define R92C_PBP_128 1 -#define R92C_PBP_256 2 -#define R92C_PBP_512 3 -#define R92C_PBP_1024 4 - -/* Bits for R92C_TRXDMA_CTRL. */ -#define R92C_TRXDMA_CTRL_RXDMA_AGG_EN 0x0004 -#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_M 0x0030 -#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_S 4 -#define R92C_TRXDMA_CTRL_TXDMA_VIQ_MAP_M 0x00c0 -#define R92C_TRXDMA_CTRL_TXDMA_VIQ_MAP_S 6 -#define R92C_TRXDMA_CTRL_TXDMA_BEQ_MAP_M 0x0300 -#define R92C_TRXDMA_CTRL_TXDMA_BEQ_MAP_S 8 -#define R92C_TRXDMA_CTRL_TXDMA_BKQ_MAP_M 0x0c00 -#define R92C_TRXDMA_CTRL_TXDMA_BKQ_MAP_S 10 -#define R92C_TRXDMA_CTRL_TXDMA_MGQ_MAP_M 0x3000 -#define R92C_TRXDMA_CTRL_TXDMA_MGQ_MAP_S 12 -#define R92C_TRXDMA_CTRL_TXDMA_HIQ_MAP_M 0xc000 -#define R92C_TRXDMA_CTRL_TXDMA_HIQ_MAP_S 14 -#define R92C_TRXDMA_CTRL_QUEUE_LOW 1 -#define R92C_TRXDMA_CTRL_QUEUE_NORMAL 2 -#define R92C_TRXDMA_CTRL_QUEUE_HIGH 3 -#define R92C_TRXDMA_CTRL_QMAP_M 0xfff0 -#define R92C_TRXDMA_CTRL_QMAP_S 4 -/* Shortcuts. */ -#define R92C_TRXDMA_CTRL_QMAP_3EP 0xf5b0 -#define R92C_TRXDMA_CTRL_QMAP_HQ_LQ 0xf5f0 -#define R92C_TRXDMA_CTRL_QMAP_HQ_NQ 0xfaf0 -#define R92C_TRXDMA_CTRL_QMAP_LQ 0x5550 -#define R92C_TRXDMA_CTRL_QMAP_NQ 0xaaa0 -#define R92C_TRXDMA_CTRL_QMAP_HQ 0xfff0 - -/* Bits for R92C_LLT_INIT. */ -#define R92C_LLT_INIT_DATA_M 0x000000ff -#define R92C_LLT_INIT_DATA_S 0 -#define R92C_LLT_INIT_ADDR_M 0x0000ff00 -#define R92C_LLT_INIT_ADDR_S 8 -#define R92C_LLT_INIT_OP_M 0xc0000000 -#define R92C_LLT_INIT_OP_S 30 -#define R92C_LLT_INIT_OP_NO_ACTIVE 0 -#define R92C_LLT_INIT_OP_WRITE 1 - -/* Bits for R92C_RQPN. */ -#define R92C_RQPN_HPQ_M 0x000000ff -#define R92C_RQPN_HPQ_S 0 -#define R92C_RQPN_LPQ_M 0x0000ff00 -#define R92C_RQPN_LPQ_S 8 -#define R92C_RQPN_PUBQ_M 0x00ff0000 -#define R92C_RQPN_PUBQ_S 16 -#define R92C_RQPN_LD 0x80000000 - -/* Bits for R92C_TDECTRL. */ -#define R92C_TDECTRL_BLK_DESC_NUM_M 0x0000000f -#define R92C_TDECTRL_BLK_DESC_NUM_S 4 - -/* Bits for R92C_FWHW_TXQ_CTRL. */ -#define R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW 0x80 - -/* Bits for R92C_SPEC_SIFS. */ -#define R92C_SPEC_SIFS_CCK_M 0x00ff -#define R92C_SPEC_SIFS_CCK_S 0 -#define R92C_SPEC_SIFS_OFDM_M 0xff00 -#define R92C_SPEC_SIFS_OFDM_S 8 - -/* Bits for R92C_RL. */ -#define R92C_RL_LRL_M 0x003f -#define R92C_RL_LRL_S 0 -#define R92C_RL_SRL_M 0x3f00 -#define R92C_RL_SRL_S 8 - -/* Bits for R92C_RRSR. */ -#define R92C_RRSR_RATE_BITMAP_M 0x000fffff -#define R92C_RRSR_RATE_BITMAP_S 0 -#define R92C_RRSR_RATE_CCK_ONLY_1M 0xffff1 -#define R92C_RRSR_RATE_ALL 0xfffff -#define R92C_RRSR_RSC_LOWSUBCHNL 0x00200000 -#define R92C_RRSR_RSC_UPSUBCHNL 0x00400000 -#define R92C_RRSR_SHORT 0x00800000 - -/* Bits for R92C_EDCA_XX_PARAM. */ -#define R92C_EDCA_PARAM_AIFS_M 0x000000ff -#define R92C_EDCA_PARAM_AIFS_S 0 -#define R92C_EDCA_PARAM_ECWMIN_M 0x00000f00 -#define R92C_EDCA_PARAM_ECWMIN_S 8 -#define R92C_EDCA_PARAM_ECWMAX_M 0x0000f000 -#define R92C_EDCA_PARAM_ECWMAX_S 12 -#define R92C_EDCA_PARAM_TXOP_M 0xffff0000 -#define R92C_EDCA_PARAM_TXOP_S 16 - -/* Bits for R92C_TXPAUSE. */ -#define R92C_TXPAUSE_AC_VO 0x01 -#define R92C_TXPAUSE_AC_VI 0x02 -#define R92C_TXPAUSE_AC_BE 0x04 -#define R92C_TXPAUSE_AC_BK 0x08 - -/* Bits for R92C_BCN_CTRL. */ -#define R92C_BCN_CTRL_EN_MBSSID 0x02 -#define R92C_BCN_CTRL_TXBCN_RPT 0x04 -#define R92C_BCN_CTRL_EN_BCN 0x08 -#define R92C_BCN_CTRL_DIS_TSF_UDT0 0x10 - -/* Bits for R92C_APSD_CTRL. */ -#define R92C_APSD_CTRL_OFF 0x40 -#define R92C_APSD_CTRL_OFF_STATUS 0x80 - -/* Bits for R92C_BWOPMODE. */ -#define R92C_BWOPMODE_11J 0x01 -#define R92C_BWOPMODE_5G 0x02 -#define R92C_BWOPMODE_20MHZ 0x04 - -/* Bits for R92C_TCR. */ -#define R92C_TCR_TSFRST 0x00000001 -#define R92C_TCR_DIS_GCLK 0x00000002 -#define R92C_TCR_PAD_SEL 0x00000004 -#define R92C_TCR_PWR_ST 0x00000040 -#define R92C_TCR_PWRBIT_OW_EN 0x00000080 -#define R92C_TCR_ACRC 0x00000100 -#define R92C_TCR_CFENDFORM 0x00000200 -#define R92C_TCR_ICV 0x00000400 - -/* Bits for R92C_RCR. */ -#define R92C_RCR_AAP 0x00000001 -#define R92C_RCR_APM 0x00000002 -#define R92C_RCR_AM 0x00000004 -#define R92C_RCR_AB 0x00000008 -#define R92C_RCR_ADD3 0x00000010 -#define R92C_RCR_APWRMGT 0x00000020 -#define R92C_RCR_CBSSID_DATA 0x00000040 -#define R92C_RCR_CBSSID_BCN 0x00000080 -#define R92C_RCR_ACRC32 0x00000100 -#define R92C_RCR_AICV 0x00000200 -#define R92C_RCR_ADF 0x00000800 -#define R92C_RCR_ACF 0x00001000 -#define R92C_RCR_AMF 0x00002000 -#define R92C_RCR_HTC_LOC_CTRL 0x00004000 -#define R92C_RCR_MFBEN 0x00400000 -#define R92C_RCR_LSIGEN 0x00800000 -#define R92C_RCR_ENMBID 0x01000000 -#define R92C_RCR_APP_BA_SSN 0x08000000 -#define R92C_RCR_APP_PHYSTS 0x10000000 -#define R92C_RCR_APP_ICV 0x20000000 -#define R92C_RCR_APP_MIC 0x40000000 -#define R92C_RCR_APPFCS 0x80000000 - -/* Bits for R92C_CAMCMD. */ -#define R92C_CAMCMD_ADDR_M 0x0000ffff -#define R92C_CAMCMD_ADDR_S 0 -#define R92C_CAMCMD_WRITE 0x00010000 -#define R92C_CAMCMD_CLR 0x40000000 -#define R92C_CAMCMD_POLLING 0x80000000 - -/* IMR */ - -/*Beacon DMA interrupt 6 */ -#define R92C_IMR_BCNDMAINT6 0x80000000 -/*Beacon DMA interrupt 5 */ -#define R92C_IMR_BCNDMAINT5 0x40000000 -/*Beacon DMA interrupt 4 */ -#define R92C_IMR_BCNDMAINT4 0x20000000 -/*Beacon DMA interrupt 3 */ -#define R92C_IMR_BCNDMAINT3 0x10000000 -/*Beacon DMA interrupt 2 */ -#define R92C_IMR_BCNDMAINT2 0x08000000 -/*Beacon DMA interrupt 1 */ -#define R92C_IMR_BCNDMAINT1 0x04000000 -/*Beacon Queue DMA OK interrupt 8 */ -#define R92C_IMR_BCNDOK8 0x02000000 -/*Beacon Queue DMA OK interrupt 7 */ -#define R92C_IMR_BCNDOK7 0x01000000 -/*Beacon Queue DMA OK interrupt 6 */ -#define R92C_IMR_BCNDOK6 0x00800000 -/*Beacon Queue DMA OK interrupt 5 */ -#define R92C_IMR_BCNDOK5 0x00400000 -/*Beacon Queue DMA OK interrupt 4 */ -#define R92C_IMR_BCNDOK4 0x00200000 -/*Beacon Queue DMA OK interrupt 3 */ -#define R92C_IMR_BCNDOK3 0x00100000 -/*Beacon Queue DMA OK interrupt 2 */ -#define R92C_IMR_BCNDOK2 0x00080000 -/*Beacon Queue DMA OK interrupt 1 */ -#define R92C_IMR_BCNDOK1 0x00040000 -/*Timeout interrupt 2 */ -#define R92C_IMR_TIMEOUT2 0x00020000 -/*Timeout interrupt 1 */ -#define R92C_IMR_TIMEOUT1 0x00010000 -/*Transmit FIFO Overflow */ -#define R92C_IMR_TXFOVW 0x00008000 -/*Power save time out interrupt */ -#define R92C_IMR_PSTIMEOUT 0x00004000 -/*Beacon DMA interrupt 0 */ -#define R92C_IMR_BCNINT 0x00002000 -/*Receive FIFO Overflow */ -#define R92C_IMR_RXFOVW 0x00001000 -/*Receive Descriptor Unavailable */ -#define R92C_IMR_RDU 0x00000800 -/*For 92C,ATIM Window End interrupt */ -#define R92C_IMR_ATIMEND 0x00000400 -/*Beacon Queue DMA OK interrupt */ -#define R92C_IMR_BDOK 0x00000200 -/*High Queue DMA OK interrupt */ -#define R92C_IMR_HIGHDOK 0x00000100 -/*Transmit Beacon OK interrupt */ -#define R92C_IMR_TBDOK 0x00000080 -/*Management Queue DMA OK interrupt */ -#define R92C_IMR_MGNTDOK 0x00000040 -/*For 92C,Transmit Beacon Error interrupt */ -#define R92C_IMR_TBDER 0x00000020 -/*AC_BK DMA OK interrupt */ -#define R92C_IMR_BKDOK 0x00000010 -/*AC_BE DMA OK interrupt */ -#define R92C_IMR_BEDOK 0x00000008 -/*AC_VI DMA OK interrupt */ -#define R92C_IMR_VIDOK 0x00000004 -/*AC_VO DMA interrupt */ -#define R92C_IMR_VODOK 0x00000002 -/*Receive DMA OK interrupt */ -#define R92C_IMR_ROK 0x00000001 - -#define R92C_IBSS_INT_MASK (R92C_IMR_BCNINT | R92C_IMR_TBDOK | R92C_IMR_TBDER) - -/* - * Baseband registers. - */ -#define R92C_FPGA0_RFMOD 0x800 -#define R92C_FPGA0_TXINFO 0x804 -#define R92C_HSSI_PARAM1(chain) (0x820 + (chain) * 8) -#define R92C_HSSI_PARAM2(chain) (0x824 + (chain) * 8) -#define R92C_TXAGC_RATE18_06(i) (((i) == 0) ? 0xe00 : 0x830) -#define R92C_TXAGC_RATE54_24(i) (((i) == 0) ? 0xe04 : 0x834) -#define R92C_TXAGC_A_CCK1_MCS32 0xe08 -#define R92C_TXAGC_B_CCK1_55_MCS32 0x838 -#define R92C_TXAGC_B_CCK11_A_CCK2_11 0x86c -#define R92C_TXAGC_MCS03_MCS00(i) (((i) == 0) ? 0xe10 : 0x83c) -#define R92C_TXAGC_MCS07_MCS04(i) (((i) == 0) ? 0xe14 : 0x848) -#define R92C_TXAGC_MCS11_MCS08(i) (((i) == 0) ? 0xe18 : 0x84c) -#define R92C_TXAGC_MCS15_MCS12(i) (((i) == 0) ? 0xe1c : 0x868) -#define R92C_LSSI_PARAM(chain) (0x840 + (chain) * 4) -#define R92C_FPGA0_RFIFACEOE(chain) (0x860 + (chain) * 4) -#define R92C_FPGA0_RFIFACESW(idx) (0x870 + (idx) * 4) -#define R92C_FPGA0_RFPARAM(idx) (0x878 + (idx) * 4) -#define R92C_FPGA0_ANAPARAM2 0x884 -#define R92C_LSSI_READBACK(chain) (0x8a0 + (chain) * 4) -#define R92C_HSPI_READBACK(chain) (0x8b8 + (chain) * 4) -#define R92C_FPGA1_RFMOD 0x900 -#define R92C_FPGA1_TXINFO 0x90c -#define R92C_CCK0_SYSTEM 0xa00 -#define R92C_CCK0_AFESETTING 0xa04 -#define R92C_OFDM0_TRXPATHENA 0xc04 -#define R92C_OFDM0_TRMUXPAR 0xc08 -#define R92C_OFDM0_RXIQIMBALANCE(chain) (0xc14 + (chain) * 8) -#define R92C_OFDM0_ECCATHRESHOLD 0xc4c -#define R92C_OFDM0_AGCCORE1(chain) (0xc50 + (chain) * 8) -#define R92C_OFDM0_AGCPARAM1 0xc70 -#define R92C_OFDM0_AGCRSSITABLE 0xc78 -#define R92C_OFDM0_TXIQIMBALANCE(chain) (0xc80 + (chain) * 8) -#define R92C_OFDM0_TXAFE(chain) (0xc94 + (chain) * 8) -#define R92C_OFDM0_RXIQEXTANTA 0xca0 -#define R92C_OFDM1_LSTF 0xd00 - -/* Bits for R92C_FPGA[01]_RFMOD. */ -#define R92C_RFMOD_40MHZ 0x00000001 -#define R92C_RFMOD_JAPAN 0x00000002 -#define R92C_RFMOD_CCK_TXSC 0x00000030 -#define R92C_RFMOD_CCK_EN 0x01000000 -#define R92C_RFMOD_OFDM_EN 0x02000000 - -/* Bits for R92C_HSSI_PARAM1(i). */ -#define R92C_HSSI_PARAM1_PI 0x00000100 - -/* Bits for R92C_HSSI_PARAM2(i). */ -#define R92C_HSSI_PARAM2_CCK_HIPWR 0x00000200 -#define R92C_HSSI_PARAM2_ADDR_LENGTH 0x00000400 -#define R92C_HSSI_PARAM2_DATA_LENGTH 0x00000800 -#define R92C_HSSI_PARAM2_READ_ADDR_M 0x7f800000 -#define R92C_HSSI_PARAM2_READ_ADDR_S 23 -#define R92C_HSSI_PARAM2_READ_EDGE 0x80000000 - -/* Bits for R92C_TXAGC_A_CCK1_MCS32. */ -#define R92C_TXAGC_A_CCK1_M 0x0000ff00 -#define R92C_TXAGC_A_CCK1_S 8 - -/* Bits for R92C_TXAGC_B_CCK11_A_CCK2_11. */ -#define R92C_TXAGC_B_CCK11_M 0x000000ff -#define R92C_TXAGC_B_CCK11_S 0 -#define R92C_TXAGC_A_CCK2_M 0x0000ff00 -#define R92C_TXAGC_A_CCK2_S 8 -#define R92C_TXAGC_A_CCK55_M 0x00ff0000 -#define R92C_TXAGC_A_CCK55_S 16 -#define R92C_TXAGC_A_CCK11_M 0xff000000 -#define R92C_TXAGC_A_CCK11_S 24 - -/* Bits for R92C_TXAGC_B_CCK1_55_MCS32. */ -#define R92C_TXAGC_B_CCK1_M 0x0000ff00 -#define R92C_TXAGC_B_CCK1_S 8 -#define R92C_TXAGC_B_CCK2_M 0x00ff0000 -#define R92C_TXAGC_B_CCK2_S 16 -#define R92C_TXAGC_B_CCK55_M 0xff000000 -#define R92C_TXAGC_B_CCK55_S 24 - -/* Bits for R92C_TXAGC_RATE18_06(x). */ -#define R92C_TXAGC_RATE06_M 0x000000ff -#define R92C_TXAGC_RATE06_S 0 -#define R92C_TXAGC_RATE09_M 0x0000ff00 -#define R92C_TXAGC_RATE09_S 8 -#define R92C_TXAGC_RATE12_M 0x00ff0000 -#define R92C_TXAGC_RATE12_S 16 -#define R92C_TXAGC_RATE18_M 0xff000000 -#define R92C_TXAGC_RATE18_S 24 - -/* Bits for R92C_TXAGC_RATE54_24(x). */ -#define R92C_TXAGC_RATE24_M 0x000000ff -#define R92C_TXAGC_RATE24_S 0 -#define R92C_TXAGC_RATE36_M 0x0000ff00 -#define R92C_TXAGC_RATE36_S 8 -#define R92C_TXAGC_RATE48_M 0x00ff0000 -#define R92C_TXAGC_RATE48_S 16 -#define R92C_TXAGC_RATE54_M 0xff000000 -#define R92C_TXAGC_RATE54_S 24 - -/* Bits for R92C_TXAGC_MCS03_MCS00(x). */ -#define R92C_TXAGC_MCS00_M 0x000000ff -#define R92C_TXAGC_MCS00_S 0 -#define R92C_TXAGC_MCS01_M 0x0000ff00 -#define R92C_TXAGC_MCS01_S 8 -#define R92C_TXAGC_MCS02_M 0x00ff0000 -#define R92C_TXAGC_MCS02_S 16 -#define R92C_TXAGC_MCS03_M 0xff000000 -#define R92C_TXAGC_MCS03_S 24 - -/* Bits for R92C_TXAGC_MCS07_MCS04(x). */ -#define R92C_TXAGC_MCS04_M 0x000000ff -#define R92C_TXAGC_MCS04_S 0 -#define R92C_TXAGC_MCS05_M 0x0000ff00 -#define R92C_TXAGC_MCS05_S 8 -#define R92C_TXAGC_MCS06_M 0x00ff0000 -#define R92C_TXAGC_MCS06_S 16 -#define R92C_TXAGC_MCS07_M 0xff000000 -#define R92C_TXAGC_MCS07_S 24 - -/* Bits for R92C_TXAGC_MCS11_MCS08(x). */ -#define R92C_TXAGC_MCS08_M 0x000000ff -#define R92C_TXAGC_MCS08_S 0 -#define R92C_TXAGC_MCS09_M 0x0000ff00 -#define R92C_TXAGC_MCS09_S 8 -#define R92C_TXAGC_MCS10_M 0x00ff0000 -#define R92C_TXAGC_MCS10_S 16 -#define R92C_TXAGC_MCS11_M 0xff000000 -#define R92C_TXAGC_MCS11_S 24 - -/* Bits for R92C_TXAGC_MCS15_MCS12(x). */ -#define R92C_TXAGC_MCS12_M 0x000000ff -#define R92C_TXAGC_MCS12_S 0 -#define R92C_TXAGC_MCS13_M 0x0000ff00 -#define R92C_TXAGC_MCS13_S 8 -#define R92C_TXAGC_MCS14_M 0x00ff0000 -#define R92C_TXAGC_MCS14_S 16 -#define R92C_TXAGC_MCS15_M 0xff000000 -#define R92C_TXAGC_MCS15_S 24 - -/* Bits for R92C_LSSI_PARAM(i). */ -#define R92C_LSSI_PARAM_DATA_M 0x000fffff -#define R92C_LSSI_PARAM_DATA_S 0 -#define R92C_LSSI_PARAM_ADDR_M 0x03f00000 -#define R92C_LSSI_PARAM_ADDR_S 20 - -/* Bits for R92C_FPGA0_ANAPARAM2. */ -#define R92C_FPGA0_ANAPARAM2_CBW20 0x00000400 - -/* Bits for R92C_LSSI_READBACK(i). */ -#define R92C_LSSI_READBACK_DATA_M 0x000fffff -#define R92C_LSSI_READBACK_DATA_S 0 - -/* Bits for R92C_OFDM0_AGCCORE1(i). */ -#define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f -#define R92C_OFDM0_AGCCORE1_GAIN_S 0 - - -/* - * USB registers. - */ -#define R92C_USB_INFO 0xfe17 -#define R92C_USB_SPECIAL_OPTION 0xfe55 -#define R92C_USB_HCPWM 0xfe57 -#define R92C_USB_HRPWM 0xfe58 -#define R92C_USB_DMA_AGG_TO 0xfe5b -#define R92C_USB_AGG_TO 0xfe5c -#define R92C_USB_AGG_TH 0xfe5d -#define R92C_USB_VID 0xfe60 -#define R92C_USB_PID 0xfe62 -#define R92C_USB_OPTIONAL 0xfe64 -#define R92C_USB_EP 0xfe65 -#define R92C_USB_PHY 0xfe68 -#define R92C_USB_MAC_ADDR 0xfe70 -#define R92C_USB_STRING 0xfe80 - -/* Bits for R92C_USB_SPECIAL_OPTION. */ -#define R92C_USB_SPECIAL_OPTION_AGG_EN 0x08 - -/* Bits for R92C_USB_EP. */ -#define R92C_USB_EP_HQ_M 0x000f -#define R92C_USB_EP_HQ_S 0 -#define R92C_USB_EP_NQ_M 0x00f0 -#define R92C_USB_EP_NQ_S 4 -#define R92C_USB_EP_LQ_M 0x0f00 -#define R92C_USB_EP_LQ_S 8 - - -/* - * Firmware base address. - */ -#define R92C_FW_START_ADDR 0x1000 -#define R92C_FW_PAGE_SIZE 4096 - - -/* - * RF (6052) registers. - */ -#define R92C_RF_AC 0x00 -#define R92C_RF_IQADJ_G(i) (0x01 + (i)) -#define R92C_RF_POW_TRSW 0x05 -#define R92C_RF_GAIN_RX 0x06 -#define R92C_RF_GAIN_TX 0x07 -#define R92C_RF_TXM_IDAC 0x08 -#define R92C_RF_BS_IQGEN 0x0f -#define R92C_RF_MODE1 0x10 -#define R92C_RF_MODE2 0x11 -#define R92C_RF_RX_AGC_HP 0x12 -#define R92C_RF_TX_AGC 0x13 -#define R92C_RF_BIAS 0x14 -#define R92C_RF_IPA 0x15 -#define R92C_RF_POW_ABILITY 0x17 -#define R92C_RF_CHNLBW 0x18 -#define R92C_RF_RX_G1 0x1a -#define R92C_RF_RX_G2 0x1b -#define R92C_RF_RX_BB2 0x1c -#define R92C_RF_RX_BB1 0x1d -#define R92C_RF_RCK1 0x1e -#define R92C_RF_RCK2 0x1f -#define R92C_RF_TX_G(i) (0x20 + (i)) -#define R92C_RF_TX_BB1 0x23 -#define R92C_RF_T_METER 0x24 -#define R92C_RF_SYN_G(i) (0x25 + (i)) -#define R92C_RF_RCK_OS 0x30 -#define R92C_RF_TXPA_G(i) (0x31 + (i)) - -/* Bits for R92C_RF_AC. */ -#define R92C_RF_AC_MODE_M 0x70000 -#define R92C_RF_AC_MODE_S 16 -#define R92C_RF_AC_MODE_STANDBY 1 - -/* Bits for R92C_RF_CHNLBW. */ -#define R92C_RF_CHNLBW_CHNL_M 0x003ff -#define R92C_RF_CHNLBW_CHNL_S 0 -#define R92C_RF_CHNLBW_BW20 0x00400 -#define R92C_RF_CHNLBW_LCSTART 0x08000 - - -/* - * CAM entries. - */ -#define R92C_CAM_ENTRY_COUNT 32 - -#define R92C_CAM_CTL0(entry) ((entry) * 8 + 0) -#define R92C_CAM_CTL1(entry) ((entry) * 8 + 1) -#define R92C_CAM_KEY(entry, i) ((entry) * 8 + 2 + (i)) - -/* Bits for R92C_CAM_CTL0(i). */ -#define R92C_CAM_KEYID_M 0x00000003 -#define R92C_CAM_KEYID_S 0 -#define R92C_CAM_ALGO_M 0x0000001c -#define R92C_CAM_ALGO_S 2 -#define R92C_CAM_ALGO_NONE 0 -#define R92C_CAM_ALGO_WEP40 1 -#define R92C_CAM_ALGO_TKIP 2 -#define R92C_CAM_ALGO_AES 4 -#define R92C_CAM_ALGO_WEP104 5 -#define R92C_CAM_VALID 0x00008000 -#define R92C_CAM_MACLO_M 0xffff0000 -#define R92C_CAM_MACLO_S 16 - -/* Rate adaptation modes. */ -#define R92C_RAID_11GN 1 -#define R92C_RAID_11N 3 -#define R92C_RAID_11BG 4 -#define R92C_RAID_11G 5 /* "pure" 11g */ -#define R92C_RAID_11B 6 - +#ifndef IF_RTWNREG_H +#define IF_RTWNREG_H + +#define R92C_MIN_TX_PWR 0x00 +#define R92C_MAX_TX_PWR 0x3f + +#define R92C_H2C_NBOX 4 + + +/* Common part of Tx descriptor (named only!). */ +struct rtwn_tx_desc_common { + uint16_t pktlen; + uint8_t offset; + uint8_t flags0; +#define RTWN_FLAGS0_OWN 0x80 + + uint32_t txdw1; +/* NB: qsel is shared too; however, it looks better at the lower level */ +#define RTWN_TXDW1_CIPHER_M 0x00c00000 +#define RTWN_TXDW1_CIPHER_S 22 +#define RTWN_TXDW1_CIPHER_NONE 0 +#define RTWN_TXDW1_CIPHER_RC4 1 +#define RTWN_TXDW1_CIPHER_SM4 2 +#define RTWN_TXDW1_CIPHER_AES 3 + + uint32_t reserved[5]; + + union txdw7_shared { + uint16_t usb_checksum; + uint16_t pci_txbufsize; + } txdw7; +} __packed __attribute__((aligned(4))); + +/* Common part of Rx descriptor. */ +struct rtwn_rx_stat_common { + uint32_t rxdw0; +#define RTWN_RXDW0_PKTLEN_M 0x00003fff +#define RTWN_RXDW0_PKTLEN_S 0 +#define RTWN_RXDW0_CRCERR 0x00004000 +#define RTWN_RXDW0_ICVERR 0x00008000 +#define RTWN_RXDW0_INFOSZ_M 0x000f0000 +#define RTWN_RXDW0_INFOSZ_S 16 +#define RTWN_RXDW0_CIPHER_M 0x00700000 +#define RTWN_RXDW0_CIPHER_S 20 +#define RTWN_RXDW0_QOS 0x00800000 +#define RTWN_RXDW0_SHIFT_M 0x03000000 +#define RTWN_RXDW0_SHIFT_S 24 +#define RTWN_RXDW0_PHYST 0x04000000 +#define RTWN_RXDW0_SWDEC 0x08000000 +#define RTWN_RXDW0_LS 0x10000000 +#define RTWN_RXDW0_FS 0x20000000 +#define RTWN_RXDW0_EOR 0x40000000 +#define RTWN_RXDW0_OWN 0x80000000 + + uint32_t rxdw1; +#define RTWN_RXDW1_AMSDU 0x00002000 +#define RTWN_RXDW1_MC 0x40000000 +#define RTWN_RXDW1_BC 0x80000000 + + uint32_t rxdw2; + uint32_t rxdw3; +#define RTWN_RXDW3_HTC 0x00000400 +#define RTWN_RXDW3_BSSID01_FIT_M 0x00003000 +#define RTWN_RXDW3_BSSID01_FIT_S 12 + + uint32_t rxdw4; + uint32_t tsf_low; +} __packed __attribute__((aligned(4))); + +/* Rx descriptor for PCIe devices. */ +struct rtwn_rx_stat_pci { + uint32_t rxdw0; + uint32_t rxdw1; + uint32_t rxdw2; + uint32_t rxdw3; + uint32_t rxdw4; + uint32_t tsf_low; + + uint32_t rxbufaddr; + uint32_t rxbufaddr64; +} __packed __attribute__((aligned(4))); /* * Macros to access subfields in registers. @@ -910,1196 +115,58 @@ #define RW(var, field, val) \ (((var) & ~field##_M) | SM(field, val)) -/* - * Firmware image header. - */ -struct r92c_fw_hdr { - /* QWORD0 */ - uint16_t signature; - uint8_t category; - uint8_t function; - uint16_t version; - uint16_t subversion; - /* QWORD1 */ - uint8_t month; - uint8_t date; - uint8_t hour; - uint8_t minute; - uint16_t ramcodesize; - uint16_t reserved2; - /* QWORD2 */ - uint32_t svnidx; - uint32_t reserved3; - /* QWORD3 */ - uint32_t reserved4; - uint32_t reserved5; -} __packed; + +#define RTWN_MAX_CONDITIONS 3 /* - * Host to firmware commands. + * Structure for MAC initialization values. */ -struct r92c_fw_cmd { - uint8_t id; -#define R92C_CMD_AP_OFFLOAD 0 -#define R92C_CMD_SET_PWRMODE 1 -#define R92C_CMD_JOINBSS_RPT 2 -#define R92C_CMD_RSVD_PAGE 3 -#define R92C_CMD_RSSI 4 -#define R92C_CMD_RSSI_SETTING 5 -#define R92C_CMD_MACID_CONFIG 6 -#define R92C_CMD_MACID_PS_MODE 7 -#define R92C_CMD_P2P_PS_OFFLOAD 8 -#define R92C_CMD_SELECTIVE_SUSPEND 9 -#define R92C_CMD_FLAG_EXT 0x80 - - uint8_t msg[5]; -} __packed; - -/* Structure for R92C_CMD_RSSI_SETTING. */ -struct r92c_fw_cmd_rssi { - uint8_t macid; - uint8_t reserved; - uint8_t pwdb; -} __packed; - -/* Structure for R92C_CMD_MACID_CONFIG. */ -struct r92c_fw_cmd_macid_cfg { - uint32_t mask; - uint8_t macid; -#define RTWN_MACID_BSS 0 -#define RTWN_MACID_BC 4 /* Broadcast. */ -#define RTWN_MACID_VALID 0x80 -} __packed; - -/* - * RTL8192CU ROM image. - */ -struct r92c_rom { - uint16_t id; /* 0x8129 */ - uint8_t reserved1[5]; - uint8_t dbg_sel; - uint16_t reserved2; - uint16_t vid; - uint16_t pid; - uint8_t usb_opt; - uint8_t ep_setting; - uint16_t reserved3; - uint8_t usb_phy; - uint8_t reserved4[3]; - uint8_t macaddr[6]; - uint8_t string[61]; /* "Realtek" */ - uint8_t subcustomer_id; - uint8_t cck_tx_pwr[R92C_MAX_CHAINS][3]; - uint8_t ht40_1s_tx_pwr[R92C_MAX_CHAINS][3]; - uint8_t ht40_2s_tx_pwr_diff[3]; - uint8_t ht20_tx_pwr_diff[3]; - uint8_t ofdm_tx_pwr_diff[3]; - uint8_t ht40_max_pwr[3]; - uint8_t ht20_max_pwr[3]; - uint8_t xtal_calib; - uint8_t tssi[R92C_MAX_CHAINS]; - uint8_t thermal_meter; - uint8_t rf_opt1; -#define R92C_ROM_RF1_REGULATORY_M 0x07 -#define R92C_ROM_RF1_REGULATORY_S 0 -#define R92C_ROM_RF1_BOARD_TYPE_M 0xe0 -#define R92C_ROM_RF1_BOARD_TYPE_S 5 -#define R92C_BOARD_TYPE_DONGLE 0 -#define R92C_BOARD_TYPE_HIGHPA 1 -#define R92C_BOARD_TYPE_MINICARD 2 -#define R92C_BOARD_TYPE_SOLO 3 -#define R92C_BOARD_TYPE_COMBO 4 - - uint8_t rf_opt2; - uint8_t rf_opt3; - uint8_t rf_opt4; - uint8_t channel_plan; -#define R92C_CHANNEL_PLAN_BY_HW 0x80 - - uint8_t version; - uint8_t curstomer_id; -} __packed; - -/* Rx MAC descriptor. */ -struct r92c_rx_desc { - uint32_t rxdw0; -#define R92C_RXDW0_PKTLEN_M 0x00003fff -#define R92C_RXDW0_PKTLEN_S 0 -#define R92C_RXDW0_CRCERR 0x00004000 -#define R92C_RXDW0_ICVERR 0x00008000 -#define R92C_RXDW0_INFOSZ_M 0x000f0000 -#define R92C_RXDW0_INFOSZ_S 16 -#define R92C_RXDW0_QOS 0x00800000 -#define R92C_RXDW0_SHIFT_M 0x03000000 -#define R92C_RXDW0_SHIFT_S 24 -#define R92C_RXDW0_PHYST 0x04000000 -#define R92C_RXDW0_DECRYPTED 0x08000000 -#define R92C_RXDW0_LS 0x10000000 -#define R92C_RXDW0_FS 0x20000000 -#define R92C_RXDW0_EOR 0x40000000 -#define R92C_RXDW0_OWN 0x80000000 - - uint32_t rxdw1; - uint32_t rxdw2; -#define R92C_RXDW2_PKTCNT_M 0x00ff0000 -#define R92C_RXDW2_PKTCNT_S 16 - - uint32_t rxdw3; -#define R92C_RXDW3_RATE_M 0x0000003f -#define R92C_RXDW3_RATE_S 0 -#define R92C_RXDW3_HT 0x00000040 -#define R92C_RXDW3_HTC 0x00000400 - - uint32_t rxdw4; - uint32_t rxdw5; - - uint32_t rxbufaddr; - uint32_t rxbufaddr64; -} __packed __attribute__((aligned(4))); - -/* Rx PHY descriptor. */ -struct r92c_rx_phystat { - uint32_t phydw0; - uint32_t phydw1; - uint32_t phydw2; - uint32_t phydw3; - uint32_t phydw4; - uint32_t phydw5; - uint32_t phydw6; - uint32_t phydw7; -} __packed __attribute__((aligned(4))); - -/* Rx PHY CCK descriptor. */ -struct r92c_rx_cck { - uint8_t adc_pwdb[4]; - uint8_t sq_rpt; - uint8_t agc_rpt; -} __packed; - -/* Tx MAC descriptor. */ -struct r92c_tx_desc { - uint32_t txdw0; -#define R92C_TXDW0_PKTLEN_M 0x0000ffff -#define R92C_TXDW0_PKTLEN_S 0 -#define R92C_TXDW0_OFFSET_M 0x00ff0000 -#define R92C_TXDW0_OFFSET_S 16 -#define R92C_TXDW0_BMCAST 0x01000000 -#define R92C_TXDW0_LSG 0x04000000 -#define R92C_TXDW0_FSG 0x08000000 -#define R92C_TXDW0_OWN 0x80000000 - - uint32_t txdw1; -#define R92C_TXDW1_MACID_M 0x0000001f -#define R92C_TXDW1_MACID_S 0 -#define R92C_TXDW1_AGGEN 0x00000020 -#define R92C_TXDW1_AGGBK 0x00000040 -#define R92C_TXDW1_QSEL_M 0x00001f00 -#define R92C_TXDW1_QSEL_S 8 -#define R92C_TXDW1_QSEL_BE 0x00 -#define R92C_TXDW1_QSEL_BK 0x02 -#define R92C_TXDW1_QSEL_VI 0x05 -#define R92C_TXDW1_QSEL_VO 0x07 -#define R92C_TXDW1_QSEL_BEACON 0x10 -#define R92C_TXDW1_QSEL_HIGH 0x11 -#define R92C_TXDW1_QSEL_MGNT 0x12 -#define R92C_TXDW1_QSEL_CMD 0x13 -#define R92C_TXDW1_RAID_M 0x000f0000 -#define R92C_TXDW1_RAID_S 16 -#define R92C_TXDW1_CIPHER_M 0x00c00000 -#define R92C_TXDW1_CIPHER_S 22 -#define R92C_TXDW1_CIPHER_NONE 0 -#define R92C_TXDW1_CIPHER_RC4 1 -#define R92C_TXDW1_CIPHER_AES 3 -#define R92C_TXDW1_PKTOFF_M 0x7c000000 -#define R92C_TXDW1_PKTOFF_S 26 - - uint32_t txdw2; - uint16_t txdw3; - uint16_t txdseq; - - uint32_t txdw4; -#define R92C_TXDW4_RTSRATE_M 0x0000003f -#define R92C_TXDW4_RTSRATE_S 0 -#define R92C_TXDW4_QOS 0x00000040 -#define R92C_TXDW4_HWSEQ 0x00000080 -#define R92C_TXDW4_DRVRATE 0x00000100 -#define R92C_TXDW4_CTS2SELF 0x00000800 -#define R92C_TXDW4_RTSEN 0x00001000 -#define R92C_TXDW4_HWRTSEN 0x00002000 -#define R92C_TXDW4_SCO_M 0x003f0000 -#define R92C_TXDW4_SCO_S 20 -#define R92C_TXDW4_SCO_SCA 1 -#define R92C_TXDW4_SCO_SCB 2 -#define R92C_TXDW4_40MHZ 0x02000000 - - uint32_t txdw5; -#define R92C_TXDW5_DATARATE_M 0x0000003f -#define R92C_TXDW5_DATARATE_S 0 -#define R92C_TXDW5_SGI 0x00000040 -#define R92C_TXDW5_DATARATE_FBLIMIT_M 0x00001f00 -#define R92C_TXDW5_DATARATE_FBLIMIT_S 8 -#define R92C_TXDW5_RTSRATE_FBLIMIT_M 0x0001e000 -#define R92C_TXDW5_RTSRATE_FBLIMIT_S 13 -#define R92C_TXDW5_RETRY_LIMIT_ENABLE 0x00020000 -#define R92C_TXDW5_DATA_RETRY_LIMIT_M 0x00fc0000 -#define R92C_TXDW5_DATA_RETRY_LIMIT_S 18 -#define R92C_TXDW5_AGGNUM_M 0xff000000 -#define R92C_TXDW5_AGGNUM_S 24 - - uint32_t txdw6; - - uint16_t txbufsize; - uint16_t pad; - - uint32_t txbufaddr; - uint32_t txbufaddr64; - - uint32_t nextdescaddr; - uint32_t nextdescaddr64; - - uint32_t reserved[4]; -} __packed __attribute__((aligned(4))); - -static const uint8_t ridx2rate[] = - { 2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108 }; - -/* HW rate indices. */ -#define RTWN_RIDX_CCK1 0 -#define RTWN_RIDX_CCK11 3 -#define RTWN_RIDX_OFDM6 4 -#define RTWN_RIDX_OFDM24 8 -#define RTWN_RIDX_OFDM54 11 -#define RTWN_RIDX_MCS0 12 -#define RTWN_RIDX_MCS15 27 - -#define RTWN_RIDX_COUNT 28 -#define RTWN_RIDX_UNKNOWN (uint8_t)-1 - -#define RTWN_RATE_IS_CCK(rate) ((rate) <= RTWN_RIDX_CCK11) -#define RTWN_RATE_IS_OFDM(rate) ((rate) >= RTWN_RIDX_OFDM6 && \ - (rate) <= RTWN_RIDX_OFDM54) - - -/* - * Driver definitions. - */ -#define RTWN_NTXQUEUES 9 -#define RTWN_RX_LIST_COUNT 256 -#define RTWN_TX_LIST_COUNT 256 -#define RTWN_HOST_CMD_RING_COUNT 32 - -/* TX queue indices. */ -#define RTWN_BK_QUEUE 0 -#define RTWN_BE_QUEUE 1 -#define RTWN_VI_QUEUE 2 -#define RTWN_VO_QUEUE 3 -#define RTWN_BEACON_QUEUE 4 -#define RTWN_TXCMD_QUEUE 5 -#define RTWN_MGNT_QUEUE 6 -#define RTWN_HIGH_QUEUE 7 -#define RTWN_HCCA_QUEUE 8 - -/* RX queue indices. */ -#define RTWN_RX_QUEUE 0 - -#define RTWN_RXBUFSZ (16 * 1024) -#define RTWN_TXBUFSZ (sizeof(struct r92c_tx_desc) + IEEE80211_MAX_LEN) - -#define RTWN_TX_TIMEOUT 5000 /* ms */ - -#define RTWN_LED_LINK 0 -#define RTWN_LED_DATA 1 - -struct rtwn_rx_radiotap_header { - struct ieee80211_radiotap_header wr_ihdr; - uint8_t wr_flags; - uint8_t wr_rate; - uint16_t wr_chan_freq; - uint16_t wr_chan_flags; - uint8_t wr_dbm_antsignal; -} __packed; - -#define RTWN_RX_RADIOTAP_PRESENT \ - (1 << IEEE80211_RADIOTAP_FLAGS | \ - 1 << IEEE80211_RADIOTAP_RATE | \ - 1 << IEEE80211_RADIOTAP_CHANNEL | \ - 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) - -struct rtwn_tx_radiotap_header { - struct ieee80211_radiotap_header wt_ihdr; - uint8_t wt_flags; - uint16_t wt_chan_freq; - uint16_t wt_chan_flags; -} __packed; - -#define RTWN_TX_RADIOTAP_PRESENT \ - (1 << IEEE80211_RADIOTAP_FLAGS | \ - 1 << IEEE80211_RADIOTAP_CHANNEL) - -struct rtwn_rx_data { - bus_dmamap_t map; - struct mbuf *m; - bus_addr_t paddr; -}; - -struct rtwn_rx_ring { - struct r92c_rx_desc *desc; - bus_addr_t paddr; - bus_dma_tag_t desc_dmat; - bus_dmamap_t desc_map; - bus_dma_tag_t data_dmat; - bus_dma_segment_t seg; - struct rtwn_rx_data rx_data[RTWN_RX_LIST_COUNT]; - -}; -struct rtwn_tx_data { - bus_dmamap_t map; - struct mbuf *m; - struct ieee80211_node *ni; -}; - -struct rtwn_tx_ring { - bus_addr_t paddr; - bus_dma_tag_t desc_dmat; - bus_dmamap_t desc_map; - bus_dma_tag_t data_dmat; - bus_dma_segment_t seg; - struct r92c_tx_desc *desc; - struct rtwn_tx_data tx_data[RTWN_TX_LIST_COUNT]; - int queued; - int cur; -}; - -struct rtwn_vap { - struct ieee80211vap vap; - int (*newstate)(struct ieee80211vap *, - enum ieee80211_state, int); -}; -#define RTWN_VAP(vap) ((struct rtwn_vap *)(vap)) - -struct rtwn_softc { - device_t sc_dev; - struct mtx sc_mtx; - struct ieee80211com sc_ic; - struct mbufq sc_snd; - - struct resource *irq; - struct resource *mem; - bus_space_tag_t sc_st; - bus_space_handle_t sc_sh; - void *sc_ih; - bus_size_t sc_mapsize; - int sc_cap_off; - - struct callout calib_to; - struct callout watchdog_to; - - int sc_debug; - - u_int sc_flags; -#define RTWN_FLAG_CCK_HIPWR 0x01 -#define RTWN_FLAG_BUSY 0x02 -#define RTWN_RUNNING 0x04 - - u_int chip; -#define RTWN_CHIP_88C 0x00 -#define RTWN_CHIP_92C 0x01 -#define RTWN_CHIP_92C_1T2R 0x02 -#define RTWN_CHIP_UMC 0x04 -#define RTWN_CHIP_UMC_A_CUT 0x08 - - uint8_t board_type; - uint8_t regulatory; - uint8_t pa_setting; - int avg_pwdb; - int thcal_state; - int thcal_lctemp; - int ntxchains; - int nrxchains; - int ledlink; - - int sc_tx_timer; - int fwcur; - struct rtwn_rx_ring rx_ring; - struct rtwn_tx_ring tx_ring[RTWN_NTXQUEUES]; - uint32_t qfullmsk; - struct r92c_rom rom; - - uint32_t rf_chnlbw[R92C_MAX_CHAINS]; - - struct rtwn_rx_radiotap_header sc_rxtap; - struct rtwn_tx_radiotap_header sc_txtap; - -#ifdef __HAIKU__ - uint32_t sc_intr_status; -#endif -}; - -/* - * MAC initialization values. - */ -static const struct { +struct rtwn_mac_prog { uint16_t reg; uint8_t val; -} rtl8192ce_mac[] = { - { 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 }, - { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 }, - { 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 }, - { 0x43a, 0x00 }, { 0x43b, 0x01 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, - { 0x43e, 0x06 }, { 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 }, - { 0x442, 0x00 }, { 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f }, - { 0x447, 0x00 }, { 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 }, - { 0x45b, 0xb9 }, { 0x460, 0x88 }, { 0x461, 0x88 }, { 0x462, 0x06 }, - { 0x463, 0x03 }, { 0x4c8, 0x04 }, { 0x4c9, 0x08 }, { 0x4cc, 0x02 }, - { 0x4cd, 0x28 }, { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, - { 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, - { 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, - { 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, - { 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, - { 0x515, 0x10 }, { 0x516, 0x0a }, { 0x517, 0x10 }, { 0x51a, 0x16 }, - { 0x524, 0x0f }, { 0x525, 0x4f }, { 0x546, 0x20 }, { 0x547, 0x00 }, - { 0x559, 0x02 }, { 0x55a, 0x02 }, { 0x55d, 0xff }, { 0x605, 0x30 }, - { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x652, 0x20 }, { 0x63c, 0x0a }, - { 0x63d, 0x0e }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 }, - { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 }, - { 0x70b, 0x87 } }; /* - * Baseband initialization values. + * Structure for baseband initialization values. */ struct rtwn_bb_prog { int count; - const uint16_t *regs; - const uint32_t *vals; - int agccount; - const uint32_t *agcvals; + const uint16_t *reg; + const uint32_t *val; + const uint8_t cond[RTWN_MAX_CONDITIONS]; + const struct rtwn_bb_prog *next; +}; + +struct rtwn_agc_prog { + int count; + const uint32_t *val; + const uint8_t cond[RTWN_MAX_CONDITIONS]; + const struct rtwn_agc_prog *next; }; /* - * RTL8192CU and RTL8192CE-VAU. - */ -static const uint16_t rtl8192ce_bb_regs[] = { - 0x024, 0x028, 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, - 0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, - 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, - 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884, - 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, 0x908, - 0x90c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, - 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04, 0xc08, - 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, - 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, - 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, - 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, 0xc98, - 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, 0xcbc, - 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc, 0xce0, - 0xce4, 0xce8, 0xcec, 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10, 0xd14, - 0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, 0xd48, - 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, 0xd6c, - 0xd70, 0xd74, 0xd78, 0xe00, 0xe04, 0xe08, 0xe10, 0xe14, 0xe18, - 0xe1c, 0xe28, 0xe30, 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, 0xe48, - 0xe4c, 0xe50, 0xe54, 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c, 0xe70, - 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0, 0xed4, - 0xed8, 0xedc, 0xee0, 0xeec, 0xf14, 0xf4c, 0xf00 -}; - -static const uint32_t rtl8192ce_bb_vals_2t[] = { - 0x0011800f, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00, - 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, - 0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727, - 0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000, - 0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a, - 0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27, - 0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070, - 0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe, - 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, - 0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, - 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, - 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, - 0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000, - 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, - 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, - 0x69543420, 0x43bc0094, 0x69543420, 0x433c0094, 0x00000000, - 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d, 0x018610db, - 0x0000001f, 0x00b91612, 0x40000100, 0x20f60000, 0x40000100, - 0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, - 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, - 0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, - 0x00080740, 0x00020403, 0x0000907f, 0x20010201, 0xa0633333, - 0x3333bc43, 0x7a8f5b6b, 0xcc979975, 0x00000000, 0x80608000, - 0x00000000, 0x00027293, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x6437140a, 0x00000000, 0x00000000, 0x30032064, - 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, - 0x322c2220, 0x000e3c24, 0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, - 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, - 0x1000dc1f, 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, - 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, - 0x02140102, 0x28160d05, 0x00000010, 0x001b25a4, 0x63db25a4, - 0x63db25a4, 0x0c1b25a4, 0x0c1b25a4, 0x0c1b25a4, 0x0c1b25a4, - 0x63db25a4, 0x0c1b25a4, 0x63db25a4, 0x63db25a4, 0x63db25a4, - 0x63db25a4, 0x001b25a4, 0x001b25a4, 0x6fdb25a4, 0x00000003, - 0x00000000, 0x00000300 -}; - -static const uint32_t rtl8192ce_bb_vals_1t[] = { - 0x0011800f, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00, - 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, - 0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a, - 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200, - 0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070, - 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe, - 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, - 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, - 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, - 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, - 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, - 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, - 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, - 0x69543420, 0x43bc0094, 0x69543420, 0x433c0094, 0x00000000, - 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d, 0x018610db, - 0x0000001f, 0x00b91612, 0x40000100, 0x20f60000, 0x40000100, - 0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, - 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, - 0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, - 0x00080740, 0x00020401, 0x0000907f, 0x20010201, 0xa0633333, - 0x3333bc43, 0x7a8f5b6b, 0xcc979975, 0x00000000, 0x80608000, - 0x00000000, 0x00027293, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x6437140a, 0x00000000, 0x00000000, 0x30032064, - 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, - 0x322c2220, 0x000e3c24, 0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, - 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, - 0x1000dc1f, 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, - 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, - 0x02140102, 0x28160d05, 0x00000010, 0x001b25a4, 0x631b25a0, - 0x631b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, - 0x631b25a0, 0x081b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, - 0x631b25a0, 0x001b25a0, 0x001b25a0, 0x6b1b25a0, 0x00000003, - 0x00000000, 0x00000300, -}; - -static const uint32_t rtl8192ce_agc_vals[] = { - 0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001, - 0x7b050001, 0x7a060001, 0x79070001, 0x78080001, 0x77090001, - 0x760a0001, 0x750b0001, 0x740c0001, 0x730d0001, 0x720e0001, - 0x710f0001, 0x70100001, 0x6f110001, 0x6e120001, 0x6d130001, - 0x6c140001, 0x6b150001, 0x6a160001, 0x69170001, 0x68180001, - 0x67190001, 0x661a0001, 0x651b0001, 0x641c0001, 0x631d0001, - 0x621e0001, 0x611f0001, 0x60200001, 0x49210001, 0x48220001, - 0x47230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001, - 0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001, - 0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001, - 0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001, - 0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001, - 0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001, - 0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001, - 0x7a460001, 0x79470001, 0x78480001, 0x77490001, 0x764a0001, - 0x754b0001, 0x744c0001, 0x734d0001, 0x724e0001, 0x714f0001, - 0x70500001, 0x6f510001, 0x6e520001, 0x6d530001, 0x6c540001, - 0x6b550001, 0x6a560001, 0x69570001, 0x68580001, 0x67590001, - 0x665a0001, 0x655b0001, 0x645c0001, 0x635d0001, 0x625e0001, - 0x615f0001, 0x60600001, 0x49610001, 0x48620001, 0x47630001, - 0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001, - 0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001, - 0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001, - 0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001, - 0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001, - 0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e, - 0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e, - 0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e, - 0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e, - 0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e, - 0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e, - 0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e -}; - -static const struct rtwn_bb_prog rtl8192ce_bb_prog_2t = { - nitems(rtl8192ce_bb_regs), - rtl8192ce_bb_regs, - rtl8192ce_bb_vals_2t, - nitems(rtl8192ce_agc_vals), - rtl8192ce_agc_vals -}; - -static const struct rtwn_bb_prog rtl8192ce_bb_prog_1t = { - nitems(rtl8192ce_bb_regs), - rtl8192ce_bb_regs, - rtl8192ce_bb_vals_1t, - nitems(rtl8192ce_agc_vals), - rtl8192ce_agc_vals -}; - -/* - * RTL8188CU. - */ -static const uint32_t rtl8192cu_bb_vals[] = { - 0x0011800d, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00, - 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, - 0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727, - 0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000, - 0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a, - 0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27, - 0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070, - 0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe, - 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, - 0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, - 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, - 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, - 0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000, - 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, - 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, - 0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000, - 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d, 0x0186115b, - 0x0000001f, 0x00b99612, 0x40000100, 0x20f60000, 0x40000100, - 0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, - 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, - 0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, - 0x00080740, 0x00020403, 0x0000907f, 0x20010201, 0xa0633333, - 0x3333bc43, 0x7a8f5b6b, 0xcc979975, 0x00000000, 0x80608000, - 0x00000000, 0x00027293, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x6437140a, 0x00000000, 0x00000000, 0x30032064, - 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, - 0x322c2220, 0x000e3c24, 0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, - 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, - 0x1000dc1f, 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, - 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, - 0x02140102, 0x28160d05, 0x00000010, 0x001b25a4, 0x63db25a4, - 0x63db25a4, 0x0c1b25a4, 0x0c1b25a4, 0x0c1b25a4, 0x0c1b25a4, - 0x63db25a4, 0x0c1b25a4, 0x63db25a4, 0x63db25a4, 0x63db25a4, - 0x63db25a4, 0x001b25a4, 0x001b25a4, 0x6fdb25a4, 0x00000003, - 0x00000000, 0x00000300 -}; - -static const struct rtwn_bb_prog rtl8192cu_bb_prog = { - nitems(rtl8192ce_bb_regs), - rtl8192ce_bb_regs, - rtl8192cu_bb_vals, - nitems(rtl8192ce_agc_vals), - rtl8192ce_agc_vals -}; - -/* - * RTL8188CE-VAU. - */ -static const uint32_t rtl8188ce_bb_vals[] = { - 0x0011800d, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00, - 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, - 0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a, - 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200, - 0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070, - 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe, - 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, - 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, - 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, - 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, - 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, - 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, - 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, - 0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000, - 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d, 0x018610db, - 0x0000001f, 0x00b91612, 0x40000100, 0x20f60000, 0x40000100, - 0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, - 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, - 0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, - 0x00080740, 0x00020401, 0x0000907f, 0x20010201, 0xa0633333, - 0x3333bc43, 0x7a8f5b6b, 0xcc979975, 0x00000000, 0x80608000, - 0x00000000, 0x00027293, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x6437140a, 0x00000000, 0x00000000, 0x30032064, - 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, - 0x322c2220, 0x000e3c24, 0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, - 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, - 0x1000dc1f, 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, - 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, - 0x02140102, 0x28160d05, 0x00000008, 0x001b25a4, 0x631b25a0, - 0x631b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, - 0x631b25a0, 0x081b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, - 0x631b25a0, 0x001b25a0, 0x001b25a0, 0x6b1b25a0, 0x00000003, - 0x00000000, 0x00000300 -}; - -static const uint32_t rtl8188ce_agc_vals[] = { - 0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001, - 0x7b050001, 0x7a060001, 0x79070001, 0x78080001, 0x77090001, - 0x760a0001, 0x750b0001, 0x740c0001, 0x730d0001, 0x720e0001, - 0x710f0001, 0x70100001, 0x6f110001, 0x6e120001, 0x6d130001, - 0x6c140001, 0x6b150001, 0x6a160001, 0x69170001, 0x68180001, - 0x67190001, 0x661a0001, 0x651b0001, 0x641c0001, 0x631d0001, - 0x621e0001, 0x611f0001, 0x60200001, 0x49210001, 0x48220001, - 0x47230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001, - 0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001, - 0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001, - 0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001, - 0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001, - 0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001, - 0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001, - 0x7a460001, 0x79470001, 0x78480001, 0x77490001, 0x764a0001, - 0x754b0001, 0x744c0001, 0x734d0001, 0x724e0001, 0x714f0001, - 0x70500001, 0x6f510001, 0x6e520001, 0x6d530001, 0x6c540001, - 0x6b550001, 0x6a560001, 0x69570001, 0x68580001, 0x67590001, - 0x665a0001, 0x655b0001, 0x645c0001, 0x635d0001, 0x625e0001, - 0x615f0001, 0x60600001, 0x49610001, 0x48620001, 0x47630001, - 0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001, - 0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001, - 0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001, - 0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001, - 0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001, - 0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e, - 0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e, - 0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e, - 0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e, - 0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e, - 0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e, - 0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e -}; - -static const struct rtwn_bb_prog rtl8188ce_bb_prog = { - nitems(rtl8192ce_bb_regs), - rtl8192ce_bb_regs, - rtl8188ce_bb_vals, - nitems(rtl8188ce_agc_vals), - rtl8188ce_agc_vals -}; - -static const uint32_t rtl8188cu_bb_vals[] = { - 0x0011800d, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00, - 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, - 0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a, - 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200, - 0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070, - 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe, - 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, - 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, - 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, - 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, - 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, - 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, - 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, - 0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000, - 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d, 0x018610db, - 0x0000001f, 0x00b91612, 0x40000100, 0x20f60000, 0x40000100, - 0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, - 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, - 0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, - 0x00080740, 0x00020401, 0x0000907f, 0x20010201, 0xa0633333, - 0x3333bc43, 0x7a8f5b6b, 0xcc979975, 0x00000000, 0x80608000, - 0x00000000, 0x00027293, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x6437140a, 0x00000000, 0x00000000, 0x30032064, - 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, - 0x322c2220, 0x000e3c24, 0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, - 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, - 0x1000dc1f, 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, - 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, - 0x02140102, 0x28160d05, 0x00000008, 0x001b25a4, 0x631b25a0, - 0x631b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, - 0x631b25a0, 0x081b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, - 0x631b25a0, 0x001b25a0, 0x001b25a0, 0x6b1b25a0, 0x00000003, - 0x00000000, 0x00000300 -}; - -static const struct rtwn_bb_prog rtl8188cu_bb_prog = { - nitems(rtl8192ce_bb_regs), - rtl8192ce_bb_regs, - rtl8188cu_bb_vals, - nitems(rtl8188ce_agc_vals), - rtl8188ce_agc_vals -}; - -/* - * RTL8188RU. - */ -static const uint16_t rtl8188ru_bb_regs[] = { - 0x024, 0x028, 0x040, 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, - 0x818, 0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, - 0x83c, 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, - 0x860, 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, - 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, - 0x908, 0x90c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, - 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04, - 0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, - 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, - 0xc50, 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, - 0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, - 0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, - 0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc, - 0xce0, 0xce4, 0xce8, 0xcec, 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10, - 0xd14, 0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, - 0xd48, 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, - 0xd6c, 0xd70, 0xd74, 0xd78, 0xe00, 0xe04, 0xe08, 0xe10, 0xe14, - 0xe18, 0xe1c, 0xe28, 0xe30, 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, - 0xe48, 0xe4c, 0xe50, 0xe54, 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c, - 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0, - 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xee8, 0xf14, 0xf4c, 0xf00 -}; - -static const uint32_t rtl8188ru_bb_vals[] = { - 0x0011800d, 0x00ffdb83, 0x000c0004, 0x80040000, 0x00000001, - 0x0000fc00, 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, - 0x00000000, 0x01000100, 0x00390204, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x569a569a, 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, - 0x32323200, 0x03000300, 0x22004000, 0x00000808, 0x00ffc3f1, - 0xc0083070, 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, - 0xfffffffe, 0x40302010, 0x00706050, 0x00000000, 0x00000023, - 0x00000000, 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, - 0x2e68120f, 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, - 0x15160000, 0x070b0f12, 0x00000104, 0x00d30000, 0x101fbf00, - 0x00000007, 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, - 0x08800000, 0x40000100, 0x08800000, 0x40000100, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, - 0x49795994, 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, - 0x007f037f, 0x6954342e, 0x43bc0094, 0x6954342f, 0x433c0094, - 0x00000000, 0x5116848b, 0x47c00bff, 0x00000036, 0x2c56000d, - 0x018610db, 0x0000001f, 0x00b91612, 0x24000090, 0x20f60000, - 0x24000090, 0x20200000, 0x00121820, 0x00000000, 0x00121820, - 0x00007f7f, 0x00000000, 0x00000080, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x28000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x64b22427, 0x00766932, 0x00222222, 0x00000000, 0x37644302, - 0x2f97d40c, 0x00080740, 0x00020401, 0x0000907f, 0x20010201, - 0xa0633333, 0x3333bc43, 0x7a8f5b6b, 0xcc979975, 0x00000000, - 0x80608000, 0x00000000, 0x00027293, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x6437140a, 0x00000000, 0x00000000, - 0x30032064, 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, - 0x1812362e, 0x322c2220, 0x000e3c24, 0x2a2a2a2a, 0x2a2a2a2a, - 0x03902a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, - 0x00000000, 0x1000dc1f, 0x10008c1f, 0x02140102, 0x681604c2, - 0x01007c00, 0x01004800, 0xfb000000, 0x000028d1, 0x1000dc1f, - 0x10008c1f, 0x02140102, 0x28160d05, 0x00000010, 0x001b25a4, - 0x631b25a0, 0x631b25a0, 0x081b25a0, 0x081b25a0, 0x081b25a0, - 0x081b25a0, 0x631b25a0, 0x081b25a0, 0x631b25a0, 0x631b25a0, - 0x631b25a0, 0x631b25a0, 0x001b25a0, 0x001b25a0, 0x6b1b25a0, - 0x31555448, 0x00000003, 0x00000000, 0x00000300 -}; - -static const uint32_t rtl8188ru_agc_vals[] = { - 0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001, - 0x7b050001, 0x7b060001, 0x7b070001, 0x7b080001, 0x7a090001, - 0x790a0001, 0x780b0001, 0x770c0001, 0x760d0001, 0x750e0001, - 0x740f0001, 0x73100001, 0x72110001, 0x71120001, 0x70130001, - 0x6f140001, 0x6e150001, 0x6d160001, 0x6c170001, 0x6b180001, - 0x6a190001, 0x691a0001, 0x681b0001, 0x671c0001, 0x661d0001, - 0x651e0001, 0x641f0001, 0x63200001, 0x62210001, 0x61220001, - 0x60230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001, - 0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001, - 0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001, - 0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001, - 0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001, - 0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001, - 0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001, - 0x7b460001, 0x7b470001, 0x7b480001, 0x7a490001, 0x794a0001, - 0x784b0001, 0x774c0001, 0x764d0001, 0x754e0001, 0x744f0001, - 0x73500001, 0x72510001, 0x71520001, 0x70530001, 0x6f540001, - 0x6e550001, 0x6d560001, 0x6c570001, 0x6b580001, 0x6a590001, - 0x695a0001, 0x685b0001, 0x675c0001, 0x665d0001, 0x655e0001, - 0x645f0001, 0x63600001, 0x62610001, 0x61620001, 0x60630001, - 0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001, - 0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001, - 0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001, - 0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001, - 0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001, - 0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e, - 0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e, - 0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e, - 0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e, - 0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e, - 0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e, - 0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e -}; - -static const struct rtwn_bb_prog rtl8188ru_bb_prog = { - nitems(rtl8188ru_bb_regs), - rtl8188ru_bb_regs, - rtl8188ru_bb_vals, - nitems(rtl8188ru_agc_vals), - rtl8188ru_agc_vals -}; - -/* - * RF initialization values. + * Structure for RF initialization values. */ struct rtwn_rf_prog { int count; - const uint8_t *regs; - const uint32_t *vals; -}; - -/* - * RTL8192CU and RTL8192CE-VAU. - */ -static const uint8_t rtl8192ce_rf1_regs[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, - 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2a, 0x2b, - 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, - 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, - 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, - 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, - 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, - 0x2c, 0x2a, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, - 0x11, 0x10, 0x11, 0x10, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, - 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x00, - 0x18, 0xfe, 0xfe, 0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00 -}; - -static const uint32_t rtl8192ce_rf1_vals[] = { - 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb1, - 0x54867, 0x8992e, 0x0e52c, 0x39ce7, 0x00451, 0x00000, 0x10255, - 0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000, - 0x00000, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x577c0, - 0x04783, 0x00001, 0x21334, 0x00000, 0x00054, 0x00001, 0x00808, - 0x53333, 0x0000c, 0x00002, 0x00808, 0x5b333, 0x0000d, 0x00003, - 0x00808, 0x63333, 0x0000d, 0x00004, 0x00808, 0x6b333, 0x0000d, - 0x00005, 0x00808, 0x73333, 0x0000d, 0x00006, 0x00709, 0x5b333, - 0x0000d, 0x00007, 0x00709, 0x63333, 0x0000d, 0x00008, 0x0060a, - 0x4b333, 0x0000d, 0x00009, 0x0060a, 0x53333, 0x0000d, 0x0000a, - 0x0060a, 0x5b333, 0x0000d, 0x0000b, 0x0060a, 0x63333, 0x0000d, - 0x0000c, 0x0060a, 0x6b333, 0x0000d, 0x0000d, 0x0060a, 0x73333, - 0x0000d, 0x0000e, 0x0050b, 0x66666, 0x0001a, 0xe0000, 0x4000f, - 0xe31fc, 0x6000f, 0xff9f8, 0x2000f, 0x203f9, 0x3000f, 0xff500, - 0x00000, 0x00000, 0x8000f, 0x3f100, 0x9000f, 0x23100, 0x32000, - 0x71000, 0xb0000, 0xfc000, 0x287af, 0x244b7, 0x204ab, 0x1c49f, - 0x18493, 0x14297, 0x10295, 0x0c298, 0x0819c, 0x040a8, 0x0001c, - 0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f424, 0x4f424, 0x8f424, - 0xcf424, 0xe0330, 0xa0330, 0x60330, 0x20330, 0x10159, 0x0f401, - 0x00000, 0x00000, 0x80003, 0x00000, 0x00000, 0x44457, 0x80000, - 0x30159 -}; - -static const uint8_t rtl8192ce_rf2_regs[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, - 0x0f, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, - 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, - 0x15, 0x15, 0x16, 0x16, 0x16, 0x16 -}; - -static const uint32_t rtl8192ce_rf2_vals[] = { - 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb1, - 0x54867, 0x8992e, 0x0e52c, 0x39ce7, 0x00451, 0x32000, 0x71000, - 0xb0000, 0xfc000, 0x287af, 0x244b7, 0x204ab, 0x1c49f, 0x18493, - 0x14297, 0x10295, 0x0c298, 0x0819c, 0x040a8, 0x0001c, 0x1944c, - 0x59444, 0x9944c, 0xd9444, 0x0f424, 0x4f424, 0x8f424, 0xcf424, - 0xe0330, 0xa0330, 0x60330, 0x20330 -}; - -static const struct rtwn_rf_prog rtl8192ce_rf_prog[] = { - { - nitems(rtl8192ce_rf1_regs), - rtl8192ce_rf1_regs, - rtl8192ce_rf1_vals - }, - { - nitems(rtl8192ce_rf2_regs), - rtl8192ce_rf2_regs, - rtl8192ce_rf2_vals - } -}; - -/* - * RTL8188CE-VAU. - */ -static const uint32_t rtl8188ce_rf_vals[] = { - 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb1, - 0x54867, 0x8992e, 0x0e52c, 0x39ce7, 0x00451, 0x00000, 0x10255, - 0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000, - 0x00000, 0x01558, 0x00060, 0x00483, 0x4f200, 0xec7d9, 0x577c0, - 0x04783, 0x00001, 0x21334, 0x00000, 0x00054, 0x00001, 0x00808, - 0x53333, 0x0000c, 0x00002, 0x00808, 0x5b333, 0x0000d, 0x00003, - 0x00808, 0x63333, 0x0000d, 0x00004, 0x00808, 0x6b333, 0x0000d, - 0x00005, 0x00808, 0x73333, 0x0000d, 0x00006, 0x00709, 0x5b333, - 0x0000d, 0x00007, 0x00709, 0x63333, 0x0000d, 0x00008, 0x0060a, - 0x4b333, 0x0000d, 0x00009, 0x0060a, 0x53333, 0x0000d, 0x0000a, - 0x0060a, 0x5b333, 0x0000d, 0x0000b, 0x0060a, 0x63333, 0x0000d, - 0x0000c, 0x0060a, 0x6b333, 0x0000d, 0x0000d, 0x0060a, 0x73333, - 0x0000d, 0x0000e, 0x0050b, 0x66666, 0x0001a, 0xe0000, 0x4000f, - 0xe31fc, 0x6000f, 0xff9f8, 0x2000f, 0x203f9, 0x3000f, 0xff500, - 0x00000, 0x00000, 0x8000f, 0x3f100, 0x9000f, 0x23100, 0x32000, - 0x71000, 0xb0000, 0xfc000, 0x287b3, 0x244b7, 0x204ab, 0x1c49f, - 0x18493, 0x1429b, 0x10299, 0x0c29c, 0x081a0, 0x040ac, 0x00020, - 0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f424, 0x4f424, 0x8f424, - 0xcf424, 0xe0330, 0xa0330, 0x60330, 0x20330, 0x10159, 0x0f401, - 0x00000, 0x00000, 0x80003, 0x00000, 0x00000, 0x44457, 0x80000, - 0x30159 -}; - -static const struct rtwn_rf_prog rtl8188ce_rf_prog[] = { - { - nitems(rtl8192ce_rf1_regs), - rtl8192ce_rf1_regs, - rtl8188ce_rf_vals - } + const uint8_t *reg; + const uint32_t *val; + const uint8_t cond[RTWN_MAX_CONDITIONS]; + const struct rtwn_rf_prog *next; }; -/* - * RTL8188CU. - */ -static const uint32_t rtl8188cu_rf_vals[] = { - 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb1, - 0x54867, 0x8992e, 0x0e52c, 0x39ce7, 0x00451, 0x00000, 0x10255, - 0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000, - 0x00000, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x577c0, - 0x04783, 0x00001, 0x21334, 0x00000, 0x00054, 0x00001, 0x00808, - 0x53333, 0x0000c, 0x00002, 0x00808, 0x5b333, 0x0000d, 0x00003, - 0x00808, 0x63333, 0x0000d, 0x00004, 0x00808, 0x6b333, 0x0000d, - 0x00005, 0x00808, 0x73333, 0x0000d, 0x00006, 0x00709, 0x5b333, - 0x0000d, 0x00007, 0x00709, 0x63333, 0x0000d, 0x00008, 0x0060a, - 0x4b333, 0x0000d, 0x00009, 0x0060a, 0x53333, 0x0000d, 0x0000a, - 0x0060a, 0x5b333, 0x0000d, 0x0000b, 0x0060a, 0x63333, 0x0000d, - 0x0000c, 0x0060a, 0x6b333, 0x0000d, 0x0000d, 0x0060a, 0x73333, - 0x0000d, 0x0000e, 0x0050b, 0x66666, 0x0001a, 0xe0000, 0x4000f, - 0xe31fc, 0x6000f, 0xff9f8, 0x2000f, 0x203f9, 0x3000f, 0xff500, - 0x00000, 0x00000, 0x8000f, 0x3f100, 0x9000f, 0x23100, 0x32000, - 0x71000, 0xb0000, 0xfc000, 0x287b3, 0x244b7, 0x204ab, 0x1c49f, - 0x18493, 0x1429b, 0x10299, 0x0c29c, 0x081a0, 0x040ac, 0x00020, - 0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f405, 0x4f405, 0x8f405, - 0xcf405, 0xe0330, 0xa0330, 0x60330, 0x20330, 0x10159, 0x0f401, - 0x00000, 0x00000, 0x80003, 0x00000, 0x00000, 0x44457, 0x80000, - 0x30159 -}; +/* XXX move to net80211. */ +static __inline int +rtwn_chan2centieee(const struct ieee80211_channel *c) +{ + int chan; -static const struct rtwn_rf_prog rtl8188cu_rf_prog[] = { - { - nitems(rtl8192ce_rf1_regs), - rtl8192ce_rf1_regs, - rtl8188cu_rf_vals - } -}; + chan = c->ic_ieee; + if (c->ic_extieee != 0) + chan = (chan + c->ic_extieee) / 2; -/* - * RTL8188RU. - */ -static const uint32_t rtl8188ru_rf_vals[] = { - 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb0, - 0x54867, 0x8992e, 0x0e529, 0x39ce7, 0x00451, 0x00000, 0x00255, - 0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000, - 0x0083c, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x977c0, - 0x04783, 0x00001, 0x21334, 0x00000, 0x00054, 0x00001, 0x00808, - 0x53333, 0x0000c, 0x00002, 0x00808, 0x5b333, 0x0000d, 0x00003, - 0x00808, 0x63333, 0x0000d, 0x00004, 0x00808, 0x6b333, 0x0000d, - 0x00005, 0x00808, 0x73333, 0x0000d, 0x00006, 0x00709, 0x5b333, - 0x0000d, 0x00007, 0x00709, 0x63333, 0x0000d, 0x00008, 0x0060a, - 0x4b333, 0x0000d, 0x00009, 0x0060a, 0x53333, 0x0000d, 0x0000a, - 0x0060a, 0x5b333, 0x0000d, 0x0000b, 0x0060a, 0x63333, 0x0000d, - 0x0000c, 0x0060a, 0x6b333, 0x0000d, 0x0000d, 0x0060a, 0x73333, - 0x0000d, 0x0000e, 0x0050b, 0x66666, 0x0001a, 0xe0000, 0x4000f, - 0xe31fc, 0x6000f, 0xff9f8, 0x2000f, 0x203f9, 0x3000f, 0xff500, - 0x00000, 0x00000, 0x8000f, 0x3f100, 0x9000f, 0x23100, 0xd8000, - 0x90000, 0x51000, 0x12000, 0x28fb4, 0x24fa8, 0x207a4, 0x1c798, - 0x183a4, 0x14398, 0x101a4, 0x0c198, 0x080a4, 0x04098, 0x00014, - 0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f405, 0x4f405, 0x8f405, - 0xcf405, 0xe0330, 0xa0330, 0x60330, 0x20330, 0x10159, 0x0f401, - 0x00000, 0x00000, 0x80003, 0x00000, 0x00000, 0x44457, 0x80000, - 0x30159 -}; - -static const struct rtwn_rf_prog rtl8188ru_rf_prog[] = { - { - nitems(rtl8192ce_rf1_regs), - rtl8192ce_rf1_regs, - rtl8188ru_rf_vals - } -}; - -struct rtwn_txpwr { - uint8_t pwr[3][28]; -}; - -/* - * Per RF chain/group/rate Tx gain values. - */ -static const struct rtwn_txpwr rtl8192cu_txagc[] = { - { { /* Chain 0. */ - { /* Group 0. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x0c, 0x0c, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, /* OFDM6~54. */ - 0x0e, 0x0d, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, /* MCS0~7. */ - 0x0e, 0x0d, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02 /* MCS8~15. */ - }, - { /* Group 1. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - }, - { /* Group 2. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - } - } }, - { { /* Chain 1. */ - { /* Group 0. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - }, - { /* Group 1. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - }, - { /* Group 2. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - } - } } -}; - -static const struct rtwn_txpwr rtl8188ru_txagc[] = { - { { /* Chain 0. */ - { /* Group 0. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x08, 0x08, 0x08, 0x06, 0x06, 0x04, 0x04, 0x00, /* OFDM6~54. */ - 0x08, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00, /* MCS0~7. */ - 0x08, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00 /* MCS8~15. */ - }, - { /* Group 1. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - }, - { /* Group 2. */ - 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ - } - } } -}; - -#define RTWN_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ - MTX_NETWORK_LOCK, MTX_DEF) -#define RTWN_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define RTWN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) -#define RTWN_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define RTWN_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) + return (chan); +} +#endif /* IF_RTWNREG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h new file mode 100644 index 0000000000..f57af43ab9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/if_rtwnvar.h @@ -0,0 +1,635 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/if_rtwnvar.h 320640 2017-07-04 07:07:08Z avos $ + */ + +#ifndef IF_RTWNVAR_H +#define IF_RTWNVAR_H + +#define RTWN_TX_DESC_SIZE 64 + +#define RTWN_BCN_MAX_SIZE 512 +#define RTWN_CAM_ENTRY_LIMIT 64 + +#define RTWN_MACID_BC 1 /* Broadcast. */ +#define RTWN_MACID_UNDEFINED 0x7fff +#define RTWN_MACID_VALID 0x8000 +#define RTWN_MACID_LIMIT 128 + +#define RTWN_TX_TIMEOUT 5000 /* ms */ +#define RTWN_MAX_EPOUT 4 +#define RTWN_PORT_COUNT 2 + +#define RTWN_LED_LINK 0 +#define RTWN_LED_DATA 1 + +struct rtwn_rx_radiotap_header { + struct ieee80211_radiotap_header wr_ihdr; + uint64_t wr_tsft; + uint8_t wr_flags; + uint8_t wr_rate; + uint16_t wr_chan_freq; + uint16_t wr_chan_flags; + int8_t wr_dbm_antsignal; + int8_t wr_dbm_antnoise; +} __packed __aligned(8); + +#define RTWN_RX_RADIOTAP_PRESENT \ + (1 << IEEE80211_RADIOTAP_TSFT | \ + 1 << IEEE80211_RADIOTAP_FLAGS | \ + 1 << IEEE80211_RADIOTAP_RATE | \ + 1 << IEEE80211_RADIOTAP_CHANNEL | \ + 1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL | \ + 1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) + +struct rtwn_tx_radiotap_header { + struct ieee80211_radiotap_header wt_ihdr; + uint8_t wt_flags; + uint16_t wt_chan_freq; + uint16_t wt_chan_flags; +} __packed __aligned(8); + +#define RTWN_TX_RADIOTAP_PRESENT \ + (1 << IEEE80211_RADIOTAP_FLAGS | \ + 1 << IEEE80211_RADIOTAP_CHANNEL) + +struct rtwn_tx_buf { + uint8_t txd[RTWN_TX_DESC_SIZE]; +} __attribute__((aligned(4))); + +#define RTWN_PHY_STATUS_SIZE 32 +struct rtwn_tx_phystat { + uint32_t phydw[RTWN_PHY_STATUS_SIZE / sizeof(uint32_t)]; +}; + + +struct rtwn_softc; + +union sec_param { + struct ieee80211_key key; + int macid; +}; + +#define CMD_FUNC_PROTO void (*func)(struct rtwn_softc *, \ + union sec_param *) + +struct rtwn_cmdq { + union sec_param data; + CMD_FUNC_PROTO; +}; +#define RTWN_CMDQ_SIZE 16 + +struct rtwn_node { + struct ieee80211_node ni; /* must be the first */ + int id; + + struct rtwn_tx_phystat last_physt; + int avg_pwdb; +}; +#define RTWN_NODE(ni) ((struct rtwn_node *)(ni)) + +struct rtwn_vap { + struct ieee80211vap vap; + int id; +#define RTWN_VAP_ID_INVALID -1 + int curr_mode; + + struct rtwn_tx_buf bcn_desc; + struct mbuf *bcn_mbuf; + struct timeout_task tx_beacon_csa; + + struct callout tsf_sync_adhoc; + struct task tsf_sync_adhoc_task; + + const struct ieee80211_key *keys[IEEE80211_WEP_NKID]; + + int (*newstate)(struct ieee80211vap *, + enum ieee80211_state, int); + void (*recv_mgmt)(struct ieee80211_node *, + struct mbuf *, int, + const struct ieee80211_rx_stats *, + int, int); +}; +#define RTWN_VAP(vap) ((struct rtwn_vap *)(vap)) + +/* + * Rx data types. + */ +enum { + RTWN_RX_DATA, + RTWN_RX_TX_REPORT, + RTWN_RX_OTHER +}; + +/* + * Firmware reset reasons. + */ +enum { + RTWN_FW_RESET_DOWNLOAD, + RTWN_FW_RESET_CHECKSUM, + RTWN_FW_RESET_SHUTDOWN +}; + +/* + * Rate control algorithm selection. + */ +enum { + RTWN_RATECTL_NONE, + RTWN_RATECTL_NET80211, + RTWN_RATECTL_FW, + RTWN_RATECTL_MAX +}; + +/* + * Control h/w crypto usage. + */ +enum { + RTWN_CRYPTO_SW, + RTWN_CRYPTO_PAIR, + RTWN_CRYPTO_FULL, + RTWN_CRYPTO_MAX, +}; + +struct rtwn_softc { + struct ieee80211com sc_ic; + struct mbufq sc_snd; + device_t sc_dev; + +#if 1 + int sc_ht40; +#endif + uint32_t sc_debug; + int sc_hwcrypto; + int sc_ratectl_sysctl; + int sc_ratectl; + + uint8_t sc_detached; + uint8_t sc_flags; +/* Device flags */ +#define RTWN_FLAG_CCK_HIPWR 0x01 +#define RTWN_FLAG_EXT_HDR 0x02 +#define RTWN_FLAG_CAM_FIXED 0x04 +/* Driver state */ +#define RTWN_STARTED 0x08 +#define RTWN_RUNNING 0x10 +#define RTWN_FW_LOADED 0x20 +#define RTWN_TEMP_MEASURED 0x40 +#define RTWN_RCR_LOCKED 0x80 + +#define RTWN_CHIP_HAS_BCNQ1(_sc) \ + ((_sc)->bcn_status_reg[0] != (_sc)->bcn_status_reg[1]) + + void *sc_priv; + const char *name; + int sc_ant; + + struct rtwn_tx_phystat last_physt; + uint8_t thcal_temp; + int cur_bcnq_id; + + int nvaps; + int ap_vaps; + int bcn_vaps; + int mon_vaps; + + int vaps_running; + int monvaps_running; + + uint16_t next_rom_addr; + uint8_t keys_bmap[howmany(RTWN_CAM_ENTRY_LIMIT, NBBY)]; + + struct rtwn_vap *vaps[RTWN_PORT_COUNT]; + struct ieee80211_node *node_list[RTWN_MACID_LIMIT]; + struct mtx nt_mtx; + + struct callout sc_calib_to; + struct callout sc_pwrmode_init; +#ifndef D4054 + struct callout sc_watchdog_to; + int sc_tx_timer; +#endif + + struct mtx sc_mtx; + + struct rtwn_cmdq cmdq[RTWN_CMDQ_SIZE]; + struct mtx cmdq_mtx; + struct task cmdq_task; + uint8_t cmdq_first; + uint8_t cmdq_last; + + struct wmeParams cap_wmeParams[WME_NUM_AC]; + + struct rtwn_rx_radiotap_header sc_rxtap; + struct rtwn_tx_radiotap_header sc_txtap; + + int ntxchains; + int nrxchains; + + int ledlink; + uint8_t thermal_meter; + + int sc_tx_n_active; + uint8_t qfullmsk; + + /* Firmware-specific */ + const char *fwname; + uint16_t fwver; + uint16_t fwsig; + int fwcur; + + void (*sc_node_free)(struct ieee80211_node *); + void (*sc_scan_curchan)(struct ieee80211_scan_state *, + unsigned long); + + /* Interface-specific. */ + int (*sc_write_1)(struct rtwn_softc *, uint16_t, + uint8_t); + int (*sc_write_2)(struct rtwn_softc *, uint16_t, + uint16_t); + int (*sc_write_4)(struct rtwn_softc *, uint16_t, + uint32_t); + uint8_t (*sc_read_1)(struct rtwn_softc *, uint16_t); + uint16_t (*sc_read_2)(struct rtwn_softc *, uint16_t); + uint32_t (*sc_read_4)(struct rtwn_softc *, uint16_t); + /* XXX eliminate */ + void (*sc_delay)(struct rtwn_softc *, int); + int (*sc_tx_start)(struct rtwn_softc *, + struct ieee80211_node *, struct mbuf *, uint8_t *, + uint8_t, int); + void (*sc_start_xfers)(struct rtwn_softc *); + void (*sc_reset_lists)(struct rtwn_softc *, + struct ieee80211vap *); + void (*sc_abort_xfers)(struct rtwn_softc *); + int (*sc_fw_write_block)(struct rtwn_softc *, + const uint8_t *, uint16_t, int); + uint16_t (*sc_get_qmap)(struct rtwn_softc *); + void (*sc_set_desc_addr)(struct rtwn_softc *); + void (*sc_drop_incorrect_tx)(struct rtwn_softc *); + void (*sc_beacon_update_begin)(struct rtwn_softc *, + struct ieee80211vap *); + void (*sc_beacon_update_end)(struct rtwn_softc *, + struct ieee80211vap *); + void (*sc_beacon_unload)(struct rtwn_softc *, int); + + /* XXX drop checks for PCIe? */ + int bcn_check_interval; + + /* Device-specific. */ + uint32_t (*sc_rf_read)(struct rtwn_softc *, int, uint8_t); + void (*sc_rf_write)(struct rtwn_softc *, int, uint8_t, + uint32_t); + int (*sc_check_condition)(struct rtwn_softc *, + const uint8_t[]); + void (*sc_efuse_postread)(struct rtwn_softc *); + void (*sc_parse_rom)(struct rtwn_softc *, uint8_t *); + void (*sc_set_led)(struct rtwn_softc *, int, int); + int (*sc_power_on)(struct rtwn_softc *); + void (*sc_power_off)(struct rtwn_softc *); +#ifndef RTWN_WITHOUT_UCODE + void (*sc_fw_reset)(struct rtwn_softc *, int); + void (*sc_fw_download_enable)(struct rtwn_softc *, int); +#endif + int (*sc_llt_init)(struct rtwn_softc *); + int (*sc_set_page_size)(struct rtwn_softc *); + void (*sc_lc_calib)(struct rtwn_softc *); + void (*sc_iq_calib)(struct rtwn_softc *); + void (*sc_read_chipid_vendor)(struct rtwn_softc *, + uint32_t); + void (*sc_adj_devcaps)(struct rtwn_softc *); + void (*sc_vap_preattach)(struct rtwn_softc *, + struct ieee80211vap *); + void (*sc_postattach)(struct rtwn_softc *); + void (*sc_detach_private)(struct rtwn_softc *); + void (*sc_fill_tx_desc)(struct rtwn_softc *, + struct ieee80211_node *, struct mbuf *, + void *, uint8_t, int); + void (*sc_fill_tx_desc_raw)(struct rtwn_softc *, + struct ieee80211_node *, struct mbuf *, + void *, const struct ieee80211_bpf_params *); + void (*sc_fill_tx_desc_null)(struct rtwn_softc *, + void *, int, int, int); + void (*sc_dump_tx_desc)(struct rtwn_softc *, const void *); + uint8_t (*sc_tx_radiotap_flags)(const void *); + uint8_t (*sc_rx_radiotap_flags)(const void *); + void (*sc_beacon_init)(struct rtwn_softc *, void *, int); + void (*sc_beacon_enable)(struct rtwn_softc *, int, int); + void (*sc_beacon_set_rate)(void *, int); + void (*sc_beacon_select)(struct rtwn_softc *, int); + void (*sc_set_chan)(struct rtwn_softc *, + struct ieee80211_channel *); + void (*sc_set_media_status)(struct rtwn_softc *, int); +#ifndef RTWN_WITHOUT_UCODE + int (*sc_set_rsvd_page)(struct rtwn_softc *, int, int, + int); + int (*sc_set_pwrmode)(struct rtwn_softc *, + struct ieee80211vap *, int); + void (*sc_set_rssi)(struct rtwn_softc *); +#endif + void (*sc_get_rx_stats)(struct rtwn_softc *, + struct ieee80211_rx_stats *, const void *, + const void *); + int8_t (*sc_get_rssi_cck)(struct rtwn_softc *, void *); + int8_t (*sc_get_rssi_ofdm)(struct rtwn_softc *, void *); + int (*sc_classify_intr)(struct rtwn_softc *, void *, int); + void (*sc_handle_tx_report)(struct rtwn_softc *, uint8_t *, + int); + void (*sc_handle_c2h_report)(struct rtwn_softc *, + uint8_t *, int); + int (*sc_check_frame)(struct rtwn_softc *, struct mbuf *); + void (*sc_temp_measure)(struct rtwn_softc *); + uint8_t (*sc_temp_read)(struct rtwn_softc *); + void (*sc_init_tx_agg)(struct rtwn_softc *); + void (*sc_init_rx_agg)(struct rtwn_softc *); + void (*sc_init_intr)(struct rtwn_softc *); + void (*sc_init_ampdu)(struct rtwn_softc *); + void (*sc_init_edca)(struct rtwn_softc *); + void (*sc_init_bb)(struct rtwn_softc *); + void (*sc_init_rf)(struct rtwn_softc *); + void (*sc_init_antsel)(struct rtwn_softc *); + void (*sc_post_init)(struct rtwn_softc *); + int (*sc_init_bcnq1_boundary)(struct rtwn_softc *); + + const uint8_t *chan_list_5ghz[3]; + int chan_num_5ghz[3]; + + const struct rtwn_mac_prog *mac_prog; + int mac_size; + const struct rtwn_bb_prog *bb_prog; + int bb_size; + const struct rtwn_agc_prog *agc_prog; + int agc_size; + const struct rtwn_rf_prog *rf_prog; + + int page_count; + int pktbuf_count; + + int ackto; + + int npubqpages; + int nhqpages; + int nnqpages; + int nlqpages; + int page_size; + + int txdesc_len; + int efuse_maxlen; + int efuse_maplen; + + uint16_t rx_dma_size; + + int macid_limit; + int cam_entry_limit; + int fwsize_limit; + int temp_delta; + + uint16_t bcn_status_reg[RTWN_PORT_COUNT]; + uint32_t rcr; /* Rx filter */ +}; +MALLOC_DECLARE(M_RTWN_PRIV); + +#define RTWN_LOCK(sc) mtx_lock(&(sc)->sc_mtx) +#define RTWN_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx) +#define RTWN_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED) + +#define RTWN_CMDQ_LOCK_INIT(sc) \ + mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF) +#define RTWN_CMDQ_LOCK(sc) mtx_lock(&(sc)->cmdq_mtx) +#define RTWN_CMDQ_UNLOCK(sc) mtx_unlock(&(sc)->cmdq_mtx) +#define RTWN_CMDQ_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->cmdq_mtx) +#define RTWN_CMDQ_LOCK_DESTROY(sc) mtx_destroy(&(sc)->cmdq_mtx) + +#define RTWN_NT_LOCK_INIT(sc) \ + mtx_init(&(sc)->nt_mtx, "node table lock", NULL, MTX_DEF) +#define RTWN_NT_LOCK(sc) mtx_lock(&(sc)->nt_mtx) +#define RTWN_NT_UNLOCK(sc) mtx_unlock(&(sc)->nt_mtx) +#define RTWN_NT_LOCK_INITIALIZED(sc) mtx_initialized(&(sc)->nt_mtx) +#define RTWN_NT_LOCK_DESTROY(sc) mtx_destroy(&(sc)->nt_mtx) + + +void rtwn_sysctlattach(struct rtwn_softc *); + +int rtwn_attach(struct rtwn_softc *); +void rtwn_detach(struct rtwn_softc *); +void rtwn_resume(struct rtwn_softc *); +void rtwn_suspend(struct rtwn_softc *); + + +/* Interface-specific. */ +#define rtwn_write_1(_sc, _addr, _val) \ + (((_sc)->sc_write_1)((_sc), (_addr), (_val))) +#define rtwn_write_2(_sc, _addr, _val) \ + (((_sc)->sc_write_2)((_sc), (_addr), (_val))) +#define rtwn_write_4(_sc, _addr, _val) \ + (((_sc)->sc_write_4)((_sc), (_addr), (_val))) +#define rtwn_read_1(_sc, _addr) \ + (((_sc)->sc_read_1)((_sc), (_addr))) +#define rtwn_read_2(_sc, _addr) \ + (((_sc)->sc_read_2)((_sc), (_addr))) +#define rtwn_read_4(_sc, _addr) \ + (((_sc)->sc_read_4)((_sc), (_addr))) +#define rtwn_delay(_sc, _usec) \ + (((_sc)->sc_delay)((_sc), (_usec))) +#define rtwn_tx_start(_sc, _ni, _m, _desc, _type, _id) \ + (((_sc)->sc_tx_start)((_sc), (_ni), (_m), (_desc), (_type), (_id))) +#define rtwn_start_xfers(_sc) \ + (((_sc)->sc_start_xfers)((_sc))) +#define rtwn_reset_lists(_sc, _vap) \ + (((_sc)->sc_reset_lists)((_sc), (_vap))) +#define rtwn_abort_xfers(_sc) \ + (((_sc)->sc_abort_xfers)((_sc))) +#define rtwn_fw_write_block(_sc, _buf, _reg, _len) \ + (((_sc)->sc_fw_write_block)((_sc), (_buf), (_reg), (_len))) +#define rtwn_get_qmap(_sc) \ + (((_sc)->sc_get_qmap)((_sc))) +#define rtwn_set_desc_addr(_sc) \ + (((_sc)->sc_set_desc_addr)((_sc))) +#define rtwn_drop_incorrect_tx(_sc) \ + (((_sc)->sc_drop_incorrect_tx)((_sc))) +#define rtwn_beacon_update_begin(_sc, _vap) \ + (((_sc)->sc_beacon_update_begin)((_sc), (_vap))) +#define rtwn_beacon_update_end(_sc, _vap) \ + (((_sc)->sc_beacon_update_end)((_sc), (_vap))) +#define rtwn_beacon_unload(_sc, _id) \ + (((_sc)->sc_beacon_unload)((_sc), (_id))) + +/* Aliases. */ +#define rtwn_bb_write rtwn_write_4 +#define rtwn_bb_read rtwn_read_4 +#define rtwn_bb_setbits rtwn_setbits_4 + +/* Device-specific. */ +#define rtwn_rf_read(_sc, _chain, _addr) \ + (((_sc)->sc_rf_read)((_sc), (_chain), (_addr))) +#define rtwn_rf_write(_sc, _chain, _addr, _val) \ + (((_sc)->sc_rf_write)((_sc), (_chain), (_addr), (_val))) +#define rtwn_check_condition(_sc, _cond) \ + (((_sc)->sc_check_condition)((_sc), (_cond))) +#define rtwn_efuse_postread(_sc) \ + (((_sc)->sc_efuse_postread)((_sc))) +#define rtwn_parse_rom(_sc, _rom) \ + (((_sc)->sc_parse_rom)((_sc), (_rom))) +#define rtwn_set_led(_sc, _led, _on) \ + (((_sc)->sc_set_led)((_sc), (_led), (_on))) +#define rtwn_get_rx_stats(_sc, _rxs, _desc, _physt) \ + (((_sc)->sc_get_rx_stats((_sc), (_rxs), (_desc), (_physt)))) +#define rtwn_get_rssi_cck(_sc, _physt) \ + (((_sc)->sc_get_rssi_cck)((_sc), (_physt))) +#define rtwn_get_rssi_ofdm(_sc, _physt) \ + (((_sc)->sc_get_rssi_ofdm)((_sc), (_physt))) +#define rtwn_power_on(_sc) \ + (((_sc)->sc_power_on)((_sc))) +#define rtwn_power_off(_sc) \ + (((_sc)->sc_power_off)((_sc))) +#ifndef RTWN_WITHOUT_UCODE +#define rtwn_fw_reset(_sc, _reason) \ + (((_sc)->sc_fw_reset)((_sc), (_reason))) +#define rtwn_fw_download_enable(_sc, _enable) \ + (((_sc)->sc_fw_download_enable)((_sc), (_enable))) +#endif +#define rtwn_llt_init(_sc) \ + (((_sc)->sc_llt_init)((_sc))) +#define rtwn_set_page_size(_sc) \ + (((_sc)->sc_set_page_size)((_sc))) +#define rtwn_lc_calib(_sc) \ + (((_sc)->sc_lc_calib)((_sc))) +#define rtwn_iq_calib(_sc) \ + (((_sc)->sc_iq_calib)((_sc))) +#define rtwn_read_chipid_vendor(_sc, _reg) \ + (((_sc)->sc_read_chipid_vendor)((_sc), (_reg))) +#define rtwn_adj_devcaps(_sc) \ + (((_sc)->sc_adj_devcaps)((_sc))) +#define rtwn_vap_preattach(_sc, _vap) \ + (((_sc)->sc_vap_preattach)((_sc), (_vap))) +#define rtwn_postattach(_sc) \ + (((_sc)->sc_postattach)((_sc))) +#define rtwn_detach_private(_sc) \ + (((_sc)->sc_detach_private)((_sc))) +#define rtwn_fill_tx_desc(_sc, _ni, _m, \ + _buf, _ridx, _maxretry) \ + (((_sc)->sc_fill_tx_desc)((_sc), (_ni), \ + (_m), (_buf), (_ridx), (_maxretry))) +#define rtwn_fill_tx_desc_raw(_sc, _ni, _m, \ + _buf, _params) \ + (((_sc)->sc_fill_tx_desc_raw)((_sc), (_ni), \ + (_m), (_buf), (_params))) +#define rtwn_fill_tx_desc_null(_sc, _buf, _11b, _qos, _id) \ + (((_sc)->sc_fill_tx_desc_null)((_sc), \ + (_buf), (_11b), (_qos), (_id))) +#define rtwn_dump_tx_desc(_sc, _desc) \ + (((_sc)->sc_dump_tx_desc)((_sc), (_desc))) +#define rtwn_tx_radiotap_flags(_sc, _buf) \ + (((_sc)->sc_tx_radiotap_flags)((_buf))) +#define rtwn_rx_radiotap_flags(_sc, _buf) \ + (((_sc)->sc_rx_radiotap_flags)((_buf))) +#define rtwn_set_chan(_sc, _c) \ + (((_sc)->sc_set_chan)((_sc), (_c))) +#ifndef RTWN_WITHOUT_UCODE +#define rtwn_set_rsvd_page(_sc, _resp, _null, _qos_null) \ + (((_sc)->sc_set_rsvd_page)((_sc), \ + (_resp), (_null), (_qos_null))) +#define rtwn_set_pwrmode(_sc, _vap, _off) \ + (((_sc)->sc_set_pwrmode)((_sc), (_vap), (_off))) +#define rtwn_set_rssi(_sc) \ + (((_sc)->sc_set_rssi)((_sc))) +#endif +#define rtwn_classify_intr(_sc, _buf, _len) \ + (((_sc)->sc_classify_intr)((_sc), (_buf), (_len))) +#define rtwn_handle_tx_report(_sc, _buf, _len) \ + (((_sc)->sc_handle_tx_report)((_sc), (_buf), (_len))) +#define rtwn_handle_c2h_report(_sc, _buf, _len) \ + (((_sc)->sc_handle_c2h_report)((_sc), (_buf), (_len))) +#define rtwn_check_frame(_sc, _m) \ + (((_sc)->sc_check_frame)((_sc), (_m))) +#define rtwn_beacon_init(_sc, _buf, _id) \ + (((_sc)->sc_beacon_init)((_sc), (_buf), (_id))) +#define rtwn_beacon_enable(_sc, _id, _enable) \ + (((_sc)->sc_beacon_enable)((_sc), (_id), (_enable))) +#define rtwn_beacon_set_rate(_sc, _buf, _is5ghz) \ + (((_sc)->sc_beacon_set_rate)((_buf), (_is5ghz))) +#define rtwn_beacon_select(_sc, _id) \ + (((_sc)->sc_beacon_select)((_sc), (_id))) +#define rtwn_temp_measure(_sc) \ + (((_sc)->sc_temp_measure)((_sc))) +#define rtwn_temp_read(_sc) \ + (((_sc)->sc_temp_read)((_sc))) +#define rtwn_init_tx_agg(_sc) \ + (((_sc)->sc_init_tx_agg)((_sc))) +#define rtwn_init_rx_agg(_sc) \ + (((_sc)->sc_init_rx_agg)((_sc))) +#define rtwn_init_intr(_sc) \ + (((_sc)->sc_init_intr)((_sc))) +#define rtwn_init_ampdu(_sc) \ + (((_sc)->sc_init_ampdu)((_sc))) +#define rtwn_init_edca(_sc) \ + (((_sc)->sc_init_edca)((_sc))) +#define rtwn_init_bb(_sc) \ + (((_sc)->sc_init_bb)((_sc))) +#define rtwn_init_rf(_sc) \ + (((_sc)->sc_init_rf)((_sc))) +#define rtwn_init_antsel(_sc) \ + (((_sc)->sc_init_antsel)((_sc))) +#define rtwn_post_init(_sc) \ + (((_sc)->sc_post_init)((_sc))) +#define rtwn_init_bcnq1_boundary(_sc) \ + (((_sc)->sc_init_bcnq1_boundary)((_sc))) + + +/* + * Methods to access subfields in registers. + */ +static __inline int +rtwn_setbits_1(struct rtwn_softc *sc, uint16_t addr, uint8_t clr, + uint8_t set) +{ + return (rtwn_write_1(sc, addr, + (rtwn_read_1(sc, addr) & ~clr) | set)); +} + +static __inline int +rtwn_setbits_1_shift(struct rtwn_softc *sc, uint16_t addr, uint32_t clr, + uint32_t set, int shift) +{ + return (rtwn_setbits_1(sc, addr + shift, clr >> shift * NBBY, + set >> shift * NBBY)); +} + +static __inline int +rtwn_setbits_2(struct rtwn_softc *sc, uint16_t addr, uint16_t clr, + uint16_t set) +{ + return (rtwn_write_2(sc, addr, + (rtwn_read_2(sc, addr) & ~clr) | set)); +} + +static __inline int +rtwn_setbits_4(struct rtwn_softc *sc, uint16_t addr, uint32_t clr, + uint32_t set) +{ + return (rtwn_write_4(sc, addr, + (rtwn_read_4(sc, addr) & ~clr) | set)); +} + +static __inline void +rtwn_rf_setbits(struct rtwn_softc *sc, int chain, uint8_t addr, + uint32_t clr, uint32_t set) +{ + rtwn_rf_write(sc, chain, addr, + (rtwn_rf_read(sc, chain, addr) & ~clr) | set); +} + +#endif /* IF_RTWNVAR_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/opt_wlan.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/opt_wlan.h new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/opt_wlan.h @@ -0,0 +1 @@ + diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.c new file mode 100644 index 0000000000..107686faf7 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.c @@ -0,0 +1,793 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_attach.c 320725 2017-07-06 07:37:33Z avos $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + + +static device_probe_t rtwn_pci_probe; +static device_attach_t rtwn_pci_attach; +static device_detach_t rtwn_pci_detach; +static device_shutdown_t rtwn_pci_shutdown; +static device_suspend_t rtwn_pci_suspend; +static device_resume_t rtwn_pci_resume; + +static int rtwn_pci_alloc_rx_list(struct rtwn_softc *); +static void rtwn_pci_reset_rx_list(struct rtwn_softc *); +static void rtwn_pci_free_rx_list(struct rtwn_softc *); +static int rtwn_pci_alloc_tx_list(struct rtwn_softc *, int); +static void rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *, int); +static void rtwn_pci_reset_beacon_ring(struct rtwn_softc *, int); +static void rtwn_pci_reset_tx_list(struct rtwn_softc *, + struct ieee80211vap *, int); +static void rtwn_pci_free_tx_list(struct rtwn_softc *, int); +static void rtwn_pci_reset_lists(struct rtwn_softc *, + struct ieee80211vap *); +static int rtwn_pci_fw_write_block(struct rtwn_softc *, + const uint8_t *, uint16_t, int); +static uint16_t rtwn_pci_get_qmap(struct rtwn_softc *); +static void rtwn_pci_set_desc_addr(struct rtwn_softc *); +static void rtwn_pci_beacon_update_begin(struct rtwn_softc *, + struct ieee80211vap *); +static void rtwn_pci_beacon_update_end(struct rtwn_softc *, + struct ieee80211vap *); +static void rtwn_pci_attach_methods(struct rtwn_softc *); + + +static const struct rtwn_pci_ident * +rtwn_pci_probe_sub(device_t dev) +{ + const struct rtwn_pci_ident *ident; + int vendor_id, device_id; + + vendor_id = pci_get_vendor(dev); + device_id = pci_get_device(dev); + + for (ident = rtwn_pci_ident_table; ident->name != NULL; ident++) + if (vendor_id == ident->vendor && device_id == ident->device) + return (ident); + + return (NULL); +} + +static int +rtwn_pci_probe(device_t dev) +{ + const struct rtwn_pci_ident *ident; + + ident = rtwn_pci_probe_sub(dev); + if (ident != NULL) { + device_set_desc(dev, ident->name); + return (BUS_PROBE_DEFAULT); + } + return (ENXIO); +} + +static int +rtwn_pci_alloc_rx_list(struct rtwn_softc *sc) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_rx_ring *rx_ring = &pc->rx_ring; + struct rtwn_rx_data *rx_data; + bus_size_t size; + int i, error; + + /* Allocate Rx descriptors. */ + size = sizeof(struct rtwn_rx_stat_pci) * RTWN_PCI_RX_LIST_COUNT; + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + size, 1, size, 0, NULL, NULL, &rx_ring->desc_dmat); + if (error != 0) { + device_printf(sc->sc_dev, "could not create rx desc DMA tag\n"); + goto fail; + } + + error = bus_dmamem_alloc(rx_ring->desc_dmat, (void **)&rx_ring->desc, + BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, + &rx_ring->desc_map); + if (error != 0) { + device_printf(sc->sc_dev, "could not allocate rx desc\n"); + goto fail; + } + error = bus_dmamap_load(rx_ring->desc_dmat, rx_ring->desc_map, + rx_ring->desc, size, rtwn_pci_dma_map_addr, &rx_ring->paddr, 0); + if (error != 0) { + device_printf(sc->sc_dev, "could not load rx desc DMA map\n"); + goto fail; + } + bus_dmamap_sync(rx_ring->desc_dmat, rx_ring->desc_map, + BUS_DMASYNC_PREWRITE); + + /* Create RX buffer DMA tag. */ + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat); + if (error != 0) { + device_printf(sc->sc_dev, "could not create rx buf DMA tag\n"); + goto fail; + } + + /* Allocate Rx buffers. */ + for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { + rx_data = &rx_ring->rx_data[i]; + error = bus_dmamap_create(rx_ring->data_dmat, 0, &rx_data->map); + if (error != 0) { + device_printf(sc->sc_dev, + "could not create rx buf DMA map\n"); + goto fail; + } + + rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, + MJUMPAGESIZE); + if (rx_data->m == NULL) { + device_printf(sc->sc_dev, + "could not allocate rx mbuf\n"); + error = ENOMEM; + goto fail; + } + + error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map, + mtod(rx_data->m, void *), MJUMPAGESIZE, + rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, + "could not load rx buf DMA map"); + goto fail; + } + + rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr, + MJUMPAGESIZE, i); + } + rx_ring->cur = 0; + + return (0); + +fail: + rtwn_pci_free_rx_list(sc); + return (error); +} + +static void +rtwn_pci_reset_rx_list(struct rtwn_softc *sc) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_rx_ring *rx_ring = &pc->rx_ring; + struct rtwn_rx_data *rx_data; + int i; + + for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { + rx_data = &rx_ring->rx_data[i]; + rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], + rx_data->paddr, MJUMPAGESIZE, i); + } + rx_ring->cur = 0; +} + +static void +rtwn_pci_free_rx_list(struct rtwn_softc *sc) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_rx_ring *rx_ring = &pc->rx_ring; + struct rtwn_rx_data *rx_data; + int i; + + if (rx_ring->desc_dmat != NULL) { + if (rx_ring->desc != NULL) { + bus_dmamap_sync(rx_ring->desc_dmat, + rx_ring->desc_map, + BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(rx_ring->desc_dmat, + rx_ring->desc_map); + bus_dmamem_free(rx_ring->desc_dmat, rx_ring->desc, + rx_ring->desc_map); + rx_ring->desc = NULL; + } + bus_dma_tag_destroy(rx_ring->desc_dmat); + rx_ring->desc_dmat = NULL; + } + + for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) { + rx_data = &rx_ring->rx_data[i]; + + if (rx_data->m != NULL) { + bus_dmamap_sync(rx_ring->data_dmat, + rx_data->map, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(rx_ring->data_dmat, rx_data->map); + m_freem(rx_data->m); + rx_data->m = NULL; + } + bus_dmamap_destroy(rx_ring->data_dmat, rx_data->map); + rx_data->map = NULL; + } + if (rx_ring->data_dmat != NULL) { + bus_dma_tag_destroy(rx_ring->data_dmat); + rx_ring->data_dmat = NULL; + } +} + +static int +rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid]; + bus_size_t size; + int i, error; + + size = sc->txdesc_len * RTWN_PCI_TX_LIST_COUNT; + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), PAGE_SIZE, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + size, 1, size, 0, NULL, NULL, &tx_ring->desc_dmat); + if (error != 0) { + device_printf(sc->sc_dev, "could not create tx ring DMA tag\n"); + goto fail; + } + + error = bus_dmamem_alloc(tx_ring->desc_dmat, &tx_ring->desc, + BUS_DMA_NOWAIT | BUS_DMA_ZERO, &tx_ring->desc_map); + if (error != 0) { + device_printf(sc->sc_dev, "can't map tx ring DMA memory\n"); + goto fail; + } + error = bus_dmamap_load(tx_ring->desc_dmat, tx_ring->desc_map, + tx_ring->desc, size, rtwn_pci_dma_map_addr, &tx_ring->paddr, + BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, "could not load desc DMA map\n"); + goto fail; + } + bus_dmamap_sync(tx_ring->desc_dmat, tx_ring->desc_map, + BUS_DMASYNC_PREWRITE); + + error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat); + if (error != 0) { + device_printf(sc->sc_dev, "could not create tx buf DMA tag\n"); + goto fail; + } + + for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { + struct rtwn_tx_data *tx_data = &tx_ring->tx_data[i]; + void *tx_desc = (uint8_t *)tx_ring->desc + sc->txdesc_len * i; + uint32_t next_desc_addr = tx_ring->paddr + + sc->txdesc_len * ((i + 1) % RTWN_PCI_TX_LIST_COUNT); + + rtwn_pci_setup_tx_desc(pc, tx_desc, next_desc_addr); + + error = bus_dmamap_create(tx_ring->data_dmat, 0, &tx_data->map); + if (error != 0) { + device_printf(sc->sc_dev, + "could not create tx buf DMA map\n"); + return (error); + } + tx_data->m = NULL; + tx_data->ni = NULL; + } + return (0); + +fail: + rtwn_pci_free_tx_list(sc, qid); + return (error); +} + +static void +rtwn_pci_reset_tx_ring_stopped(struct rtwn_softc *sc, int qid) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *ring = &pc->tx_ring[qid]; + int i; + + for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { + struct rtwn_tx_data *data = &ring->tx_data[i]; + void *desc = (uint8_t *)ring->desc + sc->txdesc_len * i; + + rtwn_pci_copy_tx_desc(pc, desc, NULL); + + if (data->m != NULL) { + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, data->map); + m_freem(data->m); + data->m = NULL; + } + if (data->ni != NULL) { + ieee80211_free_node(data->ni); + data->ni = NULL; + } + } + + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_POSTWRITE); + + sc->qfullmsk &= ~(1 << qid); + ring->queued = 0; + ring->last = ring->cur = 0; +} + +/* + * Clear entry 0 (or 1) in the beacon queue (other are not used). + */ +static void +rtwn_pci_reset_beacon_ring(struct rtwn_softc *sc, int id) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE]; + struct rtwn_tx_data *data = &ring->tx_data[id]; + struct rtwn_tx_desc_common *txd = (struct rtwn_tx_desc_common *) + ((uint8_t *)ring->desc + id * sc->txdesc_len); + + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD); + if (txd->flags0 & RTWN_FLAGS0_OWN) { + /* Clear OWN bit. */ + txd->flags0 &= ~RTWN_FLAGS0_OWN; + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_PREWRITE); + + /* Unload mbuf. */ + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, data->map); + } +} + +/* + * Drop stale entries from Tx ring before the vap will be deleted. + * In case if vap is NULL just free everything and reset cur / last pointers. + */ +static void +rtwn_pci_reset_tx_list(struct rtwn_softc *sc, struct ieee80211vap *vap, + int qid) +{ + int i; + + if (vap == NULL) { + if (qid != RTWN_PCI_BEACON_QUEUE) { + /* + * Device was stopped; just clear all entries. + */ + rtwn_pci_reset_tx_ring_stopped(sc, qid); + } else { + for (i = 0; i < RTWN_PORT_COUNT; i++) + rtwn_pci_reset_beacon_ring(sc, i); + } + } else if (qid == RTWN_PCI_BEACON_QUEUE && + (vap->iv_opmode == IEEE80211_M_HOSTAP || + vap->iv_opmode == IEEE80211_M_IBSS)) { + struct rtwn_vap *uvp = RTWN_VAP(vap); + + rtwn_pci_reset_beacon_ring(sc, uvp->id); + } else { + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *ring = &pc->tx_ring[qid]; + + for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { + struct rtwn_tx_data *data = &ring->tx_data[i]; + if (data->ni != NULL && data->ni->ni_vap == vap) { + /* + * NB: if some vap is still running + * rtwn_pci_tx_done() will free the mbuf; + * otherwise, rtwn_stop() will reset all rings + * after device shutdown. + */ + ieee80211_free_node(data->ni); + data->ni = NULL; + } + } + } +} + +static void +rtwn_pci_free_tx_list(struct rtwn_softc *sc, int qid) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *tx_ring = &pc->tx_ring[qid]; + struct rtwn_tx_data *tx_data; + int i; + + if (tx_ring->desc_dmat != NULL) { + if (tx_ring->desc != NULL) { + bus_dmamap_sync(tx_ring->desc_dmat, + tx_ring->desc_map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(tx_ring->desc_dmat, + tx_ring->desc_map); + bus_dmamem_free(tx_ring->desc_dmat, tx_ring->desc, + tx_ring->desc_map); + } + bus_dma_tag_destroy(tx_ring->desc_dmat); + } + + for (i = 0; i < RTWN_PCI_TX_LIST_COUNT; i++) { + tx_data = &tx_ring->tx_data[i]; + + if (tx_data->m != NULL) { + bus_dmamap_sync(tx_ring->data_dmat, tx_data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(tx_ring->data_dmat, tx_data->map); + m_freem(tx_data->m); + tx_data->m = NULL; + } + } + if (tx_ring->data_dmat != NULL) { + bus_dma_tag_destroy(tx_ring->data_dmat); + tx_ring->data_dmat = NULL; + } + + sc->qfullmsk &= ~(1 << qid); + tx_ring->queued = 0; + tx_ring->last = tx_ring->cur = 0; +} + +static void +rtwn_pci_reset_lists(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + int i; + + for (i = 0; i < RTWN_PCI_NTXQUEUES; i++) + rtwn_pci_reset_tx_list(sc, vap, i); + + if (vap == NULL) { + sc->qfullmsk = 0; + rtwn_pci_reset_rx_list(sc); + } +} + +static int +rtwn_pci_fw_write_block(struct rtwn_softc *sc, const uint8_t *buf, + uint16_t reg, int mlen) +{ + int i; + + for (i = 0; i < mlen; i++) + rtwn_pci_write_1(sc, reg++, buf[i]); + + /* NB: cannot fail */ + return (0); +} + +static uint16_t +rtwn_pci_get_qmap(struct rtwn_softc *sc) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + + KASSERT(pc->pc_qmap != 0, ("%s: qmap is not set!\n", __func__)); + + return (pc->pc_qmap); +} + +static void +rtwn_pci_set_desc_addr(struct rtwn_softc *sc) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: addresses:\n" + "bk: %08jX, be: %08jX, vi: %08jX, vo: %08jX\n" + "bcn: %08jX, mgt: %08jX, high: %08jX, rx: %08jX\n", + __func__, (uintmax_t)pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr, + (uintmax_t)pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr, + (uintmax_t)pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr, + (uintmax_t)pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr, + (uintmax_t)pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr, + (uintmax_t)pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr, + (uintmax_t)pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr, + (uintmax_t)pc->rx_ring.paddr); + + /* Set Tx Configuration Register. */ + rtwn_pci_write_4(sc, R92C_TCR, pc->tcr); + + /* Configure Tx DMA. */ + rtwn_pci_write_4(sc, R92C_BKQ_DESA, + pc->tx_ring[RTWN_PCI_BK_QUEUE].paddr); + rtwn_pci_write_4(sc, R92C_BEQ_DESA, + pc->tx_ring[RTWN_PCI_BE_QUEUE].paddr); + rtwn_pci_write_4(sc, R92C_VIQ_DESA, + pc->tx_ring[RTWN_PCI_VI_QUEUE].paddr); + rtwn_pci_write_4(sc, R92C_VOQ_DESA, + pc->tx_ring[RTWN_PCI_VO_QUEUE].paddr); + rtwn_pci_write_4(sc, R92C_BCNQ_DESA, + pc->tx_ring[RTWN_PCI_BEACON_QUEUE].paddr); + rtwn_pci_write_4(sc, R92C_MGQ_DESA, + pc->tx_ring[RTWN_PCI_MGNT_QUEUE].paddr); + rtwn_pci_write_4(sc, R92C_HQ_DESA, + pc->tx_ring[RTWN_PCI_HIGH_QUEUE].paddr); + + /* Configure Rx DMA. */ + rtwn_pci_write_4(sc, R92C_RX_DESA, pc->rx_ring.paddr); +} + +static void +rtwn_pci_beacon_update_begin(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct rtwn_vap *rvp = RTWN_VAP(vap); + + RTWN_ASSERT_LOCKED(sc); + + rtwn_beacon_enable(sc, rvp->id, 0); +} + +static void +rtwn_pci_beacon_update_end(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct rtwn_vap *rvp = RTWN_VAP(vap); + + RTWN_ASSERT_LOCKED(sc); + + if (rvp->curr_mode != R92C_MSR_NOLINK) + rtwn_beacon_enable(sc, rvp->id, 1); +} + +static void +rtwn_pci_attach_methods(struct rtwn_softc *sc) +{ + sc->sc_write_1 = rtwn_pci_write_1; + sc->sc_write_2 = rtwn_pci_write_2; + sc->sc_write_4 = rtwn_pci_write_4; + sc->sc_read_1 = rtwn_pci_read_1; + sc->sc_read_2 = rtwn_pci_read_2; + sc->sc_read_4 = rtwn_pci_read_4; + sc->sc_delay = rtwn_pci_delay; + sc->sc_tx_start = rtwn_pci_tx_start; + sc->sc_reset_lists = rtwn_pci_reset_lists; + sc->sc_abort_xfers = rtwn_nop_softc; + sc->sc_fw_write_block = rtwn_pci_fw_write_block; + sc->sc_get_qmap = rtwn_pci_get_qmap; + sc->sc_set_desc_addr = rtwn_pci_set_desc_addr; + sc->sc_drop_incorrect_tx = rtwn_nop_softc; + sc->sc_beacon_update_begin = rtwn_pci_beacon_update_begin; + sc->sc_beacon_update_end = rtwn_pci_beacon_update_end; + sc->sc_beacon_unload = rtwn_pci_reset_beacon_ring; + + sc->bcn_check_interval = 25000; +} + +static int +rtwn_pci_attach(device_t dev) +{ + const struct rtwn_pci_ident *ident; + struct rtwn_pci_softc *pc = device_get_softc(dev); + struct rtwn_softc *sc = &pc->pc_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint32_t lcsr; + int cap_off, i, error, rid; + + ident = rtwn_pci_probe_sub(dev); + if (ident == NULL) + return (ENXIO); + + /* + * Get the offset of the PCI Express Capability Structure in PCI + * Configuration Space. + */ + error = pci_find_cap(dev, PCIY_EXPRESS, &cap_off); + if (error != 0) { + device_printf(dev, "PCIe capability structure not found!\n"); + return (error); + } + + /* Enable bus-mastering. */ + pci_enable_busmaster(dev); + + rid = PCIR_BAR(2); + pc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + RF_ACTIVE); + if (pc->mem == NULL) { + device_printf(dev, "can't map mem space\n"); + return (ENOMEM); + } + pc->pc_st = rman_get_bustag(pc->mem); + pc->pc_sh = rman_get_bushandle(pc->mem); + + /* Install interrupt handler. */ + rid = 1; + if (pci_alloc_msi(dev, &rid) == 0) + rid = 1; + else + rid = 0; + pc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE | + (rid != 0 ? 0 : RF_SHAREABLE)); + if (pc->irq == NULL) { + device_printf(dev, "can't map interrupt\n"); + goto detach; + } + + /* Disable PCIe Active State Power Management (ASPM). */ + lcsr = pci_read_config(dev, cap_off + PCIER_LINK_CTL, 4); + lcsr &= ~PCIEM_LINK_CTL_ASPMC; + pci_write_config(dev, cap_off + PCIER_LINK_CTL, lcsr, 4); + + sc->sc_dev = dev; + ic->ic_name = device_get_nameunit(dev); + + /* Need to be initialized early. */ + rtwn_sysctlattach(sc); + mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF); + + rtwn_pci_attach_methods(sc); + rtwn_pci_attach_private(pc, ident->chip); + + /* Allocate Tx/Rx buffers. */ + error = rtwn_pci_alloc_rx_list(sc); + if (error != 0) { + device_printf(dev, + "could not allocate Rx buffers, error %d\n", + error); + goto detach; + } + for (i = 0; i < RTWN_PCI_NTXQUEUES; i++) { + error = rtwn_pci_alloc_tx_list(sc, i); + if (error != 0) { + device_printf(dev, + "could not allocate Tx buffers, error %d\n", + error); + goto detach; + } + } + + /* Generic attach. */ + error = rtwn_attach(sc); + if (error != 0) + goto detach; + + /* + * Hook our interrupt after all initialization is complete. + */ + error = bus_setup_intr(dev, pc->irq, INTR_TYPE_NET | INTR_MPSAFE, + NULL, rtwn_pci_intr, sc, &pc->pc_ih); + if (error != 0) { + device_printf(dev, "can't establish interrupt, error %d\n", + error); + goto detach; + } + + return (0); + +detach: + rtwn_pci_detach(dev); /* failure */ + return (ENXIO); +} + +static int +rtwn_pci_detach(device_t dev) +{ + struct rtwn_pci_softc *pc = device_get_softc(dev); + struct rtwn_softc *sc = &pc->pc_sc; + int i; + + /* Generic detach. */ + rtwn_detach(sc); + + /* Uninstall interrupt handler. */ + if (pc->irq != NULL) { + bus_teardown_intr(dev, pc->irq, pc->pc_ih); + bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(pc->irq), + pc->irq); + pci_release_msi(dev); + } + + /* Free Tx/Rx buffers. */ + for (i = 0; i < RTWN_PCI_NTXQUEUES; i++) + rtwn_pci_free_tx_list(sc, i); + rtwn_pci_free_rx_list(sc); + + if (pc->mem != NULL) + bus_release_resource(dev, SYS_RES_MEMORY, + rman_get_rid(pc->mem), pc->mem); + + rtwn_detach_private(sc); + mtx_destroy(&sc->sc_mtx); + + return (0); +} + +static int +rtwn_pci_shutdown(device_t self) +{ + struct rtwn_pci_softc *pc = device_get_softc(self); + + ieee80211_stop_all(&pc->pc_sc.sc_ic); + return (0); +} + +static int +rtwn_pci_suspend(device_t self) +{ + struct rtwn_pci_softc *pc = device_get_softc(self); + + rtwn_suspend(&pc->pc_sc); + + return (0); +} + +static int +rtwn_pci_resume(device_t self) +{ + struct rtwn_pci_softc *pc = device_get_softc(self); + + rtwn_resume(&pc->pc_sc); + + return (0); +} + +static device_method_t rtwn_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, rtwn_pci_probe), + DEVMETHOD(device_attach, rtwn_pci_attach), + DEVMETHOD(device_detach, rtwn_pci_detach), + DEVMETHOD(device_shutdown, rtwn_pci_shutdown), + DEVMETHOD(device_suspend, rtwn_pci_suspend), + DEVMETHOD(device_resume, rtwn_pci_resume), + + DEVMETHOD_END +}; + +static driver_t rtwn_pci_driver = { + "rtwn", + rtwn_pci_methods, + sizeof(struct rtwn_pci_softc) +}; + +static devclass_t rtwn_pci_devclass; + +DRIVER_MODULE(rtwn_pci, pci, rtwn_pci_driver, rtwn_pci_devclass, NULL, NULL); +MODULE_VERSION(rtwn_pci, 1); +MODULE_DEPEND(rtwn_pci, pci, 1, 1, 1); +MODULE_DEPEND(rtwn_pci, wlan, 1, 1, 1); +MODULE_DEPEND(rtwn_pci, rtwn, 2, 2, 2); diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.h new file mode 100644 index 0000000000..c506bc75cf --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_attach.h @@ -0,0 +1,48 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_attach.h 307529 2016-10-17 20:38:24Z avos $ + */ + +void r92ce_attach(struct rtwn_pci_softc *); + +enum { + RTWN_CHIP_RTL8192CE, + RTWN_CHIP_MAX_PCI +}; + +struct rtwn_pci_ident { + uint16_t vendor; + uint16_t device; + const char *name; + int chip; +}; + +static const struct rtwn_pci_ident rtwn_pci_ident_table[] = { + { 0x10ec, 0x8176, "Realtek RTL8188CE", RTWN_CHIP_RTL8192CE }, + { 0, 0, NULL, RTWN_CHIP_MAX_PCI } +}; + +typedef void (*chip_pci_attach)(struct rtwn_pci_softc *); + +static const chip_pci_attach rtwn_chip_pci_attach[RTWN_CHIP_MAX_PCI] = { + [RTWN_CHIP_RTL8192CE] = r92ce_attach +}; + +static __inline void +rtwn_pci_attach_private(struct rtwn_pci_softc *pc, int chip) +{ + rtwn_chip_pci_attach[chip](pc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.c new file mode 100644 index 0000000000..f9a74e0361 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.c @@ -0,0 +1,123 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_reg.c 307529 2016-10-17 20:38:24Z avos $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + + +int +rtwn_pci_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + + bus_space_write_1(pc->pc_st, pc->pc_sh, addr, val); + + return (0); +} + +int +rtwn_pci_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + + val = htole16(val); + bus_space_write_2(pc->pc_st, pc->pc_sh, addr, val); + + return (0); +} + +int +rtwn_pci_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + + val = htole32(val); + bus_space_write_4(pc->pc_st, pc->pc_sh, addr, val); + + return (0); +} + +uint8_t +rtwn_pci_read_1(struct rtwn_softc *sc, uint16_t addr) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + + return (bus_space_read_1(pc->pc_st, pc->pc_sh, addr)); +} + +uint16_t +rtwn_pci_read_2(struct rtwn_softc *sc, uint16_t addr) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + uint16_t val; + + val = bus_space_read_2(pc->pc_st, pc->pc_sh, addr); + return le16toh(val); +} + +uint32_t +rtwn_pci_read_4(struct rtwn_softc *sc, uint16_t addr) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + uint32_t val; + + val = bus_space_read_4(pc->pc_st, pc->pc_sh, addr); + return le32toh(val); +} + +void +rtwn_pci_delay(struct rtwn_softc *sc, int usec) +{ + if (usec < 1000) + DELAY(usec); + else { + (void) mtx_sleep(sc, &sc->sc_mtx, 0, "rtwn_pci", + MAX(msecs_to_ticks(usec / 1000), 1)); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.h new file mode 100644 index 0000000000..ea25a70c53 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_reg.h @@ -0,0 +1,30 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTWN_PCI_REG_H +#define RTWN_PCI_REG_H + +int rtwn_pci_write_1(struct rtwn_softc *, uint16_t, uint8_t); +int rtwn_pci_write_2(struct rtwn_softc *, uint16_t, uint16_t); +int rtwn_pci_write_4(struct rtwn_softc *, uint16_t, uint32_t); +uint8_t rtwn_pci_read_1(struct rtwn_softc *, uint16_t); +uint16_t rtwn_pci_read_2(struct rtwn_softc *, uint16_t); +uint32_t rtwn_pci_read_4(struct rtwn_softc *, uint16_t); +void rtwn_pci_delay(struct rtwn_softc *, int); + +#endif /* RTWN_PCI_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.c new file mode 100644 index 0000000000..002ba774eb --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.c @@ -0,0 +1,317 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_rx.c 320725 2017-07-06 07:37:33Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + + +void +rtwn_pci_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nsegs, + int error) +{ + + if (error != 0) + return; + KASSERT(nsegs == 1, ("too many DMA segments, %d should be 1", nsegs)); + *(bus_addr_t *)arg = segs[0].ds_addr; +} + +void +rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *pc, + struct rtwn_rx_stat_pci *desc, bus_addr_t addr, size_t len, int idx) +{ + + memset(desc, 0, sizeof(*desc)); + desc->rxdw0 = htole32(SM(RTWN_RXDW0_PKTLEN, len) | + ((idx == RTWN_PCI_RX_LIST_COUNT - 1) ? RTWN_RXDW0_EOR : 0)); + desc->rxbufaddr = htole32(addr); + bus_space_barrier(pc->pc_st, pc->pc_sh, 0, pc->pc_mapsize, + BUS_SPACE_BARRIER_WRITE); + desc->rxdw0 |= htole32(RTWN_RXDW0_OWN); +} + +static void +rtwn_pci_rx_frame(struct rtwn_softc *sc, struct rtwn_rx_stat_pci *rx_desc, + int desc_idx) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_rx_ring *ring = &pc->rx_ring; + struct rtwn_rx_data *rx_data = &ring->rx_data[desc_idx]; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_node *ni; + uint32_t rxdw0; + struct mbuf *m, *m1; + int infosz, pktlen, shift, error; + + /* Dump Rx descriptor. */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC, + "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X, " + "addr: %08X (64: %08X)\n", + __func__, le32toh(rx_desc->rxdw0), le32toh(rx_desc->rxdw1), + le32toh(rx_desc->rxdw2), le32toh(rx_desc->rxdw3), + le32toh(rx_desc->rxdw4), le32toh(rx_desc->tsf_low), + le32toh(rx_desc->rxbufaddr), le32toh(rx_desc->rxbufaddr64)); + + rxdw0 = le32toh(rx_desc->rxdw0); + if (__predict_false(rxdw0 & (RTWN_RXDW0_CRCERR | RTWN_RXDW0_ICVERR))) { + /* + * This should not happen since we setup our Rx filter + * to not receive these frames. + */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: RX flags error (%s)\n", __func__, + rxdw0 & RTWN_RXDW0_CRCERR ? "CRC" : "ICV"); + goto fail; + } + + pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); + if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) || + pktlen > MJUMPAGESIZE)) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: frame is too short/long: %d\n", __func__, pktlen); + goto fail; + } + + infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8; + shift = MS(rxdw0, RTWN_RXDW0_SHIFT); + + m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE); + if (__predict_false(m1 == NULL)) { + device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n", + __func__); + goto fail; + } + bus_dmamap_sync(ring->data_dmat, rx_data->map, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(ring->data_dmat, rx_data->map); + + error = bus_dmamap_load(ring->data_dmat, rx_data->map, mtod(m1, void *), + MJUMPAGESIZE, rtwn_pci_dma_map_addr, &rx_data->paddr, 0); + if (error != 0) { + m_freem(m1); + + error = bus_dmamap_load(ring->data_dmat, rx_data->map, + mtod(rx_data->m, void *), MJUMPAGESIZE, + rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT); + if (error != 0) + panic("%s: could not load old RX mbuf", + device_get_name(sc->sc_dev)); + + /* Physical address may have changed. */ + rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, + MJUMPAGESIZE, desc_idx); + goto fail; + } + + /* Finalize mbuf. */ + m = rx_data->m; + rx_data->m = m1; + m->m_pkthdr.len = m->m_len = pktlen + infosz + shift; + + ni = rtwn_rx_common(sc, m, rx_desc); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: Rx frame len %d, infosz %d, shift %d\n", + __func__, pktlen, infosz, shift); + + /* Update RX descriptor. */ + rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE, + desc_idx); + + /* Send the frame to the 802.11 layer. */ + RTWN_UNLOCK(sc); + if (ni != NULL) { + (void)ieee80211_input_mimo(ni, m); + /* Node is no longer needed. */ + ieee80211_free_node(ni); + } else + (void)ieee80211_input_mimo_all(ic, m); + + RTWN_LOCK(sc); + + return; + +fail: + counter_u64_add(ic->ic_ierrors, 1); +} + +static void +rtwn_pci_tx_done(struct rtwn_softc *sc, int qid) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *ring = &pc->tx_ring[qid]; + struct rtwn_tx_desc_common *desc; + struct rtwn_tx_data *data; + + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: qid %d, last %d, cur %d\n", + __func__, qid, ring->last, ring->cur); + + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD); + + while(ring->last != ring->cur) { + data = &ring->tx_data[ring->last]; + desc = (struct rtwn_tx_desc_common *) + ((uint8_t *)ring->desc + sc->txdesc_len * ring->last); + + KASSERT(data->m != NULL, ("no mbuf")); + + if (desc->flags0 & RTWN_FLAGS0_OWN) + break; + + /* Unmap and free mbuf. */ + bus_dmamap_sync(ring->data_dmat, data->map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(ring->data_dmat, data->map); + + if (data->ni != NULL) { /* not a beacon frame */ + ieee80211_tx_complete(data->ni, data->m, 0); + + data->ni = NULL; + ring->queued--; + KASSERT(ring->queued >= 0, + ("ring->queued (qid %d) underflow!\n", qid)); + } else + m_freem(data->m); + + data->m = NULL; + ring->last = (ring->last + 1) % RTWN_PCI_TX_LIST_COUNT; +#ifndef D4054 + if (ring->queued > 0) + sc->sc_tx_timer = 5; + else + sc->sc_tx_timer = 0; +#endif + } + + if ((sc->qfullmsk & (1 << qid)) != 0 && + ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1)) { + sc->qfullmsk &= ~(1 << qid); + rtwn_start(sc); + } + +#ifdef IEEE80211_SUPPORT_SUPERG + /* + * If the TX active queue drops below a certain + * threshold, ensure we age fast-frames out so they're + * transmitted. + */ + if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && ring->queued <= 1) { + /* + * XXX TODO: just make this a callout timer schedule + * so we can flush the FF staging queue if we're + * approaching idle. + */ + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); + } +#endif +} + +static void +rtwn_pci_rx_done(struct rtwn_softc *sc) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_rx_ring *ring = &pc->rx_ring; + + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, BUS_DMASYNC_POSTREAD); + + for (;;) { + struct rtwn_rx_stat_pci *rx_desc = &ring->desc[ring->cur]; + + if (le32toh(rx_desc->rxdw0) & RTWN_RXDW0_OWN) + break; + + rtwn_pci_rx_frame(sc, rx_desc, ring->cur); + + if (!(sc->sc_flags & RTWN_RUNNING)) + return; + + ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT; + } +} + +void +rtwn_pci_intr(void *arg) +{ + struct rtwn_softc *sc = arg; + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + int i, status, tx_rings; + + RTWN_LOCK(sc); +#ifndef __HAIKU__ + status = rtwn_classify_intr(sc, &tx_rings, 0); + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: status %08X, tx_rings %08X\n", + __func__, status, tx_rings); + if (status == 0 && tx_rings == 0) + goto unlock; +#else + status = atomic_get(&pc->pc_intr_status); + tx_rings = atomic_get(&pc->pc_intr_tx_rings); +#endif + + if (status & RTWN_PCI_INTR_RX) { + rtwn_pci_rx_done(sc); + if (!(sc->sc_flags & RTWN_RUNNING)) + goto unlock; + } + + if (tx_rings != 0) + for (i = 0; i < RTWN_PCI_NTXQUEUES; i++) + if (tx_rings & (1 << i)) + rtwn_pci_tx_done(sc, i); + + if (sc->sc_flags & RTWN_RUNNING) + rtwn_pci_enable_intr(pc); +unlock: + RTWN_UNLOCK(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.h new file mode 100644 index 0000000000..9bb501988f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_rx.h @@ -0,0 +1,27 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_rx.h 320725 2017-07-06 07:37:33Z avos $ + */ + +#ifndef RTWN_PCI_RX_H +#define RTWN_PCI_RX_H + +void rtwn_pci_dma_map_addr(void *, bus_dma_segment_t *, int, int); +void rtwn_pci_setup_rx_desc(struct rtwn_pci_softc *, + struct rtwn_rx_stat_pci *, bus_addr_t, size_t, int); +void rtwn_pci_intr(void *); + +#endif /* RTWN_PCI_RX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.c new file mode 100644 index 0000000000..a8ca2984da --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.c @@ -0,0 +1,272 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_tx.c 308575 2016-11-12 17:58:37Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + + +static struct mbuf * +rtwn_mbuf_defrag(struct mbuf *m0, int how) +{ + struct mbuf *m = NULL; + + KASSERT(m0->m_flags & M_PKTHDR, + ("M_PKTHDR flag is absent (m %p)!", m0)); + + /* NB: we need _exactly_ one mbuf (no less, no more). */ + if (m0->m_pkthdr.len > MJUMPAGESIZE) { + /* XXX MJUM9BYTES? */ + return (NULL); + } else if (m0->m_pkthdr.len > MCLBYTES) { + m = m_getjcl(how, MT_DATA, M_PKTHDR, MJUMPAGESIZE); + if (m == NULL) + return (NULL); + + if (m_dup_pkthdr(m, m0, how) == 0) { + m_freem(m); + return (NULL); + } + + m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t)); + m->m_len = m->m_pkthdr.len; + m_freem(m0); + + return (m); + } else + return (m_defrag(m0, how)); +} + +static int +rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, uint8_t *tx_desc, uint8_t type) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *ring; + struct rtwn_tx_data *data; + struct rtwn_tx_desc_common *txd; + bus_dma_segment_t segs[1]; + uint8_t qid; + int nsegs, error; + + RTWN_ASSERT_LOCKED(sc); + + switch (type) { + case IEEE80211_FC0_TYPE_CTL: + case IEEE80211_FC0_TYPE_MGT: + qid = RTWN_PCI_MGNT_QUEUE; + break; + default: + qid = M_WME_GETAC(m); + break; + } + + ring = &pc->tx_ring[qid]; + data = &ring->tx_data[ring->cur]; + if (data->m != NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, + "%s: ring #%u is full (m %p)\n", __func__, qid, data->m); + return (ENOBUFS); + } + + txd = (struct rtwn_tx_desc_common *) + ((uint8_t *)ring->desc + sc->txdesc_len * ring->cur); + if (txd->flags0 & RTWN_FLAGS0_OWN) { + device_printf(sc->sc_dev, + "%s: OWN bit is set (tx desc %d, ring %u)!\n", + __func__, ring->cur, qid); + return (ENOBUFS); + } + + /* Copy Tx descriptor. */ + rtwn_pci_copy_tx_desc(pc, txd, tx_desc); + txd->pktlen = htole16(m->m_pkthdr.len); + txd->offset = sc->txdesc_len; + + error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, segs, + &nsegs, BUS_DMA_NOWAIT); + if (error != 0 && error != EFBIG) { + device_printf(sc->sc_dev, "can't map mbuf (error %d)\n", + error); + return (error); + } + if (error != 0) { + struct mbuf *mnew; + + mnew = rtwn_mbuf_defrag(m, M_NOWAIT); + if (mnew == NULL) { + device_printf(sc->sc_dev, "can't defragment mbuf\n"); + return (ENOBUFS); + } + m = mnew; + + error = bus_dmamap_load_mbuf_sg(ring->data_dmat, data->map, m, + segs, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, + "can't map mbuf (error %d)\n", error); + if (ni != NULL) { + if_inc_counter(ni->ni_vap->iv_ifp, + IFCOUNTER_OERRORS, 1); + ieee80211_free_node(ni); + } + m_freem(m); + return (0); /* XXX */ + } + } + + rtwn_pci_tx_postsetup(pc, txd, segs); + txd->flags0 |= RTWN_FLAGS0_OWN; + + /* Dump Tx descriptor. */ + rtwn_dump_tx_desc(sc, txd); + + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTWRITE); + + data->m = m; + data->ni = ni; + + ring->cur = (ring->cur + 1) % RTWN_PCI_TX_LIST_COUNT; + + ring->queued++; + if (ring->queued >= (RTWN_PCI_TX_LIST_COUNT - 1)) + sc->qfullmsk |= (1 << qid); + +#ifndef D4054 + sc->sc_tx_timer = 5; +#endif + + /* Kick TX. */ + rtwn_write_2(sc, R92C_PCIE_CTRL_REG, (1 << qid)); + + return (0); +} + +static int +rtwn_pci_tx_start_beacon(struct rtwn_softc *sc, struct mbuf *m, + uint8_t *tx_desc, int id) +{ + struct rtwn_pci_softc *pc = RTWN_PCI_SOFTC(sc); + struct rtwn_tx_ring *ring; + struct rtwn_tx_data *data; + struct rtwn_tx_desc_common *txd; + bus_dma_segment_t segs[1]; + int nsegs, error, own; + + RTWN_ASSERT_LOCKED(sc); + + KASSERT(id == 0 || id == 1, ("bogus vap id %d\n", id)); + + ring = &pc->tx_ring[RTWN_PCI_BEACON_QUEUE]; + data = &ring->tx_data[id]; + txd = (struct rtwn_tx_desc_common *) + ((uint8_t *)ring->desc + id * sc->txdesc_len); + + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_POSTREAD); + own = !!(txd->flags0 & RTWN_FLAGS0_OWN); + error = 0; + if (!own || txd->pktlen != htole16(m->m_pkthdr.len)) { + if (!own) { + /* Copy Tx descriptor. */ + rtwn_pci_copy_tx_desc(pc, txd, tx_desc); + txd->offset = sc->txdesc_len; + } else { + /* Reload mbuf. */ + bus_dmamap_unload(ring->data_dmat, data->map); + } + + error = bus_dmamap_load_mbuf_sg(ring->data_dmat, + data->map, m, segs, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) { + device_printf(sc->sc_dev, + "can't map beacon (error %d)\n", error); + txd->flags0 &= ~RTWN_FLAGS0_OWN; + goto end; + } + + txd->pktlen = htole16(m->m_pkthdr.len); + rtwn_pci_tx_postsetup(pc, txd, segs); + txd->flags0 |= RTWN_FLAGS0_OWN; +end: + bus_dmamap_sync(ring->desc_dmat, ring->desc_map, + BUS_DMASYNC_PREWRITE); + } + + /* Dump Tx descriptor. */ + rtwn_dump_tx_desc(sc, txd); + + bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); + + return (0); +} + +int +rtwn_pci_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id) +{ + int error = 0; + + RTWN_ASSERT_LOCKED(sc); + + if (ni == NULL) /* beacon frame */ + error = rtwn_pci_tx_start_beacon(sc, m, tx_desc, id); + else + error = rtwn_pci_tx_start_frame(sc, ni, m, tx_desc, type); + + return (error); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.h new file mode 100644 index 0000000000..a0ca98e1e8 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_tx.h @@ -0,0 +1,25 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_tx.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTWN_PCI_TX_H +#define RTWN_PCI_TX_H + +int rtwn_pci_tx_start(struct rtwn_softc *, struct ieee80211_node *, + struct mbuf *, uint8_t *, uint8_t, int); + +#endif /* RTWN_PCI_TX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_var.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_var.h new file mode 100644 index 0000000000..645ed6bc5b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/pci/rtwn_pci_var.h @@ -0,0 +1,142 @@ +/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/pci/rtwn_pci_var.h 320725 2017-07-06 07:37:33Z avos $ + */ + +#ifndef RTWN_PCI_VAR_H +#define RTWN_PCI_VAR_H + +#define RTWN_PCI_RX_LIST_COUNT 256 +#define RTWN_PCI_TX_LIST_COUNT 256 + +struct rtwn_rx_data { + bus_dmamap_t map; + struct mbuf *m; + bus_addr_t paddr; +}; + +struct rtwn_rx_ring { + struct rtwn_rx_stat_pci *desc; + bus_addr_t paddr; + bus_dma_tag_t desc_dmat; + bus_dmamap_t desc_map; + bus_dma_tag_t data_dmat; + bus_dma_segment_t seg; + struct rtwn_rx_data rx_data[RTWN_PCI_RX_LIST_COUNT]; + int cur; +}; + +struct rtwn_tx_data { + bus_dmamap_t map; + struct mbuf *m; + struct ieee80211_node *ni; +}; + +struct rtwn_tx_ring { + bus_addr_t paddr; + bus_dma_tag_t desc_dmat; + bus_dmamap_t desc_map; + bus_dma_tag_t data_dmat; + bus_dma_segment_t seg; + void *desc; + struct rtwn_tx_data tx_data[RTWN_PCI_TX_LIST_COUNT]; + int queued; + int cur; + int last; +}; + +/* + * TX queue indices. + */ +enum { + RTWN_PCI_BK_QUEUE, + RTWN_PCI_BE_QUEUE, + RTWN_PCI_VI_QUEUE, + RTWN_PCI_VO_QUEUE, + RTWN_PCI_BEACON_QUEUE, + RTWN_PCI_TXCMD_QUEUE, + RTWN_PCI_MGNT_QUEUE, + RTWN_PCI_HIGH_QUEUE, + RTWN_PCI_HCCA_QUEUE, + RTWN_PCI_NTXQUEUES +}; + +/* + * Interrupt events. + */ +enum { + RTWN_PCI_INTR_RX_ERROR = 0x00000001, + RTWN_PCI_INTR_RX_OVERFLOW = 0x00000002, + RTWN_PCI_INTR_RX_DESC_UNAVAIL = 0x00000004, + RTWN_PCI_INTR_RX_DONE = 0x00000008, + RTWN_PCI_INTR_TX_ERROR = 0x00000010, + RTWN_PCI_INTR_TX_OVERFLOW = 0x00000020, + RTWN_PCI_INTR_TX_REPORT = 0x00000040, + RTWN_PCI_INTR_PS_TIMEOUT = 0x00000080 +}; + +/* Shortcuts */ +/* Vendor driver treats RX errors like ROK... */ +#define RTWN_PCI_INTR_RX \ + (RTWN_PCI_INTR_RX_OVERFLOW | RTWN_PCI_INTR_RX_DESC_UNAVAIL | \ + RTWN_PCI_INTR_RX_DONE) + + +struct rtwn_pci_softc { + struct rtwn_softc pc_sc; /* must be the first */ + + struct resource *irq; + struct resource *mem; + bus_space_tag_t pc_st; + bus_space_handle_t pc_sh; + void *pc_ih; + bus_size_t pc_mapsize; + + struct rtwn_rx_ring rx_ring; + struct rtwn_tx_ring tx_ring[RTWN_PCI_NTXQUEUES]; + + /* must be set by the driver. */ + uint16_t pc_qmap; + uint32_t tcr; + + void (*pc_setup_tx_desc)(struct rtwn_pci_softc *, + void *, uint32_t); + void (*pc_tx_postsetup)(struct rtwn_pci_softc *, + void *, bus_dma_segment_t *); + void (*pc_copy_tx_desc)(void *, const void *); + void (*pc_enable_intr)(struct rtwn_pci_softc *); + +#ifdef __HAIKU__ + int32 pc_intr_status; + int32 pc_intr_tx_rings; +#endif +}; +#define RTWN_PCI_SOFTC(sc) ((struct rtwn_pci_softc *)(sc)) + +#define rtwn_pci_setup_tx_desc(_pc, _desc, _addr) \ + (((_pc)->pc_setup_tx_desc)((_pc), (_desc), (_addr))) +#define rtwn_pci_tx_postsetup(_pc, _txd, _segs) \ + (((_pc)->pc_tx_postsetup)((_pc), (_txd), (_segs))) +#define rtwn_pci_copy_tx_desc(_pc, _dest, _src) \ + (((_pc)->pc_copy_tx_desc)((_dest), (_src))) +#define rtwn_pci_enable_intr(_pc) \ + (((_pc)->pc_enable_intr)((_pc))) + +#endif /* RTWN_PCI_VAR_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e.h new file mode 100644 index 0000000000..2653e616ca --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e.h @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e.h 322949 2017-08-27 12:44:56Z avos $ + */ + +#ifndef RTL8188E_H +#define RTL8188E_H + +/* + * Global definitions. + */ +#define R88E_PUBQ_NPAGES 142 +#define R88E_TXPKTBUF_COUNT 177 +#define R88E_TX_PAGE_COUNT 169 + +#define R88E_MACID_MAX 63 +#define R88E_RX_DMA_BUFFER_SIZE 0x2400 + +#define R88E_INTR_MSG_LEN 60 + +#define R88E_CALIB_THRESHOLD 4 + + +/* + * Function declarations. + */ +/* r88e_beacon.c */ +void r88e_beacon_enable(struct rtwn_softc *, int, int); + +/* r88e_calib.c */ +void r88e_iq_calib(struct rtwn_softc *); +void r88e_temp_measure(struct rtwn_softc *); +uint8_t r88e_temp_read(struct rtwn_softc *); + +/* r88e_chan.c */ +void r88e_get_txpower(struct rtwn_softc *, int, + struct ieee80211_channel *, uint8_t[]); +void r88e_set_bw20(struct rtwn_softc *, uint8_t); +void r88e_set_gain(struct rtwn_softc *, uint8_t); + +/* r88e_fw.c */ +#ifndef RTWN_WITHOUT_UCODE +int r88e_fw_cmd(struct rtwn_softc *, uint8_t, const void *, int); +void r88e_fw_reset(struct rtwn_softc *, int); +void r88e_fw_download_enable(struct rtwn_softc *, int); +#endif +void r88e_macid_enable_link(struct rtwn_softc *, int, int); +void r88e_set_media_status(struct rtwn_softc *, int); +#ifndef RTWN_WITHOUT_UCODE +int r88e_set_rsvd_page(struct rtwn_softc *, int, int, int); +int r88e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); +#endif + +/* r88e_init.c */ +void r88e_init_bb(struct rtwn_softc *); +void r88e_init_rf(struct rtwn_softc *); +int r88e_power_on(struct rtwn_softc *); + +/* r88e_led.c */ +void r88e_set_led(struct rtwn_softc *, int, int); + +/* r88e_rf.c */ +void r88e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); + +/* r88e_rom.c */ +void r88e_parse_rom(struct rtwn_softc *, uint8_t *); + +/* r88e_rx.c */ +void r88e_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); +void r88e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); +int8_t r88e_get_rssi_cck(struct rtwn_softc *, void *); +int8_t r88e_get_rssi_ofdm(struct rtwn_softc *, void *); +void r88e_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, + const void *, const void *); + +/* r88e_tx.c */ +void r88e_tx_enable_ampdu(void *, int); +void r88e_tx_setup_hwseq(void *); +void r88e_tx_setup_macid(void *, int); + +#endif /* RTL8188E_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_beacon.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_beacon.c new file mode 100644 index 0000000000..88752d6a2e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_beacon.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_beacon.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + + +void +r88e_beacon_enable(struct rtwn_softc *sc, int id, int enable) +{ + + if (enable) { + rtwn_setbits_1(sc, R92C_MBID_NUM, 0, R88E_MBID_TXBCN_RPT(id)); + rtwn_setbits_1(sc, R92C_BCN_CTRL(id), + 0, R92C_BCN_CTRL_EN_BCN); + } else { + rtwn_setbits_1(sc, R92C_MBID_NUM, R88E_MBID_TXBCN_RPT(id), 0); + rtwn_setbits_1(sc, R92C_BCN_CTRL(id), + R92C_BCN_CTRL_EN_BCN, 0); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_calib.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_calib.c new file mode 100644 index 0000000000..c780fd3c0d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_calib.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_calib.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r88e_iq_calib(struct rtwn_softc *sc) +{ + /* XXX TODO */ +} + +void +r88e_temp_measure(struct rtwn_softc *sc) +{ + rtwn_rf_write(sc, 0, R88E_RF_T_METER, R88E_RF_T_METER_START); +} + +uint8_t +r88e_temp_read(struct rtwn_softc *sc) +{ + return (MS(rtwn_rf_read(sc, 0, R88E_RF_T_METER), + R88E_RF_T_METER_VAL)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_chan.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_chan.c new file mode 100644 index 0000000000..06903085ec --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_chan.c @@ -0,0 +1,153 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_chan.c 330750 2018-03-10 23:47:03Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +static int +r88e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t chan; + int group; + + chan = rtwn_chan2centieee(c); + if (IEEE80211_IS_CHAN_2GHZ(c)) { + if (chan <= 2) group = 0; + else if (chan <= 5) group = 1; + else if (chan <= 8) group = 2; + else if (chan <= 11) group = 3; + else if (chan <= 13) group = 4; + else if (chan <= 14) group = 5; + else { + KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); + return (-1); + } + } else { + KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); + return (-1); + } + + return (group); +} + +void +r88e_get_txpower(struct rtwn_softc *sc, int chain, + struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) +{ + struct r92c_softc *rs = sc->sc_priv; + const struct rtwn_r88e_txpwr *rt = rs->rs_txpwr; + uint8_t cckpow, ofdmpow, bw20pow, htpow = 0; + int max_mcs, ridx, group; + + /* Determine channel group. */ + group = r88e_get_power_group(sc, c); + if (group == -1) { /* shouldn't happen */ + device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); + return; + } + + /* XXX net80211 regulatory */ + + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); + KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n")); + + /* Compute per-CCK rate Tx power. */ + cckpow = rt->cck_tx_pwr[group]; + for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) { + power[ridx] = (ridx == RTWN_RIDX_CCK2) ? cckpow - 9 : cckpow; + } + + if (group < 5) + htpow = rt->ht40_tx_pwr[group]; + + /* Compute per-OFDM rate Tx power. */ + ofdmpow = htpow + rt->ofdm_tx_pwr_diff; + for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) + power[ridx] = ofdmpow; + + bw20pow = htpow + rt->bw20_tx_pwr_diff; + for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++) + power[ridx] = bw20pow; + + /* Apply max limit. */ + for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } +} + +void +r88e_set_bw20(struct rtwn_softc *sc, uint8_t chan) +{ + struct r92c_softc *rs = sc->sc_priv; + + rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ); + + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0); + rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); + + /* Select 20MHz bandwidth. */ + rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, + (rs->rf_chnlbw[0] & ~0xfff) | chan | R88E_RF_CHNLBW_BW20); +} + +void +r88e_set_gain(struct rtwn_softc *sc, uint8_t gain) +{ + + rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0), + R92C_OFDM0_AGCCORE1_GAIN_M, gain); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw.c new file mode 100644 index 0000000000..880e2cadd5 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw.c @@ -0,0 +1,225 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_fw.c 312002 2017-01-13 02:11:16Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +#ifndef RTWN_WITHOUT_UCODE +int +r88e_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) +{ + struct r88e_fw_cmd cmd; + int ntries, error; + + if (!(sc->sc_flags & RTWN_FW_LOADED)) { + RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware " + "was not loaded; command (id %d) will be discarded\n", + __func__, id); + return (0); + } + + /* Wait for current FW box to be empty. */ + for (ntries = 0; ntries < 100; ntries++) { + if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) + break; + rtwn_delay(sc, 2000); + } + if (ntries == 100) { + device_printf(sc->sc_dev, + "could not send firmware command\n"); + return (ETIMEDOUT); + } + memset(&cmd, 0, sizeof(cmd)); + cmd.id = id; + KASSERT(len <= sizeof(cmd.msg), + ("%s: firmware command too long (%d > %zu)\n", + __func__, len, sizeof(cmd.msg))); + memcpy(cmd.msg, buf, len); + + /* Write the first word last since that will trigger the FW. */ + if (len > 3) { + error = rtwn_write_4(sc, R88E_HMEBOX_EXT(sc->fwcur), + *(uint32_t *)((uint8_t *)&cmd + 4)); + if (error != 0) + return (error); + } + error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), *(uint32_t *)&cmd); + if (error != 0) + return (error); + + sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; + + return (0); +} + +void +r88e_fw_reset(struct rtwn_softc *sc, int reason) +{ + uint16_t reg; + + reg = rtwn_read_2(sc, R92C_SYS_FUNC_EN); + rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg & ~R92C_SYS_FUNC_EN_CPUEN); + rtwn_write_2(sc, R92C_SYS_FUNC_EN, reg | R92C_SYS_FUNC_EN_CPUEN); +} + +void +r88e_fw_download_enable(struct rtwn_softc *sc, int enable) +{ + if (enable) { + /* MCU firmware download enable. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN); + /* 8051 reset. */ + rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN, + 0, 2); + } else { + /* MCU download disable. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0); + /* Reserved for f/w extension. */ + rtwn_write_1(sc, R92C_MCUFWDL + 1, 0); + } +} +#endif + +void +r88e_macid_enable_link(struct rtwn_softc *sc, int id, int enable) +{ + uint32_t reg; + + reg = R88E_MACID_NO_LINK; + if (id > 32) + reg += 4; + + if (enable) + rtwn_setbits_4(sc, reg, 1 << (id % 32), 0); + else + rtwn_setbits_4(sc, reg, 0, 1 << (id % 32)); + + /* XXX max macid for tx reports */ +} + +void +r88e_set_media_status(struct rtwn_softc *sc, int macid) +{ + struct r88e_fw_cmd_msrrpt status; + + if (macid & RTWN_MACID_VALID) + status.msrb0 = R88E_MSRRPT_B0_ASSOC; + else + status.msrb0 = R88E_MSRRPT_B0_DISASSOC; + status.macid = (macid & ~RTWN_MACID_VALID); + + r88e_macid_enable_link(sc, status.macid, + (macid & RTWN_MACID_VALID) != 0); + +#ifndef RTWN_WITHOUT_UCODE + if (r88e_fw_cmd(sc, R88E_CMD_MSR_RPT, &status, sizeof(status)) != 0) { + device_printf(sc->sc_dev, "%s: cannot change media status!\n", + __func__); + } +#endif +} + +#ifndef RTWN_WITHOUT_UCODE +int +r88e_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null, + int qos_null) +{ + struct r88e_fw_cmd_rsvdpage rsvd; + + rsvd.probe_resp = probe_resp; + rsvd.ps_poll = 0; + rsvd.null_data = null; + rsvd.null_data_qos = qos_null; + rsvd.null_data_qos_bt = 0; + return (r88e_fw_cmd(sc, R88E_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd))); +} + +int +r88e_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, + int off) +{ + struct r88e_fw_cmd_pwrmode mode; + int error; + + if (off && vap->iv_state == IEEE80211_S_RUN && + (vap->iv_flags & IEEE80211_F_PMGTON)) { + mode.mode = R88E_PWRMODE_LEG; + /* + * TODO: switch to RFOFF state + * (something is missing here - Rx stops with it). + */ +#ifdef RTWN_TODO + mode.pwr_state = R88E_PWRMODE_STATE_RFOFF; +#else + mode.pwr_state = R88E_PWRMODE_STATE_RFON; +#endif + } else { + mode.mode = R88E_PWRMODE_CAM; + mode.pwr_state = R88E_PWRMODE_STATE_ALLON; + } + mode.pwrb1 = + SM(R88E_PWRMODE_B1_SMART_PS, R88E_PWRMODE_B1_LEG_NULLDATA) | + SM(R88E_PWRMODE_B1_RLBM, R88E_PWRMODE_B1_MODE_MIN); + /* XXX ignored */ + mode.bcn_pass = 0; + mode.queue_uapsd = 0; + error = r88e_fw_cmd(sc, R88E_CMD_SET_PWRMODE, &mode, sizeof(mode)); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: CMD_SET_PWRMODE was not sent, error %d\n", + __func__, error); + } + + return (error); +} +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw_cmd.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw_cmd.h new file mode 100644 index 0000000000..e755a084d5 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_fw_cmd.h @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2015 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_fw_cmd.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R88E_FW_CMD_H +#define R88E_FW_CMD_H + +/* + * Host to firmware commands. + */ +struct r88e_fw_cmd { + uint8_t id; +#define R88E_CMD_RSVD_PAGE 0x00 +#define R88E_CMD_MSR_RPT 0x01 +#define R88E_CMD_SET_PWRMODE 0x20 + + uint8_t msg[7]; +} __packed __attribute__((aligned(4))); + +/* Structure for R88E_CMD_RSVD_PAGE. */ +struct r88e_fw_cmd_rsvdpage { + uint8_t probe_resp; + uint8_t ps_poll; + uint8_t null_data; + uint8_t null_data_qos; + uint8_t null_data_qos_bt; +} __packed; + +/* Structure for R88E_CMD_MSR_RPT. */ +struct r88e_fw_cmd_msrrpt { + uint8_t msrb0; +#define R88E_MSRRPT_B0_DISASSOC 0x00 +#define R88E_MSRRPT_B0_ASSOC 0x01 + + uint8_t macid; +} __packed; + +/* Structure for R88E_CMD_SET_PWRMODE. */ +struct r88e_fw_cmd_pwrmode { + uint8_t mode; +#define R88E_PWRMODE_CAM 0 +#define R88E_PWRMODE_LEG 1 +#define R88E_PWRMODE_UAPSD 2 + + uint8_t pwrb1; +#define R88E_PWRMODE_B1_RLBM_M 0x0f +#define R88E_PWRMODE_B1_RLBM_S 0 +#define R88E_PWRMODE_B1_MODE_MIN 0 +#define R88E_PWRMODE_B1_MODE_MAX 1 +#define R88E_PWRMODE_B1_MODE_DTIM 2 + +#define R88E_PWRMODE_B1_SMART_PS_M 0xf0 +#define R88E_PWRMODE_B1_SMART_PS_S 4 +#define R88E_PWRMODE_B1_LEG_PSPOLL0 0 +#define R88E_PWRMODE_B1_LEG_PSPOLL1 1 +#define R88E_PWRMODE_B1_LEG_NULLDATA 2 +#define R88E_PWRMODE_B1_WMM_PSPOLL 0 +#define R88E_PWRMODE_B1_WMM_NULLDATA 1 + + uint8_t bcn_pass; + uint8_t queue_uapsd; + uint8_t pwr_state; +#define R88E_PWRMODE_STATE_RFOFF 0x00 +#define R88E_PWRMODE_STATE_RFON 0x04 +#define R88E_PWRMODE_STATE_ALLON 0x0c +} __packed; + +#endif /* R88E_FW_CMD_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_init.c new file mode 100644 index 0000000000..7411e78daf --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_init.c @@ -0,0 +1,158 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_init.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include +#include + + +static void +r88e_crystalcap_write(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + uint32_t reg; + uint8_t val; + + val = rs->crystalcap & 0x3f; + reg = rtwn_bb_read(sc, R92C_AFE_XTAL_CTRL); + rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, + RW(reg, R92C_AFE_XTAL_CTRL_ADDR, val | val << 6)); +} + +void +r88e_init_bb(struct rtwn_softc *sc) +{ + + /* Enable BB and RF. */ + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_DIO_RF); + + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | + R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); + + r92c_init_bb_common(sc); + + rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553422); + rtwn_delay(sc, 1); + rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x69553420); + rtwn_delay(sc, 1); + + r88e_crystalcap_write(sc); +} + +int +r88e_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + int ntries; + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip power up\n"); + return (ETIMEDOUT); + } + + /* Reset BB. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST, 0)); + + RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80)); + + /* Disable HWPDN. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APDM_HPDN, 0, 1)); + + /* Disable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + 0, R92C_APS_FSMCO_APFM_ONMAC, 1)); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Enable LDO normal mode. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, + R92C_LPLDO_CTRL_SLEEP, 0)); + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + return (0); +#undef RTWN_CHK +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_led.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_led.c new file mode 100644 index 0000000000..55d4e5a8c0 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_led.c @@ -0,0 +1,68 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_led.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + + +void +r88e_set_led(struct rtwn_softc *sc, int led, int on) +{ + + if (led == RTWN_LED_LINK) { + if (!on) { + rtwn_setbits_1(sc, R92C_LEDCFG2, 0x6f, + R92C_LEDCFG0_DIS); + rtwn_setbits_1(sc, R92C_MAC_PINMUX_CFG, 0x01, 0); + } else + rtwn_setbits_1(sc, R92C_LEDCFG2, 0x0f, 0x60); + sc->ledlink = on; /* Save LED state. */ + } + + /* XXX led #1? */ +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_priv.h new file mode 100644 index 0000000000..42c9eec77b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_priv.h @@ -0,0 +1,230 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_priv.h 320055 2017-06-17 14:39:25Z kevlo $ + */ + +#ifndef R88E_PRIV_H +#define R88E_PRIV_H + +#include + +/* + * Parsed Tx power (diff) values. + */ +struct rtwn_r88e_txpwr { + uint8_t cck_tx_pwr[R88E_GROUP_2G]; + uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1]; + int8_t ofdm_tx_pwr_diff; + int8_t bw20_tx_pwr_diff; +}; + + +/* + * MAC initialization values. + */ +static const struct rtwn_mac_prog rtl8188eu_mac[] = { + { 0x026, 0x41 }, { 0x027, 0x35 }, { 0x040, 0x00 }, { 0x428, 0x0a }, + { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x01 }, { 0x432, 0x02 }, + { 0x433, 0x04 }, { 0x434, 0x05 }, { 0x435, 0x06 }, { 0x436, 0x07 }, + { 0x437, 0x08 }, { 0x438, 0x00 }, { 0x439, 0x00 }, { 0x43a, 0x01 }, + { 0x43b, 0x02 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, { 0x43e, 0x06 }, + { 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 }, { 0x442, 0x00 }, + { 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f }, { 0x447, 0x00 }, + { 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 }, { 0x45b, 0xb9 }, + { 0x460, 0x66 }, { 0x461, 0x66 }, { 0x480, 0x08 }, { 0x4c8, 0xff }, + { 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff }, { 0x4ce, 0x01 }, + { 0x4d3, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, { 0x502, 0x2f }, + { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, { 0x506, 0x5e }, + { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, { 0x50a, 0x5e }, + { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, { 0x50e, 0x00 }, + { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, { 0x516, 0x0a }, + { 0x525, 0x4f }, { 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, + { 0x55d, 0xff }, { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, + { 0x620, 0xff }, { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, + { 0x624, 0xff }, { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, + { 0x652, 0x20 }, { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, + { 0x63f, 0x0e }, { 0x640, 0x40 }, { 0x66e, 0x05 }, { 0x700, 0x21 }, + { 0x701, 0x43 }, { 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 }, + { 0x709, 0x43 }, { 0x70a, 0x65 }, { 0x70b, 0x87 } +}; + +/* + * Baseband initialization values. + */ +static const uint16_t rtl8188eu_bb_regs[] = { + 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c, + 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, + 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, + 0x860, 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, + 0x880, 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, + 0x900, 0x904, 0x908, 0x90c, 0x910, 0x914, 0xa00, 0xa04, + 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24, + 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xb2c, + 0xc00, 0xc04, 0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, + 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, + 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, 0xc5c, + 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c, + 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, 0xc98, 0xc9c, + 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, 0xcbc, + 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc, + 0xce0, 0xce4, 0xce8, 0xcec, 0xd00, 0xd04, 0xd08, 0xd0c, + 0xd10, 0xd14, 0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, 0xd3c, + 0xd40, 0xd44, 0xd48, 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c, + 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74, 0xd78, 0xe00, + 0xe04, 0xe08, 0xe10, 0xe14, 0xe18, 0xe1c, 0xe28, 0xe30, + 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, 0xe48, 0xe4c, 0xe50, + 0xe54, 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xee8, 0xeec, 0xf14, 0xf4c, 0xf00 +}; + +static const uint32_t rtl8188eu_bb_vals[] = { + 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331, + 0x020c3d10, 0x02200385, 0x00000000, 0x01000100, 0x00390204, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00010000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x569a11a9, 0x01000014, 0x66f60110, + 0x061f0649, 0x00000000, 0x27272700, 0x07000760, 0x25004000, + 0x00000808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000, + 0xccc000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00706050, + 0x00000000, 0x00000023, 0x00000000, 0x81121111, 0x00000002, + 0x00000201, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e7f120f, + 0x9500bb78, 0x1114d028, 0x00881117, 0x89140f00, 0x1a1b0000, + 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, + 0x00000900, 0x225b0606, 0x218075b1, 0x80000000, 0x48071d40, + 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100, + 0x08800000, 0x40000100, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x69e9ac47, 0x469652af, 0x49795994, 0x0a97971c, + 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, 0x69553420, + 0x43bc0094, 0x00013169, 0x00250492, 0x00000000, 0x7112848b, + 0x47c00bff, 0x00000036, 0x2c7f000d, 0x020610db, 0x0000001f, + 0x00b91612, 0x390000e4, 0x20f60000, 0x40000100, 0x20200000, + 0x00091521, 0x00000000, 0x00121820, 0x00007f7f, 0x00000000, + 0x000300a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x28000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x64b22427, 0x00766932, + 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, 0x00000740, + 0x00020401, 0x0000907f, 0x20010201, 0xa0633333, 0x3333bc43, + 0x7a8f5b6f, 0xcc979975, 0x00000000, 0x80608000, 0x00000000, + 0x00127353, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x6437140a, 0x00000000, 0x00000282, 0x30032064, 0x4653de68, + 0x04518a3c, 0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220, + 0x000e3c24, 0x2d2d2d2d, 0x2d2d2d2d, 0x0390272d, 0x2d2d2d2d, + 0x2d2d2d2d, 0x2d2d2d2d, 0x2d2d2d2d, 0x00000000, 0x1000dc1f, + 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800, + 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102, + 0x28160d05, 0x00000008, 0x001b25a4, 0x00c00014, 0x00c00014, + 0x01000014, 0x01000014, 0x01000014, 0x01000014, 0x00c00014, + 0x01000014, 0x00c00014, 0x00c00014, 0x00c00014, 0x00c00014, + 0x00000014, 0x00000014, 0x21555448, 0x01c00014, 0x00000003, + 0x00000000, 0x00000300 +}; + +static const struct rtwn_bb_prog rtl8188eu_bb[] = { + { + nitems(rtl8188eu_bb_regs), + rtl8188eu_bb_regs, + rtl8188eu_bb_vals, + { 0 }, + NULL + } +}; + +static const uint32_t rtl8188eu_agc_vals[] = { + 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001, + 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001, + 0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001, + 0xf10f0001, 0xf0100001, 0xef110001, 0xee120001, 0xed130001, + 0xec140001, 0xeb150001, 0xea160001, 0xe9170001, 0xe8180001, + 0xe7190001, 0xe61a0001, 0xe51b0001, 0xe41c0001, 0xe31d0001, + 0xe21e0001, 0xe11f0001, 0x8a200001, 0x89210001, 0x88220001, + 0x87230001, 0x86240001, 0x85250001, 0x84260001, 0x83270001, + 0x82280001, 0x6b290001, 0x6a2a0001, 0x692b0001, 0x682c0001, + 0x672d0001, 0x662e0001, 0x652f0001, 0x64300001, 0x63310001, + 0x62320001, 0x61330001, 0x46340001, 0x45350001, 0x44360001, + 0x43370001, 0x42380001, 0x41390001, 0x403a0001, 0x403b0001, + 0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001, + 0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001, + 0xfb460001, 0xfb470001, 0xfb480001, 0xfa490001, 0xf94a0001, + 0xf84B0001, 0xf74c0001, 0xf64d0001, 0xf54e0001, 0xf44f0001, + 0xf3500001, 0xf2510001, 0xf1520001, 0xf0530001, 0xef540001, + 0xee550001, 0xed560001, 0xec570001, 0xeb580001, 0xea590001, + 0xe95a0001, 0xe85b0001, 0xe75c0001, 0xe65d0001, 0xe55e0001, + 0xe45f0001, 0xe3600001, 0xe2610001, 0xc3620001, 0xc2630001, + 0xc1640001, 0x8b650001, 0x8a660001, 0x89670001, 0x88680001, + 0x87690001, 0x866a0001, 0x856b0001, 0x846c0001, 0x676d0001, + 0x666e0001, 0x656f0001, 0x64700001, 0x63710001, 0x62720001, + 0x61730001, 0x60740001, 0x46750001, 0x45760001, 0x44770001, + 0x43780001, 0x42790001, 0x417a0001, 0x407b0001, 0x407c0001, + 0x407d0001, 0x407e0001, 0x407f0001 +}; + +static const struct rtwn_agc_prog rtl8188eu_agc[] = { + { + nitems(rtl8188eu_agc_vals), + rtl8188eu_agc_vals, + { 0 }, + NULL + } +}; + +/* + * RF initialization values. + */ +static const uint8_t rtl8188eu_rf_regs[] = { + 0x00, 0x08, 0x18, 0x19, 0x1e, 0x1f, 0x2f, 0x3f, 0x42, 0x57, + 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb6, 0xb7, 0xb8, + 0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xdf, 0xef, 0x51, 0x52, 0x53, 0x56, + 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0xb6, 0x18, 0x5a, + 0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0x00, 0x18, 0xfe, 0xfe, + 0x1f, 0xfe, 0xfe, 0x1e, 0x1f, 0x00 +}; + +static const uint32_t rtl8188eu_rf_vals[] = { + 0x30000, 0x84000, 0x00407, 0x00012, 0x80009, 0x00880, 0x1a060, + 0x00000, 0x060c0, 0xd0000, 0xbe180, 0x01552, 0x00000, 0xff8fc, + 0x54400, 0xccc19, 0x43003, 0x4953e, 0x1c718, 0x060ff, 0x80001, + 0x40000, 0x00400, 0xc0000, 0x02400, 0x00009, 0x40c91, 0x99999, + 0x000a3, 0x88820, 0x76c06, 0x00000, 0x80000, 0x00180, 0x001a0, + 0x6b27d, 0x7e49d, 0x00073, 0x51ff3, 0x00086, 0x00186, + 0x00286, 0x01c25, 0x09c25, 0x11c25, 0x19c25, 0x48538, 0x00c07, + 0x4bd00, 0x739d0, 0x0adf3, 0x09df0, 0x08ded, 0x07dea, 0x06de7, + 0x054ee, 0x044eb, 0x034e8, 0x0246b, 0x01468, 0x0006d, 0x30159, + 0x68200, 0x000ce, 0x48a00, 0x65540, 0x88000, 0x020a0, 0xf02b0, + 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, 0x90080, 0x8f780, + 0x722b0, 0x6f7b0, 0x54fb0, 0x4f060, 0x30090, 0x20080, 0x10080, + 0x0f780, 0x000a0, 0x10159, 0x0f407, 0x0c350, 0x0c350, 0x80003, + 0x0c350, 0x0c350, 0x00001, 0x80000, 0x33e60 +}; + +static const struct rtwn_rf_prog rtl8188eu_rf[] = { + { + nitems(rtl8188eu_rf_regs), + rtl8188eu_rf_regs, + rtl8188eu_rf_vals, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL } +}; + +#endif /* R88E_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_reg.h new file mode 100644 index 0000000000..a9ea5b312c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_reg.h @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R88E_REG_H +#define R88E_REG_H + +#include + +/* + * MAC registers. + */ +/* System Configuration. */ +#define R88E_BB_PAD_CTRL 0x064 +#define R88E_HIMR 0x0b0 +#define R88E_HISR 0x0b4 +#define R88E_HIMRE 0x0b8 +#define R88E_HISRE 0x0bc +/* MAC General Configuration. */ +#define R88E_32K_CTRL 0x194 +#define R88E_HMEBOX_EXT(idx) (0x1f0 + (idx) * 4) +/* Protocol Configuration. */ +#define R88E_TXPKTBUF_BCNQ1_BDNY 0x457 +#define R88E_MACID_NO_LINK 0x484 +#define R88E_TX_RPT_CTRL 0x4ec +#define R88E_TX_RPT_MACID_MAX 0x4ed +#define R88E_TX_RPT_TIME 0x4f0 +#define R88E_SCH_TXCMD 0x5f8 + + +/* Bits for R88E_HIMR. */ +#define R88E_HIMR_CPWM 0x00000100 +#define R88E_HIMR_CPWM2 0x00000200 +#define R88E_HIMR_TBDER 0x04000000 +#define R88E_HIMR_PSTIMEOUT 0x20000000 + +/* Bits for R88E_HIMRE.*/ +#define R88E_HIMRE_RXFOVW 0x00000100 +#define R88E_HIMRE_TXFOVW 0x00000200 +#define R88E_HIMRE_RXERR 0x00000400 +#define R88E_HIMRE_TXERR 0x00000800 + +/* Bits for R88E_TX_RPT_CTRL. */ +#define R88E_TX_RPT1_ENA 0x01 +#define R88E_TX_RPT2_ENA 0x02 + +/* Bits for R92C_MBID_NUM. */ +#define R88E_MBID_TXBCN_RPT(id) (0x08 << (id)) + +/* Bits for R92C_SECCFG. */ +#define R88E_SECCFG_CHK_KEYID 0x0100 + + +/* + * Baseband registers. + */ +/* Bits for R92C_LSSI_PARAM(i). */ +#define R88E_LSSI_PARAM_ADDR_M 0x0ff00000 +#define R88E_LSSI_PARAM_ADDR_S 20 + + +/* + * RF (6052) registers. + */ +#define R88E_RF_T_METER 0x42 + +/* Bits for R92C_RF_CHNLBW. */ +#define R88E_RF_CHNLBW_BW20 0x00c00 + +/* Bits for R88E_RF_T_METER. */ +#define R88E_RF_T_METER_VAL_M 0x0fc00 +#define R88E_RF_T_METER_VAL_S 10 +#define R88E_RF_T_METER_START 0x30000 + +#endif /* R88E_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rf.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rf.c new file mode 100644 index 0000000000..57337aa07e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rf.c @@ -0,0 +1,60 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rf.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r88e_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val) +{ + rtwn_bb_write(sc, R92C_LSSI_PARAM(chain), + SM(R88E_LSSI_PARAM_ADDR, addr) | + SM(R92C_LSSI_PARAM_DATA, val)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom.c new file mode 100644 index 0000000000..2dff9fd60c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom.c @@ -0,0 +1,85 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rom.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + + +void +r88e_parse_rom(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r92c_softc *rs = sc->sc_priv; + struct rtwn_r88e_txpwr *rt = rs->rs_txpwr; + struct r88e_rom *rom = (struct r88e_rom *)buf; + int i; + + rt->bw20_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, HIGH_PART)); + rt->ofdm_tx_pwr_diff = RTWN_SIGN4TO8(MS(rom->tx_pwr_diff, LOW_PART)); + for (i = 0; i < nitems(rom->cck_tx_pwr); i++) + rt->cck_tx_pwr[i] = rom->cck_tx_pwr[i]; + for (i = 0; i < nitems(rom->ht40_tx_pwr); i++) + rt->ht40_tx_pwr[i] = rom->ht40_tx_pwr[i]; + + rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap, + R88E_ROM_CRYSTALCAP_DEF); + rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY); + rs->board_type = + MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE), + R92C_ROM_RF1_BOARD_TYPE); + RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type %d\n", + __func__,rs->regulatory); + + sc->thermal_meter = rom->thermal_meter; + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_defs.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_defs.h new file mode 100644 index 0000000000..21a199f595 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_defs.h @@ -0,0 +1,29 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rom_defs.h 319649 2017-06-07 09:10:24Z kevlo $ + */ + +#ifndef R88E_ROM_DEFS_H +#define R88E_ROM_DEFS_H + +#include + +#define R88E_GROUP_2G 6 + +#define R88E_EFUSE_MAX_LEN 256 +#define R88E_EFUSE_MAP_LEN 512 + +#endif /* R88E_ROM_DEFS_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_image.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_image.h new file mode 100644 index 0000000000..9a99fe33f2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rom_image.h @@ -0,0 +1,60 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rom_image.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R88E_ROM_IMAGE_H +#define R88E_ROM_IMAGE_H + +#include + +/* + * RTL8188EU ROM image. + */ +struct r88e_rom { + uint8_t reserved1[16]; + uint8_t cck_tx_pwr[R88E_GROUP_2G]; + uint8_t ht40_tx_pwr[R88E_GROUP_2G - 1]; + uint8_t tx_pwr_diff; + uint8_t reserved2[156]; + uint8_t channel_plan; + uint8_t crystalcap; +#define R88E_ROM_CRYSTALCAP_DEF 0x20 + + uint8_t thermal_meter; + uint8_t reserved3[6]; + uint8_t rf_board_opt; + uint8_t rf_feature_opt; + uint8_t rf_bt_opt; + uint8_t version; + uint8_t customer_id; + uint8_t reserved4[3]; + uint8_t rf_ant_opt; + uint8_t reserved5[6]; + uint16_t vid; + uint16_t pid; + uint8_t usb_opt; + uint8_t reserved6[2]; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint8_t reserved7[2]; + uint8_t string[33]; /* "realtek 802.11n NIC" */ + uint8_t reserved8[256]; +} __packed; + +_Static_assert(sizeof(struct r88e_rom) == R88E_EFUSE_MAP_LEN, + "R88E_EFUSE_MAP_LEN must be equal to sizeof(struct r88e_rom)!"); + +#endif /* R88E_ROM_IMAGE_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx.c new file mode 100644 index 0000000000..491d8d3b89 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx.c @@ -0,0 +1,229 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rx.c 331043 2018-03-16 01:03:10Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + + +void +r88e_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) +{ +#if __FreeBSD_version >= 1200012 + struct ieee80211_ratectl_tx_status txs; +#endif + struct r88e_tx_rpt_ccx *rpt; + struct ieee80211_node *ni; + uint8_t macid; + int ntries; + + /* Skip Rx descriptor. */ + buf += sizeof(struct r92c_rx_stat); + len -= sizeof(struct r92c_rx_stat); + + rpt = (struct r88e_tx_rpt_ccx *)buf; + if (len != sizeof(*rpt)) { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: wrong report size (%d, must be %zu)\n", + __func__, len, sizeof(*rpt)); + return; + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: ccx report dump: 0: %02X, 1: %02X, 2: %02X, queue time: " + "low %02X, high %02X, final ridx: %02X, 6: %02X, 7: %02X\n", + __func__, rpt->rptb0, rpt->rptb1, rpt->rptb2, rpt->queue_time_low, + rpt->queue_time_high, rpt->final_rate, rpt->rptb6, rpt->rptb7); + + macid = MS(rpt->rptb1, R88E_RPTB1_MACID); + if (macid > sc->macid_limit) { + device_printf(sc->sc_dev, + "macid %u is too big; increase MACID_MAX limit\n", + macid); + return; + } + + ntries = MS(rpt->rptb2, R88E_RPTB2_RETRY_CNT); + + ni = sc->node_list[macid]; + if (ni != NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was" + "%s sent (%d retries)\n", __func__, macid, + (rpt->rptb1 & R88E_RPTB1_PKT_OK) ? "" : " not", + ntries); + +#if __FreeBSD_version >= 1200012 + txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY | + IEEE80211_RATECTL_STATUS_FINAL_RATE; + txs.long_retries = ntries; + if (rpt->final_rate > RTWN_RIDX_OFDM54) { /* MCS */ + txs.final_rate = + rpt->final_rate - RTWN_RIDX_HT_MCS_SHIFT; + txs.final_rate |= IEEE80211_RATE_MCS; + } else + txs.final_rate = ridx2rate[rpt->final_rate]; + if (rpt->rptb1 & R88E_RPTB1_PKT_OK) + txs.status = IEEE80211_RATECTL_TX_SUCCESS; + else if (rpt->rptb2 & R88E_RPTB2_RETRY_OVER) + txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; + else if (rpt->rptb2 & R88E_RPTB2_LIFE_EXPIRE) + txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + else + txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + ieee80211_ratectl_tx_complete(ni, &txs); +#else + struct ieee80211vap *vap = ni->ni_vap; + if (rpt->rptb1 & R88E_RPTB1_PKT_OK) { + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); + } else { + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); + } +#endif + } else { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n", + __func__, macid); + } +} + +void +r88e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + + /* Skip Rx descriptor. */ + buf += sizeof(struct r92c_rx_stat); + len -= sizeof(struct r92c_rx_stat); + + if (len != R88E_INTR_MSG_LEN) { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: wrong interrupt message size (%d, must be %d)\n", + __func__, len, R88E_INTR_MSG_LEN); + return; + } + + /* XXX TODO */ +} + +int8_t +r88e_get_rssi_cck(struct rtwn_softc *sc, void *physt) +{ + struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt; + int8_t lna_idx, vga_idx, rssi; + + lna_idx = (phy->agc_rpt & 0xe0) >> 5; + vga_idx = (phy->agc_rpt & 0x1f); + rssi = 6 - 2 * vga_idx; + + switch (lna_idx) { + case 7: + if (vga_idx > 27) + rssi = -100 + 6; + else + rssi += -100 + 2 * 27; + break; + case 6: + rssi += -48 + 2 * 2; + break; + case 5: + rssi += -42 + 2 * 7; + break; + case 4: + rssi += -36 + 2 * 7; + break; + case 3: + rssi += -24 + 2 * 7; + break; + case 2: + rssi += -6 + 2 * 5; + if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) + rssi -= 6; + break; + case 1: + rssi += 8; + break; + case 0: + rssi += 14; + break; + } + + return (rssi); +} + +int8_t +r88e_get_rssi_ofdm(struct rtwn_softc *sc, void *physt) +{ + struct r88e_rx_phystat *phy = (struct r88e_rx_phystat *)physt; + int rssi; + + /* Get average RSSI. */ + rssi = ((phy->sig_qual >> 1) & 0x7f) - 110; + + return (rssi); +} + +void +r88e_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, + const void *desc, const void *physt_ptr) +{ + const struct r88e_rx_phystat *physt = physt_ptr; + + r92c_get_rx_stats(sc, rxs, desc, physt_ptr); + + if (!sc->sc_ht40) { /* XXX center channel */ + rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; + rxs->c_ieee = physt->chan; + rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee, + IEEE80211_CHAN_2GHZ); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx_desc.h new file mode 100644 index 0000000000..98b465f62c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_rx_desc.h @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_rx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R88E_RX_DESC_H +#define R88E_RX_DESC_H + +#include + +/* Rx MAC descriptor defines (chip-specific). */ +/* Rx dword 3 */ +#define R88E_RXDW3_RPT_M 0x0000c000 +#define R88E_RXDW3_RPT_S 14 +#define R88E_RXDW3_RPT_RX 0 +#define R88E_RXDW3_RPT_TX1 1 +#define R88E_RXDW3_RPT_TX2 2 +#define R88E_RXDW3_RPT_HIS 3 + +/* Rx PHY descriptor. */ +struct r88e_rx_phystat { + uint8_t path_agc[2]; + uint8_t chan; + uint8_t reserved1; + uint8_t sig_qual; + uint8_t agc_rpt; + uint8_t rpt_b; + uint8_t reserved2; + uint8_t noise_power; + uint8_t path_cfotail[2]; + uint8_t pcts_mask[2]; + uint8_t stream_rxevm[2]; + uint8_t path_rxsnr[2]; + uint8_t noise_power_db_lsb; + uint8_t reserved3[3]; + uint8_t stream_csi[2]; + uint8_t stream_target_csi[2]; + uint8_t sig_evm; +} __packed; + +/* Tx report (type 1). */ +struct r88e_tx_rpt_ccx { + uint8_t rptb0; +#define R88E_RPTB6_PKT_NUM_M 0x0e +#define R88E_RPTB6_PKT_NUM_S 1 +#define R88E_RPTB0_INT_CCX 0x80 + + uint8_t rptb1; +#define R88E_RPTB1_MACID_M 0x3f +#define R88E_RPTB1_MACID_S 0 +#define R88E_RPTB1_PKT_OK 0x40 +#define R88E_RPTB1_BMC 0x80 + + uint8_t rptb2; +#define R88E_RPTB2_RETRY_CNT_M 0x3f +#define R88E_RPTB2_RETRY_CNT_S 0 +#define R88E_RPTB2_LIFE_EXPIRE 0x40 +#define R88E_RPTB2_RETRY_OVER 0x80 + + uint8_t queue_time_low; + uint8_t queue_time_high; + uint8_t final_rate; + uint8_t rptb6; +#define R88E_RPTB6_QSEL_M 0xf0 +#define R88E_RPTB6_QSEL_S 4 + + uint8_t rptb7; +} __packed; + +/* Interrupt message format. */ +/* XXX recheck */ +struct r88e_intr_msg { + uint8_t c2h_id; + uint8_t c2h_seq; + uint8_t c2h_evt; + uint8_t reserved1[13]; + uint8_t cpwm1; + uint8_t reserved2[3]; + uint8_t cpwm2; + uint8_t reserved3[27]; + uint32_t hisr; + uint32_t hisr_ex; +}; + +#endif /* R88E_RX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx.c new file mode 100644 index 0000000000..a66a055210 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx.c @@ -0,0 +1,79 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_tx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r88e_tx_enable_ampdu(void *buf, int enable) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + if (enable) + txd->txdw2 |= htole32(R88E_TXDW2_AGGEN); + else + txd->txdw2 |= htole32(R88E_TXDW2_AGGBK); +} + +void +r88e_tx_setup_hwseq(void *buf) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + txd->txdseq |= htole16(R88E_TXDSEQ_HWSEQ_EN); +} + +void +r88e_tx_setup_macid(void *buf, int id) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + txd->txdw1 |= htole32(SM(R88E_TXDW1_MACID, id)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx_desc.h new file mode 100644 index 0000000000..51f8f1045c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/r88e_tx_desc.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/r88e_tx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R88E_TX_DESC_H +#define R88E_TX_DESC_H + +#include + +/* Tx MAC descriptor defines (chip-specific). */ +/* Tx dword 1. */ +#define R88E_TXDW1_MACID_M 0x0000003f +#define R88E_TXDW1_MACID_S 0 + +/* Tx dword 2. */ +#define R88E_TXDW2_AGGEN 0x00001000 +#define R88E_TXDW2_AGGBK 0x00010000 + +/* Tx dword 3. */ +#define R88E_TXDSEQ_HWSEQ_EN 0x8000 + +#endif /* R88E_TX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu.h new file mode 100644 index 0000000000..6e00c541e2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTL8188EU_H +#define RTL8188EU_H + +#include + + +/* + * Function declarations. + */ +/* r88eu_init.c */ +void r88eu_power_off(struct rtwn_softc *); +void r88eu_init_intr(struct rtwn_softc *); +void r88eu_init_rx_agg(struct rtwn_softc *); +void r88eu_post_init(struct rtwn_softc *); + +/* r88eu_rx.c */ +int r88eu_classify_intr(struct rtwn_softc *, void *, int); + +#endif /* RTL8188EU_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_attach.c new file mode 100644 index 0000000000..9c17585ca1 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_attach.c @@ -0,0 +1,218 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_attach.c 320055 2017-06-17 14:39:25Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include + +#include + +#include + + +static struct rtwn_r88e_txpwr r88e_txpwr; + +void r88eu_attach(struct rtwn_usb_softc *); + +static void +r88e_postattach(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + struct ieee80211com *ic = &sc->sc_ic; + + rs->rs_scan_start = ic->ic_scan_start; + ic->ic_scan_start = r92c_scan_start; + rs->rs_scan_end = ic->ic_scan_end; + ic->ic_scan_end = r92c_scan_end; +} + +static void +r88eu_attach_private(struct rtwn_softc *sc) +{ + struct r92c_softc *rs; + + rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); + + rs->rs_txpwr = &r88e_txpwr; + rs->rs_txagc = NULL; + + rs->rs_set_bw20 = r88e_set_bw20; + rs->rs_get_txpower = r88e_get_txpower; + rs->rs_set_gain = r88e_set_gain; + rs->rs_tx_enable_ampdu = r88e_tx_enable_ampdu; + rs->rs_tx_setup_hwseq = r88e_tx_setup_hwseq; + rs->rs_tx_setup_macid = r88e_tx_setup_macid; + rs->rs_set_name = rtwn_nop_softc; /* not used */ + + rs->rf_read_delay[0] = 10; + rs->rf_read_delay[1] = 100; + rs->rf_read_delay[2] = 10; + + sc->sc_priv = rs; +} + +static void +r88eu_adj_devcaps(struct rtwn_softc *sc) +{ + /* XXX TODO? */ +} + +void +r88eu_attach(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + + /* USB part. */ + uc->uc_align_rx = r92cu_align_rx; + uc->tx_agg_desc_num = 6; + + /* Common part. */ + sc->sc_flags = RTWN_FLAG_EXT_HDR; + + sc->sc_set_chan = r92c_set_chan; + sc->sc_fill_tx_desc = r92c_fill_tx_desc; + sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; + sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; + sc->sc_dump_tx_desc = r92cu_dump_tx_desc; + sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; + sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; + sc->sc_get_rx_stats = r88e_get_rx_stats; + sc->sc_get_rssi_cck = r88e_get_rssi_cck; + sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; + sc->sc_classify_intr = r88eu_classify_intr; + sc->sc_handle_tx_report = r88e_ratectl_tx_complete; + sc->sc_handle_c2h_report = r88e_handle_c2h_report; + sc->sc_check_frame = rtwn_nop_int_softc_mbuf; + sc->sc_rf_read = r92c_rf_read; + sc->sc_rf_write = r88e_rf_write; + sc->sc_check_condition = r92c_check_condition; + sc->sc_efuse_postread = rtwn_nop_softc; + sc->sc_parse_rom = r88e_parse_rom; + sc->sc_set_led = r88e_set_led; + sc->sc_power_on = r88e_power_on; + sc->sc_power_off = r88eu_power_off; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_fw_reset = r88e_fw_reset; + sc->sc_fw_download_enable = r88e_fw_download_enable; +#endif + sc->sc_llt_init = r92c_llt_init; + sc->sc_set_page_size = r92c_set_page_size; + sc->sc_lc_calib = r92c_lc_calib; + sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */ + sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; + sc->sc_adj_devcaps = r88eu_adj_devcaps; + sc->sc_vap_preattach = rtwn_nop_softc_vap; + sc->sc_postattach = r88e_postattach; + sc->sc_detach_private = r92c_detach_private; + sc->sc_set_media_status = r88e_set_media_status; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_set_rsvd_page = r88e_set_rsvd_page; + sc->sc_set_pwrmode = r88e_set_pwrmode; + sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */ +#endif + sc->sc_beacon_init = r92c_beacon_init; + sc->sc_beacon_enable = r88e_beacon_enable; + sc->sc_beacon_set_rate = rtwn_nop_void_int; + sc->sc_beacon_select = rtwn_nop_softc_int; + sc->sc_temp_measure = r88e_temp_measure; + sc->sc_temp_read = r88e_temp_read; + sc->sc_init_tx_agg = r92cu_init_tx_agg; + sc->sc_init_rx_agg = r88eu_init_rx_agg; + sc->sc_init_ampdu = rtwn_nop_softc; + sc->sc_init_intr = r88eu_init_intr; + sc->sc_init_edca = r92c_init_edca; + sc->sc_init_bb = r88e_init_bb; + sc->sc_init_rf = r92c_init_rf; + sc->sc_init_antsel = rtwn_nop_softc; + sc->sc_post_init = r88eu_post_init; + sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; + + sc->mac_prog = &rtl8188eu_mac[0]; + sc->mac_size = nitems(rtl8188eu_mac); + sc->bb_prog = &rtl8188eu_bb[0]; + sc->bb_size = nitems(rtl8188eu_bb); + sc->agc_prog = &rtl8188eu_agc[0]; + sc->agc_size = nitems(rtl8188eu_agc); + sc->rf_prog = &rtl8188eu_rf[0]; + + sc->name = "RTL8188EU"; + sc->fwname = "rtwn-rtl8188eufw"; + sc->fwsig = 0x88e; + + sc->page_count = R88E_TX_PAGE_COUNT; + sc->pktbuf_count = R88E_TXPKTBUF_COUNT; + + sc->ackto = 0x40; + sc->npubqpages = R88E_PUBQ_NPAGES; + sc->page_size = R92C_TX_PAGE_SIZE; + + sc->txdesc_len = sizeof(struct r92cu_tx_desc); + sc->efuse_maxlen = R88E_EFUSE_MAX_LEN; + sc->efuse_maplen = R88E_EFUSE_MAP_LEN; + sc->rx_dma_size = R88E_RX_DMA_BUFFER_SIZE; + + sc->macid_limit = R88E_MACID_MAX + 1; + sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; + sc->fwsize_limit = R92C_MAX_FW_SIZE; + sc->temp_delta = R88E_CALIB_THRESHOLD; + + sc->bcn_status_reg[0] = R92C_TDECTRL; + sc->bcn_status_reg[1] = R92C_TDECTRL; + sc->rcr = 0; + + sc->ntxchains = 1; + sc->nrxchains = 1; + + r88eu_attach_private(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_init.c new file mode 100644 index 0000000000..fc4c670473 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_init.c @@ -0,0 +1,224 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_init.c 310305 2016-12-20 01:13:11Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r88eu_power_off(struct rtwn_softc *sc) +{ + uint8_t reg; + int error, ntries; + + /* Disable any kind of TX reports. */ + error = rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, + R88E_TX_RPT1_ENA | R88E_TX_RPT2_ENA, 0); + if (error == ENXIO) /* hardware gone */ + return; + + /* Stop Rx. */ + rtwn_write_1(sc, R92C_CR, 0); + + /* Move card to Low Power State. */ + /* Block all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + + for (ntries = 0; ntries < 10; ntries++) { + /* Should be zero if no packet is transmitting. */ + if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0) + break; + + rtwn_delay(sc, 5000); + } + if (ntries == 10) { + device_printf(sc->sc_dev, "%s: failed to block Tx queues\n", + __func__); + return; + } + + /* CCK and OFDM are disabled, and clock are gated. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0); + + rtwn_delay(sc, 1); + + /* Reset MAC TRX */ + rtwn_write_1(sc, R92C_CR, + R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | + R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN); + + /* check if removed later */ + rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1); + + /* Respond TxOK to scheduler */ + rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, 0x20); + + /* If firmware in ram code, do reset. */ +#ifndef RTWN_WITHOUT_UCODE + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) + r88e_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); +#endif + + /* Reset MCU ready status. */ + rtwn_write_1(sc, R92C_MCUFWDL, 0); + + /* Disable 32k. */ + rtwn_setbits_1(sc, R88E_32K_CTRL, 0x01, 0); + + /* Move card to Disabled state. */ + /* Turn off RF. */ + rtwn_write_1(sc, R92C_RF_CTRL, 0); + + /* LDO Sleep mode. */ + rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 0, R92C_LPLDO_CTRL_SLEEP); + + /* Turn off MAC by HW state machine */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_APFM_OFF, 1); + + for (ntries = 0; ntries < 10; ntries++) { + /* Wait until it will be disabled. */ + if ((rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_OFF) == 0) + break; + + rtwn_delay(sc, 5000); + } + if (ntries == 10) { + device_printf(sc->sc_dev, "%s: could not turn off MAC\n", + __func__); + return; + } + + /* schmit trigger */ + rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0, 0x80); + + /* Enable WL suspend. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_PCIE, R92C_APS_FSMCO_AFSM_HSUS, 1); + + /* Enable bandgap mbias in suspend. */ + rtwn_write_1(sc, R92C_APS_FSMCO + 3, 0); + + /* Clear SIC_EN register. */ + rtwn_setbits_1(sc, R92C_GPIO_MUXCFG + 1, 0x10, 0); + + /* Set USB suspend enable local register */ + rtwn_setbits_1(sc, R92C_USB_SUSPEND, 0, 0x10); + + /* Reset MCU IO Wrapper. */ + reg = rtwn_read_1(sc, R92C_RSV_CTRL + 1); + rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg & ~0x08); + rtwn_write_1(sc, R92C_RSV_CTRL + 1, reg | 0x08); + + /* marked as 'For Power Consumption' code. */ + rtwn_write_1(sc, R92C_GPIO_OUT, rtwn_read_1(sc, R92C_GPIO_IN)); + rtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff); + + rtwn_write_1(sc, R92C_GPIO_IO_SEL, + rtwn_read_1(sc, R92C_GPIO_IO_SEL) << 4); + rtwn_setbits_1(sc, R92C_GPIO_MOD, 0, 0x0f); + + /* Set LNA, TRSW, EX_PA Pin to output mode. */ + rtwn_write_4(sc, R88E_BB_PAD_CTRL, 0x00080808); +} + +void +r88eu_init_intr(struct rtwn_softc *sc) +{ + /* TODO: adjust */ + rtwn_write_4(sc, R88E_HISR, 0xffffffff); + rtwn_write_4(sc, R88E_HIMR, R88E_HIMR_CPWM | R88E_HIMR_CPWM2 | + R88E_HIMR_TBDER | R88E_HIMR_PSTIMEOUT); + rtwn_write_4(sc, R88E_HIMRE, R88E_HIMRE_RXFOVW | + R88E_HIMRE_TXFOVW | R88E_HIMRE_RXERR | R88E_HIMRE_TXERR); + rtwn_setbits_1(sc, R92C_USB_SPECIAL_OPTION, 0, + R92C_USB_SPECIAL_OPTION_INT_BULK_SEL); +} + +void +r88eu_init_rx_agg(struct rtwn_softc *sc) +{ + /* XXX merge? */ + rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, + R92C_TRXDMA_CTRL_RXDMA_AGG_EN); + /* XXX dehardcode */ + rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48); + rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH + 1, 4); +} + +void +r88eu_post_init(struct rtwn_softc *sc) +{ + + /* Enable per-packet TX report. */ + rtwn_setbits_1(sc, R88E_TX_RPT_CTRL, 0, R88E_TX_RPT1_ENA); + + /* Disable Tx if MACID is not associated. */ + rtwn_write_4(sc, R88E_MACID_NO_LINK, 0xffffffff); + rtwn_write_4(sc, R88E_MACID_NO_LINK + 4, 0xffffffff); + r88e_macid_enable_link(sc, RTWN_MACID_BC, 1); + + /* Perform LO and IQ calibrations. */ + r88e_iq_calib(sc); + /* Perform LC calibration. */ + r92c_lc_calib(sc); + + rtwn_write_1(sc, R92C_USB_HRPWM, 0); + + if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { + /* No support (yet?) for f/w rate adaptation. */ + sc->sc_ratectl = RTWN_RATECTL_NET80211; + } else + sc->sc_ratectl = sc->sc_ratectl_sysctl; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_reg.h new file mode 100644 index 0000000000..22fb80bde1 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_reg.h @@ -0,0 +1,27 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R88EU_REG_H +#define R88EU_REG_H + +#include +#include + +#endif /* R88EU_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_rx.c new file mode 100644 index 0000000000..1b0295477f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8188e/usb/r88eu_rx.c @@ -0,0 +1,74 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8188e/usb/r88eu_rx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include + + +int +r88eu_classify_intr(struct rtwn_softc *sc, void *buf, int len) +{ + struct r92c_rx_stat *stat = buf; + int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT); + + switch (report_sel) { + case R88E_RXDW3_RPT_RX: + return (RTWN_RX_DATA); + case R88E_RXDW3_RPT_TX1: /* per-packet Tx report */ + case R88E_RXDW3_RPT_TX2: /* periodical Tx report */ + return (RTWN_RX_TX_REPORT); + case R88E_RXDW3_RPT_HIS: + return (RTWN_RX_OTHER); + default: /* shut up the compiler */ + return (RTWN_RX_DATA); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce.h new file mode 100644 index 0000000000..54e266a7f9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce.h @@ -0,0 +1,74 @@ +/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTL8192CE_H +#define RTL8192CE_H + +#include + + +/* + * Global definitions. + */ +#define R92CE_PUBQ_NPAGES 176 +#define R92CE_HPQ_NPAGES 41 +#define R92CE_LPQ_NPAGES 28 +#define R92CE_TX_PAGE_COUNT \ + (R92CE_PUBQ_NPAGES + R92CE_HPQ_NPAGES + R92CE_LPQ_NPAGES) + + +/* + * Function declarations. + */ +/* r92ce_calib.c */ +void r92ce_iq_calib(struct rtwn_softc *); + +/* r92ce_fw.c */ +#ifndef RTWN_WITHOUT_UCODE +void r92ce_fw_reset(struct rtwn_softc *, int); +#endif + +/* r92ce_init.c */ +void r92ce_init_intr(struct rtwn_softc *); +void r92ce_init_edca(struct rtwn_softc *); +void r92ce_init_bb(struct rtwn_softc *); +int r92ce_power_on(struct rtwn_softc *); +void r92ce_power_off(struct rtwn_softc *); +void r92ce_init_ampdu(struct rtwn_softc *); +void r92ce_post_init(struct rtwn_softc *); + +/* r92ce_led.c */ +void r92ce_set_led(struct rtwn_softc *, int, int); + +/* r92ce_rx.c */ +int r92ce_classify_intr(struct rtwn_softc *, void *, int); +void r92ce_enable_intr(struct rtwn_pci_softc *); +void r92ce_start_xfers(struct rtwn_softc *); + +/* r92ce_tx.c */ +void r92ce_setup_tx_desc(struct rtwn_pci_softc *, void *, uint32_t); +void r92ce_tx_postsetup(struct rtwn_pci_softc *, void *, + bus_dma_segment_t[]); +void r92ce_copy_tx_desc(void *, const void *); +void r92ce_dump_tx_desc(struct rtwn_softc *, const void *); + +#endif /* RTL8192CE_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_attach.c new file mode 100644 index 0000000000..160bd47647 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_attach.c @@ -0,0 +1,265 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_attach.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + + +static struct rtwn_r92c_txpwr r92c_txpwr; + +void r92ce_attach(struct rtwn_pci_softc *); + +static void +r92ce_postattach(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + struct ieee80211com *ic = &sc->sc_ic; + + if (!(rs->chip & R92C_CHIP_92C) && + rs->board_type == R92C_BOARD_TYPE_HIGHPA) + rs->rs_txagc = &rtl8188ru_txagc[0]; + else + rs->rs_txagc = &rtl8192cu_txagc[0]; + + if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) == + R92C_CHIP_UMC_A_CUT) + sc->fwname = "rtwn-rtl8192cfwE"; + else + sc->fwname = "rtwn-rtl8192cfwE_B"; + sc->fwsig = 0x88c; + + rs->rs_scan_start = ic->ic_scan_start; + ic->ic_scan_start = r92c_scan_start; + rs->rs_scan_end = ic->ic_scan_end; + ic->ic_scan_end = r92c_scan_end; +} + +static void +r92ce_set_name(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + + if (rs->chip & R92C_CHIP_92C) + sc->name = "RTL8192CE"; + else + sc->name = "RTL8188CE"; +} + +static void +r92ce_attach_private(struct rtwn_softc *sc) +{ + struct r92c_softc *rs; + + rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); + + rs->rs_txpwr = &r92c_txpwr; + + rs->rs_set_bw20 = r92c_set_bw20; + rs->rs_get_txpower = r92c_get_txpower; + rs->rs_set_gain = r92c_set_gain; + rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu; + rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq; + rs->rs_tx_setup_macid = r92c_tx_setup_macid; + rs->rs_set_name = r92ce_set_name; + + /* XXX TODO: test with net80211 ratectl! */ +#ifndef RTWN_WITHOUT_UCODE + rs->rs_c2h_timeout = hz; + + callout_init_mtx(&rs->rs_c2h_report, &sc->sc_mtx, 0); +#endif + + rs->rf_read_delay[0] = 1000; + rs->rf_read_delay[1] = 1000; + rs->rf_read_delay[2] = 1000; + + sc->sc_priv = rs; +} + +static void +r92ce_adj_devcaps(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + + /* + * XXX do NOT enable PMGT until RSVD_PAGE command + * will not be tested / fixed + HRPWM register must be set too. + */ + ic->ic_caps &= ~IEEE80211_C_PMGT; +} + +void +r92ce_attach(struct rtwn_pci_softc *pc) +{ + struct rtwn_softc *sc = &pc->pc_sc; + + /* PCIe part. */ + pc->pc_setup_tx_desc = r92ce_setup_tx_desc; + pc->pc_tx_postsetup = r92ce_tx_postsetup; + pc->pc_copy_tx_desc = r92ce_copy_tx_desc; + pc->pc_enable_intr = r92ce_enable_intr; + + pc->pc_qmap = 0xf771; + pc->tcr = + R92C_TCR_CFENDFORM | (1 << 12) | (1 << 13); + + /* Common part. */ + /* RTL8192C* cannot use pairwise keys from first 4 slots */ + sc->sc_flags = RTWN_FLAG_CAM_FIXED; + + sc->sc_start_xfers = r92ce_start_xfers; + sc->sc_set_chan = r92c_set_chan; + sc->sc_fill_tx_desc = r92c_fill_tx_desc; + sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; + sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; /* XXX recheck */ + sc->sc_dump_tx_desc = r92ce_dump_tx_desc; + sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; + sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; + sc->sc_get_rx_stats = r92c_get_rx_stats; + sc->sc_get_rssi_cck = r92c_get_rssi_cck; + sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; + sc->sc_classify_intr = r92ce_classify_intr; + sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int; + sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int; + sc->sc_check_frame = rtwn_nop_int_softc_mbuf; + sc->sc_rf_read = r92c_rf_read; + sc->sc_rf_write = r92c_rf_write; + sc->sc_check_condition = r92c_check_condition; + sc->sc_efuse_postread = r92c_efuse_postread; + sc->sc_parse_rom = r92c_parse_rom; + sc->sc_set_led = r92ce_set_led; + sc->sc_power_on = r92ce_power_on; + sc->sc_power_off = r92ce_power_off; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_fw_reset = r92ce_fw_reset; + sc->sc_fw_download_enable = r92c_fw_download_enable; +#endif + sc->sc_llt_init = r92c_llt_init; + sc->sc_set_page_size = r92c_set_page_size; + sc->sc_lc_calib = r92c_lc_calib; + sc->sc_iq_calib = r92ce_iq_calib; + sc->sc_read_chipid_vendor = r92c_read_chipid_vendor; + sc->sc_adj_devcaps = r92ce_adj_devcaps; + sc->sc_vap_preattach = rtwn_nop_softc_vap; + sc->sc_postattach = r92ce_postattach; + sc->sc_detach_private = r92c_detach_private; + sc->sc_set_media_status = r92c_joinbss_rpt; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_set_rsvd_page = r92c_set_rsvd_page; + sc->sc_set_pwrmode = r92c_set_pwrmode; + sc->sc_set_rssi = r92c_set_rssi; +#endif + sc->sc_beacon_init = r92c_beacon_init; + sc->sc_beacon_enable = r92c_beacon_enable; + sc->sc_beacon_set_rate = rtwn_nop_void_int; + sc->sc_beacon_select = rtwn_nop_softc_int; + sc->sc_temp_measure = r92c_temp_measure; + sc->sc_temp_read = r92c_temp_read; + sc->sc_init_tx_agg = rtwn_nop_softc; + sc->sc_init_rx_agg = rtwn_nop_softc; + sc->sc_init_ampdu = r92ce_init_ampdu; + sc->sc_init_intr = r92ce_init_intr; + sc->sc_init_edca = r92ce_init_edca; + sc->sc_init_bb = r92ce_init_bb; + sc->sc_init_rf = r92c_init_rf; + sc->sc_init_antsel = rtwn_nop_softc; + sc->sc_post_init = r92ce_post_init; + sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; + + sc->mac_prog = &rtl8192ce_mac[0]; + sc->mac_size = nitems(rtl8192ce_mac); + sc->bb_prog = &rtl8192ce_bb[0]; + sc->bb_size = nitems(rtl8192ce_bb); + sc->agc_prog = &rtl8192ce_agc[0]; + sc->agc_size = nitems(rtl8192ce_agc); + sc->rf_prog = &rtl8192c_rf[0]; + + sc->page_count = R92CE_TX_PAGE_COUNT; + sc->pktbuf_count = R92C_TXPKTBUF_COUNT; + + sc->ackto = 0x40; + sc->npubqpages = R92CE_PUBQ_NPAGES; + sc->nhqpages = R92CE_HPQ_NPAGES; + sc->nnqpages = 0; + sc->nlqpages = R92CE_LPQ_NPAGES; + sc->page_size = R92C_TX_PAGE_SIZE; + + sc->txdesc_len = sizeof(struct r92ce_tx_desc); + sc->efuse_maxlen = R92C_EFUSE_MAX_LEN; + sc->efuse_maplen = R92C_EFUSE_MAP_LEN; + sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE; + + sc->macid_limit = R92C_MACID_MAX + 1; + sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; + sc->fwsize_limit = R92C_MAX_FW_SIZE; + sc->temp_delta = R92C_CALIB_THRESHOLD; + + sc->bcn_status_reg[0] = R92C_TDECTRL; + /* + * TODO: some additional setup is required + * to maintain few beacons at the same time. + * + * XXX BCNQ1 mechanism is not needed here; move it to the USB module. + */ + sc->bcn_status_reg[1] = R92C_TDECTRL; + sc->rcr = 0; + + r92ce_attach_private(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_calib.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_calib.c new file mode 100644 index 0000000000..a7d2acac0c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_calib.c @@ -0,0 +1,386 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_calib.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include + + +/* Registers to save and restore during IQ calibration. */ +struct r92ce_iq_cal_reg_vals { + uint32_t adda[16]; + uint8_t txpause; + uint8_t bcn_ctrl[2]; + uint32_t gpio_muxcfg; + uint32_t ofdm0_trxpathena; + uint32_t ofdm0_trmuxpar; + uint32_t fpga0_rfifacesw1; +}; + +/* XXX 92CU? */ +static int +r92ce_iq_calib_chain(struct rtwn_softc *sc, int chain, uint16_t tx[2], + uint16_t rx[2]) +{ + uint32_t status; + int offset = chain * 0x20; + + if (chain == 0) { /* IQ calibration for chain 0. */ + /* IQ calibration settings for chain 0. */ + rtwn_bb_write(sc, 0xe30, 0x10008c1f); + rtwn_bb_write(sc, 0xe34, 0x10008c1f); + rtwn_bb_write(sc, 0xe38, 0x82140102); + + if (sc->ntxchains > 1) { + rtwn_bb_write(sc, 0xe3c, 0x28160202); /* 2T */ + /* IQ calibration settings for chain 1. */ + rtwn_bb_write(sc, 0xe50, 0x10008c22); + rtwn_bb_write(sc, 0xe54, 0x10008c22); + rtwn_bb_write(sc, 0xe58, 0x82140102); + rtwn_bb_write(sc, 0xe5c, 0x28160202); + } else + rtwn_bb_write(sc, 0xe3c, 0x28160502); /* 1T */ + + /* LO calibration settings. */ + rtwn_bb_write(sc, 0xe4c, 0x001028d1); + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, 0xe48, 0xf9000000); + rtwn_bb_write(sc, 0xe48, 0xf8000000); + + } else { /* IQ calibration for chain 1. */ + /* We're doing LO and IQ calibration in one shot. */ + rtwn_bb_write(sc, 0xe60, 0x00000002); + rtwn_bb_write(sc, 0xe60, 0x00000000); + } + + /* Give LO and IQ calibrations the time to complete. */ + rtwn_delay(sc, 1000); + + /* Read IQ calibration status. */ + status = rtwn_bb_read(sc, 0xeac); + + if (status & (1 << (28 + chain * 3))) + return (0); /* Tx failed. */ + /* Read Tx IQ calibration results. */ + tx[0] = (rtwn_bb_read(sc, 0xe94 + offset) >> 16) & 0x3ff; + tx[1] = (rtwn_bb_read(sc, 0xe9c + offset) >> 16) & 0x3ff; + if (tx[0] == 0x142 || tx[1] == 0x042) + return (0); /* Tx failed. */ + + if (status & (1 << (27 + chain * 3))) + return (1); /* Rx failed. */ + /* Read Rx IQ calibration results. */ + rx[0] = (rtwn_bb_read(sc, 0xea4 + offset) >> 16) & 0x3ff; + rx[1] = (rtwn_bb_read(sc, 0xeac + offset) >> 16) & 0x3ff; + if (rx[0] == 0x132 || rx[1] == 0x036) + return (1); /* Rx failed. */ + + return (3); /* Both Tx and Rx succeeded. */ +} + +static void +r92ce_iq_calib_run(struct rtwn_softc *sc, int n, uint16_t tx[2][2], + uint16_t rx[2][2], struct r92ce_iq_cal_reg_vals *vals) +{ + /* Registers to save and restore during IQ calibration. */ + static const uint16_t reg_adda[16] = { + 0x85c, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, + 0xed8, 0xedc, 0xee0, 0xeec + }; + int i, chain; + uint32_t hssi_param1; + + if (n == 0) { + for (i = 0; i < nitems(reg_adda); i++) + vals->adda[i] = rtwn_bb_read(sc, reg_adda[i]); + + vals->txpause = rtwn_read_1(sc, R92C_TXPAUSE); + vals->bcn_ctrl[0] = rtwn_read_1(sc, R92C_BCN_CTRL(0)); + vals->bcn_ctrl[1] = rtwn_read_1(sc, R92C_BCN_CTRL(1)); + vals->gpio_muxcfg = rtwn_read_4(sc, R92C_GPIO_MUXCFG); + } + + if (sc->ntxchains == 1) { + rtwn_bb_write(sc, reg_adda[0], 0x0b1b25a0); + for (i = 1; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x0bdb25a0); + } else { + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x04db25a4); + } + + hssi_param1 = rtwn_bb_read(sc, R92C_HSSI_PARAM1(0)); + if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { + rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), + hssi_param1 | R92C_HSSI_PARAM1_PI); + rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), + hssi_param1 | R92C_HSSI_PARAM1_PI); + } + + if (n == 0) { + vals->ofdm0_trxpathena = + rtwn_bb_read(sc, R92C_OFDM0_TRXPATHENA); + vals->ofdm0_trmuxpar = rtwn_bb_read(sc, R92C_OFDM0_TRMUXPAR); + vals->fpga0_rfifacesw1 = + rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(1)); + } + + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, 0x03a05600); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, 0x000800e4); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), 0x22204000); + if (sc->ntxchains > 1) { + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); + rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00010000); + } + + rtwn_write_1(sc, R92C_TXPAUSE, + R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); + rtwn_write_1(sc, R92C_BCN_CTRL(0), + vals->bcn_ctrl[0] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_BCN_CTRL(1), + vals->bcn_ctrl[1] & ~R92C_BCN_CTRL_EN_BCN); + rtwn_write_1(sc, R92C_GPIO_MUXCFG, + vals->gpio_muxcfg & ~R92C_GPIO_MUXCFG_ENBT); + + rtwn_bb_write(sc, 0x0b68, 0x00080000); + if (sc->ntxchains > 1) + rtwn_bb_write(sc, 0x0b6c, 0x00080000); + + rtwn_bb_write(sc, 0x0e28, 0x80800000); + rtwn_bb_write(sc, 0x0e40, 0x01007c00); + rtwn_bb_write(sc, 0x0e44, 0x01004800); + + rtwn_bb_write(sc, 0x0b68, 0x00080000); + + for (chain = 0; chain < sc->ntxchains; chain++) { + if (chain > 0) { + /* Put chain 0 on standby. */ + rtwn_bb_write(sc, 0x0e28, 0x00); + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00010000); + rtwn_bb_write(sc, 0x0e28, 0x80800000); + + /* Enable chain 1. */ + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], 0x0b1b25a4); + } + + /* Run IQ calibration twice. */ + for (i = 0; i < 2; i++) { + int ret; + + ret = r92ce_iq_calib_chain(sc, chain, + tx[chain], rx[chain]); + if (ret == 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: chain %d: Tx failed.\n", + __func__, chain); + tx[chain][0] = 0xff; + tx[chain][1] = 0xff; + rx[chain][0] = 0xff; + rx[chain][1] = 0xff; + } else if (ret == 1) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: chain %d: Rx failed.\n", + __func__, chain); + rx[chain][0] = 0xff; + rx[chain][1] = 0xff; + } else if (ret == 3) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: chain %d: Both Tx and Rx " + "succeeded.\n", __func__, chain); + } + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: results for run %d chain %d: tx[0] 0x%x, " + "tx[1] 0x%x, rx[0] 0x%x, rx[1] 0x%x\n", __func__, n, chain, + tx[chain][0], tx[chain][1], rx[chain][0], rx[chain][1]); + } + + rtwn_bb_write(sc, R92C_OFDM0_TRXPATHENA, + vals->ofdm0_trxpathena); + rtwn_bb_write(sc, R92C_FPGA0_RFIFACESW(1), + vals->fpga0_rfifacesw1); + rtwn_bb_write(sc, R92C_OFDM0_TRMUXPAR, vals->ofdm0_trmuxpar); + + rtwn_bb_write(sc, 0x0e28, 0x00); + rtwn_bb_write(sc, R92C_LSSI_PARAM(0), 0x00032ed3); + if (sc->ntxchains > 1) + rtwn_bb_write(sc, R92C_LSSI_PARAM(1), 0x00032ed3); + + if (n != 0) { + if (!(hssi_param1 & R92C_HSSI_PARAM1_PI)) { + rtwn_bb_write(sc, R92C_HSSI_PARAM1(0), hssi_param1); + rtwn_bb_write(sc, R92C_HSSI_PARAM1(1), hssi_param1); + } + + for (i = 0; i < nitems(reg_adda); i++) + rtwn_bb_write(sc, reg_adda[i], vals->adda[i]); + + rtwn_write_1(sc, R92C_TXPAUSE, vals->txpause); + rtwn_write_1(sc, R92C_BCN_CTRL(0), vals->bcn_ctrl[0]); + rtwn_write_1(sc, R92C_BCN_CTRL(1), vals->bcn_ctrl[1]); + rtwn_write_4(sc, R92C_GPIO_MUXCFG, vals->gpio_muxcfg); + } +} + +#define RTWN_IQ_CAL_MAX_TOLERANCE 5 +static int +r92ce_iq_calib_compare_results(struct rtwn_softc *sc, uint16_t tx1[2][2], + uint16_t rx1[2][2], uint16_t tx2[2][2], uint16_t rx2[2][2]) +{ + int chain, i, tx_ok[2], rx_ok[2]; + + tx_ok[0] = tx_ok[1] = rx_ok[0] = rx_ok[1] = 0; + for (chain = 0; chain < sc->ntxchains; chain++) { + for (i = 0; i < 2; i++) { + if (tx1[chain][i] == 0xff || tx2[chain][i] == 0xff || + rx1[chain][i] == 0xff || rx2[chain][i] == 0xff) + continue; + + tx_ok[chain] = (abs(tx1[chain][i] - tx2[chain][i]) <= + RTWN_IQ_CAL_MAX_TOLERANCE); + + rx_ok[chain] = (abs(rx1[chain][i] - rx2[chain][i]) <= + RTWN_IQ_CAL_MAX_TOLERANCE); + } + } + + if (sc->ntxchains > 1) + return (tx_ok[0] && tx_ok[1] && rx_ok[0] && rx_ok[1]); + else + return (tx_ok[0] && rx_ok[0]); +} +#undef RTWN_IQ_CAL_MAX_TOLERANCE + +static void +r92ce_iq_calib_write_results(struct rtwn_softc *sc, uint16_t tx[2], + uint16_t rx[2], int chain) +{ + uint32_t reg, val, x; + long y, tx_c; + + if (tx[0] == 0xff || tx[1] == 0xff) + return; + + reg = rtwn_bb_read(sc, R92C_OFDM0_TXIQIMBALANCE(chain)); + val = ((reg >> 22) & 0x3ff); + x = tx[0]; + if (x & 0x00000200) + x |= 0xfffffc00; + reg = (((x * val) >> 8) & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x3ff, reg); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x80000000, + ((x * val) & 0x80) << 24); + + y = tx[1]; + if (y & 0x00000200) + y |= 0xfffffc00; + tx_c = (y * val) >> 8; + rtwn_bb_setbits(sc, R92C_OFDM0_TXAFE(chain), 0xf0000000, + (tx_c & 0x3c0) << 22); + rtwn_bb_setbits(sc, R92C_OFDM0_TXIQIMBALANCE(chain), 0x003f0000, + (tx_c & 0x3f) << 16); + rtwn_bb_setbits(sc, R92C_OFDM0_ECCATHRESHOLD, 0x20000000, + ((y * val) & 0x80) << 22); + + if (rx[0] == 0xff || rx[1] == 0xff) + return; + + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0x3ff, + rx[0] & 0x3ff); + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQIMBALANCE(chain), 0xfc00, + (rx[1] & 0x3f) << 10); + + if (chain == 0) { + rtwn_bb_setbits(sc, R92C_OFDM0_RXIQEXTANTA, 0xf0000000, + (rx[1] & 0x3c0) << 22); + } else { + rtwn_bb_setbits(sc, R92C_OFDM0_AGCRSSITABLE, 0xf000, + (rx[1] & 0x3c0) << 6); + } +} + +#define RTWN_IQ_CAL_NRUN 3 +void +r92ce_iq_calib(struct rtwn_softc *sc) +{ + struct r92ce_iq_cal_reg_vals vals; + uint16_t tx[RTWN_IQ_CAL_NRUN][2][2], rx[RTWN_IQ_CAL_NRUN][2][2]; + int n, valid; + + valid = 0; + for (n = 0; n < RTWN_IQ_CAL_NRUN; n++) { + r92ce_iq_calib_run(sc, n, tx[n], rx[n], &vals); + + if (n == 0) + continue; + + /* Valid results remain stable after consecutive runs. */ + valid = r92ce_iq_calib_compare_results(sc, tx[n - 1], + rx[n - 1], tx[n], rx[n]); + if (valid) + break; + } + + if (valid) { + r92ce_iq_calib_write_results(sc, tx[n][0], rx[n][0], 0); + if (sc->ntxchains > 1) + r92ce_iq_calib_write_results(sc, tx[n][1], rx[n][1], 1); + } +} +#undef RTWN_IQ_CAL_NRUN diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_fw.c new file mode 100644 index 0000000000..4f2819d7b7 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_fw.c @@ -0,0 +1,75 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_fw.c 308380 2016-11-06 17:24:16Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + + +#ifndef RTWN_WITHOUT_UCODE +void +r92ce_fw_reset(struct rtwn_softc *sc, int reason) +{ + + if (reason == RTWN_FW_RESET_CHECKSUM) + return; + + r92c_fw_reset(sc, reason); + + /* + * We must sleep for one second to let the firmware settle. + * Accessing registers too early will hang the whole system. + */ + if (reason == RTWN_FW_RESET_DOWNLOAD) + rtwn_delay(sc, 1000 * 1000); +} +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_init.c new file mode 100644 index 0000000000..736c6a1838 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_init.c @@ -0,0 +1,323 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_init.c 311347 2017-01-05 02:04:53Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include +#include + + +void +r92ce_init_intr(struct rtwn_softc *sc) +{ + /* Disable interrupts. */ + rtwn_write_4(sc, R92C_HISR, 0x00000000); + rtwn_write_4(sc, R92C_HIMR, 0x00000000); +} + +void +r92ce_init_edca(struct rtwn_softc *sc) +{ + /* SIFS */ + rtwn_write_2(sc, R92C_SPEC_SIFS, 0x1010); + rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x1010); + rtwn_write_2(sc, R92C_SIFS_CCK, 0x1010); + rtwn_write_2(sc, R92C_SIFS_OFDM, 0x0e0e); + /* TXOP */ + rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); + rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); + rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005e4322); + rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002f3222); +} + +void +r92ce_init_bb(struct rtwn_softc *sc) +{ + + /* Enable BB and RF. */ + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_DIO_RF); + + rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); + + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_DIO_PCIE | R92C_SYS_FUNC_EN_PCIEA | + R92C_SYS_FUNC_EN_PPLL | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_BBRSTB); + + rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); + + rtwn_setbits_4(sc, R92C_LEDCFG0, 0, 0x00800000); + + r92c_init_bb_common(sc); +} + +int +r92ce_power_on(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + uint32_t reg; + int ntries; + + /* Wait for autoload done bit. */ + for (ntries = 0; ntries < 1000; ntries++) { + if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN) + break; + DELAY(5); + } + if (ntries == 1000) { + device_printf(sc->sc_dev, + "timeout waiting for chip autoload\n"); + return (ETIMEDOUT); + } + + /* Unlock ISO/CLK/Power control register. */ + rtwn_write_1(sc, R92C_RSV_CTRL, 0); + + if (rs->board_type != R92C_BOARD_TYPE_DONGLE) { + /* bt coex */ + rtwn_setbits_4(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_SOP_ABG | + R92C_APS_FSMCO_SOP_AMB | + R92C_APS_FSMCO_XOP_BTCK); + } + + /* Move SPS into PWM mode. */ + rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b); + + /* Set low byte to 0x0f, leave others unchanged. */ + rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0f); + + /* TODO: check if we need this for 8188CE */ + if (rs->board_type != R92C_BOARD_TYPE_DONGLE) { + /* bt coex */ + /* XXX magic from linux */ + rtwn_setbits_4(sc, R92C_AFE_XTAL_CTRL, 0x024800, 0); + } + + rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, 0xff00, + R92C_SYS_ISO_CTRL_PWC_EV12V | R92C_SYS_ISO_CTRL_DIOR); + + DELAY(200); + + /* TODO: linux does additional btcoex stuff here */ + + /* Auto enable WLAN. */ + rtwn_setbits_2(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_ONMAC); + for (ntries = 0; ntries < 1000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + DELAY(5); + } + if (ntries == 1000) { + device_printf(sc->sc_dev, "timeout waiting for MAC auto ON\n"); + return (ETIMEDOUT); + } + + /* Enable radio, GPIO and LED functions. */ + rtwn_write_2(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_PCIE | + R92C_APS_FSMCO_PDN_EN | + R92C_APS_FSMCO_PFM_ALDN); + /* Release RF digital isolation. */ + rtwn_setbits_2(sc, R92C_SYS_ISO_CTRL, R92C_SYS_ISO_CTRL_DIOR, 0); + + if (rs->chip & R92C_CHIP_92C) + rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x77); + else + rtwn_write_1(sc, R92C_PCIE_CTRL_REG + 3, 0x22); + + rtwn_write_4(sc, R92C_INT_MIG, 0); + + if (rs->board_type != R92C_BOARD_TYPE_DONGLE) { + /* bt coex */ + /* XXX magic from linux */ + rtwn_setbits_1(sc, R92C_AFE_XTAL_CTRL + 2, 0x02, 0); + } + + rtwn_setbits_1(sc, R92C_GPIO_MUXCFG, R92C_GPIO_MUXCFG_RFKILL, 0); + + reg = rtwn_read_1(sc, R92C_GPIO_IO_SEL); + if (!(reg & R92C_GPIO_IO_SEL_RFKILL)) { + device_printf(sc->sc_dev, + "radio is disabled by hardware switch\n"); + /* XXX how driver will know when radio will be enabled? */ + return (EPERM); + } + + /* Initialize MAC. */ + rtwn_setbits_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF, 0); + for (ntries = 0; ntries < 200; ntries++) { + if (!(rtwn_read_1(sc, R92C_APSD_CTRL) & + R92C_APSD_CTRL_OFF_STATUS)) + break; + DELAY(500); + } + if (ntries == 200) { + device_printf(sc->sc_dev, + "timeout waiting for MAC initialization\n"); + return (ETIMEDOUT); + } + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | + R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | + R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0)); + + rtwn_write_4(sc, R92C_MCUTST_1, 0x0); + + return (0); +} + +void +r92ce_power_off(struct rtwn_softc *sc) +{ +#ifndef RTWN_WITHOUT_UCODE + struct r92c_softc *rs = sc->sc_priv; + + /* Deinit C2H event handler. */ + callout_stop(&rs->rs_c2h_report); + rs->rs_c2h_paused = 0; + rs->rs_c2h_pending = 0; + rs->rs_c2h_timeout = hz; +#endif + + /* Stop hardware. */ + /* Disable interrupts. */ + rtwn_write_4(sc, R92C_HISR, 0); + rtwn_write_4(sc, R92C_HIMR, 0); + + /* Stop hardware. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + + /* Turn off RF. */ + rtwn_write_1(sc, R92C_RF_CTRL, 0); + + /* Reset BB state machine */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_BB_GLB_RST); + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); + + /* Disable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + rtwn_setbits_2(sc, R92C_CR, + R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | + R92C_CR_TXDMA_EN | R92C_CR_RXDMA_EN | R92C_CR_PROTOCOL_EN | + R92C_CR_SCHEDULE_EN | R92C_CR_MACTXEN | R92C_CR_MACRXEN | + R92C_CR_ENSEC, + 0); + + /* If firmware in ram code, do reset. */ +#ifndef RTWN_WITHOUT_UCODE + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) + r92ce_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); +#endif + + /* TODO: linux does additional btcoex stuff here */ + rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0x80); /* linux magic number */ + rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); /* ditto */ + rtwn_write_1(sc, R92C_AFE_XTAL_CTRL, 0x0e); /* different with btcoex */ + rtwn_write_1(sc, R92C_RSV_CTRL, 0x0e); + rtwn_write_1(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_PDN_EN); +} + +void +r92ce_init_ampdu(struct rtwn_softc *sc) +{ + + /* Setup AMPDU aggregation. */ + rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ + rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); +} + +void +r92ce_post_init(struct rtwn_softc *sc) +{ + rtwn_write_2(sc, R92C_FWHW_TXQ_CTRL, + 0x1f00 | R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW); + + rtwn_write_1(sc, R92C_BCN_MAX_ERR, 0xff); + + /* Perform LO and IQ calibrations. */ + r92ce_iq_calib(sc); + /* Perform LC calibration. */ + r92c_lc_calib(sc); + + r92c_pa_bias_init(sc); + + /* Fix for lower temperature. */ + rtwn_write_1(sc, 0x15, 0xe9); + +#ifndef RTWN_WITHOUT_UCODE + if (sc->sc_flags & RTWN_FW_LOADED) { + struct r92c_softc *rs = sc->sc_priv; + + if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { + /* XXX TODO: fix (see comment in r92cu_init.c) */ + sc->sc_ratectl = RTWN_RATECTL_NET80211; + } else + sc->sc_ratectl = sc->sc_ratectl_sysctl; + + /* Start C2H event handling. */ + callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, + r92c_handle_c2h_report, sc); + } else +#endif + sc->sc_ratectl = RTWN_RATECTL_NONE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_led.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_led.c new file mode 100644 index 0000000000..2ad18f0a8d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_led.c @@ -0,0 +1,67 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_led.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include +#include + +void +r92ce_set_led(struct rtwn_softc *sc, int led, int on) +{ + + if (led == RTWN_LED_LINK) { + rtwn_setbits_1(sc, R92C_LEDCFG2, 0x0f, + on ? R92C_LEDCFG2_EN : R92C_LEDCFG2_DIS); + sc->ledlink = on; /* Save LED state. */ + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_priv.h new file mode 100644 index 0000000000..9383542c68 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_priv.h @@ -0,0 +1,182 @@ +/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_priv.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CE_PRIV_H +#define R92CE_PRIV_H + +#include + + +/* + * MAC initialization values. + */ +static const struct rtwn_mac_prog rtl8192ce_mac[] = { + { 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 }, + { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 }, + { 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 }, + { 0x43a, 0x00 }, { 0x43b, 0x01 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, + { 0x43e, 0x06 }, { 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 }, + { 0x442, 0x00 }, { 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f }, + { 0x447, 0x00 }, { 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 }, + { 0x45b, 0xb9 }, { 0x460, 0x88 }, { 0x461, 0x88 }, { 0x462, 0x06 }, + { 0x463, 0x03 }, { 0x4c8, 0x04 }, { 0x4c9, 0x08 }, { 0x4cc, 0x02 }, + { 0x4cd, 0x28 }, { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, + { 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, + { 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, + { 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, + { 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, + { 0x515, 0x10 }, { 0x516, 0x0a }, { 0x517, 0x10 }, { 0x51a, 0x16 }, + { 0x524, 0x0f }, { 0x525, 0x4f }, { 0x546, 0x20 }, { 0x547, 0x00 }, + { 0x559, 0x02 }, { 0x55a, 0x02 }, { 0x55d, 0xff }, { 0x605, 0x30 }, + { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x652, 0x20 }, { 0x63c, 0x0a }, + { 0x63d, 0x0e }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 }, + { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 }, + { 0x70b, 0x87 } +}; + + +/* + * Baseband initialization values. + */ +static const uint16_t rtl8192ce_bb_regs0[] = { + 0x024, 0x028, 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, + 0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, + 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, + 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884, + 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, 0x908, + 0x90c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, + 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04 +}, rtl8192ce_bb_regs1[] = { + 0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, + 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, + 0xc50, 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, + 0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, + 0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, + 0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc, + 0xce0, 0xce4, 0xce8, 0xcec, 0xd00 +}; + +static const uint32_t rtl8192ce_bb_vals0_2t[] = { + 0x0011800f, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00, + 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, + 0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727, + 0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000, + 0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a, + 0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27, + 0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070, + 0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe, + 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, + 0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, + 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, + 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, + 0x48071d40, 0x03a05633 +}, rtl8192ce_bb_vals0_1t[] = { + 0x0011800f, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00, + 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, + 0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a, + 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200, + 0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070, + 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe, + 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, + 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, + 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, + 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, + 0x48071d40, 0x03a05611 +}, rtl8192ce_bb_vals1[] = { + 0x000000e4, 0x6c6c6c6c, 0x08800000, 0x40000100, 0x08800000, + 0x40000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x69e9ac44, 0x469652cf, 0x49795994, 0x0a97971c, 0x1f7c403f, + 0x000100b7, 0xec020107, 0x007f037f, 0x69543420, 0x43bc0094, + 0x69543420, 0x433c0094, 0x00000000, 0x5116848b, 0x47c00bff, + 0x00000036, 0x2c7f000d, 0x018610db, 0x0000001f, 0x00b91612, + 0x40000100, 0x20f60000, 0x40000100, 0x20200000, 0x00121820, + 0x00000000, 0x00121820, 0x00007f7f, 0x00000000, 0x00000080, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x28000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x64b22427, 0x00766932, 0x00222222, + 0x00000000, 0x37644302, 0x2f97d40c, 0x00080740 +}, rtl8192ce_bb_vals4_1t[] = { + 0x00000010, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0, + 0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0, + 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0, + 0x001b25a0, 0x6b1b25a0, 0x00000003, 0x00000000, 0x00000300 +}; + +static const struct rtwn_bb_prog rtl8192ce_bb[] = { + { + nitems(rtl8192ce_bb_regs0), + rtl8192ce_bb_regs0, + rtl8192ce_bb_vals0_2t, + { R92C_COND_RTL8192C }, + &(const struct rtwn_bb_prog){ + nitems(rtl8192ce_bb_regs0), + rtl8192ce_bb_regs0, + rtl8192ce_bb_vals0_1t, + { 0 }, + NULL + } + }, + { + nitems(rtl8192ce_bb_regs1), + rtl8192ce_bb_regs1, + rtl8192ce_bb_vals1, + { 0 }, + NULL + }, + { + nitems(rtl8192c_bb_regs3), + rtl8192c_bb_regs3, + rtl8192c_bb_vals3_92ce_92cu, + { R92C_COND_RTL8192C }, + &(const struct rtwn_bb_prog){ + nitems(rtl8192c_bb_regs3), + rtl8192c_bb_regs3, + rtl8192c_bb_vals3_88cu_88ru, + { 0 }, + NULL + } + }, + { + nitems(rtl8192c_bb_regs4), + rtl8192c_bb_regs4, + rtl8192c_bb_vals4, + { 0 }, + NULL + }, + { + nitems(rtl8192c_bb_regs5), + rtl8192c_bb_regs5, + rtl8192c_bb_vals5_92ce_92cu, + { R92C_COND_RTL8192C }, + &(const struct rtwn_bb_prog){ + nitems(rtl8192c_bb_regs5), + rtl8192c_bb_regs5, + rtl8192ce_bb_vals4_1t, + { 0 }, + NULL + } + } +}; + +#endif /* R92CE_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_reg.h new file mode 100644 index 0000000000..616c9f8b9c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_reg.h @@ -0,0 +1,103 @@ +/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CE_REG_H +#define R92CE_REG_H + +#include + +/* + * MAC registers. + */ +/* System Configuration. */ +#define R92C_PCIE_MIO_INTF 0x0e4 +#define R92C_PCIE_MIO_INTD 0x0e8 +/* PCIe Configuration. */ +#define R92C_PCIE_CTRL_REG 0x300 +#define R92C_INT_MIG 0x304 +#define R92C_BCNQ_DESA 0x308 +#define R92C_HQ_DESA 0x310 +#define R92C_MGQ_DESA 0x318 +#define R92C_VOQ_DESA 0x320 +#define R92C_VIQ_DESA 0x328 +#define R92C_BEQ_DESA 0x330 +#define R92C_BKQ_DESA 0x338 +#define R92C_RX_DESA 0x340 +#define R92C_DBI 0x348 +#define R92C_MDIO 0x354 +#define R92C_DBG_SEL 0x360 +#define R92C_PCIE_HRPWM 0x361 +#define R92C_PCIE_HCPWM 0x363 +#define R92C_UART_CTRL 0x364 +#define R92C_UART_TX_DES 0x370 +#define R92C_UART_RX_DES 0x378 + + +/* Bits for R92C_GPIO_MUXCFG. */ +#define R92C_GPIO_MUXCFG_RFKILL 0x0008 + +/* Bits for R92C_GPIO_IO_SEL. */ +#define R92C_GPIO_IO_SEL_RFKILL 0x0008 + +/* Bits for R92C_LEDCFG2. */ +#define R92C_LEDCFG2_EN 0x60 +#define R92C_LEDCFG2_DIS 0x68 + +/* Bits for R92C_HIMR. */ +#define R92C_IMR_ROK 0x00000001 /* receive DMA OK */ +#define R92C_IMR_VODOK 0x00000002 /* AC_VO DMA OK */ +#define R92C_IMR_VIDOK 0x00000004 /* AC_VI DMA OK */ +#define R92C_IMR_BEDOK 0x00000008 /* AC_BE DMA OK */ +#define R92C_IMR_BKDOK 0x00000010 /* AC_BK DMA OK */ +#define R92C_IMR_TXBDER 0x00000020 /* beacon transmit error */ +#define R92C_IMR_MGNTDOK 0x00000040 /* management queue DMA OK */ +#define R92C_IMR_TBDOK 0x00000080 /* beacon transmit OK */ +#define R92C_IMR_HIGHDOK 0x00000100 /* high queue DMA OK */ +#define R92C_IMR_BDOK 0x00000200 /* beacon queue DMA OK */ +#define R92C_IMR_ATIMEND 0x00000400 /* ATIM window end interrupt */ +#define R92C_IMR_RDU 0x00000800 /* Rx descriptor unavailable */ +#define R92C_IMR_RXFOVW 0x00001000 /* receive FIFO overflow */ +#define R92C_IMR_BCNINT 0x00002000 /* beacon DMA interrupt 0 */ +#define R92C_IMR_PSTIMEOUT 0x00004000 /* powersave timeout */ +#define R92C_IMR_TXFOVW 0x00008000 /* transmit FIFO overflow */ +#define R92C_IMR_TIMEOUT1 0x00010000 /* timeout interrupt 1 */ +#define R92C_IMR_TIMEOUT2 0x00020000 /* timeout interrupt 2 */ +#define R92C_IMR_BCNDOK1 0x00040000 /* beacon queue DMA OK (1) */ +#define R92C_IMR_BCNDOK2 0x00080000 /* beacon queue DMA OK (2) */ +#define R92C_IMR_BCNDOK3 0x00100000 /* beacon queue DMA OK (3) */ +#define R92C_IMR_BCNDOK4 0x00200000 /* beacon queue DMA OK (4) */ +#define R92C_IMR_BCNDOK5 0x00400000 /* beacon queue DMA OK (5) */ +#define R92C_IMR_BCNDOK6 0x00800000 /* beacon queue DMA OK (6) */ +#define R92C_IMR_BCNDOK7 0x01000000 /* beacon queue DMA OK (7) */ +#define R92C_IMR_BCNDOK8 0x02000000 /* beacon queue DMA OK (8) */ +#define R92C_IMR_BCNDMAINT1 0x04000000 /* beacon DMA interrupt 1 */ +#define R92C_IMR_BCNDMAINT2 0x08000000 /* beacon DMA interrupt 2 */ +#define R92C_IMR_BCNDMAINT3 0x10000000 /* beacon DMA interrupt 3 */ +#define R92C_IMR_BCNDMAINT4 0x20000000 /* beacon DMA interrupt 4 */ +#define R92C_IMR_BCNDMAINT5 0x40000000 /* beacon DMA interrupt 5 */ +#define R92C_IMR_BCNDMAINT6 0x80000000 /* beacon DMA interrupt 6 */ + +/* Shortcut. */ +#define R92C_IBSS_INT_MASK \ + (R92C_IMR_BCNINT | R92C_IMR_TBDOK | R92C_IMR_TBDER) + +#endif /* R92CE_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx.c new file mode 100644 index 0000000000..80938b2043 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx.c @@ -0,0 +1,132 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_rx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + + +int +r92ce_classify_intr(struct rtwn_softc *sc, void *arg, int len __unused) +{ + uint32_t status; + int *rings = arg; + int ret; + + *rings = 0; + status = rtwn_read_4(sc, R92C_HISR); + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: HISR %08X, HISRE %04X\n", + __func__, status, rtwn_read_2(sc, R92C_HISRE)); + if (status == 0 || status == 0xffffffff) + return (0); + + /* Disable interrupts. */ + rtwn_write_4(sc, R92C_HIMR, 0); + + /* Ack interrupts. */ + rtwn_write_4(sc, R92C_HISR, status); + + if (status & R92C_IMR_BDOK) + *rings |= (1 << RTWN_PCI_BEACON_QUEUE); + if (status & R92C_IMR_HIGHDOK) + *rings |= (1 << RTWN_PCI_HIGH_QUEUE); + if (status & R92C_IMR_MGNTDOK) + *rings |= (1 << RTWN_PCI_MGNT_QUEUE); + if (status & R92C_IMR_BKDOK) + *rings |= (1 << RTWN_PCI_BK_QUEUE); + if (status & R92C_IMR_BEDOK) + *rings |= (1 << RTWN_PCI_BE_QUEUE); + if (status & R92C_IMR_VIDOK) + *rings |= (1 << RTWN_PCI_VI_QUEUE); + if (status & R92C_IMR_VODOK) + *rings |= (1 << RTWN_PCI_VO_QUEUE); + + ret = 0; + if (status & R92C_IMR_RXFOVW) + ret |= RTWN_PCI_INTR_RX_OVERFLOW; + if (status & R92C_IMR_RDU) + ret |= RTWN_PCI_INTR_RX_DESC_UNAVAIL; + if (status & R92C_IMR_ROK) + ret |= RTWN_PCI_INTR_RX_DONE; + if (status & R92C_IMR_TXFOVW) + ret |= RTWN_PCI_INTR_TX_OVERFLOW; + if (status & R92C_IMR_PSTIMEOUT) + ret |= RTWN_PCI_INTR_PS_TIMEOUT; + + return (ret); +} + +#define R92C_INT_ENABLE (R92C_IMR_ROK | R92C_IMR_VODOK | R92C_IMR_VIDOK | \ + R92C_IMR_BEDOK | R92C_IMR_BKDOK | R92C_IMR_MGNTDOK | \ + R92C_IMR_HIGHDOK | R92C_IMR_BDOK | R92C_IMR_RDU | \ + R92C_IMR_RXFOVW) +void +r92ce_enable_intr(struct rtwn_pci_softc *pc) +{ + struct rtwn_softc *sc = &pc->pc_sc; + + /* Enable interrupts. */ + rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE); +} + +void +r92ce_start_xfers(struct rtwn_softc *sc) +{ + /* Clear pending interrupts. */ + rtwn_write_4(sc, R92C_HISR, 0xffffffff); + + /* Enable interrupts. */ + rtwn_write_4(sc, R92C_HIMR, R92C_INT_ENABLE); +} +#undef R92C_INT_ENABLE diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h new file mode 100644 index 0000000000..28d3365a0a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h @@ -0,0 +1,41 @@ +/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_rx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CE_RX_DESC_H +#define R92CE_RX_DESC_H + +#include + +/* Rx MAC descriptor (PCIe). */ +struct r92ce_rx_stat { + uint32_t rxdw0; + uint32_t rxdw1; + uint32_t rxdw2; + uint32_t rxdw3; + uint32_t rxdw4; + uint32_t tsf_low; + + uint32_t rxbufaddr; + uint32_t rxbufaddr64; +} __packed __attribute__((aligned(4))); + +#endif /* R92CE_RX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx.c new file mode 100644 index 0000000000..30c8badb74 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx.c @@ -0,0 +1,115 @@ +/* $OpenBSD: if_rtwn.c,v 1.6 2015/08/28 00:03:53 deraadt Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_tx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + + +void +r92ce_setup_tx_desc(struct rtwn_pci_softc *pc, void *desc, + uint32_t next_desc_addr) +{ + struct r92ce_tx_desc *txd = desc; + + /* setup tx desc */ + txd->nextdescaddr = htole32(next_desc_addr); +} + +void +r92ce_tx_postsetup(struct rtwn_pci_softc *pc, void *desc, + bus_dma_segment_t segs[]) +{ + struct r92ce_tx_desc *txd = desc; + + txd->txbufaddr = htole32(segs[0].ds_addr); + txd->txbufsize = txd->pktlen; + bus_space_barrier(pc->pc_st, pc->pc_sh, 0, pc->pc_mapsize, + BUS_SPACE_BARRIER_WRITE); +} + +void +r92ce_copy_tx_desc(void *dest, const void *src) +{ + struct r92ce_tx_desc *txd = dest; + size_t len = sizeof(struct r92c_tx_desc) + + sizeof(txd->txbufsize) + sizeof(txd->pad); + + if (src != NULL) + memcpy(dest, src, len); + else + memset(dest, 0, len); +} + +void +r92ce_dump_tx_desc(struct rtwn_softc *sc, const void *desc) +{ +#ifdef RTWN_DEBUG + const struct r92ce_tx_desc *txd = desc; + + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT_DESC, + "%s: len %d, off %d, flags0 %02X, dw: 1 %08X, 2 %08X, 3 %04X " + "(seq %04X), 4 %08X, 5 %08X, 6 %08X, size %04X, pad %04X, " + "addr: %08X (64: %08X), next: %08X (64: %08X), " + "rsvd: %08X %08X %08X %08X\n", + __func__, le16toh(txd->pktlen), txd->offset, txd->flags0, + le32toh(txd->txdw1), le32toh(txd->txdw2), le16toh(txd->txdw3), + le16toh(txd->txdseq), le32toh(txd->txdw4), le32toh(txd->txdw5), + le32toh(txd->txdw6), le16toh(txd->txbufsize), le16toh(txd->pad), + le32toh(txd->txbufaddr), le32toh(txd->txbufaddr64), + le32toh(txd->nextdescaddr), le32toh(txd->nextdescaddr64), + le32toh(txd->reserved[0]), le32toh(txd->reserved[1]), + le32toh(txd->reserved[2]), le32toh(txd->reserved[3])); +#endif +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h new file mode 100644 index 0000000000..7af725f2eb --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h @@ -0,0 +1,55 @@ +/* $OpenBSD: if_rtwnreg.h,v 1.3 2015/06/14 08:02:47 stsp Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/pci/r92ce_tx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CE_TX_DESC_H +#define R92CE_TX_DESC_H + +#include + +/* Tx MAC descriptor (PCIe). */ +struct r92ce_tx_desc { + uint16_t pktlen; + uint8_t offset; + uint8_t flags0; + + uint32_t txdw1; + uint32_t txdw2; + uint16_t txdw3; + uint16_t txdseq; + + uint32_t txdw4; + uint32_t txdw5; + uint32_t txdw6; + + uint16_t txbufsize; + uint16_t pad; + + uint32_t txbufaddr; + uint32_t txbufaddr64; + + uint32_t nextdescaddr; + uint32_t nextdescaddr64; + + uint32_t reserved[4]; +} __packed __attribute__((aligned(4))); + +#endif /* R92CE_TX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c.h new file mode 100644 index 0000000000..df7b8925c4 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c.h @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c.h 322950 2017-08-27 13:02:51Z avos $ + */ + +#ifndef RTL8192C_H +#define RTL8192C_H + +/* + * Global definitions. + */ +#define R92C_TXPKTBUF_COUNT 256 + +#define R92C_TX_PAGE_SIZE 128 +#define R92C_RX_DMA_BUFFER_SIZE 0x2800 + +#define R92C_MAX_FW_SIZE 0x4000 +#define R92C_MACID_MAX 31 +#define R92C_CAM_ENTRY_COUNT 32 + +#define R92C_CALIB_THRESHOLD 2 + + +/* + * Function declarations. + */ +/* r92c_attach.c */ +void r92c_detach_private(struct rtwn_softc *); +void r92c_read_chipid_vendor(struct rtwn_softc *, uint32_t); + +/* r92c_beacon.c */ +void r92c_beacon_init(struct rtwn_softc *, void *, int); +void r92c_beacon_enable(struct rtwn_softc *, int, int); + +/* r92c_calib.c */ +void r92c_iq_calib(struct rtwn_softc *); +void r92c_lc_calib(struct rtwn_softc *); +void r92c_temp_measure(struct rtwn_softc *); +uint8_t r92c_temp_read(struct rtwn_softc *); + +/* r92c_chan.c */ +void r92c_get_txpower(struct rtwn_softc *, int, + struct ieee80211_channel *, uint8_t[]); +void r92c_write_txpower(struct rtwn_softc *, int, + uint8_t power[]); +void r92c_set_bw20(struct rtwn_softc *, uint8_t); +void r92c_set_chan(struct rtwn_softc *, struct ieee80211_channel *); +void r92c_set_gain(struct rtwn_softc *, uint8_t); +void r92c_scan_start(struct ieee80211com *); +void r92c_scan_end(struct ieee80211com *); + +/* r92c_fw.c */ +#ifndef RTWN_WITHOUT_UCODE +void r92c_fw_reset(struct rtwn_softc *, int); +void r92c_fw_download_enable(struct rtwn_softc *, int); +#endif +void r92c_joinbss_rpt(struct rtwn_softc *, int); +#ifndef RTWN_WITHOUT_UCODE +int r92c_set_rsvd_page(struct rtwn_softc *, int, int, int); +int r92c_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); +void r92c_set_rssi(struct rtwn_softc *); +void r92c_handle_c2h_report(void *); +#endif + +/* r92c_init.c */ +int r92c_check_condition(struct rtwn_softc *, const uint8_t[]); +int r92c_llt_init(struct rtwn_softc *); +int r92c_set_page_size(struct rtwn_softc *); +void r92c_init_bb_common(struct rtwn_softc *); +int r92c_init_rf_chain(struct rtwn_softc *, + const struct rtwn_rf_prog *, int); +void r92c_init_rf(struct rtwn_softc *); +void r92c_init_edca(struct rtwn_softc *); +void r92c_init_ampdu(struct rtwn_softc *); +void r92c_init_antsel(struct rtwn_softc *); +void r92c_pa_bias_init(struct rtwn_softc *); + +/* r92c_llt.c */ +int r92c_llt_write(struct rtwn_softc *, uint32_t, uint32_t); + +/* r92c_rf.c */ +uint32_t r92c_rf_read(struct rtwn_softc *, int, uint8_t); +void r92c_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); + +/* r92c_rom.c */ +void r92c_efuse_postread(struct rtwn_softc *); +void r92c_parse_rom(struct rtwn_softc *, uint8_t *); + +/* r92c_rx.c */ +int8_t r92c_get_rssi_cck(struct rtwn_softc *, void *); +int8_t r92c_get_rssi_ofdm(struct rtwn_softc *, void *); +uint8_t r92c_rx_radiotap_flags(const void *); +void r92c_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, + const void *, const void *); + +/* r92c_tx.c */ +void r92c_tx_enable_ampdu(void *, int); +void r92c_tx_setup_hwseq(void *); +void r92c_tx_setup_macid(void *, int); +void r92c_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *, + struct mbuf *, void *, uint8_t, int); +void r92c_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *, + struct mbuf *, void *, const struct ieee80211_bpf_params *); +void r92c_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int); +uint8_t r92c_tx_radiotap_flags(const void *); + +#endif /* RTL8192C_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_attach.c new file mode 100644 index 0000000000..c1b3eb4d2d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_attach.c @@ -0,0 +1,80 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_attach.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + + +void +r92c_detach_private(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + + free(rs, M_RTWN_PRIV); +} + +void +r92c_read_chipid_vendor(struct rtwn_softc *sc, uint32_t reg_sys_cfg) +{ + struct r92c_softc *rs = sc->sc_priv; + + if (reg_sys_cfg & R92C_SYS_CFG_TYPE_92C) { + rs->chip |= R92C_CHIP_92C; + /* Check if it is a castrated 8192C. */ + if (MS(rtwn_read_4(sc, R92C_HPON_FSM), + R92C_HPON_FSM_CHIP_BONDING_ID) == + R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R) + rs->chip |= R92C_CHIP_92C_1T2R; + } + if (reg_sys_cfg & R92C_SYS_CFG_VENDOR_UMC) { + if (MS(reg_sys_cfg, R92C_SYS_CFG_CHIP_VER_RTL) == 0) + rs->chip |= R92C_CHIP_UMC_A_CUT; + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_beacon.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_beacon.c new file mode 100644 index 0000000000..21b6095b3f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_beacon.c @@ -0,0 +1,86 @@ +/*- + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_beacon.c 308389 2016-11-06 23:13:13Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + + +void +r92c_beacon_init(struct rtwn_softc *sc, void *buf, int id) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + /* + * NB: there is no need to setup HWSEQ_EN bit; + * QSEL_BEACON already implies it. + */ + txd->flags0 |= R92C_FLAGS0_BMCAST | R92C_FLAGS0_FSG | R92C_FLAGS0_LSG; + txd->txdw1 |= htole32( + SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_BEACON) | + SM(R92C_TXDW1_RAID, R92C_RAID_11B)); + + rtwn_r92c_tx_setup_macid(sc, buf, id); + txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id)); + txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, id)); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, RTWN_RIDX_CCK1)); +} + +void +r92c_beacon_enable(struct rtwn_softc *sc, int id, int enable) +{ + + if (enable) { + rtwn_setbits_1(sc, R92C_BCN_CTRL(id), + 0, R92C_BCN_CTRL_EN_BCN); + } else { + rtwn_setbits_1(sc, R92C_BCN_CTRL(id), + R92C_BCN_CTRL_EN_BCN, 0); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_calib.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_calib.c new file mode 100644 index 0000000000..b8bda27773 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_calib.c @@ -0,0 +1,113 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_calib.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r92c_iq_calib(struct rtwn_softc *sc) +{ + /* XXX TODO */ +} + +void +r92c_lc_calib(struct rtwn_softc *sc) +{ + uint32_t rf_ac[2]; + uint8_t txmode; + int i; + + txmode = rtwn_read_1(sc, R92C_OFDM1_LSTF + 3); + if ((txmode & 0x70) != 0) { + /* Disable all continuous Tx. */ + rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode & ~0x70); + + /* Set RF mode to standby mode. */ + for (i = 0; i < sc->nrxchains; i++) { + rf_ac[i] = rtwn_rf_read(sc, i, R92C_RF_AC); + rtwn_rf_write(sc, i, R92C_RF_AC, + RW(rf_ac[i], R92C_RF_AC_MODE, + R92C_RF_AC_MODE_STANDBY)); + } + } else { + /* Block all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + } + /* Start calibration. */ + rtwn_rf_setbits(sc, 0, R92C_RF_CHNLBW, 0, R92C_RF_CHNLBW_LCSTART); + + /* Give calibration the time to complete. */ + rtwn_delay(sc, 100000); /* 100ms */ + + /* Restore configuration. */ + if ((txmode & 0x70) != 0) { + /* Restore Tx mode. */ + rtwn_write_1(sc, R92C_OFDM1_LSTF + 3, txmode); + /* Restore RF mode. */ + for (i = 0; i < sc->nrxchains; i++) + rtwn_rf_write(sc, i, R92C_RF_AC, rf_ac[i]); + } else { + /* Unblock all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, 0x00); + } +} + +void +r92c_temp_measure(struct rtwn_softc *sc) +{ + rtwn_rf_write(sc, 0, R92C_RF_T_METER, R92C_RF_T_METER_START); +} + +uint8_t +r92c_temp_read(struct rtwn_softc *sc) +{ + return (MS(rtwn_rf_read(sc, 0, R92C_RF_T_METER), + R92C_RF_T_METER_VAL)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_chan.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_chan.c new file mode 100644 index 0000000000..7ff15cef5e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_chan.c @@ -0,0 +1,351 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_chan.c 330750 2018-03-10 23:47:03Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + + +static int +r92c_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t chan; + int group; + + chan = rtwn_chan2centieee(c); + if (IEEE80211_IS_CHAN_2GHZ(c)) { + if (chan <= 3) group = 0; + else if (chan <= 9) group = 1; + else if (chan <= 14) group = 2; + else { + KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); + return (-1); + } + } else { + KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); + return (-1); + } + + return (group); +} + +/* XXX recheck */ +void +r92c_get_txpower(struct rtwn_softc *sc, int chain, + struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) +{ + struct r92c_softc *rs = sc->sc_priv; + struct rtwn_r92c_txpwr *rt = rs->rs_txpwr; + const struct rtwn_r92c_txagc *base = rs->rs_txagc; + uint8_t ofdmpow, htpow, diff, max; + int max_mcs, ridx, group; + + /* Determine channel group. */ + group = r92c_get_power_group(sc, c); + if (group == -1) { /* shouldn't happen */ + device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); + return; + } + + /* XXX net80211 regulatory */ + + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); + KASSERT(max_mcs <= RTWN_RIDX_COUNT, ("increase ridx limit\n")); + + if (rs->regulatory == 0) { + for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) + power[ridx] = base[chain].pwr[0][ridx]; + } + for (ridx = RTWN_RIDX_OFDM6; ridx < RTWN_RIDX_COUNT; ridx++) { + if (rs->regulatory == 3) { + power[ridx] = base[chain].pwr[0][ridx]; + /* Apply vendor limits. */ + if (IEEE80211_IS_CHAN_HT40(c)) + max = rt->ht40_max_pwr[chain][group]; + else + max = rt->ht20_max_pwr[chain][group]; + if (power[ridx] > max) + power[ridx] = max; + } else if (rs->regulatory == 1) { + if (!IEEE80211_IS_CHAN_HT40(c)) + power[ridx] = base[chain].pwr[group][ridx]; + } else if (rs->regulatory != 2) + power[ridx] = base[chain].pwr[0][ridx]; + } + + /* Compute per-CCK rate Tx power. */ + for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) + power[ridx] += rt->cck_tx_pwr[chain][group]; + + htpow = rt->ht40_1s_tx_pwr[chain][group]; + if (sc->ntxchains > 1) { + /* Apply reduction for 2 spatial streams. */ + diff = rt->ht40_2s_tx_pwr_diff[chain][group]; + htpow = (htpow > diff) ? htpow - diff : 0; + } + + /* Compute per-OFDM rate Tx power. */ + diff = rt->ofdm_tx_pwr_diff[chain][group]; + ofdmpow = htpow + diff; /* HT->OFDM correction. */ + for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) + power[ridx] += ofdmpow; + + /* Compute per-MCS Tx power. */ + if (!IEEE80211_IS_CHAN_HT40(c)) { + diff = rt->ht20_tx_pwr_diff[chain][group]; + htpow += diff; /* HT40->HT20 correction. */ + } + for (ridx = RTWN_RIDX_HT_MCS(0); ridx <= max_mcs; ridx++) + power[ridx] += htpow; + + /* Apply max limit. */ + for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } +} + +void +r92c_write_txpower(struct rtwn_softc *sc, int chain, + uint8_t power[RTWN_RIDX_COUNT]) +{ + uint32_t reg; + + /* Write per-CCK rate Tx power. */ + if (chain == 0) { + reg = rtwn_bb_read(sc, R92C_TXAGC_A_CCK1_MCS32); + reg = RW(reg, R92C_TXAGC_A_CCK1, power[RTWN_RIDX_CCK1]); + rtwn_bb_write(sc, R92C_TXAGC_A_CCK1_MCS32, reg); + reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); + reg = RW(reg, R92C_TXAGC_A_CCK2, power[RTWN_RIDX_CCK2]); + reg = RW(reg, R92C_TXAGC_A_CCK55, power[RTWN_RIDX_CCK55]); + reg = RW(reg, R92C_TXAGC_A_CCK11, power[RTWN_RIDX_CCK11]); + rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); + } else { + reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK1_55_MCS32); + reg = RW(reg, R92C_TXAGC_B_CCK1, power[RTWN_RIDX_CCK1]); + reg = RW(reg, R92C_TXAGC_B_CCK2, power[RTWN_RIDX_CCK2]); + reg = RW(reg, R92C_TXAGC_B_CCK55, power[RTWN_RIDX_CCK55]); + rtwn_bb_write(sc, R92C_TXAGC_B_CCK1_55_MCS32, reg); + reg = rtwn_bb_read(sc, R92C_TXAGC_B_CCK11_A_CCK2_11); + reg = RW(reg, R92C_TXAGC_B_CCK11, power[RTWN_RIDX_CCK11]); + rtwn_bb_write(sc, R92C_TXAGC_B_CCK11_A_CCK2_11, reg); + } + /* Write per-OFDM rate Tx power. */ + rtwn_bb_write(sc, R92C_TXAGC_RATE18_06(chain), + SM(R92C_TXAGC_RATE06, power[RTWN_RIDX_OFDM6]) | + SM(R92C_TXAGC_RATE09, power[RTWN_RIDX_OFDM9]) | + SM(R92C_TXAGC_RATE12, power[RTWN_RIDX_OFDM12]) | + SM(R92C_TXAGC_RATE18, power[RTWN_RIDX_OFDM18])); + rtwn_bb_write(sc, R92C_TXAGC_RATE54_24(chain), + SM(R92C_TXAGC_RATE24, power[RTWN_RIDX_OFDM24]) | + SM(R92C_TXAGC_RATE36, power[RTWN_RIDX_OFDM36]) | + SM(R92C_TXAGC_RATE48, power[RTWN_RIDX_OFDM48]) | + SM(R92C_TXAGC_RATE54, power[RTWN_RIDX_OFDM54])); + /* Write per-MCS Tx power. */ + rtwn_bb_write(sc, R92C_TXAGC_MCS03_MCS00(chain), + SM(R92C_TXAGC_MCS00, power[RTWN_RIDX_HT_MCS(0)]) | + SM(R92C_TXAGC_MCS01, power[RTWN_RIDX_HT_MCS(1)]) | + SM(R92C_TXAGC_MCS02, power[RTWN_RIDX_HT_MCS(2)]) | + SM(R92C_TXAGC_MCS03, power[RTWN_RIDX_HT_MCS(3)])); + rtwn_bb_write(sc, R92C_TXAGC_MCS07_MCS04(chain), + SM(R92C_TXAGC_MCS04, power[RTWN_RIDX_HT_MCS(4)]) | + SM(R92C_TXAGC_MCS05, power[RTWN_RIDX_HT_MCS(5)]) | + SM(R92C_TXAGC_MCS06, power[RTWN_RIDX_HT_MCS(6)]) | + SM(R92C_TXAGC_MCS07, power[RTWN_RIDX_HT_MCS(7)])); + if (sc->ntxchains >= 2) { + rtwn_bb_write(sc, R92C_TXAGC_MCS11_MCS08(chain), + SM(R92C_TXAGC_MCS08, power[RTWN_RIDX_HT_MCS(8)]) | + SM(R92C_TXAGC_MCS09, power[RTWN_RIDX_HT_MCS(9)]) | + SM(R92C_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) | + SM(R92C_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)])); + rtwn_bb_write(sc, R92C_TXAGC_MCS15_MCS12(chain), + SM(R92C_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) | + SM(R92C_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) | + SM(R92C_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) | + SM(R92C_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)])); + } +} + +static void +r92c_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t power[RTWN_RIDX_COUNT]; + int i; + + for (i = 0; i < sc->ntxchains; i++) { + memset(power, 0, sizeof(power)); + /* Compute per-rate Tx power values. */ + rtwn_r92c_get_txpower(sc, i, c, power); +#ifdef RTWN_DEBUG + if (sc->sc_debug & RTWN_DEBUG_TXPWR) { + int max_mcs, ridx; + + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); + + /* Dump per-rate Tx power values. */ + printf("Tx power for chain %d:\n", i); + for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) + printf("Rate %d = %u\n", ridx, power[ridx]); + } +#endif + /* Write per-rate Tx power values to hardware. */ + r92c_write_txpower(sc, i, power); + } +} + +static void +r92c_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo) +{ + struct r92c_softc *rs = sc->sc_priv; + + rtwn_setbits_1(sc, R92C_BWOPMODE, R92C_BWOPMODE_20MHZ, 0); + rtwn_setbits_1(sc, R92C_RRSR + 2, 0x6f, (prichlo ? 1 : 2) << 5); + + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ); + rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ); + + /* Set CCK side band. */ + rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0x10, + (prichlo ? 0 : 1) << 4); + + rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00, + (prichlo ? 1 : 2) << 10); + + rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, + R92C_FPGA0_ANAPARAM2_CBW20, 0); + + rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26); + + /* Select 40MHz bandwidth. */ + rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, + (rs->rf_chnlbw[0] & ~0xfff) | chan); +} + +void +r92c_set_bw20(struct rtwn_softc *sc, uint8_t chan) +{ + struct r92c_softc *rs = sc->sc_priv; + + rtwn_setbits_1(sc, R92C_BWOPMODE, 0, R92C_BWOPMODE_20MHZ); + + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0); + rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); + + rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, 0, + R92C_FPGA0_ANAPARAM2_CBW20); + + /* Select 20MHz bandwidth. */ + rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, + (rs->rf_chnlbw[0] & ~0xfff) | chan | R92C_RF_CHNLBW_BW20); +} + +void +r92c_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + struct r92c_softc *rs = sc->sc_priv; + u_int chan; + int i; + + chan = rtwn_chan2centieee(c); + + /* Set Tx power for this new channel. */ + r92c_set_txpower(sc, c); + + for (i = 0; i < sc->nrxchains; i++) { + rtwn_rf_write(sc, i, R92C_RF_CHNLBW, + RW(rs->rf_chnlbw[i], R92C_RF_CHNLBW_CHNL, chan)); + } + if (IEEE80211_IS_CHAN_HT40(c)) + r92c_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c)); + else + rtwn_r92c_set_bw20(sc, chan); +} + +void +r92c_set_gain(struct rtwn_softc *sc, uint8_t gain) +{ + + rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(0), + R92C_OFDM0_AGCCORE1_GAIN_M, gain); + rtwn_bb_setbits(sc, R92C_OFDM0_AGCCORE1(1), + R92C_OFDM0_AGCCORE1_GAIN_M, gain); +} + +void +r92c_scan_start(struct ieee80211com *ic) +{ + struct rtwn_softc *sc = ic->ic_softc; + struct r92c_softc *rs = sc->sc_priv; + + RTWN_LOCK(sc); + /* Set gain for scanning. */ + rtwn_r92c_set_gain(sc, 0x20); + RTWN_UNLOCK(sc); + + rs->rs_scan_start(ic); +} + +void +r92c_scan_end(struct ieee80211com *ic) +{ + struct rtwn_softc *sc = ic->ic_softc; + struct r92c_softc *rs = sc->sc_priv; + + RTWN_LOCK(sc); + /* Set gain under link. */ + rtwn_r92c_set_gain(sc, 0x32); + RTWN_UNLOCK(sc); + + rs->rs_scan_end(ic); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw.c new file mode 100644 index 0000000000..ca7f0723d8 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw.c @@ -0,0 +1,520 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_fw.c 322988 2017-08-28 22:14:16Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + + +#ifndef RTWN_WITHOUT_UCODE +static int +r92c_fw_cmd(struct rtwn_softc *sc, uint8_t id, const void *buf, int len) +{ + struct r92c_fw_cmd cmd; + int ntries, error; + + KASSERT(len <= sizeof(cmd.msg), + ("%s: firmware command too long (%d > %zu)\n", + __func__, len, sizeof(cmd.msg))); + + if (!(sc->sc_flags & RTWN_FW_LOADED)) { + RTWN_DPRINTF(sc, RTWN_DEBUG_FIRMWARE, "%s: firmware " + "was not loaded; command (id %u) will be discarded\n", + __func__, id); + return (0); + } + + /* Wait for current FW box to be empty. */ + for (ntries = 0; ntries < 100; ntries++) { + if (!(rtwn_read_1(sc, R92C_HMETFR) & (1 << sc->fwcur))) + break; + rtwn_delay(sc, 2000); + } + if (ntries == 100) { + device_printf(sc->sc_dev, + "could not send firmware command\n"); + return (ETIMEDOUT); + } + memset(&cmd, 0, sizeof(cmd)); + cmd.id = id; + if (len > 3) { + /* Ext command: [id : byte2 : byte3 : byte4 : byte0 : byte1] */ + cmd.id |= R92C_CMD_FLAG_EXT; + memcpy(cmd.msg, (const uint8_t *)buf + 2, len - 2); + memcpy(cmd.msg + 3, buf, 2); + } else + memcpy(cmd.msg, buf, len); + + /* Write the first word last since that will trigger the FW. */ + if (len > 3) { + error = rtwn_write_2(sc, R92C_HMEBOX_EXT(sc->fwcur), + *(uint16_t *)((uint8_t *)&cmd + 4)); + if (error != 0) + return (error); + } + error = rtwn_write_4(sc, R92C_HMEBOX(sc->fwcur), + *(uint32_t *)&cmd); + if (error != 0) + return (error); + + sc->fwcur = (sc->fwcur + 1) % R92C_H2C_NBOX; + + return (0); +} + +void +r92c_fw_reset(struct rtwn_softc *sc, int reason) +{ + int ntries; + + if (reason == RTWN_FW_RESET_CHECKSUM) + return; + + /* Tell 8051 to reset itself. */ + rtwn_write_1(sc, R92C_HMETFR + 3, 0x20); + + /* Wait until 8051 resets by itself. */ + for (ntries = 0; ntries < 100; ntries++) { + if ((rtwn_read_2(sc, R92C_SYS_FUNC_EN) & + R92C_SYS_FUNC_EN_CPUEN) == 0) + return; + rtwn_delay(sc, 50); + } + /* Force 8051 reset. */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_CPUEN, 0, 1); +} + +void +r92c_fw_download_enable(struct rtwn_softc *sc, int enable) +{ + if (enable) { + /* 8051 enable. */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_CPUEN, 1); + /* MCU firmware download enable. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN); + /* 8051 reset. */ + rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN, + 0, 2); + } else { + /* MCU download disable. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0); + /* Reserved for f/w extension. */ + rtwn_write_1(sc, R92C_MCUFWDL + 1, 0); + } +} +#endif + +/* + * Initialize firmware rate adaptation. + */ +#ifndef RTWN_WITHOUT_UCODE +static int +r92c_send_ra_cmd(struct rtwn_softc *sc, int macid, uint32_t rates, + int maxrate) +{ + struct r92c_fw_cmd_macid_cfg cmd; + uint8_t mode; + int error = 0; + + /* XXX should be called directly from iv_newstate() for MACID_BC */ + /* XXX joinbss, not send_ra_cmd() */ +#ifdef RTWN_TODO + /* NB: group addressed frames are done at 11bg rates for now */ + if (ic->ic_curmode == IEEE80211_MODE_11B) + mode = R92C_RAID_11B; + else + mode = R92C_RAID_11BG; + /* XXX misleading 'mode' value here for unicast frames */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RA, + "%s: mode 0x%x, rates 0x%08x, basicrates 0x%08x\n", __func__, + mode, rates, basicrates); + + /* Set rates mask for group addressed frames. */ + cmd.macid = RTWN_MACID_BC | R92C_CMD_MACID_VALID; + cmd.mask = htole32(mode << 28 | basicrates); + error = rtwn_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); + if (error != 0) { + device_printf(sc->sc_dev, + "could not set RA mask for broadcast station\n"); + return (error); + } +#endif + + /* Set rates mask for unicast frames. */ + if (maxrate >= RTWN_RIDX_HT_MCS(0)) + mode = R92C_RAID_11GN; + else if (maxrate >= RTWN_RIDX_OFDM6) + mode = R92C_RAID_11BG; + else + mode = R92C_RAID_11B; + cmd.macid = macid | R92C_CMD_MACID_VALID; + cmd.mask = htole32(mode << 28 | rates); + error = r92c_fw_cmd(sc, R92C_CMD_MACID_CONFIG, &cmd, sizeof(cmd)); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: could not set RA mask for %d station\n", + __func__, macid); + return (error); + } + + return (0); +} +#endif + +static void +r92c_init_ra(struct rtwn_softc *sc, int macid) +{ + struct ieee80211_htrateset *rs_ht; + struct ieee80211_node *ni; + uint32_t rates; + int maxrate; + + RTWN_NT_LOCK(sc); + if (sc->node_list[macid] == NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RA, "%s: macid %d, ni is NULL\n", + __func__, macid); + RTWN_NT_UNLOCK(sc); + return; + } + + ni = ieee80211_ref_node(sc->node_list[macid]); + if (ni->ni_flags & IEEE80211_NODE_HT) + rs_ht = &ni->ni_htrates; + else + rs_ht = NULL; + /* XXX MACID_BC */ + rtwn_get_rates(sc, &ni->ni_rates, rs_ht, &rates, &maxrate, 0); + RTWN_NT_UNLOCK(sc); + +#ifndef RTWN_WITHOUT_UCODE + if (sc->sc_ratectl == RTWN_RATECTL_FW) { + r92c_send_ra_cmd(sc, macid, rates, maxrate); + } +#endif + + rtwn_write_1(sc, R92C_INIDATA_RATE_SEL(macid), maxrate); + + ieee80211_free_node(ni); +} + +void +r92c_joinbss_rpt(struct rtwn_softc *sc, int macid) +{ +#ifndef RTWN_WITHOUT_UCODE + struct r92c_softc *rs = sc->sc_priv; + struct ieee80211vap *vap; + struct r92c_fw_cmd_joinbss_rpt cmd; + + if (sc->vaps[0] == NULL) /* XXX fix */ + goto end; + + vap = &sc->vaps[0]->vap; + if ((vap->iv_state == IEEE80211_S_RUN) ^ + !(rs->rs_flags & R92C_FLAG_ASSOCIATED)) + goto end; + + if (rs->rs_flags & R92C_FLAG_ASSOCIATED) { + cmd.mstatus = R92C_MSTATUS_DISASSOC; + rs->rs_flags &= ~R92C_FLAG_ASSOCIATED; + } else { + cmd.mstatus = R92C_MSTATUS_ASSOC; + rs->rs_flags |= R92C_FLAG_ASSOCIATED; + } + + if (r92c_fw_cmd(sc, R92C_CMD_JOINBSS_RPT, &cmd, sizeof(cmd)) != 0) { + device_printf(sc->sc_dev, "%s: cannot change media status!\n", + __func__); + } + +end: +#endif + + /* TODO: init rates for RTWN_MACID_BC. */ + if (macid & RTWN_MACID_VALID) + r92c_init_ra(sc, macid & ~RTWN_MACID_VALID); +} + +#ifndef RTWN_WITHOUT_UCODE +int +r92c_set_rsvd_page(struct rtwn_softc *sc, int probe_resp, int null, + int qos_null) +{ + struct r92c_fw_cmd_rsvdpage rsvd; + + rsvd.probe_resp = probe_resp; + rsvd.ps_poll = 0; + rsvd.null_data = null; + + return (r92c_fw_cmd(sc, R92C_CMD_RSVD_PAGE, &rsvd, sizeof(rsvd))); +} + +int +r92c_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, + int off) +{ + struct r92c_fw_cmd_pwrmode mode; + int error; + + /* XXX dm_RF_saving */ + + if (off && vap->iv_state == IEEE80211_S_RUN && + (vap->iv_flags & IEEE80211_F_PMGTON)) + mode.mode = R92C_PWRMODE_MIN; + else + mode.mode = R92C_PWRMODE_CAM; + mode.smart_ps = R92C_PWRMODE_SMARTPS_NULLDATA; + mode.bcn_pass = 1; /* XXX */ + error = r92c_fw_cmd(sc, R92C_CMD_SET_PWRMODE, &mode, sizeof(mode)); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: CMD_SET_PWRMODE was not sent, error %d\n", + __func__, error); + } + + return (error); +} + +void +r92c_set_rssi(struct rtwn_softc *sc) +{ + struct ieee80211_node *ni; + struct rtwn_node *rn; + struct r92c_fw_cmd_rssi cmd; + int i; + + cmd.reserved = 0; + + RTWN_NT_LOCK(sc); + for (i = 0; i < sc->macid_limit; i++) { + /* XXX optimize? */ + ni = sc->node_list[i]; + if (ni == NULL) + continue; + + rn = RTWN_NODE(ni); + cmd.macid = i; + cmd.pwdb = rn->avg_pwdb; + RTWN_DPRINTF(sc, RTWN_DEBUG_RSSI, + "%s: sending RSSI command (macid %d, rssi %d)\n", + __func__, i, rn->avg_pwdb); + + RTWN_NT_UNLOCK(sc); + r92c_fw_cmd(sc, R92C_CMD_RSSI_SETTING, &cmd, sizeof(cmd)); + RTWN_NT_LOCK(sc); + } + RTWN_NT_UNLOCK(sc); +} + +static void +r92c_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) +{ +#if __FreeBSD_version >= 1200012 + struct ieee80211_ratectl_tx_status txs; +#endif + struct r92c_c2h_tx_rpt *rpt; + struct ieee80211_node *ni; + uint8_t macid; + int ntries; + + if (sc->sc_ratectl != RTWN_RATECTL_NET80211) { + /* shouldn't happen */ + device_printf(sc->sc_dev, "%s called while ratectl = %d!\n", + __func__, sc->sc_ratectl); + return; + } + + rpt = (struct r92c_c2h_tx_rpt *)buf; + if (len != sizeof(*rpt)) { + device_printf(sc->sc_dev, + "%s: wrong report size (%d, must be %zu)\n", + __func__, len, sizeof(*rpt)); + return; + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: ccx report dump: 0: %02X, 1: %02X, queue time: " + "low %02X, high %02X, 4: %02X, 5: %02X, 6: %02X, 7: %02X\n", + __func__, rpt->rptb0, rpt->rptb1, rpt->queue_time_low, + rpt->queue_time_high, rpt->rptb4, rpt->rptb5, rpt->rptb6, + rpt->rptb7); + + macid = MS(rpt->rptb5, R92C_RPTB5_MACID); + if (macid > sc->macid_limit) { + device_printf(sc->sc_dev, + "macid %u is too big; increase MACID_MAX limit\n", + macid); + return; + } + + ntries = MS(rpt->rptb0, R92C_RPTB0_RETRY_CNT); + + RTWN_NT_LOCK(sc); + ni = sc->node_list[macid]; + if (ni != NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was" + "%s sent (%d retries)\n", __func__, macid, + (rpt->rptb7 & R92C_RPTB7_PKT_OK) ? "" : " not", + ntries); + +#if __FreeBSD_version >= 1200012 + txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY; + txs.long_retries = ntries; + if (rpt->rptb7 & R92C_RPTB7_PKT_OK) + txs.status = IEEE80211_RATECTL_TX_SUCCESS; + else if (rpt->rptb6 & R92C_RPTB6_RETRY_OVER) + txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; /* XXX */ + else if (rpt->rptb6 & R92C_RPTB6_LIFE_EXPIRE) + txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + else + txs.status = IEEE80211_RATECTL_TX_FAIL_UNSPECIFIED; + ieee80211_ratectl_tx_complete(ni, &txs); +#else + struct ieee80211vap *vap = ni->ni_vap; + if (rpt->rptb7 & R92C_RPTB7_PKT_OK) { + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); + } else { + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); + } +#endif + } else { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: macid %u, ni is NULL\n", + __func__, macid); + } + RTWN_NT_UNLOCK(sc); + +#ifdef IEEE80211_SUPPORT_SUPERG + if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1) + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); +#endif +} + +static void +r92c_handle_c2h_task(struct rtwn_softc *sc, union sec_param *data) +{ + const uint16_t off = R92C_C2H_EVT_MSG + sizeof(struct r92c_c2h_evt); + struct r92c_softc *rs = sc->sc_priv; + uint16_t buf[R92C_C2H_MSG_MAX_LEN / 2 + 1]; + uint8_t id, len, status; + int i; + + /* Do not reschedule the task if device is not running. */ + if (!(sc->sc_flags & RTWN_RUNNING)) + return; + + /* Read current status. */ + status = rtwn_read_1(sc, R92C_C2H_EVT_CLEAR); + if (status == R92C_C2H_EVT_HOST_CLOSE) + goto end; /* nothing to do */ + else if (status == R92C_C2H_EVT_FW_CLOSE) { + len = rtwn_read_1(sc, R92C_C2H_EVT_MSG); + id = MS(len, R92C_C2H_EVTB0_ID); + len = MS(len, R92C_C2H_EVTB0_LEN); + + memset(buf, 0, sizeof(buf)); + /* Try to optimize event reads. */ + for (i = 0; i < len; i += 2) + buf[i / 2] = rtwn_read_2(sc, off + i); + KASSERT(i < sizeof(buf), ("%s: buffer overrun (%d >= %zu)!", + __func__, i, sizeof(buf))); + + switch (id) { + case R92C_C2H_EVT_TX_REPORT: + r92c_ratectl_tx_complete(sc, (uint8_t *)buf, len); + break; + default: + device_printf(sc->sc_dev, + "%s: C2H report %u (len %u) was not handled\n", + __func__, id, len); + break; + } + } + + /* Prepare for next event. */ + rtwn_write_1(sc, R92C_C2H_EVT_CLEAR, R92C_C2H_EVT_HOST_CLOSE); + +end: + /* Adjust timeout for next call. */ + if (rs->rs_c2h_pending != 0) { + rs->rs_c2h_pending = 0; + rs->rs_c2h_paused = 0; + } else + rs->rs_c2h_paused++; + + if (rs->rs_c2h_paused > R92C_TX_PAUSED_THRESHOLD) + rs->rs_c2h_timeout = hz; + else + rs->rs_c2h_timeout = MAX(hz / 100, 1); + + /* Reschedule the task. */ + callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, + r92c_handle_c2h_report, sc); +} + +void +r92c_handle_c2h_report(void *arg) +{ + struct rtwn_softc *sc = arg; + + rtwn_cmd_sleepable(sc, NULL, 0, r92c_handle_c2h_task); +} + +#endif /* RTWN_WITHOUT_UCODE */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw_cmd.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw_cmd.h new file mode 100644 index 0000000000..04c7f62e9d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_fw_cmd.h @@ -0,0 +1,148 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_fw_cmd.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92C_FW_CMD_H +#define R92C_FW_CMD_H + +/* + * Host to firmware commands. + */ +struct r92c_fw_cmd { + uint8_t id; +#define R92C_CMD_SET_PWRMODE 1 +#define R92C_CMD_JOINBSS_RPT 2 +#define R92C_CMD_RSVD_PAGE 3 +#define R92C_CMD_RSSI_SETTING 5 +#define R92C_CMD_MACID_CONFIG 6 + +#define R92C_CMD_FLAG_EXT 0x80 + + uint8_t msg[5]; +} __packed __attribute__((aligned(4))); + +/* Structure for R92C_CMD_JOINBSS_RPT. */ +struct r92c_fw_cmd_joinbss_rpt { + uint8_t mstatus; +#define R92C_MSTATUS_DISASSOC 0x00 +#define R92C_MSTATUS_ASSOC 0x01 +} __packed; + +/* Structure for R92C_CMD_SET_PWRMODE. */ +struct r92c_fw_cmd_pwrmode { + uint8_t mode; +#define R92C_PWRMODE_CAM 0 +#define R92C_PWRMODE_MIN 1 +#define R92C_PWRMODE_MAX 2 +#define R92C_PWRMODE_DTIM 3 +#define R92C_PWRMODE_UAPSD_WMM 5 +#define R92C_PWRMODE_UAPSD 6 +#define R92C_PWRMODE_IBSS 7 + + uint8_t smart_ps; +/* XXX undocumented */ +#define R92C_PWRMODE_SMARTPS_NULLDATA 2 + + uint8_t bcn_pass; /* unit: beacon interval */ +} __packed; + +/* Structure for R92C_CMD_RSVD_PAGE. */ +struct r92c_fw_cmd_rsvdpage { + uint8_t probe_resp; + uint8_t ps_poll; + uint8_t null_data; +} __packed; + +/* Structure for R92C_CMD_RSSI_SETTING. */ +struct r92c_fw_cmd_rssi { + uint8_t macid; + uint8_t reserved; + uint8_t pwdb; +} __packed; + +/* Structure for R92C_CMD_MACID_CONFIG. */ +struct r92c_fw_cmd_macid_cfg { + uint32_t mask; + uint8_t macid; +#define R92C_CMD_MACID_VALID 0x80 +} __packed; + +/* + * C2H event structure. + */ +/* Bigger value is used to prevent buffer overrun. */ +#define R92C_C2H_MSG_MAX_LEN 16 + +struct r92c_c2h_evt { + uint8_t evtb0; +#define R92C_C2H_EVTB0_ID_M 0x0f +#define R92C_C2H_EVTB0_ID_S 0 +#define R92C_C2H_EVTB0_LEN_M 0xf0 +#define R92C_C2H_EVTB0_LEN_S 4 + + uint8_t seq; + + /* Followed by payload (see below). */ +} __packed; + +/* + * C2H event types. + */ +#define R92C_C2H_EVT_DEBUG 0 +#define R92C_C2H_EVT_TX_REPORT 3 +#define R92C_C2H_EVT_EXT_RA_RPT 6 + +/* Structure for R92C_C2H_EVT_TX_REPORT event. */ +struct r92c_c2h_tx_rpt { + uint8_t rptb0; +#define R92C_RPTB0_RETRY_CNT_M 0x3f +#define R92C_RPTB0_RETRY_CNT_S 0 + + uint8_t rptb1; /* XXX junk */ +#define R92C_RPTB1_RTS_RETRY_CNT_M 0x3f +#define R92C_RPTB1_RTS_RETRY_CNT_S 0 + + uint8_t queue_time_low; + uint8_t queue_time_high; + uint8_t rptb4; +#define R92C_RPTB4_MISSED_PKT_NUM_M 0x1f +#define R92C_RPTB4_MISSED_PKT_NUM_S 0 + + uint8_t rptb5; +#define R92C_RPTB5_MACID_M 0x1f +#define R92C_RPTB5_MACID_S 0 +#define R92C_RPTB5_DES1_FRAGSSN_M 0xe0 +#define R92C_RPTB5_DES1_FRAGSSN_S 5 + + uint8_t rptb6; +#define R92C_RPTB6_RPT_PKT_NUM_M 0x1f +#define R92C_RPTB6_RPT_PKT_NUM_S 0 +#define R92C_RPTB6_PKT_DROP 0x20 +#define R92C_RPTB6_LIFE_EXPIRE 0x40 +#define R92C_RPTB6_RETRY_OVER 0x80 + + uint8_t rptb7; +#define R92C_RPTB7_EDCA_M 0x0f +#define R92C_RPTB7_EDCA_S 0 +#define R92C_RPTB7_BMC 0x20 +#define R92C_RPTB7_PKT_OK 0x40 +#define R92C_RPTB7_INT_CCX 0x80 +} __packed; + +#endif /* R92C_FW_CMD_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_init.c new file mode 100644 index 0000000000..63dc06edc4 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_init.c @@ -0,0 +1,343 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_init.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +int +r92c_check_condition(struct rtwn_softc *sc, const uint8_t cond[]) +{ + struct r92c_softc *rs = sc->sc_priv; + uint8_t mask; + int i; + + if (cond[0] == 0) + return (1); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "%s: condition byte 0: %02X; chip %02X, board %02X\n", + __func__, cond[0], rs->chip, rs->board_type); + + if (!(rs->chip & R92C_CHIP_92C)) { + if (rs->board_type == R92C_BOARD_TYPE_HIGHPA) + mask = R92C_COND_RTL8188RU; + else if (rs->board_type == R92C_BOARD_TYPE_MINICARD) + mask = R92C_COND_RTL8188CE; + else + mask = R92C_COND_RTL8188CU; + } else { + if (rs->board_type == R92C_BOARD_TYPE_MINICARD) + mask = R92C_COND_RTL8192CE; + else + mask = R92C_COND_RTL8192CU; + } + + for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++) + if ((cond[i] & mask) == mask) + return (1); + + return (0); +} + +int +r92c_llt_init(struct rtwn_softc *sc) +{ + int i, error; + + /* Reserve pages [0; page_count]. */ + for (i = 0; i < sc->page_count; i++) { + if ((error = r92c_llt_write(sc, i, i + 1)) != 0) + return (error); + } + /* NB: 0xff indicates end-of-list. */ + if ((error = r92c_llt_write(sc, i, 0xff)) != 0) + return (error); + /* + * Use pages [page_count + 1; pktbuf_count - 1] + * as ring buffer. + */ + for (++i; i < sc->pktbuf_count - 1; i++) { + if ((error = r92c_llt_write(sc, i, i + 1)) != 0) + return (error); + } + /* Make the last page point to the beginning of the ring buffer. */ + error = r92c_llt_write(sc, i, sc->page_count + 1); + return (error); +} + +int +r92c_set_page_size(struct rtwn_softc *sc) +{ + return (rtwn_write_1(sc, R92C_PBP, SM(R92C_PBP_PSRX, R92C_PBP_128) | + SM(R92C_PBP_PSTX, R92C_PBP_128)) == 0); +} + +void +r92c_init_bb_common(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + int i, j; + + /* Write BB initialization values. */ + for (i = 0; i < sc->bb_size; i++) { + const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i]; + + while (!rtwn_check_condition(sc, bb_prog->cond)) { + KASSERT(bb_prog->next != NULL, + ("%s: wrong condition value (i %d)\n", + __func__, i)); + bb_prog = bb_prog->next; + } + + for (j = 0; j < bb_prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "BB: reg 0x%03x, val 0x%08x\n", + bb_prog->reg[j], bb_prog->val[j]); + + rtwn_bb_write(sc, bb_prog->reg[j], bb_prog->val[j]); + rtwn_delay(sc, 1); + } + } + + if (rs->chip & R92C_CHIP_92C_1T2R) { + /* 8192C 1T only configuration. */ + rtwn_bb_setbits(sc, R92C_FPGA0_TXINFO, 0x03, 0x02); + rtwn_bb_setbits(sc, R92C_FPGA1_TXINFO, 0x300033, 0x200022); + rtwn_bb_setbits(sc, R92C_CCK0_AFESETTING, 0xff000000, + 0x45000000); + rtwn_bb_setbits(sc, R92C_OFDM0_TRXPATHENA, 0xff, 0x23); + rtwn_bb_setbits(sc, R92C_OFDM0_AGCPARAM1, 0x30, 0x10); + + rtwn_bb_setbits(sc, 0xe74, 0x0c000000, 0x08000000); + rtwn_bb_setbits(sc, 0xe78, 0x0c000000, 0x08000000); + rtwn_bb_setbits(sc, 0xe7c, 0x0c000000, 0x08000000); + rtwn_bb_setbits(sc, 0xe80, 0x0c000000, 0x08000000); + rtwn_bb_setbits(sc, 0xe88, 0x0c000000, 0x08000000); + } + + /* Write AGC values. */ + for (i = 0; i < sc->agc_size; i++) { + const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i]; + + while (!rtwn_check_condition(sc, agc_prog->cond)) { + KASSERT(agc_prog->next != NULL, + ("%s: wrong condition value (2) (i %d)\n", + __func__, i)); + agc_prog = agc_prog->next; + } + + for (j = 0; j < agc_prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "AGC: val 0x%08x\n", agc_prog->val[j]); + + rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, + agc_prog->val[j]); + rtwn_delay(sc, 1); + } + } + + if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR) + sc->sc_flags |= RTWN_FLAG_CCK_HIPWR; +} + +int +r92c_init_rf_chain(struct rtwn_softc *sc, + const struct rtwn_rf_prog *rf_prog, int chain) +{ + int i, j; + + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, "%s: chain %d\n", + __func__, chain); + + for (i = 0; rf_prog[i].reg != NULL; i++) { + const struct rtwn_rf_prog *prog = &rf_prog[i]; + + while (!rtwn_check_condition(sc, prog->cond)) { + KASSERT(prog->next != NULL, + ("%s: wrong condition value (i %d)\n", + __func__, i)); + prog = prog->next; + } + + for (j = 0; j < prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "RF: reg 0x%02x, val 0x%05x\n", + prog->reg[j], prog->val[j]); + + /* + * These are fake RF registers offsets that + * indicate a delay is required. + */ + /* NB: we are using 'value' to store required delay. */ + if (prog->reg[j] > 0xf8) { + rtwn_delay(sc, prog->val[j]); + continue; + } + + rtwn_rf_write(sc, chain, prog->reg[j], prog->val[j]); + rtwn_delay(sc, 1); + } + } + + return (i); +} + +void +r92c_init_rf(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + uint32_t reg, type; + int i, chain, idx, off; + + for (chain = 0, i = 0; chain < sc->nrxchains; chain++, i++) { + /* Save RF_ENV control type. */ + idx = chain / 2; + off = (chain % 2) * 16; + reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)); + type = (reg >> off) & 0x10; + + /* Set RF_ENV enable. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain), + 0, 0x100000); + rtwn_delay(sc, 1); + /* Set RF_ENV output high. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain), + 0, 0x10); + rtwn_delay(sc, 1); + /* Set address and data lengths of RF registers. */ + rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain), + R92C_HSSI_PARAM2_ADDR_LENGTH, 0); + rtwn_delay(sc, 1); + rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain), + R92C_HSSI_PARAM2_DATA_LENGTH, 0); + rtwn_delay(sc, 1); + + /* Write RF initialization values for this chain. */ + i += r92c_init_rf_chain(sc, &sc->rf_prog[i], chain); + + /* Restore RF_ENV control type. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACESW(idx), + 0x10 << off, type << off); + + /* Cache RF register CHNLBW. */ + rs->rf_chnlbw[chain] = rtwn_rf_read(sc, chain, + R92C_RF_CHNLBW); + } + + if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) == + R92C_CHIP_UMC_A_CUT) { + rtwn_rf_write(sc, 0, R92C_RF_RX_G1, 0x30255); + rtwn_rf_write(sc, 0, R92C_RF_RX_G2, 0x50a00); + } + + /* Turn CCK and OFDM blocks on. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN); + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN); +} + +void +r92c_init_edca(struct rtwn_softc *sc) +{ + /* SIFS */ + rtwn_write_2(sc, R92C_SPEC_SIFS, 0x100a); + rtwn_write_2(sc, R92C_MAC_SPEC_SIFS, 0x100a); + rtwn_write_2(sc, R92C_SIFS_CCK, 0x100a); + rtwn_write_2(sc, R92C_SIFS_OFDM, 0x100a); + /* TXOP */ + rtwn_write_4(sc, R92C_EDCA_BE_PARAM, 0x005ea42b); + rtwn_write_4(sc, R92C_EDCA_BK_PARAM, 0x0000a44f); + rtwn_write_4(sc, R92C_EDCA_VI_PARAM, 0x005ea324); + rtwn_write_4(sc, R92C_EDCA_VO_PARAM, 0x002fa226); +} + +void +r92c_init_ampdu(struct rtwn_softc *sc) +{ + + /* Setup AMPDU aggregation. */ + rtwn_write_4(sc, R92C_AGGLEN_LMT, 0x99997631); /* MCS7~0 */ + rtwn_write_1(sc, R92C_AGGR_BREAK_TIME, 0x16); + rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x0708); +} + +void +r92c_init_antsel(struct rtwn_softc *sc) +{ + uint32_t reg; + + if (sc->ntxchains != 1 || sc->nrxchains != 1) + return; + + rtwn_setbits_1(sc, R92C_LEDCFG2, 0, 0x80); + rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000); + reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); + sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); /* XXX */ +} + +void +r92c_pa_bias_init(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + int i; + + for (i = 0; i < sc->nrxchains; i++) { + if (rs->pa_setting & (1 << i)) + continue; + r92c_rf_write(sc, i, R92C_RF_IPA, 0x0f406); + r92c_rf_write(sc, i, R92C_RF_IPA, 0x4f406); + r92c_rf_write(sc, i, R92C_RF_IPA, 0x8f406); + r92c_rf_write(sc, i, R92C_RF_IPA, 0xcf406); + } + if (!(rs->pa_setting & 0x10)) + rtwn_setbits_1(sc, 0x16, 0xf0, 0x90); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_llt.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_llt.c new file mode 100644 index 0000000000..ff26c7cdd1 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_llt.c @@ -0,0 +1,73 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_llt.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +int +r92c_llt_write(struct rtwn_softc *sc, uint32_t addr, uint32_t data) +{ + int ntries, error; + + error = rtwn_write_4(sc, R92C_LLT_INIT, + SM(R92C_LLT_INIT_OP, R92C_LLT_INIT_OP_WRITE) | + SM(R92C_LLT_INIT_ADDR, addr) | + SM(R92C_LLT_INIT_DATA, data)); + if (error != 0) + return (error); + /* Wait for write operation to complete. */ + for (ntries = 0; ntries < 20; ntries++) { + if (MS(rtwn_read_4(sc, R92C_LLT_INIT), R92C_LLT_INIT_OP) == + R92C_LLT_INIT_OP_NO_ACTIVE) + return (0); + rtwn_delay(sc, 10); + } + return (ETIMEDOUT); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_priv.h new file mode 100644 index 0000000000..67021e79dd --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_priv.h @@ -0,0 +1,408 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_priv.h 322988 2017-08-28 22:14:16Z avos $ + */ + +#ifndef R92C_PRIV_H +#define R92C_PRIV_H + +#include + +/* + * Parsed Tx power (diff) values. + */ +struct rtwn_r92c_txpwr { + uint8_t cck_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; + uint8_t ht40_1s_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; + int8_t ht40_2s_tx_pwr_diff[R92C_MAX_CHAINS][R92C_GROUP_2G]; + int8_t ht20_tx_pwr_diff[R92C_MAX_CHAINS][R92C_GROUP_2G]; + int8_t ofdm_tx_pwr_diff[R92C_MAX_CHAINS][R92C_GROUP_2G]; + int8_t ht40_max_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; + int8_t ht20_max_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; +}; + + +/* + * Baseband initialization values (shared parts). + */ +#define R92C_COND_RTL8188CE 0x01 +#define R92C_COND_RTL8188CU 0x02 +#define R92C_COND_RTL8188RU 0x04 +#define R92C_COND_RTL8192CE 0x08 +#define R92C_COND_RTL8192CU 0x10 + +/* Shortcut. */ +#define R92C_COND_RTL8192C (R92C_COND_RTL8192CE | R92C_COND_RTL8192CU) + +static const uint16_t rtl8192c_bb_regs3[] = { + 0xd04 +}, rtl8192c_bb_regs4[] = { + 0xd08, 0xd0c, 0xd10, 0xd14, 0xd18, 0xd2c, 0xd30, 0xd34, 0xd38, + 0xd3c, 0xd40, 0xd44, 0xd48, 0xd4c, 0xd50, 0xd54, 0xd58, 0xd5c, + 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74, 0xd78, 0xe00, 0xe04, + 0xe08, 0xe10, 0xe14, 0xe18, 0xe1c, 0xe28, 0xe30, 0xe34, 0xe38, + 0xe3c, 0xe40, 0xe44, 0xe48, 0xe4c, 0xe50, 0xe54, 0xe58, 0xe5c +}, rtl8192c_bb_regs5[] = { + 0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xf14, + 0xf4c, 0xf00 +}; + +static const uint32_t rtl8192c_bb_vals3_88cu_88ru[] = { + 0x00020401 +}, rtl8192c_bb_vals3_92ce_92cu[] = { + 0x00020403 +}, rtl8192c_bb_vals4[] = { + 0x0000907f, 0x20010201, 0xa0633333, 0x3333bc43, 0x7a8f5b6b, + 0xcc979975, 0x00000000, 0x80608000, 0x00000000, 0x00027293, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x6437140a, + 0x00000000, 0x00000000, 0x30032064, 0x4653de68, 0x04518a3c, + 0x00002101, 0x2a201c16, 0x1812362e, 0x322c2220, 0x000e3c24, + 0x2a2a2a2a, 0x2a2a2a2a, 0x03902a2a, 0x2a2a2a2a, 0x2a2a2a2a, + 0x2a2a2a2a, 0x2a2a2a2a, 0x00000000, 0x1000dc1f, 0x10008c1f, + 0x02140102, 0x681604c2, 0x01007c00, 0x01004800, 0xfb000000, + 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102, 0x28160d05 +},rtl8192c_bb_vals5_92ce_92cu[] = { + 0x00000010, 0x001b25a4, 0x63db25a4, 0x63db25a4, 0x0c1b25a4, + 0x0c1b25a4, 0x0c1b25a4, 0x0c1b25a4, 0x63db25a4, 0x0c1b25a4, + 0x63db25a4, 0x63db25a4, 0x63db25a4, 0x63db25a4, 0x001b25a4, + 0x001b25a4, 0x6fdb25a4, 0x00000003, 0x00000000, 0x00000300 +}; + +/* + * RTL8192CU and RTL8192CE-VAU. + */ + +static const uint32_t rtl8192ce_agc_vals[] = { + 0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001, + 0x7b050001, 0x7a060001, 0x79070001, 0x78080001, 0x77090001, + 0x760a0001, 0x750b0001, 0x740c0001, 0x730d0001, 0x720e0001, + 0x710f0001, 0x70100001, 0x6f110001, 0x6e120001, 0x6d130001, + 0x6c140001, 0x6b150001, 0x6a160001, 0x69170001, 0x68180001, + 0x67190001, 0x661a0001, 0x651b0001, 0x641c0001, 0x631d0001, + 0x621e0001, 0x611f0001, 0x60200001, 0x49210001, 0x48220001, + 0x47230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001, + 0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001, + 0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001, + 0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001, + 0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001, + 0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001, + 0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001, + 0x7a460001, 0x79470001, 0x78480001, 0x77490001, 0x764a0001, + 0x754b0001, 0x744c0001, 0x734d0001, 0x724e0001, 0x714f0001, + 0x70500001, 0x6f510001, 0x6e520001, 0x6d530001, 0x6c540001, + 0x6b550001, 0x6a560001, 0x69570001, 0x68580001, 0x67590001, + 0x665a0001, 0x655b0001, 0x645c0001, 0x635d0001, 0x625e0001, + 0x615f0001, 0x60600001, 0x49610001, 0x48620001, 0x47630001, + 0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001, + 0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001, + 0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001, + 0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001, + 0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001, + 0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e, + 0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e, + 0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e, + 0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e, + 0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e, + 0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e, + 0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e +}; + +static const struct rtwn_agc_prog rtl8192ce_agc[] = { + { + nitems(rtl8192ce_agc_vals), + rtl8192ce_agc_vals, + { 0 }, + NULL + } +}; + + +/* + * RF initialization values. + */ +static const uint8_t rtl8192c_rf0_regs0[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, + 0x0f, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21 +}, rtl8192c_rf0_regs1[] = { + 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28 +}, rtl8192c_rf0_regs2[] = { + 0x29, 0x2a, 0x2b, 0x2a, 0x2b, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, + 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, + 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, + 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, + 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x2b, + 0x2b, 0x2c, 0x2a, 0x2b, 0x2b, 0x2c, 0x2a, 0x10, 0x11, 0x10, 0x11, + 0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11, 0x10, 0x11 +}, rtl8192c_rf0_regs3[] = { + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13 +}, rtl8192c_rf0_regs4[] = { + 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15 +}, rtl8192c_rf0_regs5[] = { + 0x16, 0x16, 0x16, 0x16, 0x00, 0x18, 0xfe, 0xfe, 0x1f, 0xfe, 0xfe, + 0x1e, 0x1f, 0x00 +}; + +static const uint32_t rtl8192c_rf0_vals0_88ce_88cu_92ce[] = { + 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb1, + 0x54867, 0x8992e, 0x0e52c, 0x39ce7, 0x00451, 0x00000, 0x10255, + 0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000 +}, rtl8192c_rf0_vals0_88ru[] = { + 0x30159, 0x31284, 0x98000, 0x18c63, 0x210e7, 0x2044f, 0x1adb0, + 0x54867, 0x8992e, 0x0e529, 0x39ce7, 0x00451, 0x00000, 0x00255, + 0x60a00, 0xfc378, 0xa1250, 0x4445f, 0x80001, 0x0b614, 0x6c000 +}, rtl8192c_rf0_vals1_88ru[] = { + 0x0083c, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x977c0 +}, rtl8192c_rf0_vals1_88ce[] = { + 0x00000, 0x01558, 0x00060, 0x00483, 0x4f200, 0xec7d9, 0x577c0 +}, rtl8192c_rf0_vals1_88cu_92ce[] = { + 0x00000, 0x01558, 0x00060, 0x00483, 0x4f000, 0xec7d9, 0x577c0 +}, rtl8192c_rf0_vals2[] = { + 0x04783, 0x00001, 0x21334, 0x00000, 0x00054, 0x00001, 0x00808, + 0x53333, 0x0000c, 0x00002, 0x00808, 0x5b333, 0x0000d, 0x00003, + 0x00808, 0x63333, 0x0000d, 0x00004, 0x00808, 0x6b333, 0x0000d, + 0x00005, 0x00808, 0x73333, 0x0000d, 0x00006, 0x00709, 0x5b333, + 0x0000d, 0x00007, 0x00709, 0x63333, 0x0000d, 0x00008, 0x0060a, + 0x4b333, 0x0000d, 0x00009, 0x0060a, 0x53333, 0x0000d, 0x0000a, + 0x0060a, 0x5b333, 0x0000d, 0x0000b, 0x0060a, 0x63333, 0x0000d, + 0x0000c, 0x0060a, 0x6b333, 0x0000d, 0x0000d, 0x0060a, 0x73333, + 0x0000d, 0x0000e, 0x0050b, 0x66666, 0x0001a, 0xe0000, 0x4000f, + 0xe31fc, 0x6000f, 0xff9f8, 0x2000f, 0x203f9, 0x3000f, 0xff500, + 0x00000, 0x00000, 0x8000f, 0x3f100, 0x9000f, 0x23100 +}, rtl8192c_rf0_vals3_88ru[] = { + 0xd8000, 0x90000, 0x51000, 0x12000, 0x28fb4, 0x24fa8, 0x207a4, + 0x1c798, 0x183a4, 0x14398, 0x101a4, 0x0c198, 0x080a4, 0x04098, + 0x00014 +}, rtl8192c_rf0_vals3_92ce[] = { + 0x32000, 0x71000, 0xb0000, 0xfc000, 0x287af, 0x244b7, 0x204ab, + 0x1c49f, 0x18493, 0x14297, 0x10295, 0x0c298, 0x0819c, 0x040a8, + 0x0001c +}, rtl8192c_rf0_vals3_88cu_88ce[] = { + 0x32000, 0x71000, 0xb0000, 0xfc000, 0x287b3, 0x244b7, 0x204ab, + 0x1c49f, 0x18493, 0x1429b, 0x10299, 0x0c29c, 0x081a0, 0x040ac, + 0x00020 +}, rtl8192c_rf0_vals4_92ce_88ce[] = { + 0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f424, 0x4f424, 0x8f424, + 0xcf424 +}, rtl8192c_rf0_vals4_88cu_88ru[] = { + 0x1944c, 0x59444, 0x9944c, 0xd9444, 0x0f405, 0x4f405, 0x8f405, + 0xcf405 +}, rtl8192c_rf0_vals5[] = { + 0xe0330, 0xa0330, 0x60330, 0x20330, 0x10159, 0x0f401, 0x0c350, + 0x0c350, 0x80003, 0x0c350, 0x0c350, 0x44457, 0x80000, 0x30159 +}; + +static const struct rtwn_rf_prog rtl8192c_rf[] = { + /* RF chain 0 */ + /* RTL8188RU. */ + { + nitems(rtl8192c_rf0_regs0), + rtl8192c_rf0_regs0, + rtl8192c_rf0_vals0_88ru, + { R92C_COND_RTL8188RU }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8192c_rf0_regs0), + rtl8192c_rf0_regs0, + rtl8192c_rf0_vals0_88ce_88cu_92ce, + { 0 }, + NULL + } + }, + /* RTL8188RU. */ + { + nitems(rtl8192c_rf0_regs1), + rtl8192c_rf0_regs1, + rtl8192c_rf0_vals1_88ru, + { R92C_COND_RTL8188RU }, + /* RTL8188CE. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8192c_rf0_regs1), + rtl8192c_rf0_regs1, + rtl8192c_rf0_vals1_88ce, + { R92C_COND_RTL8188CE }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8192c_rf0_regs1), + rtl8192c_rf0_regs1, + rtl8192c_rf0_vals1_88cu_92ce, + { 0 }, + NULL + } + } + }, + { + nitems(rtl8192c_rf0_regs2), + rtl8192c_rf0_regs2, + rtl8192c_rf0_vals2, + { 0 }, + NULL + }, + /* RTL8188RU. */ + { + nitems(rtl8192c_rf0_regs3), + rtl8192c_rf0_regs3, + rtl8192c_rf0_vals3_88ru, + { R92C_COND_RTL8188RU }, + /* RTL8192C. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8192c_rf0_regs3), + rtl8192c_rf0_regs3, + rtl8192c_rf0_vals3_92ce, + { R92C_COND_RTL8192C }, + /* Others. */ + &(struct rtwn_rf_prog){ + nitems(rtl8192c_rf0_regs3), + rtl8192c_rf0_regs3, + rtl8192c_rf0_vals3_88cu_88ce, + { 0 }, + NULL + } + } + }, + /* RTL8188CE / RTL8192C. */ + { + nitems(rtl8192c_rf0_regs4), + rtl8192c_rf0_regs4, + rtl8192c_rf0_vals4_92ce_88ce, + { R92C_COND_RTL8188CE | R92C_COND_RTL8192C }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8192c_rf0_regs4), + rtl8192c_rf0_regs4, + rtl8192c_rf0_vals4_88cu_88ru, + { 0 }, + NULL + } + }, + { + nitems(rtl8192c_rf0_regs5), + rtl8192c_rf0_regs5, + rtl8192c_rf0_vals5, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL }, + /* RF chain 1 (RTL8192C). */ + { + 12, /* 0x00 - 0x0f */ + rtl8192c_rf0_regs0, + rtl8192c_rf0_vals0_88ce_88cu_92ce, + { 0 }, + NULL + }, + { + nitems(rtl8192c_rf0_regs3), /* 0x12 - 0x13 */ + rtl8192c_rf0_regs3, + rtl8192c_rf0_vals3_92ce, + { 0 }, + NULL + }, + { + nitems(rtl8192c_rf0_regs4), /* 0x14 - 0x15 */ + rtl8192c_rf0_regs4, + rtl8192c_rf0_vals4_92ce_88ce, + { 0 }, + NULL + }, + { + 4, /* 0x16 */ + rtl8192c_rf0_regs5, + rtl8192c_rf0_vals5, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL } +}; + + +struct rtwn_r92c_txagc { + uint8_t pwr[R92C_GROUP_2G][28]; /* RTWN_RIDX_HT_MCS(15) + 1 */ +}; + +/* + * Per RF chain/group/rate Tx gain values. + */ +static const struct rtwn_r92c_txagc rtl8192cu_txagc[] = { + { { /* Chain 0. */ + { /* Group 0. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x0c, 0x0c, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, /* OFDM6~54. */ + 0x0e, 0x0d, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, /* MCS0~7. */ + 0x0e, 0x0d, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02 /* MCS8~15. */ + }, + { /* Group 1. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 2. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + } + } }, + { { /* Chain 1. */ + { /* Group 0. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 1. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 2. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + } + } } +}; + +static const struct rtwn_r92c_txagc rtl8188ru_txagc[] = { + { { /* Chain 0. */ + { /* Group 0. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x08, 0x08, 0x08, 0x06, 0x06, 0x04, 0x04, 0x00, /* OFDM6~54. */ + 0x08, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00, /* MCS0~7. */ + 0x08, 0x06, 0x06, 0x04, 0x04, 0x02, 0x02, 0x00 /* MCS8~15. */ + }, + { /* Group 1. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + }, + { /* Group 2. */ + 0x00, 0x00, 0x00, 0x00, /* CCK1~11. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* OFDM6~54. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MCS0~7. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* MCS8~15. */ + } + } } +}; + +#endif /* R92C_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_reg.h new file mode 100644 index 0000000000..6c0a276764 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_reg.h @@ -0,0 +1,879 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015 Stefan Sperling + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_reg.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92C_REG_H +#define R92C_REG_H + +/* + * MAC registers. + */ +/* System Configuration. */ +#define R92C_SYS_ISO_CTRL 0x000 +#define R92C_SYS_FUNC_EN 0x002 +#define R92C_APS_FSMCO 0x004 +#define R92C_SYS_CLKR 0x008 +#define R92C_AFE_MISC 0x010 +#define R92C_SPS0_CTRL 0x011 +#define R92C_SPS_OCP_CFG 0x018 +#define R92C_RSV_CTRL 0x01c +#define R92C_RF_CTRL 0x01f +#define R92C_LDOA15_CTRL 0x020 +#define R92C_LDOV12D_CTRL 0x021 +#define R92C_LDOHCI12_CTRL 0x022 +#define R92C_LPLDO_CTRL 0x023 +#define R92C_AFE_XTAL_CTRL 0x024 +#define R92C_AFE_PLL_CTRL 0x028 +#define R92C_APE_PLL_CTRL_EXT 0x02c +#define R92C_MAC_PHY_CTRL R92C_APE_PLL_CTRL_EXT +#define R92C_EFUSE_CTRL 0x030 +#define R92C_EFUSE_TEST 0x034 +#define R92C_PWR_DATA 0x038 +#define R92C_CAL_TIMER 0x03c +#define R92C_ACLK_MON 0x03e +#define R92C_GPIO_MUXCFG 0x040 +#define R92C_GPIO_IO_SEL 0x042 +#define R92C_MAC_PINMUX_CFG 0x043 +#define R92C_GPIO_PIN_CTRL 0x044 +#define R92C_GPIO_IN 0x044 +#define R92C_GPIO_OUT 0x045 +#define R92C_GPIO_IOSEL 0x046 +#define R92C_GPIO_MOD 0x047 +#define R92C_GPIO_INTM 0x048 +#define R92C_LEDCFG0 0x04c +#define R92C_LEDCFG1 0x04d +#define R92C_LEDCFG2 0x04e +#define R92C_LEDCFG3 0x04f +#define R92C_FSIMR 0x050 +#define R92C_FSISR 0x054 +#define R92C_HSIMR 0x058 +#define R92C_HSISR 0x05c +#define R92C_MULTI_FUNC_CTRL 0x068 +#define R92C_LDO_SWR_CTRL 0x07c +#define R92C_MCUFWDL 0x080 +#define R92C_HMEBOX_EXT(idx) (0x088 + (idx) * 2) +#define R92C_EFUSE_ACCESS 0x0cf +#define R92C_BIST_SCAN 0x0d0 +#define R92C_BIST_RPT 0x0d4 +#define R92C_BIST_ROM_RPT 0x0d8 +#define R92C_HPON_FSM 0x0ec +#define R92C_SYS_CFG 0x0f0 +#define R92C_TYPE_ID 0x0fc +/* MAC General Configuration. */ +#define R92C_CR 0x100 +#define R92C_MSR 0x102 +#define R92C_PBP 0x104 +#define R92C_TRXDMA_CTRL 0x10c +#define R92C_TRXFF_BNDY 0x114 +#define R92C_TRXFF_STATUS 0x118 +#define R92C_RXFF_PTR 0x11c +#define R92C_HIMR 0x120 +#define R92C_HISR 0x124 +#define R92C_HIMRE 0x128 +#define R92C_HISRE 0x12c +#define R92C_CPWM 0x12f +#define R92C_FWIMR 0x130 +#define R92C_FWISR 0x134 +#define R92C_PKTBUF_DBG_CTRL 0x140 +#define R92C_PKTBUF_DBG_DATA_L 0x144 +#define R92C_PKTBUF_DBG_DATA_H 0x148 +#define R92C_TC0_CTRL(i) (0x150 + (i) * 4) +#define R92C_TCUNIT_BASE 0x164 +#define R92C_MBIST_START 0x174 +#define R92C_MBIST_DONE 0x178 +#define R92C_MBIST_FAIL 0x17c +#define R92C_C2H_EVT_MSG 0x1a0 +#define R92C_C2H_EVT_CLEAR 0x1af +#define R92C_C2H_EVT_MSG_TEST 0x1b8 +#define R92C_MCUTST_1 0x1c0 +#define R92C_FMETHR 0x1c8 +#define R92C_HMETFR 0x1cc +#define R92C_HMEBOX(idx) (0x1d0 + (idx) * 4) +#define R92C_LLT_INIT 0x1e0 +#define R92C_BB_ACCESS_CTRL 0x1e8 +#define R92C_BB_ACCESS_DATA 0x1ec +/* Tx DMA Configuration. */ +#define R92C_RQPN 0x200 +#define R92C_FIFOPAGE 0x204 +#define R92C_TDECTRL 0x208 +#define R92C_TXDMA_OFFSET_CHK 0x20c +#define R92C_TXDMA_STATUS 0x210 +#define R92C_RQPN_NPQ 0x214 +#define R92C_AUTO_LLT 0x224 +/* Rx DMA Configuration. */ +#define R92C_RXDMA_AGG_PG_TH 0x280 +#define R92C_RXPKT_NUM 0x284 +#define R92C_RXDMA_STATUS 0x288 +/* Protocol Configuration. */ +#define R92C_VOQ_INFORMATION 0x400 +#define R92C_VIQ_INFORMATION 0x404 +#define R92C_BEQ_INFORMATION 0x408 +#define R92C_BKQ_INFORMATION 0x40c +#define R92C_MGQ_INFORMATION 0x410 +#define R92C_HGQ_INFORMATION 0x414 +#define R92C_BCNQ_INFORMATION 0x418 +#define R92C_CPU_MGQ_INFORMATION 0x41c +#define R92C_FWHW_TXQ_CTRL 0x420 +#define R92C_HWSEQ_CTRL 0x423 +#define R92C_TXPKTBUF_BCNQ_BDNY 0x424 +#define R92C_TXPKTBUF_MGQ_BDNY 0x425 +#define R92C_SPEC_SIFS 0x428 +#define R92C_RL 0x42a +#define R92C_DARFRC 0x430 +#define R92C_RARFRC 0x438 +#define R92C_RRSR 0x440 +#define R92C_ARFR(i) (0x444 + (i) * 4) +#define R92C_AGGLEN_LMT 0x458 +#define R92C_AMPDU_MIN_SPACE 0x45c +#define R92C_TXPKTBUF_WMAC_LBK_BF_HD 0x45d +#define R92C_FAST_EDCA_CTRL 0x460 +#define R92C_RD_RESP_PKT_TH 0x463 +#define R92C_INIRTS_RATE_SEL 0x480 +#define R92C_INIDATA_RATE_SEL(macid) (0x484 + (macid)) +#define R92C_QUEUE_CTRL 0x4c6 +#define R92C_MAX_AGGR_NUM 0x4ca +#define R92C_BAR_MODE_CTRL 0x4cc +/* EDCA Configuration. */ +#define R92C_EDCA_VO_PARAM 0x500 +#define R92C_EDCA_VI_PARAM 0x504 +#define R92C_EDCA_BE_PARAM 0x508 +#define R92C_EDCA_BK_PARAM 0x50c +#define R92C_BCNTCFG 0x510 +#define R92C_PIFS 0x512 +#define R92C_RDG_PIFS 0x513 +#define R92C_SIFS_CCK 0x514 +#define R92C_SIFS_OFDM 0x516 +#define R92C_AGGR_BREAK_TIME 0x51a +#define R92C_SLOT 0x51b +#define R92C_TX_PTCL_CTRL 0x520 +#define R92C_TXPAUSE 0x522 +#define R92C_DIS_TXREQ_CLR 0x523 +#define R92C_RD_CTRL 0x524 +#define R92C_TBTT_PROHIBIT 0x540 +#define R92C_RD_NAV_NXT 0x544 +#define R92C_NAV_PROT_LEN 0x546 +#define R92C_BCN_CTRL(id) ((id) + 0x550) +/* WARNING: R92C_USTIME_TSF == 0x55c, not 0x551 */ +#define R92C_MBID_NUM 0x552 +#define R92C_DUAL_TSF_RST 0x553 +#define R92C_BCN_INTERVAL(id) (0x554 + (id) * 2) +#define R92C_DRVERLYINT 0x558 +#define R92C_BCNDMATIM 0x559 +#define R92C_ATIMWND 0x55a +#define R92C_USTIME_TSF 0x55c +#define R92C_BCN_MAX_ERR 0x55d +#define R92C_RXTSF_OFFSET_CCK 0x55e +#define R92C_RXTSF_OFFSET_OFDM 0x55f +#define R92C_TSFTR(i) (0x560 + (i) * 8) +#define R92C_PSTIMER 0x580 +#define R92C_TIMER0 0x584 +#define R92C_TIMER1 0x588 +#define R92C_ACMHWCTRL 0x5c0 +#define R92C_ACMRSTCTRL 0x5c1 +#define R92C_ACMAVG 0x5c2 +#define R92C_VO_ADMTIME 0x5c4 +#define R92C_VI_ADMTIME 0x5c6 +#define R92C_BE_ADMTIME 0x5c8 +#define R92C_EDCA_RANDOM_GEN 0x5cc +#define R92C_SCH_TXCMD 0x5d0 +/* WMAC Configuration. */ +#define R92C_APSD_CTRL 0x600 +#define R92C_BWOPMODE 0x603 +#define R92C_TCR 0x604 +#define R92C_RCR 0x608 +#define R92C_RX_PKT_LIMIT 0x60c +#define R92C_RX_DRVINFO_SZ 0x60f +#define R92C_MACID0 0x610 +#define R92C_BSSID0 0x618 +#define R92C_MAR 0x620 +#define R92C_USTIME_EDCA 0x638 +#define R92C_MAC_SPEC_SIFS 0x63a +#define R92C_R2T_SIFS 0x63c +#define R92C_T2T_SIFS 0x63e +#define R92C_ACKTO 0x640 +#define R92C_NAV_UPPER 0x652 +#define R92C_WMAC_TRXPTCL_CTL 0x668 +#define R92C_CAMCMD 0x670 +#define R92C_CAMWRITE 0x674 +#define R92C_CAMREAD 0x678 +#define R92C_CAMDBG 0x67c +#define R92C_SECCFG 0x680 +#define R92C_RXFLTMAP0 0x6a0 +#define R92C_RXFLTMAP1 0x6a2 +#define R92C_RXFLTMAP2 0x6a4 +#define R92C_BCN_PSR_RPT 0x6a8 +#define R92C_MACID1 0x700 +#define R92C_BSSID1 0x708 + + +#define R92C_MACID(id) ((id) == 0 ? R92C_MACID0 : R92C_MACID1) +#define R92C_BSSID(id) ((id) == 0 ? R92C_BSSID0 : R92C_BSSID1) + +/* Bits for R92C_SYS_ISO_CTRL. */ +#define R92C_SYS_ISO_CTRL_MD2PP 0x0001 +#define R92C_SYS_ISO_CTRL_UA2USB 0x0002 +#define R92C_SYS_ISO_CTRL_UD2CORE 0x0004 +#define R92C_SYS_ISO_CTRL_PA2PCIE 0x0008 +#define R92C_SYS_ISO_CTRL_PD2CORE 0x0010 +#define R92C_SYS_ISO_CTRL_IP2MAC 0x0020 +#define R92C_SYS_ISO_CTRL_DIOP 0x0040 +#define R92C_SYS_ISO_CTRL_DIOE 0x0080 +#define R92C_SYS_ISO_CTRL_EB2CORE 0x0100 +#define R92C_SYS_ISO_CTRL_DIOR 0x0200 +#define R92C_SYS_ISO_CTRL_PWC_EV25V 0x4000 +#define R92C_SYS_ISO_CTRL_PWC_EV12V 0x8000 + +/* Bits for R92C_SYS_FUNC_EN. */ +#define R92C_SYS_FUNC_EN_BBRSTB 0x0001 +#define R92C_SYS_FUNC_EN_BB_GLB_RST 0x0002 +#define R92C_SYS_FUNC_EN_USBA 0x0004 +#define R92C_SYS_FUNC_EN_UPLL 0x0008 +#define R92C_SYS_FUNC_EN_USBD 0x0010 +#define R92C_SYS_FUNC_EN_DIO_PCIE 0x0020 +#define R92C_SYS_FUNC_EN_PCIEA 0x0040 +#define R92C_SYS_FUNC_EN_PPLL 0x0080 +#define R92C_SYS_FUNC_EN_PCIED 0x0100 +#define R92C_SYS_FUNC_EN_DIOE 0x0200 +#define R92C_SYS_FUNC_EN_CPUEN 0x0400 +#define R92C_SYS_FUNC_EN_DCORE 0x0800 +#define R92C_SYS_FUNC_EN_ELDR 0x1000 +#define R92C_SYS_FUNC_EN_DIO_RF 0x2000 +#define R92C_SYS_FUNC_EN_HWPDN 0x4000 +#define R92C_SYS_FUNC_EN_MREGEN 0x8000 + +/* Bits for R92C_APS_FSMCO. */ +#define R92C_APS_FSMCO_PFM_LDALL 0x00000001 +#define R92C_APS_FSMCO_PFM_ALDN 0x00000002 +#define R92C_APS_FSMCO_PFM_LDKP 0x00000004 +#define R92C_APS_FSMCO_PFM_WOWL 0x00000008 +#define R92C_APS_FSMCO_PDN_EN 0x00000010 +#define R92C_APS_FSMCO_PDN_PL 0x00000020 +#define R92C_APS_FSMCO_APFM_ONMAC 0x00000100 +#define R92C_APS_FSMCO_APFM_OFF 0x00000200 +#define R92C_APS_FSMCO_APFM_RSM 0x00000400 +#define R92C_APS_FSMCO_AFSM_HSUS 0x00000800 +#define R92C_APS_FSMCO_AFSM_PCIE 0x00001000 +#define R92C_APS_FSMCO_APDM_MAC 0x00002000 +#define R92C_APS_FSMCO_APDM_HOST 0x00004000 +#define R92C_APS_FSMCO_APDM_HPDN 0x00008000 +#define R92C_APS_FSMCO_RDY_MACON 0x00010000 +#define R92C_APS_FSMCO_SUS_HOST 0x00020000 +#define R92C_APS_FSMCO_ROP_ALD 0x00100000 +#define R92C_APS_FSMCO_ROP_PWR 0x00200000 +#define R92C_APS_FSMCO_ROP_SPS 0x00400000 +#define R92C_APS_FSMCO_SOP_MRST 0x02000000 +#define R92C_APS_FSMCO_SOP_FUSE 0x04000000 +#define R92C_APS_FSMCO_SOP_ABG 0x08000000 +#define R92C_APS_FSMCO_SOP_AMB 0x10000000 +#define R92C_APS_FSMCO_SOP_RCK 0x20000000 +#define R92C_APS_FSMCO_SOP_A8M 0x40000000 +#define R92C_APS_FSMCO_XOP_BTCK 0x80000000 + +/* Bits for R92C_SYS_CLKR. */ +#define R92C_SYS_CLKR_ANAD16V_EN 0x00000001 +#define R92C_SYS_CLKR_ANA8M 0x00000002 +#define R92C_SYS_CLKR_MACSLP 0x00000010 +#define R92C_SYS_CLKR_LOADER_EN 0x00000020 +#define R92C_SYS_CLKR_80M_SSC_DIS 0x00000080 +#define R92C_SYS_CLKR_80M_SSC_EN_HO 0x00000100 +#define R92C_SYS_CLKR_PHY_SSC_RSTB 0x00000200 +#define R92C_SYS_CLKR_SEC_EN 0x00000400 +#define R92C_SYS_CLKR_MAC_EN 0x00000800 +#define R92C_SYS_CLKR_SYS_EN 0x00001000 +#define R92C_SYS_CLKR_RING_EN 0x00002000 + +/* Bits for R92C_RSV_CTRL. */ +#define R92C_RSV_CTRL_WLOCK_ALL 0x01 +#define R92C_RSV_CTRL_WLOCK_00 0x02 +#define R92C_RSV_CTRL_WLOCK_04 0x04 +#define R92C_RSV_CTRL_WLOCK_08 0x08 +#define R92C_RSV_CTRL_WLOCK_40 0x10 +#define R92C_RSV_CTRL_R_DIS_PRST_0 0x20 +#define R92C_RSV_CTRL_R_DIS_PRST_1 0x40 +#define R92C_RSV_CTRL_LOCK_ALL_EN 0x80 + +/* Bits for R92C_RF_CTRL. */ +#define R92C_RF_CTRL_EN 0x01 +#define R92C_RF_CTRL_RSTB 0x02 +#define R92C_RF_CTRL_SDMRSTB 0x04 + +/* Bits for R92C_LDOA15_CTRL. */ +#define R92C_LDOA15_CTRL_EN 0x01 +#define R92C_LDOA15_CTRL_STBY 0x02 +#define R92C_LDOA15_CTRL_OBUF 0x04 +#define R92C_LDOA15_CTRL_REG_VOS 0x08 + +/* Bits for R92C_LDOV12D_CTRL. */ +#define R92C_LDOV12D_CTRL_LDV12_EN 0x01 + +/* Bits for R92C_LPLDO_CTRL. */ +#define R92C_LPLDO_CTRL_SLEEP 0x10 + +/* Bits for R92C_AFE_XTAL_CTRL. */ +#define R92C_AFE_XTAL_CTRL_ADDR_M 0x007ff800 +#define R92C_AFE_XTAL_CTRL_ADDR_S 11 + +/* Bits for R92C_AFE_PLL_CTRL. */ +#define R92C_AFE_PLL_CTRL_EN 0x0001 +#define R92C_AFE_PLL_CTRL_320_EN 0x0002 +#define R92C_AFE_PLL_CTRL_FREF_SEL 0x0004 +#define R92C_AFE_PLL_CTRL_EDGE_SEL 0x0008 +#define R92C_AFE_PLL_CTRL_WDOGB 0x0010 +#define R92C_AFE_PLL_CTRL_LPFEN 0x0020 + +/* Bits for R92C_EFUSE_CTRL. */ +#define R92C_EFUSE_CTRL_DATA_M 0x000000ff +#define R92C_EFUSE_CTRL_DATA_S 0 +#define R92C_EFUSE_CTRL_ADDR_M 0x0003ff00 +#define R92C_EFUSE_CTRL_ADDR_S 8 +#define R92C_EFUSE_CTRL_VALID 0x80000000 + +/* Bits for R92C_GPIO_MUXCFG. */ +#define R92C_GPIO_MUXCFG_ENBT 0x0020 + +/* Bits for R92C_LEDCFG0. */ +#define R92C_LEDCFG0_DIS 0x08 + +/* Bits for R92C_LEDCFG1. */ +#define R92C_LEDCFG1_DIS 0x80 + +/* Bits for R92C_MULTI_FUNC_CTRL. */ +#define R92C_MULTI_BT_FUNC_EN 0x00040000 + +/* Bits for R92C_MCUFWDL. */ +#define R92C_MCUFWDL_EN 0x00000001 +#define R92C_MCUFWDL_RDY 0x00000002 +#define R92C_MCUFWDL_CHKSUM_RPT 0x00000004 +#define R92C_MCUFWDL_MACINI_RDY 0x00000008 +#define R92C_MCUFWDL_BBINI_RDY 0x00000010 +#define R92C_MCUFWDL_RFINI_RDY 0x00000020 +#define R92C_MCUFWDL_WINTINI_RDY 0x00000040 +#define R92C_MCUFWDL_RAM_DL_SEL 0x00000080 /* 1: RAM, 0: ROM */ +#define R92C_MCUFWDL_PAGE_M 0x00070000 +#define R92C_MCUFWDL_PAGE_S 16 +#define R92C_MCUFWDL_ROM_DLEN 0x00080000 +#define R92C_MCUFWDL_CPRST 0x00800000 + +/* Bits for R92C_EFUSE_ACCESS. */ +#define R92C_EFUSE_ACCESS_OFF 0x00 +#define R92C_EFUSE_ACCESS_ON 0x69 + +/* Bits for R92C_HPON_FSM. */ +#define R92C_HPON_FSM_CHIP_BONDING_ID_S 22 +#define R92C_HPON_FSM_CHIP_BONDING_ID_M 0x00c00000 +#define R92C_HPON_FSM_CHIP_BONDING_ID_92C_1T2R 1 + +/* Bits for R92C_SYS_CFG. */ +#define R92C_SYS_CFG_XCLK_VLD 0x00000001 +#define R92C_SYS_CFG_ACLK_VLD 0x00000002 +#define R92C_SYS_CFG_UCLK_VLD 0x00000004 +#define R92C_SYS_CFG_PCLK_VLD 0x00000008 +#define R92C_SYS_CFG_PCIRSTB 0x00000010 +#define R92C_SYS_CFG_V15_VLD 0x00000020 +#define R92C_SYS_CFG_TRP_B15V_EN 0x00000080 +#define R92C_SYS_CFG_SIC_IDLE 0x00000100 +#define R92C_SYS_CFG_BD_MAC2 0x00000200 +#define R92C_SYS_CFG_BD_MAC1 0x00000400 +#define R92C_SYS_CFG_IC_MACPHY_MODE 0x00000800 +#define R92C_SYS_CFG_CHIP_VER_RTL_M 0x0000f000 +#define R92C_SYS_CFG_CHIP_VER_RTL_S 12 +#define R92C_SYS_CFG_BT_FUNC 0x00010000 +#define R92C_SYS_CFG_VENDOR_UMC 0x00080000 +#define R92C_SYS_CFG_PAD_HWPD_IDN 0x00400000 +#define R92C_SYS_CFG_TRP_VAUX_EN 0x00800000 +#define R92C_SYS_CFG_TRP_BT_EN 0x01000000 +#define R92C_SYS_CFG_BD_PKG_SEL 0x02000000 +#define R92C_SYS_CFG_BD_HCI_SEL 0x04000000 +#define R92C_SYS_CFG_TYPE_92C 0x08000000 + +/* Bits for R92C_CR. */ +#define R92C_CR_HCI_TXDMA_EN 0x0001 +#define R92C_CR_HCI_RXDMA_EN 0x0002 +#define R92C_CR_TXDMA_EN 0x0004 +#define R92C_CR_RXDMA_EN 0x0008 +#define R92C_CR_PROTOCOL_EN 0x0010 +#define R92C_CR_SCHEDULE_EN 0x0020 +#define R92C_CR_MACTXEN 0x0040 +#define R92C_CR_MACRXEN 0x0080 +#define R92C_CR_ENSWBCN 0x0100 +#define R92C_CR_ENSEC 0x0200 +#define R92C_CR_CALTMR_EN 0x0400 + +/* Bits for R92C_MSR. */ +#define R92C_MSR_NOLINK 0x00 +#define R92C_MSR_ADHOC 0x01 +#define R92C_MSR_INFRA 0x02 +#define R92C_MSR_AP 0x03 +#define R92C_MSR_MASK (R92C_MSR_AP) + +/* Bits for R92C_PBP. */ +#define R92C_PBP_PSRX_M 0x0f +#define R92C_PBP_PSRX_S 0 +#define R92C_PBP_PSTX_M 0xf0 +#define R92C_PBP_PSTX_S 4 +#define R92C_PBP_64 0 +#define R92C_PBP_128 1 +#define R92C_PBP_256 2 +#define R92C_PBP_512 3 +#define R92C_PBP_1024 4 + +/* Bits for R92C_TRXDMA_CTRL. */ +#define R92C_TRXDMA_CTRL_RX_SHIFT_EN 0x0002 +#define R92C_TRXDMA_CTRL_RXDMA_AGG_EN 0x0004 +#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_M 0x0030 +#define R92C_TRXDMA_CTRL_TXDMA_VOQ_MAP_S 4 +#define R92C_TRXDMA_CTRL_TXDMA_VIQ_MAP_M 0x00c0 +#define R92C_TRXDMA_CTRL_TXDMA_VIQ_MAP_S 6 +#define R92C_TRXDMA_CTRL_TXDMA_BEQ_MAP_M 0x0300 +#define R92C_TRXDMA_CTRL_TXDMA_BEQ_MAP_S 8 +#define R92C_TRXDMA_CTRL_TXDMA_BKQ_MAP_M 0x0c00 +#define R92C_TRXDMA_CTRL_TXDMA_BKQ_MAP_S 10 +#define R92C_TRXDMA_CTRL_TXDMA_MGQ_MAP_M 0x3000 +#define R92C_TRXDMA_CTRL_TXDMA_MGQ_MAP_S 12 +#define R92C_TRXDMA_CTRL_TXDMA_HIQ_MAP_M 0xc000 +#define R92C_TRXDMA_CTRL_TXDMA_HIQ_MAP_S 14 +#define R92C_TRXDMA_CTRL_QUEUE_LOW 1 +#define R92C_TRXDMA_CTRL_QUEUE_NORMAL 2 +#define R92C_TRXDMA_CTRL_QUEUE_HIGH 3 +#define R92C_TRXDMA_CTRL_QMAP_M 0xfff0 +/* Shortcuts. */ +#define R92C_TRXDMA_CTRL_QMAP_3EP 0xf5b0 +#define R92C_TRXDMA_CTRL_QMAP_HQ_LQ 0xf5f0 +#define R92C_TRXDMA_CTRL_QMAP_HQ_NQ 0xfaf0 +#define R92C_TRXDMA_CTRL_QMAP_LQ 0x5550 +#define R92C_TRXDMA_CTRL_QMAP_NQ 0xaaa0 +#define R92C_TRXDMA_CTRL_QMAP_HQ 0xfff0 + +/* Bits for R92C_C2H_EVT_CLEAR. */ +#define R92C_C2H_EVT_HOST_CLOSE 0x00 +#define R92C_C2H_EVT_FW_CLOSE 0xff + +/* Bits for R92C_LLT_INIT. */ +#define R92C_LLT_INIT_DATA_M 0x000000ff +#define R92C_LLT_INIT_DATA_S 0 +#define R92C_LLT_INIT_ADDR_M 0x0000ff00 +#define R92C_LLT_INIT_ADDR_S 8 +#define R92C_LLT_INIT_OP_M 0xc0000000 +#define R92C_LLT_INIT_OP_S 30 +#define R92C_LLT_INIT_OP_NO_ACTIVE 0 +#define R92C_LLT_INIT_OP_WRITE 1 + +/* Bits for R92C_RQPN. */ +#define R92C_RQPN_HPQ_M 0x000000ff +#define R92C_RQPN_HPQ_S 0 +#define R92C_RQPN_LPQ_M 0x0000ff00 +#define R92C_RQPN_LPQ_S 8 +#define R92C_RQPN_PUBQ_M 0x00ff0000 +#define R92C_RQPN_PUBQ_S 16 +#define R92C_RQPN_LD 0x80000000 + +/* Bits for R92C_TDECTRL. */ +#define R92C_TDECTRL_BLK_DESC_NUM_M 0x000000f0 +#define R92C_TDECTRL_BLK_DESC_NUM_S 4 +#define R92C_TDECTRL_BCN_VALID 0x00010000 + +/* Bits for R92C_TXDMA_OFFSET_CHK. */ +#define R92C_TXDMA_OFFSET_DROP_DATA_EN 0x00000200 + +/* Bits for R92C_AUTO_LLT. */ +#define R92C_AUTO_LLT_INIT 0x00010000 + +/* Bits for R92C_FWHW_TXQ_CTRL. */ +#define R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW 0x80 +#define R92C_FWHW_TXQ_CTRL_REAL_BEACON 0x400000 + +/* Bits for R92C_SPEC_SIFS. */ +#define R92C_SPEC_SIFS_CCK_M 0x00ff +#define R92C_SPEC_SIFS_CCK_S 0 +#define R92C_SPEC_SIFS_OFDM_M 0xff00 +#define R92C_SPEC_SIFS_OFDM_S 8 + +/* Bits for R92C_RL. */ +#define R92C_RL_LRL_M 0x003f +#define R92C_RL_LRL_S 0 +#define R92C_RL_SRL_M 0x3f00 +#define R92C_RL_SRL_S 8 + +/* Size of R92C_DARFRC. */ +#define R92C_DARFRC_SIZE 8 + +/* Bits for R92C_RRSR. */ +#define R92C_RRSR_RATE_BITMAP_M 0x000fffff +#define R92C_RRSR_RATE_BITMAP_S 0 +#define R92C_RRSR_RATE_CCK_ONLY_1M 0xffff1 +#define R92C_RRSR_RATE_ALL 0xfffff +#define R92C_RRSR_RSC_LOWSUBCHNL 0x00200000 +#define R92C_RRSR_RSC_UPSUBCHNL 0x00400000 +#define R92C_RRSR_SHORT 0x00800000 + +/* Bits for R92C_EDCA_XX_PARAM. */ +#define R92C_EDCA_PARAM_AIFS_M 0x000000ff +#define R92C_EDCA_PARAM_AIFS_S 0 +#define R92C_EDCA_PARAM_ECWMIN_M 0x00000f00 +#define R92C_EDCA_PARAM_ECWMIN_S 8 +#define R92C_EDCA_PARAM_ECWMAX_M 0x0000f000 +#define R92C_EDCA_PARAM_ECWMAX_S 12 +#define R92C_EDCA_PARAM_TXOP_M 0xffff0000 +#define R92C_EDCA_PARAM_TXOP_S 16 + +/* Bits for R92C_HWSEQ_CTRL / R92C_TXPAUSE. */ +#define R92C_TX_QUEUE_VO 0x01 +#define R92C_TX_QUEUE_VI 0x02 +#define R92C_TX_QUEUE_BE 0x04 +#define R92C_TX_QUEUE_BK 0x08 +#define R92C_TX_QUEUE_MGT 0x10 +#define R92C_TX_QUEUE_HIGH 0x20 +#define R92C_TX_QUEUE_BCN 0x40 + +/* Shortcuts. */ +#define R92C_TX_QUEUE_AC \ + (R92C_TX_QUEUE_VO | R92C_TX_QUEUE_VI | \ + R92C_TX_QUEUE_BE | R92C_TX_QUEUE_BK) + +#define R92C_TX_QUEUE_ALL \ + (R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | \ + R92C_TX_QUEUE_HIGH | R92C_TX_QUEUE_BCN | 0x80) /* XXX */ + +/* Bits for R92C_BCN_CTRL. */ +#define R92C_BCN_CTRL_EN_MBSSID 0x02 +#define R92C_BCN_CTRL_TXBCN_RPT 0x04 +#define R92C_BCN_CTRL_EN_BCN 0x08 +#define R92C_BCN_CTRL_DIS_TSF_UDT0 0x10 + +/* Bits for R92C_DUAL_TSF_RST. */ +#define R92C_DUAL_TSF_RESET(id) (0x01 << (id)) +#define R92C_DUAL_TSF_RST_TXOK 0x20 + +/* Bits for R92C_ACMHWCTRL. */ +#define R92C_ACMHWCTRL_EN 0x01 +#define R92C_ACMHWCTRL_BE 0x02 +#define R92C_ACMHWCTRL_VI 0x04 +#define R92C_ACMHWCTRL_VO 0x08 +#define R92C_ACMHWCTRL_ACM_MASK 0x0f + +/* Bits for R92C_APSD_CTRL. */ +#define R92C_APSD_CTRL_OFF 0x40 +#define R92C_APSD_CTRL_OFF_STATUS 0x80 + +/* Bits for R92C_BWOPMODE. */ +#define R92C_BWOPMODE_11J 0x01 +#define R92C_BWOPMODE_5G 0x02 +#define R92C_BWOPMODE_20MHZ 0x04 + +/* Bits for R92C_TCR. */ +#define R92C_TCR_TSFRST 0x00000001 +#define R92C_TCR_DIS_GCLK 0x00000002 +#define R92C_TCR_PAD_SEL 0x00000004 +#define R92C_TCR_PWR_ST 0x00000040 +#define R92C_TCR_PWRBIT_OW_EN 0x00000080 +#define R92C_TCR_ACRC 0x00000100 +#define R92C_TCR_CFENDFORM 0x00000200 +#define R92C_TCR_ICV 0x00000400 + +/* Bits for R92C_RCR. */ +#define R92C_RCR_AAP 0x00000001 +#define R92C_RCR_APM 0x00000002 +#define R92C_RCR_AM 0x00000004 +#define R92C_RCR_AB 0x00000008 +#define R92C_RCR_ADD3 0x00000010 +#define R92C_RCR_APWRMGT 0x00000020 +#define R92C_RCR_CBSSID_DATA 0x00000040 +#define R92C_RCR_CBSSID_BCN 0x00000080 +#define R92C_RCR_ACRC32 0x00000100 +#define R92C_RCR_AICV 0x00000200 +#define R92C_RCR_ADF 0x00000800 +#define R92C_RCR_ACF 0x00001000 +#define R92C_RCR_AMF 0x00002000 +#define R92C_RCR_HTC_LOC_CTRL 0x00004000 +#define R92C_RCR_MFBEN 0x00400000 +#define R92C_RCR_LSIGEN 0x00800000 +#define R92C_RCR_ENMBID 0x01000000 +#define R92C_RCR_APP_BA_SSN 0x08000000 +#define R92C_RCR_APP_PHYSTS 0x10000000 +#define R92C_RCR_APP_ICV 0x20000000 +#define R92C_RCR_APP_MIC 0x40000000 +#define R92C_RCR_APPFCS 0x80000000 + +/* Bits for R92C_RX_DRVINFO_SZ. */ +/* XXX other values will not work */ +#define R92C_RX_DRVINFO_SZ_DEF ((RTWN_PHY_STATUS_SIZE) / 8) + +/* Bits for R92C_WMAC_TRXPTCL_CTL. */ +#define R92C_WMAC_TRXPTCL_SHPRE 0x00020000 + +/* Bits for R92C_CAMCMD. */ +#define R92C_CAMCMD_ADDR_M 0x0000ffff +#define R92C_CAMCMD_ADDR_S 0 +#define R92C_CAMCMD_WRITE 0x00010000 +#define R92C_CAMCMD_CLR 0x40000000 +#define R92C_CAMCMD_POLLING 0x80000000 + + +/* + * CAM entries. + */ +#define R92C_CAM_CTL0(entry) ((entry) * 8 + 0) +#define R92C_CAM_CTL1(entry) ((entry) * 8 + 1) +#define R92C_CAM_KEY(entry, i) ((entry) * 8 + 2 + (i)) +#define R92C_CAM_CTL6(entry) ((entry) * 8 + 6) +#define R92C_CAM_CTL7(entry) ((entry) * 8 + 7) + +/* Bits for R92C_CAM_CTL0(i). */ +#define R92C_CAM_KEYID_M 0x00000003 +#define R92C_CAM_KEYID_S 0 +#define R92C_CAM_ALGO_M 0x0000001c +#define R92C_CAM_ALGO_S 2 +#define R92C_CAM_ALGO_NONE 0 +#define R92C_CAM_ALGO_WEP40 1 +#define R92C_CAM_ALGO_TKIP 2 +#define R92C_CAM_ALGO_AES 4 +#define R92C_CAM_ALGO_WEP104 5 +#define R92C_CAM_VALID 0x00008000 +#define R92C_CAM_MACLO_M 0xffff0000 +#define R92C_CAM_MACLO_S 16 + +/* Bits for R92C_SECCFG. */ +#define R92C_SECCFG_TXUCKEY_DEF 0x0001 +#define R92C_SECCFG_RXUCKEY_DEF 0x0002 +#define R92C_SECCFG_TXENC_ENA 0x0004 +#define R92C_SECCFG_RXDEC_ENA 0x0008 +#define R92C_SECCFG_CMP_A2 0x0010 +#define R92C_SECCFG_MC_SRCH_DIS 0x0020 +#define R92C_SECCFG_TXBCKEY_DEF 0x0040 +#define R92C_SECCFG_RXBCKEY_DEF 0x0080 + +/* Bits for R92C_RXFLTMAP*. */ +#define R92C_RXFLTMAP_SUBTYPE(subtype) \ + (1 << ((subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT)) + + +/* + * Baseband registers. + */ +#define R92C_FPGA0_RFMOD 0x800 +#define R92C_FPGA0_TXINFO 0x804 +#define R92C_HSSI_PARAM1(chain) (0x820 + (chain) * 8) +#define R92C_HSSI_PARAM2(chain) (0x824 + (chain) * 8) +#define R92C_TXAGC_RATE18_06(i) (((i) == 0) ? 0xe00 : 0x830) +#define R92C_TXAGC_RATE54_24(i) (((i) == 0) ? 0xe04 : 0x834) +#define R92C_TXAGC_A_CCK1_MCS32 0xe08 +#define R92C_TXAGC_B_CCK1_55_MCS32 0x838 +#define R92C_TXAGC_B_CCK11_A_CCK2_11 0x86c +#define R92C_TXAGC_MCS03_MCS00(i) (((i) == 0) ? 0xe10 : 0x83c) +#define R92C_TXAGC_MCS07_MCS04(i) (((i) == 0) ? 0xe14 : 0x848) +#define R92C_TXAGC_MCS11_MCS08(i) (((i) == 0) ? 0xe18 : 0x84c) +#define R92C_TXAGC_MCS15_MCS12(i) (((i) == 0) ? 0xe1c : 0x868) +#define R92C_LSSI_PARAM(chain) (0x840 + (chain) * 4) +#define R92C_FPGA0_RFIFACEOE(chain) (0x860 + (chain) * 4) +#define R92C_FPGA0_RFIFACESW(idx) (0x870 + (idx) * 4) +#define R92C_FPGA0_RFPARAM(idx) (0x878 + (idx) * 4) +#define R92C_FPGA0_ANAPARAM2 0x884 +#define R92C_LSSI_READBACK(chain) (0x8a0 + (chain) * 4) +#define R92C_HSPI_READBACK(chain) (0x8b8 + (chain) * 4) +#define R92C_FPGA1_RFMOD 0x900 +#define R92C_FPGA1_TXINFO 0x90c +#define R92C_CCK0_SYSTEM 0xa00 +#define R92C_CCK0_AFESETTING 0xa04 +#define R92C_OFDM0_TRXPATHENA 0xc04 +#define R92C_OFDM0_TRMUXPAR 0xc08 +#define R92C_OFDM0_RXIQIMBALANCE(chain) (0xc14 + (chain) * 8) +#define R92C_OFDM0_ECCATHRESHOLD 0xc4c +#define R92C_OFDM0_AGCCORE1(chain) (0xc50 + (chain) * 8) +#define R92C_OFDM0_AGCPARAM1 0xc70 +#define R92C_OFDM0_AGCRSSITABLE 0xc78 +#define R92C_OFDM0_TXIQIMBALANCE(chain) (0xc80 + (chain) * 8) +#define R92C_OFDM0_TXAFE(chain) (0xc94 + (chain) * 8) +#define R92C_OFDM0_RXIQEXTANTA 0xca0 +#define R92C_OFDM0_TXPSEUDONOISEWGT 0xce4 +#define R92C_OFDM1_LSTF 0xd00 + +/* Bits for R92C_FPGA[01]_RFMOD. */ +#define R92C_RFMOD_40MHZ 0x00000001 +#define R92C_RFMOD_JAPAN 0x00000002 +#define R92C_RFMOD_CCK_TXSC 0x00000030 +#define R92C_RFMOD_CCK_EN 0x01000000 +#define R92C_RFMOD_OFDM_EN 0x02000000 + +/* Bits for R92C_HSSI_PARAM1(i). */ +#define R92C_HSSI_PARAM1_PI 0x00000100 + +/* Bits for R92C_HSSI_PARAM2(i). */ +#define R92C_HSSI_PARAM2_CCK_HIPWR 0x00000200 +#define R92C_HSSI_PARAM2_ADDR_LENGTH 0x00000400 +#define R92C_HSSI_PARAM2_DATA_LENGTH 0x00000800 +#define R92C_HSSI_PARAM2_READ_ADDR_M 0x7f800000 +#define R92C_HSSI_PARAM2_READ_ADDR_S 23 +#define R92C_HSSI_PARAM2_READ_EDGE 0x80000000 + +/* Bits for R92C_TXAGC_A_CCK1_MCS32. */ +#define R92C_TXAGC_A_CCK1_M 0x0000ff00 +#define R92C_TXAGC_A_CCK1_S 8 + +/* Bits for R92C_TXAGC_B_CCK11_A_CCK2_11. */ +#define R92C_TXAGC_B_CCK11_M 0x000000ff +#define R92C_TXAGC_B_CCK11_S 0 +#define R92C_TXAGC_A_CCK2_M 0x0000ff00 +#define R92C_TXAGC_A_CCK2_S 8 +#define R92C_TXAGC_A_CCK55_M 0x00ff0000 +#define R92C_TXAGC_A_CCK55_S 16 +#define R92C_TXAGC_A_CCK11_M 0xff000000 +#define R92C_TXAGC_A_CCK11_S 24 + +/* Bits for R92C_TXAGC_B_CCK1_55_MCS32. */ +#define R92C_TXAGC_B_CCK1_M 0x0000ff00 +#define R92C_TXAGC_B_CCK1_S 8 +#define R92C_TXAGC_B_CCK2_M 0x00ff0000 +#define R92C_TXAGC_B_CCK2_S 16 +#define R92C_TXAGC_B_CCK55_M 0xff000000 +#define R92C_TXAGC_B_CCK55_S 24 + +/* Bits for R92C_TXAGC_RATE18_06(x). */ +#define R92C_TXAGC_RATE06_M 0x000000ff +#define R92C_TXAGC_RATE06_S 0 +#define R92C_TXAGC_RATE09_M 0x0000ff00 +#define R92C_TXAGC_RATE09_S 8 +#define R92C_TXAGC_RATE12_M 0x00ff0000 +#define R92C_TXAGC_RATE12_S 16 +#define R92C_TXAGC_RATE18_M 0xff000000 +#define R92C_TXAGC_RATE18_S 24 + +/* Bits for R92C_TXAGC_RATE54_24(x). */ +#define R92C_TXAGC_RATE24_M 0x000000ff +#define R92C_TXAGC_RATE24_S 0 +#define R92C_TXAGC_RATE36_M 0x0000ff00 +#define R92C_TXAGC_RATE36_S 8 +#define R92C_TXAGC_RATE48_M 0x00ff0000 +#define R92C_TXAGC_RATE48_S 16 +#define R92C_TXAGC_RATE54_M 0xff000000 +#define R92C_TXAGC_RATE54_S 24 + +/* Bits for R92C_TXAGC_MCS03_MCS00(x). */ +#define R92C_TXAGC_MCS00_M 0x000000ff +#define R92C_TXAGC_MCS00_S 0 +#define R92C_TXAGC_MCS01_M 0x0000ff00 +#define R92C_TXAGC_MCS01_S 8 +#define R92C_TXAGC_MCS02_M 0x00ff0000 +#define R92C_TXAGC_MCS02_S 16 +#define R92C_TXAGC_MCS03_M 0xff000000 +#define R92C_TXAGC_MCS03_S 24 + +/* Bits for R92C_TXAGC_MCS07_MCS04(x). */ +#define R92C_TXAGC_MCS04_M 0x000000ff +#define R92C_TXAGC_MCS04_S 0 +#define R92C_TXAGC_MCS05_M 0x0000ff00 +#define R92C_TXAGC_MCS05_S 8 +#define R92C_TXAGC_MCS06_M 0x00ff0000 +#define R92C_TXAGC_MCS06_S 16 +#define R92C_TXAGC_MCS07_M 0xff000000 +#define R92C_TXAGC_MCS07_S 24 + +/* Bits for R92C_TXAGC_MCS11_MCS08(x). */ +#define R92C_TXAGC_MCS08_M 0x000000ff +#define R92C_TXAGC_MCS08_S 0 +#define R92C_TXAGC_MCS09_M 0x0000ff00 +#define R92C_TXAGC_MCS09_S 8 +#define R92C_TXAGC_MCS10_M 0x00ff0000 +#define R92C_TXAGC_MCS10_S 16 +#define R92C_TXAGC_MCS11_M 0xff000000 +#define R92C_TXAGC_MCS11_S 24 + +/* Bits for R92C_TXAGC_MCS15_MCS12(x). */ +#define R92C_TXAGC_MCS12_M 0x000000ff +#define R92C_TXAGC_MCS12_S 0 +#define R92C_TXAGC_MCS13_M 0x0000ff00 +#define R92C_TXAGC_MCS13_S 8 +#define R92C_TXAGC_MCS14_M 0x00ff0000 +#define R92C_TXAGC_MCS14_S 16 +#define R92C_TXAGC_MCS15_M 0xff000000 +#define R92C_TXAGC_MCS15_S 24 + +/* Bits for R92C_LSSI_PARAM(i). */ +#define R92C_LSSI_PARAM_DATA_M 0x000fffff +#define R92C_LSSI_PARAM_DATA_S 0 +#define R92C_LSSI_PARAM_ADDR_M 0x03f00000 +#define R92C_LSSI_PARAM_ADDR_S 20 + +/* Bits for R92C_FPGA0_RFIFACEOE(0). */ +#define R92C_FPGA0_RFIFACEOE0_ANT_M 0x00000300 +#define R92C_FPGA0_RFIFACEOE0_ANT_S 8 + +/* Bits for R92C_FPGA0_ANAPARAM2. */ +#define R92C_FPGA0_ANAPARAM2_CBW20 0x00000400 + +/* Bits for R92C_LSSI_READBACK(i). */ +#define R92C_LSSI_READBACK_DATA_M 0x000fffff +#define R92C_LSSI_READBACK_DATA_S 0 + +/* Bits for R92C_CCK0_SYSTEM. */ +#define R92C_CCK0_SYSTEM_CCK_SIDEBAND 0x00000010 + +/* Bits for R92C_OFDM0_AGCCORE1(i). */ +#define R92C_OFDM0_AGCCORE1_GAIN_M 0x0000007f +#define R92C_OFDM0_AGCCORE1_GAIN_S 0 + + +/* + * RF (6052) registers. + */ +#define R92C_RF_AC 0x00 +#define R92C_RF_IQADJ_G(i) (0x01 + (i)) +#define R92C_RF_POW_TRSW 0x05 +#define R92C_RF_GAIN_RX 0x06 +#define R92C_RF_GAIN_TX 0x07 +#define R92C_RF_TXM_IDAC 0x08 +#define R92C_RF_BS_IQGEN 0x0f +#define R92C_RF_MODE1 0x10 +#define R92C_RF_MODE2 0x11 +#define R92C_RF_RX_AGC_HP 0x12 +#define R92C_RF_TX_AGC 0x13 +#define R92C_RF_BIAS 0x14 +#define R92C_RF_IPA 0x15 +#define R92C_RF_POW_ABILITY 0x17 +#define R92C_RF_CHNLBW 0x18 +#define R92C_RF_RX_G1 0x1a +#define R92C_RF_RX_G2 0x1b +#define R92C_RF_RX_BB2 0x1c +#define R92C_RF_RX_BB1 0x1d +#define R92C_RF_RCK1 0x1e +#define R92C_RF_RCK2 0x1f +#define R92C_RF_TX_G(i) (0x20 + (i)) +#define R92C_RF_TX_BB1 0x23 +#define R92C_RF_T_METER 0x24 +#define R92C_RF_SYN_G(i) (0x25 + (i)) +#define R92C_RF_RCK_OS 0x30 +#define R92C_RF_TXPA_G(i) (0x31 + (i)) + +/* Bits for R92C_RF_AC. */ +#define R92C_RF_AC_MODE_M 0x70000 +#define R92C_RF_AC_MODE_S 16 +#define R92C_RF_AC_MODE_STANDBY 1 + +/* Bits for R92C_RF_CHNLBW. */ +#define R92C_RF_CHNLBW_CHNL_M 0x003ff +#define R92C_RF_CHNLBW_CHNL_S 0 +#define R92C_RF_CHNLBW_BW20 0x00400 +#define R92C_RF_CHNLBW_LCSTART 0x08000 + +/* Bits for R92C_RF_T_METER. */ +#define R92C_RF_T_METER_START 0x60 +#define R92C_RF_T_METER_VAL_M 0x1f +#define R92C_RF_T_METER_VAL_S 0 + +#endif /* R92C_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rf.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rf.c new file mode 100644 index 0000000000..439a29b72e --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rf.c @@ -0,0 +1,93 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rf.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + + +uint32_t +r92c_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) +{ + struct r92c_softc *rs = sc->sc_priv; + uint32_t reg[R92C_MAX_CHAINS], val; + + reg[0] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)); + if (chain != 0) + reg[chain] = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain)); + + rtwn_bb_write(sc, R92C_HSSI_PARAM2(0), + reg[0] & ~R92C_HSSI_PARAM2_READ_EDGE); + rtwn_delay(sc, rs->rf_read_delay[0]); + + rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain), + RW(reg[chain], R92C_HSSI_PARAM2_READ_ADDR, addr) | + R92C_HSSI_PARAM2_READ_EDGE); + rtwn_delay(sc, rs->rf_read_delay[1]); + + rtwn_bb_write(sc, R92C_HSSI_PARAM2(0), + reg[0] | R92C_HSSI_PARAM2_READ_EDGE); + rtwn_delay(sc, rs->rf_read_delay[2]); + + if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI) + val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain)); + else + val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain)); + return (MS(val, R92C_LSSI_READBACK_DATA)); +} + +void +r92c_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, + uint32_t val) +{ + rtwn_bb_write(sc, R92C_LSSI_PARAM(chain), + SM(R92C_LSSI_PARAM_ADDR, addr) | + SM(R92C_LSSI_PARAM_DATA, val)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom.c new file mode 100644 index 0000000000..178dd86eda --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom.c @@ -0,0 +1,139 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rom.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + + +static void +r92c_set_chains(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + + if (rs->chip & R92C_CHIP_92C) { + sc->ntxchains = (rs->chip & R92C_CHIP_92C_1T2R) ? 1 : 2; + sc->nrxchains = 2; + } else { + sc->ntxchains = 1; + sc->nrxchains = 1; + } +} + +void +r92c_efuse_postread(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + + /* XXX Weird but this is what the vendor driver does. */ + sc->next_rom_addr = 0x1fa; + (void) rtwn_efuse_read_next(sc, &rs->pa_setting); + RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: PA setting=0x%x\n", __func__, + rs->pa_setting); +} + +void +r92c_parse_rom(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r92c_softc *rs = sc->sc_priv; + struct rtwn_r92c_txpwr *rt = rs->rs_txpwr; + struct r92c_rom *rom = (struct r92c_rom *)buf; + int i, j; + + rs->board_type = MS(rom->rf_opt1, R92C_ROM_RF1_BOARD_TYPE); + rs->regulatory = MS(rom->rf_opt1, R92C_ROM_RF1_REGULATORY); + RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type=%d\n", + __func__, rs->regulatory); + + /* Need to be set before postinit() (but after preinit()). */ + rtwn_r92c_set_name(sc); + r92c_set_chains(sc); + + for (j = 0; j < R92C_GROUP_2G; j++) { + for (i = 0; i < sc->ntxchains; i++) { + rt->cck_tx_pwr[i][j] = rom->cck_tx_pwr[i][j]; + rt->ht40_1s_tx_pwr[i][j] = rom->ht40_1s_tx_pwr[i][j]; + } + + rt->ht40_2s_tx_pwr_diff[0][j] = + MS(rom->ht40_2s_tx_pwr_diff[j], LOW_PART); + rt->ht20_tx_pwr_diff[0][j] = + RTWN_SIGN4TO8(MS(rom->ht20_tx_pwr_diff[j], + LOW_PART)); + rt->ofdm_tx_pwr_diff[0][j] = + MS(rom->ofdm_tx_pwr_diff[j], LOW_PART); + rt->ht40_max_pwr[0][j] = + MS(rom->ht40_max_pwr[j], LOW_PART); + rt->ht20_max_pwr[0][j] = + MS(rom->ht20_max_pwr[j], LOW_PART); + + if (sc->ntxchains > 1) { + rt->ht40_2s_tx_pwr_diff[1][j] = + MS(rom->ht40_2s_tx_pwr_diff[j], HIGH_PART); + rt->ht20_tx_pwr_diff[1][j] = + RTWN_SIGN4TO8(MS(rom->ht20_tx_pwr_diff[j], + HIGH_PART)); + rt->ofdm_tx_pwr_diff[1][j] = + MS(rom->ofdm_tx_pwr_diff[j], HIGH_PART); + rt->ht40_max_pwr[1][j] = + MS(rom->ht40_max_pwr[j], HIGH_PART); + rt->ht20_max_pwr[1][j] = + MS(rom->ht20_max_pwr[j], HIGH_PART); + } + } + + sc->thermal_meter = MS(rom->thermal_meter, R92C_ROM_THERMAL_METER); + if (sc->thermal_meter == R92C_ROM_THERMAL_METER_M) + sc->thermal_meter = 0xff; + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_defs.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_defs.h new file mode 100644 index 0000000000..c17702b1d9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_defs.h @@ -0,0 +1,57 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rom_defs.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92C_ROM_DEFS_H +#define R92C_ROM_DEFS_H + +#define R92C_MAX_CHAINS 2 +#define R92C_GROUP_2G 3 + +#define R92C_EFUSE_MAX_LEN 512 +#define R92C_EFUSE_MAP_LEN 128 + +/* + * Some generic rom parsing macros. + */ +#define RTWN_GET_ROM_VAR(var, def) (((var) != 0xff) ? (var) : (def)) +#define RTWN_SIGN4TO8(val) (((val) & 0x08) ? (val) | 0xf0 : (val)) + +#define LOW_PART_M 0x0f +#define LOW_PART_S 0 +#define HIGH_PART_M 0xf0 +#define HIGH_PART_S 4 + +/* Bits for rf_board_opt (rf_opt1) field. */ +#define R92C_ROM_RF1_REGULATORY_M 0x07 +#define R92C_ROM_RF1_REGULATORY_S 0 +#define R92C_ROM_RF1_BOARD_TYPE_M 0xe0 +#define R92C_ROM_RF1_BOARD_TYPE_S 5 + +/* Generic board types. */ +#define R92C_BOARD_TYPE_DONGLE 0 +#define R92C_BOARD_TYPE_HIGHPA 1 +#define R92C_BOARD_TYPE_MINICARD 2 +#define R92C_BOARD_TYPE_SOLO 3 +#define R92C_BOARD_TYPE_COMBO 4 + +/* Bits for channel_plan field. */ +#define R92C_CHANNEL_PLAN_BY_HW 0x80 + +#endif /* R92C_ROM_DEFS_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_image.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_image.h new file mode 100644 index 0000000000..77253acbd3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rom_image.h @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rom_image.h 320055 2017-06-17 14:39:25Z kevlo $ + */ + +#ifndef R92C_ROM_IMAGE_H +#define R92C_ROM_IMAGE_H + +#include + +/* + * RTL8192CU ROM image. + */ +struct r92c_rom { + uint16_t id; /* 0x8192 */ + uint8_t reserved1[5]; + uint8_t dbg_sel; + uint16_t reserved2; + uint16_t vid; + uint16_t pid; + uint8_t usb_opt; + uint8_t ep_setting; + uint16_t reserved3; + uint8_t usb_phy; + uint8_t reserved4[3]; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint8_t string[61]; /* "Realtek" */ + uint8_t subcustomer_id; + uint8_t cck_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; + uint8_t ht40_1s_tx_pwr[R92C_MAX_CHAINS][R92C_GROUP_2G]; + uint8_t ht40_2s_tx_pwr_diff[R92C_GROUP_2G]; + uint8_t ht20_tx_pwr_diff[R92C_GROUP_2G]; + uint8_t ofdm_tx_pwr_diff[R92C_GROUP_2G]; + uint8_t ht40_max_pwr[R92C_GROUP_2G]; + uint8_t ht20_max_pwr[R92C_GROUP_2G]; + uint8_t channel_plan; + uint8_t tssi[R92C_MAX_CHAINS]; + uint8_t thermal_meter; +#define R92C_ROM_THERMAL_METER_M 0x1f +#define R92C_ROM_THERMAL_METER_S 0 + + uint8_t rf_opt1; + uint8_t rf_opt2; + uint8_t rf_opt3; + uint8_t rf_opt4; + uint8_t reserved5; + uint8_t version; + uint8_t customer_id; +} __packed; + +_Static_assert(sizeof(struct r92c_rom) == R92C_EFUSE_MAP_LEN, + "R92C_EFUSE_MAP_LEN must be equal to sizeof(struct r92c_rom)!"); + +#endif /* R92C_ROM_IMAGE_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx.c new file mode 100644 index 0000000000..072da52e9d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx.c @@ -0,0 +1,147 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rx.c 331043 2018-03-16 01:03:10Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + + +int8_t +r92c_get_rssi_cck(struct rtwn_softc *sc, void *physt) +{ + static const int8_t cckoff[] = { 16, -12, -26, -46 }; + struct r92c_rx_cck *cck = (struct r92c_rx_cck *)physt; + uint8_t rpt; + int8_t rssi; + + if (sc->sc_flags & RTWN_FLAG_CCK_HIPWR) { + rpt = (cck->agc_rpt >> 5) & 0x03; + rssi = (cck->agc_rpt & 0x1f) << 1; + } else { + rpt = (cck->agc_rpt >> 6) & 0x03; + rssi = cck->agc_rpt & 0x3e; + } + rssi = cckoff[rpt] - rssi; + + return (rssi); +} + +int8_t +r92c_get_rssi_ofdm(struct rtwn_softc *sc, void *physt) +{ + struct r92c_rx_phystat *phy = (struct r92c_rx_phystat *)physt; + int rssi; + + /* Get average RSSI. */ + rssi = ((phy->pwdb_all >> 1) & 0x7f) - 110; + + return (rssi); +} + +uint8_t +r92c_rx_radiotap_flags(const void *buf) +{ + const struct r92c_rx_stat *stat = buf; + uint8_t flags, rate; + + if (!(stat->rxdw3 & htole32(R92C_RXDW3_SPLCP))) + return (0); + + rate = MS(le32toh(stat->rxdw3), R92C_RXDW3_RATE); + if (RTWN_RATE_IS_CCK(rate)) + flags = IEEE80211_RADIOTAP_F_SHORTPRE; + else + flags = IEEE80211_RADIOTAP_F_SHORTGI; + return (flags); +} + +void +r92c_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, + const void *desc, const void *physt_ptr) +{ + const struct r92c_rx_stat *stat = desc; + uint32_t rxdw1, rxdw3; + uint8_t rate; + + rxdw1 = le32toh(stat->rxdw1); + rxdw3 = le32toh(stat->rxdw3); + rate = MS(rxdw3, R92C_RXDW3_RATE); + + if (rxdw1 & R92C_RXDW1_AMPDU) + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU; + else if (rxdw1 & R92C_RXDW1_AMPDU_MORE) + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; + if ((rxdw3 & R92C_RXDW3_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0)) + rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; + + if (rxdw3 & R92C_RXDW3_HT40) + rxs->c_width = IEEE80211_RX_FW_40MHZ; + else + rxs->c_width = IEEE80211_RX_FW_20MHZ; + + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_phytype = IEEE80211_RX_FP_11B; + else if (rate < RTWN_RIDX_HT_MCS(0)) + rxs->c_phytype = IEEE80211_RX_FP_11G; + else + rxs->c_phytype = IEEE80211_RX_FP_11NG; + + /* Map HW rate index to 802.11 rate. */ + if (rate < RTWN_RIDX_HT_MCS(0)) { + rxs->c_rate = ridx2rate[rate]; + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_pktflags |= IEEE80211_RX_F_CCK; + else + rxs->c_pktflags |= IEEE80211_RX_F_OFDM; + } else { /* MCS0~15. */ + rxs->c_rate = + IEEE80211_RATE_MCS | (rate - RTWN_RIDX_HT_MCS_SHIFT); + rxs->c_pktflags |= IEEE80211_RX_F_HT; + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx_desc.h new file mode 100644 index 0000000000..3cd4fbed6c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_rx_desc.h @@ -0,0 +1,100 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_rx_desc.h 312315 2017-01-17 00:35:23Z avos $ + */ + +#ifndef R92C_RX_DESC_H +#define R92C_RX_DESC_H + +/* Rx MAC descriptor (common parts / USB). */ +struct r92c_rx_stat { + uint32_t rxdw0; +#define R92C_RXDW0_PKTLEN_M 0x00003fff +#define R92C_RXDW0_PKTLEN_S 0 +#define R92C_RXDW0_CRCERR 0x00004000 +#define R92C_RXDW0_ICVERR 0x00008000 +#define R92C_RXDW0_INFOSZ_M 0x000f0000 +#define R92C_RXDW0_INFOSZ_S 16 +#define R92C_RXDW0_CIPHER_M 0x00700000 +#define R92C_RXDW0_CIPHER_S 20 +#define R92C_RXDW0_QOS 0x00800000 +#define R92C_RXDW0_SHIFT_M 0x03000000 +#define R92C_RXDW0_SHIFT_S 24 +#define R92C_RXDW0_PHYST 0x04000000 +#define R92C_RXDW0_SWDEC 0x08000000 +#define R92C_RXDW0_LS 0x10000000 +#define R92C_RXDW0_FS 0x20000000 +#define R92C_RXDW0_EOR 0x40000000 +#define R92C_RXDW0_OWN 0x80000000 + + uint32_t rxdw1; +#define R92C_RXDW1_MACID_M 0x0000001f +#define R92C_RXDW1_MACID_S 0 +#define R92C_RXDW1_AMSDU 0x00002000 +#define R92C_RXDW1_AMPDU_MORE 0x00004000 +#define R92C_RXDW1_AMPDU 0x00008000 +#define R92C_RXDW1_MC 0x40000000 +#define R92C_RXDW1_BC 0x80000000 + + uint32_t rxdw2; + uint32_t rxdw3; +#define R92C_RXDW3_RATE_M 0x0000003f +#define R92C_RXDW3_RATE_S 0 +#define R92C_RXDW3_HT 0x00000040 +#define R92C_RXDW3_SPLCP 0x00000100 +#define R92C_RXDW3_HT40 0x00000200 +#define R92C_RXDW3_HTC 0x00000400 +#define R92C_RXDW3_BSSID_FIT_M 0x00003000 +#define R92C_RXDW3_BSSID_FIT_S 12 + + uint32_t rxdw4; + uint32_t tsf_low; +} __packed __attribute__((aligned(4))); + +/* Rx PHY CCK descriptor. */ +struct r92c_rx_cck { + uint8_t adc_pwdb[4]; + uint8_t sq_rpt; + uint8_t agc_rpt; +} __packed; + +/* Rx PHY descriptor. */ +struct r92c_rx_phystat { + uint8_t trsw_gain[4]; + uint8_t pwdb_all; + uint8_t cfosho[4]; + uint8_t cfotail[4]; + uint8_t rxevm[2]; + uint8_t rxsnr[4]; + uint8_t pdsnr[2]; + uint8_t csi_current[2]; + uint8_t csi_target[2]; + uint8_t sigevm; + uint8_t max_ex_pwr; + uint8_t phy_byte28; +#define R92C_PHY_BYTE28_ANTSEL 0x01 +#define R92C_PHY_BYTE28_ANTSEL_B 0x02 +#define R92C_PHY_BYTE28_ANT_TRAIN_EN 0x04 +#define R92C_PHY_BYTE28_IDLE_LONG 0x08 +#define R92C_PHY_BYTE28_RXSC_M 0x30 +#define R92C_PHY_BYTE28_RXSC_S 4 +#define R92C_PHY_BYTE28_SGI_EN 0x40 +#define R92C_PHY_BYTE28_EX_INTF_FLG 0x80 +} __packed; + +#endif /* R92C_RX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx.c new file mode 100644 index 0000000000..6969085a00 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx.c @@ -0,0 +1,434 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_tx.c 322988 2017-08-28 22:14:16Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + + +static int +r92c_tx_get_sco(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + if (IEEE80211_IS_CHAN_HT40U(c)) + return (R92C_TXDW4_SCO_SCA); + else + return (R92C_TXDW4_SCO_SCB); +} + +static void +r92c_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + if (ni->ni_chan != IEEE80211_CHAN_ANYC && + IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { + int extc_offset; + + extc_offset = r92c_tx_get_sco(sc, ni->ni_chan); + txd->txdw4 |= htole32(R92C_TXDW4_DATA_BW40); + txd->txdw4 |= htole32(SM(R92C_TXDW4_DATA_SCO, extc_offset)); + } +} + +static void +r92c_tx_protection(struct rtwn_softc *sc, struct r92c_tx_desc *txd, + enum ieee80211_protmode mode, uint8_t ridx) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint8_t rate; + + switch (mode) { + case IEEE80211_PROT_CTSONLY: + txd->txdw4 |= htole32(R92C_TXDW4_CTS2SELF); + break; + case IEEE80211_PROT_RTSCTS: + txd->txdw4 |= htole32(R92C_TXDW4_RTSEN); + break; + default: + break; + } + + if (mode == IEEE80211_PROT_CTSONLY || + mode == IEEE80211_PROT_RTSCTS) { + if (ridx >= RTWN_RIDX_HT_MCS(0)) + rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); + else + rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); + ridx = rate2ridx(rate); + + txd->txdw4 |= htole32(SM(R92C_TXDW4_RTSRATE, ridx)); + /* RTS rate fallback limit (max). */ + txd->txdw5 |= htole32(SM(R92C_TXDW5_RTSRATE_FB_LMT, 0xf)); + + if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && + (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + txd->txdw4 |= htole32(R92C_TXDW4_RTS_SHORT); + } +} + +static void +r92c_tx_raid(struct rtwn_softc *sc, struct r92c_tx_desc *txd, + struct ieee80211_node *ni, int ismcast) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_channel *chan; + enum ieee80211_phymode mode; + uint8_t raid; + + chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ? + ni->ni_chan : ic->ic_curchan; + mode = ieee80211_chan2mode(chan); + + /* NB: group addressed frames are done at 11bg rates for now */ + if (ismcast || !(ni->ni_flags & IEEE80211_NODE_HT)) { + switch (mode) { + case IEEE80211_MODE_11B: + case IEEE80211_MODE_11G: + break; + case IEEE80211_MODE_11NG: + mode = IEEE80211_MODE_11G; + break; + default: + device_printf(sc->sc_dev, "unknown mode(1) %d!\n", + ic->ic_curmode); + return; + } + } + + switch (mode) { + case IEEE80211_MODE_11B: + raid = R92C_RAID_11B; + break; + case IEEE80211_MODE_11G: + if (vap->iv_flags & IEEE80211_F_PUREG) + raid = R92C_RAID_11G; + else + raid = R92C_RAID_11BG; + break; + case IEEE80211_MODE_11NG: + if (vap->iv_flags_ht & IEEE80211_FHT_PUREN) + raid = R92C_RAID_11N; + else + raid = R92C_RAID_11BGN; + break; + default: + device_printf(sc->sc_dev, "unknown mode(2) %d!\n", mode); + return; + } + + txd->txdw1 |= htole32(SM(R92C_TXDW1_RAID, raid)); +} + +/* XXX move to device-independent layer */ +static void +r92c_tx_set_sgi(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + struct ieee80211vap *vap = ni->ni_vap; + + if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) && /* HT20 */ + (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)) + txd->txdw5 |= htole32(R92C_TXDW5_SGI); + else if (ni->ni_chan != IEEE80211_CHAN_ANYC && /* HT40 */ + IEEE80211_IS_CHAN_HT40(ni->ni_chan) && + (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) && + (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40)) + txd->txdw5 |= htole32(R92C_TXDW5_SGI); +} + +void +r92c_tx_enable_ampdu(void *buf, int enable) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + if (enable) + txd->txdw1 |= htole32(R92C_TXDW1_AGGEN); + else + txd->txdw1 |= htole32(R92C_TXDW1_AGGBK); +} + +void +r92c_tx_setup_hwseq(void *buf) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + txd->txdw4 |= htole32(R92C_TXDW4_HWSEQ_EN); +} + +void +r92c_tx_setup_macid(void *buf, int id) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + txd->txdw1 |= htole32(SM(R92C_TXDW1_MACID, id)); +} + +void +r92c_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, void *buf, uint8_t ridx, int maxretry) +{ +#ifndef RTWN_WITHOUT_UCODE + struct r92c_softc *rs = sc->sc_priv; +#endif + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211_frame *wh; + struct r92c_tx_desc *txd; + enum ieee80211_protmode prot; + uint8_t type, tid, qos, qsel; + int hasqos, ismcast, macid; + + wh = mtod(m, struct ieee80211_frame *); + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + hasqos = IEEE80211_QOS_HAS_SEQ(wh); + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + + /* Select TX ring for this frame. */ + if (hasqos) { + qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; + tid = qos & IEEE80211_QOS_TID; + } else { + qos = 0; + tid = 0; + } + + /* Fill Tx descriptor. */ + txd = (struct r92c_tx_desc *)buf; + txd->flags0 |= R92C_FLAGS0_LSG | R92C_FLAGS0_FSG; + if (ismcast) + txd->flags0 |= R92C_FLAGS0_BMCAST; + + if (!ismcast) { + struct rtwn_node *un = RTWN_NODE(ni); + /* Unicast frame, check if an ACK is expected. */ + if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != + IEEE80211_QOS_ACKPOLICY_NOACK) { + txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA); + txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT, + maxretry)); + } + + macid = un->id; + + if (type == IEEE80211_FC0_TYPE_DATA) { + qsel = tid % RTWN_MAX_TID; + + rtwn_r92c_tx_enable_ampdu(sc, buf, + (m->m_flags & M_AMPDU_MPDU) != 0); + if (m->m_flags & M_AMPDU_MPDU) { + txd->txdw2 |= htole32(SM(R92C_TXDW2_AMPDU_DEN, + vap->iv_ampdu_density)); + txd->txdw6 |= htole32(SM(R92C_TXDW6_MAX_AGG, + 0x1f)); /* XXX */ + } + if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { + txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT); + sc->sc_tx_n_active++; +#ifndef RTWN_WITHOUT_UCODE + rs->rs_c2h_pending++; +#endif + } + + if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && + (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + txd->txdw4 |= htole32(R92C_TXDW4_DATA_SHPRE); + + prot = IEEE80211_PROT_NONE; + if (ridx >= RTWN_RIDX_HT_MCS(0)) { + r92c_tx_set_ht40(sc, txd, ni); + r92c_tx_set_sgi(sc, txd, ni); + prot = ic->ic_htprotmode; + } else if (ic->ic_flags & IEEE80211_F_USEPROT) + prot = ic->ic_protmode; + + /* XXX fix last comparison for A-MSDU (in net80211) */ + /* XXX A-MPDU? */ + if (m->m_pkthdr.len + IEEE80211_CRC_LEN > + vap->iv_rtsthreshold && + vap->iv_rtsthreshold != IEEE80211_RTS_MAX) + prot = IEEE80211_PROT_RTSCTS; + + /* NB: checks for ht40 / short bits (set above). */ + if (prot != IEEE80211_PROT_NONE) + r92c_tx_protection(sc, txd, prot, ridx); + } else /* IEEE80211_FC0_TYPE_MGT */ + qsel = R92C_TXDW1_QSEL_MGNT; + } else { + macid = RTWN_MACID_BC; + qsel = R92C_TXDW1_QSEL_MGNT; + } + + txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, qsel)); + + rtwn_r92c_tx_setup_macid(sc, txd, macid); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + /* Data rate fallback limit (max). */ + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f)); + txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, uvp->id)); + r92c_tx_raid(sc, txd, ni, ismcast); + + /* Force this rate if needed. */ + if (sc->sc_ratectl != RTWN_RATECTL_FW) + txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + + if (!hasqos) { + /* Use HW sequence numbering for non-QoS frames. */ + rtwn_r92c_tx_setup_hwseq(sc, txd); + txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, uvp->id)); + } else { + uint16_t seqno; + + if (m->m_flags & M_AMPDU_MPDU) { + seqno = ni->ni_txseqs[tid]; + ni->ni_txseqs[tid]++; + } else + seqno = M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE; + + /* Set sequence number. */ + txd->txdseq = htole16(seqno); + } +} + +void +r92c_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, void *buf, const struct ieee80211_bpf_params *params) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211_frame *wh; + struct r92c_tx_desc *txd; + uint8_t ridx; + int ismcast; + + /* XXX TODO: 11n checks, matching r92c_fill_tx_desc() */ + + wh = mtod(m, struct ieee80211_frame *); + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + ridx = rate2ridx(params->ibp_rate0); + + /* Fill Tx descriptor. */ + txd = (struct r92c_tx_desc *)buf; + txd->flags0 |= R92C_FLAGS0_LSG | R92C_FLAGS0_FSG; + if (ismcast) + txd->flags0 |= R92C_FLAGS0_BMCAST; + + if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) { + txd->txdw5 |= htole32(R92C_TXDW5_RTY_LMT_ENA); + txd->txdw5 |= htole32(SM(R92C_TXDW5_RTY_LMT, + params->ibp_try0)); + } + if (params->ibp_flags & IEEE80211_BPF_RTS) + r92c_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx); + if (params->ibp_flags & IEEE80211_BPF_CTS) + r92c_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx); + + rtwn_r92c_tx_setup_macid(sc, txd, RTWN_MACID_BC); + txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT)); + + /* Set TX rate index. */ + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); + txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f)); + txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, uvp->id)); + txd->txdw4 |= htole32(R92C_TXDW4_DRVRATE); + r92c_tx_raid(sc, txd, ni, ismcast); + + if (!IEEE80211_QOS_HAS_SEQ(wh)) { + /* Use HW sequence numbering for non-QoS frames. */ + rtwn_r92c_tx_setup_hwseq(sc, txd); + txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, uvp->id)); + } else { + /* Set sequence number. */ + txd->txdseq |= htole16(M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE); + } +} + +void +r92c_fill_tx_desc_null(struct rtwn_softc *sc, void *buf, int is11b, + int qos, int id) +{ + struct r92c_tx_desc *txd = (struct r92c_tx_desc *)buf; + + txd->flags0 = R92C_FLAGS0_FSG | R92C_FLAGS0_LSG | R92C_FLAGS0_OWN; + txd->txdw1 = htole32( + SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT)); + + txd->txdw4 = htole32(R92C_TXDW4_DRVRATE); + txd->txdw4 |= htole32(SM(R92C_TXDW4_PORT_ID, id)); + if (is11b) { + txd->txdw5 = htole32(SM(R92C_TXDW5_DATARATE, + RTWN_RIDX_CCK1)); + } else { + txd->txdw5 = htole32(SM(R92C_TXDW5_DATARATE, + RTWN_RIDX_OFDM6)); + } + + if (!qos) { + rtwn_r92c_tx_setup_hwseq(sc, txd); + txd->txdw4 |= htole32(SM(R92C_TXDW4_SEQ_SEL, id)); + } +} + +uint8_t +r92c_tx_radiotap_flags(const void *buf) +{ + const struct r92c_tx_desc *txd = buf; + uint8_t flags; + + flags = 0; + if (txd->txdw4 & htole32(R92C_TXDW4_DATA_SHPRE)) + flags |= IEEE80211_RADIOTAP_F_SHORTPRE; + if (txd->txdw5 & htole32(R92C_TXDW5_SGI)) + flags |= IEEE80211_RADIOTAP_F_SHORTGI; + return (flags); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx_desc.h new file mode 100644 index 0000000000..9c84cc30ce --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_tx_desc.h @@ -0,0 +1,122 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_tx_desc.h 311948 2017-01-11 23:32:40Z avos $ + */ + +#ifndef R92C_TX_DESC_H +#define R92C_TX_DESC_H + +/* Tx MAC descriptor (common part). */ +struct r92c_tx_desc { + uint16_t pktlen; + uint8_t offset; + uint8_t flags0; +#define R92C_FLAGS0_BMCAST 0x01 +#define R92C_FLAGS0_LSG 0x04 +#define R92C_FLAGS0_FSG 0x08 +#define R92C_FLAGS0_OWN 0x80 + + uint32_t txdw1; +#define R92C_TXDW1_MACID_M 0x0000001f +#define R92C_TXDW1_MACID_S 0 +#define R92C_TXDW1_AGGEN 0x00000020 +#define R92C_TXDW1_AGGBK 0x00000040 + +#define R92C_TXDW1_QSEL_M 0x00001f00 +#define R92C_TXDW1_QSEL_S 8 + +#define R92C_TXDW1_QSEL_BE 0x00 /* or 0x03 */ +#define R92C_TXDW1_QSEL_BK 0x01 /* or 0x02 */ +#define R92C_TXDW1_QSEL_VI 0x04 /* or 0x05 */ +#define R92C_TXDW1_QSEL_VO 0x06 /* or 0x07 */ +#define RTWN_MAX_TID 8 + +#define R92C_TXDW1_QSEL_BEACON 0x10 +#define R92C_TXDW1_QSEL_MGNT 0x12 + +#define R92C_TXDW1_RAID_M 0x000f0000 +#define R92C_TXDW1_RAID_S 16 +#define R92C_TXDW1_CIPHER_M 0x00c00000 +#define R92C_TXDW1_CIPHER_S 22 +#define R92C_TXDW1_CIPHER_NONE 0 +#define R92C_TXDW1_CIPHER_RC4 1 +#define R92C_TXDW1_CIPHER_AES 3 +#define R92C_TXDW1_PKTOFF_M 0x7c000000 +#define R92C_TXDW1_PKTOFF_S 26 + + uint32_t txdw2; +#define R92C_TXDW2_CCX_RPT 0x00080000 +#define R92C_TXDW2_AMPDU_DEN_M 0x00700000 +#define R92C_TXDW2_AMPDU_DEN_S 20 + + uint16_t txdw3; + uint16_t txdseq; + + uint32_t txdw4; +#define R92C_TXDW4_RTSRATE_M 0x0000001f +#define R92C_TXDW4_RTSRATE_S 0 +#define R92C_TXDW4_SEQ_SEL_M 0x00000040 +#define R92C_TXDW4_SEQ_SEL_S 6 +#define R92C_TXDW4_HWSEQ_EN 0x00000080 +#define R92C_TXDW4_DRVRATE 0x00000100 +#define R92C_TXDW4_CTS2SELF 0x00000800 +#define R92C_TXDW4_RTSEN 0x00001000 +#define R92C_TXDW4_HWRTSEN 0x00002000 +#define R92C_TXDW4_PORT_ID_M 0x00004000 +#define R92C_TXDW4_PORT_ID_S 14 +#define R92C_TXDW4_DATA_SCO_M 0x00300000 +#define R92C_TXDW4_DATA_SCO_S 20 +#define R92C_TXDW4_SCO_SCA 1 +#define R92C_TXDW4_SCO_SCB 2 +#define R92C_TXDW4_DATA_SHPRE 0x01000000 +#define R92C_TXDW4_DATA_BW40 0x02000000 +#define R92C_TXDW4_RTS_SHORT 0x04000000 +#define R92C_TXDW4_RTS_BW40 0x08000000 +#define R92C_TXDW4_RTS_SCO_M 0x30000000 +#define R92C_TXDW4_RTS_SCO_S 28 + + uint32_t txdw5; +#define R92C_TXDW5_DATARATE_M 0x0000003f +#define R92C_TXDW5_DATARATE_S 0 +#define R92C_TXDW5_SGI 0x00000040 +#define R92C_TXDW5_DATARATE_FB_LMT_M 0x00001f00 +#define R92C_TXDW5_DATARATE_FB_LMT_S 8 +#define R92C_TXDW5_RTSRATE_FB_LMT_M 0x0001e000 +#define R92C_TXDW5_RTSRATE_FB_LMT_S 13 +#define R92C_TXDW5_RTY_LMT_ENA 0x00020000 +#define R92C_TXDW5_RTY_LMT_M 0x00fc0000 +#define R92C_TXDW5_RTY_LMT_S 18 +#define R92C_TXDW5_AGGNUM_M 0xff000000 +#define R92C_TXDW5_AGGNUM_S 24 + + uint32_t txdw6; +#define R92C_TXDW6_MAX_AGG_M 0x0000f800 +#define R92C_TXDW6_MAX_AGG_S 11 +} __packed __attribute__((aligned(4))); + + +/* Rate adaptation modes. */ +#define R92C_RAID_11BGN 0 +#define R92C_RAID_11GN 1 +#define R92C_RAID_11BN 2 +#define R92C_RAID_11N 3 +#define R92C_RAID_11BG 4 +#define R92C_RAID_11G 5 /* "pure" 11g */ +#define R92C_RAID_11B 6 + +#endif /* R92C_TX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_var.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_var.h new file mode 100644 index 0000000000..5e88147409 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/r92c_var.h @@ -0,0 +1,83 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/r92c_var.h 322949 2017-08-27 12:44:56Z avos $ + */ + +#ifndef R92C_VAR_H +#define R92C_VAR_H + +#include + +struct r92c_softc { + uint8_t rs_flags; +#define R92C_FLAG_ASSOCIATED 0x01 + + uint8_t chip; +#define R92C_CHIP_92C 0x01 +#define R92C_CHIP_92C_1T2R 0x02 +#define R92C_CHIP_UMC_A_CUT 0x04 + +#ifndef RTWN_WITHOUT_UCODE + struct callout rs_c2h_report; + int rs_c2h_timeout; + int rs_c2h_pending; + int rs_c2h_paused; +#endif +#define R92C_TX_PAUSED_THRESHOLD 20 + + void *rs_txpwr; + const void *rs_txagc; + + uint8_t board_type; + uint8_t regulatory; + uint8_t crystalcap; + uint8_t pa_setting; + + void (*rs_scan_start)(struct ieee80211com *); + void (*rs_scan_end)(struct ieee80211com *); + + void (*rs_set_bw20)(struct rtwn_softc *, uint8_t); + void (*rs_get_txpower)(struct rtwn_softc *, int, + struct ieee80211_channel *, uint8_t[]); + void (*rs_set_gain)(struct rtwn_softc *, uint8_t); + void (*rs_tx_enable_ampdu)(void *, int); + void (*rs_tx_setup_hwseq)(void *); + void (*rs_tx_setup_macid)(void *, int); + void (*rs_set_name)(struct rtwn_softc *); + + int rf_read_delay[3]; + uint32_t rf_chnlbw[R92C_MAX_CHAINS]; +}; +#define R92C_SOFTC(_sc) ((struct r92c_softc *)((_sc)->sc_priv)) + +#define rtwn_r92c_set_bw20(_sc, _chan) \ + ((R92C_SOFTC(_sc)->rs_set_bw20)((_sc), (_chan))) +#define rtwn_r92c_get_txpower(_sc, _chain, _c, _power) \ + ((R92C_SOFTC(_sc)->rs_get_txpower)((_sc), (_chain), (_c), (_power))) +#define rtwn_r92c_set_gain(_sc, _gain) \ + ((R92C_SOFTC(_sc)->rs_set_gain)((_sc), (_gain))) +#define rtwn_r92c_tx_enable_ampdu(_sc, _buf, _enable) \ + ((R92C_SOFTC(_sc)->rs_tx_enable_ampdu)((_buf), (_enable))) +#define rtwn_r92c_tx_setup_hwseq(_sc, _buf) \ + ((R92C_SOFTC(_sc)->rs_tx_setup_hwseq)((_buf))) +#define rtwn_r92c_tx_setup_macid(_sc, _buf, _id) \ + ((R92C_SOFTC(_sc)->rs_tx_setup_macid)((_buf), (_id))) +#define rtwn_r92c_set_name(_sc) \ + ((R92C_SOFTC(_sc)->rs_set_name)((_sc))) + +#endif /* R92C_VAR_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu.h new file mode 100644 index 0000000000..5534d1c399 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTL8192CU_H +#define RTL8192CU_H + +#include + + +/* + * Global definitions. + */ +#define R92CU_PUBQ_NPAGES 231 +#define R92CU_TX_PAGE_COUNT 248 + + +/* + * Function declarations. + */ +/* r92cu_init.c */ +void r92cu_init_bb(struct rtwn_softc *); +int r92cu_power_on(struct rtwn_softc *); +void r92cu_power_off(struct rtwn_softc *); +void r92cu_init_intr(struct rtwn_softc *); +void r92cu_init_tx_agg(struct rtwn_softc *); +void r92cu_init_rx_agg(struct rtwn_softc *); +void r92cu_post_init(struct rtwn_softc *); + +/* r92cu_led.c */ +void r92cu_set_led(struct rtwn_softc *, int, int); + +/* r92cu_rx.c */ +int r92cu_classify_intr(struct rtwn_softc *, void *, int); +int r92cu_align_rx(int, int); + +/* r92cu_tx.c */ +void r92cu_dump_tx_desc(struct rtwn_softc *, const void *); + +#endif /* RTL8192CU_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_attach.c new file mode 100644 index 0000000000..27d1c4fcb2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_attach.c @@ -0,0 +1,247 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_attach.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + + +static struct rtwn_r92c_txpwr r92c_txpwr; + +void r92cu_attach(struct rtwn_usb_softc *); + +static void +r92cu_postattach(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + struct ieee80211com *ic = &sc->sc_ic; + + if (!(rs->chip & R92C_CHIP_92C) && + rs->board_type == R92C_BOARD_TYPE_HIGHPA) { + sc->agc_prog = &rtl8188ru_agc[0]; + sc->agc_size = nitems(rtl8188ru_agc); + rs->rs_txagc = &rtl8188ru_txagc[0]; + } else { + sc->agc_prog = &rtl8192ce_agc[0]; + sc->agc_size = nitems(rtl8192ce_agc); + rs->rs_txagc = &rtl8192cu_txagc[0]; + } + + if ((rs->chip & (R92C_CHIP_UMC_A_CUT | R92C_CHIP_92C)) == + R92C_CHIP_UMC_A_CUT) { + sc->fwname = "rtwn-rtl8192cfwU"; + } else { + sc->fwname = "rtwn-rtl8192cfwT"; + } + sc->fwsig = 0x88c; + + rs->rs_scan_start = ic->ic_scan_start; + ic->ic_scan_start = r92c_scan_start; + rs->rs_scan_end = ic->ic_scan_end; + ic->ic_scan_end = r92c_scan_end; +} + +static void +r92cu_set_name(struct rtwn_softc *sc) +{ + struct r92c_softc *rs = sc->sc_priv; + + if (!(rs->chip & R92C_CHIP_92C)) { + if (rs->board_type == R92C_BOARD_TYPE_HIGHPA) + sc->name = "RTL8188RU"; + else if (rs->board_type == R92C_BOARD_TYPE_MINICARD) + sc->name = "RTL8188CU-VAU"; + else + sc->name = "RTL8188CUS"; + } else + sc->name = "RTL8192CU"; +} + +static void +r92cu_attach_private(struct rtwn_softc *sc) +{ + struct r92c_softc *rs; + + rs = malloc(sizeof(struct r92c_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); + + rs->rs_txpwr = &r92c_txpwr; + + rs->rs_set_bw20 = r92c_set_bw20; + rs->rs_get_txpower = r92c_get_txpower; + rs->rs_set_gain = r92c_set_gain; + rs->rs_tx_enable_ampdu = r92c_tx_enable_ampdu; + rs->rs_tx_setup_hwseq = r92c_tx_setup_hwseq; + rs->rs_tx_setup_macid = r92c_tx_setup_macid; + rs->rs_set_name = r92cu_set_name; + +#ifndef RTWN_WITHOUT_UCODE + rs->rs_c2h_timeout = hz; + + callout_init_mtx(&rs->rs_c2h_report, &sc->sc_mtx, 0); +#endif + + rs->rf_read_delay[0] = 10; + rs->rf_read_delay[1] = 100; + rs->rf_read_delay[2] = 10; + + sc->sc_priv = rs; +} + +static void +r92cu_adj_devcaps(struct rtwn_softc *sc) +{ + /* XXX Currently broken / incomplete. */ + sc->sc_ic.ic_caps &= ~IEEE80211_C_PMGT; +} + +void +r92cu_attach(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + + /* USB part. */ + uc->uc_align_rx = r92cu_align_rx; + uc->tx_agg_desc_num = 6; + + /* Common part. */ + sc->sc_flags = RTWN_FLAG_CAM_FIXED; + + sc->sc_set_chan = r92c_set_chan; + sc->sc_fill_tx_desc = r92c_fill_tx_desc; + sc->sc_fill_tx_desc_raw = r92c_fill_tx_desc_raw; + sc->sc_fill_tx_desc_null = r92c_fill_tx_desc_null; + sc->sc_dump_tx_desc = r92cu_dump_tx_desc; + sc->sc_tx_radiotap_flags = r92c_tx_radiotap_flags; + sc->sc_rx_radiotap_flags = r92c_rx_radiotap_flags; + sc->sc_get_rx_stats = r92c_get_rx_stats; + sc->sc_get_rssi_cck = r92c_get_rssi_cck; + sc->sc_get_rssi_ofdm = r92c_get_rssi_ofdm; + sc->sc_classify_intr = r92cu_classify_intr; + sc->sc_handle_tx_report = rtwn_nop_softc_uint8_int; + sc->sc_handle_c2h_report = rtwn_nop_softc_uint8_int; + sc->sc_check_frame = rtwn_nop_int_softc_mbuf; + sc->sc_rf_read = r92c_rf_read; + sc->sc_rf_write = r92c_rf_write; + sc->sc_check_condition = r92c_check_condition; + sc->sc_efuse_postread = r92c_efuse_postread; + sc->sc_parse_rom = r92c_parse_rom; + sc->sc_set_led = r92cu_set_led; + sc->sc_power_on = r92cu_power_on; + sc->sc_power_off = r92cu_power_off; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_fw_reset = r92c_fw_reset; + sc->sc_fw_download_enable = r92c_fw_download_enable; +#endif + sc->sc_llt_init = r92c_llt_init; + sc->sc_set_page_size = r92c_set_page_size; + sc->sc_lc_calib = r92c_lc_calib; + sc->sc_iq_calib = r92c_iq_calib; /* XXX TODO */ + sc->sc_read_chipid_vendor = r92c_read_chipid_vendor; + sc->sc_adj_devcaps = r92cu_adj_devcaps; + sc->sc_vap_preattach = rtwn_nop_softc_vap; + sc->sc_postattach = r92cu_postattach; + sc->sc_detach_private = r92c_detach_private; + sc->sc_set_media_status = r92c_joinbss_rpt; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_set_rsvd_page = r92c_set_rsvd_page; + sc->sc_set_pwrmode = r92c_set_pwrmode; + sc->sc_set_rssi = r92c_set_rssi; +#endif + sc->sc_beacon_init = r92c_beacon_init; + sc->sc_beacon_enable = r92c_beacon_enable; + sc->sc_beacon_set_rate = rtwn_nop_void_int; + sc->sc_beacon_select = rtwn_nop_softc_int; + sc->sc_temp_measure = r92c_temp_measure; + sc->sc_temp_read = r92c_temp_read; + sc->sc_init_tx_agg = r92cu_init_tx_agg; + sc->sc_init_rx_agg = r92cu_init_rx_agg; + sc->sc_init_ampdu = r92c_init_ampdu; + sc->sc_init_intr = r92cu_init_intr; + sc->sc_init_edca = r92c_init_edca; + sc->sc_init_bb = r92cu_init_bb; + sc->sc_init_rf = r92c_init_rf; + sc->sc_init_antsel = r92c_init_antsel; + sc->sc_post_init = r92cu_post_init; + sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; + + sc->mac_prog = &rtl8192cu_mac[0]; + sc->mac_size = nitems(rtl8192cu_mac); + sc->bb_prog = &rtl8192cu_bb[0]; + sc->bb_size = nitems(rtl8192cu_bb); + sc->rf_prog = &rtl8192c_rf[0]; + + sc->page_count = R92CU_TX_PAGE_COUNT; + sc->pktbuf_count = R92C_TXPKTBUF_COUNT; + + sc->ackto = 0x40; + sc->npubqpages = R92CU_PUBQ_NPAGES; + sc->page_size = R92C_TX_PAGE_SIZE; + + sc->txdesc_len = sizeof(struct r92cu_tx_desc); + sc->efuse_maxlen = R92C_EFUSE_MAX_LEN; + sc->efuse_maplen = R92C_EFUSE_MAP_LEN; + sc->rx_dma_size = R92C_RX_DMA_BUFFER_SIZE; + + sc->macid_limit = R92C_MACID_MAX + 1; + sc->cam_entry_limit = R92C_CAM_ENTRY_COUNT; + sc->fwsize_limit = R92C_MAX_FW_SIZE; + sc->temp_delta = R92C_CALIB_THRESHOLD; + + sc->bcn_status_reg[0] = R92C_TDECTRL; + sc->bcn_status_reg[1] = R92C_TDECTRL; + sc->rcr = 0; + + r92cu_attach_private(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_init.c new file mode 100644 index 0000000000..954889fd67 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_init.c @@ -0,0 +1,391 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_init.c 311347 2017-01-05 02:04:53Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include +#include + + +void +r92cu_init_bb(struct rtwn_softc *sc) +{ + + /* Enable BB and RF. */ + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_DIO_RF); + + rtwn_write_2(sc, R92C_AFE_PLL_CTRL, 0xdb83); + + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD | + R92C_SYS_FUNC_EN_BB_GLB_RST | R92C_SYS_FUNC_EN_BBRSTB); + + rtwn_write_1(sc, R92C_LDOHCI12_CTRL, 0x0f); + rtwn_write_1(sc, 0x15, 0xe9); + rtwn_write_1(sc, R92C_AFE_XTAL_CTRL + 1, 0x80); + + r92c_init_bb_common(sc); +} + +int +r92cu_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + uint32_t reg; + int ntries; + + /* Wait for autoload done bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_1(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_PFM_ALDN) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip autoload\n"); + return (ETIMEDOUT); + } + + /* Unlock ISO/CLK/Power control register. */ + RTWN_CHK(rtwn_write_1(sc, R92C_RSV_CTRL, 0)); + + /* Move SPS into PWM mode. */ + RTWN_CHK(rtwn_write_1(sc, R92C_SPS0_CTRL, 0x2b)); + + /* just in case if power_off() was not properly executed. */ + rtwn_delay(sc, 100); + + reg = rtwn_read_1(sc, R92C_LDOV12D_CTRL); + if (!(reg & R92C_LDOV12D_CTRL_LDV12_EN)) { + RTWN_CHK(rtwn_write_1(sc, R92C_LDOV12D_CTRL, + reg | R92C_LDOV12D_CTRL_LDV12_EN)); + + rtwn_delay(sc, 100); + + RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, + R92C_SYS_ISO_CTRL_MD2PP, 0)); + } + + /* Auto enable WLAN. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_APFM_ONMAC, 1)); + + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for MAC auto ON\n"); + return (ETIMEDOUT); + } + + /* Enable radio, GPIO and LED functions. */ + RTWN_CHK(rtwn_write_2(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | + R92C_APS_FSMCO_PDN_EN | + R92C_APS_FSMCO_PFM_ALDN)); + + /* Release RF digital isolation. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_SYS_ISO_CTRL, + R92C_SYS_ISO_CTRL_DIOR, 0, 1)); + + /* Initialize MAC. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_APSD_CTRL, + R92C_APSD_CTRL_OFF, 0)); + for (ntries = 0; ntries < 1000; ntries++) { + if (!(rtwn_read_1(sc, R92C_APSD_CTRL) & + R92C_APSD_CTRL_OFF_STATUS)) + break; + rtwn_delay(sc, 50); + } + if (ntries == 1000) { + device_printf(sc->sc_dev, + "timeout waiting for MAC initialization\n"); + return (ETIMEDOUT); + } + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + RTWN_CHK(rtwn_write_1(sc, 0xfe10, 0x19)); + + return (0); +#undef RTWN_CHK +} + +void +r92cu_power_off(struct rtwn_softc *sc) +{ +#ifndef RTWN_WITHOUT_UCODE + struct r92c_softc *rs = sc->sc_priv; +#endif + uint32_t reg; + int error; + + /* Deinit C2H event handler. */ +#ifndef RTWN_WITHOUT_UCODE + callout_stop(&rs->rs_c2h_report); + rs->rs_c2h_paused = 0; + rs->rs_c2h_pending = 0; + rs->rs_c2h_timeout = hz; +#endif + + /* Block all Tx queues. */ + error = rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + if (error == ENXIO) /* hardware gone */ + return; + + /* Disable RF */ + rtwn_rf_write(sc, 0, 0, 0); + + rtwn_write_1(sc, R92C_APSD_CTRL, R92C_APSD_CTRL_OFF); + + /* Reset BB state machine */ + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA | + R92C_SYS_FUNC_EN_BB_GLB_RST); + rtwn_write_1(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_USBD | R92C_SYS_FUNC_EN_USBA); + + /* + * Reset digital sequence + */ +#ifndef RTWN_WITHOUT_UCODE + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RDY) { + /* Reset MCU ready status */ + rtwn_write_1(sc, R92C_MCUFWDL, 0); + + /* If firmware in ram code, do reset */ + r92c_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); + } +#endif + + /* Reset MAC and Enable 8051 */ + rtwn_write_1(sc, R92C_SYS_FUNC_EN + 1, + (R92C_SYS_FUNC_EN_CPUEN | + R92C_SYS_FUNC_EN_ELDR | + R92C_SYS_FUNC_EN_HWPDN) >> 8); + + /* Reset MCU ready status */ + rtwn_write_1(sc, R92C_MCUFWDL, 0); + + /* Disable MAC clock */ + rtwn_write_2(sc, R92C_SYS_CLKR, + R92C_SYS_CLKR_ANAD16V_EN | + R92C_SYS_CLKR_ANA8M | + R92C_SYS_CLKR_LOADER_EN | + R92C_SYS_CLKR_80M_SSC_DIS | + R92C_SYS_CLKR_SYS_EN | + R92C_SYS_CLKR_RING_EN | + 0x4000); + + /* Disable AFE PLL */ + rtwn_write_1(sc, R92C_AFE_PLL_CTRL, 0x80); + + /* Gated AFE DIG_CLOCK */ + rtwn_write_2(sc, R92C_AFE_XTAL_CTRL, 0x880F); + + /* Isolated digital to PON */ + rtwn_write_1(sc, R92C_SYS_ISO_CTRL, + R92C_SYS_ISO_CTRL_MD2PP | + R92C_SYS_ISO_CTRL_PA2PCIE | + R92C_SYS_ISO_CTRL_PD2CORE | + R92C_SYS_ISO_CTRL_IP2MAC | + R92C_SYS_ISO_CTRL_DIOP | + R92C_SYS_ISO_CTRL_DIOE); + + /* + * Pull GPIO PIN to balance level and LED control + */ + /* 1. Disable GPIO[7:0] */ + rtwn_write_2(sc, R92C_GPIO_IOSEL, 0x0000); + + reg = rtwn_read_4(sc, R92C_GPIO_PIN_CTRL) & ~0x0000ff00; + reg |= ((reg << 8) & 0x0000ff00) | 0x00ff0000; + rtwn_write_4(sc, R92C_GPIO_PIN_CTRL, reg); + + /* Disable GPIO[10:8] */ + rtwn_write_1(sc, R92C_MAC_PINMUX_CFG, 0x00); + + reg = rtwn_read_2(sc, R92C_GPIO_IO_SEL) & ~0x00f0; + reg |= (((reg & 0x000f) << 4) | 0x0780); + rtwn_write_2(sc, R92C_GPIO_IO_SEL, reg); + + /* Disable LED0 & 1 */ + rtwn_write_2(sc, R92C_LEDCFG0, 0x8080); + + /* + * Reset digital sequence + */ + /* Disable ELDR clock */ + rtwn_write_2(sc, R92C_SYS_CLKR, + R92C_SYS_CLKR_ANAD16V_EN | + R92C_SYS_CLKR_ANA8M | + R92C_SYS_CLKR_LOADER_EN | + R92C_SYS_CLKR_80M_SSC_DIS | + R92C_SYS_CLKR_SYS_EN | + R92C_SYS_CLKR_RING_EN | + 0x4000); + + /* Isolated ELDR to PON */ + rtwn_write_1(sc, R92C_SYS_ISO_CTRL + 1, + (R92C_SYS_ISO_CTRL_DIOR | + R92C_SYS_ISO_CTRL_PWC_EV12V) >> 8); + + /* + * Disable analog sequence + */ + /* Disable A15 power */ + rtwn_write_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_OBUF); + /* Disable digital core power */ + rtwn_setbits_1(sc, R92C_LDOV12D_CTRL, + R92C_LDOV12D_CTRL_LDV12_EN, 0); + + /* Enter PFM mode */ + rtwn_write_1(sc, R92C_SPS0_CTRL, 0x23); + + /* Set USB suspend */ + rtwn_write_2(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APDM_HOST | + R92C_APS_FSMCO_AFSM_HSUS | + R92C_APS_FSMCO_PFM_ALDN); + + /* Lock ISO/CLK/Power control register. */ + rtwn_write_1(sc, R92C_RSV_CTRL, 0x0E); +} + +void +r92cu_init_intr(struct rtwn_softc *sc) +{ + rtwn_write_4(sc, R92C_HISR, 0xffffffff); + rtwn_write_4(sc, R92C_HIMR, 0xffffffff); +} + +void +r92cu_init_tx_agg(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + uint32_t reg; + + reg = rtwn_read_4(sc, R92C_TDECTRL); + reg = RW(reg, R92C_TDECTRL_BLK_DESC_NUM, uc->tx_agg_desc_num); + rtwn_write_4(sc, R92C_TDECTRL, reg); +} + +void +r92cu_init_rx_agg(struct rtwn_softc *sc) +{ + + /* Rx aggregation (DMA & USB). */ + rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, + R92C_TRXDMA_CTRL_RXDMA_AGG_EN); + rtwn_setbits_1(sc, R92C_USB_SPECIAL_OPTION, 0, + R92C_USB_SPECIAL_OPTION_AGG_EN); + + /* XXX dehardcode */ + rtwn_write_1(sc, R92C_RXDMA_AGG_PG_TH, 48); + rtwn_write_1(sc, R92C_USB_DMA_AGG_TO, 4); + rtwn_write_1(sc, R92C_USB_AGG_TH, 8); + rtwn_write_1(sc, R92C_USB_AGG_TO, 6); +} + +void +r92cu_post_init(struct rtwn_softc *sc) +{ + + /* Perform LO and IQ calibrations. */ + r92c_iq_calib(sc); + /* Perform LC calibration. */ + r92c_lc_calib(sc); + + /* Fix USB interference issue. */ + rtwn_write_1(sc, 0xfe40, 0xe0); + rtwn_write_1(sc, 0xfe41, 0x8d); + rtwn_write_1(sc, 0xfe42, 0x80); + + r92c_pa_bias_init(sc); + + /* Fix for lower temperature. */ + rtwn_write_1(sc, 0x15, 0xe9); + +#ifndef RTWN_WITHOUT_UCODE + if (sc->sc_flags & RTWN_FW_LOADED) { + struct r92c_softc *rs = sc->sc_priv; + + if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { + /* XXX firmware RA does not work yet */ + sc->sc_ratectl = RTWN_RATECTL_NET80211; + } else + sc->sc_ratectl = sc->sc_ratectl_sysctl; + + /* Start C2H event handling. */ + callout_reset(&rs->rs_c2h_report, rs->rs_c2h_timeout, + r92c_handle_c2h_report, sc); + } else +#endif + sc->sc_ratectl = RTWN_RATECTL_NONE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_led.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_led.c new file mode 100644 index 0000000000..ab3f5b17e2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_led.c @@ -0,0 +1,66 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_led.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + + +void +r92cu_set_led(struct rtwn_softc *sc, int led, int on) +{ + uint8_t reg; + + if (led == RTWN_LED_LINK) { + reg = rtwn_read_1(sc, R92C_LEDCFG0) & 0x70; + if (!on) + reg |= R92C_LEDCFG0_DIS; + rtwn_write_1(sc, R92C_LEDCFG0, reg); + sc->ledlink = on; /* Save LED state. */ + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_priv.h new file mode 100644 index 0000000000..b8dd921433 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_priv.h @@ -0,0 +1,322 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_priv.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CU_PRIV_H +#define R92CU_PRIV_H + +#include + + +/* + * MAC initialization values. + */ +static const struct rtwn_mac_prog rtl8192cu_mac[] = { + { 0x420, 0x80 }, { 0x423, 0x00 }, { 0x430, 0x00 }, { 0x431, 0x00 }, + { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 }, + { 0x436, 0x06 }, { 0x437, 0x07 }, { 0x438, 0x00 }, { 0x439, 0x00 }, + { 0x43a, 0x00 }, { 0x43b, 0x01 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, + { 0x43e, 0x06 }, { 0x43f, 0x07 }, { 0x440, 0x5d }, { 0x441, 0x01 }, + { 0x442, 0x00 }, { 0x444, 0x15 }, { 0x445, 0xf0 }, { 0x446, 0x0f }, + { 0x447, 0x00 }, { 0x458, 0x41 }, { 0x459, 0xa8 }, { 0x45a, 0x72 }, + { 0x45b, 0xb9 }, { 0x460, 0x66 }, { 0x461, 0x66 }, { 0x462, 0x08 }, + { 0x463, 0x03 }, { 0x4c8, 0xff }, { 0x4c9, 0x08 }, { 0x4cc, 0xff }, + { 0x4cd, 0xff }, { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, + { 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, + { 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, + { 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, + { 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, + { 0x515, 0x10 }, { 0x516, 0x0a }, { 0x517, 0x10 }, { 0x51a, 0x16 }, + { 0x524, 0x0f }, { 0x525, 0x4f }, { 0x546, 0x40 }, { 0x547, 0x00 }, + { 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55a, 0x02 }, + { 0x55d, 0xff }, { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, + { 0x652, 0x20 }, { 0x63c, 0x0a }, { 0x63d, 0x0e }, { 0x63e, 0x0a }, + { 0x63f, 0x0e }, { 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 }, + { 0x702, 0x65 }, { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, + { 0x70a, 0x65 }, { 0x70b, 0x87 } +}; + + +/* + * Baseband initialization values. + */ +static const uint16_t rtl8192cu_bb_regs0_88ru[] = { + 0x024, 0x028, 0x040, 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, + 0x818, 0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, + 0x83c, 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, + 0x860, 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, + 0x884, 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, + 0x908, 0x90c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, + 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04, + 0xc08, 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, + 0xc2c, 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, + 0xc50, 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70 +}, rtl8192cu_bb_regs0[] = { + 0x024, 0x028, 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, + 0x81c, 0x820, 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, + 0x840, 0x844, 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, + 0x864, 0x868, 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884, + 0x888, 0x88c, 0x890, 0x894, 0x898, 0x89c, 0x900, 0x904, 0x908, + 0x90c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, + 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xc00, 0xc04, 0xc08, + 0xc0c, 0xc10, 0xc14, 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, + 0xc30, 0xc34, 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, + 0xc54, 0xc58, 0xc5c, 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70 +}, rtl8192cu_bb_regs1[] = { + 0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc88 +}, rtl8192cu_bb_regs2[] = { + 0xc8c, 0xc90, 0xc94, 0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcac, + 0xcb0, 0xcb4, 0xcb8, 0xcbc, 0xcc0, 0xcc4, 0xcc8, 0xccc, 0xcd0, + 0xcd4, 0xcd8, 0xcdc, 0xce0, 0xce4, 0xce8, 0xcec, 0xd00 +}, rtl8192cu_bb_regs5_88ru[] = { + 0xe60, 0xe68, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, + 0xe88, 0xe8c, 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xee8, + 0xf14, 0xf4c, 0xf00 +}; + +static const uint32_t rtl8192cu_bb_vals0_88cu[] = { + 0x0011800d, 0x00ffdb83, 0x80040000, 0x00000001, 0x0000fc00, + 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, + 0x01000100, 0x00390004, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00010000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x569a569a, + 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, 0x32323200, + 0x07000700, 0x22004000, 0x00000808, 0x00000000, 0xc0083070, + 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, 0xfffffffe, + 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, + 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, + 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, + 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, + 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, 0x08800000, + 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, + 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, + 0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000, + 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d +}, rtl8192cu_bb_vals0_88ru[] = { + 0x0011800d, 0x00ffdb83, 0x000c0004, 0x80040000, 0x00000001, + 0x0000fc00, 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, + 0x00000000, 0x01000100, 0x00390204, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00010000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x569a569a, 0x001b25a4, 0x66e60230, 0x061f0130, 0x00000000, + 0x32323200, 0x03000300, 0x22004000, 0x00000808, 0x00ffc3f1, + 0xc0083070, 0x000004d5, 0x00000000, 0xccc000c0, 0x00000800, + 0xfffffffe, 0x40302010, 0x00706050, 0x00000000, 0x00000023, + 0x00000000, 0x81121111, 0x00d047c8, 0x80ff000c, 0x8c838300, + 0x2e68120f, 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, + 0x15160000, 0x070b0f12, 0x00000104, 0x00d30000, 0x101fbf00, + 0x00000007, 0x48071d40, 0x03a05611, 0x000000e4, 0x6c6c6c6c, + 0x08800000, 0x40000100, 0x08800000, 0x40000100, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, + 0x49795994, 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, + 0x007f037f, 0x6954342e, 0x43bc0094, 0x6954342f, 0x433c0094, + 0x00000000, 0x5116848b, 0x47c00bff, 0x00000036, 0x2c56000d +}, rtl8192cu_bb_vals0_92ce_92cu[] = { + 0x0011800d, 0x00ffdb83, 0x80040002, 0x00000003, 0x0000fc00, + 0x0000000a, 0x10005388, 0x020c3d10, 0x02200385, 0x00000000, + 0x01000100, 0x00390004, 0x01000100, 0x00390004, 0x27272727, + 0x27272727, 0x27272727, 0x27272727, 0x00010000, 0x00010000, + 0x27272727, 0x27272727, 0x00000000, 0x00000000, 0x569a569a, + 0x0c1b25a4, 0x66e60230, 0x061f0130, 0x27272727, 0x2b2b2b27, + 0x07000700, 0x22184000, 0x08080808, 0x00000000, 0xc0083070, + 0x000004d5, 0x00000000, 0xcc0000c0, 0x00000800, 0xfffffffe, + 0x40302010, 0x00706050, 0x00000000, 0x00000023, 0x00000000, + 0x81121313, 0x00d047c8, 0x80ff000c, 0x8c838300, 0x2e68120f, + 0x9500bb78, 0x11144028, 0x00881117, 0x89140f00, 0x1a1b0000, + 0x090e1317, 0x00000204, 0x00d30000, 0x101fbf00, 0x00000007, + 0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000, + 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x69e9ac44, 0x469652cf, 0x49795994, + 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, + 0x6954341e, 0x43bc0094, 0x6954341e, 0x433c0094, 0x00000000, + 0x5116848b, 0x47c00bff, 0x00000036, 0x2c7f000d +}, rtl8192cu_bb_vals1_88ru[] = { + 0x018610db, 0x0000001f, 0x00b91612, 0x24000090, 0x20f60000, + 0x24000090 +}, rtl8192cu_bb_vals1_92cu[] = { + 0x0186115b, 0x0000001f, 0x00b99612, 0x40000100, 0x20f60000, + 0x40000100 +}, rtl8192cu_bb_vals1_88cu_92ce[] = { + 0x018610db, 0x0000001f, 0x00b91612, 0x40000100, 0x20f60000, + 0x40000100 +}, rtl8192cu_bb_vals2[] = { + 0x20200000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, + 0x00000000, 0x00000080, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, + 0x00766932, 0x00222222, 0x00000000, 0x37644302, 0x2f97d40c, + 0x00080740 +}, rtl8192cu_bb_vals5_88cu[] = { + 0x00000008, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0, + 0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0, + 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0, + 0x001b25a0, 0x6b1b25a0, 0x00000003, 0x00000000, 0x00000300 +}, rtl8192cu_bb_vals5_88ru[] = { + 0x00000010, 0x001b25a4, 0x631b25a0, 0x631b25a0, 0x081b25a0, + 0x081b25a0, 0x081b25a0, 0x081b25a0, 0x631b25a0, 0x081b25a0, + 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x631b25a0, 0x001b25a0, + 0x001b25a0, 0x6b1b25a0, 0x31555448, 0x00000003, 0x00000000, + 0x00000300 +}; + +static const struct rtwn_bb_prog rtl8192cu_bb[] = { + /* RTL8188CE / RTL8188CU. */ + { + nitems(rtl8192cu_bb_regs0), + rtl8192cu_bb_regs0, + rtl8192cu_bb_vals0_88cu, + { R92C_COND_RTL8188CU | R92C_COND_RTL8188CE }, + /* RTL8188RU. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192cu_bb_regs0_88ru), + rtl8192cu_bb_regs0_88ru, + rtl8192cu_bb_vals0_88ru, + { R92C_COND_RTL8188RU }, + /* Others. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192cu_bb_regs0), + rtl8192cu_bb_regs0, + rtl8192cu_bb_vals0_92ce_92cu, + { 0 }, + NULL + } + } + }, + /* RTL8188RU. */ + { + nitems(rtl8192cu_bb_regs1), + rtl8192cu_bb_regs1, + rtl8192cu_bb_vals1_88ru, + { R92C_COND_RTL8188RU }, + /* RTL8192CU. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192cu_bb_regs1), + rtl8192cu_bb_regs1, + rtl8192cu_bb_vals1_92cu, + { R92C_COND_RTL8192CU }, + /* Others. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192cu_bb_regs1), + rtl8192cu_bb_regs1, + rtl8192cu_bb_vals1_88cu_92ce, + { 0 }, + NULL + } + } + }, + { + nitems(rtl8192cu_bb_regs2), + rtl8192cu_bb_regs2, + rtl8192cu_bb_vals2, + { 0 }, + NULL + }, + /* RTL8192CE / RTL8192CU. */ + { + nitems(rtl8192c_bb_regs3), + rtl8192c_bb_regs3, + rtl8192c_bb_vals3_92ce_92cu, + { R92C_COND_RTL8192C }, + /* Others. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192c_bb_regs3), + rtl8192c_bb_regs3, + rtl8192c_bb_vals3_88cu_88ru, + { 0 }, + NULL + } + }, + { + nitems(rtl8192c_bb_regs4), + rtl8192c_bb_regs4, + rtl8192c_bb_vals4, + { 0 }, + NULL + }, + /* RTL8188CE / RTL8188CU. */ + { + nitems(rtl8192c_bb_regs5), + rtl8192c_bb_regs5, + rtl8192cu_bb_vals5_88cu, + { R92C_COND_RTL8188CU | R92C_COND_RTL8188CE }, + /* RTL8188RU. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192cu_bb_regs5_88ru), + rtl8192cu_bb_regs5_88ru, + rtl8192cu_bb_vals5_88ru, + { R92C_COND_RTL8188RU }, + /* Others. */ + &(const struct rtwn_bb_prog){ + nitems(rtl8192c_bb_regs5), + rtl8192c_bb_regs5, + rtl8192c_bb_vals5_92ce_92cu, + { 0 }, + NULL + } + } + } +}; + + +static const uint32_t rtl8188ru_agc_vals[] = { + 0x7b000001, 0x7b010001, 0x7b020001, 0x7b030001, 0x7b040001, + 0x7b050001, 0x7b060001, 0x7b070001, 0x7b080001, 0x7a090001, + 0x790a0001, 0x780b0001, 0x770c0001, 0x760d0001, 0x750e0001, + 0x740f0001, 0x73100001, 0x72110001, 0x71120001, 0x70130001, + 0x6f140001, 0x6e150001, 0x6d160001, 0x6c170001, 0x6b180001, + 0x6a190001, 0x691a0001, 0x681b0001, 0x671c0001, 0x661d0001, + 0x651e0001, 0x641f0001, 0x63200001, 0x62210001, 0x61220001, + 0x60230001, 0x46240001, 0x45250001, 0x44260001, 0x43270001, + 0x42280001, 0x41290001, 0x402a0001, 0x262b0001, 0x252c0001, + 0x242d0001, 0x232e0001, 0x222f0001, 0x21300001, 0x20310001, + 0x06320001, 0x05330001, 0x04340001, 0x03350001, 0x02360001, + 0x01370001, 0x00380001, 0x00390001, 0x003a0001, 0x003b0001, + 0x003c0001, 0x003d0001, 0x003e0001, 0x003f0001, 0x7b400001, + 0x7b410001, 0x7b420001, 0x7b430001, 0x7b440001, 0x7b450001, + 0x7b460001, 0x7b470001, 0x7b480001, 0x7a490001, 0x794a0001, + 0x784b0001, 0x774c0001, 0x764d0001, 0x754e0001, 0x744f0001, + 0x73500001, 0x72510001, 0x71520001, 0x70530001, 0x6f540001, + 0x6e550001, 0x6d560001, 0x6c570001, 0x6b580001, 0x6a590001, + 0x695a0001, 0x685b0001, 0x675c0001, 0x665d0001, 0x655e0001, + 0x645f0001, 0x63600001, 0x62610001, 0x61620001, 0x60630001, + 0x46640001, 0x45650001, 0x44660001, 0x43670001, 0x42680001, + 0x41690001, 0x406a0001, 0x266b0001, 0x256c0001, 0x246d0001, + 0x236e0001, 0x226f0001, 0x21700001, 0x20710001, 0x06720001, + 0x05730001, 0x04740001, 0x03750001, 0x02760001, 0x01770001, + 0x00780001, 0x00790001, 0x007a0001, 0x007b0001, 0x007c0001, + 0x007d0001, 0x007e0001, 0x007f0001, 0x3800001e, 0x3801001e, + 0x3802001e, 0x3803001e, 0x3804001e, 0x3805001e, 0x3806001e, + 0x3807001e, 0x3808001e, 0x3c09001e, 0x3e0a001e, 0x400b001e, + 0x440c001e, 0x480d001e, 0x4c0e001e, 0x500f001e, 0x5210001e, + 0x5611001e, 0x5a12001e, 0x5e13001e, 0x6014001e, 0x6015001e, + 0x6016001e, 0x6217001e, 0x6218001e, 0x6219001e, 0x621a001e, + 0x621b001e, 0x621c001e, 0x621d001e, 0x621e001e, 0x621f001e +}; + +static const struct rtwn_agc_prog rtl8188ru_agc[] = { + { + nitems(rtl8188ru_agc_vals), + rtl8188ru_agc_vals, + { 0 }, + NULL + } +}; + +#endif /* R92CU_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_reg.h new file mode 100644 index 0000000000..17c95f9ed3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_reg.h @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CU_REG_H +#define R92CU_REG_H + +#include + + +/* + * MAC registers. + */ +/* System Configuration. */ +#define R92C_USB_SIE_INTF 0x0e0 + + +/* + * USB registers. + */ +#define R92C_USB_SUSPEND 0xfe10 +#define R92C_USB_INFO 0xfe17 +#define R92C_USB_SPECIAL_OPTION 0xfe55 +#define R92C_USB_HCPWM 0xfe57 +#define R92C_USB_HRPWM 0xfe58 +#define R92C_USB_DMA_AGG_TO 0xfe5b +#define R92C_USB_AGG_TO 0xfe5c +#define R92C_USB_AGG_TH 0xfe5d +#define R92C_USB_VID 0xfe60 +#define R92C_USB_PID 0xfe62 +#define R92C_USB_OPTIONAL 0xfe64 +#define R92C_USB_EP 0xfe65 +#define R92C_USB_PHY 0xfe68 +#define R92C_USB_MAC_ADDR 0xfe70 +#define R92C_USB_STRING 0xfe80 + +/* Bits for R92C_USB_SPECIAL_OPTION. */ +#define R92C_USB_SPECIAL_OPTION_AGG_EN 0x08 +#define R92C_USB_SPECIAL_OPTION_INT_BULK_SEL 0x10 + +/* Bits for R92C_USB_EP. */ +#define R92C_USB_EP_HQ_M 0x000f +#define R92C_USB_EP_HQ_S 0 +#define R92C_USB_EP_NQ_M 0x00f0 +#define R92C_USB_EP_NQ_S 4 +#define R92C_USB_EP_LQ_M 0x0f00 +#define R92C_USB_EP_LQ_S 8 + +#endif /* R92CU_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_rx.c new file mode 100644 index 0000000000..b70531313b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_rx.c @@ -0,0 +1,63 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_rx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + + +int +r92cu_classify_intr(struct rtwn_softc *sc, void *buf, int len) +{ + /* NB: reports are fetched from C2H_MSG register. */ + return (RTWN_RX_DATA); +} + +int +r92cu_align_rx(int totlen, int len) +{ + return (roundup2(totlen, 128)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx.c new file mode 100644 index 0000000000..fdc178b2b9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx.c @@ -0,0 +1,64 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_tx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r92cu_dump_tx_desc(struct rtwn_softc *sc, const void *desc) +{ +#ifdef RTWN_DEBUG + const struct r92cu_tx_desc *txd = desc; + + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT_DESC, + "%s: len %d, off %d, flags0 %02X, dw: 1 %08X, 2 %08X, 3 %04X " + "(seq %04X), 4 %08X, 5 %08X, 6 %08X, sum %04X, pad %04X\n", + __func__, le16toh(txd->pktlen), txd->offset, txd->flags0, + le32toh(txd->txdw1), le32toh(txd->txdw2), le16toh(txd->txdw3), + le16toh(txd->txdseq), le32toh(txd->txdw4), le32toh(txd->txdw5), + le32toh(txd->txdw6), le16toh(txd->txdsum), le16toh(txd->pad)); +#endif +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h new file mode 100644 index 0000000000..78d556f265 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192c/usb/r92cu_tx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R92CU_TX_DESC_H +#define R92CU_TX_DESC_H + +#include + +/* Tx MAC descriptor (USB). */ +struct r92cu_tx_desc { + uint16_t pktlen; + uint8_t offset; + uint8_t flags0; + + uint32_t txdw1; + uint32_t txdw2; + uint16_t txdw3; + uint16_t txdseq; + + uint32_t txdw4; + uint32_t txdw5; + uint32_t txdw6; + + uint16_t txdsum; + uint16_t pad; +} __packed __attribute__((aligned(4))); + +#endif /* R92CU_TX_DESC_H */ \ No newline at end of file diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e.h new file mode 100644 index 0000000000..a3159410c4 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e.h @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef RTL8192E_H +#define RTL8192E_H + +/* + * Global definitions. + */ +#define R92E_PUBQ_NPAGES 222 +#define R92E_TX_PAGE_COUNT 243 + +#define R92E_TX_PAGE_SIZE 256 +#define R92E_RX_DMA_BUFFER_SIZE 0x3d00 + +#define R92E_MAX_FW_SIZE 0x8000 + + +/* + * Function declarations. + */ +/* r92e_attach.c */ +void r92e_detach_private(struct rtwn_softc *); + +/* r92e_chan.c */ +void r92e_set_chan(struct rtwn_softc *, struct ieee80211_channel *); + +/* r92e_fw.c */ +#ifndef RTWN_WITHOUT_UCODE +void r92e_fw_reset(struct rtwn_softc *, int); +void r92e_set_media_status(struct rtwn_softc *, int); +int r92e_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, int); +#endif + +/* r92e_init.c */ +int r92e_llt_init(struct rtwn_softc *); +void r92e_init_bb(struct rtwn_softc *); +void r92e_init_rf(struct rtwn_softc *); +int r92e_power_on(struct rtwn_softc *); +void r92e_power_off(struct rtwn_softc *); + +/* r92e_led.c */ +void r92e_set_led(struct rtwn_softc *, int, int); + +/* r92e_rf.c */ +uint32_t r92e_rf_read(struct rtwn_softc *, int, uint8_t); +void r92e_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); + +/* r92e_rom.c */ +void r92e_parse_rom_common(struct rtwn_softc *, uint8_t *); +void r92e_parse_rom(struct rtwn_softc *, uint8_t *); + +/* r92e_rx.c */ +void r92e_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); +int8_t r92e_get_rssi_cck(struct rtwn_softc *, void *); + +#endif /* RTL8192E_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_chan.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_chan.c new file mode 100644 index 0000000000..20dd9e8816 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_chan.c @@ -0,0 +1,233 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_chan.c 322988 2017-08-28 22:14:16Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include + +static int +r92e_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t chan; + int group; + + chan = rtwn_chan2centieee(c); + if (IEEE80211_IS_CHAN_2GHZ(c)) { + if (chan <= 2) group = 0; + else if (chan <= 5) group = 1; + else if (chan <= 8) group = 2; + else if (chan <= 11) group = 3; + else if (chan <= 14) group = 4; + else { + KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); + return (-1); + } + } else { + KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); + return (-1); + } + + return (group); +} + +static void +r92e_get_txpower(struct rtwn_softc *sc, int chain, struct ieee80211_channel *c, + uint8_t power[RTWN_RIDX_COUNT]) +{ + struct r92e_softc *rs = sc->sc_priv; + int i, ridx, group, max_mcs; + + /* Determine channel group. */ + group = r92e_get_power_group(sc, c); + if (group == -1) { /* shouldn't happen */ + device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); + return; + } + + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); + + /* XXX regulatory */ + /* XXX net80211 regulatory */ + + for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) + power[ridx] = rs->cck_tx_pwr[chain][group]; + for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++) + power[ridx] = rs->ht40_tx_pwr_2g[chain][group]; + + for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) + power[ridx] += rs->ofdm_tx_pwr_diff_2g[chain][0]; + + for (i = 0; i < sc->ntxchains; i++) { + uint8_t min_mcs; + uint8_t pwr_diff; + + if (IEEE80211_IS_CHAN_HT40(c)) + pwr_diff = rs->bw40_tx_pwr_diff_2g[chain][i]; + else + pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i]; + + min_mcs = RTWN_RIDX_HT_MCS(i * 8); + for (ridx = min_mcs; ridx <= max_mcs; ridx++) + power[ridx] += pwr_diff; + + } + + /* Apply max limit. */ + for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } + +#ifdef RTWN_DEBUG + if (sc->sc_debug & RTWN_DEBUG_TXPWR) { + /* Dump per-rate Tx power values. */ + printf("Tx power for chain %d:\n", chain); + for (ridx = RTWN_RIDX_CCK1; ridx < RTWN_RIDX_COUNT; ridx++) + printf("Rate %d = %u\n", ridx, power[ridx]); + } +#endif +} + +static void +r92e_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t power[RTWN_RIDX_COUNT]; + int i; + + for (i = 0; i < sc->ntxchains; i++) { + memset(power, 0, sizeof(power)); + /* Compute per-rate Tx power values. */ + r92e_get_txpower(sc, i, c, power); + /* Write per-rate Tx power values to hardware. */ + r92c_write_txpower(sc, i, power); + } +} + +static void +r92e_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo) +{ + int i; + + rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x100, 0x80); + rtwn_write_1(sc, R12A_DATA_SEC, + prichlo ? R12A_DATA_SEC_PRIM_DOWN_20 : R12A_DATA_SEC_PRIM_UP_20); + + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_40MHZ); + rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ); + + /* Select 40MHz bandwidth. */ + for (i = 0; i < sc->nrxchains; i++) + rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, + R88E_RF_CHNLBW_BW20, 0x400); + + /* Set CCK side band. */ + rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, + R92C_CCK0_SYSTEM_CCK_SIDEBAND, (prichlo ? 0 : 1) << 4); + + rtwn_bb_setbits(sc, R92C_OFDM1_LSTF, 0x0c00, (prichlo ? 1 : 2) << 10); + + rtwn_bb_setbits(sc, R92C_FPGA0_ANAPARAM2, + R92C_FPGA0_ANAPARAM2_CBW20, 0); + + rtwn_bb_setbits(sc, 0x818, 0x0c000000, (prichlo ? 2 : 1) << 26); +} + +static void +r92e_set_bw20(struct rtwn_softc *sc, uint8_t chan) +{ + int i; + + rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x180, 0); + rtwn_write_1(sc, R12A_DATA_SEC, R12A_DATA_SEC_NO_EXT); + + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, R92C_RFMOD_40MHZ, 0); + rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); + + /* Select 20MHz bandwidth. */ + for (i = 0; i < sc->nrxchains; i++) + rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, + R88E_RF_CHNLBW_BW20, 0xc00); + + rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0); +} + +void +r92e_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + struct r92e_softc *rs = sc->sc_priv; + u_int chan; + int i; + + chan = rtwn_chan2centieee(c); + + for (i = 0; i < sc->nrxchains; i++) { + rtwn_rf_write(sc, i, R92C_RF_CHNLBW, + RW(rs->rf_chnlbw[0], R92C_RF_CHNLBW_CHNL, chan)); + } + + if (IEEE80211_IS_CHAN_HT40(c)) + r92e_set_bw40(sc, chan, IEEE80211_IS_CHAN_HT40U(c)); + else + r92e_set_bw20(sc, chan); + + /* Set Tx power for this new channel. */ + r92e_set_txpower(sc, c); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_fw.c new file mode 100644 index 0000000000..1a1249502c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_fw.c @@ -0,0 +1,137 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_fw.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include + +#ifndef RTWN_WITHOUT_UCODE +void +r92e_fw_reset(struct rtwn_softc *sc, int reason) +{ + /* Reset MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_CPUEN, 0, 1); + + /* Enable MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + 0, R92C_SYS_FUNC_EN_CPUEN, 1); +} + +void +r92e_set_media_status(struct rtwn_softc *sc, int macid) +{ + struct r88e_fw_cmd_msrrpt status; + + if (macid & RTWN_MACID_VALID) + status.msrb0 = R88E_MSRRPT_B0_ASSOC; + else + status.msrb0 = R88E_MSRRPT_B0_DISASSOC; + status.macid = (macid & ~RTWN_MACID_VALID); + + if (r88e_fw_cmd(sc, R88E_CMD_MSR_RPT, &status, sizeof(status)) != 0) { + device_printf(sc->sc_dev, "%s: cannot change media status!\n", + __func__); + } +} + +int +r92e_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, int off) +{ + struct r12a_fw_cmd_pwrmode mode; + int error; + + if (off && vap->iv_state == IEEE80211_S_RUN && + (vap->iv_flags & IEEE80211_F_PMGTON)) { + mode.mode = R88E_PWRMODE_LEG; + /* + * TODO: switch to RFOFF state + * (something is missing here - Rx stops with it). + */ +#ifdef RTWN_TODO + mode.pwr_state = R88E_PWRMODE_STATE_RFOFF; +#else + mode.pwr_state = R88E_PWRMODE_STATE_RFON; +#endif + } else { + mode.mode = R88E_PWRMODE_CAM; + mode.pwr_state = R88E_PWRMODE_STATE_ALLON; + } + mode.pwrb1 = + SM(R88E_PWRMODE_B1_SMART_PS, R88E_PWRMODE_B1_LEG_NULLDATA) | + SM(R88E_PWRMODE_B1_RLBM, R88E_PWRMODE_B1_MODE_MIN); + /* XXX ignored */ + mode.bcn_pass = 0; + mode.queue_uapsd = 0; + mode.pwrb5 = 0; + error = r88e_fw_cmd(sc, R88E_CMD_SET_PWRMODE, &mode, sizeof(mode)); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: CMD_SET_PWRMODE was not sent, error %d\n", + __func__, error); + } + + return (error); +} +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_init.c new file mode 100644 index 0000000000..34c86f26b2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_init.c @@ -0,0 +1,385 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_init.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include + +int +r92e_llt_init(struct rtwn_softc *sc) +{ + int ntries, error; + + error = rtwn_setbits_4(sc, R92C_AUTO_LLT, 0, R92C_AUTO_LLT_INIT); + if (error != 0) + return (error); + for (ntries = 0; ntries < 1000; ntries++) { + if (!(rtwn_read_4(sc, R92C_AUTO_LLT) & R92C_AUTO_LLT_INIT)) + return (0); + rtwn_delay(sc, 1); + } + return (ETIMEDOUT); +} + +static void +r92e_crystalcap_write(struct rtwn_softc *sc) +{ + struct r92e_softc *rs = sc->sc_priv; + uint32_t reg; + uint8_t val; + + val = rs->crystalcap & 0x3f; + reg = rtwn_bb_read(sc, R92E_AFE_XTAL_CTRL); + rtwn_bb_write(sc, R92E_AFE_XTAL_CTRL, + RW(reg, R92E_AFE_XTAL_CTRL_ADDR, val | val << 6)); + rtwn_bb_write(sc, R92C_AFE_XTAL_CTRL, 0x000f81fb); +} + +void +r92e_init_bb(struct rtwn_softc *sc) +{ + int i, j; + + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_USBA | R92C_SYS_FUNC_EN_USBD); + + /* Enable BB and RF. */ + rtwn_setbits_2(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST | + R92C_SYS_FUNC_EN_DIO_RF); + + /* PathA RF Power On. */ + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + + /* Write BB initialization values. */ + for (i = 0; i < sc->bb_size; i++) { + const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i]; + + while (!rtwn_check_condition(sc, bb_prog->cond)) { + KASSERT(bb_prog->next != NULL, + ("%s: wrong condition value (i %d)\n", + __func__, i)); + bb_prog = bb_prog->next; + } + + for (j = 0; j < bb_prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "BB: reg 0x%03x, val 0x%08x\n", + bb_prog->reg[j], bb_prog->val[j]); + + rtwn_bb_write(sc, bb_prog->reg[j], bb_prog->val[j]); + rtwn_delay(sc, 1); + } + } + + /* Write AGC values. */ + for (i = 0; i < sc->agc_size; i++) { + const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i]; + + while (!rtwn_check_condition(sc, agc_prog->cond)) { + KASSERT(agc_prog->next != NULL, + ("%s: wrong condition value (2) (i %d)\n", + __func__, i)); + agc_prog = agc_prog->next; + } + + for (j = 0; j < agc_prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "AGC: val 0x%08x\n", agc_prog->val[j]); + + rtwn_bb_write(sc, R92C_OFDM0_AGCRSSITABLE, + agc_prog->val[j]); + rtwn_delay(sc, 1); + } + } + + if (rtwn_bb_read(sc, R92C_HSSI_PARAM2(0)) & R92C_HSSI_PARAM2_CCK_HIPWR) + sc->sc_flags |= RTWN_FLAG_CCK_HIPWR; + + rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x00040022); + rtwn_delay(sc, 1); + rtwn_bb_write(sc, R92C_OFDM0_AGCCORE1(0), 0x00040020); + rtwn_delay(sc, 1); + + r92e_crystalcap_write(sc); +} + +void +r92e_init_rf(struct rtwn_softc *sc) +{ + struct r92e_softc *rs = sc->sc_priv; + uint32_t reg, type; + int i, chain, idx, off; + + for (chain = 0, i = 0; chain < sc->nrxchains; chain++, i++) { + /* Save RF_ENV control type. */ + idx = chain / 2; + off = (chain % 2) * 16; + reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACESW(idx)); + type = (reg >> off) & 0x10; + + /* Set RF_ENV enable. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain), + 0, 0x100000); + rtwn_delay(sc, 1); + /* Set RF_ENV output high. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFIFACEOE(chain), + 0, 0x10); + rtwn_delay(sc, 1); + /* Set address and data lengths of RF registers. */ + rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain), + R92C_HSSI_PARAM2_ADDR_LENGTH, 0); + rtwn_delay(sc, 1); + rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(chain), + R92C_HSSI_PARAM2_DATA_LENGTH, 0); + rtwn_delay(sc, 1); + + /* Write RF initialization values for this chain. */ + i += r92c_init_rf_chain(sc, &sc->rf_prog[i], chain); + + /* Cache RF register CHNLBW. */ + rs->rf_chnlbw[chain] = rtwn_rf_read(sc, chain, R92C_RF_CHNLBW); + } + + /* Turn CCK and OFDM blocks on. */ + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_CCK_EN); + rtwn_bb_setbits(sc, R92C_FPGA0_RFMOD, 0, R92C_RFMOD_OFDM_EN); +} + +static void +r92e_adj_crystal(struct rtwn_softc *sc) +{ + + rtwn_setbits_1(sc, R92C_AFE_PLL_CTRL, R92C_AFE_PLL_CTRL_FREF_SEL, 0); + rtwn_setbits_4(sc, R92E_APE_PLL_CTRL_EXT, 0x00000380, 0); + rtwn_setbits_1(sc, R92C_AFE_PLL_CTRL, 0x40, 0); + rtwn_setbits_4(sc, R92E_APE_PLL_CTRL_EXT, 0x00200000, 0); +} + +int +r92e_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + int ntries; + + if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN) + RTWN_CHK(rtwn_write_1(sc, R92C_LDO_SWR_CTRL, 0xc3)); + else { + RTWN_CHK(rtwn_setbits_4(sc, R92E_LDOV12_CTRL, 0x00100000, + 0x00500000)); + RTWN_CHK(rtwn_write_1(sc, R92C_LDO_SWR_CTRL, 0x83)); + } + + r92e_adj_crystal(sc); + + /* Enable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + /* Disable HWPDN, SW LPS and WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APFM_RSM | R92C_APS_FSMCO_AFSM_HSUS | + R92C_APS_FSMCO_AFSM_PCIE | R92C_APS_FSMCO_APDM_HPDN, 0, 1)); + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip power up\n"); + return (ETIMEDOUT); + } + + /* Release WLON reset. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_RDY_MACON, 2)); + + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_APFM_ONMAC, 1)); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + return (0); +} + +void +r92e_power_off(struct rtwn_softc *sc) +{ + int error, ntries; + + /* Stop Rx. */ + error = rtwn_write_1(sc, R92C_CR, 0); + if (error == ENXIO) /* hardware gone */ + return; + + /* Move card to Low Power state. */ + /* Block all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + + for (ntries = 0; ntries < 5000; ntries++) { + /* Should be zero if no packet is transmitting. */ + if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0) + break; + + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, "%s: failed to block Tx queues\n", + __func__); + return; + } + + /* CCK and OFDM are disabled, and clock are gated. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0); + + rtwn_delay(sc, 1); + + /* Reset whole BB. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); + + /* Reset MAC TRX. */ + rtwn_write_1(sc, R92C_CR, + R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN); + + /* Check if removed later. */ + rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1); + + /* Respond TxOK to scheduler */ + rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK); + + /* Reset MCU. */ + rtwn_write_1(sc, R92C_MCUFWDL, 0); + +#ifndef RTWN_WITHOUT_UCODE + /* Reset MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_CPUEN, 0, 1); + + /* Enable MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01); +#endif + + /* Move card to Disabled state. */ + /* Turn off RF. */ + rtwn_write_1(sc, R92C_RF_CTRL, 0); + + /* Switch DPDT_SEL_P output. */ + rtwn_setbits_1(sc, R92C_LEDCFG2, 0x80, 0); + + /* Turn off MAC by HW state machine */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF, + 1); + + for (ntries = 0; ntries < 5000; ntries++) { + /* Wait until it will be disabled. */ + if ((rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_OFF) == 0) + break; + + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, "%s: could not turn off MAC\n", + __func__); + return; + } + + /* SOP option to disable BG/MB. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0xff, + R92C_APS_FSMCO_SOP_RCK, 3); + + /* Unlock small LDO Register. */ + rtwn_setbits_1(sc, 0xcc, 0, 0x4); + + /* Disable small LDO. */ + rtwn_setbits_1(sc, R92C_SPS0_CTRL, 0x1, 0); + + /* Enable WL suspend. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE, + R92C_APS_FSMCO_AFSM_HSUS, 1); + + /* Enable SW LPS. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_APFM_RSM, 1); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_led.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_led.c new file mode 100644 index 0000000000..18158ca7b3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_led.c @@ -0,0 +1,69 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_led.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +void +r92e_set_led(struct rtwn_softc *sc, int led, int on) +{ + + if (led == RTWN_LED_LINK) { + if (!on) + rtwn_setbits_1(sc, R92C_LEDCFG1, 0, R92C_LEDCFG1_DIS); + else + rtwn_setbits_1(sc, R92C_LEDCFG1, R92C_LEDCFG1_DIS, 0); + sc->ledlink = on; /* Save LED state. */ + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_priv.h new file mode 100644 index 0000000000..f191dd9e8d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_priv.h @@ -0,0 +1,262 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_priv.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92E_PRIV_H +#define R92E_PRIV_H + +/* + * MAC initialization values. + */ +static const struct rtwn_mac_prog rtl8192eu_mac[] = { + { 0x011, 0xeb }, { 0x012, 0x07 }, { 0x014, 0x75 }, { 0x303, 0xa7 }, + { 0x428, 0x0a }, { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x00 }, + { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 }, + { 0x436, 0x07 }, { 0x437, 0x08 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, + { 0x43e, 0x07 }, { 0x43f, 0x08 }, { 0x440, 0x5d }, { 0x441, 0x01 }, + { 0x442, 0x00 }, { 0x444, 0x10 }, { 0x445, 0x00 }, { 0x446, 0x00 }, + { 0x447, 0x00 }, { 0x448, 0x00 }, { 0x449, 0xf0 }, { 0x44a, 0x0f }, + { 0x44b, 0x3e }, { 0x44c, 0x10 }, { 0x44d, 0x00 }, { 0x44e, 0x00 }, + { 0x44f, 0x00 }, { 0x450, 0x00 }, { 0x451, 0xf0 }, { 0x452, 0x0f }, + { 0x453, 0x00 }, { 0x456, 0x5e }, { 0x460, 0x66 }, { 0x461, 0x66 }, + { 0x4c8, 0xff }, { 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff }, + { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, { 0x502, 0x2f }, + { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, { 0x506, 0x5e }, + { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, { 0x50a, 0x5e }, + { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, { 0x50e, 0x00 }, + { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, { 0x516, 0x0a }, + { 0x525, 0x4f }, { 0x540, 0x12 }, { 0x541, 0x64 }, { 0x550, 0x10 }, + { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x50 }, { 0x55d, 0xff }, + { 0x605, 0x30 }, { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x620, 0xff }, + { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, { 0x624, 0xff }, + { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, { 0x638, 0x50 }, + { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, { 0x63f, 0x0e }, + { 0x640, 0x40 }, { 0x642, 0x40 }, { 0x643, 0x00 }, { 0x652, 0xc8 }, + { 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 }, + { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 }, + { 0x70b, 0x87 } +}; + + +/* + * Baseband initialization values. + */ +static const uint16_t rtl8192eu_bb_regs[] = { + 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x81c, 0x820, + 0x824, 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844, + 0x848, 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, 0x864, 0x868, + 0x86c, 0x870, 0x874, 0x878, 0x87c, 0x880, 0x884, 0x888, 0x88c, + 0x890, 0x894, 0x898, 0x900, 0x904, 0x908, 0x90c, 0x910, 0x914, + 0x918, 0x91c, 0x924, 0x928, 0x92c, 0x930, 0x934, 0x938, 0x93c, + 0x940, 0x944, 0x94c, 0xa00, 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, + 0xa18, 0xa1c, 0xa20, 0xa24, 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, + 0xa7c, 0xa80, 0xb38, 0xc00, 0xc04, 0xc08, 0xc0c, 0xc10, 0xc14, + 0xc18, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38, + 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, 0xc5c, + 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c, 0xc80, + 0xc84, 0xc88, 0xc8c, 0xc90, 0xc94, 0xc98, 0xc9c, 0xca0, 0xca4, + 0xca8, 0xcac, 0xcb0, 0xcb4, 0xcb8, 0xcbc, 0xcc0, 0xcc4, 0xcc8, + 0xccc, 0xcd0, 0xcd4, 0xcd8, 0xcdc, 0xce0, 0xce4, 0xce8, 0xcec, + 0xd00, 0xd04, 0xd08, 0xd0c, 0xd10, 0xd14, 0xd18, 0xd1c, 0xd2c, + 0xd30, 0xd34, 0xd38, 0xd3c, 0xd40, 0xd44, 0xd48, 0xd4c, 0xd50, + 0xd54, 0xd58, 0xd5c, 0xd60, 0xd64, 0xd68, 0xd6c, 0xd70, 0xd74, + 0xd78, 0xd80, 0xd84, 0xd88, 0xe00, 0xe04, 0xe08, 0xe10, 0xe14, + 0xe18, 0xe1c, 0xe28, 0xe30, 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, + 0xe48, 0xe4c, 0xe50, 0xe54, 0xe58, 0xe5c, 0xe60, 0xe68, 0xe6c, + 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, 0xed0, + 0xed4, 0xed8, 0xedc, 0xee0, 0xeec, 0xee4, 0xee8, 0xf14, 0xf4c, + 0xf00 +}; + +static const uint32_t rtl8192eu_bb_vals[] = { + 0x80040000, 0x00000003, 0x0000fc00, 0x0000000a, 0x10001331, + 0x020c3d10, 0x02220385, 0x00000000, 0x01000100, 0x00390204, + 0x01000100, 0x00390204, 0x32323232, 0x30303030, 0x30303030, + 0x30303030, 0x00010000, 0x00010000, 0x28282828, 0x28282828, + 0x00000000, 0x00000000, 0x009a009a, 0x01000014, 0x66f60000, + 0x061f0000, 0x30303030, 0x30303030, 0x00000000, 0x55004200, + 0x08080808, 0x00000000, 0xb0000c1c, 0x00000001, 0x00000000, + 0xcc0000c0, 0x00000800, 0xfffffffe, 0x40302010, 0x00000000, + 0x00000023, 0x00000000, 0x81121313, 0x806c0001, 0x00000001, + 0x00000000, 0x00010000, 0x00000001, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000008, 0x00d0c7c8, 0x81ff000c, 0x8c838300, + 0x2e68120f, 0x95009b78, 0x1114d028, 0x00881117, 0x89140f00, + 0x1a1b0000, 0x090e1317, 0x00000204, 0x00d30000, 0x101fff00, + 0x00000007, 0x00000900, 0x225b0606, 0x218075b1, 0x00000000, + 0x48071d40, 0x03a05633, 0x000000e4, 0x6c6c6c6c, 0x08800000, + 0x40000100, 0x08800000, 0x40000100, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x69e9ac47, 0x469652af, 0x49795994, + 0x0a97971c, 0x1f7c403f, 0x000100b7, 0xec020107, 0x007f037f, + 0x00340020, 0x0080801f, 0x00000020, 0x00248492, 0x00000000, + 0x7112848b, 0x47c00bff, 0x00000036, 0x00000600, 0x02013169, + 0x0000001f, 0x00b91612, 0x40000100, 0x21f60000, 0x40000100, + 0xa0e40000, 0x00121820, 0x00000000, 0x00121820, 0x00007f7f, + 0x00000000, 0x000300a0, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x28000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x64b22427, + 0x00766932, 0x00222222, 0x00040000, 0x77644302, 0x2f97d40c, + 0x00080740, 0x00020403, 0x0000907f, 0x20010201, 0xa0633333, + 0x3333bc43, 0x7a8f5b6b, 0x0000007f, 0xcc979975, 0x00000000, + 0x80608000, 0x00000000, 0x00127353, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x6437140a, 0x00000000, 0x00000282, + 0x30032064, 0x4653de68, 0x04518a3c, 0x00002101, 0x2a201c16, + 0x1812362e, 0x322c2220, 0x000e3c24, 0x01081008, 0x00000800, + 0xf0b50000, 0x30303030, 0x30303030, 0x03903030, 0x30303030, + 0x30303030, 0x30303030, 0x30303030, 0x00000000, 0x1000dc1f, + 0x10008c1f, 0x02140102, 0x681604c2, 0x01007c00, 0x01004800, + 0xfb000000, 0x000028d1, 0x1000dc1f, 0x10008c1f, 0x02140102, + 0x28160d05, 0x00000008, 0x0fc05656, 0x03c09696, 0x03c09696, + 0x0c005656, 0x0c005656, 0x0c005656, 0x0c005656, 0x03c09696, + 0x0c005656, 0x03c09696, 0x03c09696, 0x03c09696, 0x03c09696, + 0x0000d6d6, 0x0000d6d6, 0x0fc01616, 0xb0000c1c, 0x00000001, + 0x00000003, 0x00000000, 0x00000300 +}; + +static const struct rtwn_bb_prog rtl8192eu_bb[] = { + { + nitems(rtl8192eu_bb_regs), + rtl8192eu_bb_regs, + rtl8192eu_bb_vals, + { 0 }, + NULL + } +}; + + +static const uint32_t rtl8192eu_agc_vals[] = { + 0xfb000001, 0xfb010001, 0xfb020001, 0xfb030001, 0xfb040001, + 0xfb050001, 0xfa060001, 0xf9070001, 0xf8080001, 0xf7090001, + 0xf60a0001, 0xf50b0001, 0xf40c0001, 0xf30d0001, 0xf20e0001, + 0xf10f0001, 0xf0100001, 0xef110001, 0xee120001, 0xed130001, + 0xec140001, 0xeb150001, 0xea160001, 0xe9170001, 0xe8180001, + 0xe7190001, 0xc81a0001, 0xc71b0001, 0xc61c0001, 0x071d0001, + 0x061e0001, 0x051f0001, 0x04200001, 0x03210001, 0xaa220001, + 0xa9230001, 0xa8240001, 0xa7250001, 0xa6260001, 0x85270001, + 0x84280001, 0x83290001, 0x252a0001, 0x242b0001, 0x232c0001, + 0x222d0001, 0x672e0001, 0x662f0001, 0x65300001, 0x64310001, + 0x63320001, 0x62330001, 0x61340001, 0x45350001, 0x44360001, + 0x43370001, 0x42380001, 0x41390001, 0x403a0001, 0x403b0001, + 0x403c0001, 0x403d0001, 0x403e0001, 0x403f0001, 0xfb400001, + 0xfb410001, 0xfb420001, 0xfb430001, 0xfb440001, 0xfb450001, + 0xfa460001, 0xf9470001, 0xf8480001, 0xf7490001, 0xf64a0001, + 0xf54b0001, 0xf44c0001, 0xf34d0001, 0xf24e0001, 0xf14f0001, + 0xf0500001, 0xef510001, 0xee520001, 0xed530001, 0xec540001, + 0xeb550001, 0xea560001, 0xe9570001, 0xe8580001, 0xe7590001, + 0xe65a0001, 0xe55b0001, 0xe45c0001, 0xe35d0001, 0xe25e0001, + 0xe15f0001, 0x8a600001, 0x89610001, 0x88620001, 0x87630001, + 0x86640001, 0x85650001, 0x84660001, 0x83670001, 0x82680001, + 0x6b690001, 0x6a6a0001, 0x696b0001, 0x686c0001, 0x676d0001, + 0x666e0001, 0x656f0001, 0x64700001, 0x63710001, 0x62720001, + 0x61730001, 0x49740001, 0x48750001, 0x47760001, 0x46770001, + 0x45780001, 0x44790001, 0x437a0001, 0x427b0001, 0x417c0001, + 0x407d0001, 0x407e0001, 0x407f0001 +}; + +static const struct rtwn_agc_prog rtl8192eu_agc[] = { + { + nitems(rtl8192eu_agc_vals), + rtl8192eu_agc_vals, + { 0 }, + NULL + } +}; + +/* + * RF initialization values. + */ +static const uint8_t rtl8192eu_rf0_regs[] = { + 0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f, + 0x42, 0x57, 0x58, 0x67, 0x83, 0xb0, 0xb1, 0xb2, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbf, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, + 0xc7, 0xc8, 0xc9, 0xca, 0xdf, 0xef, 0x51, 0x52, 0x53, 0x56, 0x35, + 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x18, 0x5a, 0x19, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x00, 0x84, + 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, + 0x18, 0x1e, 0x1f, 0x00 +}, rtl8192eu_rf1_regs[] = { + 0x7f, 0x81, 0x00, 0x08, 0x18, 0x19, 0x1b, 0x1e, 0x1f, 0x2f, 0x3f, + 0x42, 0x57, 0x58, 0x67, 0x7f, 0x81, 0x83, 0xdf, 0xef, 0x51, 0x52, + 0x53, 0x56, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0x18, 0x5a, + 0x19, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x00, 0x84, 0x86, 0x87, 0x8e, 0x8f, 0xef, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0xef, 0x00, 0x1e, 0x1f, 0x00 +}; + +static const uint32_t rtl8192eu_rf0_vals[] = { + 0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x00064, + 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180, + 0x01552, 0x00000, 0xff9f1, 0x55418, 0x8cc00, 0x43083, 0x08166, + 0x0803e, 0x1c69f, 0x0407f, 0x80001, 0x40001, 0x00400, 0xc0000, + 0x02400, 0x00009, 0x40c91, 0x99999, 0x000a3, 0x88820, 0x76c06, + 0x00000, 0x80000, 0x00180, 0x001a0, 0x69545, 0x7e45e, 0x00071, + 0x51ff3, 0x000a8, 0x001e2, 0x002a8, 0x01c24, 0x09c24, 0x11c24, + 0x19c24, 0x00c07, 0x48000, 0x739d0, 0x0add7, 0x09dd4, 0x08dd1, + 0x07dce, 0x06dcb, 0x05dc8, 0x04dc5, 0x034cc, 0x0244f, 0x0144c, + 0x00014, 0x30159, 0x68180, 0x0014e, 0x48e00, 0x65540, 0x88000, + 0x020a0, 0xf02b0, 0xef7b0, 0xd4fb0, 0xcf060, 0xb0090, 0xa0080, + 0x90080, 0x8f780, 0x78730, 0x60fb0, 0x5ffa0, 0x40620, 0x37090, + 0x20080, 0x1f060, 0x0ffb0, 0x000a0, 0x0fc07, 0x00001, 0x80000, + 0x33e70 +}, rtl8192eu_rf1_vals[] = { + 0x00082, 0x3fc00, 0x30000, 0x08400, 0x00407, 0x00012, 0x00064, + 0x80009, 0x00880, 0x1a060, 0x00000, 0x060c0, 0xd0000, 0xbe180, + 0x01552, 0x00082, 0x3f000, 0x00000, 0x00180, 0x001a0, 0x69545, + 0x7e42e, 0x00071, 0x51ff3, 0x000a8, 0x001e0, 0x002a8, 0x01ca8, + 0x09c24, 0x11c24, 0x19c24, 0x00c07, 0x48000, 0x739d0, 0x0add7, + 0x09dd4, 0x08dd1, 0x07dce, 0x06dcb, 0x05dc8, 0x04dc5, 0x034cc, + 0x0244f, 0x0144c, 0x00014, 0x30159, 0x68180, 0x000ce, 0x48a00, + 0x65540, 0x88000, 0x020a0, 0xf02b0, 0xef7b0, 0xd4fb0, 0xcf060, + 0xb0090, 0xa0080, 0x90080, 0x8f780, 0x78730, 0x60fb0, 0x5ffa0, + 0x40620, 0x37090, 0x20080, 0x1f060, 0x0ffb0, 0x000a0, 0x10159, + 0x00001, 0x80000, 0x33e70 +}; + +static const struct rtwn_rf_prog rtl8192eu_rf[] = { + /* RF chain 0. */ + { + nitems(rtl8192eu_rf0_regs), + rtl8192eu_rf0_regs, + rtl8192eu_rf0_vals, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL }, + /* RF chain 1. */ + { + nitems(rtl8192eu_rf1_regs), + rtl8192eu_rf1_regs, + rtl8192eu_rf1_vals, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL } +}; + +#endif /* R92E_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_reg.h new file mode 100644 index 0000000000..7e935e2ffd --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_reg.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_reg.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92E_REG_H +#define R92E_REG_H + +#include +#include + +/* + * MAC registers. + */ +/* System Configuration. */ +#define R92E_LDOV12_CTRL 0x014 +#define R92E_AFE_XTAL_CTRL 0x02c +#define R92E_APE_PLL_CTRL_EXT 0x078 + +/* Bits for R92E_AFE_XTAL_CTRL. */ +#define R92E_AFE_XTAL_CTRL_ADDR_M 0x00fff000 +#define R92E_AFE_XTAL_CTRL_ADDR_S 12 + +#endif /* R92E_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rf.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rf.c new file mode 100644 index 0000000000..4266cbb7cb --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rf.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_rf.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +uint32_t +r92e_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) +{ + uint32_t val; + + val = rtwn_bb_read(sc, R92C_HSSI_PARAM2(chain)); + rtwn_bb_write(sc, R92C_HSSI_PARAM2(chain), + RW(val, R92C_HSSI_PARAM2_READ_ADDR, addr) & + ~R92C_HSSI_PARAM2_READ_EDGE); + + rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0), R92C_HSSI_PARAM2_READ_EDGE, 0); + rtwn_bb_setbits(sc, R92C_HSSI_PARAM2(0), 0, R92C_HSSI_PARAM2_READ_EDGE); + rtwn_delay(sc, 20); + + if (rtwn_bb_read(sc, R92C_HSSI_PARAM1(chain)) & R92C_HSSI_PARAM1_PI) + val = rtwn_bb_read(sc, R92C_HSPI_READBACK(chain)); + else + val = rtwn_bb_read(sc, R92C_LSSI_READBACK(chain)); + return (MS(val, R92C_LSSI_READBACK_DATA)); +} + +void +r92e_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, uint32_t val) +{ + + rtwn_bb_setbits(sc, 0x818, 0x20000, 0); + rtwn_bb_write(sc, R92C_LSSI_PARAM(chain), + SM(R88E_LSSI_PARAM_ADDR, addr) | SM(R92C_LSSI_PARAM_DATA, val)); + rtwn_bb_setbits(sc, 0x818, 0, 0x20000); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom.c new file mode 100644 index 0000000000..347cac4684 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_rom.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + +void +r92e_parse_rom(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r92e_softc *rs = sc->sc_priv; + struct r92e_rom *rom = (struct r92e_rom *)buf; + uint8_t pwr_diff; + int i, j, k; + + sc->thermal_meter = rom->thermal_meter; + rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap, + R92E_ROM_CRYSTALCAP_DEF); + + for (i = 0; i < sc->ntxchains; i++) { + struct r92e_tx_pwr_2g *pwr_2g = &rom->tx_pwr[i].pwr_2g; + struct r92e_tx_pwr_diff_2g *pwr_diff_2g = + &rom->tx_pwr[i].pwr_diff_2g; + + for (j = 0; j < R92E_GROUP_2G - 1; j++) { + rs->cck_tx_pwr[i][j] = + RTWN_GET_ROM_VAR(pwr_2g->cck[j], + R92E_DEF_TX_PWR_2G); + rs->ht40_tx_pwr_2g[i][j] = + RTWN_GET_ROM_VAR(pwr_2g->ht40[j], + R92E_DEF_TX_PWR_2G); + } + rs->cck_tx_pwr[i][j] = RTWN_GET_ROM_VAR(pwr_2g->cck[j], + R92E_DEF_TX_PWR_2G); + + rs->cck_tx_pwr_diff_2g[i][0] = 0; + rs->ofdm_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->ht20_ofdm, LOW_PART)); + rs->bw20_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->ht20_ofdm, HIGH_PART)); + rs->bw40_tx_pwr_diff_2g[i][0] = 0; + pwr_diff = RTWN_GET_ROM_VAR(pwr_diff_2g->ht20_ofdm, + R92E_DEF_TX_PWR_HT20_DIFF); + if (pwr_diff != R92E_DEF_TX_PWR_HT20_DIFF) { + rs->ofdm_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->ht20_ofdm, LOW_PART)); + rs->bw20_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->ht20_ofdm, HIGH_PART)); + } else { + rs->ofdm_tx_pwr_diff_2g[i][0] = + rs->bw20_tx_pwr_diff_2g[i][0] = pwr_diff; + } + + for (j = 1, k = 0; k < nitems(pwr_diff_2g->diff123); j++, k++) { + pwr_diff = RTWN_GET_ROM_VAR( + pwr_diff_2g->diff123[k].ofdm_cck, + R92E_DEF_TX_PWR_DIFF); + if (pwr_diff != R92E_DEF_TX_PWR_DIFF) { + rs->cck_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ofdm_cck, + LOW_PART)); + rs->ofdm_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ofdm_cck, + HIGH_PART)); + } else { + rs->cck_tx_pwr_diff_2g[i][j] = + rs->ofdm_tx_pwr_diff_2g[i][j] = pwr_diff; + } + pwr_diff = RTWN_GET_ROM_VAR( + pwr_diff_2g->diff123[k].ht40_ht20, + R92E_DEF_TX_PWR_DIFF); + if (pwr_diff != R92E_DEF_TX_PWR_DIFF) { + rs->bw20_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ht40_ht20, + LOW_PART)); + rs->bw40_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ht40_ht20, + HIGH_PART)); + } else { + rs->bw20_tx_pwr_diff_2g[i][j] = + rs->bw40_tx_pwr_diff_2g[i][j] = pwr_diff; + } + } + } + + rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY); + + /* Read MAC address. */ + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_defs.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_defs.h new file mode 100644 index 0000000000..3d99a1cf8b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_defs.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_rom_defs.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92E_ROM_DEFS_H +#define R92E_ROM_DEFS_H + +#include + +#define R92E_GROUP_2G 6 + +#define R92E_MAX_TX_COUNT 4 +#define R92E_MAX_RF_PATH 4 + +#define R92E_EFUSE_MAX_LEN 512 +#define R92E_EFUSE_MAP_LEN 512 + +#endif /* R92E_ROM_DEFS_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_image.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_image.h new file mode 100644 index 0000000000..ed8a15078c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rom_image.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_rom_image.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92E_ROM_IMAGE_H +#define R92E_ROM_IMAGE_H + +#include + +#define R92E_DEF_TX_PWR_2G 0x2d +#define R92E_DEF_TX_PWR_HT20_DIFF 0x02 +#define R92E_DEF_TX_PWR_DIFF 0xfe + +struct r92e_tx_pwr_2g { + uint8_t cck[R92E_GROUP_2G]; + uint8_t ht40[R92E_GROUP_2G - 1]; +} __packed; + +struct r92e_tx_pwr_diff_2g { + uint8_t ht20_ofdm; + struct { + uint8_t ht40_ht20; + uint8_t ofdm_cck; + } __packed diff123[R92E_MAX_TX_COUNT - 1]; +} __packed; + +struct r92e_tx_pwr { + struct r92e_tx_pwr_2g pwr_2g; + struct r92e_tx_pwr_diff_2g pwr_diff_2g; + uint8_t reserved[24]; +} __packed; + +/* + * RTL8192EU ROM image. + */ +struct r92e_rom { + uint8_t reserved1[16]; + struct r92e_tx_pwr tx_pwr[R92E_MAX_RF_PATH]; + uint8_t channel_plan; + uint8_t crystalcap; +#define R92E_ROM_CRYSTALCAP_DEF 0x20 + + uint8_t thermal_meter; + uint8_t iqk_lck; + uint8_t pa_type; + uint8_t lna_type_2g; + uint8_t reserved2; + uint8_t lna_type_5g; + uint8_t reserved3; + uint8_t rf_board_opt; + uint8_t rf_feature_opt; + uint8_t rf_bt_opt; + uint8_t version; + uint8_t customer_id; + uint8_t tx_bbswing_2g; + uint8_t tx_bbswing_5g; + uint8_t tx_pwr_calib_rate; + uint8_t rf_ant_opt; + uint8_t rfe_option; + uint8_t reserved4[5]; + uint16_t vid; + uint16_t pid; + uint8_t reserved5[3]; + uint8_t macaddr[IEEE80211_ADDR_LEN]; + uint8_t reserved6[2]; + uint8_t string[7]; /* "Realtek" */ + uint8_t reserved7[282]; +} __packed; + +_Static_assert(sizeof(struct r92e_rom) == R92E_EFUSE_MAP_LEN, + "R92E_EFUSE_MAP_LEN must be equal to sizeof(struct r92e_rom)!"); + +#endif /* R92E_ROM_IMAGE_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rx.c new file mode 100644 index 0000000000..16f3a70926 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_rx.c @@ -0,0 +1,97 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014, 2017 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_rx.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#ifndef RTWN_WITHOUT_UCODE +void +r92e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + + /* Skip Rx descriptor. */ + buf += sizeof(struct r92c_rx_stat); + len -= sizeof(struct r92c_rx_stat); + + if (len < 2) { + device_printf(sc->sc_dev, "C2H report too short (len %d)\n", + len); + return; + } + len -= 2; + + switch (buf[0]) { /* command id */ + case R12A_C2H_TX_REPORT: + /* NOTREACHED */ + KASSERT(0, ("use handle_tx_report() instead of %s\n", + __func__)); + break; + } +} +#else +void +r92e_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + + /* Should not happen. */ + device_printf(sc->sc_dev, "%s: called\n", __func__); +} +#endif + +int8_t +r92e_get_rssi_cck(struct rtwn_softc *sc, void *physt) +{ + + return (10 + r88e_get_rssi_cck(sc, physt)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_var.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_var.h new file mode 100644 index 0000000000..894122f523 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/r92e_var.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/r92e_var.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92E_VAR_H +#define R92E_VAR_H + +#include + +struct r92e_softc { + uint8_t chip; + uint8_t rs_flags; + + uint8_t regulatory; + uint8_t crystalcap; + + int8_t cck_tx_pwr[R92E_MAX_RF_PATH][R92E_GROUP_2G]; + int8_t ht40_tx_pwr_2g[R92E_MAX_RF_PATH][R92E_GROUP_2G]; + + int8_t cck_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT]; + int8_t ofdm_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT]; + int8_t bw20_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT]; + int8_t bw40_tx_pwr_diff_2g[R92E_MAX_RF_PATH][R92E_MAX_TX_COUNT]; + + int ac_usb_dma_size; + int ac_usb_dma_time; + uint32_t rf_chnlbw[R92E_MAX_RF_PATH]; +}; + +#endif /* R92E_VAR_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu.h new file mode 100644 index 0000000000..1749d35924 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/usb/r92eu.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + + +#ifndef RTL8192EU_H +#define RTL8192EU_H + +#include +#include + +/* + * Function declarations. + */ +/* r92eu_init.c */ +void r92eu_init_rx_agg(struct rtwn_softc *); +void r92eu_post_init(struct rtwn_softc *); + +#endif /* RTL8192EU_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_attach.c new file mode 100644 index 0000000000..f5e4810342 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_attach.c @@ -0,0 +1,204 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/usb/r92eu_attach.c 319087 2017-05-28 22:38:19Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +void r92eu_attach(struct rtwn_usb_softc *); + +static void +r92eu_attach_private(struct rtwn_softc *sc) +{ + struct r92e_softc *rs; + + rs = malloc(sizeof(struct r92e_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); + + rs->ac_usb_dma_size = 0x06; + rs->ac_usb_dma_time = 0x20; + + sc->sc_priv = rs; +} + +void +r92e_detach_private(struct rtwn_softc *sc) +{ + struct r92e_softc *rs = sc->sc_priv; + + free(rs, M_RTWN_PRIV); +} + +static void +r92eu_adj_devcaps(struct rtwn_softc *sc) +{ + /* XXX TODO? */ +} + +void +r92eu_attach(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + + /* USB part. */ + uc->uc_align_rx = r12au_align_rx; + uc->tx_agg_desc_num = 3; + + /* Common part. */ + sc->sc_flags = RTWN_FLAG_EXT_HDR; + + sc->sc_set_chan = r92e_set_chan; + sc->sc_fill_tx_desc = r12a_fill_tx_desc; + sc->sc_fill_tx_desc_raw = r12a_fill_tx_desc_raw; + sc->sc_fill_tx_desc_null = r12a_fill_tx_desc_null; + sc->sc_dump_tx_desc = r12au_dump_tx_desc; + sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags; + sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags; + sc->sc_get_rx_stats = r12a_get_rx_stats; + sc->sc_get_rssi_cck = r92e_get_rssi_cck; + sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; + sc->sc_classify_intr = r12au_classify_intr; + sc->sc_handle_tx_report = r12a_ratectl_tx_complete; + sc->sc_handle_c2h_report = r92e_handle_c2h_report; + sc->sc_check_frame = rtwn_nop_int_softc_mbuf; + sc->sc_rf_read = r92e_rf_read; + sc->sc_rf_write = r92e_rf_write; + sc->sc_check_condition = r92c_check_condition; + sc->sc_efuse_postread = rtwn_nop_softc; + sc->sc_parse_rom = r92e_parse_rom; + sc->sc_set_led = r92e_set_led; + sc->sc_power_on = r92e_power_on; + sc->sc_power_off = r92e_power_off; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_fw_reset = r92e_fw_reset; + sc->sc_fw_download_enable = r12a_fw_download_enable; +#endif + sc->sc_llt_init = r92e_llt_init; + sc->sc_set_page_size = rtwn_nop_int_softc; + sc->sc_lc_calib = r92c_lc_calib; + sc->sc_iq_calib = r88e_iq_calib; /* XXX TODO */ + sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; + sc->sc_adj_devcaps = r92eu_adj_devcaps; + sc->sc_vap_preattach = rtwn_nop_softc_vap; + sc->sc_postattach = rtwn_nop_softc; + sc->sc_detach_private = r92e_detach_private; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_set_media_status = r92e_set_media_status; + sc->sc_set_rsvd_page = r88e_set_rsvd_page; + sc->sc_set_pwrmode = r92e_set_pwrmode; + sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO? */ +#else + sc->sc_set_media_status = rtwn_nop_softc_int; +#endif + sc->sc_beacon_init = r12a_beacon_init; + sc->sc_beacon_enable = r92c_beacon_enable; + sc->sc_beacon_set_rate = rtwn_nop_void_int; + sc->sc_beacon_select = r21a_beacon_select; + sc->sc_temp_measure = r88e_temp_measure; + sc->sc_temp_read = r88e_temp_read; + sc->sc_init_tx_agg = r21au_init_tx_agg; + sc->sc_init_rx_agg = r92eu_init_rx_agg; + sc->sc_init_ampdu = rtwn_nop_softc; + sc->sc_init_intr = r12a_init_intr; + sc->sc_init_edca = r92c_init_edca; + sc->sc_init_bb = r92e_init_bb; + sc->sc_init_rf = r92e_init_rf; + sc->sc_init_antsel = rtwn_nop_softc; + sc->sc_post_init = r92eu_post_init; + sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; + + sc->mac_prog = &rtl8192eu_mac[0]; + sc->mac_size = nitems(rtl8192eu_mac); + sc->bb_prog = &rtl8192eu_bb[0]; + sc->bb_size = nitems(rtl8192eu_bb); + sc->agc_prog = &rtl8192eu_agc[0]; + sc->agc_size = nitems(rtl8192eu_agc); + sc->rf_prog = &rtl8192eu_rf[0]; + + sc->name = "RTL8192EU"; + sc->fwname = "rtwn-rtl8192eufw"; + sc->fwsig = 0x92e; + + sc->page_count = R92E_TX_PAGE_COUNT; + sc->pktbuf_count = 0; /* Unused */ + sc->ackto = 0x40; + sc->npubqpages = R92E_PUBQ_NPAGES; + sc->page_size = R92E_TX_PAGE_SIZE; + sc->txdesc_len = sizeof(struct r12au_tx_desc); + sc->efuse_maxlen = R92E_EFUSE_MAX_LEN; + sc->efuse_maplen = R92E_EFUSE_MAP_LEN; + sc->rx_dma_size = R92E_RX_DMA_BUFFER_SIZE; + + sc->macid_limit = R12A_MACID_MAX + 1; + sc->cam_entry_limit = R12A_CAM_ENTRY_COUNT; + sc->fwsize_limit = R92E_MAX_FW_SIZE; + sc->temp_delta = R88E_CALIB_THRESHOLD; + + sc->bcn_status_reg[0] = R92C_TDECTRL; + sc->bcn_status_reg[1] = R21A_DWBCN1_CTRL; + sc->rcr = 0; + + sc->ntxchains = 2; + sc->nrxchains = 2; + + r92eu_attach_private(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_init.c new file mode 100644 index 0000000000..6b7edbfcc9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_init.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/usb/r92eu_init.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + +void +r92eu_init_rx_agg(struct rtwn_softc *sc) +{ + struct r92e_softc *rs = sc->sc_priv; + + /* Rx aggregation (USB). */ + rtwn_setbits_1(sc, R12A_RXDMA_PRO, 0x20, 0x1e); + rtwn_write_4(sc, R92C_RXDMA_AGG_PG_TH, + rs->ac_usb_dma_size | (rs->ac_usb_dma_time << 8)); + rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, + R92C_TRXDMA_CTRL_RXDMA_AGG_EN); +} + +void +r92eu_post_init(struct rtwn_softc *sc) +{ + + /* Setup RTS BW (equal to data BW). */ + rtwn_setbits_1(sc, R92C_QUEUE_CTRL, 0x08, 0); + + /* Reset USB mode switch setting. */ + rtwn_write_1(sc, R92C_ACLK_MON, 0); + + rtwn_write_1(sc, R92C_USB_HRPWM, 0); + +#ifndef RTWN_WITHOUT_UCODE + if (sc->sc_flags & RTWN_FW_LOADED) { + if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { + /* TODO: implement */ + sc->sc_ratectl = RTWN_RATECTL_NET80211; + } else + sc->sc_ratectl = sc->sc_ratectl_sysctl; + } else +#endif + sc->sc_ratectl = RTWN_RATECTL_NONE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_reg.h new file mode 100644 index 0000000000..9f1d81352b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8192e/usb/r92eu_reg.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2017 Kevin Lo + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8192e/usb/r92eu_reg.h 312680 2017-01-24 02:35:38Z kevlo $ + */ + +#ifndef R92EU_REG_H +#define R92EU_REG_H + +#include +#include +#include + +#endif /* R92EU_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a.h new file mode 100644 index 0000000000..72569b991b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a.h @@ -0,0 +1,142 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a.h 312315 2017-01-17 00:35:23Z avos $ + */ + +#ifndef RTL8812A_H +#define RTL8812A_H + +/* + * Global definitions. + */ +#define R12A_PUBQ_NPAGES 219 +#define R12A_TXPKTBUF_COUNT 255 +#define R12A_TX_PAGE_COUNT 248 + +#define R12A_TX_PAGE_SIZE 512 +#define R12A_RX_DMA_BUFFER_SIZE 0x3e80 + +#define R12A_MAX_FW_SIZE 0x8000 +#define R12A_MACID_MAX 127 +#define R12A_CAM_ENTRY_COUNT 64 + +#define R12A_INTR_MSG_LEN 60 + +static const uint8_t r12a_chan_5ghz_0[] = + { 36, 40, 44, 48, 52, 56, 60, 64 }; +static const uint8_t r12a_chan_5ghz_1[] = + { 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144 }; +static const uint8_t r12a_chan_5ghz_2[] = + { 149, 153, 157, 161, 165, 169, 173, 177 }; + + +/* + * Function declarations. + */ +/* r12a_attach.c */ +void r12a_vap_preattach(struct rtwn_softc *, struct ieee80211vap *); +void r12a_detach_private(struct rtwn_softc *); + +/* r12a_beacon.c */ +void r12a_beacon_init(struct rtwn_softc *, void *, int); +void r12a_beacon_set_rate(void *, int); + +/* r12a_calib.c */ +void r12a_save_bb_afe_vals(struct rtwn_softc *, uint32_t[], + const uint16_t[], int); +void r12a_restore_bb_afe_vals(struct rtwn_softc *, uint32_t[], + const uint16_t[], int); +void r12a_save_rf_vals(struct rtwn_softc *, uint32_t[], + const uint8_t[], int); +void r12a_restore_rf_vals(struct rtwn_softc *, uint32_t[], + const uint8_t[], int); +void r12a_lc_calib(struct rtwn_softc *); +#ifndef RTWN_WITHOUT_UCODE +int r12a_iq_calib_fw_supported(struct rtwn_softc *); +#endif +void r12a_iq_calib_sw(struct rtwn_softc *); +void r12a_iq_calib(struct rtwn_softc *); + +/* r12a_caps.c */ +int r12a_ioctl_net(struct ieee80211com *, u_long, void *); + +/* r12a_chan.c */ +void r12a_fix_spur(struct rtwn_softc *, struct ieee80211_channel *); +void r12a_set_chan(struct rtwn_softc *, struct ieee80211_channel *); +void r12a_set_band_2ghz(struct rtwn_softc *, uint32_t); +void r12a_set_band_5ghz(struct rtwn_softc *, uint32_t); + +/* r12a_fw.c */ +#ifndef RTWN_WITHOUT_UCODE +void r12a_fw_reset(struct rtwn_softc *, int); +void r12a_fw_download_enable(struct rtwn_softc *, int); +void r12a_set_media_status(struct rtwn_softc *, int); +int r12a_set_pwrmode(struct rtwn_softc *, struct ieee80211vap *, + int); +void r12a_iq_calib_fw(struct rtwn_softc *); +#endif + +/* r12a_init.c */ +int r12a_check_condition(struct rtwn_softc *, const uint8_t[]); +int r12a_set_page_size(struct rtwn_softc *); +void r12a_init_edca(struct rtwn_softc *); +void r12a_init_bb(struct rtwn_softc *); +void r12a_init_rf(struct rtwn_softc *); +void r12a_crystalcap_write(struct rtwn_softc *); +int r12a_power_on(struct rtwn_softc *); +void r12a_power_off(struct rtwn_softc *); +void r12a_init_intr(struct rtwn_softc *); +void r12a_init_antsel(struct rtwn_softc *); + +/* r12a_led.c */ +void r12a_set_led(struct rtwn_softc *, int, int); + +/* r12a_rf.c */ +uint32_t r12a_rf_read(struct rtwn_softc *, int, uint8_t); +uint32_t r12a_c_cut_rf_read(struct rtwn_softc *, int, uint8_t); +void r12a_rf_write(struct rtwn_softc *, int, uint8_t, uint32_t); + +/* r12a_rom.c */ +void r12a_parse_rom_common(struct rtwn_softc *, uint8_t *); +void r12a_parse_rom(struct rtwn_softc *, uint8_t *); + +/* r12a_rx.c */ +void r12a_ratectl_tx_complete(struct rtwn_softc *, uint8_t *, int); +void r12a_handle_c2h_report(struct rtwn_softc *, uint8_t *, int); +int r12a_check_frame_checksum(struct rtwn_softc *, struct mbuf *); +uint8_t r12a_rx_radiotap_flags(const void *); +void r12a_get_rx_stats(struct rtwn_softc *, struct ieee80211_rx_stats *, + const void *, const void *); + +/* r12a_tx.c */ +void r12a_fill_tx_desc(struct rtwn_softc *, struct ieee80211_node *, + struct mbuf *, void *, uint8_t, int); +void r12a_fill_tx_desc_raw(struct rtwn_softc *, struct ieee80211_node *, + struct mbuf *, void *, const struct ieee80211_bpf_params *); +void r12a_fill_tx_desc_null(struct rtwn_softc *, void *, int, int, int); +uint8_t r12a_tx_radiotap_flags(const void *); + +#endif /* RTL8812A_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_beacon.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_beacon.c new file mode 100644 index 0000000000..ef47ea5f04 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_beacon.c @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_beacon.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +void +r12a_beacon_init(struct rtwn_softc *sc, void *buf, int id) +{ + struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; + + txd->flags0 = R12A_FLAGS0_LSG | R12A_FLAGS0_FSG | R12A_FLAGS0_BMCAST; + + /* + * NB: there is no need to setup HWSEQ_EN bit; + * QSEL_BEACON already implies it. + */ + txd->txdw1 = htole32(SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_BEACON)); + txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, RTWN_MACID_BC)); + + txd->txdw3 = htole32(R12A_TXDW3_DRVRATE); + txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id)); + + txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, RTWN_RIDX_CCK1)); + + txd->txdw6 = htole32(SM(R21A_TXDW6_MBSSID, id)); +} + +void +r12a_beacon_set_rate(void *buf, int is5ghz) +{ + struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; + + txd->txdw4 &= ~htole32(R12A_TXDW4_DATARATE_M); + if (is5ghz) { + txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, + RTWN_RIDX_OFDM6)); + } else + txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, RTWN_RIDX_CCK1)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_calib.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_calib.c new file mode 100644 index 0000000000..8a5979f4fa --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_calib.c @@ -0,0 +1,286 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_calib.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + + +void +r12a_lc_calib(struct rtwn_softc *sc) +{ + uint32_t chnlbw; + uint8_t txmode; + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: LC calibration started\n", __func__); + + txmode = rtwn_read_1(sc, R12A_SINGLETONE_CONT_TX + 2); + + if ((txmode & 0x07) != 0) { + /* Disable all continuous Tx. */ + /* + * Skipped because BB turns off continuous Tx until + * next packet comes in. + */ + } else { + /* Block all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + } + + /* Enter LCK mode. */ + rtwn_rf_setbits(sc, 0, R12A_RF_LCK, 0, R12A_RF_LCK_MODE); + + /* Start calibration. */ + chnlbw = rtwn_rf_read(sc, 0, R92C_RF_CHNLBW); + rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, chnlbw | R92C_RF_CHNLBW_LCSTART); + + /* Give calibration the time to complete. */ + rtwn_delay(sc, 150000); /* 150 ms */ + + /* Leave LCK mode. */ + rtwn_rf_setbits(sc, 0, R12A_RF_LCK, R12A_RF_LCK_MODE, 0); + + /* Restore configuration. */ + if ((txmode & 0x07) != 0) { + /* Continuous Tx case. */ + /* + * Skipped because BB turns off continuous Tx until + * next packet comes in. + */ + } else { + /* Unblock all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, 0); + } + + /* Recover channel number. */ + rtwn_rf_write(sc, 0, R92C_RF_CHNLBW, chnlbw); + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "%s: LC calibration finished\n", __func__); +} + +#ifndef RTWN_WITHOUT_UCODE +int +r12a_iq_calib_fw_supported(struct rtwn_softc *sc) +{ + if (sc->fwver == 0x19) + return (1); + + return (0); +} +#endif + +void +r12a_save_bb_afe_vals(struct rtwn_softc *sc, uint32_t vals[], + const uint16_t regs[], int size) +{ + int i; + + /* Select page C. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x80000000, 0); + + for (i = 0; i < size; i++) + vals[i] = rtwn_bb_read(sc, regs[i]); +} + +void +r12a_restore_bb_afe_vals(struct rtwn_softc *sc, uint32_t vals[], + const uint16_t regs[], int size) +{ + int i; + + /* Select page C. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x80000000, 0); + + for (i = 0; i < size; i++) + rtwn_bb_write(sc, regs[i], vals[i]); +} + +void +r12a_save_rf_vals(struct rtwn_softc *sc, uint32_t vals[], + const uint8_t regs[], int size) +{ + int c, i; + + /* Select page C. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x80000000, 0); + + for (c = 0; c < sc->nrxchains; c++) + for (i = 0; i < size; i++) + vals[c * size + i] = rtwn_rf_read(sc, c, regs[i]); +} + +void +r12a_restore_rf_vals(struct rtwn_softc *sc, uint32_t vals[], + const uint8_t regs[], int size) +{ + int c, i; + + /* Select page C. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x80000000, 0); + + for (c = 0; c < sc->nrxchains; c++) + for (i = 0; i < size; i++) + rtwn_rf_write(sc, c, regs[i], vals[c * size + i]); +} + +#ifdef RTWN_TODO +static void +r12a_iq_tx(struct rtwn_softc *sc) +{ + /* TODO */ +} + +static void +r12a_iq_config_mac(struct rtwn_softc *sc) +{ + + /* Select page C. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x80000000, 0); + rtwn_write_1(sc, R92C_TXPAUSE, + R92C_TX_QUEUE_AC | R92C_TX_QUEUE_MGT | R92C_TX_QUEUE_HIGH); + /* BCN_CTRL & BCN_CTRL1 */ + rtwn_setbits_1(sc, R92C_BCN_CTRL(0), R92C_BCN_CTRL_EN_BCN, 0); + rtwn_setbits_1(sc, R92C_BCN_CTRL(1), R92C_BCN_CTRL_EN_BCN, 0); + /* Rx ant off */ + rtwn_write_1(sc, R12A_OFDMCCK_EN, 0); + /* CCA off */ + rtwn_bb_setbits(sc, R12A_CCA_ON_SEC, 0x03, 0x0c); + /* CCK RX Path off */ + rtwn_write_1(sc, R12A_CCK_RX_PATH + 3, 0x0f); +} +#endif + +void +r12a_iq_calib_sw(struct rtwn_softc *sc) +{ +#define R12A_MAX_NRXCHAINS 2 + uint32_t bb_vals[nitems(r12a_iq_bb_regs)]; + uint32_t afe_vals[nitems(r12a_iq_afe_regs)]; + uint32_t rf_vals[nitems(r12a_iq_rf_regs) * R12A_MAX_NRXCHAINS]; + uint32_t rfe[2]; + + KASSERT(sc->nrxchains <= R12A_MAX_NRXCHAINS, + ("nrxchains > %d (%d)\n", R12A_MAX_NRXCHAINS, sc->nrxchains)); + + /* Save registers. */ + r12a_save_bb_afe_vals(sc, bb_vals, r12a_iq_bb_regs, + nitems(r12a_iq_bb_regs)); + + /* Select page C1. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0, 0x80000000); + rfe[0] = rtwn_bb_read(sc, R12A_RFE(0)); + rfe[1] = rtwn_bb_read(sc, R12A_RFE(1)); + + r12a_save_bb_afe_vals(sc, afe_vals, r12a_iq_afe_regs, + nitems(r12a_iq_afe_regs)); + r12a_save_rf_vals(sc, rf_vals, r12a_iq_rf_regs, + nitems(r12a_iq_rf_regs)); + +#ifdef RTWN_TODO + /* Configure MAC. */ + rtwn_iq_config_mac(sc); + rtwn_iq_tx(sc); +#endif + + r12a_restore_rf_vals(sc, rf_vals, r12a_iq_rf_regs, + nitems(r12a_iq_rf_regs)); + r12a_restore_bb_afe_vals(sc, afe_vals, r12a_iq_afe_regs, + nitems(r12a_iq_afe_regs)); + + /* Select page C1. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0, 0x80000000); + + /* Chain 0. */ + rtwn_bb_write(sc, R12A_SLEEP_NAV(0), 0); + rtwn_bb_write(sc, R12A_PMPD(0), 0); + rtwn_bb_write(sc, 0xc88, 0); + rtwn_bb_write(sc, 0xc8c, 0x3c000000); + rtwn_bb_setbits(sc, 0xc90, 0, 0x00000080); + rtwn_bb_setbits(sc, 0xcc4, 0, 0x20040000); + rtwn_bb_setbits(sc, 0xcc8, 0, 0x20000000); + + /* Chain 1. */ + rtwn_bb_write(sc, R12A_SLEEP_NAV(1), 0); + rtwn_bb_write(sc, R12A_PMPD(1), 0); + rtwn_bb_write(sc, 0xe88, 0); + rtwn_bb_write(sc, 0xe8c, 0x3c000000); + rtwn_bb_setbits(sc, 0xe90, 0, 0x00000080); + rtwn_bb_setbits(sc, 0xec4, 0, 0x20040000); + rtwn_bb_setbits(sc, 0xec8, 0, 0x20000000); + + rtwn_bb_write(sc, R12A_RFE(0), rfe[0]); + rtwn_bb_write(sc, R12A_RFE(1), rfe[1]); + + r12a_restore_bb_afe_vals(sc, bb_vals, r12a_iq_bb_regs, + nitems(r12a_iq_bb_regs)); +#undef R12A_MAX_NRXCHAINS +} + +void +r12a_iq_calib(struct rtwn_softc *sc) +{ +#ifndef RTWN_WITHOUT_UCODE + if ((sc->sc_flags & RTWN_FW_LOADED) && + rtwn_r12a_iq_calib_fw_supported(sc)) + r12a_iq_calib_fw(sc); + else +#endif + rtwn_r12a_iq_calib_sw(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_caps.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_caps.c new file mode 100644 index 0000000000..73d085a534 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_caps.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_caps.c 308356 2016-11-05 23:21:30Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + + +int +r12a_ioctl_net(struct ieee80211com *ic, u_long cmd, void *data) +{ + struct rtwn_softc *sc = ic->ic_softc; + struct r12a_softc *rs = sc->sc_priv; + struct ifreq *ifr = (struct ifreq *)data; + int error; + + error = 0; + switch (cmd) { + case SIOCSIFCAP: + { + struct ieee80211vap *vap; + int changed, rxmask; + + rxmask = ifr->ifr_reqcap & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6); + + RTWN_LOCK(sc); + changed = 0; + if (!(rs->rs_flags & R12A_RXCKSUM_EN) ^ + !(ifr->ifr_reqcap & IFCAP_RXCSUM)) { + rs->rs_flags ^= R12A_RXCKSUM_EN; + changed = 1; + } + if (!(rs->rs_flags & R12A_RXCKSUM6_EN) ^ + !(ifr->ifr_reqcap & IFCAP_RXCSUM_IPV6)) { + rs->rs_flags ^= R12A_RXCKSUM6_EN; + changed = 1; + } + if (changed) { + if (rxmask == 0) + sc->rcr &= ~R12A_RCR_TCP_OFFLD_EN; + else + sc->rcr |= R12A_RCR_TCP_OFFLD_EN; + + if (sc->sc_flags & RTWN_RUNNING) + rtwn_rxfilter_set(sc); + } + RTWN_UNLOCK(sc); + + IEEE80211_LOCK(ic); /* XXX */ + TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) { + struct ifnet *ifp = vap->iv_ifp; + + ifp->if_capenable &= + ~(IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6); + ifp->if_capenable |= rxmask; + } + IEEE80211_UNLOCK(ic); + break; + } + default: + error = ENOTTY; /* for net80211 */ + break; + } + + return (error); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_chan.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_chan.c new file mode 100644 index 0000000000..d30ce4e323 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_chan.c @@ -0,0 +1,601 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_chan.c 322988 2017-08-28 22:14:16Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + + +static void +r12a_write_txpower(struct rtwn_softc *sc, int chain, + struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) +{ + + if (IEEE80211_IS_CHAN_2GHZ(c)) { + /* Write per-CCK rate Tx power. */ + rtwn_bb_write(sc, R12A_TXAGC_CCK11_1(chain), + SM(R12A_TXAGC_CCK1, power[RTWN_RIDX_CCK1]) | + SM(R12A_TXAGC_CCK2, power[RTWN_RIDX_CCK2]) | + SM(R12A_TXAGC_CCK55, power[RTWN_RIDX_CCK55]) | + SM(R12A_TXAGC_CCK11, power[RTWN_RIDX_CCK11])); + } + + /* Write per-OFDM rate Tx power. */ + rtwn_bb_write(sc, R12A_TXAGC_OFDM18_6(chain), + SM(R12A_TXAGC_OFDM06, power[RTWN_RIDX_OFDM6]) | + SM(R12A_TXAGC_OFDM09, power[RTWN_RIDX_OFDM9]) | + SM(R12A_TXAGC_OFDM12, power[RTWN_RIDX_OFDM12]) | + SM(R12A_TXAGC_OFDM18, power[RTWN_RIDX_OFDM18])); + rtwn_bb_write(sc, R12A_TXAGC_OFDM54_24(chain), + SM(R12A_TXAGC_OFDM24, power[RTWN_RIDX_OFDM24]) | + SM(R12A_TXAGC_OFDM36, power[RTWN_RIDX_OFDM36]) | + SM(R12A_TXAGC_OFDM48, power[RTWN_RIDX_OFDM48]) | + SM(R12A_TXAGC_OFDM54, power[RTWN_RIDX_OFDM54])); + /* Write per-MCS Tx power. */ + rtwn_bb_write(sc, R12A_TXAGC_MCS3_0(chain), + SM(R12A_TXAGC_MCS0, power[RTWN_RIDX_HT_MCS(0)]) | + SM(R12A_TXAGC_MCS1, power[RTWN_RIDX_HT_MCS(1)]) | + SM(R12A_TXAGC_MCS2, power[RTWN_RIDX_HT_MCS(2)]) | + SM(R12A_TXAGC_MCS3, power[RTWN_RIDX_HT_MCS(3)])); + rtwn_bb_write(sc, R12A_TXAGC_MCS7_4(chain), + SM(R12A_TXAGC_MCS4, power[RTWN_RIDX_HT_MCS(4)]) | + SM(R12A_TXAGC_MCS5, power[RTWN_RIDX_HT_MCS(5)]) | + SM(R12A_TXAGC_MCS6, power[RTWN_RIDX_HT_MCS(6)]) | + SM(R12A_TXAGC_MCS7, power[RTWN_RIDX_HT_MCS(7)])); + if (sc->ntxchains >= 2) { + rtwn_bb_write(sc, R12A_TXAGC_MCS11_8(chain), + SM(R12A_TXAGC_MCS8, power[RTWN_RIDX_HT_MCS(8)]) | + SM(R12A_TXAGC_MCS9, power[RTWN_RIDX_HT_MCS(9)]) | + SM(R12A_TXAGC_MCS10, power[RTWN_RIDX_HT_MCS(10)]) | + SM(R12A_TXAGC_MCS11, power[RTWN_RIDX_HT_MCS(11)])); + rtwn_bb_write(sc, R12A_TXAGC_MCS15_12(chain), + SM(R12A_TXAGC_MCS12, power[RTWN_RIDX_HT_MCS(12)]) | + SM(R12A_TXAGC_MCS13, power[RTWN_RIDX_HT_MCS(13)]) | + SM(R12A_TXAGC_MCS14, power[RTWN_RIDX_HT_MCS(14)]) | + SM(R12A_TXAGC_MCS15, power[RTWN_RIDX_HT_MCS(15)])); + } + + /* TODO: VHT rates */ +} + +static int +r12a_get_power_group(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t chan; + int group; + + chan = rtwn_chan2centieee(c); + if (IEEE80211_IS_CHAN_2GHZ(c)) { + if (chan <= 2) group = 0; + else if (chan <= 5) group = 1; + else if (chan <= 8) group = 2; + else if (chan <= 11) group = 3; + else if (chan <= 14) group = 4; + else { + KASSERT(0, ("wrong 2GHz channel %d!\n", chan)); + return (-1); + } + } else if (IEEE80211_IS_CHAN_5GHZ(c)) { + if (chan < 36) + return (-1); + + if (chan <= 42) group = 0; + else if (chan <= 48) group = 1; + else if (chan <= 58) group = 2; + else if (chan <= 64) group = 3; + else if (chan <= 106) group = 4; + else if (chan <= 114) group = 5; + else if (chan <= 122) group = 6; + else if (chan <= 130) group = 7; + else if (chan <= 138) group = 8; + else if (chan <= 144) group = 9; + else if (chan <= 155) group = 10; + else if (chan <= 161) group = 11; + else if (chan <= 171) group = 12; + else if (chan <= 177) group = 13; + else { + KASSERT(0, ("wrong 5GHz channel %d!\n", chan)); + return (-1); + } + } else { + KASSERT(0, ("wrong channel band (flags %08X)\n", c->ic_flags)); + return (-1); + } + + return (group); +} + +static void +r12a_get_txpower(struct rtwn_softc *sc, int chain, + struct ieee80211_channel *c, uint8_t power[RTWN_RIDX_COUNT]) +{ + struct r12a_softc *rs = sc->sc_priv; + int i, ridx, group, max_mcs; + + /* Determine channel group. */ + group = r12a_get_power_group(sc, c); + if (group == -1) { /* shouldn't happen */ + device_printf(sc->sc_dev, "%s: incorrect channel\n", __func__); + return; + } + + /* TODO: VHT rates. */ + max_mcs = RTWN_RIDX_HT_MCS(sc->ntxchains * 8 - 1); + + /* XXX regulatory */ + /* XXX net80211 regulatory */ + + if (IEEE80211_IS_CHAN_2GHZ(c)) { + for (ridx = RTWN_RIDX_CCK1; ridx <= RTWN_RIDX_CCK11; ridx++) + power[ridx] = rs->cck_tx_pwr[chain][group]; + for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++) + power[ridx] = rs->ht40_tx_pwr_2g[chain][group]; + + for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) + power[ridx] += rs->ofdm_tx_pwr_diff_2g[chain][0]; + + for (i = 0; i < sc->ntxchains; i++) { + uint8_t min_mcs; + uint8_t pwr_diff; + +#ifdef notyet + if (IEEE80211_IS_CHAN_HT80(c)) { + /* Vendor driver uses HT40 values here. */ + pwr_diff = rs->bw40_tx_pwr_diff_2g[chain][i]; + } else +#endif + if (IEEE80211_IS_CHAN_HT40(c)) + pwr_diff = rs->bw40_tx_pwr_diff_2g[chain][i]; + else + pwr_diff = rs->bw20_tx_pwr_diff_2g[chain][i]; + + min_mcs = RTWN_RIDX_HT_MCS(i * 8); + for (ridx = min_mcs; ridx <= max_mcs; ridx++) + power[ridx] += pwr_diff; + } + } else { /* 5GHz */ + for (ridx = RTWN_RIDX_OFDM6; ridx <= max_mcs; ridx++) + power[ridx] = rs->ht40_tx_pwr_5g[chain][group]; + + for (ridx = RTWN_RIDX_OFDM6; ridx <= RTWN_RIDX_OFDM54; ridx++) + power[ridx] += rs->ofdm_tx_pwr_diff_5g[chain][0]; + + for (i = 0; i < sc->ntxchains; i++) { + uint8_t min_mcs; + uint8_t pwr_diff; + +#ifdef notyet + if (IEEE80211_IS_CHAN_HT80(c)) { + /* TODO: calculate base value. */ + pwr_diff = rs->bw80_tx_pwr_diff_5g[chain][i]; + } else +#endif + if (IEEE80211_IS_CHAN_HT40(c)) + pwr_diff = rs->bw40_tx_pwr_diff_5g[chain][i]; + else + pwr_diff = rs->bw20_tx_pwr_diff_5g[chain][i]; + + min_mcs = RTWN_RIDX_HT_MCS(i * 8); + for (ridx = min_mcs; ridx <= max_mcs; ridx++) + power[ridx] += pwr_diff; + } + } + + /* Apply max limit. */ + for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) { + if (power[ridx] > R92C_MAX_TX_PWR) + power[ridx] = R92C_MAX_TX_PWR; + } + +#ifdef RTWN_DEBUG + if (sc->sc_debug & RTWN_DEBUG_TXPWR) { + /* Dump per-rate Tx power values. */ + printf("Tx power for chain %d:\n", chain); + for (ridx = RTWN_RIDX_CCK1; ridx <= max_mcs; ridx++) + printf("Rate %d = %u\n", ridx, power[ridx]); + } +#endif +} + +static void +r12a_set_txpower(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint8_t power[RTWN_RIDX_COUNT]; + int i; + + for (i = 0; i < sc->ntxchains; i++) { + memset(power, 0, sizeof(power)); + /* Compute per-rate Tx power values. */ + r12a_get_txpower(sc, i, c, power); + /* Write per-rate Tx power values to hardware. */ + r12a_write_txpower(sc, i, c, power); + } +} + +void +r12a_fix_spur(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + struct r12a_softc *rs = sc->sc_priv; + uint16_t chan = rtwn_chan2centieee(c); + + if (rs->chip & R12A_CHIP_C_CUT) { + if (IEEE80211_IS_CHAN_HT40(c) && chan == 11) { + rtwn_bb_setbits(sc, R12A_RFMOD, 0, 0xc00); + rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK, 0, 0x40000000); + } else { + rtwn_bb_setbits(sc, R12A_RFMOD, 0x400, 0x800); + + if (!IEEE80211_IS_CHAN_HT40(c) && /* 20 MHz */ + (chan == 13 || chan == 14)) { + rtwn_bb_setbits(sc, R12A_RFMOD, 0, 0x300); + rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK, + 0, 0x40000000); + } else { /* !80 Mhz */ + rtwn_bb_setbits(sc, R12A_RFMOD, 0x100, 0x200); + rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK, + 0x40000000, 0); + } + } + } else { + /* Set ADC clock to 160M to resolve 2480 MHz spur. */ + if (!IEEE80211_IS_CHAN_HT40(c) && /* 20 MHz */ + (chan == 13 || chan == 14)) + rtwn_bb_setbits(sc, R12A_RFMOD, 0, 0x300); + else if (IEEE80211_IS_CHAN_2GHZ(c)) + rtwn_bb_setbits(sc, R12A_RFMOD, 0x100, 0x200); + } +} + +static void +r12a_set_band(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct r12a_softc *rs = sc->sc_priv; + uint32_t basicrates; + uint8_t swing; + int i; + + /* Check if band was changed. */ + if ((sc->sc_flags & (RTWN_STARTED | RTWN_RUNNING)) != + RTWN_STARTED && IEEE80211_IS_CHAN_5GHZ(c) ^ + !(rtwn_read_1(sc, R12A_CCK_CHECK) & R12A_CCK_CHECK_5GHZ)) + return; + + rtwn_get_rates(sc, ieee80211_get_suprates(ic, c), NULL, &basicrates, + NULL, 1); + if (IEEE80211_IS_CHAN_2GHZ(c)) { + rtwn_r12a_set_band_2ghz(sc, basicrates); + swing = rs->tx_bbswing_2g; + } else if (IEEE80211_IS_CHAN_5GHZ(c)) { + rtwn_r12a_set_band_5ghz(sc, basicrates); + swing = rs->tx_bbswing_5g; + } else { + KASSERT(0, ("wrong channel flags %08X\n", c->ic_flags)); + return; + } + + /* XXX PATH_B is set by vendor driver. */ + for (i = 0; i < 2; i++) { + uint16_t val = 0; + + switch ((swing >> i * 2) & 0x3) { + case 0: + val = 0x200; /* 0 dB */ + break; + case 1: + val = 0x16a; /* -3 dB */ + break; + case 2: + val = 0x101; /* -6 dB */ + break; + case 3: + val = 0xb6; /* -9 dB */ + break; + } + + rtwn_bb_setbits(sc, R12A_TX_SCALE(i), R12A_TX_SCALE_SWING_M, + val << R12A_TX_SCALE_SWING_S); + } +} + +void +r12a_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + uint32_t val; + uint16_t chan; + int i; + + r12a_set_band(sc, c); + + chan = rtwn_chan2centieee(c); + if (36 <= chan && chan <= 48) + val = 0x09280000; + else if (50 <= chan && chan <= 64) + val = 0x08a60000; + else if (100 <= chan && chan <= 116) + val = 0x08a40000; + else if (118 <= chan) + val = 0x08240000; + else + val = 0x12d40000; + + rtwn_bb_setbits(sc, R12A_FC_AREA, 0x1ffe0000, val); + + for (i = 0; i < sc->nrxchains; i++) { + if (36 <= chan && chan <= 64) + val = 0x10100; + else if (100 <= chan && chan <= 140) + val = 0x30100; + else if (140 < chan) + val = 0x50100; + else + val = 0x00000; + + rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, 0x70300, val); + + /* RTL8812AU-specific */ + rtwn_r12a_fix_spur(sc, c); + + KASSERT(chan <= 0xff, ("%s: chan %d\n", __func__, chan)); + rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, 0xff, chan); + } + +#ifdef notyet + if (IEEE80211_IS_CHAN_HT80(c)) { /* 80 MHz */ + rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x80, 0x100); + + /* TODO */ + + val = 0x0; + } else +#endif + if (IEEE80211_IS_CHAN_HT40(c)) { /* 40 MHz */ + uint8_t ext_chan; + + if (IEEE80211_IS_CHAN_HT40U(c)) + ext_chan = R12A_DATA_SEC_PRIM_DOWN_20; + else + ext_chan = R12A_DATA_SEC_PRIM_UP_20; + + rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x100, 0x80); + rtwn_write_1(sc, R12A_DATA_SEC, ext_chan); + + rtwn_bb_setbits(sc, R12A_RFMOD, 0x003003c3, 0x00300201); + rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK, 0x40000000, 0); + + /* discard high 4 bits */ + val = rtwn_bb_read(sc, R12A_RFMOD); + val = RW(val, R12A_RFMOD_EXT_CHAN, ext_chan); + rtwn_bb_write(sc, R12A_RFMOD, val); + + val = rtwn_bb_read(sc, R12A_CCA_ON_SEC); + val = RW(val, R12A_CCA_ON_SEC_EXT_CHAN, ext_chan); + rtwn_bb_write(sc, R12A_CCA_ON_SEC, val); + + if (rtwn_read_1(sc, 0x837) & 0x04) + val = 0x01800000; + else if (sc->nrxchains == 2 && sc->ntxchains == 2) + val = 0x01c00000; + else + val = 0x02000000; + + rtwn_bb_setbits(sc, R12A_L1_PEAK_TH, 0x03c00000, val); + + if (IEEE80211_IS_CHAN_HT40U(c)) + rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0x10, 0); + else + rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, 0, 0x10); + + val = 0x400; + } else { /* 20 MHz */ + rtwn_setbits_2(sc, R92C_WMAC_TRXPTCL_CTL, 0x180, 0); + rtwn_write_1(sc, R12A_DATA_SEC, R12A_DATA_SEC_NO_EXT); + + rtwn_bb_setbits(sc, R12A_RFMOD, 0x003003c3, 0x00300200); + rtwn_bb_setbits(sc, R12A_ADC_BUF_CLK, 0x40000000, 0); + + if (sc->nrxchains == 2 && sc->ntxchains == 2) + val = 0x01c00000; + else + val = 0x02000000; + + rtwn_bb_setbits(sc, R12A_L1_PEAK_TH, 0x03c00000, val); + + val = 0xc00; + } + + /* RTL8812AU-specific */ + rtwn_r12a_fix_spur(sc, c); + + for (i = 0; i < sc->nrxchains; i++) + rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, 0xc00, val); + + /* Set Tx power for this new channel. */ + r12a_set_txpower(sc, c); +} + +void +r12a_set_band_2ghz(struct rtwn_softc *sc, uint32_t basicrates) +{ + struct r12a_softc *rs = sc->sc_priv; + + /* Enable CCK / OFDM. */ + rtwn_bb_setbits(sc, R12A_OFDMCCK_EN, + 0, R12A_OFDMCCK_EN_CCK | R12A_OFDMCCK_EN_OFDM); + + rtwn_bb_setbits(sc, R12A_BW_INDICATION, 0x02, 0x01); + rtwn_bb_setbits(sc, R12A_PWED_TH, 0x3e000, 0x2e000); + + /* Select AGC table. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x03, 0); + + switch (rs->rfe_type) { + case 0: + case 1: + case 2: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x77777777); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77777777); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0); + break; + case 3: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x54337770); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x54337770); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0x01000000); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0x01000000); + rtwn_bb_setbits(sc, R12A_ANTSEL_SW, 0x0303, 0x01); + break; + case 4: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x77777777); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77777777); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0x00100000); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0x00100000); + break; + case 5: + rtwn_write_1(sc, R12A_RFE_PINMUX(0) + 2, 0x77); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77777777); + rtwn_setbits_1(sc, R12A_RFE_INV(0) + 3, 0x01, 0); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0); + break; + default: + break; + } + + rtwn_bb_setbits(sc, R12A_TX_PATH, 0xf0, 0x10); + rtwn_bb_setbits(sc, R12A_CCK_RX_PATH, 0x0f000000, 0x01000000); + + /* Write basic rates. */ + rtwn_set_basicrates(sc, basicrates); + + rtwn_write_1(sc, R12A_CCK_CHECK, 0); +} + +void +r12a_set_band_5ghz(struct rtwn_softc *sc, uint32_t basicrates) +{ + struct r12a_softc *rs = sc->sc_priv; + int ntries; + + rtwn_write_1(sc, R12A_CCK_CHECK, R12A_CCK_CHECK_5GHZ); + + for (ntries = 0; ntries < 100; ntries++) { + if ((rtwn_read_2(sc, R12A_TXPKT_EMPTY) & 0x30) == 0x30) + break; + + rtwn_delay(sc, 25); + } + if (ntries == 100) { + device_printf(sc->sc_dev, + "%s: TXPKT_EMPTY check failed (%04X)\n", + __func__, rtwn_read_2(sc, R12A_TXPKT_EMPTY)); + } + + /* Enable OFDM. */ + rtwn_bb_setbits(sc, R12A_OFDMCCK_EN, R12A_OFDMCCK_EN_CCK, + R12A_OFDMCCK_EN_OFDM); + + rtwn_bb_setbits(sc, R12A_BW_INDICATION, 0x01, 0x02); + rtwn_bb_setbits(sc, R12A_PWED_TH, 0x3e000, 0x2a000); + + /* Select AGC table. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0x03, 0x01); + + switch (rs->rfe_type) { + case 0: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x77337717); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77337717); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0x01000000); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0x01000000); + break; + case 1: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x77337717); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77337717); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0); + break; + case 2: + case 4: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x77337777); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77337777); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0x01000000); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0x01000000); + break; + case 3: + rtwn_bb_write(sc, R12A_RFE_PINMUX(0), 0x54337717); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x54337717); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x3ff00000, 0x01000000); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0x01000000); + rtwn_bb_setbits(sc, R12A_ANTSEL_SW, 0x0303, 0x01); + break; + case 5: + rtwn_write_1(sc, R12A_RFE_PINMUX(0) + 2, 0x33); + rtwn_bb_write(sc, R12A_RFE_PINMUX(1), 0x77337777); + rtwn_setbits_1(sc, R12A_RFE_INV(0) + 3, 0, 0x01); + rtwn_bb_setbits(sc, R12A_RFE_INV(1), 0x3ff00000, 0x01000000); + break; + default: + break; + } + + rtwn_bb_setbits(sc, R12A_TX_PATH, 0xf0, 0); + rtwn_bb_setbits(sc, R12A_CCK_RX_PATH, 0, 0x0f000000); + + /* Write basic rates. */ + rtwn_set_basicrates(sc, basicrates); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw.c new file mode 100644 index 0000000000..9c7b6b2e67 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw.c @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_fw.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include + + +#ifndef RTWN_WITHOUT_UCODE +void +r12a_fw_reset(struct rtwn_softc *sc, int reason) +{ + /* Reset MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0); + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x08, 0); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_CPUEN, 0, 1); + + /* Enable MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL, R92C_RSV_CTRL_WLOCK_00, 0); + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x08); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + 0, R92C_SYS_FUNC_EN_CPUEN, 1); +} + +void +r12a_fw_download_enable(struct rtwn_softc *sc, int enable) +{ + if (enable) { + /* MCU firmware download enable. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, 0, R92C_MCUFWDL_EN); + /* 8051 reset. */ + rtwn_setbits_1_shift(sc, R92C_MCUFWDL, R92C_MCUFWDL_ROM_DLEN, + 0, 2); + } else { + /* MCU download disable. */ + rtwn_setbits_1(sc, R92C_MCUFWDL, R92C_MCUFWDL_EN, 0); + } +} + +void +r12a_set_media_status(struct rtwn_softc *sc, int macid) +{ + struct r12a_fw_cmd_msrrpt status; + int error; + + if (macid & RTWN_MACID_VALID) + status.msrb0 = R12A_MSRRPT_B0_ASSOC; + else + status.msrb0 = R12A_MSRRPT_B0_DISASSOC; + + status.macid = (macid & ~RTWN_MACID_VALID); + status.macid_end = 0; + + error = r88e_fw_cmd(sc, R12A_CMD_MSR_RPT, &status, sizeof(status)); + if (error != 0) + device_printf(sc->sc_dev, "cannot change media status!\n"); +} + +int +r12a_set_pwrmode(struct rtwn_softc *sc, struct ieee80211vap *vap, + int off) +{ + struct r12a_fw_cmd_pwrmode mode; + int error; + + if (off && vap->iv_state == IEEE80211_S_RUN && + (vap->iv_flags & IEEE80211_F_PMGTON)) { + mode.mode = R88E_PWRMODE_LEG; + /* + * TODO: switch to RFOFF state + * (something is missing here - Rx stops with it). + */ +#ifdef RTWN_TODO + mode.pwr_state = R88E_PWRMODE_STATE_RFOFF; +#else + mode.pwr_state = R88E_PWRMODE_STATE_RFON; +#endif + } else { + mode.mode = R88E_PWRMODE_CAM; + mode.pwr_state = R88E_PWRMODE_STATE_ALLON; + } + mode.pwrb1 = + SM(R88E_PWRMODE_B1_SMART_PS, R88E_PWRMODE_B1_LEG_NULLDATA) | + SM(R88E_PWRMODE_B1_RLBM, R88E_PWRMODE_B1_MODE_MIN); + /* XXX ignored */ + mode.bcn_pass = 0; + mode.queue_uapsd = 0; + mode.pwrb5 = R12A_PWRMODE_B5_NO_BTCOEX; + error = r88e_fw_cmd(sc, R12A_CMD_SET_PWRMODE, &mode, sizeof(mode)); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: CMD_SET_PWRMODE was not sent, error %d\n", + __func__, error); + } + + return (error); +} + +void +r12a_iq_calib_fw(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + struct ieee80211_channel *c = sc->sc_ic.ic_curchan; + struct r12a_fw_cmd_iq_calib cmd; + + if (rs->rs_flags & R12A_IQK_RUNNING) + return; + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "Starting IQ calibration (FW)\n"); + + cmd.chan = rtwn_chan2centieee(c); + if (IEEE80211_IS_CHAN_5GHZ(c)) + cmd.band_bw = RTWN_CMD_IQ_BAND_5GHZ; + else + cmd.band_bw = RTWN_CMD_IQ_BAND_2GHZ; + + /* TODO: 80/160 MHz. */ + if (IEEE80211_IS_CHAN_HT40(c)) + cmd.band_bw |= RTWN_CMD_IQ_CHAN_WIDTH_40; + else + cmd.band_bw |= RTWN_CMD_IQ_CHAN_WIDTH_20; + + cmd.ext_5g_pa_lna = RTWN_CMD_IQ_EXT_PA_5G(rs->ext_pa_5g); + cmd.ext_5g_pa_lna |= RTWN_CMD_IQ_EXT_LNA_5G(rs->ext_lna_5g); + + if (r88e_fw_cmd(sc, R12A_CMD_IQ_CALIBRATE, &cmd, sizeof(cmd)) != 0) { + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "error while sending IQ calibration command to FW!\n"); + return; + } + + rs->rs_flags |= R12A_IQK_RUNNING; +} +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw_cmd.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw_cmd.h new file mode 100644 index 0000000000..f88bd0d962 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_fw_cmd.h @@ -0,0 +1,123 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_fw_cmd.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R12A_FW_CMD_H +#define R12A_FW_CMD_H + +#include + +/* + * Host to firmware commands. + */ +/* Note: some parts are shared with RTL8188EU. */ +#define R12A_CMD_MSR_RPT 0x01 +#define R12A_CMD_SET_PWRMODE 0x20 +#define R12A_CMD_IQ_CALIBRATE 0x45 + +/* Structure for R12A_CMD_MSR_RPT. */ +struct r12a_fw_cmd_msrrpt { + uint8_t msrb0; +#define R12A_MSRRPT_B0_DISASSOC 0x00 +#define R12A_MSRRPT_B0_ASSOC 0x01 +#define R12A_MSRRPT_B0_MACID_IND 0x02 + + uint8_t macid; + uint8_t macid_end; +} __packed; + +/* Structure for R12A_CMD_SET_PWRMODE. */ +struct r12a_fw_cmd_pwrmode { + uint8_t mode; + uint8_t pwrb1; + uint8_t bcn_pass; + uint8_t queue_uapsd; + uint8_t pwr_state; + uint8_t pwrb5; +#define R12A_PWRMODE_B5_NO_BTCOEX 0x40 +} __packed; + +/* Structure for R12A_CMD_IQ_CALIBRATE. */ +struct r12a_fw_cmd_iq_calib { + uint8_t chan; + uint8_t band_bw; +#define RTWN_CMD_IQ_CHAN_WIDTH_20 0x01 +#define RTWN_CMD_IQ_CHAN_WIDTH_40 0x02 +#define RTWN_CMD_IQ_CHAN_WIDTH_80 0x04 +#define RTWN_CMD_IQ_CHAN_WIDTH_160 0x08 +#define RTWN_CMD_IQ_BAND_2GHZ 0x10 +#define RTWN_CMD_IQ_BAND_5GHZ 0x20 + + uint8_t ext_5g_pa_lna; +#define RTWN_CMD_IQ_EXT_PA_5G(pa) (pa) +#define RTWN_CMD_IQ_EXT_LNA_5G(lna) ((lna) << 1) +} __packed; + + +/* + * C2H event types. + */ +#define R12A_C2H_DEBUG 0x00 +#define R12A_C2H_TX_REPORT 0x03 +#define R12A_C2H_BT_INFO 0x09 +#define R12A_C2H_RA_REPORT 0x0c +#define R12A_C2H_IQK_FINISHED 0x11 + +/* Structure for R12A_C2H_TX_REPORT event. */ +struct r12a_c2h_tx_rpt { + uint8_t txrptb0; +#define R12A_TXRPTB0_QSEL_M 0x1f +#define R12A_TXRPTB0_QSEL_S 0 +#define R12A_TXRPTB0_BC 0x20 +#define R12A_TXRPTB0_LIFE_EXPIRE 0x40 +#define R12A_TXRPTB0_RETRY_OVER 0x80 + + uint8_t macid; + uint8_t txrptb2; +#define R12A_TXRPTB2_RETRY_CNT_M 0x3f +#define R12A_TXRPTB2_RETRY_CNT_S 0 + + uint8_t queue_time_low; /* 256 msec unit */ + uint8_t queue_time_high; + uint8_t final_rate; + uint16_t reserved; +} __packed; + +/* Structure for R12A_C2H_RA_REPORT event. */ +struct r12a_c2h_ra_report { + uint8_t rarptb0; +#define R12A_RARPTB0_RATE_M 0x3f +#define R12A_RARPTB0_RATE_S 0 + + uint8_t macid; + uint8_t rarptb2; +#define R12A_RARPTB0_LDPC 0x01 +#define R12A_RARPTB0_TXBF 0x02 +#define R12A_RARPTB0_NOISE 0x04 +} __packed; + +#endif /* R12A_FW_CMD_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_init.c new file mode 100644 index 0000000000..a9d48dd346 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_init.c @@ -0,0 +1,486 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_init.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include +#include + + +int +r12a_check_condition(struct rtwn_softc *sc, const uint8_t cond[]) +{ + struct r12a_softc *rs = sc->sc_priv; + uint8_t mask[4]; + int i, j, nmasks; + + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "%s: condition byte 0: %02X; ext PA/LNA: %d/%d (2 GHz), " + "%d/%d (5 GHz)\n", __func__, cond[0], rs->ext_pa_2g, + rs->ext_lna_2g, rs->ext_pa_5g, rs->ext_lna_5g); + + if (cond[0] == 0) + return (1); + + if (!rs->ext_pa_2g && !rs->ext_lna_2g && + !rs->ext_pa_5g && !rs->ext_lna_5g) + return (0); + + nmasks = 0; + if (rs->ext_pa_2g) { + mask[nmasks] = R12A_COND_GPA; + mask[nmasks] |= R12A_COND_TYPE(rs->type_pa_2g); + nmasks++; + } + if (rs->ext_pa_5g) { + mask[nmasks] = R12A_COND_APA; + mask[nmasks] |= R12A_COND_TYPE(rs->type_pa_5g); + nmasks++; + } + if (rs->ext_lna_2g) { + mask[nmasks] = R12A_COND_GLNA; + mask[nmasks] |= R12A_COND_TYPE(rs->type_lna_2g); + nmasks++; + } + if (rs->ext_lna_5g) { + mask[nmasks] = R12A_COND_ALNA; + mask[nmasks] |= R12A_COND_TYPE(rs->type_lna_5g); + nmasks++; + } + + for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++) + for (j = 0; j < nmasks; j++) + if ((cond[i] & mask[j]) == mask[j]) + return (1); + + return (0); +} + +int +r12a_set_page_size(struct rtwn_softc *sc) +{ + return (rtwn_setbits_1(sc, R92C_PBP, R92C_PBP_PSTX_M, + R92C_PBP_512 << R92C_PBP_PSTX_S) == 0); +} + +void +r12a_init_edca(struct rtwn_softc *sc) +{ + r92c_init_edca(sc); + + /* 80 MHz clock */ + rtwn_write_1(sc, R92C_USTIME_TSF, 0x50); + rtwn_write_1(sc, R92C_USTIME_EDCA, 0x50); +} + +void +r12a_init_bb(struct rtwn_softc *sc) +{ + int i, j; + + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 0, R92C_SYS_FUNC_EN_USBA); + + /* Enable BB and RF. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, 0, + R92C_SYS_FUNC_EN_BBRSTB | R92C_SYS_FUNC_EN_BB_GLB_RST); + + /* PathA RF Power On. */ + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + + /* PathB RF Power On. */ + rtwn_write_1(sc, R12A_RF_B_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); + + /* Write BB initialization values. */ + for (i = 0; i < sc->bb_size; i++) { + const struct rtwn_bb_prog *bb_prog = &sc->bb_prog[i]; + + while (!rtwn_check_condition(sc, bb_prog->cond)) { + KASSERT(bb_prog->next != NULL, + ("%s: wrong condition value (i %d)\n", + __func__, i)); + bb_prog = bb_prog->next; + } + + for (j = 0; j < bb_prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "BB: reg 0x%03x, val 0x%08x\n", + bb_prog->reg[j], bb_prog->val[j]); + + rtwn_bb_write(sc, bb_prog->reg[j], bb_prog->val[j]); + rtwn_delay(sc, 1); + } + } + + /* XXX meshpoint mode? */ + + /* Write AGC values. */ + for (i = 0; i < sc->agc_size; i++) { + const struct rtwn_agc_prog *agc_prog = &sc->agc_prog[i]; + + while (!rtwn_check_condition(sc, agc_prog->cond)) { + KASSERT(agc_prog->next != NULL, + ("%s: wrong condition value (2) (i %d)\n", + __func__, i)); + agc_prog = agc_prog->next; + } + + for (j = 0; j < agc_prog->count; j++) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "AGC: val 0x%08x\n", agc_prog->val[j]); + + rtwn_bb_write(sc, 0x81c, agc_prog->val[j]); + rtwn_delay(sc, 1); + } + } + + for (i = 0; i < sc->nrxchains; i++) { + rtwn_bb_write(sc, R12A_INITIAL_GAIN(i), 0x22); + rtwn_delay(sc, 1); + rtwn_bb_write(sc, R12A_INITIAL_GAIN(i), 0x20); + rtwn_delay(sc, 1); + } + + rtwn_r12a_crystalcap_write(sc); + + if (rtwn_bb_read(sc, R12A_CCK_RPT_FORMAT) & R12A_CCK_RPT_FORMAT_HIPWR) + sc->sc_flags |= RTWN_FLAG_CCK_HIPWR; +} + +void +r12a_init_rf(struct rtwn_softc *sc) +{ + int chain, i; + + for (chain = 0, i = 0; chain < sc->nrxchains; chain++, i++) { + /* Write RF initialization values for this chain. */ + i += r92c_init_rf_chain(sc, &sc->rf_prog[i], chain); + } +} + +void +r12a_crystalcap_write(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + uint32_t reg; + uint8_t val; + + val = rs->crystalcap & 0x3f; + reg = rtwn_bb_read(sc, R92C_MAC_PHY_CTRL); + reg = RW(reg, R12A_MAC_PHY_CRYSTALCAP, val | (val << 6)); + rtwn_bb_write(sc, R92C_MAC_PHY_CTRL, reg); +} + +static void +r12a_rf_init_workaround(struct rtwn_softc *sc) +{ + + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R92C_RF_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | + R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R12A_RF_B_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_SDMRSTB); + rtwn_write_1(sc, R12A_RF_B_CTRL, + R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | + R92C_RF_CTRL_SDMRSTB); +} + +int +r12a_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + int ntries; + + r12a_rf_init_workaround(sc); + + /* Force PWM mode. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_SPS0_CTRL + 1, 0, 0x01)); + + /* Turn off ZCD. */ + RTWN_CHK(rtwn_setbits_2(sc, 0x014, 0x0180, 0)); + + /* Enable LDO normal mode. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_LPLDO_CTRL, R92C_LPLDO_CTRL_SLEEP, + 0)); + + /* GPIO 0...7 input mode. */ + RTWN_CHK(rtwn_write_1(sc, R92C_GPIO_IOSEL, 0)); + + /* GPIO 11...8 input mode. */ + RTWN_CHK(rtwn_write_1(sc, R92C_MAC_PINMUX_CFG, 0)); + + /* Enable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS, 0, 1)); + + /* Enable 8051. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + 0, R92C_SYS_FUNC_EN_CPUEN, 1)); + + /* Disable SW LPS. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APFM_RSM, 0, 1)); + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip power up\n"); + return (ETIMEDOUT); + } + + /* Disable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS, 0, 1)); + + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_APFM_ONMAC, 1)); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0x0000)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + return (0); +} + +void +r12a_power_off(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + int error, ntries; + + /* Stop Rx. */ + error = rtwn_write_1(sc, R92C_CR, 0); + if (error == ENXIO) /* hardware gone */ + return; + + /* Move card to Low Power state. */ + /* Block all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + + for (ntries = 0; ntries < 10; ntries++) { + /* Should be zero if no packet is transmitting. */ + if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0) + break; + + rtwn_delay(sc, 5000); + } + if (ntries == 10) { + device_printf(sc->sc_dev, "%s: failed to block Tx queues\n", + __func__); + return; + } + + /* Turn off 3-wire. */ + rtwn_write_1(sc, R12A_HSSI_PARAM1(0), 0x04); + rtwn_write_1(sc, R12A_HSSI_PARAM1(1), 0x04); + + /* CCK and OFDM are disabled, and clock are gated. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0); + + rtwn_delay(sc, 1); + + /* Reset whole BB. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); + + /* Reset MAC TRX. */ + rtwn_write_1(sc, R92C_CR, + R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN); + + /* check if removed later. (?) */ + rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1); + + /* Respond TxOK to scheduler */ + rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK); + + /* If firmware in ram code, do reset. */ +#ifndef RTWN_WITHOUT_UCODE + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) + r12a_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); +#endif + + /* Reset MCU. */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, + 0, 1); + rtwn_write_1(sc, R92C_MCUFWDL, 0); + + /* Move card to Disabled state. */ + /* Turn off 3-wire. */ + rtwn_write_1(sc, R12A_HSSI_PARAM1(0), 0x04); + rtwn_write_1(sc, R12A_HSSI_PARAM1(1), 0x04); + + /* Reset BB, close RF. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); + + rtwn_delay(sc, 1); + + /* SPS PWM mode. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0xff, + R92C_APS_FSMCO_SOP_RCK | R92C_APS_FSMCO_SOP_ABG, 3); + + /* ANA clock = 500k. */ + rtwn_setbits_1(sc, R92C_SYS_CLKR, R92C_SYS_CLKR_ANA8M, 0); + + /* Turn off MAC by HW state machine */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF, + 1); + for (ntries = 0; ntries < 10; ntries++) { + /* Wait until it will be disabled. */ + if ((rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_OFF) == 0) + break; + + rtwn_delay(sc, 5000); + } + if (ntries == 10) { + device_printf(sc->sc_dev, "%s: could not turn off MAC\n", + __func__); + return; + } + + /* Reset 8051. */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, + 0, 1); + + /* Fill the default value of host_CPU handshake field. */ + rtwn_write_1(sc, R92C_MCUFWDL, + R92C_MCUFWDL_EN | R92C_MCUFWDL_CHKSUM_RPT); + + rtwn_setbits_1(sc, R92C_GPIO_IO_SEL, 0xf0, 0xc0); + + /* GPIO 11 input mode, 10...8 output mode. */ + rtwn_write_1(sc, R92C_MAC_PINMUX_CFG, 0x07); + + /* GPIO 7...0, output = input */ + rtwn_write_1(sc, R92C_GPIO_OUT, 0); + + /* GPIO 7...0 output mode. */ + rtwn_write_1(sc, R92C_GPIO_IOSEL, 0xff); + + rtwn_write_1(sc, R92C_GPIO_MOD, 0); + + /* Turn on ZCD. */ + rtwn_setbits_2(sc, 0x014, 0, 0x0180); + + /* Force PFM mode. */ + rtwn_setbits_1(sc, R92C_SPS0_CTRL + 1, 0x01, 0); + + /* LDO sleep mode. */ + rtwn_setbits_1(sc, R92C_LPLDO_CTRL, 0, R92C_LPLDO_CTRL_SLEEP); + + /* ANA clock = 500k. */ + rtwn_setbits_1(sc, R92C_SYS_CLKR, R92C_SYS_CLKR_ANA8M, 0); + + /* SOP option to disable BG/MB. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0xff, + R92C_APS_FSMCO_SOP_RCK, 3); + + /* Disable RFC_0. */ + rtwn_setbits_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_RSTB, 0); + + /* Disable RFC_1. */ + rtwn_setbits_1(sc, R12A_RF_B_CTRL, R92C_RF_CTRL_RSTB, 0); + + /* Enable WL suspend. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_AFSM_HSUS, + 1); + + rs->rs_flags &= ~R12A_IQK_RUNNING; +} + +void +r12a_init_intr(struct rtwn_softc *sc) +{ + rtwn_write_4(sc, R88E_HIMR, 0); + rtwn_write_4(sc, R88E_HIMRE, 0); +} + +void +r12a_init_antsel(struct rtwn_softc *sc) +{ + uint32_t reg; + + rtwn_write_1(sc, R92C_LEDCFG2, 0x82); + rtwn_bb_setbits(sc, R92C_FPGA0_RFPARAM(0), 0, 0x2000); + reg = rtwn_bb_read(sc, R92C_FPGA0_RFIFACEOE(0)); + sc->sc_ant = MS(reg, R92C_FPGA0_RFIFACEOE0_ANT); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_led.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_led.c new file mode 100644 index 0000000000..63cdd76016 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_led.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_led.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + + +void +r12a_set_led(struct rtwn_softc *sc, int led, int on) +{ + /* XXX assume led #0 == LED_LINK */ + /* XXX antenna diversity */ + + if (led == RTWN_LED_LINK) { + rtwn_setbits_1(sc, R92C_LEDCFG0, 0x8f, + R12A_LEDCFG2_ENA | (on ? 0 : R92C_LEDCFG0_DIS)); + sc->ledlink = on; /* Save LED state. */ + } + + /* XXX leds #1/#2 ? */ +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_priv.h new file mode 100644 index 0000000000..77b7ca2ab3 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_priv.h @@ -0,0 +1,852 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_priv.h 310305 2016-12-20 01:13:11Z kevlo $ + */ + +#ifndef R12A_PRIV_H +#define R12A_PRIV_H + +/* + * MAC initialization values. + */ +#define RTL8812AU_MAC_PROG_START \ + { 0x010, 0x0c }, + +#define RTL8812AU_MAC_PROG_END \ + { 0x025, 0x0f }, { 0x072, 0x00 }, { 0x420, 0x80 }, { 0x428, 0x0a }, \ + { 0x429, 0x10 }, { 0x430, 0x00 }, { 0x431, 0x00 }, { 0x432, 0x00 }, \ + { 0x433, 0x01 }, { 0x434, 0x04 }, { 0x435, 0x05 }, { 0x436, 0x07 }, \ + { 0x437, 0x08 }, { 0x43c, 0x04 }, { 0x43d, 0x05 }, { 0x43e, 0x07 }, \ + { 0x43f, 0x08 }, { 0x440, 0x5d }, { 0x441, 0x01 }, { 0x442, 0x00 }, \ + { 0x444, 0x10 }, { 0x445, 0x00 }, { 0x446, 0x00 }, { 0x447, 0x00 }, \ + { 0x448, 0x00 }, { 0x449, 0xf0 }, { 0x44a, 0x0f }, { 0x44b, 0x3e }, \ + { 0x44c, 0x10 }, { 0x44d, 0x00 }, { 0x44e, 0x00 }, { 0x44f, 0x00 }, \ + { 0x450, 0x00 }, { 0x451, 0xf0 }, { 0x452, 0x0f }, { 0x453, 0x00 }, \ + { 0x45b, 0x80 }, { 0x460, 0x66 }, { 0x461, 0x66 }, { 0x4c8, 0xff }, \ + { 0x4c9, 0x08 }, { 0x4cc, 0xff }, { 0x4cd, 0xff }, { 0x4ce, 0x01 }, \ + { 0x500, 0x26 }, { 0x501, 0xa2 }, { 0x502, 0x2f }, { 0x503, 0x00 }, \ + { 0x504, 0x28 }, { 0x505, 0xa3 }, { 0x506, 0x5e }, { 0x507, 0x00 }, \ + { 0x508, 0x2b }, { 0x509, 0xa4 }, { 0x50a, 0x5e }, { 0x50b, 0x00 }, \ + { 0x50c, 0x4f }, { 0x50d, 0xa4 }, { 0x50e, 0x00 }, { 0x50f, 0x00 }, \ + { 0x512, 0x1c }, { 0x514, 0x0a }, { 0x516, 0x0a }, { 0x525, 0x4f }, \ + { 0x550, 0x10 }, { 0x551, 0x10 }, { 0x559, 0x02 }, { 0x55c, 0x50 }, \ + { 0x55d, 0xff }, { 0x604, 0x09 }, { 0x605, 0x30 }, { 0x607, 0x03 }, \ + { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x620, 0xff }, { 0x621, 0xff }, \ + { 0x622, 0xff }, { 0x623, 0xff }, { 0x624, 0xff }, { 0x625, 0xff }, \ + { 0x626, 0xff }, { 0x627, 0xff }, { 0x638, 0x50 }, { 0x63c, 0x0a }, \ + { 0x63d, 0x0a }, { 0x63e, 0x0e }, { 0x63f, 0x0e }, { 0x640, 0x80 }, \ + { 0x642, 0x40 }, { 0x643, 0x00 }, { 0x652, 0xc8 }, { 0x66e, 0x05 }, \ + { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 }, { 0x703, 0x87 }, \ + { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 }, { 0x70b, 0x87 }, \ + { 0x718, 0x40 } + +static const struct rtwn_mac_prog rtl8812au_mac_no_ext_pa_lna[] = { + RTL8812AU_MAC_PROG_START + { 0x11, 0x66 }, + RTL8812AU_MAC_PROG_END +}, rtl8812au_mac[] = { + RTL8812AU_MAC_PROG_START + { 0x11, 0x5a }, + RTL8812AU_MAC_PROG_END +}; + + +/* + * Baseband initialization values. + */ +#define R12A_COND_GPA 0x01 +#define R12A_COND_APA 0x02 +#define R12A_COND_GLNA 0x04 +#define R12A_COND_ALNA 0x08 +#define R12A_COND_TYPE(t) ((t) << 4) + +static const uint16_t rtl8812au_bb_regs0[] = { + 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x820, 0x824, + 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844, 0x848, + 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, 0x864, 0x868, 0x86c, + 0x870, 0x874, 0x878, 0x87c, 0x8a0, 0x8a4, 0x8a8, 0x8ac, 0x8b0, + 0x8b4, 0x8b8, 0x8bc, 0x8c0, 0x8c4, 0x8c8, 0x8cc, 0x8d0, 0x8dc, + 0x8d4, 0x8d8, 0x8f8, 0x8fc, 0x900, 0x90c, 0x910, 0x914, 0x918, + 0x91c, 0x920, 0x924, 0x928, 0x92c, 0x930, 0x934, 0x960, 0x964, + 0x968, 0x96c, 0x970, 0x978, 0x97c, 0x980, 0x984, 0x988, 0x990, + 0x994, 0x998, 0x99c, 0x9a0, 0x9a4, 0x9a8, 0x9ac, 0x9b0, 0x9b4, + 0x9b8, 0x9bc, 0x9d0, 0x9d4, 0x9d8, 0x9dc, 0x9e4, 0x9e8, 0xa00, + 0xa04, 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24, + 0xa28, 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xa84, 0xb00, + 0xb04, 0xb08, 0xb0c, 0xb10, 0xb14, 0xb18, 0xb1c, 0xb20, 0xb24, + 0xb28, 0xb2c, 0xb30, 0xb34, 0xb38, 0xb3c, 0xb40, 0xb44, 0xb48, + 0xb4c, 0xb50, 0xb54, 0xb58, 0xb5c, 0xc00, 0xc04, 0xc08, 0xc0c, + 0xc10, 0xc14, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, + 0xc38, 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, + 0xc5c, 0xc60, 0xc64 +}, rtl8812au_bb_regs1[] = { + 0xc68 +}, rtl8812au_bb_regs2[] = { + 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c, 0xc80, 0xc84, 0xc94, 0xc98, + 0xc9c, 0xca0, 0xca4, 0xca8, 0xcb0, 0xcb4, 0xcb8, 0xe00, 0xe04, + 0xe08, 0xe0c, 0xe10, 0xe14, 0xe1c, 0xe20, 0xe24, 0xe28, 0xe2c, + 0xe30, 0xe34, 0xe38, 0xe3c, 0xe40, 0xe44, 0xe48, 0xe4c, 0xe50, + 0xe54, 0xe58, 0xe5c, 0xe60, 0xe64, 0xe68, 0xe6c, 0xe70, 0xe74, + 0xe78, 0xe7c, 0xe80, 0xe84, 0xe94, 0xe98, 0xe9c, 0xea0, 0xea4, + 0xea8, 0xeb0, 0xeb4, 0xeb8 +}; + +static const uint32_t rtl8812au_bb_vals0[] = { + 0x8020d010, 0x080112e0, 0x0e028233, 0x12131113, 0x20101263, + 0x020c3d10, 0x03a00385, 0x00000000, 0x00030fe0, 0x00000000, + 0x002083dd, 0x2eaaeeb8, 0x0037a706, 0x06c89b44, 0x0000095b, + 0xc0000001, 0x40003cde, 0x6210ff8b, 0x6cfdffb8, 0x28874706, + 0x0001520c, 0x8060e000, 0x74210168, 0x6929c321, 0x79727432, + 0x8ca7a314, 0x338c2878, 0x03333333, 0x31602c2e, 0x00003152, + 0x000fc000, 0x00000013, 0x7f7f7f7f, 0xa202033e, 0x0ff0fa0a, + 0x00000600, 0x000fc080, 0x6c0057ff, 0x4ca520a3, 0x27f00020, + 0x00000000, 0x00012d69, 0x08248492, 0x0000b800, 0x00000000, + 0x940008a0, 0x290b5612, 0x400002c0, 0x00000000, 0x00000701, + 0x00000000, 0x0000fc00, 0x00000404, 0x1c1028c0, 0x64b11a1c, + 0xe0767233, 0x055aa500, 0x00000004, 0xfffe0000, 0xfffffffe, + 0x001fffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x801fffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x27100000, 0xffff0100, 0xffffff5c, 0xffffffff, + 0x000000ff, 0x00080080, 0x00000000, 0x00000000, 0x81081008, + 0x00000000, 0x01081008, 0x01081008, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000003, 0x000002d5, 0x00d047c8, + 0x01ff000c, 0x8c838300, 0x2e7f000f, 0x9500bb78, 0x11144028, + 0x00881117, 0x89140f00, 0x1a1b0000, 0x090e1217, 0x00000305, + 0x00900000, 0x101fff00, 0x00000008, 0x00000900, 0x225b0606, + 0x218075b2, 0x001f8c80, 0x03100000, 0x0000b000, 0xae0201eb, + 0x01003207, 0x00009807, 0x01000000, 0x00000002, 0x00000002, + 0x0000001f, 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, + 0x13121110, 0x17161514, 0x0000003a, 0x00000000, 0x00000000, + 0x13000032, 0x48080000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000007, 0x00042020, 0x80410231, 0x00000000, + 0x00000100, 0x01000000, 0x40000003, 0x12121212, 0x12121212, + 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, + 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, + 0x00000020, 0x0008121c, 0x30000c1c, 0x00000058, 0x34344443, + 0x07003333 +}, rtl8812au_bb_vals1_ext_pa_lna[] = { + 0x59791979 +}, rtl8812au_bb_vals1[] = { + 0x59799979 +}, rtl8812au_bb_vals2[] = { + 0x59795979, 0x19795979, 0x19795979, 0x19791979, 0x19791979, + 0x19791979, 0x19791979, 0x0100005c, 0x00000000, 0x00000000, + 0x00000029, 0x08040201, 0x80402010, 0x77547777, 0x00000077, + 0x00508242, 0x00000007, 0x00042020, 0x80410231, 0x00000000, + 0x00000100, 0x01000000, 0x40000003, 0x12121212, 0x12121212, + 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, + 0x12121212, 0x12121212, 0x12121212, 0x12121212, 0x12121212, + 0x00000020, 0x0008121c, 0x30000c1c, 0x00000058, 0x34344443, + 0x07003333, 0x59791979, 0x59795979, 0x19795979, 0x19795979, + 0x19791979, 0x19791979, 0x19791979, 0x19791979, 0x0100005c, + 0x00000000, 0x00000000, 0x00000029, 0x08040201, 0x80402010, + 0x77547777, 0x00000077, 0x00508242 +}; + +static const struct rtwn_bb_prog rtl8812au_bb[] = { + { + nitems(rtl8812au_bb_regs0), + rtl8812au_bb_regs0, + rtl8812au_bb_vals0, + { 0 }, + NULL + }, + /* + * Devices with: + * * External 2GHz PA, type 0; + * * External 5GHz PA, type 0 or 5; + * * External 2GHz LNA, type 0 or 5; + * * External 5GHz LNA, type 0; + */ + { + nitems(rtl8812au_bb_regs1), + rtl8812au_bb_regs1, + rtl8812au_bb_vals1_ext_pa_lna, + { + R12A_COND_GPA | R12A_COND_GLNA | + R12A_COND_APA | R12A_COND_ALNA | + R12A_COND_TYPE(0x0), + R12A_COND_APA | R12A_COND_GLNA | + R12A_COND_TYPE(0x5), 0 + }, + /* + * Others. + */ + &(const struct rtwn_bb_prog){ + nitems(rtl8812au_bb_regs1), + rtl8812au_bb_regs1, + rtl8812au_bb_vals1, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_bb_regs2), + rtl8812au_bb_regs2, + rtl8812au_bb_vals2, + { 0 }, + NULL + } +}; + + +static const uint32_t rtl8812au_agc_vals0_lna_g0[] = { + 0xfc000001, 0xfb020001, 0xfa040001, 0xf9060001, 0xf8080001, + 0xf70a0001, 0xf60c0001, 0xf50e0001, 0xf4100001, 0xf3120001, + 0xf2140001, 0xf1160001, 0xf0180001, 0xef1a0001, 0xee1c0001, + 0xed1e0001, 0xec200001, 0xeb220001, 0xea240001, 0xcd260001, + 0xcc280001, 0xcb2a0001, 0xca2c0001, 0xc92e0001, 0xc8300001, + 0xa6320001, 0xa5340001, 0xa4360001, 0xa3380001, 0xa23a0001, + 0x883c0001, 0x873e0001, 0x86400001, 0x85420001, 0x84440001, + 0x83460001, 0x82480001, 0x814a0001, 0x484c0001, 0x474e0001, + 0x46500001, 0x45520001, 0x44540001, 0x43560001, 0x42580001, + 0x415a0001, 0x255c0001, 0x245e0001, 0x23600001, 0x22620001, + 0x21640001, 0x21660001, 0x21680001, 0x216a0001, 0x216c0001, + 0x216e0001, 0x21700001, 0x21720001, 0x21740001, 0x21760001, + 0x21780001, 0x217a0001, 0x217c0001, 0x217e0001 +}, rtl8812au_agc_vals0_lna_g5[] = { + 0xf9000001, 0xf8020001, 0xf7040001, 0xf6060001, 0xf5080001, + 0xf40a0001, 0xf30c0001, 0xf20e0001, 0xf1100001, 0xf0120001, + 0xef140001, 0xee160001, 0xed180001, 0xec1a0001, 0xeb1c0001, + 0xea1e0001, 0xcd200001, 0xcc220001, 0xcb240001, 0xca260001, + 0xc9280001, 0xc82a0001, 0xc72c0001, 0xc62e0001, 0xa5300001, + 0xa4320001, 0xa3340001, 0xa2360001, 0x88380001, 0x873a0001, + 0x863c0001, 0x853e0001, 0x84400001, 0x83420001, 0x82440001, + 0x81460001, 0x48480001, 0x474a0001, 0x464c0001, 0x454e0001, + 0x44500001, 0x43520001, 0x42540001, 0x41560001, 0x25580001, + 0x245a0001, 0x235c0001, 0x225e0001, 0x21600001, 0x21620001, + 0x21640001, 0x21660001, 0x21680001, 0x216a0001, 0x236c0001, + 0x226e0001, 0x21700001, 0x21720001, 0x21740001, 0x21760001, + 0x21780001, 0x217a0001, 0x217c0001, 0x217e0001 +}, rtl8812au_agc_vals0[] = { + 0xff000001, 0xff020001, 0xff040001, 0xff060001, 0xff080001, + 0xfe0a0001, 0xfd0c0001, 0xfc0e0001, 0xfb100001, 0xfa120001, + 0xf9140001, 0xf8160001, 0xf7180001, 0xf61a0001, 0xf51c0001, + 0xf41e0001, 0xf3200001, 0xf2220001, 0xf1240001, 0xf0260001, + 0xef280001, 0xee2a0001, 0xed2c0001, 0xec2e0001, 0xeb300001, + 0xea320001, 0xe9340001, 0xe8360001, 0xe7380001, 0xe63a0001, + 0xe53c0001, 0xc73e0001, 0xc6400001, 0xc5420001, 0xc4440001, + 0xc3460001, 0xc2480001, 0xc14a0001, 0xa74c0001, 0xa64e0001, + 0xa5500001, 0xa4520001, 0xa3540001, 0xa2560001, 0xa1580001, + 0x675a0001, 0x665c0001, 0x655e0001, 0x64600001, 0x63620001, + 0x48640001, 0x47660001, 0x46680001, 0x456a0001, 0x446c0001, + 0x436e0001, 0x42700001, 0x41720001, 0x41740001, 0x41760001, + 0x41780001, 0x417a0001, 0x417c0001, 0x417e0001 +}, rtl8812au_agc_vals1_lna_a0[] = { + 0xfc800001, 0xfb820001, 0xfa840001, 0xf9860001, 0xf8880001, + 0xf78a0001, 0xf68c0001, 0xf58e0001, 0xf4900001, 0xf3920001, + 0xf2940001, 0xf1960001, 0xf0980001, 0xef9a0001, 0xee9c0001, + 0xed9e0001, 0xeca00001, 0xeba20001, 0xeaa40001, 0xe9a60001, + 0xe8a80001, 0xe7aa0001, 0xe6ac0001, 0xe5ae0001, 0xe4b00001, + 0xe3b20001, 0xa8b40001, 0xa7b60001, 0xa6b80001, 0xa5ba0001, + 0xa4bc0001, 0xa3be0001, 0xa2c00001, 0xa1c20001, 0x68c40001, + 0x67c60001, 0x66c80001, 0x65ca0001, 0x64cc0001, 0x47ce0001, + 0x46d00001, 0x45d20001, 0x44d40001, 0x43d60001, 0x42d80001, + 0x08da0001, 0x07dc0001, 0x06de0001, 0x05e00001, 0x04e20001, + 0x03e40001, 0x02e60001, 0x01e80001, 0x01ea0001, 0x01ec0001, + 0x01ee0001, 0x01f00001, 0x01f20001, 0x01f40001, 0x01f60001, + 0x01f80001, 0x01fa0001, 0x01fc0001, 0x01fe0001 +}, rtl8812au_agc_vals1[] = { + 0xff800001, 0xff820001, 0xff840001, 0xfe860001, 0xfd880001, + 0xfc8a0001, 0xfb8c0001, 0xfa8e0001, 0xf9900001, 0xf8920001, + 0xf7940001, 0xf6960001, 0xf5980001, 0xf49a0001, 0xf39c0001, + 0xf29e0001, 0xf1a00001, 0xf0a20001, 0xefa40001, 0xeea60001, + 0xeda80001, 0xecaa0001, 0xebac0001, 0xeaae0001, 0xe9b00001, + 0xe8b20001, 0xe7b40001, 0xe6b60001, 0xe5b80001, 0xe4ba0001, + 0xe3bc0001, 0xa8be0001, 0xa7c00001, 0xa6c20001, 0xa5c40001, + 0xa4c60001, 0xa3c80001, 0xa2ca0001, 0xa1cc0001, 0x68ce0001, + 0x67d00001, 0x66d20001, 0x65d40001, 0x64d60001, 0x47d80001, + 0x46da0001, 0x45dc0001, 0x44de0001, 0x43e00001, 0x42e20001, + 0x08e40001, 0x07e60001, 0x06e80001, 0x05ea0001, 0x04ec0001, + 0x03ee0001, 0x02f00001, 0x01f20001, 0x01f40001, 0x01f60001, + 0x01f80001, 0x01fa0001, 0x01fc0001, 0x01fe0001 +}; + +static const struct rtwn_agc_prog rtl8812au_agc[] = { + /* + * External 2GHz LNA (type 0). + */ + { + nitems(rtl8812au_agc_vals0_lna_g0), + rtl8812au_agc_vals0_lna_g0, + { R12A_COND_GLNA | R12A_COND_TYPE(0x0), 0 }, + /* + * External 2GHz LNA (type 5). + */ + &(const struct rtwn_agc_prog){ + nitems(rtl8812au_agc_vals0_lna_g5), + rtl8812au_agc_vals0_lna_g5, + { R12A_COND_GLNA | R12A_COND_TYPE(0x5), 0 }, + /* + * Others. + */ + &(const struct rtwn_agc_prog){ + nitems(rtl8812au_agc_vals0), + rtl8812au_agc_vals0, + { 0 }, + NULL + } + } + }, + /* + * External 5GHz LNA (type 0). + */ + { + nitems(rtl8812au_agc_vals1_lna_a0), + rtl8812au_agc_vals1_lna_a0, + { R12A_COND_ALNA | R12A_COND_TYPE(0x0), 0 }, + /* + * Others. + */ + &(const struct rtwn_agc_prog){ + nitems(rtl8812au_agc_vals1), + rtl8812au_agc_vals1, + { 0 }, + NULL + } + } +}; + +/* + * RF initialization values. + */ +static const uint8_t rtl8812au_rf0_regs0[] = { + 0x00, 0x18, 0x56, 0x66, 0x1e, 0x89 +}, rtl8812au_rf0_regs1[] = { + 0x86 +}, rtl8812au_rf0_regs2[] = { + 0x8b +}, rtl8812au_rf0_regs3[] = { + 0xb1, 0xb3, 0xb4, 0xba, 0x18, 0xef +}, rtl8812au_rf0_regs4[] = { + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b +}, rtl8812au_rf0_regs5[] = { + 0xef, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34 +}, rtl8812au_rf0_regs6[] = { + 0xef, 0xef, 0xdf, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0xef, + 0x51, 0x52, 0x53, 0x54, 0xef, 0x08, 0x18, 0xef, 0x3a, 0x3b, 0x3c, + 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, + 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, + 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, + 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, + 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, + 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, + 0x3a, 0x3b, 0x3c, 0xef +}, rtl8812au_rf0_regs7[] = { + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34 +}, rtl8812au_rf0_regs8[] = { + 0xef, 0x18, 0xef, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, + 0x35, 0xef, 0x18, 0xef, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0xef, 0xef, 0x3c, 0x3c, 0x3c, +}, rtl8812au_rf0_regs9[] = { + 0xef, 0x18, 0xef, 0xdf, 0x1f +}, rtl8812au_rf0_regs10[] = { + 0x61, 0x62, 0x63, 0x64, 0x65 +}, rtl8812au_rf0_regs11[] = { + 0x08, 0x1c, 0xb4, 0x18, 0xfe, 0xfe, 0xfe, 0xfe, 0xb4, 0x18 +}, rtl8812au_rf1_regs0[] = { + 0x56, 0x66, 0x89 +}, rtl8812au_rf1_regs3[] = { + 0xb1, 0xb3, 0xb4, 0xba, 0x18, 0xef +}; + +static const uint32_t rtl8812au_rf0_vals0[] = { + 0x10000, 0x1712a, 0x51cf2, 0x40000, 0x80000, 0x00080 +}, rtl8812au_rf0_vals1_lna_g0_g5[] = { + 0x14b3a +}, rtl8812au_rf0_vals1[] = { + 0x14b38 +}, rtl8812au_rf0_vals2_lna_a0[] = { + 0x80180 +}, rtl8812au_rf0_vals2[] = { + 0x87180 +}, rtl8812au_rf0_vals3[] = { + 0x1fc1a, 0xf0810, 0x1a78d, 0x86180, 0x00006, 0x02000 +}, rtl8812au_rf0_vals4_lna_g0_g5[] = { + 0x3f218, 0x30a58, 0x2fa58, 0x22590, 0x1fa50, 0x10248, 0x08240 +}, rtl8812au_rf0_vals4[] = { + 0x38a58, 0x37a58, 0x2a590, 0x27a50, 0x18248, 0x10240, 0x08240 +}, rtl8812au_rf0_vals5_pa_g0[] = { + 0x00100, 0x0a4ee, 0x09076, 0x08073, 0x07070, 0x0606d, 0x0506a, + 0x04049, 0x03046, 0x02028, 0x01025, 0x00022 +}, rtl8812au_rf0_vals5[] = { + 0x00100, 0x0adf4, 0x09df1, 0x08dee, 0x07deb, 0x06de8, 0x05de5, + 0x04de2, 0x03ce6, 0x024e7, 0x014e4, 0x004e1 +}, rtl8812au_rf0_vals6[] = { + 0x00000, 0x020a2, 0x00080, 0x00192, 0x08192, 0x10192, 0x00024, + 0x08024, 0x10024, 0x18024, 0x00000, 0x00c21, 0x006d9, 0xfc649, + 0x0017e, 0x00002, 0x08400, 0x1712a, 0x01000, 0x00080, 0x3a02c, + 0x04000, 0x00400, 0x3202c, 0x10000, 0x000a0, 0x2b064, 0x04000, + 0x000d8, 0x23070, 0x04000, 0x00468, 0x1b870, 0x10000, 0x00098, + 0x12085, 0xe4000, 0x00418, 0x0a080, 0xf0000, 0x00418, 0x02080, + 0x10000, 0x00080, 0x7a02c, 0x04000, 0x00400, 0x7202c, 0x10000, + 0x000a0, 0x6b064, 0x04000, 0x000d8, 0x63070, 0x04000, 0x00468, + 0x5b870, 0x10000, 0x00098, 0x52085, 0xe4000, 0x00418, 0x4a080, + 0xf0000, 0x00418, 0x42080, 0x10000, 0x00080, 0xba02c, 0x04000, + 0x00400, 0xb202c, 0x10000, 0x000a0, 0xab064, 0x04000, 0x000d8, + 0xa3070, 0x04000, 0x00468, 0x9b870, 0x10000, 0x00098, 0x92085, + 0xe4000, 0x00418, 0x8a080, 0xf0000, 0x00418, 0x82080, 0x10000, + 0x01100 +}, rtl8812au_rf0_vals7_pa_a0[] = { + 0x4a0b2, 0x490af, 0x48070, 0x4706d, 0x46050, 0x4504d, 0x4404a, + 0x43047, 0x4200a, 0x41007, 0x40004, 0x2a0b2, 0x290af, 0x28070, + 0x2706d, 0x26050, 0x2504d, 0x2404a, 0x23047, 0x2200a, 0x21007, + 0x20004, 0x0a0b2, 0x090af, 0x08070, 0x0706d, 0x06050, 0x0504d, + 0x0404a, 0x03047, 0x0200a, 0x01007, 0x00004 +}, rtl8812au_rf0_vals7_pa_a5[] = { + 0x4a0b2, 0x490af, 0x48070, 0x4706d, 0x4604d, 0x4504a, 0x44047, + 0x43044, 0x42007, 0x41004, 0x40001, 0x2a0b4, 0x290b1, 0x28072, + 0x2706f, 0x2604f, 0x2504c, 0x24049, 0x23046, 0x22009, 0x21006, + 0x20003, 0x0a0b2, 0x090af, 0x08070, 0x0706d, 0x0604d, 0x0504a, + 0x04047, 0x03044, 0x02007, 0x01004, 0x00001 +}, rtl8812au_rf0_vals7[] = { + 0x4adf5, 0x49df2, 0x48def, 0x47dec, 0x46de9, 0x45de6, 0x44de3, + 0x438c8, 0x428c5, 0x418c2, 0x408c0, 0x2adf5, 0x29df2, 0x28def, + 0x27dec, 0x26de9, 0x25de6, 0x24de3, 0x238c8, 0x228c5, 0x218c2, + 0x208c0, 0x0aff7, 0x09df7, 0x08df4, 0x07df1, 0x06dee, 0x05deb, + 0x04de8, 0x038cc, 0x028c9, 0x018c6, 0x008c3 +}, rtl8812au_rf0_vals8_pa_a0_a5[] = { + 0x00000, 0x1712a, 0x00040, 0x001d4, 0x081d4, 0x101d4, 0x201b4, + 0x281b4, 0x301b4, 0x401b4, 0x481b4, 0x501b4, 0x00000, 0x1712a, + 0x00010, 0x04bfb, 0x0cbfb, 0x14bfb, 0x1cbfb, 0x24f4b, 0x2cf4b, + 0x34f4b, 0x3cf4b, 0x44f4b, 0x4cf4b, 0x54f4b, 0x5cf4b, 0x00000, + 0x00008, 0x002cc, 0x00522, 0x00902 +}, rtl8812au_rf0_vals8[] = { + 0x00000, 0x1712a, 0x00040, 0x00188, 0x08147, 0x10147, 0x201d7, + 0x281d7, 0x301d7, 0x401d8, 0x481d8, 0x501d8, 0x00000, 0x1712a, + 0x00010, 0x84eb4, 0x8cc35, 0x94c35, 0x9cc35, 0xa4c35, 0xacc35, + 0xb4c35, 0xbcc35, 0xc4c34, 0xccc35, 0xd4c35, 0xdcc35, 0x00000, + 0x00008, 0x002a8, 0x005a2, 0x00880 +}, rtl8812au_rf0_vals9[] = { + 0x00000, 0x1712a, 0x00002, 0x00080, 0x00064 +}, rtl8812au_rf0_vals10_pa_a0[] = { + 0xfdd43, 0x38f4b, 0x32117, 0x194ac, 0x931d1 +}, rtl8812au_rf0_vals10_pa_a5[] = { + 0xfdd43, 0x38f4b, 0x32117, 0x194ac, 0x931d2 +}, rtl8812au_rf0_vals10[] = { + 0xe5d53, 0x38fcd, 0x114eb, 0x196ac, 0x911d7 +}, rtl8812au_rf0_vals11[] = { + 0x08400, 0x739d2, 0x1e78d, 0x1f12a, 0x0c350, 0x0c350, 0x0c350, + 0x0c350, 0x1a78d, 0x1712a +}, rtl8812au_rf1_vals0[] = { + 0x51cf2, 0x40000, 0x00080 +}, rtl8812au_rf1_vals3[] = { + 0x1fc1a, 0xf0810, 0x1a78d, 0x86180, 0x00006, 0x02000 +}, rtl8812au_rf1_vals6[] = { + 0x00000, 0x020a2, 0x00080, 0x00192, 0x08192, 0x10192, 0x00024, + 0x08024, 0x10024, 0x18024, 0x00000, 0x00c21, 0x006d9, 0xfc649, + 0x0017e, 0x00002, 0x08400, 0x1712a, 0x01000, 0x00080, 0x3a02c, + 0x04000, 0x00400, 0x3202c, 0x10000, 0x000a0, 0x2b064, 0x04000, + 0x000d8, 0x23070, 0x04000, 0x00468, 0x1b870, 0x10000, 0x00098, + 0x12085, 0xe4000, 0x00418, 0x0a080, 0xf0000, 0x00418, 0x02080, + 0x10000, 0x00080, 0x7a02c, 0x04000, 0x00400, 0x7202c, 0x10000, + 0x000a0, 0x6b064, 0x04000, 0x000d8, 0x63070, 0x04000, 0x00468, + 0x5b870, 0x10000, 0x00098, 0x52085, 0xe4000, 0x00418, 0x4a080, + 0xf0000, 0x00418, 0x42080, 0x10000, 0x00080, 0xba02c, 0x04000, + 0x00400, 0xb202c, 0x10000, 0x000a0, 0xab064, 0x04000, 0x000d8, + 0xa3070, 0x04000, 0x00468, 0x9b870, 0x10000, 0x00098, 0x92085, + 0xe4000, 0x00418, 0x8a080, 0xf0000, 0x00418, 0x82080, 0x10000, + 0x01100 +}, rtl8812au_rf1_vals7_pa_a5[] = { + 0x4a0b1, 0x490ae, 0x4806f, 0x4706c, 0x4604c, 0x45049, 0x44046, + 0x43043, 0x42006, 0x41003, 0x40000, 0x2a0b3, 0x290b0, 0x28071, + 0x2706e, 0x2604e, 0x2504b, 0x24048, 0x23045, 0x22008, 0x21005, + 0x20002, 0x0a0b3, 0x090b0, 0x08070, 0x0706d, 0x0604d, 0x0504a, + 0x04047, 0x03044, 0x02007, 0x01004, 0x00001 +}, rtl8812au_rf1_vals8_pa_a0_a5[] = { + 0x00000, 0x1712a, 0x00040, 0x001c5, 0x081c5, 0x101c5, 0x20174, + 0x28174, 0x30174, 0x40185, 0x48185, 0x50185, 0x00000, 0x1712a, + 0x00010, 0x05b8b, 0x0db8b, 0x15b8b, 0x1db8b, 0x262db, 0x2e2db, + 0x362db, 0x3e2db, 0x4553b, 0x4d53b, 0x5553b, 0x5d53b, 0x00000, + 0x00008, 0x002dc, 0x00524, 0x00902 +}, rtl8812au_rf1_vals10_pa_g0_a0[] = { + 0xeac43, 0x38f47, 0x31157, 0x1c4ac, 0x931d1 +}, rtl8812au_rf1_vals10_pa_a5[] = { + 0xeac43, 0x38f47, 0x31157, 0x1c4ac, 0x931d2 +}; + +static const struct rtwn_rf_prog rtl8812au_rf[] = { + /* RF chain 0. */ + { + nitems(rtl8812au_rf0_regs0), + rtl8812au_rf0_regs0, + rtl8812au_rf0_vals0, + { 0 }, + NULL + }, + /* External 2GHz LNA, type 0 or 5. */ + { + nitems(rtl8812au_rf0_regs1), + rtl8812au_rf0_regs1, + rtl8812au_rf0_vals1_lna_g0_g5, + { + R12A_COND_GLNA | R12A_COND_TYPE(0x0), + R12A_COND_GLNA | R12A_COND_TYPE(0x5), 0 + }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs1), + rtl8812au_rf0_regs1, + rtl8812au_rf0_vals1, + { 0 }, + NULL + } + }, + /* External 5GHz LNA, type 0. */ + { + nitems(rtl8812au_rf0_regs2), + rtl8812au_rf0_regs2, + rtl8812au_rf0_vals2_lna_a0, + { R12A_COND_ALNA | R12A_COND_TYPE(0x0), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs2), + rtl8812au_rf0_regs2, + rtl8812au_rf0_vals2, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_rf0_regs3), + rtl8812au_rf0_regs3, + rtl8812au_rf0_vals3, + { 0 }, + NULL + }, + /* External 2GHz LNA, type 0 or 5. */ + { + nitems(rtl8812au_rf0_regs4), + rtl8812au_rf0_regs4, + rtl8812au_rf0_vals4_lna_g0_g5, + { + R12A_COND_GLNA | R12A_COND_TYPE(0x0), + R12A_COND_GLNA | R12A_COND_TYPE(0x5), 0 + }, + /* Others */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs4), + rtl8812au_rf0_regs4, + rtl8812au_rf0_vals4, + { 0 }, + NULL + } + }, + /* External 2GHz PA, type 0. */ + { + nitems(rtl8812au_rf0_regs5), + rtl8812au_rf0_regs5, + rtl8812au_rf0_vals5_pa_g0, + { R12A_COND_GPA | R12A_COND_TYPE(0x0), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs5), + rtl8812au_rf0_regs5, + rtl8812au_rf0_vals5, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_rf0_regs6), + rtl8812au_rf0_regs6, + rtl8812au_rf0_vals6, + { 0 }, + NULL + }, + /* External 5GHz PA, type 0. */ + { + nitems(rtl8812au_rf0_regs7), + rtl8812au_rf0_regs7, + rtl8812au_rf0_vals7_pa_a0, + { R12A_COND_APA | R12A_COND_TYPE(0x0), 0 }, + /* External 5GHz PA, type 5. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs7), + rtl8812au_rf0_regs7, + rtl8812au_rf0_vals7_pa_a5, + { R12A_COND_APA | R12A_COND_TYPE(0x5), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs7), + rtl8812au_rf0_regs7, + rtl8812au_rf0_vals7, + { 0 }, + NULL + } + } + }, + /* External 5GHz PA, type 0 or 5. */ + { + nitems(rtl8812au_rf0_regs8), + rtl8812au_rf0_regs8, + rtl8812au_rf0_vals8_pa_a0_a5, + { + R12A_COND_APA | R12A_COND_TYPE(0x0), + R12A_COND_APA | R12A_COND_TYPE(0x5), 0 + }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs8), + rtl8812au_rf0_regs8, + rtl8812au_rf0_vals8, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_rf0_regs9), + rtl8812au_rf0_regs9, + rtl8812au_rf0_vals9, + { 0 }, + NULL + }, + /* External 5GHz PA, type 0. */ + { + nitems(rtl8812au_rf0_regs10), + rtl8812au_rf0_regs10, + rtl8812au_rf0_vals10_pa_a0, + { R12A_COND_APA | R12A_COND_TYPE(0x0), 0 }, + /* External 5GHz PA, type 5. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs10), + rtl8812au_rf0_regs10, + rtl8812au_rf0_vals10_pa_a5, + { R12A_COND_APA | R12A_COND_TYPE(0x5), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs10), + rtl8812au_rf0_regs10, + rtl8812au_rf0_vals10, + { 0 }, + NULL + } + } + }, + { + nitems(rtl8812au_rf0_regs11), + rtl8812au_rf0_regs11, + rtl8812au_rf0_vals11, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL }, + /* RF chain 1. */ + { + nitems(rtl8812au_rf1_regs0), + rtl8812au_rf1_regs0, + rtl8812au_rf1_vals0, + { 0 }, + NULL + }, + /* rtl8812au_rf[1] */ + /* External 2GHz LNA, type 0 or 5. */ + { + nitems(rtl8812au_rf0_regs1), + rtl8812au_rf0_regs1, + rtl8812au_rf0_vals1_lna_g0_g5, + { + R12A_COND_GLNA | R12A_COND_TYPE(0x0), + R12A_COND_GLNA | R12A_COND_TYPE(0x5), 0 + }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs1), + rtl8812au_rf0_regs1, + rtl8812au_rf0_vals1, + { 0 }, + NULL + } + }, + /* rtl8812au_rf[2] */ + /* External 5GHz LNA, type 0. */ + { + nitems(rtl8812au_rf0_regs2), + rtl8812au_rf0_regs2, + rtl8812au_rf0_vals2_lna_a0, + { R12A_COND_ALNA | R12A_COND_TYPE(0x0), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs2), + rtl8812au_rf0_regs2, + rtl8812au_rf0_vals2, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_rf1_regs3), + rtl8812au_rf1_regs3, + rtl8812au_rf1_vals3, + { 0 }, + NULL + }, + /* rtl8812au_rf[4] */ + /* External 2GHz LNA, type 0 or 5. */ + { + nitems(rtl8812au_rf0_regs4), + rtl8812au_rf0_regs4, + rtl8812au_rf0_vals4_lna_g0_g5, + { + R12A_COND_GLNA | R12A_COND_TYPE(0x0), + R12A_COND_GLNA | R12A_COND_TYPE(0x5), 0 + }, + /* Others */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs4), + rtl8812au_rf0_regs4, + rtl8812au_rf0_vals4, + { 0 }, + NULL + } + }, + /* rtl8812au_rf[5] */ + /* External 2GHz PA, type 0. */ + { + nitems(rtl8812au_rf0_regs5), + rtl8812au_rf0_regs5, + rtl8812au_rf0_vals5_pa_g0, + { R12A_COND_GPA | R12A_COND_TYPE(0x0), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs5), + rtl8812au_rf0_regs5, + rtl8812au_rf0_vals5, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_rf0_regs6), + rtl8812au_rf0_regs6, + rtl8812au_rf1_vals6, + { 0 }, + NULL + }, + /* External 5GHz PA, type 0. */ + { + nitems(rtl8812au_rf0_regs7), + rtl8812au_rf0_regs7, + rtl8812au_rf0_vals7_pa_a0, + { R12A_COND_APA | R12A_COND_TYPE(0x0), 0 }, + /* External 5GHz PA, type 5. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs7), + rtl8812au_rf0_regs7, + rtl8812au_rf1_vals7_pa_a5, + { R12A_COND_APA | R12A_COND_TYPE(0x5), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs7), + rtl8812au_rf0_regs7, + rtl8812au_rf0_vals7, + { 0 }, + NULL + } + } + }, + /* External 5GHz PA, type 0 or 5. */ + { + nitems(rtl8812au_rf0_regs8), + rtl8812au_rf0_regs8, + rtl8812au_rf1_vals8_pa_a0_a5, + { + R12A_COND_APA | R12A_COND_TYPE(0x0), + R12A_COND_APA | R12A_COND_TYPE(0x5), 0 + }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs8), + rtl8812au_rf0_regs8, + rtl8812au_rf0_vals8, + { 0 }, + NULL + } + }, + { + nitems(rtl8812au_rf0_regs9) - 1, + rtl8812au_rf0_regs9, + rtl8812au_rf0_vals9, + { 0 }, + NULL + }, + + /* External 2GHz or 5GHz PA, type 0. */ + { + nitems(rtl8812au_rf0_regs10), + rtl8812au_rf0_regs10, + rtl8812au_rf1_vals10_pa_g0_a0, + { + R12A_COND_GPA | R12A_COND_TYPE(0x0), + R12A_COND_APA | R12A_COND_TYPE(0x0), 0 + }, + /* External 5GHz PA, type 5. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs10), + rtl8812au_rf0_regs10, + rtl8812au_rf1_vals10_pa_a5, + { R12A_COND_APA | R12A_COND_TYPE(0x5), 0 }, + /* Others. */ + &(const struct rtwn_rf_prog){ + nitems(rtl8812au_rf0_regs10), + rtl8812au_rf0_regs10, + rtl8812au_rf0_vals10, + { 0 }, + NULL + } + } + }, + { + 1, + rtl8812au_rf0_regs11, + rtl8812au_rf0_vals11, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL } +}; + + +/* + * Registers to save before IQ calibration. + */ +static const uint16_t r12a_iq_bb_regs[] = { + 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0xe00, 0x838, 0x82c +}; + +static const uint16_t r12a_iq_afe_regs[] = { + 0xc5c, 0xc60, 0xc64, 0xc68, 0xcb0, 0xcb4, 0xe5c, 0xe60, 0xe64, + 0xe68, 0xeb0, 0xeb4 +}; + +static const uint8_t r12a_iq_rf_regs[] = { + 0x65, 0x8f, 0x0 +}; + +#endif /* R12A_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_reg.h new file mode 100644 index 0000000000..0baf583892 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_reg.h @@ -0,0 +1,246 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_reg.h 335351 2018-06-19 00:38:28Z avos $ + */ + +#ifndef R12A_REG_H +#define R12A_REG_H + +#include + +/* + * MAC registers. + */ +/* System Configuration. */ +#define R12A_SDIO_CTRL 0x070 +#define R12A_RF_B_CTRL 0x076 +/* Rx DMA Configuration. */ +#define R12A_RXDMA_PRO 0x290 +#define R12A_EARLY_MODE_CONTROL 0x2bc +/* Protocol Configuration. */ +#define R12A_TXPKT_EMPTY 0x41a +#define R12A_ARFR_5G(i) (0x444 + (i) * 8) +#define R12A_CCK_CHECK 0x454 +#define R12A_AMPDU_MAX_TIME 0x456 +#define R12A_AMPDU_MAX_LENGTH R92C_AGGLEN_LMT +#define R12A_DATA_SEC 0x483 +#define R12A_ARFR_2G(i) (0x48c + (i) * 8) +#define R12A_HT_SINGLE_AMPDU 0x4c7 + + +/* Bits for R92C_MAC_PHY_CTRL. */ +#define R12A_MAC_PHY_CRYSTALCAP_M 0x7ff80000 +#define R12A_MAC_PHY_CRYSTALCAP_S 19 + +/* Bits for R92C_LEDCFG2. */ +#define R12A_LEDCFG2_ENA 0x20 + +/* Bits for R12A_RXDMA_PRO. */ +#define R12A_DMA_MODE 0x02 +#define R12A_BURST_CNT_M 0x0c +#define R12A_BURST_CNT_S 2 +#define R12A_BURST_SZ_M 0x30 +#define R12A_BURST_SZ_S 4 +#define R12A_BURST_SZ_USB3 0 +#define R12A_BURST_SZ_USB2 1 +#define R12A_BURST_SZ_USB1 2 + +/* Bits for R12A_CCK_CHECK. */ +#define R12A_CCK_CHECK_BCN1 0x20 +#define R12A_CCK_CHECK_5GHZ 0x80 + +/* Bits for R12A_DATA_SEC. */ +#define R12A_DATA_SEC_NO_EXT 0x00 +#define R12A_DATA_SEC_PRIM_UP_20 0x01 +#define R12A_DATA_SEC_PRIM_DOWN_20 0x02 +#define R12A_DATA_SEC_PRIM_UPPER_20 0x03 +#define R12A_DATA_SEC_PRIM_LOWER_20 0x04 +#define R12A_DATA_SEC_PRIM_UP_40 0x90 +#define R12A_DATA_SEC_PRIM_DOWN_40 0xa0 + +/* Bits for R12A_HT_SINGLE_AMPDU. */ +#define R12A_HT_SINGLE_AMPDU_PKT_ENA 0x80 + +/* Bits for R92C_RCR. */ +#define R12A_RCR_DIS_CHK_14 0x00200000 +#define R12A_RCR_TCP_OFFLD_EN 0x02000000 +#define R12A_RCR_VHT_ACK 0x04000000 + + +/* + * Baseband registers. + */ +#define R12A_CCK_RPT_FORMAT 0x804 +#define R12A_OFDMCCK_EN 0x808 +#define R12A_RX_PATH R12A_OFDMCCK_EN +#define R12A_TX_PATH 0x80c +#define R12A_TXAGC_TABLE_SELECT 0x82c +#define R12A_PWED_TH 0x830 +#define R12A_BW_INDICATION 0x834 +#define R12A_CCA_ON_SEC 0x838 +#define R12A_L1_PEAK_TH 0x848 +#define R12A_FC_AREA 0x860 +#define R12A_RFMOD 0x8ac +#define R12A_HSSI_PARAM2 0x8b0 +#define R12A_ADC_BUF_CLK 0x8c4 +#define R12A_ANTSEL_SW 0x900 +#define R12A_SINGLETONE_CONT_TX 0x914 +#define R12A_CCK_RX_PATH 0xa04 +#define R12A_HSSI_PARAM1(chain) (0xc00 + (chain) * 0x200) +#define R12A_TX_SCALE(chain) (0xc1c + (chain) * 0x200) +#define R12A_TXAGC_CCK11_1(chain) (0xc20 + (chain) * 0x200) +#define R12A_TXAGC_OFDM18_6(chain) (0xc24 + (chain) * 0x200) +#define R12A_TXAGC_OFDM54_24(chain) (0xc28 + (chain) * 0x200) +#define R12A_TXAGC_MCS3_0(chain) (0xc2c + (chain) * 0x200) +#define R12A_TXAGC_MCS7_4(chain) (0xc30 + (chain) * 0x200) +#define R12A_TXAGC_MCS11_8(chain) (0xc34 + (chain) * 0x200) +#define R12A_TXAGC_MCS15_12(chain) (0xc38 + (chain) * 0x200) +#define R12A_TXAGC_NSS1IX3_1IX0(chain) (0xc3c + (chain) * 0x200) +#define R12A_TXAGC_NSS1IX7_1IX4(chain) (0xc40 + (chain) * 0x200) +#define R12A_TXAGC_NSS2IX1_1IX8(chain) (0xc44 + (chain) * 0x200) +#define R12A_TXAGC_NSS2IX5_2IX2(chain) (0xc48 + (chain) * 0x200) +#define R12A_TXAGC_NSS2IX9_2IX6(chain) (0xc4c + (chain) * 0x200) +#define R12A_INITIAL_GAIN(chain) (0xc50 + (chain) * 0x200) +#define R12A_AFE_POWER_1(chain) (0xc60 + (chain) * 0x200) +#define R12A_AFE_POWER_2(chain) (0xc64 + (chain) * 0x200) +#define R12A_SLEEP_NAV(chain) (0xc80 + (chain) * 0x200) +#define R12A_PMPD(chain) (0xc84 + (chain) * 0x200) +#define R12A_LSSI_PARAM(chain) (0xc90 + (chain) * 0x200) +#define R12A_RFE_PINMUX(chain) (0xcb0 + (chain) * 0x200) +#define R12A_RFE_INV(chain) (0xcb4 + (chain) * 0x200) +#define R12A_RFE(chain) (0xcb8 + (chain) * 0x200) +#define R12A_HSPI_READBACK(chain) (0xd04 + (chain) * 0x40) +#define R12A_LSSI_READBACK(chain) (0xd08 + (chain) * 0x40) + +/* Bits for R12A_CCK_RPT_FORMAT. */ +#define R12A_CCK_RPT_FORMAT_HIPWR 0x00010000 + +/* Bits for R12A_OFDMCCK_EN. */ +#define R12A_OFDMCCK_EN_CCK 0x10000000 +#define R12A_OFDMCCK_EN_OFDM 0x20000000 + +/* Bits for R12A_CCA_ON_SEC. */ +#define R12A_CCA_ON_SEC_EXT_CHAN_M 0xf0000000 +#define R12A_CCA_ON_SEC_EXT_CHAN_S 28 + +/* Bits for R12A_RFE_PINMUX(i). */ +#define R12A_RFE_PINMUX_PA_A_MASK 0x000000f0 +#define R12A_RFE_PINMUX_LNA_MASK 0x0000f000 + +/* Bits for R12A_RFMOD. */ +#define R12A_RFMOD_EXT_CHAN_M 0x3C +#define R12A_RFMOD_EXT_CHAN_S 2 + +/* Bits for R12A_HSSI_PARAM2. */ +#define R12A_HSSI_PARAM2_READ_ADDR_MASK 0xff + +/* Bits for R12A_HSSI_PARAM1(i). */ +#define R12A_HSSI_PARAM1_PI 0x00000004 + +/* Bits for R12A_TX_SCALE(i). */ +#define R12A_TX_SCALE_SWING_M 0xffe00000 +#define R12A_TX_SCALE_SWING_S 21 + +/* Bits for R12A_TXAGC_CCK11_1(i). */ +#define R12A_TXAGC_CCK1_M 0x000000ff +#define R12A_TXAGC_CCK1_S 0 +#define R12A_TXAGC_CCK2_M 0x0000ff00 +#define R12A_TXAGC_CCK2_S 8 +#define R12A_TXAGC_CCK55_M 0x00ff0000 +#define R12A_TXAGC_CCK55_S 16 +#define R12A_TXAGC_CCK11_M 0xff000000 +#define R12A_TXAGC_CCK11_S 24 + +/* Bits for R12A_TXAGC_OFDM18_6(i). */ +#define R12A_TXAGC_OFDM06_M 0x000000ff +#define R12A_TXAGC_OFDM06_S 0 +#define R12A_TXAGC_OFDM09_M 0x0000ff00 +#define R12A_TXAGC_OFDM09_S 8 +#define R12A_TXAGC_OFDM12_M 0x00ff0000 +#define R12A_TXAGC_OFDM12_S 16 +#define R12A_TXAGC_OFDM18_M 0xff000000 +#define R12A_TXAGC_OFDM18_S 24 + +/* Bits for R12A_TXAGC_OFDM54_24(i). */ +#define R12A_TXAGC_OFDM24_M 0x000000ff +#define R12A_TXAGC_OFDM24_S 0 +#define R12A_TXAGC_OFDM36_M 0x0000ff00 +#define R12A_TXAGC_OFDM36_S 8 +#define R12A_TXAGC_OFDM48_M 0x00ff0000 +#define R12A_TXAGC_OFDM48_S 16 +#define R12A_TXAGC_OFDM54_M 0xff000000 +#define R12A_TXAGC_OFDM54_S 24 + +/* Bits for R12A_TXAGC_MCS3_0(i). */ +#define R12A_TXAGC_MCS0_M 0x000000ff +#define R12A_TXAGC_MCS0_S 0 +#define R12A_TXAGC_MCS1_M 0x0000ff00 +#define R12A_TXAGC_MCS1_S 8 +#define R12A_TXAGC_MCS2_M 0x00ff0000 +#define R12A_TXAGC_MCS2_S 16 +#define R12A_TXAGC_MCS3_M 0xff000000 +#define R12A_TXAGC_MCS3_S 24 + +/* Bits for R12A_TXAGC_MCS7_4(i). */ +#define R12A_TXAGC_MCS4_M 0x000000ff +#define R12A_TXAGC_MCS4_S 0 +#define R12A_TXAGC_MCS5_M 0x0000ff00 +#define R12A_TXAGC_MCS5_S 8 +#define R12A_TXAGC_MCS6_M 0x00ff0000 +#define R12A_TXAGC_MCS6_S 16 +#define R12A_TXAGC_MCS7_M 0xff000000 +#define R12A_TXAGC_MCS7_S 24 + +/* Bits for R12A_TXAGC_MCS11_8(i). */ +#define R12A_TXAGC_MCS8_M 0x000000ff +#define R12A_TXAGC_MCS8_S 0 +#define R12A_TXAGC_MCS9_M 0x0000ff00 +#define R12A_TXAGC_MCS9_S 8 +#define R12A_TXAGC_MCS10_M 0x00ff0000 +#define R12A_TXAGC_MCS10_S 16 +#define R12A_TXAGC_MCS11_M 0xff000000 +#define R12A_TXAGC_MCS11_S 24 + +/* Bits for R12A_TXAGC_MCS15_12(i). */ +#define R12A_TXAGC_MCS12_M 0x000000ff +#define R12A_TXAGC_MCS12_S 0 +#define R12A_TXAGC_MCS13_M 0x0000ff00 +#define R12A_TXAGC_MCS13_S 8 +#define R12A_TXAGC_MCS14_M 0x00ff0000 +#define R12A_TXAGC_MCS14_S 16 +#define R12A_TXAGC_MCS15_M 0xff000000 +#define R12A_TXAGC_MCS15_S 24 + + +/* + * RF (6052) registers. + */ +#define R12A_RF_LCK 0xb4 + +/* Bits for R12A_RF_LCK. */ +#define R12A_RF_LCK_MODE 0x4000 + +#endif /* R12A_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rf.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rf.c new file mode 100644 index 0000000000..bfa7126598 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rf.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_rf.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +uint32_t +r12a_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) +{ + uint32_t pi_mode, val; + + /* Turn off CCA (avoids reading the wrong value). */ + if (addr != R92C_RF_AC) + rtwn_bb_setbits(sc, R12A_CCA_ON_SEC, 0, 0x08); + + val = rtwn_bb_read(sc, R12A_HSSI_PARAM1(chain)); + pi_mode = (val & R12A_HSSI_PARAM1_PI) ? 1 : 0; + + rtwn_bb_setbits(sc, R12A_HSSI_PARAM2, + R12A_HSSI_PARAM2_READ_ADDR_MASK, addr); + + val = rtwn_bb_read(sc, pi_mode ? R12A_HSPI_READBACK(chain) : + R12A_LSSI_READBACK(chain)); + + /* Turn on CCA (when exiting). */ + if (addr != R92C_RF_AC) + rtwn_bb_setbits(sc, R12A_CCA_ON_SEC, 0x08, 0); + + return (MS(val, R92C_LSSI_READBACK_DATA)); +} + +uint32_t +r12a_c_cut_rf_read(struct rtwn_softc *sc, int chain, uint8_t addr) +{ + uint32_t pi_mode, val; + + val = rtwn_bb_read(sc, R12A_HSSI_PARAM1(chain)); + pi_mode = (val & R12A_HSSI_PARAM1_PI) ? 1 : 0; + + rtwn_bb_setbits(sc, R12A_HSSI_PARAM2, + R12A_HSSI_PARAM2_READ_ADDR_MASK, addr); + rtwn_delay(sc, 20); + + val = rtwn_bb_read(sc, pi_mode ? R12A_HSPI_READBACK(chain) : + R12A_LSSI_READBACK(chain)); + + return (MS(val, R92C_LSSI_READBACK_DATA)); +} + +void +r12a_rf_write(struct rtwn_softc *sc, int chain, uint8_t addr, + uint32_t val) +{ + rtwn_bb_write(sc, R12A_LSSI_PARAM(chain), + SM(R88E_LSSI_PARAM_ADDR, addr) | + SM(R92C_LSSI_PARAM_DATA, val)); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom.c new file mode 100644 index 0000000000..999b5fd38f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom.c @@ -0,0 +1,222 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_rom.c 308825 2016-11-19 07:28:00Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + + +void +r12a_parse_rom_common(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r12a_softc *rs = sc->sc_priv; + struct r12a_rom *rom = (struct r12a_rom *)buf; + int i, j, k; + + sc->thermal_meter = rom->thermal_meter; + rs->crystalcap = RTWN_GET_ROM_VAR(rom->crystalcap, + R12A_ROM_CRYSTALCAP_DEF); + rs->tx_bbswing_2g = RTWN_GET_ROM_VAR(rom->tx_bbswing_2g, 0); + rs->tx_bbswing_5g = RTWN_GET_ROM_VAR(rom->tx_bbswing_5g, 0); + + for (i = 0; i < sc->ntxchains; i++) { + struct r12a_tx_pwr_2g *pwr_2g = &rom->tx_pwr[i].pwr_2g; + struct r12a_tx_pwr_5g *pwr_5g = &rom->tx_pwr[i].pwr_5g; + struct r12a_tx_pwr_diff_2g *pwr_diff_2g = + &rom->tx_pwr[i].pwr_diff_2g; + struct r12a_tx_pwr_diff_5g *pwr_diff_5g = + &rom->tx_pwr[i].pwr_diff_5g; + + for (j = 0; j < R12A_GROUP_2G - 1; j++) { + rs->cck_tx_pwr[i][j] = + RTWN_GET_ROM_VAR(pwr_2g->cck[j], + R12A_DEF_TX_PWR_2G); + rs->ht40_tx_pwr_2g[i][j] = + RTWN_GET_ROM_VAR(pwr_2g->ht40[j], + R12A_DEF_TX_PWR_2G); + } + rs->cck_tx_pwr[i][j] = RTWN_GET_ROM_VAR(pwr_2g->cck[j], + R12A_DEF_TX_PWR_2G); + + rs->cck_tx_pwr_diff_2g[i][0] = 0; + rs->ofdm_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->ht20_ofdm, LOW_PART)); + rs->bw20_tx_pwr_diff_2g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->ht20_ofdm, HIGH_PART)); + rs->bw40_tx_pwr_diff_2g[i][0] = 0; + + for (j = 1, k = 0; k < nitems(pwr_diff_2g->diff123); j++, k++) { + rs->cck_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ofdm_cck, LOW_PART)); + rs->ofdm_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ofdm_cck, HIGH_PART)); + rs->bw20_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ht40_ht20, LOW_PART)); + rs->bw40_tx_pwr_diff_2g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_2g->diff123[k].ht40_ht20, HIGH_PART)); + } + + for (j = 0; j < R12A_GROUP_5G; j++) { + rs->ht40_tx_pwr_5g[i][j] = + RTWN_GET_ROM_VAR(pwr_5g->ht40[j], + R12A_DEF_TX_PWR_5G); + } + + rs->ofdm_tx_pwr_diff_5g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ht20_ofdm, LOW_PART)); + rs->ofdm_tx_pwr_diff_5g[i][1] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ofdm_ofdm[0], HIGH_PART)); + rs->ofdm_tx_pwr_diff_5g[i][2] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ofdm_ofdm[0], LOW_PART)); + rs->ofdm_tx_pwr_diff_5g[i][3] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ofdm_ofdm[1], LOW_PART)); + + rs->bw20_tx_pwr_diff_5g[i][0] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ht20_ofdm, HIGH_PART)); + rs->bw40_tx_pwr_diff_5g[i][0] = 0; + for (j = 1, k = 0; k < nitems(pwr_diff_5g->ht40_ht20); + j++, k++) { + rs->bw20_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ht40_ht20[k], LOW_PART)); + rs->bw40_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ht40_ht20[k], HIGH_PART)); + } + + for (j = 0; j < nitems(pwr_diff_5g->ht80_ht160); j++) { + rs->bw80_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ht80_ht160[j], HIGH_PART)); + rs->bw160_tx_pwr_diff_5g[i][j] = RTWN_SIGN4TO8( + MS(pwr_diff_5g->ht80_ht160[j], LOW_PART)); + } + } + + rs->regulatory = MS(rom->rf_board_opt, R92C_ROM_RF1_REGULATORY); + rs->board_type = + MS(RTWN_GET_ROM_VAR(rom->rf_board_opt, R92C_BOARD_TYPE_DONGLE), + R92C_ROM_RF1_BOARD_TYPE); + RTWN_DPRINTF(sc, RTWN_DEBUG_ROM, "%s: regulatory type=%d\n", + __func__, rs->regulatory); +} + +void +r12a_parse_rom(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r12a_softc *rs = sc->sc_priv; + struct r12a_rom *rom = (struct r12a_rom *)buf; + uint8_t pa_type, lna_type_2g, lna_type_5g; + + /* Read PA/LNA types. */ + pa_type = RTWN_GET_ROM_VAR(rom->pa_type, 0); + lna_type_2g = RTWN_GET_ROM_VAR(rom->lna_type_2g, 0); + lna_type_5g = RTWN_GET_ROM_VAR(rom->lna_type_5g, 0); + + rs->ext_pa_2g = R12A_ROM_IS_PA_EXT_2GHZ(pa_type); + rs->ext_pa_5g = R12A_ROM_IS_PA_EXT_5GHZ(pa_type); + rs->ext_lna_2g = R21A_ROM_IS_LNA_EXT(lna_type_2g); + rs->ext_lna_5g = R21A_ROM_IS_LNA_EXT(lna_type_5g); + rs->bt_coex = (MS(rom->rf_board_opt, R92C_ROM_RF1_BOARD_TYPE) == + R92C_BOARD_TYPE_HIGHPA); + rs->bt_ant_num = (rom->rf_bt_opt & R12A_RF_BT_OPT_ANT_NUM); + + if (rs->ext_pa_2g) { + rs->type_pa_2g = + R12A_GET_ROM_PA_TYPE(lna_type_2g, 0) | + (R12A_GET_ROM_PA_TYPE(lna_type_2g, 1) << 2); + } + if (rs->ext_pa_5g) { + rs->type_pa_5g = + R12A_GET_ROM_PA_TYPE(lna_type_5g, 0) | + (R12A_GET_ROM_PA_TYPE(lna_type_5g, 1) << 2); + } + if (rs->ext_lna_2g) { + rs->type_lna_2g = + R12A_GET_ROM_LNA_TYPE(lna_type_2g, 0) | + (R12A_GET_ROM_LNA_TYPE(lna_type_2g, 1) << 2); + } + if (rs->ext_lna_5g) { + rs->type_lna_5g = + R12A_GET_ROM_LNA_TYPE(lna_type_5g, 0) | + (R12A_GET_ROM_LNA_TYPE(lna_type_5g, 1) << 2); + } + + if (rom->rfe_option & 0x80) { + if (rs->ext_lna_5g) { + if (rs->ext_pa_5g) { + if (rs->ext_pa_2g && rs->ext_lna_2g) + rs->rfe_type = 3; + else + rs->rfe_type = 0; + } else + rs->rfe_type = 2; + } else + rs->rfe_type = 4; + } else { + rs->rfe_type = rom->rfe_option & 0x3f; + + /* workaround for incorrect EFUSE map */ + if (rs->rfe_type == 4 && + rs->ext_pa_2g && rs->ext_lna_2g && + rs->ext_pa_5g && rs->ext_lna_5g) + rs->rfe_type = 0; + } + + /* Read MAC address. */ + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr_12a); + + /* Execute common part of initialization. */ + r12a_parse_rom_common(sc, buf); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_defs.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_defs.h new file mode 100644 index 0000000000..f0f284b93a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_defs.h @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_rom_defs.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R12A_ROM_DEFS_H +#define R12A_ROM_DEFS_H + +#include + +#define R12A_GROUP_2G 6 +#define R12A_GROUP_5G 14 + +#define R12A_MAX_TX_COUNT 4 +#define R12A_MAX_RF_PATH 4 + +#define R12A_EFUSE_MAX_LEN 512 +#define R12A_EFUSE_MAP_LEN 512 + +#endif /* R12A_ROM_DEFS_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_image.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_image.h new file mode 100644 index 0000000000..eab2b06030 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rom_image.h @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_rom_image.h 308913 2016-11-21 09:23:42Z kevlo $ + */ + +#ifndef R12A_ROM_IMAGE_H +#define R12A_ROM_IMAGE_H + +#include + +#define R12A_DEF_TX_PWR_2G 0x2d +#define R12A_DEF_TX_PWR_5G 0xfe + +struct r12a_tx_pwr_2g { + uint8_t cck[R12A_GROUP_2G]; + uint8_t ht40[R12A_GROUP_2G - 1]; +} __packed; + +struct r12a_tx_pwr_diff_2g { + uint8_t ht20_ofdm; + struct { + uint8_t ht40_ht20; + uint8_t ofdm_cck; + } __packed diff123[R12A_MAX_TX_COUNT - 1]; +} __packed; + +struct r12a_tx_pwr_5g { + uint8_t ht40[R12A_GROUP_5G]; +} __packed; + +struct r12a_tx_pwr_diff_5g { + uint8_t ht20_ofdm; + uint8_t ht40_ht20[R12A_MAX_TX_COUNT - 1]; + uint8_t ofdm_ofdm[2]; + uint8_t ht80_ht160[R12A_MAX_TX_COUNT]; +} __packed; + +struct r12a_tx_pwr { + struct r12a_tx_pwr_2g pwr_2g; + struct r12a_tx_pwr_diff_2g pwr_diff_2g; + struct r12a_tx_pwr_5g pwr_5g; + struct r12a_tx_pwr_diff_5g pwr_diff_5g; +} __packed; + +/* + * RTL8812AU/RTL8821AU ROM image. + */ +struct r12a_rom { + uint8_t reserved1[16]; + struct r12a_tx_pwr tx_pwr[R12A_MAX_RF_PATH]; + uint8_t channel_plan; + uint8_t crystalcap; +#define R12A_ROM_CRYSTALCAP_DEF 0x20 + + uint8_t thermal_meter; + uint8_t iqk_lck; + uint8_t pa_type; +#define R12A_ROM_IS_PA_EXT_2GHZ(pa_type) (((pa_type) & 0x30) == 0x30) +#define R12A_ROM_IS_PA_EXT_5GHZ(pa_type) (((pa_type) & 0x03) == 0x03) +#define R21A_ROM_IS_PA_EXT_2GHZ(pa_type) (((pa_type) & 0x10) == 0x10) +#define R21A_ROM_IS_PA_EXT_5GHZ(pa_type) (((pa_type) & 0x01) == 0x01) + + uint8_t lna_type_2g; +#define R12A_ROM_IS_LNA_EXT(lna_type) (((lna_type) & 0x88) == 0x88) +#define R21A_ROM_IS_LNA_EXT(lna_type) (((lna_type) & 0x08) == 0x08) + +#define R12A_GET_ROM_PA_TYPE(lna_type, chain) \ + (((lna_type) >> ((chain) * 4 + 2)) & 0x01) +#define R12A_GET_ROM_LNA_TYPE(lna_type, chain) \ + (((lna_type) >> ((chain) * 4)) & 0x03) + + uint8_t reserved2; + uint8_t lna_type_5g; + uint8_t reserved3; + uint8_t rf_board_opt; +#define R12A_BOARD_TYPE_COMBO_MF 5 + + uint8_t rf_feature_opt; + uint8_t rf_bt_opt; +#define R12A_RF_BT_OPT_ANT_NUM 0x01 + + uint8_t version; + uint8_t customer_id; + uint8_t tx_bbswing_2g; + uint8_t tx_bbswing_5g; + uint8_t tx_pwr_calib_rate; + uint8_t rf_ant_opt; + uint8_t rfe_option; + uint8_t reserved4[5]; + uint16_t vid_12a; + uint16_t pid_12a; + uint8_t reserved5[3]; + uint8_t macaddr_12a[IEEE80211_ADDR_LEN]; + uint8_t reserved6[2]; + uint8_t string_12a[8]; /* "Realtek " */ + uint8_t reserved7[25]; + uint16_t vid_21a; + uint16_t pid_21a; + uint8_t reserved8[3]; + uint8_t macaddr_21a[IEEE80211_ADDR_LEN]; + uint8_t reserved9[2]; + uint8_t string_21a[8]; /* "Realtek " */ + uint8_t reserved10[2]; + uint8_t string_ven[23]; /* XXX variable length? */ + uint8_t reserved11[208]; +} __packed; + +_Static_assert(sizeof(struct r12a_rom) == R12A_EFUSE_MAP_LEN, + "R12A_EFUSE_MAP_LEN must be equal to sizeof(struct r12a_rom)!"); + +#endif /* R12A_ROM_IMAGE_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx.c new file mode 100644 index 0000000000..076f30b21a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx.c @@ -0,0 +1,329 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_rx.c 331043 2018-03-16 01:03:10Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + + +#ifndef RTWN_WITHOUT_UCODE +void +r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) +{ +#if __FreeBSD_version >= 1200012 + struct ieee80211_ratectl_tx_status txs; +#endif + struct r12a_c2h_tx_rpt *rpt; + struct ieee80211_node *ni; + int ntries; + + /* Skip Rx descriptor / report id / sequence fields. */ + buf += sizeof(struct r92c_rx_stat) + 2; + len -= sizeof(struct r92c_rx_stat) + 2; + + rpt = (struct r12a_c2h_tx_rpt *)buf; + if (len != sizeof(*rpt)) { + device_printf(sc->sc_dev, + "%s: wrong report size (%d, must be %zu)\n", + __func__, len, sizeof(*rpt)); + return; + } + + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: ccx report dump: 0: %02X, id: %02X, 2: %02X, queue time: " + "low %02X, high %02X, final ridx: %02X, rsvd: %04X\n", + __func__, rpt->txrptb0, rpt->macid, rpt->txrptb2, + rpt->queue_time_low, rpt->queue_time_high, rpt->final_rate, + rpt->reserved); + + if (rpt->macid > sc->macid_limit) { + device_printf(sc->sc_dev, + "macid %u is too big; increase MACID_MAX limit\n", + rpt->macid); + return; + } + + ntries = MS(rpt->txrptb2, R12A_TXRPTB2_RETRY_CNT); + + ni = sc->node_list[rpt->macid]; + if (ni != NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was" + "%s sent (%d retries)\n", __func__, rpt->macid, + (rpt->txrptb0 & (R12A_TXRPTB0_RETRY_OVER | + R12A_TXRPTB0_LIFE_EXPIRE)) ? " not" : "", ntries); + +#if __FreeBSD_version >= 1200012 + txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY | + IEEE80211_RATECTL_STATUS_FINAL_RATE; + txs.long_retries = ntries; + if (rpt->final_rate > RTWN_RIDX_OFDM54) { /* MCS */ + txs.final_rate = + rpt->final_rate - RTWN_RIDX_HT_MCS_SHIFT; + txs.final_rate |= IEEE80211_RATE_MCS; + } else + txs.final_rate = ridx2rate[rpt->final_rate]; + if (rpt->txrptb0 & R12A_TXRPTB0_RETRY_OVER) + txs.status = IEEE80211_RATECTL_TX_FAIL_LONG; + else if (rpt->txrptb0 & R12A_TXRPTB0_LIFE_EXPIRE) + txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED; + else + txs.status = IEEE80211_RATECTL_TX_SUCCESS; + ieee80211_ratectl_tx_complete(ni, &txs); +#else + struct ieee80211vap *vap = ni->ni_vap; + if (rpt->txrptb0 & R12A_TXRPTB0_RETRY_OVER) { + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL); + } else { + ieee80211_ratectl_tx_complete(vap, ni, + IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL); + } +#endif + } else { + RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, + "%s: macid %u, ni is NULL\n", __func__, rpt->macid); + } +} + +void +r12a_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + struct r12a_softc *rs = sc->sc_priv; + + /* Skip Rx descriptor. */ + buf += sizeof(struct r92c_rx_stat); + len -= sizeof(struct r92c_rx_stat); + + if (len < 2) { + device_printf(sc->sc_dev, "C2H report too short (len %d)\n", + len); + return; + } + len -= 2; + + switch (buf[0]) { /* command id */ + case R12A_C2H_TX_REPORT: + /* NOTREACHED */ + KASSERT(0, ("use handle_tx_report() instead of %s\n", + __func__)); + break; + case R12A_C2H_IQK_FINISHED: + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, + "FW IQ calibration finished\n"); + rs->rs_flags &= ~R12A_IQK_RUNNING; + break; + default: + device_printf(sc->sc_dev, + "%s: C2H report %u was not handled\n", + __func__, buf[0]); + } +} +#else +void +r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + /* Should not happen. */ + device_printf(sc->sc_dev, "%s: called\n", __func__); +} + +void +r12a_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len) +{ + /* Should not happen. */ + device_printf(sc->sc_dev, "%s: called\n", __func__); +} +#endif + +int +r12a_check_frame_checksum(struct rtwn_softc *sc, struct mbuf *m) +{ + struct r12a_softc *rs = sc->sc_priv; + struct r92c_rx_stat *stat; + uint32_t rxdw1; + + stat = mtod(m, struct r92c_rx_stat *); + rxdw1 = le32toh(stat->rxdw1); + if (rxdw1 & R12A_RXDW1_CKSUM) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: %s/%s checksum is %s\n", __func__, + (rxdw1 & R12A_RXDW1_UDP) ? "UDP" : "TCP", + (rxdw1 & R12A_RXDW1_IPV6) ? "IPv6" : "IP", + (rxdw1 & R12A_RXDW1_CKSUM_ERR) ? "invalid" : "valid"); + + if (rxdw1 & R12A_RXDW1_CKSUM_ERR) + return (-1); + + if ((rxdw1 & R12A_RXDW1_IPV6) ? + (rs->rs_flags & R12A_RXCKSUM6_EN) : + (rs->rs_flags & R12A_RXCKSUM_EN)) { + m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | + CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR; + m->m_pkthdr.csum_data = 0xffff; + } + } + + return (0); +} + +uint8_t +r12a_rx_radiotap_flags(const void *buf) +{ + const struct r92c_rx_stat *stat = buf; + uint8_t flags, rate; + + if (!(stat->rxdw4 & htole32(R12A_RXDW4_SPLCP))) + return (0); + rate = MS(le32toh(stat->rxdw3), R12A_RXDW3_RATE); + if (RTWN_RATE_IS_CCK(rate)) + flags = IEEE80211_RADIOTAP_F_SHORTPRE; + else + flags = IEEE80211_RADIOTAP_F_SHORTGI; + return (flags); +} + +void +r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs, + const void *desc, const void *physt_ptr) +{ + const struct r92c_rx_stat *stat = desc; + const struct r12a_rx_phystat *physt = physt_ptr; + uint32_t rxdw0, rxdw1, rxdw3, rxdw4; + uint8_t rate; + + rxdw0 = le32toh(stat->rxdw0); + rxdw1 = le32toh(stat->rxdw1); + rxdw3 = le32toh(stat->rxdw3); + rxdw4 = le32toh(stat->rxdw4); + rate = MS(rxdw3, R12A_RXDW3_RATE); + + /* TODO: STBC */ + if (rxdw4 & R12A_RXDW4_LDPC) + rxs->c_pktflags |= IEEE80211_RX_F_LDPC; + if (rxdw1 & R12A_RXDW1_AMPDU) { + if (rxdw0 & R92C_RXDW0_PHYST) + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU; + else + rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE; + } + + if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0)) + rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI; + + switch (MS(rxdw4, R12A_RXDW4_BW)) { + case R12A_RXDW4_BW20: + rxs->c_width = IEEE80211_RX_FW_20MHZ; + break; + case R12A_RXDW4_BW40: + rxs->c_width = IEEE80211_RX_FW_40MHZ; + break; + case R12A_RXDW4_BW80: + rxs->c_width = IEEE80211_RX_FW_80MHZ; + break; + default: + break; + } + + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_phytype = IEEE80211_RX_FP_11B; + else { + int is5ghz; + + /* XXX magic */ + /* XXX check with RTL8812AU */ + is5ghz = (physt->cfosho[2] != 0x01); + + if (rate < RTWN_RIDX_HT_MCS(0)) { + if (is5ghz) + rxs->c_phytype = IEEE80211_RX_FP_11A; + else + rxs->c_phytype = IEEE80211_RX_FP_11G; + } else { + if (is5ghz) + rxs->c_phytype = IEEE80211_RX_FP_11NA; + else + rxs->c_phytype = IEEE80211_RX_FP_11NG; + } + } + + /* Map HW rate index to 802.11 rate. */ + if (rate < RTWN_RIDX_HT_MCS(0)) { + rxs->c_rate = ridx2rate[rate]; + if (RTWN_RATE_IS_CCK(rate)) + rxs->c_pktflags |= IEEE80211_RX_F_CCK; + else + rxs->c_pktflags |= IEEE80211_RX_F_OFDM; + } else { /* MCS0~15. */ + /* TODO: VHT rates */ + rxs->c_rate = + IEEE80211_RATE_MCS | (rate - RTWN_RIDX_HT_MCS_SHIFT); + rxs->c_pktflags |= IEEE80211_RX_F_HT; + } + + /* + * XXX always zero for RTL8821AU + * (vendor driver does not check this field) + */ +#if 0 + rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ; + rxs->c_ieee = MS(le16toh(physt->phyw1), R12A_PHYW1_CHAN); + rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee, + (rxs->c_ieee < 36) ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ); +#endif +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx_desc.h new file mode 100644 index 0000000000..7b45a0ae82 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_rx_desc.h @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_rx_desc.h 312315 2017-01-17 00:35:23Z avos $ + */ + +#ifndef R12A_RX_DESC_H +#define R12A_RX_DESC_H + +#include + +/* Rx MAC descriptor defines (chip-specific). */ +/* Rx dword 1 */ +#define R12A_RXDW1_AMSDU 0x00002000 +#define R12A_RXDW1_AMPDU 0x00008000 +#define R12A_RXDW1_CKSUM_ERR 0x00100000 +#define R12A_RXDW1_IPV6 0x00200000 +#define R12A_RXDW1_UDP 0x00400000 +#define R12A_RXDW1_CKSUM 0x00800000 +/* Rx dword 2 */ +#define R12A_RXDW2_RPT_C2H 0x10000000 +/* Rx dword 3 */ +#define R12A_RXDW3_RATE_M 0x0000007f +#define R12A_RXDW3_RATE_S 0 +/* Rx dword 4 */ +#define R12A_RXDW4_SPLCP 0x00000001 +#define R12A_RXDW4_LDPC 0x00000002 +#define R12A_RXDW4_STBC 0x00000004 +#define R12A_RXDW4_BW_M 0x00000030 +#define R12A_RXDW4_BW_S 4 +#define R12A_RXDW4_BW20 0 +#define R12A_RXDW4_BW40 1 +#define R12A_RXDW4_BW80 2 +#define R12A_RXDW4_BW160 3 + +/* Rx PHY descriptor. */ +struct r12a_rx_phystat { + uint8_t gain_trsw[2]; + uint16_t phyw1; +#define R12A_PHYW1_CHAN_M 0x03ff +#define R12A_PHYW1_CHAN_S 0 +#define R12A_PHYW1_CHAN_EXT_M 0x3c00 +#define R12A_PHYW1_CHAN_EXT_S 10 +#define R12A_PHYW1_RFMOD_M 0xc000 +#define R12A_PHYW1_RFMOD_S 14 + + uint8_t pwdb_all; + uint8_t cfosho[4]; + uint8_t cfotail[4]; + uint8_t rxevm[2]; + uint8_t rxsnr[2]; + uint8_t pcts_msk_rpt[2]; + uint8_t pdsnr[2]; + uint8_t csi_current[2]; + uint8_t rx_gain_c; + uint8_t rx_gain_d; + uint8_t sigevm; + uint16_t phyw13; +#define R12A_PHYW13_ANTIDX_A_M 0x0700 +#define R12A_PHYW13_ANTIDX_A_S 8 +#define R12A_PHYW13_ANTIDX_B_M 0x3800 +#define R12A_PHYW13_ANTIDX_B_S 11 +} __packed; + +#endif /* R12A_RX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx.c new file mode 100644 index 0000000000..e2e0c33ddd --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx.c @@ -0,0 +1,446 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_tx.c 322988 2017-08-28 22:14:16Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + + +static int +r12a_get_primary_channel(struct rtwn_softc *sc, struct ieee80211_channel *c) +{ + /* XXX 80 MHz */ + if (IEEE80211_IS_CHAN_HT40U(c)) + return (R12A_TXDW5_PRIM_CHAN_20_80_2); + else + return (R12A_TXDW5_PRIM_CHAN_20_80_3); +} + +static void +r12a_tx_set_ht40(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) +{ + struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; + + /* XXX 80 Mhz */ + if (ni->ni_chan != IEEE80211_CHAN_ANYC && + IEEE80211_IS_CHAN_HT40(ni->ni_chan)) { + int prim_chan; + + prim_chan = r12a_get_primary_channel(sc, ni->ni_chan); + txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_BW, + R12A_TXDW5_DATA_BW40)); + txd->txdw5 |= htole32(SM(R12A_TXDW5_DATA_PRIM_CHAN, + prim_chan)); + } +} + +static void +r12a_tx_protection(struct rtwn_softc *sc, struct r12a_tx_desc *txd, + enum ieee80211_protmode mode, uint8_t ridx) +{ + struct ieee80211com *ic = &sc->sc_ic; + uint8_t rate; + + switch (mode) { + case IEEE80211_PROT_CTSONLY: + txd->txdw3 |= htole32(R12A_TXDW3_CTS2SELF); + break; + case IEEE80211_PROT_RTSCTS: + txd->txdw3 |= htole32(R12A_TXDW3_RTSEN); + break; + default: + break; + } + + if (mode == IEEE80211_PROT_CTSONLY || + mode == IEEE80211_PROT_RTSCTS) { + if (ridx >= RTWN_RIDX_HT_MCS(0)) + rate = rtwn_ctl_mcsrate(ic->ic_rt, ridx); + else + rate = ieee80211_ctl_rate(ic->ic_rt, ridx2rate[ridx]); + ridx = rate2ridx(rate); + + txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE, ridx)); + /* RTS rate fallback limit (max). */ + txd->txdw4 |= htole32(SM(R12A_TXDW4_RTSRATE_FB_LMT, 0xf)); + + if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && + (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + txd->txdw5 |= htole32(R12A_TXDW5_RTS_SHORT); + } +} + +static void +r12a_tx_raid(struct rtwn_softc *sc, struct r12a_tx_desc *txd, + struct ieee80211_node *ni, int ismcast) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct ieee80211_channel *chan; + enum ieee80211_phymode mode; + uint8_t raid; + + chan = (ni->ni_chan != IEEE80211_CHAN_ANYC) ? + ni->ni_chan : ic->ic_curchan; + mode = ieee80211_chan2mode(chan); + + /* NB: group addressed frames are done at 11bg rates for now */ + if (ismcast || !(ni->ni_flags & IEEE80211_NODE_HT)) { + switch (mode) { + case IEEE80211_MODE_11A: + case IEEE80211_MODE_11B: + case IEEE80211_MODE_11G: + break; + case IEEE80211_MODE_11NA: + mode = IEEE80211_MODE_11A; + break; + case IEEE80211_MODE_11NG: + mode = IEEE80211_MODE_11G; + break; + default: + device_printf(sc->sc_dev, "unknown mode(1) %d!\n", + ic->ic_curmode); + return; + } + } + + switch (mode) { + case IEEE80211_MODE_11A: + raid = R12A_RAID_11G; + break; + case IEEE80211_MODE_11B: + raid = R12A_RAID_11B; + break; + case IEEE80211_MODE_11G: + if (vap->iv_flags & IEEE80211_F_PUREG) + raid = R12A_RAID_11G; + else + raid = R12A_RAID_11BG; + break; + case IEEE80211_MODE_11NA: + if (sc->ntxchains == 1) + raid = R12A_RAID_11GN_1; + else + raid = R12A_RAID_11GN_2; + break; + case IEEE80211_MODE_11NG: + if (sc->ntxchains == 1) { + if (IEEE80211_IS_CHAN_HT40(chan)) + raid = R12A_RAID_11BGN_1_40; + else + raid = R12A_RAID_11BGN_1; + } else { + if (IEEE80211_IS_CHAN_HT40(chan)) + raid = R12A_RAID_11BGN_2_40; + else + raid = R12A_RAID_11BGN_2; + } + break; + default: + /* TODO: 80 MHz / 11ac */ + device_printf(sc->sc_dev, "unknown mode(2) %d!\n", mode); + return; + } + + txd->txdw1 |= htole32(SM(R12A_TXDW1_RAID, raid)); +} + +static void +r12a_tx_set_sgi(struct rtwn_softc *sc, void *buf, struct ieee80211_node *ni) +{ + struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; + struct ieee80211vap *vap = ni->ni_vap; + + if ((vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20) && /* HT20 */ + (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)) + txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); + else if (ni->ni_chan != IEEE80211_CHAN_ANYC && /* HT40 */ + IEEE80211_IS_CHAN_HT40(ni->ni_chan) && + (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) && + (vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40)) + txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); +} + +static void +r12a_tx_set_ldpc(struct rtwn_softc *sc, struct r12a_tx_desc *txd, + struct ieee80211_node *ni) +{ + struct ieee80211vap *vap = ni->ni_vap; + + if ((vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX) && + (ni->ni_htcap & IEEE80211_HTCAP_LDPC)) + txd->txdw5 |= htole32(R12A_TXDW5_DATA_LDPC); +} + +void +r12a_fill_tx_desc(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, void *buf, uint8_t ridx, int maxretry) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211vap *vap = ni->ni_vap; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211_frame *wh; + struct r12a_tx_desc *txd; + enum ieee80211_protmode prot; + uint8_t type, tid, qos, qsel; + int hasqos, ismcast, macid; + + wh = mtod(m, struct ieee80211_frame *); + type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; + hasqos = IEEE80211_QOS_HAS_SEQ(wh); + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + + /* Select TX ring for this frame. */ + if (hasqos) { + qos = ((const struct ieee80211_qosframe *)wh)->i_qos[0]; + tid = qos & IEEE80211_QOS_TID; + } else { + qos = 0; + tid = 0; + } + + /* Fill Tx descriptor. */ + txd = (struct r12a_tx_desc *)buf; + txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG; + if (ismcast) + txd->flags0 |= R12A_FLAGS0_BMCAST; + + if (!ismcast) { + /* Unicast frame, check if an ACK is expected. */ + if (!qos || (qos & IEEE80211_QOS_ACKPOLICY) != + IEEE80211_QOS_ACKPOLICY_NOACK) { + txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA); + txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT, + maxretry)); + } + + struct rtwn_node *un = RTWN_NODE(ni); + macid = un->id; + + if (type == IEEE80211_FC0_TYPE_DATA) { + qsel = tid % RTWN_MAX_TID; + + if (m->m_flags & M_AMPDU_MPDU) { + txd->txdw2 |= htole32(R12A_TXDW2_AGGEN); + txd->txdw2 |= htole32(SM(R12A_TXDW2_AMPDU_DEN, + vap->iv_ampdu_density)); + txd->txdw3 |= htole32(SM(R12A_TXDW3_MAX_AGG, + 0x1f)); /* XXX */ + } else + txd->txdw2 |= htole32(R12A_TXDW2_AGGBK); + + if (sc->sc_ratectl == RTWN_RATECTL_NET80211) { + txd->txdw2 |= htole32(R12A_TXDW2_SPE_RPT); + sc->sc_tx_n_active++; + } + + if (RTWN_RATE_IS_CCK(ridx) && ridx != RTWN_RIDX_CCK1 && + (ic->ic_flags & IEEE80211_F_SHPREAMBLE)) + txd->txdw5 |= htole32(R12A_TXDW5_DATA_SHORT); + + prot = IEEE80211_PROT_NONE; + if (ridx >= RTWN_RIDX_HT_MCS(0)) { + r12a_tx_set_ht40(sc, txd, ni); + r12a_tx_set_sgi(sc, txd, ni); + r12a_tx_set_ldpc(sc, txd, ni); + prot = ic->ic_htprotmode; + } else if (ic->ic_flags & IEEE80211_F_USEPROT) + prot = ic->ic_protmode; + + /* XXX fix last comparison for A-MSDU (in net80211) */ + /* XXX A-MPDU? */ + if (m->m_pkthdr.len + IEEE80211_CRC_LEN > + vap->iv_rtsthreshold && + vap->iv_rtsthreshold != IEEE80211_RTS_MAX) + prot = IEEE80211_PROT_RTSCTS; + + if (prot != IEEE80211_PROT_NONE) + r12a_tx_protection(sc, txd, prot, ridx); + } else /* IEEE80211_FC0_TYPE_MGT */ + qsel = R12A_TXDW1_QSEL_MGNT; + } else { + macid = RTWN_MACID_BC; + qsel = R12A_TXDW1_QSEL_MGNT; + } + + txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, qsel)); + txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, macid)); + txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx)); + /* Data rate fallback limit (max). */ + txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f)); + /* XXX recheck for non-21au */ + txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id)); + r12a_tx_raid(sc, txd, ni, ismcast); + + /* Force this rate if needed. */ + if (sc->sc_ratectl != RTWN_RATECTL_FW) + txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE); + + if (!hasqos) { + /* Use HW sequence numbering for non-QoS frames. */ + txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN); + txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, uvp->id)); + } else { + uint16_t seqno; + + if (m->m_flags & M_AMPDU_MPDU) { + seqno = ni->ni_txseqs[tid]; + ni->ni_txseqs[tid]++; + } else + seqno = M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE; + + /* Set sequence number. */ + txd->txdw9 |= htole32(SM(R12A_TXDW9_SEQ, seqno)); + } +} + +void +r12a_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, void *buf, const struct ieee80211_bpf_params *params) +{ + struct ieee80211vap *vap = ni->ni_vap; + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct ieee80211_frame *wh; + struct r12a_tx_desc *txd; + uint8_t ridx; + int ismcast; + + /* XXX TODO: 11n checks, matching rtwn_fill_tx_desc() */ + + wh = mtod(m, struct ieee80211_frame *); + ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); + ridx = rate2ridx(params->ibp_rate0); + + /* Fill Tx descriptor. */ + txd = (struct r12a_tx_desc *)buf; + txd->flags0 |= R12A_FLAGS0_LSG | R12A_FLAGS0_FSG; + if (ismcast) + txd->flags0 |= R12A_FLAGS0_BMCAST; + + if ((params->ibp_flags & IEEE80211_BPF_NOACK) == 0) { + txd->txdw4 = htole32(R12A_TXDW4_RETRY_LMT_ENA); + txd->txdw4 |= htole32(SM(R12A_TXDW4_RETRY_LMT, + params->ibp_try0)); + } + if (params->ibp_flags & IEEE80211_BPF_RTS) + r12a_tx_protection(sc, txd, IEEE80211_PROT_RTSCTS, ridx); + if (params->ibp_flags & IEEE80211_BPF_CTS) + r12a_tx_protection(sc, txd, IEEE80211_PROT_CTSONLY, ridx); + + txd->txdw1 |= htole32(SM(R12A_TXDW1_MACID, RTWN_MACID_BC)); + txd->txdw1 |= htole32(SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT)); + + /* Set TX rate index. */ + txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE, ridx)); + txd->txdw4 |= htole32(SM(R12A_TXDW4_DATARATE_FB_LMT, 0x1f)); + txd->txdw6 |= htole32(SM(R21A_TXDW6_MBSSID, uvp->id)); + txd->txdw3 |= htole32(R12A_TXDW3_DRVRATE); + r12a_tx_raid(sc, txd, ni, ismcast); + + if (!IEEE80211_QOS_HAS_SEQ(wh)) { + /* Use HW sequence numbering for non-QoS frames. */ + txd->txdw8 |= htole32(R12A_TXDW8_HWSEQ_EN); + txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, uvp->id)); + } else { + /* Set sequence number. */ + txd->txdw9 |= htole32(SM(R12A_TXDW9_SEQ, + M_SEQNO_GET(m) % IEEE80211_SEQ_RANGE)); + } +} + +void +r12a_fill_tx_desc_null(struct rtwn_softc *sc, void *buf, int is11b, int qos, + int id) +{ + struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; + + txd->flags0 = R12A_FLAGS0_FSG | R12A_FLAGS0_LSG | R12A_FLAGS0_OWN; + txd->txdw1 = htole32( + SM(R12A_TXDW1_QSEL, R12A_TXDW1_QSEL_MGNT)); + + txd->txdw3 = htole32(R12A_TXDW3_DRVRATE); + txd->txdw6 = htole32(SM(R21A_TXDW6_MBSSID, id)); + if (is11b) { + txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, + RTWN_RIDX_CCK1)); + } else { + txd->txdw4 = htole32(SM(R12A_TXDW4_DATARATE, + RTWN_RIDX_OFDM6)); + } + + if (!qos) { + txd->txdw8 = htole32(R12A_TXDW8_HWSEQ_EN); + txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id)); + + } +} + +uint8_t +r12a_tx_radiotap_flags(const void *buf) +{ + const struct r12a_tx_desc *txd = buf; + uint8_t flags, rate; + + if (!(txd->txdw5 & htole32(R12A_TXDW5_DATA_SHORT))) + return (0); + + rate = MS(le32toh(txd->txdw4), R12A_TXDW4_DATARATE); + if (RTWN_RATE_IS_CCK(rate)) + flags = IEEE80211_RADIOTAP_F_SHORTPRE; + else + flags = IEEE80211_RADIOTAP_F_SHORTGI; + return (flags); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx_desc.h new file mode 100644 index 0000000000..3008724fa8 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_tx_desc.h @@ -0,0 +1,149 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_tx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R12A_TX_DESC_H +#define R12A_TX_DESC_H + +/* Tx MAC descriptor (common part). */ +struct r12a_tx_desc { + uint16_t pktlen; + uint8_t offset; + uint8_t flags0; +#define R12A_FLAGS0_BMCAST 0x01 +#define R12A_FLAGS0_LSG 0x04 +#define R12A_FLAGS0_FSG 0x08 +#define R12A_FLAGS0_OWN 0x80 + + uint32_t txdw1; +#define R12A_TXDW1_MACID_M 0x0000003f +#define R12A_TXDW1_MACID_S 0 +#define R12A_TXDW1_QSEL_M 0x00001f00 +#define R12A_TXDW1_QSEL_S 8 + +#define R12A_TXDW1_QSEL_BE 0x00 /* or 0x03 */ +#define R12A_TXDW1_QSEL_BK 0x01 /* or 0x02 */ +#define R12A_TXDW1_QSEL_VI 0x04 /* or 0x05 */ +#define R12A_TXDW1_QSEL_VO 0x06 /* or 0x07 */ +#define RTWN_MAX_TID 8 + +#define R12A_TXDW1_QSEL_BEACON 0x10 +#define R12A_TXDW1_QSEL_MGNT 0x12 + +#define R12A_TXDW1_RAID_M 0x001f0000 +#define R12A_TXDW1_RAID_S 16 +#define R12A_TXDW1_CIPHER_M 0x00c00000 +#define R12A_TXDW1_CIPHER_S 22 +#define R12A_TXDW1_CIPHER_NONE 0 +#define R12A_TXDW1_CIPHER_RC4 1 +#define R12A_TXDW1_CIPHER_SM4 2 +#define R12A_TXDW1_CIPHER_AES 3 +#define R12A_TXDW1_PKTOFF_M 0x1f000000 +#define R12A_TXDW1_PKTOFF_S 24 + + uint32_t txdw2; +#define R12A_TXDW2_AGGEN 0x00001000 +#define R12A_TXDW2_AGGBK 0x00010000 +#define R12A_TXDW2_MOREFRAG 0x00020000 +#define R12A_TXDW2_SPE_RPT 0x00080000 +#define R12A_TXDW2_AMPDU_DEN_M 0x00700000 +#define R12A_TXDW2_AMPDU_DEN_S 20 + + uint32_t txdw3; +#define R12A_TXDW3_SEQ_SEL_M 0x000000c0 +#define R12A_TXDW3_SEQ_SEL_S 6 +#define R12A_TXDW3_DRVRATE 0x00000100 +#define R12A_TXDW3_DISRTSFB 0x00000200 +#define R12A_TXDW3_DISDATAFB 0x00000400 +#define R12A_TXDW3_CTS2SELF 0x00000800 +#define R12A_TXDW3_RTSEN 0x00001000 +#define R12A_TXDW3_HWRTSEN 0x00002000 +#define R12A_TXDW3_MAX_AGG_M 0x003e0000 +#define R12A_TXDW3_MAX_AGG_S 17 + + uint32_t txdw4; +#define R12A_TXDW4_DATARATE_M 0x0000007f +#define R12A_TXDW4_DATARATE_S 0 +#define R12A_TXDW4_DATARATE_FB_LMT_M 0x00001f00 +#define R12A_TXDW4_DATARATE_FB_LMT_S 8 +#define R12A_TXDW4_RTSRATE_FB_LMT_M 0x0001e000 +#define R12A_TXDW4_RTSRATE_FB_LMT_S 13 +#define R12A_TXDW4_RETRY_LMT_ENA 0x00020000 +#define R12A_TXDW4_RETRY_LMT_M 0x00fc0000 +#define R12A_TXDW4_RETRY_LMT_S 18 +#define R12A_TXDW4_RTSRATE_M 0x1f000000 +#define R12A_TXDW4_RTSRATE_S 24 + + uint32_t txdw5; +#define R12A_TXDW5_DATA_PRIM_CHAN_M 0x0000000f +#define R12A_TXDW5_DATA_PRIM_CHAN_S 0 +#define R12A_TXDW5_PRIM_CHAN_20_80_3 1 +#define R12A_TXDW5_PRIM_CHAN_20_80_2 2 +#define R12A_TXDW5_PRIM_CHAN_20_80_4 3 +#define R12A_TXDW5_PRIM_CHAN_20_80_1 4 +#define R12A_TXDW5_PRIM_CHAN_40_80_1 9 +#define R12A_TXDW5_PRIM_CHAN_40_80_2 10 +#define R12A_TXDW5_DATA_SHORT 0x00000010 +#define R12A_TXDW5_DATA_BW_M 0x00000060 +#define R12A_TXDW5_DATA_BW_S 5 +#define R12A_TXDW5_DATA_BW40 1 +#define R12A_TXDW5_DATA_BW80 2 +#define R12A_TXDW5_DATA_LDPC 0x00000080 +#define R12A_TXDW5_RTS_SHORT 0x00001000 +#define R12A_TXDW5_RTS_PRIM_CHAN_M 0x0001e000 +#define R12A_TXDW5_RTS_PRIM_CHAN_S 13 + + uint32_t txdw6; +#define R21A_TXDW6_MBSSID_M 0x0000f000 +#define R21A_TXDW6_MBSSID_S 12 + + uint32_t reserved; + uint32_t txdw8; +#define R12A_TXDW8_HWSEQ_EN 0x00008000 + + uint32_t txdw9; +#define R12A_TXDW9_SEQ_M 0x00fff000 +#define R12A_TXDW9_SEQ_S 12 +} __packed __attribute__((aligned(4))); + + +/* Rate adaptation modes. */ +#define R12A_RAID_11BGN_2_40 0 +#define R12A_RAID_11BGN_1_40 1 +#define R12A_RAID_11BGN_2 2 +#define R12A_RAID_11BGN_1 3 +#define R12A_RAID_11GN_2 4 +#define R12A_RAID_11GN_1 5 +#define R12A_RAID_11BG 6 +#define R12A_RAID_11G 7 /* "pure" 11g */ +#define R12A_RAID_11B 8 +#define R12A_RAID_11AC_2_80 9 +#define R12A_RAID_11AC_1_80 10 +#define R12A_RAID_11AC_1 11 +#define R12A_RAID_11AC_2 12 + +#endif /* R12A_TX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_var.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_var.h new file mode 100644 index 0000000000..78aad9b209 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/r12a_var.h @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/r12a_var.h 310867 2016-12-30 22:24:01Z avos $ + */ + +#ifndef R12A_VAR_H +#define R12A_VAR_H + +#include + +struct r12a_softc { + uint8_t chip; +#define R12A_CHIP_C_CUT 0x01 + + uint8_t rs_flags; +#define R12A_RXCKSUM_EN 0x01 +#define R12A_RXCKSUM6_EN 0x02 +#define R12A_IQK_RUNNING 0x04 +#define R12A_RADAR_ENABLED 0x08 + + int rs_radar; + struct timeout_task rs_chan_check; + + /* ROM variables */ + int ext_pa_2g:1, + ext_pa_5g:1, + ext_lna_2g:1, + ext_lna_5g:1, + type_pa_2g:4, + type_pa_5g:4, + type_lna_2g:4, + type_lna_5g:4, + bt_coex:1, + bt_ant_num:1; + + uint8_t board_type; + uint8_t regulatory; + uint8_t crystalcap; + + uint8_t rfe_type; + uint8_t tx_bbswing_2g; + uint8_t tx_bbswing_5g; + + uint8_t cck_tx_pwr[R12A_MAX_RF_PATH][R12A_GROUP_2G]; + uint8_t ht40_tx_pwr_2g[R12A_MAX_RF_PATH][R12A_GROUP_2G]; + uint8_t ht40_tx_pwr_5g[R12A_MAX_RF_PATH][R12A_GROUP_5G]; + + int8_t cck_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t ofdm_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw20_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw40_tx_pwr_diff_2g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + + int8_t ofdm_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw20_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw40_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw80_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + int8_t bw160_tx_pwr_diff_5g[R12A_MAX_RF_PATH][R12A_MAX_TX_COUNT]; + + int sc_ant; + + int (*rs_newstate[RTWN_PORT_COUNT])(struct ieee80211vap *, + enum ieee80211_state, int); + void (*rs_scan_start)(struct ieee80211com *); + void (*rs_scan_end)(struct ieee80211com *); + + void (*rs_crystalcap_write)(struct rtwn_softc *); + void (*rs_fix_spur)(struct rtwn_softc *, + struct ieee80211_channel *); + void (*rs_set_band_2ghz)(struct rtwn_softc *, uint32_t); + void (*rs_set_band_5ghz)(struct rtwn_softc *, uint32_t); + void (*rs_init_burstlen)(struct rtwn_softc *); + void (*rs_init_ampdu_fwhw)(struct rtwn_softc *); +#ifndef RTWN_WITHOUT_UCODE + int (*rs_iq_calib_fw_supported)(struct rtwn_softc *); +#endif + void (*rs_iq_calib_sw)(struct rtwn_softc *); + + int ac_usb_dma_size; + int ac_usb_dma_time; + int ampdu_max_time; +}; +#define R12A_SOFTC(_sc) ((struct r12a_softc *)((_sc)->sc_priv)) + +#define rtwn_r12a_fix_spur(_sc, _c) \ + ((R12A_SOFTC(_sc)->rs_fix_spur)((_sc), (_c))) +#define rtwn_r12a_set_band_2ghz(_sc, _rates) \ + ((R12A_SOFTC(_sc)->rs_set_band_2ghz)((_sc), (_rates))) +#define rtwn_r12a_set_band_5ghz(_sc, _rates) \ + ((R12A_SOFTC(_sc)->rs_set_band_5ghz)((_sc), (_rates))) +#define rtwn_r12a_init_burstlen(_sc) \ + ((R12A_SOFTC(_sc)->rs_init_burstlen)((_sc))) +#define rtwn_r12a_init_ampdu_fwhw(_sc) \ + ((R12A_SOFTC(_sc)->rs_init_ampdu_fwhw)((_sc))) +#define rtwn_r12a_crystalcap_write(_sc) \ + ((R12A_SOFTC(_sc)->rs_crystalcap_write)((_sc))) +#ifndef RTWN_WITHOUT_UCODE +#define rtwn_r12a_iq_calib_fw_supported(_sc) \ + ((R12A_SOFTC(_sc)->rs_iq_calib_fw_supported)((_sc))) +#endif +#define rtwn_r12a_iq_calib_sw(_sc) \ + ((R12A_SOFTC(_sc)->rs_iq_calib_sw)((_sc))) + +#endif /* R12A_VAR_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au.h new file mode 100644 index 0000000000..acd42cb78c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au.h @@ -0,0 +1,53 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au.h 335351 2018-06-19 00:38:28Z avos $ + */ + +#ifndef RTL8812AU_H +#define RTL8812AU_H + +#include + + +/* + * Function declarations. + */ +/* r12au_init.c */ +void r12au_init_rx_agg(struct rtwn_softc *); +void r12au_init_burstlen_usb2(struct rtwn_softc *); +void r12au_init_burstlen(struct rtwn_softc *); +void r12au_init_ampdu_fwhw(struct rtwn_softc *); +void r12au_init_ampdu(struct rtwn_softc *); +void r12au_post_init(struct rtwn_softc *); + +/* r12au_rx.c */ +int r12au_classify_intr(struct rtwn_softc *, void *, int); +int r12au_align_rx(int, int); + +/* r12au_tx.c */ +void r12au_dump_tx_desc(struct rtwn_softc *, const void *); + +#endif /* RTL8812AU_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_attach.c new file mode 100644 index 0000000000..86702cfae9 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_attach.c @@ -0,0 +1,298 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au_attach.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include + +#include + +#include +#include +#include + +#include +#include + + +void r12au_attach(struct rtwn_usb_softc *); + +static void +r12au_postattach(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + struct r12a_softc *rs = sc->sc_priv; + + if (usbd_get_speed(uc->uc_udev) == USB_SPEED_SUPER) { + rs->ac_usb_dma_size = 0x07; + rs->ac_usb_dma_time = 0x1a; + } else { + rs->ac_usb_dma_size = 0x01; + rs->ac_usb_dma_time = 0x10; + } + + if (rs->chip & R12A_CHIP_C_CUT) + sc->sc_rf_read = r12a_c_cut_rf_read; + else + sc->sc_rf_read = r12a_rf_read; + + if (rs->board_type == R92C_BOARD_TYPE_MINICARD || + rs->board_type == R92C_BOARD_TYPE_SOLO || + rs->board_type == R92C_BOARD_TYPE_COMBO) + sc->sc_set_led = r88e_set_led; + else + sc->sc_set_led = r12a_set_led; + + if (!(rs->ext_pa_2g || rs->ext_lna_2g || + rs->ext_pa_5g || rs->ext_lna_5g)) + sc->mac_prog = &rtl8812au_mac_no_ext_pa_lna[0]; + + sc->sc_ic.ic_ioctl = r12a_ioctl_net; +} + +void +r12a_vap_preattach(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct r12a_softc *rs = sc->sc_priv; + struct ifnet *ifp = vap->iv_ifp; + + ifp->if_capabilities = IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6; + RTWN_LOCK(sc); + if (rs->rs_flags & R12A_RXCKSUM_EN) + ifp->if_capenable |= IFCAP_RXCSUM; + if (rs->rs_flags & R12A_RXCKSUM6_EN) + ifp->if_capenable |= IFCAP_RXCSUM_IPV6; + RTWN_UNLOCK(sc); +} + +static void +r12a_attach_private(struct rtwn_softc *sc) +{ + struct r12a_softc *rs; + + rs = malloc(sizeof(struct r12a_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); + + rs->rs_flags = R12A_RXCKSUM_EN | R12A_RXCKSUM6_EN; + + rs->rs_fix_spur = r12a_fix_spur; + rs->rs_set_band_2ghz = r12a_set_band_2ghz; + rs->rs_set_band_5ghz = r12a_set_band_5ghz; + rs->rs_init_burstlen = r12au_init_burstlen; + rs->rs_init_ampdu_fwhw = r12au_init_ampdu_fwhw; + rs->rs_crystalcap_write = r12a_crystalcap_write; +#ifndef RTWN_WITHOUT_UCODE + rs->rs_iq_calib_fw_supported = r12a_iq_calib_fw_supported; +#endif + rs->rs_iq_calib_sw = r12a_iq_calib_sw; + + rs->ampdu_max_time = 0x70; + + sc->sc_priv = rs; +} + +void +r12a_detach_private(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + + free(rs, M_RTWN_PRIV); +} + +static void +r12a_read_chipid_vendor(struct rtwn_softc *sc, uint32_t reg_sys_cfg) +{ + struct r12a_softc *rs = sc->sc_priv; + + if (MS(reg_sys_cfg, R92C_SYS_CFG_CHIP_VER_RTL) == 1) + rs->chip |= R12A_CHIP_C_CUT; +} + +static void +r12au_adj_devcaps(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + struct ieee80211com *ic = &sc->sc_ic; + + if (rs->chip & R12A_CHIP_C_CUT) { + ic->ic_htcaps |= IEEE80211_HTCAP_LDPC | + IEEE80211_HTC_TXLDPC; + } + + /* TODO: STBC, VHT etc */ +} + +void +r12au_attach(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + + /* USB part. */ + uc->uc_align_rx = r12au_align_rx; + uc->tx_agg_desc_num = 1; + + /* Common part. */ + sc->sc_flags = RTWN_FLAG_EXT_HDR; + + sc->sc_set_chan = r12a_set_chan; + sc->sc_fill_tx_desc = r12a_fill_tx_desc; + sc->sc_fill_tx_desc_raw = r12a_fill_tx_desc_raw; + sc->sc_fill_tx_desc_null = r12a_fill_tx_desc_null; + sc->sc_dump_tx_desc = r12au_dump_tx_desc; + sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags; + sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags; + sc->sc_get_rx_stats = r12a_get_rx_stats; + sc->sc_get_rssi_cck = r88e_get_rssi_cck; + sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; + sc->sc_classify_intr = r12au_classify_intr; + sc->sc_handle_tx_report = r12a_ratectl_tx_complete; + sc->sc_handle_c2h_report = r12a_handle_c2h_report; + sc->sc_check_frame = r12a_check_frame_checksum; + sc->sc_rf_write = r12a_rf_write; + sc->sc_check_condition = r12a_check_condition; + sc->sc_efuse_postread = rtwn_nop_softc; + sc->sc_parse_rom = r12a_parse_rom; + sc->sc_power_on = r12a_power_on; + sc->sc_power_off = r12a_power_off; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_fw_reset = r12a_fw_reset; + sc->sc_fw_download_enable = r12a_fw_download_enable; +#endif + sc->sc_llt_init = r92c_llt_init; + sc->sc_set_page_size = r12a_set_page_size; + sc->sc_lc_calib = r12a_lc_calib; + sc->sc_iq_calib = r12a_iq_calib; + sc->sc_read_chipid_vendor = r12a_read_chipid_vendor; + sc->sc_adj_devcaps = r12au_adj_devcaps; + sc->sc_vap_preattach = r12a_vap_preattach; + sc->sc_postattach = r12au_postattach; + sc->sc_detach_private = r12a_detach_private; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_set_media_status = r12a_set_media_status; + sc->sc_set_rsvd_page = r88e_set_rsvd_page; + sc->sc_set_pwrmode = r12a_set_pwrmode; + sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO */ +#else + sc->sc_set_media_status = rtwn_nop_softc_int; +#endif + sc->sc_beacon_init = r12a_beacon_init; + sc->sc_beacon_enable = r92c_beacon_enable; + sc->sc_beacon_set_rate = r12a_beacon_set_rate; + sc->sc_beacon_select = rtwn_nop_softc_int; + sc->sc_temp_measure = r88e_temp_measure; + sc->sc_temp_read = r88e_temp_read; + sc->sc_init_tx_agg = r92cu_init_tx_agg; + sc->sc_init_rx_agg = r12au_init_rx_agg; + sc->sc_init_ampdu = r12au_init_ampdu; + sc->sc_init_intr = r12a_init_intr; + sc->sc_init_edca = r12a_init_edca; + sc->sc_init_bb = r12a_init_bb; + sc->sc_init_rf = r12a_init_rf; + sc->sc_init_antsel = r12a_init_antsel; + sc->sc_post_init = r12au_post_init; + sc->sc_init_bcnq1_boundary = rtwn_nop_int_softc; + + sc->chan_list_5ghz[0] = r12a_chan_5ghz_0; + sc->chan_list_5ghz[1] = r12a_chan_5ghz_1; + sc->chan_list_5ghz[2] = r12a_chan_5ghz_2; + sc->chan_num_5ghz[0] = nitems(r12a_chan_5ghz_0); + sc->chan_num_5ghz[1] = nitems(r12a_chan_5ghz_1); + sc->chan_num_5ghz[2] = nitems(r12a_chan_5ghz_2); + + sc->mac_prog = &rtl8812au_mac[0]; + sc->mac_size = nitems(rtl8812au_mac); + sc->bb_prog = &rtl8812au_bb[0]; + sc->bb_size = nitems(rtl8812au_bb); + sc->agc_prog = &rtl8812au_agc[0]; + sc->agc_size = nitems(rtl8812au_agc); + sc->rf_prog = &rtl8812au_rf[0]; + + sc->name = "RTL8812AU"; + sc->fwname = "rtwn-rtl8812aufw"; + sc->fwsig = 0x950; + + sc->page_count = R12A_TX_PAGE_COUNT; + sc->pktbuf_count = R12A_TXPKTBUF_COUNT; + + sc->ackto = 0x80; + sc->npubqpages = R12A_PUBQ_NPAGES; + sc->page_size = R12A_TX_PAGE_SIZE; + + sc->txdesc_len = sizeof(struct r12au_tx_desc); + sc->efuse_maxlen = R12A_EFUSE_MAX_LEN; + sc->efuse_maplen = R12A_EFUSE_MAP_LEN; + sc->rx_dma_size = R12A_RX_DMA_BUFFER_SIZE; + + sc->macid_limit = R12A_MACID_MAX + 1; + sc->cam_entry_limit = R12A_CAM_ENTRY_COUNT; + sc->fwsize_limit = R12A_MAX_FW_SIZE; + sc->temp_delta = R88E_CALIB_THRESHOLD; + + sc->bcn_status_reg[0] = R92C_TDECTRL; + sc->bcn_status_reg[1] = R92C_TDECTRL; + sc->rcr = R12A_RCR_DIS_CHK_14 | + R12A_RCR_VHT_ACK | + R12A_RCR_TCP_OFFLD_EN; + + sc->ntxchains = 2; + sc->nrxchains = 2; + + r12a_attach_private(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_init.c new file mode 100644 index 0000000000..532a78758a --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_init.c @@ -0,0 +1,200 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au_init.c 335351 2018-06-19 00:38:28Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include +#include + + +void +r12au_init_rx_agg(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + + /* Rx aggregation (USB). */ + rtwn_write_2(sc, R92C_RXDMA_AGG_PG_TH, + rs->ac_usb_dma_size | (rs->ac_usb_dma_time << 8)); + rtwn_setbits_1(sc, R92C_TRXDMA_CTRL, 0, + R92C_TRXDMA_CTRL_RXDMA_AGG_EN); +} + +void +r12au_init_burstlen_usb2(struct rtwn_softc *sc) +{ + const uint8_t dma_count = R12A_DMA_MODE | SM(R12A_BURST_CNT, 3); + + if ((rtwn_read_1(sc, R92C_USB_INFO) & 0x30) == 0) { + /* Set burst packet length to 512 B. */ + rtwn_setbits_1(sc, R12A_RXDMA_PRO, R12A_BURST_SZ_M, + dma_count | SM(R12A_BURST_SZ, R12A_BURST_SZ_USB2)); + } else { + /* Set burst packet length to 64 B. */ + rtwn_setbits_1(sc, R12A_RXDMA_PRO, R12A_BURST_SZ_M, + dma_count | SM(R12A_BURST_SZ, R12A_BURST_SZ_USB1)); + } +} + +void +r12au_init_burstlen(struct rtwn_softc *sc) +{ + const uint8_t dma_count = R12A_DMA_MODE | SM(R12A_BURST_CNT, 3); + + if (rtwn_read_1(sc, R92C_TYPE_ID + 3) & 0x80) + r12au_init_burstlen_usb2(sc); + else { /* USB 3.0 */ + /* Set burst packet length to 1 KB. */ + rtwn_setbits_1(sc, R12A_RXDMA_PRO, R12A_BURST_SZ_M, + dma_count | SM(R12A_BURST_SZ, R12A_BURST_SZ_USB3)); + + rtwn_setbits_1(sc, 0xf008, 0x18, 0); + } +} + +static void +r12au_arfb_init(struct rtwn_softc *sc) +{ + /* ARFB table 9 for 11ac 5G 2SS. */ + rtwn_write_4(sc, R12A_ARFR_5G(0), 0x00000010); + rtwn_write_4(sc, R12A_ARFR_5G(0) + 4, 0xfffff000); + + /* ARFB table 10 for 11ac 5G 1SS. */ + rtwn_write_4(sc, R12A_ARFR_5G(1), 0x00000010); + rtwn_write_4(sc, R12A_ARFR_5G(1) + 4, 0x003ff000); + + /* ARFB table 11 for 11ac 2G 1SS. */ + rtwn_write_4(sc, R12A_ARFR_2G(0), 0x00000015); + rtwn_write_4(sc, R12A_ARFR_2G(0) + 4, 0x003ff000); + + /* ARFB table 12 for 11ac 2G 2SS. */ + rtwn_write_4(sc, R12A_ARFR_2G(1), 0x00000015); + rtwn_write_4(sc, R12A_ARFR_2G(1) + 4, 0xffcff000); +} + +void +r12au_init_ampdu_fwhw(struct rtwn_softc *sc) +{ + rtwn_setbits_1(sc, R92C_FWHW_TXQ_CTRL, + R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW, 0); +} + +void +r12au_init_ampdu(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + + /* Rx interval (USB3). */ + rtwn_write_1(sc, 0xf050, 0x01); + + /* burst length = 4 */ + rtwn_write_2(sc, R92C_RXDMA_STATUS, 0x7400); + + rtwn_write_1(sc, R92C_RXDMA_STATUS + 1, 0xf5); + + /* Setup AMPDU aggregation. */ + rtwn_write_1(sc, R12A_AMPDU_MAX_TIME, rs->ampdu_max_time); + rtwn_write_4(sc, R12A_AMPDU_MAX_LENGTH, 0xffffffff); + + /* 80 MHz clock (again?) */ + rtwn_write_1(sc, R92C_USTIME_TSF, 0x50); + rtwn_write_1(sc, R92C_USTIME_EDCA, 0x50); + + rtwn_r12a_init_burstlen(sc); + + /* Enable single packet AMPDU. */ + rtwn_setbits_1(sc, R12A_HT_SINGLE_AMPDU, 0, + R12A_HT_SINGLE_AMPDU_PKT_ENA); + + /* 11K packet length for VHT. */ + rtwn_write_1(sc, R92C_RX_PKT_LIMIT, 0x18); + + rtwn_write_1(sc, R92C_PIFS, 0); + + rtwn_write_2(sc, R92C_MAX_AGGR_NUM, 0x1f1f); + + rtwn_r12a_init_ampdu_fwhw(sc); + + /* Do not reset MAC. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL, 0, 0x60); + + r12au_arfb_init(sc); +} + +void +r12au_post_init(struct rtwn_softc *sc) +{ + + /* Setup RTS BW (equal to data BW). */ + rtwn_setbits_1(sc, R92C_QUEUE_CTRL, 0x08, 0); + + rtwn_write_1(sc, R12A_EARLY_MODE_CONTROL + 3, 0x01); + + /* Reset USB mode switch setting. */ + rtwn_write_1(sc, R12A_SDIO_CTRL, 0); + rtwn_write_1(sc, R92C_ACLK_MON, 0); + + rtwn_write_1(sc, R92C_USB_HRPWM, 0); + +#ifndef RTWN_WITHOUT_UCODE + if (sc->sc_flags & RTWN_FW_LOADED) { + if (sc->sc_ratectl_sysctl == RTWN_RATECTL_FW) { + /* TODO: implement */ + sc->sc_ratectl = RTWN_RATECTL_NET80211; + } else + sc->sc_ratectl = sc->sc_ratectl_sysctl; + } else +#endif + sc->sc_ratectl = RTWN_RATECTL_NONE; +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_reg.h new file mode 100644 index 0000000000..5310600a86 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_reg.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R12AU_REG_H +#define R12AU_REG_H + +#include +#include + +#endif /* R12AU_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_rx.c new file mode 100644 index 0000000000..bdf8f55bc4 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_rx.c @@ -0,0 +1,89 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au_rx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include + + +int +r12au_classify_intr(struct rtwn_softc *sc, void *buf, int len) +{ + struct r92c_rx_stat *stat = buf; + uint32_t rxdw2 = le32toh(stat->rxdw2); + + if (rxdw2 & R12A_RXDW2_RPT_C2H) { + int pos = sizeof(struct r92c_rx_stat); + /* Check if Rx descriptor + command id/sequence fits. */ + if (len < pos + 2) /* unknown, skip */ + return (RTWN_RX_DATA); + + if (((uint8_t *)buf)[pos] == R12A_C2H_TX_REPORT) + return (RTWN_RX_TX_REPORT); + else + return (RTWN_RX_OTHER); + } else + return (RTWN_RX_DATA); +} + +int +r12au_align_rx(int totlen, int len) +{ + if (totlen < len) + return (roundup2(totlen, 8)); + + return (totlen); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx.c new file mode 100644 index 0000000000..aa63a670c0 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au_tx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r12au_dump_tx_desc(struct rtwn_softc *sc, const void *desc) +{ +#ifdef RTWN_DEBUG + const struct r12au_tx_desc *txd = desc; + + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT_DESC, + "%s: len %d, off %d, flags0 %02X, dw: 1 %08X, 2 %08X, 3 %08X, " + "4 %08X, 5 %08X, 6 %08X, sum %04X, flags7 %04X, 8 %08X, 9 %08X\n", + __func__, le16toh(txd->pktlen), txd->offset, txd->flags0, + le32toh(txd->txdw1), le32toh(txd->txdw2), le32toh(txd->txdw3), + le32toh(txd->txdw4), le32toh(txd->txdw5), le32toh(txd->txdw6), + le16toh(txd->txdsum), le16toh(txd->flags7), le32toh(txd->txdw8), + le32toh(txd->txdw9)); +#endif +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx_desc.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx_desc.h new file mode 100644 index 0000000000..2356f62c39 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8812a/usb/r12au_tx_desc.h @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8812a/usb/r12au_tx_desc.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R12AU_TX_DESC_H +#define R12AU_TX_DESC_H + +#include + +/* Tx MAC descriptor (USB). */ +struct r12au_tx_desc { + uint16_t pktlen; + uint8_t offset; + uint8_t flags0; + + uint32_t txdw1; + uint32_t txdw2; + uint32_t txdw3; + uint32_t txdw4; + uint32_t txdw5; + uint32_t txdw6; + + uint16_t txdsum; + uint16_t flags7; +#define R12AU_FLAGS7_AGGNUM_M 0xff00 +#define R12AU_FLAGS7_AGGNUM_S 8 + + uint32_t txdw8; + uint32_t txdw9; +} __packed __attribute__((aligned(4))); + +#endif /* R12AU_TX_DESC_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a.h new file mode 100644 index 0000000000..cb8f25a149 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a.h @@ -0,0 +1,80 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTL8821A_H +#define RTL8821A_H + +/* + * Global definitions. + */ +#define R21A_TX_PAGE_COUNT 243 +#define R21A_BCNQ0_PAGE_COUNT 8 +#define R21A_BCNQ0_BOUNDARY \ + (R21A_TX_PAGE_COUNT + R21A_BCNQ0_PAGE_COUNT + 1) + +#define R21A_TX_PAGE_SIZE 256 + + +/* + * Function declarations. + */ +/* r21a_beacon.c */ +void r21a_beacon_init(struct rtwn_softc *, void *, int); +void r21a_beacon_select(struct rtwn_softc *, int); + +/* r21a_calib.c */ +#ifndef RTWN_WITHOUT_UCODE +int r21a_iq_calib_fw_supported(struct rtwn_softc *); +#endif +void r21a_iq_calib_sw(struct rtwn_softc *); + +/* r21a_chan.c */ +void r21a_set_band_2ghz(struct rtwn_softc *, uint32_t); +void r21a_set_band_5ghz(struct rtwn_softc *, uint32_t); + +/* r21a_fw.c */ +void r21a_fw_reset(struct rtwn_softc *, int); + +/* r21a_init.c */ +int r21a_power_on(struct rtwn_softc *); +void r21a_power_off(struct rtwn_softc *); +int r21a_check_condition(struct rtwn_softc *, const uint8_t[]); +void r21a_crystalcap_write(struct rtwn_softc *); +int r21a_init_bcnq1_boundary(struct rtwn_softc *); +void r21a_init_ampdu_fwhw(struct rtwn_softc *); + +/* r21a_led.c */ +void r21a_set_led(struct rtwn_softc *, int, int); + +/* r21a_rom.c */ +void r21a_parse_rom(struct rtwn_softc *, uint8_t *); + +/* r21a_rx.c */ +int8_t r21a_get_rssi_cck(struct rtwn_softc *, void *); + +#endif /* RTL8821A_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_beacon.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_beacon.c new file mode 100644 index 0000000000..9a9a6ae634 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_beacon.c @@ -0,0 +1,93 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_beacon.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + + +void +r21a_beacon_init(struct rtwn_softc *sc, void *buf, int id) +{ + struct r12a_tx_desc *txd = (struct r12a_tx_desc *)buf; + + r12a_beacon_init(sc, buf, id); + + /* XXX sequence number for beacon 1 is not stable. */ + txd->txdw3 &= ~htole32(R12A_TXDW3_SEQ_SEL_M); + txd->txdw3 |= htole32(SM(R12A_TXDW3_SEQ_SEL, id * 2)); +} + +void +r21a_beacon_select(struct rtwn_softc *sc, int id) +{ + switch (id) { + case 0: + /* Switch to port 0 beacon. */ + rtwn_setbits_1_shift(sc, R21A_DWBCN1_CTRL, + R21A_DWBCN1_CTRL_SEL_BCN1, 0, 2); + break; + case 1: + /* Switch to port 1 beacon. */ + rtwn_setbits_1_shift(sc, R21A_DWBCN1_CTRL, + 0, R21A_DWBCN1_CTRL_SEL_BCN1, 2); + break; + default: + KASSERT(0, ("wrong port id %d\n", id)); + break; + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_calib.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_calib.c new file mode 100644 index 0000000000..473a8306d5 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_calib.c @@ -0,0 +1,126 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_calib.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + + +#ifndef RTWN_WITHOUT_UCODE +int +r21a_iq_calib_fw_supported(struct rtwn_softc *sc) +{ + if (sc->fwver == 0x16) + return (1); + + return (0); +} +#endif + +void +r21a_iq_calib_sw(struct rtwn_softc *sc) +{ +#define R21A_MAX_NRXCHAINS 2 + uint32_t saved_bb_vals[nitems(r21a_iq_bb_regs)]; + uint32_t saved_afe_vals[nitems(r21a_iq_afe_regs)]; + uint32_t saved_rf_vals[nitems(r21a_iq_rf_regs) * R21A_MAX_NRXCHAINS]; + + KASSERT(sc->nrxchains <= R21A_MAX_NRXCHAINS, + ("nrxchains > %d (%d)\n", R21A_MAX_NRXCHAINS, sc->nrxchains)); + + RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB, "%s: SW IQ calibration: TODO\n", + __func__); + + /* Save registers. */ + r12a_save_bb_afe_vals(sc, saved_bb_vals, r21a_iq_bb_regs, + nitems(r21a_iq_bb_regs)); + r12a_save_bb_afe_vals(sc, saved_afe_vals, r21a_iq_afe_regs, + nitems(r21a_iq_afe_regs)); + r12a_save_rf_vals(sc, saved_rf_vals, r21a_iq_rf_regs, + nitems(r21a_iq_rf_regs)); + +#ifdef RTWN_TODO + /* Configure MAC. */ + r12a_iq_config_mac(sc); + r21a_iq_tx(sc); +#endif + + /* Restore registers. */ + r12a_restore_rf_vals(sc, saved_rf_vals, r21a_iq_rf_regs, + nitems(r21a_iq_rf_regs)); + r12a_restore_bb_afe_vals(sc, saved_afe_vals, r21a_iq_afe_regs, + nitems(r21a_iq_afe_regs)); + + /* Select page C1. */ + rtwn_bb_setbits(sc, R12A_TXAGC_TABLE_SELECT, 0, 0x80000000); + + rtwn_bb_write(sc, R12A_SLEEP_NAV(0), 0); + rtwn_bb_write(sc, R12A_PMPD(0), 0); + rtwn_bb_write(sc, 0xc88, 0); + rtwn_bb_write(sc, 0xc8c, 0x3c000000); + rtwn_bb_write(sc, 0xc90, 0x80); + rtwn_bb_write(sc, 0xc94, 0); + rtwn_bb_write(sc, 0xcc4, 0x20040000); + rtwn_bb_write(sc, 0xcc8, 0x20000000); + rtwn_bb_write(sc, 0xcb8, 0); + + r12a_restore_bb_afe_vals(sc, saved_bb_vals, r21a_iq_bb_regs, + nitems(r21a_iq_bb_regs)); +#undef R21A_MAX_NRXCHAINS +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_chan.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_chan.c new file mode 100644 index 0000000000..cef3258dcf --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_chan.c @@ -0,0 +1,153 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_chan.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include +#include + + +static void +r21a_bypass_ext_lna_2ghz(struct rtwn_softc *sc) +{ + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x00100000, 0); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x00400000, 0); + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), 0, 0x07); + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), 0, 0x0700); +} + +void +r21a_set_band_2ghz(struct rtwn_softc *sc, uint32_t basicrates) +{ + struct r12a_softc *rs = sc->sc_priv; + + /* Enable CCK / OFDM. */ + rtwn_bb_setbits(sc, R12A_OFDMCCK_EN, + 0, R12A_OFDMCCK_EN_CCK | R12A_OFDMCCK_EN_OFDM); + + /* Turn off RF PA and LNA. */ + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), + R12A_RFE_PINMUX_LNA_MASK, 0x7000); + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), + R12A_RFE_PINMUX_PA_A_MASK, 0x70); + + if (rs->ext_lna_2g) { + /* Turn on 2.4 GHz external LNA. */ + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0, 0x00100000); + rtwn_bb_setbits(sc, R12A_RFE_INV(0), 0x00400000, 0); + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), 0x05, 0x02); + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), 0x0500, 0x0200); + } else { + /* Bypass 2.4 GHz external LNA. */ + r21a_bypass_ext_lna_2ghz(sc); + } + + /* Select AGC table. */ + rtwn_bb_setbits(sc, R12A_TX_SCALE(0), 0x0f00, 0); + + rtwn_bb_setbits(sc, R12A_TX_PATH, 0xf0, 0x10); + rtwn_bb_setbits(sc, R12A_CCK_RX_PATH, 0x0f000000, 0x01000000); + + /* Write basic rates. */ + rtwn_set_basicrates(sc, basicrates); + + rtwn_write_1(sc, R12A_CCK_CHECK, 0); +} + +void +r21a_set_band_5ghz(struct rtwn_softc *sc, uint32_t basicrates) +{ + struct r12a_softc *rs = sc->sc_priv; + int ntries; + + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), + R12A_RFE_PINMUX_LNA_MASK, 0x5000); + rtwn_bb_setbits(sc, R12A_RFE_PINMUX(0), + R12A_RFE_PINMUX_PA_A_MASK, 0x40); + + if (rs->ext_lna_2g) { + /* Bypass 2.4 GHz external LNA. */ + r21a_bypass_ext_lna_2ghz(sc); + } + + rtwn_write_1(sc, R12A_CCK_CHECK, R12A_CCK_CHECK_5GHZ); + + for (ntries = 0; ntries < 100; ntries++) { + if ((rtwn_read_2(sc, R12A_TXPKT_EMPTY) & 0x30) == 0x30) + break; + + rtwn_delay(sc, 25); + } + if (ntries == 100) { + device_printf(sc->sc_dev, + "%s: TXPKT_EMPTY check failed (%04X)\n", + __func__, rtwn_read_2(sc, R12A_TXPKT_EMPTY)); + } + + /* Enable OFDM. */ + rtwn_bb_setbits(sc, R12A_OFDMCCK_EN, R12A_OFDMCCK_EN_CCK, + R12A_OFDMCCK_EN_OFDM); + + /* Select AGC table. */ + rtwn_bb_setbits(sc, R12A_TX_SCALE(0), 0x0f00, 0x0100); + + rtwn_bb_setbits(sc, R12A_TX_PATH, 0xf0, 0); + rtwn_bb_setbits(sc, R12A_CCK_RX_PATH, 0, 0x0f000000); + + /* Write basic rates. */ + rtwn_set_basicrates(sc, basicrates); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_fw.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_fw.c new file mode 100644 index 0000000000..a5aaac6a68 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_fw.c @@ -0,0 +1,78 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_fw.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + + +#ifndef RTWN_WITHOUT_UCODE +void +r21a_fw_reset(struct rtwn_softc *sc, int reason) +{ + + /* Reset MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL, 0x02, 0); + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_CPUEN, 0, 1); + + /* Enable MCU IO wrapper. */ + rtwn_setbits_1(sc, R92C_RSV_CTRL, 0x02, 0); + rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01); + + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + 0, R92C_SYS_FUNC_EN_CPUEN, 1); +} +#endif diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_init.c new file mode 100644 index 0000000000..ef1c4fd215 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_init.c @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_init.c 312680 2017-01-24 02:35:38Z kevlo $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include +#include + + +int +r21a_power_on(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + int ntries; + + /* Clear suspend and power down bits.*/ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_APDM_HPDN, 0, 1)); + + /* Disable GPIO9 as EXT WAKEUP. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0x01, 0)); + + /* Enable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + /* Enable LDOA12 MACRO block for all interfaces. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_LDOA15_CTRL, 0, R92C_LDOA15_CTRL_EN)); + + /* Disable BT_GPS_SEL pins. */ + RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0x10, 0)); + + /* 1 ms delay. */ + rtwn_delay(sc, 1000); + + /* Release analog Ips to digital isolation. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, + R92C_SYS_ISO_CTRL_IP2MAC, 0)); + + /* Disable SW LPS and WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APFM_RSM | + R92C_APS_FSMCO_AFSM_HSUS | + R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + /* Wait for power ready bit. */ + for (ntries = 0; ntries < 5000; ntries++) { + if (rtwn_read_4(sc, R92C_APS_FSMCO) & R92C_APS_FSMCO_SUS_HOST) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for chip power up\n"); + return (ETIMEDOUT); + } + + /* Release WLON reset. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_RDY_MACON, 2)); + + /* Disable HWPDN. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_APDM_HPDN, 0, 1)); + + /* Disable WL suspend. */ + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, + R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); + + RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_APFM_ONMAC, 1)); + for (ntries = 0; ntries < 5000; ntries++) { + if (!(rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_ONMAC)) + break; + rtwn_delay(sc, 10); + } + if (ntries == 5000) + return (ETIMEDOUT); + + /* Switch DPDT_SEL_P output from WL BB. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_LEDCFG3, 0, 0x01)); + + /* switch for PAPE_G/PAPE_A from WL BB; switch LNAON from WL BB. */ + RTWN_CHK(rtwn_setbits_1(sc, 0x067, 0, 0x30)); + + RTWN_CHK(rtwn_setbits_1(sc, 0x025, 0x40, 0)); + + /* Enable falling edge triggering interrupt. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0, 0x02)); + + /* Enable GPIO9 interrupt mode. */ + RTWN_CHK(rtwn_setbits_1(sc, 0x063, 0, 0x02)); + + /* Enable GPIO9 input mode. */ + RTWN_CHK(rtwn_setbits_1(sc, 0x062, 0x02, 0)); + + /* Enable HSISR GPIO interrupt. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR, 0, 0x01)); + + /* Enable HSISR GPIO9 interrupt. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_HSIMR + 2, 0, 0x02)); + + /* XTAL trim. */ + RTWN_CHK(rtwn_setbits_1(sc, R92C_APE_PLL_CTRL_EXT + 2, 0xFF, 0x82)); + + RTWN_CHK(rtwn_setbits_1(sc, R92C_AFE_MISC, 0, 0x40)); + + /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ + RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0x0000)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, + R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | + R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | + R92C_CR_PROTOCOL_EN | R92C_CR_SCHEDULE_EN | + ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | + R92C_CR_CALTMR_EN)); + + if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN) + RTWN_CHK(rtwn_setbits_1(sc, R92C_LDO_SWR_CTRL, 0, 0x40)); + + return (0); +#undef RTWN_CHK +} + +void +r21a_power_off(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + int error, ntries; + + /* Stop Rx. */ + error = rtwn_write_1(sc, R92C_CR, 0); + if (error == ENXIO) /* hardware gone */ + return; + + /* Move card to Low Power state. */ + /* Block all Tx queues. */ + rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + + for (ntries = 0; ntries < 10; ntries++) { + /* Should be zero if no packet is transmitting. */ + if (rtwn_read_4(sc, R88E_SCH_TXCMD) == 0) + break; + + rtwn_delay(sc, 5000); + } + if (ntries == 10) { + device_printf(sc->sc_dev, "%s: failed to block Tx queues\n", + __func__); + return; + } + + /* CCK and OFDM are disabled, and clock are gated. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0); + + rtwn_delay(sc, 1); + + /* Reset whole BB. */ + rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); + + /* Reset MAC TRX. */ + rtwn_write_1(sc, R92C_CR, + R92C_CR_HCI_TXDMA_EN | R92C_CR_HCI_RXDMA_EN); + + /* check if removed later. (?) */ + rtwn_setbits_1_shift(sc, R92C_CR, R92C_CR_ENSEC, 0, 1); + + /* Respond TxOK to scheduler */ + rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK); + + /* If firmware in ram code, do reset. */ +#ifndef RTWN_WITHOUT_UCODE + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) + r21a_fw_reset(sc, RTWN_FW_RESET_SHUTDOWN); +#endif + + /* Reset MCU. */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_CPUEN, + 0, 1); + rtwn_write_1(sc, R92C_MCUFWDL, 0); + + /* Move card to Disabled state. */ + /* Turn off RF. */ + rtwn_write_1(sc, R92C_RF_CTRL, 0); + + rtwn_setbits_1(sc, R92C_LEDCFG3, 0x01, 0); + + /* Enable rising edge triggering interrupt. */ + rtwn_setbits_1(sc, R92C_GPIO_INTM + 1, 0x02, 0); + + /* Release WLON reset. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, + R92C_APS_FSMCO_RDY_MACON, 2); + + /* Turn off MAC by HW state machine */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_OFF, + 1); + for (ntries = 0; ntries < 10; ntries++) { + /* Wait until it will be disabled. */ + if ((rtwn_read_2(sc, R92C_APS_FSMCO) & + R92C_APS_FSMCO_APFM_OFF) == 0) + break; + + rtwn_delay(sc, 5000); + } + if (ntries == 10) { + device_printf(sc->sc_dev, "%s: could not turn off MAC\n", + __func__); + return; + } + + /* Analog Ips to digital isolation. */ + rtwn_setbits_1(sc, R92C_SYS_ISO_CTRL, 0, R92C_SYS_ISO_CTRL_IP2MAC); + + /* Disable LDOA12 MACRO block. */ + rtwn_setbits_1(sc, R92C_LDOA15_CTRL, R92C_LDOA15_CTRL_EN, 0); + + /* Enable WL suspend. */ + rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE, + R92C_APS_FSMCO_AFSM_HSUS, 1); + + /* Enable GPIO9 as EXT WAKEUP. */ + rtwn_setbits_1(sc, R92C_GPIO_INTM + 2, 0, 0x01); + + rs->rs_flags &= ~(R12A_IQK_RUNNING | R12A_RADAR_ENABLED); +} + +int +r21a_check_condition(struct rtwn_softc *sc, const uint8_t cond[]) +{ + struct r12a_softc *rs = sc->sc_priv; + uint8_t mask; + int i; + + RTWN_DPRINTF(sc, RTWN_DEBUG_RESET, + "%s: condition byte 0: %02X; ext 5ghz pa/lna %d/%d\n", + __func__, cond[0], rs->ext_pa_5g, rs->ext_lna_5g); + + if (cond[0] == 0) + return (1); + + mask = 0; + if (rs->ext_pa_5g) + mask |= R21A_COND_EXT_PA_5G; + if (rs->ext_lna_5g) + mask |= R21A_COND_EXT_LNA_5G; + if (rs->bt_coex) + mask |= R21A_COND_BT; + if (!rs->ext_pa_2g && !rs->ext_lna_2g && + !rs->ext_pa_5g && !rs->ext_lna_5g && !rs->bt_coex) + mask = R21A_COND_BOARD_DEF; + + if (mask == 0) + return (0); + + for (i = 0; i < RTWN_MAX_CONDITIONS && cond[i] != 0; i++) + if (cond[i] == mask) + return (1); + + return (0); +} + +void +r21a_crystalcap_write(struct rtwn_softc *sc) +{ + struct r12a_softc *rs = sc->sc_priv; + uint32_t reg; + uint8_t val; + + val = rs->crystalcap & 0x3f; + reg = rtwn_bb_read(sc, R92C_MAC_PHY_CTRL); + reg = RW(reg, R21A_MAC_PHY_CRYSTALCAP, val | (val << 6)); + rtwn_bb_write(sc, R92C_MAC_PHY_CTRL, reg); +} + +int +r21a_init_bcnq1_boundary(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + RTWN_CHK(rtwn_write_1(sc, R88E_TXPKTBUF_BCNQ1_BDNY, + R21A_BCNQ0_BOUNDARY)); + RTWN_CHK(rtwn_write_1(sc, R21A_DWBCN1_CTRL + 1, + R21A_BCNQ0_BOUNDARY)); + RTWN_CHK(rtwn_setbits_1_shift(sc, R21A_DWBCN1_CTRL, 0, + R21A_DWBCN1_CTRL_SEL_EN, 2)); + + return (0); +#undef RTWN_CHK +} + +void +r21a_init_ampdu_fwhw(struct rtwn_softc *sc) +{ + rtwn_write_1(sc, R92C_FWHW_TXQ_CTRL, + R92C_FWHW_TXQ_CTRL_AMPDU_RTY_NEW); + rtwn_write_4(sc, R92C_FAST_EDCA_CTRL, 0x03087777); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_led.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_led.c new file mode 100644 index 0000000000..62b58ea8da --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_led.c @@ -0,0 +1,67 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_led.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include + + +void +r21a_set_led(struct rtwn_softc *sc, int led, int on) +{ + if (led == RTWN_LED_LINK) { + rtwn_write_1(sc, R92C_LEDCFG2, + R12A_LEDCFG2_ENA | (on ? 0 : R92C_LEDCFG0_DIS)); + sc->ledlink = on; /* Save LED state. */ + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_priv.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_priv.h new file mode 100644 index 0000000000..31c3d80e78 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_priv.h @@ -0,0 +1,464 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_priv.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R21A_PRIV_H +#define R21A_PRIV_H + +/* + * MAC initialization values. + */ +static const struct rtwn_mac_prog rtl8821au_mac[] = { + { 0x421, 0x0f }, { 0x428, 0x0a }, { 0x429, 0x10 }, { 0x430, 0x00 }, + { 0x431, 0x00 }, { 0x432, 0x00 }, { 0x433, 0x01 }, { 0x434, 0x04 }, + { 0x435, 0x05 }, { 0x436, 0x07 }, { 0x437, 0x08 }, { 0x43c, 0x04 }, + { 0x43d, 0x05 }, { 0x43e, 0x07 }, { 0x43f, 0x08 }, { 0x440, 0x5d }, + { 0x441, 0x01 }, { 0x442, 0x00 }, { 0x444, 0x10 }, { 0x445, 0x00 }, + { 0x446, 0x00 }, { 0x447, 0x00 }, { 0x448, 0x00 }, { 0x449, 0xf0 }, + { 0x44a, 0x0f }, { 0x44b, 0x3e }, { 0x44c, 0x10 }, { 0x44d, 0x00 }, + { 0x44e, 0x00 }, { 0x44f, 0x00 }, { 0x450, 0x00 }, { 0x451, 0xf0 }, + { 0x452, 0x0f }, { 0x453, 0x00 }, { 0x456, 0x5e }, { 0x460, 0x66 }, + { 0x461, 0x66 }, { 0x4c8, 0x3f }, { 0x4c9, 0xff }, { 0x4cc, 0xff }, + { 0x4cd, 0xff }, { 0x4ce, 0x01 }, { 0x500, 0x26 }, { 0x501, 0xa2 }, + { 0x502, 0x2f }, { 0x503, 0x00 }, { 0x504, 0x28 }, { 0x505, 0xa3 }, + { 0x506, 0x5e }, { 0x507, 0x00 }, { 0x508, 0x2b }, { 0x509, 0xa4 }, + { 0x50a, 0x5e }, { 0x50b, 0x00 }, { 0x50c, 0x4f }, { 0x50d, 0xa4 }, + { 0x50e, 0x00 }, { 0x50f, 0x00 }, { 0x512, 0x1c }, { 0x514, 0x0a }, + { 0x516, 0x0a }, { 0x525, 0x4f }, { 0x550, 0x10 }, { 0x551, 0x10 }, + { 0x559, 0x02 }, { 0x55c, 0x50 }, { 0x55d, 0xff }, { 0x605, 0x30 }, + { 0x607, 0x07 }, { 0x608, 0x0e }, { 0x609, 0x2a }, { 0x620, 0xff }, + { 0x621, 0xff }, { 0x622, 0xff }, { 0x623, 0xff }, { 0x624, 0xff }, + { 0x625, 0xff }, { 0x626, 0xff }, { 0x627, 0xff }, { 0x638, 0x50 }, + { 0x63c, 0x0a }, { 0x63d, 0x0a }, { 0x63e, 0x0e }, { 0x63f, 0x0e }, + { 0x640, 0x40 }, { 0x642, 0x40 }, { 0x643, 0x00 }, { 0x652, 0xc8 }, + { 0x66e, 0x05 }, { 0x700, 0x21 }, { 0x701, 0x43 }, { 0x702, 0x65 }, + { 0x703, 0x87 }, { 0x708, 0x21 }, { 0x709, 0x43 }, { 0x70a, 0x65 }, + { 0x70b, 0x87 }, { 0x718, 0x40 } +}; + + +/* + * Baseband initialization values. + */ +#define R21A_COND_EXT_PA_5G 0x01 +#define R21A_COND_EXT_LNA_5G 0x02 +#define R21A_COND_BOARD_DEF 0x04 +#define R21A_COND_BT 0x08 + +static const uint16_t rtl8821au_bb_regs[] = { + 0x800, 0x804, 0x808, 0x80c, 0x810, 0x814, 0x818, 0x820, 0x824, + 0x828, 0x82c, 0x830, 0x834, 0x838, 0x83c, 0x840, 0x844, 0x848, + 0x84c, 0x850, 0x854, 0x858, 0x85c, 0x860, 0x864, 0x868, 0x86c, + 0x870, 0x874, 0x878, 0x87c, 0x8a0, 0x8a4, 0x8a8, 0x8ac, 0x8b4, + 0x8b8, 0x8bc, 0x8c0, 0x8c4, 0x8c8, 0x8cc, 0x8d4, 0x8d8, 0x8f8, + 0x8fc, 0x900, 0x90c, 0x910, 0x914, 0x918, 0x91c, 0x920, 0x924, + 0x928, 0x92c, 0x930, 0x934, 0x960, 0x964, 0x968, 0x96c, 0x970, + 0x974, 0x978, 0x97c, 0x980, 0x984, 0x988, 0x990, 0x994, 0x998, + 0x99c, 0x9a0, 0x9a4, 0x9a8, 0x9ac, 0x9b0, 0x9b4, 0x9b8, 0x9bc, + 0x9d0, 0x9d4, 0x9d8, 0x9dc, 0x9e0, 0x9e4, 0x9e8, 0xa00, 0xa04, + 0xa08, 0xa0c, 0xa10, 0xa14, 0xa18, 0xa1c, 0xa20, 0xa24, 0xa28, + 0xa2c, 0xa70, 0xa74, 0xa78, 0xa7c, 0xa80, 0xa84, 0xb00, 0xb04, + 0xb08, 0xb0c, 0xb10, 0xb14, 0xb18, 0xb1c, 0xb20, 0xb24, 0xb28, + 0xb2c, 0xb30, 0xb34, 0xb38, 0xb3c, 0xb40, 0xb44, 0xb48, 0xb4c, + 0xb50, 0xb54, 0xb58, 0xb5c, 0xc00, 0xc04, 0xc08, 0xc0c, 0xc10, + 0xc14, 0xc1c, 0xc20, 0xc24, 0xc28, 0xc2c, 0xc30, 0xc34, 0xc38, + 0xc3c, 0xc40, 0xc44, 0xc48, 0xc4c, 0xc50, 0xc54, 0xc58, 0xc5c, + 0xc60, 0xc64, 0xc68, 0xc6c, 0xc70, 0xc74, 0xc78, 0xc7c, 0xc80, + 0xc84, 0xc94, 0xc98, 0xc9c, 0xca0, 0xca4, 0xca8, 0xcb0, 0xcb4, + 0xcb8 +}; + +static const uint32_t rtl8821au_bb_vals[] = { + 0x0020d090, 0x080112e0, 0x0e028211, 0x92131111, 0x20101261, + 0x020c3d10, 0x03a00385, 0x00000000, 0x00030fe0, 0x00000000, + 0x002081dd, 0x2aaaeec8, 0x0037a706, 0x06489b44, 0x0000095b, + 0xc0000001, 0x40003cde, 0x62103f8b, 0x6cfdffb8, 0x28874706, + 0x0001520c, 0x8060e000, 0x74210168, 0x6929c321, 0x79727432, + 0x8ca7a314, 0x888c2878, 0x08888888, 0x31612c2e, 0x00000152, + 0x000fd000, 0x00000013, 0x7f7f7f7f, 0xa2000338, 0x0ff0fa0a, + 0x000fc080, 0x6c10d7ff, 0x0ca52090, 0x1bf00020, 0x00000000, + 0x00013169, 0x08248492, 0x940008a0, 0x290b5612, 0x400002c0, + 0x00000000, 0x00000700, 0x00000000, 0x0000fc00, 0x00000404, + 0x1c1028c0, 0x64b11a1c, 0xe0767233, 0x055aa500, 0x00000004, + 0xfffe0000, 0xfffffffe, 0x001fffff, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x801fffff, 0x000003ff, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x27100000, + 0xffff0100, 0xffffff5c, 0xffffffff, 0x000000ff, 0x00480080, + 0x00000000, 0x00000000, 0x81081008, 0x01081008, 0x01081008, + 0x01081008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00005d00, 0x00000003, 0x00000001, 0x00d047c8, 0x01ff800c, + 0x8c8a8300, 0x2e68000f, 0x9500bb78, 0x11144028, 0x00881117, + 0x89140f00, 0x1a1b0000, 0x090e1317, 0x00000204, 0x00900000, + 0x101fff00, 0x00000008, 0x00000900, 0x225b0606, 0x21805490, + 0x001f0000, 0x03100040, 0x0000b000, 0xae0201eb, 0x01003207, + 0x00009807, 0x01000000, 0x00000002, 0x00000002, 0x0000001f, + 0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c, 0x13121110, + 0x17161514, 0x0000003a, 0x00000000, 0x00000000, 0x13000032, + 0x48080000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000007, 0x00042020, 0x80410231, 0x00000000, 0x00000100, + 0x01000000, 0x40000003, 0x2c2c2c2c, 0x30303030, 0x30303030, + 0x2c2c2c2c, 0x2c2c2c2c, 0x2c2c2c2c, 0x2c2c2c2c, 0x2a2a2a2a, + 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x2a2a2a2a, 0x00000020, + 0x001c1208, 0x30000c1c, 0x00000058, 0x34344443, 0x07003333, + 0x19791979, 0x19791979, 0x19791979, 0x19791979, 0x19791979, + 0x19791979, 0x19791979, 0x19791979, 0x0100005c, 0x00000000, + 0x00000000, 0x00000029, 0x08040201, 0x80402010, 0x77775747, + 0x10000077, 0x00508240 +}; + +static const struct rtwn_bb_prog rtl8821au_bb[] = { + { + nitems(rtl8821au_bb_regs), + rtl8821au_bb_regs, + rtl8821au_bb_vals, + { 0 }, + NULL + } +}; + +static const uint32_t rtl8821au_agc_vals0[] = { + 0xbf000001, 0xbf020001, 0xbf040001, 0xbf060001, 0xbe080001, + 0xbd0a0001, 0xbc0c0001, 0xba0e0001, 0xb9100001, 0xb8120001, + 0xb7140001, 0xb6160001, 0xb5180001, 0xb41a0001, 0xb31c0001, + 0xb21e0001, 0xb1200001, 0xb0220001, 0xaf240001, 0xae260001, + 0xad280001, 0xac2a0001, 0xab2c0001, 0xaa2e0001, 0xa9300001, + 0xa8320001, 0xa7340001, 0xa6360001, 0xa5380001, 0xa43a0001, + 0x683c0001, 0x673e0001, 0x66400001, 0x65420001, 0x64440001, + 0x63460001, 0x62480001, 0x614a0001, 0x474c0001, 0x464e0001, + 0x45500001, 0x44520001, 0x43540001, 0x42560001, 0x41580001, + 0x285a0001, 0x275c0001, 0x265e0001, 0x25600001, 0x24620001, + 0x0a640001, 0x09660001, 0x08680001, 0x076a0001, 0x066c0001, + 0x056e0001, 0x04700001, 0x03720001, 0x02740001, 0x01760001, + 0x01780001, 0x017a0001, 0x017c0001, 0x017e0001 +}, rtl8821au_agc_vals1_pa_lna_5g[] = { + 0xfb000101, 0xfa020101, 0xf9040101, 0xf8060101, 0xf7080101, + 0xf60a0101, 0xf50c0101, 0xf40e0101, 0xf3100101, 0xf2120101, + 0xf1140101, 0xf0160101, 0xef180101, 0xee1a0101, 0xed1c0101, + 0xec1e0101, 0xeb200101, 0xea220101, 0xe9240101, 0xe8260101, + 0xe7280101, 0xe62a0101, 0xe52c0101, 0xe42e0101, 0xe3300101, + 0xa5320101, 0xa4340101, 0xa3360101, 0x87380101, 0x863a0101, + 0x853c0101, 0x843e0101, 0x69400101, 0x68420101, 0x67440101, + 0x66460101, 0x49480101, 0x484a0101, 0x474c0101, 0x2a4e0101, + 0x29500101, 0x28520101, 0x27540101, 0x26560101, 0x25580101, + 0x245a0101, 0x235c0101, 0x055e0101, 0x04600101, 0x03620101, + 0x02640101, 0x01660101, 0x01680101, 0x016a0101, 0x016c0101, + 0x016e0101, 0x01700101, 0x01720101 +}, rtl8821au_agc_vals1[] = { + 0xff000101, 0xff020101, 0xfe040101, 0xfd060101, 0xfc080101, + 0xfd0a0101, 0xfc0c0101, 0xfb0e0101, 0xfa100101, 0xf9120101, + 0xf8140101, 0xf7160101, 0xf6180101, 0xf51a0101, 0xf41c0101, + 0xf31e0101, 0xf2200101, 0xf1220101, 0xf0240101, 0xef260101, + 0xee280101, 0xed2a0101, 0xec2c0101, 0xeb2e0101, 0xea300101, + 0xe9320101, 0xe8340101, 0xe7360101, 0xe6380101, 0xe53a0101, + 0xe43c0101, 0xe33e0101, 0xa5400101, 0xa4420101, 0xa3440101, + 0x87460101, 0x86480101, 0x854a0101, 0x844c0101, 0x694e0101, + 0x68500101, 0x67520101, 0x66540101, 0x49560101, 0x48580101, + 0x475a0101, 0x2a5c0101, 0x295e0101, 0x28600101, 0x27620101, + 0x26640101, 0x25660101, 0x24680101, 0x236a0101, 0x056c0101, + 0x046e0101, 0x03700101, 0x02720101 +}, rtl8821au_agc_vals2[] = { + 0x01740101, 0x01760101, 0x01780101, 0x017a0101, 0x017c0101, + 0x017e0101 +}; + +static const struct rtwn_agc_prog rtl8821au_agc[] = { + { + nitems(rtl8821au_agc_vals0), + rtl8821au_agc_vals0, + { 0 }, + NULL + }, + /* + * For devices with external 5GHz PA / LNA. + */ + { + nitems(rtl8821au_agc_vals1_pa_lna_5g), + rtl8821au_agc_vals1_pa_lna_5g, + { R21A_COND_EXT_PA_5G | R21A_COND_EXT_LNA_5G, 0 }, + /* + * Others. + */ + &(const struct rtwn_agc_prog){ + nitems(rtl8821au_agc_vals1), + rtl8821au_agc_vals1, + { 0 }, + NULL + } + }, + { + nitems(rtl8821au_agc_vals2), + rtl8821au_agc_vals2, + { 0 }, + NULL + } +}; + + +/* + * RF initialization values. + */ +static const uint8_t rtl8821au_rf_regs0[] = { + 0x18, 0x56, 0x66, 0x00, 0x1e, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0xef, 0x3e, 0x3f, + 0x3e, 0x3f, 0x3e, 0x3f, 0x3e, 0x3f, 0xef, 0x18, 0x89, 0x8b, 0xef, + 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, + 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, + 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, + 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, + 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, + 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0x3a, 0x3b, 0x3c, 0xef, 0xef +}, rtl8821au_rf_regs1[] = { + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34 +}, rtl8821au_rf_regs2[] = { + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0xef, 0x18, + 0xef +}, rtl8821au_rf_regs3[] = { + 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0xef, 0x18, + 0xef, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0xef, 0xef, 0x3c, 0x3c +}, rtl8821au_rf_regs4[] = { + 0x3c, 0xef, 0x18, 0xef, 0x08, 0xef, 0xdf, 0x1f, 0x58, 0x59, 0x61, + 0x62, 0x63, 0x64, 0x65 +}, rtl8821au_rf_regs5[] = { + 0x18, 0xef, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, + 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xef, 0xef, 0x34, 0x34, + 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0xef, 0xed, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0xed, 0xed, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xed, + 0xef, 0xdf, 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0xef, 0x51, + 0x52, 0x53, 0x54, 0x56, 0x51, 0x52, 0x53, 0x70, 0x71, 0x72, 0x74, + 0x35, 0x35, 0x35, 0x36, 0x36, 0x36, 0x36, 0xed, 0x45, 0x45, 0x45, + 0x46, 0x46, 0x46, 0x46, 0xdf, 0xb3, 0xb4, 0xb7, 0x1c, 0xc4, 0x18, + 0xfe, 0xfe, 0x18, +}; + +static const uint32_t rtl8821au_rf_vals0[] = { + 0x1712a, 0x51cf2, 0x40000, 0x10000, 0x80000, 0x00830, 0x21800, + 0x28000, 0x48000, 0x94838, 0x44980, 0x48000, 0x0d480, 0x42240, + 0xf0380, 0x90000, 0x22852, 0x65540, 0x88001, 0x20000, 0x00380, + 0x90018, 0x20380, 0xa0018, 0x40308, 0xa0018, 0x60018, 0xa0018, + 0x00000, 0x1712a, 0x00080, 0x80180, 0x01000, 0x00244, 0x38027, + 0x82000, 0x00244, 0x30113, 0x82000, 0x0014c, 0x28027, 0x82000, + 0x000cc, 0x27027, 0x42000, 0x0014c, 0x1f913, 0x42000, 0x0010c, + 0x17f10, 0x12000, 0x000d0, 0x08027, 0xca000, 0x00244, 0x78027, + 0x82000, 0x00244, 0x70113, 0x82000, 0x0014c, 0x68027, 0x82000, + 0x000cc, 0x67027, 0x42000, 0x0014c, 0x5f913, 0x42000, 0x0010c, + 0x57f10, 0x12000, 0x000d0, 0x48027, 0xca000, 0x00244, 0xb8027, + 0x82000, 0x00244, 0xb0113, 0x82000, 0x0014c, 0xa8027, 0x82000, + 0x000cc, 0xa7027, 0x42000, 0x0014c, 0x9f913, 0x42000, 0x0010c, + 0x97f10, 0x12000, 0x000d0, 0x88027, 0xca000, 0x00000, 0x01100 +}, rtl8821au_rf_vals1_def_or_bt[] = { + 0x4adf5, 0x49df2, 0x48def, 0x47dec, 0x46de9, 0x45ccb, 0x4488d, + 0x4348d, 0x4248a, 0x4108d, 0x4008a, 0x2adf4, 0x29df1 +}, rtl8821au_rf_vals1_ext_5g[] = { + 0x4a0f3, 0x490b1, 0x480ae, 0x470ab, 0x4608b, 0x45069, 0x44048, + 0x43045, 0x42026, 0x41023, 0x40002, 0x2a0f3, 0x290f0 +}, rtl8821au_rf_vals1[] = { + 0x4adf7, 0x49df3, 0x48def, 0x47dec, 0x46de9, 0x45ccb, 0x4488d, + 0x4348d, 0x4248a, 0x4108d, 0x4008a, 0x2adf7, 0x29df2 +}, rtl8821au_rf_vals2_ext_5g[] = { + 0x280af, 0x270ac, 0x2608b, 0x25069, 0x24048, 0x23045, 0x22026, + 0x21023, 0x20002, 0x0a0d7, 0x090d3, 0x080b1, 0x070ae, 0x0608d, + 0x0506b, 0x0404a, 0x03047, 0x02044, 0x01025, 0x00004, 0x00000, + 0x1712a, 0x00040 +}, rtl8821au_rf_vals2[] = { + 0x28dee, 0x27deb, 0x26ccd, 0x25cca, 0x2488c, 0x2384c, 0x22849, + 0x21449, 0x2004d, 0x0adf7, 0x09df4, 0x08df1, 0x07dee, 0x06dcd, + 0x05ccd, 0x04cca, 0x0388c, 0x02888, 0x01488, 0x00486, 0x00000, + 0x1712a, 0x00040 +}, rtl8821au_rf_vals3_def_or_bt[] = { + 0x00128, 0x08128, 0x10128, 0x201c8, 0x281c8, 0x301c8, 0x401c8, + 0x481c8, 0x501c8, 0x00000, 0x1712a, 0x00010, 0x063b5, 0x0e3b5, + 0x163b5, 0x1e3b5, 0x263b5, 0x2e3b5, 0x363b5, 0x3e3b5, 0x463b5, + 0x4e3b5, 0x563b5, 0x5e3b5, 0x00000, 0x00008, 0x001b6, 0x00492 +}, rtl8821au_rf_vals3[] = { + 0x00145, 0x08145, 0x10145, 0x20196, 0x28196, 0x30196, 0x401c7, + 0x481c7, 0x501c7, 0x00000, 0x1712a, 0x00010, 0x056b3, 0x0d6b3, + 0x156b3, 0x1d6b3, 0x26634, 0x2e634, 0x36634, 0x3e634, 0x467b4, + 0x4e7b4, 0x567b4, 0x5e7b4, 0x00000, 0x00008, 0x0022a, 0x00594 +}, rtl8821au_rf_vals4_def_or_bt[] = { + 0x00800, 0x00000, 0x1712a, 0x00002, 0x02000, 0x00000, 0x000c0, + 0x00064, 0x81184, 0x6016c, 0xefd83, 0x93fcc, 0x110eb, 0x1c27c, + 0x93016 +}, rtl8821au_rf_vals4_ext_5g[] = { + 0x00820, 0x00000, 0x1712a, 0x00002, 0x02000, 0x00000, 0x000c0, + 0x00064, 0x81184, 0x6016c, 0xead53, 0x93bc4, 0x110e9, 0x1c67c, + 0x93015 +}, rtl8821au_rf_vals4[] = { + 0x00900, 0x00000, 0x1712a, 0x00002, 0x02000, 0x00000, 0x000c0, + 0x00064, 0x81184, 0x6016c, 0xead53, 0x93bc4, 0x714e9, 0x1c67c, + 0x91016 +}, rtl8821au_rf_vals5[] = { + 0x00006, 0x02000, 0x3824b, 0x3024b, 0x2844b, 0x20f4b, 0x18f4b, + 0x104b2, 0x08049, 0x00148, 0x7824b, 0x7024b, 0x6824b, 0x60f4b, + 0x58f4b, 0x504b2, 0x48049, 0x40148, 0x00000, 0x00100, 0x0adf3, + 0x09df0, 0x08d70, 0x07d6d, 0x06cee, 0x05ccc, 0x044ec, 0x034ac, + 0x0246d, 0x0106f, 0x0006c, 0x00000, 0x00010, 0x0adf2, 0x09def, + 0x08dec, 0x07de9, 0x06cec, 0x05ce9, 0x044ec, 0x034e9, 0x0246c, + 0x01469, 0x0006c, 0x00000, 0x00001, 0x38da7, 0x300c2, 0x288e2, + 0x200b8, 0x188a5, 0x10fbc, 0x08f71, 0x00240, 0x00000, 0x020a2, + 0x00080, 0x00120, 0x08120, 0x10120, 0x00085, 0x08085, 0x10085, + 0x18085, 0x00000, 0x00c31, 0x00622, 0xfc70b, 0x0017e, 0x51df3, + 0x00c01, 0x006d6, 0xfc649, 0x49661, 0x7843e, 0x00382, 0x51400, + 0x00160, 0x08160, 0x10160, 0x00124, 0x08124, 0x10124, 0x18124, + 0x0000c, 0x00140, 0x08140, 0x10140, 0x00124, 0x08124, 0x10124, + 0x18124, 0x00088, 0xf0e18, 0x1214c, 0x3000c, 0x539d2, 0xafe00, + 0x1f12a, 0x0c350, 0x0c350, 0x1712a, +}; + +static const struct rtwn_rf_prog rtl8821au_rf[] = { + /* RF chain 0. */ + { + nitems(rtl8821au_rf_regs0), + rtl8821au_rf_regs0, + rtl8821au_rf_vals0, + { 0 }, + NULL + }, + /* + * No external PA/LNA; with or without BT. + */ + { + nitems(rtl8821au_rf_regs1), + rtl8821au_rf_regs1, + rtl8821au_rf_vals1_def_or_bt, + { R21A_COND_BOARD_DEF, R21A_COND_BT, 0 }, + /* + * With external 5GHz PA and LNA. + */ + &(const struct rtwn_rf_prog){ + nitems(rtl8821au_rf_regs1), + rtl8821au_rf_regs1, + rtl8821au_rf_vals1_ext_5g, + { R21A_COND_EXT_PA_5G | R21A_COND_EXT_LNA_5G, 0 }, + /* + * Others. + */ + &(const struct rtwn_rf_prog){ + nitems(rtl8821au_rf_regs1), + rtl8821au_rf_regs1, + rtl8821au_rf_vals1, + { 0 }, + NULL + } + } + }, + /* + * With external 5GHz PA and LNA. + */ + { + nitems(rtl8821au_rf_regs2), + rtl8821au_rf_regs2, + rtl8821au_rf_vals2_ext_5g, + { R21A_COND_EXT_PA_5G | R21A_COND_EXT_LNA_5G, 0 }, + /* + * Others. + */ + &(const struct rtwn_rf_prog){ + nitems(rtl8821au_rf_regs2), + rtl8821au_rf_regs2, + rtl8821au_rf_vals2, + { 0 }, + NULL + } + }, + /* + * No external PA/LNA; with or without BT. + */ + { + nitems(rtl8821au_rf_regs3), + rtl8821au_rf_regs3, + rtl8821au_rf_vals3_def_or_bt, + { R21A_COND_BOARD_DEF, R21A_COND_BT, 0 }, + /* + * Others. + */ + &(const struct rtwn_rf_prog){ + nitems(rtl8821au_rf_regs3), + rtl8821au_rf_regs3, + rtl8821au_rf_vals3, + { 0 }, + NULL + } + }, + /* + * No external PA/LNA; with or without BT. + */ + { + nitems(rtl8821au_rf_regs4), + rtl8821au_rf_regs4, + rtl8821au_rf_vals4_def_or_bt, + { R21A_COND_BOARD_DEF, R21A_COND_BT, 0 }, + /* + * With external 5GHz PA and LNA. + */ + &(const struct rtwn_rf_prog){ + nitems(rtl8821au_rf_regs4), + rtl8821au_rf_regs4, + rtl8821au_rf_vals4_ext_5g, + { R21A_COND_EXT_PA_5G | R21A_COND_EXT_LNA_5G, 0 }, + /* + * Others. + */ + &(const struct rtwn_rf_prog){ + nitems(rtl8821au_rf_regs4), + rtl8821au_rf_regs4, + rtl8821au_rf_vals4, + { 0 }, + NULL + } + } + }, + { + nitems(rtl8821au_rf_regs5), + rtl8821au_rf_regs5, + rtl8821au_rf_vals5, + { 0 }, + NULL + }, + { 0, NULL, NULL, { 0 }, NULL } +}; + + +/* + * Registers to save before IQ calibration. + */ +static const uint16_t r21a_iq_bb_regs[] = { + 0x520, 0x550, 0x808, 0xa04, 0x90c, 0xc00, 0x838, 0x82c +}; + +static const uint16_t r21a_iq_afe_regs[] = { + 0xc5c, 0xc60, 0xc64, 0xc68 +}; + +static const uint8_t r21a_iq_rf_regs[] = { + 0x65, 0x8f, 0x0 +}; + +#endif /* R21A_PRIV_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_reg.h new file mode 100644 index 0000000000..9a06f37801 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_reg.h @@ -0,0 +1,50 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R21A_REG_H +#define R21A_REG_H + +#include + +/* + * MAC registers. + */ +/* Tx DMA Configuration. */ +#define R21A_DWBCN0_CTRL R92C_TDECTRL +#define R21A_DWBCN1_CTRL 0x228 + + +/* Bits for R92C_MAC_PHY_CTRL. */ +#define R21A_MAC_PHY_CRYSTALCAP_M 0x00fff000 +#define R21A_MAC_PHY_CRYSTALCAP_S 12 + +/* Bits for R21A_DWBCN1_CTRL. */ +#define R21A_DWBCN1_CTRL_SEL_EN 0x00020000 +#define R21A_DWBCN1_CTRL_SEL_BCN1 0x00100000 + +#endif /* R21A_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rom.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rom.c new file mode 100644 index 0000000000..dfb3b36687 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rom.c @@ -0,0 +1,91 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_rom.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include + + +void +r21a_parse_rom(struct rtwn_softc *sc, uint8_t *buf) +{ + struct r12a_softc *rs = sc->sc_priv; + struct r12a_rom *rom = (struct r12a_rom *)buf; + uint8_t pa_type, lna_type_2g, lna_type_5g; + + /* Read PA/LNA types. */ + pa_type = RTWN_GET_ROM_VAR(rom->pa_type, 0); + lna_type_2g = RTWN_GET_ROM_VAR(rom->lna_type_2g, 0); + lna_type_5g = RTWN_GET_ROM_VAR(rom->lna_type_5g, 0); + + rs->ext_pa_2g = R21A_ROM_IS_PA_EXT_2GHZ(pa_type); + rs->ext_pa_5g = R21A_ROM_IS_PA_EXT_5GHZ(pa_type); + rs->ext_lna_2g = R21A_ROM_IS_LNA_EXT(lna_type_2g); + rs->ext_lna_5g = R21A_ROM_IS_LNA_EXT(lna_type_5g); + + RTWN_LOCK(sc); + rs->bt_coex = + !!(rtwn_read_4(sc, R92C_MULTI_FUNC_CTRL) & R92C_MULTI_BT_FUNC_EN); + RTWN_UNLOCK(sc); + rs->bt_ant_num = (rom->rf_bt_opt & R12A_RF_BT_OPT_ANT_NUM); + + /* Read MAC address. */ + IEEE80211_ADDR_COPY(sc->sc_ic.ic_macaddr, rom->macaddr_21a); + + /* Execute common part of initialization. */ + r12a_parse_rom_common(sc, buf); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rx.c new file mode 100644 index 0000000000..d05880e838 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/r21a_rx.c @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/r21a_rx.c 307529 2016-10-17 20:38:24Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + + +int8_t +r21a_get_rssi_cck(struct rtwn_softc *sc, void *physt) +{ + struct r12a_rx_phystat *stat = (struct r12a_rx_phystat *)physt; + int8_t lna_idx, rssi; + + lna_idx = (stat->cfosho[0] & 0xe0) >> 5; + rssi = -6 - 2*(stat->cfosho[0] & 0x1f); /* Pout - (2 * VGA_idx) */ + + switch (lna_idx) { + case 5: + rssi -= 32; + break; + case 4: + rssi -= 24; + break; + case 2: + rssi -= 11; + break; + case 1: + rssi += 5; + break; + case 0: + rssi += 21; + break; + } + + return (rssi); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au.h new file mode 100644 index 0000000000..c7c4ce65a1 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/usb/r21au.h 335351 2018-06-19 00:38:28Z avos $ + */ + +#ifndef RTL8821AU_H +#define RTL8821AU_H + +#include + + +/* + * Function declarations. + */ +/* r21au_init.c */ +void r21au_init_tx_agg(struct rtwn_softc *); + +/* r21au_dfs.c */ +void r21au_chan_check(void *, int); +int r21au_newstate(struct ieee80211vap *, enum ieee80211_state, int); +void r21au_scan_start(struct ieee80211com *); +void r21au_scan_end(struct ieee80211com *); + +#endif /* RTL8821AU_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_attach.c new file mode 100644 index 0000000000..a42e4b9e98 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_attach.c @@ -0,0 +1,284 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/usb/r21au_attach.c 335351 2018-06-19 00:38:28Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include + +#include + +#include + +#include +#include + +#include +#include + +#include + + +void r21au_attach(struct rtwn_usb_softc *); + +static void +r21a_postattach(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct r12a_softc *rs = sc->sc_priv; + + if (rs->board_type == R92C_BOARD_TYPE_MINICARD || + rs->board_type == R92C_BOARD_TYPE_SOLO || + rs->board_type == R92C_BOARD_TYPE_COMBO) + sc->sc_set_led = r88e_set_led; + else + sc->sc_set_led = r21a_set_led; + + TIMEOUT_TASK_INIT(taskqueue_thread, &rs->rs_chan_check, 0, + r21au_chan_check, sc); + + /* RXCKSUM */ + ic->ic_ioctl = r12a_ioctl_net; + /* DFS */ + rs->rs_scan_start = ic->ic_scan_start; + ic->ic_scan_start = r21au_scan_start; + rs->rs_scan_end = ic->ic_scan_end; + ic->ic_scan_end = r21au_scan_end; +} + +static void +r21au_vap_preattach(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct rtwn_vap *rvp = RTWN_VAP(vap); + struct r12a_softc *rs = sc->sc_priv; + + r12a_vap_preattach(sc, vap); + + /* Install DFS newstate handler (non-monitor vaps only). */ + if (rvp->id != RTWN_VAP_ID_INVALID) { + KASSERT(rvp->id >= 0 && rvp->id <= nitems(rs->rs_newstate), + ("%s: wrong vap id %d\n", __func__, rvp->id)); + + rs->rs_newstate[rvp->id] = vap->iv_newstate; + vap->iv_newstate = r21au_newstate; + } +} + +static void +r21a_attach_private(struct rtwn_softc *sc) +{ + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + struct r12a_softc *rs; + + rs = malloc(sizeof(struct r12a_softc), M_RTWN_PRIV, M_WAITOK | M_ZERO); + + rs->rs_flags = R12A_RXCKSUM_EN | R12A_RXCKSUM6_EN; + + rs->rs_radar = 0; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "radar_detection", CTLFLAG_RDTUN, &rs->rs_radar, + rs->rs_radar, "Enable radar detection (untested)"); + + rs->rs_fix_spur = rtwn_nop_softc_chan; + rs->rs_set_band_2ghz = r21a_set_band_2ghz; + rs->rs_set_band_5ghz = r21a_set_band_5ghz; + rs->rs_init_burstlen = r12au_init_burstlen_usb2; + rs->rs_init_ampdu_fwhw = r21a_init_ampdu_fwhw; + rs->rs_crystalcap_write = r21a_crystalcap_write; +#ifndef RTWN_WITHOUT_UCODE + rs->rs_iq_calib_fw_supported = r21a_iq_calib_fw_supported; +#endif + rs->rs_iq_calib_sw = r21a_iq_calib_sw; + + rs->ampdu_max_time = 0x5e; + + rs->ac_usb_dma_size = 0x01; + rs->ac_usb_dma_time = 0x10; + + sc->sc_priv = rs; +} + +static void +r21au_adj_devcaps(struct rtwn_softc *sc) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct r12a_softc *rs = sc->sc_priv; + + ic->ic_htcaps |= IEEE80211_HTC_TXLDPC; + if (rs->rs_radar != 0) + ic->ic_caps |= IEEE80211_C_DFS; + + /* TODO: VHT */ +} + +void +r21au_attach(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + + /* USB part. */ + uc->uc_align_rx = r12au_align_rx; + uc->tx_agg_desc_num = 6; + + /* Common part. */ + sc->sc_flags = RTWN_FLAG_EXT_HDR; + + sc->sc_set_chan = r12a_set_chan; + sc->sc_fill_tx_desc = r12a_fill_tx_desc; + sc->sc_fill_tx_desc_raw = r12a_fill_tx_desc_raw; + sc->sc_fill_tx_desc_null = r12a_fill_tx_desc_null; + sc->sc_dump_tx_desc = r12au_dump_tx_desc; + sc->sc_tx_radiotap_flags = r12a_tx_radiotap_flags; + sc->sc_rx_radiotap_flags = r12a_rx_radiotap_flags; + sc->sc_get_rx_stats = r12a_get_rx_stats; + sc->sc_get_rssi_cck = r21a_get_rssi_cck; + sc->sc_get_rssi_ofdm = r88e_get_rssi_ofdm; + sc->sc_classify_intr = r12au_classify_intr; + sc->sc_handle_tx_report = r12a_ratectl_tx_complete; + sc->sc_handle_c2h_report = r12a_handle_c2h_report; + sc->sc_check_frame = r12a_check_frame_checksum; + sc->sc_rf_read = r12a_c_cut_rf_read; + sc->sc_rf_write = r12a_rf_write; + sc->sc_check_condition = r21a_check_condition; + sc->sc_efuse_postread = rtwn_nop_softc; + sc->sc_parse_rom = r21a_parse_rom; + sc->sc_power_on = r21a_power_on; + sc->sc_power_off = r21a_power_off; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_fw_reset = r21a_fw_reset; + sc->sc_fw_download_enable = r12a_fw_download_enable; +#endif + sc->sc_llt_init = r92c_llt_init; + sc->sc_set_page_size = rtwn_nop_int_softc; + sc->sc_lc_calib = rtwn_nop_softc; /* XXX not used */ + sc->sc_iq_calib = r12a_iq_calib; + sc->sc_read_chipid_vendor = rtwn_nop_softc_uint32; + sc->sc_adj_devcaps = r21au_adj_devcaps; + sc->sc_vap_preattach = r21au_vap_preattach; + sc->sc_postattach = r21a_postattach; + sc->sc_detach_private = r12a_detach_private; +#ifndef RTWN_WITHOUT_UCODE + sc->sc_set_media_status = r12a_set_media_status; + sc->sc_set_rsvd_page = r88e_set_rsvd_page; + sc->sc_set_pwrmode = r12a_set_pwrmode; + sc->sc_set_rssi = rtwn_nop_softc; /* XXX TODO */ +#else + sc->sc_set_media_status = rtwn_nop_softc_int; +#endif + sc->sc_beacon_init = r21a_beacon_init; + sc->sc_beacon_enable = r92c_beacon_enable; + sc->sc_beacon_set_rate = r12a_beacon_set_rate; + sc->sc_beacon_select = r21a_beacon_select; + sc->sc_temp_measure = r88e_temp_measure; + sc->sc_temp_read = r88e_temp_read; + sc->sc_init_tx_agg = r21au_init_tx_agg; + sc->sc_init_rx_agg = r12au_init_rx_agg; + sc->sc_init_ampdu = r12au_init_ampdu; + sc->sc_init_intr = r12a_init_intr; + sc->sc_init_edca = r12a_init_edca; + sc->sc_init_bb = r12a_init_bb; + sc->sc_init_rf = r12a_init_rf; + sc->sc_init_antsel = r12a_init_antsel; + sc->sc_post_init = r12au_post_init; + sc->sc_init_bcnq1_boundary = r21a_init_bcnq1_boundary; + + sc->chan_list_5ghz[0] = r12a_chan_5ghz_0; + sc->chan_list_5ghz[1] = r12a_chan_5ghz_1; + sc->chan_list_5ghz[2] = r12a_chan_5ghz_2; + sc->chan_num_5ghz[0] = nitems(r12a_chan_5ghz_0); + sc->chan_num_5ghz[1] = nitems(r12a_chan_5ghz_1); + sc->chan_num_5ghz[2] = nitems(r12a_chan_5ghz_2); + + sc->mac_prog = &rtl8821au_mac[0]; + sc->mac_size = nitems(rtl8821au_mac); + sc->bb_prog = &rtl8821au_bb[0]; + sc->bb_size = nitems(rtl8821au_bb); + sc->agc_prog = &rtl8821au_agc[0]; + sc->agc_size = nitems(rtl8821au_agc); + sc->rf_prog = &rtl8821au_rf[0]; + + sc->name = "RTL8821AU"; + sc->fwname = "rtwn-rtl8821aufw"; + sc->fwsig = 0x210; + + sc->page_count = R21A_TX_PAGE_COUNT; + sc->pktbuf_count = R12A_TXPKTBUF_COUNT; + + sc->ackto = 0x80; + sc->npubqpages = R12A_PUBQ_NPAGES; + sc->page_size = R21A_TX_PAGE_SIZE; + + sc->txdesc_len = sizeof(struct r12au_tx_desc); + sc->efuse_maxlen = R12A_EFUSE_MAX_LEN; + sc->efuse_maplen = R12A_EFUSE_MAP_LEN; + sc->rx_dma_size = R12A_RX_DMA_BUFFER_SIZE; + + sc->macid_limit = R12A_MACID_MAX + 1; + sc->cam_entry_limit = R12A_CAM_ENTRY_COUNT; + sc->fwsize_limit = R12A_MAX_FW_SIZE; + sc->temp_delta = R88E_CALIB_THRESHOLD; + + sc->bcn_status_reg[0] = R92C_TDECTRL; + sc->bcn_status_reg[1] = R21A_DWBCN1_CTRL; + sc->rcr = R12A_RCR_DIS_CHK_14 | + R12A_RCR_VHT_ACK | + R12A_RCR_TCP_OFFLD_EN; + + sc->ntxchains = 1; + sc->nrxchains = 1; + + r21a_attach_private(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_dfs.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_dfs.c new file mode 100644 index 0000000000..c327b27614 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_dfs.c @@ -0,0 +1,280 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/usb/r21au_dfs.c 310867 2016-12-30 22:24:01Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +#include +#include + + +#define R21AU_RADAR_CHECK_PERIOD (2 * hz) + +static void +r21au_dfs_radar_disable(struct rtwn_softc *sc) +{ + rtwn_bb_setbits(sc, 0x924, 0x00008000, 0); +} + +static int +r21au_dfs_radar_is_enabled(struct rtwn_softc *sc) +{ + return !!(rtwn_bb_read(sc, 0x924) & 0x00008000); +} + +static int +r21au_dfs_radar_reset(struct rtwn_softc *sc) +{ + int error; + + error = rtwn_bb_setbits(sc, 0x924, 0x00008000, 0); + if (error != 0) + return (error); + + return (rtwn_bb_setbits(sc, 0x924, 0, 0x00008000)); +} + +static int +r21au_dfs_radar_enable(struct rtwn_softc *sc) +{ +#define RTWN_CHK(res) do { \ + if (res != 0) \ + return (EIO); \ +} while(0) + + RTWN_ASSERT_LOCKED(sc); + + RTWN_CHK(rtwn_bb_setbits(sc, 0x814, 0x3fffffff, 0x04cc4d10)); + RTWN_CHK(rtwn_bb_setbits(sc, R12A_BW_INDICATION, 0xff, 0x06)); + RTWN_CHK(rtwn_bb_write(sc, 0x918, 0x1c16ecdf)); + RTWN_CHK(rtwn_bb_write(sc, 0x924, 0x0152a400)); + RTWN_CHK(rtwn_bb_write(sc, 0x91c, 0x0fa21a20)); + RTWN_CHK(rtwn_bb_write(sc, 0x920, 0xe0f57204)); + + return (r21au_dfs_radar_reset(sc)); + +#undef RTWN_CHK +} + +static int +r21au_dfs_radar_is_detected(struct rtwn_softc *sc) +{ + return !!(rtwn_bb_read(sc, 0xf98) & 0x00020000); +} + +void +r21au_chan_check(void *arg, int npending __unused) +{ + struct rtwn_softc *sc = arg; + struct r12a_softc *rs = sc->sc_priv; + struct ieee80211com *ic = &sc->sc_ic; + + RTWN_LOCK(sc); +#ifdef DIAGNOSTIC + RTWN_DPRINTF(sc, RTWN_DEBUG_STATE, + "%s: periodical radar detection task\n", __func__); +#endif + + if (!r21au_dfs_radar_is_enabled(sc)) { + if (rs->rs_flags & R12A_RADAR_ENABLED) { + /* should not happen */ + device_printf(sc->sc_dev, + "%s: radar detection was turned off " + "unexpectedly, resetting...\n", __func__); + + /* XXX something more appropriate? */ + ieee80211_restart_all(ic); + } + RTWN_UNLOCK(sc); + return; + } + + if (r21au_dfs_radar_is_detected(sc)) { + r21au_dfs_radar_reset(sc); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, "%s: got radar event\n", + __func__); + + RTWN_UNLOCK(sc); + IEEE80211_LOCK(ic); + + ieee80211_dfs_notify_radar(ic, ic->ic_curchan); + + IEEE80211_UNLOCK(ic); + RTWN_LOCK(sc); + } + + if (rs->rs_flags & R12A_RADAR_ENABLED) { + taskqueue_enqueue_timeout(taskqueue_thread, + &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD); + } + RTWN_UNLOCK(sc); +} + +int +r21au_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) +{ + struct ieee80211com *ic = vap->iv_ic; + struct rtwn_softc *sc = ic->ic_softc; + struct rtwn_vap *rvp = RTWN_VAP(vap); + struct r12a_softc *rs = sc->sc_priv; + int error; + + KASSERT(rvp->id == 0 || rvp->id == 1, + ("%s: unexpected vap id %d\n", __func__, rvp->id)); + + IEEE80211_UNLOCK(ic); + RTWN_LOCK(sc); + + error = 0; + if (nstate == IEEE80211_S_CAC && + !(rs->rs_flags & R12A_RADAR_ENABLED)) { + error = r21au_dfs_radar_enable(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: cannot enable radar detection\n", __func__); + goto fail; + } + rs->rs_flags |= R12A_RADAR_ENABLED; + + RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, + "%s: radar detection was enabled\n", __func__); + + taskqueue_enqueue_timeout(taskqueue_thread, + &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD); + } + + if ((nstate < IEEE80211_S_CAC || nstate == IEEE80211_S_CSA) && + (rs->rs_flags & R12A_RADAR_ENABLED) && + (sc->vaps[!rvp->id] == NULL || + sc->vaps[!rvp->id]->vap.iv_state < IEEE80211_S_CAC || + sc->vaps[!rvp->id]->vap.iv_state == IEEE80211_S_CSA)) { + taskqueue_cancel_timeout(taskqueue_thread, &rs->rs_chan_check, + NULL); + + rs->rs_flags &= ~R12A_RADAR_ENABLED; + r21au_dfs_radar_disable(sc); + + RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, + "%s: radar detection was disabled\n", __func__); + } + +fail: + RTWN_UNLOCK(sc); + IEEE80211_LOCK(ic); + + if (error != 0) + return (error); + + return (rs->rs_newstate[rvp->id](vap, nstate, arg)); +} + +void +r21au_scan_start(struct ieee80211com *ic) +{ + struct rtwn_softc *sc = ic->ic_softc; + struct r12a_softc *rs = sc->sc_priv; + + RTWN_LOCK(sc); + if (rs->rs_flags & R12A_RADAR_ENABLED) { + RTWN_UNLOCK(sc); + while (taskqueue_cancel_timeout(taskqueue_thread, + &rs->rs_chan_check, NULL) != 0) { + taskqueue_drain_timeout(taskqueue_thread, + &rs->rs_chan_check); + } + RTWN_LOCK(sc); + + r21au_dfs_radar_disable(sc); + RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, + "%s: radar detection was (temporarily) disabled\n", + __func__); + } + RTWN_UNLOCK(sc); + + rs->rs_scan_start(ic); +} + +void +r21au_scan_end(struct ieee80211com *ic) +{ + struct rtwn_softc *sc = ic->ic_softc; + struct r12a_softc *rs = sc->sc_priv; + int error; + + RTWN_LOCK(sc); + if (rs->rs_flags & R12A_RADAR_ENABLED) { + error = r21au_dfs_radar_enable(sc); + if (error != 0) { + device_printf(sc->sc_dev, + "%s: cannot re-enable radar detection\n", + __func__); + + /* XXX */ + ieee80211_restart_all(ic); + RTWN_UNLOCK(sc); + return; + } + RTWN_DPRINTF(sc, RTWN_DEBUG_RADAR, + "%s: radar detection was re-enabled\n", __func__); + + taskqueue_enqueue_timeout(taskqueue_thread, + &rs->rs_chan_check, R21AU_RADAR_CHECK_PERIOD); + } + RTWN_UNLOCK(sc); + + rs->rs_scan_end(ic); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_init.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_init.c new file mode 100644 index 0000000000..17ceb4f798 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_init.c @@ -0,0 +1,72 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/usb/r21au_init.c 335351 2018-06-19 00:38:28Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include + +#include + +#include +#include + + +void +r21au_init_tx_agg(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + + r92cu_init_tx_agg(sc); + + rtwn_write_1(sc, R21A_DWBCN1_CTRL, uc->tx_agg_desc_num << 1); +} + diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_reg.h new file mode 100644 index 0000000000..e1d414fa15 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/rtl8821a/usb/r21au_reg.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/rtl8821a/usb/r21au_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef R21AU_REG_H +#define R21AU_REG_H + +#include +#include + +#endif /* R21AU_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.c new file mode 100644 index 0000000000..0c979a39fb --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.c @@ -0,0 +1,491 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_attach.c 321735 2017-07-30 23:35:21Z avos $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include "usbdevs.h" + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +static device_probe_t rtwn_usb_match; +static device_attach_t rtwn_usb_attach; +static device_detach_t rtwn_usb_detach; +static device_suspend_t rtwn_usb_suspend; +static device_resume_t rtwn_usb_resume; + +static int rtwn_usb_alloc_list(struct rtwn_softc *, + struct rtwn_data[], int, int); +static int rtwn_usb_alloc_rx_list(struct rtwn_softc *); +static int rtwn_usb_alloc_tx_list(struct rtwn_softc *); +static void rtwn_usb_free_list(struct rtwn_softc *, + struct rtwn_data data[], int); +static void rtwn_usb_free_rx_list(struct rtwn_softc *); +static void rtwn_usb_free_tx_list(struct rtwn_softc *); +static void rtwn_usb_reset_lists(struct rtwn_softc *, + struct ieee80211vap *); +static void rtwn_usb_reset_tx_list(struct rtwn_usb_softc *, + rtwn_datahead *, struct ieee80211vap *); +static void rtwn_usb_reset_rx_list(struct rtwn_usb_softc *); +static void rtwn_usb_start_xfers(struct rtwn_softc *); +static void rtwn_usb_abort_xfers(struct rtwn_softc *); +static int rtwn_usb_fw_write_block(struct rtwn_softc *, + const uint8_t *, uint16_t, int); +static void rtwn_usb_drop_incorrect_tx(struct rtwn_softc *); +static void rtwn_usb_attach_methods(struct rtwn_softc *); +static void rtwn_usb_sysctlattach(struct rtwn_softc *); + +#define RTWN_CONFIG_INDEX 0 + + +static int +rtwn_usb_match(device_t self) +{ + struct usb_attach_arg *uaa = device_get_ivars(self); + + if (uaa->usb_mode != USB_MODE_HOST) + return (ENXIO); + if (uaa->info.bConfigIndex != RTWN_CONFIG_INDEX) + return (ENXIO); + if (uaa->info.bIfaceIndex != RTWN_IFACE_INDEX) + return (ENXIO); + + return (usbd_lookup_id_by_uaa(rtwn_devs, sizeof(rtwn_devs), uaa)); +} + +static int +rtwn_usb_alloc_list(struct rtwn_softc *sc, struct rtwn_data data[], + int ndata, int maxsz) +{ + int i, error; + + for (i = 0; i < ndata; i++) { + struct rtwn_data *dp = &data[i]; + dp->m = NULL; + dp->buf = malloc(maxsz, M_USBDEV, M_NOWAIT); + if (dp->buf == NULL) { + device_printf(sc->sc_dev, + "could not allocate buffer\n"); + error = ENOMEM; + goto fail; + } + dp->ni = NULL; + } + + return (0); +fail: + rtwn_usb_free_list(sc, data, ndata); + return (error); +} + +static int +rtwn_usb_alloc_rx_list(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + int error, i; + + error = rtwn_usb_alloc_list(sc, uc->uc_rx, RTWN_USB_RX_LIST_COUNT, + uc->uc_rx_buf_size * RTWN_USB_RXBUFSZ_UNIT); + if (error != 0) + return (error); + + STAILQ_INIT(&uc->uc_rx_active); + STAILQ_INIT(&uc->uc_rx_inactive); + + for (i = 0; i < RTWN_USB_RX_LIST_COUNT; i++) + STAILQ_INSERT_HEAD(&uc->uc_rx_inactive, &uc->uc_rx[i], next); + + return (0); +} + +static int +rtwn_usb_alloc_tx_list(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + int error, i; + + error = rtwn_usb_alloc_list(sc, uc->uc_tx, RTWN_USB_TX_LIST_COUNT, + RTWN_USB_TXBUFSZ); + if (error != 0) + return (error); + + STAILQ_INIT(&uc->uc_tx_active); + STAILQ_INIT(&uc->uc_tx_inactive); + STAILQ_INIT(&uc->uc_tx_pending); + + for (i = 0; i < RTWN_USB_TX_LIST_COUNT; i++) + STAILQ_INSERT_HEAD(&uc->uc_tx_inactive, &uc->uc_tx[i], next); + + return (0); +} + +static void +rtwn_usb_free_list(struct rtwn_softc *sc, struct rtwn_data data[], int ndata) +{ + int i; + + for (i = 0; i < ndata; i++) { + struct rtwn_data *dp = &data[i]; + + if (dp->buf != NULL) { + free(dp->buf, M_USBDEV); + dp->buf = NULL; + } + if (dp->ni != NULL) { + ieee80211_free_node(dp->ni); + dp->ni = NULL; + } + if (dp->m != NULL) { + m_freem(dp->m); + dp->m = NULL; + } + } +} + +static void +rtwn_usb_free_rx_list(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + + rtwn_usb_free_list(sc, uc->uc_rx, RTWN_USB_RX_LIST_COUNT); + + uc->uc_rx_stat_len = 0; + uc->uc_rx_off = 0; + + STAILQ_INIT(&uc->uc_rx_active); + STAILQ_INIT(&uc->uc_rx_inactive); +} + +static void +rtwn_usb_free_tx_list(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + + rtwn_usb_free_list(sc, uc->uc_tx, RTWN_USB_TX_LIST_COUNT); + + STAILQ_INIT(&uc->uc_tx_active); + STAILQ_INIT(&uc->uc_tx_inactive); + STAILQ_INIT(&uc->uc_tx_pending); +} + +static void +rtwn_usb_reset_lists(struct rtwn_softc *sc, struct ieee80211vap *vap) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + + RTWN_ASSERT_LOCKED(sc); + + rtwn_usb_reset_tx_list(uc, &uc->uc_tx_active, vap); + rtwn_usb_reset_tx_list(uc, &uc->uc_tx_pending, vap); + if (vap == NULL) { + rtwn_usb_reset_rx_list(uc); + sc->qfullmsk = 0; + } +} + +static void +rtwn_usb_reset_tx_list(struct rtwn_usb_softc *uc, + rtwn_datahead *head, struct ieee80211vap *vap) +{ + struct rtwn_vap *uvp = RTWN_VAP(vap); + struct rtwn_data *dp, *tmp; + int id; + + id = (uvp != NULL ? uvp->id : RTWN_VAP_ID_INVALID); + + STAILQ_FOREACH_SAFE(dp, head, next, tmp) { + if (vap == NULL || (dp->ni == NULL && + (dp->id == id || id == RTWN_VAP_ID_INVALID)) || + (dp->ni != NULL && dp->ni->ni_vap == vap)) { + if (dp->ni != NULL) { + ieee80211_free_node(dp->ni); + dp->ni = NULL; + } + + if (dp->m != NULL) { + m_freem(dp->m); + dp->m = NULL; + } + + STAILQ_REMOVE(head, dp, rtwn_data, next); + STAILQ_INSERT_TAIL(&uc->uc_tx_inactive, dp, next); + } + } +} + +static void +rtwn_usb_reset_rx_list(struct rtwn_usb_softc *uc) +{ + int i; + + for (i = 0; i < RTWN_USB_RX_LIST_COUNT; i++) { + struct rtwn_data *dp = &uc->uc_rx[i]; + + if (dp->m != NULL) { + m_freem(dp->m); + dp->m = NULL; + } + } + uc->uc_rx_stat_len = 0; + uc->uc_rx_off = 0; +} + +static void +rtwn_usb_start_xfers(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + + usbd_transfer_start(uc->uc_xfer[RTWN_BULK_RX]); +} + +static void +rtwn_usb_abort_xfers(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + int i; + + RTWN_ASSERT_LOCKED(sc); + + /* abort any pending transfers */ + RTWN_UNLOCK(sc); + for (i = 0; i < RTWN_N_TRANSFER; i++) + usbd_transfer_drain(uc->uc_xfer[i]); + RTWN_LOCK(sc); +} + +static int +rtwn_usb_fw_write_block(struct rtwn_softc *sc, const uint8_t *buf, + uint16_t reg, int mlen) +{ + int error; + + /* XXX fix this deconst */ + error = rtwn_usb_write_region_1(sc, reg, __DECONST(uint8_t *, buf), + mlen); + + return (error); +} + +static void +rtwn_usb_drop_incorrect_tx(struct rtwn_softc *sc) +{ + + rtwn_setbits_1_shift(sc, R92C_TXDMA_OFFSET_CHK, 0, + R92C_TXDMA_OFFSET_DROP_DATA_EN, 1); +} + +static void +rtwn_usb_attach_methods(struct rtwn_softc *sc) +{ + sc->sc_write_1 = rtwn_usb_write_1; + sc->sc_write_2 = rtwn_usb_write_2; + sc->sc_write_4 = rtwn_usb_write_4; + sc->sc_read_1 = rtwn_usb_read_1; + sc->sc_read_2 = rtwn_usb_read_2; + sc->sc_read_4 = rtwn_usb_read_4; + sc->sc_delay = rtwn_usb_delay; + sc->sc_tx_start = rtwn_usb_tx_start; + sc->sc_start_xfers = rtwn_usb_start_xfers; + sc->sc_reset_lists = rtwn_usb_reset_lists; + sc->sc_abort_xfers = rtwn_usb_abort_xfers; + sc->sc_fw_write_block = rtwn_usb_fw_write_block; + sc->sc_get_qmap = rtwn_usb_get_qmap; + sc->sc_set_desc_addr = rtwn_nop_softc; + sc->sc_drop_incorrect_tx = rtwn_usb_drop_incorrect_tx; + sc->sc_beacon_update_begin = rtwn_nop_softc_vap; + sc->sc_beacon_update_end = rtwn_nop_softc_vap; + sc->sc_beacon_unload = rtwn_nop_softc_int; + + sc->bcn_check_interval = 100; +} + +static void +rtwn_usb_sysctlattach(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); + char str[64]; + int ret; + + ret = snprintf(str, sizeof(str), + "Rx buffer size, 512-byte units [%d...%d]", + RTWN_USB_RXBUFSZ_MIN, RTWN_USB_RXBUFSZ_MAX); + KASSERT(ret > 0, ("ret (%d) <= 0!\n", ret)); + (void) ret; + + uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_DEF; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "rx_buf_size", CTLFLAG_RDTUN, &uc->uc_rx_buf_size, + uc->uc_rx_buf_size, str); + if (uc->uc_rx_buf_size < RTWN_USB_RXBUFSZ_MIN) + uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MIN; + if (uc->uc_rx_buf_size > RTWN_USB_RXBUFSZ_MAX) + uc->uc_rx_buf_size = RTWN_USB_RXBUFSZ_MAX; +} + +static int +rtwn_usb_attach(device_t self) +{ + struct usb_attach_arg *uaa = device_get_ivars(self); + struct rtwn_usb_softc *uc = device_get_softc(self); + struct rtwn_softc *sc = &uc->uc_sc; + struct ieee80211com *ic = &sc->sc_ic; + int error; + + device_set_usb_desc(self); + uc->uc_udev = uaa->device; + sc->sc_dev = self; + ic->ic_name = device_get_nameunit(self); + + /* Need to be initialized early. */ + rtwn_sysctlattach(sc); + rtwn_usb_sysctlattach(sc); + mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF); + + rtwn_usb_attach_methods(sc); + rtwn_usb_attach_private(uc, USB_GET_DRIVER_INFO(uaa)); + + error = rtwn_usb_setup_endpoints(uc); + if (error != 0) + goto detach; + + /* Allocate Tx/Rx buffers. */ + error = rtwn_usb_alloc_rx_list(sc); + if (error != 0) + goto detach; + + error = rtwn_usb_alloc_tx_list(sc); + if (error != 0) + goto detach; + + /* Generic attach. */ + error = rtwn_attach(sc); + if (error != 0) + goto detach; + + return (0); + +detach: + rtwn_usb_detach(self); /* failure */ + return (ENXIO); +} + +static int +rtwn_usb_detach(device_t self) +{ + struct rtwn_usb_softc *uc = device_get_softc(self); + struct rtwn_softc *sc = &uc->uc_sc; + + /* Generic detach. */ + rtwn_detach(sc); + + /* Free Tx/Rx buffers. */ + rtwn_usb_free_tx_list(sc); + rtwn_usb_free_rx_list(sc); + + /* Detach all USB transfers. */ + usbd_transfer_unsetup(uc->uc_xfer, RTWN_N_TRANSFER); + + rtwn_detach_private(sc); + mtx_destroy(&sc->sc_mtx); + + return (0); +} + +static int +rtwn_usb_suspend(device_t self) +{ + struct rtwn_usb_softc *uc = device_get_softc(self); + + rtwn_suspend(&uc->uc_sc); + + return (0); +} + +static int +rtwn_usb_resume(device_t self) +{ + struct rtwn_usb_softc *uc = device_get_softc(self); + + rtwn_resume(&uc->uc_sc); + + return (0); +} + +static device_method_t rtwn_usb_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, rtwn_usb_match), + DEVMETHOD(device_attach, rtwn_usb_attach), + DEVMETHOD(device_detach, rtwn_usb_detach), + DEVMETHOD(device_suspend, rtwn_usb_suspend), + DEVMETHOD(device_resume, rtwn_usb_resume), + + DEVMETHOD_END +}; + +static driver_t rtwn_usb_driver = { + "rtwn", + rtwn_usb_methods, + sizeof(struct rtwn_usb_softc) +}; + +static devclass_t rtwn_usb_devclass; + +DRIVER_MODULE(rtwn_usb, uhub, rtwn_usb_driver, rtwn_usb_devclass, NULL, NULL); +MODULE_VERSION(rtwn_usb, 1); +MODULE_DEPEND(rtwn_usb, usb, 1, 1, 1); +MODULE_DEPEND(rtwn_usb, wlan, 1, 1, 1); +MODULE_DEPEND(rtwn_usb, rtwn, 2, 2, 2); +USB_PNP_HOST_INFO(rtwn_devs); diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.h new file mode 100644 index 0000000000..4993746d7c --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_attach.h @@ -0,0 +1,174 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_attach.h 326503 2017-12-03 22:02:30Z gnn $ + */ + +void r92cu_attach(struct rtwn_usb_softc *); +void r92eu_attach(struct rtwn_usb_softc *); +void r88eu_attach(struct rtwn_usb_softc *); +void r12au_attach(struct rtwn_usb_softc *); +void r21au_attach(struct rtwn_usb_softc *); + +enum { + RTWN_CHIP_RTL8192CU, + RTWN_CHIP_RTL8192EU, + RTWN_CHIP_RTL8188EU, + RTWN_CHIP_RTL8812AU, + RTWN_CHIP_RTL8821AU, + RTWN_CHIP_MAX_USB +}; + +/* various supported device vendors/products */ +static const STRUCT_USB_HOST_ID rtwn_devs[] = { + /* RTL8188CE-VAU/RTL8188CUS/RTL8188RU/RTL8192CU */ +#define RTWN_RTL8192CU_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8192CU) } + RTWN_RTL8192CU_DEV(ABOCOM, RTL8188CU_1), + RTWN_RTL8192CU_DEV(ABOCOM, RTL8188CU_2), + RTWN_RTL8192CU_DEV(ABOCOM, RTL8192CU), + RTWN_RTL8192CU_DEV(ASUS, RTL8192CU), + RTWN_RTL8192CU_DEV(ASUS, USBN10NANO), + RTWN_RTL8192CU_DEV(AZUREWAVE, RTL8188CE_1), + RTWN_RTL8192CU_DEV(AZUREWAVE, RTL8188CE_2), + RTWN_RTL8192CU_DEV(AZUREWAVE, RTL8188CU), + RTWN_RTL8192CU_DEV(BELKIN, F7D2102), + RTWN_RTL8192CU_DEV(BELKIN, RTL8188CU), + RTWN_RTL8192CU_DEV(BELKIN, RTL8192CU), + RTWN_RTL8192CU_DEV(CHICONY, RTL8188CUS_1), + RTWN_RTL8192CU_DEV(CHICONY, RTL8188CUS_2), + RTWN_RTL8192CU_DEV(CHICONY, RTL8188CUS_3), + RTWN_RTL8192CU_DEV(CHICONY, RTL8188CUS_4), + RTWN_RTL8192CU_DEV(CHICONY, RTL8188CUS_5), + RTWN_RTL8192CU_DEV(COREGA, RTL8192CU), + RTWN_RTL8192CU_DEV(DLINK, RTL8188CU), + RTWN_RTL8192CU_DEV(DLINK, RTL8192CU_1), + RTWN_RTL8192CU_DEV(DLINK, RTL8192CU_2), + RTWN_RTL8192CU_DEV(DLINK, RTL8192CU_3), + RTWN_RTL8192CU_DEV(DLINK, DWA131B), + RTWN_RTL8192CU_DEV(EDIMAX, EW7811UN), + RTWN_RTL8192CU_DEV(EDIMAX, RTL8192CU), + RTWN_RTL8192CU_DEV(FEIXUN, RTL8188CU), + RTWN_RTL8192CU_DEV(FEIXUN, RTL8192CU), + RTWN_RTL8192CU_DEV(GUILLEMOT, HWNUP150), + RTWN_RTL8192CU_DEV(HAWKING, RTL8192CU), + RTWN_RTL8192CU_DEV(HP3, RTL8188CU), + RTWN_RTL8192CU_DEV(NETGEAR, WNA1000M), + RTWN_RTL8192CU_DEV(NETGEAR, RTL8192CU), + RTWN_RTL8192CU_DEV(NETGEAR4, RTL8188CU), + RTWN_RTL8192CU_DEV(NOVATECH, RTL8188CU), + RTWN_RTL8192CU_DEV(PLANEX2, RTL8188CU_1), + RTWN_RTL8192CU_DEV(PLANEX2, RTL8188CU_2), + RTWN_RTL8192CU_DEV(PLANEX2, RTL8188CU_3), + RTWN_RTL8192CU_DEV(PLANEX2, RTL8188CU_4), + RTWN_RTL8192CU_DEV(PLANEX2, RTL8188CUS), + RTWN_RTL8192CU_DEV(PLANEX2, RTL8192CU), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CE_0), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CE_1), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CTV), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CU_0), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CU_1), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CU_2), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CU_3), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CU_COMBO), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188CUS), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188RU_1), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188RU_2), + RTWN_RTL8192CU_DEV(REALTEK, RTL8188RU_3), + RTWN_RTL8192CU_DEV(REALTEK, RTL8191CU), + RTWN_RTL8192CU_DEV(REALTEK, RTL8192CE), + RTWN_RTL8192CU_DEV(REALTEK, RTL8192CU), + RTWN_RTL8192CU_DEV(SITECOMEU, RTL8188CU_1), + RTWN_RTL8192CU_DEV(SITECOMEU, RTL8188CU_2), + RTWN_RTL8192CU_DEV(SITECOMEU, RTL8192CU), + RTWN_RTL8192CU_DEV(TRENDNET, RTL8188CU), + RTWN_RTL8192CU_DEV(TRENDNET, RTL8192CU), + RTWN_RTL8192CU_DEV(ZYXEL, RTL8192CU), +#undef RTWN_RTL8192CU_DEV + + /* RTL8192EU */ +#define RTWN_RTL8192EU_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8192EU) } + RTWN_RTL8192EU_DEV(DLINK, DWA131E1), + RTWN_RTL8192EU_DEV(REALTEK, RTL8192EU), + RTWN_RTL8192EU_DEV(TPLINK, WN822NV4), + RTWN_RTL8192EU_DEV(TPLINK, WN823NV2), +#undef RTWN_RTL8192EU_DEV + + /* RTL8188EU */ +#define RTWN_RTL8188EU_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8188EU) } + RTWN_RTL8188EU_DEV(ABOCOM, RTL8188EU), + RTWN_RTL8188EU_DEV(DLINK, DWA123D1), + RTWN_RTL8188EU_DEV(DLINK, DWA125D1), + RTWN_RTL8188EU_DEV(ELECOM, WDC150SU2M), + RTWN_RTL8188EU_DEV(REALTEK, RTL8188ETV), + RTWN_RTL8188EU_DEV(REALTEK, RTL8188EU), +#undef RTWN_RTL8188EU_DEV + + /* RTL8812AU */ +#define RTWN_RTL8812AU_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8812AU) } + RTWN_RTL8812AU_DEV(ASUS, USBAC56), + RTWN_RTL8812AU_DEV(CISCOLINKSYS, WUSB6300), + RTWN_RTL8812AU_DEV(DLINK, DWA182C1), + RTWN_RTL8812AU_DEV(DLINK, DWA180A1), + RTWN_RTL8812AU_DEV(EDIMAX, EW7822UAC), + RTWN_RTL8812AU_DEV(IODATA, WNAC867U), + RTWN_RTL8812AU_DEV(MELCO, WIU3866D), + RTWN_RTL8812AU_DEV(NEC, WL900U), + RTWN_RTL8812AU_DEV(PLANEX2, GW900D), + RTWN_RTL8812AU_DEV(REALTEK, RTL8812AU), + RTWN_RTL8812AU_DEV(SENAO, EUB1200AC), + RTWN_RTL8812AU_DEV(SITECOMEU, WLA7100), + RTWN_RTL8812AU_DEV(TPLINK, T4U), + RTWN_RTL8812AU_DEV(TPLINK, T4UV2), + RTWN_RTL8812AU_DEV(TPLINK, T4UHV2), + RTWN_RTL8812AU_DEV(TRENDNET, TEW805UB), + RTWN_RTL8812AU_DEV(ZYXEL, NWD6605), +#undef RTWN_RTL8812AU_DEV + + /* RTL8821AU */ +#define RTWN_RTL8821AU_DEV(v,p) \ + { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8821AU) } + RTWN_RTL8821AU_DEV(DLINK, DWA171A1), + RTWN_RTL8821AU_DEV(DLINK, DWA172A1), + RTWN_RTL8821AU_DEV(EDIMAX, EW7811UTC_1), + RTWN_RTL8821AU_DEV(EDIMAX, EW7811UTC_2), + RTWN_RTL8821AU_DEV(HAWKING, HD65U), + RTWN_RTL8821AU_DEV(MELCO, WIU2433DM), + RTWN_RTL8821AU_DEV(NETGEAR, A6100) +#undef RTWN_RTL8821AU_DEV +}; + +typedef void (*chip_usb_attach)(struct rtwn_usb_softc *); + +static const chip_usb_attach rtwn_chip_usb_attach[RTWN_CHIP_MAX_USB] = { + [RTWN_CHIP_RTL8192CU] = r92cu_attach, + [RTWN_CHIP_RTL8192EU] = r92eu_attach, + [RTWN_CHIP_RTL8188EU] = r88eu_attach, + [RTWN_CHIP_RTL8812AU] = r12au_attach, + [RTWN_CHIP_RTL8821AU] = r21au_attach +}; + +static __inline void +rtwn_usb_attach_private(struct rtwn_usb_softc *uc, int chip) +{ + rtwn_chip_usb_attach[chip](uc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.c new file mode 100644 index 0000000000..3ddab465d0 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.c @@ -0,0 +1,260 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_ep.c 321735 2017-07-30 23:35:21Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#include + + +static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = { + [RTWN_BULK_RX] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_IN, + .flags = { + .pipe_bof = 1, + .short_xfer_ok = 1 + }, + .callback = rtwn_bulk_rx_callback, + }, + [RTWN_BULK_TX_BE] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = RTWN_USB_TXBUFSZ, + .flags = { + .ext_buffer = 1, + .pipe_bof = 1, + .force_short_xfer = 1, + }, + .callback = rtwn_bulk_tx_callback, + .timeout = RTWN_TX_TIMEOUT, /* ms */ + }, + [RTWN_BULK_TX_BK] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = RTWN_USB_TXBUFSZ, + .flags = { + .ext_buffer = 1, + .pipe_bof = 1, + .force_short_xfer = 1, + }, + .callback = rtwn_bulk_tx_callback, + .timeout = RTWN_TX_TIMEOUT, /* ms */ + }, + [RTWN_BULK_TX_VI] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = RTWN_USB_TXBUFSZ, + .flags = { + .ext_buffer = 1, + .pipe_bof = 1, + .force_short_xfer = 1 + }, + .callback = rtwn_bulk_tx_callback, + .timeout = RTWN_TX_TIMEOUT, /* ms */ + }, + [RTWN_BULK_TX_VO] = { + .type = UE_BULK, + .endpoint = UE_ADDR_ANY, + .direction = UE_DIR_OUT, + .bufsize = RTWN_USB_TXBUFSZ, + .flags = { + .ext_buffer = 1, + .pipe_bof = 1, + .force_short_xfer = 1 + }, + .callback = rtwn_bulk_tx_callback, + .timeout = RTWN_TX_TIMEOUT, /* ms */ + }, +}; + +static void +rtwn_usb_setup_queues(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + int hasnq, haslq, nqueues, nqpages, nrempages; + + /* Get Tx queues to USB endpoints mapping. */ + hasnq = haslq = 0; + switch (uc->ntx) { + case 4: + case 3: + haslq = 1; + /* FALLTHROUGH */ + case 2: + hasnq = 1; + /* FALLTHROUGH */ + default: + break; + } + nqueues = 1 + hasnq + haslq; + + /* Get the number of pages for each queue. */ + nqpages = (sc->page_count - sc->npubqpages) / nqueues; + + /* + * The remaining pages are assigned to the high priority + * queue. + */ + nrempages = (sc->page_count - sc->npubqpages) % nqueues; + + sc->nhqpages = nqpages + nrempages; + sc->nnqpages = (hasnq ? nqpages : 0); + sc->nlqpages = (haslq ? nqpages : 0); +} + +int +rtwn_usb_setup_endpoints(struct rtwn_usb_softc *uc) +{ + struct usb_config *rtwn_config; + struct rtwn_softc *sc = &uc->uc_sc; + const uint8_t iface_index = RTWN_IFACE_INDEX; + struct usb_endpoint *ep, *ep_end; + uint8_t addr[RTWN_MAX_EPOUT]; + int error; + + /* Determine the number of bulk-out pipes. */ + uc->ntx = 0; + ep = uc->uc_udev->endpoints; + ep_end = uc->uc_udev->endpoints + uc->uc_udev->endpoints_max; + for (; ep != ep_end; ep++) { + uint8_t eaddr; + + if ((ep->edesc == NULL) || (ep->iface_index != iface_index)) + continue; + + eaddr = ep->edesc->bEndpointAddress; + RTWN_DPRINTF(sc, RTWN_DEBUG_USB, + "%s: endpoint: addr %u, direction %s\n", __func__, + UE_GET_ADDR(eaddr), UE_GET_DIR(eaddr) == UE_DIR_OUT ? + "output" : "input"); + + if (UE_GET_DIR(eaddr) == UE_DIR_OUT) { + if (uc->ntx == RTWN_MAX_EPOUT) + break; + + addr[uc->ntx++] = UE_GET_ADDR(eaddr); + } + } + if (uc->ntx == 0 || uc->ntx > RTWN_MAX_EPOUT) { + device_printf(sc->sc_dev, + "%s: invalid number of Tx bulk pipes (%d)\n", __func__, + uc->ntx); + return (EINVAL); + } + + rtwn_config = malloc(sizeof(rtwn_config_common), M_TEMP, M_WAITOK); + memcpy(rtwn_config, rtwn_config_common, sizeof(rtwn_config_common)); + + /* NB: keep in sync with rtwn_dma_init(). */ + rtwn_config[RTWN_BULK_TX_VO].endpoint = addr[0]; + switch (uc->ntx) { + case 4: + case 3: + rtwn_config[RTWN_BULK_TX_BE].endpoint = addr[2]; + rtwn_config[RTWN_BULK_TX_BK].endpoint = addr[2]; + rtwn_config[RTWN_BULK_TX_VI].endpoint = addr[1]; + break; + case 2: + rtwn_config[RTWN_BULK_TX_BE].endpoint = addr[1]; + rtwn_config[RTWN_BULK_TX_BK].endpoint = addr[1]; + rtwn_config[RTWN_BULK_TX_VI].endpoint = addr[0]; + break; + case 1: + rtwn_config[RTWN_BULK_TX_BE].endpoint = addr[0]; + rtwn_config[RTWN_BULK_TX_BK].endpoint = addr[0]; + rtwn_config[RTWN_BULK_TX_VI].endpoint = addr[0]; + break; + default: + KASSERT(0, ("unhandled number of endpoints %d\n", uc->ntx)); + break; + } + + rtwn_config[RTWN_BULK_RX].bufsize = + uc->uc_rx_buf_size * RTWN_USB_RXBUFSZ_UNIT; + error = usbd_transfer_setup(uc->uc_udev, &iface_index, + uc->uc_xfer, rtwn_config, RTWN_N_TRANSFER, uc, &sc->sc_mtx); + free(rtwn_config, M_TEMP); + + if (error) { + device_printf(sc->sc_dev, "could not allocate USB transfers, " + "err=%s\n", usbd_errstr(error)); + return (error); + } + + /* Assign pages for each queue (if not done). */ + if (sc->nhqpages == 0 && sc->nnqpages == 0 && sc->nlqpages == 0) + rtwn_usb_setup_queues(uc); + + return (0); +} + +uint16_t +rtwn_usb_get_qmap(struct rtwn_softc *sc) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + + switch (uc->ntx) { + case 1: + return (R92C_TRXDMA_CTRL_QMAP_HQ); + case 2: + return (R92C_TRXDMA_CTRL_QMAP_HQ_NQ); + default: + return (R92C_TRXDMA_CTRL_QMAP_3EP); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.h new file mode 100644 index 0000000000..f2b9548a4d --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_ep.h @@ -0,0 +1,25 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_ep.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef IF_RTWN_EP_H +#define IF_RTWN_EP_H + +int rtwn_usb_setup_endpoints(struct rtwn_usb_softc *); +uint16_t rtwn_usb_get_qmap(struct rtwn_softc *); + +#endif /* IF_RTWN_EP_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.c new file mode 100644 index 0000000000..e06cdbe38b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.c @@ -0,0 +1,179 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_reg.c 307529 2016-10-17 20:38:24Z avos $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +static int rtwn_do_request(struct rtwn_softc *, + struct usb_device_request *, void *); +static int rtwn_usb_read_region_1(struct rtwn_softc *, + uint16_t, uint8_t *, int); + +/* USB Requests. */ +#define R92C_REQ_REGS 0x05 + + +static int +rtwn_do_request(struct rtwn_softc *sc, struct usb_device_request *req, + void *data) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + usb_error_t err; + int ntries = 10; + + RTWN_ASSERT_LOCKED(sc); + + while (ntries--) { + err = usbd_do_request_flags(uc->uc_udev, &sc->sc_mtx, + req, data, 0, NULL, 250 /* ms */); + if (err == USB_ERR_NORMAL_COMPLETION) + return (0); + + RTWN_DPRINTF(sc, RTWN_DEBUG_USB, + "%s: control request failed, %s (retries left: %d)\n", + __func__, usbd_errstr(err), ntries); + if (err == USB_ERR_NOT_CONFIGURED) + return (ENXIO); + + usb_pause_mtx(&sc->sc_mtx, hz / 100); + } + return (EIO); +} + +/* export for rtwn_fw_write_block() */ +int +rtwn_usb_write_region_1(struct rtwn_softc *sc, uint16_t addr, uint8_t *buf, + int len) +{ + usb_device_request_t req; + + req.bmRequestType = UT_WRITE_VENDOR_DEVICE; + req.bRequest = R92C_REQ_REGS; + USETW(req.wValue, addr); + USETW(req.wIndex, 0); + USETW(req.wLength, len); + return (rtwn_do_request(sc, &req, buf)); +} + +int +rtwn_usb_write_1(struct rtwn_softc *sc, uint16_t addr, uint8_t val) +{ + return (rtwn_usb_write_region_1(sc, addr, &val, sizeof(val))); +} + +int +rtwn_usb_write_2(struct rtwn_softc *sc, uint16_t addr, uint16_t val) +{ + val = htole16(val); + return (rtwn_usb_write_region_1(sc, addr, (uint8_t *)&val, sizeof(val))); +} + +int +rtwn_usb_write_4(struct rtwn_softc *sc, uint16_t addr, uint32_t val) +{ + val = htole32(val); + return (rtwn_usb_write_region_1(sc, addr, (uint8_t *)&val, sizeof(val))); +} + +static int +rtwn_usb_read_region_1(struct rtwn_softc *sc, uint16_t addr, uint8_t *buf, + int len) +{ + usb_device_request_t req; + + req.bmRequestType = UT_READ_VENDOR_DEVICE; + req.bRequest = R92C_REQ_REGS; + USETW(req.wValue, addr); + USETW(req.wIndex, 0); + USETW(req.wLength, len); + return (rtwn_do_request(sc, &req, buf)); +} + +uint8_t +rtwn_usb_read_1(struct rtwn_softc *sc, uint16_t addr) +{ + uint8_t val; + + if (rtwn_usb_read_region_1(sc, addr, &val, 1) != 0) + return (0xff); + return (val); +} + +uint16_t +rtwn_usb_read_2(struct rtwn_softc *sc, uint16_t addr) +{ + uint16_t val; + + if (rtwn_usb_read_region_1(sc, addr, (uint8_t *)&val, 2) != 0) + return (0xffff); + return (le16toh(val)); +} + +uint32_t +rtwn_usb_read_4(struct rtwn_softc *sc, uint16_t addr) +{ + uint32_t val; + + if (rtwn_usb_read_region_1(sc, addr, (uint8_t *)&val, 4) != 0) + return (0xffffffff); + return (le32toh(val)); +} + +void +rtwn_usb_delay(struct rtwn_softc *sc, int usec) +{ + + /* 1ms delay as default is too big. */ + if (usec < 1000) + DELAY(usec); + else { + usb_pause_mtx(&sc->sc_mtx, + MAX(msecs_to_ticks(usec / 1000), 1)); + } +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.h new file mode 100644 index 0000000000..0933a10443 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_reg.h @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_reg.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTWN_USB_REG_H +#define RTWN_USB_REG_H + +static __inline uint16_t +rtwn_usb_calc_tx_checksum(void *buf) +{ + uint16_t sum = 0; + int i; + + /* NB: checksum calculation takes into account only first 32 bytes. */ + for (i = 0; i < 32 / 2; i++) + sum ^= ((uint16_t *)buf)[i]; + + return (sum); /* NB: already little endian. */ +} + +int rtwn_usb_write_region_1(struct rtwn_softc *, uint16_t, + uint8_t *, int); +int rtwn_usb_write_1(struct rtwn_softc *, uint16_t, uint8_t); +int rtwn_usb_write_2(struct rtwn_softc *, uint16_t, uint16_t); +int rtwn_usb_write_4(struct rtwn_softc *, uint16_t, uint32_t); +uint8_t rtwn_usb_read_1(struct rtwn_softc *, uint16_t); +uint16_t rtwn_usb_read_2(struct rtwn_softc *, uint16_t); +uint32_t rtwn_usb_read_4(struct rtwn_softc *, uint16_t); +void rtwn_usb_delay(struct rtwn_softc *, int); + +#endif /* RTWN_USB_REG_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.c new file mode 100644 index 0000000000..1a250a4b3b --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.c @@ -0,0 +1,439 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_rx.c 321735 2017-07-30 23:35:21Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#ifdef IEEE80211_SUPPORT_SUPERG +#include +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +static struct mbuf * rtwn_rxeof(struct rtwn_softc *, struct rtwn_data *, + uint8_t *, int); + +static int +rtwn_rx_check_pre_alloc(struct rtwn_softc *sc, + struct rtwn_rx_stat_common *stat) +{ + uint32_t rxdw0; + int pktlen; + + RTWN_ASSERT_LOCKED(sc); + + /* + * don't pass packets to the ieee80211 framework if the driver isn't + * RUNNING. + */ + if (!(sc->sc_flags & RTWN_RUNNING)) + return (-1); + + rxdw0 = le32toh(stat->rxdw0); + if (__predict_false(rxdw0 & (RTWN_RXDW0_CRCERR | RTWN_RXDW0_ICVERR))) { + /* + * This should not happen since we setup our Rx filter + * to not receive these frames. + */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: RX flags error (%s)\n", __func__, + rxdw0 & RTWN_RXDW0_CRCERR ? "CRC" : "ICV"); + return (-1); + } + + pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); + if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack))) { + /* + * Should not happen (because of Rx filter setup). + */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: frame is too short: %d\n", __func__, pktlen); + return (-1); + } + + return (0); +} + +static struct mbuf * +rtwn_rx_copy_to_mbuf(struct rtwn_softc *sc, struct rtwn_rx_stat_common *stat, + int totlen) +{ + struct ieee80211com *ic = &sc->sc_ic; + struct mbuf *m; + + RTWN_ASSERT_LOCKED(sc); + + /* Dump Rx descriptor. */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC, + "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, tsfl %08X\n", + __func__, le32toh(stat->rxdw0), le32toh(stat->rxdw1), + le32toh(stat->rxdw2), le32toh(stat->rxdw3), le32toh(stat->rxdw4), + le32toh(stat->tsf_low)); + + if (rtwn_rx_check_pre_alloc(sc, stat) != 0) + goto fail; + + m = m_get2(totlen, M_NOWAIT, MT_DATA, M_PKTHDR); + if (__predict_false(m == NULL)) { + device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n", + __func__); + goto fail; + } + + /* Finalize mbuf. */ + memcpy(mtod(m, uint8_t *), (uint8_t *)stat, totlen); + m->m_pkthdr.len = m->m_len = totlen; + + if (rtwn_check_frame(sc, m) != 0) { + m_freem(m); + goto fail; + } + + return (m); +fail: + counter_u64_add(ic->ic_ierrors, 1); + return (NULL); +} + +static struct mbuf * +rtwn_rxeof_fragmented(struct rtwn_usb_softc *uc, struct rtwn_data *data, + uint8_t *buf, int len) +{ + struct rtwn_softc *sc = &uc->uc_sc; + struct ieee80211com *ic = &sc->sc_ic; + struct rtwn_rx_stat_common *stat = &uc->uc_rx_stat; + uint32_t rxdw0; + int totlen, pktlen, infosz, min_len; + int orig_len = len; + int alloc_mbuf = 0; + + /* Check if Rx descriptor is not truncated. */ + if (uc->uc_rx_stat_len < sizeof(*stat)) { + min_len = min(sizeof(*stat) - uc->uc_rx_stat_len, len); + memcpy((uint8_t *)stat + uc->uc_rx_stat_len, buf, min_len); + + uc->uc_rx_stat_len += min_len; + buf += min_len; + len -= min_len; + + if (uc->uc_rx_stat_len < sizeof(*stat)) + goto end; + + KASSERT(data->m == NULL, ("%s: data->m != NULL!\n", __func__)); + alloc_mbuf = 1; + + /* Dump Rx descriptor. */ + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV_DESC, + "%s: dw: 0 %08X, 1 %08X, 2 %08X, 3 %08X, 4 %08X, " + "tsfl %08X\n", __func__, le32toh(stat->rxdw0), + le32toh(stat->rxdw1), le32toh(stat->rxdw2), + le32toh(stat->rxdw3), le32toh(stat->rxdw4), + le32toh(stat->tsf_low)); + } + + rxdw0 = le32toh(stat->rxdw0); + pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); + infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8; + totlen = sizeof(*stat) + infosz + pktlen; + if (alloc_mbuf) { + if (rtwn_rx_check_pre_alloc(sc, stat) == 0) { + data->m = m_getm(NULL, totlen, M_NOWAIT, MT_DATA); + if (data->m != NULL) { + m_copyback(data->m, 0, uc->uc_rx_stat_len, + (caddr_t)stat); + + if (rtwn_check_frame(sc, data->m) != 0) { + m_freem(data->m); + data->m = NULL; + counter_u64_add(ic->ic_ierrors, 1); + } + } else + counter_u64_add(ic->ic_ierrors, 1); + } else + counter_u64_add(ic->ic_ierrors, 1); + + uc->uc_rx_off = sizeof(*stat); + } + + /* If mbuf allocation fails just discard the data. */ + min_len = min(totlen - uc->uc_rx_off, len); + if (data->m != NULL) + m_copyback(data->m, uc->uc_rx_off, min_len, buf); + + uc->uc_rx_off += min_len; + if (uc->uc_rx_off == totlen) { + /* Align next frame. */ + min_len = rtwn_usb_align_rx(uc, + orig_len - len + min_len, orig_len); + min_len -= (orig_len - len); + KASSERT(len >= min_len, ("%s: len (%d) < min_len (%d)!\n", + __func__, len, min_len)); + + /* Clear mbuf stats. */ + uc->uc_rx_stat_len = 0; + uc->uc_rx_off = 0; + } + len -= min_len; + buf += min_len; +end: + if (uc->uc_rx_stat_len == 0) + return (rtwn_rxeof(sc, data, buf, len)); + else + return (NULL); +} + +static struct mbuf * +rtwn_rxeof(struct rtwn_softc *sc, struct rtwn_data *data, uint8_t *buf, + int len) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + struct rtwn_rx_stat_common *stat; + struct mbuf *m, *m0 = NULL; + uint32_t rxdw0; + int totlen, pktlen, infosz; + + /* Prepend defragmented frame (if any). */ + if (data->m != NULL) { + m0 = m = data->m; + data->m = NULL; + } + + /* Process packets. */ + while (len >= sizeof(*stat)) { + stat = (struct rtwn_rx_stat_common *)buf; + rxdw0 = le32toh(stat->rxdw0); + + pktlen = MS(rxdw0, RTWN_RXDW0_PKTLEN); + if (__predict_false(pktlen == 0)) + break; + + infosz = MS(rxdw0, RTWN_RXDW0_INFOSZ) * 8; + + /* Make sure everything fits in xfer. */ + totlen = sizeof(*stat) + infosz + pktlen; + if (totlen > len) { + RTWN_DPRINTF(sc, RTWN_DEBUG_RECV, + "%s: frame is fragmented (totlen %d len %d)\n", + __func__, totlen, len); + break; + } + + if (m0 == NULL) + m0 = m = rtwn_rx_copy_to_mbuf(sc, stat, totlen); + else { + m->m_nextpkt = rtwn_rx_copy_to_mbuf(sc, stat, totlen); + if (m->m_nextpkt != NULL) + m = m->m_nextpkt; + } + + /* Align next frame. */ + totlen = rtwn_usb_align_rx(uc, totlen, len); + buf += totlen; + len -= totlen; + } + + if (len > 0) + (void)rtwn_rxeof_fragmented(uc, data, buf, len); + + return (m0); +} + +static struct mbuf * +rtwn_report_intr(struct rtwn_usb_softc *uc, struct usb_xfer *xfer, + struct rtwn_data *data) +{ + struct rtwn_softc *sc = &uc->uc_sc; + struct ieee80211com *ic = &sc->sc_ic; + uint8_t *buf; + int len; + + usbd_xfer_status(xfer, &len, NULL, NULL, NULL); + + if (__predict_false(len < sizeof(struct rtwn_rx_stat_common) && + uc->uc_rx_stat_len == 0)) { + counter_u64_add(ic->ic_ierrors, 1); + return (NULL); + } + + buf = data->buf; + if (uc->uc_rx_stat_len > 0) + return (rtwn_rxeof_fragmented(uc, data, data->buf, len)); + + switch (rtwn_classify_intr(sc, buf, len)) { + case RTWN_RX_DATA: + return (rtwn_rxeof(sc, data, buf, len)); + case RTWN_RX_TX_REPORT: + if (sc->sc_ratectl != RTWN_RATECTL_NET80211) { + /* shouldn't happen */ + device_printf(sc->sc_dev, + "%s called while ratectl = %d!\n", + __func__, sc->sc_ratectl); + break; + } + + RTWN_NT_LOCK(sc); + rtwn_handle_tx_report(sc, buf, len); + RTWN_NT_UNLOCK(sc); + +#ifdef IEEE80211_SUPPORT_SUPERG + /* + * NB: this will executed only when 'report' bit is set. + */ + if (sc->sc_tx_n_active > 0 && --sc->sc_tx_n_active <= 1) + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); +#endif + break; + case RTWN_RX_OTHER: + rtwn_handle_c2h_report(sc, buf, len); + break; + default: + /* NOTREACHED */ + KASSERT(0, ("unknown Rx classification code")); + break; + } + + return (NULL); +} + +static struct ieee80211_node * +rtwn_rx_frame(struct rtwn_softc *sc, struct mbuf *m) +{ + struct rtwn_rx_stat_common stat; + + /* Imitate PCIe layout. */ + m_copydata(m, 0, sizeof(stat), (caddr_t)&stat); + m_adj(m, sizeof(stat)); + + return (rtwn_rx_common(sc, m, &stat)); +} + +void +rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct rtwn_usb_softc *uc = usbd_xfer_softc(xfer); + struct rtwn_softc *sc = &uc->uc_sc; + struct ieee80211com *ic = &sc->sc_ic; + struct ieee80211_node *ni; + struct mbuf *m = NULL, *next; + struct rtwn_data *data; + + RTWN_ASSERT_LOCKED(sc); + + switch (USB_GET_STATE(xfer)) { + case USB_ST_TRANSFERRED: + data = STAILQ_FIRST(&uc->uc_rx_active); + if (data == NULL) + goto tr_setup; + STAILQ_REMOVE_HEAD(&uc->uc_rx_active, next); + m = rtwn_report_intr(uc, xfer, data); + STAILQ_INSERT_TAIL(&uc->uc_rx_inactive, data, next); + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + data = STAILQ_FIRST(&uc->uc_rx_inactive); + if (data == NULL) { + KASSERT(m == NULL, ("mbuf isn't NULL")); + goto finish; + } + STAILQ_REMOVE_HEAD(&uc->uc_rx_inactive, next); + STAILQ_INSERT_TAIL(&uc->uc_rx_active, data, next); + usbd_xfer_set_frame_data(xfer, 0, data->buf, + usbd_xfer_max_len(xfer)); + usbd_transfer_submit(xfer); + + /* + * To avoid LOR we should unlock our private mutex here to call + * ieee80211_input() because here is at the end of a USB + * callback and safe to unlock. + */ + while (m != NULL) { + next = m->m_nextpkt; + m->m_nextpkt = NULL; + + ni = rtwn_rx_frame(sc, m); + + RTWN_UNLOCK(sc); + + if (ni != NULL) { + (void)ieee80211_input_mimo(ni, m); + ieee80211_free_node(ni); + } else { + (void)ieee80211_input_mimo_all(ic, m); + } + RTWN_LOCK(sc); + m = next; + } + break; + default: + /* needs it to the inactive queue due to a error. */ + data = STAILQ_FIRST(&uc->uc_rx_active); + if (data != NULL) { + STAILQ_REMOVE_HEAD(&uc->uc_rx_active, next); + STAILQ_INSERT_TAIL(&uc->uc_rx_inactive, data, next); + } + if (error != USB_ERR_CANCELLED) { + /* XXX restart device if frame was fragmented? */ + + usbd_xfer_set_stall(xfer); + counter_u64_add(ic->ic_ierrors, 1); + goto tr_setup; + } + break; + } +finish: + /* Kick-start more transmit in case we stalled */ + rtwn_start(sc); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.h new file mode 100644 index 0000000000..97190293ab --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_rx.h @@ -0,0 +1,24 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_rx.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTWN_USB_RX_H +#define RTWN_USB_RX_H + +void rtwn_bulk_rx_callback(struct usb_xfer *, usb_error_t); + +#endif /* RTWN_USB_RX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.c new file mode 100644 index 0000000000..444e3de7e2 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.c @@ -0,0 +1,285 @@ +/* $OpenBSD: if_urtwn.c,v 1.16 2011/02/10 17:26:40 jakemsr Exp $ */ + +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2014 Kevin Lo + * Copyright (c) 2015-2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +__FBSDID("$FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_tx.c 320640 2017-07-04 07:07:08Z avos $"); + +#include "opt_wlan.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +static struct rtwn_data * _rtwn_usb_getbuf(struct rtwn_usb_softc *); +static struct rtwn_data * rtwn_usb_getbuf(struct rtwn_usb_softc *); +static void rtwn_usb_txeof(struct rtwn_usb_softc *, + struct rtwn_data *, int); + + +static const uint8_t wme2qid[] = + { RTWN_BULK_TX_BE, RTWN_BULK_TX_BK, + RTWN_BULK_TX_VI, RTWN_BULK_TX_VO }; + + +static struct rtwn_data * +_rtwn_usb_getbuf(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + struct rtwn_data *bf; + + bf = STAILQ_FIRST(&uc->uc_tx_inactive); + if (bf != NULL) + STAILQ_REMOVE_HEAD(&uc->uc_tx_inactive, next); + else { + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, + "%s: out of xmit buffers\n", __func__); + } + return (bf); +} + +static struct rtwn_data * +rtwn_usb_getbuf(struct rtwn_usb_softc *uc) +{ + struct rtwn_softc *sc = &uc->uc_sc; + struct rtwn_data *bf; + + RTWN_ASSERT_LOCKED(sc); + + bf = _rtwn_usb_getbuf(uc); + if (bf == NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, "%s: stop queue\n", + __func__); + } + return (bf); +} + +static void +rtwn_usb_txeof(struct rtwn_usb_softc *uc, struct rtwn_data *data, int status) +{ + struct rtwn_softc *sc = &uc->uc_sc; + + RTWN_ASSERT_LOCKED(sc); + + if (data->ni != NULL) /* not a beacon frame */ + ieee80211_tx_complete(data->ni, data->m, status); + + if (sc->sc_ratectl != RTWN_RATECTL_NET80211) + if (sc->sc_tx_n_active > 0) + sc->sc_tx_n_active--; + + data->ni = NULL; + data->m = NULL; + + STAILQ_INSERT_TAIL(&uc->uc_tx_inactive, data, next); + sc->qfullmsk = 0; +#ifndef D4054 + if (STAILQ_EMPTY(&uc->uc_tx_active) && STAILQ_EMPTY(&uc->uc_tx_pending)) + sc->sc_tx_timer = 0; + else + sc->sc_tx_timer = 5; +#endif +} + +void +rtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error) +{ + struct rtwn_usb_softc *uc = usbd_xfer_softc(xfer); + struct rtwn_softc *sc = &uc->uc_sc; + struct rtwn_data *data; + + RTWN_ASSERT_LOCKED(sc); + + switch (USB_GET_STATE(xfer)){ + case USB_ST_TRANSFERRED: + data = STAILQ_FIRST(&uc->uc_tx_active); + if (data == NULL) + goto tr_setup; + STAILQ_REMOVE_HEAD(&uc->uc_tx_active, next); + rtwn_usb_txeof(uc, data, 0); + /* FALLTHROUGH */ + case USB_ST_SETUP: +tr_setup: + data = STAILQ_FIRST(&uc->uc_tx_pending); + if (data == NULL) { + RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT, + "%s: empty pending queue\n", __func__); + sc->sc_tx_n_active = 0; + goto finish; + } + STAILQ_REMOVE_HEAD(&uc->uc_tx_pending, next); + STAILQ_INSERT_TAIL(&uc->uc_tx_active, data, next); + + /* + * Note: if this is a beacon frame, ensure that it will go + * into appropriate queue. + */ + if (data->ni == NULL && RTWN_CHIP_HAS_BCNQ1(sc)) + rtwn_switch_bcnq(sc, data->id); + usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen); + usbd_transfer_submit(xfer); + if (sc->sc_ratectl != RTWN_RATECTL_NET80211) + sc->sc_tx_n_active++; + break; + default: + data = STAILQ_FIRST(&uc->uc_tx_active); + if (data == NULL) + goto tr_setup; + STAILQ_REMOVE_HEAD(&uc->uc_tx_active, next); + rtwn_usb_txeof(uc, data, 1); + if (error != USB_ERR_CANCELLED) { + usbd_xfer_set_stall(xfer); + goto tr_setup; + } + break; + } +finish: +#ifdef IEEE80211_SUPPORT_SUPERG + /* + * If the TX active queue drops below a certain + * threshold, ensure we age fast-frames out so they're + * transmitted. + */ + if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && + sc->sc_tx_n_active <= 1) { + /* XXX ew - net80211 should defer this for us! */ + + /* + * Note: this sc_tx_n_active currently tracks + * the number of pending transmit submissions + * and not the actual depth of the TX frames + * pending to the hardware. That means that + * we're going to end up with some sub-optimal + * aggregation behaviour. + */ + /* + * XXX TODO: just make this a callout timer schedule so we can + * flush the FF staging queue if we're approaching idle. + */ + rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all); + } +#endif + /* Kick-start more transmit */ + rtwn_start(sc); +} + +static void +rtwn_usb_tx_checksum(struct rtwn_tx_desc_common *txd) +{ + txd->txdw7.usb_checksum = 0; + txd->txdw7.usb_checksum = rtwn_usb_calc_tx_checksum(txd); +} + +int +rtwn_usb_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni, + struct mbuf *m, uint8_t *tx_desc, uint8_t type, int id) +{ + struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc); + struct rtwn_tx_desc_common *txd; + struct rtwn_data *data; + struct usb_xfer *xfer; + uint16_t ac; + + RTWN_ASSERT_LOCKED(sc); + + if (m->m_pkthdr.len + sc->txdesc_len > RTWN_USB_TXBUFSZ) + return (EINVAL); + + data = rtwn_usb_getbuf(uc); + if (data == NULL) + return (ENOBUFS); + + ac = M_WME_GETAC(m); + + switch (type) { + case IEEE80211_FC0_TYPE_CTL: + case IEEE80211_FC0_TYPE_MGT: + xfer = uc->uc_xfer[RTWN_BULK_TX_VO]; + break; + default: + xfer = uc->uc_xfer[wme2qid[ac]]; + break; + } + + txd = (struct rtwn_tx_desc_common *)tx_desc; + txd->pktlen = htole16(m->m_pkthdr.len); + txd->offset = sc->txdesc_len; + txd->flags0 |= RTWN_FLAGS0_OWN; + rtwn_usb_tx_checksum(txd); + + /* Dump Tx descriptor. */ + rtwn_dump_tx_desc(sc, tx_desc); + + memcpy(data->buf, tx_desc, sc->txdesc_len); + m_copydata(m, 0, m->m_pkthdr.len, + (caddr_t)(data->buf + sc->txdesc_len)); + + data->buflen = m->m_pkthdr.len + sc->txdesc_len; + data->id = id; + data->ni = ni; + if (data->ni != NULL) { + data->m = m; +#ifndef D4054 + sc->sc_tx_timer = 5; +#endif + } + + STAILQ_INSERT_TAIL(&uc->uc_tx_pending, data, next); + if (STAILQ_EMPTY(&uc->uc_tx_inactive)) + sc->qfullmsk = 1; + + usbd_transfer_start(xfer); + + return (0); +} diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.h new file mode 100644 index 0000000000..89aea83b09 --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_tx.h @@ -0,0 +1,26 @@ +/*- + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_tx.h 307529 2016-10-17 20:38:24Z avos $ + */ + +#ifndef RTWN_USB_TX_H +#define RTWN_USB_TX_H + +void rtwn_bulk_tx_callback(struct usb_xfer *, usb_error_t); +int rtwn_usb_tx_start(struct rtwn_softc *, struct ieee80211_node *, + struct mbuf *, uint8_t *, uint8_t, int); + +#endif /* RTWN_USB_TX_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_var.h b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_var.h new file mode 100644 index 0000000000..fefece079f --- /dev/null +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/dev/rtwn/usb/rtwn_usb_var.h @@ -0,0 +1,88 @@ +/*- + * Copyright (c) 2010 Damien Bergamini + * Copyright (c) 2016 Andriy Voskoboinyk + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * $OpenBSD: if_urtwnreg.h,v 1.3 2010/11/16 18:02:59 damien Exp $ + * $FreeBSD: releng/12.0/sys/dev/rtwn/usb/rtwn_usb_var.h 321735 2017-07-30 23:35:21Z avos $ + */ + +#ifndef RTWN_USBVAR_H +#define RTWN_USBVAR_H + +#include /* for struct rtwn_rx_stat_common */ + +#define RTWN_USB_RXBUFSZ_UNIT (512) +#define RTWN_USB_RXBUFSZ_MIN ( 4) +#define RTWN_USB_RXBUFSZ_DEF (24) +#define RTWN_USB_RXBUFSZ_MAX (64) +#define RTWN_USB_TXBUFSZ (16 * 1024) + +#define RTWN_IFACE_INDEX 0 + +#define RTWN_USB_RX_LIST_COUNT 1 +#define RTWN_USB_TX_LIST_COUNT 16 + +struct rtwn_data { + uint8_t *buf; + /* 'id' is meaningful for beacons only */ + int id; + uint16_t buflen; + struct mbuf *m; + struct ieee80211_node *ni; + STAILQ_ENTRY(rtwn_data) next; +}; +typedef STAILQ_HEAD(, rtwn_data) rtwn_datahead; + +enum { + RTWN_BULK_RX, + RTWN_BULK_TX_BE, /* = WME_AC_BE */ + RTWN_BULK_TX_BK, /* = WME_AC_BK */ + RTWN_BULK_TX_VI, /* = WME_AC_VI */ + RTWN_BULK_TX_VO, /* = WME_AC_VO */ + RTWN_N_TRANSFER = 5, +}; + +#define RTWN_EP_QUEUES RTWN_BULK_RX + +struct rtwn_usb_softc { + struct rtwn_softc uc_sc; /* must be the first */ + struct usb_device *uc_udev; + struct usb_xfer *uc_xfer[RTWN_N_TRANSFER]; + + struct rtwn_data uc_rx[RTWN_USB_RX_LIST_COUNT]; + rtwn_datahead uc_rx_active; + rtwn_datahead uc_rx_inactive; + int uc_rx_buf_size; + + struct rtwn_rx_stat_common uc_rx_stat; + int uc_rx_stat_len; + int uc_rx_off; + + struct rtwn_data uc_tx[RTWN_USB_TX_LIST_COUNT]; + rtwn_datahead uc_tx_active; + rtwn_datahead uc_tx_inactive; + rtwn_datahead uc_tx_pending; + + int (*uc_align_rx)(int, int); + + int ntx; + int tx_agg_desc_num; +}; +#define RTWN_USB_SOFTC(sc) ((struct rtwn_usb_softc *)(sc)) + +#define rtwn_usb_align_rx(_uc, _totlen, _len) \ + (((_uc)->uc_align_rx)((_totlen), (_len))) + +#endif /* RTWN_USBVAR_H */ diff --git a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/glue.c b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/glue.c index 0836b6538e..9998e53f1b 100644 --- a/src/add-ons/kernel/drivers/network/wlan/realtekwifi/glue.c +++ b/src/add-ons/kernel/drivers/network/wlan/realtekwifi/glue.c @@ -17,10 +17,11 @@ #include #include -#include +#include +#include -HAIKU_FBSD_WLAN_DRIVER_GLUE(realtekwifi, rtwn, pci) +HAIKU_FBSD_WLAN_DRIVER_GLUE(realtekwifi, rtwn_pci, pci) HAIKU_DRIVER_REQUIREMENTS(FBSD_WLAN); HAIKU_FIRMWARE_VERSION(0); HAIKU_FIRMWARE_NAME_MAP(2) = { @@ -31,24 +32,19 @@ HAIKU_FIRMWARE_NAME_MAP(2) = { NO_HAIKU_FBSD_MII_DRIVER(); NO_HAIKU_REENABLE_INTERRUPTS(); -void rtwn_write_4(struct rtwn_softc *, uint16_t, uint32_t); -uint32_t rtwn_read_4(struct rtwn_softc *, uint16_t); int HAIKU_CHECK_DISABLE_INTERRUPTS(device_t dev) { - struct rtwn_softc* sc = (struct rtwn_softc*)device_get_softc(dev); - uint32_t status; + struct rtwn_pci_softc* pc = (struct rtwn_pci_softc*)device_get_softc(dev); + int32_t status, tx_rings; - status = rtwn_read_4(sc, R92C_HISR); - if (status == 0 || status == 0xffffffff) { + status = rtwn_classify_intr(&pc->pc_sc, &tx_rings, 0); + if (status == 0 && tx_rings == 0) return 0; - } - atomic_set((int32*)&sc->sc_intr_status, status); - - /* Disable interrupts. */ - rtwn_write_4(sc, R92C_HIMR, 0x00000000); + atomic_set(&pc->pc_intr_status, status); + atomic_set(&pc->pc_intr_tx_rings, tx_rings); return 1; }