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