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.

1544 lines
33 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Monitor.c
  5. Abstract:
  6. This module is the user mode portion of the x86 monitor
  7. Author:
  8. Dave Hastings (daveh) 16 Mar 1991
  9. Environment:
  10. User mode only
  11. Revision History:
  12. William Hsieh 10-10-1992 Added A20 wrapping support
  13. --*/
  14. #define VDD_INTEG 1
  15. #include "monitorp.h"
  16. #include <windows.h>
  17. #include <stdio.h>
  18. #include <malloc.h>
  19. // Tim Nov 92.
  20. void sas_connect_memory(
  21. IN sys_addr Low,
  22. IN sys_addr High,
  23. IN int Type
  24. );
  25. //BUGBUGBUGBUG Include file
  26. // from base\inc\sas.h
  27. /* memory types for sas */
  28. #define SAS_RAM 0
  29. #define SAS_VIDEO 1
  30. #define SAS_ROM 2
  31. #define SAS_WRAP 3
  32. #define SAS_INACCESSIBLE 4
  33. #define SAS_MAX_TYPE SAS_INACCESSIBLE
  34. #define SIXTYFOURK 0x10000L
  35. #define ONEMEGA 0x100000L
  36. void rom_init();
  37. void rom_checksum();
  38. void copyROM();
  39. USHORT get_lim_backfill_segment(void);
  40. BOOL HoldEMMBackFillMemory(ULONG Address, ULONG Size);
  41. #if DBG
  42. extern unsigned short get_emm_page_size(void);
  43. extern unsigned short get_intel_page_size(void);
  44. #endif
  45. /* SYNC THESE DEFINITIONS WITH BASE\EMM.H, or sas_init will assert */
  46. #define EMM_PAGE_SIZE 0x4000
  47. #define INTEL_PAGE_SIZE 0x1000
  48. typedef struct
  49. {
  50. ULONG (*b_read) ();
  51. ULONG (*w_read) ();
  52. VOID (*str_read) ();
  53. } READ_POINTERS;
  54. // Internal Data
  55. PMEMTYPE MemType = NULL;
  56. // External Data
  57. extern READ_POINTERS read_pointers;
  58. // M variables used by video.lib
  59. host_addr Start_of_M_area; /* host addr (char *) of start of M */
  60. sys_addr Length_of_M_area; /* sys addr (long) offset of end of M */
  61. static HANDLE A20SectionHandle = NULL;
  62. static BOOL A20IsON = FALSE;
  63. static USHORT BackFillSegment;
  64. EXPORT
  65. VOID
  66. sas_init(
  67. IN sys_addr Size
  68. )
  69. /*++
  70. Routine Description:
  71. This routine initializes the SAS module, and allocates the linear
  72. address space for the VDM, and loads the ROM
  73. Arguments:
  74. Size - Supplies the size of the VDMs linear address space.
  75. Return Value:
  76. None.
  77. --*/
  78. {
  79. NTSTATUS Status;
  80. ULONG ViewSize;
  81. PVOID BaseAddress;
  82. OBJECT_ATTRIBUTES A20ObjAttr;
  83. LARGE_INTEGER SectionSize;
  84. USHORT Pages;
  85. ULONG BackFillBase;
  86. InitializeObjectAttributes(
  87. &A20ObjAttr,
  88. NULL,
  89. 0,
  90. NULL,
  91. NULL
  92. );
  93. SectionSize.HighPart = 0L;
  94. SectionSize.LowPart = 640 * 1024 + 64 * 1024;
  95. Status = NtCreateSection(
  96. &A20SectionHandle,
  97. SECTION_MAP_WRITE|SECTION_MAP_EXECUTE,
  98. &A20ObjAttr,
  99. &SectionSize,
  100. PAGE_EXECUTE_READWRITE,
  101. SEC_RESERVE,
  102. NULL
  103. );
  104. if (!NT_SUCCESS(Status)) {
  105. // bugbug -williamh
  106. // we should pop up an approiate message before we
  107. // terminate the vdm.
  108. #if DBG
  109. DbgPrint("sas_init: can not create himem section, status = %lx\n",
  110. Status);
  111. #endif
  112. TerminateVDM();
  113. }
  114. VdmSize = Size;
  115. //
  116. // N.B. We expect that process creation has reserved the first 16 MB
  117. // for us already. If not, then this won't work worth a darn
  118. // free the first 640KB virtual address.
  119. // This is done because it has been resevered before sas_init get called
  120. BaseAddress = (PVOID)1;
  121. ViewSize = 640 * 1024 - 1;
  122. Status = NtFreeVirtualMemory(
  123. NtCurrentProcess(),
  124. &BaseAddress,
  125. &ViewSize,
  126. MEM_RELEASE
  127. );
  128. if (!NT_SUCCESS(Status)) {
  129. #if DBG
  130. DbgPrint("sas_init: cannot free 1st 640k virtual address, status = %lx\n",
  131. Status);
  132. #endif
  133. TerminateVDM();
  134. }
  135. BaseAddress =(PVOID) ONEMEGA;
  136. ViewSize = SIXTYFOURK;
  137. Status = NtFreeVirtualMemory(
  138. NtCurrentProcess(),
  139. &BaseAddress,
  140. &ViewSize,
  141. MEM_RELEASE
  142. );
  143. if (!NT_SUCCESS(Status)) {
  144. #if DBG
  145. DbgPrint("sas_init: can not free himem virtual address, status = %lx\n",
  146. Status);
  147. #endif
  148. TerminateVDM();
  149. }
  150. BaseAddress = (PVOID)VDM_BASE_ADDRESS;
  151. ViewSize = SIXTYFOURK - (ULONG)VDM_BASE_ADDRESS;
  152. SectionSize.HighPart = SectionSize.LowPart = 0;
  153. Status = NtMapViewOfSection(
  154. A20SectionHandle,
  155. NtCurrentProcess(),
  156. &BaseAddress,
  157. 0,
  158. ViewSize,
  159. &SectionSize,
  160. &ViewSize,
  161. ViewUnmap,
  162. MEM_DOS_LIM,
  163. PAGE_EXECUTE_READWRITE
  164. );
  165. if (!NT_SUCCESS(Status)){
  166. #if DBG
  167. DbgPrint("sas_init: can not map view of 1st 64K, status = %ls\n",
  168. Status);
  169. #endif
  170. TerminateVDM();
  171. }
  172. BaseAddress = (PVOID) ONEMEGA;
  173. ViewSize = SIXTYFOURK;
  174. Status = NtMapViewOfSection(A20SectionHandle,
  175. NtCurrentProcess(),
  176. &BaseAddress,
  177. 0,
  178. ViewSize,
  179. &SectionSize,
  180. &ViewSize,
  181. ViewUnmap,
  182. MEM_DOS_LIM,
  183. PAGE_EXECUTE_READWRITE
  184. );
  185. if (!NT_SUCCESS(Status)){
  186. #if DBG
  187. DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
  188. Status);
  189. #endif
  190. TerminateVDM();
  191. }
  192. // get emm back fill segment address from softpc
  193. // we cut the backfill memory area into pieces in EMM_PAGE_SIZE unit.
  194. // this is done so that EMM manager can grab the address space
  195. // as EMM page frame.
  196. // note that if EMM is disabled, the backfill segment will be
  197. // (640 * 1024 / 16).
  198. BackFillSegment = get_lim_backfill_segment();
  199. ASSERT(BackFillSegment <= 640 * 1024 / 16);
  200. //
  201. // Map the rest of conventional memory
  202. // only map up to the emm backfill segment.
  203. BaseAddress = (PVOID) (64 * 1024);
  204. ViewSize = BackFillSegment * 16 - 64 * 1024;
  205. SectionSize.LowPart = 64 * 1024;
  206. SectionSize.HighPart = 0;
  207. Status = NtMapViewOfSection(A20SectionHandle,
  208. NtCurrentProcess(),
  209. &BaseAddress,
  210. 0,
  211. ViewSize,
  212. &SectionSize,
  213. &ViewSize,
  214. ViewUnmap,
  215. MEM_DOS_LIM,
  216. PAGE_EXECUTE_READWRITE
  217. );
  218. if (!NT_SUCCESS(Status)){
  219. #if DBG
  220. DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
  221. Status);
  222. #endif
  223. TerminateVDM();
  224. }
  225. // if there are any backfill memory, map it to our section initially
  226. if (BackFillSegment < 640 * 1024 / 16) {
  227. /* make sure our constants are in sync with emm.h */
  228. #if DBG
  229. ASSERT(EMM_PAGE_SIZE == get_emm_page_size());
  230. ASSERT(INTEL_PAGE_SIZE == get_intel_page_size());
  231. #endif
  232. if (!HoldEMMBackFillMemory(BackFillSegment * 16,
  233. (640 * 1024) - BackFillSegment * 16)
  234. ) {
  235. #if DBG
  236. DbgPrint("sas_init: can not map backfill space, status = %lx\n",
  237. Status);
  238. #endif
  239. TerminateVDM();
  240. }
  241. }
  242. //
  243. // Allocate ROM area
  244. //
  245. BaseAddress = (PVOID)(640 * 1024);
  246. ViewSize = 384 * 1024;
  247. Status = NtAllocateVirtualMemory(
  248. NtCurrentProcess(),
  249. &BaseAddress,
  250. 0L,
  251. &ViewSize,
  252. MEM_COMMIT,
  253. PAGE_READWRITE
  254. );
  255. if (!NT_SUCCESS(Status)){
  256. #if DBG
  257. DbgPrint("sas_init: can not map view of himem space, status = %lx\n",
  258. Status);
  259. #endif
  260. TerminateVDM();
  261. }
  262. A20IsON = FALSE;
  263. Start_of_M_area = 0;
  264. Length_of_M_area = VdmSize;
  265. sas_connect_memory(0, VdmSize + 2*SIXTYFOURK -1, SAS_RAM);
  266. }
  267. #if VDD_INTEG
  268. EXPORT
  269. VOID
  270. sas_term(
  271. VOID
  272. )
  273. /*++
  274. Routine Description:
  275. Free memory prior to reallocing it
  276. Arguments:
  277. None.
  278. Return Value:
  279. None.
  280. --*/
  281. {
  282. PVOID BaseAddress;
  283. NTSTATUS Status;
  284. ULONG Size;
  285. BaseAddress = (PVOID)VDM_BASE_ADDRESS;
  286. Size = VdmSize;
  287. Status = NtFreeVirtualMemory(
  288. NtCurrentProcess(),
  289. &BaseAddress,
  290. &Size,
  291. MEM_DECOMMIT);
  292. if (!NT_SUCCESS(Status)) {
  293. VDprint(VDP_LEVEL_ERROR,
  294. ("SoftPc: NtDeCommitVirtualMemory failed !!!! Status = %lx\n",
  295. Status));
  296. VDbreak(VDB_LEVEL_ERROR);
  297. }
  298. }
  299. EXPORT
  300. sys_addr
  301. sas_memory_size(
  302. VOID
  303. )
  304. /*++
  305. Routine Description:
  306. This routine returns the size of Intel memory
  307. Arguments:
  308. none
  309. Return Value:
  310. size of intel memory
  311. --*/
  312. {
  313. return(VdmSize);
  314. }
  315. EXPORT
  316. VOID
  317. sas_connect_memory(
  318. IN sys_addr Low,
  319. IN sys_addr High,
  320. IN int Type
  321. )
  322. /*++
  323. Routine Description:
  324. This routine sets up a type record for the specified address region.
  325. If the specified address region was a different type, it is changed to
  326. the new type.
  327. Arguments:
  328. Low -- the starting address of the region
  329. High -- the ending address of the region
  330. Type -- the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM,
  331. SAS_WRAP, SAS_INACCESSIBLE
  332. Return Value:
  333. None.
  334. --*/
  335. {
  336. //bugbug do we handle new block contained in old block correctly?
  337. PMEMTYPE Current, Previous, New, Temp;
  338. if (!MemType) {
  339. MemType = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
  340. if ( NULL == MemType ) {
  341. goto ErrorSASC;
  342. }
  343. MemType->Previous = NULL;
  344. MemType->Next = NULL;
  345. MemType->Start = Low;
  346. MemType->End = High;
  347. MemType->Type = (half_word)Type;
  348. return;
  349. }
  350. Current = MemType;
  351. while (Current && (Low > Current->Start)) {
  352. Previous = Current;
  353. Current = Current->Next;
  354. }
  355. if ((Current) && (Low == Current->Start) && (High == Current->End)) {
  356. Current->Type = (half_word)Type;
  357. return;
  358. }
  359. New = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
  360. if ( NULL == New ) {
  361. goto ErrorSASC;
  362. }
  363. if (!Current) {
  364. // Block goes at end of list
  365. Previous->Next = New;
  366. New->Previous = Previous;
  367. New->Start = Low;
  368. New->End = High;
  369. New->Type = (half_word)Type;
  370. New->Next = NULL;
  371. } else {
  372. // Block goes in front of Current
  373. New->Start = Low;
  374. New->Type = (half_word)Type;
  375. New->End = High;
  376. New->Previous = Current->Previous;
  377. New->Next = Current;
  378. Current->Previous = New;
  379. if (!New->Previous) {
  380. MemType = New;
  381. } else {
  382. New->Previous->Next = New;
  383. }
  384. }
  385. // Block overlaps one or more existing blocks
  386. if (New->Previous) {
  387. if (New->Previous->End > New->End) {
  388. // block contained in exising block
  389. Temp = (PMEMTYPE) ch_malloc(sizeof(MEMTYPE));
  390. if(NULL == Temp) {
  391. goto ErrorSASC;
  392. }
  393. Temp->Previous = New;
  394. Temp->Next = New->Next;
  395. New->Next = Temp;
  396. if (Temp->Next) {
  397. Temp->Next->Previous = Temp;
  398. }
  399. Temp->End = New->Previous->End;
  400. New->Previous->End = New->Start - 1;
  401. Temp->Start = New->End + 1;
  402. Temp->Type = New->Previous->Type;
  403. return;
  404. } else if (New->Previous->End >= New->Start){
  405. // block overlaps end of exising block
  406. New->Previous->End = New->Start - 1;
  407. }
  408. }
  409. // remove all blocks entirely contained in new block
  410. while ((New->Next) && (New->Next->End <= New->End)) {
  411. Temp = New->Next;
  412. New->Next = New->Next->Next;
  413. if (New->Next) {
  414. New->Next->Previous = New;
  415. }
  416. free(Temp);
  417. }
  418. // remove portion of next block overlapping new block
  419. if ((New->Next) && (New->Next->Start <= New->End)) {
  420. New->Next->Start = New->End + 1;
  421. }
  422. return;
  423. ErrorSASC:
  424. RcMessageBox(EG_MALLOC_FAILURE, NULL, NULL,
  425. RMB_ICON_BANG | RMB_ABORT);
  426. TerminateVDM();
  427. }
  428. EXPORT
  429. half_word
  430. sas_memory_type(
  431. IN sys_addr Address
  432. )
  433. /*++
  434. Routine Description:
  435. This routine returns the type of memory at a specific address
  436. Arguments:
  437. Address -- linear address to return type for.
  438. Return Value:
  439. the type for the region, one of SAS_RAM, SAS_VIDEO, SAS_ROM,
  440. SAS_WRAP, SAS_INACCESSIBLE
  441. --*/
  442. {
  443. PMEMTYPE Current;
  444. if (Address > VdmSize) {
  445. return SAS_INACCESSIBLE;
  446. }
  447. Current = MemType;
  448. while (Current && !((Address >= Current->Start) &&
  449. (Address <= Current->End))) {
  450. Current = Current->Next;
  451. }
  452. if (!Current) {
  453. return SAS_INACCESSIBLE;
  454. }
  455. return Current->Type;
  456. }
  457. EXPORT
  458. VOID
  459. sas_enable_20_bit_wrapping(
  460. VOID
  461. )
  462. /*++
  463. Routine Description:
  464. This routine causes memory addresses to wrap at 1MB
  465. Arguments:
  466. None.
  467. Return Value:
  468. None.
  469. --*/
  470. {
  471. NTSTATUS Status;
  472. PVOID BaseAddress;
  473. ULONG Size;
  474. LARGE_INTEGER SectionOffset;
  475. // if A20 line is off already do nothing
  476. if (A20IsON == FALSE){
  477. return;
  478. }
  479. BaseAddress = (PVOID)ONEMEGA;
  480. Size = SIXTYFOURK;
  481. Status = NtUnmapViewOfSection(NtCurrentProcess(),
  482. BaseAddress
  483. );
  484. if (!NT_SUCCESS(Status)) {
  485. #if DBG
  486. DbgPrint("A20OFF: Unable to unmap view of section, status = %lx\n",
  487. Status);
  488. #endif
  489. TerminateVDM();
  490. }
  491. SectionOffset.HighPart = SectionOffset.LowPart = 0;
  492. Status = NtMapViewOfSection(A20SectionHandle,
  493. NtCurrentProcess(),
  494. &BaseAddress,
  495. 0,
  496. Size,
  497. &SectionOffset,
  498. &Size,
  499. ViewUnmap,
  500. MEM_DOS_LIM,
  501. PAGE_EXECUTE_READWRITE
  502. );
  503. if (!NT_SUCCESS(Status)) {
  504. #if DBG
  505. DbgPrint("A20OFF: Unable to map view of section, status = %lx\n",
  506. Status);
  507. #endif
  508. TerminateVDM();
  509. }
  510. A20IsON = FALSE;
  511. }
  512. EXPORT
  513. VOID
  514. sas_disable_20_bit_wrapping(
  515. VOID
  516. )
  517. /*++
  518. Routine Description:
  519. This routine causes addressing to NOT wrap at 1MB
  520. Arguments:
  521. None.
  522. Return Value:
  523. None.
  524. --*/
  525. {
  526. NTSTATUS Status;
  527. PVOID BaseAddress;
  528. ULONG Size;
  529. LARGE_INTEGER SectionOffset;
  530. // if A20 line is on already do nothing
  531. if (A20IsON == TRUE){
  532. return;
  533. }
  534. BaseAddress = (PVOID)ONEMEGA;
  535. Size = SIXTYFOURK;
  536. Status = NtUnmapViewOfSection(NtCurrentProcess(),
  537. BaseAddress
  538. );
  539. if (!NT_SUCCESS(Status)) {
  540. #if DBG
  541. DbgPrint("A20ON: Unable to unmap view of section, status = %lx\n",
  542. Status);
  543. #endif
  544. TerminateVDM();
  545. }
  546. SectionOffset.HighPart = 0;
  547. SectionOffset.LowPart = 640 * 1024;
  548. Status = NtMapViewOfSection(A20SectionHandle,
  549. NtCurrentProcess(),
  550. &BaseAddress,
  551. 0,
  552. Size,
  553. &SectionOffset,
  554. &Size,
  555. ViewUnmap,
  556. MEM_DOS_LIM,
  557. PAGE_EXECUTE_READWRITE
  558. );
  559. if (!NT_SUCCESS(Status)) {
  560. #if DBG
  561. DbgPrint("A20ON: Unable to map view of section, status = %lx\n",
  562. Status);
  563. #endif
  564. TerminateVDM();
  565. }
  566. A20IsON = TRUE;
  567. }
  568. EXPORT
  569. half_word
  570. sas_hw_at(
  571. IN sys_addr Address
  572. )
  573. /*++
  574. Routine Description:
  575. This routine returns the byte at the specified address
  576. Arguments:
  577. Address -- address of byte to return
  578. Return Value:
  579. value of byte at specified address
  580. --*/
  581. {
  582. half_word RetVal;
  583. if (Address > VdmSize) {
  584. return 0xFE;
  585. }
  586. RetVal = *((half_word *)Address);
  587. return RetVal;
  588. }
  589. EXPORT
  590. word
  591. sas_w_at(
  592. IN sys_addr Address
  593. )
  594. /*++
  595. Routine Description:
  596. This routine returns the word at the specified address
  597. Arguments:
  598. Address -- address of word to return
  599. Return Value:
  600. value of word at specified address
  601. --*/
  602. {
  603. word RetVal;
  604. // DbgPrint("NtVdm : sas_w_at \n");
  605. if (Address > VdmSize) {
  606. return 0xFEFE;
  607. }
  608. RetVal = *((word *)Address);
  609. return RetVal;
  610. }
  611. EXPORT
  612. double_word
  613. sas_dw_at(
  614. IN sys_addr Address
  615. )
  616. /*++
  617. Routine Description:
  618. This routine returns the dword at the specified address
  619. Arguments:
  620. Address -- address of dword to return
  621. Return Value:
  622. value of dword at specified address
  623. --*/
  624. {
  625. double_word RetVal;
  626. //DbgPrint("NtVdm : sas_dw_at \n");
  627. RetVal = (double_word)(((ULONG)sas_w_at(Address + 2) << 16) +
  628. sas_w_at(Address));
  629. return RetVal;
  630. }
  631. EXPORT
  632. VOID
  633. sas_load(
  634. IN sys_addr Address,
  635. IN half_word *Value
  636. )
  637. /*++
  638. Routine Description:
  639. This routine stores the byte at the specified address in the supplied
  640. variable
  641. Arguments:
  642. Address -- address of byte to return
  643. Value -- Variable to store the value in
  644. Return Value:
  645. None.
  646. --*/
  647. {
  648. //DbgPrint("NtVdm : sas_load \n");
  649. if (Address > VdmSize) {
  650. *Value = 0xFE;
  651. return;
  652. }
  653. *Value = *((half_word *)Address);
  654. return;
  655. }
  656. EXPORT
  657. VOID
  658. sas_loadw(
  659. IN sys_addr Address,
  660. IN word *Value
  661. )
  662. /*++
  663. Routine Description:
  664. This routine stores the word at the specified address in the supplied
  665. variable
  666. Arguments:
  667. Address -- address of word to return
  668. Value -- Variable to store the value in
  669. Return Value:
  670. None.
  671. --*/
  672. {
  673. //DbgPrint("NtVdm : sas_loadw\n");
  674. if (Address > VdmSize) {
  675. *Value = 0xFEFE;
  676. return;
  677. }
  678. *Value = *((word *)Address);
  679. //DbgPrint("NtVdm : sas_loadw word at address %lx is %x (Not video)\n",Address,*Value);
  680. return;
  681. }
  682. EXPORT
  683. VOID
  684. sas_store(
  685. IN sys_addr Address,
  686. IN half_word Value
  687. )
  688. /*++
  689. Routine Description:
  690. This routine stores the specified byte at the specified address
  691. Arguments:
  692. Address -- address of word to return
  693. Value -- value to store
  694. Return Value:
  695. None.
  696. --*/
  697. {
  698. half_word Type;
  699. //DbgPrint("NtVdm : sas_store\n");
  700. if (Address <= VdmSize) {
  701. Type = sas_memory_type(Address);
  702. switch (Type) {
  703. case SAS_ROM:
  704. break;
  705. default:
  706. *((half_word *)Address) = Value;
  707. //DbgPrint("NtVdm : sas_store put byte %x at address %lx\n",Value,Address);
  708. break;
  709. }
  710. }
  711. }
  712. EXPORT
  713. VOID
  714. sas_storew(
  715. IN sys_addr Address,
  716. IN word Value
  717. )
  718. /*++
  719. Routine Description:
  720. This routine stores the specified word at the specified address
  721. Arguments:
  722. Address -- address of word to return
  723. Value -- value to store at the specified address
  724. Return Value:
  725. None.
  726. --*/
  727. {
  728. //DbgPrint("NtVdm : sas_storew\n");
  729. if (Address + 1 <= VdmSize) {
  730. switch (sas_memory_type(Address)) {
  731. case SAS_ROM:
  732. break;
  733. default:
  734. *((word *)Address) = Value;
  735. //DbgPrint("NtVdm : sas_storew put word %x at address %lx\n",Value,Address);
  736. break;
  737. }
  738. }
  739. }
  740. EXPORT
  741. VOID
  742. sas_storedw(
  743. IN sys_addr Address,
  744. IN double_word Value
  745. )
  746. /*++
  747. Routine Description:
  748. This routine stores the specified dword at the specified address
  749. Arguments:
  750. Address -- address of word to return
  751. Value -- value to store at the specified address
  752. Return Value:
  753. None.
  754. --*/
  755. {
  756. //_asm int 3;
  757. sas_storew(Address, (word)(Value & 0xFFFF));
  758. sas_storew(Address + 2, (word)((Value >> 16) & 0xFFFF));
  759. }
  760. EXPORT
  761. VOID
  762. sas_loads(
  763. IN sys_addr Source,
  764. IN host_addr Destination,
  765. IN sys_addr Length
  766. )
  767. /*++
  768. Routine Description:
  769. This routine copies the string from the specified intel address to the
  770. specified host address
  771. Arguments:
  772. Source -- Intel address to copy from
  773. Destination -- host address to copy the string to
  774. Length -- length of the string to copy
  775. Return Value:
  776. None.
  777. --*/
  778. {
  779. //DbgPrint("NtVdm : sas_loads\n");
  780. RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
  781. }
  782. EXPORT
  783. VOID
  784. sas_stores(
  785. IN sys_addr Destination,
  786. IN host_addr Source,
  787. IN sys_addr Length
  788. )
  789. /*++
  790. Routine Description:
  791. This routine copies the string from the specified host address to the
  792. specified intel address
  793. Arguments:
  794. Destination -- intel address to copy the string to
  795. Source -- host address to copy from
  796. Length -- length of the string to copy
  797. Return Value:
  798. None.
  799. --*/
  800. {
  801. //DbgPrint("NtVdm : sas_stores\n");
  802. switch (sas_memory_type(Destination)) {
  803. case SAS_ROM:
  804. break;
  805. default:
  806. RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
  807. break;
  808. }
  809. }
  810. EXPORT
  811. VOID
  812. sas_move_bytes_forward(
  813. IN sys_addr Source,
  814. IN sys_addr Destination,
  815. IN sys_addr Length
  816. )
  817. /*++
  818. Routine Description:
  819. This routine copies one region of intel memory to another.
  820. Arguments:
  821. Source -- source intel address
  822. Destination -- destination intel address
  823. Length -- length of region to copy (in bytes)
  824. Return Value:
  825. None.
  826. --*/
  827. {
  828. //DbgPrint("NtVdm : sas_move_bytes_forward\n");
  829. switch (sas_memory_type(Destination)) {
  830. case SAS_ROM:
  831. break;
  832. default:
  833. RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
  834. break;
  835. }
  836. }
  837. EXPORT
  838. VOID
  839. sas_move_words_forward(
  840. IN sys_addr Source,
  841. IN sys_addr Destination,
  842. IN sys_addr Length
  843. )
  844. /*++
  845. Routine Description:
  846. This routine copies one region of intel memory to another.
  847. Arguments:
  848. Source -- source intel address
  849. Destination -- destination intel address
  850. Length -- length of region to copy (in words)
  851. Return Value:
  852. None.
  853. --*/
  854. {
  855. //_asm int 3;
  856. Length <<= 1;
  857. switch (sas_memory_type(Destination)) {
  858. case SAS_ROM:
  859. break;
  860. default:
  861. RtlCopyMemory((PVOID) Destination, (PVOID) Source, Length);
  862. break;
  863. }
  864. }
  865. EXPORT
  866. VOID
  867. sas_move_bytes_backward(
  868. IN sys_addr Source,
  869. IN sys_addr Destination,
  870. IN sys_addr Length
  871. )
  872. /*++
  873. Routine Description:
  874. This routine copies one region of intel memory to another.
  875. Arguments:
  876. Source -- source intel address
  877. Destination -- destination intel address
  878. Length -- length of region to copy (in bytes)
  879. Return Value:
  880. None.
  881. --*/
  882. {
  883. //_asm int 3;
  884. switch (sas_memory_type(Destination)) {
  885. case SAS_ROM:
  886. break;
  887. default:
  888. RtlCopyMemory((PVOID) (Destination - Length + 1),
  889. (PVOID) (Source - Length + 1),
  890. Length);
  891. break;
  892. }
  893. }
  894. EXPORT
  895. VOID
  896. sas_move_words_backward(
  897. IN sys_addr Source,
  898. IN sys_addr Destination,
  899. IN sys_addr Length
  900. )
  901. /*++
  902. Routine Description:
  903. This routine copies one region of intel memory to another.
  904. Arguments:
  905. Source -- source intel address
  906. Destination -- destination intel address
  907. Length -- length of region to copy (in words)
  908. Return Value:
  909. None.
  910. --*/
  911. {
  912. //_asm int 3;
  913. Length <<= 1;
  914. switch (sas_memory_type(Destination)) {
  915. case SAS_ROM:
  916. break;
  917. default:
  918. RtlCopyMemory((PVOID) (Destination - Length + 1),
  919. (PVOID) (Source - Length + 1),
  920. Length);
  921. break;
  922. }
  923. }
  924. EXPORT
  925. VOID
  926. sas_fills(
  927. IN sys_addr Address,
  928. IN half_word Value,
  929. IN sys_addr Length
  930. )
  931. /*++
  932. Routine Description:
  933. This routine fills a specified region of intel memory with a byte value
  934. Arguments:
  935. Address -- address to fill at
  936. Value -- value to fill with
  937. Length -- length of region to fill
  938. Return Value:
  939. None.
  940. --*/
  941. {
  942. half_word Type;
  943. //DbgPrint("NtVdm : sas_fills\n");
  944. Type = sas_memory_type(Address);
  945. switch (Type) {
  946. case SAS_ROM:
  947. break;
  948. default:
  949. RtlFillMemory((PVOID) Address, Length, Value);
  950. break;
  951. }
  952. }
  953. EXPORT
  954. VOID
  955. sas_fillsw(
  956. IN sys_addr Address,
  957. IN word Value,
  958. IN sys_addr Length
  959. )
  960. /*++
  961. Routine Description:
  962. This routine fills a specified region of intel memory with a word value
  963. Arguments:
  964. Address -- address to fill at
  965. Value -- value to fill with
  966. Length -- length of region to fill
  967. Return Value:
  968. None.
  969. --*/
  970. {
  971. word *p;
  972. half_word Type;
  973. //DbgPrint("NtVdm : sas_fillsw\n");
  974. Type = sas_memory_type(Address);
  975. switch (Type) {
  976. case SAS_ROM:
  977. break;
  978. default:
  979. p = (word *)Address;
  980. while (Length--) {
  981. *p++ = Value;
  982. }
  983. break;
  984. }
  985. }
  986. host_addr scratch = NULL;
  987. EXPORT
  988. host_addr
  989. sas_scratch_address(
  990. IN sys_addr Length
  991. )
  992. /*++
  993. Routine Description:
  994. This routine supplies a scratch buffer for short term use
  995. Arguments
  996. Length -- length of buffer needed
  997. Return Value:
  998. None.
  999. NOTE: Sudeepb 31-Oct-1993 Converted scratch to be allocated dynamically rather
  1000. than as a static array.
  1001. --*/
  1002. {
  1003. //DbgPrint("NtVdm : sas_scratch_address\n");
  1004. if (Length > 64 * 1024) {
  1005. return NULL;
  1006. }
  1007. if (scratch)
  1008. return scratch;
  1009. if ((scratch = (host_addr) malloc (64 * 1024)) == NULL){
  1010. RcMessageBox(EG_MALLOC_FAILURE, NULL, NULL,
  1011. RMB_ICON_BANG | RMB_ABORT);
  1012. TerminateVDM();
  1013. return NULL;
  1014. }
  1015. return scratch;
  1016. }
  1017. EXPORT
  1018. half_word
  1019. sas_hw_at_no_check(
  1020. sys_addr addr
  1021. )
  1022. // bugbug comment
  1023. {
  1024. //DbgPrint("NtVdm : sas_hw_at_no_check\n");
  1025. //DbgPrint("NtVdm : sas_hw_at_no_check byte at %lx is %x\n",addr,*((half_word *)addr));
  1026. return *((half_word *)addr);
  1027. }
  1028. EXPORT
  1029. word
  1030. sas_w_at_no_check(
  1031. sys_addr addr
  1032. )
  1033. // bugbug comment
  1034. {
  1035. //DbgPrint("NtVdm : sas_w_at_no_check\n");
  1036. //DbgPrint("NtVdm : sas_w_at_no_check word at %lx is %x\n",addr,*((word *)addr));
  1037. return *((word *)addr);
  1038. }
  1039. EXPORT
  1040. double_word
  1041. sas_dw_at_no_check(
  1042. sys_addr addr
  1043. )
  1044. // bugbug comment
  1045. {
  1046. //DbgPrint("NtVdm : sas_dw_at_no_check\n");
  1047. //DbgPrint("NtVdm : sas_dw_at_no_check double word at %lx is %lx\n",addr,*((double_word *)addr));
  1048. return *((double_word *)addr);
  1049. }
  1050. EXPORT
  1051. VOID
  1052. sas_store_no_check(
  1053. sys_addr addr,
  1054. half_word val
  1055. )
  1056. // bugbug comment
  1057. {
  1058. //DbgPrint("NtVdm : sas_store_no_check\n");
  1059. *((half_word *)addr) = val;
  1060. //DbgPrint("NtVdm : sas_store_no_check stored byte %x at %lx\n",val,addr);
  1061. }
  1062. EXPORT
  1063. VOID
  1064. sas_storew_no_check(
  1065. sys_addr addr,
  1066. word val
  1067. )
  1068. // bugbug comment
  1069. {
  1070. //DbgPrint("NtVdm : sas_storew_no_check\n");
  1071. *((word *)addr) = val;
  1072. }
  1073. EXPORT
  1074. double_word
  1075. effective_addr(
  1076. IN word Segment,
  1077. IN word Offset
  1078. )
  1079. /*++
  1080. Routine Description:
  1081. This routine maps effective_addr to Sim32GetVdmPointer
  1082. Arguments:
  1083. Segment -- segment of address
  1084. Offset -- offset of address
  1085. Return Value:
  1086. Actual Intel address corresponding to the address supplied
  1087. --*/
  1088. {
  1089. //DbgPrint("NtVdm : effective_addr\n");
  1090. return (ULONG)Sim32GetVDMPointer(((((ULONG)Segment) << 16) | Offset), 1,
  1091. (UCHAR) (getMSW() & MSW_PE ? TRUE : FALSE));
  1092. }
  1093. typedef enum
  1094. {
  1095. RAM,
  1096. VIDEO,
  1097. ROM,
  1098. IN_FRAGMENT,
  1099. NEXT_FRAGMENT
  1100. } mem_type;
  1101. typedef struct
  1102. {
  1103. VOID (*b_write)();
  1104. VOID (*w_write)();
  1105. VOID (*b_fill)();
  1106. VOID (*w_fill)();
  1107. VOID (*b_move)();
  1108. VOID (*w_move)();
  1109. } MEM_HANDLERS;
  1110. #define TYPE_RANGE ((int)SAS_INACCESSIBLE)
  1111. #define write_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) )
  1112. #define write_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) )
  1113. #define write_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) )
  1114. #define write_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) )
  1115. #define init_b_write_ptrs( offset, func ) ( b_write_ptrs[(offset)] = (func) )
  1116. #define init_w_write_ptrs( offset, func ) ( w_write_ptrs[(offset)] = (func) )
  1117. #define init_b_page_ptrs( offset, func ) ( b_move_ptrs[(offset)] = b_fill_ptrs[(offset)] = (func) )
  1118. #define init_w_page_ptrs( offset, func ) ( w_move_ptrs[(offset)] = w_fill_ptrs[(offset)] = (func) )
  1119. #define read_b_write_ptrs( offset ) ( b_write_ptrs[(offset)] )
  1120. #define read_w_write_ptrs( offset ) ( w_write_ptrs[(offset)] )
  1121. #define read_b_page_ptrs( offset ) ( b_move_ptrs[(offset)] )
  1122. #define read_w_page_ptrs( offset ) ( w_move_ptrs[(offset)] )
  1123. #define read_b_move_ptrs( offset ) ( b_move_ptrs[(offset)] )
  1124. #define read_w_move_ptrs( offset ) ( w_move_ptrs[(offset)] )
  1125. #define read_b_fill_ptrs( offset ) ( b_fill_ptrs[(offset)] )
  1126. #define read_w_fill_ptrs( offset ) ( w_fill_ptrs[(offset)] )
  1127. /*
  1128. * The main gmi data structures are defined here
  1129. */
  1130. void (*(b_write_ptrs[TYPE_RANGE]))() ; /* byte write function */
  1131. void (*(w_write_ptrs[TYPE_RANGE]))() ; /* word write function */
  1132. void (*(b_fill_ptrs[TYPE_RANGE]))() ; /* byte str fill func */
  1133. void (*(w_fill_ptrs[TYPE_RANGE]))() ; /* word str fill func */
  1134. void (*(b_move_ptrs[TYPE_RANGE]))() ; /* byte str write func */
  1135. void (*(w_move_ptrs[TYPE_RANGE]))() ; /* word str write func */
  1136. void gmi_define_mem(type,handlers)
  1137. mem_type type;
  1138. MEM_HANDLERS *handlers;
  1139. {
  1140. int int_type = (int)(type);
  1141. init_b_write_ptrs(int_type, (void(*)())(handlers->b_write));
  1142. init_w_write_ptrs(int_type, (void(*)())(handlers->w_write));
  1143. b_move_ptrs[int_type] = (void(*)())(handlers->b_move);
  1144. w_move_ptrs[int_type] = (void(*)())(handlers->w_move);
  1145. b_fill_ptrs[int_type] = (void(*)())(handlers->b_fill);
  1146. w_fill_ptrs[int_type] = (void(*)())(handlers->w_fill);
  1147. }
  1148. #endif
  1149. BOOL sas_twenty_bit_wrapping_enabled() {
  1150. return (!A20IsON);
  1151. }
  1152. VOID sas_part_enable_20_bit_wrapping(){
  1153. }
  1154. VOID sas_part_disable_20_bit_wrapping(){
  1155. }
  1156. /*
  1157. * This function maps the given EMM backfill memory to DOS conventional
  1158. * memory. The function is provided to EMM manager to put back
  1159. * unmapped backfill memory(hold its contents while it is not mapped).
  1160. *
  1161. * NOTE: The very first caller will be sas_init.
  1162. *
  1163. * Input: ULONG BaseAddress -- the starting address, must be in INTEL page
  1164. * boundary
  1165. * ULONG Size -- size of the range, must be a multiple of
  1166. * EMM_PAGE_SIZE.
  1167. *
  1168. * According to LouP, a view costs about 400 bytes of memory. This is why
  1169. * I make these function strictly to work on EMM_PAGE_SIZE instead of 4KB.
  1170. */
  1171. BOOL
  1172. HoldEMMBackFillMemory(ULONG BaseAddress, ULONG Size)
  1173. {
  1174. ULONG NewBase, Pages, i;
  1175. LARGE_INTEGER SectionOffset;
  1176. ULONG ViewSize;
  1177. NTSTATUS Status = STATUS_SUCCESS;;
  1178. /* this function can only be called if there is backfill at all */
  1179. ASSERT(BackFillSegment < 640 * 1024 / 16);
  1180. // size must be EMM_PAGE_SIZE multiple
  1181. ASSERT((Size % EMM_PAGE_SIZE) == 0);
  1182. // address must be on INTEL page boundary
  1183. ASSERT((BaseAddress & (INTEL_PAGE_SIZE - 1)) == 0);
  1184. for (Pages = Size / EMM_PAGE_SIZE; Pages; Pages--) {
  1185. SectionOffset.LowPart = BaseAddress;
  1186. SectionOffset.HighPart = 0;
  1187. ViewSize = EMM_PAGE_SIZE;
  1188. Status = NtMapViewOfSection(A20SectionHandle,
  1189. NtCurrentProcess(),
  1190. (PVOID *)&BaseAddress,
  1191. 0,
  1192. ViewSize,
  1193. &SectionOffset,
  1194. &ViewSize,
  1195. ViewUnmap,
  1196. MEM_DOS_LIM,
  1197. PAGE_EXECUTE_READWRITE
  1198. );
  1199. if (!NT_SUCCESS(Status))
  1200. break;
  1201. BaseAddress += EMM_PAGE_SIZE;
  1202. }
  1203. return (NT_SUCCESS(Status));
  1204. }