CIO.A86
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:30k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $CIO.A86$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;    $Log: $
  31. ;    CIO.A86 1.20 94/12/01 10:05:21
  32. ;    Made cooked_write and is_device aware of FCB writes;    
  33. ;    CIO.A86 1.19 94/06/28 12:21:07
  34. ;    Fix last_key_ext bug
  35. ;    CIO.A86 1.18 94/05/12 14:06:22
  36. ;    The routine cooked_status now sets a flag last_key_ext if the keycode is 0.
  37. ;    On entry, it checks this flag to see if the last one was 0, and if so does
  38. ;    not do the checks for the control keys. In this way, Alt-R and Alt-Q can
  39. ;    be distinguished from Ctrl-S and Ctrl-P.
  40. ;    CIO.A86 1.17 93/12/21 17:58:15
  41. ;    Preserve BX round clock read
  42. ;    Update char_error so DS:SI -> device driver header itself
  43. ;    CIO.A86 1.10 93/05/06 19:28:03
  44. ;    Move int 23/28 support to CIO.
  45. ;    Read the clock in idle_dev, not int 28 loop.
  46. ;    CIO.A86 1.9 93/05/05 23:30:44
  47. ;    int 2A/84 is now only generated on input-and-wait functions
  48. ;    CIO.A86 1.8 93/03/25 15:05:56
  49. ;    tweak console block output
  50. ;    ENDLOG
  51. ;
  52. ; This module contains all the Character I/O functions used by PCMODE
  53. ;
  54. ; 12 Nov 87 Disable Control-Break when the Console Output mode is RAW
  55. ; 24 Feb 88 Display Control characters correctly. ie "^X"
  56. ; 23 May 88 Support ^S to Pause screen output.
  57. ; 25 May 88 Support Control-P for Cooked_Write and remove Kanji Character
  58. ;           check.
  59. ; 26 May 88 Check for CTLC on CON_DEV when character input is redirected.
  60. ;           Correctly detect EOF on redirected input.
  61. ; 17 Aug 88 Call PRN device with Open/Close on ^P
  62. ; 30 Aug 88 Jump to correct exit when Open/Close is not supported by a 
  63. ;           device driver for ^P.
  64. ; 14 Sep 88 Break checking should only be carried out when the INDOS_FLAG
  65. ;           is 1. (Novell and Cntrl-C).
  66. ; 03 Sep 88 Return the character output by INT21/04,05,06 in AL.
  67. ; 10 Nov 88 Preserve ES when calling any Device Driver (Revalation DEVDRVR)
  68. ; 15 Dec 88 Check STDERR for Control-C if it is a Device.
  69. ; 15 Mar 89 Check for CTLC during Cooked Write.
  70. ; 16 Mar 89 Explicitly allow INT 28 during char reads (SmartNotes bug)
  71. ; 25 Apr 89 Execute break_check after getting the console status INT21/0B
  72. ;  2 May 89 Save Device driver STRAT and INT address's on the stack
  73. ; 10 May 89 Now check keyboard more often during cooked write
  74. ; 25 May 89 Move INT28 flag to PCMIF.PCM
  75. ;  6 Sep 89 Enter/Exit critical region round device request
  76. ; 26 Oct 89 saving some bytes again...
  77. ; 25 Jan 90 Insert IDLE Detection Code
  78. ; 29 Jan 90 Int 2A critical section support added to device_callf
  79. ;  7 Mar 90 Convert to register preserved function calls
  80. ; 27 Mar 90 cooked_write checks STD_OUT for ctl-s ctl-p etc (STD_IN may
  81. ;           have been redirected)
  82. ; 29 Mar 90 preserve BX round device_callf (3+Share CLOCK$ bug)
  83. ; 12 Jun 90 get_doshndl parameter BX not AX
  84. ; 15 Oct 90 Added support for Return Interim Character flag (see PSP_RIC).
  85. ; 26 Oct 90 handle PSP=0 (ie. FCB device I/O)
  86. ;  1 mar 91 break_check now goes to con_device, not STDERR
  87. ; 17 jun 91 ij fix to cooked_out to avoid status checks if STDOUT redirected
  88. include pcmode.equ
  89. include i:driver.equ
  90. include i:reqhdr.equ
  91. include i:msdos.equ
  92. include i:fdos.equ
  93. include i:psp.def
  94. include i:mserror.equ
  95. include i:char.def
  96. include i:redir.equ
  97. include i:doshndl.def
  98. CIO_CTLP equ 0000$0001b ; Printer Echo State
  99. CIO_HANDLE equ 0000$0010b ; use handle rather than Int 29
  100. CIO_RAW equ 0000$0100b ; no "cooked_status" checks
  101. CHECK_EVERY equ 80 ; check keyboard every "n" characters
  102. PCM_CODE CSEG BYTE
  103. extrn char_error:near
  104. extrn device_driver:near
  105. extrn dos_entry:near
  106. extrn get_dseg:near
  107. extrn ifn2dhndl:near
  108. extrn int21_entry:near
  109. extrn int21_func:near
  110. extrn read_line:near
  111. extrn ReadTimeAndDate:near
  112. extrn reload_registers:near
  113. ; *****************************
  114. ; ***    DOS Function 01    ***
  115. ; ***  Keybd Input W/Echo   ***
  116. ; *****************************
  117. ;
  118. Public func01
  119. func01:
  120. ;
  121. ; Entry:
  122. ; AH  == 01h
  123. ; Exit:
  124. ; AL  == char
  125. ;
  126. call func08 ; Read 1 character from Standard Input
  127. ; and check for Control-C
  128. xchg ax,dx ; echo using common code
  129. ; *****************************
  130. ; ***    DOS Function 02    ***
  131. ; ***     Display Output    ***
  132. ; *****************************
  133. ;
  134. Public func02
  135. func02:
  136. ;
  137. ; Entry:
  138. ; AH  == 02h
  139. ; DL  == char to display
  140. ;
  141. push dx ; char on stack
  142. push ss ! pop es
  143. mov si,sp ; ES:DX -> character
  144. mov cx,1
  145. call stdout_cooked_write ; write character
  146. pop ax ; recover char
  147. ret
  148. ; *****************************
  149. ; ***    DOS Function 03    ***
  150. ; ***    Auxiliary Input    ***
  151. ; *****************************
  152. ;
  153. Public func03
  154. func03:
  155. ;
  156. ; Entry:
  157. ; AH  == 03h
  158. ; Exit:
  159. ; AL  == Char
  160. ;
  161. mov bx,STDAUX ; Read 1 character from Standard AUX
  162. f03_10:
  163. jmp raw_read
  164. ; *****************************
  165. ; ***    DOS Function 04    ***
  166. ; ***    Auxiliary Output   ***
  167. ; *****************************
  168. ;
  169. Public func04
  170. func04:
  171. ;
  172. ; Entry:
  173. ; AH  == 04h
  174. ; DL  == Character to output
  175. ;
  176. mov bx,STDAUX ; write the character passed in DL
  177. jmps f456common ;  to the STDAUX Handle
  178. ; *****************************
  179. ; ***    DOS Function 05    ***
  180. ; ***    Printer Output     ***
  181. ; *****************************
  182. ;
  183. Public func05
  184. func05:
  185. ;
  186. ; Entry:
  187. ; AH  == 05h
  188. ; DL  == character to output to printer
  189. ;
  190. mov bx,STDPRN ; write the character passed in DL
  191. ; jmp f456common ;  to the STDPRN Handle
  192. f456common:
  193. xchg ax,dx ; character in AL
  194. ; jmp hndl_write
  195. hndl_write:
  196. ;----------
  197. ; On Entry:
  198. ; AL = character to write
  199. ; BX = handle
  200. ; On Exit:
  201. ; AL preserved
  202. ;
  203. call is_device ; Does this handle refer to a device
  204.  jc hndl_w10
  205. test es:DH_ATTRIB[si],DA_SPECIAL
  206.  jz hndl_w10 ; Fast Console Output Using Int 29?
  207. int 29h ; This device supports FAST console
  208. ret ;  output so write this using Int29
  209. hndl_w10:
  210. push ax ; character on stack
  211. mov dx,sp ; SS:DX -> char
  212. mov cx,1 ; do a single character
  213.  jc hndl_w20 ; was it a file ?
  214. call device_write ; send to device driver
  215. jmps hndl_w30
  216. hndl_w20:
  217. push ss ! pop es ; ES:DX -> character
  218. mov ah,MS_X_WRITE ; otherwise call the FDOS to do all
  219. call dos_entry ;  the hard work
  220. hndl_w30:
  221. pop ax
  222. ret
  223. ; *****************************
  224. ; ***    DOS Function 06    ***
  225. ; ***   Direct Console I/O  ***
  226. ; *****************************
  227. ;
  228. Public func06
  229. func06:
  230. ;
  231. ; Entry:
  232. ; AH  == 06h
  233. ; DL  == 0FFh or Output char
  234. ; Exit:
  235. ; AL  == Input char, if DL was 0FFh on input
  236. ;
  237. mov bx,STDOUT ; Assume output DL to console
  238. cmp dl,0FFH ; or is it input ?
  239.  jne f456common
  240. dec bx
  241. ; mov bx,STDIN ; is there a character ready
  242. call char_check ;  to be input
  243.  jz func07
  244. mov ax,RHS_IC ; set AL=0 and also set ZF on
  245. jmps funcICexit ;  exit as incomplete char
  246. ; *****************************
  247. ; ***    DOS Function 07    ***
  248. ; ***   Raw Input w/o echo  ***
  249. ; *****************************
  250. ;
  251. Public func07
  252. func07:
  253. ;
  254. ; Entry:
  255. ; AH  == 07h
  256. ; Exit:
  257. ; AL  == character
  258. ;
  259. mov bx,STDIN
  260. call raw_read ; extra status call made
  261. jmps funcICexit ; set incomplete char
  262. ; *****************************
  263. ; ***    DOS Function 08    ***
  264. ; ***    Input w/o echo     ***
  265. ; *****************************
  266. ;
  267. Public func08
  268. func08:
  269. ;
  270. ; Entry:
  271. ; AH  == 08h
  272. ; Exit:
  273. ; AL  == character
  274. ;
  275. mov bx,STDIN ; Read 1 character from Standard Input
  276. call cooked_read
  277. funcICexit:
  278. ; exit point for incomplete character support
  279. ; On Entry:
  280. ; AL = character
  281. ; AH = request header status (RHS_IC as on return from device driver)
  282. ; On Exit:
  283. ; AL = character
  284. ; dos_FLAGS ZF set if incomplete character
  285. ;
  286. les di,int21regs_ptr ; point to callers registers
  287. and es:reg_FLAGS[di],not ZERO_FLAG ; clear ZF
  288. test ah,RHS_IC/256 ; is it an incomplete char ?
  289.  jz funcIC10 ;  no - exit
  290. or es:reg_FLAGS[di],ZERO_FLAG ;  yes - set ZF
  291. funcIC10:
  292. ret
  293. ; *****************************
  294. ; ***    DOS Function 09    ***
  295. ; ***     Print String      ***
  296. ; *****************************
  297. ;
  298. Public func09
  299. func09:
  300. ;
  301. ; Entry:
  302. ; AH  == 09h
  303. ;    DS:DX  == address of character string
  304. ;
  305. mov al,'$' ; it's terminated with a '$'
  306. mov di,dx ; locate the end of the string 
  307. mov cx,0FFFFh ; and calculate its length
  308. repnz scasb
  309. not cx
  310. dec cx ; CX is the character count
  311. mov si,dx
  312. call stdout_cooked_write ; ES:SI -> character buffer
  313.     mov al,'$'          
  314.     ret
  315. ; *****************************
  316. ; ***    DOS Function 0A    ***
  317. ; ***      Read String      ***
  318. ; *****************************
  319. ;
  320. Public func0A
  321. func0A:
  322. ;
  323. ; Entry:
  324. ; AH  == 0Ah
  325. ;    DS:DX  == pointer to input buffer
  326. ;
  327. mov bx,STDIN ; Read the editted line from STDIN
  328. mov cx,STDOUT ; and display the results on STDOUT
  329. jmp read_line ; Read the Line
  330. ; *****************************
  331. ; ***    DOS Function 0B    ***
  332. ; ***    Console Status     ***
  333. ; *****************************
  334. ;
  335. Public func0B
  336. func0B:
  337. ;
  338. ; Entry:
  339. ; AH  == 0Bh
  340. ; Exit:
  341. ; AL  == 0FFh if char available
  342. ;     ==  00h otherwise
  343. ;
  344. mov bx,STDIN
  345. call cooked_status ; Get the current handle status
  346. mov  al,0FFh ; Assume that the handle is ready
  347.  jz f0B_exit ; and return 0FFh in AL
  348. mov al,00 ; Not Ready
  349. f0B_exit:
  350. jmps funcICexit ; exit thru incomplete char support
  351. ; *****************************
  352. ; ***    DOS Function 0C    ***
  353. ; ***    Flush and Execute  ***
  354. ; *****************************
  355. ;
  356. Public func0C
  357. func0C:
  358. ;
  359. ; Entry:
  360. ; AH  == 0Ch
  361. ; AL  ==  function to execute:  1,6,7,8 or A
  362. ; Exit:
  363. ; AL = 0 if function in AL is invalid
  364. ;
  365. push ax ; save sub-function
  366. mov bx,STDIN ; Is this Standard Input Handle a
  367. call is_device ;  file or device. Do not flush the 
  368.  jc f0C_20 ;  buffer contents for a FILE
  369. f0C_10:
  370. call hndl_instat ; check if any characters are left
  371.  jnz f0C_20 ;  and quit when buffer empty
  372. call raw_read ; read the character
  373. jmps f0C_10 ; loop till the buffer is empty
  374. f0C_20:
  375. pop ax
  376. cmp al,01h ! je al_ok ; is legal for this command
  377. cmp al,0ah ! je al_ok
  378. cmp al,06h ! jb al_nogo
  379. cmp al,08h ! ja al_nogo
  380. al_ok: ; Valid function so now execute
  381. call reload_registers ; all register reloaded as per entry
  382. mov ah,al ; Get the requested sub-function in AH
  383. jmp int21_func ; execute the function
  384. al_nogo: ; Illegal command to execute
  385. xor ax,ax ; from this function so return error
  386. ret
  387. eject
  388. ;
  389. ; BREAK_CHECK checks for a CNTRL-C and is called by functions 01h to 
  390. ; 0Ch. Or by the entry code if the break flag is non zero.
  391. ;
  392. Public break_check
  393. break_check:
  394. cmp indos_flag,01 ; Skip the check if we are
  395.  jnz break_c15 ; already in the emulator
  396. push ax
  397. push es
  398. push si
  399. les si,con_device
  400. call device_instat ; get the input status
  401. pop si
  402. pop es
  403.  jnz break_c10 ; No Character Ready
  404. cmp al,CTLC ; Is the character a Control-C
  405.  jz break_c20 ; Yes
  406. break_c10:
  407. pop ax
  408. break_c15:
  409. ret
  410. break_c20: ; The User has Typed Control-C so flush
  411. mov bx,0FFFFh ;  input buffer (FFFF=con_device)
  412. call char_get
  413. go_int23:
  414. push cs ! pop es ; ES:DX -> Character Buffer
  415. mov si,offset cntrl_c_msg ; Message Offset
  416. mov cx,length cntrl_c_msg ; Message Length
  417. call stdout_cooked_write ; write the ^C String to console
  418. ;
  419. ; Prepare to execute an Interrupt 23 (Break Check) and process
  420. ; the return values. If the called routine returns with an IRET
  421. ; or with a RETF and the carry flag reset continue the function
  422. ; otherwise Abort.
  423. ;
  424. mov es,current_psp ; Get the Entry SS and SP
  425. mov ax,PSP_USERSP ; Get the Users Stack Pointer
  426. add ax,18 - 2 ; Compensate for the User Registers
  427. mov break_sp,ax ; and save for RETF check
  428. cli
  429. dec indos_flag ; Exit the PCDOS emulator
  430. mov ss,PSP_USERSS ; Switch to the Users Stack
  431. mov sp,PSP_USERSP ; and Restore the registers
  432. POP$DOS ; Update the registers then
  433. ; set the flags and return
  434. ; to the user
  435. clc ; Default to continue function
  436. int 23h ; Call the Break Handler
  437. cli ; Check the Flag State
  438.  jnc do23_10 ; If CARRY then Abort this process
  439. call get_dseg ; Get our data segment
  440. mov exit_type,TERM_BREAK ; Force EXIT_TYPE to TERM_BREAK
  441. mov ax,4C00h ; "Good-Bye Cruel World" 
  442.     jmps    do23_20
  443.     do23_10:
  444. push ds ; Otherwise restart the aborted func
  445. call get_dseg
  446. cmp sp,break_sp
  447. pop ds ; Restore the the USER DS correct
  448.  jz do23_30 ; Did we Use a RETF or Not
  449. do23_20:
  450. add sp,2 ; Yes so correct the stack pointer
  451. do23_30: ; and restart the aborted function
  452. jmp int21_entry ; re-start the function call
  453. eject
  454. ;
  455. ; cooked_status is called on input or output and looks for live keys ^C,^P,^S.
  456. ; If any of these are found they are dealt with.
  457. ; If ^P is encountered it is swallowed.
  458. ; If ^C is encountered we always do an Int23.
  459. ; If ^S is pressed we swallow it, and the next character (checking for ^C, but
  460. ; not for ^P), then say a character is ready.
  461. ; Note that this can lead to status calls (func0B) hanging inside the OS,
  462. ; or the return of ^S characters from input calls (func01), but this is
  463. ; intentional.
  464. ;
  465. cooked_status:
  466. ;-------------
  467. ; check input
  468. ; On Entry:
  469. ; BX = handle to check
  470. ; On Exit:
  471. ; ZF set if character available
  472. ; AL = character
  473. ; AH = RHS_IC
  474. ;
  475. call break_check ; check for a ^C on console
  476. call char_check ; is there a character ready
  477.  jnz cooked_s50 ;  no so keep scanning
  478. cmp last_key_ext,0 ; was last char an zero ?
  479. mov last_key_ext,0 ; (clear flag for next time)
  480.  jne cooked_s40 ; skip ^P,^S,^C checks if so
  481. cmp al,CTLP ; has the user typed ^P
  482.  jne cooked_s10 ;  flush the buffer and
  483. xor cio_state,CIO_CTLP ;  toggle ^P flag
  484. call char_get ;  flush the character from buffer
  485. call open_or_close_prn ;  open/close printer device
  486. test ax,ax ; ZF clear, ie. no char available
  487. jmps cooked_s50
  488. cooked_s10:
  489. cmp al,CTLC
  490.  jnz cooked_s30 ; has the user typed ^C
  491. call char_get ; so get the RAW character
  492. cooked_s20:
  493. jmp go_int23 ; and terminate the function
  494. cooked_s30:
  495. cmp al,CTLS ; pause if the user has typed
  496.  jnz cooked_s40 ;  a ^S
  497. call char_get ; remove ^S and resume when
  498. call raw_read_wait ; the next character is typed
  499. cmp al,CTLC
  500.  je cooked_s20 ; has the user typed ^C
  501. cooked_s40:
  502. cmp al,0
  503.  jne cooked_s45
  504. mov last_key_ext,1
  505. cooked_s45:
  506. cmp ax,ax ; ZF set, ie. char available
  507. cooked_s50:
  508. ret
  509. eject
  510. ;
  511. ; The COOKED, CMDLINE and RAW Read functions are basically the same
  512. ; except in their treatment of 'live' characters ^C,^P, and ^S.
  513. ; COOKED will look for and act upon all three live characters.
  514. ; CMDLINE will look for and act upon ^C and ^P, but ^S will be returned
  515. ; so we can use it as a line editing key.
  516. ; RAW will not check for any live keys.
  517. ;
  518. public cmdline_read, raw_read ; for CMDLINE.PCM
  519. cmdline_read_wait: ; Waiting for a device to become
  520. call idle_dev ; ready. So call IDLE routines to
  521. ; put the processor to sleep.
  522. cmdline_read:
  523. call break_check ; check for a ^C on console
  524. call char_check ; is there a character ready
  525.  jnz cmdline_read_wait ;  no so keep scanning
  526. cmp al,CTLS ; if the user has typed ^S
  527.  jne cooked_read ;  we have to do a raw read
  528. ; jmps raw_read ;  else we do a cooked read
  529. raw_read_wait: ; Waiting for a device to become
  530. call idle_dev ; ready. So call IDLE routines to
  531. ; put the processor to sleep.
  532. raw_read:
  533. call char_check ; Is there a character Ready
  534.  jnz raw_read_wait ; loop until character available
  535. jmps char_get
  536. cooked_read_wait: ; Waiting for a device to become
  537. call idle_dev ; ready. So call IDLE routines to
  538. ; put the processor to sleep.
  539. cooked_read:
  540. call break_check ; check for a ^C on console
  541. call cooked_status ; check for a ^S,^P,^C on handle BX
  542.  jnz cooked_read_wait ; wait until char is available
  543. ; jmps char_get ;  else get the character
  544. char_get:
  545. push es ! push ax ; Input one character and
  546. mov dx,sp ;  return it in AL
  547. call is_device ; Does this handle refer to a device
  548. mov cx,1
  549.  jc char_get30 ; if it's a device then
  550. call device_read ;  use device_read
  551. char_get20:
  552. pop ax ! pop es
  553. ret
  554. char_get30:
  555. ; We are redirected, so call to the FDOS to get a character
  556. push ss ! pop es ; EX:DX -> character to read
  557. mov ah,MS_X_READ ; call the FDOS to do all
  558. call dos_entry ;  the hard work
  559. jmps char_get20
  560. eject
  561. stdout_cooked_write:
  562. mov bx,STDOUT ; output to the console device
  563. ; jmp cooked_write
  564. ;
  565. ; The COOKED_WRITE routine will expand TABS etc in the string
  566. ; passed passed by the calling routine. 
  567. ;
  568. ; On Entry:
  569. ; ES:SI Buffer Address
  570. ; CX Character Count
  571. ; BX Output Handle
  572. ; On Exit:
  573. ; AL = last char written
  574. ;
  575. Public cooked_write
  576. cooked_write:
  577. push es
  578. push bx
  579. mov ah,cio_state ; get CIO_CTLP status
  580. or ah,CIO_RAW+CIO_HANDLE ; assume we will want raw handle output
  581. mov al,bl
  582. test byte ptr remote_call+1,DHM_FCB/100h
  583.  jnz cook_w03
  584. mov es,current_psp ; get our PSP
  585. cmp bx,PSP_XFNMAX ; range check our handle
  586.  jae cook_w05
  587. les di,PSP_XFTPTR
  588. mov al,es:byte ptr [bx+di] ; AL = Internal File Handle
  589. cook_w03:
  590. call ifn2dhndl ; ES:BX -> DHNDL_
  591.  jc cook_w05 ; skip if bad handle
  592. mov dx,es:DHNDL_WATTR[bx] ; get handle attributes
  593. and dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN+DHAT_REMOTE
  594. cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT+DHAT_BIN
  595.  je cook_w04 ; accept binary console device
  596. cmp dx,DHAT_DEV+DHAT_CIN+DHAT_COT
  597.  jne cook_w05 ; skip if not cooked console device
  598. and ah,not CIO_RAW ; we want cooked output
  599. cook_w04:
  600. les bx,es:DHNDL_DEVPTR[bx] ; its the console - but is it FAST ?
  601. test es:DH_ATTRIB[bx],DA_SPECIAL
  602.  jz cook_w05 ; skip if not
  603. and ah,not CIO_HANDLE ; don't use handle functions
  604. cook_w05:
  605. pop bx
  606. pop es
  607.      jcxz   cook_w80        
  608. cook_w10:
  609. lods es:al ; Read the next character
  610. cmp al,DEL ! je cook_w60 ; DEL is a NON Printing Character
  611. cmp al,' ' ! jae cook_w50 ; Space and Above are Normal
  612. cmp al,LF  ! je cook_w60 ; Just print LineFeeds
  613. cmp al,ESC ! je cook_w60 ; Just print Escape
  614. cmp al,BELL! je cook_w60 ; Just ring the Bell
  615. cmp al,CR  ! jne cook_w20 ; CR zeros the column number
  616. mov column,0
  617. mov char_count,1 ; check for ^S etc NOW
  618. jmps cook_w60
  619. cook_w20:
  620. cmp al,CTLH ! jne cook_w30 ; BackSpace decrements the
  621. dec column ; column count by one
  622. jmps cook_w60
  623. cook_w30:
  624. cmp al,TAB ! jne cook_w60 ; is it a TAB ?
  625. cook_w40:
  626. mov al,' ' ;  spaces
  627. call cooked_out ; output a space char
  628. inc column
  629. test column,7 ; are we at a TAB stop yet ?
  630.  jnz cook_w40
  631. jmps cook_w70
  632. cook_w50:
  633. inc column ; Update the column count and
  634. cook_w60:
  635. call cooked_out ;  output the character
  636. cook_w70:
  637. loop cook_w10 ; onto the next character
  638. cook_w80:
  639. ret
  640. cooked_out:
  641. ; On Entry:
  642. ; AH = handle status
  643. ; AL = character
  644. ; BX = handle
  645. ; On Exit:
  646. ; AX, BX, CX, ES:SI preserved
  647. ;
  648. dec char_count ; time to check keyboard input ?
  649.  jz cooked_o10 ;  no, skip status check
  650. test ah,CIO_HANDLE+CIO_CTLP ; is it complicated ?
  651.  jnz cooked_o10
  652. int 29h ; This device supports FAST console
  653. ret
  654. cooked_o10:
  655. push es
  656. push ax
  657. push cx
  658. push si
  659. call hndl_write ; display the character
  660. test ah,CIO_CTLP ; Check for Printer Echo
  661.  jz cooked_o20 ; Off so No Echo
  662. push bx ; Save Output Handle
  663. mov bx,STDPRN ; and output the same data to the
  664. call hndl_write ; to the Printer Handle
  665. pop bx
  666. cooked_o20:
  667. test ah,CIO_RAW ; is it a cooked console ?
  668.  jnz cooked_o30 ; skip check if not
  669. call cooked_status ; look for keyboard input
  670. mov char_count,CHECK_EVERY ; look again in a while
  671. cooked_o30:
  672. pop si
  673. pop cx
  674. pop ax
  675. pop es
  676. ret
  677. eject
  678. ; IDLE_DEV is called when the PCMODE is waiting for a character.
  679. ; This routine must determine if the request is for a device or not
  680. ; and call the IDLE interface for device requests to the system can be
  681. ; put to sleep until a character is ready.
  682. ;
  683. ; On Entry:- BX Handle Number
  684. ;
  685. idle_dev:
  686. push bx ; preserve handle
  687. mov ax,8400h
  688. int 2ah ; Server hook for idle
  689. dec clock_count
  690.  jnz idle_dev10 ; Zero if NO skip delay and execute
  691. call ReadTimeAndDate ; for PC BIOS's who must read every day
  692. idle_dev10:
  693. if IDLE_DETECT
  694. test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled
  695.  jnz idle_dev40 ; Skip if NO
  696. push es ! push si
  697. call is_device ; The requested handle a file or device
  698.  jc idle_dev30 ; File Access skip IDLE
  699. mov ax,PROC_KEYIN ; Assume this is the REAL Console
  700. test es:DH_ATTRIB[si],DA_ISCIN; Test Attribute Bits
  701.  jnz idle_dev20 ; Yes this is Default Console Device
  702. mov ax,PROC_DEVIN ; Input from Another Device
  703. idle_dev20:
  704. callf idle_vec ; Call the IDLE Handler
  705. idle_dev30:
  706. pop si ! pop es
  707. idle_dev40:
  708. endif
  709. pop bx ; recover handle
  710. ret
  711. eject
  712. ; The following routine reads CX bytes from the device whose address 
  713. ; is held in the DWORD pointer passed by DS:SI. A Request Header 
  714. ; is built on the stack and the command is executed.
  715. ;
  716. ; On Entry:
  717. ; ES:SI DWORD Pointer to Device Header
  718. ; SS:DX Buffer Address
  719. ; CX Character Count
  720. ;
  721. ; On Exit:
  722. ; AX Request Header Status
  723. ; Zero No Error
  724. ;
  725. Public device_read
  726. device_read:
  727. mov al,CMD_INPUT ; we want input
  728. jmps device_common ; now use common code
  729. eject
  730. ; The following routine writes CX bytes to the device whose address 
  731. ; is held in the DWORD pointer passed by DS:SI. A Request Header 
  732. ; is built on the stack and the command is executed.
  733. ;
  734. ; On Entry:
  735. ; ES:SI DWORD Pointer to Device Header
  736. ; SS:DX Buffer Address
  737. ; CX Character Count
  738. ;
  739. ; On Exit:
  740. ; AX Request Header Status
  741. ; Zero No Error
  742. ;
  743. Public device_write
  744. device_write:
  745. mov al,CMD_OUTPUT ; we want output
  746. device_common:
  747. push bx
  748. sub sp,RH4_LEN ; reserve space on the stack
  749. mov bx,sp ; request header offset
  750. mov ss:RH_LEN,RH4_LEN ; request header length
  751. mov ss:RH4_BUFOFF,dx ; buffer offset
  752. mov ss:RH4_BUFSEG,ss ; buffer segment
  753. device_common10:
  754. mov ss:RH4_COUNT,cx ; character count
  755. call device_req ; execute command
  756.  jns device_common20 ; if no errors return to the caller
  757. sub cx,ss:RH4_COUNT ; CX = chars remaining
  758. push ax ; save the error code
  759. call char_error ; ask int 24 what to do
  760. cmp al,ERR_RETRY ; should we retry the operation ?
  761. pop ax ; recover the error code
  762.  ja device_common20 ; Fail/Abort return error
  763. mov al,ss:RH_CMD ; reload the command
  764.  je device_common10 ; Retry, re-issue the device request
  765. mov ax,RHS_DONE ; Ignore, pretend no errors
  766. device_common20:
  767. add sp,RH4_LEN ; restore the stack to its normal
  768. test ax,RHS_ERROR ;  state and return the status.
  769. pop bx
  770. ret
  771. char_check:
  772. ; On Entry:
  773. ; BX = handle to check
  774. ; On Exit:
  775. ; ZF set if character ready
  776. ; AL = character (if device handle)
  777. ; AH = RIC status
  778. ;
  779. push bx ; Save the current handle status
  780. if IDLE_DETECT
  781. test idle_flags,IDLE_DISABLE ; Has Idle Checking been enabled
  782.  jnz char_check10 ; Skip if NO
  783. dec int28_delay ; Has the INT28 Loop count reached
  784.  jnz char_check10 ; Zero if NO skip delay and execute
  785. mov ax,int28_reload ; INT28. Otherwise DELAY/DISPATCH
  786. mov int28_delay,ax
  787. mov ax,PROC_INT28 ; Process is IDLE
  788. callf idle_vec ; Call the IDLE Handler
  789. char_check10:
  790. endif
  791. cmp indos_flag,1 ; Only execute an INT 28
  792.  jnz char_check20 ; when the INDOS flag is 1
  793. cmp int28_flag,TRUE ; Only generate INT 28s for the
  794.  jnz char_check20 ; selected functions
  795. push remote_call
  796. push machine_id
  797. mov es,current_psp ; Get the PSP
  798. push PSP_USERSP ; Save the SS:SP pointer to 
  799. push PSP_USERSS ; the register image
  800. if IDLE_DETECT ; Set IDLE_INT28 so $IDLE$ knows
  801. or idle_flags,IDLE_INT28 ; that we are nolonger inside DOS
  802. endif
  803. int 28h ; Execute an INT 28 for SideKick and
  804. ; the PRINT utility. INDOS flag is 1
  805. if IDLE_DETECT ; Reset IDLE_INT28 so $IDLE$ knows
  806. and idle_flags,not IDLE_INT28; that we are back DOS
  807. endif
  808. mov int28_flag,TRUE ; Restore INT28_FLAG
  809. mov es,current_psp ; Get the PSP
  810. pop PSP_USERSS ; Restore the SS:SP pointer to 
  811. pop PSP_USERSP ; the register image
  812. pop machine_id
  813. pop remote_call
  814. char_check20:
  815. pop bx
  816. ; jmp hndl_instat ; Check Input Status. ZERO == Ready
  817. ;
  818. ;
  819. hndl_instat:
  820. call is_device ; Does this handle refer to a device
  821.  jnc device_instat
  822. mov ax,(MS_X_IOCTL shl 8)+6 ; Get the file status
  823. call dos_entry ; for the specified handle
  824. cmp al,0FFh ; and return ZERO until the EOF
  825. ret
  826. ; The following routine executes the Non Destructive Input
  827. ; command to the device whose address passed in ES:SI.
  828. ;
  829. ; On Entry:
  830. ; ES:SI DWORD Pointer to Device Header
  831. ;
  832. ; On Exit:
  833. ; Zero Character Ready
  834. ; AH Top Byte Request Header Status
  835. ; AL Next Character if ZERO
  836. ;
  837. device_instat:
  838. push bx
  839. sub sp,RH5_LEN ; Reserve Space on the Stack
  840. mov bx,sp ; Request Header Offset
  841. mov ss:RH_LEN,RH5_LEN ; Set Request Header Length
  842. mov al,CMD_INPUT_NOWAIT ; Command Number
  843. call device_req ; Execute the Command
  844. mov al,ss:RH5_CHAR ; Assume a character is ready
  845. add sp,RH5_LEN ; Restore the Stack to its normal
  846. test ax,RHS_BUSY ; state and return the status.
  847. pop bx ; Zero if a Character is ready
  848. ret
  849. ; The following routine handles the low level device interface to
  850. ; the character device drivers. All the generic Request Header 
  851. ; initialization is carried out here.
  852. ;
  853. ; On Entry:
  854. ; AL Command
  855. ; ES:SI Device Header
  856. ; SS:BX Current Request Header
  857. ;
  858. ; On Exit:
  859. ; AX Request Header Status
  860. ;
  861. device_req:
  862. ;----------
  863. mov ss:RH_CMD,al ; save the command
  864. push ds
  865. push es
  866. push es ! pop ds ; DS:SI -> device driver
  867. mov es,ss:current_psp ; es = current PSP
  868. mov al,es:PSP_RIC ; al = Return Interim Character flag
  869. mov ss:RH4_RIC,al ; Return Interim Char flag
  870. push ss ! pop es ; ES:BX -> RH_
  871. call device_driver
  872. pop es
  873. pop ds
  874. ret
  875. eject
  876. ;
  877. ; IS_DEVICE checks the internal handle structures to determine
  878. ; if the handle referenced in BX is a file or device. Invalid
  879. ; handles all map to the default console device.
  880. ;
  881. ; On Entry:
  882. ; BX Handle Number
  883. ;
  884. ; On Exit:
  885. ; CY set if handle is for a file
  886. ; CY clear if handle is for device at ES:SI
  887. ;
  888. is_device:
  889. push ax
  890. push bx ; Convert the Standard Handle number
  891. mov ax,bx ; get XFN in AL
  892. ; mov cx,current_psp ; into an internal handle number
  893. ;  jcxz is_dev10 ; no PSP, we have IFN already
  894. ; mov es,cx
  895. test byte ptr remote_call+1,DHM_FCB/100h; if FCB initiated access
  896.  jnz is_dev10 ; we have IFN already
  897. mov es,current_psp
  898. cmp bx,es:PSP_XFNMAX ; Check if the handle is in range for
  899.  jae is_dev_bad ; this PSP.
  900. les si,es:PSP_XFTPTR
  901. mov al,es:byte ptr [bx+si] ; AL = Internal File Handle
  902. is_dev10:
  903. call ifn2dhndl ; ES:BX -> DHNDL_
  904.  jc is_dev_bad
  905. mov ax,es:DHNDL_WATTR[bx] ; get file attributes
  906. and ax,DHAT_REMOTE+DHAT_DEV
  907. cmp ax,DHAT_DEV ; is it a local device ?
  908. stc ; assume it's a file
  909.  jne is_dev30
  910. les si,es:DHNDL_DEVPTR[bx] ; its a device
  911. is_dev20:
  912. clc
  913. is_dev30:
  914. pop bx
  915. pop ax
  916. ret
  917. is_dev_bad:
  918. les si,con_device ; bad handles map to console
  919. jmps is_dev20
  920. open_or_close_prn:
  921. ;-----------------
  922. ; called when CIO_CTLP toggled - call prn device with Open or Close as appropriate
  923. ;
  924. push ds ! push ax ! push bx
  925. mov ax,CTLP
  926. push ax ; ^P on stack
  927. mov cx,current_psp ; look in PSP
  928.  jcxz oc_prn30 ; no PSP, forget it
  929. mov es,cx
  930. cmp bx,PSP_XFNMAX ; Check if the handle is in range for
  931.  jae oc_prn30 ; this PSP. 
  932. les si,es:PSP_XFTPTR ; for the internal handle number
  933. mov al,es:byte ptr STDPRN[si]
  934. cmp al,0FFh ; AL = Internal File Handle
  935.  je  oc_prn30 ;  skip if invalid Handle Number
  936. call ifn2dhndl ; ES:BX -> doshndl
  937.  jc oc_prn30
  938. test es:DHNDL_WATTR[bx],DHAT_NETPRN
  939.  jz oc_prn10
  940. mov ax,I2F_CTLP ; turn on the network printer
  941. int 2fh ; with a magic INT 2F call
  942.  jnc oc_prn10
  943. and cio_state,not CIO_CTLP ; make sure Printer Echo is off
  944. mov ax,I2F_CTLP_ERR
  945. int 2fh
  946. jmps oc_prn30
  947. oc_prn10:
  948. mov ax,es:DHNDL_WATTR[bx] ; get file attributes
  949. and ax,DHAT_REMOTE+DHAT_DEV
  950. cmp ax,DHAT_DEV ; is it a local device ?
  951.  jne oc_prn30
  952. mov al,CMD_DEVICE_OPEN ; assume we've just opened
  953. test cio_state,CIO_CTLP ; Check for Printer Echo
  954.  jnz oc_prn20 ; yes, skip next bit
  955. mov al,CMD_DEVICE_CLOSE ; no, we must close
  956. oc_prn20:
  957. les si,es:DHNDL_DEVPTR[bx] ; get the device driver address
  958. test es:DH_ATTRIB[si],DA_REMOVE
  959.  jz oc_prn30 ; no, skip call if not supported
  960. sub sp,RH13_LEN ; Reserve Space on the Stack
  961. mov bx,sp ; and point to it
  962. mov ss:RH_LEN,RH13_LEN ; Set Request Header Length
  963. mov ss:RH_CMD,al ; Command Number
  964. call device_driver ; issue the command
  965. add sp,RH13_LEN ; Restore the Stack to its normal
  966. oc_prn30:
  967. pop ax ; discard ^P from stack
  968. pop bx ! pop ax ! pop ds
  969. ret
  970. PCM_RODATA CSEG WORD
  971. cntrl_c_msg db '^C', CR, LF ; Control-Break Message
  972. GLOBAL_DATA dseg
  973. clock_count db 0
  974. PCMODE_DATA DSEG WORD
  975. extrn break_sp:word ; For Control-Break handler
  976. extrn char_count:byte
  977. extrn cio_state:byte ; Character I/O State
  978. extrn column:byte ; Console Cursor Location
  979. extrn con_device:dword ; Current Console Device
  980. extrn current_psp:word ; Current PSP Address
  981. extrn exit_type:byte
  982. extrn last_key_ext:byte
  983. extrn indos_flag:byte ; INDOS Count
  984. extrn int21regs_ptr:dword ; pointer to callers registers
  985. extrn machine_id:word
  986. extrn remote_call:word
  987. if IDLE_DETECT
  988. extrn idle_flags:word ; IDLE State Flags
  989. extrn idle_vec:dword ; IDLE routine Vector
  990. extrn int28_delay:word
  991. extrn int28_reload:word
  992. extrn int28_flag:byte
  993. endif
  994. end