source: rtems/c/src/exec/score/cpu/powerpc/cpu.c @ 72b397a

4.104.114.84.95
Last change on this file since 72b397a was 72b397a, checked in by Joel Sherrill <joel.sherrill@…>, on Mar 24, 1998 at 5:10:44 PM

Corrected register constraints per suggestion from Thomas Doerfler, IMD
<td@…>.

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 *  PowerPC CPU Dependent Source
3 *
4 *  Author:     Andrew Bray <andy@i-cubed.co.uk>
5 *
6 *  COPYRIGHT (c) 1995 by i-cubed ltd.
7 *
8 *  To anyone who acknowledges that this file is provided "AS IS"
9 *  without any express or implied warranty:
10 *      permission to use, copy, modify, and distribute this file
11 *      for any purpose is hereby granted without fee, provided that
12 *      the above copyright notice and this notice appears in all
13 *      copies, and that the name of i-cubed limited not be used in
14 *      advertising or publicity pertaining to distribution of the
15 *      software without specific, written prior permission.
16 *      i-cubed limited makes no representations about the suitability
17 *      of this software for any purpose.
18 *
19 *  Derived from c/src/exec/cpu/no_cpu/cpu.c:
20 *
21 *  COPYRIGHT (c) 1989-1998.
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 be
26 *  found in the file LICENSE in this distribution or at
27 *  http://www.OARcorp.com/rtems/license.html.
28 *
29 *  $Id$
30 */
31
32#include <rtems/system.h>
33#include <rtems/score/isr.h>
34#include <rtems/score/context.h>
35#include <rtems/score/thread.h>
36
37/*
38 *  These are for testing purposes.
39 */
40#undef Testing
41
42#ifdef Testing
43static unsigned32 msr;
44#ifdef ppc403
45static unsigned32 evpr;
46static unsigned32 exier;
47#endif
48#endif
49
50/*
51 *  ppc_interrupt_level_to_msr
52 *
53 *  This routine converts a two bit interrupt level to an MSR bit map.
54 */
55
56const unsigned32 _CPU_msrs[4] =
57  { PPC_MSR_0, PPC_MSR_1, PPC_MSR_2, PPC_MSR_3 };
58
59/*  _CPU_Initialize
60 *
61 *  This routine performs processor dependent initialization.
62 *
63 *  INPUT PARAMETERS:
64 *    cpu_table       - CPU table to initialize
65 *    thread_dispatch - address of disptaching routine
66 */
67
68static void ppc_spurious(int, CPU_Interrupt_frame *);
69
70void _CPU_Initialize(
71  rtems_cpu_table  *cpu_table,
72  void      (*thread_dispatch)      /* ignored on this CPU */
73)
74{
75  proc_ptr handler = (proc_ptr)ppc_spurious;
76  int i;
77#if (PPC_ABI != PPC_ABI_POWEROPEN)
78  register unsigned32 r2;
79#if (PPC_ABI != PPC_ABI_GCC27)
80  register unsigned32 r13;
81
82  asm ("mr %0,13" : "=r" ((r13)) : "0" ((r13)));
83  _CPU_IRQ_info.Default_r13 = r13;
84#endif
85
86  asm ("mr %0,2" : "=r" ((r2)) : "0" ((r2)));
87  _CPU_IRQ_info.Default_r2 = r2;
88#endif
89
90  _CPU_IRQ_info.Nest_level = &_ISR_Nest_level;
91  _CPU_IRQ_info.Disable_level = &_Thread_Dispatch_disable_level;
92  _CPU_IRQ_info.Vector_table = _ISR_Vector_table;
93#if (PPC_ABI == PPC_ABI_POWEROPEN)
94  _CPU_IRQ_info.Dispatch_r2 = ((unsigned32 *)_Thread_Dispatch)[1];
95#endif
96  _CPU_IRQ_info.Switch_necessary = &_Context_Switch_necessary;
97  _CPU_IRQ_info.Signal = &_ISR_Signals_to_thread_executing;
98
99  i = (int)&_CPU_IRQ_info;
100  asm volatile("mtspr 0x113, %0" : "=r" (i) : "0" (i)); /* SPRG 3 */
101
102  i = PPC_MSR_INITIAL & ~PPC_MSR_DISABLE_MASK;
103  asm volatile("mtspr 0x112, %0" : "=r" (i) : "0" (i)); /* SPRG 2 */
104
105#ifdef Testing
106  {
107    unsigned32 tmp;
108
109    asm volatile ("mfmsr %0" : "=&r" (tmp));
110    msr = tmp;
111#ifdef ppc403
112    asm volatile ("mfspr %0, 0x3d6" : "=&r" (tmp)); /* EVPR */
113    evpr = tmp;
114    asm volatile ("mfdcr %0, 0x42" : "=&r" (tmp)); /* EXIER */
115    exier = tmp;
116    asm volatile ("mtspr 0x3d6, %0" :: "r" (0)); /* EVPR */
117#endif
118  }
119#endif
120
121  if ( cpu_table->spurious_handler )
122    handler = (proc_ptr)cpu_table->spurious_handler;
123
124  for (i = 0; i < PPC_INTERRUPT_MAX;  i++)
125    _ISR_Vector_table[i] = handler;
126
127  _CPU_Table = *cpu_table;
128}
129
130/*PAGE
131 *
132 *  _CPU_ISR_Get_level
133 *
134 *  COMMENTS FROM Andrew Bray <andy@i-cubed.co.uk>:
135 *
136 *  The PowerPC puts its interrupt enable status in the MSR register
137 *  which also contains things like endianness control.  To be more
138 *  awkward, the layout varies from processor to processor.  This
139 *  is why I adopted a table approach in my interrupt handling.
140 *  Thus the inverse process is slow, because it requires a table
141 *  search.
142 *
143 *  This could fail, and return 4 (an invalid level) if the MSR has been
144 *  set to a value not in the table.  This is also quite an expensive
145 *  operation - I do hope its not too common.
146 *
147 */
148 
149unsigned32 _CPU_ISR_Get_level( void )
150{
151  unsigned32 level, msr;
152 
153  asm volatile("mfmsr %0" : "=r" ((msr)));
154 
155  msr &= PPC_MSR_DISABLE_MASK;
156 
157  for (level = 0; level < 4; level++)
158    if ((_CPU_msrs[level] & PPC_MSR_DISABLE_MASK) == msr)
159      break;
160 
161  return level;
162}
163
164/*  _CPU_ISR_install_vector
165 *
166 *  This kernel routine installs the RTEMS handler for the
167 *  specified vector.
168 *
169 *  Input parameters:
170 *    vector      - interrupt vector number
171 *    old_handler - former ISR for this vector number
172 *    new_handler - replacement ISR for this vector number
173 *
174 *  Output parameters:  NONE
175 *
176 */
177
178void _CPU_ISR_install_vector(
179  unsigned32  vector,
180  proc_ptr    new_handler,
181  proc_ptr   *old_handler
182)
183{
184   *old_handler = _ISR_Vector_table[ vector ];
185
186   /*
187    *  If the interrupt vector table is a table of pointer to isr entry
188    *  points, then we need to install the appropriate RTEMS interrupt
189    *  handler for this vector number.
190    */
191
192   /*
193    *  We put the actual user ISR address in '_ISR_vector_table'.  This will
194    *  be used by the _ISR_Handler so the user gets control.
195    */
196
197    _ISR_Vector_table[ vector ] = new_handler ? (ISR_Handler_entry)new_handler :
198       _CPU_Table.spurious_handler ? 
199          (ISR_Handler_entry)_CPU_Table.spurious_handler :
200          (ISR_Handler_entry)ppc_spurious;
201}
202
203/*PAGE
204 *
205 *  _CPU_Install_interrupt_stack
206 */
207
208void _CPU_Install_interrupt_stack( void )
209{
210#if (PPC_ABI == PPC_ABI_POWEROPEN || PPC_ABI == PPC_ABI_GCC27)
211  _CPU_IRQ_info.Stack = _CPU_Interrupt_stack_high - 56;
212#else
213  _CPU_IRQ_info.Stack = _CPU_Interrupt_stack_high - 8;
214#endif
215}
216
217/* Handle a spurious interrupt */
218static void ppc_spurious(int v, CPU_Interrupt_frame *i)
219{
220#if 0
221    printf("Spurious interrupt on vector %d from %08.8x\n",
222           v, i->pc);
223#endif
224#ifdef ppc403
225    if (v == PPC_IRQ_EXTERNAL)
226        {
227            register int r = 0;
228
229            asm volatile("mtdcr 0x42, %0" : "=r" ((r)) : "0" ((r))); /* EXIER */
230        }
231    else if (v == PPC_IRQ_PIT)
232        {
233            register int r = 0x08000000;
234
235            asm volatile("mtspr 0x3d8, %0" : "=r" ((r)) : "0" ((r))); /* TSR */
236        }
237    else if (v == PPC_IRQ_FIT)
238        {
239            register int r = 0x04000000;
240
241            asm volatile("mtspr 0x3d8, %0" : "=r" ((r)) : "0" ((r))); /* TSR */
242        }
243#endif
244}
245
246void _CPU_Fatal_error(unsigned32 _error)
247{
248#ifdef Testing
249  unsigned32 tmp;
250
251  tmp = msr;
252  asm volatile ("mtmsr %0" :: "r" (tmp));
253#ifdef ppc403
254  tmp = evpr;
255  asm volatile ("mtspr 0x3d6, %0" :: "r" (tmp)); /* EVPR */
256  tmp = exier;
257  asm volatile ("mtdcr 0x42, %0" :: "r" (tmp)); /* EXIER */
258#endif
259#endif
260  asm volatile ("mr 3, %0" : : "r" ((_error)));
261  asm volatile ("tweq 5,5");
262  asm volatile ("li 0,0; mtmsr 0");
263  while (1) ;
264}
Note: See TracBrowser for help on using the repository browser.