Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1606 lines
41 KiB

  1. PAGE ,132
  2. TITLE DXVCPIBT.ASM -- Dos Extender VCPI Support Code (initialization)
  3. ; Copyright (c) Microsoft Corporation 1990-1991. All Rights Reserved.
  4. ;*** dxvcpibt.asm - vcpi detection/setup code (discardable)
  5. ;
  6. ; Copyright <C> 1990, Microsoft Corporation
  7. ;
  8. ; Purpose:
  9. ;
  10. ; Revision History:
  11. ;
  12. ;
  13. ; 08-07-90 earleh rearranged memory map to allow building full-sized
  14. ; Pmode data structures in v86 mode, allow booting to Pmode
  15. ; without a LIM 3.2 page frame, fixed up detection code to
  16. ; work with various strange interpretations of LIM 4.0 by
  17. ; Limulator vendors. Allow use of entire linear space below
  18. ; 16 Meg by DOSX and VCPI server.
  19. ;
  20. ; 05/07/90 jimmat Started incorporating VCPI changes from languages group.
  21. ;
  22. ; [] 20-Feb-1990 Dans Created
  23. ;
  24. ;
  25. ; note that this should only be called on a 386, except
  26. ; CheckForVCPI, which can be called from 286 machines.
  27. ;
  28. ; this code is for the real mode portion of the dos extender and
  29. ; is released back to DOS prior to switching to protect mode the
  30. ; first time. NO DATA defined here in either segment as it will
  31. ; be discarded.
  32. ;
  33. ;************************************************************************/
  34. .286p
  35. ; -------------------------------------------------------
  36. ; INCLUDE FILE DEFINITIONS
  37. ; -------------------------------------------------------
  38. .xlist
  39. .sall
  40. include segdefs.inc
  41. include gendefs.inc
  42. include pmdefs.inc
  43. .list
  44. ; This entire file is only for VCPI support
  45. if VCPI
  46. .xlist
  47. .sall
  48. include dxvcpi.inc
  49. .list
  50. ;
  51. ; data
  52. ;
  53. DXDATA segment
  54. ;
  55. ; Externs
  56. ;
  57. extrn idCpuType:word
  58. extrn segBootPmode:word
  59. extrn pPteFirst:dword
  60. extrn cPteMax:dword
  61. extrn bpdxsyspages:dword
  62. extrn iddxsystype:byte
  63. extrn hmem_System_Block:word
  64. extrn fEMS:byte
  65. extrn fVCPI:byte
  66. extrn cFreePages:dword
  67. extrn bpGDT:fword
  68. extrn bpGDTbase:dword
  69. extrn bpGDTcb:word
  70. extrn bpIDT:fword
  71. extrn bpIDTbase:dword
  72. extrn bpIDTcb:word
  73. extrn selGDT:word
  74. extrn segGDT:word
  75. extrn selIDT:word
  76. extrn segIDT:word
  77. extrn cdscGDTMax:word
  78. extrn cdscIDTMax:word
  79. extrn segPSP:word
  80. extrn selPSP:word
  81. extrn selGDTFree:word
  82. extrn sysTSS:WORD
  83. ifdef NOT_NTVDM_NOT
  84. extrn fHPVectra:BYTE
  85. endif
  86. extrn lpfnXMSFunc:DWORD
  87. extrn rgbXfrBuf1:BYTE
  88. DMAServiceSegment equ 040h ;40:7B bit 5 indicates DMA services
  89. DMAServiceByte equ 07Bh ; are currently required
  90. DMAServiceBit equ 020h
  91. extrn bDMAServiceBit:BYTE
  92. if DEBUG
  93. extrn fTraceBug:WORD
  94. ifdef CV_TSS
  95. extrn FaultStack:word
  96. endif
  97. endif
  98. EXTRN hmem_XMS_Table:WORD
  99. EXTRN hmem_XMS_Count:WORD
  100. extrn fDebug:BYTE
  101. DXDATA ends
  102. DXSTACK segment
  103. extrn rgw0Stack:WORD
  104. DXSTACK ends
  105. DXCODE segment
  106. extrn CodeEnd:NEAR
  107. extrn CallVCPI:NEAR
  108. extrn ResetVCPI:NEAR
  109. extrn segDXCode:WORD
  110. DXCODE ends
  111. DXPMCODE segment
  112. ;
  113. ; Externs
  114. ;
  115. extrn fnVCPIPMoff:dword
  116. extrn CodeEndPM:near
  117. extrn PMIntr31:NEAR
  118. extrn PMIntr28:NEAR
  119. extrn PMIntr25:NEAR
  120. extrn PMIntr26:NEAR
  121. extrn PMIntr4B:NEAR
  122. extrn PMIntr70:NEAR
  123. extrn PMIntrDos:NEAR
  124. extrn PMIntrMisc:NEAR
  125. extrn PMIntrVideo:NEAR
  126. extrn PMIntrMouse:NEAR
  127. extrn PMIntrIgnore:NEAR
  128. extrn PMInt2FHandler:NEAR
  129. extrn PMIntrEntryVector:NEAR
  130. extrn PMFaultEntryVector:NEAR
  131. extrn HPxBIOS:NEAR
  132. extrn PMFaultReflectorIRET:FAR
  133. if DEBUG
  134. extrn PMDebugInt:NEAR
  135. endif
  136. externFP NSetSegmentDscr
  137. DXPMCODE ends
  138. DXCODE segment
  139. assume cs:DXCODE, ds:DXDATA, es:nothing
  140. extrn WdebVCPI:BYTE
  141. ;
  142. ; Definitions
  143. ;
  144. rgbEMMDrv db 'EMMXXXX0',0 ; emm device driver name
  145. rbgQEMMDrv db 'EMMQXXX0',0 ; QEMM v. 5.0 with "FRAME=NONE"
  146. DebOut_Int equ 41h ;Wdeb386 pMode interface Interrupt
  147. DS_VCPI_Notify equ 005Bh ;Notify Wdeb386 of VCPI interface
  148. extrn ER_QEMM386:BYTE
  149. ERC_QEMM386 equ offset ER_QEMM386
  150. extrn DisplayErrorMsg:FAR
  151. ;
  152. ; Externs
  153. ;
  154. extrn fnVCPIoff:dword
  155. extrn V86ToPm:word
  156. extrn laVTP:dword
  157. ;extrn FreeEMSHandle:proc
  158. externNP FreeEMSHandle
  159. extrn SetupHimemDriver:proc
  160. ;*** QEMM386Trap
  161. ;
  162. ; Purpose: A device driver or TSR has just failed the Windows INT 2Fh
  163. ; AX = 1605H startup broadcast. Version 5.1 and 5.11 of
  164. ; QEMM386 will do this for any version of DOSX which it
  165. ; doesn't know how to patch to work with VCPI. Since we
  166. ; do know how to work with VCPI now, QEMM386 is behaving in
  167. ; an inappropriate manner. Furthermore, QEMM386 is required
  168. ; to output an informative message if it does this, and it
  169. ; does not.
  170. ;
  171. ; This routine will ask the user for permission
  172. ; to proceed.
  173. ;
  174. ; Uses:
  175. ;
  176. ; Input: A process has told DOSX not to load by returning
  177. ; non-zero in CX on an INT 2Fh, AX=1605h.
  178. ;
  179. ; Output: AX = Zero, proceed.
  180. ; AX = Non-zero, abort.
  181. ;
  182. ;************************************************************************/
  183. cProc QEMM386Trap,<NEAR,PUBLIC>,<ds,es>
  184. cBegin
  185. mov dx,cs ;pass msg ptr in DX:AX
  186. mov ax,ERC_QEMM386
  187. call DisplayErrorMsg ; Tell the user something
  188. mov ah, 8 ; Get a character from the keyboard
  189. int 21h
  190. or al,20h ; Force lower case.
  191. cmp al,'y' ; Party if it's a 'y'.
  192. mov ax,0
  193. jne IQ_Abort
  194. jmp IQ_Exit
  195. IQ_Abort:
  196. dec ax
  197. IQ_Exit:
  198. IQ_Not_Open:
  199. or ax,ax
  200. cEnd
  201. ;*** CheckForEMS
  202. ;
  203. ; Purpose: see if an ems driver is loaded
  204. ;
  205. ; Register
  206. ; Usage: ax, cx
  207. ;
  208. ; Input: ES:BX contains int 67h vector.
  209. ;
  210. ; Output: none
  211. ;
  212. ; Returns: carry not set if ems is loaded, set if not
  213. ;
  214. ; Exceptions: none
  215. ;
  216. ; Notes: This checks for a LIM 4.0 driver. It also checks
  217. ; for a driver named 'EMMQXXX0' which could be QEMM 5.0
  218. ; without a page frame.
  219. ;
  220. ;************************************************************************/
  221. cProc CheckForEMS,<NEAR,PUBLIC>,<di,si,ds>
  222. cBegin
  223. mov di, 0ah ; es:di has string to look at
  224. mov ax, cs
  225. mov ds, ax
  226. assume ds:DXCODE,ss:DGROUP
  227. mov si, offset DXCODE:rgbEMMDrv ; ds:si has driver string
  228. mov cx, CBEMMSTR ; cx has rep count
  229. repe cmpsb
  230. jne short CheckFor_QEMM
  231. ; try QEMM driver with
  232. ; non-standard name for
  233. ; "FRAME=NONE"
  234. emscall GETEMSVER
  235. or ah, ah
  236. jz @F
  237. xor ax, ax
  238. @@:
  239. cmp al, 40h ; LIM 4.0?
  240. jb Failure_Exit ; No, can't use it.
  241. inc fEMS ; set flag
  242. clc ; return success
  243. jmp CheckForEMS_ret
  244. CheckFor_QEMM: ; look for QEMM signature
  245. mov di, 0ah ; es:di has string to look at
  246. mov si, offset DXCODE:rbgQEMMDrv ; ds:si has driver string
  247. mov cx, CBEMMSTR ; cx has rep count
  248. repe cmpsb
  249. jne short Failure_Exit ; if not equal, exit
  250. inc fEMS ; set flag
  251. clc
  252. jmp CheckForEMS_ret
  253. Failure_Exit:
  254. stc ; zero out return value first
  255. CheckForEMS_ret:
  256. cEnd
  257. assume ds:DGROUP
  258. ;*** CheckForVCPI
  259. ;
  260. ; Purpose: to see if a vcpi server is loaded
  261. ;
  262. ; Register
  263. ; Usage: ax, bx, cx
  264. ;
  265. ; Input: none
  266. ;
  267. ; Output: none
  268. ;
  269. ; Returns: ax = vcpi version if it is loaded, 0 otherwise
  270. ;
  271. ; Exceptions: none
  272. ;
  273. ; Notes: this calls CheckForEMS first, and EMSVer as well
  274. ;
  275. ;************************************************************************/
  276. cProc CheckForVCPI,<NEAR,PUBLIC>,<es>
  277. cBegin
  278. cmp idCpuType, 3 ; must be 386 or better to have
  279. jnb @F
  280. jmp novcpi286 ; vcpi server running.
  281. @@:
  282. .386
  283. mov ax, 03500h+EMS_INT ; ah = get interrupt, al = vector to get
  284. int 021h ; returns with es:bx == int vector
  285. mov ax,es ; int vector set?
  286. or ax,bx
  287. jz novcpi ; No.
  288. call CheckForEMS
  289. jc novcpi ; no ems, can't be any vcpi
  290. call SwitchToV86 ; force v86 mode
  291. or al, al
  292. jz novcpi ; failed to allocate, out of here
  293. RMvcpi vcpiVER ; see if vcpi is available
  294. or ah, ah
  295. jnz novcpi
  296. inc fVCPI ; set flag
  297. jc novcpi
  298. movzx eax,segBootPmode
  299. shl eax,4
  300. add eax,GDTOFF
  301. shr eax,4
  302. mov selGDT,ax ; save it for later
  303. mov segGDT,ax ; save it for later
  304. ; If this is changed, then GetVCPIInterface must be changed
  305. ; to save correct value in pPteFirst.
  306. .ERRE VCPIPTOFF EQ 0
  307. cCall GetVCPIInterface,<segBootPmode,VCPIPTOFF,ax,SEL_VCPI>
  308. call SetupPageTables ;
  309. jc novcpi ; had a problem setting up page table
  310. ;
  311. ; Load the VDS-implemented bit from the BIOS data area.
  312. ;
  313. mov ax,DMAServiceSegment
  314. mov es,ax
  315. mov al,byte ptr es:[DMAServiceByte]
  316. and al,DMAServiceBit
  317. mov [bDMAServiceBit],al
  318. RMvcpi vcpiVER ; refetch VCPI version
  319. mov ax,bx ; put it in AX
  320. jmp CheckForVCPI_exit ; return no error
  321. .286p
  322. novcpi:
  323. call FreeEMSHandle ; free the handle we allocated.
  324. novcpi286: ; (Free routine uses 386 instructions.)
  325. xor ax, ax ; none loaded
  326. CheckForVCPI_exit:
  327. cEnd
  328. DXCODE ends
  329. ;**************************************************************
  330. ; 386 only code from here on down!!!
  331. ;**************************************************************
  332. .386p
  333. include prot386.inc
  334. DXCODE segment
  335. assume cs:DXCODE, ds:DXDATA, es:nothing
  336. ;*** SwitchToV86
  337. ;
  338. ; Purpose: Switch to v86 mode in preparation for vcpi calls
  339. ;
  340. ; Register
  341. ; Usage: eax, bx, ecx, es
  342. ;
  343. ; Input: none
  344. ;
  345. ; Output: hEMM is updated, pages are mapped into ems frame
  346. ; segBootPmode setup
  347. ;
  348. ; Returns: al == 1 if successful, al == 0 otherwise
  349. ;
  350. ; Exceptions: none
  351. ;
  352. ; Notes: By allocating an ems handle/page, we force the lim 4.0
  353. ; emulator to switch from real mode to v86 mode. Do not free
  354. ; the ems memory until exit time.
  355. ;
  356. ;************************************************************************/
  357. cProc SwitchToV86,<NEAR,PUBLIC>,<es,si,edi,cx>
  358. cBegin
  359. ;
  360. smsw ax
  361. test al,01h ; In V86 mode?
  362. jz stv_badexit ; We don't know how to turn on
  363. ; a VCPI server without allocating
  364. ; EMS memory.
  365. mov cx,(offset CodeEnd) + CBPAGE386 - 1
  366. shr cx,4
  367. mov ax,segDXCode
  368. add ax,cx
  369. and ax,0FF00H ; page align DOS block
  370. mov segBootPmode,ax
  371. mov es,ax ; zero it out
  372. mov al,1
  373. jmp stvExit
  374. stv_badexit:
  375. call FreeEMSHandle
  376. xor al, al
  377. stvExit:
  378. cEnd
  379. ;*** GetVCPIInterface
  380. ;
  381. ; Purpose: To retrieve the vcpi protect mode interface data
  382. ;
  383. ; Register
  384. ; Usage: es, ax, edx, ebx
  385. ;
  386. ; Input: lpPT: far ptr to a page table
  387. ; lprggdte: far ptr to a range of 3 gdt entries.
  388. ;
  389. ; Output: fnVCPIoff updated with 32-bit offset of pm entry point
  390. ; for vcpi calls
  391. ; *lpPT updated with 4k vcpi 0th page table
  392. ; *lprggdte updated with vcpi server code segment, extras
  393. ;
  394. ;
  395. ; Returns: nothing
  396. ;
  397. ; Exceptions:
  398. ;
  399. ; Notes: only call in real mode prior to relocation of DosExtender,
  400. ; as it sets up a variable in DXPMCODE that needs to be
  401. ; copied up when relocated.
  402. ;
  403. ;************************************************************************/
  404. cProc GetVCPIInterface,<NEAR,PUBLIC>,<es>
  405. parmD lpPT
  406. parmD lprggdte
  407. cBegin
  408. push ds ; save ds
  409. les di, lpPT ; es:di -> vcpi's page table
  410. lds si, lprggdte ; ds:si -> vcpi's gdt entries
  411. assume ds:nothing
  412. RMvcpi vcpiPMINTERFACE
  413. mov word ptr pPteFirst,di
  414. mov ax, CBPAGE386 ; AX = size of page table
  415. sub ax, di ; AX = #bytes left over in zeroth PT
  416. shr ax, 2 ; AX = #PTEs left over
  417. add ax, DXPTMAX shr 2 ; AX = total # user PTEs available,
  418. mov word ptr cPteMax, ax ; counting those in zeroth PT
  419. pop ds ; restore ds
  420. assume ds:DXDATA
  421. mov fnVCPIoff, ebx
  422. mov ax, seg DXPMCODE
  423. mov es, ax
  424. assume es:DXPMCODE
  425. mov fnVCPIPMoff, ebx ; set pm call
  426. ;
  427. ; Refer to VCPI spec. Version 1.0 for why this call sequence is used to
  428. ; find the number of VCPI pages we may allocate.
  429. ;
  430. emscall GETNUMOFPAGES
  431. movzx ebx,bx ; BX = unallocated EMS pages
  432. shl ebx, 2 ; EBX = unallocated VCPI pages
  433. mov cFreePages, ebx ; Never allocate more than this amt.
  434. cEnd
  435. assume es:nothing
  436. ;*****************************************************************************
  437. ; Memory map of system tables buffer prior to switch to protected
  438. ; mode under vcpi.
  439. ;
  440. ; __+-------------------------------+->USERPTOFF
  441. ; __+-------------------------------+->LDTTOP
  442. ; ~100k | |
  443. ; | |
  444. ; | LDT, 64k (8190 entries) |
  445. ; | |
  446. ; | |
  447. ; |_______________________________|->
  448. ; | |
  449. ; | |
  450. ; | |
  451. ; | DXPMCODE (~18.5k) |
  452. ; | Exact size may be found from |
  453. ; | codeendPM symbol. |
  454. ; | |
  455. ; __|_______________________________|
  456. ; | |->DXPMCODEOFF (GDTTOP)
  457. ; | GDT |
  458. ; __|_______________________________|
  459. ; | |->GDTOFF
  460. ; | TSS space (2 of them for 386) |
  461. ; 18k __|_______________________________|
  462. ; | IDT, 2k |->TSSOFF
  463. ; 16k __|_______________________________|
  464. ; | |->IDTOFF
  465. ; | |
  466. ; | page directory (DXPD) |
  467. ; 12k __|_______________________________|
  468. ; | |->DXPDOFF
  469. ; | DOSX Pmode page table (DXPT2) |
  470. ; | (DXLINEARBASE) |
  471. ; 8k __|_______________________________|
  472. ; | |->DXPTSYSOFF
  473. ; | 1st user page table (DXPT1) |
  474. ; | (4-8 Meg) |
  475. ; 4k __|_______________________________|
  476. ; | |->DXPT1OFF = DXTEMPPTOFF
  477. ; | 0th page table (VCPIPT) |
  478. ; | (0-4 Meg) |
  479. ; 0k __|_______________________________|->VCPIPTOFF
  480. ; | Wasted for page alignment |
  481. ; CodeEnd --->|-------------------------------|
  482. ; Label
  483. ;
  484. ; System data structures and DOSX Pmode code will be located at linear
  485. ; addresses pointed to by the page table which begins at DXPTSYSOFF.
  486. ; During the first switch to Pmode, these addresses will exist in a
  487. ; block of conventional memory allocated from DOS. After the first
  488. ; switch, a block of extended memory allocated from VCPI will be used.
  489. ; The user page table starting at DXTEMPPTOFF will be used to access the
  490. ; second block of memory for initialization purposes.
  491. ;
  492. ; Note that the first page, which contains the zeroth page table, shared
  493. ; with the VCPI server, must use the same physical page of memory before
  494. ; and after the switch.
  495. ;
  496. ; Terms:
  497. ; DXPMCODE Dos eXtender Protect Mode CODE
  498. ; IDT Interrupt Descriptor Table
  499. ; GDT Global Descriptor Table
  500. ; DXPTx Dos eXtender Page Table number x
  501. ; VCPIPT VCPI Pate Table (we can't touch this one)
  502. ; DXPD Dos eXtender Page Directory
  503. ;
  504. ;*****************************************************************************
  505. ;*** SetupPageTables
  506. ;
  507. ; Purpose: To set up page tables and directory in ems
  508. ; frame (as described above)
  509. ;
  510. ; Register
  511. ; Usage: eax, bx, cx, edx, esi, edi
  512. ;
  513. ; Input: none
  514. ;
  515. ; Output: DXPD, DXPTx, GDT setup.
  516. ;
  517. ; Returns: cy set if error
  518. ;
  519. ; Exceptions:
  520. ;
  521. ; Notes:
  522. ;
  523. ;************************************************************************/
  524. cProc SetupPageTables,<NEAR,PUBLIC>,<ds,es>
  525. cBegin
  526. mov cdscGDTMax,8190 ; max out the GDT size
  527. mov bx, segBootPmode
  528. mov es, bx
  529. mov di,DXBOOTPTOFF
  530. shr bx, 8 ; convert to 16-bit page aligned
  531. ;
  532. ; Our extended memory stuff is located in a single contiguous
  533. ; block of DOS memory.
  534. ;
  535. mov ecx, DXPMPAGES
  536. physaddrloop:
  537. xchg cx, bx ; put page number in cx, save count
  538. ; in bx
  539. RMvcpi vcpiPHYSADDRPAGE ; get the physical address
  540. or ah, ah
  541. jnz badexit
  542. and dx, 0f000h ; mask off 12 lsb's
  543. or dx, NEWPTEMASK ; store with decent page flags
  544. mov es:[ di ], edx ; store physical in DXPT1
  545. add di, 4 ; advance to next
  546. xchg cx, bx ; get loop counter in cx,
  547. inc bx ; advance to next page in ems frame
  548. loop physaddrloop
  549. pagesmapped:
  550. ;
  551. ; Save away the page directory base for cr3 loading
  552. ;
  553. mov eax, es:[DXBOOTPTOFF + (DXPDOFF shr 10)]
  554. ; Save the pte (physical addr) of
  555. and ax, 0f000h ; page directory, mask 12 lsb's
  556. mov V86ToPm.zaCr3VTP, eax ; store it
  557. ;
  558. ; Save the linear address of bpGDT and bpIDT in V86ToPm as well
  559. ;
  560. xor eax, eax
  561. mov ax, DXDATA ; dgroup segment, masked hi word
  562. shl eax, 4 ; linearize it
  563. mov ebx, eax ; save it
  564. add eax, offset DGROUP:bpGDT; add in offset
  565. mov V86ToPm.laGdtrVTP, eax ; save it in vcpi v86 to pm structure
  566. mov eax, ebx ; restore linear dgroup
  567. add eax, offset DGROUP:bpIDT; add in offset
  568. mov V86ToPm.laIdtrVTP, eax ; save it in vcpi v86 to pm structure
  569. xor eax, eax
  570. mov ax, cs ; get current code segment
  571. shl eax, 4 ; linear dxcode
  572. add eax, offset DXCODE:V86ToPm ; add in offset of v86 to pm structure
  573. mov laVTP, eax ; save linear ptr of v86 to pm structure
  574. ;
  575. ; set up the page directory (DXPD)
  576. ; with 0-x to be VCPIPT thru DXPTx (x+1 total)
  577. ;
  578. ; (copy them out of dxpt1, starting with the 2nd entry)
  579. ;
  580. mov edi, DXPDOFF
  581. push ds
  582. push es ; make ds point to emspageframe
  583. pop ds ; as well
  584. assume ds:nothing
  585. mov esi, DXBOOTPTOFF + (VCPIPTOFF shr 10) ; point to 2nd entry in DXPT1
  586. ; (must be VCPIPT)
  587. mov ecx, CPTDX + 1 ; # of user pt's + vcpi's pt
  588. rep movsd
  589. ; point DXLINEARBASE at system area
  590. mov esi,DXBOOTPTOFF + (DXBOOTPTOFF shr 10)
  591. mov edi,DXPDOFF + (DXLINEARBASE shr 20)
  592. movsd
  593. pop es
  594. assume es:DGROUP
  595. ;
  596. ; Allocate a block of VCPI 4k pages, enough to copy our system tables
  597. ; and Pmode code into once we have achieved protected mode operation.
  598. ; Map these pages into one of the page tables that is unused until
  599. ; heap initialization time.
  600. ;
  601. ; If there is insufficient VCPI memory to complete this operation, then
  602. ; we try to grab XMS memory instead.
  603. ;
  604. lea di,bpdxsyspages
  605. cmp cFreePages, DXPMPAGES-1
  606. jc tryXMSServer ; insufficient VCPI pages to
  607. ; build this block
  608. mov cx,DXPMPAGES-1
  609. allocate_syspage_from_VCPI:
  610. RMvcpi vcpiALLOCPAGE
  611. or ah,ah
  612. jnz badexit
  613. mov eax,edx
  614. stosd
  615. loop allocate_syspage_from_VCPI
  616. sub cFreePages, DXPMPAGES-1
  617. mov iddxsystype,DXINVCPI
  618. ;
  619. ; Map these pages into a temporary area, which we use later to move most
  620. ; of the stuff in this DOS block up into extended memory.
  621. ;
  622. push es
  623. pop ds
  624. assume es:nothing,ds:DGROUP
  625. mov ax, segBootPmode
  626. mov es, ax
  627. lea si,bpdxsyspages
  628. mov cx,DXPMPAGES-1
  629. mov di,DXTEMPPTOFF
  630. mov eax,es:[DXBOOTPTOFF + (VCPIPTOFF shr 10)]
  631. stosd
  632. copy_syspage:
  633. lodsd
  634. or eax,NEWPTEMASK
  635. stosd
  636. loop copy_syspage
  637. jmp goodexit
  638. tryXMSServer:
  639. assume es:nothing,ds:DGROUP
  640. push es
  641. pop ds
  642. call SetupHimemDriver ; Need XMS driver now.
  643. mov dx,DXPMPAGES shl 2 ; kbytes = pages times 4
  644. xmssvc 09h ; allocate an XMS block
  645. cmp ax,1 ; got a block?
  646. jne goodexit ; no, try using DOS mem.
  647. mov hmem_System_Block,dx
  648. xmssvc 0ch ; lock the block
  649. cmp ax,1 ; did it work?
  650. je @F
  651. mov dx,hmem_System_Block ; No, free it up.
  652. mov hmem_System_Block,0
  653. xmssvc 0ah
  654. jmp goodexit ; and try to run in DOS mem
  655. @@:
  656. shl edx,10h ; DX:BX = locked block address
  657. mov dx,bx ; EDX = locked block address
  658. ;
  659. ; Make sure the locked XMS block is page aligned. If is not, then we
  660. ; will have to adjust the bottom address used and shrink the GDT by a
  661. ; full 386 page.
  662. ;
  663. test dx,MASK allbitsPTE
  664. jz XMSpagealigned
  665. and dx,MASK pfaPTE
  666. sub cdscGDTMax,CBPAGE386 / 8 ; shrink the GDT size
  667. XMSpagealigned:
  668. mov ax, segBootPmode
  669. mov es, ax
  670. mov di,DXTEMPPTOFF
  671. mov eax,es:[DXBOOTPTOFF + (VCPIPTOFF shr 10)]
  672. stosd
  673. mov cx,DXPMPAGES-1
  674. mov eax,edx
  675. or eax,NEWPTEMASK
  676. insertXMSpage:
  677. stosd
  678. add eax,CBPAGE386
  679. loop insertXMSpage
  680. mov iddxsystype,DXINXMS
  681. goodexit:
  682. clc
  683. jmp exit
  684. badexit:
  685. stc
  686. exit:
  687. cEnd
  688. assume ds:DXDATA
  689. ;*** InitGDTVCPI - initialize the gdt when running under vcpi
  690. ;
  691. ; Purpose:
  692. ;
  693. ; Register
  694. ; Usage: uses eax, all others preserved
  695. ;
  696. ; Input: none
  697. ;
  698. ; Output: gdt/ldt is initialized
  699. ;
  700. ; Returns: returns carry set if failure to map EMS pages
  701. ;
  702. ; Exceptions:
  703. ;
  704. ; Notes:
  705. ;
  706. ;************************************************************************/
  707. assume ds:DGROUP,es:DGROUP,ss:NOTHING
  708. public InitGDTVCPI
  709. cProc InitGDTVCPI,<NEAR,PUBLIC>,<ebx,ecx,edx,di,es>
  710. cBegin
  711. mov edx,LADXGDTBASE ; set gdt linear address
  712. mov bpGDTbase,edx
  713. mov ecx,GDT_SIZE - 1 ; set the GDT segment size
  714. mov bpGDTcb,cx
  715. mov bh, STD_DATA ; make it be a data segment
  716. mov ax, SEL_GDT
  717. cCall NSetSegmentDscr,<SEL_GDT,edx,ecx,STD_DATA>
  718. ; Set up a descriptor for the LDT and an LDT data alias.
  719. mov edx,LADXLDTBASE
  720. movzx ecx,cdscGDTMax
  721. shl ecx,3
  722. dec ecx
  723. cCall NSetSegmentDscr,<SEL_LDT,edx,ecx,STD_LDT>
  724. ;
  725. ; Set up the descriptors for the page directory and page tables
  726. ;
  727. mov eax,LADXPDBASE
  728. cCall NSetSegmentDscr,<SEL_DXPD,eax,0,CBPAGE386LIM,STD_DATA>
  729. mov edx, LADXPTBASE ; EDX = user page tables linear base
  730. mov ecx, ( (CPTDX + 1) shl 12 ) - 1
  731. ; # of user PTE's + vcpi's PTE's minus one
  732. cCall NSetSegmentDscr,<SEL_DXPT,edx,ecx,STD_DATA>
  733. ; Setup a selector and data alias for the TSS
  734. mov edx,LADXTSS1BASE ;get base address of TSS
  735. mov ecx,(TYPE TSS386) - 1
  736. cCall NSetSegmentDscr,<SEL_TSS,edx,ecx,STD_TSS386>
  737. mov eax,DXLINEARBASE
  738. xor ecx,ecx
  739. dec cx
  740. cCall NSetSegmentDscr,<SEL_LDT_ALIAS,eax,ecx,STD_DATA>
  741. mov eax,DX_TEMP_LINEARBASE
  742. cCall NSetSegmentDscr,<SEL_TSS_ALIAS,eax,ecx,STD_DATA>
  743. ; Set up a descriptor for our protected mode code.
  744. mov dx,cs
  745. movzx edx,dx ;our code segment paragraph address
  746. shl edx,4 ;convert to linear byte address
  747. cCall NSetSegmentDscr,<SEL_DXCODE,edx,0,0ffffh,STD_CODE>
  748. ; Set up another one, but ring 0 this time.
  749. cCall NSetSegmentDscr,<SEL_DXCODE0,edx,0,0ffffh,ARB_CODE0>
  750. mov edx,LADXPMCODEBASE ; EDX = LADXPMCODEBASE
  751. mov ecx, offset DXPMCODE:CodeEndPM + 10h
  752. cCall NSetSegmentDscr,<SEL_DXPMCODE,edx,ecx,STD_CODE>
  753. ;
  754. ; Set up the Ring 0 DXPMCODE alias for handling protected mode processor
  755. ; exceptions.
  756. ;
  757. cCall NSetSegmentDscr,<SEL_EH,edx,ecx,EH_CODE>
  758. ; Set up a descriptor for our protected mode data and stack area.
  759. mov dx,ds
  760. movzx edx,dx ;our data segment paragraph address
  761. shl edx,4 ;convert to linear byte address
  762. mov ecx,0FFFFh
  763. cCall NSetSegmentDscr,<SEL_DXDATA,edx,ecx,STD_DATA>
  764. ; And another one of those for ring 0
  765. cCall NSetSegmentDscr,<SEL_DXDATA0,edx,ecx,ARB_DATA0>
  766. ; Set up descriptors pointing to our PSP and environment.
  767. movzx edx, segPSP ; segment address of the PSP
  768. shl edx, 4 ; linear address of PSP
  769. cCall NSetSegmentDscr,<SEL_PSP,edx,ecx,STD_DATA>
  770. mov selPSP, SEL_PSP
  771. ; set up environment selector
  772. push es
  773. mov es,segPSP
  774. assume es:PSPSEG
  775. movzx edx,segEnviron ;segment addr of environment
  776. shl edx,4 ;linear address of env
  777. mov ecx,7FFFh ;environments can only be 32k
  778. ; byte by DOS
  779. cCall NSetSegmentDscr,<SEL_ENVIRON,edx,ecx,STD_DATA>
  780. pop es
  781. assume es:DGROUP
  782. ; Set up a descriptor pointing to the BIOS code and data areas
  783. mov edx, 0f0000h ; set to linear f0000 (f000:0000)
  784. mov ecx, 0ffffh ; make it be a 64k segment
  785. cCall NSetSegmentDscr,<SEL_BIOSCODE,edx,ecx,STD_CODE>
  786. mov edx, 40h * 16 ; linear byte addr of BIOS data area
  787. cCall NSetSegmentDscr,<SEL_BIOSDATA,edx,ecx,STD_DATA>
  788. ; Set up a descriptor pointing to the real mode interrupt vector table.
  789. xor edx, edx ; the IVT is at linear address 0,
  790. ;other registers are still set up
  791. ; 64k data segment from last one
  792. cCall NSetSegmentDscr,<SEL_RMIVT,edx,ecx,STD_DATA>
  793. ; And, set up a selector for VCPI/WDEB386 to use to access all of memory.
  794. xor edx,edx
  795. mov ecx,edx
  796. dec ecx
  797. cCall NSetSegmentDscr,<SEL_VCPIALLMEM,edx,ecx,ARB_DATA0>
  798. ; Set up the call gate descriptor for the reset to V86 mode routine.
  799. mov ecx,offset DXCODE:ResetVCPI
  800. @@: mov edx,SEL_DXCODE0
  801. cCall NSetSegmentDscr,<SEL_RESET,edx,ecx,STD_CALL>
  802. ; Set up a call gate to invoke the VCPI pMode interface in ring 0.
  803. mov ecx,offset DXCODE:CallVCPI
  804. cCall NSetSegmentDscr,<SEL_CALLVCPI,edx,ecx,STD_CALL>
  805. ; Init call gate descriptors for all the DynaLink services.
  806. if DEBUG ;------------------------------------------------------------
  807. extrn DXOutDebugStr:NEAR
  808. mov ax,SEL_DYNALINK + (OutDebugStr shl 3)
  809. mov ecx,offset DXCODE:DXOutDebugStr
  810. mov edx,(SEL_DXCODE0 or EH_RING) or 00080000h ;copy 8 stack words
  811. cCall NSetSegmentDscr,<ax,edx,ecx,STD_CALL>
  812. extrn DXTestDebugIns:NEAR
  813. mov ax,SEL_DYNALINK + (TestDebugIns shl 3)
  814. movzx edx,dx ;copy 0 stack words
  815. mov ecx,offset DXCODE:DXTestDebugIns
  816. cCall NSetSegmentDscr,<ax,edx,ecx,STD_CALL>
  817. endif ;DEBUG ---------------------------------------------------------
  818. ; Set up the fault reflector IRET call gate.
  819. mov ax,offset DXPMCODE:PMFaultReflectorIRET
  820. cCall NSetSegmentDscr,<SEL_RZIRET,5,SEL_EH,0,ax,STD_CALL>
  821. clc
  822. cEnd
  823. ;*** InitIDTVCPI ;[ds]
  824. ;
  825. ; Purpose: to initialize the idt when running under vcpi
  826. ;
  827. ; Register
  828. ; Usage: eax, all others preserved
  829. ;
  830. ; Input: none
  831. ;
  832. ; Output: idt is initialized
  833. ;
  834. ; Returns: can't fail, cy clear
  835. ;
  836. ; Exceptions:
  837. ;
  838. ; Notes: only under real mode!!!!!
  839. ;
  840. ;************************************************************************/
  841. cProc InitIDTVCPI,<NEAR,PUBLIC>,<ebx,ecx,edx,di,es>
  842. cBegin
  843. jnc @F
  844. jmp InitIDTVCPI_ret
  845. @@:
  846. movzx eax, segBootPmode ; set up segIDT,selIDT with
  847. shl eax, 4 ; the RM seg of the idt
  848. add eax, IDTOFF
  849. ;
  850. ; IDT must be paragraph aligned!!!!! (guarenteed--see dxvcpi.inc)
  851. ;
  852. shr eax, 4
  853. mov segIDT, ax ; base of IDT
  854. mov selIDT, ax ;
  855. movzx ecx, cdscIDTMax ; number of descriptors in table
  856. shl cx, 3 ; convert to count of bytes
  857. dec cx ; compute segment size limit
  858. mov bpIDTcb, cx ; set up idtr with limit,
  859. mov edx, LADXIDTBASE ; ...and...
  860. mov bpIDTbase, edx ; ...linear base
  861. cCall NSetSegmentDscr,<SEL_IDT,edx,ecx,STD_DATA>
  862. ; Fill the IDT with interrupt gates that point to the interrupt reflector
  863. ; entry vector.
  864. mov es, segIDT
  865. xor di,di
  866. mov dx,offset DXPMCODE:PMFaultEntryVector ;the 1st 32 go here
  867. mov cx,32
  868. @@: mov es:[di].offDest,dx
  869. mov es:[di].selDest,SEL_EH or EH_RING
  870. mov es:[di].cwParam,0
  871. mov es:[di].arbGate,STD_INTR
  872. mov es:[di].rsvdGate,0
  873. add dx,3
  874. add di,8
  875. loop @b
  876. mov dx,offset DXPMCODE:PMIntrEntryVector+(32*3) ; the rest go here
  877. mov cx,cdscIDTMax
  878. sub cx,32
  879. @@: mov es:[di].offDest,dx
  880. mov es:[di].selDest,SEL_DXPMCODE or STD_RING
  881. mov es:[di].cwParam,0
  882. mov es:[di].arbGate,STD_INTR
  883. mov es:[di].rsvdGate,0
  884. add dx,3
  885. add di,8
  886. loop @b
  887. ; Now, fix up the ones that don't point to the interrupt reflector.
  888. mov es:[21h*8].offDest,offset DXPMCODE:PMIntrDos
  889. mov es:[25h*8].offDest,offset DXPMCODE:PMIntr25
  890. mov es:[26h*8].offDest,offset DXPMCODE:PMIntr26
  891. mov es:[28h*8].offDest,offset DXPMCODE:PMIntr28
  892. mov es:[2Fh*8].offDest,offset DXPMCODE:PMInt2FHandler
  893. mov es:[30h*8].offDest,offset DXPMCODE:PMIntrIgnore
  894. mov es:[31h*8].offDest,offset DXPMCODE:PMIntr31
  895. mov es:[33h*8].offDest,offset DXPMCODE:PMIntrMouse
  896. mov es:[41h*8].offDest,offset DXPMCODE:PMIntrIgnore
  897. if DEBUG ;-------------------------------------------------------------
  898. cmp fTraceBug,0
  899. jz @f
  900. mov es:[41h*8].offDest,offset DXCODE:PMDebugInt
  901. mov es:[41h*8].selDest,SEL_DXCODE or STD_RING
  902. @@:
  903. endif ;DEBUG ---------------------------------------------------------
  904. mov es:[4Bh*8].offDest,offset DXPMCODE:PMIntr4B
  905. ifdef NOT_NTVDM_NOT
  906. ; HP Extended BIOS System Call handler
  907. test fHPVectra,0ffh ;only do this for an HP Vectra
  908. jz NoHPBios
  909. ; Supposedly the system driver is going to force the HP Bios to
  910. ; use interrupt 6Fh while Windows is running, so we don't need to
  911. ; search for the moveable HP Bios interrupt--just use Int 6Fh.
  912. mov es:[6Fh*8].offDest,offset HPxBios
  913. NoHPBios:
  914. endif
  915. mov es:[70h*8].offDest,offset DXPMCODE:PMIntr70
  916. clc ; return success
  917. InitIDTVCPI_ret:
  918. cEnd
  919. ;*** InitTSSVCPI - initialize the tss for use under vcpi
  920. ;
  921. ; Purpose:
  922. ;
  923. ; Register
  924. ; Usage: uses eax, all others preserved
  925. ;
  926. ; Input: none
  927. ;
  928. ; Output: tss is setup
  929. ;
  930. ; Returns: none
  931. ;
  932. ; Exceptions: none
  933. ;
  934. ; Notes: none
  935. ;
  936. ;************************************************************************/
  937. cProc InitTSSVCPI,<NEAR,PUBLIC>,<es,di>
  938. cBegin
  939. jnc @F
  940. jmp InitTSSVCPI_ret
  941. @@:
  942. mov ax, segBootPmode
  943. add ax, ( (TSSOFF shr 16d) shl 12d )
  944. mov es, ax
  945. mov di, TSSOFF AND 0FFFFH
  946. mov es:[di + ts3_ldt],SEL_LDT ;set the LDT selector
  947. ; Set the ring 0 stack seg/pointer, we don't bother to set the others
  948. ; since nothing runs below user privilege level. Currently very little
  949. ; code runs ring 0 - just when switching between real/proteted modes.
  950. mov es:[di + ts3_ss0],SEL_DXDATA0
  951. mov word ptr es:[di + ts3_esp0],offset DGROUP:rgw0Stack
  952. clc
  953. InitTSSVCPI_ret:
  954. cEnd
  955. ;
  956. ;************************************************************************/
  957. ;
  958. ; The rest of this file is code which is called during protected mode
  959. ; initialization.
  960. ;
  961. ;************************************************************************/
  962. ;
  963. ;**************************************************************
  964. ;*** CallVCPIPM
  965. ;
  966. ; Utility routine to call VCPI server in protected mode. Masks out
  967. ; interrupts during the call because QEMM enables the processor
  968. ; interrupt flag when you call it.
  969. ;
  970. ; Entry: AX = VCPI function code.
  971. ; Uses: Depends upon call.
  972. ;
  973. ; Note: There is a copy of this routine in dxvcpi.asm and another
  974. ; in dxvcpibt.asm. This is to allow near calls. The copy
  975. ; in dxvcpibt.asm is discarded after initialization time.
  976. ;
  977. ;**************************************************************
  978. cProc CallVCPIPM,<NEAR>,<si>
  979. cBegin
  980. push ax ; save function code
  981. ;
  982. ; Shut out all interrupts.
  983. ; QEMM 5.0 enables interrupts during this call. All our interrupt
  984. ; handlers are in the user code ring. A workaround is to shut off
  985. ; hardware interrupts during the call.
  986. ;
  987. in al,INTA01
  988. IO_Delay
  989. mov si, ax
  990. mov al,0FFh
  991. out INTA01,al
  992. IO_Delay
  993. pop ax ;restore function code
  994. db 9Ah ;call far SEL_CALLVCPI:0
  995. dw 0,SEL_CALLVCPI or STD_RING
  996. ; Restore the state of the interrupt mask register
  997. xchg si, ax
  998. out INTA01,al
  999. IO_Delay
  1000. xchg si, ax
  1001. cEnd
  1002. ;**************************************************************
  1003. ; This variable is used to allow calling NSetSegmentDscr from
  1004. ; the DXCODE segment in protected mode.
  1005. ;
  1006. NSetSegmentDscrCall label dword
  1007. dw OFFSET DXPMCODE:NSetSegmentDscr,SEL_DXPMCODE or STD_RING
  1008. extrn EnterProtectedMode:NEAR
  1009. extrn EnterRealMode:NEAR
  1010. DXCODE ends
  1011. DXPMCODE segment
  1012. extrn XMScontrol:FAR
  1013. DXPMCODE ends
  1014. DXCODE segment
  1015. XMScontrolCall label dword
  1016. dw OFFSET DXPMCODE:XMScontrol,SEL_DXPMCODE or STD_RING
  1017. pmxmssvc macro fcn
  1018. ifnb <fcn>
  1019. mov ah, fcn
  1020. endif
  1021. call XMScontrolCall
  1022. endm
  1023. ;************************************************************************/
  1024. ;*** GrowPageTables
  1025. ;
  1026. ; Purpose: To grow the user memory page tables large enough to
  1027. ; accomodate any expected memory allocation request.
  1028. ;
  1029. ; Register
  1030. ; Usage: NONE
  1031. ;
  1032. ; Input: NONE
  1033. ;
  1034. ; Output: Page tables grown to anticipated demand. cPteMax updated.
  1035. ; Page table segment limit extended.
  1036. ;
  1037. ; Returns:
  1038. ;
  1039. ; Exceptions:
  1040. ;
  1041. ; Notes: Fails unless there is an XMS block to hold the new page
  1042. ; tables. Cannot extend the page tables using VCPI memory.
  1043. ;
  1044. ;************************************************************************/
  1045. cProc GrowPageTables,<NEAR,PUBLIC>,<ebx,ecx,edx,si,di,es>
  1046. cBegin
  1047. PMvcpi vcpiCFREEPAGES ; Fetch current VCPI free pages
  1048. mov ecx,edx
  1049. pmxmssvc 08h ; Query free extended memory
  1050. shr ax,2 ; convert to pages
  1051. movzx eax,ax
  1052. add ecx,eax ; ECX = theoretical pages we could
  1053. ; allocate
  1054. sub ecx,cPteMax ; minus what we have room for
  1055. jna GPT_ret ; enough space already
  1056. ;
  1057. ; So we work on machines with more than 64 Meg. RAM, we should put in a check
  1058. ; here to see whether it looks like we have more.
  1059. ;
  1060. shr ecx,8 ; ECX = kilobytes to hold this stuff
  1061. ;
  1062. ; Instead, we do this quick hack for now. If there appears to be more
  1063. ; than 60 Mb available, then grow the page tables to 512k.
  1064. ;
  1065. cmp ecx,60
  1066. jb @F
  1067. mov ecx,512
  1068. @@:
  1069. mov dx,cx
  1070. add dx,3 ; need to page align
  1071. pmxmssvc 09h ; Allocate a chunk of XMS to hold it
  1072. or ax,ax
  1073. jz GPT_ret
  1074. lea si, hmem_XMS_Table ; SI points to saved handles buffer
  1075. inc [hmem_XMS_Count] ; bump XMS handle count
  1076. mov [si],dx ; save handle for later disposal
  1077. pmxmssvc 0Ch ; lock the handle
  1078. or ax,ax
  1079. jnz @F ; jump on success
  1080. mov dx,[si] ; couldn't lock handle
  1081. pmxmssvc 0Dh ; free it
  1082. dec [hmem_XMS_Count] ; decrement count of allocated handles
  1083. jmp GPT_ret ; out of here
  1084. @@:
  1085. shl edx,16 ; EDX = physical address of extended
  1086. mov dx,bx ; page tables
  1087. shr edx,10
  1088. add edx,3 ; begin on a page boundary
  1089. shr edx,2
  1090. shl edx,12
  1091. or dl,NEWPTEMASK ; EDX = first PTE
  1092. mov selGDT,SEL_GDT
  1093. mov ax,SEL_DXPT
  1094. lsl ebx,eax
  1095. shl ecx,10 ; ECX = extra space in bytes
  1096. add ebx,ecx ; EBX = page table segment limit
  1097. mov eax, LADXPTBASE ; EAX = user page tables linear base
  1098. cCall [NSetSegmentDscrCall],<SEL_DXPT,eax,ebx,STD_DATA>
  1099. mov selGDT,SEL_LDT_ALIAS
  1100. mov eax,ecx
  1101. shr eax,2 ; ECX = new PTEs
  1102. add cPteMax,eax
  1103. add ecx,CBPAGE386 - 1
  1104. shr ecx,12 ; ECX = pages of page tables
  1105. mov ax,SEL_DXPD
  1106. mov es,ax
  1107. mov edi, ( CPTDX + 1 ) shl 2
  1108. push ecx
  1109. push edi
  1110. mov eax,edx
  1111. ;
  1112. ; Map the new page tables into the page directory.
  1113. ;
  1114. GPT_add_PD:
  1115. stos dword ptr es:[edi]
  1116. add eax,CBPAGE386
  1117. dec ecx
  1118. jnz GPT_add_PD
  1119. ;
  1120. ; Map the new page tables into the page table segment, by copying
  1121. ; the page directory entries.
  1122. ;
  1123. mov eax, DXLINEARBASE + DXPTSYSOFF + ( USERPT shl 2 )
  1124. xor ecx,ecx
  1125. dec cx
  1126. cCall [NSetSegmentDscrCall],<SEL_SCR0,eax,ecx,STD_DATA>
  1127. pop edi
  1128. mov esi,edi
  1129. pop ecx
  1130. push ds
  1131. assume ds:nothing
  1132. mov ax,es
  1133. mov ds,ax
  1134. mov ax,SEL_SCR0 or STD_TBL_RING
  1135. mov es,ax
  1136. rep movsd
  1137. pop ds
  1138. assume ds:DGROUP
  1139. GPT_ret:
  1140. cEnd
  1141. ;************************************************************************/
  1142. ;*** VCPIBootStrap
  1143. ;
  1144. ; Purpose: Move the Pmode memory block into extended memory.
  1145. ;
  1146. ; Register Usage:
  1147. ; EAX, BX, CX, SI, DI, Flags.
  1148. ;
  1149. ; Input: System is in Pmode.
  1150. ;
  1151. ; Output: If successful, the entire block of memory at DXLINEARBASE
  1152. ; is copied to DX_TEMP_LINEARBASE. Then the page directory
  1153. ; and page tables are swapped around, and a new cr3 value is
  1154. ; loaded, so that the new block is placed at DXLINEARBASE.
  1155. ; The VCPI server reloads cr3.
  1156. ;
  1157. ; Exceptions:
  1158. ; No defined errors. A bug in this routine will most likely
  1159. ; crash the program.
  1160. ;
  1161. ; Returns: Nothing.
  1162. ;************************************************************************/
  1163. cProc VCPIBootStrap,<NEAR,PUBLIC>,<eax,ecx,si,di>
  1164. cBegin
  1165. assume ds:DGROUP,ss:DGROUP
  1166. call EnterProtectedMode
  1167. cmp fDebug,0
  1168. jz SkipVCPIDebugINIT
  1169. mov ax,SEL_DXCODE or STD_RING
  1170. mov es,ax
  1171. assume es:NOTHING
  1172. mov di,offset DXCODE:WdebVCPI
  1173. mov ax,DS_VCPI_Notify
  1174. int DebOut_Int
  1175. push ds
  1176. pop es
  1177. assume es:DGROUP
  1178. SkipVCPIDebugINIT:
  1179. push es
  1180. push ds
  1181. assume ds:NOTHING,es:NOTHING
  1182. mov ax,SEL_LDT_ALIAS
  1183. mov ds,ax
  1184. mov ax,SEL_TSS_ALIAS
  1185. mov es,ax
  1186. ;
  1187. ; Copy the block of memory at DXLINEARBASE, which is really in a DOS
  1188. ; memory block in conventional memory, to DX_TEMP_LINEARBASE.
  1189. ;
  1190. xor si,si
  1191. mov di,si
  1192. mov cx,LDTOFF shr 2
  1193. rep movsd
  1194. ;
  1195. ; Manipulate the page tables and page directory in the extended
  1196. ; memory block, so that all our selectors point to the new area.
  1197. ;
  1198. mov ax,es
  1199. mov ds,ax
  1200. mov si,DXTEMPPTOFF
  1201. mov di,DXPTSYSOFF
  1202. mov cx,CBPAGE386 shr 2
  1203. rep movsd
  1204. ;
  1205. ; Zero out the temporary page table that was used to copy our stuff
  1206. ; up here.
  1207. ;
  1208. mov di,DXTEMPPTOFF
  1209. mov cx,CBPAGE386 shr 2
  1210. xor eax,eax
  1211. rep stosd
  1212. ;
  1213. ; Fill in the new page directory. First, the low memory page tables.
  1214. ;
  1215. mov si,DXPTSYSOFF + (VCPIPTOFF shr 10)
  1216. mov di,DXPDOFF
  1217. mov cx,CPTDX + 1
  1218. rep movsd
  1219. ;
  1220. ; Second, the entry for our high memory system area.
  1221. ;
  1222. mov si,DXPTSYSOFF + (DXPTSYSOFF shr 10)
  1223. mov di,DXPDOFF + (DXLINEARBASE shr 20)
  1224. movsd
  1225. ;
  1226. ; Copy the two user page table page table entries to their final location.
  1227. ;
  1228. mov cx,2
  1229. mov si,DXPTSYSOFF
  1230. mov di,DXPTSYSOFF + ( USERPT shl 2 )
  1231. rep movsd
  1232. ;
  1233. ; Zero out the original entries.
  1234. ;
  1235. mov cx,2
  1236. mov di,DXPTSYSOFF
  1237. xor eax,eax
  1238. rep stosd
  1239. ;
  1240. ; Move our protected mode code segment up.
  1241. ;
  1242. mov di,DXPMCODEOFF
  1243. mov ax,SEL_GDT
  1244. mov ds,ax
  1245. mov si,SEL_LDT_ALIAS
  1246. mov dx,DXPMCODE
  1247. mov ax,dx
  1248. shl ax,4
  1249. shr dx,12
  1250. mov ds:[si].adrBaseLow,ax
  1251. mov ds:[si].adrBaseHigh,dl
  1252. mov ds:[si].adrbBaseHi386,dh
  1253. mov cx,offset DXPMCODE:CodeEndPM + 10h
  1254. shr cx,2
  1255. xor si,si
  1256. mov ax,SEL_LDT_ALIAS
  1257. mov ds,ax
  1258. rep movsd
  1259. ;
  1260. ; Fetch page directory address for later cr3 loading.
  1261. ;
  1262. mov eax, es:[DXPTSYSOFF + (DXPDOFF shr 10)]
  1263. pop ds
  1264. assume ds:DGROUP
  1265. pop es
  1266. push eax
  1267. call EnterRealMode
  1268. pop eax ; get new page directory address
  1269. ; Save the pte (physical addr) of
  1270. and ax, 0f000h ; page directory, mask 12 lsb's
  1271. mov V86ToPm.zaCr3VTP, eax ; store it
  1272. ;
  1273. ; VCPI server will load new CR3 value when we do the next real
  1274. ; to protected mode switch.
  1275. ;
  1276. call EnterProtectedMode
  1277. ; Set up a descriptor for the LDT data alias.
  1278. mov edx,LADXLDTBASE
  1279. movzx ecx,cdscGDTMax
  1280. shl ecx,3
  1281. dec ecx
  1282. mov selGDT,SEL_GDT
  1283. cCall [NSetSegmentDscrCall],<SEL_LDT_ALIAS,edx,ecx,STD_DATA>
  1284. xor eax,eax
  1285. cCall [NSetSegmentDscrCall],<SEL_TSS_ALIAS,eax,eax,STD_DATA>
  1286. mov selGDT,SEL_LDT_ALIAS
  1287. call EnterRealMode
  1288. cEnd
  1289. ;************************************************************************/
  1290. ;*** AddXMStoVCPIHeap
  1291. ;
  1292. ; Purpose: Allocate extended memory for the DOS Extender heap by
  1293. ; allocating and locking blocks of XMS memory. Fill in
  1294. ; user page tables to point to the allocated memory.
  1295. ;
  1296. ; Register
  1297. ; Usage: eax, edx
  1298. ;
  1299. ; Input: ES:DI points to beginning of user page tables.
  1300. ;
  1301. ; Output: ES:DI points to next unused page table entry.
  1302. ;
  1303. ; Returns:
  1304. ;
  1305. ; Exceptions:
  1306. ;
  1307. ; Notes: This function should not be called if memory has already been
  1308. ; allocated from another source.
  1309. ;
  1310. ;************************************************************************/
  1311. cProc AddXMStoVCPIHeap,<FAR,PUBLIC>,<bx,cx,si>
  1312. localD cVCPIFreePages
  1313. cBegin
  1314. cCall GrowPageTables
  1315. lea si, hmem_XMS_Table ; SI points to saved handles buffer
  1316. mov ax,[hmem_XMS_Count] ; Point to the first free one.
  1317. shl ax,1
  1318. add si,ax
  1319. AXVH_begin:
  1320. xor eax,eax
  1321. pmxmssvc 08h ; Query free extended memory
  1322. and ax,NOT 3 ; truncate to page size
  1323. or ax,ax ; any available?
  1324. jz AXVH_x ; no
  1325. mov ecx,cPteMax ; ECX = number of pages that will fit
  1326. shl ecx,2 ; ECX = number of kilobytes
  1327. cmp eax,ecx ; compare available to space in page tables
  1328. jb AXVH_0 ; will fit in page tables
  1329. mov ax,cx ; won't, ask for less
  1330. AXVH_0:
  1331. mov cx,ax ; save copy of size
  1332. or cx,cx
  1333. jz AXVH_x ; none left
  1334. PMvcpi vcpiCFREEPAGES ; Store current VCPI free pages
  1335. mov cVCPIFreePages,edx
  1336. mov dx,cx ; dx = #kilobytes requested
  1337. pmxmssvc 09h ; allocate extended memory block
  1338. cmp ax,1 ; got a block?
  1339. jne AXVH_x ; no
  1340. mov [si],dx ; yes, got one, save handle
  1341. PMvcpi vcpiCFREEPAGES ; Fetch VCPI free pages
  1342. cmp edx,cVCPIFreePages ; Count still the same?
  1343. jne AXVH_0a ; No, allocate the memory from VCPI.
  1344. mov dx,[si] ; fetch handle
  1345. pmxmssvc 0ch ; lock the block
  1346. cmp ax,1 ; did it work?
  1347. je AXVH_1 ; yes
  1348. AXVH_0a:
  1349. mov dx,[si] ; no, fetch handle, free it and exit
  1350. pmxmssvc 0ah
  1351. jmp AXVH_x ; (can't use unlocked blocks)
  1352. AXVH_1: ; handle to locked block is in
  1353. ; [si], address in DX:BX
  1354. movzx eax,dx
  1355. shl eax,10h
  1356. mov ax,bx ; EAX = linear address of block
  1357. shr cx,2 ; CX = number of 386 pages in block
  1358. test ax,MASK allbitsPTE ; Page aligned?
  1359. jz AXVH_2 ; yes
  1360. and ax,NOT (MASK allbitsPTE)
  1361. add ax,CBPAGE386
  1362. dec cx
  1363. jcxz AXVH_x ; none left
  1364. AXVH_2:
  1365. movzx ecx,cx
  1366. sub cPteMax,ecx ; this many PTEs used up
  1367. or ax,NEWPTEMASK ; make it a page table entry
  1368. mov edx,CBPAGE386
  1369. cld
  1370. AXVH_AddPage:
  1371. stos dword ptr es:[edi]
  1372. add eax,edx
  1373. loop AXVH_AddPage
  1374. inc [hmem_XMS_Count] ; bump XMS handle count
  1375. add si,2 ; point to next slot in handle array
  1376. cmp si,(OFFSET hmem_XMS_Table) + ( CXMSBLOCKSDX * 2 )
  1377. jb AXVH_begin ; jump if more handles fit in array
  1378. AXVH_x:
  1379. cEnd
  1380. DXCODE ends
  1381. endif ;VCPI
  1382. end