;	Static Name Aliases
;
	TITLE   mapdma.c
	NAME    mapdma

	.286p
	.287
_TEXT	SEGMENT  WORD PUBLIC 'CODE'
_TEXT	ENDS
_DATA	SEGMENT  WORD PUBLIC 'DATA'
_DATA	ENDS
CONST	SEGMENT  WORD PUBLIC 'CONST'
CONST	ENDS
_BSS	SEGMENT  WORD PUBLIC 'BSS'
_BSS	ENDS
DGROUP	GROUP	CONST, _BSS, _DATA
	ASSUME  CS: _TEXT, DS: DGROUP, SS: DGROUP
EXTRN	__acrtused:ABS
EXTRN	_GetPte:NEAR
EXTRN	_SetPte:NEAR
EXTRN	_GetCRSEntry:NEAR
EXTRN	_GetDMALinAdr:NEAR
EXTRN	_Exchange16K:NEAR
EXTRN	_FatalError:NEAR
EXTRN	_EMM_MPindex:BYTE
EXTRN	_mappable_pages:BYTE
EXTRN	_pft386:WORD
EXTRN	_DMA_Pages:BYTE
EXTRN	_DMA_PAGE_COUNT:WORD
EXTRN	_physical_page_count:WORD
_DATA      SEGMENT
$SG167	DB	'SwapDMAPages : Two Emm pages mapped to same logical page in '
	DB	'the xfer area',  00H
$SG182	DB	'Insufficient DMA pages in the DMA Buffer',  00H
$SG199	DB	'Cannot find PFT386 entry for EMM page corresponding to LinAd'
	DB	'r',  00H
_DATA      ENDS
_TEXT      SEGMENT
	ASSUME	CS: _TEXT
;|*** 
;|*** 
;|*** /*  MAPDMA.C   - Ensures DMA Xfer area is physically contiguous. Swaps pages 
;|***  *               if necessary.
;|***  *
;|***  *  Date    Author      Comments
;|***     8/12/88 JHB         updated comments, checking for sufficient pages
;|***                         available in DMA_Pages[] before remappping
;|*** 
;|***     8/18/88 JHB         if incoming parameters appear to be wrong or
;|***                         if any unmapped page found in the transfer area assume 
;|***                         the Address and Count registers do not have valid values
;|***                         and hence return without swapping pages.
;|***                         Removed IFDEF DEBUG code
;|***  */
;|*** 
;|*** #define HEX4K           0x1000
;|*** #define HEX16K          0x4000L
;|*** #define HEX64K          0x10000
;|*** #define HEX128K         0x20000
;|*** #define HEX256K         0x40000L
;|*** #define HEX640K         0xA0000L
;|*** #define HEX1MB          0x100000L
;|*** 
;|*** #define ALIGN128K       ~0x1FFFFL
;|*** #define ALIGN64K        ~0x0FFFFL
;|*** #define ALIGN16K        ~0x03FFFL
;|*** 
;|*** #define MAX_PHYS_PAGES  40
;|*** 
;|*** /* macros 
;|***  * PT(a)       - pte from index a
;|***  * INDEX(a)    - index from Linear Adr
;|***  * OFFSET(a)   - offset from Linear Adr
;|***  * LIN2PHY(l)  - Physical Adr from Linear Adr
;|***  * DosPhyPage  - consider 16K pages from 0 to 1MB. Let Page at 256K be page 0.
;|***  * DOSPHYPAGE(a) - DosPhyPage for Adr in 1 MB range
;|***  * PFT(a)      - pick up ith entry in pft386[] 
;|***  */
;|*** 
;|*** #define PT(a)           (GetPteFromIndex((a)))
;|*** #define INDEX(a)        ((((long)a)>>12) & 0x3FF)
;|*** #define OFFSET(a)       (((long)a) & 0xFFF)
;|*** #define LIN2PHY(l)      ((PT(INDEX(l)) & ~0xFFFL)+(long)OFFSET(l))
;|*** #define DOSPHYPAGE(a)   (((a)>>14)-16)
;|*** #define PFT(a)          (*(long *)(pft386+a))
;|*** struct mappable_page {
;|***    unsigned short page_seg;            /* segment of physical page */
;|***    unsigned short physical_page;       /* physical page number */
;|*** };
;|*** 
;|*** /* Xlates DosPhyPage into an index in mappable_pages[]. */
;|*** extern char EMM_MPindex[];    /* index from 4000H to 10000H in steps of 16K */
;|*** extern struct mappable_page mappable_pages[];
;|*** extern long *pft386;
;|*** extern unsigned DMA_Pages[];
;|*** extern DMA_PAGE_COUNT;                 /* size of DMA_Pages[] */
;|*** extern unsigned physical_page_count;
;|*** 
;|*** /* routines imported from elimtrap.asm */
;|*** extern long GetPte();                  /* get a PT entry given index */
;|*** extern SetPte();                       /* set a PT entry */
;|*** extern unsigned GetCRSEntry();   /* get CurRegSet entry for given EmmPhyPage */
;|*** extern long GetDMALinAdr();      /* Get Linear Adr for the DMA buffer */
;|*** extern Exchange16K();                  /* exchange page contents */
;|*** extern FatalError();
;|*** 
;|*** /* forward declarations */
;|*** long GetPteFromIndex();
;|*** 
;|*** /* 
;|***  * SwapDMAPages()
;|***  *    FromAdr - DMA Xfer addr
;|***  *    Len - Xfer length
;|***  *    bXfer - 0 for byte transfer, 1 for word transfer
;|***  *
;|***  * Check whether the DMA Xfer area starting at FromAdr is contiguous in 
;|***  * physical memory. If it isn't, make it contiguous by exchanging pages
;|***  * with the DMA buffer.
;|***  */
;|*** 
;|*** long SwapDMAPages(FromAdr, Len, bXfer)
;|*** long FromAdr, Len;
; Line 83
	PUBLIC	_SwapDMAPages
_SwapDMAPages	PROC NEAR
	*** 000000	c8 52 00 00 		enter	WORD PTR 82,0
	*** 000004	56 			push	si
