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 __FBSDID("$FreeBSD$"); 31 #include <dev/pms/config.h> 32 33 #include <dev/pms/freebsd/driver/common/osenv.h> 34 #include <dev/pms/freebsd/driver/common/ostypes.h> 35 #include <dev/pms/freebsd/driver/common/osdebug.h> 36 37 #include <dev/pms/RefTisa/sallsdk/api/sa.h> 38 #include <dev/pms/RefTisa/sallsdk/api/saapi.h> 39 #include <dev/pms/RefTisa/sallsdk/api/saosapi.h> 40 41 #include <dev/pms/RefTisa/tisa/api/titypes.h> 42 #include <dev/pms/RefTisa/tisa/api/ostiapi.h> 43 #include <dev/pms/RefTisa/tisa/api/tiapi.h> 44 #include <dev/pms/RefTisa/tisa/api/tiglobal.h> 45 46 #ifdef FDS_SM 47 #include <dev/pms/RefTisa/sat/api/sm.h> 48 #include <dev/pms/RefTisa/sat/api/smapi.h> 49 #include <dev/pms/RefTisa/sat/api/tdsmapi.h> 50 #endif 51 52 #ifdef FDS_DM 53 #include <dev/pms/RefTisa/discovery/api/dm.h> 54 #include <dev/pms/RefTisa/discovery/api/dmapi.h> 55 #include <dev/pms/RefTisa/discovery/api/tddmapi.h> 56 #endif 57 58 #include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h> 59 #include <dev/pms/freebsd/driver/common/osstring.h> 60 #include <dev/pms/RefTisa/tisa/sassata/common/tdutil.h> 61 62 #ifdef INITIATOR_DRIVER 63 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h> 64 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itddefs.h> 65 #include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdglobl.h> 66 #endif 67 68 #ifdef TARGET_DRIVER 69 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdglobl.h> 70 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdxchg.h> 71 #include <dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdtypes.h> 72 #endif 73 74 #include <dev/pms/RefTisa/tisa/sassata/common/tdsatypes.h> 75 #include <dev/pms/RefTisa/tisa/sassata/common/tdproto.h> 76 77 /***************************************************************************** 78 *! \biref tiCOMInterruptHandler 79 * 80 * Purpose: This function is called to service the hardware interrupt of the 81 * hardware. 82 * 83 * \param tiRoot: Pointer to initiator specific root data structure for this 84 * instance of the driver. 85 * 86 * \param channelNum: The zero-base channel number of the controller. 87 * 0xFFFFFFFF indicates that the OS-App Specific layer does 88 * not provide the channel number. The TD/LL Layer needs to 89 * discover of any of its own channels that are causing the 90 * interrupt. 91 * 92 * \return None 93 * 94 * \note - The only thing that this API will do is to acknowledge and mask 95 * the necessary hardware interrupt register. The actual processing 96 * of the interrupt handler is done in tiCOMDelayedInterruptHandler(). 97 * 98 *****************************************************************************/ 99 FORCEINLINE bit32 100 tiCOMInterruptHandler( 101 tiRoot_t * tiRoot, 102 bit32 channelNum) 103 { 104 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; 105 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); 106 agsaRoot_t *agRoot = &(tdsaAllShared->agRootNonInt); 107 bit32 interruptPending = agFALSE; 108 109 interruptPending = saInterruptHandler(agRoot, channelNum); 110 111 return interruptPending; 112 113 } /* tiCOMInterruptHandler() */ 114 115 116 /***************************************************************************** 117 *! \brief tiCOMDelayedInterruptHandler 118 * 119 * Purpose: This function is called to process the task associated with the 120 * interrupt handler. The task that this handler needs to do includes: 121 * completion of I/O, login event, error event, etc 122 * 123 * \param tiRoot: Pointer to initiator specific root data structure for 124 * this instance of the driver. 125 * \param channelNum: The zero-base channel number of the controller. 126 * 0xFFFFFFFF indicates that the OS-App Specific layer does 127 * not provide the channel number. The TD/LL Layer needs to 128 * discover of any of its own channels that are causing the 129 * interrupt. 130 * \param count: Count on how many items (such as IO completion) need to 131 * be processed in this context. 132 * \param interruptContext: The thread/process context within which this 133 * function is called. 134 * 135 * tiInterruptContext: this function is called within an 136 * interrupt context. 137 * tiNonInterruptContext: this function is called outside an 138 * interrupt context. 139 * \return None 140 * 141 *****************************************************************************/ 142 FORCEINLINE 143 bit32 144 tiCOMDelayedInterruptHandler( 145 tiRoot_t *tiRoot, 146 bit32 channelNum, 147 bit32 count, 148 bit32 context 149 ) 150 { 151 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; 152 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); 153 agsaRoot_t *agRoot = agNULL; 154 bit32 completed = 0; 155 156 TDSA_OUT_ENTER(tiRoot); 157 158 if(context == tiInterruptContext) 159 { 160 agRoot = &(tdsaAllShared->agRootInt); 161 } 162 else 163 { 164 agRoot = &(tdsaAllShared->agRootNonInt); 165 } 166 167 completed = saDelayedInterruptHandler(agRoot, channelNum, count); 168 169 if(completed == 0) 170 { 171 TI_DBG3(("tiCOMDelayedInterruptHandler: processedMsgCount zero\n")); 172 } 173 174 175 TDSA_OUT_LEAVE(tiRoot); 176 177 return(completed); 178 } /* tiCOMDelayedInterruptHandler() */ 179 180 181 /***************************************************************************** 182 *! \brief tiCOMSystemInterruptsActive 183 * 184 * Purpose: This function is called to indicate whether interrupts are 185 * active or not from this point in time. 186 * 187 * \param tiRoot: Pointer to initiator specific root data structure for 188 * this instance of the driver. 189 * \param sysIntsActive: Boolean value either true or false 190 * 191 * \return None 192 * 193 *****************************************************************************/ 194 osGLOBAL void 195 tiCOMSystemInterruptsActive( 196 tiRoot_t * tiRoot, 197 bit32 sysIntsActive 198 ) 199 { 200 201 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; 202 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); 203 agsaRoot_t *agRoot; 204 agRoot = &(tdsaAllShared->agRootNonInt); 205 206 #ifdef SPC_POLLINGMODE 207 if(sysIntsActive) return; 208 #endif /* SPC_POLLINGMODE */ 209 210 tdsaAllShared->flags.sysIntsActive = sysIntsActive; 211 212 TI_DBG6(("tiCOMSystemInterruptsActive: start\n")); 213 /* enable low level interrupts */ 214 if(agRoot->sdkData != agNULL) 215 { 216 saSystemInterruptsActive( 217 agRoot, 218 (agBOOLEAN) tdsaAllShared->flags.sysIntsActive 219 ); 220 } 221 222 TI_DBG6(("tiCOMSystemInterruptsActive: end\n")); 223 } /* tiCOMSystemInterruptsActive */ 224 225 226 osGLOBAL void 227 tiComCountActiveIORequests( 228 tiRoot_t * tiRoot 229 ) 230 { 231 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; 232 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); 233 agsaRoot_t *agRoot; 234 agRoot = &(tdsaAllShared->agRootNonInt); 235 saCountActiveIORequests(agRoot ); 236 } 237 238 /***************************************************************************** 239 *! \brief tiCOMInterruptEnable 240 * 241 * Purpose: This function is called to enable an interrupts on the specified channel 242 * active or not from this point in time. 243 * 244 * \param tiRoot: Pointer to initiator specific root data structure for 245 * this instance of the driver. 246 * \param : channelNum vector number for MSIX Zero for legacy interrupt 247 * 248 * \return None 249 * 250 *****************************************************************************/ 251 osGLOBAL FORCEINLINE 252 void 253 tiCOMInterruptEnable( 254 tiRoot_t * tiRoot, 255 bit32 channelNum) 256 { 257 tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; 258 tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); 259 agsaRoot_t *agRoot; 260 agRoot = &(tdsaAllShared->agRootNonInt); 261 262 saSystemInterruptsEnable(agRoot, channelNum); 263 } 264