summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/DISK.ASM
diff options
context:
space:
mode:
authorGravatar Mark Zbikowski2024-04-25 21:24:10 +0100
committerGravatar Microsoft Open Source2024-04-25 22:32:27 +0000
commit2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch)
tree80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/DOS/DISK.ASM
parentMerge pull request #430 from jpbaltazar/typoptbr (diff)
downloadms-dos-main.tar.gz
ms-dos-main.tar.xz
ms-dos-main.zip
MZ is back!HEADmain
Diffstat (limited to 'v4.0/src/DOS/DISK.ASM')
-rw-r--r--v4.0/src/DOS/DISK.ASM1073
1 files changed, 1073 insertions, 0 deletions
diff --git a/v4.0/src/DOS/DISK.ASM b/v4.0/src/DOS/DISK.ASM
new file mode 100644
index 0000000..2fad68b
--- /dev/null
+++ b/v4.0/src/DOS/DISK.ASM
@@ -0,0 +1,1073 @@
1; SCCSID = @(#)disk.asm 1.1 85/04/10
2; SCCSID = @(#)disk.asm 1.1 85/04/10
3TITLE DISK - Disk utility routines
4NAME Disk
5; Low level Read and write routines for local SFT I/O on files and devs
6;
7; SWAPCON
8; SWAPBACK
9; DOS_READ
10; DOS_WRITE
11; get_io_sft
12; DirRead
13; FIRSTCLUSTER
14; SET_BUF_AS_DIR
15; FATSecRd
16; DREAD
17; CHECK_WRITE_LOCK
18; CHECK_READ_LOCK
19;
20; Revision history:
21;
22; A000 version 4.00 Jan. 1988
23;
24
25;
26; get the appropriate segment definitions
27;
28.xlist
29include dosseg.asm
30include fastseek.inc ;AN000;
31include fastxxxx.inc ;AN000;
32
33CODE SEGMENT BYTE PUBLIC 'CODE'
34 ASSUME SS:DOSGROUP,CS:DOSGROUP
35
36.xcref
37INCLUDE DOSSYM.INC
38INCLUDE DEVSYM.INC
39include version.inc
40.cref
41.list
42
43Installed = TRUE
44
45 I_need DirStart,WORD
46 I_Need CONSft,DWORD ; SFT for swapped console In/Out
47 i_need CONSWAP,BYTE
48 i_need IDLEINT,BYTE
49 i_need THISSFT,DWORD
50 i_need DMAADD,DWORD
51 i_need DEVCALL,BYTE
52 i_need CALLSCNT,WORD
53 i_need CALLXAD,DWORD
54 i_need CONTPOS,WORD
55 i_need NEXTADD,WORD
56 i_need CONBUF,BYTE
57 i_need ClusFac,BYTE
58 i_need SecClusPos,BYTE
59 i_need DirSec,DWORD ;AN000;
60 i_need ClusNum,WORD
61 i_need NxtClusNum,WORD
62 i_need ReadOp,BYTE
63 i_need CURBUF,DWORD
64 i_need ALLOWED,BYTE
65 i_need EXTERR_LOCUS,BYTE
66 i_need FastSeekflg,BYTE ;AN000;
67 i_need HIGH_SECTOR,WORD ;AN000;
68 I_need JShare,DWORD ;AN000;
69 i_need DOS34_FLAG,WORD ;AN000;
70
71IF BUFFERFLAG
72
73 i_need BUF_EMS_MODE,BYTE
74 i_need BUF_EMS_LAST_PAGE,BYTE
75 I_need BUF_EMS_FIRST_PAGE,DWORD
76 I_need BUF_EMS_SAFE_FLAG,BYTE
77 I_need BUF_EMS_NPA640,WORD
78 I_need BUF_EMS_PAGE_FRAME,WORD
79 I_need BUF_EMS_PFRAME,WORD
80 I_need LASTBUFFER,DWORD
81
82 extrn save_user_map:near
83 extrn restore_user_map:near
84 extrn Setup_EMS_Buffers:near
85
86ENDIF
87
88Break <SwapCon, Swap Back - Old-style I/O to files>
89; * * * * Drivers for file input from devices * * * *
90
91; Indicate that ther is no more I/O occurring through another SFT outside of
92; handles 0 and 1
93;
94; Inputs: DS is DOSGroup
95; Outputs: CONSWAP is set to false.
96; Registers modified: none
97
98 procedure SWAPBACK,NEAR
99 DOSAssume CS,<DS>,"SwapBack"
100 ASSUME ES:NOTHING
101 MOV BYTE PTR [CONSWAP],0 ; signal no conswaps
102 return
103EndProc SWAPBACK
104
105; Copy ThisSFT to CONSFT for use by the 1-12 primitives.
106;
107; Inputs: ThisSFT as the sft of the desired file
108; DS is DOSGroup
109; Outputs: CONSWAP is set. CONSFT = ThisSFT.
110; Registers modified: none
111 procedure SWAPCON,NEAR
112 DOSAssume CS,<DS>,"SwapCon"
113 ASSUME ES:NOTHING
114 SaveReg <ES,DI>
115 MOV BYTE PTR [CONSWAP],1 ; CONSwap = TRUE;
116 LES DI,ThisSFT
117 Assert ISSFT,<ES,DI>,"SwapCon"
118 MOV WORD PTR CONSFT,DI
119 MOV WORD PTR CONSFT+2,ES
120 RestoreReg <DI,ES>
121 return
122EndProc SWAPCON
123
124Break <DOS_READ -- MAIN READ ROUTINE AND DEVICE IN ROUTINES>
125
126;
127; Inputs:
128; [THISSFT] set to the SFT for the file being used
129; [DMAADD] contains transfer address
130; CX = No. of bytes to read
131; Function:
132; Perform read operation
133; Outputs:
134; Carry clear
135; SFT Position and cluster pointers updated
136; CX = No. of bytes read
137; ES:DI point to SFT
138; Carry set
139; AX is error code
140; CX = 0
141; ES:DI point to SFT
142; DS preserved, all other registers destroyed
143
144 procedure DOS_READ,NEAR
145 DOSAssume CS,<DS>,"DOS_Read"
146 ASSUME ES:NOTHING
147
148IF BUFFERFLAG
149 cmp [BUF_EMS_MODE], -1
150 jz dos_rd_call
151 call choose_buf_page
152 jnc sav_map_rd_hndl
153 return
154sav_map_rd_hndl:
155; call save_user_map
156dos_rd_call:
157ENDIF
158
159
160 LES DI,[THISSFT]
161 Assert ISSFT,<ES,DI>,"DOS_Read"
162;
163; Verify that the sft has been opened in a mode that allows reading.
164;
165 MOV AL,BYTE PTR ES:[DI.sf_mode]
166 AND AL,access_mask
167 CMP AL,open_for_write
168 JNE READ_NO_MODE ;Is read or both
169 transfer SET_ACC_ERR
170
171READ_NO_MODE:
172 invoke SETUP
173 JCXZ NoIORet ; no bytes to read - fast return
174 invoke IsSFTNet
175 JZ LOCAL_READ
176
177; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ?
178; JZ IFS_HAS_SHARE ;AN000;;IFS. yes
179; EnterCrit critDisk ;AN000;;IFS. enter critical section
180; CALL CHECK_READ_LOCK ;AN000;;IFS. check read lock
181; JNC READ_OK2 ;AN000;;IFS. lock check ok
182; JMP SHORT critexit ;AN000;;IFS. fail
183READ_OK2: ;AN000;
184; LeaveCrit critDisk ;AN000;;IFS. leave critical section
185IFS_HAS_SHARE: ;AN000;
186
187IF NOT Installed
188 transfer NET_READ
189ELSE
190 MOV AX,(multNET SHL 8) OR 8
191 INT 2FH
192 return
193ENDIF
194
195;
196; The user ended up requesting 0 bytes of input. We do nothing for this case
197; except return immediately.
198;
199NoIORet:
200 CLC
201 return
202
203LOCAL_READ:
204 TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O
205 JNZ READDEV
206 MOV [EXTERR_LOCUS],errLOC_Disk
207 EnterCrit critDisk
208 TEST [FastSeekflg],Fast_yes ; FastSeek installed ?
209 JZ FS_no ; no
210 OR [FastSeekflg],FS_begin ; set fastseek mode
211FS_no:
212 invoke DISKREAD
213 PUSHF ; save flag
214 AND CS:[FastSeekflg],FS_end ; reset fastseek mode
215 POPF ; retore flag
216critexit:
217 LeaveCrit critDisk
218 return
219
220;
221; We are reading from a device. Examine the status of the device to see if we
222; can short-circuit the I/O. If the device in the EOF state or if it is the
223; null device, we can safely indicate no transfer.
224;
225READDEV:
226 DOSAssume CS,<DS>,"DISK/ReadDev"
227 ASSUME ES:NOTHING
228 MOV [EXTERR_LOCUS],errLOC_SerDev
229 MOV BL,BYTE PTR ES:[DI.sf_flags]
230 LES DI,[DMAADD]
231 TEST BL,devid_device_EOF ; End of file?
232 JZ ENDRDDEVJ3
233 TEST BL,devid_device_null ; NUL device?
234 JZ TESTRAW ; NO
235 XOR AL,AL ; Indicate EOF by setting zero
236ENDRDDEVJ3:
237 JMP ENDRDDEVJ2
238
239;
240; We need to hit the device. Figure out if we do a raw read or we do the
241; bizarre std_con_string_input.
242;
243TESTRAW:
244 TEST BL,devid_device_raw ; Raw mode?
245 JNZ DVRDRAW ; Yes, let the device do all local editing
246 TEST BL,devid_device_con_in ; Is it console device?
247 JZ NOTRDCON
248 JMP READCON
249
250DVRDRAW:
251 DOSAssume CS,<DS>,"DISK/DvRdRaw"
252 PUSH ES
253 POP DS ; Xaddr to DS:DI
254ASSUME DS:NOTHING
255ReadRawRetry:
256 MOV BX,DI ; DS:BX transfer addr
257 XOR AX,AX ; Media Byte, unit = 0
258 MOV DX,AX ; Start at 0
259 invoke SETREAD
260 PUSH DS ; Save Seg part of Xaddr
261 LDS SI,[THISSFT]
262 Assert ISSFT,<DS,SI>,"DOS_Read/DvRdRawR"
263 invoke DEVIOCALL
264 MOV DX,DI ; DS:DX is preserved by INT 24
265 MOV AH,86H ; Read error
266 MOV DI,[DEVCALL.REQSTAT]
267 TEST DI,STERR
268 JZ CRDROK ; No errors
269 invoke CHARHARD
270 MOV DI,DX ; DS:DI is Xaddr
271 OR AL,AL
272 JZ CRDROK ; Ignore
273 CMP AL,3
274 JZ CRDFERR ; fail.
275 POP DS ; Recover saved seg part of Xaddr
276 JMP ReadRawRetry ; Retry
277
278;
279; We have encountered a device-driver error. We have informed the user of it
280; and he has said for us to fail the system call.
281;
282CRDFERR:
283 POP DI ; Clean stack
284DEVIOFERR:
285 LES DI,[THISSFT]
286 Assert ISSFT,<ES,DI>,"DOS_Read/DEVIOFERR"
287 transfer SET_ACC_ERR_DS
288
289CRDROK:
290 POP DI ; Chuck saved seg of Xaddr
291 MOV DI,DX
292 ADD DI,[CALLSCNT] ; Amount transferred
293 JMP SHORT ENDRDDEVJ3
294
295; We are going to do a cooked read on some character device. There is a
296; problem here, what does the data look like? Is it a terminal device, line
297; CR line CR line CR, or is it file data, line CR LF line CR LF? Does it have
298; a ^Z at the end which is data, or is the ^Z not data? In any event we're
299; going to do this: Read in pieces up to CR (CRs included in data) or ^z (^z
300; included in data). this "simulates" the way con works in cooked mode
301; reading one line at a time. With file data, however, the lines will look
302; like, LF line CR. This is a little weird.
303
304NOTRDCON:
305 MOV AX,ES
306 MOV DS,AX
307ASSUME DS:NOTHING
308 MOV BX,DI
309 XOR DX,DX
310 MOV AX,DX
311 PUSH CX
312 MOV CX,1
313 invoke SETREAD
314 POP CX
315 LDS SI,[THISSFT]
316 Assert ISSFT,<DS,SI>,"DOS_Read/NotRdCon"
317 LDS SI,[SI.sf_devptr]
318DVRDLP:
319 invoke DSKSTATCHK
320 invoke DEVIOCALL2
321 PUSH DI ; Save "count" done
322 MOV AH,86H
323 MOV DI,[DEVCALL.REQSTAT]
324 TEST DI,STERR
325 JZ CRDOK
326 invoke CHARHARD
327 POP DI
328 MOV [CALLSCNT],1
329 CMP AL,1
330 JZ DVRDLP ;Retry
331 CMP AL,3
332 JZ DEVIOFERR ; FAIL
333 XOR AL,AL ; Ignore, Pick some random character
334 JMP SHORT DVRDIGN
335
336CRDOK:
337 POP DI
338 CMP [CALLSCNT],1
339 JNZ ENDRDDEVJ2
340 PUSH DS
341 MOV DS,WORD PTR [CALLXAD+2]
342 MOV AL,BYTE PTR [DI] ; Get the character we just read
343 POP DS
344DVRDIGN:
345 INC WORD PTR [CALLXAD] ; Next character
346 MOV [DEVCALL.REQSTAT],0
347 INC DI ; Next character
348 CMP AL,1AH ; ^Z?
349 JZ ENDRDDEVJ2 ; Yes, done zero set (EOF)
350 CMP AL,c_CR ; CR?
351 LOOPNZ DVRDLP ; Loop if no, else done
352 INC AX ; Resets zero flag so NOT EOF, unless
353 ; AX=FFFF which is not likely
354ENDRDDEVJ2:
355 JMP SHORT ENDRDDEV
356
357ASSUME DS:NOTHING,ES:NOTHING
358
359TRANBUF:
360 LODSB
361 STOSB
362 CMP AL,c_CR ; Check for carriage return
363 JNZ NORMCH
364 MOV BYTE PTR [SI],c_LF
365NORMCH:
366 CMP AL,c_LF
367 LOOPNZ TRANBUF
368 JNZ ENDRDCON
369 XOR SI,SI ; Cause a new buffer to be read
370 invoke OUTT ; Transmit linefeed
371 OR AL,1 ; Clear zero flag--not end of file
372ENDRDCON:
373 Context DS
374 CALL SWAPBACK
375 MOV [CONTPOS],SI
376ENDRDDEV:
377 Context DS
378 MOV [NEXTADD],DI
379 JNZ SETSFTC ; Zero set if Ctrl-Z found in input
380 LES DI,[THISSFT]
381 Assert ISSFT,<ES,DI>,"DOS_Read/EndRdDev"
382 AND BYTE PTR ES:[DI.sf_flags],NOT devid_device_EOF ; Mark as no more data available
383SETSFTC:
384 invoke SETSFT
385 return
386
387ASSUME DS:NOTHING,ES:NOTHING
388
389READCON:
390 DOSAssume CS,<DS>,"ReadCon"
391 CALL SWAPCON
392 MOV SI,[CONTPOS]
393 OR SI,SI
394 JNZ TRANBUF
395 CMP BYTE PTR [CONBUF],128
396 JZ GETBUF
397 MOV WORD PTR [CONBUF],0FF80H ; Set up 128-byte buffer with no template
398GETBUF:
399 PUSH CX
400 PUSH ES
401 PUSH DI
402 MOV DX,OFFSET DOSGROUP:CONBUF
403 invoke $STD_CON_STRING_INPUT ; Get input buffer
404 POP DI
405 POP ES
406 POP CX
407 MOV SI,2 + OFFSET DOSGROUP:CONBUF
408 CMP BYTE PTR [SI],1AH ; Check for Ctrl-Z in first character
409 JNZ TRANBUF
410 MOV AL,1AH
411 STOSB
412 DEC DI
413 MOV AL,c_LF
414 invoke OUTT ; Send linefeed
415 XOR SI,SI
416 JMP ENDRDCON
417
418EndProc DOS_READ
419
420Break <DOS_WRITE -- MAIN WRITE ROUTINE AND DEVICE OUT ROUTINES>
421
422;
423; Inputs:
424; [THISSFT] set to the SFT for the file being used
425; [DMAADD] contains transfer address
426; CX = No. of bytes to write
427; Function:
428; Perform write operation
429; NOTE: If CX = 0 on input, file is truncated or grown
430; to current sf_position
431; Outputs:
432; Carry clear
433; SFT Position and cluster pointers updated
434; CX = No. of bytes written
435; ES:DI point to SFT
436; Carry set
437; AX is error code
438; CX = 0
439; ES:DI point to SFT
440; DS preserved, all other registers destroyed
441
442 procedure DOS_WRITE,NEAR
443 DOSAssume CS,<DS>,"DOS_Write"
444 ASSUME ES:NOTHING
445
446IF BUFFERFLAG
447 cmp [BUF_EMS_MODE], -1
448 jz dos_wrt_call
449 call choose_buf_page
450 jnc sav_map_wrt_hndl
451 return
452sav_map_wrt_hndl:
453; call save_user_map
454dos_wrt_call:
455ENDIF
456
457
458 LES DI,[THISSFT]
459 Assert ISSFT,<ES,DI>,"DosWrite"
460 MOV AL,BYTE PTR ES:[DI.sf_mode]
461 AND AL,access_mask
462 CMP AL,open_for_read
463 JNE Check_FCB_RO ;Is write or both
464BadMode:
465 transfer SET_ACC_ERR
466
467;
468; NOTE: The following check for writting to a Read Only File is performed
469; ONLY on FCBs!!!!
470; We ALLOW writes to Read Only files via handles to allow a CREATE
471; of a read only file which can then be written to.
472; This is OK because we are NOT ALLOWED to OPEN a RO file via handles
473; for writting, or RE-CREATE an EXISTING RO file via handles. Thus,
474; CREATing a NEW RO file, or RE-CREATing an existing file which
475; is NOT RO to be RO, via handles are the only times we can write
476; to a read-only file.
477;
478Check_FCB_RO:
479 TEST ES:[DI.sf_mode],sf_isfcb
480 JZ WRITE_NO_MODE ; Not an FCB
481 TEST ES:[DI].sf_attr,attr_read_only
482 JNZ BadMode ; Can't write to Read_Only files via FCB
483WRITE_NO_MODE:
484 invoke SETUP
485 invoke IsSFTNet
486 JZ LOCAL_WRITE
487
488; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ?
489; JZ IFS_HAS_SHARE2 ;AN000;;IFS. yes
490; EnterCrit critDisk ;AN000;;IFS. enter critical section
491; CALL CHECK_WRITE_LOCK ;AN000;;IFS. check write lock
492; JC nocommit ;AN000;;IFS. lock error
493;
494; LeaveCrit critDisk ;AN000;;IFS. leave critical section
495IFS_HAS_SHARE2: ;AN000;
496
497
498IF NOT Installed
499 transfer NET_WRITE
500ELSE
501 MOV AX,(multNET SHL 8) OR 9
502 INT 2FH
503; JC nomore ;AN000;;IFS. error
504; invoke OWN_SHARE ;AN000;;IFS. IFS owns share ?
505; JZ nomore ;AN000;;IFS. yes
506;
507; MOV AX,1 ;AN000;;IFS. update all SFT for new size
508; call JShare + 14 * 4 ;AN000;;IFS. call ShSu
509
510nomore: ;AN000;
511 return
512ENDIF
513
514
515LOCAL_WRITE:
516 TEST ES:[DI.sf_flags],devid_device ; Check for named device I/O
517 JNZ WRTDEV
518 MOV [EXTERR_LOCUS],errLOC_Disk
519 EnterCrit critDisk
520 TEST [FastSeekflg],Fast_yes ;AN000;FO. FastSeek installed ?
521 JZ FS_no2 ;AN000;FO. no
522 OR [FastSeekflg],FS_begin ;AN000;FO. set fastseek mode
523FS_no2: ;AN000;
524 invoke DISKWRITE
525 PUSHF ;AN000;FO. save flag
526 AND CS:[FastSeekflg],FS_end ;AN000;FO. reset fastseek mode
527 POPF ;AN000;FO. restore flag
528;; Extended Open
529 JC nocommit ;AN000;EO.
530 LES DI,[THISSFT] ;AN000;EO.
531 TEST ES:[DI.sf_mode],auto_commit_write ;AN000;EO.
532 JZ nocommit ;AN000;EO.
533 PUSH CX ;AN000;EO.
534 invoke DOS_COMMIT ;AN000;EO.
535 POP CX ;AN000;EO.
536nocommit: ;AN000;
537;; Extended Open
538 LeaveCrit critDisk
539 return
540
541DVWRTRAW:
542ASSUME DS:NOTHING
543 XOR AX,AX ; Media Byte, unit = 0
544 invoke SETWRITE
545 PUSH DS ; Save seg of transfer
546 LDS SI,[THISSFT]
547 Assert ISSFT,<DS,SI>,"DosWrite/DvWrtRaw"
548 invoke DEVIOCALL ; DS:SI -> DEVICE
549 MOV DX,DI ; Offset part of Xaddr saved in DX
550 MOV AH,87H
551 MOV DI,[DEVCALL.REQSTAT]
552 TEST DI,STERR
553 JZ CWRTROK
554 invoke CHARHARD
555 MOV BX,DX ; Recall transfer addr
556 OR AL,AL
557 JZ CWRTROK ; Ignore
558 CMP AL,3
559 JZ CWRFERR
560 POP DS ; Recover saved seg of transfer
561 JMP DVWRTRAW ; Try again
562
563CWRFERR:
564 POP AX ; Chuck saved seg of transfer
565 JMP CRDFERR ; Will pop one more stack element
566
567CWRTROK:
568 POP AX ; Chuck saved seg of transfer
569 POP DS
570 DOSAssume CS,<DS>,"DISK/CWrtOK"
571 MOV AX,[CALLSCNT] ; Get actual number of bytes transferred
572ENDWRDEV:
573 LES DI,[THISSFT]
574 Assert ISSFT,<ES,DI>,"DosWrite/EndWrDev"
575 MOV CX,AX
576 invoke ADDREC
577 return
578
579WRTNUL:
580 MOV DX,CX ;Entire transfer done
581WrtCookJ:
582 JMP WRTCOOKDONE
583
584WRTDEV:
585 DOSAssume CS,<DS>,"DISK/WrtDev"
586 MOV [EXTERR_LOCUS],errLOC_SerDev
587 OR BYTE PTR ES:[DI.sf_flags],devid_device_EOF ; Reset EOF for input
588 MOV BL,BYTE PTR ES:[DI.sf_flags]
589 XOR AX,AX
590 JCXZ ENDWRDEV ; problem of creating on a device.
591 PUSH DS
592 MOV AL,BL
593 LDS BX,[DMAADD] ; Xaddr to DS:BX
594ASSUME DS:NOTHING
595 MOV DI,BX ; Xaddr to DS:DI
596 XOR DX,DX ; Set starting point
597 TEST AL,devid_device_raw ; Raw?
598 JZ TEST_DEV_CON
599 JMP DVWRTRAW
600
601TEST_DEV_CON:
602 TEST AL,devid_device_con_out ; Console output device?
603 JNZ WRITECON
604 TEST AL,devid_device_null
605 JNZ WRTNUL
606 MOV AX,DX
607 CMP BYTE PTR [BX],1AH ; ^Z?
608 JZ WRTCOOKJ ; Yes, transfer nothing
609 PUSH CX
610 MOV CX,1
611 invoke SETWRITE
612 POP CX
613 LDS SI,[THISSFT]
614 OR CS:[DOS34_FLAG],X25_Special;AN000;;PTM. bad x25 driver
615 MOV AH,3 ;AN000;;PTM. prompt critical error ASAP
616 invoke IOFUNC ;AN000;;PTM.
617 Assert ISSFT,<DS,SI>,"DosWrite/TestDevCon"
618 LDS SI,[SI.sf_devptr]
619DVWRTLP:
620 invoke DSKSTATCHK
621 invoke DEVIOCALL2
622 PUSH DI
623 MOV AH,87H
624 MOV DI,[DEVCALL.REQSTAT]
625 TEST DI,STERR
626 JZ CWROK
627 invoke CHARHARD
628 POP DI
629 MOV [CALLSCNT],1
630 CMP AL,1
631 JZ DVWRTLP ; Retry
632 OR AL,AL
633 JZ DVWRTIGN ; Ignore
634 JMP CRDFERR ; Fail, pops one stack element
635
636CWROK:
637 POP DI
638 CMP [CALLSCNT],0
639 JZ WRTCOOKDONE
640DVWRTIGN:
641 INC DX
642 INC WORD PTR [CALLXAD]
643 INC DI
644 PUSH DS
645 MOV DS,WORD PTR [CALLXAD+2]
646 CMP BYTE PTR [DI],1AH ; ^Z?
647 POP DS
648 JZ WRTCOOKDONE
649 MOV [DEVCALL.REQSTAT],0
650 LOOP DVWRTLP
651WRTCOOKDONE:
652 MOV AX,DX
653 POP DS
654 JMP ENDWRDEV
655
656WRITECON:
657 PUSH DS
658 Context DS
659 CALL SWAPCON
660 POP DS
661ASSUME DS:NOTHING
662 MOV SI,BX
663 PUSH CX
664WRCONLP:
665 LODSB
666 CMP AL,1AH ; ^Z?
667 JZ CONEOF
668 invoke OUTT
669 LOOP WRCONLP
670CONEOF:
671 POP AX ; Count
672 SUB AX,CX ; Amount actually written
673 POP DS
674 DOSAssume CS,<DS>,"DISK/ConEOF"
675 CALL SWAPBACK
676 JMP ENDWRDEV
677EndProc DOS_WRITE
678
679; Convert JFN number in BX to sf_entry in DS:SI We get the normal SFT if
680; CONSWAP is FALSE or if the handle desired is 2 or more. Otherwise, we
681; retrieve the sft from ConSFT which is set by SwapCon.
682
683 procedure get_io_sft,near
684ASSUME DS:NOTHING,ES:NOTHING
685 TEST ConSwap,-1
686 JNZ GetRedir
687GetNormal:
688 Context DS
689 PUSH ES
690 PUSH DI
691 invoke SFFromHandle
692 JC RET44P
693 MOV SI,ES
694 MOV DS,SI
695ASSUME DS:NOTHING
696 MOV SI,DI
697RET44P:
698 POP DI
699 POP ES
700 return
701GetRedir:
702 CMP BX,1
703 JA GetNormal
704 LDS SI,ConSFT
705 Assert ISSFT,<DS,SI>,"GetIOSft"
706 CLC
707 return
708EndProc get_io_sft
709
710Break <DIRREAD -- READ A DIRECTORY SECTOR>
711
712; Inputs:
713; AX = Directory block number (relative to first block of directory)
714; ES:BP = Base of drive parameters
715; [DIRSEC] = First sector of first cluster of directory
716; [CLUSNUM] = Next cluster
717; [CLUSFAC] = Sectors/Cluster
718; Function:
719; Read the directory block into [CURBUF].
720; Outputs:
721; [NXTCLUSNUM] = Next cluster (after the one skipped to)
722; [SECCLUSPOS] Set
723; ES:BP unchanged
724; [CURBUF] Points to Buffer with dir sector
725; Carry set if error (user said FAIL to I 24)
726; DS preserved, all other registers destroyed.
727
728 procedure DirRead,NEAR
729 DOSAssume CS,<DS>,"DirRead"
730 ASSUME ES:NOTHING
731 Assert ISDPB,<ES,BP>,"DirRead"
732
733;
734; Note that ClusFac is is the sectors per cluster. This is NOT necessarily
735; the same as what is in the DPB! In the case of the root directory, we have
736; ClusFac = # sectors in the root directory. The root directory is detected
737; by DIRStart = 0.
738;
739 XOR DX,DX
740 CMP DirStart,0
741 jnz SubDir
742 XCHG AX,DX
743 JMP DoRead
744;
745; Convert the sector number in AX into cluster and sector-within-cluster pair
746;
747SubDir:
748 MOV DL,AL
749 AND DL,ES:[BP.dpb_cluster_mask]
750;
751; DX is the sector-in-cluster
752;
753 MOV CL,ES:[BP.dpb_cluster_shift]
754 SHR AX,CL
755;
756; DX is position in cluster
757; AX is number of clusters to skip
758;
759DoRead:
760 MOV [SECCLUSPOS],DL
761 MOV CX,AX
762 MOV AH,DL
763;
764; CX is number of clusters to skip.
765; AH is remainder
766;
767 MOV DX,WORD PTR [DIRSEC+2] ;AN000;>32mb
768 MOV [HIGH_SECTOR],DX ;AN000;>32mb
769 MOV DX,WORD PTR [DIRSEC]
770 ADD DL,AH
771 ADC DH,0
772 ADC [HIGH_SECTOR],0 ;AN000;>32mb
773
774 MOV BX,[CLUSNUM]
775 MOV [NXTCLUSNUM],BX
776 JCXZ FIRSTCLUSTER
777SKPCLLP:
778 invoke UNPACK
779 retc
780 XCHG BX,DI
781 invoke IsEOF ; test for eof based on fat size
782 JAE HAVESKIPPED
783 LOOP SKPCLLP
784HAVESKIPPED:
785 MOV [NXTCLUSNUM],BX
786 MOV DX,DI
787 MOV BL,AH
788 invoke FIGREC
789
790 entry FIRSTCLUSTER
791
792 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
793 XOR AL,AL ; Indicate pre-read
794 invoke GETBUFFR
795 retc
796
797 entry SET_BUF_AS_DIR
798 DOSAssume CS,<DS>,"SET_BUF_AS_DIR"
799 ASSUME ES:NOTHING
800; Set the type of CURBUF to be a directory sector.
801; Only flags are modified.
802
803 PUSH DS
804 PUSH SI
805 LDS SI,[CURBUF]
806 Assert ISBUF,<DS,SI>,"SetBufAsDir"
807 OR [SI.buf_flags],buf_isDIR ; Clears carry
808 POP SI
809 POP DS
810 return
811EndProc DirRead
812
813Break <FATSECRD -- READ A FAT SECTOR>
814
815; Inputs:
816; Same as DREAD
817; DS:BX = Transfer address
818; CX = Number of sectors
819; DX = Absolute record number
820; ES:BP = Base of drive parameters
821; Function:
822; Calls BIOS to perform FAT read.
823; Outputs:
824; Same as DREAD
825
826 procedure FATSecRd,NEAR
827ASSUME DS:NOTHING,ES:NOTHING
828
829 Assert ISDPB,<ES,BP>,"FATSecRd"
830 MOV [ALLOWED],allowed_RETRY + allowed_FAIL
831 MOV DI,CX
832 MOV CL,ES:[BP.dpb_FAT_count]
833 MOV AX,ES:[BP.dpb_FAT_size] ;AN000;>32mb
834; XOR AH,AH
835 XOR CH,CH ;AN000;>32mb
836 PUSH DX
837NXTFAT:
838 MOV [HIGH_SECTOR],0 ;AN000;>32mb FAT sectors cannot exceed
839 PUSH CX ;AN000;>32mb
840 PUSH AX
841 MOV CX,DI
842 invoke DSKREAD
843 POP AX
844 POP CX
845 JZ RET41P ; Carry clear
846 ADD DX,AX
847 LOOP NXTFAT
848 POP DX
849 MOV CX,DI
850
851; NOTE FALL THROUGH
852
853Break <DREAD -- DO A DISK READ>
854
855; Inputs:
856; DS:BX = Transfer address
857; CX = Number of sectors
858; DX = Absolute record number (LOW)
859; [HIGH_SECTOR]= Absolute record number (HIGH)
860; ES:BP = Base of drive parameters
861; [ALLOWED] must be set in case call to HARDERR needed
862; Function:
863; Calls BIOS to perform disk read. If BIOS reports
864; errors, will call HARDERRRW for further action.
865; Outputs:
866; Carry set if error (currently user FAILED to INT 24)
867; DS,ES:BP preserved. All other registers destroyed.
868
869 entry DREAD
870ASSUME DS:NOTHING,ES:NOTHING
871
872 Assert ISDPB,<ES,BP>,"DREAD"
873 invoke DSKREAD
874 retz ; Carry clear
875 MOV BYTE PTR [READOP],0
876 invoke HARDERRRW
877 CMP AL,1 ; Check for retry
878 JZ DREAD
879 CMP AL,3 ; Check for FAIL
880 CLC
881 JNZ NO_CAR ; Ignore
882 STC
883NO_CAR:
884 return
885
886RET41P: POP DX
887 return
888EndProc FATSecRd
889
890
891Break <CHECK_WRITE_LOCK>
892
893; Inputs:
894; output of SETUP
895; ES:DI -> SFT
896; Function:
897; check write lock
898; Outputs:
899; Carry set if error
900; Carry clear if ok
901
902 procedure CHECK_WRITE_LOCK,NEAR ;AN000;
903ASSUME DS:NOTHING,ES:NOTHING ;AN000;
904
905 TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id
906 JZ write_cont ;AN000;;MS. no
907 invoke SET_ACC_ERR_DS ;AN000;;MS.
908 return ;AN000;;MS.
909write_cont: ;AN000;
910 PUSH CX ;AN000;;MS. save reg
911 OR CX,CX ;AN000;;MS.
912 JNZ Not_Truncate ;AN000;;MS.
913 MOV CX,0FFFFH ;AN000;;MS. check for lock on whole file
914Not_Truncate: ;AN000;
915 MOV AL,80H ;AN000;;MS. check write access
916 invoke LOCK_CHECK ;AN000;;MS. check lock
917 POP CX ;AN000;;MS. restore reg
918 JNC WRITE_OK ;AN000;;MS. lock ok
919 invoke WRITE_LOCK_VIOLATION ;AN000;;MS. issue I24
920 JNC CHECK_WRITE_LOCK ;AN000;;MS. retry
921WRITE_OK: ;AN000;
922 return ;AN000;;MS.
923EndProc CHECK_WRITE_LOCK ;AN000;
924
925
926Break <CHECK_READ_LOCK>
927
928; Inputs:
929; ES:DI -> SFT
930; output of SETUP
931; Function:
932; check read lock
933; Outputs:
934; Carry set if error
935; Carry clear if ok
936
937 procedure CHECK_READ_LOCK,NEAR ;AN000;
938ASSUME DS:NOTHING,ES:NOTHING ;AN000;
939
940 TEST ES:[DI].sf_attr,attr_volume_id ;AN000;;MS. volume id
941 JZ do_retry ;AN000;;MS. no
942 invoke SET_ACC_ERR ;AN000;;MS.
943 return ;AN000;;MS.
944do_retry: ;AN000;
945 MOV AL,0 ;AN000;;MS. check read access
946 invoke LOCK_CHECK ;AN000;;MS. check lock
947 JNC READ_OK ;AN000;;MS. lock ok
948 invoke READ_LOCK_VIOLATION ;AN000;;MS. issue I24
949 JNC CHECK_READ_LOCK ;AN000;;MS. retry
950READ_OK: ;AN000; MS.
951 return ;AN000;;MS.
952EndProc CHECK_READ_LOCK ;AN000;
953
954IF BUFFERFLAG
955
956;-------------------------------------------------------------------------
957; Function name : choose_buf_page
958; Inputs : DMAADD = Xaddr
959; cx = # of bytes to transfer
960; Outputs : if NC
961;
962; SAFE_FLAG - 0 ==> page is safe. no need to
963; detect collision between
964; user & system buffer.
965; SAFE_FLAG - 1 ==> page is unsafe. Must check
966; for collision
967;
968; CY - error
969;
970;
971; High Level Alogrithm:
972;
973; 1. If Xaddr. is above the first physical page above 640K
974; 2. choose that page
975; 3. set safe flag
976; 4. else
977; 5. choose highest page above 640K
978; 6. If 6 or more pages above 640k
979; 7. Set safe flag
980; 8. else
981; 9. if Xaddr. + # of bytes to transfer does not spill into the
982; chosen page
983; 10. set safe flag
984; 11.else
985; 12. clear safe flag
986; 13.endif
987; 14.endif
988; 15.endif
989;
990;----------------------------------------------------------------------------
991Procedure choose_buf_page,near
992
993 assume cs:dosgroup, ds:nothing, es:nothing, ss:dosgroup
994
995 push cx
996 push bx
997 push dx
998 push si
999 push ds
1000 push ax
1001
1002 mov ax, word ptr [DMAADD+2]
1003 and ax, 0fc00h ; page segment of transfer segment
1004
1005 cmp ax, word ptr [BUF_EMS_FIRST_PAGE]
1006 ja pick_first
1007
1008 cmp [BUF_EMS_NPA640], 6
1009 jae safe_pick_last
1010
1011 add cx, word ptr [DMAADD] ; get final offset
1012 mov bx, cx
1013
1014 mov cl, 4
1015 shr bx, cl ; get # of paragraphs
1016 mov ax, word ptr [DMAADD+2] ; get initial segment
1017 add ax, bx ; get final segment
1018
1019 and ax, 0fc00h
1020 cmp ax, word ptr [BUF_EMS_LAST_PAGE]
1021 jne safe_pick_last
1022
1023 mov [BUF_EMS_SAFE_FLAG], 0
1024 jmp fin_choose_page
1025
1026safe_pick_last:
1027 mov [BUF_EMS_SAFE_FLAG], 1
1028 jmp fin_choose_page
1029
1030;pick_last:
1031; mov ax, word ptr [BUF_EMS_LAST_PAGE]
1032; mov [BUF_EMS_PFRAME], ax
1033; mov ax, word ptr [BUF_EMS_LAST_PAGE+2]
1034; mov [BUF_EMS_PAGE_FRAME], ax
1035; xor ax, ax
1036; jmp fin_choose_page
1037
1038pick_first:
1039 mov ax, word ptr [BUF_EMS_FIRST_PAGE]
1040 cmp [BUF_EMS_PFRAME], ax
1041 je fin_choose_page
1042 call restore_user_map
1043 mov word ptr [LASTBUFFER], -1
1044 mov [BUF_EMS_PFRAME], ax
1045 mov ax, word ptr [BUF_EMS_FIRST_PAGE+2]
1046 mov [BUF_EMS_PAGE_FRAME], ax
1047 mov [BUF_EMS_SAFE_FLAG], 1
1048 call Setup_EMS_Buffers
1049 call save_user_map
1050 jmp fin_choose_page
1051
1052err_choose_page:
1053 stc
1054
1055fin_choose_page:
1056 clc
1057
1058 pop ax
1059 pop ds
1060 pop si
1061 pop dx
1062 pop bx
1063 pop cx
1064 return
1065
1066EndProc choose_buf_page
1067
1068ENDIF
1069
1070CODE ENDS
1071 END
1072
1073