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