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.

1571 lines
32 KiB

  1. ;/* himem2.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 UMB initialization
  12. ; */
  13. page 95,160
  14. title 'HIMEM2 - Initialization code'
  15. funky segment word public 'funky'
  16. extrn textseg:word ; in high segment
  17. extrn KiddValley:word
  18. extrn KiddValleyTop:word
  19. extrn cHandles:word
  20. extrn pack_and_truncate:near
  21. extrn end_of_funky_seg:byte
  22. extrn LEnblA20:word
  23. extrn LDsblA20:word
  24. funky ends
  25. .xlist
  26. include himem.inc ; get structures, equ's, etc.
  27. ; and open segment
  28. include xmssvc.inc
  29. .list
  30. ; public f000
  31. public InitInterrupt
  32. public MachineNum
  33. ;************************************************************************
  34. ;* *
  35. ;* Global Variables *
  36. ;* *
  37. ;************************************************************************
  38. extrn pPPFIRET:word
  39. extrn dd_int_loc:word
  40. extrn Interrupt:near
  41. extrn hiseg:word
  42. extrn call_hi_in_di:near
  43. extrn fCanChangeA20:byte
  44. extrn fHMAMayExist:byte
  45. ifndef NEC_98
  46. extrn fVDISK:byte
  47. extrn IsVDISKIn:near
  48. endif ;NEC_98
  49. extrn A20Handler:near
  50. extrn EnableCount:word
  51. extrn MemCorr:word
  52. extrn MinHMASize:word
  53. extrn pReqHdr:dword
  54. extrn PrevInt2f:dword
  55. extrn TopOfTextSeg:word
  56. extrn AddMem:near
  57. extrn InstallA20:near
  58. extrn Int2fHandler:near
  59. ; extrn Is6300Plus:near
  60. extrn IsA20On:near
  61. extrn SignOnMsg:byte
  62. extrn ROMDisabledMsg:byte
  63. extrn UnsupportedROMMsg:byte
  64. extrn ROMHookedMsg:byte
  65. extrn BadDOSMsg:byte
  66. extrn NowInMsg:byte
  67. extrn On8086Msg:byte
  68. extrn NoExtMemMsg:byte
  69. extrn FlushMsg:byte
  70. extrn StartMsg:byte
  71. extrn HandlesMsg:byte
  72. extrn HMAMINMsg:byte
  73. extrn KMsg:byte
  74. extrn NoHMAMsg:byte
  75. extrn A20OnMsg:byte
  76. extrn HMAOKMsg:byte
  77. ifndef NEC_98
  78. extrn VDISKInMsg:byte
  79. extrn BadArgMsg:byte
  80. endif ;NEC_98
  81. extrn DevAttr:word
  82. extrn Int15MemSize:word
  83. extrn EndText:byte
  84. extrn A20State:byte
  85. extrn DOSTI:near
  86. extrn DOCLI:near
  87. ifdef NEC_98
  88. extrn fAltA20Routine:byte
  89. extrn LocalDisableA20:near
  90. extrn LocalEnableA20:near
  91. extrn cant_ena20_msg:byte
  92. extrn cant_dia20_msg:byte
  93. endif ;NEC_98
  94. ;************************************************************************
  95. ;* *
  96. ;* Code/Data below here will be discarded after driver initialization *
  97. ;* *
  98. ;************************************************************************
  99. ; Discardable Initialization Data
  100. public fShadowOff, f1stWasWarning
  101. fShadowOff db 0 ; NZ if shadow RAM should be disabled,
  102. ; 0/1 set by command line switch, 0FFh
  103. ; set if little extended and hope to disable
  104. f1stWasWarning db 0 ; NZ if 1st attempt to diddle A20 generated
  105. ; a warning (and not an error)
  106. public fA20Control
  107. fA20Control db 0ffh ; NZ if himem should take control of A20, even
  108. ; it was already on when himem loaded.
  109. ifndef NEC_98
  110. public fCPUClock
  111. fCPUClock db 0 ; NZ if himem should try to preserve CPU clock
  112. ; speed when gating A20
  113. endif ;NEC_98
  114. public StringParm, MachineNum, MachineName
  115. StringParm db 13 DUP (' ')
  116. MachineNum dw -1
  117. ; Note: the following table MUST be in the same order as the entries in the
  118. ; A20_Scan_Table! If you add entries here, also add one there!
  119. MachineName label byte
  120. db 'ptlcascade',0 ; Phoenix Cascade BIOS
  121. db 'att6300plus',0 ; AT&T 6300 Plus
  122. db 'ps2',0 ; IBM PS/2
  123. db 'hpvectra',0 ; HP 'Classic' Vectra (A & A+)
  124. db 'acer1100',0 ; Acer 1100
  125. db 'toshiba',0 ; Toshiba 1600 & 1200XE
  126. db 'wyse',0 ; Wyse 12.5 MHz 286 machine
  127. ifndef NEC_98
  128. db 'tulip',0 ; Tulip machines
  129. db 'zenith',0 ; Zenith ZBIOS
  130. db 'at1',0 ; IBM AT/delay 0
  131. db 'at2',0 ; IBM AT/delay 1
  132. db 'at3',0 ; IBM AT/delay 2
  133. db 'philips',0 ; Philips machines
  134. db 'css',0 ; CSS Lab machines
  135. db 'fasthp',0 ; Single byte method for HP Vectras
  136. db 'ibm7552',0 ; IBM 7552 Industrial Computer
  137. db 'bullmicral',0 ; Bull Micral 60 M004
  138. endif ;NEC_98
  139. db 'at',0 ; IBM AT
  140. db 0FFh ; end of table
  141. ;NOTE: there is code in GetParms which depends on AltNameTbl coming
  142. ; after MachineName table.
  143. ifndef NEC_98
  144. public AltName1, AltName2, AltName3, AltName4, AltName5
  145. public AltName6, AltName7, AltName8, AltName9, AltName10
  146. public AltName11, AltName12, AltName13, AltName14, AltName15
  147. public AltName16 ;M004
  148. else ;NEC_98
  149. public AltName1, AltName2, AltName3, AltName4, AltName5
  150. public AltName6, AltName7, AltName8
  151. endif ;NEC_98
  152. AltNameTbl label byte
  153. AltName3 db '3',0 ; Phoenix Cascade BIOS
  154. AltName5 db '5',0 ; AT&T 6300 Plus
  155. AltName2 db '2',0 ; IBM PS/2
  156. AltName4 db '4',0 ; HP 'Classic' Vectra (A & A+)
  157. AltName6 db '6',0 ; Acer 1100
  158. AltName7 db '7',0 ; Toshiba 1600 & 1200XE
  159. AltName8 db '8',0 ; Wyse 12.5 Mhz 286 machine
  160. ifndef NEC_98
  161. AltName9 db '9',0 ; Tulip machine
  162. AltName10 db '10',0 ; Zenith ZBIOS
  163. AltName11 db '11',0 ; IBM AT/delay 0
  164. AltName12 db '12',0 ; IBM AT/delay 1
  165. AltName13 db '13',0 ; IBM AT/delay 2
  166. db '13',0 ; Philips machines (same as AT3)
  167. db '12',0 ; CSS machines
  168. AltName14 db '14',0 ; Single byte HP Vectra m/cs
  169. AltName15 db '15',0 ; IBM 7552 Industrial Computer
  170. AltName16 db '16',0 ; Bull Micral 60 M004
  171. endif ;NEC_98
  172. AltName1 db '1',0 ; IBM AT
  173. db 0FFh ; end of table
  174. ifdef debug_tsr ;-----------------------------------------------
  175. ;*----------------------------------------------------------------------*
  176. ;* *
  177. ;* ExeStart - *
  178. ;* *
  179. ;* Entry point when himem is invoked as an .EXE. *
  180. ;* *
  181. ;*----------------------------------------------------------------------*
  182. lpCmdLine dd 81h ; far ptr to command tail
  183. public ExeStart
  184. ExeStart:
  185. mov word ptr cs:[lpCmdLine+2],es ; save PSP segment in pointer
  186. mov ax,cs ; Setup segment regs to all be the same
  187. mov ds,ax
  188. mov es,ax
  189. call InitDriver ; Initialize...
  190. mov ax,TopOfTextSeg ; TopOfTextSeg == 0 is error installing
  191. or ax,ax
  192. jnz @f
  193. mov ax,4C03h ; error, so just terminate
  194. int 21h
  195. @@:
  196. mov di,offset pack_and_truncate
  197. jmp call_hi_in_di ; terminate and stay resident
  198. endif ;------------------------------------------------
  199. ;*----------------------------------------------------------------------*
  200. ;* *
  201. ;* InitInterrupt - *
  202. ;* *
  203. ;* Called by MS-DOS immediately after Strategy routine *
  204. ;* *
  205. ;* ARGS: None *
  206. ;* RETS: Return code in Request Header's Status field *
  207. ;* REGS: Preserved *
  208. ;* *
  209. ;* This entry point is used only during initialization. *
  210. ;* It replaces itself with a much shorter version which only *
  211. ;* serves to report the appropriate errors when this driver *
  212. ;* is called in error. *
  213. ;* *
  214. ;*----------------------------------------------------------------------*
  215. InitInterrupt proc far
  216. ; Save the registers including flags.
  217. push ax ; We cannot use pusha\popa because
  218. push bx ; we could be on an 8086 at this point
  219. push cx
  220. push dx
  221. push ds
  222. push es
  223. push di
  224. push si
  225. push bp
  226. pushf
  227. push cs ; Set DS=CS for access to global variables.
  228. pop ds
  229. les di,[pReqHdr] ; ES:DI = Request Header
  230. mov bl,es:[di].Command ; Get Function code in BL
  231. or bl,bl ; Only Function 00h (Init) is legal
  232. jz IInit
  233. cmp bl,16 ; Test for "legal" DOS functions
  234. jle IOtherFunc
  235. IBogusFunc:
  236. mov ax,8003h ; Return "Unknown Command"
  237. jmp short IExit
  238. IOtherFunc:
  239. xor ax,ax ; Return zero for unsupported functions
  240. jmp short IExit
  241. IInit:
  242. call InitDriver ; Initialize the driver
  243. les di,[pReqHdr] ; Restore es:di = Request Header
  244. IExit:
  245. or ax,0100h ; Turn on the "Done" bit
  246. mov es:[di].Status,ax ; Store return code
  247. popff ; restore the registers
  248. pop bp
  249. pop si
  250. pop di
  251. pop es
  252. pop ds
  253. pop dx
  254. pop cx
  255. pop bx
  256. pop ax
  257. mov dd_int_loc,offset Interrupt ; replace Interrupt with
  258. ret ; tiny permanent stub
  259. InitInterrupt endp
  260. ;*----------------------------------------------------------------------*
  261. ;* *
  262. ;* InitDriver - *
  263. ;* *
  264. ;* Called when driver is Initialized. *
  265. ;* *
  266. ;* ARGS: ES:DI = Address of the Request Header *
  267. ;* RETS: pHdr.Address = Bottom of resident driver code *
  268. ;* REGS: AX, CX and Flags are clobbered *
  269. ;* *
  270. ;*----------------------------------------------------------------------*
  271. ifndef NEC_98
  272. public InitDriver
  273. endif ;NEC_98
  274. InitDriver proc near
  275. cld
  276. ifndef debug_tsr
  277. call LocateHiSeg ; locate the hiseg in low memory properly
  278. mov ax,cs
  279. push es
  280. mov es,hiseg
  281. assume es:funky
  282. add textseg,ax ; relocate text segment pointer
  283. add LEnblA20+2, ax ; update ptrs to enble & disable a20 rtns
  284. add LDsblA20+2, ax
  285. pop es
  286. assume es:nothing
  287. endif
  288. ; mov ah,9 ; display signon message
  289. ; mov dx,offset SignOnMsg
  290. ; int 21h
  291. mov ah,30h ; make sure we've got DOS 3.00 or higher
  292. int 21h ; Get DOS versions number
  293. cmp al,3
  294. jae IDCheckXMS
  295. mov dx,offset BadDOSMsg
  296. jmp IDFlushMe
  297. IDCheckXMS:
  298. ifndef NEC_98
  299. mov ax,(INT2F_ID SHL 8) OR INT2F_INS_CHK
  300. int 2Fh ; make sure there's no other XMS installed
  301. else ;NEC_98
  302. mov ax,4300h ; make sure there's no other XMS installed
  303. int 2Fh
  304. endif ;NEC_98
  305. cmp al,80h ; Is INT 2F hooked?
  306. jne IDNotInYet
  307. mov dx,offset NowInMsg
  308. jmp IDFlushMe
  309. IDNotInYet:
  310. ifdef NEC_98
  311. xor ax,ax
  312. mov es,ax
  313. test byte ptr es:[501h],40h ; we're on an V30/V50
  314. jz @f
  315. jmp IDFlushMe ; so give out
  316. @@:
  317. call GetInt15Memory ; If Int 15h/88h reports < 384k of
  318. mov dx,offset NoExtMemMsg
  319. or ax,ax ; we have extend memory ?
  320. jnz @f
  321. jmp IDFlushMe ; so give out
  322. @@:
  323. test byte ptr es:[0501h],08h ; Q : HIRES CRT ?
  324. jz @f ; N : continue
  325. mov ah,byte ptr es:[501h] ; BIOS_FLG
  326. mov al,ah ; save
  327. and ah,07h ; get main memory size
  328. cmp ah,4 ; main memory > 512 ?
  329. jb @f ; no. don't need to init RAMWindow
  330. test byte ptr es:[458h],80h ; NPC ?
  331. jnz not_XA ; yes
  332. test al,30h ; system type = 0 ?
  333. jnz not_XA ; no. other than XA
  334. call Init_RamWindow_XA
  335. jmp short @f
  336. not_XA:
  337. call Init_RamWindow
  338. @@:
  339. endif ;NEC_98
  340. call GetParms ; process command line parameters
  341. ;; don't call IsA20On at this moment because we haven't init it yet
  342. mov ax, 2
  343. XMSSVC XMS_A20
  344. ;;;; call IsA20On ; Is A20 already enabled?
  345. or ax,ax ; (may zap cx, si, di)
  346. jz IDInsA20 ; no, go install A20 handler
  347. mov dx,offset A20OnMsg ; "A20 already on" message
  348. cmp fA20Control,0 ; should we take control of A20 anyway?
  349. jne IDInsA20 ; yes, go muck with it
  350. mov [fCanChangeA20],0 ; no, don't allow changing of A20
  351. mov ah,9 ; and tell user about it
  352. int 21h
  353. jmp short IDAfterA20
  354. IDInsA20:
  355. call InstallA20 ; install proper A20 handler
  356. jc IDFlushMe ; CY means fatal error
  357. ; Note: A side affect of the previous InstallA20 is that MemCorr
  358. ; is set to reflect the adjustment factor if we're on an AT&T 6300+
  359. IDAfterA20:
  360. call InitHandles ; initialize handle table
  361. call GetInt15Memory ; how much extended memory is installed?
  362. cmp ax,64 ; Is there >= 64K of extended?
  363. ifndef NEC_98
  364. jae IDHMAOK
  365. else ;NEC_98
  366. jb @f
  367. cmp Int15MemSize, 0 ; has the hma been allocated to INT 15 ?
  368. jz IDHMAOK ; no, HMA is available
  369. @@:
  370. endif ;NEC_98
  371. push es
  372. mov es,hiseg
  373. assume es:funky
  374. mov bx,[KiddValley] ; get size of memory we already have in tables
  375. mov cx,[cHandles]
  376. IDAnyMem:
  377. cmp [bx].Flags,FREEFLAG
  378. jnz IDAnyMem_1 ; brif not a valid free block
  379. add ax,[bx].Len ; accumulate total
  380. IDAnyMem_1:
  381. add bx,SIZE Handle
  382. loop IDAnyMem
  383. pop es
  384. assume es:nothing
  385. mov dx,offset NoHMAMsg
  386. or ax,ax ; no HMA, any other memory to control?
  387. jnz disp_hma_msg ; jmp if some memory
  388. ; We can't find any memory to manage.
  389. mov dx,offset NoExtMemMsg
  390. ; Display the message in DX followed by the "Flush" message.
  391. IDFlushMe:
  392. mov ah,9
  393. int 21h
  394. mov dx,offset FlushMsg
  395. mov ah,9
  396. int 21h
  397. xor ax,ax ; discard the driver
  398. mov [TopOfTextSeg],ax
  399. ifndef debug_tsr ;-------------------------------
  400. les di,[pReqHdr]
  401. mov es:[di].Units,al
  402. and cs:DevAttr,not 8000h ; clr bit 15 in attrib of driver header
  403. endif
  404. jmp short IDReturn ;-------------------------------
  405. IDHMAOK:
  406. mov [fHMAMayExist],1
  407. mov dx,offset HMAOKMsg
  408. disp_hma_msg:
  409. ; mov ah,9
  410. ; int 21h
  411. ;; tell xms.lib where our variable is
  412. mov ax, cs
  413. mov bx, offset A20State
  414. XMSSVC XMS_INITUMB
  415. call HookInt2F ; "turn on" the driver
  416. ; Initialization finished (or failed) -- return to caller
  417. IDReturn:
  418. ifndef debug_tsr ;-------------------------------
  419. mov di,offset pack_and_truncate
  420. jmp call_hi_in_di ; pack stuff down and terminate
  421. endif ;-------------------------------
  422. ret
  423. InitDriver endp
  424. ;
  425. ;----------------------------------------------------------------------------
  426. ; procedure : LocateHiSeg
  427. ;
  428. ; Locate the movable segment properly in the low seg.
  429. ; taking care of the stripped ORG zeroes. This function
  430. ; calculates the segment at which the hiseg should run
  431. ; with the ORG. If the segment cvalue goes below zero the
  432. ; code is moved up high enough to run the code from a seg value
  433. ; of zero.
  434. ;
  435. ; This function assumes that the 'funky' segment follows
  436. ; immediately after the text seg.
  437. ;
  438. ;----------------------------------------------------------------------------
  439. ;
  440. LocateHiSeg proc near
  441. push ds
  442. mov ax, cs ; para start of text seg
  443. mov cx, offset _text:EndText ; end of text seg
  444. add cx, 15 ; para round it
  445. shr cx, 1
  446. shr cx, 1
  447. shr cx, 1
  448. shr cx, 1
  449. add ax, cx ; para start of funky seg
  450. cmp ax, (HISEG_ORG shr 4) ; will the seg go below zero?
  451. jb MoveHiSeg ; yeah, we have to move it
  452. sub ax, (HISEG_ORG shr 4) ; no, it fits in
  453. pop ds
  454. mov hiseg, ax ; update the segment in which
  455. ; it is going to run from.
  456. ret
  457. MoveHiSeg:
  458. mov ds, ax ; segment at which funky
  459. ; resides without the ORG
  460. xor ax, ax
  461. mov es, ax ; we want to movve the code
  462. ; to 0:HISEG_ORG
  463. mov di, offset funky:end_of_funky_seg
  464. mov si, di
  465. sub si, HISEG_ORG
  466. mov cx, si
  467. dec di
  468. dec si
  469. std ; move backward (safe when
  470. ; source & dest overlap
  471. rep movsb
  472. cld
  473. pop ds
  474. mov hiseg, 0 ; funky is going to run from
  475. ; segment zero
  476. ret
  477. LocateHiSeg endp
  478. ;*----------------------------------------------------------------------*
  479. ;* *
  480. ;* HookInt2F - *
  481. ;* *
  482. ;* Insert the INT 2F hook *
  483. ;* *
  484. ;* ARGS: None *
  485. ;* RETS: None *
  486. ;* REGS: AX, SI, ES and Flags are clobbered *
  487. ;* *
  488. ;*----------------------------------------------------------------------*
  489. public HookInt2F
  490. HookInt2F proc near
  491. call DOCLI
  492. xor ax,ax
  493. mov es,ax
  494. mov si,2Fh * 4 ; save previous int2f vector
  495. mov ax,offset Int2FHandler ; and exchange with new one
  496. xchg ax,es:[si][0]
  497. mov word ptr [PrevInt2F][0],ax
  498. mov ax,cs
  499. xchg ax,es:[si][2]
  500. mov word ptr [PrevInt2F][2],ax
  501. call DOSTI
  502. ret
  503. HookInt2F endp
  504. ;*----------------------------------------------------------------------*
  505. ;* *
  506. ;* GetInt15Memory - *
  507. ;* *
  508. ;* Returns the amount of memory INT 15h, Function 88h says is free *
  509. ;* *
  510. ;* ARGS: None *
  511. ;* RETS: AX = Amount of free extended memory in K-bytes *
  512. ;* REGS: AX and Flags are clobbered *
  513. ;* *
  514. ;*----------------------------------------------------------------------*
  515. GetInt15Memory proc near
  516. ifndef NEC_98
  517. IFDEF WHEN_INT15_DONE
  518. mov ah,88h ; snag the int 15h memory
  519. clc
  520. int 15h ; Is Function 88h around?
  521. jnc xret_geti15
  522. xor ax,ax ; No, return 0
  523. xret_geti15:
  524. ifndef NOLIMIT ;M005
  525. cmp ax,15*1024 ; Limit himem.sys to using 15 meg
  526. jb @f ; of extended memory for apps
  527. mov ax,15*1024 ; that don't deal with > 24 bit
  528. @@: ; addresses
  529. endif ;M005
  530. ELSE
  531. XMSSVC XMS_EXTMEM ; return ext-mem in ax5
  532. ENDIF
  533. ret
  534. else ;NEC_98
  535. push es
  536. mov ax,40h
  537. mov es,ax
  538. mov al,byte ptr es:[01h] ; get extend memory size
  539. pop es
  540. sub ah,ah
  541. shl ax,7
  542. ret
  543. endif ;NEC_98
  544. GetInt15Memory endp
  545. ;*----------------------------------------------------------------------*
  546. ;* *
  547. ;* GetParms - *
  548. ;* *
  549. ;* Get any parameters off of the HIMEM command line *
  550. ;* *
  551. ;* ARGS: None *
  552. ;* RETS: None *
  553. ;* REGS: AX, BX, CX, DX, DI, SI, ES and Flags clobbered *
  554. ;* *
  555. ;* Side Effects: cHandles and MinHMASize may be changed *
  556. ;* *
  557. ;*----------------------------------------------------------------------*
  558. ifndef NEC_98
  559. GPArgPtr dd ?
  560. endif ;NEC_98
  561. GPRegSave dw ?
  562. public GetParms
  563. GetParms proc near
  564. cld ; better safe than sorry
  565. push ds
  566. ifdef debug_tsr ;-------------------------------
  567. lds si,lpCmdLine
  568. else ;-------------------------------
  569. les di,[pReqHdr] ; Running as a device driver
  570. lds si,es:[di].pCmdLine ; DS:SI points to first char
  571. ; after "DEVICE="
  572. ifndef NEC_98
  573. @@: call GPGetChar ; Skip over driver name, up to
  574. jc GPDatsAll ; first blank or / or eol
  575. jz GPNextArg
  576. cmp al,'/'
  577. jnz @b
  578. dec si ; Backup to get / again
  579. endif ;NEC_98
  580. endif ;-------------------------------
  581. assume ds:nothing,es:nothing
  582. ; Scan until we see a non-blank or the end of line.
  583. ifndef NEC_98
  584. GPNextArg:
  585. call GPGetChar
  586. jc GPDatsAll ; eol
  587. jz GPNextArg ; blank
  588. mov word ptr cs:[GPArgPtr], si ; save ptr to start of arg
  589. mov word ptr cs:[GPArgPtr+2], ds ; incase we want to complain
  590. dec word ptr cs:[GPArgPtr] ; (GPGetChar points at next)
  591. cmp al,'/' ; better be a / or not a valid arg
  592. jz GPGotOne
  593. ; Detected invalid parameter or value, complain to user
  594. GPBadParm:
  595. mov ah,9 ; tell'm something isn't right
  596. push cs
  597. pop ds
  598. mov dx,offset BadArgMsg
  599. int 21h
  600. lds si,cs:[GPArgPtr] ; backup to last parameter
  601. GPBadDisp:
  602. call GPGetChar ; disp arg up to space or eol
  603. jc GPDatsAll ; skips over bad arg while we're at it
  604. jz GPNextArg
  605. cmp al,'/' ; start of next arg?
  606. jnz @f
  607. dec si ; maybe yes, maybe no--might
  608. cmp si,word ptr cs:[GPArgPtr] ; be same arg
  609. jnz GPNextArg ; next, go process new arg
  610. inc si ; same, keep displaying
  611. @@:
  612. mov dl,al
  613. mov ah,2
  614. int 21h
  615. jmp short GPBadDisp
  616. ; Finished, we're outta here...
  617. else ;NEC_98
  618. GPBadParm:
  619. GPNextChar:
  620. call GPGetChar
  621. jc GPDatsAll
  622. cmp al,'/'
  623. je GPGotOne
  624. jmp short GPNextChar
  625. endif ;NEC_98
  626. GPDatsAll:
  627. pop ds
  628. ret
  629. ; Save what we found and get the number or string after it.
  630. GPGotOne:
  631. lodsb
  632. mov cs:[GPRegSave],ax
  633. ; Scan past the rest of the parm for a number, EOL, or a space.
  634. GPNeedParm:
  635. call GPGetChar
  636. ifndef NEC_98
  637. jc GPBadParm
  638. jz GPBadParm ; blank
  639. else ;NEC_98
  640. jc GPDatsAll
  641. cmp al,' '
  642. je GPBadParm
  643. endif ;NEC_98
  644. cmp al,':' ; start of string arg
  645. je GPString
  646. cmp al,'='
  647. jne GPNeedParm
  648. ; Read the number at DS:SI into DX
  649. GPNeedNum:
  650. call GPGetChar
  651. jc GPDatsAll
  652. cmp al,'0'
  653. jb GPNeedNum
  654. cmp al,'9'
  655. ja GPNeedNum
  656. xor dx,dx
  657. GPNumLoop:
  658. sub al,'0'
  659. cbw
  660. add dx,ax
  661. call GPGetChar
  662. jc GPNumDone
  663. ifndef NEC_98
  664. jz GPNumDone
  665. else ;NEC_98
  666. cmp al,' '
  667. je GPNumDone
  668. endif ;NEC_98
  669. cmp al,'0'
  670. jb GPBadParm
  671. cmp al,'9'
  672. ja GPBadParm
  673. shl dx,1 ; multiply DX by 10
  674. mov bx,dx
  675. shl dx,1
  676. shl dx,1
  677. add dx,bx
  678. jmp short GPNumLoop
  679. ; Move the string arg from ds:si to StringParm
  680. GPString:
  681. mov cx,(SIZE StringParm) - 1
  682. push cs
  683. pop es
  684. mov di,offset _text:StringParm
  685. GPStrLoop:
  686. call GPGetChar
  687. jc GPStrDone
  688. ifndef NEC_98
  689. jz GPStrDone
  690. else ;NEC_98
  691. cmp al,' '
  692. je GPStrDone
  693. endif ;NEC_98
  694. stosb
  695. loop GPStrLoop
  696. GPStrDone:
  697. mov byte ptr es:[di],0 ; Null terminate the string
  698. ifndef NEC_98
  699. mov dx,-1 ; In case parm expects a num, give'm
  700. ; a likely invalid one
  701. endif ;NEC_98
  702. ; Which parameter are we dealing with here?
  703. GPNumDone:
  704. xchg ax,cs:[GPRegSave]
  705. cmp al,'H' ; HMAMIN= parameter?
  706. jne @f
  707. jmp GPGotMin
  708. @@:
  709. cmp al,'N' ; NUMHANDLES= parameter?
  710. jne @f
  711. jmp GPGotHands
  712. @@: cmp al,'M' ; MACHINE: parameter?
  713. je GPGotMachine
  714. cmp al,'A' ; A20CONTROL: parameter?
  715. je GPGotA20Control
  716. cmp al,'S' ; SHADOWRAM: parameter?
  717. jne @f
  718. jmp GPGotShadow
  719. @@: cmp al, 'I' ; INT15=
  720. jne @f
  721. jmp GPGotInt15
  722. ifndef NEC_98
  723. @@: cmp al, 'C' ; CPUCLOCK:
  724. jne @f
  725. jmp GPGotCPUClock
  726. endif ;NEC_98
  727. @@: jmp GPBadParm
  728. ; Process /A20CONTROL: parameter
  729. GPGotA20Control:
  730. mov ax,word ptr [StringParm]
  731. or ax,2020h
  732. mov bl,0FFh
  733. cmp ax,'no' ; ON ? - means we take control
  734. jz GPSetA20
  735. inc bl
  736. cmp ax,'fo' ; OFF ? - means we leave alone if on
  737. jz GPSetA20
  738. ifndef NEC_98
  739. jmp GPBadParm
  740. else ;NEC_98
  741. jmp GPNextParm
  742. endif ;NEC_98
  743. GPSetA20:
  744. mov fA20Control,bl ; Z if A20 should be left alone if
  745. jmp GPNextParm ; it's already on when we're loaded
  746. ; Process /MACHINE: parameter.
  747. GPGotMachine:
  748. push si ; save current location
  749. push ds ; in param string
  750. push cs
  751. pop ds
  752. mov di,offset _text:MachineName ; es:di -> MachineName
  753. GPNextTbl:
  754. xor bx,bx
  755. GPNextName:
  756. mov si,offset _text:StringParm ; ds:si -> StringParm
  757. GPChkNext:
  758. cmp byte ptr es:[di],0FFh ; end of name table?
  759. ifndef NEC_98
  760. jz GPNoName
  761. else ;NEC_98
  762. jz GPBadName
  763. endif ;NEC_98
  764. lodsb ; char from StringParm
  765. cmp al,'A' ; force to lower case for match
  766. jb @f ; (might be numeric, so don't just OR)
  767. cmp al,'Z'
  768. ja @f
  769. or al,20h
  770. @@:
  771. cmp al,es:[di] ; match so far?
  772. jnz GPFlushName
  773. or al,al ; finished if matched up to & incl NULL
  774. jz GPFoundName
  775. inc di ; still matches, check next char
  776. jmp short GPChkNext
  777. GPFlushName:
  778. inc bx
  779. GPFN2:
  780. inc di
  781. cmp byte ptr es:[di],0FFh
  782. ifndef NEC_98
  783. jz GPNoName
  784. else ;NEC_98
  785. jz GPBadName
  786. endif ;NEC_98
  787. cmp byte ptr es:[di],0
  788. jnz GPFN2
  789. inc di
  790. jmp short GPNextName
  791. GPFoundName:
  792. mov cs:[MachineNum],bx ; found a match, remember which entry
  793. jmp short GPNameDone ; it is for later
  794. ifndef NEC_98
  795. GPNoName:
  796. cmp di,offset _text:AltNameTbl
  797. ja GPBadName
  798. mov di,offset _text:AltNameTbl
  799. jmp short GPNextTbl
  800. GPNameDone:
  801. pop ds ; recover parm line pointer
  802. pop si
  803. jmp GPNextParm
  804. GPBadName:
  805. pop ds ; clear stack and error out...
  806. pop si
  807. jmp GPBadParm
  808. else ;NEC_98
  809. GPBadName:
  810. cmp di,offset _text:AltNameTbl
  811. ja GPNameDone
  812. mov di,offset _text:AltNameTbl
  813. jmp short GPNextTbl
  814. GPNameDone:
  815. pop ds ; recover parm line pointer
  816. pop si
  817. jmp GPNextParm
  818. endif ;NEC_98
  819. ; Process /NUMHANDLES= parameter.
  820. GPGotHands:
  821. cmp dx,MAXHANDLES
  822. jna @f
  823. jmp GPBadParm
  824. @@:
  825. or dx,dx ; Zero?
  826. jnz @f
  827. jmp GPBadParm
  828. @@:
  829. push es
  830. mov es,hiseg
  831. assume es:funky
  832. mov [cHandles],dx ; Store it
  833. pop es
  834. assume es:nothing
  835. mov dx,offset StartMsg ; display descriptive message
  836. call GPPrintIt
  837. push es
  838. mov es,hiseg
  839. assume es:funky
  840. mov ax,[cHandles]
  841. pop es
  842. assume es:nothing
  843. call GPPrintAX
  844. mov dx,offset HandlesMsg
  845. call GPPrintIt
  846. ifndef NEC_98
  847. jmp GPNextParm
  848. else ;NEC_98
  849. jmp short GPNextParm
  850. endif ;NEC_98
  851. GPGotMin:
  852. cmp dx,64 ; process /hmamin= parameter
  853. jna @f
  854. jmp GPBadParm
  855. @@:
  856. push dx
  857. mov cs:[MinHMASize],dx
  858. mov dx,offset HMAMINMsg ; print a descriptive message
  859. call GPPrintIt
  860. mov ax,cs:[MinHMASize]
  861. call GPPrintAX
  862. mov dx,offset KMsg
  863. call GPPrintIt
  864. pop dx
  865. mov cl,10 ; Convert from K to bytes
  866. shl dx,cl
  867. mov cs:[MinHMASize],dx
  868. jmp short GPNextParm
  869. ; Process /SHADOWRAM: parameter
  870. GPGotShadow:
  871. mov ax,word ptr [StringParm]
  872. or ax,2020h
  873. xor bl,bl
  874. cmp ax,'no' ; ON ? - means we leave it alone
  875. jz GPSetShadow
  876. inc bl
  877. cmp ax,'fo' ; OFF ? - means we turn it off
  878. jz GPSetShadow
  879. ifndef NEC_98
  880. jmp GPBadParm
  881. else ;NEC_98
  882. jmp short GPNextParm
  883. endif ;NEC_98
  884. GPSetShadow:
  885. mov fShadowOff,bl ; NZ if Shadow RAM should be turned off
  886. jmp short GPNextParm
  887. ifndef NEC_98
  888. ; Process /CPUCLOCK: parameter
  889. GPGotCPUClock:
  890. mov ax,word ptr [StringParm]
  891. or ax,2020h
  892. xor bl,bl
  893. cmp ax,'fo' ; OFF ? - means we don't worry about it
  894. jz GPSetClock
  895. inc bl
  896. cmp ax,'no' ; ON ? - means we preserve CPU clock
  897. jz GPSetClock ; rate
  898. jmp GPBadParm
  899. GPSetClock:
  900. mov fCPUClock,bl ; NZ if clock rate preserved
  901. jmp short GPNextParm
  902. endif ;NEC_98
  903. ; Process /INT15= parameter
  904. GPGotInt15:
  905. cmp dx, 64 ; atleast 64K
  906. jae @f
  907. jmp GPBadParm
  908. ifndef NEC_98
  909. @@: call GetInt15Memory
  910. cmp ax, dx ; enuf Ext Mem ?
  911. else ;NEC_98
  912. call GetInt15Memory
  913. @@: cmp ax, dx ; enuf Ext Mem ?
  914. endif ;NEC_98
  915. jae @f
  916. jmp GPBadParm
  917. @@: mov [Int15MemSize], dx
  918. ; Fall through to GetNextParm
  919. ifdef NEC_98
  920. jmp short GPNextParm
  921. endif ;NEC_98
  922. GPNextParm:
  923. mov ax,cs:[GPRegSave] ; are we at the end of the line?
  924. cmp al,13 ; may not be needed any longer...
  925. je GPExit
  926. cmp al,10
  927. je GPExit
  928. ifndef NEC_98
  929. jmp GPNextArg
  930. else ;NEC_98
  931. jmp GPNextChar
  932. endif ;NEC_98
  933. GPExit:
  934. pop ds
  935. ret
  936. GetParms endp
  937. ; Get the next character from DS:SI, set CY if it's an EOL (CR, LF), set
  938. ; Z if it's a space
  939. ifndef NEC_98
  940. GPOffEOL dw -1
  941. endif ;NEC_98
  942. public GPGetChar
  943. GPGetChar proc near
  944. ifndef NEC_98
  945. cmp si,cs:[GPOffEOL] ; are we already at EOL?
  946. jnb GPAtEOL
  947. lodsb ; no, get next char
  948. cmp al,10 ; is this the EOL?
  949. je GPHitEOL
  950. cmp al,13
  951. je GPHitEOL
  952. cmp al,' ' ; set Z if blank
  953. clc
  954. ret
  955. GPHitEOL:
  956. mov cs:[GPOffEOL],si ; save EOL offset once
  957. GPAtEOL:
  958. else ;NEC_98
  959. lodsb
  960. cmp al,10
  961. je @f
  962. cmp al,13
  963. je @f
  964. clc
  965. ret
  966. @@:
  967. endif ;NEC_98
  968. stc
  969. ret
  970. GPGetChar endp
  971. ;*----------------------------------------------------------------------*
  972. GPPrintIt proc near
  973. push ds ; Save current DS
  974. push cs ; Set DS=CS
  975. pop ds
  976. mov ah,9
  977. int 21h
  978. pop ds ; Restore DS
  979. ret
  980. GPPrintIt endp
  981. ;*----------------------------------------------------------------------*
  982. GPPrintAX proc near
  983. mov cx,10
  984. xor dx,dx
  985. div cx
  986. or ax,ax
  987. jz GPAPrint
  988. push dx
  989. call GPPrintAX
  990. pop dx
  991. GPAPrint:
  992. add dl,'0'
  993. mov ah,2
  994. int 21h
  995. ret
  996. GPPrintAX endp
  997. ;*----------------------------------------------------------------------*
  998. ;* *
  999. ;* InitHandles - *
  1000. ;* *
  1001. ;* Initialize the Extended Memory Handle Table *
  1002. ;* *
  1003. ;* ARGS: None *
  1004. ;* RETS: None *
  1005. ;* REGS: AX, BX, CX, and Flags are clobbered *
  1006. ;* *
  1007. ;*----------------------------------------------------------------------*
  1008. assume ds:_text
  1009. public InitHandles
  1010. InitHandles proc near
  1011. push es
  1012. mov es,hiseg
  1013. assume es:funky
  1014. mov cx,[cHandles]
  1015. ; Init the Handle table.
  1016. mov bx,[KiddValley]
  1017. xor ax,ax
  1018. IHTabLoop:
  1019. mov [bx].Flags,UNUSEDFLAG
  1020. mov [bx].cLock,al
  1021. mov [bx].Base,ax
  1022. mov [bx].Len,ax
  1023. if keep_cs
  1024. mov [bx].Acs,ax
  1025. endif
  1026. add bx,SIZE Handle
  1027. loop IHTabLoop
  1028. mov [KiddValleyTop],bx ; save top for handle validation
  1029. pop es
  1030. assume es:nothing
  1031. ret
  1032. InitHandles endp
  1033. ifdef NEC_98
  1034. ;******************************************************************************
  1035. ; Init_Ram_Window - Initialize Ram Window Memory
  1036. ;
  1037. ; MS-DOS
  1038. ; Ram Window Memory Ram Windows Memory
  1039. ; 80 100 80 80
  1040. ; 90 110 90 90
  1041. ; BO 120 B0 B0
  1042. ; A0 130 A0 A0
  1043. ;
  1044. ;
  1045. ;
  1046. ; Author: (sbp)
  1047. ;
  1048. ; ENTRY: REAL MODE on 386 processor (CPU ID already performed)
  1049. ; EXIT:
  1050. ;
  1051. ; USED: flags
  1052. ; STACK:
  1053. ;------------------------------------------------------------------------------
  1054. Init_RamWindow proc near
  1055. push ax
  1056. push bx
  1057. push dx
  1058. push ds
  1059. cli
  1060. mov cs:[save_ss],ss
  1061. mov cs:[save_sp],sp
  1062. push cs
  1063. pop ss
  1064. mov sp,offset EISA_stack
  1065. mov al, 8
  1066. out 37h, al
  1067. mov ax, 8000h ; �]�������ڽ
  1068. mov bx, 4000h ; �]�������ڽ
  1069. mov cx, 4 ; �]���o���N��
  1070. call movebank
  1071. mov al,08h ; 80 BANK memory
  1072. mov dx,91h ; 80 BANK ram windows "
  1073. out dx,al ; set RAM WINDOW
  1074. mov al,0ah ; A0 BANK memory
  1075. mov dx,93h ; A0 BANK ram window "
  1076. out dx,al ; set RAM WINDOW
  1077. xor ax, ax
  1078. mov ds, ax
  1079. test byte ptr ds:[481h], 04h ; Q : can use shadow ram ?
  1080. jnz @f
  1081. call initshadowram
  1082. @@:
  1083. mov ax, 4000h
  1084. mov bx, 8000h
  1085. mov cx, 4
  1086. call movebank
  1087. mov ss, cs:[save_ss]
  1088. mov sp, cs:[save_sp]
  1089. mov al, 09h
  1090. out 37h, al
  1091. sti
  1092. pop ds
  1093. pop dx
  1094. pop bx
  1095. pop ax
  1096. ret
  1097. Init_RamWindow endp
  1098. ;******************************************************************************
  1099. ; Init_Ram_Window_XA - Initialize Ram Window Memory
  1100. ;
  1101. ; MS-DOS Himem
  1102. ; Ram Window Memory Ram Windows Memory
  1103. ; 80 100 80 TOM-40 or TOM-20
  1104. ; 90 110 90 TOM-30 or TOM-10
  1105. ; BO 120 B0 TOM-20 or 120
  1106. ; A0 130 A0 TOM-10 or 130
  1107. ;
  1108. ; Author: (sbp)
  1109. ;
  1110. ; ENTRY: REAL MODE on 286
  1111. ; AH = main memory size in blocks of 128k
  1112. ; EXIT:
  1113. ;
  1114. ; USED: flags
  1115. ; STACK:
  1116. ;------------------------------------------------------------------------------
  1117. Init_RamWindow_XA proc near
  1118. sub ah,3
  1119. cmp byte ptr es:[401h],ah
  1120. ja IRX_Start
  1121. mov byte ptr es:[401h],0
  1122. ret
  1123. IRX_Start:
  1124. push ax
  1125. push bx
  1126. push dx
  1127. push ds
  1128. cli
  1129. mov cs:[save_ss],ss
  1130. mov cs:[save_sp],sp
  1131. push cs
  1132. pop ss
  1133. mov sp,offset EISA_stack
  1134. mov al, 8
  1135. out 37h, al
  1136. cmp ah,1 ; main memory = 640k ?
  1137. je IRX_640
  1138. mov ax, 0a000h ; �]�������ڽ
  1139. mov bx, 4000h ; �]�������ڽ
  1140. mov cx, 2 ; �]���o���N��
  1141. call movebank
  1142. mov al,byte ptr es:[401h]
  1143. dec al
  1144. shl al,1
  1145. add al,10h ; al = BANK #
  1146. mov dx,93h ; A0 BANK ram window "
  1147. out dx,al ; set RAM WINDOW
  1148. mov ax, 4000h
  1149. mov bx, 0a000h
  1150. mov cx, 2
  1151. call movebank
  1152. dec byte ptr es:[401h]
  1153. IRX_640:
  1154. mov ax, 8000h ; �]�������ڽ
  1155. mov bx, 4000h ; �]�������ڽ
  1156. mov cx, 2 ; �]���o���N��
  1157. call movebank
  1158. mov al,byte ptr es:[401h]
  1159. dec al
  1160. shl al,1
  1161. add al,10h ; al = BANK #
  1162. mov dx,91h ; 80 BANK ram windows "
  1163. out dx,al ; set RAM WINDOW
  1164. mov ax, 4000h
  1165. mov bx, 8000h
  1166. mov cx, 2
  1167. call movebank
  1168. dec byte ptr es:[401h]
  1169. mov ss, cs:[save_ss]
  1170. mov sp, cs:[save_sp]
  1171. mov al, 09h
  1172. out 37h, al
  1173. sti
  1174. pop ds
  1175. pop dx
  1176. pop bx
  1177. pop ax
  1178. ret
  1179. Init_RamWindow_XA endp
  1180. ;-------------------------------------------------------------------
  1181. ; movebank move bank datat
  1182. ; entry ax : source seg. address
  1183. ; bx : dest. seg. address
  1184. ; cx : bank count
  1185. ;
  1186. ;----------------------------------------------------------------
  1187. movebank proc near
  1188. push es
  1189. push ds
  1190. push si
  1191. push di
  1192. @@:
  1193. mov ds, ax
  1194. mov es, bx
  1195. push cx
  1196. mov cx, 8000h
  1197. cld
  1198. xor si, si
  1199. xor di, di
  1200. rep movsw
  1201. pop cx
  1202. add ax, 1000h ; get next bank address
  1203. add bx, 1000h ; get next bank address
  1204. loop @b
  1205. pop di
  1206. pop si
  1207. pop ds
  1208. pop es
  1209. ret
  1210. movebank endp
  1211. ;*-----------------------------------------------------------
  1212. ;* initshadowram
  1213. ;*
  1214. ;*
  1215. ;*----------------------------------------------------------
  1216. initshadowram proc near
  1217. push es
  1218. push di
  1219. push cx
  1220. cld
  1221. mov ax, 8000h
  1222. mov es, ax
  1223. mov cx, 0004h
  1224. mov ax,8000h
  1225. mov es,ax
  1226. mov cx,0004h
  1227. l3:
  1228. xor di, di
  1229. push cx
  1230. mov cx, 3333h
  1231. l1:
  1232. mov ax, 0ff01h
  1233. stosw
  1234. mov ax, 55aah
  1235. stosw
  1236. mov al, 00
  1237. stosb
  1238. loop l1
  1239. stosb
  1240. xor di, di
  1241. mov cx, 3333h
  1242. l2:
  1243. mov ax,0ff01h
  1244. scasw
  1245. jnz isr_exit
  1246. mov ax,55aah
  1247. scasw
  1248. jnz isr_exit
  1249. mov al,00h
  1250. scasb
  1251. jnz isr_exit
  1252. loop l2
  1253. mov ax, es
  1254. add ax, 1000h
  1255. mov es, ax
  1256. pop cx
  1257. loop l3
  1258. ; clean up memory
  1259. mov cx, 0004h
  1260. l4:
  1261. push cx
  1262. mov ax, es
  1263. sub ax, 1000h
  1264. mov es, ax
  1265. xor ax, ax
  1266. mov di, ax
  1267. mov cx, 8000h
  1268. rep stosw
  1269. pop cx
  1270. loop l4
  1271. xor ax,ax
  1272. jmp short isr_done
  1273. isr_exit:
  1274. mov ax,0001
  1275. isr_done:
  1276. pop cx
  1277. pop di
  1278. pop es
  1279. ret
  1280. initshadowram endp
  1281. ;*----------------------------------------------------------------------*
  1282. ;* *
  1283. ;* ScanEISA - poll any EISA devices through the BIOS's Int15(0d8h) *
  1284. ;* and add any memory we find out about to our free memory table. *
  1285. ;* Note: this code (including a big buffer) gets thrown out after *
  1286. ;* completion of the initialization sequence. *
  1287. ;* *
  1288. ;* Note: The COMPAQ BIOS uses up 1.5K of stack during int15(d80x) *
  1289. ;* so we'll set up a separate stack while we're here *
  1290. ;* *
  1291. ;*----------------------------------------------------------------------*
  1292. save_ss dw 0
  1293. save_sp dw 0
  1294. EISA_Stack:
  1295. endif ;NEC_98
  1296. _text ends
  1297. ifdef debug_tsr
  1298. EndStmt equ <end ExeStart>
  1299. STACK segment stack 'STACK'
  1300. db 1024 dup (?)
  1301. STACK ends
  1302. else
  1303. EndStmt equ <end>
  1304. endif
  1305. EndStmt
  1306.