summaryrefslogtreecommitdiffstats
path: root/private/mvdm/dpmi/dxrom.asm
blob: 30b8dd89fd4677bd3c0b5ecff6373a4f0ced538d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
	PAGE	,132
	TITLE	DXROM.ASM  -- Dos Extender ROM Specific Code

; Copyright (c) Microsoft Corporation 1990-1991. All Rights Reserved.

;***********************************************************************
;
;	DXROM.ASM      -- Dos Extender ROM Specific Code
;
;-----------------------------------------------------------------------
;
; This module contains code specific to the ROM version of the DOS
; Extender.
;
;-----------------------------------------------------------------------
;
;  11/05/90 jimmat  Created.
;
;***********************************************************************

	.286p

IFDEF	ROM

; -------------------------------------------------------
;           INCLUDE FILE DEFINITIONS
; -------------------------------------------------------

	.xlist
	.sall
include segdefs.inc
include gendefs.inc
include pmdefs.inc
include dxrom.inc
	.list


; -------------------------------------------------------
;           GENERAL SYMBOL DEFINITIONS
; -------------------------------------------------------

; Define some pubilc symbols to be exported for the ROM Image Builder

	public	__selDXCODE,  __selDXDGROUP, __selDXPMCODE

__selDXCODE	=	SEL_DXCODE
__selDXDGROUP	=	SEL_DXDATA
__selDXPMCODE	=	SEL_DXPMCODE

	public	__selFirstLDT, __selLDTAlias

__selFirstLDT	=	SEL_USER
__selLDTAlias	=	SEL_LDT_ALIAS


; -------------------------------------------------------
;           EXTERNAL SYMBOL DEFINITIONS
; -------------------------------------------------------

	extrn	ParaToLinear:NEAR
	extrn	AllocateLDTSelector:NEAR
	extrn	ChildTerminationHandler:NEAR

externFP	NSetSegmentDscr

; -------------------------------------------------------
;           DATA SEGMENT DEFINITIONS
; -------------------------------------------------------

DXDATA	segment

	extrn	selGDTFree:WORD
	extrn	segDXData:WORD
	extrn	ExitCode:BYTE

SaveROMVector	dw	?

cparChildMem	dw	?		; size of child DOS mem block in para's
regOurSSSP	dd	?		; SS:SP save location

DXDATA  ends

; -------------------------------------------------------
;           CODE SEGMENT VARIABLES
; -------------------------------------------------------

DXCODE	segment

; For the ROM version, the following items locate (and size) the
; DGROUP and DXPMCODE segments.  These items are 'imported' from
; the ROM Image Builder which sets the values when the ROM image
; is created.

	extrn	lmaDXDGROUP:DWORD, cparDXDGROUP:ABS, lmaDXPMCODE:DWORD
	public	lmaRomDXPMCode

cparDgroup	dw	cparDXDGROUP
lmaDGroup	dd	lmaDXDGROUP
lmaRomDXPMCode	dd	lmaDXPMCODE

DXCODE	ends


DXPMCODE segment

	extrn	selDgroupPM:WORD

	extrn	lmaROMTOC:DWORD

MyLmaROMTOC	dd	lmaROMTOC

DXPMCODE ends


; -------------------------------------------------------
	subttl	ROM Real Mode ROM Specific Routines
        page
; -------------------------------------------------------
;	    ROM REAL MODE ROM SPECIFIC ROUTINES
; -------------------------------------------------------

DXCODE	segment
	assume	cs:DXCODE

; -------------------------------------------------------
; ROMEntry --  Setup the special ROM environment needed
;	immediately by DOSX.
;
;   Note:   This routine runs in real mode only!
;
;   Input:  ES	  -> PSP for use by DOSX
;   Output: CY clear if successful, set if init failed
;	    DS	  -> DOSX RAM DGROUP
;	    DX:AX =  far return address to app that invoked DOSX
;   Errors: none
;   Uses:   All except ES

	assume	ds:NOTHING,es:NOTHING,ss:NOTHING
	public	ROMEntry

ROMEntry proc	near

; Allocate a data segment in RAM and copy down the ROM version

	mov	ah,48h			;allocate RAM for DGROUP
	mov	bx,cparDgroup
	int	21h
	jc	REAllocFailed		;big trouble if this happens

	push	ax			;save RAM DGROUP

	mov	dx, word ptr lmaDGroup[0]
	mov	bx, word ptr lmaDGroup[2]
	mov	cx, 4
	xor	si, si
