2 ; xenix file calls for MSDOS
11 CODE SEGMENT BYTE PUBLIC 'CODE'
12 ASSUME
SS:DOSGROUP
,CS:DOSGROUP
21 TITLE XENIX
- IO system to mimic UNIX
40 i_need CurrentPDB
,WORD
41 i_need sft_addr
,DWORD ; pointer to head of table
42 i_need CURBUF
,DWORD ; pointer to current buffer
43 i_need DMAADD
,DWORD ; pointer to current dma address
48 DATA SEGMENT BYTE PUBLIC 'DATA'
58 CODE SEGMENT BYTE PUBLIC 'CODE'
61 BREAK <get_sf_from_sfn
- translate a sfn
into sf pointer
>
64 ; input: AX has sfn (0 based)
71 procedure get_sf_from_sfn
,NEAR
72 ASSUME
DS:DOSGROUP
,ES:NOTHING
73 PUSH AX ; we trash AX in process
77 CMP DI,-1 ; end of chain of tables?
78 JZ get_sf_invalid
; I guess so...
79 SUB AX,ES:[DI].sft_count
; chop number of entries in this table
80 JL get_sf_gotten
; sfn is in this table
81 LES DI,ES:[DI].sft_link
; step to next table
85 ADD AX,ES:[DI].sft_count
; reset to index in this table
88 MUL BL ; number of bytes offset into table
90 ADD AX,sft_table
; offset into sf table structure
91 ADD DI,AX ; offset into memory
101 POP AX ; remember him?
105 BREAK <get_sf_from_jfn
- translate a jfn
into sf pointer
>
108 ; input: BX is jfn 0 based
110 ; output: JNC <found>
113 ; ES,DI is indeterminate
115 procedure get_sf_from_jfn
,NEAR
116 ASSUME
DS:DOSGROUP
,ES:NOTHING
118 invoke get_jfn_pointer
119 JC get_sf_jfn_invalid
120 MOV AL,ES:[DI] ; get sfn
121 CMP AL,0FFh ; is it free?
122 JZ get_sf_jfn_invalid
; yep... error
124 invoke get_sf_from_sfn
; check this sfn out...
125 JMP SHORT get_sf_jfn_ret
; condition codes are properly set
129 BREAK <get_jfn_pointer
- map a jfn
into a pointer to jfn
>
134 ; output: JNC <found>
135 ; ES:DI is pointer to jfn
138 procedure Get_jfn_pointer
,NEAR
139 ASSUME
DS:DOSGROUP
,ES:NOTHING
154 BREAK <$Close
- release a handle
>
162 ; AX = error_invalid_handle
164 procedure $Close
,NEAR
165 ASSUME
DS:NOTHING
,ES:NOTHING
169 invoke get_jfn_pointer
; get jfn loc
172 error error_invalid_handle
175 MOV AL,BYTE PTR ES:[DI]
178 MOV BYTE PTR ES:[DI],0FFh;
180 invoke get_sf_from_sfn
185 DEC [DI].sf_ref_count
; no more reference
188 ; need to restuff Attrib if we are closing a protected file
190 TEST [DI.sf_fcb
.fcb_DevID
],devid_file_clean
+devid_device
192 PUSH WORD PTR [DI].sf_attr
196 invoke FCB_CLOSE_INNER
197 CMP AL,0FFh ; file not found error?
199 error error_file_not_found
206 BREAK <PushDMA
, PopDMA
, ptr_normalize
- set up
local dma
and save old
>
208 ; input: DS:DX is DMA
209 ; output: DS:DX is normalized , ES:BX destroyed
210 ; [DMAADD] is now set up to DS:DX
213 procedure PushDMA
,NEAR
214 ASSUME
DS:NOTHING
,ES:NOTHING
219 LES BX,DWORD PTR [DMAADD
] ; get old dma
223 invoke ptr_normalize
; get new dma
224 MOV WORD PTR [DMAADD
],DX ; save IT!
225 MOV WORD PTR [DMAADD
+2],DS
232 ; input: old DMA under ret address on stack
233 ; output: [DMAADD] set to old version and stack popped
234 procedure PopDMA
,NEAR
235 ASSUME
DS:NOTHING
,ES:NOTHING
238 POP WORD PTR [DMAADD
]
239 POP WORD PTR [DMAADD
+2]
245 ; input: DS:DX is a pointer
246 ; output: DS:DX is normalized (DX < 10h)
247 procedure ptr_normalize
,NEAR
251 SHR DX,CL ; DX = (DX >> 4) (using CX)
254 MOV DS,CX ; DS = DS + DX (using CX)
256 AND DX,0Fh ; DX = T2 & 0Fh
264 ; SHR DX,CL ; get upper part of dx
266 ; ADD AX,DX ; add into seg address
269 ; AND DX,0Fh ; save low part
275 BREAK <$Read
- Do
file/device I
/O
>
283 ; AX has number of bytes read
285 ; AX = read_invalid_handle
286 ; = read_access_denied
290 ASSUME
DS:NOTHING
,ES:NOTHING
295 CMP ES:[DI].sf_mode
,open_for_write
298 MOV AL,read_access_denied
304 invoke $FCB_RANDOM_READ_BLOCK
; do read
306 invoke get_user_stack
; get old frame
307 MOV AX,[SI].user_CX
; get returned CX
309 MOV [SI].user_CX
,CX ; stash our CX
310 invoke PopDMA
; get old DMA
314 BREAK <$Write
- Do
file/device I
/O
>
322 ; AX has number of bytes written
324 ; AX = write_invalid_handle
325 ; = write_access_denied
328 procedure $Write
,NEAR
329 ASSUME
DS:NOTHING
,ES:NOTHING
334 CMP ES:[DI].sf_mode
,open_for_read
336 invoke $FCB_RANDOM_WRITE_BLOCK
; do write
342 ASSUME
DS:NOTHING
,ES:NOTHING
345 invoke Get_sf_from_jfn
346 ; ES:DI is sf pointer
347 MOV AL,read_invalid_handle
;Assume an error
355 BREAK <$LSEEK
- set random record field
>
364 ; DX:AX has the new location of the pointer
366 ; AX = error_invalid_handle
367 ; = error_invalid_function
368 procedure $LSEEK
,NEAR
369 ASSUME
DS:NOTHING
,ES:NOTHING
372 error error_invalid_function
376 invoke get_sf_from_jfn
384 TEST [DI.sf_fcb
+fcb_devid
],devid_device
394 ; move from end of file
395 ; first, get end of file
396 XCHG AX,DX ; AX <- low
397 XCHG DX,CX ; DX <- high
399 ADD AX,[DI+sf_fcb
+fcb_FILSIZ
]
400 ADC DX,[DI+sf_fcb
+fcb_FILSIZ
+2]
404 XCHG AX,DX ; AX <- low
405 XCHG DX,CX ; DX <- high
408 MOV WORD PTR [DI+sf_fcb
+fcb_RR
],AX
409 MOV WORD PTR [DI+sf_fcb
+fcb_RR
+2],DX
410 invoke get_user_stack
416 ; ES:DI is pointer to sf... need to invoke set random record for place
417 XCHG AX,DX ; AX <- low
418 XCHG DX,CX ; DX <- high
419 ADD AX,WORD PTR [DI+sf_fcb
+fcb_RR
]
420 ADC DX,WORD PTR [DI+sf_fcb
+fcb_RR
+2]
424 error error_invalid_handle
428 BREAK <$IOCTL
- return
/set device dependent stuff
>
442 ; AX = error_invalid_handle
443 ; = error_invalid_function
444 ; = error_invalid_data
446 procedure $IOCTL
,NEAR
447 ASSUME
DS:NOTHING
,ES:NOTHING
448 MOV SI,DS ;Stash DS for calls 2,3,4 and 5
451 JA ioctl_check_block
;Block device
453 invoke get_sf_from_jfn
455 JNC ioctl_check_permissions
; have valid handle
456 error error_invalid_handle
458 ioctl_check_permissions:
460 JAE ioctl_control_string
462 MOV AL,BYTE PTR ES:[DI+sf_fcb
+fcb_devid
]
463 JZ ioctl_read
; read the byte
465 JZ ioctl_check_device
; can I set with this data?
466 error error_invalid_data
; no DH <> 0
469 TEST AL,devid_ISDEV
; can I set this handle?
470 JZ ioctl_bad_fun
; no, it is a file.
471 MOV BYTE PTR ES:[DI+sf_fcb
+fcb_devid
],DL
476 TEST AL,devid_ISDEV
; Should I set high byte
477 JZ ioctl_no_high
; no
478 LES DI,DWORD PTR ES:[DI+sf_fcb
+fcb_FIRCLUS
] ;Get device pointer
479 MOV AH,BYTE PTR ES:[DI.SDEVATT
+1] ;Get high byte
481 invoke get_user_stack
486 ioctl_control_string:
487 TEST BYTE PTR ES:[DI+sf_fcb
+fcb_devid
],devid_ISDEV
; can I?
488 JZ ioctl_bad_fun
; no, it is a file.
489 LES DI,DWORD PTR ES:[DI+sf_fcb
+fcb_FIRCLUS
] ;Get device pointer
490 XOR BL,BL ; Unit number of char dev = 0
491 JMP SHORT ioctl_do_string
495 DEC AL ;4=2,5=3,6=4,7=5
520 error error_invalid_function
523 error error_access_denied
529 PUSH SI ;DS in disguise
533 invoke FATREAD
;"get" the drive
534 MOV BL,ES:[BP.dpb_UNIT
] ; Unit number
535 LES DI,ES:[BP.dpb_driver_addr
]
536 CLC ;Make sure error jump not taken
544 TEST ES:[DI.SDEVATT
],DEVIOCTL
;See if device accepts control
548 JZ ioctl_control_read
549 MOV [IOCALL
.REQFUNC
],DEVWRIOCTL
550 JMP SHORT ioctl_control_call
552 MOV [IOCALL
.REQFUNC
],DEVRDIOCTL
555 MOV AH,BL ;Unit number
556 MOV WORD PTR [IOCALL
.REQLEN
],AX
558 MOV [IOCALL
.REQSTAT
],AX
561 MOV WORD PTR [IOXAD
],DX
562 MOV WORD PTR [IOXAD
+2],SI
566 MOV SI,DI ;DS:SI -> driver
569 MOV BX,OFFSET DOSGROUP
:IOCALL
;ES:BX -> Call header
571 MOV AX,[IOSCNT
] ;Get actual bytes transferred
576 BREAK <File_Times
- modify write
times on a handle
>
582 ; ; if AL = 1 then then next two are mandatory
586 ; ; if AL = 0 then CX/DX has the last write time/date
590 ; AX = error_invalid_function
591 ; = error_invalid_handle
593 procedure $File_times
,near
596 error error_invalid_function
603 error error_invalid_handle
608 MOV CX,ES:[DI.sf_fcb
.fcb_FTIME
]
609 MOV DX,ES:[DI.sf_fcb
.fcb_FDATE
]
610 invoke Get_user_stack
616 MOV ES:[DI.sf_fcb
.fcb_FTIME
],CX
617 MOV ES:[DI.sf_fcb
.fcb_FDATE
],DX
618 AND ES:[DI.sf_fcb
.fcb_DEVID
],NOT devid_file_clean