xref: /netbsd-src/sys/dev/pci/igc/igc_api.c (revision fb38d839b48b9b6204dbbee1672454d6e719ba01)
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