;|*** unsigned bXfer;
;|*** {
; Line 85
;	FromAdr16K = -78
;	FromAdr64_128K = -60
;	ToAdr = -56
;	ToAdr16K = -68
;	ExpectedAdr = -46
;	PgFrame = -22
;	First64_128K_Adr = -74
;	Last64_128K_Adr = -42
;	Adr = -28
;	PhyAdr = -34
;	LinAdr = -52
;	i = -38
;	j = -48
;	k = -64
;	bSwap = -70
;	n16KPages = -2
;	FromAdr = 4
;	Len = 8
;	bXfer = 12
;	Index = -36
;	Offset = -30
;	n4KPages = -82
;	PhyPages = -18
;	DMAPageK = -62
;	Page = -80
;	MPIndex = -24
;|*** unsigned Index, Offset, /* components of a PTE */
;|***       n4KPages,         /* # of 4K Pages involved in the DMA transfer */
;|***       PhyPages[8],      /* Emm Phy page numbers involved in the DMA transfer 
;|***                            atmost 8.*/
;|***       DMAPageK,         /* kth DMA Page - start exchanging pages from here */
;|***       Page, MPIndex;
;|*** 
;|*** long  FromAdr16K,       /* FromAdr rounded down to 16K boundary */
;|***       FromAdr64_128K,   /* FromAdr rounded down to 64/128K boundary */
;|***       ToAdr,            /* Last Byte for the DMA trasfer */
;|***       ToAdr16K,         /* ToAdr rounded down to 16K boundary */
;|***       ExpectedAdr,   
;|***       PgFrame,          /* PgFrame Address */
;|***       First64_128K_Adr, Last64_128K_Adr,/* First and Last 4K page aligned on a 64/128 boundary */ 
;|***       Adr, PhyAdr, LinAdr;          
;|*** 
;|*** int i, j, k, bSwap,
;|***       n16KPages;        /* # of 16K Pages involved in the DMA transfer */
;|*** 
;|*** 
;|***    if (FromAdr < HEX256K || FromAdr >= HEX1MB) 
; Line 106
	*** 000005	83 7e 06 04 		cmp	WORD PTR [bp+6],4
	*** 000009	7c 06 			jl	$L20001
	*** 00000b	83 7e 06 10 		cmp	WORD PTR [bp+6],16
	*** 00000f	7c 33 			jl	$I144
					$L20001:
;|***       return LIN2PHY(FromAdr);   /* not in the EMM area */
; Line 107
	*** 000011	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000014	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000017	b1 0c 			mov	cl,12
					$L20002:
	*** 000019	d1 fa 			sar	dx,1
	*** 00001b	d1 d8 			rcr	ax,1
	*** 00001d	fe c9 			dec	cl
	*** 00001f	75 f8 			jne	$L20002
					$L20003:
	*** 000021	80 e4 03 		and	ah,3
	*** 000024	2b d2 			sub	dx,dx
	*** 000026	52 			push	dx
	*** 000027	50 			push	ax
	*** 000028	e8 00 00 		call	_GetPteFromIndex
	*** 00002b	83 c4 04 		add	sp,4
	*** 00002e	25 00 f0 		and	ax,-4096
	*** 000031	8b 4e 04 		mov	cx,WORD PTR [bp+4]	;FromAdr
	*** 000034	8b 5e 06 		mov	bx,WORD PTR [bp+6]
	*** 000037	80 e5 0f 		and	ch,15
	*** 00003a	2b db 			sub	bx,bx
	*** 00003c	03 c1 			add	ax,cx
	*** 00003e	13 d3 			adc	dx,bx
	*** 000040	5e 			pop	si
	*** 000041	c9 			leave	
	*** 000042	c3 			ret	
	*** 000043	90 			nop	
					$I144:
;|*** 
;|*** /* Since the Address and count register are programmed a byte at a time
;|***  * they might have invalid values in them (because of left overs).
;|***  * If invalid parameters, i.e. Xfer area crosses 64K or 128K boundary,or count 
;|***  * is invalid or the DMA Xfer area has unmapped pages - just return.
;|***  */
;|***    if ((!bXfer && (FromAdr + Len) > ((FromAdr & ALIGN64K) + HEX64K)) ||
;|***        (bXfer && (FromAdr + Len) > ((FromAdr & ALIGN128K) + HEX128K)) ||
;|***        (!bXfer && Len > HEX64K) || (bXfer && Len > HEX128K))
; Line 116
	*** 000044	83 7e 0c 00 		cmp	WORD PTR [bp+12],0	;bXfer
	*** 000048	75 23 			jne	$L20004
	*** 00004a	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 00004d	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000050	03 46 08 		add	ax,WORD PTR [bp+8]	;Len
	*** 000053	13 56 0a 		adc	dx,WORD PTR [bp+10]
	*** 000056	8b 4e 04 		mov	cx,WORD PTR [bp+4]	;FromAdr
	*** 000059	8b 5e 06 		mov	bx,WORD PTR [bp+6]
	*** 00005c	2b c9 			sub	cx,cx
	*** 00005e	03 c9 			add	cx,cx
	*** 000060	83 d3 01 		adc	bx,1
	*** 000063	3b d3 			cmp	dx,bx
	*** 000065	7f 5a 			jg	$L20007
	*** 000067	7c 04 			jl	$L20004
	*** 000069	3b c1 			cmp	ax,cx
	*** 00006b	77 54 			ja	$L20007
					$L20004:
	*** 00006d	83 7e 0c 00 		cmp	WORD PTR [bp+12],0	;bXfer
	*** 000071	74 26 			je	$L20005
	*** 000073	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000076	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000079	03 46 08 		add	ax,WORD PTR [bp+8]	;Len
	*** 00007c	13 56 0a 		adc	dx,WORD PTR [bp+10]
	*** 00007f	8b 4e 04 		mov	cx,WORD PTR [bp+4]	;FromAdr
	*** 000082	8b 5e 06 		mov	bx,WORD PTR [bp+6]
	*** 000085	2b c9 			sub	cx,cx
	*** 000087	80 e3 fe 		and	bl,254
	*** 00008a	03 c9 			add	cx,cx
	*** 00008c	83 d3 02 		adc	bx,2
	*** 00008f	3b d3 			cmp	dx,bx
	*** 000091	7f 2e 			jg	$L20007
	*** 000093	7c 04 			jl	$L20005
	*** 000095	3b c1 			cmp	ax,cx
	*** 000097	77 28 			ja	$L20007
					$L20005:
	*** 000099	83 7e 0c 00 		cmp	WORD PTR [bp+12],0	;bXfer
	*** 00009d	75 0e 			jne	$L20006
	*** 00009f	83 7e 0a 01 		cmp	WORD PTR [bp+10],1
	*** 0000a3	7f 1c 			jg	$L20007
	*** 0000a5	7c 06 			jl	$L20006
	*** 0000a7	83 7e 08 00 		cmp	WORD PTR [bp+8],0	;Len
	*** 0000ab	75 14 			jne	$L20007
					$L20006:
	*** 0000ad	83 7e 0c 00 		cmp	WORD PTR [bp+12],0	;bXfer
	*** 0000b1	74 19 			je	$I146
	*** 0000b3	83 7e 0a 02 		cmp	WORD PTR [bp+10],2
	*** 0000b7	7c 13 			jl	$I146
	*** 0000b9	7f 06 			jg	$L20007
	*** 0000bb	83 7e 08 00 		cmp	WORD PTR [bp+8],0	;Len
	*** 0000bf	74 0b 			je	$I146
					$L20007:
;|***       return FromAdr;   /* assume DMA registers not programmed yet */
; Line 117
	*** 0000c1	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 0000c4	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 0000c7	5e 			pop	si
	*** 0000c8	c9 			leave	
	*** 0000c9	c3 			ret	
	*** 0000ca	90 			nop	
	*** 0000cb	90 			nop	
					$I146:
	*** 0000cc	c7 46 da 00 00 		mov	WORD PTR [bp-38],0	;i
					$FC152:
;|*** 
;|*** /* initialise PhyPages[] - unequal negative values */
;|***    for (i = 0; i < 8; i++)
;|***       PhyPages[i] = -(i+1);
; Line 121
	*** 0000d1	8b 76 da 		mov	si,WORD PTR [bp-38]	;i
	*** 0000d4	d1 e6 			shl	si,1
	*** 0000d6	8b 46 da 		mov	ax,WORD PTR [bp-38]	;i
	*** 0000d9	40 			inc	ax
	*** 0000da	f7 d8 			neg	ax
	*** 0000dc	89 42 ee 		mov	[bp-18][si],ax
	*** 0000df	ff 46 da 		inc	WORD PTR [bp-38]	;i
	*** 0000e2	83 7e da 08 		cmp	WORD PTR [bp-38],8	;i
	*** 0000e6	7c e9 			jl	$FC152
;|*** 
;|*** 
;|*** /* The DMA buffer is part of the Emm pool.
;|***  * Hence we can only swap pages which are 16K in size. Hence calculate 
;|***  * n16KPages - # of 16K pages involved in the transfer.
;|*** 
;|***  * ToAdr - Linear Address of the last byte where the DMA transfer 
;|***  * is to take place 
;|***  */
;|***    ToAdr = FromAdr + Len - 1L;
; Line 131
	*** 0000e8	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 0000eb	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 0000ee	03 46 08 		add	ax,WORD PTR [bp+8]	;Len
	*** 0000f1	13 56 0a 		adc	dx,WORD PTR [bp+10]
	*** 0000f4	2d 01 00 		sub	ax,1
	*** 0000f7	83 da 00 		sbb	dx,0
	*** 0000fa	89 46 c8 		mov	WORD PTR [bp-56],ax	;ToAdr
	*** 0000fd	89 56 ca 		mov	WORD PTR [bp-54],dx
;|***    FromAdr16K = FromAdr & ALIGN16K;
; Line 132
	*** 000100	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000103	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000106	25 00 c0 		and	ax,-16384
	*** 000109	89 46 b2 		mov	WORD PTR [bp-78],ax	;FromAdr16K
	*** 00010c	89 56 b4 		mov	WORD PTR [bp-76],dx
;|***    ToAdr16K = ToAdr & ALIGN16K;
; Line 133
	*** 00010f	8b 46 c8 		mov	ax,WORD PTR [bp-56]	;ToAdr
	*** 000112	8b 56 ca 		mov	dx,WORD PTR [bp-54]
	*** 000115	25 00 c0 		and	ax,-16384
	*** 000118	89 46 bc 		mov	WORD PTR [bp-68],ax	;ToAdr16K
	*** 00011b	89 56 be 		mov	WORD PTR [bp-66],dx
;|***    n16KPages = ((ToAdr16K - FromAdr16K)>>14) + 1; /* (ToAdr16K-FromAdr16K)/HEX16K + 1 */
; Line 134
	*** 00011e	2b 46 b2 		sub	ax,WORD PTR [bp-78]	;FromAdr16K
	*** 000121	1b 56 b4 		sbb	dx,WORD PTR [bp-76]
	*** 000124	b1 0e 			mov	cl,14
					$L20008:
	*** 000126	d1 fa 			sar	dx,1
	*** 000128	d1 d8 			rcr	ax,1
	*** 00012a	fe c9 			dec	cl
	*** 00012c	75 f8 			jne	$L20008
	*** 00012e	40 			inc	ax
	*** 00012f	89 46 fe 		mov	WORD PTR [bp-2],ax	;n16KPages
;|*** 
;|*** /* If any unmapped page in the transfer area - assume DMA registers not 
;|***  * fully programmed yet
;|***  */
;|***    for (i = 0, Adr = FromAdr16K; Adr <= ToAdr16K; Adr += HEX16K, i++)   {
; Line 139
	*** 000132	c7 46 da 00 00 		mov	WORD PTR [bp-38],0	;i
	*** 000137	8b 46 b2 		mov	ax,WORD PTR [bp-78]	;FromAdr16K
	*** 00013a	8b 56 b4 		mov	dx,WORD PTR [bp-76]
	*** 00013d	89 46 e4 		mov	WORD PTR [bp-28],ax	;Adr
	*** 000140	89 56 e6 		mov	WORD PTR [bp-26],dx
	*** 000143	eb 0d 			jmp	SHORT $F154
	*** 000145	90 			nop	
					$FC155:
	*** 000146	81 46 e4 00 40 		add	WORD PTR [bp-28],16384	;Adr
	*** 00014b	83 56 e6 00 		adc	WORD PTR [bp-26],0
	*** 00014f	ff 46 da 		inc	WORD PTR [bp-38]	;i
					$F154:
	*** 000152	8b 46 bc 		mov	ax,WORD PTR [bp-68]	;ToAdr16K
	*** 000155	8b 56 be 		mov	dx,WORD PTR [bp-66]
	*** 000158	39 56 e6 		cmp	WORD PTR [bp-26],dx
	*** 00015b	7f 4f 			jg	$FB156
	*** 00015d	7c 05 			jl	$L20010
	*** 00015f	39 46 e4 		cmp	WORD PTR [bp-28],ax	;Adr
	*** 000162	77 48 			ja	$FB156
					$L20010:
;|***       MPIndex = EMM_MPindex[DOSPHYPAGE(Adr)];
; Line 140
	*** 000164	8b 5e e4 		mov	bx,WORD PTR [bp-28]	;Adr
	*** 000167	8b 4e e6 		mov	cx,WORD PTR [bp-26]
	*** 00016a	8b c1 			mov	ax,cx
	*** 00016c	b1 0e 			mov	cl,14
					$L20013:
	*** 00016e	d1 f8 			sar	ax,1
	*** 000170	d1 db 			rcr	bx,1
	*** 000172	fe c9 			dec	cl
	*** 000174	75 f8 			jne	$L20013
	*** 000176	8a 87 f0 ff 		mov	al,BYTE PTR _EMM_MPindex[bx-16]
	*** 00017a	98 			cbw	
	*** 00017b	89 46 e8 		mov	WORD PTR [bp-24],ax	;MPIndex
;|***       if (MPIndex == -1)   /* Adr not mappable */
; Line 141
	*** 00017e	3d ff ff 		cmp	ax,-1
	*** 000181	75 03 			jne	$JCC385
	*** 000183	e9 3b ff 		jmp	$L20007
					$JCC385:
;|***          return FromAdr;
;|***       else  {
; Line 143
;|***          PhyPages[i] = GetCRSEntry(mappable_pages[MPIndex].physical_page);
; Line 144
	*** 000186	8b 76 da 		mov	si,WORD PTR [bp-38]	;i
	*** 000189	d1 e6 			shl	si,1
	*** 00018b	03 f5 			add	si,bp
	*** 00018d	83 ee 12 		sub	si,18
	*** 000190	8b d8 			mov	bx,ax
	*** 000192	c1 e3 02 		shl	bx,2
	*** 000195	ff b7 02 00 		push	WORD PTR _mappable_pages[bx+2]
	*** 000199	e8 00 00 		call	_GetCRSEntry
	*** 00019c	83 c4 02 		add	sp,2
	*** 00019f	36 89 04 		mov	WORD PTR ss:[si],ax
;|***          if (PhyPages[i] == -1)  /* Adr not mapped currently */
; Line 145
	*** 0001a2	3d ff ff 		cmp	ax,-1
	*** 0001a5	75 03 			jne	$JCC421
	*** 0001a7	e9 17 ff 		jmp	$L20007
					$JCC421:
;|***             return FromAdr;
;|***       }
;|***    }
; Line 148
	*** 0001aa	eb 9a 			jmp	SHORT $FC155
					$FB156:
;|***       
;|***    for (j = 0; j < i; j++) {
; Line 150
	*** 0001ac	c7 46 d0 00 00 		mov	WORD PTR [bp-48],0	;j
	*** 0001b1	eb 28 			jmp	SHORT $F160
	*** 0001b3	90 			nop	
					$FC164:
	*** 0001b4	ff 46 c0 		inc	WORD PTR [bp-64]	;k
					$F163:
	*** 0001b7	8b 46 da 		mov	ax,WORD PTR [bp-38]	;i
	*** 0001ba	39 46 c0 		cmp	WORD PTR [bp-64],ax	;k
	*** 0001bd	7d 19 			jge	$FC161
;|***       Page = PhyPages[j];
;|***       for (k = j+1; k < i; k++)  {
;|***          if (PhyPages[k] == Page) 
; Line 153
	*** 0001bf	8b 76 c0 		mov	si,WORD PTR [bp-64]	;k
	*** 0001c2	d1 e6 			shl	si,1
	*** 0001c4	8b 46 b0 		mov	ax,WORD PTR [bp-80]	;Page
	*** 0001c7	39 42 ee 		cmp	[bp-18][si],ax
	*** 0001ca	75 e8 			jne	$FC164
;|***             FatalError("SwapDMAPages : Two Emm pages mapped to same logical page in the xfer area");
; Line 154
	*** 0001cc	68 00 00 		push	OFFSET DGROUP:$SG167
	*** 0001cf	e8 00 00 		call	_FatalError
	*** 0001d2	83 c4 02 		add	sp,2
;|***       }
; Line 155
	*** 0001d5	eb dd 			jmp	SHORT $FC164
	*** 0001d7	90 			nop	
					$FC161:
	*** 0001d8	ff 46 d0 		inc	WORD PTR [bp-48]	;j
					$F160:
	*** 0001db	8b 46 da 		mov	ax,WORD PTR [bp-38]	;i
	*** 0001de	39 46 d0 		cmp	WORD PTR [bp-48],ax	;j
	*** 0001e1	7d 15 			jge	$FB162
;|***       Page = PhyPages[j];
; Line 151
	*** 0001e3	8b 76 d0 		mov	si,WORD PTR [bp-48]	;j
	*** 0001e6	d1 e6 			shl	si,1
	*** 0001e8	8b 42 ee 		mov	ax,[bp-18][si]
	*** 0001eb	89 46 b0 		mov	WORD PTR [bp-80],ax	;Page
;|***       for (k = j+1; k < i; k++)  {
; Line 152
	*** 0001ee	8b 46 d0 		mov	ax,WORD PTR [bp-48]	;j
	*** 0001f1	40 			inc	ax
	*** 0001f2	89 46 c0 		mov	WORD PTR [bp-64],ax	;k
	*** 0001f5	eb c0 			jmp	SHORT $F163
	*** 0001f7	90 			nop	
					$FB162:
;|***          if (PhyPages[k] == Page) 
;|***             FatalError("SwapDMAPages : Two Emm pages mapped to same logical page in the xfer area");
;|***       }
;|***    }
;|*** 
;|*** /* No unmapped page in the transfer area. Assume the Address and count registers
;|***  * have meaningful values in them.
;|***  */
;|***    Index = INDEX(FromAdr);
; Line 161
	*** 0001f8	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 0001fb	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 0001fe	b1 0c 			mov	cl,12
					$L20015:
	*** 000200	d1 fa 			sar	dx,1
	*** 000202	d1 d8 			rcr	ax,1
	*** 000204	fe c9 			dec	cl
	*** 000206	75 f8 			jne	$L20015
	*** 000208	80 e4 03 		and	ah,3
	*** 00020b	89 46 dc 		mov	WORD PTR [bp-36],ax	;Index
;|***    PgFrame = PT(Index) >> 12;
; Line 162
	*** 00020e	50 			push	ax
	*** 00020f	e8 00 00 		call	_GetPteFromIndex
	*** 000212	83 c4 02 		add	sp,2
	*** 000215	b1 0c 			mov	cl,12
					$L20017:
	*** 000217	d1 fa 			sar	dx,1
	*** 000219	d1 d8 			rcr	ax,1
	*** 00021b	fe c9 			dec	cl
	*** 00021d	75 f8 			jne	$L20017
	*** 00021f	89 46 ea 		mov	WORD PTR [bp-22],ax	;PgFrame
	*** 000222	89 56 ec 		mov	WORD PTR [bp-20],dx
;|***    Offset = OFFSET(FromAdr);
; Line 163
	*** 000225	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000228	80 e4 0f 		and	ah,15
	*** 00022b	89 46 e2 		mov	WORD PTR [bp-30],ax	;Offset
;|***    PhyAdr = (((long)PgFrame) << 12) + Offset;
; Line 164
	*** 00022e	8b 46 ea 		mov	ax,WORD PTR [bp-22]	;PgFrame
	*** 000231	b1 0c 			mov	cl,12
					$L20019:
	*** 000233	d1 e0 			shl	ax,1
	*** 000235	d1 d2 			rcl	dx,1
	*** 000237	fe c9 			dec	cl
	*** 000239	75 f8 			jne	$L20019
	*** 00023b	03 46 e2 		add	ax,WORD PTR [bp-30]	;Offset
	*** 00023e	83 d2 00 		adc	dx,0
	*** 000241	89 46 de 		mov	WORD PTR [bp-34],ax	;PhyAdr
	*** 000244	89 56 e0 		mov	WORD PTR [bp-32],dx
;|*** 
;|***    if (Offset + Len <= HEX4K)  /* within a page */
; Line 166
	*** 000247	8b 46 e2 		mov	ax,WORD PTR [bp-30]	;Offset
	*** 00024a	2b d2 			sub	dx,dx
	*** 00024c	03 46 08 		add	ax,WORD PTR [bp+8]	;Len
	*** 00024f	13 56 0a 		adc	dx,WORD PTR [bp+10]
	*** 000252	0b d2 			or	dx,dx
	*** 000254	75 10 			jne	$I168
	*** 000256	72 05 			jb	$L20021
	*** 000258	3d 00 10 		cmp	ax,4096
	*** 00025b	77 09 			ja	$I168
					$L20021:
;|***       return PhyAdr;
; Line 167
	*** 00025d	8b 46 de 		mov	ax,WORD PTR [bp-34]	;PhyAdr
	*** 000260	8b 56 e0 		mov	dx,WORD PTR [bp-32]
	*** 000263	5e 			pop	si
	*** 000264	c9 			leave	
	*** 000265	c3 			ret	
					$I168:
	*** 000266	8b 46 e2 		mov	ax,WORD PTR [bp-30]	;Offset
	*** 000269	2b d2 			sub	dx,dx
	*** 00026b	03 46 08 		add	ax,WORD PTR [bp+8]	;Len
	*** 00026e	13 56 0a 		adc	dx,WORD PTR [bp+10]
	*** 000271	b1 0c 			mov	cl,12
					$L20022:
	*** 000273	d1 ea 			shr	dx,1
	*** 000275	d1 d8 			rcr	ax,1
	*** 000277	fe c9 			dec	cl
	*** 000279	75 f8 			jne	$L20022
	*** 00027b	40 			inc	ax
	*** 00027c	89 46 ae 		mov	WORD PTR [bp-82],ax	;n4KPages
;|*** 
;|*** /* calculate # of 4K pages involved in the DMA transfer */
;|*** 
;|***    n4KPages = ((Offset + Len)>>12) + 1;   /* (Offset+Len)/4096K + 1 */
;|***    if (((Offset + Len) % HEX4K) == 0)
; Line 172
	*** 00027f	8b 46 e2 		mov	ax,WORD PTR [bp-30]	;Offset
	*** 000282	2b d2 			sub	dx,dx
	*** 000284	03 46 08 		add	ax,WORD PTR [bp+8]	;Len
	*** 000287	13 56 0a 		adc	dx,WORD PTR [bp+10]
	*** 00028a	a9 ff 0f 		test	ax,4095
	*** 00028d	75 03 			jne	$I169
;|***       n4KPages--;
; Line 173
	*** 00028f	ff 4e ae 		dec	WORD PTR [bp-82]	;n4KPages
;|*** 
;|*** /* see if these n4KPages are physically contiguous */
;|***    bSwap = 0;
; Line 176
					$I169:
	*** 000292	c7 46 ba 00 00 		mov	WORD PTR [bp-70],0	;bSwap
;|***    for (i = 1; i < n4KPages; i++)   {
; Line 177
	*** 000297	c7 46 da 01 00 		mov	WORD PTR [bp-38],1	;i
	*** 00029c	eb 03 			jmp	SHORT $F170
					$FC171:
	*** 00029e	ff 46 da 		inc	WORD PTR [bp-38]	;i
					$F170:
	*** 0002a1	8b 46 ae 		mov	ax,WORD PTR [bp-82]	;n4KPages
	*** 0002a4	39 46 da 		cmp	WORD PTR [bp-38],ax	;i
	*** 0002a7	73 32 			jae	$FB172
;|***       if ((PT(Index + i)>>12) != (PgFrame + i)) {
; Line 178
	*** 0002a9	8b 46 da 		mov	ax,WORD PTR [bp-38]	;i
	*** 0002ac	03 46 dc 		add	ax,WORD PTR [bp-36]	;Index
	*** 0002af	50 			push	ax
	*** 0002b0	e8 00 00 		call	_GetPteFromIndex
	*** 0002b3	83 c4 02 		add	sp,2
	*** 0002b6	b1 0c 			mov	cl,12
					$L20024:
	*** 0002b8	d1 fa 			sar	dx,1
	*** 0002ba	d1 d8 			rcr	ax,1
	*** 0002bc	fe c9 			dec	cl
	*** 0002be	75 f8 			jne	$L20024
	*** 0002c0	8b c8 			mov	cx,ax
	*** 0002c2	8b 46 da 		mov	ax,WORD PTR [bp-38]	;i
	*** 0002c5	8b da 			mov	bx,dx
	*** 0002c7	99 			cwd	
	*** 0002c8	03 46 ea 		add	ax,WORD PTR [bp-22]	;PgFrame
	*** 0002cb	13 56 ec 		adc	dx,WORD PTR [bp-20]
	*** 0002ce	3b c1 			cmp	ax,cx
	*** 0002d0	75 04 			jne	$L20028
	*** 0002d2	3b d3 			cmp	dx,bx
	*** 0002d4	74 c8 			je	$FC171
					$L20028:
;|***          bSwap = 1;
; Line 179
	*** 0002d6	c7 46 ba 01 00 		mov	WORD PTR [bp-70],1	;bSwap
;|***          break;
; Line 180
					$FB172:
;|***       }
;|***    }
;|*** 
;|*** /* Suppose the Xfer area is physically contiguous. We may still need to swap
;|***  * pages with the DMA buffer if the physical pages straddle a 64K/128K boundary
;|***  * (the DMA will wrap around in this case). DOS would have tried to fix this
;|***  * but it would have split the Linear Address - this is of very little use.
;|***  * 
;|***  * if (!bSwap && straddling 64/128K boundary) set bSwap;
;|***  */
;|***    if (!bSwap) {  /* the DMA Pages are contiguous, any straddling ? */
; Line 191
	*** 0002db	83 7e ba 00 		cmp	WORD PTR [bp-70],0	;bSwap
	*** 0002df	75 65 			jne	$I177
;|***       if (!bXfer) {  /* byte transfer */
; Line 192
	*** 0002e1	83 7e 0c 00 		cmp	WORD PTR [bp+12],0	;bXfer
	*** 0002e5	75 23 			jne	$I175
;|***          First64_128K_Adr = PT(Index) & ALIGN64K;
; Line 193
	*** 0002e7	ff 76 dc 		push	WORD PTR [bp-36]	;Index
	*** 0002ea	e8 00 00 		call	_GetPteFromIndex
	*** 0002ed	83 c4 02 		add	sp,2
	*** 0002f0	2b c0 			sub	ax,ax
	*** 0002f2	89 46 b6 		mov	WORD PTR [bp-74],ax	;First64_128K_Adr
	*** 0002f5	89 56 b8 		mov	WORD PTR [bp-72],dx
;|***          Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN64K;
; Line 194
	*** 0002f8	8b 46 dc 		mov	ax,WORD PTR [bp-36]	;Index
	*** 0002fb	03 46 ae 		add	ax,WORD PTR [bp-82]	;n4KPages
	*** 0002fe	48 			dec	ax
	*** 0002ff	50 			push	ax
	*** 000300	e8 00 00 		call	_GetPteFromIndex
	*** 000303	83 c4 02 		add	sp,2
	*** 000306	2b c0 			sub	ax,ax
	*** 000308	eb 27 			jmp	SHORT $L20070
					$I175:
;|***       }
;|***       else  {     /* word transfer */
; Line 196
;|***          First64_128K_Adr = PT(Index) & ALIGN128K;
; Line 197
	*** 00030a	ff 76 dc 		push	WORD PTR [bp-36]	;Index
	*** 00030d	e8 00 00 		call	_GetPteFromIndex
	*** 000310	83 c4 02 		add	sp,2
	*** 000313	2b c0 			sub	ax,ax
	*** 000315	80 e2 fe 		and	dl,254
	*** 000318	89 46 b6 		mov	WORD PTR [bp-74],ax	;First64_128K_Adr
	*** 00031b	89 56 b8 		mov	WORD PTR [bp-72],dx
;|***          Last64_128K_Adr = PT(Index+n4KPages-1) & ALIGN128K;
; Line 198
	*** 00031e	8b 46 dc 		mov	ax,WORD PTR [bp-36]	;Index
	*** 000321	03 46 ae 		add	ax,WORD PTR [bp-82]	;n4KPages
	*** 000324	48 			dec	ax
	*** 000325	50 			push	ax
	*** 000326	e8 00 00 		call	_GetPteFromIndex
	*** 000329	83 c4 02 		add	sp,2
	*** 00032c	2b c0 			sub	ax,ax
	*** 00032e	80 e2 fe 		and	dl,254
					$L20070:
	*** 000331	89 46 d6 		mov	WORD PTR [bp-42],ax	;Last64_128K_Adr
	*** 000334	89 56 d8 		mov	WORD PTR [bp-40],dx
;|***       }
; Line 199
;|***       
;|***       if (First64_128K_Adr != Last64_128K_Adr) 
; Line 201
	*** 000337	39 46 b6 		cmp	WORD PTR [bp-74],ax	;First64_128K_Adr
	*** 00033a	75 05 			jne	$L20029
	*** 00033c	39 56 b8 		cmp	WORD PTR [bp-72],dx
	*** 00033f	74 05 			je	$I177
					$L20029:
;|***          bSwap = 1;
; Line 202
	*** 000341	c7 46 ba 01 00 		mov	WORD PTR [bp-70],1	;bSwap
;|***    }
; Line 203
					$I177:
;|*** 
;|***    if (!bSwap) 
; Line 205
	*** 000346	83 7e ba 00 		cmp	WORD PTR [bp-70],0	;bSwap
	*** 00034a	75 03 			jne	$JCC842
	*** 00034c	e9 0e ff 		jmp	$L20021
					$JCC842:
	*** 00034f	83 7e 0c 00 		cmp	WORD PTR [bp+12],0	;bXfer
	*** 000353	74 0d 			je	$I179
;|***       return PhyAdr;
;|*** 
;|*** /* The DMA transfer area is not contiguous. The DMA buffer is part of the Emm
;|***  * pool. Hence we can only swap pages which are 16K in size. n16KPages is the
;|***  * # of 16K pages involved in the transfer.
;|***  */
;|*** 
;|*** /* Round down FromAdr to 64/128K boundary */
;|***    if (bXfer)  /* word transfer ? */
;|***       FromAdr64_128K = FromAdr & ALIGN128K; /* Align on 128K boundary */
; Line 215
	*** 000355	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000358	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 00035b	2b c0 			sub	ax,ax
	*** 00035d	80 e2 fe 		and	dl,254
	*** 000360	eb 08 			jmp	SHORT $L20067
					$I179:
;|***    else
;|***       FromAdr64_128K = FromAdr & ALIGN64K;    /* Align on 64K boundary */
; Line 217
	*** 000362	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000365	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000368	2b c0 			sub	ax,ax
					$L20067:
	*** 00036a	89 46 c4 		mov	WORD PTR [bp-60],ax	;FromAdr64_128K
	*** 00036d	89 56 c6 		mov	WORD PTR [bp-58],dx
;|*** 
;|*** /* Swap pages so that the DMA Xfer area is physically contiguous.
;|***    
;|***                |        |                      |        |
;|***  FromAdr     ->|        |                      |        |
;|***                |        |                      |        |
;|***                |        |                      |        |
;|***  FromAdr16K  ->|        | - - - DMAPage[k]  -->|        |
;|***                |        |                      |        |
;|***                |        |                      |        |
;|*** FromAdr64_128k-|        |       DMAPage[0]  -->|        |
;|***                ----------                      ----------
;|*** 
;|***    DMA transfer area starts at FromAdr.
;|***    Map kth DMA page to FromAdr16K and so on until all the transfer area is mapped 
;|***  
;|***  */
;|*** 
;|*** /* Linear Adr of user page which has to be relocated */
;|***    LinAdr = FromAdr16K;
; Line 237
	*** 000370	8b 46 b2 		mov	ax,WORD PTR [bp-78]	;FromAdr16K
	*** 000373	8b 56 b4 		mov	dx,WORD PTR [bp-76]
	*** 000376	89 46 cc 		mov	WORD PTR [bp-52],ax	;LinAdr
	*** 000379	89 56 ce 		mov	WORD PTR [bp-50],dx
;|*** 
;|*** /* corresponding DMA Page - k value in the above figure */
;|***    DMAPageK = (FromAdr16K - FromAdr64_128K) >> 14;
; Line 240
	*** 00037c	2b 46 c4 		sub	ax,WORD PTR [bp-60]	;FromAdr64_128K
	*** 00037f	1b 56 c6 		sbb	dx,WORD PTR [bp-58]
	*** 000382	b1 0e 			mov	cl,14
					$L20030:
	*** 000384	d1 fa 			sar	dx,1
	*** 000386	d1 d8 			rcr	ax,1
	*** 000388	fe c9 			dec	cl
	*** 00038a	75 f8 			jne	$L20030
	*** 00038c	89 46 c2 		mov	WORD PTR [bp-62],ax	;DMAPageK
;|***    
;|***    ExpectedAdr = PFT(DMA_Pages[DMAPageK]);
; Line 242
	*** 00038f	8b d8 			mov	bx,ax
	*** 000391	d1 e3 			shl	bx,1
	*** 000393	8b 9f 00 00 		mov	bx,WORD PTR _DMA_Pages[bx]
	*** 000397	c1 e3 02 		shl	bx,2
	*** 00039a	8b 36 00 00 		mov	si,_pft386
	*** 00039e	8b 00 			mov	ax,[bx][si]
	*** 0003a0	8b 50 02 		mov	dx,[bx+2][si]
	*** 0003a3	89 46 d2 		mov	WORD PTR [bp-46],ax	;ExpectedAdr
	*** 0003a6	89 56 d4 		mov	WORD PTR [bp-44],dx
;|*** 
;|***    if (DMAPageK + n16KPages > DMA_PAGE_COUNT)
; Line 244
	*** 0003a9	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;n16KPages
	*** 0003ac	03 46 c2 		add	ax,WORD PTR [bp-62]	;DMAPageK
	*** 0003af	3b 06 00 00 		cmp	ax,_DMA_PAGE_COUNT
	*** 0003b3	76 09 			jbe	$I181
;|***       FatalError("Insufficient DMA pages in the DMA Buffer");
; Line 245
	*** 0003b5	68 4a 00 		push	OFFSET DGROUP:$SG182
	*** 0003b8	e8 00 00 		call	_FatalError
	*** 0003bb	83 c4 02 		add	sp,2
;|*** 
;|***    for (k = DMAPageK; k < DMAPageK + n16KPages; k++, LinAdr += HEX16K,
; Line 247
					$I181:
;|***                                                      ExpectedAdr += HEX16K)   {
; Line 248
	*** 0003be	8b 46 c2 		mov	ax,WORD PTR [bp-62]	;DMAPageK
	*** 0003c1	89 46 c0 		mov	WORD PTR [bp-64],ax	;k
	*** 0003c4	eb 5d 			jmp	SHORT $F183
					$FC184:
;|***       /* Already mapped correctly ? */
;|***       if (LIN2PHY(LinAdr) == ExpectedAdr) 
; Line 250
	*** 0003c6	8b 46 cc 		mov	ax,WORD PTR [bp-52]	;LinAdr
	*** 0003c9	8b 56 ce 		mov	dx,WORD PTR [bp-50]
	*** 0003cc	b1 0c 			mov	cl,12
					$L20032:
	*** 0003ce	d1 fa 			sar	dx,1
	*** 0003d0	d1 d8 			rcr	ax,1
	*** 0003d2	fe c9 			dec	cl
	*** 0003d4	75 f8 			jne	$L20032
	*** 0003d6	80 e4 03 		and	ah,3
	*** 0003d9	2b d2 			sub	dx,dx
	*** 0003db	52 			push	dx
	*** 0003dc	50 			push	ax
	*** 0003dd	e8 00 00 		call	_GetPteFromIndex
	*** 0003e0	83 c4 04 		add	sp,4
	*** 0003e3	25 00 f0 		and	ax,-4096
	*** 0003e6	8b 4e cc 		mov	cx,WORD PTR [bp-52]	;LinAdr
	*** 0003e9	8b 5e ce 		mov	bx,WORD PTR [bp-50]
	*** 0003ec	80 e5 0f 		and	ch,15
	*** 0003ef	2b db 			sub	bx,bx
	*** 0003f1	03 c1 			add	ax,cx
	*** 0003f3	13 d3 			adc	dx,bx
	*** 0003f5	3b 46 d2 		cmp	ax,WORD PTR [bp-46]	;ExpectedAdr
	*** 0003f8	75 05 			jne	$I186
	*** 0003fa	3b 56 d4 		cmp	dx,WORD PTR [bp-44]
	*** 0003fd	74 0f 			je	$L20068
;|***          continue;
; Line 251
					$I186:
	*** 0003ff	ff 76 c0 		push	WORD PTR [bp-64]	;k
	*** 000402	ff 76 ce 		push	WORD PTR [bp-50]
	*** 000405	ff 76 cc 		push	WORD PTR [bp-52]	;LinAdr
	*** 000408	e8 00 00 		call	_SwapAPage
	*** 00040b	83 c4 06 		add	sp,6
;|***       /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page */
;|***       SwapAPage(LinAdr, k);
;|***    }
; Line 254
					$L20068:
	*** 00040e	ff 46 c0 		inc	WORD PTR [bp-64]	;k
	*** 000411	81 46 cc 00 40 		add	WORD PTR [bp-52],16384	;LinAdr
	*** 000416	83 56 ce 00 		adc	WORD PTR [bp-50],0
	*** 00041a	81 46 d2 00 40 		add	WORD PTR [bp-46],16384	;ExpectedAdr
	*** 00041f	83 56 d4 00 		adc	WORD PTR [bp-44],0
					$F183:
	*** 000423	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;n16KPages
	*** 000426	03 46 c2 		add	ax,WORD PTR [bp-62]	;DMAPageK
	*** 000429	3b 46 c0 		cmp	ax,WORD PTR [bp-64]	;k
	*** 00042c	77 98 			ja	$FC184
;|***    
;|***    return LIN2PHY(FromAdr);
; Line 256
	*** 00042e	8b 46 04 		mov	ax,WORD PTR [bp+4]	;FromAdr
	*** 000431	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000434	b1 0c 			mov	cl,12
					$L20069:
	*** 000436	0a c9 			or	cl,cl
	*** 000438	75 03 			jne	$JCC1080
	*** 00043a	e9 e4 fb 		jmp	$L20003
					$JCC1080:
	*** 00043d	d1 fa 			sar	dx,1
	*** 00043f	d1 d8 			rcr	ax,1
	*** 000441	fe c9 			dec	cl
	*** 000443	eb f1 			jmp	SHORT $L20069
	*** 000445	90 			nop	

_SwapDMAPages	ENDP
;|*** }
;|*** 
;|*** /* Swap the 16K page(4 4K pages) at LinAdr with the kth DMA Page.
;|***  * Update the Emm Data Structures to reflect this remapping.
;|***  * Update the Page Table too.
;|***  */
;|*** SwapAPage(LinAdr, k)
;|*** long LinAdr;
; Line 264
	PUBLIC	_SwapAPage
