himem2.asm
上传用户:xiaoan1112
上传日期:2013-04-11
资源大小:19621k
文件大小:57k
源码类别:

操作系统开发

开发平台:

Visual C++

  1. ;/*
  2. ; *                      Microsoft Confidential
  3. ; *  Copyright (C) Microsoft Corporation 1988-1992
  4. ; *                      All Rights Reserved.
  5. ; */
  6. page 95,160
  7. title   'HIMEM2 - Initialization code'
  8. funky segment word public 'funky'
  9. extrn InstallMoveBlock:near ; in high segment
  10. extrn textseg:word ; in high segment
  11. extrn KiddValley:word
  12. extrn KiddValleyTop:word
  13. extrn segKiddValley:word
  14. extrn cHandles:word
  15. extrn pack_and_truncate:near
  16. extrn MmovSegReinit:far
  17. extrn end_of_funky_seg:byte
  18. extrn LEnblA20:word
  19. extrn LDsblA20:word
  20. funky ends
  21. .xlist
  22. include himem.inc ; get structures, equ's, etc.
  23. ;  and open segment
  24. .list
  25. public f000
  26. public InitInterrupt
  27. public MachineNum
  28. ;************************************************************************
  29. ;* *
  30. ;*  Global Variables *
  31. ;* *
  32. ;************************************************************************
  33. extrn pPPFIRET:word
  34. extrn dd_int_loc:word
  35. extrn Interrupt:near
  36. extrn hiseg:word
  37. extrn call_hi_in_di:near
  38. extrn fCanChangeA20:byte
  39. extrn fHMAMayExist:byte
  40. extrn fVDISK:byte
  41. extrn IsVDISKIn:near
  42. extrn A20Handler:near
  43. extrn EnableCount:word
  44. extrn MemCorr:word
  45. extrn MinHMASize:word
  46. ifdef debug_tsr
  47. extrn MoveIt:dword
  48. else
  49. extrn MoveIt:word
  50. endif
  51. extrn pReqHdr:dword
  52. extrn PrevInt2f:dword
  53. extrn TopOfTextSeg:word
  54. extrn InstallA20:near
  55. extrn Int2fHandler:near
  56. extrn Is6300Plus:near
  57. extrn IsA20On:near
  58. extrn pAddMem:word
  59. extrn SignOnMsg:byte
  60. extrn ROMDisabledMsg:byte
  61. extrn UnsupportedROMMsg:byte
  62. extrn ROMHookedMsg:byte
  63. extrn BadDOSMsg:byte
  64. extrn NowInMsg:byte
  65. extrn On8086Msg:byte
  66. extrn NoExtMemMsg:byte
  67. extrn FlushMsg:byte
  68. extrn StartMsg:byte
  69. extrn HandlesMsg:byte
  70. extrn HMAMINMsg:byte
  71. extrn KMsg:byte
  72. extrn NoHMAMsg:byte
  73. extrn A20OnMsg:byte
  74. extrn HMAOKMsg:byte
  75. extrn VDISKInMsg:byte
  76. extrn BadArgMsg:byte
  77. extrn DevAttr:word
  78. extrn Int15MemSize:word
  79. extrn pInt15Vector:word
  80. extrn PrevISAInt15:dword
  81. extrn ISA15Handler:near
  82. extrn EndText:byte
  83. extrn XMMControl:far
  84. extrn pfnEnabA20:word
  85. extrn pfnDisabA20:word
  86. extrn LocalEnableA20:near
  87. extrn LocalDisableA20:near
  88. ;************************************************************************
  89. ;* *
  90. ;*   Code/Data below here will be discarded after driver initialization *
  91. ;* *
  92. ;************************************************************************
  93. ; Discardable Initialization Data
  94. pCOMPAQ label dword ; Pointer to COMPAQ specific for BIM
  95. dw 0FFE8h ;
  96. dw 0F000h ;
  97. pBIMGDT  dw offset BIMGDT     ; Offset to BIMGDT for BIM alloc'n
  98. GetBIMMemProc dw offset GetBIMMemory ; Offset of GetBIMMemory procedure
  99. BIMBase  dw 0 ; Base address and Lenght of remaining Compaq
  100. BIMLength dw 0 ;   Built-In Memory (set at Init time)
  101. BIMBuffer dw ? ; Buffer for unlock/lock ROM for BIM
  102. public fShadowOff, f1stWasWarning
  103. fShadowOff db 0 ; NZ if shadow RAM should be disabled,
  104. ;   0/1 set by command line switch, 0FFh
  105. ;   set if little extended and hope to disable
  106. f1stWasWarning db 0 ; NZ if 1st attempt to diddle A20 generated
  107. ; a warning (and not an error)
  108. public fA20Control
  109. fA20Control db 0ffh ; NZ if himem should take control of A20, even
  110. ;   it was already on when himem loaded.
  111. public fCPUClock
  112. fCPUClock db 0 ; NZ if himem should try to preserve CPU clock
  113. ;   speed when gating A20
  114. fEISA db 0 ; NZ if himem should take all EISA memory
  115. ;   blocks
  116. public fQuiet
  117. fQuiet db 0ffh ; NZ if himem should be quiet during install
  118. fSignOnMsg db 0 ; NZ if sign on msg has been displayed
  119. fBigMem  db 0ffh ; NZ if ISA memory above 16 meg allowed
  120. fNumHandSet db 0 ; NZ if /NUMHANDLES= parameter used
  121. fHMAminSet db 0 ; NZ if /HMAMIN= parameter used
  122. ; Parameter tables for GetParms
  123. ParmEntry   struc
  124. cParmChar   db     0 ; 1st char of option on cmd line
  125. pParmRtn    dw     0 ; offset of routine to process option
  126. ParmEntry   ends
  127. ; The 1st table is for parameters that have no arguments
  128. ParmTbl1 label  byte
  129. ParmEntry   <'E',GPGotEisa> ; /EISA
  130. ParmEntry   <'V',GPGotVerbose> ; /VERBOSE
  131. ParmEntry   <'N',GPGotBigMem> ; /NOABOVE16
  132. ParmEntry   <'Z',GPZSwitch> ; /Z
  133. db 0 ; ** END OF TABLE **
  134. ; The 2nd table is for parameters with arguments
  135. ParmTbl2 label  byte
  136. ParmEntry   <'H',GPGotMin> ; /HMAMIN=
  137. ParmEntry   <'N',GPGotHands> ; /NUMHANDLES=
  138. ParmEntry   <'M',GPGotMachine> ; /MACHINE:
  139. ParmEntry   <'A',GPGotA20Control> ; /A20CONTROL:
  140. ParmEntry   <'S',GPGotShadow> ; /SHADOWRAM:
  141. ParmEntry   <'I',GPGotInt15> ; /INT15=
  142. ParmEntry   <'C',GPGotCPUClock>  ; /CPUCLOCK:
  143. db 0 ; ** END OF TABLE **
  144. public StringParm, MachineNum, MachineName
  145. StringParm db 13 DUP (' ')
  146. MachineNum dw -1
  147. ;  Note: the following table MUST be in the same order as the entries in the
  148. ;  A20_Scan_Table!  If you add entries here, also add one there!
  149. MachineName label byte
  150. db 'ptlcascade',0 ; Phoenix Cascade BIOS
  151. db 'att6300plus',0  ; AT&T 6300 Plus
  152. db 'ps2',0  ; IBM PS/2
  153. db 'hpvectra',0 ; HP 'Classic' Vectra (A & A+)
  154. db 'acer1100',0 ; Acer 1100
  155. db 'toshiba',0 ; Toshiba 1600 & 1200XE
  156. db 'wyse',0 ; Wyse 12.5 MHz 286 machine
  157. db 'tulip',0 ; Tulip machines
  158. db 'zenith',0 ; Zenith ZBIOS
  159. db 'at1',0  ; IBM AT/delay 0
  160. db 'at2',0  ; IBM AT/delay 1
  161. db 'at3',0  ; IBM AT/delay 2
  162. db 'philips',0 ; Philips machines
  163. db 'css',0 ; CSS Lab machines
  164. db 'fasthp',0 ; Single byte method for HP Vectras
  165. db 'ibm7552',0 ; IBM 7552 Industrial Computer
  166. db 'bullmicral',0 ; Bull Micral 60 M004
  167. db 'dell',0 ; DELL XBIOS ; M010
  168. db 'at',0 ; IBM AT
  169. db 0FFh ; end of table
  170. ;NOTE: there is code in GetParms which depends on AltNameTbl coming
  171. ;      after MachineName table.
  172. public AltName1, AltName2, AltName3, AltName4, AltName5
  173. public AltName6, AltName7, AltName8, AltName9, AltName10
  174. public AltName11, AltName12, AltName13, AltName14, AltName15
  175. public AltName16,AltName17 ;M004
  176. AltNameTbl label byte
  177. AltName3    db '3',0 ; Phoenix Cascade BIOS
  178. AltName5    db '5',0 ; AT&T 6300 Plus
  179. AltName2    db '2',0 ; IBM PS/2
  180. AltName4    db '4',0 ; HP 'Classic' Vectra (A & A+)
  181. AltName6    db '6',0 ; Acer 1100
  182. AltName7    db '7',0 ; Toshiba 1600 & 1200XE
  183. AltName8    db '8',0 ; Wyse 12.5 Mhz 286 machine
  184. AltName9    db '9',0 ; Tulip machine
  185. AltName10   db '10',0 ; Zenith ZBIOS
  186. AltName11   db '11',0 ; IBM AT/delay 0
  187. AltName12   db '12',0 ; IBM AT/delay 1
  188. AltName13   db '13',0 ; IBM AT/delay 2
  189.     db '13',0 ; Philips machines (same as AT3)
  190.     db '12',0 ; CSS machines
  191. AltName14   db '14',0 ; Single byte HP Vectra m/cs
  192. AltName15   db '15',0 ; IBM 7552 Industrial Computer
  193. AltName16   db '16',0 ; Bull Micral 60          M004
  194. AltName17   db '17',0
  195. AltName1    db '1',0 ; IBM AT
  196.     db 0FFh ; end of table
  197. ifdef debug_tsr ;-----------------------------------------------
  198. ;*----------------------------------------------------------------------*
  199. ;* *
  200. ;*  ExeStart - *
  201. ;* *
  202. ;* Entry point when himem is invoked as an .EXE. *
  203. ;* *
  204. ;*----------------------------------------------------------------------*
  205. lpCmdLine dd 81h ; far ptr to command tail
  206. public ExeStart
  207. ExeStart:
  208. mov word ptr cs:[lpCmdLine+2],es ; save PSP segment in pointer
  209. mov ax,cs ; Setup segment regs to all be the same
  210. mov ds,ax
  211. mov es,ax
  212. call InitDriver ; Initialize...
  213. mov ax,TopOfTextSeg ; TopOfTextSeg == 0 is error installing
  214. or ax,ax
  215. jnz @f
  216. mov ax,4C03h ; error, so just terminate
  217. int 21h
  218. @@:
  219. mov di,offset pack_and_truncate
  220. jmp call_hi_in_di ; terminate and stay resident
  221. endif ;------------------------------------------------
  222. ;*----------------------------------------------------------------------*
  223. ;* *
  224. ;*  InitInterrupt - *
  225. ;* *
  226. ;* Called by MS-DOS immediately after Strategy routine *
  227. ;* *
  228. ;*  ARGS:   None *
  229. ;*  RETS:   Return code in Request Header's Status field *
  230. ;*  REGS:   Preserved *
  231. ;* *
  232. ;* This entry point is used only during initialization. *
  233. ;* It replaces itself with a much shorter version which only *
  234. ;* serves to report the appropriate errors when this driver *
  235. ;* is called in error. *
  236. ;* *
  237. ;*----------------------------------------------------------------------*
  238. InitInterrupt   proc    far
  239. ; Save the registers including flags.
  240. push    ax ; We cannot use pushapopa because
  241. push    bx ; we could be on an 8086 at this point
  242. push    cx
  243. push    dx
  244. push    ds
  245. push    es
  246. push    di
  247. push    si
  248. push    bp
  249. pushf
  250. push cs ; Set DS=CS for access to global variables.
  251. pop ds
  252. les di,[pReqHdr] ; ES:DI = Request Header
  253. mov     bl,es:[di].Command ; Get Function code in BL
  254. or bl,bl ; Only Function 00h (Init) is legal
  255. jz IInit
  256. cmp     bl,16 ; Test for "legal" DOS functions
  257. jle     IOtherFunc
  258. IBogusFunc:
  259. mov     ax,8003h ; Return "Unknown Command"
  260. jmp     short IExit
  261. IOtherFunc:
  262. xor     ax,ax ; Return zero for unsupported functions
  263. jmp     short IExit
  264. IInit:
  265. call    InitDriver ; Initialize the driver
  266. les di,[pReqHdr] ; Restore es:di = Request Header
  267. IExit:
  268. or ax,0100h ; Turn on the "Done" bit
  269. mov es:[di].Status,ax ; Store return code
  270. popff ; restore the registers
  271. pop bp
  272. pop si
  273. pop di
  274. pop es
  275. pop ds
  276. pop dx
  277. pop cx
  278. pop bx
  279. pop ax
  280. mov dd_int_loc,offset Interrupt ; replace Interrupt with
  281. ret ; tiny permanent stub
  282. InitInterrupt   endp
  283. ;*----------------------------------------------------------------------*
  284. ;* *
  285. ;*  InitDriver - *
  286. ;* *
  287. ;* Called when driver is Initialized. *
  288. ;* *
  289. ;*  ARGS:   ES:DI = Address of the Request Header *
  290. ;*  RETS:   pHdr.Address = Bottom of resident driver code *
  291. ;*  REGS:   AX, CX and Flags are clobbered *
  292. ;* *
  293. ;*----------------------------------------------------------------------*
  294. public InitDriver
  295. InitDriver  proc    near
  296. cld
  297. ifndef debug_tsr
  298. call LocateHiSeg ; locate the hiseg in low memory properly
  299. mov di, offset MMovSegReinit
  300. mov es, hiseg
  301. push cs
  302. call call_hi_in_di ; re-initialize the mem mover
  303. mov ax,cs
  304. push es
  305. mov es,hiseg
  306. assume es:funky
  307. add textseg,ax ; relocate text segment pointer
  308. add LEnblA20+2, ax ; update ptrs to enble & disable a20 rtns
  309. add LDsblA20+2, ax
  310. pop es
  311. assume es:nothing
  312. endif
  313. mov ah,30h ; make sure we've got DOS 3.00 or higher
  314. int 21h ; Get DOS versions number
  315. cmp al,3
  316. jae     IDCheckXMS
  317. mov dx,offset BadDOSMsg
  318. jmp IDFlushMe
  319. IDCheckXMS:
  320. mov ax,(INT2F_ID SHL 8) OR INT2F_INS_CHK
  321. int 2Fh ; make sure there's no other XMS installed
  322. cmp al,80h ; Is INT 2F hooked?
  323. jne     IDNotInYet
  324. mov dx,offset NowInMsg
  325. jmp IDFlushMe
  326. IDNotInYet:
  327. xor     ax,ax ; Move 0 into the Flags register
  328. push    ax
  329. popf
  330. pushf ; Try and get it back out
  331. pop     ax
  332. and     ax,0F000h ; If the top four bits are set...
  333. cmp     ax,0F000h
  334. mov dx,offset On8086Msg ; we're on an 8086
  335. jnz @f
  336. jmp IDFlushMe ; so crap out
  337. @@:
  338. call GetInt15Memory ; If Int 15h/88h reports < 384k of
  339. cmp ax,384 ;   extended memory available, then
  340. jae @f ;   we will try to increase memory
  341. mov fShadowOFF,0FFh  ;   by stealing shadow RAM
  342. @@:
  343. call GetParms ; process command line parameters
  344. mov ah, 2 ; Force VERBOSE mode if user is
  345. int 16h ;   holding down the Alt key
  346. test al, 08h  ; Int 16h/2 == Get Keyboard Flags
  347. jz @f ;   08h set if Alt key down
  348. mov fQuiet, 0
  349. @@:
  350. ifndef debug_tsr
  351. call DispSignOnMsg
  352. endif
  353. mov di,offset InstallMoveBlock ; install moveblock function
  354. push cs ; setup for far return
  355. call call_hi_in_di ; call into high segment
  356. call IsA20On  ; Is A20 already enabled?
  357. or ax,ax ;   (may zap cx, si, di)
  358. jz IDInsA20 ;   no, go install A20 handler
  359. mov dx,offset A20OnMsg ; "A20 already on" message
  360. cmp fA20Control,0 ; should we take control of A20 anyway?
  361. jne IDInsA20 ;   yes, go muck with it
  362. mov [fCanChangeA20],0 ;   no,  don't allow changing of A20
  363. call DispInfoMsg ;  and tell user about it
  364. jmp short IDAfterA20
  365. IDInsA20:
  366. call InstallA20 ; install proper A20 handler
  367. jnc @f
  368. jmp IDFlushMe ; CY means fatal error
  369. @@:
  370. ; Note:  A side affect of the previous InstallA20 is that MemCorr
  371. ;   is set to reflect the adjustment factor if we're on an AT&T 6300+
  372. IDAfterA20:
  373. call InitHandles ; initialize handle table
  374. call ScanEISA ; scan EISA memory into table
  375. call CheckZBim ; Check for & allocate Zenith BIM
  376. call CheckBIM ; Check for & allocate Compaq BIM
  377. ; Turn off shadow RAM if desired/possible
  378. cmp fShadowOFF,0 ; should shadow RAM be turned off?
  379. jz @f
  380. call ShadowRAMOff ; try to turn it off--also adds to free list
  381. or dx,dx ; display a msg if ShadowRAMOff is
  382. jz @f ;   pointing to one
  383. call DispInfoMsg
  384. @@:
  385. call IsVDISKIn ; Is a VDISK style allocator already
  386. cmp [fVDISK],0 ;   installed? Don't bother to load
  387. jz @f ;   if so, cause we'll just fail all
  388. mov dx,offset VDISKInMsg ;   future calls anyway...
  389. jmp short IDFlushMe
  390. @@:
  391. ; Looks like himem will install, allocate Big ISA memory (above 16 meg)
  392. ; now if available
  393. cmp [fBigMem], 0 ; Was parameter specified?
  394. je @f ; NO: don't bother trying to get it
  395. call GetBIGMemory ; Get extra ISA memory
  396. @@:
  397. call    GetInt15Memory ; how much extended memory is installed?
  398. cmp     ax,64 ; Is there >= 64K of extended?
  399. jae IDHMAOK
  400. push es
  401. mov es,hiseg
  402. assume es:funky
  403. mov bx,[KiddValley] ; get size of memory we already have in tables
  404. mov cx,[cHandles]
  405. IDAnyMem:
  406. cmp [bx].Flags,FREEFLAG
  407. jnz IDAnyMem_1 ; brif not a valid free block
  408. mov ax, [bx].Len.hi
  409. or ax, [bx].Len.lo
  410. jnz IDAnyMem_2
  411. IDAnyMem_1:
  412. add bx,SIZE Handle
  413. loop IDAnyMem
  414. IDAnyMem_2:
  415. pop es
  416. assume es:nothing
  417. mov dx,offset NoHMAMsg
  418. or ax,ax ; no HMA, any other memory to control?
  419. jnz disp_hma_msg ; jmp if some memory
  420. ; We can't find any memory to manage.
  421. mov dx,offset NoExtMemMsg
  422. ; Display the message in DX followed by the "Flush" message.
  423. IDFlushMe:
  424. call DispErrMsg
  425. mov dx,offset FlushMsg
  426. call DispErrMsg
  427. xor ax,ax ; discard the driver
  428. mov [TopOfTextSeg],ax
  429. ifndef debug_tsr ;-------------------------------
  430. les di,[pReqHdr]
  431. mov es:[di].Units,al
  432. and cs:DevAttr,not 8000h ; clr bit 15 in attrib of driver header
  433. endif
  434. jmp short IDReturn ;-------------------------------
  435. IDHMAOK:
  436. mov     [fHMAMayExist],1
  437. mov dx,offset HMAOKMsg
  438. disp_hma_msg:
  439. call DispInfoMsg
  440. call    HookInt2F ; "turn on" the driver
  441. ; Initialization finished (or failed) -- return to caller
  442. IDReturn:
  443. ifndef debug_tsr ;-------------------------------
  444. mov di,offset pack_and_truncate
  445. jmp call_hi_in_di ; pack stuff down and terminate
  446. else
  447. mov ax, hiseg ; make sure far pointer to handle
  448. mov es, ax ;   table has correct segment
  449. mov es:[segKiddValley], ax
  450. endif ;-------------------------------
  451. ret
  452. InitDriver endp
  453. ;----------------------------------------------------------------------------
  454. ;  DispXxxMsg Routines -- Display informational, error or sign on messages,
  455. ;   if enabled by /VERBOSE parameter.  Error msgs
  456. ;   are displayed regardless of /VERBOSE.
  457. ;  Entry:
  458. ; DX = offset of msg to display
  459. ;  Exit:
  460. ;
  461. ;  Used:
  462. ; AX
  463. ;----------------------------------------------------------------------------
  464. public DispInfoMsg, DispInfoChar, DispErrMsg
  465. DispInfoMsg proc near
  466. cmp cs:[fQuiet], 0 ; display an informational msg if
  467. jnz short DIM_ret ;   not in QUIET mode
  468. call DispSignOnMsg ; make sure user sees signon msg
  469. mov ah, 9
  470. int 21h
  471. DIM_ret:
  472. ret
  473. DispInfoMsg endp
  474. DispInfoChar proc near
  475. cmp cs:[fQuiet], 0
  476. jnz short DIC_ret
  477. call DispSignOnMsg ; make sure user sees signon msg
  478. mov ah, 2
  479. int 21h
  480. DIC_ret:
  481. ret
  482. DispInfoChar endp
  483. DispErrMsg proc near ; display an error msg
  484. mov cs:[fQuiet], 0 ; no longer in QUIET mode
  485. call DispSignOnMsg ; make sure user sees signon before
  486. mov ah, 9 ;   error msg
  487. int 21h
  488. ret
  489. DispErrMsg endp
  490. DispSignOnMsg proc near
  491. cmp cs:[fQuiet], 0 ; don't signon if in QUIET mode
  492. jnz short DSM_ret
  493. cmp cs:[fSignOnMsg], 0 ; don't signon more than once
  494. jnz short DSM_ret
  495. push dx ; display the signon message
  496. push ds
  497. push cs ; in case ds != _text
  498. pop ds
  499. mov ah, 9
  500. mov dx,offset SignOnMsg
  501. int 21h
  502. mov cs:[fSignOnMsg], 0FFh
  503. pop ds
  504. pop dx
  505. DSM_ret:
  506. ret
  507. DispSignOnMsg endp
  508. ;
  509. ;----------------------------------------------------------------------------
  510. ; procedure : LocateHiSeg
  511. ;
  512. ; Locate the movable segment properly in the low seg.
  513. ; taking care of the stripped ORG zeroes. This function
  514. ; calculates the segment at which the hiseg should run
  515. ; with the ORG. If the segment cvalue goes below zero the
  516. ; code is moved up high enough to run the code from a seg value
  517. ; of zero.
  518. ;
  519. ; This function assumes that the 'funky' segment follows
  520. ; immediately after the text seg.
  521. ;
  522. ;----------------------------------------------------------------------------
  523. LocateHiSeg proc near
  524. push ds
  525. mov ax, cs ; para start of text seg
  526. mov cx, offset _text:EndText ; end of text seg
  527. add cx, 15 ; para round it
  528. shr cx, 1
  529. shr cx, 1
  530. shr cx, 1
  531. shr cx, 1
  532. add ax, cx ; para start of funky seg
  533. cmp ax, (HISEG_ORG shr 4) ; will the seg go below zero?
  534. jb MoveHiSeg ; yeah, we have to move it
  535. sub ax, (HISEG_ORG shr 4) ; no, it fits in
  536. pop ds
  537. mov hiseg, ax ; update the segment in which
  538. ;   it is going to run from.
  539. ret
  540. MoveHiSeg:
  541. mov ds, ax ; segment at which funky
  542. ;  resides without the ORG
  543.   xor ax, ax
  544.   mov es, ax ; we want to movve the code
  545. ;  to 0:HISEG_ORG
  546. mov di, offset funky:end_of_funky_seg
  547. mov si, di
  548. sub si, HISEG_ORG
  549. mov cx, si
  550. dec di
  551. dec si
  552.    std ; move backward (safe when
  553. ;  source & dest overlap
  554.      rep movsb
  555. cld
  556.      pop ds
  557.      mov hiseg, 0 ; funky is going to run from
  558. ;  segment zero
  559.      ret
  560. LocateHiSeg endp
  561. ;*----------------------------------------------------------------------*
  562. ;* *
  563. ;*  HookInt2F - *
  564. ;* *
  565. ;* Insert the INT 2F hook *
  566. ;* *
  567. ;*  ARGS:   None *
  568. ;*  RETS:   None *
  569. ;*  REGS:   AX, SI, ES and Flags are clobbered *
  570. ;* *
  571. ;*----------------------------------------------------------------------*
  572. public HookInt2F
  573. HookInt2F   proc    near
  574. cli
  575. xor ax,ax
  576. mov es,ax
  577. mov si,2Fh * 4 ; save previous int2f vector
  578. mov ax,offset Int2FHandler ; and exchange with new one
  579. xchg    ax,es:[si][0]
  580. mov word ptr [PrevInt2F][0],ax
  581. mov ax,cs
  582. xchg    ax,es:[si][2]
  583. mov word ptr [PrevInt2F][2],ax
  584. sti
  585. ret
  586. HookInt2F   endp
  587. ;*----------------------------------------------------------------------*
  588. ;* *
  589. ;*  ShadowRAMOff - *
  590. ;* *
  591. ;* Attempt to turn off shadow RAM on selected machines.  Add the *
  592. ;* memory to our free pool if successful. *
  593. ;* *
  594. ;*  ARGS:   None *
  595. ;*  RETS:   DX - Msg to show user (or 0), & *
  596. ;*     CY clear - success,  *
  597. ;*     CY set   - warning/failed *
  598. ;*  REGS:   AX destroyed *
  599. ;* *
  600. ;*----------------------------------------------------------------------*
  601. public ShadowRAMOff
  602. ShadowRAMOff proc near
  603. push es
  604. push di
  605. push si
  606. push cx
  607. push bx
  608. call Compaq386 ; on a Compaq 386?
  609. jz SOIsCompaq
  610. jmp SONotCompaq
  611. ; Disable shadow RAM on a Compaq 386
  612. SOIsCompaq:
  613. ; check if the video bios points
  614. xor ax,ax ;   into the ROM copy, we don't
  615. mov es,ax ;   want to disable if someone has
  616. mov ax,es:[10h*4+2]  ;   already hooked Int 10h, 1Fh, 43h,
  617. call IsC000orE000 ;   or 6Dh
  618. jnz SORomHooked
  619. mov ax,es:[1Fh*4+2]
  620. call IsC000orE000
  621. jnz SORomHooked
  622. mov ax,es:[43h*4+2]
  623. call IsC000orE000
  624. jnz SORomHooked
  625. cmp word ptr es:[6dh*4+2],0C000h ; finally, make sure Int 6Dh
  626. jae SOVideoOkay ;   points somewhere reasonable
  627. SORomHooked:
  628. mov dx,offset ROMHookedMsg ; somebody has video ROM hooked!
  629. jmp short SONoCanDo
  630. SOVideoOkay:
  631. ; Check to see if this machine allows the ROM to be unmapped
  632. call unmap_permited
  633. jc SOROMNotSupported
  634. ; Looks good, lets disable the RAM copy. This is done by doing
  635. ; an Int 15h blockmove of a command word to the Compaq diagnostic
  636. ; register.  We share data structures with the Compaq BIM code.
  637. mov si,pBIMGDT ; setup block move GDT
  638. mov ax,cs
  639. mov es,ax
  640. mov cx,16
  641. mul cx
  642. add ax,offset BIMBuffer
  643. adc dl,0
  644. mov [si].S_BASE_LOW,ax
  645. mov [si].S_BASE_HI,dl
  646. mov cx,1
  647. mov word ptr [BIMBuffer],0FFFFh ; disable ROM replace command
  648. mov ah,87h
  649. int 15h
  650. ; Point the video vectors back at the original ROM
  651. mov ax,0
  652. mov es,ax
  653. mov ax,0C000h
  654. mov es:[10h*4+2],ax
  655. mov es:[1Fh*4+2],ax
  656. mov es:[43h*4+2],ax
  657. ; If Int 6Dh points at the now disabled ROM, change that too
  658. cmp word ptr es:[6Dh*4+2],0E000h
  659. jnz @f
  660. mov es:[6Dh*4+2],ax
  661. @@:
  662. ; Add the ram space to our free list
  663. mov ax,128 ;128k @ FE0000h
  664. mov cx,3F80h ;  (FE0000h / 1024)
  665. xor dx, dx
  666. mov bx, dx
  667. mov di, pAddMem
  668. push cs
  669. call call_hi_in_di
  670. mov dx,offset ROMDisabledMsg ; Success!
  671. clc
  672. SODone:
  673. pop bx
  674. pop cx
  675. pop si
  676. pop di
  677. pop es
  678. ret
  679. SONotCompaq:
  680. SOROMNotSupported:
  681. mov dx,offset UnsupportedROMMsg ; don't know how to disable
  682. SONoCanDo: ; only show msg if user wanted
  683. cmp fShadowOFF,0FFh  ; to disable--if trying cause
  684. jnz SOFailed ; of too little extended mem,
  685. xor dx,dx ; keep quiet.
  686. SOFailed:
  687. stc
  688. jmp short SODone
  689. ShadowRAMOff endp
  690. IsC000orE000 proc
  691. cmp ax,0C000h ; Video ROM pointers can
  692. jz @f ;   point to either of
  693. cmp ax,0E000h ;   these locations, but
  694. @@: ret ;   no others.
  695. isC000orE000 endp
  696. ;------------------------------------------------------------------------
  697. ;  UNMAP_PERMITED - This function will check if unmap roms is available.
  698. ;
  699. ;  Entry:    Nothing.
  700. ;
  701. ;  Returns:  Carry Flag Clear -  Can Unmap
  702. ;      Carry Flag Set   -  Can Not Unmap
  703. ;
  704. ;------------------------------------------------------------------------
  705. MACHINE_ID    equ  25h
  706. unmap_permited proc near ; == Check if unmap roms permitted ==
  707. mov al, MACHINE_ID ; CMOS location to read
  708. out 70h, al  ; Out CMOS location address
  709. in al, 71h  ; Read data at that location
  710. or al, al ; Q: Is it Zero
  711. jz unmap_permited_error ;  Y: Can not unmap
  712. test al, 1000b ; Q: can we unmap (Soft drive type)
  713. jz unmap_permited_ok ;  Y: continue
  714. unmap_permited_error:
  715. stc ; Set error condition - Can not unmap
  716. unmap_permited_ok:
  717. ret ; Done
  718. unmap_permited endp
  719. ;*----------------------------------------------------------------------*
  720. ;* *
  721. ;*  GetBIMMemory - *
  722. ;* *
  723. ;* Look for Compaq 'Built In Memory' and add it to the pool of *
  724. ;*  available memory *
  725. ;* *
  726. ;*  ARGS:   None *
  727. ;*  RETS:   AX = Amount of BIM memory found *
  728. ;*  REGS:   AX, BX, CX, and Flags are clobbered *
  729. ;* *
  730. ;*----------------------------------------------------------------------*
  731. ; "Built In Memory" (BIM) starts at FE00:0000h and grows downward.  It is
  732. ; controlled by a data structure at F000:FFE0h.  Changing the data structure
  733. ; involves un-write-protecting the ROMs (!) by flipping bit 1 of 80C00000.
  734. pBIMSTRUCT  equ     0FFE0h
  735. AVAILABLE   equ     0 ; Set to -1 if BIM isn't around
  736. TOTALBIM    equ     2 ; Total amount of BIM in the system
  737. AVAILBIM    equ     4 ; Amount of BIM available in paragraphs
  738. LASTUSED    equ     6 ; Paragraph address of last (lowest) used
  739. ;  paragraph of BIM
  740. GDT_TYPE    struc
  741. dw 0,0,0,0
  742. dw 0,0,0,0
  743. S_LIMIT     dw 1
  744. S_BASE_LOW  dw 0
  745. S_BASE_HI   db 0
  746. S_RIGHTS    db 93h
  747. S_RESERVED  dw 0
  748. D_LIMIT     dw 1
  749. D_BASE_LOW  dw 0000h
  750. D_BASE_HI   db 0C0h
  751. D_RIGHTS    db 93h
  752. D_RES386    db 0
  753. D_BASE_XHI  db 080h
  754. dw 0,0,0,0
  755. dw 0,0,0,0
  756. GDT_TYPE    ends
  757. BIMGDT GDT_TYPE <>
  758. GetBIMMemory proc near
  759. xor     ax,ax
  760. ; Are we on a Compaq 386 machine?
  761. push    bx
  762. push    es
  763. ; Is there a 32-bit memory board installed?
  764. mov es,cs:WORD PTR (pCOMPAQ+2) ; ROM segment
  765. mov     bx,pBIMSTRUCT
  766. mov     bx,es:[bx] ; De-reference the pointer
  767. mov     dx,es:[bx+AVAILABLE]    ; -1 means no board is installed
  768. inc     dx
  769. jz FCMNoMem2 ; Nope, return
  770. ; How much memory is available and where does it start?
  771. mov     dx,es:[bx+AVAILBIM]     ; Size in paragraphs
  772. or dx,dx ; Any left?
  773. jz FCMNoMem2
  774. mov     cx,dx ; CX = Size in paragraphs
  775. mov     ax,es:[bx+LASTUSED]
  776. sub     ax,cx ; AX = Starting location - F0000h
  777. ;  in paragraphs
  778. push    es ; Save for a rainy day...
  779. push    bx
  780. push    ax
  781. shr     ax,4 ; get base address in KBytes
  782. add     ax,0f000h
  783. shr     ax,2
  784. shr     cx,6 ; get the size in Kbytes
  785. mov     [BIMBase],ax ; store for use by HookInt15
  786. mov     [BIMLength],cx
  787. ; Un-WriteProtect the ROMs.
  788. mov     si,pBIMGDT ; Set up the BlockMove GDT
  789. mov     ax,cs
  790. mov     es,ax
  791. mov     cx,16
  792. mul     cx
  793. add     ax,offset BIMBuffer
  794. adc     dl,0
  795. mov     [si].S_BASE_LOW,ax
  796. mov     [si].S_BASE_HI,dl
  797. mov     cx,1
  798. mov     word ptr [BIMBuffer],0fefeh ; 0feh unlocks the ROMs
  799. mov     ah,87h ; Do the BlockMove
  800. int     15h
  801. or ah,ah ; Was there an error?
  802. jz FCMReserve ; Nope - continue
  803. ; Return error.
  804. pop     ax ; Clean up
  805. pop     bx
  806. pop     es
  807. xor     ax,ax
  808. mov     [BIMBase],ax
  809. mov     [BIMLength],ax
  810. FCMNoMem2:
  811. jmp     short FCMNoMem
  812. ; Change the ROM values to reserve the BIM stuff.
  813. FCMReserve:
  814. pop     ax
  815. pop     bx
  816. pop     es
  817. mov     word ptr es:[bx+AVAILBIM],0 ; Reserve all remaining BIM
  818. mov     word ptr es:[bx+LASTUSED],ax
  819. ; Re-WriteProtect the ROMs.
  820. push    cs
  821. pop     es
  822. mov     si,pBIMGDT ; Set up the BlockMove GDT
  823. mov     word ptr [BIMBuffer],0fcfch ; 0fch locks the ROMs
  824. mov     ah,87h ; Do the BlockMove
  825. int     15h
  826. mov     ax,1 ; Return success
  827. FCMNoMem:
  828. pop     es
  829. pop bx
  830. ret
  831. EndGetBIMMemory:
  832. GetBIMMemory endp
  833. ;*----------------------------------------------------------------------*
  834. ;* *
  835. ;*  CheckBIM - *
  836. ;* *
  837. ;* Check if Compaq built in memory is available *
  838. ;* *
  839. ;*  ARGS:   AX = Kbytes of int 15 memory *
  840. ;*  RETS:   AX = Amount of BIM and int 15 memory *
  841. ;*  REGS:   AX and Flags are clobbered *
  842. ;* *
  843. ;*----------------------------------------------------------------------*
  844. public CheckBIM
  845. CheckBIM  proc near
  846. push es
  847. push bx
  848. push dx
  849. call Compaq386 ; Are we on a Compaq 386 machine?
  850. jnz CBNoBIM  ; N: return
  851. mov bx,pBIMSTRUCT ; ROM data sructure
  852. mov bx,es:[bx] ; pointer to BIM data structure
  853. mov dx,es:[bx+AVAILABLE] ; -1 means no board is installed
  854. inc dx ;Q: Is there a 32-bit memory board installed?
  855. jz CBNoBIM ; N: return
  856. ; Y: How much memory is available?
  857. mov dx,es:[bx+AVAILBIM] ; Size in paragraphs
  858. or dx,dx ;Q: Any BIM available?
  859. jz CBNoBIM ; N: return
  860. call getBIMMemory ; allocate it and get base/size
  861. ; Just allocate the damn BIM memory now.  (Used to be a big headache
  862. ;   to install a deferred BIM driver, depending on whether Shadow
  863. ;   RAM was disabled.)
  864. mov cx,[BIMBase] ;   add Compaq BIM to our free list
  865. jcxz CBNoBIM
  866. mov     ax,[BIMLength]
  867. xor dx, dx
  868. mov bx, dx
  869. mov di, pAddMem
  870. push cs
  871. call call_hi_in_di
  872. CBNoBIM:
  873. pop dx
  874. pop bx
  875. pop es
  876. ret
  877. CheckBIM  endp
  878. ;*----------------------------------------------------------------------*
  879. ;* *
  880. ;*  Compaq386 -  *
  881. ;* *
  882. ;* Check if running on a Compaq 386 system. *
  883. ;* *
  884. ;*  ARGS:   none *
  885. ;*  RETS:   Z set - on a Compaq 386, NZ - not Compaq 386 *
  886. ;*     ES = ROM segment *
  887. ;*  REGS:   Flags are clobbered  *
  888. ;* *
  889. ;*----------------------------------------------------------------------*
  890. szCOMPAQ    db '03COMPAQ'
  891. public Compaq386
  892. Compaq386 proc near
  893. push si
  894. push di
  895. push cx
  896. les di,cs:pCOMPAQ ; Are we on a Compaq 386 machine?
  897. mov si,offset szCOMPAQ
  898. mov cx,8
  899. cld
  900. rep cmpsb ;Q: Are we?
  901. pop cx
  902. pop di
  903. pop si
  904. ret
  905. Compaq386 endp
  906. ;*----------------------------------------------------------------------*
  907. ;* *
  908. ;*  CheckZBim - *
  909. ;* *
  910. ;* Check if Zenith Bim (0fa0000h x 256K) is available *
  911. ;*    Call AddMem with it if so *
  912. ;* *
  913. ;*----------------------------------------------------------------------*
  914. ZDS_string db 'ZDS CORP'
  915. ZDS_len = ($-ZDS_string)
  916. f000 dw 0f000h
  917. public CheckZBIM
  918. CheckZBim proc near
  919. call GetInt15Memory ; This code added for old systems with
  920. cmp ax, 2048 ;   low memory, skip it if 'sufficient'
  921. jae no_ZBIM  ;   ext memory cause it scribbles on
  922. ;   memory just below 16 meg
  923. cld ; better safe than sorry
  924. mov si,offset ZDS_string
  925. mov es,f000
  926. mov di,800ch ; look for ZDS CORP at f000:800c
  927. mov cx,ZDS_len
  928. repz cmpsb
  929. jnz no_ZBim ; done if not Zenith machine
  930. ; Now we've got to go out and look for 256KBytes at 0fa0000h
  931. ;   Let's use the BlockMove function to help us with that so we
  932. ;   don't have to write any messy protect mode code.  We'll
  933. ;   snag a handle and set up a dummy block while we work.
  934. cli
  935. push es
  936. mov es,hiseg
  937. assume es:funky
  938. mov di,[KiddValley]
  939. mov cx,[cHandles]
  940. chk_zb0:
  941. cmp [di].Flags,UNUSEDFLAG
  942. jz ZBim_01 ; brif found free handle
  943. add di,SIZE Handle
  944. loop chk_zb0
  945. pop es
  946. sti ; restore interrupts
  947. no_ZBim:
  948. ret
  949. ZBim_01:
  950. mov [di].cLock,1 ; lock it
  951. mov [di].Base.lo,3e80h ; number of K at 0fa0000h
  952. mov [di].Base.hi,0
  953. mov [di].Len.lo,256
  954. mov [di].Len.hi, 0
  955. mov [di].Flags, USEDFLAG
  956. pop es
  957. assume es:nothing
  958. sti
  959. mov save_ss,ss ; get more elbow room for this
  960. mov save_sp,sp
  961. push cs
  962. pop ss
  963. mov sp,offset EISA_stack
  964. ; allocate a move structure on the stack
  965. ;   for now, we'll just test the first 512 bytes.  It might be
  966. ;   a good idea to test the whole damn thing, but a lot more work.
  967. sub sp,0fffeh and (1+SIZE MoveExtendedStruc)
  968. push    ss ; point es:si to stack frame
  969. pop es
  970. mov si,sp
  971. mov es:[si].SourceHandle,0 ; move from conventional memory
  972. mov es:[si].DestHandle,di ; to our fake block at 0fa0000h
  973. mov es:word ptr [si].DestOffset,0 ; move data to base of block
  974. mov es:word ptr [si].DestOffset+2,0
  975. mov es:word ptr [si].SourceOffset,8000h
  976. mov es:word ptr [si].SourceOffset+2,0f000h ; move from ROM
  977. mov es:word ptr [si].bCount,512 ; move 512 bytes
  978. mov es:word ptr [si].bCount+2,0
  979. push si ; save move structure
  980. push    di ; save handle
  981. push cs ; fake far call
  982. call BlockMove
  983. pop di
  984. pop si
  985. ; now move the 512 bytes back out into our buffer and compare
  986. push ss
  987. pop es
  988. mov es:[si].SourceHandle,di ; move from the fake block
  989. mov es:[si].DestHandle,0 ; to conventional memory
  990. mov es:word ptr [si].DestOffset,offset ZDS_Buffer
  991. mov es:word ptr [si].DestOffset+2,cs
  992. mov es:word ptr [si].SourceOffset,0
  993. mov es:word ptr [si].SourceOffset+2,0
  994. push di ; save handle for deallocation
  995. push cs ; fake far call
  996. call BlockMove
  997. ; now all we've gotta do is see if the ZDS_Buffer matches the
  998. ;   first 512 bytes of the ROM at 0f000:8000
  999. mov es,f000
  1000. mov di,8000h
  1001. mov si,offset ZDS_Buffer
  1002. mov cx,256 ; 256 words
  1003. repz cmpsw ; does it match?
  1004. jnz check_zb1 ; done if not
  1005. ; Use AddMem to add the memory to our pool, even though we
  1006. ;   could have just marked the fake block we allocated as UNUSED.
  1007. ;   Why?  What if some other source (like and EISA BIOS) also
  1008. ;   told us about that same memory?  We might as well take advantage
  1009. ;   of all of the smarts in AddMem to eliminate overlaps.
  1010. mov cx,3e80h ; add memory to pool then
  1011. mov ax,256
  1012. xor dx, dx
  1013. mov bx, dx
  1014. mov di, pAddMem
  1015. push cs
  1016. call call_hi_in_di
  1017. ; Now we've got to fill the damn block, cuz the
  1018. ;   parity isn't initialized yet.
  1019. push ds
  1020. pop es
  1021. mov di,offset ZDS_Buffer
  1022. mov cx,256
  1023. xor ax,ax
  1024. rep stosw ; fill 512 byte block with zeros
  1025. push ss ; point es: to stack frame again
  1026. pop es
  1027. mov es:[si].SourceHandle,0 ; move from conventional memory
  1028. pop di
  1029. push di ; get handle from stack
  1030. mov es:[si].DestHandle,di ; to our fake block at 0fa0000h
  1031. mov es:word ptr [si].DestOffset,0 ; move data to base of block
  1032. mov es:word ptr [si].DestOffset+2,0
  1033. mov es:word ptr [si].SourceOffset,offset ZDS_Buffer
  1034. mov es:word ptr [si].SourceOffset+2,cs ; move from ZDS_Buffer
  1035. mov es:word ptr [si].bCount,512 ; move 512 bytes
  1036. mov es:word ptr [si].bCount+2,0
  1037. mov cx,512 ; 256K/512 bytes
  1038. zfill_loop:
  1039. push es
  1040. push si
  1041. push cx
  1042. push cs ; fake far call
  1043. call BlockMove
  1044. pop cx
  1045. pop si
  1046. pop es
  1047. add es:word ptr [si].DestOffset,512
  1048. jnc zfill_skip
  1049. inc es:word ptr [si].DestOffset+2
  1050. zfill_skip:
  1051. loop zfill_loop
  1052. check_zb1:
  1053. ; Release the move structure stack frame
  1054. pop di ; restore temporary handle
  1055. add sp,0fffeh and (1+SIZE MoveExtendedStruc)
  1056. push es
  1057. mov es,hiseg
  1058. assume es:funky
  1059. mov [di].Flags,UNUSEDFLAG ; then handle is free again
  1060. pop es
  1061. assume es:nothing
  1062. mov ss,save_ss
  1063. mov sp,save_sp ; restore normal stack
  1064. ret
  1065. CheckZBim endp
  1066. ; Call MoveIt function in other segment.  Make sure we enable A20.
  1067. BlockMove proc near
  1068. ifdef debug_tsr
  1069.         jmp     MoveIt
  1070. else
  1071. mov di,MoveIt ; get function in funky segment
  1072. jmp call_hi_in_di
  1073. endif
  1074. BlockMove endp
  1075. ;*----------------------------------------------------------------------*
  1076. ;* *
  1077. ;*  GetInt15Memory - *
  1078. ;* *
  1079. ;* Returns the amount of memory INT 15h, Function 88h says is free *
  1080. ;* *
  1081. ;*  ARGS:   None *
  1082. ;*  RETS:   AX = Amount of free extended memory in K-bytes *
  1083. ;*  REGS:   AX and Flags are clobbered *
  1084. ;* *
  1085. ;*----------------------------------------------------------------------*
  1086. GetInt15Memory proc near
  1087. mov ah,88h ; snag the int 15h memory
  1088. clc
  1089. int 15h ; Is Function 88h around?
  1090. jnc     xret_geti15
  1091. xor ax,ax ; No, return 0
  1092. xret_geti15:
  1093. ifdef WIN30COMPATIBLE
  1094. cmp ax,15*1024 ; Limit himem.sys to using 15 meg
  1095. jb @f ;   of extended memory for apps
  1096. mov ax,15*1024 ;   that don't deal with > 24 bit
  1097. @@: ;   addresses
  1098. endif
  1099. ret
  1100. GetInt15Memory endp
  1101. ;*--------------------------------------------------------------------------*
  1102. ;*                                                                          *
  1103. ;*  GetBIGMemory -                                                          *
  1104. ;*                                                                          *
  1105. ;*      Returns the amount of memory Extended INT 15h, >16 Meg              *
  1106. ;*      Uses new INT 15 function E801                                       *
  1107. ;*                                                                          *
  1108. ;*  ARGS:   None                                                            *
  1109. ;*  RETS:   None     *
  1110. ;*  REGS:   AX and Flags are clobbered                                      *
  1111. ;*                                                                          *
  1112. ;*--------------------------------------------------------------------------*
  1113. GetBIGMemory proc near
  1114.         push    dx
  1115.         push    cx
  1116.         push    bx
  1117.         push    si
  1118.         push    es
  1119.         call    IsEISAMachine       ; Is this an EISA machine ?
  1120. jc short GBM_end     ;  Y: Ignore parameter
  1121. call Compaq386     ; is it a Compaq system?
  1122. jnz short GBM_end
  1123.         mov     ax,0E801h           ; determine >16M memory
  1124.         clc
  1125. int 15h     ; Is Function 88h around?
  1126. jc short GBM_end     ; No, exit
  1127.         mov     ax,bx               ; DX:AX to = length of block in 1K blocks
  1128.         mov     dx,64               ; DX should always be zero (16M extra max)
  1129.         mul     dx
  1130.         mov     cx,BIGISA_START     ; BIGISA_START=16384 in (HIMEM.INC)
  1131. xor dx, dx
  1132. mov bx, dx
  1133. mov di, pAddMem
  1134. push cs
  1135. call call_hi_in_di     ; add that memory to our tables
  1136.         les     si,dword ptr pInt15Vector   ; Save the current INT 15 vector.
  1137. cli
  1138.         mov     ax,offset ISA15Handler      ; Exchange the old vector with
  1139.         xchg    ax,es:[si][0]               ;  the new one.
  1140.         mov     word ptr [PrevISAInt15][0],ax
  1141.         mov     ax,cs
  1142.         xchg    ax,es:[si][2]
  1143. mov word ptr [PrevISAInt15][2],ax
  1144. sti
  1145. GBM_end:
  1146.         pop     es
  1147.         pop     si
  1148.         pop     bx
  1149.         pop     cx
  1150.         pop     dx
  1151.         ret
  1152. GetBIGMemory endp
  1153. ;*--------------------------------------------------------------------------*
  1154. ;*                                                                          *
  1155. ;*  IsEISAMachine                                           HARDWARE DEP.   *
  1156. ;*                                                                          *
  1157. ;*  Determine if we are on an EISA machine                                  *
  1158. ;*                                                                          *
  1159. ;*  ARGS:   None                                                            *
  1160. ;*  RETS:   CY = 1 if we're on a EISA machine                               *
  1161. ;*             = 0 otherwise                                                *
  1162. ;*  REGS:   Flags clobbered                                                 *
  1163. ;*                                                                          *
  1164. ;*--------------------------------------------------------------------------*
  1165. pEISASTRUC  equ     0FFD9h      ; offset to EISA name in ROM
  1166. pROM     equ     0F000h ; ROM segment
  1167. IsEISAMachine     proc    near                                            ;
  1168.         push    es                      ; save registers we'll use
  1169.         push    bx                      ;  ...
  1170.     ;-----------------------------------------
  1171.     ; Determine if this is an EISA system by
  1172.     ;  looking for ROM signature
  1173.     ;-----------------------------------------
  1174.         mov     bx,pROM
  1175.         mov     es,bx                   ; ROM segment
  1176.         mov     bx,pEISASTRUC           ; offset to EISA name
  1177.         cmp     word ptr es:[bx],'IE'   ; Q: is this an 'EISA' system
  1178.         jne     short IEM_NO            ;  N: set flag and return
  1179.         cmp     word ptr es:[bx+2],'AS' ;
  1180.         je      short IEM_YES           ;  Y: set flag and return
  1181. IEM_NO:
  1182.         clc                             ; Not an EISA machine...
  1183.         jmp     short IEM_Done
  1184. IEM_YES:
  1185.         stc                             ; Yes, it is an EISA box
  1186. IEM_Done:
  1187.         pop     bx
  1188.         pop     es
  1189.         ret
  1190. IsEISAMachine        endp
  1191. ;*----------------------------------------------------------------------*
  1192. ;* *
  1193. ;*  GetParms - *
  1194. ;* *
  1195. ;* Get any parameters off of the HIMEM command line *
  1196. ;* *
  1197. ;*  ARGS:   None *
  1198. ;*  RETS:   None *
  1199. ;*  REGS:   AX, BX, CX, DX, DI, SI, ES and Flags clobbered *
  1200. ;* *
  1201. ;*  Side Effects:   cHandles and MinHMASize may be changed *
  1202. ;* *
  1203. ;*----------------------------------------------------------------------*
  1204. GPArgPtr dd ?
  1205. GPRegSave dw ?
  1206. public GetParms
  1207. GetParms    proc    near
  1208. cld ; better safe than sorry
  1209. push ds
  1210. ifdef debug_tsr ;-------------------------------
  1211. lds si,lpCmdLine
  1212. else ;-------------------------------
  1213. les di,[pReqHdr] ; Running as a device driver
  1214. lds si,es:[di].pCmdLine ; DS:SI points to first char
  1215. ;   after "DEVICE="
  1216. @@: call GPGetChar ; Skip over driver name, up to
  1217. jc GPDatsAll ;   first blank or / or eol
  1218. jz GPNextArg
  1219. cmp al,'/'
  1220. jnz @b
  1221. dec si ; Backup to get / again
  1222. endif ;-------------------------------
  1223. assume ds:nothing,es:nothing
  1224. ; Scan until we see a non-blank or the end of line.
  1225. GPNextArg:
  1226. call GPGetChar
  1227. jc GPDatsAll ; eol
  1228. jz GPNextArg ; blank
  1229. mov word ptr cs:[GPArgPtr], si ; save ptr to start of arg
  1230. mov word ptr cs:[GPArgPtr+2], ds ;   incase we want to complain
  1231. dec word ptr cs:[GPArgPtr] ;   (GPGetChar points at next)
  1232. cmp al,'/' ; better be a / or not a valid arg
  1233. jz GPGotOne
  1234. ; Detected invalid parameter or value, complain to user
  1235. GPBadParm:
  1236. mov ah,9 ; tell'm something isn't right
  1237. push cs
  1238. pop ds
  1239. mov dx, offset BadArgMsg
  1240. call DispErrMsg
  1241. lds si,cs:[GPArgPtr] ; backup to last parameter
  1242. GPBadDisp:
  1243. call GPGetChar ; disp arg up to space or eol
  1244. jc GPDatsAll ;  skips over bad arg while we're at it
  1245. jz GPNextArg
  1246. cmp al,'/' ; start of next arg?
  1247. jnz @f
  1248. dec si ; maybe yes, maybe no--might
  1249. cmp si,word ptr cs:[GPArgPtr] ;   be same arg
  1250. jnz GPNextArg ;   next, go process new arg
  1251. inc si ;   same, keep displaying
  1252. @@:
  1253. mov dl,al
  1254. call DispInfoChar
  1255. jmp short GPBadDisp
  1256. ; Finished, we're outta here...
  1257. GPDatsAll:
  1258. jmp GPExit
  1259. ; Save what we found and try to process as parameter without argument
  1260. GPGotOne:
  1261. lodsb
  1262. mov cs:[GPRegSave],ax
  1263. mov bx, offset ParmTbl1 ; Process parameters with no arguments
  1264. call GPCheckParm
  1265. jc GPNeedParm ; CY means it wasn't processed
  1266. GPSkip2Next: ; Parameter was processed, skip
  1267. call GPGetChar ;   over any remaining text in the
  1268. jc GPDatsAll ;   parameter name
  1269. jz GPNextArg
  1270. cmp al,'/'
  1271. jnz GPSkip2Next
  1272. dec si ; backup to get / again
  1273. jmp GPNextArg
  1274. ; Must need an argument -- scan for a number, EOL, or a space.
  1275. GPNeedParm:
  1276. call GPGetChar
  1277. jc GPBadParm
  1278. jz GPBadParm ; blank
  1279. cmp al,':' ; start of string arg
  1280. je GPString
  1281. cmp al,'='
  1282. jne GPNeedParm
  1283. ; Read the number at DS:SI into DX
  1284. GPNeedNum:
  1285. call GPGetChar
  1286. jc GPDatsAll
  1287. cmp al,'0'
  1288. jb GPNeedNum
  1289. cmp al,'9'
  1290. ja GPNeedNum
  1291. xor dx,dx
  1292. GPNumLoop:
  1293. sub al,'0'
  1294. cbw
  1295. add dx,ax
  1296. call GPGetChar
  1297. jc GPNumDone
  1298. jz GPNumDone
  1299. cmp al,'0'
  1300. jb GPBadParm
  1301. cmp al,'9'
  1302. ja GPBadParm
  1303. shl dx,1 ; Stupid multiply DX by 10
  1304. mov bx,dx
  1305. shl dx,1
  1306. shl dx,1
  1307. add dx,bx
  1308. jmp short GPNumLoop
  1309. ; Move the string arg from ds:si to StringParm
  1310. GPString:
  1311. mov cx,(SIZE StringParm) - 1
  1312. push cs
  1313. pop es
  1314. mov di,offset _text:StringParm
  1315. GPStrLoop:
  1316. call GPGetChar
  1317. jc GPStrDone
  1318. jz GPStrDone
  1319. stosb
  1320. loop GPStrLoop
  1321. GPStrDone:
  1322. mov byte ptr es:[di],0 ; Null terminate the string
  1323. mov dx,-1 ; In case parm expects a num, give'm
  1324. ;   a likely invalid one
  1325. ; Which parameter are we dealing with here?
  1326. GPNumDone:
  1327. xchg ax,cs:[GPRegSave]
  1328. mov bx, offset ParmTbl2 ; parameters with arguments
  1329. call GPCheckParm ; process it valid
  1330. jnc GPNextParm
  1331. jmp GPBadParm
  1332. GPNextParm:
  1333. mov ax,cs:[GPRegSave] ; are we at the end of the line?
  1334. cmp al,13 ; may not be needed any longer...
  1335. je GPExit
  1336. cmp al,10
  1337. je GPExit
  1338. jmp GPNextArg
  1339. GPExit:
  1340. call GPPrintInfo ; Display user messages
  1341. pop ds
  1342. ret
  1343. GetParms    endp
  1344. ;*----------------------------------------------------------------------*
  1345. ; In:  AL =  1st character of parameter
  1346. ;      BX -> Parameter table to use
  1347. ; Out: CY set if parameter not matched
  1348. ;      CY clear if parameter matched, and routine will be called
  1349. GPCheckParm proc near
  1350. GPCP_loop:
  1351. cmp cs:[bx].cParmChar, 0 ; end of table?
  1352. je GPCP_failed
  1353. cmp cs:[bx].cParmChar, al ; match?
  1354. je GPCP_match
  1355. add bx, SIZE ParmEntry
  1356. jmp short GPCP_loop
  1357. GPCP_match:
  1358. clc ; got it, call routine to process
  1359. call cs:[bx].pParmRtn ; (handler returns with CY clr or set)
  1360. ret
  1361. GPCP_failed:
  1362. stc ; no match
  1363. ret
  1364. GPCheckParm endp
  1365. ;*----------------------------------------------------------------------*
  1366. ; Routines to process specific command line parameters
  1367. GPDoParameters proc near
  1368. ;---------------------------------------
  1369. GPGotEISA: ; /EISA
  1370. mov fEISA, 0FFh
  1371. ret ; (CY already clear)
  1372. GPGotVerbose: ; /VERBOSE
  1373. mov fQuiet, 0
  1374. ret ; (CY already clear)
  1375. GPGotBigMem: ; /NOABOVE16
  1376. cmp byte ptr [si], 'O' ; /NOABOVE16 & /NUMHANDLES= both start
  1377. jne GPBadParmRet ;   with 'N', make sure only /NOABOVE16
  1378. ;   is processed here.
  1379. mov fBigMem, 0
  1380. ret ; (CY already clear)
  1381. ; The /Z switch is for compatibility with pervious version of himem.
  1382. ; By default, himem will now call it's own XMMControl entry point to
  1383. ; enable/disable A20 around calls to himem code in the HMA.  The
  1384. ; external calls allow XMS hookers (like EMM386) to see the A20
  1385. ; changes.  The previous behavior of calling internal A20 routines
  1386. ; can be selected with the /Z switch in case the external (recursive)
  1387. ; calls cause compatibility problems with other software.
  1388. GPZSwitch: ; /Z switch
  1389. mov cs:[pfnEnabA20],  offset _text:LocalEnableA20
  1390. mov cs:[pfnDisabA20], offset _text:LocalDisableA20
  1391. ret ; (CY already clear)
  1392. ;---------------------------------------
  1393. ; Process /A20CONTROL: parameter
  1394. GPGotA20Control:
  1395. mov ax,word ptr [StringParm]
  1396. or ax,2020h
  1397. mov bl,0FFh
  1398. cmp ax,'no'  ; ON ? - means we take control
  1399. jz GPSetA20
  1400. inc bl
  1401. cmp ax,'fo'  ; OFF ? - means we leave alone if on
  1402. jz GPSetA20
  1403. GPBadParmRet: ; common failure exit
  1404. stc
  1405. ret
  1406. GPSetA20:
  1407. mov fA20Control,bl ; Z if A20 should be left alone if
  1408. ;   it's already on when we're loaded
  1409. GPGoodParmRet: ; common success exit
  1410. clc
  1411. ret
  1412. ;---------------------------------------
  1413. ; Process /MACHINE: parameter.
  1414. GPGotMachine:
  1415. push si ; save current location
  1416. push ds ;    in param string
  1417. push cs
  1418. pop ds
  1419. mov di,offset _text:MachineName ; es:di -> MachineName
  1420. GPNextTbl:
  1421. xor bx,bx
  1422. GPNextName:
  1423. mov si,offset _text:StringParm ; ds:si -> StringParm
  1424. GPChkNext:
  1425. cmp byte ptr es:[di],0FFh ; end of name table?
  1426. jz GPNoName
  1427. lodsb ; char from StringParm
  1428. cmp al,'A' ; force to lower case for match
  1429. jb @f ; (might be numeric, so don't just OR)
  1430. cmp al,'Z'
  1431. ja @f
  1432. or al,20h
  1433. @@:
  1434. cmp al,es:[di] ; match so far?
  1435. jnz GPFlushName
  1436. or al,al ; finished if matched up to & incl NULL
  1437. jz GPFoundName
  1438. inc di ; still matches, check next char
  1439. jmp short GPChkNext
  1440. GPFlushName:
  1441. inc bx
  1442. GPFN2:
  1443. inc di
  1444. cmp byte ptr es:[di],0FFh
  1445. jz GPNoName
  1446. cmp byte ptr es:[di],0
  1447. jnz GPFN2
  1448. inc di
  1449. jmp short GPNextName
  1450. GPFoundName:
  1451. mov cs:[MachineNum],bx ; found a match, remember which entry
  1452. jmp short GPNameDone ;   it is for later
  1453. GPNoName:
  1454. cmp di,offset _text:AltNameTbl
  1455. ja GPBadName
  1456. mov di,offset _text:AltNameTbl
  1457. jmp short GPNextTbl
  1458. GPNameDone:
  1459. pop ds ; recover parm line pointer
  1460. pop si
  1461. jmp GPGoodParmRet
  1462. GPBadName:
  1463. pop ds ; clear stack and error out...
  1464. pop si
  1465. jmp GPBadParmRet
  1466. ;---------------------------------------
  1467. ; Process /NUMHANDLES= parameter.
  1468. GPGotHands:
  1469. cmp dx,MAXHANDLES
  1470. jna @f
  1471. jmp GPBadParmRet
  1472. @@:
  1473. or dx,dx ; Zero?
  1474. jnz @f
  1475. jmp GPBadParmRet
  1476. @@:
  1477. push es
  1478. mov es,hiseg
  1479. assume es:funky
  1480. mov     [cHandles],dx ; Store it
  1481. pop es
  1482. assume es:nothing
  1483. mov fNumHandSet, 0FFh
  1484. jmp GPGoodParmRet
  1485. ;---------------------------------------
  1486. ;  Process /HMAMIN= parameter
  1487. GPGotMin:
  1488. cmp dx,64
  1489. jna @f
  1490. jmp GPBadParmRet
  1491. @@:
  1492. mov cl,10 ; Convert from K to bytes
  1493. shl dx,cl
  1494. mov cs:[MinHMASize],dx
  1495. mov fHMAminSet, 0FFh
  1496. jmp GPGoodParmRet
  1497. ;---------------------------------------
  1498. ; Process /SHADOWRAM: parameter
  1499. GPGotShadow:
  1500. mov ax,word ptr [StringParm]
  1501. or ax,2020h
  1502. xor bl,bl
  1503. cmp ax,'no'  ; ON ? - means we leave it alone
  1504. jz GPSetShadow
  1505. inc bl
  1506. cmp ax,'fo'  ; OFF ? - means we turn it off
  1507. jz GPSetShadow
  1508. jmp GPBadParmRet
  1509. GPSetShadow:
  1510. mov fShadowOff,bl ; NZ if Shadow RAM should be turned off
  1511. jmp GPGoodParmRet
  1512. ;---------------------------------------
  1513. ; Process /CPUCLOCK: parameter
  1514. GPGotCPUClock:
  1515. mov ax,word ptr [StringParm]
  1516. or ax,2020h
  1517. xor bl,bl
  1518. cmp ax,'fo'  ; OFF ? - means we don't worry about it
  1519. jz GPSetClock
  1520. inc bl
  1521. cmp ax,'no'  ; ON ? - means we preserve CPU clock
  1522. jz GPSetClock ;   rate
  1523. jmp GPBadParmRet
  1524. GPSetClock:
  1525. mov fCPUClock,bl ; NZ if clock rate preserved
  1526. jmp GPGoodParmRet
  1527. ;---------------------------------------
  1528. ; Process /INT15= parameter
  1529. GPGotInt15:
  1530. cmp dx, 64 ; atleast 64K
  1531. jae @f
  1532. jmp GPBadParmRet
  1533. @@: call GetInt15Memory
  1534. cmp ax, dx ; enuf Ext Mem ?
  1535. jae @f
  1536. jmp GPBadParmRet
  1537. @@: mov [Int15MemSize], dx
  1538. jmp GPGoodParmRet
  1539. GPDoParameters endp
  1540. ;*----------------------------------------------------------------------*
  1541. ; Get the next character from DS:SI, set CY if it's an EOL (CR, LF), set
  1542. ; Z if it's a space
  1543. GPOffEOL dw -1
  1544. public GPGetChar
  1545. GPGetChar proc near
  1546. cmp si,cs:[GPOffEOL] ; are we already at EOL?
  1547. jnb GPAtEOL
  1548. lodsb ; no, get next char
  1549. cmp al,10 ; is this the EOL?
  1550. je GPHitEOL
  1551. cmp al,13
  1552. je GPHitEOL
  1553. cmp al,' ' ; set Z if blank
  1554. clc
  1555. ret
  1556. GPHitEOL:
  1557. mov cs:[GPOffEOL],si ; save EOL offset once
  1558. GPAtEOL:
  1559. stc
  1560. ret
  1561. GPGetChar endp
  1562. ;*----------------------------------------------------------------------*
  1563. ;  Print user msgs now instead of while processing so they can be
  1564. ;  suppressed if /V (verbose) doesn't appear on command line.
  1565. GPPrintInfo proc   near
  1566. ; /NUMHANDLES=
  1567. cmp fNumHandSet, 0
  1568. je GPPI_HMAMin
  1569. mov dx,offset StartMsg ; display descriptive message
  1570. call    GPPrintIt
  1571. push es
  1572. mov es,hiseg
  1573. mov ax,es:[cHandles]
  1574. pop es
  1575. call    GPPrintAX
  1576. mov dx,offset HandlesMsg
  1577. call GPPrintIt
  1578. GPPI_HMAMin:
  1579. ; /HMAMIN=
  1580. cmp fHMAminSet, 0
  1581. je GPPI_exit
  1582. mov dx,offset HMAMINMsg ; print a descriptive message
  1583. call    GPPrintIt
  1584. mov ax,cs:[MinHMASize]
  1585. mov cl, 10 ; convert from bytes to k
  1586. shr ax, cl
  1587. call    GPPrintAX
  1588. mov dx,offset KMsg
  1589. call    GPPrintIt
  1590. GPPI_exit:
  1591. ret
  1592. GPPrintInfo endp
  1593. ;*----------------------------------------------------------------------*
  1594. GPPrintIt   proc    near
  1595. push    ds ; Save current DS
  1596. push    cs ; Set DS=CS
  1597. pop ds
  1598. call DispInfoMsg
  1599. pop ds ; Restore DS
  1600. ret
  1601. GPPrintIt   endp
  1602. ;*----------------------------------------------------------------------*
  1603. GPPrintAX   proc    near
  1604. mov cx,10
  1605. xor dx,dx
  1606. div cx
  1607. or ax,ax
  1608. jz GPAPrint
  1609. push    dx
  1610. call    GPPrintAX
  1611. pop dx
  1612. GPAPrint:
  1613. add dl,'0'
  1614. call DispInfoChar
  1615. ret
  1616. GPPrintAX   endp
  1617. ;*----------------------------------------------------------------------*
  1618. ;* *
  1619. ;*  InitHandles - *
  1620. ;* *
  1621. ;* Initialize the Extended Memory Handle Table *
  1622. ;* *
  1623. ;*  ARGS:   None *
  1624. ;*  RETS:   None *
  1625. ;*  REGS:   AX, BX, CX, and Flags are clobbered *
  1626. ;* *
  1627. ;*----------------------------------------------------------------------*
  1628. assume ds:_text
  1629. public InitHandles
  1630. InitHandles proc    near
  1631. push es
  1632. mov es,hiseg
  1633. assume es:funky
  1634. mov cx,[cHandles]
  1635. ; Init the Handle table.
  1636. mov bx,[KiddValley]
  1637. xor ax,ax
  1638. IHTabLoop:
  1639. mov [bx].Flags,UNUSEDFLAG
  1640. mov [bx].cLock,al
  1641. mov [bx].Base.lo,ax
  1642. mov [bx].Base.hi,ax
  1643. mov [bx].Len.lo,ax
  1644. mov [bx].Len.hi,ax
  1645. if keep_cs
  1646. mov [bx].Acs,ax
  1647. endif
  1648. add bx,SIZE Handle
  1649. loop    IHTabLoop
  1650. mov [KiddValleyTop],bx ; save top for handle validation
  1651. pop es
  1652. assume es:nothing
  1653. ret
  1654. InitHandles endp
  1655. ;*----------------------------------------------------------------------*
  1656. ;* *
  1657. ;*  ScanEISA - poll any EISA devices through the BIOS's Int15(0d8h) *
  1658. ;*     and add any memory we find out about to our free memory table. *
  1659. ;*     Note:  this code (including a big buffer) gets thrown out after *
  1660. ;*     completion of the initialization sequence. *
  1661. ;* *
  1662. ;* Note:  The COMPAQ BIOS uses up 1.5K of stack during int15(d80x) *
  1663. ;* so we'll set up a separate stack while we're here *
  1664. ;* *
  1665. ;*----------------------------------------------------------------------*
  1666. save_ss dw 0
  1667. save_sp dw 0
  1668. public ScanEISA
  1669. ScanEISA proc near
  1670. assume ds:_text
  1671. mov save_ss,ss
  1672. mov save_sp,sp
  1673. push cs
  1674. pop ss
  1675. mov sp,offset EISA_stack
  1676. xor cl,cl ; start with slot zero
  1677. SEISA_01:
  1678. push    cx ; save slot number
  1679. mov ax,0d800h ; get summary of configuration
  1680. int 15h
  1681. pop cx ; restore slot number
  1682. jc SEISA_09 ;  skip if any kind of error
  1683. test    dl,2 ; does that slot have any memory?
  1684. jz SEISA_09 ;  skip if not
  1685. cmp dh,0 ; zero functions would be an
  1686. jz SEISA_09 ;  error condition
  1687. mov ch,dh ; copy function number to ch
  1688. ; Now we've found a valid slot with some memory.  Let's find out
  1689. ;   what kind of memory it is, where its located, and how much there is.
  1690. SEISA_02:
  1691. push    cx ; save slot and function
  1692. mov ax,0d801h ; read function information
  1693. lea si,EISABuffer ; pass pointer to our buffer
  1694. int 15h
  1695. jc SEISA_04 ; brif any error
  1696. ; Now look into buffer for memory information
  1697. test    byte ptr EISA_FncInfo,80h ; function disabled?
  1698. jnz SEISA_04 ;  brif so
  1699. test    byte ptr EISA_FncInfo,2 ; memory information follows?
  1700. jz SEISA_04 ;  done if not
  1701. lea si,EISA_MemConfig ; point to memory information
  1702. SEISA_03:
  1703. ; M007
  1704. mov al, ds:byte ptr [si]
  1705. and al, 079h
  1706. cmp al, 1 ; Make sure that Reserved bit = 0
  1707. ;  Shared bit   = 0
  1708. ;  memory type = SYSTEM
  1709. ;  Read/Write  = TRUE
  1710. jne SEISA_03a ; (See EISA spec for bit definitions)
  1711. ; M007
  1712. mov cx,ds:word ptr 2[si]    ; get base address in 256 bytes
  1713. mov bl,ds:byte ptr 4[si]    ;  get highest byte
  1714. xor bh, bh
  1715. mov al,cl ; save lowest bits for later
  1716. shr bl,1 ; convert to our internal 1k format
  1717. rcr cx,1
  1718. shr bl,1
  1719. rcr cx,1
  1720. test    al,3 ; was base not on a 1k boundary?
  1721. mov ax,ds:word ptr 5[si]    ; get length in k
  1722. jz SEISA_03b ;  brif base was on 1k boundary
  1723. dec ax ; sacrifice the partial k
  1724. add cx,1 ; and bump base to first complete k
  1725. adc bx,0
  1726. SEISA_03b:
  1727. xor dx, dx
  1728. or ax, ax
  1729. jnz @f
  1730. inc dx
  1731. @@:
  1732. push    si
  1733. cmp cx,1024 ; is it below a meg?
  1734. jb seisa_0xx ; ignore it if so
  1735. ifdef WIN30COMPATIBLE ;M005
  1736. or bx, bx
  1737. jnz seisa_0xx
  1738. cmp cx,1024*16 ; is it above 16 meg?
  1739. jae seisa_0xx ; ignore it if so
  1740. endif                                           ;M005
  1741. mov di, pAddMem
  1742. push cs
  1743. call call_hi_in_di ; add that memory to our tables
  1744. seisa_0xx:
  1745. pop si
  1746. SEISA_03a:
  1747. add si,7 ; next entry
  1748. test    ds:byte ptr -7[si],80h  ;  was that the last one?
  1749. jnz SEISA_03 ;  loop if not
  1750. SEISA_04:
  1751. pop cx ; restore slot and function
  1752. dec ch ; next lower function
  1753. jnl SEISA_02 ; valid functions are 0..n
  1754. SEISA_09:
  1755. inc cl ; next slot
  1756. cmp cl,16
  1757. jae @f
  1758. jmp SEISA_01
  1759. @@:
  1760. ; Now check for EISA memory and Int 15h/88h overlap.  In the default case
  1761. ; we'll ignore any EISA blocks starting at 1Meg under the assumption that
  1762. ; this memory will be claimed later via the Int 15h hook.  If the Int 15h/88h
  1763. ; call indicates less memory than the EISA scan, it may be that an Int 15h
  1764. ; allocator has been loaded before us, and if we just grabbed all EISA
  1765. ; memory starting at 1Meg, we would stomp all over them.  On the other hand,
  1766. ; a number of BIOS' never return > 15 (16?) meg of extended memory via Int 15h
  1767. ; (even if there is much more memory installed), so we provide the /EISA
  1768. ; command line parameter to override this default and allow himem to steal
  1769. ; all EISA memory.  If the /EISA switch is used, there better not be any
  1770. ; Int 15h allocators loaded before himem!
  1771. ; Locate a free memory block in the handle table at 1 Meg (1024k)
  1772. push es
  1773. mov es,hiseg
  1774. assume es:funky
  1775. mov bx,[KiddValley]
  1776. mov     cx,[cHandles] ; Loop through the handle table
  1777. SEISA_09a:
  1778. cmp [bx].Flags,FREEFLAG ; is this a valid free memory block?
  1779. jnz SEISA_09b ; branch if not
  1780. cmp [bx].Base.hi, 0
  1781. jnz SEISA_09b
  1782. cmp [bx].Base.lo,1024 ; based at 1Meg?
  1783. jz SEISA_09c ; yup...
  1784. SEISA_09b:
  1785. add bx,SIZE Handle
  1786. loop    SEISA_09a
  1787. jmp short SEISA_09e
  1788. SEISA_09c:
  1789. cmp fEISA, 0 ; want all EISA memory, regardless?
  1790. jz SEISA_default ; no...
  1791. ifdef WIN30COMPATIBLE ;GetInt15Memory has an ifdef WIN30COMPATIBLE
  1792. .err ;  that would be silly to use with the
  1793. endif ;  following code
  1794. call GetInt15Memory ; yes, start EISA block above current
  1795. add [bx].Base.lo, ax ;   Int 15h/88h line.  The Int 15h mem
  1796. adc [bx].Base.hi, 0  ;   will be added when Int 15h hooked.
  1797. sub [bx].Len.lo, ax  ;   Existing hook and /INT15= code
  1798. sbb [bx].Len.hi, 0 ;   will work as before.
  1799. jc SEISA_09d ; (just for safeties sake)
  1800. mov ax, [bx].Len.lo  ; Len will be 0 if Int 15h covers
  1801. or ax, [bx].Len.hi  ;   entire EISA block
  1802. jz SEISA_09d
  1803. jmp short SEISA_09e
  1804. SEISA_default:
  1805. cmp [bx].Len.hi, 0 ; If the length is > 64 Meg (which is
  1806. jz SEISA_09d ;   the max that Int 15h/88h could
  1807. inc [bx].Base.hi ;   return), keep the memory above
  1808. dec [bx].Len.hi ;   that for XMS
  1809. jmp short SEISA_09e
  1810. SEISA_09d:
  1811. mov [bx].Flags,UNUSEDFLAG ; free the block at 1024
  1812. SEISA_09e:
  1813. pop es
  1814. assume es:nothing
  1815. SEISA_exit:
  1816. mov ss,save_ss
  1817. mov sp,save_sp ; restore normal stack
  1818. ret
  1819. assume ds:nothing
  1820. ScanEISA endp
  1821. ; The buffer for scanning EISA devices is big, but disposable
  1822. ZDS_Buffer label byte ; also use for Zenith memory check
  1823. EISABuffer db 22h dup (0)
  1824. EISA_FncInfo db (73h-22h) dup (0)
  1825. EISA_MemConfig db (320-73h) dup (0)
  1826. db (512-320) dup (0) ; make it 512 for Zenith
  1827. db 2000 dup (?)
  1828. EISA_Stack:
  1829. _text ends
  1830. ifdef debug_tsr ;-------------------------------
  1831. EndStmt equ <end ExeStart>
  1832. STACK segment stack 'STACK'
  1833. db 1024 dup (?)
  1834. STACK ends
  1835. else
  1836. EndStmt equ <end>
  1837. endif ;-------------------------------
  1838. EndStmt