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