OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [kernel/] [current/] [src/] [intr/] [intr.cxx] - Blame information for rev 851

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      intr/intr.cxx
4
//
5
//      Interrupt class implementations
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####                                            
9
// -------------------------------------------                              
10
// This file is part of eCos, the Embedded Configurable Operating System.   
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under    
14
// the terms of the GNU General Public License as published by the Free     
15
// Software Foundation; either version 2 or (at your option) any later      
16
// version.                                                                 
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT      
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or    
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License    
21
// for more details.                                                        
22
//
23
// You should have received a copy of the GNU General Public License        
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,    
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.            
26
//
27
// As a special exception, if other files instantiate templates or use      
28
// macros or inline functions from this file, or you compile this file      
29
// and link it with other works to produce a work based on this file,       
30
// this file does not by itself cause the resulting work to be covered by   
31
// the GNU General Public License. However the source code for this file    
32
// must still be made available in accordance with section (3) of the GNU   
33
// General Public License v2.                                               
34
//
35
// This exception does not invalidate any other reasons why a work based    
36
// on this file might be covered by the GNU General Public License.         
37
// -------------------------------------------                              
38
// ####ECOSGPLCOPYRIGHTEND####                                              
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    nickg
43
// Contributors: nickg
44
// Date:         1999-02-17
45
// Purpose:      Interrupt class implementation
46
// Description:  This file contains the definitions of the interrupt
47
//               class.
48
//
49
//####DESCRIPTIONEND####
50
//
51
//==========================================================================
52
 
53
#include <pkgconf/kernel.h>
54
 
55
#include <cyg/kernel/ktypes.h>             // base kernel types
56
#include <cyg/infra/cyg_trac.h>           // tracing macros
57
#include <cyg/infra/cyg_ass.h>            // assertion macros
58
#include <cyg/kernel/instrmnt.h>           // instrumentation
59
 
60
#include <cyg/kernel/intr.hxx>             // our header
61
 
62
#include <cyg/kernel/sched.hxx>            // scheduler
63
 
64
#include <cyg/kernel/sched.inl>
65
 
66
// -------------------------------------------------------------------------
67
// Statics
68
 
69
volatile cyg_int32 Cyg_Interrupt::disable_counter[CYGNUM_KERNEL_CPU_MAX];
70
 
71
Cyg_SpinLock Cyg_Interrupt::interrupt_disable_spinlock CYG_INIT_PRIORITY( INTERRUPTS );
72
 
73
CYG_INTERRUPT_STATE Cyg_Interrupt::interrupt_disable_state[CYGNUM_KERNEL_CPU_MAX];
74
 
75
// -------------------------------------------------------------------------
76
 
77
Cyg_Interrupt::Cyg_Interrupt(
78
    cyg_vector      vec,                // Vector to attach to
79
    cyg_priority    pri,                // Queue priority
80
    CYG_ADDRWORD    d,                  // Data pointer
81
    cyg_ISR         *ir,                // Interrupt Service Routine
82
    cyg_DSR         *dr                 // Deferred Service Routine
83
    )
84
{
85
    CYG_REPORT_FUNCTION();
86
    CYG_REPORT_FUNCARG5("vector=%d, priority=%d, data=%08x, isr=%08x, "
87
                        "dsr=%08x", vec, pri, d, ir, dr);
88
 
89
    vector      = vec;
90
    priority    = pri;
91
    isr         = ir;
92
    dsr         = dr;
93
    data        = d;
94
 
95
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
96
 
97
    dsr_count   = 0;
98
    next_dsr    = NULL;
99
 
100
#endif
101
 
102
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
103
 
104
    next        = NULL;
105
 
106
#endif
107
 
108
    CYG_REPORT_RETURN();
109
 
110
};
111
 
112
// -------------------------------------------------------------------------
113
 
114
Cyg_Interrupt::~Cyg_Interrupt()
115
{
116
    CYG_REPORT_FUNCTION();
117
    detach();
118
    CYG_REPORT_RETURN();
119
};
120
 
121
// -------------------------------------------------------------------------
122
// DSR handling statics:
123
 
124
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
125
 
126
Cyg_Interrupt *
127
Cyg_Interrupt::dsr_table[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE];
128
 
