summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/utils/imageProcs/p9_tor.C
blob: ea454c0cf867e334c0ff8dfc94f9bd41c2ef3bd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/utils/imageProcs/p9_tor.C $               */
/*                                                                        */
/* OpenPOWER sbe Project                                                  */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */

#ifdef WIN32
    #include "endian.h"
#else
    #include <endian.h>
#endif

#include "p9_tor.H"
#include "p9_scan_compression.H"
#include "p9_infrastruct_help.H"


///////////////////////////////////////////////////////////////////////////////////
//
//                          GET RING FROM SECTION   FUNCTION
//
//////////////////////////////////////////////////////////////////////////////////
static
int get_ring_from_ring_section( void*           i_ringSection,     // Ring section ptr
                                RingId_t        i_ringId,          // Ring ID
                                RingVariant_t   i_ringVariant,     // Base,CC,RL (SBE,CME,SGPE only)
                                uint8_t&        io_instanceId,     // Instance ID
                                RingBlockType_t i_ringBlockType,   // Single ring, Block
                                void**          io_ringBlockPtr,   // Output ring buffer
                                uint32_t&       io_ringBlockSize,  // Size of ring data
                                char*           o_ringName,        // Name of ring
                                uint32_t        i_dbgl )           // Debug option
{
    int               rc = TOR_SUCCESS;
    uint8_t           iInst, iRing, iVariant;
    TorHeader_t*      torHeader;
    uint32_t          torMagic;
    uint8_t           chipType;
    TorCpltBlock_t*   cpltBlock;
    TorCpltOffset_t   cpltOffset; // Offset from ringSection to chiplet section
    TorRingOffset_t   ringOffset; // Offset to actual ring container
    uint32_t          torSlotNum; // TOR slot number (within a chiplet section)
    uint32_t          ringSize;   // Size of whole ring container/block.
    RingVariantOrder* ringVariantOrder;
    RingId_t          numRings;
    GenRingIdList*    ringIdListCommon;
    GenRingIdList*    ringIdListInstance;
    GenRingIdList*    ringIdList;
    uint8_t           bInstCase = 0;
    ChipletData_t*    cpltData;
    uint8_t           numVariants;
    ChipletType_t     numChiplets;
    RingProperties_t* ringProps;

    torHeader = (TorHeader_t*)i_ringSection;
    torMagic  = be32toh(torHeader->magic);
    chipType  = torHeader->chipType;

    rc = ringid_get_noof_chiplets( chipType,
                                   torMagic,
                                   &numChiplets);

    if (rc)
    {
        MY_ERR("ringid_get_noof_chiplets() failed w/rc=0x%08x\n", rc);
        return rc;
    }

    //
    // Looper for each SBE chipleti
    //
    for (ChipletType_t iCplt = 0; iCplt < numChiplets; iCplt++)
    {
        rc = ringid_get_properties( chipType,
                                    torMagic,
                                    iCplt,
                                    &cpltData,
                                    &ringIdListCommon,
                                    &ringIdListInstance,
                                    &ringVariantOrder,
                                    &ringProps,
                                    &numVariants );

        if (rc)
        {
            MY_ERR("ringid_get_properties() failed w/rc=0x%08x\n", rc);
            return rc;
        }

        //
        // Sequentially traverse ring offset slots within a chiplet's CMN or INST section
        //
        for ( bInstCase = 0; bInstCase <= 1; bInstCase++ )
        {
            numRings = bInstCase ? cpltData->iv_num_instance_rings : cpltData->iv_num_common_rings;
            ringIdList = bInstCase ? ringIdListInstance : ringIdListCommon;

            if (ringIdList) // Only proceed if chiplet has [Common/Instance] rings.
            {
                // Calc offset to chiplet's CMN or INST section, cpltOffset (steps 1-3)
                //
                // 1. Calc offset to TOR slot pointing to chiplet's COM or INST section
                cpltOffset = sizeof(TorHeader_t) +
                             iCplt * sizeof(cpltBlock) +
                             bInstCase * sizeof(cpltBlock->cmnOffset);
                // 2. Retrive offset, endian convert and make it relative to ring section origin
                cpltOffset = *(uint32_t*)( (uint8_t*)i_ringSection + cpltOffset );
                cpltOffset = be32toh(cpltOffset);
                // 3. Make offset relative to ring section origin
                cpltOffset = sizeof(TorHeader_t) + cpltOffset;

                torSlotNum = 0;

                for ( iInst = ringIdList->instanceIdMin;
                      iInst <= ringIdList->instanceIdMax;
                      iInst++ )
                {
                    for ( iRing = 0; iRing < numRings; iRing++ )
                    {
                        for ( iVariant = 0; iVariant < numVariants; iVariant++ )
                        {
                            if ( strcmp( (ringIdList + iRing)->ringName,
                                         ringProps[i_ringId].iv_name ) == 0 &&
                                 ( i_ringVariant == ringVariantOrder->variant[iVariant] ||
                                   numVariants == 1 ) &&  // If no variants, ignore Variant
                                 ( !bInstCase || ( bInstCase && iInst == io_instanceId) ) )
                            {
                                strcpy(o_ringName, (ringIdList + iRing)->ringName);

                                // Calc offset to actual ring, ringOffset (steps 1-3)
                                //
                                // 1. Calc offset to TOR slot pointing to actual ring
                                ringOffset = cpltOffset + torSlotNum * sizeof(ringOffset);
                                // 2. Retrieve offset and endian convert
                                ringOffset = *(TorRingOffset_t*)( (uint8_t*)i_ringSection + ringOffset );
                                ringOffset = be16toh(ringOffset);

                                if (i_ringBlockType == GET_SINGLE_RING)
                                {
                                    ringSize = 0;

                                    if (ringOffset)
                                    {
                                        // 3. Make offset relative to ring section origin
                                        ringOffset = cpltOffset + ringOffset;

                                        ringSize = be16toh( ((CompressedScanData*)
                                                             ((uint8_t*)i_ringSection + ringOffset))->iv_size );

                                        if (io_ringBlockSize == 0)
                                        {
                                            if (i_dbgl > 0)
                                            {
                                                MY_DBG("io_ringBlockSize is zero. Returning required size.\n");
                                            }

                                            io_ringBlockSize =  ringSize;
                                            return TOR_SUCCESS;
                                        }

                                        if (io_ringBlockSize < ringSize)
                                        {
                                            MY_ERR("io_ringBlockSize is less than required size.\n");
                                            return TOR_BUFFER_TOO_SMALL;
                                        }

                                        // Produce return parms
                                        memcpy( *io_ringBlockPtr, (uint8_t*)i_ringSection + ringOffset, ringSize);
                                        io_ringBlockSize = ringSize;
                                        io_instanceId = (bInstCase) ? io_instanceId : (ringIdList + iRing)->instanceIdMin;

                                        if (i_dbgl > 0)
                                        {
                                            MY_DBG("Found a ring:\n" \
                                                   "  Name: %s\n" \
                                                   "  Blocksize: %d\n",
                                                   o_ringName, io_ringBlockSize);
                                        }

                                        rc = TOR_SUCCESS;
                                    }
                                    else
                                    {
                                        if (i_dbgl > 0)
                                        {
                                            MY_DBG("Ring %s was not found.\n", o_ringName);
                                        }

                                        rc = TOR_RING_NOT_FOUND;
                                    }

                                    if (i_dbgl > 0)
                                    {
                                        MY_DBG("Details for chiplet ring index=%d: \n"
                                               "  Full offset to chiplet section = 0x%08x \n"
                                               "  Full offset to RS4 header = 0x%08x \n"
                                               "  Ring size = 0x%08x \n",
                                               iRing, cpltOffset, ringOffset, ringSize);
                                    }

                                    return rc;

                                }
                                else if (i_ringBlockType == PUT_SINGLE_RING)
                                {
                                    if (ringOffset)
                                    {
                                        MY_ERR("Ring container is already present in image\n");
                                        return TOR_RING_AVAILABLE_IN_RINGSECTION;
                                    }

                                    // Special [mis]use of io_ringBlockPtr and io_ringBlockSize:
                                    // Put location of chiplet's CMN or INST section into ringBlockPtr
                                    memcpy( *io_ringBlockPtr, &cpltOffset, sizeof(cpltOffset));
                                    // Put location of ringOffset slot into ringBlockSize
                                    io_ringBlockSize = cpltOffset + (torSlotNum * sizeof(ringOffset));

                                    return TOR_SUCCESS;
                                }
                                else
                                {
                                    MY_ERR("Ring block type (i_ringBlockType=%d) is not supported\n", i_ringBlockType);
                                    return TOR_INVALID_RING_BLOCK_TYPE;
                                }
                            }

                            torSlotNum++; // Next TOR ring slot
                        }
                    }
                }
            }
            else // Since there's no Common/Instance rings, set RING_NOT_FOUND
            {
                // Note that if we get here, it's because the chiplet doesn't have either
                // a Common or Instance rings. This happens e.g. for Centaur which has
                // no Instance rings. And theoretically, it's possible to only have
                // Instance rings and no Common rings, so accommodating that as well here.
                if (i_dbgl > 0)
                {
                    MY_DBG("Chiplet=%d has no CMN(%d) or INST(%d) section\n",
                           iCplt, (1 - bInstCase), bInstCase);
                }

                rc = TOR_RING_NOT_FOUND;

            } // if (ringIdList)
        } // for (bInstCase)
    } // for (iCplt)

    if (i_dbgl > 0)
    {
        MY_DBG("i_ringId=0x%x is an invalid ring ID\n", i_ringId);
    }

    return TOR_INVALID_RING_ID;

} // End of get_ring_from_ring_section()



