summaryrefslogtreecommitdiffstats
path: root/src/ssx/pgp/pgp_async_pore.c
blob: 5f9b425e4857f7363dc27f81f3775f801bbd3b0e (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
// $Id: pgp_async_pore.c,v 1.5 2014/05/14 13:35:43 bcbrock Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_pore.c,v $
//-----------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2013
// *! All Rights Reserved -- Property of IBM
// *! *** IBM Confidential ***
//-----------------------------------------------------------------------------

/// \file pgp_async_pore.c
/// \brief PgP "async" drivers for PORE engines

#include "ssx.h"

////////////////////////////////////////////////////////////////////////////
// Global Data
////////////////////////////////////////////////////////////////////////////

// The PORE queue objects.

PoreQueue G_pore_gpe0_queue;
PoreQueue G_pore_gpe1_queue;
PoreQueue G_pore_slw_queue;


////////////////////////////////////////////////////////////////////////////
// Local Data
////////////////////////////////////////////////////////////////////////////

/// PoreFlex entry point - See G_pore_flex_table.

static uint32_t G_pore_flex_entry0 = PORE_BRAD_D0;


/// Entry 0 of the PoreFlex branch table
///
/// This variable is the only thing we represent of the branch table for PORE
/// flex requests.  PoreFlex requests are forbidden from using PORE error
/// handlers. Therefore they don't require the 60 redundant bytes of error
/// handler entry points.  They also only run trigger slot 0, and begin
/// execution with a BRAD D0, so the only thing we represent is a single BRAD
/// D0 instruction.

static uint32_t* G_pore_flex_table = &G_pore_flex_entry0 - (PORE_ERROR_SLOTS * 3);


////////////////////////////////////////////////////////////////////////////
// PoreQueue
////////////////////////////////////////////////////////////////////////////

/// Create (initialize) a PoreQueue
///
/// \param queue An uninitialized of otherwise idle PoreQueue
///
/// \param engine The identifier of a PORE engine associated with this queue.
///
/// This API initializes the PoreQueue structure and also initializes the
/// underlying PORE hardware to run in the OCC environment.  Neither the
/// branch table nor the error modes are specified here - those are considered
/// application-specific functions that are set up each time a job is run on
/// the engine.
///
/// \retval 0 Success
///
/// \retval -ASYNC_INVALID_OBJECT_PORE_QUEUE The \a queue was NULL (0).
///
/// \retval -ASYNC_INVALID_ENGINE_PORE The \a engine is not a (valid) 
/// PORE engine.

int
pore_queue_create(PoreQueue *queue, int engine)
{
    pore_control_t control;

    if (SSX_ERROR_CHECK_API) {
        SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PORE_QUEUE);
        SSX_ERROR_IF(!(engine & ASYNC_ENGINE_PORE), ASYNC_INVALID_ENGINE_PORE);
    }

    async_queue_create(&(queue->queue), engine);

    switch (engine) {

    case ASYNC_ENGINE_PORE_GPE0:
        queue->oci_base = PORE_GPE0_OCI_BASE;
        queue->irq = PGP_IRQ_PORE_GPE0_COMPLETE;
        queue->error_irq = PGP_IRQ_PORE_GPE0_ERROR;
        queue->oci_master = OCI_MASTER_ID_PORE_GPE;
        break;

    case ASYNC_ENGINE_PORE_GPE1:
        queue->oci_base = PORE_GPE1_OCI_BASE;
        queue->irq = PGP_IRQ_PORE_GPE1_COMPLETE;
        queue->error_irq = PGP_IRQ_PORE_GPE1_ERROR;
        queue->oci_master = OCI_MASTER_ID_PORE_GPE;
        break;

    case ASYNC_ENGINE_PORE_SLW:
        queue->oci_base = PORE_SLW_OCI_BASE;
        queue->irq = PGP_IRQ_PORE_SW_COMPLETE;
        queue->error_irq = PGP_IRQ_PORE_SW_ERROR;
        queue->oci_master = OCI_MASTER_ID_PORE_SLW;
        break;

    default:
        SSX_PANIC(ASYNC_BUG_PORE_AT_CREATE);
    }

    // PORE engine setup
    //
    // Force the PORE to stop and set it up for OCC control.  Neither the
    // breakpoint address nor the trap enable setting are modified in case
    // they are being controlled from Simics or a hardware debugger ab initio.
    //
    // Register field settings:
    //
    // The scanclk ratio is not modified.
    // The EXE-Trigger register is unlocked
    // The freeze action is not modified
    // Instruction parity is ignored
    // The PIB parity checking setting is not modified
    // The TRAP enable is not modified
    // The breakpoint address is not modified

    control.value = in64(queue->oci_base + PORE_CONTROL_OFFSET);

    control.fields.start_stop = 1;
    control.fields.lock_exe_trig= 0;
    control.fields.check_parity = 0;

    out64(queue->oci_base + PORE_CONTROL_OFFSET, control.value);

    return 0;
}


