.title ZTSERVER subroutines ; ; gce 7/1992 ; w.j.m. jun 1989 (0.2) ; documented 3-jul-1989 wjm ; mod 18-aug-1989 wjm (0.9): support VMS V5 ; .ident /0.1/ ;this version needs ZTDRIVERM 0.1 ; ;***** ; entries: ; status=ZT_INIT() - initialize, ; set up communication with ZTDRIVER. ; NOTE: an exit handler is set up, ; which MUST be executed eventually! ; ; status=ZT_WAIT() - wait for message (I/O request) from ZTDRIVER. ; On return, the 'message buffer' has been filled in. ; ; status=ZT_REQCOM() - send (part of) 'message buffer' ; to ZTDRIVER and complete I/O. ; ; status=ZT_TOUSER() - simulates DMA transfer ; from 'data buffer' to ZTDRIVER's user buffer. ; Number of bytes tranferred: ; MIN(UCB$W_BCNT,ZT_BUFDSC.dsc$w_length) ; Can be called at most once per I/O request! ; ; status=ZT_FRUSER() - simulates DMA transfer ; from ZTDRIVER's user buffer to 'data buffer'. ; Number of bytes transferred: ; UCB$W_BCNT ; On return, ZT_BUFDSC.dsc$w_length is set to this number. ; Can be called at most once per I/O request! ; ; ZT_MSGDSC (globaldef): ; Descriptor of 'message buffer' (see ZTDEF.MAR) ; used for communication with ZTDRIVER. ; Both buffer address and length are FIXED. ; ; ZT_BUFDSC (globaldef): ; Descriptor of 'data buffer' (see above). ; Buffer address is FIXED, actual size is ^xFFFF . ; ZT_BUFDSC.dsc$w_length is set by ZT_FRUSER(), ; and by caller of ZT_TOUSER(). ; ; ;***** ; .link "SYS$SYSTEM:SYS.STB"/selective_search .library "SYS$LIBRARY:LIB" .library "ZT" ; $dvidef $iodef $prdef $prvdef $ucbdef $lnmdef ; Added by RAM, 6/3/93 $dscdef ; Added by RAM, 6/3/93 ; smp_code=0 ;VMS V4 or earlier .iif df UCB$L_DLCK, smp_code=1 ;VMS V5 ; ztdef ; ZT definitions - need $ucbdef ; ; ;***** macros ; .macro chkr0 ?lab blbs r0,lab pushl r0 calls #1,g^lib$stop lab: .endm chkr0 ; ; ;***** PSECTs ; .psect _data,quad .psect _code,nowrt .psect _nonpagedcode,page,nowrt nonpagedcode: ;start of psect .psect _nonpageddata,page nonpageddata: ;start of psect ; .page ;***** nonpaged data ; .psect _nonpageddata ; zt_ucb: .long 0 mbx_ucb:.long 0 ; .align quad zt_namedsc: ztns: .word 24 .byte dsc$k_dtype_t .byte dsc$k_class_s ;fixed string ztna: .address log ;point at logical name trans. result. ; .ascid "_ZTA0:" ;;;;;; logt: .ascid /LNM$PROCESS_TABLE/ ;devname logical in system table logn: .ascid /ZTAPE/ ;the switch logical logitm: .word 24,LNM$_STRING .address log ;structure of trnlnm(home-made!) .address ztns ;6 longs .long 0 ;that's it log: .blkl 6 ;look in here log_l: .word 24 .align long atr: .long LNM$M_CASE_BLIND ;be case blinded! ;;;;;; ; mbx_name_size=32 mbx_name: .blkb mbx_name_size .align quad mbx_namedsc: .long 0-0 .long mbx_name ; .align quad zt_msgbuf: .byte 0[zt_msglen] ; ; ;***** get ucb from device name ; called in kernel mode, IPL=0 ; p1 = addr of descriptor ! must be nonpaged ; p2 = addr of ucb-address ! must be nonpaged ; .psect _nonpagedcode dev_to_ucb: .word ^m ; movl g^CTL$GL_PCB,r4 ; jsb g^SCH$IOLOCKR ;;***** start IPL2 ********************* movaq @1*4(ap),r1 ;; jsb g^IOC$SEARCHDEV ;;search for device blbc r0,90$ ;; movl r1,@2*4(ap) ;;r1=UCB 90$: ;; pushl r0 ;; jsb g^SCH$IOUNLOCK ;; Unlock the I/O database setipl #0 ;;***** end IPL2 *********************** popl r0 ; ret ; ; ;***** fake ZT interrupt ; called in kernel mode, IPL=0 ; .psect _nonpagedcode zt_int: .word ^m ; movl zt_ucb,r5 beql 90$ ; .if eq smp_code dsbint ucb$b_dipl(r5) ;; .iff ;; devicelock - ;; lockaddr=ucb$l_dlck(r5),- ;; lockipl=ucb$b_dipl(r5),- ;; savipl=-(sp),- ;; preserve=NO ;; .endc ;; ;; jsb @ucb_l_inter(r5) ;; ;; .if eq smp_code ;; enbint ;; .iff ;; deviceunlock - ;; lockaddr=ucb$l_dlck(r5),- ;; newipl=(sp)+,- ;; preserve=NO ;; .endc ; 90$: movl #1,r0 ret ; ; ;***** kernel mode setup ; called via $CMKRNL ; .psect _nonpagedcode k_setup: .word ^m ; movab g^lib$sig_to_ret,(fp) ; pushal mbx_ucb pushaq mbx_namedsc calls #2,dev_to_ucb blbc r0,90$ ; pushal zt_ucb pushaq zt_namedsc calls #2,dev_to_ucb blbc r0,90$ ; movl zt_ucb,r5 movl mbx_ucb,ucb_l_ztmbx(r5) ; bicw #ucb$m_valid,ucb$w_sts(r5) bisw #ucb$m_online,ucb$w_sts(r5) ; calls #0,zt_int ; interrupt unconditionally, ; to clear potential hang ; movl #1,r0 90$: ret ; ; ;***** kernel mode shutdown ; called via $CMKRNL ; .psect _nonpagedcode k_shut: .word ^m ; movab g^lib$sig_to_ret,(fp) ; movl zt_ucb,r5 beql 90$ ; clrl ucb_l_ztmbx(r5) bicw #,ucb$w_sts(r5) ; ; ggf. terminate i/o ; bicw #,- zt_msgbuf+zt_w_ucbsts ;just in case ... ; calls #0,zt_int ;interrupt unconditionally ; 90$: movl #1,r0 ret ; ; ;***** kernel mode data transfer server -> driver's user ; called via $CMKRNL ; implicit inputs: ; - 'zt_ucb' ; - data in 'buffer' ; - byte count in 'bufbct' ; implicit outputs: ; - ucb$w_bcnt cleared ; .psect _nonpagedcode k_touser: .word ^m ; movab g^lib$sig_to_ret,(fp) ; clrl r0 movab buffer,r1 ; 'from' address movzwl bufbct,r2 ; byte count movl zt_ucb,r5 beql 90$ cmpw r2,ucb$w_bcnt(r5) ;sanity check bgtru 90$ ;br if it failed ; .if eq smp_code dsbint ucb$b_fipl(r5) ;; .iff ;; forklock - ;; lock=ucb$b_flck(r5),- ;; savipl=-(sp),- ;; preserve=NO,- ;; fipl=YES ;; .endc ;; ;; tstl r2 ;; bleq 28$ ;; br if nothing to be moved! jsb ioc$movtouser ;; 28$: ;; ;; .if eq smp_code ;; enbint ;; .iff ;; forkunlock - ;; lock=ucb$b_flck(r5),- ;; newipl=(sp)+,- ;; preserve=NO ;; .endc ; clrw ucb$w_bcnt(r5) ;make sure we don't copy twice ; movl #1,r0 90$: ret ; ; ;***** kernel mode data transfer, driver's user -> server ; called via $CMKRNL ; implicit inputs: ; - 'zt_ucb' ; - byte count in 'zt_msgbuf+zt_w_bnct' ; implicit outputs: ; - data in 'buffer' ; - byte count in 'bufbct' ; - ucb$w_bcnt cleared ; .psect _nonpagedcode k_fruser: .word ^m ; movab g^lib$sig_to_ret,(fp) ; clrl r0 clrl bufbct movl zt_ucb,r5 beql 90$ ; movab buffer,r1 ;'to' address movzwl zt_msgbuf+zt_w_bcnt,r2 ;byte count cmpw r2,ucb$w_bcnt(r5) ;sanity check bgtru 90$ ;br if it failed movl r2,bufbct ; .if eq smp_code dsbint ucb$b_fipl(r5) ;; .iff ;; forklock - ;; lock=ucb$b_flck(r5),- ;; savipl=-(sp),- ;; preserve=NO,- ;; fipl=YES ;; .endc ;; ;; tstl r2 ;; bleq 28$ ;; br if nothing to be moved! jsb ioc$movfruser ;; 28$: ;; ;; .if eq smp_code ;; enbint ;; .iff ;; forkunlock - ;; lock=ucb$b_flck(r5),- ;; newipl=(sp)+,- ;; preserve=NO ;; .endc ; clrw ucb$w_bcnt(r5) ;make sure we don't copy twice ; movl #1,r0 90$: ret ; ; ;***** kernel mode copy of 'result' to driver & activate driver ; called via $CMKRNL ; implicit inputs: ; - 'zt_ucb' ; - 'result' ; .psect _nonpagedcode k_reqcom: .word ^m ; movab g^lib$sig_to_ret,(fp) ; clrl r0 movl zt_ucb,r5 beql 90$ ; movc3 #zt_msglen,zt_msgbuf,ucb_a_ztmsg(r5) ;copy back ; calls #0,zt_int ;'interrupt' driver ; movl #1,r0 90$: ret ; ; ;***** get mailbox & its name ; .psect _data ; mbx_dvi_itm: .word mbx_name_size .word dvi$_fulldevnam .long mbx_name .long mbx_namedsc .long 0 ; .align quad mbxiosb: .blkw 4 ; mbxchan: .blkw ; ; .psect _code get_mbx: .word ^m<> ; $crembx_s prmflg=#0,- chan=mbxchan,- maxmsg=#zt_msglen,- -; ??? bufquo=#zt_msglen,- promsk=#0 chkr0 ; $getdvi_s chan=mbxchan,- itmlst=mbx_dvi_itm chkr0 ; ret ; ; ;***** start mbx read ; .psect _code read_mbx: .word ^m<> ; $qio_s efn=#1,- chan=mbxchan,- func=#io$_readvblk,- iosb=mbxiosb,- p1=zt_msgbuf,- p2=#zt_msglen chkr0 ; ret ; ; ;***** wait for mbx message ; .psect _code wait_mbx: .word ^m<> ; $synch_s efn=#1,- iosb=mbxiosb chkr0 ; movzwl mbxiosb,r0 chkr0 ; cmpw mbxiosb+2,#zt_msglen beql 50$ clrl r0 chkr0 50$: ret ; ; ;***** exit handler ; ; .psect _data curprivs: .quad 0 ; ; .psect _code exith: .word ^m<> ; $setprv_s enbflg=#1,- ;establish initial privileges prvadr=curprivs ;(sometimes removed by rundown) chkr0 ; $cmkrnl_s routin=k_shut,- arglst=(ap) chkr0 ; ret ; ; ;***** setup exit handler ; .psect _data ; .align long exstat: .blkl exblk: .long 0-0,exith,1,exstat ; ; .psect _code setup_exith: .word ^m<> ; $dclexh_s desblk=exblk chkr0 ; ret ; .page ;***** externalized routines & data ; .psect _nonpageddata .align quad ZT_BUFDSC:: bufbct: .long 0-0,buffer ; ; .psect _data .align quad ZT_MSGDSC:: .long zt_msglen,zt_msgbuf ; ; ;***** initialize ; .psect _data ; .align quad lkwdata_inadr: .long nonpageddata,nonpageddata_end lkwcode_inadr: .long nonpagedcode,nonpagedcode_end ; ; .psect _code .entry ZT_INIT,^m<> ; $setprv_s prvprv=curprivs ; save current privileges chkr0 ; ;;;;; ; To allow multi-unit use, translate logical ZTAPE to get real device ; name. Use that, whatever it may be. Name is gotten from process ; table to allow its' use. $trnlnm_s attr=atr,tabnam=logt,- lognam=logn,- ;is the switch logical there? itmlst=logitm chkr0 ;;;;; $lkwset_s inadr=lkwdata_inadr ; lock "nonpaged" data chkr0 ; $lkwset_s inadr=lkwcode_inadr ; lock "nonpaged" code chkr0 ; calls #0,get_mbx ; create mbx etc. chkr0 ; calls #0,read_mbx ; post read on mbx chkr0 ; calls #0,setup_exith ; set up exit handler chkr0 ; $cmkrnl_s routin=k_setup,- ; start zt: arglst=(ap) ret ; ; ;***** wait for MBX ; .psect _code .entry ZT_WAIT,^m<> ; calls #0,wait_mbx ; ret ; ; ;***** move data from 'buffer' to user ; .psect _code .entry ZT_TOUSER,^m<> ; $cmkrnl_s routin=k_touser,- arglst=(ap) ret ; ; ;***** move data from user to 'buffer' ; .psect _code .entry ZT_FRUSER,^m<> ; $cmkrnl_s routin=k_fruser,- arglst=(ap) ret ; ; ;***** complete I/O ; .psect _code .entry ZT_REQCOM,^m<> ; calls #0,read_mbx ; post read on mbx chkr0 ; $cmkrnl_s routin=k_reqcom,- arglst=(ap) ret ; .page ;***** the end ; .psect _nonpageddata ; buffer: ;the data buffer .blkb ^xFFFF ;i.e. 64k-1 ; nonpageddata_end: .blkb ; .psect _nonpagedcode nonpagedcode_end: .blkb ; .end