Coding style cleanup
[platform/kernel/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / ntdrv / _irq.asm
1 ;****************************************************************************
2 ;*
3 ;*                  SciTech OS Portability Manager Library
4 ;*
5 ;*  ========================================================================
6 ;*
7 ;*    The contents of this file are subject to the SciTech MGL Public
8 ;*    License Version 1.0 (the "License"); you may not use this file
9 ;*    except in compliance with the License. You may obtain a copy of
10 ;*    the License at http://www.scitechsoft.com/mgl-license.txt
11 ;*
12 ;*    Software distributed under the License is distributed on an
13 ;*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 ;*    implied. See the License for the specific language governing
15 ;*    rights and limitations under the License.
16 ;*
17 ;*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
18 ;*
19 ;*    The Initial Developer of the Original Code is SciTech Software, Inc.
20 ;*    All Rights Reserved.
21 ;*
22 ;*  ========================================================================
23 ;*
24 ;* Language:    80386 Assembler, TASM 4.0 or NASM
25 ;* Environment: 32-bit Windows NT device driver
26 ;*
27 ;* Description: Low level assembly support for the PM library specific to
28 ;*              Windows NT device drivers.
29 ;*
30 ;****************************************************************************
31
32         IDEAL
33
34 include "scitech.mac"           ; Memory model macros
35
36 header      _irq                ; Set up memory model
37
38 begdataseg  _irq
39
40     cextern _PM_rtcHandler,CPTR
41     cextern _PM_prevRTC,FCPTR
42
43 RtcInside   dw      0           ; Are we still handling current interrupt
44 sidtBuf     df      0           ; Buffer for sidt instruction
45
46 enddataseg  _irq
47
48 begcodeseg  _irq                ; Start of code segment
49
50 cpublic _PM_irqCodeStart
51
52 ; Macro to delay briefly to ensure that enough time has elapsed between
53 ; successive I/O accesses so that the device being accessed can respond
54 ; to both accesses even on a very fast PC.
55
56 ifdef   USE_NASM
57 %macro  DELAY 0
58         jmp     short $+2
59         jmp     short $+2
60         jmp     short $+2
61 %endmacro
62 %macro  IODELAYN 1
63 %rep    %1
64         DELAY
65 %endrep
66 %endmacro
67 else
68 macro   DELAY
69         jmp     short $+2
70         jmp     short $+2
71         jmp     short $+2
72 endm
73 macro   IODELAYN    N
74     rept    N
75         DELAY
76     endm
77 endm
78 endif
79
80 ;----------------------------------------------------------------------------
81 ; PM_rtcISR - Real time clock interrupt subroutine dispatcher
82 ;----------------------------------------------------------------------------
83 ; Hardware interrupt handler for the timer interrupt, to dispatch control
84 ; to high level C based subroutines. We save the state of all registers
85 ; in this routine, and switch to a local stack. Interrupts are *off*
86 ; when we call the user code.
87 ;
88 ; NOTE: This routine switches to a local stack before calling any C code,
89 ;       and hence is _not_ re-entrant. Make sure your C code executes as
90 ;       quickly as possible, since a timer overrun will simply hang the
91 ;       system.
92 ;----------------------------------------------------------------------------
93 cprocfar    _PM_rtcISR
94
95 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
96 ; If we enable interrupts and call into any C based interrupt handling code,
97 ; we need to setup a bunch of important information for the NT kernel. The
98 ; code below takes care of this housekeeping for us (see Undocumented NT for
99 ; details). If we don't do this housekeeping and interrupts are enabled,
100 ; the kernel will become very unstable and crash within 10 seconds or so.
101 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
102
103         pushad
104         pushfd
105         push    fs
106
107         mov     ebx,00000030h
108         mov     fs,bx
109         sub     esp,50h
110         mov     ebp,esp
111
112 ; Setup the exception frame to NULL
113
114         mov     ebx,[DWORD cs:0FFDFF000h]
115         mov     [DWORD ds:0FFDFF000h], 0FFFFFFFFh
116         mov     [DWORD ebp],ebx
117
118 ; Save away the existing KSS ebp
119
120         mov     esi,[DWORD cs:0FFDFF124h]
121         mov     ebx,[DWORD esi+00000128h]
122         mov     [DWORD ebp+4h],ebx
123         mov     [DWORD esi+00000128h],ebp
124
125 ; Save away the kernel time and the thread mode (kernel/user)
126
127         mov     edi,[DWORD esi+00000137h]
128         mov     [DWORD ebp+8h],edi
129
130 ; Set the thread mode (kernel/user) based on the code selector
131
132         mov     ebx,[DWORD ebp+7Ch]
133         and     ebx,01
134         mov     [BYTE esi+00000137h],bl
135
136 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
137 ; End of special interrupt Prolog code
138 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
139
140 ; Clear priority interrupt controller and re-enable interrupts so we
141 ; dont lock things up for long.
142
143         mov     al,20h
144         out     0A0h,al
145         out     020h,al
146
147 ; Clear real-time clock timeout
148
149         in      al,70h              ; Read CMOS index register
150         push    eax                 ;  and save for later
151         IODELAYN 3
152         mov     al,0Ch
153         out     70h,al
154         IODELAYN 5
155         in      al,71h
156
157 ; Call the C interrupt handler function
158
159         cmp     [BYTE RtcInside],1  ; Check for mutual exclusion
160         je      @@Exit
161         mov     [BYTE RtcInside],1
162         sti                         ; Enable interrupts
163         cld                         ; Clear direction flag for C code
164         call    [CPTR _PM_rtcHandler]
165         cli                         ; Disable interrupts on exit!
166         mov     [BYTE RtcInside],0
167
168 @@Exit: pop     eax
169         out     70h,al              ; Restore CMOS index register
170
171 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
172 ; Start of special epilog code to restore stuff on exit from handler
173 ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
174
175 ; Restore the KSS ebp
176
177         mov     esi,[DWORD cs:0FFDFF124h]
178         mov     ebx,[DWORD ebp+4]
179         mov     [DWORD esi+00000128h],ebx
180
181 ; Restore the exception frame
182
183         mov     ebx,[DWORD ebp]
184         mov     [DWORD fs:00000000],ebx
185
186 ; Restore the thread mode
187
188         mov     ebx,[DWORD ebp+8h]
189         mov     esi,[DWORD fs:00000124h]
190         mov     [BYTE esi+00000137h],bl
191         add     esp, 50h
192         pop     fs
193         popfd
194         popad
195
196 ; Return from interrupt
197
198         iret
199
200 cprocend
201
202 cpublic _PM_irqCodeEnd
203
204 ;----------------------------------------------------------------------------
205 ; void _PM_getISR(int irq,PMFARPTR *handler);
206 ;----------------------------------------------------------------------------
207 ; Function to return the specific IRQ handler direct from the IDT.
208 ;----------------------------------------------------------------------------
209 cprocstart  _PM_getISR
210
211         ARG     idtEntry:UINT, handler:DPTR
212
213         enter_c 0
214         mov     ecx,[handler]           ; Get address of handler to fill in
215         sidt    [sidtBuf]               ; Get IDTR register into sidtBuf
216         mov     eax,[DWORD sidtBuf+2]   ; Get address of IDT into EAX
217         mov     ebx,[idtEntry]
218         lea     eax,[eax+ebx*8]         ; Get entry in the IDT
219         movzx   edx,[WORD eax+6]        ; Get high order 16-bits
220         shl     edx,16                  ; Move into top 16-bits of address
221         mov     dx,[WORD eax]           ; Get low order 16-bits
222         mov     [DWORD ecx],edx         ; Store linear address of handler
223         mov     dx,[WORD eax+2]         ; Get selector value
224         mov     [WORD ecx+4],dx         ; Store selector value
225         leave_c
226         ret
227
228 cprocend    _PM_getISR
229
230 ;----------------------------------------------------------------------------
231 ; void _PM_setISR(int irq,void *handler);
232 ;----------------------------------------------------------------------------
233 ; Function to set the specific IRQ handler direct in the IDT.
234 ;----------------------------------------------------------------------------
235 cprocstart  _PM_setISR
236
237         ARG     irq:UINT, handler:CPTR
238
239         enter_c 0
240         mov     ecx,[handler]           ; Get address of new handler
241         mov     dx,cs                   ; Get selector for new handler
242         sidt    [sidtBuf]               ; Get IDTR register into sidtBuf
243         mov     eax,[DWORD sidtBuf+2]   ; Get address of IDT into EAX
244         mov     ebx,[idtEntry]
245         lea     eax,[eax+ebx*8]         ; Get entry in the IDT
246         cli
247         mov     [WORD eax+2],dx         ; Store code segment selector
248         mov     [WORD eax],cx           ; Store low order bits of handler
249         shr     ecx,16
250         mov     [WORD eax+6],cx         ; Store high order bits of handler
251         sti
252         leave_c
253         ret
254
255 cprocend    _PM_setISR
256
257 ;----------------------------------------------------------------------------
258 ; void _PM_restoreISR(int irq,PMFARPTR *handler);
259 ;----------------------------------------------------------------------------
260 ; Function to set the specific IRQ handler direct in the IDT.
261 ;----------------------------------------------------------------------------
262 cprocstart  _PM_restoreISR
263
264         ARG     irq:UINT, handler:CPTR
265
266         enter_c 0
267         mov     ecx,[handler]
268         mov     dx,[WORD ecx+4]         ; Get selector for old handler
269         mov     ecx,[DWORD ecx]         ; Get address of old handler
270         sidt    [sidtBuf]               ; Get IDTR register into sidtBuf
271         mov     eax,[DWORD sidtBuf+2]   ; Get address of IDT into EAX
272         mov     ebx,[idtEntry]
273         lea     eax,[eax+ebx*8]         ; Get entry in the IDT
274         cli
275         mov     [WORD eax+2],dx         ; Store code segment selector
276         mov     [WORD eax],cx           ; Store low order bits of handler
277         shr     ecx,16
278         mov     [WORD eax+6],cx         ; Store high order bits of handler
279         sti
280         leave_c
281         ret
282
283 cprocend    _PM_restoreISR
284
285 endcodeseg  _irq
286
287         END                     ; End of module
288