129
cyg_ucount32 Cyg_Interrupt::dsr_table_head[CYGNUM_KERNEL_CPU_MAX];
130
 
131
volatile cyg_ucount32 Cyg_Interrupt::dsr_table_tail[CYGNUM_KERNEL_CPU_MAX];
132
 
133
#endif
134
 
135
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
136
 
137
Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list[CYGNUM_KERNEL_CPU_MAX];
138
 
139
#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
140
Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list_tail[CYGNUM_KERNEL_CPU_MAX];
141
#  endif
142
 
143
#endif
144
 
145
// -------------------------------------------------------------------------
146
// Call any pending DSRs
147
 
148
void
149
Cyg_Interrupt::call_pending_DSRs_inner(void)
150
{
151
//    CYG_REPORT_FUNCTION();
152
 
153
    HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
154
 
155
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE    
156
 
157
    while( dsr_table_head[cpu] != dsr_table_tail[cpu] )
158
    {
159
        Cyg_Interrupt *intr = dsr_table[cpu][dsr_table_head[cpu]];
160
 
161
        dsr_table_head[cpu]++;
162
        if( dsr_table_head[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
163
            dsr_table_head[cpu] = 0;
164
 
165
        CYG_INSTRUMENT_INTR(CALL_DSR, intr->vector, 0);
166
 
167
        CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
168
 
169
        intr->dsr( intr->vector, 1, (CYG_ADDRWORD)intr->data );
170
    }
171
 
172
#endif
173
 
174
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
175
 
176
#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
177
 
178
    cyg_uint32 old_intr;
179
    HAL_DISABLE_INTERRUPTS(old_intr);
180
    Cyg_Interrupt* intr = dsr_list[cpu];
181
    CYG_ASSERT(intr != 0, "No DSRs are pended");
182
    dsr_list[cpu] = 0;
183
    dsr_list_tail[cpu] = 0;
184
    while(true)
185
    {
186
        cyg_count32 count = intr->dsr_count;
187
        Cyg_Interrupt* next = intr->next_dsr;
188
        intr->dsr_count = 0;
189
        intr->next_dsr = 0;
190
        HAL_RESTORE_INTERRUPTS(old_intr);
191
 
192
        CYG_ASSERT(intr->dsr != 0, "No DSR defined");
193
        CYG_ASSERT(count > 0, "DSR posted but post count is zero");
194
        intr->dsr(intr->vector, count, (CYG_ADDRWORD)intr->data);
195
 
196
        if (!next)
197
            break;
198
 
199
        intr = next;
200
        HAL_DISABLE_INTERRUPTS(old_intr);
201
    }
202
 
203
#  else // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
204
 
205
    while( dsr_list[cpu] != NULL )
206
    {
207
        Cyg_Interrupt* intr;
208
        cyg_uint32 old_intr;
209
        cyg_count32 count;
210
 
211
        HAL_DISABLE_INTERRUPTS(old_intr);
212
 
213
        intr = dsr_list[cpu];
214
        dsr_list[cpu] = intr->next_dsr;
215
        count = intr->dsr_count;
216
        intr->dsr_count = 0;
217
 
218
        HAL_RESTORE_INTERRUPTS(old_intr);
219
 
220
        CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
221
 
222
        intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data );
223
 
224
    }
225
 
226
#  endif  // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
227
 
228
#endif  // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
229
 
230
};
231
 
232
externC void
233
cyg_interrupt_call_pending_DSRs(void)
234
{
235
    Cyg_Interrupt::call_pending_DSRs_inner();
236
}
237
 
238
//
239
// Use HAL supported function to run through the DSRs, but executing using
240
// the separate interrupt stack if available.  This function calls back
241
// into this module via 'cyg_interrupt_call_pending_DSRs' above, to keep
242
// the whole process as general as possible.
243
 
244
void
245
Cyg_Interrupt::call_pending_DSRs(void)
246
{
247
    CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
248
                "DSRs being called with sched_lock not equal to 1");
249
    HAL_INTERRUPT_STACK_CALL_PENDING_DSRS();
250
}
251
 
252
 
253
// -------------------------------------------------------------------------
254
 
