xref: /onnv-gate/usr/src/uts/common/io/igb/igb_osdep.c (revision 10319:0355b7a83c0d)
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
e1000_write_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)345779Sxy150489 e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
355779Sxy150489 {
365779Sxy150489 	pci_config_put16(OS_DEP(hw)->cfg_handle, reg, *value);
375779Sxy150489 }
385779Sxy150489 
395779Sxy150489 void
e1000_read_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)405779Sxy150489 e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
415779Sxy150489 {
425779Sxy150489 	*value =
435779Sxy150489 	    pci_config_get16(OS_DEP(hw)->cfg_handle, reg);
445779Sxy150489 }
455779Sxy150489 
465779Sxy150489 /*
478955SChenlu.Chen@Sun.COM  * Return the 16-bit value from pci-e config space at offset reg into the pci-e
48*10319SJason.Xu@Sun.COM  * capability block.  Note that this refers to the pci-e capability block in
49*10319SJason.Xu@Sun.COM  * standard pci config space, not the block in pci-e extended config space.
505779Sxy150489  */
515779Sxy150489 int32_t
e1000_read_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)525779Sxy150489 e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
535779Sxy150489 {
54*10319SJason.Xu@Sun.COM 	uint8_t pcie_id = PCI_CAP_ID_PCI_E;
55*10319SJason.Xu@Sun.COM 	uint16_t pcie_cap;
56*10319SJason.Xu@Sun.COM 	int32_t status;
578955SChenlu.Chen@Sun.COM 
58*10319SJason.Xu@Sun.COM 	/* locate the pci-e capability block */
59*10319SJason.Xu@Sun.COM 	status = pci_lcap_locate((OS_DEP(hw))->cfg_handle, pcie_id, &pcie_cap);
60*10319SJason.Xu@Sun.COM 	if (status == DDI_SUCCESS) {
61*10319SJason.Xu@Sun.COM 
62*10319SJason.Xu@Sun.COM 		/* read at given offset into block */
63*10319SJason.Xu@Sun.COM 		*value = pci_config_get16(OS_DEP(hw)->cfg_handle,
64*10319SJason.Xu@Sun.COM 		    (pcie_cap + reg));
658955SChenlu.Chen@Sun.COM 	}
668955SChenlu.Chen@Sun.COM 
67*10319SJason.Xu@Sun.COM 	return (status);
68*10319SJason.Xu@Sun.COM }
695779Sxy150489 
70*10319SJason.Xu@Sun.COM /*
71*10319SJason.Xu@Sun.COM  * Write the given 16-bit value to pci-e config space at offset reg into the
72*10319SJason.Xu@Sun.COM  * pci-e capability block.  Note that this refers to the pci-e capability block
73*10319SJason.Xu@Sun.COM  * in standard pci config space, not the block in pci-e extended config space.
74*10319SJason.Xu@Sun.COM  */
75*10319SJason.Xu@Sun.COM int32_t
e1000_write_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)76*10319SJason.Xu@Sun.COM e1000_write_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
77*10319SJason.Xu@Sun.COM {
78*10319SJason.Xu@Sun.COM 	uint8_t pcie_id = PCI_CAP_ID_PCI_E;
79*10319SJason.Xu@Sun.COM 	uint16_t pcie_cap;
80*10319SJason.Xu@Sun.COM 	int32_t status;
81*10319SJason.Xu@Sun.COM 
82*10319SJason.Xu@Sun.COM 	/* locate the pci-e capability block */
83*10319SJason.Xu@Sun.COM 	status = pci_lcap_locate(OS_DEP(hw)->cfg_handle, pcie_id, &pcie_cap);
84*10319SJason.Xu@Sun.COM 	if (status == DDI_SUCCESS) {
85*10319SJason.Xu@Sun.COM 
86*10319SJason.Xu@Sun.COM 		/* write at given offset into block */
87*10319SJason.Xu@Sun.COM 		pci_config_put16(OS_DEP(hw)->cfg_handle,
88*10319SJason.Xu@Sun.COM 		    (off_t)(pcie_cap + reg), *value);
89*10319SJason.Xu@Sun.COM 	}
90*10319SJason.Xu@Sun.COM 
91*10319SJason.Xu@Sun.COM 	return (status);
925779Sxy150489 }
935779Sxy150489 
945779Sxy150489 /*
958275SEric Cheng  * e1000_rar_set_vmdq - Clear the RAR registers
968275SEric Cheng  */
978275SEric Cheng void
e1000_rar_clear(struct e1000_hw * hw,uint32_t index)988275SEric Cheng e1000_rar_clear(struct e1000_hw *hw, uint32_t index)
998275SEric Cheng {
1008275SEric Cheng 
1018275SEric Cheng 	uint32_t rar_high;
1028275SEric Cheng 
1038275SEric Cheng 	/* Make the hardware the Address invalid by setting the clear bit */
1048275SEric Cheng 	rar_high = ~E1000_RAH_AV;
1058275SEric Cheng 
1068275SEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
1078275SEric Cheng 	E1000_WRITE_FLUSH(hw);
1088275SEric Cheng }
1098275SEric Cheng 
1108275SEric Cheng /*
1118275SEric Cheng  * e1000_rar_set_vmdq - Set the RAR registers for VMDq
1128275SEric Cheng  */
1138275SEric Cheng void
e1000_rar_set_vmdq(struct e1000_hw * hw,const uint8_t * addr,uint32_t index,uint32_t vmdq_mode,uint8_t qsel)1148275SEric Cheng e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *addr, uint32_t index,
1158275SEric Cheng 	uint32_t vmdq_mode, uint8_t qsel)
1168275SEric Cheng {
1178275SEric Cheng 	uint32_t rar_low, rar_high;
1188275SEric Cheng 
1198275SEric Cheng 	/*
1208275SEric Cheng 	 * NIC expects these in little endian so reverse the byte order
1218275SEric Cheng 	 * from network order (big endian) to little endian.
1228275SEric Cheng 	 */
1238275SEric Cheng 
1248275SEric Cheng 	rar_low = ((uint32_t)addr[0] | ((uint32_t)addr[1] << 8) |
1258275SEric Cheng 	    ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24));
1268275SEric Cheng 
1278275SEric Cheng 	rar_high = ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
1288275SEric Cheng 
1298275SEric Cheng 	/* Indicate to hardware the Address is Valid. */
1308275SEric Cheng 	rar_high |= E1000_RAH_AV;
1318275SEric Cheng 
1328275SEric Cheng 	/* Set que selector based on vmdq mode */
1338275SEric Cheng 	switch (vmdq_mode) {
1348275SEric Cheng 	default:
1358275SEric Cheng 	case E1000_VMDQ_OFF:
1368275SEric Cheng 		break;
1378275SEric Cheng 	case E1000_VMDQ_MAC:
1388275SEric Cheng 		rar_high |= (qsel << 18);
1398275SEric Cheng 		break;
1408275SEric Cheng 	case E1000_VMDQ_MAC_RSS:
1418275SEric Cheng 		rar_high |= 1 << (18 + qsel);
1428275SEric Cheng 		break;
1438275SEric Cheng 
1448275SEric Cheng 	}
1458275SEric Cheng 
1468275SEric Cheng 	/* write to receive address registers */
1478275SEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
1488275SEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
1498275SEric Cheng 	E1000_WRITE_FLUSH(hw);
1508275SEric Cheng }
151