CIO.A86
资源名称:drdossrc.zip [点击查看]
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:30k
源码类别:
操作系统开发
开发平台:
Asm
- ; File : $CIO.A86$
- ;
- ; Description :
- ;
- ; Original Author : DIGITAL RESEARCH
- ;
- ; Last Edited By : $CALDERA$
- ;
- ;-----------------------------------------------------------------------;
- ; Copyright Work of Caldera, Inc. All Rights Reserved.
- ;
- ; THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
- ; PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
- ; ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
- ; WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
- ; THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
- ; HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
- ; AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
- ; AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
- ; COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
- ; CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
- ; TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
- ; CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
- ; AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
- ; CIVIL LIABILITY.
- ;-----------------------------------------------------------------------;
- ;
- ; *** Current Edit History ***
- ; *** End of Current Edit History ***
- ; $Log: $
- ; CIO.A86 1.20 94/12/01 10:05:21
- ; Made cooked_write and is_device aware of FCB writes;
- ; CIO.A86 1.19 94/06/28 12:21:07
- ; Fix last_key_ext bug
- ; CIO.A86 1.18 94/05/12 14:06:22
- ; The routine cooked_status now sets a flag last_key_ext if the keycode is 0.
- ; On entry, it checks this flag to see if the last one was 0, and if so does
- ; not do the checks for the control keys. In this way, Alt-R and Alt-Q can
- ; be distinguished from Ctrl-S and Ctrl-P.
- ; CIO.A86 1.17 93/12/21 17:58:15
- ; Preserve BX round clock read
- ; Update char_error so DS:SI -> device driver header itself
- ; CIO.A86 1.10 93/05/06 19:28:03
- ; Move int 23/28 support to CIO.
- ; Read the clock in idle_dev, not int 28 loop.
- ; CIO.A86 1.9 93/05/05 23:30:44
- ; int 2A/84 is now only generated on input-and-wait functions
- ; CIO.A86 1.8 93/03/25 15:05:56
- ; tweak console block output
- ; ENDLOG
- ;
- ; This module contains all the Character I/O functions used by PCMODE
- ;
- ; 12 Nov 87 Disable Control-Break when the Console Output mode is RAW
- ; 24 Feb 88 Display Control characters correctly. ie "^X"
- ; 23 May 88 Support ^S to Pause screen output.
- ; 25 May 88 Support Control-P for Cooked_Write and remove Kanji Character
- ; check.
- ; 26 May 88 Check for CTLC on CON_DEV when character input is redirected.
- ; Correctly detect EOF on redirected input.
- ; 17 Aug 88 Call PRN device with Open/Close on ^P
- ; 30 Aug 88 Jump to correct exit when Open/Close is not supported by a
- ; device driver for ^P.
- ; 14 Sep 88 Break checking should only be carried out when the INDOS_FLAG
- ; is 1. (Novell and Cntrl-C).
- ; 03 Sep 88 Return the character output by INT21/04,05,06 in AL.
- ; 10 Nov 88 Preserve ES when calling any Device Driver (Revalation DEVDRVR)
- ; 15 Dec 88 Check STDERR for Control-C if it is a Device.
- ; 15 Mar 89 Check for CTLC during Cooked Write.
- ; 16 Mar 89 Explicitly allow INT 28 during char reads (SmartNotes bug)
- ; 25 Apr 89 Execute break_check after getting the console status INT21/0B
- ; 2 May 89 Save Device driver STRAT and INT address's on the stack
- ; 10 May 89 Now check keyboard more often during cooked write
- ; 25 May 89 Move INT28 flag to PCMIF.PCM
- ; 6 Sep 89 Enter/Exit critical region round device request
- ; 26 Oct 89 saving some bytes again...
- ; 25 Jan 90 Insert IDLE Detection Code
- ; 29 Jan 90 Int 2A critical section support added to device_callf
- ; 7 Mar 90 Convert to register preserved function calls
- ; 27 Mar 90 cooked_write checks STD_OUT for ctl-s ctl-p etc (STD_IN may
- ; have been redirected)
- ; 29 Mar 90 preserve BX round device_callf (3+Share CLOCK$ bug)
- ; 12 Jun 90 get_doshndl parameter BX not AX
- ; 15 Oct 90 Added support for Return Interim Character flag (see PSP_RIC).
- ; 26 Oct 90 handle PSP=0 (ie. FCB device I/O)
- ; 1 mar 91 break_check now goes to con_device, not STDERR
- ; 17 jun 91 ij fix to cooked_out to avoid status checks if STDOUT redirected
- include pcmode.equ
- include i:driver.equ
- include i:reqhdr.equ
- include i:msdos.equ
- include i:fdos.equ
- include i:psp.def
- include i:mserror.equ
- include i:char.def
- include i:redir.equ
- include i:doshndl.def
- CIO_CTLP equ 0000$0001b ; Printer Echo State
- CIO_HANDLE equ 0000$0010b ; use handle rather than Int 29
- CIO_RAW equ 0000$0100b ; no "cooked_status" checks
- CHECK_EVERY equ 80 ; check keyboard every "n" characters
- PCM_CODE CSEG BYTE
- extrn char_error:near
- extrn device_driver:near
- extrn dos_entry:near
- extrn get_dseg:near
- extrn ifn2dhndl:near
- extrn int21_entry:near
- extrn int21_func:near
- extrn read_line:near
- extrn ReadTimeAndDate:near
- extrn reload_registers:near
- ; *****************************
- ; *** DOS Function 01 ***
- ; *** Keybd Input W/Echo ***
- ; *****************************
- ;
- Public func01
- func01:
- ;
- ; Entry:
- ; AH == 01h
- ; Exit:
- ; AL == char
- ;
- call func08 ; Read 1 character from Standard Input
- ; and check for Control-C
- xchg ax,dx ; echo using common code
- ; *****************************
- ; *** DOS Function 02 ***
- ; *** Display Output ***
- ; *****************************
- ;
- Public func02
- func02:
- ;
- ; Entry:
- ; AH == 02h
- ; DL == char to display
- ;
- push dx ; char on stack
- push ss ! pop es
- mov si,sp ; ES:DX -> character
- mov cx,1
- call stdout_cooked_write ; write character
- pop ax ; recover char
- ret
- ; *****************************
- ; *** DOS Function 03 ***
- ; *** Auxiliary Input ***
- ; *****************************
- ;
- Public func03
- func03:
- ;
- ; Entry:
- ; AH == 03h
- ; Exit:
- ; AL == Char
- ;
- mov bx,STDAUX ; Read 1 character from Standard AUX
- f03_10:
- jmp raw_read
- ; *****************************
- ; *** DOS Function 04 ***
- ; *** Auxiliary Output ***
- ; *****************************
- ;
- Public func04
- func04:
- ;
- ; Entry:
- ; AH == 04h
- ; DL == Character to output
- ;
- mov bx,STDAUX ; write the character passed in DL
- jmps f456common ; to the STDAUX Handle
- ; *****************************
- ; *** DOS Function 05 ***
- ; *** Printer Output ***
- ; *****************************
- ;
- Public func05
- func05:
- ;
- ; Entry:
- ; AH == 05h
- ; DL == character to output to printer
- ;
- mov bx,STDPRN ; write the character passed in DL
- ; jmp f456common ; to the STDPRN Handle
- f456common:
- xchg ax,dx ; character in AL
- ; jmp hndl_write
- hndl_write:
- ;----------
- ; On Entry:
- ; AL = character to write
- ; BX = handle
- ; On Exit:
- ; AL preserved
- ;
- call is_device ; Does this handle refer to a device
- jc hndl_w10
- test es:DH_ATTRIB[si],DA_SPECIAL
- jz hndl_w10 ; Fast Console Output Using Int 29?
- int 29h ; This device supports FAST console
- ret ; output so write this using Int29
- hndl_w10:
- push ax ; character on stack
- mov dx,sp ; SS:DX -> char
- mov cx,1 ; do a single character
- jc hndl_w20 ; was it a file ?
- call device_write ; send to device driver
- jmps hndl_w30
- hndl_w20:
- push ss ! pop es ; ES:DX -> character
- mov ah,MS_X_WRITE ; otherwise call the FDOS to do all
- call dos_entry ; the hard work
- hndl_w30:
- pop ax
- ret
- ; *****************************
- ; *** DOS Function 06 ***
- ; *** Direct Console I/O ***
- ; *****************************
- ;
- Public func06
- func06:
- ;
- ; Entry:
- ; AH == 06h
- ; DL == 0FFh or Output char
- ; Exit:
- ; AL == Input char, if DL was 0FFh on input
- ;
- mov bx,STDOUT ; Assume output DL to console
- cmp dl,0FFH ; or is it input ?
- jne f456common
- dec bx
- ; mov bx,STDIN ; is there a character ready
- call char_check ; to be input
- jz func07
- mov ax,RHS_IC ; set AL=0 and also set ZF on
- jmps funcICexit ; exit as incomplete char
- ; *****************************
- ; *** DOS Function 07 ***
- ; *** Raw Input w/o echo ***
- ; *****************************
- ;
- Public func07
- func07:
- ;
- ; Entry:
- ; AH == 07h
- ; Exit:
- ; AL == character
- ;
- mov bx,STDIN
- call raw_read ; extra status call made
- jmps funcICexit ; set incomplete char
- ; *****************************
- ; *** DOS Function 08 ***
- ; *** Input w/o echo ***
- ; *****************************
- ;
- Public func08
- func08:
- ;
- ; Entry:
- ; AH == 08h
- ; Exit:
- ; AL == character
- ;
- mov bx,STDIN ; Read 1 character from Standard Input
- call cooked_read
- funcICexit:
- ; exit point for incomplete character support
- ; On Entry:
- ; AL = character
- ; AH = request header status (RHS_IC as on return from device driver)
- ; On Exit:
- ; AL = character
- ; dos_FLAGS ZF set if incomplete character
- ;
- les di,int21regs_ptr ; point to callers registers
- and es:reg_FLAGS[di],not ZERO_FLAG ; clear ZF
- test ah,RHS_IC/256 ; is it an incomplete char ?
- jz funcIC10 ; no - exit
- or es:reg_FLAGS[di],ZERO_FLAG ; yes - set ZF
- funcIC10:
- ret
- ; *****************************
- ; *** DOS Function 09 ***
- ; *** Print String ***
- ; *****************************
- ;
- Public func09
- func09:
- ;
- ; Entry:
- ; AH == 09h
- ; DS:DX == address of character string
- ;
- mov al,'$' ; it's terminated with a '$'
- mov di,dx ; locate the end of the string
- mov cx,0FFFFh ; and calculate its length
- repnz scasb
- not cx
- dec cx ; CX is the character count
- mov si,dx
- call stdout_cooked_write ; ES:SI -> character buffer
- mov al,'$'
- ret
- ; *****************************
- ; *** DOS Function 0A ***
- ; *** Read String ***
- ; *****************************
- ;
- Public func0A
- func0A:
- ;
- ; Entry:
- ; AH == 0Ah
- ; DS:DX == pointer to input buffer
- ;
- mov bx,STDIN ; Read the editted line from STDIN
- mov cx,STDOUT ; and display the results on STDOUT
- jmp read_line ; Read the Line
- ; *****************************
- ; *** DOS Function 0B ***
- ; *** Console Status ***
- ; *****************************
- ;
- Public func0B
- func0B:
- ;
- ; Entry:
- ; AH == 0Bh
- ; Exit:
- ; AL == 0FFh if char available
- ; == 00h otherwise
- ;
- mov bx,STDIN
- call cooked_status ; Get the current handle status
- mov al,0FFh ; Assume that the handle is ready
- jz f0B_exit ; and return 0FFh in AL
- mov al,00 ; Not Ready
- f0B_exit:
- jmps funcICexit ; exit thru incomplete char support
- ; *****************************
- ; *** DOS Function 0C ***
- ; *** Flush and Execute ***
- ; *****************************
- ;
- Public func0C
- func0C:
- ;
- ; Entry:
- ; AH == 0Ch
- ; AL == function to execute: 1,6,7,8 or A
- ; Exit:
- ; AL = 0 if function in AL is invalid
- ;
- push ax ; save sub-function
- mov bx,STDIN ; Is this Standard Input Handle a
- call is_device ; file or device. Do not flush the
- jc f0C_20 ; buffer contents for a FILE
- f0C_10:
- call hndl_instat ; check if any characters are left
- jnz f0C_20 ; and quit when buffer empty
- call raw_read ; read the character
- jmps f0C_10 ; loop till the buffer is empty
- f0C_20:
- pop ax
- cmp al,01h ! je al_ok ; is legal for this command
- cmp al,0ah ! je al_ok
- cmp al,06h ! jb al_nogo
- cmp al,08h ! ja al_nogo
- al_ok: ; Valid function so now execute
- call reload_registers ; all register reloaded as per entry
- mov ah,al ; Get the requested sub-function in AH
- jmp int21_func ; execute the function
- al_nogo: ; Illegal command to execute
- xor ax,ax ; from this function so return error
- ret
- eject
- ;
- ; BREAK_CHECK checks for a CNTRL-C and is called by functions 01h to
- ; 0Ch. Or by the entry code if the break flag is non zero.
- ;
- Public break_check
- break_check:
- cmp indos_flag,01 ; Skip the check if we are
- jnz break_c15 ; already in the emulator
- push ax
- push es
- push si
- les si,con_device
- call device_instat ; get the input status
- pop si
- pop es
- jnz break_c10 ; No Character Ready
- cmp al,CTLC ; Is the character a Control-C
- jz break_c20 ; Yes
- break_c10:
- pop ax
- break_c15:
- ret
- break_c20: ; The User has Typed Control-C so flush
- mov bx,0FFFFh ; input buffer (FFFF=con_device)
- call char_get
- go_int23:
- push cs ! pop es ; ES:DX -> Character Buffer
- mov si,offset cntrl_c_msg ; Message Offset
- mov cx,length cntrl_c_msg ; Message Length
- call stdout_cooked_write ; write the ^C String to console
- ;
- ; Prepare to execute an Interrupt 23 (Break Check) and process
- ; the return values. If the called routine returns with an IRET
- ; or with a RETF and the carry flag reset continue the function
- ; otherwise Abort.
- ;
- mov es,current_psp ; Get the Entry SS and SP
- mov ax,PSP_USERSP ; Get the Users Stack Pointer
- add ax,18 - 2 ; Compensate for the User Registers
- mov break_sp,ax ; and save for RETF check
- cli
- dec indos_flag ; Exit the PCDOS emulator
- mov ss,PSP_USERSS ; Switch to the Users Stack
- mov sp,PSP_USERSP ; and Restore the registers
- POP$DOS ; Update the registers then
- ; set the flags and return
- ; to the user
- clc ; Default to continue function
- int 23h ; Call the Break Handler
- cli ; Check the Flag State
- jnc do23_10 ; If CARRY then Abort this process
- call get_dseg ; Get our data segment
- mov exit_type,TERM_BREAK ; Force EXIT_TYPE to TERM_BREAK
- mov ax,4C00h ; "Good-Bye Cruel World"
- jmps do23_20
- do23_10:
- push ds ; Otherwise restart the aborted func
- call get_dseg
- cmp sp,break_sp
- pop ds ; Restore the the USER DS correct
- jz do23_30 ; Did we Use a RETF or Not
- do23_20:
- add sp,2 ; Yes so correct the stack pointer
- do23_30: ; and restart the aborted function
- jmp int21_entry ; re-start the function call
- eject
- ;
- ; cooked_status is called on input or output and looks for live keys ^C,^P,^S.
- ; If any of these are found they are dealt with.
- ; If ^P is encountered it is swallowed.
- ; If ^C is encountered we always do an Int23.
- ; If ^S is pressed we swallow it, and the next character (checking for ^C, but
- ; not for ^P), then say a character is ready.
- ; Note that this can lead to status calls (func0B) hanging inside the OS,
- ; or the return of ^S characters from input calls (func01), but this is
- ; intentional.
- ;
- cooked_status:
- ;-------------
- ; check input
- ; On Entry:
- ; BX = handle to check
- ; On Exit:
- ; ZF set if character available
- ; AL = character
- ; AH = RHS_IC
- ;
- call break_check ; check for a ^C on console
- call char_check ; is there a character ready
- jnz cooked_s50 ; no so keep scanning
- cmp last_key_ext,0 ; was last char an zero ?
- mov last_key_ext,0 ; (clear flag for next time)
- jne cooked_s40 ; skip ^P,^S,^C checks if so
- cmp al,CTLP ; has the user typed ^P
- jne cooked_s10 ; flush the buffer and
- xor cio_state,CIO_CTLP ; toggle ^P flag
- call char_get ; flush the character from buffer
- call open_or_close_prn ; open/close printer device
- test ax,ax ; ZF clear, ie. no char available
- jmps cooked_s50
- cooked_s10:
- cmp al,CTLC
- jnz cooked_s30 ; has the user typed ^C
- call char_get ; so get the RAW character
- cooked_s20:
- jmp go_int23 ; and terminate the function
- cooked_s30:
- cmp al,CTLS ; pause if the user has typed
- jnz cooked_s40 ; a ^S
- call char_get ; remove ^S and resume when
- call raw_read_wait ; the next character is typed
- cmp al,CTLC
- je cooked_s20 ; has the user typed ^C
- cooked_s40:
- cmp al,0
- jne cooked_s45
- mov last_key_ext,1
- cooked_s45:
- cmp ax,ax ; ZF set, ie. char available
- cooked_s50:
- ret
- eject
- ;
- ; The COOKED, CMDLINE and RAW Read functions are basically the same
- ; except in their treatment of 'live' characters ^C,^P, and ^S.
- ; COOKED will look for and act upon all three live characters.
- ; CMDLINE will look for and act upon ^C and ^P, but ^S will be returned
- ; so we can use it as a line editing key.
- ; RAW will not check for any live keys.
- ;
- public cmdline_read, raw_read ; for CMDLINE.PCM
- cmdline_read_wait: ; Waiting for a device to become
- call idle_dev ; ready. So call IDLE routines to
- ; put the processor to sleep.
- cmdline_read:
- call break_check ; check for a ^C on console
- call char_check ; is there a character ready
- jnz cmdline_read_wait ; no so keep scanning
- cmp al,CTLS ; if the user has typed ^S
- jne cooked_read ; we have to do a raw read
- ; jmps raw_read ; else we do a cooked read
- raw_read_wait: ; Waiting for a device to become
- call idle_dev ; ready. So call IDLE routines to
- ; put the processor to sleep.
- raw_read:
- call char_check ; Is there a character Ready
- jnz raw_read_wait ; loop until character available
- jmps char_get
- cooked_read_wait: ; Waiting for a device to become
- call idle_dev ; ready. So call IDLE routines to
- ; put the processor to sleep.
- cooked_read:
- call break_check ; check for a ^C on console
- call cooked_status ; check for a ^S,^P,^C on handle BX
- jnz cooked_read_wait ; wait until char is available
- ; jmps char_get ; else get the character
- char_get:
- push es ! push ax ; Input one character and
- mov dx,sp ; return it in AL
- call is_device ; Does this handle refer to a device
- mov cx,1
- jc char_get30 ; if it's a device then
- call device_read ; use device_read
- char_get20:
- pop ax ! pop es
- ret
- char_get30:
- ; We are redirected, so call to the FDOS to get a character
- push ss ! pop es ; EX:DX -> character to read
- mov ah,MS_X_READ ; call the FDOS to do all
- call dos_entry ; the hard work
- jmps char_get20
- eject
- stdout_cooked_write:
- mov bx,STDOUT ; output to the console device
- ; jmp cooked_write
- ;
- ; The COOKED_WRITE routine will expand TABS etc in the string
- ; passed passed by the calling routine.
- ;
- ; On Entry:
- ; ES:SI Buffer Address
- ; CX Character Count
- ; BX Output Handle
- ; On Exit:
- ; AL = last char written
- ;
- Public cooked_write
- cooked_write:
- push es
- push bx
- mov ah,cio_state ; get CIO_CTLP status
- or ah,CIO_RAW+CIO_HANDLE ; assume we will want raw handle output
- mov al,bl
- test byte ptr remote_call+1,DHM_FCB/100h
- jnz cook_w03
- mov es,current_psp ; get our PSP
- cmp bx,PSP_XFNMAX ; range check our handle
- jae cook_w05
- les di,PSP_XFTPTR
- mov al,es:byte ptr [bx+di] ; AL = Internal File Handle
- cook_w03:
- call ifn2dhndl ; ES:BX -> DHNDL_
- jc cook_w05 ; skip if bad handle
- mov dx,es:DHNDL_WATTR[bx] ; get handle attributes
- and dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN+DHAT_REMOTE
- cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN
- je cook_w04 ; accept binary console device
- cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT
- jne cook_w05 ; skip if not cooked console device
- and ah,not CIO_RAW ; we want cooked output
- cook_w04:
- les bx,es:DHNDL_DEVPTR[bx] ; its the console - but is it FAST ?
- test es:DH_ATTRIB[bx],DA_SPECIAL
- jz cook_w05 ; skip if not
- and ah,not CIO_HANDLE ; don't use handle functions
- cook_w05:
- pop bx
- pop es
- jcxz cook_w80
- cook_w10:
- lods es:al ; Read the next character
- cmp al,DEL ! je cook_w60 ; DEL is a NON Printing Character
- cmp al,' ' ! jae cook_w50 ; Space and Above are Normal
- cmp al,LF ! je cook_w60 ; Just print LineFeeds
- cmp al,ESC ! je cook_w60 ; Just print Escape
- cmp al,BELL! je cook_w60 ; Just ring the Bell
- cmp al,CR ! jne cook_w20 ; CR zeros the column number
- mov column,0
- mov char_count,1 ; check for ^S etc NOW
- jmps cook_w60
- cook_w20:
- cmp al,CTLH ! jne cook_w30 ; BackSpace decrements the
- dec column ; column count by one
- jmps cook_w60
- cook_w30:
- cmp al,TAB ! jne cook_w60 ; is it a TAB ?
- cook_w40:
- mov al,' ' ; spaces
- call cooked_out ; output a space char
- inc column
- test column,7 ; are we at a TAB stop yet ?
- jnz cook_w40
- jmps cook_w70
- cook_w50:
- inc column ; Update the column count and
- cook_w60:
- call cooked_out ; output the character
- cook_w70:
- loop cook_w10 ; onto the next character
- cook_w80:
- ret
- cooked_out:
- ; On Entry:
- ; AH = handle status
- ; AL = character
- ; BX = handle
- ; On Exit:
- ; AX, BX, CX, ES:SI preserved
- ;
- dec char_count ; time to check keyboard input ?
- jz cooked_o10 ; no, skip status check
- test ah,CIO_HANDLE+CIO_CTLP ; is it complicated ?
- jnz cooked_o10
- int 29h ; This device supports FAST console
- ret
- cooked_o10:
- push es
- push ax
- push cx
- push si
- call hndl_write ; display the character
- test ah,CIO_CTLP ; Check for Printer Echo
- jz cooked_o20 ; Off so No Echo
- push bx ; Save Output Handle
- mov bx,STDPRN ; and output the same data to the
- call hndl_write ; to the Printer Handle
- 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