source: rtems/c/src/lib/libbsp/powerpc/ppcn_60x/startup/genpvec.c @ f05b2ac

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 7.1 KB
Line 
1/*
2 *  COPYRIGHT (c) 1998 by Radstone Technology
3 *
4 *
5 * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
6 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
7 * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
8 * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
9 *
10 * You are hereby granted permission to use, copy, modify, and distribute
11 * this file, provided that this notice, plus the above copyright notice
12 * and disclaimer, appears in all copies. Radstone Technology will provide
13 * no support for this code.
14 *
15 */
16/*  genpvec.c
17 *
18 *  These routines handle the external exception.  Multiple ISRs occur off
19 *  of this one interrupt.
20 *
21 *  COPYRIGHT (c) 1989-1997.
22 *  On-Line Applications Research Corporation (OAR).
23 *
24 *  The license and distribution terms for this file may in
25 *  the file LICENSE in this distribution or at
26 *  http://www.rtems.com/license/LICENSE.
27 *
28 *  $Id$
29 */
30
31#include <bsp.h>
32#include <rtems/chain.h>
33#include <assert.h>
34
35/*
36 * Proto types for this file
37 */
38
39rtems_isr external_exception_ISR (
40  rtems_vector_number   vector                                  /* IN  */
41);
42
43#define   NUM_LIRQ_HANDLERS   20
44#define   NUM_LIRQ            ( MAX_BOARD_IRQS - PPC_IRQ_LAST )
45
46/*
47 * Current 8259 masks
48 */
49uint8_t         ucMaster8259Mask;
50uint8_t         ucSlave8259Mask;
51
52/*
53 * Structure to for one of possible multiple interrupt handlers for
54 * a given interrupt.
55 */
56typedef struct
57{
58  Chain_Node          Node;
59  rtems_isr_entry     handler;                  /* isr routine        */
60  rtems_vector_number vector;                   /* vector number      */
61} EE_ISR_Type;
62
63/* Note:  The following will not work if we add a method to remove
64 *        handlers at a later time.
65 */
66  EE_ISR_Type       ISR_Nodes [NUM_LIRQ_HANDLERS];
67  uint16_t          Nodes_Used;
68  Chain_Control     ISR_Array  [NUM_LIRQ];
69
70void initialize_external_exception_vector()
71{
72        rtems_isr_entry previous_isr;
73        rtems_status_code status;
74        int i;
75
76        Nodes_Used = 0;
77
78        for (i=0; i <NUM_LIRQ; i++)
79        {
80                Chain_Initialize_empty( &ISR_Array[i] );
81        }
82
83        /*
84         * Initialise the 8259s
85         */
86        outport_byte(ISA8259_M_CTRL, 0x11); /* ICW1 */
87        outport_byte(ISA8259_S_CTRL, 0x11); /* ICW1 */
88        outport_byte(ISA8259_M_MASK, 0x00); /* ICW2 vectors 0-7 */
89        outport_byte(ISA8259_S_MASK, 0x08); /* ICW2 vectors 8-15 */
90        outport_byte(ISA8259_M_MASK, 0x04); /* ICW3 cascade on IRQ2 */
91        outport_byte(ISA8259_S_MASK, 0x02); /* ICW3 cascade on IRQ2 */
92        outport_byte(ISA8259_M_MASK, 0x01); /* ICW4 x86 normal EOI */
93        outport_byte(ISA8259_S_MASK, 0x01); /* ICW4 x86 normal EOI */
94
95        /*
96         * Enable IRQ2 cascade and disable all other interrupts
97         */
98        ucMaster8259Mask=0xfb;
99        ucSlave8259Mask=0xff;
100
101        outport_byte(ISA8259_M_MASK, ucMaster8259Mask);
102        outport_byte(ISA8259_S_MASK, ucSlave8259Mask);
103
104        /*
105         * Set up edge/level
106         */
107        switch(ucSystemType)
108        {
109                case SYS_TYPE_PPC1:
110                {
111                        if(ucBoardRevMaj<5)
112                        {
113                                outport_byte(ISA8259_S_ELCR,
114                                             ELCRS_INT15_LVL);
115                        }
116                        else
117                        {
118                                outport_byte(ISA8259_S_ELCR,
119                                             ELCRS_INT9_LVL |
120                                             ELCRS_INT11_LVL |
121                                             ELCRS_INT14_LVL |
122                                             ELCRS_INT15_LVL);
123                        }
124                        outport_byte(ISA8259_M_ELCR,
125                                     ELCRM_INT5_LVL |
126                                     ELCRM_INT7_LVL);
127                        break;
128                }
129
130                case SYS_TYPE_PPC1a:
131                {
132                        outport_byte(ISA8259_S_ELCR,
133                                     ELCRS_INT9_LVL |
134                                     ELCRS_INT11_LVL |
135                                     ELCRS_INT14_LVL |
136                                     ELCRS_INT15_LVL);
137                        outport_byte(ISA8259_M_ELCR,
138                                     ELCRM_INT5_LVL);
139                        break;
140                }
141
142                case SYS_TYPE_PPC2:
143                case SYS_TYPE_PPC2a:
144                case SYS_TYPE_PPC4:
145                default:
146                {
147                        outport_byte(ISA8259_S_ELCR,
148                                     ELCRS_INT9_LVL |
149                                     ELCRS_INT10_LVL |
150                                     ELCRS_INT11_LVL |
151                                     ELCRS_INT14_LVL |
152                                     ELCRS_INT15_LVL);
153                        outport_byte(ISA8259_M_ELCR,
154                                     ELCRM_INT5_LVL |
155                                     ELCRM_INT7_LVL);
156                        break;
157                }
158        }
159
160        /*
161         * Install external_exception_ISR () as the handler for
162         *  the General Purpose Interrupt.
163         */
164
165        status = rtems_interrupt_catch( external_exception_ISR,
166                                        PPC_IRQ_EXTERNAL,
167                                        (rtems_isr_entry *) &previous_isr );
168}
169
170/*
171 *  This routine installs one of multiple ISRs for the general purpose
172 *  inerrupt.
173 */
174void set_EE_vector(
175  rtems_isr_entry     handler,      /* isr routine        */
176  rtems_vector_number vector        /* vector number      */
177)
178{
179        uint16_t         vec_idx  = vector - PPCN_60X_8259_IRQ_BASE;
180        uint32_t         index;
181
182        assert  (Nodes_Used < NUM_LIRQ_HANDLERS);
183
184        /*
185         *  If we have already installed this handler for this vector, then
186         *  just reset it.
187         */
188
189        for ( index=0 ; index < Nodes_Used ; index++ )
190        {
191                if(ISR_Nodes[index].vector == vector &&
192                   ISR_Nodes[index].handler == handler)
193                {
194                        return;
195                }
196        }
197
198        /*
199         *  Doing things in this order makes them more atomic
200         */
201
202        Nodes_Used++;
203
204        index = Nodes_Used - 1;
205
206        ISR_Nodes[index].handler = handler;
207        ISR_Nodes[index].vector  = vector;
208
209        Chain_Append( &ISR_Array[vec_idx], &ISR_Nodes[index].Node );
210
211        /*
212         * Enable the interrupt
213         */
214        En_Ext_Interrupt(vector);
215}
216
217/*
218 * This interrupt service routine is called for an External Exception.
219 */
220rtems_isr external_exception_ISR (
221  rtems_vector_number   vector             /* IN  */
222)
223{
224        uint16_t        index;
225        uint8_t         ucISr;
226        EE_ISR_Type     *node;
227
228        index = *((volatile uint8_t*)IRQ_VECTOR_BASE);
229
230        /*
231         * check for spurious interrupt
232         */
233        if(index==7)
234        {
235                /*
236                 * OCW3 select IS register
237                 */
238                outport_byte(ISA8259_M_CTRL, 0x0b);
239                /*
240                 * Read IS register
241                 */
242                inport_byte(ISA8259_M_CTRL, ucISr);
243                if(!(ucISr & 0x80))
244                {
245                        /*
246                         * Spurious interrupt
247                         */
248                        return;
249                }
250        }
251
252        node=(EE_ISR_Type *)ISR_Array[index].first;
253        while(!_Chain_Is_tail(&ISR_Array[index], (Chain_Node *)node))
254        {
255                (*node->handler)( node->vector );
256                node = (EE_ISR_Type *)node->Node.next;
257        }
258
259        /*
260         * Dismiss the interrupt
261         */
262        if(index&8)
263        {
264                /*
265                 * Dismiss the interrupt in Slave first as it
266                 * is cascaded
267                 */
268                outport_byte(ISA8259_S_CTRL, NONSPECIFIC_EOI);
269        }
270
271        /*
272         * Dismiss the interrupt in Master
273         */
274        outport_byte(ISA8259_M_CTRL, NONSPECIFIC_EOI);
275}
276
277void Dis_Ext_Interrupt(int level)
278{
279        ISR_Level Irql;
280
281        level-=PPCN_60X_8259_IRQ_BASE;
282
283        if(level==2)
284        {
285                /*
286                 * Level 2 is for cascade and must not be fiddled with
287                 */
288                return;
289        }
290
291        /*
292         * Ensure that accesses to the mask are indivisible
293         */
294        _ISR_Disable(Irql);
295
296        if(level<8)
297        {
298                /*
299                 * Interrupt is handled by Master
300                 */
301                ucMaster8259Mask|=1<<level;
302                outport_byte(ISA8259_M_MASK, ucMaster8259Mask);
303        }
304        else
305        {
306                /*
307                 * Interrupt is handled by Slave
308                 */
309                ucSlave8259Mask|=1<<(level-8);
310                outport_byte(ISA8259_S_MASK, ucSlave8259Mask);
311        }
312        _ISR_Enable(Irql);
313}
314
315void En_Ext_Interrupt(int level)
316{
317        ISR_Level Irql;
318
319        level-=PPCN_60X_8259_IRQ_BASE;
320
321        if(level==2)
322        {
323                /*
324                 * Level 2 is for cascade and must not be fiddled with
325                 */
326                return;
327        }
328
329        /*
330         * Ensure that accesses to the mask are indivisible
331         */
332        _ISR_Disable(Irql);
333
334        if(level<8)
335        {
336                /*
337                 * Interrupt is handled by Master
338                 */
339                ucMaster8259Mask&=~(1<<level);
340                outport_byte(ISA8259_M_MASK, ucMaster8259Mask);
341        }
342        else
343        {
344                /*
345                 * Interrupt is handled by Slave
346                 */
347                ucSlave8259Mask&=~(1<<(level-8));
348                outport_byte(ISA8259_S_MASK, ucSlave8259Mask);
349        }
350
351        _ISR_Enable(Irql);
352}
Note: See TracBrowser for help on using the repository browser.