1 /*******************************************************************************
2 *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
3 *
4 *Redistribution and use in source and binary forms, with or without modification, are permitted provided
5 *that the following conditions are met:
6 *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7 *following disclaimer.
8 *2. Redistributions in binary form must reproduce the above copyright notice,
9 *this list of conditions and the following disclaimer in the documentation and/or other materials provided
10 *with the distribution.
11 *
12 *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13 *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14 *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15 *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16 *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17 *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19 *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20
21 ********************************************************************************/
22 /*******************************************************************************/
23 /** \file
24 *
25 *
26 * This file contains interrupt related functions in the SAS/SATA TD layer
27 *
28 */
29 #include <sys/cdefs.h>
30 #include <dev/pms/config.h>
31
32 #include <dev/pms/freebsd/driver/common/osenv.h>
33 #include <dev/pms/freebsd/driver/common/ostypes.h>
34 #include <dev/pms/freebsd/driver/common/osdebug.h>
35
36 #include <dev/pms/RefTisa/sallsdk/api/sa.h>
37 #include <dev/pms/RefTisa/sallsdk/api/saapi.h>
38 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h>
39
40 #include <dev/pms/RefTisa/tisa/api/titypes.h>
41 #include <dev/pms/RefTisa/tisa/api/ostiapi.h>
42 #include <dev/pms/RefTisa/tisa/api/tiapi.h>
43 #include <dev/pms/RefTisa/tisa/api/tiglobal.h>
44
45 #ifdef FDS_SM
46 #include <dev/pms/RefTisa/sat/api/sm.h>
47 #include <dev/pms/RefTisa/sat/api/smapi.h>
48 #include <dev/pms/RefTisa/sat/api/tdsmapi.h>
49 #endif
50
51 #ifdef FDS_DM
52 #include <dev/pms/RefTisa/discovery/api/dm.h>
53 #include <dev/pms/RefTisa/discovery/api/dmapi.h>
54 #include <dev/pms/RefTisa/discovery/api/tddmapi.h>
55 #endif
56
57 #include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
58 #include <dev/pms/freebsd/driver/common/osstring.h>
59 #include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h>
60
61 #ifdef INITIATOR_DRIVER
62 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
63 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h>
64 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h>
65 #endif
66
67 #ifdef TARGET_DRIVER
68 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h>
69 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h>
70 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h>
71 #endif
72
73 #include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h>
74 #include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h>
75
76 /*****************************************************************************
77 *! \biref tiCOMInterruptHandler
78 *
79 * Purpose: This function is called to service the hardware interrupt of the
80 * hardware.
81 *
82 * \param tiRoot: Pointer to initiator specific root data structure for this
83 * instance of the driver.
84 *
85 * \param channelNum: The zero-base channel number of the controller.
86 * 0xFFFFFFFF indicates that the OS-App Specific layer does
87 * not provide the channel number. The TD/LL Layer needs to
88 * discover of any of its own channels that are causing the
89 * interrupt.
90 *
91 * \return None
92 *
93 * \note - The only thing that this API will do is to acknowledge and mask
94 * the necessary hardware interrupt register. The actual processing
95 * of the interrupt handler is done in tiCOMDelayedInterruptHandler().
96 *
97 *****************************************************************************/
98 FORCEINLINE bit32
tiCOMInterruptHandler(tiRoot_t * tiRoot,bit32 channelNum)99 tiCOMInterruptHandler(
100 tiRoot_t * tiRoot,
101 bit32 channelNum)
102 {
103 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
104 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
105 agsaRoot_t *agRoot = &(tdsaAllShared->agRootNonInt);
106 bit32 interruptPending = agFALSE;
107
108 interruptPending = saInterruptHandler(agRoot, channelNum);
109
110 return interruptPending;
111
112 } /* tiCOMInterruptHandler() */
113
114
115 /*****************************************************************************
116 *! \brief tiCOMDelayedInterruptHandler
117 *
118 * Purpose: This function is called to process the task associated with the
119 * interrupt handler. The task that this handler needs to do includes:
120 * completion of I/O, login event, error event, etc
121 *
122 * \param tiRoot: Pointer to initiator specific root data structure for
123 * this instance of the driver.
124 * \param channelNum: The zero-base channel number of the controller.
125 * 0xFFFFFFFF indicates that the OS-App Specific layer does
126 * not provide the channel number. The TD/LL Layer needs to
127 * discover of any of its own channels that are causing the
128 * interrupt.
129 * \param count: Count on how many items (such as IO completion) need to
130 * be processed in this context.
131 * \param interruptContext: The thread/process context within which this
132 * function is called.
133 *
134 * tiInterruptContext: this function is called within an
135 * interrupt context.
136 * tiNonInterruptContext: this function is called outside an
137 * interrupt context.
138 * \return None
139 *
140 *****************************************************************************/
141 FORCEINLINE
142 bit32
tiCOMDelayedInterruptHandler(tiRoot_t * tiRoot,bit32 channelNum,bit32 count,bit32 context)143 tiCOMDelayedInterruptHandler(
144 tiRoot_t *tiRoot,
145 bit32 channelNum,
146 bit32 count,
147 bit32 context
148 )
149 {
150 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
151 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
152 agsaRoot_t *agRoot = agNULL;
153 bit32 completed = 0;
154
155 TDSA_OUT_ENTER(tiRoot);
156
157 if(context == tiInterruptContext)
158 {
159 agRoot = &(tdsaAllShared->agRootInt);
160 }
161 else
162 {
163 agRoot = &(tdsaAllShared->agRootNonInt);
164 }
165
166 completed = saDelayedInterruptHandler(agRoot, channelNum, count);
167
168 if(completed == 0)
169 {
170 TI_DBG3(("tiCOMDelayedInterruptHandler: processedMsgCount zero\n"));
171 }
172
173
174 TDSA_OUT_LEAVE(tiRoot);
175
176 return(completed);
177 } /* tiCOMDelayedInterruptHandler() */
178
179
180 /*****************************************************************************
181 *! \brief tiCOMSystemInterruptsActive
182 *
183 * Purpose: This function is called to indicate whether interrupts are
184 * active or not from this point in time.
185 *
186 * \param tiRoot: Pointer to initiator specific root data structure for
187 * this instance of the driver.
188 * \param sysIntsActive: Boolean value either true or false
189 *
190 * \return None
191 *
192 *****************************************************************************/
193 osGLOBAL void
tiCOMSystemInterruptsActive(tiRoot_t * tiRoot,bit32 sysIntsActive)194 tiCOMSystemInterruptsActive(
195 tiRoot_t * tiRoot,
196 bit32 sysIntsActive
197 )
198 {
199
200 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
201 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
202 agsaRoot_t *agRoot;
203 agRoot = &(tdsaAllShared->agRootNonInt);
204
205 #ifdef SPC_POLLINGMODE
206 if(sysIntsActive) return;
207 #endif /* SPC_POLLINGMODE */
208
209 tdsaAllShared->flags.sysIntsActive = sysIntsActive;
210
211 TI_DBG6(("tiCOMSystemInterruptsActive: start\n"));
212 /* enable low level interrupts */
213 if(agRoot->sdkData != agNULL)
214 {
215 saSystemInterruptsActive(
216 agRoot,
217 (agBOOLEAN) tdsaAllShared->flags.sysIntsActive
218 );
219 }
220
221 TI_DBG6(("tiCOMSystemInterruptsActive: end\n"));
222 } /* tiCOMSystemInterruptsActive */
223
224
225 osGLOBAL void
tiComCountActiveIORequests(tiRoot_t * tiRoot)226 tiComCountActiveIORequests(
227 tiRoot_t * tiRoot
228 )
229 {
230 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
231 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
232 agsaRoot_t *agRoot;
233 agRoot = &(tdsaAllShared->agRootNonInt);
234 saCountActiveIORequests(agRoot );
235 }
236
237 /*****************************************************************************
238 *! \brief tiCOMInterruptEnable
239 *
240 * Purpose: This function is called to enable an interrupts on the specified channel
241 * active or not from this point in time.
242 *
243 * \param tiRoot: Pointer to initiator specific root data structure for
244 * this instance of the driver.
245 * \param : channelNum vector number for MSIX Zero for legacy interrupt
246 *
247 * \return None
248 *
249 *****************************************************************************/
250 osGLOBAL FORCEINLINE
251 void
tiCOMInterruptEnable(tiRoot_t * tiRoot,bit32 channelNum)252 tiCOMInterruptEnable(
253 tiRoot_t * tiRoot,
254 bit32 channelNum)
255 {
256 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData;
257 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared);
258 agsaRoot_t *agRoot;
259 agRoot = &(tdsaAllShared->agRootNonInt);
260
261 saSystemInterruptsEnable(agRoot, channelNum);
262 }
263