Leaked source code of windows server 2003
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.

2460 lines
60 KiB

  1. ;/* himem.asm
  2. ; *
  3. ; * Microsoft Confidential
  4. ; * Copyright (C) Microsoft Corporation 1988-1991
  5. ; * All Rights Reserved.
  6. ; *
  7. ; * Modification History
  8. ; *
  9. ; * Sudeepb 14-May-1991 Ported for NT XMS support
  10. ; *
  11. ; * williamh 25-Sept-1992 Added RequestUMB and ReleaseUMB
  12. ; */
  13. page 95,160
  14. title 'HIMEM.SYS - Microsoft XMS Device Driver'
  15. ;*****************************************************************************
  16. ;* *
  17. ;* HIMEM.ASM - *
  18. ;* *
  19. ;* Extended Memory Specification Driver - *
  20. ;* *
  21. ;*****************************************************************************
  22. ;
  23. ; himem.inc - global equates, macros, structures, opening segment
  24. ; himem.asm - main driver entry, interrupt hooks, a20/HMA functions
  25. ; himem1.asm - a20 switching code
  26. ; himem2.asm - driver initialization
  27. ; himem3.asm - messages for driver initialization
  28. ; himem4.asm - extended memory allocation functions
  29. ; himem5.asm - memory move function
  30. ;
  31. ; for revision history prior to 1990, see version 2.37 or earlier
  32. ;
  33. ; 2.35 - Removed a few push/pops from IsA20On, misc 01/14/90
  34. ; source code reformatting
  35. ; 2.36 - Include Int 6Dh vector in shadow RAM disable 01/18/90
  36. ; check, also allow disable if video Ints already
  37. ; point at C000h segment. Also added some CLD's near
  38. ; string instructions.
  39. ; 2.37 - Removed 2.33 'fix' for All Chargecard. They 01/23/89
  40. ; now do Global and Local enables to turn on A20, and
  41. ; the previous 'fix' caused us to never didle A20 again
  42. ; after running Windows real mode twice (Windows does
  43. ; Global enables/disables too). Also, GetParms needed to
  44. ; check for LF in addition to CR for end of line.
  45. ;;
  46. ;;; Following changes synced from \402\dev\himem tree
  47. ;;
  48. ; 2.50 - Revised version # for Windows 3.0 release. 02/05/90
  49. ; "" - Ignore 'super'-extended memory on EISA memory 02/08/90
  50. ; memory boards (mem > 16 meg). Software that
  51. ; uses 24 bit (80286) descriptors doesn't do
  52. ; well with memory @ 16 meg.
  53. ; "" - Himem will now try to control A20 by default, 02/12/90
  54. ; even if A20 is already enabled when himem is
  55. ; loaded. Added /A20CONTROL: ON | OFF switch to
  56. ; override this if necessary (ON is default and
  57. ; means we take control, OFF means we take control
  58. ; unless A20 was already on, in which case we
  59. ; don't mess with it).
  60. ;
  61. ; 2.60 - Added special A20 routine for Toshiba 1600 02/22/90
  62. ; laptop, and revised driver version number to
  63. ; be later than Compaq's (2.50) so Windows
  64. ; setup will install ours.
  65. ; "" - Clear bit 15 in device attributes word of 02/28/90
  66. ; device header if driver is being flushed. The
  67. ; MS-DOS Encylopedia says to do this, and a
  68. ; system with DOS 3.21 was hanging when loading
  69. ; the driver after himem if himem flushed itself.
  70. ; "" - Added special A20 handler for Wyse 12.5 MHz 03/27/90
  71. ; 286 machine. Almost the same as AT, but
  72. ; a little different.
  73. ; "" - Now displays a msg indicating which A20 04/05/90
  74. ; handler is installed, and allows numbers for the
  75. ; /MACHINE: parameter.
  76. ;;
  77. ;;; End of \402\dev\himem changes
  78. ;;
  79. ;
  80. ; "" - Added /INT15=xxxx option to reserve xxxxK of 04/13/90
  81. ; extended memory for INT 15. Himem will reserve xxxx K
  82. ; (64 K of HMA inclusive) for apps which use Ext Mem thru
  83. ; int 15 interface. The HMA portion of the INT 15 ext memory
  84. ; should be protected by a VDISK header. Apps which
  85. ; do not recognize VDISK headers may destroy the HMA.
  86. ;
  87. ; "" - When there is a /INT15=xxxx option on the 04/20/90
  88. ; command line, the HMA is made unavailable to the
  89. ; apps. But DOS 5.0 goes ahead and checks for INT 15
  90. ; memory if the alloc HMA call fails. And if INT 15 memory
  91. ; is present it uses the first 64 K for loading itself
  92. ; high (simulated HMA)
  93. ;
  94. ; "" - ORGed the movable segment to high value for flexibility
  95. ; in loading into HMA. Added code to be flexible enough to
  96. ; run from HMA as well as low memory.
  97. public Interrupt
  98. public dd_int_loc
  99. public fHMAExists
  100. public PrevInt15
  101. public fA20Check
  102. public OldStackSeg
  103. public pPPFIRET
  104. public EnableCount
  105. public pReqHdr
  106. public MinHMASize
  107. public Int2fHandler
  108. public fHMAMayExist
  109. public MemCorr
  110. public PrevInt2f
  111. public MoveIt
  112. public fCanChangeA20
  113. ifndef NEC_98
  114. public IsVDISKIn
  115. public fVDISK
  116. endif ;NEC_98
  117. public LocalEnableA20
  118. public LocalDisableA20
  119. public FLclEnblA20
  120. public FLclDsblA20
  121. public xLocalEnableA20
  122. public xLocalDisableA20
  123. public IsA20On
  124. public winbug_fix
  125. ifndef NEC_98
  126. public ATA20Delay
  127. else ;NEC_98
  128. public fAltA20Routine
  129. endif ;NEC_98
  130. public AddMem
  131. public TopOfTextSeg
  132. public A20State
  133. public Int15Handler
  134. ; Define a direct call to the Phoenix Cascade BIOS for A20 handling
  135. ; Note: if these segments are not defined here, the Int13Handler
  136. ; definition in segment Zero in the 386 memory move will generate
  137. ; bad code.
  138. PTL_Seg segment at 0f000h
  139. PTL_Seg ends
  140. BiosSeg SEGMENT AT 40h ; Used to locate 6300 PLUS reset address
  141. BiosSeg ends
  142. include himem.inc ; define structures, macros, open seg.
  143. include xmssvc.inc
  144. include vint.inc
  145. extrn EndText:byte
  146. _text ends
  147. funky segment para public 'funky'
  148. assume cs:funky
  149. ; externals from himem4
  150. extrn Version:near
  151. extrn MoveBlock:near
  152. extrn QueryExtMemory:near
  153. extrn AllocExtMemory:near
  154. extrn FreeExtMemory:near
  155. extrn LockExtMemory:near
  156. extrn UnlockExtMemory:near
  157. extrn GetExtMemoryInfo:near
  158. extrn ReallocExtMemory:near
  159. extrn RequestUMB:near
  160. extrn ReleaseUMB:near
  161. extrn cHandles:word
  162. extrn KiddValley:word
  163. ; externals from himem5
  164. funky ends
  165. ;
  166. ;------ the following segment should be the last in the sys file
  167. ; This segment is read by the stripdd utility to remove
  168. ; the zeroes introduced by the hi ORG in the movable segment
  169. ZZZ segment para 'ZZZ'
  170. dw 16 ; len of this segment
  171. dw offset _text:EndText ; len of text seg in double word
  172. dw 0
  173. dw HISEG_ORG ; number of zeroes to be stripped
  174. dw -1
  175. dw -1 ; terminator
  176. db (4) dup (55h) ; filler
  177. ZZZ ends
  178. _text segment word public 'code'
  179. assume cs:_text
  180. ; externals from himem1
  181. extrn A20Handler:near
  182. ; externals from himem2
  183. extrn InitInterrupt:near
  184. public DevAttr
  185. public Int15MemSize
  186. public fInHMA
  187. ; The Driver Header definition.
  188. Header dd -1 ; Link to next driver, -1 = end of list
  189. DevAttr dw 1010000000000000b ; Char device & Output until busy(?)
  190. dw Strategy ; "Stategy" entry point
  191. dd_int_loc dw InitInterrupt ; "Interrupt" entry point
  192. db 'XMSXXXX0' ; Device name
  193. ;************************************************************************
  194. ;* *
  195. ;* Global Variables *
  196. ;* *
  197. ;************************************************************************
  198. if keep_cs
  199. callers_cs dw 0
  200. endif
  201. TopOfTextSeg dw 0 ; size of retained driver
  202. pPPFIRet dw PPFIRet ; The offset of an IRET for the POPFF macro
  203. pReqHdr dd ? ; Pointer to MSDOS Request Header structure
  204. ifndef NEC_98
  205. pInt15Vector dw 15h*4,0 ; Pointer to the INT 15 Vector
  206. else ;NEC_98
  207. pInt15Vector dw 1fh*4,0 ; Pointer to the INT 15 Vector
  208. endif ;NEC_98
  209. PrevInt15 dd 0 ; Original INT 15 Vector
  210. PrevInt2f dd 0 ; Original INT 2f Vector
  211. ifdef NEC_98
  212. pInt220Vector dw 0dch*4,0; Pointer to the INT 220 Vector
  213. PrevInt220 dd 0 ; Original INT 220 Vector
  214. pInt20Vector dw 20h*4,0 ; Pointer to the INT 20 Vector
  215. PrevInt20 dd 0 ; Original INT 20 Vector
  216. pInt21Vector dw 21h*4,0 ; Pointer to the INT 21 Vector
  217. PrevInt21 dd 0 ; Original INT 21 Vector
  218. endif ;NEC_98
  219. fHMAInUse db 0 ; High Memory Control Flag, != 0 -> In Use
  220. fCanChangeA20 db 1 ; A20 Enabled at start? (assume changable)
  221. fHMAMayExist db 0 ; True if the HMA could exist at init time
  222. fHMAExists db 0 ; True if the HMA exists
  223. fInstalled db 0 ; True if ext mem has been allocated
  224. fInHMA db 0 ; true if hiseg is in HMA
  225. fVDISK db 0 ; True if a VDISK device was found
  226. fA20Check db 0 ; True if A20 handler supports On/Off check
  227. ifndef NEC_98
  228. ATA20Delay db 0 ; Type of AT A20 delay in use (0 - NUM_ALT_A20)
  229. else ;NEC_98
  230. fAltA20Routine db 0 ; True if alternative A20 routine in use
  231. endif ;NEC_98
  232. EnableCount dw 0 ; A20 Enable/Disable counter
  233. fGlobalEnable dw 0 ; Global A20 Enable/Disable flag
  234. MinHMASize dw 0 ; /HMAMIN= parameter value
  235. Int15MemSize dw 0 ; Memory size reserved for INT 15
  236. MemCorr dw 0 ; KB of memory at FA0000 on AT&T 6300 Plus.
  237. ; This is used to correct INT 15h,
  238. ; Function 88h return value.
  239. OldStackSeg dw 0 ; Stack segment save area for 6300 Plus.
  240. ; Needed during processor reset.
  241. ifndef NEC_98
  242. if NUM_A20_RETRIES
  243. A20Retries db 0 ; Count of retires remaining on A20 diddling
  244. endif
  245. else ;NEC_98
  246. I2fCheckNH_Tbl dd 0 ; Old Pointer (ES:BX) for Windows ins NEC <91.09.27>
  247. db 3,0 ; version
  248. db 01h ; type for instance is INT Vector
  249. db 0 ; R.F.U
  250. dw offset _text:PrevInt15 ; offset
  251. I2f_seg dw 0 ;
  252. dw 4 ;
  253. dw 1fh ;
  254. dd -1 ;
  255. endif ;NEC_98
  256. A20State db 0 ; recored the current A20 state
  257. ifndef NEC_98
  258. public lpExtA20Handler
  259. lpExtA20Handler dd 0 ; Far entry point to an external A20 handler
  260. endif ;NEC_98
  261. ;*----------------------------------------------------------------------*
  262. ;* *
  263. ;* Strategy - *
  264. ;* *
  265. ;* Called by MS-DOS when ever the driver is accessed. *
  266. ;* *
  267. ;* ARGS: ES:BX = Address of Request Header *
  268. ;* RETS: Nothing *
  269. ;* REGS: Preserved *
  270. ;* *
  271. ;*----------------------------------------------------------------------*
  272. Strategy proc far
  273. assume ds:nothing
  274. ; Save the address of the request header.
  275. mov word ptr [pReqHdr],bx
  276. mov word ptr [pReqHdr][2],es
  277. ret
  278. Strategy endp
  279. ;*----------------------------------------------------------------------*
  280. ;* *
  281. ;* Interrupt - *
  282. ;* *
  283. ;* Called by MS-DOS immediately after Strategy routine *
  284. ;* *
  285. ;* ARGS: None *
  286. ;* RETS: Return code in Request Header's Status field *
  287. ;* REGS: Preserved *
  288. ;* *
  289. ;* This is our permanent entry point. By this time, the only *
  290. ;* useful function done by the device driver (initializing us) *
  291. ;* has been done by a previous call. There are no more valid *
  292. ;* uses for this entry point. All we have to do is decide *
  293. ;* whether to ignore the call or generate an error. *
  294. ;* *
  295. ;*----------------------------------------------------------------------*
  296. Interrupt proc far
  297. assume ds:nothing
  298. push bx ; save minimal register set
  299. push ds
  300. lds bx,[pReqHdr] ; ds:bx = Request Header
  301. cmp ds:[bx].Command,16 ; legal DOS function? (approx???)
  302. mov ds:[bx].Status,100h ; "Done" for healthy calls
  303. jbe FuncOk
  304. or ds:[bx].Status,8003h ; Return "Unknown Command" error
  305. FuncOk:
  306. pop ds
  307. pop bx
  308. ret
  309. Interrupt endp
  310. ;*----------------------------------------------------------------------*
  311. ;* *
  312. ;* Int2fHandler - *
  313. ;* *
  314. ;* Hooks Function 43h, Subfunction 10h to return the *
  315. ;* address of the High Memory Manager Control function. *
  316. ;* Also returns 80h if Function 43h, Subfunction 0h is requested. *
  317. ;* *
  318. ;* ARGS: AH = Function, AL = Subfunction *
  319. ;* RETS: ES:BX = Address of XMMControl function (if AX=4310h) *
  320. ;* AL = 80h (if AX=4300) *
  321. ;* REGS: Preserved except for ES:BX (if AX=4310h) *
  322. ;* Preserved except for AL (if AX=4300h) *
  323. ;* *
  324. ;*----------------------------------------------------------------------*
  325. Int2fHandler proc far
  326. assume ds:nothing
  327. call DOSTI ; Flush any queued interrupts
  328. cmp ah,43h ; Function 43h?
  329. ifndef NEC_98
  330. jne I2fNextInt
  331. else ;NEC_98
  332. jne I2fChk_NH ; check for Windows 3.0 function INS NEC <91.09.27>
  333. endif ;NEC_98
  334. or al,al ; Subfunction 0?
  335. jne I2fNextSub ; No, continue
  336. mov al,80h ; Return 80h in AL (XMS Installed)
  337. PPFIRet:
  338. jmp DOIRET ; Label sets up the POPFF macro
  339. I2fNextSub:
  340. cmp al,10h ; Subfunction 10?
  341. jne I2fNextInt ; No, goto next handler
  342. push cs ; return XMS entry in es:bx
  343. pop es
  344. mov bx,offset XMMControl
  345. jmp DOIRET
  346. ; Continue down the Int 2f chain.
  347. I2fNextInt:
  348. call DOCLI ; Disable interrupts again
  349. jmp [PrevInt2f]
  350. ifdef NEC_98
  351. ; check N/H depend data for Windows 3.0 ;INS NEC <91.09.27>
  352. I2fChk_NH: ; check N/H depended data
  353. cmp ax,167fh
  354. jne I2fNextInt ; No, goto next handler
  355. cmp dx,0 ; check sub function
  356. jne I2fNextInt ; No, goto next handler
  357. mov word ptr [I2fCheckNH_Tbl], bx ; offset
  358. mov bx,es ;
  359. mov word ptr [I2fCheckNH_Tbl+2],bx ; segment
  360. mov bx,cs ;
  361. mov [I2f_Seg],bx ;
  362. push cs ;
  363. pop es ;
  364. mov bx,offset I2fCheckNH_Tbl ;
  365. jmp I2fNextInt ; goto next handler
  366. endif ;NEC_98
  367. Int2fHandler endp
  368. ;*----------------------------------------------------------------------*
  369. ;* *
  370. ;* ControlJumpTable - *
  371. ;* *
  372. ;* Contains the address for each of the XMS Functions. *
  373. ;* *
  374. ;* **************** WARNING ********************** *
  375. ;* *
  376. ;* Assumes that offsets of functions in lo mem seg are < 8000h *
  377. ;* & that offsets of segment in Hiseg are >= 8000h *
  378. ;* *
  379. ;*----------------------------------------------------------------------*
  380. ControlJumpTable label word
  381. dw Version ; Function 00h
  382. dw RequestHMA ; Function 01h
  383. dw ReleaseHMA ; Function 02h
  384. dw GlobalEnableA20 ; Function 03h
  385. dw GlobalDisableA20 ; Function 04h
  386. xLocalEnableA20 dw LocalEnableA20 ; Function 05h
  387. xLocalDisableA20 dw LocalDisableA20 ; Function 06h
  388. dw IsA20On ; Function 07h
  389. dw QueryExtMemory ; Function 08h
  390. dw AllocExtMemory ; Function 09h
  391. FreeMem dw FreeExtMemory ; Function 0Ah
  392. MoveIt dw MoveBlock ; Function 0Bh
  393. dw LockExtMemory ; Function 0Ch
  394. dw UnlockExtMemory ; Function 0Dh
  395. dw GetExtMemoryInfo ; Function 0Eh
  396. dw ReallocExtMemory ; Function 0Fh
  397. dw RequestUMB ; Function 10h
  398. dw ReleaseUMB ; Function 11h
  399. NumFns = ((offset $) - (offset ControlJumpTable))/2
  400. ;*----------------------------------------------------------------------*
  401. ;* *
  402. ;* XMMControl - *
  403. ;* *
  404. ;* Main Entry point for the Extended Memory Manager *
  405. ;* *
  406. ;* ARGS: AH = Function, AL = Optional parm *
  407. ;* RETS: AX = Function Success Code, BL = Optional Error Code *
  408. ;* REGS: AX, BX, DX and ES may not be preserved depending on func. *
  409. ;* *
  410. ;* INTERNALLY REENTRANT *
  411. ;* *
  412. ;*----------------------------------------------------------------------*
  413. XMMControl proc far
  414. jmp short XCControlEntry ; For "hookability"
  415. nop ; NOTE: The jump must be a
  416. nop ; short jump to indicate
  417. nop ; the end of any hook chain.
  418. ; The nop's allow a far jump
  419. ; to be patched in.
  420. XCControlEntry:
  421. if keep_cs ;--------------------------------------------------------
  422. push bp
  423. mov bp,sp
  424. mov bp,4[bp] ; get caller's cs
  425. mov callers_cs,bp ; (debug only)
  426. pop bp
  427. endif ;--------------------------------------------------------
  428. push cx ; preserve some registers
  429. push si
  430. push di
  431. push ds
  432. push es
  433. pushf
  434. cld
  435. push ds ; save ds in es
  436. pop es ; NOTE: ES cannot be used for parms!
  437. push cs ; ds=cs
  438. pop ds
  439. assume ds:_text
  440. push ax ; save the function number
  441. if debug_vers
  442. call debug_dump
  443. endif
  444. or ah,ah ; GetXMSVersion?
  445. jz XCCallFunc ; Yes, don't hook INT 15h yet
  446. cmp ah,NumFns ; valid function number??
  447. jb XCCheckHook
  448. pop ax ; No, Un-preserve AX and return an error
  449. xor ax,ax
  450. mov bl,ERR_NOTIMPLEMENTED
  451. jmp short XCExit
  452. XCCheckHook:
  453. pushf ; Is INT 15h already hooked?
  454. call DOCLI ; This is a critical section
  455. cmp word ptr [PrevInt15][2],0 ; Is the segment non-zero?
  456. jne XCCheckVD
  457. push dx ; save callers DX
  458. call HookInt15 ; claim all remaining ext mem
  459. pop dx
  460. ifdef NEC_98
  461. call HookInt220 ; start emulating Int220
  462. endif ;NEC_98
  463. XCCheckVD:
  464. popff ; End of critical section
  465. ifndef NEC_98
  466. cmp [fVDISK],0 ; was VDISK found?
  467. je XCCallFunc
  468. pop ax ; Yes, Un-preserve AX and return error
  469. xor ax,ax
  470. mov bl,ERR_VDISKFOUND
  471. xor dx,dx
  472. jmp short XCExit
  473. endif ;NEC_98
  474. ; Call the appropriate API function.
  475. XCCallFunc:
  476. pop ax ; Restore AX
  477. push ax ; save ax so functions get both ah & al
  478. mov al,ah
  479. xor ah,ah
  480. shl ax,1
  481. mov di,ax ; NOTE: DI cannot be used for parms!
  482. pop ax ; restore callers ax for function
  483. mov di,ControlJumpTable[di] ; get function address
  484. ifndef NEC_98
  485. or di,di
  486. jns CallLowSegFn ; brif it's in the low segment
  487. else ;NEC_98
  488. cmp di,HISEG_ORG
  489. jb CallLowSegFn ; brif it's in the low segment
  490. endif ;NEC_98
  491. cmp fInHMA, 0 ; is the hiseg in HMA ?
  492. jz InLoMem
  493. ;
  494. ;------ Turn on the A20 line if it is off
  495. ;
  496. push si
  497. push di
  498. push ax
  499. push bx
  500. push cx
  501. call LocalEnableA20 ; Note: This is always necessary
  502. cmp ax, 1
  503. pop cx ; for the Memory Move function. In
  504. pop bx ; the case where this driver loads
  505. pop ax ; high, it is necessary for all calls
  506. pop di ; to the high segment.
  507. pop si
  508. jne a20_error
  509. InLoMem:
  510. push cs ; set up far return
  511. call call_hi_in_di ; and call the function
  512. cmp fInHMA, 0 ; is the hiseg in HMA ?
  513. jz XCExit
  514. push ax ; save the registers which may be
  515. push bx ; returning values
  516. call LocalDisableA20 ; and restore a20
  517. cmp ax, 1
  518. pop bx
  519. pop ax
  520. je short XCExit
  521. a20_error:
  522. xor ax, ax
  523. xor dx, dx
  524. mov bl, ERR_A20
  525. jmp short XCExit
  526. CallLowSegFn:
  527. call di ; call routine in this segment
  528. XCExit:
  529. ; if debug_vers or tdump ;------------------------------------
  530. ; pusha
  531. ; call dump_tables
  532. ; popa
  533. ; endif ;------------------------------------------------------
  534. popff ; NOTE: Flags must be restored
  535. pop es ; immedately after call API functions.
  536. pop ds
  537. pop di
  538. pop si
  539. pop cx
  540. ; if debug_vers ;---------------------------------------------------
  541. ; pushf
  542. ; pusha
  543. ; mov al,'.'
  544. ; call cofa
  545. ; mov al,cs:byte ptr fun_number
  546. ; sub al,0bh ; don't get key on 0bh, 0ch or 0dh
  547. ; cmp al,2
  548. ; jbe no_keywait
  549. ; mov ah,1 ; wait for console key now!!!!!!
  550. ;; int 21h
  551. ;no_keywait:
  552. ; popa
  553. ; popf
  554. ; endif ;------------------------------------------------------
  555. ret
  556. XMMControl endp
  557. if tdump or debug_vers ;------------------------------------
  558. fun_number db 0 ; function number for debug info
  559. dump_tables:
  560. if not tdump
  561. cmp fun_number,9 ; only display on allocate calls
  562. jnz dd_done ; unless full tdump is enabled
  563. endif
  564. mov dx,offset heading
  565. mov ah,9
  566. int 21h
  567. push es
  568. mov es,hiseg
  569. assume es:funky
  570. mov si,[KiddValley]
  571. mov cx,[cHandles]
  572. mov bx,SIZE Handle
  573. xlup:
  574. mov al,[si].Flags ; get flags
  575. cmp al,4 ; don't show UNUSED entries
  576. jz x_entry_done
  577. mov dx,offset msg_FREE
  578. cmp al,1 ; free?
  579. jz x_showflags
  580. mov dx,offset msg_USED
  581. cmp al,2 ; used?
  582. jz x_showflags
  583. mov dx,offset msg_BAD
  584. x_showflags:
  585. mov ah,9
  586. int 21h
  587. mov al,[si].cLock ; get lock count
  588. call hex_byte
  589. call space
  590. mov ax,[si].Base ; get base
  591. call hex_word
  592. call space
  593. mov ax,[si].Len ; get length
  594. call hex_word
  595. if keep_cs
  596. call space
  597. mov ax,[si].Acs ; get the allocator's cs:
  598. call hex_word
  599. endif
  600. x_newline:
  601. mov al,13
  602. call cofa
  603. mov al,10
  604. call cofa
  605. x_entry_done:
  606. add si,bx
  607. loop xlup
  608. pop es
  609. assume es:nothing
  610. mov dx,offset donemsg
  611. mov ah,9
  612. int 21h
  613. dd_done:
  614. ret
  615. heading db 'Flags Lock Base Len CS:',13,10,'$'
  616. msg_FREE db 'FREE $'
  617. msg_USED db 'USED $'
  618. msg_BAD db 'BAD $'
  619. donemsg db 'End of XMS table$'
  620. endif
  621. if debug_vers
  622. debug_dump proc near
  623. pusha
  624. mov fun_number,ah ; save (non-reentrantly!) function number
  625. ; ; so that we can display different debug
  626. ; ; information on exit depending on which
  627. ; ; function we've been doing
  628. mov al,ah ; just display function number
  629. call hex_nib
  630. popa
  631. ret
  632. if 0 ; enable this if you want to see the
  633. ; ; command block for memory moves
  634. cmp ah,0bh ; memory move?
  635. jnz debug_dump_done ; done if not
  636. pusha
  637. call crlf
  638. mov ax,es:2[si] ; get count-hi
  639. call hex_word
  640. mov ax,es:[si] ; get count-low
  641. call hex_word
  642. add si,4 ; point to source address field
  643. mov cx,2 ; now display two handle/addresses
  644. dd1:
  645. call space
  646. lods es:word ptr [si] ; get a handle
  647. call hex_word
  648. mov al,'-'
  649. call cofa
  650. mov ax,es:2[si] ; get high address
  651. call hex_word
  652. mov al,':'
  653. call cofa
  654. lods es:word ptr [si] ; get low address
  655. call hex_word
  656. add si,2 ; skip to next entry for loop
  657. loop dd1
  658. popa
  659. debug_dump_done:
  660. endif
  661. ret
  662. debug_dump endp
  663. endif
  664. if debug_vers or tdump
  665. ifdef NEC_98
  666. RowCol dw 1700H ; ins NEC <90.07.11> Y.Ueno
  667. endif ;NEC_98
  668. hex_word:
  669. push ax
  670. mov al,ah
  671. call hex_byte
  672. pop ax
  673. hex_byte:
  674. push ax
  675. shr ax,4 ; XMS present implies '286 or better
  676. call hex_nib
  677. pop ax
  678. hex_nib:
  679. and al,0fh
  680. add al,90h
  681. daa
  682. adc al,3ah
  683. daa
  684. cofa:
  685. ; mov dl,al
  686. ; mov ah,2
  687. ; int 21h
  688. ifndef NEC_98
  689. mov ah,0eh
  690. mov bx,7
  691. int 10h
  692. ret
  693. else ;NEC_98
  694. ;======================CHG NEC <90.07.11> Y.Ueno =============================
  695. push bx ; save callers regs
  696. push cx
  697. push dx
  698. push si
  699. push di
  700. push es
  701. push ds
  702. push dx ; save this segment for later
  703. mov ds, dx ; DS -> data segment
  704. mov dx, ds:[RowCol] ; DX = current row/col
  705. cmp al, CR ; is character a CR?
  706. jne short kp1
  707. mov dl, 0 ; yes, go to column 0
  708. jmp short kp3 ; jump to common code
  709. kp1:
  710. cmp al, LF ; is character a LF?
  711. jne short kp2
  712. inc dh ; yes, go to next row
  713. jmp short kp3 ; jump to common code
  714. kp2:
  715. cmp al, TAB ; is it a tab
  716. jne short kp12
  717. and dl, 0f8h ; mask off low 3 bits (8 ch)
  718. add dl, 8 ; move to next tab position
  719. jmp short kp3 ; jmp to common code
  720. kp12:
  721. cmp al, BS ; is it backspace
  722. jne short kp13
  723. dec dl ; back up one column
  724. jmp short kp3 ; goto common code
  725. kp13:
  726. ; Must be ordinary character. Write it to screen, update position
  727. ;@@@
  728. XOR AH,AH ;
  729. push ax ; save char/attr
  730. mov al, dh ; AL = row
  731. mov ah, 80 ; multiplier, 80 char per row
  732. mul ah ; AX = cell at start of row
  733. mov bh, 0
  734. mov bl, dl ; BX = column
  735. add bx, ax ; BX = cell
  736. shl bx, 1 ; BX = byte offset of cell
  737. mov ax, 0a000h ; screen para for real mode
  738. mov es, ax ; ES -> screen
  739. pop es:[bx] ; write character
  740. inc dl ; update column
  741. kp3:
  742. ; Common code, first check for line wrap:
  743. cmp dl, 80 ; beyond rhs of screen?
  744. jl short kp4
  745. mov dl, 0 ; go to col 0
  746. inc dh ; and move to next line
  747. kp4:
  748. ; Now check for scroll needed:
  749. cmp dh, 24 ; are we off end of screen?
  750. jl short kp5
  751. ; Now scroll screen
  752. mov ax, 0a000h ; screen para for real mode
  753. mov ds, ax ; DS -> screen
  754. mov es, ax ; ES -> screen
  755. mov di, 0 ; ES:DI = copy destination
  756. mov si, 160 ; DS:SI = copy source
  757. mov cx, 2000-160 ; copy word count
  758. cld
  759. rep movsw ; scroll
  760. ; Blank bottom line
  761. mov al, ' '
  762. ;@@@
  763. mov ah, 0 ; AX = blank character
  764. mov cx, 80 ; number of cells to blank
  765. mov di, 4000-320 ; ES:DI = start point
  766. rep stosw
  767. ; Update position
  768. mov dh, 23 ; new row
  769. kp5:
  770. pop ds ; set DS to data again
  771. mov ds:[RowCol], dx ; update row/col
  772. ;@@@
  773. call SetCursor
  774. pop ds ; restore regs
  775. pop es
  776. pop di
  777. pop si
  778. pop dx
  779. pop cx
  780. pop bx
  781. ret
  782. ;*** SetCursor - updates cursor position
  783. ;
  784. ; This routine reprograms the 6845 cursor position, and
  785. ; stores the new cursor position in the ROM bios data area.
  786. ;
  787. ; ENTRY DUAL MODE
  788. ; DH, DL = row, col
  789. ;
  790. ; EXIT cursor updated
  791. ;
  792. ; USES ax, bx, cx, flags
  793. ;
  794. CRT_COLS equ 04ah
  795. CURSOR_POSN equ 050h
  796. CRT_START equ 04eh
  797. ADDR_6845 equ 063h
  798. push ds
  799. mov bx, 40h
  800. mov ds, bx
  801. ; Save new position in BIOS data area
  802. mov ds:[CURSOR_POSN], dx
  803. ; Calculate offset on screen
  804. mov al, dh ; row
  805. ; mul byte ptr ds:[CRT_COLS] ; row * cols
  806. MOV AH,80
  807. mul AH ; row * cols
  808. mov bl, dl ; bl = column
  809. mov bh, 0 ; bx = column
  810. add ax, bx ; ax = offset in screen
  811. sal ax, 1 ; double for attribute bytes
  812. ; mov cx, ds:[CRT_START] ; cx = start point of screen
  813. mov cx, 0h ; cx = start point of screen
  814. ADD AX,CX
  815. MOV DX,AX
  816. ; sar cx, 1 ; convert to char count only
  817. ; Now program 6845
  818. mov al,49h
  819. JMP SHORT $+2
  820. JMP SHORT $+2
  821. JMP SHORT $+2
  822. JMP SHORT $+2
  823. JMP SHORT $+2
  824. JMP SHORT $+2
  825. JMP SHORT $+2
  826. JMP SHORT $+2
  827. OUT 62H,AL
  828. MOV AX,DX
  829. SHR AX,1
  830. JMP SHORT $+2
  831. JMP SHORT $+2
  832. JMP SHORT $+2
  833. JMP SHORT $+2
  834. JMP SHORT $+2
  835. JMP SHORT $+2
  836. JMP SHORT $+2
  837. JMP SHORT $+2
  838. OUT 60H,AL
  839. MOV AL,AH
  840. JMP SHORT $+2
  841. JMP SHORT $+2
  842. JMP SHORT $+2
  843. JMP SHORT $+2
  844. JMP SHORT $+2
  845. JMP SHORT $+2
  846. JMP SHORT $+2
  847. JMP SHORT $+2
  848. OUT 60H,AL
  849. POP DS
  850. RET
  851. ;=============================================================================
  852. endif ;NEC_98
  853. space:
  854. mov al,' '
  855. jmp cofa
  856. crlf:
  857. mov al,13
  858. call cofa
  859. mov al,10
  860. jmp cofa
  861. endif ;------------------------------------------------------
  862. ; little utility stub for calling routine in the other segment.
  863. ; called with the branch offset address in di
  864. ; a far return address is already on the stack. Now branch to
  865. ; hiseg:(di)
  866. public hiseg ; allow initialization code to relocate hiseg
  867. hiseg dw funky
  868. public call_hi_in_di
  869. call_hi_in_di proc near
  870. push hiseg
  871. push di
  872. call_hi_in_di endp
  873. call_hi_far proc far
  874. ret
  875. call_hi_far endp
  876. ;*----------------------------------------------------------------------*
  877. ;* *
  878. ;* HookInt15 - *
  879. ;* *
  880. ;* Insert the INT 15 hook *
  881. ;* *
  882. ;* ARGS: None *
  883. ;* RETS: None *
  884. ;* REGS: AX, BX, CX, DX, DI, SI, and Flags are clobbered *
  885. ;* *
  886. ;* EXTERNALLY NON-REENTRANT *
  887. ;* Interrupts must be disabled before calling this function. *
  888. ;* *
  889. ;*----------------------------------------------------------------------*
  890. HookInt15 proc near
  891. push es
  892. ifndef NEC_98
  893. call IsVDISKIn ; has a VDISK been installed?
  894. cmp [fVDISK],0
  895. je HINoVD ; No, continue
  896. pop es ; Yes, return without hooking
  897. ret
  898. HINoVD: ; notify softpc of hooking I15
  899. mov ax,offset Int15Handler ; args: cs:di new I15 vector
  900. XMSSVC XMS_NOTIFYHOOKI15 ; returns CX=ExtMem in K
  901. ; Save the curr INT 15 vector, and put ours in the IVT
  902. les si,dword ptr pInt15Vector
  903. xchg ax,es:[si][0]
  904. mov word ptr [PrevInt15][0],ax
  905. mov ax,cs
  906. xchg ax,es:[si][2]
  907. mov word ptr [PrevInt15][2],ax
  908. mov ax, cx
  909. cmp ax,15*1024 ; Limit himem.sys to using 15 meg
  910. jb @f ; of extended memory for apps
  911. mov ax,15*1024 ; that don't deal with > 24 bit
  912. @@: ; addresses
  913. sub ax,[MemCorr] ; 6300 Plus may have memory at FA0000h
  914. else ;NEC_98
  915. ;====================== chg NEC <90.07.11> Y.Ueno ======================
  916. push es
  917. mov ax,40h
  918. mov es,ax
  919. sub ah,ah
  920. mov al,byte ptr es:[0001] ; get extend memory size
  921. shl ax,7 ; convert to k byte size
  922. pop es
  923. endif ;NEC_98
  924. cmp ax,64
  925. jb HIInitMemory ; Less than 64K free? Then no HMA.
  926. cmp Int15MemSize, 0 ; are we supporting int 15 memory
  927. jnz HIInitMemory ; then we dont support HMA
  928. mov [fHMAExists],1
  929. HIInitMemory:
  930. ; Init the first handle to be one huge free block.
  931. ifndef NEC_98
  932. or ax, ax ; don't do it if no Int 15 memory avail
  933. jz HISkipInit
  934. endif ;NEC_98
  935. mov cx,1024 ; base is just above 1 meg
  936. xor bx, bx ; assume no HMA
  937. cmp [fHMAExists],0 ; Reserve room for HMA if it exists
  938. je @f
  939. mov bx, 64
  940. @@: cmp bx, Int15MemSize
  941. jae @f
  942. mov bx, Int15MemSize
  943. @@: add cx,bx
  944. sub ax,bx
  945. ifdef NEC_98
  946. push es
  947. push ax
  948. mov ax, 40h
  949. mov es, ax
  950. pop ax
  951. push ax
  952. add ax,127 ; set 128k boundly
  953. shr ax,7
  954. sub byte ptr es:[0001h],al
  955. pop ax
  956. pop es
  957. endif ;NEC_98
  958. call AddMem ; add that to memory table
  959. ifndef NEC_98
  960. HISkipInit:
  961. else ;NEC_98
  962. ; Save the current INT 15 vector.
  963. les si,dword ptr pInt15Vector
  964. ; Exchange the old vector with the new one.
  965. mov ax,offset Int15Handler
  966. xchg ax,es:[si][0]
  967. mov word ptr [PrevInt15][0],ax
  968. mov ax,cs
  969. xchg ax,es:[si][2]
  970. mov word ptr [PrevInt15][2],ax
  971. endif ;NEC_98
  972. pop es
  973. ret
  974. HookInt15 endp
  975. ifndef NEC_98
  976. ;*----------------------------------------------------------------------*
  977. ;* *
  978. ;* IsVDISKIn - *
  979. ;* *
  980. ;* Looks for drivers which use the IBM VDISK method of allocating *
  981. ;* Extended Memory. XMS is incompatible with the VDISK method. It is *
  982. ;* necessary to check two different locations since some programs only *
  983. ;* one or the other, although they should do both. *
  984. ;* *
  985. ;* ARGS: None *
  986. ;* RETS: None. Sets "fVDISK" accordingly *
  987. ;* REGS: AX, BX, CX, SI, DI and Flags are clobbered *
  988. ;* *
  989. ;* INTERNALLY REENTRANT *
  990. ;* *
  991. ;*----------------------------------------------------------------------*
  992. pVDISK label dword
  993. dw 00013h
  994. dw 0FFFFh
  995. szVDISK db 'VDISK'
  996. IsVDISKIn proc near
  997. ; Look for "VDISK" signature at offset 12h in Int 19h segment
  998. push es
  999. xor ax,ax
  1000. mov es,ax
  1001. mov es,es:[(19h * 4)+2]
  1002. mov di,12h
  1003. mov si,offset szVDISK
  1004. mov cx,5
  1005. cld
  1006. repz cmpsb
  1007. pop es
  1008. jz IVIFoundIt
  1009. ; Look for "VDISK" starting at the 4th byte of extended memory.
  1010. call LocalEnableA20 ; Turn on A20
  1011. push es
  1012. les di,cs:pVDISK ; set up the comparison
  1013. mov si,offset szVDISK
  1014. mov cx,5
  1015. cld
  1016. repz cmpsb ; Do the comparison
  1017. pop es
  1018. pushf
  1019. call LocalDisableA20
  1020. popff
  1021. jz IVIFoundIt
  1022. mov [fVDISK],0 ; No VDISK device found
  1023. ret
  1024. IVIFoundIt:
  1025. mov [fVDISK],1 ; "VDISK" was found
  1026. ret
  1027. IsVDISKIn endp
  1028. endif ;NEC_98
  1029. ;*----------------------------------------------------------------------*
  1030. ;* *
  1031. ;* Int15Handler - *
  1032. ;* *
  1033. ;* Hooks Function 88h to return zero as the amount of extended *
  1034. ;* memory available in the system. *
  1035. ;* *
  1036. ;* Hooks Function 87h and preserves the state of A20 across the *
  1037. ;* block move. *
  1038. ;* *
  1039. ;* ARGS: AH = Function, AL = Subfunction *
  1040. ;* RETS: AX = 0 (if AH == 88h) *
  1041. ;* REGS: AX is clobbered *
  1042. ;* *
  1043. ;*----------------------------------------------------------------------*
  1044. ifdef NEC_98
  1045. I15RegSave dw ?
  1046. endif ;NEC_98
  1047. Int15Handler proc far
  1048. ifndef NEC_98
  1049. cmp ah,88h ; request == report free ext mem?
  1050. je I15ExtMem
  1051. cmp ah,87h ; Block move?
  1052. je I15BlkMov
  1053. jmp cs:[PrevInt15] ; continue down the int 15h chain
  1054. I15ExtMem:
  1055. mov ax, cs:Int15MemSize ; return 'free' Int 15h extended memory
  1056. jmp DOIRET
  1057. I15BlkMov:
  1058. call DOCLI ; Make sure interrupts are off
  1059. sub sp,4 ; Make space for A20 flag & flags word
  1060. pusha ; Preserve the caller's registers
  1061. call IsA20On ; Get current A20 state
  1062. mov bp,sp ; Stk= [pusha] [fl] [a20] [ip] [cs] [fl]
  1063. mov [bp+18],ax ; Save A20 state
  1064. mov ax,[bp+24] ; Get caller's entry flags and save on
  1065. mov [bp+16],ax ; stack, forms part of iret frame
  1066. popa ; Restore the caller's registers
  1067. ; Simulate an interrupt to lower level Int 15h handler. Note that
  1068. ; the flags image is already on the stack from code above. The Int
  1069. ; 15h handler may or may return with interrupts enabled.
  1070. call cs:[PrevInt15]
  1071. push ax ; Save returned AX
  1072. pushf ; Save flags returned from lower level
  1073. push bp ; Stack =
  1074. mov bp,sp ; [bp] [fl] [ax] [a20] [ip] [cs] [fl]
  1075. mov ax,[bp+2] ; Setup to pass lower level flags
  1076. mov [bp+12],ax ; back to caller on iret
  1077. cmp word ptr [bp+6],0 ; While we're here test old A20 state
  1078. pop bp
  1079. pop ax ; Discard flags
  1080. pop ax ; Restore AX
  1081. jz I15HExit ; A20 was off, don't mess with it
  1082. call DOCLI ; A20 handlers called with ints off
  1083. pusha ; Preserve previous handler's return
  1084. mov ax,1
  1085. call A20Handler ; turn A20 back on
  1086. popa ; Restore the previous handler's return
  1087. I15HExit:
  1088. add sp,2 ; 'pop' A20 state flag
  1089. jmp DOIRET ; Uses flags from lower level handler
  1090. else ;NEC_98
  1091. cmp ah,90h ; Is it a Block Move ?
  1092. jne I15HNext ; No , continue
  1093. call DOCLI ; Make sure interrupts are off
  1094. pusha ; Preserve the registers
  1095. mov al, 8 ; ins NEC <90.11.14> Y.Ueno
  1096. out 37h, al ; "
  1097. call IsA20On
  1098. mov cs:[I15RegSave],ax ; store A20's state
  1099. popa ; Restore the registers
  1100. ; Call the previous Int 15h handler.
  1101. pushf ; Simualate an interrupt
  1102. call cs:[PrevInt15]
  1103. pushf ; bug ? ins NEC <90.07.12> Y.Ueno
  1104. pusha ; Preserve previous handler's return
  1105. cmp cs:[I15RegSave],0 ; Restore A20
  1106. je I15HExit ; It was off, continue
  1107. mov ax,1
  1108. call A20Handler ; turn A20 back on
  1109. I15HExit:
  1110. mov al, 09h ; ins NEC <90.11.14> Y.Ueno
  1111. out 37h, al ; "
  1112. popa ; Restore the previous handler's return
  1113. popf ; bug ? chg NEC <90.07.12> Y.Ueno
  1114. retf 2 ; "
  1115. ;;; iret ; "
  1116. I15HNext:
  1117. jmp cs:[PrevInt15] ; continue down the int 15h chain
  1118. endif ;NEC_98
  1119. Int15Handler endp
  1120. ifdef NEC_98
  1121. ;*----------------------------------------------------------------------*
  1122. ;* *
  1123. ;* HookInt220 - *
  1124. ;* *
  1125. ;* Insert the INT 220 hook *
  1126. ;* *
  1127. ;* ARGS: None *
  1128. ;* *
  1129. ;* RETS: None *
  1130. ;* *
  1131. ;* REGS: AX, SI, and Flags are clobbered *
  1132. ;* *
  1133. ;* EXTERNALLY NON-REENTRANT *
  1134. ;* Interrupts must be disabled before calling this function. *
  1135. ;* *
  1136. ;*----------------------------------------------------------------------*
  1137. HookInt220 proc near
  1138. push cx
  1139. mov cl,81h
  1140. xor ax,ax
  1141. int 220 ; Get size of extended memory
  1142. pop cx
  1143. or ax,ax ; no extendec memory?
  1144. jz HI220Exit ; don't hook Int220
  1145. ; Exchange the old vector with the new one.
  1146. push es
  1147. les si,dword ptr pInt220Vector ; ES:SI points Int220 vector
  1148. mov ax,offset Int220Handler
  1149. xchg ax,es:[si][0]
  1150. mov word ptr [PrevInt220][0],ax
  1151. mov ax,cs
  1152. xchg ax,es:[si][2]
  1153. mov word ptr [PrevInt220][2],ax
  1154. pop es
  1155. HI220Exit:
  1156. ret
  1157. HookInt220 endp
  1158. ;*----------------------------------------------------------------------*
  1159. ;* *
  1160. ;* Int220Handler - *
  1161. ;* *
  1162. ;* Hooks Function 81h/82h and emulate it by twiddling EMB table *
  1163. ;* *
  1164. ;* ARGS: CL = Function, AX = Subfunction *
  1165. ;* BX = Size of memory requested in 128k block, if function 81h*
  1166. ;* *
  1167. ;* RETS: Function 81h *
  1168. ;* AX = 0 (if success) *
  1169. ;* BX = Start addr *
  1170. ;* DX = End addr *
  1171. ;* *
  1172. ;* AX = 01h (if fail) *
  1173. ;* BX = size of available memory in blocks of 128k *
  1174. ;* *
  1175. ;* Function 82h *
  1176. ;* AX = size of availabel memory in blocks of 128k *
  1177. ;* BX = Start addr *
  1178. ;* DX = End addr *
  1179. ;* *
  1180. ;* REGS: AX, BX, (DX) is clobbered *
  1181. ;* *
  1182. ;*----------------------------------------------------------------------*
  1183. USER_DX equ 6
  1184. USER_BX equ 10
  1185. USER_AX equ 12
  1186. I220EmlTbl dw offset Eml_81
  1187. dw offset Eml_82
  1188. Int220Handler proc far
  1189. cmp cl,81h ; Function 81h?
  1190. jne I220HCmp82 ;
  1191. cmp ax,0001h ; Sub function 01h?
  1192. jne I220HNext ;
  1193. jmp short I220HStart ; yes
  1194. I220HCmp82:
  1195. cmp cl,82h ; Function 82h?
  1196. jne I220HNext ;
  1197. cmp ax,0000h ; Subfunction 00Hh?
  1198. jne I220HNext ;
  1199. ;
  1200. I220HStart: ; yes
  1201. sti
  1202. push es
  1203. push ds
  1204. push ax
  1205. push bx
  1206. push cx
  1207. push dx
  1208. push di
  1209. push si
  1210. push bp
  1211. mov bp,sp
  1212. mov dx,ss
  1213. mov es,dx
  1214. push cs
  1215. pop ds
  1216. mov si,offset I220EmlTbl
  1217. sub cl,81h
  1218. xor ch,ch
  1219. shl cx,1
  1220. add si,cx
  1221. call [si] ; call our Int 220 handler.
  1222. pop bp
  1223. pop si
  1224. pop di
  1225. pop dx
  1226. pop cx
  1227. pop bx
  1228. pop ax
  1229. pop ds
  1230. pop es
  1231. iret
  1232. I220HNext:
  1233. jmp cs:[PrevInt220] ; continue down the int 220 chain
  1234. Int220Handler endp
  1235. ;*----------------------------------------------------------------------*
  1236. ;* *
  1237. ;* EML_81 - *
  1238. ;* *
  1239. ;* Emulate Int220h Function 81h *
  1240. ;* *
  1241. ;* ARGS: Int 220 regs but DS, ES, BP, CX *
  1242. ;* *
  1243. ;* RETS: Values are set into AX, BX, DX on the stacks *
  1244. ;* *
  1245. ;* REGS: AX, BX, CX, DX, SI, DI and Flags are clobbered *
  1246. ;* *
  1247. ;*----------------------------------------------------------------------*
  1248. EML_81 proc near
  1249. push bx ; save size of memory requested
  1250. mov ax,bx
  1251. call GetInt220mem ; return available memory size in CX
  1252. ; handle in DX, SI
  1253. pop ax
  1254. cmp cx,ax ; is there enough memory?
  1255. jb E81Nomem ; no
  1256. or ax,ax ; requested size = 0 ?
  1257. jz E81ReqZero ; yes
  1258. mov bx,dx ; ax:size,bx:free handle,si:unused handle
  1259. call AllocInt220mem ; allocate memory for this Int 220
  1260. mov [bp].USER_BX,bx ; start addr
  1261. mov [bp].USER_DX,dx ; ending addr
  1262. mov word ptr [bp].USER_AX,0000h ; indicates sucsess
  1263. jmp short E81Exit
  1264. E81ReqZero:
  1265. mov word ptr [bp].USER_BX,0010h ; start addr
  1266. mov word ptr [bp].USER_DX,0010h ; ending addr
  1267. mov word ptr [bp].USER_AX,0000h ; indicates sucsess
  1268. jmp short E81Exit
  1269. E81Nomem:
  1270. mov [bp].USER_BX,cx ; size of abailable memories
  1271. mov word ptr [bp].USER_AX,0001h ; indicate not enough memories
  1272. E81Exit:
  1273. ret
  1274. EML_81 endp
  1275. ;*----------------------------------------------------------------------*
  1276. ;* *
  1277. ;* EML_82 - *
  1278. ;* *
  1279. ;* Emulate Int220h Function 82h *
  1280. ;* *
  1281. ;* ARGS: Int 220 regs but DS, ES, BP, CX *
  1282. ;* *
  1283. ;* RETS: Values are set into AX, BX, DX on the stacks *
  1284. ;* *
  1285. ;* REGS: AX, BX, CX, DX, SI, DI and Flags are clobbered *
  1286. ;* *
  1287. ;*----------------------------------------------------------------------*
  1288. OwnersPSP dw 0 ;
  1289. OwnersHandle dw 0 ;
  1290. EML_82 proc near
  1291. mov ax,0ffffh ; fake request size
  1292. call GetInt220mem ; return maximum available memory in AX
  1293. ; handle in BX, SI
  1294. or ax,ax ; available size = 0 ?
  1295. jz E82Nomem ; yes
  1296. ; ax:size,bx:free handle,si:unused handle
  1297. call AllocInt220mem ; allocate memory for this Int 220
  1298. mov [bp].USER_BX,bx ; start addr
  1299. mov [bp].USER_DX,dx ; ending addr
  1300. mov [bp].USER_AX,ax ; size of memory allocated
  1301. mov [OwnersHandle],cx ; save handle of allocated block
  1302. mov ax,6200h
  1303. int 21h
  1304. mov [OwnersPSP],bx ; save current process's PSP
  1305. ; we'll hook INt20h/21h from now on
  1306. ; Exchange the old vector with the new one.
  1307. push es
  1308. cli
  1309. les si,dword ptr pInt20Vector ; replace Int20h vector
  1310. mov ax,offset Int20_Hooker ; with addr of Int20_Hooker
  1311. xchg ax,es:[si][0] ;
  1312. mov word ptr [PrevInt20][0],ax ;
  1313. mov ax,cs ;
  1314. xchg ax,es:[si][2] ;
  1315. mov word ptr [PrevInt20][2],ax ;
  1316. les si,dword ptr pInt21Vector ; replace Int21h vector
  1317. mov ax,offset Int21_Hooker ; with addr of Int21_Hooker
  1318. xchg ax,es:[si][0] ;
  1319. mov word ptr [PrevInt21][0],ax ;
  1320. mov ax,cs ;
  1321. xchg ax,es:[si][2] ;
  1322. mov word ptr [PrevInt21][2],ax ;
  1323. sti
  1324. pop es
  1325. jmp short E82Exit
  1326. E82Nomem:
  1327. mov word ptr [bp].USER_BX,0010h ; start addr
  1328. mov word ptr [bp].USER_DX,0010h ; ending addr
  1329. mov word ptr [bp].USER_AX,0000h ; no blocks was allocated
  1330. E82Exit:
  1331. ret
  1332. EML_82 endp
  1333. ;*----------------------------------------------------------------------*
  1334. ;* *
  1335. ;* Int20_Hooker - *
  1336. ;* Int21_Hooker - *
  1337. ;* *
  1338. ;* Hooks Int20h/21h *
  1339. ;* *
  1340. ;* ARGS: AH = Function *
  1341. ;* *
  1342. ;* REGS: All Regs are preserved *
  1343. ;* *
  1344. ;* EXIT: Fall through previous Int20h/21h handler *
  1345. ;* *
  1346. ;*----------------------------------------------------------------------*
  1347. Intnum db 0 ; number of Int we are handling
  1348. Int21_Hooker proc far
  1349. mov cs:[Intnum],21h
  1350. cmp ah,00h
  1351. je I2xHStart
  1352. cmp ah,4ch
  1353. jne I2xHNext
  1354. Int20_Hooker proc far
  1355. I2xHStart:
  1356. push ax
  1357. push bx
  1358. mov ax,6200h
  1359. pushf
  1360. call cs:[PrevInt21] ; Int21h GetPSP Function
  1361. cmp bx,cs:[OwnersPSP] ; this process own memory block?
  1362. pop bx
  1363. pop ax
  1364. jne I2xHNext
  1365. push ax
  1366. push bx
  1367. push cx
  1368. push dx
  1369. push di
  1370. push si
  1371. push ds
  1372. push cs
  1373. pop ds ; ds <- _text seg
  1374. push es
  1375. mov es,[hiseg] ; es <- funky seg
  1376. mov dx,[OwnersHandle] ; handle of block owned by this process
  1377. mov di,FreeMem ; get funtion in funky segment
  1378. push cs ; set up far return
  1379. call call_hi_in_di ; call into high segment
  1380. ;------------------------------------------------------------------------------
  1381. ; Restore the old vector.
  1382. ; we won't hook Int20h/21h no longer.
  1383. cli
  1384. les di,dword ptr pInt20Vector ; restore Int20h vector
  1385. mov ax,word ptr [PrevInt20][0] ;
  1386. stosw ;
  1387. mov ax,word ptr [PrevInt20][2] ;
  1388. stosw ;
  1389. les di,dword ptr pInt21Vector ; restore Int21h vector
  1390. mov ax,word ptr [PrevInt21][0] ;
  1391. stosw ;
  1392. mov ax,word ptr [PrevInt21][2] ;
  1393. stosw ;
  1394. ;------------------------------------------------------------------------------
  1395. pop es
  1396. pop ds
  1397. pop si
  1398. pop di
  1399. pop dx
  1400. pop cx
  1401. pop bx
  1402. pop ax
  1403. I2xHNext:
  1404. cmp cs:[Intnum],21h
  1405. je I21HNext
  1406. I20HNext:
  1407. jmp cs:[PrevInt20] ; continue down the int 20h chain
  1408. I21HNext:
  1409. mov cs:[Intnum],0
  1410. jmp cs:[PrevInt21] ; continue down the int 21h chain
  1411. Int20_Hooker endp
  1412. Int21_Hooker endp
  1413. assume ds:_text
  1414. ;*----------------------------------------------------------------------*
  1415. ;* *
  1416. ;* GetInt220mem - *
  1417. ;* *
  1418. ;* Serach for available memory block for Int220 in EMB table *
  1419. ;* *
  1420. ;* ARGS: AX = size of memories requested in blocks of 128k *
  1421. ;* *
  1422. ;* RETS: AX = size of maximam EMB block in blocks of 128k *
  1423. ;* BX = handle of maximam availabel EMB block *
  1424. ;* CX = size of available EMB block whith the nearest *
  1425. ;* size to request, in blocks of 128k *
  1426. ;* DX = handle of available EMB block whith the nearest *
  1427. ;* size to request *
  1428. ;* SI = handle of unused EMB block *
  1429. ;* *
  1430. ;* REGS: AX, BX, CX, DX, SI, DI and Flags are clobbered *
  1431. ;* *
  1432. ;*----------------------------------------------------------------------*
  1433. hMax dw 0 ; Handle of block that has max size
  1434. MaxSize dw 0 ; Max. size found so far
  1435. hNearest dw 0 ; Handle of block that has nearest size
  1436. ; with request size
  1437. NearestSize dw 0 ; Nearest size with request size
  1438. hUnused dw 0 ; Handle of unused block
  1439. GetInt220mem proc near
  1440. mov [hMax],0000h
  1441. mov [MaxSize],0000h
  1442. mov [hNearest],0000h
  1443. mov [NearestSize],0ffffh
  1444. mov [hUnused],0000h
  1445. ; scan for largest FREE block
  1446. push es
  1447. mov es,[hiseg]
  1448. assume es:funky
  1449. mov bx,[KiddValley]
  1450. mov cx,[cHandles] ; Loop through the handle table
  1451. GI220Loop:
  1452. cmp [bx].Flags,FREEFLAG ; Is this block free?
  1453. jne GI220Anused ; no
  1454. mov di,[bx].base
  1455. mov si,di
  1456. add si,[bx].Len ; si has end addr of free block
  1457. and si,0ff80h ; round off to 128k boundary
  1458. add di,127 ; di had start addr of free block
  1459. and di,0ff80h ; 128k boundary
  1460. sub si,di ; available size in kbytes
  1461. jnc GI220Gotmem
  1462. xor si,si ; size = 0
  1463. GI220Gotmem:
  1464. shr si,7 ; convert to number of blocks
  1465. cmp si,[MaxSize] ; is this the largest so far?
  1466. jbe GI220Nearest
  1467. mov [MaxSize],si ; Yes, save it away
  1468. mov [hMax],bx ; save handle
  1469. GI220Nearest:
  1470. cmp si,ax ; is this larger than request?
  1471. jb GI220Bottom
  1472. cmp si,[NearestSize] ; is this the nearest so far?
  1473. jae GI220Bottom
  1474. mov [NearestSize],si ; Yes save it away
  1475. mov [hNearest],bx ; save handle
  1476. jmp short GI220Bottom
  1477. GI220Anused:
  1478. cmp [bx].Flags,UNUSEDFLAG ; Is this block unused?
  1479. jne GI220Bottom
  1480. cmp [hUnused],0 ; did we already find an unused handle?
  1481. jne GI220Bottom
  1482. mov [hUnused],bx ; save this guy away
  1483. GI220Bottom:
  1484. add bx,SIZE Handle
  1485. loop GI220Loop
  1486. cmp [hMax],0 ; Is there some free blocks
  1487. je GI220Nomem ; no
  1488. mov ax,[MaxSize]
  1489. mov bx,[hMax]
  1490. mov cx,[MaxSize]
  1491. mov dx,[hMax]
  1492. mov si,[hUnused]
  1493. cmp [hNearest],0
  1494. je GI220Exit
  1495. mov cx,[NearestSize]
  1496. mov dx,[hNearest]
  1497. jmp short GI220Exit
  1498. GI220Nomem:
  1499. xor ax,ax ; no memory available
  1500. xor cx,cx ;
  1501. GI220Exit:
  1502. pop es
  1503. assume es:nothing
  1504. ret
  1505. GetInt220mem endp
  1506. ;*----------------------------------------------------------------------*
  1507. ;* *
  1508. ;* AllocInt220mem - *
  1509. ;* *
  1510. ;* Set memory block for Int220 onto EMB table *
  1511. ;* *
  1512. ;* ARGS: AX = size of memories requested in blocks of 128k *
  1513. ;* BX = handle of free EMB block *
  1514. ;* SI = handle of unused EMB block *
  1515. ;* *
  1516. ;* RETS: AX = size of EMB blocks allocated in blocks of 128k *
  1517. ;* BX = start addr of allocated memories *
  1518. ;* DX = ending addr of allocated memoies *
  1519. ;* CX = handle of allocated EMB block *
  1520. ;* *
  1521. ;* REGS: AX, BX, CX, DX and Flags are clobbered *
  1522. ;* *
  1523. ;*----------------------------------------------------------------------*
  1524. AllocInt220mem proc near
  1525. push es
  1526. mov es,[hiseg]
  1527. assume es:funky
  1528. shl ax,7 ; request size in kbytes
  1529. or si,si ; is there a unused block?
  1530. jz AI220AllocAll ; no, allocate entire block
  1531. cmp ax,[bx].Len
  1532. je AI220AllocAll
  1533. mov dx,[bx].Base
  1534. mov cx,dx
  1535. add dx,[bx].Len ; end of free block
  1536. and dx,007fh ; size beyond 128k boundary
  1537. add dx,ax
  1538. mov [si].Len,dx
  1539. sub [bx].Len,dx
  1540. add cx,[bx].Len
  1541. mov [si].Base,cx
  1542. mov bx,si
  1543. AI220AllocAll:
  1544. mov [bx].Flags,USEDFLAG ; New.Flags = USED
  1545. shr ax,7 ; size of block allocated
  1546. mov cx,bx ; handle of block allocated
  1547. mov dx,[bx].Base
  1548. add dx,[bx].Len
  1549. and dx,0ff80h
  1550. shr dx,6 ; end addr
  1551. mov bx,dx
  1552. sub bx,ax
  1553. sub bx,ax ; start addr
  1554. pop es
  1555. assume es:nothing
  1556. ret
  1557. AllocInt220mem endp
  1558. endif ;NEC_98
  1559. ;*----------------------------------------------------------------------*
  1560. ;* *
  1561. ;* RequestHMA - FUNCTION 01h *
  1562. ;* *
  1563. ;* Give caller control of the High Memory Area if it is available. *
  1564. ;* *
  1565. ;* ARGS: DX = HMA space requested in bytes *
  1566. ;* RETS: AX = 1 if the HMA was reserved, 0 otherwise. BL = Error *
  1567. ;* REGS: AX, BX and Flags clobbered *
  1568. ;* *
  1569. ;* INTERNALLY NON-REENTRANT *
  1570. ;* *
  1571. ;*----------------------------------------------------------------------*
  1572. winbug_fix dw 0 ; storage for windows bug workaround
  1573. RequestHMA proc near
  1574. call DOCLI ; This is a non-reentrant function.
  1575. ; Flags are restored after the return.
  1576. mov bl,ERR_HMAINUSE
  1577. ; ***************************
  1578. ; ** There's a problem with WIN386 2.11. It calls XMS driver
  1579. ; ** incorrectly and then goes ahead and uses the memory
  1580. ; ** it didn't properly allocate. In order to convince it
  1581. ; ** not to go ahead and use the extended memory, we must
  1582. ; ** fail this function when it calls us. We know that
  1583. ; ** al=40h and dx=free memory returned from QueryExtMemory
  1584. ; ** when we're called from windows. Hopefully no legitimate
  1585. ; ** caller will happen to have that exact same 24 bit code
  1586. ; ** in al/dx when they call this function because they will fail.
  1587. ; ***************************
  1588. cmp al,40h ; called from win386 2.11?
  1589. jnz not_winbug
  1590. cmp dx,winbug_fix ; dx=last result from QueryExtMem?
  1591. jz RHRetErr ; fail if so
  1592. not_winbug:
  1593. cmp [fHMAInUse],1 ; Is the HMA already allocated?
  1594. je RHRetErr
  1595. mov bl,ERR_HMANOTEXIST
  1596. cmp [fHMAExists],0 ; Is the HMA available?
  1597. je RHRetErr
  1598. mov bl,ERR_HMAMINSIZE
  1599. cmp dx,[MinHMASize] ; Is this guy allowed in?
  1600. jb RHRetErr
  1601. mov ax,1
  1602. mov [fHMAInUse],al ; Reserve the High Memory Area
  1603. xor bl,bl ; Clear the error code
  1604. ret
  1605. RHRetErr:
  1606. xor ax,ax ; Return failure with error code in BL
  1607. ret
  1608. RequestHMA endp
  1609. ;*----------------------------------------------------------------------*
  1610. ;* *
  1611. ;* ReleaseHMA - FUNCTION 02h *
  1612. ;* *
  1613. ;* Caller is releasing control of the High Memory area *
  1614. ;* *
  1615. ;* ARGS: None *
  1616. ;* RETS: AX = 1 if control is released, 0 otherwise. BL = Error *
  1617. ;* REGS: AX, BX and Flags clobbered *
  1618. ;* *
  1619. ;* INTERNALLY NON-REENTRANT *
  1620. ;* *
  1621. ;*----------------------------------------------------------------------*
  1622. ReleaseHMA proc near
  1623. call DOCLI ; This is a non-reentrant function
  1624. mov al,[fHMAInUse] ; HMA currently in use?
  1625. or al,al
  1626. jz RLHRetErr ; No, return error
  1627. mov [fHMAInUse],0 ; Release the HMA and return success
  1628. mov ax,1
  1629. xor bl,bl
  1630. ret
  1631. RLHRetErr:
  1632. xor ax,ax
  1633. mov bl,ERR_HMANOTALLOCED
  1634. ret
  1635. ReleaseHMA endp
  1636. ;*----------------------------------------------------------------------*
  1637. ;* *
  1638. ;* GlobalEnableA20 - FUNCTION 03h *
  1639. ;* *
  1640. ;* Globally enable the A20 line *
  1641. ;* *
  1642. ;* ARGS: None *
  1643. ;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise. BL = Error *
  1644. ;* REGS: AX, BX CX, SI, DI and Flags clobbered *
  1645. ;* *
  1646. ;* INTERNALLY NON-REENTRANT *
  1647. ;* *
  1648. ;*----------------------------------------------------------------------*
  1649. GlobalEnableA20 proc near
  1650. call DOCLI ; This is a non-reentrant function
  1651. cmp [fGlobalEnable],1 ; Is A20 already globally enabled?
  1652. je GEARet
  1653. GEAEnable:
  1654. call LocalEnableA20 ; Attempt to enable A20
  1655. or ax,ax
  1656. jz GEAA20Err
  1657. mov [fGlobalEnable],1 ; Mark A20 global enabled
  1658. GEARet:
  1659. mov ax,1 ; return success
  1660. xor bl,bl
  1661. ret
  1662. GEAA20Err:
  1663. mov bl,ERR_A20 ; some A20 error occurred
  1664. xor ax,ax
  1665. ret
  1666. GlobalEnableA20 endp
  1667. ;*----------------------------------------------------------------------*
  1668. ;* *
  1669. ;* GlobalDisableA20 - FUNCTION 04h *
  1670. ;* *
  1671. ;* Globally disable the A20 line *
  1672. ;* *
  1673. ;* ARGS: None *
  1674. ;* RETS: AX=1 if the A20 line is disabled, 0 otherwise. BL = Error *
  1675. ;* REGS: AX, BX, CX, SI, DI and Flags are clobbered *
  1676. ;* *
  1677. ;* INTERNALLY NON-REENTRANT *
  1678. ;* *
  1679. ;*----------------------------------------------------------------------*
  1680. GlobalDisableA20 proc near
  1681. call DOCLI ; This is a non-reentrant function
  1682. cmp [fGlobalEnable],0 ; Is A20 already global-disabled?
  1683. je GDARet
  1684. call LocalDisableA20 ; Attempt to disable it
  1685. or ax,ax ; (also zaps CX, SI, DI)
  1686. jz GDAA20Err
  1687. mov [fGlobalEnable],0 ; mark as global-disabled
  1688. GDARet:
  1689. mov ax,1 ; return success
  1690. xor bl,bl
  1691. ret
  1692. GDAA20Err:
  1693. mov bl,ERR_A20 ; some A20 error occurred
  1694. xor ax,ax
  1695. ret
  1696. GlobalDisableA20 endp
  1697. ;*----------------------------------------------------------------------*
  1698. ;* *
  1699. ;* LocalEnableA20 - FUNCTION 05h *
  1700. ;* *
  1701. ;* Locally enable the A20 line *
  1702. ;* *
  1703. ;* ARGS: None *
  1704. ;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise. BL = Error *
  1705. ;* REGS: AX, BX, CX, SI, DI and Flags clobbered *
  1706. ;* *
  1707. ;* INTERNALLY NON-REENTRANT *
  1708. ;* *
  1709. ;*----------------------------------------------------------------------*
  1710. LocalEnableA20 proc near
  1711. ifndef NEC_98
  1712. call DOCLI ; This is a non-reentrant function
  1713. cmp [fCanChangeA20],1 ; Can we change A20?
  1714. jne LEARet ; No, don't touch A20
  1715. if NUM_A20_RETRIES
  1716. mov A20Retries,NUM_A20_RETRIES
  1717. endif
  1718. cmp [EnableCount],0 ; If enable count == 0, go set it
  1719. jz LEASetIt ; without bothering to check 1st
  1720. if NUM_A20_RETRIES
  1721. LEATestIt:
  1722. endif
  1723. call IsA20On ; If A20 is already on, don't do
  1724. or ax,ax ; it again, but if it isn't on,
  1725. jnz LEAIncIt ; then make it so
  1726. LEASetIt:
  1727. mov ax,1 ; attempt to turn A20 on
  1728. call A20Handler ; Call machine-specific A20 handler
  1729. ife NUM_A20_RETRIES
  1730. or ax,ax ; If we're not doing retries, then
  1731. jz LEAA20Err ; use A20 handler's error return
  1732. else
  1733. dec A20Retries ; Any retries remaining? If so, go
  1734. jnz LEATestIt ; test current state, else return
  1735. jmp short LEAA20Err ; an error condition
  1736. endif
  1737. LEAIncIt:
  1738. inc [EnableCount]
  1739. LEARet:
  1740. mov ax,1 ; return success
  1741. xor bl,bl
  1742. ret
  1743. LEAA20Err:
  1744. mov bl,ERR_A20 ; some A20 error occurred
  1745. xor ax,ax
  1746. if debug_vers
  1747. disp_a20_err:
  1748. pusha
  1749. mov al,'#'
  1750. call cofa
  1751. popa
  1752. endif
  1753. ret
  1754. else ;NEC_98
  1755. call DOCLI ; This is a non-reentrant function
  1756. cmp [fCanChangeA20],1 ; Can we change A20?
  1757. jne LEARet ; No, don't touch A20
  1758. ; From 2.14 - 2.25 the following 3 lines were commented out. This caused
  1759. ; at least four (seemingly different) bugs on PS/2 systems. The problem
  1760. ; seems to be that the PS2_A20Handler returns an error code if called to
  1761. ; enable when A20 is already on (other handlers do this also!). JimMat
  1762. call IsA20On ; If A20 is already on, don't do
  1763. or ax,ax ; it again, but if it isn't on,
  1764. jnz LEAIncIt ; then make it so
  1765. mov ax,1 ; attempt to turn A20 on
  1766. call A20Handler ; Call machine-specific A20 handler
  1767. or ax,ax
  1768. jz LEAA20Err
  1769. LEAIncIt:
  1770. inc [EnableCount]
  1771. LEARet:
  1772. mov ax,1 ; return success
  1773. xor bl,bl
  1774. ret
  1775. LEAA20Err:
  1776. mov bl,ERR_A20 ; some A20 error occurred
  1777. xor ax,ax
  1778. if debug_vers
  1779. disp_a20_err:
  1780. pusha
  1781. mov al,'#'
  1782. call cofa
  1783. popa
  1784. endif
  1785. ret
  1786. endif ;NEC_98
  1787. LocalEnableA20 endp
  1788. ;*----------------------------------------------------------------------*
  1789. ;* *
  1790. ;* LocalDisableA20 - FUNCTION 06h *
  1791. ;* *
  1792. ;* Locally disable the A20 line *
  1793. ;* *
  1794. ;* ARGS: None *
  1795. ;* RETS: AX=1 if the A20 line is disabled, 0 otherwise. BL = Error *
  1796. ;* REGS: AX, BX, CX, SI, DI and Flags are clobbered *
  1797. ;* *
  1798. ;* INTERNALLY NON-REENTRANT *
  1799. ;* *
  1800. ;*----------------------------------------------------------------------*
  1801. LocalDisableA20 proc near
  1802. call DOCLI ; This is a non-reentrant function
  1803. cmp [fCanChangeA20],0 ; Can we change A20?
  1804. je LDARet ; No, don't touch A20
  1805. cmp [EnableCount],0 ; make sure the count's not zero
  1806. je LDAA20Err
  1807. ifndef NEC_98
  1808. if NUM_A20_RETRIES
  1809. mov A20Retries,NUM_A20_RETRIES
  1810. LDATestIt:
  1811. endif
  1812. endif ;NEC_98
  1813. call IsA20On ; Currently on or off?
  1814. cmp [EnableCount],1 ; Only if the count = 1 should A20 be
  1815. jnz LDAStayOn ; turned off, otherwise it stays on
  1816. or ax,ax ; If A20 is already off, don't
  1817. jz LDADecIt ; bother to turn off again
  1818. xor ax,ax ; It's on, but should be turned off
  1819. jmp short LDASetIt
  1820. LDAStayOn:
  1821. or ax,ax ; A20 must stay on, if it is on, just
  1822. jnz LDADecIt ; dec count, else force A20 on
  1823. mov ax,1
  1824. LDASetIt:
  1825. call A20Handler ; Call machine-specific A20 handler
  1826. ifndef NEC_98
  1827. ife NUM_A20_RETRIES
  1828. or ax,ax ; If we're not doing retries, then
  1829. jz LDAA20Err ; use A20 handler's error return
  1830. else
  1831. dec A20Retries ; Any retries remaining? If so, go
  1832. jnz LDATestIt ; test current state, else return
  1833. jmp short LDAA20Err ; an error condition
  1834. endif
  1835. else ;NEC_98
  1836. or ax,ax ; If we're not doing retries, then
  1837. jz LDAA20Err ; use A20 handler's error return
  1838. endif ;NEC_98
  1839. LDADecIt:
  1840. dec [EnableCount]
  1841. LDARet:
  1842. mov ax,1 ; return success
  1843. xor bl,bl
  1844. ret
  1845. LDAA20Err:
  1846. mov bl,ERR_A20 ; some A20 error occurred
  1847. xor ax,ax
  1848. if debug_vers
  1849. jmp disp_a20_err
  1850. endif
  1851. ret
  1852. LocalDisableA20 endp
  1853. ;
  1854. ;---------------------------------------------------------------------------
  1855. ; procedure : FLclEnblA20
  1856. ; procedure : FLclDsblA20
  1857. ;
  1858. ; Called from the Block move functions. Serves 2 purposes
  1859. ; 1. Interfaces a far call for a near routine
  1860. ; 2. If funky is in HMA does a dummy success return
  1861. ;---------------------------------------------------------------------------
  1862. ;
  1863. FLclEnblA20 proc far
  1864. cmp cs:fInHMA, 0
  1865. jz @f
  1866. mov ax, 1
  1867. ret
  1868. @@:
  1869. call LocalEnableA20
  1870. ret
  1871. FLclEnblA20 endp
  1872. FLclDsblA20 proc far
  1873. cmp cs:fInHMA, 0
  1874. jz @f
  1875. mov ax, 1
  1876. ret
  1877. @@:
  1878. call LocalDisableA20
  1879. ret
  1880. FLclDsblA20 endp
  1881. ;
  1882. ;*----------------------------------------------------------------------*
  1883. ;* *
  1884. ;* IsA20On - FUNCTION 07h *
  1885. ;* *
  1886. ;* Returns the state of the A20 line *
  1887. ;* *
  1888. ;* ARGS: None *
  1889. ;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise *
  1890. ;* BL = 0 *
  1891. ;* REGS: AX, BL, CX, SI, DI and Flags clobbered *
  1892. ;* *
  1893. ;* INTERNALLY REENTRANT *
  1894. ;* *
  1895. ;*----------------------------------------------------------------------*
  1896. ; NOTE: When this routine is called from the Int15 handler, ds is undefined.
  1897. ; Hence the CS: overrides on data references.
  1898. IsA20On proc near
  1899. mov al, cs:A20State
  1900. cbw
  1901. xor bl, bl
  1902. ret
  1903. IsA20On endp
  1904. ;*----------------------------------------------------------------------*
  1905. ;* *
  1906. ;* AddMem - add memory to free pool *
  1907. ;* *
  1908. ;* The trick here is that we're going to check for overlapping *
  1909. ;* or adjacent blocks and crunch them together. The thinking *
  1910. ;* here is that we may be informed of a memory resource from *
  1911. ;* more than one source. In any case, we NEVER want the same *
  1912. ;* memory to appear in our resource table more than once. *
  1913. ;* *
  1914. ;* Note: there's presently no way of reporting errors if the *
  1915. ;* handle table is full. If it happens, we'll just lose the *
  1916. ;* memory block. This should not be a problem as long as *
  1917. ;* we're only being called during program initialization. *
  1918. ;* *
  1919. ;* It would be nice if we could throw this code away after *
  1920. ;* initialization, unfortunately this is actually invoked *
  1921. ;* at HookInt15 time, so it's too late to do away with *
  1922. ;* obsolete code. *
  1923. ;* *
  1924. ;* ARGS: CX - base of block in 1K increments *
  1925. ;* AX - length of block in 1K increments *
  1926. ;* TRASHES: AX,BX,CX,DX,SI,DI *
  1927. ;* *
  1928. ;* messes with handle table - not reentrant - assumes ints disabled *
  1929. ;* *
  1930. ;*----------------------------------------------------------------------*
  1931. AddMem proc near
  1932. ; We might as well be scanning for a free handle while we're
  1933. ; at it since we're normally going to need one at the end
  1934. mov dx,ax ; save new block length in dx
  1935. mov si,cx ; save new block base in si
  1936. xor di,di ; haven't found free handle yet
  1937. push es
  1938. mov es,hiseg
  1939. assume es:funky
  1940. mov bx,[KiddValley] ; prepare to loop thru handle tab
  1941. mov cx,[cHandles]
  1942. AM01:
  1943. cmp [bx].Flags,UNUSEDFLAG ; is this handle available?
  1944. jnz AM02 ; skip if not
  1945. or di,di ; use the first free handle we
  1946. jnz AM05 ; find. skip if we've got one
  1947. mov di,bx ; save the unused handle in di
  1948. jmp short AM05
  1949. AM02:
  1950. ; Note: Normally all handles will be either UNUSED or FREE at
  1951. ; this point. However, in the case of checking for Zenith memory,
  1952. ; it may have a temporarily allocated dummy block. Therefore
  1953. ; we'll only be merging blocks marked as FREE.
  1954. cmp [bx].Flags,FREEFLAG
  1955. jnz AM05 ; ignore USED blocks
  1956. ; First check for new block being entirely after block at [bx]
  1957. mov ax,[bx].Base
  1958. add ax,[bx].Len
  1959. cmp ax,si ; is [bx].end < new.Base?
  1960. jb AM05 ; done checking this entry if so
  1961. ; Now check for new block being entirely before block at [bx]
  1962. mov ax,si ; new.base
  1963. add ax,dx ; + new.len = new.end
  1964. cmp ax,[bx].Base
  1965. jb AM05 ; brif no overlap at all
  1966. ; Now put the block at [bx] up into our block in registers so
  1967. ; that we can continue the scan. There may be other adjacent
  1968. ; blocks, even in the case of no overlap, fr'instance when a
  1969. ; block is added which entirely fills the gap between two others.
  1970. cmp si,[bx].Base ; Find base of combined block
  1971. jbe AM03 ; Brif new block on bottom
  1972. add dx,si ; Add new.base - [bx].base to
  1973. mov si,[bx].Base ; new.len, set new.base=[bx].Base
  1974. sub dx,si ; new.len
  1975. AM03:
  1976. mov ax,[bx].Base ; see which block ends later
  1977. add ax,[bx].Len ; get [bx].end
  1978. sub ax,dx ; less new.len
  1979. sub ax,si ; compare to new.Base
  1980. jbe AM04 ; brif new.end >= [bx].end
  1981. ; now ax has the amount our block must grow by
  1982. add dx,ax
  1983. AM04:
  1984. mov [bx].Flags,UNUSEDFLAG ; mark the block unused
  1985. or di,di ; did we find an unused handle yet?
  1986. jnz AM05 ; brif so
  1987. mov di,bx ; save this one if not
  1988. AM05:
  1989. add bx,SIZE handle
  1990. loop AM01
  1991. or di,di ; did we find a free handle?
  1992. jz AM06 ; error! no handles free!
  1993. mov [di].cLock,0
  1994. mov [di].Flags,FREEFLAG ; create the free memory block
  1995. mov [di].Base,si
  1996. mov [di].Len,dx
  1997. AM06:
  1998. pop es
  1999. assume es:nothing
  2000. ret
  2001. AddMem endp
  2002. PUBLIC DOCLI
  2003. DOCLI:
  2004. FCLI
  2005. ret
  2006. PUBLIC DOSTI
  2007. DOSTI:
  2008. FSTI
  2009. ret
  2010. PUBLIC DOIRET
  2011. DOIRET:
  2012. FIRET
  2013. _text ends
  2014. end
  2015.