root/sys/dev/pms/RefTisa/tisa/sassata/sas/tgt/ttdsmp.c
/*******************************************************************************
*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 <osenv.h>
#include <ostypes.h>
#include <osdebug.h>

#include <sa.h>
#include <saapi.h>
#include <saosapi.h>

#include <titypes.h>
#include <ostiapi.h>
#include <tiapi.h>
#include <tiglobal.h>

#include <tdtypes.h>
#include <osstring.h>
#include <tdutil.h>

#ifdef INITIATOR_DRIVER
#include <itdtypes.h>
#include <itddefs.h>
#include <itdglobl.h>
#endif

#ifdef TARGET_DRIVER
#include "ttdglobl.h"
#include "ttdtxchg.h"
#include "ttdtypes.h"
#endif

#include <tdsatypes.h>
#include <tdproto.h>

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;
}