Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  *  openpic.c -- OpenPIC Interrupt Handling
0003  *
0004  *  Copyright (C) 1997 Geert Uytterhoeven
0005  *
0006  *  Modified to compile in RTEMS development environment
0007  *  by Eric Valette
0008  *
0009  *  Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
0010  *
0011  *  The license and distribution terms for this file may be
0012  *  found in the file LICENSE in this distribution or at
0013  *  http://www.rtems.org/license/LICENSE.
0014  */
0015 
0016 /*
0017  *  Note: Interprocessor Interrupt (IPI) and Timer support is incomplete
0018  */
0019 
0020 #include <rtems.h>
0021 #include <bsp.h>
0022 #include <rtems/bspIo.h>
0023 #include <bsp/openpic.h>
0024 #include <rtems/pci.h>
0025 #include <libcpu/io.h>
0026 #include <libcpu/byteorder.h>
0027 #include <rtems/bspIo.h>
0028 #include <inttypes.h>
0029 
0030 #ifndef NULL
0031 #define NULL 0
0032 #endif
0033 #define REGISTER_DEBUG
0034 #undef REGISTER_DEBUG
0035 
0036 volatile struct OpenPIC *OpenPIC = NULL;
0037 
0038 static unsigned int NumProcessors;
0039 static unsigned int NumSources;
0040 
0041 static unsigned int openpic_eoi_delay = 0;
0042 static          int openpic_src_offst = 0;
0043 #define SOURCE(irq) Source[ (irq) + openpic_src_offst ]
0044 
0045     /*
0046      *  Accesses to the current processor's registers
0047      */
0048 
0049 #define THIS_CPU        Processor[cpu]
0050 #define CHECK_THIS_CPU      check_arg_cpu(cpu)
0051 
0052     /*
0053      *  Sanity checks
0054      */
0055 
0056 #if 1
0057 /* This software deliberately uses non-zero values to the method
0058  * __builtin_return_address() and we want to avoid the GCC warning.
0059  */
0060 #pragma GCC diagnostic push
0061 #pragma GCC diagnostic ignored "-Wframe-address"
0062 #define check_arg_ipi(ipi) \
0063     if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \
0064     printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi);
0065 #define check_arg_timer(timer) \
0066     if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \
0067     printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer);
0068 #define check_arg_vec(vec) \
0069     if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \
0070     printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec);
0071 #define check_arg_pri(pri) \
0072     if (pri < 0 || pri >= OPENPIC_NUM_PRI) \
0073     printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri);
0074 #define check_arg_irq(irq) \
0075     if (irq < 0 || irq >= NumSources) \
0076     printk("openpic.c:%d: illegal irq %d from 0x%08" PRIxPTR ",[0x%08" PRIxPTR "],[[0x%08" PRIxPTR "]]\n", \
0077            __LINE__, irq, (uintptr_t) __builtin_return_address(0), \
0078            (uintptr_t) __builtin_return_address(1), (uintptr_t) __builtin_return_address(2) \
0079            );
0080 #define check_arg_cpu(cpu) \
0081     if (cpu < 0 || cpu >= NumProcessors) \
0082     printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu);
0083 #else
0084 #define check_arg_ipi(ipi)  do {} while (0)
0085 #define check_arg_timer(timer)  do {} while (0)
0086 #define check_arg_vec(vec)  do {} while (0)
0087 #define check_arg_pri(pri)  do {} while (0)
0088 #define check_arg_irq(irq)  do {} while (0)
0089 #define check_arg_cpu(cpu)  do {} while (0)
0090 #endif
0091 
0092     /*
0093      *  I/O functions
0094      */
0095 
0096 static inline unsigned int openpic_read(volatile unsigned int *addr)
0097 {
0098     unsigned int val;
0099 
0100 #ifdef BSP_OPEN_PIC_BIG_ENDIAN
0101     val = in_be32((volatile uint32_t *)addr);
0102 #else
0103     val = in_le32((volatile uint32_t *)addr);
0104 #endif
0105 #ifdef REGISTER_DEBUG
0106     printk("openpic_read(0x%08x) = 0x%08x\n", (unsigned int)addr, val);
0107 #endif
0108     return val;
0109 }
0110 
0111 static inline void openpic_write(volatile unsigned int *addr, unsigned int val)
0112 {
0113 #ifdef REGISTER_DEBUG
0114     printk("openpic_write(0x%08x, 0x%08x)\n", (unsigned int)addr, val);
0115 #endif
0116 #ifdef BSP_OPEN_PIC_BIG_ENDIAN
0117     out_be32((volatile uint32_t *)addr, val);
0118 #else
0119     out_le32((volatile uint32_t *)addr, val);
0120 #endif
0121 }
0122 
0123 static inline unsigned int openpic_readfield(volatile unsigned int *addr, unsigned int mask)
0124 {
0125     unsigned int val = openpic_read(addr);
0126     return val & mask;
0127 }
0128 
0129 static inline void openpic_writefield(volatile unsigned int *addr, unsigned int mask,
0130                       unsigned int field)
0131 {
0132     unsigned int val = openpic_read(addr);
0133     openpic_write(addr, (val & ~mask) | (field & mask));
0134 }
0135 
0136 static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask)
0137 {
0138     openpic_writefield(addr, mask, 0);
0139 }
0140 
0141 static inline void openpic_setfield(volatile unsigned int *addr, unsigned int mask)
0142 {
0143     openpic_writefield(addr, mask, mask);
0144 }
0145 
0146     /*
0147      *  Update a Vector/Priority register in a safe manner. The interrupt will
0148      *  be disabled.
0149      */
0150 
0151 static void openpic_safe_writefield(volatile unsigned int *addr, unsigned int mask,
0152                     unsigned int field)
0153 {
0154     openpic_setfield(addr, OPENPIC_MASK);
0155     /* wait until it's not in use */
0156     while (openpic_read(addr) & OPENPIC_ACTIVITY);
0157     openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);
0158 }
0159 
0160 /* -------- Global Operations ---------------------------------------------- */
0161 
0162     /*
0163      *  Initialize the OpenPIC
0164      *
0165      * Add some kludge to use the Motorola Raven OpenPIC which does not
0166      * report vendor and device id, and gets the wrong number of interrupts.
0167      * (Motorola did a great job on that one!)
0168      *
0169      * T. Straumann, 12/20/2001: polarities and senses are now passed as
0170      *                           parameters, eliminated global vars.
0171      *                           IRQ0 is no longer treated specially.
0172      */
0173 
0174 void openpic_init(int main_pic, unsigned char *polarities, unsigned char *senses, int num_sources, int source_offset, unsigned long epic_freq)
0175 {
0176     unsigned int t, i;
0177     unsigned int vendorid, devid, stepping, timerfreq;
0178     const char *version, *vendor, *device;
0179 
0180     if (!OpenPIC)
0181     rtems_panic("No OpenPIC found");
0182 
0183     t = openpic_read(&OpenPIC->Global.Feature_Reporting0);
0184     switch (t & OPENPIC_FEATURE_VERSION_MASK) {
0185     case 1:
0186         version = "1.0";
0187         break;
0188     case 2:
0189         version = "1.2";
0190         break;
0191     default:
0192         version = "?";
0193         break;
0194     }
0195     NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >>
0196              OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1;
0197     NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >>
0198           OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1;
0199     t = openpic_read(&OpenPIC->Global.Vendor_Identification);
0200 
0201     vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK;
0202     devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >>
0203         OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT;
0204     stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >>
0205            OPENPIC_VENDOR_ID_STEPPING_SHIFT;
0206 
0207     /* Kludge for the Raven */
0208 /*
0209     pci_read_config_dword(0, 0, 0, 0, &t);
0210 */
0211     if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) {
0212         vendor = "Motorola";
0213     device = "Raven";
0214     NumSources += 1;
0215     }
0216     else if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_HAWK<<16)) {
0217         vendor = "Motorola";
0218     device = "Hawk";
0219     NumSources += 1;
0220     } else {
0221     switch (vendorid) {
0222         case OPENPIC_VENDOR_ID_APPLE:
0223         vendor = "Apple";
0224             break;
0225         default:
0226             vendor = "Unknown";
0227         break;
0228     }
0229     switch (devid) {
0230         case OPENPIC_DEVICE_ID_APPLE_HYDRA:
0231             device = "Hydra";
0232         break;
0233         default:
0234             device = "Unknown";
0235         break;
0236     }
0237     }
0238     printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at 0x%08" PRIuPTR "\n", version,
0239        NumProcessors, NumSources, (uintptr_t) OpenPIC);
0240 
0241     printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid,
0242        vendor, devid, device, stepping);
0243 
0244     /* Override if they desire */
0245     if ( num_sources ) {
0246         if ( NumSources != num_sources )
0247             printk("Overriding NumSources (%i) from configuration with %i\n",
0248                 NumSources, num_sources);
0249         NumSources = num_sources;
0250     }
0251 
0252     openpic_src_offst = source_offset;
0253 
0254     timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency);
0255     printk("OpenPIC timer frequency is ");
0256     if (timerfreq)
0257     printk("%d Hz\n", timerfreq);
0258     else
0259     printk("not set\n");
0260 
0261     if ( main_pic )
0262     {
0263         /* Initialize timer interrupts */
0264         for (i = 0; i < OPENPIC_NUM_TIMERS; i++) {
0265             /* Disabled, Priority 0 */
0266             openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i);
0267             /* No processor */
0268             openpic_maptimer(i, 0);
0269         }
0270 
0271         /* Initialize IPI interrupts */
0272         for (i = 0; i < OPENPIC_NUM_IPI; i++) {
0273             /* Disabled, Priority 0 */
0274             openpic_initipi(i, 0, OPENPIC_VEC_IPI+i);
0275         }
0276 
0277         /* Initialize external interrupts */
0278         for (i = 0; i < NumSources; i++) {
0279             /* Enabled, Priority 8 */
0280             openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i,
0281                     polarities ? polarities[i] : 0,
0282                     senses     ? senses[i]     : 1);
0283             /* Processor 0 */
0284             openpic_mapirq(i, 1<<0);
0285         }
0286 
0287         /* Initialize the spurious interrupt */
0288         openpic_set_spurious(OPENPIC_VEC_SPURIOUS);
0289 #if 0
0290         if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT,
0291                 "82c59 cascade", NULL))
0292           printk("Unable to get OpenPIC IRQ 0 for cascade\n");
0293 #endif
0294         openpic_set_priority(0, 0);
0295         openpic_disable_8259_pass_through();
0296     }
0297     if ( epic_freq ) {
0298         /* Speed up the serial interface; if it is too slow then we might get spurious
0299          * interrupts:
0300          * After an ISR clears the interrupt condition at the source/device, the wire
0301          * remains asserted during the propagation delay introduced by the serial interface
0302          * (something really stupid). If the ISR returns while the wire is not released
0303          * yet, then a spurious interrupt happens.
0304          * The book says we should be careful if the serial clock is > 33MHz.
0305          * Empirically, it seems that running it at 33MHz is fast enough. Otherwise,
0306          * we should introduce a delay in openpic_eoi().
0307          * The maximal delay are 16 (serial) clock cycles. If the divisor is 8
0308          * [power-up default] then the lag is 2us [66MHz SDRAM clock; I assume this
0309          * is equal to the bus frequency].
0310          * FIXME: This should probably be a EPIC-specific piece in 'openpic.c'
0311          *        Unfortunately, there is no easy way of figuring out if the
0312          *        device is an EPIC or not.
0313          */
0314         uint32_t eicr_val, ratio;
0315         /* On the 8240 this is the EICR register */
0316         eicr_val = in_le32( (volatile uint32_t *)&OpenPIC->Global.Global_Configuration1 ) & ~(7<<28);
0317         if ( (1<<27) & eicr_val ) {
0318             /* serial interface mode enabled */
0319 
0320             /* round to nearest integer:
0321              *   round(Bus_freq/33000000) = floor( 2*(Bus_freq/33e6) + 1 ) / 2
0322              */
0323             ratio   = epic_freq / 16500000 + 1;
0324             ratio >>= 2; /* EICR value is half actual divisor */
0325             if ( 0==ratio )
0326                 ratio = 1;
0327             out_le32((volatile uint32_t *)&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28));
0328             /*  Delay in TB cycles (assuming TB runs at 1/4 of the bus frequency) */
0329             openpic_set_eoi_delay( 16 * (2*ratio) / 4 );
0330         }
0331     }
0332 }
0333 
0334     /*
0335      *  Reset the OpenPIC
0336      */
0337 
0338 void openpic_reset(void)
0339 {
0340     openpic_setfield(&OpenPIC->Global.Global_Configuration0,
0341                    OPENPIC_CONFIG_RESET);
0342 }
0343 
0344     /*
0345      *  Enable/disable 8259 Pass Through Mode
0346      */
0347 
0348 void openpic_enable_8259_pass_through(void)
0349 {
0350     openpic_clearfield(&OpenPIC->Global.Global_Configuration0,
0351                    OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
0352 }
0353 
0354 void openpic_disable_8259_pass_through(void)
0355 {
0356     openpic_setfield(&OpenPIC->Global.Global_Configuration0,
0357                  OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);
0358 }
0359 
0360     /*
0361      *  Find out the current interrupt
0362      */
0363 
0364 unsigned int openpic_irq(unsigned int cpu)
0365 {
0366     unsigned int vec;
0367 
0368     check_arg_cpu(cpu);
0369     vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge,
0370                 OPENPIC_VECTOR_MASK);
0371     return vec;
0372 }
0373 
0374     /*
0375      *  Signal end of interrupt (EOI) processing
0376      */
0377 
0378 void openpic_eoi(unsigned int cpu)
0379 {
0380     check_arg_cpu(cpu);
0381     if ( openpic_eoi_delay )
0382         rtems_bsp_delay_in_bus_cycles(openpic_eoi_delay);
0383     openpic_write(&OpenPIC->THIS_CPU.EOI, 0);
0384 }
0385 
0386 unsigned openpic_set_eoi_delay(unsigned tb_cycles)
0387 {
0388 unsigned rval = openpic_eoi_delay;
0389     openpic_eoi_delay = tb_cycles;
0390     return rval;
0391 }
0392 
0393     /*
0394      *  Get/set the current task priority
0395      */
0396 
0397 unsigned int openpic_get_priority(unsigned int cpu)
0398 {
0399     CHECK_THIS_CPU;
0400     return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority,
0401                  OPENPIC_CURRENT_TASK_PRIORITY_MASK);
0402 }
0403 
0404 void openpic_set_priority(unsigned int cpu, unsigned int pri)
0405 {
0406     CHECK_THIS_CPU;
0407     check_arg_pri(pri);
0408     openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority,
0409                    OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);
0410 }
0411 
0412     /*
0413      *  Get/set the spurious vector
0414      */
0415 
0416 unsigned int openpic_get_spurious(void)
0417 {
0418     return openpic_readfield(&OpenPIC->Global.Spurious_Vector,
0419                      OPENPIC_VECTOR_MASK);
0420 }
0421 
0422 void openpic_set_spurious(unsigned int vec)
0423 {
0424     check_arg_vec(vec);
0425     openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK,
0426                    vec);
0427 }
0428 
0429     /*
0430      *  Initialize one or more CPUs
0431      */
0432 
0433 void openpic_init_processor(unsigned int cpumask)
0434 {
0435     openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask);
0436 }
0437 
0438 /* -------- Interprocessor Interrupts -------------------------------------- */
0439 
0440     /*
0441      *  Initialize an interprocessor interrupt (and disable it)
0442      *
0443      *  ipi: OpenPIC interprocessor interrupt number
0444      *  pri: interrupt source priority
0445      *  vec: the vector it will produce
0446      */
0447 
0448 void openpic_initipi(unsigned int ipi, unsigned int pri, unsigned int vec)
0449 {
0450     check_arg_timer(ipi);
0451     check_arg_pri(pri);
0452     check_arg_vec(vec);
0453     openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi),
0454                     OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
0455                     (pri << OPENPIC_PRIORITY_SHIFT) | vec);
0456 }
0457 
0458     /*
0459      *  Send an IPI to one or more CPUs
0460      */
0461 
0462 void openpic_cause_IPI(unsigned int cpu, unsigned int ipi, unsigned int cpumask)
0463 {
0464     CHECK_THIS_CPU;
0465     check_arg_ipi(ipi);
0466     openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask);
0467 }
0468 
0469 /* -------- Timer Interrupts ----------------------------------------------- */
0470 
0471     /*
0472      *  Initialize a timer interrupt (and disable it)
0473      *
0474      *  timer: OpenPIC timer number
0475      *  pri: interrupt source priority
0476      *  vec: the vector it will produce
0477      */
0478 
0479 void openpic_inittimer(unsigned int timer, unsigned int pri, unsigned int vec)
0480 {
0481     check_arg_timer(timer);
0482     check_arg_pri(pri);
0483     check_arg_vec(vec);
0484     openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority,
0485                     OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK,
0486                     (pri << OPENPIC_PRIORITY_SHIFT) | vec);
0487 }
0488 
0489     /*
0490      *  Map a timer interrupt to one or more CPUs
0491      */
0492 
0493 void openpic_maptimer(unsigned int timer, unsigned int cpumask)
0494 {
0495     check_arg_timer(timer);
0496     openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask);
0497 }
0498 
0499     /*
0500      *  Set base count and / or enable / disable interrupt.
0501      */
0502 
0503 
0504 void openpic_settimer(unsigned int timer, unsigned int base_count, int irq_enable)
0505 {
0506     check_arg_timer(timer);
0507     if ( base_count )
0508         openpic_write(&OpenPIC->Global.Timer[timer].Base_Count, base_count);
0509     if ( irq_enable )
0510         openpic_clearfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK);
0511     else
0512         openpic_setfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK);
0513 }
0514 
0515 unsigned int openpic_gettimer(unsigned int timer)
0516 {
0517     check_arg_timer(timer);
0518     return (openpic_read(&OpenPIC->Global.Timer[timer].Current_Count) & ~OPENPIC_MASK);
0519 }
0520 
0521 /* -------- Interrupt Sources ---------------------------------------------- */
0522 
0523     /*
0524      *  Enable/disable an interrupt source
0525      */
0526 
0527 void openpic_enable_irq(unsigned int irq)
0528 {
0529 unsigned long flags;
0530     check_arg_irq(irq);
0531     rtems_interrupt_disable(flags);
0532     openpic_clearfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK);
0533     rtems_interrupt_enable(flags);
0534 }
0535 
0536 int openpic_disable_irq(unsigned int irq)
0537 {
0538 int           rval;
0539 unsigned long flags;
0540     check_arg_irq(irq);
0541     if ( irq < 0 || irq >=NumSources )
0542         return -1;
0543     rtems_interrupt_disable(flags);
0544     rval = openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK) ? 0 : 1;
0545     openpic_setfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK);
0546     rtems_interrupt_enable(flags);
0547     return rval;
0548 }
0549 
0550     /*
0551      *  Initialize an interrupt source (and disable it!)
0552      *
0553      *  irq: OpenPIC interrupt number
0554      *  pri: interrupt source priority
0555      *  vec: the vector it will produce
0556      *  pol: polarity (1 for positive, 0 for negative)
0557      *  sense: 1 for level, 0 for edge
0558      */
0559 
0560 void openpic_initirq(unsigned int irq, unsigned int pri, unsigned int vec, int pol, int sense)
0561 {
0562 #if 0
0563   printk("openpic_initirq: irq=%d pri=%d vec=%d pol=%d sense=%d\n",
0564     irq, pri, vec, pol, sense);
0565 #endif
0566 
0567     check_arg_irq(irq);
0568     check_arg_pri(pri);
0569     check_arg_vec(vec);
0570     openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority,
0571                     OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK |
0572                     OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL,
0573                     (pri << OPENPIC_PRIORITY_SHIFT) | vec |
0574                 (pol ? OPENPIC_SENSE_POLARITY : 0) |
0575                 (sense ? OPENPIC_SENSE_LEVEL : 0));
0576 }
0577 
0578     /*
0579      *  Map an interrupt source to one or more CPUs
0580      */
0581 
0582 void openpic_mapirq(unsigned int irq, unsigned int cpumask)
0583 {
0584     check_arg_irq(irq);
0585     openpic_write(&OpenPIC->SOURCE(irq).Destination, cpumask);
0586 }
0587 
0588     /*
0589      * Get the current priority of an external interrupt
0590      */
0591 unsigned int openpic_get_source_priority(unsigned int irq)
0592 {
0593     check_arg_irq(irq);
0594     return openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority,
0595                              OPENPIC_PRIORITY_MASK) >> OPENPIC_PRIORITY_SHIFT;
0596 }
0597 
0598 void openpic_set_source_priority(unsigned int irq, unsigned int pri)
0599 {
0600 unsigned long flags;
0601     check_arg_irq(irq);
0602     check_arg_pri(pri);
0603     rtems_interrupt_disable(flags);
0604     openpic_writefield(
0605                     &OpenPIC->SOURCE(irq).Vector_Priority,
0606                     OPENPIC_PRIORITY_MASK,
0607                     pri << OPENPIC_PRIORITY_SHIFT);
0608     rtems_interrupt_enable(flags);
0609 }
0610     /*
0611      *  Set the sense for an interrupt source (and disable it!)
0612      *
0613      *  sense: 1 for level, 0 for edge
0614      */
0615 
0616 void openpic_set_sense(unsigned int irq, int sense)
0617 {
0618     check_arg_irq(irq);
0619     openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority,
0620                     OPENPIC_SENSE_LEVEL,
0621                 (sense ? OPENPIC_SENSE_LEVEL : 0));
0622 }