255
void
256
Cyg_Interrupt::post_dsr(void)
257
{
258
//    CYG_REPORT_FUNCTION();
259
    HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
260
 
261
    CYG_INSTRUMENT_INTR(POST_DSR, vector, 0);
262
 
263
    cyg_uint32 old_intr;
264
 
265
    // We need to disable interrupts during this part to
266
    // guard against nested interrupts.
267
 
268
    HAL_DISABLE_INTERRUPTS(old_intr);
269
 
270
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
271
 
272
    dsr_table[cpu][dsr_table_tail[cpu]++] = this;
273
    if( dsr_table_tail[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
274
        dsr_table_tail[cpu] = 0;
275
 
276
#endif
277
 
278
#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
279
 
280
    // Only add the interrupt to the dsr list if this is
281
    // the first DSR call.
282
    if( dsr_count++ == 0 )
283
    {
284
#  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
285
 
286
        // Add to the tail of the list.
287
        Cyg_Interrupt* tail = dsr_list_tail[cpu];
288
        dsr_list_tail[cpu] = this;
289
        if( tail )
290
        {
291
            CYG_ASSERT( 0 != dsr_list[cpu] ,
292
              "DSR list is not empty but its head is 0");
293
            tail->next_dsr = this;
294
        }
295
        else
296
        {
297
            CYG_ASSERT( 0 == dsr_list[cpu] ,
298
              "DSR list tail is 0 but its head is not");
299
            dsr_list[cpu] = this;
300
        }
301
 
302
#  else   // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
303
 
304
        // At present DSRs are pushed onto the list and will be called
305
        // in reverse order. We do not define the order in which DSRs
306
        // are called, so this is acceptable.
307
        next_dsr = dsr_list[cpu];
308
        dsr_list[cpu] = this;
309
 
310
#  endif  // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
311
 
312
    }
313
 
314
#endif  // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
315
 
316
    HAL_RESTORE_INTERRUPTS(old_intr);
317
};
318
 
319
// -------------------------------------------------------------------------
320
// A C callable interface to Cyg_Interrupt::post_dsr() that can be used from
321
// the HAL.
322
 
323
externC void
324
cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj )
325
{
326
    Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj;
327
    intr->post_dsr ();
328
}
329
 
330
// -------------------------------------------------------------------------
331
 
332
// FIXME: should have better name - Jifl
333
externC void
334
interrupt_end(
335
    cyg_uint32          isr_ret,
336
    Cyg_Interrupt       *intr,
337
    HAL_SavedRegisters  *regs
338
    )
339
{
340
//    CYG_REPORT_FUNCTION();
341
 
342
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
343
    Cyg_Scheduler::lock();
344
#endif
345
 
346
    // Sometimes we have a NULL intr object pointer.
347
    cyg_vector vector = (intr!=NULL)?intr->vector:0;
348
 
349
    CYG_INSTRUMENT_INTR(END, vector, isr_ret);
350
 
351
    CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
352
 
353
#ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
354
 
355
    // Only do this if we are in a non-chained configuration.
356
    // If we are chained, then chain_isr below will do the DSR
357
    // posting.
358
 
359
    if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();
360
 
361
#endif    
362
 
363
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
364
 
365
    // If we have GDB support enabled, and there is the possibility
366
    // that this thread will be context switched as a result of this
367
    // interrupt, then save the pointer to the saved thread context in
368
    // the thread object so that GDB can get a meaningful context to
369
    // look at.
370
 
371
    Cyg_Scheduler::get_current_thread()->set_saved_context(regs);
372
 
373
#endif    
374
 
375
    // Now unlock the scheduler, which may also call DSRs
376
    // and cause a thread switch to happen.
377
 
378
    Cyg_Scheduler::unlock();
379
 
380
#ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
381
 
382
    Cyg_Scheduler::get_current_thread()->set_saved_context(0);
383
 
384
#endif    
385
 
386
    CYG_INSTRUMENT_INTR(RESTORE, vector, 0);
387
}
388
 
389
// -------------------------------------------------------------------------
390
// Interrupt chaining statics.
391
 
392
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
393
 
394
Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
395
 
396
#endif
397
 
398
// -------------------------------------------------------------------------
399
// Chaining ISR inserted in HAL vector
400
 
401
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
402
 
403
cyg_uint32
404
Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data)
405
{
406
    Cyg_Interrupt *p = *(Cyg_Interrupt **)data;
407
    register cyg_uint32 isr_ret = 0;
408
    register cyg_uint32 isr_chain_ret = 0;
409
 
410
    CYG_INSTRUMENT_INTR(CHAIN_ISR, vector, 0);
411
 
412
    while( p != NULL )
413
    {
414
        if( p->vector == vector )
415
        {
416
            isr_ret = p->isr(vector, p->data);
417
 
418
            isr_chain_ret |= isr_ret;
419
 
420
            if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr();
421
 
422
            if( isr_ret & Cyg_Interrupt::HANDLED ) break;
423
        }
424
 
425
        p = p->next;
426
    }
427
 
428
#ifdef HAL_DEFAULT_ISR
429
    if( (isr_chain_ret & (Cyg_Interrupt::HANDLED|Cyg_Interrupt::CALL_DSR)) == 0 )
430
    {
431
        // If we finished the loop for some reason other than that an
432
        // ISR has handled the interrupt, call any default ISR to either
433
        // report the spurious interrupt, or do some other HAL level processing
434
        // such as GDB interrupt detection etc.
435
 
436
        HAL_DEFAULT_ISR( vector, 0 );
437
    }
438
#endif    
439
 
440
    return isr_ret & ~Cyg_Interrupt::CALL_DSR;
441
}
442
 
