From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/BIOS/MSSTACK.INC | 306 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 306 insertions(+) create mode 100644 v4.0/src/BIOS/MSSTACK.INC (limited to 'v4.0/src/BIOS/MSSTACK.INC') 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 @@ +; 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 -- cgit v1.2.3