//////////////////////////////////////////////////////////////////////////////////////////
///
///                            TOR ACCESS RING   API
///
//////////////////////////////////////////////////////////////////////////////////////////
int tor_access_ring(  void*           i_ringSection,     // Ring section ptr
                      RingId_t        i_ringId,          // Ring ID
                      uint16_t        i_ddLevel,         // DD level
                      PpeType_t       i_ppeType,         // SBE, CME, SGPE
                      RingVariant_t   i_ringVariant,     // Base,CC,RL (SBE,CME,SGPE only)
                      uint8_t&        io_instanceId,     // Instance ID
                      RingBlockType_t i_ringBlockType,   // Single ring, Block
                      void**          io_ringBlockPtr,   // Ring data buffer
                      uint32_t&       io_ringBlockSize,  // Size of ring data
                      char*           o_ringName,        // Ring name
                      uint32_t        i_dbgl )           // Debug option
{
    int rc = 0;
    uint32_t       torMagic;
    TorHeader_t*   torHeader;
    TorDdBlock_t*  torDdBlock;
    uint32_t ddLevelCount = 0;
    uint32_t ddLevelOffset = 0;
    uint32_t ddBlockSize = 0;
    void*    ddBlockStart = NULL;
    uint8_t  bDdCheck = 0;
    uint32_t ddLevel = 0;


    if (i_dbgl > 1)
    {
        MY_DBG("Entering tor_access_ring()...\n");
    }

    torHeader = (TorHeader_t*)i_ringSection;
    torMagic = be32toh(torHeader->magic);

    if (torMagic == TOR_MAGIC_HW)
    {

        ddLevelCount = torHeader->numDdLevels;

        if (ddLevelCount > MAX_NOOF_DD_LEVELS_IN_IMAGE)
        {
            MY_ERR("Too many DD levels in image:\n"
                   "  ddLevelCount = %d\n"
                   "  Max no of DD levels = %d\n",
                   ddLevelCount, MAX_NOOF_DD_LEVELS_IN_IMAGE);

            return TOR_TOO_MANY_DD_LEVELS;
        }
        else if (i_dbgl > 1)
        {
            MY_DBG("tor_access_ring(): No of DD levels: %d \n", ddLevelCount);
        }

        for (uint8_t i = 0; i < ddLevelCount; i++)
        {
            torDdBlock = (TorDdBlock_t*)( (uint8_t*)torHeader +
                                          sizeof(TorHeader_t) +
                                          i * sizeof(TorDdBlock_t) );
            ddLevel = torDdBlock->ddLevel;
            // Local ddLevelOffset (relative to where the DD blocks start)
            ddLevelOffset = be32toh(torDdBlock->offset);

            if (i_dbgl > 1)
            {
                MY_DBG("tor_access_ring(): Local DD level offset: 0x%08x for DD level: 0x%x \n",
                       ddLevelOffset, ddLevel );
            }

            if (ddLevel == i_ddLevel)
            {
                // Calc ddBlockStart from origin of the ringSection to where
                //   the DD block's PPE block starts.
                ddBlockStart = (void*)((uint8_t*)i_ringSection +
                                       sizeof(TorHeader_t) +
                                       ddLevelOffset);
                ddBlockSize = htobe32(torDdBlock->size);
                bDdCheck = 1;
                break;
            }
        }

        if (!bDdCheck)
        {
            MY_ERR("Input DD level not found and/or image indicates zero no of DD levels\n"
                   "  i_ddLevel = 0x%x\n"
                   "  ddLevelCount = %d\n",
                   i_ddLevel, ddLevelCount);

            return TOR_DD_LEVEL_NOT_FOUND;
        }

    }

    if ( ( i_ringBlockType == GET_SINGLE_RING ) ||   // All Magics supported for GET
         ( i_ringBlockType == PUT_SINGLE_RING  &&    // Can only append to SBE,CME,SGPE
           ( torMagic == TOR_MAGIC_SBE ||
             torMagic == TOR_MAGIC_CME ||
             torMagic == TOR_MAGIC_SGPE ) ) )
    {
        if ( torMagic == TOR_MAGIC_HW )
        {
            // Update i_ringSection:
            // Extract the offset to the specified ppeType's ring section TOR header and update i_ringSection
            TorPpeBlock_t*  torPpeBlock;
            torPpeBlock = (TorPpeBlock_t*)((uint8_t*)ddBlockStart + i_ppeType * sizeof(TorPpeBlock_t));
            i_ringSection = (void*)((uint8_t*)ddBlockStart + be32toh(torPpeBlock->offset));
        }

        rc =  get_ring_from_ring_section( i_ringSection,
                                          i_ringId,
                                          i_ringVariant,
                                          io_instanceId,
                                          i_ringBlockType,
                                          io_ringBlockPtr,
                                          io_ringBlockSize,
                                          o_ringName,
                                          i_dbgl );

        return rc;
    }
    else if ( i_ringBlockType == GET_DD_LEVEL_RINGS &&
              torMagic == TOR_MAGIC_HW )
    {
        if (io_ringBlockSize >= ddBlockSize)
        {
            memcpy( (uint8_t*)(*io_ringBlockPtr), ddBlockStart, ddBlockSize );
            io_ringBlockSize =  ddBlockSize;

            return TOR_SUCCESS;
        }
        else if (io_ringBlockSize == 0)
        {
            if (i_dbgl > 0)
            {
                MY_DBG("io_ringBlockSize is zero. Returning required size.\n");
            }

            io_ringBlockSize =  ddBlockSize;

            return TOR_SUCCESS;
        }
        else
        {
            MY_ERR("io_ringBlockSize is less than required size.\n");

            return TOR_BUFFER_TOO_SMALL;
        }
    }
    else if ( i_ringBlockType == GET_PPE_LEVEL_RINGS &&
              torMagic == TOR_MAGIC_HW &&
              (i_ppeType == PT_SBE || i_ppeType == PT_CME || i_ppeType == PT_SGPE) )
    {
        TorPpeBlock_t*  torPpeBlock;
        uint32_t ppeSize;

        torPpeBlock = (TorPpeBlock_t*)((uint8_t*)ddBlockStart + i_ppeType * sizeof(TorPpeBlock_t));
        ppeSize = be32toh(torPpeBlock->size);

        if (io_ringBlockSize >= ppeSize)
        {
            memcpy( (uint8_t*)(*io_ringBlockPtr),
                    (uint8_t*)ddBlockStart + be32toh(torPpeBlock->offset),
                    ppeSize );
            io_ringBlockSize = ppeSize;

            return TOR_SUCCESS;
        }
        else if (io_ringBlockSize == 0)
        {
            if (i_dbgl > 0)
            {
                MY_DBG("io_ringBlockSize is zero. Returning required size.\n");
            }

            io_ringBlockSize =  ppeSize;

            return TOR_SUCCESS;
        }
        else
        {
            MY_ERR("io_ringBlockSize is less than required size.\n");

            return TOR_BUFFER_TOO_SMALL;
        }
    }
    else
    {
        MY_ERR("Ambiguity on input parms to tor_access_ring():\n" \
               "  Possibly invalid torMagic (=0x%08x)\n" \
               "  Possibly incompatible ringBlockType (=%d)\n" \
               "  Possibly unsupported ppeType (=%d)\n" \
               "  Note that we don't care about ppeType for non-HW TOR ring sections\n",
               i_ringBlockType, torMagic, i_ppeType);

        return TOR_AMBIGUOUS_API_PARMS;
    }

    MY_ERR("Code bug in tor_access_ring(): Should never be here\n");

    return TOR_CODE_BUG;

} // End of tor_access_ring()



