ttdinit.c revision 285809
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/** \file
23 *
24 * $RCSfile: ttdinit.c,v $
25 *
26 * Copyright 2006 PMC-Sierra, Inc.
27 *
28 * $Author: vempatin $
29 * $Revision: 113679 $
30 * $Date: 2012-04-16 14:35:19 -0700 (Mon, 16 Apr 2012) $
31 *
32 * This file contains initiator IO related functions in TD layer
33 *
34 */
35#include <osenv.h>
36#include <ostypes.h>
37#include <osdebug.h>
38
39#include <sa.h>
40#include <saapi.h>
41#include <saosapi.h>
42
43#include <titypes.h>
44#include <ostiapi.h>
45#include <tiapi.h>
46#include <tiglobal.h>
47
48#include <tdtypes.h>
49#include <osstring.h>
50#include <tdutil.h>
51
52#ifdef INITIATOR_DRIVER
53#include <itdtypes.h>
54#include <itddefs.h>
55#include <itdglobl.h>
56#endif
57
58#ifdef TARGET_DRIVER
59#include "ttdglobl.h"
60#include "ttdtxchg.h"
61#include "ttdtypes.h"
62#endif
63
64#include <tdsatypes.h>
65#include <tdproto.h>
66
67/* io trace only */
68extern void TDTraceInit(void);
69/* io trace only */
70
71
72osGLOBAL bit32
73ttdssInit(
74        tiRoot_t              *tiRoot,
75        tiTargetResource_t    *targetResource,
76        tiTdSharedMem_t       *tdSharedMem
77)
78{
79    tdsaRoot_t                *tdsaRoot  = (tdsaRoot_t *)tiRoot->tdData;
80    tiTargetMem_t             *tgtMem;
81    ttdsaTgt_t                *Target;
82    ttdssOperatingOption_t    *OperatingOption;
83    char                      *buffer;
84    bit32                     buffLen;
85    bit32                     lenRecv = 0;
86    char                      *pLastUsedChar = agNULL;
87    char                      tmpBuffer[DEFAULT_KEY_BUFFER_SIZE];
88    char                      globalStr[]     = "OSParms";
89
90    TI_DBG5(("ttdssInit: start\n"));
91
92    /*
93     first set the values to Default values
94     Then, overwrite them using ostiGetTransportParam()
95     */
96
97    /* to remove compiler warnings */
98    buffer          = &tmpBuffer[0];
99    buffLen         = sizeof (tmpBuffer);
100
101    osti_memset(buffer, 0, buffLen);
102
103    tgtMem = &targetResource->targetMem;
104
105    /*
106     * Cached mem for target Transport Dependent Layer main functionality
107     */
108    Target = tgtMem->tdMem[0].virtPtr;
109
110    OperatingOption = &Target->OperatingOption;
111    /*
112     * Get default parameters from the OS Specific area
113     * and reads parameters from the configuration file
114     */
115    ttdssGetOperatingOptionParams(tiRoot, OperatingOption);
116
117
118    /*
119     * Update TD operating options
120     */
121    OperatingOption->UsecsPerTick =
122            targetResource->targetOption.usecsPerTick;
123    OperatingOption->numXchgs = tgtMem->tdMem[1].numElements;
124
125
126    if (ttdsaXchgInit(tiRoot,
127            &Target->ttdsaXchgData,
128            tgtMem,
129            OperatingOption->numXchgs
130    ) == agFALSE)
131    {
132        TI_DBG1(("ttdInit: ttdsaXchgInit failed\n"));
133        return tiError;
134    }
135
136    /* Get number of AutoGoodResponse entry */
137    if ((ostiGetTransportParam(
138                                tiRoot,
139                                globalStr,
140                                agNULL,
141                                agNULL,
142                                agNULL,
143                                agNULL,
144                                agNULL,
145                                "AutoGoodResponse",
146                                buffer,
147                                buffLen,
148                                &lenRecv
149                              ) == tiSuccess) && (lenRecv != 0))
150    {
151        if (osti_strncmp(buffer, "0x", 2) == 0)
152        {
153            tdsaRoot->autoGoodRSP = osti_strtoul (buffer, &pLastUsedChar, 0);
154        }
155        else
156        {
157            tdsaRoot->autoGoodRSP = osti_strtoul (buffer, &pLastUsedChar, 10);
158        }
159
160    }
161
162    return tiSuccess;
163}
164
165/*
166  this combines ttdGetDefaultParams and ttdGetTargetParms
167
168 */
169osGLOBAL void
170ttdssGetOperatingOptionParams(
171        tiRoot_t                *tiRoot,
172        ttdssOperatingOption_t  *OperatingOption
173)
174{
175    char    *key = agNULL;
176    char    *subkey1 = agNULL;
177    char    *subkey2 = agNULL;
178    char    *buffer;
179    bit32   buffLen;
180    bit32   lenRecv = 0;
181    char    *pLastUsedChar = agNULL;
182    char    tmpBuffer[DEFAULT_KEY_BUFFER_SIZE];
183    char    globalStr[]     = "Global";
184    char    iniParmsStr[]   = "TargetParms";
185
186    TI_DBG5(("ttdssGetOperatingOptionParams: start\n"));
187
188    /*
189     first set the values to Default values
190     Then, overwrite them using ostiGetTransportParam()
191     */
192
193
194    /* to remove compiler warnings */
195    pLastUsedChar   = pLastUsedChar;
196    lenRecv         = lenRecv;
197    subkey2         = subkey2;
198    subkey1         = subkey1;
199    key             = key;
200    buffer          = &tmpBuffer[0];
201    buffLen         = sizeof (tmpBuffer);
202
203    osti_memset(buffer, 0, buffLen);
204
205
206    /* in ttgglobl.h */
207    OperatingOption->numXchgs = DEFAULT_XCHGS;
208    OperatingOption->UsecsPerTick = DEFAULT_TGT_TIMER_TICK; /* 1 sec */
209    OperatingOption->MaxTargets = DEFAULT_MAX_TARGETS;
210    OperatingOption->BlockSize = DEFAULT_BLOCK_SIZE;
211
212
213    /* defaults are overwritten in the following */
214    /* Get number of exchanges */
215    if ((ostiGetTransportParam(
216            tiRoot,
217            globalStr,
218            iniParmsStr,
219            agNULL,
220            agNULL,
221            agNULL,
222            agNULL,
223            "NumberExchanges",
224            buffer,
225            buffLen,
226            &lenRecv
227    ) == tiSuccess) && (lenRecv != 0))
228    {
229        if (osti_strncmp(buffer, "0x", 2) == 0)
230        {
231            OperatingOption->numXchgs = osti_strtoul (buffer, &pLastUsedChar, 0);
232        }
233        else
234        {
235            OperatingOption->numXchgs = osti_strtoul (buffer, &pLastUsedChar, 10);
236        }
237
238    }
239
240    osti_memset(buffer, 0, buffLen);
241    lenRecv = 0;
242
243    /* Get number of MaxTargets */
244    if ((ostiGetTransportParam(
245            tiRoot,
246            globalStr,
247            iniParmsStr,
248            agNULL,
249            agNULL,
250            agNULL,
251            agNULL,
252            "MaxTargets",
253            buffer,
254            buffLen,
255            &lenRecv
256    ) == tiSuccess) && (lenRecv != 0))
257    {
258        if (osti_strncmp(buffer, "0x", 2) == 0)
259        {
260            OperatingOption->MaxTargets = osti_strtoul (buffer, &pLastUsedChar, 0);
261        }
262        else
263        {
264            OperatingOption->MaxTargets = osti_strtoul (buffer, &pLastUsedChar, 10);
265        }
266
267    }
268    osti_memset(buffer, 0, buffLen);
269    lenRecv = 0;
270
271    /* Get number of BlockSize */
272    if ((ostiGetTransportParam(
273            tiRoot,
274            globalStr,
275            iniParmsStr,
276            agNULL,
277            agNULL,
278            agNULL,
279            agNULL,
280            "BlockSize",
281            buffer,
282            buffLen,
283            &lenRecv
284    ) == tiSuccess) && (lenRecv != 0))
285    {
286        if (osti_strncmp(buffer, "0x", 2) == 0)
287        {
288            OperatingOption->BlockSize = osti_strtoul (buffer, &pLastUsedChar, 0);
289        }
290        else
291        {
292            OperatingOption->BlockSize = osti_strtoul (buffer, &pLastUsedChar, 10);
293        }
294    }
295    osti_memset(buffer, 0, buffLen);
296    lenRecv = 0;
297
298
299
300    TI_DBG5(("ttdssGetOperatingOptionParams: NumberExchanges %d UsecsPerTick %d MaxTargets %d BlockSize %d\n", OperatingOption->numXchgs, OperatingOption->UsecsPerTick, OperatingOption->MaxTargets, OperatingOption->BlockSize));
301
302    return;
303}
304
305/* not yet */
306osGLOBAL void
307ttdssGetResource(
308        tiRoot_t              *tiRoot,
309        tiTargetResource_t    *targetResource
310)
311{
312    tiTargetMem_t            *tgtMem;
313    int i;
314    ttdssOperatingOption_t   OperatingOption;
315    bit32                     xchgSize;
316    bit32                     respSize;
317    bit32                     smprespSize;
318
319    TI_DBG4(("ttdssGetResource: start\n"));
320
321    tgtMem = &targetResource->targetMem;
322
323    /*
324    only 4 memory descriptors are used
325     */
326    tgtMem->count = 4;
327
328    /* initiailization */
329    for (i = 0 ; i < 10 ; i++)
330    {
331        tgtMem->tdMem[i].singleElementLength  = 0;
332        tgtMem->tdMem[i].numElements          = 0;
333        tgtMem->tdMem[i].totalLength          = 0;
334        tgtMem->tdMem[i].alignment            = 0;
335        tgtMem->tdMem[i].type                 = TI_CACHED_MEM;
336        tgtMem->tdMem[i].reserved             = 0;
337        tgtMem->tdMem[i].virtPtr               = agNULL;
338        tgtMem->tdMem[i].osHandle              = agNULL;
339        tgtMem->tdMem[i].physAddrUpper         = 0;
340        tgtMem->tdMem[i].physAddrLower         = 0;
341    }
342
343    /*
344     * Get default parameters from the OS Specific area
345     * and reads parameters from the configuration file
346     */
347    ttdssGetOperatingOptionParams(tiRoot, &OperatingOption);
348
349    /* target */
350    tgtMem->tdMem[0].singleElementLength  = sizeof(ttdsaTgt_t);
351    tgtMem->tdMem[0].numElements          = 1;
352    tgtMem->tdMem[0].totalLength          =
353            tgtMem->tdMem[0].singleElementLength *
354            tgtMem->tdMem[0].numElements;
355    tgtMem->tdMem[0].alignment            = sizeof (void *);
356    tgtMem->tdMem[0].type                 = TI_CACHED_MEM;
357    tgtMem->tdMem[0].reserved             = 0;
358    tgtMem->tdMem[0].virtPtr               = agNULL;
359    tgtMem->tdMem[0].osHandle              = agNULL;
360    tgtMem->tdMem[0].physAddrUpper         = 0;
361    tgtMem->tdMem[0].physAddrLower         = 0;
362
363    /*
364     * Cached memory for I/O exchange structures
365     */
366    xchgSize = sizeof(ttdsaXchg_t);
367    xchgSize = AG_ALIGNSIZE(xchgSize, 8);
368
369    tgtMem->tdMem[1].singleElementLength = xchgSize;
370    tgtMem->tdMem[1].numElements         = OperatingOption.numXchgs;
371    tgtMem->tdMem[1].totalLength         = tgtMem->tdMem[1].singleElementLength *
372            tgtMem->tdMem[1].numElements;
373    tgtMem->tdMem[1].alignment           = sizeof(void *);
374    tgtMem->tdMem[1].type                = TI_CACHED_MEM;
375    tgtMem->tdMem[1].reserved             = 0;
376    tgtMem->tdMem[1].virtPtr               = agNULL;
377    tgtMem->tdMem[1].osHandle              = agNULL;
378    tgtMem->tdMem[1].physAddrUpper         = 0;
379    tgtMem->tdMem[1].physAddrLower         = 0;
380
381    /*
382     * Uncached memory for response buffer structures
383     */
384    TI_DBG4(("ttdssGetResource: sas_resp_t size 0x%x %d\n",
385            (unsigned int)sizeof(sas_resp_t), (int)sizeof(sas_resp_t)));
386
387    respSize = (sizeof(sas_resp_t) + AG_WORD_ALIGN_ADD) & AG_WORD_ALIGN_MASK;
388    TI_DBG4(("ttdssGetResource: response size 0x%x %d\n", respSize,respSize));
389    respSize = AG_ALIGNSIZE(respSize, 8);
390    TI_DBG4(("ttdssGetResource: response size 0x%x %d\n", respSize,respSize));
391    tgtMem->tdMem[2].singleElementLength = 0x1000; /* respSize; 0x1000;  */
392    tgtMem->tdMem[2].numElements         = OperatingOption.numXchgs;  /* Same as num of xchg */
393    tgtMem->tdMem[2].totalLength         = tgtMem->tdMem[2].singleElementLength *
394            tgtMem->tdMem[2].numElements;
395    /* 8;4;16;256;sizeof(void *); all worked */
396    tgtMem->tdMem[2].alignment           = 16;
397    tgtMem->tdMem[2].type                = TI_DMA_MEM;  /* uncached memory */
398    tgtMem->tdMem[2].reserved             = 0;
399    tgtMem->tdMem[2].virtPtr               = agNULL;
400    tgtMem->tdMem[2].osHandle              = agNULL;
401    tgtMem->tdMem[2].physAddrUpper         = 0;
402    tgtMem->tdMem[2].physAddrLower         = 0;
403
404    /*
405     * Uncached memory for SMP response buffer structures
406     */
407    smprespSize = sizeof(smp_resp_t);
408    smprespSize = AG_ALIGNSIZE(smprespSize, 8);
409    TI_DBG4(("ttdssGetResource: SMP response size 0x%x %d\n", smprespSize,smprespSize));
410
411    tgtMem->tdMem[3].singleElementLength = smprespSize; /*0x1000; smprespSize; */
412    tgtMem->tdMem[3].numElements         = OperatingOption.numXchgs;  /* Same as num of xchg */
413    tgtMem->tdMem[3].totalLength
414    = tgtMem->tdMem[3].singleElementLength * tgtMem->tdMem[3].numElements;
415    tgtMem->tdMem[3].alignment           = 16; /* 4; 256; 16; sizeof(void *); */
416    tgtMem->tdMem[3].type                = TI_DMA_MEM;  /* uncached memory */
417    tgtMem->tdMem[3].reserved             = 0;
418    tgtMem->tdMem[3].virtPtr               = agNULL;
419    tgtMem->tdMem[3].osHandle              = agNULL;
420    tgtMem->tdMem[3].physAddrUpper         = 0;
421    tgtMem->tdMem[3].physAddrLower         = 0;
422
423
424
425    targetResource->targetOption.usecsPerTick = OperatingOption.UsecsPerTick;
426    targetResource->targetOption.pageSize     = 0; /* not applicable to SAS/SATA */
427    targetResource->targetOption.numLgns      = 0; /* not applicable to SAS/SATA */
428    targetResource->targetOption.numSessions  = 0; /* not applicable to SAS/SATA */
429    targetResource->targetOption.numXchgs     = OperatingOption.numXchgs;
430
431
432    /*
433    This is not used in OS like Linux which supports dynamic memeory allocation
434    In short, this is for Windows
435     */
436    /* Estimate dynamic DMA memory */
437    targetResource->targetOption.dynamicDmaMem.alignment = sizeof(void *);
438
439    targetResource->targetOption.dynamicDmaMem.numElements = 128;
440    targetResource->targetOption.dynamicDmaMem.singleElementLength = sizeof(tdssSMPRequestBody_t);
441    targetResource->targetOption.dynamicDmaMem.totalLength =
442            targetResource->targetOption.dynamicDmaMem.numElements *
443            targetResource->targetOption.dynamicDmaMem.singleElementLength;
444
445    /* Estimate dynamic cached memory */
446    targetResource->targetOption.dynamicCachedMem.alignment =  sizeof(void *);
447    targetResource->targetOption.dynamicCachedMem.numElements = 128;
448    targetResource->targetOption.dynamicCachedMem.singleElementLength = sizeof(tdssSMPRequestBody_t);
449    targetResource->targetOption.dynamicCachedMem.totalLength =
450            targetResource->targetOption.dynamicCachedMem.numElements *
451            targetResource->targetOption.dynamicCachedMem.singleElementLength;
452
453
454    return;
455}
456
457/* not in use */
458osGLOBAL void
459ttdssGetTargetParams(
460        tiRoot_t          *tiRoot
461)
462{
463    TI_DBG6(("ttdssGetTargetParams: start\n"));
464    return;
465}
466
467osGLOBAL agBOOLEAN
468ttdsaXchgInit(
469        tiRoot_t           *tiRoot,
470        ttdsaXchgData_t    *ttdsaXchgData,
471        tiTargetMem_t      *tgtMem,
472        bit32              maxNumXchgs
473)
474{
475    ttdsaXchg_t       *ttdsaXchg;
476    bit32             i, respLen;
477    bit8              *virtualAddr;
478    bit32             phyAddrLower, phyAddrUpper;
479    bit32             smprespLen;
480    bit32             smpphyAddrLower, smpphyAddrUpper;
481    bit8              *smpvirtualAddr;
482
483
484
485    TI_DBG5(("ttdsaXchgInit: start\n"));
486    /* io trace only */
487    TDTraceInit();
488    /* io trace only */
489
490    /*
491     * Set and initialize some global exchange information
492     */
493    TDLIST_INIT_HDR(&ttdsaXchgData->xchgFreeList);
494    TDLIST_INIT_HDR(&ttdsaXchgData->xchgBusyList);
495
496    ttdsaXchgData->maxNumXchgs = maxNumXchgs;
497
498    /* Initialize exchange and response buffer structures */
499    ttdsaXchg = (ttdsaXchg_t *) tgtMem->tdMem[1].virtPtr;
500
501    /* Initialize response buffer */
502    virtualAddr  = tgtMem->tdMem[2].virtPtr;
503    phyAddrUpper = tgtMem->tdMem[2].physAddrUpper;
504    phyAddrLower = tgtMem->tdMem[2].physAddrLower;
505    respLen      = tgtMem->tdMem[2].singleElementLength;
506
507    ttdsaXchg->resp.virtAddr      = virtualAddr;
508    ttdsaXchg->resp.phyAddrUpper = phyAddrUpper;
509    ttdsaXchg->resp.phyAddrLower = phyAddrLower;
510    ttdsaXchg->resp.length = respLen;
511
512    /* Initialize SMP response buffer */
513    smpvirtualAddr  = tgtMem->tdMem[3].virtPtr;
514    smpphyAddrUpper = tgtMem->tdMem[3].physAddrUpper;
515    smpphyAddrLower = tgtMem->tdMem[3].physAddrLower;
516    smprespLen      = tgtMem->tdMem[3].singleElementLength;
517
518    ttdsaXchg->smpresp.virtAddr      = smpvirtualAddr;
519    ttdsaXchg->smpresp.phyAddrUpper = smpphyAddrUpper;
520    ttdsaXchg->smpresp.phyAddrLower = smpphyAddrLower;
521    ttdsaXchg->smpresp.length = smprespLen;
522
523    /* Initialization of callback and etc */
524    for (i=0;i<maxNumXchgs;i++)
525    {
526        ttdsaXchg->id = i;
527        ttdsaXchg->usedEsgl = agFALSE;
528        ttdsaXchg->io_found = agTRUE;
529        ttdsaXchg->DeviceData = agNULL;
530        /* callback for IO(ssp) and SMP */
531        ttdsaXchg->IORequestBody.IOCompletionFunc = ttdsaIOCompleted;
532        ttdsaXchg->SMPRequestBody.SMPCompletionFunc = ttdsaSMPCompleted;
533
534
535        TDLIST_INIT_ELEMENT(&ttdsaXchg->XchgLinks );
536
537        ttdsaXchg->IORequestBody.agIORequest.osData = (void *)ttdsaXchg;
538        ttdsaXchg->IORequestBody.tiIORequest
539        = &(ttdsaXchg->IORequestBody.IOType.TargetIO.tiIORequest);
540
541        /* Init the tdData portion of tiIORequest context for this exchange */
542        ttdsaXchg->IORequestBody.tiIORequest->tdData = ttdsaXchg;
543
544        /* SMP */
545        ttdsaXchg->SMPRequestBody.agIORequest.osData = (void *)ttdsaXchg;
546        /* ttdsaXchg->SMPRequestBody.agIORequest.osData = (void *)&ttdsaXchg->SMPRequestBody; */
547        /*ttdsaXchg->SMPRequestBody.tiIORequest.tdData = (void *)&ttdsaXchg->SMPRequestBody; */
548
549
550
551
552        /* Initialize the CDB and LUN addresses */
553        ttdsaXchg->tiTgtScsiCmnd.reqCDB  = &(ttdsaXchg->agSSPCmndIU.cdb[0]);
554        ttdsaXchg->tiTgtScsiCmnd.scsiLun = &(ttdsaXchg->agSSPCmndIU.lun[0]);
555
556        ttdsaXchg->index = i;
557        ttdsaXchg->respLen = respLen; /* 100 */
558        ttdsaXchg->smprespLen = smprespLen; /* 100 */
559        ttdsaXchg->TLR = 0;
560        TD_XCHG_SET_STATE(ttdsaXchg, TD_XCHG_STATE_INACTIVE);
561        ttdsaXchg->retries = 0;
562
563        ttdsaXchgLinkInit(tiRoot,ttdsaXchg);
564
565        /* Save current response payload/buffer address */
566        virtualAddr  = ttdsaXchg->resp.virtAddr;
567        phyAddrLower = ttdsaXchg->resp.phyAddrLower;
568        smpvirtualAddr  = ttdsaXchg->smpresp.virtAddr;
569        smpphyAddrLower = ttdsaXchg->smpresp.phyAddrLower;
570
571        TI_DBG5(("ttdsaXchgInit: +1 before\n"));
572        if (i == (maxNumXchgs - 1))
573        {
574            /* at the last one */
575            TI_DBG5(("ttdsaXchgInit: last one break\n"));
576            break;
577        }
578
579        /* Advance to next exchange */
580        ttdsaXchg = ttdsaXchg + 1;
581        TI_DBG5(("ttdsaXchgInit: +1 after\n"));
582
583        /* Update response payload/buffer address */
584        ttdsaXchg->resp.virtAddr      = virtualAddr + respLen;
585        TI_DBG5(("ttdsaXchgInit: pos 1\n"));
586        ttdsaXchg->resp.phyAddrUpper = phyAddrUpper;
587        TI_DBG5(("ttdsaXchgInit: pos 2\n"));
588        ttdsaXchg->resp.phyAddrLower = phyAddrLower + respLen;
589        TI_DBG5(("ttdsaXchgInit: pos 3\n"));
590        ttdsaXchg->resp.length = respLen;
591        TI_DBG5(("ttdsaXchgInit: pos 4\n"));
592
593        /* Update SMP response payload/buffer address */
594        ttdsaXchg->smpresp.virtAddr      = smpvirtualAddr + smprespLen;
595        ttdsaXchg->smpresp.phyAddrUpper = smpphyAddrUpper;
596        ttdsaXchg->smpresp.phyAddrLower = smpphyAddrLower + smprespLen;
597        ttdsaXchg->smpresp.length = smprespLen;
598
599    }
600
601    /* Reinitialize counters.
602     * This must be done at the end
603     */
604    TD_XCHG_CONTEXT_NO_USED(tiRoot)            = 0;
605    TD_XCHG_CONTEXT_NO_FREED(tiRoot)           = 0;
606    TD_XCHG_CONTEXT_NO_CMD_RCVD(tiRoot)        = 0;
607    TD_XCHG_CONTEXT_NO_START_IO(tiRoot)        = 0;
608    TD_XCHG_CONTEXT_NO_SEND_RSP(tiRoot)        = 0;
609    TD_XCHG_CONTEXT_NO_IO_COMPLETED(tiRoot)    = 0;
610
611    TI_DBG5(("ttdsaXchgInit: end\n"));
612    return agTRUE;
613}
614
615osGLOBAL void
616ttdsaXchgLinkInit(
617        tiRoot_t           *tiRoot,
618        ttdsaXchg_t        *ttdsaXchg
619)
620{
621    tdsaRoot_t        *tdsaRoot    = (tdsaRoot_t *)tiRoot->tdData;
622    tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
623    ttdsaTgt_t         *Target = (ttdsaTgt_t *)tdsaAllShared->ttdsaTgt;
624    bit32              i;
625    bit8               *data;
626
627    TI_DBG5(("ttdsaXchgLinkInit: start\n"));
628    TI_DBG5(("ttdsaXchgLinkInit: xchg %p\n",ttdsaXchg));
629    TI_DBG5(("ttdsaXchgLinkInit: resp %p\n",ttdsaXchg->resp.virtAddr));
630    TI_DBG5(("ttdsaXchgLinkInit: smpresp %p\n",ttdsaXchg->smpresp.virtAddr));
631
632    if (TD_XCHG_GET_STATE(ttdsaXchg) == TD_XCHG_STATE_ACTIVE)
633    {
634        TI_DBG1(("ttdsaXchgLinkInit: active xchg *****************; wrong\n"));
635        return;
636    }
637
638    ttdsaXchg->tag = 0xFFFF;
639    ttdsaXchg->IORequestBody.agIORequest.sdkData  = agNULL;
640    ttdsaXchg->SMPRequestBody.agIORequest.sdkData  = agNULL;
641    ttdsaXchg->statusSent        = agFALSE;
642    ttdsaXchg->responseSent      = agFALSE;
643    ttdsaXchg->readRspCollapsed  = agFALSE;
644    ttdsaXchg->wrtRspCollapsed  = agFALSE;
645    ttdsaXchg->pTMResp           = agNULL;
646    ttdsaXchg->oustandingIos     = 0;
647    ttdsaXchg->isAborting        = agFALSE;
648    ttdsaXchg->oslayerAborting   = agFALSE;
649    ttdsaXchg->isTMRequest       = agFALSE;
650    ttdsaXchg->io_found          = agTRUE;
651    ttdsaXchg->tiIOToBeAbortedRequest          = agNULL;
652    ttdsaXchg->XchgToBeAborted          = agNULL;
653
654    osti_memset((void *)ttdsaXchg->resp.virtAddr, 0, ttdsaXchg->respLen);
655    osti_memset((void *)ttdsaXchg->smpresp.virtAddr, 0, ttdsaXchg->smprespLen);
656
657    data = (bit8 *)ttdsaXchg->resp.virtAddr;
658    for (i = 0; i< ttdsaXchg->respLen; i++)
659    {
660        if (data[i] != 0)
661        {
662            TI_DBG5(("!! ttdsaXchgLinkInit: data[%d] 0x%x\n", i, data[i]));
663        }
664    }
665
666    ttdsaXchg->resp.length       = 0;
667
668    ttdsaXchg->DeviceData = agNULL;
669    TI_DBG5(("ttdsaXchgLinkInit: id %d\n", ttdsaXchg->id));
670
671    TD_XCHG_SET_STATE(ttdsaXchg, TD_XCHG_STATE_INACTIVE);
672    tdsaSingleThreadedEnter(tiRoot, TD_TGT_LOCK);
673    TDLIST_ENQUEUE_AT_TAIL( &ttdsaXchg->XchgLinks, &Target->ttdsaXchgData.xchgFreeList);
674    tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
675
676
677    TD_XCHG_CONTEXT_NO_FREED(tiRoot)           = TD_XCHG_CONTEXT_NO_FREED(tiRoot) +1;
678    TI_DBG5(("ttdsaXchgLinkInit: end\n"));
679    return;
680}
681
682/*
683   before: ttdsaXchg is in xchgBusyList
684   after: ttdsaXchg is in xchgFreeList
685 */
686osGLOBAL void
687ttdsaXchgFreeStruct(
688        tiRoot_t           *tiRoot,
689        ttdsaXchg_t        *ttdsaXchg
690)
691{
692    tdsaRoot_t        *tdsaRoot    = (tdsaRoot_t *)tiRoot->tdData;
693    tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
694    ttdsaTgt_t        *Target = (ttdsaTgt_t *)tdsaAllShared->ttdsaTgt;
695    bit32             i;
696    bit8              *data;
697
698    TI_DBG5(("ttdsaXchgFreeStruct: start\n"));
699    TI_DBG5(("ttdsaXchgFreeStruct: xchg %p\n",ttdsaXchg));
700    TI_DBG5(("ttdsaXchgFreeStruct: resp %p\n",ttdsaXchg->resp.virtAddr));
701    TI_DBG5(("ttdsaXchgFreeStruct: smpresp %p\n",ttdsaXchg->smpresp.virtAddr));
702
703    if (TD_XCHG_GET_STATE(ttdsaXchg) == TD_XCHG_STATE_INACTIVE)
704    {
705        TI_DBG1(("tdsaXchgFreeStruct: INACTIVE xchg *****************, wrong\n"));
706        return;
707    }
708
709    ttdsaXchg->tag = 0xFFFF;
710    ttdsaXchg->IORequestBody.agIORequest.sdkData  = agNULL;
711    ttdsaXchg->SMPRequestBody.agIORequest.sdkData  = agNULL;
712    ttdsaXchg->statusSent        = agFALSE;
713    ttdsaXchg->responseSent      = agFALSE;
714    ttdsaXchg->readRspCollapsed  = agFALSE;
715    ttdsaXchg->wrtRspCollapsed  = agFALSE;
716    ttdsaXchg->pTMResp           = agNULL;
717    ttdsaXchg->oustandingIos     = 0;
718    ttdsaXchg->isAborting        = agFALSE;
719    ttdsaXchg->oslayerAborting   = agFALSE;
720    ttdsaXchg->isTMRequest       = agFALSE;
721    ttdsaXchg->io_found          = agTRUE;
722    ttdsaXchg->tiIOToBeAbortedRequest          = agNULL;
723    ttdsaXchg->XchgToBeAborted          = agNULL;
724
725    osti_memset((void *)ttdsaXchg->resp.virtAddr, 0, ttdsaXchg->respLen);
726    osti_memset((void *)ttdsaXchg->smpresp.virtAddr, 0, ttdsaXchg->smprespLen);
727
728    data = (bit8 *)ttdsaXchg->resp.virtAddr;
729    for (i = 0; i< ttdsaXchg->respLen; i++)
730    {
731        if (data[i] != 0)
732        {
733            TI_DBG5(("!! ttdsaXchgFreeStruct: data[%d] 0x%x\n", i, data[i]));
734        }
735    }
736
737    ttdsaXchg->resp.length       = 0;
738
739    ttdsaXchg->DeviceData = agNULL;
740    TI_DBG5(("ttdsaXchgFreeStruct: id %d\n", ttdsaXchg->id));
741
742    tdsaSingleThreadedEnter(tiRoot, TD_TGT_LOCK);
743    TD_XCHG_SET_STATE(ttdsaXchg, TD_XCHG_STATE_INACTIVE);
744    TDLIST_DEQUEUE_THIS(&ttdsaXchg->XchgLinks);
745    TDLIST_ENQUEUE_AT_TAIL( &ttdsaXchg->XchgLinks, &Target->ttdsaXchgData.xchgFreeList);
746    tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
747
748    TD_XCHG_CONTEXT_NO_FREED(tiRoot)           = TD_XCHG_CONTEXT_NO_FREED(tiRoot) +1;
749    TI_DBG5(("ttdsaXchgFreeStruct: end\n"));
750    return;
751}
752
753
754/*
755   before: ttdsaXchg is in xchgFreeList
756   after: ttdsaXchg is in xchgBusyList
757 */
758osGLOBAL ttdsaXchg_t *ttdsaXchgGetStruct(agsaRoot_t *agRoot)
759{
760    tdsaRootOsData_t       *osData = (tdsaRootOsData_t *)agRoot->osData;
761    tiRoot_t               *tiRoot = (tiRoot_t *)osData->tiRoot;
762    ttdsaTgt_t             *Target = (ttdsaTgt_t *)osData->ttdsaTgt;
763    tdList_t               *Link;
764    ttdsaXchg_t            *ttdsaXchg = agNULL;
765
766    TI_DBG3 (("ttdsaXchgGetStruct: enter\n"));
767
768    tdsaSingleThreadedEnter(tiRoot, TD_TGT_LOCK);
769    if (TDLIST_EMPTY(&(Target->ttdsaXchgData.xchgFreeList)))
770    {
771        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
772        TI_DBG1(("ttdsaXchgGetStruct: no free ttdsaXchgData\n"));
773        //    ttdsaDumpallXchg(tiRoot);
774        return agNULL;
775    }
776
777    TDLIST_DEQUEUE_FROM_HEAD(&Link, &Target->ttdsaXchgData.xchgFreeList);
778    if ( Link == agNULL )
779    {
780        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
781        TI_DBG1(("ttdsaXchgGetStruct: Link NULL: PRBLM \n"));
782        return agNULL;
783    }
784
785    ttdsaXchg = TDLIST_OBJECT_BASE(ttdsaXchg_t, XchgLinks, Link);
786
787    if (TD_XCHG_GET_STATE(ttdsaXchg) == TD_XCHG_STATE_ACTIVE)
788    {
789        TI_DBG1(("ttdsaXchgGetStruct: ACTIVE xchg *****************, wrong\n"));
790        TDLIST_DEQUEUE_THIS(&ttdsaXchg->XchgLinks);
791        TDLIST_ENQUEUE_AT_TAIL(&ttdsaXchg->XchgLinks, &Target->ttdsaXchgData.xchgFreeList);
792        TD_XCHG_SET_STATE(ttdsaXchg, TD_XCHG_STATE_INACTIVE);
793        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
794
795        return agNULL;
796    }
797
798    TDLIST_DEQUEUE_THIS(&ttdsaXchg->XchgLinks);
799    TDLIST_ENQUEUE_AT_TAIL(&ttdsaXchg->XchgLinks, &Target->ttdsaXchgData.xchgBusyList);
800    TD_XCHG_SET_STATE(ttdsaXchg, TD_XCHG_STATE_ACTIVE);
801    tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
802
803    TD_XCHG_CONTEXT_NO_USED(tiRoot)           = TD_XCHG_CONTEXT_NO_USED(tiRoot) +1;
804    TI_DBG5(("ttdsaXchgGetStruct: id %d\n", ttdsaXchg->id));
805    return ttdsaXchg;
806}
807
808/* for debugging */
809osGLOBAL void
810ttdsaDumpallXchg(tiRoot_t           *tiRoot)
811{
812    tdsaRoot_t        *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
813    tdsaContext_t     *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
814    ttdsaTgt_t        *Target = (ttdsaTgt_t *)tdsaAllShared->ttdsaTgt;
815    ttdsaTgt_t        *tmpTarget;
816    tdList_t          *XchgList;
817#ifdef TD_DEBUG_ENABLE
818    ttdsaXchg_t       *ttdsaXchg = agNULL;
819#endif
820
821    tmpTarget = Target;
822
823    tdsaSingleThreadedEnter(tiRoot, TD_TGT_LOCK);
824    if (TDLIST_EMPTY(&(tmpTarget->ttdsaXchgData.xchgFreeList)))
825    {
826        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
827        TI_DBG1(("ttdsaDumpallXchg: no FREE ttdsaXchgData\n"));
828    }
829    else
830    {
831        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
832        XchgList = tmpTarget->ttdsaXchgData.xchgFreeList.flink;
833
834        while(XchgList != &(tmpTarget->ttdsaXchgData.xchgFreeList))
835        {
836#ifdef TD_DEBUG_ENABLE
837            ttdsaXchg = TDLIST_OBJECT_BASE(ttdsaXchg_t, XchgLinks, XchgList);
838#endif
839            TI_DBG1(("ttdsaDumpallXchg: FREE id %d state %d\n", ttdsaXchg->id, TD_XCHG_GET_STATE(ttdsaXchg)));
840            XchgList = XchgList->flink;
841        }
842    }
843
844    tdsaSingleThreadedEnter(tiRoot, TD_TGT_LOCK);
845    if (TDLIST_EMPTY(&(tmpTarget->ttdsaXchgData.xchgBusyList)))
846    {
847        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
848        TI_DBG1(("ttdsaDumpallXchg: no BUSY ttdsaXchgData\n"));
849    }
850    else
851    {
852        tdsaSingleThreadedLeave(tiRoot, TD_TGT_LOCK);
853        XchgList = tmpTarget->ttdsaXchgData.xchgBusyList.flink;
854
855        while(XchgList != &(tmpTarget->ttdsaXchgData.xchgBusyList))
856        {
857#ifdef TD_DEBUG_ENABLE
858            ttdsaXchg = TDLIST_OBJECT_BASE(ttdsaXchg_t, XchgLinks, XchgList);
859#endif
860            TI_DBG1(("ttdsaDumpallXchg: BUSY id %d state %d\n", ttdsaXchg->id, TD_XCHG_GET_STATE(ttdsaXchg)));
861            XchgList = XchgList->flink;
862        }
863    }
864
865
866    return;
867}
868
869
870#ifdef PASSTHROUGH
871
872osGLOBAL bit32
873tiTGTPassthroughCmndRegister(
874        tiRoot_t                        *tiRoot,
875        tiPortalContext_t               *tiportalContext,
876        tiPassthroughProtocol_t        tiProtocol,
877        tiPassthroughSubProtocol_t        tiSubProtocol,
878        tiPassthroughFrameType_t        tiFrameType,
879        ostiProcessPassthroughCmnd_t    agPasthroughCB
880)
881{
882    tdsaRoot_t                *tdsaRoot        = (tdsaRoot_t *) tiRoot->tdData;
883    tdsaContext_t             *tdsaAllShared = (tdsaContext_t *)&tdsaRoot->tdsaAllShared;
884    ttdsaTgt_t                *Target = (ttdsaTgt_t *)tdsaAllShared->ttdsaTgt;
885
886    TI_DBG1(("tiTGTPassthroughCmndRegister: start\n"));
887    /* error checking */
888    if (tiProtocol != tiSASATA)
889    {
890        TI_DBG1(("tiTGTPassthroughCmndRegister: not supported protocol %d\n", tiProtocol));
891        return tiError;
892    }
893
894    if (tiSubProtocol != tiSSP || tiSubProtocol != tiSTP || tiSubProtocol != tiSMP)
895    {
896        TI_DBG1(("tiTGTPassthroughCmndRegister: not supported sub protocol %d\n", tiSubProtocol));
897        return tiError;
898    }
899
900
901    if (tiFrameType == tiSMPResponse)
902    {
903        TI_DBG1(("tiTGTPassthroughCmndRegister: SMP response frametype %d\n"));
904        Target->PasthroughCB = agPasthroughCB;
905    }
906
907    else if (tiFrameType == tiSSPPMC)
908    {
909        TI_DBG1(("tiTGTPassthroughCmndRegister: RMC response frametype %d\n"));
910        Target->PasthroughCB = agPasthroughCB;
911    }
912    else
913    {
914        TI_DBG1(("tiTGTPassthroughCmndRegister: not supported frametype %d\n", tiFrameType));
915        return tiError;
916    }
917
918
919    return tiSuccess;
920}
921
922#endif
923