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

操作系统开发

开发平台:

Asm

  1. title 'F_DOS Character device I/O'
  2. ;    File              : $CDEVIO.A86$
  3. ;
  4. ;    Description       :
  5. ;
  6. ;    Original Author   : DIGITAL RESEARCH
  7. ;
  8. ;    Last Edited By    : $CALDERA$
  9. ;
  10. ;-----------------------------------------------------------------------;
  11. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  12. ;      
  13. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  14. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  15. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  16. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  17. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  18. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  19. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  20. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  21. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  22. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  23. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  24. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  25. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  26. ;    CIVIL LIABILITY.
  27. ;-----------------------------------------------------------------------;
  28. ;
  29. ;    *** Current Edit History ***
  30. ;    *** End of Current Edit History ***
  31. ;    $Log: $
  32. ;    CDEVIO.A86 1.18 94/12/21 11:16:29
  33. ;    Changed dev_dup to refuse from duplicating remote devices rather
  34. ;    than refuse from duplicating FCBs 
  35. ;    Made open_dev return IFN rather than XFN for FCB opens 
  36. ;    Made open_dev put the current time/date into DHNDL_TIME/DHNDL_DATE
  37. ;    CDEVIO.A86 1.16 94/10/07 09:00:18
  38. ;    Added patch 004 as source fix. Changed request header length for character
  39. ;    device to 16h. Used RH4_CDEV_LEN instead of RH4_LEN.
  40. ;    CDEVIO.A86 1.15 93/12/10 00:09:17
  41. ;    Move non-inherited bit to correct place in file handle
  42. ;    CDEVIO.A86 1.14 93/11/26 16:17:14
  43. ;    Update char_error so ES:SI -> device driver header itself;
  44. ;    ENDLOG
  45. eject ! include i:psp.def
  46. eject ! include i:modfunc.def
  47. eject ! include i:fdos.equ
  48. eject ! include i:mserror.equ
  49. eject ! include i:doshndl.def
  50. eject ! include i:driver.equ
  51. eject ! include rh.equ
  52. BDOS_DATA dseg
  53. extrn fdos_buf:byte ; caveat: in PCMODE data segment
  54. extrn fdos_pb:word
  55. extrn fdos_ret:word
  56. ;
  57. ; Critical Error responses from the default INT 24 handler and
  58. ; the DO_INT24 routine.
  59. ;
  60. ERR_IGNORE equ 0 ; Ignore Error
  61. ERR_RETRY equ 1 ; Retry the Operation
  62. ERR_ABORT equ 2 ; Terminate the Process
  63. ERR_FAIL equ 3 ; Fail Function
  64. BDOS_CODE cseg
  65. public open_dev
  66. public close_dev
  67. public dup_dev
  68. public read_dev
  69. public write_dev
  70. public first_dev
  71. public ioc6_dev
  72. public ioc7_dev
  73. extrn cooked_write:near ; write to cooked console
  74. extrn read_line:near ; read edited line
  75. extrn break_check:near ; look for CTRL C
  76. extrn char_error:near ; generate Int 24
  77. extrn current_dsk2al:near ; get default drive in AL
  78. extrn device_driver:near
  79. extrn alloc_dhndl:near ; find free DHNDL_ structure
  80. extrn alloc_xfn:near
  81. extrn les_di_dmaptr:near
  82. extrn release_handle:near
  83. extrn get_xftptr:near
  84. extrn timestamp_dhndl:near
  85. ;    Character device functions
  86. ;    ==========================
  87. open_dev:
  88. ;--------
  89. ; Entry: ES:BX -> character device header
  90. ; Note: We own the MXdisk here, fdos_pb -> parameter data
  91. push es ! push bx ; save device driver address
  92. call alloc_xfn ; DI = XFN
  93. push di ; save XFN
  94. call alloc_dhndl ; ES:BX -> DHNDL, AX = IFN
  95. pop dx ; DX = XFN
  96. xchg ax,si ; SI = IFN
  97. xor ax,ax
  98. lea di,DHNDL_DATRB[bx] ; point at start of area to fill
  99. mov cx,DHNDL_UID-DHNDL_DATRB
  100. rep stosb
  101. mov es:DHNDL_SHARE[bx],ax ; also zap share word
  102. pop es:DHNDL_DEVOFF[bx]
  103. pop es:DHNDL_DEVSEG[bx] ; save device driver address
  104. push si ! push dx ; save IFN/XFN
  105. mov es:DHNDL_COUNT[bx],1
  106. push ds
  107. mov ax,fdos_pb+6 ; AX = open mode
  108. mov cx,DHAT_DEV+DHAT_CLEAN+DHAT_TIMEOK
  109. lds si,es:DHNDL_DEVPTR[bx] ; DS:SI -> device driver
  110. or cl,ds:byte ptr DH_ATTRIB[si]
  111. ; get attrib from device driver
  112. test al,DHM_LOCAL ; is it private ?
  113.  jz open_dev10
  114. and al,not DHM_LOCAL ; clear inherit bit
  115. or ch,DHAT_LOCAL/256 ; rememmber it's local
  116. open_dev10:
  117. mov es:DHNDL_MODE[bx],ax
  118. mov es:DHNDL_WATTR[bx],cx
  119. lea si,DH_NAME[si] ; copy the device name
  120. lea di,DHNDL_NAME[bx] ;  from the device header
  121. mov cx,8/WORD
  122. rep movsw
  123. mov al,' '
  124. mov cl,3 ; space the file extension
  125. rep stosb
  126. pop ds
  127. pop dx ! pop ax ; AX = IFN, DX = XFN
  128. push es
  129. call get_xftptr ; ES:DI -> PSP_XFTPTR for current_psp
  130.  jc open_dev20 ; no PSP, skip updating XFN
  131. add di,dx ; ES:DI -> entry in PSP
  132. stosb ; update entry in PSP
  133. xchg ax,dx
  134. open_dev20:
  135. pop es
  136. mov fdos_ret,ax ; save XFN (IFN for FCB open) to return
  137. call timestamp_dhndl
  138. or es:DHNDL_ATTR[bx],DHAT_READY
  139. ; jmp open_dup_dev
  140. open_dup_dev:
  141. ;------------
  142. ; On Entry:
  143. ; ES:BX = DHNDL_
  144. ; On Exit:
  145. ; None
  146. ;
  147. mov al,CMD_DEVICE_OPEN
  148. ; jmp open_close_dev ; call device open routine
  149. open_close_dev:
  150. ;--------------
  151. ; entry: ES:BX = DHNDL_
  152. ; AL = cmd_type (CMD_DEVICE_OPEN/CMD_DEVICE_CLOSE)
  153. ;
  154. push ds ! push es
  155. push bx ! push si
  156. lds si,es:DHNDL_DEVPTR[bx] ; DS:SI -> device driver
  157. test ds:DH_ATTRIB[si],DA_REMOVE
  158.  jz ocdev1  ; does the device support OPEN/CLOSE/RM
  159. sub sp,RH13_LEN-2*word ; make space on stack for RH_
  160. push ax ; RH_CMD = AL
  161. mov ax,RH13_LEN
  162. push ax ; RH_LEN = RH13_LEN
  163. push ss ! pop es
  164. mov bx,sp ; ES:BX -> RH_
  165. call device_driver ; call the device driver
  166. add sp,RH13_LEN ; recover stack space
  167. ocdev1:
  168. pop si ! pop bx
  169. pop es ! pop ds
  170. ret
  171. dup_dev:
  172. ;-------
  173. ; On Entry:
  174. ; ES:BX -> DHNDL_
  175. ; On Exit:
  176. ; None
  177. ; AX trashed
  178. ;
  179. mov ax,es:DHNDL_WATTR[bx]
  180. test al,DHAT_DEV
  181.  jz dup_dev10 ; skip if disk file
  182. test ax,DHAT_REMOTE ; or remote
  183.  jz open_dup_dev
  184. dup_dev10:
  185. ret
  186. close_dev: ; close character device handle
  187. ;---------
  188. ; entry: FDOS_PB+2 = user file handle
  189. ; ES:BX = file handle
  190. ; NOTE: This is called with the MXdisk owned
  191. mov al,CMD_DEVICE_CLOSE
  192. call open_close_dev ; call device close routine
  193. call release_handle ; release the XFN
  194. dec es:DHNDL_COUNT[bx] ; one less XFN refers to this IFN
  195. ret
  196. write_dev: ; write to character device handle
  197. ;---------
  198. ; entry: ES:BX -> DHNDL_ structure
  199. ;
  200. mov cl,CMD_OUTPUT ; OUTPUT driver function
  201. or es:DHNDL_ATTR[bx],DHAT_READY
  202. mov al,es:DHNDL_ATTR[bx] ; get file info
  203. and al,DHAT_BIN+DHAT_NUL+DHAT_CIN+DHAT_COT
  204. cmp al,DHAT_CIN+DHAT_COT ; is it cooked console?
  205.  jne inst_io ; no, device driver i/o
  206. mov si,2[bp] ; SI -> parameter block
  207. mov cx,ds:8[si] ; CX = string length
  208.  jcxz write_dev20 ; exit if nothing to write
  209. les di,ds:4[si] ; ES:DI -> string to print
  210. mov al,'Z'-40h ; we have to stop at ^Z
  211. repne scasb ; scan for ^Z character
  212.  jne write_dev10 ; skip if ^Z not found
  213. inc cx ; include ^Z in count of chars to skip
  214. sub ds:8[si],cx ; subtract from total count
  215. write_dev10:
  216. mov bx,ds:2[si] ; BX = handle number
  217. mov cx,ds:8[si] ; CX = string length
  218. mov si,ds:4[si] ; ES:SI -> string to print
  219. call cooked_write ; write w/ tab expansion & ^C checking
  220. write_dev20:
  221. sub bx,bx ; no errors
  222. ret ; return the result
  223. read_dev: ; read to character device handle
  224. ;--------
  225. ; entry: ES:BX -> DHNDL_ structure
  226. mov al,es:DHNDL_ATTR[bx] ; get the file info
  227. mov ah,al ; save ioctl info
  228. and al,DHAT_BIN+DHAT_CIN+DHAT_COT
  229. cmp al,DHAT_CIN+DHAT_COT ; is it cooked console?
  230.  jne rddev1 ; skip if binary or not console
  231. jmp read_con ; read from console handle
  232. ; return the result
  233. rddev1:
  234. test ah,DHAT_READY ; previous EOF ?
  235.  jnz rddev2 ; yes we return now
  236. mov di,2[bp] ; DI -> parameter block
  237. mov ds:word ptr 8[di],0 ; zero bytes xfered
  238. ret
  239. rddev2:
  240. mov cl,CMD_INPUT
  241. inst_io:
  242. ; ES:BX = DHNDL_, CL = command
  243. sub sp,RH4_CDEV_LEN ; make RH_ on stack
  244. mov di,bx ; save address DHNDL_ in DI
  245. mov bx,sp ; SS:BX -> request header
  246. mov ds:RH_CMD[bx],cl
  247. mov ds:RH_LEN[bx],RH4_CDEV_LEN
  248. mov ds:RH_STATUS[bx],0 ; status OK in case of zero chars
  249. mov si,2[bp] ; DS:SI -> parameter block
  250. lea si,4[si] ; point at buffer offset
  251. lodsw ; get buffer offset
  252. ; Normalising the address has been unnecessary so far
  253. ; push ax
  254. ; and ax,15 ; normalise the address
  255. ; pop cx
  256. ; shr cx,1 ! shr cx,1
  257. ; shr cx,1 ! shr cx,1
  258. mov ds:RH4_BUFOFF[bx],ax ; set buffer offset in request header
  259. lodsw ; get buffer segment
  260. ; add ax,cx ; add in normalised offset/16
  261. mov ds:RH4_BUFSEG[bx],ax ; get buffer segment in request header
  262. lodsw ; get byte count
  263. xchg ax,cx ; byte count in CX
  264. ; Parameter block created on stack at SS:BX and initialised for xfer
  265. ; ES:DI -> DHNDL_, CX = total number of bytes to xfer
  266. inst_io20:
  267. mov ds:RH4_COUNT[bx],cx ; try and do this many
  268. test es:DHNDL_ATTR[di],DHAT_BIN+DHAT_NUL
  269. ; are we in binary mode ?
  270.  jcxz inst_io30 ; return on zero length xfer
  271.  jnz inst_io25 ; binary, skip calling PCMODE
  272.     mov ds:RH4_COUNT[bx],1  ; do one char at a time
  273. call break_check ; call the break check routine
  274. cmp ds:RH_CMD[bx],CMD_OUTPUT ; which way are we going 
  275.  jne inst_io25
  276. call inst_io_getchar ; AL = 1st char in the buffer
  277. cmp al,1Ah ; EOF - don't send it or anything after
  278.  je inst_io30 ;  and exit without xfering any
  279. inst_io25:
  280. push ds ! push es ! push di ! push cx
  281. lds si,es:DHNDL_DEVPTR[di] ; DS:SI -> device driver
  282. push ss ! pop es ; ES:BX -> RH_
  283. call device_driver ; execute the command
  284. pop cx ! pop di ! pop es ! pop ds
  285.  jns inst_io_continue ; if no errors carry on
  286. push es
  287. les si,es:DHNDL_DEVPTR[di] ; ES:SI -> device driver
  288. call char_error ; this will handle the Int 24
  289. pop es
  290. cmp al,ERR_RETRY ; what should we do ?
  291.  je inst_io20 ; retry the operation
  292.  ja inst_io30 ; fail - return error
  293. mov ds:RH_STATUS[bx],RHS_DONE
  294. jmps inst_io_ignore ; ignore - fiddle status and
  295. inst_io_continue: ;  say we did it all
  296. mov dx,ds:RH4_COUNT[bx] ; how many did we xfer ?
  297. test dx,dx ;  if we haven't done any
  298.  jz inst_io30 ;  we are stuck so exit now
  299. inst_io_ignore:
  300. call inst_io_getchar ; AL = 1st char in the buffer
  301. add ds:RH4_BUFOFF[bx],dx ; it may not enough so adjust offset
  302. sub cx,dx ;  and number still to do
  303. cmp ds:RH_CMD[bx],CMD_INPUT ; which way are we going - if input
  304.  jne inst_io20 ;  we need to check for CR/EOF
  305. test es:DHNDL_ATTR[di],DHAT_BIN+DHAT_NUL
  306.  jnz inst_io30 ; if BIN then exit now
  307. cmp al,13 ; is it a CR character ?
  308.  je inst_io30 ;  yes, we stop now
  309. cmp al,1Ah ; is it the EOF character ?
  310.  jne inst_io20 ;  yes, we aren't ready
  311. and es:DHNDL_ATTR[di],not DHAT_READY
  312. inst_io30:
  313. mov di,2[bp] ; DI -> parameter block
  314. sub ds:8[di],cx ; subtract # not xfered from byte count
  315. mov ax,ds:RH_STATUS[bx] ; get result for later
  316. sub bx,bx ; assume no errors
  317. test ax,ax ; test error bit (8000h)
  318.  jns rddev_no_err ; skip if ERROR set
  319. mov bl,al ; AL is error code
  320. neg bx ; make it negative code
  321. add bx,ED_PROTECT ; normalize for extended errors
  322. rddev_no_err:
  323. add sp,RH4_CDEV_LEN ; free up RH_ on stack
  324. ret ; return BX
  325. inst_io_getchar:
  326. push ds
  327. lds si,ds:RH4_BUFFER[bx] ; point to the users buffer
  328. lodsb ; get 1st char in the buffer
  329. pop ds
  330. ret
  331. read_con: ; handle read from cooked console
  332. ;--------
  333. ; entry: AH = DHNDL_ATTR
  334. ; ES:BX -> DHNDL_
  335. ; 2[BP] -> F_DOS parameter block
  336. ; exit: BX = return value
  337. xor cx,cx ; assume we've already had EOF
  338. test ah,DHAT_READY ; now see if we have
  339.  jnz con_dev_not_eof
  340. jmp con_dev_exit ; yes, just return zero chars read
  341. con_dev_not_eof:
  342. push es
  343. push bx ; save DHNDL_
  344. con_dev_loop:
  345. mov bx,word ptr fdos_buf ; get # of bytes already used
  346. xor ax,ax
  347. xchg al,bh ; get # bytes in the buffer
  348. inc ax ! inc ax ; also count the CR/LF
  349. sub ax,bx ; have we any bytes left in the buffer?
  350.  ja con_dev_cont ; yes, return them
  351.   ; no, we need a fresh input line
  352. mov fdos_buf,128 ; read up to 128 characters
  353. mov si,2[bp] ; SI -> parameter block
  354. mov bx,ds:2[si] ; BX = input handle
  355. push ds ! pop es
  356. mov dx,offset fdos_buf ; ES:DX -> console buffer
  357. mov cx,bx ; output to same handle as input
  358. push bx
  359. push bp
  360. call read_line ; read edited line
  361. pop bp
  362. mov bl,fdos_buf+1 ; # byte we have read
  363. mov bh,0 ; BX = # of characters read
  364. mov word ptr fdos_buf+2[bx],0A0Dh; append carriage return/line feed
  365. mov fdos_buf,0 ; start reading at beginning
  366. lea si,fdos_buf+3[bx] ; Echo the LF character to the 
  367. pop bx ; Same Output handle
  368. mov cx,1 ; Only One Character
  369. call cooked_write
  370. jmps con_dev_loop
  371. con_dev_cont: ; BX = buffer offset
  372. mov di,2[bp] ; DI -> parameter block
  373. mov cx,ds:8[di] ; CX = # of bytes to read
  374. cmp cx,ax ; reading more than available?
  375.  jbe con_dev_ok ; no, read as much as you want
  376. mov cx,ax ; else take all that there is
  377. con_dev_ok:
  378. add fdos_buf,cl ; update buffer index for next time
  379. les di,ds:4[di] ; ES:DI -> buffer to read into
  380. lea si,fdos_buf+2[bx] ; DS:SI -> function 10 buffer
  381. push cx ; save count
  382. rep movsb ; read all the data
  383. pop cx ; restore count
  384. mov al,1Ah ; now we look for EOF mark...
  385. push ds ! pop es
  386. lea di,fdos_buf+2[bx] ; ES:DI -> function 10 buffer
  387. mov si,cx ; keep count safe
  388. repne scasb
  389. xchg cx,si ; restore count
  390. pop bx ; recover DHNDL_
  391. pop es
  392.  jne con_dev_exit ; if no EOF, skip to exit
  393. sub cx,si ; subtract any after EOF mark
  394. dec cx ; and the EOF mark itself
  395. and es:DHNDL_ATTR[bx],not DHAT_READY
  396. con_dev_exit:
  397. mov di,2[bp] ; DI -> parameter block
  398. mov ds:8[di],cx ; set # of characters read
  399. sub bx,bx ; good return code
  400. ret
  401. eject
  402. first_dev: ; F_DOS FIRST call on device performed
  403. ;--------- ; Called with MXDisk
  404. ; On Entry:
  405. ; ES:BX -> device header
  406. ; On Exit:
  407. ; dma_buffer initialised with device name
  408. ;
  409. mov dx,es ; DX:BX -> device header
  410. call les_di_dmaptr ; ES:DI -> DMA buffer
  411. mov al,0FFh ; invalidate search state for NEXT
  412. mov cx,21
  413. rep stosb
  414. mov al,40h ; mark it as a device
  415. stosb
  416. sub ax,ax
  417. mov cx,4
  418. rep stosw ; zero time, date, file size
  419. lea si,10[bx]
  420. push ds
  421. mov ds,dx ; DS:SI -> name in device header
  422. mov cx,4
  423. rep movsw ; copy device name across
  424. pop ds
  425. mov cx,8
  426. frstdev1: ; scan off trailing spaces
  427. cmp es:byte ptr 0-1[di],' '
  428.  jne frstdev2
  429. dec di
  430. loop frstdev1
  431. frstdev2:
  432. mov al,0
  433. stosb ; add a trailing NUL
  434. ret
  435. eject
  436. ioc6_dev: ; IOCTL(6) - input status for device
  437. ;--------
  438. ; entry: ES:BX -> DHNDL_
  439. mov al,CMD_INPUT_NOWAIT
  440. jmps ioc67d ; call the device driver
  441. ioc7_dev: ; IOCTL(7) - output status for device
  442. ;--------
  443. ; entry: ES:BX -> DHNDL_
  444. mov al,CMD_OUTPUT_STATUS ; OUTPUT STATUS
  445. ioc67d: ; common code for I/O STATUS
  446. push ds
  447. sub sp,RH5_LEN-2*word ; allocate request header on stack
  448. push ax ; RH_CMD = AL
  449. mov ax,RH5_LEN
  450. push ax ; RH_LEN = RH5_LEN
  451. lds si,es:DHNDL_DEVPTR[bx] ; DS:SI -> device driver
  452. push ss ! pop es
  453. mov bx,sp ; ES:BX -> RH_
  454. mov es:RH5_CHAR[bx],0 ; zero the char
  455. call device_driver ; do the CALLF's to the device driver
  456. xor dl,dl ; assume not ready
  457. mov dh,es:RH5_CHAR[bx] ; possible peeked character
  458. add sp,RH5_LEN ; recover stack space
  459. pop ds
  460. test ax,RHS_ERROR+RHS_BUSY ; test if BUSY bit set in status
  461.  jnz ioc67d_ret ; device not ready if error or busy
  462. dec dl ; return ready DL = FF
  463. ioc67d_ret:
  464. mov si,2[bp] ; SI -> user's parameter block
  465. mov ds:6[si],dx ; update returned status
  466. sub bx,bx ; no error occurred
  467. ret ; for now
  468. end ; of CDEVIO.A86