/******************************************************************************* *Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved. * *Redistribution and use in source and binary forms, with or without modification, are permitted provided *that the following conditions are met: *1. Redistributions of source code must retain the above copyright notice, this list of conditions and the *following disclaimer. *2. Redistributions in binary form must reproduce the above copyright notice, *this list of conditions and the following disclaimer in the documentation and/or other materials provided *with the distribution. * *THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED *WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE *FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT *NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR *BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ********************************************************************************/ /*******************************************************************************/ /** \file * * * This file contains interrupt related functions in the SAS/SATA TD layer * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #ifdef FDS_SM #include #include #include #endif #ifdef FDS_DM #include #include #include #endif #include #include #include #ifdef INITIATOR_DRIVER #include #include #include #endif #ifdef TARGET_DRIVER #include #include #include #endif #include #include /***************************************************************************** *! \biref tiCOMInterruptHandler * * Purpose: This function is called to service the hardware interrupt of the * hardware. * * \param tiRoot: Pointer to initiator specific root data structure for this * instance of the driver. * * \param channelNum: The zero-base channel number of the controller. * 0xFFFFFFFF indicates that the OS-App Specific layer does * not provide the channel number. The TD/LL Layer needs to * discover of any of its own channels that are causing the * interrupt. * * \return None * * \note - The only thing that this API will do is to acknowledge and mask * the necessary hardware interrupt register. The actual processing * of the interrupt handler is done in tiCOMDelayedInterruptHandler(). * *****************************************************************************/ FORCEINLINE bit32 tiCOMInterruptHandler( tiRoot_t * tiRoot, bit32 channelNum) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); agsaRoot_t *agRoot = &(tdsaAllShared->agRootNonInt); bit32 interruptPending = agFALSE; interruptPending = saInterruptHandler(agRoot, channelNum); return interruptPending; } /* tiCOMInterruptHandler() */ /***************************************************************************** *! \brief tiCOMDelayedInterruptHandler * * Purpose: This function is called to process the task associated with the * interrupt handler. The task that this handler needs to do includes: * completion of I/O, login event, error event, etc * * \param tiRoot: Pointer to initiator specific root data structure for * this instance of the driver. * \param channelNum: The zero-base channel number of the controller. * 0xFFFFFFFF indicates that the OS-App Specific layer does * not provide the channel number. The TD/LL Layer needs to * discover of any of its own channels that are causing the * interrupt. * \param count: Count on how many items (such as IO completion) need to * be processed in this context. * \param interruptContext: The thread/process context within which this * function is called. * * tiInterruptContext: this function is called within an * interrupt context. * tiNonInterruptContext: this function is called outside an * interrupt context. * \return None * *****************************************************************************/ FORCEINLINE bit32 tiCOMDelayedInterruptHandler( tiRoot_t *tiRoot, bit32 channelNum, bit32 count, bit32 context ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); agsaRoot_t *agRoot = agNULL; bit32 completed = 0; TDSA_OUT_ENTER(tiRoot); if(context == tiInterruptContext) { agRoot = &(tdsaAllShared->agRootInt); } else { agRoot = &(tdsaAllShared->agRootNonInt); } completed = saDelayedInterruptHandler(agRoot, channelNum, count); if(completed == 0) { TI_DBG3(("tiCOMDelayedInterruptHandler: processedMsgCount zero\n")); } TDSA_OUT_LEAVE(tiRoot); return(completed); } /* tiCOMDelayedInterruptHandler() */ /***************************************************************************** *! \brief tiCOMSystemInterruptsActive * * Purpose: This function is called to indicate whether interrupts are * active or not from this point in time. * * \param tiRoot: Pointer to initiator specific root data structure for * this instance of the driver. * \param sysIntsActive: Boolean value either true or false * * \return None * *****************************************************************************/ osGLOBAL void tiCOMSystemInterruptsActive( tiRoot_t * tiRoot, bit32 sysIntsActive ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); agsaRoot_t *agRoot; agRoot = &(tdsaAllShared->agRootNonInt); #ifdef SPC_POLLINGMODE if(sysIntsActive) return; #endif /* SPC_POLLINGMODE */ tdsaAllShared->flags.sysIntsActive = sysIntsActive; TI_DBG6(("tiCOMSystemInterruptsActive: start\n")); /* enable low level interrupts */ if(agRoot->sdkData != agNULL) { saSystemInterruptsActive( agRoot, (agBOOLEAN) tdsaAllShared->flags.sysIntsActive ); } TI_DBG6(("tiCOMSystemInterruptsActive: end\n")); } /* tiCOMSystemInterruptsActive */ osGLOBAL void tiComCountActiveIORequests( tiRoot_t * tiRoot ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); agsaRoot_t *agRoot; agRoot = &(tdsaAllShared->agRootNonInt); saCountActiveIORequests(agRoot ); } /***************************************************************************** *! \brief tiCOMInterruptEnable * * Purpose: This function is called to enable an interrupts on the specified channel * active or not from this point in time. * * \param tiRoot: Pointer to initiator specific root data structure for * this instance of the driver. * \param : channelNum vector number for MSIX Zero for legacy interrupt * * \return None * *****************************************************************************/ osGLOBAL FORCEINLINE void tiCOMInterruptEnable( tiRoot_t * tiRoot, bit32 channelNum) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&(tdsaRoot->tdsaAllShared); agsaRoot_t *agRoot; agRoot = &(tdsaAllShared->agRootNonInt); saSystemInterruptsEnable(agRoot, channelNum); }