@@:
	shr	bx, 1			;determine if its in conventional
	rcr	dx, 1			;memory and if so the canonical
	rcr	si, 1			;segment:offset in dx:si
	loop	@B

	or	bx, bx
	jnz	RECopyFromExtended

RECopyFromConventional:
	push	es			;save es
	mov	es,ax
	mov	ds,dx
	mov	cx,cparDgroup		;		      (CS variable)
	shl	cx,3			;DGROUP size in words
	xor	di,di
	cld
	rep	movsw
	pop	es			;restore es

	pop	ds			;point to RAM dgroup
	assume	ds:DGROUP, es:NOTHING

	clc				;worked!

REAllocFailed:

	ret

RECopyFromExtended:

	sub	sp, 30h
	mov	si, sp
	push	ss
	pop	es
	mov	di, si
	push	ax
	xor	ax,ax
	mov	cx, 18h
	rep	stosw
	dec	ax
	mov	es:[si+10h], ax 	; Limits to FFFF
	mov	es:[si+18h], ax
	mov	al, 93h
	mov	es:[si+15h], al 	; access to data rw
	mov	es:[si+1Dh], al
	pop	ax
	mov	cx, 4
	sub	dx, dx
@@:
	shl	ax, 1			;compute new DGROUP lma
	rcl	dx, 1
	loop	@B
	mov	es:[si+1Ah], ax 	;stuff into dest descr
	mov	es:[si+1Ch], dl
	mov	ax, word ptr lmaDGroup[0]
	mov	dx, word ptr lmaDGroup[2]
	mov	es:[si+12h], ax
	mov	es:[si+14h], dl 	;put ROM lma in source descr
	mov	cx, cparDGroup
	shl	cx, 3			;length of dgroup ***in words ***
	mov	ah, 87h 		;fn 87h = copy extended memory
	int	15h
	jc	REExtCopyFailed
	add	sp, 30h
	pop	ds			;get ram address in ds
	clc
	ret

REExtCopyFailed:
	add	sp, 32h 		;remove stuff from stack
	stc
	ret

ROMEntry endp


; -------------------------------------------------------
; InvokeROMChild  --  ROM specific method of invoking the
;	child application.
;
;   Note:   This routine must be called in real mode!
;	It returns to the caller after the child returns.  Control
;	passes directly to ChildTerminationHandler if child does a
;	DOS exit call.
;
;   Input:  none
;   Output: CY clear if child executed successfully, set if failed
;	    AX = error code if failure (8 = insufficient DOS memory)
;   Errors: none
;   Uses:   All except DS

	assume	ds:DGROUP,es:NOTHING,ss:NOTHING
	public	InvokeROMChild

InvokeROMChild proc	near

; Setup the environment for the ROM child app.	First, allocate
; the largest conventional memory block available and build a PSP
; at the start of it.

	mov	bx,-1			; how big is the largest avail block?
	dossvc	48h

	cmp	bx,64 SHL 6		; is there at least 64k available?
	jae	@f
	mov	ax,8			; DOS insufficient memory error
	jmp	short IRCFail
@@:
	mov	cparChildMem,bx 	; save block size
	dossvc	48h			; allocate block

IF	DEBUG
	jnc	@f			; shouldn't fail, but...
	int	3
@@:
ENDIF

; Got conventional memory, now build a PSP at the start of it.

	mov	dx,ax			; new PSP here
	mov	si,10h			; use this as mem length for now
	dossvc	55h			; duplicate PSP call

; Set up the termination vector in the child's PSP to point to
; the Dos Extender termination code.

	mov	es,dx
	assume	es:PSPSEG

	mov	word ptr [lpfnParent],offset ChildTerminationHandler
	mov	word ptr [lpfnParent+2],cs

; Switch to protected mode to complete initialization of child environment

	SwitchToProtectedMode
	assume	ds:DGROUP,es:DGROUP

	sti

; Allocate/init a selector mapping first 64k of child memory block & PSP

	call	AllocateLDTSelector	; get new selector in AX

					; DX still has PSP segment,
	call	ParaToLinear		;   convert to linear memory address

	push	bx			; save lma for later
	push	dx
	push	ax			; save mem/PSP selector too

	cCall	NSetSegmentDscr,<ax,bx,dx,0,0FFFFh,STD_DATA>

