xref: /freebsd/sys/dev/isci/scil/scic_sds_pci.c (revision 4310d6deb27da04d3fe079a0584edd557a764e21)
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