443
#endif
444
 
445
// -------------------------------------------------------------------------
446
// Attach an ISR to an interrupt vector.
447
 
448
void
449
Cyg_Interrupt::attach(void)
450
{
451
    CYG_REPORT_FUNCTION();
452
 
453
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
454
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
455
 
456
    CYG_INSTRUMENT_INTR(ATTACH, vector, 0);
457
 
458
    HAL_INTERRUPT_SET_LEVEL( vector, priority );
459
 
460
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
461
 
462
    CYG_ASSERT( next == NULL , "Cyg_Interrupt already on a list");
463
 
464
    cyg_uint32 index;
465
 
466
    HAL_TRANSLATE_VECTOR( vector, index );
467
 
468
    if( chain_list[index] == NULL )
469
    {
470
        int in_use CYGBLD_ATTRIB_UNUSED;
471
        // First Interrupt on this chain, just assign it and register
472
        // the chain_isr with the HAL.
473
 
474
        chain_list[index] = this;
475
 
476
        HAL_INTERRUPT_IN_USE( vector, in_use );
477
        CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
478
        HAL_INTERRUPT_ATTACH( vector, chain_isr, &chain_list[index], NULL );
479
    }
480
    else
481
    {
482
        // There are already interrupts chained, add this one into the
483
        // chain in priority order.
484
 
485
        Cyg_Interrupt **p = &chain_list[index];
486
 
487
        while( *p != NULL )
488
        {
489
            Cyg_Interrupt *n = *p;
490
 
491
            if( n->priority < priority ) break;
492
 
493
            p = &n->next;
494
        }
495
        next = *p;
496
        *p = this;
497
    }
498
 
499
#else
500
 
501
    {
502
        int in_use CYGBLD_ATTRIB_UNUSED;
503
 
504
        HAL_INTERRUPT_IN_USE( vector, in_use );
505
        CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
506
 
507
        HAL_INTERRUPT_ATTACH( vector, isr, data, this );
508
    }
509
 
510
#endif    
511
    CYG_REPORT_RETURN();
512
}
513
 
514
// -------------------------------------------------------------------------
515
// Detach the ISR from the vector
516
 
517
void
518
Cyg_Interrupt::detach(void)
519
{
520
    CYG_REPORT_FUNCTION();
521
 
522
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
523
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
524
 
525
    CYG_INSTRUMENT_INTR(DETACH, vector, 0);
526
 
527
#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
528
 
529
    // Remove the interrupt object from the vector chain.
530
 
531
    cyg_uint32 index;
532
 
533
    HAL_TRANSLATE_VECTOR( vector, index );
534
 
535
    Cyg_Interrupt **p = &chain_list[index];
536
 
537
    while( *p != NULL )
538
    {
539
        Cyg_Interrupt *n = *p;
540
 
541
        if( n == this )
542
        {
543
            *p = next;
544
            break;
545
        }
546
 
547
        p = &n->next;
548
    }
549
 
550
    // If this was the last one, detach the vector.
551
 
552
    if( chain_list[index] == NULL )
553
        HAL_INTERRUPT_DETACH( vector, chain_isr );
554
 
555
#else
556
 
557
    HAL_INTERRUPT_DETACH( vector, isr );
558
 
559
#endif
560
 
561
    CYG_REPORT_RETURN();
562
 
563
}
564
 
