1c869993eSxy150489 /*
2c869993eSxy150489 * CDDL HEADER START
3c869993eSxy150489 *
480a11ad2Schenlu chen - Sun Microsystems - Beijing China * Copyright(c) 2007-2009 Intel Corporation. All rights reserved.
5c869993eSxy150489 * The contents of this file are subject to the terms of the
6c869993eSxy150489 * Common Development and Distribution License (the "License").
7c869993eSxy150489 * You may not use this file except in compliance with the License.
8c869993eSxy150489 *
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.
11c869993eSxy150489 * See the License for the specific language governing permissions
12c869993eSxy150489 * and limitations under the License.
13c869993eSxy150489 *
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 *
17c869993eSxy150489 * If applicable, add the following below this CDDL HEADER, with the
18c869993eSxy150489 * fields enclosed by brackets "[]" replaced with your own identifying
19c869993eSxy150489 * information: Portions Copyright [yyyy] [name of copyright owner]
20c869993eSxy150489 *
21c869993eSxy150489 * CDDL HEADER END
22c869993eSxy150489 */
23c869993eSxy150489
24c869993eSxy150489 /*
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 */
28c869993eSxy150489
29*75eba5b6SRobert Mustacchi #include "e1000_osdep.h"
30*75eba5b6SRobert Mustacchi #include "e1000_api.h"
31c869993eSxy150489
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 }
47c869993eSxy150489
48c869993eSxy150489 void
e1000_write_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)49c869993eSxy150489 e1000_write_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
50c869993eSxy150489 {
51c869993eSxy150489 pci_config_put16(OS_DEP(hw)->cfg_handle, reg, *value);
52c869993eSxy150489 }
53c869993eSxy150489
54c869993eSxy150489 void
e1000_read_pci_cfg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)55c869993eSxy150489 e1000_read_pci_cfg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
56c869993eSxy150489 {
57c869993eSxy150489 *value =
58c869993eSxy150489 pci_config_get16(OS_DEP(hw)->cfg_handle, reg);
59c869993eSxy150489 }
60c869993eSxy150489
61c869993eSxy150489 /*
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.
65c869993eSxy150489 */
66c869993eSxy150489 int32_t
e1000_read_pcie_cap_reg(struct e1000_hw * hw,uint32_t reg,uint16_t * value)67c869993eSxy150489 e1000_read_pcie_cap_reg(struct e1000_hw *hw, uint32_t reg, uint16_t *value)
68c869993eSxy150489 {
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;
72c869993eSxy150489
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));
80c869993eSxy150489 }
81c869993eSxy150489
827d46e7adSzhefeng xu - Sun Microsystems - Beijing China return (status);
837d46e7adSzhefeng xu - Sun Microsystems - Beijing China }
84c869993eSxy150489
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 }
1057d46e7adSzhefeng xu - Sun Microsystems - Beijing China
1067d46e7adSzhefeng xu - Sun Microsystems - Beijing China return (status);
107c869993eSxy150489 }
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