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.

2635 lines
78 KiB

  1. PAGE ,132
  2. TITLE DXINT31.ASM -- Dos Extender Int 31h Handler
  3. ; Copyright (c) Microsoft Corporation 1989-1991. All Rights Reserved.
  4. ;***********************************************************************
  5. ;
  6. ; DXINT31.ASM -- DOS Extender Int 31h Handler
  7. ;
  8. ;-----------------------------------------------------------------------
  9. ;
  10. ; This module provides the Int 31h services to the protected mode
  11. ; application running under the DOS Extender.
  12. ;
  13. ;-----------------------------------------------------------------------
  14. ;
  15. ; 12/03/90 amitc 'i31_GetSetRMInt' will map vectors in the range 50-57h
  16. ; to the range 8-fh if 'Win30CommDriver' switch is set in
  17. ; system.ini
  18. ; 12/18/89 jimmat Service 0003 changed from Get LDT Base to Get Sel Incr,
  19. ; and added Virtual Interrupt State services.
  20. ; 09/18/89 jimmat Added Allocate/Free Real Mode Call-Back services
  21. ; 08/20/89 jimmat Changed A20 diddling to use XMS local enable/disable
  22. ; 06/14/89 jimmat Added a few missing and new services.
  23. ; 05/17/89 jimmat Added protected to real mode call/int services.
  24. ; 05/12/89 jimmat Original version (split out from DXINTR.ASM)
  25. ; 18-Dec-1992 sudeepb Changed cli/sti to faster FCLI/FSTI
  26. ;
  27. ;***********************************************************************
  28. .286p
  29. ; -------------------------------------------------------
  30. ; INCLUDE FILE DEFINITIONS
  31. ; -------------------------------------------------------
  32. .xlist
  33. .sall
  34. include segdefs.inc
  35. include gendefs.inc
  36. include pmdefs.inc
  37. include interupt.inc
  38. include int31.inc
  39. include dpmi.inc
  40. Int_Get_PMode_Vec EQU 04h
  41. Int_Set_PMode_Vec EQU 05h
  42. include intmac.inc
  43. include stackchk.inc
  44. .list
  45. ; -------------------------------------------------------
  46. ; GENERAL SYMBOL DEFINITIONS
  47. ; -------------------------------------------------------
  48. RealMode_SaveBP equ word ptr RealMode_EBP+4
  49. RealMode_SaveSP equ word ptr RealMode_EBP+6
  50. SelectorIncrement equ 8 ;DOSX increments consecutive selectors by 8
  51. Trans_Reset_HW equ 01h ;Reset PIC/A20 line on PM->Call services
  52. I31VERSION equ 0090d ;Int 31 services major/minor version #'s
  53. ; version 00.90 (not quite ready for DPMI)
  54. I31FLAGS equ 000Dh ; 386 extender, pMode NetBIOS
  55. I31MasterPIC equ 08h ;Master PIC Interrupts start at 08h
  56. ifdef NEC_98
  57. I31SlavePIC equ 10h
  58. else ;NEC_98
  59. I31SlavePIC equ 70h ;Slave PIC Interrupts start at 70h
  60. endif ;NEC_98
  61. ; -------------------------------------------------------
  62. ; EXTERNAL SYMBOL DEFINITIONS
  63. ; -------------------------------------------------------
  64. extrn EnterIntHandler:NEAR
  65. extrn LeaveIntHandler:NEAR
  66. extrn EnterRealMode:NEAR
  67. extrn EnterProtectedMode:NEAR
  68. extrn GetSegmentAddress:NEAR
  69. extrn SetSegmentAddress:NEAR
  70. extrn FreeSelector:NEAR
  71. extrn FreeSelectorBlock:NEAR
  72. extrn AllocateSelector:NEAR
  73. extrn AllocateSelectorBlock:NEAR
  74. extrn ParaToLDTSelector:NEAR
  75. extrn DupSegmentDscr:NEAR
  76. extrn GetFaultVector:NEAR
  77. extrn PutFaultVector:NEAR
  78. extrn AllocateXmemBlock:NEAR
  79. extrn FreeXmemBlock:NEAR
  80. extrn ModifyXmemBlock:NEAR
  81. extrn FreeLowBlock:NEAR
  82. extrn AllocateLowBlock:NEAR
  83. extrn AllocateLDTSelector:NEAR
  84. extrn ParaToLinear:NEAR
  85. extrn GetIntrVector:NEAR, PutIntrVector:NEAR
  86. extrn NSetSegmentLimit:near
  87. extrn NMoveDescriptor:near
  88. extrn NWOWSetDescriptor:near
  89. extrn DFSetIntrVector:near
  90. extrn RmSaveRestoreState:far
  91. extrn PmSaveRestoreState:far
  92. extrn RmRawModeSwitch:far
  93. extrn PmRawModeSwitch:far
  94. extrn IsSelectorFree:near
  95. extrn gtpara:near
  96. externNP NSetSegmentAccess
  97. externFP NSetSegmentDscr
  98. externNP FreeSpace
  99. ; -------------------------------------------------------
  100. ; DATA SEGMENT DEFINITIONS
  101. ; -------------------------------------------------------
  102. DXDATA segment
  103. extrn selGDT:WORD
  104. extrn segPSP:WORD
  105. extrn idCpuType:WORD
  106. extrn npXfrBuf1:WORD
  107. extrn rgbXfrBuf1:BYTE
  108. extrn pbReflStack:WORD
  109. extrn bReflStack:WORD
  110. extrn lpfnXMSFunc:DWORD
  111. extrn A20EnableCount:WORD
  112. extrn regUserAX:WORD, regUserFL:WORD, regUserSS:WORD
  113. extrn regUserSP:WORD, regUserDS:WORD, regUserES:WORD
  114. extrn PMInt24Handler:DWORD
  115. extrn DpmiFlags:WORD
  116. IFDEF WOW_x86
  117. extrn FastBop:fword
  118. ENDIF
  119. extrn selPspChild:WORD
  120. extrn LowMemAllocFn:DWORD
  121. extrn LowMemFreeFn:DWORD
  122. public i31HWReset
  123. i31HWReset db 0 ;NZ if in 'standard' real mode state
  124. i31_dsp_rtn dw 0 ;Int 31h service routine to dispatch
  125. ifdef DEBUG
  126. debugsavess dw 0 ; Usefull when debugging WOW KERNEL
  127. debugsavesp dw 0 ;
  128. debugsavebp dw 0 ;
  129. debugsavecx dw 0 ;
  130. endif
  131. public i31_selectorbitmap
  132. i31_selectorbitmap dw 0000000000000000b
  133. ;Reserved LDT Selectors
  134. ifdef JAPAN
  135. justw_flag dw 0 ; for Just Window
  136. endif ; JAPAN
  137. DXDATA ends
  138. ; -------------------------------------------------------
  139. ; CODE SEGMENT VARIABLES
  140. ; -------------------------------------------------------
  141. DXCODE segment
  142. assume cs:DXCODE
  143. extrn segDXData:WORD
  144. extrn selDgroup:WORD
  145. extrn segDXCode:word
  146. assume cs:NOTHING
  147. DXCODE ends
  148. DXPMCODE segment
  149. extrn selDgroupPM:WORD
  150. extrn segDXCodePM:WORD
  151. i31_dispatch label word
  152. dw 0000h, offset i31_AllocSel
  153. dw 0001h, offset i31_FreeSel
  154. dw 0002h, offset i31_MapSeg2Sel
  155. dw 0003h, offset i31_GetSelIncr
  156. dw 0004h, offset i31_Success ;lock selector memory
  157. dw 0005h, offset i31_Success ;unlock selector mem
  158. dw 0006h, offset i31_GetSegAddr
  159. dw 0007h, offset i31_SetSegAddr
  160. dw 0008h, offset i31_SetLimit
  161. dw 0009h, offset i31_SetAccess
  162. dw 000Ah, offset i31_CreateDataAlias
  163. dw 000Bh, offset i31_GetSetDescriptor
  164. dw 000Ch, offset i31_GetSetDescriptor
  165. dw 000Dh, offset i31_SpecificSel ; Allocate specific descriptor
  166. dw 0100h, offset i31_AllocDOSMem
  167. dw 0101h, offset i31_FreeDOSMem
  168. dw 0102h, offset i31_SizeDOSMem
  169. dw 0200h, offset i31_GetSetRMInt
  170. dw 0201h, offset i31_GetSetRMInt
  171. dw 0202h, offset i31_GetSetFaultVector
  172. dw 0203h, offset i31_GetSetFaultVector
  173. dw 0204h, offset i31_GetSetPMInt
  174. dw 0205h, offset i31_GetSetPMInt
  175. dw 0300h, offset i31_RMCall
  176. dw 0301h, offset i31_RMCall
  177. dw 0302h, offset i31_RMCall
  178. dw 0303h, offset i31_AllocCallBack
  179. dw 0304h, offset i31_FreeCallBack
  180. dw 0305h, offset i31_GetStateSaveRestore
  181. dw 0306h, offset i31_GetRawModeSwitch
  182. dw 0400h, offset i31_Version
  183. dw 04f1h, offset i31_WOW_AllocSel
  184. dw 04f2h, offset i31_WOW_SetDescriptor
  185. dw 04f3h, offset i31_WOW_SetAllocFunctions
  186. ;
  187. ; INCOMPLETE !!!!!!!!!!!
  188. ; Needed by kernel.
  189. ;
  190. dw 0500h, offset i31_GetFreeMem
  191. dw 0501h, offset i31_AllocMem
  192. dw 0502h, offset i31_FreeMem
  193. ;
  194. ; Fails by design if block is to be extended and this cannot be done
  195. ; in place.
  196. ;
  197. dw 0503h, offset i31_SizeMem
  198. dw 0600h, offset i31_Success ;lock linear region
  199. dw 0601h, offset i31_Success ;unlock linear region
  200. dw 0602h, offset i31_Success ;mark real mode rgn pageable
  201. dw 0603h, offset i31_Success ;relock real mode region
  202. dw 0604h, offset i31_PageSize ;get page size
  203. dw 0700h, offset i31_fail ;reserved
  204. dw 0701h, offset i31_fail ;reserved
  205. dw 0702h, offset i31_Success ;demand page candidate
  206. dw 0703h, offset i31_Success ;discard page contents
  207. dw 0800h, offset i31_fail ;physical addr mapping
  208. dw 0900h, offset i31_VirtualInt ;get & disable Int state
  209. dw 0901h, offset i31_VirtualInt ;get & enable Int state
  210. dw 0902h, offset i31_VirtualInt ;get Int state
  211. ;
  212. ; UNIMPLEMENTED !!!!!!!!!!!
  213. ; To be used for MSDOS protected mode API?
  214. ;
  215. dw 0A00h, offset i31_unimplemented ;get vendor specific API
  216. IFDEF WOW_x86
  217. NO386 = 0
  218. else
  219. NO386 = 1
  220. ENDIF
  221. ife NO386
  222. ;
  223. ; 386 Debug Register access routines.
  224. ;
  225. dw 0B00h, offset i31_Debug_Register_Access
  226. ;set debug watchpoint
  227. dw 0B01h, offset i31_Debug_Register_Access
  228. ;clear debug watchpoint
  229. dw 0B02h, offset i31_Debug_Register_Access
  230. ;get debug watchpoint state
  231. dw 0B03h, offset i31_Debug_Register_Access
  232. ;reset debug watchpoint
  233. endif ; NO386
  234. dw -1, offset i31_unimplemented
  235. DXPMCODE ends
  236. ; -------------------------------------------------------
  237. subttl INT 31h Entry Point
  238. page
  239. ; -------------------------------------------------------
  240. ; INT 31h SERVICE ENTRY POINT
  241. ; -------------------------------------------------------
  242. DXPMCODE segment
  243. assume cs:DXPMCODE
  244. ; -------------------------------------------------------
  245. ; PMIntr31 -- Service routine for the Protect Mode INT 31h
  246. ; services. These functions duplicate the
  247. ; Windows/386 VMM INT 31h services for protected
  248. ; mode applications. They were implemented to
  249. ; support a protect mode version of Windows/286.
  250. ;
  251. ; Input: Various registers
  252. ; Output: Various registers
  253. ; Errors:
  254. ; Uses: All registers preserved, other than return values
  255. assume ds:NOTHING,es:NOTHING,ss:NOTHING
  256. public PMIntr31
  257. PMIntr31 proc near
  258. cld ;practice 'safe programming'
  259. ; Determine if this one of the services we support.
  260. push bx
  261. mov bx,offset i31_dispatch ;cs:bx -> dispatch table
  262. @@:
  263. cmp ax,cs:[bx] ;scan dispatch table for
  264. jz i31_do_it ; service code in AH/AL
  265. cmp word ptr cs:[bx],-1 ;end of table is -1
  266. jz i31_do_it
  267. add bx,4
  268. jmp short @b
  269. ; BX contains the offset of the routine to service this request!
  270. i31_do_it:
  271. push ds ;save the service routine address
  272. mov ds,selDgroupPM ; in our DGROUP for now
  273. assume ds:DGROUP
  274. mov bx,cs:[bx+2]
  275. FCLI ;needed for [i31_dsp_rtn]
  276. mov i31_dsp_rtn,bx
  277. ifdef DEBUG
  278. mov debugsavess,ss ; usefule when debugging WOW kernel
  279. mov debugsavesp,sp
  280. mov debugsavebp,bp
  281. mov debugsavecx,cx
  282. endif
  283. pop ds
  284. pop bx
  285. i31_doit:
  286. call EnterIntHandler ;build an interrupt stack frame
  287. assume ds:DGROUP,es:DGROUP ; also sets up addressability
  288. push i31_dsp_rtn ;routine address on stack
  289. FSTI ;no need to keep interrupts disabled
  290. retn ;go perform the service
  291. i31_unimplemented: ;not implemented or undefined
  292. Debug_Out "Unsupported Int 31h requested (AX = #AX)"
  293. ; Int 31h service routines return (jmp) here to indicate failure. The
  294. ; standard failure return sets the carry flag, and sets ax = 0.
  295. i31_fail:
  296. mov [bp].intUserAX,0
  297. i31_fail_CY:
  298. or byte ptr [bp].intUserFL,1
  299. jmp short i31_exit
  300. ; Int 31h service routines return (jmp) here -- they jump back instead
  301. ; of returning because they expect the stack to be setup by EnterIntHandler,
  302. ; no extra items should be pushed.
  303. i31_done:
  304. and byte ptr [bp].intUserFL,not 1 ;clear carry flag
  305. i31_exit:
  306. assume ds:NOTHING,es:NOTHING
  307. FCLI ;LeaveIntHandler needs them off
  308. call LeaveIntHandler ;restore caller's registers, and
  309. riret ; get on down the road
  310. PMIntr31 endp
  311. ; -------------------------------------------------------
  312. ; This routine is for Int 31h services that the 286 DOS extender
  313. ; allows, but doesn't actually perform any work. Most of these
  314. ; services are related to demand paging under Windows/386.
  315. assume ds:DGROUP,es:DGROUP
  316. public i31_Success
  317. i31_Success proc near
  318. jmp i31_done ;nothing to do currently
  319. i31_Success endp
  320. ; -------------------------------------------------------
  321. ; Page Size. Gotta be 1000h, even if we don't do anything
  322. ; with it.
  323. ;
  324. assume ds:DGROUP,es:DGROUP
  325. public i31_PageSize
  326. i31_PageSize proc near
  327. mov [bp].intUserBX,0
  328. mov [bp].intUserCX,1000h
  329. jmp i31_done ;nothing to do currently
  330. i31_pageSize endp
  331. ; -------------------------------------------------------
  332. subttl INT 31h LDT/Heap Services
  333. page
  334. ; -------------------------------------------------------
  335. ; LDT/HEAP INTERRUPT (INT 31h) SERVICE ROUTINES
  336. ; -------------------------------------------------------
  337. ; -------------------------------------------------------
  338. ; Service 00/00 - Allocate Space in LDT for Selector
  339. ; in: cx - # selectors required
  340. ; out: ax - *index* of first selector
  341. assume ds:DGROUP,es:DGROUP
  342. public i31_AllocSel
  343. i31_AllocSel proc near
  344. jcxz short i31_15
  345. cmp cx,1 ;1 selector or more?
  346. ja @f
  347. call AllocateSelector ;allocate 1 selector
  348. jc i31_15
  349. jmp short i31_10
  350. @@: mov ax,cx
  351. push cx ; save # of selector to be allocated
  352. xor cx,cx ; allocate from lower range
  353. call AllocateSelectorBlock ;allocate a block of selectors
  354. pop cx
  355. jc i31_15
  356. i31_10:
  357. or al,STD_TBL_RING ;add standard table/ring bits
  358. mov [bp].intUserAX,ax ;return 1st/only selector in AX
  359. setsel: mov bx,STD_DATA ;all the selectors we allocate
  360. ; xor bl,bl ; get initialized to data/ring ?
  361. xor dx,dx ; 0 base, 0 limit
  362. @@:
  363. cCall NSetSegmentDscr,<ax,dx,dx,dx,dx,bx>
  364. add ax,SelectorIncrement
  365. loop @b
  366. jmp i31_done
  367. i31_15:
  368. jmp i31_fail ;fail the request
  369. i31_AllocSel endp
  370. ; -------------------------------------------------------
  371. ; Service 00/01 - Free LDT Selector
  372. ; in: bx - selector to free
  373. ; out: none
  374. assume ds:DGROUP,es:DGROUP
  375. public i31_FreeSel
  376. i31_FreeSel proc near
  377. mov ax,bx ;release the selector
  378. cmp ax,SEL_DPMI_LAST ; reserved selector?
  379. ja i31_Free_Regular_LDT_Selector ; No.
  380. mov cx,ax
  381. shr cl,3 ; Selector to selector index in LDT
  382. mov ax,1
  383. shl ax,cl ; AX = bit in i31_selectorbitmap
  384. test i31_selectorbitmap,ax ; test for already allocated
  385. jz i31_FreeSel_Fail ; already free!
  386. not ax
  387. and i31_selectorbitmap,ax ; mark as free
  388. jmp i31_done
  389. i31_Free_Regular_LDT_Selector:
  390. and ax,SELECTOR_INDEX ; only pass it the index
  391. or ax,SELECTOR_TI ;only allow LDT selectors
  392. jz i31_Check_DS_ES
  393. call FreeSelector
  394. jnc i31_Check_DS_ES
  395. i31_FreeSel_Fail:
  396. jmp i31_fail_CY
  397. i31_Check_DS_ES:
  398. ; check in case user frees the selector in DS or ES - we
  399. ; don't want to fault when popping his regs
  400. and bl,NOT SELECTOR_RPL ;compare without ring bits
  401. mov ax,[bp].pmUserDS
  402. and al,NOT SELECTOR_RPL
  403. cmp ax,bx
  404. jnz @f
  405. mov [bp].pmUserDS,0
  406. @@: mov ax,[bp].pmUserES
  407. and al,NOT SELECTOR_RPL
  408. cmp ax,bx
  409. jnz @f
  410. mov [bp].pmUserES,0
  411. @@:
  412. jmp i31_done
  413. i31_FreeSel endp
  414. ; -------------------------------------------------------
  415. ; Service 00/02 - Map Segment to Selector
  416. ; in: bx - real mode segment value
  417. ; out: ax - selector which maps area
  418. assume ds:DGROUP,es:DGROUP
  419. public i31_MapSeg2Sel
  420. i31_MapSeg2Sel proc near
  421. mov ax,bx ;find/make selector for real memory
  422. mov bx,STD_DATA ;assume it's a data selector
  423. call ParaToLDTSelector
  424. jnc @f
  425. jmp i31_fail_CY ;Falied!?
  426. @@:
  427. mov [bp].intUserAX,ax
  428. jmp i31_done
  429. i31_MapSeg2Sel endp
  430. ; -------------------------------------------------------
  431. ; Service 00/03 - Get Next Selector Increment Value
  432. ; in: none
  433. ; out: ax - Next Selector Increment Value
  434. assume ds:DGROUP,es:DGROUP
  435. public i31_GetSelIncr
  436. i31_GetSelIncr proc near
  437. mov [bp].intUserAX,SelectorIncrement ;DOSX incr value
  438. jmp i31_done
  439. i31_GetSelIncr endp
  440. ; -------------------------------------------------------
  441. ; Service 00/06 - Get Segment Base address.
  442. ; in: bx - selector
  443. ; out: cx:dx - 32 bit lma of segment
  444. assume ds:DGROUP,es:DGROUP
  445. public i31_GetSegAddr
  446. i31_GetSegAddr proc near
  447. mov ax,selGDT
  448. assume es:nothing
  449. lsl ax,ax
  450. push bx
  451. and bx,SELECTOR_INDEX
  452. cmp bx,ax
  453. jnc gsa10 ; not in ldt
  454. call IsSelectorFree
  455. jc gsa20
  456. gsa10: pop bx
  457. jmp i31_fail_CY
  458. gsa20: pop bx
  459. mov ax,bx
  460. call GetSegmentAddress
  461. mov [bp].intUserCX,bx
  462. mov [bp].intUserDX,dx
  463. jmp i31_done
  464. i31_GetSegAddr endp
  465. ; -------------------------------------------------------
  466. ; Service 00/07 - Set Segment Base address.
  467. ; in: bx - selector
  468. ; cx:dx - 32 bit lma of segment
  469. ; out: none
  470. assume ds:DGROUP,es:DGROUP
  471. public i31_SetSegAddr
  472. i31_SetSegAddr proc near
  473. mov ax,selGDT
  474. assume es:nothing
  475. lsl ax,ax
  476. push bx
  477. and bx,SELECTOR_INDEX
  478. cmp bx,ax
  479. jnc ssa10 ; not in ldt
  480. call IsSelectorFree
  481. jc ssa20
  482. ssa10: pop bx
  483. jmp i31_fail_CY
  484. ssa20: pop bx
  485. mov ax,bx
  486. mov bx,cx
  487. call SetSegmentAddress
  488. jmp i31_done
  489. i31_SetSegAddr endp
  490. ; -------------------------------------------------------
  491. ; Service 00/08 - Set Segment Limit.
  492. ; in: bx - selector
  493. ; cx:dx - 32 bit limit of segment
  494. ; out: none
  495. assume ds:DGROUP,es:DGROUP
  496. public i31_SetLimit
  497. i31_SetLimit proc near
  498. mov ax,selGDT
  499. assume es:nothing
  500. lsl ax,ax
  501. push bx
  502. and bx,SELECTOR_INDEX
  503. cmp bx,ax
  504. jnc sl10 ; not in ldt
  505. call IsSelectorFree
  506. jc sl20
  507. sl10: pop bx
  508. jmp i31_fail_CY
  509. sl20: pop bx
  510. mov es,selGDT
  511. and bx,SELECTOR_INDEX
  512. and es:[bx].cbLimitHi386,070h ; clear 'G' bit and old
  513. ; extended limit bits
  514. test cx,0fff0h ; bits 20-31 set?
  515. jz i31_SetLimit_0 ; No
  516. shr dx,12d ; Yes
  517. mov ax,cx
  518. shl ax,4d
  519. or dx,ax
  520. shr cx,12d
  521. or es:[bx].cbLimitHi386,080h ; set 'G' bit
  522. i31_SetLimit_0:
  523. mov es:[bx].cbLimit,dx
  524. or es:[bx].cbLimitHi386,cl
  525. cCall NSetSegmentLimit,<bx>
  526. jmp i31_done
  527. i31_SetLimit endp
  528. ; -------------------------------------------------------
  529. ; Service 00/09 - Set Segment Access Rights
  530. ; in: bx - selector
  531. ; cl - segment access rights byte
  532. assume ds:DGROUP,es:DGROUP
  533. public i31_SetAccess
  534. i31_SetAccess proc near
  535. mov ax,selGDT
  536. assume es:nothing
  537. lsl ax,ax
  538. push bx
  539. and bx,SELECTOR_INDEX
  540. cmp bx,ax
  541. jnc sa10 ; not in ldt
  542. call IsSelectorFree
  543. jc sa20
  544. sa10: pop bx
  545. sa11:
  546. jmp i31_fail_CY
  547. sa20: pop bx
  548. test cl,010000b ; system segment?
  549. jz sa11 ; y: error
  550. push cx
  551. and cl,AB_DPL ; mask off all but DPL bits
  552. cmp cl,STD_DPL ; is this the correct DPL?
  553. pop cx
  554. jnz sa11 ; n: error
  555. cCall NSetSegmentAccess,<bx,cx>
  556. jmp i31_done
  557. i31_SetAccess endp
  558. ; -------------------------------------------------------
  559. ; Service 00/0A - Create Data Segment Alias (for a code seg)
  560. ; in: bx - selector
  561. ; out: ax - new data selector
  562. assume ds:DGROUP,es:DGROUP
  563. public i31_CreateDataAlias
  564. i31_CreateDataAlias proc near
  565. mov ax,bx ;make sure it's a vaild selector
  566. verr ax
  567. jnz cda_failed
  568. mov bx,ax ;get a new selector for the alias
  569. ifdef JAPAN
  570. justw_check:
  571. endif ; JAPAN
  572. call AllocateSelector
  573. jc cda_failed
  574. ifdef JAPAN
  575. cmp [justw_flag],0
  576. jne not_justw
  577. mov [justw_flag],1
  578. jmp justw_check
  579. not_justw:
  580. endif ; JAPAN
  581. xchg ax,bx ;copy old to new
  582. call DupSegmentDscr
  583. mov es,selGDT
  584. and bx,SELECTOR_INDEX
  585. mov al,es:[bx].arbSegAccess
  586. and al,11100000b ;mask off all but present and DPL bits
  587. or al,AB_DATA or AB_WRITE
  588. mov ah, es:[bx].cbLimitHi386
  589. cCall NSetSegmentAccess,<bx,ax>
  590. or bl,STD_TBL_RING ;set standard table/ring bits
  591. mov [bp].intUserAX,bx
  592. jmp i31_done
  593. cda_failed:
  594. jmp i31_fail_CY
  595. i31_CreateDataAlias endp
  596. ; -------------------------------------------------------
  597. ; Service 00/0B - Get Descriptor
  598. ; Service 00/0C - Set Descriptor
  599. ; in: bx - selector
  600. ; es:di -> buffer to hold copy of descriptor
  601. assume ds:DGROUP,es:DGROUP
  602. public i31_GetSetDescriptor
  603. i31_GetSetDescriptor proc near
  604. .386p
  605. push esi
  606. push edi
  607. .286p
  608. mov ax,selGDT
  609. mov es,ax
  610. assume es:NOTHING
  611. lsl ax,ax
  612. and bx,SELECTOR_INDEX
  613. cmp bx,ax ; range-test selector against
  614. jc @f ; the limit of the GDT/LDT
  615. .386p
  616. pop edi
  617. pop esi
  618. .286p
  619. jmp i31_fail_CY ;fail if invalid selector specified
  620. @@:
  621. call IsSelectorFree
  622. jc @f
  623. .386p
  624. pop edi
  625. pop esi
  626. .286p
  627. jmp i31_fail_CY
  628. @@:
  629. cmp byte ptr [bp].intUserAX,SelMgt_Get_Desc ;Get or Set?
  630. jz i31_GetDscr
  631. ;
  632. ; Set Descriptor
  633. ;
  634. test DpmiFlags,DPMI_32BIT
  635. jnz gsd10
  636. .386p
  637. mov esi,0 ; zero high half
  638. mov edi,0
  639. jmp gsd20
  640. gsd10: mov esi,edi ; get high half of edi
  641. mov edi,0 ; zero high half
  642. .286p
  643. gsd20:
  644. push ds ;Set -
  645. mov ds,[bp].pmUserES
  646. assume ds:nothing
  647. mov si,[bp].pmUserDI ; ds:si -> caller's buffer
  648. mov di,bx ; es:di -> dscr slot in GDT/LDT
  649. .386p
  650. mov cl,ds:[esi].arbSegAccess386
  651. .286p
  652. test cl,010000b ; system segment?
  653. jz gsd25 ; y: error
  654. and cl,AB_DPL ; mask off all but DPL bits
  655. cmp cl,STD_DPL ; is this the correct DPL?
  656. jnz gsd25 ; n: error
  657. jmp short i31_MovDscr
  658. gsd25: ; set ldt format error
  659. pop ds
  660. .386p
  661. pop edi
  662. pop esi
  663. .286p
  664. jmp i31_fail_CY
  665. i31_GetDscr:
  666. assume ds:DGROUP
  667. ;
  668. ; Get Descriptor
  669. ;
  670. test DpmiFlags,DPMI_32BIT
  671. jnz gsd30
  672. .386p
  673. mov edi,0 ; zero high half of edi
  674. gsd30: mov esi,0 ; zero high half of esi
  675. .286p
  676. push ds ;Get -
  677. push es
  678. pop ds
  679. assume ds:nothing
  680. mov si,bx ; ds:si -> dscr slot in GDT/LDT
  681. mov es,[bp].pmUserES
  682. mov di,[bp].pmUserDI ; es:di -> caller's buffer
  683. i31_MovDscr:
  684. .386p
  685. cCall NMoveDescriptor,<ds,esi,es,edi>
  686. .286p
  687. i31_gs25:
  688. pop ds
  689. assume ds:DGROUP
  690. .386p
  691. pop edi
  692. pop esi
  693. .286p
  694. jmp i31_done
  695. i31_GetSetDescriptor endp
  696. ; -------------------------------------------------------
  697. ; Service 00/0D - Allocate Specific LDT Selector
  698. ; in: bx - selector
  699. ; out: carry clear if selector was allocated
  700. ; carry set if selector was not allocated
  701. assume ds:DGROUP,es:DGROUP
  702. public i31_SpecificSel
  703. i31_SpecificSel proc near
  704. and bx,SELECTOR_INDEX
  705. cmp bx,SEL_DPMI_LAST
  706. ja i31_SpecificSel_Fail
  707. mov cx,bx
  708. shr cl,3 ; Selector to selector index in LDT
  709. mov ax,1
  710. shl ax,cl ; AX = bit in i31_selectorbitmap
  711. test i31_selectorbitmap,ax ; test for already allocated
  712. jnz i31_SpecificSel_Fail ; allocated, fail
  713. or i31_selectorbitmap,ax ; mark as allocated
  714. ;
  715. ; Set up the DPL and size
  716. ;
  717. mov ax,bx
  718. mov cx,1
  719. jmp setsel
  720. i31_SpecificSel_Fail: ; couldn't get that one
  721. jmp i31_fail_CY
  722. i31_SpecificSel endp
  723. ; -------------------------------------------------------
  724. subttl INT 31h DOS Memory Services
  725. page
  726. ; -------------------------------------------------------
  727. ; INT 31h DOS MEMORY SERVICE ROUTINES
  728. ; -------------------------------------------------------
  729. ; -------------------------------------------------------
  730. ; Service 01/00 - Allocate DOS Memory Block
  731. ;
  732. ; In: BX - # paragraphs to allocate
  733. ; Out: If successful: Carry Clear
  734. ; AX - segment address of block
  735. ; DX - selector to access block
  736. ;
  737. ; If unsuccessful: Carry Set
  738. ; AX - DOS error code
  739. ; BX - size of largest available block in paragraphs
  740. ;
  741. ; 13-Feb-1991 -- ERH This call is not supported under Windows 3.1,
  742. ; but try to find a block in our net heap to
  743. ; satisfy the request, anyway.
  744. ;
  745. assume ds:DGROUP,es:DGROUP
  746. public i31_AllocDOSMem
  747. i31_AllocDOSMem proc near
  748. and [bp].intUserFL,NOT 1 ; clear carry in status
  749. mov cx,[bp].intUserBX
  750. mov dx,[bp].intUserBX
  751. shr dx,12 ; high half of byte count
  752. shl cx,4 ; low half of byte count
  753. call AllocateLowBlock
  754. jc adm30
  755. mov [bp].intUserDX,ax
  756. mov si,ax
  757. call GTPARA ; get paragraph address
  758. mov [bp].intUserAX,ax
  759. jmp i31_done
  760. adm30: shr cx,4
  761. shl dx,12
  762. or cx,dx ; paragraph size of largest
  763. ifdef JAPAN
  764. or cx,cx
  765. jz notdec
  766. dec cx
  767. notdec:
  768. endif ; JAPAN
  769. mov [bp].intUserBX,cx
  770. mov [bp].intUserAX,ax ; error code
  771. jmp i31_fail_CY
  772. i31_AllocDOSMem endp
  773. ; -------------------------------------------------------
  774. ; Service 01/01 - Release DOS Memory Block
  775. ;
  776. ; In: DX - SELECTOR of block to release
  777. ; Out: If successful: Carry Clear
  778. ;
  779. ; If unsuccessful: Carry Set
  780. ; AX - DOS error code
  781. assume ds:DGROUP,es:DGROUP
  782. public i31_FreeDOSMem
  783. i31_FreeDOSMem proc near
  784. mov ax,[bp].intUserDX
  785. verw ax
  786. jnz fdm60
  787. push bx
  788. mov bx, ax ; selector
  789. and bx,SELECTOR_INDEX ; make it index into ldt
  790. call IsSelectorFree
  791. pop bx
  792. jnc fdm60
  793. mov ax,[bp].intUserDX
  794. call FreeLowBlock
  795. jc fdm60
  796. jmp i31_Success
  797. fdm60: mov [bp].intUserAX,ax
  798. jmp i31_fail_CY
  799. i31_FreeDOSMem endp
  800. ; -------------------------------------------------------
  801. ; Service 01/02 - Resize DOS Memory Block
  802. ;
  803. ; In: BX - new block size in paragraphs
  804. ; DX - SELECTOR of block to release
  805. ; Out: If successful: Carry Clear
  806. ;
  807. ; If unsuccessful: Carry Set
  808. ; AX - DOS error code
  809. assume ds:DGROUP,es:DGROUP
  810. public i31_SizeDOSMem
  811. i31_SizeDOSMem proc near
  812. mov [bp].intUserBX,0
  813. mov [bp].intUserAX,08h ; insufficient mem. available
  814. jmp i31_fail_CY
  815. i31_SizeDOSMem endp
  816. ; -------------------------------------------------------
  817. subttl INT 31h Real Mode Int Vector Routines
  818. page
  819. ; -------------------------------------------------------
  820. ; INT 31h INTERRUPT SERVICES
  821. ; -------------------------------------------------------
  822. ; -------------------------------------------------------
  823. ; i31_GetSetRMInt -- Get/Set Real Mode Interrupt Vector
  824. ;
  825. ; In: bl - Interrupt #
  826. ; cx:dx - SEG:Offset of real mode int vector (if set)
  827. ; Out: cx:dx - SEG:Offset of real mode int vector (if get)
  828. assume ds:DGROUP,es:DGROUP
  829. public i31_GetSetRMInt
  830. i31_GetSetRMInt proc near
  831. push SEL_RMIVT or STD_RING ;address the real mode IVT
  832. pop es
  833. assume es:NOTHING
  834. xor bh,bh ;convert int # to offset
  835. shl bx,2
  836. FCLI ;play it safe
  837. cmp al,Int_Get_Real_Vec ;Get or Set?
  838. jnz i31_gs_set
  839. mov cx,word ptr es:[bx+2] ;get segment:offset
  840. mov dx,word ptr es:[bx]
  841. mov [bp].intUserCX,cx ;return them to caller
  842. mov [bp].intUserDX,dx
  843. jmp short i31_gs_ret
  844. i31_gs_set: ;setting the vector...
  845. mov es:[bx],dx ;set the real mode IDT vector
  846. mov es:[bx+2],cx
  847. i31_gs_ret:
  848. FSTI
  849. jmp i31_done
  850. i31_GetSetRMInt endp
  851. ; -------------------------------------------------------
  852. ; i31_GetSetFaultVector -- Get/Set Protected Mode Fault Vector (0h-1Fh)
  853. ;
  854. ; In: bl - Interrupt #
  855. ; cx:dx - Sel:Offset of pMode int vector (if set)
  856. ; Out: cx:dx - Sel:Offset of pMode int vector (if get)
  857. assume ds:DGROUP,es:DGROUP
  858. public i31_GetSetFaultVector
  859. i31_GetSetFaultVector proc near
  860. cmp bl,10h ; zero to 10h are defined for 80386
  861. jbe @f
  862. jmp i31_fail_CY ;must be <= 10h or fail it
  863. @@:
  864. xor bh,bh
  865. mov ax,bx ;interrupt # to AX
  866. cmp byte ptr [bp].intUserAX,Int_Get_Excep_Vec ;Get or Set?
  867. jne i31_gfv_set
  868. call GetFaultVector ;wants to get the vector
  869. mov [bp].intUserCX,cx
  870. mov [bp].intUserDX,dx
  871. jmp short i31_gfv_ret
  872. i31_gfv_set:
  873. .386p
  874. test DpmiFlags,DPMI_32BIT
  875. jnz sfv10
  876. movzx edx,dx ; zero high half
  877. .286p
  878. sfv10: call PutFaultVector ;doing a set (args already set)
  879. i31_gfv_ret:
  880. jmp i31_done
  881. i31_GetSetFaultVector endp
  882. ; -------------------------------------------------------
  883. ; i31_GetSetPMInt -- Get/Set Protected Mode Interrupt Vector
  884. ;
  885. ; In: bl - Interrupt #
  886. ; cx:dx - SEL:Offset of protected mode int vector (if set)
  887. ; Out: cx:dx - SEL:Offset of protected mode int vector (if get)
  888. assume ds:DGROUP,es:DGROUP
  889. public i31_GetSetPMInt
  890. i31_GetSetPMInt proc near
  891. xchg al,bl
  892. xor ah,ah
  893. cmp bl,Int_Get_PMode_Vec ;Get or Set?
  894. jnz i31_gsp_set
  895. ; NOTE: we don't call DFGetIntrVector here, because all it does is a call to
  896. ; the following routine
  897. call GetIntrVector
  898. mov [bp].intUserCX,cx
  899. mov [bp].intUserDX,dx
  900. jmp i31_gsp_done
  901. i31_gsp_set:
  902. ; set up the appropriate real mode reflector, and hook the int.
  903. call DFSetIntrVector
  904. i31_gsp_done:
  905. FSTI
  906. jmp i31_done
  907. i31_GetSetPMInt endp
  908. ; -------------------------------------------------------
  909. subttl INT 31h Protected-to-Real Mode Call/Int
  910. page
  911. ; -------------------------------------------------------
  912. ; INT 31h PROTECTED-TO-REAL MODE CALL/INT SERVICES
  913. ; -------------------------------------------------------
  914. ; -------------------------------------------------------
  915. ; Service 03/00 -- Simulate real mode interrupt
  916. ; Service 03/01 -- Call real mode procedure with far return frame
  917. ; Service 03/02 -- Call real mode procedure with iret return frame
  918. ;
  919. ; In: es:di -> client register structure for real mode
  920. ; bl = interrupt number (03/00 only)
  921. ; cx = # words to copy from protected mode stack
  922. ; Out: es:di -> updated client register structure
  923. assume ds:DGROUP,es:DGROUP
  924. public i31_RMCall
  925. i31_RMCall proc near
  926. ; First off, we need to copy the client register structure down to
  927. ; real mode addressable memory... Lets use rgbXfrBuf1 for now...
  928. ; Changed to use the interrupt reflector stack because these routines
  929. ; need to be reentrant. This also lets us leave interrupts enabled
  930. ; longer.
  931. ; Earleh - 27-Jun-1990.
  932. mov di,sp ; DI = SP = client regs. buffer
  933. sub di,size Real_Mode_Call_Struc+2 ; Make room for client
  934. sub di,[bp].intUserCX ; call structure plus
  935. sub di,[bp].intUserCX ; any optional stack params
  936. sub di,32 ; pushad
  937. push di ; plus copy of di.
  938. .386p
  939. pushad ; have to save high 16 bits
  940. .286p
  941. mov sp,di
  942. ; --------------------------------------------------------------
  943. ;
  944. ; The interrupt reflector stack frame now looks like this...
  945. ;
  946. ; pbReflStack + CB_STKFRAME-> ---------------------------
  947. ; (old pbReflStack) | |
  948. ; | INTRSTACK Struc |
  949. ; | from EnterIntHandler |
  950. ; | |
  951. ; ---------------------------
  952. ; pbReflStack + CB_STKFRAME | word pointer |>>--\
  953. ; - (SIZE INTRSTACK) - 2 -> --------------------------- |
  954. IFDEF WOW_x86
  955. ; | | |
  956. ; | Pushad frame | |
  957. ; | | |
  958. ; --------------------------- |
  959. ENDIF
  960. ; | | |
  961. ; | optional stack params | |
  962. ; | | |
  963. ; --------------------------- |
  964. ; | | |
  965. ; | | |
  966. ; | Real_Mode_Call_Struc | |
  967. ; | | |
  968. ; | | |
  969. ; ---------------------------<<--/
  970. ; | |
  971. ; | Available stack space |
  972. ; | |
  973. ; pbReflStack---------->---------------------------
  974. ;
  975. ; After returning from the real mode procedure, we will need
  976. ; to fetch the word pointer stored just below the EnterIntHandler
  977. ; frame, and use it to access our temporary Real_Mode_Call_Struc.
  978. ; In addition to holding the client register values, this also
  979. ; holds the SP and BP values we will need to switch back to our
  980. ; stack when we return from the real mode procedure.
  981. ;
  982. ; !!! -- Storing the optional stack parameters on top of our
  983. ; Real_Mode_Call_Struc has several problems. It eats up stack
  984. ; space if we call the real mode procedure on our stack, because
  985. ; we then have to make another copy of these. It also means we have to
  986. ; carry around a pointer to where the Real_Mode_Call_Struc lives.
  987. ; If we didn't have the stack parameters on top of the Real_Mode_Call_Struc,
  988. ; then we could find things strictly by offset from the value in
  989. ; pbReflStack. The picture above should be rearranged to make optimal
  990. ; use of space. I basically did it this way so I could have a minimum-
  991. ; change fix for a bug in Windows 3.0.
  992. ; !!!
  993. ; --------------------------------------------------------------
  994. ;
  995. ;
  996. cld
  997. .386p
  998. xor ecx,ecx
  999. .286p
  1000. mov cx,(size Real_Mode_Call_Struc) / 2
  1001. mov bx,di ;bx used to reference client regs below
  1002. .386p
  1003. test DpmiFlags,DPMI_32BIT
  1004. jz rmc10
  1005. mov esi,edi ; copy over high 16 bits
  1006. jmp rmc20
  1007. rmc10: xor esi,esi ; clear high 16 bits esi
  1008. rmc20: xor edi,edi ; clear high 16 bits edi
  1009. mov di,bx
  1010. .286p
  1011. mov si,[bp].pmUserDI
  1012. mov ds,[bp].pmUserES
  1013. assume ds:NOTHING
  1014. .386p
  1015. rep movs word ptr [esi],word ptr [edi]
  1016. .286p
  1017. ; Copy stack parameters from PM to RM stack if requested by caller. To
  1018. ; avoid excessive selector munging, we do this in two steps (under the
  1019. ; assumption the # words to copy will be small). First the PM stack args
  1020. ; are copied to a buffer in DXDATA, then after switching to real mode,
  1021. ; to the real mode stack. If the caller has more stack words than will
  1022. ; fit in our buffer, or the real mode stack, bad things will happen...
  1023. .386p
  1024. xor ecx,ecx
  1025. .286p
  1026. mov cx,[bp].intUserCX ;caller's CX has # stack words to copy
  1027. jcxz @f
  1028. Trace_Out "Int 31h PM-to-RM int/call copying #CX stack words"
  1029. .386p
  1030. xor esi,esi
  1031. .286p
  1032. mov ds,[bp].pmUserSS
  1033. mov si,[bp].pmUserSP
  1034. .386p
  1035. test DpmiFlags,DPMI_32BIT
  1036. jz rmc30
  1037. ;
  1038. ; Have to go groping for user stack, since we switched stacks to get
  1039. ; here.
  1040. ;
  1041. ; | |
  1042. ; +----------------+
  1043. ; | |
  1044. ; +---- SS -----+
  1045. ; | |
  1046. ; +----------------+
  1047. ; | |
  1048. ; +---- ESP -----+
  1049. ; | |
  1050. ; +----------------+
  1051. ; | Flags |
  1052. ; +----------------+
  1053. ; | CS |
  1054. ; +----------------+
  1055. ; | IP |
  1056. ; ds:si -> +----------------+
  1057. push dword ptr ds:[si + 6]
  1058. push word ptr ds:[si + 10]
  1059. pop ds
  1060. pop esi
  1061. add esi,6 ; other half of 32 bit stack frame
  1062. rmc30: add esi,6 ;ds:si -> PM stack args
  1063. rep movs word ptr [esi],word ptr [edi]
  1064. .286p
  1065. ;es:di already points to buffer
  1066. @@:
  1067. push es ;restore ds -> DGROUP
  1068. pop ds
  1069. assume ds:DGROUP
  1070. ; Switch to real mode, set up the real mode stack
  1071. SwitchToRealMode
  1072. assume ds:DGROUP,es:DGROUP
  1073. i31_rmcall_hw_ok:
  1074. FSTI ;RestoreHardwareIntr disables ints
  1075. ;don't need them disabled now
  1076. mov [bx].RealMode_SaveBP,bp ;save our stack in reserved area of
  1077. mov [bx].RealMode_SaveSP,sp ; real mode register frame
  1078. mov cx,[bp].pmUserCX ;cx = caller's CX (# stk words)
  1079. mov dh,byte ptr [bp].pmUserAX ;dh = caller's AL (subfunction)
  1080. mov dl,byte ptr [bp].pmUserBX ;dl = caller's BL (RM int #)
  1081. mov ax,[bx].RealMode_SS ;did caller specify his own stack?
  1082. or ax,[bx].RealMode_SP
  1083. jz @f
  1084. ; NOTE: can't reference [bp].xxUserXX varaibles after switching stacks
  1085. mov ss,[bx].RealMode_SS ;switch to caller's real mode stack
  1086. mov sp,[bx].RealMode_SP
  1087. assume ss:NOTHING
  1088. @@:
  1089. ; Copy stack args to real mode stack if there are any
  1090. jcxz @f
  1091. sub sp,cx
  1092. sub sp,cx ;make space on stack for args
  1093. mov di,sp
  1094. mov ax,ss
  1095. mov es,ax ;es:di -> real mode stack
  1096. assume es:NOTHING
  1097. lea si,[bx + size Real_Mode_Call_Struc]
  1098. cld
  1099. rep movsw
  1100. push ds
  1101. pop es
  1102. assume es:DGROUP
  1103. @@:
  1104. ; Put a far ret or iret frame on stack to return to us
  1105. cmp dh,Trans_Far_Call ;Does this service use a far ret or
  1106. jz i31_rmcall_retf ; an iret frame?
  1107. mov ax, [bx].RealMode_Flags ;real mode routine thinks these were
  1108. and ax, NOT 100h ;remove TF
  1109. push ax
  1110. push cs ; the prior flags and CS:IP
  1111. push offset i31_rmcall_ret
  1112. FCLI ;flags with interrupts disabled -- real
  1113. pushf ; mode rtn entered with these flags
  1114. FSTI
  1115. jmp short @f
  1116. i31_rmcall_retf:
  1117. push cs ;push a far ret frame so the
  1118. push offset i31_rmcall_ret ; real mode routine returns to us
  1119. mov ax, [bx].RealMode_Flags ;real mode rtn entered with these flags
  1120. and ax, NOT 100h ;remove TF
  1121. push ax
  1122. @@:
  1123. cmp dh,Trans_Sim_Int ;use an int vector, or caller's spec'd
  1124. jnz i31_rmcall_csip ; cs:ip?
  1125. mov al,dl ;push CS:IP for interrupt
  1126. xor ah,ah ; number in caller's BL
  1127. mov si,ax
  1128. shl si,2
  1129. xor ax,ax ;address real mode IDT
  1130. mov es,ax
  1131. assume es:NOTHING
  1132. push word ptr es:[si+2]
  1133. push word ptr es:[si]
  1134. jmp short @f
  1135. i31_rmcall_csip:
  1136. push [bx].RealMode_CS ;execute the real mode routine at
  1137. push [bx].RealMode_IP ; specified CS:IP
  1138. @@:
  1139. ; Load the clients registers, and pass control to the real mode routine
  1140. .386p
  1141. mov edi,dword ptr [bx].RealMode_DI
  1142. mov esi,dword ptr [bx].RealMode_SI
  1143. mov ebp,dword ptr [bx].RealMode_BP
  1144. mov edx,dword ptr [bx].RealMode_DX
  1145. mov ecx,dword ptr [bx].RealMode_CX
  1146. mov eax,dword ptr [bx].RealMode_AX
  1147. mov es,[bx].RealMode_ES
  1148. assume es:NOTHING
  1149. push [bx].RealMode_DS
  1150. push dword ptr [bx].RealMode_BX
  1151. pop ebx
  1152. pop ds
  1153. assume ds:NOTHING
  1154. .286p
  1155. iret
  1156. ; The real mode routine returns here when finished
  1157. i31_rmcall_ret:
  1158. pushf ;save returned flags, ds, bx on stack
  1159. FSTI ;don't need ints disabled
  1160. push ds
  1161. .386p
  1162. push ebx
  1163. .286p
  1164. mov ds,segDXData ;address our DGROUP
  1165. assume ds:DGROUP
  1166. ;
  1167. ; Fetch word pointer to temporary client register save area, that we
  1168. ; saved before switching stacks.
  1169. ;
  1170. mov bx,[pbReflStack]
  1171. mov bx,[bx + CB_STKFRAME - (SIZE INTRSTACK) - 2]
  1172. ; Save the real mode registers in client frame
  1173. .386p
  1174. mov dword ptr [bx].RealMode_DI,edi
  1175. mov dword ptr [bx].RealMode_SI,esi
  1176. mov dword ptr [bx].RealMode_BP,ebp
  1177. mov dword ptr [bx].RealMode_DX,edx
  1178. mov dword ptr [bx].RealMode_CX,ecx
  1179. mov dword ptr [bx].RealMode_AX,eax
  1180. mov [bx].RealMode_ES,es
  1181. pop dword ptr [bx].RealMode_BX
  1182. .286p
  1183. pop [bx].RealMode_DS
  1184. pop [bx].RealMode_Flags
  1185. or [bx].RealMode_Flags,03000h ; IOPL always has to be 3
  1186. ; Restore our stack and return to protected mode
  1187. ; SP will now point to base of temporary client register save area
  1188. ; on our stack. BP points to stack frame set up for us by EnterIntHandler.
  1189. ; SP must be restored to value in BP before calling LeaveIntHandler.
  1190. mov ss,segDXData ;address our DGROUP
  1191. mov sp,[bx].RealMode_SaveSP
  1192. mov bp,[bx].RealMode_SaveBP
  1193. SwitchToProtectedMode
  1194. assume ds:DGROUP,es:DGROUP
  1195. FSTI ;still don't need ints disabled
  1196. ; Apparently in win31 standard mode, the pm caller's flags are set to the
  1197. ; value of the rm flags at the handler's iret. On win31 enhanced mode, this
  1198. ; was *not* done, and the pm flags are, except for carry, basically
  1199. ; preserved. Since setting the flags kills some apps (winfax deltest),
  1200. ; we should adhere to the enhanced mode convention. Thus, the following
  1201. ; code is if'd out.
  1202. if 0
  1203. mov ax,[bx].RealMode_Flags
  1204. mov [bp].intUserFL,ax
  1205. endif
  1206. ; Copy the updated client register frame to the caller, and we're finished
  1207. cld
  1208. .386p
  1209. xor ecx,ecx
  1210. .286p
  1211. mov cx,(size Real_Mode_Call_Struc) / 2
  1212. .386p
  1213. xor esi,esi
  1214. xor edi,edi
  1215. mov si,bx
  1216. add si,[bp].pmUserCX
  1217. add si,[bp].pmUserCX
  1218. add si,size Real_Mode_Call_Struc
  1219. ;
  1220. ; Si now points at pushad frame
  1221. ;
  1222. push si
  1223. test DpmiFlags,DPMI_32BIT
  1224. jz rmc80
  1225. mov edi,[si]
  1226. rmc80:
  1227. .286p
  1228. mov si,bx
  1229. mov di,[bp].pmUserDI
  1230. mov es,[bp].pmUserES
  1231. assume es:NOTHING
  1232. .386p
  1233. rep movs word ptr [esi],word ptr [edi]
  1234. pop sp ; value calculated above
  1235. popad
  1236. mov sp,bp
  1237. .286p
  1238. jmp i31_done ;finished!
  1239. i31_RMCall endp
  1240. ; -------------------------------------------------------
  1241. ; Service 03/03 -- Allocate Real Mode Call-Back Address
  1242. ;
  1243. ; In: ds:si -> pMode CS:IP to be called when rMode
  1244. ; call-back address executed
  1245. ; es:di -> client register structure to be updated
  1246. ; when call-back address executed
  1247. ; Out: cx:dx -> SEGMENT:offset of real mode call-back hook
  1248. ; CY clear if successful, CY set if can't allocate
  1249. ; call back
  1250. assume ds:DGROUP,es:DGROUP
  1251. public i31_AllocCallBack
  1252. i31_AllocCallBack proc near
  1253. push ax
  1254. call AllocateLDTSelector
  1255. jc acb_nosel
  1256. push [bp].pmUserDS ;pass in user's ds on stack
  1257. push [bp].pmUserES ;pass in user's es on stack
  1258. DPMIBOP AllocateRMCallBack
  1259. add sp, 4
  1260. jc acb_nocb
  1261. mov [bp].intUserCX,cx ;callback segment
  1262. mov [bp].intUserDX,dx ;callback offset
  1263. mov cx,-1
  1264. cCall NSetSegmentDscr,<ax,0,0,0,cx,STD_DATA>
  1265. pop ax
  1266. jmp i31_done
  1267. acb_nocb:
  1268. call FreeSelector
  1269. acb_nosel:
  1270. pop ax
  1271. jmp i31_fail_CY ;no call-backs available, fail
  1272. i31_AllocCallBack endp
  1273. ; -------------------------------------------------------
  1274. ; Service 03/04 -- Free Real Mode Call-Back Address
  1275. ;
  1276. ; In: cx:dx -> SEGMENT:offset of rMode call-back to free
  1277. ; Out: CY clear if successful, CY set if failure
  1278. assume ds:DGROUP,es:DGROUP
  1279. public i31_FreeCallBack
  1280. i31_FreeCallBack proc near
  1281. push ax
  1282. DPMIBOP FreeRMCallBack
  1283. jc @f
  1284. call FreeSelector
  1285. pop ax
  1286. jmp i31_done
  1287. @@:
  1288. pop ax
  1289. jmp i31_fail_CY ;no call-backs available, fail
  1290. i31_FreeCallBack endp
  1291. ; -------------------------------------------------------
  1292. DXPMCODE ends
  1293. ; -------------------------------------------------------
  1294. DXCODE segment
  1295. assume cs:DXCODE
  1296. ;
  1297. ; RMCallBackBop
  1298. ;
  1299. ; Originally, the real mode call back hook was implemented here in
  1300. ; the 16-bit client dosx. What it did was allocate a stacklet on
  1301. ; its own stack and run the PM code on that stack. So the basic
  1302. ; stack layout was that the RM stack pointer was followed by approx.
  1303. ; 100 bytes or so of space, and then you started on the PM stack
  1304. ; (corresponding to the start of the next stacklet).
  1305. ;
  1306. ; This whole approach was basically broken, since apps don't expect
  1307. ; this. For example, the DOS4GW dos extender, which is used by a
  1308. ; lot of games, switches stacks immediately in the PM callback proc
  1309. ; from the protect mode stack to the real mode stack. That is, they
  1310. ; use the same contiguous stack for both real mode and protect mode.
  1311. ; What happens then with the original design is that the protect mode
  1312. ; code, depending on how deep it goes on the stack, ends up overwriting
  1313. ; the new stacklet further down, so we lose the return information
  1314. ; needed to get back from the PM callback proc.
  1315. ;
  1316. ; The new design is just to do it in the unobtrusive dpmi32 host,
  1317. ; including switching to a real PM stack. So here we just bop out
  1318. ; to perform the switch and PM call.
  1319. ;
  1320. public RMCallBackBop
  1321. RMCallBackBop proc far
  1322. DPMIBOP RMCallBackCall
  1323. ret ;finished!
  1324. RMCallBackBop endp
  1325. ; -------------------------------------------------------
  1326. DXCODE ends
  1327. ; -------------------------------------------------------
  1328. DXPMCODE segment
  1329. assume cs:DXPMCODE
  1330. ; -------------------------------------------------------
  1331. subttl INT 31h Memory Management Services
  1332. page
  1333. ; -------------------------------------------------------
  1334. ; INT 31h MEMORY MANAGEMENT SERVICES
  1335. ; -------------------------------------------------------
  1336. ; -------------------------------------------------------
  1337. ; Service 05/00 -- Get Free Memory Information
  1338. ;
  1339. ; In: es:di -> 30h byte buffer
  1340. ; Out: es:di -> Largest free block (in bytes) placed at
  1341. ; start of caller's buffer
  1342. ; Rest of buffer filled in with -1.
  1343. assume ds:DGROUP,es:DGROUP
  1344. public i31_GetFreeMem
  1345. i31_GetFreeMem proc near
  1346. mov es,[bp].pmUserES ; Point to user buffer
  1347. mov di,[bp].pmUserDI
  1348. assume es:NOTHING
  1349. FBOP BOP_DPMI, GetMemoryInformation, FastBop
  1350. jmp i31_done
  1351. i31_GetFreeMem endp
  1352. ; -------------------------------------------------------
  1353. ; Service 05/01 -- Allocate Memory Block
  1354. ;
  1355. ; In: bx:cx - size of block to allocate in bytes
  1356. ; Out: successful, carry clear &
  1357. ; bx:cx = linear memory address of block
  1358. ; si:di = handle to block
  1359. ; failed, carry set
  1360. assume ds:DGROUP,es:DGROUP
  1361. public i31_AllocMem
  1362. i31_AllocMem proc near
  1363. mov bx,[bp].pmUserBX
  1364. mov cx,[bp].pmUserCX
  1365. mov dx, selPSPChild
  1366. FBOP BOP_DPMI, AllocXmem, FastBop
  1367. jnc @f
  1368. jmp i31_fail_CY
  1369. @@: mov [bp].intUserBX,bx
  1370. mov [bp].intUserCX,cx
  1371. mov [bp].intUserSI,si
  1372. mov [bp].intUserDI,di
  1373. jmp i31_Done
  1374. i31_AllocMem endp
  1375. ; -------------------------------------------------------
  1376. ; Service 05/02 -- Free Memory Block
  1377. ;
  1378. ; In: si:di - 'handle' of block to free
  1379. ; Out: successful, carry clear
  1380. ; failed, carry set
  1381. assume ds:DGROUP,es:DGROUP
  1382. public i31_FreeMem
  1383. i31_FreeMem proc near
  1384. mov si,[bp].pmUserSI
  1385. mov di,[bp].pmUserDI
  1386. FBOP BOP_DPMI, FreeXmem, FastBop
  1387. jnc @f
  1388. jmp i31_fail_CY
  1389. @@: jmp i31_Done
  1390. i31_FreeMem endp
  1391. ; -------------------------------------------------------
  1392. ; Service 05/03 -- Resize Memory Block
  1393. ;
  1394. ; In: bx:cx - new size of block to allocate in bytes
  1395. ; si:di - 'handle' of block to free
  1396. ; Out: successful, carry clear &
  1397. ; bx:cx = linear memory address of block
  1398. ; si:di = handle to block
  1399. ; failed, carry set
  1400. assume ds:DGROUP,es:DGROUP
  1401. public i31_SizeMem
  1402. i31_SizeMem proc near
  1403. mov bx,[bp].pmUserBX
  1404. mov cx,[bp].pmUserCX
  1405. mov si,[bp].pmUserSI
  1406. mov di,[bp].pmUserDI
  1407. FBOP BOP_DPMI, ReallocXmem, FastBop
  1408. jnc @f
  1409. jmp i31_fail_CY
  1410. @@: mov [bp].intUserBX,bx
  1411. mov [bp].intUserCX,cx
  1412. mov [bp].intUserSI,si
  1413. mov [bp].intUserDI,di
  1414. jmp i31_Done
  1415. i31_SizeMem endp
  1416. ; -------------------------------------------------------
  1417. ; Service 09/00 -- Get and Disable Virtual Interrupt State
  1418. ; 09/01 -- Get and Enable Virtual Interrupt State
  1419. ; 09/02 -- Get Virtual Interrupt State
  1420. ;
  1421. ; In: none
  1422. ; Out: AL = previous interrupt state
  1423. assume ds:DGROUP,es:DGROUP
  1424. public i31_VirtualInt
  1425. i31_VirtualInt proc near
  1426. mov ah,byte ptr [bp].intUserFL+1 ;get/isolate user's IF in AH
  1427. shr ah,1
  1428. and ah,1
  1429. cmp byte ptr [bp].intUserAX,Get_Int_State ;only getting state?
  1430. jz @f ; yes, skip set
  1431. mov al,byte ptr [bp].intUserAX ;get desired state
  1432. shl al,1 ; move into IF position
  1433. and byte ptr [bp].intUserFL+1,not 02h ;clr old IF bit
  1434. or byte ptr [bp].intUserFL+1,al ; set desired
  1435. @@:
  1436. mov byte ptr [bp].intUserAX,ah ;return old state in user's AL
  1437. jmp i31_done
  1438. i31_VirtualInt endp
  1439. ; -------------------------------------------------------
  1440. subttl INT 31h Utility Routines
  1441. page
  1442. ; -------------------------------------------------------
  1443. ; INT 31h UTILITY ROUTINES
  1444. ; -------------------------------------------------------
  1445. ; -------------------------------------------------------
  1446. ; i31_Version -- Return Int 31h version information.
  1447. ;
  1448. ; In: none
  1449. ; Out: ah - major version
  1450. ; al - minor version
  1451. ; bx - flags
  1452. ; cl - processor type
  1453. ; dh - master PIC base interrupt
  1454. ; dl - slave PIC bas interrupt
  1455. ;
  1456. public i31_Version
  1457. assume ds:DGROUP,es:DGROUP
  1458. i31_Version proc near
  1459. mov [bp].intUserAX,I31VERSION
  1460. mov [bp].intUserBX,I31FLAGS
  1461. mov al,byte ptr idCpuType
  1462. mov byte ptr [bp].intUserCX,al
  1463. mov [bp].intUserDX,(I31MasterPIC SHL 8) OR I31SlavePIC
  1464. jmp i31_done
  1465. i31_Version endp
  1466. ; -------------------------------------------------------
  1467. ; i31_MemGetHeader -- Get selector to our header on a Int 31h allocated
  1468. ; DOS memory block.
  1469. ;
  1470. ; In: DX - SELECTOR of block to get header of
  1471. ; Out: ES - selector pointing to our header for block
  1472. ; Uses: none
  1473. public i31_MemGetHeader
  1474. assume ds:DGROUP,es:NOTHING,ss:NOTHING
  1475. i31_MemGetHeader proc near
  1476. ; User wants to release block pointed to by selector in DX. Use a scratch
  1477. ; selector to point 1 paragraph before that to make sure this is a block
  1478. ; we allocated, and get some misc info
  1479. push ax
  1480. push bx
  1481. push cx
  1482. push dx
  1483. mov ax,dx
  1484. call GetSegmentAddress ;BX:DX -> user's data area
  1485. sub dx,10h ;backup one paragraph
  1486. sbb bx,0
  1487. mov cx,0fh
  1488. mov ax,SEL_SCR0 or STD_TBL_RING
  1489. cCall NSetSegmentDscr,<ax,bx,dx,0,cx,STD_DATA>
  1490. mov es,ax
  1491. pop dx
  1492. pop cx
  1493. pop bx
  1494. pop ax
  1495. ret
  1496. i31_MemGetHeader endp
  1497. ; -------------------------------------------------------
  1498. ; RZCall -- Utility routine to call a Ring
  1499. ; Zero procedure. Stack parameter is the NEAR
  1500. ; address of the routine in the DXPMCODE segment to
  1501. ; call. The called routine must be declared FAR
  1502. ; and take no stack parameters.
  1503. ;
  1504. ; USES: Whatever Ring 0 routine uses
  1505. ; +Flags
  1506. ; RETURNS: Whatever Ring 0 routine returns
  1507. ;
  1508. ; NOTE: Assumes that interrupts must be disabled
  1509. ; for the Ring 0 routine.
  1510. ;
  1511. ; History:
  1512. ; 12-Feb-1991 -- ERH wrote it!!!
  1513. ; -------------------------------------------------------
  1514. My_Call_Gate dd (SEL_SCR0 or STD_TBL_RING) shl 10h
  1515. public RZCall
  1516. RZCall proc near
  1517. pushf
  1518. FCLI
  1519. push bp
  1520. mov bp,sp
  1521. cCall NSetSegmentDscr,<SEL_SCR0,0,SEL_EH,0,[bp+6],STD_CALL>
  1522. pop bp
  1523. call dword ptr My_Call_Gate
  1524. cCall NSetSegmentDscr,<SEL_SCR0,0,0,0,-1,STD_DATA>
  1525. npopf
  1526. retn 2
  1527. RZCall endp
  1528. ife NO386
  1529. i31_Debug_Register_Access proc near
  1530. or byte ptr [bp].intUserFL,1 ;set carry flag
  1531. cmp idCpuType,3 ;at least 386?
  1532. jb i31_Debug_Register_Access_Done ;No.
  1533. IFNDEF WOW_x86
  1534. push offset DXPMCODE:I31_Win386_Call
  1535. call RZCall
  1536. ELSE
  1537. call far ptr I31_Win386_Call
  1538. ENDIF
  1539. i31_Debug_Register_Access_Done:
  1540. jmp i31_exit
  1541. i31_Debug_Register_Access endp
  1542. .386
  1543. ;******************************************************************************
  1544. ;
  1545. ; I31_Win386_Call
  1546. ;
  1547. ; The routine to implement the INT 31h debug register functions is copied
  1548. ; directly from the WIN386 routine in vmm/int31.asm. This routine sets
  1549. ; up the 386 registers so that the actual API is callable from the 16-bit
  1550. ; DOS Extender.
  1551. ;
  1552. ;******************************************************************************
  1553. I31_Win386_Call proc far ; Called via ring-transition call gate
  1554. ;
  1555. ; Save 386 extended registers that are used by the WIN386 code.
  1556. ;
  1557. pushad
  1558. ;
  1559. ; Call the actual routine
  1560. ;
  1561. movzx ebp,bp
  1562. call I31_Debug_Register_Support
  1563. ;
  1564. ; Restore 386 extended registers that are used by the WIN386 code.
  1565. ;
  1566. popad
  1567. ret
  1568. I31_Win386_Call endp
  1569. DXPMCODE ends
  1570. ;******************************************************************************
  1571. ; R E C O R D S
  1572. ;******************************************************************************
  1573. ;
  1574. ; The following record defines the debug status register.
  1575. ;
  1576. DBG6 RECORD d6_r1:16,d6_bt:1,d6_bs:1,d6_bd:1,d6_r2:9,d6_b3:1,d6_b2:1,d6_b1:1,d6_b0:1
  1577. DBG6_RESERVED EQU (MASK d6_r1) OR (MASK D6_r2)
  1578. ;
  1579. ; The following record defines the debug control register.
  1580. ;
  1581. DBG7 RECORD d7_ln3:2,d7_rw3:2,d7_ln2:2,d7_rw2:2,d7_ln1:2,d7_rw1:2,d7_ln0:2,d7_rw0:2,d7_rs:6,d7_ge:1,d7_le:1,d7_g3:1,d7_l3:1,d7_g2:1,d7_l2:1,d7_g1:1,d7_l1:1,d7_g0:1,d7_l0:1
  1582. DBG7_RESERVED EQU (MASK d7_rs)
  1583. Num_Watchpoints EQU 4 ; Only 4 live watchpoints in 386, 486.
  1584. ;******************************************************************************
  1585. ; m a c r o s
  1586. ;******************************************************************************
  1587. ;******************************************************************************
  1588. ;
  1589. ; The following set of macros allows us to copy WIN386 code directly
  1590. ;
  1591. ;******************************************************************************
  1592. BeginProc macro fname
  1593. fname proc near
  1594. endm
  1595. EndProc macro fname
  1596. fname endp
  1597. endm
  1598. Assert_Client_Ptr macro dummy
  1599. endm
  1600. Client_Flags equ intUserFL
  1601. Client_EAX equ intUserAX
  1602. Client_AX equ intUserAX
  1603. Client_BX equ intUserBX
  1604. Client_CX equ intUserCX
  1605. Client_DX equ intUserDX
  1606. CF_MASK equ 1
  1607. OFFSET32 equ <OFFSET>
  1608. ;******************************************************************************
  1609. ; d a t a
  1610. ;******************************************************************************
  1611. DXDATA segment
  1612. PUBLIC Debug_Regs
  1613. ;
  1614. ; A memory image of the debug registers. The first version assumes
  1615. ; that we have complete control over the debug registers, so only
  1616. ; one copy is needed.
  1617. ;
  1618. ALIGN DWORD
  1619. Debug_Regs LABEL DWORD
  1620. DD_DR0 dd 0
  1621. DD_DR1 dd 0
  1622. DD_DR2 dd 0
  1623. DD_DR3 dd 0
  1624. DD_DR6 dd 0
  1625. DD_DR7 dd 0
  1626. DXDATA ends
  1627. .386p
  1628. DXPMCODE segment
  1629. ;******************************************************************************
  1630. ;
  1631. ; I31_Debug_Register_Support
  1632. ;
  1633. ; ENTRY: AL = Function code
  1634. ; 01 -- Set debug watchpoint
  1635. ; BX:CX = linear address of watchpoint
  1636. ; DL = size of watchpoint (1, 2, or 4)
  1637. ; DH = type of watchpoint
  1638. ; 0 = Execute
  1639. ; 1 = Write
  1640. ; 2 = Read/Write
  1641. ;
  1642. ; Returns
  1643. ; BX = debug watchpoint handle
  1644. ;
  1645. ; 02 -- Clear debug watchpoint
  1646. ;
  1647. ; 03 -- Get state of debug watchpoint
  1648. ; Returns
  1649. ; AX = bit 0 set if watch point has been executed
  1650. ;
  1651. ; 04 -- Reset debug watchpoint
  1652. ;
  1653. ; EXIT: Carry clear in client flags if successful
  1654. ; Carry set in client flags if not
  1655. ;
  1656. ; USES: EDI, EAX, ECX, EDX, ESI
  1657. ;
  1658. ; History:
  1659. ; 08-Feb-1991 -- ERH wrote it.
  1660. ;
  1661. ;******************************************************************************
  1662. BeginProc I31_Debug_Register_Support
  1663. IFNDEF WOW_x86
  1664. call Store_DBG_Regs ; make copy of debug regs.
  1665. ENDIF
  1666. test [DD_DR6],MASK d6_bd
  1667. jnz DD_I31_Error ; ICE-386 is active!
  1668. and [ebp.Client_Flags],NOT CF_MASK
  1669. mov eax, dword ptr [ebp.Client_EAX]
  1670. cmp al, 03h
  1671. ja DD_I31_Error
  1672. je DD_I31_Reset_Watchpoint
  1673. cmp al, 01h
  1674. ja DD_I31_Get_Status
  1675. je DD_I31_Clear_Watchpoint
  1676. ;
  1677. ; Function AX = 0A00h -- Set Debug Watchpoint
  1678. ;
  1679. PUBLIC DD_I31_Set_Watchpoint
  1680. DD_I31_Set_Watchpoint:
  1681. xor ecx, ecx
  1682. mov edx,(MASK d7_l0) OR (MASK d7_g0); EDX = DR0 enable bits
  1683. DD_I31_Search_Loop:
  1684. ;
  1685. ; Look for an unused breakpoint. In order for a breakpoint to be
  1686. ; unused, the corresponding global and local enable bits must be clear.
  1687. ;
  1688. test [DD_DR7],edx
  1689. jz SHORT DD_I31_SW_Found_One
  1690. DD_I31_SkipIt:
  1691. shl edx,2 ; EDX = next BP's enable bits
  1692. inc ecx
  1693. cmp ecx, Num_Watchpoints
  1694. jb DD_I31_Search_Loop
  1695. jmp DD_I31_Error
  1696. DD_I31_SW_Found_One:
  1697. mov esi, OFFSET32 Debug_Regs
  1698. mov eax,ecx
  1699. shl eax,2
  1700. add esi,eax ; ESI -> BP address buffer
  1701. mov ax, [ebp.Client_BX]
  1702. shl eax, 16
  1703. mov ax, [ebp.Client_CX] ; EAX = linear address
  1704. mov dword ptr [esi],eax ; record address
  1705. or [DD_DR7],edx ; enable the break point
  1706. mov edx,NOT((MASK d7_ln0) OR (MASK d7_rw0))
  1707. shl cl,2
  1708. rol edx,cl
  1709. shr cl,2
  1710. and [DD_DR7],edx ; clear type and size bits
  1711. ;
  1712. ; Client_DX =
  1713. ; DH = 0 : execute
  1714. ; DH = 1 : write
  1715. ; DH = 2 : read/write
  1716. ;
  1717. ; DL = 1 : byte
  1718. ; DL = 2 : word
  1719. ; DL = 4 : dword
  1720. ;
  1721. movzx edx,[ebp.Client_DX] ; load BP size and type
  1722. cmp dh,0 ; execute?
  1723. jne SHORT @F ; no
  1724. mov dl,1 ; yes, force size zero
  1725. @@:
  1726. cmp dl,4 ; check for valid values
  1727. ja DD_I31_Error ; size in dl is 1, 2, or 4
  1728. cmp dl,3
  1729. je DD_I31_Error
  1730. dec dl ; DL = 0, 1, or 3 for DR7
  1731. js DD_I31_Error ; len field
  1732. cmp dh,2 ; type in dh is 0, 1, or 2
  1733. ja DD_I31_Error
  1734. jne SHORT @F
  1735. inc dh ; 386 wants 3, not 2
  1736. @@: ; DH = RWn field
  1737. shl dl,2
  1738. or dl,dh
  1739. xor dh,dh
  1740. shl edx,d7_rw0
  1741. shl cl,2
  1742. shl edx,cl
  1743. or [DD_DR7],edx ; set size, type
  1744. shr cl,2
  1745. mov edx,NOT (MASK d6_b0) ; clear triggered bit
  1746. rol edx,cl ; EDX = mask to clear hit
  1747. and [DD_DR6],edx ; clear triggered bit
  1748. mov [ebp.Client_BX],cx ; return address register
  1749. ; number as BP handle
  1750. or [DD_DR7],(MASK d7_ge) OR (MASK d7_le)
  1751. ; enable debugging
  1752. call Load_DBG_Regs ; load changes into debug registers
  1753. ret
  1754. ;
  1755. ; Function AX = 0A01h -- Clear Debug Watchpoint
  1756. ;
  1757. ; Error if Watchpoint not previously set. In that case, do nothing.
  1758. ; If Watchpoint was set, then clear enable bits, triggered bit, and
  1759. ; breakpoint address.
  1760. ;
  1761. PUBLIC DD_I31_Clear_Watchpoint
  1762. DD_I31_Clear_Watchpoint:
  1763. movzx ecx,[ebp.Client_BX]
  1764. cmp ecx, Num_Watchpoints
  1765. jnb DD_I31_Error
  1766. mov edx,(MASK d7_l0) OR (MASK d7_g0); EDX = enable DR0 mask
  1767. shl edx,cl
  1768. shl edx,cl ; EDX = enable DRn mask
  1769. test [DD_DR7],edx ; BP set?
  1770. jz DD_I31_Error ; No, error.
  1771. not edx
  1772. and [DD_DR7],edx ; disable the BP
  1773. mov edx,NOT (MASK d6_b0) ; EDX = DR0 not hit
  1774. rol edx,cl ; EDX = DRn not hit
  1775. and [DD_DR6],edx ; clear triggered bit
  1776. mov esi, OFFSET32 Debug_Regs ; ESI -> DRn table
  1777. shl ecx,2 ; ECX = DWORD offset
  1778. add esi,ecx ; ESI -> DRn
  1779. mov dword ptr [esi],0 ; clear address
  1780. mov edx,NOT((MASK d7_ln0) OR (MASK d7_rw0))
  1781. rol edx,cl
  1782. and [DD_DR7],edx
  1783. ;
  1784. ; Test whether this leaves any breakpoints active. If not, disable
  1785. ; the exact match condition. Note: the following is a long line.
  1786. ;
  1787. test [DD_DR7],(MASK d7_g3) OR (MASK d7_l3) OR (MASK d7_g2) OR (MASK d7_l2) OR (MASK d7_g1) OR (MASK d7_l1) OR (MASK d7_g0) OR (MASK d7_l0)
  1788. jne SHORT @F
  1789. and [DD_DR7],NOT ((MASK d7_ge) OR (MASK d7_le))
  1790. @@:
  1791. call Load_DBG_Regs ; load changes into debug registers
  1792. ret
  1793. ;
  1794. ; Function AX = 0A02h -- Get Status of Debug Watchpoint
  1795. ;
  1796. PUBLIC DD_I31_Get_Status
  1797. DD_I31_Get_Status:
  1798. movzx ecx,[ebp.Client_BX]
  1799. cmp ecx, Num_Watchpoints
  1800. jnb SHORT DD_I31_Error
  1801. mov edx,(MASK d7_g0) OR (MASK d7_l0); EDX = DR0 enable bits
  1802. shl edx,cl
  1803. shl edx,cl ; EDX = DRn enable bits
  1804. test [DD_DR7],edx ; DRn enabled?
  1805. jz SHORT DD_I31_Error ; No, error.
  1806. mov edx,MASK d6_b0 ; EDX = DR0 hit mask
  1807. shl edx,cl ; EDX = DRn hit mask
  1808. xor eax,eax
  1809. test [DD_DR6],edx ; DRn hit?
  1810. jne SHORT @F ; no
  1811. inc al ; yes, store result
  1812. @@:
  1813. mov [ebp.Client_AX],ax
  1814. ret
  1815. ;
  1816. ; Function AX = 0A03h -- Reset Debug Watchpoint
  1817. ;
  1818. PUBLIC DD_I31_Reset_Watchpoint
  1819. DD_I31_Reset_Watchpoint:
  1820. movzx ecx,[ebp.Client_BX]
  1821. cmp ecx, Num_Watchpoints
  1822. jnb SHORT DD_I31_Error
  1823. mov edx,(MASK d7_g0) OR (MASK d7_l0); EDX = DR0 enable bits
  1824. shl edx,cl
  1825. shl edx,cl ; EDX = DRn enable bits
  1826. test [DD_DR7],edx ; DRn enabled?
  1827. jz SHORT DD_I31_Error ; No, error.
  1828. mov edx,NOT (MASK d6_b0) ; EDX = DR0 hit mask
  1829. rol edx,cl ; EDX = DRn hit mask
  1830. and [DD_DR6],edx ; clear triggered bit
  1831. call Load_DBG_Regs ; load changes into debug registers
  1832. ret
  1833. DD_I31_Error:
  1834. Assert_Client_Ptr ebp
  1835. or [ebp.Client_Flags], CF_Mask
  1836. ret
  1837. EndProc I31_Debug_Register_Support
  1838. ;******************************************************************************
  1839. ;
  1840. ; Load_DBG_Regs - Load debug registers from memory.
  1841. ; Do not change undefined bits.
  1842. ;
  1843. ; ENTRY: NONE
  1844. ; EXIT: Memory image copied to debug registers, undefined bits unchanged.
  1845. ; USES: eax, ecx, edi, esi
  1846. ;
  1847. ;******************************************************************************
  1848. BeginProc Load_DBG_Regs
  1849. mov esi,OFFSET32 Debug_Regs
  1850. DPMIBOP SetDebugRegisters
  1851. jnc short ldr_exit
  1852. cld
  1853. xor eax, eax
  1854. mov ecx, 6
  1855. mov edi, OFFSET32 Debug_Regs
  1856. rep stosd ;clear local copy
  1857. ldr_exit:
  1858. ret
  1859. EndProc Load_DBG_Regs
  1860. ; -------------------------------------------------------
  1861. IFNDEF WOW_x86
  1862. ;******************************************************************************
  1863. ;
  1864. ; Load_DBG_Regs - Load debug registers from memory.
  1865. ; Do not change undefined bits.
  1866. ;
  1867. ; ENTRY: NONE
  1868. ; EXIT: Memory image copied to debug registers, undefined bits unchanged.
  1869. ; USES: NONE
  1870. ;
  1871. ;******************************************************************************
  1872. BeginProc Load_DBG_Regs
  1873. push esi
  1874. push edx
  1875. push eax
  1876. cld
  1877. mov esi,OFFSET32 Debug_Regs
  1878. lods dword ptr ds:[esi]
  1879. mov dr0, eax
  1880. lods dword ptr ds:[esi]
  1881. mov dr1, eax
  1882. lods dword ptr ds:[esi]
  1883. mov dr2, eax
  1884. lods dword ptr ds:[esi]
  1885. mov dr3, eax
  1886. lods dword ptr ds:[esi]
  1887. and eax,NOT DBG6_RESERVED
  1888. mov edx,dr6
  1889. and edx,DBG6_RESERVED
  1890. or eax,edx
  1891. mov dr6, eax
  1892. .ERRNZ dd_dr6 - dd_dr3 - 4
  1893. lods dword ptr ds:[esi]
  1894. and eax,NOT DBG7_RESERVED
  1895. mov edx,dr7
  1896. and edx,DBG7_RESERVED
  1897. or eax,edx
  1898. mov dr7, eax
  1899. pop eax
  1900. pop edx
  1901. pop esi
  1902. ret
  1903. EndProc Load_DBG_Regs
  1904. ;******************************************************************************
  1905. ;
  1906. ; Store_DBG_Regs - Copy debug registers to memory.
  1907. ;
  1908. ; ENTRY: NONE
  1909. ; EXIT: Debug registers copied to memory image.
  1910. ; Undefined bits = don't care.
  1911. ; USES: NONE
  1912. ;
  1913. ;******************************************************************************
  1914. BeginProc Store_DBG_Regs
  1915. push eax
  1916. push edi
  1917. cld
  1918. mov edi,OFFSET32 Debug_Regs
  1919. mov eax, dr0
  1920. stos dword ptr es:[edi]
  1921. mov eax, dr1
  1922. stos dword ptr es:[edi]
  1923. mov eax, dr2
  1924. stos dword ptr es:[edi]
  1925. mov eax, dr3
  1926. stos dword ptr es:[edi]
  1927. mov eax, dr6
  1928. .ERRNZ dd_dr6 - dd_dr3 - 4
  1929. stos dword ptr es:[edi]
  1930. mov eax, dr7
  1931. stos dword ptr es:[edi]
  1932. pop edi
  1933. pop eax
  1934. ret
  1935. EndProc Store_DBG_Regs
  1936. ENDIF ; WOW_x86
  1937. ; -------------------------------------------------------
  1938. endif ; NO386
  1939. ; -------------------------------------------------------
  1940. subttl INT 31h Raw Modeswitch Routines
  1941. page
  1942. ; -------------------------------------------------------
  1943. ; INT 31h Raw Modeswitch Routines
  1944. ; -------------------------------------------------------
  1945. ; -------------------------------------------------------
  1946. ; i31_GetSaveRestoreState -- Return Int 31h Save/Restore State addresses.
  1947. ;
  1948. ; In: none
  1949. ; Out: ax - size of buffer required to save state
  1950. ; bx:cx - real mode address used to save/restore state
  1951. ; si:di - protected mode address used to save/restore state
  1952. ;
  1953. public i31_GetStateSaveRestore
  1954. assume ds:DGROUP,es:DGROUP
  1955. i31_GetStateSaveRestore proc near
  1956. mov [bp].intUserAX,0
  1957. push es
  1958. push SEL_DXCODE OR STD_RING
  1959. pop es
  1960. assume es:DXCODE
  1961. mov ax,segDXCode
  1962. pop es
  1963. assume es:DGROUP
  1964. mov [bp].intUserBX,ax
  1965. mov [bp].intUserCX,offset DXCODE:RmSaveRestoreState
  1966. mov [bp].intUserSI,SEL_DXPMCODE OR STD_RING
  1967. test DpmiFlags,DPMI_32BIT
  1968. jz gssr10
  1969. mov edi,dword ptr (offset DXPMCODE:PmSaveRestoreState)
  1970. gssr10: mov [bp].intUserDI,offset DXPMCODE:PmSaveRestoreState
  1971. jmp i31_done
  1972. i31_GetStateSaveRestore endp
  1973. ; -------------------------------------------------------
  1974. ; i31_GetRawModeSwitch -- Return Int 31h Save/Restore State addresses.
  1975. ;
  1976. ; In: none
  1977. ; Out: bx:cx - real -> protected mode switch address
  1978. ; si:di - protected -> real mode switch address
  1979. ;
  1980. public i31_GetRawModeSwitch
  1981. assume ds:DGROUP,es:DGROUP
  1982. i31_GetRawModeSwitch proc near
  1983. push es
  1984. push SEL_DXCODE OR STD_RING
  1985. pop es
  1986. assume es:DXCODE
  1987. mov ax,segDXCode
  1988. pop es
  1989. assume es:DGROUP
  1990. mov [bp].intUserBX,ax
  1991. mov [bp].intUserCX,offset DXCODE:RmRawModeSwitch
  1992. mov [bp].intUserSI,SEL_DXPMCODE OR STD_RING
  1993. test DpmiFlags,DPMI_32BIT
  1994. jz grms10
  1995. mov edi,dword ptr (offset DXPMCODE:PmRawModeSwitch)
  1996. grms10: mov [bp].intUserDI,offset DXPMCODE:PmRawModeSwitch
  1997. jmp i31_done
  1998. i31_GetRawModeSwitch endp
  1999. ;
  2000. ; make sure 286 protect mode else code generated for mips will be wrong.
  2001. ;
  2002. .286p
  2003. ; -------------------------------------------------------
  2004. ; Service 04/f1 - Allocate Space in LDT for Selector (WOW only)
  2005. ; Don't initialize the descriptor to Zero.
  2006. ; in: cx - # selectors required
  2007. ; out: ax - *index* of first selector
  2008. assume ds:DGROUP,es:DGROUP
  2009. public i31_WOW_AllocSel
  2010. i31_WOW_AllocSel proc near
  2011. cmp cx,1 ;1 selector or more?
  2012. ja @f
  2013. call AllocateSelector ;allocate 1 selector
  2014. jc i31_WOW_15
  2015. jmp short i31_WOW_10
  2016. @@: mov ax,cx ;WOW, cx != 0, allocate from higher range
  2017. call AllocateSelectorBlock ;allocate a block of selectors
  2018. jc i31_WOW_15
  2019. i31_WOW_10:
  2020. or al,STD_TBL_RING ;add standard table/ring bits
  2021. mov [bp].intUserAX,ax ;return 1st/only selector in AX
  2022. jmp i31_done
  2023. i31_WOW_15:
  2024. jmp i31_fail ;fail the request
  2025. i31_WOW_AllocSel endp
  2026. ; -------------------------------------------------------
  2027. ; Service 04/f2 - Set Descriptor (WOW only)
  2028. ; in: bx - selector
  2029. ; cx - number of contiguous selectors
  2030. assume ds:DGROUP,es:DGROUP
  2031. public i31_WOW_SetDescriptor
  2032. i31_WOW_SetDescriptor proc near
  2033. mov ax,selGDT
  2034. mov es,ax
  2035. assume es:NOTHING
  2036. lsl ax,ax
  2037. and bx,SELECTOR_INDEX ; input selector
  2038. cmp bx,ax ; range-test selector against
  2039. jc @F ; the limit of the GDT/LDT
  2040. jmp i31_fail_CY
  2041. @@:
  2042. cCall NWOWSetDescriptor,<cx,es,bx>
  2043. jmp i31_done
  2044. i31_WOW_SetDescriptor endp
  2045. ; -------------------------------------------------------
  2046. ; Service 04/f3 - Set Descriptor (WOW only)
  2047. ; in: bx:dx -- pointer to low memory allocation routine
  2048. ; si:di -- pointer to low memory free routine
  2049. assume ds:DGROUP,es:DGROUP
  2050. public i31_WOW_SetAllocFunctions
  2051. i31_WOW_SetAllocFunctions proc near
  2052. mov word ptr [LowMemAllocFn],dx
  2053. mov word ptr [LowMemAllocFn + 2],bx
  2054. mov word ptr [LowMemFreeFn],di
  2055. mov word ptr [LowMemFreeFn + 2], si
  2056. jmp i31_done
  2057. i31_WOW_SetAllocFunctions endp
  2058. DXPMCODE ends
  2059. ;****************************************************************
  2060. end