; Allocate/init a zero length selector pointing to just past the end of
; the child's memory block and plug the selector into the PSP.

	call	AllocateLDTSelector	; get another selector

	pop	es
	assume	es:PSPSEG

	mov	segMemEnd,ax		; store in child's PSP

	mov	dx,cparChildMem 	; get size of memory block in bytes
	call	ParaToLinear		;   in BX:DX

	pop	ax			; recover lma of block start
	pop	cx			;   in CX:AX

	add	dx,ax
	adc	bx,cx			; BX:DX = lma of block end

	cCall	NSetSegmentDscr,<segMemEnd,bx,dx,0,0,STD_DATA>

; Allocate/init a selector pointin to our DOS environment block--plug this
; into the child's PSP so it can party on the same env block.

	call	AllocateLDTSelector

	mov	dx,segEnviron		; segment from PSP
	call	ParaToLinear

	cCall	NSetSegmentDscr,<ax,bx,dx,0,7FFFH,STD_DATA>

	mov	segEnviron,ax		; selector to PSP

; The child environment is now build, invoke the child with DS = ES =
; memory/PSP block.  Set the stack 64k (less one word) into the block,
; push our far return address on the stack.

	mov	word ptr [regOurSSSP],sp	;save DOSX stack location
	mov	word ptr [regOurSSSP+2],ss

	mov	ax,es			; switch to child stack
	mov	ss,ax
	mov	sp,0FFFEh

	push	cs			; far return address to us
	push	offset IRCReturn

	call	GetROMTOCPointer	; push the kernel entry CS:IP on stack
	assume	es:ROMTOC

	push	word ptr [KRNL_CSIP+2]
	push	word ptr [KRNL_CSIP]

	mov	ds,ax
	mov	es,ax
	assume	ds:NOTHING,es:NOTHING

	xor	cx, cx			; tell KRNL386 linear == physical
	xor	dx, dx

	retf				; invoke the kernel

	public	IRCReturn		;public for debugging
IRCReturn:

	mov	ds,selDgroupPM			; restore our DS
	assume	ds:DGROUP

	mov	ss,word ptr [regOurSSSP+2]	;   and our stack
	mov	sp,word ptr [regOurSSSP]

	mov	ExitCode,al			; save the child exit code

	SwitchToRealMode
	sti

	clc
	ret

IRCFail:
	stc
	ret

InvokeROMChild endp


; -------------------------------------------------------
; ROMInitialization	-- This routine performs the initial ROM
;	specific DOS Extender initialization.
;
;   Note:   This routine runs in real mode only!
;
;   Input:  none
;   Output: CY clear if successful, set if init failed
;   Errors: none
;   Uses:   AX

	assume	ds:DGROUP,es:NOTHING,ss:NOTHING
	public	ROMInitialization

ROMInitialization	proc	near

; Point 2nd word of DOSX ROM Int vector to the data segment.

	push	es
	xor	ax,ax
	mov	es,ax

	mov	ax, word ptr es:[ROMIntVector*4][2]	;save current vector
	mov	SaveROMVector,ax			;  contents

	mov	word ptr es:[ROMIntVector*4][2],ds	;point vector to data
	pop	es

	clc

ROMInitFailed:

	ret

ROMInitialization	endp


; -------------------------------------------------------
; ROMCleanUp	-- This routine performs the ROM specific
;	DOS Extender termination clean up.
;
;   Note:   This routine runs in real mode only!
;
;   Input:  none
;   Output: none
;   Errors: none
;   Uses:   none

	assume	ds:DGROUP,es:NOTHING,ss:NOTHING
	public	ROMCleanUp

ROMCleanUp	proc	near

; Remove DOSX Int vector pointer to the data segment.

	push	es
	xor	ax,ax
	mov	es,ax

	mov	ax,SaveROMVector			;restore prior contents
	mov	word ptr es:[ROMIntVector*4][2],ax

	pop	es

	ret

ROMCleanUp	endp


; -------------------------------------------------------
	subttl	ROM Real Mode Utility Routines
        page
; -------------------------------------------------------
;	    ROM REAL MODE UTILITY ROUTINES
; -------------------------------------------------------

