/******************************************************************************* *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 * * $RCSfile: ttdsmp.c,v $ * * Copyright 2006 PMC-Sierra, Inc. * * $Author: hasungwo $ * $Revision: 112322 $ * $Date: 2012-01-04 19:23:42 -0800 (Wed, 04 Jan 2012) $ * * This file contains initiator IO related functions in TD layer * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef INITIATOR_DRIVER #include #include #include #endif #ifdef TARGET_DRIVER #include "ttdglobl.h" #include "ttdtxchg.h" #include "ttdtypes.h" #endif #include #include osGLOBAL void ttdsaSMPCompleted( agsaRoot_t *agRoot, agsaIORequest_t *agIORequest, bit32 agIOStatus, //agsaSMPFrameHeader_t *agFrameHeader, //(TP) bit32 agIOInfoLen, agsaFrameHandle_t agFrameHandle ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; ttdsaXchg_t *ttdsaXchg = (ttdsaXchg_t *)agIORequest->osData; /* cf) ttdsaIOCompleted */ TI_DBG1(("ttdsaSMPCompleted: start\n")); if (tiRoot == agNULL) { TI_DBG1(("ttdsaSMPCompleted: tiRoot is NULL, wrong\n")); return; } if (ttdsaXchg == agNULL) { TI_DBG1(("ttdsaSMPCompleted: ttdsaXchg is NULL, wrong\n")); return; } ttdsaXchgFreeStruct(tiRoot,ttdsaXchg); /* to-do: no callback to OS layer */ return; } osGLOBAL void ttdsaNotSupportRespSend( agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, ttdsaXchg_t *ttdsaXchg, bit8 smpfn ) { bit32 agRequestType; agsaSASRequestBody_t *agSASRequestBody; agsaSMPFrame_t *agSMPFrame; agsaIORequest_t *agIORequest; bit8 SMPPayload[SMP_DIRECT_PAYLOAD_LIMIT]; /*(TP)*/ tdssSMPFrameHeader_t tdSMPFrameHeader; /*(TP)*/ TI_DBG1(("ttdsaNotSupportSend:\n")); agRequestType = AGSA_SMP_TGT_RESPONSE; agIORequest = &(ttdsaXchg->SMPRequestBody.agIORequest); agSASRequestBody = &(ttdsaXchg->SMPRequestBody.agSASRequestBody); agSMPFrame = &(agSASRequestBody->smpFrame); osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t)); /*(TP)*/ /* smp header */ /*(TP)*/ tdSMPFrameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */ tdSMPFrameHeader.smpFunction = smpfn; tdSMPFrameHeader.smpFunctionResult = UNKNOWN_SMP_FUNCTION; /* unknown smp */ tdSMPFrameHeader.smpReserved = 0; /*old*/ //agSMPFrame->frameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */ //agSMPFrame->frameHeader.smpFunction = smpfn; //agSMPFrame->frameHeader.smpFunctionResult = UNKNOWN_SMP_FUNCTION; /* unknown smp */ osti_memcpy(SMPPayload, &tdSMPFrameHeader, 4); /*TP)*/ agSMPFrame->outFrameBuf = SMPPayload; /*(TP)*/ agSMPFrame->outFrameAddrUpper32 = ttdsaXchg->smpresp.phyAddrUpper; agSMPFrame->outFrameAddrLower32 = ttdsaXchg->smpresp.phyAddrLower; agSMPFrame->outFrameLen = 0; /* no smp response payload */ //agSMPFrame->phyId = ttdsaXchg->SMPphyId; #ifdef RPM_SOC /* not work yet because of high priority q */ saSMPStart( agRoot, agIORequest, agDevHandle, agRequestType, agSASRequestBody, &ossaSMPCompleted ); #else saSMPStart( agRoot, agIORequest, 0, /* queue number */ agDevHandle, agRequestType, agSASRequestBody, &ossaSMPCompleted ); #endif return; } osGLOBAL void ttdsaDiscoverRespSend( agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, ttdsaXchg_t *ttdsaXchg ) { bit32 agRequestType; agsaSASRequestBody_t *agSASRequestBody; agsaSMPFrame_t *agSMPFrame; smpRespDiscover_t *Resp; smp_resp_t *SMPResp; agsaIORequest_t *agIORequest; bit8 SMPPayload[SMP_DIRECT_PAYLOAD_LIMIT]; /*(TP)*/ tdssSMPFrameHeader_t tdSMPFrameHeader; /*(TP)*/ TI_DBG1(("ttdsaDiscoverRespSend:\n")); agRequestType = AGSA_SMP_TGT_RESPONSE; SMPResp = (smp_resp_t *)ttdsaXchg->smpresp.virtAddr; agIORequest = &(ttdsaXchg->SMPRequestBody.agIORequest); agSASRequestBody = &(ttdsaXchg->SMPRequestBody.agSASRequestBody); agSMPFrame = &(agSASRequestBody->smpFrame); osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t)); /*(TP)*/ /* smp header */ /*(TP)*/ tdSMPFrameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */ tdSMPFrameHeader.smpFunction = SMP_DISCOVER; /* discover */ tdSMPFrameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED; tdSMPFrameHeader.smpReserved = 0; /*old*/ //agSMPFrame->frameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */ //agSMPFrame->frameHeader.smpFunction = SMP_DISCOVER; /* discover */ //agSMPFrame->frameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED; osti_memcpy(SMPPayload, &tdSMPFrameHeader, 4); /*TP)*/ agSMPFrame->outFrameBuf = SMPPayload; /*(TP)*/ agSMPFrame->outFrameAddrUpper32 = ttdsaXchg->smpresp.phyAddrUpper; agSMPFrame->outFrameAddrLower32 = ttdsaXchg->smpresp.phyAddrLower; agSMPFrame->outFrameLen = sizeof(smpRespDiscover_t); //agSMPFrame->phyId = ttdsaXchg->SMPphyId; /* smp response payload */ Resp = (smpRespDiscover_t *)&(SMPResp->RespData); osti_memset(Resp, 0, sizeof(smpRespDiscover_t)); /* temp, hardcode smp discover response */ /* needs to read contents from ID frame */ /* assumption: for now, attached to edge expander */ Resp->phyIdentifier = 0; Resp->attachedDeviceType = SAS_EDGE_EXPANDER_DEVICE; Resp->negotiatedPhyLinkRate = 0x9; /* enabled, 1.5G */ Resp->attached_Ssp_Stp_Smp_Sata_Initiator = 0; Resp->attached_SataPS_Ssp_Stp_Smp_Sata_Target = 0x2; /* SMP target */ Resp->sasAddressHi[3] = 0x01; Resp->sasAddressHi[2] = 0x02; Resp->sasAddressHi[1] = 0x03; Resp->sasAddressHi[0] = 0x04; Resp->sasAddressLo[3] = 0x05; Resp->sasAddressLo[2] = 0x06; Resp->sasAddressLo[1] = 0x07; Resp->sasAddressLo[0] = 0x08; Resp->attachedSasAddressHi[3] = 0x01; Resp->attachedSasAddressHi[2] = 0x01; Resp->attachedSasAddressHi[1] = 0x01; Resp->attachedSasAddressHi[0] = 0x01; Resp->attachedSasAddressLo[3] = 0x02; Resp->attachedSasAddressLo[2] = 0x02; Resp->attachedSasAddressLo[1] = 0x02; Resp->attachedSasAddressLo[0] = 0x02; Resp->attachedPhyIdentifier = 0; Resp->programmedAndHardware_MinPhyLinkRate = 0x8; /* not programmable and 1.5 G */ Resp->programmedAndHardware_MaxPhyLinkRate = 0x8; /* not programmable and 1.5 G */ Resp->phyChangeCount = 0; /* No broadcast(Change) received */ Resp->virtualPhy_partialPathwayTimeout = 0x7; /* no virutal phy and see spec 10.4.3.5, p 404 rev 7 */ Resp->routingAttribute = 0; osti_memset(&Resp->reserved13, 0, 5); osti_memset(&Resp->vendorSpecific, 0, 2); #ifdef RPM_SOC /* not work yet because of high priority q */ saSMPStart( agRoot, agIORequest, agDevHandle, agRequestType, agSASRequestBody, &ossaSMPCompleted ); #else saSMPStart( agRoot, agIORequest, 0, /* queue number */ agDevHandle, agRequestType, agSASRequestBody, &ossaSMPCompleted ); #endif return; } osGLOBAL void ttdsaReportGeneralRespSend( agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, ttdsaXchg_t *ttdsaXchg ) { bit32 agRequestType; agsaSASRequestBody_t *agSASRequestBody; agsaSMPFrame_t *agSMPFrame; smpRespReportGeneral_t *Resp; smp_resp_t *SMPResp; agsaIORequest_t *agIORequest; bit8 SMPPayload[SMP_DIRECT_PAYLOAD_LIMIT]; /*(TP)*/ tdssSMPFrameHeader_t tdSMPFrameHeader; /*(TP)*/ TI_DBG1(("ttdsaReportGeneralRespSend:\n")); agRequestType = AGSA_SMP_TGT_RESPONSE; SMPResp = (smp_resp_t *)ttdsaXchg->smpresp.virtAddr; agIORequest = &(ttdsaXchg->SMPRequestBody.agIORequest); agSASRequestBody = &(ttdsaXchg->SMPRequestBody.agSASRequestBody); agSMPFrame = &(agSASRequestBody->smpFrame); osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t)); /*(TP)*/ tdSMPFrameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */ tdSMPFrameHeader.smpFunction = SMP_REPORT_GENERAL; /* report general */ tdSMPFrameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED; tdSMPFrameHeader.smpReserved = 0; /*old*/ //agSMPFrame->frameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */ //agSMPFrame->frameHeader.smpFunction = SMP_REPORT_GENERAL; /* report general */ //agSMPFrame->frameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED; osti_memcpy(SMPPayload, &tdSMPFrameHeader, 4); /*(TP)*/ agSMPFrame->outFrameBuf = SMPPayload; /*(TP)*/ agSMPFrame->outFrameAddrUpper32 = ttdsaXchg->smpresp.phyAddrUpper; agSMPFrame->outFrameAddrLower32 = ttdsaXchg->smpresp.phyAddrLower; agSMPFrame->outFrameLen = sizeof(smpRespReportGeneral_t); //agSMPFrame->phyId = ttdsaXchg->SMPphyId; /* smp response payload */ Resp = (smpRespReportGeneral_t *)&(SMPResp->RespData); osti_memset(Resp, 0, sizeof(smpRespReportGeneral_t)); /* temp, hardcode smp general response */ Resp->expanderChangeCount16[0] = 1; Resp->expanderRouteIndexes16[0] = 2; Resp->numOfPhys = 0x5; /* 0x1; */ Resp->configuring_configurable = 0; tdhexdump("smp general response", (bit8 *)Resp, sizeof(smpRespReportGeneral_t)); #ifdef RPM_SOC /* not work yet because of high priority q */ saSMPStart( agRoot, agIORequest, agDevHandle, agRequestType, agSASRequestBody, &ossaSMPCompleted ); #else saSMPStart( agRoot, agIORequest, 0, /* queue number */ agDevHandle, agRequestType, agSASRequestBody, &ossaSMPCompleted ); #endif return; } osGLOBAL void ttdsaSMPReqReceived( agsaRoot_t *agRoot, agsaDevHandle_t *agDevHandle, agsaSMPFrameHeader_t *agFrameHeader, agsaFrameHandle_t agFrameHandle, bit32 agFrameLength, bit32 phyId ) { tdsaRootOsData_t *osData = (tdsaRootOsData_t *)agRoot->osData; tiRoot_t *tiRoot = (tiRoot_t *)osData->tiRoot; ttdsaXchg_t *ttdsaXchg; tdsaDeviceData_t *oneDeviceData = agNULL; TI_DBG1(("ttdsaSMPReqReceived: start\n")); oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData; if (oneDeviceData == agNULL) { TI_DBG1(("ttdsaSMPReqReceived: no device data\n")); return; } ttdsaXchg = ttdsaXchgGetStruct(agRoot); if (ttdsaXchg == agNULL) { TI_DBG1(("ttdsaSMPReqReceived: no free xchg structures\n")); return; } oneDeviceData->agDevHandle = agDevHandle; oneDeviceData->agRoot = agRoot; /* saving the device */ ttdsaXchg->DeviceData = oneDeviceData; ttdsaXchg->agRoot = agRoot; ttdsaXchg->tiRoot = tiRoot; ttdsaXchg->SMPRequestBody.agIORequest.sdkData = agNULL; ttdsaXchg->SMPphyId = phyId; switch ( agFrameHeader->smpFunction ) { case SMP_REPORT_GENERAL: { /* must spec p392, rev7*/ TI_DBG1(("ttdsaSMPReqReceived: REPORT_GENERAL\n")); ttdsaReportGeneralRespSend(agRoot, agDevHandle, ttdsaXchg); break; } case SMP_REPORT_MANUFACTURE_INFORMATION: { /* optional, spec p394, rev7*/ TI_DBG1(("ttdsaSMPReqReceived: REPORT_MANUFACTURE_INFORMATION\n")); ttdsaNotSupportRespSend(agRoot, agDevHandle, ttdsaXchg, SMP_REPORT_MANUFACTURE_INFORMATION); break; } case SMP_DISCOVER: { /* must, spec p398, rev7*/ TI_DBG1(("ttdsaSMPReqReceived: DISCOVER\n")); ttdsaDiscoverRespSend(agRoot, agDevHandle, ttdsaXchg); break; } default: { TI_DBG1(("ttdsaSMPReqReceived: UKNOWN or not yet supported 0x%x\n", agFrameHeader->smpFunction)); ttdsaNotSupportRespSend(agRoot, agDevHandle, ttdsaXchg, (bit8) agFrameHeader->smpFunction); break; } } return; }