_SwapAPage	PROC NEAR
	*** 000446	c8 12 00 00 		enter	WORD PTR 18,0
	*** 00044a	57 			push	di
	*** 00044b	56 			push	si
;|*** unsigned k;
;|*** {
; Line 266
;	EmmPhyPage = -18
;	UserPFTIndex = -2
;	DMAPhyAdr = -12
;	DMALinAdr = -16
;	i = -6
;	j = -8
;	LinAdr = 4
;	k = 8
;	DosPhyPage = -4
;|*** unsigned DosPhyPage, /* each page 16K in size, page at 256K is Page 0 */
;|***          EmmPhyPage, /* Phy page numbering according to Emm */
;|***          UserPFTIndex;  /* index into pft386 for Emm phy page at LinAdr */
;|*** 
;|*** long DMAPhyAdr, DMALinAdr;
;|*** int i, j;
;|*** 
;|*** /* Updating Emm data structures */
;|*** 
;|*** /* Find the pft386 entry for LinAdr */
;|***    DosPhyPage = DOSPHYPAGE(LinAdr); /* Page at 256K is page zero */
; Line 277
	*** 00044c	8b 46 04 		mov	ax,WORD PTR [bp+4]	;LinAdr
	*** 00044f	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000452	b1 0e 			mov	cl,14
					$L20036:
	*** 000454	d1 fa 			sar	dx,1
	*** 000456	d1 d8 			rcr	ax,1
	*** 000458	fe c9 			dec	cl
	*** 00045a	75 f8 			jne	$L20036
	*** 00045c	2d 10 00 		sub	ax,16
	*** 00045f	89 46 fc 		mov	WORD PTR [bp-4],ax	;DosPhyPage
;|***    EmmPhyPage = mappable_pages[EMM_MPindex[DosPhyPage]].physical_page;
; Line 278
	*** 000462	8b d8 			mov	bx,ax
	*** 000464	8a 87 00 00 		mov	al,BYTE PTR _EMM_MPindex[bx]
	*** 000468	98 			cbw	
	*** 000469	8b d8 			mov	bx,ax
	*** 00046b	c1 e3 02 		shl	bx,2
	*** 00046e	8b 87 02 00 		mov	ax,WORD PTR _mappable_pages[bx+2]
	*** 000472	89 46 ee 		mov	WORD PTR [bp-18],ax	;EmmPhyPage
;|*** 
;|*** /* get the CurRegSet entry for this physical page. */
;|***    UserPFTIndex = GetCRSEntry(EmmPhyPage);
; Line 281
	*** 000475	50 			push	ax
	*** 000476	e8 00 00 		call	_GetCRSEntry
	*** 000479	83 c4 02 		add	sp,2
	*** 00047c	89 46 fe 		mov	WORD PTR [bp-2],ax	;UserPFTIndex
;|***    
;|***    if (UserPFTIndex == -1)
; Line 283
	*** 00047f	3d ff ff 		cmp	ax,-1
	*** 000482	75 09 			jne	$I198
;|***       FatalError("Cannot find PFT386 entry for EMM page corresponding to LinAdr");   
; Line 284
	*** 000484	68 73 00 		push	OFFSET DGROUP:$SG199
	*** 000487	e8 00 00 		call	_FatalError
	*** 00048a	83 c4 02 		add	sp,2
;|***       
;|*** /* exchange pft386 entries at UserPFTIndex and DMA_Pages[k] */
;|*** 
;|***    DMAPhyAdr = PFT(DMA_Pages[k]);
; Line 288
					$I198:
	*** 00048d	8b 5e 08 		mov	bx,WORD PTR [bp+8]	;k
	*** 000490	d1 e3 			shl	bx,1
	*** 000492	8b b7 00 00 		mov	si,WORD PTR _DMA_Pages[bx]
	*** 000496	c1 e6 02 		shl	si,2
	*** 000499	03 36 00 00 		add	si,_pft386
	*** 00049d	8b 04 			mov	ax,WORD PTR [si]
	*** 00049f	8b 54 02 		mov	dx,WORD PTR [si+2]
	*** 0004a2	89 46 f4 		mov	WORD PTR [bp-12],ax	;DMAPhyAdr
	*** 0004a5	89 56 f6 		mov	WORD PTR [bp-10],dx
;|***    PFT(DMA_Pages[k]) = PFT(UserPFTIndex);
; Line 289
	*** 0004a8	8b 7e fe 		mov	di,WORD PTR [bp-2]	;UserPFTIndex
	*** 0004ab	c1 e7 02 		shl	di,2
	*** 0004ae	03 3e 00 00 		add	di,_pft386
	*** 0004b2	8b 05 			mov	ax,WORD PTR [di]
	*** 0004b4	8b 55 02 		mov	dx,WORD PTR [di+2]
	*** 0004b7	89 04 			mov	WORD PTR [si],ax
	*** 0004b9	89 54 02 		mov	WORD PTR [si+2],dx
;|***    PFT(UserPFTIndex) = DMAPhyAdr;
; Line 290
	*** 0004bc	8b 46 f4 		mov	ax,WORD PTR [bp-12]	;DMAPhyAdr
	*** 0004bf	8b 56 f6 		mov	dx,WORD PTR [bp-10]
	*** 0004c2	89 05 			mov	WORD PTR [di],ax
	*** 0004c4	89 55 02 		mov	WORD PTR [di+2],dx
;|*** 
;|*** /* Fix Page table entries .
;|***  * The contents of the user page and DMA buffer page are exchanged always.
;|***  *  - because a mapping for this page may exist in a saved context,
;|***  *  - can do a one way copy if the non-existence of such a mapping is detected
;|***  *    by scanning emm_pages[]. Will optimize this later. 8/12/88 - JHB
;|***  *
;|***  * The PT entry for the user page has to be updated.
;|***  * There may or may not exist a PT entry for the DMA page. There exists
;|***  * an entry only if there exists a mapping in the CurRegSet. If there exists
;|***  * an entry it should be updated too.
;|***  */
;|*** 
;|*** /* Does PT Entry exist for the DMA buffer below 1 MB? */
;|*** 
;|***    for (i = 0; i < physical_page_count; i++) {
; Line 306
	*** 0004c7	c7 46 fa 00 00 		mov	WORD PTR [bp-6],0	;i
	*** 0004cc	eb 03 			jmp	SHORT $F200
					$FC201:
	*** 0004ce	ff 46 fa 		inc	WORD PTR [bp-6]	;i
					$F200:
	*** 0004d1	a1 00 00 		mov	ax,_physical_page_count
	*** 0004d4	39 46 fa 		cmp	WORD PTR [bp-6],ax	;i
	*** 0004d7	73 14 			jae	$FB202
;|***       if (GetCRSEntry(i) == DMA_Pages[k])
; Line 307
	*** 0004d9	ff 76 fa 		push	WORD PTR [bp-6]	;i
	*** 0004dc	e8 00 00 		call	_GetCRSEntry
	*** 0004df	83 c4 02 		add	sp,2
	*** 0004e2	8b 5e 08 		mov	bx,WORD PTR [bp+8]	;k
	*** 0004e5	d1 e3 			shl	bx,1
	*** 0004e7	39 87 00 00 		cmp	WORD PTR _DMA_Pages[bx],ax
	*** 0004eb	75 e1 			jne	$FC201
;|***          break;
; Line 308
					$FB202:
;|***    }
;|*** 
;|***    if (i == physical_page_count) {  
; Line 311
	*** 0004ed	a1 00 00 		mov	ax,_physical_page_count
	*** 0004f0	39 46 fa 		cmp	WORD PTR [bp-6],ax	;i
	*** 0004f3	75 2b 			jne	$I204
;|***       /* No Phy page mapped to the DMA page - so no pte to be updated for DMA Page */       
;|***       Exchange16K(LinAdr, GetDMALinAdr(DMAPhyAdr));
; Line 313
	*** 0004f5	ff 76 f6 		push	WORD PTR [bp-10]
	*** 0004f8	ff 76 f4 		push	WORD PTR [bp-12]	;DMAPhyAdr
	*** 0004fb	e8 00 00 		call	_GetDMALinAdr
	*** 0004fe	83 c4 04 		add	sp,4
	*** 000501	52 			push	dx
	*** 000502	50 			push	ax
	*** 000503	ff 76 06 		push	WORD PTR [bp+6]
	*** 000506	ff 76 04 		push	WORD PTR [bp+4]	;LinAdr
	*** 000509	e8 00 00 		call	_Exchange16K
	*** 00050c	83 c4 08 		add	sp,8
;|***       UpdateUserPTE(LinAdr, UserPFTIndex);
; Line 314
	*** 00050f	ff 76 fe 		push	WORD PTR [bp-2]	;UserPFTIndex
	*** 000512	ff 76 06 		push	WORD PTR [bp+6]
	*** 000515	ff 76 04 		push	WORD PTR [bp+4]	;LinAdr
	*** 000518	e8 00 00 		call	_UpdateUserPTE
	*** 00051b	83 c4 06 		add	sp,6
;|***    }
; Line 315
;|***    else  {
; Line 316
	*** 00051e	eb 6c 			jmp	SHORT $I206
					$I204:
;|***       /* ith EmmPhyPage mapped to DMA buffer 
;|***        * Scan mappable_pages[] array and find the Linear address that maps to it.
;|***        */
;|***       for (j = 0; j < MAX_PHYS_PAGES; j++)   {
; Line 320
	*** 000520	c7 46 f8 00 00 		mov	WORD PTR [bp-8],0	;j
	*** 000525	eb 04 			jmp	SHORT $F207
	*** 000527	90 			nop	
					$FC208:
	*** 000528	ff 46 f8 		inc	WORD PTR [bp-8]	;j
					$F207:
	*** 00052b	83 7e f8 28 		cmp	WORD PTR [bp-8],40	;j
	*** 00052f	7d 0f 			jge	$FB209
;|***          if (mappable_pages[j].physical_page == i)
; Line 321
	*** 000531	8b 5e f8 		mov	bx,WORD PTR [bp-8]	;j
	*** 000534	c1 e3 02 		shl	bx,2
	*** 000537	8b 46 fa 		mov	ax,WORD PTR [bp-6]	;i
	*** 00053a	39 87 02 00 		cmp	WORD PTR _mappable_pages[bx+2],ax
	*** 00053e	75 e8 			jne	$FC208
;|***             break;
; Line 322
					$FB209:
;|***       }
;|***       if (j == MAX_PHYS_PAGES)
; Line 324
	*** 000540	83 7e f8 28 		cmp	WORD PTR [bp-8],40	;j
	*** 000544	75 06 			jne	$I211
;|***          FatalError(); /* invalid Phy page # - doesn't exist in mappable_pages[] */
; Line 325
	*** 000546	e8 00 00 		call	_FatalError
;|***       else
; Line 326
	*** 000549	eb 1d 			jmp	SHORT $I212
	*** 00054b	90 			nop	
					$I211:
;|***          DMALinAdr = ((long )mappable_pages[j].page_seg) << 4;
; Line 327
	*** 00054c	8b 5e f8 		mov	bx,WORD PTR [bp-8]	;j
	*** 00054f	c1 e3 02 		shl	bx,2
	*** 000552	8b 87 00 00 		mov	ax,WORD PTR _mappable_pages[bx]
	*** 000556	2b d2 			sub	dx,dx
	*** 000558	b1 04 			mov	cl,4
					$L20038:
	*** 00055a	d1 e0 			shl	ax,1
	*** 00055c	d1 d2 			rcl	dx,1
	*** 00055e	fe c9 			dec	cl
	*** 000560	75 f8 			jne	$L20038
	*** 000562	89 46 f0 		mov	WORD PTR [bp-16],ax	;DMALinAdr
	*** 000565	89 56 f2 		mov	WORD PTR [bp-14],dx
					$I212:
;|***       
;|***       Exchange16K(LinAdr, DMALinAdr);
; Line 329
	*** 000568	ff 76 f2 		push	WORD PTR [bp-14]
	*** 00056b	ff 76 f0 		push	WORD PTR [bp-16]	;DMALinAdr
	*** 00056e	ff 76 06 		push	WORD PTR [bp+6]
	*** 000571	ff 76 04 		push	WORD PTR [bp+4]	;LinAdr
	*** 000574	e8 00 00 		call	_Exchange16K
	*** 000577	83 c4 08 		add	sp,8
;|***       ExchangePTEs(LinAdr, DMALinAdr);
; Line 330
	*** 00057a	ff 76 f2 		push	WORD PTR [bp-14]
	*** 00057d	ff 76 f0 		push	WORD PTR [bp-16]	;DMALinAdr
	*** 000580	ff 76 06 		push	WORD PTR [bp+6]
	*** 000583	ff 76 04 		push	WORD PTR [bp+4]	;LinAdr
	*** 000586	e8 00 00 		call	_ExchangePTEs
	*** 000589	83 c4 08 		add	sp,8
;|***    }
; Line 331
					$I206:
;|***    
;|*** /* UserPFTIndex is present in DMA_Pages[] we should exchange the entries in
;|***  * DMA_Pages[] */
;|***    for (i = 0; i < DMA_PAGE_COUNT; i++)   {
; Line 335
	*** 00058c	c7 46 fa 00 00 		mov	WORD PTR [bp-6],0	;i
	*** 000591	eb 04 			jmp	SHORT $F214
	*** 000593	90 			nop	
					$FC215:
	*** 000594	ff 46 fa 		inc	WORD PTR [bp-6]	;i
					$F214:
	*** 000597	a1 00 00 		mov	ax,_DMA_PAGE_COUNT
	*** 00059a	39 46 fa 		cmp	WORD PTR [bp-6],ax	;i
	*** 00059d	7d 1b 			jge	$FB216
;|***       if (DMA_Pages[i] == UserPFTIndex)   {
; Line 336
	*** 00059f	8b 76 fa 		mov	si,WORD PTR [bp-6]	;i
	*** 0005a2	d1 e6 			shl	si,1
	*** 0005a4	81 c6 00 00 		add	si,OFFSET _DMA_Pages
	*** 0005a8	8b 04 			mov	ax,WORD PTR [si]
	*** 0005aa	39 46 fe 		cmp	WORD PTR [bp-2],ax	;UserPFTIndex
	*** 0005ad	75 e5 			jne	$FC215
;|***          DMA_Pages[i] = DMA_Pages[k];
; Line 337
	*** 0005af	8b 5e 08 		mov	bx,WORD PTR [bp+8]	;k
	*** 0005b2	d1 e3 			shl	bx,1
	*** 0005b4	8b 87 00 00 		mov	ax,WORD PTR _DMA_Pages[bx]
	*** 0005b8	89 04 			mov	WORD PTR [si],ax
;|***          break;
; Line 338
					$FB216:
;|***       }
;|***    }
;|*** 
;|*** /* Now, DMA_Pages[k] has a different index into the pft386[] array */
;|***    DMA_Pages[k] = UserPFTIndex; 
; Line 343
	*** 0005ba	8b 5e 08 		mov	bx,WORD PTR [bp+8]	;k
	*** 0005bd	d1 e3 			shl	bx,1
	*** 0005bf	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;UserPFTIndex
	*** 0005c2	89 87 00 00 		mov	WORD PTR _DMA_Pages[bx],ax
;|*** }
; Line 344
	*** 0005c6	5e 			pop	si
	*** 0005c7	5f 			pop	di
	*** 0005c8	c9 			leave	
	*** 0005c9	c3 			ret	

