source: vendor/emx/current/src/dos/vcpi.asm

Last change on this file was 18, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 20.3 KB
Line 
1;
2; VCPI.ASM -- Virtual Control Program Interface
3;
4; Copyright (c) 1991-1999 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26 INCLUDE EMX.INC
27 INCLUDE TABLES.INC
28 INCLUDE PMINT.INC
29 INCLUDE PAGING.INC
30 INCLUDE SEGMENTS.INC
31 INCLUDE RPRINT.INC
32 INCLUDE MEMORY.INC
33 INCLUDE OPRINT.INC
34 INCLUDE MISC.INC
35
36 PUBLIC VCPI_FLAG, DV_FLAG
37 PUBLIC V2P_LIN, V2P_CR3, V2P_IDTR, V2P_GDTR
38 PUBLIC START_VCPI, INT_BACK_VCPI, INT_VCPI
39 PUBLIC VCPI_ALLOC, VCPI_AVAIL
40 PUBLIC INIT_VCPI, CHECK_VCPI, GET_INT_MAP, SET_INT_MAP
41 PUBLIC CHECK_VM, CLEANUP_VCPI, VCPI_LIN_TO_PHYS
42
43SV_DATA SEGMENT
44
45 TALIGN 2
46V2P_LIN LABEL DWORD
47 DW VCPI_TO_PROT, 0
48
49 TALIGN 2
50VCPI_TO_PROT LABEL DWORD
51V2P_CR3 DD ?
52V2P_GDTR LABEL DWORD
53 DW GDT_PTR, 0
54V2P_IDTR LABEL DWORD
55 DW IDT_PTR, 0
56V2P_LDTR DW G_LDT_SEL
57V2P_TR DW G_TSS_SEL
58V2P_EIP DD ?
59V2P_CS DW G_SV_CODE_SEL
60
61;
62; We have to remember all VCPI pages we've allocated, as we have to
63; deallocate them when terminating. This is done by maintaining a
64; bitmap of pages allocated by calling the VCPI server. The first bit
65; refers to physical address 0. Currently, only one page is used for
66; the bitmap, therefore only 128 MB of memory are supported. This bitmap
67; must be in low memory, as deallocation is done in real mode.
68;
69VCPI_BITMAP_PHYS DD ? ; Points to the bitmap
70VCPI_BITMAP_SEG DW 0 ; Real-mode segment, zero: not alloc.
71
72
73EMM_PAGE DW 0
74EMM_PAGE_FLAG DB FALSE ; EMM_PAGE allocated
75
76VCPI_FLAG DB FALSE
77DV_FLAG DB FALSE
78
79;
80; Names of devices implemented by expanded memory managers
81;
82EMS_FNAME DB "EMMXXXX0", 0 ; EMS enabled
83NOEMS_FNAME1 DB "EMMQXXX0", 0 ; EMS disabled
84NOEMS_FNAME2 DB "$MMXXXX0",0 ; EMS disabled
85
86$NO_VCPI DB "Virtual mode not supported without VCPI", CR, LF, 0
87$DESQVIEW DB "DESQview without expanded memory emulator not supported", CR, LF, 0
88$VA_BUG DB "Page allocated more than once", CR, LF, 0
89$RTP_FAILURE DB "VCPI function 6 error", CR, LF, 0
90
91 DALIGN 4
92
93VCPI_ENTRY LABEL FWORD
94VCPI_OFF DD ?
95 DW G_SERVER_SEL
96
97
98SV_DATA ENDS
99
100
101
102SV_CODE SEGMENT
103
104 ASSUME CS:SV_CODE, DS:NOTHING
105
106;
107; Switch from protected mode to virtual mode
108;
109 ASSUME DS:NOTHING
110 TALIGN 4
111INT_VCPI: MOV AX, G_ZERO_SEL
112 MOV DS, AX
113 ASSUME DS:NOTHING
114 XOR EAX, EAX
115 MOV AX, SV_DATA
116 PUSH EAX ; GS
117 PUSH EAX ; FS
118 PUSH EAX ; DS
119 PUSH EAX ; ES
120 MOV AX, RM_STACK
121 PUSH EAX ; SS
122 LEA AX, RM_TOS
123 PUSH EAX ; ESP
124 XOR EAX, EAX
125 PUSH EAX ; EFLAGS
126 MOV AX, INIT_CODE
127 PUSH EAX ; CS
128 LEA EAX, V2V_CONT
129 PUSH EAX ; EIP
130 XOR EAX, EAX
131 PUSH EAX
132 PUSH EAX
133 MOV AX, G_SV_DATA_SEL
134 MOV ES, AX
135 ASSUME ES:SV_DATA
136 MOV AX, 0DE0CH
137 CLI
138 JMP VCPI_ENTRY
139
140 ASSUME ES:NOTHING
141
142;
143; Allocate one page
144;
145; Out: EAX Physical address (or NULL_PHYS if failed)
146;
147 ASSUME DS:SV_DATA
148VCPI_ALLOC PROC NEAR
149 PUSH ES
150 PUSH EDX
151 PUSH EBX
152 MOV AX, G_PHYS_SEL
153 MOV ES, AX
154VA_RETRY: MOV AX, 0DE04H ; Allocate a 4K page
155 CALL VCPI_ENTRY
156 OR AH, AH ; Failure?
157 JNZ SHORT VA_ERROR ; Yes -> return 0
158 MOV EAX, EDX
159 SHR EAX, 12 ; Physical page number
160 CMP EAX, 4096*8 ; Number of bits exceeded?
161 JAE SHORT VA_RETRY ; Yes -> retry, don't free
162 MOV EBX, VCPI_BITMAP_PHYS
163 BTS DWORD PTR ES:[EBX], EAX ; Test/set bit
164 JC SHORT VA_BUG ; Impossible
165 MOV EAX, EDX
166 JMP SHORT VA_RET
167
168VA_ERROR: MOV EAX, NULL_PHYS ; Yes -> return NULL_PHYS
169VA_RET: POP EBX
170 POP EDX
171 POP ES
172 RET
173
174VA_BUG: LEA EDX, $VA_BUG
175 CALL OTEXT ; Display error message
176 MOV AX, 4CFFH ; Quit
177 INT 21H
178 JMP SHORT $ ; Never reached
179VCPI_ALLOC ENDP
180
181
182;
183; Available VCPI memory
184;
185; Amount of available memory will be added to TAVAIL.
186;
187 ASSUME DS:SV_DATA
188VCPI_AVAIL PROC NEAR
189 PUSH EAX
190 PUSH EDX
191 MOV AX, 0DE03H ; Get number of free 4K pages
192 CALL VCPI_ENTRY
193 OR AH, AH ; Failure?
194 JNZ SHORT VAV_RET ; Yes -> no memory
195 ADD TAVAIL, EDX ; Add to sum
196VAV_RET: POP EDX
197 POP EAX
198 RET
199VCPI_AVAIL ENDP
200
201
202SV_CODE ENDS
203
204
205INIT_CODE SEGMENT
206
207 ASSUME CS:INIT_CODE, DS:NOTHING
208
209;
210; Check presence of VCPI server
211;
212 ASSUME DS:SV_DATA
213CHECK_VCPI PROC NEAR
214 MOV EMM_PAGE_FLAG, FALSE
215;
216; First, check the EMS interrupt vector
217;
218 MOV AX, 3567H ; Get interrupt vector 67H
219 INT 21H
220 MOV AX, ES
221 OR AX, BX ; Is the vector 0:0 ?
222 JZ SHORT CV_END ; Yes -> no VCPI
223;
224; Check for an EMM with EMS enabled
225;
226 LEA DX, EMS_FNAME
227 CALL CHECK_EMM ; EMS present?
228 JC SHORT EMM_DISABLED ; No -> try disabled EMS
229;
230; Check EMM status
231;
232 MOV AH, 40H ; Get EMM status
233 INT 67H
234 CMP AH, 0 ; Successful?
235 JNE SHORT CV_END ; No -> no VCPI
236;
237; Try to allocate a page. Ignore failure
238;
239 MOV BX, 1
240 MOV AH, 43H ; Allocate an EMS page
241 INT 67H
242 CMP AH, 0
243 JNE SHORT EMS_1
244 MOV EMM_PAGE, DX
245 MOV EMM_PAGE_FLAG, NOT FALSE
246EMS_1: JMP SHORT EMM_OK
247
248;
249; Check for an EMM with EMS disabled (using undocumented "features")
250;
251EMM_DISABLED: LEA DX, NOEMS_FNAME1
252 CALL CHECK_EMM
253 JNC SHORT EMM_OK ; EMM present
254 LEA DX, NOEMS_FNAME2
255 CALL CHECK_EMM
256 JC SHORT CV_END ; No EMM present -> no VCPI
257;
258; There is an EMM with EMS enabled or disabled. Check for VCPI
259;
260EMM_OK: MOV AX, 0DE00H ; VCPI presence detection
261 INT 67H
262 CMP AH, 0 ; VCPI present?
263 JNE SHORT CV_END ; No ->
264;
265; VCPI server present. Don't deallocate the page to prevent the VCPI
266; server from switching back to real mode
267;
268 MOV VCPI_FLAG, NOT FALSE
269 JMP SHORT CV_RET
270
271;
272; Dellocate the EMS page if we have allocated one
273;
274CV_END: CMP EMM_PAGE_FLAG, FALSE
275 JE SHORT CV_RET
276 MOV EMM_PAGE_FLAG, FALSE
277 MOV DX, EMM_PAGE
278 MOV AH, 45H
279 INT 67H
280CV_RET: RET
281CHECK_VCPI ENDP
282
283
284;
285; Check for the presence of an expanded memory manager
286;
287; In: DX Pointer to device name
288;
289; Out: NC EMM present
290;
291 EVEN
292CHECK_EMM PROC NEAR
293 MOV AX, 3D00H ; Open
294 INT 21H
295 JC SHORT CE_RET
296;
297; A file or device with that name exists. Check for a device
298;
299 MOV BX, AX ; Handle
300 MOV AX, 4400H ; IOCTL: get device data
301 INT 21H
302 JC SHORT CE_FAIL ; Failure -> no EMM
303 TEST DL, 80H ; Device?
304 JZ SHORT CE_FAIL ; No -> no EMM
305 MOV AX, 4407H ; IOCTL: check output status
306 INT 21H
307 JC SHORT CE_FAIL ; Failure -> no EMM
308 CMP AL, 0FFH ; Ready?
309 JNE SHORT CE_FAIL ; No -> no EMM
310 MOV AH, 3EH ; Close
311 INT 21H
312 CLC
313CE_RET: RET
314
315CE_FAIL: MOV AH, 3EH ; Close
316 INT 21H
317 STC
318 RET
319CHECK_EMM ENDP
320
321
322;
323; Fatal exit for some cases not handled without VCPI (virtual mode, DESQview)
324;
325 EVEN
326CHECK_VM PROC NEAR
327 CMP VCPI_FLAG, FALSE
328 JNE SHORT CVM_RET
329 .386P
330 SMSW AX ; Get machine status word
331 .386
332 TEST AX, 0001H ; Protected (virtual) mode?
333 JZ SHORT NO_VCPI_1 ; No -> continue
334 LEA DX, $NO_VCPI ; We've a problem...
335VCPI_ERROR: CALL RTEXT
336 MOV AL, 0FFH
337 JMP EXIT
338
339;
340; No VCPI: DESQview not supported
341;
342NO_VCPI_1: CMP DV_FLAG, FALSE ; Running under DESQview?
343 JE SHORT CVM_RET ; No -> ok
344 LEA DX, $DESQVIEW ; Not supported
345 JMP SHORT VCPI_ERROR
346
347CVM_RET: RET
348CHECK_VM ENDP
349
350
351
352;
353; Free all pages allocated via VCPI
354;
355CLEANUP_VCPI PROC NEAR
356 CMP VCPI_FLAG, FALSE ; VCPI active?
357 JE SHORT CUV_RET ; No -> nothing to do
358 MOV AX, VCPI_BITMAP_SEG ; Get segment of bitmap
359 OR AX, AX ; Bitmap allocated?
360 JZ SHORT CUV_5 ; No -> nothing to do
361 MOV ES, AX
362 XOR DI, DI ; Bitmap pointer
363 XOR EDX, EDX ; Physical address
364CUV_1: CMP DI, 4096 ; End of bitmap?
365 JAE SHORT CUV_5 ; Yes -> done
366 CMP DWORD PTR ES:[DI], 0 ; Any bits in this DWORD?
367 JNZ SHORT CUV_2 ; Yes -> deallocate pages
368 ADD DI, 4 ; Next DWORD
369 ADD EDX, 32*4096 ; Adjust physical address
370 JMP SHORT CUV_1 ; Repeat
371
372CUV_2: MOV CX, 32 ; Examine 32 bits
373 XOR ESI, ESI
374 XCHG ESI, ES:[DI] ; Fetch DWORD, set to zero
375CUV_3: SHR ESI, 1 ; Bit set?
376 JNC SHORT CUV_4 ; No -> skip
377 MOV AX, 0DE05H ; Free a 4K page
378 INT 67H
379CUV_4: ADD EDX, 4096 ; Adjust physical address
380 LOOP CUV_3 ; Repeat for all 32 bits
381 ADD DI, 4 ; Next DWORD
382 JMP SHORT CUV_1
383
384;
385; Deallocate the EMS page allocated by the VCPI presence check
386;
387CUV_5: CMP EMM_PAGE_FLAG, FALSE
388 JE SHORT CUV_RET
389 MOV EMM_PAGE_FLAG, FALSE
390 MOV DX, EMM_PAGE
391 MOV AH, 45H
392 INT 67H
393CUV_RET: RET
394CLEANUP_VCPI ENDP
395
396
397;
398; VCPI specific initializations, setup page tables, allocate bitmap.
399;
400 ASSUME DS:SV_DATA
401INIT_VCPI PROC NEAR
402 MOV AX, 1
403 CALL RM_ALLOC ; Allocate 0th page table
404 CMP AX, NULL_RM ; Out of memory?
405 JE RM_OUT_OF_MEM ; Yes -> abort
406 MOV PAGE_TAB0_SEG, AX ; Save address
407 MOV ES, AX
408 XOR DI, DI
409 MOV ECX, 1024
410 XOR EAX, EAX
411 CLD
412 REP STOS DWORD PTR ES:[DI]
413 XOR DI, DI ; ES:DI --> 0th page table
414 LEA SI, G_VCPI_DESC ; DS:SI --> GDT entries
415 MOV AX, 0DE01H ; Get protected mode interface
416 INT 67H
417;
418; RM_TO_PHYS works from now onwards.
419;
420 MOV VCPI_OFF, EBX
421 MOV LIN_START, 1 SHL 22 ; 1st page table
422;
423; Put page table 0 into page directory
424;
425 MOV AX, PAGE_TAB0_SEG
426 XOR DX, DX
427 CALL RM_TO_PHYS
428 OR EAX, 7
429 MOV FS, PAGE_DIR_SEG
430 MOV FS:[0], EAX
431;
432; Create linear address space for G_PHYS_SEL
433;
434; The VCPI server initializes parts of page table 0 (0..4M), at least the
435; first 1M. We must not change the page table entries initialized by the VCPI
436; server. But the `Allocate a 4K Page' call of the VCPI server may return a
437; page with a physical address in this range. Now we have a problem: How
438; shall we access those pages, as we cannot use identity mapping?
439; Solution: We remap the entire physical memory for use with G_PHYS_SEL.
440; The part of the 0th page table initialized by the VCPI server will be
441; copied.
442;
443; Important: LIN_START must point to an unused page table (or no
444; swapper info will be created). This is done by making
445; LIN_START point to the beginning of the next page table.
446;
447 MOV AX, 0DE02H ; Get maximum physical address
448 INT 67H
449 ADD EDX, 1000H ; First free physical address
450 ADD EDX, (1 SHL 22)-1 ; Round to next page table
451 AND EDX, NOT ((1 SHL 22)-1)
452 MOV EBP, 0 ; Physical address = 0
453 MOV FS, PAGE_DIR_SEG ; Page directory
454 MOV SI, 4 ; Page table 1
455 MOV EAX, LIN_START ; First free linear address
456 PUSH EAX ; Save for G_PHYS_SEL base
457 ADD LIN_START, EDX ; First free linear address
458 MOV ECX, EDX ; Compute number of pages
459 SHR ECX, 22 ; of physical memory
460 PUSH EDX
461 CALL MAP_PAGES ; Initialize page tables
462IVCPI_1: POP ECX
463 POP EAX ; Base address of G_PHYS_SEL
464 MOV G_PHYS_BASE, EAX
465 LEA DI, G_PHYS_DESC
466 CALL RM_SEG_BASE
467 CALL RM_SEG_SIZE
468;
469; Allocate and zero the VCPI allocation bitmap
470;
471 MOV AX, 1
472 CALL RM_ALLOC ; Allocate bitmap
473 CMP AX, NULL_RM ; Out of memory?
474 JE RM_OUT_OF_MEM ; Yes -> abort
475 MOV VCPI_BITMAP_SEG, AX ; Save segment
476 PUSH AX
477 XOR DX, DX ; Offset = 0
478 CALL RM_TO_PHYS ; Compute physical address
479 MOV VCPI_BITMAP_PHYS, EAX ; Save physical address
480 POP ES ; Restore segment
481 XOR DI, DI ; Zero the bitmap
482 XOR AL, AL
483 MOV CX, 4096
484 CLD
485 REP STOS BYTE PTR ES:[DI]
486 RET
487INIT_VCPI ENDP
488
489
490;
491; Start protected mode
492;
493 ASSUME DS:SV_DATA
494START_VCPI PROC NEAR
495 MOV V2P_EIP, OFFSET PROT1 ; Protected mode entry point
496 MOV ESI, V2P_LIN ; Table of registers
497 MOV AX, 0DE0CH ; Switch to protected mode
498 CLI ; Required by VCPI specs.
499 INT 67H ; Call VCPI server
500 JMP SHORT $ ; Hardly ever reached (note 1)
501;
502; Note 1: INT 67H doesn't work when single-stepping into the interrupt
503; routine due to virtual mode and changed IDTR.
504;
505START_VCPI ENDP
506
507
508;
509; Return from virtual mode to protected-mode interrupt handler
510;
511 ASSUME DS:SV_DATA
512 TALIGN 4
513INT_BACK_VCPI PROC NEAR
514 MOV V2P_EIP, OFFSET V2P_CONT
515 MOV ESI, V2P_LIN
516 MOV AX, 0DE0CH
517 CLI
518 INT 67H
519 JMP SHORT $ ; Hardly ever reached (note 1)
520INT_BACK_VCPI ENDP
521
522
523;
524; Get interrupt vector mappings
525;
526 ASSUME DS:NOTHING
527GET_INT_MAP PROC NEAR
528 MOV AX, 0DE0AH
529 INT 67H ; Get interrupt vector mappings
530 RET
531GET_INT_MAP ENDP
532
533
534;
535; Inform VCPI server about interrupt vector mappings
536;
537 ASSUME DS:NOTHING
538SET_INT_MAP PROC NEAR
539 MOV AX, 0DE0BH
540 INT 67H
541 RET
542SET_INT_MAP ENDP
543
544
545;
546; Convert linear address in first Megabyte to physical address
547;
548; In: EAX Linear address (less than 1M)
549;
550; Out: EAX Physical address
551;
552 ASSUME DS:SV_DATA
553VCPI_LIN_TO_PHYS PROC NEAR
554 PUSH CX ; Save CX
555 PUSH EDX ; Save EDX
556 PUSH EAX ; Save linear address
557 SHR EAX, 12 ; Compute page number
558 MOV CX, AX
559 MOV AX, 0DE06H ; Get physical address of 4K
560 INT 67H ; page in first Megabyte
561 OR AH, AH ; Success?
562 JNZ SHORT RTP_FAILURE ; No -> stop (cannot happen)
563 POP EAX ; Restore linear address
564 AND EAX, 0FFFH ; Keep offset into page
565 ADD EAX, EDX ; Add physical address
566 POP EDX ; Restore EDX
567 POP CX ; Restore CX
568 RET
569
570RTP_FAILURE: LEA DX, $RTP_FAILURE ; Error message
571 CALL RTEXT
572 MOV AL, 0FFH ; Return code = 255
573 JMP EXIT ; Quit
574
575VCPI_LIN_TO_PHYS ENDP
576
577
578INIT_CODE ENDS
579
580 END
Note: See TracBrowser for help on using the repository browser.