1 /*- 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of version 2 of the GNU General Public License as 11 * published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, but 14 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 21 * The full GNU General Public License is included in this distribution 22 * in the file called LICENSE.GPL. 23 * 24 * BSD LICENSE 25 * 26 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 41 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 42 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 43 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 44 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 46 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 47 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 48 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 49 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 50 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 51 */ 52 53 #include <sys/cdefs.h> 54 __FBSDID("$FreeBSD$"); 55 56 /** 57 * @file 58 * 59 * @brief This file contains the method implementations utilized in writing 60 * out PCI data for the SCI core. 61 */ 62 63 #include <dev/isci/scil/scic_user_callback.h> 64 65 #include <dev/isci/scil/scic_sds_pci.h> 66 #include <dev/isci/scil/scic_sds_controller.h> 67 68 /** 69 * @brief This method reads from the driver the BARs that are needed to 70 * determine the virtual memory space for the controller registers 71 * 72 * @param[in] this_controller The controller for which to read the base 73 * address registers. 74 */ 75 void scic_sds_pci_bar_initialization( 76 SCIC_SDS_CONTROLLER_T* this_controller 77 ) 78 { 79 #ifdef ARLINGTON_BUILD 80 81 #define ARLINGTON_LEX_BAR 0 82 #define ARLINGTON_SMU_BAR 1 83 #define ARLINGTON_SCU_BAR 2 84 #define LEX_REGISTER_OFFSET 0x40000 85 86 this_controller->lex_registers = 87 ((char *)scic_cb_pci_get_bar( 88 this_controller, ARLINGTON_LEX_BAR) + LEX_REGISTER_OFFSET); 89 this_controller->smu_registers = 90 (SMU_REGISTERS_T *)scic_cb_pci_get_bar(this_controller, ARLINGTON_SMU_BAR); 91 this_controller->scu_registers = 92 (SCU_REGISTERS_T *)scic_cb_pci_get_bar(this_controller, ARLINGTON_SCU_BAR); 93 94 #else // !ARLINGTON_BUILD 95 96 #if !defined(ENABLE_PCI_IO_SPACE_ACCESS) 97 98 this_controller->smu_registers = 99 (SMU_REGISTERS_T *)( 100 (char *)scic_cb_pci_get_bar(this_controller, PATSBURG_SMU_BAR) 101 +(0x4000 * this_controller->controller_index)); 102 this_controller->scu_registers = 103 (SCU_REGISTERS_T *)( 104 (char *)scic_cb_pci_get_bar(this_controller, PATSBURG_SCU_BAR) 105 +(0x400000 * this_controller->controller_index)); 106 107 #else // !defined(ENABLE_PCI_IO_SPACE_ACCESS) 108 109 if (this_controller->controller_index == 0) 110 { 111 this_controller->smu_registers = (SMU_REGISTERS_T *) 112 scic_cb_pci_get_bar(this_controller, PATSBURG_IO_SPACE_BAR0); 113 } 114 else 115 { 116 if (this_controller->pci_revision == SCU_PBG_HBA_REV_B0) 117 { 118 // SCU B0 violates PCI spec for size of IO bar this is corrected 119 // in subsequent version of the hardware so we can safely use the 120 // else condition below. 121 this_controller->smu_registers = (SMU_REGISTERS_T *) 122 (scic_cb_pci_get_bar(this_controller, PATSBURG_IO_SPACE_BAR0) + 0x100); 123 } 124 else 125 { 126 this_controller->smu_registers = (SMU_REGISTERS_T *) 127 scic_cb_pci_get_bar(this_controller, PATSBURG_IO_SPACE_BAR1); 128 } 129 } 130 131 // No need to get the bar. We will be using the offset to write to 132 // input/output ports via 0xA0 and 0xA4. 133 this_controller->scu_registers = (SCU_REGISTERS_T *) 0; 134 135 #endif // !defined(ENABLE_PCI_IO_SPACE_ACCESS) 136 137 #endif // ARLINGTON_BUILD 138 } 139 140 #if defined(ENABLE_PCI_IO_SPACE_ACCESS) && !defined(ARLINGTON_BUILD) 141 142 /** 143 * @brief This method will read from PCI memory for the SMU register 144 * space via IO space access. 145 * 146 * @param[in] controller The controller for which to read a DWORD. 147 * @param[in] address This parameter depicts the address from 148 * which to read. 149 * 150 * @return The value being returned from the PCI memory location. 151 * 152 * @todo This PCI memory access calls likely need to be optimized into macro? 153 */ 154 U32 scic_sds_pci_read_smu_dword( 155 SCI_CONTROLLER_HANDLE_T controller, 156 void * address 157 ) 158 { 159 return scic_cb_pci_read_dword(controller, address); 160 } 161 162 /** 163 * @brief This method will write to PCI memory for the SMU register 164 * space via IO space access. 165 * 166 * @param[in] controller The controller for which to read a DWORD. 167 * @param[in] address This parameter depicts the address into 168 * which to write. 169 * @param[out] write_value This parameter depicts the value being written 170 * into the PCI memory location. 171 * 172 * @todo This PCI memory access calls likely need to be optimized into macro? 173 */ 174 void scic_sds_pci_write_smu_dword( 175 SCI_CONTROLLER_HANDLE_T controller, 176 void * address, 177 U32 write_value 178 ) 179 { 180 scic_cb_pci_write_dword(controller, address, write_value); 181 } 182 183 /** 184 * @brief This method will read from PCI memory for the SCU register 185 * space via IO space access. 186 * 187 * @param[in] controller The controller for which to read a DWORD. 188 * @param[in] address This parameter depicts the address from 189 * which to read. 190 * 191 * @return The value being returned from the PCI memory location. 192 * 193 * @todo This PCI memory access calls likely need to be optimized into macro? 194 */ 195 U32 scic_sds_pci_read_scu_dword( 196 SCI_CONTROLLER_HANDLE_T controller, 197 void * address 198 ) 199 { 200 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller; 201 202 scic_cb_pci_write_dword( 203 controller, 204 (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_ADDRESS_WINDOW_OFFSET), 205 (U32) address 206 ); 207 208 return scic_cb_pci_read_dword( 209 controller, 210 (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_DATA_WINDOW_OFFSET) 211 ); 212 } 213 214 /** 215 * @brief This method will write to PCI memory for the SCU register 216 * space via IO space access. 217 * 218 * @param[in] controller The controller for which to read a DWORD. 219 * @param[in] address This parameter depicts the address into 220 * which to write. 221 * @param[out] write_value This parameter depicts the value being written 222 * into the PCI memory location. 223 * 224 * @todo This PCI memory access calls likely need to be optimized into macro? 225 */ 226 void scic_sds_pci_write_scu_dword( 227 SCI_CONTROLLER_HANDLE_T controller, 228 void * address, 229 U32 write_value 230 ) 231 { 232 SCIC_SDS_CONTROLLER_T * this_controller = (SCIC_SDS_CONTROLLER_T*)controller; 233 234 scic_cb_pci_write_dword( 235 controller, 236 (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_ADDRESS_WINDOW_OFFSET), 237 (U32) address 238 ); 239 240 scic_cb_pci_write_dword( 241 controller, 242 (void*) ((char *)(this_controller->smu_registers) + SCU_MMR_DATA_WINDOW_OFFSET), 243 write_value 244 ); 245 } 246 247 #endif // defined(ENABLE_PCI_IO_SPACE_ACCESS) 248