1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
|
; MSStack.inc
;
; Interrupt level 2, 3, 4, 5, 6, 7,(10, 11, 12, 14, 15 - AT level)
; should follow the standard Interrupt Sharing Scheme which has
; a standard header structure.
; Fyi, the following shows the relations between
; the interrupt vector and interrupt level.
; VEC(Hex) 2 8 9 A B C D E 70 72 73 74 76 77
; LVL(Deci) 9 0 1 2 3 4 5 6 8 10 11 12 14 15
; MSSTACK module modifies the following interrupt vectors
; to meet the standard Interrupt Sharing standard;
; A, B, C, D, E, 72, 73, 74, 76, 77.
; Also, for interrupt level 7 and 15, the FirstFlag in a standard header
; should be initialized to indicat whether this interrupt handler is
; the first (= 80h) or not. The FirstFlag entry of INT77h's
; program header is initialized in STKINIT.INC module.
; FirstFlag is only meaningful for interrupt level 7 and 15.
;
; User specifies the number of stack elements - default = 9
; minimum = 8
; maximum = 64
;
; Intercepts Asynchronous Hardware Interrupts only
;
; Picks a stack from pool of stacks and switches to it
;
; Calls the previously saved interrupt vector after pushing flags
;
; On return, returns the stack to the stack pool
;
; This is a modification of STACKS:
; 1. To fix a bug which was causing the program to take up too much space.
; 2. To dispense stack space from hi-mem first rather than low-mem first.
; . Clobbers the stack that got too big instead of innocent stack
; . Allows system to work if the only stack that got too big was the most
; deeply nested one
; 3. Disables NMI interrupts while setting the NMI vector.
; 4. Does not intercept any interupts on a PCjr.
; 5. Double checks that a nested interrupt didn't get the same stack.
; 6. Intercepts Ints 70, 72-77 for PC-ATs and other future products
;The following variables are for MSSTACK.inc
EVEN
dw 0 ; SPARE FIELD BUT LEAVE THESE IN ORDER
StackCount dw 0
StackAt dw 0
StackSize dw 0
Stacks dw 0
dw 0
FirstEntry dw Stacks
LastEntry dw Stacks+(DefaultCount*EntrySize)-EntrySize
NextEntry dw Stacks+(DefaultCount*EntrySize)-EntrySize
;End of variables defined for MSSTACK.
;*******************************************************************
;Macro Interrupt handler for the ordinary interrupt vectors and
;the shared interrupt vectors.
;*****************************
Stack_Main MACRO AA
ASSUME DS:NOTHING
ASSUME ES:NOTHING
ASSUME SS:NOTHING
PUBLIC Int&AA
PUBLIC Old&AA
;-----------------------------
ife IntSharingFlag ;if not IntSharingFlag
;-----------------------------
Old&AA DD 0
Int&AA PROC FAR
;-----------------------------
else ;for shared interrupt. A Header exists.
PUBLIC FirstFlag&AA
Int&AA PROC FAR
jmp short Entry_Int&AA&_Stk
Old&AA dd 0 ;Forward pointer
dw 424Bh ;compatible signature for Int. Sharing
FirstFlag&AA db 0 ;the firstly hooked.
jmp short Intret_&AA ;Reset routine. We don't care this.
db 7 dup (0) ;Reserved for future.
Entry_Int&AA&_Stk:
;-----------------------------
endif
;-----------------------------
;
; Keyboard interrupt must have a three byte jump, a NOP and a zero byte
; as its first instruction for compatibility reasons
ifidn <&aa>,<09>
jmp Keyboard_lbl
nop
db 0
Keyboard_lbl label near
endif
; This patches INTERRUPT 75h to be "unhooked". We do this Wierdness,
; rather than never hooking INT 75h, to maintain maximum compat. with IBMs
; post production patch.
push ax
ifidn <&aa>,<02>
; *********************************************************************
;
; This is special support for the PC Convertible / NMI handler
;
; On the PC Convertible, there is a situation where an NMI can be
; caused by using the "OUT" instructions to certain ports. When this
; occurs, the PC Convertible hardware *GUARANTEES* that **NOTHING**
; can stop the NMI or interfere with getting to the NMI handler. This
; includes other type of interrupts (hardware and software), and
; also includes other type of NMI's. When any NMI has occured,
; no other interrtupt (hardware, software or NMI) can occur until
; the software takes specific steps to allow further interrupting.
;
; For PC Convertible, the situation where the NMI is generated by the
; "OUT" to a control port requires "fixing-up" and re-attempting. In
; otherwords, it is actually a "restartable exception". In this
; case, the software handler must be able to get to the stack in
; order to figure out what instruction caused the problem, where
; it was "OUT"ing to and what value it was "OUT"ing. Therefore,
; we will not switch stacks in this situation. This situation is
; detected by interrogating port 62h, and checking for a bit value
; of 80h. If set, *****DO NOT SWITCH STACKS*****.
;
; *********************************************************************
push es
mov ax,0f000h
mov es,ax
cmp byte ptr es:[0fffeh],mdl_convert ;check if convertible
pop es
jne Normal&aa
in al,62h
test al,80h
jz Normal&aa
Special&aa:
pop ax
jmp dword ptr Old&aa
Normal&aa:
; *********************************************************************
endif
push bp
push es
mov es, cs:[STACKS+2] ; Get segment of stacks
mov bp,NextEntry ; get most likely candidate
mov al,Allocated
xchg AllocByte,al ; grab the entry
cmp al,Free ; still avail?
jne NotFree&aa
sub NextEntry,EntrySize ; set for next interrupt
Found&aa:
mov SavedSP,sp ; save sp value
mov SavedSS,ss ; save ss also
; mov IntLevel,aa&h ; save the int level
mov ax,bp ; temp save of table offset
mov bp,NewSP ; get new SP value
cmp es:[bp],ax ; check for offset into table
jne FoundBad&aa
mov ax,es ; point ss,sp to the new stack
mov ss,ax
mov sp,bp
pushf ; go execute the real interrupt handler
call dword ptr old&aa ; which will iret back to here
mov bp,sp ; retrieve the table offset for us
mov bp,es:[bp] ; but leave it on the stack
mov ss,SavedSS ; get old stack back
mov sp,SavedSP
; cmp AllocByte,Allocated ; If an error occured,
; jne NewError&aa ; do not free us
mov AllocByte,Free ; free the entry
mov NextEntry,bp ; setup to use next time
NewError&aa:
pop es
pop bp ; saved on entry
pop ax ; saved on entry
INTRET_&AA: ;3.30
iret ; done with this interrupt
NotFree&aa:
cmp al,Allocated ; error flag
je findnext&aa ; no, continue
xchg AllocByte,al ; yes, restore error value
FindNext&aa:
call LongPath
jmp Found&aa
FoundBad&aa:
cmp bp,FirstEntry
jc findnext&aa
mov bp,ax ; flag this entry
mov AllocByte,Clobbered
; add bp,EntrySize ; and previous entry
; mov AllocByte,Overflowed
; sub bp,EntrySize
jmp findnext&aa ; keep looking
int&aa endp
endm
;***************************** ;3.30
;End of Macro definition ;3.30
;******************************************************************** ;3.30
; THESE ARE THE INDIVIDUAL INTERRUPT HANDLERS ;3.30
;3.30
IRP A,<02,08,09,70> ;3.30
IntSharingFlag=0 ;3.30
Stack_Main &A ;3.30
ENDM ;3.30
;3.30
IRP A,<0A,0B,0C,0D,0E,72,73,74,76,77> ;3.30
IntSharingFlag=1 ;3.30
Stack_Main &A ;3.30
ENDM ;3.30
;3.30
;******************************************************************** ;3.30
;Common routines ;3.30
longpath:
mov bp,LastEntry ; start with last entry in table
LPLOOPP: ;3.30
cmp AllocByte,Free ; is entry free?
jne inuse ; no, try next one
mov al,Allocated
xchg AllocByte,al ; allocate entry
cmp al,Free ; is it still free?
je found ; yes, go use it
cmp al,Allocated ; is it other than Allocated or Free?
je inuse ; no, check the next one
mov AllocByte,al ; yes, put back the error state
inuse:
cmp bp,FirstEntry
je Fatal
sub bp,EntrySize
JMP LPLOOPP ;3.30
found:
ret
page
fatal proc near
push ds ;3.30
mov ax, 0f000h ;loook at the model byte ;3.30
mov ds, ax ;3.30
cmp ds:byte ptr [0fffeh], mdl_convert ;convertible? ;3.30
pop ds ;3.30
jne Skip_NMIS ;3.30
;3.30
mov al,07h ; disable PC Convertible NMIs
out 72h,al
Skip_NMIS: ;3.30
cli ; disable and mask
mov al,0ffh ; all other ints
out 021h,al
out 0a1h,al
mov si,cs
mov ds,si
mov si,offset fatal_msg
fatal_loop:
lodsb
cmp al,'$'
je fatal_done
mov bl,7 ;3.30*
mov ah,14 ;3.30*
int 010h ; whoops, this enables ints ;3.30*
jmp fatal_loop
fatal_done:
jmp fatal_done
fatal endp
|