]> wirehaze git hosting - MS-DOS.git/blob - v4.0/src/MEMM/MEMM/MOVEB.ASM

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / MEMM / MEMM / MOVEB.ASM
1
2
3 page 58,132
4 ;******************************************************************************
5 title MOVEB - move block emulator
6 ;******************************************************************************
7 ;
8 ; (C) Copyright MICROSOFT Corp. 1986
9 ;
10 ; Title: MEMM.EXE - MICROSOFT Expanded Memory Manager 386 Driver
11 ;
12 ; Module: MOVEB - move block code for MEMM
13 ;
14 ; Version: 0.05
15 ;
16 ; Date: 05/22/86
17 ;
18 ; Author:
19 ;
20 ;*************************************************************************
21 ; CHANGE LOG:
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
28 ; diag byte location.
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 ;*************************************************************************
34 .386p
35
36
37 ;****************************************
38 ; P U B L I C S
39 ;****************************************
40 public Move_Block
41 public MB_Exit
42 public MB_Stat
43 public i15_Entry
44 public MB_Flag
45 public i15_Old
46
47 page
48 ;****************************************
49 ; D E F I N E S
50 ;****************************************
51 include vdmseg.inc
52 include vdmsel.inc
53 include desc.inc
54 include instr386.inc
55 include oemdep.inc
56 include vm386.inc
57
58 TRUE equ 0FFh
59 FALSE equ 00h
60
61 D_G_BIT equ 80h ; granularity bit in high status bits
62
63 FLAGS_CY equ 0001h
64 FLAGS_ZF equ 0040h
65 FLAGS_IF equ 0200h
66
67 ; 386 data descriptor format
68 DATA_DESC_386 struc
69 DD386_Limit_lo dw ? ; low word of seg limit
70 DD386_Base_lo dw ? ; low 24 bits of seg base addr
71 db ? ;
72 DD386_Access db ? ; access byte
73 DD386_L_Stat db ? ; high 4 bits of seg limit
74 ; and futher status
75 DD386_Base_hi db ? ; high 8 bits of seg base addr
76 DATA_DESC_386 ends
77
78 ; format of move block descriptor table passed on entry
79 MB_GDT struc
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
84 MB_GDT ends
85
86 ;************************************************************
87 ; DescrMap - map address in descriptor
88 ; ENTRY: ES:DI = descriptor
89 ; EXIT: descriptor's address is mapped by MapLinear
90 ; USED: EAX
91 ;************************************************************
92 DescrMap MACRO
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
95 OP32
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
100 OP32
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
104 ENDM
105
106 ;*******************************************************************************
107 ; E X T E R N A L R E F E R E N C E S
108 ;*******************************************************************************
109 _TEXT segment
110
111 extrn MapLinear:near
112 extrn Set_Par_Vect:near
113 extrn Rest_Par_Vect:near
114 extrn togl_A20:near
115 extrn get_a20_state:near
116
117 _TEXT ends
118
119 _DATA segment
120
121 extrn Active_Status:byte ; non-zero if in VM
122
123 _DATA ends
124
125
126 page
127 ;*******************************************************************************
128 ; D A T A S E G M E N T
129 ;*******************************************************************************
130 _DATA segment
131
132 MB_Stat db 0 ; move block status
133 Toggle_st db 0
134
135 _DATA ends
136
137 page
138 ;****************************************
139 ; C O D E S E G M E N T _TEXT
140 ;****************************************
141 _TEXT segment
142 assume cs:_TEXT, ds:DGROUP, es:DGROUP
143
144 page
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.
151 ;
152 ;
153 ; ENTRY PROTECTED MODE
154 ; AH = 87h
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.
158 ;
159 ; EXIT PROTECTED MODE
160 ; AH = 00 if OK
161 ; 01 if parity error *** currently not checked ***
162 ; 02 if exception error
163 ; 03 if gate address bit A20 fails.
164 ; if no error:
165 ; ZF and NC in client's flags
166 ; if error:
167 ; NZ and CY in client's flags
168 ;
169 ;
170 ; USES AX, FLAGS -> CLD.
171 ;
172 ; Descriptor Table Format
173 ; ES:SI ---> +-------------------------------+
174 ; | Dummy descriptor |
175 ; +-------------------------------+
176 ; | GDT descriptor |
177 ; +-------------------------------+
178 ; | Source segment descriptor |
179 ; +-------------------------------+
180 ; | Target segment descriptor |
181 ; +-------------------------------+
182 ;
183 ;*************************************************************************
184 Move_Block proc near
185 ;
186 push ds
187 push es
188 PUSH_EAX
189 push cx
190 push si
191 push di
192 ;
193 cld
194 ;
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.
198 ;
199 ; check word count field
200 ;
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
204
205 ;
206 ; check source and target descriptor's lengths against transfer count
207 ; only need check low word since caller set up a 286 descriptor
208 ;
209 MB_chk_length:
210 mov ax,cx
211 shl ax,1 ; AX = # of bytes to transfer(0=>8000h)
212 dec ax ; convert to seg limit type value
213 ; ( 0FFFFh => 64K )
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.
217
218 MB_chk_tarl:
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
222 ;
223 ; source and target descriptors OK, set up scratch selector descriptors
224 ;
225
226 MB_setup:
227 push cx ; save copy count
228
229 push es
230 pop ds ; set DS:SI to input descriptor table
231 mov ax,GDTD_GSEL
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
236 mov cx,4
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
240 call MB_Map_Src
241 DescrMap ; fixup this descriptor's linear address
242
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
246 mov cx,4
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
250 call MB_Map_Dest
251 DescrMap ; fixup this descriptor's linear address
252
253 ;
254 ; install NMI/parity exception handler
255 ;
256 call Set_Par_Vect ; restore the parity interrupt handler
257
258 ;
259 ; copy the data
260 ;
261
262 ;
263 ; check if a20 line is to be enabled or not
264 ;
265 call get_a20_state
266 jnz a20_is_enb
267 ;
268 ; a20 line is currently disabled. we need to enable the a20
269 ;
270 call togl_a20
271 mov [toggle_st],0ffh
272 a20_is_enb:
273 ;
274 pop cx ; restore copy count
275
276 xor di,di
277 xor si,si
278 mov ax,MBSRC_GSEL
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
282 mov ax,MBTAR_GSEL
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
287 ;
288 ; Error reporting
289 ;
290 MB_Excp_Error:
291 mov ax,VDMD_GSEL ; get data selector
292 mov ds,ax ; DS = DGROUP
293 mov [MB_Stat],2
294 jmp MB_Exit
295 ;
296 ; move the block
297 ;
298 MB_move_block:
299
300 call MB_Start
301
302 ;
303 ; MOVE the BLOCK - dwords
304 ;
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
308 MB_moved:
309 shr cx,1 ; move CX dwords...
310 OP32
311 rep movsw ; REP MOVSD
312
313 mov ax,VDMD_GSEL ; get data selector
314 mov ds,ax ; DS = DGROUP
315
316 ; restore a20 state to what it was before this routine
317 ;
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
321 a20_restored:
322 mov [toggle_st],0 ; clear this flag
323
324 jmp MB_Exit
325 Move_Block endp
326
327 ;*************************************************************************
328 ; This is special JUMP entry point for parity handler
329 ;
330 MB_Exit proc near
331 ;
332 ; reset NMI handler
333 ;
334
335 call Rest_Par_Vect ; restore the parity interrupt handler
336
337 ;
338 ;
339 MB_leave:
340 pop di
341 pop si
342 pop cx
343 POP_EAX
344 mov ah,[MB_Stat]
345 ;
346 ; set client's flags to no error
347 ;
348 or [bp.VTFOE+VMTF_EFLAGS],FLAGS_ZF ; ZF
349 and [bp.VTFOE+VMTF_EFLAGS],NOT FLAGS_CY ; NC
350
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
356 ;
357 MB_ret:
358 pop es
359 pop ds
360 ret
361 ;
362 MB_Exit endp
363
364 _TEXT ends
365
366 page
367 ;****************************************
368 ; C O D E S E G M E N T R_CODE
369 ;****************************************
370 R_CODE segment
371 assume cs:R_CODE, ds:DGROUP, es:DGROUP
372
373 ;*************************************************************************
374 ; local data
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
379 ;
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.
386 ; size here.
387
388 page
389 ;*************************************************************************
390 ; i15_Entry - real/virtual mode patch code for int 15h
391 ;
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.
397 ;
398 ; ENTRY Real/Virtual mode
399 ; see int15h entry parameters in ROM spec
400 ;
401 ; EXIT
402 ;
403 ; 87h: Real/Virtual mode
404 ; AH = 00 if OK
405 ; 01 if parity error *** currently not checked ***
406 ; 02 if exception error
407 ; 03 if gate address bit A20 fails.
408 ; if no error:
409 ; ZF and NC in client's flags
410 ; if error:
411 ; NZ and CY in client's flags
412 ;
413 ; 88h: Real/Virtual mode
414 ; AX = Size of extended memory in KB
415 ;
416 ;
417 ; USES AX, FLAGS -> CLD.
418 ;
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
422 ; for itself.
423 ;*************************************************************************
424 i15_flags equ 6
425 i15_cs equ 4
426 i15_ip equ 2
427 i15_bp equ 0
428
429 i15_Entry proc near
430 ;
431 cli ; in case of pushf/call far
432 pushf ; save entry flags
433 ;
434 ; Check to see if it is the extended memory size request
435 ;
436 cmp ah,88h ;Q: extended memory size request?
437 jne chk_blk_move ; N: go to check for move block call
438 ;
439 ; Implement int15 allocation scheme by reporting a lowered value of extended
440 ; memory.
441 popf
442 mov ax,cs:[ext_mem_size] ; report new extended memory size
443 iret ;
444 ;
445 ; Checking for move block call
446 ;
447 chk_blk_move:
448 cmp ah,87h ;Q: move block call ?
449 jne i15_jmpf ; N: jmp to old code
450 push ds
451 push seg DGROUP ;
452 pop ds ; DS -> DOSGROUP
453 cmp [Active_Status],0 ; Y: Q: in Virtual mode ?
454 pop ds ; reset DS
455 je i15_jmpf ; N: jmp to old code
456 ; Y: VM move block
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
461 cli ; just in case
462 push bp ; save bp
463 mov bp,sp
464 push ax ; save ax
465 pushf
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
470 pop ax
471 pop bp
472 iret ; and leave
473 ;
474 ; far jump to old code
475 ;
476 i15_jmpf:
477 popf ; retrieve entry flags
478 jmp CS:[i15_Old]
479 ;
480 i15_Entry endp
481
482 R_CODE ends
483
484
485 LAST SEGMENT
486 ;
487 ASSUME CS:LAST
488 ;
489 public set_ext
490 ;
491 ;*************************************************************************
492 ; set_ext - to fill up size of extended memory reported by int 15
493 ;
494 ; This function fills up the size of extended memory reported by the
495 ; int 15 real/virtual mode patch.
496 ;
497 ; ENTRY Real Mode
498 ; bx=size of extended memory in Kb
499 ;
500 ; EXIT None. R_CODE:ext_mem_size filled.
501 ;
502 ; USES None.
503 ;
504 ; WRITTEN 7/25/88 ISP
505 ;
506 ;*************************************************************************
507
508 set_ext proc near
509 ;
510 ASSUME DS:NOTHING,ES:NOTHING
511
512 push ax
513 push ds
514 ;
515 mov ax,seg R_CODE
516 mov ds,ax
517 ;
518 ASSUME DS:R_CODE
519 ;
520 mov [ext_mem_size],bx
521 ;
522 pop ds
523 pop ax
524 ;
525 ASSUME DS:NOTHING
526 ;
527 ret
528 ;
529 set_ext endp
530 ;
531
532 LAST ENDS
533 end