xref: /openbsd/sys/dev/pci/igc_api.c (revision 83306792)
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