/******************************************************************************* *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 initiator initialization functions * */ #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 /***************************************************************************** *! \brief itdssGetResource * * Purpose: This function is called to determine the Transport * Dependent Layer internal resource requirement for the initiator * side. * * /param tiRoot: Pointer to driver/port instance. * /param initiatorResource: Pointer to initiator functionality memory and * option requirement. * * /return: None * * /note - This function only return the memory requirement in the tiMem_t * structure in initiatorResource. It does not allocated memory, so the * address fields in tiMem_t are not used. * *****************************************************************************/ osGLOBAL void itdssGetResource( tiRoot_t * tiRoot, tiInitiatorResource_t * initiatorResource ) { itdssOperatingOption_t OperatingOption; tiInitiatorMem_t *iniMem; bit32 i; iniMem = &initiatorResource->initiatorMem; iniMem->count = 1; /* Only 1 memory descriptors are used */ TI_DBG6(("itdssGetResource: start\n")); /* other than [0], nothing is used * tdCachedMem[0]: cached mem for initiator TD Layer main functionality : * itdssIni_t * tdCachedMem[1-5]: is availalbe */ /* * Get default parameters from the OS Specific area * and reads parameters from the configuration file */ itdssGetOperatingOptionParams(tiRoot, &OperatingOption); /* * Cached mem for initiator Transport Dependent Layer main functionality */ iniMem->tdCachedMem[0].singleElementLength = sizeof(itdsaIni_t); iniMem->tdCachedMem[0].numElements = 1; iniMem->tdCachedMem[0].totalLength = iniMem->tdCachedMem[0].singleElementLength * iniMem->tdCachedMem[0].numElements; iniMem->tdCachedMem[0].alignment = sizeof (void *); /* 4 bytes */ iniMem->tdCachedMem[0].type = TI_CACHED_MEM; iniMem->tdCachedMem[0].reserved = 0; iniMem->tdCachedMem[0].virtPtr = agNULL; iniMem->tdCachedMem[0].osHandle = agNULL; iniMem->tdCachedMem[0].physAddrUpper = 0; iniMem->tdCachedMem[0].physAddrLower = 0; /* * Not used mem structure. Initialize them. */ for (i = iniMem->count; i < 6; i++) { iniMem->tdCachedMem[i].singleElementLength = 0; iniMem->tdCachedMem[i].numElements = 0; iniMem->tdCachedMem[i].totalLength = 0; iniMem->tdCachedMem[i].alignment = 0; iniMem->tdCachedMem[i].type = TI_CACHED_MEM; iniMem->tdCachedMem[i].reserved = 0; iniMem->tdCachedMem[i].virtPtr = agNULL; iniMem->tdCachedMem[i].osHandle = agNULL; iniMem->tdCachedMem[i].physAddrUpper = 0; iniMem->tdCachedMem[i].physAddrLower = 0; } /* * Operating option of TISA * fills in tiInitiatorOption */ initiatorResource->initiatorOption.usecsPerTick = OperatingOption.UsecsPerTick; /* default value 1 sec*/ initiatorResource->initiatorOption.pageSize = 0; /* initialization */ initiatorResource->initiatorOption.dynamicDmaMem.numElements = 0; initiatorResource->initiatorOption.dynamicDmaMem.singleElementLength = 0; initiatorResource->initiatorOption.dynamicDmaMem.totalLength = 0; initiatorResource->initiatorOption.dynamicDmaMem.alignment = 0; /* initialization */ initiatorResource->initiatorOption.dynamicCachedMem.numElements = 0; initiatorResource->initiatorOption.dynamicCachedMem.singleElementLength = 0; initiatorResource->initiatorOption.dynamicCachedMem.totalLength = 0; initiatorResource->initiatorOption.dynamicCachedMem.alignment = 0; /* This is not used in OS like Linux which supports dynamic memeory allocation In short, this is for Windows, which does not support dynamic memory allocation */ /* ostiallocmemory(..... ,agFALSE) is supported by the following code eg) sat.c The memory is DMA capable(uncached) */ #ifdef CCBUILD_EncryptionDriver /* extend the DMA memory for supporting two encryption DEK tables */ initiatorResource->initiatorOption.dynamicDmaMem.numElements = 128 + DEK_MAX_TABLE_ENTRIES / 2; #else initiatorResource->initiatorOption.dynamicDmaMem.numElements = 128; #endif /* worked initiatorResource->initiatorOption.dynamicDmaMem.singleElementLength = sizeof(tdIORequestBody_t); */ initiatorResource->initiatorOption.dynamicDmaMem.singleElementLength = 512; initiatorResource->initiatorOption.dynamicDmaMem.totalLength = initiatorResource->initiatorOption.dynamicDmaMem.numElements * initiatorResource->initiatorOption.dynamicDmaMem.singleElementLength; initiatorResource->initiatorOption.dynamicDmaMem.alignment = sizeof(void *); /* This is not used in OS like Linux which supports dynamic memeory allocation In short, this is for Windows, which does not support dynamic memory allocation */ /* ostiallocmemory(..... ,agTRUE) is supported by the following code eg) sat.c The memory is DMA incapable(cached) */ initiatorResource->initiatorOption.dynamicCachedMem.numElements = 1024 + 256; /* worked initiatorResource->initiatorOption.dynamicCachedMem.singleElementLength = sizeof(tdIORequestBody_t); initiatorResource->initiatorOption.dynamicCachedMem.singleElementLength = sizeof(tdssSMPRequestBody_t); */ initiatorResource->initiatorOption.dynamicCachedMem.singleElementLength = 512; initiatorResource->initiatorOption.dynamicCachedMem.totalLength = initiatorResource->initiatorOption.dynamicCachedMem.numElements * initiatorResource->initiatorOption.dynamicCachedMem.singleElementLength; initiatorResource->initiatorOption.dynamicCachedMem.alignment = sizeof(void *); /* * set the I/O request body size */ initiatorResource->initiatorOption.ioRequestBodySize = sizeof(tdIORequestBody_t); TI_DBG6(("itdssGetResource: sizeof(tdssSMPRequestBody_t) %d\n", (int)sizeof(tdssSMPRequestBody_t))); TI_DBG6(("itdssGetResource: end\n")); return; } /***************************************************************************** *! \brief itdssGetOperatingOptionParams * * Purpose: This function is called to get default parameters from the * OS Specific area. This function is called in the context of * tiCOMGetResource() and tiCOMInit(). * * * \param tiRoot: Pointer to initiator driver/port instance. * \param option: Pointer to the Transport Dependent options. * * \return: None * * \note - * *****************************************************************************/ osGLOBAL void itdssGetOperatingOptionParams( tiRoot_t *tiRoot, itdssOperatingOption_t *OperatingOption ) { char *key = agNULL; char *subkey1 = agNULL; char *subkey2 = agNULL; char *buffer; bit32 buffLen; bit32 lenRecv = 0; char *pLastUsedChar = agNULL; char tmpBuffer[DEFAULT_KEY_BUFFER_SIZE]; char globalStr[] = "Global"; char iniParmsStr[] = "InitiatorParms"; TI_DBG6(("itdssGetOperatingOptionParams: start\n")); /* first set the values to Default values Then, overwrite them using ostiGetTransportParam() */ /* to remove compiler warnings */ pLastUsedChar = pLastUsedChar; lenRecv = lenRecv; subkey2 = subkey2; subkey1 = subkey1; key = key; buffer = &tmpBuffer[0]; buffLen = sizeof (tmpBuffer); osti_memset(buffer, 0, buffLen); /* default values */ OperatingOption->MaxTargets = DEFAULT_MAX_DEV; /* DEFAULT_MAX_TARGETS; */ /* 256 */ OperatingOption->UsecsPerTick = DEFAULT_INI_TIMER_TICK; /* 1 sec */ osti_memset(buffer, 0, buffLen); lenRecv = 0; /* defaults are overwritten in the following */ /* Get MaxTargets */ if ((ostiGetTransportParam( tiRoot, globalStr, iniParmsStr, agNULL, agNULL, agNULL, agNULL, "MaxTargets", buffer, buffLen, &lenRecv ) == tiSuccess) && (lenRecv != 0)) { if (osti_strncmp(buffer, "0x", 2) == 0) { OperatingOption->MaxTargets = osti_strtoul (buffer, &pLastUsedChar, 0); } else { OperatingOption->MaxTargets = osti_strtoul (buffer, &pLastUsedChar, 10); } TI_DBG2(("itdssGetOperatingOptionParams: MaxTargets %d\n", OperatingOption->MaxTargets )); } #ifdef REMOVED /* get UsecsPerTick */ if ((ostiGetTransportParam( tiRoot, globalStr, iniParmsStr, agNULL, agNULL, agNULL, agNULL, "UsecsPerTick", buffer, buffLen, &lenRecv ) == tiSuccess) && (lenRecv != 0)) { if (osti_strncmp(buffer, "0x", 2) == 0) { OperatingOption->UsecsPerTick = osti_strtoul (buffer, &pLastUsedChar, 0); } else { OperatingOption->UsecsPerTick = osti_strtoul (buffer, &pLastUsedChar, 10); } } osti_memset(buffer, 0, buffLen); lenRecv = 0; #endif return; } /***************************************************************************** *! \brief itdssInit * * Purpose: This function is called to initialize the initiator specific * Transport Dependent Layer. * This function is not directly called by OS Specific module, * as it is internally called by tiCOMInit(). * * /param tiRoot: Pointer to driver/port instance. * /param initiatorResource: Pointer to initiator functionality memory * and option requirement. * /param tdSharedMem: Pointer to cached memory required by the * target/initiator shared functionality. * * /return: * tiSuccess OK * others not OK * * /note - * *****************************************************************************/ osGLOBAL bit32 itdssInit( tiRoot_t *tiRoot, tiInitiatorResource_t *initiatorResource, tiTdSharedMem_t *tdSharedMem ) { tiInitiatorMem_t *iniMem; itdsaIni_t *Initiator; itdssOperatingOption_t *OperatingOption; tdsaRoot_t *tdsaRoot; TI_DBG6(("itdssInit: start\n")); iniMem = &initiatorResource->initiatorMem; tdsaRoot = (tdsaRoot_t *)tiRoot->tdData; /* * Cached mem for initiator Transport Dependent Layer main functionality */ Initiator = iniMem->tdCachedMem[0].virtPtr; /* * Get default parameters from the OS Specific area */ OperatingOption = &Initiator->OperatingOption; /* * Get default parameters from the OS Specific area * and reads parameters from the configuration file */ itdssGetOperatingOptionParams(tiRoot, OperatingOption); /* * Update TD operating options with OS-layer-saved value * Only UsecsPerTick is updated */ OperatingOption->UsecsPerTick = initiatorResource->initiatorOption.usecsPerTick; Initiator->NumIOsActive = 0; /* * tdCachedMem[0]: cached mem for initiator TD Layer main functionality : * itdssIni_t * tdCachedMem[1-5]: not in use */ /* initialize the timerlist */ itdssInitTimers(tiRoot); /* Initialize the tdsaAllShared, tdssSASShared pointers */ Initiator->tdsaAllShared = &(tdsaRoot->tdsaAllShared); TI_DBG6(("itdssInit: end\n")); return (tiSuccess); } /***************************************************************************** *! \brief * itdssInitTimers * * Purpose: This function is called to initialize the timers * for initiator * * \param tiRoot: pointer to the driver instance * * \return: None * * \note - * *****************************************************************************/ osGLOBAL void itdssInitTimers( tiRoot_t *tiRoot ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *)(tiRoot->tdData); tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni; /* initialize the timerlist */ TDLIST_INIT_HDR(&(Initiator->timerlist)); return; }