IMD 1.17: 11/11/2014 14:59:18 82VKXBVERDOS C* VERSADOS/RMS68K OBJECT 4.4 SN=48634 17 OF 22  BT17\82VKXBVERDOS 0420¿;-*ŠCALL�INCLOS(input_id,param_blk_addr)…close�selected�channels-*ŠCALL�INSTAT(input_id,param_blk_addr)…status8*ŠCALL�INENAB(input_id,param_blk_addr)…enable�interrupts9*ŠCALL�INDSAB(input_id,param_blk_addr)…disable�interrupts*D*‰and�where�input_id�is�the�CMR�channel�mnemonic�of�a�VME�610�or�620*”boardA*‰and�where�param_blk_addr�is�the�base�address�of�an�Input�Driver*“Command�Parameter�Block*,*‰All�arguments�for�the�calls�are�identical.7*‰The�contents�of�the�param_blk�for�each�call�is�unique*‰to�the�call.*6*‰All�the�command�subroutines�call�a�common�subroutine3*‰INPSET�to�build�the�Initiate�I/O�parameter�block.**‰STACK�FOR�ALL�CALLS:*7*‰deepest�stack:�(stack�address�stays�at�INPSET�return)0*˜command�codeƒ2�bytes�(initiate�I/O�param.�blk) *˜n/aŒ2�bytes*˜input_id‡4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes.*˜command�addrƒ4�bytes�(input�command�address),*˜command�lng„2�bytes�(input�command�length)-*˜INPSET�return‚4�bytes�deepest�stack�address *˜A3�4�bytes *˜A2�4�bytes *˜A1�4�bytes *˜D0�4�bytes*‰entry�stack:ƒreturn‰4�bytes*˜^param_blk_adr�4�bytes*˜^input-idˆ4�bytes* ŠSECTION�9?ŠXDEFƒINOPEN,INCLOS,INSTATƒThe�FORTRAN�subroutine�calls�use�the5ŠXDEFƒINENAB,INDSAB‰the�same�command�mnemonics�as�the(*¦corresponding�assembly�language�calls.&*‰CALL�INOPEN(input_id,param_blk_addr)*‰open�and�configure�channels*1INOPEN„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚INPSET�set-up�the�initiate�I/O�parameter�block)ŠMOVE.L�#1,(A2)Œset�the�open�command�codeINOPN00ƒCLR.L‚D0‘clear�for�use'ŠMOVE.W�4(A2),D0‹get�number�of�channelsŠASL.L‚#2,D0Žmultiply�by�4.INOPN05ƒADD.L‚#6,D0Žadd�in�the�6�byte�overhead-INOPN10ƒMOVE.W�D0,(A1)Œset�the�command�length=(80 -ŠMOVE.L�A3,A0ŽTRAP�#1�parameter�block�address#ŠMOVE.L�#60,D0�CMR�directive�numberŠTRAPƒ#1‘call�RMS68K'ŠMOVE.W�D0,(A2)Œset�the�returned�status)ŠMOVEM.L�(A7)+,D0/A1-A3„restore�registers!ŠMOVE.L�(A7)+,A0‹put�return�in�A0 ŠLEA„8(A7),A7‹clean�up�the�stackŠJMP„(A0)�return�to�user*&*‰CALL�INCLOS(input_id,param_blk_addr)"*‰close�all�channels�for�this�user*1INCLOS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚INPSET�set-up�the�initiate�I/O�parameter�block*ŠMOVE.L�#2,(A2)Œset�the�close�command�code/INCLS10ƒMOVE.W�#6,D0ŽInput�close�command�lengthŠBRA„INOPN10Œgo�do�the�CMR�call*&*‰CALL�INSTAT(input_id,param_blk_addr))*‰read�input�status�on�specified�channels*1INSTAT„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚INPSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#5,(A2)Œset�the�status�command�code4ŠBRA„INCLS10Œgo�set�command�length�&�do�the�CMR�call*&*‰CALL�INENAB(input_id,param_blk_addr).*‰enable�interrpts�on�specified�input�channels*1INENAB„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚INPSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#6,(A2)Œset�the�enable�command�code4ŠBRA„INCLS10Œgo�set�command�length�&�do�the�CMR�call*&*‰CALL�INDSAB(input_id,param_blk_addr)0*‰disable�interrupts�on�specified�input�channels*1INDSAB„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚INPSET�set-up�the�initiate�I/O�parameter�block,ŠMOVE.L�#7,(A2)Œset�the�disable�command�code4ŠBRA„INCLS10Œgo�set�command�length�&�do�the�CMR�call*4*‰INPSET�set�up�the�CMR�initiate�I/O�parameter�block.*‰returns:ƒA1=address�for�Input�command�length**”A2=Input�command�parameter�block�address)*”A3=Initiate�I/O�parameter�block�address*(INPSET„CLR.W‚-2(A7)�clear�command�length-ŠLEA„-2(A7),A1Šsave�address�of�command�length$ŠMOVE.L�24(A7),A0Šget�param_blk_addr%ŠMOVE.L�A0,-6(A7)Šsave�param_blk_addr,ŠMOVE.L�A0,A2Žsave�param_blk_addr�for�returnŠCLR.L‚-10(A7)Œnot�usedŠCLR.L‚-14(A7)Œnot�usedŠCLR.L‚-18(A7)Œnot�usedŠMOVE.L�28(A7),A0Šget�^input_id!ŠMOVE.L�(A0),-22(A7)‡get�input_idŠCLR.W‚-24(A7)Œnot�used0ŠMOVE.W�#$0700,-26(A7)…initiate�I/O�command�code4ŠLEA„-26(A7),A3‰initiate�I/O�parameter�block�addressŠRTS—return�to�callerŠENDééééééé *!*…MVME�615�AC�OUTPUT�BOARD�DRIVER *…copyrighted�1983�MOTOROLA�INC. *œTOM�KRYKA* ‰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‡MVME615�DRIVER‰PAGEM615DRV‚IDNT†1,0‡ACO�DRIVERJ****************************************************************************ƒDR615�--�REV.�1.00�8/2/83*+*ƒPurpose:‚MVME�615�AC�OUTPUT�BOARD�HANDLER*/*ƒEntry:‚JSR�FROM�CMR�HANDLER�(COMMAND�SERVICE) *‹JSR�FROM�CMR�INTERRUPT�HANDLER-*ƒExit:�-�ALWAYS�EXITS�WITH�A�RTS�INSTRUCTION**ƒCODE�IS�RE-ENTRANT********************************* CHANNEL CONTROL BLOCK (CCB) *********************************B*ƒContains�channel�device�dependent�description�and�data�areas�for*ƒI/O�handler.*‰OFFSETƒCCBDDP*H* I/O HANDLER DATA AREA *************************************************CCBFLGƒDS.B†2‰Flags(CCBERAD1�DS.B†4‰Error�debug�save�address2CCBQVER1�DS.B†4‰Event�queueing�error�debug�address7CCBCCBƒDS.B†4‰Physical�address�of�command�packet�(IOCB)CCBTASKB�DS.B†4‰Buffer�task�TCB-CCBPKTƒDS.B†18ˆEvent�work�area�(command�tour)0CCBCPKT‚DS.B†18ˆEvent�work�area�(interrupt�tour)(CCBPTRƒDS.B†4‰Physical�address�of�bufferCCBLENƒDS.B†4‰Length�of�buffer0CCBPTR1‚DS.B†4‰Physical�address�of�2ndary�buffer&CCBLEN1‚DS.B†4‰Length�of�2ndary�buffer*CCBCIDƒDS.B†4‰CMR�parameter�block�id�(DCB)CCBCOPT‚DS.B†2‰IOCB�options#CCBCFIG‚DS.B†$26‡Configuration�data**‰56�bytes�remain*9*‰CCBFLG�DEFINITIONS:�if‚CCBFLG.B�if�not�0�the�ACO�module$*�for�the�CCB�cannot�be�used�for�the*�following�reasons:*9*‰CCBFLG.B�=�$FA�=�CCB�allocation�exceeded�#�of�specified/*šdevices�-�no�room�in�ACO�table�for�the�module!*’=�$FC�=�no�ACOTBL�was�allocated/*’=�$F5�=�no�room�in�ACOTBL�for�this�ACO�module*™(incorrect�table�allocation)*‰PAGE 8MA<I0Q?Y8a4i<qGy>�9‰4‘;™7¡1©B±8¹CÁHÉ8Ñ ‰SECTIONƒ8 ‰XREF†ACOTBLH*************************************************************************ƒACO�SERVICE�VECTOR�TABLEH************************************************************************#*ˆDC.L†ACOINTŽinterrupt�svc�address!*ˆDC.L†ACOCMDŽcommand�svc�address)*ˆDC.L†ACOINIT�initialization�svc�address*7*…Below�are�the�offset�form�of�service�pointers�for�CMR*.ACODVRƒDC.L†ACOINT-ACODVR‡interrupt�svc�offset*‰DC.L†ACOCMD-ACODVR‡command�service�offset.‰DC.L†ACOINIT-ACODVR†initialization�svc�offset‰DC.L†0“Reserved‰DC.B†0“number�of�extra�pages‰DC.B†0,0,0�reserved‰DC.L†0,0,0�reserved*3*ƒ---ƒ---…CONFIGURATION�CONTROL�INFORMATION…---ƒ---*$‰DC.B†'080283'‚date�of�last�assembly'‰DC.B†'�'‡space�means�no�patches�in�.LO#‰DC.B†'4'‡major�Versados�revision�#*I**************************************************************************ƒCOMMAND�TABLE�&�JUMP�TABLE:*‰These�are�used�by�the�command�service�routine�to�jump�to.*‰the�appropriate�routine�to�handle�a�command.I************************************************************************** CMDTBLƒDC.W†ACOPEN„OPEN�command.‰DC.W†ACOCLS„CLOSE�command.‰DC.W†ACOUT…OUTPUT�ON�command. ‰DC.W†ACOOFF„OUTPUT�OFF�command.‰DC.W†ACOSTA„STATUS�command.‰DC.W†X1ˆ(not�used)‰DC.W†X2ˆ(not�used)#‰DC.W†ACOPLS„PULSED�OUTPUT�command.=NUMCMDS‚EQU‡(*-CMDTBL)/2‚The�number�of�commands�in�the�table.*8JMPTBLƒDC.W†OPEN-*„Biases�to�the�corresponding�routines. ‰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‡Offset�between�the�two�tables.*‰PAGEH*************************************************************************+*ƒACO�DRIVER�INITIALIZATION�SERVICE�ROUTINE*>*ˆThe�driver�is� entered�here�for�each�CCB�allocated.‚More�than:*ˆone�CCB�may�be�allocated�for�each�ACO�module.‚One�CCB�is%*ˆallocated�for�each�interrupt�level.?*ˆThis�routine�checks�to�see�if�there�is�room�in�the�ACOTBL�for=*ˆthe�device�ID.‚It�saves�the�device�ID�and�the�memory�mapped**ˆI/O�address�of�the�device�in�the�ACOTBL.*:*ˆAn�error�code�is�saved�in�the�CCB�if�this�CCB�allocation=*ˆexceeds�the�maximum�number�of�CCB's�specified�during�SYSGEN9*ˆ(SYSGEN�parameter�NACO),�if�no�ACOTBL�exists�or�no�room*ˆin�the�table�for�this�module.*$*ˆEntry:‚all�registers�are�available*�A5�=�CCB�address,*ˆsingle�exit�&�pointer�(A0-A6)�preservationI**************************************************************************ACOINIT‚PUSHPOINT•save�pointers3‰MOVE.L„CCBCHB(A5),A0‡get�memory�mapped�I/O�address$‰MOVE.L„ACOTBL,A1‹get�ACOTBL�address‰CMP.L…#0,A1�is�there�one?&‰BNE.S…ACOINIT1Œbranch�if�have�a�table8‰MOVE.B„#ACONTBL,CCBFLG(A5)�set�no�table�error�condition!‰BRA.S…ACOINEX1Œgoto�error�returnACOINIT5�TST.L…(A1,D3)�look�for�an�entry�slot�to�save�this�guy5‰BMI.S…ACOINIT6Œbranch�if�this�slot�is�empty�-�use�it.‰ADD.W…#IOLNG,D3‹not�empty,�bump�to�next�entry"‰SUB.B…#1,D4�decrement�the�counter(‰BNE.S…ACOINIT5Œbranch�if�more�to�search4‰BRA‡ACOEXTERŒerror�if�got�here-�no�room�for�the�map>ACOINIT6�MOVE.L„D2,(A1,D3)Šsave�this�memory�mapped�I/O�address‰MOVE.L„#0,D0�write�0�to�reg‰MOVE.B„D0,IOADR(A0)1ACOEXIT1�CLR.B…CCBFLG(A5)Šset�for�good�allocation3‰MOVE.L„CCBCHB(A5),A1‡get�memory�mapped�I/O�address&ACOINEX1�POP_POINT•recall�all�pointers‰RTS*‰PAGEG************************************************************************$*ƒACO�DRIVER�COMMAND�SERVICE�ROUTINE*6*‹PARAMETER�ADDRESS�AND�BOUNDARY�CHECKS�HAVE�BEEN�MADE**ƒEntry:‚JSR�FROM�CMR�HANDLER.*‹A2�-�PHYSICAL�ADDRESS�OF�CMR�PARAMETER�BLOCK*‹A5�-�PHYSICAL�ADDRESS�OF�CCB*5*ƒExit:‚RTS�-�PARAMETER�BLOCK�VALIDATION�STATUS�IN�D0**ƒREGISTERS�USED:ƒ01234567 *”D******** *”A**P**PP*"*”A3�=�ACO�PARAMETER�BLOCK�ADDRESS*”A6�=�REQUESTOR�TCB�ADDRESS*J***************************************************************************)*ŒConvert�logical�PB�address�to�physical.*ACOCMDƒCLR.L…D57‰MOVE.L„XIOCPK(A2),D6‡Set�up�address�of�ACO�para.�block:‰MOVE.W„XIOPLN(A2),D5‡Set�up�length�of�ACO�parameter�block+‰MOVE.L„CCBTASKA(A5),A1…Set�up�TCB�pointer.&‰BSR‡IOHADRCKŒCall�conversion�routine.‰BRA.S…CMD010ŽGood�return.‰NOP›Bad�length�return. ‰CLR.L…D0;‰MOVE.W„#RTCDPBLK,D0ˆSet�up�invalid�parameter�block�address‰BRA.S…ACOCEX1�goto�error�exit*!*�see�if�passed�the�initialize�ok*7CMD010ƒMOVE.L„D6,A3�Stage�phys.�addr.�of�ACO�para.�blk. ‰CLR.L…D04‰TST.B…CCBFLG(A5)Šerror�code�set�in�CCB�duri ng�INIT?/‰BEQ.S…CMD020Žbranch�if�no�error�code,�continue$‰MOVE.B„CCBFLG(A5),D0‡set�error�code‰BRA.S…ACOCEX2�goto�error�exit*,*Œget�ACOTBL�address�into�A4�for�command�use* CMD020ƒEQU‡* ‰MOVE.L„ACOTBL,A4‹ACOTBL�address)‰CMP.L…#'!ACO',(A4)ˆreally�is�the�ACOTBL?,‰BEQ.S…CMD030Žbranch�if�really�is�the�ACOTBL4‰MOVE.W„#ACONTBL,D0‰set�error�return�code�-�no�table‰BRA.S…ACOCEX2�and�return**‹find�ACO-ID�in�ACOTBL*‹A1�=�entry�address*0CMD030ƒMOVE.L„XIOCID(A2),D0‡get�specified�ACO-ID(‰MOVE.B„ACONMAX(A4),D1†max�#�of�ACO-ID's$‰MOVE.L„#ACONTRY,D2‰bump�past�header"FNDACO10�CMP.L…(A4,D2),D0Ša�match?!‰BEQ.S…FNDACO20Œbranch�if�a�match&‰ADD.W…#ACOIDLNG,D2ˆbump�to�next�entry1‰SUB.L…#1,D1�decrement�number�of�entries�to�check&‰BNE.S…FNDACO10Œbranch�if�more�entries.‰MOVE.W„#ACONID,D0Šerror�-�ACO-ID�not�in�table3‰BRA.S…ACOCEX2�return�to�CMR�with�err�condition�set+FNDACO20�MOVE.L„A4,A1�bass�address�of�table‰ADD.L…D2,A1�address�of�entry*(*ŒFind�the�command�in�the�command�table.*-‰MOVEQ…#NUMCMDS-1,D0‡Set�up�the�loop�counter./‰LEA‡CMDTBL,A0‹A0�<--�address�of�command�table.+‰MOVE.W„CMDCOD(A3),D6‡get�ACO�command�code.8CMDSRCH‚CMP.W…(A0)+,D6ŒSearch�the�table�for�the�command.‰DBEQ†D0,CMDSRCH3‰BNE.S…CMDERRŽIf�we�found�the�command�in�the�table,8‰ADD.L…#JMPOFF-2,A0ˆget�the�corresponding�entry�from�the5‰MOVE.W„(A0),D0�jump�table�and�jump�to�the�routine�to"‰JMP‡(A0,D0.W)‹handle�the�command.>CMDERRƒMOVE.W„#ACOINVD,D0‰didn't�find�cmd�code�-�exit�with�errAACOCEX2‚MOVE.W„D0,CMDSTA(A3)‡write�err�code�to�users�ACO�para�blk ACOCEX1‚RTS*‰PAGEJ***************************************************************************A*„OPEN�COMMAND‚assigns�the�logical�connection�between�a�user�task9*‰and�specified�channels�within�an�ACO�module.�8�channels/*‰maximum�may�be�specified�in�one�open�command.*#*„ACO�OPEN�command‚parameter�block: *‰DS.W‚1„returned�command�status*‰DS.W‚1„command�code�(01)*‰DS.W‚1„#�of�channels�to�open*‰DS.W‚1„1st�channel�number*‰DS.W‚1„channel�configuration*Œ.*‰DS.W‚1„nth�channel�number*‰DS.W‚1„channel�configuration**„configuration�word:+*‰bit�0=1�wake-up�task�on�output�pulse�done-*Ž=0�queue�event�to�task�on�output�pulse�done2*ˆbit�15=1�use�default�configuration(ignore�bit�0)+*Ž=0�use�specified�configuration�from�bit�0B*ƒDefault�configuration:‚no�wakeup�or�queue�event�on�pulse�output.-*‰The�actual�configuation�is�saved�in�ACOTBL.%*‰The�task�TCB�address�is�also�saved.*)*‚Entry:�A1�=�address�of�ACO-ID�in�ACOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�ACO�parameter�block*‰A4�=�address�of�ACOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�CLRIOM,�SETIO,�DOIOH**************************************************************************‰see�if�channel�already�opened*$OPEN…PUSHPOINT‹save�all�address�regs‰ALLOCATE‚CHCONFIG*2‰BSR‡CLRIOM„clear�(to�$FF)�the�IO�map�for�this�ACO‰CLR.L…D7ˆchannel�counter:‰CMP.W…#ACONID,D0‚an�error�returned�from�clearing�the�map?)‰BEQ.S…OPNOID‡branch�if�an�error�returned$‰CLR.L…D2‘channel�offset�into�ACOTBL)‰CLR.L…D1‘offset�into�ACO�parameter�block1‰MOVE.W„CMDCHN(A3),D0†get�#�of�channels�specified/‰BLE.S…OPNINC�branch�if�negative�or�zero,�error0‰CMP.W…#8,D0�cannot�specify�more�than�8�channels-‰BGT.S…OPNINC�branch�if�greater�than�8,�errorEOPEN10ƒMOVE.W„NUMCHAN(A3,D1),D2‚get�channel�number�from�ACO�para.blk.!‰CMP.W…#7,D2�insure�channel�#�<�8 ‰BGT.S…OPNINV‰MOVE.W„D2,D5Žsave�it0‰MULU†#CHANLNG,D2ˆget�channel�offset�into�ACOTBL‰ADD.L…#4,D2Žbump�past�ACO-ID+‰TST.W…(A1,D2)Œthis�channel�already�opened?-‰BPL.S…OPNOPN�branch�if�already�opened,�error‰ADD.L…#1,D7Žcount�this�channel>‰MOVE.W„CHNCNFG(A3,D1),D3‚get�configuration�from�ACO�para.blk.-‰STORE…D3,CHCONFIG†save�channel�configuration*0*Œsave�TCB�address�and�configuration�information*.‰LOAD†D3,CHCONFIG‰recall�channel�configuration)‰BSR‡SETIO�go�set�IO�map�for�this�channel5‰CMP.W…#ACONID,D0Šan�error�fou nd�during�the�save�map?*‰BEQ.S…OPNERRŽbranch�if�an�error�was�found6‰MOVE.W„D3,ACOCNIF(A1,D2)ƒsave�configuration�in�ACOTBL)‰MOVE.L„A6,ACOTCB(A1,D2)„save�TCB�address4‰ADD.W…#OPNTRY,D1Šbump�to�next�ACO�param.�blk.�entry3‰SUB.W…#1,D0�decrement�number�of�channels�specified)‰BGT‡OPEN10Žbranch�if�more�channels�to�do*‰BSR‡DOIO�go�set�the�IO�hardware�registers!‰CMP.W…#ACONID,D0Šan�error�found?2‰BEQ.S…OPNERRŽbra�if�an�err�was�found�-�don't�open‰CLR.L…D0’set�for�good�return‰BRA.S…OPNXITŽgo�return�to�CMR**Œopen�errors�here*5OPNINVƒMOVE.W„#ACOICNS,D0‰set�invalid�channel�#�error ‰BRA.S…OPNXIT8OPNINCƒMOVE.W„#ACOINC,D0Šset�invalid�#�of�channels�error‰BRA.S…OPNXITŽexit;OPNOIDƒMOVE.W„#ACONID,D0Šset�ACO�module�not�allocated�error‰BRA.S…OPNXITŽgo�return�to�CMR9OPNOPNƒMOVE.W„#ACOPND,D0Šset�channel�already�opened�error*)*Œreset�any�opened�channels�to�not�opened*%OPNERRƒTST.W…D7’any�channels�to�undo?3‰BEQ.S…OPNXITŽbranch�if�none�to�undo,�return�to�CMR&‰MOVE.W„#$FFFF,D3‹set�'un-opened'�code‰CLR.L…D1’clear�for�use6OPNERR10�MOVE.W„NUMCHAN(A3,D1),D2ƒget�a�channel�number$‰MULU†#CHANLNG,D2‰get�channel�offset‰ADD.L…#4,D2�bump�past�headers*‰MOVE.W„D3,(A1,D2)Šset�this�entry�unopened-‰ADD.W…#OPNTRY,D1Šbump�to�next�channel�number‰SUB.W…#1,D7�decrement�counter&‰BGT.S…OPNERR10Œbranch�if�more�to�undo*ŽFall�into�exit* OPNXITƒEQU‡*)‰ADD.L…#8,A7…DEALLOCATE�CHCONFIG�on�stack‰POP_POINT‹restore�all�pointers ‰BRA‡NRMEXIT*I**************************************************************************A*ƒCLRIOMƒClear�out�the�IO�map�for�this�memory�mapped�I/O�address.*&*‰Entry:�A1�=�ACO-ID�address�in�ACOTBL%*�A2�=�address�of�CMR�parameter�block%*�A3�=�address�of�ACO�parameter�block*�A4�=�address�of�ACOTBL*�A5�=�address�of�CCB*�A6�=�address�of�users�TCB**‰Uses:‚D4,D6,D7*%*‰Exit:‚D0�=�ACONID�if�an�error�found**�D0�=�contents�on�entry�if�no�error�found*I**************************************************************************0CLRIOMƒMOVE.W„ACOIO(A4),D7ˆget�offset�to�IO�maps.‰MOVE.B„ACONAL(A4),D6‡get�#�of�ACO'S�allocated3‰MOVE.L„CCBCHB(A5),D4‡get�memory�mapped�I/O�address?CLRIOM1‚CMP.L…IODDR(A4,D7),D4…look�for�match�mem.�map.�I/O�addr‰BEQ.S…CLRIOM2�branch�if�found#‰ADD.W…#IOLNG,D7‹bump�to�next�entry‰SUB.B…#1,D6�decrement�counter/‰BNE.S…CLRIOM1�branch�if�more�entries�to�search#‰MOVE.W„#ACONID,D0Šset�error�return‰RTS›return�to�caller)CLRIOM2‚CLR.B…DODR07(A4,D7)‡clear�the�map‰RTS›return�to�caller*‰PAGEI**************************************************************************<*ƒSETIO…Build�the�IO�map�entries�for�the�specified�channels.*�Builds�1�entry�per�call*�Map�is�in�ACOTBL.**‰Entry:�A4ƒ=�ACOTBL�address*�D3.W�=�channel�configuration*�D5.B�=�channel�number*7*‰Exit:‚D0.W�=�ACONID�if�map�entry�not�found,�otherwise*—D0�unchanged *‰Uses:�D4,D6*‰Entry�point�=�SETIO*‰Exit�point‚=�SETIORT**ˆPrivate�subroutine�for�OPEN*$* Single exit & pointer preservation*I***************************************************************************‰find�map�entry* SETIO„EQU‡*‰PUSHPOINT‘save�all�pointers‰MOVE.L„D7,-(A7)‹save�D73‰MOVE.W„ACOIO(A4),D7†get�offset�to�start�of�IO�maps.‰MOVE.B„ACONAL(A4),D6†get�#�of�ACO'S�allocated3‰MOVE.L„CCBCHB(A5),D4†get�memory�mapped�I/O�address;SETIOFD‚CMP.L…IODDR(A4,D7),D4ƒfind�the�matching�I/O�address‰BEQ.S…SETIO00‹branch�if�found#‰ADD.W…#IOLNG,D7‰bump�to�next�entry‰SUB.B…#1,D6Ždecrement�counter/‰BNE.S…SETIOFD‹branch�if�more�entries�to�search8‰MOVE.W„#ACONID,D0†set�fatal�err�-�this�shouldn't�happen‰BRA.S…SETIORT‰return�to�caller**Œdetermine�channel�number*SETIO00‚CLR.L…D6‘clear�for�use/‰MOVE.B„D5,D6Žcopy�channel�number�to�work�space**ŒCHANNEL�0-7�as�output�channel*0‰BSET†D5,DODR07(A4,D7)ƒset�data�image�for�output"SETIORT‚MOVE.L„(A7)+,D7‹restore�D7‰POP_POINT‘restore�all�pointers‰RTS—return�to�caller*‰PAGED************************************** *******************************;*ƒDOIO†Copy�the�data�information�from�the�IO�register�image"*�(in�the�map)�to�the�IO�register.**ˆENTRY�PARAMETERS:*�A4�=�address�of�ACOTBL*�A5�=�address�of�CCB*)*‰Exit:‚D0.W�=�ACONID�if�IO�map�not�found*�D0.W�=�0�if�no�errors�found**‰Uses:�A0,D1,D6,D7*#* Single exit, pointer preservation*D********************************************************************* DOIO…EQU‡*‰PUSHPOINT’save�all�pointers!‰MOVE.L„D7,-(A7)‹save�register�D7*‰MOVE.W„ACOIO(A4),D7†get�offset�to�IO�maps$‰MOVE.B„ACONAL(A4),D6†get�#�of�ACO'S3‰MOVE.L„CCBCHB(A5),D1†get�memory�mapped�I/O�address*‰This�command�deactivates�outputs�for�specified�channels�that9*‰have�previously�been�opened�for�output�by�the�same�task<*‰requesting�this�activation.‚The�parameter�block�is�checked<*‰for�errors�before�any�output�is�deactivated.‚No�channel�is#*‰deactivated�if�an�error�is�found.*)*‰ACO�OUTPUT�OFF�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�044*‰DS.Wƒ1ƒbit�mask�containing�channel�#'s�to�activate*)*‚Entry:�A1�=�address�of�ACO-ID�in�ACOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�ACO�parameter�block*‰A4�=�address�of�ACOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�DOOFF*%* Single exit with pointers preserved*H*************************************************************************"OUTOFFƒPUSHPOINT‘save�all�pointers0‰CLR.L‚D3‘flag�-�ck�para.blk .�before�stop�output'‰MOVE.L�#4,D1Žbump�past�ACO-ID�in�table!‰CLR.L‚D2‘use�for�channel�counter‰CLR.L‚D0‘clear�for�use+‰MOVE.W�CMDCHN(A3),D0†get�channels�to�start0‰MOVE.WƒD0,D3Œcopy�chan.�to�turn�off�to�work�reg+OUTOF20‚BTSTƒD2,D0Ždeactivate�this�channel?0‰BEQ.S‚OUTOF30Œbranch�if�no�-�check�next�channel5‰CMP.L‚ACOTCB(A1,D1),A6ƒchannel�belongs�to�this�user? ‰BNE„OUTONERŒbranch�if�no,�error.‰BCLR…D2,D3Œnegate�check�flag�for�this�channel$‰TST„D3‘is�all�of�parameter�checked?(‰BNE.S‚OUTOF30Œbranch�if�not�all�checked2‰BSR.S‚DOOFFŽgood�para.�block�-�deactivate�channel‰BRA.S„OUTOFFXŠnormal�exit/OUTOF30‚ADD.L‚#1,D2Žbump�to�next�channel�number-‰ADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry&‰CMP.L‚#8,D2�checked�all�the�channels?/‰BNE.S‚OUTOF20Œbranch�if�more�channels�to�check ‰BRA†OUTONEROUTOFFX‚EQU‡*‰normal�exit‰POP_POINT‹recall�all�pointers‰CLR.L„D0‰signal�no�errors‰BRA.S…NRMEXITƒnormal�exit*‰PAGEI**************************************************************************"*‚STAT�-�GET�OUTPUT�STATUS�COMMANDA*†This�command�reads�the�status�of�specified�output�channels.�The>*†channels�must�have�previously�been�opened�for�output�by�thisC*†user.�The�parameter�block�is�checked�for�errors�before�any�outputA*†status�is�read.�The�users�parameter�block�is�modified�to�signalB*†active�channels�by�setting�the�corresponding�bit�in�the�bit-maskE*†word.�The�corresponding�bit�number�of�inactive�channels�is�cleared.* *†All�channels�are�read�at�once.*,*„ACO�OUTPUT�STATUS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�05<*‰DS.Wƒ1ƒbit�mask�containing�channels�numbers�to�read�status$*”(�this�is�also�the�returned�field)*)*‚Entry:�A1�=�address�of�ACO-ID�in�ACOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�ACO�parameter�block*‰A4�=�address�of�ACOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�GTSTAT*I************************************************************************** STAT†PUSHPOINT‘save�all�pointers(ŠCLR.L‚D5‘use�for�returned�status�values/ŠCLR.L‚D3‘flag�-�ck�para.blk.before�read�status(ŠMOVE.L�#4,D1Žbump�past�ACO-ID�in�ACOTBLŠCLR.L‚D2‘channel�counterŠCLR.L‚D0‘clear�for�use;ŠMOVE.W�CMDCHN(A3),D0†get�channel�numbers�to�read�status�on3ŠMOVE.W�D0,D3Žcopy�chan�activation�req.�bit�pattern$ŠAND„#$00FF,D0Šmask�all�but�low�byte/STAT20„BTSTƒD2,D0Žread�status�for�this�channel?ŠBEQ.S‚STAT40�branch�if�no5ŠCMP.L‚ACOTCB(A1,D1),A6ƒchannel�belongs�to�this�user?1ŠBNE„OUTONERŒbranch�if�no�-�return�with�error�set0ŠBCLRƒD2,D3Žclr�activation�flag�for�this�channel*ŠTST„D3‘finished�checking�parameter�block?1ŠBNE.S‚STAT40�branch�if�not�finished�checking�yet0ŠBSR.S‚GTSTAT�go�read�status�and�save�in�REG.�D5!ŠBRA.S‚STAT50�goto�procedure�exit3STAT40„ADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry(ŠADD.L‚#1,D2Žbump�to�next�channel�number,ŠBRA„STAT20�branch�to�channel�check�sequence6STAT50„MOVE.W�D5,CMDCHN(A3)†set�returned�status�values&ŠBRA„OUTONEXŒand�return�with�no�errors*‰PAGEI*************************************************************************<*‚ENABLE�-�ENABLE�INTERRUPTS�COMMAND�---�NOT�USED�THIS�BOARD3*‰IF�CALLED,�EXITS�WITH�INVALID�COMMAND�ERROR�CODE.*0*„ACO�ENABLE�INTERRUPTS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�066*‰DS.Wƒ1ƒbit�mask�of�channels�to�enable�for�interrupts)*‚Entry:�A1�=�address�of�ACO-ID�in�ACOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�ACO�parameter�block*‰A4�=�address�of�ACOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCBI**************************************************************************5ENABLER‚MOVE.W„#ACOINVD,D0‡set�code�'invalid�command'(‰BRA.S…NRMEXITŒand�return�with�error�set**I*************************************************************************=*‚DSABLE�-�DISABLE�INTERRUPTS�COMMAND�---�NOT�USED�THIS�BOARD-*‰IF�CALLED,�EXITS�WITH�INVALID�COMMAND�CODE.*1*„ACO�DISABLE�INTERRUPTS �command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�077*‰DS.Wƒ1ƒbit�mask�of�channels�to�disable�for�interrupts)*‚Entry:�A1�=�address�of�ACO-ID�in�ACOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�ACO�parameter�block*‰A4�=�address�of�ACOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCBH*************************************************************************DSABLEƒBRA.S…ENABLER**H************************************************************************* *ƒNORMAL�EXIT,*ˆEntry:�A2�=�address�of�CMR�parameter�block%*�A3�=�address�of�ACO�parameter�block*�A5�=�address�of�CCB*�A6�=�address�of�users�TCB*�D0�=�ACO�error�code*I**************************************************************************ANRMEXITƒMOVE.W�D0,CMDSTA(A3)†set�return�status�in�ACO�para.�blockŠRTS—return�to�CMR*‰PAGEH**************************************************************************ƒPLSO�-�PULSED�OUTPUT�COMMAND*)*‚Entry:�A1�=�address�of�ACO-ID�in�ACOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�ACO�parameter�block*‰A4�=�address�of�ACOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*‚Exits�to�NRMEXIT*+*‚Parameter�block�format�for�pulsed�output:1*‚ACO�parameter�block�(pointed�to�by�A3�on�entry)* *ˆDS.W†1‰returned�command�status*ˆDS.W†1‰command�code*ˆDS.W†1‰number�of�channels<*�---ƒ---ƒ---ƒparameters�for�individual�channelsƒ---ƒ---ƒ---*ˆDS.W†1‰first�channel�number,*ˆDS.L†1‰number�of�milliseconds�for�pulse�on*ˆ.*ˆ.*ˆDS.W†1‰nth�channel�number2*ˆDS.L†1‰number�of�milliseconds�for�nth�chan�pulse*7* EACH CHANNEL IS ACTIVATED IN TURN (NON-SYNCHRONOUSLY)H*************************************************************************@*„Pulsed_Out(IN-LIST�OF�channel�activation�request,�pulse�times;*�OUT-error�code)?PLSO…ALLOCATE�CHANID,ACOPARBK†allocate�chan.id�&�ACO�para�block3‰STORE…A3,ACOPARBK‰save�ACO�parameter�block�address ‰CLR.L…D6’Initiate�pulsed�output ‰CLR.L…D3 ‰CLR.L…D2 ‰CLR.L…D0$*—get�number�of�channels�to�activate9‰MOVE.W„CMDCHN(A3),D0‡get�no.�of�chan's�from�ACO�para�blk)PLSO1„TST.W…D0’loop�on�#�of�chan.'s�to�do ‰BEQ.S…PLSOX‰CLR.L…D5’get�channel�number‰MOVE.W„NUMCHAN(A3,D6),D5-‰STORE…D5,CHANID‹save�channel�number�on�stackC*„Channel�ID�consists�of�user�CCB�address�+�chan�number�in�LS�byte.+‰MOVE.L„A5,D7�copy�user's�CCB�address�to�D75‰ADD.L…D7,CHANID(A7)‡CHANID�now�has�complete�chan.�ID"‰MOVE.L„D5,D7�copy�channel�#�to�D7,‰BSR‡BIN_BIT�convert�binary�to�bit�map�in�D56‰MULU†#CHANLNG,D7‰compute�offset�to�nth�chan�in�ACOTBL%‰ADD‡#4,D7�bump�to�user�TCB�in�ACOTBL-‰CMP.L…ACOTCB(A1,D7),A6„compare�TCB�addresses1‰BNE.S…PLSOER1�branch�on�channel�not�current�user2*„Get�pulse�time�from�ACO�commmand�parameter�block‰MOVE.L„CHNCNFG(A3,D6),D3%*„IF�pulse�time�>�pulse_min_time�THEN'‰BEQ.S…PLSOER3ƒbranch�on�pulse�time�=�0(‰ADD.W…#6,D6…increment�to�next�channel�#-*„request�periodic�activation(this�channel�#)2‰LEA‡PLSOFF(PC),A0‡point�to�pulse�turn�off�routine%‰CLR.L…D1’set�request�for�1�time�only6‰MOVE.B„CCBPPRIO(A5),D1…set�act.�priority�same�as�task/‰LOAD†D2,CHANID‹setup�channel�ID�to�goto�PLSOFF‰PUSHALL'‰MOVE.L„D3,A1�setup�activation�interval$‰TR0$.RQPA�,“pass�request�for�wakeup)*ŒIf�no�err�in�periodic�act.�request�THEN‰BRA.S…RQPAOKŽgood�return(‰BRA.S…PLSOER4�err�in�periodic�act.�req."*›activate_this_channel(channel�#)*RQPAOKƒMOVE.L„D5,D0�pass�bit�mask�to�DOOUT ‰BSR‡DOOUT‰POPALL"‰SUB‡#1,D0�decrement�channel�count ‰BRA‡PLSO1**ŒError�handling)PLSOER1‚CLR.L…D0’Channel�not�current�user‰MOVE.W„#ACOICNS,D0 ‰BRA.S…PLSOX1)PLSOER3‚CLR.L…D0’Requested�pulse�time�=�03‰MOVE.W„#ACOCNFG,D0‰return�'bad�configuration'�code ‰BRA.S…PLSOX1PLSOER4‚POPALL#‰CLR.L…D0’Periodic�activation�error,‰MOVE.W„#ACOBSY,D0‹return�'device�busy'�code ‰BRA.S…PLSOX1*ŒPulsed�output�good�exit�point6PLSOX„LOAD†A3,ACOPARBK‚restore�ACO�para�blk�addr�to�A3‰CLR.L…D0ˆset�for�normal�return4PL SOX1ƒADD.L…#12,A7„DEALLOC‚CHANID,ACOPARBK�on�stack*‰BRA‡NRMEXITƒgoto�normal�common�exit�point*‰PAGE*<*‚PULSED�OUTPUT�DEACTIVATION‚Entered�by�periodic�activation. *„On�entry:?*‡D1�contains�channel�ID�composed�of�user's�CCB�address�in�M.S.7*Š3�bytes,�and�channel�number�(0-7)�in�least�sig.�byte.*PLSOFFƒPUSHALL&‰MOVE.B„D1,D5�save�combined�channel�ID ‰AND.B…#0,D1�recover�CCB�address+‰MOVE.L„D1,A5�stage�CCB�address�for�'DOOFF'+‰AND.L…#$000000FF,D5‡recover�channel�number‰MOVE.L„D5,D4�save�binary�value‰MOVE.L„#$0C010000,D2 ‰MOVE.B„D5,D2.‰BSR.S…BIN_BIT�convert�chan�#�to�bit�map�in�D5"‰MOVE.L„D5,D0�stage�data�for�DOOFF‰BSR‡DOOFF�turn�off�channel0‰MULU†#6,D4�point�to�data�field�assoc.with�chan.5‰ADD‡#ACONTRY,D4‰add�offset�to�1st�channel�data�field‰ADD‡#4,D4�add�in�size�of�ACOID+‰MOVE.L„ACOTBL,A2‹get�addr.�of�ACOTBL�to�A2,‰MOVE.L„CCBTASKA(A5),A6…A6�=�users�TCB�addr. ‰CLR.L…D72‰MOVE.B„ACONMAX(A2),D7†get�max�#�of�ACO-ID's�to�D7#‰MOVE.L„CCBMNEM(A5),D6†get�CCB�name!PLS001ƒEQU‡*“find�matching�ACO-ID!‰MOVE.L„ACOID(A2),D3ˆACO-ID�to�D3(‰CMP.L…D3,D6�does�CCB�name�match�ACO-ID?‰BEQ.S…PLS002Žbranch�on�match*‰ADDA.W„#ACOIDLNG,A2ˆadd�offset�to�next�ID"‰SUB.B…#1,D7�end�of�possible�ID's?$‰BMI.S…PLS003Žbranch�on�ID�not�found‰BRA‡PLS001Žcheck�next�ID PLS002ƒEQU‡*-‰MOVE.W„ACOCNIF(A2,D4),D0ƒconfiguration�to�D0(‰BSR.S…NOTFYUSRŒsee�if�wakeup�or�quevent PLS003ƒEQU‡*‰POPALL‰RTE*‰PAGEF**********************************************************************$*‚BINARY�to�BIT-map�conversion�in�D5@*…Produces�a�1�in�D5�bit�corresponding�to�the�binary�value�in�D5*…(up�to�bit�15).A*…For�input�>�15�binary,�the�resultant�pattern�in�D5�is�undefined*BIN_BIT‚ALLOCATE‚BITMAP‰CLR.L…BITMAP(A7)‰ADD.W…#1,BITMAP(A7) LOOP…EQU‡* ‰TST.W…D5 ‰BEQ.S…BINBITX�exit�on�bit�found‰ROL.W…BITMAP(A7) ‰SUB‡#1,D5 ‰BRA.S…LOOP* BINBITX‚EQU‡*‰MOVE.W„BITMAP(A7),D5'‰ADD.L…#8,A7�DEALLOCATE�BITMAP�on�stack‰RTS*‰PAGEA*‚NOTIFY�USERƒby�means�of�que�event�or�wakeup�as�specified�in�the*”channel�configuration�word.*ƒINPUT�PARAMETERS:'*�A2:�Address�of�channel�name�in�ACOTBL;*�D4:�Offset�from�channel�name�to�channel�data�field�(base) *™in�ACOTBL.*�A5:�Address�of�channel�CCB.*�A6:�User's�TCB�address#*�D2:�$0C01�*GNOTFYUSR�MOVE.WƒACOCNIF(A2,D4),D0�get�configuration�from�channel�ACOTBL#‰BTST†#15,D0‹default�configuration? ‰BNE.S…NOTIFX1‰BTST…#0,D0‰no,�determine:�wake-up=1�or�q-event=0 ‰BNE.S…NOTIFA*ŽQueue�event;�data�staging:$*ŽD2�=�$0C01� *ŽD3�=�ACOID*ŽD4�=�Mem�mapped�I/O�address*ŽA6�=�User's�TCB�address*8‰MOVE.L„CCBCHB(A5),D4ƒget�mem.�mapped�I/O�address�staged‰BSR.S…QUEVENT‰queue�the�event‰BRA.S…NOTIFXŠgo�to�exit*+NOTIFAƒMOVE.LƒA6,A0Žstage�users�TCB�address#‰TR0$.WAKEUP�,�issue�wakeup�to�userNOTIFX:‰RTS*ŠPAGE*H*‚QUEVENT�-�queue's�event�to�driving�task�using�data�staged�in�registers *‹as�follows:*‹A6�=�user's�TCB�address&*‹D2�=�$0C01�*‹D3�=�ACOID‚(module�name)&*‹D4�=�mem�mapped�I/O�address�of�board<*†(dumps�contents�of�registers�D2,�D3,�&�D4�to�users�buffer)* QUEVENT‚EQU‡*‰PUSHALL�push�all�regs"‰MOVE.L„A6,A0…stage�user's�address ‰TR0$.QEVNTI*+‰BRA.S…QUEVNTOK‚good�return�for�queue�event+‰BRA.S…QUEVNTER‚bad�return�from�queue�eventQUEVNTOK�EQU‡*‰POPALLŽrestore�all�regs‰RTS QUEVNTER:(‰BRA‡QUEVNTOK‚put�a�break�here�for�debug*‰PAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLING�TASKS�ADDRESS�SPACE.*#*�ENTRY:ƒD5‚-�NO.�OF�BYTES�TO�CHECK*ŠD6‚-�68000�ADDRESS�(LOGICAL)*ŠA1‚-�TCB�ADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1*7*�EXIT:„D6�-�PHYSICAL�ADDRESS�OF�BUFFER�BASE�(IF�LEGAL)*ŠRETURN�TO�PC„FOR�GOOD�ADDRESS*”PC+2‚FOR�BAD�LENGTH*”PC+4‚FOR�BAD�ADDRESS*F***********************************************************************-IOHADRCK‚BTSTƒ#0,D6‘Must�b e�on�word�boundary.)ŠBNE.S‚IOHADR4�Branch�if�bad�buffer�base.ŠTST.L‚D5”Length�can't�be�zero.1ŠBEQ.S‚IOHADR8�Don't�go�to�logphy�with�zero�count1ŠMOVE.L�TCBTST(A1),A0‰Address�of�task�seg.�table. ŠTR0$.LOGPHY*.ŠBRA.S‚IOHADR8�Branch�for�good�address�return.0ŠBRA.S‚IOHADR6�Branch�for�bad�byte�count�return.(ŠTST.L‚D5”Was�an�entry�pointer�returned.#ŠBEQ.S‚IOHADR4�Branch�if�no�-�ERROR)ŠTST.B‚7(A0,D5)ŽIs�this�an�MMIO�segment�?ŠBNE.S‚IOHADR8�Yes,�OK.3IOHADR4ƒADD.L‚#2,(A7)�Adjust�PC�for�invalid�return.3IOHADR6ƒADD.L‚#2,(A7)�Adjust�PC�for�invalid�return.IOHADR8ƒRTSšReturn.*ŠPAGEH*************************************************************************!* INTERRUPT SIDE FOR IOH HANDLING*?*ƒPURPOSE:‚HANDLE�ACKNOWLEDGEMENTS�AND�MESSAGE�COMPLETIONS�FROM2*ˆTHE�IOH.‚OPERATES�AT�HARDWARE�INTERRUPT�PRIORITY=*ˆLEVEL�AS�A�SUBROUTINE�TO�THE�FIRST�LEVEL�INTERRUPT�HANDLER.*+*ƒENTRY:‚JSR‚FROM�INTERRUPT�HANDLER�ROUTINE*‹A0�-�WORK�REGISTER *‹A1�=�SELF*‹A5�=�ADDRESS�OF�CCB*‹D0�=�WORK�REGISTER*/*ƒEXIT:‚RTS�-�BACK�TO�INTERRUPT�HANDLER�ROUTINE*/*ƒNOTE:ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***@*ƒThis�routine�is�called�only�by�the�common�interrupt�handler�in'*ƒRMS68K.ƒThe�common�interrupt�handler:7*ƒDOES‚NOT‚PRESERVEƒVALUES‚IN‚REGISTERS‚BEFORE‚THE‚CALL?*ƒThis�interrupt�handler�MUST�PRESERVE�all�data�&�address�regs.**ƒREGISTERS�USED:ƒ01234567 *”D******** *”A*****P***4*ƒIf�channel�is�off-line�or�not�attached,�just�exit.H*************************************************************************<*‹Find�ACO�TABLE�module�(board)�name�which�matches�CCB�name:*3ACOINTƒMOVEM.LƒA0-A6/D1-D7,-(A7)ƒsave�all�except�D01‰ALLOCATE‚ACOTADR,CHANUM†allocate�local�variables-‰MOVE.L„ACOTBL,A2‹get�address�of�ACOTBL�to�A2 ‰CLR.L…D76‰MOVE.B„ACONMAX(A2),D7†get�max�number�of�ACOID's�to�D7#‰MOVE.L„CCBMNEM(A5),D0†get�ccb�name2IOHI011‚EQU‡*‡find�matching�ACOID�loop�entry�point*‰MOVE.L„ACOID(A2),D3ˆget�ACOID�for�staging'‰CMP.L…D3,D0�does�CCB�name�match�ACOID?#‰BEQ.S…IOHI020�branch�on�name�match.‰ADDA.W„#ACOIDLNG,A2ˆadd�offset�to�next�ACOTBL#‰SUB.B…#1,D7�test�for�end�of�ACOTBL4‰BMI.S…IOHIPX„error,�exit�on�ACO-ID�not�found�in�CCB ‰BRA‡IOHI011D*„Found�matching�names,�now�get�number�of�interrupting�channel�to�D2C*„on�this�board,�use�non-existant�chan.�8�to�indicate�no�interrupt.5IOHI020‚STORE…A2,ACOTADRŠsave�ACOTBL�address�on�stack,‰MOVE.L„#$0C010008,D2‡init�para�fields�in�D2*‰STORE…D2,CHANUM‹save�chan.#�&�return�code>*„Compute�address�of�field�in�ACOTBL�having�user's�TCB�address ‰CLR.L…D4!‰MOVE.B„D2,D4�get�channel‚to�D4.B$IOHIPXƒEQU‡*“'ACOINT'�procedure�exit-‰MOVE.L„#0,D0�get�int.�claim�check(�0�=�none)*„dealocate�ACOTADR,CHANUM#‰ADD‡#12,A7Žrelease�local�variables0‰MOVEM.Lƒ(A7)+,A0-A6/D1-D7ƒrestore�all�except�D0-‰AND‡#$FFFE,SR‹signal�CMR�'int.�not�from�ACO'‰RTS**‰ENDéééé éFTACO…IDNTƒ1,0�ACO�subroutines**‰FORTRAN�callable�subroutines*‰for�ACO�driver�calls*$*‰CALL�ACOCMD(aco_id,param_blk_addr)*‰where�ACOCMD�may�be:*)*‰CALL�ACOPEN(aco_id,param_blk_addr)…open**‰CALL�ACOCLS(aco_id,param_blk_addr)…close.*‰CALL�ACOOUT(aco_id,param_blk_addr)…output�on/*‰CALL�ACOOFF(aco_id,param_blk_addr)…output�off+*‰CALL�ACOSTA(aco_id,param_blk_addr)…status2*‰CALL�ACOPLS(aco_id,param_blk_addr)„output�pulsed*,*‰All�arguments�for�the�calls�are�identical.7*‰The�contents�of�the�param_blk�for�each�call�is�unique*‰to�the�call.*6*‰All�the�command�subroutines�call�a�common�subroutine3*‰ACOSET�to�build�the�initiate�I/O�parameter�block.**‰STACK�FOR�ALL�CALLS:*7*‰deepest�stack:�(stack�address�stays�at�ACOSET�return)0*˜command�codeƒ2�bytes�(initiate�I/O�param.�blk) *˜n/aŒ2�bytes*˜aco_id‰4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes,*˜command�addrƒ4�bytes�(aco�command�address)**˜command�lng„2�bytes�(aco�command�length)-*˜ACOSET�return‚4�bytes�deepest�stack�address *˜A3�4�bytes *˜A2�4�bytes *˜A1�4�bytes *˜D0�4�bytes*‰entry�stack:ƒreturn‰4�bytes*˜^param_blk_adr�4�bytes*˜^aco-idˆ4�bytes* ŠSECTION�9!ŠXDEFƒACOPEN,ACOCLS,ACOOUT,ACOOFFŠXDEFƒACOSTA,ACOPLS*$*‰CALL�ACOPEN(aco_id,param_blk_addr)*‰open�and�configure�channels*1ACOPEN„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers3ŠBSR„ACOSET�set-up�the�initiate�I/O�parameter�block)ŠMOVE.L�#1,(A2)Œset�the�open�command�codeACOPN00ƒCLR.L‚D0‘clear�for�use'ŠMOVE.W�4(A2),D0‹get�number�of�channelsŠASL.L‚#2,D0Žmultiply�by�4.ACOPN05ƒADD.L‚#6,D0Žadd�in�the�6�byte�overhead-ACOPN10ƒMOVE.W�D0,(A1)Œset�the�command�length-ŠMOVE.L�A3,A0ŽTRAP�#1�parameter�block�address#ŠMOVE.L�#60,D0�CMR�directive�numberŠTRAPƒ#1‘call�RMS68K'ŠMOVE.W�D0,(A2)Œset�the�returned�status)ŠMOVEM.L�(A7)+,D0/A1-A3„restore�registers!ŠMOVE.L�(A7)+,A0‹put�return�in�A0 ŠLEA„8(A7),A7‹clean�up�the�stackŠJMP„(A0)�return�to�user*$*‰CALL�ACOCLS(aco_id,param_blk_addr)"*‰close�all�channels�for�this�userÙDâ8ê *1ACOCLS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚ACOSET�set-up�the�initiate�I/O�parameter�block*ŠMOVE.L�#2,(A2)Œset�the�close�command�code&ŠMOVE.W�#4,D0ŽACO�close�command�lengthŠBRA„ACOPN10Œgo�do�the�CMR�call*$*‰CALL�ACOOUT(aco_id,param_blk_addr)'*‰activate�output�on�requested�channels*1ACOOUT„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚ACOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#3,(A2)Œset�the�output�command�code*ACOUT10ƒMOVE.Wƒ#6,D0Œset�up�command�lengthŠBRA„ACOPN10Œgo�do�the�CMR�call*$*‰CALL�ACOOFF(aco_id,param_blk_addr))*‰deactivate�output�on�specified�channels*1ACOOFF„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚ACOSET�set-up�the�initiate�I/O�parameter�block/ŠMOVE.L�#4,(A2)Œset�the�output�off�command�code4ŠBRA„ACOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�ACOSTA(aco_id,param_blk_addr))*‰read�input�status�on�specified�channels*1ACOSTA„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚ACOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#5,(A2)Œset�the�status�command�code4ŠBRA„ACOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�ACOPLS(aco_id,param_blk_addr)>*‰activate�output�for�x#�of�milliseconds�on�specified�channels*1ACOPLS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚ACOSET�set-up�the�initiate�I/O�parameter�block2ŠMOVE.L�#8,(A2)Œset�the�pulsed�output�command�codeŠCLR.L‚D0‘clear�for�use,ŠMOVE.W�4(A2),D0‹get�specified�#�of�channelsŠASL.L‚#2,D0Žmultiply�by�6ŠADD.W‚4(A2),D 04ŠBRA„ACOPN05Œgo�set�command�length�&�do�the�CMR�callŠPAGE*4*‰ACOSET�set�up�the�CMR�initiate�I/O�parameter�block,*‰returns:ƒA1=address�for�ACO�command�length(*”A2=ACO�command�parameter�block�address)*”A3=initiate�I/O�parameter�block�address*(ACOSET„CLR.W‚-2(A7)�clear�command�length-ŠLEA„-2(A7),A1Šsave�address�of�command�length$ŠMOVE.L�24(A7),A0Šget�param_blk_addr%ŠMOVE.L�A0,-6(A7)Šsave�param_blk_addr,ŠMOVE.L�A0,A2Žsave�param_blk_addr�for�returnŠCLR.L‚-10(A7)Œnot�usedŠCLR.L‚-14(A7)Œnot�usedŠCLR.L‚-18(A7)Œnot�usedŠMOVE.L�28(A7),A0Šget�aco_idŠMOVE.L�(A0),-22(A7)‡get�aco_idŠCLR.W‚-24(A7)Œnot�used0ŠMOVE.W�#$0700,-26(A7)…initiate�I/O�command�code4ŠLEA„-26(A7),A3‰initiate�I/O�parameter�block�addressŠRTS—return�to�caller*ŠEND*éééééé*!*…MVME�625�DC�OUTPUT�BOARD�DRIVER *…copyrighted�1983�MOTOROLA�INC. *œTOM�KRYKA* ‰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�9995.&.M625DRV.EQ‰PAGEŠINCLUDE�9995.&.M625DRV.EQŠTTL�MVME625�DRIVER‰PAGE#M625DRV‚IDNTƒ1,0‰DCO�DRIVERƒ4/21/83J****************************************************************************ƒDR625�--�REV.�1.00�7/5/83*+*ƒPurpose:‚MVME�625�DC�OUTPUT�BOARD�HANDLER*/*ƒEntry:‚JSR�FROM�CMR�HANDLER�(COMMAND�SERVICE) *‹JSR�FROM�CMR�INTERRUPT�HANDLER-*ƒExit:�-�ALWAYS�EXITS�WITH�A�RTS�INSTRUCTION**ƒCODE�IS�RE-ENTRANT*H*-----------------------------------------------------------------------********************************* CHANNEL CONTROL BLOCK (CCB) *********************************B*ƒContains�channel�device�dependent�description�and�data�areas�for*ƒI/O�handler.*ŠOFFSET‚CCBDDP*H* I/O HANDLER DATA AREA *************************************************CCBFLG„DS.B„2ŒFlags(CCBERAD1‚DS.B„4ŒError�debug�save�address2CCBQVER1‚DS.B„4ŒEvent�queueing�error�debug�address7CCBCCB„DS.B„4ŒPhysical�address�of�command�packet�(IOCB)CCBTASKB‚DS.B„4ŒBuffer�task�TCB-CCBPKT„DS.B„18‹Event�work�area�(command�tour)0CCBCPKTƒDS.B„18‹Event�work�area�(interrupt�tour)(CCBPTR„DS.B„4ŒPhysical�address�of�bufferCCBLEN„DS.B„4ŒLength�of�buff er0CCBPTR1ƒDS.B„4ŒPhysical�address�of�2ndary�buffer&CCBLEN1ƒDS.B„4ŒLength�of�2ndary�buffer*CCBCID„DS.B„4ŒCMR�parameter�block�id�(DCB)CCBCOPTƒDS.B„2ŒIOCB�options#CCBCFIGƒDS.B„$26ŠConfiguration�data**‰56�bytes�remain*9*‰CCBFLG�DEFINITIONS:�if‚CCBFLG.B�if�not�0�the�DCO�module$*�for�the�CCB�cannot�be�used�for�the*�following�reasons:*9*‰CCBFLG.B�=�$FA�=�CCB�allocation�exceeded�#�of�specified/*šdevices�-�no�room�in�DCO�table�for�the�module!*’=�$FC�=�no�DCOTBL�was�allocated òKûG2 =99#@+D3@;<C7K<S5[=c?kAsD{Jƒ>‹&/*’=�$F5�=�no�room�in�DCOTBL�for�this�DCO�module*™(incorrect�table�allocation)*‰PAGE ‰SECTION�8 ‰XREF�DCOTBLJ****************************************************************************‚DCO�SERVICE�VECTOR�TABLE*L*****************************************************************************#*ˆDC.L†DCOINTŽinterrupt�svc�address!*ˆDC.L†DCOCMDŽcommand�svc�address)*ˆDC.L†DCOINIT�initialization�svc�address*?*Below are the new offset form of service pointers, for new CMR*DCODVR:(‰DC.L†DCOINT-DCODVR†interrupt�svc�offset*‰DC.L†DCOCMD-DCODVR†command�service�offset.‰DC.L†DCOINIT-DCODVR…initialization�svc�offset‰DC.L†0‰Reserved‰DC.B†0“number�of�extra�pages‰DC.B†0,0,0�reserved‰DC.L†0,0,0�reserved*3*ƒ---ƒ---…CONFIGURATION�CONTROL�INFORMATION…---ƒ---*$‰DC.B…'070583'ƒdate�of�last�assembly'‰DC.B†'�'‡space�means�no�patches�in�.LO#‰DC.B†'4'‡major�Versados�revision�#*‰PAGEJ****************************************************************************‰COMMAND�TABLE�&�JUMP�TABLE*:*‰These�are�used�by�the�command�service�routine�to�jump�to.*‰the�appropriate�routine�to�handle�a�command.*J***************************************************************************CMDTBL:ŠDC.WƒDCOPEN�OPEN�command.ŠDC.WƒDCOCLS�CLOSE�command.ŠDC.WƒDCOUTŽOUTPUT�ON�command. ŠDC.WƒDCOOFF�OUTPUT�OFF�command.ŠDC.WƒDCOSTA�STATUS�command.ŠDC.WƒX1‘(not�used)ŠDC.WƒX2‘(not�used)#ŠDC.WƒDCOPLS�PULSED�OUTPUT�command.=NUMCMDSƒEQU„(*-CMDTBL)/2‡The�number�of�commands�in�the�table.*9JMPTBL:ƒDC.WƒOPEN-*�Biases�to�the�corresponding�routines. Š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†Offset�between�the�two�tables.*ŠPAGEJ***************************************************************************+*ˆDCO�DRIVER�INITIALIZATION�SERVICE�ROUTINE*>*ˆThe�driver�is�entered�here�for�each�CCB�allocated.‚More�than:*ˆone�CCB�may�be�allocated�for�each�DCO�module.‚One�CCB�is%*ˆallocated�for�each�interrupt�level.?*ˆThis�routine�checks�to�see�if�there�is�room�in�the�DCOTBL�for=*ˆthe�device�ID.‚It�saves�the�device�ID�and�the�memory�mapped**ˆI/O�address�of�the�device�in�the�DCOTBL.*:*ˆAn�error�code�is�saved�in�the�CCB�if�this�CCB�allocation=*ˆexceeds�the�maximum�number�of�CCB's�specified�during�SYSGEN:*ˆ(SYSGEN�parameter�NDCO1),�if�no�DCOTBL�exists�or�no�room*ˆin�the�table�for�this�module.*$*ˆEntry:‚all�registers�are�available*�A5�=�CCB�address*I**************************************************************************,*‚single�exit�&�pointer�(A0-A6)�preservation*DCOINIT:ŠPUSHPOINT‘save�pointers3ŠMOVE.LƒCCBCHB(A5),A0„get�memory�mapped�I/O�address$ŠMOVE.L�DCOTBL,A1Šget�DCOTBL�addressŠCMP.L‚#0,A1Žis�there�one?&ŠBNE.S‚DCOINIT1‹branch�if�have�a�table8ŠMOVE.B�#DCONTBL,CCBFLG(A5)�set�no�table�error�condition!ŠBRA.S�DCOINEX1Œgoto�error�returnDCOINIT5‚TST.L‚(A1,D3)Œlook�for�an�entry�slot�to�save�this�guy5ŠBMI.S‚DCOINIT6‹branch�if�this�slot�is�empty�-�use�it.ŠADD.W‚#IOLNG,D3‰not�empty,�bump�to�next�entry"ŠSUB.B‚#1,D4Ždecrement�the�counter(ŠBNE.S‚DCOINIT5‹branch�if�more�to�search4ŠBRA„DCOEXTER‹error�if�got�here-�no�room�for�the�map>DCOINIT6‚MOVE.L�D2,(A1,D3)‰save�this�memory�mapped�I/O�addressŠMOVE.L‚#0,D0�write�0�to�regŠMOVE.B‚D0,IOADR(A0)1DCOEXIT1‚CLR.B‚CCBFLG(A5)‰set�for�good�allocation3ŠMOVE.L�CCBCHB(A5),A1†get�memory�mapped�I/O�address'DCOINEX1:�POP_POINT‘recall�all�pointersŠRTS*ŠPAGEJ***************************************************************************$*‰DCO�DRIVER�COMMAND�SERVICE�ROUTINE*6*‹PARAMETER�ADDRESS�AND�BOUNDARY�CHECKS�HAVE�BEEN�MADE**ƒEntry:‚JSR�FROM�CMR�HANDLER.*‹A2�-�PHYSICAL�ADDRESS�OF�CMR�PARAMETER�BLOCK*‹A5�-�PHYSICAL�ADDRESS�OF�CCB*5*ƒExit:‚RTS�-�PARAMETER�BLOCK�VALIDATION�STATUS�IN�D0**ƒREGISTERS�USED:ƒ01234567 *”D******** *”A**P**PP*"*”A3�=�DCO�PARAMETER�BLOCK�ADDRESS*”A6�=�REQUESTOR�TCB�ADDRESS**ƒCODE�IS�RE-ENTRANT*J***************************************************************************)*‰Convert�logical�PB�address�to�physical.*DCOCMD„CLR.L‚D5;ŠMOVE.L�XIOCPK(A2),D6†Set�up�address�of�DCO�parameter�block:ŠMOVE.W�XIOPLN(A2),D5†Set�up�length�of�DCO�parameter�block+ŠMOVE.L�CCBTASKA(A5),A1„Set�up�TCB�pointer.&ŠBSR„IOHADRCK‹Call�conversion�routine.ŠBRA.S‚CMD010�Good�return.ŠNOP—Bad�length�return. ŠCLR.L‚D0;ŠMOVE.W�#RTCDPBLK,D0‡Set�up�invalid�parameter�block�addressŠBRA.S�DCOCEX1�goto�error�exit*!*‰see�if�passed�the�initialize�ok*7CMD010„MOVE.LƒD6,A3ŒStage�phys.�addr.�of�DCO�para.�blk. ŠCLR.L‚D04ŠTST.B‚CCBFLG(A5)‰error�code�set�in�CCB�during�INIT?/ŠBEQ.S‚CMD020�branch�if�no�error�code,�continue$ŠMOVE.B�CCBFLG(A5),D0†set�error�codeŠBRA.S‚DCOCEX2Œgoto�error�exit CMD020„EQU�**,*‰get�DCOTBL�address�into�A4�for�command�use* ŠMOVE.L�DCOTBL,A4ŠDCOTBL�address)ŠCMP.L‚#'!DCO',(A4)‡really�is�the�DCOTBL?,ŠBEQ.S‚CMD030�branch�if�really�is�the�DCOTBL4ŠMOVE.W�#DCONTBL,D0ˆset�error�return�code�-�no�tableŠBRA.S‚DCOCEX2Œand�return**‰find�DCO-ID�in�DCOTBL*‰A1�=�entry�address*0CMD030„MOVE.L�XIOCID(A2),D0†get�specified�DCO-ID(ŠMOVE.B�DCONMAX(A4),D1…max�#�of�DCO-ID's$ŠMOVE.L�#DCONTRY,D2ˆbump�past�header"FNDDCO10‚CMP.L‚(A4,D2),D0‰a�match?!ŠBEQ.S‚FNDDCO20‹branch�if�a�match&ŠADD.W‚#DCOIDLNG,D2‡bump�to�next�entry1ŠSUB.L‚#1,D1Ždecrement�number�of�entries�to�check&ŠBNE.S‚FNDDCO10‹branch�if�more�entries.ŠMOVE.W�#DCONID,D0‰error�-�DCO-ID�not�in�table5ŠBRA.S‚DCOCEX2Œreturn�to�CMR�with�error�condition�set+FNDDCO20‚MOVE.L�A4,A1Žbass�address�of�tableŠADD.L‚D2,A1Žaddress�of�entry (*‰Find�the�command�in�the�command�table.*-ŠMOVEQ‚#NUMCMDS-1,D0†Set�up�the�loop�counter./ŠLEA„CMDTBL,A0ŠA0�<--�address�of�command�table.+ŠMOVE.W�CMDCOD(A3),D6†get�DCO�command�code.8CMDSRCHƒCMP.W‚(A0)+,D6‹Search�the�table�for�the�command.ŠDBEQƒD0,CMDSRCH3ŠBNE.S‚CMDERR�If�we�found�the�command�in�t  he�table,8ŠADD.L‚#JMPOFF-2,A0‡get�the�corresponding�entry�from�the5ŠMOVE.W�(A0),D0Œjump�table�and�jump�to�the�routine�to"ŠJMP„(A0,D0.W)Šhandle�the�command.DCMDERR„MOVE.W�#DCOINVD,D0ˆdidn't�find�command�code�-�exit�with�errorCDCOCEX2ƒMOVE.WƒD0,CMDSTA(A3)„write�error�code�to�users�DCO�para�blk DCOCEX1ƒRTS*ŠPAGEL******************************************************************************‰OPEN�COMMAND*A*‰This�command�assigns�the�logical�connection�between�a�user�task9*‰and�specified�channels�within�an�DCO�module.�8�channels/*‰maximum�may�be�specified�in�one�open�command.*#*‰DCO�OPEN�command‚parameter�block: *�DS.W‚1„returned�command�status*�DS.W‚1„command�code�(01)*�DS.W‚1„#�of�channels�to�open*�DS.W‚1„1st�channel�number*�DS.W‚1„channel�configuration*’.*�DS.W‚1„nth�channel�number*�DS.W‚1„channel�configuration**‰configuration�word:+*�bit�0=1�wake-up�task�on�output�pulse�done-*•=0�queue�event�to�task�on�output�pulse�done2*�bit�15=1�use�default�configuration(ignore�bit�0) *•=0�use�specified�configuration**‰Default�configuration:,*�no�wakeup�or�queue�event�on�pulsed�output.B*‰When�default�configuration�is�specified,�the�actual�configuation9*‰is�saved�in�DCOTBL.�The�task�TCB�address�is�also�saved.*)*‚Entry:�A1�=�address�of�DCO-ID�in�DCOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A4�=�address�of�DCOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�CLRIOM,�SETIO,�DOIO*K*****************************************************************************‰see�if�channel�already�opened*$OPEN†PUSHPOINT‘save�all�address�regsŠALLOCATEƒCHCONFIG2ŠBSR�CLRIOM�clear�(to�$FF)�the�IO�map�for�this�DCOŠCLR.L‚D7‘channel�counter:ŠCMP.W‚#DCONID,D0‰an�error�returned�from�clearing�the�map?)ŠBEQ.S‚OPNOID�branch�if�an�error�returned$ŠCLR.L‚D2‘channel�offset�into�DCOTBL)ŠCLR.L‚D1‘offset�into�DCO�parameter�block1ŠMOVE.W�CMDCHN(A3),D0†get�#�of�channels�specified/ŠBLE.S‚OPNINC�branch�if�negative�or�zero,�error0ŠCMP.W‚#8,D0�cannot�specify�more�than�8�channels-ŠBGT.S‚OPNINC�branch�if�greater�than�8,�errorGOPEN10„MOVE.W�NUMCHAN(A3,D1),D2‚get�channel�number�from�DCO�param.�blk.!ŠCMP.W�#7,D2�insure�channel�#�<�8 ŠBGT.S�OPNINVŠMOVE.W�D2,D5Žsave�it0ŠMULUƒ#CHANLNG,D2ˆget�channel�offset�into�DCOTBLŠADD.L‚#4,D2Žbump�past�DCO-ID+ŠTST.W‚(A1,D2)Œthis�channel�already�opened?-ŠBPL.S‚OPNOPN�branch�if�already�opened,�errorŠADD.L‚#1,D7Žcount�this�channel@ŠMOVE.W�CHNCNFG(A3,D1),D3‚get�configuration�from�DCO�param.�blk.-ŠSTORE„D3,CHCONFIG†save�channel�configuration*0*‰save�TCB�address�and�configuration�information*.ŠLOAD…D3,CHCONFIG†recall�channel�configuration+ŠBSR.S‚SETIO�go�set�IO�map�for�this�channel5ŠCMP.W‚#DCONID,D0‰an�error�found�during�the�save�map?*ŠBEQ.S‚OPNERR�branch�if�an�error�was�found6ŠMOVE.W�D3,DCOCNIF(A1,D2)‚save�configuration�in�DCOTBL)ŠMOVE.L�A6,DCOTCB(A1,D2)ƒsave�TCB�address4ŠADD.W‚#OPNTRY,D1‰bump�to�next�DCO�param.�blk.�entry3ŠSUB.W‚#1,D0Ždecrement�number�of�channels�specified)ŠBGT„OPEN10�branch�if�more�channels�to�do,ŠBSR.S‚DOIOŽgo�set�the�IO�hardware�registers!ŠCMP.W‚#DCONID,D0‰an�error�found?7ŠBEQ.S‚OPNERR�branch�if�an�error�was�found�-�don't�openŠCLR.L‚D0‘set�for�good�returnŠBRA.S‚OPNXIT�go�return�to�CMR**‰open�errors�here*5OPNINVƒMOVE.W„#DCOICNS,D0‰set�invalid�channel�#�error ‰BRA.S…OPNXIT8OPNINCƒMOVE.W„#DCOINC,D0‰set�invalid�#�of�channels�error‰BRA.S…OPNXIT‹exit;OPNOIDƒMOVE.W„#DCONID,D0‰set�DCO�module�not�allocated�error‰BRA.S…OPNXIT�go�return�to�CMR9OPNOPNƒMOVE.W„#DCOPND,D0‰set�channel�already�opened�error*)*‰reset�any�opened�channels�to�not�opened*%OPNERR„TST.W‚D7‘any�channels�to�undo?3ŠBEQ.S‚OPNXIT�branch�if�none�to�undo,�return�to�CMR&ŠMOVE.W�#$FFFF,D3Šset�'un-opened'�codeŠCLR.L‚D1‘clear�for�use6OPNERR10‚MOVE.W�NUMCHAN(A3,D1),D2‚get�a�channel�number$ŠMULUƒ#CHANLNG,D2ˆget�channel�offsetŠADD.L‚#4,D2Žbump�past�headers*ŠMOVE.  W�D3,(A1,D2)‰set�this�entry�unopened-ŠADD.W‚#OPNTRY,D1‰bump�to�next�channel�numberŠSUB.W‚#1,D7Ždecrement�counter&ŠBGT.S‚OPNERR10‹branch�if�more�to�undo*…Fall�into�exit* OPNXIT EQU *)ŠADD.L„#8,A7ŒDEALLOCATE�CHCONFIG�on�stackŠPOP_POINT‘restore�all�pointers ŠBRA�NRMEXIT*ŠPAGEK*****************************************************************************‰SETIO*6*‰Build�the�IO�map�entries�for�the�specified�channels.*‰Builds�1�entry�per�call*‰Map�is�in�DCOTBL.**‰Entry:�A4ƒ=�DCOTBL�address*�D3.W�=�channel�configuration*�D5.B�=�channel�number*7*‰Exit:‚D0.W�=�DCONID�if�map�entry�not�found,�otherwise*—D0�unchanged *‰Uses:�D4,D6*‰Entry�point�=�SETIO*‰Exit�point‚=�SETIORT**ˆPrivate�subroutine�for�OPEN*$* Single exit & pointer preservation*L******************************************************************************‰find�map�entry* SETIO EQU *ŠPUSHPOINT‘save�all�pointersŠMOVE.L�D7,-(A7)‹save�D73ŠMOVE.W�DCOIO(A4),D7†get�offset�to�start�of�IO�maps.ŠMOVE.B�DCONAL(A4),D6†get�#�of�DCO'S�allocated3ŠMOVE.L�CCBCHB(A5),D4†get�memory�mapped�I/O�address;SETIOFD‚CMP.L‚IODDR(A4,D7),D4ƒfind�the�matching�I/O�addressŠBEQ.S‚SETIO00‹branch�if�found#ŠADD.W‚#IOLNG,D7‰bump�to�next�entryŠSUB.B‚#1,D6Ždecrement�counter/ŠBNE.S‚SETIOFD‹branch�if�more�entries�to�search>ŠMOVE.W�#DCONID,D0‰set�for�fatal�error�-�this�shouldn't�happenŠBRA.S„SETIORT‰return�to�caller**‰determine�channel�number*SETIO00‚CLR.L‚D6‘clear�for�use/ŠMOVE.B�D5,D6Žcopy�channel�number�to�work�space**‰CHANNEL�0-7�as�output�channel*/ŠBSETƒD5,DODR07(A4,D7)ƒset�ddr�image�for�output"SETIORT‚MOVE.L�(A7)+,D7‹restore�D7ŠPOP_POINT‘restore�all�pointersŠRTS—return�to�caller*ŠPAGED**********************************************************************‰DOIO*6*ˆCopy�the�data�information�from�the�IO�register�image"*ˆ(in�the�map)�to�the�IO�register.**ˆENTRY�PARAMETERS:*�A4�=�address�of�DCOTBL*�A5�=�address�of�CCB*)*‰Exit:‚D0.W�=�DCONID�if�IO�map�not�found*�D0.W�=�0�if�no�errors�found**‰Uses:�A0,D1,D6,D7*#* Single exit, pointer preservation*D********************************************************************* DOIO EQU *ŠPUSHPOINT’save�all�pointers!ŠMOVE.L�D7,-(A7)‹save�register�D7*ŠMOVE.W�DCOIO(A4),D7†get�offset�to�IO�maps$ŠMOVE.B�DCONAL(A4),D6†get�#�of�DCO'S3ŠMOVE.L�CCBCHB(A5),D1†get�memory�mapped�I/O�address*‰This�command�deactivates�outputs�for�specified�channels�that9*‰have�previously�been�opened�for�output�by�the�same�task<*‰requesting�this�activation.‚The�parameter�block�is�checked<*‰for�errors�before�any�output�is�deactivated.‚No�channel�is#*‰deactivated�if�an�error�is�found.*)*‰DCO�OUTPUT�OFF�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�044*‰DS.Wƒ1ƒbit�mask�containing�channel�#'s�to�activate*)*‚Entry:�A1�=�address�of�DCO-ID�in�DCOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A4�=�address�of�DCOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�DOOFF*%* Single exit with pointers preserved*L*****************************************************************************OUTOFF:ŠPUSHPOINT‘save�all�pointers2ŠCLR.L‚D3‘flag�to�ck�para.�blk.�before�stop�output'ŠMOVE.L�#4,D1Žbump�past�DCO-ID�in�table!ŠCLR.L‚D2‘use�for�channel�counterŠCLR.L‚D0‘clear�for�use+ŠMOVE.W�CMDCHN(A3),D0†get�channels�to�start0ŠMOVE.WƒD0,D3Œcopy�chan.�to�turn�off�to�work�reg+OUTOF20ƒBTSTƒD2,D0Ždeactivate�this�channel?0ŠBEQ.S‚OUTOF30Œbranch�if�no�-�check�next�channel5ŠCMP.L‚DCOTCB(A1,D1),A6ƒchannel�belongs�to�this�user? ŠBNE„OUTONERŒbranch�if�no,�error.ŠBCLR…D2,D3Œnegate�check�flag�for�this�channel$ŠTST„D3‘is�all�of�parameter�checked?(ŠBNE.S‚OUTOF30Œbranch�if�not�all�checked5ŠBSR.S‚DOOFFŽgood�para.�block�-�go�deactivate�channelŠBRA.S„OUTOFFXŠnormal�exit/OUTOF30ƒADD.L‚#1,D2Žbump�to�next�channel�number-ŠADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry&ŠCMP.L‚#8,D2�checked�all�the�channels?/ŠBNE.S‚OUTOF20Œbranch�if�more�channels�to�check ŠBRA†OUTONEROUTOFFX�EQU�*šnormal�exitŠPOP_POINT‘recall�all�pointersŠCLR.L„D0�signal�no�errorsŠBRA�NRMEXIT�normal�exit*‰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)*‹A5�has�address�of�user�CCB:*ˆDOOFF�is�called�by�OUTOFF�and�PULSED�OUTPUT�deactivation DOOFF…EQU†*/ŠMOVE.LƒA2,-(A7)Œsave�address�of�CMR�para�block3ŠMOVE.LƒCCBCHB(A5),A2‡get�memory�mapped�I/O�address)ŠEOR.B„D0,IOADR(A2)†turn�off�selected�0-72ŠMOVE.Lƒ(A7)+,A2Œrestore�address�of�CMR�para�blockŠRTS*ŠPAGEM******************************************************************************"*ˆSTAT�-�GET�OUTPUT�STATUS�COMMANDA*ˆThis�command�reads�the�status�of�specified�output�channels.�The>*ˆchannels�must�have�previously�been�opened�for�output�by�thisC*ˆuser.�The�parameter�block�is�checked�for�errors�before�any�outputA*ˆstatus�is�read.�The�users�parameter�block�is�modified�to�signalB*ˆactive�channels�by�setting�the�corresponding�bit�in�the�bit-maskE*ˆword.�The�corresponding�bit�number�of�inactive�channels�is�cleared.*-*ˆAll�channels�in�a�IO�side�are�read�at�once.*,*‰DCO�OUTPUT�STATUS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�05<*‰DS.Wƒ1ƒbit�mask�containing�channels�numbers�to�read�status$*”(�this�is�also�the�returned�field)*)*‚Entry:�A1�=�address�of  �DCO-ID�in�DCOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A4�=�address�of�DCOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�GTSTAT*M******************************************************************************STAT:ŠPUSHPOINT‘save�all�pointers(ŠCLR.L‚D5‘use�for�returned�status�values2ŠCLR.L‚D3‘flag�to�ck�para.�blk.�before�read�status(ŠMOVE.L�#4,D1Žbump�past�DCO-ID�in�DCOTBLŠCLR.L‚D2‘channel�counterŠCLR.L‚D0‘clear�for�use;ŠMOVE.W�CMDCHN(A3),D0†get�channel�numbers�to�read�status�on3ŠMOVE.W�D0,D3Žcopy�chan�activation�req.�bit�pattern$ŠAND„#$00FF,D0Šmask�all�but�low�byte/STAT20„BTSTƒD2,D0Žread�status�for�this�channel?ŠBEQ.S‚STAT40�branch�if�no5ŠCMP.L‚DCOTCB(A1,D1),A6ƒchannel�belongs�to�this�user?1ŠBNE„OUTONERŒbranch�if�no�-�return�with�error�set0ŠBCLRƒD2,D3Žclr�activation�flag�for�this�channel*ŠTST„D3‘finished�checking�parameter�block?1ŠBNE.S‚STAT40�branch�if�not�finished�checking�yet0ŠBSR.S‚GTSTAT�go�read�status�and�save�in�REG.�D5!ŠBRA.S‚STAT50�goto�procedure�exit3STAT40„ADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry(ŠADD.L‚#1,D2Žbump�to�next�channel�number,ŠBRA„STAT20�branch�to�channel�check�sequence6STAT50„MOVE.W�D5,CMDCHN(A3)†set�returned�status�values&ŠBRA„OUTONEXŒand�return�with�no�errors*‰PAGE*I* GSTAT reads the channels as required by the channel activation bit map,*‡on�a�byte�basis.**‡Data�is�returned�in�D5.**…Channel�data�mask:/BS07…EQU‡$000000FF‹select�mask�for�channels�0-7* GTSTAT EQU *‰MOVE.L„A2,-(A7)Œpush�A25‰MOVE.L„CCBCHB(A5),A2‡get�memory�mapped�I/O�base�addr8‰MOVE.W„CMDCHN(A3),D0‡get�new�channel�activation�bit�map)‰AND‡#BS07,D0Œselect�channels�0-7�bit�map)‰BEQ.S…GSTATXŽexit�on�no�channels�to�read%‰MOVE.B„IOADR(A2),D5†get�channels�0-7'‰AND.B…D0,D5�mask�off�non-read�channels GSTATX EQU *‰MOVE.L„(A7)+,A2Œrestore�A2‰RTS*ŠPAGEM******************************************************************************$*‰ENABLE�-�ENABLE�INTERRUPTS�COMMAND**‰NOT�USED�THIS�BOARD3*‰IF�CALLED,�EXITS�WITH�INVALID�COMMAND�ERROR�CODE.*0*‰DCO�ENABLE�INTERRUPTS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�06A*‰DS.Wƒ1ƒbit�mask�containing�channel�numbers�to�enable�interrupts)*‚Entry:�A1�=�address�of�DCO-ID�in�DCOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A4�=�address�of�DCOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCBM******************************************************************************ENABLE:5ENABLERƒMOVE.Wƒ#DCOINVD,D0‡set�code�'invalid�command'&ŠBRA„NRMEXITŒand�return�with�error�set***M******************************************************************************%*ˆDSABLE�-�DISABLE�INTERRUPTS�COMMAND**‰NOT�USED�THIS�BOARD-*‰IF�CALLED,�EXITS�WITH�INVALID�COMMAND�CODE.*1*‰DCO�DISABLE�INTERRUPTS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�07B*‰DS.Wƒ1ƒbit�mask�containing�channel�numbers�to�disable�interrupts)*‚Entry:�A1�=�address�of�DCO-ID�in�DCOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A4�=�address�of�DCOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCBM******************************************************************************DSABLE:‰BRA.S…ENABLER*‰PAGEM*******************************************************************************ˆPLSO�-�PULSED�OUTPUT�COMMAND*)*‚Entry:�A1�=�address�of�DCO-ID�in�DCOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A4�=�address�of�DCOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*‚Exits�to�NRMEXIT*+* Parameter block format for pulsed output:1* DCO parameter block (pointed to by A3 on entry)* *ˆDS.W†1‰returned�command�status*ˆDS.W†1‰command�code*ˆDS.W†1‰number�of�channels<*ƒ---ƒ---ƒ---ƒparameters�for�i  ndividual�channelsƒ---ƒ---ƒ---*ˆDS.W†1‰first�channel�number,*ˆDS.L†1‰number�of�milliseconds�for�pulse�on*ˆ.*ˆ.*ˆDS.W†1‰nth�channel�number5*ˆDS.L†1‰number�of�milliseconds�for�nth�channel�pulse*7* EACH CHANNEL IS ACTIVATED IN TURN (NON-SYNCHRONOUSLY)M******************************************************************************@*„Pulsed_Out(IN-LIST�OF�channel�activation�request,�pulse�times;*�OUT-error�code)BPLSO…ALLOCATE�CHANID,DCOPARBK†allocate�channel�id�&�DCO�para�block3‰STORE…A3,DCOPARBK‰save�DCO�parameter�block�address ‰CLR.L…D6’Initiate�pulsed�output ‰CLR.L…D3 ‰CLR.L…D2 ‰CLR.L…D0$*—get�number�of�channels�to�activate<‰MOVE.W„CMDCHN(A3),D0‡get�number�of�chan's�from�DCO�para�blkPLSO1:$‰TST.W…D0’loop�on�#�of�chan.'s�to�do ‰BEQ.S…PLSOX‰CLR.L…D5’get�channel�number‰MOVE.W„NUMCHAN(A3,D6),D5-‰STORE…D5,CHANID‹save�channel�number�on�stackC*„Channel�ID�consists�of�user�CCB�address�+�chan�number�in�LS�byte.+‰MOVE.L„A5,D7�copy�user's�CCB�address�to�D75‰ADD.L…D7,CHANID(A7)‡CHANID�now�has�complete�chan.�ID"‰MOVE.L„D5,D7�copy�channel�#�to�D7,‰BSR‡BIN_BIT�convert�binary�to�bit�map�in�D56‰MULU†#CHANLNG,D7‰compute�offset�to�nth�chan�in�DCOTBL%‰ADD‡#4,D7�bump�to�user�TCB�in�DCOTBL-‰CMP.L…DCOTCB(A1,D7),A6„compare�TCB�addresses1‰BNE.S…PLSOER1�branch�on�channel�not�current�user2*„Get�pulse�time�from�DCO�commmand�parameter�block‰MOVE.L„CHNCNFG(A3,D6),D3%*„IF�pulse�time�>�pulse_min_time�THEN'‰BEQ.S…PLSOER3ƒbranch�on�pulse�time�=�0(‰ADD.W…#6,D6…increment�to�next�channel�#-*„request�periodic�activation(this�channel�#)2‰LEA‡PLSOFF(PC),A0‡point�to�pulse�turn�off�routine%‰CLR.L…D1’set�request�for�1�time�only6‰MOVE.B„CCBPPRIO(A5),D1…set�act.�priority�same�as�task/‰LOAD†D2,CHANID‹setup�channel�ID�to�goto�PLSOFF‰PUSHALL'‰MOVE.L„D3,A1�setup�activation�interval$‰TR0$.RQPA�,“pass�request�for�wakeup)*ŒIf�no�err�in�periodic�act.�request�THEN‰BRA.S…RQPAOKŽgood�return(‰BRA.S…PLSOER4�err�in�periodic�act.�req.RQPAOK:"*›activate_this_channel(channel�#)$‰MOVE.L„D5,D0�pass�bit�mask�to�DOOUT ‰BSR‡DOOUT‰POPALL"‰SUB‡#1,D0�decrement�channel�count ‰BRA‡PLSO1**ŒError�handlingPLSOER1:"‰CLR.L…D0’Channel�not�current�user‰MOVE.W„#DCOICNS,D0 ‰BRA.S…PLSOX1*PLSOER3:"‰CLR.L…D0’Requested�pulse�time�=�03‰MOVE.W„#DCOCNFG,D0‰return�'bad�configuration'�code ‰BRA.S…PLSOX1*PLSOER4:‰POPALL#‰CLR.L…D0’Periodic�activation�error,‰MOVE.W„#DCOBSY,D0‹return�'device�busy'�code ‰BRA.S…PLSOX1*PLSOX:*ŒPulsed�output�good�exit�point6‰LOAD†A3,DCOPARBK‰restore�DCO�para�block�address�to�A3‰CLR.L…D0ˆset�for�normal�return*PLSOX1:1‰ADD.L…#12,A7„DEALLOCATE�CHANID,DCOPARBK�on�stack*‰BRA‡NRMEXITƒgoto�normal�common�exit�point*‰PAGE*„PULSED�OUTPUT�DEACTIVATION:!*ŒEntered�by�periodic�activation. *‡On�entry:?*ˆD1�contains�channel�ID�composed�of�user's�CCB�address�in�M.S.7*‹3�bytes,�and�channel�number�(0-7)�in�least�sig.�byte.*PLSOFF:‰PUSHALL&‰MOVE.B„D1,D5�save�combined�channel�ID ‰AND.B…#0,D1�recover�CCB�address+‰MOVE.L„D1,A5�stage�CCB�address�for�'DOOFF'+‰AND.L…#$000000FF,D5‡recover�channel�number‰MOVE.L„D5,D4�save�binary�value‰MOVE.L„#$0C010000,D2 ‰MOVE.B„D5,D2.‰BSR.S…BIN_BIT�convert�chan�#�to�bit�map�in�D5"‰MOVE.L„D5,D0�stage�data�for�DOOFF‰BSR‡DOOFF�turn�off�channel0‰MULU†#6,D4�point�to�data�field�assoc.with�chan.5‰ADD‡#DCONTRY,D4‰add�offset�to�1st�channel�data�field‰ADD‡#4,D4�add�in�size�of�DCOID+‰MOVE.L„DCOTBL,A2‹get�addr.�of�DCOTBL�to�A2,‰MOVE.L„CCBTASKA(A5),A6…A6�=�users�TCB�addr. ‰CLR.L…D72‰MOVE.B„DCONMAX(A2),D7†get�max�#�of�DCO-ID's�to�D7#‰MOVE.L„CCBMNEM(A5),D6†get�CCB�name!PLS001ƒEQU‡*“find�matching�DCO-ID!‰MOVE.L„DCOID(A2),D3ˆDCO-ID�to�D3(‰CMP.L…D3,D6�does�CCB�name�match�DCO-ID?‰BEQ.S…PLS002Žbranch�on�match*‰ADDA.W„#DCOIDLNG,A2ˆadd�offset�to�next�ID"‰SUB.B…#1,D7�end�of�possible�ID's?$‰BMI.S…PLS003Žbranch�on�ID�not�found‰BRA‡PLS001Žcheck�next�ID PLS002ƒEQU‡*-‰MOVE.W„DCOCNIF(A2,D4),D0ƒconfiguration�to�D0(‰BSR.S  …NOTFYUSRŒsee�if�wakeup�or�quevent PLS003ƒEQU‡*‰POPALL‰RTE*‰PAGE$*‰Binary�to�bit-map�conversion�in�D5@*‰Produces�a�1�in�D5�bit�corresponding�to�the�binary�value�in�D5*‰up�to�bit�15.@*‹For�input�>�15�binary�the�resultant�pattern�in�D5�is�undefinedBIN_BIT:‰ALLOCATE‚BITMAP‰CLR.L…BITMAP(A7)‰ADD.W…#1,BITMAP(A7) LOOP…EQU‡* ‰TST.W…D5 ‰BEQ.S…BINBITX�exit�on�bit�found‰ROL.W…BITMAP(A7) ‰SUB‡#1,D5 ‰BRA.S…LOOP* BINBITX‚EQU‡*‰MOVE.W„BITMAP(A7),D5'‰ADD.L…#8,A7�DEALLOCATE�BITMAP�on�stack‰RTS*‰PAGE *„NOTIFY�USERA*ˆnotify�user�by�means�of�que�event�or�wakeup�as�specified�in�the*ˆchannel�configuration�word.*„INPUT�PARAMETERS:'*’A2:�Address�of�channel�name�in�DCOTBL;*’D4:�Offset�from�channel�name�to�channel�data�field�(base) *™in�DCOTBL.*’A5:�Address�of�channel�CCB.*’A6:�User's�TCB�address#*’D2:�$0C01�* NOTFYUSR:?‰MOVE.WƒDCOCNIF(A2,D4),D0�get�configuration�from�channel�DCOTBL#‰BTST†#15,D0‹default�configuration? ‰BNE.S…NOTIFX1‰BTST…#0,D0‰no,�determine:�wake-up=1�or�q-event=0 ‰BNE.S…NOTIFA*ŽEnqueue�event;�data�staging:$*ŽD2�=�$0C01� *ŽD3�=�DCOID*ŽD4�=�Mem�mapped�I/O�address*ŽA6�=�User's�TCB�address*8‰MOVE.LƒCCBCHB(A5),D4…get�mem.�mapped�I/O�address�staged ‰BSR.S�QUEVENT�enqueue�the�event‰BRA.S‚NOTIFXŽgoto�exit*+NOTIFAƒMOVE.LƒA6,A0Žstage�users�TCB�address#‰TR0$.WAKEUP�,�issue�wakeup�to�userNOTIFX:‰RTS*ŠPAGEO******************************************************************************** *ˆNORMAL�EXIT*,*‚Entry:�A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�DCO�parameter�block*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*‰D0�=�DCO�error�code*I**************************************************************************NRMEXIT:>ŠMOVE.W�D0,CMDSTA(A3)†set�return�status�in�DCO�parameter�blockŠRTS—return�to�CMR*ŠPAGE*H*‚QUEVENT�-�queue's�event�to�driving�task�using�data�staged�in�registers *‹as�follows:*‹A6�=�user's�TCB�address&*‹D2�=�$0C01�*‹D3�=�DCOID‚(module�name)&*‹D4�=�mem�mapped�I/O�address�of�board<*†(dumps�contents�of�registers�D2,�D3,�&�D4�to�users�buffer)* QUEVENT EQU *‹PUSHALL”push�all�regs"‹MOVE.L…A6,A0Žstage�user's�address ‹TR0$.QEVNTI*)‹BRA.SƒQUEVNTOKŒgood�return�for�que�event'‹BRA.SƒQUEVNTERŒbad�return�from�queventQUEVNTOK EQU *‹POPALL•restore�all�regs‹RTS QUEVNTER:(‹BRA�QUEVNTOK�put�a�break�here�for�debug*ŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLING�TASKS�ADDRESS�SPACE.*#*�ENTRY:ƒD5‚-�NO.�OF�BYTES�TO�CHECK*ŠD6‚-�68000�ADDRESS�(LOGICAL)*ŠA1‚-�TCB�ADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1*7*�EXIT:„D6�-�PHYSICAL�ADDRESS�OF�BUFFER�BASE�(IF�LEGAL)*ŠRETURN�TO�PC„FOR�GOOD�ADDRESS*”PC+2‚FOR�BAD�LENGTH*”PC+4‚FOR�BAD�ADDRESS*F*********************************************************************** IOHADRCK:%ŠBTSTƒ#0,D6‘Must�be�on�work�boundary.)ŠBNE.S‚IOHADR4�Branch�if�bad�buffer�base.ŠTST.L‚D5”Length�can't�be�zero.2ŠBEQ.S‚IOHADR8�Don't�go�to�logphy�with�zero�count.1ŠMOVE.L�TCBTST(A1),A0‰Address�of�task�seg.�table. ŠTR0$.LOGPHY*.ŠBRA.S‚IOHADR8�Branch�for�good�address�return.0ŠBRA.S‚IOHADR6�Branch�for�bad�byte�count�return.(ŠTST.L‚D5”Was�an�entry�pointer�returned.#ŠBEQ.S‚IOHADR4�Branch�if�no�-�ERROR)ŠTST.B‚7(A0,D5)ŽIs�this�an�MMIO�segment�?ŠBNE.S‚IOHADR8�Yes,�OK.3IOHADR4ƒADD.L‚#2,(A7)�Adjust�PC�for�invalid�return.3IOHADR6ƒADD.L‚#2,(A7)�Adjust�PC�for�invalid�return.IOHADR8ƒRTSšReturn.*ŠPAGEJ***************************************************************************!* INTERRUPT SIDE FOR IOH HANDLING*?*ƒPURPOSE:‚HANDLE�ACKNOWLEDGEMENTS�AND�MESSAGE�COMPLETIONS�FROM2*�THE�IOH.‚OPERATES�AT�HARDWARE�INTERRUPT�PRIORITY=*�LEVEL�AS�A�SUBROUTINE�TO�THE�FIRST�LEVEL�INTERRUPT�HANDLER.  *+*ƒENTRY:‚JSR‚FROM�INTERRUPT�HANDLER�ROUTINE*‹A0�-�WORK�REGISTER *‹A1�=�SELF*‹A5�=�ADDRESS�OF�CCB*‹D0�=�WORK�REGISTER*/*ƒEXIT:‚RTS�-�BACK�TO�INTERRUPT�HANDLER�ROUTINE*/*ƒNOTE:ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***@*ƒThis�routine�is�called�only�by�the�common�interrupt�handler�in'*ƒRMS68K.ƒThe�common�interrupt�handler:;*ƒ!!!ƒDOES‚NOTƒPRESERVEƒVALUESƒINƒREGISTERSƒBEFOREƒTHEƒCALLK*ƒso�this�interrupt�handler�must�pruserve�all�data�reg.'s�&�address�reg.'s.5*ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***ƒ***‚***‚***�***ƒ***ƒ***ƒ*****ƒREGISTERS�USED:ƒ01234567 *”D******** *”A*****P***4*ƒIf�channel�is�off-line�or�not�attached,�just�exit.K****************************************************************************<*‹Find�DCO�TABLE�module�(board)�name�which�matches�CCB�name:*3DCOINTƒMOVEM.LƒA0-A6/D1-D7,-(A7)ƒsave�all�except�D01‰ALLOCATE‚DCOTADR,CHANUM†allocate�local�variables-‰MOVE.L„DCOTBL,A2‹get�address�of�DCOTBL�to�A2 ‰CLR.L…D76‰MOVE.B„DCONMAX(A2),D7†get�max�number�of�DCOID's�to�D7#‰MOVE.L„CCBMNEM(A5),D0†get�ccb�name2IOHI011‚EQU‡*‡find�matching�DCOID�loop�entry�point*‰MOVE.L„DCOID(A2),D3ˆget�DCOID�for�staging'‰CMP.L…D3,D0�does�CCB�name�match�DCOID?#‰BEQ.S…IOHI020�branch�on�name�match.‰ADDA.W„#DCOIDLNG,A2ˆadd�offset�to�next�DCOTBL#‰SUB.B…#1,D7�test�for�end�of�DCOTBL6‰BMI.S…IOHIEX01Œbranch�to�error�exit�1�on�id�not�found ‰BRA‡IOHI011F*…Found�matching�names,�now�get�number�of�interrupting�channel�(to�D2)$*£in�this�case,�non-existant�chan.�85IOHI020‚STORE…A2,DCOTADRŠsave�DCOTBL�address�on�stack,‰MOVE.L„#$0C010008,D2‡init�para�fields�in�D2+‰STORE…D2,CHANUM‹save�chan.�#�&�return�code>*„Compute�address�of�field�in�DCOTBL�having�user's�TCB�address ‰CLR.L…D4!‰MOVE.B„D2,D4�get�channel‚to�D4.B$IOHIPXƒEQU‡*‰'DCOINT'�procedure�exit2‰MOVE.L„#0,D0�get�interrupt�claim�check(=0�-�none)*„dealocate�DCOTADR,CHANUM#‰ADD‡#12,A7Žrelease�local�variables0‰MOVEM.Lƒ(A7)+,A0-A6/D1-D7ƒrestore�all�except�D02‰AND‡#$FFFE,SR‹signal�CMR�'interrupt�not�from�DCO'‰RTS*IOHIEX01�EQU‡*,*‹error�exit�for�DCOID�name�not�found�in�CCB‰BRA‡IOHIPXŽgoto�procedure�exit**‰ENDééFTDCO…IDNTƒ1,0�DCO�subroutines**‰FORTRAN�callable�subroutines*‰for�DCO�driver�calls*$*‰CALL�DCOCMD(dco_id,param_blk_addr)*‰where�DCOCMD�may�be:*)*‰CALL�DCOPEN(dco_id,param_blk_addr)…open**‰CALL�DCOCLS(dco_id,param_blk_addr)…close.*‰CALL�DCOOUT(dco_id,param_blk_addr)…output�on/*‰CALL�DCOOFF(dco_id,param_blk_addr)…output�off+*‰CALL�DCOSTA(dco_id,param_blk_addr)…status2*‰CALL�DCOPLS(dco_id,param_blk_addr)„output�pulsed*,*‰All�arguments�for�the�calls�are�identical.7*‰The�contents�of�the�param_blk�for�each�call�is�unique*‰to�the�call.*6*‰All�the�command�subroutines�call�a�common�subroutine3*‰DCOSET�to�build�the�initiate�I/O�parameter�block.**‰STACK�FOR�ALL�CALLS:*7*‰deepest�stack:�(stack�address�stays�at�DCOSET�return)0*˜command�codeƒ2�bytes�(initiate�I/O�param.�blk) *˜n/aŒ2�bytes*˜dco_id‰4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes,*˜command�addrƒ4�bytes�(dco�command�address)**˜command�lng„2�bytes�(dco�command�length)-*˜DCOSET�return‚4�bytes�deepest�stack�address *˜A3�4�bytes *˜A2�4�bytes *˜A1�4�bytes *˜D0�4�bytes*‰entry�stack:ƒreturn‰4�bytes*˜^param_blk_adr�4�bytes*˜^dco-idˆ4�bytes* ŠSECTION�9!ŠXDEFƒDCOPEN,DCOCLS,DCOOUT,DCOOFFŠXDEFƒDCOSTA,DCOPLS*$*‰CALL�DCOPEN(dco_id,p  aram_blk_addr)*‰open�and�configure�channels*1DCOPEN„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers3ŠBSR„DCOSET�set-up�the�initiate�I/O�parameter�block)ŠMOVE.L�#1,(A2)Œset�the�open�command�codeDCOPN00ƒCLR.L‚D0‘clear�for�use'ŠMOVE.W�4(A2),D0‹get�number�of�channelsŠASL.L‚#2,D0Žmultiply�by�4.DCOPN05ƒADD.L‚#6,D0Žadd�in�the�6�byte�overhead-DCOPN10ƒMOVE.W�D0,(A1)Œset�the�command�length-ŠMOVE.L�A3,A0ŽTRAP�#1�parameter�block�address#ŠMOVE.L�#60,D0�CMR�directive�numberŠTRAPƒ#1‘call�RMS68K'ŠMOVE.W�D0,(A2)Œset�the�returned�status)ŠMOVEM.L�(A7)+,D0/A1-A3„restore�registers!ŠMOVE.L�(A7)+,A0‹put�return�in�A0 ŠLEA„8(A7),A7‹clean�up�the�stackŠJMP„(A0)�return�to�user*$*‰CALL�DCOCLS(dco_id,param_blk_addr)"*‰close�all�channels�for�this�user“Dœ8¤ *1DCOCLS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚DCOSET�set-up�the�initiate�I/O�parameter�block*ŠMOVE.L�#2,(A2)Œset�the�close�command�code&ŠMOVE.W�#4,D0ŽDCO�close�command�lengthŠBRA„DCOPN10Œgo�do�the�CMR�call*$*‰CALL�DCOOUT(dco_id,param_blk_addr)'*‰activate�output�on�requested�channels*1DCOOUT„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚DCOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#3,(A2)Œset�the�output�command�code*DCOUT10ƒMOVE.Wƒ#6,D0Œset�up�command�lengthŠBRA„DCOPN10Œgo�do�the�CMR�call*$*‰CALL�DCOOFF(dco_id,param_blk_addr))*‰deactivate�output�on�specified�channels*1DCOOFF„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚DCOSET�set-up�the�initiate�I/O�parameter�block/ŠMOVE.L�#4,(A2)Œset�the�output�off�command�code4ŠBRA„DCOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�DCOSTA(dco_id,param_blk_addr))*‰read�input�status�on�specified�channels*1DCOSTA„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚DCOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#5,(A2)Œset�the�status�command�code4ŠBRA„DCOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�DCOPLS(dco_id,param_blk_addr)>*‰activate�output�for�x#�of�milliseconds�on�specified�channels*1DCOPLS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚DCOSET�set-up�the�initiate�I/O�parameter�block2ŠMOVE.L�#8,(A2)Œset�the�pulsed�output�command�codeŠCLR.L‚D0‘clear�for�use,ŠMOVE.W�4(A2),D0‹get�specified�#�of�channelsŠASL.L‚#2,D0Žmultiply�by�6ŠADD.W‚4(A2),D04ŠBRA„DCOPN05Œgo�set�command�length�&�do�the�CMR�callŠPAGE*4*‰DCOSET�set�up�the�CMR�initiate�I/O�parameter�block,*‰returns:ƒA1=address�for�DCO�command�length(*”A2=DCO�command�parameter�block�address)*”A3=initiate�I/O�parameter�block�address*(DCOSET„CLR.W‚-2(A7)�clear�command�length-ŠLEA„-2(A7),A1Šsave�address�of�command�length$ŠMOVE.L�24(A7),A0Šget�param_blk_addr%ŠMOVE.L�A0,-6(A7)Šsave�param_blk_addr,ŠMOVE.L�A0,A2Žsave�param_blk_addr�for�returnŠCLR.L‚-10(A7)Œnot�usedŠCLR.L‚-14(A7)Œnot�usedŠCLR.L‚-18(A7)Œnot�usedŠMOVE.L�28(A7),A0Šget�^dco_idŠMOVE.L�(A0),-22(A7)‡get�dco_idŠCLR.W‚-24(A7)Œnot�used0ŠMOVE.W�#$0700,-26(A7)…initiate�I/O�command�code4ŠLEA„-26(A7),A3‰initiate�I/O�parameter�block�addressŠRTS—return�to�caller*ŠEND*éé  éééé@‰TTL�RAD1�DRIVER‚===============================================9RADDRVƒIDNT†1,0�RAD1�DRIVER‚COPYRIGHT�1982�MOTOROLA,�INC.‰PAGE8*ˆ6/21/82ƒ<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<H*************************************************************************ˆ======================*ˆ{”}*‡{†RAD�Driver†}*ˆ{”}*ˆ======================I*************************************************************************** ‰TTL�STR.SA‰PAGE‰INCLUDE�9995.&.STR.EQ* ‰TTL�TCB.EQ‰PAGE‰INCLUDE�9995.&.TCB.EQ* ‰TTL�CCB.SA‰PAGE‰INCLUDE�9995.&.CCB.EQ* ‰TTL�LV5.SA‰PAGE‰INCLUDE�9995.&.LV5.EQ*‰TTL�9995.&.RADDRV.EQ‰PAGEŠINCLUDE�9995.&.RADDRV.EQ*@‰TTL�RAD1�DRIVER‚===============================================ŠPAGE;************************************************************ *ˆCONSTANTS*;*************************************************************ˆCommand�Codes*%RASTPCMD�EQU‡00ˆ"Stop"�command�value.%RALODCMD�EQU‡01ˆ"Load"�command�value.%RADMPCMD�EQU‡02ˆ"Dump"�command�value.%RAJMPCMD�EQU‡03ˆ"Jump"�command�value.*RATSTCMD�EQU‡04ˆ"Self-test"�command�value.&RAOPNCMD�EQU‡$10‡"Open"�command�value.'RACLSCMD�EQU‡$20‡"Close"�command�value.'RAABTCMD�EQU‡$7F‡"Abort"�command�value.2RAEXTCMD�EQU‡$81‡"External�trigger"�command�value.*RASETCMD�EQU‡$82‡"Setpoint"�command�value.&RASCNCMD�EQU‡$83‡"Scan"�command�value.1RAATOCMD�EQU‡$84‡"Auto-range�scan"�command�value.+RACALCMD�EQU‡$85‡"Calibrate"�command�value.1RAHISCMD�EQU‡$86‡"High-speed�scan"�command�value.:RAXEQBYT�EQU‡$80‡"Execute�function"�command�(OR-ed�in�with(*¦function�number�to�form�command�byte.)RAXEQCMD�EQU‡RAXEQBYT7RASTOPIT�EQU‡$FF‡Value�to�put�in�stop�byte�to�stop�RAD.**ˆOffsets�in�shared-RAM=*’(68000�addressing--i.e.�values�are�twice�the�6809�offsets.)*RASTPBYT�EQU‡0‰Stop�byte.RACMDBYT�EQU‡2‰Command�byte.#RAINTFLG�EQU‡4‰Interrupt�flag�byte."RACSTAT‚EQU‡6‰Command�status�byte.#RAINTMSK�EQU‡8‰Interrupt�mask�byte.¥¬Fµ<½8Å0ÍFÕ0ÝCå7í2õEý?- 250%@-:5:=6E3M=U5]3e0m8u8}-…6�-•6%RAFIFOST�EQU‡10ˆStart-of-FIFO�offset."RAFIFOND�EQU‡12ˆEnd-of-FIFO�offset(RANXT2GT�EQU‡14ˆFIFO-next-to-get�offset.RAPRMPTR�EQU‡18ˆParameter�ptr.'RAPARAM‚EQU‡84ˆStart�of�parameter�list.!RATSTAT‚EQU‡502‡Self-test�status.BRAOK2STO�EQU‡508‡High-speed�scan�"communications"�flag.‚(1�=�ok�to**¦put�data,�2�=�ok�to�take�data,�0�=�stop))RAXSTAT‚EQU‡510‡Hardware�status�register.***ˆTable�offsets**)*‚CCB�(device-dependent�section)�offsets.*;RARDLADR�EQU‡CCBDDP„Addr�of�this�RAD's�entry�in�'RARADLST'.ARACMDCOD�EQU‡RARDLADR+4ˆCommand�code�RAD�is�currently�working�on.8RARDFLAG�EQU‡RACMDCOD+1Š"Interrupt-being-serviced"�flag.3RAUSRTCB�EQU‡RARDFLAG+1ŠAddr�of�current�user's�TCB.:RARTRVAD�EQU‡RAUSRTCB+4ŠAddr�of�data-retrieval�subroutine. =RACHNUSR�EQU‡RARTRVAD+4ŠUser�ptr�for�chan�0‚(start�of�channel*¦user�ptr�list).?RAINSTR‚EQU‡RACHNUSR+64‰Interrupt�"instruction"�flag�(indicates&*¦what�is�to�be�done�when�an�interrupt$*¦occurs�from�the�current�function).9RAJMPRRG�EQU‡RAINSTR+1‹Contains�value�from�harware�jumper%*¦"register"�on�RAD�board�(loc�7000)./RASHRAD‚EQU‡CCBCHBŽStarting�addr�of�shared-RAM.*M*============================================================================B*‚CCB�offsets�for�locations�used�by�standard�driver�skeleton�code.0CCBERAD1�EQU‡RAJMPRRG+1ŠError�debug�save�address9CCBQVER1�EQU‡CCBERAD1+4ŠEvent�queuing�error�debug�address(CCBCIDƒEQU‡CCBQVER1+4ŠCMR�param�block�ID*3******‚Check�for�too�much�stuff�to�fit�in�CCB�.�.�.‰IFGT†CCBCID+4-256%‰FAIL†499‘Abort�assembly�if�too�much.‰ENDC******** CCB flag positionsCCBFGBSY�EQU‡7“Channel�busyN*=============================================================================***‚Command�packet�offsets**RACMDERR�EQU‡0“Error�return�code�location..RAREQCMD�EQU‡RACMDERR+2ŠRequested�command�code8RACMDPRM�EQU‡RAREQCMD+2ŠStart�of�command�parameter�list.** *ˆFlag�values*:RAWRKFLG�EQU‡1‰Flag�setting�for�RARDFLAG�indicating�we�are(*¦working�on�an�interrupt�from�this�RAD.** *ˆError�codes*RAERR1ƒEQU‡$F0‡RAD�is�"bad".RAERR2ƒEQU‡$F1‡RAD�is�"busy".RANOTUSR�EQU‡$FF‡This�user�is�not�using�this�RAD�now�(tried�to*œdo�a�RADSTP).:RAABORTD�EQU‡$FB‡This�RAD�was�aborted�since�this�user�last#*¦called--user�must�reopen�for�RAD.7RASYSERR�EQU‡$FA‡This�is�an�"extra"�RAD--can't�be�used.'*¦(SYSGEN�was�set�up�for�too�few�RADs.)RAOVRFLO�EQU‡$FC‡FIFO�overflow.***ˆRAD�status�codes*(RAUNINIT�EQU‡$F000…RAD�is�uninitialized.RASTBAD‚EQU‡$FFFF…RAD�is�"bad".6RASTOKƒEQU‡$F0F0…RAD�is�ok�and�ready�to�take�commands.3RASTDOIN�EQU‡$F001…RAD�is�now�doing�initialization.*** *ˆBit�masks*=RAINTBIT�EQU‡$C0‡Bits�to�check�in�status�byte�for�interrupts..*œ(Bit�7�=�level�4�int.,�bit�6�=�level�3�int.)*;RASUBRBT�EQU‡0‰Option�bit�#�for�user-supplied�data-handling+*œsubroutine�for�when�data�for�this�chan�is*œreceived�from�the�RAD.;RAQUEBT‚EQU‡1‰Option�bit�#�to�queue�event�to�user�when�data)*œfor�this�chan�is�received�from�the�RAD.=RAWAKEBT�EQU‡2‰Option�bit�#�to�wake�up�the�user�when�data�for%*œthis�chan�is�received�from�the�RAD.**ˆMisc.�constants*RARDRMND�EQU‡$D7FF…End�addr�of�RAD�RAM�(excluding�shared-RAM).?RALODLNG�EQU‡100‡Max�#�of�words�to�load�or�dump�thru�shared-RAM*¦at�one�time.*ˆset�aside�in�the�SYSGEN�for�use�by�the�driver�(RAD1TBL).‚TheC*ˆdriver�takes�a�command�from�the�user,�passes�it�on�to�the�correct?*ˆRAD1�board�(where�the�firmware�will�interpret�and�execute�theD*ˆcommand),�takes�the�data�back�from�the�RAD1,�and�passes�it�back�to>*ˆthe�user�in�the�manner�specified�by�that�user.‚Communication>*ˆbetween�the�68000�and�the�RAD1�board�takes�place�through�the*ˆ256-byte-long�shared-RAM.*>*ˆCode�in�this�driver�is�relocatable,�re-entrant,�and�ROMable.**/*ƒENTRY:‚JSR�FROM�CMR�HANDLER�(COMMAND�SERVICE) *‹JSR�FROM�CMR�INTERRUPT�HANDLER*-*ƒEXIT:�-�ALWAYS�EXITS�WITH�A�RTS�INSTRUCTION**I*========================================================================*²<<<<<<<<<<<<<<<<<<<<<<<<<<<A*ˆAssemble�using�chain�file�RADASM.CF‡<<<<<<<<<<<<<<<<<<<<<<<<<<<*²<<<<<<<<<<<<<<<<<<<<<<<<<<<H*-----------------------------------------------------------------------*‰PAGEJ*****************************************************************************C*‚THIS�IS�THE�SERVICE�VECTOR�TABLE�WHICH�IS�REQUIRED�FOR�CMR-CALLED*ˆI/O�DRIVERS.***L****************************************************************************** ‰SECTION�8***‚Service�vector�table�for�CMR: RADDRVR‚EQU‡*9‰DC.L†RADISR-RADDRVR†Offset�to�interrupt�service�routine.7‰DC.L†RADCMD-RADDRVR†Offset�to�command�service�routine.6‰DC.L†RAINIT-RADDRVR†Offset�to�initialization�routine.‰DC.L†0“RESERVED***‚Other�CMR�params:!‰DC.B†0“#�of�extra�pages�per�CCB. ‰DC.B†0,0,0 ‰DC.L†0,0,0***‚Revision�info.:-‰DC.B†'021783'ŒRADDRV�revision�date�(MMDDYY).*‰DC.B†'�'‘Patch�flag�(blank�=�no�patches).$‰DC.B†'4'‘Major�VERSAdos�revision�#.*‰PAGEM*******************************************************************************ˆInitialization�Routine*5*’Called�through�CMR�once�for�each�CCB�when�system�is5*’booted.‚This�routine�initializes�the�data�area�used*’by�the�RAD�driver.*!*ˆUpon�entry:‰A5�=�address�of�CCB*8*ˆUpon�exit:ŠThe�following�register�contents�are�changed%*œ(and�not�restored):ƒA0,�A1,�D1,�D2.*M***************************************************************************** RAINITƒEQU‡*7‰MOVEA.LƒRAD1TBL,A0ŠPut�address�of�RAD�table�area�(from*¦SYSPAR)�into�A0.5‰CMPA.L„#0,A0�Has�memory�been�set�up�for�RADs�on�this!‰BEQ.S…RAERRXS�system?‚No--error.>‰CMPI.B„#RALVL4,CCBPPRIO(A5)…Is�this�a�level�4�CCB?‚(Interrupt**¦levels�are�set�internally�as�1�more�than*¦actual�level.)7‰BEQ.S…RAINRET�Yes--ignore�it,�no�initializtion�needed."‰CLR.L…D2’No,�must�be�level�3�CCB.%‰MOVE.L„D2,A1�Clear�A1�for�later�use.>‰MOVE.B„RARADUSD(A0),D2…Set�up�D2�to�contain�number�of�entries*¦in�RARADLST�already�used.6‰CMP.B…RANUMRAD(A0),D2…Are�any�entries�left�available?(‰BGE.S…RAERRXS�No--table�is�full--error.8‰ADDQ.B„#1,RARADUSD(A0)…Yes.‚Bump�count�of�entries �used.9‰MULU†#RARDENTL,D2ˆMultiply�#�entries�used�by�length�of�1$*¦entry�to�get�offset�in�RARADLST�to*¦next�available�entry.=‰MOVEA…RARADLAD(A0),A1…Put�start�addr�of�RARADLST�into�A1,�by4‰ADDA.L„A0,A1�adding�table�area�start�addr�to�offset*¦to�RARADLST..‰ADDA.L„D2,A1�Set�A1�to�addr�of�next�available*¦entry�in�RARADLST.<‰MOVE.L„CCBMNEM(A5),(A1)„Move�RAD-ID�into�RARADLST�entry�for *¦this�RAD.=‰MOVE.L„A1,RARDLADR(A5)…Put�addr�of�this�RAD's�RARADLST�entry *¦into�CCB.2‰CLR.B…RACMDCOD(A5)ˆInitialize�the�rest�of�the�CCB*‰CLR.B…RARDFLAG(A5)ˆdevice-dependent�area.0‰LEA‡RARDFIFO(PC),A1…Set�addr�for�data-retrieval8‰MOVE.L„A1,RARTRVAD(A5)…subroutine�to�read-FIFO�routine.‰CLR.B…RAINSTR(A5)‰CLR.B…RAJMPRRG(A5)0‰MOVE†#16,D2ŽInit�the�channel�user�ptrs‚(2�bytes,‰LEA‡RACHNUSR(A5),A1…each--for�32�channels).ARAINLP4‚MOVE.L„#$F000F000,(A1)+„Set�channel�user�ptrs�to�$F000�to&*¦indicate�channels�can't�be�used�yet.‰SUBQ†#1,D2�Done?‰BGT‡RAINLP4�No--do�next.=‰MOVE.L„RARDLADR(A5),A1…Yes.‚Set�address�of�entry�in�RARADLST*¦for�this�RAD�in�A1..‰MOVE†#RAUNINIT,RARDSTAT(A1)ˆSet�RAD�status�to)*¦"uninitialized".‚(The�RAD�board�will�be'*¦initialized�upon�the�1st�user�request*¦for�this�RAD.)‰CLR.L…D1ˆSet�D1�to�zero.9‰ADDQ.L„#RACHNLST,A1ˆSet�ptr�to�1st�channel�for�this�RAD.?‰MOVE.L„#8*RACHNLLG,D2„Init�D2�to�be�used�as�a�channel�counter.1*œ(Set�D2�to:‚32�*�RACHNLLG�/�4,�since�we�will�be0*�initializing�the�32�channel�entries�4�bytes�at *�a�time.)HRAINLP1‚MOVE.L„D1,(A1)+‚Init�channel�data�for�this�RAD�in�RARADLST�to�0.‰SUBQ†#1,D2…All�done?$‰BHI‡RAINLP1ƒNo--go�do�next�channel.RAINRET‚RTS‘Return.*;RAERRXS‚EQU‡*‰SOMETHING�IS�WRONG!!!‚This�routine�was�called#*¦more�times�than�there�are�RADs�in*¦the�system!!!*;‰MOVE.B„#RASYSERR,RAINSTR(A5)‰Set�a�flag�in�CCB�to�indicate&*¦that�this�RAD�cannot�be�used--due�to%*¦a�SYSGEN�error,�there�is�not�enough'*¦room�in�the�RAD�table�area�to�include *¦this�RAD.‰BRA‡RAINRETƒReturn‰PAGEJ***************************************************************************%*ˆTHIS�IS�THE�COMMAND�SERVICE�ROUTINE**ƒENTRY:‚JSR�FROM�CMR�HANDLER**‹A2�-�PHYSICAL�ADDRESS�OF�PARAMETER�BLOCK*‹A5�-�PHYSICAL�ADDRESS�OF�CCB,*‹A6�-�PHYSICAL�ADDRESS�OF�ATTACHED�TASK�TCB*5*ƒEXIT:‚RTS�-�PARAMETER�BLOCK�VALIDATION�STATUS�IN�D0**ƒREGISTERS�USED:ƒ01234567 *”D******** *”A**P**PP**”A3�=�COMMAND�PACKET�POINTER*”A6�=�REQUESTOR�TCB�ADDRESS***ƒCODE�IS�RE-ENTRANT*J*************************************************************************** RADCMD„EQU„*-‰TST.B…XIOSCD(A2)ŠIs�the�CMR�cmd�subcode�=�0?‰BEQ.S…IOH01110ŒYes.9‰MOVE.B„#RAERR9,D7ŠNo--error--set�"illegal�command"�error,‰BSR‡IOHERCHKŒcode�and�go�make�error�return.*1* CHECK FOR COMMAND PACKET WITHIN TASK BOUNDARIES*CIOH01110‚MOVE.L�XIOUID(A2),CCBCID(A5)�SAVE�CMR�PARAM�BLOCK�ID�(DCB) ŠCLR.L‚D5,ŠMOVE.L�XIOCPK(A2),D6†ADDR�OF�COMMAND�PACKET)ŠMOVEƒXIOPLN(A2),D5†LENGTH�OF�COMMAND�PKT*ŠMOVE.L�CCBTASKA(A5),A1„SET�UP�TCB�POINTER ŠBSR„IOHADRCKŠBRA.S‚IOH01160‹GOOD�RETURNŠNOP—BAD�LENGTH�RETURN%ŠMOVE.B�#XSTBLN,D7‰BAD�ADDRESS�RETURN ŠBSR„IOHERCHK5IOH01160‚MOVE.L�D6,A3ŽCOMMAND�PACKET�PHYSICAL�ADDRESS*0* INSURE THAT COMMAND PACKET IS ON EVEN BOUNDARY* ŠBTSTƒ#0,D6ŠBEQ.S„RACOMAND6ŠMOVE.B�#XSTBLN,D7‰BAD�COMMAND�PACKET�ADDR�(ODD�BNDRY) ŠBSR„IOHERCHK**F************************************************************************ˆCommand�Processor*2*’User's�command�is�processed�here.‚A�check�on�the1*’desired�RAD's�status�is�made,�and�if�the�status0*’is�"good",�the�command�processor�will�call�the/*’appropriate�subroutine�to�handle�the�command.*F***********************************************************************RACOMAND�EQU‡**7‰CLR‡RACMDERR(A3)ˆClear�error�return�location�in�user's)*¦cmd�param�table�(used�later�as�a�flag).4‰CMP.B…#RASYSERR,RAINSTR(A5)‰Is�this�a�non-available*¦RAD�(due�to�SYSGEN�error)?-‰BEQ‡RASKIPITŒYes--make�error�return�to�user.-‰BSR‡RAFNDUSRŒNo.‚Find�this� user�in�RAUSRLST.7‰CMP.L…#RAABORTD,D0ˆWas�this�RAD�aborted�since�the�last*¦time�this�user�called?3‰BEQ‡RACMDRETŒYes--make�error�return�(D0�is�already *¦set�up).*;*’No.‚Data�in�D0�and�D1�will�be�used�later�in�this�routine.*9‰MOVE†RAREQCMD(A3),D2…Store�requested�command�code�in�D2.*‰CLR.L…D3’Init�D3,�which�will�be�offset�in*¦'RAJMPTBL'�for�this�command.5‰LEA‡RACMDTBL(PC),A4…Set�A4�to�addr�of�start�of�table*¦of�"legal"�command�codes.=RACMDLUP�CMP.B…(A4),D2�Does�requested�command�code�match�this*¦table�entry?6‰BEQ.S…RAGOTCMDŒYes--continue�processing�this�command.‰CMP.B…#$FF,(A4)+ŠEnd�of�table?*‰BEQ.S…RANOSUCHŒYes--illegal�command�code.-‰ADDQ†#4,D3�Set�jump�table�ptr�to�next�entry.+‰BRA‡RACMDLUPŒGo�back�and�check�next�entry.?RANOSUCH�MOVE.L„#RAERR9,D0ŠSet�error�return�to�"illegal�command‰BRA‡RACMDRETŒcode"�and�return.ARAGOTCMD�MOVE.L„RARDLADR(A5),A1…Put�addr�of�entry�for�this�RAD�in*¦'RARADLST'�into�A1.4RACMD0ƒCMPI†#RASTBAD,RARDSTAT(A1)‰Is�RAD�marked�bad?‰BNE.S…RACMD1ŽNo.-‰MOVE.L„#RAERR1,D0ŠYes--set�D0�to�error�code.‰BRA.S…RACMDRETŒGo�return.=RACMD1ƒCMPI†#RAUNINIT,RARDSTAT(A1)ˆIs�this�RAD�uninitialized?‰BNE.S…RACMD2ŽNo.$‰BSR‡RAINITRDŒYes--go�initialize�it.‰BRA‡RACMD0ŽNow�try�again.BRACMD2ƒCMP‡#RASTDOIN,RARDSTAT(A1)‚Is�RAD�doing�initialization�now?*‰BEQ.S…RACMD3ŽYes--make�"RAD�busy"�return.6‰CMPI.B„#RAOPNCMD,D2ˆAt�this�point,�the�RAD�must�be�in%*¦working�condition.‚Is�the�requested*¦command�an�"open"?+‰BEQ.S…RADOITŽYes--go�do�"open"�processing.8‰CMPI.B„#RACLSCMD,D2ˆIs�the�requested�command�a�"close"?,‰BEQ.S…RADOITŽYes--go�do�"close"�processing..‰CMPI.B„#RASTPCMD,D2ˆIs�this�a�"stop"�command?‰BEQ.S…RADOIT2�Yes--go�do�it.0‰CMPI.B„#RAABTCMD,D2ˆIs�this�an�"abort"�command?‰BEQ.S…RADOIT2�Yes--go�do�it./‰CMP‡#RASTOK,RARDSTAT(A1)‚No.‚Is�RAD�ready�now?'‰BEQ.S…RADOCMD�Yes--go�process�command.6RACMD3ƒMOVE.L„#RAERR2,D0ŠNo--set�error�code�to�"busy".‰BRA.S…RACMDRETŒGo�return.ARACMD4ƒMOVE.L„#RAUSRERR,D0ˆSet�error�flag�to�indicate�user�is�not*¦set�up�to�use�this�RAD.‰BRA.S…RACMDRETŒGo�return.*4RADOCMD‚EQU‡*“At�this�point,�must�be�a�command�which)*¦actually�uses�the�RAD�board,�so�set�the*¦RAD�status�to�busy.*8*’D0�and�D1�still�contain�data�from�RAFNDUSR�call�above.*)‰TST.L…D0’Is�user�set�up�to�use�this�RAD?‰BNE‡RACMD4ŽNo--error.9‰MOVE†D1,RARDSTAT(A1)…Set�RAD�status�to�user�ptr�for�this*¦user�to�indicate�RAD�is�busy.:‰MOVE†#1,RACMDERR(A3)…Set�cmd�error�code�to�1�as�a�flag�to%*¦indicate�that�this�cmd�uses�the�RAD%*¦board�and�set�the�status�to�"busy".3RADOIT2‚MOVE.L„A6,RAUSRTCB(A5)…Store�addr�of�user's*¦TCB�in�CCB�for�future�use. RADOITƒEQU‡*8‰LEA‡RAINSTBL(PC),A4…Put�start�addr�of�interrupt�"instr-*¦uction"�table.1‰MOVE.L„D3,D0�Get�offset�into�this�table�for�this‰ASR.L…#2,D0�command.?‰MOVE.B„(A4,D0),RAINSTR(A5)�Store�"instruction"�flag�in�CCB�for*¦use�when�interrupt�comes�in.:‰LEA‡RAJMPTBL(PC),A4…Load�addr�of�start�of�jump�table�into"*¦A4.‚D3�still�has�offset�for�this#*¦command�code�into�the�jump�table.%*¦A3�contains�addr�of�command�packet.1‰JSR‡(A4,D3)�Go�to�command-processing�routine�for(*¦this�command.‚(NOTE:�D1�still�contains*¦user�ptr�for�this�user.)6‰TST‡RACMDERR(A3)ˆDid�this�cmd�set�the�RAD�status�flag *¦to�"busy"?‰BEQ.S…RACMDRETŒNo--go�return. ‰TST‡D0’Yes.‚Was�there�an�error?‰BEQ.S…RACMDRETŒNo--go�return.,‰BSR‡RACLRSTAŒYes--go�clear�RAD�status�flag.*ARACMDRET�MOVE†D0,RACMDERR(A3)…Put�error�return�code�in�user's�cmd*¦param�table.!‰RTS›Return�from�command�handler.*?RASKIPIT�MOVE.L„#RASYSERR,D0ˆSet�D0�to�indicate�"can't�use�this*¦RAD"�(due�to�SYSGEN�error).‰BRA‡RACMDRETŒReturn�to�user.*D*-------------------------------------------------------------------D*ˆCommand�table,�jump�table,�and�"interrupt�instruction"�flag�table.2*’(Entries�in�these�three�tables�must�correspond.)*9RAJMPTBL�BRA.L…RARADSTPŒJump�table�--�all�entries�must�be6‰BRA.L…RARADLODŒlong�branches�to�appropriate�routines.‰BRA.L…RARADDMP‰BRA.L…RARADJMP ‰BRA.L…RARADTSTŒ(5th�entry)‰BRA.L…RARADEXT‰BRA.L…RARADSET‰BRA.L…RARADSCN‰BRA.L…RARADATO‰BRA.L…RARADCALŒ(10th�entry)‰BRA.L…RARADOPN‰BRA.L…RARADCLS‰BRA.L…RARADXEQ‰BRA.L…RARADABT‰BRA.L…RARADHISŒ(15th�entry)**--------------------------*4RACMDTBL�DC.B†RASTPCMDŒTable�of�legal�command�codes.2‰DC.B†RALODCMDŒEach�entry�is�one�byte�long;‚end�of4‰DC.B†RADMPCMDŒtable�is�indicated�by�$FF,�which�must.‰DC.B†RAJMPCMDŒNOT�be�a�valid�code,�of�course.‰DC.B†RATSTCMDŒ(5th�entry)‰DC.B†RAEXTCMD‰DC.B†RASETCMD‰DC.B†RASCNCMD‰DC.B†RAATOCMD‰DC.B†RACALCMDŒ(10th�entry)‰DC.B†RAOPNCMD‰DC.B†RACLSCMD‰DC.B†RAXEQCMD‰DC.B†RAABTCMD‰DC.B†RAHISCMDŒ(15th�entry)‰DC.B†$FF‘End�of�table.**----------------------------*7RAINSTBL�DC.B†1‰Table�of�"instruction"�flags�which�tell-‰DC.B†1‰the�driver�what�is�to�be�done�when�an-‰DC.B†1‰interrupt�comes�in�for�this�function.4‰DC.B†2‰(1�=�Put�"task"�into�READY�state;�i.e.,�turn)‰DC.B†1“cmd�handler�for�this�cmd�back�on.+‰DC.B†2Š2�=�Call�data-retrieval�subroutine.4‰DC.B†2Š0�=�Don't�do�anything�special--just�turn�off,‰DC.B†2“the�interrupt�and�return.‚(Shouldn't#‰DC.B†2“get�an�interrupt�on�these.)‰DC.B†1‰(10th�entry)‰DC.B†0‰DC.B†1‰DC.B†2‰DC.B†1‰DC.B†0‰(15th�entry)*‰DSˆ0‰(Set�PC�to�even�address.)‰PAGE** ERROR ROUTINE*IOHERCHK‚EQU„* ŠCLR.L‚D0ŠMOVE.B�D7,D0ŽVALIDATION�STATUS2ŠMOVE.L�(A7)+,CCBERAD1(A5)�SAVE�DBUG�ERROR�ADDRESSŠBRA†RACMDRET‰GET�OUT�OF�HEREŠPAGE;************************************************************$*ˆSubroutine�to�handle�RADOPN�calls.*3*’This�routine�"opens"�the�desired�channels�for�use*’by�this�user.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P*;***********************************************************RARADOPN�EQU‡*8‰BSR‡RAFNDUSR‚Check�user�list�to�see�if�there�already�is*¦and�entry�for�this�user-RAD*¦combination�in�RAUSRLST.6‰MOVE.L„RAD1TBL,A1ŠSet�A1�to�start�addr�of�table�area.‰TST‡D0ˆIs�there�an�entry?(‰BEQ.S…RAOPGOT1‚Yes--use�the�same�entry.+‰CLR.L…D2ˆNo--put�this�comb.�into�RAUSRLST.7‰MOVE†RAUSRLNX(A1),D2…Put�next-avail�entry�ptr�into�D2.4‰CMP‡#$FFFF,D2‹Is�there�an�available�RAUSRLST�entry?‰BEQ‡RAOPNORMŒNo--error.***¦Yes--calculate�addr�of�next�avail�entry.5‰MOVE.L„D2,D1�Store�next�avail�entry�#�for�later�use.*‰MULU†#RAULNG,D2ŠMultiply�by�entry�length.9‰LEA‡RAUSRLST(A1),A4…Load�start�addr�of�RAUSRLST�into�A4.2‰ADDA.L„D2,A4�Set�A4�to�start�addr�of�avail�entry.:‰MOVE†RAURADID(A4),RAUSRLNX(A1)…Move�ptr�to�the�next�avail(*¦entry�(which�was�stored�in�the�1st�two'*¦bytes�of�the�RAD-ID�field�of�RAUSRLST#*¦entry)�into�header�of�table�area.8‰MOVE.L„TCBNAME(A6),RAUUSRNO(A4)†Store�user�#�and�RAD-ID6‰MOVE.L„TCBSESSN(A6),RAUUSRNO+4(A4)ƒinto�this�entry�in*‰MOVE.L„CCBMNEM(A5),RAURADID(A4)†RAUSRLST.>RAOPGOT1�EQU‡*‰At�this�point,�D1�contains�the�ptr�to�the�entry*¦for�this�user�in�RAUSRLST.‚A3"*¦contains�addr�of�command�packet.:‰MOVE†#RAUNORET,D0ˆInit�D0�to�error�code�for�"user�has�not$*¦specified�error-reporting�option"./‰MOVE.L„D1,D3�Set�D3�to�user�ptr�for�this�user.9‰MULU†#RAULNG,D3ŠMultiply�by�length�of�an�RAUSRLST�entry.6‰MOVE.L„RAD1TBL,A1ŠSet�A1�to�start�addr�of�table�area.8‰LEA‡RAUSRLST(A1),A1…Put�start�addr�of�RAUSRLST�into�A1.4‰ADD.L…D3,A1�A1�now�contains�the�addr�of�this�user's*¦entry�in�RAUSRLST.:‰TST‡RAUEROPT(A1)ˆHas�error-reporting�option�for�this�user‰BEQ.S…RAOP2�been�set?‚No. ‰CLR.L…D0’Yes--clear�error�flag.ARAOP2„MOVE†RACMDPRM(A3),D2…Put�#�chan's�(from�param�table)�in�D2."‰BNE.S…RAOP3�If�not�0,�then�go�on.:‰MOVE.L„#RAERR4,D0ŠSet�D0�to�"parameter-table-error"�code.‰BRA‡RAOPRET�Go�return.@RAOP3„LEA‡RACMDPRM+2(A3),A4ƒSet�A4�to�start�addr�of�chan�data�in*¦command�param�table./RAOPLUP1�CLR.L…D3’Put�requested�chan�#�into�D3.‰MOVE.B„1(A4), D3‰CMPI.B„#$1F,D3�Valid�chan�#?‰BLS.S…RAOP4�Yes.5‰CMP.B…#$FF,D3�No--is�this�the�error-reporting�option*¦specification?6‰BNE‡RAOPERR1ŒNo--invalid�chan�#.�Go�to�error�routine.+‰MOVE†2(A4),D4ŒYes.‚Check�the�options�flag.%‰AND.L…#7,D4�Are�any�option�bits�set?(‰BEQ‡RAOPERR1ŒNo--no�options�set--error. ‰CLR.L…D0’Yes--clear�error�flag.‰BRA.S…RAOPOKX�Do�next�chan.3RAOP4„ASL‡#1,D3�Double�chan�#�to�be�used�as�offset.8‰CMPI†#$FFFF,RACHNUSR(A5,D3)ˆCheck�the�user�ptr�for�this)*¤chan�(in�CCB).‚Is�this�chan�unassigned?‰BEQ.S…RAOPOK1�Yes--it's�ok.?‰CMP‡RACHNUSR(A5,D3),D1‚No.‚Is�it�already�"owned"�by�this�user?3‰BNE.S…RAOPERR2ŒNo--this�chan�belongs�to�some�other*¦user.‚Go�to�error�routine.4‰MOVE.B„#1,(A4)�Yes--set�upper�byte�of�chan�#�in�cmd(*¦param�table�to�1�to�indicate�this�chan#*¦was�already�"owned"�by�this�user.'*¦(This�will�be�used�if�an�error�occurs'*¦so�that�the�user�ptr�won't�be�reset.)HRAOPOK1‚MOVE†D1,RACHNUSR(A5,D3)‚Set�user�ptr�for�this�chan�to�this�user.RAOPERR1�MOVE.L„#RAOPILL,D0‰Set�D0�to�indicate�illegal�chan�#.0‰BRA.S…RAOPERR3ŒGo�reset�user�ptrs.�for�previous*¦channels�in�cmd�param�list.CRAOPERR2�MOVE.L„#RAOPUNAV,D0ˆSet�D0�to�indicate�unavailable�chan�#.*1RAOPERR3�EQU‡*“Clear�any�user�ptrs�which�were�set'*¦while�processing�this�call�before�the*¦error�was�detected.9‰LEA‡RACMDPRM+2(A3),A4ƒSet�A4�to�start�of�chan�#'s�in�cmd *¦param�list.9‰MOVE†RACMDPRM(A3),D4…Store�#�of�chans�in�cmd�param�list.7RAOPERLP�CMP‡D2,D4�Have�we�gone�thru�all�the�entries�we(*¦went�thru�before?‚(Quit�when�we�get�to'*¦the�same�chan�#�we�got�the�error�on.)%‰BEQ‡RAOPRET�Yes--that's�all--return.#‰SUBQ†#1,D4�No--dec�count�of�chans.<‰TST.B…(A4)†Was�this�chan�assigned�to�user�before�this�call?(‰BEQ.S…RAOPERR4‚No--must�clear�user�ptr.;‰CLR.B…(A4)†Yes--leave�assignment�alone.‚Just�clear�"flag"./‰BRA.S…RAOPERR5‚Set�up�to�do�next�chan�in�list./RAOPERR4�CLR.L…D3ˆClear�user�ptr�for�this�chan.$‰MOVE.B„1(A4),D3‚Put�chan�#�into�D3.:‰ASL‡#1,D3…Double�it�to�give�offset�into�chan�list�in�CCB.5‰MOVE†#$FFFF,RACHNUSR(A5,D3)ˆSet�this�chan�to�unused.GRAOPERR5�ADDA.L„#12,A4„Set�A4�to�addr�of�next�chan�#�in�cmd�param�list.'‰BRA‡RAOPERLP‚Go�back�and�do�next�chan.**?RAOPNORM�MOVE.L„#RAOPNOMO,D0ˆSet�D0�to�indicate�no�room�for�any*¦more�user-RAD�combinations.‰BRA‡RAOPRET�Return.*‰PAGEK****************************************************************************)*ˆSubroutine�to�initialize�the�RAD�board.9*’(Sends�a�DUMP�command�to �RAD�and�checks�for�completion.3*’If�RAD�responds�correctly,�sets�chan�user�ptrs�to5*’"available"�status�and�sets�RAD�status�to�"ready".)*,*’Called�from�the�command�processor�routine.*7*ˆUpon�entry:‰A1�=�addr�of�this�RAD's�entry�in�RARADLST*œA5�=�CCB�addr**ˆUpon�return:**œ0�1�2�3�4�5�6�7*˜D:‚P�P�P�P�*�*�*�**˜A:‚*�P�P�P�*�P�P**K***************************************************************************RAINITRD�EQU‡*-‰MOVEM.LƒD0-D3,-(A7)‰Store�register�contents.;‰MOVE†#RASTDOIN,RARDSTAT(A1)‚Set�RAD�status�to�"busy--doing*¦initialization".6‰MOVE†#RAINNTRY,D4ˆSet�D4�to�max�#�of�times�to�try�for$*¦a�successful�response�from�the�RAD"*¦before�declaring�the�RAD�"dead".ARAINRD2‚MOVE.L„RASHRAD(A5),A4†Set�A4�to�start�addr�of�shared-RAM.=‰BTST.B„#7,RAXSTAT(A4)†Is�RAD�done�with�power�up�routine�yet?6‰BNE.S…RAINRDEDŒNo--should�have�been,�something�wrong.=‰MOVE.B„#RAPARAM/2,RAPRMPTR(A4)‡Yes.‚Set�param�ptr�in�shared-&*¦RAM�to�offset�in�shared-RAM�to�param%*¦area�(using�RAD-addressing�offset).8‰CLR.B…RAINTMSK(A4)ˆSet�interrupt�mask�to�no�interrupts.<‰MOVE.B„#RADMPCMD,RACMDBYT(A4)ˆPut�DUMP�command�into�command)*¦byte�in�shared-RAM.‚This�will�start�the*¦"RAD-initialize"�dump.6‰BSR.S…RAWAITŽWait�for�10�millisec�before�checking�for*¦response�from�RAD.2‰CMPI.B„#$81,RACSTAT(A4)„Is�initial�dump�complete?$‰BNE.S…RAINRDEDŒNo--something�wrong.,‰MOVEP.LƒRAPARAM(A4),D3†Yes.‚Check�response.8‰CMP.L…#RABNGRAD,D3ˆIs�dump�ok�(i.e.,�was�first�longword*¦correct--should�be�"!RAD")?$‰BNE.S…RAINRDEDŒNo--something�wrong.:‰MOVE.B„RAPARAM+8(A4),RAJMPRRG(A5)ˆYes--store�RAD�"jumper"*¦data�from�dump�in�CCB�loc.(‰MOVE.L„#16,D3ŽSet�counter�for�channels.@‰BTST.B„#5,RAJMPRRG(A5)…Is�RAD�board�jumpered�for�16�chan�or�32?‰BNE.S…RAINRD3�16�channels.3‰MOVE.L„#32,D3Ž32�channels--set�chan�counter�to�32.CRAINRD3‚LEA‡RACHNUSR(A5),A4…Put�start�addr�of�chan�user�ptrs�in�A4.GRAINRDLP�MOVE.L„#$FFFFFFFF,(A4)+„Set�chan�ptr�to�"unused"�(2�chans�at�a‰SUBQ†#2,D3�time).‚All�done?‰BGT‡RAINRDLPŒNo--go�do�next.B‰MOVE†#RASTOK,RARDSTAT(A1)�Yes--set�RAD�status�to�ok�(and�unused).7RAINRDRT�MOVEM.Lƒ(A7)+,D0-D3‰Restore�register�contents. ‰RTS›Return.**:RAINRDED�SUBQ†#1,D4�RAD�did�not�respond�correctly.‚Have�we*¦tried�enough�times?*‰BLE.S…RAINRBADŒYes--go�mark�this�RAD�bad.(‰BSR.S…RAWAITŽNo--delay�for�10�millisec.‰BRA‡RAINRD2�Go�try�it�again.9RAINRBAD�MOVE†#RASTBAD,RARDSTAT(A1)‰RAD�is�not�responding&*¦correctly--set�RAD�status�to�"dead".‰BRA‡RAINRDRTŒReturn.*G* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =*.RAWAITƒEQU‡*‰Routine�to�delay�10�milliseconds.*-‰MOVEM.LƒD2/A1,-(A7)‰Store�register�contents.7‰MOVE.L„#RANREQ,D3ŠSet�D3�to�max�#�of�times�to�"request%*¦periodic�activation"�unsuccessfully&*¦before�giving�up�and�just�returning.ARAWAIT1‚LEA‡RADLAY(PC),A0‡Set�up�for�periodic�activation�routine.%*¦RADLAY�is�the�routine�which�will�be)*¦turned�on�at�the�end�of�10�msec.,�which&*¦will,�in�turn,�reactivate�this�task.%‰MOVE.L„#10,A1ŽSet�delay�for�10�msec.2‰CLR.L…D1’Set�to�request�activation�one�time�only.:‰MOVE.B„CCBPPRIO(A5),D1…Set�priority�of�activation�to�same*¦priority�as�this�task�has.1‰MOVE.L„A6,D2�Put�TCB�addr�into�D2,�to�be�used�as *¦request�ID.2‰TR0$.RQPA‚,’Trap�to�"request�periodic�activation" *¦routine.%‰BRA.S…RAWAITOKŒRequest�was�accepted.0‰SUBQ†#1,D3�Request�was�denied.‚Have�we�tried�it*¦enough�times?#‰BGT‡RAWAIT1�No--try�request�again.,‰BRA.S…RAWAITRTŒYes--forget�it--just�return.9RAWAITOK�TR0$.PAUSE�,’Wait�for�10�msec.�to�be�up.‚(RADLAY(*¦will�then�be�"turned�on"�and�will�then*¦restart�this�task�here.)7RAWAITRT�MOVEM.L„(A7)+,D2/A1ˆRestore�register�contents. ‰RTS›Return.*M*‚=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=�=*2RADLAYƒEQU‡*“Routine�to�re-activate�driver�routine#*¦after�a�delay�made�using�"request*¦periodic�activation"�routine.*3‰MOVE.L„D1,A0�D1�contain s�TCB�addr�which�was�passed&*¦as�request�ID�to�periodic�activation%*¦routine.‚Put�it�in�A0�as�task�to�be*¦turned�back�on.*‰TR0$.READY�,’Put�task�into�"ready"�state.%‰RTE›Return�from�periodic�activation.**‰PAGE:***********************************************************$*ˆSubroutine�to�handle�RADSET�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**:**********************************************************3RARADSET�EQU‡*‰Routine�to�set�up�for�setpoint�scan.:‰MOVE†RACMDPRM+2(A3),D4ƒPut�#�of�non-setpoint�chans�in�D4.:‰LEA‡RACMDPRM+4(A3),A4ƒSet�A4�to�addr�of�start�of�chans�in*¦cmd�param�table. ‰CLR.L…D35‰MOVE†RAPARAM(A3),D3†Put�#�of�setpoint�chans�into�D3.0‰MULU†#6,D3�Calculate�#�bytes�for�setpt�chans�in*¦cmd�param�table.1‰ADD.L…D3,A4�Set�A4�to�start�addr�of�non-setpoint*¦chans�in�cmd�param�table.3‰MOVE.L„#2,D3�Set�D3�to�addr�increment�to�next�chan *¦in�list.6‰BSR‡RACHKCHNŒGo�check�these�chans�to�be�sure�they�are*¦"owned"�by�this�user.‰TST.L…D0’All�ok?3‰BNE.S…RASETRETŒNo,�error--make�error�return�(D0�is#*¦already�set�to�error�flag�value).*‰CLR.L…D4ˆPut�#�of�setpoint�chans�into�D4.‰MOVE†RACMDPRM(A3),D47‰LEA‡RACMDPRM+4(A3),A4ƒSet�A4�to�start�addr�of�setpoint*¦chans�in�cmd�param�list..‰MOVE.L„#6,D3�Set�D3�to�addr�increment�to�next*¦setpoint�chan�#�in�list.1‰BSR‡RACHKCHNŒGo�check�setpoint�chans�to�see�that*¦they�"belong"�to�this�user.‰TST.L…D0’Do�they?4‰BNE.S…RASETRETŒNo,�error--return�(D0�contains�error*¦code�already).8‰MULU†#3,D4…Multiply�by�3�to�give�#�of�words�of�setpoint*¦chan�data�in�param�table.3‰ADD‡RACMDPRM+2(A3),D4„Add�#�of�non-setpoint�chans./‰ADD‡#2,D4�Add�2�for�the�counts�to�give�total�#*¦of�words�in�param�table. ‰MOVE†D4,D3�Store�#�words�in�D3.'‰ADDQ†#1,D4�Add�1�for�#-of-words�count.;‰ASL‡#1,D4…Double�D4�to�give�#�bytes�to�move�to�shared-RAM.:‰LEA‡RACMDPRM-2(A3),A4…Set�A4�to�start�addr�of�params�(1st**¦2�bytes�are�garbage--will�be�set�later.)2‰BSR‡RAMOVPRMŒPut�the�param�table�into�shared-RAM.8‰MOVEP…D3,RAPARAM(A1)†Set�#�of�words�in�shared-RAM�param*¦table.2‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�in�shared-RAM.;‰MOVE.B„#5,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to)*¦interrupt�at�end�of�scan�or�end�of�cmd.8‰MOVE.B„#RASETCMD,RACMDCOD(A5)ˆStore�cmd�code�in�CCB�for *¦later�use.<‰MOVE.B„#RASETCMD,RACMDBYT(A1)ˆStore�cmd�code�in�cmd�byte�of,*£shared-RAM�to�start�execution�of�function./‰CLR.L…D0’Clear�D0�to�indicate�successful�start*¦of�setpoint�cmd.RASETRET�EQU‡**‰RTS›Return�and�wait�for�"done"�interrupt.‰PAGE K****************************************************************************$*ˆSubroutine�to�handle�RADSCN�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**K***************************************************************************RARADSCN�EQU‡****+‰MOVE†RACMDPRM+2(A3),D4ƒMove�#�chans�to�do.7‰LEA‡RACMDPRM+4(A3),A4ƒSet�A4�to�addr�of�chan�#s�in�cmd*¦param�table.0‰MOVE.L„#2,D3�Set�increment�value�to�next�chan�# *¦in�list.1‰BSR‡RACHKCHNŒCheck�requested�chan�#s�to�see�that!*¦they�all�"belong"�to�this�user.‰TST.L…D0’Do�they?2‰BNE.S…RASCNRETŒNo--make�error�return.‚(D0�already*¦contains�error�code.)1‰ADDQ†#2,D4�Add�2�to�give�#�of�words�to�move�into4‰ASL.L…#1,D4�param�area;�then�double�to�get�#�bytes.9‰LEA‡RACMDPRM(A3),A4…Set�A4�to�start�addr�of�params�to�be*¦put�into�shared-RAM./‰BSR‡RAMOVPRMŒMove�param�table�into�shared-RAM.3‰LEA‡RAPARAM(A1),A4†Set�A4�to�addr�in�shared-RAM�of*¦param�table.-‰MOVE†RACMDPRM+2(A3),D4ƒSet�D4�to�#�of�chans.&‰ADDQ†#1,D4� Add�1�to�give�#�of�params.6‰MOVE.B„(A4),4(A4)ŠRearrange�param�table�in�shared-RAM9‰MOVE.B„2(A4),6(A4)‰for�RAD�firmware.‚Put�#�params�first,&*¦followed�by�delay�length.‚(Note�that2‰MOVEP…D4,0(A4)Œ68000�addresses�shared-RAM�on�only*¦every�other�byte.);‰CLR.B…RACSTAT(A1)‰Clear�command�status�byte�in�shared-RAM.=‰MOVE.B„#5,RAINTMSK(A1)…Set�interrupt�mask�byte�in�shared-RAM!*¦for�interrupt�on�end-of-scan�or*¦end-of-command.C‰MOVE.B„#RASCNCMD,RACMDCOD(A5)‚Store�cmd�code�in�CCB�for�later�use.:‰MOVE.B„#RASCNCMD,RACMDBYT(A1)ˆSet�command�byte�in�shared-#*¦RAM�to�execute�scanning�function.8‰CLR.L…D0ˆClear�D0�to�indicate�successful�start�of�scan.RASCNRET�EQU‡**‰RTS‘Return�and�wait�for�"done"�interrupt.‰PAGEL*****************************************************************************$*ˆSubroutine�to�handle�RADEXT�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**L****************************************************************************?RARADEXT�EQU‡*‰Routine�to�set�up�for�external�trigger�function.1‰MOVE†RACMDPRM(A3),D4…Set�D4�to�#�of�chans�to�do.5‰LEA‡RACMDPRM+2(A3),A4ƒPut�addr�of�chan�#�list�in�A4.1‰MOVE.L„#2,D3�Set�D2�to�increment�to�next�chan�#.0‰BSR‡RACHKCHNŒCheck�chan�#s�to�see�that�they�all*¦"belong"�to�this�user.‰TST.L…D0’Do�they?3‰BNE.S…RAEXTRETŒNo,�make�error�return.‚(D0�contains*¦correct�error�code.),‰ADDQ†#1,D4�Add�one�to�#�of�chans�for�count..‰ASL.L…#1,D4�Double�to�give�#�bytes�to�be�sent *¦to�the�RAD.7‰LEA‡RACMDPRM(A3),A4…Set�A4�to�addr�of�params�to�be�put!*¦into�param�table�in�shared-RAM.*‰BSR‡RAMOVPRMŒMove�params�into�shared-RAM.7‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�byte�in�shared-RAM.;‰MOVE.B„#5,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to)*¦interrupt�on�end�of�scan�or�end�of�cmd.C‰MOVE.B„#RAEXTCMD,RACMDCOD(A5)‚Store�cmd�code�in�CCB�for�later�use.<‰MOVE.B„#RAEXTCMD,RACMDBYT(A1)‚Put�cmd�code�into�cmd�byte�in,*¤shared-RAM�to�start�execution�of�function.<‰CLR.L…D0ˆClear�D0�to�indicate�successful�start�of�function.RAEXTRET�EQU‡*#‰RTS›Return�and�wait�for�interrupt.‰PAGEN*******************************************************************************$*ˆSubroutine�to�handle�RADATO�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**N******************************************************************************5RARADATO�EQU‡*‰Routine�to�set�up�for�auto-range�scan.*‰MOVE†RACMDPRM(A3),D4…Move�#�chan�to�scan.5‰LEA‡RACMDPRM+2(A3),A4ƒPut�addr�of�chan�list�into�A4.6‰MOVE.L„#2,D3�Set�D3�to�addr�increment�to�next�chan�#.0‰BSR‡RACHKCHNŒCheck�chan�#s�to�see�that�they�all*¦"belong"�to�this�user.‰TST.L…D0’Do�they?3‰BNE.S…RAATORETŒNo,�make�error�return.‚(D0�contains*¦correct�error�code.)1‰ADDQ†#1,D4…Add�1�to�#�of�chans�to�include�count.;‰ASL‡#1,D4…Double�to�give�#�bytes�of�params�to�send�to�RAD.:‰LEA‡RACMDPRM(A3),A4…Set�A4�to�addr�of�params�to�be�moved.-‰BSR‡RAMOVPRMŒMove�param�table�to�shared-RAM.7‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�byte�in�shared-RAM.@‰MOVE.B„#5,RAINTMSK(A1)…Set�interrupt�mask�byte�in�shared-RAM�to)*¦interrupt�on�end�of�scan�or�end�of�cmd.C‰MOVE.B„#RAATOCMD,RACMDCOD(A5)‚Store�cmd�code�in�CCB�for�later�use.B‰MOVE.B„#RAATOCMD,RACMDBYT(A1)‚Set�cmd�byte�in�shared-RAM�to�start*¦auto-range�scanning�function.<‰CLR.L…D0ˆClear�D0�to�indicate�successful�start�of�function.RAATORET�EQU‡*#‰RTS›Return�and�wait�for�interrupt.‰PAGEN*******************************************************************************$*ˆSubroutine�to�handle�RADHIS�calls.*,*’Call ed�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**N******************************************************************************5RARADHIS�EQU‡*‰Routine�to�set�up�for�high-speed�scan.,‰CLR.L…D3’Set�up�to�check�chan�#�to�see�that(‰MOVE.L„#1,D4�it�"belongs"�to�this�user.5‰LEA‡RACMDPRM+4(A3),A4ƒSet�A4�to�addr�of�chan�"list".‰BSR‡RACHKCHNŒGo�check�chan�#./‰TST.L…D0’Does�this�chan�"belong"�to�this�user?2‰BNE.S…RAHISRETŒNo--make�error�return.‚(D0�already*¦contains�correct�error�code.);‰TST.L…RACMDPRM(A3)ˆIs�there�a�user-supplied�data-retrieval *¦subroutine?‰BEQ.S…RAHIS2ŽNo--error.?‰MOVE.L„RASHRAD(A5),A1†Yes--set�A1�to�start�addr�of�shared-RAM.:‰CLR.B…RAPARAM(A1)‰Move�$0001�into�1st�word�of�param�table'‰MOVE.B„#1,RAPARAM+2(A1)„in�shared-RAM.B‰MOVE.B„RACMDPRM+4(A3),RAPARAM+4(A1)‚Put�chan�#�to�be�scanned�into?‰MOVE.B„RACMDPRM+5(A3),RAPARAM+6(A1)‚param�table�in�shared-RAM.<‰MOVE.B„#RAPARAM/2,RAPRMPTR(A1)‡Put�offset�to�param�table�in)*¦shared-RAM�(6809�addressing)�into�param*¦ptr�in�shared-RAM.7‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�byte�in�shared-RAM.9‰CLR.B…RAINTMSK(A1)ˆSet�interrupt�mask�in�shared-RAM�to�0*¦to�indicate�no�interrupts.>‰MOVE.B„#1,RAOK2STO(A1)…Set�"ok�to�store�next�conversion"�flag*¦in�shared-RAM.8‰MOVE.B„#RAHISCMD,RACMDCOD(A5)ˆStore�cmd�code�in�CCB�for *¦later�use.<‰MOVE.B„#RAHISCMD,RACMDBYT(A1)ˆSet�cmd�byte�in�shared-RAM�to%*¦begin�execution�of�high-speed�scan.<‰MOVE.L„RACMDPRM(A3),A2…Go�to�user-supplied�data-acquisition=‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒroutine�after�storing�all�register.‰JSR‡(A2)�contents.‚This�routine�will�take�all(*¦the�desired�data�and�will�return�after(*¦having�stopped�the�high-speed�scanning *¦function.5‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestore�register�contents.4‰CLR.L…D0‡Clear�D0�indicate�a�successful�completion.RAHISRET�EQU‡* ‰RTS›Return..RAHIS2ƒMOVE.L„#RAERR4,D0ŠSet�error�code�in�D0.‰BRA‡RAHISRETŒGo�return.‰PAGEN*******************************************************************************$*ˆSubroutine�to�handle�RADJMP�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**N******************************************************************************>RARADJMP�EQU‡*‰Routine�to�set�up�for�jump-to-RAD-addr�command.9‰MOVE.B„#RAJMPCMD,D1ˆSet�D1�to�cmd�code�for�jump�command.=‰LEA‡RACMDPRM(A3),A4…Set�A4�to�start�addr�of�cmd�param�table.4‰BRA.S…RAXEQ2ŽGo�to�2nd�entry�in�RARADXEQ.‚(Jump�and)*¦execute-function�routines�have�the�same*¦set-up�for�running.)‰PAGEL*****************************************************************************$*ˆSubroutine�to�handle�RADXEQ�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**L****************************************************************************>RARADXEQ�EQU‡*‰Routine�to�set�up�for�execute-function�command.>‰MOVE.B„RACMDPRM+1(A3),D1…Set�D1�to�function�#�to�be�executed.5‰OR.B†#RAXEQBYT,D1ˆSet�the�"execute�function"�cmd�bit*¦to�get�the�command�code.<‰LEA‡RACMDPRM+2(A3),A4ƒSet�A4�to�addr�of�rest�of�the�params.*M*============================================================================K*=============‚RAXEQ2�is�a�2nd�entry�point�into�this�routine.‚=============>*=============…(It�is�used�by�RARADJMP�routine.)Œ=============*9RAXEQ2ƒTST.L…(A4)†Is�there�a�user-supplied�data-retrieval*¦subroutine�specified?2‰BEQ.S…RAXEQ3„No--use�read-F IFO�routine�(default).>‰MOVE.L„(A4),RARTRVAD(A5)ƒYes--store�addr�of�subroutine�in�CCB*¦for�later�use.BRAXEQ3ƒADDQ.L„#6,A4…Set�A4�to�start�of�params�to�be�passed�to�RAD.1‰MOVE†(A4),D4ƒSet�D4�to�#�of�params�to�be�passed.(‰ADDQ†#1,D4…Add�1�to�include�word�count.<‰ASL‡#1,D4…Double�to�give�#�bytes�to�be�moved�to�shared-RAM.9‰BSR‡RAMOVPRM‚Move�params�into�param�table�in�shared-RAM.9‰MOVE.B„-1(A4),RAINTMSK(A1)‹Set�interrupt�mask�in�shared-*¦RAM�as�specified�by�the�user.7‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�byte�in�shared-RAM.<‰MOVE.B„D1,RACMDCOD(A5)…Store�cmd�code�in�CCB�for�later�use.;‰MOVE.B„D1,RACMDBYT(A1)…Set�cmd�byte�in�shared-RAM�to�start*¦execution�of�desired�command.<‰CLR.L…D0ˆClear�D0�to�indicate�successful�start�of�function.‰RTS›Return�and�wait�for�data.‰PAGEM******************************************************************************$*ˆSubroutine�to�handle�RADSTP�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**M*****************************************************************************>RARADSTP�EQU‡*‰Routine�to�stop�this�user's�function�running�on*¦the�RAD�board.1‰BSR‡RAFNDUSR‚Find�this�user's�entry�in�RAUSRLST.%‰TST‡D0ˆIs�this�user/RAD�in�RAUSRLST?‰BNE.S…RASTPER1‚No--error.9‰MOVE.L„RARDLADR(A5),A1…Yes.‚Put�addr�of�this�RAD's�entry*¦in�RARADLST�into�A1.4‰CMP‡RARDSTAT(A1),D1…(D1�contains�user�ptr.)‚Is�this*¦user�using�this�RAD�now?‰BNE.S…RASTPER1ŒNo--error.;‰MOVE.L„RASHRAD(A5),A1†Yes.‚Set�A1�to�start�addr�of�shared-*¦RAM.7‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�byte�in�shared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to#*¦interrupt�when�command�completes.:‰MOVE.B„#RASTOPIT,RASTPBYT(A1)ˆSet�stop�byte�in�shared-RAM*¦to�stop�RAD�processing.&‰TR0$.PAUSEŠ,‰Wait�for�done�interrupt.K*>>>>>>>>>>>>>>>>‚Return�here�from�interrupt.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<<'‰CMP.B…#$84,RACSTAT(A1)„RAD�stopped�ok?‰BNE.S…RASTPERRŒNo--error.7‰MOVE.L„RARTRVAD(A5),A2…Yes.‚Get�addr�of�data-retrieval>‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒroutine�and�get�whatever�data�there‰JSR‡(A2)�is�in�shared-RAM.5‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestore�register�contents.7‰MOVE.L„RARDLADR(A5),A1…Put�addr�of�this�RAD's�entry�in*¦RARADLST�into�A1.4‰MOVE†#RASTOK,RARDSTAT(A1)ŠSet�RAD�status�to�unused./‰LEA‡RARDFIFO(PC),A1…Set�addr�of�data-retrieval4‰MOVE.L„A1,RARTRVAD(A5)…subroutine�to�RARDFIFO�addr./‰CLR.L…D0ˆClear�D0�to�indicate�successful�stop.RASTPRET�EQU‡*‰RTS‘Return�to�user.7RASTPERR�BSR‡RAEXERR�Set�"execution�error"�value�in�D0.‰BRA‡RASTPRETŒGo�return.>RASTPER1�MOVE.L„#RANOTUSR,D0ˆSet�"this�user�not�using�RAD�now"'‰BRA‡RASTPRETŒerror�flag�and�go�return.‰PAGEM******************************************************************************$*ˆSubroutine�to�handle�RADCLS�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**M*****************************************************************************:RARADCLS�EQU‡*‰Routine�to�close�RAD�from�use�by�this�user.?‰BSR‡RAFNDUSR‚Find�this�user's�entry�(w/�this�RAD)�in�RAUSRLST.,‰TST‡D0ˆWas�this�user/RAD�combination�found?‰BNE.S…RACLSERR‚No--error.<‰MOVE.L„RARDLADR(A5),A2…Yes--D1�contains�user�ptr.‚Set�A2�to'*¦addr�of�this�RAD's�entry�in�RARADLST.5‰CMP‡RARDSTAT(A2),D1…Is�this�user�using�this�RAD�now?‰BNE.S…RACLS2ŽNo.9‰MOVE.L„RASHRAD(A5),A1†Yes--stop�function�running�in�RAD.%*¦Set�A1�to�start�addr�of�shared-RAM.9‰MOVE†#1,RACMDERR(A3)…Set�error�return�location�in�user's&*¦cmd�table�to�indicate�that�this�user'*¦is�stopping�the�RAD�board,�so� the�RAD'*¦status�will�be�set�to�"ok"�when�done.2‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�in�shared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to*¦interrupt�at�end�of�cmd.:‰MOVE.B„#RASTOPIT,RASTPBYT(A1)ˆSet�stop�byte�in�shared-RAM*¦to�stop�RAD�processing.&‰TR0$.PAUSEŠ,‰Wait�fpr�done�interrupt.=*>>>>>>>>>>>> Return here from interrupt. <<<<<<<<<<<<<<<<<<<(‰CMP.B…#$84,RACSTAT(A1)„Did�RAD�stop�ok?0‰BNE.S…RACLSER2ŒNo--some�kind�of�error�occurred.4RACLS2ƒMOVE†#32,D2ŽYes.‚Close�all�this�user's�chans.5‰LEA‡RACHNUSR(A5),A1…Set�A1�to�addr�of�user�pointers.:RACLSLUP�CMP‡(A1),D1�Does�this�chan�"belong"�to�this�user? ‰BNE.S…RACLS3ŽNo--go�check�next.0‰MOVE†#$FFFF,(A1)‰Yes--set�this�chan�user�ptr�to*¦"unassigned"�status.9RACLS3ƒADD.L…#2,A1�Bump�A1�to�pt�to�next�chan's�user�ptr.‰SUBQ†#1,D2�All�done?‰BGT‡RACLSLUPŒNo--go�do�next.2‰MOVE†D1,D2�Yes.‚Store�user�ptr�for�this�user/RAD.:‰MULU†#RAULNG,D1ˆDelete�this�user/RAD�entry�from�RAUSRLST.0‰MOVE.L„RAD1TBL,A1ŠPut�addr�of�RAUSRLST�into�A2.‰LEA‡RAUSRLST(A1),A2<‰CLR.L…RAUUSRNO(A2,D1)…Clear�user�#,�RAD-ID,�and�user�status+‰CLR.L…RAUUSRNO+4(A2,D1)ƒfor�this�user/RAD.‰CLR.L…RAURADID(A2,D1)‰CLR‡RAUSTAT(A2,D1)A‰MOVE†RAUSRLNX(A1),RAURADID(A2,D1)‚Put�ptr�to�next�avail�entry�in,*¤RAUSRLST�into�1st�2�bytes�of�RAD-ID�field.=‰MOVE†D2,RAUSRLNX(A1)…Set�next-avail-entry�ptr�to�this�entry.0‰CLR.L…D0’Clear�D0�to�indicate�successful�close.RACLSRET�EQU‡*3‰TST‡RACMDERR(A3)ˆDid�this�user�stop�the�RAD�board?‰BEQ.S…RACLSRT2ŒNo--go�return.'‰BSR‡RACLRSTAŒYes--go�clear�RAD�status.RACLSRT2�EQU‡* ‰RTS›Return.BRACLSERR�MOVE.L„#RAUSRERR,D0ˆSet�"this�user�not�open�for�this�RAD"*¦error�flag�in�D0.‰BRA‡RACLSRETŒGo�return.6RACLSER2�BSR‡RAEXERR�Set�"execution�error"�flag�in�D0.‰BRA‡RACLSRET‚Go�return.‰PAGEM******************************************************************************$*ˆSubroutine�to�handle�RADDMP�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**M*****************************************************************************6RARADDMP�EQU‡*‰Routine�to�set�up�to�dump�RAD's�memory.3‰MOVE.L„RACMDPRM(A3),-(A7)‚Save�command�parameters.‰MOVE.L„RACMDPRM+4(A3),-(A7)RADMP1ƒCLR.L…D39‰MOVE†RACMDPRM+4(A3),D3ƒPut�#�words�to�be�dumped�into�D3.6‰CMP‡#RALODLNG,D3ˆIs�#�words�to�be�dumped�small�enough$*¦to�be�done�in�one�transfer�through *¦shared-RAM?‰BLS.S…RADMP2ŽYes--go�do�it.6‰MOVE†#RALODLNG,D3ˆNo--must�break�it�up�and�do�it�part'*¦at�a�time.‚Set�up�to�do�the�1st�part.@RADMP2ƒMOVE.L„RASHRAD(A5),A1†Set�A1�to�start�addr�of�shared-RAM.;‰MOVE.B„#RAPARAM/2,RAPRMPTR(A1)‡Set�up�param�ptr�in�shared-5‰CLR.B…RAPARAM(A1)‰RAM.‚Clear�1st�byte�of�param�table9‰MOVE.B„#2,RAPARAM+2(A1)„and�put�2�(#�of�words�of�params)!*¦into�param�table�in�shared-RAM.<‰MOVEP…D3,RAPARAM+8(A1)„Put�#�words�to�dump�into�param�table*¦in�shared-RAM.>‰MOVE.B„RACMDPRM+6(A3),RAPARAM+4(A1)‚Put�RAD�addr�to�dump�fromA‰MOVE.B„RACMDPRM+7(A3),RAPARAM+6(A1)‚into�shared-RAM�param�table.8‰MOVE.B„#RADMPCMD,RACMDCOD(A5)ˆStore�cmd�code�in�CCB�for *¦later�use.2‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�in�shared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to *¦interrupt�on�command�complete.9‰MOVE.B„#RADMPCMD,RACMDBYT(A1)ˆSet�cmd�code�in�shared-RAM*¦to�execute�dump�function.(‰TR0$.PAUSEŠ,‰Wait�for�"done"�interrupt.F*>>>>>>>>>>>>>‚Return�from�interrupt�here.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<:‰CMPI.B„#$80,RACSTAT(A1)„Check�completion�status�from�RAD.*‰BNE.S…RADMPERRŒStatus�is�not�good--error.'‰MOVE†D3,D4�Put�#�words�dumped�into�D4.$‰ASL‡#1,D4�Double�it�to�get�#�bytes.:‰MOVE.L„RACMDPRM(A3),A4…Put�addr�of�user's�buffer�into�A4.:‰LEA‡RAPARAM+12(A1),A2ƒPut�addr�in�shared-RAM�of�dump�data *¦into�A2.;RADMPLUP�MOVE.B„(A2),(A4)+ŠMove�a�byte�from�shared-RAM�into*¦user's�data�buffer.+‰ADD‡#2,A2�B ump�shared-RAM�ptr�to�next�byte*¦(68000�addressing).1‰SUBQ†#1,D4�Decrement�byte�count--any�more�to�do?‰BHI‡RADMPLUPŒYes--go�do�next.<‰SUB‡D3,RACMDPRM+4(A3)ƒNo.‚Subtract�#�words�dumped�this�time!*¦from�total�#�left�to�be�dumped.6‰BEQ.S…RADMP3ŽIf�zero,�finished�all�of�requested�dump.+‰ASL.L…#1,D3�Double�#�words�to�get�#�bytes.9‰ADD.L…D3,RACMDPRM(A3)…Add�#�bytes�to�user's�buffer�addr.<‰ADD‡D3,RACMDPRM+6(A3)ƒAdd�#�bytes�to�RAD�addr�to�dump�from.(‰BRA‡RADMP1ŽGo�back�and�do�next�piece�of*¦requested�dump./RADMP3ƒCLR.L…D0’Clear�D0�to�indicate�successful*¦completion�of�dump.‰BSR‡RACLRSTAŒClear�RAD�status.RADMPRET�EQU‡*3‰MOVE.L„(A7)+,RACMDPRM+4(A3)ŠRestore�user's�command+‰MOVE.L„(A7)+,RACMDPRM(A3)Œparameter�table. ‰RTS›Return.‰MOVE.B„RACMDPRM+6(A3),RAPARAM+4(A1)‚Put�addr�in�RAD�RAM�to�be;‰MOVE.B„RACMDPRM+7(A3),RAPARAM+6(A1)‚loaded�into�shared-RAM*¦param�table.+‰MOVE†D3,D4�Put�#�words�to�be�loaded�in�D4.&‰ADDQ†#1,D4�Add�1�to�give�#�of�params.2‰MOVEP…D4,RAPARAM(A1)†Put�#�params�into�shared-RAM*¦param�table.C‰MOVE.B„#RALODCMD,RACMDCOD(A5)‚Store�cmd�code�in�CCB�for�later�use.7‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�byte�in�shared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to *¦interrupt�on�command�complete.<‰MOVE.B„#RALODCMD,RACMDBYT(A1)‚Set�cmd�byte�in�shared-RAM�to*¦execute�load�function.(‰TR0$.PAUSEŠ,‰Wait�for�"done"�interrupt.K*>>>>>>>>>>>>>>>>‚Return�here�from�interrupt.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<<:‰CMPI.B„#$80,RACSTAT(A1)„Check�completion�status�from�RAD.*‰BNE.S…RALODER2ŒStatus�is�not�good--error.=‰SUB‡D3,RACMDPRM+4(A3)ƒSubtract�#�words�loaded�this�time�from*¦#�left�to�be�loaded.,‰BEQ.S…RALOD3ŽIf�no�more�left�to�do,�return./‰ASL.L…#1,D3�Double�to�get�#�bytes�just�loaded.6‰ADD.L…D3,RACMDPRM(A3)…Add�#�bytes�loaded�this�time�to7‰ADD‡D3,RACMDPRM+6(A3)ƒaddresses�in�cmd�param�table�for*¦ remaining�loading.'‰BRA‡RALOD1ŽGo�back�and�load�next�part.5RALOD3ƒCLR.L…D0’Clear�D0�to�indicate�successful�load.‰BSR‡RACLRSTAŒClear�RAD�status.RALODRET�EQU‡*3‰MOVE.L„(A7)+,RACMDPRM+4(A3)ŠRestore�user's�command+‰MOVE.L„(A7)+,RACMDPRM(A3)Œparameter�table. ‰RTS›Return.@RALODERR�MOVE.L„#RAERR4,D0ŠSet�D0�to�error�value�for�param�table*¦error.‰BRA‡RALODRETŒGo�return.8RALODER2�BSR‡RAEXERR�Set�D0�to�error�value�for�execution*¦error.‰BRA‡RALODRET‚Go�return.‰PAGEJ***************************************************************************$*ˆSubroutine�to�handle�RADCAL�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**K***************************************************************************>>>>>>>>>>>>>>‚Return�from�interrupt�here.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<-‰CMP.B…#$80,RACSTAT(A1)„Was�cmd�completed�ok?‰BNE.S…RACALERRŒNo--error.@‰MOVE.B„RANXT2GT(A1),D2…Yes--get�calibration�readings�from�FIFO.!*¦Put�next-to-get�offset�into�D2. ‰CLR.L…D5>>>>>>>>>>>>>>‚Return�from�interrupt�here.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<;‰MOVEP.LƒRATSTAT(A1),D0†Put�status�into�cmd�param�table�for)‰MOVE.L„D0,RACMDPRM+2(A3)†return�to�user./‰CMP.B…#$80,RACSTAT(A1)„Self-test�completed�ok?‰BEQ.S…RATST2ŽYes.-‰CMP.B…#$03,RACSTAT(A1)„No.‚Self-test�failed?%‰BNE.S…RATSTERRŒNo--some�other�error.8‰MOVE.L„#RATSTFAL,D0ˆSet�D0�to�"test�failed"�indication.4‰MOVE.L„RARDLADR(A5),A1…Set�the�RAD�status�to�"bad".‰MOVE†#RASTBAD,RARDSTAT(A1)RATSTRET�EQU‡* ‰RTS›Return-RATST2ƒCLR.L…D0’Set�D0�to�indicate�no�errors.‰BSR‡RACLRSTAŒClear�RAD�status.‰BRA‡RATSTRETŒGo�return.:RATSTERR�BSR‡RAEXERR�Set�D0�to�indicate�"execution�error".‰BRA‡RATSTRETŒGo�return.‰PAGEN*******************************************************************************$*ˆSubroutine�to�handle�RADABT�calls.*,*’Called�from�the�command�processor�routine.*#*ˆUpon�entry:‰A2�=�param�block�addr*œA3�=�command�packet�addr*œA5�=�CCB�addr*œA6�=�TCB�addr*2*ˆUpon�return:ˆD0�=�error�code�(=0,�if�successful)**œ0�1�2�3�4�5�6�7*˜D:‚*�*�*�*�*�*�*�**˜A:‚*�*�P�P�*�P�P**O*******************************************************************************=RARADABT�EQU‡*‰Routine�to�abort�whatever�the�RAD�is�doing�and$*¦close�all�chans�for�this�RAD.‚(All&*¦users�of�this�RAD�will�be�flagged�in'*¦RAUSRLST�so�they�can�be�"notified"�of"*¦the�abort�on�their�next�request.@‰MOVE.L„RARDLADR(A5),A1…Put�addr�of�this�RAD's�entry�in�RARADLST ‰CLR.L…D3=‰MOVE†RARDSTAT(A1),D3…Store�RAD�status�(which�is�the�user�ptr&*¦if�the�RAD�is�currently�being�used).*‰CMP‡#RASTOK,D3Šin�A1.‚Is�RAD�running�now?(‰BEQ.S…RAABT0ŽNo--don't�have�to�stop�it.#‰CMP‡#RASTBAD,D3‰Is�RAD�marked�bad?)‰BEQ.S…RAABT0ŽYes--don't�have�to�stop�it.#*¦No--RAD�must�be�running--stop�it.<‰MOVE.L„RASHRAD(A5),A1†Put�start�addr�of�shared-RAM�into�A1.2‰CLR.B…RACSTAT(A1)‰Clear�cmd�status�in�shared-RAM.;‰MOVE.B„#1,RAINTMSK(A1)…Set�interrupt�mask�in�shared-RAM�to *¦interrupt�when�RAD�is�stopped.:‰MOVE.B„#RASTOPIT,RASTPBYT(A1)ˆSet�stop�byte�in�shared-RAM*¦to�stop�RAD�processing.&‰TR0$.PAUSEŠ,‰Wait�for�done�interrupt.I*>>>>>>>>>>>>>>>‚Return�from�interrupt�here.‚<<<<<<<<<<<<<<<<<<<<<<<<<<<<6RAABT1ƒMOVE.L„RAD1TBL,A1ŠPut�addr�of�table�area�in�A1.6‰LEA‡RAUSRLST(A1),A2…Set�A2�to�start�addr�of�RAUSRLST.4‰MOVE†#32,D1ŽMust�set�all�chans�to�unused�status�and&*¦flag�all�users�of�this�RAD�to�inform'*¦them�of�the�abort�on�their�next�call.?‰LEA‡RACHNUSR(A5),A1‚Set�A1�to�start�of�user�ptrs�for�this�RAD.1RAABTLUP�CMP‡#$FFFF,(A1)‰Is�this�chan�unassigned?&‰BEQ.S…RAABT2ŽYes--go�on�to�next�chan.*‰CMP‡#$F000,(A1)‰Is�this�chan�unavailable?&‰BEQ.S…RAABT2ŽYes--go�on�to�next�chan.(‰CLR.L…D2’No--must�"unassign"�this�chan.!‰MOVE†(A1),D2�Put�user�ptr�in�D2.0‰MOVE†#$FFFF,(A1)‰Set�chan�to�unassigned�status.´�2¦3®8¶+¾4Æ4Î8Ö4ÞBæ/î1ö</‰CMP‡D2,D3�Does�this�chan�belong�to�the�current*¦user�of�this�RAD�(if�any)?#‰BEQ.S…RAABT2ŽYes--don't�flag�user.8‰MULU†#RAULNG,D2ŠMultiply�user�ptr�by�length�of�RAUSRLST+*¤entry�to�get�offset�to�this�user's�entry.<‰MOVE.B„#RAABTCOD,RAUSTAT(A2,D2)†Set�user�status�in�RAUSRLST#*¦to�abort�code�so�that�user�can�be%*¦notified�of�abort�on�his�next�call.2RAABT2ƒADD.L…#2,A1�Bump�A1�to�pt�to�next�user�ptr.‰SUBQ†#1,D1�All�chans�done?‰BGT‡RAABTLUPŒNo--go�do�next.=‰MOVE.L„#RAABTCOD,D0ˆYes--notify�c urrent�user�(if�any)�of�the‰BSR‡RANOTIFYŒabort.@‰MOVE.L„RARDLADR(A5),A1…Put�addr�of�this�RAD's�entry�in�RARADLST *¦into�A1.2‰MOVE†#RASTOK,RARDSTAT(A1)ŠSet�RAD�status�to�"ok".5‰MOVE.L„RASHRAD(A5),A1†Set�A1�to�start�of�shared-RAM.8‰CMP.B…#$84,RACSTAT(A1)„Yes.‚Did�the�RAD�stop�correctly?‰BNE.S…RAABTERRŒNo--error.3‰CLR.L…D0�Yes--set�D0�to�indicate�successful�abort.RAABTRET�EQU‡* ‰RTS›Return.@RAABT0ƒMOVE.L„RASHRAD(A5),A1†Set�A1�to�start�addr�of�shared-RAM.8‰MOVE.B„#$84,RACSTAT(A1)„Set�cmd�status�in�shared-RAM�to$*¦"successful�stop"�value�for�later.+‰BRA‡RAABT1ŽContinue�with�abort�processing.6RAABTERR�BSR‡RAEXERR�Execution�error�in�RAD.‚Set�D0�to *¦error�code.‰BRA.S…RAABTRETŒGo�return.‰PAGEK****************************************************************************=*ˆSubroutine�to�set�error�return�value�in�D0�for�unsuccessful*’function�execution.*+*ˆCalled�from�command-handling�subroutines.*2*ˆUpon�entry:ƒA1�=�addr�of�shared-RAM�for�this�RAD*K***************************************************************************ARAEXERR‚CMP.B…#$01,RACSTAT(A1)„Did�we�get�an�"illegal�cmd"�return*¦from�the�RAD?‰BNE.S…RAEXERR2ŒNo.-‰MOVE.L„#RAERR9,D0ŠYes--set�D0�to�error�code.‰BRA.S…RAEXERR9ŒGo�return.=RAEXERR2�MOVE.L„#RAEXERRV,D0ˆSet�D0�to�execution�error�value.RAEXERR9�RTS›Return‰PAGEM******************************************************************************>*ˆSubroutine�to�set�the�RAD�status�to�"ok"�and�reset�the�data-:*’retrieval-subroutine�address�to�the�address�of�RARDFIFO.*+*ˆCalled�from�command-handling�subroutines.**ˆUpon�entry:‰A5�=�CCB�address.*=*ˆUpon�exit:‚contents�of�register�A1�are�destroyed--all�other*œregisters�are�"untouched".*N******************************************************************************RACLRSTA�EQU‡**;‰LEA‡RARDFIFO(PC),A1…Put�addr�of�read-FIFO�routine�into�A1.=‰MOVE.L„A1,RARTRVAD(A5)…Store�it�in�data-retrieval-subroutine)*¦addr�loc�in�CCB.‚(This�is�the�"default"*¦data-retrieval�subroutine.)=‰MOVE.L„RARDLADR(A5),A1…Set�A1�to�addr�of�this�RAD's�entry�in *¦RARADLST.2‰MOVE†#RASTOK,RARDSTAT(A1)ŠSet�RAD�status�to�"ok". ‰RTS›Return.‰PAGEN*******************************************************************************,*ˆSubroutine�to�read�the�FIFO�in�shared-RAM.*(*ˆCalled�from�interrupt�service�routine.*3*’Upon�entry,�A1�contains�start�addr�of�shared-RAM.**•0�1�2�3�4�5�6�7*’D:�*ƒ*�*�*�*�* *’A:ƒP�*�**N******************************************************************************RARDFIFO�EQU‡*RAFILUP1�CLR.L…D29‰MOVE.B„RANXT2GT(A1),D2…Get�next-to-get�ptr�for�FIFO�from *°shared-RAM.0‰CLR.L…D6’Set�up�D6�to�contain�command�status�in=‰MOVE.B„RACSTAT(A1),D6†bits�8-15�for�later�use�in�queueing�an‰ASL.L…#8,D6�event.;‰ASL‡#1,D2…Double�next-to-get�ptr�to�get�actual�offset�from'*¦start�of�shared-RAM�(68K-addressing).4‰LEA‡(A1,D2),A2ŠGet�actual�addr�of�next�value�to�get*°and�store�it�in�A2.3‰CMPI.B„#$FF,(A2)‹Any�data�in�next-to-get�location?$‰BEQ‡RAFIFOMTŒNo--FIFO�is�now�empty.4‰MOVE.B„0(A2),D5‚Yes--find�out�what�to�do�with�data.1‰MOVE.B„D5,D3�Store�gain�and�chan�#�in�D5�and�D3.>‰AND.L…#$1F,D5ƒMask�off�gain,�leaving�just�the�channel�number.0‰MOVE.B„D5,D6�Move�chan�#�into�D6�for�later�use.7‰MULU†#RACHNLLG,D5ˆCalculate�offset�into�'RARADLST'�for*¦this�channel.5‰ADD.L…RARDLADR(A5),D5…Add�start-of-entry�address�(in*¦'RARADLST')�for�this�RAD.;‰ADD.L…#RACHNLST,D5ˆD5�now�contains�the�addr�of�the�options4‰MOVE.L„D5,A3�flag�for�this�channel.‚Put�addr�in�A3.*9*’========‚Pack�data�for�this�reading�into�D3.‚==========4‰MOVE.B„2(A2),D4ŒPut�flags�and�hi-data�byte�into�D4.‰ASL.L…#8,D3�Shift�data�in�D3.,‰MOVE.B„D4,D3�Put�flags�and�hi-data�into�D3.6‰ANDI.B„#$F0,D3�Mask�off�low�byte,�leaving�just�flags.&‰ASL.L…#8,D3�Shift�data�over�one�byte.2‰MOVE.B„D4,D3�Put�flags�and�hi-data�into�D3�again.8‰ANDI.B„#$0F,D3�Mask�off�low�byte,�leaving�just�hi-data.&‰ASL.L…#8,D3�Shift�data�over�one�byte.7‰MOVE.B„4(A2), D3ŒPut�lo-data�byte�into�D3.‚Now�all�data(*¦for�this�reading�has�been�put�into�the&*¦4�bytes�of�D3�in�the�correct�format.8‰MOVE.L„RACHNSTO-RACHNOPT(A3),A3†Put�storage-addr�in�A3.4‰MOVE.L„D3,(A3)�Store�data�in�loc�specified�by�user.+‰MOVE.B„#$FF,(A2)‹Set�FIFO�loc�to�"unused".=‰ADDQ.B„#3,RANXT2GT(A1)…Set�FIFO�next-to-get�ptr�to�next�data*°location�in�the�FIFO.3‰MOVE.B„RAFIFOND(A1),D4…Set�D4�to�end-of-FIFO�addr.7‰CMP.B…RANXT2GT(A1),D4…Are�we�past�the�end�of�the�FIFO?‰BHS.S…RAF1�No.?‰MOVE.B„RAFIFOST(A1),RANXT2GT(A1)…Yes--set�FIFO�next-to-get�ptr*°to�start-of-FIFO�ptr�value.6RAF1…MOVE.L„D5,A3�Reset�A3�to�addr�of�options�flag�for *¦this�chan.'‰MOVE†(A3),D0�Put�options�flag�into�D0.<‰BTST.L„#RASUBRBT,D0ˆIs�there�a�subroutine�to�be�called�when*¦there�is�data�for�this�chan?‰BEQ.S…RAF2�No.?‰MOVE.L„RACHNSUB-RACHNOPT(A3),A3†Yes,�put�addr�of�subr�into�A3.3‰MOVEM.LƒD1-D7/A0-A6,-(A7)ƒStore�register�contents.‰JSR‡(A3)�Jump�to�subroutine.5‰MOVEM.Lƒ(A7)+,D1-D7/A0-A6ƒRestore�register�contents.L*======================‚On�return�from�subroutine,�D0�will�be�set�for�either0*œqueue�event�or�wakeup�if�either�of�these�is�to-*œbe�done�after�the�subr.‚Else,�D0�will�be�0.=RAF2…BTST.L„#RAQUEBT,D0‰Are�we�to�queue�an�event�to�the�user?‰BEQ.S…RAF3�No.:‰MOVE.L„#RAEVNTHI,D2ˆYes--set�upper�half�of�D2�to�standard*¦event�data�(length�and�code).2‰MOVE†D6,D2�Put�command�status�and�chan�#�into�D2.=‰MOVE.L„CCBMNEM(A5),D3†Put�RAD-ID�into�2nd�longword�of�event.*‰BSR‡QEVENTŽGo�queue�an�event�to�the�user.$‰BRA.S…RAF9�All�done�with�this�chan.;RAF3…BTST.L„#RAWAKEBT,D0ˆAre�we�to�do�a�wakeup�of�the�user?(‰BEQ.S…RAF9�No--all�done�with�this�chan.#‰MOVE.L„A6,A0�Put�TCB�addr�into�A0.+‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒStore�registers.*‰TR0$.WAKEUP‰,‰Issue�a�wakeup�to�the�user.-‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestore�registers.9RAF9…BRA‡RAFILUP1‚Go�back�and�get�next�reading�from�FIFO.-RAFIFOMT�RTS‘RAD�FIFO�is�now�empty�--�return.‰PAGEK****************************************************************************/*ˆSubroutine�to�find�user's�entry�in�'RAUSRLST'*>*ˆCalled�from�command�processor�and�command-handling�routines.**’Upon�exit:ƒD0�=�error�flag*ŸD1�=�entry�#�for�this�user.**œAll�other�registers�used�will�have�their*œcontents�restored.*L****************************************************************************RAFNDUSR�EQU‡**3‰MOVEM.LƒD2-D4/A0-A1,-(A7)ƒStore�register�contents.4‰MOVE.L„RAD1TBL,A1ŠPut�addr�of�RAD�table�area�in�A1.1‰LEA‡RAUSRLST(A1),A0…Put�addr�of�user�list�in�A0.6‰MOVE.L„A1,D0�Set�D0�to�addr�of�RARADLST,�which�is�the1‰ADD‡RARADLAD(A1),D0…same�as�the�end�of�RAUSRLST.-‰CLR.L…D1’D1�will�be�a�"user�counter".‚(First*¦user�will�be�#�0.)7‰MOVE.L„TCBNAME(A6),D2†Put�user�task�name�and�session�#'‰MOVE.L„TCBSESSN(A6),D3…into�D2�and�D3.(‰MOVE.L„CCBMNEM(A5),D4†Put�RAD-ID�in�D4.4RAFNDLP‚CMP.L…RAUUSRNO(A0),D2…Does�this�entry�match?!‰BNE.S…RAFNXTŽNo--try�next�entry.‰CMP.L…RAUUSRNO+4(A0),D3ƒMaybe.‰BNE.S…RAFNXTŽNo--try�next.‰CMP.L…RAURADID(A0),D4…Maybe.‰BEQ.S…RAFGOTITŒYes.:RAFNXTƒADDA.L„#RAULNG,A0ŠDoesn't�match.‚Set�up�to�try�next0‰CMPA.L„D0,A0�entry.‚Are�there�any�more�entries?2‰BHS.S…RAFNOGOTŒNo--this�user�is�not�set�up�to�use!*¦this�RAD.‚Go�make�error�return.!‰ADDQ†#1,D1�Yes--inc�entry�count.*‰BRA‡RAFNDLP�Go�back�and�check�this�entry.*RAFNOGOT�MOVE.L„#RAERR3,D0ŠSet�error�code.‰BRA.S…RAFRETŽGo�return.)RAFGOTIT�EQU‡*“A0�contains�addr�of�entry;&*¦D1�contains�ptr�to�this�entry�(i.e., *¦entry�#).7‰CMP.B…#RAABTCOD,RAUSTAT(A0)‰Was�this�RAD�aborted�since*¦the�last�call�by�this�user?#‰BNE.S…RAFNDOK�No--everything's�ok.*B************‚Because�of�the�way�the�"abort"�flag�is�set�and�reset,G************‚the�following�code�will�only�be�executed�when�this�routineD************‚is�called�from�the�command�handler�on�the�first�call�by@************‚each�user�after�this�RAD�has�been�aborted�(RADABT).*3‰CLR.B…RAUSTAT(A0)‰Yes.‚Clear�the�"aborted"�flag�in*¦this�user's�status.8‰MOVE.L„#RAABORTD, D0ˆSet�error�code�to�"warning--RAD�was*¦aborted"�code.‰BRA.S…RAFRETŽGo�return. ************ ************/RAFNDOK‚CLR.L…D0’Clear�D0�to�indicate�no�error.;RAFRETƒMOVEM.Lƒ(A7)+,D2-D4/A0-A1ƒRestore�register�contents. ‰RTS›Return.‰PAGEL*****************************************************************************@*ˆSubroutine�to�move�parameters�into�shared-RAM�parameter�table.*+*’Called�from�command-handling�subroutines.*L*****************************************************************************2*’Upon�entry--ˆA4�=�addr�of�parameters�to�be�moved*¦D4�=�#�of�bytes�to�be�moved7*’(A4�and�D4�will�contain�the�same�as�above�upon�exit.)$*’Upon�exit:ŠA1�=�addr�of�shared-RAML*---------------------------------------------------------------------------RAMOVPRM�EQU‡*-‰MOVEM.LƒA4/D4,-(A7)‰Store�register�contents.<‰MOVE.L„RASHRAD(A5),A1†Put�start�addr�of�shared-RAM�into�A1.9‰LEA‡RAPARAM(A1),A0†Put�addr�of�param�table�in�shared-RAM *¦into�A0.RANTF2ƒBTST.L„#RAWAKEBT,D0ˆAre�we�supposed�to�issue�a�wake-up?‰BEQ.S…RANTFRETŒNo--go�return.8‰MOVEM.LƒD0-D7/A0-A6,-(A7)ƒYes--store�register�contents.*‰MOVE.L„A6,A0�Put�user's�TCB�addr�into�A0. ‰TR0$.WAKEUP‰,‰Go�issue�wake-up.-‰MOVEM.Lƒ(A7)+,D0-D7/A0-A6ƒRestore�registers.RANTFRET�EQU‡*0‰MOVEM.Lƒ(A7)+,D0-D3/A1-A2/A6ŠRestore�registers. ‰RTS›Return.‰PAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLING�TASKS�ADDRESS�SPACE.*#*�ENTRY:ƒD5‚-�NO.�OF�BYTES�TO�CHECK*ŠD6‚-�68000�ADDRESS�(LOGICAL)*ŠA1‚-�TCB�ADDRESS**#* REGISTERS USED: D0-D1,D3,D6/A0-A1**7*�EXIT:„D6�-�PHYSICAL�ADDRESS�OF�BUFFER�BASE�(IF�LEGAL)*ŠRETURN�TO�PC„FOR�GOOD�ADDRESS*”PC+2‚FOR�BAD�LENGTH*”PC+4‚FOR�BAD�ADDRESS**C*******************************************************************IOHADRCK‚EQU„*$ŠBTSTƒ#0,D6ŽMUST�BE�ON�WORD�BOUNDARY(ŠBNE.S‚IOHADR4ŒBRANCH�IF�BAD�BUFFER�BASE ŠTST.L‚D5.ŠBEQ.S‚IOHADR8ŒDON'T�GO�TO�LOGPHY�WITH�0�COUNT IOHADR2ƒEQU„*/ŠMOVE.L�TCBTST(A1),A0†ADDRESS�OF�TASK�SEG�TABLE ŠTR0$.LOGPHY&ŠBRA.S‚IOHADR8ŒBRANCH�FOR�GOOD�ADDRESS(ŠBRA.S‚IOHADR6ŒBRANCH�FOR�BAD�BYTE�COUNT'ŠTST.L‚D5‘WAS�AN�ENTRY�POINTER�RETURNED#ŠBEQ.S‚IOHADR4ŒBRANCH�IF�NO�-�ERROR'ŠTST.B‚7(A0,D5)‹IS�THIS�AN�MMIO�SEGMENTŠBNE.S‚IOHADR8ŒYES,�OKIOHADR4ƒADD.L‚#2,(A7)IOHADR6ƒADD.L‚#2,(A7) IOHADR8ƒRTSŠPAGEJ***************************************************************************F*�INTERRUPT�SERVICE�ROUTINE…<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*?*ƒPURPOSE:‚HANDLE�ACKNOWLEDGEMENTS�AND�MESSAGE�COMPLETIONS�FROM3*�THE�RAD1.‚OPERATES�AT�HARDWARE�INTERRUPT�PRIORITY<*�LEVEL�AS�A�SUBROUTINE�TO�THE�FIRST�LEVEL�INTERRUPT�HANDLER *�(IN�CMR).*4*ƒENTRY:‚JSR‚FROM�INTERRUPT�HANDLER�ROUTINE�(IN�CMR)*‹A0�=�WORK�REGISTER *‹A1�=�SELF*‹A5�=�CCB�ADDRESS*‹D0�=�WORK�REGISTER*/*ƒEXIT:‚RTS�-�BACK�TO�INTERRUPT�HANDLER�ROUTINE**ƒREGISTERS�USED:ƒ01234567 *”D******** *”A*****PP***ƒCODE�IS�RE-ENTRANT*F*---------------------------------------------------------------------**"RADISR„EQU„*’INTERRUPT�ENTRY�POINT.‰MOVEM.LƒD1-D7/A2-A4/A6,-(A7)…STORE�REGISTERS.*=‰MOVE.L„RAUSRTCB(A5),A6…Set�A6�to�addr�of�current�user's�TCB,(*¦which�was�stored�when�command�was�sent*¦to�this�RAD�board.7‰MOVEA.LƒRASHRAD(A5),A1†Put�addr�of�shared-RAM�into�A1.3‰MOVE.B„RAXSTAT(A1),D1†Put�status�from�RAD�into�D1.4‰AND.B…#RAINTBIT,D1ˆDid�this�RAD�send�the�interrupt?)‰BEQ‡RAINO�No.‚Return�and�check�next�RAD.8‰CMP.B…#RALVL4,CCBPPRIO(A5)ŠIs�this�a�level�4�interrupt?‰BNE.S…RAISR1ŽNo--level�3.**¦Yes--RAD�"died".8‰MOVE.L„CCBMNEM(A5),D0†Put�RAD-ID�from�this�CCB�into�D0.7‰SUB.L…#$0400,D0‹Subtract�to�get�RAD-ID�for�level�3�CCB(*¦which�corresponds�to�this�level�4�CCB.*0*�Search�CCB�chain�for�level�3�CCB�for�this�RAD.*+‰MOVE.L„A5,-(A7)ŒStore�addr�of�level�4�CCB.6‰MOVE.L„CCBHD,A5ŒStore�addr�of�1st�CCB�in�chain�in�A5.%RAISRLP‚CMP.L…#0,A5�End�of�CCB�chain?6‰BEQ.S…RAISRFALŒYes.‚Something�wrong--can't�find�level)*¦3�CCB�for�this�RAD.‚Oh�well,�forget�it!<‰CMP.L…CCBMNEM(A5),D0†Is�this�the�CCB�we�have�been�s earching#‰BEQ.S…RAISR0Žfor?ƒEUREKA!!!�It�is!0‰MOVE.L„CCBALL(A5),A5‡No--try�next�CCB�in�chain. ‰BRA‡RAISRLPFRAISR0ƒMOVE.L„RARDLADR(A5),A2…Put�addr�of�this�RAD's�entry�in�RARADLST *¦into�A2. ‰CLR.L…D3=‰MOVE†RARDSTAT(A2),D3…Store�RAD�status�(which�is�user�ptr�for*¦current�user,�if�any).4‰MOVE†#RASTBAD,RARDSTAT(A2)‰Set�RAD�status�to�"bad".(‰MOVE.L„#RAERR1,D0ŠSet�D0�to�error�code.3‰BSR‡RANOTIFYŒNotify�current�user,�if�any,�that�RAD *¦just�died.RAISR8ƒCLR.B…RARDFLAG(A5)ˆFinished�processing�this�interrupt--$*¦clear�"working�on�interrupt"�flag.*3RAISR4ƒEQU‡*“Tell�CMR�that�interrupt�has�been�taken *¦care�of.7‰CLR.B…RAINTFLG(A1)ˆClear�interrupt�flag�in�shared-RAM.-‰ORˆ#1,SR�Set�carry�bit�to�ind icate�that�this*¦interrupt�has�been�handled. ‰BRA.S…RAISR9*4RAINO„EQU‡*“Tell�CMR�that�this�interrupt�is�not�from *¦this�RAD.2‰AND‡#$FFFE,SR‹(Clear�carry�bit�to�indicate�this.)**RAISR9ƒEQU‡*“Return�to�CMR.***-* RAD INTERRUPT HANDLER EXITS FROM THIS POINT*/ŠMOVEM.L�(A7)+,D1-D7/A2-A4/A6…RESTORE�REGISTERSŠRTSšBACK�TO�INTERRUPT�HANDLERŠPAGEK*****************************************************************************9* ROUTINE TO QUEUE EVENT (ALREADY STAGED IN REGISTERS) TO*ƒ-�DRIVING�TASK. *ƒ-�EVENT�BEGINS�IN�REGISTER�D2.***ˆEXEC�ROUTINE/*ˆREGISTERS�USED:�D0-D1/A0,A3-A6‚WORK�REGISTERS*˜D2-D7‹STAGING�REGISTERS**K**************************************************************************** QEVENTƒEQU‡**ŠMOVEM.L�A0-A6/D0-D7,-(A7)‡Save�registers.#‰MOVE.L„A6,A0�Caller's�TCB�address.6ŠTR0$.QEVNTIˆ,‰(QEVNTI�routine�is�used�since�this�will#*¦be�called�only�while�servicing�an *¦interrupt.)#ŠBRA.S‚IOHQ5ŽBranch�if�queueing�ok.-ŠMOVEM.L�(A7)+,A0-A6/D0-D7…Restore�registers.9ŠMOVE.L�(A7),CCBQVER1(A5)‚Save�callers�address�for�debug.ŠBRA.S‚IOHQRTN 2IOHQ5…MOVEM.L�(A7)+,A0-A6/D0-D7„Restore�registers..ŠCLR.L‚CCBQVER1(A5)‡Clear�queue�error�address. IOHQRTNƒRTS—RETURN‰ENDéK*==========================================================================*=*ˆFORTRAN-callable�subroutines�used�to�invoke�the�RAD�driver.*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‘Error�code�for�"param�table�error".*%RASTPCMD�EQU‡00ˆ"Stop"�command�value.%RALODCMD�EQU‡01ˆ"Load"�command�value.%RADMPCMD�EQU‡02ˆ"Dump"�command�value.%RAJMPCMD�EQU‡03ˆ"Jump"�command�value.*RATSTCMD�EQU‡04ˆ"Self-test"�command�value.&RAOPNCMD�EQU‡$10‡"Open"�command�value.'RACLSCMD�EQU‡$20‡"Close"�command�value.'RAABTCMD�EQU‡$7F‡"Abort"�command�value.2RAEXTCMD�EQU‡$81‡"External�trigger"�command�value.*RASETCMD�EQU‡$82‡"Setpoint"�command�value.&RASCNCMD�EQU‡$83‡"Scan"�command�value.1RAATOCMD�EQU‡$84‡"Auto-range�scan"�command�value.+RACALCMD�EQU‡$85‡"Calibrate"�command�value.1RAHISCMD�EQU‡$86‡"High-speed�scan"�command�value.2RAXEQCMD�EQU‡$80‡"Execute�function"�command�value.‰PAGE*H*-----------------------------------------------------------------------*!*ˆGeneral�format�of�FORTRAN�call:&*’CALL�RADXXX(rad-id,param-table-addr)*=*ˆThis�call�will�cause�3�items�to�be�pushed�onto�the�stack�--:*’(1)‚address�where�the�desired�RAD-ID�is�stored‚(4�bytes)9*’(2)‚address�of�parameter�table�in�user's�area‚(4�bytes)*’(3)‚return�address‚(4�bytes)*A*ˆAll�registers�will�be�saved�and�restored�upon�return�except�for+*’register�A0,�whose�contents�will�be�lost.*@*ˆUpon�return,�the�stack�pointer�will�be�the�same�as�it�was�just6*’prior�to�the�RAD�call.‚The�following�illustrates�the4*’data�which�is�put�on�the�stack�(and�removed�before$*’returning�to�the�calling�program).*?*ˆ(Lowest�addr�of�stack)…1)�CMR�command�code,�subcode…(2�bytes)*£2)�**‚(zero-filled)�(2�bytes)*£3)�RAD-ID˜(4�bytes)þ8679*£4)�**‚(zero-filled)�(4�bytes)*£5)�**‚(zero-filled)�(4�bytes)*£6)�**‚(zero-filled)�(4�bytes)%*£7)�cmd�packet�addr�(=addr�of�user's*°param�table)ˆ(4�bytes)#*£8)�length�of�cmd�packetŠ(2�bytes)*£9)�contents�of�A3�(4�bytes)*¢10)�contents�o f�D2�(4�bytes)*¢11)�contents�of�D1�(4�bytes)*¢12)�contents�of�D0�(4�bytes)*¢13)�return�addr“(4�bytes) *¢14)�param-table-addrŽ(4�bytes)>*ˆ(high�memory�addr)ˆ15)�addr�where�RAD-ID�is�storedƒ(4�bytes)*5*’#1�through�8�above�form�the�parameter�block�for�the(*œCMR�TRAP1.‚(**�mark�the�unused�fields)6*’#9�through�12�are�storage�locations�for�the�register *œcontents.;*’#14�and�15�are�the�parameters�passed�by�the�FORTRAN�call.*O*********************************************************************************‰PAGECRADOPNƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents�on�the�stack.1‰MOVE†#RAOPNCMD,D1ˆStore�command�code�for�"open".9‰MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3. ‰CLR.L…D2)‰MOVE†4(A3),D2ŒPut�#�of�channels�into�D2..‰MULU†#12,D2ŽCalculate�#�of�bytes�in�parameter-‰ADD.L…#6,D2�table�(including�first�6�bytes).6‰BRA‡CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**CRADTSTƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents�on�the�stack.2‰MOVE†#RATSTCMD,D1ˆStore�cmd�code�for�"self-test".@RADTST2‚MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3.2‰MOVE.L„#10,D2ŽPut�#�bytes�in�param�table�into�D2.6‰BRA‡CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADABTƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents..‰MOVE†#RAABTCMD,D1ˆStore�cmd�code�for�"abort".@RADABT2‚MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3.0‰MOVE.L„#4,D2�Put�length�of�param�table�into�D2.6‰BRA‡CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADJMPƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.-‰MOVE†#RAJMPCMD,D1ˆStore�cmd�code�for�"jump".9‰MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3. ‰CLR.L…D2%‰MOVE†10(A3),D2‹Put�#�params�into�D2.&‰ASL.L…#1,D2�Double�to�get�#�of�bytes./‰ADD.L…#12,D2ŽAdd�#�bytes�in�beginning�of�table**¦(including�count)�to�give�total�#�bytes.6‰BRA‡CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADLODƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.-‰MOVE†#RALODCMD,D1ˆStore�cmd�code�for�"load".>RADLOD2‚MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�in�A3.2‰MOVE.L„#12,D2ŽPut�#�bytes�in�param�table�into�D2.6‰BRA‡CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADDMPƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.-‰MOVE†#RADMPCMD,D1ˆStore�cmd�code�for�"dump".3‰BRA‡RADLOD2�Go�finish�set�up�(same�as�for�RADLOD).**‰PAGE6RADXEQƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.9‰MOVE†#RAXEQCMD,D1ˆStore�cmd�code�for�"execute�function".9‰MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3. ‰CLR.L…D2(‰MOVE†12(A3),D2‹Put�#�of�params�into�D2.'‰ASL.L…#1,D2�Double�to�give�#�of�bytes.2‰ADD.L…#14,D2ŽAdd�#�bytes�in�beginning�of�table�to*¦total�#�bytes�in�table.6‰BRA‡CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADSTPƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.-‰MOVE†#RASTPCMD,D1ˆStore�cmd�code�for�"stop".3‰BRA‡RADABT2�Go�finish�set�up�(same�as�for�RADABT).**6RADATOƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.8‰MOVE†#RAATOCMD,D1ˆStore�cmd�code�for�"auto-range�scan".@RADATO2‚MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3. ‰CLR.L…D2#‰MOVE†4(A3),D2ŒPut�#�chans�into�D2.'‰ASL.L…#1,D2�Double�to�give�#�of�bytes.5‰ADD.L…#6,D2�Add�to�give�total�length�of�param�table.8‰BRA.S…CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADCLSƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents..‰MOVE†#RACLSCMD,D1ˆStore�cmd�code�for�"close".3‰BRA‡RADABT2�Go�finish�set�up�(same�as�for�RADABT).**6RADSCNƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.-‰MOVE†#RASCNCMD,D1ˆStore�cmd�code�for�"scan".9‰MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3. ‰CLR.L…D2#‰MOVE†6(A3),D2ŒPut�#�chans�into�D2.$‰ASL.L…#1,D2�Double�to�give�#�bytes.4‰ADD.L…#8,D2�Add�#�bytes�in�beginning�of�param�table'*¦to�give�total�#�bytes�in�param�table.8‰BRA.S…CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADEXTƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.9‰MOVE†#RAEXTCMD,D1ˆStore�cmd�code�fo r�"external�trigger".3‰BRA‡RADATO2�Go�finish�set�up�(same�as�for�RADATO).**‰PAGE6RADSETƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.9‰MOVE.L„20(A7),A3‹Put�addr�of�user's�param�table�into�A3. ‰CLR.L…D13‰MOVE†4(A3),D1ŒMultiply�#�of�setpoint�chans�by�6�to$‰MULU†#6,D1�#�bytes�for�setpt�chans. ‰CLR.L…D20‰MOVE†6(A3),D2ŒPut�#�non-setpoint�chans�into�D2.6‰ASL.L…#1,D2ŽDouble�to�get�#�bytes�of�non-setpt�chans.0‰ADD.L…D1,D2�Get�total�#�of�bytes�in�param�table‰ADD.L…#8,D2�into�D2.9‰MOVE†RASETCMD,D1‰Set�D1�to�cmd�code�for�"setpoint�scan".8‰BRA.S…CALLDRVRŒGo�set�up�param�block�and�make�CMR�call.**6RADHISƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.8‰MOVE†#RAHISCMD,D1ˆStore�cmd�code�for�"high-speed�scan"./‰BRA‡RADTST2�Go�finish�set�up�(same�as�RADTST).**6RADCALƒMOVEM.LƒD0-D2/A3,-(A7)†Store�register�contents.4‰MOVE†#RACALCMD,D1ˆStore�cmd�code�for�"calibration"./‰BRA‡RADLOD2�Go�finish�set�up�(same�as�RADLOD).**‰PAGE?CALLDRVR�MOVE†D1,2(A3)ŒPut�cmd�code�intouser's�cmd�param�table.2‰CMP.L…#$7FFF,D2‹Is�length�of�param�table�too�big?‰BHI.S…PRMERRŽYes--error."*---------------------------------*/*ˆSet�up�parameter�block�for�CMR�call�on�stack.**’(This�will�be�built�from�the�bottom�up.)*2‰MOVE†D2,-(A7)ŒPut�packet�length�(i.e.,�#�bytes�in$*¦user's�param�table)�at�"bottom"�of*¦param�block�for�CMR.7‰MOVE.L„A3,-(A7)ŒAddr�of�param�table�(=cmd�packet)�goes*¦next.0‰CLR.L…-(A7)�Clear�unused�fields�of�param�block. ‰CLR.L…-(A7) ‰CLR.L…-(A7)-‰MOVE.L„42(A7),A3‹Put�addr�of�RAD-ID�into�A3.7‰MOVE.L„(A3),-(A7)ŠPut�RAD-ID�into�param�block�for�CMR.<‰MOVE.L„#$07000000,-(A7)„Put�CMR�cmd�code,�subcode,�etc.,�at*¦"top"�of�param�block�for�CMR.0‰MOVE.L„A7,A0�Put�addr�of�param�block�(which�now"*¦starts�at�top�of�stack)�into�A0.#‰MOVE.L„#60,D0ŽSet�D0�for�CMR�call..‰TRAP†#1’Call�CMR,�which�will�in�turn�call�the *¦RAD�driver.=RTRN…MOVE.L„46(A7),A3‹Put�addr�of�user's�param�table�into�A3.5‰MOVE†D0,(A3)�Put�returned�error�flag�into�error�code*¦byte�in�user's�param�table.3‰LEA‡26(A7),A7‹Set�stack�ptr�to�addr�where�register*¦contents�are�stored.2‰MOVEM.Lƒ(A7)+,D0-D2/A3†Restore�register�contents.)‰MOVE.L„(A7)+,A0ŒPut�return�addr�into�A0.0‰LEA‡8(A7),A7Œ"Pop"�passed�parameters�off�stack.‰JMP‡(A0)�Return�to�user.**<*--------------------------‚Error�in�user's�parameter�table.*:PRMERRƒMOVE†#ERRCOD,D0ŠSet�D0�to�error�code�for�"parameter*¦table�error".‰BRA‡RTRN�Go�return�to�user.**‰END  éééééŠPAGEŠTTL„TR1RTCD.EQŠINCLUDE�9995.&.TR1RTCD.EQ ŠTTL„STR.EQŠINCLUDE�9995.&.STR.EQ ŠTTL„TCB.EQŠINCLUDE�9995.&.TCB.EQ ŠTTL�CCB.EQŠINCLUDE�9995.&.CCB.EQ ŠTTL�LV5.EQŠINCLUDE�9995.&.LV5.EQŠLISTŠTTL�RIODRV.EQŠINCLUDE�9995.&.RIODRV.E QŠTTL�STDMACRO.AIŠINCLUDE�STDMACRO.AI/ŠTTL�RIO�DRIVER�COPYRIGHT�1982�BY�MOTOROLA�INC.*‰INCLUDE�9995.&.STR.EQ*‰INCLUDE�9995.&.TR1RTCD.EQ*‰INCLUDE�9995.&.TCB.EQ*‰INCLUDE�9995.&.CCB.EQ*‰INCLUDE�9995.&.LV5.EQ*‰INCLUDE�9995.&.RIO.EQ*‰INCLUDE�0..STDMACRO.SA@RIODRV„IDNTƒ2,0‰RIO�DRVR�3/28/83�COPYRIGHT�1982�BY�MOTOROLA�INC. ŠLLENƒ120ŠPAGEJ****************************************************************************8*ƒRIODRV�--�REV.�1.00�5/12/82�(C313)�RONI�WOOD�&�JIM�LOE4*�REV.�2.00�3/28/83�(C313)�CHANGED�INTERRUPT�HANDLER***ƒPurpose:‚REMOTE�I/O�HANDLER*/*ƒEntry:‚JSR�FROM�CMR�HANDLER�(COMMAND�SERVICE) *‹JSR�FROM�CMR�INTERRUPT�HANDLER*-*ƒExit:�-�ALWAYS�EXITS�WITH�A�RTS�INSTRUCTION***ƒCODE�IS�RE-ENTRANT*&*ˆASSEMBLY:�USE�CHAIN�FILE�'RIOASM.CF'*H*-----------------------------------------------------------------------*ŠPAGE*************************** MISCELLANEOUS EQUATES ***************************IOEVCD„EQU„1’I/O�event�code*********************** *‡MACROS†************************* Macro for putting the H/W priority level'* to the priority indicated by the CCB.* INHIB„MACRO-‰MOVE.W„CCBISR(A5),SR‡Set�processor�priority.‰ENDM*+* Macro for dropping the H/W priority level* to an interruptable state.* ENABL„MACRO4‰MOVE.W„CCBSR(A5),SRˆDrop�processor�priority�by�one.‰ENDM*+* Macro for dropping the H/W priority level * to zero.* UNMASKƒMACRO1‰MOVE.W„#$2000,SR‹Set�processor�priority�to�zero.‰ENDM‰PAGE********************************* CHANNEL CONTROL BLOCK (CCB) *********************************B*ƒContains�channel�device�dependent�description�and�data�areas�for*ƒI/O�handler.*ŠOFFSET‚CCBDDP* '\0F89@-HHP<X9`9h;pFxK€7ˆ>�/˜@ 8¨<°5¸=À8È3Ð<Ø5à=è>ðOø^QI9H* I/O HANDLER DATA AREA *************************************************CCBFLG„DS.B„2ŒFlags(CCBERAD1‚DS.B„4ŒError�debug�save�address2CCBQVER1‚DS.B„4ŒEvent�queueing�error�debug�address7CCBCCB„DS.B„4ŒPhysical�address�of�command�packet�(IOCB)CCBTASKB‚DS.B„4ŒBuffer�task�TCB-CCBPKT„DS.B„18‹Event�work�area�(command�tour)0CCBCPKTƒDS.B„18‹Event�work�area�(interrupt�tour)(CCBPTR„DS.B„4ŒPhysical�address�of�bufferCCBLEN„DS.B„4ŒLength�of�buffer0CCBPTR1ƒDS.B„4ŒPhysical�address�of�2ndary�buffer&CCBLEN1ƒDS.B„4ŒLength�of�2ndary�buffer*CCBCID„DS.B„4ŒCMR�parameter�block�id�(DCB)CCBCOPTƒDS.B„2ŒIOCB�options#CCBCFIGƒDS.B„$26ŠConfiguration�data**‰56�bytes�remain*9*‰CCBFLG�DEFINITIONS:�if‚CCBFLG.B�if�not�0�the�RIO�module$*�for�the�CCB�cannot�be�used�for�the*�following�reasons:*9*‰CCBFLG.B�=�$FA�=�CCB�allocation�exceeded�#�of�specified/*šdevices�-�no�room�in�RIO�table�for�the�module!*’=�$FC�=�no�RIOTBL�was�allocated/*’=�$F5�=�no�room�in�RIOTBL�for�this�RIO�module*™(incorrect�table�allocation)**‰PAGE ‰SECTION�8 ‰XREF�RIOTBLJ******************************************************************************‚RIO�SERVICE�VECTOR�TABLE***L*****************************************************************************RIODVR:#*ˆDC.L†RIOINTŽinterrupt�svc�address!*ˆDC.L†RIOCMDŽcommand�svc�address)*ˆDC.L†RIOINIT�initialization�svc�address**?*Below are the new offset form of service pointers, for new CMR**(‰DC.L†RIOINT-RIODVR†interrupt�svc�offset*‰DC.L†RIOCMD-RIODVR†command�service�offset.‰DC.L†RIOINIT-RIODVR…initialization�svc�offset‰DC.L†0‰Reserved‰DC.B†0“number�of�extra�pages‰DC.B†0,0,0�reserved‰DC.L†0,0,0�reserved 3*ƒ---ƒ---…CONFIGURATION�CONTROL�INFORMATION…---ƒ---ŠSPC�1$‰DC.B…'032983'ƒdate�of�last�assembly'‰DC.B†'�'‡space�means�no�patches�in�.LO#‰DC.B†'4'‡major�Versados�revision�#‰PAGEJ****************************************************************************‰COMMAND�TABLE�&�JUMP�TABLE* :*‰These�are�used�by�the�command�service�routine�to�jump�to.*‰the�appropriate�routine�to�handle�a�command.*J***************************************************************************CMDTBL:ŠDC.WƒROPENŽOPEN�command.ŠDC.WƒRCLOSE�CLOSE�command.ŠDC.WƒROUTON�RELAY�ON�command. ŠDC.WƒROUTOFFŒRELAY�OFF�command.ŠDC.WƒRSTATŽSTATUS�command.'ŠDC.WƒRENABL�ENABLE�INTERRUPTS�command.(ŠDC.WƒRDSABL�DISABLE�INTERRUPTS�command."ŠDC.WƒRPLSOŽPULSED�OUTPUT�command.=NUMCMDSƒEQU„(*-CMDTBL)/2‡The�number�of�commands�in�the�table.*9JMPTBL:ƒDC.WƒOPEN-*�Biases�to�the�corresponding�routines. Š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†Offset�between�the�two�tables.ŠPAGEJ****************************************************************************+*ˆRIO�DRIVER�INITIALIZATION�SERVICE�ROUTINE*>*ˆThe�driver�is�entered�here�for�each�CCB�allocated.‚More�than:*ˆone�CCB�may�be�allocated�for�each�RIO�module.‚One�CCB�is>*ˆallocated�for�each�interrupt�level�the�board�is�jumpered�to.?*ˆThis�routine�checks�to�see�if�there�is�room�in�the�RIOTBL�for=*ˆthe�device�ID.‚It�saves�the�device�ID�and�the�memory�mapped>*ˆI/O�address�of�the�device�the�the�RIOTBL.‚It�initializes�the5*ˆinput�PIA�of�the�device�if�not�already�initialized.B*ˆThis�routine�also�checks�to�see�if�the�RIO�LED�is�on,�indicating<*ˆan�I/O�channel�reset�was�issued�or�a�power-up.�If�on,�thisA*ˆroutine�turns�it�off.�The�on/off�indicator�is�bit�#7�of�TSTREG.*:*ˆAn�error�code�is�saved�in�the�CCB�if�this�CCB�allocation=*ˆexceeds�the�maximum�number�of�CCB's�specified�during�SYSGEN9*ˆ(SYSGEN�parameter�NRIO),�if�no�RIOTBL�exists�or�no�room*ˆin�the�table�for�this�module.*$*ˆEntry:‚all�registers�are�available*�A5�=�CCB�address*I**************************************************************************RIOINIT:ŠPUSHPOINT‘save�pointers3ŠMOVE.LƒCCBCHB(A5),A0„get�memory�mapped�I/O�address$ŠMOVE.L�RIOTBL,A1Šget�RIOTBL�addressŠCMP.L‚#0,A1Žis�there�one?&ŠBNE.S‚RIOINIT1‹branch�if�have�a�table8ŠMOVE.B�#RIONTBL,CCBFLG(A5)�set�no�table�error�conditionŠBRA�RIOINEX1�goto�error�returnRIOINIT5‚TST.L‚(A1,D3)Œlook�for�an�entry�slot�to�save�this�guy5ŠBMI.S‚RIOINIT6‹branch�if�this�slot�is�empty�-�use�it/ŠADD.W‚#PIALNG,D3‰not�empty,�bump�to�next�entry"ŠSUB.B‚#1,D4Ždecrement�the�counter(ŠBNE.S‚RIOINIT5‹branch�if�more�to�search4ŠBRA„RIOEXTER‹error�if�got�here-�no�room�for�the�map>RIOINIT6‚MOVE.L�D2,(A1,D3)‰save�this�memory�mapped�I/O�address*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 initialized L*to�all�inputs.‚On�any�channel�which�is�allocted�for�output,�only�the�outputD*�Pia�will�be�set�for�output.‚When�this�channel�is�de-allocated,�theH*�corresponding�output�PIA�bit�must�be�re-initialized�for�input.‚FailureM* to follow this policy will result in impropper operation of input channels.*.ŠMOVE.L‚#0,D0�write�0�to�all�pia�control�reg'sŠBSR.SƒRIO.WCR‹do�itBŠMOVE.B‚#0,PIA1ADR(A0)„clear�all�data�direction�regs�(set�for�inpu!ŠMOVE.B‚#0,PIA1BDR(A0)„clear�next!ŠMOVE.B‚#0,PIA2ADR(A0)„clear�next!ŠMOVE.B‚#0,PIA2BDR(A0)„clear�last2ŠMOVE.B‚#4,D0�set�control�regs�for�data�reg�access ,ŠBSR.SƒRIO.WCR‹writes�are�done�by�subroutine&ŠBSR.SƒRIO.CLR‹go�clear�all�interrupts **‰turn�off�the�LED*1RIOEXIT1‚CLR.B‚CCBFLG(A5)‰set�for�good�allocation3ŠMOVE.L�CCBCHB(A5),A1†get�memory�mapped�I/O�address,ŠMOVE.B�TSTREG(A1),D1†read�the�test�register$ŠBPL.S‚RIOINEX1‹return�if�LED�is�off%ŠBCLRƒ#LEDSTA,D1‰clear�the�LED�on�bit&ŠMOVE.B�D1,TSTREG(A1)†turn�the�LED�off'RIOINEX1:�POP_POINT‘recall�all�pointersŠRTS**‚Subroutines�used�by�RIOINIT:*DRIO.WCR‚EQU�*ƒwrites�data�in�ls�byte�of�D0�to�all�pia�control�reg`s.‰MOVE.B‚D0,PIA1ACR(A0)‰MOVE.B‚D0,PIA1BCR(A0)‰MOVE.B‚D0,PIA2ACR(A0)‰MOVE.B‚D0,PIA2BCR(A0)‰RTS›end�RIOWCR**RIO.CLRƒEQU�*ƒclear�any�pending�interrupts*‰MOVE.B‚PIA1ADR(A0),D0‰MOVE.B‚PIA1BDR(A0),D0‰MOVE.B‚PIA2ADR(A0),D0‰MOVE.B‚PIA2BDR(A0),D0‰RTS›end�RIOCLRŠPAGEJ***************************************************************************$*‰RIO�DRIVER�COMMAND�SERVICE�ROUTINE*6*‹PARAMETER�ADDRESS�AND�BOUNDARY�CHECKS�HAVE�BEEN�MADE**ƒEntry:‚JSR�FROM�CMR�HANDLER.*‹A2�-�PHYSICAL�ADDRESS�OF�CMR�PARAMETER�BLOCK*‹A5�-�PHYSICAL�ADDRESS�OF�CCB*5*ƒExit:‚RTS�-�PARAMETER�BLOCK�VALIDATION�STATUS�IN�D0**ƒREGISTERS�USED:ƒ01234567 *”D******** *”A**P**PP*"*”A3�=�RIO�PARAMETER�BLOCK�ADDRESS*”A6�=�REQUESTOR�TCB�ADDRESS**ƒEXEC�ROUTINES�CALLED:‚QEVENTI**ƒCODE�IS�RE-ENTRANT*****J***************************************************************************RIOCMD:*)*‰Convert�logical�PB�address�to�physical.* ŠCLR.L‚D5;ŠMOVE.L�XIOCPK(A2),D6†Set�up�address�of�RIO�parameter�block:ŠMOVE.W�XIOPLN(A2),D5†Set�up�length�of�RIO�parameter�block+ŠMOVE.L�CCBTASKA(A5),A1„Set�up�TCB�pointer.&ŠBSR„IOHADRCK‹Call�conversion�routine.ŠBRA.S‚CMD010�Good�return.ŠNOP—Bad�length�return. ŠCLR.L‚D0;ŠMOVE.B�#RTCDPBLK,D0‡Set�up�invalid�parameter�block�addressŠBRA�RIOCEX2�goto�error�exit*!*‰see�if�passed�the�initialize�ok*CMD010„CLR.L‚D02ŠMOVE.LƒD6,A3ŒStage�phys.�addr.�opf�RIO�para.�blk.4ŠTST.B‚CCBFLG(A5)‰error�code�set�in�CCB�during�INIT?/ŠBEQ.S‚CMD020�branch�if�no�error�code,�continue$ŠMOVE.B�CCBFLG(A5),D0†set�error�code%CMDSRTRƒBRA.S‚RIOCEX2Œgoto�error�exit CMD020„EQU�**,*‰get�RIOTBL�address�into�A4�for�command�use* ŠMOVE.L�RIOTBL,A4ŠRIOTBL�address)ŠCMP.L‚#'!RIO',(A4)‡really�is�the�RIOTBL?,ŠBEQ.S‚CMD030�branch�if�really�is�the�RIOTBL4ŠMOVE.B�#RIONTBL,D0ˆset�error�return�code�-�no�tableŠBRA.S‚CMDSRTRŒand�return**‰find�RIO-ID�in�RIOTBL*‰A1�=�entry�address*0CMD030„MOVE.L�XIOCID(A2),D0†get�specified�RIO-ID(ŠMOVE.B�RIONMAX(A4),D1…max�#�of�RIO-ID's$ŠMOVE.L�#RIONTRY,D2ˆbump�past�header"FNDRIO10‚CMP.L‚(A4,D2),D0‰a�match?!ŠBEQ.S‚FNDRIO20‹branch�if�a�match&ŠADD.W‚#RIOIDLNG,D2‡bump�to�next�entry1ŠSUB.L‚#1,D1Ždecrement�number�of�entries�to�check&ŠBNE.S‚FNDRIO10‹branch�if�more�entries.ŠMOVE.W�#RIONID,D0‰error�-�RIO-ID�not�in�table3ŠBRA„CMDSRTRŒreturn�to�CMR�with�error�condition�set+FNDRIO20‚MOVE.L�A4,A1Žbass�address�of�tableŠADD.L‚D2,A1Žaddress�of�entry*(*‰Find�the�command�in�the�command�table.*-ŠMOVEQ‚#NUMCMDS-1,D0†Set�up�the�loop�counter./ŠLEA„CMDTBL,A0ŠA0�<--�address�of�command�table.+ŠMOVE.W�CMDCOD(A3),D6†get�RIO�command�code.8CMDSRCHƒCMP.W‚(A0)+,D6‹Search�the�table�for�the�command.ŠDBEQƒD0,CMDSRCH‰*3ŠBNE.S‚CMDERR�If�we�found�the�command�in�the�table,8ŠADD.L‚#JMPOFF-2,A0‡get�the�corresponding�entry�from�the 5ŠMOVE.W�(A0),D0Œjump�table�and�jump�to�the�routine�to"ŠJMP„(A0,D0.W)Šhandle�the�command.DCMDERR„MOVE.B�#RIOINVD,D1ˆdidn't�find�command�code�-�exit�with�errorŠSPC�1RIOCEX2:;ŠMOVE.WƒD0,CMDSTA(A3)‡write�error�code�to�users�RIO�para�blRIOCEX1:ŠRTSŠPAGEL*****************************************************************************‰OPEN�COMMANDA*‰This�command�assigns�the�logical�connection�between�a�user�task:*‰and�specified�channels�within�an�RIO�module.�16�channels?*‰maximum�may�be�specified�in�one�open�command.�Interrupt�levelB*‰of�the�channels�are�taken�from�the�CCB.�The�interrupts�levels�of4*‰input�channels�0-7�must�match�the�following�order:-*‰channels�0-1�must�have�same�interrupt�level-*‰channels�2-3�must�have�same�interrupt�level-*‰channels�4-5�must�have�same�interrupt�level-*‰channels�6-7�must�have�same�interrupt�levelD*‰It�is�ok�for�all�these�channels�to�have�the�same�interrupt�levels.*#*‰RIO�OPEN�command‚parameter�block: *�DS.W‚1„returned�command�status*�DS.W‚1„command�code�(01)*�DS.W‚1„#�of�channels�to�open*�DS.W‚1„1st�channel�number*�DS.W‚1„channel�configuration*’.*�DS.W‚1„nth�channel�number*�DS.W‚1„channel�configuration**‰configuration�byte:*�bit�0=1�output�channel*•=0�input�channel*�bit�1=1�disable�interrupt*•=0�enable�interrupt"*�bit�2=1�interrupt�on�rising�edge*•=0�interrupt�on�falling�edge)*�bit�3=1�wake-up�task�on�input�interrupt,*•=0�queue�event�to�task�on�intput�interrupt8*Œbits�8-14=‚debounce�interval.‚0=no�debounce,�otherwise-*˜debounce�time�is�value�times�4�milliseconds$*�bit�15=1�use�default�configuration *•=0�use�specified�configuration**‰Default�configuration:*�channels�0-7’channels�8-15*�------------’-------------*�input�channel‘output�channel*�interrupt�enabled*�interrupt�on�falling�edge*�queue�event�on�interruptB*‰When�default�configuration�is�specified,�the�actual�configuation9*‰is�saved�in�RIOTBL.�The�task�TCB�address�is�also�saved.*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�CLRPIAM,�SETPIA,�DOPIA*L**************************************************************************** PAGE*OPEN:*‰see�if�channel�already�opened* ŠPUSHPOINT‘save�all�address�regsŠALLOCATEƒCHCONFIG4ŠBSR�CLRPIAM�clear�(to�$FF)�the�PIA�map�for�this�RIOŠCLR.L‚D7‘channel�counter:ŠCMP.W‚#RIONID,D0‰an�error�returned�from�clearing�the�map?'ŠBEQ„OPNOID�branch�if�an�error�returned$ŠCLR.L‚D2‘channel�offset�into�RIOTBL)ŠCLR.L‚D1‘offset�into�RIO�parameter�block1ŠMOVE.W�CMDCHN(A3),D0†get�#�of�channels�specified-ŠBLE„OPNINC�branch�if�negative�or�zero,�error2ŠCMP.W‚#16,D0�cannot�specify�more�than�16�channels,ŠBGT„OPNINC�branch�if�greater�than�16,�errorGOPEN10„MOVE.W�NUMCHAN(A3,D1),D2‚get�channel�number�from�RIO�param.�blk.ŠMOVE.W�D2,D5Žsave�it0ŠMULUƒ#CHANLNG,D2ˆget�channel�offset�into�RIOTBLŠADD.L‚#4,D2Žbump�past�RIO-ID+ŠTST.W‚(A1,D2)Œthis�channel�already�opened?+ŠBPL„OPNOPN�branch�if�already�opened,�errorŠADD.L‚#1,D7Žcount�this�channel@ŠMOVE.W�CHNCNFG(A3,D1),D3‚get�configuration�from�RIO�param.�blk.-ŠSTORE„D3,CHCONFIG†save�channel�configuration*ŠBMI.S‚OPEN60�branch�if�defaults�specifiedŠBTSTƒ#0,D3Žoutput�channel?&ŠBNE.S‚OPEN70�branch�if�output�channel**‰set�this�channel�for�input* ŠMOVE.W�D3,D4Žsave�configuration"ŠCMP.B‚#8,D5Žsee�if�channel�#�8-153ŠBGE.S‚OPEN50�branch�if�channel�8-15,�no�interrupts3ŠMOVE.B�CCBPPRIO(A5),D4„get�intrrupt�level�from�CCBŠASL.L‚#4,D4Žget�into�bits�4-6$ŠOR.WƒD4,D3Žsave�the�interrupt�level*6*‰check�to�see�that�interrupt�levels�of�channels�match*,OPEN20„MOVE.B�D5,D6Žsave�this�channel�numberŠBTSTƒ#0,D5Žodd�channel?*ŠBNE.S‚OPEN30�branch�if�odd�channel�number*ŠADD.B‚#1,D6Ževen�-�get�channel�number�+�1ŠBRA.S‚OPEN40�and�continue/OPEN30„SUB.B‚#1,D6Žodd�-�get�channel�number�-�15OPEN40„MULUƒ#CHANLNG,D6ˆget�channel�offset�into�table ŠADD.L‚#4,D6Žbump�past�RIO-ID#ŠTST.W‚(A1,D6)Œthis�channel�opened?"ŠBMI.S‚OPEN50�branch�if�not�opened9ŠMOVE.W�RIOCNIF(A1,D6),D6‚get�other�channel�configurationŠSPC�2ŠBTSTƒ#0,D6Žan�input�channel?,ŠBNE.S‚OPEN50�branch�if�not�an�input�channel$ŠASR.L‚#4,D6Žget�into�low�order�bits**‰good�configuration0*‰save�TCB�address�and�configuration�information* OPEN50„EQU†*.ŠLOAD…D3,CHCONFIG†recall�channel�configuration+ŠBSR„SETPIA�go�set�PIA�map�for�this�channel5ŠCMP.W‚#RIONID,D0‰an�error�found�during�the�save�map?*ŠBEQ.S‚OPNERR�branch�if�an�error�was�found6ŠMOVE.W�D3,RIOCNIF(A1,D2)‚save�configuration�in�RIOTBL)ŠMOVE.L�A6,RIOTCB(A1,D2)ƒsave�TCB�address4ŠADD.W‚#OPNTRY,D1‰bump�to�next�RIO�param.�blk.�entry3ŠSUB.W‚#1,D0Ždecrement�number�of�channels�specified)ŠBGT„OPEN10�branch�if�more�channels�to�do,ŠBSR„DOPIAŽgo�set�the�PIA�hardware�registers!ŠCMP.W‚#RIONID,D0‰an�error�found?7ŠBEQ.S‚OPNERR�branch�if�an�error�was�found�-�don't�openŠCLR.L‚D0‘set�for�good�returnŠBRA.S‚OPNXIT�go�return�to�CMR**‰default�configuration�set*%OPEN60„CMP.W‚#7,D5Žsee�if�channel�0-7!ŠBLE.S‚OPEN80�branch�if�maybe�0-7!ŠCMP.W‚#16,D5�see�if�channel�8-16-ŠBGT.S‚OPNCNŽbranch�if�greater�than�16,�error**‰output�channel*,OPEN70„MOVE.W�#1,D3Žset�output�configurationŠBRA.S‚OPEN50�go�save�it**‰input�configuration�specified*-OPEN80„TST.W‚D5‘must�be�channel�#0�or�greater)ŠBLT.S‚OPNCNŽbranch�if�less�than�0,�errorŠCLR.W‚D3‘set�for�defaults/ŠMOVE.B�CCBPPRIO(A5),D3„get�CCB�interrupt�levelŠASL.L‚#4,D3Žput�into�bits�4-6ŠBRA.S‚OPEN20�go�save�it**‰open�errors�here*;OPNINT„MOVE.W�#RIOIINT,D0ˆset�invalid�interrupt�level�error.ŠBRA.S‚OPNERR�go�'de-open'�any�opened�channels>OPNCN…MOVE.W�#RIOICNS,D0ˆset�illegal�channel�#�specified�error.ŠBRA.S‚OPNERR�go�'de-open'�any�opened�channels8OPNINC„MOVE.W�#RIOINC,D0‰set�invalid�#�of�channels�errorŠBRA.S„OPNXIT‹exit;OPNOID„MOVE.W�#RIONID,D0‰set�RIO�module�not�allocated�errorŠBRA.S‚OPNXIT�go�return�to�CMR9OPNOPN„MOVE.W�#RIOPND,D0‰set�channel�already�opened�error*)*‰reset�any�opened�channels�to�not�opened*%OPNERR„TST.W‚D7‘any�channels�to�undo?3ŠBEQ.S‚OPNXIT�branch�if�none�to�undo,�return�to�CMR&ŠMOVE.W�#$FFFF,D3Šset�'un-opened'�codeŠCLR.L‚D1‘clear�for�use6OPNERR10‚MOVE.W�NUMCHAN(A3,D1),D2‚get�a�channel�number$ŠMULUƒ#CHANLNG,D2ˆget�channel�offsetŠADD.L‚#4,D2Žbump�past�headers*ŠMOVE.W�D3,(A1,D2)‰set�this�entry�unopened-ŠADD.W‚#OPNTRY,D1‰bump�to�next�channel�numberŠSUB.W‚#1,D7Ždecrement�counter&ŠBGT.S‚OPNERR10‹branch�if�more�to�undo** Fall into exit* OPNXIT EQU * ŠADD.L„#8,A7Œdeallocate�CHCONFIGŠPOP_POINT‘restore�all�pointers ŠBRA�NRMEXITŠPAGEK*****************************************************************************‰SETPIA*7*‰Build�the�PIA�map�entries�for�the�specified�channels.*‰Builds�1�entry�per�call*‰Map�is�in�RIOTBL.**‰Entry:�A4ƒ=�RIOTBL�address*�D3.W�=�channel�configuration*�D5.B�=�channel�number*7*‰Exit:‚D0.W�=�RIONID�if�map�entry�not�found,�otherwise*—D0�unchanged *‰Uses:�D4,D6*‰Entry�point�=�SETPIA*‰Exit�point‚=�SETPIART**L******************************************************************************‰find�map�entry* SETPIA EQU *ŠPUSHPOINT‘save�all�pointersŠMOVE.L�D7,-(A7)‹save�D75ŠMOVE.W�RIOPIA(A4),D7†get�offset�to�start�of�PIA�maps.ŠMOVE.B�RIONAL(A4),D6†get�#�of�RIO'S�allocated3ŠMOVE.L�CCBCHB(A5),D4†get�memory�mapped�I/O�address=SETPIAFD‚CMP.L‚PIADDR(A4,D7),D4ƒfind�the�matching�I/O�addressŠBEQ.S‚SETPIA00‹branch�if�found$ŠADD.W‚#PIALNG,D7‰bump�to�next�entryŠSUB.B‚#1,D6Ždecrement�counter0ŠBNE.S‚SETPIAFD‹branch�if�more�entries�to�search>ŠMOVE.W�#RIONID,D0‰set�for�fatal�error�-�this�shouldn't�happen ŠBRA.S„SETPIART‰return�to�caller**‰determine�channel�number*SETPIA00‚CLR.L‚D6‘clear�for�use/ŠMOVE.B�D5,D6Žcopy�channel�number�to�work�spaceŠCMP.B‚#7,D5Žchannel�0-7?ŠBLE.S‚SETPIA20‹branch�if�0-7**‰channel�8-15*/ŠSUB.B‚#8,D6Žget�bit�#�offset�of�channel�number ŠBTSTƒ#0,D3Žan�output�channel?0ŠBNE.S‚SETPIA10‹branch�if�yes,�an�output�channel**‰channel�8-15�as�input�channel*%ŠBCLRƒD6,DODR815(A4,D7)‚set�for�input ŠBRA.S‚SETPIART‹return�to�caller* *‰channel�8-15�as�output�channel*SETPIA10 EQU *0ŠBSET…D6,DODR815(A4,D7)ƒset�ddr�image�for�output ŠBRA.S‚SETPIART‹return�to�caller* *‰channel�0-7*%SETPIA20‚BTSTƒ#0,D3Žan�input�channel?,ŠBEQ.S‚SETPIA30‹branch�if�yes,�input�channel**‰CHANNEL�0-7�as�output�channel*/ŠBSETƒD5,DODR07(A4,D7)ƒset�ddr�image�for�output#SETPIART‚MOVE.L�(A7)+,D7‹restore�D7ŠPOP_POINT‘restore�all�pointersŠRTS—return�to�caller**‰channel�0-7�as�input�channel*SETPIA30‚EQU�*$ŠBCLRƒD5,DODR07(A4,D7)ƒset�for�input1ŠBSR„NEWSETPŒinit�PIA�control�regs�for�interrupts ŠBRA†SETPIARTŠPAGED********************************************************************&*ˆNEWSETP�is�interrupt�setup�for�PIA's&*ˆNEWSETP�initializes�one�PIA�per�call** Private subroutine for SETPIA** Table driven pia setup::*‚PIAICMSK‚is�a�table�of�PIA�interrupt�control�mask�words.N*‚The�LS�byte�is�AND'ed�with�map�entry,�and�the�MS�byte�is�OR'd�with�map�entry‰SPC�3PIAICMSK EQU *-‰DC.W†$05FD…enable�falling�irq�on�even�port�#‰DC.W†$04FE…disable�even‰DC.W†$07FF…enable�rising‰even‰DC.W†$04FE…disable�evenA*----------------------------------------------------------------‰DC.W†$0CEF…enable�fallingˆodd‰DC.W†$04F7…disable�odd‰DC.W†$1CFF…enable�rising‰odd‰DC.W†$04F7…disable�oddŠSPC�3)PIAMGOFF�EQU�*‚IRQ�control�image�offsets:‰DC.B†2‰DC.B†3‰DC.B†0‰DC.B†1‰SPC�3NEWSETP:ŠSPC�1L*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‚contains�channel�configuration*ˆD5.B‚contains�channel�number%*ˆD7„contains�offset�to�PIA�map�start**‰PUSHALL–save�all ‰CLR.L…D0/‰MOVE.B„D3,D0…get�IRQ�config.�to�working�reg�D0+‰AND.B…#$0004,D0‚select�IRQ�config�data�bit‰TST.B…D0ˆsetup�for�branches7‰BMI.S…SETPIA33‚branch�on�default�configuration�request8‰BEQ.S…SETPIA32‚branch�on�falling�edge�irq�configuration‰CMP.B…#4,D0…rising�edge�irq�?7‰BEQ.S…SETPIA32‚branch�on�rising�edge�irq�configuration1‰MOVE.L„#2,D0…on�all�other�config.'s,�disable�irq6SETPIA32ƒEQU‚*ƒnow�determine�even�/�odd�channel�number"‰BTST†#0,D5…even�or�odd�channel�#?(‰BEQ.S…SETPIA31‚branch�on�even�channel�#"‰ADD‡#8,D0…add�8�for�odd�channel�##SETPIA31ŠEQU�*…rejoin�main�sequence ‰CLR.L…D18‰MOVE.W„PIAICMSK(PC,D0),D1‚fetch�control�word�from�table)‰MOVE.L„D3,D0…get�new�copy�of�config�data5‰AND.L…#$00000008,D0‚select�wakeup/que�event�data�bit ‰MOVE.L„#21,D4„setup�shift�count2‰LSL.L…D4,D0„position�wakeup/quevent�bit�in�bit�24‰SPC�1)‰AND.L…#$0000FF00,D3‡select�debounce�data1‰LSL.L…#8,D3…position�debounce�data�in�bits�16-23‰OR.L†D3,D1…add�debounce�data-‰OR.L†D0,D1…add�wakeup/quevent�data�at�bit�248‰BSR‡WRITMAPƒwrite�the�interrupt�control�data�to�PIA�map7SETPIA33‚EQU‚*‚branch�here�for�no�change�in�irq�setting‰POPALL˜restore�register�values‰RTS‰PAGEWRITMAP:#*ˆWrites�interrupt�data�to�PIA�map.*ˆInput�parameters�to�WRITMAP:*ˆD5ƒchannel�# *ˆD7ƒoffset�to�start�of�PIA�maps$*ˆA4ƒRIOTBL�address�for�current�user;*ˆD1.L�PIA�control�mask�word�(bits�16-23�are�debounce�data)!*¤(bit�24�is�wakeup/quevent�bit).*>*ˆTranslates�channel�number�to�PIA�register�image�map�address,4*ˆthen�modifys�the�map�image�based�on�data�in�D1�.L.2*ˆNow�translate�channel�number�into�PIA�map�offset* ‰CLR.L…D0/‰MOVE.B„D5,D0…put�channel�#�into�working�reg�D0"‰LSR.B…#1,D0…divide�channel�#�by�2*;*‡PIA�channel�index�now�in�D0;�now�add�offset�from�PIAMGOFF*‡(pia�image�offset�table)*;‰ADD.B…PIAMGOFF(PC,D0),D7‚add�offset�to�channel�IRQ�control$‰ADD.B…#8,D7…bump�to�register�images**ˆD7�contains�offset�to�PIA�map*.‰AND.B…D1,(A4,D7)‚modify�PIA�control�reg�image0‰LSR.L…#8,D1…bring�OR�byte�into�working�position -‰OR.B†D1,(A4,D7)‚modify�PIA�control�reg�image.‰LSR.L…#8,D1…bring�debounce�data�into�position/‰OR.B†D1,-1(A4,D7)‚add�debounce�data�to�PIA�map*‰LSR.L…#1,D1‡bring�wakeup/que�bit�to�bit�7(‰AND.B…#$80,D1Šselect�wakeup/quevent�bit.‰OR.B†D1,(A4,D7)„add�wakeup/que�bit�to�PIA�map‰RTS‰PAGED*********************************************************************:*‰DOPIA‚Copy�the�interrupt�control�data�and�data�direction3*�information�from�the�PIA�register�images�(in�map)*�to�the�PIA�registers.*A*‚The�PIA�must�not�be�allowed�to�generate�an�interrupt�during�theE*‚initialization�process�because�the�CMR�and�RIO�tables�have�not�been@*‚set�up.‚To�enforce�this,�all�interupts�are�disabled�during�the@*‚code�section�where�the�PIA�control�reg.'s�are�set,�and�the�PIA*‚interrupt�flags�are�cleared.**ˆENTRY�PARAMETERS:*�A4�=�address�of�RIOTBL*�A5�=�address�of�CCB***‰Exit:‚D0.W�=�RIONID�if�PIA�map�not�found*�D0.W�=�0�if�no�errors�found**‰Uses:�A0,D1,D6,D7**D*********************************************************************;*‚CLRIRQ�is�an�AND�mask�used�to�clear�PIA�IRQ�control�bits.*"CLRIRQƒEQU‡$E4‡clears�bits�0,1,3,4*** DOPIA EQU *ŠPUSHPOINT’save�all�pointers!ŠMOVE.L�D7,-(A7)‹save�register�D7,ŠMOVE.W�RIOPIA(A4),D7†get�offset�to�PIA�maps$ŠMOVE.B�RIONAL(A4),D6†get�#�of�RIO'S3ŠMOVE.L�CCBCHB(A5),D1†get�memory�mapped�I/O�address>DOPIA10ƒCMP.L‚PIADDR(A4,D7),D1ƒlook�for�a�matching‚I/O�address(ŠBEQ.S‚DOPIA20Œbranch�if�found�the�entry(ŠADD.W‚#PIALNG,D7‰bump�to�next�map�entry"ŠSUB.B‚#1,D6Ždecrement�the�counter/ŠBNE.S‚DOPIA10Œbranch�if�more�entries�to�search9ŠMOVE.W�#RIONID,D0‰set�for�fatal�error�(shouldn't�happen) ŠBRA�DOPIAX�branch�to�exit�point**‰D7�contains�offset�to�PIA�map(*‰set�direction�register�of�channels�0-7**ˆMASK�ALL�INTERRUPTS* DOPIA20 EQU *0ŠMOVE.WƒSR,D6Œsave�present�interrupt�mask�status!ŠOR‡#$0700,SRˆmask�all�interrupts***‰Set�direction�register�for�channel�0�-�73*‰Newly�created�OUTPUT�channels�must�be�set�to�OFF.4*‰To�do�this,�OR�new�channels�bit�map�with�data�reg.<*‰(there�is�logical�inversion)�between�PIA�and�final�output.*ŠCLR†D2�for�useŠCLR†D1�for�use6ŠMOVE.L�PIADDR(A4,D7),A0ƒget�memory�mapped�I/O�address,ŠBSET…#2,PIA2ADR(A0)ƒset�for�data�reg�access-ŠMOVE.BƒPIA2ADR(A0),D4ƒget�old�data�reg�value+ŠNOT†D4�convert�data�format�to�conventional'ŠBCLR…#2,PIA2ACR(A0)ƒset�for�DDR�access;ŠMOVE.BƒPIA2ADR(A0),D2ƒget�a�copy�of�old�data�direction�reg-ŠAND†D2,D4Œselect�on�channels�that�are�outputŠNOT†D24ŠMOVE.BƒDODR07(A4,D7),D1„get�the�new�output�channelsŠAND†D2,D1Œfind�new�channels:ŠMOVE.B�PIA2ADR(A0),D0…read�channel�0-7�direction�register9ŠOR.BƒDODR07(A4,D7),D0ƒadd�in�the�new�setting�information8ŠMOVE.B�D0,PIA2ADR(A0)…store�into�the�direction�register,ŠBSETƒ#2,PIA2ACR(A0)…set�for�output�function4ŠOR.B„D1,PIA2ADR(A0)„set�new�OUTPUT�channels�for�OFF'ŠNOT…D4�convert�to�inverted�data�format/ŠAND.B„D4,PIA2ADR(A0)ƒadd�in�old�data�reg�value*-*‰Set�direction�register�for�channels�8�-�16.*>*‰Newly�created�OUTPUT�channels�must�be�set�OFF.‚To�do�this,OR>*‰new�channels�bit�mask�with�data�register�(there�is�a�logical3*‰inversion�between�PIA�outputs�and�final�outputs).*ŠCLR†D2�for�useŠCLR†D1�for�use,ŠBSET…#2,PIA2BDR(A0)ƒset�for�data�reg�access-ŠMOVE.BƒPIA2BDR(A0),D4†get�old�data�reg�value+ŠNOT†D4�convert�data�to�conventional�format'ŠBCLR…#2,PIA2BCR(A0)†set�for�DDR�access7ŠMOVE.BƒPIA2BDR(A0),D2†get�a�copy�of�old�direction�reg.-ŠAND†D2,D4Œselect�on�channels�that�are�outputŠNOT†D20ŠMOVE.BƒDODR815(A4,D7),D1ƒget�new�direction�reg.%ŠAND†D2,D1Œselect�new�output�channels;ŠMOVE.B�PIA2BDR(A0),D0…read�channel�8-15�direction�register:ŠOR.BƒDODR815(A4,D7),D0‚add�in�the�new�setting�information8ŠMOVE.B�D0,PIA2BDR(A0)…store�into�the�direction�register,ŠBSETƒ#2,PIA2BCR(A0)…set�for�output�function0ŠOR.BƒD1,PIA2BDR(A0)…set�new�output�channels�off'ŠNOT†D4�convert�data�to�inverted�format 1ŠAND.B„D4,PIA2BDR(A0)ƒreplace�old�data�reg�values **ˆClear�all�PIA�interrupts*‰TST.B…PIA1ADR(A0)‰clear�PIA�1A‰TST.B…PIA1BDR(A0)‰clear�PIA�1B‰TST.B…PIA2ADR(A0)‰clear�PIA�2A‰TST.B…PIA2BDR(A0)‰clear�PIA�2B*#* Set channels 4-5 IRQ control bits*6ŠMOVE.B�PIA2ACR(A0),D0…get�0-7�output�control�register)ŠAND.B„#CLRIRQ,D0‡negate�IRQ�control�bits;ŠOR.BƒOCR07(A4,D7),D0„add�channel�4-5�interrupt�information*ŠMOVE.B�D0,PIA2ACR(A0)…write�the�new�stuff*,*‰set�interrupt�information�for�channels�6-7*<ŠMOVE.B�PIA2BCR(A0),D0…get�chan�8-15�output�control�register(ŠAND.B„#CLRIRQ,D0‡clear�IRQ�control�bits<ŠOR.BƒOCR815(A4,D7),D0ƒset�channel�6-7�interrupt�information*ŠMOVE.B�D0,PIA2BCR(A0)…write�the�new�stuff*,*‰set�interrupt�information�for�channels�0-1*:ŠMOVE.B�PIA1ACR(A0),D0…get�chan�0-7�input�control�register(ŠAND.B„#CLRIRQ,D0‡clear�IRQ�control�bits;ŠOR.BƒICR07(A4,D7),D0„set�channel�0-1�interrupt�information*ŠMOVE.B�D0,PIA1ACR(A0)…write�the�new�stuff*,*‰set�interrupt�information�for�channels�2-3*>ŠMOVE.B�PIA1BCR(A0),D0…get�channel�8-15�input�control�register(ŠAND.B„#CLRIRQ,D0‡clear�IRQ�control�bits<ŠOR.BƒICR815(A4,D7),D0ƒset�channel�2-3�interrupt�information*ŠMOVE.B�D0,PIA1BCR(A0)…write�the�new�stuffŠCLR.L‚D0‘set�for�good�return**ˆrestore�interrupt�level*6ŠMOVE.WƒD6,SRŒreturn�interrupt�masks�to�previous�valueDOPIAX�EQU�*˜exit�sequenceŠMOVE.Lƒ(A7)+,D7‰restore�D7ŠPOP_POINT‘recall�all�pointersŠRTS—return�to�callerŠPAGEL*****************************************************************************6*‰CLRPIAMƒClear�out�the�PIA�map�for�this�memory�mapped*“I/O�address.*&*‰Entry:�A1�=�RIO-ID�address�in�RIOTBL%*�A2�=�address�of�CMR�parameter�block%*�A3�=�address�of�RIO�parameter�block*�A4�=�address�of�RIOTBL*�A5�=�address�of�CCB*�A6�=�address�of�users�TCB**‰Uses:‚D4,D6,D7*%*‰Exit:‚D0�=�RIONID�if�an�error�found**�D0�=�contents�on�entry�if�no�error�found*L*****************************************************************************3CLRPIAMƒMOVE.W�RIOPIA(A4),D7†get�offset�to�PIA�maps.ŠMOVE.B�RIONAL(A4),D6†get�#�of�RIO'S�allocated3ŠMOVE.L�CCBCHB(A5),D4†get�memory�mapped�I/O�addressDCLRPIAM1‚CMP.L‚PIADDR(A4,D7),D4ƒlook�for�matching�mem.�map.�I/O�addrŠBEQ.S‚CLRPIAM2‹branch�if�found$ŠADD.W‚#PIALNG,D7‰bump�to�next�entryŠSUB.B‚#1,D6Ždecrement�counter0ŠBNE.S‚CLRPIAM1‹branch�if�more�entries�to�search#ŠMOVE.W�#RIONID,D0‰set�error�returnŠRTS—return�to�caller*CLRPIAM2‚CLR.L‚DODR07(A4,D7)†clear�the�map ŠCLR.L‚OCR07(A4,D7)‡and�the�restŠRTS—return�to�callerŠPAGEL******************************************************************************‚CLOSE�COMMAND*A*‚Close�all�connections�with�this�user�task�and�his�open�channelsB*‚for�this�RIO�module.�The�channels�are�put�back�to�the�pre-opened4*‚state.�All�I/O�on�this�user's�channels�is�stopped.*$*‚RIO�CLOSE�COMMAND�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�02*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�STOPPIA*L*****************************************************************************CLOSE:+ŠMOVE.L�#4,D1Žbump�past�RIO-ID�in�the�table!ŠCLR.L‚D2‘use�for�channel�counter5CLOSE10ƒCMP.L‚RIOTCB(A1,D1),A6ƒchannel�for�this�user?*ŠBNE.S‚CLOSE20Œbranch�if�not�for�this�user3ŠMOVE.W�RIOCNIF(A1,D1),D0‚get�channel�configuration4ŠBSR„STOPPIAŒgo�stop�I/O�on�this�channel�D2�=�chan�#?ŠMOVE.W�#$FFFF,RIOTCB(A1,D1)�set�this�channel�entry�to�not�used5CLOSE20ƒADD.L‚#CHANLNG,D1ˆpoint�to�next�channel�entryŠADD.L‚#1,D2Žcount�this�channel$ŠCMP.L‚#16,D2�searched�all�channels?&ŠBNE.S‚CLOSE10Œbranch�if�more�channelsŠCLR.L‚D0‘set�for�no�errorsŠBRA„NRMEXITŒand�return�to�CMRŠPAGED********************************************************************* 4*‚STOPPIAƒdeactivate�I/O�on�specified�channel�number*&*‚Entry:�A1�=�RIO-ID�address�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‰D0.W�=�channel�configuration%*‰D2.L�=�channel�number�to�deactivate* *‚Uses:‚D0,A0*L*****************************************************************************:STOPPIAƒMOVE.L�CCBCHB(A5),A0†get�memory�mapped�I/O�addressŠCMP.B‚#8,D2Žchannel�8-15?&ŠBGE.S‚STOPIA60‹branch�if�channel�8-15* *‰channel�0-7*5ŠBCLRƒ#2,PIA2ACR(A0)…select�output�direction�register/ŠBCLRƒD2,PIA2ADR(A0)…set�this�channel�for�input0ŠBSETƒ#2,PIA2ACR(A0)…select�output�data�register,ŠBCLRƒD2,PIA2ADR(A0)…deactivate�this�channelŠBTSTƒ#0,D0Žinput�channel?,ŠBNE.S‚STOPIART‹branch�if�no,�output�channel*/*‰input�channel�-�determine�if�using�interrupts* ŠBTSTƒ#1,D0Žinterrupts�disabled?"ŠBNE.S‚STOPIART‹branch�if�disabled-ŠBTSTƒ#0,D2Žsee�if�odd�or�even�channel�number,ŠBNE.S‚STOPIA10‹branch�if�odd�channel�number7ŠMOVE.B�#1,D0Ževen�chan�-�disable�interrupts�bit�#�is�0ŠBRA.S‚STOPIA20‹and�continue>STOPIA10�MOVE.B�#4,D0�odd�chan�-�disable�interrupts�bit�#�is�3.STOPIA20�CMP.B‚#1,D2�get�actual�channel�number)ŠBGT.S‚STOPIA30‹branch�if�not�channel�0-15ŠBCLRƒD0,PIA1ACR(A0)…disable�interrupts�-�channel�0-1STOPIART‚RTS—return�to�caller.STOPIA30‚CMP.B‚#3,D2Žsee�if�channel�number�2-3!ŠBGT.S‚STOPIA40‹branch�if�not�2-33ŠBCLRƒD0,PIA1BCR(A0)…disable�interrupts�channel�2-3ŠBRA.S‚STOPIART‹and�return.STOPIA40‚CMP.B‚#5,D2Žsee�if�channel�number�4-5!ŠBGT.S‚STOPIA50‹branch�if�not�4-53ŠBCLRƒD0,PIA2ACR(A0)…disable�interrupts�channel�4-5ŠBRA.S‚STOPIART‹and�return;STOPIA50‚BCLRƒD0,PIA2BCR(A0)…disable�interrupts�channel�6-7ŠBRA.S‚STOPIART‹and�returnŠPAGE**‰channel�8-15*(STOPIA60‚MOVE.L�D2,D0Žget�channel�number!ŠSUB.L‚#8,D0Žmake�0-7�type�number5ŠBCLRƒ#2,PIA2BCR(A0)…select�output�direction�register"ŠBCLRƒD0,PIA2BDR(A0)…set�for�input0ŠBSETƒ#2,PIA2BCR(A0)…select�output�data�register,ŠBCLRƒD0,PIA2BDR(A0)…deactivate�this�channelŠRTS—return�to�callerŠPAGEF************************************************************************‰OUTON�-�TURN�ON�RELAY�COMMAND;*‰This�command�activates�relays�for�specified�channels�that9*‰have�previously�been�opened�for�output�by�the�same�task<*‰requesting�this�activation.‚The�parameter�block�is�checked9*‰for�errors�before�any�relay�is�activated.‚No�channel�is!*‰activated�if�an�error�is�found.9*‰All�channels�within�a�PIA�are�activated�sumultaneously.>*‰Outon�reads�the�pia�data�register�to�find�the�current�state.*%*‰RIO�OUTPUT�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�034*‰DS.Wƒ1ƒbit�mask�containing�channel�#'s�to�activate*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�DOOUT**L*****************************************************************************OUTON:ŠPUSHPOINT‘save�all�pointers3ŠCLR.L‚D3‘flag�to�ck�para.�blk.�before�doing�output.OUTON10ƒMOVE.L�#4,D1Žbump�past�RIO-ID�in�table!ŠCLR.L‚D2‘use�for�channel�counterŠCLR.L‚D0‘clear�for�use+ŠMOVE.W�CMDCHN(A3),D0†get�channels�to�start8ŠMOVE.WƒCMDCHN(A3),D3„copy�ON�request�to�check�register.)OUTON20ƒBTSTƒD2,D0Žactivate�this�channel?0ŠBEQ.S‚OUTON30Œbranch�if�no�-�check�next�channel5ŠCMP.L‚RIOTCB(A1,D1),A6ƒchannel�belonge�to�this�user?"ŠBNE.S‚OUTONERŒbranch�if�no,�error3ŠMOVE.W�RIOCNIF(A1,D1),D4‚get�channel�configurationŠBTST‚#0,D4�an�output�channel?+ŠBEQ.S‚OUTONER1‹branch�if�not�output,�error.ŠBCLRƒD2,D3Žnegate�check�flag�for�this�channel$ŠTST„D3‘is�all�of�parameter�checked?(ŠBNE.S‚OUTON30Œbranch�if�not�all�checked5ŠBSR„DOOUTŽgood�parameter�block�-�go�activate�channelŠBRA.S‚OUTONEXŒnormal�exit/OUTON30ƒADD.L‚#1,D2Žbump�to�next�channel�number -ŠADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry'ŠCMP.L‚#16,D2�checked�all�the�channels?/ŠBNE.S‚OUTON20Œbranch�if�more�channels�to�check*<*Fall into invalid command for error return (error in OUTON)*AOUTONERƒMOVE.W�#RIOICU,D0‰set�invalid�command�for�this�user�errorŠBRA.S‚OUTONRTŒand�return?OUTONER1‚MOVE.W�#RIOICC,D0‰set�invalid�command�for�this�channelŠBRA.S‚OUTONRTŒand�return$OUTONEXƒCLR.L‚D0‘set�for�good�return%OUTONRTƒPOP_POINT‘recall�all�pointersŠBRA„NRMEXITŒgo�return�to�CMR‰PAGE** DOOUT…EQU„***A*DOOUT talks directly to the PIA data reg.s and turns on outputs.**‰On�entry�to�DOOUT:8*‰D0�contains�(16�bit)�bit�mask�for�desired�ON�channels.<*‰A5�contains�address�of�CCB�from�which�I/O�base�addr�is�ob.*-“MOVE.L„A2,-(A7)Œsave�address�of�CMR�para�blk*“MOVE.L„CCBCHB(A5),A2‡get�I/O�base�address#“NOT‡D0’logic�inversion�in�RIO�ckts*“AND.B…D0,PIA2ADR(A2)†turn�on�channels�0-7%“LSR.W…#8,D0�select�data�for�ch.�8-15+“AND.B…D0,PIA2BDR(A2)†turn�on�channels�8-15-“MOVE.L„(A7)+,A2Œrestore�addr�of�CMR�para�blk“RTS‰PAGEM******************************************************************************"*‰OUTOFF�-�TURN�OFF�RELAYS�COMMAND=*‰This�command�deactivates�relays�for�specified�channels�that9*‰have�previously�been�opened�for�output�by�the�same�task<*‰requesting�this�activation.‚The�parameter�block�is�checked;*‰for�errors�before�any�relay�is�deactivated.‚No�channel�is#*‰deactivated�if�an�error�is�found.*)*‰RIO�OUTPUT�OFF�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�044*‰DS.Wƒ1ƒbit�mask�containing�channel�#'s�to�activate*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�DOOFF*L*****************************************************************************OUTOFF:ŠPUSHPOINT‘save�all�pointers2ŠCLR.L‚D3‘flag�to�ck�para.�blk.�before�stop�output.OUTOF10ƒMOVE.L�#4,D1Žbump�past�RIO-ID�in�table!ŠCLR.L‚D2‘use�for�channel�counterŠCLR.L‚D0‘clear�for�use+ŠMOVE.W�CMDCHN(A3),D0†get�channels�to�start0ŠMOVE.WƒD0,D3Œcopy�chan.�to�turn�off�to�work�reg+OUTOF20ƒBTSTƒD2,D0Ždeactivate�this�channel?0ŠBEQ.S‚OUTOF30Œbranch�if�no�-�check�next�channel5ŠCMP.L‚RIOTCB(A1,D1),A6ƒchannel�belongs�to�this�user? ŠBNE„OUTONERŒbranch�if�no,�error3ŠMOVE.W�RIOCNIF(A1,D1),D4‚get�channel�configurationŠBTST‚#0,D4�an�output�channel?)ŠBEQ„OUTONER1‹branch�if�not�output,�error.ŠBCLR…D2,D3Œnegate�check�flag�for�this�channel$ŠTST„D3‘is�all�of�parameter�checked?(ŠBNE.S‚OUTOF30Œbranch�if�not�all�checked3ŠBSR„DOOFFŽgood�para.�block�-�go�deactivate�channelŠBRA.S„OUTOFFXŠnormal�exit/OUTOF30ƒADD.L‚#1,D2Žbump�to�next�channel�number-ŠADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry'ŠCMP.L‚#16,D2�checked�all�the�channels?/ŠBNE.S‚OUTOF20Œbranch�if�more�channels�to�check ŠBRA†OUTONEROUTOFFX�EQU�*šnormal�exitŠPOP_POINT‘recall�all�pointersŠCLR.L„D0�signal�no�errorsŠBRA�NRMEXIT�normal�exit‰PAGE*** DOOFF…EQU�**B*DOOFF‚talks�directly�to�the�PIA�output�regs�and�turns�off�outputs*G* On entry: D0 has bit map of channels to turn off (a 1 means turn off)*‹A5�has�address�of�user�CCB*:*‰DOOFF�is�called�by�OUTOFF�and�pulsed�output�deactivation*/ŠMOVE.LƒA2,-(A7)Œsave�address�of�CMR�para�block3ŠMOVE.LƒCCBCHB(A5),A2‡get�memory�mapped�I/O�address*D*‚There�is�a�logical�inversion�between�PIA�outputs�and�final�outputs**ŠOR.B…D0,PIA2ADR(A2)†turn�off�selected�0-71ŠLSR.W„#8,D0�select�information�for�channels�8-15+ŠOR.B…D0,PIA2BDR(A2)†turn�off�selected�8-152ŠMOVE.Lƒ(A7)+,A2Œrestore�address�of�CMR�para�blockŠRTSŠPAGEM******************************************************************************!*‰STAT�-�GET�INPUT�STATUS�COMMAND;*‰This�command�reads�the�status�of�specified�input�channels=*‰that�do�not�have�interrupts�enabled.‚The�channels�must�have >*‰previously�been�opened�for�input�by�this�user.‚The�parameter>*‰block�is�checked�for�errors�before�any�input�status�is�read.A*‰The�users�parameter�block�is�modified�to�signal�active�channels<*‰by�setting�the�corresponding�bit�in�the�bit-mask�word.�The;*‰corresponding�bit�number�of�inactive�channels�is�cleared.**.*‰All�channels�in�a�PIA�side�are�read�at�once.*+*‰RIO�INPUT�STATUS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�05<*‰DS.Wƒ1ƒbit�mask�containing�channels�numbers�to�read�status$*”(�this�is�also�the�returned�field)*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�GTSTAT*M******************************************************************************STAT:ŠPUSHPOINT‘save�all�pointers(ŠCLR.L‚D5‘use�for�returned�status�values2ŠCLR.L‚D3‘flag�to�ck�para.�blk.�before�read�status.STAT10„MOVE.L�#4,D1Žbump�past�RIO-ID�in�RIOTBLŠCLR.L‚D2‘channel�counterŠCLR.L‚D0‘clear�for�use;ŠMOVE.W�CMDCHN(A3),D0†get�channel�numbers�to�read�status�on3ŠMOVE.W�D0,D3Žcopy�chan�activation�req.�bit�pattern/STAT20„BTSTƒD2,D0Žread�status�for�this�channel?ŠBEQ.S‚STAT40�branch�if�no5ŠCMP.L‚RIOTCB(A1,D1),A6ƒchannel�belongs�to�this�user?1ŠBNE„OUTONERŒbranch�if�no�-�return�with�error�set3ŠMOVE.W�RIOCNIF(A1,D1),D4‚get�channel�configurationŠBTSTƒ#0,D4Žan�input�channel?9ŠBNE„OUTONER1‹branch�if�not�input�-�return�with�error�set'ŠCMP.B‚#8,D2Žsee�if�channel�number�8-156ŠBGE.S‚STAT30�branch�if�8-15�-�do�not�check�interrupts,ŠBTSTƒ#1,D4Žis�chan�1-7,�set�for�interrupts?2ŠBEQ„OUTONER1‹branch�if�set�for�interrupts�-�error6STAT30„BCLRƒD2,D3Žclr�activation�flag�for�this�channel*ŠTST„D3‘finished�checking�parameter�block?1ŠBNE.S‚STAT40�branch�if�not�finished�checking�yet.ŠBSR„GTSTAT�go�read�status�and�save�in�REG.�D5!ŠBRA.S‚STAT50�goto�procedure�exit3STAT40„ADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry(ŠADD.L‚#1,D2Žbump�to�next�channel�number#ŠCMP.L‚#16,D2�checked�all�channels?,ŠBRA„STAT20�branch�to�channel�check�sequence�X�X‚(stamp�coupling)?*‚Return�parameters:‚none�(side�effects;�writes�to�PIA�ctl�reg)* DOENBL EQU *3‰LEA‡ENBLIRQ(PC),A1†get�address�of�enable_irq�table3‰BSR‡MODIFYPIAŒmodify�PIA�control�reg�IRQ1�ctl�bits‰RTS‰PAGE *MODIFYPIA**†It's�functions�are:0*ˆa.�To�write�interrupt�control�data�to�PIA�maps=*ˆb.�To�write�interrupt�control�data�to�PIA�control�registers*>*‹It�performs�these�two�functions�be�invoking�WRITMAP�&�DOPIA.+*‹It�DOES�NOT�MODIFY�DEBOUNCE�CONTROL�DATA.***ˆInput�parameters:/*’A1„address�of�enable�/�disable�constant�table*’D2„channel�#*’A4„RIOTBL�address*’D1„X��X�X>*ˆOutput�parameters:‚none�(side�effects;�writes�PIA�registers)*MODIFYPIA EQU * ‰CLR.L…D7‰MOVE.L„D2,D5ˆsetup�channel�#2‰MOVE.W„RIOPIA(A4),D7‡get�offset�to�user's�PIA�map ‰BTST†#0,D2…even�or�odd�channel?"‰BNE.S…MODF1…branch�on�odd�channel-‰MOVE.W„(A1),D1ƒget�even�channel�control�mask ‰BRA.S…MODF2 MODF1 EQU ***ˆstage�code�for�WRITMAP*1‰MOVE.W„2(A1),D1‚get�odd�channel�IRQ�control�mask MODF2 EQU *2‰BSR‡WRITMAPƒwrite�the�new�interrupt�status�to�map,‰BSR‡DOPIA…write�the�new�control�data�to�PIA‰RTS‰SPC�10*ENBLIRQ�EQU�*†table�for�use�by�DOENBL�only@*‚MS�byte�is�OR'ed�with�control�data,�LS�byte�is�AND'ed�with�it.%‰DC.W†$01FF…enable�irq�even�channel�#$‰DC.W†$08FF…enable�IRQ�odd�channel�#;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -ŠPAGEM******************************************************************************%*ˆDSABLE�-�DISABLE�INTERRUPTS�COMMAND>*‰This�command�disables�interrupts�for�the�specified�channels.<*‰The�channels�must�have�been�opened�for�input�by�this�user,?*‰must�be�channels�0-7�only,�and�must�currently�have�interrupts;*‰enabled.‚The�parameter�block�is�checked�for�errors�before>*‰any�interrupts�are�disabled.�No�channels�are�disabled�if�any*‰error�is�found.*1*‰RIO�DISABLE�INTERRUPTS�command�parameter�block: *‰DS.Wƒ1ƒreturned�command�status*‰DS.Wƒ1ƒcommand�code�07B*‰DS.Wƒ1ƒbit�mask�containing�channel�numbers�to�disable�interrupts*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block %*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‚Calls:�DODSABL*M*****************************************************************************DSABLE:ŠPUSHPOINT‘save�all�pointers7DSABL10ƒMOVE.L�#4,D1Žset�D1�to�chan�config.�entry�(row)!ŠCLR.L‚D2‘use�for�channel�counter1ŠCLR.L‚D0‘clear�for�use�as�channel�activ.�bit�map4ŠMOVE.W�CMDCHN(A3),D0†get�channel�activation�bit�map+ŠCMP.W‚#$FF,D0Œcannot�specify�channels�8-153ŠBGT„ENABLERŒbranch�if�8-15�-�return�with�error�set(DSABL20ƒBTSTƒD2,D0Ždisable�this�channel?)ŠBEQ.S‚DSABL30Œbranch�if�not�this�channel-ŠCMP.L‚RIOTCB(A1,D1),A6ƒbelongs�to�this�user?0ŠBNE„OUTONERŒbranch�if�no,�return�with�error�set3ŠMOVE.W�RIOCNIF(A1,D1),D4‚get�channel�configurationŠBTSTƒ#0,D4Žan�input�channel?8ŠBNE„OUTONER1‹branch�in�not�input,�return�with�error�setŠBTSTƒ#1,D4Žinterrupts�enabled?1ŠBNE„OUTONER1‹branch�if�no,�return�with�error�set/ŠBSET…#1,D4Œdisable�interrupts�for�this�channel>ŠMOVE.WƒD4,RIOCNIF(A1,D1)ƒstore�out�irq�data�in�config.�RIOTBLŠPUSHALL“save�all�regs!ŠBSR„DODSABLŒgo�do�actual�disableŠPOPALL”restore�all(DSABL30ƒADD.L‚#1,D2Žbump�to�next�channel-ŠADD.L‚#CHANLNG,D1ˆbump�to�next�channel�entry"ŠCMP.L‚#8,D2Žchecked�all�channels?&ŠBNE.S‚DSABL20Œbranch�if�more�channels)ŠBRA†ENABLOKŠreturn�with�status�=�no�errsŠPAGE**.*DODSABL is a local subroutine for DSABLE only**ƒInput�parameters**’D2.W‚channel�#*’A4„RIOTBL�address*?*‚Return�parameters:‚none�(side�effects;�writes�to�PIA�ctl�reg)* DODSABL EQU *3‰LEA‡DSBLIRQ(PC),A1†get�address�of�enable_irq�table3‰BSR‡MODIFYPIAŒmodify�PIA�control�reg�IRQ1�ctl�bits‰RTS*** DSBLIRQ‚EQU‡*.‰DC.W†$00FE…disable�IRQ�on�even�channel�number%‰DC.W†$00F7…disable�IRQ�odd�channel�#;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - -‰PAGEM*******************************************************************************ˆPLSO�-�PULSED�OUTPUT�COMMAND*)*‚Entry:�A1�=�address�of�RIO-ID�in�RIOTBL%*‰A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A4�=�address�of�RIOTBL*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB***‰Exits�to�NRMEXIT***Parameter block format for pulsed output:*0*RIO parameter block (pointed to by A3 on entry)* *ˆDS.W†1‰returned�command�status*ˆDS.W†1‰command�code*ˆDS.W†1‰number�of�channels<*ƒ---ƒ---ƒ---ƒparameters�for�individual�channelsƒ---ƒ---ƒ---*ˆDS.W†1‰first�channel�number,*ˆDS.L†1‰number�of�milliseconds�for�pulse�on*ˆ.*ˆ.*ˆDS.W†1‰nth�channel�number5*ˆDS.L†1‰number�of�milliseconds�for�nth�channel�pulse*7* EACH CHANNEL IS ACTIVATED IN TURN (NON-SYNCHRONOUSLY)**M***************************************************************************** PLSO:*@*ƒPulsed_Out(IN:LIST�OF�channel�activation�request,�pulse�times;*ˆOUT:error�code)>‰ALLOCATE�CHANID,RIOPARBK†allocate�channel�id�&�RIO�para�block3‰STORE…A3,RIOPARBK‰save�RIO�parameter�block�address**†Initiate�pulsed�output*!‰CLR.L…D6’clear�working�registers ‰CLR.L…D3’. ‰CLR.L…D2’. ‰CLR.L…D0’.*$*ˆget�number�of�channels�to�activate*<‰MOVE.W„CMDCHN(A3),D0‡get�number�of�chan's�from�RIO�para�blk**‡WHILE�channel�count�>�0*PLSO1:$‰TST.W…D0’loop�on�#�of�chan.'s�to�do ‰BEQ‡PLSOX**ˆDO**‡get�first�channel�number* ‰CLR.L…D5‰MOVE.W„NUMCHAN(A3,D6),D5$‰STORE…D5,CHANID‹save�channel�number*G* Channel ID will consist of user CCB address + chan number in LS byte.*+‰MOVE.L„A5,D7�copy�user's�CCB�address�to�D75‰ADD.L…D7,CHANID(A7)‡CHANID�now�has�complete�chan.�ID"‰MOVE.L„D5,D7�copy�channel�#�to�D7,‰BSR‡BIN_BIT�convert�binary�to�bit�map�in�D5*)*‚IF�channel�belongs�to�current�user�THEN*6‰MULU†#CHANLNG,D7‰compute�offset�to�nth�chan�in�RIOTBL%‰ADD‡#4,D7�bump�to�user�TCB�in�RIOTBL-‰CMP.L…RIOTCB(A1,D7),A6„compare�TCB�addresses1‰BNE.S…PLSOER1�branch�on�channel�not�current�user**ˆDO'*ˆGet�channel�configuration�from�RIOTBL*  8‰MOVE.W„RIOCNIF(A1,D7),D3ƒget�channel�config�from�RIOTBL*&*‚IF�channel�is�an�output�channel�THEN* ‰BTST†#0,D3.‰BEQ.S…PLSOER2ƒbranch�on�not�an�output�channel**„DO2*…Get�pulse�time�from�RIO�commmand�parameter�block*‰MOVE.L„CHNCNFG(A3),D3*%*„IF�pulse�time�>�pulse_min_time�THEN*'‰BEQ.S…PLSOER3ƒbranch�on�pulse�time�=�0**„DO-*†request�periodic�activation(this�channel�#)*2‰LEA‡PLSOFF(PC),A0‡point�to�pulse�turn�off�routine%‰CLR.L…D1’set�request�for�1�time�only6‰MOVE.B„CCBPPRIO(A5),D1…set�act.�priority�same�as�task/‰LOAD†D2,CHANID‹setup�channel�ID�to�goto�PLSOFF'‰MOVE.L„D3,A1�setup�activation�interval‰PUSHALL"‰TR0$.RQPA˜pass�request�for�wakeup*)*‚If�no�err�in�periodic�act.�request�THEN*‰BRA.S…RQPAOKŽgood�return(‰BRA.S…PLSOER4�err�in�periodic�act.�req.**†DO*RQPAOK:‰POPALL(‰PUSHALL—a�more�elegant�way�to�do�this�?*"*ˆactivate_this_channel(channel�#)*$‰MOVE.L„D5,D0�pass�bit�mask�to�DOOUT ‰BSR‡DOOUT‰POPALL**†END*ƒEND*ƒdecrement�channel�count* ‰SUB‡#1,D0**END* ‰BRA‡PLSO1**ˆError�handling*PLSOER1‚CLR.L…D00‰MOVE.B„#RIOICNS,D0‰channel�not�for�current�user ‰BRA.S…PLSOX1PLSOER2: ‰CLR.L…D00‰MOVE.B„#RIOICC,D0Šchannel�not�an�output�channel ‰BRA.S…PLSOX1PLSOER3:"‰CLR.L…D0’requested�pulse�time�=�03‰MOVE.B„#RIOCNFG,D0‰return�'bad�configuration'�code ‰BRA.S…PLSOX1PLSOER4:‰POPALL ‰CLR.L…D0+‰MOVE.B„RIOBSY,D0‹periodic�activation�error ‰BRA.S…PLSOX1Žreturn�device�busy‰SPC�2** Pulsed output good exit point*;PLSOX„LOAD†A3,RIOPARBK‰restore�RIO�para�block�address�to�A3‰CLR.L…D0ˆset�for�normal�returnPLSOX1: ‰ADD.L…#12,A7*‰BRA†NRMEXIT„goto�normal�common�exit�point‰PAGE**‡PULSED�OUTPUT�DEACTIVATION:**ˆPulsed�output�de-activation.!*ˆEntered�by�periodic�activation. *ƒOn�entry:?*ˆD1�contains�channel�ID�composed�of�user's�CCB�address�in�M.S.8*ˆ3�bytes,�and�channel�number�(0-15)�in�least�sig.�byte.*PLSOFF:‰PUSHALL&‰MOVE.B„D1,D5�save�combined�channel�ID ‰AND.B…#0,D1�recover�CCB�address+‰MOVE.L„D1,A5�stage�CCB�address�for�'DOOFF'+‰AND.L…#$000000FF,D5‡recover�channel�number,‰BSR‡BIN_BIT�convert�chan�#�to�bit�map�in�D5"‰MOVE.L„D5,D0�stage�data�for�DOOFF‰BSR‡DOOFF�turn�off�channel‰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.@*ˆFor�input�>�15�binary�the�resultant�pattern�in�D5�is�undefined*‰ALLOCATE‚BITMAP‰CLR.L…BITMAP(A7)‰ADD.W…#1,BITMAP(A7) LOOP…SET‡* ‰TST.W…D5‰BEQ‡BINBITX�exit�on�bit�found‰ROL.W…BITMAP(A7) ‰SUB‡#1,D5 ‰BRA‡LOOP BINBITXŒEQU‡*‰MOVE.W„BITMAP(A7),D5‰DEALOC„BITMAP‰RTSŠPAGEO******************************************************************************** *ˆNORMAL�EXIT*,*‚Entry:�A2�=�address�of�CMR�parameter�block%*‰A3�=�address�of�RIO�parameter�block*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*‰D0�=�RIO�error�code*I**************************************************************************NRMEXIT:>ŠMOVE.W�D0,CMDSTA(A3)†set�return�status�in�RIO�parameter�blockŠRTS—return�to�CMRŠPAGEJ****************************************************************************ˆKILR�(KILLER)*4*“Routine�called�to�handle�unrecoverable�conditions.**K****************************************************************************KILR: ‰TR0$.KILLERŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLING�TASKS�ADDRESS�SPACE.*#*�ENTRY:ƒD5‚-�NO.�OF�BYTES�TO�CHECK*ŠD6‚-�68000�ADDRESS�(LOGICAL)*ŠA1‚-�TCB�ADDRESS*** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1**7*�EXIT:„D6�-�PHYSICAL�ADDRESS�OF�BUFFER�BASE�(IF�LEGAL)*ŠRETURN�TO�PC„FOR�GOOD�ADDRESS*”PC+2‚FOR�BAD�LENGTH*”PC+4‚FOR�BAD�ADDRESS*F*********************************************************************** IOHADRCK:%ŠBTSTƒ#0,D6‘Must�be�on�work�boundary.  )ŠBNE.S‚IOHADR4�Branch�if�bad�buffer�base.ŠTST.L‚D5”Length�can't�be�zero.2ŠBEQ.S‚IOHADR8�Don't�go�to�logphy�with�zero�count. IOHADR2ƒEQU„*1ŠMOVE.L�TCBTST(A1),A0‰Address�of�task�seg.�table. ŠTR0$.LOGPHY.ŠBRA.S‚IOHADR8�Branch�for�good�address�return.0ŠBRA.S‚IOHADR6�Branch�for�bad�byte�count�return.(ŠTST.L‚D5”Was�an�entry�pointer�returned.#ŠBEQ.S‚IOHADR4�Branch�if�no�-�ERROR)ŠTST.B‚7(A0,D5)ŽIs�this�an�MMIO�segment�?ŠBNE.S‚IOHADR8�Yes,�OK.3IOHADR4ƒADD.L‚#2,(A7)�Adjust�PC�for�invalid�return.3IOHADR6ƒADD.L‚#2,(A7)�Adjust�PC�for�invalid�return.IOHADR8ƒRTSšReturn.ŠPAGEI***************************************************************************ˆGET�TCB�ROUTINE*)*’ENTRY:�A0�=�POINTER�TO�TASK�AND�SESSION***’EXEC�ROUTINE*’REGISTERS�USED:�D0-D1/A0-A1***’EXIT:�A0�=�TCB�ADRESS**˜RETURN�TO�PC„FOR�GOOD�TASK�SPECIFICATION!*¢PC+2‚FOR�BAD�TASK�SPECIFICATION**J***************************************************************************GETTCB: ŠTR0$.GETTCB&ŠBRA.S„GETT10ŽGood�task�specification.ŠNOPšBad�task�specification.&ŠADD.L„#2,(A7)�Bad�task�specification.GETT10„RTSšReturn.ŠPAGEJ**************************************************************************** INTERRUPT SSERVICE ROUTINE*?*ƒPURPOSE:‚HANDLE�THE�RIO�INTERRUPTS�AND�NOTIFY�THE�USER�OF�THE5*�INTERRUPTS.‚OPERATES�AT�HARDWARE�INTERRUPT�PRIORITY*�LEVEL.*1*ƒENTRY:‚JSR‚FROM�INTERRUPT�HANDLER�ROUTINE�-�CMR*‹A0�-�WORK�REGISTER *‹A1�=�SELF*‹A5�=�ADDRESS�OF�CCB*‹D0�=�WORK�REGISTER*5*ƒEXIT:‚RTS�-�BACK�TO�INTERRUPT�HANDLER�ROUTINE�-�CMR*C*ŠInterrupt�handler�must�pruserve�all�data�reg.'s�&�address�reg.'s.***ƒREGISTERS�USED:ƒ01234567 *”D******** *”A*****P****ƒEXEC�ROUTINES�CALLED:‚QEVENTI**ƒCODE�IS�RE-ENTRANT**?*‚Debounce�on�interrupt�added�9/13/82.‚Debounce�is�0�to�512�ms,9*‚encoded�in�bits�8-14�of�the�channel�configuration�word.I*‚The�scale�factor�for�debounce�time�is�4�ms�per�count�in�ch.�config.�wd.*F*---------------------------------------------------------------------*RIOINT:*<* Find RIO TABLE module (board) name which matches CCB name:*-ˆMOVEM.L„A0-A6/D1-D7,-(A7)„save�all�except�D0:ˆALLOCATEƒRIOTADR,CHANUM,CLAIMCHKƒallocate�local�variables/ˆCLR.L†CLAIMCHK(A7)…clear�interrupt�claim�check-ˆMOVE.L…RIOTBL,A2‰get�address�of�RIOTBL�to�A2 ˆCLR.L…D76ˆMOVE.B„RIONMAX(A2),D7…get�max�number�of�RIOID's�to�D7#ˆMOVE.L„CCBMNEM(A5),D0…get�ccb�name2IOHI011�EQU�*‚find�matching�RIOID�loop�entry�point*ˆMOVE.L„RIOID(A2),D3‡get�RIOID�for�staging'ŠCMP.LƒD3,D0Ždoes�CCB�name�match�RIOID?#ŠBEQ.SƒIOHI020Œbranch�on�name�match,ŠADDA.W‚RIOOFST,A2‰add�offset�to�next�RIOTBL#ŠSUB.Bƒ#1,D7Žtest�for�end�of�RIOTBL*ŠBMI…IOHIPXŠbranch�to�exit�if�id�not�found ŠBRA�IOHI011 IOHI020ƒEQU�**F*‚Found�matching�names,�now�get�number�of�interrupting�channel�(to�D2)2*‚and�clear�hardware�interrupt�flag�in�PIA�device.*%‰STORE…A2,RIOTADRŠsave�RIOTBL�address,‰MOVE.L„#$0C010000,D2‡init�para�fields�in�D2)‰BSR‡IOHICLR�clr�irq�&�get�int.�channel�#+‰STORE…D2,CHANUM‹save�chan.�#�&�return�code*>* Compute address of field in RIOTBL having user's TCB address* ŠCLR.L„D4!ŠMOVE.BƒD2,D4�get�channel‚to�D4.B)ŠCMP.B„#8,D4�channel�must�be�<�8�or�error'ŠBEQ.S„IOHIPXŒexit�on�channel�not�found1ŠADD.L„#1,CLAIMCHK(A7)ƒmark�interrupt�acknowledge2ŠMULU…#6,D4�point�to�data�field�assoc�with�channel5ŠADD†#RIONTRY,D4‡add�offset�to�1st�channel�data�fieldŠADD†#4,D4�add�in�size�of�RIOID-ŠMOVE.LƒRIOTBL,A2‰get�address�of�RIOTBL�to�A26ŠMOVE.L‚RIOTCB(A2,D4),A6„A6�now�has�user's�TCB�address*"*IF channel requires debounce THEN*3ŠMOVE.WƒRIOCNIF(A2,D4),D0ƒget�channel�configuration(ŠAND†#$7F00,D0‹select�debounce�time�data…IF.L†ŠTHEN*„DO;*ˆRequest�periodic�activation(CCB_adr,chan_#,debounce_time)6*ˆGenerate�channel�ID�=�CCB�address�+�channel�#�to�D2:**‰MOVE.L„A5,D7�copy�board�CCB�address�to�D7‰ADD.B…D2,D7�add�channel�number/‰MOVE.L„D7,D2�stage�channel�ID�for�period.�act.! .‰LEA‡DEBOUNCE(PC),A0…point�to�debounce�routine!‰CLR.L…D1’request�1�periodic�act.1‰MOVE.B„CCBPPRIO(A5),D1…set�priority�same�as�task&‰LSR‡#8,D0�position�debounce�time�data-‰MULU†#4,D0�multiply�by�debounce�delay�factor ‰MOVE.L„#0,A1*‰MOVE.W„D0,A1�stage�time�for�periodic�act..‰LINK†A6,#-(ALLREGS+4)…add�some�extra�room�(4)*I* NOTE: LINK has reserved space on the stack for all registers + 4 words.A*‡Now�I�can�do�MOVEM.L�to�the�stack�without�auto�inc�or�auto�dec.B*‡and�as�long�as�I�get�back�A6�unchanged,�UNLINK�A6�will�take�care+*‡of�adjusting�the�stack�pointer�correctly.*.‰MOVEM.LƒA0-A6/D0-D7,(A7)„save�all�reg.�values ‰TR0$.RQPA*/*‡IF�no�error�returned�from�per.�act.�req.�THEN*,‰BRA.S…DBACTOK�good�return�from�per.act.req.+‰BRA.S…DBACTNG�bad�return�from�per.act.req.*‡DO*DBACTOK‚EQU‡*‰Debounce�act.�req.�return�ok**ŠDisable�IRQ�on�this�channel.%*ŽStage�arguments�for�call�to�DODSABL*0‰MOVEM.Lƒ(A7),A0-A6/D0-D7„recall�register�values.‰MOVE.L„RIOTADR+4(A6),A4„recall�RIOTBL�address#‰AND‡#$000000FF,D2‡select�channel�#+‰BSR‡DODSABL�disable�IRQ.�note:�ck'�9/15/82*DBACTNG„EQU…*‰debounce�act.�req.�return�NG*ˆENDƒdisable�IRQ0‰MOVEM.Lƒ(A7),A0-A6/D0-D7„recall�register�values‰UNLK„A6*…END†debounce�setup�sequence†ELSE**…here�if�no�debounce�required*.‰LOAD†D2,CHANUM‹recall�channel�#�&�return�code‰BSR‡NOTIFYUSR†ENDI$IOHIPX„EQU�*‡'RIOINT'�procedure�exit+‰LOAD‚D0,CLAIMCHKŒget�interrupt�claim�check#‰ADD‡#16,A7Žrelease�local�variables0‰MOVEM.Lƒ(A7)+,A0-A6/D1-D7ƒrestore�all�except�D0+‰TST.L…D0’does�RIODRV�claim�this�interrupt?‰IF.L‚�THEN(‰ORˆ#1,SR�signal�CMR�'interrupt�handled'‰ELSE2‰AND‡#$FFFE,SR‹signal�CMR�'interrupt�not�from�RIO'‰ENDI‹RTS…PAGE NOTIFYUSR:*A*ˆnotify�user�by�means�of�que�event�or�wakeup�as�specified�in�the*ˆchannel�configuration�word.**„INPUT�PARAMETERS:'*’A2:�Address�of�channel�name�in�RIOTBL;*’D4:�Offset�from�channel�name�to�channel�data�field�(base) *™in�RIOTBL.*’A5:�Address�of�channel�CCB./A!;)41L9*’A6:�User's�TCB�address#*’D2:�$0C01�**@ŠMOVE.WƒRIOCNIF(A2,D4),D0�get�channel�configuration�from�channel *¤configuration�table�in�RIOTBL.)ŠBTST…#3,D0�determine:�wake-up�or�q-event ‰IF…‰THEN**ˆDO*ˆEnqueue�event;�data�staging:*$*ƒD2�=�$0C01� *ƒD3�=�RIOID*ƒD4�=�Mem�mapped�I/O�address*ƒA6�=�User's�TCB�address*8ŒMOVE.LƒCCBCHB(A5),D4…get�mem.�mapped�I/O�address�stagedŒBSR�QUEVENT�enqueue�the�eventŒRTS˜and�return�to�caller*‰ELSE*DO%ŒMOVE.LƒA6,A0Žstage�users�TCB�address#ŒTR0$.WAKEUP�,�issue�wakeup�to�user*ENDŒENDIŒRTS™return�to�caller‰PAGE=*‚IOHICLR�determines�if�the�interrupt�is�for�this�RIO�module.E*‚If�the�interrupt�is�not�for�this�channel�D2�contains�'8'�on�return.C*‚If�the�interrupt�is�for�this�RIO�module,�the�interrupting�channelI*‚number�is�returned�in�D2‚The�interrupt�in�the�PIA�is�cleared�here�also.**‚Input�parameters:%*’A5:�Points�to�the�I/O�base�address.*‚Output�parameters:(*’D2:�Contains�interrupt�channel�number.* IOHICLR EQU *0ŠMOVE.L�CCBCHB(A5),A0ˆget�I/O�base�address�to�A08ŠBTST.Bƒ#0,PIA1ACR(A0)…is�channel�#0�set�for�interrupts?/ŠBEQ.S„IOHIO01Œbranch�if�not�set�-�check�chan�18ŠBTST.Bƒ#7,PIA1ACR(A0)…set�for�interrupt�-�is�there�one?(ŠBNE†IOHI021Œbranch�on�IRQ�found�on�ch�0$IOHIO01ƒADD�#1,D2“bump�channel�count5ŠBTST.Bƒ#3,PIA1ACR(A0)…is�chan.�1�set�for�interrupts?/ŠBEQ.S„IOHIO02Œbranch�if�not�set�-�check�chan�28ŠBTST.Bƒ#6,PIA1ACR(A0)…set�for�interrupt�-�is�there�one?*ŠBNE.S�IOHI021�branch�on�IRQ�found�on�ch�1$IOHIO02ƒADD�#1,D2“bump�channel�count4ŠBTST.B‚#0,PIA1BCR(A0)†is�chan�2�set�for�interrupts?*ŠBEQ.SƒIOHIO03�branch�if�no�-�check�chan�38ŠBTST.Bƒ#7,PIA1BCR(A0)…set�for�interrupt�-�is�there�one?*ŠBNE.S! „IOHI022Œbranch�on�IRQ�found�on�ch�2$IOHIO03ƒADD‚#1,D2’bump�channel�count4ŠBTST.B‚#3,PIA1BCR(A0)†is�chan�3�set�for�interrupts?*ŠBEQ.SƒIOHIO04�branch�if�no�-�check�chan�48ŠBTST.B‚#6,PIA1BCR(A0)†set�for�interrupt�-�is�there�one?*ŠBNE.S‚IOHI022Žbranch�on�IRQ�found�on�ch�3&IOHIO04ƒADD�#1,D2“bump�channel�counter4ŠBTST.Bƒ#0,PIA2ACR(A0)…is�chan�4�set�for�interrupts?*ŠBEQ.S„IOHIO05Œbranch�if�no�-�check�chan�58ŠBTST.Bƒ#7,PIA2ACR(A0)…set�for�interrupt�-�is�there�one?*ŠBNE.S�IOHI023�branch�on�IRQ�found�on�ch�4&IOHIO05ƒADD�#1,D2“bump�channel�counter4ŠBTST.B‚#3,PIA2ACR(A0)†is�chan�5�set�for�interrupts?-ŠBEQ.SƒIOHIO06�branch�if�no�-�go�check�chan�68ŠBTST.B‚#6,PIA2ACR(A0)†set�for�interrupt�-�is�there�one?*ŠBNE.S�IOHI023�branch�on�IRQ�found‚on�ch�5&IOHIO06ƒADD�#1,D2“bump�channel�counter4ŠBTST.B‚#0,PIA2BCR(A0)†is�chan�6�set�for�interrupts?-ŠBEQ.S„IOHIO07Œbranch�if�no�-�go�check�chan�78ŠBTST.B‚#7,PIA2BCR(A0)†set�for�interrupt�-�is�there�one?*ŠBNE.S�IOHI024�branch�on�IRQ�found‚on�ch�6&IOHIO07ƒADD�#1,D2“bump�channel�counter4ŠBTST.B‚#3,PIA2BCR(A0)†is�chan�7�set�for�interrupts?2ŠBEQ.SƒIOHIONO�branch�if�no�-this�inter�not�for�me8ŠBTST.B‚#6,PIA2BCR(A0)†set�for�interrupt�-�is�there�one?*ŠBNE.S�IOHI024�branch�on�IRQ�found‚on�ch�77IOHIONOƒADD�#1,D2“set�chan�#�=�8�=�interrupt�not�for�me ŠRTS™return�to�interrupt�handler5IOHI021ƒTST.B„PIA1ADR(A0)ˆreading�data�reg�clears�IRQŠRTS™and�return-IOHI022ƒTST.BƒPIA1BDR(A0)‰clear�the�interruptŠRTS™and�return(IOHI023ƒTST.BƒPIA2ADR(A0)‰clear�IRQ�flagŠRTS™and�return(IOHI024ƒTST.BƒPIA2BDR(A0)‰clear�IRQ�flag‰RTSšand�return‹PAGE'*‹DEBOUNCE�-�interrupt�debounce�routine3*‹Control�returns�here�when�the�periodic�activation*‹request�time�expires.*ƒInput�parameters:**’D1:�CCB�address�+�channel�#�(in�ls�byte)* DEBOUNCE:‰PUSHALL�save�all�registers*F*‚IF�(((channel�config�=�rising�edge�IRQ)�AND�(channel�state�=�up))�ORH*†((channel�config�=�falling�edge�IRQ)�AND�(channel�state�=�down)))�THEN*0*…Compute�offset�for�this�channel�in�the�RIOTBL:*5‰MOVE.L„#$0C010000,D2‡setup�data�fileds�for�NOTIFYUSR!‰CLR.L…D3’clear�working�registers ‰CLR.L…D4’. ‰CLR.L…D6’.%‰MOVE.B„D1,D4�extract�channel�#�to�D46‰MOVE.B„D4,D2�complete�stage�of�chan�data�to�NOTIFYUSR*‰MOVE.B„D4,D3�save�copy�of�channel�#�in�D35‰MULU†#6,D4�point�to�data�field�for�channel�in�RIOTBL7‰ADD‡#RIONTRY+RIOCNIF,D4�add�offset�to�1st�channel�data*'*ˆGet�channel�I/O�address�base�from�CCB*'‰AND‡#$FFFFFF00,D1‡clear�ls�byte�in�CCB#‰MOVE.L„D1,A5�put�CCB�address�on�A5*‰MOVE.L„CCBCHB(A5),A1‡get�I/O�base�address*+*ˆFind�RIOTBL�data�section�for�this�channel*+‰MOVE.L„RIOTBL,A2‹get�address�of�the�RIOTBL ‰CLR.L…D70‰MOVE.L„CCBMNEM(A5),D0†get�channel�name�from�CCB1‰MOVE.B„RIONMAX(A2),D6†get�max�number�of�RIOTBL's LOOP…SET‡*.‰MOVE.L„RIOID(A2),D5ˆget�channel�name�from�CCB%‰CMP.L…D5,D0�channel�name�=�CCB�name? ‰BEQ.S…FOUND13‰ADD.W…RIOOFST,A2Šbump�to�next�RIOID�(channel�name)!‰SUB‡#1,D6�decrement�loop�counter*‰BEQ.S…DBERR�err�if�channel�name�not�found ‰BRA�LOOPFOUND1:/‰MOVE.L„RIOTCB(A2,D4),A6†get�user's�TCB�address3‰BTST†#2,RIOCNIF+1(A2,D4)ƒconfig�=�rising�edge�IRQ? ‰IF…‡THEN*%* DO if set for rising edge interrupt*-‰BTST†D3,PIA1ADR(A1)†channel�status�=�hi�now? �IF‚ƒTHEN*9*‰DO‚notify�user�if�still�on�rising�edge�-�good�interrupt*ŒPUSHALL”save�all�regsŒBSR„NOTIFYUSRŒPOPALL•restor�all�regs**‰END„of�interrupt�on�rising�edge�sequenceˆENDIˆELSE*?*„Else�the�channel�configuration�is�for�falling�edge�interrupt.!*†DO‚see�if�still�on�falling�edge*-‰BTST†D3,PIA1ADR(A1)†channel�status�=�lo�now? †IF‚ƒTHEN*5*†Channel�status�=�lo‚-�notify�user�of�good�interrupt*†DO‰PUSHALL‰BSR�NOTIFYUSR‰POPALL"*†END‚of�falling�edge�IRQ�sequence‡ENDI**‚ENDƒof�debounce�sequence*ƒENDI*"*ˆEnable�IRQ�on�debounced�channel:***BEGIN�stage�parameters�for�call�to�DOENBL*%‰AND.L…#$000000FF,D2‡select�channel�#&‰MOVE.L„A2,A4�get�RIOTBL�address�to�A4)‰CLR.L…D1’" set�debounce�data�field�to�null.‰BSR�DOENBL”invoke�routine�to�enable�interrupt*END*/DBERR�EQU�*‚debounce�err;�riotbl�name�not�found+‰POPALLŽrestore�all�registers�before�return‰RTE›return�to�O.S.‰PAGE*H*‚QUEVENT‚enqueue's�event�to�driving�task�using�data�staged�in�registers *‹as�follows:**‹A6�=�user's�TCB�address&*‹D2�=�$0C01�*‹D3�=�RIOID‚(module�name)*‹D4�=�mem�mapped�I/O�address** QUEVENT EQU *‹PUSHALL”push�all�regs"‹MOVE.L…A6,A0Žstage�user's�address ‹TR0$.QEVNTI)‹BRA.SƒQUEVNTOKŒgood�return�for�que�event'‹BRA.SƒQUEVNTERŒbad�return�from�queventQUEVNTOK EQU *‹POPALL•restore�all�regs‹RTS QUEVNTER:(‹BRA�QUEVNTOK�put�a�break�here�for�debug*‰ENDéééééFTRIO…IDNTƒ1,0�RIO�subroutines**‰FORTRAN�callable�subroutines*‰for�RIO�driver�calls*$*‰CALL�RIOCMD(rio_id,param_blk_addr)*‰where�RIOCMD�may�be:*)*‰CALL�RIOPEN(rio_id,param_blk_addr)…open**‰CALL�RIOCLS(rio_id,param_blk_addr)…close3*‰CALL�RIOOUT(rio_id,param_blk_addr)…output�latched/*‰CALL�RIOOFF(rio_id,param_blk_addr)…output�off+*‰CALL�RIOSTA(rio_id,param_blk_addr)…status6*‰CALL�RIOENB(rio_id,param_blk_addr)„enable�interrupts7*‰CALL�RIODSB(rio_id,param_blk_addr)„disable�interrupts2*‰CALL�RIOPLS(rio_id,param_blk_addr)„output�pulsed*,*‰All�arguments�for�the�calls�are�identical.7*‰The�contents�of�the�param_blk�for�each�call�is�unique*‰to�the�call.*6*‰All�the�command�subroutines�call�a�common�subroutine3*‰RIOSET�to�build�the�initiate�I/O�parameter�block.**‰STACK�FOR�ALL�CALLS:*7*‰deepest�stack:�(stack�address�stays�at�RIOSET�return)0*˜command�codeƒ2�bytes�(initiate�I/O�param.�blk) *˜n/aŒ2�bytes*˜rio_id‰4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes *˜n/aŒ4�bytes,*˜command�addrƒ4�bytes�(rio�command�address)**˜command�lng„2�bytes�(rio�command�length)-*˜RIOSET�return‚4�bytes�deepest�stack�address *˜A3�4�bytes *˜A2�4�bytes *˜A1�4�bytes *˜D0�4�bytes*‰entry�stack:ƒreturn‰4�bytes*˜^param_blk_adr�4�bytes*˜^rio-idˆ4�bytes* ŠSECTION�9!ŠXDEFƒRIOPEN,RIOCLS,RIOOUT,RIOOFF!ŠXDEFƒRIOSTA,RIOENB,RIODSB,RIOPLS*$*‰CALL�RIOPEN(rio_id,param_blk_addr)*‰open�and�configure�channels*1RIOPEN„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers3ŠBSR„RIOSET�set-up�the�initiate�I/O�parameter�block)ŠMOVE.L�#1,(A2)Œset�the�open�command�codeRIOPN00ƒCLR.L‚D0‘clear�for�use'ŠMOVE.W�4(A2),D0‹get�number�of�channelsŠASL.L‚#2,D0Žmultiply�by�4.RIOPN05ƒADD.L‚#6,D0Žadd�in�the�6�byte�overhead-RIOPN10ƒMOVE.W�D0,(A1)Œset" �the�command�length-ŠMOVE.L�A3,A0ŽTRAP�#1�parameter�block�address#ŠMOVE.L�#60,D0�CMR�directive�numberŠTRAPƒ#1‘call�RMS68K'ŠMOVE.W�D0,(A2)Œset�the�returned�status)ŠMOVEM.L�(A7)+,D0/A1-A3„restore�registers!ŠMOVE.L�(A7)+,A0‹put�return�in�A0AAJ8R ŠLEA„8(A7),A7‹clean�up�the�stackŠJMP„(A0)�return�to�user*$*‰CALL�RIOCLS(rio_id,param_blk_addr)"*‰close�all�channels�for�this�user*1RIOCLS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block*ŠMOVE.L�#2,(A2)Œset�the�close�command�code&ŠMOVE.W�#4,D0ŽRIO�close�command�lengthŠBRA„RIOPN10Œgo�do�the�CMR�call*$*‰CALL�RIOOUT(rio_id,param_blk_addr)'*‰activate�output�on�requested�channels*1RIOOUT„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#3,(A2)Œset�the�output�command�code*RIOUT10ƒMOVE.Wƒ#6,D0Œset�up�command�lengthŠBRA„RIOPN10Œgo�do�the�CMR�call*$*‰CALL�RIOOFF(rio_id,param_blk_addr))*‰deactivate�output�on�specified�channels*1RIOOFF„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block/ŠMOVE.L�#4,(A2)Œset�the�output�off�command�code4ŠBRA„RIOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�RIOSTA(rio_id,param_blk_addr))*‰read�input�status�on�specified�channels*1RIOSTA„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#5,(A2)Œset�the�status�command�code4ŠBRA„RIOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�RIOENB(rio_id,param_blk_addr).*‰enable�interrpts�on�specified�input�channels*1RIOENB„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block+ŠMOVE.L�#6,(A2)Œset�the�enable�command�code4ŠBRA„RIOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�RIODSB(rio_id,param_blk_addr)0*‰disable�interrupts�on�specified�input�channels*1RIODSB„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block,ŠMOVE.L�#7,(A2)Œset�the�disable�command�code4ŠBRA„RIOUT10Œgo�set�command�length�&�do�the�CMR�call*$*‰CALL�RIOPLS(rio_id,param_blk_addr)>*‰activate�output�for�x#�of�milliseconds�on�specified�channels*1RIOPLS„MOVEM.L�D0/A1-A3,-(A7)„save�some�registers5ŠBSR.S‚RIOSET�set-up�the�initiate�I/O�parameter�block2ŠMOVE.L�#8,(A2)Œset�the�pulsed�output�command�codeŠCLR.L‚D0‘clear�for�use,ŠMOVE.W�4(A2),D0‹get�specified�#�of�channelsŠASL.L‚#2,D0Žmultiply�by�6ŠADD.W‚4(A2),D04ŠBRA„RIOPN05Œgo�set�command�length�&�do�the�CMR�callŠPAGE*4*‰RIOSET�set�up�the�CMR�initiate�I/O�parameter�block,*‰returns:ƒA1=address�for�RIO�command�length(*”A2=RIO�command�parameter�block�address)*”A3=initiate�I/O�parameter�block�address*(RIOSET„CLR.W‚-2(A7)�clear�command�length-ŠLEA„-2(A7),A1Šsave�address�of�command�length$ŠMOVE.L�24(A7),A0Šget�param_blk_addr%ŠMOVE.L�A0,-6(A7)Šsave�param_blk_addr,ŠMOVE.L�A0,A2Žsave�param_blk_addr�for�returnŠCLR.L‚-10(A7)Œnot�usedŠCLR.L‚-14(A7)Œnot�usedŠCLR.L‚-18(A7)Œnot�usedŠMOVE.L�28(A7),A0Šget�^rio_idŠMOVE.L�(A0),-22(A7)‡get�rio_idŠCLR.W‚-24(A7)Œnot�used0ŠMOVE.W�#$0700,-26(A7)…initiate�I/O�command�code4ŠLEA„-26(A7),A3‰initiate�I/O�parameter�block�addressŠRTS—return�to�callerŠENDé# éé‰SPC�10!*†---†---…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*‚which�are�referred�to�as�an�offset�from�stack�pointer.\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,A7*ƒENDM*B*DEALLOCATE�MACRO‚has�to�be�named�DEALOC�to�overcome�assembler�bug 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. *The�syntax�is:‚LOAD�Rn,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.!*The�syntax�is:‚STORE�Rn,VARNAME.?*The local storage is DYNAMICALLY ALLOCATED by macro 'ALLOCATE'* STORE MACRO*‰MOVE.L„\1,\2(A7)‰ENDM*‰SPC�5PUSHPOINTŠ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ˆSpace�for�all�the�reg.'s�in�the�stack** *NOW USE THEM *MACTEST:* *ˆPUSHPOINT *ˆPUSHALL&*ˆALLOCATE�COUNT,POINT,CHAR,VAL,MURPHY*ˆMOVE.L„#12345,D1*ˆSTORE†D1,COUNT*ˆLOAD‡D2,COUNT(*ˆDEALLOCATE�COUNT,POINT,CHAR,VAL,MURPHY*ˆPOPALL *ˆPOP_POINT*ˆRTS*ˆEND*‰PAGEZ`=/*=/*†IOCFAIL.AF=/*F=/* Chain file to assemble device-failure routine which is called when2=/* a level-4 interrupt occurs in the RAD1 driver.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to IOCFAIL.LS=/*=/IFC \1ƒ=ARG�IOCFAIL.LS=/ENDIF=/*=ASM IOCFAIL.SA,IOCFAIL.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDééé# éééc=/*=/*†M600DRV.AF=/*B=/*�Chain�file�to�assemble�the‚MVME600�A/D�CONVERTER�device�driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M600DRV.LS=/*=/IFC \1ƒ=ARG�M600DRV.LS=/ENDIF=/*$=ASM M600DRV.SA,M600DRV.RO,\1;MRZ=70=/*{ Included files are:=/*ƒM600CMTS.SA=/*ƒM600SERV.SA=/*ƒM600INTL.SA=/*ƒM600CMDS.SA=/*}=/*=ENDéééééél=/*=/*†M600LIB.AF=/*7=/* Chain file to assemble FORTRAN-callable subroutines)=/* to interface with the MVME600 driver.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M600LIB.LS=/*=/IFC \1ƒ=ARG�M600LIB.LS=/ENDIF=/*=ASM M600LIB.SA,M600LIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDé$ éééééu=/*=/*†M605DRV.AF=/*B=/*�Chain�file�to�assemble�the‚MVME605�D/A�CONVERTER�device�driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M605DRV.LS=/*=/IFC \1ƒ=ARG�M605DRV.LS=/ENDIF=/*$=ASM M605DRV.SA,M605DRV.RO,\1;MRZ=75=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.M605DRV.EQ=/*}=/*=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$ „=ARG�M605LIB.LS=/ENDIF=/*=ASM M605LIB.SA,M605LIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=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ƒ=ARG�M610DRV.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ééééé% �=/*=/*†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ƒ=ARG�M610LIB.LS=/ENDIF=/*=ASM M610LIB.SA,M610LIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=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ƒ=ARG�M615DRV.LS=/ENDIF=/*$=ASM 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éééé% éé¢=/*=/*†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ƒ=ARG�M615LIB.LS=/ENDIF=/*=ASM M615LIB.SA,M615LIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=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ƒ=ARG�M625DRV.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éé& éééé´' M625LIB AFÉÉbbRADDRV AFÒÒbbRADLIB AFÛÛbbRIODRV AFääbbRIOLIB AFííbb=/*=/*†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ƒ=ARG�M625LIB.LS=/ENDIF=/*=ASM M625LIB.SA,M625LIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=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ƒ=ARG�RADDRV.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ééééééÊ=/* =/*†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ƒ=ARG�RADLIB.LS=/ENDIF=/*=ASM RADLIB.SA,RADLIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=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ƒ=ARG�RIODRV.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ééééééÜ=/* =/*†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ƒ=ARG�RIOLIB.LS=/ENDIF=/*=ASM RIOLIB.SA,RIOLIB.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDé' éééééå'M600DRV TEST600 SAúúJ‚bbTEST600 AFKKbbN*******************************************************************************Ì**Ì**�MVME600�&�605…Test�Programž**Ì**Ì*N********************************************************************************G* This program was written to test both the MVME600 and MVME605 driver.**    *‰Modification�HistoryN*-----------------------------------------------------------------------------*�10/26/84‡DUH�Initial�writing   *�1.‚Introduction*F*‰This�program�was�written�to�test�the�MVME600�and�the�MVME605�driver.F*‚This�program�will�ask�for�the�channel�number�of�the�D/A�module�and�aK*‚digital�value�to�convert�for�that�channel.‚The�program�will�then�read�theG*‚MVME600�A/D�channel�and�compare�with�what�was�written�to�the�D/A.‚The*‚result�is�output�on�the�CRT.*8*‰This�program�assumes�the�boards�are�jumpered�as�shown:* *‚VME600: *„J3‚(open)‚address�offset�$1E00*„J4‚1-2…interrupt�-�not�used*„J5‚(open)‚single�ended�mode*„J6‚1-2…single�ended�mode*„J7‚2-3…single�ended�mode* *‚VME605: *„J2,J4,J5,J6‚3-4†+/-�10v�output*„J3‹3-4†address�offset�$1E00*C*‚Connect�an�output�channel�(0-3)�of�the�VME605�to�an�input�channel>*‚on�the�VME600.‚You�must�use�the�SAME�channel�on�both�boards.*ŠPAGE ,*£ASCVAL,�BHLCVT,�and�CVT2�are�commonly�used**£functions�which�are�modules�in�a�library(*£file�called�UTILIB.RO.‚A�call�to�these'*£functions�are�included�in�this�source)*£program,�which�is�provided�with�an�XREF&*£declaration.‚This�also�r( equires�that'*£UTILIB.RO�be�available�to�the�linkage$*£editor�during�the�linking�process.%*£See�TEST605.LF�for�link�chain�file. -ŠXREFƒASCVAL�Converts�ASCII�to�a�binary�value$*£This�routine�will�convert�an�ASCII,*£character�string�representing�a�decimal�or,*£hexidecimal�value�to�the�equivalent�binary,*£value.‚If�a�dollar�sign�($)�is�encountered&*£hexidecimal�conversion�is�performed;,*£otherwise�decimal�conversion�is�performed.+*£An�empty�character�string�field�passed�toòBû:J >IA#B+I3M;,*£this�function�in�A0�produces�a�zero�binary'*£value.‚Conversion�terminates�when�the)*£first�invalid�character�is�encountered.'*£ENTRY:‚A0�-�Starting�address�of�ASCII*°character�string�to�convert#*£EXIT�:‚D1�-�Character�that�caused *°termination%*«D2�-�Class�code�of�terminating�char"*«D3�-�Binary�result�of�conversion*«A0�-�Address�of�the�character *°following�the�terminating�char 8ŠXREFƒBHLCVT�Converts�4-byte�binary�value�to�ASCII�digit)*£This�routine�will�convert�a�long�binary-*£word�value�to�a�hexadecimal�value�expressed)*£as�an�8�character�ASCII�string.‚Leading*£zeros�are�suppressed.,*£ENTRY:‚D0.L�-�Binary�value�to�be�converted(*£EXIT�:‚D2.L�-�Four�high�order�bytes�of*²converted�value *«D3.L�-�Four�low�order�bytes�of*²converted�value 6ŠXREFƒCVT2�Converts�two�ASCII�decimal�digits�to�binary-*£This�routine�will�convert�two�ASCII�decimal(*£digits�to�the�equivalent�binary�value.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary**£value.‚Conversion�terminates�when�a�non-*£decimal�digit�is�encountered)*£ENTRY:‚A0�-�Address�of�most�significant*°ASCII�decimal�digit)*£EXIT�:‚D0�-�Binary�result�of�conversion!*«A0�-�Address�of�the�terminating *°character ŠPAGE:BUFSIZEƒEQU„$100�This�label�defines�the�value�for�the�size*£of�the�conversion�tableS. ŠMOVE.L�A0,IOSOUT+16-PBA(A4)�Set�the�ending�address�of�messageŠLEA„IOSOUT(PC),A0ŠTRAPƒ#2ŠENDM ŠPAGE 2ŠOPT„PCS�We�use�a�PCS�option�so�the�assembler�will%*£force�PC�relative�addressing�within(*£SECTION.‚Forces�PC�relative�addressing-*£(whenever�such�an�addressing�mode�is�legal))*£in�an�instruction�which�occurs�within�a'*£relocatable�SECTION�and�references�an,*£operand�in�a�relocatable�SECTION�(need�not**£be�the�same�SECTION�as�the�instruction).,*£Failure�to�resolve�sucn�a�reference�into�a-*£16-bit�displacement�from�the�PC�will�result)*£in�an�error.‚This�option�may�be�used�to+*£force�position�independent�code;�however,(*£this�option�does�not�force�PC�relative,*£addressing�of�absolute�operands�or�unknown*£forward�references. ŠPAGE N*******************************************************************************Ì**™D�A�T�AƒS�E�C�T�I�O�Nœ**Ì*N****************************************************************************** ŠSECTION�DATA =D_ABUF„DS.BƒBUFSIZEŒThis�is�the�buffer�area�that�will�contain**£the�delay�and�the�conversion�value�to�be *£converted. =A_DBUF„DS.BƒBUFSIZEŒThis�is�the�buffer�area�that�will�contain(*£the�converted�analog�to�digital�value. $PBA‡EQU„*’Program�Base�Address�(PBA)%*£This�label�is�used�to�designate�the+*£beginning�of�the�program.‚This�is�used�to'*£make�references�to�other�parts�of�the*£program,�relocatable. :BUFOFSTƒDC.LƒPBA-D_ABUF‰This�is�the�offset�from�PBA�to�the'*£conversion�table�so�that�the�relative**£address�can�be�found�to�make�the�program*£relocatable. 9ŠDS.WƒSTACKLEN‹This�is�the�stack�area�for�the�VME605�test2STACK…EQU„*’program.‚Registers�and�other�important,*£information�will�be�stored�on�the�stack�as)*£the�program�is�executed.‚The�stack�area'*£is�dynamic�and�will�change�during�the *£execution�of�the�test�program. 9BUFADR_DAƒDS.Lƒ1�This�is�the�storage�area�for�the�address-*£of�the�conversion�table�for�the�D/A�driver. 9BUFADR_ADƒDS.Lƒ1�This�is�the�storage�area�for�the�address-*£of�the�conversion�table�for�the�A/D�driver. =INPUTBUF‚DS.WƒSTRNGLEN‹This�is�the�storage�area�for�the�input*£strings�that�are�entered. 9STATUS„DS.Lƒ1’This�will�be�the�storage�are�for�the�status,*£code�that�is�returned�from�CMR.‚This�value-*£will�be�displayed�to�show�the�user�what�the*£error�code�was. 6NUMBER„DS.Lƒ2’Save�area�for�the�ASCII�value�of�STATUS. 8INPUT_VALUE‚DS.W‚1�Entered�digital�value�to�be�converted**£to�analog�(D/A)�is�stored�here�in�binary**£form�for�later�comparison�with�the�value*£read�off�the�A/D.ŠPAGE N*******************************************************************************Ì*!*–P�A�R�A�M�E�T�E�RƒB�L�O�C�K�S—**Ì*N****************************************************************************** ŠNEXTWB”Force�even�boundaryIOSOUTŠDC.Bƒ0’Request�code"ŠDC.BƒWRITEŽFunction�specificationŠDC.Wƒ8’OptionsŠDC.Bƒ0’StatusŠDC.BƒCRT�Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address  )  ŠNEXTWB”Force�even�boundaryIOSINŠDC.Bƒ0’Request�code!ŠDC.BƒREAD�Function�specificationŠDC.Wƒ0’OptionsŠDC.Bƒ0’Status"ŠDC.BƒKEYBOARD‹Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address*#*‚CMR�Initiate�I/O�parameter�block:CMRBLK„DC.Bƒ7’Initiate�I/OŠDC.BƒUNUSED�UnusedŠDC.WƒUNUSED�Unused/ŠDC.Lƒ'DAC1'�Channel�name�(Dynamically�changed)ŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�Unused$ŠDC.Lƒ0’Address�of�I/O�control�block#ŠDC.Lƒ0’Length�of�I/O�control�blockŠPAGE*2*‚OPEN�command�parameter�block�for�the�D/A�driver:*OPEN_DAƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�codeŠDC.Wƒ1’#�of�channels�to�open-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)4OLEN_DAƒEQU„*-OPEN_DAŠLength�of�OPEN�parameter�block*5*‚CONVERT�command�parameter�block�for�the�D/A�driver:*CONV_DAƒDC.Wƒ0’Returned�status�from�driver"ŠDC.WƒCONVERTŒConvert�command�code ŠDC.Wƒ1’#�of�channels�to�convert0ŠDC.Wƒ0’Channel�to�convert�(Dynamically�changed)ŠDC.Wƒ1’#�of�conversions%ŠDC.Lƒ0’Buffer�address�of�conversionsŠDC.Wƒ01‘Wake�up�when�done7CLEN_DAƒEQU„*-CONV_DAŠLength�of�CONVERT�parameter�block*2*‚OPEN�command�parameter�block�for�the�A/D�driver:*OPEN_ADƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�code-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)4OLEN_ADƒEQU„*-OPEN_ADŠLength�of�OPEN�parameter�block*5*‚CONVERT�command�parameter�block�for�the�A/D�driver:*CONV_ADƒDC.Wƒ0’Returned�status�from�driver"ŠDC.WƒCONVERTŒConvert�command�code ŠDC.Wƒ1’#�of�channels�to�convert )ŠDC.Wƒ0’Command�ID�(return�when�complete)0ŠDC.Wƒ0’Channel�to�convert�(Dynamically�changed) ŠDC.Wƒ00‘Channel�completion�code%ŠDC.Lƒ0’Buffer�address�of�conversionsŠDC.Wƒ2’Buffer�size�in�bytesŠDC.Wƒ0’Control�field7CLEN_ADƒEQU„*-CONV_ADŠLength�of�CONVERT�parameter�block*@*‚CLOSE�command�parameter�block�for�the�A/D�and�the�D/A�drivers:)CLSBLK„DC.Wƒ0’Returned�status�from�driverŠDC.WƒCLOSEŽClose�command�codeCLOSLENƒEQU„*-CLSBLK ŠNEXTWB ŠPAGE N*******************************************************************************Ì**œM�E�S�S�A�G�E�S¡**Ì*N****************************************************************************** ŠSECTION�MESSAGES CHEAD†DC.BƒCR,LF,LF,'MVME600�&�MVME605�Driver�Test�Program',CR,LF,LF HEADE…EQU„*-1ŠNEXTWB1MESS1…DC.Bƒ'…Number�of�the�channel�to�convert‚>�'MESS1E„EQU„*-1ŠNEXTWB4MESS5…DC.Bƒ'‚Value�to�be�converted�($000�-�$FFF)‚>�'MESS5E„EQU„*-1ŠNEXTWBMESS8…DC.Bƒ'Entered�value�=�'MESS8E„EQU„*-1ŠNEXTWB#MESS9…DC.Bƒ'�=�Result�value.',CR,LFMESS9E„EQU„*-1ŠNEXTWB6MESS10„DC.BƒCR,LF,'<<<�Starting�conversions�>>>',CR,LFMESS10EƒEQU„*-1ŠNEXTWB2MESS11„DC.BƒCR,LF,'<<<ƒConversions�doneƒ>>>',CR,LFMESS11EƒEQU„*-1ŠNEXTWB3BADOPN_DA�DC.BƒCR,LF,'***�OPEN�ABORTED�D/A�***�--�'BOPEN_DA‚EQU„*-1ŠNEXTWB9BADCNV_DA�DC.BƒCR,LF,'***�CONVERSION�ABORTED�D/A�***�--�'BCNV_DAƒEQU„*-1ŠNEXTWB4BADCLS_DA�DC.BƒCR,LF,'***�CLOSE�ABORTED�D/A�***�--�'BCLS_DAƒEQU„*-1ŠNEXTWB3BADOPN_AD�DC.BƒCR,LF,'***�OPEN�ABORTED�A/D�***�--�'BOPEN_AD‚EQU„*-1ŠNEXTWB9BADCNV_AD�DC.BƒCR,LF,'***�CONVERSION�ABORTED�A/D�***�--�'BCNV_ADƒEQU„*-1ŠNEXTWB4BADCLS_AD�DC.BƒCR,LF,'***�CLOSE�ABORTED�A/D�***�--�'BCLS_ADƒEQU„*-1ŠNEXTWB+STATUSMƒDC.Bƒ'Error�code�returned�in�D0�=�'STATUSME‚EQU„*-1ŠNEXTWBCRLF†DC.BƒCR,LF CRLFE…EQU„*-1ŠNEXTWBSPACE…DC.Bƒ'„'SPACE_END�EQU„*-1ŠNEXTWBŠPAGEN*******************************************************************************Ì**–P�R�O�G�R�A�MƒS�E�C�T�I�O�N™**Ì*N****************************************************************************** ŠSECTION�CODE PROGSTRTŠLEA„STACK(PC),A7.ŠLEA„PBA(PC),A4‰Get�Program�Base�Address�(PBA)?ŠMOVE.L�BUFOFST(PC),D0…D0�=�offset�to�find�the�conversion�tableŠNEG.L‚D0–from�PBA3ŠLEA„(A4,D0.L),A0‡Address�for�D/A�conversion) �bufferFŠMOVE.L�A0,BUFADR_DA-PBA(A4)�Save�the�address�of�the�conversion�buffer@ŠMOVE.L�A0,CONV_DA+$A-PBA(A4)�the�physical�address�of�the�buffer3ŠADD.L‚#BUFSIZE,A0ˆAddress�for�A/D�conversion�buferFŠMOVE.L�A0,BUFADR_AD-PBA(A4)�Save�the�address�of�the�conversion�buffer@ŠMOVE.L�A0,CONV_AD+$C-PBA(A4)�the�physical�address�of�the�buffer &ŠOUTPUT�HEAD,HEADE‰Display�the�heading N*-----------------------------------------------------------------------------***‰Get�the�number�of�the�channel�to�convert*N*-----------------------------------------------------------------------------GETCHAN.ŠOUTPUT�MESS1,MESS1E‡Channel�number�to�convertŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.L�D0��#0�OR.L�D0��#3�THEN.S ŒBRA�GETCHANŠENDI@ŠMOVE.W�D0,OPEN_DA+6-PBA(A4)�Channel�number�for�D/A�OPEN„commandCŠMOVE.W�D0,CONV_DA+6-PBA(A4)�Channel�number�for�D/A�CONVERT�command@ŠMOVE.W�D0,OPEN_AD+4-PBA(A4)�Channel�number�for�A/D�OPEN„commandCŠMOVE.W�D0,CONV_AD+8-PBA(A4)�Channel�number�for�A/D�CONVERT�command **‰C�=�Constant�level�waveform*)ŒBSR„GETVAL‹Returns�D3�=�Value�to�convertŒMOVE.W�#1,CONV_DA+8-PBA(A4)@ŒMOVE.L�BUFADR_DA(PC),A0‚Get�the�address�of�the�conversion�tableŒMOVE.W�#0,D1ŒZero�delay%ŒMOVE.W�D1,(A0)+‰D1�=�Delay�value�=�0&ŒMOVE.W�D3,(A0)+‰D3�=�Value�to�convertBŒMOVE.W�D3,INPUT_VALUE-PBA(A4)‚Save�the�user�entered�digital�value%*¢for�later�comparison�with�A/D�valueŒPAGEN*-----------------------------------------------------------------------------**‰Start�the�conversions�here*N*-----------------------------------------------------------------------------**ƒOPEN�THE�D/A�CHANNEL*ŠLEA„CMRBLK(PC),A0ŠLEA„OPEN_DA(PC),A1ŠMOVE.L�#'DAC1',$4(A0)ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OLEN_DA,$18(A0)7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�toŠTRAPƒ#1‘invoke�CMR.1ŠIF��THEN.SŒCMR�returns�a�status�code�in�D0.BŒMOVE.L�D0,STATUS-PBA(A4)/ŒOUTPUT�BADOPN_DA,BOPEN_DA‚***�OPEN�ABORTED�***ŒBRA.L‚SHOW_D0ŠENDI**ƒOPEN�THE�A/D�CHANNEL*ŠLEA„CMRBLK(PC),A0ŠLEA„OPEN_AD(PC),A1ŠMOVE.L�#'AD01',$4(A0)ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OLEN_AD,$18(A0)7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�toŠTRAPƒ#1‘invoke�CMR.1ŠIF��THEN.SŒCMR�returns�a�status�code�in�D0.BŒMOVE.L�D0,STATUS-PBA(A4)/ŒOUTPUT�BADOPN_AD,BOPEN_AD‚***�OPEN�ABORTED�***ŒBRA.L‚SHOW_D0ŠENDI**ƒDO�CONVERSIONS*3ŠOUTPUT�MESS10,MESS10E…<<<ƒStarting�conversionsƒ>>> ŒLEA„CMRBLK(PC),A0ŒLEA„CONV_DA(PC),A1ŒMOVE.L�#'DAC1',$4(A0)ŒMOVE.L�A1,$14(A0)ŒMOVE.W�#CLEN_DA,$18(A0)5ŒMOVE.L�#CMR,D0ŠTell�the�driver�to�do�the�conversionsŒTRAPƒ#1*(*ƒDo�a�wait�until�the�driver�wakes�us�up*ŒMOVE.L�#19,D0ŒTRAPƒ#1 ŒMOVE.W�CONV_DA(PC),D01ŒIF��THEN.SŒCMR�returns�a�status�code�in�D0.BŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADCNV_DA,BCNV_DAƒ***�CONVERSION�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI  ŒLEA„CMRBLK(PC),A0ŒLEA„CONV_AD(PC),A1ŒMOVE.L�#'AD01',$4(A0)ŒMOVE.L�A1,$14(A0)ŒMOVE.W�#CLEN_AD,$18(A0)5ŒMOVE.L�#CMR,D0ŠTell�the�driver�to�do�the�conversionsŒTRAPƒ#1*A*‚THE�A/D�DRIVER�WILL�ONLY�RETURN�WHEN�CHANNEL�HAS�BEEN�CONVERTED*ŒMOVE.W�CONV_AD(PC),D01ŒIF��THEN.SŒCMR�returns�a�status�code�in�D0.BŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADCNV_AD,BCNV_ADƒ***�CONVERSION�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 'ŒOUTPUT�MESS8,MESS8E‡'ENTERED�VALUE�=�' ŒCLR.L‚D04ŒMOVE.W�INPUT_VALUE-PBA(A4),D0‚Get�the�entered�valueŒBSR„BHLCVTŽConvert�to�ASCIIŒMOVE.L�D2,NUMBER-PBA(A4)ŒMOVE.L�D3,NUMBER+4-PBA(A4)0ŒOUTPUT�NUMBER,NUMBER+7…Output�the�entered�value0ŒOUTPUT�SPACE,SPACE_END…'„'�(output�some�spaces) 7ŒMOVE.L�BUFADR_AD(PC),A0„Point�to�result�buffer�for�A/D ŒCLR.L‚D0ŒMOVE.W�(A0),D0�Get�the�result"ŒAND.W‚#$0FFF,D0‹Result�is�12�bitsŒBSR„BHLCVTŽConvert�to�ASCIIŒMOVE.L�D2,NUMBER-PBA(A4)ŒMOVE.L�D3,NUMBER+4-PBA(A4)/ŒOUTPUT�NUMBER,NUMBER+7…Output�the�result�value'ŒOUTPUT�MESS9,MESS9Eˆ'�=�result�value.' ŒBRA.S‚EXIT :SHOW_D0ƒMOVE* .L�STATUS(PC),D0†Get�the�status�value�returned'SHOW1_D0‚BSR„BHLCVT�Convert�it�to�ASCII9ŠMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŠMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŠOUTPUT�STATUSM,STATUSMEŠOUTPUT�NUMBER,NUMBER+7ŠOUTPUT�CRLF,CRLFE ŠBRA.S‚EXIT  CHECKQ3ŠCMP.B‚#'Q',INPUTBUF-PBA(A4)�Do�they�want�to�Quit�? ŠBEQ.S‚EXIT3ŠCMP.B‚#'.',INPUTBUF-PBA(A4)�Do�they�want�to�Quit�? ŠBEQ.S‚EXITŠRTS  EXIT**‚CLOSE�THE�CHANNELS:*ŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�#'DAC1',$4(A0)ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)1ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�D/A�channelŠTRAPƒ#1ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)/ŒOUTPUT�BADCLS_DA,BCLS_DAƒ***�CLOSE�ABORTED�***ŠENDI ŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�#'AD01',$4(A0)ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)1ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�D/A�channelŠTRAPƒ#1ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)/ŒOUTPUT�BADCLS_AD,BCLS_ADƒ***�CLOSE�ABORTED�***ŠENDI /ŠOUTPUT�MESS11,MESS11E…<<<ƒConversions�doneƒ>>> "ŠMOVE.L�#15,D0�Terminate�this�taskŠTRAPƒ#1 *=*‚Routine�to�get�the�digital�value�to�be�converted�to�analog:*GETVAL8ŠOUTPUT�MESS5,MESS5E‡Value�to�be�converted�($000�-�$FFF)ŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0!ŠBSR„ASCVAL‹D3�=�Value�to�convertŠRTS ŠEND„PROGSTRTééééé=/*=/*†M600DRV.TEST605.AF=/*,=/*†TEST600�test�program�assembly�chain�file=/*6=/*†The�command�line�will�accept�arguments�as�follows:=/*;=/*‹Argument�01…\1�=�Output�file�assembly�listing�or�device=/*H=/*†The�following�shows�the�assembly�chain�sequence.‚In�this�example�theH=/*†NULL�device�was�chosen�as�Argument�01,�however,�the�user�could�if�he5=/*†so�desired�have�requested�an�output�listing�file.=/*=/*�=CHAIN�TEST600.AF�#NULL=/*-=/*†Default�argument�01�is�M600DRV.TEST600.LS=/*=/IFC \1ƒ=ARG�M600DRV.TEST600.LS=/ENDIF=/*4=ASM M600DRV.TEST600.SA,M600DRV.TEST600.RO,\1;RZ=100=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDéé* éééC'M605DRV TEST605 SAXXWûbbTEST605 AF±±bbN*******************************************************************************Ì**Ì**šMVME605�Test�Programž**Ì**Ì*N********************************************************************************6* This program was written to test the MVME605 driver.**    *‰Modification�HistoryN*-----------------------------------------------------------------------------*�03/01/84‡KEG�Initial�writing ŠPAGE*�1.‚Introduction*C*‰This�program�was�written�to�test�the�MVME605�driver�program.‚ThisK*‚test�program�will�ask�questions�will�initialize�the�conversion�table�withN*‚the�delays�and�conversion�values�given�or�with�values�that�this�program�willL*‚generate.‚If�a�period�"."�or�a�"Q"�is�entered�for�any�of�the�questions�theD*‚program�will�terminate�and�return�back�to�VERSAdos.‚You�can�use�an,*‚oscilloscope�to�check�the�output�waveform.**�2.‚Explanation�of�Questions*'*‰A.‚Number�of�the�channel�to�convert…>;*�This�question�asks�which�channel�you�would�like�to�do�the>*�conversions�on.‚The�answer�must�be�(0�-�63),�decimal,�or�the/*�test�program�will�ask�for�a�different�answer.*'*‰B.‚(C)onstant�level‚(S)awtooth�wave„>?*�This�question�asks�for�the�type�of�waveform�you�would�like�to>*�test�for.‚An�answer�of�"C"�will�then�ask�you�question�#C�and?*�then�question�#D.‚An�answer�of�"S"�will�then�ask�you�question8*�#C�and�then�question�#E.‚An�answer�of�"O"�will�ask�you?*�question�#C�and�then�question�#D�until�you�answer�question�#C>*�with�an�$FFFF�to�exit.‚The�"O"�option�is�used�to�create�your6*�own�waveform.‚This�will�enable�the�user�to�creat‚the<*�conversion�table�with�his�own�delays�and�conversion�values* *‰C.‚Delay�between�conversionsŒ>;*�This�question�asks�for�the�delay�of�the�conversion�value.?*�This�value�can�be�from�$0�to�$FFFF�with�$0�being�no�delay�and<*�$FFFF�being�the�longest�delay.‚Each�delay�is�approximately*�1�(one)�millisecond�of�delay.***‰D.‚Value�to�be�converted�($000�-�$FFF)‚>+ P6YAa:i;qLyC�T‰F‘D™E¡^=*�This�question�asks�for�the�value�to�be�converted.‚The�value<*�can�be�from�$000�to�$FFF�with�$000�being�the�most�negative;*�value�and�$FFF�being�the�most�positive�value.‚Question�#F*�follows�this�question.*"*�ValueŠ5�volt�scaleŠ10�volt�scale* equivalent�equivalent4*�--------------------------------------------------*�$FFFŒ+5.0�volts�+10.0�volts*�$C00Œ+2.5“+5.0*�$800�0.0”0.0*�$400Œ-2.5“-5.0*�$000Œ-5.0“-10.0*%*‰E.‚Increment�for�conversion�value‡>>*�This�question�asks�for�the�increment�value�that�will�be�used;*�to�calculate�the�sawtooth�waveform�with.‚This�is�how�much@*�the�sawtooth�waveform�will�be�incremented�for�each�conversion.<*�This�value�can�be�from�$000�to�$FFF.‚Anything�outside�this>*�range�will�not�be�accepted�and�the�test�program�will�ask�for*�a�different�answer.*(*‰F.‚Number�of�times�to�do�conversions„>?*�This�question�asks�for�the�amount�of�times�to�run�through�the*�conversion�table. ŠPAGE *‚Examples:*B*‰The�following�example�should�make�a�constant�level�at�+5.0�volts:*‰if�the�input�voltage�on�the�VME605�board�is�+10.0�volts.**‰MVME605�Driver�Test�Program**&*ŒNumber�of�the�channel�to�convert‚>�0&*‹(C)onstant�level‚(S)awtooth�wave‚>�C*“Delay�between�conversions‚>�1,*‰Value�to�be�converted�($000�-�$FFF)‚>�$C00'*‹Number�of�times�to�do�conversions‚>�1    E*‰The�following�example�will�create�a�sawtooth�wave�that�will�be�from-*‰the�minimum�voltage�to�the�maximum�voltage.**‰MVME605�Driver�Test�Program**&*ŒNumber�of�the�channel�to�convert‚>�0&*‹(C)onstant�level‚(S)awtooth�wave‚>�S*“Delay�between�conversions‚>�0'*ŽIncrement�for�conversion�value‚>�$100(*‹Number�of�times�to�do�conversions‚>�50  ŠPAGE,*£ASCVAL,�BHLCVT,�and�CVT2�are�commonly�used**£functions�which�are�modules�in�a�library(*£file�called�UTILIB.RO.‚A�call�to�these'*£functions�are�included�in�this�source)*£program,�which�is�provided�with�an�XREF&*£declaration.‚This�also�requires�that'*£UTILIB.RO�be�available�to�the�linkage$*£editor�during�the�linking�process.%*£See�TEST605.LF�for�link�chain�file. -ŠXREFƒASCVAL�Converts�ASCII�to�a�binary�value$*£This�routine�will�convert�an�ASCII,*£character�string�representing�a�decimal�or,*£hexidecimal�value�to�the�equivalent�binary,*£value.‚If�a�dollar�sign�($)�is�encountered&*£hexidecimal�conversion�is�performed;,*£otherwise�decimal�conversion�is�performed.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary'*£value.‚Conversion�terminates�when�the)*£first�invalid�character�is�encountered.'*£ENTRY:‚A0�-�Starting�address�of�ASCII*°character�string�to�convert#*£EXIT�:‚D1�-�Character�that�caused *°termination%*«D2�-�Class�code�of�terminating�char"*«D3�-�Binary�result�of�conversion*«A0�-�Address�of�the�character *°following�the�terminating�char 8ŠXREFƒBHLCVT�Converts�4-byte�binary�value�to�ASCII�digit)*£This�routine�will�convert�a�long�binary-*£word�value�to�a�hexadecimal�value�expressed)*£as�an�8�character�ASCII�string.‚Leading*£zeros�are�suppressed.,*£ENTRY:‚D0.L�-�Binary�value�to�be�converted(*£EXIT�:‚D2.L�-�Four�high�order�bytes�of*²converted�value *«D3.L�-�Four�low�order�bytes�of*²converted�value   6ŠXREFƒCVT2�Converts�two�ASCII�decimal�digits�to�binary-*£This�routine�will�convert�two�ASCII�decimal(*£digits�to�the�equivalent�binary�value.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary**£value.‚Conversion�terminates�when�a�non-*£decimal�digit�is�encountered)*£ENTRY:‚A0�-�Address�of�most�significant*°ASCII�decimal�digit)*£EXIT�:‚D0�-�Binary�result�of�conversion!*«A0�-�Address�of�the�terminating *°characterŠPAGE ;BUFSIZEƒEQU„$8000ŽTh+ is�label�defines�the�value�for�the�size$*£of�the�delay�and�conversion�table. 6CLOSE…EQU„2’This�label�defines�the�code�value�that�the+*£D/A�driver�recognizes�as�the�command�code*£for�a�CLOSE�command. @CLSIZE„EQU„BUFSIZE/4ŠThis�label�defines�the�value�for�performing,*£a�loop�to�fill�the�conversion�table�with�a)*£certain�delay�and�conversion�value.‚The-*£size�is�BUFSIZE/4�because�there�are�2�words,*£per�entry,�1�word�for�delay�and�1�word�for-*£the�conversion�value,�and�there�are�2�bytes *£per�word. 4CMR‡EQU„60‘This�label�defines�the�code�value�that�we,*£must�use�to�tell�the�operating�system�that+*£we�want�to�invoke�CMR,�the�RMS68K�Channel*£Management�Routine. /CODE†EQU„8’This�label�defines�the�number�of�the%*£program�section�that�contains�code.-*£Section�8�is�a�relatively�arbitrary�section(*£but�it�is�the�section�where�the�system(*£expects�(by�default)�to�see�code�for�a*£program,�(read�only). 8CONVERTƒEQU„3’This�label�defines�the�code�value�that�the+*£D/A�driver�recognizes�as�the�command�code*£for�a�CONVERT�command. 5CRˆEQU„$0D�This�label�defines�the�code�for�a�carriage*£return 1CRT‡EQU„6’This�label�defines�the�value�for�the�LU*£number�for�the�CRT. 4DATA†EQU„0’This�label�defines�the�number�of�the�data**£section�that�contains�data.‚Section�0�is+*£a�relatively�arbitrary�section,�but�it�is-*£the�section�where�the�system�expects�to�see"*£code�for�data�(read/write�area). 6KEYBOARD‚EQU„5’This�label�defines�the�value�for�the�LU*£number�for�the�keyboard. 6LFˆEQU„$0A�This�label�defines�the�code�for�a�line�feed 3MESSAGES‚EQU„1’This�label�defines�the�number�of�the,*£messages�section�that�will�contain�all�the%*£messages.‚Section�1�is�a�relatively*£arbitrary�section. 5OPEN†EQU„1’This�label�defines�the�code�value�that�the+*£D/A�driver�recognizes�as�the�command�code*£for�an�OPEN�command. 3READ†EQU„1’This�label�defines�the�code�value�of�the&*£IOS�request�code�for�a�READ�command. ŠMOVE.L�A0,IOSOUT+16-PBA(A4)�Set�the�ending�address�of�messageŠLEA„IOSOUT(PC),A0ŠTRAPƒ#2ŠENDM ŠPAGE 2ŠOPT„PCS�We�use�a�PCS�option�so�the�assembler�will%*£force�PC�relative�addressing�within(*£SECTION.‚Forces�PC�relative�addressing-*£(whenever�such�an�addressing�mode�is�legal))*£in�an�instruction�which�occurs�within�a'*£relocatable�SECTION�and�references�an,*£operand�in�a�relocatable�SECTION�(need�not**£be�the�same�SECTION�as�the�instruction).,*£Failure�to�resolve�sucn�a�reference�into�a-*£16-bit�displacement�from�the�PC�will�result)*£in�an�error.‚This�option�may�be�used�to+*£force�position�independent�code;�however,(*£this�option�does�not�force�PC�relative,*£addressing�of�absolute�operands�or�unknown*£forward�references. ŠPAGE N**********************************************, *********************************Ì**™D�A�T�AƒS�E�C�T�I�O�Nœ**Ì*N****************************************************************************** ŠSECTION�DATA =D_ABUF„DS.BƒBUFSIZEŒThis�is�the�buffer�area�that�will�contain**£the�delay�and�the�conversion�value�to�be *£converted. $PBA‡EQU„*’Program�Base�Address�(PBA)%*£This�label�is�used�to�designate�the+*£beginning�of�the�program.‚This�is�used�to'*£make�references�to�other�parts�of�the*£program,�relocatable. 9ŠDS.WƒSTACKLEN‹This�is�the�stack�area�for�the�VME605�test2STACK…EQU„*’program.‚Registers�and�other�important,*£information�will�be�stored�on�the�stack�as)*£the�program�is�executed.‚The�stack�area'*£is�dynamic�and�will�change�during�the *£execution�of�the�test�program. 8BUFFADDR‚DS.Lƒ1’This�is�the�storage�area�for�the�address,*£of�the�conversion�table.‚This�address�will-*£be�figured�at�execution�time�so�the�program*£will�be�relocatable. =INPUTBUF‚DS.WƒSTRNGLEN‹This�is�the�storage�area�for�the�input*£strings�that�are�entered. 6DELAYVAL‚DS.Wƒ1’This�is�the�storage�area�for�the�delay(*£that�is�entered�for�the�delay�for�each *£conversion. :BUFOFSTƒDC.LƒPBA-D_ABUF‰This�is�the�offset�from�PBA�to�the'*£conversion�table�so�that�the�relative**£address�can�be�found�to�make�the�program*£relocatable. 9STATUS„DS.Lƒ1’This�will�be�the�storage�are�for�the�status,*£code�that�is�returned�from�CMR.‚This�value-*£will�be�displayed�to�show�the�user�what�the*£error�code�was.  NUMBER„DS.Lƒ2 1NUMT†DS.Lƒ1’This�is�the�storage�for�the�number�of&*£conversions�to�perform.‚This�will�be,*£changed�dynamically�after�the�question�has*£been�answered. 5INC‡DS.Wƒ1’This�is�the�storage�area�for�the�increment**£that�will�be�used�to�figure�the�sawtooth *£waveform. ŠPAGE N*******************************************************************************Ì*!*–P�A�R�A�M�E�T�E�RƒB�L�O�C�K�S—**Ì*N****************************************************************************** ŠNEXTWB”Force�even�boundaryIOSOUTŠDC.Bƒ0’Request�code"ŠDC.BƒWRITEŽFunction�specificationŠDC.Wƒ8’OptionsŠDC.Bƒ0’StatusŠDC.BƒCRT�Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address   ŠNEXTWB”Force�even�boundaryIOSINŠDC.Bƒ0’Request�code!ŠDC.BƒREAD�Function�specificationŠDC.Wƒ0’OptionsŠDC.Bƒ0’Status"ŠDC.BƒKEYBOARD‹Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address  CMRBLK„DC.Bƒ7’Initiate�I/OŠDC.BƒUNUSED�UnusedŠDC.WƒUNUSED�UnusedŠDC.Lƒ'DAC1'�Channel�nameŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�Unused$ŠDC.Lƒ0’Address�of�I/O�control�block#ŠDC.Lƒ0’Length�of�I/O�control�block   *OPENBLKƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�codeŠDC.Wƒ1’#�of�channels�to�open-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)4OPENLENƒEQU„*-OPENBLKŠLength�of�OPEN�parameter�block   *CONVBLKƒDC.Wƒ0’Returned�status�from�driver"ŠDC.WƒCONVERTŒConvert�command�code ŠDC.Wƒ1’#�of�channels�to�convert0ŠDC.Wƒ0’Channel�to�convert�(Dynamically�changed).ŠDC.Wƒ0’#�of�conversions�(Dynamically�changed)%ŠDC.Lƒ0’Buffer�address�of�conversionsŠDC.Wƒ01‘Wake�up�when�done7CONVLENƒEQU„*-CONVBLKŠLength�of�CONVERT�parameter�block   )CLSBLK„DC.Wƒ0’Returned�status�from�driverŠDC.WƒCLOSEŽClose�command�codeCLOSLENƒEQU„*-CLSBLK ŠNEXTWB ŠPAGE N*******************************************************************************Ì**œM�E�S�S�A�G�E�S¡**Ì*N****************************************************************************** ŠSECTION�MESSAGES 9HEAD†DC.BƒCR,LF,LF,'MVME605�Driver�Test�Program',CR,LF,LF HEADE…EQU„*-1ŠNEXTWB1MESS1…DC.Bƒ'…Number�of�the�channel�to�convert‚>�'MESS1E„EQU„*-1ŠNEXTWB*MESS3…DC.Bƒ'ŒDelay�between, �conversions‚>�'MESS3E„EQU„*-1ŠNEXTWB1MESS4…DC.Bƒ'„(C)onstant�level‚(S)awtooth�wave‚>�'MESS4E„EQU„*-1ŠNEXTWB4MESS5…DC.Bƒ'‚Value�to�be�converted�($000�-�$FFF)‚>�'MESS5E„EQU„*-1ŠNEXTWB2MESS6…DC.Bƒ'„Number�of�times�to�do�conversions‚>�'MESS6E„EQU„*-1ŠNEXTWB/MESS7…DC.Bƒ'‡Increment�for�conversion�value‚>�'MESS7E„EQU„*-1ŠNEXTWB0MESS10„DC.BƒCR,LF,'<<<�Starting�conversions�>>>'MESS10EƒEQU„*-1ŠNEXTWB2MESS11„DC.BƒCR,LF,'<<<ƒConversions�doneƒ>>>',CR,LFMESS11EƒEQU„*-1ŠNEXTWB,BADOPN„DC.BƒCR,LF,'***�OPEN�ABORTED�***�--�'BADOPNEƒEQU„*-1ŠNEXTWB2BADCNV„DC.BƒCR,LF,'***�CONVERSION�ABORTED�***�--�'BADCNVEƒEQU„*-1ŠNEXTWB-BADCLS„DC.BƒCR,LF,'***�CLOSE�ABORTED�***�--�'BADCLSEƒEQU„*-1ŠNEXTWB+STATUSMƒDC.Bƒ'Error�code�returned�in�D0�=�'STATUSME‚EQU„*-1ŠNEXTWBCRLF†DC.BƒCR,LF CRLFE…EQU„*-1 ŠNEXTWB ŠPAGE N*******************************************************************************Ì**–P�R�O�G�R�A�MƒS�E�C�T�I�O�N™**Ì*N****************************************************************************** ŠSECTION�CODE PROGSTRTŠLEA„STACK(PC),A7.ŠLEA„PBA(PC),A4‰Get�Program�Base�Address�(PBA)?ŠMOVE.L�BUFOFST(PC),D0…D0�=�offset�to�find�the�conversion�tableŠNEG.L‚D0–from�PBA7ŠLEA„(A4,D0.L),A0‡Add�the�negative�offset�to�PBA�to�getEŠMOVE.L�A0,BUFFADDR-PBA(A4)�Save�the�address�of�the�conversion�buffer@ŠMOVE.L�A0,CONVBLK+$A-PBA(A4)�the�physical�address�of�the�buffer &ŠOUTPUT�HEAD,HEADE‰Display�the�heading N*-----------------------------------------------------------------------------***‰Get�the�number�of�the�channel�to�convert*N*-----------------------------------------------------------------------------GETCHAN.ŠOUTPUT�MESS1,MESS1E‡Channel�number�to�convertŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary(ŠIF.L�D0��#0�OR.L�D0��#63�THEN.S ŒBRA�GETCHANŠENDI?ŠMOVE.W�D0,OPENBLK+6-PBA(A4)�Save�the�channel�number�in�OPENBLK?ŠMOVE.W�D0,CONVBLK+6-PBA(A4)�Save�the�channel�number�in�CONVBLK N*-----------------------------------------------------------------------------*.*‰Get�(C)onstant�level‚or�(S)awtooth�wave�form*N*-----------------------------------------------------------------------------GETCLST<ŠOUTPUT�MESS4,MESS4E‡(C)onstant�level�or�(S)awtooth�waveform+ŠINPUT‚INPUTBUF,INPUTBUF+8�Get�their�choiceŠMOVE.B�INPUTBUF(PC),D0**£C�=�Constant�level*£O�=�create�your�Own�waveform*£S�=�Sawtooth�waveform* **‰O�=�Own�waveform*CŠIF.B�D0��#'O'�THEN.S‚See�if�they�want�to�do�there�own�waveformŒMOVE.L�BUFFADDR(PC),A2 ŒMOVE.L�A2,A1%OWNVAL†BSR„GETDELAY‰Get�a�delay�value<ŒIF.L�D3��#$FFFF�THEN.S�D3�=�$FFFF�means�exit�"O"�option-ŽMOVE.W�D3,(A1)+‰Store�the�delay�in�the�table/ŽBSR„GETVAL‹Go�get�the�value�for�the�conversion ŽMOVE.W�D3,(A1)+‰Save�that�value ŽBRA„OWNVALŒENDI6ŒSUB.L‚A2,A1ŠFind�the�difference�between�the�beg�&�end ŒMOVE.L�A1,D01ŒDIVU.W‚#4,D0‰Divide�by�4�because�4�bytes/commandŒMOVE.W�D0,CONVBLK+8-PBA(A4)0ŒBRA„GETNUMTˆGo�get�the�number�of�times�to�do�itŠENDI **‰C�=�Constant�level�waveform*ŠIF.B�D0��#'C'�THEN.S7ŒBSR„GETDELAY‹Go�get�the�delay�value�for�each�conversio0ŒMOVE.W�D3,DELAYVAL-PBA(A4)�Save�the�delay�value)ŒBSR„GETVAL‹Returns�D3�=�Value�to�convertŒMOVE.W�#1,CONVBLK+8-PBA(A4)?ŒMOVE.L�BUFFADDR(PC),A0‚Get�the�address�of�the�conversion�tableCŒMOVE.W�DELAYVAL(PC),D1‚Get�the�delay�value�to�put�into�buffer�tabl!ŒMOVE.W�D1,(A0)+‰D1�=�Delay�value&ŒMOVE.W�D3,(A0)+‰D3�=�Value�to�convert0ŒBRA„GETNUMTˆGo�get�the�number�of�times�to�do�itŠENDI **‰S�=�Sawtooth�waveform*ŠIF.B�D0��#'S'�THEN.L7ŒBSR„GETDELAY‹Go�get�the�delay�value�for�each�conversio0ŒMOVE.W�D3,DELAYVAL-PBA(A4)�Save�the�delay�valueGETINCŒREPEAT3ŽOUTPUT�MESS7,MESS7EƒIncrement�for�conversion�valueŽINPUT‚INPUTBUF,INPUTBUF+8ŽLEA„INPUTBUF(PC),A0 ŽBSR„ASCVALŒUNTIL.L�D1��#0+ŒIF.L�D3��#1�OR.L�D3��#$0FFF�THEN.S ŽBRA„GETINCŒENDI8ŒMOVE.W�D3,INC-PBA(A4)- ƒSave�the�number�of�times�to�do�itCŒMOVE.W�DELAYVAL(PC),D0‚Get�the�delay�value�to�put�into�buffer�tabl-ŒCLR.L‚D1�Start�with�a�maximum�negative�value;ŒMOVE.L�BUFFADDR(PC),A0‚Get�the�address�of�the�buffer�table ŒMOVE.L�A0,A1ŒMOVE.W�INC(PC),D2 ŒREPEAT/ŽMOVE.W�D0,(A1)+‡Move�the�delay�into�the�buffer<ŽMOVE.W�D1,(A1)+‡Move�the�data�to�be�converted�into�the�buff ŽADD.W‚D2,D1ŒUNTIL.W�D1��#$0FFF ŒIF.W�D1��#$0FFF�THEN.S ŽSUB.W‚D2,D1ŒENDI ŒREPEAT/ŽMOVE.W�D0,(A1)+‡Move�the�delay�into�the�buffer<ŽMOVE.W�D1,(A1)+‡Move�the�data�to�be�converted�into�the�buff ŽSUB.W‚D2,D1ŒUNTIL.W�D1��#0 6ŒSUB.L‚A0,A1ŒFind�the�difference�between�the�beg�&�end ŒMOVE.L�A1,D01ŒDIVU.W‚#4,D0‹Divide�by�4�because�4�bytes/commandŒMOVE.W�D0,CONVBLK+8-PBA(A4)2ŒBRA.S‚GETNUMTˆGo�get�the�number�of�times�to�do�itŠENDI ŠBRA„GETCLSTN*-----------------------------------------------------------------------------*.*‰Get�the�number�of�time�to�do�the�conversions*N*-----------------------------------------------------------------------------GETNUMTŠREPEAT6ŒOUTPUT�MESS6,MESS6E‡Number�of�times�to�do�conversionsŒINPUT‚INPUTBUF,INPUTBUF+8ŒLEA„INPUTBUF(PC),A0 ŒBSR„ASCVALŠUNTIL�D1��#0+ŠIF.L�D3��#1�OR.L�D3��#$FFFF�THEN.S ŒBRA„GETNUMTŠENDI8ŠMOVE.L�D3,NUMT-PBA(A4)„Save�the�number�of�time�to�do�it N*-----------------------------------------------------------------------------**‰Start�the�conversions�here*N*-----------------------------------------------------------------------------**ƒOPEN�THE�D/A�CHANNEL*ŠLEA„CMRBLK(PC),A0ŠLEA„OPENBLK(PC),A1ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OPENLEN,$18(A0)7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�to.ŠTRAPƒ#1‘invoke�CMR.‚The�value�in�D0�tells�the)*£operating�system�that�we�want�to�invoke**£CMR,�and�the�value�in�A0�tells�CMR�where&*£to�find�its�parameter�block.‚The�CMR+*£parameter�block�contains�a�pointer�to�the(*£I/O�command�block,�and�the�I/O�command"*£block�spwcifies�an�OPEN�command. 9ŠBNE.S‚BADOPENŒCMR�returns�a�status�code�in�D0.B,�and�CMR+*£returns�the�CC.Z�bit�to�reflect�the�value'*£of�the�status�code�in�D0.B.‚A�nonzero+*£status�code�indicates�that�the�driver�has*£rejected�the�OPEN�command.**ƒDO�CONVERSIONS*3ŠOUTPUT�MESS10,MESS10E…<<<ƒStarting�conversionsƒ>>>:ŠMOVE.L�NUMT(PC),D7ˆD7�=�Number�of�times�to�do�conversionsŠFOR.L�D6�=�#1�TO�D7�DO.SŒLEA„CMRBLK(PC),A0ŒLEA„CONVBLK(PC),A1ŒMOVE.L�A1,$14(A0)ŒMOVE.W�#CONVLEN,$18(A0)5ŒMOVE.L�#CMR,D0ŠTell�the�driver�to�do�the�conversionsŒTRAPƒ#1*'*ƒDo�a�wait�until�the�drive�wakes�us�up*ŒMOVE.L�#19,D0ŒTRAPƒ#1 ŒMOVE.W�CONVBLK(PC),D0ŒBNE.S‚BADCONVŠENDF**‚CLOSE�THE�CHANNEL*ŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)1ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�D/A�channelŠTRAPƒ#1ŠBNE.S‚BADCLOSE/ŠOUTPUT�MESS11,MESS11E…<<<ƒConversions�doneƒ>>> ŠBRA„EXIT BADOPENŠMOVE.L�D0,STATUS-PBA(A4)+ŠOUTPUT�BADOPN,BADOPNE…***�OPEN�ABORTED�***ŠBRA.S‚SHOW_D0 BADCONVŠMOVE.L�D0,STATUS-PBA(A4)1ŠOUTPUT�BADCNV,BADCNVE…***�CONVERSION�ABORTED�***ŠBRA.S‚SHOW_D0 BADCLOSEŠMOVE.L�D0,STATUS-PBA(A4),ŠOUTPUT�BADCLS,BADCLSE…***�CLOSE�ABORTED�*** :SHOW_D0ƒMOVE.L�STATUS(PC),D0†Get�the�status�value�returnedŠBSR„BHLCVT�Convert�it�to�ASCII9ŠMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŠMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŠOUTPUT�STATUSM,STATUSMEŠOUTPUT�NUMBER,NUMBER+7ŠOUTPUT�CRLF,CRLFE ŠBRA.S‚EXIT  CHECKQ3ŠCMP.B‚#'Q',INPUTBUF-PBA(A4)�Do�they�want�to�Quit�? ŠBEQ.S‚EXIT3ŠCMP.B‚#'.',INPUTBUF-PBA(A4)�Do�they�want�to�Quit�? ŠBEQ.S‚EXITŠRTS  EXIT"ŠMOVE.L�#15,D0�Terminate�this�taskŠTRAPƒ#1 GETDELAY.ŠOUTPUT�MESS3,MESS3E‡Delay�between�conversionsŠINPUT‚INPUTBUF,INPUTBUF+8 ŠBSR„CHECKQŠLEA„INPUTBUF(PC),A0 ŠBSR„ASCVAL ŠTST.L‚D1 ŠBEQ„GETDELAY+ŠIF.L�D3��#0�OR.L�D3��#$FFFF�THEN.S ŒBRA„GETDELAYŠENDI ŠRTS   GETVAL8ŠOUTPUT�MESS5,- MESS5E‡Value�to�be�converted�($000�-�$FFF)ŠINPUT‚INPUTBUF,INPUTBUF+8 ŠBSR„CHECKQŠLEA„INPUTBUF(PC),A0!ŠBSR„ASCVAL‹D3�=�Value�to�convertŠRTS   ŠEND„PROGSTRT=/*=/*†M605DRV.TEST605.AF=/*,=/*†TEST605�test�program�assembly�chain�file=/*6=/*†The�command�line�will�accept�arguments�as�follows:=/*;=/*‹Argument�01…\1�=�Output�file�assembly�listing�or�device=/*H=/*†The�following�shows�the�assembly�chain�sequence.‚In�this�example�theH=/*†NULL�device�was�chosen�as�Argument�01,�however,�the�user�could�if�he5=/*†so�desired�have�requested�an�output�listing�file.=/*#=/*�=CHAIN�M605DRV.TEST605.AF�#NULL=/*-=/*†Default�argument�01�is�M605DRV.TEST605.LS=/*=/IFC \1ƒ=ARG�M605DRV.TEST605.LS=/ENDIF=/*4=ASM M605DRV.TEST605.SA,M605DRV.TEST605.RO,\1;RZ=100=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDééééé©'M610DRV INPTST SA¾¾ÒbbINTSTASMSAÏÏ'MbbTEST610 SAøøF[bbINTSTASMAFAAbbTEST610 AFJJbb"program Input_Test (input,output); const ƒWAIT„=�0; ƒOPEN„=�1; ƒCLOSEƒ=�2; ƒSTAT„=�5; ƒENABLE‚=�6; ƒDISABLE�=�7; typeƒbyte�=�-128..+127;ƒword�=�-32768..+32767; ƒopen_cdb�=�packed�record�chan_no�:�word;�config‚:�wordŽend; ƒcommand�=�packed�record�status�:�word; �codeƒ:�word;�case�boolean�of’true‚:�(chan_mask�:�word);’false�:�(chan_cnt‚:�word; ›cdb‡:�array�[0..7]�of�open_cdb)�end; ƒinit_IO�=�packed�record�done_flag:�word; �code…:�byte;�s. ub_code�:�byte;�unused_1�:�word;(�mnemonic�:�packed�array�[1..4]�of�char;)�unused_2�:�packed�array�[1..12]�of�byte;�cmd_adr‚:�^command;�cmd_len‚:�word�end; )ƒtask_name�=�packed�array�[1..4]�of�char; varƒcmd_blk…:�command;ƒcmd_char„:�string[8];ƒtask_ID…:�task_name;ƒtask_cnt,�i�:�integer;ƒinit_blk„:�init_IO;ƒin_char…:�char; *procedure p$force (var fil:text); forward; 4procedure clone_tasks (task_cnt : integer); forward; .function send_command (var init_blk : init_IO;*—var�task_ID�:�task_name)�:�word;�forward;{$E}function hex_in : word; varƒnum_str�:�string[6];ƒnum�,i‚:�word;ƒerrorƒ:�boolean; beginƒrepeat†begin ‰error�:=�FALSE;‰readln�(num_str); ‰num�:=�0;‰i�:=�1; #‰while�(�i�<=�length�(num_str))�and7�(�((�num_str[i]�>=�'0'�)�and�(�num_str[i]�<=�'9'�))�or7‘((�num_str[i]�>=�'A'�)�and�(�num_str[i]�<=�'F'�))ƒ)�doŒbegin�if�num_str[i]�>=�'A'9’then�num�:=�num�*�16�+�ord�(num_str[i])�-�ord�('A')�+�105’else�num�:=�num�*�16�+�ord�(num_str[i])�-�ord�('0'); �i�:=�i�+�1Œend;‰if�i�<=�length�(num_str)�thenŒbegin�error�:=�TRUE;+�write�('Invalid�hex�number�-�reenter�>�');�p$force�(output)Œend†endƒuntil�error�=�FALSE;ƒhex_in�:=�num end;{$E} procedure hex_out ( num : word); varƒnum_str�:�string[4];ƒi,j…:�integer; begin ƒnum_str�:=�'„';ƒfor�i�:=4�downto�1�do†begin‰j�:=�num�mod�16;‰num�:=�num�div�16; ‰if�j�>=�10¶k¿h,Œthen�num_str[i]�:=�chr�(j�-�10�+�ord�('A'))'Œelse�num_str[i]�:=�chr�(j�+�ord�('0'))†end;ƒwriteln�(num_str)end;{$E}procedure enter_command; varƒstatus„:�word; ƒi‰:�integer; beginƒwith�init_blk.cmd_adr^�do„begin†case�cmd_char[1]�of‰'W'�:�code�:=�WAIT;‰'O'�:�code�:=�OPEN;‰'C'�:�code�:=�CLOSE;‰'E'�:�code�:=�ENABLE;‰'D'�:�code�:=�DISABLE;‰'S'�:�code�:=�STAT†end;†if�code�<>�WAIT�thenˆbegin%Šwrite�('Enter�channel�mnemonic�>�');Šp$force�(output);Šreadln�(init_blk.mnemonic);Šif�code�<>�OPEN �then”{All�commands�except�OPEN}�begin*“write�('Enter�channels�mask�in�hex.�>�');“p$force�(output);“chan_mask�:=�hex_in�end�else”{OPEN�command}�begin /“write�('Enter�number�of�channels�to�open�>�');“p$force�(output);“readln�(chan_cnt); “for�i�:=�0�to�chan_cnt�-�1�do–begin#™write�('Enter�channel�number�>�');™p$force�(output);™readln�(cdb[i].chan_no);2™write�('Enter�channel�configuration�in�hex.�>�');™p$force�(output);™cdb[i].config�:=�hex_in–end Œend‚{else} ˆend;{if},†status�:=�send_command�(init_blk,�task_ID);†if�code�<>�WAITˆthen‰begin‹if�code�=�STATŽthen�begin’write�('Channel�Status�=�');’p$force�(output);’hex_out(chan_mask)�end;‹write�('Command�Status�is�');‹p$force�(output);‹hex_out�(status)‰end „end‚{with}end;{$E} begin‚{main} ƒwith�init_blk�do†begin ‰code�:=�7;‰sub_code�:=�0;‰new�(cmd_adr)†end; +ƒwrite�('Enter�number�of�tasks�(1-26)�>�');ƒp$force�(output);ƒreadln�(�task_cnt); ƒtask_ID�:=�'INPx'; ƒclone_tasks�(task_cnt); ƒwhile�true�do†for�i�:=�1�to�task_cnt�do‡repeat‰begin(Œtask_id[4]�:=�chr�(ord�('A')�+�i�-�1�);$Œwriteln�('**�Task�',task_ID,'�**');EŠwrite�('Command�(O-pen,C-lose,E-nable,D-isable,S-tatus,W-ait�)�>�');Œp$force�(output);Œreadln�(cmd_char); Œif�(length�(cmd_char)�<>�0)�and+�(cmd_char[1]�in�['W','O','C','E','D','S'])�then‚enter_command‰end‡until�length�(cmd_char)�=�0end. *‰INCLUDE�9995.&.TR1.EQŠINCLUDE�9995.&.TR1.EQ*‰INCLUDE�9995.&.TR1RTCD.EQŠINCLUDE�9995.&.TR1RTCD.EQ*‰INCLUDE�9995.&.EXE.EQŠINCLUDE�9995.&.EXE.EQ*‰INCLUDE�9995.&.LV5.EQŠINCLUDE�9995.&.LV5.EQ*‰INCLUDE�9995.&.M610CMD.EQŠINCLUDE�9995.&.. M610CMD.EQŠPAGE*H* VME 610/620 Driver Assembly language test routines. These routines are;* called from a Pascal test task that performs terminal I/OŠSPC„2 ŠSECTION�9ŠXDEFƒCLONE_TA I*‚Create�the�specified�number�of�test�tasks�that�share�the�code�and�stackL* segments of the PASCAL program that is calling this routine. Then allocate.* an ASQ for each task and start them running. ,CLONE_TA‚MOVE.L�(A7)+,A4‹Save�return�addressŠSPC„2$ŠMOVE.L�(A7)+,D7‹Save�task�count�-�1 ŠSUB.L‚#1,D7ŠSPC„2:ŠLEA.L‚-100(A7),A7ˆAllocate�parameter�block�space�on�stackŠSPC„27ŠMOVE.L�A7,A0ŽStore�CRTCB�parameter�block�address�in�A0ŠSPC„2'*‚Initialize�Create�TCB�parameter�block @ŠMOVE.L�#'INPA',CRTTSK(A0)ƒName�tasks�alphabetically�within�sameŠCLR.L‚CRTSES(A0)‰sessionŠSPC„23ŠMOVE.W�#CTOPMP,CRTOPT(A0)�Propogate�monitor�optionŠSPC„21ŠMOVE.B�#$7F,CRTIPR(A0)„Run�task�at�max.�priorityŠMOVE.B�#$7F,CRTLPR(A0)ŠSPC„2-ŠMOVE.W�#$2000,CRTATT(A0)‚Task�dump�attributeŠSPC„2.ŠLEA.L‚TASKENT(PC),A1…Task�entry�point�addressŠMOVE.L�A1,CRTENT(A0)ŠSPC„2ŠMOVE.W�#0,CRTUID(A0)†User�0ŠSPC„2* Create TCB's %ŠMOVE.W�D7,D1ŽInitialize�loop�counterŠSPC„2)TCBLOOPƒMOVE.L�#CRTCB,D0ŠIssue�CRTCB�callŠTRAPƒ#1 ŠBEQ.S‚TCBOK ŠBSR„ERRORŠSPC„2ETCBOK…ADD.B‚#1,CRTTSK+3(A0)„Update�task�name�and�loop�until�all�tasks#ŠDBRAƒD1,TCBLOOP‰have�been�created.ŠSPC„25* Initialize Share Segment directive parameter block. #ŠMOVE.L�#'INPA',SEGTCB(A0)ƒTaskname<ŠMOVE.W�#SGOPPA,SEGOPT(A0)ƒLogical�=�physical�address�optionŠSPC„23ŠMOVE.W�#SGATSS,SEGATT(A0)ƒSession�sharable�segmentŠSPC„2,* Share code and data segments to each task. %ŠMOVE.L�D7,D1ŽInitialize�loop�counter ŠMOVE.L�A7,A1ŠSPC„2ÇHÐIØ9àBèB=SEGLOOPƒMOVE.L�#SHRSEG,D0‰Share�the�code�segment�to�each�taskŠMOVE.L�#'CODE',SEGNAM(A1) ŠMOVE.L�A1,A0ŠTRAPƒ#1 ŠBEQ.S‚SEG010 ŠBSR„ERRORŠSPC„2DSEG010„MOVE.L�#SHRSEG,D0‰Share�the�PASCAL�stack�segment�to�each�taskŠMOVE.L�#'SEG2',SEGNAM(A1) ŠMOVE.L�A1,A0ŠTRAPƒ#1 ŠBEQ.S‚SEG020 ŠBSR„ERRORŠSPC„2FSEG020„ADD.B‚#1,SEGTCB+3(A1)†Loop�until�both�segments�have�been�sharedŠDBRAƒD1,SEGLOOP‰to�all�tasks.ŠSPC„2)* Initialize Allocate ASQ parameter block ŠMOVE.L�A1,A0,ŠMOVE.L�#'INPA',ASQTSK(A0)„Initial�task�nameŠSPC„2AŠMOVE.B�#AQSTQE+AQSTRE+8,ASQSTA(A0)�ASR/ASQ�enabled,�no�registersŠSPC„23ŠMOVE.B�#18,ASQMML(A0)…Max.�event�length�=�18�bytesŠSPC„2.ŠMOVE.L�#2048,ASQQLN(A0)ƒASQ�length�=�2K�bytesŠSPC„2-ŠLEA.L‚INTASR(PC),A1†Default�to�interrupt�ASRŠMOVE.L�A1,ASQASR(A0)ŠSPC„2* Allocate ASQs for each task %ŠMOVE.L�D7,D1ŽInitialize�loop�counterŠSPC„25ASQLOOPƒMOVE.L�#GTASQ,D0ƒIssue�Allocate�ASQ�directiveŠTRAPƒ#1 ŠBEQ.S‚ASQ010 ŠBSR„ERRORŠSPC„2EASQ010„ADD.B‚#1,ASQTSK+3(A0)†Loop�until�an�ASQ�has�been�allocated�forŠDBRAƒD1,ASQLOOP‰each�task.ŠSPC„2'*Initialize Start Task parameter block. :ŠMOVE.L�#'INPA',STRTSK(A0)ƒStart�tasks�without�passing�any+ŠMOVE.W�#0,STROPT(A0)†initialize�registers.ŠSPC„2* Start all tasks *ŠMOVE.L�D7,D1�Initialize�the�loop�counter.ŠSPC„2#STARTLPƒMOVE.L�#START,D0ŠStart�taskŠTRAPƒ#1ŠBEQ.S‚STRT010 ŠBSR„ERRORŠSPC„2DSTRT010ƒADD.B‚#1,STRTSK+3(A0)„Loop�until�all�tasks�have�been�startedŠDBRAƒD1,STARTLPŠSPC„2* Task startup completeŠSPC„2-ŠLEA.L‚100(A7),A7‰Restore�entry�stack�pointerŠSPC„2+ŠJMP„(A4)�Return�to�calling�PASCAL�routine.ŠSPC„2ŠPAGEŠXDEFƒSEND_COMŠSPC„2K* This routine passes the address of an Initiate I/O parameter block to oneM* of the test tasks in an event that is queued to the task. After sending theM* command event, the routine waits for the test task to set a flag indicatingM* that the command has been issued to the driver and the return status can be/ H* read from the command parameter block. The routine then returns to theN* calling PASCAL routine with the command status as the function return value. :SEND_COM‚MOVEM.L�(A7)+,A1/A2/A4„Pull�parameters�from�stack*¤A1�=�Return�address*¤A2�=�Task�ID�address*¤A4�=�Initiate�I/O�PB�addressŠSPC„2>ŠLEA.L‚-100(A7),A7ˆAllocate�parameter�block�space�on�the�stackŠSPC„2-* Initialize the Queue Event parameter block. 6ŠMOVE.L�A7,A0ŽSave�parameter�block�base�address�in�A0.ŠSPC„2?ŠMOVE.L�(A2),QEVTSK(A0)†Copy�the�task�ID�passed�from�the�PASCAL'*£routine�to�the�destination�task�name.ŠSPC„2@ŠMOVE.W�#QVOPAS,QEVOPT(A0)ƒSet�the�command�processing�ASR�of�the?ŠLEA.L‚CMDASR(PC),A2†tast�task�to�be�the�alternate�ASRT�serviceŠMOVE.L�A2,QEVIAD(A0)†address.ŠSPC„2?ŠLEA.L‚QEVIAD+4(A0),A2†Load�the�event�buffer�address�(following=ŠMOVE.L�A2,QEVPKT(A0)†the�parameter�block)�into�the�parameter*£block.ŠSPC„22ŠCLR.W‚(A4)+�Clear�the�command�conpletion�flag�and(*£update�the�pointer�to�the�Initiate�I/O*£parameter�block�base�address.ŠSPC„2;ŠMOVE.W�#$0603,(A2)+‰Event�length�=�6�bytes,�Event�code�=�3ŠMOVE.L�A4,(A2)+ŠSPC„2@ŠMOVE.W�#CMDLEN,XIOPLN(A4)ƒAssume�that�the�length�of�the�command'*£block�is�standard�(i.e.�not�an�OPEN�) ŠSPC„29ŠMOVE.L�XIOCPK(A4),A2‡Get�the�command�block�base�address.ŠSPC„2BŠCMP.W‚#INOPEN,CMDCOD(A2)‚If�the�command�is�not�OPEN,�the�standard/ŠBNE.S‚QUECMD�length�already�loaded�is�correct.ŠSPC„2:ŠMOVE.W�CMDNCO(A2),D1ˆCalculate�the�correct�length�for�the:ŠMULUƒ#OPNCDB,D1‰OPEN�command�parameter�block�and�store�in)ŠADD.L‚#CMDCHL,D1‰the�Initiate�I/O�block.ŠMOVE.W�D1,XIOPLN(A4)ŠSPC„2AQUECMD„MOVE.L�#QEVNT,D0‹Queue�the�command�event�to�the�test�task.ŠTRAPƒ#1ŠBEQ.S‚ACKLOOP ŠBSR„ERRORŠSPC„2;ACKLOOPƒTST.B‚-2(A4)�Loop�until�the�command�completion�flag+ŠBEQ„ACKLOOPŒhas�been�set�by�the�test�task.ŠSPC„22ŠLEA.L‚100(A7),A7‹Restore�the�entry�stack�pointer.ŠSPC„2=ŠMOVE.W�CMDSTA(A2),(A7)†Save�the�command�completion�status�in(*£the�function�return�word�on�the�stack.ŠSPC„2/ŠJMP„(A1)‘Return�to�the�calling�PASCAL�routine.ŠSPC„2ŠPAGEJ*‚This�is�the�test�task�that�issues�commands�to�the�driver�as�specified�byL* the controlling PASCAL task. The test task handles interrupt notificationsN* sent by the driver. The user is notified of the interrupt via LEDs connected:* to an MVME 625 Digital Output module on the I/O channel. 5VME625„EQU„$FE6001ŒVME�625�module�I/O�channel�address (* Allocate Stack Segment parameter block SEGBLK„DC.Lƒ0’Task�name…(self)ŠDC.Lƒ0’Session�number(self)6ŠDC.WƒSGOPPA�Logical�Address�=�Physical�address�option)ŠDC.WƒSGATRW�Read/Write�Segmant�attributeŠDC.Lƒ'STAK'�Segment�name)ŠDC.Lƒ0’Segment�address�(Returned�by�RMS)ŠDC.Lƒ$100�Segment�lengthŠSPC„2* Test task entry point* Allocate a stack segment >TASKENTƒMOVE.L�#GTSEG,D0ŠAllocate�a�stack�segment�of�256�bytesŠLEA.L‚SEGBLK(PC),A0ŠTRAPƒ#1 ŠBEQ.S‚TSK010 ŠBSR„ERRORŠSPC„2BTSK010„LEA.L‚$F8(A0),A7‰Initialize�the�stack�pointer�to�the�end�of*£the�stack�segment.ŠSPC„2CTSKWTEVT‚MOVE.L�#WTEVNT,D0‹Wait�for�a�command�event�or�an�interrupt*ŠTRAPƒ#1‘event�to�be�processed�in�the�ASR.ŠBEQ.S‚TSKWTEVT ŠBSR„ERRORŠSPC„2I*‚Control�reaches�here�when�the�user�has�issued�a�command�for�the�task�to* enter the wait state. ;TSKWAITƒMOVE.L�#WAIT,D0ŒPlace�the�task�into�a�WAIT�state�so0ŠTRAPƒ#1‘interrupts�may�be�processed�on�channels*£using�WAKEUP.ŠSPC„23ŠBSETƒ#7,VME625ŒPulse�LED�7�on�the�VME�625�board�to8ŠBCLRƒ#7,VME625Šindicate�that�a�wakeup�has�been�receivedŠSPC„26ŠBRA.S‚TSKWAITŽThis�loop�repeats�until�a�command�event*£is�queued�to�the�test�task.ŠPAGE* Command event ASR 3CMDASR„SUB.L‚#16,A7�Allocate�stack�to�receive�event ŠMOVE.L�A7,A0ŠSPC„21ŠMOVE.L�#RDEVNT,D0ŠRead�command�event�into�bufferŠTRAPƒ#1 ŠBEQ.S‚CMD020 ŠBSR.S‚ERRORŠSPC„28CMD020„MOVE.L�EVQTXT(A0),A0‡Load�event�text�base�address ŠADD.L‚#16,A7=ŠMOVE.L�XIOCPK(A0),A1ˆLoad�Input�Command�Parameter�Block�base *£address/ ŠSPC„27ŠTST.W‚CMDCOD(A1)ŠIf�the�command�code�is�zero,�the�test3ŠBEQ.S‚CMDWAITŒtask�is�to�be�put�into�a�WAIT�state.ŠSPC„2* Issue command to the driver. 5ŠMOVE.L�#CMR,D0ŒIssue�the�Initiate�I/O�command�to�CMRŠTRAPƒ#1 ŠBEQ.S‚CMD030ŠSPC„2=ŠMOVE.W�D0,CMDSTA(A1)ˆIf�an�error�is�returne�by�CMR,�copy�the'*£error�code�into�the�IPB�status�field.ŠSPC„24* Signal supervisor task that command was completed. FCMD030„MOVE.W�#$FFFF,-2(A0)†Set�the�command�completion�flag�and�returnŠRTR—from�the�eventŠSPC„2* Put task in WAIT state CCMDWAITƒLEA.L‚TSKWAIT(PC),A1‡Change�the�event�return�address�to�the'ŠMOVE.L�A1,2(A7)‹WAIT�loop�entry�point.ŠSPC„25ŠMOVE.W�#$FFFF,-2(A0)ˆSet�the�command�completion�flagŠSPC„2;ŠMOVE.L�#SETASQ,D0‹Enable�the�ASR�and�ASQ�so�command�events4ŠMOVE.L�#5,A0Žmay�be�processed�when�a�WAKEUP�occurs.ŠTRAPƒ#1 ŠBEQ.S‚CMD010 ŠBSR.S‚ERRORŠSPC„20CMD010„RTR˜Return�to�the�WAIT�state�loop�until�a+*£command�event�is�waiting�and�a�WAKEUP�has(*£been�issued�to�the�task�by�the�driver.ŠPAGE* Interrupt Event ASR 3INTASR„SUB.L‚#16,A7�Allocate�stack�to�receive�event ŠMOVE.L�A7,A0ŠSPC„2)ŠMOVE.L�#RDEVNT,D0‰Read�event�into�bufferŠTRAPƒ#1 ŠBEQ.S‚INT010 ŠBSR.S‚ERRORŠSPC„2;INT010„MOVE.B�3(A0),D0‹Load�the�interrupting�channal�numberŠSPC„28ŠCMP.L‚#'IN02',4(A0)ˆIf�the�first�module�is�interrupting1ŠBNE.S‚INT020�leave�the�channel�number�unchanged.ŠSPC„21ŠADD.B‚#4,D0�If�the�second�module�is�interrupting!*£add�four�to�the�channel�number.ŠSPC„28INT020„BSETƒD0,VME625ŒPulse�the�LED�corresponding�to�the(ŠBCLRƒD0,VME625Šmodified�channel�number.ŠSPC„2ŠADD.L‚#16,A7�Restore�stackŠSPC„2ŠRTR™Return�from�eventŠSPC„2;ERROR…MOVE.L�(A7)+,A0�Abort�the�task�if�an�unexpected�error9ŠMOVE.L�#ABORT,D0Šoccurs.�The�address�of�wherer�the�error3ŠTRAPƒ#1‘occurred�is�stored�in�A0�for�the�SCT�abort *£message.ŠSPC„2ŠENDN*******************************************************************************Ì**Ì*#*—MVME610�or�MVME620‚Test�Program•**Ì**Ì*N********************************************************************************6* This program was written to test the MVME610 driver.**    *‰Modification�HistoryN*-----------------------------------------------------------------------------*�11/01/84‡DUH�Initial�writing   *�1.‚Introduction*B*‰This�program�was�written�to�test�the�MVME610�driver.‚It�can�alsoI*‚be�used�to�test�the�VME620�board.‚This�program�will�ask�for�the�channelI*‚number�to�use.‚It�will�then�ask�if�the�user�wants�to�read�the�status�ofL*‚that�channel�or�enable�and�wait�for�a�negative�going�edge�on�that�channel.K*‚To�use�this�test�program,�connect�a�square�wave�generator�to�a�channel�onD*‚the�VME620�DC�input�module�or�a�switch�connected�to�120VAC�for�the*‚VME610�AC�input�module.*8*‰This�program�assumes�the�boards�are�jumpered�as�shown:**‚VME610�or�VME620:%*„J3‚1,2‚3,4‚5,6‡address�offset�$0005*„J2‚2,4‘interrupt�INT1*ŠPAGE ,*£ASCVAL,�BHLCVT,�and�CVT2�are�commonly�used**£functions�which�are�modules�in�a�library(*£file�called�UTILIB.RO.‚A�call�to�these'*£functions�are�included�in�this�source)*£program,�which�is�provided�with�an�XREF&*£declaration.‚This�also�requires�that'*£UTILIB.RO�be�available�to�the�linkage$*£editor�during�the�linking�process.%*£See�TEST620.LF�for�link�chain�file. -ŠXREFƒASCVAL�Converts�ASCII�to�a�binary�value$*£This�routine�will�convert�an�ASCII,*£character�string�representing�a�decimal�or,*£hexidecimal�value�to�the�equivalent�binary,*£value.‚If�a�dollar�sign�($)�is�encountered&*£hexidecimal�conversion�is�performed;,*£otherwise�decimal�conversion�is�performed.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary'*£value.‚Conversion�terminates�when�the)*£first�invalid�character�is�encountered.'*£ENTRY:‚A0�-�Starting�address�of�ASCII0 ð>ù:D BGF!F)S18*°character�string�to�convert#*£EXIT�:‚D1�-�Character�that�caused *°termination%*«D2�-�Class�code�of�terminating�char"*«D3�-�Binary�result�of�conversion*«A0�-�Address�of�the�character *°following�the�terminating�char 8ŠXREFƒBHLCVT�Converts�4-byte�binary�value�to�ASCII�digit)*£This�routine�will�convert�a�long�binary-*£word�value�to�a�hexadecimal�value�expressed)*£as�an�8�character�ASCII�string.‚Leading*£zeros�are�suppressed.,*£ENTRY:‚D0.L�-�Binary�value�to�be�converted(*£EXIT�:‚D2.L�-�Four�high�order�bytes�of*²converted�value *«D3.L�-�Four�low�order�bytes�of*²converted�value 6ŠXREFƒCVT2�Converts�two�ASCII�decimal�digits�to�binary-*£This�routine�will�convert�two�ASCII�decimal(*£digits�to�the�equivalent�binary�value.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary**£value.‚Conversion�terminates�when�a�non-*£decimal�digit�is�encountered)*£ENTRY:‚A0�-�Address�of�most�significant*°ASCII�decimal�digit)*£EXIT�:‚D0�-�Binary�result�of�conversion!*«A0�-�Address�of�the�terminating *°character ŠPAGEŠMOVE.L�A0,IOSOUT+16-PBA(A4)�Set�the�ending�address�of�messageŠLEA„IOSOUT(PC),A0ŠTRAPƒ#2ŠENDM ŠPAGE 2ŠOPT„PCS�We�use�a�PCS�option�so�the�assembler�will%*£force�PC�relative�addressing�within(*£SECTION.‚Forces�PC�relative�addressing-*£(whenever�such�an�addressing�mode�is�legal))*£in�an�instruction�which�occurs�within�a'*£relocatable�SECTION�and�references�an,*£operand�in�a�relocatable�SECTION�(need�not**£be�the�same�SECTION�as�the�instruction).,*£Failure�to�resolve�sucn�a�reference�into�a-*£16-bit�displacement�from�the�PC�will�result)*£in�an�error.‚This�option�may�be�used�to+*£force�position�independent�code;�however,(*£this�option�does�not�force�PC�relative,*£addressing�of�absolute�operands�or�unknown*£forward�references. ŠPAGE N*******************************************************************************Ì**™D�A�T�AƒS�E�C�T�I�O�Nœ**Ì*N****************************************************************************** ŠSECTION�DATA $PBA‡EQU„*’Program�Base�Address�(PBA)%*£This�label�is�used�to�designate�the+*£beginning�of�the�program.‚This�is�used�to'*£make�references�to�other�parts�of�the*£program,�relocatable. 9ŠDS.WƒSTACKLEN‹This�is�the�stack�area�for�the�VME620�test2STACK…EQU„*’program.‚Registers�and�other�important,*£information�will�be�stored�on�the�stack�as)*£the�program�is�executed.‚The�stack�area'*£is�dynamic�and�will�change�during�the *£execution�of�the�test�program. =INPUTBUF‚DS.WƒSTRNGLEN‹This�is�the�storage�area�for�the�input*£strings�that�are�entered. 9STATUS„DS.Lƒ1’This�will�be�the�storage�are�for�the�status,*£code�that�is�returned�from�CMR.‚This�value-*£will�be�displayed�to�show�the�user�what�the*£error�code�was. 6NUMBER„DS.Lƒ2’Save�area�for�the�ASCII�value�of�STATUS.ŠPAGE N*******************************************************************************Ì*!*–P�A�R�A�M�E�T�E�RƒB�L�O�C�K�S—**Ì*N****************************************************************************** ŠNEXTWB”Force�even�boundaryIOSOUTŠDC.Bƒ0’Request�code"ŠDC.BƒWRITEŽFunction�specificationŠDC.Wƒ8’OptionsŠDC.Bƒ0’StatusŠDC.BƒCRT�Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address   ŠNEXTWB”Force�even�boundaryIOSINŠDC.Bƒ0’Request�code!ŠDC.BƒREAD�Function�specificationŠDC.Wƒ0’OptionsŠDC.Bƒ0’Status"ŠDC.BƒKEYBOARD‹Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address  CMRBLK„DC.Bƒ7’Initiate�I/OŠDC.BƒUNUSED�UnusedŠDC.WƒUNUSED�UnusedŠDC.Lƒ'IN01'�Channel�nameŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�Unused$ŠDC.Lƒ0’Address�of�I/O�control�block#ŠDC.Lƒ0’Length�of�I/O�control�blockŠPAGE*7*‚OPEN�command�parameter�block�for�the�DC�INPUT�driver:+OPEN_DCI‚DC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�codeŠDC.Wƒ1’#�of�channels�to�open-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)-ŠDC.WƒDEFAULTŒChannel�configuration�(Dynamic)6OLEN_DCI‚EQU„*-OPEN_DCI‰Length�of�OPEN�parameter�block*E*‚READ�OUTPUT�STATUS�command�parameter�block�for�the�DC�INPUT�driver:+READ_DCI‚DC.Wƒ0’Returned�status�from�driver*ŠDC.WƒREAD_STATUSˆRead�status�command�code.ŠDC.Wƒ0’Bit�mask�for�channels�to�read�and�upon(*£return�holds�the�actual�channel�status1 =RLEN_DCI‚EQU„*-READ_DCI‰Length�of�READ�STATUS�parameter�block*D*‚ENABLE�INTERRUPTS�command�parameter�block�for�the�DC�INPUT�driver:+ENAB_DCI‚DC.Wƒ0’Returned�status�from�driver-ŠDC.WƒENAB_INT‹Enable�interrupts�command�code.ŠDC.Wƒ0’Bit�mask�for�channels�to�read�and�upon(*£return�holds�the�actual�channel�statusCELEN_DCI‚EQU„*-ENAB_DCI‰Length�of�ENABLE�INTERRUPTS�parameter�block*D*‚ENABLE�INTERRUPTS�command�parameter�block�for�the�DC�INPUT�driver:+DISB_DCI‚DC.Wƒ0’Returned�status�from�driver.ŠDC.WƒDISAB_INTŠEnable�interrupts�command�code.ŠDC.Wƒ0’Bit�mask�for�channels�to�read�and�upon(*£return�holds�the�actual�channel�status>DLEN_DCI‚EQU„*-DISB_DCI‰Length�of�DISABLE�INTERRUPTS�parameter*8*‚CLOSE�command�parameter�block�for�the�DC�INPUT�driver:)CLSBLK„DC.Wƒ0’Returned�status�from�driverŠDC.WƒCLOSEŽClose�command�codeCLOSLENƒEQU„*-CLSBLKŠNEXTWBŠPAGE N*******************************************************************************Ì**œM�E�S�S�A�G�E�S¡**Ì*N****************************************************************************** ŠSECTION�MESSAGES 9HEAD†DC.BƒCR,LF,LF,'MVME620�Driver�Test�Program',CR,LF,LF HEADE…EQU„*-1ŠNEXTWB1MESS1…DC.Bƒ'…Number�of�the�channel�to�convertˆ>�'MESS1E„EQU„*-1ŠNEXTWB(MESS2…DC.Bƒ'…Enter�one�of�the�above...�'MESS2E„EQU„*-1ŠNEXTWB?MESS4…DC.BƒCR,LF,LF,'…0�=�READ�THE�CURRENT�INPUT�STATUS.',CR,LFMESS4E„EQU„*-1ŠNEXTWB0MESS5…DC.Bƒ'…1�=�ENABLE�FOR�AN�INTERRUPT.',CR,LFMESS5E„EQU„*-1ŠNEXTWBMESS6…DC.Bƒ'…2�=�QUIT.',CR,LFMESS6E„EQU„*-1ŠNEXTWB4MESS9…DC.BƒCR,LF,'STATUS�OF�ALL�CHANNELS�(ASCII)�=�'MESS9E„EQU„*-1ŠNEXTWB2MESS10„DC.BƒCR,LF,'<<<�Starting�command�>>>',CR,LFMESS10EƒEQU„*-1ŠNEXTWB1MESS11„DC.BƒCR,LF,'<<<�Command�done�>>>',CR,LF,LFMESS11EƒEQU„*-1ŠNEXTWBŠPAGE,BADOPN„DC.BƒCR,LF,'***�OPEN�ABORTED�***�--�'BADOPNEƒEQU„*-1ŠNEXTWB8BADEN…DC.BƒCR,LF,'***�ENABLE�INTERRRUPT�ABORTED�***�--�'BADENE„EQU„*-1ŠNEXTWB:BADDIS„DC.BƒCR,LF,'***�DISABLE�INTERRRUPT�ABORTED�***�--�'BADDISEƒEQU„*-1ŠNEXTWB4BADREADƒDC.BƒCR,LF,'***�READ�STATUS�ABORTED�***�--�'BADREADE‚EQU„*-1ŠNEXTWB-BADCLS„DC.BƒCR,LF,'***�CLOSE�ABORTED�***�--�'BADCLSEƒEQU„*-1ŠNEXTWB+STATUSMƒDC.Bƒ'Error�code�returned�in�D0�=�'STATUSME‚EQU„*-1ŠNEXTWBCRLF†DC.BƒCR,LF CRLFE…EQU„*-1ŠNEXTWBŠPAGE N*******************************************************************************Ì**–P�R�O�G�R�A�MƒS�E�C�T�I�O�N™**Ì*N****************************************************************************** ŠSECTION�CODEPROGSTRTŠLEA„STACK(PC),A7.ŠLEA„PBA(PC),A4‰Get�Program�Base�Address�(PBA) &ŠOUTPUT�HEAD,HEADE‰Display�the�heading N*-----------------------------------------------------------------------------***‰Get�the�number�of�the�channel�to�convert*N*-----------------------------------------------------------------------------GETCHAN.ŠOUTPUT�MESS1,MESS1E‡Channel�number�to�convertŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.L�D0��#0�OR.L�D0��#7�THEN.S ŒBRA�GETCHANŠENDI8ŠMOVE.W�D0,OPEN_DCI+6-PBA(A4)�Save�the�channel�number... <ŠLEA„BIT_NUMBER(PC),A0‚Convert�the�channel�number�(0-7)�into?ŠMOVE.B�(A0,D0.W),D0‡the�corresponding�bit�number�(1,2,4,8...).8ŠMOVE.W�D0,READ_DCI+4-PBA(A4)�Save�the�bit�mask�value...ŠMOVE.W�D0,ENAB_DCI+4-PBA(A4)ŠMOVE.W�D0,DISB_DCI+4-PBA(A4) N*-----------------------------------------------------------------------------*4*‰Get„0�=�READ�STATUS‚1�=�ENABLE�INTERRUPTSƒ2�=�QUIT*N*-----------------------------------------------------------------------------GETCLST'ŠOUTPUT�MESS4,MESS4E…Put�up�the�menu...ŠOUTPUT�MESS5,MESS5EŠOUTPUT�MESS6,MESS6EFGET_CHOICE‚OUTPUT�MESS2,MESS2E…Ask�the�user�to�enter�one�of�the�above. +ŠINPUT‚INPUTBUF,INPUTBUF+8�Get�their�choiceŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.W�D0��#0�OR.W�D0��#2�THEN.S�BRA.S�GET_CHOICEŠENDIŠPAGE* *‰0�=�Read�input�status�co1 mmand:*ŠIF.B�D0��#0�THEN.L /ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> ŒBSR.L‚CLOSE_ALL>ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A06ŒLEA„READ_DCI(PC),A1‚Read�input�status�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#RLEN_DCI,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�READ_DCI(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADREAD,BADREADEƒ***�READ�STATUS�ABORTED�***ŒENDI ŒCLR.L‚D0<ŒMOVE.W�READ_DCI+4-PBA(A4),D0‚Get�the�status�value�returned.ŒBSR„BHLCVT�Convert�it�to�ASCII9ŒMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŒMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŒOUTPUT�MESS9,MESS9EŒOUTPUT�NUMBER,NUMBER+7ŒOUTPUT�CRLF,CRLFE 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDIŠPAGE* *‰1�=�Enable�interrupts�command:*ŠIF.B�D0��#1�THEN.S /ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> ŒBSR.L‚CLOSE_ALL 3ŒMOVE.W�#$7F08,D0ˆEnable�interrupts,�WAKEUP�option,8*‡software�debounce�=�508mSec,�trigger�on�negative�edge.$ŒBSR.S‚OPEN_CHANˆGo�open�the�channel *(*‚Do�a�wait�until�the�driver�wakes�us�up*ŒMOVE.L�#19,D0ŒTRAPƒ#1 ŒIF��THEN.SŽMOVE.W�ENAB_DCI(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)6ŽOUTPUT�BADEN,BADENE„***�ENABLE�INTERRUPTS�ABORTED�***ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰2�=�quit�command:*ŠIF.B�D0��#2�THEN.S �BRA.L�EXITŠENDI ŠBRA.L�GETCHAN�Go�start�over.ŠPAGEM*----------------------------------------------------------------------------**ƒOPEN�THE�CHANNEL*M*----------------------------------------------------------------------------OPEN_CHAN�LEA„CMRBLK(PC),A0ŠLEA„OPEN_DCI(PC),A1BŠMOVE.W�D0,OPEN_DCI+8-PBA(A4)‚Save�the�open�configuration�options.ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OLEN_DCI,$18(A0)7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�toŠTRAPƒ#1‘invoke�CMR.ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)+ŒOUTPUT�BADOPN,BADOPNE…***�OPEN�ABORTED�***ŒBRA.S‚SHOW_D0ŠENDIŠRTS M*----------------------------------------------------------------------------**ƒOUTPUT�THE�ERROR�CODE:*M*----------------------------------------------------------------------------:SHOW_D0ƒMOVE.L�STATUS(PC),D0†Get�the�status�value�returnedŠBSR„BHLCVT�Convert�it�to�ASCII9ŠMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŠMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŠOUTPUT�STATUSM,STATUSMEŠOUTPUT�NUMBER,NUMBER+7ŠOUTPUT�CRLF,CRLFE EXIT:ŠBSR.S‚CLOSE_ALL +EXIT_OUT:�MOVE.L�#15,D0�Terminate�this�taskŠTRAPƒ#1ŠPAGEN*-----------------------------------------------------------------------------**‚CLOSE�ALL�CHANNEL'S�ROUTINE:*N*-----------------------------------------------------------------------------CLOSE_ALL MOVE.W D0,-(A7) ŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)6ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�DC�INPUT�channelŠTRAPƒ#1ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)ŒBSR„BHLCVT�Convert�it�to�ASCII9ŒMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŒMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytes,ŒOUTPUT�BADCLS,BADCLSE…***�CLOSE�ABORTED�***ŒOUTPUT�NUMBER,NUMBER+7ŒOUTPUT�CRLF,CRLFEŒMOVE.W�(A7)+,D0‰Restore�stack.&ŒBRA.S‚EXIT_OUT‰Output�the�error�code.ŠENDI ŠMOVE.W�(A7)+,D0ŠRTS M*----------------------------------------------------------------------------*A*ƒTABLE�TO�CONVERT�THE�CHANNEL�NUMBER�(0-7)�TO�IT'S�CORRESPONDING**ƒBIT�MAPPED�VALUE�(1,2,4,8,16,32,64,128).*M*----------------------------------------------------------------------------$BIT_NUMBER‚DC.B‚1,2,4,8,16,32,64,128 ŠEND„PROGSTRT2 é=/*=/*†M610DRV.INTSTASM.AF=/*5=/* Chain file to assemble portion of the MVME610/620=/* driver test program.=/*:=/* If no output argument is specified for the listing the2=/* chain file will default to M610DRV.INTSTASM.LS=/*=/IFC \1ƒ=ARG�M610DRV.INTSTASM.LS=/ENDIF=/*4=ASM M610DRV.INTSTASM.SA,M610DRV.INTSTASM.RO,\1;Z=80=/*{ Included files are:=/*ƒ9995.&.TR1.EQ=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.EXE.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.M610CMD.EQ=/*}=/*=ENDéééééé9=/*=/*†M610DRV.TEST610.AF=/*,=/*†TEST610�test�program�assembly�chain�file=/*6=/*†The�command�line�will�accept�arguments�as�follows:=/*;=/*‹Argument�01…\1�=�Output�file�assembly�listing�or�device=/*=/*H=/*†The�following�shows�the�assembly�chain�sequence.‚In�this�example�theH=/*†NULL�device�was�chosen�as�Argument�01,�however,�the�user�could�if�he5=/*†so�desired�have�requested�an�output�listing�file.=/*#=/*�=CHAIN�M610DRV.TEST610.AF�#NULL=/*-=/*†Default�argument�01�is�M610DRV.TEST610.LS=/*=/IFC \1ƒ=ARG�M610DRV.TEST610.LS=/ENDIF=/*4=ASM M610DRV.TEST610.SA,M610DRV.TEST610.RO,\1;RZ=100=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDééé2 ééB'M615DRV TEST615 SAWWP¿bbTESTAC SA°°‰¨bbTEST615 AFAAbbTESTAC AFJJbbN*******************************************************************************Ì**Ì**–MVME615…Test�Programž**Ì**Ì*N********************************************************************************6* This program was written to test the MVME615 driver.**    *‰Modification�HistoryN*-----------------------------------------------------------------------------*�10/31/84‡DUH�Initial�writing   *�1.‚Introduction*C*‰This�program�was�written�to�test�the�MVME615�driver.‚This�programK*‚will�ask�for�the�channel�number�of�the�AC�output�module.‚It�will�then�askH*‚if�the�user�wants�to�turn�that�channel�on,�off,�pulsed�on,�or�read�theC*‚status�of�all�channels.‚A�lamp�connected�to�120VAC�can�be�used�to*‚monitor�the�channel.*6*‰This�program�assumes�the�board�is�jumpered�as�shown:* *‚VME615:%*„J2‚1,2‚3,4‚5,6†address�offset�$0003*ŠPAGE ,*£ASCVAL,�BHLCVT,�and�CVT2�are�commonly�used**£functions�which�are�modules�in�a�library(*£file�called�UTILIB.RO.‚A�call�to�these'*£functions�are�included�in�this�source)*£program,�which�is�provided�with�an�XREF&*£declaration.‚This�also�requires�that'*£UTILIB.RO�be�available�to�the�linkage$*£editor�during�the�linking�process.%*£See�TEST615.LF�for�link�chain�file. -ŠXREFƒASCVAL�Converts�ASCII�to�a�binary�value$*£This�routine�will�convert�an�ASCII,*£character�string�representing�a�decimal�or,*£hexidecimal�value�to�the�equivalent�binary,*£value.‚If�a�dollar�sign�($)�is�encountered&*£hexidecimal�conversion�is�performed;,*£otherwise�decimal�conversion�is�performed.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary'*£value.‚Conversion�terminates�when�the)*£first�invalid�character�is�encountered.'*£ENTRY:‚A0�-�Starting�address�of�ASCII*°character�string�to�convert#*£EXIT�:‚D1�-�Character�that�caused *°termination%*«D2�-�Class�code�of�terminating�char"*«D3�-�Binary�result�of�conversion*«A0�-�Address�of�the�characterOAX:`DhBpHxB€EˆQ�R˜I 3  *°following�the�terminating�char 8ŠXREFƒBHLCVT�Converts�4-byte�binary�value�to�ASCII�digit)*£This�routine�will�convert�a�long�binary-*£word�value�to�a�hexadecimal�value�expressed)*£as�an�8�character�ASCII�string.‚Leading*£zeros�are�suppressed.,*£ENTRY:‚D0.L�-�Binary�value�to�be�converted(*£EXIT�:‚D2.L�-�Four�high�order�bytes�of*²converted�value *«D3.L�-�Four�low�order�bytes�of*²converted�value 6ŠXREFƒCVT2�Converts�two�ASCII�decimal�digits�to�binary-*£This�routine�will�convert�two�ASCII�decimal(*£digits�to�the�equivalent�binary�value.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary**£value.‚Conversion�terminates�when�a�non-*£decimal�digit�is�encountered)*£ENTRY:‚A0�-�Address�of�most�significant*°ASCII�decimal�digit)*£EXIT�:‚D0�-�Binary�result�of�conversion!*«A0�-�Address�of�the�terminating *°character ŠPAGEŠMOVE.L�A0,IOSOUT+16-PBA(A4)�Set�the�ending�address�of�messageŠLEA„IOSOUT(PC),A0ŠTRAPƒ#2ŠENDM ŠPAGE 2ŠOPT„PCS�We�use�a�PCS�option�so�the�assembler�will%*£force�PC�relative�addressing�within(*£SECTION.‚Forces�PC�relative�addressing-*£(whenever�such�an�addressing�mode�is�legal))*£in�an�instruction�which�occurs�within�a'*£relocatable�SECTION�and�references�an,*£operand�in�a�relocatable�SECTION�(need�not**£be�the�same�SECTION�as�the�instruction).,*£Failure�to�resolve�sucn�a�reference�into�a-*£16-bit�displacement�from�the�PC�will�result)*£in�an�error.‚This�option�may�be�used�to+*£force�position�independent�code;�however,(*£this�option�does�not�force�PC�relative,*£addressing�of�absolute�operands�or�unknown*£forward�references. ŠPAGE N*******************************************************************************Ì**™D�A�T�AƒS�E�C�T�I�O�Nœ**Ì*N****************************************************************************** ŠSECTION�DATA $PBA‡EQU„*’Program�Base�Address�(PBA)%*£This�label�is�used�to�designate�the+*£beginning�of�the�program.‚This�is�used�to'*£make�references�to�other�parts�of�the*£program,�relocatable. 9ŠDS.WƒSTACKLEN‹This�is�the�stack�area�for�the�VME615�test2STACK…EQU„*’program.‚Registers�and�other�important,*£information�will�be�stored�on�the�stack�as)*£the�program�is�executed.‚The�stack�area'*£is�dynamic�and�will�change�during�the *£execution�of�the�test�program. =INPUTBUF‚DS.WƒSTRNGLEN‹This�is�the�storage�area�for�the�input*£strings�that�are�entered. 9STATUS„DS.Lƒ1’This�will�be�the�storage�are�for�the�status,*£code�that�is�returned�from�CMR.‚This�value-*£will�be�displayed�to�show�the�user�what�the*£error�code�was. 6NUMBER„DS.Lƒ2’Save�area�for�the�ASCII�value�of�STATUS.ŠPAGE N*******************************************************************************Ì*!*–P�A�R�A�M�E�T�E�RƒB�L�O�C�K�S—**Ì*N****************************************************************************** ŠNEXTWB”Force�even�boundaryIOSOUTŠDC.Bƒ0’Request�code"ŠDC.BƒWRITEŽFunction�specificationŠDC.Wƒ8’OptionsŠDC.Bƒ0’StatusŠDC.BƒCRT�Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address   ŠNEXTWB”Force�even�boundaryIOSINŠDC.Bƒ0’Request�code!ŠDC.BƒREAD�Function�specificationŠDC.Wƒ0’OptionsŠDC.Bƒ0’Status"ŠDC.BƒKEYBOARD‹Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address  CMRBLK„DC.Bƒ7’Initiate�I/OŠDC.BƒUNUSED�UnusedŠDC.WƒUNUSED�UnusedŠDC.Lƒ'ACO1'�Channel�nameŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�Unused$ŠDC.Lƒ0’Address�of�I/O�control�block#ŠDC.Lƒ0’Length�of�I/O�control�blockŠPAGE*8*‚OPEN�command�parameter�block�for�the�AC�OUTPUT�driver:+OPEN_ACO‚DC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�codeŠDC.Wƒ1’#�of�channels�to�open-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)-ŠDC.WƒDEFAULTŒChannel�configuration�(Dynamic)6OLEN_ACO‚EQU„*-OPEN_ACO‰Length�of�OPEN�parameter�block*C*‚START�OUTPUT�ON�command�parameter�block�for�the�AC�OUTPUT�driver:)ON_ACO„DC.Wƒ0’Returned�status�from�driverŠDC.WƒON‘ON�command�code2ŠDC.Wƒ0’Bit�mask�for�channels�to�turn�on�(Dynamic)2NLEN_ACO‚EQU„*-ON_ACO‹Length�of�ON�parameter�block*C*‚TURN�OUTPUT�OFF�command�parameter�block�for�the�AC�OUTPUT�driver:*OFF_ACOƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒOFF�Off�command�code4 3ŠDC.Wƒ0’Bit�mask�for�channels�to�turn�off�(Dynamic)4FLEN_ACO‚EQU„*-OFF_ACOŠLength�of�OFF�parameter�block*A*‚PULSED�OUTPUT�command�parameter�block�for�the�AC�OUTPUT�driver:*PON_ACOƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒPULSEŽPulse�command�codeŠDC.Wƒ1’#�of�channels,ŠDC.Wƒ0’Channel�number�(Dynamically�changed)/ŠDC.Lƒ0’Time�of�pulse�in�milliseconds�(Dynamic)6PLEN_ACO‚EQU„*-PON_ACOŠLength�of�PULSE�parameter�block*F*‚READ�OUTPUT�STATUS�command�parameter�block�for�the�AC�OUTPUT�driver:+READ_ACO‚DC.Wƒ0’Returned�status�from�driver*ŠDC.WƒREAD_STATUSˆRead�status�command�code.ŠDC.Wƒ0’Bit�mask�for�channels�to�read�and�upon(*£return�holds�the�actual�channel�status=RLEN_ACO‚EQU„*-READ_ACO‰Length�of�READ�STATUS�parameter�block*9*‚CLOSE�command�parameter�block�for�the�AC�OUTPUT�driver:)CLSBLK„DC.Wƒ0’Returned�status�from�driverŠDC.WƒCLOSEŽClose�command�codeCLOSLENƒEQU„*-CLSBLKŠNEXTWBŠPAGE N*******************************************************************************Ì**œM�E�S�S�A�G�E�S¡**Ì*N****************************************************************************** ŠSECTION�MESSAGES 9HEAD†DC.BƒCR,LF,LF,'MVME615�Driver�Test�Program',CR,LF,LF HEADE…EQU„*-1ŠNEXTWB1MESS1…DC.Bƒ'…Number�of�the�channel�to�convertˆ>�'MESS1E„EQU„*-1ŠNEXTWB(MESS2…DC.Bƒ'…Enter�one�of�the�above...�'MESS2E„EQU„*-1ŠNEXTWB8MESS3…DC.Bƒ'…Time�(in�milliseconds)�for�output�pulse�>�'MESS3E„EQU„*-1ŠNEXTWB+MESS4…DC.BƒCR,LF,LF,'…0�=�OUTPUT�ON.',CR,LFMESS4E„EQU„*-1ŠNEXTWB#MESS5…DC.Bƒ'…1�=�OUTPUT�OFF.',CR,LFMESS5E„EQU„*-1ŠNEXTWB=MESS6…DC.Bƒ'…2�=�PULSE�AN�OUTPUT�FOR�A�SPECIFIED�TIME.',CR,LFMESS6E„EQU„*-1ŠNEXTWB7MESS7…DC.Bƒ'…3�=�READ�THE�CURRENT�OUTPUT�STATUS.',CR,LFMESS7E„EQU„*-1ŠNEXTWB MESS8…DC.Bƒ'…4�=�QUIT.',CR,LF,LFMESS8E„EQU„*-1ŠNEXTWB4MESS9…DC.BƒCR,LF,'STATUS�OF�ALL�CHANNELS�(ASCII)�=�'MESS9E„EQU„*-1ŠNEXTWB2MESS10„DC.BƒCR,LF,'<<<�Starting�command�>>>',CR,LFMESS10EƒEQU„*-1ŠNEXTWB1MESS11„DC.BƒCR,LF,'<<<�Command�done�>>>',CR,LF,LFMESS11EƒEQU„*-1ŠNEXTWBŠPAGE,BADOPN„DC.BƒCR,LF,'***�OPEN�ABORTED�***�--�'BADOPNEƒEQU„*-1ŠNEXTWB6BADON…DC.BƒCR,LF,'***�START�OUTPUT�ON�ABORTED�***�--�'BADONE„EQU„*-1ŠNEXTWB7BADOFF„DC.BƒCR,LF,'***�TURN�OUTPUT�OFF�ABORTED�***�--�'BADOFFEƒEQU„*-1ŠNEXTWB:BADPLS„DC.BƒCR,LF,'***�START�OUTPUT�PULSE�ABORTED�***�--�'BADPLSEƒEQU„*-1ŠNEXTWB4BADREADƒDC.BƒCR,LF,'***�READ�STATUS�ABORTED�***�--�'BADREADE‚EQU„*-1ŠNEXTWB-BADCLS„DC.BƒCR,LF,'***�CLOSE�ABORTED�***�--�'BADCLSEƒEQU„*-1ŠNEXTWB+STATUSMƒDC.Bƒ'Error�code�returned�in�D0�=�'STATUSME‚EQU„*-1ŠNEXTWBCRLF†DC.BƒCR,LF CRLFE…EQU„*-1ŠNEXTWBŠPAGE N*******************************************************************************Ì**–P�R�O�G�R�A�MƒS�E�C�T�I�O�N™**Ì*N****************************************************************************** ŠSECTION�CODEPROGSTRTŠLEA„STACK(PC),A7.ŠLEA„PBA(PC),A4‰Get�Program�Base�Address�(PBA) &ŠOUTPUT�HEAD,HEADE‰Display�the�heading N*-----------------------------------------------------------------------------***‰Get�the�number�of�the�channel�to�convert*N*-----------------------------------------------------------------------------GETCHAN.ŠOUTPUT�MESS1,MESS1E‡Channel�number�to�convertŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.L�D0��#0�OR.L�D0��#7�THEN.S ŒBRA�GETCHANŠENDI8ŠMOVE.W�D0,OPEN_ACO+6-PBA(A4)�Save�the�channel�number...ŠMOVE.W�D0,PON_ACO+6-PBA(A4) <ŠLEA„BIT_NUMBER(PC),A0‚Convert�the�channel�number�(0-7)�into?ŠMOVE.B�(A0,D0.W),D0‡the�corresponding�bit�number�(1,2,4,8...).6ŠMOVE.W�D0,ON_ACO+4-PBA(A4)�Save�the�bit�mask�value...ŠMOVE.W�D0,OFF_ACO+4-PBA(A4)ŠMOVE.W�D0,READ_ACO+4-PBA(A4) N*-----------------------------------------------------------------------------*4*‰Get„0�=�OUTPUT�ON„1�=�OUTPUT�OFFƒ2�=�PULSED�OUTPUT*�3�=�READ�STATUS‚4�=�QUIT*4 N*-----------------------------------------------------------------------------GETCLST'ŠOUTPUT�MESS4,MESS4E…Put�up�the�menu...ŠOUTPUT�MESS5,MESS5EŠOUTPUT�MESS6,MESS6EŠOUTPUT�MESS7,MESS7EŠOUTPUT�MESS8,MESS8EFGET_CHOICE‚OUTPUT�MESS2,MESS2E…Ask�the�user�to�enter�one�of�the�above. +ŠINPUT‚INPUTBUF,INPUTBUF+8�Get�their�choiceŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.W�D0��#0�OR.W�D0��#4�THEN.S�BRA.S�GET_CHOICEŠENDIŠPAGE**‰0�=�Start�output�ON�command:*ŠIF.B�D0��#0�THEN.S 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> >ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A02ŒLEA„ON_ACO(PC),A1„Start�output�ON�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#NLEN_ACO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�ON_ACO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADON,BADONE…***�START�OUTPUT�ON�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰1�=�Turn�output�OFF�command:*ŠIF.B�D0��#1�THEN.S 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> >ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A03ŒLEA„OFF_ACO(PC),A1ƒTurn�output�OFF�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#FLEN_ACO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�OFF_ACO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)6ŽOUTPUT�BADOFF,BADOFFE„***�TURN�OUTPUT�OFF�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰2�=�PULSE�an�output�command:*ŠIF.B�D0��#2�THEN.L3ŒBSR„GET_TIME‰Get�the�pulse�duration�(milliseconds)+ŒMOVE.L�D3,PON_ACO+8-PBA(A4)�Store�the�time 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS10,MESS10E…<<<ƒStarting�commandƒ>>> 7ŒMOVE.W�#WAKEUP_O,D0…Use�the�WAKEUP�option�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A06ŒLEA„PON_ACO(PC),A1ƒStart�output�pulse�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#PLEN_ACO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1*(*ƒDo�a�wait�until�the�driver�wakes�us�up*ŒMOVE.L�#19,D0ŒTRAPƒ#1 ŒIF��THEN.SŽMOVE.W�PON_ACO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4);ŽOUTPUT�BADREAD,BADREADEƒ***�START�OUTPUT�PULSE�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰3�=�READ�STATUS�command:*ŠIF.B�D0��#3�THEN.L /ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> ŒLEA„CMRBLK(PC),A00ŒLEA„READ_ACO(PC),A1‚Read�status�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#RLEN_ACO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�READ_ACO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADREAD,BADREADEƒ***�READ�STATUS�ABORTED�***ŒENDI ŒCLR.L‚D0;ŒMOVE.W�READ_ACO+4-PBA(A4),D0‚Get�the�status�value�returnedŒBSR„BHLCVT�Convert�it�to�ASCII9ŒMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŒMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŒOUTPUT�MESS9,MESS9EŒOUTPUT�NUMBER,NUMBER+7ŒOUTPUT�CRLF,CRLFE 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI**‰4�=�quit�command:*ŠIF.B�D0�<EQ>�#4�THEN.S'�BSR.L‚CLOSE_ALLˆGo�close�all�channels. �BRA.L�EXITŠENDI ŠBRA.L�GETCHAN�Go�start�over.ŠPAGEM*----------------------------------------------------------------------------**ƒOPEN�THE�CHANNEL*M*----------------------------------------------------------------------------OPEN_CHAN�LEA„CMRBLK(PC),A0ŠLEA„OPEN_ACO(PC),A1BŠMOVE.W�D0,OPEN_ACO+8-PBA(A4)‚Save�the�open�configuration�options.ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OLEN_ACO,$18(A0)5 7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�toŠTRAPƒ#1‘invoke�CMR.ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)+ŒOUTPUT�BADOPN,BADOPNE…***�OPEN�ABORTED�***ŒBRA.S‚SHOW_D0ŠENDIŠRTS M*----------------------------------------------------------------------------*+*‚GET�THE�TIME�DURATION�FOR�AN�OUTPUT�PULSE*M*----------------------------------------------------------------------------GET_TIMEŠOUTPUT�MESS3,MESS3EŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0 ŠBSR„ASCVAL ŠTST.L‚D3 ŠBEQ„GET_TIME+ŠIF.L�D3��#0�OR.L�D3��#$FFFF�THEN.S ŒBRA„GET_TIMEŠENDIŠAND.L‚#$0000FFFF,D3ŠRTS M*----------------------------------------------------------------------------**ƒOUTPUT�THE�ERROR�CODE:*M*----------------------------------------------------------------------------:SHOW_D0ƒMOVE.L�STATUS(PC),D0†Get�the�status�value�returnedŠBSR„BHLCVT�Convert�it�to�ASCII9ŠMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŠMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŠOUTPUT�STATUSM,STATUSMEŠOUTPUT�NUMBER,NUMBER+7ŠOUTPUT�CRLF,CRLFE EXITŠBSR.S‚CLOSE_ALL"ŠMOVE.L�#15,D0�Terminate�this�taskŠTRAPƒ#1ŠPAGEN*-----------------------------------------------------------------------------**‚CLOSE�ALL�CHANNEL'S�ROUTINE:*N*-----------------------------------------------------------------------------CLOSE_ALL MOVE.W D0,-(A7) ŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)7ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�AC�OUTPUT�channelŠTRAPƒ#1ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4),ŒOUTPUT�BADCLS,BADCLSE…***�CLOSE�ABORTED�***ŒMOVE.W�(A7)+,D0‰Restore�stack.%ŒBRA.L‚SHOW_D0ŠOutput�the�error�code.ŠENDI ŠMOVE.W�(A7)+,D0ŠRTS M*----------------------------------------------------------------------------*A*ƒTABLE�TO�CONVERT�THE�CHANNEL�NUMBER�(0-7)�TO�IT'S�CORRESPONDING**ƒBIT�MAPPED�VALUE�(1,2,4,8,16,32,64,128).*M*----------------------------------------------------------------------------$BIT_NUMBER‚DC.B‚1,2,4,8,16,32,64,128 ŠEND„PROGSTRTééééééé5 B*„This�is�TESTAC,�a�relocatable�program�that�tests�the�ACO�driver.*$*„Copyrighted�1983�by�Motorola,�Inc.E**********************************************************************B*‚This�program�sets�up�for�task�ACO1�and�verifies�it�exists.�If�it;*‚does�it�proceeds�with�the�test,�if�not�it�trys�task�ACO2./*‚If�either�task�is�missing,�it�skips�the�test.*:*‚This�program�performs�the�following�tests�on�the�driver:*9*ˆTEST1‚-‚individually�opens�each�channel,�outputs�to�it,-*’checks�status,�turns�it�off,�checks�status, *’and�closes.9*ˆTEST2‚-‚individually�opens�each�channel,�outputs�to�it,1*’checks�status,�continues�until�all�are�on.�Then,*’individually�turns�off�each�channel,checks0*’status,�continues�until�all�are�off.�Turns�all%*’channels�back�on�for�the�next�test.7*ˆTEST3‚-‚closes�the�channels,�OPERATOR�must�check�they *’turned�off.4*ˆTEST4‚-‚opens�all�channels,�turns�all�channels�on,-*’delays,�turns�all�channels�off,�and�closes.9*ˆTEST5‚-‚individually�opens�each�channel,�commands�pulse*’output,�delays,�and�closes.7*ˆTEST6‚-‚opens�four�channels,�commands�pulse�output�of3*’different�lengths�to�each�simultaneously,�delays,*’closes�channels.;*ˆTEST7�-ƒopens�channel�two�with�queue�event�configuration,'*’pulses�output,�waits�for�queue�event,)*’verifies�message�sent,�closes�channels.:*ˆTEST8‚-‚opens�channel�one�with�wait�for�wake-up�config.,'*’pulses�output,�waits�for�wake-up,�and*’closes�channels.:*ˆTEST9‚-‚trys�output�ON�with�channels�closed�and�verifies*’error.3*’trys�output�OFF�with�channels�closed�and�verifies*’error./*’trys�checking�status�with�channels�closed�and*’verifies�error.,*’trys�pulse�output�with�channels�closed�and*’verifies�error.<*ˆTEST10�-‚trys�opening�invalid�channel�numbers�and�verifies3*’errors.�(ZERO�channels,�more�than�eight�channels,"*’channel�#�9,�same�two�channels).:*ˆTEST11�-‚opens�channel�and�trys�invalid�commands�(�0,�6,*’7,�>�8�)�and�verifies�errors. ¨/±P¹PÁPÉVÑ\Ù\áUéWñPùYZ YRR!W)b1=*ˆTEST12�-‚trys�opening�channels�when�they�are�already�opened*’and�verifies�error.*>*ˆIf�it�passed�these�tests�it�returns�to�the�top�to�set�up�for2*’task�ACO2.�If�this�was�for�task�ACO2,�it�sets�up$*’to�test�both�tasks�simultaneously.7*ˆIF�ALL�TESTS�ARE�SUCCESSFUL,�prints�message�attesting0*’to�that�fact.�If�any�test�fails,�ERROR�message$*’is�printed�and�test�is�terminated.*D********************************************************************‰PAGE*5IOADR0ƒEQU‡$F80000�VM02�base�mem�map�I/O�chan�address5IOADR1ƒEQU‡$FA0000�VM03�base�mem�map�I/O�chan�address7IOADR2ƒEQU‡$FE6000�VME110�base�mem�map�I/O�chan�address7IOADR3ƒEQU‡$F1C000�VME/10�base�mem�map�I/O�chan�address* ‰SECTIONƒ0*TEST…LEA‡STACK(PC),A7‰LEA‡INITIO(PC),A0.‰CLR.W…DUALFG-INITIO(A0)ƒclear�dual�test�flags‰CLR.W…DUALCK-INITIO(A0)**�SET�UP�A.S.Q.*!‰MOVE.L„#31,D0Žstage�command�code-‰LEA‡ASQBLOCK(PC),A0…stage�command�parameters.‰LEA‡TESTIRQ(PC),A1†initializes�addr.�of�async*‰MOVE.L„A1,ASQLA-ASQBLOCK(A0)‚service�rtn.‰TRAP†#1 ‰BNE‡FAULT11*‰MOVE.L„#'ACO1',D0(TNAME„LEA‡INITIO(PC),A0‡SET�UP�TASK�NAME‰MOVE.L„D0,ACOPAR-INITIO(A0)‰MOVE.L„D0,TMSG-INITIO(A0)*!TRYBTHƒLEA‡SMSG24(PC),A1‡space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*‰LEA‡SMSG24(PC),A1†again‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*.‰LEA‡SMSG1(PC),A1ˆoutput�start�of�test�message‰LEA‡EMSG1(PC),A2 ‰BSR‡MSGOUT*‰LEA‡SMSG24(PC),A1‡space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*‰LEA‡INITIO(PC),A0‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)+‰MOVE.W„#CLSLNG,A1ŠINSURE�CHANNEL(S)�CLOSED$‰MOVE.W„A1,CMDL-INITIO(A0)‚TO�START.‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT16*‰PAGE* *…OPEN�THE�CHANNELS�INDIVIDUALLY*5TEST1„LEA‡SMSG2(PC),A1‡output�'open�&�output'�message6 ‰LEA‡EMSG2(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0"‰CLR.W…0(A0)�initialize�parameters‰LEA‡INITIO(PC),A0*‰MOVE.W„#1,ONCMD1-INITIO(A0)�'ON'�bit�mask,‰MOVE.W„#1,OFFCMD1-INITIO(A0)�'OFF'�bit�mask2‰MOVE.W„#1,STATSHF-INITIO(A0)�status�req.�bit�mask;OPNLP„MOVE.W„EVNTCNT(PC),D0†OPEN�CHANNEL�(event�count�holds‰LEA‡INITIO(PC),A0‡channel�#�)+‰MOVE.W„D0,OPNCH-INITIO(A0)�channel�to�open‰LEA‡OPNCMDS(PC),A1,‰MOVE.L„A1,CMDA-INITIO(A0)‚parameters�to�CMR‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*+‰LEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNEL�OPENED‰LEA‡ONCMD(PC),A1,‰MOVE.L„A1,CMDA-INITIO(A0)‚parameters�to�CMR ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*!‰LEA‡OPNLP(PC),A1ˆloop�back�addr.&‰LEA‡TEST1B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*%TEST1BƒLEA‡INITIO(PC),A0‡CHECK�STATUS/‰MOVE.W„STATSHF(PC),D0†move�channel�to�check�to1‰MOVE.W„D0,STAT-INITIO(A0)‚status�parameter�block‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*3‰MOVE.W„STAT(PC),D0‰does�status�check�with�bit�that"‰CMP.W…ONCMD1(PC),D0‡should�be�on? ‰BNE‡FAULT4*#‰LEA‡INITIO(PC),A0‡TURN�OFF�CHANNEL‰LEA‡OFFCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT5*‰LEA‡INITIO(PC),A0‡CHECK�STATUS/‰MOVE.W„STATSHF(PC),D0†move�channel�to�check�to1‰MOVE.W„D0,STAT-INITIO(A0)‚status�parameter�block‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*.‰MOVE.W„STAT(PC),D0‰does�status�check�show�bit#‰BNE‡FAULT4Žstill�on?�if�so,�error.*#‰LEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST1B(PC),A1‡loop�back�addr.&‰LEA‡TEST1C(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST1CƒLEA‡INITIO(PC),A0>‰ASL.W…ONCMD1-INITIO(A0)ƒshift�'ON'�channel�bit�mask�one�place/‰ASL.W…OFFCMD1-INITIO(A0)‚shift�'OFF'ƒ"…"ƒ"„"„"0‰ASL.W…STATSHF-INITIO(A0)‚shift�status‚"…"ƒ"„"„"‰LEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP*‰PAGE*2*„OUTPUT�TO�CHANNELS�SEQUENTIALLY�UNTIL�ALL�ARE�ON*5TEST2„LEA‡SMSG3(PC),A1‡output�'output�to�all'�message‰LEA‡EMSG3(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0"‰CLR.W…0(A0)�initialize�parameters‰LEA‡INITIO(PC),A06‰MOVE.W„#1,ONCMD1-INITIO(A0)‚bit�mask�for�'ON'�channel9‰MOVE.W„#1,STATSHF-INITIO(A0)�bit�mask�for�status�channel)OPNLP2ƒMOVE.W„EVNTCNT(PC),D0†OPEN�CHANNEL‰LEA‡INITIO(PC),A0‰MOVE.W„D0,OPNCH-INITIO(A0)/‰LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*+‰LEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNEL�OPENED‰LEA‡ONCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡OPNLP2(PC),A1‡loop�back�addr.&‰LEA‡TEST2A(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*1TEST2AƒLEA‡INITIO(PC),A0‡CHECK�STATUS�OF�CHANNELS‰MOVE.W„STATSHF(PC),D0‰MOVE.W„D0,STAT-INITIO(A0)‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*&‰MOVE.W„STAT(PC),D0‰does�status�check?‰CMP.W…STATSHF(PC),D0 ‰BNE‡FAULT4*"‰LEA‡TEST2A(PC),A16 ‡loop�back�addr.&‰LEA‡TEST2B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST2BƒLEA‡INITIO(PC),A0>‰ASL.W…ONCMD1-INITIO(A0)ƒshift�'ON'�channel�bit�mask�one�place‰ORI‡#$10,CCRŒset�X�bit/‰ROXL.W„STATSHF-INITIO(A0)‚add�statusƒ"…"ƒ"„"„"‰LEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP2*7TEST2CƒLEA‡SMSG39(PC),A1‡output�'turn�off�seq.'�message‰LEA‡EMSG39(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0"‰CLR.W…0(A0)�initialize�parameters‰LEA‡INITIO(PC),A08‰MOVE.W„#1,OFFCMD1-INITIO(A0)‚bit�mask�for�'OFF'�channel9‰MOVE.W„#1,STATSHF-INITIO(A0)�bit�mask�for�status�channel*)OPNLP3ƒLEA‡INITIO(PC),A0‡TURN�OFF�CHANNEL‰LEA‡OFFCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT5*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡OPNLP3(PC),A1‡loop�back�addr.&‰LEA‡TEST2D(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*0TEST2DƒLEA‡INITIO(PC),A0‡CHECK�STATUS�OF�CHANNEL‰MOVE.W„STATSHF(PC),D0‰MOVE.W„D0,STAT-INITIO(A0)‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*&‰MOVE.W„STAT(PC),D0‰does�status�check? ‰BNE‡FAULT4*"‰LEA‡TEST2D(PC),A1‡loop�back�addr.&‰LEA‡TEST2E(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST2EƒLEA‡INITIO(PC),A0@‰ASL.W…OFFCMD1-INITIO(A0)‚shift�'OFF'�channel�bit�mask�one�place0‰ASL.W…STATSHF-INITIO(A0)‚shift�status‚"…"ƒ"„"„"‰LEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP3*+TEST2FƒLEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNELS‰LEA‡ONCMDA(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST2F(PC),A1‡loop�back�addr.%‰LEA‡TEST3(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle**%**************************************ƒCLOSE�TEST–*%**************************************-TEST3„LEA‡SMSG4(PC),A1‡output�'close'�message‰LEA‡EMSG4(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*)TEST3AƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST3A(PC),A1‡loop�back�addr.%‰LEA‡TEST4(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*‰PAGE$*„TURN�ON�ALL�OUTPUTS,�THEN�TURN�OFF*9TEST4„LEA‡SMSG5(PC),A1‡output�'turn�on,�turn�off'�message‰LEA‡EMSG5(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15**TEST4AƒLEA‡INITIO(PC),A0‡OPEN�ALL�CHANNELS/‰LEA‡OPNCMD(PC),A1‡point�to�CMR�parameter�block‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*,‰LEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNELS�OPENED‰LEA‡ONCMDA(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST4A(PC),A1‡loop�back�addr.&‰LEA‡TEST4B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle**TEST4BƒLEA‡INITIO(PC),A0‡TURN�OFF�CHANNELS‰LEA‡OFFCMDA(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT5*#‰LEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST4B(PC),A1‡loop�back�addr.%‰LEA‡TEST5(PC),A7 2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*‰PAGE*„PULSE�EACH�OUTPUT�IN�TURN*2TEST5„LEA‡SMSG6(PC),A1‡output�'pulse�each'�message‰LEA‡EMSG6(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0‰CLR.W…0(A0)�initialize�evntcnt)OPNLP4ƒMOVE.W„EVNTCNT(PC),D0†OPEN�CHANNEL/‰LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block+‰MOVE.W„D0,OPNCH-INITIO(A0)�channel�to�open,‰MOVE.W„D0,PLSO1-INITIO(A0)�channel�to�pulse‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡OPNLP4(PC),A1‡loop�back�addr.&‰LEA‡TEST5A(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*)TEST5AƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST5A(PC),A1‡loop�back�addr.&‰LEA‡TEST5B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST5BƒLEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP4*‰PAGE#*„PULSE�FOUR�OUTPUTS�SIMULTANEOUSLY*6TEST6„LEA‡SMSG32(PC),A1†output�'pulse�simult.'�message‰LEA‡EMSG32(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1500,A0Œ1500�MS‰TRAP†#1 ‰BNE‡FAULT15*&TEST6AƒLEA‡INITIO(PC),A0‡OPEN�CHANNELS‰LEA‡OPNCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSTWO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#PLSTLG,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST6A(PC),A1‡loop�back�addr.&‰LEA‡TEST6B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST6BƒMOVE.L„#21,D0ŽDELAY‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*)TEST6CƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST6C(PC),A1‡loop�back�addr.%‰LEA‡TEST7(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*‰PAGE+*„PULSE�OUTPUT�TWO�AND�GENERATE�QUEUE�EVENT*6TEST7„LEA‡SMSG7(PC),A1‡output�'pulse�output�2'�message‰LEA‡EMSG7(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*1TEST7AƒLEA‡RCVBUF(PC),A0‡ensure�RCVBUF�zeroed�out‰MOVE.L„#0,0(A0)‰MOVE.L„#0,4(A0)‰MOVE.L„#0,8(A0)*‰LEA‡INITIO(PC),A09‰MOVE.W„#0,OPNCNF-INITIO(A0)�set�up�config.�(queue�event)‰MOVE.W„#2,D0�OPEN�CHANNEL�TWO+‰MOVE.W„D0,OPNCH-INITIO(A0)‚channel�to�open,‰MOVE.W„D0,PLSO1-INITIO(A0)‚channel�to�pulse‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*+WAITQ„MOVE.L„#36,D0Žrequest�wait�for�event.$‰TRAP†#1’to�be�issued�by�ACO�driver. ‰BNE‡FAULT13*4‰MOVE.L„RCVBUF(PC),D0‡verify�message�returned�by�ASQ4‰CMP.L…#$0C010002,D0‡$0C01�� ‰BNE‡FAULT6‰MOVE.L„RCVBUF+4(PC),D0‰CMP.L…ACOPAR(PC),D0‡ACO-ID ‰BNE‡FAULT6‰MOVE.L„RCVBUF+8(PC),D0,‰AND.L…#$FFFFFF00,D0‡mask�off�low�order�byte0‰CMP.L…#IOADR0,D0ŠVM02�memory�mapped�I/O�address ‰BEQ.S…TEST710‰CMP.L…#IOADR1,D0ŠVM03�memory�mapped�I/O�address ‰BEQ.S…TEST722‰CMP.L…#IOADR2,D0ŠVME110�memory�mapped�I/O�add7 ress ‰BEQ.S…TEST732‰CMP.L…#IOADR3,D0ŠVME/10�memory�mapped�I/O�address ‰BNE‡FAULT6*‰LEA‡SMSG43(PC),A1‰LEA‡EMSG43(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TEST74TEST71ƒLEA‡SMSG40(PC),A1‰LEA‡EMSG40(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TEST74TEST72ƒLEA‡SMSG41(PC),A1‰LEA‡EMSG41(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TEST74TEST73ƒLEA‡SMSG42(PC),A1‰LEA‡EMSG42(PC),A2 ‰BSR‡MSGOUT2TEST74ƒLEA‡SMSG38(PC),A1‡output�'asq�verified'�msg‰LEA‡EMSG38(PC),A2 ‰BSR‡MSGOUT*"‰LEA‡TEST7A(PC),A1‡loop�back�addr.&‰LEA‡TEST7B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*)TEST7BƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST7B(PC),A1‡loop�back�addr.&‰LEA‡TEST7C(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*6TEST7CƒMOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰PAGE'*…PULSE�OUTPUT�ONE�AND�GENERATE�WAKE-UP3TEST8„LEA‡SMSG8(PC),A1‡output�'pulse�led�1'�message‰LEA‡EMSG8(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*1TEST8AƒLEA‡INITIO(PC),A0‡point�to�CMR�para.�block5‰MOVE.W„#1,OPNCNF-INITIO(A0)�set�up�config.�(wake-up)‰MOVE.W„#1,D0�OPEN�CHANNEL�ONE+‰MOVE.W„D0,OPNCH-INITIO(A0)‚channel�to�open,‰MOVE.W„D0,PLSO1-INITIO(A0)‚channel�to�pulse‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*-WAITW„MOVE.L„#19,D0Žrequest�wait�for�wake-up.$‰TRAP†#1’to�be�issued�by�ACO�driver. ‰BNE‡FAULT130‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST8A(PC),A1‡loop�back�addr.&‰LEA‡TEST8B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*)TEST8BƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST8B(PC),A1‡loop�back�addr.&‰LEA‡TEST8C(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*6TEST8CƒLEA‡INITIO(PC),A0‡restore�default�configuration ‰MOVE.W„#$8000,OPNCNF-INITIO(A0)2‰MOVE.W„#0,OPNCH-INITIO(A0)�restore�channel�select1‰MOVE.W„#1,STAT-INITIO(A0)‚restore�status�channel3‰MOVE.W„#1,OFFCMD1-INITIO(A0)‚restore�off�cmd�chan.*‰PAGE#*„TRY�COMMANDS�WITH�CHANNELS�CLOSED7TEST9„LEA‡SMSG9(PC),A1‡output�'try�with�closed'�message‰LEA‡EMSG9(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*1TEST9AƒLEA‡INITIO(PC),A0‡OUTPUT�TO�CLOSED�CHANNEL‰LEA‡ONCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1)‰MOVE.W„ONCMD(PC),D0ˆread�returned�status(‰CMP.W…#$F2,D0�verify�correct�error�code ‰BNE‡FAULT2 ‰LEA‡SMSG12(PC),A1‡output�ok�msg‰LEA‡EMSG12(PC),A2 ‰BSR‡MSGOUT*#‰LEA‡INITIO(PC),A0‡TURN�OFF�CHANNEL‰LEA‡OFFCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„OFFCMD(PC),D0‡read�returned�status(‰CMP.W…#$F2,D0�verify�correct�error�code ‰BNE‡FAULT5‰LEA‡SMSG14(PC),A1‡off�ok�msg‰LEA‡EMSG14(PC),A2 ‰BSR‡MSGOUT*‰LEA‡INITIO(PC),A0‡CHECK�STATUS‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1+‰MOVE.W„STATCMD(PC),D0†read�returned�status(‰CMP.W…#$F2,D0�verify�correct�error�code ‰BNE‡FAULT3 ‰LEA‡SMSG16(PC),A1‡status�ok�msg‰LEA‡EMSG16(PC),A2 ‰BSR‡MSGOUT*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1(‰MOVE.W„PLSO(PC),D0‰read�returned�status(‰CMP.W…#$F6,D0�verify�correct�error�code ‰BNE‡FAULT10*"‰LEA‡TEST9A(PC8 ),A1‡loop�back�addr.&‰LEA‡TEST9B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*%TEST9BƒLEA‡SMSG18(PC),A1‡pulse�ok�msg‰LEA‡EMSG18(PC),A2 ‰BSR‡MSGOUT*‰PAGE*ƒTRY�TO�OPEN�INVALID�CHANNELS6TEST10ƒLEA‡SMSG11(PC),A1‡output�'try�invalid�channels'‰LEA‡EMSG11(PC),A2 ‰BSR‡MSGOUT0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*3TEST10A‚LEA‡INITIO(PC),A0‡TRY�TO�OPEN�ZERO�CHANNELS‰LEA‡OPNCH0(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNCHL,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1%‰MOVE.W„OPNCH0(PC),D0‡read�cmd�status‰CMP.W…#$F7,D0 ‰BNE‡FAULT7*3‰LEA‡INITIO(PC),A0‡TRY�TO�OPEN�MORE�THAN�8�CHANNELS‰LEA‡OPNMOR(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNML,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1%‰MOVE.W„OPNMOR(PC),D0‡read�cmd�status‰CMP.W…#$F7,D0 ‰BNE‡FAULT7*,‰LEA‡INITIO(PC),A0‡TRY�TO�OPEN�CHANNEL�#�>�8‰LEA‡OPNCH9(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNC9L,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1%‰MOVE.W„OPNCH9(PC),D0‡read�cmd�status‰CMP.W…#$F6,D0 ‰BNE‡FAULT7*0‰LEA‡INITIO(PC),A0‡TRY�TO�OPEN�SAME�TWO�CHANNELS‰LEA‡OPNTW(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNTL,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1$‰MOVE.W„OPNTW(PC),D0ˆread�cmd�status‰CMP.W…#$FE,D0 ‰BNE‡FAULT7*#‰LEA‡TEST10A(PC),A1†loop�back�addr.'‰LEA‡TEST10B(PC),A2†continue�on�forward‰BRA‡FLOP�test�for�toggle*6TEST10B‚LEA‡SMSG36(PC),A1‡output�'invalid�channels�ok'‰LEA‡EMSG36(PC),A2 ‰BSR‡MSGOUT*‰PAGE*„TRY�TO�USE�INVALID�COMMANDS*2TEST11ƒLEA‡SMSG25(PC),A1‡output�'try�invalid�cmds'‰LEA‡EMSG25(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*&TEST11A‚LEA‡INITIO(PC),A0‡OPEN�CHANNEL‰MOVE.W„#1,OPNCH-INITIO(A0)‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*$‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�0‰LEA‡INVCM0(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM0(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*$‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�6‰LEA‡INVCM6(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM6(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*$‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�7‰LEA‡INVCM7(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM7(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*&‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�>�8‰LEA‡INVCM9(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM9(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*#‰LEA‡TEST11A(PC),A1†loop�back�addr.'‰LEA‡TEST11B(PC),A2†continue�on�forward‰BRA‡FLOP�test�for�toggle*-TEST11B‚LEA‡SMSG26(PC),A1‡invalid�cmds�ok�msg‰LEA‡EMSG26(PC),A2 ‰BSR‡MSGOUT*‰PAGE*„TRY�OPEN�AND�ALREADY�OPENED9TEST12ƒLEA‡SMSG20(PC),A1†output�'try�with�opened'�message‰LEA‡EMSG20(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*6TEST12A‚LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block(‰MOVE.W„#0,OPNCH-INITIO(A0)�OPEN�CHANNEL‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*/‰LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block‰LEA‡OPNCMDS(PC),A1)‰MOVE.L„A1,CMDA-INITIO(A0)‚TRY�OPEN�again‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1+‰MOVE.W„OPNCMDS(PC),D0‡read�returned�status‰CMP.W…#$FE,D0 ‰BNE.S…FAULT1*#‰LEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡C8 LSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*#‰LEA‡TEST12A(PC),A1†loop�back�addr.%‰LEA‡TESTC(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*1**************************************************„TEST�COMPLETED�*1************************************************* TESTC„LEA‡SMSG24(PC),A1‡space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*1‰LEA‡SMSG23(PC),A1†output�'test�complete'�message‰LEA‡EMSG23(PC),A2 ‰BSR‡MSGOUT*‰LEA‡SMSG24(PC),A1†space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*#NEXT…MOVE.W„DUALFG(PC),D0‡flag�set? ‰BNE‡TERM.NEXTA„MOVE.L„ACOPAR(PC),D0‡try�for�second�task‰CMP.L…#'ACO1',D0‰BNE‡TERMA�done‰MOVE.L„#'ACO2',D0‰BRA‡TNAME�set�up�second�task*‰PAGE*#FAULT1ƒLEA‡SMSG22(PC),A1‡open�error‰LEA‡EMSG22(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM%FAULT2ƒLEA‡SMSG13(PC),A1‡output�error‰LEA‡EMSG13(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM%FAULT3ƒLEA‡SMSG17(PC),A1‡status�error‰LEA‡EMSG17(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM+FAULT4ƒLEA‡SMSG28(PC),A1‡status�check�error‰LEA‡EMSG28(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM"FAULT5ƒLEA‡SMSG15(PC),A1‡off�error‰LEA‡EMSG15(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM*FAULT6ƒLEA‡SMSG10(PC),A1‡ASQ�message�error‰LEA‡EMSG10(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM.FAULT7ƒLEA‡SMSG21(PC),A1‡invalid�channel�error‰LEA‡EMSG21(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM$FAULT8ƒLEA‡SMSG33(PC),A1‡close�error‰LEA‡EMSG33(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM.FAULT9ƒLEA‡SMSG27(PC),A1‡invalid�cmd�error�msg‰LEA‡EMSG27(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM%FAULT10‚LEA‡SMSG19(PC),A1‡pulse�error‰LEA‡EMSG19(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM#FAULT11‚LEA‡SMSG30(PC),A1‡ASQ�error‰LEA‡EMSG30(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TERM#FAULT12‚LEA‡SMSG29(PC),A1‡ASQ�error‰LEA‡EMSG29(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM6FAULT13‚LEA‡SMSG31(PC),A1‡WAKE-UP�or�QUEUE�EVENT�error‰LEA‡EMSG31(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM2FAULT14‚LEA‡SMSG34(PC),A1‡IOS�(trap�#2)�call�error‰LEA‡EMSG34(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM*FAULT15‚LEA‡SMSG35(PC),A1‡call�delay�error‰LEA‡EMSG35(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM/FAULT16‚LEA‡SMSG37(PC),A1‡non-existant�task�msg‰LEA‡EMSG37(PC),A2 ‰BSR.S…MSGOUT(‰LEA‡DUALFG(PC),A0‡set�flag�to�eliminate‰ADD.W…#1,(A0)�dual�test ‰BRA‡NEXTA**„DE-ACTIVATE�SELF*0TERMA„LEA‡INITIO(PC),A0‡test�for�dual�board�test‰TST.W…DUALFG-INITIO(A0) ‰BNE.S…TERM4‰MOVE.W„#1,DUALFG-INITIO(A0)‚set�up�for�dual�bd�test‰MOVE.W„#1,DUALCK-INITIO(A0)!‰MOVE.L„#'ACO1',ACOPAR-INITIO(A0)*‰MOVE.L„#'ACO1',TMSG-INITIO(A0)‚set�up�msg‰MOVE.W„#'&2',TMSG+4-INITIO(A0) ‰BRA‡TRYBTH*%TERM…MOVE.L„#32,D0ŽDE-ALLOCATE�A.S.Q.‰TRAP†#1**‰MOVE.L„#15,D0ŽNOW�DE-ACTIVATE�SELF�(EXIT)‰TRAP†#1**„MESSAGE�OUTPUT�SUBROUTINE*/MSGOUTƒLEA‡MSG(PC),A0Šoutput�message�pointed�to(‰MOVE.L„A1,X1-MSG(A0)‡by�A1,�ended�by�A2‰MOVE.L„A2,X2-MSG(A0)‰TRAP†#2 ‰BNE‡FAULT14‰RTS*1FLOP…LEA‡INITIO(PC),A0‡toggle�between�ACO1�&�ACO2‰MOVE.W„DUALCK-INITIO(A0),D0 ‰BEQ.S…FLOP2�continue�on�if�zero‰CMP.W…#1,D0�see�if�=�1 ‰BNE.S…FLOP11‰MOVE.W„#2,DUALCK-INITIO(A0)‚is�=�1,�set�up�for�2!‰MOVE.L„#'ACO2',ACOPAR-INITIO(A0)‰JMP‡(A1)�loop�back6FLOP1„MOVE.W„#1,DUALCK-INITIO(A0)‚is�=�2,�set�up�for�1!‰MOVE.L„#'ACO1',ACOPAR-INITIO(A0))FLOP2„JMP‡(A2)�continue�on�with�next�test*-*ƒMOVE�THE�ASQ�MESSAGE�FROM�THE�ASQ�TO�RCVBUF*8TESTIRQ‚EQU‡*‰entry�point�moving�data�from�ASQ�to�RCVBUF!‰MOVE.L„#34,D0„stage�command�code‰LEA‡RCVBUF(PC),A0‰TRAP†#1 ‰BNE‡FAULT12*„RETURN�FROM�EVENT!‰MOVE.L„#37,D0„stage�command�code ‰MOVE.W„#1,A0‰TRAP†#1*‰PAGE**„CMR�parameter�block*INITIOƒDC.B†7,0,0,0ACOPARƒDC.L†'ACO1'„TASK�NAME ‰DC.L†0,0,0*CMDA…DC.L†0‰address�of�ACO�parameter�blockCMDL…DC.W†0‰command�length**„A.S.Q.�parameter�block*ASQBLOCK�EQU‡*‰DC.L†0‰task�name‰DC.L†0‰dummy�field*‰DC.B†5‰ASQ�&�ASR�enabled�=�initial�status"‰DC.B†16ˆlength�of�message�for�ASQ‰DC.L†16ˆstorage�for�4�events?ASQLA„DC.L†TESTIRQƒlogical�address�of�target�task�async�9 svc�rtn‰DC.L†0‰dummy�fieldASQLNGƒEQU‡*-ASQBLOCK*0*„ACO�parameter�block�to�open�individual�channel*OPNCMDS‚DC.W†0‰returned�status‰DC.W†1‰OPEN�command�code‰DC.W†1‰open�1�channelOPNCH„DC.W†0‰channel�#/OPNCNFƒDC.W†$8000…Default�channel�configurationOPNLNGS‚EQU‡*-OPNCMDS�length***„ACO�parameter�block�to�open�ALL�channels*OPNCMDƒDC.W†0‰returned�status‰DC.W†1‰OPEN�command�code‰DC.W†8‰open�8�channels*‰DC.W†0,$8000ƒCHAN�0,default�configuration‰DC.W†1,$8000ƒCHAN�1,ƒ"‰"‰DC.W†2,$8000ƒCHAN�2,ƒ"‰"‰DC.W†3,$8000ƒCHAN�3,ƒ"‰"‰DC.W†4,$8000ƒCHAN�4,ƒ"‰"‰DC.W†5,$8000ƒCHAN�5,ƒ"‰"‰DC.W†6,$8000ƒCHAN�6,ƒ"‰"‰DC.W†7,$8000ƒCHAN�7,ƒ"‰"OPNLNGƒEQU‡*-OPNCMD‚length*#*ƒparameter�block�for�CLOSE�command*CLSCMDƒDC.W†0‰returned�status‰DC.W†2‰CLOSE�command(CLSLNGƒEQU‡*-CLSCMD‚close�command�length*$*…ACO�parameter�block�for�ON�command* ONCMD„EQU‡*‰DC.W†0‰returned�command�status‰DC.W†3‰OUTPUT�ON�command,ONCMD1ƒDC.W†1‰bit�mask�of�channel�to�turn�ON* ONCMDAƒEQU‡*‰DC.W†0‰returned�command�status‰DC.W†3‰OUTPUT�ON�command,‰DC.W†$00FF…bit�mask�to�turn�ON�all�channels*%*…ACO�parameter�block�for�OFF�command* OFFCMDƒEQU‡*&‰DC.W†0‰return�command�status�location‰DC.W†4‰OFF�command.OFFCMD1‚DC.W†1‰bit�mask�of�channel�to�turn�OFF* OFFCMDA‚EQU‡*&‰DC.W†0‰return�command�status�location‰DC.W†4‰OFF�command-‰DC.W†$00FF…bit�mask�to�turn�OFF�all�channels*$*„parameter�block�for�STATUS�command* STATCMD‚EQU‡*‰DC.W†0‰returned�command�status‰DC.W†5‰STATUS�command2STAT…DC.W†1‰bit�mask�&�read�status�of�channels�0-7*:*„ACO�parameter�block�to�do�1000�ms�PULSE�on�selected�chan*PLSO…DC.W†0‰returned�cmd�status‰DC.W†8‰PULSE�command�code‰DC.W†1‰one�channelPLSO1„DC.W†1‰pulse�channel�#‰DC.L†500‡500�ms�pulse*7*„parameter�block�to�PULSE�four�channels�simultaneously*!PLSTWOƒDC.W†0‰returned�cmd�status‰DC.W†8‰PULSE�command�code‰DC.W†4‰four�channels‰DC.W†4‰chan.�#�4‰DC.L†250‡250�ms‰DC.W†5‰chan.�#�5‰DC.L†500‡500�ms‰DC.W†6‰chan.�#�6‰DC.L†750‡750�ms‰DC.W†7‰chan.�#�7‰DC.L†1000†1000�msPLSTLGƒEQU‡*-PLSTWO*"*„INVALID�CHANNEL�parameter�blocks*!OPNCH0ƒDC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�command�code‰DC.W†0‰open�zero�channels‰DC.W†0‰channel�0‰DC.W†$8000…config.OPNCHLƒEQU‡*-OPNCH0*!OPNCH9ƒDC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�cmd�code‰DC.W†1‰open�one�channel‰DC.W†9‰open�channel�#�9‰DC.W†$8000…config.OPNC9LƒEQU‡*-OPNCH9* OPNTW„DC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�cmd�code‰DC.W†3‰open�three�chan.‰DC.W†1,$8000ƒchan,�config.‰DC.W†2,$8000ƒchan,�config.‰DC.W†2,$8000ƒchan,�config.OPNTL„EQU‡*-OPNTW*!OPNMORƒDC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�cmd�code‰DC.W†9‰open�9�channels‰DC.W†0,$8000ƒchan,�config.‰DC.W†1,$8000ƒchan,�config.‰DC.W†2,$8000ƒchan,�config.‰DC.W†3,$8000ƒchan,�config.‰DC.W†4,$8000ƒchan,�config.‰DC.W†5,$8000ƒchan,�config.‰DC.W†6,$8000ƒchan,�config.‰DC.W†7,$8000ƒchan,�config.‰DC.W†8,$8000ƒchan,�config.OPNML„EQU‡*-OPNMOR*#*…INVALID�COMMANDS�parameter�blocks*!INVCM0ƒDC.W†0‰returned�cmd�status‰DC.W†0‰invalid�command�0*!INVCM6ƒDC.W†0‰returned�cmd�status‰DC.W†6‰invalid�command�6*!INVCM7ƒDC.W†0‰returned�cmd�status‰DC.W†7‰invalid�command�7*!INVCM9ƒDC.W†0‰returned�cmd�status"‰DC.W†9‰invalid�cmd�greater�than�8**„IOS�MESSAGE�parameter�block*MSG†DC.B†0‰Data�xfer�code=0‰DC.B†2‰Write�data‰DC.W†0‰Options�-�none‰DC.B†0‰Status ‰DC.B†6‰LUN‰DC.W†0‰reserved‰DC.L†0‰random�record�countX1‡DC.L†0‰bfr�start�addr.X2‡DC.L†0‰bfr�end�addr.‰DC.L†0‰length�of�data�xfer ‰DC.L†0‰completion/service�addr.*‰PAGE *„MESSAGES*6SMSG1„DC.W†'**********�AC�OUTPUT�TEST�PROGRAM�******�'TMSG…DC.W†'ACO1‚' EMSG1„EQU‡*-1*8SMSG2„DC.W†'‚OPEN�&�OUTPUT�TO�EACH�CHANNEL�INDIVIDUALLY' EMSG2„EQU‡*-1*9SMSG3„DC.W†'‚OPEN�&�OUTPUT�EACH�CHANNEL�UNTIL�ALL�ARE�ON' EMSG3„EQU‡*-1*5SMSG4„DC.W†'‚CLOSE�CHANNELS,�OUTPUTS�SHOULD�TU9 RN�OFF' EMSG4„EQU‡*-1*0SMSG5„DC.W†'‚TURN�ON�ALL�OUTPUTS,�THEN�TURN�OFF' EMSG5„EQU‡*-1*'SMSG6„DC.W†'‚PULSE�EACH�OUTPUT�IN�TURN' EMSG6„EQU‡*-1*5SMSG7„DC.W†'‚PULSE�OUTPUT�2�AND�GENERATE�QUEUE�EVENT' EMSG7„EQU‡*-1*1SMSG8„DC.W†'‚PULSE�OUTPUT�1�AND�GENERATE�WAKE-UP' EMSG8„EQU‡*-1*/SMSG9„DC.W†'‚TRY�COMMANDS�WITH�CHANNELS�CLOSED' EMSG9„EQU‡*-1**SMSG10ƒDC.W†'‚INVALID�ASQ�MESSAGE�-�ERROR'EMSG10ƒEQU‡*-1*+SMSG11ƒDC.W†'‚TRY�TO�OPEN�INVALID�CHANNELS'EMSG11ƒEQU‡*-1*4SMSG12ƒDC.W†'‚CALL�OUTPUT�AND�CHANNELS�CLOSED�-�OK!'EMSG12ƒEQU‡*-1*"SMSG13ƒDC.W†'‚CALL�OUTPUT�-�ERROR'EMSG13ƒEQU‡*-1*1SMSG14ƒDC.W†'‚CALL‚OFFƒAND�CHANNELS�CLOSED�-�OK!'EMSG14ƒEQU‡*-1*SMSG15ƒDC.W†'‚CALL�OFF�-�ERROR'EMSG15ƒEQU‡*-1*4SMSG16ƒDC.W†'‚CALL�STATUS�AND�CHANNELS�CLOSED�-�OK!'EMSG16ƒEQU‡*-1*"SMSG17ƒDC.W†'‚CALL�STATUS�-�ERROR'EMSG17ƒEQU‡*-1*3SMSG18ƒDC.W†'‚CALL�PULSE‚AND�CHANNELS�CLOSED�-�OK!'EMSG18ƒEQU‡*-1*!SMSG19ƒDC.W†'‚CALL�PULSE�-�ERROR'EMSG19ƒEQU‡*-1*4SMSG20ƒDC.W†'‚TRY�CALL�OPEN�AND�ALREADY�OPENED�-OK!'EMSG20ƒEQU‡*-1*&SMSG21ƒDC.W†'‚INVALID�CHANNEL�-�ERROR'EMSG21ƒEQU‡*-1* SMSG22ƒDC.W†'‚CALL�OPEN�-�ERROR'EMSG22ƒEQU‡*-1*9SMSG23ƒDC.W†'‚******�TEST�COMPLETED�SUCCESSFULLY�*******'EMSG23ƒEQU‡*-1*SMSG24ƒDC.W†'‚'EMSG24ƒEQU‡*-1**SMSG25ƒDC.W†'‚TRY�TO�USE�INVALID�COMMANDS'EMSG25ƒEQU‡*-1**SMSG26ƒDC.W†'‚CALL„INVALID„COMMANDS„-‚OK!'EMSG26ƒEQU‡*-1*&SMSG27ƒDC.W†'‚INVALID�COMMAND�-�ERROR'EMSG27ƒEQU‡*-1*#SMSG28ƒDC.W†'‚STATUS�CHECK�-�ERROR'EMSG28ƒEQU‡*-1*"SMSG29ƒDC.W†'‚A.S.Q.�MOVE‚-�ERROR'EMSG29ƒEQU‡*-1*SMSG30ƒDC.W†'‚A.S.Q.�-�ERROR'EMSG30ƒEQU‡*-1*$SMSG31ƒDC.W†'‚WAKEUP�OR�QUEUE�ERROR'EMSG31ƒEQU‡*-1*9SMSG32ƒDC.W†'‚PULSE�CHANNELS�4,�5,�6,�&�7�SIMULTANEOUSLY'EMSG32ƒEQU‡*-1*!SMSG33ƒDC.W†'‚CALL�CLOSE�-�ERROR'EMSG33ƒEQU‡*-1*#SMSG34ƒDC.W†'‚TRAP�#�2�(IOS)�ERROR'EMSG34ƒEQU‡*-1*!SMSG35ƒDC.W†'‚CALL�DELAY�-�ERROR'EMSG35ƒEQU‡*-1**SMSG36ƒDC.W†'‚CALL„INVALID„CHANNELS„-‚OK!'EMSG36ƒEQU‡*-1*‰PAGE*:SMSG37ƒDC.W†'-�-�-�NON-EXISTANT�TASK/BOARD�-�-�-�-�-�-�-^'EMSG37ƒEQU‡*-1*&SMSG38ƒDC.W†'‚A.S.Q.�MESSAGE�VERIFIED'EMSG38ƒEQU‡*-1*-SMSG39ƒDC.W†'‚TURN�OFF�CHANNELS�SEQUENTIALLY'EMSG39ƒEQU‡*-1*SMSG40ƒDC.W†'‚VM02'EMSG40ƒEQU‡*-1*SMSG41ƒDC.W†'‚VM03'EMSG41ƒEQU‡*-1*SMSG42ƒDC.W†'‚VME110'EMSG42ƒEQU‡*-1*SMSG43ƒDC.W†'‚VME/10'EMSG43ƒEQU‡*-1*‰PAGE*EVNTCNT‚DS.W†1‰event�counter!STATSHF‚DS.W†1‰status�bit�shifter1DUALFGƒDS.W†1‰dual�board�test�flag(1=do�not�test)ŠMOVE.L�A0,IOSOUT+16-PBA(A4)�Set�the�ending�address�of�messageŠLEA„IOSOUT(PC),A0ŠTRAPƒ#2ŠENDM ŠPAGE 2ŠOPT„PCS�We�use�a�PCS�option�so�the�assembler�will%*£force�PC�relative�addressing�within(*£SECTION.‚Forces�PC�relative�addressing-*£(whenever�such�an�addressing�mode�is�legal))*£in�an�instruction�which�occurs�within�a'*£relocatable�SECTION�and�references�an,*£operand�in�a�relocatable�SECTION�(need�not**£be�the�same�SECTION�as�the�instruction).,*£Failure�to�resolve�sucn�a�reference�into�a-*£16-bit�displacement�from�the�PC�will�result)*£in�an�error.‚This�option�may�be�used�to+*£force�position�independent�code;�however,(*£this�option�does�not�force�PC�relative,*£addressing�of�absolute�operands�or�unknown*£forward�references. ŠPAGE N*******************************************************************************Ì**™D�A�T�AƒS�E�C�T�I�O�Nœ**Ì*N****************************************************************************** ŠSECTION�DATA $PBA‡EQU„*’Program�Base�Address�(PBA)%*£This�label�is�used�to�designate�the+*£beginning�of�the�program.‚This�is�used�to'*£make�references�to�other�parts�of�the*£program,�relocatable. 9ŠDS.WƒSTACKLEN‹This�is�the�stack�area�for�the�VME625�test2STACK…EQU„*’program.‚Registers�and�other�important,*£information�will�be�stored�on�the�stack�as)*£the�program�is�executed.‚The�stack�area'*£is�dynamic�and�will�change�during�the *£execution�of�the�test�program. =INPUTBUF‚DS.WƒSTRNGLEN‹This�is�the�storage�area�for�the�input*£strings�that�are�entered. 9STATUS„DS.Lƒ1’This�will�be�the�storage�are�for�the�status,*£code�that�is�returned�from�CMR.‚This�value-*£will�be�displayed�to�show�the�user�what�the*£error�code�was. 6NUMBER„DS.Lƒ2’Save�area�for�the�ASCII�value�of�STATUS.ŠPAGE N*******************************************************************************Ì*!*–P�A�R�A�M�E�T�E�RƒB�L�O�C�K�S—**Ì*N****************************************************************************** ŠNEXTWB”Force�even�boundaryIOSOUTŠDC.Bƒ0’Request�code"ŠDC.BƒWRITEŽFunction�specificationŠDC.Wƒ8’OptionsŠDC.Bƒ0’StatusŠDC.BƒCRT�Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address   ŠNEXTWB”Force�even�boundaryIOSINŠDC.Bƒ0’Request�code!ŠDC.BƒREAD�Function�specificationŠDC.Wƒ0’OptionsŠDC.Bƒ0’Status"ŠDC.BƒKEYBOARD‹Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address  CMRBLK„DC.Bƒ7’Initiate�I/OŠDC.BƒUNUSED�UnusedŠDC.WƒUNUSED�UnusedŠDC.Lƒ'DCO1'�Channel�nameŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�Unused$ŠDC.Lƒ0’Address�of�I/O�control�block#ŠDC.Lƒ0’Length�of�I/O�control�blockŠPAGE*8*‚OPEN�command�parameter�block�for�the�DC�OUTPUT�driver:+OPEN_DCO‚DC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�codeŠDC.Wƒ1’#�of�channels�to�open-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)-ŠDC.WƒDEFAULTŒChannel�configuration�(Dynamic)6OLEN_DCO‚EQU„*-OPEN_DCO‰Length�of�OPEN�parameter�block*C*‚START�OUTPUT�ON�command�parameter�block�for�the�DC�OUTPUT�driver:)ON_DCO„DC.Wƒ0’Returned�status�from�driverŠDC.WƒON‘ON�command�code2ŠDC.Wƒ0’Bit�mask�for�channels�to�turn�on�(Dynamic)2NLEN_DCO‚EQU„*-ON_DCO‹Length�of�ON�parameter�block*C*‚TURN�OUTPUT�OFF�command�parameter�block�for�the�DC�OUTPUT�driver:*OFF_DCOƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒOFF�Off�command�code3ŠDC.Wƒ0’Bit�mask�for�channels�to�turn�off�(Dynamic)4FLEN_DCO‚EQU„*-OFF_DCOŠLength�of�OFF�parameter�block*< A*‚PULSED�OUTPUT�command�parameter�block�for�the�DC�OUTPUT�driver:*PON_DCOƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒPULSEŽPulse�command�codeŠDC.Wƒ1’#�of�channels,ŠDC.Wƒ0’Channel�number�(Dynamically�changed)/ŠDC.Lƒ0’Time�of�pulse�in�milliseconds�(Dynamic)6PLEN_DCO‚EQU„*-PON_DCOŠLength�of�PULSE�parameter�block*F*‚READ�OUTPUT�STATUS�command�parameter�block�for�the�DC�OUTPUT�driver:+READ_DCO‚DC.Wƒ0’Returned�status�from�driver*ŠDC.WƒREAD_STATUSˆRead�status�command�code.ŠDC.Wƒ0’Bit�mask�for�channels�to�read�and�upon(*£return�holds�the�actual�channel�status=RLEN_DCO‚EQU„*-READ_DCO‰Length�of�READ�STATUS�parameter�block*9*‚CLOSE�command�parameter�block�for�the�DC�OUTPUT�driver:)CLSBLK„DC.Wƒ0’Returned�status�from�driverŠDC.WƒCLOSEŽClose�command�codeCLOSLENƒEQU„*-CLSBLKŠNEXTWBŠPAGE N*******************************************************************************Ì**œM�E�S�S�A�G�E�S¡**Ì*N****************************************************************************** ŠSECTION�MESSAGES 9HEAD†DC.BƒCR,LF,LF,'MVME625�Driver�Test�Program',CR,LF,LF HEADE…EQU„*-1ŠNEXTWB1MESS1…DC.Bƒ'…Number�of�the�channel�to�convertˆ>�'MESS1E„EQU„*-1ŠNEXTWB(MESS2…DC.Bƒ'…Enter�one�of�the�above...�'MESS2E„EQU„*-1ŠNEXTWB8MESS3…DC.Bƒ'…Time�(in�milliseconds)�for�output�pulse�>�'MESS3E„EQU„*-1ŠNEXTWB+MESS4…DC.BƒCR,LF,LF,'…0�=�OUTPUT�ON.',CR,LFMESS4E„EQU„*-1ŠNEXTWB#MESS5…DC.Bƒ'…1�=�OUTPUT�OFF.',CR,LFMESS5E„EQU„*-1ŠNEXTWB=MESS6…DC.Bƒ'…2�=�PULSE�AN�OUTPUT�FOR�A�SPECIFIED�TIME.',CR,LFMESS6E„EQU„*-1ŠNEXTWB7MESS7…DC.Bƒ'…3�=�READ�THE�CURRENT�OUTPUT�STATUS.',CR,LFMESS7E„EQU„*-1ŠNEXTWB MESS8…DC.Bƒ'…4�=�QUIT.',CR,LF,LFMESS8E„EQU„*-1ŠNEXTWB4MESS9…DC.BƒCR,LF,'STATUS�OF�ALL�CHANNELS�(ASCII)�=�'MESS9E„EQU„*-1ŠNEXTWB2MESS10„DC.BƒCR,LF,'<<<�Starting�command�>>>',CR,LFMESS10EƒEQU„*-1ŠNEXTWB1MESS11„DC.BƒCR,LF,'<<<�Command�done�>>>',CR,LF,LFMESS11EƒEQU„*-1ŠNEXTWBŠPAGE,BADOPN„DC.BƒCR,LF,'***�OPEN�ABORTED�***�--�'BADOPNEƒEQU„*-1ŠNEXTWB6BADON…DC.BƒCR,LF,'***�START�OUTPUT�ON�ABORTED�***�--�'BADONE„EQU„*-1ŠNEXTWB7BADOFF„DC.BƒCR,LF,'***�TURN�OUTPUT�OFF�ABORTED�***�--�'BADOFFEƒEQU„*-1ŠNEXTWB:BADPLS„DC.BƒCR,LF,'***�START�OUTPUT�PULSE�ABORTED�***�--�'BADPLSEƒEQU„*-1ŠNEXTWB4BADREADƒDC.BƒCR,LF,'***�READ�STATUS�ABORTED�***�--�'BADREADE‚EQU„*-1ŠNEXTWB-BADCLS„DC.BƒCR,LF,'***�CLOSE�ABORTED�***�--�'BADCLSEƒEQU„*-1ŠNEXTWB+STATUSMƒDC.Bƒ'Error�code�returned�in�D0�=�'STATUSME‚EQU„*-1ŠNEXTWBCRLF†DC.BƒCR,LF CRLFE…EQU„*-1ŠNEXTWBŠPAGE N*******************************************************************************Ì**–P�R�O�G�R�A�MƒS�E�C�T�I�O�N™**Ì*N****************************************************************************** ŠSECTION�CODEPROGSTRTŠLEA„STACK(PC),A7.ŠLEA„PBA(PC),A4‰Get�Program�Base�Address�(PBA) &ŠOUTPUT�HEAD,HEADE‰Display�the�heading N*-----------------------------------------------------------------------------***‰Get�the�number�of�the�channel�to�convert*N*-----------------------------------------------------------------------------GETCHAN.ŠOUTPUT�MESS1,MESS1E‡Channel�number�to�convertŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.L�D0��#0�OR.L�D0��#7�THEN.S ŒBRA�GETCHANŠENDI8ŠMOVE.W�D0,OPEN_DCO+6-PBA(A4)�Save�the�channel�number...ŠMOVE.W�D0,PON_DCO+6-PBA(A4) <ŠLEA„BIT_NUMBER(PC),A0‚Convert�the�channel�number�(0-7)�into?ŠMOVE.B�(A0,D0.W),D0‡the�corresponding�bit�number�(1,2,4,8...).6ŠMOVE.W�D0,ON_DCO+4-PBA(A4)�Save�the�bit�mask�value...ŠMOVE.W�D0,OFF_DCO+4-PBA(A4)ŠMOVE.W�D0,READ_DCO+4-PBA(A4) N*-----------------------------------------------------------------------------*4*‰Get„0�=�OUTPUT�ON„1�=�OUTPUT�OFFƒ2�=�PULSED�OUTPUT*�3�=�READ�STATUS‚4�=�QUIT*N*-----------------------------------------------------------------------------GETCLST'ŠOUTPUT�MESS4,MESS4E…Put�up�the�menu...ŠOUTPUT�MESS5,MESS5EŠOUTPUT�MESS6,MESS6EŠOUTPUT�MESS7,MESS7E< ŠOUTPUT�MESS8,MESS8EFGET_CHOICE‚OUTPUT�MESS2,MESS2E…Ask�the�user�to�enter�one�of�the�above. +ŠINPUT‚INPUTBUF,INPUTBUF+8�Get�their�choiceŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.W�D0��#0�OR.W�D0��#4�THEN.S�BRA.S�GET_CHOICEŠENDIŠPAGE**‰0�=�Start�output�ON�command:*ŠIF.B�D0��#0�THEN.S 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> >ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A02ŒLEA„ON_DCO(PC),A1„Start�output�ON�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#NLEN_DCO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�ON_DCO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADON,BADONE…***�START�OUTPUT�ON�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰1�=�Turn�output�OFF�command:*ŠIF.B�D0��#1�THEN.S 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> >ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A03ŒLEA„OFF_DCO(PC),A1ƒTurn�output�OFF�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#FLEN_DCO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�OFF_DCO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)6ŽOUTPUT�BADOFF,BADOFFE„***�TURN�OUTPUT�OFF�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰2�=�PULSE�an�output�command:*ŠIF.B�D0��#2�THEN.L3ŒBSR„GET_TIME‰Get�the�pulse�duration�(milliseconds)+ŒMOVE.L�D3,PON_DCO+8-PBA(A4)�Store�the�time 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS10,MESS10E…<<<ƒStarting�commandƒ>>> 7ŒMOVE.W�#WAKEUP_O,D0…Use�the�WAKEUP�option�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A06ŒLEA„PON_DCO(PC),A1ƒStart�output�pulse�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#PLEN_DCO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1*(*ƒDo�a�wait�until�the�driver�wakes�us�up*ŒMOVE.L�#19,D0ŒTRAPƒ#1 ŒIF��THEN.SŽMOVE.W�PON_DCO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4);ŽOUTPUT�BADREAD,BADREADEƒ***�START�OUTPUT�PULSE�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI **‰3�=�READ�STATUS�command:*ŠIF.B�D0��#3�THEN.L /ŒOUTPUT�MESS10,MESS10Eƒ<<<ƒStarting�commandƒ>>> ŒLEA„CMRBLK(PC),A00ŒLEA„READ_DCO(PC),A1‚Read�status�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#RLEN_DCO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�READ_DCO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADREAD,BADREADEƒ***�READ�STATUS�ABORTED�***ŒENDI ŒCLR.L‚D0;ŒMOVE.W�READ_DCO+4-PBA(A4),D0‚Get�the�status�value�returnedŒBSR„BHLCVT�Convert�it�to�ASCII9ŒMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŒMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŒOUTPUT�MESS9,MESS9EŒOUTPUT�NUMBER,NUMBER+7ŒOUTPUT�CRLF,CRLFE 3ŒOUTPUT�MESS11,MESS11Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI**‰4�=�quit�command:*ŠIF.B�D0��#4�THEN.S'�BSR.L‚CLOSE_ALLˆGo�close�all�channels. �BRA.L�EXITŠENDI ŠBRA.L�GETCHAN�Go�start�over.ŠPAGEM*----------------------------------------------------------------------------**ƒOPEN�THE�CHANNEL*M*----------------------------------------------------------------------------OPEN_CHAN�LEA„CMRBLK(PC),A0ŠLEA„OPEN_DCO(PC),A1BŠMOVE.W�D0,OPEN_DCO+8-PBA(A4)‚Save�the�open�configuration�options.ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OLEN_DCO,$18(A0)7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�toŠTRAPƒ#1‘invoke�CMR.ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)+ŒOUTPUT�BADOPN,BADOPNE…***�OPEN�ABORTED�***ŒBRA.S‚SHOW_D0ŠENDIŠRTS = M*----------------------------------------------------------------------------*+*‚GET�THE�TIME�DURATION�FOR�AN�OUTPUT�PULSE*M*----------------------------------------------------------------------------GET_TIMEŠOUTPUT�MESS3,MESS3EŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0 ŠBSR„ASCVAL ŠTST.L‚D3 ŠBEQ„GET_TIME+ŠIF.L�D3��#0�OR.L�D3��#$FFFF�THEN.S ŒBRA„GET_TIMEŠENDIŠAND.L‚#$0000FFFF,D3ŠRTS M*----------------------------------------------------------------------------**ƒOUTPUT�THE�ERROR�CODE:*M*----------------------------------------------------------------------------:SHOW_D0ƒMOVE.L�STATUS(PC),D0†Get�the�status�value�returnedŠBSR„BHLCVT�Convert�it�to�ASCII9ŠMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŠMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŠOUTPUT�STATUSM,STATUSMEŠOUTPUT�NUMBER,NUMBER+7ŠOUTPUT�CRLF,CRLFE EXITŠBSR.S‚CLOSE_ALL"ŠMOVE.L�#15,D0�Terminate�this�taskŠTRAPƒ#1ŠPAGEN*-----------------------------------------------------------------------------**‚CLOSE�ALL�CHANNEL'S�ROUTINE:*N*-----------------------------------------------------------------------------CLOSE_ALL MOVE.W D0,-(A7) ŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)7ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�DC�OUTPUT�channelŠTRAPƒ#1ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4),ŒOUTPUT�BADCLS,BADCLSE…***�CLOSE�ABORTED�***ŒMOVE.W�(A7)+,D0‰Restore�stack.%ŒBRA.L‚SHOW_D0ŠOutput�the�error�code.ŠENDI ŠMOVE.W�(A7)+,D0ŠRTS M*----------------------------------------------------------------------------*A*ƒTABLE�TO�CONVERT�THE�CHANNEL�NUMBER�(0-7)�TO�IT'S�CORRESPONDING**ƒBIT�MAPPED�VALUE�(1,2,4,8,16,32,64,128).*M*----------------------------------------------------------------------------$BIT_NUMBER‚DC.B‚1,2,4,8,16,32,64,128 ŠEND„PROGSTRTB*„This�is�TESTDC,�a�relocatable�program�that�tests�the�DCO�driver.*$*„Copyrighted�1983�by�Motorola,�Inc.E**********************************************************************B*‚This�program�sets�up�for�task�DCO1�and�verifies�it�exists.�If�it;*‚does�it�proceeds�with�the�test,�if�not�it�trys�task�DCO2./*‚If�either�task�is�missing,�it�skips�the�test.*:*‚This�program�performs�the�following�tests�on�the�driver:*9*ˆTEST1‚-‚individually�opens�each�channel,�outputs�to�it,-*’checks�status,�turns�it�off,�checks�status, *’and�closes.9*ˆTEST2‚-‚individually�opens�each�channel,�outputs�to�it,1*’checks�status,�continues�until�all�are�on.�Then,*’individually�turns�off�each�channel,checks0*’status,�continues�until�all�are�off.�Turns�all%*’channels�back�on�for�the�next�test.7*ˆTEST3‚-‚closes�the�channels,�OPERATOR�must�check�they *’turned�off.4*ˆTEST4‚-‚opens�all�channels,�turns�all�channels�on,-*’delays,�turns�all�channels�off,�and�closes.9*ˆTEST5‚-‚individually�opens�each�channel,�commands�pulse*’output,�delays,�and�closes.7*ˆTEST6‚-‚opens�four�channels,�commands�pulse�output�of3*’different�lengths�to�each�simultaneously,�delays,*’closes�channels.;*ˆTEST7�-ƒopens�channel�two�with�queue�event�configuration,'*’pulses�output,�waits�for�queue�event,)*’verifies�message�sent,�closes�channels.:*ˆTEST8‚-‚opens�channel�one�with�wait�for�wake-up�config.,'*’pulses�output,�waits�for�wake-up,�and*’closes�channels.:*ˆTEST9‚-‚trys�output�ON�with�channels�closed�and�verifies*’error.3*’trys�output�OFF�with�channels�closed�and�verifies*’error./*’trys�checking�status�with�channels�closed�and*’verifies�error.,*’trys�pulse�output�with�channels�closed�and*’verifies�error.<*ˆTEST10�-‚trys�opening�invalid�channel�numbers�and�verifies3*’errors.�(ZERO�channels,�more�than�eight�channels,"*’channel�#�9,�same�two�channels).:*ˆTEST11�-‚opens�channel�and�trys�invalid�commands�(�0,�6,*’7,�>�8�)�and�verifies�errors.=   /©P±P¹PÁVÉ\Ñ\ÙUáWéPñYùZY RRW!b)=*ˆTEST12�-‚trys�opening�channels�when�they�are�already�opened*’and�verifies�error.*>*ˆIf�it�passed�these�tests�it�returns�to�the�top�to�set�up�for2*’task�DCO2.�If�this�was�for�task�DCO2,�it�sets�up$*’to�test�both�tasks�simultaneously.7*ˆIF�ALL�TESTS�ARE�SUCCESSFUL,�prints�message�attesting0*’to�that�fact.�If�any�test�fails,�ERROR�message$*’is�printed�and�test�is�terminated.*D********************************************************************‰PAGE*5IOADR0ƒEQU‡$F80000�VM02�base�mem�map�I/O�chan�address5IOADR1ƒEQU‡$FA0000�VM03�base�mem�map�I/O�chan�address7IOADR2ƒEQU‡$FE6000�VME110�base�mem�map�I/O�chan�address7IOADR3ƒEQU‡$F1C000�VME/10�base�mem�map�I/O�chan�address* ‰SECTIONƒ0*TEST…LEA‡STACK(PC),A7‰LEA‡INITIO(PC),A0.‰CLR.W…DUALFG-INITIO(A0)ƒclear�dual�test�flags‰CLR.W…DUALCK-INITIO(A0)**�SET�UP�A.S.Q.*!‰MOVE.L„#31,D0Žstage�command�code-‰LEA‡ASQBLOCK(PC),A0…stage�command�parameters.‰LEA‡TESTIRQ(PC),A1†initializes�addr.�of�async*‰MOVE.L„A1,ASQLA-ASQBLOCK(A0)‚service�rtn.‰TRAP†#1 ‰BNE‡FAULT11*‰MOVE.L„#'DCO1',D0(TNAME„LEA‡INITIO(PC),A0‡SET�UP�TASK�NAME‰MOVE.L„D0,DCOPAR-INITIO(A0)‰MOVE.L„D0,TMSG-INITIO(A0)*!TRYBTHƒLEA‡SMSG24(PC),A1‡space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*‰LEA‡SMSG24(PC),A1†again‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*.‰LEA‡SMSG1(PC),A1ˆoutput�start�of�test�message‰LEA‡EMSG1(PC),A2 ‰BSR‡MSGOUT*‰LEA‡SMSG24(PC),A1‡space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*‰LEA‡INITIO(PC),A0‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)+‰MOVE.W„#CLSLNG,A1ŠINSURE�CHANNEL(S)�CLOSED$‰MOVE.W„A1,CMDL-INITIO(A0)‚TO�START.‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT16*‰PAGE* *…OPEN�THE�CHANNELS�INDIVIDUALLY*5TEST1„LEA‡SMSG2(PC),A1‡output�'open�&�output'�message‰LEA‡EMSG2(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0"‰CLR.W…0(A0)�initialize�parameters‰LEA‡INITIO(PC),A0*‰MOVE.W„#1,ONCMD1-INITIO(A0)�'ON'�bit�mask,‰MOVE.W„#1,OFFCMD1-INITIO(A0)�'OFF'�bit�mask2‰MOVE.W„#1,STATSHF-INITIO(A0)�status�req.�bit�mask;OPNLP„MOVE.W„EVNTCNT(PC),D0†OPEN�CHANNEL�(event�count�holds‰LEA‡INITIO(PC),A0‡channel�#�)+‰MOVE.W„D0,OPNCH-INITIO(A0)�channel�to�open‰LEA‡OPNCMDS(PC),A1,‰MOVE.L„A1,CMDA-INITIO(A0)‚parameters�to�CMR‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*+‰LEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNEL�OPENED‰LEA‡ONCMD(PC),A1,‰MOVE.L„A1,CMDA-INITIO(A0)‚parameters�to�CMR ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*!‰LEA‡OPNLP(PC),A1ˆloop�back�addr.&‰LEA‡TEST1B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*%TEST1BƒLEA‡INITIO(PC),A0‡CHECK�STATUS/‰MOVE.W„STATSHF(PC),D0†move�channel�to�check�to1‰MOVE.W„D0,STAT-INITIO(A0)‚status�parameter�block‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*3‰MOVE.W„STAT(PC),D0‰does�status�check�with�bit�that"‰CMP.W…ONCMD1(PC),D0‡should�be�on? ‰BNE‡FAULT4*#‰LEA‡INITIO(PC),A0‡TURN�OFF�CHANNEL‰LEA‡OFFCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT5*‰LEA‡INITIO(PC),A0‡CHECK�STATUS/‰MOVE.W„STATSHF(PC),D0†move�channel�to�check�to1‰MOVE.W„D0,STAT-INITIO(A0)‚status�parameter�block‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*.‰MOVE.W„STAT(PC),D0‰does�status�check�show�bit#‰BNE‡FAULT4Žstill�on?�if�so,�error.*#‰LEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(> PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST1B(PC),A1‡loop�back�addr.&‰LEA‡TEST1C(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST1CƒLEA‡INITIO(PC),A0>‰ASL.W…ONCMD1-INITIO(A0)ƒshift�'ON'�channel�bit�mask�one�place/‰ASL.W…OFFCMD1-INITIO(A0)‚shift�'OFF'ƒ"…"ƒ"„"„"0‰ASL.W…STATSHF-INITIO(A0)‚shift�status‚"…"ƒ"„"„"‰LEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP*‰PAGE*2*„OUTPUT�TO�CHANNELS�SEQUENTIALLY�UNTIL�ALL�ARE�ON*5TEST2„LEA‡SMSG3(PC),A1‡output�'output�to�all'�message‰LEA‡EMSG3(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0"‰CLR.W…0(A0)�initialize�parameters‰LEA‡INITIO(PC),A06‰MOVE.W„#1,ONCMD1-INITIO(A0)‚bit�mask�for�'ON'�channel9‰MOVE.W„#1,STATSHF-INITIO(A0)�bit�mask�for�status�channel)OPNLP2ƒMOVE.W„EVNTCNT(PC),D0†OPEN�CHANNEL‰LEA‡INITIO(PC),A0‰MOVE.W„D0,OPNCH-INITIO(A0)/‰LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*+‰LEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNEL�OPENED‰LEA‡ONCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡OPNLP2(PC),A1‡loop�back�addr.&‰LEA‡TEST2A(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*1TEST2AƒLEA‡INITIO(PC),A0‡CHECK�STATUS�OF�CHANNELS‰MOVE.W„STATSHF(PC),D0‰MOVE.W„D0,STAT-INITIO(A0)‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*&‰MOVE.W„STAT(PC),D0‰does�status�check?‰CMP.W…STATSHF(PC),D0 ‰BNE‡FAULT4*"‰LEA‡TEST2A(PC),A1‡loop�back�addr.&‰LEA‡TEST2B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST2BƒLEA‡INITIO(PC),A0>‰ASL.W…ONCMD1-INITIO(A0)ƒshift�'ON'�channel�bit�mask�one�place‰ORI‡#$10,CCRŒset�X�bit/‰ROXL.W„STATSHF-INITIO(A0)‚add�statusƒ"…"ƒ"„"„"‰LEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP2*7TEST2CƒLEA‡SMSG39(PC),A1‡output�'turn�off�seq.'�message‰LEA‡EMSG39(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0"‰CLR.W…0(A0)�initialize�parameters‰LEA‡INITIO(PC),A08‰MOVE.W„#1,OFFCMD1-INITIO(A0)‚bit�mask�for�'OFF'�channel9‰MOVE.W„#1,STATSHF-INITIO(A0)�bit�mask�for�status�channel*)OPNLP3ƒLEA‡INITIO(PC),A0‡TURN�OFF�CHANNEL‰LEA‡OFFCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT5*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡OPNLP3(PC),A1‡loop�back�addr.&‰LEA‡TEST2D(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*0TEST2DƒLEA‡INITIO(PC),A0‡CHECK�STATUS�OF�CHANNEL‰MOVE.W„STATSHF(PC),D0‰MOVE.W„D0,STAT-INITIO(A0)‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT3*&‰MOVE.W„STAT(PC),D0‰does�status�check? ‰BNE‡FAULT4*"‰LEA‡TEST2D(PC),A1‡loop�back�addr.&‰LEA‡TEST2E(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST2EƒLEA‡INITIO(PC),A0@‰ASL.W…OFFCMD1-INITIO(A0)‚shift�'OFF'�channel�bit�mask�one�place0‰ASL.W…STATSHF-INITIO(A0)‚shift�status‚"…"ƒ"„"„"‰LEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP3*+TEST2FƒLEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNELS‰LEA‡ONCMDA(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�S> O�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST2F(PC),A1‡loop�back�addr.%‰LEA‡TEST3(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle**%**************************************ƒCLOSE�TEST–*%**************************************-TEST3„LEA‡SMSG4(PC),A1‡output�'close'�message‰LEA‡EMSG4(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*)TEST3AƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST3A(PC),A1‡loop�back�addr.%‰LEA‡TEST4(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*‰PAGE$*„TURN�ON�ALL�OUTPUTS,�THEN�TURN�OFF*9TEST4„LEA‡SMSG5(PC),A1‡output�'turn�on,�turn�off'�message‰LEA‡EMSG5(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15**TEST4AƒLEA‡INITIO(PC),A0‡OPEN�ALL�CHANNELS/‰LEA‡OPNCMD(PC),A1‡point�to�CMR�parameter�block‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*,‰LEA‡INITIO(PC),A0‡OUTPUT�TO�CHANNELS�OPENED‰LEA‡ONCMDA(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT2*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST4A(PC),A1‡loop�back�addr.&‰LEA‡TEST4B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle**TEST4BƒLEA‡INITIO(PC),A0‡TURN�OFF�CHANNELS‰LEA‡OFFCMDA(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT5*#‰LEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST4B(PC),A1‡loop�back�addr.%‰LEA‡TEST5(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*‰PAGE*„PULSE�EACH�OUTPUT�IN�TURN*2TEST5„LEA‡SMSG6(PC),A1‡output�'pulse�each'�message‰LEA‡EMSG6(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰LEA‡EVNTCNT(PC),A0‰CLR.W…0(A0)�initialize�evntcnt)OPNLP4ƒMOVE.W„EVNTCNT(PC),D0†OPEN�CHANNEL/‰LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block+‰MOVE.W„D0,OPNCH-INITIO(A0)�channel�to�open,‰MOVE.W„D0,PLSO1-INITIO(A0)�channel�to�pulse‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡OPNLP4(PC),A1‡loop�back�addr.&‰LEA‡TEST5A(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*)TEST5AƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST5A(PC),A1‡loop�back�addr.&‰LEA‡TEST5B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST5BƒLEA‡EVNTCNT(PC),A0'‰ADD.W…#1,0(A0)Œincrement�event�counter‰MOVE.W„EVNTCNT(PC),D0‰CMPI.W„#8,D0�done? ‰BMI‡OPNLP4*‰PAGE#*„PULSE�FOUR�OUTPUTS�SIMULTANEOUSLY*6TEST6„LEA‡SMSG32(PC),A1†output�'pulse�simult.'�message‰LEA‡EMSG32(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1500,A0Œ1500�MS‰TRAP†#1 ‰BNE‡FAULT15*&TEST6AƒLEA‡INITIO(PC),A0‡OPEN�CHANNELS‰LEA‡OPNCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSTWO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#PLSTLG,CMDL-INITIO(A0)‰MOVE.? L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#500,A0�500�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST6A(PC),A1‡loop�back�addr.&‰LEA‡TEST6B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*TEST6BƒMOVE.L„#21,D0ŽDELAY‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*)TEST6CƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST6C(PC),A1‡loop�back�addr.%‰LEA‡TEST7(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*‰PAGE+*„PULSE�OUTPUT�TWO�AND�GENERATE�QUEUE�EVENT*6TEST7„LEA‡SMSG7(PC),A1‡output�'pulse�output�2'�message‰LEA‡EMSG7(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*1TEST7AƒLEA‡RCVBUF(PC),A0‡ensure�RCVBUF�zeroed�out‰MOVE.L„#0,0(A0)‰MOVE.L„#0,4(A0)‰MOVE.L„#0,8(A0)*‰LEA‡INITIO(PC),A09‰MOVE.W„#0,OPNCNF-INITIO(A0)�set�up�config.�(queue�event)‰MOVE.W„#2,D0�OPEN�CHANNEL�TWO+‰MOVE.W„D0,OPNCH-INITIO(A0)‚channel�to�open,‰MOVE.W„D0,PLSO1-INITIO(A0)‚channel�to�pulse‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*+WAITQ„MOVE.L„#36,D0Žrequest�wait�for�event.$‰TRAP†#1’to�be�issued�by�DCO�driver. ‰BNE‡FAULT13*4‰MOVE.L„RCVBUF(PC),D0‡verify�message�returned�by�ASQ4‰CMP.L…#$0C010002,D0‡$0C01�� ‰BNE‡FAULT6‰MOVE.L„RCVBUF+4(PC),D0‰CMP.L…DCOPAR(PC),D0‡DCO-ID ‰BNE‡FAULT6‰MOVE.L„RCVBUF+8(PC),D0,‰AND.L…#$FFFFFF00,D0‡mask�off�low�order�byte0‰CMP.L…#IOADR0,D0ŠVM02�memory�mapped�I/O�address ‰BEQ.S…TEST710‰CMP.L…#IOADR1,D0ŠVM03�memory�mapped�I/O�address ‰BEQ.S…TEST722‰CMP.L…#IOADR2,D0ŠVME110�memory�mapped�I/O�address ‰BEQ.S…TEST732‰CMP.L…#IOADR3,D0ŠVME/10�memory�mapped�I/O�address ‰BNE‡FAULT6*‰LEA‡SMSG43(PC),A1‰LEA‡EMSG43(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TEST74TEST71ƒLEA‡SMSG40(PC),A1‰LEA‡EMSG40(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TEST74TEST72ƒLEA‡SMSG41(PC),A1‰LEA‡EMSG41(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TEST74TEST73ƒLEA‡SMSG42(PC),A1‰LEA‡EMSG42(PC),A2 ‰BSR‡MSGOUT2TEST74ƒLEA‡SMSG38(PC),A1‡output�'asq�verified'�msg‰LEA‡EMSG38(PC),A2 ‰BSR‡MSGOUT*"‰LEA‡TEST7A(PC),A1‡loop�back�addr.&‰LEA‡TEST7B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*)TEST7BƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST7B(PC),A1‡loop�back�addr.&‰LEA‡TEST7C(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*6TEST7CƒMOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*‰PAGE'*…PULSE�OUTPUT�ONE�AND�GENERATE�WAKE-UP3TEST8„LEA‡SMSG8(PC),A1‡output�'pulse�led�1'�message‰LEA‡EMSG8(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*1TEST8AƒLEA‡INITIO(PC),A0‡point�to�CMR�para.�block5‰MOVE.W„#1,OPNCNF-INITIO(A0)�set�up�config.�(wake-up)‰MOVE.W„#1,D0�OPEN�CHANNEL�ONE+‰MOVE.W„D0,OPNCH-INITIO(A0)‚channel�to�open,‰MOVE.W„D0,PLSO1-INITIO(A0)‚channel�to�pulse‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT10*-WAITW„MOVE.L„#19,D0Žrequest�wait�for�wake-up.$‰TRAP†#1’to�be�issued�by�DCO�driver. ‰BNE‡FAULT130‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�CHANNEL‰MOVE.L„#1000,A0Œ1000�MS‰TRAP†#1 ‰BNE‡FAULT15*"‰LEA‡TEST8A(PC),A1‡loop�back�addr.&‰LEA‡TEST8B(PC),A2‡continue�on�for? ward‰BRA‡FLOP�test�for�toggle*)TEST8BƒLEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*"‰LEA‡TEST8B(PC),A1‡loop�back�addr.&‰LEA‡TEST8C(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*6TEST8CƒLEA‡INITIO(PC),A0‡restore�default�configuration ‰MOVE.W„#$8000,OPNCNF-INITIO(A0)2‰MOVE.W„#0,OPNCH-INITIO(A0)�restore�channel�select1‰MOVE.W„#1,STAT-INITIO(A0)‚restore�status�channel3‰MOVE.W„#1,OFFCMD1-INITIO(A0)‚restore�off�cmd�chan.*‰PAGE#*„TRY�COMMANDS�WITH�CHANNELS�CLOSED7TEST9„LEA‡SMSG9(PC),A1‡output�'try�with�closed'�message‰LEA‡EMSG9(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*1TEST9AƒLEA‡INITIO(PC),A0‡OUTPUT�TO�CLOSED�CHANNEL‰LEA‡ONCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#6,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1)‰MOVE.W„ONCMD(PC),D0ˆread�returned�status(‰CMP.W…#$F2,D0�verify�correct�error�code ‰BNE‡FAULT2 ‰LEA‡SMSG12(PC),A1‡output�ok�msg‰LEA‡EMSG12(PC),A2 ‰BSR‡MSGOUT*#‰LEA‡INITIO(PC),A0‡TURN�OFF�CHANNEL‰LEA‡OFFCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„OFFCMD(PC),D0‡read�returned�status(‰CMP.W…#$F2,D0�verify�correct�error�code ‰BNE‡FAULT5‰LEA‡SMSG14(PC),A1‡off�ok�msg‰LEA‡EMSG14(PC),A2 ‰BSR‡MSGOUT*‰LEA‡INITIO(PC),A0‡CHECK�STATUS‰LEA‡STATCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#6,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1+‰MOVE.W„STATCMD(PC),D0†read�returned�status(‰CMP.W…#$F2,D0�verify�correct�error�code ‰BNE‡FAULT3 ‰LEA‡SMSG16(PC),A1‡status�ok�msg‰LEA‡EMSG16(PC),A2 ‰BSR‡MSGOUT*‰LEA‡INITIO(PC),A0‰LEA‡PLSO(PC),A1‰PULSE�OUTPUT‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#12,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1(‰MOVE.W„PLSO(PC),D0‰read�returned�status(‰CMP.W…#$F6,D0�verify�correct�error�code ‰BNE‡FAULT10*"‰LEA‡TEST9A(PC),A1‡loop�back�addr.&‰LEA‡TEST9B(PC),A2‡continue�on�forward‰BRA‡FLOP�test�for�toggle*%TEST9BƒLEA‡SMSG18(PC),A1‡pulse�ok�msg‰LEA‡EMSG18(PC),A2 ‰BSR‡MSGOUT*‰PAGE*ƒTRY�TO�OPEN�INVALID�CHANNELS6TEST10ƒLEA‡SMSG11(PC),A1‡output�'try�invalid�channels'‰LEA‡EMSG11(PC),A2 ‰BSR‡MSGOUT0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*3TEST10A‚LEA‡INITIO(PC),A0‡TRY�TO�OPEN�ZERO�CHANNELS‰LEA‡OPNCH0(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNCHL,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1%‰MOVE.W„OPNCH0(PC),D0‡read�cmd�status‰CMP.W…#$F7,D0 ‰BNE‡FAULT7*3‰LEA‡INITIO(PC),A0‡TRY�TO�OPEN�MORE�THAN�8�CHANNELS‰LEA‡OPNMOR(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNML,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1%‰MOVE.W„OPNMOR(PC),D0‡read�cmd�status‰CMP.W…#$F7,D0 ‰BNE‡FAULT7*,‰LEA‡INITIO(PC),A0‡TRY�TO�OPEN�CHANNEL�#�>�8‰LEA‡OPNCH9(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNC9L,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1%‰MOVE.W„OPNCH9(PC),D0‡read�cmd�status‰CMP.W…#$F6,D0 ‰BNE‡FAULT7*0‰LEA‡INITIO(PC),A0‡TRY�TO�OPEN�SAME�TWO�CHANNELS‰LEA‡OPNTW(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNTL,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1$‰MOVE.W„OPNTW(PC),D0ˆread�cmd�status‰CMP.W…#$FE,D0 ‰BNE‡FAULT7*#‰LEA‡TEST10A(PC),A1†loop�back�addr.'‰LEA‡TEST10B(PC),A2†continue�on�forward‰BRA‡FLOP�test�for�toggle*6TEST10B‚LEA‡SMSG36(PC),A1‡output�'invalid�channels�ok'‰LEA‡EMSG36(PC),A2 ‰BSR‡MSGOUT*‰PAGE*„TRY�TO�USE�INVALID�COMMANDS*2TEST11ƒLEA‡SMSG25(PC),A1‡output�'try�invalid�cmds'‰LEA‡EMSG25(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*&TEST11A‚LEA‡INITIO(PC),A0‡OPEN�CHANNEL‰MOVE.W„#1,OPNCH-INITIO(A0)‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„@ A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*$‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�0‰LEA‡INVCM0(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM0(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*$‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�6‰LEA‡INVCM6(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM6(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*$‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�7‰LEA‡INVCM7(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM7(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*&‰LEA‡INITIO(PC),A0‡INVALID�COMMAND�>�8‰LEA‡INVCM9(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0) ‰MOVE.W„#4,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1*‰MOVE.W„INVCM9(PC),D0‡read�returned�status‰CMP.W…#$F4,D0 ‰BNE‡FAULT9*#‰LEA‡TEST11A(PC),A1†loop�back�addr.'‰LEA‡TEST11B(PC),A2†continue�on�forward‰BRA‡FLOP�test�for�toggle*-TEST11B‚LEA‡SMSG26(PC),A1‡invalid�cmds�ok�msg‰LEA‡EMSG26(PC),A2 ‰BSR‡MSGOUT*‰PAGE*„TRY�OPEN�AND�ALREADY�OPENED9TEST12ƒLEA‡SMSG20(PC),A1†output�'try�with�opened'�message‰LEA‡EMSG20(PC),A2 ‰BSR‡MSGOUT*0‰MOVE.L„#21,D0ŽDELAY�SO�OPERATOR�CAN�SEE�MESSAGE‰MOVE.L„#1200,A0Œ1200�MS‰TRAP†#1 ‰BNE‡FAULT15*6TEST12A‚LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block(‰MOVE.W„#0,OPNCH-INITIO(A0)�OPEN�CHANNEL‰LEA‡OPNCMDS(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1 ‰BNE‡FAULT1*/‰LEA‡INITIO(PC),A0‡point�to�CMR�parameter�block‰LEA‡OPNCMDS(PC),A1)‰MOVE.L„A1,CMDA-INITIO(A0)‚TRY�OPEN�again‰MOVE.W„#OPNLNGS,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0ŽCMR‰TRAP†#1+‰MOVE.W„OPNCMDS(PC),D0‡read�returned�status‰CMP.W…#$FE,D0 ‰BNE.S…FAULT1*#‰LEA‡INITIO(PC),A0‡CLOSE�CHANNEL(S)‰LEA‡CLSCMD(PC),A1‰MOVE.L„A1,CMDA-INITIO(A0)‰MOVE.W„#CLSLNG,A1‰MOVE.W„A1,CMDL-INITIO(A0)‰MOVE.L„#60,D0‰TRAP†#1 ‰BNE‡FAULT8*#‰LEA‡TEST12A(PC),A1†loop�back�addr.%‰LEA‡TESTC(PC),A2ˆcontinue�on�forward‰BRA‡FLOP�test�for�toggle*1**************************************************„TEST�COMPLETED�*1************************************************* TESTC„LEA‡SMSG24(PC),A1‡space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*1‰LEA‡SMSG23(PC),A1†output�'test�complete'�message‰LEA‡EMSG23(PC),A2 ‰BSR‡MSGOUT*‰LEA‡SMSG24(PC),A1†space�up‰LEA‡EMSG24(PC),A2 ‰BSR‡MSGOUT*#NEXT…MOVE.W„DUALFG(PC),D0‡flag�set? ‰BNE‡TERM.NEXTA„MOVE.L„DCOPAR(PC),D0‡try�for�second�task‰CMP.L…#'DCO1',D0‰BNE‡TERMA�done‰MOVE.L„#'DCO2',D0‰BRA‡TNAME�set�up�second�task*‰PAGE*#FAULT1ƒLEA‡SMSG22(PC),A1‡open�error‰LEA‡EMSG22(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM%FAULT2ƒLEA‡SMSG13(PC),A1‡output�error‰LEA‡EMSG13(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM%FAULT3ƒLEA‡SMSG17(PC),A1‡status�error‰LEA‡EMSG17(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM+FAULT4ƒLEA‡SMSG28(PC),A1‡status�check�error‰LEA‡EMSG28(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM"FAULT5ƒLEA‡SMSG15(PC),A1‡off�error‰LEA‡EMSG15(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM*FAULT6ƒLEA‡SMSG10(PC),A1‡ASQ�message�error‰LEA‡EMSG10(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM.FAULT7ƒLEA‡SMSG21(PC),A1‡invalid�channel�error‰LEA‡EMSG21(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM$FAULT8ƒLEA‡SMSG33(PC),A1‡close�error‰LEA‡EMSG33(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM.FAULT9ƒLEA‡SMSG27(PC),A1‡invalid�cmd�error�msg‰LEA‡EMSG27(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM%FAULT10‚LEA‡SMSG19(PC),A1‡pulse�error‰LEA‡EMSG19(PC),A2 ‰BSR‡MSGOUT ‰BRA‡TERM#FAULT11‚LEA‡SMSG30(PC),A1‡ASQ�error‰LEA‡EMSG30(PC),A2 ‰BSR‡MSGOUT ‰BRA.S…TERM#FAULT12‚LEA‡SMSG29(PC),A1‡ASQ�error‰LEA‡EMSG29(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM6FAULT13‚LEA‡SMSG31(PC),A1‡WAKE-UP�or�QUEUE�EVENT�error‰LEA‡EMSG31(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM2FAULT14‚LEA‡SMSG34(PC),A1‡IOS�(trap�#2)�call�error‰LEA‡EMSG34(PC),A2 ‰B@ SR.S…MSGOUT ‰BRA.S…TERM*FAULT15‚LEA‡SMSG35(PC),A1‡call�delay�error‰LEA‡EMSG35(PC),A2 ‰BSR.S…MSGOUT ‰BRA.S…TERM/FAULT16‚LEA‡SMSG37(PC),A1‡non-existant�task�msg‰LEA‡EMSG37(PC),A2 ‰BSR.S…MSGOUT(‰LEA‡DUALFG(PC),A0‡set�flag�to�eliminate‰ADD.W…#1,(A0)�dual�test ‰BRA‡NEXTA**„DE-ACTIVATE�SELF*0TERMA„LEA‡INITIO(PC),A0‡test�for�dual�board�test‰TST.W…DUALFG-INITIO(A0) ‰BNE.S…TERM4‰MOVE.W„#1,DUALFG-INITIO(A0)‚set�up�for�dual�bd�test‰MOVE.W„#1,DUALCK-INITIO(A0)!‰MOVE.L„#'DCO1',DCOPAR-INITIO(A0)*‰MOVE.L„#'DCO1',TMSG-INITIO(A0)‚set�up�msg‰MOVE.W„#'&2',TMSG+4-INITIO(A0) ‰BRA‡TRYBTH*%TERM…MOVE.L„#32,D0ŽDE-ALLOCATE�A.S.Q.‰TRAP†#1**‰MOVE.L„#15,D0ŽNOW�DE-ACTIVATE�SELF�(EXIT)‰TRAP†#1**„MESSAGE�OUTPUT�SUBROUTINE*/MSGOUTƒLEA‡MSG(PC),A0Šoutput�message�pointed�to(‰MOVE.L„A1,X1-MSG(A0)‡by�A1,�ended�by�A2‰MOVE.L„A2,X2-MSG(A0)‰TRAP†#2 ‰BNE‡FAULT14‰RTS*1FLOP…LEA‡INITIO(PC),A0‡toggle�between�DCO1�&�DCO2‰MOVE.W„DUALCK-INITIO(A0),D0 ‰BEQ.S…FLOP2�continue�on�if�zero‰CMP.W…#1,D0�see�if�=�1 ‰BNE.S…FLOP11‰MOVE.W„#2,DUALCK-INITIO(A0)‚is�=�1,�set�up�for�2!‰MOVE.L„#'DCO2',DCOPAR-INITIO(A0)‰JMP‡(A1)�loop�back6FLOP1„MOVE.W„#1,DUALCK-INITIO(A0)‚is�=�2,�set�up�for�1!‰MOVE.L„#'DCO1',DCOPAR-INITIO(A0))FLOP2„JMP‡(A2)�continue�on�with�next�test*-*ƒMOVE�THE�ASQ�MESSAGE�FROM�THE�ASQ�TO�RCVBUF*8TESTIRQ‚EQU‡*‰entry�point�moving�data�from�ASQ�to�RCVBUF!‰MOVE.L„#34,D0„stage�command�code‰LEA‡RCVBUF(PC),A0‰TRAP†#1 ‰BNE‡FAULT12*„RETURN�FROM�EVENT!‰MOVE.L„#37,D0„stage�command�code ‰MOVE.W„#1,A0‰TRAP†#1*‰PAGE**„CMR�parameter�block*INITIOƒDC.B†7,0,0,0DCOPARƒDC.L†'DCO1'„TASK�NAME ‰DC.L†0,0,0*CMDA…DC.L†0‰address�of�DCO�parameter�blockCMDL…DC.W†0‰command�length**„A.S.Q.�parameter�block*ASQBLOCK�EQU‡*‰DC.L†0‰task�name‰DC.L†0‰dummy�field*‰DC.B†5‰ASQ�&�ASR�enabled�=�initial�status"‰DC.B†16ˆlength�of�message�for�ASQ‰DC.L†16ˆstorage�for�4�events?ASQLA„DC.L†TESTIRQƒlogical�address�of�target�task�async�svc�rtn‰DC.L†0‰dummy�fieldASQLNGƒEQU‡*-ASQBLOCK*0*„DCO�parameter�block�to�open�individual�channel*OPNCMDS‚DC.W†0‰returned�status‰DC.W†1‰OPEN�command�code‰DC.W†1‰open�1�channelOPNCH„DC.W†0‰channel�#/OPNCNFƒDC.W†$8000…Default�channel�configurationOPNLNGS‚EQU‡*-OPNCMDS�length***„DCO�parameter�block�to�open�ALL�channels*OPNCMDƒDC.W†0‰returned�status‰DC.W†1‰OPEN�command�code‰DC.W†8‰open�8�channels*‰DC.W†0,$8000ƒCHAN�0,default�configuration‰DC.W†1,$8000ƒCHAN�1,ƒ"‰"‰DC.W†2,$8000ƒCHAN�2,ƒ"‰"‰DC.W†3,$8000ƒCHAN�3,ƒ"‰"‰DC.W†4,$8000ƒCHAN�4,ƒ"‰"‰DC.W†5,$8000ƒCHAN�5,ƒ"‰"‰DC.W†6,$8000ƒCHAN�6,ƒ"‰"‰DC.W†7,$8000ƒCHAN�7,ƒ"‰"OPNLNGƒEQU‡*-OPNCMD‚length*#*ƒparameter�block�for�CLOSE�command*CLSCMDƒDC.W†0‰returned�status‰DC.W†2‰CLOSE�command(CLSLNGƒEQU‡*-CLSCMD‚close�command�length*$*…DCO�parameter�block�for�ON�command* ONCMD„EQU‡*‰DC.W†0‰returned�command�status‰DC.W†3‰OUTPUT�ON�command,ONCMD1ƒDC.W†1‰bit�mask�of�channel�to�turn�ON* ONCMDAƒEQU‡*‰DC.W†0‰returned�command�status‰DC.W†3‰OUTPUT�ON�command,‰DC.W†$00FF…bit�mask�to�turn�ON�all�channels*%*…DCO�parameter�block�for�OFF�command* OFFCMDƒEQU‡*&‰DC.W†0‰return�command�status�location‰DC.W†4‰OFF�command.OFFCMD1‚DC.W†1‰bit�mask�of�channel�to�turn�OFF* OFFCMDA‚EQU‡*&‰DC.W†0‰return�command�status�location‰DC.W†4‰OFF�command-‰DC.W†$00FF…bit�mask�to�turn�OFF�all�channels*$*„parameter�block�for�STATUS�command* STATCMD‚EQU‡*‰DC.W†0‰returned�command�status‰DC.W†5‰STATUS�command2STAT…DC.W†1‰bit�mask�&�read�status�of�channels�0-7*:*„DCO�parameter�block�to�do�1000�ms�PULSE�on�selected�chan*PLSO…DC.W†0‰returned�cmd�status‰DC.W†8‰PULSE�command�code‰DC.W†1‰one�channelPLSO1„DC.W†1‰pulse�channel�#‰DC.L†500‡500�ms�pulse*7*„parameter�block�to�PULSE�four�channels�simultaneously*!PLSTWOƒDC.W†0‰returned�cmd�status‰DC.W†8‰PULSE�command�code‰DC.W†4‰four�channels‰DC.W†4‰chan.�#�4‰DC.L†250‡25A 0�ms‰DC.W†5‰chan.�#�5‰DC.L†500‡500�ms‰DC.W†6‰chan.�#�6‰DC.L†750‡750�ms‰DC.W†7‰chan.�#�7‰DC.L†1000†1000�msPLSTLGƒEQU‡*-PLSTWO*"*„INVALID�CHANNEL�parameter�blocks*!OPNCH0ƒDC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�command�code‰DC.W†0‰open�zero�channels‰DC.W†0‰channel�0‰DC.W†$8000…config.OPNCHLƒEQU‡*-OPNCH0*!OPNCH9ƒDC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�cmd�code‰DC.W†1‰open�one�channel‰DC.W†9‰open�channel�#�9‰DC.W†$8000…config.OPNC9LƒEQU‡*-OPNCH9* OPNTW„DC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�cmd�code‰DC.W†3‰open�three�chan.‰DC.W†1,$8000ƒchan,�config.‰DC.W†2,$8000ƒchan,�config.‰DC.W†2,$8000ƒchan,�config.OPNTL„EQU‡*-OPNTW*!OPNMORƒDC.W†0‰returned�cmd�status‰DC.W†1‰OPEN�cmd�code‰DC.W†9‰open�9�channels‰DC.W†0,$8000ƒchan,�config.‰DC.W†1,$8000ƒchan,�config.‰DC.W†2,$8000ƒchan,�config.‰DC.W†3,$8000ƒchan,�config.‰DC.W†4,$8000ƒchan,�config.‰DC.W†5,$8000ƒchan,�config.‰DC.W†6,$8000ƒchan,�config.‰DC.W†7,$8000ƒchan,�config.‰DC.W†8,$8000ƒchan,�config.OPNML„EQU‡*-OPNMOR*#*…INVALID�COMMANDS�parameter�blocks*!INVCM0ƒDC.W†0‰returned�cmd�status‰DC.W†0‰invalid�command�0*!INVCM6ƒDC.W†0‰returned�cmd�status‰DC.W†6‰invalid�command�6*!INVCM7ƒDC.W†0‰returned�cmd�status‰DC.W†7‰invalid�command�7*!INVCM9ƒDC.W†0‰returned�cmd�status"‰DC.W†9‰invalid�cmd�greater�than�8**„IOS�MESSAGE�parameter�block*MSG†DC.B†0‰Data�xfer�code=0‰DC.B†2‰Write�data‰DC.W†0‰Options�-�none‰DC.B†0‰Status ‰DC.B†6‰LUN‰DC.W†0‰reserved‰DC.L†0‰random�record�countX1‡DC.L†0‰bfr�start�addr.X2‡DC.L†0‰bfr�end�addr.‰DC.L†0‰length�of�data�xfer ‰DC.L†0‰completion/service�addr.*‰PAGE *„MESSAGES*6SMSG1„DC.W†'**********�DC�OUTPUT�TEST�PROGRAM�******�'TMSG…DC.W†'DCO1‚' EMSG1„EQU‡*-1*8SMSG2„DC.W†'‚OPEN�&�OUTPUT�TO�EACH�CHANNEL�INDIVIDUALLY' EMSG2„EQU‡*-1*9SMSG3„DC.W†'‚OPEN�&�OUTPUT�EACH�CHANNEL�UNTIL�ALL�ARE�ON' EMSG3„EQU‡*-1*5SMSG4„DC.W†'‚CLOSE�CHANNELS,�OUTPUTS�SHOULD�TURN�OFF' EMSG4„EQU‡*-1*0SMSG5„DC.W†'‚TURN�ON�ALL�OUTPUTS,�THEN�TURN�OFF' EMSG5„EQU‡*-1*'SMSG6„DC.W†'‚PULSE�EACH�OUTPUT�IN�TURN' EMSG6„EQU‡*-1*5SMSG7„DC.W†'‚PULSE�OUTPUT�2�AND�GENERATE�QUEUE�EVENT' EMSG7„EQU‡*-1*1SMSG8„DC.W†'‚PULSE�OUTPUT�1�AND�GENERATE�WAKE-UP' EMSG8„EQU‡*-1*/SMSG9„DC.W†'‚TRY�COMMANDS�WITH�CHANNELS�CLOSED' EMSG9„EQU‡*-1**SMSG10ƒDC.W†'‚INVALID�ASQ�MESSAGE�-�ERROR'EMSG10ƒEQU‡*-1*+SMSG11ƒDC.W†'‚TRY�TO�OPEN�INVALID�CHANNELS'EMSG11ƒEQU‡*-1*4SMSG12ƒDC.W†'‚CALL�OUTPUT�AND�CHANNELS�CLOSED�-�OK!'EMSG12ƒEQU‡*-1*"SMSG13ƒDC.W†'‚CALL�OUTPUT�-�ERROR'EMSG13ƒEQU‡*-1*1SMSG14ƒDC.W†'‚CALL‚OFFƒAND�CHANNELS�CLOSED�-�OK!'EMSG14ƒEQU‡*-1*SMSG15ƒDC.W†'‚CALL�OFF�-�ERROR'EMSG15ƒEQU‡*-1*4SMSG16ƒDC.W†'‚CALL�STATUS�AND�CHANNELS�CLOSED�-�OK!'EMSG16ƒEQU‡*-1*"SMSG17ƒDC.W†'‚CALL�STATUS�-�ERROR'EMSG17ƒEQU‡*-1*3SMSG18ƒDC.W†'‚CALL�PULSE‚AND�CHANNELS�CLOSED�-�OK!'EMSG18ƒEQU‡*-1*!SMSG19ƒDC.W†'‚CALL�PULSE�-�ERROR'EMSG19ƒEQU‡*-1*4SMSG20ƒDC.W†'‚TRY�CALL�OPEN�AND�ALREADY�OPENED�-OK!'EMSG20ƒEQU‡*-1*&SMSG21ƒDC.W†'‚INVALID�CHANNEL�-�ERROR'EMSG21ƒEQU‡*-1* SMSG22ƒDC.W†'‚CALL�OPEN�-�ERROR'EMSG22ƒEQU‡*-1*9SMSG23ƒDC.W†'‚******�TEST�COMPLETED�SUCCESSFULLY�*******'EMSG23ƒEQU‡*-1*SMSG24ƒDC.W†'‚'EMSG24ƒEQU‡*-1**SMSG25ƒDC.W†'‚TRY�TO�USE�INVALID�COMMANDS'EMSG25ƒEQU‡*-1**SMSG26ƒDC.W†'‚CALL„INVALID„COMMANDS„-‚OK!'EMSG26ƒEQU‡*-1*&SMSG27ƒDC.W†'‚INVALID�COMMAND�-�ERROR'EMSG27ƒEQU‡*-1*#SMSG28ƒDC.W†'‚STATUS�CHECK�-�ERROR'EMSG28ƒEQU‡*-1*"SMSG29ƒDC.W†'‚A.S.Q.�MOVE‚-�ERROR'EMSG29ƒEQU‡*-1*SMSG30ƒDC.W†'‚A.S.Q.�-�ERROR'EMSG30ƒEQU‡*-1*$SMSG31ƒDC.W†'‚WAKEUP�OR�QUEUE�ERROR'EMSG31ƒEQU‡*-1*9SMSG32ƒDC.W†'‚PULSE�CHANNELS�4,�5,�6,�&�7�SIMULTANEOUSLY'EMSG32ƒEQU‡*-1*!SMSG33ƒDC.W†'‚CALL�CLOSE�-�ERROR'EMSG33ƒEQU‡*-1*#SMSG34ƒDC.W†'‚TRAP�#�2�(IOS)�ERROR'EMSG34ƒEQU‡*-1*!SMSG35ƒDC.W†'‚CALL�DELAY�-�ERROR'EMSG35ƒEQU‡*-1**SMSG36ƒDC.W†'‚CALL„INVALID„CHANNELA S„-‚OK!'EMSG36ƒEQU‡*-1*‰PAGE*:SMSG37ƒDC.W†'-�-�-�NON-EXISTANT�TASK/BOARD�-�-�-�-�-�-�-^'EMSG37ƒEQU‡*-1*&SMSG38ƒDC.W†'‚A.S.Q.�MESSAGE�VERIFIED'EMSG38ƒEQU‡*-1*-SMSG39ƒDC.W†'‚TURN�OFF�CHANNELS�SEQUENTIALLY'EMSG39ƒEQU‡*-1*SMSG40ƒDC.W†'‚VM02'EMSG40ƒEQU‡*-1*SMSG41ƒDC.W†'‚VM03'EMSG41ƒEQU‡*-1*SMSG42ƒDC.W†'‚VME110'EMSG42ƒEQU‡*-1*SMSG43ƒDC.W†'‚VME/10'EMSG43ƒEQU‡*-1*‰PAGE*EVNTCNT‚DS.W†1‰event�counter!STATSHF‚DS.W†1‰status�bit�shifter1DUALFGƒDS.W†1‰dual�board�test�flag(1=do�not�test)500ƒFORMAT�('�OPEN�&�OUTPUT�TO�EACH�CHANNEL�UNTIL�ALL�ARE�ON')C †DO�600�I=1,8 †OPN(3)�=�1 †OPN(4)�=�I-1†OPN(5)�=�IHEX(10)†CALL�DCOPEN�(ID,OPN)1q:cB(†OUT(3)�=�IHEX(I)†CALL�DCOOUT�(ID,OUT)C †CALL�DELAYC†STATUS(3)�=�MSK(I)†CALL�DCOSTA�(ID,STATUS)"†IF�(STATUS(3)-MSK(I))�550,600,550550ƒCALL�ERRPR1�(I-1) 600ƒCONTINUEC†WRITE�(6,620)7620ƒFORMAT�('�CLOSE�CHANNELS,�OUTPUTS�SHOULD�TURN�OFF') †CALL�DELAY†CALL�DCOCLS�(ID,CLSE) †CALL�DELAYC†WRITE�(6,750)2750ƒFORMAT�('�TURN�ON�ALL�OUTPUTS,�THEN�TURN�OFF')C †OPN(3)�=�8†K=0†DO�800�I�=�4,18,2 †OPN(I)�=�K†OPN(I+1)�=�IHEX(10)†K�=�K+1 800ƒCONTINUE†CALL�DCOPEN(ID,OPN)†OUT(3)�=�IHEX(9)†CALL�DCOOUT�(ID,OUT)C †CALL�DELAY†OFF(3)�=�IHEX(9)†CALL�DCOOFF(ID,OFF)†CALL�DCOCLS�(ID,CLSE)C†WRITE�(6,950))950ƒFORMAT�('�PULSE�EACH�OUTPUT�IN�TURN')C†DO�1000�I�=�1,8 †OPN(3)�=�1 †OPN(4)�=�I-1†OPN(5)�=�IHEX(10)†CALL�DCOPEN�(ID,OPN) †PULSE(3)�=�1†PULSE(4)�=�I-1 †PULSE(5)�=�0†PULSE(6)�=�500†CALL�DCOPLS�(ID,PULSE)C †CALL�DELAY †CALL�DELAY 1000‚CONTINUE†CALL�DCOCLS(ID,CLSE)C†WRITE�(6,1030)11030‚FORMAT('�TRY�COMMANDS�WITH�CHANNELS�CLOSED')C†CALL�DCOCLS(ID,CLSE)†IF�(CLSE(1))�1090,1070,10901070‚WRITE�(6,1080)31080‚FORMAT�('�CALL�CLOSE�AND�CHANNELS�CLOSED--OK') †GO�TO�10951090‚WRITE�(6,1093)#1093‚FORMAT�('�CALL�CLOSE�-�ERROR')C1095‚OUT(3)�=�1†CALL�DCOOUT(ID,OUT)†IF�(OUT(1))�1040,1060,10401040‚WRITE�(6,1050)01050‚FORMAT('�CALL‚OUT‚AND�CHANNELS�CLOSED--OK') †GO�TO�10651060‚WRITE�(6,1063)!1063‚FORMAT�('�CALL�OUT�-�ERROR')C1065‚OFF(3)�=�1†CALL�DCOOFF(ID,OFF)†IF�(OFF(1))�1100,1120,11001100‚WRITE�(6,1110)11110‚FORMAT�('�CALL‚OFF‚AND�CHANNELS�CLOSED--OK') †GO�TO�11251120‚WRITE�(6,1123)!1123‚FORMAT�('�CALL�OFF�-�ERROR')C1125‚STATUS(3)�=1†CALL�DCOSTA(ID,STATUS)†IF�(STATUS(1))�1130,1150,11301130‚WRITE�(6,1140)21140‚FORMAT('�CALL�STATUS�AND�CHANNELS�CLOSED-OK') †GO�TO�11551150‚WRITE�(6,1153)$1153‚FORMAT�('�CALL�STATUS�-�ERROR')C1155‚PULSE(3)�=�1 †PULSE(4)�=�1 †PULSE(5)�=�0†PULSE(6)�=�10†CALL�DCOPLS(ID,PULSE)†IF�(PULSE(1))�1160,1180,11601160‚WRITE�(6,1170)21170‚FORMAT('�CALL�PULSE�AND�CHANNELS�CLOSED--OK') †GO�TO�11851180‚WRITE�(6,1183)#1183‚FORMAT�('�CALL�PULSE�-�ERROR')C1185‚OPN(3)�=�1 †OPN(4)�=�1†OPN(5)�=�IHEX(10)†CALL�DCOPEN(ID,OPN)C†WRITE�(6,1190)01190‚FORMAT('�TRY�CALL�OPEN�AND�ALREADY�OPENED')C †OPN(3)�=�1 †OPN(4)�=�1†OPN(5)�=�IHEX(10)†CALL�DCOPEN(ID,OPN)†IF�(OPN(1))�1200,1220,12001200‚WRITE�(6,1210)21210‚FORMAT('�CALL�OPEN�AND�CHANNELS�ARE�OPEN-OK') †GO�TO�12251220‚WRITE�(6,1222)"1222‚FORMAT�('�CALL�OPEN�-�ERROR')C1225‚WRITE�(6,60)C†WRITE�(6,1300)31300‚FORMAT�('*********�TEST�COMPLETED�**********')C †WRITE�(6,60)CCˆSEE�IF�SECOND�BOARD�TO�TESTC#1350‚IF�(ID�.EQ.�'DCO2')�GO�TO�15001400‚ID�=�'DCO2'†GO�TO�5C 1500‚STOP†ENDééB ééC:C ********************************************************C†SUBROUTINE�DELAY C–DELAY�APPROXIMATELY�ONE�SECOND†DO�30�J�=�1,100†DO�20�K�=�1,350 20„CONTINUE 30„CONTINUE†RETURN†ENDéééééééJ C:C ********************************************************C†SUBROUTINE�ERRPR1(I)†WRITE�(6,10)�I#10„FORMAT�('�STATUS�ERROR-BIT�',I1)†RETURN†ENDééééC éééS=/*=/*†M625DRV.TEST625.AF=/*,=/*†TEST625�test�program�assembly�chain�file=/*6=/*†The�command�line�will�accept�arguments�as�follows:=/*;=/*‹Argument�01…\1�=�Output�file�assembly�listing�or�device=/*H=/*†The�following�shows�the�assembly�chain�sequence.‚In�this�example�theH=/*†NULL�device�was�chosen�as�Argument�01,�however,�the�user�could�if�he5=/*†so�desired�have�requested�an�output�listing�file.=/*#=/*�=CHAIN�M625DRV.TEST625.AF�#NULL=/*-=/*†Default�argument�01�is�M625DRV.TEST625.LS=/*=/IFC \1ƒ=ARG�M625DRV.TEST625.LS=/ENDIF=/*4=ASM M625DRV.TEST625.SA,M625DRV.TEST625.RO,\1;RZ=100=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDééééé\=/*=/*†M625DRV.TESTDC.AF=/*;=/* Chain file to assemble DCO driver test routine 'TESTDC'=/*:=/* If no output argument is specified for the listing the0=/* chain file will default to M625DRV.TESTDC.LS=/*=/IFC \1ƒ=ARG�M625DRV.TESTDC.LS=/ENDIF=/*2=ASM M625DRV.TESTDC.SA,M625DRV.TESTDC.RO,\1;MRZ=70=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDéC ééééée'RIODRV TESTE SAzzbbTESTRIO SA££WbbTESTE AFüübbTESTRIO AF  bbŠOPT„EQU5*This is TESTE the version that tests wait for event. ŠSECTION�0 PBA‡EQU„*TEST†LEA„PBA(PC),A6ŠLEA„STACK-PBA(A6),A7+ŠCLR.L‚EVENTCNT-PBA(A6)ƒclear�event�counter* *‚GET�A.S.Q.1ŠLEA„ASQBLOCK-PBA(A6),A0�stage�command�parametersŠLEA„TESTIRQ-PBA(A6),A1ŠMOVE.L�A1,ASQBLOCK+14-PBA(A6)!ŠMOVE.L�#31,D0‚stage�command�codeŠTRAPƒ#1 ŠBNE„FAULT2*‚OPEN�THE�CHANNELS 3ŠLEA„INITIO-PBA(A6),A0‚point�to�CMR�parameter�blockŠLEA„OPNCMD-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#OPNLNG,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 ŠBNE„FAULT1**** WAIT EQU **‚REQUEST�WAIT�FOR�EVENTŠMOVE.L�#36,D0ŠTRAPƒ#1 ŠBNE„FAULT3**RUNTEST*‚read�status�of�channel‚10**‚stage�code�for�read�commandŠLEA„STATCMD-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)-ŠMOVE.W�#6,CMDL-PBA(A6)„set�up�command�lengthŠMOVE.L�#60,D0�set�up�CMR�callŠTRAPƒ#1 ŠBNE„FAULT7ŠSPC„2*Pulse channel 7ŠLEA„PLS7-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#12,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 ŠBNE„FAULT10ŠSPC�2*Pulse channel 8ŠLEA„PLS8-PBA(A6),A1éD éér7{Fƒ ‹M“FŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#12,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 ŠBNE„FAULT11*Pulse channel 9ŠLEA„PLS9-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#12,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 ŠBNE„FAULT12* *Inc EVENTCNTŠADD.L‚#1,EVENTCNT-PBA(A6)**If EVENTCNT = 10 THENŠCMP.L‚#10,EVENTCNT-PBA(A6) ŠBEQ.S‚TEST1*DO*‚disable�channel�1�interupts*‚wait�for�event*END*IF EVENTCNT >= 20 THENŠCMP.L‚#20,EVENTCNT-PBA(A6) ŠBGE.S‚TEST2*DO*‚EVENTCNT�=�0*‚enable�channel�1�interrupts*‚wait�for�event*END*ELSE*DO ŠBRA.S‚TEST3#*‚toggle�output�on�sucessive�events*END** TEST1…EQU„*!*Stage code for disable channel 1ŠLEA„INITIO-PBA(A6),A0ŠLEA„DSA1-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#6,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 ŠBNE„FAULT8 ŠBRA„WAIT* TEST2…EQU„*ŠCLR.L‚EVENTCNT"* Stage code for enable interruptsŠLEA„INITIO-PBA(A6),A0ŠLEA„ENA1-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#6,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 ŠBNE.S‚FAULT9 ŠBRA„WAIT* TEST3…EQU„*-*toggle EVENTCNT & output on sucessive eventsBŠBTSTƒ#0,EVENTCNT+3-PBA(A6)�Micky�Mouse�way�to�test�LS�byte�in�mem ŠBNE.S‚LAMPON*Stage code for OFF-ŠLEA„INITIO-PBA(A6),A0‚point�to�command�tableŠLEA„OFFCMD-PBA(A6),A1;ŠMOVE.L�A1,CMDA-PBA(A6)„pass�address�of�RIO�parameter�block+ŠMOVE.W�#6,CMDL-PBA(A6)„pass�command�lengthéé)ŠMOVE.L�#60,D0�set�up�trap�1�service�codeŠTRAPƒ#1‘call�for�service"ŠBNE.S‚FAULT6�branch�on�trap�error ŠBRA„WAITŠSPC„3#LAMPON�EQU�*‚turn�output�(lamp)�on.**Stage code for ON-ŠLEA„INITIO-PBA(A6),A0‚point�to�command�tableŠLEA„ONCMD-PBA(A6),A1;ŠMOVE.L�A1,CMDA-PBA(A6)„pass�address�of�RIO�parameter�blockéééD ééé#ŠMOVE.W�#6,CMDL-PBA(A6)„pass�length/ŠMOVE.L�#60,D0�setup�trap1�service�request�codeŠTRAPƒ#1 ŠBNE.S‚FAULT5ŠBRA„WAIT�wait�for�next�eventŠSPC„8*‚CLOSE�CHANNELSŠLEA„CLSCMD-PBA(A6),A1ŠMOVE.L�A1,CMDA-PBA(A6)ŠMOVE.W�#CLSLNG,CMDL-PBA(A6)ŠMOVE.L�#60,D0ŠTRAPƒ#1 FAULT1„NOP FAULT2„NOP FAULT3„NOP FAULT4„NOP FAULT5„NOP FAULT6„NOP FAULT7„NOP FAULT8„NOP FAULT9„NOP FAULT10ƒNOP FAULT11ƒNOP FAULT12ƒNOP*‚DE-ACTIVATE�SELF ŠMOVE.L�#15,D0ŠTRAPƒ#1ŠSPC„10A*ƒ---ƒ---ƒ---�MOVE�THE�ASQ�MESSAGE�FROM�THE�ASQ�TO�RCVBUF‚---‚---ŠSPC„18TESTIRQƒEQU„*‚entry�point�moving�data�from�ASQ�to�RCVBUFŠLEA„RCVBUF-PBA(A6),A0!ŠMOVE.L�#34,D0„stage�command�codeŠTRAPƒ#1 ŠBNE.S‚FAULT4*‚RETURN�FROM�EVENT ŠMOVE.W�#1,A0!ŠMOVE.L�#37,D0„stage�command�codeŠTRAPƒ#1ŠRTS  ASQBLOCK‚EQU„*ŠDC.Lƒ0‰task�nameŠDC.Lƒ0‰dummy�field1ŠDC.B†5‰initial�status�of�ASQ�=�ASQ�&�ASR�enabled"ŠDC.B†16ˆlength�of�message�for�ASQŠDC.L†64ˆstorage�for�4�events4ŠDC.L†0‰logical�address�of�target�task�async�svc�rtnŠDC.L†0‰dummy�field*%RCVBUFƒDS.L†64ˆdefine�reciever�bufferEVENTCNT�DS.L†1‰event�counter**‚CMR�PARAMETER�BLOCK*INITIO„DC.Bƒ7,0,0,0ŠDC.Lƒ'RI01'†TASK�NAME ŠDC.Lƒ0,0,0*CMDA†DC.Lƒ0‹address�of�RIO�parameter�blockCMDL†DC.Wƒ0‹command�length*&*‚RIO�PARAMETER�BLOCK�to�open�channels*OPNCMD„DC.Wƒ0,1ŠDC.Wƒ9‘open�9�channels1ŠDC.Wƒ0,$7F00‹CHAN�0�IRQ�on�fall,�512�ms�debounce1ŠDC.Wƒ1,$3F04‹CHAN�1�IRQ�on�fall,�255�ms�debounce)ŠDC.Wƒ2,4�CHAN�2�interrupt�on�rising�edge*ŠDC.Wƒ3,0�CHAN�3�interrupt�on�falling�edge&*¢CHAN�4ˆ{{‚CH�4�IS�NO�GOOD�ON�HARDWAR0ŠDC.Wƒ5,1�CHAN�5�output�{{�hardware�checked�ok}}ŠDC.Wƒ7,1�CHAN�7�outputŠDC.Wƒ8,1�CHAN�8�outputŠDC.Wƒ9,1�CHAN�9�outputŠDC.Wƒ10,0�CHAN�10�INPUTéOPNLNG„EQU„*-OPNCMD„lengthCLSCMD„DC.Wƒ0,2‰close�command(CLSLNG„EQU„*-CLSCMD„close�command�length*$*ˆRIO�parameter�block�for�ON�command ONCMD EQU *ŠDC.W…0‰returned�command�statusŠDC.W…3‰OUTPUT�ON�commandŠDC.W…$0020…turn�on�channel�#5‰SPC�5%*ˆRio�parameter�block�for�OFF�command‰SPC�1 OFFCMD EQU *&ŠDC.W…0‰return�command�status�locationŠDC.W…4‰off�commandŠDC.W…$0020…turn�off�channel�5ŠSPC�5 STATCMD EQU *ŠDC.W…0‰returned�command�statusŠDC.W…5‰read�commandŠDC.W…$0400…read�channel�10*:*ƒRIO�parameter�block�for�DISABLE�INTERRUPTS�on�channel�1:* DSA1…EQU�*‰DC.W†0‰returned�status‰DC.W†7‰disable�interrupt�code$‰DC.W†2‰bit�mask�selecting�channel�1**8*‚RIO�parameter�block�for�ENABLE�INTERRUPTS�on�channel�1* ENA1…EQU�*‰DC.W†0‰returned�status‰DC.W†6‰enable�interrupt�code$‰DC.W†2‰bit�mask�selecting�channel�1******†stack‚definition* ŠDS.Bƒ$400 STACK…EQU„**PLS7:2* RIO parameter block to do 200 ms pulse on chan 7‰DC.W†0‰returned�cmd�status‰DC.W†8‰pulse�command�code‰DC.W†1‰one�channels‰DC.W†7‰pulse�channel�7‰DC.L†200ˆ200�ms�pulse‰SPC�2PLS8:1*RIO parameter block to do 300 ms pulse on chan 8‰DC.W†0‰returned�cmd�status‰DC.W†8‰pulse�command�code‰DC.E W†1‰one�channels‰DC.W†8‰pulse�channel�8‰DC.L†300ˆ300�ms�pulsePLS9:1*RIO parameter block to do 550 ms pulse on chan 9‰DC.W†0‰returned�cmd�status‰DC.W†8‰pulse�command�code‰DC.W†1‰one�channels‰DC.W†9‰pulse�channel�9‰DC.L†550‡550�ms�pulse ŠEND�TESTéN*******************************************************************************Ì**Ì**™RIO1…Test�Programž**Ì**Ì*N********************************************************************************2* This program was written to test the RIO driver.**    *‰Modification�HistoryN*-----------------------------------------------------------------------------*�11/02/84‡DUH�Initial�writing   *�1.‚Introduction*D*‰This�program�was�written�to�test�the�RIO�driver.‚This�program�willJ*‚ask�for�the�channel�number.‚It�will�then�put�up�a�menu�for�the�following *‚functions:*…1.‚Turn�an�output�channel�on. *…2.‚Turn�an�output�channel�off.*…3.‚Pulse�an�output�channel.)*…4.‚Read�the�status�of�an�input�channel.:*…5.‚Enable�and�wait�for�an�interrupt�on�an�input�channel.*6*‰This�program�assumes�the�board�is�jumpered�as�shown:*%*„J9‚1,2‚3,4‚7,8…address�offset�$0021=*„The�interrupt�level�for�all�4�interrupts�should�be�on�INT3.*ŠPAGE ,*£ASCVAL,�BHLCVT,�and�CVT2�are�commonly�used**£functions�which�are�modules�in�a�library(*£file�called�UTILIB.RO.‚A�call�to�these'*£functions�are�included�in�this�source)*£program,�which�is�provided�with�an�XREF&*£declaration.‚This�also�requires�that'*£UTILIB.RO�be�available�to�the�linkage$*£editor�during�the�linking�process.!*£See�RIO.LF�for�link�chain�file. -ŠXREFƒASCVAL�Converts�ASCII�to�a�binary�value$*£This�routine�will�convert�an�ASCII,*£character�string�representing�a�decimal�or,*£hexidecimal�value�to�the�equivalent�binary,*£value.‚If�a�dollar�sign�($)�is�encountered&*£hexidecimal�conversion�is�performed;,*£otherwise�decimal�conversion�is�performed.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary'*£value.‚Conversion�terminates�when�the)*£first�invalid�character�is�encountered.'*£ENTRY:‚A0�-�Starting�address�of�ASCII*°character�string�to�convert#*£EXIT�:‚D1�-�Character�that�caused *°termination%*«D2�-�Class�code�of�terminating�char›B¤;¬?´G¼IÄ7ÌOÔCÜWäXìB"*«D3�-�Binary�result�of�conversion*«A0�-�Address�of�the�character *°following�the�terminating�char 8ŠXREFƒBHLCVT�Converts�4-byte�binary�value�to�ASCII�digit)*£This�routine�will�convert�a�long�binary-*£word�value�to�a�hexadecimal�value�expressed)*£as�an�8�character�ASCII�string.‚Leading*£zeros�are�suppressed.,*£ENTRY:‚D0.L�-�Binary�value�to�be�converted(*£EXIT�:‚D2.L�-�Four�high�order�bytes�of*²converted�value *«D3.L�-�Four�low�order�bytes�of*²converted�value 6ŠXREFƒCVT2�Converts�two�ASCII�decimal�digits�to�binary-*£This�routine�will�convert�two�ASCII�decimal(*£digits�to�the�equivalent�binary�value.+*£An�empty�character�string�field�passed�to,*£this�function�in�A0�produces�a�zero�binary**£value.‚Conversion�terminates�when�a�non-*£decimal�digit�is�encountered)*£ENTRY:‚A0�-�Address�of�most�significant*°ASCII�decimal�digit)*£EXIT�:‚D0�-�Binary�result�of�conversion!*«A0�-�Address�of�the�terminating *°character ŠPAGEŠMOVE.L�A0,IOSOUT+16-PBA(A4)�Set�the�ending�address�of�messageŠLEA„IOSOUT(PC),A0ŠTRAPƒ#2ŠENDM ŠPAGE 2ŠOPT„PCS�We�use�a�PCS�option�so�the�assembler�will%*£force�PC�relative�addressing�within(*£SECTION.‚Forces�PC�relative�addressing-*£(whenever�such�an�addressing�mode�is�legal))*£in�an�instruction�which�occurs�within�a'*£relocatable�SECTION�and�references�an,*£operand�in�a�relocatable�SECTION�(need�not**£beF �the�same�SECTION�as�the�instruction).,*£Failure�to�resolve�sucn�a�reference�into�a-*£16-bit�displacement�from�the�PC�will�result)*£in�an�error.‚This�option�may�be�used�to+*£force�position�independent�code;�however,(*£this�option�does�not�force�PC�relative,*£addressing�of�absolute�operands�or�unknown*£forward�references. ŠPAGE N*******************************************************************************Ì**™D�A�T�AƒS�E�C�T�I�O�Nœ**Ì*N****************************************************************************** ŠSECTION�DATA $PBA‡EQU„*’Program�Base�Address�(PBA)%*£This�label�is�used�to�designate�the+*£beginning�of�the�program.‚This�is�used�to'*£make�references�to�other�parts�of�the*£program,�relocatable. 6ŠDS.WƒSTACKLEN‹This�is�the�stack�area�for�the�RIO�test2STACK…EQU„*’program.‚Registers�and�other�important,*£information�will�be�stored�on�the�stack�as)*£the�program�is�executed.‚The�stack�area'*£is�dynamic�and�will�change�during�the *£execution�of�the�test�program. =INPUTBUF‚DS.WƒSTRNGLEN‹This�is�the�storage�area�for�the�input*£strings�that�are�entered. 9STATUS„DS.Lƒ1’This�will�be�the�storage�are�for�the�status,*£code�that�is�returned�from�CMR.‚This�value-*£will�be�displayed�to�show�the�user�what�the*£error�code�was. 6NUMBER„DS.Lƒ2’Save�area�for�the�ASCII�value�of�STATUS.ŠPAGE N*******************************************************************************Ì*!*–P�A�R�A�M�E�T�E�RƒB�L�O�C�K�S—**Ì*N****************************************************************************** ŠNEXTWB”Force�even�boundaryIOSOUTŠDC.Bƒ0’Request�code"ŠDC.BƒWRITEŽFunction�specificationŠDC.Wƒ8’OptionsŠDC.Bƒ0’StatusŠDC.BƒCRT�Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address   ŠNEXTWB”Force�even�boundaryIOSINŠDC.Bƒ0’Request�code!ŠDC.BƒREAD�Function�specificationŠDC.Wƒ0’OptionsŠDC.Bƒ0’Status"ŠDC.BƒKEYBOARD‹Logical�unit�numberŠDC.Wƒ0’ReservedŠDC.Lƒ0’Random�record�numberŠDC.Lƒ0’Start�addressŠDC.Lƒ0’End�addressŠDC.Lƒ0’Length�of�data�transferŠDC.Lƒ0’Completion�address  CMRBLK„DC.Bƒ7’Initiate�I/OŠDC.BƒUNUSED�UnusedŠDC.WƒUNUSED�UnusedŠDC.Lƒ'RI01'�Channel�nameŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�UnusedŠDC.LƒUNUSED�Unused$ŠDC.Lƒ0’Address�of�I/O�control�block#ŠDC.Lƒ0’Length�of�I/O�control�blockŠPAGE*2*‚OPEN�command�parameter�block�for�the�RIO�driver:+OPEN_RIO‚DC.Wƒ0’Returned�status�from�driverŠDC.WƒOPEN�Open�command�codeŠDC.Wƒ1’#�of�channels�to�open-ŠDC.Wƒ0’Channel�to�open�(Dynamically�changed)-ŠDC.WƒDEFAULTŒChannel�configuration�(Dynamic)6OLEN_RIO‚EQU„*-OPEN_RIO‰Length�of�OPEN�parameter�block*=*‚START�OUTPUT�ON�command�parameter�block�for�the�RIO�driver:)ON_RIO„DC.Wƒ0’Returned�status�from�driverŠDC.WƒON‘ON�command�code2ŠDC.Wƒ0’Bit�mask�for�channels�to�turn�on�(Dynamic)2NLEN_RIO‚EQU„*-ON_RIO‹Length�of�ON�parameter�block*=*‚TURN�OUTPUT�OFF�command�parameter�block�for�the�RIO�driver:*OFF_RIOƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒOFF�Off�command�code3ŠDC.Wƒ0’Bit�mask�for�channels�to�turn�off�(Dynamic)4FLEN_RIO‚EQU„*-OFF_RIOŠLength�of�OFF�parameter�block*;*‚PULSED�OUTPUT�command�parameter�block�for�the�RIO�driver:*PON_RIOƒDC.Wƒ0’Returned�status�from�driverŠDC.WƒPULSEŽPulse�command�codeŠDC.Wƒ1’#�of�channels,ŠDC.Wƒ0’Channel�number�(Dynamically�changed)/ŠDC.Lƒ0’Time�of�pulse�in�milliseconds�(Dynamic)6PLEN_RIO‚EQU„*-PON_RIOŠLength�of�PULSE�parameter�block*?*‚READ�INPUT�STATUS�command�parameter�block�for�the�RIO�driver:+READ_RIO‚DC.Wƒ0’Returned�status�from�driver*ŠDC.WƒREAD_STATUSˆRead�status�command�code.ŠDC.Wƒ0’Bit�mask�for�channels�to�read�and�upon(*§return�holds�the�actual�channel�status=RLEN_RIO‚EQU„*-READ_RIO‰Length�of�READ�STATUS�parameter�block*?*‚ENABLE�INTERRUPTS�command�parameter�block�for�the�RIO�driver:+ENAB_RIO‚DC.Wƒ0’RetuF rned�status�from�driver-ŠDC.WƒENAB_INT‹Enable�interrupts�command�code2ŠDC.Wƒ0’Bit�mask�for�channels�to�enable�interruptsCELEN_RIO‚EQU„*-ENAB_RIO‰Length�of�ENABLE�INTERRUPTS�parameter�block*?*‚ENABLE�INTERRUPTS�command�parameter�block�for�the�RIO�driver:+DISB_RIO‚DC.Wƒ0’Returned�status�from�driver.ŠDC.WƒDISAB_INTŠEnable�interrupts�command�code3ŠDC.Wƒ0’Bit�mask�for�channels�to�disable�interrupts>DLEN_RIO‚EQU„*-DISB_RIO‰Length�of�DISABLE�INTERRUPTS�parameter*3*‚CLOSE�command�parameter�block�for�the�RIO�driver:)CLSBLK„DC.Wƒ0’Returned�status�from�driverŠDC.WƒCLOSEŽClose�command�codeCLOSLENƒEQU„*-CLSBLKŠNEXTWBŠPAGE N*******************************************************************************Ì**œM�E�S�S�A�G�E�S¡**Ì*N****************************************************************************** ŠSECTION�MESSAGES 5HEAD†DC.BƒCR,LF,LF,'RIO�Driver�Test�Program',CR,LF,LF HEADE…EQU„*-1ŠNEXTWB+MESS1…DC.BƒCR,LF,LF,'…0�=�OUTPUT�ON.',CR,LFMESS1E„EQU„*-1ŠNEXTWB#MESS2…DC.Bƒ'…1�=�OUTPUT�OFF.',CR,LFMESS2E„EQU„*-1ŠNEXTWB=MESS3…DC.Bƒ'…2�=�PULSE�AN�OUTPUT�FOR�A�SPECIFIED�TIME.',CR,LFMESS3E„EQU„*-1ŠNEXTWB6MESS4…DC.Bƒ'…3�=�READ�THE�CURRENT�INPUT�STATUS.',CR,LFMESS4E„EQU„*-1ŠNEXTWB0MESS5…DC.Bƒ'…4�=�ENABLE�FOR�AN�INTERRUPT.',CR,LFMESS5E„EQU„*-1ŠNEXTWBMESS6…DC.Bƒ'…5�=�QUIT.',CR,LFMESS6E„EQU„*-1ŠNEXTWB5MESS10„DC.BƒCR,LF,'STATUS�OF�ALL�CHANNELS�(ASCII)�=�'MESS10EƒEQU„*-1ŠNEXTWB2MESS11„DC.Bƒ'…Number�of�the�channel�to�convertˆ>�'MESS11EƒEQU„*-1ŠNEXTWB)MESS12„DC.Bƒ'…Enter�one�of�the�above...�'MESS12EƒEQU„*-1ŠNEXTWB9MESS13„DC.Bƒ'…Time�(in�milliseconds)�for�output�pulse�>�'MESS13EƒEQU„*-1ŠNEXTWB2MESS14„DC.BƒCR,LF,'<<<�Starting�command�>>>',CR,LFMESS14EƒEQU„*-1ŠNEXTWB1MESS15„DC.BƒCR,LF,'<<<�Command�done�>>>',CR,LF,LFMESS15EƒEQU„*-1ŠPAGEŠNEXTWB6BADON…DC.BƒCR,LF,'***�START�OUTPUT�ON�ABORTED�***�--�'BADONE„EQU„*-1ŠNEXTWB7BADOFF„DC.BƒCR,LF,'***�TURN�OUTPUT�OFF�ABORTED�***�--�'BADOFFEƒEQU„*-1ŠNEXTWB:BADPLS„DC.BƒCR,LF,'***�START�OUTPUT�PULSE�ABORTED�***�--�'BADPLSEƒEQU„*-1ŠNEXTWB,BADOPN„DC.BƒCR,LF,'***�OPEN�ABORTED�***�--�'BADOPNEƒEQU„*-1ŠNEXTWB8BADEN…DC.BƒCR,LF,'***�ENABLE�INTERRRUPT�ABORTED�***�--�'BADENE„EQU„*-1ŠNEXTWB:BADDIS„DC.BƒCR,LF,'***�DISABLE�INTERRRUPT�ABORTED�***�--�'BADDISEƒEQU„*-1ŠNEXTWB4BADREADƒDC.BƒCR,LF,'***�READ�STATUS�ABORTED�***�--�'BADREADE‚EQU„*-1ŠNEXTWB-BADCLS„DC.BƒCR,LF,'***�CLOSE�ABORTED�***�--�'BADCLSEƒEQU„*-1ŠNEXTWB+STATUSMƒDC.Bƒ'Error�code�returned�in�D0�=�'STATUSME‚EQU„*-1ŠNEXTWBCRLF†DC.BƒCR,LF CRLFE…EQU„*-1ŠNEXTWBŠPAGE N*******************************************************************************Ì**–P�R�O�G�R�A�MƒS�E�C�T�I�O�N™**Ì*N****************************************************************************** ŠSECTION�CODEPROGSTRTŠLEA„STACK(PC),A7.ŠLEA„PBA(PC),A4‰Get�Program�Base�Address�(PBA) &ŠOUTPUT�HEAD,HEADE‰Display�the�heading N*-----------------------------------------------------------------------------***‰Get�the�number�of�the�channel�to�convert*N*-----------------------------------------------------------------------------GETCHAN0ŠOUTPUT�MESS11,MESS11E…Channel�number�to�convertŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary(ŠIF.L�D0��#0�OR.L�D0��#15�THEN.S ŒBRA�GETCHANŠENDI8ŠMOVE.W�D0,OPEN_RIO+6-PBA(A4)�Save�the�channel�number...ŠMOVE.W�D0,PON_RIO+6-PBA(A4) =ŠLEA„BIT_NUMBER(PC),A0‚Convert�the�channel�number�(0-15)�into7ŠLSL.B‚#1,D0Žthe�corresponding�bit�number�(1,2,4,8...).ŠMOVE.W�(A0,D0.W),D08ŠMOVE.W�D0,READ_RIO+4-PBA(A4)�Save�the�bit�mask�value...ŠMOVE.W�D0,ENAB_RIO+4-PBA(A4)ŠMOVE.W�D0,DISB_RIO+4-PBA(A4)ŠMOVE.W�D0,ON_RIO+4-PBA(A4)ŠMOVE.W�D0,OFF_RIO+4-PBA(A4) N*-----------------------------------------------------------------------------*3*‰Get„0�=�OUTPUT�ON„1�=�OUTPUT�OFFŠ2�=�PULSE�OUTPUT0*�3�=�READ�STATUS‚4�=�ENABLE�INTG ERRUPTSƒ5�=�QUIT*N*-----------------------------------------------------------------------------GETCLST'ŠOUTPUT�MESS1,MESS1E…Put�up�the�menu...ŠOUTPUT�MESS2,MESS2EŠOUTPUT�MESS3,MESS3EŠOUTPUT�MESS4,MESS4EŠOUTPUT�MESS5,MESS5EŠOUTPUT�MESS6,MESS6EHGET_CHOICE‚OUTPUT�MESS12,MESS12EƒAsk�the�user�to�enter�one�of�the�above. +ŠINPUT‚INPUTBUF,INPUTBUF+8�Get�their�choiceŠLEA„INPUTBUF(PC),A0)ŠBSR„CVT2�Convert�ASCII�decimal�to�binary'ŠIF.W�D0��#0�OR.W�D0��#5�THEN.S�BRA.S�GET_CHOICEŠENDIŠPAGE**‰0�=�Start�output�ON�command:*ŠIF.B�D0��#0�THEN.S 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS14,MESS14Eƒ<<<ƒStarting�commandƒ>>> >ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A02ŒLEA„ON_RIO(PC),A1„Start�output�ON�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#NLEN_RIO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�ON_RIO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADON,BADONE…***�START�OUTPUT�ON�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS15,MESS15Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDIŠPAGE**‰1�=�Turn�output�OFF�command:*ŠIF.B�D0��#1�THEN.S 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS14,MESS14Eƒ<<<ƒStarting�commandƒ>>> >ŒMOVE.W�#DEFAULT,D0†Use�the�default�configuration�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A03ŒLEA„OFF_RIO(PC),A1ƒTurn�output�OFF�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#FLEN_RIO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�OFF_RIO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)6ŽOUTPUT�BADOFF,BADOFFE„***�TURN�OUTPUT�OFF�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS15,MESS15Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDIŠPAGE**‰2�=�PULSE�an�output�command:*ŠIF.B�D0��#2�THEN.L3ŒBSR„GET_TIME‰Get�the�pulse�duration�(milliseconds)+ŒMOVE.L�D3,PON_RIO+8-PBA(A4)�Store�the�time 'ŒBSR.L‚CLOSE_ALLˆGo�close�all�channels./ŒOUTPUT�MESS14,MESS14Eƒ<<<ƒStarting�commandƒ>>> 6ŒMOVE.W�#DEFAULT,D0†Use�the�WAKEUP�option�for�the�open$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A06ŒLEA„PON_RIO(PC),A1ƒStart�output�pulse�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#PLEN_RIO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1*7*ƒDRIVER�DOES�NOT�SUPPORT�WAKEUP�AFTER�AN�OUTPUT�PULSE.**‹MOVE.L�#19,D0 *‹TRAPƒ#1 ŒIF��THEN.SŽMOVE.W�PON_RIO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)9ŽOUTPUT�BADPLS,BADPLSEƒ***�START�OUTPUT�PULSE�ABORTED�***ŽBRA.L‚SHOW_D0ŒENDI 3ŒOUTPUT�MESS15,MESS15E…***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDIŠPAGE* *‰3�=�Read�input�status�command:*ŠIF.B�D0��#3�THEN.L /ŒOUTPUT�MESS14,MESS14Eƒ<<<ƒStarting�commandƒ>>> ŒBSR.L‚CLOSE_ALL'ŒMOVE.W�#$000E,D0ˆSet�for�input�channel$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel ŒLEA„CMRBLK(PC),A06ŒLEA„READ_RIO(PC),A1‚Read�input�status�parameter�blockŒMOVE.L�A1,$14(A0)ŒMOVE.W�#RLEN_RIO,$18(A0)ŒMOVE.L�#CMR,D0ŒTRAPƒ#1ŒIF��THEN.SŽMOVE.W�READ_RIO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)4ŽOUTPUT�BADREAD,BADREADEƒ***�READ�STATUS�ABORTED�***ŒENDI ŒCLR.L‚D0<ŒMOVE.W�READ_RIO+4-PBA(A4),D0‚Get�the�status�value�returned.ŒBSR„BHLCVT�Convert�it�to�ASCII9ŒMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŒMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŒOUTPUT�MESS10,MESS10EŒOUTPUT�NUMBER,NUMBER+7ŒOUTPUT�CRLF,CRLFE 3ŒOUTPUT�MESS15,MESS15E…***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDIŠPAGE* *‰4�=�Enable�interrupts�command:*ŠIF.B�D0��#4�THEN.S /ŒOUTPUT�MESS14,MESS14Eƒ<<<ƒStarting�commandƒ>>> ŒBSR.L‚CLOSE_ALL 3ŒMOVE.W�#$7F0C,D0ˆEnable�interrupts,�WAKEUP�option,8*‡software�debounce�=�508mSec,�trigger�on�positive�edge.$ŒBSR.L‚OPEN_CHANˆGo�open�the�channel *(*‚Do�a�wait�until�the�driver�wakes�uG s�up*ŒMOVE.L�#19,D0ŒTRAPƒ#1 ŒIF��THEN.SŽMOVE.W�ENAB_RIO(PC),D0ŽMOVE.L�D0,STATUS-PBA(A4)6ŽOUTPUT�BADEN,BADENE„***�ENABLE�INTERRUPTS�ABORTED�***ŒENDI 3ŒOUTPUT�MESS15,MESS15Eƒ***‚<<<�Command�done�>>>‚***ŒBRA.L�GETCHAN�Go�start�over. ŠENDI    **‰5�=�quit�command:*ŠIF.B�D0��#5�THEN.S �BRA.L�EXITŠENDI ŠBRA.L�GETCHAN�Go�start�over.ŠPAGEM*----------------------------------------------------------------------------*+*‚GET�THE�TIME�DURATION�FOR�AN�OUTPUT�PULSE*M*----------------------------------------------------------------------------GET_TIMEŠOUTPUT�MESS13,MESS13EŠINPUT‚INPUTBUF,INPUTBUF+8ŠLEA„INPUTBUF(PC),A0 ŠBSR„ASCVAL+ŠIF.L�D3��#1�OR.L�D3��#$FFFF�THEN.S ŒBRA„GET_TIMEŠENDIŠAND.L‚#$0000FFFF,D3ŠRTS M*----------------------------------------------------------------------------**ƒOPEN�THE�CHANNEL*M*----------------------------------------------------------------------------OPEN_CHAN�LEA„CMRBLK(PC),A0ŠLEA„OPEN_RIO(PC),A1BŠMOVE.W�D0,OPEN_RIO+8-PBA(A4)‚Save�the�open�configuration�options.ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#OLEN_RIO,$18(A0)7ŠMOVE.L�#CMR,D0ŒHere�we�perform�an�executive�request�toŠTRAPƒ#1‘invoke�CMR.ŠIF��THEN.SŒMOVE.L�D0,STATUS-PBA(A4)+ŒOUTPUT�BADOPN,BADOPNE…***�OPEN�ABORTED�***ŒBRA.S‚SHOW_D0ŠENDIŠRTS M*----------------------------------------------------------------------------**ƒOUTPUT�THE�ERROR�CODE:*M*----------------------------------------------------------------------------:SHOW_D0ƒMOVE.L�STATUS(PC),D0†Get�the�status�value�returnedŠBSR„BHLCVT�Convert�it�to�ASCII9ŠMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŠMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytesŠOUTPUT�STATUSM,STATUSMEŠOUTPUT�NUMBER,NUMBER+7ŠOUTPUT�CRLF,CRLFE EXIT:ŠBSR.S‚CLOSE_ALL +EXIT_OUT:�MOVE.L�#15,D0�Terminate�this�taskŠTRAPƒ#1ŠPAGEN*-----------------------------------------------------------------------------**‚CLOSE�ALL�CHANNEL'S�ROUTINE:*N*----------------------------------------------------------------------------- CLOSE_ALLŠLEA„CMRBLK(PC),A0ŠLEA„CLSBLK(PC),A1ŠMOVE.L�A1,$14(A0)ŠMOVE.W�#CLOSLEN,$18(A0)-ŠMOVE.L�#CMR,D0ŒTell�CMR�to�close�the�channelŠTRAPƒ#1ŠIF��THEN.SŒBSR„BHLCVT�Convert�it�to�ASCII9ŒMOVE.L�D2,NUMBER-PBA(A4)‚Save�the�upper�four�ASCII�bytes;ŒMOVE.L�D3,NUMBER+4-PBA(A4)�Save�the�lower�four�ASCII�bytes,ŒOUTPUT�BADCLS,BADCLSE…***�CLOSE�ABORTED�***ŒOUTPUT�NUMBER,NUMBER+7ŒOUTPUT�CRLF,CRLFE&ŒBRA.S‚EXIT_OUT‰Output�the�error�code.ŠENDI ŠRTS M*----------------------------------------------------------------------------*B*ƒTABLE�TO�CONVERT�THE�CHANNEL�NUMBER�(0-15)�TO�IT'S�CORRESPONDING-*ƒBIT�MAPPED�VALUE�(1,2,4,8,....$4000,$8000).*M*----------------------------------------------------------------------------'BIT_NUMBER‚DC.W‚1,2,4,8,$10,$20,$40,$805ŒDC.W‚$0100,$0200,$0400,$0800,$1000,$2000,$4000,$8000 ŠEND„PROGSTRT=/*=/*†RIODRV.TESTE.AF=/*:=/* Chain file to assemble RIO driver test routine 'TESTE'=/*:=/* If no output argument is specified for the listing the.=/* chain file will default to RIODRV.TESTE.LS=/*=/IFC \1ƒ=ARG�RIODRV.TESTE.LS=/ENDIF=/*)=ASM RIODRV.TESTE.SA,RIODRV.TESTE.RO,\1;R=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDééH ééééô=/*=/*†RIODRV.TESTRIO.AF=/*,=/*†TESTRIO�test�program�assembly�chain�file=/*6=/*†The�command�line�will�accept�arguments�as�follows:=/*;=/*‹Argument�01…\1�=�Output�file�assembly�listing�or�device=/*H=/*†The�following�shows�the�assembly�chain�sequence.‚In�this�example�theH=/*†NULL�device�was�chosen�as�Argument�01,�however,�the�user�could�if�he5=/*†so�desired�have�requested�an�output�listing�file.=/*"=/*�=CHAIN�RIODRV.TESTRIO.AF�#NULL=/*,=/*†Default�argument�01�is�RIODRV.TESTRIO.LS=/*=/IFC \1ƒ=ARG�RIODRV.TESTRIO.LS=/ENDIF=/*2=ASM RIODRV.TESTRIO.SA,RIODRV.TESTRIO.RO,\1;RZ=100=/*{ Included files are:=/*ƒ--�none�--=/*}=/*=ENDéééééý' ACIADRV SA  dobbARTDRV SA { {ÙbbH >ACIADRVƒIDNTƒ4,1‡VERSADOS�ACIA�TERMINAL�DRIVER�WITH�TYPE-AHEAD;ŠTTL„ACIADRV:‚VERSADOS�ACIA�TERMINAL�DRIVER�WITH�TYPE-AHEAD ŠLLENƒ120J**************************************************************************J***************************************************************************9*‰ACIADRV:‚VERSAdos�ACIA�terminal�driver�with�type-ahead.*8*‰Purpose:‚VERSAdos�device�driver�to�handle�asynchronous/*�terminals�(of�any�type)�over�the�ACIA�chip�on*�the�following�boards:*’DEBUG�(EXORmacs),…MVME110**‰Revision�history:*8*�12/17/84‚Interrupt�routine�and�RCA�routine�modified�to1*šprevent�the�EDITOR�from�hanging.‚We�must�detect5*šend-of-break�before�checking�the�received�character4*šfor�bit�7�set�(garbage�character�at�end-of-break).6*�11/21/84‚Modified�the�interrupt�routine.‚The�Special0*šReceive�Condition�routine�is�executed�now�only1*šwhen�there�has�been�a�receive�interrupt�and�SRC2*šbits�are�pending.‚This�will�prevent�the�terminal/*šfrom�hanging�when�BREAK�is�pressed�to�log�on.1*�10/23/84‚All�BSR's�to�TERMLIB�now�JSR's�in�case.*šTERMLIB�is�located�more�than�32K�bytes�away.3*‘9/27/84‚Adding�documentation,�INCLUDE�9995�files,"*šusing�TERM_BREAK�in�SRC�routine.,*‘9/25/84‚Removed�XREF�to�BREAK�and�GET_LEN.5*‘9/21/84‚Changed�PASS19.MPSCDRV.SA�to�drive�an�ACIA.3*‘8/30/84‚Fixed�SPR�concerning�SETUP.‚Commented�out(*šthe�code�that�tests�the�modem�bit.‚Now**šif�the�off�hook�bit�is�set,�the�DTR�line&*šis�set�low,‚whether�or�not�the�modem *šbit�is�set.*9*�05/23/84‚Changed�code�that�referenced�the�baud�rate�PIA1*šon�the�EXORmacs�to�be�executed�conditionally�if/*šthe�channel�type�is�a�$66�or�a�$67.‚This�will(*šallow�the�ACIADRV�to�work�on�a�VME110.1*šChanged�the�code�that�reset�the�ACIA�to�get�the!*švalue�for�reset�out�of�the�CDB.0*šChanged�UNSTOP�routine�to�fix�bug�where�a�char(*šis�destroyed�in�the�USE�XOFF/XON�mode.2*šChanged�GET_STAT�routine�to�test�CTS�bit�instead *šof�DCD�bit.*»KEG�05/23/84 / X ? #F +6 3> ;B CN KG SK [J cH k<7*�08/05/83‚Changed�To�Drive�An�ACIA�instead�of�NEC�7201*šBy�Tom�Angert*7*�10/19/82‚Major�repairs�so�that�interrupts�will�not�be3*šdisabled�so�long�as�to�screw�up�SDLC.‚Revision�1.**‘9/16/82‚Initial�release�by�Steve�Franck.*J**************************************************************************J**************************************************************************‰PAGE****‚XREF's�from�TERMLIB* ‰XREF†LOG_ERR ‰XREF†RESET‰XREF†TERM_INIT‰XREF†TERM_COMMAND‰XREF†TERM_TBE‰XREF†TERM_BREAK‰XREF†TERM_GOT_CHAR%***†XREF†TERM_UNRDYŠNot�used�by�ACIA.$***†XREF†MARK_DOWN‹Not�used�by�ACIA. *?*‚Masks�delineating�all�recognized�(REC)�and�unrecognized�(UNR)(*‚attributes�(ATT)�and�parameters�(PAR).*C*REC_ATTƒEQU„%1000111111111111‚1�bits�represent�defined�attributes.D*UNR_ATTƒEQU„$FFFF-REC_ATT†The�1's�complement�of�that�are�undefined. C*REC_PARƒEQU„%0111111111111111‚1�bits�represent�defined�parameters.D*UNR_PARƒEQU„$FFFF-REC_PAR†The�1's�complement�of�that�are�undefined.***‚Equate�files�included:**‰STR*‰TCB*‰CCB*ˆ9995..BAB.EQ*‰IOE*‰NIO*‰LV5#*‰TERMINAL.EQˆEquates�for�terminals *‰UTILITY.MC:*‰TERMCCB.EQ‰Offsets�and�equates�for�CCBDDP�for�terminals.*ŠPAGE**‚I ACIA�equates:* CREG†EQU„0 SREG†EQU„CREG DREG†EQU„2,RDRFBITƒEQU„0’Receive�data�register�full�bit.TDREBITƒEQU„1’Transmit�data�register�empty�bit$DCDBIT„EQU„2’Data�Carrier�Detect�bitCTSBIT„EQU„3’Clear�To�Send�bit'OVRNBITƒEQU„5’Received�data�overrun�bit**%*‰SPECIAL�EQUATE�FOR�THE�EXORMACS�PIA*0BAUDPIAƒEQU„$FEE001ŒBaud�rate�PIA�device�address(*£Address�of�PIA�on�EXORmacs�Debug�board#*£to�set�the�baud�rate�for�the�ACIA****‡PAGEŠNOLIST ŠTTL…STR.EQŠINCLUDE�9995.&.STR.EQŠNOLISTŠINCLUDE�9995.&.TCB.EQŠNOLISTŠINCLUDE�9995.&.CCB.EQŠNOLISTŠINCLUDE�9995.&.IOE.EQ‰NOLISTŠINCLUDE�9995.&.NIO.EQŠNOLISTŠINCLUDE�9995.&.LV5.EQ‰NOLIST‰INCLUDEƒ9995.&.BAB.EQŠLISTŠINCLUDE�9995.&.TERMINAL.EQ‰PAGEŠINCLUDE�9995.&.UTILITY.MCŠINCLUDE�9995.&.TERMCCB.EQŠLIST‰OFFSET„TERMDDP */*‚Device�dependent�Background�activation�blocks$*‚None�required�for�the�ACIA�driver.**7�RESERVE.1�XINTENAB‘Value�to�put�in�control�register�to*§enable�transmit�interrupts. 7�RESERVE.1�XINTDISA‘Value�to�put�in�control�register�to*§disable�transmit�interrupts. 0�RESERVE.1�XRTSHI“Value�to�make�RTS�line�go�HIGH <�RESERVE.1�GOTBREAK‘Indicates�that�a�break�has�been�recieved*§and�that�all�errors�shall�be%*§ignored�untill�after�the�next�valid *§character *@*ƒCompute�the�number�of�pages�of�memory�that�we�need�for�one�CCB>*ƒfor�the�MPSC�driver.‚CMR�automatically�allocates�one�page�ofA*ƒmemory�($100�bytes)�for�the�CCB,�and�our�variable�EXTCCBSZ�willB*ƒreside�in�the�CMR�parameter�table�at�the�beginning�of�the�driver8*ƒto�tell�CMR�how�many�extra�pages�of�memory�are�needed.**CCBSIZEB�EQU‡*PAGESIZE�EQU‡$100L1‡SET‡CCBSIZEB+PAGESIZE-1CCBSIZE‚EQU‡L1/PAGESIZEEXTCCBSZ�EQU‡CCBSIZE-1;ŠTTL„ACIADRV:‚VERSADOS�ACIA�TERMINAL�DRIVER�WITH�TYPE-AHEADŠPAGEJ***************************************************************************+*‰SERVICE�VECTOR�TABLE,�REVISION�INFO,�ETC.*@*‰This�table�is�examined�by�CMR�when�the�channel�is�allocated�toC*‰determine�where�to�go�for�interrupts,�commands,�&�initialization.<*‰It�must�always�be�at�the�very�top�of�the�driver�code.‚Also>*‰included�is�a�parameter�telling�the�number�of�extra�pages�of>*‰memory�to�include�in�the�CCB,�and�information�describing�the*‰revision�of�the�driver.*L**************************************************************************** ŠSECTION‚0ŠOPT„BRS ACIADRV: *D*‚Service�vector�table.‚Notice�that�these�values�are�relative�to�theC*‚beginning�of�the�driver�so�the�mechanism�is�position-independent!*=ŠDC.LƒINTERRUPT-ACIADRV‚Address�of�interrupt�service�routine.9ŠDC.LƒCOMMAND-ACIADRV„Address�of�command�service�routine.5ŠDC.LƒINIT-ACIADRV‡Address�of�initialization�routine.ŠDC.Lƒ0’Reserved. **‚Other�CMR�parameters.*7ŠDC.BƒEXTCCBSZ‹#�of�extra�pages�in�the�CCB.‚The�CCB�may)*§be�any�size�from�1�to�256�pages�(a�page'*§is�256�bytes):‚if�this�field�is�0,�it*§will�be�1�page,�etc.ŠDC.Bƒ0,0,0ŽReserved.ŠDC.Lƒ0,0,0ŽReserved. **‚Revision�info:*/ŠDC.Bƒ'121784'‹Date�of�last�assembly�as�MMDDYY.1ŠDC.Bƒ'�'�Space�indicates�no�patches�to�.LO�file.)ŠDC.Bƒ'4'�Major�VERSAdos�revision�number.*‰PAGE*+*‚Jump�table�for�use�by�the�generic�TERMLIB*‰BRA.L…PUT_CHAR ‰BRA.L…CK_TBE‰BRA.L…DDP_RESET ‰BRA.L…SETUP‰BRA.L…CLOCK_RESET‰BRA.L…GET_STAT‰BRA.L…DDP_STOP‰BRA.L…DDP_UNSTOP‰BRA.L…DDP_BEG_BREAK‰BRA.L…DDP_END_BREAK **‰PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INITIALIZATION�ROUTINE*>*‰This�routine�is�called�by�CMR�when�the�channel�is�allocated.9*‰Its�purpose�is�to�set�up�things�for�command�service�and7*‰interrupt�service.‚The�major�functions�performed�are:"*�Validate�the�channel�type�field.+*�Get�memory�for�transmit�&�receive�queues..*�Initialize�flags,�pointers,�I etc.�in�the�CCB.*�Initialize�the�ACIA.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.**‰Entry:�A5�=�address�of�CCB.*'*‰Exits�to:‚CMR�(via�RTS)�if�all�is�OK.'*”KILLER�if�exec�won't�allocate�memory.*J**************************************************************************J**************************************************************************J************************************************************************** ŠDS…0 INIT:.‰JSR‡TERM_INIT‹Do�the�device-independent�stuff*%%%%%%%%%%%%%%ƒbwn‚8/13/842‰IFƒƒTHEN…Something�went�wrong�with�TERM_INIT.4‰IFƒƒTHEN„The�exec�call�failed�and�we�cannot�get!*œthe�scheduler's�entry�point�!!!ŽTR0$.KILLER‚,‰ELSE�RTS�The�channel�is�down�!!‰ENDI‰ENDI*?*‚Call�guarded�for�the�device�dependent�initialization�routine.*‰LEA‡DO_INIT(PC),A0‰MOVE.L„#T0GUARD,D0‰TRAP†#0‰RTSŠPAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰COMMAND�SERVICE�ROUTINE*>*‰We�get�entered�here�when�the�attached�task�(IOS)�invokes�CMR?*‰via�a�TRAP�1�with�an�INITIATE�I/O�parameter�block�to�process.>*‰CMR�has�already�checked�the�CMR�parameter�block�to�ensure�it<*‰resides�within�the�address�space�of�the�attached�task.‚IOSA*‰has�already�validated�the�IOCB,�except�for�the�buffer�addresses *‰therein.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.*5*‰Entry:�A2�=�physical�address�of�CMR�parameter�block*�A5�=�physical�address�of�CCB*3*‰Exit:‚D0�=�results�of�parameter�block�validation:3*•always�0�in�our�case,�indicating�it�was�OK,�since2*•IOS�will�not�send�us�any�request�except�HALT�I/O/*•if�we�are�already�busy,�and�CMR�makes�all�the*•other�checks.*A*‰Note:‚TERMLIB�does�not�recognize�CMR�commands�for�HALT�&�RESET.B*‰HALT�can�still�be�accomplished�through�use�of�the�HALT�I/O�IOCB.*J**************************************************************************J**************************************************************************J************************************************************************** COMMAND:‹JSR…TERM_COMMAND‹RTS—return�to�CMR.‹PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INTERRUPT�HANDLING�ROUTINE*<*‰This�routine�completes�I/O�requests�started�by�the�command:*‰service�routine.‚It�is�entered�at�the�interrupt�priority;*‰level�of�interrupts�on�this�channel,�and�is�essentially�a9*‰subroutine�to�the�first�level�interrupt�handler�in�CMR.*:*‰Entry:�D0,A0,A1�have�been�saved�by�CMR�and�are�available*�A5�=�address�of�CCB*9*‰Exit�is�always�via�RTS,�which�takes�us�back�to�CMR.‚The3*�carry�bit�is�examined�by�CMR�to�determine�whether7*�the�driver�handled�the�interrupt�or�whether�it�should4*�pass�the�interrupt�on�to�the�next�guy�in�the�chain*�on�that�vector:*��=�'I�handled�it'**‰Stack:*�(A7)+4�.�.�.*�(A7)ƒlongword�return�address*J**************************************************************************J**************************************************************************J************************************************************************** INTERRUPT:0‰MOVE.L„CCBCHB(A5),A1‡STATUS/CONTROL�REG�ADDRESS$‰MOVE.B„SREG(A1),D0‰GET�COPY�OF�SREG‰IF��THEN.S�IF�NO�INTERRUPT‹AND…#$FFFE,SR‹CLEAR�CARRY‹RTS‰ENDI ‰PUSH.L„D1’SAVE�D1 (‰BTST†#RDRFBIT,D0‰Test�Receive�reg�full.*‰BNE.S…RCA‘BrancJ h�if�received�a�character. +‰BTST†#OVRNBIT,D0‰Test�for�receive�overrun.‰BNE.S…SRC‘Branch�if�overrun. )‰BTST†#DCDBIT,D0ŠTest�for�DCD�transition.&‰BNE.S…SRC‘Branch�if�DCD�(don't�care). -‰BTST†#TDREBIT,D0‰Test�transmit�buffer�empty.%‰BNE.S…TBE‘Branch�if�buffer�is�empty. +‰BRA.S…INT_EXITŒShould�not�get�here�anyway.ŠPAGEJ***************************************************************************)*‰TRANSMIT�BUFFER�EMPTY�INTERRUPT�HANDLER*=*‰The�ACIA's�transmit�buffer�just�became�empty,�so�if�we�have+*‰more�characters�to�send�we�can�do�it�now.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�ACIA*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** TBE:5ŠMOVE.B�XINTDISA(A5),CREG(A1)ƒDISABLE�XMIT�INTERRUPTS *%%%%%%%%%%ƒBWN‚9/17/84*F*‚Call�the�device-independent�routine�that�deals�with�transparent�mode)*‚or�invokes�the�XMIT�background�routine.* ‰JSR‡TERM_TBE ‰BRA‡INT_EXITŠPAGEJ***************************************************************************(*‰RECEIVED�CHARACTER�AVAILABLE�INTERRUPT*=*‰The�ACIA�has�just�received�a�character,�and�it�is�available=*‰for�reading.‚We�will�do�that�now,�and�the�result�will�go�in$*‰the�receive�queue�if�there's�room.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�ACIA*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** RCA:.‰MOVEQ…#$74,D1‰Test�PARITY,FRAMING,OVERRUN�and‰AND.B…D0,D1‹DCD�errors.&‰BNE.S…SRC�Branch�if�one�of�the�above. 8‰MOVE.B�DREG(A1),D0ˆGet�the�char�from�the�ACIA�and�reset ‰TST.B…GOTBREAK(A5) ‰IF��THEN/‹SFˆGOTBREAK(A5)„Clear�error�on�last�char�flag./‹TST.B…D0ŽIs�this�garbage�char�at�end-of-break? ‹BLT‡INT_EXIT‰ENDI *%%%%%%%%%%%%‚BWN�9/17/84*C*‚Call�the�device�independent�routine�to�check�for�transparent�modeG*‚and�do�the�stuff�for�transparent�mode�or�if�not�in�tranparent�mode�toG*‚check�for�any�special�characters�such�as�XON,�XOFF,�BREAK�EQUIVALENT,G*‚or�DISCARD�OUTPUT.�Otherwise,�put�the�character�in�the�receive�queue.*‰JSR‡TERM_GOT_CHAR ‰BRA‡INT_EXITŠPAGEJ***************************************************************************%*‰SPECIAL�RECEIVE�CONDITION�INTERRUPT*:*‰The�ACIA�detected�an�error�in�the�process�of�receiving�a<*‰character.‚We�need�to�record�this�information�so�that�when<*‰the�corresponding�data�is�requested�from�the�receive�queue*‰we�can�report�an�error.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�ACIA*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** #SRC:†EQU„*’A1�<--�addr�of�our�ACIA."*£D0�<--�our�ACIA�status�register.'‰MOVE.B‚DREG(A1),D1ˆD1�CONTENTS�OF�DREG0‰TST.BƒGOTBREAK(A5)‡TEST�ERROR�ON�LAST�CHAR�FLAG ‰BNE…INT_EXIT ‰BTST†#4,D0"‰IF��THEN.S�TEST�FRAMING�ERROR‹ST…GOTBREAK(A5)†SET�ERROR�FLAG3‹JSR„TERM_BREAKˆCall�the�device�independent�routine*£to�take�care�of�a�break. ‹BRA„INT_EXIT‰ENDI—* ‰BTSTƒ#6,D0ŽTEST�PARITY�ERROR‰IF��THEN.S1‹PUT_BYTE�PAR_FRAM,D0„Log�a�parity/framing�error;‹JSR„LOG_ERRŠ* ‹BRA„INT_EXIT*¢else�(not�parity�or�framing)‰ELSE.S‰BTST†#5,D0‹TEST�OVERRUN�ERROR‰IF��THEN.S*‹PUT_BYTE�OVERRUN,D0…Log�an�overrun�error.‹JSR„LOG_ERRŠ* ‹BRA„INT_EXIT‰ENDI–*‰ENDI2‰BRA„INT_EXIT‹Exit.�MUST�HAVE�BEEN�DCD.�DONT�CARE.‰NOP‰PAGE*E*‚Now�exit�as�from�an�interrupt.‚We�may�in�fact�have�been�called�fromF*‚command�service�or�initialization,�but�they�had�to�set�it�up�to�look*‚like�an�interrupt,�too.*INT_EXIT:�POP.L‚D1‘Restore�D1,7ŠMOVEQ‚#1,D0Žset�carry�bit�to�tell�CMR�'we�handled�iJ t,' ŠSUBQƒ#2,D0Ž*ŠRTS—and�return.ŠPAGEO********************************************************************************2*‰ROUTINES�TO�SET�THE�CLOCK�DIVISOR�TO�x16�AND�x64*7*‰No�work�here�since�ACIA�cannot�set�the�clock�divisor.*=*‰We�must�have�a�CLOCKRESET�entry�point�for�TERMLIB,�however.**‰Entry:*‹A1ƒ=*‹A5ƒ=�addr�of�our�CCB.**‰Exit:*O******************************************************************************* CLOCK_RESET:ŠRTSŠPAGEK*****************************************************************************!*�R�O�U�T�I�N�E�S„C�A�L�L�E�D„B�Y**–T�E�R�M�L�I�B**F**********************************************************************‰PAGEL******************************************************************************ˆTRANSMIT�THE�CHARACTER*?*ˆThis�is�the�device�dependent�routine�that�actually�writes�the*ˆcharacter�to�the�device.*F*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning�of�the *ˆdriver.**ˆEntry:„A1�=�address�of�ACIA*’A5�=�address�of�CCB*’D0.B�=�character�to�transmit*ˆInterrupt�level�on�entry:�0*C*ˆExit:…All�registers�are�preserved,�including�the�status�register.<*’It�is�important�to�keep�the�interrupt�level�the�same�as�it*’was�upon�entry.*J************************************************************************** PUT_CHAR:‰PUSHƒSR‰INHIBIT1‰MOVE.B�D0,DREG(A1)ˆOtherwise,�transmit�the�char./‰MOVE.B�XINTENAB(A5),CREG(A1)‚ENABLE�XMIT�INTS.‰POP„SR‰RTS‰PAGEM******************************************************************************$*ˆCHECK�THE�DEVICE'S�TRANSMIT�BUFFER*F*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installed�at*ˆthe�beginning�of�the�driver.**ˆEntry:�A1�=�address�of�ACIA*�A5�=�address�of�CCB*ˆInterrupt�level�on�entry:�0**ˆExit:‚Condition�codes:"*��=�transmit�buffer�not�empty*��=�transmit�buffer�empty<*ˆIt�is�important�to�keep�the�interrupt�level�the�same�as�it*ˆwas�upon�entry.*M*****************************************************************************CK_TBE:A‰BTST.B�#TDREBIT,SREG(A1)‚If�ACIA's�transmit�buffer�is�not�empty,‰RTS‰PAGEH************************************************************************* *ˆDEVICE�DEPENDENT�RESET�ROUTINE*9*ˆThis�is�the�device-dependent�part�of�the�reset�routine.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:�A5�=�addr�of�CCB*ˆInterrupt�level�on�entry:�0*$*ˆExit:‚All�registers�are�preserved.<*ˆIt�is�important�to�keep�the�interrupt�level�the�same�as�it*ˆwas�upon�entry.*E********************************************************************* DDP_RESET:*A*‚ACIA�did�not�have�any�device�dependent�reset�stuff�in�the�RESET:*‚routine,�which�is�where�this�stuff�would�have�come�from.* ŠRTS—exit.ŠPAGEJ***************************************************************************@*‰SUBROUTINE�TO�SET�UP�THE�DEVICE�ACCORDING�TO�THE�CONFIGURATION*;*‰Uses�the�working�configuration�(in�the�CCB)�to�set�up�the;*‰device,�and�some�configuration-related�fields�in�the�CCB.*?*‰The�offset�to�this�routine�must�be�installed�at�the�beginning*‰of�the�driver.**‰Entry:�A5�=�address�of�CCB*‰Interrupt�level�on�entry:�0*$*‰Exit:‚All�registers�are�preserved.<*‰It�is�important�to�keep�the�interrupt�level�the�same�as�it*‰was�upon�entry.*J************************************************************************** SETUP:<ŠMOVEM.L�D0-D1/A0-A3,-(A7)�Save�some�registers�on�the�stack. ŠPUSHƒSR **‚First�set�up�addresses.*4ŠLEA„CONFIG(A5),A0†A0�<--�addr�of�CCB�configuration.3ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�ACIA�port.**‚[4]„x16�clock�rate,(*‰stop�bits�&�parity�from�configuration.*)ŠMOVE.Bƒ#1,D0ŒStart�with�x16�clock�in�D0. )‰BTSTWƒ#IOABITS,IOSATW(A0)ƒTEST�BITS/CHAR‰IF��THEN.S�IF�8�THEN‹OR.Bƒ#$10,D0Œ(8�bits/char)>‹BTSTW‚#IOAUSEP,IOSATW(A0)�If�we'rK e�using�parity,�enable�it... ‹IF…�THEN �OR.Bƒ#$08,D09�BTSTW‚#IOAPRTY,IOSATW(A0)�and�if�we're�using�odd�parity,�IF…�THENŠset�it�up. �OR.Bƒ#$04,D0�ENDI‹ELSE.S•8�BITS�NO�PARITY)�BTSTW‚#IOASTPB,IOSATW(A0)ƒTEST�STOP�BITS�IF��THEN.S�IF�1�THEN �OR.Wƒ#$04,D0�ENDI‹ENDI‰ELSE.S˜ELSE�7�THEN)‹BTSTW„#IOASTPB,IOSATW(A0)„TEST�STOP�BITS‹IF��THEN.S�OR.Wƒ#$08,D0�IF�1‹ENDI&‹BTSTW„#IOAPRTY,IOSATW(A0)ƒTEST�PARITY‹IF��THEN.S‘IF�ODD�THEN �OR.W„#$04,D0‹ENDI‰ENDI "*§Transmitter�int�disabled�DTR�low /ŠOR.B…#$80,D0ŽRecieve,Overrun,DCD‚Int's�Enabled‰INHIBITŠMOVE.BƒD0,(A1)‰POP‡SR9ŠMOVE.BƒD0,XINTDISA(A5)†SAVE�CONT�REG�(XMIT�INT�DISABLED) ŠOR.B…#$20,D08ŠMOVE.BƒD0,XINTENAB(A5)…SAVE�CONT�REG�(XMIT�INT�ENABLED):ŠAND.B„#%10011111,D0„Clear�bits�5�and�6�for�setting�up�RTS*ŠOR.B…#%01000000,D0„Set�RTS�bit�for�a�HIGHŠMOVE.BƒD0,XRTSHI(A5)**‚Set�up�baud�rate*G‰IF.B�CCBTYPE(A5)��#$66�OR.B�CCBTYPE(A5)��#$67�THEN.S�KG�052384.‹MOVE.B„IOSBRT(A0),D0‡The�configured�baud�rate‹PUT_BYTE‚$F0,D1ŽMask!‹BTST†#0,CCBTYPE(A5)†A�side�port?‹IF��THEN.S �LSL.B…#4,D0�PUT_BYTE‚$0F,D1‹ENDI2‹AND.B…D1,BAUDPIA…Clear�old�baud�rate…KEG�05/23/842‹OR.B†D0,BAUDPIA…Insert�new�baud�rate„KEG�05/23/84‰ENDI **‚Restore�registers�and�return.*8ŠMOVEM.L�(A7)+,D0-D1/A0-A3�Restore�registers�from�stack.ŠRTSŠPAGEJ****************************************************************************‰GET�DEVICE�STATUS�BYTE*"*‰Prepares�the�DEVICE�STATUS�byte.*8*‰Note:‚this�routine�does�not�set�the�break�indicator�in*�the�device�status�byte.*?*‰The�offset�to�this�routine�must�be�installed�at�the�beginning*‰of�the�driver.**‰Entry:�A5�=�address�of�CCB*‰Interrupt�level�on�entry:�0*&*‰Exit:‚D0.B�=�the�device�status�byte.<*‰It�is�important�to�keep�the�interrupt�level�the�same�as�it*‰was�upon�entry.*J************************************************************************** GET_STAT: ŠCLR.B‚D0 ŠPUSH.L�A0ŠMOVE.LƒCCBCHB(A5),A00ŠBTST…#CTSBIT,SREG(A0)„TEST�CTS�BITŒKEG�05/23/84ŠIF��THEN.S'ŒBSETƒ#XDSNRB,D0ŠDATA�SET�NOT�READY�BITŠENDI ŠPOP.L‚A0 ŠRTS—Return.ŠPAGEM******************************************************************************5*ˆDEVICE�DEPENDENT�STUFF�FOR�LOWERING�A�HARDWARE�LINE*ˆTO�STOP�THE�TRANSMITTER.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�address�of�ACIA*�A5�=�address�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*K*************************************************************************** DDP_STOP:DŠMOVE.B�XRTSHI(A5),CREG(A1)�Make�RTS�go�HIGH�to�stop�the�transmitter*¤KEG�05/23/84ŠRTS‰PAGEK****************************************************************************$*ˆDEVICE�DEPENDENT�UNSTOP�THE�DEVICE*=*ˆWhen�we�are�not�using�XOFF/XON,�we�unstop�the�device�in�our*ˆown�device�dependent�way.*;*ˆWe�are�running�in�background�when�this�routine�is�called.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�address�of�ACIA*�A5�=�address�of�the�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*J************************************************************************** DDP_UNSTOP:CŠMOVE.B�XINTENAB(A5),CREG(A1)�Make�RTS�go�LOW�to�enable�transmitter*¦KEG�05/23/84ŠRTSŠPAGEK****************************************************************************&*ˆDEVICE�DEPENDENT�BEGIN�BREAK�ROUTINE*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�addr�of�ACIA*�A5�=�addr�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*E********************************************************************* DDP_BEG_BRK EAK:‰SAVEƒD08‰MOVE.B�XINTDISA(A5),D0„D0�<--�image�of�ACIA�CONTROL�REG,‰OR.Bƒ#$60,D0ŒAdd�bits�to�send�break�signal.‰MOVE.B�D0,CREG(A1)ˆ* ‰RESTORE�D0‰RTS‰PAGEK****************************************************************************$*ˆDEVICE�DEPENDENT�END�BREAK�ROUTINE*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�addr�of�ACIA*�A5�=�addr�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*L**************************************************************************** DDP_END_BREAK:.‰MOVE.B‚XINTENAB(A5),CREG(A1)ƒENABLE�XMIT�INT.‰RTS‰PAGEI***************************************************************************“B�A�C�K�G�R�O�U�N�D**šAND**‘C�A�L�L�__�G�U�A�R�D�E�D**–R�O�U�T�I�N�E�S**•(DEVICE-DEPENDENT)*E*********************************************************************ŠPAGEO*********************************************************************************‰FINISH�OFF�THE�INITIALIZATION*A*‰The�initialization�routine�has�gone�around�resetting�everything@*‰it�can,�but�the�routines�RESET�and�SETUP�should�only�be�called>*‰from�within�the�background.‚So�he�invoked�this�routine�to�do *‰it�for�him.**‰Entry:*�A5�=�address�of�CCB.*O******************************************************************************* DO_INIT:**‚Inhibit�interrupts*‰PUSH†SR‰INHIBIT*)*‚Get�address�of�start�of�driver�into�CCB*‰LEA‡ACIADRV(PC),A4‰MOVE.L„A4,DRV_ADDR(A5)*0*‚Now�actually�do�the�minimum�setup�on�the�ACIA.*.ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�ACIA.4ŠMOVE.B�CCBRESV(A5),CREG(A1)�Reset�our�ACIA�channel. ŠJSR„RESETŽReset�everything.ŠBSR.L‚DDP_RESET5ŠBSR.L‚SETUPŽSet�up�the�ACIA�according�to�the�config.**‚Enable�interrupts�now.*‰POP‡SR‰RTS‰PAGE*********************** *‚PATCH�SPACE***********************ŠDS.Wƒ30ŠEND  éééADARTDRVƒIDNTƒ4,0‡VERSADOS�SCN2681�TERMINAL�DRIVER�WITH�TYPE-AHEAD>ŠTTL„DARTDRV:‚VERSADOS�SCN2681�TERMINAL�DRIVER�WITH�TYPE-AHEAD ŠLLENƒ120J**************************************************************************J**************************************************************************J**************************************************************************J***************************************************************************<*‰DARTDRV:‚VERSAdos�SCN2681�terminal�driver�with�type-ahead.*8*‰Purpose:‚VERSAdos�device�driver�to�handle�asynchronous2*�terminals�(of�any�type)�over�the�SCN2681�chip�on*�the�following�boards:2*“MVME115„MVME115-A�(This�one�not�implemented�yet)**‰Revision�history:1*‘10/23/84‚All�BSR's�to�TERMLIB�now�JSR's�in�case.*›TERMLIB�is�located�more�than�32K�bytes�away.**‘10/17/84‚Initial�release�by�Julie�Hoban.*J**************************************************************************J**************************************************************************J**************************************************************************J************************************************************************** **‚XREF's�from�TERMLIB* ‰XREF†LOG_ERR‰XREF†MARK_DOWN ‰XREF†RESET‰XREF†TERML _BREAK‰XREF†TERM_COMMAND‰XREF†TERM_GOT_CHAR‰XREF†TERM_INIT‰XREF†TERM_TBE‰XREF†TERM_UNRDY **‚Equate�files�included:* *‰STR.EQ*‰TCB.EQ*‰CCB.EQ*‰IOE.EQ*‰NIO.EQ*‰LV5.EQ0*‰BAB.EQ�Background�Activation�Block�description:*‰TERMCCB.EQ‰Offsets�and�equates�for�CCBDDP�for�terminals.#*‰TERMINAL.EQˆEquates�for�terminals*‰SCN2681.EQ‰Device�description*‰UTILITY.MC‰Macros*ŠNOLISTŠINCLUDE�9995.&.STR.EQŠNOLISTŠINCLUDE�9995.&.TCB.EQŠNOLISTŠINCLUDE�9995.&.CCB.EQŠNOLISTŠINCLUDE�9995.&.IOE.EQŠNOLISTŠINCLUDE�9995.&.NIO.EQŠNOLISTŠINCLUDE�9995.&.LV5.EQŠNOLISTŠINCLUDE�9995.&.BAB.EQŠNOLISTŠINCLUDE�9995.&.UTILITY.MCŠLISTŠINCLUDE�9995.&.SCN2681.EQŠINCLUDE�9995.&.TERMINAL.EQ sI |A „B Œ8 ”4 œ< ¤6 ¬8 ´9 ¼3 Ä9 Ì> Ô> ÜO ä? ìIŠINCLUDE�9995.&.TERMCCB.EQŠLIST>ŠTTL„DARTDRV:‚VERSADOS�SCN2681�TERMINAL�DRIVER�WITH�TYPE-AHEADŠPAGEŠOFFSET„TERMDDP*>*‚The�device-dependent�variables�of�the�CCB�are�defined�below.* :�RESERVE.4�SAV_SPR’Address�of�the�supervisor's�driver�CCB.%*§We�must�save�this�because�interrupt&*§processing�returns�to�the�supervisor *§driver. ;�RESERVE.4�SAV_ISR’Image�of�2681�interrupt�status�register. *§Used�to�keep�track�of�any�bits#*§(interrupts)�left�to�service�upon%*§return�to�the�supervisor.�Long�word*§not�required,�but�it�makes�it *§simple. :�RESERVE.1�SAV_CREG‘Image�of�2681�command�register,�needed#*§to�keep�track�of�the�state�of�the%*§transmitter�and‚receiver.‚To�give�a$*§command�other�than�RX/TX�On/Off�or$*§Reset,�read�the�current�state�from#*§here,�OR�in�the�bits�for�the�misc*§commands,�then�tell�the�chip. <�RESERVE.1�SAV_SREG‘Image�of�2681�status�register,�needed�to'*§keep�track�of�break�and�received�char#*§bits�in�the�status�register�while*§clearing�bits�in�SAV_ISR. 7�RESERVE.1�BRK_FLAG‘Flag�used�to�keep�track�of�when�the%*§SCN2681�is�transmitting�a�break�and%*§should�not�disable�the�transmitter. ;�RESERVE.1�TBE_FLAG‘Flag�used�to�keep�track�of�when�a�char-*§acter�has�been�output�and�the!*§transmit�buffer�empty�interrupt%*§has�not�yet�been�received�-�used�to%*§simulate�transmit�buffer�NOT�empty. ŠPAGE*L*‚The�device-dependent�Background�Activation�Blocks�(BAB)�are�defined�below.* :�RESERVE.12�IPC_BAB‘Routine�to�handle�IP2�line�transition. *@*ƒCompute�the�number�of�pages�of�memory�that�we�need�for�one�CCB>*ƒfor�the�DART�driver.‚CMR�automatically�allocates�one�page�ofA*ƒmemory�($100�bytes)�for�the�CCB,�and�our�variable�EXTCCBSZ�willB*ƒreside�in�the�CMR�parameter�table�at�the�beginning�of�the�driver8*ƒto�tell�CMR�how�many�extra�pages�of�memory�are�needed.**CCBSIZEB�EQU‡*PAGESIZE�EQU‡$100L1‡SET‡CCBSIZEB+PAGESIZE-1CCBSIZE‚EQU‡L1/PAGESIZEEXTCCBSZ�EQU‡CCBSIZE-1‰PAGEJ***************************************************************************+*‰SERVICE�VECTOR�TABLE,�REVISION�INFO,�ETC.*@*‰This�table�is�examined�by�CMR�when�the�channel�is�allocated�toC*‰determine�where�to�go�for�interrupts,�commands,�&�initialization.<*‰It�must�always�be�at�the�very�top�of�the�driver�code.‚Also>*‰included�is�a�parameter�telling�the�number�of�extra�pages�of>*‰memory�to�include�in�the�CCB,�and�information�describing�the*‰revision�of�the�driver.*L**************************************************************************** ŠSECTION‚0ŠOPT„BRS DARTDRV: *D*‚Service�vector�table.‚Notice�that�these�values�are�relative�to�theC*‚beginning�of�the�driver�so�the�mechanism�is�position-independent!*=ŠDC.LƒINTERRUPT-DARTDRV‚Address�of�interrupt�service�routine.9ŠDC.LƒCOMMAND-DARTDRV„Address�of�command�service�routine.5ŠDC.LƒINIT-DARTDRV‡Address�of�initialization�routine.ŠDC.Lƒ0’Reserved. **‚Other�CMR�parameters.*7ŠDC.BƒEXTCCBSZ‹#�of�extra�L pages�in�the�CCB.‚The�CCB�may)*§be�any�size�from�1�to�256�pages�(a�page'*§is�256�bytes):‚if�this�field�is�0,�it*§will�be�1�page,�etc.ŠDC.Bƒ0,0,0ŽReserved.ŠDC.Lƒ0,0,0ŽReserved. **‚Revision�info:*/ŠDC.Bƒ'110784'‹Date�of�last�assembly�as�MMDDYY.1ŠDC.Bƒ'�'�Space�indicates�no�patches�to�.LO�file.)ŠDC.Bƒ'4'�Major�VERSAdos�revision�number.*‰PAGEO********************************************************************************+*ˆJump�table�for�use�by�the�generic�TERMLIB*O******************************************************************************* ‰BRA.L…PUT_CHAR ‰BRA.L…CK_TBE‰BRA.L…DDP_RESET ‰BRA.L…SETUP‰BRA.L…CLOCK_RESET‰BRA.L…GET_STAT‰BRA.L…DDP_STOP‰BRA.L…DDP_UNSTOP‰BRA.L…DDP_BEG_BREAK‰BRA.L…DDP_END_BREAK‰PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INITIALIZATION�ROUTINE*>*‰This�routine�is�called�by�CMR�when�the�channel�is�allocated.9*‰Its�purpose�is�to�set�up�things�for�command�service�and7*‰interrupt�service.‚The�major�functions�performed�are:*@*‹1.�Device-Independent�initialization�in�the�call�to�TERM_INIT.3*‹2.�Device-Dependent�initialization�of�the�device.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.**‰Entry:…A5�=�address�of�CCB.*6*‰Calls:…TERM_INIT�in�generic�terminal�driver�TERMLIB.*'*‰Exits�to:‚CMR�(via�RTS)�if�all�is�OK.'*”KILLER�if�exec�won't�allocate�memory,.*•or�can't�get�background�routine�entry�point.*J**************************************************************************J**************************************************************************J**************************************************************************ŠDS…0INIT:*>*‚Perform�the�device-independent�initialization�by�calling�the'*‚generic�routine�TERM_INIT�in�TERMLIB.*.‰JSR‡TERM_INIT‹Do�the�device-independent�stuff2‰IFƒƒTHEN…Something�went�wrong�with�TERM_INIT.4‰IFƒƒTHEN„The�exec�call�failed�and�we�cannot�get!*œthe�scheduler's�entry�point�!!!ŽTR0$.KILLER‚,‰ELSE�RTS�The�channel�is�down�!!‰ENDI‰ENDI*;*‚Perform�the�minimum�device-dependent�initialization�using@*‚call�guarded�to�the�EXEC�for�a�routine�resident�in�background.*5‰LEA‡DO_INIT(PC),A0†Device-dependent�routine�address.-‰MOVE.L„#T0GUARD,D0‰Call�guarded�to�the�EXEC.‰TRAP†#0‰RTS‰PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰COMMAND�SERVICE�ROUTINE*>*‰We�get�entered�here�when�the�attached�task�(IOS)�invokes�CMR?*‰via�a�TRAP�1�with�an�INITIATE�I/O�parameter�block�to�process.>*‰CMR�has�already�checked�the�CMR�parameter�block�to�ensure�it<*‰resides�within�the�address�space�of�the�attached�task.‚IOSA*‰has�already�validated�the�IOCB,�except�for�the�buffer�addresses *‰therein.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.*5*‰Entry:�A2�=�physical�address�of�CMR�parameter�block*�A5�=�physical�address�of�CCB*9*‰Calls:�TERM_COMMAND�in�generic�terminal�driver�TERMLIB.*3*‰Exit:‚D0�=�results�of�parameter�block�validation:3*•always�0�in�our�case,�indicating�it�was�OK,�since2*•IOS�will�not�send�us�any�request�except�HALT�I/O/*•if�we�are�already�busy,�and�CMR�makes�all�the*•other�checks.**J**************************************************************************J**************************************************************************J********************************************************************M ****** COMMAND: *,*‚Perform�any�device-dependent�stuff�here...*9‰ST.BƒTBE_FLAG(A5)‹Set�the�flag�to�indicate�buffer�empty.*I*‚Perform�the�device-independent�command�handler�by�calling�TERM_COMMAND.* %ŠJSR…TERM_COMMAND†Perform�the�commandŠRTS—return�to�CMR.ŠPAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INTERRUPT�HANDLING�ROUTINE*<*‰This�routine�completes�I/O�requests�started�by�the�command:*‰service�routine.‚It�is�entered�at�the�interrupt�priority;*‰level�of�interrupts�on�this�channel,�and�is�essentially�a9*‰subroutine�to�the�first�level�interrupt�handler�in�CMR.=*‰Remember,�however,�that�this�is�a�subordinate�driver--hence=*‰the�interrupt�was�fielded�first�by�the�supervisor�used�with(*‰whatever�type�of�board�we're�handling.*5*‰Entry:�A0�=�address�of�the�supervisor�driver's�CCB.*�A5�=�address�of�our�CCB.3*�D1�=�Copy�of�Interrupt�Status�Register�from�2681.*"*�D0,A0,A1�have�been�saved�by�CMR.-*�D1‡has�been�saved�by�the�supervisor�driver.*�D0,A1„are�available�to�use.8*�A0‡must�be�returned�to�the�supervisor�with�the�address*šof�the�supervisor's�CCB.4*�D1‡must�be�returned�to�the�supervisor�with�the�bit(*špattern�of�interrupts�left�to�service.*>*‰Exit:‚always�via�RTS,�which�takes�us�back�to�the�supervisor.**‰Stack:*�(A7)+8�.�.�. *�(A7)+4�longword�return�address6*�(A7)ƒlongword�saved�contents�of�D1�(must�be�restored*—before�exit�to�CMR)*J**************************************************************************J**************************************************************************J************************************************************************** INTERRUPT: *‚NOTE:*?*‚This�driver�requires�a�supervisor�driver�since�it�handles�theA*‚SCN2681.‚The�supervisor�driver�written�for�use�with�this�one�isC*‚DARTSPR,�which�branches�to�the�appropriate�longword�in�this�tableC*‚depending�on�interrupt�type.‚The�supervisor�will�not�pass�controlA*‚to�this�driver�unless�there�is�in�fact�an�interrupt�on�my�port.**‚ENTRY�POINTS:*%ŠBRA.S‚RCA�Character�received�for�me.ŠNOP'ŠBRA.S‚TBE�My�transmit�buffer�is�ready.ŠNOP-ŠBRA.L‚BCI�Change�in�BREAK�status�on�my�port.ŠNOP&ŠBRA.L‚IP2�Input�Port�2�Status�change.ŠPAGEJ***************************************************************************)*‰TRANSMIT�BUFFER�EMPTY�INTERRUPT�HANDLER*@*‰The�SCN2681's�transmit�buffer�just�became�empty,�so�if�we�have+*‰more�characters�to�send�we�can�do�it�now.*5*‰Entry:�A0�=�address�of�the�supervisor�driver's�CCB.*�A5�=�address�of�CCB7*�D1�=�copy�of�Interrupt�Status�Register�from�the�2681.*9*‰Calls:�TERM_TBE�in�the�generic�terminal�driver�TERMLIB.*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*O******************************************************************************* TBE:.ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�port.<ŠMOVE.L�A0,SAV_SPR(A5)…Save�address�of�the�supervisor's�CCB. 4ŠBCLRƒ#CLRTBE,D1‰Clear�interrupt�bit�in�copy�of�ISR.*ŠMOVE.L�D1,SAV_ISR(A5)…Save�it�in�the�CCB. ?ŠTST.B‚BRK_FLAG(A5)‡Is�this�TBE�because�we're�transmitting�brk?+ŠIF…�THENŠThe�flag�is�set�if�yes,�so...(‹MOVEQ‚#0,D0�Put�some�nulls�into�D0,�and:‹MOVE.B�D0,DREG(A1)‡Output�a�character�to�clear�interrupt.)‹BRA.L‚INT_EXITŠExit�from�this�interrupt.ŠENDI 3ŠPUT_BYTE�TXOFF,D0‰Set�disable�transmitter�command.5ŠMOVE.B�D0,SAV_CREG(A5)„Replace�current�value�in�CCB.=ŠMOVE.B�D0,CREG(A1)ˆClear�interrupt�by�disabling�transmitter.5ŠST.BƒTBE_FLAG(A5)‡Set�flag�to�indicate�buffer�empty.*D*‚Now�call�the�device-independent�routine�that�tests�for�transparent/*‚mode�and�invokes�the�XMIT�background�routine.*ŠJSR„TERM_TBE‹JSR�into�TREMLIB.(ŠBRA.L‚INT_EXIT‹Exit�from�the�interrupt.ŠPAGEJ**M *************************************************************************(*‰RECEIVED�CHARACTER�AVAILABLE�INTERRUPT*@*‰The�SCN2681�has�just�received�a�character,�and�it�is�available=*‰for�reading.‚We�will�do�that�now,�and�the�result�will�go�in$*‰the�receive�queue�if�there's�room.*5*‰Entry:�A0�=�address�of�the�supervisor�driver's�CCB.*�A5�=�address�of�CCB7*�D1�=�copy�of�Interrupt�Status�Register�from�the�2681.*>*‰Calls:�TERM_GOT_CHAR�in�the�generic�terminal�driver�TERMLIB.*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** RCA:.ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�port.<ŠMOVE.L�A0,SAV_SPR(A5)…Save�address�of�the�supervisor's�CCB.*7*‚Get�the�character�from�the�2681�and�check�for�errors.*>ŠMOVE.B�DREG(A1),D0ˆClear�interrupt�by�getting�char�from�2681.2ŠBCLRƒ#CLRRCA,D1‰Clear�bit�in�working�copy�of�ISR.*ŠMOVE.L�D1,SAV_ISR(A5)…Save�it�in�the�CCB. 3ŠMOVE.B�SREG(A1),D1ˆGet�the�status�for�the�process./ŠAND.B‚#$70,D1ŒMask�out�all�but�the�error�bits.1ŠBNE.S‚INTERR�Branch�if�any�error�bits�turned�on.*D*‚Call�the�device�independent�routine�to�check�for�transparent�mode,D*‚and�any�special�characters�such�as�XON,�XOFF,�BREAK�EQUIVALENT,�or?*‚DISCARD�OUTPUT�and�invoke�the�appropriate�background�routine.9*‚Otherwise,�just�put�the�character�in�the�receive�queue.*"ŠJSRƒTERM_GOT_CHAR‡JSR�to�TERMLIB.(ŠBRA.L…INT_EXITˆExit�from�the�interrupt.ŠPAGEJ***************************************************************************#*‰FOUND�ERROR�ON�RECEIVED�CHARACTER*=*‰The�SCN2681�detected�an�error�in�the�process�of�receiving�a<*‰character.‚We�need�to�record�this�information�so�that�when<*‰the�corresponding�data�is�requested�from�the�receive�queue*‰we�can�report�an�error.*0*‰Entry:�D0.B�=�character�which�generated�error.0*�D1.B�=�status�register�value�(error�bits�only)*�A1ƒ=�address�of�our�port*�A5ƒ=�address�of�CCB*8*‰Calls:�LOG_ERR�in�the�generic�terminal�driver�TERMLIB.*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** INTERR:ŠSWAPƒD0‘Make�room.:ŠMOVE.B�SAV_CREG(A5),D0„Current�value�of�command�register.0ŠOR.Bƒ#RSTEST,D0‰Set�the�reset�error�status�bit.(ŠMOVE.B�D0,CREG(A1)ˆTell�it�to�the�chip.ŠSWAPƒD0‘Restore�character. )ŠBTSTƒ#SPARER,D1‰Was�this�a�parity�error?-ŠIF…�THENŠIf�the�parity�error�bit�is�set,8‹PUT_BYTE�PAR_FRAM,D0…Put�the�VERSAdos�error�code�in�D0,‹JSR„LOG_ERR‹Log�the�error.-‹BRA.L‚INT_EXITŠAnd�exit�from�this�interrupt.ŠENDI )ŠBTSTƒ#SDAOVR,D1‰Was�this�a�data�overrun?3ŠIF…�THENŠIf�the�data�overrun�error�bit�is�set,7‹PUT_BYTE�OVERRUN,D0†Put�the�VERSAdos�error�code�in�D0,‹JSR„LOG_ERR‹Log�the�error.-‹BRA.L‚INT_EXITŠAnd�exit�from�this�interrupt.ŠENDI *ŠBTSTƒ#SFRMER,D1‰Was�this�a�framing�error?.ŠIF…�THENŠIf�the�framing�error�bit�is�off,-‹BRA.L‚INT_EXITŠWe�shouldn't�be�here�so�exit."ŠELSE–The�framing�error�bit�is�on,3‹TST.B‚D0�So�let's�see�if�it�really�is�a�character.9‹IF…�THEN‰Character�is�real,�and�so�is�framing�error.8ŒPUT_BYTE�PAR_FRAM,D0„Put�the�VERSAdos�error�code�in�D0,ŒJSR„LOG_ERRŠLog�the�error.-ŒBRA.L‚INT_EXIT‰And�exit�from�this�interrupt.‹ENDIŠENDI‰PAGE*$*‚This�must�have�really�been�a�break*7ŠMOVE.B�SAV_CREG(A5),D0„Get�current�value�from�the�CCB.0ŠOR.Bƒ#RSTBCI,D0‰Set�the�reset�break�status�bit..ŠMOVE.B�D0,CREG(A1)ˆThis�clears�the�interrupt. *ŠMOVE.L�SAV_ISR(A5),D1…Get�value�from�CCB.4ŠBCLRƒ#CLRBCI,D1‰Clear�interrupt�bit�in�copy�of�ISR.*ŠMOVE.L�D1,SAV_ISR(A5)…Save�it�in�the�CCB. ŠBKGRND�BREAKŠBRA.L‚INT_EXITŠPAGEJ****************************************************************************‰BREAK�CHANGE�INTERRUPT*9*‰This�interrupt�from�the�2681�is�caused�when�either�port6*‰has�deN tected�the�beginning�or�end�of�a�break�signal.9*‰The�only�condition�we�care�about�is�when�a�break�signal:*‰starts�(detected�from�the�status�register�for�our�port),:*‰in�which�case�we�have�to�get�an�appropriate�event�to�the9*‰attached�task�(IOS).�For�both�interrupts,�we�must�issue7*‰a�'reset�break�change�interrupt'�command�to�clear�the*‰interrupt�bit�in�the�ISR.*.*‰Entry:�A0�=�address�of�the�supervisor's�CCB.*�A5�=�address�of�CCB?*�D1�=�working�copy�of�Interrupt�Status�Register�from�the�2681.*;*‰Calls:�TERM_BREAK�in�the�generic�terminal�driver�TERMLIB.*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** BCI:.ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�port.<ŠMOVE.L�A0,SAV_SPR(A5)…Save�address�of�the�supervisor's�CCB. DŠMOVE.B�SREG(A1),SAV_SREG(A5)�Save�current�value�of�status�register. ,ŠMOVE.B�SAV_CREG(A5),D0„Get�current�command.3ŠOR.Bƒ#RSTBCI,D0‰Set�the�reset�break�status�change.6ŠMOVE.B�D0,CREG(A1)ˆThis�clears�the�BCI�interrupt�bit.2ŠBCLRƒ#CLRBCI,D1‰Clear�bit�in�working�copy�of�ISR.ŠMOVE.B�D1,SAV_ISR(A5)…Save�it. **‚Clear�the�FIFO...*?CLRFIFOƒMOVE.B�6(A1),D0‹Read�the�FIFO...up�to�3�bytes�to�clear.ŠMOVE.B�6(A1),D0‹*ŠMOVE.B�6(A1),D0‹* 2ŠBCLRƒ#CLRRCA,D1‰Clear�bit�in�working�copy�of�ISR.*ŠMOVE.L�D1,SAV_ISR(A5)…Save�it�in�the�CCB. ;ŠMOVE.B�SAV_SREG(A5),D0„Get�saved�value�of�status�register.4ŠBTSTƒ#SRXBRK,D0‰This�bit�indicates�begin/end�break..ŠBEQ„INT_EXIT‹If��it�was�the�end,�so�exit. 7ŠJSR„TERM_BREAK‰JSR�to�TERMLIB�to�handle�dev-ind�break.&ŠBRA„INT_EXIT‹Exit�from�the�interrupt.ŠPAGEO*********************************************************************************‰IP2�INTERRUPT*<*‰The�Input�Port�2�has�made�a�transition�(active-to-inactive>*‰or�inactive-to-active).�The�Input�Port�2�is�jumpered�to�Port>*‰B�and�hard-wired�to�RS232�line�20.�IP2�is�monitored�from�the;*‰Input�Port�Change�Register�(IPCR)�of�the�SCN2681.�The�IP2<*‰interrupt�is�enabled�for�modem�operation�only�(the�IOAMODM<*‰bit�in�IOSATW�is�set).‚It�is�likely�that�the�user�will�fix;*‰the�MVME115�so�that�pin�8�of�the�RS232�interface�comes�in *‰on�IP2.*>*‰The�IPCR�is�read,�and�depending�on�the�current�state�of�IP2,C*‰the�appropriate�background�routine�is�activated�(IP2�active�low).*@*‰If�IP2�went�inactive-to-active,�then�a�modem�probably�answered@*‰the�phone�and�we�activate�BREAK�in�the�background.‚If�IP2�wentA*‰active-to-inactive,�then�the�modem�hung�up�or�the�terminal�wentA*‰unready,�and�we�may�have�to�queue�an�event�if�there�was�I/O.�We.*‰activate�IPC�in�the�background�to�handle�it.***‰Entry:�A0�=�address�of�supervisor's�CCB.*�A5�=�address�of�CCB?*�D1�=�working�copy�of�Interrupt�Status�Register�from�the�2681.*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*O******************************************************************************* IP2:4ŠBCLRƒ#CLRIP2,D1‰Clear�interrupt�bit�in�copy�of�ISR.*ŠMOVE.L�D1,SAV_ISR(A5)…Save�it�in�the�CCB.<ŠMOVE.L�A0,SAV_SPR(A5)…Save�address�of�the�supervisor's�CCB. ŠMOVE.L�ADRSIDEA(A5),A0>ŠMOVE.B�IPCR(A0),D0ˆD0�<--�current�input�port�change�register.**£(reading�this�register�clears�interrupt) 9ŠBTSTƒ#STAIP2,D0‰Test�IP2�to�indicate�active�or�inactive.)ŠBNE.S‚IPC20ŽIP2�is�low,�device�is�ready.8ŠBKGRND�BREAKŽHandle�device�ready�with�background�BREAK.ŠBRA.S‚INT_EXIT 9IPC20…BKGRND�IPC�Handle�device�unready�in�background�IPC.8*‰BRA.L‚INT_EXIT‹Fall�through�to�interrupt�exit�routine.ŠPAGEO*********************************************************************************‰INTERRUPT�EXIT�ROUTINE*;*‰All�interrupts�return�to�the�supervisor�via�this�routine.6*‰Here�we�look�at�our�flag�SAV_ISR�in�the�CCB.‚SAV_ISR7*‰started�out�looking�exactly�like�the�Interrupt�Status;*‰Register�from�the�2681.‚N As�we�cleared�interrupt�bits�fromA*‰the�various�sources�of�interrupts,�we�cleared�bits�in�our�flag.A*‰The�function�of�this�routine�is�to�let�us�set�up�for�our�return*‰to�the�supervisor.*O******************************************************************************* INT_EXIT:;‰MOVE.L�SAV_SPR(A5),A0‰Restore�address�of�supervisor's�CCB.0‰MOVE.L�SAV_ISR(A5),D1‰Restore�our�flag�into�D1.+‰RTS›And�we�must�go�back�to�the�supervisor.  SPC 15O********************************************************************************"*ˆEND�OF�INTERRUPT�SERVICE�ROUTINE*O*******************************************************************************ŠPAGEO*********************************************************************************!*�R�O�U�T�I�N�E�S„C�A�L�L�E�D„B�Y**–T�E�R�M�L�I�B**O*******************************************************************************‰PAGEL******************************************************************************ˆTRANSMIT�THE�CHARACTER*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedA*ˆat�the�beginning�of�the�driver.‚The�function�of�this�routine�isC*ˆwrite�the�character�contained�in�D0�to�the�transmit�data�register*ˆof�the�device.*;*ˆWe�are�running�in�background�when�this�routine�is�called.*-*ˆEntry:�A1�=�address�of�our�side�of�the�chip*�A5�=�address�of�CCB*�D0.B�=�character�to�transmit**�Interrupt�level�on�entry�is�0**ˆExit:‚RTS�to�caller.*0*ˆThis�routine�must�preserve�all�registers�used.0*ˆThe�interrupt�level�upon�exit�must�be�the�same*ˆas�it�was�upon�entry.*J************************************************************************** PUT_CHAR:ŠINHIBIT>ŠMOVE.B�#TXON,SAV_CREG(A5)„Save�enable�transmitter�cmd�in�CCB.2ŠMOVE.B�SAV_CREG(A5),CREG(A1)�Tell�it�to�the�chip.+ŠMOVE.B�D0,DREG(A1)‹Transmit�the�character.6ŠSF.BƒTBE_FLAG(A5)ŠClear�flag�to�indicate�buffer�full.'ŠUNMASK—Must�exit�at�interrupt�level�0.ŠRTSŠPAGEM******************************************************************************$*ˆCHECK�THE�DEVICE'S�TRANSMIT�BUFFER*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toF*ˆcheck�that�the�transmit�buffer�is�empty�before�allowing�any�transmit *ˆactivity.*;*ˆWe�are�running�in�background�when�this�routine�is�called.*-*ˆEntry:�A1�=�address�of�our�side�of�the�chip*�A5�=�address�of�CCB**�Interrupt�level�on�entry�is�0*/*ˆExit:‚RTS�to�caller�with�Condition�codes�set:"*��=�transmit�buffer�not�empty*��=�transmit�buffer�empty*0*ˆThis�routine�must�preserve�all�registers�used.0*ˆThe�interrupt�level�upon�exit�must�be�the�same*ˆas�it�was�upon�entry.*M***************************************************************************** CK_TBE:*E*‚Test�the�flag�to�simulate�transmit�buffer�empty�status.‚The�flag�isJ*‚set�when�a�character�is�output�and�cleared�when�the�tranmit�buffer�empty*‚interrupt�is�received.*ŠTST.B‚TBE_FLAG(A5)ŠRTSŠPAGEH************************************************************************* *ˆDEVICE�DEPENDENT�RESET�ROUTINE*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toC*ˆperform�a�minimum�reset�of�the�device.�For�the�SCN2681�this�means6*ˆclearing�any�error�status�and�enabling�the�receiver.*;*ˆWe�are�running�in�background�when�this�routine�is�called.**ˆEntry:�A5�=�address�of�CCB**�Interrupt�level�on�entry�is�0**ˆExit:‚RTS�to�caller*0*ˆThis�routine�must�preserve�all�registers�used.0*ˆThe�interrupt�level�upon�exit�must�be�the�same*ˆas�it�was�upon�entry.*E********************************************************************* DDP_RESET:6ŠMOVEM.L�D0/A1,-(A7)‹Save�used�registers�on�the�stack.1ŠMOVE.L�CCBCHB(A5),A1ŠA1�<--�address�of�our�port..ŠPUT_BYTE�RXON,D0ŽBe�sure�we�turn�receiver�on.5ŠMOVE.B�D0,SAV_CREG(A5)ˆSave�aO s�current�value�in�CCB.4ŠOR.Bƒ#RSTEST,D0�Set�reset�error�status�command�bit.(ŠMOVE.B�D0,CREG(A1)ŒTell�it�to�the�chip./ŠMOVEM.L�(A7)+,D0/A1‹Restore�working�registers.ŠRTSŠPAGEJ***************************************************************************@*ˆSUBROUTINE�TO�SET�UP�THE�DEVICE�ACCORDING�TO�THE�CONFIGURATION*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toE*ˆset�up�the�device�according�to�the�working�configuration�in�the�CCB3*ˆand�some�configuration-related�fields�in�the�CCB.*;*ˆWe�are�running�in�background�when�this�routine�is�called.**ˆEntry:�A5�=�address�of�CCB**�Interrupt�level�on�entry�is�0**ˆExit:‚RTS�to�caller*0*ˆThis�routine�must�preserve�all�registers�used.0*ˆThe�interrupt�level�upon�exit�must�be�the�same*ˆas�it�was�upon�entry.*J************************************************************************** SETUP:2ŠMOVEM.L�D0-D2/A0-A2,-(A7)„Save�working�registers.ŠPUSHƒSR **‚First�set�up�addresses.*4ŠLEA„CONFIG(A5),A0†A0�<--�addr�of�CCB�configuration..ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�port..ŠMOVE.L�ADRSIDEA(A5),A2„A2�<--�addr�of�port�A. */*‚Insure�that�RTS�if�off�(unready)�for�our�port*3‹BTST.B�#0,CCBTYPE(A5)‡If�we're�handling�the�A�port ‹IF…�THENŒ(we're�the�A-side)7ŒMOVE.B�#RTSAOFF,OPRR(A2)ƒset�the�RTS�line�HIGH�via�OP0‹ELSE˜(we're�the�B-side)7ŒMOVE.B�#RTSBOFF,OPRR(A2)ƒset�the�RTS�line�HIGH�via�OP1‹ENDI˜* **‚Perform�some�resets.*3ŠMOVE.B�SAV_CREG(A5),D0‡Get�current�value�from�CCB.,ŠOR.Bƒ#RSTEST,D0ŒSet�reset�error�status�bit.(ŠMOVE.B�D0,CREG(A1)‹Tell�it�to�the�chip. PAGE**‚Program�Mode�Register�1"*ˆstart�with:�flow�control�enabled*”interrupt�upon�FIFO�full*”character�error�mode3*ˆdetermine�other�fields�from�current�configuration*ˆworking�register�is�D0 !‰PUT_BYTE‚RXIRDY+CRXRTS+EMCHAR,D0 * Parity Mode [4:3]>ŠBTSTW‚#IOAUSEP,IOSATW(A0)ƒIf�we're�using�parity,�enable�it... ŠIF…�THEN)ŠOR.Bƒ#PAROFF,D0ŒMust�set�no�parity�bits.ŠELSE+ŠOR.Bƒ#PARENB,D0ŒOr�set�enable�parity�bits.ŠENDI* Parity Type [2]:ŠBTSTW‚#IOAPRTY,IOSATW(A0)ƒAnd�if�we're�using�even�parity,ŠIF…�THEN�set�it�up.ŠOR.Bƒ#PAREVN,D0ŠENDI * Character Length [1:0]1ŠBTSTW‚#IOABITS,IOSATW(A0)ƒAdd�in�bits/char�info. ŠIF…�THENŠOR.Bƒ#DTBPC7,D0Œ(7�bits/char)ŠELSEŠOR.Bƒ#DTBPC8,D0Œ(8�bits/char)ŠENDI *!*‚Program�Mode�Register�2�(MREG2)*ˆstart�with:‚normal�mode*•No�Tx�RTS�control*•No�Tx�CTS�control(*ˆdetermine�stop�bits�from�configuration*ˆworking�register�is�D1 ‰PUT_BYTE�CMNORM,D1 * Stop Bit Length [3:0]:ŠBTSTW‚#IOASTPB,IOSATW(A0)ƒAdd�in�the�number�of�stop�bits. ŠIF…�THENŠOR.Bƒ#SB1,D1�(1�stop�bit)ŠELSEŠOR.Bƒ#SB2,D1�(2�stop�bits)ŠENDI PAGE$‰INHIBIT—Inhibit�interrupts�while...3‰MOVE.B�SAV_CREG(A5),D2ˆGet�current�value�from�CCB.1‰OR.Bƒ#RSTMRP,D2�Set�reset�mode�register�pointer.(‰MOVE.B�D2,CREG(A1)ŒTell�it�to�the�chip./‰MOVE.B„D0,MREG1(A1)ˆProgram�mode�register�1...)‰MOVE.B„D1,MREG2(A1)ˆand�mode�register�2.‰ENABLE *C*‚Clock�Select�Register�(CSEL)�and�Auxiliary�Control�Register�(ACR)6*‡sets�the�baud�rate�for�the�receiver�and�transmitter.*‡working�register�D0�and�D1 *‰MOVEQ.L�#0,D0‘Clear�the�working�register.6‰MOVE.B‚IOSBRT(A0),D0‰Get�the�VERSAdos�baud�rate�CODE.,‰LSL.Lƒ#1,D0‘Double�it�to�use�in�BAUD_TABLE.<‰MOVE.W‚BAUD_TABLE(PC,D0.W),D1�Get�the�Rx/Tx�baud�rate�codes%*§and�baud�rate�set�bit�from�the�Baud(*§Rate�Conversion�Table�for�this�device. *3*‚Now�write�to�the�Auxiliary�Control�Register�(ACR)(*‚(Accessed�from�channel�A�address�only)*?‰BTSTW‚#IOAMODM,IOSATW(A0)‚If�this�is�a�modem�we're�talking�to,‰IF…�THEN�*7ŠOR.B„#INTIP2,D1‰Allow�interrupts�through�Input�Port�2.‰ENDI<‰MOVE.B‚D1,ACR(A2)ŠTell�the�chip�which�baud�rate�set�to�use. <*‚Now�write�to�the�Clock�Select�Register�for�the�baud�rates. .‰ROR.Wƒ#8,D1‘Put�the�baud�raO te�codes�into‚LSB.9‰MOVE.B‚D1,CSEL(A1)‹Move�LSB�(baud�rate�codes)�into�CSEL. *+*‚Program�the�Interrupt�Mask�Register�(IMR)=*ˆThe�driver�selected�which�ISR�bits�will�cause�an�interrupt.-*ˆThese�are:�change�in�break,�channel�A�and�B*“RxRDY,�channel�A�and�B*“TxRDY,�channel�A�and�B*“Input�Port�Change�on�IP21*ˆThe�counter/timer�interrupt�bit�is�turned�'off' 3ŠBTST.B�#0,CCBTYPE(A5)ˆIf�we're�handling�the�A�port ŠIF…�THEN�(we're�the�A-side)0‹MOVE.B�#$07,D0Žallow�interrupts�on�A-side�only.ŠELSE™(we're�the�B-side)2‹MOVE.B�#$F7,D0Žallow�interrupts�on�A�and�B�sides.ŠENDI™*'ŠMOVE.B�D0,IMR(A2)ŒTell�it�to�the�chip. ŠBRA.S‚SET10 PAGEO********************************************************************************"*‰TABLE�FOR�TRANSLATING�BAUD�RATES*O******************************************************************************* **�-----------------�Defines�Set�1�or�Set�2*�|&*�|�---------------�Baud�rate�set�code*�|�|*�V�V BAUD_TABLEŠDC.Bƒ$00,0‡50ŠDC.Bƒ$00,1‡75ŠDC.Bƒ$11,0†110ŠDC.Bƒ$22,0†134.5ŠDC.Bƒ$33,1†150ŠDC.Bƒ$44,0†300ŠDC.Bƒ$55,0†600ŠDC.Bƒ$66,0…1200ŠDC.Bƒ$AA,1…1800ŠDC.Bƒ$77,1…2000ŠDC.Bƒ$88,0…24000ŠDC.Bƒ$88,0…3600…We�don't�have�it�so�we�use�2400ŠDC.Bƒ$99,0…4800ŠDC.Bƒ$AA,0…7200ŠDC.Bƒ$BB,0…9600ŠDC.Bƒ$CC,1„19200 SET10…DS.Wƒ0 PAGE*!*‚Program�Command�Register�(CREG)+*ˆcurrent�state�is:�RTS�line�high�(unready)#*šreceiver�and�transmitter�disabled5*ˆWe�must�make�us�ready�and�enable�the�Receiver�only.  "* Make us ready by setting RTS low 3ŠBTST.B�#0,CCBTYPE(A5)‡If�we're�handling�the�A�port ŠIF��THEN�(we're�the�A-side)5‹MOVE.B�#RTSAON,OPSR(A2)„set�the�RTS�line�LOW�via�OP0ŠELSE˜(we're�the�B-side)5‹MOVE.B�#RTSBON,OPSR(A2)„set�the�RTS�line�LOW�via�OP1ŠENDI˜* %* See if the user wants us offhook...7‰BTSTW‚#IOAOFFH,IOSATW(A0)ƒIf�the�guy�wants�it�offhook,&‰IF…�THEN�Make�our�port�'unready'.3‰BTST.B�#0,CCBTYPE(A5)ˆIf�we're�handling�the�A�port ‰IF…�THEN�(we're�the�A-side)7ŠMOVE.B�#RTSAOFF,OPRR(A2)„set�the�RTS�line�HIGH�via�OP0‰ELSE™(we're�the�B-side)7ŠMOVE.B�#RTSBOFF,OPRR(A2)„set�the�RTS�line�HIGH�via�OP1‰ENDI™*‰ENDI )* Now enable the receiver and we're done..ŠPUT_BYTE�RXON,D0ŠSet�enable�receiver�command.5ŠMOVE.B�D0,SAV_CREG(A5)„Replace�current�value�in�CCB.(ŠMOVE.B�D0,CREG(A1)ˆTell�it�to�the�chip. **‚Restore�registers�and�return.*ŠPOP…SR8ŠMOVEM.L�(A7)+,D0-D2/A0-A2�Restore�registers�from�stack.ŠRTSŠPAGEO*********************************************************************************ˆRESET�THE�CLOCK*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�to3*ˆchange�the�clock�speed�back�to�its�default�value.*;*ˆWe�are�running�in�background�when�this�routine�is�called.*.*ˆEntry:�A1�=�address�of�our�side�of�the�chip.*�A5�=�address�of�our�CCB.**�Interrupt�level�on�entry�is�0**ˆExit:‚RTS�to�caller*éééé