]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/MEMM/MOVEB.ASM
4 ;******************************************************************************
5 title MOVEB
- move block emulator
6 ;******************************************************************************
8 ; (C) Copyright MICROSOFT Corp. 1986
10 ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
12 ; Module: MOVEB - move block code for MEMM
20 ;*************************************************************************
22 ; DATE VERSION Description
23 ;--------- -------- --------------------------------------------------
24 ; 05/15/86 Check source/target selector using verr,verw
25 ; and add parity handler
26 ; 06/09/86 Added MapLinear call
27 ; 06/17/86 Added code to detect and "handle" writes to
29 ; 06/28/86 0.02 Name changed from MEMM386 to MEMM
30 ; 07/06/86 0.04 DiagByte moved to _DATA
31 ; 07/06/86 0.04 changed assume to DGROUP
32 ; 07/10/86 0.05 Added Real Mode patch code
33 ;*************************************************************************
37 ;****************************************
39 ;****************************************
48 ;****************************************
50 ;****************************************
61 D_G_BIT equ 80h
; granularity bit in high status bits
67 ; 386 data descriptor format
69 DD386_Limit_lo dw ?
; low word of seg limit
70 DD386_Base_lo dw ?
; low 24 bits of seg base addr
72 DD386_Access db ?
; access byte
73 DD386_L_Stat db ?
; high 4 bits of seg limit
75 DD386_Base_hi db ?
; high 8 bits of seg base addr
78 ; format of move block descriptor table passed on entry
80 MG_dummy dd 2 dup (?
) ; dummy descriptor entry
81 MG_GDT dd 2 dup (?
) ; GDT entry
82 MG_Source dd 2 dup (?
) ; source segment entry
83 MG_Target dd 2 dup (?
) ; target segment entry
86 ;************************************************************
87 ; DescrMap - map address in descriptor
88 ; ENTRY: ES:DI = descriptor
89 ; EXIT: descriptor's address is mapped by MapLinear
91 ;************************************************************
93 mov ah,ES:[di.DD386_Base_hi
] ; ah = high 8 bits of address
94 mov al,byte ptr ES:[di.DD386_Base_lo
+2] ; al = bits 16-23 of addr
96 shl ax,16 ; high addr word into high EAX
97 mov ax,ES:[di.DD386_Base_lo
] ; EAX = 32 bit address
98 call MapLinear
; map linear address
99 mov ES:[di.DD386_Base_lo
],ax ; store low word of address
101 shr ax,16 ; ax = high word of address
102 mov byte ptr ES:[di.DD386_Base_lo
+2],al ; store
103 mov ES:[di.DD386_Base_hi
],ah ; high word of address
106 ;*******************************************************************************
107 ; E X T E R N A L R E F E R E N C E S
108 ;*******************************************************************************
112 extrn Set_Par_Vect
:near
113 extrn Rest_Par_Vect
:near
115 extrn get_a20_state
:near
121 extrn Active_Status
:byte ; non-zero if in VM
127 ;*******************************************************************************
128 ; D A T A S E G M E N T
129 ;*******************************************************************************
132 MB_Stat db 0 ; move block status
138 ;****************************************
139 ; C O D E S E G M E N T _TEXT
140 ;****************************************
142 assume
cs:_TEXT
, ds:DGROUP
, es:DGROUP
145 ;*************************************************************************
146 ;*** Move_Block - Mimics the 286 ROM function Move Block ( int15h AH=87h ).
147 ; Move a block of data (copy it) to/from anywhere in
148 ; 24bits of linear address space. Normally used to move
149 ; data to/from extended memory (past 1M) since real mode
150 ; can only address the first meg of memory.
153 ; ENTRY PROTECTED MODE
155 ; CX = # of words to move ( max 8000h ).
156 ; ES:SI = ptr to a descriptor table containing segment descriptors
157 ; for the source and target memory of the transfer.
159 ; EXIT PROTECTED MODE
161 ; 01 if parity error *** currently not checked ***
162 ; 02 if exception error
163 ; 03 if gate address bit A20 fails.
165 ; ZF and NC in client's flags
167 ; NZ and CY in client's flags
170 ; USES AX, FLAGS -> CLD.
172 ; Descriptor Table Format
173 ; ES:SI ---> +-------------------------------+
174 ; | Dummy descriptor |
175 ; +-------------------------------+
177 ; +-------------------------------+
178 ; | Source segment descriptor |
179 ; +-------------------------------+
180 ; | Target segment descriptor |
181 ; +-------------------------------+
183 ;*************************************************************************
195 mov ax,VDMD_GSEL
; get data selector
196 mov ds,ax ; DS = DGROUP
197 mov [MB_Stat
],0 ; init status of move block to OK.
199 ; check word count field
201 cmp cx,8000h
;Q: word count too high
202 jbe MB_chk_length
; N: check length of segments
203 jmp MB_Excp_Error
; Y: report exception error
206 ; check source and target descriptor's lengths against transfer count
207 ; only need check low word since caller set up a 286 descriptor
211 shl ax,1 ; AX = # of bytes to transfer(0=>8000h)
212 dec ax ; convert to seg limit type value
214 cmp ax,ES:[si.MG_Source
.DD386_Limit_lo
] ;Q: source seg limit low ?
215 jbe MB_chk_tarl
; N: chk target length
216 jmp MB_Excp_Error
; Y: return excp error.
219 cmp ax,ES:[si.MG_Target
.DD386_Limit_lo
] ;Q: tar seg too small ?
220 jbe MB_setup
; N: seg limits OK.
221 jmp MB_Excp_Error
; Y: return excp error
223 ; source and target descriptors OK, set up scratch selector descriptors
227 push cx ; save copy count
230 pop ds ; set DS:SI to input descriptor table
232 mov es,ax ; ES:0 pts to GDT
233 mov di,MBSRC_GSEL
; ES:DI pts to source work descriptor in GDT
234 push si ; save input descr table ptr
235 lea si,[si.MG_Source
]; DS:SI pts to input source descr
237 rep movsw ; set move block source work descr
238 pop si ; restore input descr table ptr
239 mov di,MBSRC_GSEL
; ES:DI pts to source work descriptor in GDT
241 DescrMap
; fixup this descriptor's linear address
243 mov di,MBTAR_GSEL
; ES:DI pts to target work descr in GDT
244 push si ; save input descr table ptr
245 lea si,[si.MG_Target
] ; DS:SI pts to input target descr
247 rep movsw ; set move blk target work descr
248 pop si ; restore input descr table ptr
249 mov di,MBTAR_GSEL
; ES:DI pts to target work descr in GDT
251 DescrMap
; fixup this descriptor's linear address
254 ; install NMI/parity exception handler
256 call Set_Par_Vect
; restore the parity interrupt handler
263 ; check if a20 line is to be enabled or not
268 ; a20 line is currently disabled. we need to enable the a20
274 pop cx ; restore copy count
279 verr ax ;Q: source selector valid ?
280 jnz MB_Excp_Error
; N: return exception error
281 mov ds,ax ; Y: DS:SI pts to source segment
283 verw ax ;Q: target selector valid ?
284 jnz MB_Excp_Error
; N: return exception error
285 mov es,ax ; Y: ES:DI pts to target segment
286 jmp MB_move_block
; and go ahead
291 mov ax,VDMD_GSEL
; get data selector
292 mov ds,ax ; DS = DGROUP
303 ; MOVE the BLOCK - dwords
305 test cx,01h ;Q: move an odd # of words?
306 jz MB_moved
; N: move dwords
307 movsw ; Y: move the first one => dwords now
309 shr cx,1 ; move CX dwords...
311 rep movsw ; REP MOVSD
313 mov ax,VDMD_GSEL
; get data selector
314 mov ds,ax ; DS = DGROUP
316 ; restore a20 state to what it was before this routine
318 test [toggle_st
],0ffh ; do we need to toggle the a20 back?
319 jz a20_restored
; N: skip toggling
320 call togl_a20
; Y: else toggle the A20 line
322 mov [toggle_st
],0 ; clear this flag
327 ;*************************************************************************
328 ; This is special JUMP entry point for parity handler
335 call Rest_Par_Vect
; restore the parity interrupt handler
346 ; set client's flags to no error
348 or [bp.VTFOE
+VMTF_EFLAGS
],FLAGS_ZF
; ZF
349 and [bp.VTFOE
+VMTF_EFLAGS
],NOT FLAGS_CY
; NC
351 or ah,ah ;Q: error occured ?
352 jz MB_ret
; N: continue
353 ; Y: set error in client's flags
354 and [bp.VTFOE
+VMTF_EFLAGS
],NOT FLAGS_ZF
; NZ
355 or [bp.VTFOE
+VMTF_EFLAGS
],FLAGS_CY
; CY
367 ;****************************************
368 ; C O D E S E G M E N T R_CODE
369 ;****************************************
371 assume
cs:R_CODE
, ds:DGROUP
, es:DGROUP
373 ;*************************************************************************
375 ;*************************************************************************
376 I15_Old dd 0 ; old Int 15h handler
377 MB_Flag db 0 ; non-zero => do move block in ring 0
378 Exit_Flags dw 0 ; flags for int15 exit
380 ext_mem_size dw 0 ; we are using new int 15 allocation
381 ; scheme now whereby we have to lower
382 ; the size reported by int 15 function
383 ; 88h to grab some memory for ourself
384 ; The extended memory allocate routine
385 ; in allocmem.asm fills in the approp.
389 ;*************************************************************************
390 ; i15_Entry - real/virtual mode patch code for int 15h
392 ; This function patches the real mode IDT for MEMM. If it is
393 ; entered for a move block, this code sets a flag to tell MEMM to
394 ; pick up the move block, then i15_Entry lets MEMM do it. Otherwise
395 ; MEMM jumps to the previous code. For function 88h it reports the
396 ; the new size of extended memory.
398 ; ENTRY Real/Virtual mode
399 ; see int15h entry parameters in ROM spec
403 ; 87h: Real/Virtual mode
405 ; 01 if parity error *** currently not checked ***
406 ; 02 if exception error
407 ; 03 if gate address bit A20 fails.
409 ; ZF and NC in client's flags
411 ; NZ and CY in client's flags
413 ; 88h: Real/Virtual mode
414 ; AX = Size of extended memory in KB
417 ; USES AX, FLAGS -> CLD.
419 ; NOTE:**ISP This routine was modified to implement the new INT15 allocation
420 ; scheme whereby MEMM by lowering the size of extended memory could
421 ; grab the difference between the old size and the new size reported
423 ;*************************************************************************
431 cli ; in case of pushf/call far
432 pushf ; save entry flags
434 ; Check to see if it is the extended memory size request
436 cmp ah,88h
;Q: extended memory size request?
437 jne chk_blk_move
; N: go to check for move block call
439 ; Implement int15 allocation scheme by reporting a lowered value of extended
442 mov ax,cs:[ext_mem_size
] ; report new extended memory size
445 ; Checking for move block call
448 cmp ah,87h
;Q: move block call ?
449 jne i15_jmpf
; N: jmp to old code
452 pop ds ; DS -> DOSGROUP
453 cmp [Active_Status
],0 ; Y: Q: in Virtual mode ?
455 je i15_jmpf
; N: jmp to old code
457 mov CS:[MB_Flag
],TRUE
; let MEMM have it ...
458 popf ; retrieve entry flags (IF cleared!!!)
459 int 15h
; give it to MEMM
460 ; MEMM will reset MB_Flag
466 pop ax ; AX = exit flags
467 xchg ax,[bp+i15_Flags
] ; AX = entry flag, exit flags on stack
468 and ax,FLAGS_IF
; save only IF bit of entry
469 or [bp+i15_Flags
],ax ; set IF state in flags on stack
474 ; far jump to old code
477 popf ; retrieve entry flags
491 ;*************************************************************************
492 ; set_ext - to fill up size of extended memory reported by int 15
494 ; This function fills up the size of extended memory reported by the
495 ; int 15 real/virtual mode patch.
498 ; bx=size of extended memory in Kb
500 ; EXIT None. R_CODE:ext_mem_size filled.
504 ; WRITTEN 7/25/88 ISP
506 ;*************************************************************************
510 ASSUME
DS:NOTHING
,ES:NOTHING
520 mov [ext_mem_size
],bx