/////////////////////////////////////////////////////////////////////////////////////
//
//                             TOR GET SINGLE RING   API
//
/////////////////////////////////////////////////////////////////////////////////////
int tor_get_single_ring ( void*         i_ringSection,     // Ring section ptr
                          uint16_t      i_ddLevel,         // DD level
                          RingId_t      i_ringId,          // Ring ID
                          PpeType_t     i_ppeType,         // SBE, CME, SGPE
                          RingVariant_t i_ringVariant,     // Base,CC,RL (SBE/CME/SGPE only)
                          uint8_t       i_instanceId,      // Instance ID
                          void**        io_ringBlockPtr,   // Output ring buffer
                          uint32_t&     io_ringBlockSize,  // Size of ring data
                          uint32_t      i_dbgl )           // Debug option
{

    uint32_t rc;
    char i_ringName[MAX_RING_NAME_LENGTH];

    if (i_dbgl > 1)
    {
        MY_DBG("Entering tor_get_single_ring()...\n");
    }

    rc = tor_access_ring( i_ringSection,
                          i_ringId,
                          i_ddLevel,
                          i_ppeType,
                          i_ringVariant,
                          i_instanceId,
                          GET_SINGLE_RING,
                          io_ringBlockPtr,
                          io_ringBlockSize,
                          i_ringName,
                          i_dbgl );

    if (i_dbgl > 1)
    {
        MY_DBG("Exiting tor_get_single_ring() (ringBlockSize=%d)...\n", io_ringBlockSize );
    }

    return rc;
}