; GetDXDataRM	-- This routine returns the paragraph address of
;	the DOS Extender data segment.	It should only be called
;	by real mode code.
;
;   Input:  none
;   Output: AX = DOSX data segment paragraph address
;   Errors: none
;   Uses:   none

	assume	ds:NOTHING,es:NOTHING,ss:NOTHING
	public	GetDXDataRM

GetDXDataRM	proc	near

; Get data segment value from 2nd word of DOSX Int vector

	push	ds

	xor	ax,ax
	mov	ds,ax
	mov	ax,word ptr ds:[ROMIntVector*4][2]

IF	DEBUG
	mov	ds,ax
	cmp	ax,ds:[segDXData]	; Make sure ax points to the
	jz	@f			;   right place
	int	3
@@:
ENDIF
	pop	ds
	ret

GetDXDataRM	endp


; -------------------------------------------------------
; SetDXDataRM	-- This routine sets DS equal to the DOS Extender
;	data segment address.  It should only be called by real
;	mode code.
;
;   Input:  none
;   Output: DS -> DOSX data segment
;   Errors: none
;   Uses:   none

	assume	ds:NOTHING,es:NOTHING,ss:NOTHING
	public	SetDXDataRM

SetDXDataRM	proc	near

; Get data segment value from 2nd word of DOSX Int vector

	push	ax

	xor	ax,ax
	mov	ds,ax
	mov	ds,word ptr ds:[ROMIntVector*4][2]

IF	DEBUG
	mov	ax,ds			; Make sure DS points to the
	cmp	ax,ds:[segDXData]	;   right place
	jz	@f
	int	3
@@:
ENDIF
	pop	ax
	ret

SetDXDataRM	endp


DXCODE	ends

;****************************************************************

DXPMCODE SEGMENT
	assume	cs:DXPMCODE

; -------------------------------------------------------
	subttl	ROM Protect Mode Utility Routines
        page
; -------------------------------------------------------
;	    ROM PROTECT MODE UTILITY ROUTINES
; -------------------------------------------------------

; ROMInitLDT	-- This routine initializes the LDT descriptors
;	defined in the ROM prototype LDT.
;
;   Input:  none
;   Output: none
;   Errors: none
;   Uses:   none

	assume	ds:DGROUP,es:NOTHING,ss:NOTHING
	public	ROMInitLDT

ROMInitLDT	proc	near

; Access the ROM Table of Contents to find out where the proto LDT
; is, and how many descriptors it contains.

	pusha
	push	ds
	push	es

	call	GetROMTOCPointer	; Note: uses SEL_SCR0
	assume	es:ROMTOC

	mov	cx,cROMsels		   ; # descriptors defined in proto LDT
	mov	bx,word ptr [lmaROMLDT+2]
	mov	dx,word ptr [lmaROMLDT]       ; bx:dx = lma of proto LDT
	mov	ax,FirstROMSel
	mov	di, ax

; Do a quick (and dirty?) allocation of the correct number of LDT selectors.
; DANGER: this code has intimate knowledge of how the LDT free list is kept!
; We could make CX calls to AllocateLDTSelector, but that is slow and would
; do zillions and zillions of segment loads.
;
	cmp	ax,selGDTFree		; next free descriptor in LDT
	jne	alloc_in_chain

IF	DEBUG
	cmp	ax,__selFirstLDT	; first one free better be the one
	jz	@f			;   the ROM Image Builder used.
	int	3
@@:
ENDIF
	shl	cx,3			; 'allocate' all these by setting
	add	ax,cx			;   the next free to be beyond them
	mov	selGDTFree,ax
	push	SEL_LDT_ALIAS OR STD_RING
	pop	es
	jmp	short sels_alloced

alloc_in_chain:
	mov	si, ax
	sub	si, 8
	push	SEL_LDT_ALIAS OR STD_RING
	pop	es
	shl	cx, 3
	add	ax, cx
	mov	es:[si], ax

sels_alloced:

; Copy the prototype descriptors into the actual LDT

	cCall	NSetSegmentDscr,<SEL_SCR0,bx,dx,0,-1,STD_DATA>

	push	SEL_SCR0 OR STD_TBL_RING
	pop	ds			; ds -> proto LDT descriptors
	assume	ds:NOTHING

	xor	si,si

	shr	cx,1			; # words of descriptors to copy

	cld
	rep movsw			; move'm into the LDT

	pop	es
	pop	ds
	assume	ds:DGROUP,es:NOTHING
	popa

	ret

