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