_SwapAPage	ENDP
;|*** 
;|*** /* Update PT entry for LinAdr to map to pft386[UserPFTIndex] */
;|*** UpdateUserPTE(LinAdr, UserPFTIndex)
;|*** long LinAdr;
; Line 348
	PUBLIC	_UpdateUserPTE
_UpdateUserPTE	PROC NEAR
	*** 0005ca	c8 06 00 00 		enter	WORD PTR 6,0
	*** 0005ce	56 			push	si
;|*** unsigned UserPFTIndex;
;|*** {
; Line 350
;	LinAdr = 4
;	UserPFTIndex = 8
;	index = -2
;	pte = -6
;|*** unsigned index;
;|*** long pte;
;|*** 
;|***    index = INDEX(LinAdr);
; Line 354
	*** 0005cf	8b 46 04 		mov	ax,WORD PTR [bp+4]	;LinAdr
	*** 0005d2	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 0005d5	b1 0c 			mov	cl,12
					$L20040:
	*** 0005d7	d1 fa 			sar	dx,1
	*** 0005d9	d1 d8 			rcr	ax,1
	*** 0005db	fe c9 			dec	cl
	*** 0005dd	75 f8 			jne	$L20040
	*** 0005df	80 e4 03 		and	ah,3
	*** 0005e2	89 46 fe 		mov	WORD PTR [bp-2],ax	;index
;|*** 
;|***    pte = PFT(UserPFTIndex) & ~0xfff;   /* Pg Frame Adr in 20 MSBs */
; Line 356
	*** 0005e5	8b 5e 08 		mov	bx,WORD PTR [bp+8]	;UserPFTIndex
	*** 0005e8	c1 e3 02 		shl	bx,2
	*** 0005eb	8b 36 00 00 		mov	si,_pft386
	*** 0005ef	8b 00 			mov	ax,[bx][si]
	*** 0005f1	8b 50 02 		mov	dx,[bx+2][si]
	*** 0005f4	25 00 f0 		and	ax,-4096
	*** 0005f7	89 46 fa 		mov	WORD PTR [bp-6],ax	;pte
	*** 0005fa	89 56 fc 		mov	WORD PTR [bp-4],dx
;|*** 
;|***    SetPteFromIndex(index, pte);
; Line 358
	*** 0005fd	52 			push	dx
	*** 0005fe	50 			push	ax
	*** 0005ff	ff 76 fe 		push	WORD PTR [bp-2]	;index
	*** 000602	e8 00 00 		call	_SetPteFromIndex
	*** 000605	83 c4 06 		add	sp,6
;|***    SetPteFromIndex(index+1, pte+HEX4K);
; Line 359
	*** 000608	8b 46 fa 		mov	ax,WORD PTR [bp-6]	;pte
	*** 00060b	8b 56 fc 		mov	dx,WORD PTR [bp-4]
	*** 00060e	05 00 10 		add	ax,4096
	*** 000611	83 d2 00 		adc	dx,0
	*** 000614	52 			push	dx
	*** 000615	50 			push	ax
	*** 000616	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;index
	*** 000619	40 			inc	ax
	*** 00061a	50 			push	ax
	*** 00061b	e8 00 00 		call	_SetPteFromIndex
	*** 00061e	83 c4 06 		add	sp,6
;|***    SetPteFromIndex(index+2, pte+HEX4K*2);
; Line 360
	*** 000621	8b 46 fa 		mov	ax,WORD PTR [bp-6]	;pte
	*** 000624	8b 56 fc 		mov	dx,WORD PTR [bp-4]
	*** 000627	05 00 20 		add	ax,8192
	*** 00062a	83 d2 00 		adc	dx,0
	*** 00062d	52 			push	dx
	*** 00062e	50 			push	ax
	*** 00062f	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;index
	*** 000632	05 02 00 		add	ax,2
	*** 000635	50 			push	ax
	*** 000636	e8 00 00 		call	_SetPteFromIndex
	*** 000639	83 c4 06 		add	sp,6
;|***    SetPteFromIndex(index+3, pte+HEX4K*3);
; Line 361
	*** 00063c	8b 46 fa 		mov	ax,WORD PTR [bp-6]	;pte
	*** 00063f	8b 56 fc 		mov	dx,WORD PTR [bp-4]
	*** 000642	05 00 30 		add	ax,12288
	*** 000645	83 d2 00 		adc	dx,0
	*** 000648	52 			push	dx
	*** 000649	50 			push	ax
	*** 00064a	8b 46 fe 		mov	ax,WORD PTR [bp-2]	;index
	*** 00064d	05 03 00 		add	ax,3
	*** 000650	50 			push	ax
	*** 000651	e8 00 00 		call	_SetPteFromIndex
	*** 000654	83 c4 06 		add	sp,6
;|*** }
; Line 362
	*** 000657	5e 			pop	si
	*** 000658	c9 			leave	
	*** 000659	c3 			ret	

