1 /*
2 * CDDL HEADER START
3 *
4 * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
5 * The contents of this file are subject to the terms of the
6 * Common Development and Distribution License (the "License").
7 * You may not use this file except in compliance with the License.
8 *
9 * You can obtain a copy of the license at:
10 * http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When using or redistributing this file, you may do so under the
15 * License only. No other modification of this header is permitted.
16 *
17 * If applicable, add the following below this CDDL HEADER, with the
18 * fields enclosed by brackets "[]" replaced with your own identifying
19 * information: Portions Copyright [yyyy] [name of copyright owner]
20 *
21 * CDDL HEADER END
22 */
23
24 /*
25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms of the CDDL.
27 */
28
29 #include "e1000_osdep.h"
30 #include "e1000_api.h"
31
32 void
e1000_pci_set_mwi(struct e1000_hw * hw)33 e1000_pci_set_mwi(struct e1000_hw *hw)
34 {
35 uint16_t val = hw->bus.pci_cmd_word | CMD_MEM_WRT_INVALIDATE;
36
37 e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &val);
38 }
39
40 void
e1000_pci_clear_mwi(struct e1000_hw * hw)41 e1000_pci_clear_mwi(struct e1000_hw *hw)
42 {
43 uint16_t val = hw->bus.pci_cmd_word & ~CMD_MEM_WRT_INVALIDATE;
44
45 e1000_write_pci_cfg(hw, PCI_COMMAND_REGISTER, &val);
46 }
47
48 void
e1000_write_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)49 e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
50 {
51 pci_config_put16(OS_DEP(hw)->cfg_handle, reg, *value);
52 }
53
54 void
e1000_read_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)55 e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
56 {
57 *value =
58 pci_config_get16(OS_DEP(hw)->cfg_handle, reg);
59 }
60
61 /*
62 * Return the 16-bit value from pci-e config space at offset reg into the pci-e
63 * capability block. Note that this refers to the pci-e capability block in
64 * standard pci config space, not the block in pci-e extended config space.
65 */
66 int32_t
e1000_read_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)67 e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
68 {
69 uint8_t pcie_id = PCI_CAP_ID_PCI_E;
70 uint16_t pcie_cap;
71 int32_t status;
72
73 /* locate the pci-e capability block */
74 status = pci_lcap_locate((OS_DEP(hw))->cfg_handle, pcie_id, &pcie_cap);
75 if (status == DDI_SUCCESS) {
76
77 /* read at given offset into block */
78 *value = pci_config_get16(OS_DEP(hw)->cfg_handle,
79 (pcie_cap + reg));
80 }
81
82 return (status);
83 }
84
85 /*
86 * Write the given 16-bit value to pci-e config space at offset reg into the
87 * pci-e capability block. Note that this refers to the pci-e capability block
88 * in standard pci config space, not the block in pci-e extended config space.
89 */
90 int32_t
e1000_write_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)91 e1000_write_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
92 {
93 uint8_t pcie_id = PCI_CAP_ID_PCI_E;
94 uint16_t pcie_cap;
95 int32_t status;
96
97 /* locate the pci-e capability block */
98 status = pci_lcap_locate(OS_DEP(hw)->cfg_handle, pcie_id, &pcie_cap);
99 if (status == DDI_SUCCESS) {
100
101 /* write at given offset into block */
102 pci_config_put16(OS_DEP(hw)->cfg_handle,
103 (off_t)(pcie_cap + reg), *value);
104 }
105
106 return (status);
107 }
108
109 /*
110 * e1000_rar_set_vmdq - Clear the RAR registers
111 */
112 void
e1000_rar_clear(struct e1000_hw * hw,uint32_t index)113 e1000_rar_clear(struct e1000_hw *hw, uint32_t index)
114 {
115
116 uint32_t rar_high;
117
118 /* Make the hardware the Address invalid by setting the clear bit */
119 rar_high = ~E1000_RAH_AV;
120
121 E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
122 E1000_WRITE_FLUSH(hw);
123 }
124
125 /*
126 * e1000_rar_set_vmdq - Set the RAR registers for VMDq
127 */
128 void
e1000_rar_set_vmdq(struct e1000_hw * hw,const uint8_t * addr,uint32_t index,uint32_t vmdq_mode,uint8_t qsel)129 e1000_rar_set_vmdq(struct e1000_hw *hw, const uint8_t *addr, uint32_t index,
130 uint32_t vmdq_mode, uint8_t qsel)
131 {
132 uint32_t rar_low, rar_high;
133
134 /*
135 * NIC expects these in little endian so reverse the byte order
136 * from network order (big endian) to little endian.
137 */
138
139 rar_low = ((uint32_t)addr[0] | ((uint32_t)addr[1] << 8) |
140 ((uint32_t)addr[2] << 16) | ((uint32_t)addr[3] << 24));
141
142 rar_high = ((uint32_t)addr[4] | ((uint32_t)addr[5] << 8));
143
144 /* Indicate to hardware the Address is Valid. */
145 rar_high |= E1000_RAH_AV;
146
147 /* Set que selector based on vmdq mode */
148 switch (vmdq_mode) {
149 default:
150 case E1000_VMDQ_OFF:
151 break;
152 case E1000_VMDQ_MAC:
153 rar_high |= (qsel << 18);
154 break;
155 case E1000_VMDQ_MAC_RSS:
156 rar_high |= 1 << (18 + qsel);
157 break;
158
159 }
160
161 /* write to receive address registers */
162 E1000_WRITE_REG_ARRAY(hw, E1000_RA, (index << 1), rar_low);
163 E1000_WRITE_REG_ARRAY(hw, E1000_RA, ((index << 1) + 1), rar_high);
164 E1000_WRITE_FLUSH(hw);
165 }
166