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
|