home *** CD-ROM | disk | FTP | other *** search
- ; PMODE v3.07 DPMI/VCPI/XMS/raw protected mode interface kernel.
- ; Copyright (c) 1994, Tran (a.k.a. Thomas Pytel).
- ;
- ; Changed to compile under TASM for DJGPP by m.grimrath@tu-bs.de
- ; Assemble case sensitive on all symbols!
-
- P386
- IDEAL
- ASSUME cs:_TEXT, ds:DGROUP, es:nothing, ss:nothing
- GROUP DGROUP _DATA, _BSS
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; Configuration options
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ; Set to one to call exception 7 through a trap gate. An improvement of
- ; 10% in execution speed is possible using wmemu387.
- ; However, if one of the pics uses ints 0 to 7 (highly unlikely but supported)
- ; then an IRQ7 or IRQ15 will probably crash the computer.
- ; Also we cannot tell 'int 7' from exception 7.
- FAST_FPU_EMU = 1
-
- ; Set to one to let int 24 (critical error) conform to the DPMI spec.
- ; Since CWSDPMI doesn't support it, there is usually no need to support
- ; it in PMODE/DJ.
- SUPPORT_INT_24 = 0
-
- ; Set to 1 to have PMODE/DJ extensions to the DPMI standard.
- ; So far no extension is available; setting this just wastes memory.
- PMODEDJ_EXT = 0
-
- ; Set this to have DPMI 1.0 functions 0e,0f (Get/Set multiple selectors)
- ; For DJGPP you can leave it 0; Recommended to set only if you just can't
- ; live without it! :-)
- MULTI_DESCRIPTORS = 0
-
- ; Setting this pmode will check if the requested DPL of descriptors match
- ; the CPL of the client. If not set, pmode will ignore the DPL and replace
- ; it with zero.
- ; This is only useful if you want pmodetsr to work around a bug in
- ; clients, namely zip. For DJGPP, always set this to 1
- STRICT_RING_CHECKING = 1
-
- ; Setting this pmode will check each segment limit. In particular, requesting
- ; to set a limit >1Mb while the lower 12 bits are != FFF will fail. If it
- ; not set, the 12 lower bits are ignored.
- ; For DJGPP, you must clear this flag; if not, your program won't run under
- ; a clean system.
- STRICT_LIMITS = 0
-
- ; How much bytes for physical address mapping. Will be rounded up to the next
- ; multiple of 4MB. Be careful! Setting this to high values consumes much
- ; conventional memory!
- ; Note that you might map more memory than specified here, because mapped
- ; memory uses the same pagetables as "normal" memory.
- EXTRALINEAR = 8096*1024
-
- RMSTACKLEN = 0C00h ; real mode stack length, in bytes
- RMONESTACKLEN = 200h
- PMSTACKLEN = 0C00h ; protected mode stack length, in bytes
- PMONESTACKLEN = 200h
- VCPISTACKLEN = 100h ; just for switching
- CALLBACKS = 16 ; number of real mode callbacks
- NUM_EXCEPTIONS = 16 ; # of handled exceptions
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; Makros
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- off EQU offset
- pdseg EQU fs ; take advantage of the 2 additional
- coreseg EQU gs ; segment registers!
-
- ; Macros to build up standard selectors
- MACRO init_sel ; Initialize selector
- sel_aktcnt = 0
- ENDM
- MACRO mk_sel selec ; Add one selectors
- selec = sel_aktcnt*8
- sel_aktcnt = sel_aktcnt+1
- ENDM
- MACRO mk_msel selec,num ; Make multiple selectors
- selec = sel_aktcnt*8
- sel_aktcnt = sel_aktcnt+num
- ENDM
- MACRO get_num_sel lab ; returns the current number of selectors
- lab = sel_aktcnt
- ENDM
-
- ; a 32 addressing nop (for a 386 bug)
- MACRO dnop
- DB 67h
- nop
- ENDM
-
- ; Makes a linear address from seg:ofs
- MACRO ptr2lin seg,ofs,r1,r2,er1,er2
- mov r1,seg
- movzx er1,r1
- shl er1,4
- mov r2,ofs
- movzx er2,r2
- add er1,er2
- ENDM
-
- ; Make a segment from a linear address
- MACRO lin2seg segm,lin,ereg,reg
- IFDIF <lin>,<ereg>
- mov ereg,lin
- ENDIF
- shr ereg,4
- mov segm,reg
- ENDM
-
- ; Sets a memory area to zero
- MACRO setmemw seg,ofs,size
- IFDIF <seg>,<es>
- push seg
- pop es
- ENDIF
- IFDIF <ofs>,<di>
- mov di,ofs
- ENDIF
- mov cx,(size) / 2
- sub ax,ax
- cld
- rep stosw
- nop ; 386 bug
- ENDM
-
- ; Copies memory areas with ESI and EDI
- MACRO dmemcpyw sseg,sofs,dseg,dofs,size
- IFDIF <sofs>,<esi>
- mov esi,sofs ; Put this HERE, or else you can't use esp
- ENDIF
- IFDIF <dofs>,<edi>
- mov edi,dofs ; as macro argument
- ENDIF
- IFDIF <size>,<ecx>
- mov ecx,(size) / 2
- ENDIF
- push ds es
- IFDIF <dseg>,<es>
- push dseg
- ENDIF
- IFDIF <sseg>,<ds>
- push sseg
- pop ds
- ENDIF
- IFDIF <dseg>,<es>
- pop es
- ENDIF
- cld
- DB 67h ; To use ECX, ESI and EDI
- rep movsw
- dnop ; 386 bug
- pop es ds
- ENDM
-
- ; Copies memory areas with SI and DI
- MACRO memcpyw sseg,sofs,dseg,dofs,size
- IFDIF <sofs>,<si>
- mov si,sofs ; Put this HERE, or else you can't use esp
- ENDIF
- IFDIF <dofs>,<di>
- mov di,dofs ; as macro argument
- ENDIF
- IFDIF <size>,<cx>
- mov cx,(size) / 2
- ENDIF
- push ds es
- IFDIF <dseg>,<es>
- push dseg
- ENDIF
- IFDIF <sseg>,<ds>
- push sseg
- pop ds
- ENDIF
- IFDIF <dseg>,<es>
- pop es
- ENDIF
- cld
- rep movs [WORD PTR es:di],[WORD PTR ds:si]
- pop es ds ; these pops cover 386 bug
- ENDM
-
- ; to save one line of source code
- MACRO copy dst,src,reg
- mov reg,src
- mov dst,reg
- ENDM
-
- ; not to write so many lines
- MACRO init_dsc base,sel,limit,rights
- IFDIF <base>,<ax>
- mov ax,base
- ENDIF
- IFDIF <sel>,<bx>
- mov bx,sel
- ENDIF
- IFDIF <limit>,<ecx>
- mov ecx,limit
- ENDIF
- IFDIF <rights>,<dx>
- mov dx,rights
- ENDIF
- call vxr_initsetdsc
- ENDM
-
- ; zero extends 16 bit offset to 32, so it can be linked without 32 records
- MACRO do16to32 mnem,p1,p2
- DB 66h ; 32 bit operand mode
- mnem p1,p2
- DW 0
- ENDM
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; Constants and structures
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ; As you might notice, all structures start with a capital letter
- ; When changing the source, please keep this style!
-
- init_sel ; Global descriptortable
- mk_sel SELNULL ; NULL selector
- mk_sel SELCORE ; selector of entire memory space
- mk_sel SELCS ; Selector for Codesegment
- mk_sel SELDS ; Selector for Datasegment
- mk_sel SELREAL ; real mode attributes selector
- mk_sel SELALIASCS ; to write to CS
- mk_sel SELPRIVAT ; to access privat data
- IF SUPPORT_INT_24 NE 0
- mk_sel SELINT24 ; for INT 24h callback
- ENDIF
- mk_sel SELVCPITSS ; TSS selector for VCPI
- mk_sel SELVCPI ; VCPI call code selector
- mk_sel SELVCPI1
- mk_sel SELVCPI2 ; reserved for VCPI host
- mk_msel SELTASKS,NUM_EXCEPTIONS
- get_num_sel SYSSELECTORS ; number of system-selectors
- GDT_NUM_ENTRIES = 128 ; # of entries in the gdt
-
- ; A 32bit Task status structure
- STRUC Tss
- backlink DW ?,?
- esp0 DD ?
- ss0 DW ?,?
- esp1 DD ?
- ss1 DW ?,?
- esp2 DD ?
- ss2 DW ?,?
- cr3 DD ?
- eip DD ?
- eflags DD ?
- eax DD ?
- ecx DD ?
- edx DD ?
- ebx DD ?
- esp DD ?
- ebp DD ?
- esi DD ?
- edi DD ?
- es DW ?,?
- cs DW ?,?
- ss DW ?,?
- ds DW ?,?
- fs DW ?,?
- gs DW ?,?
- ldt DW ?,?
- trap DW ?
- iomapbase DW ?
- ENDS
-
- ; DPMI register structure
- STRUC Dpmi_regs
- LABEL edi DWORD
- di DW ?
- di_hi DW ?
- LABEL esi DWORD
- si DW ?
- si_hi DW ?
- LABEL ebp DWORD
- bp DW ?
- bp_hi DW ?
- res DD ?
- LABEL ebx DWORD
- LABEL bx WORD
- bl DB ?
- bh DB ?
- bx_hi DW ?
- LABEL edx DWORD
- LABEL dx WORD
- dl DB ?
- dh DB ?
- dx_hi DW ?
- LABEL ecx DWORD
- LABEL cx WORD
- cl DB ?
- ch DB ?
- cx_hi DW ?
- LABEL eax DWORD
- LABEL ax WORD
- al DB ?
- ah DB ?
- ax_hi DW ?
- flags DW ?
- es DW ?
- ds DW ?
- fs DW ?
- gs DW ?
- ip DW ?
- cs DW ?
- sp DW ?
- ss DW ?
- ENDS
-
- ; to access a descriptor entry more easily
- STRUC Descriptor
- limit0_15 DW ?
- base0_15 DW ?
- base16_23 DB ?
- LABEL types WORD
- types0 DB ?
- types1 DB ?
- base24_31 DB ?
- ENDS
-
- ; Almost the same as a descriptor, but its a gate
- STRUC Gate
- offset0 DW ?
- sel DW ?
- reserved DB ?
- gtype DB ?
- offset1 DW ?
- ENDS
-
- ; for DPMI call memory information
- STRUC Dpmi_meminfo
- available_memory DD ?
- available_pages DD ?
- available_lockable_pages DD ?
- linear_space DD ?
- unlocked_pages DD ?
- available_physical_pages DD ?
- total_physical_pages DD ?
- free_linear_space DD ?
- max_pages_in_paging_file DD ?
- reserved DD 3 DUP(?)
- ENDS
-
- ; also for easy access
- STRUC Farptr16 ; A 16 bit far ptr
- LABEL ptr DWORD
- offset DW ?
- sel DW ?
- ENDS
-
- STRUC Farptr32 ; A 32 Bit far ptr
- LABEL ptr FWORD
- offset DD ?
- sel DW ?
- pad DW ? ; one for align
- ENDS
-
- STRUC Temp ; for temporary variables
- LABEL d0 DWORD
- LABEL w0 WORD
- b0 DB ?
- b1 DB ?
- LABEL w1 WORD
- b2 DB ?
- b3 DB ?
- ENDS
-
- STRUC Callback
- DB 0Fh,0A8h ; PUSH gs
- DB 0Fh,0A0h ; PUSH fs
- DB 1Eh ; PUSH ds
- DB 06h ; PUSH es
- DB 9Ch ; PUSHF
- DB 66h,60h ; PUSHAD instruction
- DB 68h ; PUSH WORD instruction
- ds DW 0 ; immediate 0 used as free flag
- DB 66h,68h ; PUSH DWORD instruction
- esi DD 0 ; immediate data
- DB 0B9h ; MOV CX,? instruction
- es DW 0 ; immediate data
- DB 66h,68h ; PUSH DWORD instruction
- edi DD 0 ; immediate data
- DB 0EAh ; JMP FAR PTR ?:? intruction
- ptr Farptr16 ? ; immediate data
- ENDS
-
- ; The data structure for privat data
- STRUC Pdata
- rmstack DB RMSTACKLEN DUP(?)
- pmstack DB PMSTACKLEN DUP(?)
- vcpistack DB VCPISTACKLEN DUP(?)
- vcpitss Tss ?
- exceptiontasks Tss NUM_EXCEPTIONS DUP(?)
- exceptions Farptr32 32 DUP(?)
- rmint_ptrs DD 256 DUP(?)
- rmint_copy Farptr16 16 DUP(?) ; transparent hooking of HW RM Ints
- rmint_old Farptr16 16 DUP(?)
- lowint Farptr32 NUM_EXCEPTIONS DUP(?)
- DB 256 DUP(?)
- LABEL exceptionstack WORD
- idt Gate 256 DUP(?)
- gdt Descriptor GDT_NUM_ENTRIES DUP(?)
- LABEL after WORD
- ENDS
- ; if running under VCPI, this is (page aligned) followed by the
- ; pagedirectory and the pagetables.
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DATA
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- SEGMENT _DATA PARA PUBLIC USE16 'DATA'
-
- PUBLIC pm_exit ; user procedure at exit
- ; [fold] [
-
- lvcpistruc DD ? ; VCPI switch structure linear address
- LABEL vcpi_switch_struct WORD
- vcpi_cr3 DD ? ; VCPI CR3 value for protected mode
- vcpi_gdtaddx DD ? ; linear addx of GDT limit and base
- vcpi_idtaddx DD ? ; linear addx of IDT limit and base
- vcpi_selldt DW 0 ; LDT selector for protected mode
- vcpi_seltss DW SELVCPITSS ; TSS selector for protected mode
- vcpi_eip DW off v_rmtopmswpm; destination EIP in protected mode
- DW 0
- vcpi_cs DW SELCS ; destination CS in protected mode
-
- emspage DW -1 ; For some VCPI Managers
-
- picbasetab DB 88h,90h,98h,0A0h,0A8h,0B0h,0B8h,68h,78h,-1
-
- initrouttbl DW r_init,x_init,v_init,d_init
- exitrouttbl DW r_exit,x_exit,v_exit ; exit functions. DPMI not needed
- pm_exit DW ret_only ; Just a ret
-
- int31functbl DW 0000h, 0001h, 0002h, 0003h, 0006h
- DW 0007h, 0008h, 0009h, 000ah, 000bh
- DW 000ch
- IF MULTI_DESCRIPTORS NE 0
- DW 000eh, 000fh
- ENDIF
- DW 0100h, 0101h, 0102h
- DW 0200h, 0201h, 0202h, 0203h
- DW 0204h, 0205h
- DW 0300h, 0301h, 0302h, 303h, 304h
- DW 0305h, 0306h
- DW 0400h
- DW 0500h, 0501h, 0502h, 0503h
- DW 0600h, 0601h, 0602h, 0603h, 0604h
- DW 0702h, 0703h
- DW 0800h, 0801h
- DW 0900h, 0901h, 0902h
- IF PMODEDJ_EXT EQ 1
- DW 0A00h
- ENDIF
- DW 0E00h, 0E01h
- INT31FUNCNUM = ($ - int31functbl) / 2
-
- int31routtbl DW int310000, int310001, int310002, int310003, int310006
- DW int310007, int310008, int310009, int31000a, int31000b
- DW int31000c
- IF MULTI_DESCRIPTORS NE 0
- DW int31000e, int31000f
- ENDIF
- DW int310100, int310101, int310102
- DW int310200, int310201, int310202, int310203
- DW int310204, int310205
- DW int310300, int310301, int310302, int310303, int310304
- DW int310305, int310306
- DW int310400
- DW int310500, int310501, int310502, int310503
- DW int310600, int310601, int310602, int310603, int310604
- DW int310702, int310703
- int31phystbl DW int310800v,int310801v
- DW int310900, int310901, int310902
- IF PMODEDJ_EXT EQ 1
- DW int310a00
- ENDIF
- DW int310e00, int310e01
-
- ; the letters stand for:
- ; v - VCPI memory
- ; x - XMS memory
- ; r - raw memory (INT15/VDISK)
- ; n - no memory
- int31mvrouttbl DW int310500v, int310501v, int310502v, int310503v
- int31mxrouttbl DW int310500x, int310501x, int310502x, int310503x
- int31mrrouttbl DW int310500r, int310501r, int310502r, int310503r
- int31mnrouttbl DW int310500n, int310501n, int310502n, int310503n
- INT31MROUTTBL_ENTRIES = ($ - int31mnrouttbl) / 2
-
- int31physxrtbl DW int310800xr, int310801xr
-
- IF PMODEDJ_EXT EQ 1
- apitab:
- APITAB_SIZE = $ - apitab
- pmodedj_id DB 'DJGPP',0
- PMODEDJ_ID_SIZE = $ - pmodedj_id
- ENDIF
- ALIGN 4
-
- ; Placed here, coz my TASM had problems putting this in the code
- common_callbacks Callback CALLBACKS DUP(<>)
-
- rawextmemused DW 1 ; raw extended memory used in K
- rawextmembase DD 0ffffffffh ; raw extended memory base
- rawextmemtop DD 0 ; raw extended memory top
-
- rmidtlimit DW 3ffh ; real mode IDT limit
- rmidtbase DD 0 ; real mode IDT base
-
- ; THIS MUST BE THE LAST VAR! padsec will kill any trailing zeros from the
- ; exefile, which means variables initialized here 0 have undefined values
- ; in them.
- ; padsec must do this job because tasm or tlink doesn't get it right. :(
- DW 0abcdh
- ENDS
-
- SEGMENT _BSS PARA PUBLIC USE16 'BSS'
- int31mrouttbl DW INT31MROUTTBL_ENTRIES DUP(?)
-
- segmentbases DW 16*2 DUP(?) ; segment bases for function 0002h
- segmentbases_SIZE = ($ - segmentbases)
-
- temp0 Temp ? ; temporary variables
- temp1 Temp ? ; " "
-
- rmwrapper Farptr16 8 DUP(?) ; real mode wrappers to reprogram PIC
- xms_call Farptr16 ?
-
- dpmiepmode Farptr16 ? ; DPMI protected mode entry
-
- vcpiswitchstack Farptr32 ? ; VCPI temporary mode switch stack
- vcpi_service Farptr32 ? ; VCPI code pointer
-
- gdtlimit DW ? ; GDT limit
- gdtbase DD ? ; GDT base
- idtlimit DW ? ; IDT limit
- idtbase DD ? ; IDT base
-
- SetMasterPIC DW ? ; offset of PIC set routine
- ResetMasterPIC DW ? ; offset of PIC reset routine
- SetA20 DW ? ; offset of A20 set routine
- ResetA20 DW ? ; offset of A20 reset routine
-
- pmstackbase DD ? ; bottom of protected mode stack area
- pmstacktop DD ? ; top of protected mode stack area
- rmstackbase DW ? ; bottom of real mode stack area
- rmstacktop DW ? ; top of real mode stack area
-
- processortype DB ? ; processor type
- pmodetype DB ? ; protected mode type
- reprogrampic DB ? ; if first PIC should be reprogrammed
- from_us DB ? ; if int call by PMODE
- picslaveold DB ? ; old PIC slave base interrupt
- picmasterold DB ? ; old PIC master base interrupt
- picslavenew DB ? ; New PIC slave base
- picmasternew DB ? ; New PIC master base
-
- olda20 DB ?
- detectionflags DB ?
- oldCR0L DB ? ; low byte of CR0
- newEM_MP DB ? ; user specified EM and MP
- oldint15vector DD ?
- oldint2fvector DD ?
-
- pagedir DD ? ; linear address of pagedirectory
- pagetablebase DD ? ; base of page table area
- pagetabletop DD ? ; top of page table area
- pagetablefree DD ? ; base of available page table area
- pagetabledelta DD ? ; # of KB for allocates pagetables
-
- privatedataseg DW ? ; segment of privat data
-
- rmtopmswrout DW ? ; offset of real to protected routine
- pmtormswrout DW ? ; offset of protected to real routine
- rmstackparmtop DW ? ; for functions 0300h, 0301h, 0302h
- DB 128 DUP(?) ; little stack at exit
- LABEL endstack WORD
- ENDS
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DETECT/INIT CODE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- SEGMENT _TEXT PARA PUBLIC USE16 'CODE'
-
- PUBLIC pm_info ; procedure to get info
- PUBLIC pm_init ; switches to protected mode
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; [fold] [
- ; pm_info: Get protected mode info
- ; In:
- ; AX =
- ; Bit 0 = 0: Check for DPMI first, else check for VCPI first
- ; Bit 1 : ignored and reserved for pm_init
- ;
- ; Bit 8 = 1: forbid raw
- ; Bit 9 = 1: forbid XMS
- ; Bit 10 = 1: forbid VCPI
- ; Bit 11 = 1: forbid DPMI
- ;
- ; Out:
- ; AX = return code:
- ; 0000h = successful
- ; 0001h = no 80386+ detected
- ; 0002h = system already in protected mode and no VCPI or DPMI found
- ; 0003h = no way to switch into protected mode
- ; CF = set on error, if no error:
- ; BX = number of paragraphs needed for protected mode data (may be 0)
- ; CL = processor type:
- ; 02h = 80286
- ; 03h = 80386
- ; 04h = 80486
- ; 05h = 80586
- ; 06h-FFh = reserved for future use
- ; CH = protected mode type:
- ; 00h = raw
- ; 01h = XMS
- ; 02h = VCPI
- ; 03h = DPMI
- ;
- ; Remark by MG: spaghetticode!
- ;
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- pm_info:
- push dx si di bp ds es bx cx ; preserve registers
-
- mov [detectionflags],ah ; store detection flags
- test al,1 ; check order of DPMI/VCPI detection
- jz short @@infof0
-
- call @@detect_VCPI ; check for VCPI first
- call @@detect_DPMI ; check for DPMI second
- jmp short @@infof2 ; neither found, go on to XMS check
-
- @@infof0:
- call @@detect_DPMI ; check for DPMI first
- call @@detect_VCPI ; check for VCPI second
-
- ;-----------------------------------------------------------------------------
- @@infof2:
- smsw ax ; AX = machine status word
- test al,1 ; is system in protected mode?
- mov ax,2 ; error code in case protected mode
- jnz short @@infofail ; if in protected mode, fail
-
- mov ch,1 ; pmode type XMS
- test [detectionflags],2 ; XMS allowed?
- jnz short @@chkr
- mov ax,4300h ; check for XMS
- int 2fh
- cmp al,80h ; XMS present?
- jz short @@w1 ; if so, go on
-
- @@chkr: sub ch,ch ; set type to raw
- test [detectionflags],1 ; raw allowed?
- jz short @@w1 ; if so
-
- mov ax,3 ; else set error code
- jmp short @@infofail ; and fail
-
- @@w1: sub bx,bx ; no special memory needed
-
- ;-----------------------------------------------------------------------------
- @@infof1:
- add bx,(SIZE Pdata+15) / 16 ; Size of privatdata structure
- jmp short @@infook ; go to done ok
-
- ;-----------------------------------------------------------------------------
- @@infofail:
- pop cx bx ; restore BX and CX
- stc ; carry set, failed
- jmp short @@infodone
-
- ;-----------------------------------------------------------------------------
- @@infook:
- mov [pmodetype],ch ; store pmode type
-
- add sp,4 ; skip BX and CX on stack
- xor ax,ax ; success code, also clear carry flag
- clc ; Signal success
-
- ;-----------------------------------------------------------------------------
- @@infodone:
- pop es ds bp di si dx ; restore other registers
- ret ; return
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- @@detect_DPMI: ; detect a DPMI host
- pop bp ; pop return address from stack
-
- test [detectionflags],8 ; DPMI allowed?
- jnz short @@detect_DPMIdone ; if not, quit
-
- sub ax,ax
- mov es,ax
- mov ax,[es:02Fh*4]
- or ax,[es:02Fh*4+2] ; check if multiplex set
- jz short @@detect_DPMIdone
-
- mov ax,1687h ; check for DPMI
- int 2fh
-
- or ax,ax ; DPMI present?
- jnz short @@detect_DPMIdone ; if no, exit routine
-
- mov ax,3 ; error code in case DPMI not 32bit
- test bl,1 ; is DPMI 32bit?
- jz short @@detect_DPMIdone ; if not, this DPMI host is no good
-
- mov ax,1 ; error code in case no processor 386+
- cmp cl,3 ; is processor 386+? (redundant)
- jb short @@infofail ; if no, fail
-
- mov [dpmiepmode.offset],di ; store DPMI initial mode switch addx
- mov [dpmiepmode.sel],es
-
- mov bx,si ; BX = number of paragraphs needed
- mov ch,3 ; pmode type is 3 (DPMI)
-
- jmp @@infook ; go to done ok
-
- @@detect_DPMIdone:
- jmp bp ; return to calling routine
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- @@detect_VCPI: ; detect a VCPI server
- pop bp ; pop return address from stack
-
- call @@detect_processor ; get processor type
-
- mov ax,1 ; error code in case no processor 386+
- cmp cl,3 ; is processor 386+?
- jb short @@infofail ; if no, no VCPI
- mov [processortype],cl ; store processor type
-
- test [detectionflags],4 ; VCPI allowed?
- jnz @@detect_VCPIdone ; if not, ignore
-
- xor ax,ax ; get INT 67h vector
- mov es,ax
- mov ax,[es:67h*4]
- or ax,[es:67h*4+2] ; is vector NULL
- jz short @@detect_VCPIdone ; if yes, no VCPI
-
- cmp [emspage],-1 ; if already EMS Page allocated,
- jnz short @@no_alloc ; skip
- mov ah,40H ;Get Status
- int 67h
- cmp ah,0
- jne short @@no_alloc ;maybe only EMS turned off
- mov ah,42H ;Get Unallocate Page Count
- int 67h
- cmp ah,0
- jne short @@no_alloc
- cmp bx,dx ;Other Program EMS Page Used?
- jne short @@no_alloc ;Used!!
- mov bx,1
- mov ah,43H ;Allocate Pages(1 Page Only),
- int 67h ;so EMS has to be turned on
- cmp ah,0
- jne short @@no_alloc ;if page alloc failed
- mov [emspage],dx ; store EMS page
-
- @@no_alloc:
- mov ax,0de00h ; call VCPI installation check
- int 67h
- or ah,ah ; AH returned as 0?
- jnz short @@detect_VCPIdone2 ; if no, no VCPI
-
- ; determine here # of max pagetables + pagedir
- mov ax,0DE03h ; # of free pages
- int 67h
- add edx,1023+1024+(((EXTRALINEAR+4096*1024-1) AND NOT (4096*1024-1)) \
- /(1024*4)) ; align to next pagetable +
- and dx,NOT 1023 ; first MB + 8 MB extra linear
- shl edx,2 ; # of bytes for page tables
- mov [pagetabledelta],edx ; store size of pagetables
- shr edx,12-8 ; calc # of paragraphs
- mov bx,dx ; if highword is not zero, you would
- ; still have enough mem!
- add bx,(4096+4096) / 16 ; page directory and page align
- mov ch,2 ; pmode type is 2 (VCPI)
-
- jmp @@infof1 ; go to figure other memory needed
-
- @@detect_VCPIdone2:
- mov dx,[emspage]
- cmp dx,-1
- jz short @@detect_VCPIdone ; free allocated EMS page
- mov ah,45h
- int 67h
- mov [emspage],-1 ; reset to 'no emspage allocated'
- @@detect_VCPIdone:
- jmp bp ; return to calling routine
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- @@detect_processor: ; get processor: 286, 386, 486, or 586
- xor cl,cl ; processor type 0 in case of exit
-
- pushf ; transfer FLAGS to BX
- pop bx
-
- mov ax,bx ; try to clear high 4 bits of FLAGS
- and ah,0fh
-
- push ax ; transfer AX to FLAGS
- popf
- pushf ; transfer FLAGS back to AX
- pop ax
-
- and ah,0f0h ; isolate high 4 bits
- cmp ah,0f0h
- je short @@detect_processordone ; if bits are set, CPU is 8086/8
-
- mov cl,2 ; processor type 2 in case of exit
-
- or bh,0f0h ; try to set high 4 bits of FLAGS
-
- push bx ; transfer BX to FLAGS
- popf
- pushf ; transfer FLAGS to AX
- pop ax
-
- and ah,0f0h ; isolate high 4 bits
- jz short @@detect_processordone ; if bits are not set, CPU is 80286
-
- inc cx ; processor type 3 in case of exit
-
- push eax ebx edx ; preserve 32bit registers
-
- pushfd ; transfer EFLAGS to EBX
- pop ebx
-
- mov eax,ebx ; try to flip AC bit in EFLAGS
- xor eax,40000h
-
- push eax ; transfer EAX to EFLAGS
- popfd
- pushfd ; transfer EFLAGS back to EAX
- pop eax
-
- xor eax,ebx ; AC bit fliped?
- jz short @@detect_try_cpuid ; if no, CPU is 386
-
- inc cx ; processor type 4 in case of exit
- @@detect_try_cpuid:
-
- mov eax,ebx ; try to flip ID bit in EFLAGS
- xor eax,200000h
-
- push eax ; transfer EAX to EFLAGS
- popfd
- pushfd ; transfer EFLAGS back to EAX
- pop eax
-
- xor eax,ebx ; ID bit fliped?
- jz short @@detect_processordone2; if no, return 386 or 486
-
- ; Use cpuid instruction if supported
- ; cpuid is supported on some new 486, some new Nx586, Pentium, Am5x86,
- ; Cyrix 6x86 and all newer processors. I'm not sure about Cyrix 5x86.
- ; Nx586 returns 5, Am5x86 returns 4, Cyrix 6x86 returns 6.
- mov eax,0 ; check if CPUID accepts 1 in eax
- db 0fh,0a2h ; CPUID
- or eax,eax ; eax for distant future compatibility
- mov cx,5 ; processor type 5 in case of exit
- jz short @@detect_processordone2; cpuid can not be used further
-
- mov eax,1 ; get chip type and supported features
- db 0fh,0a2h ; CPUID
- and ah,0fh ; clear type field
- movzx cx,ah ; return family field.
-
- @@detect_processordone2:
- pop edx ebx eax ; restore 32bit registers
-
- @@detect_processordone:
- ret ; return
- ; [fold] ]
-
- ; [fold] ]
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; [fold] [
- ; pm_init: switch into protected mode
- ; In:
- ; AX = Bit 0 = 1 Check for VCPI first
- ; Bit 1 = 1 Reprogram first PIC if possible
- ; Bit 8 = 1 forbid raw
- ; Bit 9 = 1 forbid XMS
- ; Bit 10 = 1 forbid VCPI
- ; Bit 11 = 1 forbid DPMI
- ; ES = real mode segment for protected mode data (ignored if not needed)
- ; Out:
- ; AX = return code:
- ; 0000h = successful
- ; 0001h = no 80386+ detected
- ; 0002h = system already in protected mode and no VCPI or DPMI found
- ; 0003h = (changed) no way to switch into protected mode
- ; 0004h = could not enable A20 gate
- ; 0005h = DPMI - could not enter 32bit protected mode
- ; CF = set on error, if no error running in protected mode:
- ; ESP = high word clear
- ; CS = 16bit selector for real mode CS with limit of 64k
- ; SS = selector for real mode SS with limit of 64k
- ; DS = selector for real mode DS with limit of 64k
- ; ES = selector for PSP with limit of 100h
- ; FS = 0 (NULL selector)
- ; GS = 0 (NULL selector)
- ; Rem: DS == SS, if DS == SS on entry
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; [fold] [
- pm_init:
- push ax
- call pm_info
- pop ax
- jnc short @@initf0 ; error?
- ret ; yup, abort
-
- @@initf0: ; no error, init protected mode
- test ax,2
- setnz [reprogrampic]
-
- push esi edi ebp
- cld
-
- setmemw es,<off 0+Pdata.gdt>,<GDT_NUM_ENTRIES * SIZE Descriptor>
- ; clear GDT with all 0
- mov [privatedataseg],es ; save data segment
- movzx bx,[pmodetype] ; jump to appropriate init code
- add bx,bx
- jmp [bx + initrouttbl]
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- d_init: ; DPMI protected mode init
- mov ax,1 ; enter DPMI protected mode
- call [dpmiepmode.ptr]
- sub bx,bx
- jnc short init_done ; error? if not, finished here
- mov bx,5 ; error entering protected mode, set
-
- ;-----------------------------------------------------------------------------
- init_done: ; return with return code
- mov ax,bx
- pop ebp edi esi
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; This assumes, that the extender runs in 1 Code and 1 Datasegment.
- ; (This applies for model tiny, small, compact, and sometimes for tpascal)
- ; The original source put here created a codesegment descriptor
- ; to return from this procedure. But as pm_init is near-called, there is no
- ; need for such a code.
- ; [fold] [
- dvxr_init: ; DPMI/VCPI/XMS/raw common init tail
- sub bx,bx ; error code = 0 (no error)
- mov fs,bx ; changed, when switching by raw
- mov gs,bx
- clc ; signal success
- jmp init_done
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; In: ES = segment for host private data buffer
- ; [fold] [
- v_init: ; VCPI protected mode init
- mov [SetMasterPIC],off v_setpic
- mov [ResetMasterPIC],off v_resetpic
- mov [SetA20],off v_seta20
- mov [ResetA20],off v_reseta20
-
- mov ax,0de0ah ; get PIC mappings
- int 67h
- mov [picmasterold],bl
- mov [picslaveold],cl
-
- mov ax,0de07h ; get CR0
- int 67h
- mov [oldCR0L],bl ; save old state
- sar bl,1
- and bl,3 ; keep EM and MP
- mov [newEM_MP],bl
-
- ptr2lin es,<off 0+Pdata.after>,ax,bx,eax,ebx
- add eax,4095
- and ax,NOT 4095 ; align data area on page
- mov [pagedir],eax ; store
-
- add eax,1000h ; skip pagedir
- mov [pagetablebase],eax ; set base of page table area
- add eax,[pagetabledelta] ; size of pagetables
- mov [pagetabletop],eax ; set top of page table area
-
- lin2seg es,[pagedir],eax,ax
- mov gs,ax ; GS = segment of page directory
- mov es,ax ; ES = segment of page directory
- add ax,100h
- mov fs,ax ; FS = segment of first page table
-
- setmemw es,0,2*4096 ; clear page dir and first page table
- copy es,fs,ax ; ES = segment of first pagetable
-
- push ds
- mov ds,[privatedataseg]
- mov si,off SELVCPI+Pdata.gdt ; descriptors for VCPI host
- xor di,di ; get VCPI protected mode interface
- mov ax,0de01h
- int 67h
- pop ds ; restore old ds
-
- movzx eax,di ; set base of usable page table area
- add ax,4095
- and ax,NOT 4095 ; align to next pagetable
- add eax,[pagetablebase]
- mov [pagetablefree],eax
-
- mov [vcpi_service.sel],SELVCPI ; store protected mode VCPI call CS
- mov [vcpi_service.offset],ebx ; store protected mode VCPI call EIP
-
- ; For safety clear reserved bits 9-11
- @@v_initl0:
- and [byte ptr es:di+1],0f1h
- sub di,4
- jnc @@v_initl0
-
- ; --------- Link pagetables in pagedirectory ----------
- mov si,es ; DX = current page table segment
- xor ebx,ebx ; index in page dir, also loop counter
- mov ebp,[pagetabledelta]
- shr ebp,12 ; # of pagetables
- jmp short @@v_initl1f0
-
- @@v_initl1:
- xor di,di ; clear page table
- mov cx,800h
- xor ax,ax
- rep stosw
- nop ; 386 bug
-
- @@v_initl1f0:
- mov cx,si
- shr cx,8 ; get page number
- mov ax,0de06h ; get physical address
- int 67h
- and dh,0f1h ; For safety clear reserved bits 9-11
- or dl,7 ; set present, User and R/W bit
- mov [gs:ebx*4],edx ; store in page directory
-
- add si,100h ; increment page table segment
- mov es,si
-
- inc bx ; increment index in page directory
- cmp bx,bp ; at end of page tables?
- jb @@v_initl1 ; if no, loop
-
- ;-----------------------------------------------------------------------------
-
- mov ecx,[pagedir]
- shr ecx,12
- mov ax,0de06h
- int 67h ; get physical address
- mov [vcpi_cr3],edx
- ptr2lin ds,<off gdtlimit>,ax,bx,eax,ebx
- mov [vcpi_gdtaddx],eax
- ptr2lin ds,<off idtlimit>,ax,bx,eax,ebx
- mov [vcpi_idtaddx],eax
- ptr2lin ds,<off vcpi_switch_struct>,ax,bx,eax,ebx
- mov [lvcpistruc],eax
- mov [rmtopmswrout],off v_rmtopmsw
- mov [pmtormswrout],off v_pmtormsw
-
- mov si,off int31mvrouttbl
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- vxr_init: ; VCPI/XMS/raw common init tail
- mov [from_us],0 ; init
- mov pdseg,[privatedataseg] ; access private data
-
- push ds ; ES = DS for table copy
- pop es
- mov di,off int31mrouttbl
- mov cx,INT31MROUTTBL_ENTRIES ; set memory allocation function
- memcpyw ds,si,es,di,cx ; copy memory allocation function
-
- setmemw ds,<off segmentbases>,segmentbases_SIZE
-
- sub edx,edx
- mov dx,off critical_error ; Standard exception handler
- mov si,off 0 + Pdata.exceptions
- mov ax,32 ;NUM_EXCEPTIONS
- @@lp: mov [pdseg:si + Farptr32.sel],SELCS
- mov [pdseg:si + Farptr32.offset],edx
- mov [pdseg:si + Farptr32.pad],0
- add si,SIZE Farptr32
- dec ax
- jnz @@lp
- do16to32 mov,ax,<off NMI_exception> ; NMI is passed down to real mode
- mov [pdseg:off (2*SIZE Farptr32) + Pdata.exceptions],eax
-
- IF FAST_FPU_EMU EQ 1
- mov ax,[pdseg:7*SIZE Farptr32 + Pdata.exceptions.sel]
- mov [cs:FPU_emu_vector.sel],ax
- mov eax,[pdseg:7*SIZE Farptr32 + Pdata.exceptions.offset]
- mov [cs:FPU_emu_vector.offset],eax
- ENDIF
-
- copy [picslavenew],[picslaveold],al
- copy [picmasternew],[picmasterold],al
- test [reprogrampic],-1 ; reprogram first PIC?
- jz short @@pice
- cmp [picmasternew],8 ; default value for first PIC?
- jnz short @@pice ; if not, keep hands off!
- @@gopic:mov di,off picbasetab
- copy es,0,ax ; ES -> Base of IVT
- jmp short @@lpde
- @@lpd: mov eax,[es:edx*4] ; get first interrupt vector
- mov cl,7
- @@lpc: inc dx
- cmp eax,[es:edx*4] ; contest the same?
- jnz short @@lpde ; if not, try next
- dec cl ; Rem: This is faster than 'loop'!
- jnz @@lpc ; Compare next
- sub dx,7 ; yeah, found a place
- jmp short @@repr
- @@lpde: movzx edx,[BYTE PTR di]
- inc di
- cmp dl,-1
- jnz @@lpd
-
- @@repr: cmp dl,-1 ; search successful?
- jz short @@pice ; if not, everything's the same
- mov [picmasternew],dl
-
- @@pice: ptr2lin pdseg,<off 0+Pdata.idt>,ax,bx,eax,ebx
- mov [idtbase],eax ; set IDT base address
- mov [idtlimit],(256 * SIZE Gate)-1
-
- mov [rmstackbase],off 0+Pdata.rmstack ; set top and base of
- mov [rmstacktop],off RMSTACKLEN + Pdata.rmstack ; real mode stack
-
- ; ------------------ Set up IDT -----------------
- sub di,di
- mov si,off common_int_handler
- sub cx,cx
- @@vxr_idt_loop1:
- mov [pdseg:di + Pdata.idt.offset0],si
- mov [pdseg:di + Pdata.idt.offset1],0
- mov [pdseg:di + Pdata.idt.reserved],0
- mov [pdseg:di + Pdata.idt.sel],SELCS
- mov [pdseg:di + Pdata.idt.gtype],8Fh ; trap gate
- add di,SIZE Gate
- add si,INT_HANDLER_SIZE
- inc cx
- cmp cx,256
- jne @@vxr_idt_loop1
-
- ; ------------------ Set up RM vector pointers --------------
- sub edi,edi
- @@rm_vector_pointer_loop:
- mov [pdseg:di + Pdata.rmint_ptrs],edi
- add di,4
- cmp di,256*4
- jne short @@rm_vector_pointer_loop
-
- ; --------------- Set up hardware IRQ handlers --------------
- mov ax,off common_hardirq_handler
- movzx edx,[privatedataseg]
- shl edx,4
- do16to32 add,dx,<off 0+Pdata.rmint_copy>
-
- mov cl,16
- movzx edi,[picmasterold]
- movzx esi,[picmasternew]
- @@hi1: cmp cl,8
- jne short @@www1
- movzx edi,[picslaveold]
- movzx esi,[picslavenew]
- @@www1: mov [pdseg:edi*SIZE Gate + Pdata.idt.offset0],ax ; fast HW IRQ handler
- mov [pdseg:edi*SIZE Gate + Pdata.idt.gtype],8Eh ; interrupt gate
- mov [pdseg:esi*SIZE Gate + Pdata.idt.offset0],ax ; fast HW IRQ handler
- mov [pdseg:esi*SIZE Gate + Pdata.idt.gtype],8Eh ; interrupt gate
- mov [pdseg:edi*4 + Pdata.rmint_ptrs],edx ; to transparate hook
- mov [pdseg:esi*4 + Pdata.rmint_ptrs],edx ; RM IRQ
- inc si
- inc di
- add ax,HARDIRQ_HANDLER_SIZE
- add edx,SIZE Farptr16
- dec cl
- jne short @@hi1
-
- ; --------------- Copy RM HW Intvectors ---------------------
- mov bl,[picmasterold]
- mov bh,[picslaveold]
- push ds
- cld
- mov di,off 0+Pdata.rmint_copy
- copy es,pdseg,ax
- movzx si,bl
- shl si,2
- sub ax,ax
- mov ds,ax
- mov cx,(8*4)/2
- rep movsw
- movzx si,bh ; NOP not needed
- shl si,2
- mov cx,(8*4)/2
- rep movsw
- mov si,off 0+Pdata.rmint_copy
- mov di,off 0+Pdata.rmint_old
- mov cx,(16*4)/2
- rep movs [word ptr es:di],[word ptr pdseg:si]
- pop ds ; NOP not needed
-
- ; --------------- Set up RM wrappers ------------------------
- mov cl,8
- mov di,off rmwrapper
- mov si,off pic_ints
- @@wrlp: mov [di+Farptr16.sel],cs
- mov [di+Farptr16.offset],si
- add si,PIC_INT_SIZE
- add di,SIZE Farptr16
- dec cl
- jne short @@wrlp
- call [SetMasterPIC] ; set new pic base
-
- ; --------------- Set up exception handler tasks ------------
- sub di,di
- mov si,SELTASKS
- sub cx,cx
- mov bx,off 0 + Pdata.lowint
- @@vxr_idt_loop2:
- mov ax,[pdseg:di + Pdata.idt.offset1]
- shl eax,16
- mov ax,[pdseg:di + Pdata.idt.offset0]
- mov [pdseg:bx + Farptr32.offset],eax
- mov ax,[pdseg:di + Pdata.idt.sel]
- mov [pdseg:bx + Farptr32.sel],ax
- mov [pdseg:bx + Farptr32.pad],0
-
- mov [pdseg:di + Pdata.idt.offset0],0
- mov [pdseg:di + Pdata.idt.offset1],0
- mov [pdseg:di + Pdata.idt.reserved],0
- mov [pdseg:di + Pdata.idt.sel],si
- mov [pdseg:di + Pdata.idt.gtype],85h ; set to Task Gate
-
- add di,SIZE Gate
- add si,SIZE Descriptor
- add bx,SIZE Farptr32
- inc cx
- cmp cx,NUM_EXCEPTIONS
- jne @@vxr_idt_loop2
-
- IF FAST_FPU_EMU EQ 1
- ; 'FPU not present' called by trap gate
- DB 66h
- mov [WORD PTR pdseg:(7*SIZE Gate) + Pdata.idt.offset0],off FPU_emulation
- DW 0
- mov [pdseg:(7*SIZE Gate) + Pdata.idt.reserved],0
- mov [pdseg:(7*SIZE Gate) + Pdata.idt.sel],SELCS
- mov [pdseg:(7*SIZE Gate) + Pdata.idt.gtype],8Fh
- ENDIF
-
- ; Set up special ints
- mov [pdseg:8*31h+Pdata.idt.offset0],off int31 ; protected mode INT 31h
- mov [pdseg:8*21h+Pdata.idt.offset0],off int21 ; protected mode INT 21h
- mov [pdseg:8*23h+Pdata.idt.offset0],off int23pm ; pm INT 23h
- mov [pdseg:8*24h+Pdata.idt.offset0],off int24pm ; pm INT 24h
- mov [pdseg:8*2fh+Pdata.idt.offset0],off int2fpm ; pm INT 2fh
- ; Set callback for int23
- do16to32 mov,<[word ptr cs:hardirq_callback+16*HARDIRQ_CALLBACK_SIZE+HARDIRQ_CALLBACK_OFS]>,<off int23pm>
- mov [word ptr cs:hardirq_callback+16*HARDIRQ_CALLBACK_SIZE \
- +HARDIRQ_CALLBACK_SEL],SELCS
-
- ;-----------------------------------------------------------------------------
-
- ptr2lin pdseg,<off 0+Pdata.pmstack>,ax,bx,eax,ebx
- mov [pmstackbase],eax
- ptr2lin pdseg,<off PMSTACKLEN + Pdata.pmstack>,ax,bx,eax,ebx
- mov [pmstacktop],eax
-
- ;-----------------------------------------------------------------------------
-
- ptr2lin pdseg,<off 0 + Pdata.gdt>,ax,bx,eax,ebx
- mov [gdtbase],eax ; set GDT base address
- mov [gdtlimit],(GDT_NUM_ENTRIES * SIZE Descriptor) - 1
-
- ;-----------------------------------------------------------------------------
-
- ptr2lin pdseg,<off 0 + Pdata.vcpitss>,ax,bx,eax,ebx
- mov [pdseg:SELVCPITSS + Pdata.gdt.base0_15],ax
- shr eax,16
- mov [pdseg:SELVCPITSS + Pdata.gdt.base16_23],al
- mov [pdseg:SELVCPITSS + Pdata.gdt.base24_31],ah
- mov [pdseg:SELVCPITSS + Pdata.gdt.limit0_15],SIZE Tss-1
- mov [pdseg:SELVCPITSS + Pdata.gdt.types],0089h
-
- mov [vcpiswitchstack.offset],off VCPISTACKLEN+Pdata.vcpistack
- mov [vcpiswitchstack.sel],SELPRIVAT
-
- ;-----------------------------------------------------------------------------
-
- setmemw [privatedataseg],<off 0+Pdata.vcpitss>,<SIZE Tss>
- ; clear Switch TSS
- mov es,[privatedataseg]
- mov eax,[vcpi_cr3] ; set CR3 in TSS
- mov [es:Pdata.vcpitss.cr3],eax
- mov [es:Pdata.vcpitss.iomapbase],SIZE Tss
-
- ;-----------------------------------------------------------------------------
-
- mov [WORD PTR pdseg:-2+Pdata.exceptionstack],0
- mov di,off 0 + Pdata.exceptiontasks ; set up exception tasks
- sub esi,esi
- mov si,off common_exception_without_error_handler
- mov edx,[vcpi_cr3] ; EDX = page directory
- sub ecx,ecx
- @@exceptiontaskloop:
- push cx di
- setmemw pdseg,di,<SIZE Tss> ; Clear exception task
- pop di cx
-
- mov [pdseg:di + Tss.ss0],SELPRIVAT
- mov [pdseg:di + Tss.esp0],off 0+Pdata.exceptionstack
- mov [pdseg:di + Tss.ss1],SELPRIVAT
- mov [pdseg:di + Tss.esp1],off 0+Pdata.exceptionstack
- mov [pdseg:di + Tss.ss2],SELPRIVAT
- mov [pdseg:di + Tss.esp2],off 0+Pdata.exceptionstack
- mov [pdseg:di + Tss.ss],SELPRIVAT
- mov [pdseg:di + Tss.esp],off 0+Pdata.exceptionstack
-
- mov [pdseg:di + Tss.cs],SELCS
- mov [pdseg:di + Tss.eip],esi
-
- mov [pdseg:di + Tss.ds],SELPRIVAT ; es and ds are needed
- mov [pdseg:di + Tss.es],SELDS
-
- mov [pdseg:di + Tss.eflags],0
-
- mov [pdseg:di + Tss.cr3],edx
- mov [pdseg:di + Tss.iomapbase],SIZE Tss
-
- mov [pdseg:di + Tss.ebx],ecx ; store exception number
-
- push cx
- and cl,7
- mov ah,1
- shl ah,cl ; ah is mask for pic
- pop cx
-
- mov al,cl ; al is high 5 bits of cx used
- and al,0f8h ; to compare to pic base
- mov [pdseg:di + Tss.eax],eax
- mov [pdseg:di + Tss.edx],off 0 + Pdata.exceptionstack
-
- cmp al,8 ; exceptions 8, 9-0eh have error
- jne short @@go_on ; and we can skip the checking
- cmp cl,9
- je short @@go_on
- cmp cl,0fh
- je short @@go_on
- sub eax,eax
- mov ax,off common_exception_with_error_handler
- mov [pdseg:di + Tss.eip],eax
- @@go_on:
-
- mov [pdseg:di + Tss.ecx],0 ; to be used as default error code
-
- add di,SIZE Tss
- inc cx
- cmp cx,NUM_EXCEPTIONS
- jne @@exceptiontaskloop
-
- ;-----------------------------------------------------------------------------
-
- ptr2lin pdseg,<off 0+Pdata.exceptiontasks>,ax,bx,eax,ebx
- mov bx,SELTASKS
- mov ecx,SIZE Tss-1 ; Limit
- mov dx,1089h ; waiting Task
- sub si,si
- @@taskgateloop:
- push eax dx
- mov [pdseg:bx + Pdata.gdt.limit0_15],cx ; limit = CX
- mov [pdseg:bx + Pdata.gdt.base0_15],ax
- shr eax,16
- mov [pdseg:bx + Pdata.gdt.base16_23],al
- mov [pdseg:bx + Pdata.gdt.base24_31],ah
- mov eax,ecx
- shr eax,8
- and dh,0F0h ; Clear limit16_19
- or dh,ah ; Set it
- mov [pdseg:bx + Pdata.gdt.types],dx ; access rights = DX
- add bx,8
- pop dx eax
-
- add eax,SIZE Tss
- inc si
- cmp si,NUM_EXCEPTIONS
- jne @@taskgateloop
-
- ;-----------------------------------------------------------------------------
-
- init_dsc 0,SELCORE,0FFFFFh,0D092h
-
- init_dsc cs,SELCS,0FFFFh,109Ah ; Make selector for CS
- init_dsc 0,SELREAL,ecx,1092h ; set real mode attributes descriptor
- init_dsc cs,SELALIASCS,ecx,5092h; To write to CS in protected mode
- init_dsc ds,SELDS,ecx,dx ; Make selector for DS
- IF SUPPORT_INT_24
- init_dsc ax,SELINT24,ecx,dx ; Make selector for INT 24 callback
- ENDIF
- init_dsc pdseg,SELPRIVAT,<SIZE Pdata>,dx
-
-
- mov bx,SIZE Descriptor*SYSSELECTORS ; BX = base of free descriptors
- push bx ; store CS selector
- init_dsc cs,bx,0FFFFh,109Ah ; make caller cs selector
- push bx bx ; store SS and DS selectors
-
- init_dsc ss,bx,ecx,5092h ; set caller SS descriptor
-
- mov ax,ds
- mov si,ss ; SS = DS?
- cmp ax,si
- jz short @@skip ; if so, they have to be equal!
- pop ax ; else set new selector for DS
- push bx
- init_dsc ds,bx,ecx,dx
- @@skip:
- push bx ; get PSP segment
- mov ah,51h
- int 21h
- mov es,bx ; set caller environment descriptor
- mov si,bx
- pop bx
-
- mov ax,[es:2ch]
- or ax,ax ; is environment seg 0?
- jz short @@vxr_initf0 ; if yes, dont convert to descriptor
- mov [es:2ch],bx ; store selector value in PSP
- init_dsc ax,bx,ecx,dx
-
- @@vxr_initf0:
- init_dsc si,bx,0FFh,dx ; set caller PSP descriptor
-
- ;-----------------------------------------------------------------------------
-
- lea ecx,[ebx-8] ; CX = ES descriptor, just set
- pop ax ; AX = DS descriptor, from datasegment
- pop dx ; DX = SS descriptor, from stack
- pop si ; target CS, from codesegment
- mov di,off @@vxr_initf2 ; target EIP
- movzx ebx,sp ; EBX = SP, current SP - same stack
- movzx edi,di
-
- jmp [rmtopmswrout] ; jump to mode switch routine
-
- @@vxr_initf2:
- copy coreseg,SELCORE,ax
- copy pdseg,SELDS,ax
-
- mov eax,[coreseg:4*2Fh] ; check if multiplex set
- mov [pdseg:oldint2fvector],eax
- or eax,eax
- jnz short @@ok
- DB 66h
- mov [WORD PTR coreseg:4*2Fh],off int2frm ; set multiplex
- DW _TEXT
- @@ok:
- DB 66h ; set new INT 23h handler
- mov [WORD PTR coreseg:4*23h],off hardirq_callback+16*HARDIRQ_CALLBACK_SIZE
- DW _TEXT
- DB 66h
- mov [WORD PTR coreseg:4*24h],off int24rm ; set new INT 24h handler
- DW _TEXT
- push ds
- copy ds,SELALIASCS,ax
- mov bx,off oldint21vector ; setting direct makes tlink puke
- mov eax,[coreseg:4*21h] ; get DOS vector
- mov [ds:bx],eax ; save
- pop ds
- DB 66h
- mov [WORD PTR coreseg:4*21h],off dos21rm ; set new DOS vector
- DW _TEXT
-
- mov eax,[coreseg:4*15h] ; get INT 15h vector
- mov [pdseg:oldint15vector],eax ; store INT 15h vector
-
- mov esi,[pdseg:rawextmembase] ; ESI = raw base of extended memory
- cmp esi,[pdseg:rawextmemtop] ; is there any raw extended memory?
- jae dvxr_init ; if no, go DPMI/VCPI/XMS/raw init
-
- DB 66h
- mov [WORD PTR coreseg:4*15h],off int15 ; MOV [4*15],_TEXT:offset int15
- DW _TEXT ; set new INT 15h handler
-
- mov edi,[pdseg:rawextmemtop] ; EDI = raw top of extended memory
- mov eax,edi ; EAX = size of extended memory
- sub eax,esi
- sub eax,10h ; subtract memory control block size
- mov [coreseg:edi-16],eax ; store size in memory control block
- xor eax,eax
- mov [coreseg:edi-12],eax ; no next memory control block
- mov [coreseg:edi-8],eax ; no previous memory control block
- mov [coreseg:edi-4],al ; memory block is free
-
- jmp dvxr_init ; go to DPMI/VCPI/XMS/raw init tail
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; set descriptor for VCPI/XMS/raw init
- ; In
- ; ax = real mode segment
- ; bx = Selector
- ; ecx = limit
- ; dx = access rights/type
- ; pdseg = segment to privat data
- ; Out
- ; bx+8, trashes eax
- vxr_initsetdsc:
- push dx
- movzx eax,ax ; EAX = base of segment
- shl eax,4
- mov [pdseg:bx + Pdata.gdt.limit0_15],cx ; limit = CX
- mov [pdseg:bx + Pdata.gdt.base0_15],ax
- shr eax,16
- mov [pdseg:bx + Pdata.gdt.base16_23],al
- mov [pdseg:bx + Pdata.gdt.base24_31],ah
- mov eax,ecx
- shr eax,8
- and dh,0F0h ; Clear limit16_19
- or dh,ah ; Set it
- mov [pdseg:bx + Pdata.gdt.types],dx ; access rights = DX
- add bx,8
- pop dx
- ret
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- x_init: ; XMS protected mode init
- push es
- mov ax,4310h ; get XMS driver address
- int 2fh
- mov [xms_call.offset],bx ; store XMS driver address
- mov [xms_call.sel],es
- pop es
-
- call x_seta20 ; enable A20
- mov bx,4 ; error code 0004h in case of error
- cmp ax,1 ; error enabling A20?
- jc init_done ; if yes, exit with error 0004h
-
- mov [SetA20],off x_seta20 ; procedure to enable a20 under XMS
- mov [ResetA20],off x_reseta20 ; resets a20 to startup state
-
- mov si,off int31mxrouttbl ; set XMS memory allocation functions
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- xr_init: ; XMS/raw common init tail
- mov eax,[dword ptr int31physxrtbl] ; copy physical mapping functions
- mov [dword ptr int31phystbl],eax
-
- mov [rmtopmswrout],off xr_rmtopmsw ; set XMS/raw mode switch addresses
- mov [pmtormswrout],off xr_pmtormsw
-
- mov [SetMasterPIC],off xr_setpic ; set XMS/raw PIC program address
- mov [ResetMasterPIC],off xr_resetpic
-
- mov [picmasterold],8 ; assuming standard PIC mappings
- mov [picslaveold],70h
-
- mov ebx,cr0 ; get CR0
- mov [oldCR0L],bl ; save old state
- sar bl,1
- and bl,3
- mov [newEM_MP],bl
-
- jmp vxr_init ; go to VCPI/XMS/raw continue init
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- r_init: ; raw protected mode init
- mov [SetA20],off r_seta20 ; procedure to enable a20 under raw
- mov [ResetA20],off r_reseta20 ; resets a20 to startup state
-
- mov ah,88h ; how much extended memory free
- int 15h
-
- mov si,off int31mnrouttbl ; SI -> no memory allocation functions
- or ax,ax ; if none, done with raw init
- jz xr_init
-
- movzx eax,ax ; convert AX K to ptr to top of mem
- shl eax,10
- add eax,100000h
- mov [rawextmemtop],eax
-
- call r_seta20 ; enable A20
- mov bx,4
- jc init_done
-
- xor cx,cx ; ES -> 0 (interrupt vector table)
- mov es,cx
- les bx,[dword ptr es:4*19h] ; ES:BX -> int vector table
-
- mov eax,100000h ; initial free extended memory base
- cmp [dword ptr es:bx+12h],'SIDV'; VDISK memory allocation?
- jne short @@r_initf0 ; if present, get base of free mem
-
- mov eax,[dword ptr es:bx+2ch] ; get first free byte of extended mem
- add eax,0fh ; align on paragraph
- and eax,0fffff0h ; address is only 24bit
-
- @@r_initf0:
- dec cx ; ES -> 0ffffh for ext mem addressing
- mov es,cx
-
- cmp [dword ptr es:13h],'SIDV' ; VDISK memory allocation?
- jne short @@r_initf1 ; if present, get base of free mem
-
- movzx ebx,[word ptr es:2eh] ; get first free K of extended memory
- shl ebx,10 ; adjust K to bytes
-
- cmp eax,ebx ; pick larger of 2 addresses
- ja short @@r_initf1
-
- mov eax,ebx
-
- @@r_initf1:
- mov si,off int31mnrouttbl ; SI -> no memory allocation functions
- cmp eax,[rawextmemtop] ; any valid free extended memory
- jae xr_init ; if none, done with raw init
-
- mov [rawextmembase],eax
- mov si,off int31mrrouttbl ; set raw memory allocation functions
-
- jmp xr_init ; go to XMS/raw continue init
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; PROTECTED MODE KERNEL CODE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; VCPI real to protected switch
- v_rmtopmsw:
- pushf ; store FLAGS
- cli
- push DGROUP
- pop ds
- pop [temp0.w0] ; move FLAGS from stack to temp
- mov [temp0.w1],ax ; store AX (protected mode DS)
- mov [temp1.w0],si ; store SI (protected mode CS)
- mov esi,[lvcpistruc] ; ESI = linear addx of VCPI structure
- mov ax,0de0ch ; VCPI switch to protected mode
- int 67h
- v_rmtopmswpm:
- mov ax,SELDS
- mov ds,ax
- mov es,cx ; load protected mode es
- xor eax,eax
- mov fs,ax ; load protected mode FS with NULL
- mov gs,ax ; load protected mode GS with NULL
- mov ax,[temp0.w0]
- and ax,0bfffh ; clear NT flag
- push eax
- popfd
- mov ss,dx ; load protected mode SS:ESP
- mov esp,ebx
- push [temp1.d0] ; push cs
- push edi ; push eip
- mov ds,[temp0.w1] ; caller ds
- DB 66h
- retf ; go to target addx in protected mode
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; VCPI protected to real switch
- v_pmtormsw:
- pushf ; store FLAGS
- cli
- push SELCORE
- pop ds ; for VCPI server
- push SELDS
- pop es
- pop [es:temp0.w0] ; store flags
- mov [es:temp0.w1],ax ; save AX (real mode DS)
- lss esp,[es:vcpiswitchstack.ptr] ; set up switchstack
- sub ax,ax
- push eax ; real mode GS
- push eax ; real mode FS
- push DGROUP ; real mode DS
- push ecx ; real mode ES
- push edx ; real mode SS
- push 0 bx ; real mode ESP
- push eax ; reserved
- DB 66h
- push _TEXT ; push dword _TEXT
- DW 0 ; real mode entry CS
- DB 66h
- push off @@v_pmtormswf0 ; push dword value
- DW 0 ; real mode entry IP
- mov ax,0de0ch ; VCPI switch to real mode (V86)
- call [es:vcpi_service.ptr]
- @@v_pmtormswf0:
- push [temp0.w0] ; store old FLAGS
- mov ds,[temp0.w1] ; get caller ds
- push si ; store target CS in real mode
- push di ; store target IP in real mode
- iret ; go to target addx in real mode
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; XMS/raw real to protected switch
- xr_rmtopmsw:
- pushfd ; store EFLAGS
- cli
- push DGROUP
- pop ds
- push [vcpi_seltss]
- push si ; save SI
- lidt [fword ptr idtlimit] ; load protected mode IDT
- lgdt [fword ptr gdtlimit] ; load protected mode GDT
- mov si,[vcpi_seltss]
- mov ds,[privatedataseg]
- mov [ds:si + Pdata.gdt.types],0089h ; Clear busy bit
- mov esi,cr0 ; switch to protected mode
- or si,1
- mov cr0,esi
- db 0eah ; JMP FAR PTR SELCODE:$+4
- dw $+4,SELCS ; (clear prefetch que)
- pop si
- mov ds,ax ; load protected mode DS
- mov es,cx ; load protected mode ES
- xor ax,ax
- mov fs,ax ; load protected mode FS with NULL
- mov gs,ax ; load protected mode GS with NULL
- lldt ax ; load protected mode LDT
- pop ax ; set up task register
- ltr ax ; load protected mode TR
- clts ; free coprocessor
- pop eax
- mov ss,dx ; load protected mode SS:ESP
- mov esp,ebx
- and ah,0bfh ; set NT=0 in old EFLAGS
- push eax ; set current EFLAGS
- popfd
- push esi ; store protected mode target CS
- push edi ; store protected mode target EIP
- DB 66h
- retf ; go to targed addx in protected mode
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; XMS/raw protected to real switch
- xr_pmtormsw:
- pushf ; store FLAGS
- cli
- push SELDS
- pop ds
- mov [temp0.w0],ax ; move real mode DS to temp
- pop [temp0.w1] ; move FLAGS from stack to temp
- lidt [fword ptr rmidtlimit] ; load real mode IDT
- mov ax,SELREAL ; load descriptors with real mode seg
- mov ds,ax ; attributes
- mov es,ax
- mov fs,ax
- mov gs,ax
- mov ss,ax ; load descriptor with real mode attr
- movzx esp,bx ; load real mode SP, high word 0
- mov eax,cr0 ; switch to real mode
- and al,0feh
- mov cr0,eax
- db 0eah ; JMP FAR PTR PMODE_TEXT:$+4
- dw $+4,_TEXT ; (clear prefetch que)
- mov ss,dx ; load real mode SS
- mov es,cx ; load real mode ES
- xor ax,ax
- mov fs,ax ; load real mode FS with NULL
- mov gs,ax ; load real mode GS with NULL
- copy ds,DGROUP,ax ; datasegment
- push [temp0.w1] ; store old FLAGS
- mov ds,[temp0.w0] ; load real mode DS
- push si ; store real mode target CS
- push di ; store real mode target IP
- iret ; go to target addx in real mode
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; General interrupt handler
- common_int_handler:
- REPT 256
- DB 0E8h
- DW @@int_handler - 2 - $ ; call @@int_handler
- DB 90h ; align
- ENDM
- INT_HANDLER_SIZE = ($ - common_int_handler) / 256
- IF INT_HANDLER_SIZE NE 4
- ERR INT_HANDLER_SIZE must be 4! Or change the code (good luck...)
- ENDIF
- @@int_handler:
- push gs fs ds es
- pushad ; store general registers
- pushf
- and [WORD PTR esp],NOT 300h ; Clear IF and TF
- popf
- copy ds,SELDS,ax
- copy pdseg,SELPRIVAT,ax
- copy coreseg,SELCORE,ax
-
- mov dx,[rmstacktop]
- movzx ebx,dx
- sub dx,RMONESTACKLEN
- cmp dx,[rmstackbase] ; exceeded real mode stack space?
- jb critical_error ; if yes, critical error (hang)
- mov [rmstacktop],dx ; update for possible reentrancy
-
- mov si,[esp+40] ; get "return" address
- sub si,3 + off common_int_handler
- mov esi,[pdseg:si + Pdata.rmint_ptrs] ; get intvector offset pointer
- sub bx,50 ; space on real mode stack
- mov ax,[esp+50] ; get flags
- and ax,NOT 300h ; Clear IF and TF (like in real mode)
- mov [pdseg:bx+32],ax ; put FLAGS
- mov [pdseg:bx+42],ax
- copy [pdseg:bx+34],[coreseg:esi],eax
- DB 66h
- mov [word ptr pdseg:bx+38],off @@inte
- DW _TEXT
- mov [pdseg:bx+44],esp ; protected mode stack
- mov [pdseg:bx+48],ss ; to return to protected mode
-
- dmemcpyw ss,esp,pdseg,ebx,32 ; copy to real mode stack
-
- mov dx,[privatedataseg]
- mov si,_TEXT
- mov di,off @@intrirqf0
- jmp [pmtormswrout] ; switch to real mode
-
- @@intrirqf0:
- popad ; get general registers
- popf
- retf ; jump into rm int
- @@inte: pushf
- pushad ; store general registers
- copy ds,DGROUP,ax
- movzx ebp,sp
- mov dx,[bp+38] ; protected mode SS
- mov ebx,[bp+34] ; protected mode ESP
- mov si,SELCS ; protected mode CS
- mov di,off @@intrirqf1
- movzx edi,di ; protected mode EIP
- mov cx,SELPRIVAT ; protected mode ES
- mov ax,SELDS ; protected mode DS
- jmp [rmtopmswrout] ; jump back to protected mode
-
- @@intrirqf1:
- add [rmstacktop],RMONESTACKLEN ; adjust realmode stack
- mov ax,[es:bp+32] ; get real mode flags
- and [WORD PTR ss:esp+50],200h ; Change all except IF
- and ax,NOT 200h ; Clear IF
- or [ss:esp+50],ax ; set return flags
- dmemcpyw es,ebp,ss,esp,32 ; copy general registers
-
- popad
- pop es ds fs gs ; restore all registers
- add esp,2 ; kill interrupt #
- iretd
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; General hardware IRQ handler (faster than above)
- common_hardirq_handler:
- count = 0
- REPT 16
- DB 6Ah
- DB count ; push offet in rmint_master table
- jmp short @@hard_handler
- count = count + (SIZE Farptr16)
- ENDM
- HARDIRQ_HANDLER_SIZE = ($ - common_hardirq_handler) / 16
- @@hard_handler:
- push 0 ds es fs gs
- pushad ; store general registers
- copy ds,SELDS,ax
- copy pdseg,SELPRIVAT,ax
-
- mov dx,[rmstacktop]
- movzx ebx,dx
- sub dx,RMONESTACKLEN
- cmp dx,[rmstackbase] ; exceeded real mode stack space?
- jb critical_error ; if yes, critical error (hang)
- mov [rmstacktop],dx ; update for possible reentrancy
-
- mov si,[ss:esp+42] ; get intvector
- sub bx,6 ; space on real mode stack
- DB 66h
- mov [WORD PTR pdseg:bx],off @@entr
- DW _TEXT
- mov [word ptr pdseg:bx+4],0 ; put flags on rm iret frame
- mov ebp,esp ; EBP = pm ESP
- mov dx,[privatedataseg] ; set dx to real mode ss
- mov cx,ss ; ES = pm SS
- mov di,[pdseg:si+Pdata.rmint_copy.offset] ; offset of rm int
- mov ax,DGROUP
- mov si,[pdseg:si+Pdata.rmint_copy.sel] ; segment of rm int
- jmp [pmtormswrout] ; switch to real mode
-
- ; regs won't change, because this is an hardware int
- @@entr: mov dx,es ; protected mode SS
- mov ebx,ebp ; protected mode ESP
- mov si,SELCS ; protected mode CS
- do16to32 mov,di,<off @@intrirqf1> ; mov edi,off @@intrirqf1
- mov cx,SELDS ; protected mode ES
- mov ax,cx ; protected mode DS
- jmp [rmtopmswrout] ; jump back to protected mode
-
- @@intrirqf1:
- add [rmstacktop],RMONESTACKLEN ; adjust realmode stack
- popad
- pop gs fs es ds ; restore all registers
- add esp,4 ; kill interrupt #
- iretd
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; Hardware IRQ callback. (for simulating v86 mode)
- hardirq_callback:
- REPT 17 ; used for int23 also
- DB 68h
- DW -1 ; push selector of pm int
- DB 66h,68h
- DD -1 ; push offset of pm int
- DB 0E9h
- DW @@hardirq_callback - 2 - $ ; jump @@hardirq_callback:
- ENDM
- HARDIRQ_CALLBACK_SIZE = ($ - hardirq_callback) / 16
- HARDIRQ_CALLBACK_SEL = 1
- HARDIRQ_CALLBACK_OFS = 5
- @@hardirq_callback:
- push gs fs ds es ; cli not needed, because ints are
- pushad ; disabled automatically on RM HW Ints
- copy ds,DGROUP,ax
- mov bp,ss ; save real mode stack for later
- shl ebp,16
- mov bp,sp
-
- xor eax,eax ; EAX = base address of SS
- mov ax,ss
- shl eax,4
- movzx ebx,sp ; EBX = stack in prot. mode
- add ebx,eax
-
- mov ax,SELDS ; DS selector for protected mode
- mov cx,ax ; ES selector for protected mode
- mov dx,SELCORE ; SS selector
- mov si,SELCS ; target protected mode CS:EIP
- do16to32 mov,di,<off @@callbackf0> ; mov edi,off @@callbackf0
- jmp [rmtopmswrout] ; go to protected mode
-
- @@callbackf0:
- push ebp ; save real mode stack
- pushfd ; simulate interrupt
- call [ss:esp+48+Farptr32.ptr] ; call pm int
- pop bx ; BX = real mode SP
- pop dx ; DX = real mode SS
- mov si,_TEXT ; SI = real mode CS
- mov di,off @@callbackf2 ; DI = real mode IP
- jmp [pmtormswrout] ; switch to real mode
-
- @@callbackf2:
- mov bp,sp
- mov eax,[bp + Dpmi_regs.res] ; get old highword of esp
- mov ax,sp
- mov esp,eax ; restore old esp
-
- popad
- pop es ds fs gs ; restore old regvalues
- add sp,6
- iret
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; handler for NMI interrupt.
- NMI_exception:
- pushfd
- push large cs
- push 0
- call common_int_handler + 2*INT_HANDLER_SIZE
- DB 66h
- retf
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; special handler for emulating the FPU.
- IF FAST_FPU_EMU EQ 1
- EX_SIZE EQU 100 ; bytes to be made available on the user stack
- ; djgpp v2 requires 92 bytes (exception structure size)
- ; in the release version, while beta4 needs 0
- FPU_emulation:
- sub esp,EX_SIZE+6 ; leave required bytes plus slot for ds and edi
- push ss
- push esp
- add [DWORD PTR esp],EX_SIZE+20 ; esp before exception
- push [DWORD PTR esp+EX_SIZE+20] ; move eflags
- push [DWORD PTR esp+EX_SIZE+20] ; move cs
- push [DWORD PTR esp+EX_SIZE+20] ; move eip
- push eax ; dummy error code
- push large cs ; return segment
- db 66h
- push off FPU_emulation_end ; return address
- dw 0
- db 66h, 0EAh ; jmp far to 32 bit offset
- FPU_emu_vector Farptr32 <0,0,0>
-
- FPU_emulation_end:
- add esp,4 ; kill error code
- mov [esp+18],edi ; store edi and ds
- mov [esp+22],ds
- sub [dword ptr esp+12],12 ; make room for iret frame
- lds edi,[esp+12]
- pop [DWORD PTR ds:edi] ; get EIP
- pop [DWORD PTR ds:edi+4] ; get CS
- pop [DWORD PTR ds:edi+8] ; get EFLAGS
- lds edi,[esp+6] ; restore ds and edi
- lss esp,[esp] ; switch to requested stack
- iretd
- ENDIF
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; Exception handler code
- ; We get here through a task switch. ds is SELPRIVAT, es is SELDS, bx is
- ; exception number, al is bl & 0f8h, ah is 1<<(bl&7) (both used for user
- ; int identification), dx is Pdata.exceptionstack, ecx is 0.
- ; ints are disabled, for details, see vxr_init
-
- ASSUME ds:NOTHING
- common_exception_with_error_handler:
- push 2
- popf ; Clear NT flag, disable ints
-
- cmp sp,dx ; Error code on stack?
- jz short do_user_int ; yes, its an exception
- pop ecx ; pop error code
- jmp do_exception
-
- common_exception_without_error_handler:
- push 2
- popf ; Clear NT flag, disable ints
-
- mov dx,020h ; port for master pic
- cmp al,[es:picmasternew]
- je short @@test_hw_int
- mov dx,0a0h ; port for slave pic
- cmp al,[es:picslavenew]
- jne short @@test_sw_int
-
- ; This code assumes that the appropriate hardware int is enabled. I may add
- ; code to fix that, but the probability of this causing trouble is extremely
- ; low and only possible in strange configurations.
- @@test_hw_int:
- mov al,0bh ; read ISR
- out dx,al ; dx is pic port
- jmp short $+2
- in al,dx
- and al,ah ; mask is already in ah
- jnz short do_user_int ; it is an exception
-
- ; There is a probability of wrong identification here if an exception occurs
- ; after an instruction that ends with the sequence 0cdxxh where xx is the
- ; exception number.
- @@test_sw_int:
- mov edi,[ds:Pdata.vcpitss.eip]
- cmp edi,2 ; is it the beginning of the segment
- jb do_exception ; so that int instruction doesn't fit?
- mov ax,[ds:Pdata.vcpitss.cs]
- mov fs,ax
- mov ax,[word ptr fs:edi-2]
- cmp al,0cdh ; is it an int instruction?
- jne short do_exception
- cmp ah,bl ; is the int number correct?
- jne short do_exception
-
- ; Here we serve a hardware or software int if it uses the same vector with an
- ; exception. The registers are restored and we switch to the user task.
- do_user_int:
- mov di,[es:vcpi_seltss]
- mov [ds:di + Pdata.gdt.types],0089h
- ltr di ; now we are in user task
- shl bx,3
- mov [ds:bx + SELTASKS + Pdata.gdt.types],0089h ; clear busy bit
-
- mov ss,[ds:Pdata.vcpitss.ss] ; CPU disables ints for next ins.
- mov esp,[ds:Pdata.vcpitss.esp] ; switch to user stack
-
- ; interrupt frame
- push [ds:Pdata.vcpitss.eflags]
- push [DWORD PTR ds:Pdata.vcpitss.cs]
- push [ds:Pdata.vcpitss.eip]
- ; handler address
- push [DWORD PTR ds:bx + Pdata.lowint.sel]
- push [ds:bx + Pdata.lowint.offset]
-
- mov eax,[ds:Pdata.vcpitss.eax]
- mov ecx,[ds:Pdata.vcpitss.ecx]
- mov edx,[ds:Pdata.vcpitss.edx]
- mov ebx,[ds:Pdata.vcpitss.ebx]
- mov ebp,[ds:Pdata.vcpitss.ebp]
- mov esi,[ds:Pdata.vcpitss.esi]
- mov edi,[ds:Pdata.vcpitss.edi]
- mov es,[ds:Pdata.vcpitss.es]
- mov fs,[ds:Pdata.vcpitss.fs]
- mov gs,[ds:Pdata.vcpitss.gs]
- mov ds,[ds:Pdata.vcpitss.ds]
-
- clts
- DB 66h ; a 32 far return
- retf
-
- ; Here we serve an exception. Error code is in ecx.
- do_exception:
- shl bx,3
- mov di,[es:vcpi_seltss]
- mov [ds:di + Pdata.gdt.types],0089h
- ltr di ; now we are in user task
- mov [ds:bx + SELTASKS + Pdata.gdt.types],0089h ; clear busy bit
-
- push SELCORE ; selector for ss
- mov eax,[es:pmstacktop]
- push eax ; top of pmstack
- sub eax,PMONESTACKLEN ; set EAX to next stack location
- mov [es:pmstacktop],eax ; update ptr for possible reenterancy
-
- cmp eax,[es:pmstackbase] ; exceeded protected mode stack space?
- jbe critical_error ; if yes, critical error (hang)
-
- lss esp,[esp]
- push [DWORD PTR ds:Pdata.vcpitss.ss] ; build up stack like DPMI says
- push [ds:Pdata.vcpitss.esp]
- push [ds:Pdata.vcpitss.eflags]
- push [DWORD PTR ds:Pdata.vcpitss.cs]
- push [ds:Pdata.vcpitss.eip]
- push ecx ; store error code
- push large SELCS
- DB 66h
- push off @@back ; push return address
- DW 0
- push [DWORD PTR ds:bx + Pdata.exceptions.sel] ; push address of
- push [ds:bx + Pdata.exceptions.offset] ; handler
-
- mov eax,[ds:Pdata.vcpitss.eax]
- mov ecx,[ds:Pdata.vcpitss.ecx]
- mov edx,[ds:Pdata.vcpitss.edx]
- mov ebx,[ds:Pdata.vcpitss.ebx]
- mov ebp,[ds:Pdata.vcpitss.ebp]
- mov esi,[ds:Pdata.vcpitss.esi]
- mov edi,[ds:Pdata.vcpitss.edi]
- mov es,[ds:Pdata.vcpitss.es]
- mov fs,[ds:Pdata.vcpitss.fs]
- mov gs,[ds:Pdata.vcpitss.gs]
- mov ds,[ds:Pdata.vcpitss.ds]
-
- DB 66h ; a 32 far return
- retf
-
- @@back: ; if come here, jump back to caller
- sub [DWORD PTR esp+16],18 ; return interrupt frame in user stack
- push edi
- push ds
- mov edi,[esp+22] ; user esp
- mov ds,[esp+26] ; user ss
- pop [WORD PTR ds:edi] ; task's DS
- pop [DWORD PTR ds:edi+2] ; task's EDI
- add esp,4 ; Kill error code
- pop [DWORD PTR ds:edi+6] ; return eip to user stack
- pop [DWORD PTR ds:edi+10] ; return cs to user stack
- pop [DWORD PTR ds:edi+14] ; return eflags to user stack
-
- lss esp,[esp] ; switch to user stack
- push SELDS ; restore the pmstack from the user
- pop ds ; stack in case ints are enabled
- add [ds:pmstacktop],PMONESTACKLEN
- pop ds
- pop edi
- clts
- iretd
-
- ASSUME ds:DGROUP
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; callback handler
- ; The callbacks are not 100% DPMI compliant. If the callback code doesn't
- ; update the cs:ip fields of the call structure the callback should be
- ; entered immediately again. We will hang the computer instead, but this
- ; practice shouldn't be a real problem.
- callback:
- cli
- cld
- mov ax,sp
- add ax,10+32+2+8 ; sp when called
- push ss ax ; store for later use
- copy ds,DGROUP,ax
-
- sub [pmstacktop],PMONESTACKLEN
- mov ebx,[pmstacktop]
- cmp ebx,[pmstackbase] ; exceeded protected mode stack space?
- jbe critical_error ; if yes, critical error (hang)
- add ebx,PMONESTACKLEN ; EBX = top of pmstack
-
- xor eax,eax ; EAX = base address of SS
- mov ax,ss
- shl eax,4
- movzx ebp,sp ; EBP = current linear SS:SP
- add ebp,eax
-
- mov ax,SELCORE ; DS selector for protected mode
- mov dx,ax ; SS selector = DS selector
- mov si,SELCS ; target protected mode CS:EIP
- do16to32 mov,di,<offset @@callbackf0>
-
- jmp [rmtopmswrout] ; go to protected mode
-
- @@callbackf0:
- mov edi,[ebp+4] ; get register structure
- lea esi,[ebp+4+10] ; pointer to saved registers
- dmemcpyw ds,esi,es,edi,32+2+8 ; copy register to struct
- sub edi,32+2+8 ; correct edi
- mov [es:edi+Dpmi_regs.ip],off critical_error
- mov [es:edi+Dpmi_regs.cs],_TEXT ; in case cs:ip are not updated...
- mov eax,[ebp] ; get original ss:sp
- mov [DWORD PTR es:edi+Dpmi_regs.sp],eax
-
- pushfd ; push flags for IRETD from callback
- db 66h ; push 32bit CS for IRETD
- push cs
- dw 6866h,@@callbackf1,0 ; push 32bit EIP for IRETD
-
- push 0 ; pad stack
- push [WORD PTR ebp+4+4+4] ; get callback cs
- push [DWORD PTR ebp+4+4] ; get callback eip
-
- db 66h ; 32bit RETF to callback
- retf
-
- @@callbackf1:
- cli
- push es ; DS:ESI = register structure
- pop ds
- mov esi,edi
- copy es,SELCORE,ax ; ES -> 0 (beginning of memory)
- copy fs,SELDS,ax ; selector for Datasegment
- add [fs:pmstacktop],PMONESTACKLEN ; correct stack
-
- ptr2lin [ds:esi+Dpmi_regs.ss],[ds:esi+Dpmi_regs.sp],di,ax,edi,eax
- sub edi,32+2+8+4 ; Space for regs on rm stack + jump
- dmemcpyw ds,esi,es,edi,32+2+8+4 ; copy regs + jump
- sub esi,32+2+8+4 ; correct ESI
-
- mov bx,[ds:esi+Dpmi_regs.sp]
- sub bx,32+2+8+4 ; BX = real mode SP
- mov dx,[ds:esi+Dpmi_regs.ss] ; DX = real mode SS
- mov si,_TEXT ; SI = real mode CS
- mov di,off @@callbackf2 ; DI = real mode IP
- jmp [fs:pmtormswrout] ; switch to real mode
-
- @@callbackf2:
- mov bp,sp
- mov eax,[bp+Dpmi_regs.res] ; get old highword of esp
- mov ax,sp
- mov esp,eax ; restore old esp
-
- popad ; get callback return general regs
- popf ; get callback flags
- pop es ds fs gs ; get callback return segment regs
- retf ; go to callback return CS:IP
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; real mode INT 15h handler
- int15: push ds
- push DGROUP
- pop ds
- cmp ah,88h ; function 88h?
- je short @@int15f0 ; if yes, need to process
-
- pushf
- call [oldint15vector]
- push bp
- pushf
- mov bp,sp
- pop [WORD PTR bp+10] ; store flags
- pop bp ds
- iret
-
- @@int15f0:
- pushf ; call old int 15h handler
- call [oldint15vector]
-
- sub ax,[rawextmemused] ; adjust AX by extended memory used
-
- push bp ; clear carry flag on stack for IRET
- mov bp,sp
- and [byte ptr bp+8],0feh
- pop bp
-
- pop ds
- iret ; return with new AX extended memory
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; Int 21 (shelling out)
- dos21rm:
- cmp ax,4B00h ; dos exec call
- je short @@doit
- cmp ax,4B03h
- je short @@doit
- cmp ax,4B05h
- je short @@doit
- jmp short @@exit
-
- @@doit: push ax gs fs ds es ; store registers on stack
- pushad
- copy ds,DGROUP,ax
- test [from_us],-1
- jnz short @@nous ; int not from us
-
- inc [from_us] ; for reentrancy
- call [ResetMasterPIC] ; reset to default
- call [ResetA20]
- mov bp,sp
- mov ax,[bp+46]
- mov [bp+40],ax
- popad
- pop es ds fs gs
- call [cs:oldint21vector.ptr] ; call old
- push gs fs ds es ; save return
- pushad
- pushf
- copy ds,DGROUP,ax
- call [SetMasterPIC]
- call [SetA20]
- dec [from_us]
- pop ax ; get flags
- mov bp,sp
- mov [bp+44],ax ; store for iret
- popad
- pop es ds fs gs
- iret ; return to caller
-
- @@nous: popad
- pop es ds fs gs ax
- @@exit: DB 0EAh ; jmp far ?:?
- oldint21vector Farptr16 ?
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; Int 23 (ctrl-c)
- int23pm: iretd ; default pm handler
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; Int 24 (critical error)
- IF SUPPORT_INT_24 NE 0
- int24pm: ; default pm handler
- mov al,3 ; fail is default action. I hope it will never
- iretd ; happen that dos aborts on return
- int24rm: ; callbacks to protected mode
- push gs fs ds es
- pushad
- cli
- copy ds,DGROUP,ax
- mov bp,ss ; save real mode stack for later
- shl ebp,16
- mov bp,sp
-
- xor eax,eax ; EAX = base address of SS
- mov ax,ss
- shl eax,4
- movzx ebx,sp ; EBX = stack in prot. mode
- add ebx,eax
-
- mov ax,SELDS ; DS selector for protected mode
- mov cx,ax ; ES selector for protected mode
- mov dx,SELCORE ; SS selector
- mov si,SELCS ; target protected mode CS:EIP
- do16to32 mov,di,<off @@callbackf0> ; mov edi,off @@callbackf0
- jmp [rmtopmswrout] ; go to protected mode
-
- @@callbackf0:
- movzx edx,[esp + Dpmi_regs.bp]
- shl edx,4
- mov ecx,edx
- shr ecx,16
- mov bx,SELINT24
- mov ax,0007h
- int 31h ; set base of INT 24 selector
-
- mov ax,[esp + Dpmi_regs.ax]
- mov si,[esp + Dpmi_regs.si]
- mov di,[esp + Dpmi_regs.di]
- push ebp
- mov bp,SELINT24
- int 24h ; call pm critical error handler
- pop bx ; BX = real mode SP
- pop dx ; DX = real mode SS
- mov [esp + Dpmi_regs.al],al ; store return value
- mov si,_TEXT ; SI = real mode CS
- mov di,off @@callbackf2 ; DI = real mode IP
- jmp [pmtormswrout] ; switch to real mode
-
- @@callbackf2:
- mov bp,sp
- mov eax,[bp + Dpmi_regs.res] ; get old highword of esp
- mov ax,sp
- mov esp,eax ; restore old esp
-
- popad ; get callback return general regs
- pop es ds fs gs ; get callback return segment regs
- iret
- ELSE
- int24pm: ; for safety supply a pm handler
- mov al,3
- iretd
- int24rm: ; real mode handler
- mov al,3 ; fail is default action. I hope it will never
- iret ; happen that dos aborts on return
- ENDIF
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; internal int 2f, ax=1680h, ax=1686h or ax=168ah
- int2fpm:
- IF PMODEDJ_EXT EQ 1
- cmp ax,168ah
- je short @@int2f168a
- ENDIF
- cmp ax,1680h
- je short @@int2f1680
- cmp ax,1686h
- jne common_int_handler+2fh*INT_HANDLER_SIZE ; if no, go to INT 2fh
- @@int2f1686: ; Get CPU Mode
- xor ax,ax ; we are runniing in protected mode
- iretd
- @@int2f1680: ; Release Current Virtual Machine's Time Slice
- pushfd
- push large cs
- push 0
- call common_int_handler+2fh*INT_HANDLER_SIZE ; pass down to real mode
- test al,al ; is it supported?
- je short @@int2f1680ok ; yes, we are done.
- sti ; give processor a chance to cool down :)
- hlt ; wait for int.
- xor al,al
- @@int2f1680ok:
- iretd
- IF PMODEDJ_EXT EQ 1
- @@int2f168a: ; Get Vendor-Specific API Entry Point
- mov ax,0a00h
- int 31h ; try the extension
- mov ax,1600h ; prepare ax for succesful exit
- iretd
- ENDIF
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; real mode INT 2F handler
- int2frm: iret
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; VCPI/XMS/raw save/restore status (called from real mode)
- vxr_saverestorerm:
- retf ; no save/restore needed, 16bit RETF
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; VCPI/XMS/raw save/restore status (called from protected mode)
- vxr_saverestorepm:
- db 66h,0cbh ; no save/restore needed, 32bit RETF
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; critical error routine
- critical_error: ; some unrecoverable error
- cli ; make sure we are not interrupted
- in al,61h ; beep
- or al,3
- out 61h,al
- jmp $ ; now hang
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; PIC reprogramming
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- ; Resets the master PIC base
- v_resetpic:
- pushf
- cli
- call pic_repr ; reprogramming allowed?
- movzx bx,[picmasterold]
- movzx cx,[picslaveold]
- mov ax,0DE0Bh ; VCPI set pic mappings
- int 67h
- jmp short xr_ddd
- xr_resetpic:
- pushf
- cli
- call pic_repr ; reprogramming allowed?
- xr_ddd: mov cl,[picmasterold] ; set master PIC base to default
- call Change_PIC
- movzx di,[picmasternew] ; Clear entries in the IVT
- shl di,2
- setmemw 0,di,8*4
- popf
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- ; Sets the master PIC base
- v_setpic:
- pushf
- cli
- call pic_repr ; reprogramming allowed?
- movzx bx,[picmasternew]
- movzx cx,[picslavenew]
- mov ax,0DE0Bh ; VCPI set pic mappings
- int 67h
- jmp short xr_eee
- xr_setpic:
- pushf
- cli
- call pic_repr ; reprogramming allowed?
- xr_eee: mov si,off rmwrapper
- movzx di,[picmasternew]
- shl di,2
- sub ax,ax
- mov es,ax
- mov cx,(8*4)/2
- rep movsw ; copy wrappers
- mov cl,[picmasternew] ; NOP not needed
- call Change_PIC
- popf
- ret
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- ; Returns to caller, if reprogramming of the master PIC is not allowed.
- pic_repr:
- pop bx ; pop return address
- test [reprogrampic],-1
- jz short @@oops
- mov al,[picmasternew]
- cmp al,[picmasterold] ; same?
- jz short @@oops
- jmp bx ; repromming allowed, return
- @@oops: popf ; return to caller
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- ; Reprograms the first PIC
- ; IN: CL = new master PIC base; Interrupts disabled
- Change_PIC:
- in al,21h
- mov di,ax ; save old state
- call @@wt
- mov al,0FFh
- out 21h,al ; disable master ints
-
- call @@wt
- mov al,11h
- out 20h,al
- call @@wt
- mov al,cl ; set new base
- out 21h,al
- call @@wt
- mov al,4
- out 21h,al
- call @@wt
- mov al,1
- out 21h,al ; init finished here
- call @@wt
- mov al,0FFh
- out 21h,al ; disable master ints again
-
- mov ax,di
- out 21h,al ; restore master ints
- ret
- @@wt: in al,80h ; a safe ioport
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- ; Redirection interrupt handlers.
- ; Needed so the Compi (hopefully) doesn't crash in real mode when the master
- ; PIC base is changed.
- pic_ints:
- count = 8
- REPT 8
- push eax
- push bp ds
- sub bp,bp
- mov ds,bp
- mov eax,[ds:count*4]
- mov bp,sp
- xchg eax,[ss:bp+4]
- pop ds bp
- retf
- count = count +1
- ENDM
- PIC_INT_SIZE = ($ - pic_ints) / 8
- ; [fold] ]
-
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; A20 control
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- v_seta20: ; Under VCPI A20 is controlled complety by the Memory Manager
- v_reseta20:
- ret_only:
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- x_seta20: ; XMS set A20
- mov ah,7
- call [xms_call.ptr] ; get current state of A20
- mov [olda20],al ; store
-
- mov ah,3 ; enable A20
- call [xms_call.ptr]
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- x_reseta20: ; XMS reset A20
- mov ah,[olda20] ; get old state of A20
- xor ah,1
- add ah,3
- call [xms_call.ptr] ; set to old state
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- r_seta20: ; raw set A20
- clc ; assume success
- pushf ; save intena flag
- cli
- call enablea20test ; get old state
- mov [olda20],al ; is A20 already enabled?
- jz short @@enablea20done ; if yes, done
-
- in al,92h ; PS/2 A20 enable
- or al,2
- jmp short $+2
- jmp short $+2
- jmp short $+2
- out 92h,al
-
- call enablea20test ; is A20 enabled?
- jz short @@enablea20done ; if yes, done
-
- call enablea20kbwait ; AT A20 enable
- jnz short @@enablea20f0
-
- mov al,0d1h
- out 64h,al
-
- call enablea20kbwait
- jnz short @@enablea20f0
-
- mov al,0dfh
- out 60h,al
-
- call enablea20kbwait
-
- @@enablea20f0: ; wait for A20 to enable
- mov cx,800h ; do 800h tries
-
- @@enablea20l0:
- call enablea20test ; is A20 enabled?
- jz short @@enablea20done ; if yes, done
-
- in al,40h ; get current tick counter
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,40h
- mov ah,al
-
- @@enablea20l1: ; wait a single tick
- in al,40h
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,40h
- cmp al,ah
- je @@enablea20l1
-
- loop @@enablea20l0 ; loop for another try
-
- mov bp,sp ; error, A20 did not enable
- or [WORD PTR bp],1 ; set carry
-
- @@enablea20done:
- popf
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- r_reseta20: ; raw reset A20 from GO32/CWSDPMI
- cmp [olda20],0 ; old state of A20
- jne short @@done ; if it was set, do not disable
- pushf ; save INTENA
- cli ; disable ints
- in al,092h ; 092h PS/2 & clone system control port "A"
- and al,not 2 ; this resets the A20 bit in register al
- jmp short $+2 ; forget the instruction fetch
- jmp short $+2
- jmp short $+2
- out 092h,al ; set the A20 bit off
- popf ; restore INTENA
- @@done: ret
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- enablea20kbwait: ; wait for safe to write to 8042
- xor cx,cx
- @@enablea20kbwaitl0:
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,64h ; read 8042 status
- test al,2 ; buffer full?
- loopnz @@enablea20kbwaitl0 ; if yes, loop
- ret
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- enablea20test: ; test for enabled A20
- push ds es
-
- xor ax,ax ; set A20 test segments 0 and 0ffffh
- mov ds,ax
- dec ax
- mov es,ax
-
- mov al,[ds:0] ; get byte from 0:0
- mov ah,al ; preserve old byte
- not al ; modify byte
- xchg al,[es:10h] ; put modified byte to 0ffffh:10h
- xchg bl,[ds:0] ; force cache flush
- cmp ah,bl ; set zero if byte at 0:0 not modified
- xchg bl,[ds:0] ; put back old byte and restore bl
- mov [es:10h],al ; put back old byte at 0ffffh:10h
- sete al
- cbw
-
- pop es ds
- ret ; return, zero if A20 enabled
- ; [fold] ]
-
- ; [fold] ]
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- ; internal int 21, ah=4C
- int21: cmp ah,4ch ; AH = 4Ch?
- jne common_int_handler+21h*INT_HANDLER_SIZE ; if no, go to INT 21h
-
- push ax ; save return value
- copy ds,SELDS,ax
- copy es,SELCORE,ax
- mov eax,[oldint15vector] ; put back old INT 15h handler
- mov [es:4*15h],eax
- mov eax,[oldint2fvector] ; put back old multiplex
- mov [es:4*2fh],eax
- mov eax,[cs:oldint21vector.ptr] ; put back old INT 21h handler
- mov [es:4*21h],eax
-
- mov ebx,cr0 ; restore EM bit
- and ebx,NOT 4
- mov al,[oldCR0L]
- and al,4
- or bl,al
- mov cr0,ebx
-
- mov ax,[privatedataseg]
- mov dx,DGROUP
- sub cx,cx
- mov bx,off endstack-2
- pop [WORD PTR bx] ; put returnvalue on real mode stack
- mov si,_TEXT
- mov di,off @@come
- jmp [pmtormswrout] ; switch to real mode
-
- @@come: mov bl,[ss:picmasterold]
- mov bh,[ss:picslaveold]
- cld
- mov si,off 0+Pdata.rmint_old
- movzx di,bl
- shl di,2
- mov cx,(8*4)/2
- rep movsw
- nop
- movzx di,bh
- shl di,2
- mov cx,(8*4)/2
- rep movsw
- copy ds,DGROUP,ax ; NOP no needed
-
- movzx bx,[pmodetype]
- add bx,bx
- call [exitrouttbl+bx] ; deinit
-
- mov es,[privatedataseg]
- mov ah,49h
- int 21h ; free private data
- call [pm_exit] ; user defined cleanup routine
- pop ax
- int 21h ; quit
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- ; deinit VCPI
- v_exit: call [ResetMasterPIC] ; default PIC mappings
- mov dx,[emspage] ; emspage allocated?
- cmp dx,-1
- jz short @@ok1 ; if not, skip
- mov ah,45h
- int 67h ; free emspage
- @@ok1: ret
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- ; deinit XMS/raw
- x_exit:
- r_exit: call [ResetMasterPIC] ; default PIC mappings
- call [ResetA20] ; default A20 state
- ret
- ; [fold] ]
-
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; INT 31h INTERFACE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- int31: ; protected mode INT 31h handler
- cli
- cld
- push ds es fs gs ; push regs needed
- pushad
- copy coreseg,SELCORE,ax
- copy pdseg,SELPRIVAT,ax
- copy ds,SELDS,ax ; set up selectors
- mov ax,[esp+Dpmi_regs.ax] ; restore ax
-
- push bx
- mov bx,(INT31FUNCNUM - 1) * 2 ; number of functions to check
- @@int31l0:
- cmp ax,[int31functbl+bx] ; found function value?
- jne short @@int31l0c
-
- mov bx,[int31routtbl+bx] ; yes, go to appropriate handler
- xchg bx,[esp]
- ret
-
- @@int31l0c:
- sub bx,2 ; no, continue loop
- jnc @@int31l0
-
- pop bx ; no function found
- jmp short int31fail8001 ; error 8001h
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- ; int 31 fail labels
- int31fail8024: ; INT 31h return fail with error 8024h
- mov [word ptr esp+28],8024h ; set AX on stack to 8024h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8023: ; INT 31h return fail with error 8023h
- mov [word ptr esp+28],8023h ; set AX on stack to 8023h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8022: ; INT 31h return fail with error 8022h
- mov [word ptr esp+28],8022h ; set AX on stack to 8022h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8021: ; INT 31h return fail with error 8021h
- mov [word ptr esp+28],8021h ; set AX on stack to 8021h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8016: ; INT 31h return fail with error 8016h
- mov [word ptr esp+28],8016h ; set AX on stack to 8016h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8015: ; INT 31h return fail with error 8015h
- mov [word ptr esp+28],8015h ; set AX on stack to 8015h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8013: ; INT 31h return fail with error 8013h
- mov [word ptr esp+28],8013h ; set AX on stack to 8013h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8012: ; INT 31h return fail with error 8012h
- mov [word ptr esp+28],8012h ; set AX on stack to 8012h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8011: ; INT 31h return fail with error 8011h
- mov [word ptr esp+28],8011h ; set AX on stack to 8011h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8010: ; INT 31h return fail with error 8010h
- mov [word ptr esp+28],8010h ; set AX on stack to 8010h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8003: ; INT 31h return fail with error 8003h
- mov [word ptr esp+28],8003h ; set AX on stack to 8003h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8001: ; INT 31h return fail with error 8001h
- mov [word ptr esp+28],8001h ; set AX on stack to 8001h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31failcx: ; INT 31h return fail with CX,AX
- mov [word ptr esp+24],cx ; put CX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31failax: ; INT 31h return fail with AX
- mov [word ptr esp+28],ax ; put AX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31fail: ; INT 31h return fail, pop all regs
- popad
- pop gs fs es ds
-
- ;-----------------------------------------------------------------------------
- int31failnopop: ; INT 31h return fail with carry set
- or [byte ptr esp+8],1 ; set carry in EFLAGS on stack
- iretd
-
- ;-----------------------------------------------------------------------------
- int31okedx: ; INT 31h return ok with EDX,CX,AX
- mov [esp+20],edx ; put EDX onto stack for POPAD
- jmp short int31okcx
-
- ;-----------------------------------------------------------------------------
- int31okdx: ; INT 31h return ok with DX,CX,AX
- mov [esp+20],dx ; put DX onto stack for POPAD
- jmp short int31okcx
-
- ;-----------------------------------------------------------------------------
- int31oksinoax: ; INT 31h return ok SI,DI,BX,CX
- mov ax,[esp+28] ; get old value of AX for restore
-
- ;-----------------------------------------------------------------------------
- int31oksi: ; INT 31h return ok SI,DI,BX,CX,AX
- mov [esp+4],si ; put SI onto stack for POPAD
- mov [esp],di ; put DI onto stack for POPAD
- mov [esp+16],bx ; put BX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31okcx: ; INT 31h return ok with CX,AX
- mov [esp+24],cx ; put CX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31okax: ; INT 31h return ok with AX
- mov [esp+28],ax ; put AX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31ok: ; INT 31h return ok, pop all regs
- popad
- pop gs fs es ds
-
- ;-----------------------------------------------------------------------------
- int31oknopop: ; INT 31h return ok with carry clear
- and [byte ptr esp+8],0feh ; clear carry in EFLAGS on stack
- iretd
- ; [fold] ]
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DESCRIPTOR FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int31testsel: ; test for valid selector BX
- pop bp ; pop return address
-
- movzx ebx,bx
- mov edi,[gdtbase]
- cmp bx,[gdtlimit] ; selector BX out of range?
- ja int31fail8022 ; if yes, fail with error 8022h
-
- test bl,7 ; index in LDT? Or wrong RPL?
- jnz int31fail8022 ; Only GDT allowed
- ;and bl,0f8h mask offset table index and RPL - not needed, its zero
- test [byte ptr coreseg:6+ebx+edi],10h; is descriptor used?
- jz int31fail8022 ; if descriptor not used, fail 8022h
-
- jmp bp ; return ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int31testaccess: ; test access bits in CX
- pop bp ; pop return address
-
- IF STRICT_RING_CHECKING EQ 0
- and cl,9Fh
- ENDIF
- test ch,20h ; test MUST BE 0 bit in CH
- jnz int31fail8021 ; if not 0, error 8021h
-
- test cl,90h ; test present and MUST BE 1 bits
- jz int31fail8021 ; if both 0, error 8021h
- jpo int31fail8021 ; if unequal, error 8021h
-
- test cl,60h ; test DPL
- jnz int31fail8021 ; if not 0, error 8021h
-
- test cl,8 ; if code, more tests needed
- jz short @@int31testselok ; if data, skip code tests
-
- test cl,2 ; readable?
- jz int31fail8021
- test cl,4 ; non-conform?
- jnz int31fail8021
-
- @@int31testselok:
- jmp bp ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310000: ; allocate descriptors
- or cx,cx ; if CX = 0, error 8021h
- jz int31fail8021
-
- mov edx,[gdtbase] ; get base of GDT
- movzx eax,[gdtlimit] ; EAX = last selector index
- and al,0f8h
-
- mov bx,cx ; BX = number of selectors to find
- @@int310000l0:
- test [byte ptr coreseg:edx+eax+6],10h; is descriptor used?
- jnz short @@int310000l0f0
-
- dec bx ; found free descriptor, dec counter
- jnz short @@int310000l0f1 ; continue if need to find more
-
- mov ebx,eax ; found all descriptors requested
- @@int310000l1:
- mov [dword ptr coreseg:edx+ebx],0 ; set entire new descriptor
- mov [dword ptr coreseg:edx+ebx+4],109200h
- add bx,8 ; increment selector index
- dec cx ; dec counter of descriptors to mark
- jnz @@int310000l1 ; loop if more to mark
-
- jmp int31okax ; return ok, with AX
-
- @@int310000l0f0:
- mov bx,cx ; reset number of selectors to find
-
- @@int310000l0f1:
- sub ax,8 ; dec current selector counter
- cmp ax,8*SYSSELECTORS ; more descriptors to go?
- jae @@int310000l0 ; if yes, loop
-
- jmp int31fail8011 ; did not find descriptors
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310001: ; free descriptor
- call int31testsel ; test for valid selector BX
- mov ax,ss
- cmp bx,ax ; free stackselector?
- jz int31fail8022 ; never do this!
- cmp bx,[esp+32+8+4] ; free codeselector?
- jz int31fail8022
-
- and [byte ptr coreseg:edi+ebx+6],0efh; mark descriptor as free
- and [byte ptr coreseg:edi+ebx+5],07Fh; clear present bit
-
- mov cx,4 ; zero any segregs loaded with BX
- lea ebp,[esp+32] ; EBP -> selectors on stack
- @@int310001l0:
- cmp [word ptr ebp],bx ; selector = BX?
- jne short @@int310001l0f0 ; if no, continue loop
-
- mov [word ptr ebp],0 ; zero selector on stack
-
- @@int310001l0f0:
- add ebp,2 ; increment selector ptr
- loop @@int310001l0 ; loop
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310002: ; segment to selector
- mov si,off segmentbases ; check, if segment already mapped
- @@lp1: mov ax,[si + 0] ; load selector to ax
- test ax,ax ; selector valid?
- jz short @@skp
- cmp bx,[si + 2] ; compare segment values
- jz int31okax
- @@skp: add si,4
- cmp si,off segmentbases + segmentbases_SIZE
- jb @@lp1
-
- mov si,off segmentbases ; search for a free entry
- @@lp2: test [word ptr si],-1 ; this field free?
- jz short @@skp2 ; if so, use it
- add si,4
- cmp si,off segmentbases + segmentbases_SIZE
- jb @@lp2
- jmp int31fail8010 ; no entry free
-
- @@skp2: mov [si + 2],bx ; store segment
- movzx edi,bx ; convert to linear address
- shl edi,4
- mov cx,1
- sub ax,ax
- int 31h ; allocate selector
- jc int31failax
- mov [si + 0],ax ; store selector
-
- mov bx,ax
- sub cx,cx
- mov dx,-1
- mov ax,8
- int 31h ; set descriptor limit
-
- mov dx,di
- shr edi,16
- mov cx,di
- mov ax,7
- int 31h ; set descriptor base - cannot fail
-
- mov cx,4092h
- mov ax,9
- int 31h ; set access rights
-
- mov ax,bx ; return selector
- jmp int31okax
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310003: ; get selector increment value
- mov ax,8 ; selector increment value is 8
- jmp int31okax ; return ok, with AX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310006: ; get segment base address
- call int31testsel ; test for valid selector BX
-
- mov dx,[word ptr coreseg:edi+ebx+2] ; low word of 32bit linear addr
- mov cl,[byte ptr coreseg:edi+ebx+4] ; high word of 32bit linear addr
- mov ch,[byte ptr coreseg:edi+ebx+7]
-
- jmp int31okdx ; return ok, with DX, CX, AX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310007: ; set segment base address
- call int31testsel ; test for valid selector BX
-
- mov [word ptr coreseg:edi+ebx+2],dx ; low word of 32bit linear addr
- mov [byte ptr coreseg:edi+ebx+4],cl ; high word of 32bit linear addr
- mov [byte ptr coreseg:edi+ebx+7],ch
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310008: ; set segment limit
- call int31testsel ; test for valid selector BX
-
- cmp cx,0fh ; limit greater than 1M?
- jbe short @@int310008f0
-
- ; Current DJGPP code doesn't work with limit check, so...
- IF STRICT_LIMITS EQ 1
- mov ax,dx ; yup, limit greater than 1M
- and ax,0fffh
- cmp ax,0fffh ; low 12 bits set?
- jne int31fail8021 ; if no, error 8021h
- ENDIF
- shrd dx,cx,12 ; DX = low 16 bits of page limit
- shr cx,12 ; CL = high 4 bits of page limit
- or cl,80h ; set granularity bit in CL
-
- @@int310008f0:
- mov [word ptr coreseg:edi+ebx],dx ; put low word of limit
- and [byte ptr coreseg:edi+ebx+6],70h ; mask off G and high nybble of limit
- or [byte ptr coreseg:edi+ebx+6],cl ; put high nybble of limit
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310009: ; set descriptor access rights
- call int31testsel ; test for valid selector BX
-
- call int31testaccess ; test access bits in CX
-
- or ch,10h ; set AVL bit, descriptor used
- and ch,0f0h ; mask off low nybble of CH
- and [byte ptr coreseg:edi+ebx+6],0fh ; mask off high nybble access rights
- or [byte ptr coreseg:edi+ebx+6],ch ; or in high access rights byte
- mov [byte ptr coreseg:edi+ebx+5],cl ; put low access rights byte
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int31000a: ; create alias descriptor
- call int31testsel ; test for valid selector BX
-
- mov ax,0000h ; allocate descriptor
- mov cx,1
- int 31h
- jc int31fail8011 ; if failed, descriptor unavailable
-
- push ax ; preserve allocated selector
-
- movzx edi,ax ; EDI = target selector
- mov esi,[gdtbase] ; ESI -> GDT
-
- copy [coreseg:esi+edi],[coreseg:esi+ebx],eax
- mov eax,[coreseg:esi+ebx+4] ; copy descriptor data
- mov ah,92h
- mov [coreseg:esi+edi+4],eax
-
- pop ax ; restore allocated selector
-
- jmp int31okax ; return ok, with AX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int31000b: ; get descriptor
- call int31testsel ; test for valid selector BX
-
- lea esi,[edi+ebx] ; ESI -> descriptor in GDT
- mov edi,[esp] ; get EDI buffer ptr from stack
- copy [es:edi+0],[coreseg:esi+0],eax ; copy descriptor
- copy [es:edi+4],[coreseg:esi+4],eax
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int31000c: ; set descriptor
- call int31testsel ; test for valid selector BX
-
- mov esi,[esp] ; ESI = EDI buffer ptr from stack
- mov cx,[es:esi+5] ; get access rights from descriptor
- call int31testaccess ; test access bits in CX
-
- add edi,ebx ; adjust EDI to descriptor in GDT
- copy [coreseg:edi],[es:esi],eax
- mov eax,[es:esi+4]
- or eax,100000h ; set descriptor AVL bit
- mov [coreseg:edi+4],eax
- IF STRICT_RING_CHECKING EQ 0
- and [byte ptr coreseg:edi+5],9Fh ; set DPL to 0
- ENDIF
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int31000e: ; get multiple descriptors
- IF MULTI_DESCRIPTORS NE 0
- mov ax,000bh ; function 000bh, get descriptor
-
- ;-----------------------------------------------------------------------------
- int31000ef: ; common to funcions 000eh and 000fh
- or cx,cx ; if CX = 0, return ok immediately
- jz int31ok
-
- mov dx,cx ; DX = number of descriptors
- xor cx,cx ; CX = successful counter
- @@int31000efl0:
- mov bx,[es:edi] ; BX = selector to get
- add edi,2
-
- int 31h ; get/set descriptor
- jc int31failcx ; if error, fail with AX and CX
-
- add edi,8 ; increment descriptor ptr
- inc cx ; increment successful copy counter
- dec dx ; decrement loop counter
- jnz @@int31000efl0 ; if more descriptors to go, loop
-
- jmp int31ok ; return ok
- ENDIF
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int31000f: ; set multiple descriptors
- IF MULTI_DESCRIPTORS NE 0
- mov ax,000ch ; function 000ch, set descriptor
-
- jmp int31000ef ; go to common function
- ENDIF
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DOS MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int31010getdosbase:
- pop bp ; return address
-
- mov si,dx ; save selector for later use
- mov bx,si
- mov ax,6
- int 31h ; Get base of selector
- jc int31failax ; fail, if selector invalid
-
- test dx,0Fh ; not paragraph aligned?
- jnz int31failax ; not a valid segment address
-
- shrd dx,cx,4 ; make segment address
- test cx,0FFF0h ; above first MB border?
- jnz int31fail8021 ; if so, fail
-
- jmp bp ; else selector and address ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int31010issueint:
- pop bp
-
- mov [esp + Dpmi_regs.es],dx
- mov [esp + Dpmi_regs.ss],0
- mov [esp + Dpmi_regs.sp],0 ; no own stack
- mov edi,esp
- copy es,ss,ax
- mov bx,21h ; dos int, no reset of PICs and A20
- sub cx,cx ; no stack params to copy
- mov ax,300h
- int 31h ; make dos interrupt
- jnc short @@ok
- add esp,SIZE Dpmi_regs
- jmp int31failax
- @@ok: mov cx,[esp + Dpmi_regs.flags]
- mov ax,[esp + Dpmi_regs.ax]
- mov bx,[esp + Dpmi_regs.bx]
- add esp,SIZE Dpmi_regs ; correct stack
- test cx,1 ; allocation successful?
- jz short @@away
- mov [esp + Dpmi_regs.bx],bx ; return max. # of paragraphs
- jmp int31failax
-
- @@away: jmp bp
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310100: ; Allocate DOS memory block
- sub esp,SIZE Dpmi_regs ; space for real mode registers
- mov [esp + Dpmi_regs.ax],4800h ; dos function allocate memory
- mov [esp + Dpmi_regs.bx],bx ; # of paragraphs
- call int31010issueint ; attempt to allocate memory
- mov si,ax ; save segment for later use
-
- sub ax,ax ; Allocate Descriptor
- mov cx,1 ; 1 is enough for 32bit code
- int 31h ; try to get one
- jc short @@failfree ; fail, if no descriptor free
- mov bx,ax ; BX = DOS mem selector
-
- mov cx,4092h ; data descriptor
- mov ax,9
- int 31h ; set descriptor type
-
- movzx ecx,[esp + Dpmi_regs.bx] ; get size
- shl ecx,4
- dec ecx
- mov dx,cx
- shr ecx,16
- mov ax,8
- int 31h ; Set descriptor limit
-
- mov cx,si ; CX = highword of linear address
- mov dx,cx ; DX = lowword of linear address
- shr cx,12
- shl dx,4
- mov ax,7
- int 31h ; set descriptor base
-
- mov ax,si ; initial real mode segment
- mov [esp + Dpmi_regs.dx],bx ; store selector
- jmp int31okax ; return successful
-
- @@failfree:
- sub esp,SIZE Dpmi_regs ; space for real mode registers
- mov [esp + Dpmi_regs.ax],4900h ; dos function free memory
- mov dx,si ; segment
- call int31010issueint ; free memory
- jmp int31fail8011 ; and fail
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310101: ; Free DOS memory block
- call int31010getdosbase ; check selector and get segment addr
-
- mov bx,si
- mov ax,1
- int 31h ; free associated selector
-
- sub esp,SIZE Dpmi_regs ; space for real mode registers
- mov [esp + Dpmi_regs.ax],4900h ; dos function free memory
- call int31010issueint ; attempt to free memory
-
- jmp int31okax ; else return no error
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310102: ; Resize DOS memory block
- mov di,bx ; save size for later use
-
- call int31010getdosbase ; check selector and segment addr
-
- sub esp,SIZE Dpmi_regs ; space for real mode registers
- mov [esp + Dpmi_regs.ax],4A00h ; dos function resize memory
- mov [esp + Dpmi_regs.bx],di ; new size
- call int31010issueint ; attempt to resize memory
-
- movzx ecx,[esp + Dpmi_regs.bx] ; get size again
- shl ecx,4
- dec ecx
- mov dx,cx
- shr cx,16
- mov bx,[esp + Dpmi_regs.dx] ; get selector
- mov ax,8
- int 31h ; Set descriptor limit
-
- jmp int31okax
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; INTERRUPT FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310200: ; get real mode interrupt vector
- mov al,bl
- and al,0F8h ; In any PIC range?
-
- cmp al,[picmasterold]
- je short @@std
- cmp al,[picmasternew] ; In the new range?
- je int31fail8003 ; system integrity
-
- @@std: movzx ebx,bl ; EBX = BL (interrupt number)
- mov ebx,[pdseg:ebx*4 + Pdata.rmint_ptrs]
- mov dx,[coreseg:ebx] ; load real mode vector offset
- mov cx,[coreseg:ebx+2] ; load real mode vector segment
- jmp int31okdx ; return ok, with AX, CX, DX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310201: ; set real mode interrupt vector
- movzx ebx,bl ; EBX = BL (interrupt number)
- push cx dx
- pop edx ; EDX = pointer to RM Int vector
- mov al,bl
- and ax,0F8h ; In any PIC range?
- mov si,bx
- and esi,7 ; IRQ #
- mov bp,si
-
- movzx edi,[picmasternew]
- cmp al,[picmasterold]
- je short @@pics
- cmp ax,di ; In the new range?
- je int31fail8003 ; system integrity
-
- movzx edi,[picslavenew]
- cmp al,[picslaveold]
- jne short @@std
- add si,8
-
- @@pics: shl si,2
- mov [pdseg:si + Pdata.rmint_copy.ptr],edx
- cmp edx,[pdseg:si + Pdata.rmint_old.ptr]
- jne short @@hook ; original handler installed?
-
- cmp ax,di ; any difference in old and new?
- je short @@skp
- add di,bp
- imul dx,si,PIC_INT_SIZE
- shr dx,2
- add dx,off pic_ints
- push _TEXT dx
- pop edx
- mov [si + rmwrapper.ptr],edx
- mov [coreseg:edi*SIZE Farptr16 + Farptr16.ptr],edx
-
- @@skp: mov ax,204h ; This will unhook the hidden
- int 31h ; callback if not necessary
- mov ax,205h
- int 31h
- jmp int31ok
-
- @@hook: cmp ax,di
- je short @@std
- add di,bp
- mov [si + rmwrapper.ptr],edx
- mov [coreseg:edi*SIZE Farptr16 + Farptr16.ptr],edx
-
- @@std: mov [coreseg:ebx*4],edx ; set real mode int vector offset
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310202: ; get exception handler
- cmp bl,31 ; Check exception number
- ja int31fail8021
-
- movzx ebx,bl
- mov cx,[pdseg:ebx*SIZE Farptr32 + Pdata.exceptions.sel]
- mov edx,[pdseg:ebx*SIZE Farptr32 + Pdata.exceptions.offset]
-
- mov ax,202h ; no error code
- jmp int31okedx
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310203: ; set exception handler
- cmp bl,31 ; Check exception number
- ja int31fail8021
-
- xchg bx,cx ; swap int number with int selector
- call int31testsel ; test for valid selector BX
-
- movzx ecx,cl
- mov [pdseg:ecx*SIZE Farptr32 + Pdata.exceptions.pad],0
- mov [pdseg:ecx*SIZE Farptr32 + Pdata.exceptions.sel],bx
- mov [pdseg:ecx*SIZE Farptr32 + Pdata.exceptions.offset],edx
-
- IF FAST_FPU_EMU EQ 1
- copy es,SELALIASCS,ax
- mov ax,[pdseg:7*SIZE Farptr32 + Pdata.exceptions.sel]
- mov [es:FPU_emu_vector.sel],ax
- mov eax,[pdseg:7*SIZE Farptr32 + Pdata.exceptions.offset]
- mov [es:FPU_emu_vector.offset],eax
- ENDIF
- jmp int31ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310204: ; get protected mode interrupt vector
- movzx ebx,bl ; EBX = BL (interrupt number)
- cmp bl,NUM_EXCEPTIONS
- jae short @@ok3
- mov cx,[pdseg:ebx*SIZE Farptr32 + Pdata.lowint.sel]
- mov edx,[pdseg:ebx*SIZE Farptr32 + Pdata.lowint.offset]
-
- mov ax,204h
- jmp int31okedx
-
- @@ok3: mov dx,[pdseg:ebx*8+Pdata.idt.offset1] ; get high word of offset
- shl edx,16
- mov dx,[pdseg:ebx*8+Pdata.idt.offset0] ; get low word of offset
- mov cx,[pdseg:ebx*8+Pdata.idt.sel] ; get selector
-
- mov ax,204h
- jmp int31okedx ; return ok, with AX, CX, EDX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310205: ; set protected mode interrupt vector
- xchg bx,cx ; swap int number with int selector
- call int31testsel ; test for valid selector BX
-
- copy es,SELALIASCS,ax
- movzx ecx,cl ; ECX = CL (interrupt number)
-
- ; This code sets the requested int number and if it is a hardware int on the
- ; master pic, then the actual irq int is set as well. The only problem is that
- ; requests to set one of the actual irq's will fail with error 8003h (system
- ; integrity). One possible solution is to reprogram the offending pic in such
- ; a case, but I won't bother for the time being.
- mov al,cl
- and al,0f8h
- cmp al,[picmasterold]
- jne short @@notmaster
- ; set master pic int
- mov esi,ecx
- and si,7
- call @@hookhidden
- call @@setint
- sub cl,[picmasterold]
- add cl,[picmasternew]
- jmp short @@soft
-
- @@notmaster:
- cmp al,[picslaveold]
- jne short @@notslave
-
- mov esi,ecx
- and si,7
- or si,8
- call @@hookhidden
- jmp short @@soft
-
- @@notslave:
- cmp al,[picmasternew]
- je int31fail8003
-
- @@soft: call @@setint
- cmp cl,23h ; ctrl-c ?
- jne int31ok ; if not, finished
-
- @@ctrl: mov si,16
- call @@hookhidden ; set ctrl-c callback
- jmp int31ok
-
- ;-----------------------------------------------------------------------------
- @@hookhidden: ; hooks RM HW
- imul bp,si,HARDIRQ_CALLBACK_SIZE
- add bp,off hardirq_callback ; update pointer in hardirq_callback
- mov [es:bp+HARDIRQ_CALLBACK_OFS],edx
- mov [es:bp+HARDIRQ_CALLBACK_SEL],bx
-
- cmp bx,SELCS ; our pm int handler?
- je short @@remo ; if so, deinstall our callback
-
- mov [coreseg:ecx*SIZE Farptr16 + Farptr16.sel],_TEXT
- mov [coreseg:ecx*SIZE Farptr16 + Farptr16.offset],bp
- ret ; install our 'hidden' rm to pm IRQ callback
-
- @@remo: mov eax,[pdseg:esi*SIZE Farptr16 + Pdata.rmint_copy.ptr]
- mov [coreseg:ecx*SIZE Farptr16+Farptr16.ptr],eax
- ret ; deinstall 'hidden' IRQ callback
-
- ;-----------------------------------------------------------------------------
- @@setint:
- cmp cl,NUM_EXCEPTIONS
- jae short @@setint1
- mov [pdseg:ecx*SIZE Farptr32 + Pdata.lowint.pad],0
- mov [pdseg:ecx*SIZE Farptr32 + Pdata.lowint.sel],bx
- mov [pdseg:ecx*SIZE Farptr32 + Pdata.lowint.offset],edx
- ret
- @@setint1:
- mov [pdseg:ecx*8+Pdata.idt.offset0],dx ; set low word of offset
- shld eax,edx,16
- mov [pdseg:ecx*8+Pdata.idt.offset1],ax ; set high word of offset
- mov [pdseg:ecx*8+Pdata.idt.sel],bx ; set selector
- ret
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310900: ; get and disable interrupt state
- btc [word ptr esp+48],9 ; test and clear IF bit in EFLAGS
- setc al ; set AL = carry (IF flag from EFLAGS)
-
- jmp int31okax ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310901: ; get and enable interrupt state
- bts [word ptr esp+48],9 ; test and set IF bit in EFLAGS
- setc al ; set AL = carry (IF flag from EFLAGS)
-
- jmp int31okax ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310902: ; get interrupt state
- bt [word ptr esp+48],9 ; just test IF bit in EFLAGS
- setc al ; set AL = carry (IF flag from EFLAGS)
-
- jmp int31okax ; return ok
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; REAL/PROTECTED MODE TRANSLATION FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310300: ; simulate real mode interrupt
- push cx
- mov ax,200h
- int 31h ; get real mode INT CS:IP
- mov [es:edi+Dpmi_regs.cs],cx
- mov [es:edi+Dpmi_regs.ip],dx
- pop cx
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310301: ; call real mode FAR procedure
- ; same start as function 0302h
- ;─────────────────────────────────────────────────────────────────────────────
- int310302: ; call real mode IRET procedure
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int3103: ; common to 0300h, 0301h, and 0302h
- movzx ebx,[es:edi+Dpmi_regs.sp] ; EBX = SP from register structure
- movzx edx,[es:edi+Dpmi_regs.ss] ; EDX = SS from register structure
-
- mov ax,bx ; check if caller provided stack
- or ax,dx
- jnz short @@int3103f3 ; if yes, go on to set stack
-
- mov dx,[privatedataseg] ; real mode SS
- mov bx,[rmstacktop] ; BX = top of real mode stack
- mov ax,bx ; save top of stack
- sub bx,RMONESTACKLEN ; adjust BX to next stack location
-
- cmp bx,[rmstackbase] ; exceeded real mode stack space?
- jb int31fail8012 ; if yes, error 8012h
-
- mov [rmstacktop],bx ; update ptr for possible reenterancy
- mov bx,ax ; restore top of stack
-
- @@int3103f3:
- shl edx,4 ; convert seg:ofs form to linear
- mov edi,edx ; address
- add edi,ebx ; EDI = top of real mode stack
-
- sub edi,10
- lea ax,[bx-10] ; AX = top of stack parms
- xchg ax,[rmstackparmtop] ; preserve and set new top of stack
- push ax ; parms for possible reenterancy
-
- mov [coreseg:edi+8],cx ; store # of parameters
- mov [coreseg:edi+6],ss ; store SS:ESP on real mode stack
- mov [coreseg:edi+2],esp ; ESP when switching to real mode
- mov [coreseg:edi+0],es ; store ES on real mode stack
-
- movzx ecx,cx
- lea esi,[esp+ecx*2+2+32+8+12] ; start of parameters on stack
- mov ebx,ecx
- jmp short @@lp1in
- @@lp1: sub esi,2
- mov ax,[ss:esi]
- sub edi,2
- mov [coreseg:edi],ax ; copy parameters
- @@lp1in:dec ebx
- jns @@lp1
-
- mov esi,[esp+2+Dpmi_regs.edi] ; call struct
- mov ax,[es:esi+Dpmi_regs.flags] ; AX = flags for real mode
- cmp [esp+2+Dpmi_regs.ax],301h ; if function 301h, no space for flags
- jz short @@w1
- and ah,0fch ; 0300h or 0302h, clear IF and TF flag
- mov [es:esi+Dpmi_regs.flags],ax
- sub edi,2 ; push flags for IRET stack frame
- mov [coreseg:edi],ax
- @@w1:
- mov [WORD PTR coreseg:edi-4],off @@int3103f1
- mov [WORD PTR coreseg:edi-2],_TEXT
- copy <[DWORD PTR coreseg:edi-8]>,<[DWORD PTR es:esi+Dpmi_regs.ip]>,eax
-
- sub edi,8+42
- dmemcpyw es,esi,coreseg,edi,42 ; copy registers + flags
- sub edi,42 ; correct edi
-
- sub edi,edx
- mov ax,DGROUP ; AX = Real Mode DS
- movzx ebx,di ; EBX = Real Mode ESP
- shr edx,4 ; DX = Real Mode SS
- mov si,_TEXT ; SI = Real Mode CS
- mov di,off @@int3103f0 ; DI = Real Mode IP
- jmp [pmtormswrout] ; switch to real mode
-
- @@int3103f0: ; real mode INT, FAR, or IRET call
- popad ; load regs with call values
- popf ; load flags with call value
- pop es ds fs gs ; load sregs with call values
- retf ; go to call address
-
- @@int3103f1:
- push gs fs ds es ; store registers on stack
- pushf ; store flags on stack
- cli
- pushad
- copy ds,DGROUP,ax
- mov bp,[rmstackparmtop]
-
- mov cx,[bp+0] ; get protected mode ES from stack
- mov ebx,[bp+2] ; get protected mode SS:ESP from stack
- mov dx,[bp+6]
-
- mov bp,ss ; EBP = linear ptr to SS
- movzx ebp,bp
- shl ebp,4
-
- mov ax,SELDS ; DS selector value for protected mode
- mov si,SELCS ; target CS:EIP in protected mode
- do16to32 mov,di,<off @@int3103f2>
- jmp [rmtopmswrout] ; go back to protected mode
-
- @@int3103f2:
- copy coreseg,SELCORE,ax
- copy pdseg,SELPRIVAT,ax
-
- movzx eax,[rmstackparmtop]
- add ebp,eax ; EBP = linear address of rm stack
- pop [rmstackparmtop]
-
- movzx eax,[WORD PTR coreseg:ebp+8] ; get paramcount
- add eax,eax
- sub ebp,eax
- lea esi,[ebp-42]
- mov edi,[esp+Dpmi_regs.edi] ; get structure offset from stack
- dmemcpyw coreseg,esi,es,edi,42 ; copy regs and flags
-
- cmp [dword ptr es:edi+4],0 ; stack provided by caller?
- jne int31ok ; if yes, done now
-
- add [rmstacktop],RMONESTACKLEN ; restore top of real mode stack
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310303: ; allocate real mode callback address
- mov dx,CALLBACKS ; DX = total number of callbacks
- mov bx,off common_callbacks ; BX = base of callbacks
- jmp short @@in
- @@int310303l0:
- cmp [bx+Callback.ds],0 ; is this callback free?
- jz short @@int310303f0 ; if yes, allocate
-
- add bx,SIZE Callback ; increment ptr to callback
- @@in: dec dx ; decrement loop counter
- jns @@int310303l0 ; if more callbacks to check, loop
-
- jmp int31fail8015 ; no free callback, error 8015h
-
- @@int310303f0:
- mov cx,[esp+38] ; CX = caller DS from stack
- mov [bx+Callback.ds],cx ; store callback parms in callback
- mov [bx+Callback.esi],esi
- mov [bx+Callback.es],es
- mov [bx+Callback.edi],edi
- mov [bx+Callback.ptr.offset],off callback
- mov [bx+Callback.ptr.sel],_TEXT
-
- mov dx,bx ; DX = offset of callback
- mov cx,DGROUP ; CX = segment of callback
-
- jmp int31okdx ; return ok, with DX, CX, AX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310304: ; free real mode callback address
- cmp cx,DGROUP ; valid callback segment?
- jne int31fail8024 ; if no, error 8024h
-
- mov bx,dx ; BX = offset of callback
-
- xor ax,ax ; check if valid offset
- xchg dx,ax
- sub ax,off common_callbacks
- mov cx,SIZE Callback
- div cx
-
- or dx,dx ; is there a remainder
- jnz int31fail8024 ; if yes, not valid, error 8024h
-
- cmp ax,CALLBACKS ; callback index out of range?
- jae int31fail8024 ; if yes, not valid, error 8024h
-
- mov [bx+Callback.ds],0 ; set callback free
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; MISC FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310305: ; get state save/restore addresses
- add esp,20h ; adjust stack
-
- xor ax,ax ; size needed is none
- mov bx,_TEXT ; real mode seg of same RETF
- mov cx,off vxr_saverestorerm ; same offset of 16bit RETF
- mov si,cs ; selector of routine is this one
- DB 66h
- mov di,off vxr_saverestorepm ; offset of simple 32bit RETF
- DW 0
- pop gs fs es ds ; restore segment registers
- jmp int31oknopop ; return ok, dont pop registers
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310306: ; get raw mode switch addresses
- add esp,20h ; adjust stack
-
- mov si,cs ; selector of pmtorm rout is this one
- movzx edi,[pmtormswrout] ; offset in this seg of rout
- mov bx,_TEXT ; real mode seg of rmtopm rout
- mov cx,[rmtopmswrout] ; offset of rout in real mode
-
- pop gs fs es ds ; restore segment registers
- jmp int31oknopop ; return ok, dont pop registers
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310400: ; get version
- add esp,20h ; adjust stack
-
- mov ax,90 ; return version 0.90
- mov bx,3 ; capabilities
- mov cl,[processortype] ; processor type
- mov dl,[picslaveold] ; master and slave PIC default
- mov dh,[picmasterold] ; values for this PC
-
- pop gs fs es ds ; restore segment registers
- jmp int31oknopop ; return ok, dont pop registers
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; LOCK MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ; So far all of these functions only clear the carry
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310600: ; Lock Linear Region
- jmp int31ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310601: ; Unlock Linear Region
- jmp int31ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310602: ; Mark Real Mode Region as Pageable
- jmp int31ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310603: ; Relock Real Mode Region
- jmp int31ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310604: ; Get Page Size
- sub bx,bx
- mov cx,4096
- jmp int31oksinoax
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DEMAND PAGING PERFORMANCE TUNING SERVICES
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ; So far all of these functions only clear the carry
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310702: ; Mark Page as Demand Paging Candidate
- jmp int31ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310703: ; Discard Page Contents
- jmp int31ok
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; PMODE/DJ EXTENSIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- IF PMODEDJ_EXT EQ 1
- ;═════════════════════════════════════════════════════════════════════════════
- ; [fold] [
- int310a00: ; PMODE/DJ DPMI extensions
- mov ds,[esp + 32 + 6]
- copy es,SELDS,ax
- do16to32 mov di,<off pmodedj_id>
- mov ecx,PMODEDJ_ID_SIZE
- repe cmps [BYTE PTR ds:esi],[BYTE PTR es:edi]
- dnop
- jnz int31fail8001 ; dont wanna talk to us
- mov [esp + 32 + 4],cs
- do16to32 mov <[WORD PTR esp + Dpmi_regs.edi]>,<off @@api>
- jmp int31ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- @@api: ; extension entry
- stc
- DB 66h
- retf
- ; [fold] ]
- ENDIF
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; COPROCESSOR FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310e00: ; get coprocessor status
- mov al,[processortype]
- mov bl,[oldCR0L]
- cmp al,3 ; is it 386?
- jne short @@ok1
- test bl,10h ; ET bit
- jnz short @@ok1
- mov al,2 ; is 287
- @@ok1: shl al,4
- and bl,6
- shl bl,1
- or al,bl
- or al,[newEM_MP]
- sub ah,ah
- jmp int31okax
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310e01: ; set coprocessor emulation
- mov eax,cr0
- and al,0fbh ; clear bit 3 (EM)
- and bl,3 ; keep EM and MP bits
- mov [newEM_MP],bl
- shl bl,1 ; move to place
- and bl,4 ; clear MP
- or al,bl
- mov cr0,eax
- jmp int31ok
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] (
-
- ; A potential problems are the memory handles. We must tell extended memory
- ; handles from conventional mem ones. Here the MSB bit of the 32 Bit handle
- ; is used. This "restricts" the available base linear addresses below 2GB.
- ;
- ; This is no problem for XMS and raw, since both can handle only up to
- ; 64 MByte due to system restriction. (size in KB as a 16 Bit value)
- ; Though unlikely, VCPI checks if the linear address is below 2 GB.
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500convertbxcx: ; convert bx:cx (on stack) bytes to bx paragraphs
- pop bp
-
- mov bx,[esp + Dpmi_regs.bx]
- shl ebx,16
- mov bx,[esp + Dpmi_regs.cx] ; get # of requested bytes
- add ebx,15 ; align on paragraph
- shr ebx,4 ; convert to paragraphs
-
- test ebx,0FFFF0000h ; more than 1 meg?
- jnz int31fail8013 ; sorry, that's too much
- or bx,bx
- jz int31fail8021 ; can't allocate 0 bytes
-
- jmp bp
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500doserror: ; convert dos error to DPMI error
- cmp ax,8022h ; descriptor invalid?
- jz int31fail8023 ; convert to invalid handle
- cmp ax,8 ; not enough free memory?
- jz int31fail8013 ; yup
- jnz int31fail8016 ; else return this (but correct?)
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310500: ; get free memory information
- call [int31mrouttbl + 0*2]
- mov edi,eax ; save free extended memory
-
- mov ebx,0000FFFFh
- mov ax,100h
- int 31h ; get free dos memory
- cmp ax,8
- jz short @@w1 ; any error other than insufficient memory
- sub bx,bx ; is treated as no mem available
- @@w1: mov eax,ebx
- shl eax,4 ; convert to bytes
-
- cmp eax,edi ; take larger of both
- jnc short @@setbuf
- mov eax,edi ; take extended memory
-
- @@setbuf:
- mov es,[esp+24h] ; get ES:EDI buffer ptr from stack
- mov edi,[esp]
-
- stos [dword ptr es:edi] ; store block size in output buffer
- dnop
- shr eax,12 ; convert from bytes to pages
- stos [dword ptr es:edi] ; store in output buffer max unlock
- stos [dword ptr es:edi] ; store in output buffer max locked
- dnop
- mov ecx,09h ; fill rest of buffer with 0ffffffffh
- mov eax,0ffffffffh
- rep stos [dword ptr es:edi]
- dnop
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310501: ; allocate memory block
- pushfd
- push large cs
- DB 66h
- push off @@cont
- DW 0
- push ds es fs gs
- pushad
- jmp [int31mrouttbl + 1*2] ; try extended memory first
-
- @@cont: jc short @@try_dos ; mem not available, try dos mem
- add esp,8*4
- pop gs fs es ds ; got extended mem, return ok
- jmp int31oknopop
-
- @@try_dos:
- call int310500convertbxcx
-
- mov ax,100h
- int 31h ; attempt to allocate memory
- jc int310500doserror ; convert dos error to DPMI error
-
- mov cx,ax
- mov bx,ax
- shl cx,4 ; make lo-word of linear address
- shr bx,12 ; make hi-word of linear address
-
- mov si,8000h ; hi-word of handle, mark as dos
- mov di,dx ; lo-word of handle = selector
-
- jmp int31oksinoax ; return ok with BX,CX,SI,DI
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] (
- int310502: ; free memory block
- or si,si ; dos memory handle?
- js short @@dos_handle
- jmp [int31mrouttbl + 2*2] ; else extended memory
-
- @@dos_handle:
- mov dx,di ; DX = selector of dos memory
- mov ax,101h ; free dos memory
- int 31h
- jnc int31ok ; no problem, exit
- jmp int31fail8023 ; DPMI specs force this error
- ; [fold] )
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310503: ; resize memory block
- ; We make it simple here - extended memory blocks will stay in extended
- ; memory, and dos memory blocks in dos memory.
- ;
- ; A better approach would be to change dynamically between both memory types.
- ; However, DJGPP will never free any memory before exit, and DOS is a single
- ; task system. So if we have to use dos memory as DPMI memory, we can assume
- ; there is no extended memory available. (Remember: PMODE runs only under
- ; plain DOS, in a DOS shell of a different OS PMODE won't be active!)
- or si,si ; dos memory handle?
- js short @@dos_handle
- jmp [int31mrouttbl + 3*2] ; else extended memory
-
- @@dos_handle:
- call int310500convertbxcx
-
- mov dx,di ; get selector
- mov ax,102h
- int 31h ; attempt to resize memory
- jc int310500doserror
-
- mov bx,di
- mov ax,006h ; get address
- int 31h
- mov bx,cx
- mov cx,dx
- jmp int31oksinoax ; handle won't change
- ; [fold] ]
-
- ; [fold] )
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; VCPI EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500vsiditoesi: ; convert handle SI:DI to ptr ESI
- pop bp ; pop return address
-
- test di,3 ; is handle (ptr) aligned on dword?
- jnz int31fail8023 ; if no, error 8023h
-
- shl esi,16 ; ESI = SI:DI
- mov si,di
-
- cmp esi,[pagetablefree] ; handle too low?
- jb int31fail8023 ; if yes, error 8023h
-
- cmp esi,[pagetabletop] ; handle too high?
- jae int31fail8023 ; if yes, error 8023h
-
- test [byte ptr coreseg:esi+1],2 ; is page first in allocated block?
- jz int31fail8023 ; if no, error 8023h
-
- jmp bp ; return ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500vbxcxtoebx: ; convert BX:CX bytes to EBX pages
- pop bp ; pop return address
-
- shl ebx,16 ; EBX = BX:CX
- mov bx,cx
-
- or ebx,ebx ; check for invalid value
- jz int31fail8021 ; if invalid value, error 8021h
-
- add ebx,0fffh ; convert EBX to page count
- shr ebx,12
-
- jmp bp ; return ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500vpmalloc: ; allocate physical memory block
- mov edi,esi ; EDI = ESI, ptr to linear block start
- xor ebp,ebp ; EBP = running allocated page count
-
- @@int310500vpmallocl0:
- mov ax,0de04h ; VCPI allocate a page
- call [vcpi_service.ptr]
-
- or ah,ah ; got a page?
- jz short @@int310500vpmallocl0f0; if yes, go on
-
- cmp ebp,1 ; allocated any pages?
- jc short @@int310500vpmallocdone; if no, fail immediately
-
- or [byte ptr coreseg:edi-3],4 ; set last allocated page as last
-
- call int310500vfree ; free what was allocated
-
- stc ; carry set, failed
- jmp short @@int310500vpmallocdone ; go to done
-
- @@int310500vpmallocl0f0:
- and dh,0f0h ; clear 4 bits of page table entry
- mov dl,7 ; set page as user/writeable/present
- mov [coreseg:edi],edx ; store page in page table
- add edi,4 ; increment page table ptr
-
- inc ebp ; increment allocated page count
- cmp ebp,ebx ; allocated all needed pages?
- jb @@int310500vpmallocl0 ; if no, loop
-
- or [byte ptr coreseg:esi+1],2 ; set first allocated page as first
- or [byte ptr coreseg:edi-3],4 ; set last allocated page as last
- clc ; carry clear, success
-
- @@int310500vpmallocdone:
- mov eax,ebp ; EAX = number of pages allocated
- ret ; return
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500vlmalloc: ; check for linear memory block
- mov edi,[pagetablefree] ; EDI = search ptr in page table
-
- mov ecx,[pagetabletop] ; ECX = count of pages to search
- sub ecx,edi
- shr ecx,2
-
- xor edx,edx ; EDX = largest linear block found
- xor eax,eax ; EAX = search unit, free entry (0)
-
- push ebx ; preserve EBX, memory requested
-
- @@int310500vlmallocl0:
- jecxz short @@int310500vlmallocdone ; if no more entries, done
-
- repne scas [dword ptr es:edi] ; search for first next free entry
- dnop
- jne short @@int310500vlmallocdone ; if no more free, go on
-
- mov ebp,ecx ; EBP = current count
- lea ebx,[edi-4] ; EBX = start of free block
-
- repe scas [dword ptr es:edi] ; search for end of free linear block
- dnop
- jne short @@int310500vlmallocl0f0 ; if previous entry not free, go on
-
- inc ebp ; previous entry free, extra one
-
- @@int310500vlmallocl0f0:
- sub ebp,ecx ; EBP = number of free pages in block
-
- cmp ebp,edx ; new block larger than last largest?
- jb @@int310500vlmallocl0 ; if no, loop
-
- mov esi,ebx ; ESI = ptr to largest block found
- mov edx,ebp ; size of new largest block found
-
- cmp ebp,[esp] ; block sufficient for memory request?
- jb @@int310500vlmallocl0 ; if no, loop
-
- @@int310500vlmallocdone:
- pop ebx ; restore EBX, memory requested
- ret ; return
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500vmalloc: ; allocate linear+physical mem block
- call int310500vlmalloc ; try to allocate linear memory block
-
- cmp edx,1 ; found ANY free linear area?
- jc short @@int310500vmallocfaillinear ; if no, done
-
- cmp edx,ebx ; linear block enough for request?
- jb short @@int310500vmallocf0 ; if no, go to physical memory check
-
- call int310500vpmalloc ; try to allocate physical mem
-
- mov cl,1 ; error is not enough physical memory
- jmp short @@int310500vmallocdone; go to done
-
- @@int310500vmallocf0:
- mov ebx,edx ; only linear block size physical mem
-
- call int310500vpmalloc ; try to allocate physical memory
- mov cl,1 ; if failed, physical mem
- jc short @@int310500vmallocdone ; if failed, done
-
- call int310500vfree ; success, so must free block
-
- mov eax,ebx ; can allocate this much total memory
- stc ; carry set, failed
-
- @@int310500vmallocfaillinear:
- mov cl,0 ; error is not enough linear memory
-
- @@int310500vmallocdone:
- ret ; return
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500vfree: ; free linear+physical memory block
- mov edi,esi ; EDI = ESI, ptr to linear block start
-
- @@int310500vfreel0:
- xor ecx,ecx ; new page table entry is free (0)
- xchg ecx,[coreseg:edi] ; swap ECX with page table entry
- add edi,4 ; increment page table ptr
-
- mov edx,ecx ; EDX = page table entry
- and dx,0f000h ; mask off low 12 bits
-
- mov ax,0de05h ; VCPI free a page
- call [vcpi_service.ptr]
-
- test ch,4 ; last page of block?
- jz @@int310500vfreel0 ; if no, loop
-
- ret ; return
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310500v: ; VCPI get free memory information (near called)
- push coreseg ; ES = core for VCPI malloc functions
- pop es
-
- mov ebx,0ffffffffh ; try to allocate an impossible amount
- call int310500vmalloc
- shl eax,12 ; returned EAX is highest possible
- ret ; return memory information
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310501v: ; VCPI allocate memory block
- push coreseg ; ES=coreseg for VCPI malloc functions
- pop es
-
- call int310500vbxcxtoebx ; convert BX:CX bytes to EBX pages
-
- call int310500vmalloc ; try to allocate requested amount
- jnc short int310501vaddxnhandle ; if successful, go to done
-
- or cl,cl ; error is not enough linear memory?
- jz int31fail8012 ; if yes, error 8012h
- jmp int31fail8013 ; error is physical, error 8013h
-
- int310501vaddxnhandle:
- or esi,esi
- jns short @@ok
- call int310500vfree ; sorry, need this bit for dos mem
- jmp int31fail8013
-
- @@ok: mov ecx,esi ; figure address of block from handle
- sub ecx,[pagetablebase]
- shl ecx,10
- shld ebx,ecx,16
-
- mov di,si ; SI:DI = ESI, handle
- shr esi,16
-
- mov eax,[vcpi_cr3] ; reload CR3 to clear TLB
- mov cr3,eax
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310502v: ; VCPI free memory block
- call int310500vsiditoesi ; convert handle SI:DI to ptr ESI
-
- call int310500vfree ; free memory block
-
- mov eax,[vcpi_cr3] ; reload CR3 to clear TLB
- mov cr3,eax
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310503v: ; VCPI resize memory block
- push coreseg ; ES=coreseg for VCPI malloc functions
- pop es
-
- call int310500vbxcxtoebx ; convert BX:CX bytes to EBX pages
-
- call int310500vsiditoesi ; convert handle SI:DI to ptr ESI
-
- mov edi,esi ; EDI = ESI, ptr to linear block start
- xor ebp,ebp ; EBP = running block size in pages
-
- @@int310503vl0:
- add edi,4 ; increment page table ptr
- inc ebp ; increment block size
-
- test [byte ptr coreseg:edi-3],4 ; last page of block?
- jz @@int310503vl0 ; if no, loop
-
- sub ebx,ebp ; EBX = change in block size
- jz int310501vaddxnhandle ; if no change, done
-
- jc @@int310503vf0 ; if block made smaller, just free top
-
- mov ecx,[pagetabletop] ; ECX = count of pages to search
- sub ecx,edi
- shr ecx,2
-
- mov edx,ecx ; EDX = current count
- xor eax,eax ; EAX = search unit, free entry (0)
-
- jecxz short @@int310503vf3 ; if no entries above, try below
-
- repe scas [dword ptr es:edi] ; check for free entries above block
- dnop
- je short @@int310503vf2 ; if previous entry free, go on
-
- dec edx ; previous entry not free, minus one
-
- @@int310503vf2:
- sub edx,ecx ; EDX = number of free pages in block
-
- cmp edx,ebx ; enough linear memory?
- jb short @@int310503vf3 ; if no, try below in linear memory
-
- push esi ; preserve start of block
- lea esi,[esi+ebp*4] ; ESI -> start of new block for alloc
-
- call int310500vpmalloc ; try to allocate physical memory
- mov edi,esi ; EDI -> start of new block
- pop esi ; restore start of old block
- jc int31fail8013 ; if alloc failed, error 8013h
-
- and [byte ptr coreseg:edi-3],0fbh ; clear last bit in old block end
- and [byte ptr coreseg:edi+1],0fdh ; clear first bit in new block start
-
- jmp int310501vaddxnhandle ; go to done
-
- @@int310503vf3:
- mov ecx,esi ; ECX = count of pages to search up
- sub ecx,[pagetablefree]
- shr ecx,2
-
- or ecx,ecx ; any linear memory below?
- jz @@int310503vf1 ; if no, try to allocate
-
- push ebp ; preserve size of original block
-
- lea edi,[esi-4] ; EDI = ESI, ptr to linear block start
- mov ebp,ecx ; EBP = current count
-
- std ; search is up
- repe scas [dword ptr es:edi] ; check for free entries after block
- dnop
- cld
- je short @@int310503vf4 ; if previous entry free, go on
-
- dec ebp ; previous entry not free, minus one
-
- @@int310503vf4:
- sub ebp,ecx ; EBP = number of free pages in block
- lea eax,[ebp+edx] ; free size below + free size above
-
- pop ebp ; restore original block size
-
- cmp eax,ebx ; enough linear memory?
- jb @@int310503vf1 ; if no, try to allocate
-
- push esi ; preserve original block address
-
- sub ebx,edx ; EBX = number of pages needed below
- lea eax,[ebx*4] ; get base of block below
- sub esi,eax
-
- push edx ebp ; preserve some vars
- call int310500vpmalloc ; try to allocate physical memory
- pop ebp edx ; restore some vars
-
- mov edi,esi ; EDI -> base of block below
- pop esi ; restore base of original block
- jc int31fail8013 ; if alloc failed, error 8013h
-
- or edx,edx ; any pages needed above?
- jz short @@int310503vf6 ; if no, go on
-
- push esi edi ebp ; preserve some vars
-
- mov ebx,edx ; EBX = size of block below
- lea esi,[esi+ebp*4] ; ESI -> start of block above
-
- call int310500vpmalloc ; try to allocate physical memory
- pop ebp edi esi ; restore some vars
- jnc short @@int310503vf5 ; if allocated ok, go on
-
- mov esi,edi ; ESI -> allocated block below
- call int310500vfree ; free allocated block below
-
- jmp int31fail8013 ; fail, error 8013h
-
- @@int310503vf5:
- and [byte ptr coreseg:esi-3],0fbh ; clear last bit in below block end
- and [byte ptr coreseg:esi+ebp*4+1],0fdh ; clear first bit in above block start
-
- @@int310503vf6:
- and [byte ptr coreseg:edi+1],0fdh ; clear first bit in below block start
- and [byte ptr coreseg:esi+ebp*4-3],0fbh ; clear last bit in old block end
-
- push edi ; preserve new block start
-
- mov edx,edi ; EDX = base of move area
- lea ebx,[esi-4] ; EBX = current location in move area
-
- @@int310503vl1:
- mov edi,ebx ; set up to shift up a page
- mov esi,ebx
- mov ecx,ebp
-
- push ds ; save data selector
- push coreseg
- pop ds ; ds = core selector
- lods [dword ptr ds:esi] ; shift old pages a page down in table
- rep movs [dword ptr es:edi],[dword ptr ds:esi]
- stos [dword ptr es:edi]
- dnop ; 386 bug
- pop ds ; ds now data selector again
-
- sub ebx,4 ; decrement to next page to shift
- cmp ebx,edx ; more pages to shift?
- jae @@int310503vl1 ; if yes, loop
-
- pop esi ; restore new block start address
-
- jmp int310501vaddxnhandle ; go to done
-
- @@int310503vf1:
- add ebx,ebp ; restore EBX as requested size
-
- push esi ebp ; preserve some vars
- call int310500vlmalloc ; check for linear memory block
- pop ebp edi ; restore some vars
-
- cmp edx,ebx ; enough linear memory?
- jb int31fail8012 ; if no, error 8012h
-
- sub ebx,ebp ; EBX = extra pages needed
- push esi ; preserve for later copy
- lea esi,[esi+ebp*4] ; ESI -> start of extra space needed
-
- push edi ebp ; preserve some vars
- call int310500vpmalloc ; try to allocate physical memory
- pop ecx esi edi ; restore some vars
- jc int31fail8013 ; if not enough mem, error 8013h
-
- push edi esi ecx ; preserve, new and old block, size
-
- push ds
- push coreseg
- pop ds
- rep movs [dword ptr es:edi],[dword ptr ds:esi] ; copy old block pages
- dnop ; 386 bug
- pop ds
-
- and [byte ptr coreseg:edi-3],0fbh ; clear last bit in old block end
- and [byte ptr coreseg:edi+1],0fdh ; clear first bit in new block start
-
- pop ecx edi ; restore to clear old block
-
- xor eax,eax ; new page table entry is free (0)
- rep stos [dword ptr es:edi] ; clear old page table block
- dnop ; 386 bug
-
- pop esi ; restore new block address
-
- jmp int310501vaddxnhandle ; go to done
-
- @@int310503vf0:
- sub edi,4 ; decrement page table ptr
-
- xor edx,edx ; new page table entry is free (0)
- xchg edx,[coreseg:edi] ; swap EDX with page table entry
- and dx,0f000h ; mask off low 12 bits
-
- mov ax,0de05h ; VCPI free a page
- call [vcpi_service.ptr]
-
- inc ebx ; increment negative change counter
- jnz @@int310503vf0 ; if more pages to free, loop
-
- or [byte ptr coreseg:edi-3],4 ; set next page up as last of block
-
- jmp int310501vaddxnhandle ; go to done
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310800v: ; VCPI physical address mapping
- push coreseg
- pop es
- shl ebx,16
- mov bx,cx
- cmp ebx,100000h ; below 1st MB?
- jb int31fail8021 ; DPMI says to fail then
-
- mov bx,si
- shl ebx,16
- mov bx,di ; get size
- or ebx,ebx ; size 0?
- jz int31fail8021 ; if invalid value, error 8021h
-
- and ecx,0FFFh ; mask lower 12 bits of phys addr
- add ebx,ecx ; add page offset to size
- jc int31fail8021
- add ebx,4095
- jc int31fail8021
- shr ebx,12 ; get # of pages
-
- push ecx ; save page offset
- call int310500vlmalloc ; allocate linear address space
- pop ebp
- cmp edx,ebx ; linear block enough for request?
- jb int31fail8012 ; if no, fail
-
- ; fill PTEs will correct values
- mov edi,esi ; edi = addr of PTE
- mov ax,[esp + Dpmi_regs.bx]
- shl eax,16
- mov ax,[esp + Dpmi_regs.cx] ; get physical address
- and ah,0f0h ; clear 4 bits of page table entry
- mov al,17h ; user/writeable/present/PCD
- @@loop: mov [coreseg:edi],eax ; set page address
- add eax,4096 ; next page in real memory
- add edi,4 ; next PTE
- dec ebx
- jne short @@loop
-
- or [byte ptr coreseg:esi+1],2 ; set first allocated page as first
- or [byte ptr coreseg:edi-3],4 ; set last allocated page as last
-
- mov ecx,esi ; figure address of block from handle
- sub ecx,[pagetablebase]
- shl ecx,10
- add ecx,ebp ; add page offset
- shld ebx,ecx,16
-
- mov eax,[vcpi_cr3] ; reload CR3 to clear TLB
- mov cr3,eax
-
- mov si,[esp + Dpmi_regs.si]
- mov di,[esp + Dpmi_regs.di]
- jmp int31oksinoax
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310801v: ; VCPI free physical address mapping
- shl ebx,16
- mov bx,cx ; make linear address
- shr ebx,10
- and bl,0FCh
- add ebx,[pagetablebase] ; EBX = start of PTE
-
- @@loop: sub eax,eax
- xchg eax,[coreseg:ebx] ; mark this PTE as free
- add ebx,4
- test ah,4 ; last page?
- jz short @@loop ; if not, loop
-
- jmp int31ok
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; XMS EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] (
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500xcallxms: ; make a call to real mode XMS driver
- pop bp ; pop return address
- sub esp,32h ; stack space for register structure
-
- mov [esp+1ch],ax ; put AX in register structure
- mov [esp+10h],bx ; put BX in register structure
- mov [esp+18h],cx ; put CX in register structure
- mov [esp+14h],dx ; put DX in register structure
-
- mov [word ptr esp+20h],0 ; zero FLAGS in register structure
- mov [dword ptr esp+2eh],0 ; zero SS:SP in register structure
- mov eax,[xms_call.ptr] ; put XMS driver address in CS:IP in
- mov [esp+2ah],eax ; register structure
-
- push ss ; ES:EDI -> register structure
- pop es
- mov edi,esp
-
- xor cx,cx ; copy 0 words as stack parameters
- ; xor bh,bh ; doesnt really need to be here
- mov ax,301h ; call real mode FAR procedure
- int 31h
- jc critical_error ; if INT 31h failed, hang
-
- mov ax,[esp+1ch] ; get AX from register structure
- mov bx,[esp+10h] ; get BX from register structure
- mov cx,[esp+18h] ; get CX from register structure
- mov dx,[esp+14h] ; get DX from register structure
- add esp,32h ; adjust ESP
-
- jmp bp ; return
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500xbxcxtodx: ; convert BX:CX bytes to DX K
- pop bp ; pop return address
-
- mov dx,cx ; check for invalid value, BX=CX=0
- or dx,bx
- jz int31fail8021 ; if invalid value, error 8021h
-
- add cx,1023 ; adjust for size in K and align
- adc bx,0
-
- test bh,0fch ; memory request too high
- jnz int31fail8013 ; if yes, error 8013h
-
- shrd cx,bx,10 ; CX = memory in K
- mov dx,cx
-
- jmp bp ; return ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500xerror: ; XMS error, return with DPMI error
- cmp bl,0a0h ; out of memory?
- je int31fail8013 ; if yes, error 8013h
-
- cmp bl,0a1h ; handles exhausted?
- je int31fail8016 ; if yes, error 8016h
-
- cmp bl,0a2h ; invalid handle?
- je int31fail8023 ; if yes, error 8023h
-
- jmp int31fail8010 ; else, error 8010h
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310500x: ; XMS get free memory information (near called)
- mov ah,8 ; get largest free memory block in K
- call int310500xcallxms
- movzx eax,ax
- shl eax,10 ; EAX = free memory in bytes
- ret ; return memory information
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310501x: ; XMS allocate memory block
- call int310500xbxcxtodx ; convert BX:CX bytes to DX K
- mov cx,dx ; preserve size of block in K
-
- mov ah,9 ; allocate DX K of XMS memory
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if yes, convert XMS error to DPMI
-
- mov si,dx ; get DPMI handle from XMS handle
-
- int310501xgotmem:
- mov ah,0ch ; lock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jnz short @@int310501xf0 ; if no, go on
-
- push bx ; yup, preserve error number
-
- mov ah,0ah ; free block causing lock error
- call int310500xcallxms
-
- pop bx ; restore error number
- jmp int310500xerror ; XMS error, return with DPMI error
-
- @@int310501xf0:
- mov di,si ; lo-word of handle = XMS handle
- sub si,si ; mark handle as non-dos
-
- mov cx,bx ; XMS linear address to DPMI regs
- mov bx,dx
-
- add cx,0fh ; align linear address on paragraph
- adc bx,0
- and cl,0f0h
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310502x: ; XMS free memory block
- mov dx,di ; get XMS handle from DPMI handle
-
- mov ah,0dh ; unlock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if XMS error, return with DPMI error
-
- mov ah,0ah ; free memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if yes, convert XMS error to DPMI
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] (
- int310503x: ; XMS resize memory block
- mov si,di ; xcallxms clobbers di
- call int310500xbxcxtodx ; convert BX:CX bytes to DX K
- mov cx,dx ; preserve size of block in K
- mov dx,si ; get XMS handle from DPMI handle
-
- mov ah,0dh ; unlock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if XMS error, return with DPMI error
-
- mov bx,cx ; BX = new size in K
- mov ah,0fh ; resize memory block
- call int310500xcallxms
- mov dx,si ; get XMS handle again
- or ax,ax ; error in resize?
- jnz int310501xgotmem ; if no, go to memory block code
-
- push bx ; yup, preserve error number
-
- mov ah,0ch ; lock memory block
- call int310500xcallxms
-
- pop bx ; restore error number
- jmp int310500xerror ; XMS error, return with DPMI error
- ; [fold] )
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310800xr: ; physical address mapping (both XMS and raw)
- shl ebx,16
- mov bx,cx
- cmp ebx,100000h ; below 1st MB?
- jb int31fail8021 ; DPMI says to fail then
-
- or si,di
- jz int31fail8021 ; size is zero
- jmp int31ok ; physical and linear address is the same
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310801xr: ; free physical address mapping (both XMS and raw)
- jmp int31ok ; physical and linear address is the same
-
- ; [fold] )
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; RAW EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500rbxcxtoebx: ; convert BX:CX bytes to EBX bytes
- pop bp ; pop return address
-
- shl ebx,16 ; EBX = BX:CX
- mov bx,cx
-
- or ebx,ebx ; check for invalid value
- jz int31fail8021 ; if invalid value, error 8021h
-
- add ebx,0fh ; align EBX on paragraph
- and bl,0f0h
-
- jmp bp ; return ok
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500rfindmcb: ; find MCB for handle SI:DI
- pop bp ; pop return address
-
- shl esi,16 ; ESI = handle SI:DI = address of MCB
- mov si,di
-
- mov edi,[rawextmemtop] ; EDI -> first memory control block
-
- @@int310500rfindmcbl0:
- cmp edi,esi ; found MCB?
- jne short @@int310500rfindmcbl0f0 ; if no, keep looking
-
- cmp [byte ptr coreseg:edi-4],0 ; memory block free?
- je int31fail8023 ; if yes, error 8023h
-
- jmp bp ; return ok, found MCB
-
- @@int310500rfindmcbl0f0:
- mov edi,[coreseg:edi-12] ; EDI -> next memory control block
- or edi,edi ; is there another MCB?
- jnz @@int310500rfindmcbl0 ; if yes, loop
-
- jmp int31fail8023 ; fail, error 8023h
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500radjustused: ; adjust INT 15h extended memory used
- mov eax,[rawextmemtop] ; EAX -> first memory control block
-
- @@int310500radjustusedl0:
- cmp [dword ptr coreseg:eax-12],0 ; last memory control block?
- jz short @@int310500radjustusedf0 ; if yes, go to set new used K
-
- mov eax,[coreseg:eax-12] ; EAX -> next memory control block
- jmp @@int310500radjustusedl0 ; loop
-
- @@int310500radjustusedf0:
- cmp [byte ptr coreseg:eax-4],0 ; memory block free?
- je short @@int310500radjustusedf1 ; if no, go on
-
- sub eax,[coreseg:eax-16] ; used, adjust by size of block
-
- @@int310500radjustusedf1:
- sub eax,10h ; adjust by size of MCB
- and eax,0fffffc00h ; align on K
- sub eax,[rawextmemtop] ; size of extended memory used
- neg eax
- shr eax,10 ; convert from bytes to K
-
- mov [rawextmemused],ax ; adjust INT 15h extended memory used
-
- @@int310500radjustuseddone:
- ret ; return
- ; [fold] ]
-
- ;-----------------------------------------------------------------------------
- ; [fold] [
- int310500rlinkmcb: ; link memory blocks at ESI and EDI
- mov eax,[coreseg:esi-16] ; combine two block sizes
- add eax,10h
- add [coreseg:edi-16],eax ; add size of next block to this one
- mov ecx,[coreseg:esi-12] ; copy next MCB field
- mov [coreseg:edi-12],ecx
- jecxz short @@int310500rlinkmcbf0 ; if no next MCB, done
-
- mov [coreseg:ecx-8],edi ; set prev MCB in next MCB to this MCB
-
- @@int310500rlinkmcbf0:
- ret ; return
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310500r: ; raw get free memory information (near called)
- mov edi,[rawextmemtop] ; EDI -> first memory control block
-
- xor eax,eax ; running highest free memory block
- @@int310500rl0:
- cmp [byte ptr coreseg:edi-4],0 ; is block free?
- jne short @@int310500rl0f0 ; if no, loop
-
- mov ebx,[coreseg:edi-16] ; EBX = size of block
- cmp eax,ebx ; last free block larger?
- ja short @@int310500rl0f0 ; if yes, loop
-
- mov eax,ebx ; found larger block, new largest
-
- @@int310500rl0f0:
- mov edi,[coreseg:edi-12] ; EDI -> next memory control block
- or edi,edi ; is there another MCB?
- jnz @@int310500rl0 ; if yes, loop
-
- ret ; return memory information
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310501r: ; raw allocate memory block
- call int310500rbxcxtoebx ; convert BX:CX bytes to EBX bytes
-
- mov edi,[rawextmemtop] ; EDI -> first memory control block
-
- @@int310501rl0:
- cmp [byte ptr coreseg:edi-4],0 ; is block free?
- je short @@int310501rl0f2 ; if yes, check block
-
- @@int310501rl0f0:
- mov edi,[coreseg:edi-12] ; EDI -> next memory control block
- or edi,edi ; is there another MCB?
- jnz @@int310501rl0 ; if yes, loop
-
- jmp int31fail8013 ; fail, error 8013h
-
- @@int310501rl0f2:
- lea ecx,[coreseg:edi-10h] ; ECX -> possible new MCB
- sub ecx,ebx
-
- mov eax,[coreseg:edi-16] ; EAX = size of block
- sub eax,ebx ; enough free memory in block?
- jc short @@int310501rl0f0 ; if no, loop
-
- jz short @@int310501rl0f1 ; if exactly same size, continue
-
- sub eax,10h ; adjust for size of new created MCB
- mov [coreseg:ecx-16],eax ; put size of new block in new MCB
- mov eax,ecx ; set next MCB in old MCB as new one
- xchg [coreseg:edi-12],eax ; copy next MCB from old to new MCB
- mov [coreseg:ecx-12],eax
- or eax,eax ; is there a next MCB?
- jz short @@int310501rl0f3 ; if no, go on
-
- mov [coreseg:eax-8],ecx ; set prev MCB in next MCB to new MCB
-
- @@int310501rl0f3:
- mov [coreseg:ecx-8],edi ; set prev MCB in new MCB as old one
- mov [byte ptr coreseg:ecx-4],0 ; set new MCB as free
- mov [coreseg:edi-16],ebx ; set size of allocated block
-
- @@int310501rl0f1:
- mov [byte ptr coreseg:edi-4],1 ; set block as allocated
-
- int310501raddxnhandle:
- shld ebx,ecx,16 ; BX:CX = ECX, address of block
- shld esi,edi,16 ; SI:DI = EDI, handle (address of MCB)
-
- call int310500radjustused ; adjust INT 15h extended memory used
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310502r: ; raw free memory block
- call int310500rfindmcb ; find MCB for handle SI:DI
-
- mov [byte ptr coreseg:edi-4],0 ; set this memory block as free
-
- mov esi,[coreseg:edi-12] ; ESI -> next memory control block
- or esi,esi ; is there next MCB?
- jz short @@int310502rf0 ; if no, go on
-
- cmp [byte ptr coreseg:esi-4],0 ; is next memory block free?
- jne short @@int310502rf0 ; if no, go on
-
- call int310500rlinkmcb ; link two memory blocks
-
- @@int310502rf0:
- mov esi,[coreseg:edi-8] ; ESI -> previous memory control block
- or esi,esi ; is there previous MCB?
- jz short @@int310502rf1 ; if no, go on
-
- cmp [byte ptr coreseg:esi-4],0 ; is previous memory block free?
- jne short @@int310502rf1 ; if no, go on
-
- xchg esi,edi ; change mcb order for function
- call int310500rlinkmcb ; link two memory blocks
-
- @@int310502rf1:
- call int310500radjustused ; adjust INT 15h extended memory used
-
- jmp int31ok ; return ok
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310503r: ; raw resize memory block
- call int310500rbxcxtoebx ; convert BX:CX bytes to EBX bytes
- mov edx,ebx ; EDX = size of new block
-
- call int310500rfindmcb ; find MCB for handle SI:DI
-
- copy ds,SELCORE,ax ; for easier block copy
- copy es,ds,ax ; ES = DS for possible block copy
-
- sub ebx,[esi-16] ; EBX = change in block size
- jz @@int310503rf0 ; if no change, done
-
- jc @@int310503rf1 ; if block made smaller, just free top
-
- xor eax,eax ; running memory counter
-
- mov ecx,[esi-12] ; ECX -> next MCB
- jecxz short @@int310503rf4 ; if no next MCB, check previous MCB
-
- cmp [byte ptr ecx-4],0 ; next MCB free?
- jne short @@int310503rf4 ; if not, check previous MCB
-
- mov eax,[ecx-16] ; EAX = amount of free memory in block
- add eax,10h ; including memory control block
-
- @@int310503rf4:
- mov ecx,[esi-8] ; ECX -> previous MCB
- jecxz short @@int310503rf5 ; if no previous MCB, check memory
-
- cmp [byte ptr ecx-4],0 ; previous MCB free?
- jne short @@int310503rf5 ; if not, check memory
-
- add eax,[ecx-16] ; add amount of free memory in block
- add eax,10h ; including memory control block
-
- @@int310503rf5:
- cmp eax,ebx ; enough to resize within area
- jb @@int310503rf3 ; if no, try to allocate
-
- or ecx,ecx ; is there a previous MCB?
- jz @@int310503rf6 ; if no, resize to next
-
- cmp [byte ptr ecx-4],0 ; previous MCB free?
- jne short @@int310503rf6 ; if not, resize to next
-
- mov ebp,[ecx-16] ; EBP = size of previous block, try to
- add ebp,10h ; resize within previous block
-
- sub ebp,ebx ; EBP = prev block size - needed size
- jbe short @@int310503rf7 ; if prev block too small, go on
-
- mov edi,ecx ; EDI -> new MCB for new memory block
- sub edi,ebp ; resize will fit entirely
-
- lea eax,[ebp-10h] ; EAX = new size of free block
- mov [ecx-16],eax ; store mew free size in prev MCB
- mov [edi-16],edx ; store new size in new MCB
- mov [ecx-12],edi ; set next MCB in prev MCB to new MCB
- mov [edi-8],ecx ; set prev MCB in new MCB to prev MCB
- mov [byte ptr edi-4],1 ; set new MCB as used
-
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- or ecx,ecx ; is there a next MCB
- jz @@int310503rf0 ; if no, go to block readjust
-
- mov [ecx-8],edi ; set prev MCB in next MCB to new MCB
-
- jmp @@int310503rf0 ; go to block readjust
-
- @@int310503rf7:
- mov edi,ecx ; EDI -> new MCB for new memory block
-
- lea eax,[edx+ebp] ; EAX = size of new block
- mov [edi-16],eax ; store mew free size in new MCB
- mov [byte ptr edi-4],1 ; set new MCB as used
-
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- jecxz short @@int310503rf8 ; if no next MCB, go on
-
- mov [ecx-8],edi ; set prev MCB in next MCB to new MCB
-
- @@int310503rf8:
- add ebp,ebx ; EBP = size of block just acquired
- sub ebx,ebp ; EBX = new size still needed
- jz @@int310503rf0 ; if no more space needed, done
-
- mov esi,edi ; ESI -> new MCB
-
- @@int310503rf6:
- mov edi,[esi-12] ; EDI -> next MCB
-
- mov ecx,[edi-12] ; copy next MCB field
- mov [esi-12],ecx
- jecxz short @@int310503rf9 ; if no next MCB, go on
-
- mov [ecx-8],esi ; set prev MCB in next MCB to this MCB
-
- @@int310503rf9:
- mov eax,[edi-16] ; EAX = size of next memory block
- add eax,10h
-
- sub edi,eax ; EDI -> start of next memory block
- sub eax,ebx ; EAX = amount of free space left
-
- mov ecx,[esi-16] ; ECX = old size of this memory block
- mov [esi-16],edx ; store new size in this MCB
- mov [byte ptr esi-4],1 ; set this MCB as used
-
- sub esi,ecx ; ESI -> start of this memory block
- sub esi,10h
-
- shr ecx,2 ; copy this memory block down in mem
- rep movs [dword ptr es:edi],[dword ptr ds:esi]
- dnop
-
- add esi,10h ; adjust ESI to top MCB
- mov edi,esi ; EDI -> top MCB
-
- mov ebx,eax ; EBX = negative of space free at top
- neg ebx
- jz @@int310503rf0 ; in no space free, go to done
-
- jmp short @@int310503rf1 ; set new MCBs for moved block
-
- @@int310503rf3:
- mov ebp,edi ; preserve old block MCB address
- sub edx,ebx ; EDX = size of old block
-
- mov bx,[esp+16] ; BX:CX = new block size from stack
- mov cx,[esp+24]
- mov ax,501h ; try to allocate new block
- int 31h
- jc int31failax ; if could not, fail with error AX
-
- shrd eax,esi,16 ; EAX -> new block MCB
- mov ax,di
-
- shrd edi,ebx,16 ; EDI -> start of new block
- mov di,cx
-
- lea esi,[ebp-10h] ; ESI -> start of old block
- sub esi,edx
-
- mov ecx,edx ; copy memory from old block to new
- shr ecx,2
- rep movs [dword ptr es:edi],[dword ptr ds:esi]
- dnop
-
- mov edx,eax ; EDX -> new block MCB
-
- shld esi,ebp,16 ; SI:DI = handle of old block
- mov di,bp
- mov ax,0502h ; free old block
- int 31h
-
- mov edi,edx ; EDI -> new block MCB for done
-
- jmp short @@int310503rf0 ; go to done
-
- @@int310503rf1:
- lea edi,[esi+ebx] ; EDI -> new MCB for new memory block
-
- lea eax,[ebx+10h] ; EAX = size of freed block
- neg eax
- mov [esi-16],eax ; store freed size in old MCB
- mov [edi-16],edx ; store new size in new MCB
-
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- jecxz short @@int310503rf2 ; if no next MCB, go on
-
- mov [ecx-8],edi ; set prev MCB in next MCB to new MCB
-
- @@int310503rf2:
- mov [esi-12],edi ; set next MCB in old MCB as new MCB
- mov [edi-8],esi ; set prev MCB in new MCB as old MCB
- mov [byte ptr edi-4],1 ; set new MCB as used
- mov [byte ptr esi-4],0 ; set old MCB as free
-
- mov ecx,[esi-8] ; ECX -> prev MCB of old MCB
- jecxz short @@int310503rf0 ; if no prev MCB, done
-
- cmp [byte ptr ecx-4],0 ; is previous MCB free?
- jne short @@int310503rf0 ; if no, dont link
-
- push edi ; preserve new MCB
- mov edi,ecx ; top MCB = prev MCB for link function
- call int310500rlinkmcb ; link two memory blocks
- pop edi ; restore new MCB
-
- @@int310503rf0:
- mov ecx,[edi-16] ; ECX = base address of new block
- neg ecx
- lea ecx,[ecx+edi-10h]
-
- push SELDS
- pop ds ; restore old DS
- jmp int310501raddxnhandle ; return address and handle
- ; [fold] ]
-
- ; [fold] ]
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; "NO MEMORY" EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; [fold] [
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310500n: ; no free extended memory present (near called)
- xor eax,eax ; 0 bytes available extended memory
- ret ; return memory information
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- ; [fold] [
- int310501n: ; no allocation of memory
- jmp int31fail8013
- ; [fold] ]
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310502n: ; freeing not possible
- int310503n: ; resizing as well
- jmp int31fail8023
-
- ; [fold] ]
- ENDS
- END
-
- ; [fold] 148
-