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.

586 lines
14 KiB

  1. PAGE ,132
  2. TITLE DXVCPI.ASM -- Dos Extender VCPI Support Code
  3. ; Copyright (c) Microsoft Corporation 1990-1991. All Rights Reserved.
  4. ;*** dxvcpi.asm - vcpi detection/maintenance/cleanup code (resident)
  5. ;
  6. ; Copyright <C> 1990, Microsoft Corporation
  7. ;
  8. ; Purpose:
  9. ;
  10. ; Revision History:
  11. ;
  12. ;
  13. ; 08-07-90 earleh Allow program to boot without LIM 3.2 page frame.
  14. ; 05/07/90 jimmat Started incorporating VCPI changes from languages group.
  15. ;
  16. ; [] 20-Feb-1990 Dans Created
  17. ;
  18. ;************************************************************************/
  19. .286p
  20. ; -------------------------------------------------------
  21. ; INCLUDE FILE DEFINITIONS
  22. ; -------------------------------------------------------
  23. .xlist
  24. .sall
  25. include segdefs.inc
  26. include gendefs.inc
  27. include pmdefs.inc
  28. .list
  29. ; This entire file is only for VCPI support
  30. if VCPI
  31. .xlist
  32. .sall
  33. include dxvcpi.inc
  34. .list
  35. ;
  36. ; miscellaneous equates
  37. ;
  38. ;
  39. ; also in dxmmgr.asm
  40. ;
  41. .ERRE CB_MEMHDR EQ 10h ;size of memory block header
  42. ;
  43. ; also in dxmmgr.asm
  44. ;
  45. ;
  46. ; data
  47. ;
  48. DXDATA segment
  49. ;
  50. ; Externs
  51. ;
  52. extrn idCpuType:word
  53. extrn bpGDT:fword
  54. extrn cKbInitialHeapSize:word
  55. extrn cbHeapSize:dword
  56. extrn dsegCurrent:word
  57. extrn hmemHeap:word
  58. extrn lpfnXMSFunc:DWORD
  59. extrn selGDT:WORD
  60. ;
  61. ; Definitions, data
  62. ;
  63. public fEms
  64. fEMS db 0 ; ems present
  65. public fVCPI
  66. fVCPI db 0 ; vcpi present
  67. public iddxsystype
  68. iddxsystype db DXINDOS ; type of memory used to hold
  69. ; final dx Pmode data.
  70. public segBootPmode
  71. segBootPmode dw 0 ; segment of block used to
  72. ; build system tables in real
  73. align 4
  74. public cFreePages
  75. cFreePages dd 0 ; free 4k pages, updated on each
  76. ; allocation.
  77. public bpdxsyspages
  78. bpdxsyspages dd DXPMPAGES-1 dup(0)
  79. ;
  80. ; pointer (off of SEL_DXPT) where next free page table entry is
  81. ;
  82. ; we initialize dxpt1 to have cptdx+2 entries in it (see
  83. ; SetupPageTables in dxvcpibt.asm)
  84. ;
  85. ;
  86. ; Offset in zeroth page table of first page table entry that belongs
  87. ; to DX. Set by initial call to GetVCPIInterface.
  88. ;
  89. public pPteFirst
  90. pPteFirst dd 0
  91. ;
  92. ; Offset in block pointed to by SEL_DXPT of where to put next page
  93. ; table entry when allocating extended memory by the page.
  94. ;
  95. public pPteNext
  96. pPteNext dd 0
  97. ;
  98. ; Maximum number of user page table entries that will fit in our
  99. ; original page table buffers.
  100. ;
  101. public cPteMax
  102. cPteMax dd 0
  103. EXTRN hmem_XMS_Table:WORD
  104. EXTRN hmem_XMS_Count:WORD
  105. public hmem_System_Block
  106. hmem_System_Block dw 0
  107. DXDATA ends
  108. DXPMCODE segment
  109. IFDEF ROM
  110. %OUT VCPI Support not compatible with ROM! Code segment variables!
  111. .ERR
  112. ENDIF
  113. ;
  114. ; Data set up in real mode prior to relocation of DX into vcpi
  115. ; (read only after init time anyway)
  116. ;
  117. public fnVCPIPM, fnVCPIPMoff
  118. fnVCPIPM label fword ; vcpi interface entrypoint
  119. fnVCPIPMoff dd 0 ; set up in GetVCPIInterface
  120. dw SEL_VCPI ; we know what this is.
  121. externFP NSetSegmentDscr
  122. extrn XMScontrol:FAR
  123. pmxmssvc macro fcn
  124. ifnb <fcn>
  125. mov ah, fcn
  126. endif
  127. call XMScontrol
  128. endm
  129. DXPMCODE ends
  130. DXCODE segment
  131. ;
  132. ; Data set up in real mode prior to relocation of DX into vcpi
  133. ; (read only after init time anyway)
  134. ;
  135. public WdebVCPI, fnVCPI, fnVCPIoff
  136. ;--------- WdebVCPIInfo structure -----------
  137. public laVTP, V86ToPm
  138. ;
  139. ; Begin WDEB386 VCPI notification structure. The following variables
  140. ; are copied by WDEB386 when we send it a VCPI presence notification,
  141. ; just after entering protected mode. The structure of this block of variables
  142. ; must not be changed without also changing the format of the data
  143. ; structure used by WDEB386.
  144. ;
  145. ;--------- WdebVCPIInfo structure -----------
  146. WdebVCPI LABEL BYTE
  147. fnVCPI label fword ; vcpi interface entrypoint
  148. fnVCPIoff dd 0 ; set up in GetVCPIInterface
  149. dw SEL_VCPI ; we know what this is.
  150. dw SEL_VCPIALLMEM ; for Wdeb386 information
  151. laVTP dd 0 ; linear address of next structure
  152. ;
  153. ; End WDEB386 VCPI notification structure.
  154. ;
  155. ; Structure for switching from v86 mode to protect mode via VCPI
  156. EXTRN epmVCPI:BYTE
  157. V86ToPm VTP <,,, SEL_LDT, SEL_TSS, OFFSET epmVCPI, 0, SEL_DXCODE0>
  158. externFP AddXMStoVCPIHeap
  159. DXCODE ends
  160. DXCODE segment
  161. assume cs:DXCODE, ds:DXDATA, es:nothing
  162. ;*** FreeEMSHandle - free DX system memory
  163. ;
  164. ; Purpose: free the VCPI pages OR XMS block we allocated for system use
  165. ;
  166. ; Register
  167. ; Usage: eax, edx, si, cx
  168. ;
  169. ; Input: none
  170. ;
  171. ; Output: VCPI DOS Extender system pages freed
  172. ; XMS handle deallocated
  173. ;
  174. ; Returns: nothing
  175. ;
  176. ; Exceptions: No operation if none of these entities have been
  177. ; allocated yet
  178. ;
  179. ; Notes:
  180. ;
  181. ;************************************************************************/
  182. cProc FreeEMSHandle,<NEAR,PUBLIC,<>
  183. cBegin
  184. lea si,bpdxsyspages ; Load VCPI system pages array.
  185. mov cx,DXPMPAGES-1 ; (First page was in PSP block.)
  186. cld
  187. .386
  188. FreeVCPI_syspage:
  189. lodsd ; fetch next page
  190. or eax,eax ; page present?
  191. jz FreeVCPI_Done ; No, could have been XMS.
  192. and ax,0f000h ; Yes, clear lower 12 bits.
  193. mov edx,eax
  194. RMvcpi vcpiFREEPAGE ; and free it.
  195. loop FreeVCPI_syspage ; loop until all freed
  196. .286p
  197. FreeVCPI_Done:
  198. test iddxsystype,DXINXMS ; loaded in XMS?
  199. jz FreeEMSHandle_ret ; No.
  200. mov dx,hmem_System_Block ; Yes, load block
  201. xmssvc 0dh ; unlock XMS block
  202. mov dx,hmem_System_Block
  203. xmssvc 0ah ; free XMS block
  204. FreeEMSHandle_ret:
  205. cEnd
  206. DXCODE ends
  207. ;**************************************************************
  208. ; 386 only code from here on down!!!
  209. ;**************************************************************
  210. .386p
  211. include prot386.inc
  212. DXCODE segment
  213. assume cs:DXCODE, ds:DXDATA, es:nothing
  214. DXCODE ends
  215. DXPMCODE segment
  216. assume cs:DXPMCODE
  217. ;**************************************************************
  218. ;*** CallVCPIPM
  219. ;
  220. ; Utility routine to call VCPI server in protected mode. Masks out
  221. ; interrupts during the call because QEMM enables the processor
  222. ; interrupt flag when you call it.
  223. ;
  224. ; Entry: AX = VCPI function code.
  225. ; Uses: Depends upon call.
  226. ;
  227. ; Note: There is a copy of this routine in dxvcpi.asm and another
  228. ; in dxvcpibt.asm. This is to allow near calls. The copy
  229. ; in dxvcpibt.asm is discarded after initialization time.
  230. ;
  231. ;**************************************************************
  232. cProc CallVCPIPM,<NEAR>,<si>
  233. cBegin
  234. push ax ; save function code
  235. ;
  236. ; Shut out all interrupts.
  237. ; QEMM 5.0 enables interrupts during this call. All our interrupt
  238. ; handlers are in the user code ring. A workaround is to shut off
  239. ; hardware interrupts during the call.
  240. ;
  241. in al,INTA01
  242. IO_Delay
  243. mov si, ax
  244. mov al,0FFh
  245. out INTA01,al
  246. IO_Delay
  247. pop ax ;restore function code
  248. db 9Ah ;call far SEL_CALLVCPI:0
  249. dw 0,SEL_CALLVCPI or STD_RING
  250. ; Restore the state of the interrupt mask register
  251. xchg si, ax
  252. out INTA01,al
  253. IO_Delay
  254. xchg si, ax
  255. cEnd
  256. ;************************************************************************/
  257. ;*** AllocVCPIMem
  258. ;
  259. ; Purpose: to allocate a block of memory from VCPI
  260. ;
  261. ; Register
  262. ; Usage: eax, ebx, edx, ecx, es
  263. ;
  264. ; Input: ECX has number of 4k pages to allocate
  265. ; ES:EDI points to page table entries to fill.
  266. ;
  267. ; Output: pPteNext updated with next free pte
  268. ; cFreePages updated with number of free 4k pages from vcpi
  269. ;
  270. ; Returns: if success, linear ptr in eax
  271. ; if fail, eax 0, ebx has number of 4k pages available.
  272. ;
  273. ; Exceptions:
  274. ;
  275. ; Notes: maximum allocation is 65535 4k pages (more than enough)
  276. ; at one time.
  277. ; Also, this is PROTECT MODE ONLY.
  278. ;
  279. ;************************************************************************/
  280. cProc AllocVCPIMem,<NEAR,PUBLIC>,<bx,dx>
  281. cBegin
  282. ;
  283. ; Compute the number of entries free in our page table
  284. ;
  285. mov edx, cPteMax
  286. cmp ecx, edx ; compare request with PTEs
  287. jb @F
  288. ;
  289. ; our page tables have less room than the vcpi server can allocate,
  290. ; so adjust our count downward to reflect that
  291. ;
  292. mov ecx, edx
  293. @@:
  294. cmp ecx, cFreePages ; compare request with pages we are
  295. ; allowed to allocate
  296. jb @F ; request < max.?
  297. mov ecx, cFreePages ; No, clip.
  298. @@:
  299. jecxz AVM_exit ; ECX = pages to allocate
  300. AVM_getpage:
  301. PMvcpi vcpiALLOCPAGE
  302. or ah, ah
  303. jnz AVM_exit ; something happened...not as much
  304. ; as vcpi said was there.
  305. dec cPteMax ; fix up free PTEs
  306. dec cFreePages ; and free VCPI pages
  307. ;
  308. ; make it a page table entry, and store into page table
  309. ; don't need to worry about the tlb here, since not-present
  310. ; pages are not cached in the tlb.
  311. ;
  312. or dx, NEWPTEMASK
  313. mov eax, edx
  314. stos dword ptr es:[edi]
  315. dec ecx
  316. jnz AVM_getpage ; next allocate
  317. AVM_exit:
  318. cEnd
  319. ;************************************************************************/
  320. ;*** VCPISpace
  321. ;
  322. ; Purpose: Return maximum possible VCPI memory allocation.
  323. ;
  324. ; Uses:
  325. ;
  326. ; Input:
  327. ;
  328. ; Output:
  329. ;
  330. ; Return: EAX = maximum possible VCPI pages we can get.
  331. ;
  332. ; Exceptions:
  333. ;
  334. ; Notes:
  335. ;
  336. ;************************************************************************/
  337. cProc VCPISpace,<NEAR,PUBLIC>,<edx>
  338. cBegin
  339. PMvcpi vcpiCFREEPAGES ; EDX = free VCPI pages
  340. cmp edx,cFreePages ; clip to maximum EMS allocation
  341. jb VS_00
  342. mov edx,cFreePages
  343. VS_00:
  344. mov eax,cPteMax ; clip to space in page tables
  345. cmp edx,eax
  346. jb VS_01
  347. mov edx,eax
  348. VS_01:
  349. mov eax,edx
  350. cEnd
  351. ;************************************************************************/
  352. ;*** FreeVCPIHeap
  353. ;
  354. ; Purpose: To free the Extended Memory heap memory.
  355. ;
  356. ; Register
  357. ; Usage: eax, ebx, ecx, edx
  358. ;
  359. ; Input:
  360. ;
  361. ; Output: All VCPI pages allocated for the heap are freed.
  362. ; All XMS blocks allocated for the heap are freed.
  363. ; Page table entries are set to zero.
  364. ;
  365. ;
  366. ; Returns: nothing
  367. ;
  368. ; Exceptions: none
  369. ;
  370. ; Notes: Protect mode only
  371. ;
  372. ;************************************************************************/
  373. cProc FreeVCPIHeap,<NEAR,PUBLIC>,<es,edi,si,eax,edx>
  374. cBegin
  375. mov ax, SEL_DXPT ; set up es with the selector
  376. mov es, ax ; for our page tables
  377. mov edi, pPteFirst ; point to first page allocated
  378. mov ecx, pPteNext ; point to first unallocated PTE
  379. sub ecx, edi
  380. jbe Free_XMS_Handles
  381. shr ecx, 2 ; ECX = pages to free
  382. startloop:
  383. mov edx, es:[edi] ; get pte into edx
  384. and dx, 0f000h ; mask off 12 lsb's
  385. PMvcpi vcpiFREEPAGE ; free the page
  386. xor eax, eax
  387. stos dword ptr es:[edi] ; clear out PTE
  388. dec ecx
  389. jnz startloop
  390. @@:
  391. Free_XMS_Handles:
  392. lea si, hmem_XMS_Table ; si points to XMS handle array
  393. mov cx,[hmem_XMS_Count]
  394. jcxz No_XMS_Handles
  395. Free_XMS_Handles_Loop:
  396. mov dx,[si]
  397. pmxmssvc 0dh ; unlock any XMS blocks
  398. mov dx,[si]
  399. pmxmssvc 0ah ; free any XMS blocks
  400. add si,2 ; point to next slot in handle array
  401. loop Free_XMS_Handles_Loop ; loop if more handle slots
  402. No_XMS_Handles:
  403. cEnd
  404. AddXMStoVCPIHeapCall label dword
  405. dw offset dxcode:AddXMStoVCPIHeap,SEL_DXCODE or STD_RING
  406. ;*** AddVCPIHeap
  407. ;
  408. ; Purpose: to replace the himem specific code in AddToXmemHeap
  409. ;
  410. ; Register
  411. ; Usage: all preserved except return values in bx:dx
  412. ;
  413. ; Input: dx:cx is the minimum block length required (bytes).
  414. ;
  415. ; Output: cbHeapSize is updated if a heap is allocated
  416. ;
  417. ; Returns: bx:dx is 32bit linear address of allocated block if success,
  418. ; cy clear, else cy set
  419. ;
  420. ; Exceptions:
  421. ;
  422. ; Notes:
  423. ;
  424. ;************************************************************************/
  425. cProc AddVCPIHeap,<NEAR,PUBLIC>,<eax,ecx>
  426. localD cbNeeded
  427. cBegin
  428. push ebx ; save extended registers
  429. push edx
  430. add cx, CB_MEMHDR * 3 ; add memory manager overhead
  431. adc dx, 0
  432. movzx ecx,cx
  433. shl edx,16d
  434. or ecx,edx ; ECX = minimum bytes wanted
  435. mov cbNeeded,ecx
  436. add ecx,CBPAGE386-1
  437. shr ecx,12d ; ECX = minimum pages wanted
  438. mov eax, cPteMax
  439. cmp ecx,eax ; make sure we have enough
  440. jna AVH_00 ; page table entries
  441. mov ecx,eax ; ECX = minimum pages wanted
  442. AVH_00:
  443. mov cbHeapSize,0
  444. mov ax, SEL_DXPT ; ES -> user page tables
  445. mov es, ax
  446. mov edi, pPteNext ; Point to first unused PTE
  447. or edi, edi ; Initialized?
  448. jnz AVH_10 ; Yes, skip XMS allocate.
  449. mov edi, pPteFirst ; No, initialize first unused PTE.
  450. mov pPteNext, edi
  451. cCall AddXMStoVCPIHeapCall
  452. mov pPteFirst,edi ; VCPI allocations start here
  453. AVH_10:
  454. mov ebx, pPteNext ; EBX = first PTE
  455. shl ebx, 10d ; EBX = linear address of start of block
  456. mov dx, bx
  457. shr ebx, 16d ; DX:BX = linear address of block
  458. mov eax, edi
  459. sub eax, pPteNext
  460. shr eax, 2 ; AX = count of pages allocated
  461. sub ecx, eax ; Get what we asked for?
  462. jbe AVH_Done ; Yes.
  463. cCall AllocVCPIMem ; allocate it from VCPI
  464. ; cx has number of 4k pages
  465. AVH_Done:
  466. mov eax, edi
  467. sub eax, pPteNext
  468. mov pPteNext, edi
  469. or eax, eax
  470. jz AVH_BadExit
  471. shl eax, 10d ; EAX = count of bytes allocated
  472. sub eax, CB_MEMHDR * 3 ; deduct overhead
  473. mov cbHeapSize, eax
  474. clc
  475. jmp AVH_Exit
  476. AVH_BadExit:
  477. stc
  478. AVH_Exit:
  479. ;
  480. ; Result is in BX:DX, but we have to save restore the MSW of EBX and
  481. ; that of EDX before we return to our caller.
  482. ;
  483. mov ax,dx
  484. pop edx
  485. mov dx,ax
  486. mov ax,bx
  487. pop ebx
  488. mov bx,ax
  489. cEnd
  490. DXPMCODE ends
  491. endif ;VCPI
  492. end