// The interrupt handler for asynchronous PORE errors
//
// The PORE interrupts are disabled here, then cleared and re-enabled when the
// next job runs.  This is to protect against "phantom" interrupts caused by
// PORE freeze-on-checkstop behavior.

SSX_IRQ_FAST2FULL(pore_async_error_handler, pore_async_error_handler_full);

void
pore_async_error_handler_full(void *arg, SsxIrqId irq, int priority)
{
    PoreQueue* queue = (PoreQueue*)arg;

    ssx_irq_disable(queue->irq);
    ssx_irq_disable(queue->error_irq);

    async_error_handler((AsyncQueue *)arg, ASYNC_REQUEST_STATE_FAILED);
}


// The interrupt handler for asynchronous PORE requests
//
// The PORE interrupts are disabled here, then cleared and re-enabled when the
// next job runs.  This is to protect against "phantom" interrupts caused by
// PORE freeze-on-checkstop behavior.
//
// Note that if the system checkstops and freezes the PORE we will get a
// normal completion interrupt.  Therefore we have to check to see if the
// completion is associated with a freeze, and if so, fail the job.

SSX_IRQ_FAST2FULL(pore_async_handler, pore_async_handler_full);

void
pore_async_handler_full(void *arg, SsxIrqId irq, int priority)
{
    PoreQueue* queue = (PoreQueue*)arg;
    pore_status_t status;

    status.value = in64(queue->oci_base + PORE_STATUS_OFFSET);
    if (status.fields.freeze_action) {

        pore_async_error_handler_full(arg, irq, priority);

    } else {

        ssx_irq_disable(queue->irq);
        ssx_irq_disable(queue->error_irq);

        async_handler((AsyncQueue *)arg);
    }
}


////////////////////////////////////////////////////////////////////////////
// PoreRequest
////////////////////////////////////////////////////////////////////////////

/// Create (initialize) the PoreRequest base class
///
/// \param request An uninitialized or otherwise idle PoreRequest.
///
/// \param queue An initialized PoreQueue
///
/// \param table The PORE branch table to install prior to kicking off the
/// engine. All PoreFlex jobs use a common (stubbed) table.  PoreFixed jobs
/// must supply a fully-formed table.
///
/// \param error_mask The initial value of the PORE ERROR_MASK register to be
/// installed before kicking off the engine.
///
/// \param entry_point The entry point address of the routine.  For PoreFlex
/// this entry point will be non-0 and will be inserted into D0, as PoreFlex
/// jobs are kicked off by BRAD D0.  For PoreFixed this parameter will be zero
/// and ignored.
///
/// \param start_vector The TBAR start vector to execute. This will always be
/// 0 for PoreFlex.
///
/// \param parameter The single 32-bit parameter to the PORE program.  This
/// value is stored in the low-order part of the \c EXE_TRIGGER register
/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
///
/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
/// will be governed by a private watchdog timer that will cancel a queued job
/// or kill a running job if the hardware operation does not complete before
/// it times out.
///
/// \param callback The callback to execute when the PORE program completes,
/// or NULL (0) to indicate no callback.
///
/// \param arg The parameter to the callback routine; ignored if the \a
/// callback is NULL.
///
/// \param options Options to control request priority and callback context.
///
/// This routine has no way to know if the PoreRequest structure is currently
/// in use, so this API should only be called on uninitialized or otherwise
/// idle PoreRequest structures.
///
/// \retval 0 Success
///
/// \retval -ASYNC_INVALID_OBJECT_PORE_REQUEST The \a request was NULL (0) 
/// or the \a queue was NULL (0) or not a PoreQueue.
///
/// \retval -ASYNC_INVALID_ARGUMENT_PORE_REQUEST The \a start_vector is invalid or any of
/// the parameters that represent OCI addresses are not 4-byte aligned, , or
/// the \a table was null.
///
/// See async_request_create() for other errors that may be returned by this
/// call.

