1 /*- 2 * Copyright (c) 2016 Adrian Chadd <adrian@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification. 11 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13 * redistribution must be conditioned upon including a substantially 14 * similar Disclaimer requirement for further binary redistribution. 15 * 16 * NO WARRANTY 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27 * THE POSSIBILITY OF SUCH DAMAGES. 28 */ 29 30 #include <sys/cdefs.h> 31 /* 32 * This is the top-level N-PHY support for the Broadcom softmac driver. 33 */ 34 35 #include "opt_bwn.h" 36 #include "opt_wlan.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/kernel.h> 41 #include <sys/malloc.h> 42 #include <sys/module.h> 43 #include <sys/endian.h> 44 #include <sys/errno.h> 45 #include <sys/firmware.h> 46 #include <sys/lock.h> 47 #include <sys/mutex.h> 48 #include <machine/bus.h> 49 #include <machine/resource.h> 50 #include <sys/bus.h> 51 #include <sys/rman.h> 52 #include <sys/socket.h> 53 #include <sys/sockio.h> 54 55 #include <net/ethernet.h> 56 #include <net/if.h> 57 #include <net/if_var.h> 58 #include <net/if_arp.h> 59 #include <net/if_dl.h> 60 #include <net/if_llc.h> 61 #include <net/if_media.h> 62 #include <net/if_types.h> 63 64 #include <dev/pci/pcivar.h> 65 #include <dev/pci/pcireg.h> 66 67 #include <net80211/ieee80211_var.h> 68 #include <net80211/ieee80211_radiotap.h> 69 #include <net80211/ieee80211_regdomain.h> 70 #include <net80211/ieee80211_phy.h> 71 #include <net80211/ieee80211_ratectl.h> 72 73 #include <dev/bwn/if_bwnreg.h> 74 #include <dev/bwn/if_bwnvar.h> 75 76 #include <dev/bwn/if_bwn_debug.h> 77 #include <dev/bwn/if_bwn_misc.h> 78 #include <dev/bwn/if_bwn_phy_n.h> 79 80 #ifdef BWN_GPL_PHY 81 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_tables.h> 82 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_ppr.h> 83 #include <gnu/dev/bwn/phy_n/if_bwn_phy_n_core.h> 84 #endif 85 86 /* 87 * This module is always compiled into the kernel, regardless of 88 * whether the GPL PHY is enabled. If the GPL PHY isn't enabled 89 * then it'll just be stubs that will fail to attach. 90 */ 91 92 int 93 bwn_phy_n_attach(struct bwn_mac *mac) 94 { 95 96 #ifdef BWN_GPL_PHY 97 return bwn_nphy_op_allocate(mac); 98 #else 99 device_printf(mac->mac_sc->sc_dev, 100 "%s: BWN_GPL_PHY not in kernel config; " 101 "no PHY-N support\n", __func__); 102 return (ENXIO); 103 #endif 104 } 105 106 void 107 bwn_phy_n_detach(struct bwn_mac *mac) 108 { 109 110 #ifdef BWN_GPL_PHY 111 return bwn_nphy_op_free(mac); 112 #endif 113 } 114 115 int 116 bwn_phy_n_prepare_hw(struct bwn_mac *mac) 117 { 118 119 #ifdef BWN_GPL_PHY 120 return (bwn_nphy_op_prepare_structs(mac)); 121 #else 122 return (ENXIO); 123 #endif 124 } 125 126 void 127 bwn_phy_n_init_pre(struct bwn_mac *mac) 128 { 129 130 /* XXX TODO */ 131 } 132 133 int 134 bwn_phy_n_init(struct bwn_mac *mac) 135 { 136 #ifdef BWN_GPL_PHY 137 return bwn_nphy_op_init(mac); 138 #else 139 return (ENXIO); 140 #endif 141 } 142 143 void 144 bwn_phy_n_exit(struct bwn_mac *mac) 145 { 146 147 /* XXX TODO */ 148 } 149 150 uint16_t 151 bwn_phy_n_read(struct bwn_mac *mac, uint16_t reg) 152 { 153 154 BWN_WRITE_2(mac, BWN_PHYCTL, reg); 155 return BWN_READ_2(mac, BWN_PHYDATA); 156 } 157 158 void 159 bwn_phy_n_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 160 { 161 162 BWN_WRITE_2(mac, BWN_PHYCTL, reg); 163 BWN_WRITE_2(mac, BWN_PHYDATA, value); 164 } 165 166 uint16_t 167 bwn_phy_n_rf_read(struct bwn_mac *mac, uint16_t reg) 168 { 169 170 /* Register 1 is a 32-bit register. */ 171 if (mac->mac_phy.rev < 7 && reg == 1) { 172 BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 173 } 174 175 if (mac->mac_phy.rev >= 7) 176 reg |= 0x200; /* radio 0x2057 */ 177 else 178 reg |= 0x100; 179 180 BWN_WRITE_2(mac, BWN_RFCTL, reg); 181 return BWN_READ_2(mac, BWN_RFDATALO); 182 } 183 184 void 185 bwn_phy_n_rf_write(struct bwn_mac *mac, uint16_t reg, uint16_t value) 186 { 187 188 /* Register 1 is a 32-bit register. */ 189 if (mac->mac_phy.rev < 7 && reg == 1) { 190 BWN_ERRPRINTF(mac->mac_sc, "%s: bad reg access\n", __func__); 191 } 192 193 BWN_WRITE_2(mac, BWN_RFCTL, reg); 194 BWN_WRITE_2(mac, BWN_RFDATALO, value); 195 } 196 197 int 198 bwn_phy_n_hwpctl(struct bwn_mac *mac) 199 { 200 201 return (0); 202 } 203 204 void 205 bwn_phy_n_rf_onoff(struct bwn_mac *mac, int on) 206 { 207 #ifdef BWN_GPL_PHY 208 bwn_nphy_op_software_rfkill(mac, on); 209 #endif 210 } 211 212 void 213 bwn_phy_n_switch_analog(struct bwn_mac *mac, int on) 214 { 215 #ifdef BWN_GPL_PHY 216 bwn_nphy_op_switch_analog(mac, on); 217 #endif 218 } 219 220 int 221 bwn_phy_n_switch_channel(struct bwn_mac *mac, uint32_t newchan) 222 { 223 #ifdef BWN_GPL_PHY 224 return bwn_nphy_op_switch_channel(mac, newchan); 225 #else 226 return (ENXIO); 227 #endif 228 } 229 230 uint32_t 231 bwn_phy_n_get_default_chan(struct bwn_mac *mac) 232 { 233 234 if (bwn_current_band(mac) == BWN_BAND_2G) 235 return (1); 236 return (36); 237 } 238 239 void 240 bwn_phy_n_set_antenna(struct bwn_mac *mac, int antenna) 241 { 242 /* XXX TODO */ 243 } 244 245 int 246 bwn_phy_n_im(struct bwn_mac *mac, int mode) 247 { 248 /* XXX TODO */ 249 return (0); 250 } 251 252 bwn_txpwr_result_t 253 bwn_phy_n_recalc_txpwr(struct bwn_mac *mac, int ignore_tssi) 254 { 255 #ifdef BWN_GPL_PHY 256 return bwn_nphy_op_recalc_txpower(mac, ignore_tssi); 257 #else 258 return (BWN_TXPWR_RES_DONE); 259 #endif 260 } 261 262 void 263 bwn_phy_n_set_txpwr(struct bwn_mac *mac) 264 { 265 266 } 267 268 void 269 bwn_phy_n_task_15s(struct bwn_mac *mac) 270 { 271 272 } 273 274 void 275 bwn_phy_n_task_60s(struct bwn_mac *mac) 276 { 277 278 } 279