IMD 1.17: 11/11/2014 10:43:00 82VKXSVRDOS B* VERSADOS/RMS68K SRC/OBJ 4.4 (NOT BOOTABLE) SN=49367 3 OF 30  SR03q82VKXSVRDOS 0420¥j-DACINIT5‚TST.L‚(A1,D3)Œlookforanentryslottosavethisguy5ŠBMI.S‚DACINIT6‹branchifthisslotisempty-useit.ŠADD.W‚#IOLNG,D3‰notempty,bumptonextentry"ŠSUB.B‚#1,D4Ždecrementthecounter(ŠBNE.S‚DACINIT5‹branchifmoretosearch4ŠBRA„DACEXTER‹errorifgothere-noroomforthemap>DACINIT6‚MOVE.LD2,(A1,D3)‰savethismemorymappedI/Oaddress1DACEXIT1‚CLR.B‚CCBFLG(A5)‰setforgoodallocation'DACINEX1:POP_POINT‘recallallpointersŠRTS*ŠPAGEJ***************************************************************************$*‰DACDRIVERCOMMANDSERVICEROUTINE*6*‹PARAMETERADDRESSANDBOUNDARYCHECKSHAVEBEENMADE**ƒEntry:‚JSRFROMCMRHANDLER.*‹A2-PHYSICALADDRESSOFCMRPARAMETERBLOCK*‹A5-PHYSICALADDRESSOFCCB*5*ƒExit:‚RTS-PARAMETERBLOCKVALIDATIONSTATUSIND0**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A**P**PP*"*”A3=DACPARAMETERBLOCKADDRESS*”A6=REQUESTORTCBADDRESS**ƒCODEISRE-ENTRANT*J***************************************************************************)*‰ConvertlogicalPBaddresstophysical.*DACCMD„CLR.L‚D5;ŠMOVE.LXIOCPK(A2),D6†SetupaddressofDACparameterblock:ŠMOVE.WXIOPLN(A2),D5†SetuplengthofDACparameterblock+ŠMOVE.LCCBTASKA(A5),A1„SetupTCBpointer.&ŠBSR„IOHADRCK‹Callconversionroutine.ŠBRA.S‚CMD010Goodreturn.ŠNOP—Badlengthreturn. ŠCLR.L‚D0;ŠMOVE.W#RTCDPBLK,D0‡SetupinvalidparameterblockaddressŠRTS*!*‰seeifpassedtheinitializeok*7CMD010„MOVE.LD6,A3ŽStagephys.addr.ofDACpara.blk. ŠCLR.L‚D04ŠTST.B‚CCBFLG(A5)‰errorcodesetinCCBduringINIT?/ŠBEQ.S‚CMD020branchifnoerrorcode,continue$ŠMOVE.BCCBFLG(A5),D0†seterrorcodeŠBRA.S‚DACCEX2Œgotoerrorexit CMD020„EQU**,*‰getDACTBLaddressintoA4forcommanduse* ŠMOVE.LDACTBL,A4ŠDACTBLaddress)ŠCMP.L‚#'!DAC',(A4)‡reallyistheDACTBL?,ŠBEQ.S‚CMD030branchifreallyistheDACTBL4ŠMOVE.W#DACNTBL,D0ˆseterrorreturncode-notableŠBRA.S‚DACCEX2Œandreturn**‰findDAC-IDinDACTBL*‰A1=entryaddress*0CMD030„MOVE.LXIOCID(A2),D0†getspecifiedDAC-ID(ŠMOVE.BDACNMAX(A4),D1…max#ofDAC-ID's$ŠMOVE.L#DACNTRY,D2ˆbumppastheader"FNDDCO10‚CMP.L‚(A4,D2),D0‰amatch?!ŠBEQ.S‚FNDDCO20‹branchifamatch&ŠADD.W‚#DACIDLNG,D2‡bumptonextentry1ŠSUB.B‚#1,D1Ždecrementnumberofentriestocheck&ŠBNE.S‚FNDDCO10‹branchifmoreentries.ŠMOVE.W#DACNID,D0‰error-DAC-IDnotintable5ŠBRA.S‚DACCEX2ŒreturntoCMRwitherrorconditionset+FNDDCO20‚MOVE.LA4,A1ŽbassaddressoftableŠADD.L‚D2,A1Žaddressofentry (*‰Findthecommandinthecommandtable.*-ŠMOVEQ‚#NUMCMDS-1,D0†Setuptheloopcounter./ŠLEA„CMDTBL,A0ŠA0<--addressofcommandtable.+ŠMOVE.WCMDCOD(A3),D6†getDACcommandcode.8CMDSRCHƒCMP.W‚(A0)+,D6‹Searchthetableforthecommand.ŠDBEQƒD0,CMDSRCH3ŠBNE.S‚CMDERRIfwefoundthecommandinthetable,8ŠADD.L‚#JMPOFF-2,A0‡getthecorrespondingentryfromthe5ŠMOVE.W(A0),D0Œjumptableandjumptotheroutineto"ŠJMP„(A0,D0.W)Šhandlethecommand.DCMDERR„MOVE.W#DACINVD,D0ˆdidn'tfindcommandcode-exitwitherrorCDACCEX2ƒMOVE.WƒD0,CMDSTA(A3)„writeerrorcodetousersDACparablkŠRTS*ŠPAGEL******************************************************************************‰OPENCOMMAND*A*‰Thiscommandassignsthelogicalconnectionbetweenausertask9*‰andspecifiedchannelswithinanDACmodule.4channels/*‰maximummaybespecifiedinoneopencommand.*#*‰DACOPENcommand‚parameterblock: *DS.W‚1„returnedcommandstatus*DS.W‚1„commandcode(01)*DS.W‚1„#ofchannelstoopen*DS.W‚1„1stchannelnumber$*DS.W‚1„channelwake-upinformation*’.*’.%*DS.W‚1„nthchannelnumber‚(max=4)$*DS.W‚1„channelwake-upinformation**)*‚Entry:A1=addressofDAC-IDinDACTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDACparameterblock *‰A4=addressofDACTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:CLRIOM,SETIO*K*****************************************************************************‰seeifchannelalreadyopened*$OPEN†PUSHPOINT‘savealladdressregsŠALLOCATEƒCHCONFIG4ŠBSR.S‚VALIDACŒMakesuretheDAChasbeenallocated.(ŠBNE.S‚OPNOIDErrorifDacnotallocatedŠCLR.L‚D7‘channelcounter$ŠCLR.L‚D2‘channeloffsetintoDACTBL)ŠCLR.L‚D1‘offsetintoDACparameterblock1ŠMOVE.WCMDCHN(A3),D0†get#ofchannelsspecified/ŠBLE.S‚OPNINCbranchifnegativeorzero,error0ŠCMP.W‚#4,D0cannotspecifymorethan4channels-ŠBGT.S‚OPNINCbranchifgreaterthan4,errorGOPEN10„MOVE.WNUMCHAN(A3,D1),D2‚getchannelnumberfromDACparam.blk.!ŠCMP.W#4,D2insurechannel#<4 ŠBGT.SOPNINVŠMOVE.WD2,D5Žsaveit0ŠMULUƒ#CHANLNG,D2ˆgetchanneloffsetintoDACTBLŠADD.L‚#4,D2ŽbumppastDAC-ID+ŠTST.W‚(A1,D2)Œthischannelalreadyopened?-ŠBPL.S‚OPNOPNbranchifalreadyopened,errorŠADD.L‚#1,D7Žcountthischannel**…SaveTCBaddress*)ŠMOVE.LA6,DACTCB(A1,D2)ƒsaveTCBaddress4ŠADD.W‚#OPNTRY,D1‰bumptonextDACparam.blk.entry3ŠSUB.W‚#1,D0Ždecrementnumberofchannelsspecified)ŠBGT„OPEN10branchifmorechannelstodoŠBRA.S‚OPNXITgoreturntoCMR**‰openerrorshere*5OPNINVƒMOVE.W„#DACICNS,D0‰setinvalidchannel#error ‰BRA.S…OPNXIT8OPNINCƒMOVE.W„#DACINC,D0‰setinvalid#ofchannelserror‰BRA.S…OPNXIT‹exit;OPNOIDƒMOVE.W„#DACNID,D0‰setDACmodulenotallocatederror‰BRA.S…OPNXITgoreturntoCMR9OPNOPNƒMOVE.W„#DACPND,D0‰setchannelalreadyopenederror*)*‰resetanyopenedchannelstonotopened*%OPNERR„TST.W‚D7‘anychannelstoundo?3ŠBEQ.S‚OPNXITbranchifnonetoundo,returntoCMR&ŠMOVE.W#$FFFF,D3Šset'un-opened'codeŠCLR.L‚D1‘clearforuse6OPNERR10‚MOVE.WNUMCHAN(A3,D1),D2‚getachannelnumber$ŠMULUƒ#CHANLNG,D2ˆgetchanneloffsetŠADD.L‚#4,D2Žbumppastheaders*ŠMOVE.WD3,(A1,D2)‰setthisentryunopened-ŠADD.W‚#OPNTRY,D1‰bumptonextchannelnumberŠSUB.W‚#1,D7Ždecrementcounter&ŠBGT.S‚OPNERR10‹branchifmoretoundo*…Fallintoexit* OPNXIT EQU *4ŠADD.L„#NUM_RESERVED,A7‚DEALLOCATECHCONFIGonstackŠPOP_POINT‘restoreallpointers ŠBRANRMEXIT*ŠPAGEL*****************************************************************************2*‰VALIDAC‚CheckstoinsureDAChasbeenallocated.*&*‰Entry:A1=DAC-IDaddressinDACTBL%*A2=addressofCMRparameterblock%*A3=addressofDACparameterblock*A4=addressofDACTBL*A5=addressofCCB*A6=addressofusersTCB**‰Uses:‚D4,D6,D7*%*‰Exit:‚D0=DACNIDifanerrorfound**D0=contentsonentryifnoerrorfound*L*****************************************************************************1VALIDAC‚MOVE.WDACIO(A4),D7†getoffsettoIOmaps.ŠMOVE.BDACNAL(A4),D6†get#ofDAC'Sallocated3ŠMOVE.LCCBCHB(A5),D4†getmemorymappedI/OaddressCVALIDAC1CMP.L‚IODDR(A4,D7),D4ƒlookformatchingmem.map.I/OaddrŠBEQ.S‚VALIDAC2Šbranchiffound#ŠADD.W‚#IOLNG,D7‰bumptonextentryŠSUB.B‚#1,D6Ždecrementcounter0ŠBNE.S‚VALIDAC1Šbranchifmoreentriestosearch#ŠMOVE.W#DACNID,D0‰seterrorreturnVALIDAC2ŠRTS—returntocaller*ŠPAGEL******************************************************************************‚CLOSECOMMAND*A*‚CloseallconnectionswiththisusertaskandhisopenchannelsB*‚forthisDACmodule.Thechannelsareputbacktothepre-opened)*‚state.Thechannelsaresetto0volts.*$*‚DACCLOSECOMMANDparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode02*)*‚Entry:A1=addressofDAC-IDinDACTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDACparameterblock*‰A4=addressofDACTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:STOPIO*L*****************************************************************************CLOSE:+ŠMOVE.L#4,D1ŽbumppastDAC-IDinthetable !ŠCLR.L‚D2‘useforchannelcounter5CLOSE10ƒCMP.L‚DACTCB(A1,D1),A6ƒchannelforthisuser?*ŠBNE.S‚CLOSE20Œbranchifnotforthisuser5ŠBSR.S‚STOPIOŒgostopI/OonthischannelD2=chan#?ŠMOVE.W#$FFFF,DACTCB(A1,D1)setthischannelentrytonotused5CLOSE20ƒADD.L‚#CHANLNG,D1ˆpointtonextchannelentryŠADD.L‚#1,D2Žcountthischannel#ŠCMP.L‚#4,D2searchedallchannels?&ŠBNE.S‚CLOSE10ŒbranchifmorechannelsŠCLR.L‚D0‘setfornoerrorsŠBRA„NRMEXITŒandreturntoCMR*ŠPAGED*********************************************************************3*‚STOPIOƒdeactivateI/Oonspecifiedchannelnumber*&*‚Entry:A1=DAC-IDaddressinDACTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDACparameterblock*‰A4=addressofDACTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‰D0.W=channelconfiguration%*‰D2.L=channelnumbertodeactivate* *‚Uses:‚D0,A0*L*****************************************************************************9STOPIOƒMOVE.LCCBCHB(A5),A0†getmemorymappedI/Oaddress+‰MOVEƒIOADR(A1,D1),D0„Getoffsettochannel5‰MOVE.B#ZEROL,(A0,D0)…Setlowbyteofconverterto07‰MOVE.B#ZEROH,2(A0,D0)„Sethighbyteofconverterto0‰RTS—returntocaller*ŠPAGEF*********************************************************************** *‰CNVRT-TURNONOUTPUTCOMMAND<*‰Thiscommandactivatesoutputsforspecifiedchannelsthat9*‰havepreviouslybeenopenedforoutputbythesametask<*‰requestingthisactivation.‚Theparameterblockischecked:*‰forerrorsbeforeanyoutputisactivated.‚Nochannelis!*‰activatedifanerrorisfound.*%*‰DACOUTPUTcommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode03*‰DS.Wƒ1ƒChannel#toconvert**‰DS.Wƒ1ƒ#ofconversionsforthischannel(*‰DS.Lƒ1ƒAddressofconversiondatalist*‹.2*‹.ˆUpto4channelsinthelistandtheymustall*‹.ˆbeforthesameboard=*‰DS.Wƒ1ƒWakeupinformationwhenendoflistisencountered.* *‰Datalist*.*‰DS.Wƒ1ƒDelayinformationbetweenconversions&*‰DS.Wƒ1ƒDigitalvaluetobeconverted*)*‚Entry:A1=addressofDAC-IDinDACTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDACparameterblock*‰A4=addressofDACTBL*‰A5=addressofCCB*‰A6=addressofusersTCB*L*****************************************************************************CNVRT:6ŠMOVE.LA3,-(A7)‹Savetheregister--Ineedtoremember"*£wheretowritethestatuslater.:ŠMOVEƒCMDCHN(A3),D7†Getthenumberofchannelstoconvert.ŠIF.WOR.BD7#4THEN.SŠMOVE.L(A7)+,A30ŠMOVEƒ#DACINC,D0‰Setinvalid#ofchannelserrorŠBRA„EXITgetoutŠENDI 0ŠSUBQƒ#1,D7ŽAdjustthenumberfortheDBRAloop.5ŠADD.L‚#CMDNXT,A3‰Pointtotheconvertportionofthe*£parameterblock.CNVRT19ŠMOVEƒ(A3)+,D1‹D1<--channelnumberforthisconversion.)ŠCMP„#3,D1ŽMakesurechannelisinrange.ŠIF…THEN.S"ŠMOVE.L(A7)+,A3‹Restorethestack0ŠMOVEƒ#DACICNS,D0ˆSettheerrorreturnconditionŠBRA„EXITNowwecangetoutŠENDI 7ŠMOVEƒ(A3)+,D2‹D2<--#ofconversionsforthischannel:ŠMOVE.L(A3)+,D6‹D6<--logicaladdressofconversiondata1ŠMOVEƒD2,D5ŽFindlengthofconversiondatabuffer#*£forthelogicaltophysicalcall.2ŠMULUƒ#4,D5ŽMulitiplythenumberofconversionsby&*£thenumberofbytesperentryinthe*£table.1ŠSUBQƒ#1,D2ŽDBRAadjustthenumberofconversions6ŠMOVE.LA1,-(A7)‹Needthisregisterforthelogicalto*£physicalcall.+ŠMOVE.LA6,A1ŽA1<--TCBaddressofcaller.ŠBSR„IOHADRCK‹Dotranslation.ŠBRA.S‚CNVRT2Goodreturn.ŠNOP—Badreturnfromcall<ŠMOVEM.L(A7)+,A1/A6‡Cleanupthestackfortheerrorreturn5ŠMOVEƒ#RTCDPBLK,D0‡TelluseraddressnotinhisspaceŠBRA„EXITGetoutofhere.CNVRT28ŠMOVE.LD6,A0ŽA0<--physicaladdressofconversiondata+ŠMOVE.LCCBCHB(A5),A2†OffsettoI/Oaddress'*£A2<--BaseI/Oaddressoftheboard.*ŠMOVE.L(A7),A1ŒRestorepointertoDACTBL. 8ŠADDQ.L#4,A1ŽPointtotheinformationaboutthechannel *£intheDAC.1ŠMULUƒ#CHANLNG,D1ˆOffsettothespecificchannel.CŠCMP.L‚DACTCB(A1,D1),A6ƒFindoutifthecallerreallyownsthechnlŠIF…THEN.S(ŠMOVEM.L(A7)+,A1/A3ˆCleanupthestack.,ŠMOVEƒ#DACICU,D0‰Settheerrorreturnvalue.ŠBRA.S‚EXITgetoutŠENDIAŠMOVEƒIOADR(A1,D1),D3„D3<--offsetfrombaseI/Oaddressofthis,ŠMOVE.L(A7)+,A1‹Restorethesavedregister.,ŠMOVE.L(A1),D5ŒSavetheIDforthismodule. *£channelCNVRT36ŠTST„(A0)+ŽIsthereadelaybeforeconvertingthedataŠIFTHEN.S#ŠMOVE.L(A7)+,D0‹Cleanupthestack<ŠDIVUƒ#CHANLNG,D1ˆGetthechannel#forthisconversionbackŠMOVEƒD1,D6ŽSaveit@ŠMULUƒ#SAVEREGS*4,D6…Thisistheoffsettothischannelsareain**£theCCBwherewecansavetheregisters.:ŠMOVEM.LD0-D3/D5/D7/A0-A6,CHNLREGS(A5,D6)Savetheworld.7ŠMOVE.LA5,D2ŽUsetheCCBaddressastheidentification&ŠOR.BƒD1,D2ŽEncodethechannelnumber.ŠSUB.L‚A1,A1ŽZerotheregister.#ŠMOVEƒ-2(A0),A1ŠGetdelayinterval.,ŠLEA„ACTENTRY(PC),A0„Activationentrypoint.0ŠMOVE„#1,D1Setoptions--Newperiodicactivation*°singleactivation*°interruptlevel1ŠTR0$.RQPA‘Doit.$ŠBRA.S‚EXIT1ŽGetoutifgoodreturn.;ŠBRA.S‚*ˆ**********************FORNOW*********************CNVRT3A7ŠMOVE.LD0,-(A7)‹Stack<--startaddressofpara.blockŠENDI#ŠMOVEƒ(A0)+,D4‹Getdatatoconvert.2ŠMOVE.BD4,0(A2,D3)ˆGivelowbytetothehardware. ŠROR„#8,D4ŽSetupthehighbyte.7ŠMOVE.BD4,2(A2,D3)ˆGivethehighbytetothehardware."ŠDBRAƒD2,CNVRT3ŠDothewholelist.!ŠDBRAƒD7,CNVRT1ŠDoeverychannel.(ŠMOVEƒ(A3),D0ŒD0<--wakeupinformation7ŠMOVE.L(A7)+,A3‹Restorethestackpointerwhichwehad)*£savedtheaddressofthestatuswordin*£thecommandpacket.,ŠTST„D0‘FindouthowrequestorwhatstoknowŠBMI.S‚CNVRT5thejobisdone. ŠBTSTƒ#0,D0 ŠBEQ.S‚CNVRT4*0*‰Therequestorwantsawake-upsogivehimone.*-ŠMOVE.LA6,A0ŽA0<--TCBAddressofrequestor ŠTR0$.WAKEUPŠBRA.S‚CNVRT5Exitgood**‰Unabletowakeuptheuser*0ŠBRA.S‚*’***************FORNOW*****************CNVRT4+ŠBSR.S‚QUEVENTŒQueuetherequestoraneventCNVRT5#ŠCLR„D0‘SetreturnedstatustogoodEXIT-ŠMOVEƒD0,(A3)ŒPutstatusinusersparmblock.EXIT1 ŠCLR.L‚D0ŠRTS‰PAGEO******************************************************************************** *ˆNORMALEXIT*,*‚Entry:A2=addressofCMRparameterblock%*‰A3=addressofDACparameterblock*‰A5=addressofCCB*‰A6=addressofusersTCB*‰D0=DACerrorcode*I**************************************************************************NRMEXIT:>ŠMOVE.WD0,CMDSTA(A3)†setreturnstatusinDACparameterblockŠRTS—returntoCMR*ŠPAGE*‚ACTIVATIONENTRYPOINT*ACTENTRY)ŠMOVEM.LD2-D7/A2-A6,-(A7)SaveregistersŠAND.W‚#$F8FF,SRŠDropthemask.ŠCLR„D2‘Initializeregisters.#ŠMOVE.BD1,D2ŽD2<--channelnumberŠAND.B‚#0,D1ŽD1<--CCBaddress-ŠMOVE.LD1,A0ŽPutCCBaddressinuseablereg.5ŠMULUƒ#SAVEREGS*4,D2…Findregistersforthischannel.*ŠMOVEM.LCHNLREGS(A0,D2),D0-D3/D5/D7/A0-A6ŠMULU„#CHANLNG,D1.ŠBSR.S‚CNVRT3AŒGoworkontheconversionlist.-ŠMOVEM.L(A7)+,D2-D7/A2-A6Restorethestack. ŠRTE—Exit.ŠPAGE*H*‚QUEVENT-queue'seventtodrivingtaskusingdatastagedinregisters *‹asfollows:*‹A6=user'sTCBaddress&*‹D2=$0C01*‹D3=DACID‚(modulename)&*‹D4=memmappedI/Oaddressofboard<*†(dumpscontentsofregistersD2,D3,&D4tousersbuffer)* QUEVENT EQU *‹PUSHALL”pushallregs"‹MOVE.L…A6,A0Žstageuser'saddress+ŠMOVE.LD5,D3ŽPutDACIDinthecorrectreg.-ŠMOVE.LA2,D4ŽPutI/Oaddressincorrectreg.!ŠCLR.L‚D2‘Initializetheregister*ŠMOVEƒ#$0C01,D2ŠSeteventlengthandtype.(ŠSWAPƒD2‘Setuptomoveinthechannel#7ŠDIVUƒ#CHANLNG,D1ˆThechannel#hastobere-calculated ŠMOVEƒD1,D2ŽFinishuptheevent. ‹TR0$.QEVNTI*)‹BRA.SƒQUEVNTOKŒgoodreturnforqueevent '‹BRA.SƒQUEVNTERŒbadreturnfromqueventQUEVNTOK EQU *‹POPALL•restoreallregs‹RTS QUEVNTER:(‹BRAQUEVNTOKputabreakherefordebug*ŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLINGTASKSADDRESSSPACE.*#*ENTRY:ƒD5‚-NO.OFBYTESTOCHECK*ŠD6‚-68000ADDRESS(LOGICAL)*ŠA1‚-TCBADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1*7*EXIT:„D6-PHYSICALADDRESSOFBUFFERBASE(IFLEGAL)*ŠRETURNTOPC„FORGOODADDRESS*”PC+2‚FORBADLENGTH*”PC+4‚FORBADADDRESS*F*********************************************************************** IOHADRCK:%ŠBTSTƒ#0,D6‘Mustbeonworkboundary.)ŠBNE.S‚IOHADR4Branchifbadbufferbase.ŠTST.L‚D5”Lengthcan'tbezero.2ŠBEQ.S‚IOHADR8Don'tgotologphywithzerocount.1ŠMOVE.LTCBTST(A1),A0‰Addressoftaskseg.table. ŠTR0$.LOGPHY*.ŠBRA.S‚IOHADR8Branchforgoodaddressreturn.0ŠBRA.S‚IOHADR6Branchforbadbytecountreturn.(ŠTST.L‚D5”Wasanentrypointerreturned.#ŠBEQ.S‚IOHADR4Branchifno-ERROR)ŠTST.B‚7(A0,D5)ŽIsthisanMMIOsegment?ŠBNE.S‚IOHADR8Yes,OK.3IOHADR4ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.3IOHADR6ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.IOHADR8ƒRTSšReturn.* PAGE**ˆINTERRUPTSERVICEENTRYPOINT*<*ˆTherearenointerruptsforthisboardsoexitifentered.*DACINT‰RTS‰ENDéé=/*=/*†M605LIB.AF=/*D=/* Chain file to assemble FORTRAN-callable subroutines to interface=/* with the MVME605 driver.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M605LIB.LS=/*=/IFC \1„=ARGM605LIB.LS=/ENDIF=/*=ASM M605LIB.SA,M605LIB.RO,\1;R=/*{ Included files are:=/*ƒ--none--=/*}=/*=ENDéééééé €FTDAC…IDNTƒ1,0DACsubroutines**‰FORTRANcallablesubroutines*‰forDACdrivercalls*$*‰CALLDACCMD(dac_id,param_blk_addr)*‰whereDACCMDmaybe:*)*‰CALLDAOPEN(dac_id,param_blk_addr)…open**‰CALLDACCLS(dac_id,param_blk_addr)…close.*‰CALLDACOUT(dac_id,param_blk_addr)…outputon*,*‰Allargumentsforthecallsareidentical.7*‰Thecontentsoftheparam_blkforeachcallisunique*‰tothecall.*6*‰Allthecommandsubroutinescallacommonsubroutine3*‰DACSETtobuildtheinitiateI/Oparameterblock.**‰STACKFORALLCALLS:*7*‰deepeststack:(stackaddressstaysatDACSETreturn)0*˜commandcodeƒ2bytes(initiateI/Oparam.blk) *˜n/aŒ2bytes*˜dac_id‰4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes,*˜commandaddrƒ4bytes(daccommandaddress)**˜commandlng„2bytes(daccommandlength)-*˜DACSETreturn‚4bytesdeepeststackaddress *˜A34bytes *˜A24bytes *˜A14bytes *˜D04bytes*‰entrystack:ƒreturn‰4bytes*˜^param_blk_adr4bytes*˜^dac-idˆ4bytes* ŠSECTION9ŠXDEFƒDAOPEN,DACCLS,DACNVT*$*‰CALLDAOPEN(dac_id,param_blk_addr)*‰openandconfigurechannels*1DAOPEN„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DACSETset-uptheinitiateI/Oparameterblock)ŠMOVE.L#1,(A2)ŒsettheopencommandcodeDACPN00ƒCLR.L‚D0‘clearforuse'ŠMOVE.W4(A2),D0‹getnumberofchannelsŠASL.L‚#1,D0Žmultiplyby4.DACPN05ƒADD.L‚#6,D0Žaddinthe6byteoverhead-DACPN10ƒMOVE.WD0,(A1)Œsetthecommandlength-ŠMOVE.LA3,A0ŽTRAP#1parameterblockaddress#ŠMOVE.L#60,D0CMRdirectivenumberŠTRAPƒ#1‘callRMS68K'ŠMOVE.WD0,(A2)Œsetthereturnedstatus)ŠMOVEM.L(A7)+,D0/A1-A3„restoreregisters!ŠMOVE.L(A7)+,A0‹putreturninA0 ŠLEA„8(A7),A7‹cleanupthestackŠJMP„(A0)returntouser*$*‰CALLDACCLS(dac_id,param_blk_addr)"*‰closeallchannelsforthisuser*1DACCLS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DACSETset-uptheinitiateI/Oparameterblock*ŠMOVE.L#2,(A2)Œsettheclosecommandcode‰D’;&ŠMOVE.W#4,D0ŽDACclosecommandlengthŠBRA„DACPN10ŒgodotheCMRcall*$*‰CALLDACNVT(dac_id,param_blk_addr)'*‰activateoutputonrequestedchannels*1DACNVT„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DACSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#3,(A2)Œsettheoutputcommandcode+ŠMOVE.W4(A2),D0‹getthenumberofchannels2ŠMULUƒ#8,D0Žfindthelengthoftheparameterblock%DACUT10ƒADD.W„#6,D0ŒaddintheheaderŠBRA„DACPN10ŒgodotheCMRcall*ŠPAGE*4*‰DACSETsetuptheCMRinitiateI/Oparameterblock,*‰returns:ƒA1=addressforDACcommandlength(*”A2=DACcommandparameterblockaddress)*”A3=initiateI/Oparameterblockaddress*(DACSET„CLR.W‚-2(A7)clearcommandlength-ŠLEA„-2(A7),A1Šsaveaddressofcommandlength$ŠMOVE.L24(A7),A0Šgetparam_blk_addr%ŠMOVE.LA0,-6(A7)Šsaveparam_blk_addr,ŠMOVE.LA0,A2Žsaveparam_blk_addrforreturnŠCLR.L‚-10(A7)ŒnotusedŠCLR.L‚-14(A7)ŒnotusedŠCLR.L‚-18(A7)ŒnotusedŠMOVE.L28(A7),A0Šget^dac_idŠMOVE.L(A0),-22(A7)‡getdac_idŠCLR.W‚-24(A7)Œnotused0ŠMOVE.W#$0700,-26(A7)…initiateI/Ocommandcode4ŠLEA„-26(A7),A3‰initiateI/OparameterblockaddressŠRTS—returntocaller* *ˆGetthelocationofavariable* *ˆI=LOC(VAR)*-*’I‰Theinteger*4variablewhichreceivesthe*œlocationofVAR.**’VAR‡Anyvariableorconstant.* ‰XDEF†LOC**ˆDeepeststack:*ˆEntrystack:ˆreturn*œ^var* ‰SECTION9LOC#‰MOVE.L„(A7)+,A0ŒGetreturnaddress"‰MOVE.L„(A7)+,D0ŒSupplytheansw er‰JMP‡(A0)Return*ŠEND*é=/*=/*†M610DRV.AF=/*-=/* Chain file to assemble the MVME610 driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M610DRV.LS=/*=/IFC \1ƒ=ARGM610DRV.LS=/ENDIF=/*$=ASM M610DRV.SA,M610DRV.RO,\1;RZ=100=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.M610CCB.EQ=/*ƒ9995.&.M610INTQ.EQ=/*ƒ9995.&.M610CMD.EQ=/*}=/*=ENDéééééš ŠNOFORMAT ŠOPT„CRE,BRS;ŠTTLVME610/620InputModuleDriverVersion1.0-11/01/848M610†IDNTƒ1,0VME610/620InputModuleDriver-11/01/84K****************************************************************************<*ŠVME610-AC/620-DCInputModuleDriverSource-Version1.0<*Š----------------------------------------------------------*K*ƒThissourcesatisfiesallrequirementssetforthintheVME610/620AC/DCC* Input Module Driver Engineering Specification - ES0145 Issue 2.0.***ƒRevisionhistory:*A*Š11/01/84‚RemovedallreferencestotheRMS68KTIMEODparameter.4*”TheywerereplacedbyacalltotheRMS68KRDTIMER,*”routinetoobtainthecurrenttime-of-day.***‰GlossaryofAbbreviations*‰-------------------------**‰CCBƒ-ChannelControlBlock#*‰BABƒ-BackgroundActivationBlock&*‰IQCT‚-InterruptQueueControlTable(*‰ICCT‚-InterruptChannelControlTable-*‰NICCT-Non-interruptChannelControlTable*L****************************************************************************ŠFORMATŠPAGE*‰INCLUDE‚9995.&.STR.EQŠINCLUDE‚9995.&.STR.EQŠPAGE*‰INCLUDE‚9995.&.TR1RTCD.EQŠINCLUDE‚9995.&.TR1RTCD.EQŠPAGE*‰INCLUDE‚9995.&.TCB.EQŠINCLUDE‚9995.&.TCB.EQŠPAGE*‰INCLUDE‚9995.&.L V5.EQŠINCLUDE‚9995.&.LV5.EQŠPAGE*‰INCLUDE‚9995.&.CCB.EQŠINCLUDE‚9995.&.CCB.EQ ŠNOFORMAT*‰INCLUDE‚9995.&.BAB.EQŠINCLUDE‚9995.&.BAB.EQŠINCLUDE‚9995.&.M610CCB.EQŠINCLUDE‚9995.&.M610INTQ.EQŠINCLUDE‚9995.&.M610CMD.EQŠPAGE*(*ƒInputModuleHardwareRegisterOffsets*E*ƒThefollowingequatesdefinetheoffsetstoeachVME610/620moduleJ* hardware register from the base memory mapped I/O address of the module.D* The base address is assumed to specified on an even byte boundary.*ŠSPC„2 ŠOFFSET0ŠSPC„20INPCSTAT‚DS.Bƒ1”Thistheoffsettotheread-only*£ChannelStatusregister.ŠSPC„2:INPICNTR‚EQU„INPCSTATThisistheoffsettothewrite-only(*£InterruptMask/SenseControlregister.ŠSPC„2œ£E¬<´0¼0Ä9Ì'Ô)Ü2ä2ì6ô3ü$4 5(6$6,44/<1D0L2T4\,d5l2t1|2„.Œ0-ŠDS.Bƒ1”Allevenbyteaddressesareundefined*£ontheI/OChannel.ŠSPC„23INPISTAT‚DS.Bƒ1”Thisistheoffsettotheread-only*£InterruptStatusregister.ŠPAGE ŠSECTION0 ŠOPT„BRS,CREŠSPC„2(*‚ExternallyDefinedSymbolDeclarations 7ŠXREF.SINPTBLThissymbolistheaddressofalocation&*£withinSYSPARthatcontainsthebase**£addressoftheGlobalVariableAreathat)*£allocatedandinitializedduringsystem*£initialization.ŠPAGEN*******************************************************************************0*‰CMRParametersandModuleRevisionInformation0*‰----------------------------------------------*L*ƒThissectioncontainstheCMRServiceVectorTable,CMRchannelallcoation.* parameters, and module revision Information.*N****************************************************************************** INPDRV: **‚CMRServiceVectorTable*H*ƒThistablecontainstheentrypointoffsetsoftheinputmoduledriverK* Foreground Interrupt Handler, Command Handler, and Initialization RoutineK* relative to the driver base memory address. When one of these routines isG* to be executed, CMR adds the entry point offset of the routine to theH* driver base memory address defined by SYSgen and performs a JSR to the* resulting address.*ŠSPC„27ŠDC.LƒINTERUPT-INPDRV†ThisfielddefinestheForeground'*£InterruptHandlerentrypointoffset.ŠSPC„2;ŠDC.LƒCOMMAND-INPDRV‡ThisfielddefinestheCommandHandler*£entrypointoffset.ŠSPC„27ŠDC.LƒINIT-INPDRVŠThisfielddefinestheInitialization*£Routineentrypointoffset.ŠSPC„2-ŠDC.Lƒ0”Thisfieldisreservedforfutureuse *£byCMR.ŠSPC„2*H*ƒThissectioncontainsinformationusedbyCMRtoallocateinputmoduleN* CCB's. Currently, the only parameter defined for this field is the number ofH* additional pages to be allocated to each CCB. All other fields in this-* section are reserved for future use by CMR.*ŠSPC„2(ŠDC.Bƒ1”Thisfielddefinesthenumberof+*£additionalpagestobeallocatedforeach+*£CCBbyCMR.Thisdriverusestwopagesin *£eachCCB.ŠSPC„24ŠDCB.B‚15,0‘Theremaining15bytesofthisparameter+*£fieldarereservedforfutureusebyCMR.ŠSPC„2*G*ƒThissectioncontainsmodulerevisioninformation.TheinformationisO* stored as part of the driver object code to allow determination of the driverK* revision that was included in a particular application system when SYSgen* listings are not available.*ŠSPC„22ŠDC.Bƒ'110184'Thisisthedateofassemblyofthe**£releaseversionofthisdriverrevision.ŠSPC„2,ŠDC.Bƒ''’Thisfieldspecifiesthenumberof&*£patchesthathavebeenappliedsince'*£releaseofthisdriverrevision.This(*£fieldalwayscontainsablankwhenever*£thedriverisreassembled.ŠSPC„20ŠDC.Bƒ'4'’ThisfieldcontainstheminimumRMS68K&*£majorrevisionlevelwithwhichthis'*£revisionofthedriveriscompatible.ŠPAGEM****************************************************************** ************4*‰InputModuleDriverChannelInitializationRoutine4*‰--------------------------------------------------*J*ƒThechannelinitializationroutineiscalledbyCMRwheneveranAllocateH* Channel command is issued to CMR. This normally occurs once, at systemM* initialization time, for each input module specified by SYSgen. On entry toL* this routine, A5 contains the address of the CCB allocated by CMR for thisK* input module. Also, CMR initializes the device independent portion of theM* CCB and clears the device dependent portion to zeros before the calling the* initialization routine.*F*ƒThisroutinefirstinitializestheinputmodulehardwareatthebaseN* memory mapped I/O address specified in the Allocate call. Several CCB fieldsH* are initialized that contain bit masks used to manipulate the hardwareM* registers of the VME 610/620 module and control operation of the Foreground* Interrupt Handler.*%*‰EntryConditions:A0=CCBaddress*6*‰ExitConditions‚:AllregistersarepreservedbyCMR*-*‰GeneralRegisterUsage:D0=WorkRegister*¢D1=WorkRegister*¢A0=WorkRegister**¢A3=InterruptQueueControlTableEntry *§address#*¢A4=GlobalVariableAreaaddress*¢A5=CCBaddress*N******************************************************************************ŠPAGEJ*ƒThefollowingtablecontainsthedirectivenumbersfortheRMS68KTrap0K* routines that are called by this driver. This table is used by the driverL* initialization routine to obtain the JSR entry point address correspondingK* to each directive number in the table. The order of the table entries mayL* not be changed unless the order of the corresponding JSR address fields in* the CCB is also changed. *TRAP0TBL‚DC.BƒT0GUARDŒCallGuardedroutine)ŠDC.BƒT0SCHEDŒScheduleBackgroundroutine4ŠDC.BƒT0LOGPHY‹Logcaltophysicaladdressconversion2ŠDC.BƒT0RQPAExecutivePeriodicActivationroutine,ŠDC.BƒT0QEVNTI‹InterruptQueueEventroutine"ŠDC.BƒT0WAKEUP‹TaskWakeuproutine3ŠDC.BƒT0RDTIMŒReadTimerroutine‚***added10/25/84ŠSPC„2>NUMTR0„EQU„*-TRAP0TBL‰NumberofentriesinthedirectivetableŠPAGEAINIT†MOVE.LCCBCHB(A5),A0ˆLoadthememory-mappedI/Obaseaddress<ŠCLR.B‚INPICNTR(A0)‡oftheinputmoduleandperformhardware9ŠTST.B‚INPISTAT(A0)‡initializationbywritingzerotothe**£InterruptMask/SenseControlregisterto(*£disableallinterruptsfromthemodule'*£followedbyareadfromtheInterrupt&*£Statusregistertoclearanypending$*£interrupts.Theorderofthesetwo,*£operationscannotbechangedorinterrupts*£maybeleftpending.ŠSPC„29ŠMOVE.LINPTBL,A4ŒLoadtheaddressoftheGlobalVariable*£areafromSYSPAR.ŠSPC„2=ŠMOVE.BCCBPPRIO(A5),D1†Ifthehardwareinterruptpriorityof=ŠCMP.B‚QMAXIL(A4),D1†thenewCCBishigherthantheinterrupt7ŠBLS„INIT010ŒprioritiesofallpreviousCCBsallocated,?ŠMOVE.BD1,QMAXIL(A4)†copythenewmaximuminterruptlevelinto$*£theInterruptQueueControlTable.ŠSPC„2*J*ƒInitializethefieldsoftheCCBthatapplytoallinputchannelsonthe* the input module.*ŠSPC„2CINIT010ƒMOVE.LA4,CCBQCTAD(A5)†WritetheaddressesoftheInterrupt!*£QueueControlTabletotheCCB.ŠSPC„2;ŠLEA.L‚BACKGRND(PC),A0ŠInitializetheActivationAddressin@ŠMOVE.LA0,QBAB+BABPTR(A4)…theInterruptQueueControlentryBAB#*§totheentrypointaddressofthe*§backgroundinterrupthandler.ŠSPC„2;ŠLEA.L‚DOWNCHAN(PC),A0ˆStoretheentrypointaddressoftheCŠMOVE.LA0,CCBBAB+BABPTR(A5)BackgroundChannelShutdownHandlerin**¥thepointerfieldoftheBABintheCCB.ŠSPC„2;ŠCLR.B‚CCBIQENA(A5)‰SettheInterruptQueueingMasksothat%*£queueingofinterruptsisinitially,*£disabledforallinterruptchannelsonthe*£inputmodule.ŠSPC„29ŠCLR.B‚CCBCHTYP(A5)‰SettheChannelTypemasktomarkall$*£channelsinitiallyasnon-debounce *£channels.ŠPAGEE*‚ObtaintheJSRentrypointaddressesfortheRMS68KTrap0routines 6ŠMOVE.L#T0ENTRY,D0ŠCall theEntryPointroutineviaa2ŠMOVE.LD0,D1ŽTrap0toobtaintheJSRentrypointŠTRAPƒ#0‘oftheroutineitself.ŠNOPŠSPC„26ŠMOVE.LA0,A3SavetheEntryPointroutineJSRaddress*£inA3.ŠSPC„25ŠMOVE.L#0,D1ClearD1inpreparationfortheloading"*£oftheTrap0directivenumbers.ŠSPC„2<ŠLEA.L‚CCBGUARD(A5),A2†LoadthebaseaddressofblockofJSR*£addresslocationsintheCCB.ŠSPC„2:ŠLEA.L‚TRAP0TBL(PC),A1†LoadthebaseaddressoftheTrap0<ŠMOVE.W#NUMTR0-1,D0‡DirectiveNumberTableandinitializea'*£loopcounterwiththenumberoftable *£entries.ŠSPC„2AINIT020ƒMOVE.B(A1)+,D1LoadtheTrap0directivenumberintoD1.ŠSPC„21ŠJSR„(A3)‘CalltheEntryPointroutine.Theentry0ŠNOP—pointoftheroutinewhoseTrap0directive-*£numberisinD1willbereturnedinA0.The+*£NOPisaplacefillerfortheEntryPoint,*£directives"non-error"return.The"error"'*£return(followingtheNOP)isignored(*£becausetheTrap0routinesmustbein$*£RMS68Kforthisdrivertooperate.ŠSPC„26ŠMOVE.LA0,(A2)+StorethereturnedJSRaddressinthe*£correspondingCCBlocation.ŠSPC„25ŠDBRAƒD0,INIT020‹Loopuntilallentrynecessaryentry*£pointshavebeenobtained.ŠSPC„2)ŠRTS™TheinitializationoftheCCBisnow*£completesoreturntoCMR.ŠPAGEO********************************************************************************7*ŠInputModuleDriverCommonCommandProcessingRoutine7*Š-----------------------------------------------------*L*ƒThiscommandprocessingroutineiscalledbyCMRwheneverataskissuesanG* Initiate I/O command to CMR, via a Trap 1, that specifies the channelN* mnemonic for an input module controlled by this driver. The function of thisL* module is to perform all command independent pre-processing before passing<* control to one of the command specific processing modules.*H*ƒThisroutineassumesthattheInitiateI/OcommandparameterblockhasM* already been validated by CMR before entry to the command handler. The onlyH* fields in this parameter block that are processed here are the commandO* sub-code field and the fields that specify the base address and length of theK* Input Driver command parameter block(IPB). Command sub-codes for Reset or!* Halt I/O commands are rejected.*L*ƒAfterverifyingthattheuserspecifiedbaseaddressandlengthoftheIPBN* reside within the requesting tasks address space, several checks are made onL* the contents of the IPB for the following commands: Close Channels, EnableM* Interrupts, Disable Interrupts, and Input Status. All IPB validation for anN* Open Channels command is performed by the associated command specific moduleN* because its IPB structure is different from those of the other commands. ForL* the other commands this module validates IPB length and checks the ChannelM* number mask for non-existent channels (channel numbers 8-15) and checks forH* channels that the requesting task has not claimed via an Open Channels * command.*L*ƒAfterallIPBcheckshavebeenpassed,thecommandprocessingroutinejumpN* table is searched for a match to the specified Input Driver Command Code. IfO* no match is found the request is rejected and an error is returned. OtherwiseJ* a JSR is performed to the entry point of the command specific processing * routine.*J*ƒWhencontrolreturnstothismodulefollowingnormalcommandcompletion,M* the command handler returns to CMR with a zero status in D0. If an error isH* detected during command processing, a jump is performed to the commandN* handler error exit where the original value of the stack pointer is restored:* an a return is made to CMR with a non-zero status in D0.*F*‰EntryConditions:A2=InitiateI/OCommandparameterblockaddress1*œA5=AddressoftheCCBfortheInputModuleon'*¡whichthecommandistobeperformed.)*œA6=TCBaddressoftherequestingtask*2*‰ExitConditions‚:D0=Commandstatus/errorcode'*œAllotherregisterspreservedbyCMR.*F *‰GeneralRegisterUsage:D1=Containsanerrorcodewhenanexitis*§madethroughCMDERR&*¢D2=ChannelsMask(CMDCHM)fromIPB*¢D5=LengthofIPB*¢D0,D3,D6=Scratchregisters*¢A0,A1=Scratchregisters'*¢A4=PhysicalbaseaddressoftheIPB*O*******************************************************************************ŠPAGEK*ƒThefollowingtablecontainstheIPBcommandcodesthatarerecognizedbyM* this driver and the command specific processing routine entry point offsetsM* from the base address of the command table. For each table entry, the entryN* point offset to the command specific routine preceeds the command code. BothN* the offset and command code fields are 16-bit long to force each table entry* to start on a word boundary.ŠSPC„2:CMDTBL„DC.WƒOPEN-CMDTBL,INOPEN„OpenChannelscommandentry6ŠDC.WƒCLOSE-CMDTBL,INCLOSƒCloseChannelscommandentry:ŠDC.WƒSTATUS-CMDTBL,INSTAT‚ReadInputStatuscommandentry:ŠDC.WƒENABIN-CMDTBL,INENAB‚EnableInterruptscommandentry;ŠDC.WƒDSABIN-CMDTBL,INDSAB‚DisableInterruptscommandentryŠSPC„2;NUMCMD„EQU„(*-CMDTBL)/4‰Thisequatespecifiesthenumberof*£entriesinthecommandtable.ŠPAGEHCOMMANDƒMOVE.LA7,CCBCMDST(A5)†Savetheentryvalueofthestackpointer(*£intheCCBsoitcanberestoredifan&*£errorexitisrequiredfromanested *£subroutine.ŠSPC„22ŠCLR.L‚D1“Ifthecommandsub-codespecifiedinthe9ŠMOVE.B#INPISC,D1‰intheInitiateI/Oparameterblockis6ŠTST.B‚XIOSCD(A2)‰notzero,performanerrorexitwith(ŠBNE.L‚CMDERRaninvalidsub-codeerror.ŠSPC„29ŠMOVE.B#INPBAWB,D1ŠLoadthebaseaddressoftheIPBfrom>ŠMOVE.LXIOCPK(A2),D6†theInitiateI/Oparameterblock.Ifthe3ŠBTSTƒ#0,D6Žaddressisnotonawordboundary,exit7ŠBNE.L‚CMDERRwithanoddbyteboundaryparameterblock*£baseaddresserror.ŠSPC„2<ŠMOVE.B#INPPBLN,D1ŠLoadthelengthoftheIPBinbytesinto<ŠMOVE.WXIOPLN(A2),D5†D5andreturnaparameterblocklength4ŠCMP.W‚#4,D5Žerrorifthespecifiedlengthiseither6ŠBLO.L‚CMDERRlessthanfourbytesorspecifiesanoddŠBTSTƒ#0,D5Žnumberofbytes. ŠBNE.L‚CMDERRŠSPC„2*:*‰NewRegisterAssignmentsD5=LengthoftheIPBinbytes*<ŠMOVE.LCCBLOGPY(A5),A1†CallRMS68KsubroutineLOGPHY,viaa;ŠMOVE.LTCBTST(A6),A0†JSR,toverifythatthespecifiedIPB0ŠJSR„(A1)liesentirelywithintheaddressspace3ŠBRA„CMD010ofthetaskthatissuedthecommand.If**£noerrorisdetected,controlreturnsto)*£theinstructionfollowingthetrapwith)*£thephysicalbaseaddressoftheIPBin*£D6.ŠSPC„2)ŠNOP™Therearetwopossibleerrorreturns:ŠMOVE.B#INPPBLK,D1ˆfromLOGPHYatthetrapreturnaddress8ŠBRA.L‚CMDERRplustwoorfourbytesrespectively.Since+*£theerrorsarenotdifferentiatedhere,a&*£NOPisspecifiedforthefirsterror)*£return.Ineithercase,anexitismade'*£withaparameterblockaddresserror.ŠSPC„2=CMD010„MOVE.LD6,A4MovethephysicalbaseaddressoftheIPBAŠMOVE.WXIOPLN(A2),D5†intoA4andrestoretheIPBlengthinD5as)*£itwasdestroyedbytheLOGPHYroutine.ŠPAGE@*‰NewRegisterAssignments‚A4=PhysicalBaseAddressoftheIPB*CŠCMP.W‚#INOPEN,CMDCOD(A4)ƒIftheIPBcommandcodespecifiesanOpen9ŠBEQ„CMDFCTCK‹Channelscommand,skiptheremainingcommon*£IPBvalidationsteps.ŠSPC„26ŠMOVE.B#INPPBLN,D1ŠLoadtheerrorcodeforaninvalid(*£parameterblocklengthintothereturn*£statusregister.ŠSPC„29ŠCMP.L‚#CMDLEN,D5‹IfthespecifiedIPBlengthisequalto5ŠBEQ„CMD020thestandardlengthproceedwiththenext*£check.ŠSPC„22ŠBHI„CMDERRIfthespecifiedIPBlengthisgreater'*£thanthestandardlength,exitwitha*£parameterblocklengtherror.ŠSPC„2<ŠCMP.W‚#INCLOS,CMDCOD(A4)‚IftheIPBlengthislessthanthe3ŠBNE„CMDERRstandardlengthandthisisnotaClose-*£AllChannelscommand,exitwithaparameter*£blocklengtherror.ŠSPC„29ŠCMP.L‚#CMDLEN-2,D5‰TheonlyvalidIPBlengthforaClose7ŠBNE„CMDERRAll Channelscommandisthestandardlength7ŠBRA„CMDFCTCK‹minus2bytes.Foranyotherlength,exit&*£withaparameterblocklengtherror.ŠSPCƒ2*G*ƒCheckthebitmaskthatspecifiesthechannelstobeaffectedbythisN* command for non-existant channel numbers (8-15) and for channel numbers thatN* have not been connected to the requesting task via an Open Channels command.* ACMD020„MOVE.B#INPUNKWN,D1‰Iftheupperbyteofthechannelsmask;ŠTST.B‚CMDCHM(A4)‰wordoftheIPBisnon-zero,exitwithan)ŠBNE„CMDERRinvalidchannelnumbererror.ŠSPC„28ŠMOVE.B#INPOWNR,D1ŠLoadtheerrorcodeforspecifyinga,*£channelnotownedbytherequestorincase*£anerrorisdetected.ŠSPC„20ŠCLR.L‚D2“LoadtheleastsignificantbyteoftheAŠMOVE.BCMDCHM+1(A4),D2„channelsmaskwordintoD2.Movethemask2ŠSWAPƒD2‘bitsforthenon-interruptchannels(4-7)8ŠLSR.L‚#4,D2Žintothefourleastsignificantbitsofthe-*£upperwordofD2andmovethemaskbitsfor,*£theinterruptchannels(0-3)intothefour,*£mostsignificantbitsofthelowerwordof*£D2.ŠPAGE0ŠTST.W‚D2“Ifnoneoftheinterruptchannelswere6ŠBEQ„CMD045selectedinthechannelsmask,skiptothe(*£checksforthenon-interruptchannels.ŠSPC„2=ŠLEA.L‚CCBICCTE+1(A5),A0„Loadtheendaddressplusoneofthe**£InterruptChannelControlTableintoA0.ŠSPC„2CCMD030„LEA.L‚-ICCENTLN(A0),A0…UpdatetheICCTindextopointtothe-*£entryforthenextlowernumberedinterrupt *£channel.ŠSPC„23ŠLSL.W‚#1,D2Ifthenextbitofthechannelmaskis5ŠBCC„CMD040zero,thecorrespondinginterruptchannel+*£isnotaffectedbythecurrentcommandso*£skiptothenextchannel.ŠSPC„2=ŠCMP.L‚ICCTCB(A0),A6ˆIftheTCBaddressofthetasktryingto5ŠBNE„CMDERRaccessthechanneldoesnotmatchtheTCB**£addressintheInterruptChannelControl**£Entry,thentherequestedchannelisnot**£accessibletotherequestorsoexitwith#*£thepreviouslyloadederrorcode.ŠSPC„27CMD040„TST.W‚D2“Loopuntilallofthemaskbitsforthe1ŠBNE„CMD030interruptchannelshavebeenchecked.ŠSPC„21CMD045„SWAPƒD2“Movethechannelmaskbitsforthe5ŠBEQ„CMDFCTCK‹non-interruptchannelsintothe4least+*£significantbitsofthelowerwordofD2.+*£Ifnoneofthenon-interruptchannelsare(*£selected,skiptothecommandfunction *£codecheck.ŠSPC„23ŠLEA.L‚CCBNICCT(A5),A0†Loadthebaseaddressofthe&*£Non-interruptChannelControlTable.ŠSPC„27CMD050„LSR.B‚#1,D2Ifthenextbitofthechannelsmask4ŠBCC„CMD060iszero,thecorrespondingnon-interrupt+*£channelisnotaffectedbythecommandso*£skiptothenextchannel.ŠSPC„28ŠCMP.L‚(A0),A6ŽIftheTCBaddressofthetaskattempting4ŠBNE„CMDERRaccesstothechanneldoesnotmatchthe**£TCBaddressintheNon-interruptChannel#*£ControlEntry,thechannelisnot+*£accessabletotherequestingtasksoexit(*£withthepreviouslyloadederrorcode. ŠPAGE;CMD060„ADD.L‚#4,A0UpdatetheNon-interruptChannelControl4ŠTST.B‚D2‘Tablepointertoaccessthenextentryand2ŠBNE„CMD050loopuntilallspecifiednon-interrupt*£channelshavebeenchecked.ŠSPC„2 K*ƒThefollowingcodeverifiesthatthecommandcodespecifiedintheIPBisH*valid.‚ThenaJSRismade,viathecommandjumptable,tothecommand* specific handling routine. ACMDFCTCK‚LEA.L‚CMDTBL(PC),A1ˆLoadthebaseaddressofthecommand<ŠMOVE.B#INPICMD,D1ˆspecifichandlingroutinejumptableand>ŠMOVE.WCMDCOD(A4),D2†thecommandcodefromtheIPB.Alsoload&*£theerrorcodetobereturnedifthe**£specifiedcommandcodecannotbelocated*£inthejumptable.ŠSPC„23ŠMOVE.LA1,A0Copythejumptablebaseaddresstoa>ŠMOVE.L#NUMCMD-1,D0‡tableindexregister,loadaloopcounter4ŠCLR.L‚D3‘totellwhentheendofthejumptablehas+*£beenreached,andclearD3tocontainthe(*£offsetofthecommandhandlingroutine(*£entrypointrelativetothejumptable*£baseaddress.ŠSPC„2>CMD070„MOVE.W(A0)+,D3Loadtheentrypointoffset ofthenext7ŠCMP.W‚(A0)+,D2‹commandhandlerfromthejumptableand(*£comparethecorrespondingcommandcode*£tothecodefromtheIPB.ŠSPC„27ŠDBEQƒD0,CMD070ŒSearchthejumptableuntilanentryis-*£foundwithamatchingcommandcodeoruntil"*£theendofthetableisreached.ŠSPC„20ŠBNE„CMDERRIfcommandcodefromtheIPBdidnot)*£matchanyentryinthejumptable,exit(*£withthepreviouslyloadederrorcode.ŠSPC„2.ŠCLR.L‚D1“Clearthecommandstatusregisterto,*£indicatethatnoerrorshavebeendetected+*£intheCommonCommandProcessingRoutine.ŠSPC„22ŠJSRƒ0(A1,D3.W)ŒCalltheappropriatesubroutineto**£performthespecifiedcommand.Theentry+*£pointoffsetobtainedfromthejumptable'*£isaddedtothetablebaseaddressto$*£determinetheentrypointaddress.ŠPAGEDCMDERR„MOVE.LCCBCMDST(A5),A7†Restorethestackpointertothestate(*£ineffectwhenthecommandhandlerwas**£entered.Thisstepisnecessaryonlyfor**£errorexitsfromnestedsubroutines.For(*£normalcommandexits,thisinstruction**£actsasaNOPsincethestackisalready*£intheproperstate.ŠSPC„2=CMDDONEƒMOVE.LD1,D0MovethecommandreturnstatustoD0and@ŠMOVE.WD0,CMDSTA(A4)†totheIPBstatusfieldandreturntoCMR.ŠRTSŠPAGEO*********************************************************************************–OpenInputChannelsCommand*–---------------------------M*ƒThissubroutinecreatesconnectionsbetweenataskandoneormorechannelsO* on an input module. After a connection is made, the task has exclusive accessN* rights to the associated input channel. The task may then issue any commandsO* to manipulate the channel with the exception of another Open Channels command"* that specifies the same channel.*L*ƒThefirstfunctionperformedbythisroutineisvalidationofthecontentsJ* of the IPB (command parameter block). After verifying that the number ofN* channels to be opened is in the range 1-8, the minimum acceptable length forK* the specified number of channels is calculated and compared to the actualF* IPB length specified by the user. If the IPB length is less than theN* acceptable minimum, the routine exits with an error. The routine then checksL* the list of channels to be opened for invalid channel numbers (i.e. not inO* the range 0-7) or for channels that are already owned by some task (includingM* the requesting task). If either condition occurs, the routine exits with an* error.*I*ƒAftertheIPBcontentshavebeenvalidated,thesubroutineperformstheI* operations necessary to open and initialize the specified channels. ForJ* non-interrupt channels, the only operation necessary is to place the TCBK* address of the requesting task in the Non-interrupt Channel Control TableO* entries for the requested channels. When interrupt channels are being opened,J* the Interrupt Channel Control Table entry for each channel is cleared toL* zeros and initialized using the TCB address of the requesting task and theG* information contained in the Configuration word for each channel. TheI* required initialization of the VME 610/620 module hardware is done in aO* single operation after all channels have been opened rather than by accessing)* the hardware as each channel is opened.*+*‰EntryRegisters:D5=CommandIPBlength&*›A4=PhysicaladdressofcommandIPB*›A5=CCBaddress*›A6=Requestor'sTCBaddress*4*‚GeneralRegisterUsage:A0-A2=Workingregisters4*›A3=Baseaddressoflistofchannelstobeopened*›D2,D3,D5=WorkingRegisters&*›D4=Numberofchannelstobeopened/*›D6-D7=Usedtoaccumulatemiscellaneousdata,*£necessarytoinitializeinterruptchannels*1*‰ExitRegisters‚:‚D1=CommandCompletionStatus*œA5=CCBAddress*œA6=Requestor'sTCBaddress**œAllotherregistersarepreservedbyCMR*O*******************************************************************************ŠPAGE@OPEN†MOVE.B#INPMAXCH,D1‰Loadtheerrorcodetobeissuedifthe**£numberof channelstoopenisnotinthe *£range1-8.ŠSPC„2.ŠCLR.L‚D2“Ifthenumberofchannelstoopenis;ŠMOVE.WCMDNCO(A4),D2†zero,exitwithanerror.Makeacopy6ŠMOVE.LD2,D4ŽofthenumberofchannelstoopeninD4. ŠBEQ„CMDERRŠSPC„25ŠCMP.W‚#8,D2Ifthenumberofchannelstoopenhasan3ŠBHI„CMDERRunsignedvaluegreaterthaneight,exit*£withanerror.ŠSPC„22ŠLSL.W‚#2,D2Multiplythenumberofchannelstobe<ŠADD.W‚#CMDLEN,D2‰openedbythelengthofthedatablockfor+*£eachchannel(4bytes)andaddthelength**£ofastandardcommandparameterblockto**£determinetheexpectedlengthoftheIPB *£inprocess.ŠSPC„2;ŠMOVE.B#INPPBLN,D1ŠIftheactuallengthoftheIPBisless2ŠCMP.L‚D2,D5Žthantheexpectedlength,exitwitha5ŠBLO„CMDERRparameterblocklengtherror.Noerroris'*£returnediftheIPBislongerthanis'*£necessaryforthespecifiednumberof *£channels.ŠSPC„29ŠLEA.L‚CMDCHL(A4),A3ˆLoadthebaseaddressofthelistof6ŠMOVE.LA3,A0ŽchannelstobeopenedintoA3andmakea3ŠSUB.W‚#1,D4ŽscratchcopyinA0.Loadthenumberof(*£channelstoopenminusonetouseasa*£loopcounter.ŠSPC„2/ŠCLR.B‚D6“ClearthelowerbyteofD6sothatit)*£canbeusedtoaccumulateamaskofall*£channelstobeopened.ŠSPC„2AOPN010„MOVE.WOPNCHN(A0),D0ˆLoadthenextchannelnumberfromthe *£listofchannelstobeopened.ŠSPC„2>ŠMOVE.W#INPUNKWN,D1‰Ifthechannelnumberspecifiedisnotin2ŠCMP.W‚#7,D0Žtherange0-7,performanerrorexit. ŠBHI„CMDERRŠSPC„29ŠMOVE.W#INPDUPL,D1ŠIfthechannelsmaskbitforthenext6ŠBSETƒD0,D6Žchanneltobeopenedisalreadyset,issue6ŠBNE„CMDERRtheerrorforspecifyingduplicatechannel**£numbers.Otherwisesetthechannelsmask*£bitforthenewchannel.ŠPAGE8ŠMOVE.B#INPOWNR,D1ŠLoadtheerrorcodeforspecifyinga)*£channelnumberthatisownedbyanother*£task.ŠSPC„2<ŠLEA.L‚CCBICCT(A5),A1‡Incasethechanneltobeopenedisan=ŠMOVE.W#ICCENTLN,D3‡interruptchannel,loadthebaseaddress6ŠMULUƒD0,D3ŽoftheInterruptChannelControlTableandEŠLEA.L‚ICCTCB(A1,D3.L),A2loadA2withtheaddressoftheTCBaddress-*£fieldofthetableentryforthechannelto *£beopened.ŠSPC„26ŠCMP.W‚#3,D0Ifthenumberofthechanneltobeopened3ŠBLS„OPN020isforainterruptchannel(range4-7),)*£wealreadyhavetherightcontroltable,*£addressandentrylengthloadedsoskipto*£thetableoffsetcalculation.ŠSPC„23ŠLEA.L‚CCBNICCT(A5),A1†Loadthebaseaddressofthe&*£Non-interruptchannelcontroltable.ŠSPC„26ŠMOVE.WD0,D3Subtractfourfromthechannelnumberto5ŠSUB.W‚#4,D3ŽobtaintheNon-InterruptChannelControl**£Tableentrynumberforthechannelbeing *£opened.ŠSPC„23ŠLSL.L‚#2,D3Multiplythetableentrynumberbythe@ŠLEA.L‚0(A1,D3.L),A2†entrylength(4bytes)andloadA2withthe,*£addressofthetableentryforthechannel*£beingopened.ŠSPC„27OPN020„TST.L‚(A2)‘IftheownerTCBaddressfieldofthe5ŠBEQ„OPN025channelcontrolentryiszero,proceedto&*£checkthenextchanneltobeopened.ŠSPC„26ŠCMP.L‚(A2),A6ŽIftheTCBaddressofthechannelowner6ŠBNE„CMDERRdoesnotmatchthatoftherequestor,exit#*£witharequestornotownererror.ŠSPC„2<ŠMOVE.B#INPAOPN,D1ŠIfthetaskrequestingthechanneltobe4ŠBRA„CMDERRopenedalreadyownsthechannel,issuea*£channelalreadyopenederror.ŠSPC„2ŠMOVE.WCMDNCO(A4),D4ˆLoadthenumberofchannelstobeopened6ŠSUB.W‚#1,D4Žminusonetoserveasaloopcounter.The)*£baseaddressofthelistofchannelsto!*£openisalreadyloadedintoA3.ŠSPC„2BOPN030„MOVE.WOPNCHN(A3),D0ˆLoadthenumberofthenextchannelto"*£beopenedfromthechannellist.ŠSPC„24ŠMOVE.WD0,D5Storethechannelnumberplus16inD58ŠADD.W‚#16,D5Thisvalueisusedtomanipulatedatabits"*£intheupperwordsofD6andD7.ŠSPC„26ŠCMP.W‚#3,D0Ifthenumberofthechanneltobeopened1ŠBLS„OPN040isintherange0-3,branchtohandle*£openinganinterruptchannel.ŠSPC„2G*ƒOpenanon-interruptchannelandinitializetheNon-interruptChannel* Control Entry.ŠSPC„25ŠSUB.W‚#4,D0Subtractfourfromthechannelnumberto**£obtaintheNon-interruptChannelControl+*£Tableentryforthechannelbeingopened.ŠPAGE?ŠLEA.L‚CCBNICCT(A5),A1†Sincethechanneltobeopenedisanon-(*£interruptchannel(4-7),loadthebase&*£addressoftheNon-interruptChannel*£ControlTable.ŠSPC„27ŠMOVE.WD0,D3Multiplythechannelnumberbythelength7ŠLSL.W‚#2,D3ŽofaNon-interruptControlEntry(4bytes)@ŠMOVE.LA6,0(A1,D3.L)†todeterminetheoffsetforthechannelto)*£beopened.StoretheTCBaddressofthe,*£requestingtaskinthetableentrytoopen*£thechannel.ŠSPC„23ŠBRA„OPN100Branchtotheendofthelooptoset-up$*£forthenextchanneltobeopened.ŠSPC„2H*ƒOpenaninterruptchannelandinitializetheInterruptChannelControl* Entry.ŠSPC„2EOPN040„LEA.L‚CCBICCT(A5),A1‡Loadthebaseaddressandentrylengthof9ŠMOVE.W#ICCENTLN,D3‡theInterruptChannelControlTable.ŠSPC„2/ŠBSETƒD5,D6Sinceaninterruptchannelistobe(*£opened,settheappropriatebitinthe**£upperwordofD6(maskofchannelstobe *£opened).ŠSPC„24ŠMULUƒD0,D3Multiplythenumberofthechanneltobe=ŠLEA.L‚0(A1,D3.L),A1†openedbythetableentrylengthtofind'*£thetableentryoffset.Loadthebase*£addressoftheentryintoA1.ŠSPC„2F*ƒInitializetheInterruptChannelControlEntryforthechanneltobe * opened.ŠSPC„26ŠMOVE.LA1,A0InitializetheInterruptChannelControl(ŠMOVE.W#ICCENTLN,D1‡Entrytoallzeros.OPN050„CLR.B‚(A0)+ŠDBRAƒD1,OPN050ŠSPC„29ŠLEA.L‚DBTOBKG(PC),A0‹LoadtheentrypointaddressoftheAŠMOVE.LA0,ICCBAB+BABPTR(A1)ƒBackgroundDebounceTime-outHandler(*§andstoreitintheActivationAddress(*§fieldoftheInterruptChannelControl *§EntryBAB.ŠPAGE>ŠMOVE.LCCBBKGST(A5),ICCBKGST(A1)‚StoretheJSRaddressofthe%*©backgroundschedulerroutineinthe%*©ICCTentryforusebytheInterrupt*©DebounceTimeoutHandler.ŠSPC„2=ŠMOVE.LA6,ICCTCB(A1)ˆStoretheTCBaddressoftherequesting-*£taskintheentrytomarkthechannelopen.ŠSPC„28ŠMOVE.LA5,ICCB(A1)ŠStoretheCCBaddressinthecontrol&*£entry.Thisisnecessarybecausethe)*£BackgroundDebounceTimeoutHandlerhas+*£onlytheaddressoftheInterruptChannel)*£ControlEntrywhen  itbeginsexecution.ŠSPC„2;ŠMOVE.BD0,ICCNUM(A1)ˆStorethenumberofthechannelbeing**£openedintheentry.Thisinformationis(*£alsoneededbytheBackgroundDebounce*£TimeoutHandler.ŠSPC„2;ŠMOVE.WOPNCFG(A3),D1ˆIfbit7oftheChannelConfiguration2ŠBPL„OPN060wordclear,branchtoprocesstheuser*£specifiedconfiguration.ŠSPC„2=ŠMOVE.W#DEFLTCFG,D1‰Sincebit7oftheChannelConfiguration**£wordwasset,theuserwishestousethe)*£defaultconfiguration.Loadthedefault)*£configurationwordforprocessingasif*£ithadbeenuserspecified.ŠSPC„2:OPN060„LSR.W‚#2,D1Ignorebit0oftheconfigurationword.0ŠBCS„OPN070IftheInterruptControlbitsaysto,*£disableinterrupts(bitset),noactionis'*£necessarysinceinterruptsarealways-*£disabledpriortoopeningachannelandthe(*£InterruptsEnabledflaginthechannel!*£controlentryisalreadyclear.ŠSPC„27ŠST…ICCENABL(A1)‰SettheInterruptsEnabledflaginthe-ŠBSETƒD0,D7Žchannelcontrolentryandsetthe-*£bitintheInterruptControlregisterimage-*£inD7thatcorrespondstothenumberofthe*£channelbeingopened.ŠSPC„2:OPN070„LSR.W‚#1,D1Ifinterruptsaretooccuronenergized3ŠBCC„OPN080todeenergizedtransitions,theICCEDGE,*£flaginthecontrolentryisalreadyclear**£andtheappropriatebitoftheInterrupt'*£SenseControlregisterimageinD6is*£alreadyclear.ŠPAGE0ŠST…ICCEDGE(A1)ŠSinceinterruptsaretooccuron5ŠBSETƒD0,D6Ždeenergizedtoenergizedtransitions,set+*£theICCEGDEflaginthecontrolentryand,*£setthebitoftheInterruptSenseControl**£registerimageinD6thatcorrespondsto)*£thenumberofthechannelbeingopened.ŠSPC„2:OPN080„LSR.W‚#1,D1Ifinterruptnotificationistobemade/ŠBCS„OPN090viaaWAKEUPrequesttoRMS68K,the'*£ICCQEVNTflaginthecontrolentryis*£alreadyclear.ŠSPC„26ŠST…ICCQEVNT(A1)‰Sinceinterruptnotifiactionistobe)*£madeviaaeventsenttotherequestors'*£ASQ,theICCQEVNTflaginthecontrol*£entryisset.ŠSPC„2:OPN090„BCLRƒD5,D7Cleartheappropriatebitofthechannel+*£typemaskintheupperwordofD7incase,*£nosoftwaredebounceistobeperformedon*£thechannel.5ŠLSR.W‚#4,D1Skipbits4-7oftheconfigurationword.ŠSPC„25ŠLSL.W‚#2,D1Multiplythedebounceintervallengthby2ŠBEQ„OPN100fourtodeterminethenumberofmilli-)*£secondsperdebounceintervalandstore)*£theresultinthecontrolentry.Ifthe&*£intervallengthiszero,nosoftware-*£debounceistobeperformedonthechannel.ŠSPC„2?ŠMOVE.WD1,ICCDBINT(A1)†Storethedebounceintervallengthinto1ŠBSETƒD5,D7Žthechannelcontrolentryandsetthe**£appropriatebitofthechanneltypemask**£intheupperwordofD7toindicatethat!*£thechannelistobedebounced.ŠSPC„2>OPN100„ADD.L‚#OPNCDB,A3‹AdjustthepointerinA3toselectthe:ŠDBRAƒD4,OPN030Šnextentryinthelistofchannelstoopen+*£andloopuntilalllistentrieshavebeen *£processed.ŠPAGE!*[**********WARNING**********] G*ƒThefollowingsectionofcodeperformshardwaresetup,clearspendingI* interrupts on all channels being opened and then enables queuing of newO* interrupts by the Foreground Interrupt Handler. This code is HIGHLY interruptI* sensitive. The sequence of operations given below is CRITICAL to assureK* that newly opened interrupt channels are initialized properly and withoutO* side effects. NOTE that interrupts must not be disabled anywhere in this codeJ* since the Foreground Interrupt Handler must execute to clear any pending * interrupts.ŠSPC„2>ŠMOVE.LCCBCHB(A5),A0ˆLoadthebase,memory-mappedI/Oaddress'*£oftheinputmodulehardwareintoA0.ŠSPC„24ŠMOVE.BD6,D0Copythehardwareinterruptsensebits3ŠLSL.B‚#4,D0Žfrombits0-3ofD6tobits4-7ofD0.ŠSPC„22ŠSWAPƒD6“Copythemaskofinterruptchannelsbeing3ŠOR.BƒD6,D0Žopenedbythecurrentcommandfrombits *£16-19ofD6tobits0-3ofD0.ŠSPC„2ŠOR.BƒD0,CCBINTCR(A5)!ŠMOV  E.BCCBINTCR(A5),INPICNTR(A0))*¥ORthevalueinbits0-7ofD0withthe+*£hardwareinterruptcontrolregisterimage+*£intheCCBandmovetheimagetothereal-*£hardwareregister.Bits4-7ofD0configure&*£theinterruptsensebitsforthenew-*£channelsasspecifiedbytheuser.Bits0-3**£ofD0enableinterruptsforthechannels,*£beingopened.Thusanyinterruptsthatare,*£pending(whetherpre-existingorcausedby(*£initializationofthesensebits)will(*£occur.Anysuchinterruptswillnotbe**£placedintheInterruptProcessingQueue%*£bytheForegroundInterruptHandler(*£becauseinterruptqueueingforthenew)*£channelsisdisabledbythebitmaskin *£CCBIQENA.ŠPAGE?ŠEOR.B‚D6,CCBINTCR(A5)†EORthemaskofinterruptchannelsbeing,*£openedwiththehardwareinterruptcontrol**£registerimagetoforceinterruptstobe**£disabledforthenewchannels.Notethat**£althoughtheregisterimageisnotmoved**£tothehardwareuntilafterexecutionof+*£thenextinstruction,nodamagecanoccur*£ifaninterruptoccurshere.ŠSPC„27ŠOR.BƒD7,CCBINTCR(A5)Setthestateofinterrupts(i.e.>ŠMOVE.BCCBINTCR(A5),INPICNTR(A0)enabled/disabled)onthenew*ªchannelsasspecifiedbythe&*ªcommand.Thebitsarechangedinthe!*ªcontrolregisterimageandthen*ªmovedtotheactualhardware!*ªregister.Notethatqueueingof&*ªinterruptsisstilldisabledforthe*ªnewchannels.ŠSPC„2+ŠSWAPƒD7“ORthechanneltypebitsfrombits?ŠOR.BƒD7,CCBCHTYP(A5)„16-19ofD7intothechanneltypemaskin(*£theCCB.Thisstepmustbedonebefore**£theinterruptqueuesareenabledsothat**£nointerruptsarediscardedprematurely.ŠSPC„2?ŠOR.BƒD6,CCBIQENA(A5)†ORthemaskofchannelstobeopenedinto-*£theInterruptQueueEnablemaskintheCCB.+*£Theenablingoftheinterruptqueuesmust$*£bethelaststeptoassurethatno,*£undesiredinterruptsarequeued.Thisalso-*£servestosimultaneously"arm"allchannels*£openedinthesamecommand.ŠSPC„29*‰[**********ENDOFINTERRUPTSENSITIVECODE**********]ŠSPC„2K*ƒAtthispoint,OpenChannelscommandprocessinghasbeencompletedandnoK* errors were detected so a return is made to the Common Command Processing * Routine.ŠSPC„29OPNRTN„CLR.L‚D1“SetD1tozerotoindicatethatnoerrors+ŠRTS—weredetectedandreturntotheCommon*£CommandProcessingRoutine.ŠPAGEO********************************************************************************(*‘CloseAllorSelectedChannelsCommand(*‘--------------------------------------*L*ƒThisroutineclosespreviouslyestablishedconnectionsbetweenausertaskJ* and one or more channels of an input module. If the user has specified aJ* non-zero mask of channels to close, only those selected channels will beJ* affected by the command. If the channel mask is zero or the IPB does notK* contain a channel mask, all channels currently attached to the requesting* task are closed.*G*ƒNon-interruptchannelsareclosedbysimplyclearingtheowningtasksF* TCB address from the Non-Interrupt Channel Control Table entry. WhenF* interrupt channels with software debounce are closed, interrupts areJ* disabled and any debounce operations in progress are canceled before theH* owners TCB address is cleared from the Interrupt Channel Control TableK* entry. Non-debounce interrupt channels are closed by disabling interruptsH* and clearing the owners TCB address from the ICCT entry. Also, when anL* interrupt channel is closed, whether debounce or non-debounce, queueing ofK* interrupts for the channel is disabled and the channel type bit is set toL* zero so that a new channel type may be ORed in if the channel is reopened.*=*Entryregisters:D5=InputCommandParameterBlocklength,*¢A4=InputCommandParameterBlockaddress*¢A5=CCBaddress*¢A6=RequestorsTCBaddress*%*RegisterUsage‚:D0=WorkRegister*¢D3=WorkRegister(CLSINTCH)*¢D4=WorkRegister(CL  SINTCH) *¢D7=Maskofchannelstoclose*¢A0=WorkRegister*¢A1=WorkRegister*7*ExitRegisters‚:Entryregistersandunusedregisters+*¢preserved.Allotherregistersdestroyed.*O*******************************************************************************ŠPAGEBCLOSE…MOVE.B#%11111111,D7ˆLoadachannelmaskofallonesincase%*£theusertaskwantsallofitsopen*£channelsclosed.ŠSPC„24ŠCMP.W‚#CMDLEN,D5‹IftheIPBlengthislessthanthe0ŠBNE„CLS010standardlength,thisisacloseall**£channelscommandsousethechannelmask*£alreadyloadedinD7.ŠSPC„2<ŠMOVE.BCMDCHM+1(A4),D0†Ifthespecifiedmaskofchannelsto5ŠBEQ„CLS010closeiszero,processasforacloseall*£channelscommand.ŠSPC„26ŠMOVE.BD0,D7Movetheuserspecifiedmaskofchannels*£tocloseintoD7.ŠSPC„2L*ƒPerformcloseoperationsfornon-interruptchannelsinorderofdecreasing* channel number.ŠSPC„2FCLS010„LEA.L‚CCBNICCE+1(A5),A1„Loadtheendingaddressplusoneofthe8ŠMOVE.L#4-1,D0ŒNon-interruptChannelControlTableinto)*£anindexregisterandinitializealoop *£counter.ŠSPC„29CLS020„SUB.L‚#4,A1Adjustthetableindextotheprevious*£tableentry.ŠSPC„24ŠLSL.B‚#1,D7Ifthechannelmaskbitforthecurrent5ŠBCC„CLS030channelnumberisclear,skiptothenext *£channel.ŠSPC„25ŠCMP.L‚(A1),A6ŽIftheTCBaddressoftherequestoris6ŠBNE„CLS030notthesameasthatofthetaskthatowns(*£thechannel,skiptothenextchannel.$*£Thisconditioncanonlyoccurwhen**£processingacloseallchannelscommand.ŠSPC„2/ŠCLR.L‚(A1)‘CleartheownersTCBaddressinthe+*£Non-interruptChannelControlTableentry*£toclosethechannel.ŠSPC„2;CLS030„DBRAƒD0,CLS020ŒLoopuntilallnon-interruptchannels*£havebeenprocessed.ŠPAGE9ŠMOVE.LCCBGUARD(A5),A1†Thenecessaryprocessingtoclose=ŠLEA.L‚CLSINTCH(PC),A0„interruptchannelsisperformedfroma.ŠJSR„(A1)guardedsubroutine.Sincebackground&*£activitywillbesuspendedwhilethe%*£subroutineexecutes,eachinterrupt#*£channelisshutdowninaneatand)*£orderlyfashion.Theguardedsubroutine"*£isenteredviaacalltoRMS68K.ŠSPC„2+ŠRTS™Afterallrequestedchannelshavebeen&*£closed,returntotheCommonCommand*£ProcessingRoutineŠPAGEO********************************************************************************-*CloseInterruptChannelsGuardedSubroutine-*-------------------------------------------*H*ƒThissubroutineisexecutedbyRMS68KinGuardedMode.GuardedModeisL* used when operations are to be performed (i.e. modification of shared dataI* structures) that are sensitive to "concurrent" background activity as aD* result of an interrupt. While the guarded subroutine executes, newL* background processes may be scheduled but their execution is held pending.*I*ƒWithintheenvironmentofthisdriver,GuardedModeblocksexecutionofL* the Background Interrupt Handler, Background Debounce Timeout Handler, andI* the Background Channel Shutdown Handler. Since Close command processingG* affects several data structures that are accessed by these backgroundF* routines, the guarded subroutine guarantees mutual exclusion without5* requiring interrupts to be masked at the processor.*J*‚Thisroutinedisablesqueueingofinterrupts,disablesinterruptsattheH* VME 160/620 module, and cancels any pending debounce operations on the* channels being closed.*<*EntryRegisters:D7=Maskofinterruptchannelstoclose*§(bits4-7only)*¢A5=CCBaddress*¢A6=RequestorsTCBaddress*.*Registerusage‚:D3=Currentchannelnumber!*¢D4=Currentchannelnumber+4)*¢A0=Memory-mappedchannelbaseaddress*¢A1=ICCTentryaddress*=*ExitRegisters‚:A5,A6,andallunusedregisterspreserved *¢Allotherregistersdestroyed.*N******************************************************************************ŠPAGEFCLSINTCH‚MOVE.LCCBCHB(A5),A0ˆLoadthememory-mappedinputmodulebase   *£address.ŠSPC„2=ŠLEA.L‚CCBICCTE+1(A5),A1„Loadtheendaddressplusoneofthe"*£InterruptChannelControlTable.ŠSPC„21ŠMOVE.B#3,D3Processingwillbedoneinorderof5ŠMOVE.B#3+4,D4Œdecreasingchannelnumbersoloadthe)*£startingchannelnumberintoD3andthe,*£startingchannelnumberplusfourintoD4.ŠSPC„2FCLI010„LEA.L‚-ICCENTLN(A1),A1…UpdatethetableindextotheICCTentry&*£forthenextlowernumberedchannel.ŠSPC„24ŠLSL.B‚#1,D7Ifthecurrentbitofthechannelsmask/ŠBCC„CLI030isclear,skiptothenextchannel.ŠSPC„2;ŠCMP.L‚ICCTCB(A1),A6ˆIftheTCBaddressoftherequestoris6ŠBNE„CLI030notthesameasthatofthechannelowner,**£skiptothenextchannel.Thiscondition,*£canoccuronlywhenprocessingaCloseAll*£Channelscommand.ŠSPC„2<ŠBCLRƒD3,CCBIQENA(A5)†Disablequeueingofinterruptsforthe*£channelbeingclosed.ŠSPC„2:ŠBCLRƒD4,CCBINTCR(A5)†Clearthesensebitintheinterrupt)*£controlregisterimagethatcorresponds(*£tothechannelbeingclosed.Thiswill**£allowanewsensebitsettingtobeORed"*£inwhenthechannelisreopened.ŠSPC„28ŠBCLRƒD3,CCBCHTYP(A5)†Clearthechanneltypebitforthe)*£channelbeingclosed.Thiswillallowa(*£newchanneltypesettingtobeORedin*£whenthechannelisreopened.ŠSPC„28ŠBSR.L‚DBCANCLŽCallDBCANCLtodisableinterruptsonthe(*£channelbeingclosedandtocancelany,*£pendingsoftwaredebounceprocessing.Note**£thatthecalledroutineisautomatically**£guardedsinceitiscalledfromwithina*£guardedsubroutine.ŠSPC„2;ŠCLR.L‚ICCTCB(A1)‹CleartheownersTCBaddressfieldofthe"*£ICCTentrytoclosethechannel.ŠSPC„24CLI030„SUB.B‚#1,D3Preparetoprocessthenextlower(ŠSUB.B‚#1,D4Žnumberedinterruptchannel.ŠSPC„21ŠTST.B‚D7“Loopuntilallinterruptchannelstobe'ŠBNE„CLI010closedhavebeenprocessed.ŠSPC„2$ŠRTS™Returntothenon-guardedclose*£processingroutine.ŠPAGEO********************************************************************************.*EnableInterruptsCommandProcessingRoutine.*--------------------------------------------*E*…ThisenablesinterruptsononeormorechannelsasspecifiedbytheI* requesting task. If any of the specified channels are already interruptI* enabled a warning code is returned to the user in D0 and in the commandI* parameter block but interrupts are still enabled on the other requestedG* channels. First, queueing of interrupts is disabled for the specifiedL* channels. Next interrupts are enabled on the input module hardware so thatJ* any pending interrupts will occur and be discarded. Finally, queueing ofJ* interrupts on the selected channels is reenabled. Due to restrictions inL* the VME 610/620 module hardware, interrupt conditions occuring on disabledM* channels may or may not still be pending when interrupts are later enabled.M* Since the status of pending interrupts is not predictable prior to enablingH* of interrupts, pending interrupts are cleared to put each channel in a* known state.*>*EntryRegisters:A4=InputCommandParameterBlockaddress*¢A5=CCBaddress*%*Registerusage‚:D0=WorkRegister+*¢D1=Commandstatus(warningcodeifany)!*¢D6=Maskofchannelstoenable!*¢D7=Maskofchannelstoenable)*¢A0=Memory-mappedchannelbaseaddress*¢A1=ICCTentryaddress*7*ExitRegisters‚:Entryregistersandunusedregisters(*¢arepreserved.Allotherregistersare *¢destroyed.*O*******************************************************************************ŠPAGE9ENABIN„BSR.L‚EIDICHKŽCallEIDICHKtovalidatethemaskof)*£channelstobeenabledandtoloaddata*£intovariousregisters.**£Onreturn:D1=Destroyed*¯D6=EnableChannelsMask*¯D7=EnableChannelsMask*¯A0=Memory-mappedchannel*´baseaddress*¯A1=ICCTbaseaddressŠSPC„2F*ƒThefollowingcodelooksforchannelsspecifiedinthemaskthatareK* already interrupt   enabled. If any such channels are found, a warning codeH* is loaded into D1 and the corresponding channel mask bits are cleared.ŠSPC„2:ENA010„LSR.B‚#1,D7Ifthemaskbitforthecurrentchannel/ŠBCC„ENA030isclear,skiptothenextchannel.ŠSPC„29ŠTST.B‚ICCENABL(A1)‰Testtheinterruptenableflaginthe9ŠST…ICCENABL(A1)‡ICCTentryandthensettheflag.Ifthe3ŠBEQ„ENA030flagwaspreviouslyclear,proceedwith*£thenextchannel.ŠSPC„2=ŠMOVE.BICCNUM(A1),D0ˆSinceinterruptsarealreadyenabledon7ŠBCLRƒD0,D6Žthecurrentchannel,forcethemaskbitfor<ŠMOVE.B#INPINTR,D1ˆthechanneltozeroandloadthewarning*£codeintoD1.ŠSPC„2BENA030„LEA.L‚ICCENTLN(A1),A1†UpdatetheindexregistertotheICCT4ŠTST.B‚D7‘entryforthenexthighernumberedchannel5ŠBNE„ENA010andloopuntilalltherequestedchannels*£havebeenchecked.ŠSPC„2J*ƒThefollowingcodeclearspendinginterruptsandthenenablesinterruptsI* on the requested channels that were disabled when the request was made.ŠSPC„2=ŠEOR.B‚D6,CCBIQENA(A5)†Disablequeueingofinterruptsforthe*£channelstobeenabled.ŠSPC„28ŠOR.BƒD6,CCBINTCR(A5)EnableinterruptsontherequestedEŠMOVE.BCCBINTCR(A5),INPICNTR(A0)channels.Anypendinginterruptson#ŠNOPžthechannelswilloccurandbe)ŠNOPždiscarded.TheNOPsarenecessaryto%ŠNOPžallowtimeforthisinterruptto*ªoccur.ŠSPC„2;ŠOR.BƒD6,CCBIQENA(A5)†Enablequeueingofinterruptsforthe"*£channelsthatwerejustenabled.ŠPAGE,ŠRTS™ReturntotheCommonCommandProcessing+*£Routinewitheitheranoerrororwarning*£statusinD1.ŠPAGEO********************************************************************************/*DisableInterruptsCommandProcessingRoutine/*---------------------------------------------*J*ƒThisroutinedisablesinterruptsononeormorechannelsasspecifiedbyL* the requesting task. The routine verifies that only interrupt channels areN* specified in the channels mask. If any of the channels specified are alreadyI* interrupt disabled, a warning code is returned in D0 and in the commandJ* parameter block but interrupts are still disabled on the other requestedH* channels. The remainder of the processing to disable interrupts on theO* channels is performed from within a guarded subroutine so that all background* activity is suspended.*>*EntryRegisters:A4=InputCommandParameterBlockaddress*¢A5=CCBaddress*%*Registerusage‚:D0=WorkRegister+*¢D1=Commandstatus(warningcodeifany)!*¢D6=Maskofchannelstoenable!*¢D7=Maskofchannelstoenable)*¢A0=Memory-mappedchannelbaseaddress*¢A1=ICCTentryaddress*7*ExitRegisters‚:Entryregistersandunusedregisters(*¢arepreserved.Allotherregistersare *¢destroyed.*O*******************************************************************************ŠPAGE7DSABIN„BSR„EIDICHKŽCallEIDICHKtovalidatethemaskof**£channelstobedisabledandtoloaddata*£intovariousregisters.**£Onreturn:D1=Destroyed*¯D6=DisableChannelsMask*¯D7=DisableChannelsMask*¯A0=Memory-mappedchannel*´baseaddress*¯A1=ICCTbaseaddressŠSPC„2;DSA010„LSR.B‚#1,D7Ifthedisablechannelsmaskbitforthe6ŠBCC„DSA030currentchannelisclear,skiptothenext *£channel.ŠSPC„2:ŠTST.B‚ICCENABL(A1)‰Ifinterruptsarecurrentlyenabledon2ŠBNE„DSA030thechannel,proceedtocheckthenext *£channel.ŠSPC„29ŠMOVE.BICCNUM(A1),D0ˆClearthechannelsmaskbitforthe1ŠBCLRƒD0,D6Žalreadydisabledchannelandloadthe)ŠMOVE.B#INPINTR,D1ˆwarningcodeintoD1.ŠSPC„2CDSA030„LEA.L‚ICCENTLN(A1),A1†UpdatetheindextotheICCTentryfor3ŠTST.B‚D7‘thenexthighernumberedchannelandloop2ŠBNE„DSA010untilallrequestedchannelshavebeen *£checked.ŠSPC„2?ŠMOVE.LCCBGUARD(A5),A1†Theremainderofthedisableinterrupts<ŠLEA.L‚GDSABLE(PC),A0…processingisperformedfromaguarded0ŠJSR„(A1)subrouti  newhichiscalledviaRMS68K.ŠSPC„2,ŠRTS™ReturntotheCommonCommandProcessing *£Routine.ŠPAGEO********************************************************************************'*•GuardedDisableInterruptsSubroutine'*•-------------------------------------*H*ƒThissubroutineisexecutedbyRMS68KinGuardedMode.GuardedModeisL* used when operations are to be performed (i.e. modification of shared dataI* structures) that are sensitive to "concurrent" background activity as aD* result of an interrupt. While the guarded subroutine executes, newL* background processes may be scheduled but their execution is held pending.*I*ƒWithintheenvironmentofthisdriver,GuardedModeblocksexecutionofL* the Background Interrupt Handler, Background Debounce Timeout Handler, andH* the Background Channel Shutdown Handler. Since this subroutine affectsI* several data structures that are accessed by these background routines,F* the guarded subroutine guarantees mutual exclusion without requiring+* interrupts to be masked at the processor.*H*ƒThefunctionofthisroutineistodisableinterruptsonthecurrentlyN* enabled channels that were specified by the requesting task and to terminateB* pending software debounce operations, if any, on these channels.*>*Entryregisters:D6=Maskofchannelstointerruptdisable*¢A5=CCBaddress*¢A6=RequestorsTCBaddress*.*Registerusage‚:D3=Currentchannelnumber)*¢A0=Memory-mappedchannelbaseaddress*¢A1=ICCTentryaddress*;*Exitregisters‚:Allentryregistersandunusedregisters&*¢(exceptD6)arepreserved.Allother*¢registersaredestroyed.*O*******************************************************************************ŠPAGEDGDSABLEƒMOVE.LCCBCHB(A5),A0ˆLoadthememory-mappedchannelbaseand,ŠLEA.L‚CCBICCT(A5),A1…theICCTbaseaddress.ŠSPC„2:GDS010„LSR.B‚#1,D6Ifthemaskbitforthecurrentchannel/ŠBCC„GDS020isclear,skiptothenextchannel.ŠSPC„29ŠSF…ICCENABL(A1)‰CleartheInterruptsEnabledflaginthe-*£ICCTentrytoindicatethatinterruptswere-*£disabledattherequestoftheowningtask.ŠSPC„2;ŠMOVE.BICCNUM(A1),D3ˆLoadthechannelnumberfromtheICCT5ŠBSR„DBCANCLŒentryforthechanneltobedisabledand(*£callDBCANCLtodisableinterruptsand,*£toterminateanypendingsoftwaredebounce)*£activityonthechannel.Notethatthis+*£subroutineexecutesinGuardedModesince)*£itiscalledfromaguardedsubroutine.ŠSPC„2CGDS020„LEA.L‚ICCENTLN(A1),A1†UpdatetheindextotheICCTentryfor3ŠTST.B‚D6‘thenexthighernumberedchannelandloop2ŠBNE„GDS010untilallrequestedchannelshavebeen *£processed.ŠSPC„2&ŠRTS™Returntothenon-guardedDisable(*£InterruptsCommandprocessingroutine.ŠPAGEO********************************************************************************>*‰ReadCurrentInputChannelStatusCommandProcessingRoutine>*‰------------------------------------------------------------*H*ƒThisroutinereadsthecurrentstatusofalleightinputchannelsofaL* VME 610/620 module and returns the results to the user in the Channel MaskI* field of the Input Command Parameter Block. All bits that correspond toG* channels specified in the channels mask are returned as read from the1* hardware and all other bits are forced to zero.*>*‰Entryregisters:‚A4=InputCommandParameterBlockaddress*œA5=CCBaddress*D*‰Registerusage‚:‚D0=VME610/620ChannelStatusregistercontents)*œA0=Memory-mappedchannelbaseaddress*?*‰Exitregisters‚:‚D1=CommandStatusCode(zerofornoerror)-*œAllentryregistersorunusedregistersare *preserved.*O*******************************************************************************ŠPAGEBSTATUS„MOVE.LCCBCHB(A5),A0ˆLoadthememory-mappedbaseaddressof*£theinputmodulehardware.ŠSPC„2=ŠMOVE.BINPCSTAT(A0),D0†Readthecurrentinputchannelstatus  ,*£fromthehardwareChannelStatusregister.ŠSPC„2>ŠAND.B‚D0,CMDCHM+1(A4)†Andthecurrentchannelstatusintothe(*£channelsmaskinthecommandparameter)*£blocktoclearstatusbitsforchannels*£thatwerenotrequested.ŠSPC„25ŠMOVE.L#0,D1ReturntotheCommonCommandProcessing*ŠRTS—routinewithano-errorstatusinD1.ŠPAGEO********************************************************************************>*‰Enable/DisableInterruptsChannelMaskValidationSubroutine>*‰------------------------------------------------------------*J*„ThisroutinechecksthechannelsmaskspecifiedforanEnableorDisableI* Interrupts Command to make sure that none of the non-interrupt channelsN* are specified. If any such channels are specified an error exit is made withL* an error code in D1. The routine then loads the memory-mapped channel baseK* address and the Interrupt Channel Control Table base address and returns.*>*Entryregisters:A4=InputCommandParameterBlockaddress*¢A5=CCBaddress*!*Exitregisters‚:D0=destroyed*¢D1=CommandStatusCode)*¢D6=Maskofchannelstoenable/disable)*¢D7=Maskofchannelstoenable/disable)*¢A0=Memory-mappedchannelbaseaddress*¢A1=ICCTbaseaddress*$*¢Allotherregistersarepreserved.*O*******************************************************************************ŠPAGEDEIDICHKƒMOVE.BCMDCHM+1(A4),D7†LoadthechannelsmaskfromtheInput6ŠMOVE.BD7,D6ŽCommandParameterBlockintoD7andmake*£acopyinD6ŠSPC„26ŠMOVE.L#INPICHN,D1ŠIfthechannelsmaskspecifiesany>ŠMOVE.B#%11110000,D0†non-interruptchannels(4-7)exittothe6ŠAND.B‚D7,D0ŽcommoncommandhandlerwithanerrorcodeŠBNE.L‚CMDERRinD1.ŠSPC„29ŠMOVE.LCCBCHB(A5),A0ˆLoadthememory-mappedchannelbaseAŠLEA.L‚CCBICCT(A5),A1…addressintoA0andthebaseaddressofthe**£InterruptChannelControlTableintoA1.ŠSPC„22ŠMOVE.L#0,D1ReturntothecallingroutinewithaŠRTS—noerrorstatusinD1.ŠPAGEO********************************************************************************-*InterruptDisableandDebounceCancellation*œGuardedSubroutine-*-------------------------------------------*H*ƒThissubroutineisexecutedbyRMS68KinGuardedMode.GuardedModeisL* used when operations are to be performed (i.e. modification of shared dataI* structures) that are sensitive to "concurrent" background activity as aD* result of an interrupt. While the guarded subroutine executes, newL* background processes may be scheduled but their execution is held pending.*I*ƒWithintheenvironmentofthisdriver,GuardedModeblocksexecutionofL* the Background Interrupt Handler, Background Debounce Timeout Handler, andH* the Background Channel Shutdown Handler. Since this subroutine affectsI* several data structures that are accessed by these background routines,F* the guarded subroutine guarantees mutual exclusion without requiring+* interrupts to be masked at the processor.*H*ƒThefunctionofthisroutineistodisableinterruptsontheinterruptD* channel specified in D3 on entry and to terminate pending debounce$* operations on the channel, if any.*:*EntryRegisters:D3=Numberofinterruptchanneltobe *§processed.)*¢A0=Memory-mappedchannelbaseaddress*¢A1=ICCTentryaddress*¢A5=CCBaddress*)*RegisterUsage‚:D0-D2=Workregisters*3*Exitregisters‚:Allregisterspreservedonexit.*O*******************************************************************************ŠPAGEDDBCANCLƒMOVEM.LD0-D2/A0,-(A7)†Saveallregistersusedonthestack.ŠSPC„20ŠBCLRƒD3,CCBINTCR(A5)DisableinterruptsfortheDŠMOVE.BCCBINTCR(A5),INPICNTR(A0)specifiedchannelintheInterrupt!*ªControlRegisterimageandmove%*ªtheimagetothehardwareregister.ŠSPC„2;ŠTST.B‚ICCDBACT(A1)‰Ifnosoftwaredebounceoperationisin2ŠBEQ„DBC010processonthespecifiedchannel,exit*£fromthesubroutine.ŠSPC„29ŠCLR.B‚ICCDBACT(A1)‰CleartheDebounceAct  iveflaginthe,*£ICCTentrysothattheBackgroundDebounce-*£TimeoutHandlerwillknowthatthedebounce*£operationwascanceled.ŠSPC„2CANRQPAƒEQU„$8000:ŠMOVE.W#CANRQPA,D1ŠLoadtheoptiontocancelapreviously5ŠMOVE.LA1,D2Žrequestedexecutiveperiodicactivation+*£andspecifytheActivationIDastheICCT*£entryaddress.ŠSPC„26ŠMOVE.LCCBRQPA(A5),A0‡Attempttocanceltherequested4ŠJSR„(A0)activationoftheInterruptLevelDebounce-ŠNOP—TimeoutHandler.Ifanerroroccurs,the)*£activationhasalreadyoccurredandthe(*£BackgroundDebounceTimeoutHandleris)*£scheduledtoexecuteassoonascommand)*£processingexitsGuardedMode.However,'*£thebackgroundroutinewillterminate)*£whenitseesthattheBackgroundActive*£flaghasbeenclearedŠSPC„2DDBC010„MOVEM.L(A7)+,D0-D2/A0†RestoretheentryregistersandreturnŠRTS—tothecallingroutine.ŠPAGEO********************************************************************************«”6¥!­5µ/½'Å,Í/Õ2Ý,å7í/õ0ý21 !/1%-&54=,E1M2U*] *šBackgroundInterruptHandler*š----------------------------*G*ƒThisroutineiscalledbytheRMS68KBackgroundProcessDispatcheratO* processor interrupt mask level zero after it has been scheduled for executionG* by the Foreground Interrupt Handler. The Foreground Interrupt HandlerN* attempts to schedule this routine after each interrupt event has been placedM* in the Interrupt Processing Queue. However, if multiple scheduling requestsF* are made using the same Background Activation Block (BAB) before theN* background process has been dispatched, the process will be scheduled on the* first request only.*L*ƒUponentrytothisroutine,A1containstheaddressoftheactivatingBAB.F* The contents of all other address and data registers, except A7, areJ* considered to be undefined. Since the activating BAB is contained in theO* Interrupt Queue Control Table, the base address of the table is easily found.:* The routine then enters the queue entry processing loop.*H*ƒWefirstcheckforanemptyqueuebytestingforequalityofthequeueN* input and output offsets. This check is made with a single instruction so itI* is not vulnerable to an interrupt that would cause the output offset toM* change. This empty queue check must be performed the first time through theG* loop since it is possible for this background routine to be activatedM* when the queue is empty. This condition occurs if the background process isK* in execution and an interrupt occurs that places a new interrupt entry inM* the queue. The new interrupt causes the background routine to scheduled forM* execution even though it is already executing. Since the current invocationO* of the process will empty the queue before terminating, the second invocationO* will start execution with no queue entries to process. This is an unavoidableL* side effect of assuring that whenever at least one interrupt entry exists,N* the Background Interrupt Handler is either already executing or is scheduledL* for execution so that interrupt entry processing is guaranteed before task* level execution can resume.*J*ƒWhentheinterruptqueueisnon-empty,theoldestentry(asindicatedbyM* the queue output offset) is retrieved and processed. The entry contains theK* CCB address of the VME 610/620 module that interrupted, a bit mask of theI* interrupting input channels, and the contents of the RMS68K Time-of-DayK* clock at the time of the interrupt. The queue output offset is updated to%* access the next oldest queue entry.*L*ƒTheinterruptingchannelsmask,obtainedfromthequeueentry,arecheckedJ* in order of decreasing channel number. For each channel with a interruptO* the corresponding Interrupt Channel Control Table entry in the C  CB is checked5* to determine how the interrupt should be processed.*E*ƒIftheinterruptingchannelisnotsoftwaredebounced,animmediateM* interrupt notification is made to the owning task via either Queue Event orL* Wakeup as specified in the channel configuration word when the channel was * opened.ŠPAGEJ*ƒForasoftwaredebouncechannel,interruptsforthechannelhavealreadyM* been disabled on the VME 610/620 board by the Foreground Interrupt Handler.K* A debounce timeout interval is determined from the elapsed time since theL* occurrance of the interrupt and the user specified debounce period. If theJ* specified debounce period has not already passed, the Interrupt DebounceL* Timeout Handler is scheduled for execution at the appropriate time. If theO* specified debounce period has already expired, the routine clears any pendingE* interrupts on the channel, enables interrupts, and issues interrupt"* notification to the owning task.*M*ƒWhenalloftheinterruptingchannelsmaskbitsobtainedfromtheinterruptL* queue entry have been processed, the next entry is obtained from the queueM* and the process is repeated. When there are no more entries in the queue toJ* process, the Background Interrupt Handler terminates by returning to the'* RMS68K Background Process Dispatcher.*;*Entryregisters:‚A1=AddressofInterruptQueueControl *¨TableBAB*6*RegisterUsage‚:‚D1=ChannelNumberBeingProcessed$*£D3=InputModuleChannelMnemonic!*£D4=InterruptQueueEntryTime$*£D7=MaskofInterruptingChannels*£A2=CCBaddress*£A3=ICCTentryaddress,*£A6=InterruptQueueControlTableAddress*:*Exitregisters‚:‚Allregistersaresaved/restoredbythe&*£RMS68KBackgroundProcessDispatcher*O*******************************************************************************ŠPAGE DBACKGRND‚LEA.L‚-QBAB(A1),A6‰LoadtheInterruptControlTableAddress*£intoanaddressregister.ŠSPC„2L*ƒCheckforanemptyinterruptqueuebycomparingthequeueinputandoutputI*offsets.‚Thischeckisperformedviaamemory-to-memorycomparesothat * interrupts need not be masked. EBCK000„LEA.L‚QINOFST(A6),A0‡Ifthequeueinputandoutputoffsetsare<ŠCMP.W‚(A0)+,(A0)+ˆnotequal,thereisatleastoneentryin7ŠBNE„BCK005thequeuesoproceedtotheinterruptqueue,ŠRTS—entryprocessingloop.Iftheinputand(*£outputoffsetsareequal,thequeueis+*£emptysotheBackgroundInterruptHandler**£returnscontroltotheRMS68KBackground*£ProcessDispatcher.ŠSPC„21*‚Readtheoldestentryfromtheinterruptqueue. BBCK005„MOVE.WQOUTOFST(A6),D0†Loadthequeueoutputoffsetandthe9ŠMOVE.LQPTR(A6),A0ˆqueuebaseaddressfromtheInterrupt*£QueueControlTable.ŠSPC„2?ŠMOVEM.L0(A0,D0.W),D4/D7/A2‚Pulltheentryfromthequeueinto*£workingregistersasfollows:**¦A2=CCBaddressofinterruptingchannel(*¦D4=Timeofinterruptoccurrance(mS)#*«(D4isusedsothatbytes8-11of!*¬aninterruptnotificationevent*¬arepre-stagedintheproper$*¬registerwhenEXQEVNTIiscalled.)$*¦D7=MaskofInterruptingChannels%*«(Onlybits0-4ofD7containvalid!*­data.Itisplacedinthequeue *­asalongwordsothataMOVEM*­instructioncanbeusedto *­minimizequeuinganddequeuing*­time.)ŠSPC„2;ŠADD.W‚#IQENTLN,D0ŠUpdatethequeueoutputoffsettoaccess>ŠAND.W‚QWAMSK(A6),D0†thenextoldestqueueentrybyaddingthe?ŠMOVE.WD0,QOUTOFST(A6)„queueentrylengthandforcewraparound,*£fromtheendofthequeuetothebeginning+*£ifnecessary.Sincethelength,inbytes,+*£ofboththeinterruptqueueandthequeue,*£entryarepowersoftwo,wraparoundtothe(*£beginningofthequeueisperformedby,*£logicallyANDingthequeuelength-1with*£thequeueoutputoffset.ŠPAGE=ŠMOVE.LCCBMNEM(A2),D3‡Loadtheinputmodulechannelmnemonic)*£intoD3incaseaQueueEventinterrupt**£notificationmustbesenttoatask.The (*£channelmnemonicoccupiesbytes4-7of)*£theinterruptnotificationevent.Since**£D3mustcontaineventbytes4-7onentry)*£totheEXQEVNTIroutine,thelasteight**£bytesofaninterruptnotificationevent*£arepre-stagedinD3andD4.ŠSPC„2J*‚StartprocessingoftheinterrupingchannelsmaskbitsobtainedfromtheN* interrupt queue entry. The channels will be processed in order of decreasing)* channel number starting with channel 3. =ŠLEA.L‚CCBICCTE+1(A2),A3„Loadtheendaddressplusoneofthe9ŠMOVE.L#3,D1ŽInterruptQueueControlTableandthefirst!*£channelnumbertobeprocessed.ŠSPC„2FBCK010„LEA.L‚-ICCENTLN(A3),A3…UpdatetheICCTentryindextoreference'*£theentryforthenextlowernumbered *£channel.ŠSPC„21ŠBCLRƒD1,D7Testandclearthestatusbitforthe6ŠBEQ.L‚BCK050currentchannel.Ifthestatuswaszero,)*£nointerruptoccurredsoproceedtothe*£nextchannel.ŠSPC„2I*ƒSincetheinterruptstatusbitforthecurrentchannelisset,thereisK* an interrupt to process. In the event that the interrupt occurred and wasK* queued while a Close Channels or Disable Interrupts command was executingK* in Guarded Mode (i.e. background processing was blocked), the channel forH* which the interrupt was queued may already be closed or interrupts mayM* already be disabled when the Background Interrupt Handler begins execution.L* Therefore, before proceeding with interrupt processing, it is necessary toG* assure that the channel is currently open and interrupts are enabled.K* Otherwise it would be possible for one or more interrupt notifications toO* be sent to a task AFTER a Close or Disable Interrupts command for the channel!* had been sucessfully completed. 9ŠTST.L‚ICCTCB(A3)‹IftheTCBaddressofthechannelowner6ŠBEQ„BCK050intheICCTentryiszero,thechannelhas'*£beenclosedsodiscardtheinterrupt.ŠSPC„2;ŠTST.B‚ICCENABL(A3)‰Ifinterruptshavebeendisabledonthe+ŠBEQ„BCK050channel,discardtheinterrupt.ŠSPC„2 6ŠMOVE.L#0,D6Iftheuserspecifieddebounceperiodis?ŠMOVE.WICCDBINT(A3),D6„zero,thechannelisnottobesoftware1ŠBEQ„BCK040debouncedsoproceedtotheinterrupt*£notificationstep.ŠPAGEM*ƒAninterrupthasbeenreceivedonachannelthatisconfiguredforsoftwareL* debounce. Since the user specified debounce period is to be timed from theO* occurrance of the interrupt, the time that has elapsed since the occurrance oK* the interrupt is calculated to determine if the debounce period should beJ* shortened or if the required debounce period has already expired. In theO* latter case, the interrupt is processed immediately. Otherwise, processing ofG* the interrupt is deferred until required debounce period has expired. K*ƒThelineofcode‚'MOVE.LTIMEOD,D5'‚hadtobereplacedbecausetheTIMEODL* parameter has been eliminated in the new Periodic Activation mechanism forN*VERSAdos4.4.‚AcallisnowmadetotheRMS68KRDTIMERroutinetoobtainthe* current time-of-day. ;ŠMOVEM.LD0-D1/A0,-(A7)„SavetheregistersusedbyRDTIMER.;ŠMOVE.LCCBRDTIM(A2),A0„GettheRMS68KaddressforRDTIMER,0ŠJSR„(A0)andgoobtainthecurrenttime-of-day.*(*ƒTheregistersreturnedbyRDTIMERare:%*…D0.L=timercontents(notneeded).G*…D1.L=time-of-dayexpressedinmillisecondssincemidnight(TIMEOD).*4ŠMOVE.LD1,D5ŽSavetime-of-dayasperoriginalcode.:ŠMOVEM.L(A7)+,D0-D1/A0„RestoreregistersusedbyRDTIMER.*>*ƒEndofreplacementcodefor‚'MOVE.LTIMEOD,D5'‚***10/25/84.*1ŠSUB.L‚D4,D5ŽCalculatetheelapsedtimesincethe6ŠBPL„BCK030occurranceoftheinterruptbyreadingthe)*£currentvalueoftheRMS68Ktime-of-day**£clockandsubtractingtheinterrupttime)*£thatwasobtainedfromthequeueentry.-*£Iftheresultispositive,thereisnoneed)*£toadjustformidnightcrossoverofthe*£time-of-dayclock.ŠSPC„2>MSPERDAY‚EQU„24*60*60*1000ˆIftheinterruptoccursjustbefore?ŠADD.L‚#MSPERDAY,D5‡midnightandpro cessingoftheinterruptis(*£delayeduntiljustaftermidnight,the**£interrupttimevaluewillbelargerthan,*£thetime-of-dayclockvaluesotheelapsed(*£timecalculationwillyieldanegative%*£result.Thecorrectelapsedtimeis(*£obtainedbyaddingthetotalnumberof*£millisecondsinaday.ŠSPC„27BCK030„SUB.W‚D5,D6Subtractthecalculatedelapsedtime1ŠBGT„BCK035fromtherequesteddebounceperiodto&*£obtaintheadjusteddebounceperiod.,*£Iftheadjusteddebounceperiodisgreater)*£thanzero,setupforadebouncetimeout&*£interruptattheendoftheadjusted(*£period.Notethata16-bitsubtractis+*£permissableherebecauseitisimpossible**£fortheelapsedtimesincetheinterrupt)*£occurredtoexceed32,767milliseconds.ŠPAGEL*ƒControlreachesherewhentheadjusteddebounceperiodiszeroornegativeM* meaning that the requested debounce period has expired. Any such interruptsM* are processed in the same way as those that are processed by the BackgroundL* Debounce Timeout Handler. First, any pending interrupts on the channel areO* cleared, channel interrupts are enabled, and the current state of the channelK* (Energized/Deenergized) is checked for consistency with the channel stateN* transition that caused the interrupt. If the current state of the channel isL* inconsistent, the interrupt is assumed to be spurious and is discarded. IfK* the current state is consistent, an interrupt notification is sent to the* task that owns the channel. =ŠMOVE.LCCBCHB(A2),A0ˆLoadthememory-mappedI/Obaseaddress!*£ofthe610/620modulehardware.ŠSPC„2;ŠBCLRƒD1,CCBIQENA(A2)†Disablequeueingofnewinterruptson)*£thechannelbytheForegroundInterrupt *£Handler.ŠSPC„29ŠBSETƒD1,CCBINTCR(A2)ŒEnableinterruptsonthechannelatBŠMOVE.BCCBINTCR(A2),INPICNTR(A0)the610/620modulehardware.Any(ŠNOPžpendinginterruptwilloccurandbe(ŠNOPždiscardedbecauseinterruptqueuing&ŠNOPžhasbeendisabledonthechannel."*ªTheNOP'sallowtimefortheI/O&*ªchannelinterrupthardwaretoacton*ªtheinterrupt.ŠSPC„2:ŠBSETƒD1,CCBIQENA(A2)†Enablequeueingofinterruptsonthe,*£channelnowthatanypendinginterrupthas*£beencleared.ŠSPC„28ŠMOVE.BINPCSTAT(A0),D0†IfthecurrentchannelstatusisAŠMOVE.BICCEDGE(A3),D2…inconsistentwiththeinterruptgenerating7ŠEOR.B‚D2,D0Žtransition,discardtheinterruptassuming4ŠBTSTƒD1,D0Žittobespuriousandproceedtoprocess0ŠBNE„BCK050thenextlowernumberedchannel.The-*£interruptgenerating'edge'flagmeaningis**£describedintheICCTequates.Sincethe(*£currentchannelstatusisaoneifthe$*£channelisenergizedandazeroif-*£deenergized,anexclusiveORofthechannel-*£statusbitandthecorrespondingbitinthe,*£'edge'flagalwaysyieldseitherzerowhen**£theinterruptisvalidoraonewhenthe*£interruptisspurious.ŠSPC„23ŠBRA„BCK040Sincethecurrentstatusofthechannel-*£isconsistentwiththeinterruptgenerating-*£transition,issueaninterruptnotification*£totheowningtask.ŠPAGEI*‚Whentheadjusteddebounceperiodisgreaterthanzero,wemustissueaJ* request to RMS68K for a 'timer interrupt' at the end of the period. ThisO* 'timer interrupt' causes execution of the Interrupt Debounce Timeout Handler.E* The RMS68K routine EXRQPA is called to setup the 'timer interrupt'. ?BCK035„ST…ICCDBACT(A3)‰SetaflagintheICCTentrytoindicate,*£thatdebounceoperationsareactiveonthe *£channel.ŠSPC„2@ŠMOVE.LD4,ICCDBST(A3)‡Savethetimeofinterruptocurrancefrom-*£theinterruptqueueentryintothedebounce,*£periodstarttimefieldoftheICCTentry.ŠSPC„2M*ƒSetuptheregistersnecessaryfortheEXRQPAroutinetoscheduleactivationO* of the Interrupt Debounce Timeout Handler at the end of the adjusted debounce* timeout period. 1ŠMOVE.WD1,-(A7)SaveD1onthestacksinceitis"*£destroyedbythecalltoEXRQPA.ŠSPC„2?ŠMOVE.BCCBPPRIO(A2),D1†Se tthetimeoutroutinetoexecuteata-*£processorinterruptmasklevelthatmatches-*£thehardwareinterruptlevelofthechannel*£beingdebounced.ŠSPC„25ŠMOVE.LA3,D2SettheActivationIDtotheICCTentry*£addressforthechannel.ŠSPC„20ŠMOVE.LD6,A1SettheActivationIntervaltothe*£adjusteddebounceperiod.ŠSPC„2:ŠLEA.L‚DBTIMOUT(PC),A0†Loadtheentrypointaddressofthe?ŠMOVE.LCCBRQPA(A2),A4…InterruptDebounceTimeoutHandler.Load/ŠJSR„(A4)theentrypointaddressoftheEXRQPA7ŠBRA.S‚BCK037routinefromtheCCBandcalltheroutine *£viaaJSR.ŠSPC„25RQPAERRƒNOP™Thiserrorreturnshouldneverbereached**£undernormaloperatingconditions.Ifan'*£errordoesoccurforsomereason,the(*£channelwill'lockup'untilaCloseor,*£aDisableInterruptscommandisissuedfor*£thechannel.ŠSPC„2>BCK037„MOVE.W(A7)+,D1RestoreD1andproceedtoprocessingofŠBRA„BCK050thenextchannel.ŠPAGEL*ƒControlreachesherewhenaninterruptnotificationistobeissuedtotheJ* owner of the channel. The Interrupt Notification subroutine is called toH* issue either a Wakeup or a Queue Event to the task as specified in the9* channel configuration word when the channel was opened. :BCK040„MOVE.L#0,D2Issueaninterruptnotificationtothe7ŠBSR„NOTFYINT‹owningtask.Ifaneventistobesentto+*£thetask,settheeventstatustozeroto*£indicate'noerror'.ŠSPC„2J*ƒInterruptprocessingforthecurrentchanneliscompleted,soproceedtoL* process the next lower numbered channel. If all interrupting channels fromG* the interrupt queue entry have been processed, return to the start ofH* the interrupt queue entry processing loop to obtain a new queue entry. 7BCK050„TST.B‚D7“Loopuntilallinterruptingchannelsin1ŠDBEQƒD1,BCK010Šthecurrentqueueentryhavebeen *£processed.ŠSPC„22ŠBRA.L‚BCK000Returntothestartoftheinterrupt-*£queueentryprocessinglooptoobtainanew*£queueentry.ŠPAGEO********************************************************************************#*“InterruptNotificationSubroutine#*“---------------------------------K*ƒThissubroutineiscalledwhenaninterruptnotificationistobesenttoL* the owner of a particular channel. The TCB address of the channel owner isI*obtainedfromtheICCTentry.‚ThenotificationmodeisspecifiedbytheO* owning task to be either a Wakeup of the task or an event queued to the task.*C*ƒIfaneventistobesent,theformatoftheeventisasfollows:* *˜Eventlength(12bytes)(byte)*˜EventCode($01)”(byte)*˜EventStatus˜(byte)**˜InterruptingInputChannelNumberƒ(byte)(*˜Mnemonicof610/620modulethat…(long)#*šcontainstheinterruptingchannel$*˜TimeofInterruptOccurance‰(long)*K* The twelve data bytes of the event must be in registers D2, D3, and D4 onI* entry the RMS68K EXQEVNTI routine. D3 and D4 are already setup with theL* proper data on entry to this subroutine, so the only register that must beI*setupisD2.‚Alloftheentryregisterstothisroutine,exceptD2,areG* preserved when the subroutine exits. All other registers are probably-* probably destroyed by the EXQEVNTI routine.*K*ƒIfaWakeupisissuedtothetask,allentryregistersarepreservedwhen* the subroutine exits.*?*ƒAlternateentrypoints:NOTQEVNT-Queueaneventtothetask'*›NOTWAKUP-IssueaWakeuptothetask*9*EntryRegisters:D1.W=Numberofinterruptingchannel*¢D2ƒ=Interrupteventstatus$*¢D3ƒ=InputModuleChannelMnemonic#*¢D4ƒ=Timeofinterruptoccurrance&*¢D7.W=Maskofinterruptingchannels*¢A2ƒ=CCBaddress*¢A3ƒ=ICCTentryaddress*7*Exitregisters‚:D1.W,D3,D4,D7.W,A2,A3,A6,andA7are-*¢preserved.Allotherregistersareprobably *¢destroyed.*O*******************************************************************************ŠPAGE?NOTFYINT‚TST.B‚ICCQEVNT(A3)‰Ifnoeventistobequeuedforthe6ŠBEQ„N OTWAKUP‹interrupt,branchtotheWakeuproutine.ŠSPC„2"* Interrupt Notification via Event :NOTQEVNT‚MOVE.LA3,-(A7)Saveentryregistersthatwillbe8ŠMOVE.WD1,-(A7)‹destroyedbythecalltoEXQEVNT.Since8ŠMOVE.WD7,-(A7)‹vitaldataiscontainedonlyinthelow-*£orderwordsofthedataregisters,thehigh+*£orderwordofeachregisterisallowedto*£bedestroyedbyEXQEVNT.ŠSPC„2?ŠMOVE.LICCTCB(A3),A0ˆLoadtheTCBaddressofthechannelowner*£fromtheICCTentry.ŠSPC„2:EVNTHDRƒEQU„$0C010000ŒThisequatedefinestheeventlength&*£(12bytes)andtheeventcode($01).ŠSPC„21ŠLSL.W‚#8,D2Loadtheeventcodeandeventlength6ŠOR.BƒD1,D2ŽheaderintotheupperwordofD2.Loadthe;ŠOR.Lƒ#EVNTHDR,D2ˆeventstatusandtheinterruptingchannel#*£numberintothelowerwordofD2.ŠSPC„2;ŠMOVE.LCCBQEVNT(A2),A4†Loadtheentrypointaddressofthe2ŠJSR„(A4)RMS68KEXQEVNTIroutinefromtheCCBand'ŠBRA„NOT010calltheroutineviaaJSR.ŠSPC„25NOTQUERƒNOP™Thiserrorreturnshouldonlybeexecuted *£inoneofthefollowingcases:**¨Taskdoesnotexist*¨TaskhasnoASQallocated*¨ThetasksASQisdisabled*¨ThetasksASQisfull+*£Sincethereisnosingleactionthatwill)*£adequatelycoverallofthesecasesand+*£thecasescannotbedifferentiatedwitha)*£singleerrorreturn,thereisnochoice-*£otherthanignoringtheerror.Notethatif+*£owningtasknolongerexists,thereisno-*£wayforanothertasktotakeoveruseofthe *£channel.ŠSPC„2@NOT010„MOVE.W(A7)+,D7Restorethevaluesoftheentryregisters8ŠMOVE.W(A7)+,D1‹thatweredestroyed.Onlytheloworder:ŠMOVE.L(A7)+,A3‹wordsofthedataregistersarerestored.ŠSPC„2#ŠRTS™Returntothecallingroutine.ŠPAGE#* Interrupt Notification via Wakeup ANOTWAKUP‚MOVE.LICCTCB(A3),A0ˆLoadtheTCBaddressofthechannel*£ownerfromtheICCTentry.ŠSPC„2;ŠMOVE.LCCBWAKUP(A2),A4†Loadtheentrypointaddressofthe0ŠJSR„(A4)EXWAKEUProutinefromtheCCBandcall!ŠBRA„NOT020theroutineviaaJSRŠSPC„22NOTWAKER‚NOP™Theonlytimethiserrorroutinewill&*£everbeusediswhentheowningtask(*£nolongerexists.Aswasmentionedfor-*£queueeventnotification,ifthiscondition**£occursthechannelbecomesinaccessable.ŠSPC„2)NOT020„RTS™Returntothecallingroutine.ŠPAGEO********************************************************************************$*”InterruptDebounceTimeoutHandler$*”----------------------------------*K*ƒThisroutineexecutesasaresultoftheEXRQPArequestmadetoRMS68KbyL* the Background Interrupt Handler for a 'timer interrupt' at the end of theM* adjusted debounce period. On entry to this routine, the processor interruptJ* mask is set to the hardware interrupt level of the input channel that isM* being debounced. Since there is no need to perform the remaining processingN* for the channel with interrupts masked, this routine schedules activation ofM* the Background Debounce Timeout Handler to perform the remaining processingI* at processor interrupt mask level zero. After scheduling the background4* routine this routine returns to RMS68K via an RTE.*<*Entryregisters:‚D0=Numberofactivationintervalsthat"*¨havepassedsinceactivationwas%*¨scheduled.(Thisinformationisnot*¨usedinthisroutine.)+*£D1=AddressofInterruptChannelControl'*¨TableentryBABforthechannelbeing *¨debounced.*>*ExitRegisters‚:‚AllregisterspreservedbytheRMS68Ktimer*£interrupthandler.*O*******************************************************************************ŠPAGE?DBTIMOUT‚MOVE.LD1,A0LoadtheICCTentryBackgroundActivation**£BlockaddressintoA0.ThisBABcontains+*£theentrypointaddressoftheBackground*£DebounceTimeoutHandler.ŠSPC„2;ŠMOVE.LICCBKGST(A0),A1†Loadtheentrypointaddressofthe2ŠJSR„(A1)RMS68KBackgroundProcessSchedulerfrom)*£theICCTentryandcalltheroutinevia*£aJSR.ŠSPC„2.ŠRTE™Ret urntoRMS68Ktimerinterrupthandler.ŠPAGEO********************************************************************************%*”BackgroundDebounceTimeoutHandler%*”-----------------------------------*J*ƒThisroutineperformspost-debounceprocessingofinterruptsonsoftwareJ* debounced input channels. It executes as an RMS68K background process atI* processor interrupt mask level 0 after being scheduled by the Interrupt* Debounce Timeout Handler.*M*‚Thefunctionofthisroutineistoclearpendinginterruptsonthechannel,N* enable interrupts on the channel, and issue an interrupt notification to theN* owning task if the current state of the input channel is consistent with theO* channel state transition that generated the initial interrupt. If the currentG* state is inconsistent, the interrupt is assumed to be spurious and isH* discarded. After processing is completed on the debounced channel, the>* routine returns to the RMS68K Background Process Dispatcher.*=*EntryRegisters‚:A1=AddressoftheICCTentryBackground(*¨ActivationBlockforthechannelbeing$*¨debounced.Thisisthesameasthe*¨ICCTentrybaseaddress.*6*Registerusageƒ:D1=Channelnumberbeingprocessed$*£D3=InputModuleChannelmnemonic)*£D4=Timeofinterruptthatstartedthe*¨debounceoperation.*£A2=CCBaddress*£A3=ICCTentryaddress*=*Exitregistersƒ:Allregisterssaved/restoredbytheRMS68K&*£BackgroundProcessDispatchroutine.*O*******************************************************************************ŠPAGE8DBTOBKGƒMOVE.LA1,A3SavetheICCTentrybaseaddressin&*£theaddressregisterrequiredbythe*£NOTFYINTsubroutine.ŠSPC„2M*ƒIntheeventthatthisbackgroundroutinewasscheduledforexecutionwhileN* a Close Channels or Disable Interrupts command was executing in Guarded ModeJ* (i.e. background processing was blocked), the channel for which debounceK* processing was to be completed may have already been closed or interruptsJ* may have been disabled prior to execution of this routine. Therefore, itM* is necessary to assure that the channel is currently open and that debounceL* processing on the channel is still active. Otherwise, it would be possibleM* for an interrupt notification to be sent to a task AFTER a Close or DisableE* Interrupts command for the channel had been successfully completed. 7ŠTST.L‚ICCTCB(A3)‹IftheownersTCBaddressintheICCT6ŠBEQ„DBTRTNentryiszero,thechannelhasbeenclosed*£sodiscardtheinterrupt.ŠSPC„2:ŠTST.B‚ICCDBACT(A3)‰Ifthedebouncecyclewascanceledvia5ŠBEQ„DBTRTNaDisableInterruptscommand,discardthe *£interrupt.ŠSPC„29ŠCLR.B‚ICCDBACT(A3)‰Clearthedebounceactiveflaginthe *£ICCTentry.ŠSPC„2=ŠMOVE.LICCB(A3),A2ŠLoadtheCCBaddressforthechannelfrom*£theICCTentry.ŠSPC„2=ŠMOVE.LCCBCHB(A2),A0ˆLoadtheinputmodulememory-mappedI/O*£baseaddress.ŠSPC„2:ŠMOVE.BICCNUM(A3),D1ˆLoadthenumberofthechannelbeing *£processedfromtheICCTentry.ŠSPC„2:ŠBCLRƒD1,CCBIQENA(A2)†Disablequeuingofinterruptsonthe%*£channelbytheForegroundInterrupt *£Handler.ŠSPC„26ŠBSETƒD1,CCBINTCR(A2)EnableinterruptsonthechannelEŠMOVE.BCCBINTCR(A2),INPICNTR(A0)atthe610/620modulehardware.Any(ŠNOPžpendinginterruptwilloccurandbe(ŠNOPždiscardedbecauseinterruptqueuing&ŠNOPžhasbeendisabledonthechannel.!*ªTheNOPsallowtimefortheI/O#*ªChannelinterrupthardwaretoact*ªontheinterrupt.ŠPAGE9ŠBSETƒD1,CCBIQENA(A2)†Enablequeuingofinterruptsonthe,*£channelnowthatanypendinginterrupthas*£beencleared.ŠSPC„28ŠMOVE.BINPCSTAT(A0),D0†IfthecurrentchannelstatusisAŠMOVE.BICCEDGE(A3),D2…inconsistentwiththeinterruptgenerating7ŠEOR.B‚D2,D0Žtransition,discardtheinterruptassuming4ŠBTSTƒD1,D0Žittobespuriousandproceedtoprocess0ŠBNE„DBTRTNthenextlowernumberedchannel.The-*£interruptgenerating'edge'flagmeaningis **£describedintheICCTequates.Sincethe(*£currentchannelstatusisaoneifthe$*£channelisenergizedandazeroif-*£deenergized,anexclusiveORofthechannel-*£statusbitandthecorrespondingbitinthe,*£'edge'flagalwaysyieldseitherzerowhen**£theinterruptisvalidoraonewhenthe*£interruptisspurious.ŠSPC„2=ŠMOVE.LCCBMNEM(A2),D3‡Loadtheinputmodulechannelmnemonic?ŠMOVE.LICCDBST(A3),D4…fromtheCCBandthetimeoftheinitial(*£interruptfromthedebouncestarttime+*£fieldoftheICCTentry.Thesevaluesare)*£loadedtopreparetoissueaninterrupt"*£notificationeventifnecessary.ŠSPC„24ŠMOVE.L#0,D2Issueaninterruptnotificationtothe7ŠBSR„NOTFYINT‹owningtask.Ifaneventistobesentto**£thetasksettheeventstatustozeroto*£indicate'noerror'.ŠSPC„22DBTRTN„RTS™ReturntotheRMS68KBackgroundProcess *£Dispatcher.ŠPAGEO********************************************************************************%*BackgroundChannelShutdownHandler%*-----------------------------------*F*ƒThisbackgroundroutineisscheduledforexecutionbytheForegroundI* Interrupt Handler when an incoming interrupt could not be placed in theL* Interrupt Processing Queue because the queue was full. When this conditionK* occurs, the Foreground Interrupt Handler disables interrupts on the inputK* channels that could not be processed and sets a mask of shutdown channelsK* in the CCB so that this routine can issue a Channel Shutdown NotificationL* to the owners of the affected channels. A Channel Shutdown Notification isL* an event that is sent to the owning tasks ASQ. The format of this event isL* the same as that for an Interrupt Notification Event except that the eventI* status is $FF and the time of interrupt occurrance is always zero. ThisN* special event informs the owning task that interrupt queue overflow occurredK* resulting in the loss of one or more interrupts on the channel. The eventN* also informs the task that the driver has disabled interrupts on the channel*J*ƒWhentheinterruptnotificationmethodforachannelisviaaWakeup,noM* Shutdown Notification is sent since a Wakeup sent as a result of a shutdownO* is indistinguishable from one sent as a result of an interrupt. If a shutdownF* occurs for a Wakeup channel, the task owning the channel will become?* permanently locked-up when it issues the next Wait directive.*H*ƒSincethisbackgroundroutineisonlyscheduledforexecutionwhentheG* interrupt queue is full, the Background Interrupt Handler will alwaysH* be scheduled or already in execution. Therefore this routine will onlyF* execute after the interrupt queue has been emptied by the BackgroundL* Interrupt Handler. This assures that the owning task will recieve shutdownJ* notification for a channel only after notification has been received forD* all interrupts that were queued for the channel prior to shutdown.*9*Entryregisters:‚A1=AddressoftheBABinthedevice#*¨dependentportionoftheCCBthat*¨activatedthisroutine.*6*Registerusageƒ:D1=Channelnumberbeingprocessed$*£D3=InputModuleChannelmnemonic)*£D4=Timeofinterruptthatstartedthe*¨debounceoperation. *£D7=Maskofshutdownchannels*£A2=CCBaddress*£A3=ICCTentryaddress*:*Exitregistersƒ:Allregistersaresaved/restoredbythe-*£RMS68KBackgroundProcessDispatchroutine.*O*******************************************************************************ŠPAGE?DOWNCHAN‚LEA.L‚-CCBBAB(A1),A2‡CalculatetheCCBaddressforthe-*£shutdownchannel(s)fromtheBABaddressin*£A1onentrytothisroutine.ŠSPC„2>ŠMOVE.BCCBSHTDN(A2),D7†Copythemaskofshutdownchannelsand<ŠEOR.B‚D7,CCBSHTDN(A2)„forcetozero,allbitsthatwereset,*£intheoriginalmaskintheCCB.AnEORis&*£usedinsteadofaCLRtoproducethe'*£effectasingleinstruction"readand-*£clear"inthatanyothermaskbitsthatare +*£setasaresultofaninterruptafterthe+*£MOVE.BwillnotbemodifiedbytheEOR.B.ŠSPC„2?ŠMOVE.LCCBMNEM(A2),D3‡Loadthe610/620modulechannelmnemonic+*£tobesentintheChannelShutdownEvent.ŠSPC„22ŠMOVE.L#0,D4Loadaninterrupttimeofzerotobe*£sentintheshutdownevent.ŠSPC„2<ŠLEA.L‚CCBICCTE+1(A2),A3„Sincetheshutdownchannelswillbe6ŠMOVE.L#3,D1Žprocessedinorderofdecreasingchannel**£number,loadtheendaddressoftheICCT+*£plusoneandstartwithchannelnumber3.ŠSPC„2BDWN020„LEA.L‚-ICCENTLN(A3),A3…IndextheICCTentrywithnextlower*£channelnumber.ŠSPC„24ŠBCLRƒD1,D7Testandcleartheshutdownflagforthe4ŠBEQ„DWN030currentchannel.Iftheflagwasnotset*£proceedtothenextchannel.ŠSPC„2M*ƒIntheeventthatthisbackgroundroutinewasscheduledforexecutionwhileN* a Close Channels or Disable Interrupts command was executing in Guarded ModeL* (i.e. background processing was blocked), the channel for which a shutdownL* event was to be issued may have already been closed or interrupts may haveN* been disabled prior to execution of this routine. Therefore, it is necessaryM* to assure that the channel is currently open and that interrupts are markedL* as Enabled in the ICCT entry. If the channel was closed or interrupts wereH* disabled by the owning task, all queued interrupts for the channel areJ* automatically discarded making the information contained in the shutdown* event redundant. 7ŠTST.L‚ICCTCB(A3)‹IftheownersTCBaddressintheICCT6ŠBEQ„DWN030entryiszero,thechannelhasbeenclosed)*£sothereisnoneedtoissueashutdown*£event.ŠSPC„2;ŠTST.B‚ICCENABL(A3)‰Ifinterruptshavebeendisabledonthe0ŠBEQ„DWN030channel,thereisnoneedtoissuea*£shutdownevent.ŠPAGE8ŠSF…ICCENABL(A3)‰Interruptsforthechannelhavealready%*£beendisabledatthe610/620module,*£hardwaresointerruptsmustalsobemarked *£asdisabledintheICCTentry.ŠSPC„2<ŠTST.B‚ICCQEVNT(A3)‰IfinterruptnotificationisviaWakeup,3ŠBEQ„DWN030noshutdownnotificationispossibleso&*£proceedtoprocessthenextshutdown *£channel.ŠSPC„2SHUTDOWN‚EQU„$FF;ŠMOVE.L#SHUTDOWN,D2‰Loadthestatusforachannelshutdown*£eventintoD2.ŠSPC„24ŠBSR„NOTQEVNTIssuetheshutdowneventtotheowning*£task.ŠSPC„27DWN030„TST.B‚D7“Loopuntilallshutdownflagshavebeen;ŠDBEQƒD1,DWN020Šclearedorallinterruptchannelshavebeen *£processed.ŠSPC„2)ŠRTS™Returntothebackgrounddispatcher.ŠPAGEO*********************************************************************************•ForegroundInterruptHandler*•----------------------------N*(Note:‚Thisroutinealwaysexecuteswiththeprocessorinterruptmasksetto7*‡atleasttheleveloftheinterruptbeingprocessed.)*I*ƒThisroutineiscalledbytheRMS68KChannelManagementRoutinewhenanJ* I/O Channel interrupt is being processed and a VME 610/620 module CCB isH* encountered in the interrupt polling chain. On entry to this interruptN* handler, the memory mapped I/O base address of the 610/620 board is obtainedO* from the CCB and the Interrupt Status register is read. The latched interruptK* channel status (bits 0-3) is ANDed with the interrupt channel enable maskN* (bits 4-7) to obtain the mask of interrupting input channels for the 610/620L* module being processed. If none of the input channels are interrupting, anN* immediate return is made to CMR with the SR Carry bit clear to indicate thatM* the interrupt has not been claimed and that the polling chain search should * continue.*J*ƒIfoneormorechannelsonthe610/620moduleareinterrupting,themaskG* of interrupting channels is ANDed with the mask of channels for whichH* interrupt queuing is enabled. If all of the interrupting channels haveL* interrupt queuing disabled, an immediate return is made to CMR with the SRI* Carry bit set to indicate that the interrupt was  claimed. This allows aI* Command Handler routine to generate a 'programmed interrupt' to clear aK* particular input channel by disabling interrupt queuing and then enablingK* interrupts on the channel. If a command routine simply read the InterruptJ* Status register to clear the channel, it could accidentally 'capture' anF* interrupt that occurred during the read operation. Since the latchedM* interrupt status would be cleared after the read, the command routine wouldN* have the only knowledge that an interrupt had occurred but there would be noH* way to process it. The 'programmed interrupt' approach eliminates thisM* problem since any channel with a pending interrupt that has queuing enabledK* will be processed normally and interrupts on queue disabled channels will* be discarded.*B*ƒTheForegroundInterruptHandlerthendisablesinterruptsonallG* interrupting channels that are software debounced to block additionalA* interrupts from occurring until the end of the debounce period.*H*ƒNext,iftheInterruptProcessingQueueisnotfull,anewqueueentryL* is created that contains the mask of interrupting channels, the address ofK* the CCB for the interrupting 610/610 module, and the current value of theK* RMS68K Time-of-Day clock (milliseconds past midnight of the current day).N* Then, the Background Interrupt Handler is scheduled for execution by callingN* the RMS68K Background Process Scheduler and a return is made to CMR with the>* SR Carry bit set to indicate that the interrupt was claimed.ŠPAGEK*ƒIftheanewinterruptqueueentrycannotbecreatedbecausethequeueisO* full, the driver performs channel shutdown processing on all of the currentlyO* interrupting channels. First, the shutdown flag is set in the CCB for each ofI* the interrupting channels. This information is needed by the BackgroundM* Channel Shutdown Handler to send a Shutdown Notification Event to the ownerJ* of each shutdown channel. Second, interrupts are disabled at the 610/620K* module hardware for each of the shutdown channels. If frequent interruptsI* from a single channel or a small group of channels are the cause of theJ* interrupt queue overflow, disabling of interrupts on each channel as itsK* interrupts are discarded should shutdown the trouble causing channels andH* reduce interrupt activity to a manageable level without penalizing theN* input channels that have lower interrupt rates. After the channels have beenM* marked as shutdown, the Foreground Interrupt Handler schedules execution ofN* the Background Channel Shutdown Handler and returns to CMR with the SR Carry:* bit set to indicate that the interrupt has been claimed.*&*Entryregisters‚:D0=Workregister*£A0=Workregister*£A1=Workregister*£A5=CCBaddress*&*Registersusedƒ:D0,D1,D2,A0,andA1*8*Exitregistersƒ:AllregistersexceptD0,A0,andA1are*£preservedonreturntoCMR.*O*******************************************************************************ŠPAGEEINTERUPT‚MOVE.LCCBCHB(A5),A1ˆLoadthememory-mappedI/Obaseaddress*£ofVME610/620hardware.ŠSPC„2:ŠMOVE.BINPISTAT(A1),D0†ReadthehardwareInterruptStatus'*£registertogetthelatchedinterrupt+*£statusandtheinterruptenabledchannels$*£mask.Thereadalsoclearspending$*£interruptsonallofthechannels.ŠSPC„24ŠMOVE.BD0,-(A7)SaveacopyoftheInterruptStatus5ŠLSR.B‚#4,D0Žregistercontentsonthestackandshift+*£themaskofinterruptenabledchannelsto*£bits0-3ofD0.ŠSPC„25ŠAND.B‚(A7)+,D0ANDthemaskofenabledchannelswith/ŠBNE„INT010interruptstatustogetthemaskof)*£interruptingchannelsinbits0-3ofD0'*£andzerosinbits3-7.‚Ifthemaskis**£non-zero,oneormoreinputchannelsare&*£interruptingsocontinueprocessing.ŠSPC„2,ŠRTS™Ifnochannelsofthisinputmoduleare)*£interrupting,returntoCMRwiththeSR&*£Carrybitcleartoindicatethatthe+*£interrupthasnotbeenclaimed.The Carry**£bitwasclearedautomaticallybytheAND*£thatwasjustexecuted.ŠSPC„2BINT010„AND.B‚CCBIQENA(A5),D0†ANDthemaskofinterruptingchannels4ŠBNE„INT020withthemaskofchannelswithinterrupt&*£queuingenabled.Ifthisnewmaskof,*£interruptingchannelsisnon-zero,proceed*£withinterruptprocessingŠSPC„22ŠSUB.B‚#1,D0Noneoftheinterruptingchannelsare+ŠRTS—interruptqueueenabledsodiscardthe)*£interruptinformationthatwasobtained-*£andreturntoCMRwiththeSRCarrybitset)*£toshowthattheinterruptwasclaimed.-*£SincetheloworderbyteofD0iszero,the+*£Carrybitcanbesetsubtractingonefrom*£D0.ŠSPC„2>INT020„MOVE.WD1,-(A7)Savethecontentsofthedataregisters8ŠMOVE.WD2,-(A7)‹thatwillbedestroyedbytheinterrupt+*£handlerandnotrestoredbyCMR.Onlythe)*£loworderwordofeachregisterisused'*£bytheinterrupthandlersoonlythat**£portionissavedonthestackforfaster*£interruptservice.ŠSPC„27ŠMOVE.BD0,D1CopythemaskofinterruptingchannelstoAŠAND.B‚CCBCHTYP(A5),D0„D1.ANDtheothercopyinD0withthemask(*£ofsoftwaredebouncechannelstogeta)*£maskofinterruptingdebouncechannels.ŠSPC„2/ŠEOR.B‚D0,CCBINTCR(A5)ExclusiveORthemaskof@ŠMOVE.BCCBINTCR(A5),INPICNTR(A1)interruptingsoftwaredebounce%*ªchannelswiththeInterruptControl%*ªregisterimageintheCCBandwrite *ªtheimageintothehardwareto$*ªdisableinterruptsonthedebounce *ªchannels.ŠSPC„2?ŠMOVE.LCCBQCTAD(A5),A1†LoadtheaddressoftheInterruptQueue**£ControlTablefromtheCCBintoanindex *£register.ŠSPC„29ŠMOVE.LQPTR(A1),A0ŠLoadtheInterruptQueuebaseaddress-*£fromtheInterruptQueueControlTableinto*£anaddressregister.ŠSPC„2G*ƒThefollowingcodestoresanewinterruptentryintothequeueattheN* location specified by the queue input offset. Since the same interrupt queueH* is used to contain interrupt entries for 610/620 modules that may haveO* different hardware interrupt priorities, the processor interrupt mask must beO* raised to the level of the highest priority 610/620 module interrupt possibleN* while a new entry is being placed in the queue. The hardware interrupt levelI* of the highest priority 610/620 module is stored in the Interrupt QueueN* Control Table and is updated each time a CMR channel for a 610/620 module isL* allocated. After the queue entry has been created and the input offset hasK* been updated, the processor interrupt mask is reduced to the level of the* original interrupt. 6ŠMOVE.WSR,D0CopythecurrentSRintoadataregister.ŠMOVE.WD0,-(A7)‹andsaveacopyonthestack.ŠSPC„26ŠAND.W‚#$F8FF,D0ŒSettheinterruptmaskbitsintheSR8ŠOR.WƒQMAXIL(A1),D0†copytozeroandORintheinterrupt3ŠMOVE.WD0,SRŽlevelofthehighestpriority610/620&*£modulefromtheIQCT.Thenraisethe(*£processormasktothedesiredlevelby+*£movingthemodifieddataregisterbackto%*£theSR.Thiscodemodifiesonlythe(*£processorinterruptmaskandcondition+*£codeportionoftheSR.Allotherbitsof)*£theSRareunmodifiedforcompatibility,*£withfutureM68XXXfamilyprocessors(i.e. *£68020).ŠPAGE;ŠMOVE.WQINOFST(A1),D2‡Loadthequeueinputoffsetfromthe-*£InterruptQueueControlTableintoanindex *£register. K*ƒThelineofcode‚'MOVE.LTIMEOD,D0'‚hadtobereplacedbecausetheTIMEODL* parameter has been eliminated in the new Periodic Activation mechanism forN*VERSAdos4.4.‚AcallisnowmadetotheRMS68KRDTIMERroutinetoobtainthe* current time-of-day. 8ŠMOVEM.LD1/A0,-(A7)‡SavetheregistersusedbyRDTIMER.;ŠMOVE.LCCBRDTIM(A5),A0„GettheRMS68KaddressforRDTIMER,0ŠJSR„(A0)andgoobtainthecurrenttime-of-day.*(*ƒTheregistersreturnedbyRDTIMERare:%*…D0.L=timercontents(notneeded).G*…D1.L=time-of-dayexpressedinmillisecondssincemidnight(TIMEOD).*4ŠMOVE.LD1,D0ŽSavetime-of-dayasperoriginalcode.7ŠMOVEM.L(A7)+,D1/A0‡RestoreregistersusedbyR DTIMER.(*£HereweWANTthetime-of-dayinD0,so'*£wedon'tneedtosaveandrestoreD0.*>*ƒEndofreplacementcodefor‚'MOVE.LTIMEOD,D0'‚***10/25/84.*ŠSPC„2DŠMOVEM.LD0/D1/A5,0(A0,D2.W)Moveanewinterruptentrytothequeue)*£atthelocationreferencedbythequeue**£inputoffset.Thedataismovedinthree$*£longwordsinthefollowingorder:*«Time-of-Dayclockvalue*«Maskofinterruptingchannels*«CCBaddresssuppliedbyCMR+*£AMOVEM.Linstructionisusedtominimize+*£thetotalexecutiontimeoftheinterrupt,*£handler.Allothermethodsofstoringdata,*£intothequeueentrywouldspendadditonal+*£timeinsaving,loading,andrestoringan,*£addressregisterandinperformingaddress)*£calculations.Fourbytesarestoredfor(*£themaskofinterruptingchannelseven)*£thoughonlytheloworderbytecontains,*£usefuldata.Thevaluesoftheupperthree'*£bytesareconsideredtobeundefined.ŠSPC„2:ŠADD.W‚#IQENTLN,D2ŠUpdatethequeueinputoffsettoaccess<ŠAND.W‚QWAMSK(A1),D2†thenextfreequeueentrybyaddingthe)*£queueentrylengthandforcewraparound,*£fromtheendofthequeuetothebeginning+*£ifnecessary.Sincethelength,inbytes,+*£ofboththeinterruptqueueandthequeue,*£entryarepowersoftwo,wraparoundtothe(*£beginningofthequeueisperformedby,*£logicallyANDingthequeuelength-1with*£thequeueinputoffset.ŠPAGE;ŠCMP.W‚QOUTOFST(A1),D2†Iftheupdatedqueueinputoffsetis7ŠBEQ„QOVERFLO‹notequaltothequeueoutputoffset,the-*£interruptqueueisnotfullsoproceedwith-*£normalprocessing.Ifthequeueisfulland,*£theupdatedinputoffsetwerewrittenback(*£intotheInterruptQueueControlTable(*£here,theBackgroundInterruptHandler)*£woulderroneouslydecidethatthequeue**£wasempty.Topreventthis,thequeueis)*£treatedasfullwhenthereisstillone,*£unusedentryandthetestforafullqueue,*£ismadeAFTERinformationhasbeenwritten'*£totheunusedentry.Byallowingthis+*£singlewastedwritetoa"full"queue,we**£savetimewhenwritingentriestoanon-(*£fullqueueviaafasterqueueoverflow*£check.ŠSPC„2=ŠMOVE.WD2,QINOFST(A1)‡Savetheupdatedqueueinputoffsetin$*£theInterruptQueueControlTable.ŠSPC„27ŠMOVE.W(A7)+,SRRestorethesavedvalueoftheSRfrom-*£thestacktoreducetheprocessorinterrupt*£masktoitspreviouslevel.ŠSPC„28ŠMOVE.W(A7)+,D2Restoretheloworderwordsofthedata8ŠMOVE.W(A7)+,D1‹registersthatweresavedonthestack.,*£NotethataMOVEM.Wcannotbeusedbecause(*£thewordvalueswouldbesignextended,*£andtheupperwordsoftheregisterswould*£bedestroyed.ŠSPC„27ŠLEA.L‚QBAB(A1),A0ŠScheduleexecutionoftheBackground?ŠMOVE.LCCBBKGST(A5),A1„InterruptHandler,usingtheBABinthe3ŠJSR„(A1)InterruptQueueControlTable,byloading'*£theentrypointaddressoftheRMS68K+*£BackgroundProcessSchedulerfromtheCCB$*£andcallingtheroutineviaaJSR.ŠSPC„25ŠMOVE.L#0,D0ReturntoCMRwiththeSRCarrybitset8ŠSUB.L‚#1,D0Žtoindicatethattheinterruptwasclaimed./ŠRTS—SinceD0isrestoredbyCMR,settingD0to,*£zeroandsubtractingonesetsCarryfaster *£thanaOR.W#1,SRinstruction.ŠPAGEH*‚ControlreachesherewhenoneormoreinterruptinginputchannelsonaK* 610/620 module must be processed and there is only one free entry left inK* the Interrupt Processing Queue. Since each new interrupt entry is writtenO* into the queue before a check is made for a full queue, the last entry acts aL* a safety buffer between the last occupied queue entry and the first. UnderL* these circumstances, the updated queue input offset is not written back toK* the Interrupt Queue Control Table so the queue still is shown to have oneM* free entry. The data written to the last entry is discarded. Therefore, anyK* additional interrupts that occur while the queue is full will receive the4* same shutdown processing as the initial interrupt. ?QOVE RFLO‚MOVE.W(A7)+,SRRestorethesavedvalueoftheSRfrom-*£thestacktoreducetheprocessorinterrupt*£masktoitspreviouslevel.ŠSPC„24ŠMOVE.BD1,D0Savethemaskofinterruptingchannels-*£tobeshutdowninadataregisterthatwill*£berestoredonreturntoCMR.ŠSPC„28ŠMOVE.W(A7)+,D2Restoretheloworderwordsofthedata8ŠMOVE.W(A7)+,D1‹registersthatweresavedonthestack.,*£NotethataMOVEM.Wcannotbeusedbecause(*£thewordvalueswouldbesignextended,*£andtheupperwordsoftheregisterswould*£bedestroyed.ŠSPC„2=ŠOR.BƒD0,CCBSHTDN(A5)†ORthemaskofinterruptingchannelsto)*£beshutdownwiththemaskofpreviously*£shutdownchannelsintheCCB.ŠSPC„22ŠMOVE.LCCBCHB(A5),A0EORthemaskofinterrupting7ŠEOR.B‚D0,CCBINTCR(A5)‹channelstobeshutdownwiththe>ŠMOVE.BCCBINTCR(A5),INPICNTR(A0)interruptenablebitsinthe&*ªCCBinterruptcontrolregisterimage#*ªandmovetheimagetothe610/620#*ªhardwaretodisableinterruptson*ªtheshutdownchannels.ŠSPC„2:ŠLEA.L‚CCBBAB(A5),A0ˆScheduleactivationoftheBackgroundAŠMOVE.LCCBBKGST(A5),A1„ChannelShutdownHandlerusingtheBABat3ŠJSR„(A1)thestartofthedevicedependentportion'*£oftheCCBbyloadingtheentrypoint**£addressoftheRMS68KBackgroundProcess(*£SchedulerfromtheCCBandcallingthe*£routineviaaJSR.ŠSPC„25ŠMOVE.L#0,D0ReturntoCMRwiththeSRCarrybitset8ŠSUB.L‚#1,D0Žtoindicatethattheinterruptwasclaimed./ŠRTS—SinceD0isrestoredbyCMR,settingD0to,*£zeroandsubtractingonesetsCarryfaster *£thanaOR.W#1,SRinstruction.ŠENDéééééé=/*=/*†M610LIB.AF=/*7=/* Chain file to assemble FORTRAN-callable subroutines-=/* to interface with the MVME610/620 driver.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M610LIB.LS=/*=/IFC \1ƒ=ARGM610LIB.LS=/ENDIF=/*=ASM M610LIB.SA,M610LIB.RO,\1;R=/*{ Included files are:=/*ƒ--none--=/*}=/*=ENDé éééééeDFTINP…IDNTƒ1,0VME610/620DriverFORTRANInterfaceRoutines9/12/83**‰FORTRANcallablesubroutines*‰forVME610/620drivercalls*&*‰CALLINPCMD(input_id,param_blk_addr)*‰whereINPCMDmaybe:*4*ŠCALLINOPEN(input_id,param_blk_addr)…openchannels>*ŠCALLINCLOS(input_id,param_blk_addr)…closeselectedchannels-*ŠCALLINSTAT(input_id,param_blk_addr)…status8*ŠCALLINENAB(input_id,param_blk_addr)…enableinterrupts9*ŠCALLINDSAB(input_id,param_blk_addr)…disableinterrupts*D*‰andwhereinput_idistheCMRchannelmnemonicofaVME610or620*”boardA*‰andwhereparam_blk_addristhebaseaddressofanInputDriver*“CommandParameterBlock*,*‰Allargumentsforthecallsareidentical.7*‰Thecontentsoftheparam_blkforeachcallisunique*‰tothecall.*6*‰Allthecommandsubroutinescallacommonsubroutine3*‰INPSETtobuildtheInitiateI/Oparameterblock.**‰STACKFORALLCALLS:*7*‰deepeststack:(stackaddressstaysatINPSETreturn)0*˜commandcodeƒ2bytes(initiateI/Oparam.blk) *˜n/aŒ2bytes*˜input_id‡4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes.*˜commandaddrƒ4bytes(inputcommandaddress),*˜commandlng„2bytes(inputcommandlength)-*˜INPSETreturn‚4bytesdeepeststackaddress *˜A34bytes *˜A24bytes *˜A14bytes *˜D04bytes*‰entrystack:ƒreturn‰4bytes*˜^param_blk_adr4bytes*˜^input-idˆ4bytes* ŠSECTION9?ŠXDEFƒINOPEN,INCLOS,INSTATƒTheFORTRANsubroutinecallsusethe5ŠXDEFƒINENAB,INDSAB‰thesamecommandmnemonicsasthe(*¦correspondingassemblylanguagecalls.&*‰CALLINOPEN(input_id,param_blk_addr)*‰openandconfigurechannels*1INOPEN„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚INPSETset-uptheinitiateI/Oparameterblock)ŠMOVE.L#1,(A2)ŒsettheopencommandcodeINOPN00ƒCLR.L‚D0‘clearforuse'ŠMOVE.W4(A2),D0‹getnumberofchannelsŠASL.L‚#2,D0Žmultiplyby4.INOPN05ƒADD.L‚#6,D0Žaddinthe6byteoverhead-INOPN10ƒMOVE.WD0,(A1)Œsetthecommandlengthn=w8-ŠMOVE.LA3,A0ŽTRAP#1parameterblockaddress#ŠMOVE.L#60,D0CMRdirectivenumberŠTRAPƒ#1‘callRMS68K'ŠMOVE.WD0,(A2)Œsetthereturnedstatus)ŠMOVEM.L(A7)+,D0/A1-A3„restoreregisters!ŠMOVE.L(A7)+,A0‹putreturninA0 ŠLEA„8(A7),A7‹cleanupt hestackŠJMP„(A0)returntouser*&*‰CALLINCLOS(input_id,param_blk_addr)"*‰closeallchannelsforthisuser*1INCLOS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚INPSETset-uptheinitiateI/Oparameterblock*ŠMOVE.L#2,(A2)Œsettheclosecommandcode/INCLS10ƒMOVE.W#6,D0ŽInputclosecommandlengthŠBRA„INOPN10ŒgodotheCMRcall*&*‰CALLINSTAT(input_id,param_blk_addr))*‰readinputstatusonspecifiedchannels*1INSTAT„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚INPSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#5,(A2)Œsetthestatuscommandcode4ŠBRA„INCLS10Œgosetcommandlength&dotheCMRcall*&*‰CALLINENAB(input_id,param_blk_addr).*‰enableinterrptsonspecifiedinputchannels*1INENAB„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚INPSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#6,(A2)Œsettheenablecommandcode4ŠBRA„INCLS10Œgosetcommandlength&dotheCMRcall*&*‰CALLINDSAB(input_id,param_blk_addr)0*‰disableinterruptsonspecifiedinputchannels*1INDSAB„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚INPSETset-uptheinitiateI/Oparameterblock,ŠMOVE.L#7,(A2)Œsetthedisablecommandcode4ŠBRA„INCLS10Œgosetcommandlength&dotheCMRcall*4*‰INPSETsetuptheCMRinitiateI/Oparameterblock.*‰returns:ƒA1=addressforInputcommandlength**”A2=Inputcommandparameterblockaddress)*”A3=InitiateI/Oparameterblockaddress*(INPSET„CLR.W‚-2(A7)clearcommandlength-ŠLEA„-2(A7),A1Šsaveaddressofcommandlength$ŠMOVE.L24(A7),A0Šgetparam_blk_addr%ŠMOVE.LA0,-6(A7)Šsaveparam_blk_addr,ŠMOVE.LA0,A2Žsaveparam_blk_addrforreturnŠCLR.L‚-10(A7)ŒnotusedŠCLR.L‚-14(A7)ŒnotusedŠCLR.L‚-18(A7)ŒnotusedŠMOVE.L28(A7),A0Šget^input_id!ŠMOVE.L(A0),-22(A7)‡getinput_idŠCLR.W‚-24(A7)Œnotused0ŠMOVE.W#$0700,-26(A7)…initiateI/Ocommandcode4ŠLEA„-26(A7),A3‰initiateI/OparameterblockaddressŠRTS—returntocallerŠENDééééééé=/*=/*†M615DRV.AF=/*>=/* Chain file to assemble the MVME615 AC OUTPUT device driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M615DRV.LS=/*=/IFC \1ƒ=ARGM615DRV.LS=/ENDIF=/*$=A SM M615DRV.SA,M615DRV.RO,\1;MRZ=75=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.M615DRV.EQ=/*}=/*=ENDéééééé‡*!*…MVME615ACOUTPUTBOARDDRIVER *…copyrighted1983MOTOROLAINC. *œTOMKRYKA* ‰LLEN†120 ‰TTL‡STR.EQ‰INCLUDEƒ9995.&.STR.EQ ‰TTL‡TCB.EQ‰PAGE‰INCLUDEƒ9995.&.TCB.EQ‰TTL‡TR1RTCD.EQ‰PAGE‰INCLUDEƒ9995.&.TR1RTCD.EQ ‰TTL‡CCB.EQ‰PAGE‰INCLUDEƒ9995.&.CCB.EQ ‰TTL‡LV5.EQ‰PAGE‰INCLUDEƒ9995.&.LV5.EQ‰TTL‡M615DRV.EQ‰PAGE‰INCLUDEƒ9995.&.M615DRV.EQ‰TTL‡MVME615DRIVER‰PAGEM615DRV‚IDNT†1,0‡ACODRIVERJ****************************************************************************ƒDR615--REV.1.008/2/83*+*ƒPurpose:‚MVME615ACOUTPUTBOARDHANDLER*/*ƒEntry:‚JSRFROMCMRHANDLER(COMMANDSERVICE) *‹JSRFROMCMRINTERRUPTHANDLER-*ƒExit:-ALWAYSEXITSWITHARTSINSTRUCTION**ƒCODEISRE-ENTRANT********************************* CHANNEL CONTROL BLOCK (CCB) *********************************B*ƒContainschanneldevicedependentdescriptionanddataareasfor*ƒI/Ohandler.*‰OFFSETƒCCBDDP*H* I/O HANDLER DATA AREA *************************************************CCBFLGƒDS.B†2‰Flags(CCBERAD1DS.B†4‰Errordebugsaveaddress2CCBQVER1DS.B†4‰Eventqueueingerrordebugaddress7CCBCCBƒDS.B†4‰Physicaladdressofcommandpacket(IOCB)CCBTASKBDS.B†4‰BuffertaskTCB-CCBPKTƒDS.B†18ˆEventworkarea(commandtour)0CCBCPKT‚DS.B†18ˆEventworkarea(interrupttour)(CCBPTRƒDS.B†4‰PhysicaladdressofbufferCCBLENƒDS.B†4‰Lengthofbuffer0CCBPTR1‚DS.B†4‰Physicaladdressof2ndarybuffer&CCBLEN1‚DS.B†4‰Lengthof2ndarybuffer*CCBCIDƒDS.B†4‰CMRparameterblockid(DCB)CCBCOPT‚DS.B†2‰IOCBoptions#CCBCFIG‚DS.B†$26‡Configurationdata**‰56bytesremain*9*‰CCBFLGDEFINITIONS:if‚CCBFLG.Bifnot0theACOmodule$*fortheCCBcannotbeusedforthe*followingreasons:*9*‰CCBFLG.B=$FA=CCBallocationexceeded#ofspecified/*šdevices-noroominACOtableforthemodule!*’=$FC=noACOTBLwasallocated/*’=$F5=noroominACOTBLforthisACOmodule*™(incorrecttableallocation)*‰PAGE  M™<¡0©?±8¹4Á<ÉGÑ>Ù9á4é;ñ7ù1B 8CH!8) ‰SECTIONƒ8 ‰XREF†ACOTBLH*************************************************************************ƒACOSERVICEVECTORTABLEH************************************************************************#*ˆDC.L†ACOINTŽinterruptsvcaddress!*ˆDC.L†ACOCMDŽcommandsvcaddress)*ˆDC.L†ACOINITinitializationsvcaddress*7*…BelowaretheoffsetformofservicepointersforCMR*.ACODVRƒDC.L†ACOINT-ACODVR‡interruptsvcoffset*‰DC.L†ACOCMD-ACODVR‡commandserviceoffset.‰DC.L†ACOINIT-ACODVR†initializationsvcoffset‰DC.L†0“Reserved‰DC.B†0“numberofextrapages‰DC.B†0,0,0reserved‰DC.L†0,0,0reserved*3*ƒ---ƒ---…CONFIGURATIONCONTROLINFORMATION…---ƒ---*$‰DC.B†'080283'‚dateoflastassembly'‰DC.B†''‡spacemeansnopatchesin.LO#‰DC.B†'4'‡majorVersadosrevision#*I**************************************************************************ƒCOMMANDTABLE&JUMPTABLE:*‰Theseareusedbythecommandserviceroutinetojumpto.*‰theappropriateroutinetohandleacommand.I************************************************************************** CMDTBLƒDC.W†ACOPEN„OPENcommand.‰DC.W†ACOCLS„CLOSEcommand.‰DC.W†ACOUT…OUTPUTONcommand. ‰DC.W†ACOOFF„OUTPUTOFFcommand.‰DC.W†ACOSTA„STATUScommand.‰DC.W†X1ˆ(notused)‰DC.W†X2ˆ(notused)#‰DC.W†ACOPLS„PULSEDOUTPUTcommand.=NUMCMDS‚EQU‡(*-CMDTBL)/2‚Thenumberofcommandsinthetable.*8JMPTBLƒDC.W†OPEN-*„Biasestothecorrespondingroutines. ‰DC.W†CLOSE-* ‰DC.W†OUTON-*‰DC.W†OUTOFF-* ‰DC.W†STAT-*‰DC.W†ENABLER-*‰DC.W†DSABLE-* ‰DC.W†PLSO-*7JMPOFFƒEQU‡JMPTBL-CMDTBL‡Offsetbetweenthetwotables.*‰PAGEH*************************************************************************+*ƒACODRIVERINITIALIZATIONSERVICEROUTINE*>*ˆThedriverisenteredhereforeachCCBallocated.‚Morethan:*ˆoneCCBmaybeallocatedforeachACOmodule.‚OneCCBis%*ˆallocatedforeachinterruptlevel.?*ˆThisroutinecheckstoseeifthereisroomintheACOTBLfor=*ˆthedeviceID.‚ItsavesthedeviceIDandthememorymapped**ˆI/OaddressofthedeviceintheACOTBL.*:*ˆAnerrorcodeissavedintheCCBifthisCCBallocation=*ˆexceedsthemaximumnumberofCCB'sspecifiedduringSYSGEN9*ˆ(SYSGENparameterNACO),ifnoACOTBLexistsornoroom*ˆinthetableforthismodule.*$*ˆEntry:‚allregistersareavailable*A5=CCBaddress,*ˆsingleexit&pointer(A0-A6)preservationI**************************************************************************ACOINIT‚PUSHPOINT•savepointers3‰MOVE.L„CCBCHB(A5),A0‡getmemorymappedI/Oaddress$‰MOVE.L„ACOTBL,A1‹getACOTBLaddress‰CMP.L…#0,A1isthereone?&‰BNE.S…ACOINIT1Œbranchifhaveatable8‰MOVE.B„#ACONTBL,CCBFLG(A5)setnotableerrorcondition!‰BRA.S…ACOINEX1ŒgotoerrorreturnACOINIT5TST.L…(A1,D3)lookforanentryslottosavethisguy5‰BMI.S…ACOINIT6Œbranchifthisslotisempty-useit.‰ADD.W…#IOLNG,D3‹notempty,bumptonextentry"‰SUB.B…#1,D4decrementthecounter(‰BNE.S…ACOINIT5Œbranchifmoretosearch4‰BRA‡ACOEXTERŒerrorifgothere-noroomforthemap>ACOINIT6MOVE.L„D2,(A1,D3)ŠsavethismemorymappedI/Oaddress‰MOVE.L„#0,D0write0toreg‰MOVE.B„D0,IOADR(A0)1ACOEXIT1CLR.B…CCBFLG(A5)Šsetforgoodallocation3‰MOVE.L„CCBCHB(A5),A1‡getmemorymappedI/Oaddress&ACOINEX1POP_POINT•recallallpointers‰RTS*‰PAGEG************************************************************************$*ƒACODRIVERCOMMANDSERVICEROUTINE*6*‹PARAMETERADDRESSANDBOUNDARYCHECKSHAVEBEENMADE**ƒEntry:‚JSRFROMCMRHANDLER.*‹A2-PHYSICALADDRESSOFCMRPARAMETERBLOCK*‹A5-PHYSICALADDRESSOFCCB*5*ƒExit:‚RTS-PARAMETERBLOCKVALIDATIONSTATUSIND0**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A**P**PP*"*”A3=ACOPARAMETERBLOCKADDRESS*”A6=REQUESTORTCBADDRESS*J***************************************************************************)*ŒConvertlogicalPBaddresstophysical.*ACOCMDƒCLR.L…D57‰MOVE.L„XIOCPK(A2),D6‡SetupaddressofACOpara.block:‰MOVE.W„XIOPLN(A2),D5‡SetuplengthofACOparameterblock+‰MOVE.L„CCBTASKA(A5),A1…SetupTCBpointer.&‰BSR‡IOHADRCKŒCallconversionroutine.‰BRA.S…CMD010ŽGoodreturn.‰NOP›Badlengthreturn. ‰CLR.L…D0;‰MOVE.W„#RTCDPBLK,D0ˆSetupinvalidparameterblockaddress‰BRA.S…ACOCEX1gotoerrorexit*!*seeifpassedtheinitializeok*7CMD010ƒMOVE.L„D6,A3Stagephys.addr.ofACOpara.blk. ‰CLR.L…D04‰TST.B…CCBFLG(A5)ŠerrorcodesetinCCBduringINIT?/‰BEQ.S…CMD020Žbranchifnoerrorcode,continue$‰MOVE.B„CCBFLG(A5),D0‡seterrorcode‰BRA.S…ACOCEX2gotoerrorexit*,*ŒgetACOTBLaddressintoA4forcommanduse* CMD020ƒEQU‡* ‰MOVE.L„ACOTBL,A4‹ACOTBLaddress)‰CMP.L…#'!ACO',(A4)ˆreallyistheACOTBL?,‰BEQ.S…CMD030ŽbranchifreallyistheACOTBL4‰MOVE.W„#ACONTBL,D0‰seterrorreturncode-notable‰BRA.S…ACOCEX2andreturn**‹findACO-IDinACOTBL*‹A1=entryaddress*0CMD030ƒMOVE.L„XIOCID(A2),D0‡getspecifiedACO-ID(‰MOVE.B„ACONMAX(A4),D1†max#ofACO-ID's$‰MOVE.L„#ACONTRY,D2‰bumppastheader"FNDACO10CMP.L…(A4,D2),D0Šamatch?!‰BEQ.S…FNDACO20Œbranchifamatch&‰ADD.W…#ACOIDLNG,D2ˆbumptonextentry1‰SUB.L…#1,D1decrementnumberofentriestocheck&‰BNE.S…FNDACO10Œbranchifmoreentries.‰MOVE.W„#ACONID,D0Šerror-ACO-IDnotintable3‰BRA.S…ACOCEX2returntoCMRwitherrconditionset+FNDACO20MOVE.L„A4,A1bassaddressoftable‰ADD.L…D2,A1addressofentry*(*ŒFindthecommandinthecommandtable.*-‰MOVEQ…#NUMCMDS-1,D0‡Setuptheloopcounter./‰LEA‡CMDTBL,A0‹A0<--addressofcommandtable.+‰MOVE.W„CMDCOD(A3),D6‡getACOcommandcode.8CMDSRCH‚CMP.W…(A0)+,D6ŒSearchthetableforthecommand.‰DBEQ†D0,CMDSRCH3‰BNE.S…CMDERRŽIfwefoundthecommandinthetable,8‰ADD.L…#JMPOFF-2,A0ˆgetthecorrespondingentryfromthe5‰MOVE.W„(A0),D0jumptableandjumptotheroutineto"‰JMP‡(A0,D0.W)‹handlethecommand.>CMDERRƒMOVE.W„#ACOINVD,D0‰didn'tfindcmdcode-exitwitherrAACOCEX2‚MOVE.W„D0,CMDSTA(A3)‡writeerrcodetousersACOparablk ACOCEX1‚RTS*‰PAGEJ***************************************************************************A*„OPENCOMMAND‚assignsthelogicalconnectionbetweenausertask9*‰andspecifiedchannelswithinanACOmodule.8channels/*‰maximummaybespecifiedinoneopencommand.*#*„ACOOPENcommand‚parameterblock: *‰DS.W‚1„returnedcommandstatus*‰DS.W‚1„commandcode(01)*‰DS.W‚1„#ofchannelstoopen*‰DS.W‚1„1stchanneln umber*‰DS.W‚1„channelconfiguration*Œ.*‰DS.W‚1„nthchannelnumber*‰DS.W‚1„channelconfiguration**„configurationword:+*‰bit0=1wake-uptaskonoutputpulsedone-*Ž=0queueeventtotaskonoutputpulsedone2*ˆbit15=1usedefaultconfiguration(ignorebit0)+*Ž=0usespecifiedconfigurationfrombit0B*ƒDefaultconfiguration:‚nowakeuporqueueeventonpulseoutput.-*‰TheactualconfiguationissavedinACOTBL.%*‰ThetaskTCBaddressisalsosaved.*)*‚Entry:A1=addressofACO-IDinACOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofACOparameterblock*‰A4=addressofACOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:CLRIOM,SETIO,DOIOH**************************************************************************‰seeifchannelalreadyopened*$OPEN…PUSHPOINT‹savealladdressregs‰ALLOCATE‚CHCONFIG*2‰BSR‡CLRIOM„clear(to$FF)theIOmapforthisACO‰CLR.L…D7ˆchannelcounter:‰CMP.W…#ACONID,D0‚anerrorreturnedfromclearingthemap?)‰BEQ.S…OPNOID‡branchifanerrorreturned$‰CLR.L…D2‘channeloffsetintoACOTBL)‰CLR.L…D1‘offsetintoACOparameterblock1‰MOVE.W„CMDCHN(A3),D0†get#ofchannelsspecified/‰BLE.S…OPNINCbranchifnegativeorzero,error0‰CMP.W…#8,D0cannotspecifymorethan8channels-‰BGT.S…OPNINCbranchifgreaterthan8,errorEOPEN10ƒMOVE.W„NUMCHAN(A3,D1),D2‚getchannelnumberfromACOpara.blk.!‰CMP.W…#7,D2insurechannel#<8 ‰BGT.S…OPNINV‰MOVE.W„D2,D5Žsaveit0‰MULU†#CHANLNG,D2ˆgetchanneloffsetintoACOTBL‰ADD.L…#4,D2ŽbumppastACO-ID+‰TST.W…(A1,D2)Œthischannelalreadyopened?-‰BPL.S…OPNOPNbranchifalreadyopened,error‰ADD.L…#1,D7Žcountthischannel>‰MOVE.W„CHNCNFG(A3,D1),D3‚getconfigurationfromACOpara.blk.-‰STORE…D3,CHCONFIG†savechannelconfiguration*0*ŒsaveTCBaddressandconfigurationinformation*.‰LOAD†D3,CHCONFIG‰recallchannelconfiguration)‰BSR‡SETIOgosetIOmapforthischannel5‰CMP.W…#ACONID,D0Šanerrorfoundduringthesavemap?*‰BEQ.S…OPNERRŽbranchifanerrorwasfound6‰MOVE.W„D3,ACOCNIF(A1,D2)ƒsaveconfigurationinACOTBL)‰MOVE.L„A6,ACOTCB(A1,D2)„saveTCBaddress4‰ADD.W…#OPNTRY,D1ŠbumptonextACOparam.blk.entry3‰SUB.W…#1,D0decrementnumberofchannelsspecified)‰BGT‡OPEN10Žbranchifmorechannelstodo*‰BSR‡DOIOgosettheIOhardwareregisters!‰CMP.W…#ACONID,D0Šanerrorfound?2‰BEQ.S…OPNERRŽbraifanerrwasfound-don'topen‰CLR.L…D0’setforgoodreturn‰BRA.S…OPNXITŽgoreturntoCMR**Œopenerrorshere*5OPNINVƒMOVE.W„#ACOICNS,D0‰setinvalidchannel#error ‰BRA.S…OPNXIT8OPNINCƒMOVE.W„#ACOINC,D0Šsetinvalid#ofchannelserror‰BRA.S…OPNXITŽexit;OPNOIDƒMOVE.W„#ACONID,D0ŠsetACOmodulenotallocatederror‰BRA.S…OPNXITŽgoreturntoCMR9OPNOPNƒMOVE.W„#ACOPND,D0Šsetchannelalreadyopenederror*)*Œresetanyopenedchannelstonotopened*%OPNERRƒTST.W…D7’anychannelstoundo?3‰BEQ.S…OPNXITŽbranchifnonetoundo,returntoCMR&‰MOVE.W„#$FFFF,D3‹set'un-opened'code‰CLR.L…D1’clearforuse6OPNERR10MOVE.W„NUMCHAN(A3,D1),D2ƒgetachannelnumber$‰MULU†#CHANLNG,D2‰getchanneloffset‰ADD.L…#4,D2bumppastheaders*‰MOVE.W„D3,(A1,D2)Šsetthisentryunopened-‰ADD.W…#OPNTRY,D1Šbumptonextchannelnumber‰SUB.W…#1,D7decrementcounter&‰BGT.S…OPNERR10Œbranchifmoretoundo*ŽFallintoexit* OPNXITƒEQU‡*)‰ADD.L…#8,A7…DEALLOCATECHCONFIGonstack‰POP_POINT‹restoreallpointers ‰BRA‡NRMEXIT*I**************************************************************************A*ƒCLRIOMƒClearouttheIOmapforthismemorymappedI/Oaddress.*&*‰Entry:A1=ACO-IDaddressinACOTBL%*A2=addressofCMRparameterblock%*A3=addressofACOparameterblock*A4=addressofACOTBL*A5=addressofCCB*A6=addressofusersTCB**‰Uses:‚D4,D6,D7*%*‰Exit:‚D0=ACONIDifanerrorfound**D0=contentsonentryifnoerrorfound*I**************************************************************** **********0CLRIOMƒMOVE.W„ACOIO(A4),D7ˆgetoffsettoIOmaps.‰MOVE.B„ACONAL(A4),D6‡get#ofACO'Sallocated3‰MOVE.L„CCBCHB(A5),D4‡getmemorymappedI/Oaddress?CLRIOM1‚CMP.L…IODDR(A4,D7),D4…lookformatchmem.map.I/Oaddr‰BEQ.S…CLRIOM2branchiffound#‰ADD.W…#IOLNG,D7‹bumptonextentry‰SUB.B…#1,D6decrementcounter/‰BNE.S…CLRIOM1branchifmoreentriestosearch#‰MOVE.W„#ACONID,D0Šseterrorreturn‰RTS›returntocaller)CLRIOM2‚CLR.B…DODR07(A4,D7)‡clearthemap‰RTS›returntocaller*‰PAGEI**************************************************************************<*ƒSETIO…BuildtheIOmapentriesforthespecifiedchannels.*Builds1entrypercall*MapisinACOTBL.**‰Entry:A4ƒ=ACOTBLaddress*D3.W=channelconfiguration*D5.B=channelnumber*7*‰Exit:‚D0.W=ACONIDifmapentrynotfound,otherwise*—D0unchanged *‰Uses:D4,D6*‰Entrypoint=SETIO*‰Exitpoint‚=SETIORT**ˆPrivatesubroutineforOPEN*$* Single exit & pointer preservation*I***************************************************************************‰findmapentry* SETIO„EQU‡*‰PUSHPOINT‘saveallpointers‰MOVE.L„D7,-(A7)‹saveD73‰MOVE.W„ACOIO(A4),D7†getoffsettostartofIOmaps.‰MOVE.B„ACONAL(A4),D6†get#ofACO'Sallocated3‰MOVE.L„CCBCHB(A5),D4†getmemorymappedI/Oaddress;SETIOFD‚CMP.L…IODDR(A4,D7),D4ƒfindthematchingI/Oaddress‰BEQ.S…SETIO00‹branchiffound#‰ADD.W…#IOLNG,D7‰bumptonextentry‰SUB.B…#1,D6Ždecrementcounter/‰BNE.S…SETIOFD‹branchifmoreentriestosearch8‰MOVE.W„#ACONID,D0†setfatalerr-thisshouldn'thappen‰BRA.S…SETIORT‰returntocaller**Œdeterminechannelnumber*SETIO00‚CLR.L…D6‘clearforuse/‰MOVE.B„D5,D6Žcopychannelnumbertoworkspace**ŒCHANNEL0-7asoutputchannel*0‰BSET†D5,DODR07(A4,D7)ƒsetdataimageforoutput"SETIORT‚MOVE.L„(A7)+,D7‹restoreD7‰POP_POINT‘restoreallpointers‰RTS—returntocaller*‰PAGED*********************************************************************;*ƒDOIO†CopythedatainformationfromtheIOregisterimage"*(inthemap)totheIOregister.**ˆENTRYPARAMETERS:*A4=addressofACOTBL*A5=addressofCCB*)*‰Exit:‚D0.W=ACONIDifIOmapnotfound*D0.W=0ifnoerrorsfound**‰Uses:A0,D1,D6,D7*#* Single exit, pointer preservation*D********************************************************************* DOIO…EQU‡*‰PUSHPOINT’saveallpointers!‰MOVE.L„D7,-(A7)‹saveregisterD7*‰MOVE.W„ACOIO(A4),D7†getoffsettoIOmaps$‰MOVE.B„ACONAL(A4),D6†get#ofACO'S3‰MOVE.L„CCBCHB(A5),D1†getmemorymappedI/Oaddress*‰Thiscommanddeactivatesoutputsforspecifiedchannelsthat9*‰havepreviouslybeenopenedforoutputbythesametask<*‰requestingthisactivation.‚Theparameterblockischecked<*‰forerrorsbeforeanyoutputisdeactivated.‚Nochannelis#*‰deactivatedifanerrorisfound.*)*‰ACOOUTPUTOFFcommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode044*‰DS.Wƒ1ƒbitmaskcontainingchannel#'stoactivate*)*‚Entry:A1=addressofACO-IDinACOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofACOparameterblock*‰A4=addressofACOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:DOOFF*%* Single exit with pointers preserved*H*************************************************************************"OUTOFFƒPUSHPOINT‘saveallpointers0‰CLR.L‚D3‘flag-ckpara.blk.beforestopoutput'‰MOVE.L#4,D1ŽbumppastACO-IDintable!‰CLR.L‚D2‘useforchannelcounter‰CLR.L‚D0‘clearforuse+‰MOVE.WCMDCHN(A3),D0†getchannelstostart0‰MOVE.WƒD0,D3Œcopychan.toturnofftoworkreg+OUTOF20‚BTSTƒD2,D0Ždeactivatethischannel?0‰BEQ.S‚OUTOF30Œbranchifno-checknextchannel5‰CMP.L‚ACOTCB(A1,D1),A6ƒchannelbelongstothisuser? ‰BNE„OUTONERŒbranchifno,error.‰BCLR…D2,D3Œnegatecheckflagforthischannel$‰TST„D3‘isallofparameterchecked?(‰BNE.S‚OUTOF30Œbranchifnotallchecked2‰BSR.S‚DOOFFŽgoodpara.block-deactivatechannel‰BRA.S„OUTOFFXŠnormalexit/OUTOF30‚ADD.L‚#1,D2Žbumptonextchannelnumber-‰ADD.L‚#CHANLNG,D1ˆbumptonextchannelentry&‰CMP.L‚#8,D2checkedallthechannels?/‰BNE.S‚OUTOF20Œbranchifmorechannelstocheck ‰BRA†OUTONEROUTOFFX‚EQU‡*‰normalexit‰POP_POINT‹recallallpointers‰CLR.L„D0‰signalnoerrors‰BRA.S…NRMEXITƒnormalexit*‰PAGEI**************************************************************************"*‚STAT-GETOUTPUTSTATUSCOMMANDA*†Thiscommandreadsthestatusofspecifiedoutputchannels.The>*†channelsmusthavepreviouslybeenopenedforoutputbythisC*†user.TheparameterblockischeckedforerrorsbeforeanyoutputA*†statusisread.TheusersparameterblockismodifiedtosignalB*†activechannelsbysettingthecorrespondingbitinthebit-maskE*†word.Thecorrespondingbitnumberofinactivechannelsiscleared.* *†Allchannelsarereadatonce.*,*„ACOOUTPUTSTATUScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode05<*‰DS.Wƒ1ƒbitmaskcontainingchannelsnumberstoreadstatus$*”(thisisalsothereturnedfield)*)*‚Entry:A1=addressofACO-IDinACOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofACOparameterblock*‰A4=addressofACOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:GTSTAT*I********************************************************** **************** STAT†PUSHPOINT‘saveallpointers(ŠCLR.L‚D5‘useforreturnedstatusvalues/ŠCLR.L‚D3‘flag-ckpara.blk.beforereadstatus(ŠMOVE.L#4,D1ŽbumppastACO-IDinACOTBLŠCLR.L‚D2‘channelcounterŠCLR.L‚D0‘clearforuse;ŠMOVE.WCMDCHN(A3),D0†getchannelnumberstoreadstatuson3ŠMOVE.WD0,D3Žcopychanactivationreq.bitpattern$ŠAND„#$00FF,D0Šmaskallbutlowbyte/STAT20„BTSTƒD2,D0Žreadstatusforthischannel?ŠBEQ.S‚STAT40branchifno5ŠCMP.L‚ACOTCB(A1,D1),A6ƒchannelbelongstothisuser?1ŠBNE„OUTONERŒbranchifno-returnwitherrorset0ŠBCLRƒD2,D3Žclractivationflagforthischannel*ŠTST„D3‘finishedcheckingparameterblock?1ŠBNE.S‚STAT40branchifnotfinishedcheckingyet0ŠBSR.S‚GTSTATgoreadstatusandsaveinREG.D5!ŠBRA.S‚STAT50gotoprocedureexit3STAT40„ADD.L‚#CHANLNG,D1ˆbumptonextchannelentry(ŠADD.L‚#1,D2Žbumptonextchannelnumber,ŠBRA„STAT20branchtochannelchecksequence6STAT50„MOVE.WD5,CMDCHN(A3)†setreturnedstatusvalues&ŠBRA„OUTONEXŒandreturnwithnoerrors*‰PAGEI*************************************************************************<*‚ENABLE-ENABLEINTERRUPTSCOMMAND---NOTUSEDTHISBOARD3*‰IFCALLED,EXITSWITHINVALIDCOMMANDERRORCODE.*0*„ACOENABLEINTERRUPTScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode066*‰DS.Wƒ1ƒbitmaskofchannelstoenableforinterrupts)*‚Entry:A1=addressofACO-IDinACOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofACOparameterblock*‰A4=addressofACOTBL*‰A5=addressofCCB*‰A6=addressofusersTCBI**************************************************************************5ENABLER‚MOVE.W„#ACOINVD,D0‡setcode'invalidcommand'(‰BRA.S…NRMEXITŒandreturnwitherrorset**I*************************************************************************=*‚DSABLE-DISABLEINTERRUPTSCOMMAND---NOTUSEDTHISBOARD-*‰IFCALLED,EXITSWITHINVALIDCOMMANDCODE.*1*„ACODISABLEINTERRUPTScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode077*‰DS.Wƒ1ƒbitmaskofchannelstodisableforinterrupts)*‚Entry:A1=addressofACO-IDinACOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofACOparameterblock*‰A4=addressofACOTBL*‰A5=addressofCCB*‰A6=addressofusersTCBH*************************************************************************DSABLEƒBRA.S…ENABLER**H************************************************************************* *ƒNORMALEXIT,*ˆEntry:A2=addressofCMRparameterblock%*A3=addressofACOparameterblock*A5=addressofCCB*A6=addressofusersTCB*D0=ACOerrorcode*I**************************************************************************ANRMEXITƒMOVE.WD0,CMDSTA(A3)†setreturnstatusinACOpara.blockŠRTS—returntoCMR*‰PAGEH**************************************************************************ƒPLSO-PULSEDOUTPUTCOMMAND*)*‚Entry:A1=addressofACO-IDinACOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofACOparameterblock*‰A4=addressofACOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB*‚ExitstoNRMEXIT*+*‚Parameterblockformatforpulsedoutput:1*‚ACOparameterblock(pointedtobyA3onentry)* *ˆDS.W†1‰returnedcommandstatus*ˆDS.W†1‰commandcode*ˆDS.W†1‰numberofchannels<*---ƒ---ƒ---ƒparametersforindividualchannelsƒ---ƒ---ƒ---*ˆDS.W†1‰firstchannelnumber,*ˆDS.L†1‰numberofmillisecondsforpulseon*ˆ.*ˆ.*ˆDS.W†1‰nthchannelnumber2*ˆDS.L†1‰numberofmillisecondsfornthchanpulse*7* EACH CHANNEL IS ACTIVATED IN TURN (NON-SYNCHRONOUSLY)H*************************************************************************@*„Pulsed_Out(IN-LISTOFchannelactivationrequest,pulsetimes;*OUT-errorcode)?PLSO…ALLOCATECHANID,ACOPARBK†allocatechan.id&ACOparablock3‰STORE…A3,ACOPARBK‰saveACOparameterblockaddress ‰CLR.L…D 6’Initiatepulsedoutput ‰CLR.L…D3 ‰CLR.L…D2 ‰CLR.L…D0$*—getnumberofchannelstoactivate9‰MOVE.W„CMDCHN(A3),D0‡getno.ofchan'sfromACOparablk)PLSO1„TST.W…D0’loopon#ofchan.'stodo ‰BEQ.S…PLSOX‰CLR.L…D5’getchannelnumber‰MOVE.W„NUMCHAN(A3,D6),D5-‰STORE…D5,CHANID‹savechannelnumberonstackC*„ChannelIDconsistsofuserCCBaddress+channumberinLSbyte.+‰MOVE.L„A5,D7copyuser'sCCBaddresstoD75‰ADD.L…D7,CHANID(A7)‡CHANIDnowhascompletechan.ID"‰MOVE.L„D5,D7copychannel#toD7,‰BSR‡BIN_BITconvertbinarytobitmapinD56‰MULU†#CHANLNG,D7‰computeoffsettonthchaninACOTBL%‰ADD‡#4,D7bumptouserTCBinACOTBL-‰CMP.L…ACOTCB(A1,D7),A6„compareTCBaddresses1‰BNE.S…PLSOER1branchonchannelnotcurrentuser2*„GetpulsetimefromACOcommmandparameterblock‰MOVE.L„CHNCNFG(A3,D6),D3%*„IFpulsetime>pulse_min_timeTHEN'‰BEQ.S…PLSOER3ƒbranchonpulsetime=0(‰ADD.W…#6,D6…incrementtonextchannel#-*„requestperiodicactivation(thischannel#)2‰LEA‡PLSOFF(PC),A0‡pointtopulseturnoffroutine%‰CLR.L…D1’setrequestfor1timeonly6‰MOVE.B„CCBPPRIO(A5),D1…setact.prioritysameastask/‰LOAD†D2,CHANID‹setupchannelIDtogotoPLSOFF‰PUSHALL'‰MOVE.L„D3,A1setupactivationinterval$‰TR0$.RQPA,“passrequestforwakeup)*ŒIfnoerrinperiodicact.requestTHEN‰BRA.S…RQPAOKŽgoodreturn(‰BRA.S…PLSOER4errinperiodicact.req."*›activate_this_channel(channel#)*RQPAOKƒMOVE.L„D5,D0passbitmasktoDOOUT ‰BSR‡DOOUT‰POPALL"‰SUB‡#1,D0decrementchannelcount ‰BRA‡PLSO1**ŒErrorhandling)PLSOER1‚CLR.L…D0’Channelnotcurrentuser‰MOVE.W„#ACOICNS,D0 ‰BRA.S…PLSOX1)PLSOER3‚CLR.L…D0’Requestedpulsetime=03‰MOVE.W„#ACOCNFG,D0‰return'badconfiguration'code ‰BRA.S…PLSOX1PLSOER4‚POPALL#‰CLR.L…D0’Periodicactivationerror,‰MOVE.W„#ACOBSY,D0‹return'devicebusy'code ‰BRA.S…PLSOX1*ŒPulsedoutputgoodexitpoint6PLSOX„LOAD†A3,ACOPARBK‚restoreACOparablkaddrtoA3‰CLR.L…D0ˆsetfornormalreturn4PLSOX1ƒADD.L…#12,A7„DEALLOC‚CHANID,ACOPARBKonstack*‰BRA‡NRMEXITƒgotonormalcommonexitpoint*‰PAGE*<*‚PULSEDOUTPUTDEACTIVATION‚Enteredbyperiodicactivation. *„Onentry:?*‡D1containschannelIDcomposedofuser'sCCBaddressinM.S.7*Š3bytes,andchannelnumber(0-7)inleastsig.byte.*PLSOFFƒPUSHALL&‰MOVE.B„D1,D5savecombinedchannelID ‰AND.B…#0,D1recoverCCBaddress+‰MOVE.L„D1,A5stageCCBaddressfor'DOOFF'+‰AND.L…#$000000FF,D5‡recoverchannelnumber‰MOVE.L„D5,D4savebinaryvalue‰MOVE.L„#$0C010000,D2 ‰MOVE.B„D5,D2.‰BSR.S…BIN_BITconvertchan#tobitmapinD5"‰MOVE.L„D5,D0stagedataforDOOFF‰BSR‡DOOFFturnoffchannel0‰MULU†#6,D4pointtodatafieldassoc.withchan.5‰ADD‡#ACONTRY,D4‰addoffsetto1stchanneldatafield‰ADD‡#4,D4addinsizeofACOID+‰MOVE.L„ACOTBL,A2‹getaddr.ofACOTBLtoA2,‰MOVE.L„CCBTASKA(A5),A6…A6=usersTCBaddr. ‰CLR.L…D72‰MOVE.B„ACONMAX(A2),D7†getmax#ofACO-ID'stoD7#‰MOVE.L„CCBMNEM(A5),D6†getCCBname!PLS001ƒEQU‡*“findmatchingACO-ID!‰MOVE.L„ACOID(A2),D3ˆACO-IDtoD3(‰CMP.L…D3,D6doesCCBnamematchACO-ID?‰BEQ.S…PLS002Žbranchonmatch*‰ADDA.W„#ACOIDLNG,A2ˆaddoffsettonextID"‰SUB.B…#1,D7endofpossibleID's?$‰BMI.S…PLS003ŽbranchonIDnotfound‰BRA‡PLS001ŽchecknextID PLS002ƒEQU‡*-‰MOVE.W„ACOCNIF(A2,D4),D0ƒconfigurationtoD0(‰BSR.S…NOTFYUSRŒseeifwakeuporquevent PLS003ƒEQU‡*‰POPALL‰RTE*‰PAGEF**********************************************************************$*‚BINARYtoBIT-mapconversioninD5@*…Producesa1inD5bitcorrespondingtothebinaryvalueinD5*…(uptobit15).A*…Forinput>15binary,theresultantpatterninD5isundefined*BIN_BIT‚ALLOCATE‚BITMAP‰CLR.L…BITMAP(A7)‰ADD.W…#1,BITMAP(A7) LOOP…EQU‡* ‰TST.W…D5 ‰BEQ.S…BINBITXexitonbitfound‰ROL.W…BITMAP(A7) ‰SUB‡#1,D5 ‰BRA.S…LOOP* BINBITX‚EQU‡*‰MOVE.W„BITMAP(A7),D5'‰ADD.L…#8,A7DEALLOCATEBITMAPonstack‰RTS*‰PAGEA*‚NOTIFYUSERƒbymeansofqueeventorwak eupasspecifiedinthe*”channelconfigurationword.*ƒINPUTPARAMETERS:'*A2:AddressofchannelnameinACOTBL;*D4:Offsetfromchannelnametochanneldatafield(base) *™inACOTBL.*A5:AddressofchannelCCB.*A6:User'sTCBaddress#*D2:$0C01*GNOTFYUSRMOVE.WƒACOCNIF(A2,D4),D0getconfigurationfromchannelACOTBL#‰BTST†#15,D0‹defaultconfiguration? ‰BNE.S…NOTIFX1‰BTST…#0,D0‰no,determine:wake-up=1orq-event=0 ‰BNE.S…NOTIFA*ŽQueueevent;datastaging:$*ŽD2=$0C01 *ŽD3=ACOID*ŽD4=MemmappedI/Oaddress*ŽA6=User'sTCBaddress*8‰MOVE.L„CCBCHB(A5),D4ƒgetmem.mappedI/Oaddressstaged‰BSR.S…QUEVENT‰queuetheevent‰BRA.S…NOTIFXŠgotoexit*+NOTIFAƒMOVE.LƒA6,A0ŽstageusersTCBaddress#‰TR0$.WAKEUP,issuewakeuptouserNOTIFX:‰RTS*ŠPAGE*H*‚QUEVENT-queue'seventtodrivingtaskusingdatastagedinregisters *‹asfollows:*‹A6=user'sTCBaddress&*‹D2=$0C01*‹D3=ACOID‚(modulename)&*‹D4=memmappedI/Oaddressofboard<*†(dumpscontentsofregistersD2,D3,&D4tousersbuffer)* QUEVENT‚EQU‡*‰PUSHALLpushallregs"‰MOVE.L„A6,A0…stageuser'saddress ‰TR0$.QEVNTI*+‰BRA.S…QUEVNTOK‚goodreturnforqueueevent+‰BRA.S…QUEVNTER‚badreturnfromqueueeventQUEVNTOKEQU‡*‰POPALLŽrestoreallregs‰RTS QUEVNTER:(‰BRA‡QUEVNTOK‚putabreakherefordebug*‰PAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLINGTASKSADDRESSSPACE.*#*ENTRY:ƒD5‚-NO.OFBYTESTOCHECK*ŠD6‚-68000ADDRESS(LOGICAL)*ŠA1‚-TCBADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1*7*EXIT:„D6-PHYSICALADDRESSOFBUFFERBASE(IFLEGAL)*ŠRETURNTOPC„FORGOODADDRESS*”PC+2‚FORBADLENGTH*”PC+4‚FORBADADDRESS*F***********************************************************************-IOHADRCK‚BTSTƒ#0,D6‘Mustbeonwordboundary.)ŠBNE.S‚IOHADR4Branchifbadbufferbase.ŠTST.L‚D5”Lengthcan'tbezero.1ŠBEQ.S‚IOHADR8Don'tgotologphywithzerocount1ŠMOVE.LTCBTST(A1),A0‰Addressoftaskseg.table. ŠTR0$.LOGPHY*.ŠBRA.S‚IOHADR8Branchforgoodaddressreturn.0ŠBRA.S‚IOHADR6Branchforbadbytecountreturn.(ŠTST.L‚D5”Wasanentrypointerreturned.#ŠBEQ.S‚IOHADR4Branchifno-ERROR)ŠTST.B‚7(A0,D5)ŽIsthisanMMIOsegment?ŠBNE.S‚IOHADR8Yes,OK.3IOHADR4ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.3IOHADR6ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.IOHADR8ƒRTSšReturn.*ŠPAGEH*************************************************************************!* INTERRUPT SIDE FOR IOH HANDLING*?*ƒPURPOSE:‚HANDLEACKNOWLEDGEMENTSANDMESSAGECOMPLETIONSFROM2*ˆTHEIOH.‚OPERATESATHARDWAREINTERRUPTPRIORITY=*ˆLEVELASASUBROUTINETOTHEFIRSTLEVELINTERRUPTHANDLER.*+*ƒENTRY:‚JSR‚FROMINTERRUPTHANDLERROUTINE*‹A0-WORKREGISTER *‹A1=SELF*‹A5=ADDRESSOFCCB*‹D0=WORKREGISTER*/*ƒEXIT:‚RTS-BACKTOINTERRUPTHANDLERROUTINE*/*ƒNOTE:ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***@*ƒThisroutineiscalledonlybythecommoninterrupthandlerin'*ƒRMS68K.ƒThecommoninterrupthandler:7*ƒDOES‚NOT‚PRESERVEƒVALUES‚IN‚REGISTERS‚BEFORE‚THE‚CALL?*ƒThisinterrupthandlerMUSTPRESERVEalldata&addressregs.**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A*****P***4*ƒIfchannelisoff-lineornotattached,justexit.H*************************************************************************<*‹FindACOTABLEmodule(board)namewhichmatchesCCBname:*3ACOINTƒMOVEM.LƒA0-A6/D1-D7,-(A7)ƒsaveallexceptD01‰ALLOCATE‚ACOTADR,CHANUM†allocatelocalvariables-‰MOVE.L„ACOTBL,A2‹getaddressofACOTBLtoA2 ‰CLR.L…D76‰MOVE.B„ACONMAX(A2),D7†getmaxnumberofACOID'stoD7#‰MOVE.L„CCBMNEM(A5),D0†getccbname2IOHI011‚EQU‡*‡findmatchingACOIDloopentrypoint*‰MOVE.L„ACOID(A2),D3ˆgetACOIDforstaging'‰CMP.L…D3, D0doesCCBnamematchACOID?#‰BEQ.S…IOHI020branchonnamematch.‰ADDA.W„#ACOIDLNG,A2ˆaddoffsettonextACOTBL#‰SUB.B…#1,D7testforendofACOTBL4‰BMI.S…IOHIPX„error,exitonACO-IDnotfoundinCCB ‰BRA‡IOHI011D*„Foundmatchingnames,nowgetnumberofinterruptingchanneltoD2C*„onthisboard,usenon-existantchan.8toindicatenointerrupt.5IOHI020‚STORE…A2,ACOTADRŠsaveACOTBLaddressonstack,‰MOVE.L„#$0C010008,D2‡initparafieldsinD2*‰STORE…D2,CHANUM‹savechan.#&returncode>*„ComputeaddressoffieldinACOTBLhavinguser'sTCBaddress ‰CLR.L…D4!‰MOVE.B„D2,D4getchannel‚toD4.B$IOHIPXƒEQU‡*“'ACOINT'procedureexit-‰MOVE.L„#0,D0getint.claimcheck(0=none)*„dealocateACOTADR,CHANUM#‰ADD‡#12,A7Žreleaselocalvariables0‰MOVEM.Lƒ(A7)+,A0-A6/D1-D7ƒrestoreallexceptD0-‰AND‡#$FFFE,SR‹signalCMR'int.notfromACO'‰RTS**‰ENDééééé=/*=/*†M615LIB.AF=/*7=/* Chain file to assemble FORTRAN-callable subroutines)=/* to interface with the MVME615 driver.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M615LIB.LS=/*=/IFC \1ƒ=ARGM615LIB.LS=/ENDIF=/*=ASM M615LIB.SA,M615LIB.RO,\1;R=/*{ Included files are:=/*ƒ--none--=/*}=/*=ENDééééé é1FTACO…IDNTƒ1,0ACOsubroutines**‰FORTRANcallablesubroutines*‰forACOdrivercalls*$*‰CALLACOCMD(aco_id,param_blk_addr)*‰whereACOCMDmaybe:*)*‰CALLACOPEN(aco_id,param_blk_addr)…open**‰CALLACOCLS(aco_id,param_blk_addr)…close.*‰CALLACOOUT(aco_id,param_blk_addr)…outputon/*‰CALLACOOFF(aco_id,param_blk_addr)…outputoff+*‰CALLACOSTA(aco_id,param_blk_addr)…status2*‰CALLACOPLS(aco_id,param_blk_addr)„outputpulsed*,*‰Allargumentsforthecallsareidentical.7*‰Thecontentsoftheparam_blkforeachcallisunique*‰tothecall.*6*‰Allthecommandsubroutinescallacommonsubroutine3*‰ACOSETtobuildtheinitiateI/Oparameterblock.**‰STACKFORALLCALLS:*7*‰deepeststack:(stackaddressstaysatACOSETreturn)0*˜commandcodeƒ2bytes(initiateI/Oparam.blk) *˜n/aŒ2bytes*˜aco_id‰4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes,*˜commandaddrƒ4bytes(acocommandaddress)**˜commandlng„2bytes(acocommandlength)-*˜ACOSETreturn‚4bytesdeepeststackaddress *˜A34bytes *˜A24bytes *˜A14bytes *˜D04bytes*‰entrystack:ƒreturn‰4bytes*˜^param_blk_adr4bytes*˜^aco-idˆ4bytes* ŠSECTION9!ŠXDEFƒACOPEN,ACOCLS,ACOOUT,ACOOFFŠXDEFƒACOSTA,ACOPLS*$*‰CALLACOPEN(aco_id,param_blk_addr)*‰openandconfigurechannels*1ACOPEN„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters3ŠBSR„ACOSETset-uptheinitiateI/Oparameterblock)ŠMOVE.L#1,(A2)ŒsettheopencommandcodeACOPN00ƒCLR.L‚D0‘clearforuse'ŠMOVE.W4(A2),D0‹getnumberofchannelsŠASL.L‚#2,D0Žmultiplyby4.ACOPN05ƒADD.L‚#6,D0Žaddinthe6byteoverhead-ACOPN10ƒMOVE.WD0,(A1)Œsetthecommandlength-ŠMOVE.LA3,A0ŽTRAP#1parameterblockaddress#ŠMOVE.L#60,D0CMRdirectivenumberŠTRAPƒ#1‘callRMS68K'ŠMOVE.WD0,(A2)Œsetthereturnedstatus)ŠMOVEM.L(A7)+,D0/A1-A3„restoreregisters!ŠMOVE.L(A7)+,A0‹putreturninA0 ŠLEA„8(A7),A7‹cleanupthestackŠJMP„(A0)returntouser*$*‰CALLACOCLS(aco_id,param_blk_addr)"*‰closeallchannelsforthisuser:DC8K *1ACOCLS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚ACOSETset-uptheinitiateI/Oparameterblock*ŠMOVE.L#2,(A2)Œsettheclosecommandcode&ŠMOVE.W#4,D0ŽACOclosecommandlengthŠBRA„ACOPN10ŒgodotheCMRcall*$*‰CALLACOOUT(aco_id,param_blk_addr)'*‰activateoutputonrequestedchannels*1ACOOUT„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚ACOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#3,(A2)Œsettheoutputcommandcode*ACOUT10ƒMOVE.Wƒ#6,D0ŒsetupcommandlengthŠBRA„ACOPN10ŒgodotheCMRcall*$*‰CALLACOOFF(aco_id,param_blk_addr))*‰deactivateoutputonspecifiedchannels*1ACOOFF„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚ACOSETset-uptheinitiateI/Oparameterblock/ŠMOVE.L#4,(A2)Œsettheoutputoffcommandcode4ŠBRA„ACOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLACOSTA(aco_id,param_blk_addr))*‰readinputstatusonspecifiedchannels*1ACOSTA„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚ACOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#5,(A2)Œsetthestatuscommandcode4ŠBRA„ACOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLACOPLS(aco_id,param_blk_addr)>*‰activateoutputforx#ofmillisecondsonspecifiedchannels*1ACOPLS„MOVEM.LD0/ A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚ACOSETset-uptheinitiateI/Oparameterblock2ŠMOVE.L#8,(A2)ŒsetthepulsedoutputcommandcodeŠCLR.L‚D0‘clearforuse,ŠMOVE.W4(A2),D0‹getspecified#ofchannelsŠASL.L‚#2,D0Žmultiplyby6ŠADD.W‚4(A2),D04ŠBRA„ACOPN05Œgosetcommandlength&dotheCMRcallŠPAGE*4*‰ACOSETsetuptheCMRinitiateI/Oparameterblock,*‰returns:ƒA1=addressforACOcommandlength(*”A2=ACOcommandparameterblockaddress)*”A3=initiateI/Oparameterblockaddress*(ACOSET„CLR.W‚-2(A7)clearcommandlength-ŠLEA„-2(A7),A1Šsaveaddressofcommandlength$ŠMOVE.L24(A7),A0Šgetparam_blk_addr%ŠMOVE.LA0,-6(A7)Šsaveparam_blk_addr,ŠMOVE.LA0,A2Žsaveparam_blk_addrforreturnŠCLR.L‚-10(A7)ŒnotusedŠCLR.L‚-14(A7)ŒnotusedŠCLR.L‚-18(A7)ŒnotusedŠMOVE.L28(A7),A0Šgetaco_idŠMOVE.L(A0),-22(A7)‡getaco_idŠCLR.W‚-24(A7)Œnotused0ŠMOVE.W#$0700,-26(A7)…initiateI/Ocommandcode4ŠLEA„-26(A7),A3‰initiateI/OparameterblockaddressŠRTS—returntocaller*ŠEND*éééééé=/*=/*†M625DRV.AF=/*>=/* Chain file to assemble the MVME625 DC OUTPUT device driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M625DRV.LS=/*=/IFC \1ƒ=ARGM625DRV.LS=/ENDIF=/*$=ASM M625DRV.SA,M625DRV.RO,\1;MRZ=75=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.M625DRV.EQ=/*}=/*=ENDééé éééS*!*…MVME625DCOUTPUTBOARDDRIVER *…copyrighted1983MOTOROLAINC. *œTOMKRYKA* ‰LLEN120 ŠTTL„STR.EQŠINCLUDE9995.&.STR.EQ ŠTTL„TCB.EQ‰PAGEŠINCLUDE9995.&.TCB.EQŠTTLTR1RTCD.EQ‰PAGEŠINCLUDE9995.&.TR1RTCD.EQ ŠTTLCCB.EQ‰PAGEŠINCLUDE9995.&.CCB.EQ ŠTTLLV5.EQ‰PAGEŠINCLUDE9995.&.LV5.EQŠTTL9995.&.M625DRV.EQ‰PAGEŠINCLUDE9995.&.M625DRV.EQŠTTLMVME625DRIVER‰PAGE#M625DRV‚IDNTƒ1,0‰DCODRIVERƒ4/21/83J****************************************************************************ƒDR625--REV.1.007/5/83*+*ƒPurpose:‚MVME625DCOUTPUTBOARDHANDLER*/*ƒEntry:‚JSRFROMCMRHANDLER(COMMANDSERVICE) *‹JSRFROMCMRINTERRUPTHANDLER-*ƒExit:-ALWAYSEXITSWITHARTSINSTRUCTION**ƒCODEISRE-ENTRANT*H*-----------------------------------------------------------------------********************************* CHANNEL CONTROL BLOCK (CCB) *********************************B*ƒContainschanneldevicedependentdescriptionanddataareasfor*ƒI/Ohandler.*ŠOFFSET‚CCBDDP*H* I/O HANDLER DATA AREA *************************************************CCBFLG„DS.B„2ŒFlags(CCBERAD1‚DS.B„4ŒErrordebugsaveaddress2CCBQVER1‚DS.B„4ŒEventqueueingerrordebugaddress7CCBCCB„DS.B„4ŒPhysicaladdressofcommandpacket(IOCB)CCBTASKB‚DS.B„4ŒBuffertaskTCB-CCBPKT„DS.B„18‹Eventworkarea(commandtour)0CCBCPKTƒDS.B„18‹Eventworkarea(interrupttour)(CCBPTR„DS.B„4ŒPhysicaladdressofbufferCCBLEN„DS.B„4ŒLengthofbuffer0CCBPTR1ƒDS.B„4ŒPhysicaladdressof2ndarybuffer&CCBLEN1ƒDS.B„4ŒLengthof2ndarybuffer*CCBCID„DS.B„4ŒCMRparameterblockid(DCB)CCBCOPTƒDS.B„2ŒIOCBoptions#CCBCFIGƒDS.B„$26ŠConfigurationdata**‰56bytesremain*9*‰CCBFLGDEFINITIONS:if‚CCBFLG.Bifnot0theDCOmodule$*fortheCCBcannotbeusedforthe*followingreasons:*9*‰CCBFLG.B=$FA=CCBallocationexceeded#ofspecified/*šdevices-noroominDCOtableforthemodule!*’=$FC=noDCOTBLwasallocated \KeGm2u=}9…9@•D@¥<­7µ<½5Å=Í?ÕAÝDåJí>õ&/*’=$F5=noroominDCOTBLforthisDCOmodule*™(incorrecttableallocation)*‰PAGE ‰SECTION8 ‰XREFDCOTBLJ****************************************************************************‚DCOSERVICEVECTORTABLE*L*****************************************************************************#*ˆDC.L†DCOINTŽinterruptsvcaddress!*ˆDC.L†DCOCMDŽcommandsvcaddress)*ˆDC.L†DCOINITinitializationsvcaddress*?*Below are the new offset form of service pointers, for new CMR*DCODVR:(‰DC.L†DCOINT-DCODVR†interruptsvcoffset*‰DC.L†DCOCMD-DCODVR†commandserviceoffset.‰DC.L†DCOINIT-DCODVR…initializationsvcoffset‰DC.L†0‰Reserved‰DC.B†0“numberofextrapages‰DC.B†0,0,0reserved‰DC.L†0,0,0reserved*3*ƒ---ƒ---…CONFIGUR ATIONCONTROLINFORMATION…---ƒ---*$‰DC.B…'070583'ƒdateoflastassembly'‰DC.B†''‡spacemeansnopatchesin.LO#‰DC.B†'4'‡majorVersadosrevision#*‰PAGEJ****************************************************************************‰COMMANDTABLE&JUMPTABLE*:*‰Theseareusedbythecommandserviceroutinetojumpto.*‰theappropriateroutinetohandleacommand.*J***************************************************************************CMDTBL:ŠDC.WƒDCOPENOPENcommand.ŠDC.WƒDCOCLSCLOSEcommand.ŠDC.WƒDCOUTŽOUTPUTONcommand. ŠDC.WƒDCOOFFOUTPUTOFFcommand.ŠDC.WƒDCOSTASTATUScommand.ŠDC.WƒX1‘(notused)ŠDC.WƒX2‘(notused)#ŠDC.WƒDCOPLSPULSEDOUTPUTcommand.=NUMCMDSƒEQU„(*-CMDTBL)/2‡Thenumberofcommandsinthetable.*9JMPTBL:ƒDC.WƒOPEN-*Biasestothecorrespondingroutines. ŠDC.WƒCLOSE-* ŠDC.WƒOUTON-*ŠDC.WƒOUTOFF-* ŠDC.WƒSTAT-*ŠDC.WƒENABLE-*ŠDC.WƒDSABLE-* ŠDC.WƒPLSO-**7JMPOFF„EQU„JMPTBL-CMDTBL†Offsetbetweenthetwotables.*ŠPAGEJ***************************************************************************+*ˆDCODRIVERINITIALIZATIONSERVICEROUTINE*>*ˆThedriverisenteredhereforeachCCBallocated.‚Morethan:*ˆoneCCBmaybeallocatedforeachDCOmodule.‚OneCCBis%*ˆallocatedforeachinterruptlevel.?*ˆThisroutinecheckstoseeifthereisroomintheDCOTBLfor=*ˆthedeviceID.‚ItsavesthedeviceIDandthememorymapped**ˆI/OaddressofthedeviceintheDCOTBL.*:*ˆAnerrorcodeissavedintheCCBifthisCCBallocation=*ˆexceedsthemaximumnumberofCCB'sspecifiedduringSYSGEN:*ˆ(SYSGENparameterNDCO1),ifnoDCOTBLexistsornoroom*ˆinthetableforthismodule.*$*ˆEntry:‚allregistersareavailable*A5=CCBaddress*I**************************************************************************,*‚singleexit&pointer(A0-A6)preservation*DCOINIT:ŠPUSHPOINT‘savepointers3ŠMOVE.LƒCCBCHB(A5),A0„getmemorymappedI/Oaddress$ŠMOVE.LDCOTBL,A1ŠgetDCOTBLaddressŠCMP.L‚#0,A1Žisthereone?&ŠBNE.S‚DCOINIT1‹branchifhaveatable8ŠMOVE.B#DCONTBL,CCBFLG(A5)setnotableerrorcondition!ŠBRA.SDCOINEX1ŒgotoerrorreturnDCOINIT5‚TST.L‚(A1,D3)Œlookforanentryslottosavethisguy5ŠBMI.S‚DCOINIT6‹branchifthisslotisempty-useit.ŠADD.W‚#IOLNG,D3‰notempty,bumptonextentry"ŠSUB.B‚#1,D4Ždecrementthecounter(ŠBNE.S‚DCOINIT5‹branchifmoretosearch4ŠBRA„DCOEXTER‹errorifgothere-noroomforthemap>DCOINIT6‚MOVE.LD2,(A1,D3)‰savethismemorymappedI/OaddressŠMOVE.L‚#0,D0write0toregŠMOVE.B‚D0,IOADR(A0)1DCOEXIT1‚CLR.B‚CCBFLG(A5)‰setforgoodallocation3ŠMOVE.LCCBCHB(A5),A1†getmemorymappedI/Oaddress'DCOINEX1 :POP_POINT‘recallallpointersŠRTS*ŠPAGEJ***************************************************************************$*‰DCODRIVERCOMMANDSERVICEROUTINE*6*‹PARAMETERADDRESSANDBOUNDARYCHECKSHAVEBEENMADE**ƒEntry:‚JSRFROMCMRHANDLER.*‹A2-PHYSICALADDRESSOFCMRPARAMETERBLOCK*‹A5-PHYSICALADDRESSOFCCB*5*ƒExit:‚RTS-PARAMETERBLOCKVALIDATIONSTATUSIND0**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A**P**PP*"*”A3=DCOPARAMETERBLOCKADDRESS*”A6=REQUESTORTCBADDRESS**ƒCODEISRE-ENTRANT*J***************************************************************************)*‰ConvertlogicalPBaddresstophysical.*DCOCMD„CLR.L‚D5;ŠMOVE.LXIOCPK(A2),D6†SetupaddressofDCOparameterblock:ŠMOVE.WXIOPLN(A2),D5†SetuplengthofDCOparameterblock+ŠMOVE.LCCBTASKA(A5),A1„SetupTCBpointer.&ŠBSR„IOHADRCK‹Callconversionroutine.ŠBRA.S‚CMD010Goodreturn.ŠNOP—Badlengthreturn. ŠCLR.L‚D0;ŠMOVE.W#RTCDPBLK,D0‡SetupinvalidparameterblockaddressŠBRA.SDCOCEX1gotoerrorexit*!*‰seeifpassedtheinitializeok*7CMD010„MOVE.LƒD6,A3ŒStagephys.addr.ofDCOpara.blk. ŠCLR.L‚D04ŠTST.B‚CCBFLG(A5)‰errorcodesetinCCBduringINIT?/ŠBEQ.S‚CMD020branchifnoerrorcode,continue$ŠMOVE.BCCBFLG(A5),D0†seterrorcodeŠBRA.S‚DCOCEX2Œgotoerrorexit CMD020„EQU**,*‰getDCOTBLaddressintoA4forcommanduse* ŠMOVE.LDCOTBL,A4ŠDCOTBLaddress)ŠCMP.L‚#'!DCO',(A4)‡reallyistheDCOTBL?,ŠBEQ.S‚CMD030branchifreallyistheDCOTBL4ŠMOVE.W#DCONTBL,D0ˆseterrorreturncode-notableŠBRA.S‚DCOCEX2Œandreturn**‰findDCO-IDinDCOTBL*‰A1=entryaddress*0CMD030„MOVE.LXIOCID(A2),D0†getspecifiedDCO-ID(ŠMOVE.BDCONMAX(A4),D1…max#ofDCO-ID's$ŠMOVE.L#DCONTRY,D2ˆbumppastheader"FNDDCO10‚CMP.L‚(A4,D2),D0‰amatch?!ŠBEQ.S‚FNDDCO20‹branchifamatch&ŠADD.W‚#DCOIDLNG,D2‡bumptonextentry1ŠSUB.L‚#1,D1Ždecrementnumberofentriestocheck&ŠBNE.S‚FNDDCO10‹branchifmoreentries.ŠMOVE.W#DCONID,D0‰error-DCO-IDnotintable5ŠBRA.S‚DCOCEX2ŒreturntoCMRwitherrorconditionset+FNDDCO20‚MOVE.LA4,A1ŽbassaddressoftableŠADD.L‚D2,A1Žaddressofentry (*‰Findthecommandinthecommandtable.*-ŠMOVEQ‚#NUMCMDS-1,D0†Setuptheloopcounter./ŠLEA„CMDTBL,A0ŠA0<--addressofcommandtable.+ŠMOVE.WCMDCOD(A3),D6†getDCOcommandcode.8CMDSRCHƒCMP.W‚(A0)+,D6‹Searchthetableforthecommand.ŠDBEQƒD0,CMDSRCH3ŠBNE.S‚CMDERRIfwefoundthecommandinthetable,8ŠADD.L‚#JMPOFF-2,A0‡getthecorrespondingentryfromthe5ŠMOVE.W(A0),D0Œjumptableandjumptotheroutineto"ŠJMP„(A0,D0.W)Šhandlethecommand.DCMDERR„MOVE.W#DCOINVD,D0ˆdidn'tfindcommandcode-exitwitherrorCDCOCEX2ƒMOVE.WƒD0,CMDSTA(A3)„writeerrorcodetousersDCOparablk DCOCEX1ƒRTS*ŠPAGEL******************************************************************************‰OPENCOMMAND*A*‰Thiscommandassignsthelogicalconnectionbetweenausertask9*‰andspecifiedchannelswithinanDCOmodule.8channels/*‰maximummaybespecifiedinoneopencommand.*#*‰DCOOPENcommand‚parameterblock: *DS.W‚1„returnedcommandstatus*DS.W‚1„commandcode(01)*DS.W‚1„#ofchannelstoopen*DS.W‚1„1stchannelnumber*DS.W‚1„channelconfiguration*’.*DS.W‚1„nthchannelnumber*DS.W‚1„channelconfiguration**‰configurationword:+*bit0=1wake-uptaskonoutputpulsedone-*•=0queueeventtotaskonoutputpulsedone2*bit15=1usedefaultconfiguration(ignorebit0) *•=0usespecifiedconfiguration**‰Defaultconfiguration:,*nowakeuporqueueeventonpulsedoutput.B*‰Whendefaultconfigurationisspecified,theactualconfiguation9*‰issavedinDCOTBL.ThetaskTCBaddressisalsosaved.*)*‚Entry:A1=addressofDCO-IDinDCOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A4=addressofDCOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:CLR IOM,SETIO,DOIO*K*****************************************************************************‰seeifchannelalreadyopened*$OPEN†PUSHPOINT‘savealladdressregsŠALLOCATEƒCHCONFIG2ŠBSRCLRIOMclear(to$FF)theIOmapforthisDCOŠCLR.L‚D7‘channelcounter:ŠCMP.W‚#DCONID,D0‰anerrorreturnedfromclearingthemap?)ŠBEQ.S‚OPNOIDbranchifanerrorreturned$ŠCLR.L‚D2‘channeloffsetintoDCOTBL)ŠCLR.L‚D1‘offsetintoDCOparameterblock1ŠMOVE.WCMDCHN(A3),D0†get#ofchannelsspecified/ŠBLE.S‚OPNINCbranchifnegativeorzero,error0ŠCMP.W‚#8,D0cannotspecifymorethan8channels-ŠBGT.S‚OPNINCbranchifgreaterthan8,errorGOPEN10„MOVE.WNUMCHAN(A3,D1),D2‚getchannelnumberfromDCOparam.blk.!ŠCMP.W#7,D2insurechannel#<8 ŠBGT.SOPNINVŠMOVE.WD2,D5Žsaveit0ŠMULUƒ#CHANLNG,D2ˆgetchanneloffsetintoDCOTBLŠADD.L‚#4,D2ŽbumppastDCO-ID+ŠTST.W‚(A1,D2)Œthischannelalreadyopened?-ŠBPL.S‚OPNOPNbranchifalreadyopened,errorŠADD.L‚#1,D7Žcountthischannel@ŠMOVE.WCHNCNFG(A3,D1),D3‚getconfigurationfromDCOparam.blk.-ŠSTORE„D3,CHCONFIG†savechannelconfiguration*0*‰saveTCBaddressandconfigurationinformation*.ŠLOAD…D3,CHCONFIG†recallchannelconfiguration+ŠBSR.S‚SETIOgosetIOmapforthischannel5ŠCMP.W‚#DCONID,D0‰anerrorfoundduringthesavemap?*ŠBEQ.S‚OPNERRbranchifanerrorwasfound6ŠMOVE.WD3,DCOCNIF(A1,D2)‚saveconfigurationinDCOTBL)ŠMOVE.LA6,DCOTCB(A1,D2)ƒsaveTCBaddress4ŠADD.W‚#OPNTRY,D1‰bumptonextDCOparam.blk.entry3ŠSUB.W‚#1,D0Ždecrementnumberofchannelsspecified)ŠBGT„OPEN10branchifmorechannelstodo,ŠBSR.S‚DOIOŽgosettheIOhardwareregisters!ŠCMP.W‚#DCONID,D0‰anerrorfound?7ŠBEQ.S‚OPNERRbranchifanerrorwasfound-don'topenŠCLR.L‚D0‘setforgoodreturnŠBRA.S‚OPNXITgoreturntoCMR**‰openerrorshere*5OPNINVƒMOVE.W„#DCOICNS,D0‰setinvalidchannel#error ‰BRA.S…OPNXIT8OPNINCƒMOVE.W„#DCOINC,D0‰setinvalid#ofchannelserror‰BRA.S…OPNXIT‹exit;OPNOIDƒMOVE.W„#DCONID,D0‰setDCOmodulenotallocatederror‰BRA.S…OPNXITgoreturntoCMR9OPNOPNƒMOVE.W„#DCOPND,D0‰setchannelalreadyopenederror*)*‰resetanyopenedchannelstonotopened*%OPNERR„TST.W‚D7‘anychannelstoundo?3ŠBEQ.S‚OPNXITbranchifnonetoundo,returntoCMR&ŠMOVE.W#$FFFF,D3Šset'un-opened'codeŠCLR.L‚D1‘clearforuse6OPNERR10‚MOVE.WNUMCHAN(A3,D1),D2‚getachannelnumber$ŠMULUƒ#CHANLNG,D2ˆgetchanneloffsetŠADD.L‚#4,D2Žbumppastheaders*ŠMOVE.WD3,(A1,D2)‰setthisentryunopened-ŠADD.W‚#OPNTRY,D1‰bumptonextchannelnumberŠSUB.W‚#1,D7Ždecrementcounter&ŠBGT.S‚OPNERR10‹branchifmoretoundo*…Fallintoexit* OPNXIT EQU *)ŠADD.L„#8,A7ŒDEALLOCATECHCONFIGonstackŠPOP_POINT‘restoreallpointers ŠBRANRMEXIT*ŠPAGEK*****************************************************************************‰SETIO*6*‰BuildtheIOmapentriesforthespecifiedchannels.*‰Builds1entrypercall*‰MapisinDCOTBL.**‰Entry:A4ƒ=DCOTBLaddress*D3.W=channelconfiguration*D5.B=channelnumber*7*‰Exit:‚D0.W=DCONIDifmapentrynotfound,otherwise*—D0unchanged *‰Uses:D4,D6*‰Entrypoint=SETIO*‰Exitpoint‚=SETIORT**ˆPrivatesubroutineforOPEN*$* Single exit & pointer preservation*L******************************************************************************‰findmapentry* SETIO EQU *ŠPUSHPOINT‘saveallpointersŠMOVE.LD7,-(A7)‹saveD73ŠMOVE.WDCOIO(A4),D7†getoffsettostartofIOmaps.ŠMOVE.BDCONAL(A4),D6†get#ofDCO'Sallocated3ŠMOVE.LCCBCHB(A5),D4†getmemorymappedI/Oaddress;SETIOFD‚CMP.L‚IODDR(A4,D7),D4ƒfindthematchingI/OaddressŠBEQ.S‚SETIO00‹branchiffound#ŠADD.W‚#IOLNG,D7‰bumptonextentryŠSUB.B‚#1,D6Ždecrementcounter/ŠBNE.S‚SETIOFD‹branchifmoreentriestosearch>ŠMOVE.W#DCONID,D0‰setforfatalerror-thisshouldn'thappenŠBRA.S„SETIORT‰returntocaller**‰determinechannelnumber*SETIO00‚CLR.L‚D6‘clearforuse/ŠMOVE.BD5 ,D6Žcopychannelnumbertoworkspace**‰CHANNEL0-7asoutputchannel*/ŠBSETƒD5,DODR07(A4,D7)ƒsetddrimageforoutput"SETIORT‚MOVE.L(A7)+,D7‹restoreD7ŠPOP_POINT‘restoreallpointersŠRTS—returntocaller*ŠPAGED**********************************************************************‰DOIO*6*ˆCopythedatainformationfromtheIOregisterimage"*ˆ(inthemap)totheIOregister.**ˆENTRYPARAMETERS:*A4=addressofDCOTBL*A5=addressofCCB*)*‰Exit:‚D0.W=DCONIDifIOmapnotfound*D0.W=0ifnoerrorsfound**‰Uses:A0,D1,D6,D7*#* Single exit, pointer preservation*D********************************************************************* DOIO EQU *ŠPUSHPOINT’saveallpointers!ŠMOVE.LD7,-(A7)‹saveregisterD7*ŠMOVE.WDCOIO(A4),D7†getoffsettoIOmaps$ŠMOVE.BDCONAL(A4),D6†get#ofDCO'S3ŠMOVE.LCCBCHB(A5),D1†getmemorymappedI/Oaddress*‰Thiscommanddeactivatesoutputsforspecifiedchannelsthat9*‰havepreviouslybeenopenedforoutputbythesametask<*‰requestingthisactivation.‚Theparameterblockischecked<*‰forerrorsbeforeanyoutputisdeactivated.‚Nochannelis#*‰deactivatedifanerrorisfound.*)*‰DCOOUTPUTOFFcommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode044*‰DS.Wƒ1ƒbitmaskcontainingchannel#'stoactivate*)*‚Entry:A1=addressofDCO-IDinDCOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A4 =addressofDCOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:DOOFF*%* Single exit with pointers preserved*L*****************************************************************************OUTOFF:ŠPUSHPOINT‘saveallpointers2ŠCLR.L‚D3‘flagtockpara.blk.beforestopoutput'ŠMOVE.L#4,D1ŽbumppastDCO-IDintable!ŠCLR.L‚D2‘useforchannelcounterŠCLR.L‚D0‘clearforuse+ŠMOVE.WCMDCHN(A3),D0†getchannelstostart0ŠMOVE.WƒD0,D3Œcopychan.toturnofftoworkreg+OUTOF20ƒBTSTƒD2,D0Ždeactivatethischannel?0ŠBEQ.S‚OUTOF30Œbranchifno-checknextchannel5ŠCMP.L‚DCOTCB(A1,D1),A6ƒchannelbelongstothisuser? ŠBNE„OUTONERŒbranchifno,error.ŠBCLR…D2,D3Œnegatecheckflagforthischannel$ŠTST„D3‘isallofparameterchecked?(ŠBNE.S‚OUTOF30Œbranchifnotallchecked5ŠBSR.S‚DOOFFŽgoodpara.block-godeactivatechannelŠBRA.S„OUTOFFXŠnormalexit/OUTOF30ƒADD.L‚#1,D2Žbumptonextchannelnumber-ŠADD.L‚#CHANLNG,D1ˆbumptonextchannelentry&ŠCMP.L‚#8,D2checkedallthechannels?/ŠBNE.S‚OUTOF20Œbranchifmorechannelstocheck ŠBRA†OUTONEROUTOFFXEQU*šnormalexitŠPOP_POINT‘recallallpointersŠCLR.L„D0signalnoerrorsŠBRANRMEXITnormalexit*‰PAGE*;* DOOFF talks directly to the IO reg and turns off outputs.G* On entry: D0 has bit map of channels to turn off (a 1 means turn off)*‹A5hasaddressofuserCCB:*ˆDOOFFiscalledbyOUTOFFandPULSEDOUTPUTdeactivation DOOFF…EQU†*/ŠMOVE.LƒA2,-(A7)ŒsaveaddressofCMRparablock3ŠMOVE.LƒCCBCHB(A5),A2‡getmemorymappedI/Oaddress)ŠEOR.B„D0,IOADR(A2)†turnoffselected0-72ŠMOVE.Lƒ(A7)+,A2ŒrestoreaddressofCMRparablockŠRTS*ŠPAGEM******************************************************************************"*ˆSTAT-GETOUTPUTSTATUSCOMMANDA*ˆThiscommandreadsthestatusofspecifiedoutputchannels.The>*ˆchannelsmusthavepreviouslybeenopenedforoutputbythisC*ˆuser.TheparameterblockischeckedforerrorsbeforeanyoutputA*ˆstatusisread.TheusersparameterblockismodifiedtosignalB*ˆactivechannelsbysettingthecorrespondingbitinthebit-maskE*ˆword.Thecorrespondingbitnumberofinactivechannelsiscleared.*-*ˆAllchannelsinaIOsidearereadatonce.*,*‰DCOOUTPUTSTATUScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode05<*‰DS.Wƒ1ƒbitmaskcontainingchannelsnumberstoreadstatus$*”(thisisalsothereturnedfield)*)*‚Entry:A1=addressofDCO-IDinDCOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A4=addressofDCOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:GTSTAT*M******************************************************************************STAT:ŠPUSHPOINT‘saveallpointers(ŠCLR.L‚D5‘useforreturnedstatusvalues2ŠCLR.L‚D3‘flagtockpara.blk.beforereadstatus(ŠMOVE.L#4,D1ŽbumppastDCO-IDinDCOTBLŠCLR.L‚D2‘channelcounterŠCLR.L‚D0‘clearforuse;ŠMOVE.WCMDCHN(A3),D0†getchannelnumberstoreadstatuson3ŠMOVE.WD0,D3Žcopychanactivationreq.bitpattern$ŠAND„#$00FF,D0Šmaskallbutlowbyte/STAT20„BTSTƒD2,D0Žreadstatusforthischannel?ŠBEQ.S‚STAT40branchifno5ŠCMP.L‚DCOTCB(A1,D1),A6ƒchannelbelongstothisuser?1ŠBNE„OUTONERŒbranchifno-returnwitherrorset0ŠBCLRƒD2,D3Žclractivationflagforthischannel*ŠTST„D3‘finishedcheckingparameterblock?1ŠBNE.S‚STAT40branchifnotfinishedcheckingyet0ŠBSR.S‚GTSTATgoreadstatusandsaveinREG.D5!ŠBRA.S‚STAT50gotoprocedureexit3STAT40„ADD.L‚#CHANLNG,D1ˆbumptonextchannelentry(ŠADD.L‚#1,D2Žbumptonextchannelnumber,ŠBRA„STAT20branchtochannelchecksequence6STAT50„MOVE.WD5,CMDCHN(A3)†setreturnedstatusvalues&ŠBRA„OUTONEXŒandreturnwithnoerrors*‰PAGE*I* GSTAT reads the channels as required by the channel activation bit map,*‡onabytebasis.**‡DataisreturnedinD5.**…Channeldatamask:/BS07…EQU‡$000000FF ‹selectmaskforchannels0-7* GTSTAT EQU *‰MOVE.L„A2,-(A7)ŒpushA25‰MOVE.L„CCBCHB(A5),A2‡getmemorymappedI/Obaseaddr8‰MOVE.W„CMDCHN(A3),D0‡getnewchannelactivationbitmap)‰AND‡#BS07,D0Œselectchannels0-7bitmap)‰BEQ.S…GSTATXŽexitonnochannelstoread%‰MOVE.B„IOADR(A2),D5†getchannels0-7'‰AND.B…D0,D5maskoffnon-readchannels GSTATX EQU *‰MOVE.L„(A7)+,A2ŒrestoreA2‰RTS*ŠPAGEM******************************************************************************$*‰ENABLE-ENABLEINTERRUPTSCOMMAND**‰NOTUSEDTHISBOARD3*‰IFCALLED,EXITSWITHINVALIDCOMMANDERRORCODE.*0*‰DCOENABLEINTERRUPTScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode06A*‰DS.Wƒ1ƒbitmaskcontainingchannelnumberstoenableinterrupts)*‚Entry:A1=addressofDCO-IDinDCOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A4=addressofDCOTBL*‰A5=addressofCCB*‰A6=addressofusersTCBM******************************************************************************ENABLE:5ENABLERƒMOVE.Wƒ#DCOINVD,D0‡setcode'invalidcommand'&ŠBRA„NRMEXITŒandreturnwitherrorset***M******************************************************************************%*ˆDSABLE-DISABLEINTERRUPTSCOMMAND**‰NOTUSEDTHISBOARD-*‰IFCALLED,EXITSWITHINVALIDCOMMANDCODE.*1*‰DCODISABLEINTERRUPTScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode07B*‰DS.Wƒ1ƒbitmaskcontainingchannelnumberstodisableinterrupts)*‚Entry:A1=addressofDCO-IDinDCOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A4=addressofDCOTBL*‰A5=addressofCCB*‰A6=addressofusersTCBM******************************************************************************DSABLE:‰BRA.S…ENABLER*‰PAGEM*******************************************************************************ˆPLSO-PULSEDOUTPUTCOMMAND*)*‚Entry:A1=addressofDCO-IDinDCOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A4=addressofDCOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB*‚ExitstoNRMEXIT*+* Parameter block format for pulsed output:1* DCO parameter block (pointed to by A3 on entry)* *ˆDS.W†1‰returnedcommandstatus*ˆDS.W†1‰commandcode*ˆDS.W†1‰numberofchannels<*ƒ---ƒ---ƒ---ƒparametersforindividualchannelsƒ---ƒ---ƒ---*ˆDS.W†1‰firstchannelnumber,*ˆDS.L†1‰numberofmillisecondsforpulseon*ˆ.*ˆ.*ˆDS.W†1‰nthchannelnumber5*ˆDS.L†1‰numberofmillisecondsfornthchannelpulse*7* EACH CHANNEL IS ACTIVATED IN TURN (NON-SYNCHRONOUSLY)M******************************************************************************@*„Pulsed_Out(IN-LISTOFchannelactivationrequest,pulsetimes;*OUT-errorcode)BPLSO…ALLOCATECHANID,DCOPARBK†allocatechannelid&DCOparablock3‰STORE…A3,DCOPARBK‰saveDCOparameterblockaddress ‰CLR.L…D6’Initiatepulsedoutput ‰CLR.L…D3 ‰CLR.L…D2 ‰CLR.L…D0$*—getnumberofchannelstoactivate<‰MOVE.W„CMDCHN(A3),D0‡getnumberofchan'sfromDCOparablkPLSO1:$‰TST.W…D0’loopon#ofchan.'stodo ‰BEQ.S…PLSOX‰CLR.L…D5’getchannelnumber‰MOVE.W„NUMCHAN(A3,D6),D5-‰STORE…D5,CHANID‹savechannelnumberonstackC*„ChannelIDconsistsofuserCCBaddress+channumberinLSbyte.+‰MOVE.L„A5,D7copyuser'sCCBaddresstoD75‰ADD.L…D7,CHANID(A7)‡CHANIDnowhascompletechan.ID"‰MOVE.L„D5,D7copychannel#toD7,‰BSR‡BIN_BITconvertbinarytobitmapinD56‰MULU†#CHANLNG,D7‰computeoffsettonthchaninDCOTBL%‰ADD‡#4,D7bumptouserTCBinDCOTBL-‰CMP.L…DCOTCB(A1,D7),A6„compareTCBaddresses1‰BNE.S…PLSOER1branchonchannelnotcurrentuser2*„GetpulsetimefromDCOcommmandparameterblock‰MOVE.L„CHNCNFG(A3,D6),D3%*„IFpulsetime>pulse_min_timeTHEN'‰BEQ.S…PLSOER3ƒbranchonpulsetime= 0(‰ADD.W…#6,D6…incrementtonextchannel#-*„requestperiodicactivation(thischannel#)2‰LEA‡PLSOFF(PC),A0‡pointtopulseturnoffroutine%‰CLR.L…D1’setrequestfor1timeonly6‰MOVE.B„CCBPPRIO(A5),D1…setact.prioritysameastask/‰LOAD†D2,CHANID‹setupchannelIDtogotoPLSOFF‰PUSHALL'‰MOVE.L„D3,A1setupactivationinterval$‰TR0$.RQPA,“passrequestforwakeup)*ŒIfnoerrinperiodicact.requestTHEN‰BRA.S…RQPAOKŽgoodreturn(‰BRA.S…PLSOER4errinperiodicact.req.RQPAOK:"*›activate_this_channel(channel#)$‰MOVE.L„D5,D0passbitmasktoDOOUT ‰BSR‡DOOUT‰POPALL"‰SUB‡#1,D0decrementchannelcount ‰BRA‡PLSO1**ŒErrorhandlingPLSOER1:"‰CLR.L…D0’Channelnotcurrentuser‰MOVE.W„#DCOICNS,D0 ‰BRA.S…PLSOX1*PLSOER3:"‰CLR.L…D0’Requestedpulsetime=03‰MOVE.W„#DCOCNFG,D0‰return'badconfiguration'code ‰BRA.S…PLSOX1*PLSOER4:‰POPALL#‰CLR.L…D0’Periodicactivationerror,‰MOVE.W„#DCOBSY,D0‹return'devicebusy'code ‰BRA.S…PLSOX1*PLSOX:*ŒPulsedoutputgoodexitpoint6‰LOAD†A3,DCOPARBK‰restoreDCOparablockaddresstoA3‰CLR.L…D0ˆsetfornormalreturn*PLSOX1:1‰ADD.L…#12,A7„DEALLOCATECHANID,DCOPARBKonstack*‰BRA‡NRMEXITƒgotonormalcommonexitpoint*‰PAGE*„PULSEDOUTPUTDEACTIVATION:!*ŒEnteredbyperiodicactivation. *‡Onentry:?*ˆD1containschannelIDcomposedofuser'sCCBaddressinM.S.7*‹3bytes,andchannelnumber(0-7)inleastsig.byte.*PLSOFF:‰PUSHALL&‰MOVE.B„D1,D5savecombinedchannelID ‰AND.B…#0,D1recoverCCBaddress+‰MOVE.L„D1,A5stageCCBaddressfor'DOOFF'+‰AND.L…#$000000FF,D5‡recoverchannelnumber‰MOVE.L„D5,D4savebinaryvalue‰MOVE.L„#$0C010000,D2 ‰MOVE.B„D5,D2.‰BSR.S…BIN_BITconvertchan#tobitmapinD5"‰MOVE.L„D5,D0stagedataforDOOFF‰BSR‡DOOFFturnoffchannel0‰MULU†#6,D4pointtodatafieldassoc.withchan.5‰ADD‡#DCONTRY,D4‰addoffsetto1stchanneldatafield‰ADD‡#4,D4addinsizeofDCOID+‰MOVE.L„DCOTBL,A2‹getaddr.ofDCOTBLtoA2,‰MOVE.L„CCBTASKA(A5),A6…A6=usersTCBaddr. ‰CLR.L…D72‰MOVE.B„DCONMAX(A2),D7†getmax#ofDCO-ID'stoD7#‰MOVE.L„CCBMNEM(A5),D6†getCCBname!PLS001ƒEQU‡*“findmatchingDCO-ID!‰MOVE.L„DCOID(A2),D3ˆDCO-IDtoD3(‰CMP.L…D3,D6doesCCBnamematchDCO-ID?‰BEQ.S…PLS002Žbranchonmatch*‰ADDA.W„#DCOIDLNG,A2ˆaddoffsettonextID"‰SUB.B…#1,D7endofpossibleID's?$‰BMI.S…PLS003ŽbranchonIDnotfound‰BRA‡PLS001ŽchecknextID PLS002ƒEQU‡*-‰MOVE.W„DCOCNIF(A2,D4),D0ƒconfigurationtoD0(‰BSR.S…NOTFYUSRŒseeifwakeuporquevent PLS003ƒEQU‡*‰POPALL‰RTE*‰PAGE$*‰Binarytobit-mapconversioninD5@*‰Producesa1inD5bitcorrespondingtothebinaryvalueinD5*‰uptobit15.@*‹Forinput>15binarytheresultantpatterninD5isundefinedBIN_BIT:‰ALLOCATE‚BITMAP‰CLR.L…BITMAP(A7)‰ADD.W…#1,BITMAP(A7) LOOP…EQU‡* ‰TST.W…D5 ‰BEQ.S…BINBITXexitonbitfound‰ROL.W…BITMAP(A7) ‰SUB‡#1,D5 ‰BRA.S…LOOP* BINBITX‚EQU‡*‰MOVE.W„BITMAP(A7),D5'‰ADD.L…#8,A7DEALLOCATEBITMAPonstack‰RTS*‰PAGE *„NOTIFYUSERA*ˆnotifyuserbymeansofqueeventorwakeupasspecifiedinthe*ˆchannelconfigurationword.*„INPUTPARAMETERS:'*’A2:AddressofchannelnameinDCOTBL;*’D4:Offsetfromchannelnametochanneldatafield(base) *™inDCOTBL.*’A5:AddressofchannelCCB.*’A6:User'sTCBaddress#*’D2:$0C01* NOTFYUSR:?‰MOVE.WƒDCOCNIF(A2,D4),D0getconfigurationfromchannelDCOTBL#‰BTST†#15,D0‹defaultconfiguration? ‰BNE.S…NOTIFX1‰BTST…#0,D0‰no,determine:wake-up=1orq-event=0 ‰BNE.S…NOTIFA*ŽEnqueueevent;datastaging:$*ŽD2=$0C01 *ŽD3=DCOID*ŽD4=MemmappedI/Oaddress*ŽA6=User'sTCBaddress*8‰MOVE.LƒCCBCHB(A5),D4…getmem.mappedI/Oaddressstaged ‰BSR.SQUEVENTenqueuetheevent‰BRA.S‚NOTIFXŽgotoexit*+NOTIFAƒMOVE.LƒA6,A0ŽstageusersTCBaddress#‰TR0$.WAKEUP,issuewakeuptouserNOTIFX:‰RTS*ŠPAGEO******** ************************************************************************ *ˆNORMALEXIT*,*‚Entry:A2=addressofCMRparameterblock%*‰A3=addressofDCOparameterblock*‰A5=addressofCCB*‰A6=addressofusersTCB*‰D0=DCOerrorcode*I**************************************************************************NRMEXIT:>ŠMOVE.WD0,CMDSTA(A3)†setreturnstatusinDCOparameterblockŠRTS—returntoCMR*ŠPAGE*H*‚QUEVENT-queue'seventtodrivingtaskusingdatastagedinregisters *‹asfollows:*‹A6=user'sTCBaddress&*‹D2=$0C01*‹D3=DCOID‚(modulename)&*‹D4=memmappedI/Oaddressofboard<*†(dumpscontentsofregistersD2,D3,&D4tousersbuffer)* QUEVENT EQU *‹PUSHALL”pushallregs"‹MOVE.L…A6,A0Žstageuser'saddress ‹TR0$.QEVNTI*)‹BRA.SƒQUEVNTOKŒgoodreturnforqueevent'‹BRA.SƒQUEVNTERŒbadreturnfromqueventQUEVNTOK EQU *‹POPALL•restoreallregs‹RTS QUEVNTER:(‹BRAQUEVNTOKputabreakherefordebug*ŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLINGTASKSADDRESSSPACE.*#*ENTRY:ƒD5‚-NO.OFBYTESTOCHECK*ŠD6‚-68000ADDRESS(LOGICAL)*ŠA1‚-TCBADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1*7*EXIT:„D6-PHYSICALADDRESSOFBUFFERBASE(IFLEGAL)*ŠRETURNTOPC„FORGOODADDRESS*”PC+2‚FORBADLENGTH*”PC+4‚FORBADADDRESS*F*********************************************************************** IOHADRCK:%ŠBTSTƒ#0,D6‘Mustbeonworkboundary.)ŠBNE.S‚IOHADR4Branchifbadbufferbase.ŠTST.L‚D5”Lengthcan'tbezero.2ŠBEQ.S‚IOHADR8Don'tgotologphywithzerocount.1ŠMOVE.LTCBTST(A1),A0‰Addressoftaskseg.table. ŠTR0$.LOGPHY*.ŠBRA.S‚IOHADR8Branchforgoodaddressreturn.0ŠBRA.S‚IOHADR6Branchforbadbytecountreturn.(ŠTST.L‚D5”Wasanentrypointerreturned.#ŠBEQ.S‚IOHADR4Branchifno-ERROR)ŠTST.B‚7(A0,D5)ŽIsthisanMMIOsegment?ŠBNE.S‚IOHADR8Yes,OK.3IOHADR4ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.3IOHADR6ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.IOHADR8ƒRTSšReturn.*ŠPAGEJ***************************************************************************!* INTERRUPT SIDE FOR IOH HANDLING*?*ƒPURPOSE:‚HANDLEACKNOWLEDGEMENTSANDMESSAGECOMPLETIONSFROM2*THEIOH.‚OPERATESATHARDWAREINTERRUPTPRIORITY=*LEVELASASUBROUTINETOTHEFIRSTLEVELINTERRUPTHANDLER.*+*ƒENTRY:‚JSR‚FROMINTERRUPTHANDLERROUTINE*‹A0-WORKREGISTER *‹A1=SELF*‹A5=ADDRESSOFCCB*‹D0=WORKREGISTER*/*ƒEXIT:‚RTS-BACKTOINTERRUPTHANDLERROUTINE*/*ƒNOTE:ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***@*ƒThisroutineiscalledonlybythecommoninterrupthandlerin'*ƒRMS68K.ƒThecommoninterrupthandler:;*ƒ!!!ƒDOES‚NOTƒPRESERVEƒVALUESƒINƒREGISTERSƒBEFOREƒTHEƒCALLK*ƒsothisinterrupthandlermustpruservealldatareg.'s&addressreg.'s.5*ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***‚***‚******ƒ***ƒ***ƒ*****ƒREGISTERSUSED:ƒ01234567 *”D******** *”A*****P***4*ƒIfchannelisoff-lineornotattached,justexit.K****************************************************************************<*‹FindDCOTABLEmodule(board)namewhichmatchesCCBname:*3DCOINTƒMOVEM.LƒA0-A6/D1-D7,-(A7)ƒsaveallexceptD01‰ALLOCATE‚DCOTADR,CHANUM†allocatelocalvariables-‰MOVE.L„DCOTBL,A2‹getaddressofDCOTBLtoA2 ‰CLR.L…D76‰MOVE.B„DCONMAX(A2),D7†getmaxnumberofDCOID'stoD7#‰MOVE.L„CCBMNEM(A5),D0†getccbname2IOHI011‚EQU‡*‡findmatchingDCOIDloopentrypoint*‰MOVE.L„DCOID(A2),D3ˆgetDCOIDforstaging'‰CMP.L…D3,D0doesCCBnamematchDCOID?#‰BEQ.S…IOHI020branchonnamematch.‰ADDA.W„#DCOIDLNG,A2ˆaddoffsettonextDCOTBL#‰SUB.B…#1,D7testforendofDCOTBL6‰BMI.S…IOHIEX01Œbranchtoerrorexit1onidnotfound ‰BRA‡IOHI011F*…Foundmatchingnames,nowgetnumberofinterruptingchannel(toD2)$*£inthiscase,non-existantchan.8  5IOHI020‚STORE…A2,DCOTADRŠsaveDCOTBLaddressonstack,‰MOVE.L„#$0C010008,D2‡initparafieldsinD2+‰STORE…D2,CHANUM‹savechan.#&returncode>*„ComputeaddressoffieldinDCOTBLhavinguser'sTCBaddress ‰CLR.L…D4!‰MOVE.B„D2,D4getchannel‚toD4.B$IOHIPXƒEQU‡*‰'DCOINT'procedureexit2‰MOVE.L„#0,D0getinterruptclaimcheck(=0-none)*„dealocateDCOTADR,CHANUM#‰ADD‡#12,A7Žreleaselocalvariables0‰MOVEM.Lƒ(A7)+,A0-A6/D1-D7ƒrestoreallexceptD02‰AND‡#$FFFE,SR‹signalCMR'interruptnotfromDCO'‰RTS*IOHIEX01EQU‡*,*‹errorexitforDCOIDnamenotfoundinCCB‰BRA‡IOHIPXŽgotoprocedureexit**‰ENDéé=/*=/*†M625LIB.AF=/*7=/* Chain file to assemble FORTRAN-callable subroutines)=/* to interface with the MVME625 driver.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M625LIB.LS=/*=/IFC \1ƒ=ARGM625LIB.LS=/ENDIF=/*=ASM M625LIB.SA,M625LIB.RO,\1;R=/*{ Included files are:=/*ƒ--none--=/*}=/*=ENDééééééýFTDCO…IDNTƒ1,0DCOsubroutines**‰FORTRANcallablesubroutines*‰forDCOdrivercalls*$*‰CALLDCOCMD(dco_id,param_blk_addr)*‰whereDCOCMDmaybe:*)*‰CALLDCOPEN(dco_id,param_blk_addr)…open**‰CALLDCOCLS(dco_id,param_blk_addr)…close.*‰CALLDCOOUT(dco_id,param_blk_addr)…outputon/*‰CALLDCOOFF(dco_id,param_blk_addr)…outputoff+*‰CALLDCOSTA(dco_id,param_blk_addr)…status2*‰CALLDCOPLS(dco_id,param_blk_addr)„outputpulsed*,*‰Allargumentsforthecallsareidentical.7*‰Thecontents  oftheparam_blkforeachcallisunique*‰tothecall.*6*‰Allthecommandsubroutinescallacommonsubroutine3*‰DCOSETtobuildtheinitiateI/Oparameterblock.**‰STACKFORALLCALLS:*7*‰deepeststack:(stackaddressstaysatDCOSETreturn)0*˜commandcodeƒ2bytes(initiateI/Oparam.blk) *˜n/aŒ2bytes*˜dco_id‰4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes,*˜commandaddrƒ4bytes(dcocommandaddress)**˜commandlng„2bytes(dcocommandlength)-*˜DCOSETreturn‚4bytesdeepeststackaddress *˜A34bytes *˜A24bytes *˜A14bytes *˜D04bytes*‰entrystack:ƒreturn‰4bytes*˜^param_blk_adr4bytes*˜^dco-idˆ4bytes* ŠSECTION9!ŠXDEFƒDCOPEN,DCOCLS,DCOOUT,DCOOFFŠXDEFƒDCOSTA,DCOPLS*$*‰CALLDCOPEN(dco_id,param_blk_addr)*‰openandconfigurechannels*1DCOPEN„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters3ŠBSR„DCOSETset-uptheinitiateI/Oparameterblock)ŠMOVE.L#1,(A2)ŒsettheopencommandcodeDCOPN00ƒCLR.L‚D0‘clearforuse'ŠMOVE.W4(A2),D0‹getnumberofchannelsŠASL.L‚#2,D0Žmultiplyby4.DCOPN05ƒADD.L‚#6,D0Žaddinthe6byteoverhead-DCOPN10ƒMOVE.WD0,(A1)Œsetthecommandlength-ŠMOVE.LA3,A0ŽTRAP#1parameterblockaddress#ŠMOVE.L#60,D0CMRdirectivenumberŠTRAPƒ#1‘callRMS68K'ŠMOVE.WD0,(A2)Œsetthereturnedstatus)ŠMOVEM.L(A7)+,D0/A1-A3„restoreregisters!ŠMOVE.L(A7)+,A0‹putreturninA0 ŠLEA„8(A7),A7‹cleanupthestackŠJMP„(A0)returntouser*$*‰CALLDCOCLS(dco_id,param_blk_addr)"*‰closeallchannelsforthisuserD8 *1DCOCLS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DCOSETset-uptheinitiateI/Oparameterblock*ŠMOVE.L#2,(A2)Œsettheclosecommandcode&ŠMOVE.W#4,D0ŽDCOclosecommandlengthŠBRA„DCOPN10ŒgodotheCMRcall*$*‰CALLDCOOUT(dco_id,param_blk_addr)'*‰activateoutputonrequestedchannels*1DCOOUT„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DCOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#3,(A2)Œsettheoutputcommandcode*DCOUT10ƒMOVE.Wƒ#6,D0ŒsetupcommandlengthŠBRA„DCOPN10ŒgodotheCMRcall*$*‰CALLDCOOFF(dco_id,param_blk_addr))*‰deactivateoutputonspecifiedchannels*1DCOOFF„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DCOSETset-uptheinitiateI/Oparameterblock/ŠMOVE.L#4,(A2)Œsettheoutputoffcommandcode4ŠBRA„DCOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLDCOSTA(dco_id,param_blk_addr))*‰readinputstatusonspecifiedchannels*1DCOSTA„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DCOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#5,(A2)Œsetthestatuscommandcode4ŠBRA„DCOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLDCOPLS(dco_id,param_blk_addr)>*‰activateoutputforx#ofmillisecondsonspecifiedchannels*1DCOPLS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚DCOSETset-uptheinitiateI/Oparameterblock2ŠMOVE.L#8,(A2)ŒsetthepulsedoutputcommandcodeŠCLR.L‚D0‘clearforuse,ŠMOVE.W4(A2),D0‹getspecified#ofchannelsŠASL.L‚#2,D0Žmultiplyby6ŠADD.W‚4(A2),D04ŠBRA„DCOPN05Œgosetcommandlength&dotheCMRcallŠPAGE*4*‰DCOSETsetuptheCMRinitiateI/Oparameterblock,*‰returns:ƒA1=addressforDCOcommandlength(*”A2=DCOcommandparameterblockaddress)*”A3=initiateI/Oparameterblockaddress*(DCOSET„CLR.W‚-2(A7)clearcommandlength-ŠLEA„-2(A7),A1Šsaveaddressofcommandlength$ŠMOVE.L24(A7),A0Šgetparam_blk_addr%ŠMOVE.LA0,-6(A7)Šsaveparam_blk_addr,ŠMOVE.LA0,A2Žsaveparam_blk_addrforreturnŠCLR.L‚-10(A7)ŒnotusedŠCLR.L‚-14(A7)ŒnotusedŠCLR.L‚-18(A7)ŒnotusedŠMOVE.L28(A7),A0Šget^dco_idŠMOVE.L(A0),-22(A7)‡getdco_idŠCLR.W‚-24(A7)Œnotused0ŠMOVE.W#$0700,-26(A7)…initiateI/Ocommandcode4ŠLEA„-26(A7),A3‰initiateI/OparameterblockaddressŠRTS—r! eturntocaller*ŠEND*éééééé=/* =/*†RADDRV.AF=/*&=/* Chain file to assemble RAD1 driver=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to RADDRV.LS=/*=/IFC \1ƒ=ARGRADDRV.LS=/ENDIF=/*#=ASM RADDRV.SA,RADDRV.RO,\1;MRZ=126=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.RADDRV.EQ=/*}=/*=ENDéééééé! @‰TTLRAD1DRIVER‚===============================================9RADDRVƒIDNT†1,0RAD1DRIVER‚COPYRIGHT1982MOTOROLA,INC.‰PAGE8*ˆ6/21/82ƒ<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<H*************************************************************************ˆ======================*ˆ{”}*‡{†RADDriver†}*ˆ{”}*ˆ======================I*************************************************************************** ‰TTLSTR.SA‰PAGE‰INCLUDE9995.&.STR.EQ* ‰TTLTCB.EQ‰PAGE‰INCLUDE9995.&.TCB.EQ* ‰TTLCCB.SA‰PAGE‰INCLUDE9995.&.CCB.EQ* ‰TTLLV5.SA‰PAGE‰INCLUDE9995.&.LV5.EQ*‰TTL9995.&.RADDRV.EQ‰PAGEŠINCLUDE9995.&.RADDRV.EQ*@‰TTLRAD1DRIVER‚===============================================ŠPAGE;************************************************************ *ˆCONSTANTS*;*************************************************************ˆCommandCodes*%RASTPCMDEQU‡00ˆ"Stop"commandvalue.%RALODCMDEQU‡01ˆ"Load"commandvalue.%RADMPCMDEQU‡02ˆ"Dump"commandvalue.%RAJMPCMDEQU‡03ˆ"Jump"commandvalue.*RATSTCMDEQU‡04ˆ"Self-test"commandvalue.&RAOPNCMDEQU‡$10‡"Open"commandvalue.'RACLSCMDEQU‡$20‡"Close"commandvalue.'RAABTCMDEQU‡$7F‡"Abort"commandvalue.2RAEXTCMDEQU‡$81‡"Externaltrigger"commandvalue.*RASETCMDEQU‡$82‡"Setpoint"commandvalue.&RASCNCMDEQU‡$83‡"Scan"commandvalue.1RAATOCMDEQU‡$84‡"Auto-rangescan"commandvalue.+RACALCMDEQU‡$85‡"Calibrate"commandvalue.1RAHISCMDEQU‡$86‡"High-speedscan"commandvalue.:RAXEQBYTEQU‡$80‡"Executefunction"command(OR-edinwith(*¦functionnumbertoformcommandbyte.)RAXEQCMDEQU‡RAXEQBYT7RASTOPITEQU‡$FF‡ValuetoputinstopbytetostopRAD.**ˆOffsetsinshared-RAM=*’(68000addressing--i.e.valuesaretwicethe6809offsets.)*RASTPBYTEQU‡0‰Stopbyte.RACMDBYTEQU‡2‰Commandbyte.#RAINTFLGEQU‡4‰Interruptflagbyte."RACSTAT‚EQU‡6‰Commandstatusbyte.#RAINTMSKEQU‡8‰Interruptmaskbyte.!(F1<98A0IFQ0YCa7i2qEy?-‰2‘5™0¡@©:±:¹6Á3É=Ñ5Ù3á0é8ñ8ù-6 -6%RAFIFOSTEQU‡10ˆStart-of-FIFOoffset."RAFIFONDEQU‡12ˆEnd-of-FIFOoffset(RANXT2GTEQU‡14ˆFIFO-next-to-getoffset.RAPRMPTREQU‡18ˆParameterptr.'RAPARAM‚EQU‡84ˆStartofparameterlist.!RATSTAT‚EQU‡502‡Self-teststatus.BRAOK2STOEQU‡508‡High-speedscan"communications"flag.‚(1=okto**¦putdata,2=oktotakedata,0=stop))RAXSTAT‚EQU‡510‡Hardwarestatusregister.***ˆTableoffsets**)*‚CCB(device-dependentsection)offsets.*;RARDLADREQU‡CCBDDP„AddrofthisRAD'sentryin'RARADLST'.ARACMDCODEQU‡RARDLADR+4ˆCommandcodeRADiscurrentlyworkingon.8RARDFLAGEQU‡RACMDCOD+1Š"Interrupt-being-serviced"flag.3RAUSRTCBEQU‡RARDFLAG+1ŠAddrofcurrentuser'sTCB.:RARTRVADEQU‡RAUSRTCB+4ŠAddrofdata-retrievalsubroutine.=RACHNUSREQU‡RARTRVAD+4ŠUserptrforchan0‚(startofchannel*¦userptrlist).?RAINSTR‚EQU‡RACHNUSR+64‰Interrupt"instruction"flag(indicates&*¦whatistobedonewhenaninterrupt$*¦occursfromthecurrentfunction).9RAJMPRRGEQU‡RAINSTR+1‹Containsvaluefromharwarejumper%*¦"register"onRADboard(loc7000)./RASHRAD‚EQU‡CCBCHBŽStartingaddrofshared-RAM.*M*============================================================================B*‚CCBoffsetsforlocationsusedbystandarddriverskeletoncode.0CCBERAD1EQU‡RAJMPRRG+1ŠErrordebugsaveaddress9CCBQVER1EQU‡CCBERAD1+4ŠEventqueuingerrordebugaddress(CCBCIDƒEQU‡CCBQVER1+4ŠCMRparamblockID*3******‚CheckfortoomuchstufftofitinCCB...‰IFGT†CCBCID+4-256%‰FAIL†499‘Abortassemblyiftoomuch.‰ENDC******** CCB flag positionsCCBFGBSYEQU‡7“ChannelbusyN*=============================================================================***‚Commandpacketoffsets**RACMDERREQU‡0“Errorreturncode" location..RAREQCMDEQU‡RACMDERR+2ŠRequestedcommandcode8RACMDPRMEQU‡RAREQCMD+2ŠStartofcommandparameterlist.** *ˆFlagvalues*:RAWRKFLGEQU‡1‰FlagsettingforRARDFLAGindicatingweare(*¦workingonaninterruptfromthisRAD.** *ˆErrorcodes*RAERR1ƒEQU‡$F0‡RADis"bad".RAERR2ƒEQU‡$F1‡RADis"busy".RANOTUSREQU‡$FF‡ThisuserisnotusingthisRADnow(triedto*œdoaRADSTP).:RAABORTDEQU‡$FB‡ThisRADwasabortedsincethisuserlast#*¦called--usermustreopenforRAD.7RASYSERREQU‡$FA‡Thisisan"extra"RAD--can'tbeused.'*¦(SYSGENwassetupfortoofewRADs.)RAOVRFLOEQU‡$FC‡FIFOoverflow.***ˆRADstatuscodes*(RAUNINITEQU‡$F000…RADisuninitialized.RASTBAD‚EQU‡$FFFF…RADis"bad".6RASTOKƒEQU‡$F0F0…RADisokandreadytotakecommands.3RASTDOINEQU‡$F001…RADisnowdoinginitialization.*** *ˆBitmasks*=RAINTBITEQU‡$C0‡Bitstocheckinstatusbyteforinterrupts..*œ(Bit7=level4int.,bit6=level3int.)*;RASUBRBTEQU‡0‰Optionbit#foruser-supplieddata-handling+*œsubroutineforwhendataforthischanis*œreceivedfromtheRAD.;RAQUEBT‚EQU‡1‰Optionbit#toqueueeventtouserwhendata)*œforthischanisreceivedfromtheRAD.=RAWAKEBTEQU‡2‰Optionbit#towakeuptheuserwhendatafor%*œthischanisreceivedfromtheRAD.**ˆMisc.constants*RARDRMNDEQU‡$D7FF…EndaddrofRADRAM(excludingshared-RAM).?RALODLNGEQU‡100‡Max#ofwordstoloadordumpthrushared-RAM*¦atonetime.*ˆsetasideintheSYSGENforusebythedriver(RAD1TBL).‚TheC*ˆdrivertakesacommandfromtheuser,passesitontothecorrect?*ˆRAD1board(wherethefirmwarewillinterpretandexecutetheD*ˆcommand),takesthedatabackfromtheRAD1,andpassesitbackto>*ˆtheuserinthemannerspecifiedbythatuser.‚Communication>*ˆbetweenthe68000andtheRAD1boardtakesplacethroughthe*ˆ256-byte-longshared-RAM.*>*ˆCodeinthisdriverisrelocatable,re-entrant,andROMable.**/*ƒENTRY:‚JSRFROMCMRHANDLER(COMMANDSERVICE) *‹JSRFROMCMRINTERRUPTHANDLER*-*ƒEXIT:-ALWAYSEXITSWITHARTSINSTRUCTION**I*========================================================================*²<<<<<<<<<<<<<<<<<<<<<<<<<<<A*ˆAssembleusingchainfileRADASM.CF‡<<<<<<<<<<<<<<<<<<<<<<<<<<<*²<<<<<<<<<<<<<<<<<<<<<<<<<<<H*-----------------------------------------------------------------------*‰PAGEJ*****************************************************************************C*‚THISISTHESERVICEVECTORTABLEWHICHISREQUIREDFORCMR-CALLED*ˆI/ODRIVERS.***L****************************************************************************** ‰SECTION8***‚ServicevectortableforCMR: RADDRVR‚EQU‡*9‰DC.L†RADISR-RADDRVR†Offsettointerruptserviceroutine.7‰DC.L†RADCMD-RADDRVR†Offsettocommandserviceroutine.6‰DC.L†RAINIT-RADDRVR†Offsettoinitializationroutine.‰DC.L†0“RESERVED***‚OtherCMRparams:!‰DC.B†0“#ofextrapagesperCCB. ‰DC.B†0,0,0 ‰DC.L†0,0,0***‚Revisioninfo.:-‰DC.B†'021783'ŒRADDRVrevisiondate(MMDDYY).*‰DC.B†''‘Patchflag(blank=nopatches).$‰DC.B†'4'‘MajorVERSAdosrevision#.*‰PAGEM*******************************************************************************ˆInitializationRoutine*5*’CalledthroughCMRonceforeachCCBwhensystemis5*’booted.‚Thisroutineinitializesthedataareaused*’bytheRADdriver.*!*ˆUponentry:‰A5=addressofCCB*8*ˆUponexit:ŠThefollowingregistercontentsarechanged%*œ(andnotrestored):ƒA0,A1,D1,D2.*M***************************************************************************** RAINITƒEQU‡*7‰MOVEA.LƒRAD1TBL,A0ŠPutaddressofRADtablearea(from*¦SYSPAR)intoA0.5‰CMPA.L„#0,A0HasmemorybeensetupforRADsonthis!‰BEQ.S…RAERRXSsystem?‚No--error.>‰CMPI.B„#RALVL4,CCBPPRIO(A5)…Isthisalevel4CCB?‚(Interrupt**¦levelsaresetinternallyas1morethan*¦actuallevel.)7‰BEQ.S…RAINRETYes--ignoreit,noinitializtionneeded."‰CLR.L…D2’No,mustbelevel3CCB.%‰MOVE.L„D2,A1ClearA1forlateruse.>‰MOVE.B„RARADUSD(A0),D2…SetupD2tocontainnumberofentries*¦inRARADLSTalreadyused.6‰CMP.B…RANUMRAD(A0),D2…Areanyentriesleftavailable?(‰BGE.S…RAERRXSNo--tableisfull--error.8‰ADDQ.B„#1,RARADUSD(A0)…Yes.‚Bumpcountofentriesused.9‰MULU†#RARDENTL,D2ˆMultiply#entriesusedbylengthof1$*¦entrytogetoffsetinRARADLSTto*¦nextavailableentry.=‰MOVEA…RARADLAD(A0),A1…PutstartaddrofRARADLSTintoA1,by4‰ADDA.L„A0,A1addingtableareastartaddrtooffset*¦toRARADLST..‰ADDA.L„D2,A1SetA1toaddrofnextavailable*¦entryinRARADLST.<‰MOVE.L„CCBMNEM(A5),(A1)„MoveRAD-IDintoRARADLSTentryfor *¦thisRAD.=‰MOVE.L„A1,RARDLADR(A5)…PutaddrofthisRAD'sRARADLSTentry *¦intoCCB.2‰CLR.B…RACMDCOD(A5)ˆInitializetherestoftheCCB*‰CLR.B…RARDFLAG(A5)ˆdevice-dependentarea.0‰LEA‡RARDFIFO(PC),A1…Setaddrfordata-retrieval8‰MOVE.L„A1,RARTRVAD(A5)…subroutinetoread-FIFOroutine.‰CLR.B…RAINSTR(A5)‰CLR.B…RAJMPRRG(A5)0‰MOVE†#16,D2ŽInitthechanneluserptrs‚(2bytes,‰LEA‡RACHNUSR(A5),A1…each--for32channels).ARAINLP4‚MOVE.L„#$F000F000,(A1)+„Setchanneluserptrsto$F000to&*¦indicatechannelscan'tbeusedyet.‰SUBQ†#1,D2Done?‰BGT‡RAINLP4No--donext.=‰MOVE.L„RARDLADR(A5),A1…Yes.‚Setadd# ressofentryinRARADLST*¦forthisRADinA1..‰MOVE†#RAUNINIT,RARDSTAT(A1)ˆSetRADstatusto)*¦"uninitialized".‚(TheRADboardwillbe'*¦initializeduponthe1stuserrequest*¦forthisRAD.)‰CLR.L…D1ˆSetD1tozero.9‰ADDQ.L„#RACHNLST,A1ˆSetptrto1stchannelforthisRAD.?‰MOVE.L„#8*RACHNLLG,D2„InitD2tobeusedasachannelcounter.1*œ(SetD2to:‚32*RACHNLLG/4,sincewewillbe0*initializingthe32channelentries4bytesat *atime.)HRAINLP1‚MOVE.L„D1,(A1)+‚InitchanneldataforthisRADinRARADLSTto0.‰SUBQ†#1,D2…Alldone?$‰BHI‡RAINLP1ƒNo--godonextchannel.RAINRET‚RTS‘Return.*;RAERRXS‚EQU‡*‰SOMETHINGISWRONG!!!‚Thisroutinewascalled#*¦moretimesthanthereareRADsin*¦thesystem!!!*;‰MOVE.B„#RASYSERR,RAINSTR(A5)‰SetaflaginCCBtoindicate&*¦thatthisRADcannotbeused--dueto%*¦aSYSGENerror,thereisnotenough'*¦roomintheRADtableareatoinclude *¦thisRAD.‰BRA‡RAINRETƒReturn‰PAGEJ***************************************************************************%*ˆTHISISTHECOMMANDSERVICEROUTINE**ƒENTRY:‚JSRFROMCMRHANDLER**‹A2-PHYSICALADDRESSOFPARAMETERBLOCK*‹A5-PHYSICALADDRESSOFCCB,*‹A6-PHYSICALADDRESSOFATTACHEDTASKTCB*5*ƒEXIT:‚RTS-PARAMETERBLOCKVALIDATIONSTATUSIND0**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A**P**PP**”A3=COMMANDPACKETPOINTER*”A6=REQUESTORTCBADDRESS***ƒCODEISRE-ENTRANT*J*************************************************************************** RADCMD„EQU„*-‰TST.B…XIOSCD(A2)ŠIstheCMRcmdsubcode=0?‰BEQ.S…IOH01110ŒYes.9‰MOVE.B„#RAERR9,D7ŠNo--error--set"illegalcommand"error,‰BSR‡IOHERCHKŒcodeandgomakeerrorreturn.*1* CHECK FOR COMMAND PACKET WITHIN TASK BOUNDARIES*CIOH01110‚MOVE.LXIOUID(A2),CCBCID(A5)SAVECMRPARAMBLOCKID(DCB) ŠCLR.L‚D5,ŠMOVE.LXIOCPK(A2),D6†ADDROFCOMMANDPACKET)ŠMOVEƒXIOPLN(A2),D5†LENGTHOFCOMMANDPKT*ŠMOVE.LCCBTASKA(A5),A1„SETUPTCBPOINTER ŠBSR„IOHADRCKŠBRA.S‚IOH01160‹GOODRETURNŠNOP—BADLENGTHRETURN%ŠMOVE.B#XSTBLN,D7‰BADADDRESSRETURN ŠBSR„IOHERCHK5IOH01160‚MOVE.LD6,A3ŽCOMMANDPACKETPHYSICALADDRESS*0* INSURE THAT COMMAND PACKET IS ON EVEN BOUNDARY* ŠBTSTƒ#0,D6ŠBEQ.S„RACOMAND6ŠMOVE.B#XSTBLN,D7‰BADCOMMANDPACKETADDR(ODDBNDRY) ŠBSR„IOHERCHK**F************************************************************************ˆCommandProcessor*2*’User'scommandisprocessedhere.‚Acheckonthe1*’desiredRAD'sstatusismade,andifthestatus0*’is"good",thecommandprocessorwillcallthe/*’appropriatesubroutinetohandlethecommand.*F***********************************************************************RACOMANDEQU‡**7‰CLR‡RACMDERR(A3)ˆClearerrorreturnlocationinuser's)*¦cmdparamtable(usedlaterasaflag).4‰CMP.B…#RASYSERR,RAINSTR(A5)‰Isthisanon-available*¦RAD(duetoSYSGENerror)?-‰BEQ‡RASKIPITŒYes--makeerrorreturntouser.-‰BSR‡RAFNDUSRŒNo.‚FindthisuserinRAUSRLST.7‰CMP.L…#RAABORTD,D0ˆWasthisRADabortedsincethelast*¦timethisusercalled?3‰BEQ‡RACMDRETŒYes--makeerrorreturn(D0isalready *¦setup).*;*’No.‚DatainD0andD1willbeusedlaterinthisroutine.*9‰MOVE†RAREQCMD(A3),D2…StorerequestedcommandcodeinD2.*‰CLR.L…D3’InitD3,whichwillbeoffsetin*¦'RAJMPTBL'forthiscommand.5‰LEA‡RACMDTBL(PC),A4…SetA4toaddrofstartoftable*¦of"legal"commandcodes.=RACMDLUPCMP.B…(A4),D2Doesrequestedcommandcodematchthis*¦tableentry?6‰BEQ.S…RAGOTCMDŒYes--continueprocessingthiscommand.‰CMP.B…#$FF,(A4)+ŠEndoftable?*‰BEQ.S…RANOSUCHŒYes--illegalcommandcode.-‰ADDQ†#4,D3Setjumptableptrtonextentry.+‰BRA‡RACMDLUPŒGobackandchecknextentry.?RANOSUCHMOVE.L„#RAERR9,D0ŠSeterrorreturnto"illegalcommand‰BRA‡RACMDRETŒcode"andreturn.ARAGOTCMDMOVE.L„RARDLADR(A5),A1…PutaddrofentryforthisRADin*¦'RARADLST'intoA1.4RACMD0ƒCMPI†#RASTBAD,RARDSTAT(A1)‰IsRADmarkedbad?‰BNE.S…R# ACMD1ŽNo.-‰MOVE.L„#RAERR1,D0ŠYes--setD0toerrorcode.‰BRA.S…RACMDRETŒGoreturn.=RACMD1ƒCMPI†#RAUNINIT,RARDSTAT(A1)ˆIsthisRADuninitialized?‰BNE.S…RACMD2ŽNo.$‰BSR‡RAINITRDŒYes--goinitializeit.‰BRA‡RACMD0ŽNowtryagain.BRACMD2ƒCMP‡#RASTDOIN,RARDSTAT(A1)‚IsRADdoinginitializationnow?*‰BEQ.S…RACMD3ŽYes--make"RADbusy"return.6‰CMPI.B„#RAOPNCMD,D2ˆAtthispoint,theRADmustbein%*¦workingcondition.‚Istherequested*¦commandan"open"?+‰BEQ.S…RADOITŽYes--godo"open"processing.8‰CMPI.B„#RACLSCMD,D2ˆIstherequestedcommanda"close"?,‰BEQ.S…RADOITŽYes--godo"close"processing..‰CMPI.B„#RASTPCMD,D2ˆIsthisa"stop"command?‰BEQ.S…RADOIT2Yes--godoit.0‰CMPI.B„#RAABTCMD,D2ˆIsthisan"abort"command?‰BEQ.S…RADOIT2Yes--godoit./‰CMP‡#RASTOK,RARDSTAT(A1)‚No.‚IsRADreadynow?'‰BEQ.S…RADOCMDYes--goprocesscommand.6RACMD3ƒMOVE.L„#RAERR2,D0ŠNo--seterrorcodeto"busy".‰BRA.S…RACMDRETŒGoreturn.ARACMD4ƒMOVE.L„#RAUSRERR,D0ˆSeterrorflagtoindicateuserisnot*¦setuptousethisRAD.‰BRA.S…RACMDRETŒGoreturn.*4RADOCMD‚EQU‡*“Atthispoint,mustbeacommandwhich)*¦actuallyusestheRADboard,sosetthe*¦RADstatustobusy.*8*’D0andD1stillcontaindatafromRAFNDUSRcallabove.*)‰TST.L…D0’IsusersetuptousethisRAD?‰BNE‡RACMD4ŽNo--error.9‰MOVE†D1,RARDSTAT(A1)…SetRADstatustouserptrforthis*¦usertoindicateRADisbusy.:‰MOVE†#1,RACMDERR(A3)…Setcmderrorcodeto1asaflagto%*¦indicatethatthiscmdusestheRAD%*¦boardandsetthestatusto"busy".3RADOIT2‚MOVE.L„A6,RAUSRTCB(A5)…Storeaddrofuser's*¦TCBinCCBforfutureuse. RADOITƒEQU‡*8‰LEA‡RAINSTBL(PC),A4…Putstartaddrofinterrupt"instr-*¦uction"table.1‰MOVE.L„D3,D0Getoffsetintothistableforthis‰ASR.L…#2,D0command.?‰MOVE.B„(A4,D0),RAINSTR(A5)Store"instruction"flaginCCBfor*¦usewheninterruptcomesin.:‰LEA‡RAJMPTBL(PC),A4…Loadaddrofstartofjumptableinto"*¦A4.‚D3stillhasoffsetforthis#*¦commandcodeintothejumptable.%*¦A3containsaddrofcommandpacket.1‰JSR‡(A4,D3)Gotocommand-processingroutinefor(*¦thiscommand.‚(NOTE:D1stillcontains*¦userptrforthisuser.)6‰TST‡RACMDERR(A3)ˆDidthiscmdsettheRADstatusflag *¦to"busy"?‰BEQ.S…RACMDRETŒNo--goreturn. ‰TST‡D0’Yes.‚Wasthereanerror?‰BEQ.S…RACMDRETŒNo--goreturn.,‰BSR‡RACLRSTAŒYes--goclearRADstatusflag.*ARACMDRETMOVE†D0,RACMDERR(A3)…Puterrorreturncodeinuser'scmd*¦paramtable.!‰RTS›Returnfromcommandhandler.*?RASKIPITMOVE.L„#RASYSERR,D0ˆSetD0toindicate"can'tusethis*¦RAD"(duetoSYSGENerror).‰BRA‡RACMDRETŒReturntouser.*D*-------------------------------------------------------------------D*ˆCommandtable,jumptable,and"interruptinstruction"flagtable.2*’(Entriesinthesethreetablesmustcorrespond.)*9RAJMPTBLBRA.L…RARADSTPŒJumptable--allentriesmustbe6‰BRA.L…RARADLODŒlongbranchestoappropriateroutines.‰BRA.L…RARADDMP‰BRA.L…RARADJMP‰BRA.L…RARADTSTŒ(5thentry)‰BRA.L…RARADEXT‰BRA.L…RARADSET‰BRA.L…RARADSCN‰BRA.L…RARADATO‰BRA.L…RARADCALŒ(10thentry)‰BRA.L…RARADOPN‰BRA.L…RARADCLS‰BRA.L…RARADXEQ‰BRA.L…RARADABT‰BRA.L…RARADHISŒ(15thentry)**--------------------------*4RACMDTBLDC.B†RASTPCMDŒTableoflegalcommandcodes.2‰DC.B†RALODCMDŒEachentryisonebytelong;‚endof4‰DC.B†RADMPCMDŒtableisindicatedby$FF,whichmust.‰DC.B†RAJMPCMDŒNOTbeavalidcode,ofcourse.‰DC.B†RATSTCMDŒ(5thentry)‰DC.B†RAEXTCMD‰DC.B†RASETCMD‰DC.B†RASCNCMD‰DC.B†RAATOCMD‰DC.B†RACALCMDŒ(10thentry)‰DC.B†RAOPNCMD‰DC.B†RACLSCMD‰DC.B†RAXEQCMD‰DC.B†RAABTCMD‰DC.B†RAHISCMDŒ(15thentry)‰DC.B†$FF‘Endoftable.**----------------------------*7RAINSTBLDC.B†1‰Tableof"instruction"flagswhichtell-‰DC.B†1‰thedriverwhatistobedonewhenan-‰DC.B†1‰interruptcomesinforthisfunction.4‰DC.B†2‰(1=Put"task"intoREADYstate;i.e.,turn)‰DC.B†1“cmdhandlerforthiscmdbackon.+‰DC.B†2Š$ 2=Calldata-retrievalsubroutine.4‰DC.B†2Š0=Don'tdoanythingspecial--justturnoff,‰DC.B†2“theinterruptandreturn.‚(Shouldn't#‰DC.B†2“getaninterruptonthese.)‰DC.B†1‰(10thentry)‰DC.B†0‰DC.B†1‰DC.B†2‰DC.B†1‰DC.B†0‰(15thentry)*‰DSˆ0‰(SetPCtoevenaddress.)‰PAGE** ERROR ROUTINE*IOHERCHK‚EQU„* ŠCLR.L‚D0ŠMOVE.BD7,D0ŽVALIDATIONSTATUS2ŠMOVE.L(A7)+,CCBERAD1(A5)SAVEDBUGERRORADDRESSŠBRA†RACMDRET‰GETOUTOFHEREŠPAGE;************************************************************$*ˆSubroutinetohandleRADOPNcalls.*3*’Thisroutine"opens"thedesiredchannelsforuse*’bythisuser.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP*;***********************************************************RARADOPNEQU‡*8‰BSR‡RAFNDUSR‚Checkuserlisttoseeiftherealreadyis*¦andentryforthisuser-RAD*¦combinationinRAUSRLST.6‰MOVE.L„RAD1TBL,A1ŠSetA1tostartaddroftablearea.‰TST‡D0ˆIsthereanentry?(‰BEQ.S…RAOPGOT1‚Yes--usethesameentry.+‰CLR.L…D2ˆNo--putthiscomb.intoRAUSRLST.7‰MOVE†RAUSRLNX(A1),D2…Putnext-availentryptrintoD2.4‰CMP‡#$FFFF,D2‹IsthereanavailableRAUSRLSTentry?‰BEQ‡RAOPNORMŒNo--error.***¦Yes--calculateaddrofnextavailentry.5‰MOVE.L„D2,D1Storenextavailentry#forlateruse.*‰MULU†#RAULNG,D2ŠMultiplybyentrylength.9‰LEA‡RAUSRLST(A1),A4…LoadstartaddrofRAUSRLSTintoA4.2‰ADDA.L„D2,A4SetA4tostartaddrofavailentry.:‰MOVE†RAURADID(A4),RAUSRLNX(A1)…Moveptrtothenextavail(*¦entry(whichwasstoredinthe1sttwo'*¦bytesoftheRAD-IDfieldofRAUSRLST#*¦entry)intoheaderoftablearea.8‰MOVE.L„TCBNAME(A6),RAUUSRNO(A4)†Storeuser#andRAD-ID6‰MOVE.L„TCBSESSN(A6),RAUUSRNO+4(A4)ƒintothisentryin*‰MOVE.L„CCBMNEM(A5),RAURADID(A4)†RAUSRLST.>RAOPGOT1EQU‡*‰Atthispoint,D1containstheptrtotheentry*¦forthisuserinRAUSRLST.‚A3"*¦containsaddrofcommandpacket.:‰MOVE†#RAUNORET,D0ˆInitD0toerrorcodefor"userhasnot$*¦specifiederror-reportingoption"./‰MOVE.L„D1,D3SetD3touserptrforthisuser.9‰MULU†#RAULNG,D3ŠMultiplybylengthofanRAUSRLSTentry.6‰MOVE.L„RAD1TBL,A1ŠSetA1tostartaddroftablearea.8‰LEA‡RAUSRLST(A1),A1…PutstartaddrofRAUSRLSTintoA1.4‰ADD.L…D3,A1A1nowcontainstheaddrofthisuser's*¦entryinRAUSRLST.:‰TST‡RAUEROPT(A1)ˆHaserror-reportingoptionforthisuser‰BEQ.S…RAOP2beenset?‚No. ‰CLR.L…D0’Yes--clearerrorflag.ARAOP2„MOVE†RACMDPRM(A3),D2…Put#chan's(fromparamtable)inD2."‰BNE.S…RAOP3Ifnot0,thengoon.:‰MOVE.L„#RAERR4,D0ŠSetD0to"parameter-table-error"code.‰BRA‡RAOPRETGoreturn.@RAOP3„LEA‡RACMDPRM+2(A3),A4ƒSetA4tostartaddrofchandatain*¦commandparamtable./RAOPLUP1CLR.L…D3’Putrequestedchan#intoD3.‰MOVE.B„1(A4),D3‰CMPI.B„#$1F,D3Validchan#?‰BLS.S…RAOP4Yes.5‰CMP.B…#$FF,D3No--isthistheerror-reportingoption*¦specification?6‰BNE‡RAOPERR1ŒNo--invalidchan#.Gotoerrorroutine.+‰MOVE†2(A4),D4ŒYes.‚Checktheoptionsflag.%‰AND.L…#7,D4Areanyoptionbitsset?(‰BEQ‡RAOPERR1ŒNo--nooptionsset--error. ‰CLR.L…D0’Yes--clearerrorflag.‰BRA.S…RAOPOKXDonextchan.3RAOP4„ASL‡#1,D3Doublechan#tobeusedasoffset.8‰CMPI†#$FFFF,RACHNUSR(A5,D3)ˆChecktheuserptrforthis)*¤chan(inCCB).‚Isthischanunassigned?‰BEQ.S…RAOPOK1Yes--it'sok.?‰CMP‡RACHNUSR(A5,D3),D1‚No.‚Isitalready"owned"bythisuser?3‰BNE.S…RAOPERR2ŒNo--thischanbelongstosomeother*¦user.‚Gotoerrorroutine.4‰MOVE.B„#1,(A4)Yes--setupperbyteofchan#incmd(*¦paramtableto1toindicatethischan#*¦wasalready"owned"bythisuser.'*¦(Thiswillbeusedifanerroroccurs'*¦sothattheuserptrwon'tbereset.)HRAOPOK1‚MOVE†D1,RACHNUSR(A5,D3)‚Setuserptrforthischantothisuser.RAOPERR1MOVE.L„#RAOPILL,D0‰SetD0toindicateillegalchan#.0‰BRA.S…RAOPERR3ŒGoresetuserptrs.forprevious*¦channelsincmdparamlist.CRAOPERR2MOVE.L„#RAOPUNAV,D0ˆSetD0toindicateunavailablechan#.*1RAOPERR3EQU‡*“Clearanyuserptrswhichwereset'*¦whileprocessingthiscallbeforethe*¦errorwasdetected.9‰LEA‡RACMDPRM+2(A3),A4ƒSetA4tostartofchan#'sincmd *¦paramlist.9‰MOVE†RACMDPRM(A3),D4…Store#ofchansincmdparamlist.7RAOPERLPCMP‡D2,D4Havewegonethrualltheentrieswe(*¦wentthrubefore?‚(Quitwhenwegetto'*¦thesamechan#wegottheerroron.)%‰BEQ‡RAOPRETYes--that'sall--return.#‰SUBQ†#1,D4No--deccountofchans.<‰TST.B…(A4)†Wasthischanassignedtouserbeforethiscall?(‰BEQ.S…RAOPERR4‚No--mustclearuserptr.;‰CLR.B…(A4)†Yes--leaveassignmentalone.‚Justclear"flag"./‰BRA.S…RAOPERR5‚Setuptodonextchaninlist./RAOPERR4CLR.L…D3ˆClearuserptrforthischan.$‰MOVE.B„1(A4),D3‚Putchan#intoD3.:‰ASL‡#1,D3…DoubleittogiveoffsetintochanlistinCCB.5‰MOVE†#$FFFF,RACHNUSR(A5,D3)ˆSetthischantounused.GRAOPERR5ADDA.L„#12,A4„SetA4toaddrofnextchan#incmdparamlist.'‰BRA‡RAOPERLP‚Gobackanddonextchan.**?RAOPNORMMOVE.L„#RAOPNOMO,D0ˆSetD0toindicatenoroomforany*¦moreuser-RADcombinations.‰BRA‡RAOPRETReturn.*‰PAGEK****************************************************************************)*ˆSubroutinetoinitializetheRADboard.9*’(SendsaDUMPcommandtoRADandchecksforcompletion.3*’IfRADrespondscorrectly,setschanuserptrsto5*’"available"statusandsetsRADstatusto"ready".)*,*’Calledfromthecommandprocessorroutine.*7*ˆUponentry:‰A1=addrofthisRAD'sentryinRARADLST*œA5=CCBaddr**ˆUponreturn:**œ01234567*˜D:‚PPPP*****˜A:‚*PPP*PP**K***************************************************************************RAINITRDEQU‡*-‰MOVEM.LƒD0-D3,-(A7)‰Storeregistercontents.;‰MOVE†#RASTDOIN,RARDSTAT(A1)‚SetRADstatusto"busy--doing*¦initialization".6‰MOVE†#RAINNTRY,D4ˆSetD4tomax#oftimestotryfor$*¦asuccessfulresponsefromtheRAD"*¦beforedeclaringtheRAD"dead".ARAINRD2‚MOVE.L„RASHRAD(A5),A4†SetA4tostartaddrofshared-RAM.=‰BTST.B„#7,RAXSTAT(A4)†IsRADdonewithpoweruproutineyet?6‰BNE.S…RAINRDEDŒNo--shouldhavebeen,somethingwrong.=‰MOVE.B„#RAPARAM/2,RAPRMPTR(A4)‡Yes.‚Setparamptrinshared-&*¦RAMtooffsetinshared-RAMtoparam%*¦area(us% ingRAD-addressingoffset).8‰CLR.B…RAINTMSK(A4)ˆSetinterruptmasktonointerrupts.<‰MOVE.B„#RADMPCMD,RACMDBYT(A4)ˆPutDUMPcommandintocommand)*¦byteinshared-RAM.‚Thiswillstartthe*¦"RAD-initialize"dump.6‰BSR.S…RAWAITŽWaitfor10millisecbeforecheckingfor*¦responsefromRAD.2‰CMPI.B„#$81,RACSTAT(A4)„Isinitialdumpcomplete?$‰BNE.S…RAINRDEDŒNo--somethingwrong.,‰MOVEP.LƒRAPARAM(A4),D3†Yes.‚Checkresponse.8‰CMP.L…#RABNGRAD,D3ˆIsdumpok(i.e.,wasfirstlongword*¦correct--shouldbe"!RAD")?$‰BNE.S…RAINRDEDŒNo--somethingwrong.:‰MOVE.B„RAPARAM+8(A4),RAJMPRRG(A5)ˆYes--storeRAD"jumper"*¦datafromdumpinCCBloc.(‰MOVE.L„#16,D3ŽSetcounterforchannels.@‰BTST.B„#5,RAJMPRRG(A5)…IsRADboardjumperedfor16chanor32?‰BNE.S…RAINRD316channels.3‰MOVE.L„#32,D3Ž32channels--setchancounterto32.CRAINRD3‚LEA‡RACHNUSR(A5),A4…PutstartaddrofchanuserptrsinA4.GRAINRDLPMOVE.L„#$FFFFFFFF,(A4)+„Setchanptrto"unused"(2chansata‰SUBQ†#2,D3time).‚Alldone?‰BGT‡RAINRDLPŒNo--godonext.B‰MOVE†#RASTOK,RARDSTAT(A1)Yes--setRADstatustook(andunused).7RAINRDRTMOVEM.Lƒ(A7)+,D0-D3‰Restoreregistercontents. ‰RTS›Return.**:RAINRDEDSUBQ†#1,D4RADdidnotrespondcorrectly.‚Havewe*¦triedenoughtimes?*‰BLE.S…RAINRBADŒYes--gomarkthisRADbad.(‰BSR.S…RAWAITŽNo--delayfor10millisec.‰BRA‡RAINRD2Gotryitagain.9RAINRBADMOVE†#RASTBAD,RARDSTAT(A1)‰RADisnotresponding&*¦correctly--setRADstatusto"dead".‰BRA‡RAINRDRTŒReturn.*G* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*.RAWAITƒEQU‡*‰Routinetodelay10milliseconds.*-‰MOVEM.LƒD2/A1,-(A7)‰Storeregistercontents.7‰MOVE.L„#RANREQ,D3ŠSetD3tomax#oftimesto"request%*¦periodicactivation"unsuccessfully&*¦beforegivingupandjustreturning.ARAWAIT1‚LEA‡RADLAY(PC),A0‡Setupforperiodicactivationroutine.%*¦RADLAYistheroutinewhichwillbe)*¦turnedonattheendof10msec.,which&*¦will,inturn,reactivatethistask.%‰MOVE.L„#10,A1ŽSetdelayfor10msec.2‰CLR.L…D1’Settorequestactivationonetimeonly.:‰MOVE.B„CCBPPRIO(A5),D1…Setpriorityofactivationtosame*¦priorityasthistaskhas.1‰MOVE.L„A6,D2PutTCBaddrintoD2,tobeusedas *¦requestID.2‰TR0$.RQPA‚,’Trapto"requestperiodicactivation" *¦routine.%‰BRA.S…RAWAITOKŒRequestwasaccepted.0‰SUBQ†#1,D3Requestwasdenied.‚Havewetriedit*¦enoughtimes?#‰BGT‡RAWAIT1No--tryrequestagain.,‰BRA.S…RAWAITRTŒYes--forgetit--justreturn.9RAWAITOKTR0$.PAUSE,’Waitfor10msec.tobeup.‚(RADLAY(*¦willthenbe"turnedon"andwillthen*¦restartthistaskhere.)7RAWAITRTMOVEM.L„(A7)+,D2/A1ˆRestoreregistercontents. ‰RTS›Return.*M*‚======================================*2RADLAYƒEQU‡*“Routinetore-activatedriverroutine#*¦afteradelaymadeusing"request*¦periodicactivation"routine.*3‰MOVE.L„D1,A0D1containsTCBaddrwhichwaspassed&*¦asrequestIDtoperiodicactivation%*¦routine.‚PutitinA0astasktobe*¦turnedbackon.*‰TR0$.READY,’Puttaskinto"ready"state.%‰RTE›Returnfromperiodicactivation.**‰PAGE:***********************************************************$*ˆSubroutinetohandleRADSETcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**:**********************************************************3RARADSETEQU‡*‰Routinetosetupforsetpointscan.:‰MOVE†RACMDPRM+2(A3),D4ƒPut#ofnon-setpointchansinD4.:‰LEA‡RACMDPRM+4(A3),A4ƒSetA4toaddrofstartofchansin*¦cmdparamtable. ‰CLR.L…D35‰MOVE†RAPARAM(A3),D3†Put#ofsetpointchansintoD3.0‰MULU†#6,D3Calculate#bytesforsetptchansin*¦cmdparamtable.1‰ADD.L…D3,A4S% etA4tostartaddrofnon-setpoint*¦chansincmdparamtable.3‰MOVE.L„#2,D3SetD3toaddrincrementtonextchan *¦inlist.6‰BSR‡RACHKCHNŒGocheckthesechanstobesuretheyare*¦"owned"bythisuser.‰TST.L…D0’Allok?3‰BNE.S…RASETRETŒNo,error--makeerrorreturn(D0is#*¦alreadysettoerrorflagvalue).*‰CLR.L…D4ˆPut#ofsetpointchansintoD4.‰MOVE†RACMDPRM(A3),D47‰LEA‡RACMDPRM+4(A3),A4ƒSetA4tostartaddrofsetpoint*¦chansincmdparamlist..‰MOVE.L„#6,D3SetD3toaddrincrementtonext*¦setpointchan#inlist.1‰BSR‡RACHKCHNŒGochecksetpointchanstoseethat*¦they"belong"tothisuser.‰TST.L…D0’Dothey?4‰BNE.S…RASETRETŒNo,error--return(D0containserror*¦codealready).8‰MULU†#3,D4…Multiplyby3togive#ofwordsofsetpoint*¦chandatainparamtable.3‰ADD‡RACMDPRM+2(A3),D4„Add#ofnon-setpointchans./‰ADD‡#2,D4Add2forthecountstogivetotal#*¦ofwordsinparamtable. ‰MOVE†D4,D3Store#wordsinD3.'‰ADDQ†#1,D4Add1for#-of-wordscount.;‰ASL‡#1,D4…DoubleD4togive#bytestomovetoshared-RAM.:‰LEA‡RACMDPRM-2(A3),A4…SetA4tostartaddrofparams(1st**¦2bytesaregarbage--willbesetlater.)2‰BSR‡RAMOVPRMŒPuttheparamtableintoshared-RAM.8‰MOVEP…D3,RAPARAM(A1)†Set#ofwordsinshared-RAMparam*¦table.2‰CLR.B…RACSTAT(A1)‰Clearcmdstatusinshared-RAM.;‰MOVE.B„#5,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto)*¦interruptatendofscanorendofcmd.8‰MOVE.B„#RASETCMD,RACMDCOD(A5)ˆStorecmdcodeinCCBfor *¦lateruse.<‰MOVE.B„#RASETCMD,RACMDBYT(A1)ˆStorecmdcodeincmdbyteof,*£shared-RAMtostartexecutionoffunction./‰CLR.L…D0’ClearD0toindicatesuccessfulstart*¦ofsetpointcmd.RASETRETEQU‡**‰RTS›Returnandwaitfor"done"interrupt.‰PAGE K****************************************************************************$*ˆSubroutinetohandleRADSCNcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**K***************************************************************************RARADSCNEQU‡****+‰MOVE†RACMDPRM+2(A3),D4ƒMove#chanstodo.7‰LEA‡RACMDPRM+4(A3),A4ƒSetA4toaddrofchan#sincmd*¦paramtable.0‰MOVE.L„#2,D3Setincrementvaluetonextchan# *¦inlist.1‰BSR‡RACHKCHNŒCheckrequestedchan#stoseethat!*¦theyall"belong"tothisuser.‰TST.L…D0’Dothey?2‰BNE.S…RASCNRETŒNo--makeerrorreturn.‚(D0already*¦containserrorcode.)1‰ADDQ†#2,D4Add2togive#ofwordstomoveinto4‰ASL.L…#1,D4paramarea;thendoubletoget#bytes.9‰LEA‡RACMDPRM(A3),A4…SetA4tostartaddrofparamstobe*¦putintoshared-RAM./‰BSR‡RAMOVPRMŒMoveparamtableintoshared-RAM.3‰LEA‡RAPARAM(A1),A4†SetA4toaddrinshared-RAMof*¦paramtable.-‰MOVE†RACMDPRM+2(A3),D4ƒSetD4to#ofchans.&‰ADDQ†#1,D4Add1togive#ofparams.6‰MOVE.B„(A4),4(A4)ŠRearrangeparamtableinshared-RAM9‰MOVE.B„2(A4),6(A4)‰forRADfirmware.‚Put#paramsfirst,&*¦followedbydelaylength.‚(Notethat2‰MOVEP…D4,0(A4)Œ68000addressesshared-RAMononly*¦everyotherbyte.);‰CLR.B…RACSTAT(A1)‰Clearcommandstatusbyteinshared-RAM.=‰MOVE.B„#5,RAINTMSK(A1)…Setinterruptmaskbyteinshared-RAM!*¦forinterruptonend-of-scanor*¦end-of-command.C‰MOVE.B„#RASCNCMD,RACMDCOD(A5)‚StorecmdcodeinCCBforlateruse.:‰MOVE.B„#RASCNCMD,RACMDBYT(A1)ˆSetcommandbyteinshared-#*¦RAMtoexecutescanningfunction.8‰CLR.L…D0ˆClearD0toindicatesuccessfulstartofscan.RASCNRETEQU‡**‰RTS‘Returnandwaitfor"done"interrupt.‰PAGEL*****************************************************************************$*ˆSubroutinetohandleRADEXTcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponret& urn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**L****************************************************************************?RARADEXTEQU‡*‰Routinetosetupforexternaltriggerfunction.1‰MOVE†RACMDPRM(A3),D4…SetD4to#ofchanstodo.5‰LEA‡RACMDPRM+2(A3),A4ƒPutaddrofchan#listinA4.1‰MOVE.L„#2,D3SetD2toincrementtonextchan#.0‰BSR‡RACHKCHNŒCheckchan#stoseethattheyall*¦"belong"tothisuser.‰TST.L…D0’Dothey?3‰BNE.S…RAEXTRETŒNo,makeerrorreturn.‚(D0contains*¦correcterrorcode.),‰ADDQ†#1,D4Addoneto#ofchansforcount..‰ASL.L…#1,D4Doubletogive#bytestobesent *¦totheRAD.7‰LEA‡RACMDPRM(A3),A4…SetA4toaddrofparamstobeput!*¦intoparamtableinshared-RAM.*‰BSR‡RAMOVPRMŒMoveparamsintoshared-RAM.7‰CLR.B…RACSTAT(A1)‰Clearcmdstatusbyteinshared-RAM.;‰MOVE.B„#5,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto)*¦interruptonendofscanorendofcmd.C‰MOVE.B„#RAEXTCMD,RACMDCOD(A5)‚StorecmdcodeinCCBforlateruse.<‰MOVE.B„#RAEXTCMD,RACMDBYT(A1)‚Putcmdcodeintocmdbytein,*¤shared-RAMtostartexecutionoffunction.<‰CLR.L…D0ˆClearD0toindicatesuccessfulstartoffunction.RAEXTRETEQU‡*#‰RTS›Returnandwaitforinterrupt.‰PAGEN*******************************************************************************$*ˆSubroutinetohandleRADATOcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**N******************************************************************************5RARADATOEQU‡*‰Routinetosetupforauto-rangescan.*‰MOVE†RACMDPRM(A3),D4…Move#chantoscan.5‰LEA‡RACMDPRM+2(A3),A4ƒPutaddrofchanlistintoA4.6‰MOVE.L„#2,D3SetD3toaddrincrementtonextchan#.0‰BSR‡RACHKCHNŒCheckchan#stoseethattheyall*¦"belong"tothisuser.‰TST.L…D0’Dothey?3‰BNE.S…RAATORETŒNo,makeerrorreturn.‚(D0contains*¦correcterrorcode.)1‰ADDQ†#1,D4…Add1to#ofchanstoincludecount.;‰ASL‡#1,D4…Doubletogive#bytesofparamstosendtoRAD.:‰LEA‡RACMDPRM(A3),A4…SetA4toaddrofparamstobemoved.-‰BSR‡RAMOVPRMŒMoveparamtabletoshared-RAM.7‰CLR.B…RACSTAT(A1)‰Clearcmdstatusbyteinshared-RAM.@‰MOVE.B„#5,RAINTMSK(A1)…Setinterruptmaskbyteinshared-RAMto)*¦interruptonendofscanorendofcmd.C‰MOVE.B„#RAATOCMD,RACMDCOD(A5)‚StorecmdcodeinCCBforlateruse.B‰MOVE.B„#RAATOCMD,RACMDBYT(A1)‚Setcmdbyteinshared-RAMtostart*¦auto-rangescanningfunction.<‰CLR.L…D0ˆClearD0toindicatesuccessfulstartoffunction.RAATORETEQU‡*#‰RTS›Returnandwaitforinterrupt.‰PAGEN*******************************************************************************$*ˆSubroutinetohandleRADHIScalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**N******************************************************************************5RARADHISEQU‡*‰Routinetosetupforhigh-speedscan.,‰CLR.L…D3’Setuptocheckchan#toseethat(‰MOVE.L„#1,D4it"belongs"tothisuser.5‰LEA‡RACMDPRM+4(A3),A4ƒSetA4toaddrofchan"list".‰BSR‡RACHKCHNŒGocheckchan#./‰TST.L…D0’Doesthischan"belong"tothisuser?2‰BNE.S…RAHISRETŒNo--makeerrorreturn.‚(D0already*¦containscorrecterrorcode.);‰TST.L…RACMDPRM(A3)ˆIsthereauser-supplieddata-retrieval *¦subroutine?‰BEQ.S…RAHIS2ŽNo--error.?‰MOVE.L„RASHRAD(A5),A1†Yes--setA1tostartaddrofshared-RAM.:‰CLR.B…RAPARAM(A1)‰Move$0001into1stwordofparamtable'‰MOVE.B„#1,RAPARAM+2(A1)„inshared-RAM.B‰MOVE.B„RACMDPRM+4(A3),RAPAR& AM+4(A1)‚Putchan#tobescannedinto?‰MOVE.B„RACMDPRM+5(A3),RAPARAM+6(A1)‚paramtableinshared-RAM.<‰MOVE.B„#RAPARAM/2,RAPRMPTR(A1)‡Putoffsettoparamtablein)*¦shared-RAM(6809addressing)intoparam*¦ptrinshared-RAM.7‰CLR.B…RACSTAT(A1)‰Clearcmdstatusbyteinshared-RAM.9‰CLR.B…RAINTMSK(A1)ˆSetinterruptmaskinshared-RAMto0*¦toindicatenointerrupts.>‰MOVE.B„#1,RAOK2STO(A1)…Set"oktostorenextconversion"flag*¦inshared-RAM.8‰MOVE.B„#RAHISCMD,RACMDCOD(A5)ˆStorecmdcodeinCCBfor *¦lateruse.<‰MOVE.B„#RAHISCMD,RACMDBYT(A1)ˆSetcmdbyteinshared-RAMto%*¦beginexecutionofhigh-speedscan.<‰MOVE.L„RACMDPRM(A3),A2…Gotouser-supplieddata-acquisition=‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒroutineafterstoringallregister.‰JSR‡(A2)contents.‚Thisroutinewilltakeall(*¦thedesireddataandwillreturnafter(*¦havingstoppedthehigh-speedscanning *¦function.5‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestoreregistercontents.4‰CLR.L…D0‡ClearD0indicateasuccessfulcompletion.RAHISRETEQU‡* ‰RTS›Return..RAHIS2ƒMOVE.L„#RAERR4,D0ŠSeterrorcodeinD0.‰BRA‡RAHISRETŒGoreturn.‰PAGEN*******************************************************************************$*ˆSubroutinetohandleRADJMPcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**N******************************************************************************>RARADJMPEQU‡*‰Routinetosetupforjump-to-RAD-addrcommand.9‰MOVE.B„#RAJMPCMD,D1ˆSetD1tocmdcodeforjumpcommand.=‰LEA‡RACMDPRM(A3),A4…SetA4tostartaddrofcmdparamtable.4‰BRA.S…RAXEQ2ŽGoto2ndentryinRARADXEQ.‚(Jumpand)*¦execute-functionroutineshavethesame*¦set-upforrunning.)‰PAGEL*****************************************************************************$*ˆSubroutinetohandleRADXEQcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**L****************************************************************************>RARADXEQEQU‡*‰Routinetosetupforexecute-functioncommand.>‰MOVE.B„RACMDPRM+1(A3),D1…SetD1tofunction#tobeexecuted.5‰OR.B†#RAXEQBYT,D1ˆSetthe"executefunction"cmdbit*¦togetthecommandcode.<‰LEA‡RACMDPRM+2(A3),A4ƒSetA4toaddrofrestoftheparams.*M*============================================================================K*=============‚RAXEQ2isa2ndentrypointintothisroutine.‚=============>*=============…(ItisusedbyRARADJMProutine.)Œ=============*9RAXEQ2ƒTST.L…(A4)†Isthereauser-supplieddata-retrieval*¦subroutinespecified?2‰BEQ.S…RAXEQ3„No--useread-FIFOroutine(default).>‰MOVE.L„(A4),RARTRVAD(A5)ƒYes--storeaddrofsubroutineinCCB*¦forlateruse.BRAXEQ3ƒADDQ.L„#6,A4…SetA4tostartofparamstobepassedtoRAD.1‰MOVE†(A4),D4ƒSetD4to#ofparamstobepassed.(‰ADDQ†#1,D4…Add1toincludewordcount.<‰ASL‡#1,D4…Doubletogive#bytestobemovedtoshared-RAM.9‰BSR‡RAMOVPRM‚Moveparamsintoparamtableinshared-RAM.9‰MOVE.B„-1(A4),RAINTMSK(A1)‹Setinterruptmaskinshared-*¦RAMasspecifiedbytheuser.7‰CLR.B…RACSTAT(A1)‰Clearcmdstatusbyteinshared-RAM.<‰MOVE.B„D1,RACMDCOD(A5)…StorecmdcodeinCCBforlateruse.;‰MOVE.B„D1,RACMDBYT(A1)…Setcmdbyteinshared-RAMtostart*¦executionofdesiredcommand.<‰CLR.L…D0ˆClearD0toindicatesuccessfulstartoffunction.‰RTS›Returnandwaitfordata.‰PAGEM******************************************************************************$*ˆSubroutinetohandleRADSTPcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=c' ommandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**M*****************************************************************************>RARADSTPEQU‡*‰Routinetostopthisuser'sfunctionrunningon*¦theRADboard.1‰BSR‡RAFNDUSR‚Findthisuser'sentryinRAUSRLST.%‰TST‡D0ˆIsthisuser/RADinRAUSRLST?‰BNE.S…RASTPER1‚No--error.9‰MOVE.L„RARDLADR(A5),A1…Yes.‚PutaddrofthisRAD'sentry*¦inRARADLSTintoA1.4‰CMP‡RARDSTAT(A1),D1…(D1containsuserptr.)‚Isthis*¦userusingthisRADnow?‰BNE.S…RASTPER1ŒNo--error.;‰MOVE.L„RASHRAD(A5),A1†Yes.‚SetA1tostartaddrofshared-*¦RAM.7‰CLR.B…RACSTAT(A1)‰Clearcmdstatusbyteinshared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto#*¦interruptwhencommandcompletes.:‰MOVE.B„#RASTOPIT,RASTPBYT(A1)ˆSetstopbyteinshared-RAM*¦tostopRADprocessing.&‰TR0$.PAUSEŠ,‰Waitfordoneinterrupt.K*>>>>>>>>>>>>>>>>‚Returnherefrominterrupt.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'‰CMP.B…#$84,RACSTAT(A1)„RADstoppedok?‰BNE.S…RASTPERRŒNo--error.7‰MOVE.L„RARTRVAD(A5),A2…Yes.‚Getaddrofdata-retrieval>‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒroutineandgetwhateverdatathere‰JSR‡(A2)isinshared-RAM.5‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestoreregistercontents.7‰MOVE.L„RARDLADR(A5),A1…PutaddrofthisRAD'sentryin*¦RARADLSTintoA1.4‰MOVE†#RASTOK,RARDSTAT(A1)ŠSetRADstatustounused./‰LEA‡RARDFIFO(PC),A1…Setaddrofdata-retrieval4‰MOVE.L„A1,RARTRVAD(A5)…subroutinetoRARDFIFOaddr./‰CLR.L…D0ˆClearD0toindicatesuccessfulstop.RASTPRETEQU‡*‰RTS‘Returntouser.7RASTPERRBSR‡RAEXERRSet"executionerror"valueinD0.‰BRA‡RASTPRETŒGoreturn.>RASTPER1MOVE.L„#RANOTUSR,D0ˆSet"thisusernotusingRADnow"'‰BRA‡RASTPRETŒerrorflagandgoreturn.‰PAGEM******************************************************************************$*ˆSubroutinetohandleRADCLScalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**M*****************************************************************************:RARADCLSEQU‡*‰RoutinetocloseRADfromusebythisuser.?‰BSR‡RAFNDUSR‚Findthisuser'sentry(w/thisRAD)inRAUSRLST.,‰TST‡D0ˆWasthisuser/RADcombinationfound?‰BNE.S…RACLSERR‚No--error.<‰MOVE.L„RARDLADR(A5),A2…Yes--D1containsuserptr.‚SetA2to'*¦addrofthisRAD'sentryinRARADLST.5‰CMP‡RARDSTAT(A2),D1…IsthisuserusingthisRADnow?‰BNE.S…RACLS2ŽNo.9‰MOVE.L„RASHRAD(A5),A1†Yes--stopfunctionrunninginRAD.%*¦SetA1tostartaddrofshared-RAM.9‰MOVE†#1,RACMDERR(A3)…Seterrorreturnlocationinuser's&*¦cmdtabletoindicatethatthisuser'*¦isstoppingtheRADboard,sotheRAD'*¦statuswillbesetto"ok"whendone.2‰CLR.B…RACSTAT(A1)‰Clearcmdstatusinshared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto*¦interruptatendofcmd.:‰MOVE.B„#RASTOPIT,RASTPBYT(A1)ˆSetstopbyteinshared-RAM*¦tostopRADprocessing.&‰TR0$.PAUSEŠ,‰Waitfprdoneinterrupt.=*>>>>>>>>>>>> Return here from interrupt. <<<<<<<<<<<<<<<<<<<(‰CMP.B…#$84,RACSTAT(A1)„DidRADstopok?0‰BNE.S…RACLSER2ŒNo--somekindoferroroccurred.4RACLS2ƒMOVE†#32,D2ŽYes.‚Closeallthisuser'schans.5‰LEA‡RACHNUSR(A5),A1…SetA1toaddrofuserpointers.:RACLSLUPCMP‡(A1),D1Doesthischan"belong"tothisuser? ‰BNE.S…RACLS3ŽNo--gochecknext.0‰MOVE†#$FFFF,(A1)‰Yes--setthischanuserptrto*¦"unassigned"status.9RACLS3ƒADD.L…#2,A1BumpA1topttonextchan'suserptr.‰SUBQ†#1,D2Alldone?‰BGT‡RACLSLUPŒNo--godonext.2‰MOVE†D1,D2Yes.‚Storeuserptrforthisuser/RAD.:‰MULU†#RAULNG,D1ˆDeletethisuser/RADentryfromRAUSRLST.0‰MOVE.L„RAD1TBL,A1ŠPutaddrofRAUSRLST' intoA2.‰LEA‡RAUSRLST(A1),A2<‰CLR.L…RAUUSRNO(A2,D1)…Clearuser#,RAD-ID,anduserstatus+‰CLR.L…RAUUSRNO+4(A2,D1)ƒforthisuser/RAD.‰CLR.L…RAURADID(A2,D1)‰CLR‡RAUSTAT(A2,D1)A‰MOVE†RAUSRLNX(A1),RAURADID(A2,D1)‚Putptrtonextavailentryin,*¤RAUSRLSTinto1st2bytesofRAD-IDfield.=‰MOVE†D2,RAUSRLNX(A1)…Setnext-avail-entryptrtothisentry.0‰CLR.L…D0’ClearD0toindicatesuccessfulclose.RACLSRETEQU‡*3‰TST‡RACMDERR(A3)ˆDidthisuserstoptheRADboard?‰BEQ.S…RACLSRT2ŒNo--goreturn.'‰BSR‡RACLRSTAŒYes--goclearRADstatus.RACLSRT2EQU‡* ‰RTS›Return.BRACLSERRMOVE.L„#RAUSRERR,D0ˆSet"thisusernotopenforthisRAD"*¦errorflaginD0.‰BRA‡RACLSRETŒGoreturn.6RACLSER2BSR‡RAEXERRSet"executionerror"flaginD0.‰BRA‡RACLSRET‚Goreturn.‰PAGEM******************************************************************************$*ˆSubroutinetohandleRADDMPcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**M*****************************************************************************6RARADDMPEQU‡*‰RoutinetosetuptodumpRAD'smemory.3‰MOVE.L„RACMDPRM(A3),-(A7)‚Savecommandparameters.‰MOVE.L„RACMDPRM+4(A3),-(A7)RADMP1ƒCLR.L…D39‰MOVE†RACMDPRM+4(A3),D3ƒPut#wordstobedumpedintoD3.6‰CMP‡#RALODLNG,D3ˆIs#wordstobedumpedsmallenough$*¦tobedoneinonetransferthrough *¦shared-RAM?‰BLS.S…RADMP2ŽYes--godoit.6‰MOVE†#RALODLNG,D3ˆNo--mustbreakitupanddoitpart'*¦atatime.‚Setuptodothe1stpart.@RADMP2ƒMOVE.L„RASHRAD(A5),A1†SetA1tostartaddrofshared-RAM.;‰MOVE.B„#RAPARAM/2,RAPRMPTR(A1)‡Setupparamptrinshared-5‰CLR.B…RAPARAM(A1)‰RAM.‚Clear1stbyteofparamtable9‰MOVE.B„#2,RAPARAM+2(A1)„andput2(#ofwordsofparams)!*¦intoparamtableinshared-RAM.<‰MOVEP…D3,RAPARAM+8(A1)„Put#wordstodumpintoparamtable*¦inshared-RAM.>‰MOVE.B„RACMDPRM+6(A3),RAPARAM+4(A1)‚PutRADaddrtodumpfromA‰MOVE.B„RACMDPRM+7(A3),RAPARAM+6(A1)‚intoshared-RAMparamtable.8‰MOVE.B„#RADMPCMD,RACMDCOD(A5)ˆStorecmdcodeinCCBfor *¦lateruse.2‰CLR.B…RACSTAT(A1)‰Clearcmdstatusinshared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto *¦interruptoncommandcomplete.9‰MOVE.B„#RADMPCMD,RACMDBYT(A1)ˆSetcmdcodeinshared-RAM*¦toexecutedumpfunction.(‰TR0$.PAUSEŠ,‰Waitfor"done"interrupt.F*>>>>>>>>>>>>>‚Returnfrominterrupthere.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<:‰CMPI.B„#$80,RACSTAT(A1)„CheckcompletionstatusfromRAD.*‰BNE.S…RADMPERRŒStatusisnotgood--error.'‰MOVE†D3,D4Put#wordsdumpedintoD4.$‰ASL‡#1,D4Doubleittoget#bytes.:‰MOVE.L„RACMDPRM(A3),A4…Putaddrofuser'sbufferintoA4.:‰LEA‡RAPARAM+12(A1),A2ƒPutaddrinshared-RAMofdumpdata *¦intoA2.;RADMPLUPMOVE.B„(A2),(A4)+ŠMoveabytefromshared-RAMinto*¦user'sdatabuffer.+‰ADD‡#2,A2Bumpshared-RAMptrtonextbyte*¦(68000addressing).1‰SUBQ†#1,D4Decrementbytecount--anymoretodo?‰BHI‡RADMPLUPŒYes--godonext.<‰SUB‡D3,RACMDPRM+4(A3)ƒNo.‚Subtract#wordsdumpedthistime!*¦fromtotal#lefttobedumped.6‰BEQ.S…RADMP3ŽIfzero,finishedallofrequesteddump.+‰ASL.L…#1,D3Double#wordstoget#bytes.9‰ADD.L…D3,RACMDPRM(A3)…Add#bytestouser'sbufferaddr.<‰ADD‡D3,RACMDPRM+6(A3)ƒAdd#bytestoRADaddrtodumpfrom.(‰BRA‡RADMP1ŽGobackanddonextpieceof*¦requesteddump./RADMP3ƒCLR.L…D0’ClearD0toindicatesuccessful*¦completionofdump.‰BSR‡RACLRSTAŒClearRADstatus.RADMPRETEQU‡*3‰MOVE.L„(A7)+,RACMDPRM+4(A3)ŠRestoreuser'scommand+‰MOVE.L„(A7)+,RACMDPRM(A3)Œparametertable. ‰RTS›Return.‰MOVE.B„RACMDPRM+6(A3),RAPARAM+4(A1)‚PutaddrinRADRAMtobe;‰MOVE.B„RACMDPRM+7(A3),RAPARAM+6(A1)‚loadedintoshared-RAM*¦paramtable.+‰MOVE†D3,D4Put#wordstobeloadedinD4.&‰ADDQ†#1,D4Add1togive#ofparams.2‰MOVEP…D4,RAPARAM(A1)†Put#paramsintoshared-RAM*¦paramtable.C‰MOVE.B„#RALODCMD,RACMDCOD(A5)‚StorecmdcodeinCCBforlateruse.7‰CLR.B…RACSTAT(A1)‰Clearcmdstatusbyteinshared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto *¦interruptoncommandcomplete.<‰MOVE.B„#RALODCMD,RACMDBYT(A1)‚Setcmdbyteinshared-RAMto*¦executeloadfunction.(‰TR0$.PAUSEŠ,‰Waitfor"done"interrupt.K*>>>>>>>>>>>>>>>>‚Returnherefrominterrupt.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<<:‰CMPI.B„#$80,RACSTAT(A1)„CheckcompletionstatusfromRAD.*‰BNE.S…RALODER2ŒStatusisnotgood--error.=‰SUB‡D3,RACMDPRM+4(A3)ƒSubtract#wordsloadedthistimefrom*¦#lefttobeloaded.,‰BEQ.S…RALOD3ŽIfnomorelefttodo,return./‰ASL.L…#1,D3Doubletoget#bytesjustloaded.6‰ADD.L…D3,RACMDPRM(A3)…Add#bytesloadedthistimeto7‰ADD‡D3,RACMDPRM+6(A3)ƒaddressesincmdparamtablefor*¦remainingloading.'‰BRA‡RALOD1ŽGobackandloadnextpart.5RALOD3ƒCLR.L…D0’ClearD0toindicatesuccessfulload.‰BSR‡RACLRSTAŒClearRADstatus.RALODRETEQU‡*3‰MOVE.L„(A7)+,RACMDPRM+4(A3)ŠRestoreuser'scommand+‰MOVE.L„(A7)+,RACMDPRM(A3)Œparametertable. ‰RTS›Return.@RALODERRMOVE.L„#RAERR4,D0ŠSetD0toerrorvalueforparamtable*¦error.‰BRA‡RALODRETŒGoreturn.8RALODER2BSR‡RAEXERRSetD0toerrorvalueforexecution*¦error.‰BRA‡RALODRET‚Goreturn.‰PAGEJ***************************************************************************$*ˆSubroutinetohandleRADCALcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**K***************************************************************************>>>>>>>>>>>>>>‚Returnfrominterrupthere.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<-‰CMP.B…#$80,RACSTAT(A1)„Wascmdcompletedok?‰BNE.S…RACALERRŒNo--error.@‰MOVE.B„RANXT2GT(A1),D2…Yes--getcalibrationreadingsfromFIFO.!*¦Putnext-to-getoffsetintoD2. ‰CLR.L…D5>>>>>>>>>>>>>>‚Returnfrominterrupthere.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;‰MOVEP.LƒRATSTAT(A1),D0†Putstatusintocmdparamtablefor)‰MOVE.L„D0,RACMDPRM+2(A3)†returntouser./‰CMP.B…#$80,RACSTAT(A1)„Self-testcompletedok?‰BEQ.S…RATST2ŽYes.-‰CMP.B…#$03,RACSTAT(A1)„No.‚Self-testfailed?%‰BNE.S…RATSTERRŒNo--someothererror.8‰MOVE.L„#RATSTFAL,D0ˆSetD0to"testfailed"indication.4‰MOVE.L„RARDLADR(A5),A1…SettheRADstatusto"bad".‰MOVE†#RASTBAD,RARDSTAT(A1)RATSTRETEQU‡* ‰RTS›Return-RATST2ƒCLR.L…D0’SetD0toindicatenoerrors.‰BSR‡RACLRSTAŒClearRADstatus.‰BRA‡RATSTRETŒGoreturn.:RA) TSTERRBSR‡RAEXERRSetD0toindicate"executionerror".‰BRA‡RATSTRETŒGoreturn.‰PAGEN*******************************************************************************$*ˆSubroutinetohandleRADABTcalls.*,*’Calledfromthecommandprocessorroutine.*#*ˆUponentry:‰A2=paramblockaddr*œA3=commandpacketaddr*œA5=CCBaddr*œA6=TCBaddr*2*ˆUponreturn:ˆD0=errorcode(=0,ifsuccessful)**œ01234567*˜D:‚*********˜A:‚**PP*PP**O*******************************************************************************=RARADABTEQU‡*‰RoutinetoabortwhatevertheRADisdoingand$*¦closeallchansforthisRAD.‚(All&*¦usersofthisRADwillbeflaggedin'*¦RAUSRLSTsotheycanbe"notified"of"*¦theabortontheirnextrequest.@‰MOVE.L„RARDLADR(A5),A1…PutaddrofthisRAD'sentryinRARADLST ‰CLR.L…D3=‰MOVE†RARDSTAT(A1),D3…StoreRADstatus(whichistheuserptr&*¦iftheRADiscurrentlybeingused).*‰CMP‡#RASTOK,D3ŠinA1.‚IsRADrunningnow?(‰BEQ.S…RAABT0ŽNo--don'thavetostopit.#‰CMP‡#RASTBAD,D3‰IsRADmarkedbad?)‰BEQ.S…RAABT0ŽYes--don'thavetostopit.#*¦No--RADmustberunning--stopit.<‰MOVE.L„RASHRAD(A5),A1†Putstartaddrofshared-RAMintoA1.2‰CLR.B…RACSTAT(A1)‰Clearcmdstatusinshared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Setinterruptmaskinshared-RAMto *¦interruptwhenRADisstopped.:‰MOVE.B„#RASTOPIT,RASTPBYT(A1)ˆSetstopbyteinshared-RAM*¦tostopRADprocessing.&‰TR0$.PAUSEŠ,‰Waitfordoneinterrupt.I*>>>>>>>>>>>>>>>‚Returnfrominterrupthere.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<6RAABT1ƒMOVE.L„RAD1TBL,A1ŠPutaddroftableareainA1.6‰LEA‡RAUSRLST(A1),A2…SetA2tostartaddrofRAUSRLST.4‰MOVE†#32,D1ŽMustsetallchanstounusedstatusand&*¦flagallusersofthisRADtoinform'*¦themoftheabortontheirnextcall.?‰LEA‡RACHNUSR(A5),A1‚SetA1tostartofuserptrsforthisRAD.1RAABTLUPCMP‡#$FFFF,(A1)‰Isthischanunassigned?&‰BEQ.S…RAABT2ŽYes--goontonextchan.*‰CMP‡#$F000,(A1)‰Isthischanunavailable?&‰BEQ.S…RAABT2ŽYes--goontonextchan.(‰CLR.L…D2’No--must"unassign"thischan.!‰MOVE†(A1),D2PutuserptrinD2.0‰MOVE†#$FFFF,(A1)‰Setchantounassignedstatus.02"3*82+:4B4J8R4ZBb/j1r</‰CMP‡D2,D3Doesthischanbelongtothecurrent*¦userofthisRAD(ifany)?#‰BEQ.S…RAABT2ŽYes--don'tflaguser.8‰MULU†#RAULNG,D2ŠMultiplyuserptrbylengthofRAUSRLST+*¤entrytogetoffsettothisuser'sentry.<‰MOVE.B„#RAABTCOD,RAUSTAT(A2,D2)†SetuserstatusinRAUSRLST#*¦toabortcodesothatusercanbe%*¦notifiedofabortonhisnextcall.2RAABT2ƒADD.L…#2,A1BumpA1topttonextuserptr.‰SUBQ†#1,D1Allchansdone?‰BGT‡RAABTLUPŒNo--godonext.=‰MOVE.L„#RAABTCOD,D0ˆYes--notifycurrentuser(ifany)ofthe‰BSR‡RANOTIFYŒabort.@‰MOVE.L„RARDLADR(A5),A1…PutaddrofthisRAD'sentryinRARADLST *¦intoA1.2‰MOVE†#RASTOK,RARDSTAT(A1)ŠSetRADstatusto"ok".5‰MOVE.L„RASHRAD(A5),A1†SetA1tostartofshared-RAM.8‰CMP.B…#$84,RACSTAT(A1)„Yes.‚DidtheRADstopcorrectly?‰BNE.S…RAABTERRŒNo--error.3‰CLR.L…D0Yes--setD0toindicatesuccessfulabort.RAABTRETEQU‡* ‰RTS›Return.@RAABT0ƒMOVE.L„RASHRAD(A5),A1†SetA1tostartaddrofshared-RAM.8‰MOVE.B„#$84,RACSTAT(A1)„Setcmdstatusinshared-RAMto$*¦"successfulstop"valueforlater.+‰BRA‡RAABT1ŽContinuewithabortprocessing.6RAABTERRBSR‡RAEXERRExecutionerrorinRAD.‚SetD0to *¦errorcode.‰BRA.S…RAABTRETŒGoreturn.‰PAGEK****************************************************************************=*ˆSubroutinetoseterrorreturnvalueinD0forunsuccessful*’functionexecution.*+*ˆCalledfromcommand-handlingsubroutines.*2*ˆUponentry:ƒA1=addrofshared-RAMforthisRAD*K********************) *******************************************************ARAEXERR‚CMP.B…#$01,RACSTAT(A1)„Didwegetan"illegalcmd"return*¦fromtheRAD?‰BNE.S…RAEXERR2ŒNo.-‰MOVE.L„#RAERR9,D0ŠYes--setD0toerrorcode.‰BRA.S…RAEXERR9ŒGoreturn.=RAEXERR2MOVE.L„#RAEXERRV,D0ˆSetD0toexecutionerrorvalue.RAEXERR9RTS›Return‰PAGEM******************************************************************************>*ˆSubroutinetosettheRADstatusto"ok"andresetthedata-:*’retrieval-subroutineaddresstotheaddressofRARDFIFO.*+*ˆCalledfromcommand-handlingsubroutines.**ˆUponentry:‰A5=CCBaddress.*=*ˆUponexit:‚contentsofregisterA1aredestroyed--allother*œregistersare"untouched".*N******************************************************************************RACLRSTAEQU‡**;‰LEA‡RARDFIFO(PC),A1…Putaddrofread-FIFOroutineintoA1.=‰MOVE.L„A1,RARTRVAD(A5)…Storeitindata-retrieval-subroutine)*¦addrlocinCCB.‚(Thisisthe"default"*¦data-retrievalsubroutine.)=‰MOVE.L„RARDLADR(A5),A1…SetA1toaddrofthisRAD'sentryin *¦RARADLST.2‰MOVE†#RASTOK,RARDSTAT(A1)ŠSetRADstatusto"ok". ‰RTS›Return.‰PAGEN*******************************************************************************,*ˆSubroutinetoreadtheFIFOinshared-RAM.*(*ˆCalledfrominterruptserviceroutine.*3*’Uponentry,A1containsstartaddrofshared-RAM.**•01234567*’D:*ƒ***** *’A:ƒP***N******************************************************************************RARDFIFOEQU‡*RAFILUP1CLR.L…D29‰MOVE.B„RANXT2GT(A1),D2…Getnext-to-getptrforFIFOfrom *°shared-RAM.0‰CLR.L…D6’SetupD6tocontaincommandstatusin=‰MOVE.B„RACSTAT(A1),D6†bits8-15forlateruseinqueueingan‰ASL.L…#8,D6event.;‰ASL‡#1,D2…Doublenext-to-getptrtogetactualoffsetfrom'*¦startofshared-RAM(68K-addressing).4‰LEA‡(A1,D2),A2ŠGetactualaddrofnextvaluetoget*°andstoreitinA2.3‰CMPI.B„#$FF,(A2)‹Anydatainnext-to-getlocation?$‰BEQ‡RAFIFOMTŒNo--FIFOisnowempty.4‰MOVE.B„0(A2),D5‚Yes--findoutwhattodowithdata.1‰MOVE.B„D5,D3Storegainandchan#inD5andD3.>‰AND.L…#$1F,D5ƒMaskoffgain,leavingjustthechannelnumber.0‰MOVE.B„D5,D6Movechan#intoD6forlateruse.7‰MULU†#RACHNLLG,D5ˆCalculateoffsetinto'RARADLST'for*¦thischannel.5‰ADD.L…RARDLADR(A5),D5…Addstart-of-entryaddress(in*¦'RARADLST')forthisRAD.;‰ADD.L…#RACHNLST,D5ˆD5nowcontainstheaddroftheoptions4‰MOVE.L„D5,A3flagforthischannel.‚PutaddrinA3.*9*’========‚PackdataforthisreadingintoD3.‚==========4‰MOVE.B„2(A2),D4ŒPutflagsandhi-databyteintoD4.‰ASL.L…#8,D3ShiftdatainD3.,‰MOVE.B„D4,D3Putflagsandhi-dataintoD3.6‰ANDI.B„#$F0,D3Maskofflowbyte,leavingjustflags.&‰ASL.L…#8,D3Shiftdataoveronebyte.2‰MOVE.B„D4,D3Putflagsandhi-dataintoD3again.8‰ANDI.B„#$0F,D3Maskofflowbyte,leavingjusthi-data.&‰ASL.L…#8,D3Shiftdataoveronebyte.7‰MOVE.B„4(A2),D3ŒPutlo-databyteintoD3.‚Nowalldata(*¦forthisreadinghasbeenputintothe&*¦4bytesofD3inthecorrectformat.8‰MOVE.L„RACHNSTO-RACHNOPT(A3),A3†Putstorage-addrinA3.4‰MOVE.L„D3,(A3)Storedatainlocspecifiedbyuser.+‰MOVE.B„#$FF,(A2)‹SetFIFOlocto"unused".=‰ADDQ.B„#3,RANXT2GT(A1)…SetFIFOnext-to-getptrtonextdata*°locationintheFIFO.3‰MOVE.B„RAFIFOND(A1),D4…SetD4toend-of-FIFOaddr.7‰CMP.B…RANXT2GT(A1),D4…ArewepasttheendoftheFIFO?‰BHS.S…RAF1No.?‰MOVE.B„RAFIFOST(A1),RANXT2GT(A1)…Yes--setFIFOnext-to-getptr*°tostart-of-FIFOptrvalue.6RAF1…MOVE.L„D5,A3ResetA3toaddrofoptionsflagfor *¦thischan.'‰MOVE†(A3),D0PutoptionsflagintoD0.<‰BTST.L„#RASUBRBT,D0ˆIsthereasubroutinetobecalledwhen*¦thereisdataforthischan?‰BEQ.S…RAF2No.?‰MOVE.L„RACHNSUB-RACHNOPT(A3),A3†Yes,putaddrofsubrintoA3.3‰MOVEM.LƒD1-D7/A0-A6,-(A7)ƒStoreregistercontents.‰JSR‡(A3)Jumptosubroutine.5‰MOVEM.Lƒ(A7)+,D1-D7/A0-A6ƒRestoreregisterco* ntents.L*======================‚Onreturnfromsubroutine,D0willbesetforeither0*œqueueeventorwakeupifeitheroftheseisto-*œbedoneafterthesubr.‚Else,D0willbe0.=RAF2…BTST.L„#RAQUEBT,D0‰Arewetoqueueaneventtotheuser?‰BEQ.S…RAF3No.:‰MOVE.L„#RAEVNTHI,D2ˆYes--setupperhalfofD2tostandard*¦eventdata(lengthandcode).2‰MOVE†D6,D2Putcommandstatusandchan#intoD2.=‰MOVE.L„CCBMNEM(A5),D3†PutRAD-IDinto2ndlongwordofevent.*‰BSR‡QEVENTŽGoqueueaneventtotheuser.$‰BRA.S…RAF9Alldonewiththischan.;RAF3…BTST.L„#RAWAKEBT,D0ˆArewetodoawakeupoftheuser?(‰BEQ.S…RAF9No--alldonewiththischan.#‰MOVE.L„A6,A0PutTCBaddrintoA0.+‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒStoreregisters.*‰TR0$.WAKEUP‰,‰Issueawakeuptotheuser.-‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestoreregisters.9RAF9…BRA‡RAFILUP1‚GobackandgetnextreadingfromFIFO.-RAFIFOMTRTS‘RADFIFOisnowempty--return.‰PAGEK****************************************************************************/*ˆSubroutinetofinduser'sentryin'RAUSRLST'*>*ˆCalledfromcommandprocessorandcommand-handlingroutines.**’Uponexit:ƒD0=errorflag*ŸD1=entry#forthisuser.**œAllotherregistersusedwillhavetheir*œcontentsrestored.*L****************************************************************************RAFNDUSREQU‡**3‰MOVEM.LƒD2-D4/A0-A1,-(A7)ƒStoreregistercontents.4‰MOVE.L„RAD1TBL,A1ŠPutaddrofRADtableareainA1.1‰LEA‡RAUSRLST(A1),A0…PutaddrofuserlistinA0.6‰MOVE.L„A1,D0SetD0toaddrofRARADLST,whichisthe1‰ADD‡RARADLAD(A1),D0…sameastheendofRAUSRLST.-‰CLR.L…D1’D1willbea"usercounter".‚(First*¦userwillbe#0.)7‰MOVE.L„TCBNAME(A6),D2†Putusertasknameandsession#'‰MOVE.L„TCBSESSN(A6),D3…intoD2andD3.(‰MOVE.L„CCBMNEM(A5),D4†PutRAD-IDinD4.4RAFNDLP‚CMP.L…RAUUSRNO(A0),D2…Doesthisentrymatch?!‰BNE.S…RAFNXTŽNo--trynextentry.‰CMP.L…RAUUSRNO+4(A0),D3ƒMaybe.‰BNE.S…RAFNXTŽNo--trynext.‰CMP.L…RAURADID(A0),D4…Maybe.‰BEQ.S…RAFGOTITŒYes.:RAFNXTƒADDA.L„#RAULNG,A0ŠDoesn'tmatch.‚Setuptotrynext0‰CMPA.L„D0,A0entry.‚Arethereanymoreentries?2‰BHS.S…RAFNOGOTŒNo--thisuserisnotsetuptouse!*¦thisRAD.‚Gomakeerrorreturn.!‰ADDQ†#1,D1Yes--incentrycount.*‰BRA‡RAFNDLPGobackandcheckthisentry.*RAFNOGOTMOVE.L„#RAERR3,D0ŠSeterrorcode.‰BRA.S…RAFRETŽGoreturn.)RAFGOTITEQU‡*“A0containsaddrofentry;&*¦D1containsptrtothisentry(i.e., *¦entry#).7‰CMP.B…#RAABTCOD,RAUSTAT(A0)‰WasthisRADabortedsince*¦thelastcallbythisuser?#‰BNE.S…RAFNDOKNo--everything'sok.*B************‚Becauseofthewaythe"abort"flagissetandreset,G************‚thefollowingcodewillonlybeexecutedwhenthisroutineD************‚iscalledfromthecommandhandleronthefirstcallby@************‚eachuserafterthisRADhasbeenaborted(RADABT).*3‰CLR.B…RAUSTAT(A0)‰Yes.‚Clearthe"aborted"flagin*¦thisuser'sstatus.8‰MOVE.L„#RAABORTD,D0ˆSeterrorcodeto"warning--RADwas*¦aborted"code.‰BRA.S…RAFRETŽGoreturn. ************ ************/RAFNDOK‚CLR.L…D0’ClearD0toindicatenoerror.;RAFRETƒMOVEM.Lƒ(A7)+,D2-D4/A0-A1ƒRestoreregistercontents. ‰RTS›Return.‰PAGEL*****************************************************************************@*ˆSubroutinetomoveparametersintoshared-RAMparametertable.*+*’Calledfromcommand-handlingsubroutines.*L*****************************************************************************2*’Uponentry--ˆA4=addrofparameterstobemoved*¦D4=#ofbytestobemoved7*’(A4andD4willcontainthesameasaboveuponexit.)$*’Uponexit:ŠA1=addrofshared-RAML*---------------------------------------------------------------------------RAMOVPRMEQU‡*-‰MOVEM.LƒA4/D4,-(A7)‰Storeregistercontents.<‰MOVE.L„RASHRAD(A5),A1†Putstartaddrofshared-RAMintoA1.9‰LEA‡RAPARAM(A1),A0†Putaddrofparamtableinshared-RAM *¦intoA0.RANTF2ƒBTST.L„#RAWAKEBT,D0ˆArewesupposedtoissueawake-up?‰BEQ.S…RANTFRETŒNo--goreturn.8‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒYes--storeregistercontents.*‰MOVE.L„A6,A0Putuser'sTCBaddrintoA0. ‰TR0$.WAKEUP‰,‰Go+ issuewake-up.-‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestoreregisters.RANTFRETEQU‡*0‰MOVEM.Lƒ(A7)+,D0-D3/A1-A2/A6ŠRestoreregisters. ‰RTS›Return.‰PAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLINGTASKSADDRESSSPACE.*#*ENTRY:ƒD5‚-NO.OFBYTESTOCHECK*ŠD6‚-68000ADDRESS(LOGICAL)*ŠA1‚-TCBADDRESS**#* REGISTERS USED: D0-D1,D3,D6/A0-A1**7*EXIT:„D6-PHYSICALADDRESSOFBUFFERBASE(IFLEGAL)*ŠRETURNTOPC„FORGOODADDRESS*”PC+2‚FORBADLENGTH*”PC+4‚FORBADADDRESS**C*******************************************************************IOHADRCK‚EQU„*$ŠBTSTƒ#0,D6ŽMUSTBEONWORDBOUNDARY(ŠBNE.S‚IOHADR4ŒBRANCHIFBADBUFFERBASE ŠTST.L‚D5.ŠBEQ.S‚IOHADR8ŒDON'TGOTOLOGPHYWITH0COUNT IOHADR2ƒEQU„*/ŠMOVE.LTCBTST(A1),A0†ADDRESSOFTASKSEGTABLE ŠTR0$.LOGPHY&ŠBRA.S‚IOHADR8ŒBRANCHFORGOODADDRESS(ŠBRA.S‚IOHADR6ŒBRANCHFORBADBYTECOUNT'ŠTST.L‚D5‘WASANENTRYPOINTERRETURNED#ŠBEQ.S‚IOHADR4ŒBRANCHIFNO-ERROR'ŠTST.B‚7(A0,D5)‹ISTHISANMMIOSEGMENTŠBNE.S‚IOHADR8ŒYES,OKIOHADR4ƒADD.L‚#2,(A7)IOHADR6ƒADD.L‚#2,(A7) IOHADR8ƒRTSŠPAGEJ***************************************************************************F*INTERRUPTSERVICEROUTINE…<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*?*ƒPURPOSE:‚HANDLEACKNOWLEDGEMENTSANDMESSAGECOMPLETIONSFROM3*THERAD1.‚OPERATESATHARDWAREINTERRUPTPRIORITY<*LEVELASASUBROUTINETOTHEFIRSTLEVELINTERRUPTHANDLER *(INCMR).*4*ƒENTRY:‚JSR‚FROMINTERRUPTHANDLERROUTINE(INCMR)*‹A0=WORKREGISTER *‹A1=SELF*‹A5=CCBADDRESS*‹D0=WORKREGISTER*/*ƒEXIT:‚RTS-BACKTOINTERRUPTHANDLERROUTINE**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A*****PP***ƒCODEISRE-ENTRANT*F*---------------------------------------------------------------------**"RADISR„EQU„*’INTERRUPTENTRYPOINT.‰MOVEM.LƒD1-D7/A2-A4/A6,-(A7)…STOREREGISTERS.*=‰MOVE.L„RAUSRTCB(A5),A6…SetA6toaddrofcurrentuser'sTCB,(*¦whichwasstoredwhencommandwassent*¦tothisRADboard.7‰MOVEA.LƒRASHRAD(A5),A1†Putaddrofshared-RAMintoA1.3‰MOVE.B„RAXSTAT(A1),D1†PutstatusfromRADintoD1.4‰AND.B…#RAINTBIT,D1ˆDidthisRADsendtheinterrupt?)‰BEQ‡RAINONo.‚ReturnandchecknextRAD.8‰CMP.B…#RALVL4,CCBPPRIO(A5)ŠIsthisalevel4interrupt?‰BNE.S…RAISR1ŽNo--level3.**¦Yes--RAD"died".8‰MOVE.L„CCBMNEM(A5),D0†PutRAD-IDfromthisCCBintoD0.7‰SUB.L…#$0400,D0‹SubtracttogetRAD-IDforlevel3CCB(*¦whichcorrespondstothislevel4CCB.*0*SearchCCBchainforlevel3CCBforthisRAD.*+‰MOVE.L„A5,-(A7)ŒStoreaddroflevel4CCB.6‰MOVE.L„CCBHD,A5ŒStoreaddrof1stCCBinchaininA5.%RAISRLP‚CMP.L…#0,A5EndofCCBchain?6‰BEQ.S…RAISRFALŒYes.‚Somethingwrong--can'tfindlevel)*¦3CCBforthisRAD.‚Ohwell,forgetit!<‰CMP.L…CCBMNEM(A5),D0†IsthistheCCBwehavebeensearching#‰BEQ.S…RAISR0Žfor?ƒEUREKA!!!Itis!0‰MOVE.L„CCBALL(A5),A5‡No--trynextCCBinchain. ‰BRA‡RAISRLPFRAISR0ƒMOVE.L„RARDLADR(A5),A2…PutaddrofthisRAD'sentryinRARADLST *¦intoA2. ‰CLR.L…D3=‰MOVE†RARDSTAT(A2),D3…StoreRADstatus(whichisuserptrfor*¦currentuser,ifany).4‰MOVE†#RASTBAD,RARDSTAT(A2)‰SetRADstatusto"bad".(‰MOVE.L„#RAERR1,D0ŠSetD0toerrorcode.3‰BSR‡RANOTIFYŒNotifycurrentuser,ifany,thatRAD *¦justdied.RAISR8ƒCLR.B…RARDFLAG(A5)ˆFinishedprocessingthisinterrupt--$*¦clear"workingoninterrupt"flag.*3RAISR4ƒEQU‡*“TellCMRthatinterrupthasbeentaken *¦careof.7‰CLR.B…RAINTFLG(A1)ˆClearinterruptflaginshared-RAM.-‰ORˆ#1,SRSetcarrybittoindicatethatthis*¦interrupthasbeenhandled. ‰BRA.S…RAISR9*4RAINO„EQU‡*“TellCMRthatthisinterruptisnotfrom *¦thisRAD.2‰AND‡#$FFFE,SR‹(Clearcarrybittoindicatethis.)**RAISR9ƒEQU‡*“ReturntoCMR.***-* RAD INTERRUPT HANDLER EXITS FROM THIS POINT*/ŠMOVEM.L(A7)+,D1-D7/A2-A4/A6…RESTOREREGISTERSŠRTSšBACKTOINTERRUPTHANDLERŠPAGEK*****************************************************************************9* ROUTINE TO QUEUE EVENT (ALREADY STAGED IN REGISTERS) TO*ƒ-DRIVINGTASK. *ƒ-EVENTBEGINSINREGISTERD2.***ˆEXECROUTINE/*ˆREGISTERSUSED:D0-D1/A0,A3-A6‚WORKREGISTERS*˜D2-D7‹STAGINGREGISTERS**K**************************************************************************** QEVENTƒEQU‡**ŠMOVEM.LA0-A6/D0-D7,-(A7)‡Saveregisters.#‰MOVE.L„A6,A0Caller'sTCBaddress.6ŠTR0$.QEVNTIˆ,‰(QEVNTIroutineisusedsincethiswill#*¦becalledonlywhileservicingan *¦interrupt.)#ŠBRA.S‚IOHQ5ŽBranchifqueueingok.-ŠMOVEM, .L(A7)+,A0-A6/D0-D7…Restoreregisters.9ŠMOVE.L(A7),CCBQVER1(A5)‚Savecallersaddressfordebug.ŠBRA.S‚IOHQRTN 2IOHQ5…MOVEM.L(A7)+,A0-A6/D0-D7„Restoreregisters..ŠCLR.L‚CCBQVER1(A5)‡Clearqueueerroraddress. IOHQRTNƒRTS—RETURN‰ENDé=/* =/*†RADLIB.AF=/*7=/* Chain file to assemble FORTRAN-callable subroutines&=/* to interface with the RAD1 driver.=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to RADLIB.LS=/*=/IFC \1ƒ=ARGRADLIB.LS=/ENDIF=/*=ASM RADLIB.SA,RADLIB.RO,\1;R=/*{ Included files are:=/*ƒ--none--=/*}=/*=ENDéééééézK*==========================================================================*=*ˆFORTRAN-callablesubroutinesusedtoinvoketheRADdriver.*K*==========================================================================** ‰SECTIONƒ9=‰XDEF†RADOPN,RADTST,RADABT,RADJMP,RADLOD,RADDMP,RADXEQ,RADSTP6‰XDEF†RADATO,RADCLS,RADSCN,RADEXT,RADSET,RADHIS,RADCAL****J*----------------‚CONSTANTS----------------------------------------------*2ERRCODƒEQU‡$F3‘Errorcodefor"paramtableerror".*%RASTPCMDEQU‡00ˆ"Stop"commandvalue.%RALODCMDEQU‡01ˆ"Load"commandvalue.%RADMPCMDEQU‡02ˆ"Dump"commandvalue.%RAJMPCMDEQU‡03ˆ"Jump"commandvalue.*RATSTCMDEQU‡04ˆ"Self-test"commandvalue.&RAOPNCMDEQU‡$10‡"Open"commandvalue.'RACLSCMDEQU‡$20‡"Close"commandvalue.'RAABTCMDEQU‡$7F‡"Abort"commandvalue.2RAEXTCMDEQU‡$81‡"Externaltrigger"commandvalue.*RASETCMDEQU‡$82‡"Setpoint"commandvalue.&RASCNCMDEQU‡$83‡"Scan"commandvalue.1RAATOCMDEQU‡$84‡"Auto-rangescan"commandvalue.+RACALCMDEQU‡$85‡"Calibrate"commandvalue.1RAHISCMDEQU‡$86‡"High-speedscan"commandvalue.2RAXEQCMDEQU‡$80‡"Executefunction"commandvalue.‰PAGE*H*-----------------------------------------------------------------------*!*ˆ, GeneralformatofFORTRANcall:&*’CALLRADXXX(rad-id,param-table-addr)*=*ˆThiscallwillcause3itemstobepushedontothestack--:*’(1)‚addresswherethedesiredRAD-IDisstored‚(4bytes)9*’(2)‚addressofparametertableinuser'sarea‚(4bytes)*’(3)‚returnaddress‚(4bytes)*A*ˆAllregisterswillbesavedandrestoreduponreturnexceptfor+*’registerA0,whosecontentswillbelost.*@*ˆUponreturn,thestackpointerwillbethesameasitwasjust6*’priortotheRADcall.‚Thefollowingillustratesthe4*’datawhichisputonthestack(andremovedbefore$*’returningtothecallingprogram).*?*ˆ(Lowestaddrofstack)…1)CMRcommandcode,subcode…(2bytes)*£2)**‚(zero-filled)(2bytes)*£3)RAD-ID˜(4bytes)ƒ8Œ6”7œ9¤*£4)**‚(zero-filled)(4bytes)*£5)**‚(zero-filled)(4bytes)*£6)**‚(zero-filled)(4bytes)%*£7)cmdpacketaddr(=addrofuser's*°paramtable)ˆ(4bytes)#*£8)lengthofcmdpacketŠ(2bytes)*£9)contentsofA3(4bytes)*¢10)contentsofD2(4bytes)*¢11)contentsofD1(4bytes)*¢12)contentsofD0(4bytes)*¢13)returnaddr“(4bytes) *¢14)param-table-addrŽ(4bytes)>*ˆ(highmemoryaddr)ˆ15)addrwhereRAD-IDisstoredƒ(4bytes)*5*’#1through8aboveformtheparameterblockforthe(*œCMRTRAP1.‚(**marktheunusedfields)6*’#9through12arestoragelocationsfortheregister *œcontents.;*’#14and15aretheparameterspassedbytheFORTRANcall.*O*********************************************************************************‰PAGECRADOPNƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontentsonthestack.1‰MOVE†#RAOPNCMD,D1ˆStorecommandcodefor"open".9‰MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3. ‰CLR.L…D2)‰MOVE†4(A3),D2ŒPut#ofchannelsintoD2..‰MULU†#12,D2ŽCalculate#ofbytesinparameter-‰ADD.L…#6,D2table(includingfirst6bytes).6‰BRA‡CALLDRVRŒGosetupparamblockandmakeCMRcall.**CRADTSTƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontentsonthestack.2‰MOVE†#RATSTCMD,D1ˆStorecmdcodefor"self-test".@RADTST2‚MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3.2‰MOVE.L„#10,D2ŽPut#bytesinparamtableintoD2.6‰BRA‡CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADABTƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents..‰MOVE†#RAABTCMD,D1ˆStorecmdcodefor"abort".@RADABT2‚MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3.0‰MOVE.L„#4,D2PutlengthofparamtableintoD2.6‰BRA‡CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADJMPƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.-‰MOVE†#RAJMPCMD,D1ˆStorecmdcodefor"jump".9‰MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3. ‰CLR.L…D2%‰MOVE†10(A3),D2‹Put#paramsintoD2.&‰ASL.L…#1,D2Doubletoget#ofbytes./‰ADD.L…#12,D2ŽAdd#bytesinbeginningoftable**¦(includingcount)togivetotal#bytes.6‰BRA‡CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADLODƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.-‰MOVE†#RALODCMD,D1ˆStorecmdcodefor"load".>RADLOD2‚MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableinA3.2‰MOVE.L„#12,D2ŽPut#bytesinparamtableintoD2.6‰BRA‡CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADDMPƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.-‰MOVE†#RADMPCMD,D1ˆStorecmdcodefor"dump".3‰BRA‡RADLOD2Gofinishsetup(sameasforRADLOD).**‰PAGE6RADXEQƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.9‰MOVE†#RAXEQCMD,D1ˆStorecmdcodefor"executefunction".9‰MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3. ‰CLR.L…D2(‰MOVE†12(A3),D2‹Put#ofparamsintoD2.'‰ASL.L…#1,D2Doubletogive#ofbytes.2‰ADD.L…#14,D2ŽAdd#bytesinbeginningoftableto*¦total#bytesintable.6‰BRA‡CALLDRVRŒGosetupparamblockandmakeCMRcall.- **6RADSTPƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.-‰MOVE†#RASTPCMD,D1ˆStorecmdcodefor"stop".3‰BRA‡RADABT2Gofinishsetup(sameasforRADABT).**6RADATOƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.8‰MOVE†#RAATOCMD,D1ˆStorecmdcodefor"auto-rangescan".@RADATO2‚MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3. ‰CLR.L…D2#‰MOVE†4(A3),D2ŒPut#chansintoD2.'‰ASL.L…#1,D2Doubletogive#ofbytes.5‰ADD.L…#6,D2Addtogivetotallengthofparamtable.8‰BRA.S…CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADCLSƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents..‰MOVE†#RACLSCMD,D1ˆStorecmdcodefor"close".3‰BRA‡RADABT2Gofinishsetup(sameasforRADABT).**6RADSCNƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.-‰MOVE†#RASCNCMD,D1ˆStorecmdcodefor"scan".9‰MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3. ‰CLR.L…D2#‰MOVE†6(A3),D2ŒPut#chansintoD2.$‰ASL.L…#1,D2Doubletogive#bytes.4‰ADD.L…#8,D2Add#bytesinbeginningofparamtable'*¦togivetotal#bytesinparamtable.8‰BRA.S…CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADEXTƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.9‰MOVE†#RAEXTCMD,D1ˆStorecmdcodefor"externaltrigger".3‰BRA‡RADATO2Gofinishsetup(sameasforRADATO).**‰PAGE6RADSETƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.9‰MOVE.L„20(A7),A3‹Putaddrofuser'sparamtableintoA3. ‰CLR.L…D13‰MOVE†4(A3),D1ŒMultiply#ofsetpointchansby6to$‰MULU†#6,D1#bytesforsetptchans. ‰CLR.L…D20‰MOVE†6(A3),D2ŒPut#non-setpointchansintoD2.6‰ASL.L…#1,D2ŽDoubletoget#bytesofnon-setptchans.0‰ADD.L…D1,D2Gettotal#ofbytesinparamtable‰ADD.L…#8,D2intoD2.9‰MOVE†RASETCMD,D1‰SetD1tocmdcodefor"setpointscan".8‰BRA.S…CALLDRVRŒGosetupparamblockandmakeCMRcall.**6RADHISƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.8‰MOVE†#RAHISCMD,D1ˆStorecmdcodefor"high-speedscan"./‰BRA‡RADTST2Gofinishsetup(sameasRADTST).**6RADCALƒMOVEM.LƒD0-D2/A3,-(A7)†Storeregistercontents.4‰MOVE†#RACALCMD,D1ˆStorecmdcodefor"calibration"./‰BRA‡RADLOD2Gofinishsetup(sameasRADLOD).**‰PAGE?CALLDRVRMOVE†D1,2(A3)ŒPutcmdcodeintouser'scmdparamtable.2‰CMP.L…#$7FFF,D2‹Islengthofparamtabletoobig?‰BHI.S…PRMERRŽYes--error."*---------------------------------*/*ˆSetupparameterblockforCMRcallonstack.**’(Thiswillbebuiltfromthebottomup.)*2‰MOVE†D2,-(A7)ŒPutpacketlength(i.e.,#bytesin$*¦user'sparamtable)at"bottom"of*¦paramblockforCMR.7‰MOVE.L„A3,-(A7)ŒAddrofparamtable(=cmdpacket)goes*¦next.0‰CLR.L…-(A7)Clearunusedfieldsofparamblock. ‰CLR.L…-(A7) ‰CLR.L…-(A7)-‰MOVE.L„42(A7),A3‹PutaddrofRAD-IDintoA3.7‰MOVE.L„(A3),-(A7)ŠPutRAD-IDintoparamblockforCMR.<‰MOVE.L„#$07000000,-(A7)„PutCMRcmdcode,subcode,etc.,at*¦"top"ofparamblockforCMR.0‰MOVE.L„A7,A0Putaddrofparamblock(whichnow"*¦startsattopofstack)intoA0.#‰MOVE.L„#60,D0ŽSetD0forCMRcall..‰TRAP†#1’CallCMR,whichwillinturncallthe *¦RADdriver.=RTRN…MOVE.L„46(A7),A3‹Putaddrofuser'sparamtableintoA3.5‰MOVE†D0,(A3)Putreturnederrorflagintoerrorcode*¦byteinuser'sparamtable.3‰LEA‡26(A7),A7‹Setstackptrtoaddrwhereregister*¦contentsarestored.2‰MOVEM.Lƒ(A7)+,D0-D2/A3†Restoreregistercontents.)‰MOVE.L„(A7)+,A0ŒPutreturnaddrintoA0.0‰LEA‡8(A7),A7Œ"Pop"passedparametersoffstack.‰JMP‡(A0)Returntouser.**<*--------------------------‚Errorinuser'sparametertable.*:PRMERRƒMOVE†#ERRCOD,D0ŠSetD0toerrorcodefor"parameter*¦tableerror".‰BRA‡RTRNGoreturntouser.**‰END  é- éééé=/* =/*†RIODRV.AF=/*%=/* Chain file to assemble RIO driver=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to RIODRV.LS=/*=/IFC \1ƒ=ARGRIODRV.LS=/ENDIF=/*%=ASM RIODRV.SA,RIODRV.RO,\1;MR-WZ=134=/*{ Included files are:=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.RIODRV.EQ=/*ƒSTDMACRO.AI=/*}=/*=ENDéééééé¬Î' RIODRV SAÁ²|qqRIOLIB AFÛÛqqRIOLIB SAää–qqSTDMACROAIýý_qqM605MEM AG;qqM610MEM AG~qqM615MEM AG00<qqM625MEM AGAA9qqIOCINT AGRRºqqADMEM AGkkqqRIOMEM AGtt6qqM605MEM CI…… qqRADMEM CIŽŽ qqM610MEM CI—— qqM625DRV CI  qqM6. 15MEM CI©© qqRIOMEM CI²² qqM625MEM CI»» qqM600DRV CIÄÄqqM605DRV CIÍÍqqŠPAGEŠTTL„TR1RTCD.EQŠINCLUDE9995.&.TR1RTCD.EQ ŠTTL„STR.EQŠINCLUDE9995.&.STR.EQ ŠTTL„TCB.EQŠINCLUDE9995.&.TCB.EQ ŠTTLCCB.EQŠINCLUDE9995.&.CCB.EQ ŠTTLLV5.EQŠINCLUDE9995.&.LV5.EQŠLISTŠTTLRIODRV.EQŠINCLUDE9995.&.RIODRV.EQŠTTLSTDMACRO.AIŠINCLUDESTDMACRO.AI/ŠTTLRIODRIVERCOPYRIGHT1982BYMOTOROLAINC.*‰INCLUDE9995.&.STR.EQ*‰INCLUDE9995.&.TR1RTCD.EQ*‰INCLUDE9995.&.TCB.EQ*‰INCLUDE9995.&.CCB.EQ*‰INCLUDE9995.&.LV5.EQ*‰INCLUDE9995.&.RIO.EQ*‰INCLUDE0..STDMACRO.SA@RIODRV„IDNTƒ2,0‰RIODRVR3/28/83COPYRIGHT1982BYMOTOROLAINC. ŠLLENƒ120ŠPAGEJ****************************************************************************8*ƒRIODRV--REV.1.005/12/82(C313)RONIWOOD&JIMLOE4*REV.2.003/28/83(C313)CHANGEDINTERRUPTHANDLER***ƒPurpose:‚REMOTEI/OHANDLER*/*ƒEntry:‚JSRFROMCMRHANDLER(COMMANDSERVICE) *‹JSRFROMCMRINTERRUPTHANDLER*-*ƒExit:-ALWAYSEXITSWITHARTSINSTRUCTION***ƒCODEISRE-ENTRANT*&*ˆASSEMBLY:USECHAINFILE'RIOASM.CF'*H*-----------------------------------------------------------------------*ŠPAGE*************************** MISCELLANEOUS EQUATES ***************************IOEVCD„EQU„1’I/Oeventcode*********************** *‡MACROS†************************* Macro for putting the H/W priority level'* to the priority indicated by the CCB.* INHIB„MACRO-‰MOVE.W„CCBISR(A5),SR‡Setprocessorpriority.‰ENDM*+* Macro for dropping the H/W priority level* to an interruptable state.* ENABL„MACRO4‰MOVE.W„CCBSR(A5),SRˆDropprocessorprioritybyone.‰ENDM*+* Macro for dropping the H/W priority level * to zero.* UNMASKƒMACRO1‰MOVE.W„#$2000,SR‹Setprocessorprioritytozero.‰ENDM‰PAGE********************************* CHANNEL CONTROL BLOCK (CCB) *********************************B*ƒContainschanneldevicedependentdescriptionanddataareasfor*ƒI/Ohandler.*ŠOFFSET‚CCBDDP*²¹\ÂFÊ9Ò-ÚHâ<ê9ò9ú;F K7>"/*@28:<B5J=R8Z3b<j5r=z>‚OŠ^’QšI¢9H* I/O HANDLER DATA AREA *************************************************CCBFLG„DS.B„2ŒFlags(CCBERAD1‚DS.B„4ŒErrordebugsaveaddress2CCBQVER1‚DS.B„4ŒEventqueueingerrordebugaddress7CCBCCB„DS.B„4ŒPhysicaladdressofcommandpacket(IOCB)CCBTASKB‚DS.B„4ŒBuffertaskTCB-CCBPKT„DS.B„18‹Eventworkarea(commandtour)0CCBCPKTƒDS.B„18‹Eventworkarea(interrupttour)(CCBPTR„DS.B„4ŒPhysicaladdressofbufferCCBLEN„DS.B„4ŒLengthofbuffer0CCBPTR1ƒDS.B„4ŒPhysicaladdressof2ndarybuffer&CCBLEN1ƒDS.B„4ŒLengthof2ndarybuffer*CCBCID„DS.B„4ŒCMRparameterblockid(DCB)CCBCOPTƒDS.B„2ŒIOCBoptions#CCBCFIGƒDS.B„$26ŠConfigurationdata**‰56bytesremain*9*‰CCBFLGDEFINITIONS:if‚CCBFLG.Bifnot0theRIOmodule$*fortheCCBcannotbeusedforthe*followingreasons:*9*‰CCBFLG.B=$FA=CCBallocationexceeded#ofspecified/*šdevices-noroominRIOtableforthemodule!*’=$FC=noRIOTBLwasallocated/*’=$F5=noroominRIOTBLforthisRIOmodule*™(incorrecttableallocation)**‰PAGE ‰SECTION8 ‰XREFRIOTBLJ******************************************************************************‚RIOSERVICEVECTORTABLE***L*****************************************************************************RIODVR:#*ˆDC.L†RIOINTŽinterruptsvcaddress!*ˆDC.L†RIOCMDŽcommandsvcaddress)*ˆDC.L†RIOINITinitializationsvcaddress**?*Below are the new offset form of service pointers, for new CMR**(‰DC.L†RIOINT-RIODVR†interruptsv. coffset*‰DC.L†RIOCMD-RIODVR†commandserviceoffset.‰DC.L†RIOINIT-RIODVR…initializationsvcoffset‰DC.L†0‰Reserved‰DC.B†0“numberofextrapages‰DC.B†0,0,0reserved‰DC.L†0,0,0reserved 3*ƒ---ƒ---…CONFIGURATIONCONTROLINFORMATION…---ƒ---ŠSPC1$‰DC.B…'032983'ƒdateoflastassembly'‰DC.B†''‡spacemeansnopatchesin.LO#‰DC.B†'4'‡majorVersadosrevision#‰PAGEJ****************************************************************************‰COMMANDTABLE&JUMPTABLE*:*‰Theseareusedbythecommandserviceroutinetojumpto.*‰theappropriateroutinetohandleacommand.*J***************************************************************************CMDTBL:ŠDC.WƒROPENŽOPENcommand.ŠDC.WƒRCLOSECLOSEcommand.ŠDC.WƒROUTONRELAYONcommand. ŠDC.WƒROUTOFFŒRELAYOFFcommand.ŠDC.WƒRSTATŽSTATUScommand.'ŠDC.WƒRENABLENABLEINTERRUPTScommand.(ŠDC.WƒRDSABLDISABLEINTERRUPTScommand."ŠDC.WƒRPLSOŽPULSEDOUTPUTcommand.=NUMCMDSƒEQU„(*-CMDTBL)/2‡Thenumberofcommandsinthetable.*9JMPTBL:ƒDC.WƒOPEN-*Biasestothecorrespondingroutines. ŠDC.WƒCLOSE-* ŠDC.WƒOUTON-*ŠDC.WƒOUTOFF-* ŠDC.WƒSTAT-*ŠDC.WƒENABLE-*ŠDC.WƒDSABLE-* ŠDC.WƒPLSO-**7JMPOFF„EQU„JMPTBL-CMDTBL†Offsetbetweenthetwotables.ŠPAGEJ****************************************************************************+*ˆRIODRIVERINITIALIZATIONSERVICEROUTINE*>*ˆThedriverisenteredhereforeachCCBallocated.‚Morethan:*ˆoneCCBmaybeallocatedforeachRIOmodule.‚OneCCBis>*ˆallocatedforeachinterruptleveltheboardisjumperedto.?*ˆThisroutinecheckstoseeifthereisroomintheRIOTBLfor=*ˆthedeviceID.‚ItsavesthedeviceIDandthememorymapped>*ˆI/OaddressofthedevicethetheRIOTBL.‚Itinitializesthe5*ˆinputPIAofthedeviceifnotalreadyinitialized.B*ˆThisroutinealsocheckstoseeiftheRIOLEDison,indicating<*ˆanI/Ochannelresetwasissuedorapower-up.Ifon,thisA*ˆroutineturnsitoff.Theon/offindicatorisbit#7ofTSTREG.*:*ˆAnerrorcodeissavedintheCCBifthisCCBallocation=*ˆexceedsthemaximumnumberofCCB'sspecifiedduringSYSGEN9*ˆ(SYSGENparameterNRIO),ifnoRIOTBLexistsornoroom*ˆinthetableforthismodule.*$*ˆEntry:‚allregistersareavailable*A5=CCBaddress*I**************************************************************************RIOINIT:ŠPUSHPOINT‘savepointers3ŠMOVE.LƒCCBCHB(A5),A0„getmemorymappedI/Oaddress$ŠMOVE.LRIOTBL,A1ŠgetRIOTBLaddressŠCMP.L‚#0,A1Žisthereone?&ŠBNE.S‚RIOINIT1‹branchifhaveatable8ŠMOVE.B#RIONTBL,CCBFLG(A5)setnotableerrorconditionŠBRARIOINEX1gotoerrorreturnRIOINIT5‚TST.L‚(A1,D3)Œlookforanentryslottosavethisguy5ŠBMI.S‚RIOINIT6‹branchifthiss/ lotisempty-useit/ŠADD.W‚#PIALNG,D3‰notempty,bumptonextentry"ŠSUB.B‚#1,D4Ždecrementthecounter(ŠBNE.S‚RIOINIT5‹branchifmoretosearch4ŠBRA„RIOEXTER‹errorifgothere-noroomforthemap>RIOINIT6‚MOVE.LD2,(A1,D3)‰savethismemorymappedI/Oaddress*E*The input pia ios used exclusively for all input, and is initialized1* to all inputs and muist remain so for all time.*N*The output pia (PIA 2) is used exclusively for all output, and is initializedL*toallinputs.‚Onanychannelwhichisalloctedforoutput,onlytheoutputD*Piawillbesetforoutput.‚Whenthischannelisde-allocated,theH*correspondingoutputPIAbitmustbere-initializedforinput.‚FailureM* to follow this policy will result in impropper operation of input channels.*.ŠMOVE.L‚#0,D0write0toallpiacontrolreg'sŠBSR.SƒRIO.WCR‹doitBŠMOVE.B‚#0,PIA1ADR(A0)„clearalldatadirectionregs(setforinpu!ŠMOVE.B‚#0,PIA1BDR(A0)„clearnext!ŠMOVE.B‚#0,PIA2ADR(A0)„clearnext!ŠMOVE.B‚#0,PIA2BDR(A0)„clearlast2ŠMOVE.B‚#4,D0setcontrolregsfordataregaccess ,ŠBSR.SƒRIO.WCR‹writesaredonebysubroutine&ŠBSR.SƒRIO.CLR‹goclearallinterrupts **‰turnofftheLED*1RIOEXIT1‚CLR.B‚CCBFLG(A5)‰setforgoodallocation3ŠMOVE.LCCBCHB(A5),A1†getmemorymappedI/Oaddress,ŠMOVE.BTSTREG(A1),D1†readthetestregister$ŠBPL.S‚RIOINEX1‹returnifLEDisoff%ŠBCLRƒ#LEDSTA,D1‰cleartheLEDonbit&ŠMOVE.BD1,TSTREG(A1)†turntheLEDoff'RIOINEX1:POP_POINT‘recallallpointersŠRTS**‚SubroutinesusedbyRIOINIT:*DRIO.WCR‚EQU*ƒwritesdatainlsbyteofD0toallpiacontrolreg`s.‰MOVE.B‚D0,PIA1ACR(A0)‰MOVE.B‚D0,PIA1BCR(A0)‰MOVE.B‚D0,PIA2ACR(A0)‰MOVE.B‚D0,PIA2BCR(A0)‰RTS›endRIOWCR**RIO.CLRƒEQU*ƒclearanypendinginterrupts*‰MOVE.B‚PIA1ADR(A0),D0‰MOVE.B‚PIA1BDR(A0),D0‰MOVE.B‚PIA2ADR(A0),D0‰MOVE.B‚PIA2BDR(A0),D0‰RTS›endRIOCLRŠPAGEJ***************************************************************************$*‰RIODRIVERCOMMANDSERVICEROUTINE*6*‹PARAMETERADDRESSANDBOUNDARYCHECKSHAVEBEENMADE**ƒEntry:‚JSRFROMCMRHANDLER.*‹A2-PHYSICALADDRESSOFCMRPARAMETERBLOCK*‹A5-PHYSICALADDRESSOFCCB*5*ƒExit:‚RTS-PARAMETERBLOCKVALIDATIONSTATUSIND0**ƒREGISTERSUSED:ƒ01234567 *”D******** *”A**P**PP*"*”A3=RIOPARAMETERBLOCKADDRESS*”A6=REQUESTORTCBADDRESS**ƒEXECROUTINESCALLED:‚QEVENTI**ƒCODEISRE-ENTRANT*****J***************************************************************************RIOCMD:*)*‰ConvertlogicalPBaddresstophysical.* ŠCLR.L‚D5;ŠMOVE.LXIOCPK(A2),D6†SetupaddressofRIOparameterblock:ŠMOVE.WXIOPLN(A2),D5†SetuplengthofRIOparameterblock+ŠMOVE.LCCBTASKA(A5),A1„SetupTCBpointer.&ŠBSR„IOHADRCK‹Callconversionroutine.ŠBRA.S‚CMD010Goodreturn.ŠNOP—Badlengthreturn. ŠCLR.L‚D0;ŠMOVE.B#RTCDPBLK,D0‡SetupinvalidparameterblockaddressŠBRARIOCEX2gotoerrorexit*!*‰seeifpassedtheinitializeok*CMD010„CLR.L‚D02ŠMOVE.LƒD6,A3ŒStagephys.addr.opfRIOpara.blk.4ŠTST.B‚CCBFLG(A5)‰errorcodesetinCCBduringINIT?/ŠBEQ.S‚CMD020branchifnoerrorcode,continue$ŠMOVE.BCCBFLG(A5),D0†seterrorcode%CMDSRTRƒBRA.S‚RIOCEX2Œgotoerrorexit CMD020„EQU**,*‰getRIOTBLaddressintoA4forcommanduse* ŠMOVE.LRIOTBL,A4ŠRIOTBLaddress)ŠCMP.L‚#'!RIO',(A4)‡reallyistheRIOTBL?,ŠBEQ.S‚CMD030branchifreallyistheRIOTBL4ŠMOVE.B#RIONTBL,D0ˆseterrorreturncode-notableŠBRA.S‚CMDSRTRŒandreturn**‰findRIO-IDinRIOTBL*‰A1=entryaddress*0CMD030„MOVE.LXIOCID(A2),D0†getspecifiedRIO-ID(ŠMOVE.BRIONMAX(A4),D1…max#ofRIO-ID's$ŠMOVE.L#RIONTRY,D2ˆbumppastheader"FNDRIO10‚CMP.L‚(A4,D2),D0‰amatch?!ŠBEQ.S‚FNDRIO20‹branchifamatch&ŠADD.W‚#RIOIDLNG,D2‡bumptonextentry1ŠSUB.L‚#1,D1Ždecrementnumberofentriestocheck&ŠBNE.S‚FNDRIO10‹branchifmoreentries.ŠMOVE.W#RIONID,D0‰error-RIO-IDnotintable3ŠBRA„C/ MDSRTRŒreturntoCMRwitherrorconditionset+FNDRIO20‚MOVE.LA4,A1ŽbassaddressoftableŠADD.L‚D2,A1Žaddressofentry*(*‰Findthecommandinthecommandtable.*-ŠMOVEQ‚#NUMCMDS-1,D0†Setuptheloopcounter./ŠLEA„CMDTBL,A0ŠA0<--addressofcommandtable.+ŠMOVE.WCMDCOD(A3),D6†getRIOcommandcode.8CMDSRCHƒCMP.W‚(A0)+,D6‹Searchthetableforthecommand.ŠDBEQƒD0,CMDSRCH‰*3ŠBNE.S‚CMDERRIfwefoundthecommandinthetable,8ŠADD.L‚#JMPOFF-2,A0‡getthecorrespondingentryfromthe5ŠMOVE.W(A0),D0Œjumptableandjumptotheroutineto"ŠJMP„(A0,D0.W)Šhandlethecommand.DCMDERR„MOVE.B#RIOINVD,D1ˆdidn'tfindcommandcode-exitwitherrorŠSPC1RIOCEX2:;ŠMOVE.WƒD0,CMDSTA(A3)‡writeerrorcodetousersRIOparablRIOCEX1:ŠRTSŠPAGEL*****************************************************************************‰OPENCOMMANDA*‰Thiscommandassignsthelogicalconnectionbetweenausertask:*‰andspecifiedchannelswithinanRIOmodule.16channels?*‰maximummaybespecifiedinoneopencommand.InterruptlevelB*‰ofthechannelsaretakenfromtheCCB.Theinterruptslevelsof4*‰inputchannels0-7mustmatchthefollowingorder:-*‰channels0-1musthavesameinterruptlevel-*‰channels2-3musthavesameinterruptlevel-*‰channels4-5musthavesameinterruptlevel-*‰channels6-7musthavesameinterruptlevelD*‰Itisokforallthesechannelstohavethesameinterruptlevels.*#*‰RIOOPENcommand‚parameterblock: *DS.W‚1„returnedcommandstatus*DS.W‚1„commandcode(01)*DS.W‚1„#ofchannelstoopen*DS.W‚1„1stchannelnumber*DS.W‚1„channelconfiguration*’.*DS.W‚1„nthchannelnumber*DS.W‚1„channelconfiguration**‰configurationbyte:*bit0=1outputchannel*•=0inputchannel*bit1=1disableinterrupt*•=0enableinterrupt"*bit2=1interruptonrisingedge*•=0interruptonfallingedge)*bit3=1wake-uptaskoninputinterrupt,*•=0queueeventtotaskonintputinterrupt8*Œbits8-14=‚debounceinterval.‚0=nodebounce,otherwise-*˜debouncetimeisvaluetimes4milliseconds$*bit15=1usedefaultconfiguration *•=0usespecifiedconfiguration**‰Defaultconfiguration:*channels0-7’channels8-15*------------’-------------*inputchannel‘outputchannel*interruptenabled*interruptonfallingedge*queueeventoninterruptB*‰Whendefaultconfigurationisspecified,theactualconfiguation9*‰issavedinRIOTBL.ThetaskTCBaddressisalsosaved.*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:CLRPIAM,SETPIA,DOPIA*L**************************************************************************** PAGE*OPEN:*‰seeifchannelalreadyopened* ŠPUSHPOINT‘savealladdressregsŠALLOCATEƒCHCONFIG4ŠBSRCLRPIAMclear(to$FF)thePIAmapforthisRIOŠCLR.L‚D7‘channelcounter:ŠCMP.W‚#RIONID,D0‰anerrorreturnedfromclearingthemap?'ŠBEQ„OPNOIDbranchifanerrorreturned$ŠCLR.L‚D2‘channeloffsetintoRIOTBL)ŠCLR.L‚D1‘offsetintoRIOparameterblock1ŠMOVE.WCMDCHN(A3),D0†get#ofchannelsspecified-ŠBLE„OPNINCbranchifnegativeorzero,error2ŠCMP.W‚#16,D0cannotspecifymorethan16channels,ŠBGT„OPNINCbranchifgreaterthan16,errorGOPEN10„MOVE.WNUMCHAN(A3,D1),D2‚getchannelnumberfromRIOparam.blk.ŠMOVE.WD2,D5Žsaveit0ŠMULUƒ#CHANLNG,D2ˆgetchanneloffsetintoRIOTBLŠADD.L‚#4,D2ŽbumppastRIO-ID+ŠTST.W‚(A1,D2)Œthischannelalreadyopened?+ŠBPL„OPNOPNbranchifalreadyopened,errorŠADD.L‚#1,D7Žcountthischannel@ŠMOVE.WCHNCNFG(A3,D1),D3‚getconfigurationfromRIOparam.blk.-ŠSTORE„D3,CHCONFIG†savechannelconfiguration*ŠBMI.S‚OPEN60branchifdefaultsspecifiedŠBTSTƒ#0,D3Žoutputchannel?&ŠBNE.S‚OPEN70branchifoutputchannel**‰setthischannelforinput* ŠMOVE.WD3,D4Žsaveconfiguration"ŠCMP.B‚#8,D5Žseeifchannel#8-153ŠBGE.S‚OPEN50branchifchannel8-150 ,nointerrupts3ŠMOVE.BCCBPPRIO(A5),D4„getintrruptlevelfromCCBŠASL.L‚#4,D4Žgetintobits4-6$ŠOR.WƒD4,D3Žsavetheinterruptlevel*6*‰checktoseethatinterruptlevelsofchannelsmatch*,OPEN20„MOVE.BD5,D6ŽsavethischannelnumberŠBTSTƒ#0,D5Žoddchannel?*ŠBNE.S‚OPEN30branchifoddchannelnumber*ŠADD.B‚#1,D6Ževen-getchannelnumber+1ŠBRA.S‚OPEN40andcontinue/OPEN30„SUB.B‚#1,D6Žodd-getchannelnumber-15OPEN40„MULUƒ#CHANLNG,D6ˆgetchanneloffsetintotableŠADD.L‚#4,D6ŽbumppastRIO-ID#ŠTST.W‚(A1,D6)Œthischannelopened?"ŠBMI.S‚OPEN50branchifnotopened9ŠMOVE.WRIOCNIF(A1,D6),D6‚getotherchannelconfigurationŠSPC2ŠBTSTƒ#0,D6Žaninputchannel?,ŠBNE.S‚OPEN50branchifnotaninputchannel$ŠASR.L‚#4,D6Žgetintoloworderbits**‰goodconfiguration0*‰saveTCBaddressandconfigurationinformation* OPEN50„EQU†*.ŠLOAD…D3,CHCONFIG†recallchannelconfiguration+ŠBSR„SETPIAgosetPIAmapforthischannel5ŠCMP.W‚#RIONID,D0‰anerrorfoundduringthesavemap?*ŠBEQ.S‚OPNERRbranchifanerrorwasfound6ŠMOVE.WD3,RIOCNIF(A1,D2)‚saveconfigurationinRIOTBL)ŠMOVE.LA6,RIOTCB(A1,D2)ƒsaveTCBaddress4ŠADD.W‚#OPNTRY,D1‰bumptonextRIOparam.blk.entry3ŠSUB.W‚#1,D0Ždecrementnumberofchannelsspecified)ŠBGT„OPEN10branchifmorechannelstodo,ŠBSR„DOPIAŽgosetthePIAhardwareregisters!ŠCMP.W‚#RIONID,D0‰anerrorfound?7ŠBEQ.S‚OPNERRbranchifanerrorwasfound-don'topenŠCLR.L‚D0‘setforgoodreturnŠBRA.S‚OPNXITgoreturntoCMR**‰defaultconfigurationset*%OPEN60„CMP.W‚#7,D5Žseeifchannel0-7!ŠBLE.S‚OPEN80branchifmaybe0-7!ŠCMP.W‚#16,D5seeifchannel8-16-ŠBGT.S‚OPNCNŽbranchifgreaterthan16,error**‰outputchannel*,OPEN70„MOVE.W#1,D3ŽsetoutputconfigurationŠBRA.S‚OPEN50gosaveit**‰inputconfigurationspecified*-OPEN80„TST.W‚D5‘mustbechannel#0orgreater)ŠBLT.S‚OPNCNŽbranchiflessthan0,errorŠCLR.W‚D3‘setfordefaults/ŠMOVE.BCCBPPRIO(A5),D3„getCCBinterruptlevelŠASL.L‚#4,D3Žputintobits4-6ŠBRA.S‚OPEN20gosaveit**‰openerrorshere*;OPNINT„MOVE.W#RIOIINT,D0ˆsetinvalidinterruptlevelerror.ŠBRA.S‚OPNERRgo'de-open'anyopenedchannels>OPNCN…MOVE.W#RIOICNS,D0ˆsetillegalchannel#specifiederror.ŠBRA.S‚OPNERRgo'de-open'anyopenedchannels8OPNINC„MOVE.W#RIOINC,D0‰setinvalid#ofchannelserrorŠBRA.S„OPNXIT‹exit;OPNOID„MOVE.W#RIONID,D0‰setRIOmodulenotallocatederrorŠBRA.S‚OPNXITgoreturntoCMR9OPNOPN„MOVE.W#RIOPND,D0‰setchannelalreadyopenederror*)*‰resetanyopenedchannelstonotopened*%OPNERR„TST.W‚D7‘anychannelstoundo?3ŠBEQ.S‚OPNXITbranchifnonetoundo,returntoCMR&ŠMOVE.W#$FFFF,D3Šset'un-opened'codeŠCLR.L‚D1‘clearforuse6OPNERR10‚MOVE.WNUMCHAN(A3,D1),D2‚getachannelnumber$ŠMULUƒ#CHANLNG,D2ˆgetchanneloffsetŠADD.L‚#4,D2Žbumppastheaders*ŠMOVE.WD3,(A1,D2)‰setthisentryunopened-ŠADD.W‚#OPNTRY,D1‰bumptonextchannelnumberŠSUB.W‚#1,D7Ždecrementcounter&ŠBGT.S‚OPNERR10‹branchifmoretoundo** Fall into exit* OPNXIT EQU * ŠADD.L„#8,A7ŒdeallocateCHCONFIGŠPOP_POINT‘restoreallpointers ŠBRANRMEXITŠPAGEK*****************************************************************************‰SETPIA*7*‰BuildthePIAmapentriesforthespecifiedchannels.*‰Builds1entrypercall*‰MapisinRIOTBL.**‰Entry:A4ƒ=RIOTBLaddress*D3.W=channelconfiguration*D5.B=channelnumber*7*‰Exit:‚D0.W=RIONIDifmapentrynotfound,otherwise*—D0unchanged *‰Uses:D4,D6*‰Entrypoint=SETPIA*‰Exitpoint‚=SETPIART**L******************************************************************************‰findmapentry* SETPIA EQU *ŠPUSHPOINT‘saveallpointersŠMOVE.LD7,-(A7)‹saveD75ŠMOVE.WRIOPIA(A4),D7†getoffsettostartofPIAmaps.ŠMOVE.BRIONAL(A4),D6†get#ofRIO'Sallocated3ŠMOVE.LCCBCHB(A5),D4†getmemorymappedI/Oaddress=SETPIAFD‚CMP.L‚PIADDR(A4,D7),D4ƒfindthematchingI/Oaddress0 ŠBEQ.S‚SETPIA00‹branchiffound$ŠADD.W‚#PIALNG,D7‰bumptonextentryŠSUB.B‚#1,D6Ždecrementcounter0ŠBNE.S‚SETPIAFD‹branchifmoreentriestosearch>ŠMOVE.W#RIONID,D0‰setforfatalerror-thisshouldn'thappen ŠBRA.S„SETPIART‰returntocaller**‰determinechannelnumber*SETPIA00‚CLR.L‚D6‘clearforuse/ŠMOVE.BD5,D6ŽcopychannelnumbertoworkspaceŠCMP.B‚#7,D5Žchannel0-7?ŠBLE.S‚SETPIA20‹branchif0-7**‰channel8-15*/ŠSUB.B‚#8,D6Žgetbit#offsetofchannelnumberŠBTSTƒ#0,D3Žanoutputchannel?0ŠBNE.S‚SETPIA10‹branchifyes,anoutputchannel**‰channel8-15asinputchannel*%ŠBCLRƒD6,DODR815(A4,D7)‚setforinput ŠBRA.S‚SETPIART‹returntocaller* *‰channel8-15asoutputchannel*SETPIA10 EQU *0ŠBSET…D6,DODR815(A4,D7)ƒsetddrimageforoutput ŠBRA.S‚SETPIART‹returntocaller* *‰channel0-7*%SETPIA20‚BTSTƒ#0,D3Žaninputchannel?,ŠBEQ.S‚SETPIA30‹branchifyes,inputchannel**‰CHANNEL0-7asoutputchannel*/ŠBSETƒD5,DODR07(A4,D7)ƒsetddrimageforoutput#SETPIART‚MOVE.L(A7)+,D7‹restoreD7ŠPOP_POINT‘restoreallpointersŠRTS—returntocaller**‰channel0-7asinputchannel*SETPIA30‚EQU*$ŠBCLRƒD5,DODR07(A4,D7)ƒsetforinput1ŠBSR„NEWSETPŒinitPIAcontrolregsforinterrupts ŠBRA†SETPIARTŠPAGED********************************************************************&*ˆNEWSETPisinterruptsetupforPIA's&*ˆNEWSETPinitializesonePIApercall** Private subroutine for SETPIA** Table driven pia setup::*‚PIAICMSK‚isatableofPIAinterruptcontrolmaskwords.N*‚TheLSbyteisAND'edwithmapentry,andtheMSbyteisOR'dwithmapentry‰SPC3PIAICMSK EQU *-‰DC.W†$05FD…enablefallingirqonevenport#‰DC.W†$04FE…disableeven‰DC.W†$07FF…enablerising‰even‰DC.W†$04FE…disableevenA*----------------------------------------------------------------‰DC.W†$0CEF…enablefallingˆodd‰DC.W†$04F7…disableodd‰DC.W†$1CFF…enablerising‰odd‰DC.W†$04F7…disableoddŠSPC3)PIAMGOFFEQU*‚IRQcontrolimageoffsets:‰DC.B†2‰DC.B†3‰DC.B†0‰DC.B†1‰SPC3NEWSETP:ŠSPC1L*Generate index into table of interrupt control masks based on configuration * and even / odd channel number:(*Configurations are between 00X and 11X.**On entry (data input:)%*ˆD3.W‚containschannelconfiguration*ˆD5.B‚containschannelnumber%*ˆD7„containsoffsettoPIAmapstart**‰PUSHALL–saveall ‰CLR.L…D0/‰MOVE.B„D3,D0…getIRQconfig.toworkingregD0+‰AND.B…#$0004,D0‚selectIRQconfigdatabit‰TST.B…D0ˆsetupforbranches7‰BMI.S…SETPIA33‚branchondefaultconfigurationrequest8‰BEQ.S…SETPIA32‚branchonfallingedgeirqconfiguration‰CMP.B…#4,D0…risingedgeirq?7‰BEQ.S…SETPIA32‚branchonrisingedgeirqconfiguration1‰MOVE.L„#2,D0…onallotherconfig.'s,disableirq6SETPIA32ƒEQU‚*ƒnowdetermineeven/oddchannelnumber"‰BTST†#0,D5…evenoroddchannel#?(‰BEQ.S…SETPIA31‚branchonevenchannel#"‰ADD‡#8,D0…add8foroddchannel##SETPIA31ŠEQU*…rejoinmainsequence ‰CLR.L…D18‰MOVE.W„PIAICMSK(PC,D0),D1‚fetchcontrolwordfromtable)‰MOVE.L„D3,D0…getnewcopyofconfigdata5‰AND.L…#$00000008,D0‚selectwakeup/queeventdatabit ‰MOVE.L„#21,D4„setupshiftcount2‰LSL.L…D4,D0„positionwakeup/queventbitinbit24‰SPC1)‰AND.L…#$0000FF00,D3‡selectdebouncedata1‰LSL.L…#8,D3…positiondebouncedatainbits16-23‰OR.L†D3,D1…adddebouncedata-‰OR.L†D0,D1…addwakeup/queventdataatbit248‰BSR‡WRITMAPƒwritetheinterruptcontroldatatoPIAmap7SETPIA33‚EQU‚*‚branchherefornochangeinirqsetting‰POPALL˜restoreregistervalues‰RTS‰PAGEWRITMAP:#*ˆWritesinterruptdatatoPIAmap.*ˆInputparameterstoWRITMAP:*ˆD5ƒchannel# *ˆD7ƒoffsettostartofPIAmaps$*ˆA4ƒRIOTBLaddressforcurrentuser;*ˆD1.LPIAcontrolmaskword(bits16-23aredebouncedata)!*¤(bit24iswakeup/queventbit).*>*ˆTranslateschannelnumbertoPIAregisterimagemapaddress,4*ˆthenmodifysthemapimagebasedondatainD1.L.21 *ˆNowtranslatechannelnumberintoPIAmapoffset* ‰CLR.L…D0/‰MOVE.B„D5,D0…putchannel#intoworkingregD0"‰LSR.B…#1,D0…dividechannel#by2*;*‡PIAchannelindexnowinD0;nowaddoffsetfromPIAMGOFF*‡(piaimageoffsettable)*;‰ADD.B…PIAMGOFF(PC,D0),D7‚addoffsettochannelIRQcontrol$‰ADD.B…#8,D7…bumptoregisterimages**ˆD7containsoffsettoPIAmap*.‰AND.B…D1,(A4,D7)‚modifyPIAcontrolregimage0‰LSR.L…#8,D1…bringORbyteintoworkingposition-‰OR.B†D1,(A4,D7)‚modifyPIAcontrolregimage.‰LSR.L…#8,D1…bringdebouncedataintoposition/‰OR.B†D1,-1(A4,D7)‚adddebouncedatatoPIAmap*‰LSR.L…#1,D1‡bringwakeup/quebittobit7(‰AND.B…#$80,D1Šselectwakeup/queventbit.‰OR.B†D1,(A4,D7)„addwakeup/quebittoPIAmap‰RTS‰PAGED*********************************************************************:*‰DOPIA‚Copytheinterruptcontroldataanddatadirection3*informationfromthePIAregisterimages(inmap)*tothePIAregisters.*A*‚ThePIAmustnotbeallowedtogenerateaninterruptduringtheE*‚initializationprocessbecausetheCMRandRIOtableshavenotbeen@*‚setup.‚Toenforcethis,allinteruptsaredisabledduringthe@*‚codesectionwherethePIAcontrolreg.'sareset,andthePIA*‚interruptflagsarecleared.**ˆENTRYPARAMETERS:*A4=addressofRIOTBL*A5=addressofCCB***‰Exit:‚D0.W=RIONIDifPIAmapnotfound*D0.W=0ifnoerrorsfound**‰Uses:A0,D1,D6,D7**D*********************************************************************;*‚CLRIRQisanANDmaskusedtoclearPIAIRQcontrolbits.*"CLRIRQƒEQU‡$E4‡clearsbits0,1,3,4*** DOPIA EQU *ŠPUSHPOINT’saveallpointers!ŠMOVE.LD7,-(A7)‹saveregisterD7,ŠMOVE.WRIOPIA(A4),D7†getoffsettoPIAmaps$ŠMOVE.BRIONAL(A4),D6†get#ofRIO'S3ŠMOVE.LCCBCHB(A5),D1†getmemorymappedI/Oaddress>DOPIA10ƒCMP.L‚PIADDR(A4,D7),D1ƒlookforamatching‚I/Oaddress(ŠBEQ.S‚DOPIA20Œbranchiffoundtheentry(ŠADD.W‚#PIALNG,D7‰bumptonextmapentry"ŠSUB.B‚#1,D6Ždecrementthecounter/ŠBNE.S‚DOPIA10Œbranchifmoreentriestosearch9ŠMOVE.W#RIONID,D0‰setforfatalerror(shouldn'thappen) ŠBRADOPIAXbranchtoexitpoint**‰D7containsoffsettoPIAmap(*‰setdirectionregisterofchannels0-7**ˆMASKALLINTERRUPTS* DOPIA20 EQU *0ŠMOVE.WƒSR,D6Œsavepresentinterruptmaskstatus!ŠOR‡#$0700,SRˆmaskallinterrupts***‰Setdirectionregisterforchannel0-73*‰NewlycreatedOUTPUTchannelsmustbesettoOFF.4*‰Todothis,ORnewchannelsbitmapwithdatareg.<*‰(thereislogicalinversion)betweenPIAandfinaloutput.*ŠCLR†D2foruseŠCLR†D1foruse6ŠMOVE.LPIADDR(A4,D7),A0ƒgetmemorymappedI/Oaddress,ŠBSET…#2,PIA2ADR(A0)ƒsetfordataregaccess-ŠMOVE.BƒPIA2ADR(A0),D4ƒgetolddataregvalue+ŠNOT†D4convertdataformattoconventional'ŠBCLR…#2,PIA2ACR(A0)ƒsetforDDRaccess;ŠMOVE.BƒPIA2ADR(A0),D2ƒgetacopyofolddatadirectionreg-ŠAND†D2,D4ŒselectonchannelsthatareoutputŠNOT†D24ŠMOVE.BƒDODR07(A4,D7),D1„getthenewoutputchannelsŠAND†D2,D1Œfindnewchannels:ŠMOVE.BPIA2ADR(A0),D0…readchannel0-7directionregister9ŠOR.BƒDODR07(A4,D7),D0ƒaddinthenewsettinginformation8ŠMOVE.BD0,PIA2ADR(A0)…storeintothedirectionregister,ŠBSETƒ#2,PIA2ACR(A0)…setforoutputfunction4ŠOR.B„D1,PIA2ADR(A0)„setnewOUTPUTchannelsforOFF'ŠNOT…D4converttoinverteddataformat/ŠAND.B„D4,PIA2ADR(A0)ƒaddinolddataregvalue*-*‰Setdirectionregisterforchannels8-16.*>*‰NewlycreatedOUTPUTchannelsmustbesetOFF.‚Todothis,OR>*‰newchannelsbitmaskwithdataregister(thereisalogical3*‰inversionbetweenPIAoutputsandfinaloutputs).*ŠCLR†D2foruseŠCLR†D1foruse,ŠBSET…#2,PIA2BDR(A0)ƒsetfordataregaccess-ŠMOVE.BƒPIA2BDR(A0),D4†getolddataregvalue+ŠNOT†D4convertdatatoconventionalformat'ŠBCLR…#2,PIA2BCR(A0)†setforDDRaccess7ŠMOVE.BƒPIA2BDR(A0),D2†getacopyofolddirectionr1 eg.-ŠAND†D2,D4ŒselectonchannelsthatareoutputŠNOT†D20ŠMOVE.BƒDODR815(A4,D7),D1ƒgetnewdirectionreg.%ŠAND†D2,D1Œselectnewoutputchannels;ŠMOVE.BPIA2BDR(A0),D0…readchannel8-15directionregister:ŠOR.BƒDODR815(A4,D7),D0‚addinthenewsettinginformation8ŠMOVE.BD0,PIA2BDR(A0)…storeintothedirectionregister,ŠBSETƒ#2,PIA2BCR(A0)…setforoutputfunction0ŠOR.BƒD1,PIA2BDR(A0)…setnewoutputchannelsoff'ŠNOT†D4convertdatatoinvertedformat1ŠAND.B„D4,PIA2BDR(A0)ƒreplaceolddataregvalues **ˆClearallPIAinterrupts*‰TST.B…PIA1ADR(A0)‰clearPIA1A‰TST.B…PIA1BDR(A0)‰clearPIA1B‰TST.B…PIA2ADR(A0)‰clearPIA2A‰TST.B…PIA2BDR(A0)‰clearPIA2B*#* Set channels 4-5 IRQ control bits*6ŠMOVE.BPIA2ACR(A0),D0…get0-7outputcontrolregister)ŠAND.B„#CLRIRQ,D0‡negateIRQcontrolbits;ŠOR.BƒOCR07(A4,D7),D0„addchannel4-5interruptinformation*ŠMOVE.BD0,PIA2ACR(A0)…writethenewstuff*,*‰setinterruptinformationforchannels6-7*<ŠMOVE.BPIA2BCR(A0),D0…getchan8-15outputcontrolregister(ŠAND.B„#CLRIRQ,D0‡clearIRQcontrolbits<ŠOR.BƒOCR815(A4,D7),D0ƒsetchannel6-7interruptinformation*ŠMOVE.BD0,PIA2BCR(A0)…writethenewstuff*,*‰setinterruptinformationforchannels0-1*:ŠMOVE.BPIA1ACR(A0),D0…getchan0-7inputcontrolregister(ŠAND.B„#CLRIRQ,D0‡clearIRQcontrolbits;ŠOR.BƒICR07(A4,D7),D0„setchannel0-1interruptinformation*ŠMOVE.BD0,PIA1ACR(A0)…writethenewstuff*,*‰setinterruptinformationforchannels2-3*>ŠMOVE.BPIA1BCR(A0),D0…getchannel8-15inputcontrolregister(ŠAND.B„#CLRIRQ,D0‡clearIRQcontrolbits<ŠOR.BƒICR815(A4,D7),D0ƒsetchannel2-3interruptinformation*ŠMOVE.BD0,PIA1BCR(A0)…writethenewstuffŠCLR.L‚D0‘setforgoodreturn**ˆrestoreinterruptlevel*6ŠMOVE.WƒD6,SRŒreturninterruptmaskstopreviousvalueDOPIAXEQU*˜exitsequenceŠMOVE.Lƒ(A7)+,D7‰restoreD7ŠPOP_POINT‘recallallpointersŠRTS—returntocallerŠPAGEL*****************************************************************************6*‰CLRPIAMƒClearoutthePIAmapforthismemorymapped*“I/Oaddress.*&*‰Entry:A1=RIO-IDaddressinRIOTBL%*A2=addressofCMRparameterblock%*A3=addressofRIOparameterblock*A4=addressofRIOTBL*A5=addressofCCB*A6=addressofusersTCB**‰Uses:‚D4,D6,D7*%*‰Exit:‚D0=RIONIDifanerrorfound**D0=contentsonentryifnoerrorfound*L*****************************************************************************3CLRPIAMƒMOVE.WRIOPIA(A4),D7†getoffsettoPIAmaps.ŠMOVE.BRIONAL(A4),D6†get#ofRIO'Sallocated3ŠMOVE.LCCBCHB(A5),D4†getmemorymappedI/OaddressDCLRPIAM1‚CMP.L‚PIADDR(A4,D7),D4ƒlookformatchingmem.map.I/OaddrŠBEQ.S‚CLRPIAM2‹branchiffound$ŠADD.W‚#PIALNG,D7‰bumptonextentryŠSUB.B‚#1,D6Ždecrementcounter0ŠBNE.S‚CLRPIAM1‹branchifmoreentriestosearch#ŠMOVE.W#RIONID,D0‰seterrorreturnŠRTS—returntocaller*CLRPIAM2‚CLR.L‚DODR07(A4,D7)†clearthemap ŠCLR.L‚OCR07(A4,D7)‡andtherestŠRTS—returntocallerŠPAGEL******************************************************************************‚CLOSECOMMAND*A*‚CloseallconnectionswiththisusertaskandhisopenchannelsB*‚forthisRIOmodule.Thechannelsareputbacktothepre-opened4*‚state.AllI/Oonthisuser'schannelsisstopped.*$*‚RIOCLOSECOMMANDparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode02*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:STOPPIA*L*****************************************************************************CLOSE:+ŠMOVE.L#4,D1ŽbumppastRIO-IDinthetable!ŠCLR.L‚D2‘useforchannelcounter5CLOSE10ƒCMP.L‚RIOTCB(A1,D1),A6ƒchannelforthisuser?*ŠBNE.S‚CLOSE20Œbranchifnotforthisuser2 3ŠMOVE.WRIOCNIF(A1,D1),D0‚getchannelconfiguration4ŠBSR„STOPPIAŒgostopI/OonthischannelD2=chan#?ŠMOVE.W#$FFFF,RIOTCB(A1,D1)setthischannelentrytonotused5CLOSE20ƒADD.L‚#CHANLNG,D1ˆpointtonextchannelentryŠADD.L‚#1,D2Žcountthischannel$ŠCMP.L‚#16,D2searchedallchannels?&ŠBNE.S‚CLOSE10ŒbranchifmorechannelsŠCLR.L‚D0‘setfornoerrorsŠBRA„NRMEXITŒandreturntoCMRŠPAGED*********************************************************************4*‚STOPPIAƒdeactivateI/Oonspecifiedchannelnumber*&*‚Entry:A1=RIO-IDaddressinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‰D0.W=channelconfiguration%*‰D2.L=channelnumbertodeactivate* *‚Uses:‚D0,A0*L*****************************************************************************:STOPPIAƒMOVE.LCCBCHB(A5),A0†getmemorymappedI/OaddressŠCMP.B‚#8,D2Žchannel8-15?&ŠBGE.S‚STOPIA60‹branchifchannel8-15* *‰channel0-7*5ŠBCLRƒ#2,PIA2ACR(A0)…selectoutputdirectionregister/ŠBCLRƒD2,PIA2ADR(A0)…setthischannelforinput0ŠBSETƒ#2,PIA2ACR(A0)…selectoutputdataregister,ŠBCLRƒD2,PIA2ADR(A0)…deactivatethischannelŠBTSTƒ#0,D0Žinputchannel?,ŠBNE.S‚STOPIART‹branchifno,outputchannel*/*‰inputchannel-determineifusinginterrupts* ŠBTSTƒ#1,D0Žinterruptsdisabled?"ŠBNE.S‚STOPIART‹branchifdisabled-ŠBTSTƒ#0,D2Žseeifoddorevenchannelnumber,ŠBNE.S‚STOPIA10‹branchifoddchannelnumber7ŠMOVE.B#1,D0Ževenchan-disableinterruptsbit#is0ŠBRA.S‚STOPIA20‹andcontinue>STOPIA10MOVE.B#4,D0oddchan-disableinterruptsbit#is3.STOPIA20CMP.B‚#1,D2getactualchannelnumber)ŠBGT.S‚STOPIA30‹branchifnotchannel0-15ŠBCLRƒD0,PIA1ACR(A0)…disableinterrupts-channel0-1STOPIART‚RTS—returntocaller.STOPIA30‚CMP.B‚#3,D2Žseeifchannelnumber2-3!ŠBGT.S‚STOPIA40‹branchifnot2-33ŠBCLRƒD0,PIA1BCR(A0)…disableinterruptschannel2-3ŠBRA.S‚STOPIART‹andreturn.STOPIA40‚CMP.B‚#5,D2Žseeifchannelnumber4-5!ŠBGT.S‚STOPIA50‹branchifnot4-53ŠBCLRƒD0,PIA2ACR(A0)…disableinterruptschannel4-5ŠBRA.S‚STOPIART‹andreturn;STOPIA50‚BCLRƒD0,PIA2BCR(A0)…disableinterruptschannel6-7ŠBRA.S‚STOPIART‹andreturnŠPAGE**‰channel8-15*(STOPIA60‚MOVE.LD2,D0Žgetchannelnumber!ŠSUB.L‚#8,D0Žmake0-7typenumber5ŠBCLRƒ#2,PIA2BCR(A0)…selectoutputdirectionregister"ŠBCLRƒD0,PIA2BDR(A0)…setforinput0ŠBSETƒ#2,PIA2BCR(A0)…selectoutputdataregister,ŠBCLRƒD0,PIA2BDR(A0)…deactivatethischannelŠRTS—returntocallerŠPAGEF************************************************************************‰OUTON-TURNONRELAYCOMMAND;*‰Thiscommandactivatesrelaysforspecifiedchannelsthat9*‰havepreviouslybeenopenedforoutputbythesametask<*‰requestingthisactivation.‚Theparameterblockischecked9*‰forerrorsbeforeanyrelayisactivated.‚Nochannelis!*‰activatedifanerrorisfound.9*‰AllchannelswithinaPIAareactivatedsumultaneously.>*‰Outonreadsthepiadataregistertofindthecurrentstate.*%*‰RIOOUTPUTcommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode034*‰DS.Wƒ1ƒbitmaskcontainingchannel#'stoactivate*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:DOOUT**L*****************************************************************************OUTON:ŠPUSHPOINT‘saveallpointers3ŠCLR.L‚D3‘flagtockpara.blk.beforedoingoutput.OUTON10ƒMOVE.L#4,D1ŽbumppastRIO-IDintable!ŠCLR.L‚D2‘useforchannelcounterŠCLR.L‚D0‘clearforuse+ŠMOVE.WCMDCHN(A3),D0†getchannelstostart8ŠMOVE.WƒCMDCHN(A3),D3„copyONrequesttocheckregister.)OUTON20ƒBTSTƒD2,D0Žactivatethischannel?0ŠBEQ.S‚OUTON30Œbranchifno-checknextchannel5ŠCMP.L‚RIOTCB(A12 ,D1),A6ƒchannelbelongetothisuser?"ŠBNE.S‚OUTONERŒbranchifno,error3ŠMOVE.WRIOCNIF(A1,D1),D4‚getchannelconfigurationŠBTST‚#0,D4anoutputchannel?+ŠBEQ.S‚OUTONER1‹branchifnotoutput,error.ŠBCLRƒD2,D3Žnegatecheckflagforthischannel$ŠTST„D3‘isallofparameterchecked?(ŠBNE.S‚OUTON30Œbranchifnotallchecked5ŠBSR„DOOUTŽgoodparameterblock-goactivatechannelŠBRA.S‚OUTONEXŒnormalexit/OUTON30ƒADD.L‚#1,D2Žbumptonextchannelnumber-ŠADD.L‚#CHANLNG,D1ˆbumptonextchannelentry'ŠCMP.L‚#16,D2checkedallthechannels?/ŠBNE.S‚OUTON20Œbranchifmorechannelstocheck*<*Fall into invalid command for error return (error in OUTON)*AOUTONERƒMOVE.W#RIOICU,D0‰setinvalidcommandforthisusererrorŠBRA.S‚OUTONRTŒandreturn?OUTONER1‚MOVE.W#RIOICC,D0‰setinvalidcommandforthischannelŠBRA.S‚OUTONRTŒandreturn$OUTONEXƒCLR.L‚D0‘setforgoodreturn%OUTONRTƒPOP_POINT‘recallallpointersŠBRA„NRMEXITŒgoreturntoCMR‰PAGE** DOOUT…EQU„***A*DOOUT talks directly to the PIA data reg.s and turns on outputs.**‰OnentrytoDOOUT:8*‰D0contains(16bit)bitmaskfordesiredONchannels.<*‰A5containsaddressofCCBfromwhichI/Obaseaddrisob.*-“MOVE.L„A2,-(A7)ŒsaveaddressofCMRparablk*“MOVE.L„CCBCHB(A5),A2‡getI/Obaseaddress#“NOT‡D0’logicinversioninRIOckts*“AND.B…D0,PIA2ADR(A2)†turnonchannels0-7%“LSR.W…#8,D0selectdataforch.8-15+“AND.B…D0,PIA2BDR(A2)†turnonchannels8-15-“MOVE.L„(A7)+,A2ŒrestoreaddrofCMRparablk“RTS‰PAGEM******************************************************************************"*‰OUTOFF-TURNOFFRELAYSCOMMAND=*‰Thiscommanddeactivatesrelaysforspecifiedchannelsthat9*‰havepreviouslybeenopenedforoutputbythesametask<*‰requestingthisactivation.‚Theparameterblockischecked;*‰forerrorsbeforeanyrelayisdeactivated.‚Nochannelis#*‰deactivatedifanerrorisfound.*)*‰RIOOUTPUTOFFcommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode044*‰DS.Wƒ1ƒbitmaskcontainingchannel#'stoactivate*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:DOOFF*L*****************************************************************************OUTOFF:ŠPUSHPOINT‘saveallpointers2ŠCLR.L‚D3‘flagtockpara.blk.beforestopoutput.OUTOF10ƒMOVE.L#4,D1ŽbumppastRIO-IDintable!ŠCLR.L‚D2‘useforchannelcounterŠCLR.L‚D0‘clearforuse+ŠMOVE.WCMDCHN(A3),D0†getchannelstostart0ŠMOVE.WƒD0,D3Œcopychan.toturnofftoworkreg+OUTOF20ƒBTSTƒD2,D0Ždeactivatethischannel?0ŠBEQ.S‚OUTOF30Œbranchifno-checknextchannel5ŠCMP.L‚RIOTCB(A1,D1),A6ƒchannelbelongstothisuser? ŠBNE„OUTONERŒbranchifno,error3ŠMOVE.WRIOCNIF(A1,D1),D4‚getchannelconfigurationŠBTST‚#0,D4anoutputchannel?)ŠBEQ„OUTONER1‹branchifnotoutput,error.ŠBCLR…D2,D3Œnegatecheckflagforthischannel$ŠTST„D3‘isallofparameterchecked?(ŠBNE.S‚OUTOF30Œbranchifnotallchecked3ŠBSR„DOOFFŽgoodpara.block-godeactivatechannelŠBRA.S„OUTOFFXŠnormalexit/OUTOF30ƒADD.L‚#1,D2Žbumptonextchannelnumber-ŠADD.L‚#CHANLNG,D1ˆbumptonextchannelentry'ŠCMP.L‚#16,D2checkedallthechannels?/ŠBNE.S‚OUTOF20Œbranchifmorechannelstocheck ŠBRA†OUTONEROUTOFFXEQU*šnormalexitŠPOP_POINT‘recallallpointersŠCLR.L„D0signalnoerrorsŠBRANRMEXITnormalexit‰PAGE*** DOOFF…EQU**B*DOOFF‚talksdirectlytothePIAoutputregsandturnsoffoutputs*G* On entry: D0 has bit map of channels to turn off (a 1 means turn off)*‹A5hasaddressofuserCCB*:*‰DOOFFiscalledbyOUTOFFandpulsedoutputdeactivation*/ŠMOVE.LƒA2,-(A7)ŒsaveaddressofCMRparablock3ŠMOVE.LƒCCBCHB(A5),A2‡getmemorymappedI/Oaddress*D*‚ThereisalogicalinversionbetweenPIA3 outputsandfinaloutputs**ŠOR.B…D0,PIA2ADR(A2)†turnoffselected0-71ŠLSR.W„#8,D0selectinformationforchannels8-15+ŠOR.B…D0,PIA2BDR(A2)†turnoffselected8-152ŠMOVE.Lƒ(A7)+,A2ŒrestoreaddressofCMRparablockŠRTSŠPAGEM******************************************************************************!*‰STAT-GETINPUTSTATUSCOMMAND;*‰Thiscommandreadsthestatusofspecifiedinputchannels=*‰thatdonothaveinterruptsenabled.‚Thechannelsmusthave>*‰previouslybeenopenedforinputbythisuser.‚Theparameter>*‰blockischeckedforerrorsbeforeanyinputstatusisread.A*‰Theusersparameterblockismodifiedtosignalactivechannels<*‰bysettingthecorrespondingbitinthebit-maskword.The;*‰correspondingbitnumberofinactivechannelsiscleared.**.*‰AllchannelsinaPIAsidearereadatonce.*+*‰RIOINPUTSTATUScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode05<*‰DS.Wƒ1ƒbitmaskcontainingchannelsnumberstoreadstatus$*”(thisisalsothereturnedfield)*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:GTSTAT*M******************************************************************************STAT:ŠPUSHPOINT‘saveallpointers(ŠCLR.L‚D5‘useforreturnedstatusvalues2ŠCLR.L‚D3‘flagtockpara.blk.beforereadstatus.STAT10„MOVE.L#4,D1ŽbumppastRIO-IDinRIOTBLŠCLR.L‚D2‘channelcounterŠCLR.L‚D0‘clearforuse;ŠMOVE.WCMDCHN(A3),D0†getchannelnumberstoreadstatuson3ŠMOVE.WD0,D3Žcopychanactivationreq.bitpattern/STAT20„BTSTƒD2,D0Žreadstatusforthischannel?ŠBEQ.S‚STAT40branchifno5ŠCMP.L‚RIOTCB(A1,D1),A6ƒchannelbelongstothisuser?1ŠBNE„OUTONERŒbranchifno-returnwitherrorset3ŠMOVE.WRIOCNIF(A1,D1),D4‚getchannelconfigurationŠBTSTƒ#0,D4Žaninputchannel?9ŠBNE„OUTONER1‹branchifnotinput-returnwitherrorset'ŠCMP.B‚#8,D2Žseeifchannelnumber8-156ŠBGE.S‚STAT30branchif8-15-donotcheckinterrupts,ŠBTSTƒ#1,D4Žischan1-7,setforinterrupts?2ŠBEQ„OUTONER1‹branchifsetforinterrupts-error6STAT30„BCLRƒD2,D3Žclractivationflagforthischannel*ŠTST„D3‘finishedcheckingparameterblock?1ŠBNE.S‚STAT40branchifnotfinishedcheckingyet.ŠBSR„GTSTATgoreadstatusandsaveinREG.D5!ŠBRA.S‚STAT50gotoprocedureexit3STAT40„ADD.L‚#CHANLNG,D1ˆbumptonextchannelentry(ŠADD.L‚#1,D2Žbumptonextchannelnumber#ŠCMP.L‚#16,D2checkedallchannels?,ŠBRA„STAT20branchtochannelchecksequenceXX‚(stampcoupling)?*‚Returnparameters:‚none(sideeffects;writestoPIActlreg)* DOENBL EQU *3‰LEA‡ENBLIRQ(PC),A1†getaddressofenable_irqtable3‰BSR‡MODIFYPIAŒmodifyPIAcontrolregIRQ1ctlbits‰RTS‰PAGE *MODIFYPIA**†It'sfunctionsare:0*ˆa.TowriteinterruptcontroldatatoPIAmaps=*ˆb.TowriteinterruptcontroldatatoPIAcontrolregisters*>*‹ItperformsthesetwofunctionsbeinvokingWRITMAP&DOPIA.+*‹ItDOESNOTMODIFYDEBOUNCECONTROLDATA.***ˆInputparameters:/*’A1„addressofenable/disableconstanttable*’D2„channel#*’A4„RIOTBLaddress*’D1„XXX>*ˆOutputparameters:‚none(sideeffects;writesPIAregisters)*MODIFYPIA EQU * ‰CLR.L…D7‰MOVE.L„D2,D5ˆsetupchannel#2‰MOVE.W„RIOPIA(A4),D7‡getoffsettouser'sPIAmap ‰BTST†#0,D2…evenoroddchannel?"‰BNE.S…MODF1…branchonoddchannel-‰MOVE.W„(A1),D1ƒgetevenchannelcontrolmask ‰BRA.S…MODF2 MODF1 EQU ***ˆstagecodeforWRITMAP*1‰MOVE.W„2(A1),D1‚getoddchannelIRQcontrolmask MODF2 EQU *2‰BSR‡WRITMAPƒwritethenewinterruptstatustomap,‰BSR‡DOPIA…writethenewcontroldatatoPIA‰RTS‰SPC10*ENBLIRQEQU*†tableforusebyDOENBLonly@*‚MSbyteisOR'edwithcontroldata,LSbyteisAND'edwithit.%‰DC.W†$01FF…enableirqevenchannel#$‰DC.W†$08FF…enableIRQoddchannel#;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ŠPAGEM******************************************************************************%*ˆDSABLE-DISABLEINTERRUPTSCOMMAND>*‰Thiscommanddisablesinterruptsforthespecifiedchannels.<*‰Thechannelsmusthavebeenopenedforinputbythisuser,4 ?*‰mustbechannels0-7only,andmustcurrentlyhaveinterrupts;*‰enabled.‚Theparameterblockischeckedforerrorsbefore>*‰anyinterruptsaredisabled.Nochannelsaredisabledifany*‰errorisfound.*1*‰RIODISABLEINTERRUPTScommandparameterblock: *‰DS.Wƒ1ƒreturnedcommandstatus*‰DS.Wƒ1ƒcommandcode07B*‰DS.Wƒ1ƒbitmaskcontainingchannelnumberstodisableinterrupts*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB**‚Calls:DODSABL*M*****************************************************************************DSABLE:ŠPUSHPOINT‘saveallpointers7DSABL10ƒMOVE.L#4,D1ŽsetD1tochanconfig.entry(row)!ŠCLR.L‚D2‘useforchannelcounter1ŠCLR.L‚D0‘clearforuseaschannelactiv.bitmap4ŠMOVE.WCMDCHN(A3),D0†getchannelactivationbitmap+ŠCMP.W‚#$FF,D0Œcannotspecifychannels8-153ŠBGT„ENABLERŒbranchif8-15-returnwitherrorset(DSABL20ƒBTSTƒD2,D0Ždisablethischannel?)ŠBEQ.S‚DSABL30Œbranchifnotthischannel-ŠCMP.L‚RIOTCB(A1,D1),A6ƒbelongstothisuser?0ŠBNE„OUTONERŒbranchifno,returnwitherrorset3ŠMOVE.WRIOCNIF(A1,D1),D4‚getchannelconfigurationŠBTSTƒ#0,D4Žaninputchannel?8ŠBNE„OUTONER1‹branchinnotinput,returnwitherrorsetŠBTSTƒ#1,D4Žinterruptsenabled?1ŠBNE„OUTONER1‹branchifno,returnwitherrorset/ŠBSET…#1,D4Œdisableinterruptsforthischannel>ŠMOVE.WƒD4,RIOCNIF(A1,D1)ƒstoreoutirqdatainconfig.RIOTBLŠPUSHALL“saveallregs!ŠBSR„DODSABLŒgodoactualdisableŠPOPALL”restoreall(DSABL30ƒADD.L‚#1,D2Žbumptonextchannel-ŠADD.L‚#CHANLNG,D1ˆbumptonextchannelentry"ŠCMP.L‚#8,D2Žcheckedallchannels?&ŠBNE.S‚DSABL20Œbranchifmorechannels)ŠBRA†ENABLOKŠreturnwithstatus=noerrsŠPAGE**.*DODSABL is a local subroutine for DSABLE only**ƒInputparameters**’D2.W‚channel#*’A4„RIOTBLaddress*?*‚Returnparameters:‚none(sideeffects;writestoPIActlreg)* DODSABL EQU *3‰LEA‡DSBLIRQ(PC),A1†getaddressofenable_irqtable3‰BSR‡MODIFYPIAŒmodifyPIAcontrolregIRQ1ctlbits‰RTS*** DSBLIRQ‚EQU‡*.‰DC.W†$00FE…disableIRQonevenchannelnumber%‰DC.W†$00F7…disableIRQoddchannel#;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -‰PAGEM*******************************************************************************ˆPLSO-PULSEDOUTPUTCOMMAND*)*‚Entry:A1=addressofRIO-IDinRIOTBL%*‰A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A4=addressofRIOTBL*‰A5=addressofCCB*‰A6=addressofusersTCB***‰ExitstoNRMEXIT***Parameter block format for pulsed output:*0*RIO parameter block (pointed to by A3 on entry)* *ˆDS.W†1‰returnedcommandstatus*ˆDS.W†1‰commandcode*ˆDS.W†1‰numberofchannels<*ƒ---ƒ---ƒ---ƒparametersforindividualchannelsƒ---ƒ---ƒ---*ˆDS.W†1‰firstchannelnumber,*ˆDS.L†1‰numberofmillisecondsforpulseon*ˆ.*ˆ.*ˆDS.W†1‰nthchannelnumber5*ˆDS.L†1‰numberofmillisecondsfornthchannelpulse*7* EACH CHANNEL IS ACTIVATED IN TURN (NON-SYNCHRONOUSLY)**M***************************************************************************** PLSO:*@*ƒPulsed_Out(IN:LISTOFchannelactivationrequest,pulsetimes;*ˆOUT:errorcode)>‰ALLOCATECHANID,RIOPARBK†allocatechannelid&RIOparablock3‰STORE…A3,RIOPARBK‰saveRIOparameterblockaddress**†Initiatepulsedoutput*!‰CLR.L…D6’clearworkingregisters ‰CLR.L…D3’. ‰CLR.L…D2’. ‰CLR.L…D0’.*$*ˆgetnumberofchannelstoactivate*<‰MOVE.W„CMDCHN(A3),D0‡getnumberofchan'sfromRIOparablk**‡WHILEchannelcount>0*PLSO1:$‰TST.W…D0’loopon#ofchan.'stodo ‰BEQ‡PLSOX**ˆDO**‡getfirstchannelnumber* ‰CLR.L…D5‰MOVE.W„NUMCHAN(A3,D6),D5$‰STORE…D5,CHANID‹savechannelnumber*G* Channel ID will consist of user CCB address + chan numbe4 r in LS byte.*+‰MOVE.L„A5,D7copyuser'sCCBaddresstoD75‰ADD.L…D7,CHANID(A7)‡CHANIDnowhascompletechan.ID"‰MOVE.L„D5,D7copychannel#toD7,‰BSR‡BIN_BITconvertbinarytobitmapinD5*)*‚IFchannelbelongstocurrentuserTHEN*6‰MULU†#CHANLNG,D7‰computeoffsettonthchaninRIOTBL%‰ADD‡#4,D7bumptouserTCBinRIOTBL-‰CMP.L…RIOTCB(A1,D7),A6„compareTCBaddresses1‰BNE.S…PLSOER1branchonchannelnotcurrentuser**ˆDO'*ˆGetchannelconfigurationfromRIOTBL*8‰MOVE.W„RIOCNIF(A1,D7),D3ƒgetchannelconfigfromRIOTBL*&*‚IFchannelisanoutputchannelTHEN* ‰BTST†#0,D3.‰BEQ.S…PLSOER2ƒbranchonnotanoutputchannel**„DO2*…GetpulsetimefromRIOcommmandparameterblock*‰MOVE.L„CHNCNFG(A3),D3*%*„IFpulsetime>pulse_min_timeTHEN*'‰BEQ.S…PLSOER3ƒbranchonpulsetime=0**„DO-*†requestperiodicactivation(thischannel#)*2‰LEA‡PLSOFF(PC),A0‡pointtopulseturnoffroutine%‰CLR.L…D1’setrequestfor1timeonly6‰MOVE.B„CCBPPRIO(A5),D1…setact.prioritysameastask/‰LOAD†D2,CHANID‹setupchannelIDtogotoPLSOFF'‰MOVE.L„D3,A1setupactivationinterval‰PUSHALL"‰TR0$.RQPA˜passrequestforwakeup*)*‚Ifnoerrinperiodicact.requestTHEN*‰BRA.S…RQPAOKŽgoodreturn(‰BRA.S…PLSOER4errinperiodicact.req.**†DO*RQPAOK:‰POPALL(‰PUSHALL—amoreelegantwaytodothis?*"*ˆactivate_this_channel(channel#)*$‰MOVE.L„D5,D0passbitmasktoDOOUT ‰BSR‡DOOUT‰POPALL**†END*ƒEND*ƒdecrementchannelcount* ‰SUB‡#1,D0**END* ‰BRA‡PLSO1**ˆErrorhandling*PLSOER1‚CLR.L…D00‰MOVE.B„#RIOICNS,D0‰channelnotforcurrentuser ‰BRA.S…PLSOX1PLSOER2: ‰CLR.L…D00‰MOVE.B„#RIOICC,D0Šchannelnotanoutputchannel ‰BRA.S…PLSOX1PLSOER3:"‰CLR.L…D0’requestedpulsetime=03‰MOVE.B„#RIOCNFG,D0‰return'badconfiguration'code ‰BRA.S…PLSOX1PLSOER4:‰POPALL ‰CLR.L…D0+‰MOVE.B„RIOBSY,D0‹periodicactivationerror ‰BRA.S…PLSOX1Žreturndevicebusy‰SPC2** Pulsed output good exit point*;PLSOX„LOAD†A3,RIOPARBK‰restoreRIOparablockaddresstoA3‰CLR.L…D0ˆsetfornormalreturnPLSOX1: ‰ADD.L…#12,A7*‰BRA†NRMEXIT„gotonormalcommonexitpoint‰PAGE**‡PULSEDOUTPUTDEACTIVATION:**ˆPulsedoutputde-activation.!*ˆEnteredbyperiodicactivation. *ƒOnentry:?*ˆD1containschannelIDcomposedofuser'sCCBaddressinM.S.8*ˆ3bytes,andchannelnumber(0-15)inleastsig.byte.*PLSOFF:‰PUSHALL&‰MOVE.B„D1,D5savecombinedchannelID ‰AND.B…#0,D1recoverCCBaddress+‰MOVE.L„D1,A5stageCCBaddressfor'DOOFF'+‰AND.L…#$000000FF,D5‡recoverchannelnumber,‰BSR‡BIN_BITconvertchan#tobitmapinD5"‰MOVE.L„D5,D0stagedataforDOOFF‰BSR‡DOOFFturnoffchannel‰POPALL‰RTE‰PAGEBIN_BIT:*$* Binary to bit-map conversion in D5*J*Produces a 1 in D5 corresponding to the value in D5 (in binary) up to 15.@*ˆForinput>15binarytheresultantpatterninD5isundefined*‰ALLOCATE‚BITMAP‰CLR.L…BITMAP(A7)‰ADD.W…#1,BITMAP(A7) LOOP…SET‡* ‰TST.W…D5‰BEQ‡BINBITXexitonbitfound‰ROL.W…BITMAP(A7) ‰SUB‡#1,D5 ‰BRA‡LOOP BINBITXŒEQU‡*‰MOVE.W„BITMAP(A7),D5‰DEALOC„BITMAP‰RTSŠPAGEO******************************************************************************** *ˆNORMALEXIT*,*‚Entry:A2=addressofCMRparameterblock%*‰A3=addressofRIOparameterblock*‰A5=addressofCCB*‰A6=addressofusersTCB*‰D0=RIOerrorcode*I**************************************************************************NRMEXIT:>ŠMOVE.WD0,CMDSTA(A3)†setreturnstatusinRIOparameterblockŠRTS—returntoCMRŠPAGEJ****************************************************************************ˆKILR(KILLER)*4*“Routinecalledtohandleunrecoverableconditions.**K****************************************************************************KILR: ‰TR0$.KILLERŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BO5 UNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLINGTASKSADDRESSSPACE.*#*ENTRY:ƒD5‚-NO.OFBYTESTOCHECK*ŠD6‚-68000ADDRESS(LOGICAL)*ŠA1‚-TCBADDRESS*** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1**7*EXIT:„D6-PHYSICALADDRESSOFBUFFERBASE(IFLEGAL)*ŠRETURNTOPC„FORGOODADDRESS*”PC+2‚FORBADLENGTH*”PC+4‚FORBADADDRESS*F*********************************************************************** IOHADRCK:%ŠBTSTƒ#0,D6‘Mustbeonworkboundary.)ŠBNE.S‚IOHADR4Branchifbadbufferbase.ŠTST.L‚D5”Lengthcan'tbezero.2ŠBEQ.S‚IOHADR8Don'tgotologphywithzerocount. IOHADR2ƒEQU„*1ŠMOVE.LTCBTST(A1),A0‰Addressoftaskseg.table. ŠTR0$.LOGPHY.ŠBRA.S‚IOHADR8Branchforgoodaddressreturn.0ŠBRA.S‚IOHADR6Branchforbadbytecountreturn.(ŠTST.L‚D5”Wasanentrypointerreturned.#ŠBEQ.S‚IOHADR4Branchifno-ERROR)ŠTST.B‚7(A0,D5)ŽIsthisanMMIOsegment?ŠBNE.S‚IOHADR8Yes,OK.3IOHADR4ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.3IOHADR6ƒADD.L‚#2,(A7)AdjustPCforinvalidreturn.IOHADR8ƒRTSšReturn.ŠPAGEI***************************************************************************ˆGETTCBROUTINE*)*’ENTRY:A0=POINTERTOTASKANDSESSION***’EXECROUTINE*’REGISTERSUSED:D0-D1/A0-A1***’EXIT:A0=TCBADRESS**˜RETURNTOPC„FORGOODTASKSPECIFICATION!*¢PC+2‚FORBADTASKSPECIFICATION**J***************************************************************************GETTCB: ŠTR0$.GETTCB&ŠBRA.S„GETT10ŽGoodtaskspecification.ŠNOPšBadtaskspecification.&ŠADD.L„#2,(A7)Badtaskspecification.GETT10„RTSšReturn.ŠPAGEJ**************************************************************************** INTERRUPT SSERVICE ROUTINE*?*ƒPURPOSE:‚HANDLETHERIOINTERRUPTSANDNOTIFYTHEUSEROFTHE5*INTERRUPTS.‚OPERATESATHARDWAREINTERRUPTPRIORITY*LEVEL.*1*ƒENTRY:‚JSR‚FROMINTERRUPTHANDLERROUTINE-CMR*‹A0-WORKREGISTER *‹A1=SELF*‹A5=ADDRESSOFCCB*‹D0=WORKREGISTER*5*ƒEXIT:‚RTS-BACKTOINTERRUPTHANDLERROUTINE-CMR*C*ŠInterrupthandlermustpruservealldatareg.'s&addressreg.'s.***ƒREGISTERSUSED:ƒ01234567 *”D******** *”A*****P****ƒEXECROUTINESCALLED:‚QEVENTI**ƒCODEISRE-ENTRANT**?*‚Debounceoninterruptadded9/13/82.‚Debounceis0to512ms,9*‚encodedinbits8-14ofthechannelconfigurationword.I*‚Thescalefactorfordebouncetimeis4mspercountinch.config.wd.*F*---------------------------------------------------------------------*RIOINT:*<* Find RIO TABLE module (board) name which matches CCB name:*-ˆMOVEM.L„A0-A6/D1-D7,-(A7)„saveallexceptD0:ˆALLOCATEƒRIOTADR,CHANUM,CLAIMCHKƒallocatelocalvariables/ˆCLR.L†CLAIMCHK(A7)…clearinterruptclaimcheck-ˆMOVE.L…RIOTBL,A2‰getaddressofRIOTBLtoA2 ˆCLR.L…D76ˆMOVE.B„RIONMAX(A2),D7…getmaxnumberofRIOID'stoD7#ˆMOVE.L„CCBMNEM(A5),D0…getccbname2IOHI011EQU*‚findmatchingRIOIDloopentrypoint*ˆMOVE.L„RIOID(A2),D3‡getRIOIDforstaging'ŠCMP.LƒD3,D0ŽdoesCCBnamematchRIOID?#ŠBEQ.SƒIOHI020Œbranchonnamematch,ŠADDA.W‚RIOOFST,A2‰addoffsettonextRIOTBL#ŠSUB.Bƒ#1,D7ŽtestforendofRIOTBL*ŠBMI…IOHIPXŠbranchtoexitifidnotfound ŠBRAIOHI011 IOHI020ƒEQU**F*‚Foundmatchingnames,nowgetnumberofinterruptingchannel(toD2)2*‚andclearhardwareinterruptflaginPIAdevice.*%‰STORE…A2,RIOTADRŠsaveRIOTBLaddress,‰MOVE.L„#$0C010000,D2‡initparafieldsinD2)‰BSR‡IOHICLRclrirq&getint.channel#+‰STORE…D2,CHANUM‹savechan.#&returncode*>* Compute address of field in RIOTBL having user's TCB address* ŠCLR.L„D4!ŠMOVE.BƒD2,D4getchannel‚toD4.B)ŠCMP.B„#8,D4channelmustbe<8orerror'ŠBEQ.S„IOHIPXŒexitonchannelnotfound1ŠADD.L„#1,CLAIMCHK(A7)ƒmarkinterruptacknowledge2ŠMULU…#6,D4pointtodatafieldassocwithchannel5ŠADD†#RIONTRY,D4‡addoffsetto1stchanneldatafieldŠADD†#4,D4addinsizeofRIOID-ŠMOVE.LƒRIOTBL,A2‰ge5 taddressofRIOTBLtoA26ŠMOVE.L‚RIOTCB(A2,D4),A6„A6nowhasuser'sTCBaddress*"*IF channel requires debounce THEN*3ŠMOVE.WƒRIOCNIF(A2,D4),D0ƒgetchannelconfiguration(ŠAND†#$7F00,D0‹selectdebouncetimedata…IF.L†ŠTHEN*„DO;*ˆRequestperiodicactivation(CCB_adr,chan_#,debounce_time)6*ˆGeneratechannelID=CCBaddress+channel#toD2:**‰MOVE.L„A5,D7copyboardCCBaddresstoD7‰ADD.B…D2,D7addchannelnumber/‰MOVE.L„D7,D2stagechannelIDforperiod.act..‰LEA‡DEBOUNCE(PC),A0…pointtodebounceroutine!‰CLR.L…D1’request1periodicact.1‰MOVE.B„CCBPPRIO(A5),D1…setprioritysameastask&‰LSR‡#8,D0positiondebouncetimedata-‰MULU†#4,D0multiplybydebouncedelayfactor ‰MOVE.L„#0,A1*‰MOVE.W„D0,A1stagetimeforperiodicact..‰LINK†A6,#-(ALLREGS+4)…addsomeextraroom(4)*I* NOTE: LINK has reserved space on the stack for all registers + 4 words.A*‡NowIcandoMOVEM.Ltothestackwithoutautoincorautodec.B*‡andaslongasIgetbackA6unchanged,UNLINKA6willtakecare+*‡ofadjustingthestackpointercorrectly.*.‰MOVEM.LƒA0-A6/D0-D7,(A7)„saveallreg.values ‰TR0$.RQPA*/*‡IFnoerrorreturnedfromper.act.req.THEN*,‰BRA.S…DBACTOKgoodreturnfromper.act.req.+‰BRA.S…DBACTNGbadreturnfromper.act.req.*‡DO*DBACTOK‚EQU‡*‰Debounceact.req.returnok**ŠDisableIRQonthischannel.%*ŽStageargumentsforcalltoDODSABL*0‰MOVEM.Lƒ(A7),A0-A6/D0-D7„recallregistervalues.‰MOVE.L„RIOTADR+4(A6),A4„recallRIOTBLaddress#‰AND‡#$000000FF,D2‡selectchannel#+‰BSR‡DODSABLdisableIRQ.note:ck'9/15/82*DBACTNG„EQU…*‰debounceact.req.returnNG*ˆENDƒdisableIRQ0‰MOVEM.Lƒ(A7),A0-A6/D0-D7„recallregistervalues‰UNLK„A6*…END†debouncesetupsequence†ELSE**…hereifnodebouncerequired*.‰LOAD†D2,CHANUM‹recallchannel#&returncode‰BSR‡NOTIFYUSR†ENDI$IOHIPX„EQU*‡'RIOINT'procedureexit+‰LOAD‚D0,CLAIMCHKŒgetinterruptclaimcheck#‰ADD‡#16,A7Žreleaselocalvariables0‰MOVEM.Lƒ(A7)+,A0-A6/D1-D7ƒrestoreallexceptD0+‰TST.L…D0’doesRIODRVclaimthisinterrupt?‰IF.L‚THEN(‰ORˆ#1,SRsignalCMR'interrupthandled'‰ELSE2‰AND‡#$FFFE,SR‹signalCMR'interruptnotfromRIO'‰ENDI‹RTS…PAGE NOTIFYUSR:*A*ˆnotifyuserbymeansofqueeventorwakeupasspecifiedinthe*ˆchannelconfigurationword.**„INPUTPARAMETERS:'*’A2:AddressofchannelnameinRIOTBL;*’D4:Offsetfromchannelnametochanneldatafield(base) *™inRIOTBL.*’A5:AddressofchannelCCB.ÁªA³;»4ÃLË*’A6:User'sTCBaddress#*’D2:$0C01**@ŠMOVE.WƒRIOCNIF(A2,D4),D0getchannelconfigurationfromchannel *¤configurationtableinRIOTBL.)ŠBTST…#3,D0determine:wake-uporq-event ‰IF…‰THEN**ˆDO*ˆEnqueueevent;datastaging:*$*ƒD2=$0C01 *ƒD3=RIOID*ƒD4=MemmappedI/Oaddress*ƒA6=User'sTCBaddress*8ŒMOVE.LƒCCBCHB(A5),D4…getmem.mappedI/OaddressstagedŒBSRQUEVENTenqueuetheeventŒRTS˜andreturntocaller*‰ELSE*DO%ŒMOVE.LƒA6,A0ŽstageusersTCBaddress#ŒTR0$.WAKEUP,issuewakeuptouser*ENDŒENDIŒRTS™returntocaller‰PAGE=*‚IOHICLRdeterminesiftheinterruptisforthisRIOmodule.E*‚IftheinterruptisnotforthischannelD2contains'8'onreturn.C*‚IftheinterruptisforthisRIOmodule,theinterruptingchannelI*‚numberisreturnedinD2‚TheinterruptinthePIAisclearedherealso.**‚Inputparameters:%*’A5:PointstotheI/Obaseaddress.*‚Outputparameters:(*’D2:Containsinterruptchannelnumber.* IOHICLR EQU *0ŠMOVE.LCCBCHB(A5),A0ˆgetI/ObaseaddresstoA08ŠBTST.Bƒ#0,PIA1ACR(A0)…ischannel#0setforinterrupts?/ŠBEQ.S„IOHIO01Œbranchifnotset-checkchan18ŠBTST.Bƒ#7,PIA1ACR(A0)…setforint6 errupt-isthereone?(ŠBNE†IOHI021ŒbranchonIRQfoundonch0$IOHIO01ƒADD#1,D2“bumpchannelcount5ŠBTST.Bƒ#3,PIA1ACR(A0)…ischan.1setforinterrupts?/ŠBEQ.S„IOHIO02Œbranchifnotset-checkchan28ŠBTST.Bƒ#6,PIA1ACR(A0)…setforinterrupt-isthereone?*ŠBNE.SIOHI021branchonIRQfoundonch1$IOHIO02ƒADD#1,D2“bumpchannelcount4ŠBTST.B‚#0,PIA1BCR(A0)†ischan2setforinterrupts?*ŠBEQ.SƒIOHIO03branchifno-checkchan38ŠBTST.Bƒ#7,PIA1BCR(A0)…setforinterrupt-isthereone?*ŠBNE.S„IOHI022ŒbranchonIRQfoundonch2$IOHIO03ƒADD‚#1,D2’bumpchannelcount4ŠBTST.B‚#3,PIA1BCR(A0)†ischan3setforinterrupts?*ŠBEQ.SƒIOHIO04branchifno-checkchan48ŠBTST.B‚#6,PIA1BCR(A0)†setforinterrupt-isthereone?*ŠBNE.S‚IOHI022ŽbranchonIRQfoundonch3&IOHIO04ƒADD#1,D2“bumpchannelcounter4ŠBTST.Bƒ#0,PIA2ACR(A0)…ischan4setforinterrupts?*ŠBEQ.S„IOHIO05Œbranchifno-checkchan58ŠBTST.Bƒ#7,PIA2ACR(A0)…setforinterrupt-isthereone?*ŠBNE.SIOHI023branchonIRQfoundonch4&IOHIO05ƒADD#1,D2“bumpchannelcounter4ŠBTST.B‚#3,PIA2ACR(A0)†ischan5setforinterrupts?-ŠBEQ.SƒIOHIO06branchifno-gocheckchan68ŠBTST.B‚#6,PIA2ACR(A0)†setforinterrupt-isthereone?*ŠBNE.SIOHI023branchonIRQfound‚onch5&IOHIO06ƒADD#1,D2“bumpchannelcounter4ŠBTST.B‚#0,PIA2BCR(A0)†ischan6setforinterrupts?-ŠBEQ.S„IOHIO07Œbranchifno-gocheckchan78ŠBTST.B‚#7,PIA2BCR(A0)†setforinterrupt-isthereone?*ŠBNE.SIOHI024branchonIRQfound‚onch6&IOHIO07ƒADD#1,D2“bumpchannelcounter4ŠBTST.B‚#3,PIA2BCR(A0)†ischan7setforinterrupts?2ŠBEQ.SƒIOHIONObranchifno-thisinternotforme8ŠBTST.B‚#6,PIA2BCR(A0)†setforinterrupt-isthereone?*ŠBNE.SIOHI024branchonIRQfound‚onch77IOHIONOƒADD#1,D2“setchan#=8=interruptnotforme ŠRTS™returntointerrupthandler5IOHI021ƒTST.B„PIA1ADR(A0)ˆreadingdataregclearsIRQŠRTS™andreturn-IOHI022ƒTST.BƒPIA1BDR(A0)‰cleartheinterruptŠRTS™andreturn(IOHI023ƒTST.BƒPIA2ADR(A0)‰clearIRQflagŠRTS™andreturn(IOHI024ƒTST.BƒPIA2BDR(A0)‰clearIRQflag‰RTSšandreturn‹PAGE'*‹DEBOUNCE-interruptdebounceroutine3*‹Controlreturnsherewhentheperiodicactivation*‹requesttimeexpires.*ƒInputparameters:**’D1:CCBaddress+channel#(inlsbyte)* DEBOUNCE:‰PUSHALLsaveallregisters*F*‚IF(((channelconfig=risingedgeIRQ)AND(channelstate=up))ORH*†((channelconfig=fallingedgeIRQ)AND(channelstate=down)))THEN*0*…ComputeoffsetforthischannelintheRIOTBL:*5‰MOVE.L„#$0C010000,D2‡setupdatafiledsforNOTIFYUSR!‰CLR.L…D3’clearworkingregisters ‰CLR.L…D4’. ‰CLR.L…D6’.%‰MOVE.B„D1,D4extractchannel#toD46‰MOVE.B„D4,D2completestageofchandatatoNOTIFYUSR*‰MOVE.B„D4,D3savecopyofchannel#inD35‰MULU†#6,D4pointtodatafieldforchannelinRIOTBL7‰ADD‡#RIONTRY+RIOCNIF,D4addoffsetto1stchanneldata*'*ˆGetchannelI/OaddressbasefromCCB*'‰AND‡#$FFFFFF00,D1‡clearlsbyteinCCB#‰MOVE.L„D1,A5putCCBaddressonA5*‰MOVE.L„CCBCHB(A5),A1‡getI/Obaseaddress*+*ˆFindRIOTBLdatasectionforthischannel*+‰MOVE.L„RIOTBL,A2‹getaddressoftheRIOTBL ‰CLR.L…D70‰MOVE.L„CCBMNEM(A5),D0†getchannelnamefromCCB1‰MOVE.B„RIONMAX(A2),D6†getmaxnumberofRIOTBL's LOOP…SET‡*.‰MOVE.L„RIOID(A2),D5ˆgetchannelnamefromCCB%‰CMP.L…D5,D0channelname=CCBname? ‰BEQ.S…FOUND13‰ADD.W…RIOOFST,A2ŠbumptonextRIOID(channelname)!‰SUB‡#1,D6decrementloopcounter*‰BEQ.S…DBERRerrifchannelnamenotfound ‰BRALOOPFOUND1:/‰MOVE.L„RIOTCB(A2,D4),A6†getuser'sTCBaddress3‰BTST†#2,RIOCNIF+1(A2,D4)ƒconfig=risingedgeIRQ? ‰IF…‡THEN*%* DO if set for rising edge interrupt*-‰BTST†D3,PIA1ADR(A1)†channelstatus=hinow? IF‚ƒTHEN*9*‰DO‚notifyuserifstillonrisingedge-goodinterrupt*ŒPUSHALL”saveallregsŒBSR„NOTIFYUSRŒPOPALL•restorallregs**‰END„ofinterruptonrisingedgesequenceˆENDIˆELSE*?*„Elsethechannelconfigurati6 onisforfallingedgeinterrupt.!*†DO‚seeifstillonfallingedge*-‰BTST†D3,PIA1ADR(A1)†channelstatus=lonow? †IF‚ƒTHEN*5*†Channelstatus=lo‚-notifyuserofgoodinterrupt*†DO‰PUSHALL‰BSRNOTIFYUSR‰POPALL"*†END‚offallingedgeIRQsequence‡ENDI**‚ENDƒofdebouncesequence*ƒENDI*"*ˆEnableIRQondebouncedchannel:***BEGINstageparametersforcalltoDOENBL*%‰AND.L…#$000000FF,D2‡selectchannel#&‰MOVE.L„A2,A4getRIOTBLaddresstoA4)‰CLR.L…D1’setdebouncedatafieldtonull.‰BSRDOENBL”invokeroutinetoenableinterrupt*END*/DBERREQU*‚debounceerr;riotblnamenotfound+‰POPALLŽrestoreallregistersbeforereturn‰RTE›returntoO.S.‰PAGE*H*‚QUEVENT‚enqueue'seventtodrivingtaskusingdatastagedinregisters *‹asfollows:**‹A6=user'sTCBaddress&*‹D2=$0C01*‹D3=RIOID‚(modulename)*‹D4=memmappedI/Oaddress** QUEVENT EQU *‹PUSHALL”pushallregs"‹MOVE.L…A6,A0Žstageuser'saddress ‹TR0$.QEVNTI)‹BRA.SƒQUEVNTOKŒgoodreturnforqueevent'‹BRA.SƒQUEVNTERŒbadreturnfromqueventQUEVNTOK EQU *‹POPALL•restoreallregs‹RTS QUEVNTER:(‹BRAQUEVNTOKputabreakherefordebug*‰ENDééééé=/* =/*†RIOLIB.AF=/*7=/* Chain file to assemble FORTRAN-callable subroutines%=/* to interface with the RIO driver.=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to RIOLIB.LS=/*=/IFC \1ƒ=ARGRIOLIB.LS=/ENDIF=/*=ASM RIOLIB.SA,RIOLIB.RO,\1;R=/*{ Included files are:=/*ƒ--none--=/*}=/*=ENDééé7 éééÓFTRIO…IDNTƒ1,0RIOsubroutines**‰FORTRANcallablesubroutines*‰forRIOdrivercalls*$*‰CALLRIOCMD(rio_id,param_blk_addr)*‰whereRIOCMDmaybe:*)*‰CALLRIOPEN(rio_id,param_blk_addr)…open**‰CALLRIOCLS(rio_id,param_blk_addr)…close3*‰CALLRIOOUT(rio_id,param_blk_addr)…outputlatched/*‰CALLRIOOFF(rio_id,param_blk_addr)…outputoff+*‰CALLRIOSTA(rio_id,param_blk_addr)…status6*‰CALLRIOENB(rio_id,param_blk_addr)„enableinterrupts7*‰CALLRIODSB(rio_id,param_blk_addr)„disableinterrupts2*‰CALLRIOPLS(rio_id,param_blk_addr)„outputpulsed*,*‰Allargumentsforthecallsareidentical.7*‰Thecontentsoftheparam_blkforeachcallisunique*‰tothecall.*6*‰Allthecommandsubroutinescallacommonsubroutine3*‰RIOSETtobuildtheinitiateI/Oparameterblock.**‰STACKFORALLCALLS:*7*‰deepeststack:(stackaddressstaysatRIOSETreturn)0*˜commandcodeƒ2bytes(initiateI/Oparam.blk) *˜n/aŒ2bytes*˜rio_id‰4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes *˜n/aŒ4bytes,*˜commandaddrƒ4bytes(riocommandaddress)**˜commandlng„2bytes(riocommandlength)-*˜RIOSETreturn‚4bytesdeepeststackaddress *˜A34bytes *˜A24bytes *˜A14bytes *˜D04bytes*‰entrystack:ƒreturn‰4bytes*˜^param_blk_adr4bytes*˜^rio-idˆ4bytes* ŠSECTION9!ŠXDEFƒRIOPEN,RIOCLS,RIOOUT,RIOOFF!ŠXDEFƒRIOSTA,RIOENB,RIODSB,RIOPLS*$*‰CALLRIOPEN(rio_id,param_blk_addr)*‰openandconfigurechannels*1RIOPEN„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters3ŠBSR„RIOSETset-uptheinitiateI/Oparameterblock)ŠMOVE.L#1,(A2)ŒsettheopencommandcodeRIOPN00ƒCLR.L‚D0‘clearforuse'ŠMOVE.W4(A2),D0‹getnumberofchannelsŠASL.L‚#2,D0Žmultiplyby4.RIOPN05ƒADD.L‚#6,D0Žaddinthe6byteoverhead-RIOPN10ƒMOVE.WD0,(A1)Œsetthecommandlength-ŠMOVE.LA3,A0ŽTRAP#1parameterblockaddress#ŠMOVE.L#60,D0CMRdirectivenumberŠTRAPƒ#1‘callRMS68K'ŠMOVE.WD0,(A2)Œsetthereturnedstatus)ŠMOVEM.L(A7)+,D0/A1-A3„restoreregisters!ŠMOVE.L(A7)+,A0‹putreturninA0ÜAå8í ŠLEA„8(A7),A7‹cleanupthestackŠJMP„(A0)returntouser*$*‰CALLRIOCLS(rio_id,param_blk_addr)"*‰closeallchannelsforthisuser*1RIOCLS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock*ŠMOVE.L#2,(A2)Œsettheclosecommandcode&ŠMOVE.W#4,D0ŽRIOclosecommandlengthŠBRA„RIOPN10ŒgodotheCMRcall*$*‰CALLRIOOUT(rio_id,param_blk_addr)'*‰activateoutputonrequestedchannels*1RIOOUT„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#3,(A2)Œsettheoutputcommandcode*RIOUT10ƒMOVE.Wƒ#6,D0ŒsetupcommandlengthŠBRA„RIOPN10ŒgodotheCMRcall*$*‰CALLRIOOFF(rio_id,param_blk_addr))*‰deactivateoutputonspecifiedcha7 nnels*1RIOOFF„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock/ŠMOVE.L#4,(A2)Œsettheoutputoffcommandcode4ŠBRA„RIOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLRIOSTA(rio_id,param_blk_addr))*‰readinputstatusonspecifiedchannels*1RIOSTA„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#5,(A2)Œsetthestatuscommandcode4ŠBRA„RIOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLRIOENB(rio_id,param_blk_addr).*‰enableinterrptsonspecifiedinputchannels*1RIOENB„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock+ŠMOVE.L#6,(A2)Œsettheenablecommandcode4ŠBRA„RIOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLRIODSB(rio_id,param_blk_addr)0*‰disableinterruptsonspecifiedinputchannels*1RIODSB„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock,ŠMOVE.L#7,(A2)Œsetthedisablecommandcode4ŠBRA„RIOUT10Œgosetcommandlength&dotheCMRcall*$*‰CALLRIOPLS(rio_id,param_blk_addr)>*‰activateoutputforx#ofmillisecondsonspecifiedchannels*1RIOPLS„MOVEM.LD0/A1-A3,-(A7)„savesomeregisters5ŠBSR.S‚RIOSETset-uptheinitiateI/Oparameterblock2ŠMOVE.L#8,(A2)ŒsetthepulsedoutputcommandcodeŠCLR.L‚D0‘clearforuse,ŠMOVE.W4(A2),D0‹getspecified#ofchannelsŠASL.L‚#2,D0Žmultiplyby6ŠADD.W‚4(A2),D04ŠBRA„RIOPN05Œgosetcommandlength&dotheCMRcallŠPAGE*4*‰RIOSETsetuptheCMRinitiateI/Oparameterblock,*‰returns:ƒA1=addressforRIOcommandlength(*”A2=RIOcommandparameterblockaddress)*”A3=initiateI/Oparameterblockaddress*(RIOSET„CLR.W‚-2(A7)clearcommandlength-ŠLEA„-2(A7),A1Šsaveaddressofcommandlength$ŠMOVE.L24(A7),A0Šgetparam_blk_addr%ŠMOVE.LA0,-6(A7)Šsaveparam_blk_addr,ŠMOVE.LA0,A2Žsaveparam_blk_addrforreturnŠCLR.L‚-10(A7)ŒnotusedŠCLR.L‚-14(A7)ŒnotusedŠCLR.L‚-18(A7)ŒnotusedŠMOVE.L28(A7),A0Šget^rio_idŠMOVE.L(A0),-22(A7)‡getrio_idŠCLR.W‚-24(A7)Œnotused0ŠMOVE.W#$0700,-26(A7)…initiateI/Ocommandcode4ŠLEA„-26(A7),A3‰initiateI/OparameterblockaddressŠRTS—returntocallerŠENDééé‰SPC10!*†---†---…STANDARDƒMACROS…---…---*H*Allocate macro allocates local storage as long words on the stack,(A7).,*Up to 6 variables may be allocated by name.C*These variables may then be referred to by name offset to stack orH*they may be stored to (by macro STORE) and loaded from (by macro LOAD).*O*Prior to exit, the variables must be de-allocated by invocation of DEALLOCATE. ALLOCATE MACRO*B*Allocate reserves storage on the stack for local named variables,8*‚whicharereferredtoasanoffsetfromstackpointer.\1 SET 2‰IFGT(NARG-1)\2 SET 6‰ENDC‰IFGT(NARG-2) \3 SET 10‰ENDC‰IFGT(NARG-3) \4 SET 14‰ENDC‰IFGT(NARG-4) \5 SET 18‰ENDC‰IFGT(NARG-5) \6 SET 22‰ENDC*ƒSUB.Lƒ#(NARG*4)+4,A78 *ƒENDM*B*DEALLOCATEMACRO‚hastobenamedDEALOCtoovercomeassemblerbug DEALOC‚MACRO*>* Deallocate removes storage for local variables on the stack.ƒADD.L‚#(NARG*4)+4,A7*ƒENDMI*LOAD macro allows loading a register from local storage named variables. *Thesyntaxis:‚LOADRn,VARNAME.9*The storage is DYNAMICALLY ALLOCATED by macro 'ALLOCATE'* LOAD‚MACRO*‰MOVE.L„\2(A7),\1‰ENDM*H*STORE macro allows storing a register to local storage named variables.!*Thesyntaxis:‚STORERn,VARNAME.?*The local storage is DYNAMICALLY ALLOCATED by macro 'ALLOCATE'* STORE MACRO*‰MOVE.L„\1,\2(A7)‰ENDM*‰SPC5PUSHPOINTŠMACRO‰MOVEM.LƒA0-A6,-(A7)‰ENDM*POP_POINTŠMACRO‰MOVEM.Lƒ(A7)+,A0-A6‰ENDM* PUSHALLŒMACRO‰MOVEM.LƒA0-A6/D0-D7,-(A7)‰ENDM* POPALLƒMACRO‰MOVEM.Lƒ(A7)+,A0-A6/D0-D7‰ENDM*4ALLREGS‚EQU‡68ˆSpaceforallthereg.'sinthestack** *NOW USE THEM *MACTEST:* *ˆPUSHPOINT *ˆPUSHALL&*ˆALLOCATECOUNT,POINT,CHAR,VAL,MURPHY*ˆMOVE.L„#12345,D1*ˆSTORE†D1,COUNT*ˆLOAD‡D2,COUNT(*ˆDEALLOCATECOUNT,POINT,CHAR,VAL,MURPHY*ˆPOPALL *ˆPOP_POINT*ˆRTS*ˆEND*‰PAGEõ`**ˆ&.M605MEM.AG*J*==========================================================================*‚CodeaddedtoallocatememoryfortableusedbyDACdriver.6*‚Thiscodeisassembledandlinkedinatsysgentime.*>*‚06/01/84‚psg‚Changedconditionalnamefornewsysgenmethod.*‚01/11/84‚bwn*K*==========================================================================‰IFNE„\NVME6055T0PAGAL‚EQU…4‘Pageallocationdirective#forTrap0.6‰XREF„DACTBLŒSYSPARlocationcontainingDACTBLaddress ‰XDEF„M605MEM%‰INCLUDE&.M605DRV.EQ†DACequatefile* ‰SECTIONƒ8 M605MEM‚EQU‡*>DCMEM1ƒMOVE.L#\NVME605,D2‡getnumberofDACmodulesinsystem0‰BEQ.S‚NODACSbranchifnoDACmodulesonsystem<‰MOVE.L#\NU605,D3‰getnumberofinterruptlevelspermodule$‰MOVE.LD2,D4Žsavenumberofmodules!‰MULUƒD3,D4ŽgetnumberofDAC-IDs-‰MULUƒ#DACIDLNG,D4‡get#ofbytesforDAC-IDs%‰ADD.L‚#DACNTRY,D4ˆaddinheadersize)‰MULUƒ#IOLNG,D2‰get#ofbytesforIOmap,‰ADD.L‚D4,D2Ž#ofbytesneededforDACtable‰MOVE.LD2,D5Žsave#ofbytes'‰ADD.L‚#255,D2Œrounduptopageboundry‰ASR.L‚#8,D2Ž#ofpagesneeded'‰BMI.S‚DACERRbranchifnegative,error)‰MOVE.L#0,A0Žclearforallocatingmemory)‰MOVE.WD2,A0Žnumberofpagestoallocate-‰MOVE.L#T0PAGAL,D0ˆpageallocationdirective"‰TRAPƒ#0‘callRMS68Ktogetmemory"‰BRA.S‚DACOKŽbranchifgoodreturn1DACERRƒMOVE.L#32,D0fatalerror-gostopsystem‰TRAPƒ#08DACOK„MOVE.L#'!DAC',DACEYE(A0)setDACtableeyecatcher)‰MOVE.WD5,DACLNG(A0)†#ofbytesintable5‰MOVE.W#DACNTRY,DACOFST(A0)offsettoDAC-IDentries&‰MOVE.WD4,DACIO(A0)†offsettoIOmaps'‰CLR.B‚DACNAL(A0)‰noDACsallocatedyet.‰MOVE.L#\NVME605,D4‡getnumberofDACmodules-‰MULUƒ#\NU605,D4‰getnumberofDAC-IDentries-‰MOVE.BD4,DACNMAX(A0)…maxnumberofDAC-ID's6‰MOVE.LA0,DACTBLŠsavetableaddressinsystemparams.0‰LEA„DACID(A0),A0‡startaddressoftableentries/‰SUB.W‚#DACNTRY,D5ˆnumberofbytestosettoFF‰ASR.W‚#1,D5Žnumberofwordsþ43‰MOVE.W#$FFFF,D4Šstorethisinallentrylocations&DACCLRƒMOVE.WD4,(A0)+‹settheentries‰SUB.W‚#1,D5Ždecrementcounter ‰BNE.S‚DACCLRbranchifnotdone NODACSƒEQU„*‰ENDC*‰END8 ééééééé**ˆ&.M610MEM.AG*„IFNEƒ\NVME610+\NVME620 ŠNOFORMATŠPAGE0PAGAL…EQU„4ŽRMS68KPAGALTrap0directivenumber3KILLER„EQU„32RMS68KKILLERTrap0directivenumberŠOPTƒCRE N*******************************************************************************:*‹InterruptProcessingQueueAllocationandInitialization+*fortheInputModule(VME610/620)Driver*M*ƒThissectionofcodeallocatesmemoryfortheInterruptQueueControlTableM* and the Interrupt Processing Queue used by the Input Module Driver. First aO* page of memory is allocated for the control table and the base address of theJ* table is stored in the INPTBL field of SYSPAR for later retrieval by theN* drivers initialization routine. The table is then initialized and the memoryO* required for the Interrupt Processing Queue is calculated and allocated basedJ* on the SYSGEN parameter M610QSIZ. If all of the required pages of memoryO* cannot be allocated, RMS68K routine KILLER is called to force a system crash.*>*ƒThiscodeislinkedintothe‚SystemInitializerasdescribedK* in the SYSgen instructions for the driver. In the following code, symbolsM* preceeded by a backslash '\' character are user specified SYSgen parametersK* that are replaced with numeric values by the SYSgen SUBS command prior toO* assembly of this source. The parameters are assumed to have been validated inA* in a separate assembly performed earlier in the SYSgen process.*O*******************************************************************************ŠSPC„25ŠXREFƒINPTBLThissymbolisanaddresswithinSYSPAR. ŠXDEFƒM610MEMŠSPC„2 ŠSECTION8ŠSPC„28M610QSIZ‚EQU„\M610QSIZThisisthesizeoftheInterrupt&*£ProcessingQueueintermsofmaximum,*£numberofentriesthequeueistocontain.ŠSPC„2ŠINCLUDE‚&.BAB.EQ*‰INCLUDE‚&.BAB.EQŠINCLUDE‚&.M610INTQ.EQ*‰INCLUDE‚&.M610INTQ.EQ ŠSECTION‚8ŠSPC„2 M610MEM‚EQU‡*9INPMEM„CLR.L‚D0“Clearallregisterstobeusedincalling27 9 3ŠMOVE.LD0,A0ŽtheRMS68Kmemoryallocationroutine. ŠMOVE.LD0,A1 ŠMOVE.LD0,A6ŠSPC„22ŠADD.W‚#1,A0CallRMS68KroutinePAGALtoallocate9ŠMOVE.B#PAGAL,D0Š256bytes(1page)ofmemoryforglobal*ŠTRAPƒ#0‘variablestorage.Ifnomemoryis7ŠBRA.S‚INPM010Œavailable,callRMS68KroutineKILLERto!ŠBSR.S‚INPMKILL‹crashthesystem.ŠSPC„2>INPM010ƒMOVE.LA0,INPTBLŒSavetheglobalvariableareaaddress3ŠMOVE.LA0,A4ŽreturnedbyPAGALintheinputdriver'*£tablepointer(INPTBL)withinSYSPAR.-*£MakeapermanentcopyoftheaddressinA3.ŠSPC„24ŠMOVE.W#63,D0CleartheglobalvariableareatoallINPM020ƒCLR.L‚(A0)+Žzeros.ŠDBRAƒD0,INPM020ŠPAGEI*ƒThefollowingcodeusestheInterruptQueueControlTableandallocates* memory for the queue.ŠSPC„24INPM050ƒCLR.L‚D1’ClearD1foruseasworkregister.ŠSPC„28ŠMOVE.W#M610QSIZ,D5‰Loadthenumberofentriesthatthe(*£InterruptQueueistocontainintoD5.ŠSPC„2<ŠMOVE.L#'IQCT',QID(A4)†InitializetheasciiIDfieldinthe(*£InterruptQueueControlTablewiththe**£mnemonic'IQCT'.Thismnemonicservesas-*£servesasavisualaideinanalysingmemory*£dumpsfordebugging.ŠSPC„28ŠMULUƒ#IQENTLN,D5ŠCalculatethequeuelengthinbytesby**£multiplyingthenumberofentriesinthe"*£queuebythequeueentrylength.ŠSPC„22ŠTST.B‚D5“Calculatetheminimumnumberof256byte7ŠBEQ.S‚INPM055Œmemorypagesnecessarytoaccomodatethe1ŠADD.W‚#256,D5Œspecifiednumberofqueueentries.INPM055ƒLSR.W‚#8,D5ŠSPC„23ŠMOVE.W#15,D0Calculatethebitnumberofthemost=INPM057ƒLSL.W‚#1,D5Žsignificantbitofthenumberofpagesto ŠDBCSƒD0,INPM057‰allocateinD5.ŠSPC„2/ŠBEQ.S‚INPM058ŽIfbitsotherthanjustthemost6ŠADD.W‚#1,D0Žsignificantbitofthenumberofpagesis'*£set,incrementthenumberofthemost-*£significantbittothenexthigherpowerof*£two.ŠSPC„27INPM058ƒCLR.L‚D5“Setthenumberofpagestoallocateto6ŠBSETƒD0,D5Žthelowestpoweroftwothatwillholdthe$*£requestednumberofqueueentries.ŠSPC„2=INPM060ƒMOVE.LD5,A0Loadthenumberofpagestobeallocated:ŠMOVE.L#PAGAL,D0ŠintoA0andcallRMS68KroutinePAGALto2ŠTRAPƒ#0‘obtainthememory.Iftherequiredamount6ŠBRA.S‚INPM070Œofmemoryisnotavailable,callRMS68K>INPMKILL‚MOVE.L#KILLER,D0‰routineKILLERtocrashthesystem.ŠTRAPƒ#0ŠSPC„2?INPM070ƒMOVE.LA0,QPTR(A4)ŠStoretheinterruptprocessingqueue**£baseaddressinthequeuecontroltable.ŠSPC„20ŠASL.W‚#8,D5Convertthelengthoftheinterrupt5ŠSUB.W‚#1,D5Žqueuein256bytepagestothelengthin>ŠMOVE.WD5,QWAMSK(A4)†bytes.Formthequeuewraparoundmaskby)*£decrementingthequeuelengthandstore&*£themaskinthequeuecontrolentry.ŠSPC„2K*ƒThisistheendoftheInputModuleDriversysteminitializationroutine.*ŠFORMAT„ENDC‰ENDéééé9 **ˆ&.M615MEM.AG*J*==========================================================================*‚CodeaddedtoallocatememoryfortableusedbyACOdriver.H*‚Thiscodeisassembledandlinkedintotheapproprateinitializerfile*‚atSYSGENtime.*K*==========================================================================‰IFNE„\NVME6155T0PAGAL‚EQU…4‹Pageallocationdirective#forTrap0.6‰XREF„ACOTBL…SYSPARlocationcontainingACOTBLaddress ‰XDEF„M615MEM*&*ˆINCLUDE&.M615DRV.EQ…ACOequatefile%‰INCLUDE&.M615DRV.EQ…ACOequatefile* ‰SECTIONƒ8 M615MEM‚EQU‡*HACMEM1ƒMOVE.L#\NVME615,D2(NVME615)getnumberofACOmodulesinsystem0‰BEQ.S‚NOACOSbranchifnoACOmodulesonsystem?‰MOVE.L#\NU615,D3‰(NU615)getnumberofinterruptlevels/module$‰MOVE.LD2,D4Žsavenumberofmodules!‰MULUƒD3,D4ŽgetnumberofACO-IDs-‰MULUƒ#ACOIDLNG,D4‡get#ofbytesforACO-IDs%‰ADD.L‚#ACONTRY,D4ˆaddinheadersize)‰MULUƒ#IOLNG,D2‰get#ofbytesforIOmap,‰ADD.L‚D4,D2Ž#ofbytesneededforACOtable‰MOVE.LD2,D5Žsave#ofbytes'‰ADD.L‚#255,D2Œrounduptopageboundry‰ASR.L‚#8,D2Ž#ofpagesneeded'‰BMI.S‚ACOERRbranchifnegative,error)‰MOVE.L#0,A0Žclearforallocatingmemory)‰MOVE.WD2,A0Žnumberofpagestoallocate-‰MOVE.L#T0PAGAL,D0ˆpageallocationdirective"‰TRAPƒ#0‘callRMS68Ktogetmemory"‰BRA.S‚ACOOKŽbranchifgoodreturn1ACOERRƒMOVE.L#32,A0fatalerror-gostopsystem‰TRAPƒ#08ACOOK„MOVE.L#'!ACO',ACOEYE(A0)setACOtableeyecatcher)‰MOVE.WD5,ACOLNG(A0)†#ofbytesintable5‰MOVE.W#ACONTRY,ACOOFST(A0)offsettoACO-IDentries&‰MOVE.WD4,ACOIO(A0)‡offsettoIOmaps'‰CLR.B‚ACONAL(A0)‰noACOsallocatedyet8‰MOVE.L#\NVME615,D4ƒ(NVME615)getnumberofACOmodules5‰MULUƒ#\NU615,D4‰(NU615)getnumberofACO-IDentries-‰MOVE.BD4,ACONMAX(A0)…maxnumberofACO-ID's6‰MOVE.LA0,ACOTBLŠsavetableaddressinsystemparams.0‰LEA„ACOID(A0),A0‡startaddressoftableentries/‰SUB.W‚#ACONTRY,D5ˆnumberofbytestosettoFF‰ASR.W‚#1,D5Žnumberofwords(31 3‰MOVE.W#$FFFF,D4Šstorethisinallentrylocations&ACOCLRƒMOVE.WD4,(A0)+‹settheentries‰SUB.W‚#1,D5Ždecrementcounter ‰BNE.S‚ACOCLRbranchifnotdone NOACOSƒEQU„*‰ENDC**‰END éééééé: é**ˆ&.M625MEM.AG*J*=========================================================================*A*‚CodeaddedtoallocatememoryfortableusedbyMVME625driver.7*‚ThiscodeisassembledandlinkedduringSYSGENtime.*K*==========================================================================‰IFNE„\NVME6255T0PAGAL‚EQU…4‹Pageallocationdirective#forTrap0.6‰XREF„DCOTBL…SYSPARlocationcontainingDCOTBLaddress ‰XDEF„M625MEM&*ˆINCLUDE&.M625DRV.EQ†DCOequatefile%‰INCLUDE&.M625DRV.EQ†DCOequatefile* ‰SECTION8 M625MEM‚EQU‡*>DCMEM1ƒMOVE.L#\NVME625,D2‡getnumberofDCOmodulesinsystem0‰BEQ.S‚NODCOSbranchifnoDCOmodulesonsystem,‰MOVE.L#\NU625,D3‰getnumberofuser/boards$‰MOVE.LD2,D4Žsavenumberofmodules!‰MULUƒD3,D4ŽgetnumberofDCO-IDs-‰MULUƒ#DCOIDLNG,D4‡get#ofbytesforDCO-IDs%‰ADD.L‚#DCONTRY,D4ˆaddinheadersize)‰MULUƒ#IOLNG,D2‰get#ofbytesforIOmap,‰ADD.L‚D4,D2Ž#ofbytesneededforDCOtable‰MOVE.LD2,D5Žsave#ofbytes'‰ADD.L‚#255,D2Œrounduptopageboundry‰ASR.L‚#8,D2Ž#ofpagesneeded'‰BMI.S‚DCOERRbranchifnegative,error)‰MOVE.L#0,A0Žclearforallocatingmemory)‰MOVE.WD2,A0Žnumberofpagestoallocate-‰MOVE.L#T0PAGAL,D0ˆpageallocationdirective"‰TRAPƒ#0‘callRMS68Ktogetmemory"‰BRA.S‚DCOOKŽbranchifgoodreturn1DCOERRƒMOVE.L#32,A0fatalerror-gostopsystem‰TRAPƒ#08DCOOK„MOVE.L#'!DCO',DCOEYE(A0)setDCOtableeyecatcher)‰MOVE.WD5,DCOLNG(A0)†#ofbytesintable5‰MOVE.W#DCONTRY,DCOOFST(A0)offsettoDCO-IDentries&‰MOVE.WD4,DCOIO(A0)†offsettoIOmaps'‰CLR.B‚DCONAL(A0)‰noDCOsallocatedyet.‰MOVE.L#\NVME625,D4‡getnumberofDCOmodules-‰MULUƒ#\NU625,D4‰getnumberofDCO-IDentries-‰MOVE.BD4,DCONMAX(A0)…maxnumberofDCO-ID's6‰MOVE.LA0,DCOTBLŠsavetableaddressinsystemparams.0‰LEA„DCOID(A0),A0‡startaddressoftableentries/‰SUB.W‚#DCONTRY,D5ˆnumberofbytestosettoFF‰ASR.W‚#1,D5Žnumberofwords3‰MOVE.W#$FFFF,D4Šstorethisinallentrylocations93B&DCOCLRƒMOVE.WD4,(A0)+‹settheentries‰SUB.W‚#1,D5Ždecrementcounter ‰BNE.S‚DCOCLRbranchifnotdone NODCOSƒEQU„*‰ENDC*‰ENDééééé: éé* *ˆ&.IOCINT.AG*F***********************************************************************#*IOCINTI/OCHANNELCCBALLOCATION*$*COPYRIGHTED1982BYMOTOROLA,INC.*F************************************************************************PROGRAMNAME:‚IOCINT*D*REV.‚1.00‚6/14/82ƒ(RONIWOOD)-ALLOCATEALLCCB'SFORI/OCHANNEL*¥DEVICEDRIVERS.*SUPPORTTABLES:‚CHANNELCONTROLBLOCKS(CCB)*’DEVICECONTROLBLOCKS(DCB)*F**********************************************************************‡NOLIST‡INCLUDE&.TR1.EQ‡INCLUDE&.EXE.EQ‡INCLUDE&.LV5.EQ‡LIST*†INCLUDE&.TR1.EQ*†INCLUDE&.EXE.EQ*†INCLUDE&.LV5.EQ*‡INCLUDEMACRO.DCB.SI*†INCLUDEMACRO.DCB.SI*!IOCINT‚IDNT‚1,0„I/OCHANNELCCB'S‰OPTƒMEX* ‰XDEF†IOSEG* SECTION 1*9*SET UP CHANNEL CONTROL BLOCKS FOR DEVICES ON I/O CHANNEL*K****************************************************************************-*ˆINTERRUPTVECTORSANDLEVELSONI/OCHANNEL*!*ˆVECTORSƒVM02†VM03†VME110„VMES10**‰IOCVEC1ƒ$71‡$49‡$19‡$41*‰IOCVEC2ƒ$72‡$4A‡$1A‡$43*‰IOCVEC3ƒ$73‡$4B‡$1B‡$44*‰IOCVEC4ƒ$74‡$4C‡$1C‡$45** *ˆLEVELS„VM02†VM03†VME110„VMES10**ˆIOCLVL1…2‰3‰1‰2*ˆIOCLVL2…3‰4‰2‰4*ˆIOCLVL3…4‰5‰3‰5*ˆIOCLVL4…5‰6‰4‰6**6*ˆINTERRUPTVECTOR1CORRESPONDSTOINTERRUPTLEVEL1,*ˆANDSOFORTH.5*ˆPLEASEBESURETHATYOURBOARDISJUMPEREDPROPERLY6*ˆTOPRODUCETHEINTERRUPTVECTORANDLEVELCALLEDFOR*ˆINTHECDBMACRO.**ˆI/OCHANNELBASEADDRESSES**—VM02†VM03†VME110„VMES10***ˆIOCBASE:†$F80000ƒ$FA0000ƒ$FE6000ƒ$F1C000** IOSEG EQU *H************************************************************************‰PAGEH*************************************************************************F*ƒIfanyRADboardsarespecifiedin.CNFGDRVR.CI,includethe3* code to perform CCB allocations for those boards.* ‚IFNE\NRADŒINCLUDEƒ&.XRADIOC.SI‚ENDC‰PAGEJVSL[H*************************************************************************F*ƒIfanyRIOboardsarespecifiedin.CNFGDRVR.CI,includethe3* code to perform CCB allocations for those boards.* ‚IFNE\NRIOŒINCLUDEƒ&.XRIOIOC.SI‚ENDC‰PAGEH*************************************************************************J*ƒIfanyVME600boardsarespecifiedin.CNFGDRVR.CI,includethe3* code to perform CCB allocations for those boards.* ‚IFNE\NVME600ŒINCLUDEƒ&.XM600IOC.SI‚ENDC‰PAGEH*************************************************************************J*ƒIfanyVME605boardsarespecifiedin.CNFGDRVR.CI,includethe3* code to perform CCB allocations for those boards.* ‚IFNE\NVME605ŒINCLUDEƒ&.XM605IOC.SI‚ENDC‰PAGEH*************************************************************************I*ƒIfanyVME610orVME620boardsarespecifiedin.CNFGDRVR.CI,?* include the code to perform CCB allocations for those boards.* ‚IFNE\NVME610+\NVME620ŒINCLUDEƒ&.XM610IOC.SI‚ENDC‰PAGEH*************************************************************************J*ƒIfanyVME615boardsarespecifiedin.CNFGDRVR.CI,includethe3* code to perform CC; B allocations for those boards.* ‚IFNE\NVME615ŒINCLUDEƒ&.XM615IOC.SI‚ENDC‰PAGE<*************************************************************J*ƒIfanyVME625boardsarespecifiedin.CNFGDRVR.CI,includethe3* code to perform CCB allocations for those boards.*‚IFNE\NVME625‹INCLUDE„&.XM625IOC.SI‚ENDC*I***************************************************************************‰DC.L0ENDOFCCB'S‰DS.B†$10‡STACKAREA STACK„EQU‡***ˆALLOCATECHANNEL*ALLBLKƒDC.B…XDCALLCOMMANDCODE‰DC.B„0“COMMANDSUB-CODE‰DC.B„0“RESERVED'‰DC.B…XOPEXCOPTIONS(EXCLUSIVEACCESS)‰DC.L„0“CHANNELMNEMONIC)‰DS.B„XIOALN+(2*XIOXLN)-XIOPRM†PARAMETERS‰DC.L„0“PRECAUTION*5*ˆWALKCCBCHAINANDALLOCATEALLKNOWNI/OCHANNELS.**INIT…MOVE.L‚#STACK,A7‹SETUPSTACKPOINTER,‰MOVE.L‚#IOSEG,A1…SETUPPOINTERTOCCBLIST‰TST.Lƒ(A1)ˆANYTODO?‰BEQ.SINIT40ˆBRANCHIFNO0‰MOVE.L‚#ALLBLK,A0ŠSETUPPOINTERTOPARAMBLOCK2INIT10ƒMOVE.W‚XCDBOPT(A1),XIOOPT-1(A0)‚GETOPTIONS6‰MOVE.L‚XCDBAID(A1),XIOCID(A0)SETUPCHANNELMNEMONIC3‰MOVEM.LXCDBPRM(A1),D0-D5/A2-A4ƒPICKUPPARAMETERS=‰MOVEM.LD0-D5/A2-A4,XIOPRM(A0)„MOVEPARAMETERSTOPARAMBLOC/INIT15ƒMOVE.L‚#XCCMR,D0‹SETUPDIRECTIVENUMBER‰TRAPƒ#1“ALLOCATECHANNEL)INIT17ƒMOVE.L‚XCDBPTR(A1),A1†GETNEXTCCB ‰TST.L(A1)‰BNE.SƒINIT10ŽNOTFINISHEDINIT40ƒERQ.TERM**ˆABORT* KILL…EQU…*'‰MOVEM.LD0/A0,-(A7)‰SAVEREGD0ANDA0‰ERQ.ABORT‚#0ABORTSELF‰PAGE ‰END…INITéééé4‰CLR‡RAUSRLNX(A0)ˆClearoffsetin'RAUSRLST'tonext*¦availableentry.9‰MOVE†#\NURAD,RANUMUSR(A0)Setmax#ofuser-RADcomb.in-‰MOVE†#1,D2header.‚Initnext-available-entry*¦pointerto1.9‰LEA‡RAUSRLST(A0),A1…LoadstartaddrofRAUSRLSTintoA1.:RAINLP3‚CLR.L…RAUUSRNO(A1)ˆClearuser#entryinRAUSRLST.‰CLR.L…RAUUSRNO+4(A1)=‰MOVE†D2,RAURADID(A1)…SetRAD-IDinRAUSRLSTtopointtonext)*¦avail.entry(whichisjustnextentry,;‰CLR‡RAURADID+2(A1)†initially).‚ClearrestofRAD-IDfield.4‰CLR‡RAUSTAT(A1)‰ClearuserstatusflaginRAUSRLST.2‰CLR‡RAUEROPT(A1)ˆClearerror-notificationfields.‰CLR.L…RAUERSTO(A1)‰CLR.L…RAUERSUB(A1)6‰ADD.L…#RAULNG,A1ŠUpdateptrtostartofnextentryin0‰ADDQ†#1,D2RAUSRLST.‚Bumpnext-avail-entryptr.8‰CMP‡#\NURAD,D2ŠHaveweinitializedthewholetableyet?"‰BLE‡RAINLP3No--godonextentry.?‰MOVE†#$FFFF,RAURADID-RAULNG(A1)„Yes--setthelastptrtonext-**¦avail-entryto$FFFFtoindicatenomore*¦left.9‰MOVE.L„A0,RAD1TBLŠPutaddrofRADtablesintoSYSPARloc*¦forusebyotherprogs. ZERORADSEQU‡*“EndofRADstuff.O*==============================================================================‰END; éééc*J*=========================================================================*=*‚CodeaddedtoallocatememoryfortableusedbyRIOdriver.=*‚Thiscodeistomergedintotheapproprateinitializerfile4*‚aspertheinstructionsreceivedwiththisdriver.@*‚Edittheinitializerfile.Positiontothecorrectlineinthe<*‚file.MergethisfilebytheEditcommand:MERGERIOMEM.SA**K*==========================================================================6‰XREF„RIOTBL…SYSPARlocationcontainingRIOTBLaddress ‰XREF„KILLER*ˆBRA.SƒRIOMEM1%*ˆINCLUDE&.RIODRV.EQ„RIOequatefile$‰INCLUDE&.RIODRV.EQ„RIOequatefile* ŠSECTION‚8ŠMOVE.L#\NRIOINT,D3‡getnumberofinterruptlevelspermodule$ŠMOVE.LD2,D4Žsavenumberofmodules!ŠMULUƒD3,D4ŽgetnumberofRIO-IDs-ŠMULUƒ#RIOIDLNG,D4‡get#ofbytesforRIO-IDs%ŠADD.L‚#RIONTRY,D4ˆaddinheadersize+ŠMULUƒ#PIALNG,D2‰get#ofbytesforPIAmap,ŠADD.L‚D4,D2Ž#ofbytesneededforRIOtableŠMOVE.LD2,D5Žsave#ofbytes'ŠADD.L‚#255,D2ŒrounduptopageboundryŠASR.L‚#8,D2Ž#ofpagesneeded'ŠBMI.S‚RIOERRbranchifnegative,error)ŠMOVE.L#0,A0Žclearforallocatingmemory)ŠMOVE.WD2,A0Žnumberofpagestoallocate'ŠMOVE.L#4,D0Žpageallocationdirective"ŠTRAPƒ#0‘callRMS68Ktogetmemory"ŠBRA.S‚RIOOKŽbranchifgoodreturn.RIOERR„BSR„KILLERfatalerror-gostopsystem8RIOOK…MOVE.L#'!RIO',RIOEYE(A0)setRIOtableeyecatcher)ŠMOVE.WD5,RIOLNG(A0)†#ofbytesintable5ŠMOVE.W#RIONTRY,RIOOFST(A0)offsettoRIO-IDentries(ŠMOVE.WD4,RIOPIA(A0)†offsettoPIAmaps'ŠCLR.B‚RIONAL(A0)‰noRIOsallocatedyet+ŠMOVE.L#\NRIO,D4ŠgetnumberofRIOmodules/ŠMULUƒ#\NRIOINT,D4‡getnumberofRIO-IDentries-ŠMOVE.BD4,RIONMAX(A0)…maxnumberofRIO-ID's6ŠMOVE.LA0,RIOTBLŠsavetableaddressinsystemparams.0ŠLEA„RIOID(A0),A0‡startaddressoftableentries/ŠSUB.W‚#RIONTRY,D5ˆnumberofbytestosettoFFl0uŠASR.W‚#1,D5Žnumberofwords3ŠMOVE.W#$FFFF,D4Šstorethisinallentrylocations&RIOCLR„MOVE.WD4,(A0)+‹settheentriesŠSUB.W‚#1,D5Ždecrementcounter ŠBNE.S‚RIOCLRbranchifnotdone NORIOS„EQU„*ŠENDéé< ééééé**ˆ&.M605MEM.CI*GMSG‰*******************************************************************#MSG‰*‚MVME605driverinitializationGMSG‰******************************************************************* SUBSˆ&.M605MEM.AGASM‰&.M605MEM.AG,NEW.RO,\ASMLS IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC INCLUDE…&.ROGEN.CIéééééé}* *ˆ&.RADMEM.CI*GMSG‰*******************************************************************MSG‰*‚RADdriverinitializationGMSG‰******************************************************************* SUBSˆ&.RADMEM.AGASM‰&.RADMEM.AG,NEW.RO,\ASMLS IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC INCLUDE…&.ROGEN.CI< éééééé†**ˆ&.M610MEM.CI*EMSG‰*****************************************************************'MSG‰*‚MVME610/620„driverinitializationDMSG‰**************************************************************** SUBSˆ&.M610MEM.AGASM‰&.M610MEM.AG,NEW.RO,\ASMLS IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC INCLUDE…&.ROGEN.CIéééééé= **ˆ&.M625DRV.CI*GMSG‰*******************************************************************!MSG‰**‚VME625DRIVER-‚DCOUTPUTGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF%=COPY‡VERSAPT.M625DRV.CF,VERSAPT.CF;A M625DRVƒ=*SUBSˆ&.M625IOC.SISUBSˆ&.M625DRV.LGLINKˆ&.M625DRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.M625DRV.LOEND‰&.M625DRV.LOééééé˜**ˆ&.M615MEM.CI*GMSG‰*******************************************************************MSG‰*‚615driverinitializationGMSG‰******************************************************************* SUBSˆ&.M615MEM.AGASM‰&.M615MEM.AG,NEW.RO,\ASMLS IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC INCLUDE…&.ROGEN.CIééééé= é¡* *ˆ&.RIOMEM.CI*GMSG‰*******************************************************************MSG‰*‚RIOdriverinitializationGMSG‰******************************************************************* SUBSˆ&.RIOMEM.AGASM‰&.RIOMEM.AG,NEW.RO,\ASMLS IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC INCLUDE…&.ROGEN.CIééééééª**ˆ&.M625MEM.CI*GMSG‰*******************************************************************MSG‰*‚625driverinitializationGMSG‰******************************************************************* SUBSˆ&.M625MEM.AGASM‰&.M625MEM.AG,NEW.RO,\ASMLS IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC INCLUDE…&.ROGEN.CIééé> ééé³**ˆ&.M600DRV.CI*GMSG‰*******************************************************************3MSG‰**„VME600DRIVER-‚ANALOGTODIGITALCONVERTERGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF%=COPY‡VERSAPT.M600DRV.CF,VERSAPT.CF;A +M600DRVƒ=*ŒMVME600/601driverbaseaddress!SUBSˆ&.M600IOC.SICCBallocations1SUBSˆ&.M600DRV.LGDrivermoduleLINKcommandfileLINKˆ&.M600DRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.M600DRV.LOEND‰&.M600DRV.LOééééé¼**ˆ&.M605DRV.CI*GMSG‰*******************************************************************%MSG‰**„VME605DRIVER-‚ANALOGOUTPUTGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF%=COPY‡VERSAPT.M605DRV.CF,VERSAPT.CF;A M605DRVƒ=*SUBSˆ&.M605IOC.SISUBSˆ&.M605DRV.LGLINKˆ&.M605DRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.M605DRV.LOEND‰&.M605DRV.LO> éééééÅ ' M610DRV CIÚÚqqM615DRV CIããqqPCDRV CIììqqRADDRV CIõõqqRIODRV CIþþqqIOCI CIqqM600DRV LGqqM605DRV LGqqM610DRV LG""qqM615DRV LG++qqM625DRV LG44qqIOCINT LG==qqIOCFAIL LGFFqqRADDRV LGOOqqRIODRV LGXXqqM600DRV NWaajqqM600FORTNWnn:ÏqqM605DRV NW¯¯ŠqqM610DRV NWÈÈ"¸qqM615DRV NWññàqq**ˆ&.M610DRV.CI*GMSG‰*******************************************************************-MSG‰**‚VME610/620DRIVER-ACINPUT/DCINPUTGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF%=COPY‡VERSAPT.M610DRV.CF,VERSAPT.CF;A +M610DRVƒ=*ŒMVME610/620driverbaseaddress!SUBSˆ&.M610IOC.SICCBallocations1SUBSˆ&.M610DRV.LGDrivermoduleLINKcommandfileLINKˆ&.M610DRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.M610DRV.LOEND‰&.M610DRV.LOééé? ééÒ**ˆ&.M615DRV.CI*GMSG‰*******************************************************************!MSG‰**„VME615DRIVER-‚ACOUTPUTGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF%=COPY‡VERSAPT.M615DRV.CF,VERSAPT.CF;A M615DRVƒ=*SUBSˆ&.M615IOC.SISUBSˆ&.M615DRV.LGLINKˆ&.M615DRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.M615DRV.LOEND‰&.M615DRV.LOéééééÛ* *ˆ&.PCDRV.CI* IFGTˆ\NRADƒINCLUDE…&.RADMEM.CIENDC* IFGTˆ\NRIOƒINCLUDE…&.RIOMEM.CIENDC* IFGTˆ\NVME605ƒINCLUDE…&.M605MEM.CIENDC*IFGTˆ\NVME610+\NVME620ƒINCLUDE…&.M610MEM.CIENDC* IFGTˆ\NVME615ƒINCLUDE…&.M615MEM.CIENDC* IFGTˆ\NVME625ƒINCLUDE…&.M625MEM.CIENDCéé? ééééä* *ˆ&.RADDRV.CI*GMSG‰*******************************************************************MSG‰**„RADDRIVERGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF$=COPY‡VERSAPT.RADDRV.CF,VERSAPT.CF;A RADDRV„=*SUBSˆ&.RADIOC.SISUBSˆ&.RADDRV.LGLINKˆ&.RADDRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.RADDRV.LOEND‰&.RADDRV.LOééééééí* *ˆ&.RIODRV.CI*GMSG‰*******************************************************************MSG‰**„RIODRIVERGMSG‰******************************************************************* *‚SetProcessControlFlag=ON&PCDRV„=\&PCDRV+1 5* Build VERSAdos patch chain file .VERSAPT.CF$=COPY‡VERSAPT.RIODRV.CF,VERSAPT.CF;A RIODRV„=*SUBSˆ&.RIOIOC.SISUBSˆ&.RIODRV.LGLINKˆ&.RIODRV.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDCPROCESS…&.RIODRV.LOEND‰&.RIODRV.LO@ ééééééö* *ˆ&.IOCI.CI*MSG$MSG‰StartofI/OchannelinitializerMSGTASKˆ&.IOCI.LOSTATE…='READ' SESSIONƒ=1PRIORITY‚=$DA IOCISTRƒ=* SUBSˆ&.IOCINT.AG'ASM‰&.IOCINT.AG,&.IOCINT.RO,\ASMLS;Z=50 IFEQˆ\ASMLSWƒ=COPY‡\ASMLS,\WORKLS;AENDC SUBSˆ&.IOCINT.LGLINKˆ&.IOCINT.LG IFEQˆ\LINKLSWƒ=COPY‡\LINKLS,\WORKLS;AENDC END‰&.IOCI.LOééééééÿ@ =/*=/*†&.M600DRV.LG=/*==/* Link chain file run at sysgen time to link MVME600 driver=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter M600DRV = \M600DRV = address at which to link driver=/* =LINK ,&.M600DRV.LO,\LINKLS;MIXHSEG M600:8 \M600DRVINPUT &.M600DRV.ROEND=/*=ENDéééééé=/*=/*†&.M605DRV.LG=/*==/* Link chain file run at sysgen time to link MVME605 driver=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter M605DRV = \M605DRV = address at which to link driver=/* =LINK ,&.M605DRV.LO,\LINKLS;MIXHSEG DAC1:8 \M605DRVINPUT &.M605DRV.ROINPUT &.SYSPAR.ROEND=/*=ENDéééééA é=/*=/*†&.M610DRV.LG=/*==/* Link chain file run at sysgen time to link MVME610 driver=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter M610DRV = \M610DRV = address at which to link driver=/* =LINK ,&.M610DRV.LO,\LINKLS;MIXHSEG SEG0:0 \M610DRVINPUT &.M610DRV.ROINPUT &.SYSPAR.ROEND=/*=ENDéééééé=/*=/*†&.M615DRV.LG=/*==/* Link chain file run at sysgen time to link MVME615 driver=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter M615DRV = \M615DRV = address at which to link driver=/* =LINK ,&.M615DRV.LO,\LINKLS;MIXHSEG M615:8 \M615DRVINPUT &.M615DRV.ROINPUT &.SYSPAR.ROEND=/*=ENDéééA ééé#=/*=/*†&.M625DRV.LG=/*==/* Link chain file run at sysgen time to link MVME625 driver=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter M625DRV = \M625DRV = address at which to link driver=/* =LINK ,&.M625DRV.LO,\LINKLS;MIXHSEG M625:8 \M625DRVINPUT &.M625DRV.ROINPUT &.SYSPAR.ROEND=/*=ENDéééééé,=/*=/*†&.IOCINT.LG=/*5=/* Link chain file run at sysgen time to link IOCINT=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter IOCISTR = \IOCISTR = address at which to link driver=/*=LINK ,&.IOCI.LO,\LINKLS;IXHMSSEGMENT IOCI:1 \IOCISTRINPUT &.IOCINT.ROEND=/*=ENDéB ééééé5=/*=/*†&.IOCFAIL.LG=/*6=/* Link chain file run at sysgen time to link IOCFAIL=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*I=/* Sysgen parameter IOCFSTR = \IOCFSTR = address at which to link driver=/*!=LINK ,&.IOCFAIL.LO,\LINKLS;IXHMSSEGMENT IOCF:0 \IOCFSTRINPUT &.IOCFAIL.ROEND=/*=ENDéééééé>=/*=/*†&.RADDRV.LG=/*5=/* Link chain file run at sysgen time to link RADDRV=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*G=/* Sysgen parameter RADDRV = \RADDRV = address at which to liB nk driver=/*=LINK ,&.RADDRV.LO,\LINKLS;MIXHSEG RAD1:8 \RADDRVINPUT &.RADDRV.ROINPUT &.SYSPAR.ROEND=/*=ENDééééééG=/*=/*†&.RIODRV.LG=/*9=/* Link chain file run at sysgen time to link RIO driver=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*G=/* Sysgen parameter RIODRV = \RIODRV = address at which to link driver=/*=LINK ,&.RIODRV.LO,\LINKLS;MIXHSEG RIO1:8 \RIODRVINPUT &.RIODRV.ROINPUT &.SYSPAR.ROEND=/*=ENDééééééC PN==============================================================================F====‚NEWSFILEFORA/D…(MVME600-A/DINPUTBOARD)ƒDRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N============================================================================== 8This driver is compatible with both RMS68K and VERSAdos.   .This driver consists of the following files -- ‰MVME600driverfiles:-9992.&.M600DRV.SA‚MVME600driversourcefile99992.&.M600CMDS.SAMVME600sourcecommand/interruptcode09992.&.M600CMTS.SAMVME600sourcecommentsfile69992.&.M600INTL.SAMVME600sourceinitializationcode@9992.&.M600SERV.SAMVME600sourcedrivervectortable/revtable-9992.&.M600DRV.RO‚MVME600driverobjectfile59992.&.M600DRV.AF‚MVME600driverassemblychainfile  ‰Filesforsystemconfiguration:"9992.&.M600DRV.CIˆSYSGENcommands"9992.&.M600IOC.SIˆCCBallocations39992.&.M600DRV.LGˆChainfiletolinkinthedriver#9998.VERSAPT.M600DRV.CF‚Patchfile   ‰FORTRANinterfacesubroutines:09992.&.M600LIB.SA…Assemblylanguagesourcefile&9992.&.M600LIB.AF…Assemblychainfile9992.&.M600LIB.RO…Objectfile  ‰"News"file:9992.&.M600DRV.NW…Newsfile79992.&.M600FORT.NW„DocumentationforFORTRANinterface   %‰Filestogeneratethetestprograms: >‰9992.M600DRV.TEST600.SA‡AssemblylanguagetestprogramsourceA‰9992.M600DRV.TEST600.AF‡chainfileforassemblylanguageprogramA‰9992.M600DRV.TEST600.LF‡chainfileforlinkofasmlang.program7‰9992.M600DRV.TEST600.LO‡assemblylanguagetestprogram  KTheMVME600driversourcefileis:9992.&.M600DRV.SA.‚Toassemblethisfile%use the chain file 9992.&.M600DRV.AF.  >In order to incorporate this driver into your system, you will=have to set some parameters in the .CNFGDRVR.CI file.  #This driver requires the following:;‰1)‚Memorymustbeallocatedfortheinternaldrivertable.9‰2)‚Achannelcontrolblock(CCB)mustbecreatedfortheY<b/6“commandsissuedforeachMVME600boardinthesystem. HThe size of the memory area set aside for the driver table is determinedJbythevalueofthevariablespecifiedbyyouin.CNFGDRVR.CI.‚Thevariable is "NVME600". =NVME600ƒThisisthenumberofMVME600boardswhichwillbeon6Šthesystem.‚Sincetherecanbenomorethan16boards6ŠontheI/OChannel(whichiswheretheseboardsare),&Šthemaximumvalueof"NVME600"is16.   ?To include the MVME600 driver in your SYSgen, do the following: <‰(1)UseCOPYSGENtogetallthefilesneededfortheSYSgenintoyourSYSgenusernumber.2NOTE:‚Makesureargument5=PCDRVsotheProcess+”ControlDriverswillbecopiedbyCOPYSGEN 9‰(2)SetthevariableNVME600inthe.CNFGDRVR.CI,filefortheprocessorboardyouareusing. 8‰(3)CheckthefileM600IOC.SItobesurethattheCCB'sconformtoyourconfiguration. BWhen setting up the "CDB" calls please note that each ID must haveCauniquename.‚ThisisalsothenameanyapplicationtaskwoulduseBtoaddressthedriverforaboard.‚Thememory-mappedI/Oaddresses"are also different for each board. JM600LIB.SAisassembledusingtheM600LIB.AFchainfile.‚M600LIB.ROistheEFORTRAN-callable subroutine which, when called by the user program orJFORTRAN test program, will invoke the appropriate MVME600 driver function. >After configuring your system and creating a VERSAdos with the>MVME605 driver included, you may want to run the provided C testprogram. GM600DRV.TEST600.SA is an assembly language test program which tests theDMVME600driver.‚ThisprogrampromptstheusertorunasubsetofallDcommandsavailableinthedriver.‚ItcanbeusedasafirstcheckofAthe hardware and as an example of writing commands to the driver. ‰ENDN==============================================================================N==============================================================================   ½31-Jan-85  + 1 MVME600 A/D Interface User Documentation:ƒEachofthefollowingmodulearelocatedin&.M600LIB.SA.  „A.‚MODULENAME: ŠA2DOPN „B.‚MODULETYPE: ŠUtilitysubroutine „C.‚MODULEPURPOSE: /ŠThissubroutineprovidesaninterfacewiththe1ŠA/D600/601driver,allowingausertaskwritten+ŠinFORTRANtoopenoneormoremeasurement Šchannels. „D.‚CALLINGSEQUENCE: )‰CALLA2DOPN(CHNLMN,CMDBLK,CMDBKL,STATUS) „E.‚ENTRYCONDITIONS: ‰CHNLMN=ChannelMnemonic’(4ASCIIcharacters)#‰CMDBLK=I/OCommandBlockaddress ’(Integer*4)"‰CMDBKL=I/OCommandBlocklength,‰STATUS=StatusreturnedbytheA/Ddriver.  ‰ChannelBlockFormat "‹+---------------+---------------+‹|‚Statuscode’|"‹+---------------+---------------+‹|‚OPENcommandcode($0001)„|"‹+---------------+---------------+‹|‚Firstchannelnumber‰|"‹+---------------+---------------+‹:::‹:::"‹+---------------+---------------+ j3o4sdw#{@aƒ+‡9‹==“E—7›CŸ@£d‹|‚LastchannelnumberŠ|"‹+---------------+---------------+  „F.‚EXITCONDITIONS: ,‰STATUS=StatusreturnedbytheA/Ddriver.       -1-   ½31-Jan-85  „G.‚TABLESUSED: ‰ParameterBlock "‹+---------------+---------------+ ‹|‚Commandcode(InitiateI/O)‚|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚LengthI/Ocommandblock…|"‹+---------------+---------------+ „H.‚MODULESUSED: „I.‚MODULESCALLINGTHISMODULE: -ŠAnymodulerequiringinterfacetoA/Ddriver #„J.‚ERRORMESSAGESGENERATED:„None.                        -2-   ½31-Jan-85  „A.‚MODULENAME:„A2DMRS #„B.‚MODULETYPE:„UTILITYSUBROUTINE „C.‚MODULEPURPOSE: /ŠThissubroutineprovidesaninterfacewiththe1ŠA/D600/601driver,allowingausertaskwritten2ŠinFORTRANtorequestsingle-endedmeasurement(s)&Šforspecifiedmeasurementchannel(s). „D.‚CALLINGSEQUENCE: )ˆCALLA2DMRS(CHNLMN,CMDBLK,CMDBKL,STATUS) „E.‚ENTRYCONDITIONS: ‰CHNLMN=ChannelMnemonic’(4ASCIIcharacters)#‰CMDBLK=I/OCommandBlockaddress ’(Integer*4)"‰CMDBKL=I/OCommandBlocklength                                     -3-   ½31-Jan-85  +‰I/OCommandBlock(MEASURESINGLEcommand) "‹+---------------+---------------+‹|‚Statuscode’|"‹+---------------+---------------+!‹|‚MEASUREcommandcode($0003)|"‹+---------------+---------------+ ‹|‚Repeatcount(0=Infinity)‚|"‹+---------------+---------------+‹|‚TimedelaybetweenD sweeps„|‹+--…4bytefieldŠ--+‹|ƒ(omitifrepeatcount=1)‚|"‹+---------------+---------------+‹|‚CommandCompletionOption„|"‹+---------------+---------------+›:•ChannelBlocks›:"‹+---------------+---------------+‹|‚Channelnumber|"‹+---------------+---------------+‹|‚ChannelCompletionOptionsƒ|"‹+---------------+---------------+!‹|‚SubroutineAddress(Optional)|"‹+---------------+---------------+!‹|‚SubroutineAddress(Optional)|"‹+---------------+---------------+‹|‚Bufferaddress|"‹+---------------+---------------+‹|‚Bufferaddress|"‹+---------------+---------------+‹|‚Sizeofbufferinbytes†|"‹+---------------+---------------+!‹|‚TriggerModeandGainOption|"‹+---------------+---------------+                        -4-   ½31-Jan-85  „F.‚EXITCONDITIONS: ,‰STATUS=StatusreturnedbytheA/Ddriver. „G.‚TABLESUSED: ‰ParameterBlock "‹+---------------+---------------+ ‹|‚Commandcode(InitiateI/O)‚|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚LengthI/Ocommandblock…|"‹+---------------+---------------+ „H.‚MODULESUSED: „I.‚MODULESCALLINGTHISMODULE: -ŠAnymodulerequiringinterfacetoA/Ddriver #„J.‚ERRORMESSAGESGENERATED:„None.                    -5-   ½31-Jan-85  „A.‚MODULENAME:„A2DMRD #„B.‚MODULETYPE:„UTILITYSUBROUTINE „C.‚MODULEPURPOSE: /ŠThissubroutineprovidesaninterfacewiththe1ŠA/D600/601driver,allowingausertaskwritten2ŠinFORTRANtorequestdifferentialmeasurement(s)&Šforspecifiedmeasurementchannel(s). „D.‚CALLINGSEQUENCE: )ˆCALLA2DMRD(CHNLMN,CMDBLK,CMDBKL,STATUS) „E.‚ENTRYCONDITIONS: ‰CHNLMN=ChannelMnemonic’(4ASCIIcharacters)#‰CMDBLK=I/OCommandBlockaddress ’(Integer*4)"‰CMDBKL=I/OCommandBlocklength                                     -6-   ½31-Jan-85  1‰I/OCommandBlock(MEASUREDIFFERENTIALcommand) "‹+---------------+---------------+‹|‚Statuscode’|"‹+---------------+---------------+!‹|‚MEASUREcommandcode($0004)|"‹+---------------+---------------+ ‹|‚Repeatcount(0=Infinity)‚|"‹+---------------+---------------+‹|‚Timedelaybetweensweeps„|‹+--…4bytefieldŠ--+‹|‚(omitifrepeatcount=1)ƒ|"‹+---------------+---------------+‹|‚CommandCompletionOption„|"‹+---------------+---------------+›:•ChannelBlocks›:"‹+---------------+---------------+‹|‚Channelnumber|"‹+---------------+---------------+‹|‚ChannelCompletionOptionsƒ|"‹+---------------+---------------+!‹|‚SubroutineAddress(Optional)|"‹+---------------+---------------+!‹|‚SubroutineAddress(Optional)|"‹+---------------+---------------+‹|‚Bufferaddress|"‹+---------------+---------------+‹|‚Bufferaddress|"‹+---------------+---------------+‹|‚Sizeofbufferinbytes†|"‹+---------------+---------------+!‹|‚TriggerModeandGainOption|"‹+---------------+---------------+                        -7-   ½31-Jan-85  „F.‚EXITCONDITIONS: ,‰STATUS=StatusreturnedbytheA/Ddriver.  „G.‚TABLESUSED: ‰ParameterBlock "‹+---------------+---------------+ ‹|‚ComD mandcode(InitiateI/O)‚|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚LengthI/Ocommandblock…|"‹+---------------+---------------+  „H.‚MODULESUSED: „I.‚MODULESCALLINGTHISMODULE: -ŠAnymodulerequiringinterfacetoA/Ddriver #„J.‚ERRORMESSAGESGENERATED:„None.                  -8-   ½31-Jan-85  „A.‚MODULENAME:„A2DSTP #„B.‚MODULETYPE:„UTILITYSUBROUTINE „C.‚MODULEPURPOSE: /ŠThissubroutineprovidesaninterfacewiththe1ŠA/D600/601driver,allowingausertaskwritten+ŠinFORTRANtostopthemeasurementforanyŠspecifiedMEASUREcommand. „D.‚CALLINGSEQUENCE: )‰CALLA2DSTP(CHNLMN,CMDBLK,CMDBKL,STATUS) „E.‚ENTRYCONDITIONS: ‰CHNLMN=ChannelMnemonic’(4ASCIIcharacters)#‰CMDBLK=I/OCommandBlockaddress ’(Integer*4)"‰CMDBKL=I/OCommandBlocklength ‰ChannelBlockFormat "‹+---------------+---------------+‹|‚Statuscode’|"‹+---------------+---------------+‹|‚STOPcommandcode($0000)„|"‹+---------------+---------------+‹|‚Firstchannelnumber‰|"‹+---------------+---------------+‹:::‹:::"‹+---------------+---------------+‹|‚LastchannelnumberŠ|"‹+---------------+---------------+                      -9-   ½31-Jan-85  „F.‚EXITCONDITIONS: ,‰STATUS=StatusreturnedbytheA/Ddriver. „G.‚TABLESUSED:ƒNone ‰ParameterBlock "‹+---------------+---------------+ ‹|‚Commandcode(InitiateI/O)‚|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚LengthI/Ocommandblock…|"‹+---------------+---------------+  „H.‚MODULESUSED: „I.‚MODULESCALLINGTHISMODULE: -ŠAnymodulerequiringinterfacetoA/Ddriver „J.‚ERRORMESSAGESGENERATED: ŠNone                 -10-   ½31-Jan-85  „A.‚MODULENAME: ŠA2DCLS „B.‚MODULETYPE: ŠUtilitysubroutine „C.‚MODULEPURPOSE: /ŠThissubroutineprovidesaninterfacewiththe1ŠA/D600/601driver,allowingausertaskwritten,ŠinFORTRANtocloseoneormoremeasurement Šchannels. „D.‚CALLINGSEQUENCE: )‰CALLA2DCLS(CHNLMN,CMDBLK,CMDBKL,STATUS) „E.‚ENTRYCONDITIONS: ‰CHNLMN=ChannelMnemonic’(4ASCIIcharacters)#‰CMDBLK=I/OCommandBlockaddress ’(Integer*4)"‰CMDBKL=I/OCommandBlocklength ‰ChannelBlockFormat "‹+---------------+---------------+‹|‚Statuscode’|"‹+---------------+---------------+‹|‚CLOSEcommandcode($0002)ƒ|"‹+---------------+---------------+‹|‚Firstchannelnumber‰|"‹+---------------+---------------+‹:::‹:::"‹+---------------+---------------+‹|‚LastchannelnumberŠ|"‹+---------------+---------------+  „F.‚EXITCONDITIONS: ,‰STATUS=StatusreturnedbytheA/DdriveE r.             -11-   ½31-Jan-85  „G.‚TABLESUSED: ‰ParameterBlock "‹+---------------+---------------+ ‹|‚Commandcode(InitiateI/O)‚|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+‹|‚ChannelMnemonic(ASCII)…|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+ ‹|Šnotused|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚AddressI/Ocommandblock„|"‹+---------------+---------------+‹|‚LengthI/Ocommandblock…|"‹+---------------+---------------+  „H.‚MODULESUSED: „I.‚MODULESCALLINGTHISMODULE: -ŠAnymodulerequiringinterfacetoA/Ddriver #„J.‚ERRORMESSAGESGENERATED:„None.                       -12-   ½31-Jan-85  „A.‚MODULENAME:„BLDCB #„B.‚MODULETYPE:„UTILITYSUBROUTINE „C.‚MODULEPURPOSE: -ŠThissubroutinebuildsachannelblockentry3Šfromthespecifiedparametersintheuserprovided0Šdataarea.‚Thissubroutineisusedtobuildthe+Šchannelblocksforbothofthemeasurement Šroutines. „D.‚CALLINGSEQUENCE: 4ˆCALLBLDCB(CMDBLK,CHNLNO,OPTION,BFA,BFL,SBA,TGRMOD,“RTNADR,CMDBKL) „E.‚ENTRYCONDITIONS: #‰CMDBLK‚=I/OCommandBlockaddress “(Integer*4)‰CHNLNO‚=Channelnumber$‰OPTION‚=Channelcompletionoptions‰BFA…=BufferAddress “(Integer*4)‰BFL…=BufferLength-‰SBA…=SubroutineAddress‚(0ifnotrequired) “(Integer*4)'‰TGRMOD‚=TriggerModeandGainOptions-‰RTNADR‚=Addressofnextavailchannelblock“(Returnedbythissubroutine) “(Integer*4)'‰CMDBKL‚=LengthofChannelBlockbuilt“(Returnedbythissubroutine)                         -13-   ½31-Jan-85  ‰ChannelBlockFormat "‹+---------------+---------------+‹|‚Channelnumber|"‹+---------------+---------------+‹|‚ChannelCompletionOptionsƒ|"‹+---------------+---------------+!‹|‚SubroutineAddress(Optional)|"‹+---------------+---------------+!‹|‚SubroutineAddress(Optional)|"‹+---------------+---------------+‹|ˆBufferaddress‰|"‹+---------------+---------------+‹|ˆBufferaddress‰|"‹+---------------+---------------+‹|‚Sizeofbufferinbytes†|"‹+---------------+---------------+!‹|‚TriggerModeandGainOption|"‹+---------------+---------------+                                        -14-   ½31-Jan-85  „F.‚EXITCONDITIONS: „G.‚TABLESUSED: „H.‚MODULESUSED: „I.‚MODULESCALLINGTHISMODULE: -ŠAnymodulerequiringinterfacetoA/Ddriver „J.‚ERRORMESSAGESGENERATED: ŠNone END                                            -15- éN==============================================================================@====‚NEWSFILEFORDAC…(MVME605-D/ABOARD)‰DRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N========================================================================E ====== 8This driver is compatible with both RMS68K and VERSAdos.   .This driver consists of the following files -- ‰MVME605driverfiles: -9992.&.M605DRV.SA‚MVME605driversourcefile-9992.&.M605DRV.RO‚MVME605driverobjectfile59992.&.M605DRV.AF‚MVME605driverassemblychainfile  ‰Filesforallocatingmemory:09992.&.M605MEM.CI‰FileincludedatSYSGENtime.09992.&.M605MEM.AG‰FileassembledatSYSGENtime  !‰Filesforsystemconfiguration: "9992.&.M605DRV.CIˆSYSGENcommands"9992.&.M605IOC.SIˆCCBallocations39992.&.M605DRV.LGˆChainfiletolinkinthedriver#9998.VERSAPT.M605DRV.CF‚Patchfile  ‰FORTRANinterfacesubroutines:09992.&.M605LIB.SAˆAssemblylanguagesourcefile&9992.&.M605LIB.AFˆAssemblychainfile9992.&.M605LIB.ROˆObjectfile  9‰Thefollowingfilesareusedtogenerateatestprogram: >‰9992.M605DRV.TEST605.SA‡AssemblylanguagetestprogramsourceA‰9992.M605DRV.TEST605.AF‡chainfileforassemblylanguageprogramA‰9992.M605DRV.TEST605.LF‡chainfileforlinkofasmlang.program7‰9992.M605DRV.TEST605.LO‡assemblylanguagetestprogram  ‰"News"file:9992.&.M605DRV.NWˆNewsfile KTheMVME605driversourcefileis:9992.&.M605DRV.SA.‚Toassemblethisfile%use the chain file 9992.&.M605DRV.AF.;The following files are used in the assembly of M605DRV.SA:9995.&.STR.EQ9995.&.TCB.EQ9995.&.CCB.EQ9995.&.LV5.EQ9995.&.TR1RTCD.EQ9995.&.M605DRV.EQ  >In order to incorporate this driver into your system, you will=have to set some parameters in the .CNFGDRVR.CI file.  #This driver requires the following:;‰1)‚Memorymustbeallocatedfortheinternaldrivertable.§A°4¸9‰2)‚Achannelcontrolblock(CCB)mustbecreatedforthe6“commandsissuedforeachMVME605boardinthesystem. HThe size of the memory area set aside for the driver table is determinedGbythevaluesoftwovariablesasspecifiedbyyouintheSYSGEN.‚These$variables are "NVME605" and "NU605". =NVME605ƒThisisthenumberofMVME605boardswhichwillbeon6Šthesystem.‚Sincetherecanbenomorethan16boards6ŠontheI/OChannel(whichiswheretheseboardsare),&Šthemaximumvalueof"NVME605"is16. 3NU605…Thisvariableissettothemaximumnumberof7Šuser/MVME605combinationsyouwishtoallowatanyone2Štime.‚Sinceitispossibletohaveoneuserusing;ŠmorethanoneMVME605board,aswellasmorethanoneuser4ŠusingthesameMVME605board,weneedthenumberofŠuser/MVME605combinations.   ?Example:‚IfuserAusesboard#1andboard#2,userBusesjust1Šboard#1,anduserCusesboard#2andboard#3,,Štherewouldbe5user/boardcombinations--ŠA/1,A/2,B/1,C/2,C/3.FIf the configuration of MVME605 boards is the same as in this example,$you would set NVME605=3 and NU605=5. INote that if you set either of these variables to a larger number than isHactuallyneeded,thesystemwillstilloperatenormally.‚ThiswouldjustBresult in having more memory allocated for internal tables than is necessary.  ?To include the MVME605 driver in your SYSGEN, do the following:  9‰(1)DoaCOPYSGENtogetthefilesneededfortheSYSgenintoyoursysgenusernumber.7NOTE:‚Makesurethatargument5=PCDRVsotheProcess,”ControlDriverswillbecopiedbyCOPYSGEN. D‰(2)SetthevariablesNVME605andNU605inthe.CNFGDRVR.CI,filefortheprocessorboardyouareusing. 8‰(3)CheckthefileM605IOC.SItobesurethattheCCB'sconformtoyourconfiguration.   FWhen setting up the "CDB" calls please note that each DAC-ID must haveCauniquename.‚ThisisalsothenameanyapplicationtaskwoulduseF Btoaddressthedriverforaboard.‚Thememory-mappedI/Oaddresses"are also different for each board.   >After configuring your system and creating a VERSAdos with the>MVME605 driver included, you may want to run the provided testprogram. GM605DRV.TEST605.SA is an assembly language test program which tests theDMVME605driver.‚ThisprogrampromptstheusertorunasubsetofallDcommandsavailableinthedriver.‚ItcanbeusedasafirstcheckofAthe hardware and as an example of writing commands to the driver.  JM605LIB.SA is assembled using the M605LIB.AF chain file. M605LIB.RO is theEFORTRAN-callable subroutine which, when called by the user program orJFORTRAN test program, will invoke the appropriate MVME605 driver function. ‰ENDN==============================================================================N==============================================================================ééééN==============================================================================H====‚NEWSFILEFORAC/DCƒ(MVME610/620-AC/DCBOARD)ƒDRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N============================================================================== 8This driver is compatible with both RMS68K and VERSAdos. 4This driver package consists of the following files: ‰VME610/620Driverfiles:19992.&.M610DRV.SAˆMVME610/620DriverSourcefile19992.&.M610DRV.ROˆMVME610/620DriverObjectfile99992.&.M610DRV.AFˆMVME610/620DriverAssemblyChainfile <‰FilestoallocatememoryfortheInterruptProcessingqueue09992.&.M610MEM.AGŠFileassembledatSYSgentime49992.&.M610MEM.CIŠFileINCLUDEdintoSYSgencommand¨fileatSYSgentime. ‰Filesforsystemconfiguration:%9992.&.M610DRV.CIŠCommandstoSYSgen"9992.&.M610IOC.SIŠCCBallocations 9992.&.M610DRV.LGŠLINKcommands#9998.VERSAPT.M610DRV.CF„Patchfile  /‰Thedrivernewsfilethatyouarenowreading:9992.&.M610DRV.NW‰Newsfile F‰MVME610/620DriverCommandandErrorCodeEquatefiles.TheseequatesB‹areusedbytheapplicationcodewhenmakingcallstothedriver.9995.&.M610CMD.EQ ?‰Thefollowingfilesareusedtogenerateadrivertestprogram9992.M610DRV.INPTST.LO: 79992.M610DRV.INPTST.SA…Pascalmainprogramsourcefile?9992.M610DRV.INTSTASM.SAƒSourceforassemblyprocedurescalled¨fromPascalmainprogram59992.M610DRV.INPTST.PF…Pascalcompilationchainfile-9992.M610DRV.INTSTASM.AFƒAssemblychainfile.9992.M610DRV.INPTST.LF…Testprogramlinkfile?9992.M610DRV.PDOLRLIB.ROƒSupplementaryPascalRun-timeLibrary @‰Thefollowingfilesareusedtogenerateasecondtestprogram: >‰9992.M610DRV.TEST610.SA‡AssemblylanguagetestprogramsourceA‰9992.M610DRV.TEST610.AF‡chainfileforassemblylanguageprogramA‰9992.M610DRV.TEST610.LF‡chainfileforlinkofasmlang.program7‰9992.M610DRV.TEST610.LO‡assemblylanguagetestprogram F À3É0Ñ#Ù'á G‚ThefollowingfilesareusedtoassembleandlinktheFortrancallable"driver command subroutine library: 0‰9992.&.M610LIB.SAAssemblylanguagesourcefile‰9992.&.M610LIB.ROObjectfile&‰9992.&.M610LIB.AFAssemblychainfile M‚ToassembletheMVME610/620Driverexecutethechainfile9992.&.M610DRV.AF.9The following files are required to assemble this driver: ‰9995.&.STR.EQ‰9995.&.TR1RTCD.EQ‰9995.&.TCB.EQ‰9995.&.LV5.EQ‰9995.&.BAB.EQ‰9995.&.CCB.EQ‰9995.&.M610CCB.EQ‰9995.&.M610INTQ.EQ‰9995.&.M610CMD.EQ +SYSgen Procedure for the MVME610/620 Driver+------------------------------------------- <1.‚UseCOPYSGENtogetallthefilesrequiredfortheSYSgen7„totheusernumberwheretheSYSgenwillbeperformed.G„NOTE:‚Makesurethatargument5=PCDRVsotheProcessControlDrivers‹willbecopiedbyCOPYSGEN. K2.‚Editthe.CNFGDRVR.CIfileforgeneratingtheRMS68KorVERSAdosC„foryourtargetsystem.‚ModifytheSYSgenparameters"NVME610"andE„"NVME620".‚TheseparametersdefinethemaximumnumberofMVME610andD„NVME620boardsthatwilloccupythetargetsystem.OneothersysgenH„parameterthatmustbemodifiedisM610QSIZ.‚ThisparameterdefinestheI„minimumsizeoftheinterruptprocessingqueueintermsofthenumberofK„entriesthatthequeuemaycontain.‚ThedrivercanaccomodateamaximumofE„2048queueentries.‚FormoreinformationontheInterruptProcessing3„QueueconsulttheMVME610/620DriverUsersManual.  I3.‚EditthefileM610IOC.SIsothatonecalltotheCDBmacroismadeforJ„eachMVME610orMVME620boardthatwasspecifiedin.CNFGDRVR.CI.J„EachCDBmustspecifyauniquechannelmnemonic(i.e.'IN01').‚Thememory=„mappedI/OaddressoffsetcanbemodifiedinIOC.ADDRESS.CI.5„TheI/OchannelinterruptvectornumberandhardwareJ„interruptlevelspecifiedforeachCDBcanalsobemodifiedifnecessary.;„ConsulttheSYSgenUsersGuideforadditionalinformation.  F4. You may now run the SYSgen utility to generate a RMS68K or VERSAdos$ƒbootmoduleforyourtargetsystem. I‚AlsoprovidedwiththisdriverisalibraryofFortrancallableassemblyFlanguage subroutines that allow a Fortran application program to issueIcommands directly to the MVME610/620 driver. This library is contained infile M610LIB.RO. I‚IfthedriverstargetenvironmentincludesVERSAdos,youmaywishtorunMthe driver test program INPTST.LO to verify that you have an operable SYSgen. L‚ThistestprogramallowsyoutocreatemultipletasksandtoissuecommandsGfrom these tasks to the MVME610/620 driver by responding to prompts for1input commands via a single interactive terminal. J‚Whentheprogrambeginsexecuting,theuserispromptedforthenumberofKtasks that are to be created. The tasks that are spawned are exact replicasJof one another. After each task initializes itself, it waits for a command)from the user to be issued to the driver. F‚ThenameofthefirsttesttaskisdisplayedandtheuserisaskedtoNselect a command to be issued to the driver (i.e Open, Close, Enable, Disable,KStatus, or Wait). If the Open command is selected, the user is prompted forKthe channel mnemonic of the desired MVME610/620 board and the number of theFchannel to be opened by the command. The user is then prompted for theFchannel number and configuration for each channel to be opened. If theKClose, Enable, Disable, or Status command is selected, the user is promptedIfor the MVME610/620 board channel mnemonic and the mask of channels to beHaffected by the command. After each command has been issued, the commandJstatus returned by the driver is displayed. If a Status command is issued,.the returned channel status G is also displayed. G‚Afterthecommandstatusisreturned,theuserispromptedforanotherLcommand for the same task. The program will continue to request commands forLthe same test task until a CR only is entered in response to the prompt. TheGuser will then be prompted for commands to the next test task. When theKprogram has prompted for commands for each of the test tasks, it begins theJcycle again by prompting for commands for the first task. This loop may beKterminated by pressing the break key on the terminal after all open channelassignments have been closed. L‚Onceaninterruptchannelhasbeenopenedandinterruptshavebeenenabled,Ithe user may connect an input source to the channel to test the interruptFmechanism. Whenever an interrupt generating condition is detected on aKchannel (as specified in the channel configuration), the driver informs theLtest task that opened the channel of the interrupt via an event to the tasksLASQ or by issuing a WAKEUP to the task. When an interrupt event is received,Mthe task provides an external acknowledgement of the interrupt by pulsing oneFoutputs of a MVME625 Digital Output board that is assumed to reside atKaddress $FE6001 of the I/O channel. This pulse may be detected via standardJoscilloscope or by other available means. The program will accomodate uptoKtwo MVME610/620 boards with assumed channel mnemonics of 'IN01' and 'IN02'.NThe acknowledge pulse is sent to a unique MVME625 output for each interruptingchannel as follows: "„MVME610/620ƒInputChannel„MVME625…mnemonic‰NumberˆOutput"„-----------ƒ-------------„------- †IN0100 †IN0111 †IN0122 †IN0133 †IN0204 †IN0215 †IN0226 †IN0237 G‚WhenataskistobenotifiedofaninterruptviaaWakeup,aslightlyMdifferent procedure is used. After the channel has been opened and interruptsKhave been enabled, the user enters a Wait command to the task that assignedIthe channel. This command causes the task to be placed in a Wait state soKthat it can respond to the Wakeup to be issued to the driver. When a WakeupBis received, the test task pulses output 7 of the MVME625 board toGacknowledge the interrupt. Since only output 7 is used to acknowledge aNWakeup, receiving of Wakeup's by multiple tasks will result in all acknowledgeNpulses being superimposed on output 7. Also once a task has been placed in theNWait state, issuing a new command to the same task will cause the test program1to be suspended until the task recieves a Wakeup.   GM610DRV.TEST610.SA is an assembly language test program which tests theDMVME610driver.‚ThisprogrampromptstheusertorunasubsetofallDcommandsavailableinthedriver.‚ItcanbeusedasafirstcheckofAthe hardware and as an example of writing commands to the driver. ééééG éN==============================================================================F====‚NEWSFILEFORACO…(MVME615-ACOUTPUTBOARD)ƒDRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N============================================================================== 8This driver is compatible with both RMS68K and VERSAdos.   .This driver consists of the following files -- ‰MVME615driverfiles:-9992.&.M615DRV.SA†MVME615driversourcefile-9992.&.M615DRV.RO†MVME615driverobjectfile59992.&.M615DRV.AF†MVME615driverassemblychainfile  ‰Filesforallocatingmemory:09992.&.M615MEM.CIŠFileincludedatSYSgentime.09992.&.M615MEM.AGŠFileassembledatSYSgentime   ‰Files‚forsystemconfiguration:"9992.&.M615IOC.SIˆCCBallocations"9992.&.M615DRV.CIˆSYSGENcommands39992.&.M615DRV.LGˆChainfiletolinkinthedriver#9998.VERSAPT.M615DRV.CF‚Patchfile   ‰FORTRANinterfacesubroutines:09992.&.M615LIB.SA…Assemblylanguagesourcefile&9992.&.M615LIB.AF…Assemblychainfile9992.&.M615LIB.RO…Objectfile  ‰"News"file:9992.&.M615DRV.NW…Newsfile   "‰Filestogenerateatestprogram: ;‰9992.M615DRV.TESTAC.SAˆASSEMBLYlanguagetestprog.source=‰9992.M615DRV.TESTAC.AFˆchainfileforASSEMBLYlanguageasm.>‰9992.M615DRV.TESTAC.LFˆchainfileforLINKofasm.lang.prog6‰9992.M615DRV.TESTAC.LOˆASSEMBLYlanguagetestprogram @‰Thefollowingfilesareusedtogenerateasecondtestprogram: >‰9992.M615DRV.TEST615.SA‡AssemblylanguagetestprogramsourceA‰9992.M615DRV.TEST615.AF‡chainfileforassemblylanguageprogramA‰9992.M615DRV.TEST615.LF‡chainfileforlinkofasmlang.program7‰9992.M615DRV.TEST615.LO‡assemblylanguagetestprogram  KTheMVME615driversourcefileis:9992.&.M615DRV.SA.‚Toassemblethisfile%use the chain file 9992.&.M615DRV.AF.;The following files are used in the assembly of M615DRV.SA:9995.&.STR.EQ9995.&.TCB.EQ9995.&.CCB.EQ9995.&.LV5.EQ9995.&.TR1RTCD.EQéAò4ú8 49995.&.M615DRV.EQ  >In order to incorporate this driver into your system, you will=have to set some parameters in the .CNFGDRVR.CI file. #This driver requires the following:;‰1)‚Memorymustbeallocatedfortheinternaldrivertable.9‰2)‚Achannelcontrolblock(CCB)mustbecreatedforthe6commandsissuedforeachMVME615boardinthesystem. HThe size of the memory area set aside for the driver table is determinedGbythevaluesoftwovariablesasspecifiedbyyouintheSYSGEN.‚These$variables are "NVME615" and "NU615". =NVME615ƒThisisthenumberofMVME615boardswhichwillbeon6Šthesystem.‚Sincetherecanbenomorethan16boards6ŠontheI/OChannel(whichiswheretheseboardsare),&Šthemaximumvalueof"NVME615"is16. 3NU615…Thisvariableissettothemaximumnumberof7Šuser/MVME615combinationsyouwishtoallowatanyone2Štime.‚Sinceitispossibletohaveoneuserusing;ŠmorethanoneMVME615board,aswellasmorethanoneuser4ŠusingthesameMVME615board,weneedthenumberofŠuser/MVME615combinations.   ?Example:‚IfuserAusesboard#1andboard#2,userBusesjust1Šboard#1,anduserCusesboard#2andboard#3,,Štherewouldbe5user/boardcombinations--ŠA/1,A/2,B/1,C/2,C/3.FIf the configuration of MVME615 boards is the same as in this example,$you would set NVME615=3 and NU615=5. INote that if you set either of these variables to a larger number than isHactuallyneeded,thesystemwillstilloH peratenormally.‚ThiswouldjustBresult in having more memory allocated for internal tables than is necessary.  ?To include the MVME615 driver in your SYSgen, do the following: <‰(1)UseCOPYSGENtogetallthe‚filesneededfortheSYSgenyourSYSgenusernumber.7NOTE:‚Makesurethatargument5=PCDRVsotheProcess,”ControlDriverswillbecopiedbyCOPYSGEN. D‰(2)SetthevariablesNVME615andNU615inthe.CNFGDRVR.CI,filefortheprocessorboardyouareusing. 8‰(3)CheckthefileM615IOC.SItobesurethattheCCB'sconformtoyourconfiguration.   FWhen setting up the "CDB" calls please note that each ACO-ID must haveCauniquename.‚ThisisalsothenameanyapplicationtaskwoulduseFtoaddressthedriverforaboard.‚Thememory-mappedI/Oaddressesarealso different for each board. 1After creating and booting your VERSAdos with the>MVME615 driver included, you may want to run the provided test"program to test your VME615 board.  FTESTAC.SA is an assembly language test program which tests the MVME615Cdriver. This program provides as complete and comprehensive test ofCthe driver as is possible. It tests combinations of opens, outputs,Fpulses, closes, status, and error tests, and checks outputs and errors@forcorrectness.‚PleaseedititbeforeassemblingtospecifytheIcorrect ACO-ID and memory-mapped I/O address to match your configuration.   ETESTAC.SA is assembled with the chain file TESTAC.AF, and linked with1the file TESTAC.LF. The load module is TESTAC.LO.   GTo use the test program TESTAC.LO, provide an MVME615 board with output indicators on channels 0 thru 7.  +The tests made on the board are as follows:  <‰TEST1individuallyopenseachchannelontheboard,outputs7toit,checksstatus,turnsitoff,checksstatus,and5closes.Anyerrorsintheprocessareprintedonthe terminal. >‰TEST2individuallyopenseachchannel,outputstoit&checks8statusuntilallareon.Thenitindividuallyturnsoff9eachchannel&checksstatusuntilallareoff.Itturns'alloutputsbackonforthenexttest. ?‰TEST3closesthechannels.TheOPERATORofthetestmustcheckthattheoutputsturnoff. =‰TEST4opensallchannels,turnsthechannelsallon,delays,$turnsallchannelsoff,andcloses. @‰TEST5individuallyopenseachchannel,commandsapulseoutput,8delayslongenoughtobeabletoseethepulseend,andcloses. ?‰TEST6opensfourchannels,commandspulseoutputsofdifferent9lengthstoeachsimultaneously,delaystobeabletoseeithappen,andcloses. A‰TEST7openschanneltwowith"queueevent"configuration,pulses:output,waitsforqueueevent,verifiesthemessagesent, andcloses.  ?‰TEST8openschannelonewith"waitforwake-up"configuration,.pulsesoutput,waitsforwake-up,andcloses. ;‰TEST9trysOUTPUTONwithchannelsclosedandverifiesthecommanderror.6trysOUTPUTOFFwithchannelsclosedandverifiesthecommanderror.7tryscheckingSTATUSwithchannelsclosedandverifiesthecommanderror.8trysPULSEoutputwiththechannelsclosedandverifiesthecommanderror. =‰TEST10trysopeninginvalidchannelnumbersandverifiesthecommanderrors.7(zerochannels,morethaneightchannels,channel#9,(andtwochannelswiththesamenumber). :‰TEST11opensvalidchannelsandtrysinvalidcommandsandverifieserrors.(commands0,6,7,&9). =‰TEST12trysopeningchannelsandthenopeningthemagainandverifiestheerror.  ;‰Thenthechannelsareclosed.Ifalltestsaresuccessful,3amessageisprintedsayingso.Ifanytestfails,anerrormessageisprinted.<‰Ifasecondboardisonthesystem,itreturnstoTEST1and(repeatsthetestsforthesecondboard.=‰Inaddition,iftwoboardsarepresent,athirdpassthrough6thetestsalternatesbetweentheboardstocheckbothatthesametime.  GH M615DRV.TEST615.SA is an assembly language test program which tests theDMVME615driver.‚ThisprogrampromptstheusertorunasubsetofallDcommandsavailableinthedriver.‚ItcanbeusedasafirstcheckofAthe hardware and as an example of writing commands to the driver. ‰ENDN==============================================================================N==============================================================================' M625DRV NW  *>qqRADDRV NW G G¥qqRIODRV NW h hµqqM600IOC SI ‰ ‰ qqM605IOC SI ’ ’qqM610IOC SI › ›qqM615IOC SI ¤ ¤qqM625IOC SI ­ ­qqRIOIOC SI ¶ ¶ qqRADIOC SI ¿ ¿ qqIOCFAIL RO È ÈqqM600DRV RO Ñ ÑqqM600LIB RO Ú ÚqqM605DRV RO ã ãqqM605LIB RO ì ìqqM610DRV RO õ õqq610LIB ROÿÿÿÿÿÿÿÿqqN==============================================================================F====‚NEWSFILEFORDCO…(MVME625-DCOUTPUTBOARD)ƒDRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N============================================================================== 8This driver is compatible with both RMS68K and VERSAdos.   .This driver consists of the following files -- ‰MVME625driverfiles:-9992.&.M625DRV.SA‚MVME625driversourcefile-9992.&.M625DRV.RO‚MVME625driverobjectfile59992.&.M625DRV.AF‚MVME625driverassemblychainfile  ‰Files‚forallocatingmemory:/9992.&.M625MEM.CI‰FileincludedatSYSgentime09992.&.M625MEM.AG‰FileassembledatSYSgentime  ‰Filesforsystemconfiguration:"9992.&.M625DRV.CIˆSYSGENcommands"9992.&.M625IOC.SIˆCCBallocations39992.&.M625DRV.LGˆChainfiletolinkinthedriver#9998.VERSAPT.M625DRV.CF‚Patchfile   ‰FORTRANinterfacesubroutines:09992.&.M625LIB.SA…Assemblylanguagesourcefile&9992.&.M625LIB.AF…Assemblychainfile9992.&.M625LIB.RO…Objectfile  ‰"News"file:9992.&.M625DRV.NW…Newsfile   %‰Filestogeneratethetestprograms: ;‰9992.M625DRV.TESTDC.SAˆASSEMBLYlanguagetestprog.source=‰9992.M625DRV.TESTDC.AFˆchainfileforASSEMBLYlanguageasm.>‰9992.M625DRV.TESTDC.LFˆchainfileforLINKofasm.lang.prog6‰9992.M625DRV.TESTDC.LOˆASSEMBLYlanguagetestprogram 3‰9992.M625DRV.TSTDCO.SAˆFORTRANtestprogramsource=‰9992.M625DRV.TSTDLY.SAˆFORTRANtestprogramsubrtnfordelay?‰9992.M625DRV.TSTPR1.SAˆFORTRANtestprogramsubrtnerrorprint;‰9992.M625DRV.TSTDCO.AFˆchainfileforFORTRANcompiletest>‰9992.M625DRV.TSTDCO.LFˆlinksFORTRANtestprog.&libraryrtn6‰9992.M625DRV.TSTDCO.LOˆFORTRANtestprogramloadfile >‰9992.M625DRV.TEST625.SA‡AssemblylanguagetestprogramsourceA‰9992.M625DRV.TEST625.AF‡chainfileforassemblylanguageprogramA‰9992.M625DRV.TEST625.LF‡chainfileforlinkofasmlang.program : 8 4 '7 /P 77‰9992.M625DRV.TEST625.LO‡assemblylanguagetestprogram  KTheMVME625driversourcefileis:9992.&.M625DRV.SA.‚Toassemblethisfile%use the chain file 9992.&.M625DRV.AF.;The following files are used in the assembly of M625DRV.SA:9995.&.I STR.EQ9995.&.TCB.EQ9995.&.CCB.EQ9995.&.LV5.EQ9995.&.TR1RTCD.EQ9995.&.M625DRV.EQ  >In order to incorporate this driver into your system, you will=have to set some parameters in the .CNFGDRVR.CI file.  #This driver requires the following:;‰1)‚Memorymustbeallocatedfortheinternaldrivertable.9‰2)‚Achannelcontrolblock(CCB)mustbecreatedforthe6“commandsissuedforeachMVME625boardinthesystem. HThe size of the memory area set aside for the driver table is determinedGbythevaluesoftwovariablesasspecifiedbyyouintheSYSGEN.‚These$variables are "NVME625" and "NU625". =NVME625ƒThisisthenumberofMVME625boardswhichwillbeon6Šthesystem.‚Sincetherecanbenomorethan16boards6ŠontheI/OChannel(whichiswheretheseboardsare),&Šthemaximumvalueof"NVME625"is16. 3NU625…Thisvariableissettothemaximumnumberof7Šuser/MVME625combinationsyouwishtoallowatanyone2Štime.‚Sinceitispossibletohaveoneuserusing;ŠmorethanoneMVME625board,aswellasmorethanoneuser4ŠusingthesameMVME625board,weneedthenumberofŠuser/MVME625combinations.   ?Example:‚IfuserAusesboard#1andboard#2,userBusesjust1Šboard#1,anduserCusesboard#2andboard#3,,Štherewouldbe5user/boardcombinations--ŠA/1,A/2,B/1,C/2,C/3.FIf the configuration of MVME625 boards is the same as in this example,$you would set NVME625=3 and NU625=5. INote that if you set either of these variables to a larger number than isHactuallyneeded,thesystemwillstilloperatenormally.‚ThiswouldjustBresult in having more memory allocated for internal tables than is necessary.    ?To include the MVME625 driver in your SYSgen, do the following: <‰(1)UseCOPYSGENtogetallthefilesneededfortheSYSgenintoyourSYSgenusernumber.2NOTE:‚Makesureargument5=PCDRVsotheProcess+”ControlDriverswillbecopiedbyCOPYSGEN D‰(2)SetthevariablesNVME625andNU625inthe.CNFGDRVR.CI,filefortheprocessorboardyouareusing. 8‰(3)CheckthefileM625IOC.SItobesurethattheCCB'sconformtoyourconfiguration. FWhen setting up the "CDB" calls please note that each DCO-ID must haveCauniquename.‚ThisisalsothenameanyapplicationtaskwoulduseBtoaddressthedriverforaboard.‚Thememory-mappedI/Oaddresses"are also different for each board.  >After configuring your system and creating a VERSAdos with the>MVME625 driver included, you may want to run the provided test=programs.‚TwoareassemblylanguageandonerequiresFortran.ABothofthetestprogramsrequireVERSAdos.‚Allthetestprograms=contain the catalog name M625DRV and are in user number 9992.  FTESTDC.SA is an assembly language test program which tests the MVME625Cdriver. This program provides as complete and comprehensive test ofCthe driver as is possible. It tests combinations of opens, outputs,Fpulses, closes, status, and error tests, and checks outputs and errors@forcorrectness.‚PleaseedititbeforeassemblingtospecifytheIcorrect DCO-ID and memory-mapped I/O address to match your configuration.   ETESTDC.SA is assembled with the chain file TESTDC.AF, and linked with1the file TESTDC.LF. The load module is TESTDC.LO.   GTo use the test program TESTDC.LO, provide an MVME625 board with output indicators on channels 0 thru 7.  +The tests made on the board are as follows:  <‰TEST1individuallyopenseachchannelontheboard,outputs7toit,checksstatus,turnsitoff,checksstatus,and5closes.Anyerrorsintheprocessareprintedonthe terminal. >‰TEST2individuallyopenseachchannel,outputstoit&checks8statusuntilallareon.Thenitindividuallyturnsoff9eachchannel&checksstatusuntilallareoff.Itturns'alloutputsbackonforthenexttest. ?‰TEST3closesthechannelsI .TheOPERATORofthetestmustcheckthattheoutputsturnoff. =‰TEST4opensallchannels,turnsthechannelsallon,delays,$turnsallchannelsoff,andcloses. @‰TEST5individuallyopenseachchannel,commandsapulseoutput,8delayslongenoughtobeabletoseethepulseend,andcloses. ?‰TEST6opensfourchannels,commandspulseoutputsofdifferent9lengthstoeachsimultaneously,delaystobeabletoseeithappen,andcloses. A‰TEST7openschanneltwowith"queueevent"configuration,pulses:output,waitsforqueueevent,verifiesthemessagesent, andcloses.  ?‰TEST8openschannelonewith"waitforwake-up"configuration,.pulsesoutput,waitsforwake-up,andcloses. ;‰TEST9trysOUTPUTONwithchannelsclosedandverifiesthecommanderror.6trysOUTPUTOFFwithchannelsclosedandverifiesthecommanderror.7tryscheckingSTATUSwithchannelsclosedandverifiesthecommanderror.8trysPULSEoutputwiththechannelsclosedandverifiesthecommanderror. =‰TEST10trysopeninginvalidchannelnumbersandverifiesthecommanderrors.7(zerochannels,morethaneightchannels,channel#9,(andtwochannelswiththesamenumber). :‰TEST11opensvalidchannelsandtrysinvalidcommandsandverifieserrors.(commands0,6,7,&9). =‰TEST12trysopeningchannelsandthenopeningthemagainandverifiestheerror.  ;‰Thenthechannelsareclosed.Ifalltestsaresuccessful,3amessageisprintedsayingso.Ifanytestfails,anerrormessageisprinted.<‰Ifasecondboardisonthesystem,itreturnstoTEST1and(repeatsthetestsforthesecondboard.=‰Inaddition,iftwoboardsarepresent,athirdpassthrough6thetestsalternatesbetweentheboardstocheckbothatthesametime.      JM625LIB.SAisassembledusingtheM625LIB.AFchainfile.‚M625LIB.ROistheEFORTRAN-callable subroutine which, when called by the user program orJFORTRAN test program, will invoke the appropriate MVME625 driver function.   BTSTDCO.SA is a FORTRAN example test program which uses the driver.EThe purpose in providing the FORTRAN test program is to give the userEa relatively simple way to check out a new system with software whichis known to work correctly.   FTSTDCO.SA, TSTDLY.SA, and TSTPR1.SA are Fortran compiled with the fileETSTDCO.AF.‚FileTSTDCO.LFlinksthetestroutineswithM625LIB.ROandFFORTLIB.RO (and FORTVMC.RO for the VMC or VME systems) and creates theprogram TSTDCO.LO.  ETo use test program TSTDCO.LO, provide a board with output indicators+onchannels0thru7.‚ThenRUNtheprogram.  BThe result will be observable on the output indicators as follows:  ?‰indicators0thru7willturnonindividuallyatapproximately‰onesecondintervals.“FORN=1to8OPENchannelN-1turnonindicatorN-1waitonesecondreadoutputstatusverifyindicatorN-1onturnoffindicatorN-1CLOSE“NEXTN A‰indicators0thru7willturnononeatatimeuntilallareon.“FORN=1to8OPENchannelN-1turnonindicatorN-1waitonesecondreadoutputstatus"verifyindicators0toN-1areon“NEXTN“waitonesecond“CLOSE“waitonesecond “readstatus“verifyoutputsareoff "‰indicators‚0thru7willturnon. “OPENall“turnonallindicators“waitonesecond“turnOFFallindicators“verifyallindicatorsareoff“CLOSE ,‰indicatorswillbePULSEDononeatatime.4‰(defaultconfiguration-nowake-uporqueueevent) “OPENall“FORN=1TO8PULSEindicatorN-1waitonesecond“NEXTN“CLOSE 7‰CLOSEallchannelsandtryallcommands.Verifyerror.“DCOUT‚command “DCOOFFƒ" “DCOSTAƒ" “DCOPLSƒ" “DCOPENƒ"6‰TryDCOPENafteritisalreadyopenandverifyerror.  ;‰Checkforasecondboardonthesystemandrepeatthetest‰ifoneispresent.  GM625DRV.TEST625.SA is an assembly language test program which J tests theDMVME625driver.‚ThisprogrampromptstheusertorunasubsetofallDcommandsavailableinthedriver.‚ItcanbeusedasafirstcheckofAthe hardware and as an example of writing commands to the driver. ‰ENDN==============================================================================N==============================================================================éééééN==============================================================================L====‚NEWSFILEFORRAD1(REMOTEANALOG-TO-DIGITALBOARD)DRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N==============================================================================   3RAD1 Driver is compatible with RMS68K and VERSAdos.   /This release consists of the following files -- ‰RAD1Driverfiles:)“9992.&.RADDRV.SA…RAD1driversourcefile1“9992.&.RADDRV.AF…RAD1driverassemblychainfile)“9992.&.RADDRV.RO…RAD1driverobjectfile ‰Fileforallocatingmemory:,“9992.&.RADMEM.AG…Fileforallocatingmemory.“9992.&.RADMEM.CI…Fileincludedatsysgentime ‰Filesforsystemconfiguration:5“9992.&.RADDRV.CI…SysgenincludefileforRAD1driver3“9992.&.RADDRV.LG…ChainfiletolinkinRAD1driver!“9992.&.RADIOC.SI…CCBallocations7“9992.&.IOCFAIL.SA„Boardfailuremonitorroutinesource.“9992.&.IOCFAIL.AF„IOCFAILassemblychainfile .“9992.&.IOCINT.LG…ChainfiletolinkinIOCINT0“9992.&.IOCFAIL.LG„ChainfiletolinkinIOCFAIL"“9998.VERSAPT.RADDRV.CFPatchfile ‰FilesassembledduringSYSGEN:4“9992.&.IOCINT.AG…CCBallocationroutinesourcefile ‰FORTRANinterfacesubroutines:/“9992.&.RADLIB.SA…Assemblylanguagesourcefile%“9992.&.RADLIB.AF…Assemblychainfile“9992.&.RADLIB.RO…Objectfile ‰"News"file:“9992.&.RADDRV.NW…Newsfile   JTheRAD1driversourcefileis:‚RADDRV.SA.‚Toassemblethisfile,usetheKchainfile:‚RADDRV.AF.‚Thefollowingequatefilesareusedintheassembly of RADDRV:“9995.&.STR.EQ“9995.&.TCB.EQ“9995.&.CCB.EQ“9995.&.LV5.EQ“9995.&.RADDRV.EQ   BIn order to incorporate the RAD1 driver into your system, you will.CNFGDRVR.CI file.   'The RAD1 driver requires the following:<‰1)‚Memorymustbeallocatedfortheinternaldrivertables.9‰2)‚Achannelcontrolblock(CCB)mustbecreatedforthe ?A H4 P$ X J 6“datainterrupt(level3interrupt)oneachRAD1board“inthesystem.9‰3)‚ACCBmustbecreatedfortheboard-failureinterrupt-“(level4interrupt)oneachRAD1boardwhich+“doesnothavethisinterruptdisabledbya“jumperontheboard.   IThe size of the memory area set aside for the driver tables is determinedKby the values of two variables as specified by you in .CNFGDRVR.CI.'These variables are "NRAD" and "NURAD". 7NRAD†ThisisthenumberofRAD1boardswhichwillbeon6Šthesystem.‚Sincetherecanbenomorethan16boards9ŠontheI/OChannel(whichiswheretheRAD1boardsare),#Šthemaximumvalueof"NRAD"is16. 3NURAD…Thisvariableissettothemaximumnumberof4Šuser/RAD1combinationsyouwishtoallowatanyone2Štime.‚Sinceitispossibletohaveoneuserusing8ŠmorethanoneRAD1board,aswellasmorethanoneuser1ŠusingthesameRAD1board,weneedthenumberofŠuser/RAD1combinations. ,Example:‚IfuserAusesRAD1#1andRAD1#2,ŠuserBusesjustRAD1#1,%ŠanduserCusesRAD1#2andRAD1#3,+Štherewouldbe5user/RAD1combinations--ŠA/1,A/2,B/1,C/2,C/3.CIf the configuration of RAD1 boards is the same as in this example,!you would set NRAD=3 and NURAD=5. INote that if you set either of these variables to a larger number than isHactuallyneeded,thesystemwillstilloperatenormally.‚ThiswouldjustBresult in having more memory allocated for internal tables than is necessary. JThe variables NRAD and NURAD are defined in the file .CNFGDRVR.CI.FYou will have to edit this file to reflect the correct values of these,variables for your particular configuration.   BThe code to allocate memory for the RAD1 driver internal tables iscontained in the file RADMEM.AG   EYour SYSGEN will set up a task which will allocate the CCB's (channelAcontrol blocks) for the RAD1 boards during system initialization.IThe file IOCINT.AG is included in this release to simplify the allocation2oftheCCB's.‚ThefileRADIOC.SIhasbeenincluded5to give you an example of the set-up used to pass theEinformation on each RAD1 board to the program which builds the CCB's. 8When setting up the "CDB" calls, remember the following: '1)ƒTheRAD-IDisa4-charactermnemonicE…suchas"RA01"forthefirstRAD1board,"RA02"forthesecond,etc.J…EachRAD1boardnormallyhastwoCCB's--oneforinterruptlevel3(normalF…interrupts)andoneforinterruptlevel4(board-failureinterrupts).H…WhileeachCCBmusthaveadifferentRAD-ID,thelevel-4CCBforaRAD1H…boardmustuseforitsRAD-ID‚$00004000morethanthe4-byteASCIIcodeE…fortheRAD-IDofthecorrespondinglevel-3CCB.‚ThisissothattheI…drivercanfindthelevel-3CCBforaparticularRAD1boardwhenitgets…alevel-4interruptH…(board-failureinterrupt).‚Forexample:ifthelevel-3CCBhasaRAD-IDF…of"RA01",thenthelevel-4CCBforthatboardmustuse"RA41"asitsE…RAD-ID.‚Similarly,if"RA13"isthelevel-3RAD-ID,thenthelevel-4$…CCBmusthave"RA53"asitsRAD-ID. M2)ƒWhenmodifyingthe.CNFGDRVR.CIfileforyourparticularsituation&…youshouldrememberthatinthe"CDB"E…macrocalls,theaddressofthememory-mappedI/Ospace(shared-RAM)G…isthesameforbothCCB'sforeachRAD1board.‚AlsothelengthoftheH…memory-mappedI/Ospaceissetat511sinceshared-RAMstartsonanodd(…address(fromthe68000pointofview).   ?IOCFAIL.SA‚isanoptionaltaskwhichwillbe"called"byhaving@an event queued to it when a board-failure interrupt is receivedDbythedriver.‚Thedevicetable("DEVTBL")inIOCFAILmustbesetupJwith the device mnemonic (RAD-ID) of all the level-4 CCB's that IOCFAIL isItobeattachedto.‚ThedevicetableintheIOCFAILfilegivenhereissetNup for two RAD1 boards as a sample -- the level-4 CCB RAD-ID's for these beingL"RA41"and"RA42".‚InitspresentformIOCFAILsetsuptoreceivetheevent,K Kbutdoesn'treallydoanythingwhentheeventisreceived.‚YouwillhavetoGadd whatever programming is necessary to the "receive-event" routine toIhave this program perform the processes you deem necessary in the case ofFaRAD1boardfailure.‚Ifyouchoosetodonothingwhenaboardfailure;occurs, this task can be left out of the SYSGEN altogether.   CRADLIB.SA‚and‚RADLIB.RO‚aretheFORTRAN-callablesubroutineswhich,Hwhen called by the user program, will invoke the appropriate RAD1 driver function. N==============================================================================éééééN==============================================================================B====‚NEWSFILEFORRIO(REMOTEINPUT/OUTPUT)DRIVERRELEASE‚===="====‚Lastmodified-01/31/85¬====N==============================================================================  2RIO Driver is compatible with RMS68K and VERSAdos.   /This release consists of the following files -- ‰RIODriverfiles:(“9992.&.RIODRV.SA„RIOdriversourcefile0“9992.&.RIODRV.AF„RIOdriverassemblychainfile(“9992.&.RIODRV.RO„RIOdriverobjectfile-“9992.&.STDMACRO.AI‚MacrosusedinRIOdriver ‰Fileforallocatingmemory:,“9992.&.RIOMEM.AG„Fileforallocatingmemory.“9992.&.RIOMEM.CI„Fileincludedatsysgentime ‰Fileforsystemconfiguration:!“9992.&.RIOIOC.SI„CCBallocations4“9992.&.RIODRV.CI„SysgenincludefileforRIOdriver2“9992.&.RIODRV.LG„ChainfiletolinkinRIOdriver.“9992.&.IOCINT.LG„ChainfiletolinkinIOCINT"“9998.VERSAPT.RIODRV.CFPatchfile ‰FilesassembledduringSYSGEN:4“9992.&.IOCINT.AG„CCBallocationroutinesourcefile ‰Testprogramfiles/“9992.RIODRV.TESTE.SAƒExampleprogramusingRIOªdriverinwait_for_eventmode.*“9992.RIODRV.TESTE.AFƒAssemblychainfile.1“9992.RIODRV.TESTE.LFƒChainfiletolinkinTESTE4“9992.RIODRV.TESTE.LOƒAssemblylanguagetestprogram @‰Thefollowingfilesareusedtogenerateasecondtestprogram: =‰9992.RIODRV.TESTRIO.SA‡Assemblylanguagetestprogramsource@‰9992.RIODRV.TESTRIO.AF‡chainfileforassemblylanguageprogram@‰9992.RIODRV.TESTRIO.LF‡chainfileforlinkofasmlang.program6‰9992.RIODRV.TESTRIO.LO‡assemblylanguagetestprogram ‰FORTRANinterfacesubroutines:/“9992.&.RIOLIB.SA„Assemblylanguagesourcefile%“9992.&.RIOLIB.AF„Assemblychainfile“9992.&.RIOLIB.RO„Objectfile ‰"News"file:“9992.&.RIODRV.NW„Newsfile  ITheRIOdriversourcefileis:‚RIODRV.SA.‚Toassemblethisfile,usetheKchainfile:‚RIODRV.AF.‚Thefollowingequatefilesareusedintheassembly of RIODRV:K  `: i8 q, y“9995.&.STR.EQ“9995.&.TCB.EQ“9995.&.CCB.EQ“9995.&.LV5.EQ“9995.&.RIODRV.EQ“9995.&.TR1RTCD.EQ  AIn order to incorporate the RIO driver into your system, you will6have to modify items in the .CNFGDRVR.CI file.  &The RIO driver requires the following:<‰1)‚Memorymustbeallocatedfortheinternaldrivertables.:‰2)‚Achannelcontrolblock(CCB)mustbecreatedforeach5interruptlevelforwhichtheRIOboardisjumpered.   IThe size of the memory area set aside for the driver tables is determinedCbytwovariablesasspecifiedbyyouin.CNFGDRVR.CI.‚These$variables are "NRIO", and "NRIOINT". 6NRIO†ThisisthenumberofRIOboardswhichwillbeon6Šthesystem.‚Sincetherecanbenomorethan16boards8ŠontheI/OChannel(whichiswheretheRIOboardsare),#Šthemaximumvalueof"NRIO"is16. GNRIOINTƒThisvariableissettothenumberofhardwareinterruptlevels>ŠforwhichtheRIOboardswillbejumpered.‚Theminimumnumber"Šis1andthemaximumnumberis4. :Note that if you set either of these variables larger thanHactuallyneeded,thesystemwillstilloperatenormally.‚ThiswouldjustBresult in having more memory allocated for internal tables than is necessary. LThe variables NRIO and NRIOINT are defined in the file .CNFGDRVR.CI.FYou will have to edit this file to reflect the correct values of these,variables for your particular configuration.   AThe code to allocate memory for the RIO driver internal tables is contained in the file RIOMEM.AG.   EYour SYSGEN will set up a task which will allocate the CCB's (channel@control blocks) for the RIO boards during system initialization.IThe file IOCINT.AG is included in this release to simplify the allocation2oftheCCB's.‚ThefileRIOIOC.SIhasbeenincluded5to give you an example of the set-up used to pass theDinformation on each RIO board to the program which builds the CCB's. 8When setting up the "CDB" calls, remember the following: '1)ƒTheRIO-IDisa4-charactermnemonicE…suchas"RIO1"forthefirstRIO1board,"RIO2"forthesecond,etc.  CRIOLIB.SA‚and‚RIOLIB.RO‚aretheFORTRAN-callablesubroutineswhich,Gwhen called by the user program, will invoke the appropriate RIO driver function.  FTESTE.SA is an example program written in assembly language which uses?theRIOdriver.‚Thepurposeinprovidingthetestprogramisto?give the user a relatively simple way to check out a new system/with software which is known to work correctly. 3To use the test program as is, provide an RIO board:with input relays in locations 0,1,2,3 and 10, and provideDoutputrelaysinlocations5,7,8,and9.‚Connectanelectronicpulse@generator to input 0, with the ON pulse time of 10 milliseconds,Lamp5willalternateon/offatthepulserepetitionrate.<„>Lamps7,8,9willturnontogetherateachinputONpulse,9†thenwillgooutinsequence7-8-9(theyareonchannels†performingpulsedoutput). EChannel 0 is set to cause an interrupt on falling edge, so it's inputBneeds to be low (OFF) for the period of the debounce time which isB512milliseconds.‚Withthepulsegeneratorsetasdescribedabove,?thisrequirementismet.‚IftheinputpulseOFFtimeisreducedCto below 512 milliseconds, the debounce requirement will not be met%and the input signal will be ignored. milliseconddebounce.‚Tomakechannel1signalsberecognized,The test program disables channel 1 interrupts after recievingA10 interrupts on that channel, then re-enables them after another610 interrupts (which must come in on another channel). AThe test program sets channel 2 for interrupt on rising edge withBno debounce, and sets channel 3 for interrupt on falling edge with no debounce. EChannel 10 is set for input with interrupts disabled, and will return>it's input state to the 'returned command status' field in theRIO parameter block. FSince the test program is configured to recieve interrupt notificationBvia a 'queued event', each recognized interrupt will place a dummy@messageinthetesttaskA.S.Q..‚Theroutine'TESTIRQ'movestheAmessage from the ASQ (which is not directly acessable by the user?task'TESTE')tothetaskrecieverbuffer,definedasRCVBUF‚inTESTE. FRIODRV.TESTRIO.SA is an assembly language test program which tests the@RIOdriver.‚ThisprogrampromptstheusertorunasubsetofallDcommandsavailableinthedriver.‚ItcanbeusedasafirstcheckofAthe hardware and as an example of writing commands to the driver. N==============================================================================ééé*‰&.M600IOC.SIG*======================================================================*E* THIS IS THE CODE NEEDED TO SET UP CCB'S FOR MVME 600 or 601 BOARDS.*@* Add a CCB definition for each additional board in your system.A* Note that the memory-mapped I/O address must be unique for eachB* board, must not conflict with any other board in the system, andF*mustmatchtheon-boardjumperselections.‚TheI/OChannelinterruptC* vector number and hardware interrupt level must correspond to the* jumpers on the board.*G*======================================================================*M600†EQU„\M600DRV)L600$01ƒSET„\L600$01‹Setboard#1address)L600$02ƒSET„\L600$02‹Setboard#2address***ˆSetup600/601boardCCB*@ CDB XOPEXC,'AD01',$80,0,M600,0,L600$01,1,\IOCVEC1,\IOCLVL1,$FF,&0,0,0,0,0,0,0,0,0,0,0*N*-----------------------------------------------------------------------------*IFGE…\NVME600-2**ˆSetup600/601boardCCB*@ CDB XOPEXC,'AD02',$80,0,M600,0,L600$02,1,\IOCVEC1,\IOCLVL1,$FF,&0,0,0,0,0,0,0,0,0,0,0 ENDCééL é !*ˆ&.M605IOC.SIG*======================================================================*@* THIS IS THE CODE NEEDED TO SET UP A CCB FOR ONE MVME605 BOARD.*@* Add a CCB definition for each additional board in your system.@* An address for a second MVME605 board can be offset $100 bytes* from the first.=* For example, another MVME605 board could have an address of* \IOCBASE+$1D01.A* Note that the memory mapped I/O address must be unique for eachB* board, must not conflict with any other board in the system, andB*mustmatchtheon-boardjumperselections.‚SincethisboarddoesG* not generate interrupts it may be nice to choose the lowest interrupt5* level and software priority level for CCB chaining.*G*======================================================================*/M605†EQU„\M605DRV‹Settheaddressofthedriver-L605$01ƒSET„\L605$01‹Settheboard#1address**J CDB XOPINH+XOPEXC,'DAC1',$80,254,M605,0,L605$01,31,\IOCVEC1,\IOCLVL1,$50,&„0,0,0,0,0,0,0,0,0,0,0éééé Š*ˆINCLUDE‚&.M610IOC.SIG*======================================================================*E* THIS IS THE CODE NEEDED TO SET UP CCB'S FOR MVME 610 or 620 BOARDS.*@* Add a CCB definition for each additional board in your system.A* Note that the memory mapped I/O address must be unique for eachB* board, must not conflict with any other board in the system, andM* must match the on-board jumper selections. The I/O Channel interrupt vectorM* number and hardware interrupt level must correspond to the interrupt jumper* on the board.*G*======================================================================*/M610†EQU„\M610DRV‹Settheaddressofthedriver-L610$01ƒSET„\L610$01‹Settheboard#1address-L610$02ƒSET„\L610$02‹Settheboard#2address**@ CDB XOPEXC,'IN01',$80,0,M610,0,L610$01,3,\IOCVEC1,\IOCLVL1,$FF,&„0,0,0,0,0,0,0,0,0,0,0**IFGE…\NVME610-2*@ CDB XOPEXC,'IN02',$80,0,M610,0,L610$02,3,\IOCVEC2,\IOCLVL2,$FF,&„0,0,0,0,0,0,0,0,0,0,0 ENDCéM ééé “*ˆ&.M615IOC.SIG************************************************************************0*Codetobeincludedin‚IOCINT.AG‚tosetupfor,*’buildingtheCCB'sfortheMVME615boards.*G*======================================================================*@* THIS IS THE CODE NEEDED TO SET UP A CCB FOR ONE MVME615 BOARD.*@* Add a CCB definition for each additional board in your system.E* An additional board may be placed at an offset of $2 bytes from the@* first, for example, on the VME110, two boards may be placed at?* $FE6003 and $FE6005, provided these addresses do not conflict+* with any other board's memory mapped I/O.A* Note that the memory mapped I/O address must be unique for eachB* board, must not conflict with any other board in the system, andB*mustmatchtheon-boardjumperselections.‚SincethisboarddoesG* not generate interrupts it may be nice to choose the lowest interrupt5* level and software priority level for CCB chaining.*G*======================================================================*/M615†EQU„\M615DRV‹Settheaddressofthedriver-L615$01ƒSET„\L615$01‹Settheboard#1address**B CDB XOPEXC,'ACO1',$80,254,M615,0,L615$01,1,\IOCVEC1,\IOCLVL1,$50,&„0,0,0,0,0,0,0,0,0,0,0ééé œ*ˆ&.M625IOC.SIG************************************************************************&*Codetobeincludedin‚IOCINT.AGƒfor,*’buildingtheCCB'sfortheMVME625boards.*G************************************************************************G*======================================================================*@* THIS IS THE CODE NEEDED TO SET UP A CCB FOR ONE MVME625 BOARD.*@* Add a CCB definition for each additional board in your system.E* An additional board may be placed at an offset of $2 bytes from the@* first, for example, on the VME110, two boards may be placed at?* $FE6001 and $FE6003, provided these addresses do not conflict+* with any other board's memory mapped I/O.A* Note that the memory mapped I/O addresM s must be unique for eachB* board, must not conflict with any other board in the system, andB*mustmatchtheon-boardjumperselections.‚SincethisboarddoesG* not generate interrupts it may be nice to choose the lowest interrupt5* level and software priority level for CCB chaining.*G*======================================================================*/M625†EQU„\M625DRV‹Settheaddressofthedriver-L625$01ƒSET„\L625$01‹Settheboard#1address**B CDB XOPEXC,'DCO1',$80,254,M625,0,L625$01,1,\IOCVEC1,\IOCLVL1,$50,&„0,0,0,0,0,0,0,0,0,0,0éé ¥ *ˆ&.RIOIOC.SI*RIO†EQU‡\RIODRVLRIO$01‚SET‡\LRIO$01*$*ˆADDNECESSARYCCBINFORMATIONHERE**ˆSETUPRIOCCB'S*B CDB XOPEXC,'RI01',$80,254,RIO,0,LRIO$01,31,\IOCVEC3,\IOCLVL3,$50,&0,0,0,0,0,0,0,0,0,0,0ééééééé ®  *ˆ&.RADIOC.SI*RAD†EQU‡\RADDRVLRAD$01 SET \LRAD$01**ˆSETUPRADCCB'S4*ƒ(MEMORYLENGTHIS511SINCEWESTARTATODDADDR.)*C CDB XOPEXC,'RA01',$80,254,RAD,0,LRAD$01,511,\IOCVEC3,\IOCLVL3,$50,&0,0,0,0,0,0,0,0,0,0,0 C CDB XOPEXC,'RN A41',$80,254,RAD,0,LRAD$01,511,\IOCVEC4,\IOCLVL4,$50,&0,0,0,0,0,0,0,0,0,0,0éééééé · K1IOCFAIL ASREL' IOCFAIL SA3(…Board Fail Montior Task 4-28-822 žF30042882 1RA41RA42OúÿþCúÿÜ IB™B™ü ü "ü Eú6"ÊBQpNAF3f>EúÿªJ’g"HüB2ü"Ú2ü B™B™p4 Ap(ÀüF3 Kèÿ"›ÀJ-sf|aþ2Lß,|Ns"m"Jj,J-sf PíqJ)`Hç~0B-s mv$I3 |aþ0Lß ~<Nu4éé É,1A2DLIB ASREL' M600LIB SA'(…e2IBLDCB ®IA2DCLS XIA2DOPN IA2DMRD ¬IA2DMRS VIA2DSTP  )" 3H3 //MúA ú0<`B6R@ @oô¼ o-P o-H1| o=Pp,, (-"¸´pg XGSfô0<ýF3 NurB‚½ñfa3¼ÿÿ\R‚ ‚fæB€`ø m"01¼¼Nu/ >+F3 c c &_0<÷`ÄSG\‹2 Ac &_0<ö`®4,:ÊüSB/ "Naô`F3 NqLßB0<`Š F$m""WX‰Âü½ñg Lß 0<ò`j61"_*JXg. ‚ü<F3 Ìü4Hõ¯`p$ „“É2hÿþAúJ2<p"N@`6`þ/8„0à\„0QÊÿÀQÏÿ`0&_J@F3 kg NpN@``þa4B@6€B€Nu6€NuHç?>|øÿBB AÄü4Lð¯ pÂüF3 a¢Lß|üNsHçÿþ N&( B‚4< HB‚ü4pN@``LßÿNu`øfJ…g i6p3 N@`` J…gJ0PfT—T—NuNu4ééé Û;1FTDAC ASREL' M605LIB SA((…DAC subroutinesB2ILOC ŒIDACCLS ,IDAOPEN IDACNVT >)’F3 Hç€paP$¼B€0*ã€\€2€ KpJ+g&/ ?? k áJ„‚F3 (j8N”`Nq>2&_Nu k (j