ROMInitLDT	endp


; -------------------------------------------------------
; GetROMTOCPointer -- return ES:0 pointing to the ROM Table of
;	Contents.
;
;   Note: modifies the SEL_SCR0 descriptor!
;
;   Input:  none
;   Output: ES:0 -> ROM TOC
;   Errors: none
;   Uses:   none

	assume	ds:DGROUP,es:NOTHING,ss:NOTHING
	public	GetROMTOCPointer

GetROMTOCPointer proc	near

	push	bx
	push	dx

	mov	bx,word ptr [MyLmaROMTOC+2]
	mov	dx,word ptr [MyLmaROMTOC]	;bx:dx = lma of ROMTOC

	cCall	NSetSegmentDscr,<SEL_SCR0,bx,dx,0,-1,STD_DATA>

	push	SEL_SCR0 OR STD_TBL_RING
	pop	es

	pop	dx
	pop	bx

	ret

GetROMTOCPointer endp


; -------------------------------------------------------
; GetDXDataPM	-- This routine returns the paragraph address of
;	the DOS Extender data segment.	It should only be called
;	by protected mode code.
;
;   Input:  none
;   Output: AX = DOSX data segment paragraph address
;   Errors: none
;   Uses:   none

	assume	ds:NOTHING,es:NOTHING,ss:NOTHING
	public	GetDXDataPM

GetDXDataPM	proc	near

; Get data segment value from 1st word of DOSX Int vector

	push	ds

	mov	ax,SEL_RMIVT or STD_RING
	mov	ds,ax
	mov	ax,word ptr ds:[ROMIntVector*4][2]

	pop	ds
	ret

GetDXDataPM	endp

if 0	;***************************************************************
; -------------------------------------------------------
; SetDXDataPM	-- This routine sets DS equal to the DOS Extender
;	data segment address.  It should only be called by protected
;	mode code.
;
;   Input:  none
;   Output: DS -> DOSX data segment
;   Errors: none
;   Uses:   none

	assume	ds:NOTHING,es:NOTHING,ss:NOTHING
	public	SetDXDataPM

SetDXDataPM	proc	near

; Set DS = data segment selector.

	push	SEL_DXDATA OR STD_RING
	pop	ds
	ret

SetDXDataPM	endp
endif	;***************************************************************


DXPMCODE ends

;****************************************************************

ifdef ROMSTUB	;--------------------------------------------------------

	*********************************************
	*********************************************
	*****					*****
	*****	 THIS CODE IS NO LONGER USED	*****
	*****					*****
	*********************************************
	*********************************************

DXSTUB	SEGMENT
	assume	cs:DXSTUB

; -------------------------------------------------------
	subttl	Real Mode RAM Stub Segment
        page
; -------------------------------------------------------
;	    REAL MODE RAM STUB SEGMENT
; -------------------------------------------------------

; This segment contains code and data that is moved to conventional
; RAM during initialization.  The code is only executed from RAM
; mode and exists for those few cases where it is most convenient
; to have code segement variables.
;
; Note: Since this code is moved to RAM, be very carefull of the
; instructions it contains.  In particular, realize the the code segment
; value is going to be different from the copy in ROM.

; -------------------------------------------------------
;		CODE SEGMENT VARIABLES
; -------------------------------------------------------

	public	PrevInt2FHandler

PrevInt2FHandler	dd	?

; -------------------------------------------------------
; StubInt2FHook -- This code is used by the DOS Extender real mode
;	Int 2Fh hook to chain the interrupt to the previous Int 2Fh
;	handler.
;
; Note: This code executes in real mode only!
;
;   Input:  stack = [DS] [IP] [CS] [FL]
;   Output: none
;   Errors: none
;   Uses:   none


	assume	ds:NOTHING,es:NOTHING,ss:NOTHING
	public	StubInt2FHook

StubInt2FHook	proc	far

	pop	ds
	jmp	[PrevInt2FHandler]

StubInt2FHook	endp

; -------------------------------------------------------

DXSTUB	ends

endif	;----------------------------------------------------------------

;****************************************************************

ENDIF	;ROM

        end