int
pore_request_create(PoreRequest *request,
                    PoreQueue *queue,
                    PoreBraia* table,
                    uint32_t error_mask,
                    uint32_t entry_point,
                    int start_vector,
                    uint32_t parameter,
                    SsxInterval timeout,
                    AsyncRequestCallback callback,
                    void *arg,
                    int options)
{
    AsyncQueue *async_queue = (AsyncQueue *)queue;
    int rc;
    pore_exe_trigger_t etr;

    if (SSX_ERROR_CHECK_API) {
        SSX_ERROR_IF(!(async_queue->engine & ASYNC_ENGINE_PORE),
                     ASYNC_INVALID_OBJECT_PORE_REQUEST);
        SSX_ERROR_IF((start_vector < 0) ||
                     (start_vector >= PORE_TRIGGER_SLOTS) ||
                     ((uint32_t) table % 4) ||
                     (entry_point % 4) ||
                     (table == 0),
                     ASYNC_INVALID_ARGUMENT_PORE_REQUEST);
    }

    rc = async_request_create(&(request->request),
                              async_queue,
                              pore_run_method,
                              pore_error_method,
                              timeout,
                              callback,
                              arg,
                              options);

    if (!rc) {
        request->table = table;
        request->error_mask = error_mask;
        request->entry_point = entry_point;
        request->parameter = parameter;
        etr.value = 0;
        etr.fields.start_vector = start_vector;
        request->exe_trigger = etr.words.high_order;
    }

    return rc;
}


// Start a PoreRequest on a PORE
//
// \param async_request A PoreRequest upcast to an AsyncRequest.
//
// This is an internal API. At entry both the completion and error interrupts
// are disabled and may show status that needs to be cleared before they are
// re-enabled.
//
// This routine implements a simple procedure:
//
// - Check to make sure the PORE is not frozen due to a checkstop, and if so,
//   collect FFDC and immediately fail the job.
//
// Otherwise:
//
// - Reset the PORE engine to clear up any error status that may remain from
//   the last job .
// - Install the TBAR (Table Base Address Register) from the request as an OCI
//   address
// - Set the EMR (Error Mask Register) from the request
// - Install the parameter (ETR[32:63])
// - If the entry point is non-0 then this is a PoreFlex job that is kicked
//   off by a BRAD D0, and the entry point is installed in D0 as a full OCI
//   address. 
// - Clear pending interrupt status
// - Hit ETR[0:31] to start the job.
// - Enable interrupts.
//
// If the PORE is frozen due to a system checkstop we fail the job immediately
// right here.  Note that there is still a small window where the system may
// checkstop and the PORE may freeze after this check. Unfortunately the PORE
// design locks out register writes while frozen, and instead of reporting
// write access attempts as bus errors, silently ignores them and simply sets
// a FIR bit. Originally the "frozen" check was done last to shrink the
// window, however this practically guarantees these FIRs in a checkstopped
// system (which the FW team finds problematic), so the check was moved to the
// front of the procedure. (SW256621).
//
// Note that PORE interrupts remain masked unless the job starts successfully.

int
pore_run_method(AsyncRequest *async_request)
{
    PoreQueue *queue = (PoreQueue*)(async_request->queue);
    PoreRequest *request = (PoreRequest*)async_request;
    pore_status_t status;
    pore_reset_t reset;
    uint32_t oci_base;
    int rc;

    oci_base = queue->oci_base;

    status.value = in64(oci_base + PORE_STATUS_OFFSET);
    if (status.fields.freeze_action) {

        pore_error_method(async_request);
        async_request->completion_state = ASYNC_REQUEST_STATE_FAILED;
        rc = -ASYNC_REQUEST_COMPLETE;

    } else {

        reset.value = 0;
        reset.fields.fn_reset = 1;
        out32(oci_base + PORE_RESET_OFFSET, reset.value);

        out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET, PORE_ADDRESS_SPACE_OCI);
        out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET + 4,
              (uint32_t)(request->table));
        out32(oci_base + PORE_ERROR_MASK_OFFSET, request->error_mask);
        out32(oci_base + PORE_EXE_TRIGGER_OFFSET + 4, request->parameter);

        if (request->entry_point != 0) {
            out32(oci_base + PORE_SCRATCH1_OFFSET, PORE_ADDRESS_SPACE_OCI);
            out32(oci_base + PORE_SCRATCH1_OFFSET + 4, request->entry_point);
        }

        ssx_irq_status_clear(queue->irq);
        ssx_irq_status_clear(queue->error_irq);

        out32(oci_base + PORE_EXE_TRIGGER_OFFSET, request->exe_trigger);

        ssx_irq_enable(queue->irq);
        ssx_irq_enable(queue->error_irq);
        rc = 0;
    }

    return rc;
}


