📄 cio.a86
字号:
pop bx
cooked_o20:
test ah,CIO_RAW ; is it a cooked console ?
jnz cooked_o30 ; skip check if not
call cooked_status ; look for keyboard input
mov char_count,CHECK_EVERY ; look again in a while
cooked_o30:
pop si
pop cx
pop ax
pop es
ret
eject
; IDLE_DEV is called when the PCMODE is waiting for a character.
; This routine must determine if the request is for a device or not
; and call the IDLE interface for device requests to the system can be
; put to sleep until a character is ready.
;
; On Entry:- BX Handle Number
;
idle_dev:
push bx ; preserve handle
mov ax,8400h
int 2ah ; Server hook for idle
dec clock_count
jnz idle_dev10 ; Zero if NO skip delay and execute
call ReadTimeAndDate ; for PC BIOS's who must read every day
idle_dev10:
if IDLE_DETECT
test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled
jnz idle_dev40 ; Skip if NO
push es ! push si
call is_device ; The requested handle a file or device
jc idle_dev30 ; File Access skip IDLE
mov ax,PROC_KEYIN ; Assume this is the REAL Console
test es:DH_ATTRIB[si],DA_ISCIN; Test Attribute Bits
jnz idle_dev20 ; Yes this is Default Console Device
mov ax,PROC_DEVIN ; Input from Another Device
idle_dev20:
callf idle_vec ; Call the IDLE Handler
idle_dev30:
pop si ! pop es
idle_dev40:
endif
pop bx ; recover handle
ret
eject
; The following routine reads CX bytes from the device whose address
; is held in the DWORD pointer passed by DS:SI. A Request Header
; is built on the stack and the command is executed.
;
; On Entry:
; ES:SI DWORD Pointer to Device Header
; SS:DX Buffer Address
; CX Character Count
;
; On Exit:
; AX Request Header Status
; Zero No Error
;
Public device_read
device_read:
mov al,CMD_INPUT ; we want input
jmps device_common ; now use common code
eject
; The following routine writes CX bytes to the device whose address
; is held in the DWORD pointer passed by DS:SI. A Request Header
; is built on the stack and the command is executed.
;
; On Entry:
; ES:SI DWORD Pointer to Device Header
; SS:DX Buffer Address
; CX Character Count
;
; On Exit:
; AX Request Header Status
; Zero No Error
;
Public device_write
device_write:
mov al,CMD_OUTPUT ; we want output
device_common:
push bx
sub sp,RH4_LEN ; reserve space on the stack
mov bx,sp ; request header offset
mov ss:RH_LEN,RH4_LEN ; request header length
mov ss:RH4_BUFOFF,dx ; buffer offset
mov ss:RH4_BUFSEG,ss ; buffer segment
device_common10:
mov ss:RH4_COUNT,cx ; character count
call device_req ; execute command
jns device_common20 ; if no errors return to the caller
sub cx,ss:RH4_COUNT ; CX = chars remaining
push ax ; save the error code
call char_error ; ask int 24 what to do
cmp al,ERR_RETRY ; should we retry the operation ?
pop ax ; recover the error code
ja device_common20 ; Fail/Abort return error
mov al,ss:RH_CMD ; reload the command
je device_common10 ; Retry, re-issue the device request
mov ax,RHS_DONE ; Ignore, pretend no errors
device_common20:
add sp,RH4_LEN ; restore the stack to its normal
test ax,RHS_ERROR ; state and return the status.
pop bx
ret
char_check:
; On Entry:
; BX = handle to check
; On Exit:
; ZF set if character ready
; AL = character (if device handle)
; AH = RIC status
;
push bx ; Save the current handle status
if IDLE_DETECT
test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled
jnz char_check10 ; Skip if NO
dec int28_delay ; Has the INT28 Loop count reached
jnz char_check10 ; Zero if NO skip delay and execute
mov ax,int28_reload ; INT28. Otherwise DELAY/DISPATCH
mov int28_delay,ax
mov ax,PROC_INT28 ; Process is IDLE
callf idle_vec ; Call the IDLE Handler
char_check10:
endif
cmp indos_flag,1 ; Only execute an INT 28
jnz char_check20 ; when the INDOS flag is 1
cmp int28_flag,TRUE ; Only generate INT 28s for the
jnz char_check20 ; selected functions
push remote_call
push machine_id
mov es,current_psp ; Get the PSP
push PSP_USERSP ; Save the SS:SP pointer to
push PSP_USERSS ; the register image
if IDLE_DETECT ; Set IDLE_INT28 so $IDLE$ knows
or idle_flags,IDLE_INT28 ; that we are nolonger inside DOS
endif
int 28h ; Execute an INT 28 for SideKick and
; the PRINT utility. INDOS flag is 1
if IDLE_DETECT ; Reset IDLE_INT28 so $IDLE$ knows
and idle_flags,not IDLE_INT28; that we are back DOS
endif
mov int28_flag,TRUE ; Restore INT28_FLAG
mov es,current_psp ; Get the PSP
pop PSP_USERSS ; Restore the SS:SP pointer to
pop PSP_USERSP ; the register image
pop machine_id
pop remote_call
char_check20:
pop bx
; jmp hndl_instat ; Check Input Status. ZERO == Ready
;
;
hndl_instat:
call is_device ; Does this handle refer to a device
jnc device_instat
mov ax,(MS_X_IOCTL shl 8)+6 ; Get the file status
call dos_entry ; for the specified handle
cmp al,0FFh ; and return ZERO until the EOF
ret
; The following routine executes the Non Destructive Input
; command to the device whose address passed in ES:SI.
;
; On Entry:
; ES:SI DWORD Pointer to Device Header
;
; On Exit:
; Zero Character Ready
; AH Top Byte Request Header Status
; AL Next Character if ZERO
;
device_instat:
push bx
sub sp,RH5_LEN ; Reserve Space on the Stack
mov bx,sp ; Request Header Offset
mov ss:RH_LEN,RH5_LEN ; Set Request Header Length
mov al,CMD_INPUT_NOWAIT ; Command Number
call device_req ; Execute the Command
mov al,ss:RH5_CHAR ; Assume a character is ready
add sp,RH5_LEN ; Restore the Stack to its normal
test ax,RHS_BUSY ; state and return the status.
pop bx ; Zero if a Character is ready
ret
; The following routine handles the low level device interface to
; the character device drivers. All the generic Request Header
; initialization is carried out here.
;
; On Entry:
; AL Command
; ES:SI Device Header
; SS:BX Current Request Header
;
; On Exit:
; AX Request Header Status
;
device_req:
;----------
mov ss:RH_CMD,al ; save the command
push ds
push es
push es ! pop ds ; DS:SI -> device driver
mov es,ss:current_psp ; es = current PSP
mov al,es:PSP_RIC ; al = Return Interim Character flag
mov ss:RH4_RIC,al ; Return Interim Char flag
push ss ! pop es ; ES:BX -> RH_
call device_driver
pop es
pop ds
ret
eject
;
; IS_DEVICE checks the internal handle structures to determine
; if the handle referenced in BX is a file or device. Invalid
; handles all map to the default console device.
;
; On Entry:
; BX Handle Number
;
; On Exit:
; CY set if handle is for a file
; CY clear if handle is for device at ES:SI
;
is_device:
push ax
push bx ; Convert the Standard Handle number
mov ax,bx ; get XFN in AL
; mov cx,current_psp ; into an internal handle number
; jcxz is_dev10 ; no PSP, we have IFN already
; mov es,cx
test byte ptr remote_call+1,DHM_FCB/100h; if FCB initiated access
jnz is_dev10 ; we have IFN already
mov es,current_psp
cmp bx,es:PSP_XFNMAX ; Check if the handle is in range for
jae is_dev_bad ; this PSP.
les si,es:PSP_XFTPTR
mov al,es:byte ptr [bx+si] ; AL = Internal File Handle
is_dev10:
call ifn2dhndl ; ES:BX -> DHNDL_
jc is_dev_bad
mov ax,es:DHNDL_WATTR[bx] ; get file attributes
and ax,DHAT_REMOTE+DHAT_DEV
cmp ax,DHAT_DEV ; is it a local device ?
stc ; assume it's a file
jne is_dev30
les si,es:DHNDL_DEVPTR[bx] ; its a device
is_dev20:
clc
is_dev30:
pop bx
pop ax
ret
is_dev_bad:
les si,con_device ; bad handles map to console
jmps is_dev20
open_or_close_prn:
;-----------------
; called when CIO_CTLP toggled - call prn device with Open or Close as appropriate
;
push ds ! push ax ! push bx
mov ax,CTLP
push ax ; ^P on stack
mov cx,current_psp ; look in PSP
jcxz oc_prn30 ; no PSP, forget it
mov es,cx
cmp bx,PSP_XFNMAX ; Check if the handle is in range for
jae oc_prn30 ; this PSP.
les si,es:PSP_XFTPTR ; for the internal handle number
mov al,es:byte ptr STDPRN[si]
cmp al,0FFh ; AL = Internal File Handle
je oc_prn30 ; skip if invalid Handle Number
call ifn2dhndl ; ES:BX -> doshndl
jc oc_prn30
test es:DHNDL_WATTR[bx],DHAT_NETPRN
jz oc_prn10
mov ax,I2F_CTLP ; turn on the network printer
int 2fh ; with a magic INT 2F call
jnc oc_prn10
and cio_state,not CIO_CTLP ; make sure Printer Echo is off
mov ax,I2F_CTLP_ERR
int 2fh
jmps oc_prn30
oc_prn10:
mov ax,es:DHNDL_WATTR[bx] ; get file attributes
and ax,DHAT_REMOTE+DHAT_DEV
cmp ax,DHAT_DEV ; is it a local device ?
jne oc_prn30
mov al,CMD_DEVICE_OPEN ; assume we've just opened
test cio_state,CIO_CTLP ; Check for Printer Echo
jnz oc_prn20 ; yes, skip next bit
mov al,CMD_DEVICE_CLOSE ; no, we must close
oc_prn20:
les si,es:DHNDL_DEVPTR[bx] ; get the device driver address
test es:DH_ATTRIB[si],DA_REMOVE
jz oc_prn30 ; no, skip call if not supported
sub sp,RH13_LEN ; Reserve Space on the Stack
mov bx,sp ; and point to it
mov ss:RH_LEN,RH13_LEN ; Set Request Header Length
mov ss:RH_CMD,al ; Command Number
call device_driver ; issue the command
add sp,RH13_LEN ; Restore the Stack to its normal
oc_prn30:
pop ax ; discard ^P from stack
pop bx ! pop ax ! pop ds
ret
PCM_RODATA CSEG WORD
cntrl_c_msg db '^C', CR, LF ; Control-Break Message
GLOBAL_DATA dseg
clock_count db 0
PCMODE_DATA DSEG WORD
extrn break_sp:word ; For Control-Break handler
extrn char_count:byte
extrn cio_state:byte ; Character I/O State
extrn column:byte ; Console Cursor Location
extrn con_device:dword ; Current Console Device
extrn current_psp:word ; Current PSP Address
extrn exit_type:byte
extrn last_key_ext:byte
extrn indos_flag:byte ; INDOS Count
extrn int21regs_ptr:dword ; pointer to callers registers
extrn machine_id:word
extrn remote_call:word
if IDLE_DETECT
extrn idle_flags:word ; IDLE State Flags
extrn idle_vec:dword ; IDLE routine Vector
extrn int28_delay:word
extrn int28_reload:word
extrn int28_flag:byte
endif
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -