1/*******************************************************************************
2*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3*
4*Redistribution and use in source and binary forms, with or without modification, are permitted provided
5*that the following conditions are met:
6*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7*following disclaimer.
8*2. Redistributions in binary form must reproduce the above copyright notice,
9*this list of conditions and the following disclaimer in the documentation and/or other materials provided
10*with the distribution.
11*
12*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20
21********************************************************************************/
22/*******************************************************************************/
23/** \file
24 *
25 * $RCSfile: ttdsmp.c,v $
26 *
27 * Copyright 2006 PMC-Sierra, Inc.
28 *
29 * $Author: hasungwo $
30 * $Revision: 112322 $
31 * $Date: 2012-01-04 19:23:42 -0800 (Wed, 04 Jan 2012) $
32 *
33 * This file contains initiator IO related functions in TD layer
34 *
35 */
36#include <osenv.h>
37#include <ostypes.h>
38#include <osdebug.h>
39
40#include <sa.h>
41#include <saapi.h>
42#include <saosapi.h>
43
44#include <titypes.h>
45#include <ostiapi.h>
46#include <tiapi.h>
47#include <tiglobal.h>
48
49#include <tdtypes.h>
50#include <osstring.h>
51#include <tdutil.h>
52
53#ifdef INITIATOR_DRIVER
54#include <itdtypes.h>
55#include <itddefs.h>
56#include <itdglobl.h>
57#endif
58
59#ifdef TARGET_DRIVER
60#include "ttdglobl.h"
61#include "ttdtxchg.h"
62#include "ttdtypes.h"
63#endif
64
65#include <tdsatypes.h>
66#include <tdproto.h>
67
68osGLOBAL void
69ttdsaSMPCompleted(
70                  agsaRoot_t            *agRoot,
71                  agsaIORequest_t       *agIORequest,
72                  bit32                 agIOStatus,
73                  //agsaSMPFrameHeader_t  *agFrameHeader, //(TP)
74                  bit32                 agIOInfoLen,
75                  agsaFrameHandle_t     agFrameHandle
76                 )
77{
78  tdsaRootOsData_t       *osData = (tdsaRootOsData_t *)agRoot->osData;
79  tiRoot_t               *tiRoot = (tiRoot_t *)osData->tiRoot;
80  ttdsaXchg_t            *ttdsaXchg    = (ttdsaXchg_t *)agIORequest->osData;
81
82  /* cf) ttdsaIOCompleted */
83  TI_DBG1(("ttdsaSMPCompleted: start\n"));
84  if (tiRoot == agNULL)
85  {
86    TI_DBG1(("ttdsaSMPCompleted: tiRoot is NULL, wrong\n"));
87    return;
88  }
89
90  if (ttdsaXchg == agNULL)
91  {
92    TI_DBG1(("ttdsaSMPCompleted: ttdsaXchg is NULL, wrong\n"));
93    return;
94  }
95
96  ttdsaXchgFreeStruct(tiRoot,ttdsaXchg);
97
98
99  /* to-do: no callback to OS layer */
100  return;
101}
102
103osGLOBAL void
104ttdsaNotSupportRespSend(
105                        agsaRoot_t            *agRoot,
106                        agsaDevHandle_t       *agDevHandle,
107                        ttdsaXchg_t           *ttdsaXchg,
108                        bit8                  smpfn
109                        )
110{
111  bit32                     agRequestType;
112  agsaSASRequestBody_t      *agSASRequestBody;
113  agsaSMPFrame_t            *agSMPFrame;
114  agsaIORequest_t           *agIORequest;
115  bit8                       SMPPayload[SMP_DIRECT_PAYLOAD_LIMIT];    /*(TP)*/
116  tdssSMPFrameHeader_t       tdSMPFrameHeader;              /*(TP)*/
117
118  TI_DBG1(("ttdsaNotSupportSend:\n"));
119  agRequestType = AGSA_SMP_TGT_RESPONSE;
120
121  agIORequest = &(ttdsaXchg->SMPRequestBody.agIORequest);
122
123  agSASRequestBody = &(ttdsaXchg->SMPRequestBody.agSASRequestBody);
124  agSMPFrame = &(agSASRequestBody->smpFrame);
125
126  osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));    /*(TP)*/
127
128  /* smp header */                            /*(TP)*/
129  tdSMPFrameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */
130  tdSMPFrameHeader.smpFunction = smpfn;
131  tdSMPFrameHeader.smpFunctionResult = UNKNOWN_SMP_FUNCTION; /* unknown smp */
132  tdSMPFrameHeader.smpReserved = 0;
133
134  /*old*/
135  //agSMPFrame->frameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */
136  //agSMPFrame->frameHeader.smpFunction = smpfn;
137  //agSMPFrame->frameHeader.smpFunctionResult = UNKNOWN_SMP_FUNCTION; /* unknown smp */
138
139  osti_memcpy(SMPPayload, &tdSMPFrameHeader, 4);            /*TP)*/
140
141  agSMPFrame->outFrameBuf = SMPPayload;                 /*(TP)*/
142  agSMPFrame->outFrameAddrUpper32 = ttdsaXchg->smpresp.phyAddrUpper;
143  agSMPFrame->outFrameAddrLower32 = ttdsaXchg->smpresp.phyAddrLower;
144  agSMPFrame->outFrameLen = 0; /* no smp response payload */
145
146  //agSMPFrame->phyId = ttdsaXchg->SMPphyId;
147
148#ifdef RPM_SOC
149  /* not work yet because of high priority q */
150  saSMPStart(
151             agRoot,
152             agIORequest,
153             agDevHandle,
154             agRequestType,
155             agSASRequestBody,
156             &ossaSMPCompleted
157             );
158#else
159  saSMPStart(
160             agRoot,
161             agIORequest,
162             0, /* queue number */
163             agDevHandle,
164             agRequestType,
165             agSASRequestBody,
166             &ossaSMPCompleted
167             );
168#endif
169  return;
170}
171
172osGLOBAL void
173ttdsaDiscoverRespSend(
174                      agsaRoot_t            *agRoot,
175                      agsaDevHandle_t       *agDevHandle,
176                      ttdsaXchg_t           *ttdsaXchg
177                      )
178{
179  bit32                     agRequestType;
180  agsaSASRequestBody_t      *agSASRequestBody;
181  agsaSMPFrame_t            *agSMPFrame;
182  smpRespDiscover_t         *Resp;
183  smp_resp_t                *SMPResp;
184  agsaIORequest_t           *agIORequest;
185  bit8                       SMPPayload[SMP_DIRECT_PAYLOAD_LIMIT];    /*(TP)*/
186  tdssSMPFrameHeader_t       tdSMPFrameHeader;              /*(TP)*/
187
188  TI_DBG1(("ttdsaDiscoverRespSend:\n"));
189
190  agRequestType = AGSA_SMP_TGT_RESPONSE;
191
192  SMPResp = (smp_resp_t *)ttdsaXchg->smpresp.virtAddr;
193
194  agIORequest = &(ttdsaXchg->SMPRequestBody.agIORequest);
195
196  agSASRequestBody = &(ttdsaXchg->SMPRequestBody.agSASRequestBody);
197  agSMPFrame = &(agSASRequestBody->smpFrame);
198
199  osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));    /*(TP)*/
200
201  /* smp header */                          /*(TP)*/
202  tdSMPFrameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */
203  tdSMPFrameHeader.smpFunction = SMP_DISCOVER; /* discover */
204  tdSMPFrameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED;
205  tdSMPFrameHeader.smpReserved = 0;
206
207  /*old*/
208  //agSMPFrame->frameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */
209  //agSMPFrame->frameHeader.smpFunction = SMP_DISCOVER; /* discover */
210  //agSMPFrame->frameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED;
211
212  osti_memcpy(SMPPayload, &tdSMPFrameHeader, 4);            /*TP)*/
213
214  agSMPFrame->outFrameBuf = SMPPayload;                 /*(TP)*/
215  agSMPFrame->outFrameAddrUpper32 = ttdsaXchg->smpresp.phyAddrUpper;
216  agSMPFrame->outFrameAddrLower32 = ttdsaXchg->smpresp.phyAddrLower;
217  agSMPFrame->outFrameLen = sizeof(smpRespDiscover_t);
218
219  //agSMPFrame->phyId = ttdsaXchg->SMPphyId;
220
221  /* smp response payload */
222  Resp = (smpRespDiscover_t *)&(SMPResp->RespData);
223  osti_memset(Resp, 0, sizeof(smpRespDiscover_t));
224  /* temp, hardcode smp discover response */
225  /* needs to read contents from ID frame */
226  /* assumption: for now, attached to edge expander */
227  Resp->phyIdentifier = 0;
228  Resp->attachedDeviceType = SAS_EDGE_EXPANDER_DEVICE;
229  Resp->negotiatedPhyLinkRate = 0x9; /* enabled, 1.5G */
230  Resp->attached_Ssp_Stp_Smp_Sata_Initiator = 0;
231  Resp->attached_SataPS_Ssp_Stp_Smp_Sata_Target = 0x2; /* SMP target */
232  Resp->sasAddressHi[3] = 0x01;
233  Resp->sasAddressHi[2] = 0x02;
234  Resp->sasAddressHi[1] = 0x03;
235  Resp->sasAddressHi[0] = 0x04;
236  Resp->sasAddressLo[3] = 0x05;
237  Resp->sasAddressLo[2] = 0x06;
238  Resp->sasAddressLo[1] = 0x07;
239  Resp->sasAddressLo[0] = 0x08;
240
241  Resp->attachedSasAddressHi[3] = 0x01;
242  Resp->attachedSasAddressHi[2] = 0x01;
243  Resp->attachedSasAddressHi[1] = 0x01;
244  Resp->attachedSasAddressHi[0] = 0x01;
245  Resp->attachedSasAddressLo[3] = 0x02;
246  Resp->attachedSasAddressLo[2] = 0x02;
247  Resp->attachedSasAddressLo[1] = 0x02;
248  Resp->attachedSasAddressLo[0] = 0x02;
249
250  Resp->attachedPhyIdentifier = 0;
251  Resp->programmedAndHardware_MinPhyLinkRate = 0x8; /* not programmable and 1.5 G */
252  Resp->programmedAndHardware_MaxPhyLinkRate = 0x8; /* not programmable and 1.5 G */
253  Resp->phyChangeCount = 0; /* No broadcast(Change) received */
254  Resp->virtualPhy_partialPathwayTimeout = 0x7; /* no virutal phy and see spec 10.4.3.5, p 404 rev 7 */
255  Resp->routingAttribute = 0;
256  osti_memset(&Resp->reserved13, 0, 5);
257  osti_memset(&Resp->vendorSpecific, 0, 2);
258
259#ifdef RPM_SOC
260  /* not work yet because of high priority q */
261  saSMPStart(
262             agRoot,
263             agIORequest,
264             agDevHandle,
265             agRequestType,
266             agSASRequestBody,
267             &ossaSMPCompleted
268             );
269#else
270  saSMPStart(
271             agRoot,
272             agIORequest,
273             0, /* queue number */
274             agDevHandle,
275             agRequestType,
276             agSASRequestBody,
277             &ossaSMPCompleted
278             );
279#endif
280  return;
281}
282
283osGLOBAL void
284ttdsaReportGeneralRespSend(
285                           agsaRoot_t            *agRoot,
286                           agsaDevHandle_t       *agDevHandle,
287                           ttdsaXchg_t           *ttdsaXchg
288                           )
289{
290  bit32                     agRequestType;
291  agsaSASRequestBody_t      *agSASRequestBody;
292  agsaSMPFrame_t            *agSMPFrame;
293  smpRespReportGeneral_t    *Resp;
294  smp_resp_t                *SMPResp;
295  agsaIORequest_t           *agIORequest;
296  bit8                       SMPPayload[SMP_DIRECT_PAYLOAD_LIMIT];    /*(TP)*/
297  tdssSMPFrameHeader_t       tdSMPFrameHeader;              /*(TP)*/
298
299  TI_DBG1(("ttdsaReportGeneralRespSend:\n"));
300
301  agRequestType = AGSA_SMP_TGT_RESPONSE;
302
303  SMPResp = (smp_resp_t *)ttdsaXchg->smpresp.virtAddr;
304
305  agIORequest = &(ttdsaXchg->SMPRequestBody.agIORequest);
306
307  agSASRequestBody = &(ttdsaXchg->SMPRequestBody.agSASRequestBody);
308  agSMPFrame = &(agSASRequestBody->smpFrame);
309
310  osti_memset(&tdSMPFrameHeader, 0, sizeof(tdssSMPFrameHeader_t));    /*(TP)*/
311
312  tdSMPFrameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */
313  tdSMPFrameHeader.smpFunction = SMP_REPORT_GENERAL; /* report general */
314  tdSMPFrameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED;
315  tdSMPFrameHeader.smpReserved = 0;
316
317  /*old*/
318  //agSMPFrame->frameHeader.smpFrameType = SMP_RESPONSE; /* SMP response */
319  //agSMPFrame->frameHeader.smpFunction = SMP_REPORT_GENERAL; /* report general */
320  //agSMPFrame->frameHeader.smpFunctionResult = SMP_FUNCTION_ACCEPTED;
321
322  osti_memcpy(SMPPayload, &tdSMPFrameHeader, 4);            /*(TP)*/
323
324  agSMPFrame->outFrameBuf = SMPPayload;                 /*(TP)*/
325  agSMPFrame->outFrameAddrUpper32 = ttdsaXchg->smpresp.phyAddrUpper;
326  agSMPFrame->outFrameAddrLower32 = ttdsaXchg->smpresp.phyAddrLower;
327  agSMPFrame->outFrameLen = sizeof(smpRespReportGeneral_t);
328
329  //agSMPFrame->phyId = ttdsaXchg->SMPphyId;
330
331  /* smp response payload */
332  Resp = (smpRespReportGeneral_t *)&(SMPResp->RespData);
333  osti_memset(Resp, 0, sizeof(smpRespReportGeneral_t));
334  /* temp, hardcode smp general response */
335  Resp->expanderChangeCount16[0] = 1;
336  Resp->expanderRouteIndexes16[0] = 2;
337  Resp->numOfPhys = 0x5; /* 0x1; */
338  Resp->configuring_configurable = 0;
339  tdhexdump("smp general response", (bit8 *)Resp, sizeof(smpRespReportGeneral_t));
340
341#ifdef RPM_SOC
342  /* not work yet because of high priority q */
343  saSMPStart(
344             agRoot,
345             agIORequest,
346             agDevHandle,
347             agRequestType,
348             agSASRequestBody,
349              &ossaSMPCompleted
350             );
351 #else
352  saSMPStart(
353             agRoot,
354             agIORequest,
355             0, /* queue number */
356             agDevHandle,
357             agRequestType,
358             agSASRequestBody,
359             &ossaSMPCompleted
360             );
361#endif
362  return;
363}
364
365
366osGLOBAL void
367ttdsaSMPReqReceived(
368                    agsaRoot_t            *agRoot,
369                    agsaDevHandle_t       *agDevHandle,
370                    agsaSMPFrameHeader_t  *agFrameHeader,
371                    agsaFrameHandle_t     agFrameHandle,
372                    bit32                 agFrameLength,
373                    bit32                 phyId
374                    )
375{
376  tdsaRootOsData_t       *osData = (tdsaRootOsData_t *)agRoot->osData;
377  tiRoot_t               *tiRoot = (tiRoot_t *)osData->tiRoot;
378  ttdsaXchg_t            *ttdsaXchg;
379  tdsaDeviceData_t       *oneDeviceData = agNULL;
380
381
382  TI_DBG1(("ttdsaSMPReqReceived: start\n"));
383
384  oneDeviceData = (tdsaDeviceData_t *)agDevHandle->osData;
385
386  if (oneDeviceData == agNULL)
387  {
388    TI_DBG1(("ttdsaSMPReqReceived: no device data\n"));
389    return;
390  }
391
392  ttdsaXchg = ttdsaXchgGetStruct(agRoot);
393
394  if (ttdsaXchg == agNULL)
395  {
396    TI_DBG1(("ttdsaSMPReqReceived: no free xchg structures\n"));
397    return;
398  }
399
400
401  oneDeviceData->agDevHandle = agDevHandle;
402  oneDeviceData->agRoot = agRoot;
403
404  /* saving the device */
405  ttdsaXchg->DeviceData = oneDeviceData;
406
407  ttdsaXchg->agRoot  = agRoot;
408  ttdsaXchg->tiRoot  = tiRoot;
409
410  ttdsaXchg->SMPRequestBody.agIORequest.sdkData = agNULL;
411
412  ttdsaXchg->SMPphyId = phyId;
413
414  switch ( agFrameHeader->smpFunction )
415  {
416  case SMP_REPORT_GENERAL:
417  {
418    /* must spec p392, rev7*/
419    TI_DBG1(("ttdsaSMPReqReceived: REPORT_GENERAL\n"));
420    ttdsaReportGeneralRespSend(agRoot, agDevHandle, ttdsaXchg);
421    break;
422  }
423  case SMP_REPORT_MANUFACTURE_INFORMATION:
424  {
425    /* optional, spec p394, rev7*/
426    TI_DBG1(("ttdsaSMPReqReceived: REPORT_MANUFACTURE_INFORMATION\n"));
427    ttdsaNotSupportRespSend(agRoot, agDevHandle, ttdsaXchg, SMP_REPORT_MANUFACTURE_INFORMATION);
428    break;
429  }
430  case SMP_DISCOVER:
431  {
432    /* must, spec p398, rev7*/
433    TI_DBG1(("ttdsaSMPReqReceived: DISCOVER\n"));
434    ttdsaDiscoverRespSend(agRoot, agDevHandle, ttdsaXchg);
435    break;
436  }
437  default:
438  {
439    TI_DBG1(("ttdsaSMPReqReceived: UKNOWN or not yet supported 0x%x\n", agFrameHeader->smpFunction));
440    ttdsaNotSupportRespSend(agRoot, agDevHandle, ttdsaXchg, (bit8) agFrameHeader->smpFunction);
441    break;
442  }
443  }
444
445  return;
446}
447