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