_UpdateUserPTE	ENDP
;|*** 
;|*** /* exchange 4 ptes at LinAdr1 and LinAdr2 */
;|*** ExchangePTEs(LinAdr1, LinAdr2)
;|*** long LinAdr1, LinAdr2;
; Line 366
	PUBLIC	_ExchangePTEs
_ExchangePTEs	PROC NEAR
	*** 00065a	c8 0a 00 00 		enter	WORD PTR 10,0
	*** 00065e	57 			push	di
	*** 00065f	56 			push	si
;|*** {
; Line 367
;	LinAdr1 = 4
;	LinAdr2 = 8
;	index1 = -4
;	index2 = -6
;	tPte = -10
;	i = -2
;|*** unsigned index1, index2;
;|*** long tPte;
;|*** int i;
;|*** 
;|***    index1 = INDEX(LinAdr1);
; Line 372
	*** 000660	8b 46 04 		mov	ax,WORD PTR [bp+4]	;LinAdr1
	*** 000663	8b 56 06 		mov	dx,WORD PTR [bp+6]
	*** 000666	b1 0c 			mov	cl,12
					$L20042:
	*** 000668	d1 fa 			sar	dx,1
	*** 00066a	d1 d8 			rcr	ax,1
	*** 00066c	fe c9 			dec	cl
	*** 00066e	75 f8 			jne	$L20042
	*** 000670	80 e4 03 		and	ah,3
	*** 000673	89 46 fc 		mov	WORD PTR [bp-4],ax	;index1
;|***    index2 = INDEX(LinAdr2);
; Line 373
	*** 000676	8b 46 08 		mov	ax,WORD PTR [bp+8]	;LinAdr2
	*** 000679	8b 56 0a 		mov	dx,WORD PTR [bp+10]
	*** 00067c	b1 0c 			mov	cl,12
					$L20044:
	*** 00067e	d1 fa 			sar	dx,1
	*** 000680	d1 d8 			rcr	ax,1
	*** 000682	fe c9 			dec	cl
	*** 000684	75 f8 			jne	$L20044
	*** 000686	80 e4 03 		and	ah,3
	*** 000689	89 46 fa 		mov	WORD PTR [bp-6],ax	;index2
;|***    
;|***    for (i = 0; i < 4; i++) {
; Line 375
	*** 00068c	c7 46 fe 00 00 		mov	WORD PTR [bp-2],0	;i
					$FC232:
;|***       tPte = PT(index1+i);
; Line 376
	*** 000691	8b 76 fe 		mov	si,WORD PTR [bp-2]	;i
	*** 000694	03 76 fc 		add	si,WORD PTR [bp-4]	;index1
	*** 000697	56 			push	si
	*** 000698	e8 00 00 		call	_GetPteFromIndex
	*** 00069b	83 c4 02 		add	sp,2
	*** 00069e	89 46 f6 		mov	WORD PTR [bp-10],ax	;tPte
	*** 0006a1	89 56 f8 		mov	WORD PTR [bp-8],dx
;|***       SetPteFromIndex(index1+i, PT(index2+i));
; Line 377
	*** 0006a4	8b 7e fe 		mov	di,WORD PTR [bp-2]	;i
	*** 0006a7	03 7e fa 		add	di,WORD PTR [bp-6]	;index2
	*** 0006aa	57 			push	di
	*** 0006ab	e8 00 00 		call	_GetPteFromIndex
	*** 0006ae	83 c4 02 		add	sp,2
	*** 0006b1	52 			push	dx
	*** 0006b2	50 			push	ax
	*** 0006b3	56 			push	si
	*** 0006b4	e8 00 00 		call	_SetPteFromIndex
	*** 0006b7	83 c4 06 		add	sp,6
;|***       SetPteFromIndex(index2+i, tPte);
; Line 378
	*** 0006ba	ff 76 f8 		push	WORD PTR [bp-8]
	*** 0006bd	ff 76 f6 		push	WORD PTR [bp-10]	;tPte
	*** 0006c0	57 			push	di
	*** 0006c1	e8 00 00 		call	_SetPteFromIndex
	*** 0006c4	83 c4 06 		add	sp,6
;|***    }
; Line 379
	*** 0006c7	ff 46 fe 		inc	WORD PTR [bp-2]	;i
	*** 0006ca	83 7e fe 04 		cmp	WORD PTR [bp-2],4	;i
	*** 0006ce	7c c1 			jl	$FC232
;|*** }
; Line 380
	*** 0006d0	5e 			pop	si
	*** 0006d1	5f 			pop	di
	*** 0006d2	c9 			leave	
	*** 0006d3	c3 			ret	

