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