[ac7d5ef0] | 1 | /* |
---|
| 2 | * Intel i386 Dependent Source |
---|
| 3 | * |
---|
| 4 | * |
---|
| 5 | * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. |
---|
| 6 | * On-Line Applications Research Corporation (OAR). |
---|
| 7 | * All rights assigned to U.S. Government, 1994. |
---|
| 8 | * |
---|
| 9 | * This material may be reproduced by or for the U.S. Government pursuant |
---|
| 10 | * to the copyright license under the clause at DFARS 252.227-7013. This |
---|
| 11 | * notice must appear in all copies of this file and its derivatives. |
---|
| 12 | * |
---|
| 13 | * $Id$ |
---|
| 14 | */ |
---|
| 15 | |
---|
| 16 | #include <rtems/system.h> |
---|
| 17 | #include <rtems/fatal.h> |
---|
| 18 | #include <rtems/isr.h> |
---|
| 19 | #include <rtems/wkspace.h> |
---|
| 20 | |
---|
| 21 | /* _CPU_Initialize |
---|
| 22 | * |
---|
| 23 | * This routine performs processor dependent initialization. |
---|
| 24 | * |
---|
| 25 | * INPUT PARAMETERS: |
---|
| 26 | * cpu_table - CPU table to initialize |
---|
| 27 | * thread_dispatch - address of disptaching routine |
---|
| 28 | */ |
---|
| 29 | |
---|
| 30 | |
---|
| 31 | void _CPU_Initialize( |
---|
| 32 | rtems_cpu_table *cpu_table, |
---|
| 33 | void (*thread_dispatch) /* ignored on this CPU */ |
---|
| 34 | ) |
---|
| 35 | { |
---|
| 36 | register unsigned16 fp_status asm ("ax"); |
---|
| 37 | register unsigned8 *fp_context; |
---|
| 38 | |
---|
| 39 | if ( cpu_table == NULL ) |
---|
| 40 | rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED ); |
---|
| 41 | |
---|
| 42 | _CPU_Table = *cpu_table; |
---|
| 43 | |
---|
| 44 | /* |
---|
| 45 | * The following code saves a NULL i387 context which is given |
---|
| 46 | * to each task at start and restart time. The following code |
---|
| 47 | * is based upon that provided in the i386 Programmer's |
---|
| 48 | * Manual and should work on any coprocessor greater than |
---|
| 49 | * the i80287. |
---|
| 50 | * |
---|
| 51 | * NOTE: The NO RTEMS_WAIT form of the coprocessor instructions |
---|
| 52 | * MUST be used in case there is not a coprocessor |
---|
| 53 | * to wait for. |
---|
| 54 | */ |
---|
| 55 | |
---|
| 56 | fp_status = 0xa5a5; |
---|
| 57 | asm volatile( "fninit" ); |
---|
| 58 | asm volatile( "fnstsw %0" : "=a" (fp_status) : "0" (fp_status) ); |
---|
| 59 | |
---|
| 60 | if ( fp_status == 0 ) { |
---|
| 61 | |
---|
| 62 | fp_context = _CPU_Null_fp_context; |
---|
| 63 | |
---|
| 64 | asm volatile( "fsave (%0)" : "=r" (fp_context) |
---|
| 65 | : "0" (fp_context) |
---|
| 66 | ); |
---|
| 67 | } |
---|
| 68 | } |
---|
| 69 | |
---|
[637df35] | 70 | /*PAGE |
---|
| 71 | * |
---|
| 72 | * _CPU_ISR_install_raw_handler |
---|
| 73 | */ |
---|
| 74 | |
---|
| 75 | #if __GO32__ |
---|
| 76 | #include <go32.h> |
---|
| 77 | #include <dpmi.h> |
---|
| 78 | #endif /* __GO32__ */ |
---|
| 79 | |
---|
| 80 | void _CPU_ISR_install_raw_handler( |
---|
| 81 | unsigned32 vector, |
---|
| 82 | proc_ptr new_handler, |
---|
| 83 | proc_ptr *old_handler |
---|
| 84 | ) |
---|
| 85 | { |
---|
| 86 | #if __GO32__ |
---|
| 87 | _go32_dpmi_seginfo handler_info; |
---|
| 88 | |
---|
[1690c6b] | 89 | /* get the address of the old handler */ |
---|
| 90 | _go32_dpmi_get_protected_mode_interrupt_vector( vector, &handler_info); |
---|
| 91 | |
---|
| 92 | /* Notice how we're failing to save the pm_segment portion of the */ |
---|
| 93 | /* structure here? That means we might crash the system if we */ |
---|
| 94 | /* try to restore the ISR. Can't fix this until i386_isr is */ |
---|
| 95 | /* redefined. XXX [BHC]. */ |
---|
| 96 | *old_handler = (proc_ptr *) handler_info.pm_offset; |
---|
[637df35] | 97 | |
---|
[8044533] | 98 | handler_info.pm_offset = (u_long) new_handler; |
---|
[637df35] | 99 | handler_info.pm_selector = _go32_my_cs(); |
---|
| 100 | |
---|
| 101 | /* install the IDT entry */ |
---|
| 102 | _go32_dpmi_set_protected_mode_interrupt_vector( vector, &handler_info ); |
---|
| 103 | #else |
---|
| 104 | i386_IDT_slot idt; |
---|
| 105 | unsigned32 handler; |
---|
| 106 | |
---|
| 107 | *old_handler = 0; /* XXX not supported */ |
---|
| 108 | |
---|
| 109 | handler = (unsigned32) new_handler; |
---|
| 110 | |
---|
| 111 | /* build the IDT entry */ |
---|
| 112 | idt.offset_0_15 = handler & 0xffff; |
---|
| 113 | idt.segment_selector = i386_get_cs(); |
---|
| 114 | idt.reserved = 0x00; |
---|
| 115 | idt.p_dpl = 0x8e; /* present, ISR */ |
---|
| 116 | idt.offset_16_31 = handler >> 16; |
---|
| 117 | |
---|
| 118 | /* install the IDT entry */ |
---|
| 119 | i386_Install_idt( |
---|
| 120 | (unsigned32) &idt, |
---|
| 121 | _CPU_Table.interrupt_table_segment, |
---|
| 122 | (unsigned32) _CPU_Table.interrupt_table_offset + (8 * vector) |
---|
| 123 | ); |
---|
| 124 | #endif |
---|
| 125 | } |
---|
| 126 | |
---|
| 127 | /*PAGE |
---|
| 128 | * |
---|
| 129 | * _CPU_ISR_install_vector |
---|
[ac7d5ef0] | 130 | * |
---|
| 131 | * This kernel routine installs the RTEMS handler for the |
---|
| 132 | * specified vector. |
---|
| 133 | * |
---|
| 134 | * Input parameters: |
---|
| 135 | * vector - interrupt vector number |
---|
| 136 | * old_handler - former ISR for this vector number |
---|
| 137 | * new_handler - replacement ISR for this vector number |
---|
| 138 | * |
---|
| 139 | * Output parameters: NONE |
---|
| 140 | * |
---|
| 141 | */ |
---|
| 142 | |
---|
| 143 | void _ISR_Handler_0(), _ISR_Handler_1(); |
---|
| 144 | |
---|
| 145 | #define PER_ISR_ENTRY \ |
---|
| 146 | (((unsigned32) _ISR_Handler_1 - (unsigned32) _ISR_Handler_0)) |
---|
| 147 | |
---|
| 148 | #define _Interrupt_Handler_entry( _vector ) \ |
---|
| 149 | (((unsigned32)_ISR_Handler_0) + ((_vector) * PER_ISR_ENTRY)) |
---|
| 150 | |
---|
| 151 | void _CPU_ISR_install_vector( |
---|
| 152 | unsigned32 vector, |
---|
| 153 | proc_ptr new_handler, |
---|
| 154 | proc_ptr *old_handler |
---|
| 155 | ) |
---|
| 156 | { |
---|
[637df35] | 157 | proc_ptr ignored; |
---|
[ac7d5ef0] | 158 | unsigned32 unique_handler; |
---|
| 159 | |
---|
[637df35] | 160 | *old_handler = _ISR_Vector_table[ vector ]; |
---|
| 161 | |
---|
[ac7d5ef0] | 162 | /* calculate the unique entry point for this vector */ |
---|
| 163 | unique_handler = _Interrupt_Handler_entry( vector ); |
---|
| 164 | |
---|
[637df35] | 165 | _CPU_ISR_install_raw_handler( vector, (void *)unique_handler, &ignored ); |
---|
[ac7d5ef0] | 166 | |
---|
| 167 | _ISR_Vector_table[ vector ] = new_handler; |
---|
| 168 | } |
---|