565
// -------------------------------------------------------------------------
566
// Get the current service routine
567
 
568
void
569
Cyg_Interrupt::get_vsr(cyg_vector vector, cyg_VSR **vsr)
570
{
571
    CYG_REPORT_FUNCTION();
572
    CYG_REPORT_FUNCARG2("vector = %d, mem to put VSR in is at %08x", vector,
573
                        vsr);
574
 
575
    CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
576
    CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
577
 
578
    HAL_VSR_GET( vector, vsr );
579
 
580
    CYG_REPORT_RETURN();
581
}
582
 
583
// -------------------------------------------------------------------------
584
// Install a vector service routine
585
 
586
void
587
Cyg_Interrupt::set_vsr(cyg_vector vector, cyg_VSR *vsr, cyg_VSR **old)
588
{
589
    CYG_REPORT_FUNCTION();
590
 
591
    CYG_REPORT_FUNCARG3( "vector = %d, new vsr is at %08x, mem to put "
592
                         "old VSR in is at %08x", vector, vsr, old);
593
 
594
    CYG_INSTRUMENT_INTR(SET_VSR, vector, vsr);
595
 
596
    CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");
597
    CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
598
 
599
    CYG_INTERRUPT_STATE old_ints;
600
 
601
    HAL_DISABLE_INTERRUPTS(old_ints);
602
 
603
    HAL_VSR_SET( vector, vsr, old );
604
 
605
    HAL_RESTORE_INTERRUPTS(old_ints);
606
 
607
    CYG_REPORT_RETURN();
608
}
609
 
610
// -------------------------------------------------------------------------
611
// Disable interrupts at the CPU
612
 
613
 
614
void
615
Cyg_Interrupt::disable_interrupts(void)
616
{
617
    CYG_REPORT_FUNCTION();
618
 
619
    CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
620
 
621
    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
622
 
623
    // If the disable_counter is zero, disable interrupts and claim the spinlock.
624
 
625
    if( 0 == disable_counter[cpu_this] )
626
    {
627
        // Claim the spinlock and disable interrupts. We save the original interrupt
628
        // enable state to restore later.
629
        interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
630
    }
631
 
632
    // Now increment our disable counter.
633
 
634
    disable_counter[cpu_this]++;
635
 
636
    CYG_REPORT_RETURN();
637
}
638
 
639
 
640
// -------------------------------------------------------------------------
641
// Re-enable CPU interrupts
642
 
643
void
644
Cyg_Interrupt::enable_interrupts(void)
645
{
646
    CYG_REPORT_FUNCTION();
647
 
648
    CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
649
 
650
    HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
651
 
652
    CYG_ASSERT( disable_counter[cpu_this] > 0 , "Disable counter not greater than zero");
653
 
654
    // If the disable counter goes to zero, then release the spinlock and restore
655
    // the previous interrupt state.
656
 
657
    if( --disable_counter[cpu_this] == 0 )
658
    {
659
        interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
660
    }
661
 
662
    CYG_REPORT_RETURN();
663
}
664
 
665
// -------------------------------------------------------------------------
666
// Mask a specific interrupt in a PIC
667
 
668
void
669
Cyg_Interrupt::mask_interrupt(cyg_vector vector)
670
{
671
    CYG_REPORT_FUNCTION();
672
    CYG_REPORT_FUNCARG1("vector=%d", vector);
673
 
674
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
675
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
676
 
677
    CYG_INSTRUMENT_INTR(MASK, vector, 0);
678
 
679
    CYG_INTERRUPT_STATE old_ints;
680
 
681
    HAL_DISABLE_INTERRUPTS(old_ints);
682
    HAL_INTERRUPT_MASK( vector );
683
    HAL_RESTORE_INTERRUPTS(old_ints);
684
 
685
    CYG_REPORT_RETURN();
686
}
687
 
688
// -------------------------------------------------------------------------
689
// Mask a specific interrupt in a PIC (but not interrupt safe)
690
 
