xref: /illumos-gate/usr/src/uts/common/io/igb/igb_osdep.c (revision 75eba5b6)
1c869993eSxy /*
2c869993eSxy  * CDDL HEADER START
3c869993eSxy  *
480a11ad2Schenlu chen - Sun Microsystems - Beijing China  * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
5c869993eSxy  * The contents of this file are subject to the terms of the
6c869993eSxy  * Common Development and Distribution License (the "License").
7c869993eSxy  * You may not use this file except in compliance with the License.
8c869993eSxy  *
980a11ad2Schenlu chen - Sun Microsystems - Beijing China  * You can obtain a copy of the license at:
1080a11ad2Schenlu chen - Sun Microsystems - Beijing China  *	http://www.opensolaris.org/os/licensing.
11c869993eSxy  * See the License for the specific language governing permissions
12c869993eSxy  * and limitations under the License.
13c869993eSxy  *
1480a11ad2Schenlu chen - Sun Microsystems - Beijing China  * When using or redistributing this file, you may do so under the
1580a11ad2Schenlu chen - Sun Microsystems - Beijing China  * License only. No other modification of this header is permitted.
1680a11ad2Schenlu chen - Sun Microsystems - Beijing China  *
17c869993eSxy  * If applicable, add the following below this CDDL HEADER, with the
18c869993eSxy  * fields enclosed by brackets "[]" replaced with your own identifying
19c869993eSxy  * information: Portions Copyright [yyyy] [name of copyright owner]
20c869993eSxy  *
21c869993eSxy  * CDDL HEADER END
22c869993eSxy  */
23c869993eSxy 
24c869993eSxy /*
2580a11ad2Schenlu chen - Sun Microsystems - Beijing China  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2680a11ad2Schenlu chen - Sun Microsystems - Beijing China  * Use is subject to license terms of the CDDL.
27da14cebeSEric Cheng  */
28c869993eSxy 
29*75eba5b6SRobert Mustacchi #include "e1000_osdep.h"
30*75eba5b6SRobert Mustacchi #include "e1000_api.h"
31c869993eSxy 
32*75eba5b6SRobert Mustacchi void
e1000_pci_set_mwi(struct e1000_hw * hw)33*75eba5b6SRobert Mustacchi e1000_pci_set_mwi(struct e1000_hw *hw)
34*75eba5b6SRobert Mustacchi {
35*75eba5b6SRobert Mustacchi 	uint16_t val = hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE;
36*75eba5b6SRobert Mustacchi 
37*75eba5b6SRobert Mustacchi 	e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &val);
38*75eba5b6SRobert Mustacchi }
39*75eba5b6SRobert Mustacchi 
40*75eba5b6SRobert Mustacchi void
e1000_pci_clear_mwi(struct e1000_hw * hw)41*75eba5b6SRobert Mustacchi e1000_pci_clear_mwi(struct e1000_hw *hw)
42*75eba5b6SRobert Mustacchi {
43*75eba5b6SRobert Mustacchi 	uint16_t val = hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
44*75eba5b6SRobert Mustacchi 
45*75eba5b6SRobert Mustacchi 	e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &val);
46*75eba5b6SRobert Mustacchi }
47c869993eSxy 
48c869993eSxy void
e1000_write_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)49c869993eSxy e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
50c869993eSxy {
51c869993eSxy 	pci_config_put16(OS_DEP(hw)->cfg_handle, reg, *value);
52c869993eSxy }
53c869993eSxy 
54c869993eSxy void
e1000_read_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)55c869993eSxy e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
56c869993eSxy {
57c869993eSxy 	*value =
58c869993eSxy 	    pci_config_get16(OS_DEP(hw)->cfg_handle, reg);
59c869993eSxy }
60c869993eSxy 
61c869993eSxy /*
62b8d0a377Schenlu chen - Sun Microsystems - Beijing China  * Return the 16-bit value from pci-e config space at offset reg into the pci-e
637d46e7adSzhefeng xu - Sun Microsystems - Beijing China  * capability block.  Note that this refers to the pci-e capability block in
647d46e7adSzhefeng xu - Sun Microsystems - Beijing China  * standard pci config space, not the block in pci-e extended config space.
65c869993eSxy  */
66c869993eSxy int32_t
e1000_read_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)67c869993eSxy e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
68c869993eSxy {
697d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	uint8_t pcie_id = PCI_CAP_ID_PCI_E;
707d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	uint16_t pcie_cap;
717d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	int32_t status;
727d46e7adSzhefeng xu - Sun Microsystems - Beijing China 
737d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	/* locate the pci-e capability block */
747d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	status = pci_lcap_locate((OS_DEP(hw))->cfg_handle, pcie_id, &pcie_cap);
757d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	if (status == DDI_SUCCESS) {
767d46e7adSzhefeng xu - Sun Microsystems - Beijing China 
777d46e7adSzhefeng xu - Sun Microsystems - Beijing China 		/* read at given offset into block */
787d46e7adSzhefeng xu - Sun Microsystems - Beijing China 		*value = pci_config_get16(OS_DEP(hw)->cfg_handle,
797d46e7adSzhefeng xu - Sun Microsystems - Beijing China 		    (pcie_cap + reg));
80b8d0a377Schenlu chen - Sun Microsystems - Beijing China 	}
81c869993eSxy 
827d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	return (status);
837d46e7adSzhefeng xu - Sun Microsystems - Beijing China }
847d46e7adSzhefeng xu - Sun Microsystems - Beijing China 
857d46e7adSzhefeng xu - Sun Microsystems - Beijing China /*
867d46e7adSzhefeng xu - Sun Microsystems - Beijing China  * Write the given 16-bit value to pci-e config space at offset reg into the
877d46e7adSzhefeng xu - Sun Microsystems - Beijing China  * pci-e capability block.  Note that this refers to the pci-e capability block
887d46e7adSzhefeng xu - Sun Microsystems - Beijing China  * in standard pci config space, not the block in pci-e extended config space.
897d46e7adSzhefeng xu - Sun Microsystems - Beijing China  */
907d46e7adSzhefeng xu - Sun Microsystems - Beijing China int32_t
e1000_write_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)917d46e7adSzhefeng xu - Sun Microsystems - Beijing China e1000_write_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
927d46e7adSzhefeng xu - Sun Microsystems - Beijing China {
937d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	uint8_t pcie_id = PCI_CAP_ID_PCI_E;
947d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	uint16_t pcie_cap;
957d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	int32_t status;
967d46e7adSzhefeng xu - Sun Microsystems - Beijing China 
977d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	/* locate the pci-e capability block */
987d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	status = pci_lcap_locate(OS_DEP(hw)->cfg_handle, pcie_id, &pcie_cap);
997d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	if (status == DDI_SUCCESS) {
1007d46e7adSzhefeng xu - Sun Microsystems - Beijing China 
1017d46e7adSzhefeng xu - Sun Microsystems - Beijing China 		/* write at given offset into block */
1027d46e7adSzhefeng xu - Sun Microsystems - Beijing China 		pci_config_put16(OS_DEP(hw)->cfg_handle,
1037d46e7adSzhefeng xu - Sun Microsystems - Beijing China 		    (off_t)(pcie_cap + reg), *value);
1047d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	}
105c869993eSxy 
1067d46e7adSzhefeng xu - Sun Microsystems - Beijing China 	return (status);
107c869993eSxy }
108da14cebeSEric Cheng 
109da14cebeSEric Cheng /*
110da14cebeSEric Cheng  * e1000_rar_set_vmdq - Clear the RAR registers
111da14cebeSEric Cheng  */
112da14cebeSEric Cheng void
e1000_rar_clear(struct e1000_hw * hw,uint32_t index)113da14cebeSEric Cheng e1000_rar_clear(struct e1000_hw *hw, uint32_t index)
114da14cebeSEric Cheng {
115da14cebeSEric Cheng 
116da14cebeSEric Cheng 	uint32_t rar_high;
117da14cebeSEric Cheng 
118da14cebeSEric Cheng 	/* Make the hardware the Address invalid by setting the clear bit */
119da14cebeSEric Cheng 	rar_high = ~E1000_RAH_AV;
120da14cebeSEric Cheng 
121da14cebeSEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
122da14cebeSEric Cheng 	E1000_WRITE_FLUSH(hw);
123da14cebeSEric Cheng }
124da14cebeSEric Cheng 
125da14cebeSEric Cheng /*
126da14cebeSEric Cheng  * e1000_rar_set_vmdq - Set the RAR registers for VMDq
127da14cebeSEric Cheng  */
128da14cebeSEric Cheng void
e1000_rar_set_vmdq(struct e1000_hw * hw,const uint8_t * addr,uint32_t index,uint32_t vmdq_mode,uint8_t qsel)129da14cebeSEric Cheng e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *addr, uint32_t index,
130da14cebeSEric Cheng 	uint32_t vmdq_mode, uint8_t qsel)
131da14cebeSEric Cheng {
132da14cebeSEric Cheng 	uint32_t rar_low, rar_high;
133da14cebeSEric Cheng 
134da14cebeSEric Cheng 	/*
135da14cebeSEric Cheng 	 * NIC expects these in little endian so reverse the byte order
136da14cebeSEric Cheng 	 * from network order (big endian) to little endian.
137da14cebeSEric Cheng 	 */
138da14cebeSEric Cheng 
139da14cebeSEric Cheng 	rar_low = ((uint32_t)addr[0] | ((uint32_t)addr[1] << 8) |
140da14cebeSEric Cheng 	    ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24));
141da14cebeSEric Cheng 
142da14cebeSEric Cheng 	rar_high = ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
143da14cebeSEric Cheng 
144da14cebeSEric Cheng 	/* Indicate to hardware the Address is Valid. */
145da14cebeSEric Cheng 	rar_high |= E1000_RAH_AV;
146da14cebeSEric Cheng 
147da14cebeSEric Cheng 	/* Set que selector based on vmdq mode */
148da14cebeSEric Cheng 	switch (vmdq_mode) {
149da14cebeSEric Cheng 	default:
150da14cebeSEric Cheng 	case E1000_VMDQ_OFF:
151da14cebeSEric Cheng 		break;
152da14cebeSEric Cheng 	case E1000_VMDQ_MAC:
153da14cebeSEric Cheng 		rar_high |= (qsel << 18);
154da14cebeSEric Cheng 		break;
155da14cebeSEric Cheng 	case E1000_VMDQ_MAC_RSS:
156da14cebeSEric Cheng 		rar_high |= 1 << (18 + qsel);
157da14cebeSEric Cheng 		break;
158da14cebeSEric Cheng 
159da14cebeSEric Cheng 	}
160da14cebeSEric Cheng 
161da14cebeSEric Cheng 	/* write to receive address registers */
162da14cebeSEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
163da14cebeSEric Cheng 	E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
164da14cebeSEric Cheng 	E1000_WRITE_FLUSH(hw);
165da14cebeSEric Cheng }
166