// PORE FFDC collection
//
// \param async_request A PoreRequest upcast to an AsyncRequest
//
// This is an internal API, called from an interrupt context when a PORE
// engine signals an error interrupt.  See the comments for PoreFfdc for a
// description of why this particular set of data is collected.
//
// PORE error handling procedure:
//
// - Collect FFDC from the PLB arbiter
//
// - Collect FFDC from the failing engine
//
// Currently all PORE errors are treated as recoverable

/// \todo Consider analyzing the errors to determine if the error should be
/// considered fatal.

int
pore_error_method(AsyncRequest *async_request)
{
    PoreQueue *queue = (PoreQueue*)(async_request->queue);
    PoreRequest *request = (PoreRequest*)async_request;
    uint32_t oci_base;
    PoreFfdc* ffdc;

    oci_base = queue->oci_base;
    ffdc = &(request->ffdc);
 
    oci_ffdc(&(ffdc->oci_ffdc), queue->oci_master);

    ffdc->debug[0] = in64(oci_base + PORE_DBG0_OFFSET);
    ffdc->debug[1] = in64(oci_base + PORE_DBG1_OFFSET);
    ffdc->address[0] = in32(oci_base + PORE_OCI_BASE_ADDRESS0_OFFSET + 4);
    ffdc->address[1] = in32(oci_base + PORE_OCI_BASE_ADDRESS1_OFFSET + 4);
    ffdc->ibuf[0] = in32(oci_base + PORE_IBUF_01_OFFSET);
    ffdc->ibuf[1] = in32(oci_base + PORE_IBUF_01_OFFSET + 4);
    ffdc->ibuf[2] = in32(oci_base + PORE_IBUF_2_OFFSET);

    return 0;
}


/// Create (initialize) a PoreBraia branch table entry
///
/// \param instr  A pointer to the BRAIA instruction to initialize. Use the
/// macros PORE_ERROR_BRANCH(table, n) and PORE_ENTRY_BRANCH(table, n) to
/// select one of 5 error branches or one of 16 entry point branches in a PORE
/// branch table.
///
/// \param address The 32-bit OCI address of the error routine or entry point.
///
/// This routine initializes the given entry of a PORE branch table with an
/// OCI-based BRAIA instruction, them flushes the entry from the D-Cache.

// Note that we don't know the alignment of the jump table, so we need to
// flush both the first and last jump address to ensure that the BRAI is
// completely flushed. This assumes (correctly) that uint32_t are at least
// 4-byte aligned.

void
pore_braia_create(PoreBraia* instr, uint32_t address) {
    instr->word[0] = PORE_BRAI;
    instr->word[1] = PORE_ADDRESS_SPACE_OCI;
    instr->word[2] = address;
    dcache_flush_line(&(instr->word[0]));
    dcache_flush_line(&(instr->word[2]));
}


////////////////////////////////////////////////////////////////////////////
// PoreFlex
////////////////////////////////////////////////////////////////////////////

/// Create (initialize) a flex-mode PORE request
///
/// \param request An uninitialized or otherwise idle PoreFlex.
///
/// \param queue A pointer to a PoreQueue
///
/// \param entry_point The entry point of the PORE program. This must be a
/// 32-bit, 4-byte aligned byte address in OCI space. The PoreEntryPoint
/// typedef is provided to declare external PORE entry points. Note that an \a
/// entry_point of 0 is considered an error - although it \e is conceivably a
/// legal OCI address in mainstore via the PBA.
///
/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
/// will be governed by a private watchdog timer that will cancel a queued job
/// or kill a running job if the hardware operation does not complete before
/// it times out.
///
/// \param parameter The single 32-bit parameter to the PORE program.  This
/// value is stored in the high-order part of the \c EXE_TRIGGER register
/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
///
/// \param callback The callback to execute when the PORE program completes,
/// or NULL (0) to indicate no callback.
///
/// \param arg The parameter to the callback routine; ignored if the \a
/// callback is NULL.
///
/// \param options Options to control request priority and callback context.
///
/// This routine has no way to know if the PoreFlex structure is currently
/// in use, so this API should only be called on uninitialized or
/// otherwise idle PoreFlex structures.
///
/// \retval 0 Success
///
/// See pore_request_create() for error return codes that may be returned by
/// this call.

