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