1 ; SCCSID = @(#)handle.asm 1.1 85/04/10
2 TITLE HANDLE
- Handle
-related system calls
5 ; Handle related system calls for MSDOS 2.X. Only top-level system calls
6 ; are present. I/O specs are defined in DISPATCH. The system calls are:
9 ; $Commit written DOS 3.3 F.C. 6/4/86
10 ; $ExtHandle written DOS 3.3 F.C. 6/4/86
12 ; Align_Buffer DOS 4.00
21 ; Created: MZ 28 March 1983
22 ; MZ 15 Dec 1982 Jeff Harbers and Multiplan hard disk copy
23 ; rely on certain values in AX when $CLOSE
24 ; succeeds even though we document it as
27 ; A000 version 4.00 Jan. 1988
32 ; get the appropriate segment definitions
36 CODE SEGMENT BYTE PUBLIC 'CODE'
37 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
48 EXTRN DOS_Read
:NEAR, DOS_Write
:NEAR
51 extrn save_user_map
:near
52 extrn restore_user_map
:near
53 extrn Setup_EMS_Buffers
:near
56 I_need ThisSFT
,DWORD ; pointer to SFT entry
57 I_need DMAAdd
,DWORD ; old-style DMA address
58 I_Need EXTERR_LOCUS
,byte ; Extended Error Locus
59 I_need FailErr
,BYTE ; failed error flag
60 I_need User_ID
,WORD ; current effective user_id
61 i_need JShare
,DWORD ; jump table
62 I_need CurrentPDB
,WORD ; current process data block
63 I_need EXTOPEN_ON
,BYTE ;AN000;FT. flag for extended open
64 ; I_need XA_device,BYTE ;AN000; XA device
65 I_need XA_type
,BYTE ;AN000; extended open subfunction
66 ; I_need XA_handle,WORD ;AN000; handle
67 I_need THISCDS
,DWORD ;AN000;
68 I_need DUMMYCDS
,128 ;AN000;
69 I_need SAVE_ES
,WORD ;AN000; saved ES
70 I_need SAVE_DI
,WORD ;AN000; saved DI
71 I_need SAVE_DS
,WORD ;AN000; saved DS
72 I_need SAVE_SI
,WORD ;AN000; saved SI
73 I_need SAVE_CX
,WORD ;AN000; saved CX
77 I_need BUF_EMS_MODE
,BYTE
78 I_need BUF_EMS_LAST_PAGE
,DWORD
79 I_need BUF_EMS_FIRST_PAGE
,DWORD
80 I_need BUF_EMS_SAFE_FLAG
,BYTE
81 I_need BUF_EMS_NPA640
,WORD
82 I_need BUF_EMS_PAGE_FRAME
,WORD
83 I_need BUF_EMS_PFRAME
,WORD
84 I_need LASTBUFFER
,DWORD
88 ; I_need XA_ES,WORD ;AN000; extended find
89 ; I_need XA_BP,WORD ;AN000; extended find
90 ; I_need XA_from,BYTE ;AN000; for filetimes
97 BREAK <$Close
- return a handle to the system
>
106 ; AX = error_invalid_handle
108 ; No registers returned
110 Procedure $Close
,NEAR
111 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
112 fmt TypSysCall
,LevLog
,<"$p Close\n">
113 fmt TypSysCall
,LevArgs
,<"$p Handle = $x\n">,<BX>
115 ; Grab the SFT pointer from the JFN.
117 call CheckOwner
; get system file entry
118 JC CloseError
; error return
119 fmt TypAccess
,LevSFN
,<"$p Close SFT $x:$x\n">,<es,di>
120 context
DS ; For DOS_CLOSE
121 MOV WORD PTR [ThisSFT
],DI ; save offset of pointer
122 MOV WORD PTR [ThisSFT
+2],ES ; save segment value
124 ; DS:SI point to JFN table entry.
127 ; We now examine the user's JFN entry; If the file was a 70-mode file (network
128 ; FCB, we examine the ref count on the SFT; if it was 1, we free the JFN.
129 ; If the file was not a net FCB, we free the JFN too.
131 CMP ES:[DI].sf_ref_count
,1 ; will the SFT become free?
132 JZ FreeJFN
; yes, free JFN anyway.
133 MOV AL,BYTE PTR ES:[DI].sf_mode
135 CMP AL,sharing_net_fcb
136 JZ PostFree
; 70-mode and big ref count => free it
138 ; The JFN must be freed. Get the pointer to it and replace the contents with
142 Invoke pJFNFromHandle
; d = pJFN (handle);
143 fmt TypAccess
,LevSFN
,<"$p Close jfn pointer $x:$x\n">,<es,di>
144 MOV BYTE PTR ES:[DI],0FFh ; release the JFN
147 ; ThisSFT is correctly set, we have DS = DOSGROUP. Looks OK for a DOS_CLOSE!
151 ; DOS_Close may return an error. If we see such an error, we report it but
152 ; the JFN stays closed because DOS_Close always frees the SFT!
155 fmt TypSysCall
,LevLog
,<"$p: Close ok\n">
156 MOV AH,close
; MZ Bogus multiplan fix
160 fmt TypSysCall
,LevLog
,<"$p: Close error $x\n">,<AX>
164 BREAK <$Commit
- commit the
file>
173 ; AX = error_invalid_handle
175 ; No registers returned
177 Procedure $Commit
,NEAR
178 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
180 ; Grab the SFT pointer from the JFN.
182 call CheckOwner
; get system file entry
183 JC Commiterror
; error return
184 context
DS ; For DOS_COMMIT
185 MOV WORD PTR [ThisSFT
],DI ; save offset of pointer
186 MOV WORD PTR [ThisSFT
+2],ES ; save segment value
191 ; ThisSFT is correctly set, we have DS = DOSGROUP. Looks OK for a DOS_COMMIT
205 BREAK <$ExtHandle
- extend handle count
>
209 ; MOV BX, Number of Opens Allowed (MAX=65534;66535 is
210 ; MOV AX, 6700H reserved to mark SFT
211 ; INT int_command busy )
214 ; AX = error_not_enough_memory
215 ; or error_too_many_open_files
216 ; No registers returned
218 Procedure $ExtHandle
,NEAR
219 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
223 XOR BP,BP ; 0: enlarge 1: shrink 2:psp
224 CMP BX,FilPerProc
; < 20
226 MOV BX,FilPerProc
; bx = 20
229 MOV ES,[CurrentPDB
] ; get user process data block
230 MOV CX,ES:[PDB_JFN_Length
] ; get number of handle allowed
231 CMP BX,CX ; the requested == current
232 JE ok_done
; yes and exit
233 JA larger
; go allocate new table
236 MOV DS,WORD PTR ES:[PDB_JFN_Pointer
+2] ;
238 SUB CX,BX ; get difference
240 CMP BYTE PTR DS:[SI],-1 ; scan through handles to ensure close
241 JNZ too_many_files
; status
244 CMP BX,FilPerProc
; = 20
248 MOV DI,PDB_JFN_Table
; es:di -> jfn table in psp
253 CMP BX,-1 ; 65535 is not allowed
256 PUSH BX ; save requested number
257 ADD BX,0FH ; adjust to paragraph boundary
259 RCR BX,CL ; DOS 4.00 fix ;AC000;
260 AND BX,1FFFH
; clear most 3 bits
263 invoke $ALLOC
; allocate memory
265 JC no_memory
; not enough meory
267 MOV ES,AX ; es:di points to new table memory
270 MOV DS,[CurrentPDB
] ; get user PDB address
272 TEST BP,3 ; enlarge ?
274 POP CX ; cx = the amount you shrink
280 MOV AL,error_too_many_open_files
283 MOV CX,DS:[PDB_JFN_Length
] ; get number of old handles
286 LDS SI,DS:[PDB_JFN_Pointer
] ; get old table pointer
288 REP MOVSB ; copy infomation to new table
290 POP CX ; get new number of handles
291 PUSH CX ; save it again
292 SUB CX,DX ; get the difference
293 MOV AL,-1 ; set availability to handles
296 MOV DS,[CurrentPDB
] ; get user process data block
297 CMP WORD PTR DS:[PDB_JFN_Pointer
],0 ; check if original table pointer
298 JNZ update_info
; yes, go update PDB entries
300 PUSH DS ; save old table segment
301 PUSH ES ; save new table segment
302 MOV ES,WORD PTR DS:[PDB_JFN_Pointer
+2] ; get old table segment
303 invoke $DEALLOC
; deallocate old table meomory
304 POP ES ; restore new table segment
305 POP DS ; restore old table segment
311 MOV WORD PTR DS:[PDB_JFN_Pointer
],PDB_JFN_Table
; restore
314 MOV WORD PTR DS:[PDB_JFN_Pointer
],0 ; new table pointer offset always 0
316 MOV WORD PTR DS:[PDB_JFN_Pointer
+2],ES ; update table pointer segment
317 POP DS:[PDB_JFN_Length
] ; restore new number of handles
321 MOV AL,error_not_enough_memory
324 MOV AL,error_invalid_function
328 BREAK <$READ
- Read
from a
file handle
>
336 ; AX has number of bytes read
338 ; AX = read_invalid_handle
339 ; = read_access_denied
341 ; Returns in register AX
344 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
345 fmt TypSysCall
,LevLog
,<"Read\n">
346 fmt TypSysCall
,LevArgs
,<" Handle $x Cnt $x Buf $x:$x\n">,<BX,CX,DS,DX>
347 MOV SI,OFFSET DOSGROUP
:DOS_Read
349 invoke pJFNFromHandle
352 call CheckOwner
; get the handle
353 JNC ReadSetup
; no errors do the operation
355 fmt TypSysCall
,LevLog
,<"Read/Write error $x\n">,<AX>
356 transfer SYS_RET_ERR
; go to error traps
358 MOV WORD PTR [ThisSFT
],DI ; save offset of pointer
359 MOV WORD PTR [ThisSFT
+2],ES ; save segment value
361 TEST ES:[DI.sf_mode
],INT_24_ERROR
;AN000;;EO. need i24
362 JZ needi24
;AN000;;EO. yes
363 OR [EXTOPEN_ON
],EXT_OPEN_I24_OFF
;AN000;;EO. set it off
367 SaveReg
<<WORD PTR [DMAAdd
]>, <WORD PTR [DMAAdd
+2]>>
368 ;;;;; BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!!
369 CALL Align_Buffer
;AN000;MS. align user's buffer
370 ;;;;; END BAD SPOT FOR 286!!! SEGMENT ARITHMETIC!!!
375 ; cmp [BUF_EMS_MODE], -1
377 ; call choose_buf_page
383 context
DS ; go for DOS addressability
384 CALL SI ; indirect call to operation
385 RestoreReg
<<WORD PTR [DMAAdd
+2]>, <WORD PTR [DMAAdd
]>>
392 cmp cs:[BUF_EMS_MODE
], -1
394 call restore_user_map
395 mov ax, word ptr cs:[BUF_EMS_LAST_PAGE
]
396 cmp cs:[BUF_EMS_PFRAME
], ax
398 mov word ptr cs:[LASTBUFFER
], -1
399 mov cs:[BUF_EMS_PFRAME
], ax
400 mov ax, word ptr cs:[BUF_EMS_LAST_PAGE
+2]
401 mov cs:[BUF_EMS_PAGE_FRAME
], ax
402 mov cs:[BUF_EMS_SAFE_FLAG
], 1
403 call Setup_EMS_Buffers
412 JC ReadError
; if error, say bye bye
419 MOV AX,CX ; get correct return in correct reg
420 fmt TypSysCall
,LevLog
,<"Read/Write cnt done $x\n">,<AX>
421 transfer sys_ret_ok
; successful return
425 ; Input: DS:DX points to user's buffer addr
426 ; Function: rearrange segment and offset for READ/WRITE buffer
427 ; Output: [DMAADD] set
431 procedure Align_Buffer
,NEAR ;AN000;
432 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
;AN000;
433 MOV BX,DX ; copy offset
434 SaveReg
<CX> ; don't stomp on count
435 MOV CL,4 ; bits to shift bytes->para
436 SHR BX,CL ; get number of paragraphs
437 RestoreReg
<CX> ; get count back
438 MOV AX,DS ; get original segment
439 ADD AX,BX ; get new segment
440 MOV DS,AX ; in seg register
441 AND DX,0Fh ; normalize offset
442 MOV WORD PTR [DMAAdd
],DX ; use user DX as offset
443 MOV WORD PTR [DMAAdd
+2],DS ; use user DS as segment for DMA
445 EndProc Align_Buffer
;AN000;
447 BREAK <$WRITE
- write to a
file handle
>
456 ; AX has number of bytes written
458 ; AX = write_invalid_handle
459 ; = write_access_denied
461 ; Returns in register AX
463 procedure $WRITE
,NEAR
464 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
465 fmt TypSysCall
,LevLog
,<"Write\n">
466 fmt TypSysCall
,LevArgs
,<" Handle $x Cnt $x Buf $x:$x\n">,<BX,CX,DS,DX>
467 MOV SI,OFFSET DOSGROUP
:DOS_Write
471 BREAK <$LSEEK
- move r
/w pointer
>
481 ; DX:AX has the new location of the pointer
483 ; AX = error_invalid_handle
484 ; = error_invalid_function
485 ; Returns in registers DX:AX
487 procedure $LSEEK
,NEAR
488 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
489 call CheckOwner
; get system file entry
495 JC ReadError
; error return
497 CMP AL,2 ; is the seek value correct?
498 JBE LSeekDisp
; yes, go dispatch
499 MOV EXTERR_LOCUS
,errLoc_Unk
; Extended Error Locus
500 error error_invalid_function
; invalid method
502 CMP AL,1 ; best way to dispatch; check middle
503 JB LSeekStore
; just store CX:DX
504 JA LSeekEOF
; seek from end of file
505 ADD DX,WORD PTR ES:[DI.SF_Position
]
506 ADC CX,WORD PTR ES:[DI.SF_Position
+2]
509 XCHG AX,DX ; DX:AX is the correct value
511 MOV WORD PTR ES:[DI.SF_Position
],AX
512 MOV WORD PTR ES:[DI.SF_Position
+2],DX
513 invoke Get_user_stack
514 MOV DS:[SI.User_DX
],DX ; return DX:AX
515 transfer SYS_RET_OK
; successful return
518 TEST ES:[DI.sf_flags
],sf_isnet
519 JNZ Check_LSeek_Mode
; Is Net
521 ADD DX,WORD PTR ES:[DI.SF_Size
]
522 ADC CX,WORD PTR ES:[DI.SF_Size
+2]
523 JMP LSeekStore
; go and set the position
526 TEST ES:[DI.sf_mode
],sf_isfcb
527 JNZ LOCAL_LSeek
; FCB treated like local file
528 MOV AX,ES:[DI.sf_mode
]
530 CMP AX,sharing_deny_none
531 JZ NET_LSEEK
; LSEEK exported in this mode
532 CMP AX,sharing_deny_read
533 JNZ LOCAL_LSeek
; Treated like local Lseek
536 ; REMOVE ABOVE INSTRUCTION TO ENABLE DCR 142
537 CallInstall Net_Lseek
,multNet
,33
543 BREAK <FileTimes
- modify write
times on a handle
>
547 ; MOV AH, FileTimes (57H)
550 ; ; if AL = 1 then then next two are mandatory
554 ; ; if AL = 0 then CX/DX has the last write time/date
557 ; AL=02 get extended attributes
559 ; CX=size of buffer (0, return max size )
560 ; DS:SI query list (si=-1, selects all EA)
561 ; ES:DI buffer to hold EA list
563 ; AL=03 get EA name list
565 ; CX=size of buffer (0, return max size )
566 ; ES:DI buffer to hold name list
568 ; AL=04 set extended attributes
570 ; ES:DI buffer of EA list
576 ; AX = error_invalid_function
577 ; = error_invalid_handle
580 procedure $File_Times
,NEAR
581 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
582 CMP AL,2 ; correct subfunction?
584 JMP filetimes_ok
; Yes, continue
585 ;;;; DOS 4.00 ;AN000;
587 EnterCrit critSFT
;AN000;;FT. enter critical section
588 CMP AL,4 ;AN000;;FT. =4
589 JBE gshandle
;AN000;;FT. 2,3,4 do get/set by handle
591 JMP inval_func
;AN000;;FT. invalid function
594 MOV [SAVE_ES
],ES ;AN000;;FT. save regs
595 MOV [SAVE_DI
],DI ;AN000;;FT.
596 MOV [SAVE_DS
],DS ;AN000;;FT. save regs
597 MOV [SAVE_SI
],SI ;AN000;;FT.
598 MOV [SAVE_CX
],CX ;AN000;;FT.
599 MOV [XA_TYPE
],AL ;AN000;;FT.
601 ; MOV [XA_handle],BX ;AN000; ;FT. save handle
602 CALL CheckOwner
;AN000; ;FT. get sf pointer
603 JNC getsetit
;AN000; ;FT. good handle
604 LeaveCrit critSFT
;AN000; ;FT. leave critical section
605 JMP LSeekError
;AN000; ;FT. turkey handle
608 MOV WORD PTR [ThisSFT
],DI ;AN000; ;FT. set ThisSFT
609 MOV WORD PTR [ThisSFT
+2],ES ;AN000; ;FT. set ThisSFT
610 ; TEST ES:[DI.sf_mode],INT_24_ERROR ;AN000;;FT. mask INT 24
611 ; JZ nomask ;AN000;;FT. no
612 ; OR [EXTOPEN_ON],EXT_OPEN_I24_OFF ;AN000;;FT. set bit for I24 handler
614 TEST ES:[DI.sf_flags
],sf_isnet
;AN000;;FT. remote handle
615 JZ localhandle
;AN000;;FT. no
616 LeaveCrit critSFT
;AN000;;FT. doesn't support Network
618 MOV BL,[XA_TYPE
] ;AN000;;FT.
620 MOV AX,(multNET
SHL 8) or 45 ;AN000;;FT. Get/Set XA support
622 JC getseterror
;AN000;;FT. error
623 transfer SYS_RET_OK
;AN000;;FT.
625 ; TEST ES:[DI.sf_flags],devid_device ;AN000;;FT. device
626 ; JZ getsetfile8 ;AN000;;FT. no
627 ; MOV [XA_device],1 ;AN000;;FT. indicating device
628 ; JMP SHORT doXA ;AN000;;FT. do XA
630 ; MOV [XA_device],0 ;AN000;;FT. indicating File
631 ; LES BP,ES:[DI.sf_devptr] ;AN000;;FT. ES:BP -> DPB
634 ; MOV [XA_from],By_XA ;AN000;;FT. from get/set XA
635 ; PUSH [SAVE_ES] ;AN000;;FT. save XA list
636 ; PUSH [SAVE_DI] ;AN000;;FT. save XA list
638 invoke GetSet_XA
;AN000;;FT. issue Get/Set XA
639 ; POP SI ;AN000;;FT. DS:SI -> XA list
641 JC getexit
;AN000;;FT. error
642 ; CMP [XA_device],0 ;AN000;;FT. device ?
643 ; JNZ ftok ;AN000;;FT. yes, exit
644 ; MOV AX,4 ;AN000;;FT. function 4 for ShSU
645 ; CMP [XA_type],4 ;AN000;;FT. set XA
646 ; JNZ ftok ;AN000;;FT. no
649 ; LES DI,[ThisSFT] ;AN000;;FT. es:di -> sft
650 ; CMP WORD PTR [SI],0 ;AN000;;FT. null list ?
651 ; JNZ do_share ;AN000;;FT. no
652 JMP SHORT ftok
;AN000;;FT. return
654 LeaveCrit critSFT
;AN000;;FT. leave critical section
658 transfer SYS_RET_ERR
;AN000;;FT. mark file as dirty
662 MOV EXTERR_LOCUS
,errLoc_Unk
; Extended Error Locus
663 error error_invalid_function
; give bad return
665 call CheckOwner
; get sf pointer
667 JMP LSeekError
; turkey handle
669 OR AL,AL ; is it Get?
670 JNZ filetimes_set
; no, go set the time
672 MOV CX,ES:[DI.sf_Time
] ; suck out time
673 MOV DX,ES:[DI.sf_Date
] ; and date
675 invoke Get_user_stack
; obtain place to return it
676 MOV [SI.user_CX
],CX ; and stash in time
677 MOV [SI.user_DX
],DX ; and stask in date
679 transfer SYS_RET_OK
; and say goodnight
682 MOV ES:[DI.sf_Time
],CX ; drop in new time
683 MOV ES:[DI.sf_Date
],DX ; and date
692 AND ES:[DI.sf_Flags
],NOT devid_file_clean
693 OR ES:[DI.sf_Flags
],sf_close_nodate
696 transfer SYS_RET_OK
; mark file as dirty and return
699 BREAK <$
DUP - duplicate a jfn
>
705 ; AX has the returned handle
707 ; AX = dup_invalid_handle
708 ; = dup_too_many_open_files
710 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
711 MOV AX,BX ; save away old handle in AX
712 invoke JFNFree
; free handle? into ES:DI, new in BX
714 JC DupErr
; nope, bye
715 SaveReg
<ES,DI> ; save away SFT
716 RestoreReg
<SI,DS> ; into convenient place DS:SI
717 XCHG AX,BX ; get back old handle
718 call CheckOwner
; get sft in ES:DI
719 JC DupErr
; errors go home
720 invoke DOS_Dup_Direct
721 invoke pJFNFromHandle
; get pointer
722 MOV BL,ES:[DI] ; get SFT number
723 MOV DS:[SI],BL ; stuff in new SFT
724 transfer SYS_RET_OK
; and go home
725 DupErr: transfer SYS_RET_ERR
729 BREAK <$DUP2
- force a
dup on a particular jfn
>
737 ; AX = error_invalid_handle
740 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
741 SaveReg
<BX,CX> ; save source
742 MOV BX,CX ; get one to close
743 invoke $Close
; close destination handle
744 RestoreReg
<BX,AX> ; old in AX, new in BX
745 invoke pJFNFromHandle
; get pointer
746 JMP DupErrorCheck
; check error and do dup
749 Break <CheckOwner
- verify ownership of handles
from server
>
752 ; CheckOwner - Due to the ability of the server to close file handles for a
753 ; process without the process knowing it (delete/rename of open files, for
754 ; example), it is possible for the redirector to issue a call to a handle
755 ; that it soes not rightfully own. We check here to make sure that the
756 ; issuing process is the owner of the SFT. At the same time, we do a
757 ; SFFromHandle to really make sure that the SFT is good.
759 ; Inputs: BX has the handle
760 ; User_ID is the current user
761 ; Output: Carry Clear => ES:DI points to SFT
762 ; Carry Set => AX has error code
763 ; Registers modified: none
766 Procedure CheckOwner
,NEAR
767 ASSUME
CS:DOSGROUP
,DS:NOTHING
,ES:NOTHING
,SS:DOSGROUP
772 cmp ax,es:[di].sf_UID
775 mov al,error_invalid_handle
780 ;-------------------------------------------------------------------------
781 ; Function name : choose_buf_page
782 ; Inputs : DMAADD = Xaddr
783 ; cx = # of bytes to transfer
786 ; SAFE_FLAG - 0 ==> page is safe. no need to
787 ; detect collision between
788 ; user & system buffer.
789 ; SAFE_FLAG - 1 ==> page is unsafe. Must check
795 ; High Level Alogrithm:
797 ; 1. If Xaddr. is above the first physical page above 640K
798 ; 2. choose that page
801 ; 5. choose highest page above 640K
802 ; 6. If 6 or more pages above 640k
805 ; 9. if Xaddr. + # of bytes to transfer does not spill into the
809 ; 12. clear safe flag
814 ;----------------------------------------------------------------------------
815 ;Procedure choose_buf_page,near
817 ; assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup
826 ; mov ax, word ptr [DMAADD+2]
827 ; and ax, 0fc00h ; page segment of transfer segment
829 ; cmp ax, word ptr [BUF_EMS_FIRST_PAGE]
832 ; cmp [BUF_EMS_NPA640], 6
835 ; add cx, word ptr [DMAADD] ; get final offset
839 ; shr bx, cl ; get # of paragraphs
840 ; mov ax, word ptr [DMAADD+2] ; get initial segment
841 ; add ax, bx ; get final segment
844 ; cmp ax, word ptr [BUF_EMS_LAST_PAGE]
847 ; mov [BUF_EMS_SAFE_FLAG], 0
848 ; jmp fin_choose_page
851 ; mov [BUF_EMS_SAFE_FLAG], 1
852 ; jmp fin_choose_page
855 ;; mov ax, word ptr [BUF_EMS_LAST_PAGE]
856 ;; mov [BUF_EMS_PFRAME], ax
857 ;; mov ax, word ptr [BUF_EMS_LAST_PAGE+2]
858 ;; mov [BUF_EMS_PAGE_FRAME], ax
860 ;; jmp fin_choose_page
863 ; mov ax, word ptr [BUF_EMS_FIRST_PAGE]
864 ; cmp [BUF_EMS_PFRAME], ax
866 ; mov word ptr [LASTBUFFER], -1
867 ; mov [BUF_EMS_PFRAME], ax
868 ; mov ax, word ptr [BUF_EMS_FIRST_PAGE+2]
869 ; mov [BUF_EMS_PAGE_FRAME], ax
870 ; mov [BUF_EMS_SAFE_FLAG], 1
871 ; call Setup_EMS_Buffers
872 ; jmp fin_choose_page
888 ;EndProc choose_buf_page