////////////////////////////////////////////////////////////////////////////////////////
//
//                            TOR GET BLOCK OF RINGS   API
//
///////////////////////////////////////////////////////////////////////////////////////
int tor_get_block_of_rings ( void*           i_ringSection,     // Ring section ptr
                             uint16_t        i_ddLevel,         // DD level
                             PpeType_t       i_ppeType,         // SBE,CME,SGPE
                             RingVariant_t   i_ringVariant,     // Base,CC,RL
                             void**          io_ringBlockPtr,   // Output ring buffer
                             uint32_t&       io_ringBlockSize,  // Size of ring data
                             uint32_t        i_dbgl )           // Debug option
{
    uint32_t rc = 0;
    uint8_t      l_instanceId;
    char i_ringName[MAX_RING_NAME_LENGTH];
    uint32_t     torMagic;
    ChipType_t   chipType = UNDEFINED_CHIP_TYPE;
    TorHeader_t* torHeader;

    if (i_dbgl > 1)
    {
        MY_DBG("Entering tor_get_block_of_rings()...\n");
    }

    torHeader = (TorHeader_t*)i_ringSection;
    torMagic  = be32toh(torHeader->magic);
    chipType  = torHeader->chipType;

    if ( torMagic == TOR_MAGIC_HW && chipType != CT_CEN )
    {
        if (i_ppeType == NUM_PPE_TYPES)
        {
            // Get DD level block of rings
            rc = tor_access_ring( i_ringSection,
                                  UNDEFINED_RING_ID,
                                  i_ddLevel,
                                  i_ppeType,
                                  i_ringVariant,
                                  l_instanceId,
                                  GET_DD_LEVEL_RINGS,
                                  io_ringBlockPtr,
                                  io_ringBlockSize,
                                  i_ringName,
                                  i_dbgl );
        }
        else if (i_ppeType == PT_SBE || i_ppeType == PT_CME || i_ppeType == PT_SGPE)
        {
            // Get block of rings specific to a PPE type
            rc = tor_access_ring( i_ringSection,
                                  UNDEFINED_RING_ID,
                                  i_ddLevel,
                                  i_ppeType,
                                  i_ringVariant,
                                  l_instanceId,
                                  GET_PPE_LEVEL_RINGS,
                                  io_ringBlockPtr,
                                  io_ringBlockSize,
                                  i_ringName,
                                  i_dbgl );

        }
        else
        {
            MY_ERR("tor_get_block_of_rings(): Ambiguous API parameters\n");
            return TOR_AMBIGUOUS_API_PARMS;
        }
    }
    else
    {
        MY_ERR("tor_get_block_of_rings(): Only the P9 HW ring section is supported. However, torMagic=0x%08x and chipType=%d\n",
               torMagic, chipType);
        return TOR_UNSUPPORTED_RING_SECTION;
    }

    if (i_dbgl > 1)
    {
        MY_DBG("Exiting tor_get_block_of_rings() (ringBlockSize=%d)...\n", io_ringBlockSize);
    }

    return rc;
}



