;***************************************************** ;* ;* BDOS interface ;* ;***************************************************** BMPM equ true BCPM equ false CSEG if PCMODE EXTRN bdosrw:NEAR EXTRN compfs:NEAR EXTRN closef:NEAR EXTRN deletef:NEAR EXTRN getspace:NEAR EXTRN makef:NEAR EXTRN openf:NEAR EXTRN chk_pcfcb:NEAR EXTRN pc_chkrec:NEAR EXTRN pcsearch:NEAR EXTRN renamef:NEAR EXTRN setattsf:NEAR EXTRN setstamp:NEAR EXTRN truncatef:NEAR EXTRN xfcb:NEAR PUBLIC check_fcb1 PUBLIC check_fcb3 PUBLIC checkwrite PUBLIC chk_olist PUBLIC chk_wild PUBLIC chk_wild0 PUBLIC ckrofile PUBLIC close021 PUBLIC conv_rr PUBLIC copy_user_no PUBLIC dblockio PUBLIC directio PUBLIC discard_data PUBLIC flush PUBLIC flushx PUBLIC fxi40 PUBLIC get_atts PUBLIC init_wzf PUBLIC lret_eq_ff PUBLIC openx1a PUBLIC pack_sdcnt PUBLIC pc_make_test PUBLIC rd_pcdir PUBLIC reset_checksum_fcb PUBLIC roferror PUBLIC search_olist PUBLIC seek; PUBLIC setcdr PUBLIC setenddir PUBLIC set_aret PUBLIC set_lret1 PUBLIC test_lock PUBLIC tst_olist PUBLIC update_fat PUBLIC wrbuff; PUBLIC wrdir endif org 0000h jmp init ;bdos initialization jmp entry ;inter module entry pt. sysdat dw 0 ;seg address of sysdat supervisor rw 2 ;supervisor offset and segment dev_ver dw 6 ; chk'd by GENSYS db 'COPYRIGHT(C)1983,84,' db 'DIGITAL RESEARCH(02/07/84)' db 'XXXX-0000-654321' ;==== init: ; initialize bdos/xios modules ;==== ; entry: DS = system data area ; code segment values setup by gensys ; mov sysdat,ds ; mov ax,supmod ; mov cs:supervisor,ax ; mov ax,supmod+2 ; mov cs:supervisor+2,ax retf ;***************************************************** ;* ;* bdos function table ;* ;***************************************************** ; structure of entry in functab btab_addr equ word ptr 0 btab_flag equ byte ptr (btab_addr + word) bf_getmx equ 00001b ;get mxdisk queue bf_cshell equ 00010b ;conditional shell function bf_fcb33 equ 00100b ;33 byte fcb flag bf_fcb36 equ 01000b ;36 byte fcb flag bf_resel equ 10000b ;disk reselect flag ; bdos function table functab dw func13 ! db 00001b ; fxi13 equ 00h ;disk reset dw func14 ! db 00001b ; fxi14 equ 01h ;select disk dw func15 ! db 10101b ! fxi15 equ 02h ;open file ftab16 dw func16 ! db 10101b ! fxi16 equ 03h ;close file dw func17 ! db 00101b ! fxi17 equ 04h ;search first dw func18 ! db 00001b ! fxi18 equ 05h ;search next dw func19 ! db 10101b ! fxi19 equ 06h ;delete file dw func20 ! db 10111b ! fxi20 equ 07h ;read sequential dw func21 ! db 10111b ! fxi21 equ 08h ;write sequential dw func22 ! db 00101b ! fxi22 equ 09h ;make file dw func23 ! db 10101b ! fxi23 equ 0Ah ;rename file dw func24 ! db 00000b ; fxi24 equ 0Bh ;return login vector dw func25 ! db 00000b ; fxi25 equ 0Ch ;return current disk dw func26 ! db 00000b ; fxi26 equ 0Dh ;set dma address dw func27 ! db 00001b ! fxi27 equ 0Eh ;get alloc addr dw func28 ! db 00001b ; fxi28 equ 0Fh ;write protect disk dw func29 ! db 00000b ; fxi29 equ 10h ;get r/o vector dw func30 ! db 00101b ! fxi30 equ 11h ;set file attributes dw func31 ! db 00001b ! fxi31 equ 12h ;get disk parm addr dw func32 ! db 00000b ; fxi32 equ 13h ;set/get user code dw func33 ! db 11011b ! fxi33 equ 14h ;read random dw func34 ! db 11011b ! fxi34 equ 15h ;write random dw func35 ! db 11001b ! fxi35 equ 16h ;compute file size dw func36 ! db 01001b ; fxi36 equ 17h ;set random record dw func37 ! db 00001b ; fxi37 equ 18h ;reset drive dw func38 ! db 00001b ; fxi38 equ 19h ;access drive dw func39 ! db 00001b ! fxi39 equ 1Ah ;free drive dw func40 ! db 11011b ! fxi40 equ 1Bh ;write random w/zero fill dw func42 ! db 11001b ! fxi42 equ 1Ch ;lock record dw func43 ! db 11001b ! fxi43 equ 1Dh ;unlock record dw func44 ! db 00000b ; fxi44 equ 1Eh ;set multi-sector count dw func45 ! db 00000b ; fxi45 equ 1Fh ;set bdos error mode dw func46 ! db 00001b ; fxi46 equ 20h ;get disk free space dw func48 ! db 00001b ! fxi48 equ 21h ;flush buffers dw func51 ! db 00000b ; fxi51 equ 22h ;set dma base dw func52 ! db 00000b ; fxi52 equ 23h ;get dma base dw func98 ! db 00001b ! fxi98 equ 24h ;reset alloc vector dw func99 ! db 01001b ! fxi99 equ 25h ;truncate file dw func100 ! db 00101b ! fxi100 equ 26h ;set directory label dw func101 ! db 00001b ; fxi101 equ 27h ;return directory label data dw func102 ! db 00101b ! fxi102 equ 28h ;read file xfcb dw func103 ! db 00101b ! fxi103 equ 29h ;write or update file xfcb dw func104 ! db 00000b ; fxi104 equ 2Ah ;set current date and time dw func105 ! db 00000b ; fxi105 equ 2Bh ;get current date and time dw func106 ! db 00001b ; fxi106 equ 2Ch ;set default password dw func116 ! db 10101b ; fxi113 equ 2Dh ;set file date and time dw pr_term ! db 00001b ! fxi143 equ 2Eh ;terminate process dw funcdio ! db 00001b ; fxi??? equ 2Fh ;direct disk I/O ;===== entry: ; bdos module entry point ;===== ; entry: CL = internal bdos function number ; DX = argument ; DS = system data area ; ES = user data area ; exit: AX = BX = return code xor ch,ch! mov si,cx shl si,1! add si,cx ; multiply by 3 add si,offset functab test cs:btab_flag[si],bf_getmx jz nomx call getdiskmx jmps exit nomx: xor bx,bx ;initialize return parameter call cs:btab_addr[si] exit: mov ax,bx retf restart: ;restart entry point for media changes ;------- mov cl,fx_intrn ;CX = internal function # xor ch,ch ;SI = offset of BDOS functab entry mov si,cx shl si,1 add si,cx add si,offset functab mov bx,rlr ;BX = PD addr mov dx,info ;DX = argument addr mov es,uda_save ;ES = UDA addr cli jmps setup_stack getdiskmx: ;--------- ; entry: SI = offset of bdos functab entry ; CX = internal bdos function number ; DX = argument mov bx,rlr mov ax,p_flag[bx] ! and ax,pf_tempkeep push ax ;save tempkeep flag or p_flag[bx],pf_tempkeep ;do not allow ctrl c while in bdos push si! push dx! push cx mov cx,f_qread ! mov dx,offset mxdiskqpb call mpmif ;get mxdisk queue pop cx! pop dx! pop si or ax,ax! jz $+5 ;was MXQ read successful? jmp retmonx1 ;no mov fx_intrn,cl ;save internal bdos func # mov bx,rlr test p_flag[bx],pf_ctlc jz not_ctlc xor al,al ;AL = no error message to print mov bx,0ffffh jmp retmonxa not_ctlc: cli ;switch to internal bdos stack mov ss_save,ss mov sp_save,sp setup_stack: mov ss,sysdat mov sp,offset bdosstack sti mov pdaddr,bx ;BX = rlr mov ax,word ptr p_dsk[bx] mov word ptr seldsk,ax ;set default disk and user code mov ax,u_wrkseg ;initialize bdos data area for user mov parametersegment,ax mov ax,u_retseg mov returnseg,ax mov u_ioexerr,0FFh ;initialize IOS extended error byte push es mov uda_save,es ;save uda segment push si mov ax,ds! mov bx,es ;copy uda bdos vars to local area mov ds,bx! mov es,ax mov si,offset u_dma_ofst mov di,offset dma_ofst mov cx,uda_ovl_len rep movsb mov ds,ax mov ax,dma_ofst mov cl,4! shr ax,cl add dma_seg,ax and dma_ofst,000fh mov cx,zerolength ! xor al,al ;zero local variables mov di,offset fcbdsk rep stosb mov info,dx ;info=dx mov linfo,dl ;linfo = low(info) - don't equ pop si! push si mov ah,cs:btab_flag[si] test ah,bf_fcb33! jz notfcb33 ;if 33 byte fcb call parsave33! jmps notfcb36 ; copy 33 bytes to local FCB notfcb33: test ah,bf_fcb36! jz notfcb36 ;else if 36 byte fcb call parsave36! call save_rr ; copy 36 bytes to local FCB notfcb36: ; and save random record bytes pop si cmp mult_cnt,1 ! je noshell ;if mult_cnt <> 1 and test cs:btab_flag[si],bf_cshell ; func uses mult_cnt then jz noshell call shell ; use bdos multi sector shell jmps retmon noshell: call call_bdos retmon: mov cl,parlg or cl,cl! jz retmon6 xor ch,ch ;copy local FCB back to user segment? mov si,offset info_fcb mov di,info mov es,parametersegment rep movsb retmon6: pop es ;restore uda segment mov si,offset dma_ofst+4 ! mov di,offset u_dma_ofst+4 mov cx,uda_ovl_len-4 rep movsb mov ax,returnseg ;setup return registers mov u_retseg,ax mov bx,aret pushf ! pop ax ! cli ;switch back to user's stack mov ss,ss_save mov sp,sp_save push ax ! popf mov al,err_type retmonxa: push bx ;save return code test al,true jz retmonx js denied_typ push parametersegment ;fcb segment mov bx,0ffffh ;0ffffh => no fcb to print in message test resel,true jz no_fcb mov bx,info ;fcb offset no_fcb: push bx jmps comn_dat denied_typ: push err_pd_addr ;denied error pd address comn_dat: mov ah,err_drv retmonx: push ax ;AL = error message type to print mov cx,f_qwrite ! mov dx,offset mxdiskqpb call mpmif ;release mxdisk queue pop ax test al,0ffh jnz $+5! jmp retmonx1a push ax mov bx,offset msg_spb mov cx,f_sync call mpmif cmp word ptr err_intercept+2,0 ;check if error interception je ret_err0 ; no callf dword ptr err_intercept ;call intercept routine jmp free_spb ret_err0: pop ax add ah,'A' test al,0ffh jns $+5! jmp denied_err push ax mov dskerr,ah ;set D: field mov dx,offset dskmsg call xprint ;print "CP/M Error On D:" pop ax mov bl,al xor bh,bh shl bx,1 mov dx,xerr_list[bx] ;compute extended error message offset call xprint ;print error message mov al,u_func ;convert func# to character mov ch,30h mov bx,offset pr_fx1 cmp al,100! jb ret_err1 mov b[bx],31h inc bx sub al,100 ret_err1: sub al,10! jb ret_err2 inc ch jmps ret_err1 ret_err2: mov [bx],ch inc bx add al,3ah mov [bx],al inc bx mov b[bx],20h mov bx,offset pr_fcb ;0 = message delimiter mov b[bx],0 pop si! pop dx ;DX,SI = offset of fcb inc si ;was reselect called? jz ret_err3 ;no - don't print fcb mov b[bx],20h ;remove delimiter mov di,offset pr_fcb1 mov ax,ds! mov bx,es mov es,ax ;ES = DS mov ds,dx ;DS = parametersegment mov cx,4 ;move file name to message rep movsw mov es:b[di],'.' ;move '.' to message inc di mov cl,3 ;move file type to message rep movsb mov ds,ax! mov es,bx ;restore DS,ES ret_err3: mov dx,offset pr_fx ;print "bdos function = ### " call xprint ; + "file = ffffffff.ttt" jmps free_spb denied_err: mov denieddrv,ah pop si mov al,p_cns[si] add al,'0' mov deniedcns,al add si,p_name mov di,offset deniedprc push es! push ds! pop es ;ES = DS mov cx,4 ;copy process name to message rep movsw pop es ;restore ES mov dx,offset deniedmsg call xprint free_spb: mov dx,offset crlf_str call xprint mov bx,offset msg_spb mov cx,f_unsync call mpmif retmonx1a: pop bx ;restore retcode retmonx1: mov si,rlr pop ax ;restore tempkeep flag or ax,not pf_tempkeep and p_flag[si],ax test p_flag[si],pf_ctlc ;see if control C occured jz mxdiskexit mov cx,f_terminate! xor dx,dx push bx! call mpmif! pop bx mxdiskexit: ret call_bdos: ;--------- ; entry: DX = argument ; SI = offset of bdos functab entry mov save_sp,sp test cs:btab_flag[si],bf_resel jz cbdos1 push si call reselect pop si cbdos1: call cs:btab_addr[si] bdos_return: cmp resel,0 je retmon5 cmp comp_fcb_cks,true! jne retmon1 call set_chksum_fcb retmon1: mov al,xfcb_read_only mov bx,offset info_fcb or f7[bx],al mov al,high_ext cmp al,60h! jne retmon3 or byte ptr f8[bx],80h jmps retmon4 retmon3: or extnum[bx],al retmon4: mov al,actual_rc or reccnt[bx],al mov al,fcbdsk mov drv[bx],al retmon5: ret shell: ;----- ; entry: SI = offset of functab entry mov shell_si,si mov ah,cs:btab_flag[si] mov al,mult_cnt mult_io1: MOV MULT_NUM,AL push ax mov si,shell_si mov dx,info call call_bdos mov bl,byte ptr aret or bl,bl pop ax jz no_shell_err cmp bl,0ffh! je shell04 mov bh,mult_cnt sub bh,al ;BH = # of successfull records jmps shell03 no_shell_err: test ah,bf_fcb36! jz mult_io2 ;AH = entry functab flags call incr_rr mult_io2: add dma_ofst,80h dec al jnz mult_io1 xor bx,bx shell03: mov aret,bx test info_fcb+modnum,80h jnz shell04 test high_ext,80h jz shell04 push ax! push bx mov si,offset ftab16 or info_fcb+f5,80h mov aret,0 call call_bdos pop ax cmp lret+1,0 jnz shell03b cmp lret,0 jz shell03a mov al,11 shell03a: mov aret,ax shell03b: pop ax shell04: test ah,bf_fcb36! jz parret ;jmps reset_rr reset_rr: ;-------- call save_rr2! jmps save_rr1 save_rr: ;------- call save_rr2! xchg bx,dx save_rr1: mov cl,3! jmp move save_rr2: mov bx,offset info_fcb+ranrec mov dx,offset shell_rr ret parsave33: ;copy 33 byte length FCB ;--------- mov cl,33 jmps parsave parsave36: ;copy 36 byte length FCB ;--------- mov cl,36 parsave: ;copy FCB from user segment to bdos segment ;------- ; entry: CL = length of FCB to save mov parlg,cl xor ch,ch mov si,info mov di,offset info_fcb push ds mov ds,parametersegment rep movsb pop ds parret: ret incr_rr: ;------- ; exit: AX = preserved mov bx,offset info_fcb+ranrec inc w[bx]! jnz incr_rr_ret inc byte ptr 2[bx] incr_rr_ret: ret xprint: ;print message at DX ;------ ; entry: DX = offset of message to print push dx mov cx,f_cconattch ;make sure we own console before call mpmif ; attempting to print message pop dx or al,al! jnz parret mov cx,f_conprint ;jmps mpmif ;these functions added for mpm interface ;===== mpmif: ;call mpm function ;===== mov si,rlr push es! mov es,p_uda[si] callf cs:dword ptr supervisor pop es ret ;***************************************************** ;* ;* bdos - xios interface ;* ;***************************************************** ;====== ======================== xiosif: ; xios interface routine ;====== ======================== ; entry: AL = function number ; CX = argument 1 ; DX = argument 2 ; exit: AX = BX = output push es! mov es,uda_save callf dword ptr xiosmod cld! pop es ret ;======== ================================ rwxiosif: ; disk read/write xios interface ;======== ================================ ; entry: AL = function number ; exit: AX = BX = output mov dx,arecord mov ch,byte ptr arecord+2 mov bl,curdsk mov bh,1 xchg bh,mult_sec ;BH = multi sector count ; stack on entry to the xios push bx ; +C | DRV | MCNT | push track ; +A | TRACK | push sector ; +8 | SECTOR | push cur_dma_seg ; +6 | DMA_SEG | push cur_dma ; +4 | DMA_OFF | ; +2 | RET_SEG | ; SP+0 | RET_OFF | mov es,uda_save callf dword ptr xiosmod add sp,10 ;remove parameters from stack cld! push ds! pop es ret ;************* end of BDOS interface ****************