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