_ExchangePTEs	ENDP
;|*** 
;|*** /* sanity check on the index, and then call GetPte */
;|*** long GetPteFromIndex(index)
;|*** unsigned index;
; Line 384
	PUBLIC	_GetPteFromIndex
_GetPteFromIndex	PROC NEAR
	*** 0006d4	c8 06 00 00 		enter	WORD PTR 6,0
;|*** {
; Line 385
;	index = 4
;	i = -6
;	PhyAdr = -4
;|*** unsigned i;
;|*** long PhyAdr;
;|*** 
;|***    PhyAdr = ((long) index) << 12;
; Line 389
	*** 0006d8	8b 46 04 		mov	ax,WORD PTR [bp+4]	;index
	*** 0006db	2b d2 			sub	dx,dx
	*** 0006dd	b1 0c 			mov	cl,12
					$L20046:
	*** 0006df	d1 e0 			shl	ax,1
	*** 0006e1	d1 d2 			rcl	dx,1
	*** 0006e3	fe c9 			dec	cl
	*** 0006e5	75 f8 			jne	$L20046
	*** 0006e7	89 46 fc 		mov	WORD PTR [bp-4],ax	;PhyAdr
	*** 0006ea	89 56 fe 		mov	WORD PTR [bp-2],dx
;|***    
;|***    if (PhyAdr < HEX256K || PhyAdr >= HEX1MB)
; Line 391
	*** 0006ed	83 fa 04 		cmp	dx,4
	*** 0006f0	7c 05 			jl	$L20049
	*** 0006f2	83 fa 10 		cmp	dx,16
	*** 0006f5	7c 09 			jl	$I238
					$L20049:
;|***       return (PhyAdr);
; Line 392
	*** 0006f7	8b 46 fc 		mov	ax,WORD PTR [bp-4]	;PhyAdr
	*** 0006fa	8b 56 fe 		mov	dx,WORD PTR [bp-2]
	*** 0006fd	c9 			leave	
	*** 0006fe	c3 			ret	
	*** 0006ff	90 			nop	
					$I238:
	*** 000700	8b 5e fc 		mov	bx,WORD PTR [bp-4]	;PhyAdr
	*** 000703	8b 4e fe 		mov	cx,WORD PTR [bp-2]
	*** 000706	8b c1 			mov	ax,cx
	*** 000708	b1 0e 			mov	cl,14
					$L20052:
	*** 00070a	d1 f8 			sar	ax,1
	*** 00070c	d1 db 			rcr	bx,1
	*** 00070e	fe c9 			dec	cl
	*** 000710	75 f8 			jne	$L20052
	*** 000712	8a 87 f0 ff 		mov	al,BYTE PTR _EMM_MPindex[bx-16]
	*** 000716	98 			cbw	
	*** 000717	89 46 fa 		mov	WORD PTR [bp-6],ax	;i
;|***    
;|***    i = EMM_MPindex[DOSPHYPAGE(PhyAdr)];
;|*** 
;|***    if (i != -1)
; Line 396
	*** 00071a	3d ff ff 		cmp	ax,-1
	*** 00071d	74 d8 			je	$L20049
;|***       return GetPte(index);
; Line 397
	*** 00071f	ff 76 04 		push	WORD PTR [bp+4]	;index
	*** 000722	e8 00 00 		call	_GetPte
	*** 000725	c9 			leave	
	*** 000726	c3 			ret	
	*** 000727	90 			nop	

_GetPteFromIndex	ENDP
;|***    else  
;|***       return PhyAdr; 
;|*** }
;|*** 
;|*** /* sanity check on the index and then call SetPte */
;|*** SetPteFromIndex(index, pte)
;|*** unsigned index;
; Line 404
	PUBLIC	_SetPteFromIndex
