3 ;******************************************************************************
4 title DMATRAP
.ASM
- Trap handlers for DMA ports
5 ;******************************************************************************
7 ; (C) Copyright MICROSOFT Corp. 1986
9 ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11 ; Module: DMATRAP.ASM - Trap Handlers for DMA ports
19 ;******************************************************************************
23 ; DATE REVISION DESCRIPTION
24 ; -------- -------- -------------------------------------------------------
26 ; 06/18/86 0.01 Modified LIM_Map to handle all 4 boards and call
27 ; page mapping routine in EMMLIB.LIB
28 ; 06/27/86 0.02 Made _page_frame_address indexing dword (was word)
30 ; 06/28/86 0.02 Name change from MEMM386 to MEMM
31 ; 07/01/86 0.03 Added DMA support routines
32 ; 07/02/86 0.03 Fixed CNT size vs. length problem
33 ; 07/06/86 0.04 Made _pft386 a ptr to _pft386 array
34 ; 07/06/86 0.04 now sets _window array also
35 ; 08/11/86 0.05 moved IO_Trap code for LIM DMA trapping here
36 ; 06/09/88 remove IOT_LIM, LIMMap, and InitELIM since we don't
37 ; have any EMM hardware to trap and emulate now (Paulch)
38 ; 07/26/88 reintroduced initelim removing iab port trap (ISP)
40 ; 07/27/88 Started rewriting the DMA port trap handlers - similar to the
41 ; code in VDMAD.ASM in Win/386 V2.03
42 ; - Jaywant H Bharadwaj
44 ;*****************************************************************************
47 ;******************************************************************************
49 ; Functional Description:
51 ; Monitors writes/reads to the DMA ports.
52 ; Reads are simple - return the value saved in DMARegSav structure.
53 ; On a write to Page/Base/count Reg port -
54 ; user specifies a linear address. DMAs can handle only physical addresses.
55 ; Therefore, the actual physical address has to be written into the Page and
56 ; base Address Reg. Also the DMA transfer area may not be physically contiguous.
57 ; If it isn't we should remap the linear address so that it is physically
60 ; We never know when a DMA is started. Hence on every access to the Page/Base
61 ; or count Register we make sure that the linear address specified by the user
62 ; maps to a physical address which is contiguous over the DMA transfer area.
63 ; This has to be done even if the count register is altered since the user
64 ; might be relying on the previous contents of Page/Addr Regs which may not be
67 ; All routines except InitDMA are entered through protected mode only.
69 ;******************************************************************************
71 .lfcond
; list false conditionals
75 ;******************************************************************************
76 ; P U B L I C D E C L A R A T I O N S
77 ;******************************************************************************
80 ; routines called from C
89 public InitELIM
; initialization routine for LIMulator
90 public InitDMA
; init DMA register save area
94 public _DMA_PAGE_COUNT
129 ;******************************************************************************
130 ; L O C A L C O N S T A N T S
131 ;******************************************************************************
144 ;******************************************************************************
146 ; Get_FRS_window - get pointer to Fast Register Set window
148 ; ENTRY: Reg - points to an FRS_struc
150 ; EXIT: Reg - points to FRS_window entry in the structure
154 ;******************************************************************************
155 Get_FRS_window
MACRO Reg
157 mov Reg
, word ptr [CurRegSet
] ; just offset (assume dgroup)
158 add Reg
, FRS_window
; points to FRS window entries
161 ;****************************************************************************
163 ; InitDMARegSav - MACRO for initialising save area for channels
165 ; ENTRY: chan_num = channel number (1,2,3,5,6,7)
168 ;-----------------------------------------------------------------------------
170 InitDMARegSav
MACRO chan_num
172 lea di,[DMARegSav
.Chnl
&chan_num
] ; pt to channel's save area
175 in al,DMA_P
&chan_num
; page register for channel
178 shl eax,16 ; high EAX = high word of linear addr
180 ; flip-flop already reset by the caller
182 in al,DMA_B
&chan_num
; get low byte of base
186 in al,DMA_B
&chan_num
; get high byte of base
188 ; EAX = LINEAR BASE address
190 stosd ; store LINEAR BASE address
192 stosd ; store PHYSICAL BASE address
194 xor eax, eax ; clear EAX
197 in al,DMA_C
&chan_num
; get low byte of count
201 in al,DMA_C
&chan_num
; get high byte of count
207 add di, 4 ; skip 4 bytes - 3 ports+mode byte
212 ;******************************************************************************
213 ; DMA_WADDR_TO_BADDR - convert internal DMA word address to a byte address
215 ; ENTRY: 386 PROTECTED MODE
220 ; EXIT: EAX - Byte address
223 ;------------------------------------------------------------------------------
224 DMA_WADDR_TO_BADDR
MACRO
227 cmp [ROM_BIOS_Machine_ID
], RBMI_Sys80
228 jbe short Not_AT
; If running on EBIOS machine
230 ror eax,16 ; AX = high word
231 shr al,1 ; adjust for D0 null in page reg
232 rol eax,17 ; EAX = address w/ adjust for
235 shl ecx, 1 ; Adjust for word units
239 ;******************************************************************************
240 ; DMA_BADDR_TO_WADDR - convert internal DMA byte address to a word address
242 ; ENTRY: 386 PROTECTED MODE
247 ; EXIT: EAX - Byte address
250 ;------------------------------------------------------------------------------
251 DMA_BADDR_TO_WADDR
MACRO
254 cmp [ROM_BIOS_Machine_ID
], RBMI_Sys80
255 jbe short Not_AT
; If running on EBIOS machine
257 shr eax, 1 ; Adjust for implied 'A0'
258 push ax ; Save A16-A1
260 shl eax, 1 ; Adjust for unused Pg Reg D0
261 pop ax ; Restore A16-A1
265 ;******************************************************************************
266 ; E X T E R N A L R E F E R E N C E S
267 ;******************************************************************************
270 extrn ROM_BIOS_Machine_ID
:byte
271 extrn _page_frame_base
:word
279 extrn PortTrap
:near ; set port bit in I/O bit Map
283 ; Swap pages so that DMA Xfer area is physically contiguous.
284 ; defined in mapdma.c
286 extrn _SwapDMAPages
:near
290 ;******************************************************************************
291 ; S E G M E N T D E F I N I T I O N
292 ;******************************************************************************
296 DMARegSav DMARegBuf
<> ; DMA Register buffer
299 ; dw DMA_P0 ; DMA page registers
307 ; dw DMA_P0+10h ; page regs mapped to here also
316 ; dw DMA_B0 ; DMA base registers
323 DMAP_Count
label word
324 ; dw DMA_C0 ; DMA count registers
331 dw DMA1_CLR_FF
; reset flip-flop commands
337 LIMDMAP_CNT
= ($ - DMAP_Page
) / 2
339 ; DMA_Pages - EMM Pages for DMA relocation. Each is an index into pft386.
340 ; To access actual entry in pft386 you need to multiply index by 4.
341 ; If eight contingous 16k EMM pages are not available - the unavailable
342 ; entries are left at NULL_PAGE.
343 ; This array should be initialized at boot time.
345 _DMA_Pages
LABEL WORD
346 DMA_Pages dw 8 dup (NULL_PAGE
) ; null for start
347 _DMA_PAGE_COUNT
LABEL WORD
348 DMA_PAGE_COUNT dw 0 ; number of above initialised
355 ;------------------------------------------------------------------------------
358 assume
cs:_TEXT
, ds:DGROUP
, es:DGROUP
, ss:DGROUP
360 ;******************************************************************************
362 ; InitDMA - initialize internal values for DMA registers of each channel
368 ; DGROUP:[DMARegSav] = DMA register save area initialized
370 ;------------------------------------------------------------------------------
386 out DMA1_CLR_FF
, al ; clear FF on first controller
387 mov [DMARegSav
.DMAFF1
], al ; reset S/W FF
391 ; initialize regs for channels 1,2,3
398 out DMA2_CLR_FF
, al ; clear FF on second controller
399 mov [DMARegSav
.DMAFF2
], al ; reset S/W FF
403 ; initialize regs for channels 5,6,7
417 ;******************************************************************************
419 ; DMABase(0-7) - Write/Read DMA Channel N Base Register
422 ; AL = byte to output to port
424 ; DH = 0 => Emulate Input
425 ; <>0 => Emulate Output
428 ; AL = emulated input/output value from port.
429 ; CLC => I/O emulated or performed
431 ;------------------------------------------------------------------------------
432 DMABase0to7 proc
near
434 DMABase4: ; I/O port C0h
435 DMABase5: ; I/O port C4h
436 DMABase6: ; I/O port C8h
437 DMABase7: ; I/O port CCh
444 ; Now, BX = port * 2 and DX = IO code
445 ; Code ported from Win/386 expects DX = port and BH = IO code
449 xchg bh,bl ; move IO code to bh
452 sub si, 0B0h ; SI = Channel * 4
453 shl si, 2 ; SI = Channel * 16
454 mov bl, [DMARegSav
.DMAFF2
] ; get flip-flop
455 xor [DMARegSav
.DMAFF2
], 1 ; and toggle it
458 DMABase0: ; I/O port 00h
459 DMABase1: ; I/O port 02h
460 DMABase2: ; I/O port 04h
461 DMABase3: ; I/O port 06h
468 ; Now, BX = port * 2 and DX = IO code
469 ; Code ported from Win/386 expects DX = port and BH = IO code
473 xchg bh,bl ; move IO code to bh
475 mov si, dx ; SI = Channel * 2
476 shl si, 3 ; SI = Channel * 16
477 mov bl, [DMARegSav
.DMAFF1
] ; get flip-flop
478 xor [DMARegSav
.DMAFF1
], 1 ; and toggle it
484 ;******************************************************************************
486 ; DMABaseN - Write/Read DMA Channel N Base Register
488 ; ENTRY: As above plus
489 ; SI = 16 * channel #
491 ;------------------------------------------------------------------------------
493 and bl, 1 ; Look at bit0 only - safety
496 jz short Base_rd_port
; Y: do Read operation
497 ; N: save value "written"
498 mov [SaveAL
], al ; save AL in Save area.
499 xor bh, bh ; Make BX = Flip Flop state
500 mov byte ptr DMARegSav
.DMALinAdr
[bx][si], al
502 in al, dx ; Just a Dummy I/O to
503 ; toggle the real flip-flop
504 ; to match DMAFF above
507 xor bl,1 ; and the s/w one
509 call DMA_DMAFixup
; Translate Lin to Phys
511 call DMA_WrtAdrReg
; emulate the write
515 in al, dx ; Toggle the real flop-flip
517 ; bh is already zero, therefore BX = flip flop state
519 mov al,byte ptr DMARegSav
.DMALinAdr
[bx][si]
535 ;******************************************************************************
537 ; DMACnt(0-7) - Write/Read DMA Channel N Count Register
540 ; AL = byte to output to port.
542 ; DH = 0 => Emulate Input.
543 ; <>0 => Emulate Output.
546 ; AL = emulated input/output value from port.
547 ; CLC => I/O emulated or performed
549 ;------------------------------------------------------------------------------
553 DMACnt4: ; I/O port C2h
554 DMACnt5: ; I/O port C6h
555 DMACnt6: ; I/O port CAh
556 DMACnt7: ; I/O port CEh
563 ; Now, BX = port * 2 and DX = IO code
564 ; Code ported from Win/386 expects DX = port and BH = IO code
568 xchg bh,bl ; move IO code to bh
571 sub si, 0B2h ; SI = 4 * channel #
572 shl si, 2 ; si = 16 * channel #
573 mov bl, [DMARegSav
.DMAFF2
] ; get flip-flop
574 xor [DMARegSav
.DMAFF2
], 1 ; toggle our flip-flop
577 DMACnt0: ; I/O port 01h
578 DMACnt1: ; I/O port 03h
579 DMACnt2: ; I/O port 05h
580 DMACnt3: ; I/O port 07h
587 ; Now, BX = port * 2 and DX = IO code
588 ; Code ported from Win/386 expects DX = port and BH = IO code
592 xchg bh,bl ; move IO code to bh
596 shl si, 3 ; si = 16 * channel #
597 mov bl, [DMARegSav
.DMAFF1
] ; get flip-flop
598 xor [DMARegSav
.DMAFF1
], 1 ; toggle our flip-flop
603 ;******************************************************************************
605 ; DMACntN - Write/Read DMA Channel N Count Register
607 ; ENTRY: As DMACnt1to7 plus
608 ; si = 16 * channel #
610 ;------------------------------------------------------------------------------
612 and bl, 1 ; Look at bit0 only - Safety
615 jz short DMA_CntN_rd
; Y: do Read operation
616 ; N: save value "written"
617 mov [SaveAL
], al ; save AL in Save area.
618 xor bh, bh ; make BX = Flip Flop state
619 mov byte ptr DMARegSav
.DMACount
[bx][si], al ; save cnt
620 out dx, al ; do the I/O
622 xor bl,1 ; Toggle flip-flop for Wrt
623 call DMA_DMAFixup
; Translate Lin to Phys
625 call DMA_WrtAdrReg
; emulate the write
630 xor bh,bh ; make BX = Flip Flop state
631 in al, dx ; Toggle the real flip-flop
637 xor bl,1 ; and the s/w one
639 ; get current count values from cntlr
641 in al, dx ; get 2nd byte of Count reg
644 mov byte ptr DMARegSav
.DMACount
[bx][si], al ; save it
645 xor bl, 1 ; flip to other byte
646 in al, dx ; get 1st byte of Count reg
647 mov byte ptr DMARegSav
.DMACount
[bx][si], al ; save it
656 clc ; I/O emulated, return
662 ;******************************************************************************
664 ; DMAPgN - Write/Read DMA Channel N Page Register
667 ; AL = byte to output to port
669 ; DX = 0 => Emulate Input
670 ; <>0 => Emulate Output
674 ; AL = emulated input/output value from port.
675 ; CLC => I/O emulated or performed
680 ; NOTES: For channels 0-4, DMACount is in Bytes, and
681 ; DMALinAdr holds the address as:
683 ; +-----------+-----------+----------------------+
684 ; | 31-24 | 23-16 | 15-0 |
685 ; +-----------+-----------+----------------------+
686 ; | 0000 0000 | A23-A16 | A15-A0 |
687 ; +-----------+-----------+----------------------+
689 ; For channels 5-7, DMACount is in Words, and
690 ; DMALinAdr holds the address as:
692 ; +-----------+-----------+----------------------+
693 ; | 31-24 |23-17 | 16 | 15-0 |
694 ; +-----------+-----------+----------------------+
695 ; | 0000 0000 |A23-A17 |0 | A16-A1 |
696 ; +-----------+-----------+----------------------+
699 ;------------------------------------------------------------------------------
704 mov si,0*16 ; si = 16 * channel #
708 mov si,1*16 ; si = 16 * channel #
712 mov si,2*16 ; si = 16 * channel #
716 mov si,3*16 ; si = 16 * channel #
720 mov si,5*16 ; si = 16 * channel #
724 mov si,6*16 ; si = 16 * channel #
728 mov si,7*16 ; si = 16 * channel #
731 ;----------------------------------------------------------------------
732 ; DMAPgN - Common Page Code
734 ; ENTRY: As above plus
735 ; si = 16 * Channel #
737 ;----------------------------------------------------------------------
745 ; Now, BX = port * 2 and DX = IO code
746 ; Code ported from Win/386 expects DX = port and BH = IO code
750 xchg bh,bl ; move IO code to bh
753 jz short Pg_rd_port
; Y: do Read operation
755 mov [SaveAL
], al ; save AL in Save area.
757 ; Get s/w FF for WrtAdrReg
759 mov bl, [DMARegSav
.DMAFF1
] ; Assume Chan 1 FF
760 cmp si, 4*16 ; Q: Addr for 2nd controller
761 jb short PgN_FF
; A: No, FF is correct
762 mov bl, [DMARegSav
.DMAFF2
] ; Chan 2 FF
764 xor bh, bh ; make BX = flip-flop state
766 mov byte ptr DMARegSav
.DMALinAdr
.HighWord
[si], al ; save value
767 call DMA_DMAFixup
; Translate Lin to Phys
769 call DMA_WrtAdrReg
; emulate the write
772 mov al, byte ptr DMARegSav
.DMALinAdr
.HighWord
[si]
788 ;******************************************************************************
790 ; DMAClrFF1 - Reset Controller 1's FlipFlop
791 ; DMAClrFF2 - Reset Controller 2's FlipFlop
794 ; AL = byte to output to port.
796 ; DH = 0 => Emulate Input.
797 ; <>0 => Emulate Output.
800 ; AL = emulated input/output value from port.
801 ; CLC => I/O emulated or performed
803 ;------------------------------------------------------------------------------
811 ; Now, BX = port * 2 and DX = IO code
812 ; Code ported from Win/386 expects DX = port and BH = IO code
816 xchg bh,bl ; move IO code to bh
819 jz short DMA_CLF_RdEm
; Y: Let it go
820 out dx, al ; N: do it
821 mov [DMARegSav
.DMAFF1
], 0
824 in al,dx ; do the read
842 ; Now, BX = port * 2 and DX = IO code
843 ; Code ported from Win/386 expects DX = port and BH = IO code
847 xchg bh,bl ; move IO code to bh
850 jz DMA_CLF_RdEm
; Y: Let it go
851 out dx, al ; N: do it
852 mov [DMARegSav
.DMAFF2
], 0
858 ;******************************************************************************
860 ; DMAMode1 - Track Controller 1's Mode Register
861 ; DMAMode2 - Track Controller 2's Mode Register
864 ; AL = byte to output to port.
866 ; DX = 0 => Emulate Input.
867 ; <>0 => Emulate Output.
870 ; AL = emulated input/output value from port.
871 ; CLC => I/O emulated or performed
873 ;------------------------------------------------------------------------------
882 ; Now, BX = port * 2 and DX = IO code
883 ; Code ported from Win/386 expects DX = port and BH = IO code
887 xchg bh,bl ; move IO code to bh
890 jz short DMA_Mread
; Y: Let it go
892 mov [SaveAL
], al ; save AL in Save area.
895 and si, DMA_M_CHANNEL
897 and bl, NOT DMA_M_16BIT
; 8 bit xfers for controller 1
899 shl si, 4 ; Channel * 16
900 mov [DMARegSav
.DMAMode
][si], bl
901 out dx, al ; N: do it
905 in al, dx ; do the read
926 ; Now, BX = port * 2 and DX = IO code
927 ; Code ported from Win/386 expects DX = port and BH = IO code
931 xchg bh,bl ; move IO code to bh
934 jz DMA_Mread
; Y: Let it go
936 mov [SaveAL
], al ; save AL in Save area.
939 and si, DMA_M_CHANNEL
940 add si, 4 ; Channel 4 to 7
942 or bl, DMA_M_16BIT
; 16 bit for controller 2
950 ;******************************************************************************
951 ;DMA_GetLinAdr - return Linear Address, count and mode from DMARegSave area
954 ; si = channel # * 16
958 ; EAX = linear Base Address
959 ; ECX = SIZE of transfer (bytes)
964 ;------------------------------------------------------------------------------
965 DMA_GetLinAdr proc
near
967 mov eax, dword ptr DMARegSav
.DMALinAdr
[si]
968 mov ecx, dword ptr DMARegSav
.DMACount
[si]
969 mov dl, byte ptr DMARegSav
.DMAMode
[si]
970 inc ecx ; ECX = SIZE of transfer
971 test dl, DMA_M_16BIT
; Word transfer?
972 jz short GLexit
; N: no special treatment
974 DMA_WADDR_TO_BADDR
; Y: fixup values from regs
981 ;******************************************************************************
982 ; DMA_SetPhyAdr - Load the Page and Base DMA registers with the input
983 ; Physical Address and save this addr as current phy addr.
986 ; EAX = physical address
987 ; SI = DMA channel # * 16
991 ;------------------------------------------------------------------------------
992 DMA_SetPhyAdr proc
near
999 mov bl, [DMARegSav
.DMAFF1
]
1000 cmp si,4*16 ; 2nd cntlr?
1002 mov bl, [DMARegSav
.DMAFF2
] ; yes, other flip-flop
1004 test [DMARegSav
.DMAMode
][si], DMA_M_16BIT
; word transfer?
1005 jz short SaveIt
; no, no translation
1008 mov dword ptr DMARegSav
.DMAPhyAdr
[si], eax
1012 mov dl, byte ptr DMARegSav
.DMAPagePort
[si]
1013 mov al, byte ptr DMARegSav
.DMAPhyAdr
.HighWord
[si]
1016 ; set base address register
1017 mov dl, byte ptr DMARegSav
.DMABasePort
[si]
1018 mov al, byte ptr DMARegSav
.DMAPhyAdr
[si][bx]
1019 out dx,al ; send out 1st byte
1020 xor bl,1 ; toggle FF
1023 mov al, byte ptr DMARegSav
.DMAPhyAdr
[si][bx]
1024 out dx,al ; send out other byte
1025 xor bl,1 ; toggle FF to original state
1035 ;******************************************************************************
1036 ; DMALoadCount - Load the Count DMA register with the input
1039 ; si = DMA channel # * 16
1041 ;------------------------------------------------------------------------------
1042 DMALoadCount proc
near
1048 mov bl, byte ptr [DMARegSav
.DMAFF1
]
1049 cmp si,4*16 ;Q: Adrs from 2nd cntlr
1050 jb short DMA_SC1
; N: save it as is
1051 mov bl, byte ptr [DMARegSav
.DMAFF2
]
1054 mov dl, byte ptr DMARegSav
.DMACntPort
[si]
1056 mov al, byte ptr DMARegSav
.DMACount
[bx][si]
1061 mov al, byte ptr DMARegSav
.DMACount
[bx][si]
1072 ;******************************************************************************
1073 ; DMA_DMAFixup - Fixup Linear to Physical mapping for DMA
1076 ; SI = 16 * channel #
1080 ; DMARegSav is updated
1082 ; USED: flags, registers (calls a C program, so most registers are trashed)
1084 ; Check to see if DMA Page fixup is needed.
1085 ; We test for the following cases for optimization:
1086 ; Lin Base Add == Lin Page Reg == 0, assume that transfer addr
1089 ;------------------------------------------------------------------------------
1090 DMA_DMAFixup proc
near
1093 mov eax, dword ptr DMARegSav
.DMALinAdr
[si]
1095 jz short DMA_nofixup
; Y:DMA not programmed yet
1097 pushfd ; ENABLE INTERRUPTS!
1098 push bx ; C code trashes these regs
1101 ; long SwapDMAPages(LinAdr, Len, XferSize);
1103 ; unsigned XferSize; 0/1 Byte/word Xfer
1105 movzx eax, [DMARegSav
.DMAMode
][si]
1106 and al, DMA_M_16BIT
; Non-zero for 16bit transfer
1107 push ax ; push XferSize
1110 push ecx ; push count
1111 push eax ; push LinAdr
1113 ; C code saves di si bp ds ss sp
1115 call _SwapDMAPages
; C program to do the dirty work
1119 mov ax, dx ; eax = returned value
1121 add sp, 10 ; clean up stack
1125 popfd ; Restore original FLAGS state
1127 test [DMARegSav
.DMAMode
][si], DMA_M_16BIT
; word transfer?
1128 jz short SavIt
; no, no translation
1129 DMA_BADDR_TO_WADDR
; Y: Put in special format
1131 mov dword ptr DMARegSav
.DMAPhyAdr
[si], eax
1141 ;******************************************************************************
1142 ; DMA_WrtAdrReg - Write registers associated with DMA address
1145 ; BX = Flip Flop State, 0 or 1
1146 ; SI = channel # * 16
1148 ; Uses Values in DMARegSav
1154 ;------------------------------------------------------------------------------
1155 DMA_WrtAdrReg proc
near
1157 ; Must Update Page and Base registers simultaneously when remapping occurs...
1161 and bx, 1 ; Lose extra bit just in case...
1163 xor dh, dh ; clear high byte
1165 ; NOTE: Internal flip-
1166 ; flop flag not updated,
1167 ; since we write twice....
1168 ; BX = flip flop state
1170 mov dl, byte ptr DMARegSav
.DMABasePort
[si]
1171 mov al, byte ptr DMARegSav
.DMAPhyAdr
[bx][si]
1172 out dx, al ; output the byte
1175 xor bx, 1 ; toggle flip-flop
1177 mov al, byte ptr DMARegSav
.DMAPhyAdr
[bx][si]
1178 out dx, al ; output the byte
1181 xor bx, 1 ; toggle flip-flop
1184 mov al, byte ptr DMARegSav
.DMAPhyAdr
.HighWord
[si] ; fetch value
1185 mov dl, byte ptr DMARegSav
.DMAPagePort
[si]
1186 out dx,al ; output the byte
1195 ;******************************************************************************
1196 ; InitELIM - initialize LIM h/w trapping data structures and
1197 ; I/O bit map for this ports.
1199 ; NOTE: this is a FAR routine
1204 ; TSS:[IOBitMap] - LIM addresses entered in I/O bit map
1208 ;------------------------------------------------------------------------------
1224 ; now set entries in I/O Bit Map
1227 mov es,ax ; ES -> TSS
1229 ; now set DMA ports in I/O Bit Map
1232 mov si,offset DGROUP
:DMAP_Page
; DS:SI -> DMA ports
1233 mov bx,8000h
; trap it every 1k
1235 lodsw ; AX = port to trap
1236 call PortTrap
; set bit(s) for this port
1237 loop IE_maploop
;if more ...
1252 ; C callable routines for manipulating page table entries.
1253 ; and Current FRS - CurRegSet
1257 ; Equates for picking up arguments passed in from C code.
1259 ; Arg2 - word or dword Arg
1266 ;*****************************************************************************
1268 ; _GetPte - called from C code
1270 ; return pte in dx:ax
1272 ; long GetPte(PTIndex)
1275 ; Written: JHB Aug 10,1988
1276 ; Modif: ISP Aug 12,1988 parameter should be returned in dx:ax not eax
1277 ; removed some of pushes and pops
1278 ; added cld before load just to be safe
1279 ; offset specified in DGROUP
1281 ; JHB Aug 21 88 changed input param to PTIndex
1283 ;*****************************************************************************
1295 mov si, WORD PTR Arg1
1296 shl si, 2 ; dword entries in the PT
1299 lodsw ; get low word
1300 mov dx, ax ; into dx
1302 xchg dx, ax ; dx:ax = long return value
1310 ;*****************************************************************************
1312 ; _SetPte - called from C code
1314 ; Locate the PT entry for given EmmPhyPage and set it to pte.
1316 ; SetPte(PTIndex, pte)
1320 ; WRITTEN: JHB Aug 10,1988
1321 ; MODIF: ISP Aug 12,1988 pushes and pops removed
1322 ; cld added for safety
1323 ; offset specified in DGROUP
1324 ; pushed poped eax (check on this)
1326 ; JHB Aug 21, 1988 changed first input param to PTIndex
1328 ;*****************************************************************************
1340 mov di, WORD PTR Arg1
1343 mov eax, DWORD PTR Arg2
1344 and ax, 0F000H ; clear low 12 bits
1345 or ax, P_AVAIL
; page control bits - user, present, write
1350 ; reload CR3 to flush TLB
1355 ; mov eax,dword ptr [Page_Dir] ; mov EAX,dword ptr [Page_Dir]
1356 ; db 0Fh,22h,18h ; mov CR3,EAX
1364 ;*****************************************************************************
1366 ; _GetCRSEntry - called from C code
1368 ; return the Emm page mapped to the EmmPhyPage by looking up CurRegSet.
1370 ; unsigned GetCRSEntry(EmmPhyPage)
1371 ; unsigned EmmPhyPage
1373 ; WRITTEN: JHB Aug 10,1988
1374 ; MODIF: ISP Aug 12,1988 pushes and pops removed
1375 ; Offset specified in DGROUP
1376 ; cld added for safety
1377 ;*****************************************************************************
1379 _GetCRSEntry proc
near
1385 mov bx, WORD PTR Arg1
1386 shl bx, 1 ; each FRS entry is a word
1387 Get_FRS_Window
DI ; di = address of Current FRS
1389 mov ax, word ptr [di] ; load FRS entry
1397 ; Equates for picking up long Arguments from C code
1399 ; Larg2 - long Arg when the first Arg is also long
1405 ;*****************************************************************************
1407 ; _GetDMALinAdr - called from C code
1409 ; returns the Lin Adr for the DMA buffer whose physical adr is given
1411 ; long GetDMALinAdr(DMAPhyAdr)
1414 ; Get the Linear address for DMAPhyAdr. There is a pte which always
1415 ; maps to this always. MapLinear translates DMAPhyAdr to a linear adr.
1418 ; 8/12/88 JHB removed _Copy16K, changed it to this routine.
1420 ;*****************************************************************************
1422 _GetDMALinAdr proc
near
1430 ; convert the DMAPhyAdr into a linear address.
1432 mov eax, dword ptr LArg1
1435 ; eax = 32 bit linear adr for the DMA Xfer area.
1439 ror eax, 16 ; dx:ax 32 bit linear adr to be returned
1448 ;******************************************************************************
1450 ; set_selector - set up a selector address/attrib
1452 ; ENTRY: EAX = address for GDT selector - a linear address
1454 ; EXIT: selector in DI is writeable data segment,128k long and points
1455 ; to desired address.
1457 ;******************************************************************************
1459 set_selector proc
near
1465 and di,NOT 07h ; just in case... GDT entry
1467 pop es ; ES:DI -> selector entry
1469 mov es:[di+2],ax ; low word of base address
1471 shr eax,16 ; AX = high word of address
1472 mov es:[di+4],al ; low byte of high word of address
1473 xor al,al ; clear limit/G bit
1474 or al, 1 ; set LSB0 i.e. Limit16 bit for 128K Xfer
1475 mov es:[di+6],ax ; set high byte of high word of addr
1476 ; and high nibble of limit/G bit
1477 ; and Limit Bit 16 for 128K transfer
1479 mov es:[di],ax ; set limit bits 0-15
1481 mov al,D_DATA0
; writeable DATA seg / ring 0
1492 ;****************************************************************************
1493 ; _Exchange16K - called from C
1495 ; Exchange contents of the pages at LinAdr1 and LinAdr2
1497 ; Exchange16K(LinAdr1, LinAdr2)
1498 ; long LinAdr1, LinAdr2;
1500 ; Written: JHB Aug 11, 1988
1501 ; ISP Aug 12, 1988 Added cld.
1502 ; DWORD PTR mentioned explicitly
1503 ;*****************************************************************************
1505 _Exchange16K proc
near
1513 mov di,MBSRC_GSEL
; source selector
1514 mov eax,dword ptr LArg1
; load linear adr
1515 call set_selector
; set up a selector in GDT
1518 mov di,MBTAR_GSEL
; destination selector
1519 mov eax,dword ptr LArg2
1520 call set_selector
; set up selector
1522 mov cx,1000h
; 16k bytes (4 at a time)
1523 xor di,di ; initialize index
1526 mov eax,dword ptr es:[di] ; pick a dword at LArg1
1527 xchg eax,dword ptr ds:[di] ; swap with dword at LArg2
1528 stosd ; store new dword at LArg1
1540 ; signals an exception error
1542 _FatalError proc
near
1556 _TEXT ends
; end of segment