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 **/
22int
23igc_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	}
37out:
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 **/
48int
49igc_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	}
63out:
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 **/
74int
75igc_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	}
89out:
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 **/
102int
103igc_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 **/
150int
151igc_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	}
208out:
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 **/
221void
222igc_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 **/
238int
239igc_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 **/
254int
255igc_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 **/
270int
271igc_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 **/
289int
290igc_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 **/
306int
307igc_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 **/
322int
323igc_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 **/
339int
340igc_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 **/
355int
356igc_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 **/
372int
373igc_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 **/
388int
389igc_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