summaryrefslogtreecommitdiffstats
path: root/private/mvdm/dpmi/dxvcpi.asm
blob: b9d9a0308fdf1138f35fafae1a233f31b8ef07fc (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
	PAGE	,132
	TITLE	DXVCPI.ASM -- Dos Extender VCPI Support Code

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

;*** dxvcpi.asm - vcpi detection/maintenance/cleanup code (resident)
;
;   Copyright <C> 1990, Microsoft Corporation
;
;   Purpose:
;
;   Revision History:
;
;
;  08-07-90 earleh Allow program to boot without LIM 3.2 page frame.
;  05/07/90 jimmat Started incorporating VCPI changes from languages group.
;
;   []      20-Feb-1990 Dans    Created
;
;************************************************************************/

.286p

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

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

; This entire file is only for VCPI support

if VCPI

.xlist
.sall
include         dxvcpi.inc
.list
;
; miscellaneous equates
;
;
; also in dxmmgr.asm
;
.ERRE CB_MEMHDR EQ 10h          ;size of memory block header
;
; also in dxmmgr.asm
;
;
; data
;

DXDATA  segment

;
; Externs
;

extrn   idCpuType:word
extrn   bpGDT:fword

extrn   cKbInitialHeapSize:word
extrn   cbHeapSize:dword
extrn   dsegCurrent:word
extrn   hmemHeap:word
extrn	lpfnXMSFunc:DWORD

extrn	selGDT:WORD
;
; Definitions, data
;

public	fEms
fEMS            db      0               ; ems present

public  fVCPI
fVCPI           db      0               ; vcpi present

public	iddxsystype
iddxsystype	db	DXINDOS		; type of memory used to hold
					; final dx Pmode data.
public	segBootPmode
segBootPmode	dw	0		; segment of block used to
					; build system tables in real
align	4

public  cFreePages
cFreePages      dd      0               ; free 4k pages, updated on each
					;  allocation.
public	bpdxsyspages
bpdxsyspages	dd	DXPMPAGES-1	dup(0)
;
; pointer (off of SEL_DXPT) where next free page table entry is
;
;       we initialize dxpt1 to have cptdx+2 entries in it (see
;       SetupPageTables in dxvcpibt.asm)
;

;
; Offset in zeroth page table of first page table entry that belongs
; to DX.  Set by initial call to GetVCPIInterface.
;
public	pPteFirst
pPteFirst	dd	0

;
; Offset in block pointed to by SEL_DXPT of where to put next page
; table entry when allocating extended memory by the page.
;
public	pPteNext
pPteNext	dd	0

;
; Maximum number of user page table entries that will fit in our
; original page table buffers.
;
public	cPteMax
cPteMax 	dd	0

EXTRN	hmem_XMS_Table:WORD
EXTRN	hmem_XMS_Count:WORD

public	hmem_System_Block
hmem_System_Block	dw	0

DXDATA  ends


DXPMCODE	segment

IFDEF	ROM
	%OUT VCPI Support not compatible with ROM!  Code segment variables!
	.ERR
ENDIF

;
; Data set up in real mode prior to relocation of DX into vcpi
;       (read only after init time anyway)
;

public  fnVCPIPM, fnVCPIPMoff

fnVCPIPM        label   fword           ; vcpi interface entrypoint
fnVCPIPMoff     dd      0               ; set up in GetVCPIInterface
                dw      SEL_VCPI        ; we know what this is.

externFP NSetSegmentDscr
	extrn   XMScontrol:FAR

pmxmssvc macro   fcn
	ifnb    <fcn>
	mov     ah, fcn
	endif
	call    XMScontrol
endm

DXPMCODE        ends

DXCODE  segment
;
; Data set up in real mode prior to relocation of DX into vcpi
;       (read only after init time anyway)
;

public	WdebVCPI, fnVCPI, fnVCPIoff

;---------	WdebVCPIInfo structure	-----------

public	laVTP, V86ToPm

;
; Begin WDEB386 VCPI notification structure.  The following variables
; are copied by WDEB386 when we send it a VCPI presence notification,
; just after entering protected mode.  The structure of this block of variables
; must not be changed without also changing the format of the data
; structure used by WDEB386.
;
;---------	WdebVCPIInfo structure	-----------
WdebVCPI	LABEL	BYTE

fnVCPI          label   fword           ; vcpi interface entrypoint
fnVCPIoff       dd      0               ; set up in GetVCPIInterface
		dw	SEL_VCPI	; we know what this is.

		dw	SEL_VCPIALLMEM	; for Wdeb386 information

laVTP		dd	0		; linear address of next structure
;
; End WDEB386 VCPI notification structure.
;

; Structure for switching from v86 mode to protect mode via VCPI

	EXTRN	epmVCPI:BYTE

V86ToPm VTP	<,,, SEL_LDT, SEL_TSS, OFFSET epmVCPI, 0, SEL_DXCODE0>

	externFP AddXMStoVCPIHeap

DXCODE  ends


DXCODE  segment

        assume  cs:DXCODE, ds:DXDATA, es:nothing


;*** FreeEMSHandle - free DX system memory
;
;   Purpose:	free the VCPI pages OR XMS block we allocated for system use
;
;   Register
;	Usage:	eax, edx, si, cx
;
;   Input:      none
;
;   Output:	VCPI DOS Extender system pages freed
;		XMS handle deallocated
;
;   Returns:	nothing
;
;   Exceptions: No operation if none of these entities have been
;		allocated yet
;
;   Notes:
;
;************************************************************************/
cProc FreeEMSHandle,<NEAR,PUBLIC,<>
cBegin
	lea	si,bpdxsyspages		; Load VCPI system pages array.
	mov	cx,DXPMPAGES-1		; (First page was in PSP block.)
	cld
.386
FreeVCPI_syspage:
	lodsd				; fetch next page
	or	eax,eax			; page present?
	jz	FreeVCPI_Done		; No, could have been XMS.
	and	ax,0f000h		; Yes, clear lower 12 bits.
	mov	edx,eax
	RMvcpi	vcpiFREEPAGE		; and free it.
	loop	FreeVCPI_syspage	; loop until all freed
.286p
FreeVCPI_Done:
	test	iddxsystype,DXINXMS	; loaded in XMS?
	jz	FreeEMSHandle_ret	; No.
	mov	dx,hmem_System_Block	; Yes, load block
	xmssvc	0dh			; unlock XMS block
	mov	dx,hmem_System_Block
	xmssvc	0ah			; free XMS block
FreeEMSHandle_ret:
cEnd

DXCODE  ends

;**************************************************************
;       386 only code from here on down!!!
;**************************************************************
.386p

include prot386.inc

DXCODE  segment

        assume  cs:DXCODE, ds:DXDATA, es:nothing

DXCODE  ends


DXPMCODE        segment
	assume	cs:DXPMCODE

;**************************************************************
;*** CallVCPIPM
;
; Utility routine to call VCPI server in protected mode.  Masks out
; interrupts during the call because QEMM enables the processor
; interrupt flag when you call it.
;
; Entry: AX = VCPI function code.
; Uses:  Depends upon call.
;
; Note: There is a copy of this routine in dxvcpi.asm and another
;	in dxvcpibt.asm.  This is to allow near calls.	The copy
;	in dxvcpibt.asm is discarded after initialization time.
;
;**************************************************************
cProc	CallVCPIPM,<NEAR>,<si>
cBegin

	push	ax			   ; save function code
;
; Shut out all interrupts.
; QEMM 5.0 enables interrupts during this call.  All our interrupt
; handlers are in the user code ring.  A workaround is to shut off
; hardware interrupts during the call.
;

        in      al,INTA01
	IO_Delay
	mov	si, ax
	mov	al,0FFh
	out	INTA01,al
	IO_Delay

	pop	ax			    ;restore function code
	db	9Ah			    ;call  far SEL_CALLVCPI:0
	dw	0,SEL_CALLVCPI or STD_RING

; Restore the state of the interrupt mask register

	xchg	si, ax
        out     INTA01,al
	IO_Delay
	xchg	si, ax
cEnd

;************************************************************************/
;*** AllocVCPIMem
;
;   Purpose:    to allocate a block of memory from VCPI
;
;   Register
;       Usage:  eax, ebx, edx, ecx, es
;
;   Input:	ECX has number of 4k pages to allocate
;		ES:EDI points to page table entries to fill.
;
;   Output:     pPteNext updated with next free pte
;               cFreePages updated with number of free 4k pages from vcpi
;
;   Returns:    if success, linear ptr in eax
;               if fail, eax 0, ebx has number of 4k pages available.
;
;   Exceptions:
;
;   Notes:      maximum allocation is 65535 4k pages (more than enough)
;               at one time.
;               Also, this is PROTECT MODE ONLY.
;
;************************************************************************/
cProc AllocVCPIMem,<NEAR,PUBLIC>,<bx,dx>
cBegin
	;
        ; Compute the number of entries free in our page table 
        ;
	mov	edx, cPteMax
	cmp     ecx, edx                ; compare request with PTEs
        jb      @F
        ;
        ; our page tables have less room than the vcpi server can allocate,
        ; so adjust our count downward to reflect that
        ;
	mov	ecx, edx
@@:
	cmp     ecx, cFreePages         ; compare request with pages we are
					; allowed to allocate
	jb      @F                      ; request < max.?
	mov     ecx, cFreePages         ; No, clip.
@@:
	jecxz	AVM_exit		; ECX = pages to allocate

AVM_getpage:

	PMvcpi	vcpiALLOCPAGE

	or	ah, ah
	jnz     AVM_exit                ; something happened...not as much
                                        ; as vcpi said was there.
	dec     cPteMax                 ; fix up free PTEs
	dec     cFreePages              ; and free VCPI pages
;
; make it a page table entry, and store into page table
; don't need to worry about the tlb here, since not-present
; pages are not cached in the tlb.
;
	or      dx, NEWPTEMASK
	mov     eax, edx
	stos	dword ptr es:[edi]

	dec	ecx
	jnz	AVM_getpage		; next allocate

AVM_exit:
cEnd

;************************************************************************/
;*** VCPISpace
;
;   Purpose:    Return maximum possible VCPI memory allocation.
;
;   Uses:
;
;   Input:
;
;   Output:
;
;   Return:     EAX = maximum possible VCPI pages we can get.
;
;   Exceptions:
;
;   Notes:
;
;************************************************************************/
cProc VCPISpace,<NEAR,PUBLIC>,<edx>
cBegin

	PMvcpi  vcpiCFREEPAGES          ; EDX = free VCPI pages
	cmp     edx,cFreePages          ; clip to maximum EMS allocation
	jb      VS_00
	mov     edx,cFreePages
VS_00:
	mov	eax,cPteMax	       ; clip to space in page tables
	cmp     edx,eax
	jb      VS_01
	mov     edx,eax
VS_01:
	mov     eax,edx
cEnd

;************************************************************************/
;*** FreeVCPIHeap
;
;   Purpose:    To free the Extended Memory heap memory.
;
;   Register
;       Usage:  eax, ebx, ecx, edx
;
;   Input:
;
;   Output:     All VCPI pages allocated for the heap are freed.
;               All XMS blocks allocated for the heap are freed.
;               Page table entries are set to zero.
;
;
;   Returns:    nothing
;
;   Exceptions: none
;
;   Notes:      Protect mode only
;
;************************************************************************/
cProc	FreeVCPIHeap,<NEAR,PUBLIC>,<es,edi,si,eax,edx>
cBegin

	mov     ax, SEL_DXPT            ; set up es with the selector
	mov     es, ax                  ;  for our page tables
	mov	edi, pPteFirst		; point to first page allocated
	mov	ecx, pPteNext		; point to first unallocated PTE
	sub	ecx, edi
	jbe     Free_XMS_Handles
	shr	ecx, 2			; ECX = pages to free

startloop:
	mov	edx, es:[edi]		; get pte into edx
	and	dx, 0f000h		; mask off 12 lsb's

	PMvcpi	vcpiFREEPAGE		; free the page

	xor	eax, eax
	stos	dword ptr es:[edi]	; clear out PTE
	dec	ecx
	jnz	startloop
@@:
Free_XMS_Handles:
	lea     si, hmem_XMS_Table      ; si points to XMS handle array
	mov	cx,[hmem_XMS_Count]
	jcxz	No_XMS_Handles

Free_XMS_Handles_Loop:
	mov	dx,[si]
	pmxmssvc  0dh                   ; unlock any XMS blocks
	mov     dx,[si]
	pmxmssvc  0ah                   ; free any XMS blocks
	add	si,2			; point to next slot in handle array
	loop    Free_XMS_Handles_Loop   ; loop if more handle slots

No_XMS_Handles:

cEnd

AddXMStoVCPIHeapCall label dword
	dw offset dxcode:AddXMStoVCPIHeap,SEL_DXCODE or STD_RING

;*** AddVCPIHeap
;
;   Purpose:    to replace the himem specific code in AddToXmemHeap
;
;   Register
;       Usage:  all preserved except return values in bx:dx
;
;   Input:      dx:cx is the minimum block length required (bytes).
;
;   Output:     cbHeapSize is updated if a heap is allocated
;
;   Returns:    bx:dx is 32bit linear address of allocated block if success,
;               cy clear, else cy set
;
;   Exceptions:
;
;   Notes:
;
;************************************************************************/
cProc   AddVCPIHeap,<NEAR,PUBLIC>,<eax,ecx>
localD  cbNeeded
cBegin

	push    ebx                     ; save extended registers
	push    edx

	add     cx, CB_MEMHDR * 3       ; add memory manager overhead
	adc     dx, 0
	movzx   ecx,cx
	shl     edx,16d
	or      ecx,edx                 ; ECX = minimum bytes wanted
	mov     cbNeeded,ecx
	add     ecx,CBPAGE386-1
	shr     ecx,12d                 ; ECX = minimum pages wanted
	mov	eax, cPteMax
	cmp     ecx,eax                 ; make sure we have enough
	jna     AVH_00                  ; page table entries
	mov     ecx,eax                 ; ECX = minimum pages wanted
AVH_00:

	mov     cbHeapSize,0

	mov     ax, SEL_DXPT            ; ES -> user page tables
	mov     es, ax
	mov	edi, pPteNext		; Point to first unused PTE
	or	edi, edi		; Initialized?
	jnz     AVH_10                  ; Yes, skip XMS allocate.
	mov	edi, pPteFirst		; No, initialize first unused PTE.
	mov	pPteNext, edi

	cCall	AddXMStoVCPIHeapCall

	mov	pPteFirst,edi		; VCPI allocations start here

AVH_10:
	mov	ebx, pPteNext		; EBX = first PTE
	shl     ebx, 10d                ; EBX = linear address of start of block
	mov     dx, bx
	shr     ebx, 16d                ; DX:BX = linear address of block

	mov	eax, edi
	sub	eax, pPteNext
	shr	eax, 2			; AX = count of pages allocated
	sub	ecx, eax		; Get what we asked for?
	jbe     AVH_Done                ; Yes.

	cCall   AllocVCPIMem            ; allocate it from VCPI
					; cx has number of 4k pages
AVH_Done:
	mov	eax, edi
	sub	eax, pPteNext
	mov	pPteNext, edi
	or	eax, eax
	jz      AVH_BadExit
	shl     eax, 10d                ; EAX = count of bytes allocated
	sub     eax, CB_MEMHDR * 3      ; deduct overhead
	mov     cbHeapSize, eax
	clc
	jmp     AVH_Exit
AVH_BadExit:
	stc
AVH_Exit:
;
; Result is in BX:DX, but we have to save restore the MSW of EBX and
; that of EDX before we return to our caller.
;
	mov     ax,dx
	pop     edx
	mov     dx,ax
	mov     ax,bx
	pop     ebx
	mov     bx,ax
cEnd

DXPMCODE        ends

endif	;VCPI

        end