int
pore_flex_create(PoreFlex *request,
                 PoreQueue *queue,
                 PoreEntryPoint entry_point,
                 uint32_t parameter,
                 SsxInterval timeout,
                 AsyncRequestCallback callback,
                 void *arg,
                 int options)
{
    uint32_t emr;

    // PoreFlex jobs run w/o error handlers, and ignore sleeping cores. All
    // errors are signalled on both error outputs of all PORE engines.

    emr = (PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0       |
           PORE_ERROR_MASK_ENABLE_ERR_OUTPUT1       |
           PORE_ERROR_MASK_ENABLE_ERR_OUTPUT2       |
           PORE_ERROR_MASK_ENABLE_ERR_OUTPUT3       |
           PORE_ERROR_MASK_ENABLE_ERR_OUTPUT4       |
           PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 |
           PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 |
           PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 |
           PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 |
           PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 |
           PORE_ERROR_MASK_STOP_EXE_ON_ERROR0       |
           PORE_ERROR_MASK_STOP_EXE_ON_ERROR1       |
           PORE_ERROR_MASK_STOP_EXE_ON_ERROR2       |
           PORE_ERROR_MASK_STOP_EXE_ON_ERROR3       |
           PORE_ERROR_MASK_STOP_EXE_ON_ERROR4) >> 32;

    return pore_request_create((PoreRequest*)request,
                               queue,
                               (PoreBraia*)G_pore_flex_table,
                               emr,
                               (uint32_t)entry_point,
                               0,
                               parameter,
                               timeout,
                               callback,
                               arg,
                               options);
}


////////////////////////////////////////////////////////////////////////////
// PoreFixed
////////////////////////////////////////////////////////////////////////////

/// Create (initialize) a fixed-mode PORE request
///
/// \param request An uninitialized or otherwise idle PoreFixed request.
///
/// \param queue A PoreQueue capable of running fixed requests.
///
/// \param table A PORE branch table containing all of the error handler and
/// entry point assignments required for the request.
///
/// \param error_mask A value that will be loaded into the high-order 32-bits
/// of the PORE Error Mask Register to control error behavior.
///
/// \param start_vector The branch table slot reserved for this request.
///
/// \param parameter The single 32-bit parameter to the PORE program.  This
/// value is stored in the high-order part of the \c EXE_TRIGGER register
/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER
/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as
/// this is the hardware usage for hardware-initiated PORE-SLW routines.)
///
/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request
/// will be governed by a private watchdog timer that will cancel a queued job
/// or kill a running job if the hardware operation does not complete before
/// it times out.
///
/// \param callback The callback to execute when the PORE program completes,
/// or NULL (0) to indicate no callback.
///
/// \param arg The parameter to the callback routine; ignored if the \a
/// callback is NULL.
///
/// \param options Options to control request priority and callback context.
///
/// This routine has no way to know if the PoreFixed structure is currently
/// in use, so this API should only be called on uninitialized or
/// otherwise idle PoreFlex structures.
///
/// \retval 0 Success
///
/// See pore_request_create() for error return codes that may be returned by
/// this call.

int
pore_fixed_create(PoreFixed *request,
                  PoreQueue *queue,
                  PoreBraia* table,
                  uint32_t error_mask,
                  int start_vector,
                  uint32_t parameter,
                  SsxInterval timeout,
                  AsyncRequestCallback callback,
                  void *arg,
                  int options)
{
    return pore_request_create((PoreRequest*)request,
                               queue,
                               table,
                               error_mask,
                               0,
                               start_vector,
                               parameter,
                               timeout,
                               callback,
                               arg,
                               options);
}


////////////////////////////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////////////////////////////

// Due to the fact that PORE signals a "complete" interrupt on a freeze event
// (i.e., a checkstop, even if PORE is not running), we can not enable PORE
// interrupts globally.  They need to be carefully managed to avoid "phantom
// interrupt" panics from async_handler().

void
async_pore_initialize(PoreQueue *queue,int engine)
{
    pore_queue_create(queue, engine);
    async_edge_handler_setup(pore_async_handler,
                             (void *)queue,
                             queue->irq, SSX_CRITICAL);
    async_edge_handler_setup(pore_async_error_handler,
                             (void *)queue,
                             queue->error_irq, SSX_CRITICAL);
}



OpenPOWER on IntegriCloud