_SetPteFromIndex	PROC NEAR
	*** 000728	c8 06 00 00 		enter	WORD PTR 6,0
;|*** long pte;
;|*** {
; Line 406
;	index = 4
;	pte = 6
;	i = -6
;	PhyAdr = -4
;|*** unsigned i;
;|*** long PhyAdr;
;|*** 
;|***    PhyAdr = ((long) index) << 12;
; Line 410
	*** 00072c	8b 46 04 		mov	ax,WORD PTR [bp+4]	;index
	*** 00072f	2b d2 			sub	dx,dx
	*** 000731	b1 0c 			mov	cl,12
					$L20054:
	*** 000733	d1 e0 			shl	ax,1
	*** 000735	d1 d2 			rcl	dx,1
	*** 000737	fe c9 			dec	cl
	*** 000739	75 f8 			jne	$L20054
	*** 00073b	89 46 fc 		mov	WORD PTR [bp-4],ax	;PhyAdr
	*** 00073e	89 56 fe 		mov	WORD PTR [bp-2],dx
;|***    
;|***    if (PhyAdr < HEX256K || PhyAdr >= HEX1MB)
; Line 412
	*** 000741	83 fa 04 		cmp	dx,4
	*** 000744	7c 2e 			jl	$EX244
	*** 000746	83 fa 10 		cmp	dx,16
	*** 000749	7d 29 			jge	$EX244
;|***       return;
; Line 413
	*** 00074b	8b d8 			mov	bx,ax
	*** 00074d	8b ca 			mov	cx,dx
	*** 00074f	8b c1 			mov	ax,cx
	*** 000751	b1 0e 			mov	cl,14
					$L20060:
	*** 000753	d1 f8 			sar	ax,1
	*** 000755	d1 db 			rcr	bx,1
	*** 000757	fe c9 			dec	cl
	*** 000759	75 f8 			jne	$L20060
	*** 00075b	8a 87 f0 ff 		mov	al,BYTE PTR _EMM_MPindex[bx-16]
	*** 00075f	98 			cbw	
	*** 000760	89 46 fa 		mov	WORD PTR [bp-6],ax	;i
;|***    
;|***    i = EMM_MPindex[DOSPHYPAGE(PhyAdr)];
;|*** 
;|***    if (i != -1)
; Line 417
	*** 000763	3d ff ff 		cmp	ax,-1
	*** 000766	74 0c 			je	$EX244
;|***       return SetPte(index, pte);
; Line 418
	*** 000768	ff 76 08 		push	WORD PTR [bp+8]
	*** 00076b	ff 76 06 		push	WORD PTR [bp+6]	;pte
	*** 00076e	ff 76 04 		push	WORD PTR [bp+4]	;index
	*** 000771	e8 00 00 		call	_SetPte
					$EX244:
	*** 000774	c9 			leave	
	*** 000775	c3 			ret	

_SetPteFromIndex	ENDP
_TEXT	ENDS
END
;|***    else  
;|***       return;
;|*** }
;|*** 
;|*** 
;|*** 
