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

操作系统开发

开发平台:

Asm

  1. title 'FCB - DOS file system FCB support'
  2. ;    File              : $FCBS.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. ;    FCBS.A86 1.10 93/11/11 15:38:14
  33. ;    Chart Master fix - fcb_readblk over > 64k is truncated to 64k and
  34. ;    error 2 (Segment boundry overlap) is returned
  35. ;    FCBS.A86 1.9 93/10/18 17:37:06
  36. ;    fix for >255 open files (PNW Server)
  37. ;    ENDLOG
  38. eject ! include i:fdos.equ
  39. eject ! include i:msdos.equ
  40. eject ! include i:mserror.equ
  41. eject ! include i:doshndl.def ; DOS Handle Structures
  42. eject
  43. BDOS_DATA dseg word
  44. BDOS_CODE cseg
  45. extrn ifn2dhndl:near
  46. extrn parse_one:near
  47. extrn fdos_entry:near
  48. Public fdos_exit
  49. eject
  50. ; TERMINATE CHILD (EXIT)
  51. ; +----+----+
  52. ; |    24   |
  53. ; +----+----+
  54. ; entry:
  55. ; ------
  56. ; -none-
  57. ; exit:
  58. ; -----
  59. ; -none-
  60. ; Close down all FCB handles associated with the current PSP
  61. ;
  62. fdos_exit:
  63. ;---------
  64. push ds
  65. push ss ! pop ds ; DS -> PCM_DSEG
  66. sub ax,ax ; start with first DHNDL_
  67. fdos_exit10:
  68. call ifn2dhndl ; get DHNDL_
  69.  jc fdos_exit40 ; stop if we have run out
  70. mov fcb_pb+2,ax ; we may close this IFN
  71. push ax
  72. mov cx,es:DHNDL_COUNT[bx] ; get the open count
  73.  jcxz fdos_exit30 ; skip if nothing to do
  74. mov ax,current_psp ; get current PSP
  75. cmp ax,es:DHNDL_PSP[bx] ; does it belong to this PSP
  76.  jne fdos_exit30
  77. mov ax,ss:machine_id ; get current process
  78.     cmp ax,es:DHNDL_UID[bx] 
  79.  jne fdos_exit30
  80. test es:DHNDL_MODE[bx],DHM_FCB
  81.  jz fdos_exit20 ; skip close if not FCB
  82. push es
  83. push bx ; save the DHNDL
  84. mov ax,MS_X_CLOSE
  85. call fcb_fdos ; make the FDOS do the work
  86. pop bx
  87. pop es ; recover the DHNDL
  88. fdos_exit20:
  89. mov es:DHNDL_COUNT[bx],0 ; always free the handle if it's ours
  90. fdos_exit30:
  91. pop ax
  92. inc al ; onto next IFN
  93.  jnz fdos_exit10
  94. fdos_exit40:
  95. pop ds
  96. ret
  97. Public fdos_fcb
  98. eject
  99. ; GENERIC FCB FUNCTION (FCB)
  100. ; +----+----+----+----+----+----+----+----+
  101. ; |    22   |       fcbadr      |  count  |
  102. ; +----+----+----+----+----+----+----+----+
  103. ; |  func   |
  104. ; +----+----+
  105. ; entry:
  106. ; ------
  107. ; fcbadr: FCB address
  108. ; count: multi-sector count for read/write
  109. ; func: FCB sub-function
  110. ; exit:
  111. ; -----
  112. ; AX: return code or error code ( < 0)
  113. fdos_fcb:
  114. ;--------
  115. mov bx,2[bp] ; BX -> parameter block
  116. mov bx,8[bx] ; get subfunction code
  117. shl bx,1 ; make it word index
  118. sub bl,15*WORD ; adjust to base address
  119.  jc fcb_error ; reject if too low
  120. cmp bl,FCB_MAX1 ; is it in 1st block
  121.  jb fdos_fcb10
  122. sub bl,(33-24)*WORD ; adjust for gap
  123.  jc fcb_error
  124. cmp bl,FCB_MAX2 ; is it in 2nd block
  125.  jb fdos_fcb10
  126. sub bl,(39-37)*WORD ; adjust for gap
  127.  jc fcb_error
  128. fdos_fcb10:
  129. cmp bx,FCB_MAX3 ; check the range
  130.  jae fcb_error ; skip if invalid function
  131. jmp fcb_table[bx] ; call the right function
  132. fcb_error:
  133. mov bx,ED_FUNCTION
  134. ret
  135. fcb_table dw fcb_open ; 15-open file
  136. dw fcb_close ; 16-close file
  137. dw fcb_first ; 17-find first
  138. dw fcb_next ; 18-find next
  139. dw fcb_delete ; 19-delete file
  140. dw fcb_read ; 20-read from file
  141. dw fcb_write ; 21-write to file
  142. dw fcb_make ; 22-make file
  143. dw fcb_rename ; 23-rename file
  144. FCB_MAX1 equ (offset $ - offset fcb_table)
  145. dw fcb_readrand ; 33-read from file
  146. dw fcb_writerand ; 34-write to file
  147. dw fcb_size ; 35-compute file size
  148. dw fcb_setrecord ; 36-set relative record
  149. FCB_MAX2 equ (offset $ - offset fcb_table)
  150. dw fcb_readblk ; 39-read from file
  151. dw fcb_writeblk ; 40-write to file
  152. FCB_MAX3 equ (offset $ - offset fcb_table)
  153. fcb_make:
  154. ;--------
  155. call fcb_path_prep ; build pathname
  156. mov ax,MS_X_CREAT
  157. jmps fcb_open_make_common
  158. fcb_open:
  159. ;--------
  160. call fcb_path_prep ; build pathname
  161. mov ax,MS_X_OPEN
  162. fcb_open_make_common:
  163. mov fcb_pb+6,DHM_RW+DHM_FCB ; open as an FCB for read/write
  164. call fcb_fdos ; lets try and open the file
  165.  jnc fcb_open10 ; skip if we can't
  166. ret
  167. fcb_open10:
  168. call ifn2dhndl ; ES:BX -> DHNDL_ we have opened
  169. push ds
  170. push es ! push bx ; save DHNDL_
  171. call fcb_point ; ES:BX = FCB
  172. pop si ! pop ds ; DS:SI -> DHNDL_
  173. mov es:MSF_IFN[bx],al ; store IFN away
  174. mov es:MSF_BLOCK[bx],0 ; current block number
  175. mov es:MSF_RECSIZE[bx],128 ; current logical record size
  176. call fcb_update ; update misc changing fields
  177. mov ax,ds:DHNDL_DEVOFF[si]
  178. mov es:word ptr MSF_DEVPTR[bx],ax
  179. mov ax,ds:DHNDL_DEVSEG[si]
  180. mov es:word ptr MSF_DEVPTR+2[bx],ax
  181. mov ax,ds:DHNDL_BLK1[si]
  182. mov es:MSF_BLOCK1[bx],ax
  183. mov al,ds:DHNDL_ATTR[si]
  184. mov es:MSF_IOCTL[bx],al
  185. mov al,es:MSF_DRIVE[bx] ; get drive from FCB
  186. dec al ; was absolute drive specified ?
  187.  jns fcb_open20 ; if so use it
  188. mov al,ss:current_dsk ; else use default drive
  189. fcb_open20:
  190. inc al ; make drive 1 rather than 0 based
  191. mov es:MSF_DRIVE[bx],al ; drive code
  192. if 0
  193. test ds:DHNDL_DATRB[si],DA_VOLUME
  194. else
  195. test ss:fcb_pb+8,DA_VOLUME
  196. endif
  197. pop ds
  198.  jnz fcb_close ; don't leave VOL label's open
  199. xor bx,bx ; no errors !
  200. ret
  201. fcb_update:
  202. ;----------
  203. ; On Entry:
  204. ; DS:SI -> DHNDL_
  205. ; ES:BX -> FCB
  206. ; On Exit:
  207. ; DATE/TIME/SIZE/DBLK/DCNT fields updated
  208. ;
  209. mov ax,ds:DHNDL_TIME[si]
  210. mov es:MSF_TIME[bx],ax
  211. mov ax,ds:DHNDL_DATE[si]
  212. mov es:MSF_DATE[bx],ax
  213. mov ax,ds:DHNDL_SIZELO[si]
  214. mov es:MSF_SIZE[bx],ax
  215. mov ax,ds:DHNDL_SIZEHI[si]
  216. mov es:MSF_SIZE+2[bx],ax
  217. mov ax,ds:DHNDL_DBLK[si]
  218. mov es:MSF_DBLK[bx],ax
  219. mov al,ds:DHNDL_DCNTLO[si]
  220. mov ah,ds:DHNDL_DCNTHI[si]
  221. mov es:MSF_DCNT[bx],ax
  222. ret
  223. fcb_close:
  224. ;---------
  225. ; close file (DOS function 10h)
  226. call fcb_point ; ES:BX -> FCB
  227. mov al,0FFh
  228. cmp al,es:MSF_IFN[bx] ; is it a multiple close ?
  229.  je fcb_fdos_common10 ;  don't re-open for this...
  230. call fcb_handle_vfy ; verify we have a sensible handle
  231. mov es:MSF_IFN[bx],al ; mark FCB as closed (it will be)
  232. mov ax,MS_X_CLOSE ; now close it
  233. ; jmps fcb_fdos_common
  234. fcb_fdos_common:
  235. ;---------------
  236. call fcb_fdos ; make the FDOS do the work
  237.  jc fcb_fdos_common20 ; return any error codes
  238. fcb_fdos_common10:
  239. xor bx,bx ; else return zero
  240. fcb_fdos_common20:
  241. ret
  242. fcb_rename:
  243. ;----------
  244. call fcb_path_prep
  245. call fcb_path2_prep
  246. mov ax,MS_X_RENAME ; it's a rename
  247. jmps fcb_fdos_common
  248. fcb_delete:
  249. ;----------
  250. call fcb_path_prep
  251. mov ax,MS_X_UNLINK ; it's a delete
  252. jmps fcb_fdos_common
  253. fcb_first:
  254. ;---------
  255. call fcb_path_prep ; prepare pathname
  256. mov ax,MS_X_FIRST ; we want to search 1st
  257. jmps fcb_search_common
  258. fcb_next:
  259. ;--------
  260. call fcb_restore_search_state
  261. mov ax,MS_X_NEXT
  262. fcb_search_common:
  263. call fcb_search ; 0 of OK, otherwise ED_..
  264.  jc fcb_search_common10
  265. call fcb_save_search_state ; save sucessful state
  266. xor bx,bx ; return code in BX
  267. fcb_search_common10:
  268. ret
  269. fcb_setrecord:
  270. ;-------------
  271. call fcb_point ; ES:BX -> FCB
  272. mov ax,128 ; multiply current block by 128
  273. mul es:MSF_BLOCK[bx] ;  to give current record number
  274. xor cx,cx
  275. mov cl,es:MSF_CR[bx] ; Add in the current record
  276. add ax,cx ;  to DX:AX to give the
  277. adc dx,0 ;  relative record
  278. mov es:MSF_RR[bx],ax ; save the result
  279. mov es:MSF_RR2[bx],dl
  280. xor bx,bx ; we did OK
  281. ret
  282. fcb_write:
  283. ;---------
  284. mov ax,MS_X_WRITE ; make it a write
  285. jmps fcb_seq_rw
  286. fcb_read:
  287. ;--------
  288. mov ax,MS_X_READ ; make it a read
  289. fcb_seq_rw:
  290. call fcb_handle_vfy ; verify we have a sensible handle
  291. push ax ; save the operation
  292. call fcb_get_count ; AX = bytes to read
  293. push ax ; save byte count
  294. call fcb_seek_seq ; Seek to position in the file
  295. pop cx ; recover byte to xfer
  296. pop ax ;  and the Operation Code
  297.  jc fcb_seq_rw10
  298. call fcb_rw ; do the Op
  299.  jc fcb_seq_rw10
  300. push bx ; save the error code
  301. call fcb_update_seq ; update FCB filepos
  302. pop bx ; recover error
  303. fcb_seq_rw10:
  304. ret
  305. fcb_rw:
  306. ; On Entry:
  307. ; AX = operation code
  308. ; CX = count
  309. ; fcb_pb+2 = IFN
  310. ; On Exit:
  311. ; BX = error code
  312. les dx,ss:dword ptr dma_offset
  313. add cx,dx ; see if we overflow
  314.  jc fcb_rw20
  315. sub cx,dx ; count back to normal
  316. push cx ; save target count
  317. mov fcb_pb+4,dx
  318. mov fcb_pb+6,es ; setup buffer address
  319. mov fcb_pb+8,cx ;  and target count
  320. call fcb_fdos ; ask the FDOS to do the read/write
  321.  jc fcb_rw10 ; we got a real error...
  322. push ds
  323. push es
  324. mov ax,fcb_pb+2 ; get IFN
  325. call ifn2dhndl ; ES:BX -> DHNDL_ we have open
  326. push es ! push bx ; save DHNDL_
  327. call fcb_point ; ES:BX = FCB
  328. pop si ! pop ds ; DS:SI -> DHNDL_
  329. call fcb_update ; update file size/time-stamp
  330. pop es
  331. pop ds
  332. pop ax ; recover target count
  333. mov cx,fcb_pb+8 ; we xfered this much
  334. cmp cx,ax ; did we xfer enough
  335.  jb fcb_rw30 ; nope..
  336. xor bx,bx ; xfer went OK
  337. ret
  338. fcb_rw10:
  339. pop ax ; discard target count
  340. ret
  341. fcb_rw20:
  342. ; Our DTA is too small - return 2
  343. mov bx,2 ; indicate the DTA is too small
  344. ; stc ; error - don't update FCB
  345. ret
  346. fcb_rw30:
  347. ; We have some form of EOF - lets look into it
  348. call fcb_point ; ES:BX = FCB
  349. mov bx,es:MSF_RECSIZE[bx] ; BX = record size
  350. mov ax,cx
  351. xor dx,dx ; DX:AX = bytes xfer'd
  352. div bx ; did we xfer a complete
  353. test dx,dx ;  number of records ?
  354.  jz fcb_rw40 ;  if so return 1
  355. ; Partial data was read - fill out with zero's and return 3
  356. inc ax ; allow for incomplete record
  357. push ax ; save rounded up xfer count
  358. les di,ss:dword ptr dma_offset
  359. add di,cx ; point to 1st byte after xfer
  360. mov cx,bx ; this many in a record
  361. sub cx,dx ; so this many weren't xfer'd
  362. xor ax,ax ; fill them with zero's
  363. rep stosb ; zap the bytes we didn't xfer to
  364. pop ax ; recover xfer count
  365. mul bx ;  and work out # bytes xfered
  366. xchg ax,cx ; return bytes in CX
  367. mov bx,3 ; indicate EOF (partial read)
  368. ; clc ; update FCB
  369. ret
  370. fcb_rw40:
  371. ; No Data was xfered - return 1
  372. mov bx,1 ; indicate EOF (no data read)
  373. ; clc ; update FCB
  374. ret
  375. fcb_writerand:
  376. ;-------------
  377. mov ax,MS_X_WRITE ; make it a write
  378. jmps fcb_random_rw
  379. fcb_readrand:
  380. ;------------
  381. mov ax,MS_X_READ ; make it a read
  382. fcb_random_rw:
  383. call fcb_handle_vfy ; check the handle is OK
  384. push ax ; save the code
  385. call fcb_get_count ; AX = bytes to read
  386. push ax ; save byte count
  387. xor cx,cx ; cause update of seq posn from
  388. call fcb_update_rr ;  random record position
  389. call fcb_seek_rr ; Seek to position in the file
  390. pop cx ; recover byte to xfer
  391. pop ax ;  and the Operation Code
  392.  jc fcb_random_rw10
  393. call fcb_rw ; do the Op
  394. fcb_random_rw10:
  395. ret
  396. fcb_writeblk:
  397. ;------------
  398. mov ax,MS_X_WRITE ; make it a write
  399. jmps fcb_block_rw
  400. fcb_readblk:
  401. ;-----------
  402. mov ax,MS_X_READ ; make it a read
  403. fcb_block_rw:
  404. call fcb_handle_vfy ; check the handle is OK
  405. push ax ; save the code
  406. call fcb_get_count ; AX = bytes per record, CX = # records
  407. xchg ax,cx ; CX = bytes per record
  408. mul cx ; AX = bytes to xfer
  409. test dx,dx ; more than 64K ?
  410.  jz fcb_block_rw10 ; then we should truncate it
  411. mov ax,15 ; AX = handy mask
  412. cwd ; DX = 0
  413. and ax,ss:dma_offset ; get dma offset for para
  414. not ax ; DX/AX = maximum bytes we can xfer
  415. div cx ; AX = maximum blocks we can xfer
  416. mul cx ; AX = bytes to xfer (now < 64K)
  417. fcb_block_rw10:
  418. push ax ; save byte count
  419. call fcb_seek_rr ; Seek to position in the file
  420. pop cx ; recover byte to xfer
  421. pop ax ;  and the Operation Code
  422.  jc fcb_block_rw20
  423. call fcb_rw ; do the Op
  424.  jc fcb_block_rw20
  425. push bx ; save the error code
  426. call fcb_update_rr ; update FCB filepos, get records xferd
  427. mov bx,2[bp] ; BX -> parameter block
  428. xchg cx,6[bx] ; update amount xfered
  429. sub cx,6[bx] ; CX = # we didn't xfer (normally 0)
  430. pop bx ; recover (possible) error
  431.  jcxz fcb_block_rw20 ; skip if we read all we wanted to
  432. test bx,bx ; did we have a partial read for
  433.  jnz fcb_block_rw20 ;  a reason like EOF ?
  434. mov bx,2 ; no, we must have truncated it
  435. fcb_block_rw20:
  436. ret
  437. fcb_size:
  438. ;--------
  439. call fcb_path_prep
  440. mov ax,MS_X_CHMOD ; it's a get info
  441. mov fcb_pb+6,0
  442. call fcb_fdos
  443.  jc fcb_size40
  444. call fcb_point ; ES:BX = FCB
  445. mov cx,es:MSF_RECSIZE[bx] ; get the record size
  446. test cx,cx ; is it non-zero ?
  447.  jnz fcb_size10 ;  if not
  448. mov cx,128 ;  make it 128 bytes
  449. fcb_size10:
  450. mov ax,fcb_pb+10
  451. mov dx,fcb_pb+12 ; DX:AX = file length in bytes
  452. call div_32 ; DX:AX = file length in records
  453.  jcxz fcb_size20 ; was there an overflow
  454. add ax,1
  455. adc dx,0 ; include an extra record
  456. fcb_size20:
  457. call fcb_point ; ES:BX = FCB
  458. mov es:MSF_RR[bx],ax ; low word of size
  459. mov es:MSF_RR2[bx],dl ; hi byte of size
  460. cmp es:MSF_RECSIZE[bx],64 ; if record size < 64 bytes
  461.  jae fcb_size30 ;  then we use a 4 byte
  462. mov es:MSF_RR2+1[bx],dh ;  random record position
  463. fcb_size30:
  464. xor bx,bx ; good return
  465. fcb_size40:
  466. ret
  467. ; Utility FCB subroutines
  468. ;========================
  469. fcb_handle_vfy:
  470. ;--------------
  471. ; Verify FCB is valid and open, do not return if it isn't
  472. ; nb. Called with nothing on stack
  473. ;
  474. ; On Entry:
  475. ; FCB address in parameter block
  476. ; On Exit:
  477. ; AX preserved
  478. ; ES:BX -> FCB (skipping EXT bit if present)
  479. ; fcb_pb+2 = IFN of handle
  480. ; On Error - blow away caller and return error in BX
  481. ;
  482. ; DEBUG - on reopen we could do more checks to ensure we are re-opening the
  483. ; same file
  484. push ax
  485. call fcb_point
  486. cmp es:MSF_RECSIZE[bx],0
  487.  jne fcb_handle_vfy10
  488. mov es:MSF_RECSIZE[bx],128
  489. fcb_handle_vfy10:
  490. mov al,es:MSF_IFN[bx] ; get IFN
  491. call ifn2dhndl ; ES:BX -> DHNDL_
  492.  jc fcb_handle_vfy20 ; it must be a valid IFN
  493. test es:DHNDL_MODE[bx],DHM_FCB
  494.  jz fcb_handle_vfy20 ; it must be an FCB..
  495. cmp es:DHNDL_COUNT[bx],0
  496.  jne fcb_handle_vfy30 ; it must also be open..
  497. fcb_handle_vfy20:
  498. call fcb_point
  499. push es:MSF_RECSIZE[bx] ; save current record size
  500. push es:MSF_BLOCK[bx] ; save current block number
  501. push es ! push bx
  502. call fcb_open ; try to re-open the file
  503. pop bx ! pop es ; point back at FCB
  504. pop es:MSF_BLOCK[bx] ; restore current block number
  505. pop es:MSF_RECSIZE[bx] ; restore record size
  506.  jc fcb_handle_err
  507. mov al,es:MSF_IFN[bx] ; get new IFN
  508. fcb_handle_vfy30:
  509. xor ah,ah
  510. mov fcb_pb+2,ax ; set parameter block accordingly
  511. call fcb_point ; ES:BX -> MSF_
  512. pop ax
  513. clc
  514. ret
  515. fcb_handle_err:
  516. add sp,2*WORD ; discard AX and near return address
  517. cmp ax,ED_HANDLE ; if we have run out of handles then
  518.  jne fcb_handle_err10 ;  say no FCB's, else return error
  519. mov ax,ED_NOFCBS
  520. fcb_handle_err10:
  521. xchg ax,bx ; error code in BX
  522. stc
  523. ret
  524. fcb_path2_prep:
  525. ;--------------
  526. ; On Entry:
  527. ; FCB address in parameter block
  528. ; On Exit:
  529. ; ES:BX -> FCB (skipping EXT bit if present)
  530. ; fcb_pb+6/8 -> unparse name from FCB
  531. ;
  532. call fcb_point ; point at the FCB
  533. mov al,es:MSF_DRIVE[bx] ; get drive
  534. add bx,16 ; point at 2nd name in FCB
  535. mov di,offset fcb_path2
  536. mov fcb_pb+6,di
  537. mov fcb_pb+8,ds ; point at buffer we want
  538. jmps fcb_path_prep_common
  539. fcb_path_prep:
  540. ;-------------
  541. ; On Entry:
  542. ; FCB address in parameter block
  543. ; On Exit:
  544. ; ES:BX -> FCB (skipping EXT bit if present)
  545. ; fcb_pb+2/4 -> unparse name from FCB
  546. ;
  547. xor ax,ax ; assume no attribute
  548. mov bx,2[bp] ; BX -> parameter block
  549. les bx,2[bx] ; ES:BX -> FCB
  550. cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB
  551.  jne fcb_path_prep10
  552. or al,es:MSF_ATTRIB[bx] ; we can use file mode from XFCB
  553. add bx,7 ; skip EXT bit of FCB
  554. fcb_path_prep10:
  555. mov fcb_pb+8,ax ; remember the attribute
  556. mov al,es:MSF_DRIVE[bx] ; get drive
  557. mov di,offset fcb_path
  558. mov fcb_pb+2,di
  559. mov fcb_pb+4,ds ; point at buffer we want
  560. fcb_path_prep_common:
  561. dec al ; 0 = default drive
  562.  jns fcb_path_prep20
  563. mov al,current_dsk ; use default drive
  564. fcb_path_prep20:
  565. push ds
  566. push ds ! push es
  567. pop ds ! pop es ; ES:DI -> name buffer
  568. add al,'A' ; make drive ASCII
  569. stosb
  570. mov al,':'
  571. stosb ; now we have 'd:'
  572. lea si,MSF_NAME[bx] ; DS:SI -> source name
  573. movsw ! movsw
  574. movsw ! movsw ; copy the name leaving spaces intact
  575. mov al,'.'
  576. stosb
  577. movsw ! movsb ; copy the extention
  578. pop ds
  579. ; jmps fcb_point ; point ES:BX at FCB again
  580. fcb_point:
  581. ;---------
  582. ; On Entry:
  583. ; FCB address in parameter block
  584. ; On Exit:
  585. ; ES:BX -> FCB (skipping EXT bit if present)
  586. ; (All other regs preserved)
  587. ;
  588. mov bx,2[bp] ; BX -> parameter block
  589. les bx,2[bx] ; ES:BX -> FCB
  590. cmp es:MSF_EXTFLG[bx],0ffh ; is it an extended FCB
  591.  jne fcb_point10
  592. add bx,7 ; skip EXT bit of FCB
  593. fcb_point10:
  594. ret
  595. fcb_get_count:
  596. ;-------------
  597. ; On Entry:
  598. ; none
  599. ; On Exit:
  600. ; AX = bytes per record
  601. ; CX = callers CX count
  602. ; All regs fair game
  603. ;
  604. call fcb_point ; ES:BX -> FCB
  605. mov si,2[bp] ; SI -> parameter block
  606. mov cx,6[si] ; CX = count
  607. mov ax,es:MSF_RECSIZE[bx] ; get record size
  608. ret
  609. fcb_update_seq:
  610. ;--------------
  611. ; On Entry:
  612. ; CX = byte count actually transferred
  613. ; On Exit:
  614. ; CX = record count transferred
  615. ; All other regs fair game
  616. ; CR/BLOCK updated with new value
  617. ;
  618. mov ax,cx
  619. xor dx,dx ; DX:AX = byte count transfered
  620. call fcb_point ; ES:BX -> FCB
  621. div es:MSF_RECSIZE[bx] ; make records xfered
  622. push ax ; save records xfered
  623. xchg ax,cx ; also in CX for later
  624. mov ax,128
  625. mul es:MSF_BLOCK[bx] ; DX:AX = record of block
  626. add ax,cx
  627. adc dx,0 ; add in amount just xfered
  628. mov cl,es:MSF_CR[bx]
  629. xor ch,ch ; now add in CR as a word
  630. add ax,cx
  631. adc dx,0 ; DX:AX = record
  632. mov dh,dl ; DH:AX = record for common code
  633. jmps fcb_update_common
  634. fcb_update_rr:
  635. ;-------------
  636. ; On Entry:
  637. ; CX = byte count actually transferred
  638. ; On Exit:
  639. ; CX = record count transferred
  640. ; All other regs fair game
  641. ; Random Record and CR/BLOCK updated with new value
  642. ;
  643. xchg ax,cx
  644. xor dx,dx ; DX:AX = byte count transfered
  645. call fcb_point ; ES:BX -> FCB
  646. div es:MSF_RECSIZE[bx] ; make records xfered
  647. push ax ; save records xfered
  648. add es:MSF_RR[bx],ax ; update the RR field
  649. adc es:MSF_RR2[bx],0 ;  and the overflow
  650. mov ax,es:MSF_RR[bx] ; get low part of RR
  651. mov dh,es:MSF_RR2[bx] ;  and the hi part
  652. fcb_update_common:
  653. mov dl,ah ; DX will be block number
  654. shl al,1 ; get top bit of CR into CY
  655. adc dx,dx ; then into DX
  656. shr al,1 ; AL = CR (remember mod 128)
  657. mov es:MSF_CR[bx],al ; set the CR field
  658. mov es:MSF_BLOCK[bx],dx ;  and the block field
  659. pop cx ; recover records xfered
  660. ret
  661. fcb_seek_seq:
  662. ;------------
  663. ; Seek to position in file indicated by the RR position
  664. ; On Entry:
  665. ; ES:BX -> FCB_
  666. ; On Exit:
  667. ; CY clear if no problem, fcb_pb+2=IFN
  668. ; else
  669. ; CY set, AX = BX = error code
  670. ; All other regs fair game
  671. ;
  672. call fcb_point ; ES:BX -> FCB_
  673. mov ax,128
  674. mul es:MSF_BLOCK[bx] ; get record in DX:AX
  675. mov cl,es:MSF_CR[bx]
  676. xor ch,ch
  677. add ax,cx ; add in CR
  678. adc dx,0 ; so DX:AX is really the record
  679. push ax ; save low word of record
  680. mov ax,dx
  681. mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h
  682. mov cx,ax ; save the important word
  683. pop ax ; recover low word of record
  684. jmps fcb_seek_common
  685. fcb_seek_rr:
  686. ;-----------
  687. ; Seek to position in file indicated by the RR position
  688. ; On Entry:
  689. ; ES:BX -> FCB_
  690. ; On Exit:
  691. ; CY clear if no problem, fcb_pb+2=IFN
  692. ; else
  693. ; CY set, AX = BX = error code
  694. ; All other regs fair game
  695. ;
  696. call fcb_point ; ES:BX -> FCB_
  697. mov al,es:MSF_RR2[bx]
  698. xor ah,ah
  699. mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file/10000h
  700. mov cx,ax ; save the important word
  701. mov ax,es:MSF_RR[bx]
  702. fcb_seek_common:
  703. mul es:MSF_RECSIZE[bx] ; DX:AX = byte offset in file
  704. add dx,cx ; add the two bits together
  705. mov fcb_pb+4,ax
  706. mov fcb_pb+6,dx ; save position
  707. mov fcb_pb+8,0 ; seek from start
  708. xor ax,ax
  709. mov al,es:MSF_IFN[bx] ; AX = IFN
  710. mov fcb_pb+2,ax ; save IFN
  711. mov ax,MS_X_LSEEK
  712. jmp fcb_fdos ; try and seek to this position
  713. fcb_search:
  714. ;----------
  715. ; On Entry:
  716. ; AX = operation to perform
  717. ; On Exit:
  718. ; AX = 0, or ED_ error code (CY set if error)
  719. push dma_offset
  720. push dma_segment
  721. mov dma_offset,offset fcb_search_buf
  722. mov dma_segment,ds
  723. call fcb_fdos ; do the search
  724. pop dma_segment
  725. pop dma_offset
  726. test ax,ax ; was there an error
  727. stc ; assume there was
  728.  js fcb_search10 ; return the error
  729. xor ax,ax ; no problems
  730. fcb_search10:
  731. ret
  732. fcb_save_search_state:
  733. ;---------------------
  734. ; On entry DS=PCMODE
  735. call fcb_point
  736. lea di,MSF_NAME[bx] ; ES:DI -> FCB name
  737. mov si,offset fcb_search_buf
  738. lodsb ; get 1st byte = drive info
  739. mov cx,20/WORD ; copy 20 bytes to FCB
  740. rep movsw ; (the rest of the search template)
  741. stosb ; drive info byte follow them
  742. les di,dword ptr dma_offset ; ES:DI -> search state in DMA address
  743. mov si,2[bp] ; SI -> parameter block
  744. lds si,2[si] ; DS:SI -> FCB_
  745. cmp ds:MSF_EXTFLG[si],0ffh ; extended FCB ?
  746.  jne fcb_sss10
  747. mov cx,7 ; copy extended FCB portions too
  748. rep movsb ; we have copied up to name
  749. fcb_sss10:
  750. stosb ; save drive byte info
  751. push di
  752. mov al,' ' ; space fill name
  753. mov cx,11
  754. rep stosb ; all blanks now
  755. pop di
  756. push ss ! pop ds ; DS:SI -> pathname
  757. mov si,offset fcb_search_buf+1Eh
  758. push di ; unparse knowing name is good
  759. mov cx,8 ; length of name field
  760. fcb_sss20:  
  761. lodsb ; treat '.' and '..' specially
  762. cmp al,'.' ; is either possible ?
  763.  jne fcb_sss30 ; no, continue as normal
  764. stosb ; copy the '.'
  765. loop fcb_sss20 ; go around for another '.'
  766. jmps fcb_sss40 ; this name is rubbish!!
  767. fcb_sss30:
  768. dec si ; forget the non '.'
  769. call parse_one ; parse just the name
  770. fcb_sss40:
  771. pop di
  772. add di,8 ; di -> fcb ext field
  773. cmp al,'.' ; do we have an extention ?
  774.  jne fcb_sss50
  775. mov cx,3 ; length of ext field
  776. push di
  777. call parse_one ; parse just extension
  778. pop di
  779. fcb_sss50:
  780. add di,3 ; di -> rest of fcb
  781. mov si,offset fcb_search_buf+15h
  782. movsb ; copy the attribute field
  783. xor ax,ax
  784. mov cx,10/WORD
  785. rep stosw ; 10 bytes of zeros
  786. movsw ; copy time
  787. movsw ; copy date
  788. mov ax,word ptr srch_buf+21+DBLOCK1
  789. stosw ; 1st block
  790. movsw ! movsw ; copy filesize
  791. ret
  792. fcb_restore_search_state:
  793. ;------------------------
  794. ; On entry DS=PCMODE
  795. push ds
  796. call fcb_point ; ES:BX -> FCB_
  797. push es ! push ds
  798. pop es ! pop ds ; swap DS/ES
  799. mov di,offset fcb_search_buf+1
  800. ; ES:DI -> internal state
  801. lea si,1[bx] ; DS:SI -> FCB+1
  802. mov cx,10
  803. rep movsw ; copy info from FCB
  804. lodsb ; get "drive" info
  805. mov es:fcb_search_buf,al ; it's the 1st byte in the srch state
  806. pop ds
  807. ret
  808. fcb_fdos:
  809. ;--------
  810. ; Make an FDOS call (NB. We don't have MX here, so it's OK)
  811. ; Set top bit of remote_call flag so we use IFN's not XFN's
  812. ; On Entry:
  813. ; AX = FDOS operation
  814. ; fcb_pb -> FDOS parameter block
  815. ; On Exit:
  816. ; As FDOS call
  817. ;
  818. mov fcb_pb,ax ; save operation type
  819. or remote_call,DHM_FCB ; forget about PSP during FCB call
  820. mov dx,offset fcb_pb ; DS:DX -> parameter block
  821. push ds
  822. push bp
  823. call fdos_entry ; call the FDOS
  824. pop bp
  825. pop ds
  826. and remote_call,not DHM_FCB ; FCB operation over
  827. cmp ax,ED_LASTERROR
  828. cmc ; CY set if an error occurred
  829. ret
  830. div_32:
  831. ; Entry: DX,AX = long dividend
  832. ; CX = word divisor
  833. ; Exit: DX,AX = long result
  834. ; CX = remainder
  835. jcxz div0 ; divide by 0
  836. cmp cx,1
  837.  je div1 ; divide by 1
  838. push di
  839. push bx
  840. xor bx,bx ; BX = 0
  841. xchg ax,bx ; low word in BX, AX = 0
  842. xchg ax,dx ; high word in DX:AX
  843. push ax ; save high word
  844. div cx ; divide high part
  845. mov di,ax ; save result
  846. mul cx ; AX = even divisor part
  847. pop dx ; old high in DX
  848. sub dx,ax ; eliminate even part
  849. xchg ax,bx ; AX = low word
  850. div cx ; low part in AX
  851. mov cx,dx ; CX = remainder
  852. mov dx,di ; high result in DX
  853. pop bx
  854. pop di
  855. ret
  856. div0:
  857. mov ax,-1
  858. mov dx,ax
  859. ret
  860. div1:
  861. dec cx ; CX = remainder = 0
  862. ret
  863. PCMODE_DATA DSEG WORD
  864. extrn fcb_pb:word
  865. extrn fcb_path:byte
  866. extrn fcb_path2:byte
  867. extrn fcb_search_buf:byte
  868. extrn current_dsk:byte
  869. extrn current_psp:word
  870. extrn dma_offset:word
  871. extrn dma_segment:word
  872. extrn machine_id:word
  873. extrn remote_call:word
  874. extrn srch_buf:byte
  875. end