/******************************************************************************* *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 Management IOCTL APIs * */ #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 #include #ifdef INITIATOR_DRIVER #include #include #include #endif #ifdef TARGET_DRIVER #include #include #include #endif #include #include #include #include #include #include #include #include #define agFieldOffset(baseType,fieldName) \ /*lint -e545 */ \ ((bit32)((bitptr)(&(((baseType *)0)->fieldName)))) \ #ifdef SA_LL_API_TEST osGLOBAL bit32 tdLlApiTestIoctl(tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3); #endif /* SA_LL_API_TEST */ extern bit32 volatile sgpioResponseSet; #ifdef SPC_ENABLE_PROFILE /***************************************************************************** * * tdipFWProfileIoctl * * Purpose: This routine is called to process the FW Profile IOCTL function. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdipFWProfileIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { bit32 status = IOCTL_CALL_SUCCESS; bit32 bufAddrUpper = 0; bit32 bufAddrLower = 0; tdFWProfile_t *fwProfile; void *osMemHandle = agNULL; void *buffer = agNULL; agsaFwProfile_t fwProfileInfo = {0}; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &tdsaAllShared->agRootInt; fwProfile = (tdFWProfile_t *)&agIOCTLPayload->FunctionSpecificArea[0]; fwProfileInfo.processor = fwProfile->processor; fwProfileInfo.cmd = fwProfile->cmd; fwProfileInfo.len = fwProfile->len; fwProfileInfo.tcid = fwProfile->tcid; if(fwProfile->cmd == START_CODE_PROFILE) { fwProfileInfo.codeStartAdd = fwProfile->codeStartAdd; fwProfileInfo.codeEndAdd = fwProfile->codeEndAdd; } if((fwProfile->cmd == STOP_TIMER_PROFILE) || (fwProfile->cmd == STOP_CODE_PROFILE)) { if(fwProfile->len != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &bufAddrUpper, &bufAddrLower, 8, fwProfile->len, agFALSE)) { return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, fwProfile->len); } fwProfileInfo.agSgl.sgLower = bufAddrLower; fwProfileInfo.agSgl.sgUpper = bufAddrUpper; fwProfileInfo.agSgl.len = fwProfile->len; fwProfileInfo.agSgl.extReserved = 0; tdsaAllShared->tdFWProfileEx.buffer = osMemHandle; tdsaAllShared->tdFWProfileEx.virtAddr = buffer; tdsaAllShared->tdFWProfileEx.len = fwProfile->len; } tdsaAllShared->tdFWProfileEx.tdFWProfile = fwProfile; tdsaAllShared->tdFWProfileEx.param1 = agParam1; tdsaAllShared->tdFWProfileEx.param2 = agParam2; tdsaAllShared->tdFWProfileEx.payload = agIOCTLPayload; tdsaAllShared->tdFWProfileEx.inProgress = 1; status = saFwProfile(agRoot, agNULL, 0, &fwProfileInfo ); if(status) { if((fwProfile->cmd == STOP_TIMER_PROFILE) || (fwProfile->cmd == STOP_CODE_PROFILE)) ostiFreeMemory(tiRoot, osMemHandle, fwProfile->len); status = IOCTL_CALL_FAIL; } else status = IOCTL_CALL_PENDING; return status; } #endif /***************************************************************************** * * tdipFWControlIoctl * * Purpose: This routine is called to process the FW control IOCTL function. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdipFWControlIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { bit32 status = IOCTL_CALL_PENDING; bit32 bufAddrUpper = 0; bit32 bufAddrLower = 0; tdFWControl_t *fwControl; void *osMemHandle = agNULL; void *buffer = agNULL; agsaUpdateFwFlash_t flashUpdateInfo; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &tdsaAllShared->agRootInt; if( agIOCTLPayload->Length < ( agFieldOffset(tiIOCTLPayload_t, FunctionSpecificArea) + sizeof(tdFWControl_t) ) ) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; status = IOCTL_CALL_FAIL; return status; } fwControl = (tdFWControl_t *)&agIOCTLPayload->FunctionSpecificArea[0]; if(fwControl->len != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &bufAddrUpper, &bufAddrLower, 8, fwControl->len, agFALSE) ) return IOCTL_CALL_FAIL; } osti_memset( (void *)buffer, 0, fwControl->len ); osti_memcpy( (void *)buffer, fwControl->buffer, fwControl->len ); flashUpdateInfo.agSgl.sgLower = bufAddrLower; flashUpdateInfo.agSgl.sgUpper = bufAddrUpper; flashUpdateInfo.agSgl.len = fwControl->len; flashUpdateInfo.agSgl.extReserved = 0; flashUpdateInfo.currentImageOffset = fwControl->offset; flashUpdateInfo.currentImageLen = fwControl->len; flashUpdateInfo.totalImageLen = fwControl->size; switch (agIOCTLPayload->MinorFunction) { case IOCTL_MN_FW_DOWNLOAD_DATA: { TI_DBG6(("tdipFWControlIoctl: calling saFwFlashUpdate\n")); tdsaAllShared->tdFWControlEx.tdFWControl = fwControl; tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = saFwFlashUpdate( agRoot, agNULL, 0, &flashUpdateInfo ); if(status) { status = IOCTL_CALL_FAIL; fwControl->retcode = IOCTL_CALL_TIMEOUT; } else { status = IOCTL_CALL_PENDING; } break; } default: status = IOCTL_CALL_INVALID_CODE; TI_DBG1( ("tdipFWControlIoctl: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction) ); ostiFreeMemory(tiRoot, osMemHandle, fwControl->len); return status; } /* end IOCTL switch */ return status; } /* tdipFWControlIoctl */ /***************************************************************************** * * tiCOMMgntIOCTL * * Purpose: This routine is a TISA API for processing the PMC specific * IOCTL function. * * Each IOCTL function is identified by the IOCTL header * specified in the data payload as the following: * Field Description * ----- ----------- * Signature PMC IOCTL signature. * #define PMC_IOCTL_SIGNATURE 0x1234 * MajorFunction Major function number. * MinorFunction Minor function number. * Length Length of this structure in bytes. * Status Return status for this IOCTL function. * FunctionSpecificArea Variable length function specific area. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * IOCTL_CALL_INVALID_DEVICE Invalid target or destination device. * * Note: * Used ostiAllocMemory() OS layer callback function to allocate memory * for DMA operaion. Then use ostiFreeMemory() to deallocate the memory. * *****************************************************************************/ osGLOBAL bit32 tiCOMMgntIOCTL( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { bit32 status = IOCTL_CALL_INVALID_CODE; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootNonInt); bit32 EventLogLength = 0; bit32 EventLogOption; bit32 ReadLength = 0; bit32 Offset = 0; bit32 RequestLength = 0; /* user request on how much data to pass to application */ agsaContext_t *agContext = NULL; bit8 *loc = 0; TI_DBG3(("tiCOMMgntIOCTL: start\n")); TI_DBG3(("tiCOMMgntIOCTL: tiRoot %p agIOCTLPayload %p agParam1 %p agParam2 %p agParam3 %p\n", tiRoot,agIOCTLPayload,agParam1,agParam2,agParam3 )); TI_DBG3(("tiCOMMgntIOCTL: Signature %X\ntiCOMMgntIOCTL: MajorFunction 0x%X\ntiCOMMgntIOCTL: MinorFunction 0x%X\ntiCOMMgntIOCTL: Length 0x%X\ntiCOMMgntIOCTL: Status 0x%X\ntiCOMMgntIOCTL: Reserved 0x%X\ntiCOMMgntIOCTL: FunctionSpecificArea 0x%X\n", agIOCTLPayload->Signature, agIOCTLPayload->MajorFunction, agIOCTLPayload->MinorFunction, agIOCTLPayload->Length, agIOCTLPayload->Status, agIOCTLPayload->Reserved, agIOCTLPayload->FunctionSpecificArea[0] )); /* PMC IOCTL signatures matched ? */ if(agIOCTLPayload->Signature != PMC_IOCTL_SIGNATURE) { TI_DBG1(("tiCOMMgntIOCTL:agIOCTLPayload->Signature %x IOCTL_CALL_INVALID_CODE\n",agIOCTLPayload->Signature )); status = IOCTL_CALL_INVALID_CODE; return (status); } switch (agIOCTLPayload->MajorFunction) { //TODO: make the card identification more robust. For now - just to keep going with FW download #ifdef IOCTL_INTERRUPT_TIME_CONFIG case IOCTL_MJ_CARD_PARAMETER: { switch( agIOCTLPayload->MinorFunction ) { case IOCTL_MN_CARD_GET_INTERRUPT_CONFIG: { agsaInterruptConfigPage_t *pInterruptConfig = (agsaInterruptConfigPage_t *)&agIOCTLPayload->FunctionSpecificArea[0]; status = saGetControllerConfig(agRoot, 0, AGSA_INTERRUPT_CONFIGURATION_PAGE, pInterruptConfig->vectorMask0, pInterruptConfig->vectorMask1, agParam2); if(status == AGSA_RC_SUCCESS) { status = IOCTL_CALL_PENDING; agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } break; } case IOCTL_MN_CARD_GET_TIMER_CONFIG: status = saGetControllerConfig(agRoot, 0, AGSA_SAS_PROTOCOL_TIMER_CONFIG_PAGE, 0, 0, agParam2); if(status == AGSA_RC_SUCCESS) { status = IOCTL_CALL_PENDING; agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } break; } break; } #endif /* IOCTL_INTERRUPT_TIME_CONFIG */ case IOCTL_MJ_INI_DRIVER_IDENTIFY: { status=IOCTL_CALL_SUCCESS; break; } case IOCTL_MJ_GET_DEVICE_LUN: status = tdsaGetNumOfLUNIOCTL(tiRoot,agIOCTLPayload, agParam1, agParam2, agParam3); if(status == IOCTL_CALL_SUCCESS) { status = IOCTL_CALL_PENDING; } break; case IOCTL_MJ_SMP_REQUEST: status = tdsaSendSMPIoctl(tiRoot, agIOCTLPayload, agParam1,agParam2,agParam3); break; case IOCTL_MJ_FW_CONTROL: { //ostiIOCTLClearSignal (tiRoot, &agParam1, &agParam2, &agParam3); status = tdipFWControlIoctl( tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } //#ifdef EVENT_LOG_INFO_TESTING /* Reserved field in tiIOCTLPayload_t is used as offset */ case IOCTL_MJ_GET_EVENT_LOG1: { switch (agIOCTLPayload->MinorFunction) { case IOCTL_MN_FW_GET_TRACE_BUFFER: { agsaControllerEventLog_t EventLog; saGetControllerEventLogInfo(agRoot, &EventLog); TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GET_EVENT_LOG1 Length %d\n", agIOCTLPayload->Length)); RequestLength = agIOCTLPayload->Length; Offset = agIOCTLPayload->Reserved; EventLogLength = EventLog.eventLog1.totalLength; EventLogOption = EventLog.eventLog1Option; if (EventLogLength <= Offset) { TI_DBG1(("tiCOMMgntIOCTL: 1 out of range Requestlength %d Offset %d event log length %d\n", RequestLength, Offset, EventLogLength)); // out of range agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; if(EventLogOption == 0) { agIOCTLPayload->Status = IOCTL_ERR_FW_EVENTLOG_DISABLED; } status=IOCTL_CALL_SUCCESS; return status; } ReadLength = MIN(EventLogLength - Offset, RequestLength); loc = (bit8 *)EventLog.eventLog1.virtPtr + Offset; osti_memcpy(&(agIOCTLPayload->FunctionSpecificArea), loc, ReadLength); // tdhexdump("IOCTL_MJ_GET_EVENT_LOG1 first 32bytes", (bit8 *)&(agIOCTLPayload->FunctionSpecificArea), 32); agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; agIOCTLPayload->Length = (bit16)ReadLength; status=IOCTL_CALL_SUCCESS; break; } case IOCTL_MN_FW_GET_EVENT_FLASH_LOG1: { TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MN_FW_GET_EVENT_FLASH_LOG1\n")); status = tdsaRegDumpGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } } break; } case IOCTL_MJ_GET_EVENT_LOG2: { switch (agIOCTLPayload->MinorFunction) { case IOCTL_MN_FW_GET_TRACE_BUFFER: { agsaControllerEventLog_t EventLog; saGetControllerEventLogInfo(agRoot, &EventLog); TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GET_EVENT_LOG2 Length %d\n", agIOCTLPayload->Length)); RequestLength = agIOCTLPayload->Length; Offset = agIOCTLPayload->Reserved; EventLogLength = EventLog.eventLog2.totalLength; EventLogOption = EventLog.eventLog2Option; if (EventLogLength <= Offset) { TI_DBG1(("tiCOMMgntIOCTL: 2 out of range Requestlength %d Offset %d event log length %d\n", RequestLength, Offset, EventLogLength)); /* out of range */ agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; if(EventLogOption == 0) { agIOCTLPayload->Status = IOCTL_ERR_FW_EVENTLOG_DISABLED; } status=IOCTL_CALL_SUCCESS; return status; } ReadLength = MIN(EventLogLength - Offset, RequestLength); loc = (bit8 *)EventLog.eventLog2.virtPtr + Offset; osti_memcpy(&(agIOCTLPayload->FunctionSpecificArea), loc, ReadLength); // tdhexdump("IOCTL_MJ_GET_EVENT_LOG2 first 32bytes", (bit8 *)&(agIOCTLPayload->FunctionSpecificArea), 32); agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; agIOCTLPayload->Length = (bit16)ReadLength; status=IOCTL_CALL_SUCCESS; break; } case IOCTL_MN_FW_GET_EVENT_FLASH_LOG2: { TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MN_FW_GET_EVENT_FLASH_LOG2\n")); status = tdsaRegDumpGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } } break; } case IOCTL_MJ_FW_INFO: { agsaControllerInfo_t ControllerInfo; saGetControllerInfo(agRoot, &ControllerInfo); TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_FW_INFO Length %d\n", agIOCTLPayload->Length)); RequestLength = agIOCTLPayload->Length; Offset = agIOCTLPayload->Reserved; if (RequestLength == 0) { TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_FW_INFO: No more Data!\n")); /* out of range */ agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; status=IOCTL_CALL_SUCCESS; return status; } osti_memcpy((bit8*)&(agIOCTLPayload->FunctionSpecificArea), (bit8*)&ControllerInfo, sizeof(agsaControllerInfo_t)); TI_DBG1(("tiCOMMgntIOCTL:IOCTL_MJ_FW_INFO ControllerInfo signature 0x%X\n",ControllerInfo.signature)); TI_DBG1(("tiCOMMgntIOCTL:IOCTL_MJ_FW_INFO ControllerInfo PCILinkRate 0x%X\n",ControllerInfo.PCILinkRate)); TI_DBG1(("tiCOMMgntIOCTL:IOCTL_MJ_FW_INFO ControllerInfo PCIWidth 0x%X\n",ControllerInfo.PCIWidth)); agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status=IOCTL_CALL_SUCCESS; break; } case IOCTL_MJ_GET_FW_REV: { agsaControllerInfo_t ControllerInfo; saGetControllerInfo(agRoot, &ControllerInfo); TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_FW_REV Length %d\n", agIOCTLPayload->Length)); RequestLength = agIOCTLPayload->Length; Offset = agIOCTLPayload->Reserved; if (RequestLength == 0) { TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_GET_FW_REV: No more Data!\n")); /* out of range */ agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; status=IOCTL_CALL_SUCCESS; return status; } osti_memcpy((bit8*)&(agIOCTLPayload->FunctionSpecificArea), (bit8*)&ControllerInfo.fwRevision, sizeof(bit32)); loc = (bit8 *)&(agIOCTLPayload->FunctionSpecificArea)+ sizeof(bit32); osti_memcpy(loc, (bit8*)&ControllerInfo.sdkRevision, sizeof(bit32)); agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status=IOCTL_CALL_SUCCESS; break; } #ifdef SPC_ENABLE_PROFILE case IOCTL_MJ_FW_PROFILE: { TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_FW_PROFILE\n")); status = tdipFWProfileIoctl( tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } #endif /* SPC_ENABLE_PROFILE */ case IOCTL_MJ_GET_CORE_DUMP: { TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GET_CORE_DUMP\n")); if (tiIS_SPC(agRoot)) { status = tdsaRegDumpGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED; status = IOCTL_CALL_SUCCESS; } break; } //#endif case IOCTL_MJ_NVMD_SET: { bit8 nvmDev; TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_NVMD_SET\n")); nvmDev = (bit8) agIOCTLPayload->Status; agIOCTLPayload->Status = 0; status = tdsaNVMDSetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, &nvmDev); break; } #if 0 case IOCTL_MJ_GPIO: { bit32 sVid =0; TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_GPIO\n")); /* Get Subsystem vendor */ sVid = ostiChipConfigReadBit32(tiRoot,0x2C); sVid = sVid & 0xFFFF; /* GPIO is only intended for chip down design * therefore it's only applies to 8H/SPCv product family */ if(sVid == 0x9005) return IOCTL_CALL_INVALID_DEVICE; status = tdsaGpioSetup(tiRoot, agContext, agIOCTLPayload, agParam1, agParam2); if(status == IOCTL_CALL_SUCCESS) status = IOCTL_CALL_PENDING; /* Wait for response from the Controller */ else return status; break; } #endif case IOCTL_MJ_SGPIO: { TI_DBG6(("tiCOMMgntIOCTL: IOCTL_MJ_SGPIO\n")); status = tdsaSGpioIoctlSetup(tiRoot, agContext, agIOCTLPayload, agParam1, agParam2); break; } case IOCTL_MJ_NVMD_GET: { bit8 nvmDev; TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_NVMD_GET\n")); nvmDev = (bit8) agIOCTLPayload->Status; agIOCTLPayload->Status = 0; status = tdsaNVMDGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, &nvmDev); break; } case IOCTL_MJ_GET_FORENSIC_DATA: { TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_FORENSIC_DATA\n")); status = tdsaForensicDataGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } case IOCTL_MJ_GET_DEVICE_INFO: { TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_DEVICE_INFO\n")); status = tdsaDeviceInfoGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } case IOCTL_MJ_GET_IO_ERROR_STATISTIC: { TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_IO_ERROR_STATISTIC\n")); status = tdsaIoErrorStatisticGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } case IOCTL_MJ_GET_IO_EVENT_STATISTIC: { TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_GET_IO_EVENT_STATISTIC\n")); status = tdsaIoEventStatisticGetIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } case IOCTL_MJ_SEND_BIST: { TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_SEND_BIST\n")); status = tdsaSendBISTIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } #if 0 case IOCTL_MJ_SET_OR_GET_REGISTER: { TI_DBG3(("tiCOMMgntIOCTL: IOCTL_MJ_SET_OR_GET_REGISTER\n")); status = tdsaRegisterIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } #endif case IOCTL_MJ_PHY_DETAILS: { PhyDetails_t *PhyDetails = (PhyDetails_t*)&agIOCTLPayload->FunctionSpecificArea; agsaRoot_t *agRoot = &(tdsaAllShared->agRootNonInt); agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); bit8 *sasAddressHi; bit8 *sasAddressLo; bit8 sas_dev_type; int i = 0; tiIniGetDirectSataSasAddr(tiRoot, i , &sasAddressHi, &sasAddressLo); for( i = 0; i < saRoot->phyCount ; i++) { PhyDetails[i].attached_phy = saRoot->phys[i].sasIdentify.phyIdentifier; /* deice types * SAS * 0x01 - Sas end device * 0x02 - Expander device * SATA * 0x11 - Sata * NO DEVICE 0x00 */ sas_dev_type = (saRoot->phys[i].sasIdentify.deviceType_addressFrameType & 0x70 ) >> 4 ; if ((saRoot->phys[i].status == 1) && (sas_dev_type == 0)){ //status 1 - Phy Up //Sata phy PhyDetails[i].attached_dev_type = SAS_PHY_SATA_DEVICE;//0x11 for sata end device osti_memcpy(&PhyDetails[i].attached_sasAddressHi, tdsaAllShared->Ports[i].SASID.sasAddressHi, sizeof(bit32)); osti_memcpy(&PhyDetails[i].attached_sasAddressLo, tdsaAllShared->Ports[i].SASID.sasAddressLo, sizeof(bit32)); PhyDetails[i].attached_sasAddressLo[3] += i + 16; } else { PhyDetails[i].attached_dev_type = sas_dev_type; osti_memcpy(&PhyDetails[i].attached_sasAddressHi, saRoot->phys[i].sasIdentify.sasAddressHi, sizeof(bit32)); osti_memcpy(&PhyDetails[i].attached_sasAddressLo, saRoot->phys[i].sasIdentify.sasAddressLo, sizeof(bit32)); } osti_memcpy(&PhyDetails[i].sasAddressLo,&(tdsaAllShared->Ports[i].SASID.sasAddressLo), sizeof(bit32)); osti_memcpy(&PhyDetails[i].sasAddressHi,&(tdsaAllShared->Ports[i].SASID.sasAddressHi), sizeof(bit32)); } // osti_memcpy(&agIoctlPayload->FunctionSpecificArea,&PhyInfo, sizeof(agsaSGpioReqResponse_t)); // printk("Ioctl success\n"); return IOCTL_CALL_SUCCESS; } case IOCTL_MJ_PHY_GENERAL_STATUS: { agsaPhyGeneralState_t *PhyData=NULL; bit32 ret = AGSA_RC_FAILURE; PhyData = (agsaPhyGeneralState_t*) &agIOCTLPayload->FunctionSpecificArea[0]; PhyData->Reserved2 = 0; /* Validate the length */ if (agIOCTLPayload->Length < sizeof(agsaPhyGeneralState_t)) { status = IOCTL_CALL_FAIL; break; } tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; //tdsaAllShared->tdFWControlEx.usrAddr = PhyData; ret = tdsaGetPhyGeneralStatusIoctl(tiRoot,PhyData); if(ret == AGSA_RC_FAILURE) { status = IOCTL_CALL_FAIL; tdsaAllShared->tdFWControlEx.payload = NULL; tdsaAllShared->tdFWControlEx.inProgress = 0; break; } else if(ret == IOCTL_ERR_STATUS_NOT_SUPPORTED) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED; status = IOCTL_CALL_SUCCESS; break; } //status = IOCTL_CALL_PENDING; status = IOCTL_CALL_PENDING; } break; #if 1 case IOCTL_MJ_GET_PHY_PROFILE: { TI_DBG1(("tiCOMMgntIOCTL: IOCTL_MJ_GET_PHY_PROFILE %p %p %p\n",agParam1,agParam2,agParam3)); status = tdsaPhyProfileIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, agParam3); break; } #endif case IOCTL_MJ_LL_TRACING: { void * stu = &agIOCTLPayload->FunctionSpecificArea[0]; switch(agIOCTLPayload->MinorFunction) { case IOCTL_MN_LL_RESET_TRACE_INDEX: { #ifdef SA_ENABLE_TRACE_FUNCTIONS TSTMTID_TRACE_BUFFER_RESET *llist = (TSTMTID_TRACE_BUFFER_RESET *)stu; hpTraceBufferParms_t BufferParms; TI_DBG5(("tdReturnIOCTL_Info: hpIOCTL_ResetTraceIndex\n")); BufferParms.TraceCompiled = 0; BufferParms.TraceWrap = 0; BufferParms.CurrentTraceIndexWrapCount = 0; BufferParms.BufferSize = 0; BufferParms.CurrentIndex = 0; BufferParms.pTrace = NULL; BufferParms.pTraceIndexWrapCount = NULL; BufferParms.pTraceMask = NULL; BufferParms.pCurrentTraceIndex = NULL; smTraceGetInfo(agRoot,&BufferParms); TI_DBG5(("tdReturnIOCTL_Info: pTrace %p\n",BufferParms.pTrace)); TI_DBG5(("tdReturnIOCTL_Info: pCurrentTraceIndex %p %X\n",BufferParms.pCurrentTraceIndex,*BufferParms.pCurrentTraceIndex)); TI_DBG5(("tdReturnIOCTL_Info: pTraceIndexWrapCount %p %X\n",BufferParms.pTraceIndexWrapCount,*BufferParms.pTraceIndexWrapCount)); TI_DBG5(("tdReturnIOCTL_Info: pTraceMask %p %X\n",BufferParms.pTraceMask,*BufferParms.pTraceMask)); if( llist->Flag != 0) { if( llist->TraceMask != *BufferParms.pTraceMask) { smTraceSetMask(agRoot, llist->TraceMask ); } } if( llist->Reset) { *BufferParms.pCurrentTraceIndex = 0; smResetTraceBuffer(agRoot); *BufferParms.pCurrentTraceIndex = 0; *BufferParms.pTraceIndexWrapCount =0; llist->TraceMask = *BufferParms.pTraceMask; } #endif /* SA_ENABLE_TRACE_FUNCTIONS */ agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status = IOCTL_CALL_SUCCESS; } break; case IOCTL_MN_LL_GET_TRACE_BUFFER_INFO: { hpTraceBufferParms_t BufferParms; TSTMTID_TRACE_BUFFER_INFO *llist = (TSTMTID_TRACE_BUFFER_INFO *)stu; TI_DBG5(("tdReturnIOCTL_Info: hpIOCTL_GetTraceBufferInfo\n")); BufferParms.TraceCompiled = 0; BufferParms.TraceWrap = 0; BufferParms.CurrentTraceIndexWrapCount = 0; BufferParms.BufferSize = 0; BufferParms.CurrentIndex = 0; BufferParms.pTrace = NULL; BufferParms.pTraceMask = NULL; #ifdef SA_ENABLE_TRACE_FUNCTIONS smTraceGetInfo(agRoot,&BufferParms); #endif /* SA_ENABLE_TRACE_FUNCTIONS not enabled */ llist->TraceCompiled = BufferParms.TraceCompiled; llist->BufferSize = BufferParms.BufferSize; llist->CurrentIndex = BufferParms.CurrentIndex ; llist->CurrentTraceIndexWrapCount = BufferParms.CurrentTraceIndexWrapCount; llist->TraceWrap = BufferParms.TraceWrap; if(BufferParms.pTraceMask != NULL) { llist->TraceMask = *BufferParms.pTraceMask; } agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status = IOCTL_CALL_SUCCESS; } break; case IOCTL_MN_LL_GET_TRACE_BUFFER: { #ifdef SA_ENABLE_TRACE_FUNCTIONS TSTMTID_TRACE_BUFFER_FETCH *llist = (TSTMTID_TRACE_BUFFER_FETCH *)stu; hpTraceBufferParms_t BufferParms; bit32 c= 0; BufferParms.TraceCompiled = 0; BufferParms.TraceWrap = 0; BufferParms.CurrentTraceIndexWrapCount = 0; BufferParms.BufferSize = 0; BufferParms.CurrentIndex = 0; BufferParms.pTrace = NULL; smTraceGetInfo(agRoot,&BufferParms); TI_DBG6(("tdReturnIOCTL_Info: hpIOCTL_GetTraceBuffer\n")); if(llist->LowFence != LowFence32Bits) { break; } if(llist->HighFence != HighFence32Bits) { break; } if(llist->BufferOffsetBegin + FetchBufferSIZE > BufferParms.BufferSize ) { } for ( c=0; c < FetchBufferSIZE;c++) { llist->Data[c] = *(BufferParms.pTrace+( c + llist->BufferOffsetBegin)); } #endif /* SA_ENABLE_TRACE_FUNCTIONS not enabled */ } agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status = IOCTL_CALL_SUCCESS; break; } break; } #ifdef SA_LL_API_TEST case IOCTL_MJ_LL_API_TEST: { status = tdLlApiTestIoctl( tiRoot, agIOCTLPayload, agParam1,agParam2,agParam3 ); break; } #endif /* SA_LL_API_TEST */ case IOCTL_MJ_MODE_CTL_PAGE: { /* The SPCv controller has some options accessed via mode pages */ tiEncryptDekConfigPage_t *pModePage= (tiEncryptDekConfigPage_t *) &agIOCTLPayload->FunctionSpecificArea[0]; bit32 pageLength = 0; bit32 pageCode; bit32 modeOperation; pageCode = pModePage->pageCode & 0xFF; modeOperation = *(bit32 *) agParam2; switch(modeOperation) { case tiModePageSet: switch (pageCode) { case TI_ENCRYPTION_DEK_CONFIG_PAGE: pageLength = sizeof(tiEncryptDekConfigPage_t); break; case TI_ENCRYPTION_CONTROL_PARM_PAGE: pageLength = sizeof(tiEncryptControlParamPage_t); break; case TI_ENCRYPTION_GENERAL_CONFIG_PAGE: /* Pages are currently unsupported */ pageLength = 0; break; } status = saSetControllerConfig(agRoot, 0, pageCode, pageLength, pModePage, (agsaContext_t *)agIOCTLPayload); break; case tiModePageGet: status = saGetControllerConfig(agRoot, 0, pageCode, 0, 0, (agsaContext_t *)agIOCTLPayload); break; default: agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED; } } break; #ifdef PHY_RESTART_TEST case IOCTL_MJ_PORT_START: { bit32 portID, tiStatus; bit32 *data = (bit32*) &agIOCTLPayload->FunctionSpecificArea[0]; portID = *data; tiStatus = tiCOMPortStart(tiRoot, portID, tdsaAllShared->Ports[portID].tiPortalContext, 0); if (tiStatus == tiSuccess) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } status = IOCTL_CALL_SUCCESS; break; } case IOCTL_MJ_PORT_STOP: { bit32 portID, tiStatus; bit32 *data = (bit32*) &agIOCTLPayload->FunctionSpecificArea[0]; portID = *data; tiStatus = tiCOMPortStop(tiRoot, tdsaAllShared->Ports[portID].tiPortalContext); if (tiStatus == tiSuccess) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } status = IOCTL_CALL_SUCCESS; break; } #endif case IOCTL_MJ_SEND_TMF: switch(agIOCTLPayload->MinorFunction) { case IOCTL_MN_TMF_DEVICE_RESET: status = tdsaSendTMFIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, AG_TARGET_WARM_RESET); break; case IOCTL_MN_TMF_LUN_RESET: status = tdsaSendTMFIoctl(tiRoot, agIOCTLPayload, agParam1, agParam2, AG_LOGICAL_UNIT_RESET); break; } break; case IOCTL_MJ_GET_DRIVER_VERSION: osti_sprintf(agIOCTLPayload->FunctionSpecificArea, "%s", AGTIAPI_DRIVER_VERSION); agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status=IOCTL_CALL_SUCCESS; break; default: agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_SUPPORTED; break; } return status; } #if 0 /***************************************************************************** * * tdsaGpioSetup * * Purpose: This routine is called to set Gpio parameters to the controller. * * Parameters: * tiRoot: Pointer to driver instance * agsaContext_t : * tiIOCTLPayload_t : ioctl header with payload gpio info * agParam1,agParam2 : Generic parameters * * Return: status * * *****************************************************************************/ osGLOBAL bit32 tdsaGpioSetup( tiRoot_t *tiRoot, agsaContext_t *agContext, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2 ) { tdsaTimerRequest_t *osIoctlTimer; agsaGpioEventSetupInfo_t *gpioEventSetupInfo; agsaGpioWriteSetupInfo_t *gpioWriteSetupInfo; agsaGpioPinSetupInfo_t *gpioPinSetupInfo; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); bit32 status = IOCTL_CALL_SUCCESS; TI_DBG3(("tdsaGpioSetup: start\n")); if(tiRoot == agNULL || agIOCTLPayload == agNULL ) return IOCTL_CALL_FAIL; osIoctlTimer = &tdsaAllShared->osIoctlTimer; tdsaInitTimerRequest(tiRoot, osIoctlTimer); tdIoctlStartTimer(tiRoot, osIoctlTimer); /* Start the timout handler for both ioctl and controller response */ tdsaAllShared->tdFWControlEx.virtAddr = (bit8 *)osIoctlTimer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8 *)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; switch (agIOCTLPayload->MinorFunction) { case IOCTL_MN_GPIO_PINSETUP: { TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_PINSETUP\n")); gpioPinSetupInfo =(agsaGpioPinSetupInfo_t *)&agIOCTLPayload->FunctionSpecificArea[0]; status = saGpioPinSetup(agRoot, agContext, 0, gpioPinSetupInfo); break; } case IOCTL_MN_GPIO_EVENTSETUP: { TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_EVENTSETUP\n")); gpioEventSetupInfo = (agsaGpioEventSetupInfo_t *)&agIOCTLPayload->FunctionSpecificArea[0]; status = saGpioEventSetup(agRoot, agContext, 0, gpioEventSetupInfo); break; } case IOCTL_MN_GPIO_READ: { TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_READ\n")); status = saGpioRead(agRoot, agContext, 0); break; } case IOCTL_MN_GPIO_WRITE: { TI_DBG3(("tdsaGpioSetup: IOCTL_MN_GPIO_WRITE\n")); gpioWriteSetupInfo = (agsaGpioWriteSetupInfo_t *)&agIOCTLPayload->FunctionSpecificArea[0]; status = saGpioWrite(agRoot, agContext, 0, gpioWriteSetupInfo->gpioWritemask, gpioWriteSetupInfo->gpioWriteVal); break; } default : return status; } if(status != AGSA_RC_SUCCESS) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; tdsaSingleThreadedEnter(tiRoot, TD_TIMER_LOCK); if (osIoctlTimer->timerRunning == agTRUE) { tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK); tdsaKillTimer(tiRoot, osIoctlTimer); }else{ tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK); } } TI_DBG3(("tdsaGpioPinSetup: End\n")); return status; } #endif /***************************************************************************** * * ostiGetGpioIOCTLRsp * * Purpose: This routine is called for Get Gpio IOCTL reaponse has been received. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the FW download IOMB's payload. * * Return: none * * *****************************************************************************/ osGLOBAL void ostiGetGpioIOCTLRsp( tiRoot_t *tiRoot, bit32 status, bit32 gpioReadValue, agsaGpioPinSetupInfo_t *gpioPinSetupInfo, agsaGpioEventSetupInfo_t *gpioEventSetupInfo ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIoctlPayload ; agsaGpioReadInfo_t *gpioReadInfo; tdsaTimerRequest_t *osIoctlTimer; osIoctlTimer = (tdsaTimerRequest_t *)tdsaAllShared->tdFWControlEx.virtAddr; TI_DBG2(("ostiGetGpioIOCTLRsp: start, status = %d \n", status)); agIoctlPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); if(agIoctlPayload == agNULL){ return; } agIoctlPayload->Status =(bit16) status; if( (status != IOCTL_CALL_TIMEOUT) && (osIoctlTimer != NULL)) { tdsaSingleThreadedEnter(tiRoot, TD_TIMER_LOCK); if (osIoctlTimer->timerRunning == agTRUE) { tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK); tdsaKillTimer(tiRoot, osIoctlTimer); }else{ tdsaSingleThreadedLeave(tiRoot, TD_TIMER_LOCK); } }else { tdsaAllShared->tdFWControlEx.inProgress = 0; agIoctlPayload->Status = (bit16)status; ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); return; } if(status == SUCCESS) TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response from OUTBuf")); else { tdsaAllShared->tdFWControlEx.inProgress = 0; ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); return; } switch (agIoctlPayload->MinorFunction) { case IOCTL_MN_GPIO_PINSETUP: { TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response for IOCTL_MN_GPIO_PINSETUP")); break; } case IOCTL_MN_GPIO_EVENTSETUP: { TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response for IOCTL_MN_GPIO_EVENTSETUP")); break; } case IOCTL_MN_GPIO_WRITE: { TI_DBG3((" ostiGetGpioIOCTLRsp:Got GPIO response for IOCTL_MN_GPIO_WRITE")); break; } case IOCTL_MN_GPIO_READ: { gpioReadInfo = ( agsaGpioReadInfo_t *)tdsaAllShared->tdFWControlEx.usrAddr; gpioReadInfo->gpioReadValue = gpioReadValue; gpioReadInfo->gpioInputEnabled = gpioPinSetupInfo->gpioInputEnabled ; /* GPIOIE */ gpioReadInfo->gpioEventLevelChangePart1 = gpioPinSetupInfo->gpioTypePart1; /* GPIEVCHANGE (pins 11-0) */ gpioReadInfo->gpioEventLevelChangePart2 = gpioPinSetupInfo->gpioTypePart2; /* GPIEVCHANGE (pins 23-20) */ gpioReadInfo->gpioEventRisingEdgePart1 = 0xFFF & gpioEventSetupInfo->gpioEventRisingEdge; /* GPIEVRISE (pins 11-0) */ gpioReadInfo->gpioEventRisingEdgePart2 = 0x00F00000 & (gpioEventSetupInfo->gpioEventRisingEdge); /* GPIEVRISE (pins 23-20) */ gpioReadInfo->gpioEventFallingEdgePart1 = 0xFFF & gpioEventSetupInfo->gpioEventFallingEdge; /* GPIEVALL (pins 11-0) */ gpioReadInfo->gpioEventFallingEdgePart2 = 0x00F00000 & gpioEventSetupInfo->gpioEventFallingEdge; /* GPIEVALL (pins 23-20 */ break; } default : break; } if(tdsaAllShared->tdFWControlEx.inProgress) { tdsaAllShared->tdFWControlEx.inProgress = 0; ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } TI_DBG2(("ostiGetGpioIOCTLRsp: end \n")); return ; } /***************************************************************************** * * tdsaSGpioIoctlSetup * * Purpose: This routine is called to send SGPIO request to the controller. * * Parameters: * tiRoot: Pointer to driver instance * agsaContext_t: Context for this request * tiIOCTLPayload_t: ioctl header with payload sgpio info * agParam1,agParam2: Generic parameters * * Return: status * * *****************************************************************************/ osGLOBAL bit32 tdsaSGpioIoctlSetup( tiRoot_t *tiRoot, agsaContext_t *agContext, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); bit32 status = IOCTL_CALL_FAIL; agsaSGpioReqResponse_t *pSGpioReq = (agsaSGpioReqResponse_t *)&agIOCTLPayload->FunctionSpecificArea[0]; TI_DBG3(("tdsaSGpioIoctlSetup: start\n")); agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; do { if (tiRoot == agNULL || agIOCTLPayload == agNULL) { break; } /* Validate the length */ if (agIOCTLPayload->Length < sizeof(agsaSGpioReqResponse_t)) { TI_DBG3(("Invalid length\n")); break; } /* Validate the SMP Frame Type, Function and Register Type fields */ if ((pSGpioReq->smpFrameType != SMP_REQUEST) || \ ((pSGpioReq->function != SMP_READ_GPIO_REGISTER) && (pSGpioReq->function != SMP_WRITE_GPIO_REGISTER)) || \ (pSGpioReq->registerType > AGSA_SGPIO_GENERAL_PURPOSE_TRANSMIT_REG)) { TI_DBG4(("Invalid Parameter\n")); break; } /* Specific validation for configuration register type */ if (AGSA_SGPIO_CONFIG_REG == pSGpioReq->registerType) { if ((pSGpioReq->registerIndex > 0x01) || \ ((0x00 == pSGpioReq->registerIndex) && (pSGpioReq->registerCount > 0x02)) || \ ((0x01 == pSGpioReq->registerIndex) && (pSGpioReq->registerCount > 0x01))) { break; } } /* Use FW control place in shared structure to keep the necessary information */ tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = saSgpio(agRoot, agContext, 0, pSGpioReq); if (status != AGSA_RC_SUCCESS) { break; } status = IOCTL_CALL_PENDING; } while (0); TI_DBG3(("tdsaGpioPinSetup: End\n")); return status; } /***************************************************************************** * * ostiSgpioIoctlRsp * * Purpose: This routine is called when a SGPIO IOCTL response is received. * * Parameters: * tiRoot: Pointer to driver instance * pSgpioResponse: Pointer to the SGPIO response * * Return: none * * *****************************************************************************/ osGLOBAL void ostiSgpioIoctlRsp( tiRoot_t *tiRoot, agsaSGpioReqResponse_t *pSgpioResponse ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIoctlPayload = agNULL; TI_DBG3(("ostiSgpioIoctlRsp: start\n")); if (tdsaAllShared->tdFWControlEx.inProgress) { agIoctlPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); if (agIoctlPayload) { tdsaAllShared->tdFWControlEx.payload = NULL; osti_memcpy(&agIoctlPayload->FunctionSpecificArea[0], pSgpioResponse, sizeof(agsaSGpioReqResponse_t)); agIoctlPayload->Status = IOCTL_ERR_STATUS_OK; sgpioResponseSet = 1; } tdsaAllShared->sgpioResponseSet = 1; //Sunitha:Check if needed? ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, agNULL); tdsaAllShared->tdFWControlEx.inProgress = 0; } TI_DBG3(("ostiSgpioIoctlRsp: end\n")); } /***************************************************************************** * * ostiCOMMgntIOCTLRsp * * Purpose: This routine is called when FW control IOCTL reaponse has been received. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the FW download IOMB's payload. * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiCOMMgntIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; TI_DBG1(("ostiCOMMgntIOCTLRsp: status 0x%x\n",status)); (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status; ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.tdFWControl->len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } /***************************************************************************** * * ostiRegDumpIOCTLRsp * * Purpose: This routine is called when Register Dump from flash IOCTL reaponse has been received. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the FW download IOMB's payload. * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiRegDumpIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; TI_DBG1(("ostiRegDumpIOCTLRsp: start\n")); // (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status; osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr), (void *)(tdsaAllShared->tdFWControlEx.virtAddr), tdsaAllShared->tdFWControlEx.len); ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } /***************************************************************************** * * ostiSetNVMDIOCTLRsp * * Purpose: This routine is called for Set NVMD IOCTL reaponse has been received. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the FW download IOMB's payload. * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiSetNVMDIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload; if(status) { agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); agIOCTLPayload->Status = (bit16)status; } TI_DBG1(("ostiSetNVMDIOCTLRsp: start, status = %d\n", status)); // (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status; ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } #ifdef SPC_ENABLE_PROFILE /***************************************************************************** * * ostiFWProfileIOCTLRsp * * Purpose: This routine is called for Fw Profile IOCTL reaponse has been received. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * status: * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiFWProfileIOCTLRsp( tiRoot_t *tiRoot, bit32 status, bit32 len) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tdFWProfile_t *fwProfile; TI_DBG1(("ostiFWProfileIOCTLRsp: start\n")); fwProfile = (tdFWProfile_t *)tdsaAllShared->tdFWProfileEx.tdFWProfile; // (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status; if (status == AGSA_RC_SUCCESS) { if((fwProfile->cmd == STOP_TIMER_PROFILE) || (fwProfile->cmd == STOP_CODE_PROFILE)) { osti_memcpy((void *)(fwProfile->buffer), (void *)(tdsaAllShared->tdFWProfileEx.virtAddr), len); ostiFreeMemory(tiRoot, tdsaAllShared->tdFWProfileEx.buffer, tdsaAllShared->tdFWProfileEx.len); } } fwProfile->status = status; fwProfile->len = len; ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWProfileEx.param1, tdsaAllShared->tdFWProfileEx.param2, NULL); } #endif /***************************************************************************** * * ostiGetNVMDIOCTLRsp * * Purpose: This routine is called for Get NVMD IOCTL reaponse has been received. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the FW download IOMB's payload. * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiGetNVMDIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload; if(status) { agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); agIOCTLPayload->Status = (bit16)status; } TI_DBG1(("ostiGetNVMDIOCTLRsp: start, status = %d\n", status)); tdsaAllShared->NvmdResponseSet = 1; if(tdsaAllShared->tdFWControlEx.param1 != agNULL) { osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr), (void *)(tdsaAllShared->tdFWControlEx.virtAddr), tdsaAllShared->tdFWControlEx.len); ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } } /***************************************************************************** * * ostiGetPhyProfileIOCTLRsp * * Purpose: This routine is called for phy response has been received. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the IOMB's payload. * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiGetPhyProfileIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload; tdPhyCount_t *PhyBlob = agNULL; if(status) { agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); agIOCTLPayload->Status = (bit16)status; PhyBlob = (tdPhyCount_t*)&agIOCTLPayload->FunctionSpecificArea[0]; if(PhyBlob) { // PhyBlob->Phy |= 0x800; if(PhyBlob->phyResetProblem == 0 ) { PhyBlob->phyResetProblem = -1; } TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->Phy 0x%x\n",PhyBlob->Phy)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->BW_rx 0x%x\n",PhyBlob->BW_rx)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->BW_tx 0x%x\n",PhyBlob->BW_tx)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->InvalidDword 0x%x\n",PhyBlob->InvalidDword)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->runningDisparityError 0x%x\n",PhyBlob->runningDisparityError)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->codeViolation 0x%x\n",PhyBlob->codeViolation)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->phyResetProblem 0x%x\n",PhyBlob->phyResetProblem)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: PhyBlob->inboundCRCError 0x%x\n",PhyBlob->inboundCRCError)); } } TI_DBG1(("ostiGetPhyProfileIOCTLRsp: start, status = %d\n", status)); TI_DBG1(("ostiGetPhyProfileIOCTLRsp: start, len = %d %p %p\n", tdsaAllShared->tdFWControlEx.len,tdsaAllShared->tdFWControlEx.usrAddr,tdsaAllShared->tdFWControlEx.virtAddr)); // osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr), // (void *)(tdsaAllShared->tdFWControlEx.virtAddr), // tdsaAllShared->tdFWControlEx.len); ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } /***************************************************************************** * * ostiGenEventIOCTLRsp * * Purpose: This routine is called when General Event happened while waiting for IOCTL response. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * payloadRsp: Pointer to the FW download IOMB's payload. * * Return: none * * * *****************************************************************************/ osGLOBAL void ostiGenEventIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload; TI_DBG1(("ostiGenEventIOCTLRsp: start\n")); if(tdsaAllShared->tdFWControlEx.inProgress) /*Free only if our IOCTL is in progress*/ { agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = IOCTL_ERR_STATUS_INTERNAL_ERROR; ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); tdsaAllShared->tdFWControlEx.inProgress = 0; } #ifdef SPC_ENABLE_PROFILE if(tdsaAllShared->tdFWProfileEx.inProgress) { agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWProfileEx.payload); agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; if(tdsaAllShared->tdFWProfileEx.virtAddr != NULL) /*Free only if our IOCTL is in progress*/ { ostiFreeMemory(tiRoot, tdsaAllShared->tdFWProfileEx.buffer, tdsaAllShared->tdFWProfileEx.len); tdsaAllShared->tdFWProfileEx.virtAddr = NULL; } ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWProfileEx.param1, tdsaAllShared->tdFWProfileEx.param2, NULL); tdsaAllShared->tdFWProfileEx.inProgress = 0; } #endif /*SPC_ENABLE_PROFILE*/ } osGLOBAL void ostiGetDeviceInfoIOCTLRsp( tiRoot_t *tiRoot, bit32 status, void *param ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload = agNULL; tdDeviceInfoPayload_t *pTDDeviceInfo = agNULL; agsaDeviceInfo_t *pSADeviceInfo = agNULL; TI_DBG1(("ostiGetDeviceInfoIOCTLRsp: start\n")); agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); pSADeviceInfo = (agsaDeviceInfo_t*)param; pTDDeviceInfo = (tdDeviceInfoPayload_t*)agIOCTLPayload->FunctionSpecificArea; if (pSADeviceInfo != agNULL) { /* fill the device information in IOCTL payload */ osti_memcpy(&pTDDeviceInfo->devInfo.sasAddressHi, pSADeviceInfo->sasAddressHi, sizeof(bit32)); osti_memcpy(&pTDDeviceInfo->devInfo.sasAddressLo, pSADeviceInfo->sasAddressLo, sizeof(bit32)); pTDDeviceInfo->devInfo.sasAddressHi = DMA_BEBIT32_TO_BIT32(pTDDeviceInfo->devInfo.sasAddressHi); pTDDeviceInfo->devInfo.sasAddressLo = DMA_BEBIT32_TO_BIT32(pTDDeviceInfo->devInfo.sasAddressLo); pTDDeviceInfo->devInfo.deviceType = (pSADeviceInfo->devType_S_Rate & 0x30) >> 4; pTDDeviceInfo->devInfo.linkRate = pSADeviceInfo->devType_S_Rate & 0x0F; agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE; } if(tdsaAllShared->tdFWControlEx.inProgress) /*Free only if our IOCTL is in progress*/ { ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); tdsaAllShared->tdFWControlEx.inProgress = 0; } } #ifdef INITIATOR_DRIVER osGLOBAL void ostiGetIoErrorStatsIOCTLRsp( tiRoot_t *tiRoot, bit32 status, void *param ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; itdsaIni_t *Initiator = (itdsaIni_t *)tdsaAllShared->itdsaIni; tiIOCTLPayload_t *agIOCTLPayload = agNULL; tdIoErrorStatisticPayload_t *pIoErrorPayload = agNULL; agsaIOErrorEventStats_t *pIoErrorCount = agNULL; OS_ASSERT(sizeof(agsaIOErrorEventStats_t) == sizeof(tdIoErrorEventStatisticIOCTL_t), "agsaIOErrorEventStats_t tdIoErrorEventStatisticIOCTL_t\n"); TI_DBG1(("ostiGetIoErrorStatsIOCTLRsp: start\n")); agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); pIoErrorPayload = (tdIoErrorStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea; pIoErrorCount = (agsaIOErrorEventStats_t*)param; osti_memcpy(&pIoErrorPayload->IoError, pIoErrorCount, sizeof(agsaIOErrorEventStats_t)); /*copy SCSI status and sense key count from OS layer to TD layer*/ osti_memcpy(&pIoErrorPayload->ScsiStatusCounter, &Initiator->ScsiStatusCounts, sizeof(tdSCSIStatusCount_t)); osti_memcpy(&pIoErrorPayload->SenseKeyCounter, &Initiator->SenseKeyCounter, sizeof(tdSenseKeyCount_t)); if (pIoErrorPayload->flag) { osti_memset(&Initiator->ScsiStatusCounts, 0,sizeof(tdSCSIStatusCount_t) ); osti_memset(&Initiator->SenseKeyCounter, 0,sizeof(tdSenseKeyCount_t) ); } agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } #endif /* INITIATOR_DRIVER */ osGLOBAL void ostiGetIoEventStatsIOCTLRsp( tiRoot_t *tiRoot, bit32 status, void *param ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload = agNULL; tdIoEventStatisticPayload_t *pIoEventPayload = agNULL; agsaIOErrorEventStats_t *pIoEventCount = agNULL; TI_DBG1(("ostiGetIoEventStatsIOCTLRsp: start\n")); agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); pIoEventPayload = (tdIoEventStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea; pIoEventCount = (agsaIOErrorEventStats_t*)param; osti_memcpy(&pIoEventPayload->IoEvent, pIoEventCount, sizeof(agsaIOErrorEventStats_t)); agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } osGLOBAL void ostiGetForensicDataIOCTLRsp( tiRoot_t *tiRoot, bit32 status, void *param ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload = agNULL; tdForensicDataPayload_t *pForensicDataPayload = agNULL; agsaForensicData_t *pForensicData = agNULL; TI_DBG3(("ostiGetForensicDataIOCTLRsp: start, status = %d\n", status)); agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); pForensicDataPayload = (tdForensicDataPayload_t*)agIOCTLPayload->FunctionSpecificArea; pForensicData = (agsaForensicData_t*)param; if (agNULL == agIOCTLPayload) { return; } if (FORENSIC_DATA_TYPE_CHECK_FATAL == pForensicData->DataType) { agIOCTLPayload->Status = (bit16)status; return; } if (status == AGSA_RC_SUCCESS) { switch (pForensicData->DataType) { case FORENSIC_DATA_TYPE_NON_FATAL: case FORENSIC_DATA_TYPE_FATAL: pForensicDataPayload->dataBuffer.directOffset = pForensicData->BufferType.dataBuf.directOffset; pForensicDataPayload->dataBuffer.readLen = pForensicData->BufferType.dataBuf.readLen; break; case FORENSIC_DATA_TYPE_GSM_SPACE: pForensicDataPayload->gsmBuffer.directOffset = pForensicData->BufferType.gsmBuf.directOffset; pForensicDataPayload->gsmBuffer.readLen = pForensicData->BufferType.gsmBuf.readLen; break; case FORENSIC_DATA_TYPE_QUEUE: break; default: TI_DBG1(("ostiGetForensicDataIOCTLRsp: forensic data type error %d\n", pForensicData->DataType)); break; } agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; } else if(status == IOCTL_ERROR_NO_FATAL_ERROR) { agIOCTLPayload->Status = (bit16)status; } else { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } /*Free only if our IOCTL is in progress*/ if(tdsaAllShared->tdFWControlEx.inProgress) { TI_DBG3(("ostiGetForensicDataIOCTLRsp: Waiting for the signal \n")); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); TI_DBG3(("ostiGetForensicDataIOCTLRsp: Signal wait completed \n")); tdsaAllShared->tdFWControlEx.inProgress = 0; } } /***************************************************************************** * * tdsaRegDumpGetIoctl * * Purpose: This routine is called to get Register Dump information. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaRegDumpGetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); // agsaControllerStatus_t RegDump; bit32 Offset = 0; bit32 RequestLength = 0; /* user request on how much data to pass to application */ agsaRegDumpInfo_t regDumpInfo; void *buffer = agNULL; void *osMemHandle = agNULL; bit32 status = IOCTL_CALL_SUCCESS; bit32 CoreDumpLength = 16384; /* change it once data is available */ bit32 EventLogOffset = 65536; ///saGetControllerStatus(agRoot, &RegDump); /* length of FSA as provided by application */ RequestLength = agIOCTLPayload->Length; /// FunctionSpecificOffset = 0; /* Offset into the FunctionSpecificArea of payload */ /* offset into core dump that was passed from application */ Offset = agIOCTLPayload->Reserved; if((CoreDumpLength <= Offset)&& (agIOCTLPayload->MinorFunction != IOCTL_MN_FW_GET_EVENT_FLASH_LOG1)&& (agIOCTLPayload->MinorFunction != IOCTL_MN_FW_GET_EVENT_FLASH_LOG2)) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; status=IOCTL_CALL_SUCCESS; return status; } regDumpInfo.regDumpOffset = Offset; agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; /* dump either aap1 or iop registers */ switch(agIOCTLPayload->MinorFunction){ /*Coredump*/ case IOCTL_MN_FW_GET_CORE_DUMP_AAP1: //CoreDumpBAROffset = RegDump.fatalErrorInfo.regDumpOffset0; /* get this from mpi config table */ //CoreDumpLength = RegDump.fatalErrorInfo.regDumpLen0; /*changes for added Call back*/ tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; regDumpInfo.regDumpSrc = 0; regDumpInfo.regDumpNum = 0; regDumpInfo.directLen = RequestLength; regDumpInfo.directData = &agIOCTLPayload->FunctionSpecificArea[0]; /*changes for added Call back*/ //status = IOCTL_CALL_SUCCESS; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; case IOCTL_MN_FW_GET_CORE_DUMP_IOP: //CoreDumpBAROffset = RegDump.fatalErrorInfo.regDumpOffset1; /* get this from mpi config table */ //CoreDumpLength = RegDump.fatalErrorInfo.regDumpLen1; /*changes for added Call back*/ tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; regDumpInfo.regDumpSrc = 0; regDumpInfo.regDumpNum = 1; regDumpInfo.directLen = RequestLength; regDumpInfo.directData = &agIOCTLPayload->FunctionSpecificArea[0]; /*changes for added Call back*/ //status = IOCTL_CALL_SUCCESS; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; case IOCTL_MN_FW_GET_CORE_DUMP_FLASH_AAP1: regDumpInfo.regDumpSrc = 1; regDumpInfo.regDumpNum = 0; if(RequestLength != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &(regDumpInfo.indirectAddrUpper32), &(regDumpInfo.indirectAddrLower32), 8, RequestLength, agFALSE)) return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, RequestLength); regDumpInfo.indirectLen = RequestLength; // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = RequestLength; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; case IOCTL_MN_FW_GET_CORE_DUMP_FLASH_IOP: regDumpInfo.regDumpSrc = 1; regDumpInfo.regDumpNum = 1; if(RequestLength != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &(regDumpInfo.indirectAddrUpper32), &(regDumpInfo.indirectAddrLower32), 8, RequestLength, agFALSE)) return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, RequestLength); regDumpInfo.indirectLen = RequestLength; // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = RequestLength; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; /*EventLog from Flash*/ case IOCTL_MN_FW_GET_EVENT_FLASH_LOG1: //aap1 Eventlog if(CoreDumpLength + EventLogOffset <= Offset) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; status=IOCTL_CALL_SUCCESS; return status; } regDumpInfo.regDumpSrc = 1; regDumpInfo.regDumpNum = 0; if(RequestLength != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &(regDumpInfo.indirectAddrUpper32), &(regDumpInfo.indirectAddrLower32), 8, RequestLength, agFALSE)) return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, RequestLength); regDumpInfo.indirectLen = RequestLength; // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = RequestLength; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; case IOCTL_MN_FW_GET_EVENT_FLASH_LOG2: //iop Eventlog if(CoreDumpLength + EventLogOffset <= Offset) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; status=IOCTL_CALL_SUCCESS; return status; } regDumpInfo.regDumpSrc = 1; regDumpInfo.regDumpNum = 1; if(RequestLength != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &(regDumpInfo.indirectAddrUpper32), &(regDumpInfo.indirectAddrLower32), 8, RequestLength, agFALSE)) return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, RequestLength); regDumpInfo.indirectLen = RequestLength; // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = RequestLength; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; default: status = IOCTL_CALL_INVALID_CODE; TI_DBG1(("tiCOMMgntIOCTL: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction)); break; } if(saGetRegisterDump(agRoot, agNULL, 0, ®DumpInfo) != AGSA_RC_SUCCESS) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } return status; } osGLOBAL void ostiCOMMgntVPDSetIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; // agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); TI_DBG1(("ostiCOMMgntVPDSetIOCTLRsp: start\n")); (tdsaAllShared->tdFWControlEx.tdFWControl)->retcode = status; ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); } /***************************************************************************** * * tdsaNVMDSetIoctl * * Purpose: This routine is called to set Config. SEEPROM information. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaNVMDSetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { bit32 RequestLength = 0; bit32 bufAddrUpper = 0; bit32 bufAddrLower = 0; tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); void *buffer = agNULL; void *osMemHandle = agNULL; bit32 status = IOCTL_CALL_SUCCESS; agsaNVMDData_t nvmdInfo; TI_DBG2(("tdsaNVMDSetIoctl: start\n")); RequestLength = agIOCTLPayload->Length; osti_memset(&nvmdInfo, 0, sizeof(agsaNVMDData_t)); switch(agIOCTLPayload->MinorFunction) { case IOCTL_MN_NVMD_SET_CONFIG: //nvmdInfo.NVMDevice = 1; nvmdInfo.NVMDevice = *((bit8*)agParam3); nvmdInfo.signature = 0xFEDCBA98; nvmdInfo.dataOffsetAddress = agIOCTLPayload->Reserved; nvmdInfo.indirectPayload = 1; nvmdInfo.indirectLen = RequestLength; if (nvmdInfo.NVMDevice == 0) { nvmdInfo.TWIDeviceAddress = 0xa0; nvmdInfo.TWIBusNumber = 0; nvmdInfo.TWIDevicePageSize = 0; nvmdInfo.TWIDeviceAddressSize = 1; } if(RequestLength != 0) { if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &bufAddrUpper, &bufAddrLower, 8, RequestLength, agFALSE)) return IOCTL_CALL_FAIL; } else { return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, RequestLength); osti_memcpy((void *)buffer, agIOCTLPayload->FunctionSpecificArea, RequestLength); nvmdInfo.indirectAddrLower32 = bufAddrLower; nvmdInfo.indirectAddrUpper32 = bufAddrUpper; // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = RequestLength; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; default: status = IOCTL_CALL_INVALID_CODE; TI_DBG1(("tdsaNVMDSetIoctl: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction)); break; } if(saSetNVMDCommand(agRoot, agNULL, 0, &nvmdInfo) != AGSA_RC_SUCCESS) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } return status; } /***************************************************************************** * * tdsaNVMDGetIoctl * * Purpose: This routine is called to get Config. SEEPROM information. * This function is used for both target and initiator. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaNVMDGetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); void *buffer = agNULL; void *osMemHandle = agNULL; bit32 status = IOCTL_CALL_SUCCESS; agsaNVMDData_t nvmdInfo; bit32 Offset = 0; bit32 RequestLength = 0; bit32 ostiMemoryStatus = 0; bit32 i,j; bit8* seepromBuffer; bit8* phySettingsBuffer; TI_DBG2(("tdsaNVMDGetIoctl: start\n")); RequestLength = agIOCTLPayload->Length; Offset = agIOCTLPayload->Reserved; osti_memset(&nvmdInfo, 0, sizeof(agsaNVMDData_t)); /* This condition is not valid for direct read so commenting */ /*if(!tiIS_SPC(agRoot)) { if( RequestLength <= Offset ) //4096-max seeprom size { agIOCTLPayload->Status = IOCTL_ERR_STATUS_NO_MORE_DATA; agIOCTLPayload->Length = 0; status=IOCTL_CALL_SUCCESS; return status; } }*/ agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; switch(agIOCTLPayload->MinorFunction) { case IOCTL_MN_NVMD_GET_CONFIG: // nvmdInfo.NVMDevice = 1; nvmdInfo.NVMDevice = *((bit8*)agParam3); nvmdInfo.signature = 0xFEDCBA98; nvmdInfo.dataOffsetAddress = Offset; nvmdInfo.indirectPayload = 1; nvmdInfo.indirectLen = RequestLength; if (nvmdInfo.NVMDevice == 0) { nvmdInfo.TWIDeviceAddress = 0xa0; nvmdInfo.TWIBusNumber = 0; nvmdInfo.TWIDevicePageSize = 0; nvmdInfo.TWIDeviceAddressSize = 1; } if(RequestLength != 0) { ostiMemoryStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &(nvmdInfo.indirectAddrUpper32), &(nvmdInfo.indirectAddrLower32), 8, RequestLength, agFALSE); if((ostiMemoryStatus != tiSuccess) && (buffer == agNULL)) return IOCTL_CALL_FAIL; } else { return IOCTL_CALL_FAIL; } osti_memset((void *)buffer, 0, RequestLength); // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = RequestLength; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; break; default: status = IOCTL_CALL_INVALID_CODE; TI_DBG1(("tiCOMMgntIOCTL: ERROR: Wrong IOCTL code %d\n", agIOCTLPayload->MinorFunction)); break; } tdsaAllShared->NvmdResponseSet = 0; if(saGetNVMDCommand(agRoot, agNULL, 0, &nvmdInfo) != AGSA_RC_SUCCESS) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; return status; } /* Copy the SAS address */ if(agParam1 == agNULL) { while(!tdsaAllShared->NvmdResponseSet) { // tiCOMDelayedInterruptHandler(tiRoot, 0, 1, tiNonInterruptContext); } if(nvmdInfo.NVMDevice == 4 || nvmdInfo.NVMDevice == 1) { seepromBuffer = buffer; /*Get Initiator SAS address*/ if(tiIS_SPC(agRoot)) { for(j=0,i=ADAPTER_WWN_SPC_START_OFFSET; i<= ADAPTER_WWN_SPC_END_OFFSET; i++,j++) agIOCTLPayload->FunctionSpecificArea[j] = seepromBuffer[i]; } else { for(j=0,i=ADAPTER_WWN_START_OFFSET; i<= ADAPTER_WWN_END_OFFSET; i++,j++) agIOCTLPayload->FunctionSpecificArea[j] = seepromBuffer[i]; } } /* Copy the Phy settings */ else if(nvmdInfo.NVMDevice == 6) { phySettingsBuffer = buffer; for(i=0; iFunctionSpecificArea[i] = phySettingsBuffer[i]; } tdsaAllShared->NvmdResponseSet = 0; ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); } return status; } /***************************************************************************** * * tdsaDeviceInfoGetIoctl * * Purpose: This routine is called to get the specified device information. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaDeviceInfoGetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaDeviceData_t *oneDeviceData = agNULL; tiDeviceHandle_t *tiDeviceHandle = agNULL; tdDeviceInfoPayload_t *pDeviceInfo = agNULL; /*agsaDevHandle_t *agDevHandle = agNULL;*/ bit32 status = IOCTL_CALL_SUCCESS; pDeviceInfo = (tdDeviceInfoPayload_t*)agIOCTLPayload->FunctionSpecificArea; TI_DBG3(("tdsaDeviceInfoGetIoctl: %d:%3d:%d %p %p %p\n", (bit8)pDeviceInfo->PathId, (bit8)pDeviceInfo->TargetId, (bit8)pDeviceInfo->Lun, agParam1, agParam2, agParam3)); tiDeviceHandle = ostiMapToDevHandle(tiRoot, (bit8)pDeviceInfo->PathId, (bit8)pDeviceInfo->TargetId, (bit8)pDeviceInfo->Lun ); if (tiDeviceHandle == agNULL) { TI_DBG1(("tdsaDeviceInfoGetIoctl: tiDeviceHandle is NULL !!!! SCSI address = %d:%3d:%d\n", pDeviceInfo->PathId, pDeviceInfo->TargetId, pDeviceInfo->Lun)); agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE; status = IOCTL_CALL_FAIL; return status; } oneDeviceData = (tdsaDeviceData_t *)tiDeviceHandle->tdData; if(oneDeviceData == agNULL) { TI_DBG1(("tdsaDeviceInfoGetIoctl: tiDeviceHandle=%p DeviceData is NULL!!! SCSI address = %d:%3d:%d\n", tiDeviceHandle, pDeviceInfo->PathId, pDeviceInfo->TargetId, pDeviceInfo->Lun)); agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE; status = IOCTL_CALL_FAIL; return status; } /* for hotplug */ if (oneDeviceData->valid != agTRUE || oneDeviceData->registered != agTRUE || oneDeviceData->tdPortContext == agNULL ) { TI_DBG1(("tdsaDeviceInfoGetIoctl: tiDeviceHandle=%p did %d DeviceData was removed!!! SCSI address = %d:%3d:%d\n", tiDeviceHandle, oneDeviceData->id, pDeviceInfo->PathId, pDeviceInfo->TargetId, pDeviceInfo->Lun)); agIOCTLPayload->Status = IOCTL_ERR_STATUS_INVALID_DEVICE; status = IOCTL_CALL_FAIL; return status; } /* fill the device information in IOCTL payload */ pDeviceInfo->devInfo.phyId = oneDeviceData->phyID; osti_memcpy(&pDeviceInfo->devInfo.sasAddressHi, oneDeviceData->agDeviceInfo.sasAddressHi, sizeof(bit32)); osti_memcpy(&pDeviceInfo->devInfo.sasAddressLo, oneDeviceData->agDeviceInfo.sasAddressLo, sizeof(bit32)); pDeviceInfo->devInfo.sasAddressHi = DMA_BEBIT32_TO_BIT32(pDeviceInfo->devInfo.sasAddressHi); pDeviceInfo->devInfo.sasAddressLo = DMA_BEBIT32_TO_BIT32(pDeviceInfo->devInfo.sasAddressLo); pDeviceInfo->devInfo.deviceType = (oneDeviceData->agDeviceInfo.devType_S_Rate & 0x30) >> 4; pDeviceInfo->devInfo.linkRate = oneDeviceData->agDeviceInfo.devType_S_Rate & 0x0F; agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; TI_DBG3(("tdsaDeviceInfoGetIoctl:IOCTL_CALL_SUCCESS\n")); /*saGetDeviceInfo(agRoot, agNULL, 0, 0, agDevHandle);*/ status = IOCTL_CALL_SUCCESS; return status; } /***************************************************************************** * * tdsaIoErrorStatisticGetIoctl * * Purpose: This routine is called to get the IO error statistic. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaIoErrorStatisticGetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); tdIoErrorStatisticPayload_t *pIoErrorPayload = agNULL; bit32 status = IOCTL_CALL_SUCCESS; pIoErrorPayload = (tdIoErrorStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea; tdsaAllShared->tdFWControlEx.buffer = agNULL; tdsaAllShared->tdFWControlEx.virtAddr = agNULL; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = 0; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 0; saGetIOErrorStats(agRoot, agNULL, pIoErrorPayload->flag); return status; } /***************************************************************************** * * tdsaIoEventStatisticGetIoctl * * Purpose: This routine is called to get the IO event statistic. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaIoEventStatisticGetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); tdIoEventStatisticPayload_t *pIoEventPayload = agNULL; bit32 status = IOCTL_CALL_SUCCESS; pIoEventPayload = (tdIoEventStatisticPayload_t*)agIOCTLPayload->FunctionSpecificArea; tdsaAllShared->tdFWControlEx.buffer = agNULL; tdsaAllShared->tdFWControlEx.virtAddr = agNULL; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = 0; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 0; saGetIOEventStats(agRoot, agNULL, pIoEventPayload->flag); return status; } /***************************************************************************** * * tdsaRegisterIoctl * * Purpose: This routine is called to get Forensic Data. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaRegisterIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; // agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); tdRegisterPayload_t *pRegisterPayload = agNULL; bit32 status = IOCTL_CALL_SUCCESS; pRegisterPayload = (tdRegisterPayload_t*)agIOCTLPayload->FunctionSpecificArea; tdsaAllShared->tdFWControlEx.buffer = agNULL; tdsaAllShared->tdFWControlEx.virtAddr = agNULL; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = 0; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 0; TI_DBG1(("tdsaRegisterIoctl: Flag %d RegAddr 0x%x RegValue 0x%x\n", pRegisterPayload->flag, pRegisterPayload->RegAddr, pRegisterPayload->RegValue)); if (pRegisterPayload->flag) { /* set register */ ostiChipWriteBit32Ext(tiRoot, 0, pRegisterPayload->RegAddr, pRegisterPayload->RegValue); } else { /* get register */ pRegisterPayload->RegValue = ostiChipReadBit32Ext(tiRoot, 0, pRegisterPayload->RegAddr); } agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; return status; } osGLOBAL bit32 tdsaGetPhyGeneralStatusIoctl( tiRoot_t *tiRoot, agsaPhyGeneralState_t *PhyData ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootNonInt); // agsaLLRoot_t *saRoot = (agsaLLRoot_t *)(agRoot->sdkData); // bit8 totalValidPhys; bit32 status = AGSA_RC_SUCCESS; bit32 i = 0; agsaControllerInfo_t ControllerInfo; saGetControllerInfo(agRoot,&ControllerInfo); TI_DBG3(("tdsaGetPhyGeneralStatusIoctl: start\n")); do { if(tIsSPC(agRoot)||tIsSPCHIL(agRoot)) { status = IOCTL_ERR_STATUS_NOT_SUPPORTED; break; } PhyData->Reserved1 = ControllerInfo.phyCount; for(i=0;iReserved1;i++) { status = saGetPhyProfile( agRoot,agNULL,tdsaRotateQnumber(tiRoot, agNULL), AGSA_SAS_PHY_GENERAL_STATUS_PAGE,i); if(status == AGSA_RC_FAILURE) { break; } } }while(0); TI_DBG3(("tdsaGetPhyGeneralStatusIoctl: End\n")); return status; } /***************************************************************************** * * ostiGetPhyGeneralStatusRsp * * Purpose: This routine is called when a PhyStatus IOCTL response is received. * * Parameters: * tiRoot: Pointer to driver instance * agsaSASPhyGeneralStatusPage_t: Status of the phy. * bit32: phyID * * Return: none * * *****************************************************************************/ osGLOBAL void ostiGetPhyGeneralStatusRsp( tiRoot_t *tiRoot, agsaSASPhyGeneralStatusPage_t *GenStatus, bit32 phyID ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIoctlPayload = agNULL; agsaPhyGeneralState_t *pSetPhyStatusRes = agNULL; TI_DBG1(("ostiGetPhyGeneralStatusRsp: start\n")); if (tdsaAllShared->tdFWControlEx.inProgress) { agIoctlPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); if ((agIoctlPayload) && (PMC_IOCTL_SIGNATURE == agIoctlPayload->Signature)&& (IOCTL_MJ_PHY_GENERAL_STATUS == agIoctlPayload->MajorFunction)) { pSetPhyStatusRes = (agsaPhyGeneralState_t*) &agIoctlPayload->FunctionSpecificArea[0]; osti_memcpy(&pSetPhyStatusRes->PhyGenData[phyID], GenStatus, sizeof(agsaSASPhyGeneralStatusPage_t)); pSetPhyStatusRes->Reserved2++; if(pSetPhyStatusRes->Reserved1 == pSetPhyStatusRes->Reserved2) { tdsaAllShared->tdFWControlEx.payload = NULL; ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, agNULL); tdsaAllShared->tdFWControlEx.inProgress = 0; agIoctlPayload->Status = IOCTL_ERR_STATUS_OK; } } } TI_DBG1(("ostiGetPhyGeneralStatusRsp: end\n")); } osGLOBAL bit32 tdsaPhyProfileIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); void *buffer = agNULL; void *osMemHandle = agNULL; bit32 status = IOCTL_CALL_SUCCESS; bit32 retcode = AGSA_RC_FAILURE; bit32 RequestLength= agIOCTLPayload->Length; bit32 bufAddrUpper = 0; bit32 bufAddrLower = 0; tdPhyCount_t *PhyBlob = (tdPhyCount_t*)&agIOCTLPayload->FunctionSpecificArea[0]; if(ostiAllocMemory( tiRoot, &osMemHandle, (void **)&buffer, &bufAddrUpper, &bufAddrLower, RequestLength, RequestLength, agTRUE)) return IOCTL_CALL_FAIL; tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = buffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = 32; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; TI_DBG1(("tdsaPhyProfileIoctl: MinorFunction %d\n",agIOCTLPayload->MinorFunction)); // PhyBlob->Phy |= 0x100; if( tiIS_SPC(agRoot) ) { TI_DBG1(("tdsaPhyProfileIoctl: SPC operation 0x%x PHY %d\n",agIOCTLPayload->MinorFunction,PhyBlob->Phy)); retcode = saLocalPhyControl(agRoot,agNULL,0 ,PhyBlob->Phy ,agIOCTLPayload->MinorFunction , agNULL); if(retcode == AGSA_RC_SUCCESS) { status = IOCTL_CALL_PENDING; } } else { TI_DBG1(("tdsaPhyProfileIoctl: SPCv operation 0x%x PHY %d\n",agIOCTLPayload->MinorFunction,PhyBlob->Phy)); retcode = saGetPhyProfile( agRoot,agNULL,0,agIOCTLPayload->MinorFunction , PhyBlob->Phy); if(retcode == AGSA_RC_SUCCESS) { status = IOCTL_CALL_PENDING; } } TI_DBG2(("tdsaPhyProfileIoctl: after\n")); return status; } /***************************************************************************** * * tdsaForensicDataGetIoctl * * Purpose: This routine is called to get Forensic Data. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaForensicDataGetIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); tdForensicDataPayload_t *pForensicDataPayload = agNULL; agsaForensicData_t ForensicData; bit32 status = IOCTL_CALL_SUCCESS; pForensicDataPayload = (tdForensicDataPayload_t*)agIOCTLPayload->FunctionSpecificArea; tdsaAllShared->tdFWControlEx.buffer = agNULL; tdsaAllShared->tdFWControlEx.virtAddr = agNULL; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = 0; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 0; osti_memset(&ForensicData, 0, sizeof(agsaForensicData_t)); ForensicData.DataType = pForensicDataPayload->DataType; switch (ForensicData.DataType) { case FORENSIC_DATA_TYPE_NON_FATAL: case FORENSIC_DATA_TYPE_FATAL: ForensicData.BufferType.dataBuf.directLen = pForensicDataPayload->dataBuffer.directLen; ForensicData.BufferType.dataBuf.directOffset = pForensicDataPayload->dataBuffer.directOffset; ForensicData.BufferType.dataBuf.readLen = pForensicDataPayload->dataBuffer.readLen; ForensicData.BufferType.dataBuf.directData = (void*)pForensicDataPayload->dataBuffer.directData; break; case FORENSIC_DATA_TYPE_GSM_SPACE: ForensicData.BufferType.gsmBuf.directLen = pForensicDataPayload->gsmBuffer.directLen; ForensicData.BufferType.gsmBuf.directOffset = pForensicDataPayload->gsmBuffer.directOffset; ForensicData.BufferType.dataBuf.readLen = pForensicDataPayload->gsmBuffer.readLen; ForensicData.BufferType.gsmBuf.directData = (void*)pForensicDataPayload->gsmBuffer.directData; break; case FORENSIC_DATA_TYPE_IB_QUEUE: ForensicData.BufferType.queueBuf.directLen = pForensicDataPayload->queueBuffer.directLen; //ForensicData.BufferType.queueBuf.queueType = pForensicDataPayload->queueBuffer.queueType; ForensicData.BufferType.queueBuf.queueType = FORENSIC_DATA_TYPE_IB_QUEUE; ForensicData.BufferType.queueBuf.queueIndex = pForensicDataPayload->queueBuffer.queueIndex; ForensicData.BufferType.queueBuf.directData = (void*)pForensicDataPayload->queueBuffer.directData; break; case FORENSIC_DATA_TYPE_OB_QUEUE: ForensicData.BufferType.queueBuf.directLen = pForensicDataPayload->queueBuffer.directLen; ForensicData.BufferType.queueBuf.queueType = FORENSIC_DATA_TYPE_OB_QUEUE; ForensicData.BufferType.queueBuf.queueIndex = pForensicDataPayload->queueBuffer.queueIndex; ForensicData.BufferType.queueBuf.directData = (void*)pForensicDataPayload->queueBuffer.directData; break; default: TI_DBG1(("tdsaGetForensicDataIoctl: forensic data type error %d\n", pForensicDataPayload->DataType)); status = IOCTL_CALL_INVALID_CODE; return status; } if ( saGetForensicData(agRoot, agNULL, &ForensicData) != AGSA_RC_SUCCESS ) { status = IOCTL_CALL_FAIL; } return status; } osGLOBAL bit32 tdsaSendSMPIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); void *reqBuffer = agNULL; void *respBuffer = agNULL; void *osMemHandle = agNULL; bit32 status = IOCTL_CALL_SUCCESS; // bit32 Offset = 0; // bit32 RequestLength = 0; bit32 ostiMemoryStatus = 0; smp_pass_through_req_t *smp_pass_through_req; tiDeviceHandle_t *devHandle; agsaSMPFrame_t agSMPFrame; tdsaDeviceData_t *oneDeviceData = agNULL; bit32 i; TI_DBG2(("tdsaSendSMPIoctl: start\n")); smp_pass_through_req = (smp_pass_through_req_t*)agIOCTLPayload->FunctionSpecificArea; for(i=0;i<8;i++) TI_DBG2(("SAS Address[%d]:%x",i,smp_pass_through_req->exp_sas_addr[i])); TI_DBG2(("SAS Request Length:%d",smp_pass_through_req->smp_req_len)); TI_DBG2(("SAS Response Length:%d",smp_pass_through_req->smp_resp_len)); for(i=0;ismp_req_len;i++) TI_DBG2(("SAS request + %d:%x",i,smp_pass_through_req->smp_req_resp[i])); devHandle = ostiGetDevHandleFromSasAddr(tiRoot, smp_pass_through_req->exp_sas_addr); if(devHandle == NULL) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; return status; } //agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; agIOCTLPayload->Status = IOCTL_ERR_STATUS_NOT_RESPONDING; if((ostiMemoryStatus != tiSuccess) && (reqBuffer == agNULL )) return IOCTL_CALL_FAIL; tdsaAllShared->tdFWControlEx.param3 = osMemHandle; agSMPFrame.outFrameBuf = smp_pass_through_req->smp_req_resp; agSMPFrame.expectedRespLen = smp_pass_through_req->smp_resp_len; agSMPFrame.inFrameLen = smp_pass_through_req->smp_resp_len - 4; if(!(smp_pass_through_req->smp_req_len - 8) && !tiIS_SPC(agRoot)) { agSMPFrame.flag = 1; // Direct request Indirect response agSMPFrame.outFrameLen = smp_pass_through_req->smp_req_len - 4; //Exclude header } else { agSMPFrame.flag = 3; //Indirect request and Indirect response ostiMemoryStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&reqBuffer, &(agSMPFrame.outFrameAddrUpper32), &(agSMPFrame.outFrameAddrLower32), 8, smp_pass_through_req->smp_req_len, agFALSE); tdsaAllShared->tdFWControlEx.param3 = osMemHandle; if(tiIS_SPC(agRoot)) { agSMPFrame.outFrameLen = smp_pass_through_req->smp_req_len - 4; //Exclude crc osti_memcpy((void *)reqBuffer, (void *)(smp_pass_through_req->smp_req_resp), smp_pass_through_req->smp_req_len); } else { agSMPFrame.outFrameLen = smp_pass_through_req->smp_req_len - 8; //Exclude header and crc osti_memcpy((void *)reqBuffer, (void *)(smp_pass_through_req->smp_req_resp + 4), smp_pass_through_req->smp_req_len - 4); } } ostiMemoryStatus = ostiAllocMemory( tiRoot, &osMemHandle, (void **)&respBuffer, &(agSMPFrame.inFrameAddrUpper32), &(agSMPFrame.inFrameAddrLower32), 8, smp_pass_through_req->smp_resp_len + 4, agFALSE); if((ostiMemoryStatus != tiSuccess) && (respBuffer == agNULL )) return IOCTL_CALL_FAIL; osti_memset((void *)respBuffer, 0, smp_pass_through_req->smp_resp_len); // use FW control place in shared structure to keep the neccesary information tdsaAllShared->tdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.virtAddr = respBuffer; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)smp_pass_through_req->smp_req_resp + smp_pass_through_req->smp_req_len; tdsaAllShared->tdFWControlEx.len = smp_pass_through_req->smp_resp_len; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 1; status = IOCTL_CALL_PENDING; oneDeviceData = (tdsaDeviceData_t *)devHandle->tdData; if(saSendSMPIoctl(agRoot, oneDeviceData->agDevHandle, 0, &agSMPFrame, &ossaSMPIoctlCompleted) != AGSA_RC_SUCCESS) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; } return status; } osGLOBAL void ostiSendSMPIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload; agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); agIOCTLPayload->Status = (bit16)status; TI_DBG1(("ostiSendSMPIOCTLRsp: start, status = %d\n", status)); // if(tdsaAllShared->tdFWControlEx.param1 != agNULL) // { osti_memcpy((void *)(tdsaAllShared->tdFWControlEx.usrAddr), (void *)(tdsaAllShared->tdFWControlEx.virtAddr), tdsaAllShared->tdFWControlEx.len); // } ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.buffer, tdsaAllShared->tdFWControlEx.len); ostiFreeMemory(tiRoot, tdsaAllShared->tdFWControlEx.param3, tdsaAllShared->tdFWControlEx.len); //if(tdsaAllShared->tdFWControlEx.param1 != agNULL) // { ostiIOCTLComplete(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); // } } /***************************************************************************** * * tdsaSendBISTIoctl * * Purpose: This routine is called to get Forensic Data. * * Parameters: * tiRoot: Pointer to driver instance * agIOCTLPayload: Pointer to the IOCTL payload. * agParam1: Pointer to pass context handle for IOCTL DMA operation * agParam2: Pointer to pass context handle for IOCTL DMA operation * agParam3: Pointer to pass context handle for IOCTL DMA operation * * Return: * * IOCTL_CALL_SUCCESS The requested operation completed successfully. * IOCTL_CALL_FAIL Fail to complete the IOCTL request. * Detail error code is function specific and * defined by the specific IOCTL function. * IOCTL_CALL_PENDING This request is asynchronous and completed * in some other context. * IOCTL_CALL_INVALID_CODE This IOCTL function is not recognized. * * *****************************************************************************/ osGLOBAL bit32 tdsaSendBISTIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); tdBistPayload_t *pBistPayload; // bit32 length = 0; // bit32 status = IOCTL_CALL_SUCCESS; bit32 status = IOCTL_CALL_FAIL; pBistPayload = (tdBistPayload_t*)agIOCTLPayload->FunctionSpecificArea; tdsaAllShared->tdFWControlEx.buffer = agNULL; tdsaAllShared->tdFWControlEx.virtAddr = agNULL; tdsaAllShared->tdFWControlEx.usrAddr = (bit8*)&agIOCTLPayload->FunctionSpecificArea[0]; tdsaAllShared->tdFWControlEx.len = 0; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; tdsaAllShared->tdFWControlEx.payload = agIOCTLPayload; tdsaAllShared->tdFWControlEx.inProgress = 0; TI_DBG1(("tdsaSendBISTIoctl: Type %d Length %d Data %p\n", pBistPayload->testType, pBistPayload->testLength, pBistPayload->testData )); // pBistPayload->testtype = AGSA_BIST_TEST; if( pBistPayload->testType == AGSA_BIST_TEST) { if( pBistPayload->testLength != sizeof(agsaEncryptSelfTestBitMap_t)) { return status; } } else if( pBistPayload->testType == AGSA_SHA_TEST) { if( pBistPayload->testLength != sizeof(agsaEncryptSHATestDescriptor_t) ) { return status; } } else if( pBistPayload->testType == AGSA_HMAC_TEST ) { if( pBistPayload->testLength != sizeof(agsaEncryptHMACTestDescriptor_t)) { return status; } } /* GLOBAL bit32 saEncryptSelftestExecute( agsaRoot_t *agRoot, agsaContext_t *agContext, bit32 queueNum, bit32 type, bit32 length, void *TestDescriptor); */ if ( saEncryptSelftestExecute(agRoot, agNULL, 0, pBistPayload->testType, pBistPayload->testLength, pBistPayload->testData ) != AGSA_RC_SUCCESS ) { status = IOCTL_CALL_FAIL; } return status; } osGLOBAL bit32 tdsaSendTMFIoctl( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, unsigned long resetType ) { bit32 status; tmf_pass_through_req_t *tmf_req = (tmf_pass_through_req_t*)agIOCTLPayload->FunctionSpecificArea; #if !(defined(__FreeBSD__)) status = ostiSendResetDeviceIoctl(tiRoot, agParam2, tmf_req->pathId, tmf_req->targetId, tmf_req->lun, resetType); #endif TI_DBG3(("Status returned from ostiSendResetDeviceIoctl is %d\n",status)); if(status != IOCTL_CALL_SUCCESS) { agIOCTLPayload->Status = status; return status; } status = IOCTL_CALL_SUCCESS; return status; } #ifdef VPD_TESTING /* temporary to test saSetVPDCommand() and saGetVPDCommand */ osGLOBAL bit32 tdsaVPDSet( tiRoot_t *tiRoot ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); bit32 status = IOCTL_CALL_SUCCESS; agsaVPD_t VPDInfo; bit32 ret = AGSA_RC_SUCCESS; bit32 bufAddrUpper = 0; bit32 bufAddrLower = 0; tdVPDControl_t *VPDControl; void *osMemHandle = agNULL; void *buffer; bit32 timeCount=0; bit8 ioctlErr=0; bit8 VPDPayload[32]; bit8 i; TI_DBG2(("tdsaVPDSet: start\n")); for(i=0;itdFWControlEx.buffer = osMemHandle; tdsaAllShared->tdFWControlEx.param1 = agParam1; tdsaAllShared->tdFWControlEx.param2 = agParam2; /* for testing only */ tdsaAllShared->addrUpper = bufAddrUpper; tdsaAllShared->addrLower = bufAddrLower; ret = saSetVPDCommand(agRoot, agNULL, 0, &VPDInfo); if (ret == AGSA_RC_SUCCESS) { status = tiSuccess; } else { status = tiError; } ostiFreeMemory(tiRoot, osMemHandle, sizeof(VPDPayload)); return status; } /* temporary to test saSetVPDCommand() and saGetVPDCommand */ osGLOBAL bit32 tdsaVPDGet(tiRoot_t *tiRoot) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); bit32 status = IOCTL_CALL_SUCCESS; agsaVPD_t VPDInfo; bit32 ret = AGSA_RC_SUCCESS; TI_DBG2(("tdsaVPDGet: start\n")); osti_memset(&VPDInfo, 0, sizeof(agsaVPD_t)); /* direct mode worked */ VPDInfo.indirectMode = 0; /* direct mode */ VPDInfo.VPDDevice = 1; /* SEEPROM-1*/ VPDInfo.directLen = 32; VPDInfo.VPDOffset = 0; VPDInfo.directData = agNULL; VPDInfo.indirectAddrUpper32 = 0; VPDInfo.indirectAddrLower32 = 0; VPDInfo.indirectLen = 0; #ifdef NOT_YET /* worked; can't read VPD in ossaGetVPDResponseCB() because of indirect */ VPDInfo.indirectMode = 1; /* direct mode */ VPDInfo.VPDDevice = 1; /* SEEPROM-1*/ VPDInfo.directLen = 0; VPDInfo.VPDOffset = 0; VPDInfo.directData = agNULL; VPDInfo.indirectAddrUpper32 = tdsaAllShared->addrUpper; VPDInfo.indirectAddrLower32 = tdsaAllShared->addrLower; VPDInfo.indirectLen = 32; #endif ret = saGetVPDCommand(agRoot, agNULL, 0, &VPDInfo); if (ret == AGSA_RC_SUCCESS) { status = tiSuccess; } else { status = tiError; } return status; } #endif /***************************************************************************** * * tdsaGetNumOfLUNIOCTL * * Purpose: This routine is called to send Report LUN SSP command request. * * Parameters: * tiRoot: Pointer to driver instance * tiIOCTLPayload_t: Status of the Controller Reset. * agParam1: Void pointer to device extension * agParam2: Void pointer to SRB * agParam3: NULL * * Return: status * * *****************************************************************************/ osGLOBAL bit32 tdsaGetNumOfLUNIOCTL( tiRoot_t *tiRoot, tiIOCTLPayload_t *agIOCTLPayload, void *agParam1, void *agParam2, void *agParam3 ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; agsaRoot_t *agRoot = &(tdsaAllShared->agRootInt); tdDeviceLUNInfoIOCTL_t *pDeviceLUNInfo = agNULL; tiDeviceHandle_t *devHandle = agNULL; void *tiRequestBody = agNULL; tiIORequest_t *tiIORequest = agNULL; bit32 status = IOCTL_CALL_SUCCESS; TI_DBG2(("tdsaGetNumOfLUNIOCTL: Start\n")); do { pDeviceLUNInfo = (tdDeviceLUNInfoIOCTL_t*)agIOCTLPayload->FunctionSpecificArea; if (agIOCTLPayload->Length < sizeof(tdDeviceLUNInfoIOCTL_t)) { status = IOCTL_CALL_FAIL; break; } if(!pDeviceLUNInfo->tiDeviceHandle) { status = IOCTL_CALL_FAIL; agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; break; } devHandle = (tiDeviceHandle_t*)pDeviceLUNInfo->tiDeviceHandle; agIOCTLPayload->Status = IOCTL_ERR_STATUS_OK; status = ostiNumOfLUNIOCTLreq(tiRoot,agParam1,agParam2,&tiRequestBody,&tiIORequest); if(status != AGSA_RC_SUCCESS) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; break; } status = tiNumOfLunIOCTLreq(tiRoot,tiIORequest,devHandle,tiRequestBody,agIOCTLPayload,agParam1,agParam2); if(status != AGSA_RC_SUCCESS) { agIOCTLPayload->Status = IOCTL_ERR_STATUS_INTERNAL_ERROR; break; } // ostiIOCTLWaitForSignal (tiRoot, agParam1, agParam2, agParam3); }while(0); TI_DBG2(("tdsaGetNumOfLUNIOCTL: End\n")); return status; } /***************************************************************************** * * ostiNumOfLUNIOCTLRsp * * Purpose: This routine is called when a Report LUN SSP command response id recieved. * * Parameters: * tiRoot: Pointer to driver instance * bit32 status * * Return: none * * *****************************************************************************/ osGLOBAL void ostiNumOfLUNIOCTLRsp( tiRoot_t *tiRoot, bit32 status ) { tdsaRoot_t *tdsaRoot = (tdsaRoot_t *) tiRoot->tdData; tdsaContext_t *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared; tiIOCTLPayload_t *agIOCTLPayload; tdDeviceLUNInfoIOCTL_t *pDeviceLUNInfo = NULL; bit32 count = 0; bit32 numOfLUN =0; TI_DBG1(("ostiNumOfLUNIOCTLRsp: start, status = %d\n", status)); if(tdsaAllShared->tdFWControlEx.inProgress == 1) { agIOCTLPayload = (tiIOCTLPayload_t *)(tdsaAllShared->tdFWControlEx.payload); if ((agIOCTLPayload) && (PMC_IOCTL_SIGNATURE == agIOCTLPayload->Signature)&& (IOCTL_MJ_GET_DEVICE_LUN == agIOCTLPayload->MajorFunction)) { agIOCTLPayload->Status = (bit16)status; pDeviceLUNInfo = (tdDeviceLUNInfoIOCTL_t*)agIOCTLPayload->FunctionSpecificArea; numOfLUN = ((tdsaAllShared->tdFWControlEx.virtAddr[0] << 24)|(tdsaAllShared->tdFWControlEx.virtAddr[1] << 16)|\ (tdsaAllShared->tdFWControlEx.virtAddr[2] << 8)|(tdsaAllShared->tdFWControlEx.virtAddr[3])); numOfLUN = numOfLUN/8; pDeviceLUNInfo->numOfLun = numOfLUN; // ostiFreeMemory(tiRoot, // tdsaAllShared->tdFWControlEx.virtAddr, // tdsaAllShared->tdFWControlEx.len); // if(tdsaAllShared->tdFWControlEx.param1 != agNULL) // { ostiIOCTLSetSignal(tiRoot, tdsaAllShared->tdFWControlEx.param1, tdsaAllShared->tdFWControlEx.param2, NULL); tdsaAllShared->tdFWControlEx.payload = NULL; // } tdsaAllShared->tdFWControlEx.inProgress = 0; } } TI_DBG1(("ostiNumOfLUNIOCTLRsp: End\n")); }