691
void
692
Cyg_Interrupt::mask_interrupt_intunsafe(cyg_vector vector)
693
{
694
    CYG_REPORT_FUNCTION();
695
    CYG_REPORT_FUNCARG1("vector=%d", vector);
696
 
697
 
698
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
699
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
700
 
701
    CYG_INSTRUMENT_INTR(MASK, vector, 0);
702
 
703
    HAL_INTERRUPT_MASK( vector );
704
 
705
    CYG_REPORT_RETURN();
706
}
707
 
708
// -------------------------------------------------------------------------
709
// Clear PIC mask
710
 
711
void
712
Cyg_Interrupt::unmask_interrupt(cyg_vector vector)
713
{
714
    CYG_REPORT_FUNCTION();
715
 
716
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
717
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
718
 
719
    CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
720
 
721
    CYG_INTERRUPT_STATE old_ints;
722
 
723
    HAL_DISABLE_INTERRUPTS(old_ints);
724
    HAL_INTERRUPT_UNMASK( vector );
725
    HAL_RESTORE_INTERRUPTS(old_ints);
726
 
727
    CYG_REPORT_RETURN();
728
}
729
 
730
 
731
// -------------------------------------------------------------------------
732
// Clear PIC mask (but not interrupt safe)
733
 
734
void
735
Cyg_Interrupt::unmask_interrupt_intunsafe(cyg_vector vector)
736
{
737
    CYG_REPORT_FUNCTION();
738
 
739
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
740
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
741
 
742
    CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
743
 
744
    HAL_INTERRUPT_UNMASK( vector );
745
 
746
    CYG_REPORT_RETURN();
747
}
748
 
749
 
750
// -------------------------------------------------------------------------
751
// Acknowledge interrupt at PIC
752
 
753
void
754
Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector)
755
{
756
//    CYG_REPORT_FUNCTION();
757
 
758
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
759
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
760
 
761
    CYG_INSTRUMENT_INTR(ACK, vector, 0);
762
 
763
    HAL_INTERRUPT_ACKNOWLEDGE( vector );
764
}
765
 
766
// -------------------------------------------------------------------------
767
// Change interrupt detection at PIC
768
 
769
void
770
Cyg_Interrupt::configure_interrupt(
771
    cyg_vector vector,              // vector to control
772
    cyg_bool level,                 // level or edge triggered
773
    cyg_bool up                     // hi/lo level, rising/falling edge
774
    )
775
{
776
    CYG_REPORT_FUNCTION();
777
    CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level,
778
                        up);
779
 
780
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
781
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
782
 
783
    CYG_INSTRUMENT_INTR(CONFIGURE, vector, (level<<1)|up);
784
 
785
    HAL_INTERRUPT_CONFIGURE( vector, level, up );
786
 
787
    CYG_REPORT_RETURN();
788
}
789
 
790
// -------------------------------------------------------------------------
791
// SMP support for setting/getting interrupt CPU
792
 
793
#ifdef CYGPKG_KERNEL_SMP_SUPPORT
794
 
795
void
796
Cyg_Interrupt::set_cpu(
797
    cyg_vector vector,              // vector to control
798
    HAL_SMP_CPU_TYPE cpu            // CPU to set
799
    )
800
{
801
    CYG_REPORT_FUNCTION();
802
    CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
803
 
804
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
805
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
806
 
807
    CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
808
 
809
    HAL_INTERRUPT_SET_CPU( vector, cpu );
810
 
811
    CYG_REPORT_RETURN();
812
}
813
 
814
HAL_SMP_CPU_TYPE
815
Cyg_Interrupt::get_cpu(
816
    cyg_vector vector              // vector to control
817
    )
818
{
819
    CYG_REPORT_FUNCTION();
820
    CYG_REPORT_FUNCARG1("vector = %d", vector);
821
 
822
    CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
823
    CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
824
 
825
    HAL_SMP_CPU_TYPE cpu = 0;
826
 
827
    HAL_INTERRUPT_GET_CPU( vector, cpu );
828
 
829
    CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
830
 
831
    CYG_REPORT_RETURN();
832
 
833
    return cpu;
834
}
835
 
836
#endif
837
 
838
// -------------------------------------------------------------------------
839
// EOF intr/intr.cxx

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.