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 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 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 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 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 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 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 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 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