/******************************************************************************* *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 ********************************************************************************/ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef SM_DEBUG bit32 gSMDebugLevel = 1; #endif smRoot_t *gsmRoot = agNULL; /* start smapi defined APIS */ osGLOBAL void smGetRequirements( smRoot_t *smRoot, smSwConfig_t *swConfig, smMemoryRequirement_t *memoryRequirement, bit32 *usecsPerTick, bit32 *maxNumLocks ) { bit32 memoryReqCount = 0; bit32 i; bit32 max_dev = SM_MAX_DEV; char *buffer; bit32 buffLen; bit32 lenRecv = 0; static char tmpBuffer[DEFAULT_KEY_BUFFER_SIZE]; char *pLastUsedChar = agNULL; char globalStr[] = "Global"; char iniParmsStr[] = "InitiatorParms"; SM_DBG2(("smGetRequirements: start\n")); /* sanity check */ SM_ASSERT((agNULL != swConfig), ""); SM_ASSERT((agNULL != memoryRequirement), ""); SM_ASSERT((agNULL != usecsPerTick), ""); SM_ASSERT((agNULL != maxNumLocks), ""); /* memory requirement for smRoot, CACHE memory */ memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].singleElementLength = sizeof(smIntRoot_t); memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].numElements = 1; memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].totalLength = (memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].singleElementLength) * (memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].numElements); memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].alignment = 4; memoryRequirement->smMemory[SM_ROOT_MEM_INDEX].type = SM_CACHED_MEM; memoryReqCount++; /* reading the configurable parameter of MaxTargets */ buffer = tmpBuffer; buffLen = sizeof(tmpBuffer); sm_memset(buffer, 0, buffLen); lenRecv = 0; if ((tdsmGetTransportParam( smRoot, globalStr, iniParmsStr, agNULL, agNULL, agNULL, agNULL, "MaxTargets", buffer, buffLen, &lenRecv ) == SM_RC_SUCCESS) && (lenRecv != 0)) { if (osti_strncmp(buffer, "0x", 2) == 0) { max_dev = osti_strtoul (buffer, &pLastUsedChar, 0); } else { max_dev = osti_strtoul (buffer, &pLastUsedChar, 10); } } SM_DBG3(("smGetRequirements: max_expander %d\n", max_dev)); /* memory requirement for Device Links, CACHE memory */ memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].singleElementLength = sizeof(smDeviceData_t); memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].numElements = max_dev; memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].totalLength = (memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].singleElementLength) * (memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].numElements); memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].alignment = 4; memoryRequirement->smMemory[SM_DEVICE_MEM_INDEX].type = SM_CACHED_MEM; memoryReqCount++; /* memory requirement for IO inks, CACHE memory */ memoryRequirement->smMemory[SM_IO_MEM_INDEX].singleElementLength = sizeof(smIORequestBody_t); memoryRequirement->smMemory[SM_IO_MEM_INDEX].numElements = SM_MAX_IO; memoryRequirement->smMemory[SM_IO_MEM_INDEX].totalLength = (memoryRequirement->smMemory[SM_IO_MEM_INDEX].singleElementLength) * (memoryRequirement->smMemory[SM_IO_MEM_INDEX].numElements); memoryRequirement->smMemory[SM_IO_MEM_INDEX].alignment = 4; memoryRequirement->smMemory[SM_IO_MEM_INDEX].type = SM_CACHED_MEM; memoryReqCount++; /* for debugging */ for (i=0;i< memoryReqCount;i++) { SM_DBG3(("smGetRequirements: index %d numElements %d totalLength %d singleElementLength %d alignment %d\n", i , memoryRequirement->smMemory[i].numElements, memoryRequirement->smMemory[i].totalLength, memoryRequirement->smMemory[i].singleElementLength,memoryRequirement->smMemory[i].alignment )); } /* set up memory requirement count */ memoryRequirement->count = memoryReqCount; /* requirement for locks */ *maxNumLocks = SM_MAX_LOCKS; /* setup the time tick */ *usecsPerTick = SM_USECS_PER_TICK; /* set up the number of active IOs */ swConfig->maxActiveIOs = SM_MAX_IO; /* set up the number of device handles */ swConfig->numDevHandles = SM_MAX_DEV; return; } osGLOBAL bit32 smInitialize( smRoot_t *smRoot, agsaRoot_t *agRoot, smMemoryRequirement_t *memoryAllocated, smSwConfig_t *swConfig, bit32 usecsPerTick ) { smIntRoot_t *smIntRoot; smDeviceData_t *smDevice; smIORequestBody_t *smIORequest; smIntContext_t *smAllShared; bit32 i; bit32 max_dev = SM_MAX_DEV; char *buffer; bit32 buffLen; bit32 lenRecv = 0; static char tmpBuffer[DEFAULT_KEY_BUFFER_SIZE]; char *pLastUsedChar = agNULL; char globalStr[] = "Global"; char iniParmsStr[] = "InitiatorParms"; SM_DBG2(("smInitialize: start\n")); /* sanity check */ SM_ASSERT((agNULL != smRoot), ""); SM_ASSERT((agNULL != agRoot), ""); SM_ASSERT((agNULL != memoryAllocated), ""); SM_ASSERT((agNULL != swConfig), ""); SM_ASSERT((SM_ROOT_MEM_INDEX < memoryAllocated->count), ""); SM_ASSERT((SM_DEVICE_MEM_INDEX < memoryAllocated->count), ""); SM_ASSERT((SM_IO_MEM_INDEX < memoryAllocated->count), ""); /* Check the memory allocated */ for ( i = 0; i < memoryAllocated->count; i ++ ) { /* If memory allocatation failed */ if (memoryAllocated->smMemory[i].singleElementLength && memoryAllocated->smMemory[i].numElements) { if ( (0 != memoryAllocated->smMemory[i].numElements) && (0 == memoryAllocated->smMemory[i].totalLength) ) { /* return failure */ SM_DBG1(("smInitialize: Memory[%d] singleElementLength = 0x%x numElements = 0x%x NOT allocated!!!\n", i, memoryAllocated->smMemory[i].singleElementLength, memoryAllocated->smMemory[i].numElements)); return SM_RC_FAILURE; } } } /* for debugging */ for ( i = 0; i < memoryAllocated->count; i ++ ) { SM_DBG3(("smInitialize: index %d virtPtr %p osHandle%p\n",i, memoryAllocated->smMemory[i].virtPtr, memoryAllocated->smMemory[i].osHandle)); SM_DBG3(("smInitialize: index %d phyAddrUpper 0x%x phyAddrLower 0x%x totalLength %d numElements %d\n", i, memoryAllocated->smMemory[i].physAddrUpper, memoryAllocated->smMemory[i].physAddrLower, memoryAllocated->smMemory[i].totalLength, memoryAllocated->smMemory[i].numElements)); SM_DBG3(("smInitialize: index %d singleElementLength 0x%x alignment 0x%x type %d reserved %d\n", i, memoryAllocated->smMemory[i].singleElementLength, memoryAllocated->smMemory[i].alignment, memoryAllocated->smMemory[i].type, memoryAllocated->smMemory[i].reserved)); } /* SM's internal root */ smIntRoot = (smIntRoot_t *) (memoryAllocated->smMemory[SM_ROOT_MEM_INDEX].virtPtr); smRoot->smData = (void *) smIntRoot; smAllShared = (smIntContext_t *)&(smIntRoot->smAllShared); /**< Initialize the TDM data part of the interrupt context */ smAllShared->smRootOsData.smRoot = smRoot; smAllShared->smRootOsData.smAllShared = (void *) smAllShared; gsmRoot = smRoot; smAllShared->FCA = agTRUE; /* Devices */ smDevice = (smDeviceData_t *) (memoryAllocated->smMemory[SM_DEVICE_MEM_INDEX].virtPtr); smAllShared->DeviceMem = (smDeviceData_t *)smDevice; /* IOs */ smIORequest = (smIORequestBody_t *) (memoryAllocated->smMemory[SM_IO_MEM_INDEX].virtPtr); smAllShared->IOMem = (smIORequestBody_t *)smIORequest; smAllShared->agRoot = agRoot; smAllShared->usecsPerTick = usecsPerTick; /**< initializes timers */ smInitTimers(smRoot); /**< initializes devices */ buffer = tmpBuffer; buffLen = sizeof(tmpBuffer); sm_memset(buffer, 0, buffLen); lenRecv = 0; if ((tdsmGetTransportParam( smRoot, globalStr, iniParmsStr, agNULL, agNULL, agNULL, agNULL, "MaxTargets", buffer, buffLen, &lenRecv ) == SM_RC_SUCCESS) && (lenRecv != 0)) { if (osti_strncmp(buffer, "0x", 2) == 0) { max_dev = osti_strtoul (buffer, &pLastUsedChar, 0); } else { max_dev = osti_strtoul (buffer, &pLastUsedChar, 10); } SM_DBG1(("smInitialize: MaxTargets %d\n", max_dev)); } smDeviceDataInit(smRoot, max_dev); /**< initializes IOs */ smIOInit(smRoot); #ifdef SM_DEBUG gSMDebugLevel = swConfig->SMDebugLevel; #endif return SM_RC_SUCCESS; } osGLOBAL void smInitTimers( smRoot_t *smRoot ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; SM_DBG2(("smInitTimers: start\n")); /* initialize the timerlist */ SMLIST_INIT_HDR(&(smAllShared->timerlist)); return; } osGLOBAL void smDeviceDataReInit( smRoot_t *smRoot, smDeviceData_t *oneDeviceData ) { int j=0; smSatInternalIo_t *satIntIO; SM_DBG2(("smDeviceDataReInit: start \n")); if (oneDeviceData->satPendingIO != 0) { SM_DBG1(("smDeviceDataReInit: did %d\n", oneDeviceData->id)); SM_DBG1(("smDeviceDataReInit: satPendingIO %d satNCQMaxIO %d!!!\n", oneDeviceData->satPendingIO, oneDeviceData->satNCQMaxIO )); SM_DBG1(("smDeviceDataReInit: satPendingNCQIO %d satPendingNONNCQIO %d!!!\n", oneDeviceData->satPendingNCQIO, oneDeviceData->satPendingNONNCQIO)); } // oneDeviceData->smRoot = agNULL; oneDeviceData->agDevHandle = agNULL; oneDeviceData->valid = agFALSE; oneDeviceData->SMAbortAll = agFALSE; oneDeviceData->smDevHandle = agNULL; oneDeviceData->directlyAttached = agFALSE; oneDeviceData->agExpDevHandle = agNULL; oneDeviceData->phyID = 0xFF; oneDeviceData->SMNumOfFCA = 0; /* default */ oneDeviceData->satDriveState = SAT_DEV_STATE_NORMAL; oneDeviceData->satNCQMaxIO =SAT_NCQ_MAX; oneDeviceData->satPendingIO = 0; oneDeviceData->satPendingNCQIO = 0; oneDeviceData->satPendingNONNCQIO = 0; oneDeviceData->IDDeviceValid = agFALSE; oneDeviceData->freeSATAFDMATagBitmap = 0; oneDeviceData->NumOfFCA = 0; oneDeviceData->NumOfIDRetries = 0; oneDeviceData->ID_Retries = 0; oneDeviceData->OSAbortAll = agFALSE; sm_memset(oneDeviceData->satMaxLBA, 0, sizeof(oneDeviceData->satMaxLBA)); sm_memset(&(oneDeviceData->satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); oneDeviceData->satSaDeviceData = oneDeviceData; satIntIO = (smSatInternalIo_t *)&(oneDeviceData->satIntIo[0]); for (j = 0; j < SAT_MAX_INT_IO; j++) { SM_DBG2(("tdsaDeviceDataReInit: in loop of internal io free, id %d\n", satIntIO->id)); smsatFreeIntIoResource(smRoot, oneDeviceData, satIntIO); satIntIO = satIntIO + 1; } return; } osGLOBAL void smDeviceDataInit( smRoot_t *smRoot, bit32 max_dev ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; smDeviceData_t *smDeviceData = (smDeviceData_t *)smAllShared->DeviceMem; int i,j; smSatInternalIo_t *satIntIO; SM_DBG2(("smDeviceDataInit: start \n")); SMLIST_INIT_HDR(&(smAllShared->MainDeviceList)); SMLIST_INIT_HDR(&(smAllShared->FreeDeviceList)); for(i=0;i<(int)max_dev;i++) { SMLIST_INIT_ELEMENT(&(smDeviceData[i].FreeLink)); SMLIST_INIT_ELEMENT(&(smDeviceData[i].MainLink)); smDeviceData[i].id = i; smDeviceData[i].smRoot = agNULL; smDeviceData[i].agDevHandle = agNULL; smDeviceData[i].valid = agFALSE; smDeviceData[i].SMAbortAll = agFALSE; smDeviceData[i].smDevHandle = agNULL; smDeviceData[i].directlyAttached = agFALSE; smDeviceData[i].agExpDevHandle = agNULL; smDeviceData[i].phyID = 0xFF; smDeviceData[i].SMNumOfFCA = 0; SMLIST_INIT_HDR(&(smDeviceData[i].satIoLinkList)); SMLIST_INIT_HDR(&(smDeviceData[i].satFreeIntIoLinkList)); SMLIST_INIT_HDR(&(smDeviceData[i].satActiveIntIoLinkList)); /* default */ smDeviceData[i].satDriveState = SAT_DEV_STATE_NORMAL; smDeviceData[i].satNCQMaxIO =SAT_NCQ_MAX; smDeviceData[i].satPendingIO = 0; smDeviceData[i].satPendingNCQIO = 0; smDeviceData[i].satPendingNONNCQIO = 0; smDeviceData[i].IDDeviceValid = agFALSE; smDeviceData[i].freeSATAFDMATagBitmap = 0; smDeviceData[i].NumOfFCA = 0; smDeviceData[i].NumOfIDRetries = 0; smDeviceData[i].ID_Retries = 0; smDeviceData[i].OSAbortAll = agFALSE; smInitTimerRequest(smRoot, &(smDeviceData[i].SATAIDDeviceTimer)); sm_memset(&(smDeviceData[i].satIdentifyData), 0xFF, sizeof(agsaSATAIdentifyData_t)); sm_memset(smDeviceData[i].satMaxLBA, 0, sizeof(smDeviceData[i].satMaxLBA)); smDeviceData[i].satSaDeviceData = &smDeviceData[i]; #if 1 satIntIO = &smDeviceData[i].satIntIo[0]; for (j = 0; j < SAT_MAX_INT_IO; j++) { SMLIST_INIT_ELEMENT (&satIntIO->satIntIoLink); SMLIST_ENQUEUE_AT_TAIL (&satIntIO->satIntIoLink, &smDeviceData[i].satFreeIntIoLinkList); satIntIO->satOrgSmIORequest = agNULL; satIntIO->id = j; satIntIO = satIntIO + 1; } #endif /* some other variables */ SMLIST_ENQUEUE_AT_TAIL(&(smDeviceData[i].FreeLink), &(smAllShared->FreeDeviceList)); } return; } osGLOBAL void smIOInit( smRoot_t *smRoot ) { smIntRoot_t *smIntRoot = (smIntRoot_t *)smRoot->smData; smIntContext_t *smAllShared = (smIntContext_t *)&smIntRoot->smAllShared; smIORequestBody_t *smIOCommand = (smIORequestBody_t *)smAllShared->IOMem; int i = 0; SM_DBG3(("smIOInit: start\n")); SMLIST_INIT_HDR(&(smAllShared->freeIOList)); SMLIST_INIT_HDR(&(smAllShared->mainIOList)); for(i=0;ifreeIOList)); } return; } FORCEINLINE void smIOReInit( smRoot_t *smRoot, smIORequestBody_t *smIORequestBody ) { SM_DBG3(("smIOReInit: start\n")); smIORequestBody->InUse = agTRUE; smIORequestBody->ioStarted = agFALSE; smIORequestBody->ioCompleted = agFALSE; smIORequestBody->reTries = 0; smIORequestBody->smDevHandle = agNULL; smIORequestBody->smIORequest = agNULL; smIORequestBody->smIOToBeAbortedRequest = agNULL; smIORequestBody->transport.SATA.satIOContext.satOrgIOContext = agNULL; /*sm_memset(&(smIORequestBody->transport.SATA.agSATARequestBody), 0, sizeof(agsaSATAInitiatorRequest_t));*/ return; } /* end smapi defined APIS */