1 1.2 rin /* $NetBSD: igc_api.c,v 1.2 2023/10/04 07:35:27 rin Exp $ */ 2 1.1 rin /* $OpenBSD: igc_api.c,v 1.1 2021/10/31 14:52:57 patrick Exp $ */ 3 1.1 rin /*- 4 1.1 rin * Copyright 2021 Intel Corp 5 1.1 rin * Copyright 2021 Rubicon Communications, LLC (Netgate) 6 1.1 rin * SPDX-License-Identifier: BSD-3-Clause 7 1.1 rin */ 8 1.1 rin 9 1.2 rin #include <sys/cdefs.h> 10 1.2 rin __KERNEL_RCSID(0, "$NetBSD: igc_api.c,v 1.2 2023/10/04 07:35:27 rin Exp $"); 11 1.2 rin 12 1.2 rin #include <dev/pci/igc/igc_api.h> 13 1.2 rin #include <dev/pci/igc/igc_hw.h> 14 1.1 rin 15 1.1 rin /** 16 1.1 rin * igc_init_mac_params - Initialize MAC function pointers 17 1.1 rin * @hw: pointer to the HW structure 18 1.1 rin * 19 1.1 rin * This function initializes the function pointers for the MAC 20 1.1 rin * set of functions. Called by drivers or by igc_setup_init_funcs. 21 1.1 rin **/ 22 1.1 rin int 23 1.1 rin igc_init_mac_params(struct igc_hw *hw) 24 1.1 rin { 25 1.1 rin int ret_val = IGC_SUCCESS; 26 1.1 rin 27 1.1 rin if (hw->mac.ops.init_params) { 28 1.1 rin ret_val = hw->mac.ops.init_params(hw); 29 1.1 rin if (ret_val) { 30 1.1 rin DEBUGOUT("MAC Initialization Error\n"); 31 1.1 rin goto out; 32 1.1 rin } 33 1.1 rin } else { 34 1.1 rin DEBUGOUT("mac.init_mac_params was NULL\n"); 35 1.1 rin ret_val = -IGC_ERR_CONFIG; 36 1.1 rin } 37 1.1 rin out: 38 1.1 rin return ret_val; 39 1.1 rin } 40 1.1 rin 41 1.1 rin /** 42 1.1 rin * igc_init_nvm_params - Initialize NVM function pointers 43 1.1 rin * @hw: pointer to the HW structure 44 1.1 rin * 45 1.1 rin * This function initializes the function pointers for the NVM 46 1.1 rin * set of functions. Called by drivers or by igc_setup_init_funcs. 47 1.1 rin **/ 48 1.1 rin int 49 1.1 rin igc_init_nvm_params(struct igc_hw *hw) 50 1.1 rin { 51 1.1 rin int ret_val = IGC_SUCCESS; 52 1.1 rin 53 1.1 rin if (hw->nvm.ops.init_params) { 54 1.1 rin ret_val = hw->nvm.ops.init_params(hw); 55 1.1 rin if (ret_val) { 56 1.1 rin DEBUGOUT("NVM Initialization Error\n"); 57 1.1 rin goto out; 58 1.1 rin } 59 1.1 rin } else { 60 1.1 rin DEBUGOUT("nvm.init_nvm_params was NULL\n"); 61 1.1 rin ret_val = -IGC_ERR_CONFIG; 62 1.1 rin } 63 1.1 rin out: 64 1.1 rin return ret_val; 65 1.1 rin } 66 1.1 rin 67 1.1 rin /** 68 1.1 rin * igc_init_phy_params - Initialize PHY function pointers 69 1.1 rin * @hw: pointer to the HW structure 70 1.1 rin * 71 1.1 rin * This function initializes the function pointers for the PHY 72 1.1 rin * set of functions. Called by drivers or by igc_setup_init_funcs. 73 1.1 rin **/ 74 1.1 rin int 75 1.1 rin igc_init_phy_params(struct igc_hw *hw) 76 1.1 rin { 77 1.1 rin int ret_val = IGC_SUCCESS; 78 1.1 rin 79 1.1 rin if (hw->phy.ops.init_params) { 80 1.1 rin ret_val = hw->phy.ops.init_params(hw); 81 1.1 rin if (ret_val) { 82 1.1 rin DEBUGOUT("PHY Initialization Error\n"); 83 1.1 rin goto out; 84 1.1 rin } 85 1.1 rin } else { 86 1.1 rin DEBUGOUT("phy.init_phy_params was NULL\n"); 87 1.1 rin ret_val = -IGC_ERR_CONFIG; 88 1.1 rin } 89 1.1 rin out: 90 1.1 rin return ret_val; 91 1.1 rin } 92 1.1 rin 93 1.1 rin /** 94 1.1 rin * igc_set_mac_type - Sets MAC type 95 1.1 rin * @hw: pointer to the HW structure 96 1.1 rin * 97 1.1 rin * This function sets the mac type of the adapter based on the 98 1.1 rin * device ID stored in the hw structure. 99 1.1 rin * MUST BE FIRST FUNCTION CALLED (explicitly or through 100 1.1 rin * igc_setup_init_funcs()). 101 1.1 rin **/ 102 1.1 rin int 103 1.1 rin igc_set_mac_type(struct igc_hw *hw) 104 1.1 rin { 105 1.1 rin struct igc_mac_info *mac = &hw->mac; 106 1.1 rin int ret_val = IGC_SUCCESS; 107 1.1 rin 108 1.1 rin DEBUGFUNC("igc_set_mac_type"); 109 1.1 rin 110 1.1 rin switch (hw->device_id) { 111 1.1 rin case PCI_PRODUCT_INTEL_I220_V: 112 1.1 rin case PCI_PRODUCT_INTEL_I221_V: 113 1.1 rin case PCI_PRODUCT_INTEL_I225_BLANK_NVM: 114 1.1 rin case PCI_PRODUCT_INTEL_I225_I: 115 1.1 rin case PCI_PRODUCT_INTEL_I225_IT: 116 1.1 rin case PCI_PRODUCT_INTEL_I225_K: 117 1.1 rin case PCI_PRODUCT_INTEL_I225_K2: 118 1.1 rin case PCI_PRODUCT_INTEL_I225_LM: 119 1.1 rin case PCI_PRODUCT_INTEL_I225_LMVP: 120 1.1 rin case PCI_PRODUCT_INTEL_I225_V: 121 1.1 rin case PCI_PRODUCT_INTEL_I226_BLANK_NVM: 122 1.1 rin case PCI_PRODUCT_INTEL_I226_IT: 123 1.1 rin case PCI_PRODUCT_INTEL_I226_LM: 124 1.2 rin case PCI_PRODUCT_INTEL_I226_LMVP: 125 1.1 rin case PCI_PRODUCT_INTEL_I226_K: 126 1.1 rin case PCI_PRODUCT_INTEL_I226_V: 127 1.1 rin mac->type = igc_i225; 128 1.1 rin break; 129 1.1 rin default: 130 1.1 rin /* Should never have loaded on this device */ 131 1.1 rin ret_val = -IGC_ERR_MAC_INIT; 132 1.1 rin break; 133 1.1 rin } 134 1.1 rin 135 1.1 rin return ret_val; 136 1.1 rin } 137 1.1 rin 138 1.1 rin /** 139 1.1 rin * igc_setup_init_funcs - Initializes function pointers 140 1.1 rin * @hw: pointer to the HW structure 141 1.1 rin * @init_device: true will initialize the rest of the function pointers 142 1.1 rin * getting the device ready for use. FALSE will only set 143 1.1 rin * MAC type and the function pointers for the other init 144 1.1 rin * functions. Passing FALSE will not generate any hardware 145 1.1 rin * reads or writes. 146 1.1 rin * 147 1.1 rin * This function must be called by a driver in order to use the rest 148 1.1 rin * of the 'shared' code files. Called by drivers only. 149 1.1 rin **/ 150 1.1 rin int 151 1.1 rin igc_setup_init_funcs(struct igc_hw *hw, bool init_device) 152 1.1 rin { 153 1.1 rin int ret_val; 154 1.1 rin 155 1.1 rin /* Can't do much good without knowing the MAC type. */ 156 1.1 rin ret_val = igc_set_mac_type(hw); 157 1.1 rin if (ret_val) { 158 1.1 rin DEBUGOUT("ERROR: MAC type could not be set properly.\n"); 159 1.1 rin goto out; 160 1.1 rin } 161 1.1 rin 162 1.1 rin if (!hw->hw_addr) { 163 1.1 rin DEBUGOUT("ERROR: Registers not mapped\n"); 164 1.1 rin ret_val = -IGC_ERR_CONFIG; 165 1.1 rin goto out; 166 1.1 rin } 167 1.1 rin 168 1.1 rin /* 169 1.1 rin * Init function pointers to generic implementations. We do this first 170 1.1 rin * allowing a driver module to override it afterward. 171 1.1 rin */ 172 1.1 rin igc_init_mac_ops_generic(hw); 173 1.1 rin igc_init_phy_ops_generic(hw); 174 1.1 rin igc_init_nvm_ops_generic(hw); 175 1.1 rin 176 1.1 rin /* 177 1.1 rin * Set up the init function pointers. These are functions within the 178 1.1 rin * adapter family file that sets up function pointers for the rest of 179 1.1 rin * the functions in that family. 180 1.1 rin */ 181 1.1 rin switch (hw->mac.type) { 182 1.1 rin case igc_i225: 183 1.1 rin igc_init_function_pointers_i225(hw); 184 1.1 rin break; 185 1.1 rin default: 186 1.1 rin DEBUGOUT("Hardware not supported\n"); 187 1.1 rin ret_val = -IGC_ERR_CONFIG; 188 1.1 rin break; 189 1.1 rin } 190 1.1 rin 191 1.1 rin /* 192 1.1 rin * Initialize the rest of the function pointers. These require some 193 1.1 rin * register reads/writes in some cases. 194 1.1 rin */ 195 1.1 rin if (!(ret_val) && init_device) { 196 1.1 rin ret_val = igc_init_mac_params(hw); 197 1.1 rin if (ret_val) 198 1.1 rin goto out; 199 1.1 rin 200 1.1 rin ret_val = igc_init_nvm_params(hw); 201 1.1 rin if (ret_val) 202 1.1 rin goto out; 203 1.1 rin 204 1.1 rin ret_val = igc_init_phy_params(hw); 205 1.1 rin if (ret_val) 206 1.1 rin goto out; 207 1.1 rin } 208 1.1 rin out: 209 1.1 rin return ret_val; 210 1.1 rin } 211 1.1 rin 212 1.1 rin /** 213 1.1 rin * igc_update_mc_addr_list - Update Multicast addresses 214 1.1 rin * @hw: pointer to the HW structure 215 1.1 rin * @mc_addr_list: array of multicast addresses to program 216 1.1 rin * @mc_addr_count: number of multicast addresses to program 217 1.1 rin * 218 1.1 rin * Updates the Multicast Table Array. 219 1.1 rin * The caller must have a packed mc_addr_list of multicast addresses. 220 1.1 rin **/ 221 1.1 rin void 222 1.1 rin igc_update_mc_addr_list(struct igc_hw *hw, uint8_t *mc_addr_list, 223 1.1 rin uint32_t mc_addr_count) 224 1.1 rin { 225 1.1 rin if (hw->mac.ops.update_mc_addr_list) 226 1.1 rin hw->mac.ops.update_mc_addr_list(hw, mc_addr_list, 227 1.1 rin mc_addr_count); 228 1.1 rin } 229 1.1 rin 230 1.1 rin /** 231 1.1 rin * igc_check_for_link - Check/Store link connection 232 1.1 rin * @hw: pointer to the HW structure 233 1.1 rin * 234 1.1 rin * This checks the link condition of the adapter and stores the 235 1.1 rin * results in the hw->mac structure. This is a function pointer entry 236 1.1 rin * point called by drivers. 237 1.1 rin **/ 238 1.1 rin int 239 1.1 rin igc_check_for_link(struct igc_hw *hw) 240 1.1 rin { 241 1.1 rin if (hw->mac.ops.check_for_link) 242 1.1 rin return hw->mac.ops.check_for_link(hw); 243 1.1 rin 244 1.1 rin return -IGC_ERR_CONFIG; 245 1.1 rin } 246 1.1 rin 247 1.1 rin /** 248 1.1 rin * igc_reset_hw - Reset hardware 249 1.1 rin * @hw: pointer to the HW structure 250 1.1 rin * 251 1.1 rin * This resets the hardware into a known state. This is a function pointer 252 1.1 rin * entry point called by drivers. 253 1.1 rin **/ 254 1.1 rin int 255 1.1 rin igc_reset_hw(struct igc_hw *hw) 256 1.1 rin { 257 1.1 rin if (hw->mac.ops.reset_hw) 258 1.1 rin return hw->mac.ops.reset_hw(hw); 259 1.1 rin 260 1.1 rin return -IGC_ERR_CONFIG; 261 1.1 rin } 262 1.1 rin 263 1.1 rin /** 264 1.1 rin * igc_init_hw - Initialize hardware 265 1.1 rin * @hw: pointer to the HW structure 266 1.1 rin * 267 1.1 rin * This inits the hardware readying it for operation. This is a function 268 1.1 rin * pointer entry point called by drivers. 269 1.1 rin **/ 270 1.1 rin int 271 1.1 rin igc_init_hw(struct igc_hw *hw) 272 1.1 rin { 273 1.1 rin if (hw->mac.ops.init_hw) 274 1.1 rin return hw->mac.ops.init_hw(hw); 275 1.1 rin 276 1.1 rin return -IGC_ERR_CONFIG; 277 1.1 rin } 278 1.1 rin 279 1.1 rin /** 280 1.1 rin * igc_get_speed_and_duplex - Returns current speed and duplex 281 1.1 rin * @hw: pointer to the HW structure 282 1.1 rin * @speed: pointer to a 16-bit value to store the speed 283 1.1 rin * @duplex: pointer to a 16-bit value to store the duplex. 284 1.1 rin * 285 1.1 rin * This returns the speed and duplex of the adapter in the two 'out' 286 1.1 rin * variables passed in. This is a function pointer entry point called 287 1.1 rin * by drivers. 288 1.1 rin **/ 289 1.1 rin int 290 1.1 rin igc_get_speed_and_duplex(struct igc_hw *hw, uint16_t *speed, uint16_t *duplex) 291 1.1 rin { 292 1.1 rin if (hw->mac.ops.get_link_up_info) 293 1.1 rin return hw->mac.ops.get_link_up_info(hw, speed, duplex); 294 1.1 rin 295 1.1 rin return -IGC_ERR_CONFIG; 296 1.1 rin } 297 1.1 rin 298 1.1 rin /** 299 1.1 rin * igc_rar_set - Sets a receive address register 300 1.1 rin * @hw: pointer to the HW structure 301 1.1 rin * @addr: address to set the RAR to 302 1.1 rin * @index: the RAR to set 303 1.1 rin * 304 1.1 rin * Sets a Receive Address Register (RAR) to the specified address. 305 1.1 rin **/ 306 1.1 rin int 307 1.1 rin igc_rar_set(struct igc_hw *hw, uint8_t *addr, uint32_t index) 308 1.1 rin { 309 1.1 rin if (hw->mac.ops.rar_set) 310 1.1 rin return hw->mac.ops.rar_set(hw, addr, index); 311 1.1 rin 312 1.1 rin return IGC_SUCCESS; 313 1.1 rin } 314 1.1 rin 315 1.1 rin /** 316 1.1 rin * igc_check_reset_block - Verifies PHY can be reset 317 1.1 rin * @hw: pointer to the HW structure 318 1.1 rin * 319 1.1 rin * Checks if the PHY is in a state that can be reset or if manageability 320 1.1 rin * has it tied up. This is a function pointer entry point called by drivers. 321 1.1 rin **/ 322 1.1 rin int 323 1.1 rin igc_check_reset_block(struct igc_hw *hw) 324 1.1 rin { 325 1.1 rin if (hw->phy.ops.check_reset_block) 326 1.1 rin return hw->phy.ops.check_reset_block(hw); 327 1.1 rin 328 1.1 rin return IGC_SUCCESS; 329 1.1 rin } 330 1.1 rin 331 1.1 rin /** 332 1.1 rin * igc_get_phy_info - Retrieves PHY information from registers 333 1.1 rin * @hw: pointer to the HW structure 334 1.1 rin * 335 1.1 rin * This function gets some information from various PHY registers and 336 1.1 rin * populates hw->phy values with it. This is a function pointer entry 337 1.1 rin * point called by drivers. 338 1.1 rin **/ 339 1.1 rin int 340 1.1 rin igc_get_phy_info(struct igc_hw *hw) 341 1.1 rin { 342 1.1 rin if (hw->phy.ops.get_info) 343 1.1 rin return hw->phy.ops.get_info(hw); 344 1.1 rin 345 1.1 rin return IGC_SUCCESS; 346 1.1 rin } 347 1.1 rin 348 1.1 rin /** 349 1.1 rin * igc_phy_hw_reset - Hard PHY reset 350 1.1 rin * @hw: pointer to the HW structure 351 1.1 rin * 352 1.1 rin * Performs a hard PHY reset. This is a function pointer entry point called 353 1.1 rin * by drivers. 354 1.1 rin **/ 355 1.1 rin int 356 1.1 rin igc_phy_hw_reset(struct igc_hw *hw) 357 1.1 rin { 358 1.1 rin if (hw->phy.ops.reset) 359 1.1 rin return hw->phy.ops.reset(hw); 360 1.1 rin 361 1.1 rin return IGC_SUCCESS; 362 1.1 rin } 363 1.1 rin 364 1.1 rin /** 365 1.1 rin * igc_read_mac_addr - Reads MAC address 366 1.1 rin * @hw: pointer to the HW structure 367 1.1 rin * 368 1.1 rin * Reads the MAC address out of the adapter and stores it in the HW structure. 369 1.1 rin * Currently no func pointer exists and all implementations are handled in the 370 1.1 rin * generic version of this function. 371 1.1 rin **/ 372 1.1 rin int 373 1.1 rin igc_read_mac_addr(struct igc_hw *hw) 374 1.1 rin { 375 1.1 rin if (hw->mac.ops.read_mac_addr) 376 1.1 rin return hw->mac.ops.read_mac_addr(hw); 377 1.1 rin 378 1.1 rin return igc_read_mac_addr_generic(hw); 379 1.1 rin } 380 1.1 rin 381 1.1 rin /** 382 1.1 rin * igc_validate_nvm_checksum - Verifies NVM (EEPROM) checksum 383 1.1 rin * @hw: pointer to the HW structure 384 1.1 rin * 385 1.1 rin * Validates the NVM checksum is correct. This is a function pointer entry 386 1.1 rin * point called by drivers. 387 1.1 rin **/ 388 1.1 rin int 389 1.1 rin igc_validate_nvm_checksum(struct igc_hw *hw) 390 1.1 rin { 391 1.1 rin if (hw->nvm.ops.validate) 392 1.1 rin return hw->nvm.ops.validate(hw); 393 1.1 rin 394 1.1 rin return -IGC_ERR_CONFIG; 395 1.1 rin } 396