]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/kernel/v2_0/src/intr/intr.cxx
unified MX27, MX25, MX37 trees
[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 #  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
141 Cyg_Interrupt* volatile Cyg_Interrupt::dsr_list_tail[CYGNUM_KERNEL_CPU_MAX];
142 #  endif
143
144 #endif
145
146 // -------------------------------------------------------------------------
147 // Call any pending DSRs
148
149 void
150 Cyg_Interrupt::call_pending_DSRs_inner(void)
151 {
152 //    CYG_REPORT_FUNCTION();
153
154     HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
155     
156 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE    
157
158     while( dsr_table_head[cpu] != dsr_table_tail[cpu] )
159     {
160         Cyg_Interrupt *intr = dsr_table[cpu][dsr_table_head[cpu]];
161
162         dsr_table_head[cpu]++;
163         if( dsr_table_head[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
164             dsr_table_head[cpu] = 0;
165
166         CYG_INSTRUMENT_INTR(CALL_DSR, intr->vector, 0);
167         
168         CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
169
170         intr->dsr( intr->vector, 1, (CYG_ADDRWORD)intr->data );
171     }
172     
173 #endif
174
175 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
176
177 #  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
178
179     cyg_uint32 old_intr;
180     HAL_DISABLE_INTERRUPTS(old_intr);
181     Cyg_Interrupt* intr = dsr_list[cpu];
182     CYG_ASSERT(intr != 0, "No DSRs are pended");
183     dsr_list[cpu] = 0;
184     dsr_list_tail[cpu] = 0;
185     while(true)
186     {
187         cyg_count32 count = intr->dsr_count;
188         Cyg_Interrupt* next = intr->next_dsr;
189         intr->dsr_count = 0;
190         intr->next_dsr = 0;
191         HAL_RESTORE_INTERRUPTS(old_intr);
192
193         CYG_ASSERT(intr->dsr != 0, "No DSR defined");
194         CYG_ASSERT(count > 0, "DSR posted but post count is zero");
195         intr->dsr(intr->vector, count, (CYG_ADDRWORD)intr->data);
196
197         if (!next)
198             break;
199
200         intr = next;
201         HAL_DISABLE_INTERRUPTS(old_intr);
202     }
203
204 #  else // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
205     
206     while( dsr_list[cpu] != NULL )
207     {
208         Cyg_Interrupt* intr;
209         cyg_uint32 old_intr;
210         cyg_count32 count;
211         
212         HAL_DISABLE_INTERRUPTS(old_intr);
213         
214         intr = dsr_list[cpu];
215         dsr_list[cpu] = intr->next_dsr;
216         count = intr->dsr_count;
217         intr->dsr_count = 0;
218         
219         HAL_RESTORE_INTERRUPTS(old_intr);
220         
221         CYG_ASSERT( intr->dsr != NULL , "No DSR defined");
222
223         intr->dsr( intr->vector, count, (CYG_ADDRWORD)intr->data );
224         
225     }
226     
227 #  endif  // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
228
229 #endif  // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
230
231 };
232
233 externC void
234 cyg_interrupt_call_pending_DSRs(void)
235 {
236     Cyg_Interrupt::call_pending_DSRs_inner();
237 }
238
239 //
240 // Use HAL supported function to run through the DSRs, but executing using
241 // the separate interrupt stack if available.  This function calls back
242 // into this module via 'cyg_interrupt_call_pending_DSRs' above, to keep
243 // the whole process as general as possible.
244
245 void
246 Cyg_Interrupt::call_pending_DSRs(void)
247 {
248     CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1,
249                 "DSRs being called with sched_lock not equal to 1");
250     HAL_INTERRUPT_STACK_CALL_PENDING_DSRS();
251 }
252
253
254 // -------------------------------------------------------------------------
255
256 void
257 Cyg_Interrupt::post_dsr(void)
258 {
259 //    CYG_REPORT_FUNCTION();
260     HAL_SMP_CPU_TYPE cpu = CYG_KERNEL_CPU_THIS();
261     
262     CYG_INSTRUMENT_INTR(POST_DSR, vector, 0);
263
264     cyg_uint32 old_intr;
265
266     // We need to disable interrupts during this part to
267     // guard against nested interrupts.
268     
269     HAL_DISABLE_INTERRUPTS(old_intr);
270
271 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE
272     
273     dsr_table[cpu][dsr_table_tail[cpu]++] = this;
274     if( dsr_table_tail[cpu] >= CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE )
275         dsr_table_tail[cpu] = 0;
276
277 #endif
278
279 #ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
280
281     // Only add the interrupt to the dsr list if this is
282     // the first DSR call.
283     if( dsr_count++ == 0 )
284     {
285 #  ifdef CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
286
287         // Add to the tail of the list.
288         Cyg_Interrupt* tail = dsr_list_tail[cpu];
289         dsr_list_tail[cpu] = this;
290         if( tail )
291         {
292             CYG_ASSERT( 0 != dsr_list[cpu] ,
293               "DSR list is not empty but its head is 0");
294             tail->next_dsr = this;
295         }
296         else
297         {
298             CYG_ASSERT( 0 == dsr_list[cpu] ,
299               "DSR list tail is 0 but its head is not");
300             dsr_list[cpu] = this;
301         }
302
303 #  else   // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
304
305         // At present DSRs are pushed onto the list and will be called
306         // in reverse order. We do not define the order in which DSRs
307         // are called, so this is acceptable.
308         next_dsr = dsr_list[cpu];
309         dsr_list[cpu] = this;
310
311 #  endif  // ! defined CYGSEM_KERNEL_INTERRUPTS_DSRS_LIST_FIFO
312
313     }
314
315 #endif  // defined CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST
316     
317     HAL_RESTORE_INTERRUPTS(old_intr);    
318 };
319
320 // -------------------------------------------------------------------------
321 // A C callable interface to Cyg_Interrupt::post_dsr() that can be used from
322 // the HAL.
323
324 externC void
325 cyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj )
326 {
327     Cyg_Interrupt* intr = (Cyg_Interrupt*) intr_obj;
328     intr->post_dsr ();
329 }
330
331 // -------------------------------------------------------------------------
332
333 // FIXME: should have better name - Jifl
334 externC void
335 interrupt_end(
336     cyg_uint32          isr_ret,
337     Cyg_Interrupt       *intr,
338     HAL_SavedRegisters  *regs
339     )
340 {
341 //    CYG_REPORT_FUNCTION();
342
343 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
344     Cyg_Scheduler::lock();
345 #endif
346     
347     // Sometimes we have a NULL intr object pointer.
348     cyg_vector vector = (intr!=NULL)?intr->vector:0;
349
350     CYG_INSTRUMENT_INTR(END, vector, isr_ret);
351     
352     CYG_UNUSED_PARAM( cyg_vector, vector ); // prevent compiler warning
353     
354 #ifndef CYGIMP_KERNEL_INTERRUPTS_CHAIN
355
356     // Only do this if we are in a non-chained configuration.
357     // If we are chained, then chain_isr below will do the DSR
358     // posting.
359     
360     if( isr_ret & Cyg_Interrupt::CALL_DSR && intr != NULL ) intr->post_dsr();
361
362 #endif    
363
364 #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
365
366     // If we have GDB support enabled, and there is the possibility
367     // that this thread will be context switched as a result of this
368     // interrupt, then save the pointer to the saved thread context in
369     // the thread object so that GDB can get a meaningful context to
370     // look at.
371     
372     Cyg_Scheduler::get_current_thread()->set_saved_context(regs);
373     
374 #endif    
375     
376     // Now unlock the scheduler, which may also call DSRs
377     // and cause a thread switch to happen.
378     
379     Cyg_Scheduler::unlock();
380
381 #ifdef CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
382
383     Cyg_Scheduler::get_current_thread()->set_saved_context(0);
384     
385 #endif    
386     
387     CYG_INSTRUMENT_INTR(RESTORE, vector, 0);    
388 }
389
390 // -------------------------------------------------------------------------
391 // Interrupt chaining statics.
392
393 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
394
395 Cyg_Interrupt *Cyg_Interrupt::chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];
396
397 #endif
398
399 // -------------------------------------------------------------------------
400 // Chaining ISR inserted in HAL vector
401
402 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
403
404 cyg_uint32
405 Cyg_Interrupt::chain_isr(cyg_vector vector, CYG_ADDRWORD data)
406 {
407     Cyg_Interrupt *p = *(Cyg_Interrupt **)data;
408     register cyg_uint32 isr_ret = 0;
409     register cyg_uint32 isr_chain_ret = 0;
410
411     CYG_INSTRUMENT_INTR(CHAIN_ISR, vector, 0);
412
413     while( p != NULL )
414     {
415         if( p->vector == vector )
416         {
417             isr_ret = p->isr(vector, p->data);
418
419             isr_chain_ret |= isr_ret;
420
421             if( isr_ret & Cyg_Interrupt::CALL_DSR ) p->post_dsr();
422
423             if( isr_ret & Cyg_Interrupt::HANDLED ) break;
424         }
425
426         p = p->next;
427     }
428
429 #ifdef HAL_DEFAULT_ISR
430     if( (isr_chain_ret & (Cyg_Interrupt::HANDLED|Cyg_Interrupt::CALL_DSR)) == 0 )
431     {
432         // If we finished the loop for some reason other than that an
433         // ISR has handled the interrupt, call any default ISR to either
434         // report the spurious interrupt, or do some other HAL level processing
435         // such as GDB interrupt detection etc.
436
437         HAL_DEFAULT_ISR( vector, 0 );
438     }
439 #endif    
440
441     return isr_ret & ~Cyg_Interrupt::CALL_DSR;
442 }
443
444 #endif
445
446 // -------------------------------------------------------------------------
447 // Attach an ISR to an interrupt vector.
448
449 void
450 Cyg_Interrupt::attach(void)
451 {
452     CYG_REPORT_FUNCTION();
453
454     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");
455     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
456
457     CYG_INSTRUMENT_INTR(ATTACH, vector, 0);
458
459     HAL_INTERRUPT_SET_LEVEL( vector, priority );
460     
461 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
462
463     CYG_ASSERT( next == NULL , "Cyg_Interrupt already on a list");
464
465     cyg_uint32 index;
466
467     HAL_TRANSLATE_VECTOR( vector, index );
468
469     if( chain_list[index] == NULL )
470     {
471         int in_use;
472         // First Interrupt on this chain, just assign it and register
473         // the chain_isr with the HAL.
474         
475         chain_list[index] = this;
476
477         HAL_INTERRUPT_IN_USE( vector, in_use );
478         CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
479         HAL_INTERRUPT_ATTACH( vector, chain_isr, &chain_list[index], NULL );
480     }
481     else
482     {
483         // There are already interrupts chained, add this one into the
484         // chain in priority order.
485         
486         Cyg_Interrupt **p = &chain_list[index];
487
488         while( *p != NULL )
489         {
490             Cyg_Interrupt *n = *p;
491
492             if( n->priority < priority ) break;
493             
494             p = &n->next;
495         }
496         next = *p;
497         *p = this;
498     }
499     
500 #else
501     
502     {
503         int in_use;
504
505
506         HAL_INTERRUPT_IN_USE( vector, in_use );
507         CYG_ASSERT( 0 == in_use, "Interrupt vector not free.");
508
509         HAL_INTERRUPT_ATTACH( vector, isr, data, this );
510     }
511
512 #endif    
513     CYG_REPORT_RETURN();
514 }
515
516 // -------------------------------------------------------------------------
517 // Detach the ISR from the vector
518
519 void
520 Cyg_Interrupt::detach(void)
521 {
522     CYG_REPORT_FUNCTION();
523
524     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
525     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
526
527     CYG_INSTRUMENT_INTR(DETACH, vector, 0);
528
529 #ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN
530
531     // Remove the interrupt object from the vector chain.
532     
533     cyg_uint32 index;
534
535     HAL_TRANSLATE_VECTOR( vector, index );
536
537     Cyg_Interrupt **p = &chain_list[index];
538
539     while( *p != NULL )
540     {
541         Cyg_Interrupt *n = *p;
542
543         if( n == this )
544         {
545             *p = next;
546             break;
547         }
548             
549         p = &n->next;
550     }
551
552     // If this was the last one, detach the vector.
553     
554     if( chain_list[index] == NULL )
555         HAL_INTERRUPT_DETACH( vector, chain_isr );
556     
557 #else
558     
559     HAL_INTERRUPT_DETACH( vector, isr );
560
561 #endif
562
563     CYG_REPORT_RETURN();
564     
565 }
566
567 // -------------------------------------------------------------------------
568 // Get the current service routine
569
570 void
571 Cyg_Interrupt::get_vsr(cyg_vector vector, cyg_VSR **vsr)
572 {
573     CYG_REPORT_FUNCTION();
574     CYG_REPORT_FUNCARG2("vector = %d, mem to put VSR in is at %08x", vector,
575                         vsr);
576
577     CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");        
578     CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");
579
580     HAL_VSR_GET( vector, vsr );
581
582     CYG_REPORT_RETURN();
583 }
584
585 // -------------------------------------------------------------------------
586 // Install a vector service routine
587
588 void
589 Cyg_Interrupt::set_vsr(cyg_vector vector, cyg_VSR *vsr, cyg_VSR **old)
590 {
591     CYG_REPORT_FUNCTION();
592
593     CYG_REPORT_FUNCARG3( "vector = %d, new vsr is at %08x, mem to put "
594                          "old VSR in is at %08x", vector, vsr, old);
595
596     CYG_INSTRUMENT_INTR(SET_VSR, vector, vsr);
597
598     CYG_ASSERT( vector >= CYGNUM_HAL_VSR_MIN, "Invalid vector");    
599     CYG_ASSERT( vector <= CYGNUM_HAL_VSR_MAX, "Invalid vector");    
600
601     CYG_INTERRUPT_STATE old_ints;
602     
603     HAL_DISABLE_INTERRUPTS(old_ints);
604
605     HAL_VSR_SET( vector, vsr, old );
606     
607     HAL_RESTORE_INTERRUPTS(old_ints);
608
609     CYG_REPORT_RETURN();
610 }
611
612 // -------------------------------------------------------------------------
613 // Disable interrupts at the CPU
614
615
616 void
617 Cyg_Interrupt::disable_interrupts(void)
618 {
619     CYG_REPORT_FUNCTION();
620
621     CYG_INSTRUMENT_INTR(DISABLE, disable_counter[CYG_KERNEL_CPU_THIS()]+1, 0);
622
623     HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
624
625     // If the disable_counter is zero, disable interrupts and claim the spinlock.
626     
627     if( 0 == disable_counter[cpu_this] )
628     {
629         // Claim the spinlock and disable interrupts. We save the original interrupt
630         // enable state to restore later.
631         interrupt_disable_spinlock.spin_intsave(&interrupt_disable_state[cpu_this]);
632     }
633
634     // Now increment our disable counter.
635     
636     disable_counter[cpu_this]++;
637     
638     CYG_REPORT_RETURN();
639 }
640
641
642 // -------------------------------------------------------------------------
643 // Re-enable CPU interrupts
644
645 void
646 Cyg_Interrupt::enable_interrupts(void)
647 {
648     CYG_REPORT_FUNCTION();
649         
650     CYG_INSTRUMENT_INTR(ENABLE, disable_counter[CYG_KERNEL_CPU_THIS()], 0);
651
652     HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS();
653
654     CYG_ASSERT( disable_counter[cpu_this] > 0 , "Disable counter not greater than zero");
655     
656     // If the disable counter goes to zero, then release the spinlock and restore
657     // the previous interrupt state.
658     
659     if( --disable_counter[cpu_this] == 0 )
660     {
661         interrupt_disable_spinlock.clear_intsave(interrupt_disable_state[cpu_this]);
662     }
663
664     CYG_REPORT_RETURN();
665 }
666     
667 // -------------------------------------------------------------------------
668 // Mask a specific interrupt in a PIC
669
670 void
671 Cyg_Interrupt::mask_interrupt(cyg_vector vector)
672 {
673     CYG_REPORT_FUNCTION();
674     CYG_REPORT_FUNCARG1("vector=%d", vector);
675
676     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
677     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
678
679     CYG_INSTRUMENT_INTR(MASK, vector, 0);
680
681     CYG_INTERRUPT_STATE old_ints;
682     
683     HAL_DISABLE_INTERRUPTS(old_ints);
684     HAL_INTERRUPT_MASK( vector );
685     HAL_RESTORE_INTERRUPTS(old_ints);
686
687     CYG_REPORT_RETURN();
688 }
689
690 // -------------------------------------------------------------------------
691 // Mask a specific interrupt in a PIC (but not interrupt safe)
692
693 void
694 Cyg_Interrupt::mask_interrupt_intunsafe(cyg_vector vector)
695 {
696     CYG_REPORT_FUNCTION();
697     CYG_REPORT_FUNCARG1("vector=%d", vector);
698
699
700     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
701     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
702
703     CYG_INSTRUMENT_INTR(MASK, vector, 0);
704
705     HAL_INTERRUPT_MASK( vector );
706
707     CYG_REPORT_RETURN();
708 }
709
710 // -------------------------------------------------------------------------
711 // Clear PIC mask
712
713 void
714 Cyg_Interrupt::unmask_interrupt(cyg_vector vector)
715 {
716     CYG_REPORT_FUNCTION();
717
718     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
719     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
720     
721     CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
722
723     CYG_INTERRUPT_STATE old_ints;
724     
725     HAL_DISABLE_INTERRUPTS(old_ints);
726     HAL_INTERRUPT_UNMASK( vector );
727     HAL_RESTORE_INTERRUPTS(old_ints);
728
729     CYG_REPORT_RETURN();
730 }
731     
732
733 // -------------------------------------------------------------------------
734 // Clear PIC mask (but not interrupt safe)
735
736 void
737 Cyg_Interrupt::unmask_interrupt_intunsafe(cyg_vector vector)
738 {
739     CYG_REPORT_FUNCTION();
740
741     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
742     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
743     
744     CYG_INSTRUMENT_INTR(UNMASK, vector, 0);
745
746     HAL_INTERRUPT_UNMASK( vector );
747
748     CYG_REPORT_RETURN();
749 }
750     
751
752 // -------------------------------------------------------------------------
753 // Acknowledge interrupt at PIC
754
755 void
756 Cyg_Interrupt::acknowledge_interrupt(cyg_vector vector)
757 {
758 //    CYG_REPORT_FUNCTION();
759
760     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
761     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
762
763     CYG_INSTRUMENT_INTR(ACK, vector, 0);
764
765     HAL_INTERRUPT_ACKNOWLEDGE( vector );
766 }
767
768 // -------------------------------------------------------------------------
769 // Change interrupt detection at PIC
770
771 void
772 Cyg_Interrupt::configure_interrupt(
773     cyg_vector vector,              // vector to control
774     cyg_bool level,                 // level or edge triggered
775     cyg_bool up                     // hi/lo level, rising/falling edge
776     )
777 {
778     CYG_REPORT_FUNCTION();
779     CYG_REPORT_FUNCARG3("vector = %d, level = %d, up = %d", vector, level,
780                         up);
781
782     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
783     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
784
785     CYG_INSTRUMENT_INTR(CONFIGURE, vector, (level<<1)|up);
786
787     HAL_INTERRUPT_CONFIGURE( vector, level, up );
788
789     CYG_REPORT_RETURN();
790 }
791
792 // -------------------------------------------------------------------------
793 // SMP support for setting/getting interrupt CPU
794
795 #ifdef CYGPKG_KERNEL_SMP_SUPPORT
796
797 void
798 Cyg_Interrupt::set_cpu(
799     cyg_vector vector,              // vector to control
800     HAL_SMP_CPU_TYPE cpu            // CPU to set
801     )
802 {
803     CYG_REPORT_FUNCTION();
804     CYG_REPORT_FUNCARG2("vector = %d, cpu = %d", vector, cpu );
805
806     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
807     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
808
809     CYG_INSTRUMENT_INTR(SET_CPU, vector, cpu);
810
811     HAL_INTERRUPT_SET_CPU( vector, cpu );
812
813     CYG_REPORT_RETURN();
814 }
815
816 HAL_SMP_CPU_TYPE
817 Cyg_Interrupt::get_cpu(
818     cyg_vector vector              // vector to control
819     )
820 {
821     CYG_REPORT_FUNCTION();
822     CYG_REPORT_FUNCARG1("vector = %d", vector);
823
824     CYG_ASSERT( vector >= CYGNUM_HAL_ISR_MIN, "Invalid vector");    
825     CYG_ASSERT( vector <= CYGNUM_HAL_ISR_MAX, "Invalid vector");
826
827     HAL_SMP_CPU_TYPE cpu = 0;
828     
829     HAL_INTERRUPT_GET_CPU( vector, cpu );
830
831     CYG_INSTRUMENT_INTR(GET_CPU, vector, cpu);
832     
833     CYG_REPORT_RETURN();
834
835     return cpu;
836 }
837
838 #endif
839
840 // -------------------------------------------------------------------------
841 // EOF intr/intr.cxx