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

wirehaze git hosting

MZ is back!
[MS-DOS.git] / v4.0 / src / DOS / DISK.ASM
1 ; SCCSID = @(#)disk.asm 1.1 85/04/10
2 ; SCCSID = @(#)disk.asm 1.1 85/04/10
3 TITLE DISK - Disk utility routines
4 NAME 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
29 include dosseg.asm
30 include fastseek.inc ;AN000;
31 include fastxxxx.inc ;AN000;
32
33 CODE SEGMENT BYTE PUBLIC 'CODE'
34 ASSUME SS:DOSGROUP,CS:DOSGROUP
35
36 .xcref
37 INCLUDE DOSSYM.INC
38 INCLUDE DEVSYM.INC
39 include version.inc
40 .cref
41 .list
42
43 Installed = 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
71 IF 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
86 ENDIF
87
88 Break <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
103 EndProc 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
122 EndProc SWAPCON
123
124 Break <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
148 IF 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
154 sav_map_rd_hndl:
155 ; call save_user_map
156 dos_rd_call:
157 ENDIF
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
171 READ_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
183 READ_OK2: ;AN000;
184 ; LeaveCrit critDisk ;AN000;;IFS. leave critical section
185 IFS_HAS_SHARE: ;AN000;
186
187 IF NOT Installed
188 transfer NET_READ
189 ELSE
190 MOV AX,(multNET SHL 8) OR 8
191 INT 2FH
192 return
193 ENDIF
194
195 ;
196 ; The user ended up requesting 0 bytes of input. We do nothing for this case
197 ; except return immediately.
198 ;
199 NoIORet:
200 CLC
201 return
202
203 LOCAL_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
211 FS_no:
212 invoke DISKREAD
213 PUSHF ; save flag
214 AND CS:[FastSeekflg],FS_end ; reset fastseek mode
215 POPF ; retore flag
216 critexit:
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 ;
225 READDEV:
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
236 ENDRDDEVJ3:
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 ;
243 TESTRAW:
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
250 DVRDRAW:
251 DOSAssume CS,<DS>,"DISK/DvRdRaw"
252 PUSH ES
253 POP DS ; Xaddr to DS:DI
254 ASSUME DS:NOTHING
255 ReadRawRetry:
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 ;
282 CRDFERR:
283 POP DI ; Clean stack
284 DEVIOFERR:
285 LES DI,[THISSFT]
286 Assert ISSFT,<ES,DI>,"DOS_Read/DEVIOFERR"
287 transfer SET_ACC_ERR_DS
288
289 CRDROK:
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
304 NOTRDCON:
305 MOV AX,ES
306 MOV DS,AX
307 ASSUME 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]
318 DVRDLP:
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
336 CRDOK:
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
344 DVRDIGN:
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
354 ENDRDDEVJ2:
355 JMP SHORT ENDRDDEV
356
357 ASSUME DS:NOTHING,ES:NOTHING
358
359 TRANBUF:
360 LODSB
361 STOSB
362 CMP AL,c_CR ; Check for carriage return
363 JNZ NORMCH
364 MOV BYTE PTR [SI],c_LF
365 NORMCH:
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
372 ENDRDCON:
373 Context DS
374 CALL SWAPBACK
375 MOV [CONTPOS],SI
376 ENDRDDEV:
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
383 SETSFTC:
384 invoke SETSFT
385 return
386
387 ASSUME DS:NOTHING,ES:NOTHING
388
389 READCON:
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
398 GETBUF:
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
418 EndProc DOS_READ
419
420 Break <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
446 IF 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
452 sav_map_wrt_hndl:
453 ; call save_user_map
454 dos_wrt_call:
455 ENDIF
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
464 BadMode:
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 ;
478 Check_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
483 WRITE_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
495 IFS_HAS_SHARE2: ;AN000;
496
497
498 IF NOT Installed
499 transfer NET_WRITE
500 ELSE
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
510 nomore: ;AN000;
511 return
512 ENDIF
513
514
515 LOCAL_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
523 FS_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.
536 nocommit: ;AN000;
537 ;; Extended Open
538 LeaveCrit critDisk
539 return
540
541 DVWRTRAW:
542 ASSUME 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
563 CWRFERR:
564 POP AX ; Chuck saved seg of transfer
565 JMP CRDFERR ; Will pop one more stack element
566
567 CWRTROK:
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
572 ENDWRDEV:
573 LES DI,[THISSFT]
574 Assert ISSFT,<ES,DI>,"DosWrite/EndWrDev"
575 MOV CX,AX
576 invoke ADDREC
577 return
578
579 WRTNUL:
580 MOV DX,CX ;Entire transfer done
581 WrtCookJ:
582 JMP WRTCOOKDONE
583
584 WRTDEV:
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
594 ASSUME 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
601 TEST_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]
619 DVWRTLP:
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
636 CWROK:
637 POP DI
638 CMP [CALLSCNT],0
639 JZ WRTCOOKDONE
640 DVWRTIGN:
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
651 WRTCOOKDONE:
652 MOV AX,DX
653 POP DS
654 JMP ENDWRDEV
655
656 WRITECON:
657 PUSH DS
658 Context DS
659 CALL SWAPCON
660 POP DS
661 ASSUME DS:NOTHING
662 MOV SI,BX
663 PUSH CX
664 WRCONLP:
665 LODSB
666 CMP AL,1AH ; ^Z?
667 JZ CONEOF
668 invoke OUTT
669 LOOP WRCONLP
670 CONEOF:
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
677 EndProc 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
684 ASSUME DS:NOTHING,ES:NOTHING
685 TEST ConSwap,-1
686 JNZ GetRedir
687 GetNormal:
688 Context DS
689 PUSH ES
690 PUSH DI
691 invoke SFFromHandle
692 JC RET44P
693 MOV SI,ES
694 MOV DS,SI
695 ASSUME DS:NOTHING
696 MOV SI,DI
697 RET44P:
698 POP DI
699 POP ES
700 return
701 GetRedir:
702 CMP BX,1
703 JA GetNormal
704 LDS SI,ConSFT
705 Assert ISSFT,<DS,SI>,"GetIOSft"
706 CLC
707 return
708 EndProc get_io_sft
709
710 Break <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 ;
747 SubDir:
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 ;
759 DoRead:
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
777 SKPCLLP:
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
784 HAVESKIPPED:
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
811 EndProc DirRead
812
813 Break <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
827 ASSUME 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
837 NXTFAT:
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
853 Break <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
870 ASSUME 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
883 NO_CAR:
884 return
885
886 RET41P: POP DX
887 return
888 EndProc FATSecRd
889
890
891 Break <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;
903 ASSUME 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.
909 write_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
914 Not_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
921 WRITE_OK: ;AN000;
922 return ;AN000;;MS.
923 EndProc CHECK_WRITE_LOCK ;AN000;
924
925
926 Break <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;
938 ASSUME 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.
944 do_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
950 READ_OK: ;AN000; MS.
951 return ;AN000;;MS.
952 EndProc CHECK_READ_LOCK ;AN000;
953
954 IF 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 ;----------------------------------------------------------------------------
991 Procedure 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
1026 safe_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
1038 pick_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
1052 err_choose_page:
1053 stc
1054
1055 fin_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
1066 EndProc choose_buf_page
1067
1068 ENDIF
1069
1070 CODE ENDS
1071 END
1072
1073 \1a