xref: /onnv-gate/usr/src/uts/common/io/igb/igb_osdep.c (revision 8955:5280fc6da91b)
15779Sxy150489 /*
25779Sxy150489  * CDDL HEADER START
35779Sxy150489  *
48571SChenlu.Chen@Sun.COM  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
55779Sxy150489  * The contents of this file are subject to the terms of the
65779Sxy150489  * Common Development and Distribution License (the "License").
75779Sxy150489  * You may not use this file except in compliance with the License.
85779Sxy150489  *
98571SChenlu.Chen@Sun.COM  * You can obtain a copy of the license at:
108571SChenlu.Chen@Sun.COM  *	http://www.opensolaris.org/os/licensing.
115779Sxy150489  * See the License for the specific language governing permissions
125779Sxy150489  * and limitations under the License.
135779Sxy150489  *
148571SChenlu.Chen@Sun.COM  * When using or redistributing this file, you may do so under the
158571SChenlu.Chen@Sun.COM  * License only. No other modification of this header is permitted.
168571SChenlu.Chen@Sun.COM  *
175779Sxy150489  * If applicable, add the following below this CDDL HEADER, with the
185779Sxy150489  * fields enclosed by brackets "[]" replaced with your own identifying
195779Sxy150489  * information: Portions Copyright [yyyy] [name of copyright owner]
205779Sxy150489  *
215779Sxy150489  * CDDL HEADER END
225779Sxy150489  */
235779Sxy150489 
245779Sxy150489 /*
258571SChenlu.Chen@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
268571SChenlu.Chen@Sun.COM  * Use is subject to license terms of the CDDL.
278275SEric Cheng  */
285779Sxy150489 
295779Sxy150489 #include "igb_osdep.h"
305779Sxy150489 #include "igb_api.h"
315779Sxy150489 
325779Sxy150489 
335779Sxy150489 void
345779Sxy150489 e1000_pci_set_mwi(struct e1000_hw *hw)
355779Sxy150489 {
365779Sxy150489 	uint16_t val = hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE;
375779Sxy150489 
385779Sxy150489 	e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &val);
395779Sxy150489 }
405779Sxy150489 
415779Sxy150489 void
425779Sxy150489 e1000_pci_clear_mwi(struct e1000_hw *hw)
435779Sxy150489 {
445779Sxy150489 	uint16_t val = hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
455779Sxy150489 
465779Sxy150489 	e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &val);
475779Sxy150489 }
485779Sxy150489 
495779Sxy150489 void
505779Sxy150489 e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
515779Sxy150489 {
525779Sxy150489 	pci_config_put16(OS_DEP(hw)->cfg_handle, reg, *value);
535779Sxy150489 }
545779Sxy150489 
555779Sxy150489 void
565779Sxy150489 e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
575779Sxy150489 {
585779Sxy150489 	*value =
595779Sxy150489 	    pci_config_get16(OS_DEP(hw)->cfg_handle, reg);
605779Sxy150489 }
615779Sxy150489 
625779Sxy150489 /*
63*8955SChenlu.Chen@Sun.COM  * Return the 16-bit value from pci-e config space at offset reg into the pci-e
64*8955SChenlu.Chen@Sun.COM  * capability block.
655779Sxy150489  */
665779Sxy150489 int32_t
675779Sxy150489 e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
685779Sxy150489 {
69*8955SChenlu.Chen@Sun.COM 	uint32_t pcie_cap = PCI_EX_CONF_CAP;	/* default */
70*8955SChenlu.Chen@Sun.COM 
71*8955SChenlu.Chen@Sun.COM 	switch (hw->mac.type) {
72*8955SChenlu.Chen@Sun.COM 	case e1000_82575:
73*8955SChenlu.Chen@Sun.COM 		pcie_cap = 0xa0;
74*8955SChenlu.Chen@Sun.COM 		break;
75*8955SChenlu.Chen@Sun.COM 	case e1000_82576:
76*8955SChenlu.Chen@Sun.COM 		pcie_cap = 0xa0;
77*8955SChenlu.Chen@Sun.COM 		break;
78*8955SChenlu.Chen@Sun.COM 	}
79*8955SChenlu.Chen@Sun.COM 
80*8955SChenlu.Chen@Sun.COM 	*value = pci_config_get16(OS_DEP(hw)->cfg_handle, (pcie_cap + reg));
815779Sxy150489 
825779Sxy150489 	return (0);
835779Sxy150489 }
845779Sxy150489 
855779Sxy150489 /*
868275SEric Cheng  * e1000_rar_set_vmdq - Clear the RAR registers
878275SEric Cheng  */
888275SEric Cheng void
898275SEric Cheng e1000_rar_clear(struct e1000_hw *hw, uint32_t index)
908275SEric Cheng {
918275SEric Cheng 
928275SEric Cheng 	uint32_t rar_high;
938275SEric Cheng 
948275SEric Cheng 	/* Make the hardware the Address invalid by setting the clear bit */
958275SEric Cheng 	rar_high = ~E1000_RAH_AV;
968275SEric Cheng 
978275SEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
988275SEric Cheng 	E1000_WRITE_FLUSH(hw);
998275SEric Cheng }
1008275SEric Cheng 
1018275SEric Cheng /*
1028275SEric Cheng  * e1000_rar_set_vmdq - Set the RAR registers for VMDq
1038275SEric Cheng  */
1048275SEric Cheng void
1058275SEric Cheng e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *addr, uint32_t index,
1068275SEric Cheng 	uint32_t vmdq_mode, uint8_t qsel)
1078275SEric Cheng {
1088275SEric Cheng 	uint32_t rar_low, rar_high;
1098275SEric Cheng 
1108275SEric Cheng 	/*
1118275SEric Cheng 	 * NIC expects these in little endian so reverse the byte order
1128275SEric Cheng 	 * from network order (big endian) to little endian.
1138275SEric Cheng 	 */
1148275SEric Cheng 
1158275SEric Cheng 	rar_low = ((uint32_t)addr[0] | ((uint32_t)addr[1] << 8) |
1168275SEric Cheng 	    ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24));
1178275SEric Cheng 
1188275SEric Cheng 	rar_high = ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
1198275SEric Cheng 
1208275SEric Cheng 	/* Indicate to hardware the Address is Valid. */
1218275SEric Cheng 	rar_high |= E1000_RAH_AV;
1228275SEric Cheng 
1238275SEric Cheng 	/* Set que selector based on vmdq mode */
1248275SEric Cheng 	switch (vmdq_mode) {
1258275SEric Cheng 	default:
1268275SEric Cheng 	case E1000_VMDQ_OFF:
1278275SEric Cheng 		break;
1288275SEric Cheng 	case E1000_VMDQ_MAC:
1298275SEric Cheng 		rar_high |= (qsel << 18);
1308275SEric Cheng 		break;
1318275SEric Cheng 	case E1000_VMDQ_MAC_RSS:
1328275SEric Cheng 		rar_high |= 1 << (18 + qsel);
1338275SEric Cheng 		break;
1348275SEric Cheng 
1358275SEric Cheng 	}
1368275SEric Cheng 
1378275SEric Cheng 	/* write to receive address registers */
1388275SEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
1398275SEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
1408275SEric Cheng 	E1000_WRITE_FLUSH(hw);
1418275SEric Cheng }
142