////////////////////////////////////////////////////////////////////////////////////////
//
//                             TOR APPEND RING   API
//
///////////////////////////////////////////////////////////////////////////////////////
int tor_append_ring(  void*           i_ringSection,      // Ring section ptr
                      uint32_t&       io_ringSectionSize, // In: Exact size of ring section.
                      // Out: Updated size of ring section.
                      void*           i_ringBuffer,       // Ring work buffer
                      const uint32_t  i_ringBufferSize,   // Max size of ring work buffer
                      RingId_t        i_ringId,           // Ring ID
                      PpeType_t       i_ppeType,          // SBE, CME, SGPE
                      RingVariant_t   i_ringVariant,      // Base,CC,RL
                      uint8_t         i_instanceId,       // Instance ID
                      void*           i_rs4Container,     // RS4 ring container
                      uint32_t        i_dbgl )            // Debug option
{
    uint32_t   rc = 0;
    char       i_ringName[MAX_RING_NAME_LENGTH];
    uint32_t   l_buf = 0;
    uint32_t*  l_cpltSection = &l_buf;
    uint32_t   l_ringBlockSize;
    uint16_t   l_ringOffset16;
    uint32_t   l_torOffsetSlot;

    rc = tor_access_ring( i_ringSection,
                          i_ringId,
                          0x00,
                          i_ppeType,
                          i_ringVariant,
                          i_instanceId,
                          PUT_SINGLE_RING,
                          (void**)&l_cpltSection, // On return, contains offset (wrt ringSection) of
                          // chiplet section's common or instance section
                          l_torOffsetSlot,        // On return, contains offset (wrt ringSection) of
                          // TOR offset slot
                          i_ringName,
                          i_dbgl);

    if (rc)
    {
        if (i_dbgl > 0)
        {
            MY_ERR("tor_append_ring() failed in call to tor_access_ring w/rc=0x%x \n", rc);
        }

        return rc;
    }

    if (i_dbgl > 1)
    {
        MY_INF(" TOR offset slot for ring address %d \n", l_torOffsetSlot );
    }

    // Explanation to the following:
    // tor_append_ring() appends a ring to the end of ringSection. The offset value to
    // that ring is wrt the beginning of the chiplet's TOR section. Below we calculate
    // the offset value and put it into the TOR slot. But first, check that the offset
    // value can be contained within the 2B of the TOR slot.
    if ( (io_ringSectionSize - *l_cpltSection) <= MAX_TOR_RING_OFFSET )
    {
        l_ringOffset16 = htobe16(io_ringSectionSize - *l_cpltSection);
        memcpy( (uint8_t*)i_ringSection + l_torOffsetSlot,
                &l_ringOffset16, sizeof(l_ringOffset16) );
    }
    else
    {
        MY_ERR("Code bug: TOR ring offset (=0x%x) exceeds MAX_TOR_RING_OFFSET (=0x%x)",
               io_ringSectionSize - *l_cpltSection, MAX_TOR_RING_OFFSET);
        return TOR_OFFSET_TOO_BIG;
    }

    // Now append the ring to the end of ringSection.
    l_ringBlockSize = be16toh( ((CompressedScanData*)i_rs4Container)->iv_size );
    memcpy( (uint8_t*)i_ringSection + io_ringSectionSize,
            (uint8_t*)i_rs4Container, (size_t)l_ringBlockSize);

    // Update the ringSectionSize
    io_ringSectionSize += l_ringBlockSize;

    // Update also the size in the TOR header
    TorHeader_t* torHeader = (TorHeader_t*)i_ringSection;
    torHeader->size = htobe32(be32toh(torHeader->size) + l_ringBlockSize);

    return TOR_SUCCESS;
}


//
// Inform caller of TOR version.
//
uint8_t tor_version( void)
{
    return (uint8_t)TOR_VERSION;
}
OpenPOWER on IntegriCloud