IMD 1.17: 11/11/2014 15:15:50 82VKXBVERDOS C* VERSADOS/RMS68K OBJECT 4.4 SN=48634 21 OF 22  BT21\82VKXBVERDOS 0420¼=-�AND.L�#1<�MOVE.L�QTAIL(A5),A0„get�current�queue�pointer�(even�if�empty)(�CMPA.L�QHEAD(A5),A0„is�the�queue�empty?�BNE.S‚INTROK3‰br�=�no.�LEA.L‚CONFINFO(A5),A4ƒyes,�the�queue�is�empty,�MOVE.L�DVDCBPTR(A4),A4ƒso�set�A4�<=�BUS�DCB'�SUB.L‚A3,A3�set�up�dummy�IOSPB�address BRA.S INTROK4*4INTROK3�MOVE.L�DCBQOFST(A0),A4ƒA4�<==�address�of�DCB7�MOVE.L�IPBQOFST(A0),A3ƒA3�<==�address�of�current�IOSPB*.*ˆGive�DMA�complete�interrupt�highest�priority*DINTROK4�BTST.L�#IOCINT,D0‚did�an�I/O�complete�(DMA)�interrupt�occur?�BEQ.S�INTR100‚yes*, BTST #TMSINT,D0 was it a TMS9914 interrupt? BEQ INTR500 br = yes*'*ˆElse�it�must�be�a�BUS�ERROR�interrupt*E********************************************************************** *ƒBUS�ERROR*:*ˆThe�Bus�error�interrupt�is�generated�by�the�MVME300�cardB*ˆwhenever�a�DMA�bus�error�condition�occurs�during�a�transmission.8*ˆIf�there�was�no�I/O�in�progress,�the�interrupt�will�be>*ˆconsidered�spurious�and�will�generate�an�unsolicited�channel?*ˆinterrupt�to�IOS.‚If�I/O�was�in�progress,�the�current�command=*ˆwill�be�aborted�and�a�hardware�malfunction�error�event�sent *ˆto�IOS.*6�BSET.B�#VBIMENAB,CONTREG2(A1)‚enable�Bus�error�vector(�MOVE.L�QTAIL(A5),A0‚is�I/O�in�progress? CMPA.L QHEAD(A5),A0�BEQ�INTREXIT‰branch�if�no*@*ƒIf�an�SRQ�was�in�progress,�abort�all�SRQ�processing�and�send�a$*ƒHardware�Malfunction�error�to�IOS.*B*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<* *ˆ4/24/84ƒbwn*9*ˆMust�inhibit�TMS9914A‚interrupts‚during�DMA�operations.*ˆMust�re-enable�here.*4�BSET.B�#VBIMENAB,CONTREG0(A1)‚re-enable�9914�intrps*?*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>. MOVEQ #ISTABUS,D1 indicate hardware bus error�BSR�PROCMERR‚process�error�BRA�INTREXIT‚normal�exit6 TTL GPIB DRIVER - INTERRUPT PROCESSING (DMA COMPLETE) PAGEG*************************************************************************ƒI/O�COMPLETE*:*ˆThis�interrupt�is�generated�by�the�MVME300�card�whenever>*ˆa�DMA�WRITE�or�DMA�READ�has�completed.�Three�major�functions<*ˆare�accomplished�in�this�sectionand�they�are:�(1)�I/O�post6*ˆformatting�(if�specified)�after�a�DMA�WRITE/READ�has;*ˆcompleted,�(2)�menu�processing�and�initiation�and�(3)�SRQ *ˆprocessing.*8*ˆFor�post�I/O�formatting,�the�user�may�specify�a�formatD*ˆroutines�to�be�executed�upon�completing�the�desired�DMA�operation.<*ˆThese�routines�must�be�specified�at�sysgen�time�and�should*ˆreport�errors.*<*ˆThe�menu�processing�section�is�designed�to�either�initiate;*ˆthe�next�menu�item�or,�if�at�end�of�menu,�to�queue�an�I/O:*ˆcompletion�event�back�to�IOS�and�initiate�an�new�menu�if7*ˆthere�are�other�operations�waiting�on�the�GPIB�queue.*;*ˆThe�last�major�section�of�the�I/O�complete�portion�of�the8*ˆinterrupt�handler�is�to�handle�program�flow�of�service;*ˆrequest�functions�(SRQ)�when�received�in�controller�mode.?*ˆThe�processor�will�run�status�menues�to�each�device�connected;*ˆto�the�GPIB�until�the�device�requesting�service�is�found.;*ˆOnce�found,�an�SRQ�ASQ�event�will�be�sent�back�to�IOS�for*ˆexamination.*INTR100:5 MOVE.B #1<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>/�MOVE.L�QTAIL(A5),A0‚current�menu�queue�pointer)�CMPA.L�QHEAD(A5),A0‚is�I/O�in�progress�?�BEQ�INTREXIT‰br�=�no*5�BTSTW�#CAC_S,BUSACTIV(A5)ƒare�we�in�controller�mode?�BEQ.S�INTR115�br�=�no*4�BTST�#LADS_B,ADDRSTAT(A1)ƒis�9914�in�listener�mode?�BEQ.S�INTR110�br�=�no7�MOVE.B�#TCS,AUXCMD(A1)†so�take�control�(synchronously)2�MOVE.B�DATAIO(A1),D0ˆread�reg�to�get�things�going BRA.S INTR115**ƒAll�data�DMA�sequences�require�the�length�of�the�transfer�toD*ƒbe�reported�back�in�the�IOS�parameter�block�originating�this�call.*<�MOVEQ�#0,D0ƒread�the�current�memory�location�in�the�MAR�reg/ MOVE.B MARMSB(A1),D0 get most significant byte ASL.L #8,D0+ MOVE.B MARISB(A1),D0 get intermediate byte ASL.L #8,D00�MOVE.B�MARLSB(A1),D0‚get�least�significant�byteB*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn*8*ˆThe�address�we�get�in�D0�is�the�address�as�seen�by�the*ˆMVME300�board.4*ˆIf�we�are�using�dual�ported�ram‚on�the�VME/10,�and5*ˆif�this�address�is�in�on-board�ram,�then�it�must�be:*ˆtranslated�to�an�on-board�address�as�the�driver�sees�it.8*ˆWe�do�this�by�subtracting�the�RAM_SKEW�offset�from�the%*ˆaddress,�using�the�GET_ON_BD�macro.* ‰GET_ON_BD�D0*>*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>**<*‚Check�to�see�if�this�was�the�IN�or�OUT�processor.�If�it�is8*‚calculate�the�length�of�the�last�transfer�based�on�the=*‚contents�of�the�GPIBC�memory�address�register�(MAR)�and�theC*‚type�of�I/O�operation�performed,�else�no�length�calcs.�are�req'd.*?�MOVE.L�MENUCPOS(A5),A0‚get�address�of�menu�item�just�completed1�CMPI.B�#OUT,(A0)„was�the�OUT�processor�executed?�BEQ.S�INTR150…br�=�yes*/�CMPI.B�#IN,(A0)„was�the�IN�processor�executed?1�BNE.S�INTR200„br�=�TERM�or�SEOI�process�finished*I* Check for the one command that uses the secondary buffer instead of the* primary buffer for data xfer.*GINTR130�CMPI.W�#IOOWIN,IOSFCT(A3)ƒis�this�an�outout�with�input�command?�BNE.S�INTR150ƒbr�=�noG�SUB.L�D6,D0‚D0�=�current�M.A.R.�minus�(secondary)�buffer�start�address BRA.S INTR160*LINTR150 SUB.L D7,D0 D0 = current M.A.R. minus (primary) buffer start address*;INTR160 MOVE.L D0,IOSLEN(A3) store I/O xfer length in IOSPB*C*ƒCheck�to�see�if�there�is�a�special�post�formatters�to�be�executed*C�MOVE.L�IOSFMTA+DCBDEV(A4),D1‚get�pointer�to�user�defined�formatter1 BEQ.S INTR200 br = no user defined I/O formatter*B*‚Check�to�see�whether�input�or�output�menu�processor�was�executedA*‚and�then�see�if�there�is�a�user�defined�post�processor�for�this *‚device.*@�MOVE.W�#PST_OFMT,D0ƒD0�<==�preload�post�output�formatter�offset5�CMPI.B�#OUT,(A0)…are�we�doing�"OUT"�menu�processing?�BEQ.S�INTR180„branch�if�yes7�MOVE.W�#PST_IFMT,D0ƒD0�<==�post�input�formatter�offset*:INTR180�MOVE.L�D1,A0†A0�<==�base�address�of�all�formatters8�TST.L�0(A0,D0.W)ƒdid�user�define�a�post�data�formatter?�BEQ.S�INTR200ƒbranch�=�no*+�MOVEM.L�D1-D7/A0-A6,-(A7)‚save�environment.�JSR�0(A0,D0.W)‚execute�user�defined�formatter MOVEM.L (A7)+,D1-D7/A0-A6,�TST.B�D0ƒcheck�error�code�from�user�routine!�BEQ.S�INTR200‚branch�if�no�error*B*‚An�error�has�been�detected�in�the�user's�input�formatter�routine*-�MOVEQ‚#ISTAINFE,D1‚set�input�formatter�error�BSR�PROCMERR‚process�error+ BRA.S INTR250 exit DMA interrupt processor*INTR200:'�BSR�PROCMENU„process�next�menu�item(s)*INTR250:6 MOVE.W (A7)+,D5 retrieve previous TMS9914 status regs (�TST.W�D5ˆwas�there�a�pending�interrupt? BEQ INTREXIT br = no �BRA.S�INTR510‚else�go�handle�it  ; TTL GPIB DRIVER - INTERRUPT PROCESSING (TMS9914 INTERRUPT) PAGEE***********************************************************************ƒTMS9914A�INTERRUPT�SECTION*<*„Entering�this�section�of�the�interrupt�processor�indicates8*„that�one�or�more�interrupt�conditions�enabled�has�been;*„received.�Reading�the�interrupt�mask�regsiters�(INTR0�and9*„INTR1)�of�the�TMS9914A�will�indicate�which�condition(s) *„occurred.*;*„The�GPIB�can�be�in�one�and�only�one�of�the�four�following<*„states:�(1)�controller�mode,�(2)�talker�mode,�(3)�listener%*„mode,�or�(4)�idle�mode.‚These�modes@*„are�stored�in�'BUSACTIV'�and�may�change�depending�on�what�type=*„of�interrupt�occurred.‚Also,�different�actions�may�be�taken?*„depending�on�the�current�state�of�the�BUS.‚All�interrupt�bits8*„will�be�checked�each�time�a�TMS9914A�interrupt�occurs.* INTR500:5�MOVEP.W�INTR0(A1),D5ƒread�interrupt�status�registers6�AND.W‚TMSMASK(A5),D5ƒD5�=�valid�interrupt�status�bitsINTR510:B BSET.B #VBIMENAB,CONTREG0(A1) reset interrupt enable for TMS9914A***0***†My�Address�Change�(MAC)�check�and�processing***$�BTST�#MACBIT,D5†is�the�MAC�bit�set?�BEQ.S�INTR600ƒbr�=�no*I AND.W #$FFFF-(1< BTSTW #SRQPROG,BUSACTIV(A5) USER I/O or SRQ polling sequence?(�BNE.S�INTR605�br�=�SRQ�polling�sequenceJ MOVE.B SRQBYTE(A5),IOSSAD-1(A3) else move serial poll byte to user's IOPB-INTR605�BSR�PROCMENU‰continue�processing�menu BRA INTR700*+*ˆCheck�if�we�have�any�Task�I/O�ready�to�go*8INTR610�MOVE.L�#READPEND,D3‚set�up�for�I/O�pending�check0�BSR�CHECKIOP�go�look�for�task�level�I/O�pending***0***„Byte�Out�(BO)�interrupt�check�and�processing***)INTR700�BTST�#BOBIT,D5„is�the�BO�bit�set? BEQ.S INTR800*9�BTSTW�#CAC_S,BUSACTIV(A5)ƒis�the�BUS�in�controller�mode?�BEQ.S�INTR750�br�=�no*5*‚A�command�string�might�be�in�progress.‚Send�out�the"*‚next�command�byte�with�ATN�true.*/�TST.L�CMDCOUNT(A5)‰false�or�last�BO�interrupt?(�BEQ.S�INTR800Žbranch�if�yes�(ignore�it)*5�SUB.L�#1,CMDCOUNT(A5)†decrement�command�string�count5�BEQ.S�INTR730Žbranch�if�finished�with�command�string4�MOVE.L�CMDBFPTR(A5),A0…get�ptr�to�next�command�byte&�MOVE.B�(A0)+,D1Œget�next�command�byte5�MOVE.L�A0,CMDBFPTR(A5)…update�command�buffer�pointer%�BSR�COMCMD‘output�command�on�the�BUS�BRA.S�INTR800Žcontinue*@*ƒCommand�processing�is�complete�for�now.�Continue�with�the�next=*ƒmenu�item�after�the�command�out�menu�item�processor�for�the*ƒcurrent�command.*1INTR730�BSR�PROCMENUˆcontinue�with�next�menu�item�BRA.S�INTR800Žcontinue*!* We are not the active cntroller*8INTR750�MOVE.L�#WRITPEND,D3‚set�up�for�pending�I/O�check.�BSR�CHECKIOP�check�for�pending�task�level�I/O*** 8***†Service�Request�(SRQ)�interrupt�check�and�processing***BINTR800�BTST�#SRQBIT,D5ƒis�a�device�on�our�BUS�requesting�service?�BEQ.S�INTR900„br�=�no*: BSETW #SRQWAIT,BUSACTIV(A5) indicate SRQ intrp processing3�MOVE.L�QHEAD(A5),D1‡yes,�get�current�queue�pointer'�CMP.L�QTAIL(A5),D1ˆis�the�queue�empty?(�BNE.S�INTR900Žbranch�if�no,�bus�is�busy*A*‚Since�the�GPIB�is�idle,�initiate�the�service�request�processing2*‚to�determine�which�device�is�requesting�service.*9*ˆFirst�build�a�dummy�queue�entry�for�standard�processing** MOVEM.L A3-A4/D4-D7,-(A7) save intrp regs SUB.L A3,A3 dummy IOSPB address LEA.L CONFINFO(A5),A4L MOVE.L DVDCBPTR(A4),A4 A4 <= to BUS DCB (serial polling is a BUS operation)* LEA.L SRQBYTE(A5),A0 input buffer pointer,�MOVEQ�#1,D4‚Status�byte�response�length�=�1/ MOVE.L A3,D5 dummy length for secondary buffer2 MOVE.L A0,D6 dummy primary buffer address pointer4 MOVE.L A3,D7 dummy secondary buffer address pointer' BSR PSHGPIBQ go put entry on the queue- MOVEM.L (A7)+,A3-A4/D4-D7 restore intrp regs1 BEQ.S INTR900 br = queue full, process SRQ later&�BSR�PROCMSRQ‚start�up�the�SRQ�process***<***ƒRemote/Local�Change�(RLC)�interrupt�check�and�processing***6INTR900�BTST�#RLCBIT,D5ƒremote/local�change�interrupt?�BEQ.S�INTR1000ƒbranch�if�no*@�MOVE.B�ADDRSTAT(A1),D1‡D1�<==‚current�address�state�of�TMS9914A6�AND.W�#1<*‚bit�mask�and�check�to�see�if�we�even�need�to�respond�to�this*‚secondary�address.*8�LEA.L�CONFINFO(A5),A0„A0�<==�ptr�to�configuration�areas?�MOVE.L�CNFIGPTR(A0),A0ƒA0�<==�ptr�to�configuration�area�of�BUS*=*‚Read�the�command�pass�thru�register�to�obtain�the�secondary*‚address�that�is�required.*D�MOVE.B�CMDPTHRU(A1),D2†D2�=�secondary�addr�controller�is�requesting$�AND.L�#SECMASK,D2‹mask�address�bitsA�MOVE.L�IOSSAMW(A0),D1‡D1�<==�mask�of�valid�secondary�write�addrsD�BTST�#TADS_B,ADDRSTAT(A1)ƒAre�we�in�primary�talker�addressed�state?�BEQ.S�INTR1140ŽBranch�if�no*@�MOVE.L�IOSSAMR(A0),D1‡D1�<==�mask�of�valid�secondary�read�addrs*.INTR1140�BTST.L�D2,D1ˆvalid�secondary�address?�BNE.S�INTR1150�branch�if�yes*(*‚This�is�not�a�valid�secondary�address.*?�MOVE.B�#DACR0,AUXCMD(A1)‚release�hdshk�&�don't�enter�LADS/TADS�BRA.S�INTR1200ƒcontinue*AINTR1150 MOVE.B #DACR1,AUXCMD(A1) release hdshk & enter TADS/LADS4�OR.B�#1<�BRA.S�CKIO040�go�send�event�to�user�about�type�of�pending�I/O*&*ˆTask�I/O�is�pending,�check�for�match.*’on�operation�type�&�secondary�addr.�if�req'd*8CKIO010 BTST.B D3,IOPEND(A5) Is it a a matching request?.�BEQ.S�CKIO030�Br�=�no,�abort�Task�I/O�request*C BTST.B #SECONDAR,IOPEND(A5) Is there a secondary address involved?)�BEQ.S�CKIO050�Br�=�no,�go�start�the�menu5�MOVE.L�QTAIL(A5),A0‰get�pointer�to�current�operation2�MOVE.L�IPBQOFST(A0),A0†AO�<==�I/O�parameter�block9�CMP.W�#IORSEC,IOSFCT(A0)„Is�it�a�secondary�read�command?�BEQ.S�CKIO015�br�=�yes:�CMP.W�#IOWSEC,IOSFCT(A0)„Is�it�s�secondary�write�command?.�BNE.S�CKIO030�br�=�no,�abort�pending�task�I/O*CKIO015 MOVEQ #SECMASK,D1@�AND.B�IOPEND(A5),D1‰D1�=�active�controller�requested�sec.�addr.H�CMP.B�IOSSAD-1(A0),D1‡is�it�the�same�as�rhe�Task's�requested�sec�addr.?'�BEQ.S�CKIO050�br�=�yes,�start�the�menu*.CKIO030�BSR�HLTCMD‹kill�the�task�requested�I/O CKIO050�BSETW�#BUSIOP,BUSACTIV(A5)ƒset�INTRP�level�I/O�pending&�BSR�PROCMENU‘Initiate�I/O�on�the�menu* CKIO060 RTS PAGEH**************************************************************************—CANCEL�PENDING�I/O*;*ˆAn�event�has�occurred�on�the�BUS�that�forces�us�to�cancel9*ˆany�pending�I/O�regardless�of�source.‚The�cause�of�this&*ˆevent�will�also�be�sent�to�the�user.**/*ˆENTER:„A1�<==‚base�address�of�GPIBC�registers*’A3�<==‚address�of�IOSPB*’A4�<==‚address�of�DCB*’A5�<==‚address�of�CCB*.*’D5.W�<==�current�9914�intrp�reg�(INTR�LEVEL)**’D3.B�<==�I/O�operation�type�(READ/WRITE)* CANCLIOP:#�BSR�HLTALL’Halt�all�I/O�on�the�BUS, MOVE.B #0,IOPEND(A5) cancel any pending I/OH�AND.W‚#$FFFF-(1<PROCMENA�MOVE.L�QTAIL(A5),A6‰A6�<==�ptr�to�current�queue�entry1�BTSTW�#HALTED,CSTQOFST(A6)‚was�this�menu�Halted?�BNE�PROCM020�br�=�yesK MOVE.L MENUNPOS(A5),MENUCPOS(A5) update: next item is now the current item6�MOVE.L�MENUNPOS(A5),A0ƒget�next�menu�position�pointer#�MOVE.B�(A0)+,D0ƒget�next�menu�item5�MOVE.L�A0,MENUNPOS(A5)ƒupdate�next�menu�item�pointer* *ƒcheck�to�see�if�at�end�of�menu*�CMP.B�#END,D0Œend�of�menu?�BEQ.S�PROCM020‹yes* * Initiate I/O on next menu item*;�LEA.L�MENUCTBL(PC),A0ƒA0�<--�menu�function�code�jump�table(�CMP.B�#MENUCLEN,D0‚valid�function�code?�BGT�PROCMERB‚branch�if�no*/�AND.W�#$FF,D0ƒmask�the�offset�of�routine�index"�ASL.W�#1,D0…make�table�compatibleA�MOVE.W�0(A0,D0.W),D0‚relative�distance�between�table�and�routineA�MOVEM.L�D0/D2-D7/A0-A6,-(A7)‚save�everything�except�D1�for�error,�MOVE.L�CCBCHB(A5),A1‚get�base�addr�of�GPIBC)�JSR�0(A0,D0.W)‚initiate�I/O�on�menu�item3�MOVEM.L�(A7)+,D0/D2-D7/A0-A6‚restore�all�registers �TST.B�D1‚set�conditional�return2�BNE‚PROCMERA‚go�to�processor�menu�error�processor*C*…These�previous�menu�item�was�successfully�initiated/completed.�If;*…the�menu�item�was�a�Class�II�or�Class�III�type�(auxiliary5*…command�or�special�function�type)�no�interrupt�will9*…be�generated�so�check�that�here�to�keep�things�rolling.*5�MOVE.L�MENUCPOS(A5),A0ƒget�current�menu�item�pointer/�CMPI.B�#AUXTYPE,(A0)‚was�it�an�auxiliary�type?,�BGE.S�PROCMENA‚yes,�continue�with�next�item*:*‚The�following�is�a�special�case�check�for�the�menu�items9*„DATAXFR�TERM/SEOI.�If�either�processor�was�performed�in7*„the�image�mode�or�performed�in�formatted�mode�with�no>*„EOR�characters�enabled,�then�no�interrupt�will�be�generated.*;�BCLRW�#TERMINT,CSTQOFST(A6)ˆare�we�expecting�an�interrupt?-�BNE.S�PROCMENA•br�=�no,�go�to�next�menu�item*6PROCMRTN�MOVEM.L�(A7)+,D2-D7/A1-A6‚restore�environment RTS  PAGE*>*‚It�has�been�determined�that�we�are�at�the�end�of�the�currentB*‚operation�menu�item�table�or�this�I/O�operation�has�been�HALTED.*8PROCM020�BTSTW�#SRQPROG,BUSACTIV(A5)‚is�SRQ�in�progress?�BNE�PROCM200•yes7�MOVEQ‚#ISTAOK,D1�set�operation�completion�status�to�ok PROCM050 MOVEQ #0,D0+�MOVE.B�DCBCDV(A4),D0‚get�the�device�number1�MOVE.W�D1,-(A7)ˆsave�operation�completion�status9�MOVE.W�DEVQBSY(A5),D1‚D1�<==�current�device�busy�bit�map(�BCLR�D0,D1�clear�that�device's�busy�bit%�MOVE.W�D1,DEVQBSY(A5)‚update�bit�map�MOVE.W�(A7)+,D1ˆrestore�status: BTSTW #HALTED,CSTQOFST(A6) was this operation terminated?�BNE.S�PROCM055Žbr�=�yesH BTSTW #SRQFAIL,CSTQOFST(A6) if an SRQ poll, did the device not respond?�BEQ.S�PROCM060‰br�=�O.K.*5PROCM055�MOVEQ�#ISTATO,D1„else�set�timeout�error�code*2PROCM060 MOVE.B D1,IOSSTA(A3) save status in IOSPB2�MOVE.B�#XPSNRM,D4ƒD4�<==�set�event�type�to�normal�BSR�QEVENT‚send�event�to�IOS/�BTSTW�#SRQWAIT,BUSACTIV(A5)†is�an�SRQ�waiting?�BEQ.S�PROCM100”no*7*‚Overlay�the�current�completed�queue�entry�(operation)1*‚with�dummy�SRQ�processing�information�pointers.* LEA.L CONFINFO(A5),A1J MOVE.L DVDCBPTR(A1),DCBQOFST(A6) set to DCB of the BUS for SRQ processing'�CLR.W�CSTQOFST(A6)ŠInit�command�status-�CLR.L�IPBQOFST(A6)Šclear�dummy�IOSPB�pointer LEA.L SRQBYTE(A5),A16�MOVE.L�A1,PBPAOFST(A6)†set�dummy�input�buffer�address5�MOVE.B�#1,PBLNOFST(A6)†set�dummy�input�buffer�length(�CLR.L�SBPAOFST(A6)Šno�secondary�buffer!'�CLR.W�SBLNOFST(A6)Šand�its�length�is�0 BRA.S PROCSRQA  PAGE*3*ˆENTRY�POINT�FOR�SRQ�PROCESSING�AT�INTERRUPT�LEVEL*?*‚There�is�an�SRQ�request�waiting�to�be�handled�so�initiate�the@*‚status�menu�for�the�first�device�number�connected�to�this�CCB.=*‚Also,�send�an�I/O�complete�event�back�for�previous�function%*‚since�we�got�other�things�to�do�now* PROCMSRQ: +�MOVEM.L�D2-D7/A1-A6,-(A7)…save�environment*>PROCSRQA�MOVE.L�QTAIL(A5),A6ŠA6�<==�ptr�to�current�queue�entry2�BCLRW�#SRQWAIT,BUSACTIV(A5)„take�out�of�wait�mode8�BSETW�#SRQPROG,BUSACTIV(A5)„put�in�SRQ�in�progress�mode3�LEA.L�COND_SP(PC),A0‹A0�<==�serial�poll�menu�table+�MOVE.L�A0,MENU(A5)�set�top�of�menu�pointer=�MOVE.B�CSPDEVNM(A5),D0‰get�device�number�of�last�serial�poll<�MOVE.B�D0,FSPDEVNM(A5)‰set�first�serial�poll�device�#�indexD*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+*�USED�TO�BE�BRA.S�PROCM240ŒS.J.F.�10/10/84D*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>(�BRA.S�PROCM227‘initiate�I/O�on�SRQ�menu* PAGE$PROCM100�BSR�POPGPIBQƒpop�GPIB�queue;�BEQ�PROCMRTN‚branch�if�queue�is�empty�(nothing�else�to�do)*:*‚Set�up�the�necessary�pointers�from�the�queue�information-*‚and�then�build�the�menu�for�the�new�command**�MOVE.L�QTAIL(A5),A6‚get�new�queue�pointer3*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn#*ˆSet�up�registers�before�branching?�MOVE.L�IPBQOFST(A6),A3‚A3�<==�address�of�IOSPB�for�new�command=�MOVE.L�DCBQOFST(A6),A4‚A4�<==�address�of�DCB�for�new�command*6*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>E�BTSTW�#HALTED,CSTQOFST(A6)‚was�this�command�entry�previously�halted?�BNE�PROCM020ƒbranch�if�yes2*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn**ƒThese�moves�done�above�now.*?*MOVE.L�IPBQOFST(A6),A3‚A3�<==�address�of�IOSPB�for�new�command=*MOVE.L�DCBQOFST(A6),A4‚A4�<==�address�of�DCB�for�new�command*8*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*(�BSR�GETCMDP…get�pointer�to�next�command+�BNE�PROCM020„BR�=�invalid�command,�discard4�BSR�VALOPER…validate�operational�mode�and�abilities)�BNE�PROCM020„Error,�invalid�cmd,�discard(�BSR�BUILDMEN„build�menu�for�new�command�BNE�PROCM020„Branch�if�error&�BRA�PROCMENA„initiate�I/O�on�new�menu**‚SRQ�Processing�and�Detection*7PROCM200 BTSTW #HALTED,CSTQOFST(A6) SRQ polling halted?&�BNE.S�PROCM300„br�=�yes,�term�polling+�MOVE.B�SRQBYTE(A5),D1ƒread�the�status�byte*.�BTST�#6,D1ƒis�this�device�requesting�service? BNE.S PROCM400 branch if yes*A*‚Get�next�index�device�number�of�the�next�device�to�serial�poll.?*‚The�technique�used�allows�wraparound�so�that�no�device�on�the:*‚BUS�will�have�a�greater�priority�of�being�serial�polled.*1PROCM220�MOVE.B�CSPDEVNM(A5),D0‚get�current�index2�ADD.B�#1,D0ƒbump�by�one�to�get�next�device�number+�CMPI.B�#MAXDEVNM+1,D0ƒend�of�device�chain?�BNE.S�PROCM225‚not�yet �MOVEQ�#1,D0‚reset�to�device�#�1*I*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<* *‡10/9/84…SJF*A*‡We�will�insert�code�in�here�to�implement�the�concept�of�looping?*‡twice�through�all�devices�on�a�bus�to�locate�the�source�of�an=*‡SRQ.‚This�was�necessary�due�to�devices�pulsing�the�SRQ�line1*‡and�then�missing�true�SRQ's�from�other�devices.*J*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>EPROCM225�MOVE.B‚FSPDEVNM(A5),D2…D2�<--�device�#�we�started�SRQ's�with(�AND.Bƒ#$0F,D2�Mask�out�the�loop�counter5�CMP.BƒD0,D2�Have�we�reached�the�starting�SRQ�device?�BNE.SƒPROCM227ŒNot�yet7�BSET.B‚#7,FSPDEVNM(A5)…Set�the�potemtial�lap�indicator.�BNE.SƒPROCM300ŒBranch�if�we�have�lapped�twice*?PROCM227�MOVE.L�CCBCHB(A5),A1‚A1�<--�base�GPIB�address�of�board.�BTST.B‚#BUSSRQ,BUSSTAT(A1)ƒis�SRQ�still�true?1�BEQ.SƒPROCM300Žbranch�if�not,�exit�SRQ�processes =*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<* *�10/9/84…sjf*+*ˆThis�code�was�replaced�by�the�above�logic*L*PROCM225�CMP.B�FSPDEVNM(A5),D0‚have�we�done�a�complete�turn�around�the�BUS?**�BEQ.S�PROCM300ƒyes,�we�may�have�problems*@*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *-*‚Check�to�see�if�this�device�number�is�valid**PROCM240�ANDI.L�#$FF,D0ƒget�rid�of�garbage4�MOVE.B�D0,CSPDEVNM(A5)ƒupdate�current�device�number /�ASL.L�#3,D0ƒcalc�offset�into�config�info�table5�LEA.L�CONFINFO(A5),A0ƒbase�addr�of�config�info�table6�MOVE.L�DVDCBPTR(A0,D0.L),A4ƒget�pointer�to�device�DCBJ�MOVE.L�CNFIGPTR(A0,D0.L),A0ƒget�ptr�to�current�device�configuration�block MOVE.L A0,D0 set cond codes:�BEQ.S�PROCM220ƒbranch�if�device�not�present�or�configuredF MOVE.L A4,DCBQOFST(A6) save new DCB pointer at current queue locationC�BTSTW�#IOASPOC,IOSATW(A0)‚does�device�have�serial�poll�capability?�BEQ.S�PROCM220ƒbranch�if�no*>�MOVE.L�MENU(A5),MENUNPOS(A5)‚reset�status�menu�pointer�to�top�BRA�PROCMENAƒinitiate�I/O*>PROCM300 BCLRW #SRQPROG,BUSACTIV(A5) clear SRQ in progress bit(�BRA�PROCM100„continue�normal�processing*.*ƒFound�a�device�on�the�bus�requesting�service*5PROCM400�MOVEQ‚#SRQTYPE,D0‚set�event�type�to�SRQ�type�BSR�SENDUEVS‚send�event>*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>* *’10/9/84„sjf*5*ˆThis�logic�is�now�performed�above�after�each�device *ˆis�queried.*-*�MOVE.L�CCBCHB(A5),A1‚get�base�addr�of�GPIBC/*�BTST.B�#BUSSRQ,BUSSTAT(A1)ƒis�SRQ�still�TRUE?7*�BEQ.S�PROCM300‚no,�clean�up�and�continue�normal�oper.*>*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *5*ˆReset�the�lap�indicator�and�the�first�device�polled5*ˆfor�this�next�SRQ�series.�Each�time�an�SRQ�is�found4*ˆwe�must�lap�at�least�twice�to�catch�devices�missed*ˆby�toggling�SRQ's.***<�MOVE.B�CSPDEVNM(A5),D0‚last�device�#�that�was�serial�polled �ADD.B�#1,D0‚start�with�next�one2 CMPI.B #MAXDEVNM+1,D0 should we wraparound first? BNE.S PROCM520 branch if no> MOVEQ #1,D0 set to first device index of configuration blocks*DPROCM520 MOVE.B D0,FSPDEVNM(A5) set start of serial poll index chainA�BRA.S�PROCM227‚start�over�again…***�10/9/84�sjf‚WAS�PROCM240�*****5*‚Process�Menu�entry�point�when�an�error�has�occurred#*‚with�the�reason�fro�error�in�D1.B* PROCMERR:+�MOVEM.L�D2-D7/A1-A6,-(A7)…save�environment*>PROCMERA�MOVE.L�QTAIL(A5),A6ƒA6�<==�ptr�to�current�queue�entry1 BCLRW #SRQPROG,BUSACTIV(A5) was SRQ in progress?4�BEQ�PROCM050ƒbr�=�NO,�terminate�USER�I/O�processing-�BRA�PROCM100ƒelse�pop�SRQ�menu�and�terminate*:PROCMERB�MOVEQ�#ISTADRVE,D1‚set�driver�run-time�error�code% BRA.S PROCMERA go to error processor 8 TTL GPIB DRIVER - INTERRUPT PROCESSOR (MENU PROCESSORS) PAGEE***********************************************************************’MENU�ITEM�COMMAND�PROCESSES*>*ˆThe�following�routines�are�the�individual�menu�item�routinesA*…that�when�combined�make�up�a�menu�for�each�GPIB�function.�TheseE*…menu�items�are�dispatched�by�the�menu�processor�at�either�interrupt;*…level�or�command�level.�All�registers�have�been�preserved?*…before�entering�except�for�D0�and�A0�which�may�always�be�used@*…as�work�registers.�The�following�register�description�entry�is$*…true�for�all�menu�item�processors:*-*’ENTER:‚A1�=�Base�Address�of�GPIBC�registers%*šA3�=�Address�of�IOS�Parameter�Block,*šA4�=�Address�of�Device�Control�Block�(DCB)-*šA5�=�Address�of�Channel�Control�Block�(CCB)1*šA6�=�Address�of�User's�Task�Control�Block�(TCB)* *’EXIT:ƒIf�D1�=�0…THENƒNo�errors*œELSE�D1�=�error�code9*�Note:�The�INITIO�processor�has�saved�all�registers�upon)*”entry�so�all�registers�are�free�to�use.*G*********************************************************************** ! TTL CLASS I MENU ITEM PROCESSORS PAGEF************************************************************************ˆCLASS�I�MENU�ITEM�PROCESSORS*1*’This�class�of�menu�items�initiate�various�types>*ˆof�I/O�in�both�DMA�and�non-DMA�modes.�All�class�I�menu�items-*ˆwill�generate�an�interrupt�after�execution.*F********************************************************************** **ˆPROCESSOR:�Write�Data*:*ˆPURPOSE:�To�setup�the�write�request�according�to�the�IOS0*‘options,�set�up�the�DMA�registers,�and�then�to*‘initiate�the�I/O.* WRITDATA: 9 MOVEQ #1<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>& MOVE.B D2,UNICMD(A1) initiate the I/O*3WRITD025�MOVEQ‚#ISTAOK,D1�set�return�status�to�O.K.*WRITDRTN�RTS…exit�write�data*<*ˆSpecial�processing�for�DMA�transfer�of�only�1�byte�(either&*ˆdata�or�termination�char.�sequence).*HWRITD030 BSETW #TERMINT,CSTQOFST(A6) let PROCMENU know no intrp expected‰BRA.S�WRITD025Žtake�good�exit**‚Write�Formatted�Mode;*ˆSince�DMA�write�requests�are�transfered�directly�from�the;*ˆusers�buffer,�and�Write�Formatted�EOR�characteristics�(if8*ˆenabled)�will�be�sent�out�by�the�termination�processor'*ˆupon�completion�of�this�DMA�transfer.*>WRITDFMT�MOVE.B�WEORFMT(A2),D1‚get�EOR�req�for�Write�Formatted2�BTST.L�#FIXTERM,D1‚fixed�length�transfer�enabled?�BEQ.S�WRITD060„branch�if�noF MOVE.W IOSFBWF(A2),D0 yes change transfer length to fixed requirement*G*ƒIf�any�of�the�CR,�LF,�or�EOS�characters�are�enabled,�EOI�(if�enabled);*ƒmust�be�held�off�for�this�transfer�and�transmitted�by�the*ƒtermination�processor.*WRITD060 MOVE.B D1,D37 AND.B #1<*„terminate�on�the�highest�priority�terminator�with�EOS�having:*„the�highest�priority�followed�by�LF�and�CR�respectively.*0READ115�MOVEQ�#0,D2Šclear�DMA�operation�register#�BTST.L�#EOSTERM,D1Šis�EOS�enabled?�BEQ.S�READD060�branch�if�no; MOVE.B IOSEOSR(A2),EOSCOMP(A1) yes, set EOS read character+�BRA.S�READD080�and�bypass�CR/LF�EOS�checks)READD060�BTST.L�#LFTERM,D1‚is�LF�enabled?�BEQ.S�READD070�branch�if�no1�MOVE.B�#LF,EOSCOMP(A1)…yes,�set�LF�as�terminator'�BRA.S�READD080�and�bypass�CR�EOS�check)READD070�BTST.L�#CRTERM,D1ƒis�CR�enabled?6*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn*=*ˆFix�so�that�read�will�terminate�on�fixed�length�data�input. *ˆInserted�READD090�label�below.**BEQ.S�READD020�branch�if�no BEQ.S READD090*?*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>1�MOVE.B�#CR,EOSCOMP(A1)…yes,�set�CR�as�terminator@READD080�BSET.L�#EOSBIT,D2‚enable�EOS�detection�for�DMA�transfer2READD090�BTST.L�#FIXTERM,D1‰fixed�length�transfer?�BEQ.S�READD020�branch�if�no1�TST.W�D3“did�user�really�specify�a�fixed�length?3�BEQ.S�READD020�br�=�no,�use�IOSPB�specified�length;�CMP.W�D0,D3‘compare�user's�real�buffer�length�to�DEVICE'S!8�BGE.S�READD011Žbr�=�user's�buffer�size�.GE.�to�device's4�MOVEQ‚#ISTAADD,D1Šbr�=�his�buffer�is�not�big�enough�BRA.S�READDRTNŽabort*BREADD011�MOVE.W�D3,D0ˆset�up�DMA�for�device's�fixed�length�record!4READD020:�BSR�SETUPDMA†set�up�DMA�byte�count�and�MAR+�MOVE.B�#LON1,AUXCMD(A1)…set�up�Listen�mode .�BSET.L�#DMAWRITE,D2ˆenable�DMA�write�commmand6�BCLRW�#BIBIT,TMSMASK(A5)ƒdisable�BI�interrupts�on�DMA7�MOVE.W�TMSMASK(A5),D1†reset�interrupt�mask�on�TMS9914A MOVEP.W D1,INTR0(A1)*�MOVE.B�#GTS,AUXCMD(A1)…lower�the�ATN�lineB*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<* *ˆ4/24/84ƒbwn*9*ˆMust�inhibit�TMS9914A‚interrupts‚during�DMA�operations.*2�BCLR.B�#VBIMENAB,CONTREG0(A1)‚disable�9914�intrps*?*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>&�MOVE.B�D2,UNICMD(A1)‡initiate�the�I/O+�MOVEQ‚#ISTAOK,D1Šset�return�status�to�O.K.READDRTN�RTS�exit�read�data PAGE(*ˆPROCESSOR:�Send�Termination�Characters*6*ˆPURPOSE:�This�processor�will�send�the�EOR�characters,*‘in�DMA�mode�to�complete�the�previous�write*‘formatted�transfer.* SENDTERM:%�MOVE.W�IOSOPT(A3),D1‚get�IOS�options.�AND.W�#IOPIMG,D1‚data�transfer�in�image�mode?>�BNE.S�SENDTRM9ƒbranch�if�yes�(no�EOS�characters�in�this�mode)*3�BSR�GETCNFIGƒget�ptr�to�current�configuration�dataB MOVE.B WEORFMT(A0),D1 get EOR characteristics for Write Formatted$ MOVE.B IOSEOSW(A0),D2 get EOS char.7�LEA.L�TERMBUF(A5),A0‚A0�<==�termination�buffer�pointer*?*ƒOnce�again,�just�as�in�the�read�processor,�the�EOR�characters8*ƒmay�be�multiply�set�and�are�software�priority�encoded.>*ƒIf�enabled,�the�CR�character�will�be�sent�out�first�followed1*ƒby�the�LF�character�and�then�the�EOS�character.** MOVEQ #0,D0 reset EOS string byte counter+�BTST.L�#CRTERM,D1ƒis�CR�character�enabled?�BEQ.S�SENDTRM2„branch�if�no0�MOVE.B�#CR,(A0)+‚store�CR�in�termination�buffer�ADDQ.L�#1,D0ˆbump�byte�count*3SENDTRM2�BTST.L�#LFTERM,D1ƒis�LF�character�enabled?�BEQ.S�SENDTRM4„branch�if�no?�MOVE.B�#LF,(A0)+‚yes,�store�LF�character�in�termination�buffer�ADDQ.L�#1,D0ˆbump�byte�count*;SENDTRM4�BTST.L�#EOSTERM,D1‚is�write�EOS�character�enabled?�BEQ.S�SENDTRM8„branch�if�no:�MOVE.B�D2,(A0)+ƒstore�EOS�character�in�termination�buffer�ADDQ.L�#1,D0ˆbump�count*1SENDTRM5 MOVEQ #0,D2 initialize DMA transfer type �SUB.L�D0,A0‡set�start�of�buffer*0*ˆSet�up�for�data�xfer:‰A0�<--�terminator�string*¦D0�=ƒstring�length*¦D1�=ƒEOR�options*¦D2�=ƒDMA�command*,�BRA�WRITD010†do�the�terminator�string�write*(SENDTRM8�TST.L�D0‚any�EOS�char.�to�send? BNE.S SENDTRM5*?SENDTRM9 BSETW #TERMINT,CSTQOFST(A6) set no interrupt expected!+�MOVEQ‚#ISTAOK,D1�set�return�status�to�O.K.)�RTS„exit�termination�character�processor  PAGE***ˆPROCESSOR:�Send�EOI*<*ˆPURPOSE:ƒSends�the�last�character�of�a�data�(OUT)�transfer3*“with�the�EOI�line�True�(uses�TMS9914�EOI�control)**SENDEOI:)�BSR�GETCNFIG�get�pointer�to�config.�data2�MOVE.B�WEORFMT(A0),D1‡get�Write�Formatted�options MOVE.W IOSOPT(A3),D0.�AND.W�#IOPIMG,D0Œwas�data�xfer�in�Image�mode?.�BEQ.S�SENDEOI2Žbr�=�NO,�use�Formatted�options*.�MOVE.B�WEORIMG(A0),D1‡get�Write�Image�options*ASENDEOI2�BTST�#EOITERM,D1„do�we�need�to�send�last�char.�with�EOI?�BEQ.S�SENDEOI4Žbr�=�no,�exit*-*ƒSend�the�last�data�byte�of�the�string�(DMA)*B�MOVE.B�#FEOI,AUXCMD(A1)…set�TMS9914�to�send�EOI�coincident�w/data;�MOVE.B�#$FE,BCNTLSB(A1)…set�up�BCR�to�1's�compl.�of�1�byteF�MOVE.B�#$FF,BCNTMSB(A1)…THE�MAR�IS�STILL�SET�FROM�PREVIOUS�XFER!!!!!!#�MOVEQ�#0,D2‘set�up�for�data�output(�BRA�WRITD022�go�do�the�output�operation*LSENDEOI4 BSETW #TERMINT,CSTQOFST(A6) set no intrp expected flag for PROCMENU>�BTSTW�#CAC_S,BUSACTIV(A5)ƒNo�more�output�is�to�take�place,�so?�BEQ.S�SENDEOI5Žif�we�are�a�Controller,�take�control�of�the�BUSH�MOVE.B�#TCA,AUXCMD(A1)†NOW!�cause�it�won't�be�done�at�normal�intrp�time*SENDEOI5 MOVEQ #ISTAOK,D1 RTS ‰PAGE*ˆPROCESSOR:�Untalk‚(UNT)*:*ˆPURPOSE:�To�send�the�universal�UNTALK�command�out�on�the*‘BUS�with�the�ATN�line�true.*SENDUNT:&�MOVE.B�#UNT_CMD,D1‚set�Untalk�command!�BRA�COMOUT…send�out�command�byte **ˆPROCESSOR:�Unlisten‚(UNL)*<*ˆPURPOSE:�To�send�the�universal�UNLISTEN�command�out�on�the *‘BUS�with�the�ATN�line�true.*SENDUNL:(�MOVE.B�#UNL_CMD,D1‚set�Unlisten�command!�BRA�COMOUT…send�out�command�byte *'*ˆPROCESSOR:�Listen�Address�Group�(LAG)*;*ˆPURPOSE:�To�send�the�primary�listen�address�of�the�device1*‘specified�in�the�LUN�parameter�of�the�IOSPB�out#*‘on�the�BUS�with�the�ATN�line�true*SENDLAG:3�BSR�GETPADDR‚get�the�primary�address�of�the�device/�OR.B�#$20,D1ˆconvert�to�primary�listen�address!�BRA�COMOUT…send�out�command�byte *%*ˆPROCESSOR:�Other�Talk�Address�(OTA)*9*ˆPURPOSE:�To�send�the�primary�talk�address�of�the�device1*‘specified�in�the�LUN�parameter�of�the�IOSPB�out#*‘on�the�BUS�with�the�ATN�line�true*SENDOTA:K MOVE.B #TON0,AUXCMD(A1) UNTALK the GPIB, send aux command talk only (cs=0)3�BSR�GETPADDR‚get�the�primary�address�of�the�device-�OR.B�#$40,D1ƒconvert�to�primary�talk�address!�BRA�COMOUT…send�out�command�byte ***ˆPROCESSOR:�Other�Secondary�Address�(OSA)*9*ˆPURPOSE:�To�send�the�secondary�address�specified�in�the.*‘secondary�address�parameter�of�the�IOSPB�out$*‘on�the�BUS�with�the�ATN�line�true.*SENDOSA:5�MOVE.B�IOSSAD-1(A3),D1‚get�desired�secondary�address �AND.B�#$1F,D1ƒmask�address�bits8 OR.B #PPE_CMD,D1 set into secondary address group range!�BRA�COMOUT…send�out�command�byte *,*ˆPROCESSOR:�Parallel�Poll�Unconfigure�(PPU)*:*ˆPURPOSE:�To�send�the�universal�parallel�poll�unconfigure1*‘command�out�on�the�BUS�with�the�ATN�line�true.t*SENDPPU:I�LEA.L�CONFINFO(A5),A0‚A0�<==�start�of�configuration�area�for�all�devices*;*‚Reset�the�current�parallel�poll�configuration�of�the�BUS.*0�MOVE.L�CNFIGPTR(A0),A2‚A2�<==�cnfig�ptr�for�BUS6�BSET.B�#PPIS,IOSPOLC(A2)‚set�Parallel�Poll�Idle�State> MOVE.B #0,PARLPOLL(A1) clear the GPIBC parallel poll register#�MOVE.B�#PPU_CMD,D1‚set�PPU�command+�BRA�COMOUTƒsend�the�command�out�on�the�BUS *'*ˆPROCESSOR:�Parallel�Poll�Enable�(PPE)*:*ˆPURPOSE:�To�send�parallel�poll�configuration�information3*‘(PPP�and�S�bits�set�up�in�PPE�parameter�of�IOSPB)*‘out�on�the�BUS.*SENDPPE:1�MOVE.B�IOSSAD-1(A3),D1‚get�PP�configuration�info"�AND.B�#$0F,D1†mask�PPP�and�S�bits*8*‚Set�the�parallel�poll�configuration�register�to�active *ˆand�set�the�new�configuration.*9�BSR�GETCNFIGƒA0�<==�ptr�to�configuration�area�for�device8�MOVE.B�D1,IOSPOLC(A0)‚save�in�device�configuration�area*3�OR.B�#PPE_CMD,D1„encode�bits�to�make�a�PPE�command+�BRA�COMOUT…send�out�command�byte�to�device ***ˆPROCESSOR:�Parallel�Poll�Configure�(PPC)*8*ˆPURPOSE:�To�send�the�universal�parallel�poll�configure0*‘command�out�on�the�BUS�with�the�ATN�line�true.*SENDPPC:*�MOVE.B�#PPC_CMD,D1‚set�up�the�PPC�command!�BRA�COMOUT…send�out�command�byte *(*ˆPROCESSOR:�Parallel�Poll�Disable�(PPD)*6*ˆPURPOSE:�To�send�the�universal�parallel�poll�disable0*‘command�out�on�the�BUS�with�the�ATN�line�true.*SENDPPD:*�MOVE.B�#PPD_CMD,D1‚set�up�the�PPD�command!�BRA�COMOUT…send�out�command�byte *%*ˆPROCESSOR:�Serial�Poll�Enable�(SPE)*3*ˆPURPOSE:�To�send�the�universal�serial�poll�enable0*‘command�out�on�the�BUS�with�the�ATN�line�true.*SENDSPE:*�MOVE.B�#SPE_CMD,D1‚set�up�the�SPE�command!�BRA�COMOUT…send�out�command�byte *&*ˆPROCESSOR:�Serial�Poll�Disable�(SPD)*4*ˆPURPOSE:�To�send�the�universal�serial�poll�disable0*‘command�out�on�the�BUS�with�the�ATN�line�true.*SENDSPD:*�MOVE.B�#SPD_CMD,D1‚set�up�the�SPD�command!�BRA�COMOUT…send�out�command�byte *$*ˆPROCESSOR:�Clear�All�Devices�(DCL)*5*ˆPURPOSE:�To�send�the�universal�device�clear�command(*‘out�on�the�BUS�with�the�ATN�line�true.*SENDDCL:*�MOVE.B�#DCL_CMD,D1‚set�up�the�DCL�command!�BRA�COMOUT…send�out�command�byte * *ˆPROCESSOR:�Local�Lockout�(LLO)*6*ˆPURPOSE:�To�send�the�universal�local�lockout�command(*‘out�on�the�BUS�with�the�ATN�line�true.*SENDLLO:*�MOVE.B�#LLO_CMD,D1‚set�up�the�LLO�command!�BRA�COMOUT…send�out�command�byte **ˆPROCESSOR:�Take�Control�(TCT)* 5*ˆPURPOSE:�To�send�the�addressed�take�control�command(*‘out�on�the�BUS�with�the�ATN�line�true.*SENDTCT:*�MOVE.B�#TCT_CMD,D1‚set�up�the�TCT�command!�BRA�COMOUT…send�out�command�byte *)*ˆPROCESSOR:�Selective�Device�Clear�(SDC)*7*ˆPURPOSE:�To�send�the�addressed�selective�device�clear/*‘command�out�on�the�BUS�with�the�ATN�line�true*‘to�all�current�listeners.*SENDSDC:*�MOVE.B�#SDC_CMD,D1‚set�up�the�SDC�command!�BRA�COMOUT…send�out�command�byte **ˆPROCESSOR:�Go�To�Local�(GTL)*4*ˆPURPOSE:�To�send�the�universal�go�to�local�command(*‘out�on�the�BUS�with�the�ATN�line�true.*SENDGTL:*�MOVE.B�#GTL_CMD,D1‚set�up�the�GTL�command!�BRA�COMOUT…send�out�command�byte *(*ˆPROCESSOR:�Group�Execute�Trigger�(GET)*6*ˆPURPOSE:�To�send�the�universal�group�execute�trigger0*‘command�out�on�the�BUS�with�the�ATN�line�true.*SENDGET:*�MOVE.B�#GET_CMD,D1‚set�up�the�GET�command!�BRA�COMOUT…send�out�command�byte *)*ˆPROCESSOR:�Read�Serial�Poll�status�byte*0*ˆPURPOSE:�This�processor�is�part�of�the�COND_SP)*‘(Conduct�Serial�Poll)�menu.�Its�purpose+*‘is�to�set�up�for�Byte-In�interrupt‚to�get!*‘the�status�byte�desired�device.*READSP:)�BSR�MTFIFO’clear�the�FIFO�(VME-300�bug!)3�MOVEM.L�D0-D7/A0-A6,-(A7)ƒsave�regs�on�Trap�0�call1�LEA�SP_TO(PC),A0Œset�PAT�for�serial�poll�timeout"�MOVE.L�#1000,A1�wait�for�1�second MOVEQ #0,D1E�MOVE.B�CCBISR(A5),D1ˆget�intrp�level�from�high�byte�of�CCB�S.R.�word�AND.B�#$0F,D1�mask�off�garbage)�MOVE.L�A5,D2�set�CCB�address�as�PAT�I.D.�TR0$.RQPA�,‘start�timer�BRA.S�READSP1�br�=�timer�going*#�TR0$.KILLER�,�else�bomb�the�system !READSP1 MOVEM.L (A7)+,D0-D7/A0-A6/ BSETW #SPTIMER,BUSACTIV(A5) mark timer running4�MOVE.B�#LON1,AUXCMD(A1)…set�up�to�read�SP�data�byte3�MOVE.B�#GTS,AUXCMD(A1)†Drop�ATN�to�let�him�send�it#�MOVEQ�#ISTAOK,D1Œset�return�status RTS  PAGE .*ˆSerial�Poll�Read�Status�Byte�Timeout�Routine*=*ˆIf�a�user�has�requested�the�serial�poll�function,�a�timeout=*ˆerror�status�will�be�returned.‚Else�if�the�timeout�occurred;*ˆas�a�result�of�the�driver�polling�a�device�in�response�to<*ˆan�SRQ�interrupt,�the�Serial�Poll�status�byte�(in�the�CCB)<*ˆwill�be�set�to�zero�and�the�current�device�will�be�skipped*ˆin�the�polling�sequence.*+SP_TO:ƒMOVEM.L�A3-A5,-(A7)‹save�immed.�regs‰MOVE.L�D1,A5’set�CCB�pointer‰MOVE.L�QTAIL(A5),A07‰CMPA.L�QHEAD(A5),A0‹is�there�an�operation�in�progress?/‰BEQ.S�SP_TO2’br�=�no,�must�have�been�cancelled9‰BCLRW�#SPTIMER,BUSACTIV(A5)ƒwas�timer�already�cancelled?‰BEQ.S�SP_TO2’br�=�yes,�ignore*1*ˆSet�up�registers�to�look�like�VME-300�interrupt*"‰MOVE.L�DCBQOFST(A0),A4ˆA4�<--�DCB#‰MOVE.L�IPBQOFST(A0),A3ˆA3�<--�IOPB+‰MOVE.L�CCBCHB(A5),A1ŠA1�=�hardware�address<‰MOVE.B�#TCS,AUXCMD(A1)ˆtake�control�of�BUS�now,�since�there)‰MOVE.B�DATAIO(A1),D1Šis�no�intrp�coming!)‰BTSTW�#SRQPROG,BUSACTIV(A5)ƒSRQ�polling?‰BNE.S�SP_TO1’br�=�no,�user�I/O;‰BSETW�#SRQFAIL,CSTQOFST(A0)ƒmark�SRQ�poll�response�failure*SP_TO1ƒCLR.B�SRQBYTE(A5)�reset�status�byte3‰BSR�PROCMENU’and�process�as�normal�status�response'SP_TO2ƒMOVEM.L�(A7)+,A3-A5‹restore�regs‰RTE*?*ˆRoutine�to�cancel‚the�currently�running�Serial�Poll�I/O�timer* KILLSPTO:5‰BCLRW�#SPTIMER,BUSACTIV(A5)ƒclear�timer�running�flag3‰MOVEM.L�D0-D7/A0-A6,-(A7)…save�regs�on�Trap�0�call.‰LEA�SP_TO(PC),A0Žset�up�parms�to�cancel�timer‰SUBA.L�A1,A1’interval‰MOVE.L�A5,D2’set�CCB�I.D.1‰MOVE.B�CCBISR(A5),D1Šget�intrp�level�for�request#‰AND.L�#$0F,D1‘clear�excess�garbage(‰OR.L�#$8000,D1�options�=�cancel�request‰TR0$.RQPA�,“go�cancel$‰BRA.S�KILLSP1‘br�=�request�accepted$‰TR0$.KILLER�,‘else�crash�the�system*.KILLSP1‚MOVEM.L�(A7)+,D0-D7/A0-A6…restore�regs‰RTS  PAGE*1*ˆPROCESSOR:�Send�Auxiliary�Command�Buffer�String*4*ˆPURPOSE:�This�general�processor�will�simply�output-*‘what�ever�is�in�the�users�auxiliary�command+*‘string�buffer�out�on�the�BUS�with�the�ATN *‘line�true.* SENDAUXS:8�BSR�GETXFRAD‹get�physical�I/O�address�for�this�function ,�MOVE.L�D6,A0‹A0�<==�starting�buffer�address1 MOVE.L D5,CMDCOUNT(A5) set command string length+�MOVE.B�(A0)+,D1Špreload�first�command�byte?�MOVE.L�A0,CMDBFPTR(A5)‚set�command�buffer�pointer�to�next�byte�BRA�COMCMD�send�command  " TTL CLASS I MENU ITEM SUBROUTINES PAGE**‚TLPROC*&*ˆTALKER/LISTENER�WRITE/READ�PROCESSOR*6*ˆThe�purpose�of�this�routine�is�to�determine�if�it�is9*ˆO.K.�to�initiate�the�current�Read/Write�command�at�this1*ˆtime.‚If�not,�the�current�operation�will�set�up%*ˆa�Task�level�I/O�operation�pending.*.*’ENTER:‚D0.B�=‚type�of�operation�-�Read/Write#*šA1�=�base�addr�of�GPIBC�registers'*šA3�=�address�of�IOCB�for�this�request*šA5�=�address�of�CCB*:*’EXIT:‚IF�CC�then�O.K.�to�initiate�I/O�(D0.b�=�don'�care)*™ELSE�(IF�CS�AND�D1�=�0)2*œTHEN‚task�waiting�for�controller�to�make�request$*™ELSE�(IF�CS�AND�D1.B�=�error�code)*œTHEN�command�is�aborted* *’Register�Usageƒ0�1�2�3�4�5�6�7 *¡D�*�R�*�**¡A*TLPROC:5�BTSTW�#CAC_S,BUSACTIV(A5)„is�BUS�in�controller�mode?+�BNE.S�TLP20‘br�=�yes,�O.K.�to�initiate�I/O*=�BTSTW�#BUSIOP,BUSACTIV(A5)ƒis�there�INTRP�level�I/O�pending?6�BNE.S�TLP10‘br�=�yes,�go�check�for�matching�operation*6�MOVE.B�D0,IOPEND(A5)ˆelse�mark�Task�level�I/O�pendingD�MOVE.L�MENUCPOS(A5),MENUNPOS(A5)‚back�up�menu�pointer�to�re-execute(�MOVEQ�#ISTAOK,D1Œset�return�code�=�O.K. �BRA.S�TLP40‘and�exit�with�C�=�1*>TLP10�MOVE.B�IOPEND(A5),D2ƒD2�=�INTRP�level�I/O�pending�status MOVE.B D0,D11�AND.B�D2,D1‘D1�=�INTRP�^�TASK�I/O�pending�status1�BEQ.S�TLP30‘br�=�operation�type�mismatch�-�error*/�BTST�#SECONDAR,D2‹secondary�address�operation?*�BEQ.S�TLP20‘br�=�no,�O.K.�to�initiate�I/O* MOVEQ #SECMASK,D3 MOVE.B IOSSAD-1(A3),D1-�AND.B�D3,D1‘D1�=�task�requested�sec.�address0�AND.B�D2,D3‘D3�=�INTRP�level�pending�sec.�addr.�CMP.B�D1,D3‘are�they�the�same?4�BNE.S�TLP30‘br�=�no,�go�kill�task�requested�command*,TLP20�BSR�MTFIFO�O.K.�to�init.�I/O!�LET'S�GO'�BNE.S�TLP40‘oops,�hardware�malfunction*6�CLR.B�IOPEND(A5)Œclear�INTRP�level�I/O�pending�status/�BCLRW�#BUSIOP,BUSACTIV(A5)ƒand�associated�flag&�MOVEQ�#ISTAOK,D1Œset�return�code�O.K.�ANDI�#$FE,CCR�clear�Carry�bit RTS*'TLP30�MOVEQ�#ISTAIRPI,D1…set�error�code* TLP40�ORI�#$01,CCR‹set�Carry�bit RTS  PAGE* *ƒSETUPDMA*>*‡This�routine�is�used�by�the�READDATA,�WRITDATA,�and�SENDTERM<*„processors�to�set�up�the�memory�address�register�(MAR)�andA*„the�byte�count�register�(BCR)�on�the�MVME300�card.�These�simply8*„set�up�the�DMA�transfer�registers�but�initiate�no�I/O.*-*ˆENTER:‚A1�=�base�address�of�GPIBC�registers,*�A0�=�buffer�address�to�read/write�to/from."*�D0�=�number�of�bytes�to�transfer*!*ˆRegister�Usage:†0�1�2�3�4�5�6�7*šD‚P*šA‚P* SETUPDMA: MOVE.L D0,-(A7).�NOT.W�D0…convert�byte�count�to�1's�compliment-�MOVE.B�D0,BCNTLSB(A1)‚save�LSB�of�byte�count �LSR.W�#8,D0‡get�next�eigth�bits-�MOVE.B�D0,BCNTMSB(A1)‚save�MSB�of�byte�count*#�MOVE.L�A0,D0†D0�<==�buffer�addressB*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn*8*ˆThe�address�we�get�in�D0�is�the�address�as�seen�by�the *ˆdriver.4*ˆIf�we�are�using�dual�ported�ram‚on�the�VME/10,�and5*ˆif�this�address�is�in�on-board�ram,�then�it�must�be;*ˆtranslated�to�an�on-board�address�as�the�MVME300�sees�it.1*ˆWe�do�this�by�adding�the�RAM_SKEW�offset�to�the%*ˆaddress,�using�the�GO_OFF_BD�macro.* ‰GO_OFF_BD�D0*>*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>%�MOVE.B�D0,MARLSB(A1)‚save�LSB�of�MAR �LSR.L�#8,D0„get�next�eight�bits%�MOVE.B�D0,MARISB(A1)‚save�ISB�of�MAR �LSR.L�#8,D0„get�next�eight�bits%�MOVE.B�D0,MARMSB(A1)‚save�MSB�of�MAR MOVE.L (A7)+,D0 �RTS…exit PAGE**‚COMOUT*7*ˆSince�commands�bytes�(ATN�=�true)�can�not�be�sent�out=*„in�DMA�mode,�this�processor�will�send�out�a�byte�at�a�time.'*„It�assumes�that�the�ATN�line�is�true.*-*ˆENTER:„A1�=�base�address�of�GPIBC�registers*’A5�=�address�of�CCB *’D1.B�=�command�byte�to�be�sent*  ' ED!<):189:A-I5Q4Y.a1iJqMy?�:‰/‘2™:¡=©>±6¹DÁ7É !*ˆRegister�Usage:„0�1�2�3�4�5�6�7*˜D„P‡P*˜A„P*COMOUT:F�MOVE.L�#1,CMDCOUNT(A5)ƒset�command�count�to�1�for�interrupt�processor*C*‚Entry�Point�used�by�the�Command�Out/Data�Out�and�the�Command�Out/*‚Data�In�processors**ƒspace�in�the�CCB�for�new�block�and�storing�new�configuration=*ƒinformation.‚In�actuality,�the�space�for�all�configurations<*ƒattached�to�this�CCB�have�already�been�allocated�and�it�is+*ƒjust�a�matter�of�adjusting�some�pointers.=*‡Since�IOI�is�initiating�this�call,�A1�looks�like�the�user's?*ƒbuffer�but�is�really�apointer�to�the�default�configuration�of *ƒthe�DCB.;*‡The�BUS�activity�flag�(BUSACTV)�is�set�up�at�this�time�to$*ƒindicate�its�initial�startup�mode.*+�MOVE.L�A2,-(A7)‚save�address�of�GPIBC�regs6�LEA.L�CONFINFO(A5),A2‚configuration/DCB�pointer�table MOVEQ #0,D0'�MOVE.B�DCBCDV(A4),D0‚get�device�number"�ASL.L�#3,D0‡calculate�table�index@�MOVE.L�NEXTCNFG(A5),A0‚A0�<==�next�available�configuration�area=�MOVE.L�A0,CNFIGPTR(A2,D0.L)‚set�configuration�ptr�for�device3�MOVE.L�A4,DVDCBPTR(A2,D0.L)„set�DCB�ptr�for�device*I*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*8*ˆ10/16/84‚SET�SERVICE�REQUEST�WAITING�FLAG�TO�CATCH�ANY2*’SRQ'S�PENDING�ON�THE�BUS�AT�TIME�OF�BOOT/STARTUP6*’SINCE�THAT�SRQ�INTERRUPT�WILL�BE�LOST�IN�THE�TMS9914$*’AT�TIME�OF�CHANNEL�INITIALIZATION.*‰BSETW…#SRQWAIT,BUSACTIV(A5)*I*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>J�MOVE.W�IOSVARL+DCBDEV(A4),D0„D0�<==�length�of�variable�configuration�area �BTST�#0,D0…odd�number�of�bytes?�BEQ.S�CDEVA„branch�  if�noB�ADDQ�#1,D0…allocate�in�even�by�amounts�for�addressing�consistency*KCDEVA�LEA.L�IOSILN(A0,D0.W),A2‚calculate�total�length�of�configuration�areaD�MOVE.L�A2,NEXTCNFG(A5)ƒupdate�next�available�configuration�area�ptr.�MOVE.L�(A7)+,A2‚restore�address�of�GPIBC�regs*?*ƒThe�next�check�will�determine�if�the�GPIB�is�being�configured4*ƒwith�system�controller�capabilities.‚If�this�is�so=*ƒthen�the�bus�interface�will�take�control�of�the�BUS�at�this?*ƒpoint.‚Otherwise�its�mode�will�be�set�according�to�the�deviceB*ƒattributes�word�(IOSATW)�passed�in�the�configuration�data�block.E*ƒIf�the�BUS�is�configured�for�Talker/Listener�only,�NO�OTHER�DEVICESI*ƒWILL�BE�ALLOWED�TO�BE�CONFIGURED�AT�SYSTEM�INTIALIZATION�TIME.‚AttemptsG*ƒto�access�these�devices�at�a�later�time�will�cause�a�DEVICE�NOT�READY(*ƒerror�condition�to�be�returned�by�IOS.*&�TST.B�DCBCDV(A4)”configuring�the�BUS?�BNE.S�COMNCNFG”branch�if�no MOVE.L A1,-(A7)9�BSR�RESETIO—correct�for�intrps�to�an�un-attached�channel MOVE.L (A7)+,A1A�BTSTW�#IOASCTC,IOSATW(A1)‰is�BUS�being�config.�with�S.C.�capab�?�BEQ.S�COMNCNFG•branch�if�no*2*ˆElse�test�interface�for�compatible�configuration*:*ˆNOTE!!!‚The�device�will�be�stripped�of�system�controller8*ˆcapabilities�without�notifying�the�caller�on�the�first9*ˆtime�configuration�only.�This�allows�a�successful�first:*ˆtime�configuration�and�will�not�mark�this�device�OFFLINE*ˆupon�return.*.�TST.B�ADDRREG(A2)‘is�MVME300�card�in�SC�mode?�BPL.S�CDEVB—branch�if�yes9�BCLRW�#IOASCTC,IOSATW(A1)‰do�not�allow�S.C.�capabilities BRA.S COMNCNFG*>*ˆSoftware�&�hardware�S.C.�configurations�agree,�TAKE�CONTROL!*CDEVB MOVE.L A1,-(A7)#�MOVE.L�A2,A1•set�up�A1�for�SENDIFC&�BSR�SENDIFC–Take�control�of�BUS,�NOW! MOVE.L (A7)+,A1*/*‚Continue�with�normal�configuration�processing*"*ˆCheck�for�unsupported�attributes*MCOMNCNFG�MOVE.W�#CECUAP,D2ƒpreload�unsupported�attribute/parameter�error�code*3�MOVE.W�#NVALBATM,D0ƒget�mask�of�invalid�attributes8�AND.W�IOSATM(A1),D0ƒtrying�to�change�invalid�attribute?"�BNE�CNFGERR†branch�if�yes�(error)*1�MOVE.W�#NVALBPRM,D0‚get�mask�of�valid�parameters8�AND.W�IOSPRM(A1),D0‚trying�to�change�invalid�parameter?"�BNE�CNFGERR…branch�if�yes�(error)*9*‚Set�the�attributes�into�the�user's�configuration�buffer"*‚that�he�does�not�want�to�change.*0�MOVE.W�IOSATM(A1),D0‚D0�<==�his�attributes�mask;�AND.W�D0,IOSATW(A1)ƒZero�out�the�attributes�of�his�that�he9�NOT.W�D0Ždoesn't�want�to�change,�zero�out�the�attributes=�AND.W�IOSATW(A0),D0ƒof�mine�that�he�does�want�to�change,�and.�OR.W�D0,IOSATW(A1)„combine�them�in�his�space.* *‚Do�the�same�for�the�parameters*3COMN010�MOVEQ�#0,D0ƒbe�sure�upper�16�bits�are�clearK�MOVE.W�IOSPRM(A1),D0‚D0�<==�mask�of�parameters�that�he�does�want�to�change7�MOVEM.L�A0-A2,-(A7)„save�configuration�block�addresses4�LEA.L�IOSREC(A0),A0„A0�<==�addr�of�1st�param�in�CCB@�LEA.L�IOSREC(A1),A1„A1�<==�addr�of�1st�param�in�user�data�block2�LEA.L�PAR_SIZ,A2…A2�<==�addr�of�table�param�sizes*NXTPARM MOVEQ #0,D11�MOVE.B�(A2)+,D1‚get�#�of�bytes�in�next�parameter%�BEQ.S�CHKPARM„branch�if�end�of�table*+�LSR.W�#1,D0…want�to�change�next�parameter?�BCS.S�INCPARMƒbranch�if�yesA�SUBQ�#1,D1†does�not�want�to�change�it�so�move�parameter�from�CCB2*�to�the�user's�buffer�so�that�he�will�have�a�copy)MOVPARM�MOVE.B�(A0)+,(A1)+‚move�next�byte)�DBRA�D1,MOVPARMƒuntil�byte�count�expires'�BRA.S�NXTPARMƒcheck�the�next�parameter*?INCPARM�ADD.L�D1,A0‚he�does�want�to�change�it�so�leave�his�copy4�ADD.L�D1,A1‰alone�and�just�go�to�the�next�parameter BRA NXTPARM*>*ƒCheck�to�see�if�he's�doing�any�configuration�that�is�illegal*:CHKPARM�MOVEM.L�(A7)+,A0-A2‚restore�configuration�pointers=�MOVE.W�#CECIPA,D2‚preload�invalid�primary�address�error�code*2�MOVE.B�IOSPRMA(A1),D0‚get�current�primary�address0�CMP.B�#$1E,D0…valid?�(MUST�BE�0<=�ADDR.�<=�$1E)�BHI�CNFGERR…branch�=‚error*"�TST.B�DCBCDV(A4)‚is�this�the�bus?�BNE.S�CHKPRM2…branch�if�no*=*‚Chec  k�to�see�if�the�primary�address�configured�matches�what-*‚is�set�on�the�switches�of�the�MVME300�card.*C�MOVE.B�ADDRREG(A2),D1ƒD1�<==�primary�addr�read�from�board�switches+�NOT.B�D1‰use�complement�of�switch�register �AND.B�#$1F,D1„mask�primary�addr?�CMP.B�#$1F,D1„is�switch�register�=�$1F�(INVALID�GPIB�ADDRESS!)C�BNE.S�CHKPRM1„BR�=�no,�use�hardware�switch�register�as�BUS�address)�MOVE.B�D0,D1…else�use�SYSGEN�BUS�address*@CHKPRM1�MOVE.B�D1,ADDRREG(A2)‚set�TMS9914A�primary�addr�register, MOVE.B D1,IOSPRMA(A1) update config. buffer9�BTSTW�#IOSPOLCB,IOSPRM(A1)‚local�pp�configuring�the�bus?�BEQ.S�CHKPRM2ƒbranch�if�no*=�MOVE.B�IOSPOLC(A1),D0‚D0�<==�new�parallel�poll�configuration/�BMI.S�CHKPRM2ƒbr�=�no�configuration�set�for�PP;�AND.B�#$1F,D0ƒmask�PPP,�S�and�I�bits,�BUS�is�in�PPSS�state+�MOVE.B�D0,IOSPOLC(A1)‚save�in�users�buffer+�BSR�SETPPREG‚set�up�parallel�poll�register*JCHKPRM2�ANDI.L�#$7FFFFFFF,IOSSAMR(A1)ƒmask�out�bit�31�of�both�the�Read�and<�ANDI.L�#$7FFFFFFF,IOSSAMW(A1)ƒWrite�Secondary�Address�masks*<*‚If�we�make�it�to�here�everything�has�been�validated�and�is:*‚OK�with�the�fixed�portion�of�the�configuration�block.�If<*‚the�user�has�defined�a�variable�configuration�area,�do�the*‚necessary�sequences�for�that.*C�TST.W�IOSVARL+DCBDEV(A4)‚is�there�any�variable�configuration�info?�BEQ.S�OKCNFG†branch�if�no*<�MOVE.W�#CECVARL,D2ƒpreload�variable�config�param�error�code?�MOVE.L�IOSFMTA+DCBDEV(A4),D0ƒget�pointer�to�user�I/O�formatter4�BEQ.S�OKCNFG�branch�=�no�user�defined�I/O�formatter MOVE.L D0,A2A�TST.L�USER_CNF(A2)†is�a�variable�config�parameter�routine�given?�BEQ.S�OKCNFGŽbranch�if�noF MOVEM.L D1-D7/A0-A6,-(A7) save everything except user's return status<�JSR�USER_CNF(A2)‹execute�user�defined�configuration�routine. MOVEM.L (A7)+,D1-D7/A0-A6 restore environment�TST.B�D0�Any�errors?�BNE.S�CNFGERR…branch�if�error*>*‚The�only�thing�that�remains�now�is�sec.�addr.�validation�andD*‚to�update�the�TMS9914A�interrupt�mask�register�to�enable�secondaryI*‚addressing�if�valid�secondary�addresses�were�newly�defined�for�the�BUS.*8OKCNFG�TST.L�IOSSAMR(A1)‚any�sec.�Read�addr's�specified?�SNE�D0“D0�=�Yes/No3�TST.L�IOSSAMW(A1)ˆany�sec.�Write�addr's�specified?�SNE�D1“D1�=�Yes/No$�MOVEQ�#CECSADR,D2ˆpreset�error�code$�EOR.B�D0,D1ŽBoth�must�be�specified! �BNE�CNFGERRŽelse�it�is�an�error*" TST.B DCBCDV(A4) is this the BUS? BNE.S OKCNFG3 br = noB�MOVE.W�TMSMASK(A5),D0‚set�the�current�state�of�the�9914A�mask�reg5 BSET #APTBIT,D0 set up to enable secondary adressing0 TST.L IOSSAMR(A1) any sec read addresses valid?�BNE.S�OKCNFG2ƒbranch�if�yes:�BCLR�#APTBIT,D0ƒelse�disable�secondary�address�interrupts5OKCNFG2�MOVE.W�D0,TMSMASK(A5)‚save�in�mask�status�reg8 MOVEP.W D0,INTR0(A2) update TMS9914A interrupt mask reg*OKCNFG3 MOVEQ #0,D0F�MOVE.W�IOSVARL+DCBDEV(A4),D0„D0�<==�length�of�variable�parameter�area@�ADD.L�#(IOSILN-IOSATW)/2-1,D0ƒadd�in�rest�of�configuration�area*�MOVEM.L�A0/A1,-(A7)ƒsave�start�of�buffers5�LEA.L�IOSATW(A0),A0‚set�pointers�to�start�of�buffers LEA.L IOSATW(A1),A1*?OKCNFG5�MOVE.W�(A1)+,(A0)+‚copy�his�validated�buffer�to�the�CCB#�DBRA�D0,OKCNFG5„configuration�area*5�MOVEM.L�(A7)+,A0/A1ƒrestore�start�of�buffer�pointers.�EXG�A0,A1‰set�A0�=�his�buffer,�A1�=CCB�buffer5�BSR.S�STATYP1…set�up�status�and�configuration�headerF�MOVE.B�#1,DCBCCF(A4)ƒset�flag�indicating�that�a�CONFIGURE�or�a�CHANGE *®DEFAULT�CONFIGURATION�was�done*A*ˆThis�test�is�performed�at�this�time�so�an�initial�configurationC*ˆwill�occur�even�if�there�is�a�S.C.�switch/sysgen�incompatibility.*-�TST.B�DCBCDV(A4)‚are�we�configuring�the�BUS?#�BNE.S�OKCNFG7‚branch�=�not�the�bus*2�EXG�A0,A1ƒset�A0�=�CCB�buffer�and�A1�=�his�buffer4�MOVEQ‚#CECSCE,D2ƒpreload�invalid�S.C.�configurationB�BTSTW�#IOASCTC,IOSATW(A0)‚are�we�configuring�for�S.C.�capability?6 BEQ.S OKCNFG7 branch = no, else test hardware config.9 TST.B ADDRREG(A2) is the MVME300 card switch in SC mode?'�BMI.S�CNFGERR‚branch�=�no  ,�go�to�error*0OKCNFG7�MOVEQ‚#ISTAOK,D1‚set�return�status�to�OK �RTSƒexit*CCNFGERR MOVE.B D2,IOSCEC(A1) save specific configuration error codeB�MOVEQ‚#ISTACNF,D1‚set�invalid�configuration�for�device�error�code(�RTSƒexit�common�configuration�processor  TTL COMMON SUBROUTINES PAGE**‚STATYP*A*ˆThis�routine�is�used�by�CONFIGURE,�CHANGE�DEFAULT�CONFIGURATION;*…and�REQUEST�STATUS�processors�to�store�the�current�status8*…information�in�the�standard�configuration�area�header.*,*ˆENTER:‚A2�=�base�address�of�GPIB�registers*�A4�=�address�of�DCB*�A5�=�address�of�CCB*5*ˆEXIT:ƒA0�=�address�of�configuration�area�for�device*!*‹Register�Usage:ƒ0�1�2�3�4�5�6�7*›D�* *›A�R‡P�P*STATYP:0�BSR.S�GETCNFIGƒA0�<==�current�configuration�ptr*STATYP1: MOVEQ #0,D0"�TST.B�DCBCDV(A4)‰is�this�the�BUS?�BNE.S�STATYP2Œbr�=�no'�MOVE.B�ADDRSTAT(A2),D0ƒget�GPIB�status�AND.B�#$FE,D0Œmask�out�garbage*6STATYP2 MOVE.B D0,IOSDST(A0) put dev. status in buffer9 MOVE.B DCBDEV+IOSCTP(A4),IOSCTP(A0) set the channel type8 MOVE.B DCBDEV+IOSDTP(A4),IOSDTP(A0) set the device type/ MOVE.B #IODGPIB,IOSDRC(A0) set the driver code �RTSƒexit  PAGE* *„SETPPREG*:*ˆThis�subroutine�will�set�or�clear�the�desired�bit�of�the?*…parallel�poll�register�for�when�a�parallel�poll�is�performed.A*…If�both�the�Individual�Status�bit�and�the�Sense�bits�are�equal,>*…the�bit�specified�will�be�set�in�the�parallel�poll�register.8*…otherwise�the�parallel�poll�register�would�be�cleared.*;*ˆThe�PPreg�will�not�be�set�if�the�system�is�in�PPIS�state.**,*ˆENTER:‚A0�=�pointer�to�configuration�table*�A5�=�address�of�CCB**ˆEXIT:ƒno�errors�return*!*‹Register�Usage:ƒ0�1�2�3�4�5�6�7*›D�*ƒ**›AƒP* SETPPREG:!�MOVE.L�A1,-(A7)‚Save�environment MOVEQ #0,D23 MOVE.B IOSPOLC(A0),D0 get current PP configuration3�BMI.S�SETPR025ˆbr�=�In�PPIS�state,�don't�set�PPreg'�BTST�#PPSENSE,D0‚is�the�sense�bit�set?�BNE.S�SETPR020‚branch�if�yes*:*‚The�sense�bit�is�equal�to�zero,�so�the�individual�status8*‚must�also�be�zero�to�set�the�parallel�poll�status�to�1*2�BTST�#INDIVST,D0‚is�the�individual�status�bit�set�BNE.S�SETPR015ƒno*$SETPR010�AND.L�#7,D0‚mask�bit�number'�BSET�D0,D2‚set�to�parallel�poll�status*6SETPR015�MOVE.L�CCBCHB(A5),A1‚A1�<==�ptr�to�GPIBC�regs:�MOVE.B�D2,PARLPOLL(A1)‚store�results�in�Parallel�poll�reg$�MOVE.L�(A7)+,A1ƒrestore�environment SETPR025 RTS*:*‚The�sense�bit�has�been�determine�that�it�is�equal�to�one*7SETPR020�BTST�#INDIVST,D0‚is�individual�status�bit�set?�BNE.S�SETPR010„branch�if�yes�BRA.S�SETPR015„no,�exit PAGE* *ƒGETCNFIG*5*ˆGet�a�pointer�to�the�current�configuration�area�for*…the�desired�device.**ˆENTER:‚A4�=�address�of�DCB*�A5�=�address�of�CCB*5*ˆEXIT:ƒA0�=�address�of�configuration�area�for�device*!*‹Register�Usage:ƒ0�1�2�3�4�5�6�7*›D�* *›A�R‡P�P* GETCNFIG: MOVEQ #0,D0<�MOVE.B�DCBCDV(A4),D0ƒD0�<==�device�number�of�desired�deviceC�LEA.L�CONFINFO(A5),A0ƒA0�<==�base�addr�of�configuration�table�ptrs!�ASL.L�#3,D0‡Two�long�words/entryB�MOVE.L�CNFIGPTR(A0,D0.L),A0‚A0�<==�base�addr�of�config�for�device �RTSƒexit * *ƒGETXFRAD*7*‰This�routine�will�simply�pull�off�the�physical�buffer *‡addresses�from�the�GPIB�queue.**�ENTER:‚A5�=�address�of�CCB*"*�EXIT:‚D4�=�primary�buffer�length*–D5�=�secondary�buffer�length/*–D6�=�physical�addr�of�secondary/config�buffer&*–D7�=�physical�addr�of�primary�buffer*!*‘Register�Usage:„0�1�2�3�4�5�6�7 *¡DŠR�R�R�R*¡A‚** GETXFRAD:.�MOVE.L�QTAIL(A5),A0…get�current�queue�pointer;�MOVE.L�PBPAOFST(A0),D7‚D7�<==�physical�primary�buffer�addrD�MOVE.L�SBPAOFST(A0),D6‚D6�<==�physical�secondary/config�buffer�addr MOVEQ #0,D54�MOVE.W�SBLNOFST(A0),D5‚D5�=�secondary�buffer�length MOVEQ #0,D42�MOVE.W�PBLNOFST(A0),D4‚D4�=�primary�buffer�length �RTS‚exit PAGE****ˆSET�UP�INDEX�(POINTER)�TO�FUNCTION�TABLE*ˆBASED�UPON�IOSPB�FUNCTION**ˆON�ENTRY:�A3�=>�  IOCB*'*ˆON�EXIT:‚D2.W�IS�TABLE�OFFSET�(INDEX)+*’D1.B�&��=�OPERATION�STATUS�(�0�=�O.K)*8*‚Find�the�function�in�the�table�of�valid�GPIB�functions*GETCMDP:!ˆMOVEM.L�A0/D0/D6,-(A7)�save�regs5�MOVE.W�#NUMCMDS-1,D0ƒnumber�of�valid�GPIB�commands-14�LEA.L�IOSCMDTB(PC),A0ƒset�ptr�to�GPIB�command�table1�MOVE.W�IOSFCT(A3),D6ƒpick�up�function�from�IOSPB8�MOVEQ‚#ISTAIF,D1ƒset�invalid�command�error�just�in�case*&GETCMD50�CMP.W�(A0)+,D6ƒfound�command?.�DBEQ�D0,GETCMD50ƒbranch�if�no,�look�some�more*,�BNE.S�GETCMDX„exit�with�error,�end�of�table4�MOVE.W�#NUMCMDS-1,D2ƒcalculate�relative�table�index�SUB.W�D0,D2‚D2�<==�table�index"�ASL.W�#1,D2‚Calculate�word�offset*0�MOVEQ‚#ISTAOK,D1�set�process�O.K.�return�status*GETCMDX TST.B D1 set return condition code$ MOVEM.L (A7)+,A0/D0/D6 restore regs RTS* 6 TTL GPIB DRIVER - COMMON SUBROUTINES (QUEUE HANDLING) PAGE**‚POP�GPIB�QUEUE�ENTRY*6*ˆIf�I/O�is�aborted�or�an�operation�is�completed,�this9*…routine�will�pop�that�operation�from�the�GPIB�queue�and9*…update�the�necessary�queue�pointers.�It�is�assumed�that:*…the�caller�has�previously�inhibited�all�interrupts�since*…this�is�critical�processing.**’ENTER:ƒA5�-�address�of�CCB*#*’EXIT:ƒIF�„THEN‚queue�is�empty)*œELSE‚queue�still�has�at�least�one�entry*!*ŽRegister�Usage:ƒ0�1�2�3�4�5�6�7*žD *žA�*�*‡P* POPGPIBQ:1�LEA.L�GPIBQEND(A5),A0‚A0�<==�ptr�to�end�of�queue.�MOVE.L�QTAIL(A5),A1„get�current�queue�pointer2�CMPA.L�QHEAD(A5),A1„is�there�an�entry�to�POP�off?,�BEQ.S�POPG15ŒBR�=�no,�exit�with�proper�?�ADDA.L�#GPIBQLEN,A1„advance�pointer�by�length�of�a�queue�entry�CMPA.L�A0,A1…at�end�of�queue?�BNE.S�POPG10ƒno*%* time to wrap around to top of queue*5�LEA.L�GPIBQ(A5),A1…set�queue�pointer�to�top�of�queue*APOPG10�MOVE.L�A1,QTAIL(A5)ƒupdate�current�operation�queue�pointer<�CMPA.L�QHEAD(A5),A1ƒset�condition�for�empty/not�empty�queue POPG15 RTS‰PAGE* *ƒPSHGPIBQ*9*ˆThis�routine�is�used�regardless�of�whether�the�queue�is?*…busy�or�not.�It�will�place�in�the�GPIB�queue�all�the�pointers=*…necessary�to�execute�this�command�when�its�time�comes.�LikeD*…the�POPGPIBQ�routine�it�also�assumes�that�the�caller�has�inhibited*…interrupts�before�entering.**’ENTER:‚A3�-�address�of�IOSPB*šA4�-�address�of�DCB*šA5�-�address�of�CCB*šD4�-�primary�buffer�length*šD5�-�secondary�buffer�length&*šD6�-�physical�addr�of�primary�buffer/*šD7�-�physical�addr�of�secondary/config�buffer**’IF�„THENƒno�errors*•ELSE„queue�is�full*!*�Register�Usage:ƒ0�1�2�3�4�5�6�7 * D�*‡P�P�P�P* A�*�PƒP�P�P�P* PSHGPIBQ:!�MOVE.L�A1,-(A7)ƒsave�environment4�LEA.L�GPIBQEND(A5),A1„A1�<==�end�of�GPIB�queue�area4�MOVE.L�QHEAD(A5),A0†A0�<==�next�available�queue�ptr*�CLR.W‚CSTQOFST(A0)†set�entry�status�to�OK+�MOVE.L�A4,DCBQOFST(A0)ƒsave�address�of�DCB6�MOVE.L�A3,IPBQOFST(A0)ƒsave�physical�address�of�IOSPB?�MOVE.L�D7,PBPAOFST(A0)ƒsave�physical�address�of�primary�bufferI�MOVE.L�D6,SBPAOFST(A0)ƒsave�physical�address�of�secondary/config.�buffer2�MOVE.W�D4,PBLNOFST(A0)ƒsave�primary�buffer�length4�MOVE.W�D5,SBLNOFST(A0)ƒsave�secondary�buffer�length;�ADDA.L�#GPIBQLEN,A0„increment�by�length�of�one�queue�entry"�CMPA.L�A1,A0…time�to�wrap�around?�BNE.S�PSHQ010„branch�if�no*0�LEA.L�GPIBQ(A5),A0‚set�ptr�to�top�of�queue�area**PSHQ010�CMPA.L�QTAIL(A5),A0‚is�queue�full?5�BEQ.S�PSHQRTN‚yes,�but�this�should�not�have�happened4 MOVE.L A0,QHEAD(A5) update next available queue ptr4�MOVEQ�#1,D0‚set�condition�code��for�O.K.�return*PSHQRTN�MOVE.L�(A7)+,A1ƒrestore RTSA TTL GPIB DRIVER - COMMON SUBROUTINES (VALIDATE OPERATIONAL MODE) PAGE**‚VALIDATE�OPERATIONAL�MODE*9*ˆThis�routine�will�be�called�at�the�point�when�a�command:*ˆis�about�to�be�scheduled�for�I/O�initiation.�The�purpose;*ˆis�to�determine�if�the�BUS�is�in�the�proper�mode�for�this:*ˆcommand�and�to�determine�if�the�BUS�or�device�(depending:*ˆon�who�this�command�is�directed�to)�has�the�ca  pabilities3*ˆ(if�any�are�necessary)�to�perform�this�operation.*3*’ENTER:‚A3�=�address�of�IOSPB�for�current�function*šA4�=�address�of�the�DCB*šA5�=�address�of�the�CCB%*šD2.W�=�index�of�command�in�VALPARTB*'*’EXIT„D1�=�error�code�(0�if�no�errors)* *�Register�Usage…0�1�2�3�4�5�6�7 *¡D�*�R�*�*�**¡A�**VALOPER:F�LEA.L�VALPARTB(PC),A0ƒA0�<==�base�address�of�command�validation�tableD�MOVE.W�0(A0,D2.W),D4‚D4�<==�bit�map�of�necessary�command�parameters*?�CMP.B�#XDSGDEV,IOSDTP+DCBDEV(A4)‚is�this�command�for�a�device?�BNE.S�VALOP050ƒbranch�if�no*@*‚Since�this�command�is�directed�towards�a�device�and�the�valuesB*‚in�VALPARTB�are�relative�to�the�BUS,�the�READ/WRITE�bits�take�onA*‚the�opposite�meaning�than�they�did�for�the�BUS.‚For�example,�ifB*‚there�is�a�write�command�to�a�device,�the�value�in�VALPARTB�willB*‚indicate�that�the�talker�ability�(VALTALK)�will�be�necessary�forA*‚this�command.‚However,�this�bit�was�set�relative�to�the�BUS.�SoA*‚if�the�write�command�is�directed�to�a�device,�this�requires�theC*‚BUS�to�be�in�the�talker�mode�and�the�device�to�be�in�the�listenerB*‚mode.‚It�is�for�these�reasons�that�the�TALK�and�LISTEN�abilitiesA*‚(VALTALK�and�VALLIST�respectively)�are�exclusive�or'd�with�'11' *‚so�as�to�invert�their�meaning.*B�MOVEQ�#VALTALK+VALLIST,D0‚set�up�specific�capabilities�to�look�at MOVE.B D0,D39�AND.B�D4,D3�D3�=�Talker/Listener�capability�requirements#�BEQ.S�VALOP050�br�=�none,�continue�CMP.B�D0,D3�are�both�required?-�BEQ.S�VALOP050�br�=�yes,�so�no�need�to�alter6�EOR.W�D0,D4�else,�change�meaning�relative�to�a�device*C*ƒNow�that�we�have�the�meaning�of�the�ability�bits�correct�relative;*ƒto�the�command,�check�the�current�attributes�word�for�theB*ƒspecified�device�to�see�if�the�device�or�BUS�is�capable�of�doing*ƒthat�command.*,VALOP050�MOVE.W�D4,D2‡D2�<==�Working�bit�mapH�AND.W�#VALTALK+VALLIST+VALCTL+VALSCTL+VALSRQ,D2‚any�abilities�required?�BEQ.S�VALOP100�branch�if�no8�BSR�GETCNFIG�get�a�pointer�to�user's�configuration�area-�MOVE.W�D2,D3�D3�<==�current�device�abilities5�AND.W�IOSATW(A0),D3ˆmask�abilities�that�are�required;�CMP.B�D2,D3�does�this�device/BUS�have�the�right�abilities.�BNE.S�VALOP250�branch�if�no*C*‚Now�that�the�ability�has�been�verified,�check�to�see�that�the�BUS,*‚is�in�the�necessary�mode�for�this�command.**VALOP100�MOVE.W�D4,D2…save�current�bit�map?�AND.W�#VALTMOD+VALLMOD+VALCMOD+VALBTLM,D2‚any�modes�necessary?�BEQ.S�VALOP500ƒbranch�if�no*3�MOVE.W�BUSACTIV(A5),D0‚D0�<==�current�bus�activity3�CMP.B�#XDSGDEV,IOSDTP+DCBDEV(A4)‚is�this�a�device?�BEQ.S�VALOP200‚branch�if�yes8�BTST�#BVALBTLM,D4‚do�we�need�to�be�in�T/L�mode�for�BUS?�BNE.S�VALOP300‚branch�if�yes*5VALOP200�BTST�#CAC_S,D0ƒis�the�BUS�in�controller�mode/�BNE.S�VALOP500‚branch�if�yes,�everything�is�OK*"*‚ERROR:�A�mode�error�has�occurred*?VALOP250�MOVEQ�#ISTAIVCM,D1ƒset�invalid�command�mode�error�code�BRA.S�VALOPRTNƒexit�with�error*6VALOP300�BTST�#CAC_S,D0‚is�the�BUS�in�controller�mode?F�BNE.S�VALOP250‚branch�if�yes�-�error�-�can(t�be�in�controller�for�cmd*?*‚Since�this�command�is�directed�to�the�BUS,�it�may�require�the>*‚BUS�to�be�either�in�Talker�or�Listener�mode.‚Check�to�see�if>*‚those�modes�are�required�for�this�command�and�if�so�check�to=*‚see�that�the�BUS�is�in�the�appropriate�mode.‚The�proper�T/L>*‚mode�check�is�skipped�if�the�BUS�is�IDLE.‚The�operation�will#*‚subsequently�be�queued�in�TLPROC.*4 AND.W #1<*‚This�check�will�  see�if�a�secondary�address�is�to�be�verified<*‚for�this�command�and�check�against�valid�device�addresses.*?VALOP500�BTST�#BVALSADR,D4ƒcheck�GPIB�device�secondary�address?�BEQ.S�VALOP600ƒbranch�if�no*3 CMP.B #XDSGDEV,IOSDTP+DCBDEV(A4) Is this a device? BEQ.S VALOP520*?�BTSTW�#APTBIT,TMSMASK(A5)‚operating�in�secondary�address�mode?$�BEQ.S�VALOP250‚branch�if�no�(error)*5VALOP520�BSR�GETCNFIG‰get�configuration�ptr�of�deviceD�MOVE.L�IOSSAMR(A0),D2„D2�<==�bit�mask�of�configured�valid�read�S.A./�BTST‚#BVALLIST,D4‚is�this�a�sec�read�function?�BNE.S�VALOP540‚branch�if�yesE�MOVE.L�IOSSAMW(A0),D2ƒD2�<==�bit�mask�of�configured�valid�write�S.A.*DVALOP540‚MOVE.B�IOSSAD-1(A3),D0‚get�S.A.�from�IOSPB�for�this�request@�MOVEQ�#ISTAIVSA,D1‚preload�invalid/unconfigured�S.A.�error�code?�BTST.L�D0,D2„is�this�addr�configured�to�be�valid�in�this�mode?'�BEQ.S�VALOPRTN‚exit�with�error�in�D1.B*NVALOP600 BTST #BVALBCHG,D4 does commmand reequire user to be in charge of BUS?, BEQ.S VALOP700 br = no, all checks complete% MOVEQ #ISTAIVBD,D1 preset error code LEA.L CONFINFO(A5),A0*�MOVE.L�DVDCBPTR(A0),A0‚A0�<---�DCb�of�BUS" TST.L DCBWNT(A0) is the BUS open?/�BEQ.S�VALOPRTNƒbr�=�no,�return�with�error�code*;*‚The�mode�and�device�is�now�capable�of�completing�the�task*/VALOP700�MOVEQ�#ISTAOK,D1„set�return�code�to�OKVALOPRTN�RTS„exit @ TTL GPIB DRIVER - COMMON SUBROUTINES (HALT ALL I/O IN PROGRESS) PAGE*%*•HALT�I/O�TO�BUS�OR�SPECIFIED�DEVICE*>*ˆThis�routine�is�designed�to�halt�all�I/O�that�is�in�progress?*ˆand�any�I/O�that�is�waiting�to�be�executed�on�the�GPIB�queue.=*ˆThis�routine�may�be�envoked�at�interrupt�or�command�levels.>*ˆIf�at�command�level,�a�HALT�command�was�received�directed�to;*ˆthe�BUS.�At�interrupt�level,�a�IFC,�DCL,�or�TCT�interrupt<*ˆwas�encountered.‚These�interrupts�cause�all�pending�I/O�to *ˆbe�aborted.*2*’ENTER:„A4�=�address�of�DCB�for�current�operation*œA5�=�address�of�CCB*)*’EXIT:…If�D1.B�=�0ƒThen�all�entries�were%*œmarked�'Halted'�and�the�appropriate+*œevents�were�sent�for�the�waiting�commands*œon�the�queue.*˜ELSE*œthere�was�no�I/O�to�halt.*!*ŽRegister�Usage:†0�1�2�3�4�5�6�7*ŸDƒ*�R*ŸA‹P�P*HLTALL:+�MOVEM.L�D2-D7/A1-A6,-(A7)ƒsave�environment6�MOVE.L�QTAIL(A5),A6‰A6�<==�ptr�to�current�queue�entry(�CMPA.L�QHEAD(A5),A6‰is�the�queue�empty?+�BEQ�HLTERR’branch�if�yes�(nothing�to�halt)*�BSR�RESETIO‘do�a�soft�reset1�BSR�KILLSPTO�cancel�Serial�Poll�timer�if�running>�LEA.L�GPIBQEND(A5),A0‡A0�<==�address�of�physical�end�of�queue*CHLTALL10�BSETW�#HALTED,CSTQOFST(A6)‚set�this�entry�status�to�halted5�ADDA.L�#GPIBQLEN,A6‰bump�pointer�to�next�queue�entry&�CMPA.L�A6,A0�at�the�end�of�the�queue?�BNE.S�HLTALL20Žbr�=�no6�LEA.L�GPIBQ(A5),A6Šelse�wrap�around�to�start�of�queue*>HLTALL20 CMPA.L QHEAD(A5),A6 at the end of all queued entries?'�BNE.S�HLTALL10Žbranch�if�no�-�continue*< BCLRW #SRQWAIT,BUSACTIV(A5) clear any potential SRQ waiting=�BTSTW�#BUSIOP,BUSACTIV(A5)‚is�the�pending�I/O�interrupt�set?�BNE.S�HLTALL30Žbranch�if�yes-�CLR.B�IOPEND(A5)Œreset�pending�task�I/O�flag*>HLTALL30 MOVE.L QTAIL(A5),A6 A6 <== current operation on queue�MOVE.L�DCBQOFST(A6),A4†get�DCB!�MOVE.L�IPBQOFST(A6),A3†get�IOSPB8�BSR�PROCMENU�clean�up�and�send�halts�to�queued�commands BRA.S HLTOK 4 TTL GPIB DRIVER - COMMON SUBROUTINES (HALT COMMAND) PAGE*6*ˆHalt�I/O�to�a�specific�device�or�the�BUS�in�T/L�mode*HLTCMD:1�MOVE.L�QTAIL(A5),A6ƒget�pointer�to�current�entry(�CMPA.L�QHEAD(A5),A6‰is�the�queue�empty?(�BEQ.S�HLTXIT�br�=�yes�(nothing�to�halt)*+�MOVEM.L�D2-D7/A1-A6,-(A7)ƒsave�environment9*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn**ˆFix�an�OOPS�!#*LEA.L�GPIBQEND,A0‹set�end-of-queue LEA.L GPIBQEND(A5),A0*>*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<**ˆLocate�the�command*1HLTC60 CMPA.L DCBQOFST(A6),A4 is this the device?�BEQ.S�HLTC80�br�=�yes*'�ADD  A.L�#GPIBQLEN,A6‰bump�to�next�entry�CMPA.L�A6,A0�end�of�queue?�BNE.S�HLTC70�br�=�no*0�LEA.L�GPIBQ(A5),A6Šelse�reset�to�start�of�queue*HLTC70�CMPA.L�QHEAD(A5),A6ƒend�of�entries?(�BNE.S�HLTC60�br�=�no,�continue�checking:�BRA.S�HLTERR�entry�not�found,�return�error�to�IOS�request*5HLTC80 BSETW #HALTED,CSTQOFST(A6) mark command halted+�CMPA.L�QTAIL(A5),A6‰is�it�the�current�I/O?�BNE.S�HLTOK‘br�=�no**�BSR�RESETIO‘terminate�any�I/O�in�progress3�MOVE.L�IPBQOFST(A6),A3†set�pointer�to�user's�IOSPB�BSR�PROCMENU�cancel�command0�BTSTW�#BUSIOP,BUSACTIV(A5)‚any�BUS�I/O�pending?�BNE.S�HLTOK‘br�=�yes8�AND.B�#$3F,IOPEND(A5)‡else�clear�pending�task�I/O�FLAGS*3HLTOK�MOVEM.L�(A7)+,D2-D7/A1-A6ƒrestore�environment2HLTXIT�MOVEQ�#ISTAOK,D1†set�good�error�return�code RTS*+HLTERR�MOVE.B�#$FF,D1ˆset�error�return�code.�MOVEM.L�(A7)+,D2-D7/A1-A6ƒrestore�environment RTS 7 TTL GPIB DRIVER - COMMON SUBROUTINES (BUILD NEXT MENU) PAGE**ƒBUILD�NEW�MENU�ITEM*:*ˆThis�routine�will�set�up�all�the�menu�pointers�necessary<*ˆto�execute�the�next�command.�Since�the�command�has�already9*ˆbeen�validated,�if�it�is�not�now�found�in�the�IOSCMDTB,;*ˆthis�routine�will�return�a�run�time�error�code�to�IOS�and*ˆthe�command�will�be�aborted.*3*�ENTER:‚A3�=�address�of�IOSPB�for�current�function*—A5�=�address�of�CCB*!*�Register�Usage:…0�1�2�3�4�5�6�7*žD‚*�* *žA‚*…PƒP* BUILDMEN:6�MOVE.W�IOSFCT(A3),D0ˆextract�current�function�command4�LEA.L�IOSCMDTB(PC),A0‡table�of�valid�GPIB�functions;�MOVE.L�#NUMCMDS-1,D1ˆD1�=�number�of�commands�in�GPIB�table*<*‚Find�the�function�in�the�table�of�available�GPIB�functions*9BUILDM10�CMP.W�(A0)+,D0…compare�to�next�function�in�table�BEQ.S�BUILDM20�found�function?%�DBRA�D1,BUILDM10‹no,�continue�search*=*‚ERROR:�This�is�an�irrecoverable�error�because�this�function9*‰was�validated�previously�and�now�a�match�did�not�occur.(*‰Somebody�overran�the�parameter�buffer.*:BUILDM15�MOVEQ‚#ISTADRVE,D1‚set�driver�run�time�error�code�RTSšexit�with�error*.*‚Match�has�been�found�so�set�up�menu�pointers*JBUILDM20 MOVE.L #NUMCMDS-1,D0 subtract index from total number of commands SUB.L D1,D0�ASL.L�#1,D0�get�word�offset9�LEA.L�CTLCFTBL(PC),A0…table�of�controller�menu�functions3�BTSTW�#CAC_S,BUSACTIV(A5)‚GPIB�in�controller�mode?�BNE.S�BUILDM30Œbranch�if�yesE�LEA.L�TLCFTBL(PC),A0†no,�set�table�of�talker/listener�menu�functions*;BUILDM30�MOVE.W�0(A0,D0.W),D1ƒget�relative�distance�of�menu?�BEQ.S�BUILDM15Šthis�should�never�happen�but�do�this�if�it�doesI�LEA.L�0(A0,D1.W),A0…get�absolute�pointer�to�menu�table�for�this�function+�MOVE.L�A0,MENU(A5)†set�top�of�menu�pointer2�MOVE.L�A0,MENUNPOS(A5)‚set�next�menu�item�pointer�MOVEQ‚#ISTAOK,D1‡good�return �RTS•exit3 TTL GPIB DRIVER - COMMON SUBROUTINES (QUEUE EVENT) PAGED*********************************************************************5*‰QUEUE�A�COMPLETION�EVENT�TO�THE�ATTACHED�TASK�(IOS)*;*‰This�routine�calls�the�exec�to�send�a�small�event�to�IOS.9*‰Uses�QEVNTI�if�we're�processing�an�interrupt�and�QEVNTT*‰if�we're�not.*8*‰NOTE:‚This�routine�is�completely�re-entrant�and�may�be2*�run�at�any�time.‚All�work�is�completely�register3*�oriented.‚All�messages�are�assumed�to�be�10�bytes*�in�length�!!!!!!**‰Entry:�D1.W�=�event�status*�D4.B�=�event�type*�A4�=�address�of�DCB.*�A5�=�address�of�CCB.**‰Exit:‚D0�=�garbage.*�D1�=�garbage.*;*‰The�structure�of�the�event�you�must�supply�is�as�follows:*‹BYTES‚MEANING@*‰*ƒ1„event�length�assuming�no�service�address�(always�10�bytes)4*‰*ƒ1„event�code�(1�if�no�service�address,�else�$81)*�1„event�type*‰*ƒ1„channel�key<*‰*ƒ4„ID�(DCB�address�for�us�since�we're�a�standard�channel)*�2„status�value*@*‰Fields�marked�by�*�are�placed�in�the�event�by�this�routine�and%*‰need�not�be�prepared�by�the�caller.@*‰If�a�service�address�was�specified�for�the�I/O,�it�is�insertedD*‰before�the�event�type�field,�and�event�length�is�u pdate�by�4�bytes>*‰and�the�event�code�will�be�modified�to�indicate�a�completion:*‰service�address�is�present�(MSB�of�event�code�is�a�"1").*J************************************************************************** QEVENT:>ŠMOVEM.L�D2-D7/A0-A6,-(A7)�Save�the�registers�we'll�blow�away.*0*‚Start�setting�those�values�which�never�change.*!ŠMOVE.W�D1,D6’D6�<==�event�statusBŠMOVE.W�#(10*256)+IOEVCD,D2„D2�<==�prepare�event�length/event�code#ŠMOVE.L�A4,D5’D5�<==�address�of�DCB3ŠASL.W�#8,D4“shift�event�type�to�upper�byte�of�word7ŠMOVE.B�CCBKEY(A5),D4ŠSet�the�channel�key�in�lower�byte0ŠAND.L�#$FF,D6‘clear�upper�bytes�of�event�status*C*‚If�there�was�a�service�address�specified,�go�back�and�fix�things.*AŠMOVE.L�CCBSVVC(A5),D3…is�a�completion�service�address�specified?ŠBEQ.S�QEVT010�branch�if�no*-ŠADDI.W�#4*256,D2Šadjust�event�length�for�CSA7ŠMOVE.B�#$80+IOEVCD,D2…adjust�event�code�to�set�CSA�bit***ˆStage�all�registers�for�event�processing*-QEVT010ƒSWAP�D2“stage�event�length/event�codeŠTST.L�D3’any�CSA�specified?ŠBEQ.S�QEVT020�branch�if�no*,*ˆStage�registers�for�event�with�CSA�address*ŠSWAP�D3 ŠMOVE.W�D3,D2 ŠMOVE.W�D4,D3 ŠMOVE.L�D5,D4 ŠMOVE.L�D6,D5ŠSWAP�D5ŠBRA.S�QEVT030*3*ˆStage�all�registers�for�event�with�no�CSA�address*QEVT020ƒMOVE.W�D4,D2 ŠMOVE.L�D5,D3 ŠMOVE.L�D6,D4ŠSWAP�D4 ŠCLR.L�D5*&*‚Do�the�exec�call�to�queue�the�event.*FQEVT030ƒMOVE.L�CCBRQSTA(A5),A0„A0�<--�address�of�TCB�of�attached�task.0ŠMOVEQ‚#T0QEVNTI,D0‡D0�<--�the�QEVNTI�directive.7ŠTST.B‚BINTCNT(A5)ˆIf�we're�not�queueing�the�event�from(ŠIF…�THENŠwithin�the�interrupt�tour,0ŠMOVEQ‚#T0QEVNTT,D0‡D0�<--�the�QEVNTT�directive.ŠENDI–* *ŠTRAPƒ#0‘Call�the�exec�to�queue�the�event. ŠBRA„OKEVENTŒIf�good,�go�return.(ŠTR0$.KILLER�,�If�bad,�crash�the�system. COKEVENTƒMOVEM.L�(A7)+,D2-D7/A0-A6�Restore�the�registers�and�return.ŠRTS—* 4 TTL GPIB DRIVER - INTERRUPT PROCESSING (SEND EVENT) PAGEF*********************************************************************** *‚SENDUEVT*5*ˆThe�purpose�of�this�task‚is�to�send�an�event�to�the9*„user�task�from�the�device�I/O�driver.‚This�task�must�be7*„run�at�interrupt�level�or�else�the�system�will�crash.:*„Currently�there�are�7�reasons�for�this�event�on�the�GPIB>*„and�they�are:�SRQ,�RLC,�DCL,�TCT,�GET,�IFC,�and�I/O�pending.**ˆENTER:‚D0.B�=�event�type*�D1.B�=�event�status3*�A4.L�=�address�of�DCB�of�device�assoc.�with�event*�A5.L�=�address�of�CCB*.*ˆEXIT:ƒevent�was�sent�or�else�system�crashed.* *’Register�Usage‚0�1�2�3�4�5�6�7* D�*�* * A�*‡P�P*9*ˆNOTE:ƒThe�entry�point�SENDUEVS:�is�used�when�a�non-zero6*�event�status�(passed�in�D1.B)�will�be�sent�in�event.%*�Otherwise�use�SENDUEVT�entry�point.*6*ˆNOTE:‚This�routine�will�check�to�see�that�the�device-*�specified�by�the�DCB�pointer�is�open�before0*�trying�to�send�the�event.‚If�the�device�is�not1*�open,�an�attempt�will�be�made�to�send�the�event.*�to�the�BUS.‚If�the�BUS�is�not�open�the�event*�will�be�discarded.*C******************************************************************* SENDUEVT:&�MOVEQ�#0,D1‰preload�zero�event�status*DSENDUEVS: MOVEM.L D2-D7/A0-A6,-(A7) save regs that may get destroyed6�TST.B‚BINTCNT(A5)ƒmake�sure�we�are�at�interrupt�levelB�BEQ.S‚SENDUEOK†br�=�no,�fatal�error!�BUT�DON'T�CRASH,�just�ignore; MOVE.L DCBAID(A4),A2 A2 = DCB I.D. of event causing device*9SENDUE05 TST.L DCBTSK(A4) is this device claiming Events?/�BNE.S�SENDUE07‹branch�=�yes,�go�send�the�event1�TST.B�DCBCDV(A4)‰is�this�device�already�the�BUS?3�BEQ.S�SENDUEOK�br�=�yes,�then�throw�the�event�away)�MOVE.L�DCBSUP(A4),A4‡else�go�try�the�BUS�BRA.S�SENDUE05Žgo�try�again!*7SENDUE07�ASL.W�#8,D0‡put�Async�event�type�in�high�byte,&�MOVE.B�D1,D0†add�in�event�status�byte�MOVE.W�D0,-(A7)ƒsave�on�stack/�MOVE.L�A2,-(A7)ƒsave�device�I.D.�data�on�stackK MOVE.W #(AILNG*256)+AIEVCD,-(A7) PUSH event length + Async event type code*.�MOVE.L�DCBSES(A4),D1‚D1�=�tas k�session�number$�MOVE.L�DCBTSK(A4),A0‚A0�=�task�name.�MOVEQ�#13,D0†Call�'GTXTCB'�for�the�right�info TRAP #0) BRA.S SENDUE10 good, A0 = address of TCB'�MOVEM.L�(A7)+,D2-D3‚Clean�up�the�stack( BRA.S SENDUEOK bad, go throw away event*BSENDUE10�MOVEM.L�(A7)+,D2-D3ƒstage�the�registers�for�RMS68K�QEVENT.�MOVEQ�#T0QEVNTI,D0‚initiate�QEVENTI�directive TRAP #0�NOPŒgood�event*5*ƒIf�we�return�here�directly�the�event�wasn't�queued!!*ˆIgnore�the�error�and�keep�going*6SENDUEOK MOVEM.L (A7)+,D2-D7/A0-A6 restore environment RTS éééééé' TTL GPIB MENU ITEM TABLE - GPIB TABLES PAGEE********************************************************************** *�COMMAND�I/O�MENU�DRIVER�TABLES*E**********************************************************************=*…THE�FOLLOWING�COMMAND�I/O�MENUS�ARE�USED�TO�COORDINATE�GPIB<*…TRANSMISSION�PROTOCOL�ON�THE�BUS.�MENUS�ARE�GENERATED�EACH:*…TIME�A�REQUEST�FROM�IOS�IS�MADE�TO�THE�DRIVER.�EACH�MENU=*…CONSISTS�OF�SEVERAL�MENU�ITEMS�EACH�OF�WHICH�HAS�A�SPECIFIC?*…TASK�TO�ACCOMPLISH�OR�INITIATE.�ONLY�ONE�MENU�MAY�BE�EXECUTED?*…AT�A�TIME�AND�ANY�REQUESTS�FOR�I/O�THAT�OCCUR�WHILE�EXECUTINGA*…A�MENU�ARE�QUEUED�UP�AND�WILL�BE�PROCESSED�WHEN�ITS�TURN�COMES.9*…MENU�ITEMS�CONSIST�OF�ESSENTIALLY�FOUR�DIFFERENT�TYPES:**…1.�COMMAND�ITEMS�(BUSCMD)*?*ˆTHESE�WILL�SEND�IEEE-488�COMMANDS�TO�THE�GPIBC�INTERFACE�WITH@*ˆTHE�ATN�LINE�TRUE.�ALL�THESE�TYPES�ARE�DESIGNATED�BY�THE�MACRO*ˆBUSCMD�.*&*…2.�AUXILLIARY�COMMAND�ITEMS�(AUXCMD)*5*ˆAUXILLIARY�COMMANDS�ARE�MENU�ITEMS�THAT�ARE�WRITTEN<*ˆDIRECTLY�TO�THE�AUXILIARY�COMMAND�REGISTER�OF�THE�TMS9914A?*ˆREGARDLESS�OF�THE�THE�STATE�OF�THE�ATN�LINE�AND�ARE�GENERATED*ˆBY�AUXCMD��MACRO�CALL.*,*…3.�DATA�INPUT/OUTPUT�MENU�ITEMS�(DATAXFER)*@*ˆTHESE�INITIATE�THE�ACTUAL�DATA�DMA�TRANSFER.�THE�COMPLETION�OF@*ˆTHESE�COMMANDS�IS�PROMPTED�BY�AN�I/O�COMPLETE�INTERRUPT�BY�THE3*ˆGPIBC.�THESE�TYPES�ARE�CALLED�WITH�DATAXFR�.*#*…4.�FUNCTION�MENU�ITEMS�(FUNCTION)*7*ˆTHESE�CAUSE�SOME�SORT�OF�MENU�FUNCTION�TO�TAKE�PLACE.>*ˆFOR�EXAMPLE,�THE�FUNCTION��MENU�ITEM�SIGNIFIES�THE�THIS>*ˆMENU�PACKET�IS�COMPLETE�AND�THAT�THE�MENU�PROCESSOR�IS�READY?*ˆFOR�A�NEW�MENU.�ALL�THESE�TYPES�OF�COMMANDS�ARE�PREFIXED�WITH *ˆTHE�MACRO�CALL�FUNCTION�.*D************ ******************************************************** SECTION 0 DS 0*D**********************************************************************ˆFUNCTION:�INPUT�DATA*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOREAD‚(CONTROLLER�MODE�ONLY)* Ñ6ÚBâ?êAò@úB@ DCF"?*02+:0B<J5R(Z/<*ˆPURPOSE:�TO�INITIATE�DMA�WRITE�(WRITE�INTO�MEMORY)�OF�DATA*C********************************************************************INP_DATA�BUSCMD�UNT„UNTALKˆBUSCMD�UNL„UNLISTEN%ˆBUSCMD�OTA„SEND�PRIMARY�TALK�ADDRESSˆDATAXFR�IN„DMA�WRITE�(INPUT)ˆBUSCMD�UNT„UNTALKˆFUNCTION�END„END�OF�MENUˆDS.W�0ŠASSURE�WORD�ALIGNMENT*C*********************************************************************ˆFUNCTION:�OUTPUT�DATA*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOWRIT�(CONTROLLER�MODE�ONLY)*:*ˆPURPOSE:�TO�INITIATE�DMA�READ�(READ�FROM�MEMORY)�OF�DATA*D*********************************************************************OUT_DATA�BUSCMD�UNTˆUNTALK‰BUSCMD�UNLˆUNLISTEN'‰BUSCMD�LAGˆSEND�PRIMARY�LISTEN�ADDRESS‰DATAXFR�OUT‡DMA�READ�(OUTPUT)#‰DATAXFR�TERM†SEND�TERMINATING�CHAR'‰DATAXFR�SEOI†SEND�'EOI'�WITH�LAST�BYTE‰BUSCMD�UNLˆUNLISTEN‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*D**********************************************************************ˆFUNCTION:�OUTPUT�WITH�INPUT*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOOWIN‚(CONTROLLER�MODE�ONLY)*8*ˆPURPOSE:�TO�PERFORM�AND�OUTPUT�FUNCTION�FOLLOWED�BY�AN'*‘INPUT�FUNCTION�WITH�ONE�MENU�REQUEST.*D*********************************************************************OWI_DATA�BUSCMD�UNTˆUNTALK‰BUSCMD�UNLˆUNLISTEN'‰BUSCMD�LAGˆSEND�PRIMARY�LISTEN�ADDRESS'‰DATAXFR�OUT‡INITIATE�DMA�READ�(OUTPUT)&‰DATAXFR�TERM†SEND�TERMINATING�CHAR(S)'‰DATAXFR�SEOI†SEND�'EOI'�WITH�LAST�BYTE‰BUSCMD�UNLˆUNLISTEN%‰BUSCMD�OTAˆSEND�PRIMARY�TALK�ADDRESS&‰DATAXFR�INˆINITIATE�DMA�WRITE�(INPUT)‰BUSCMD�UNTˆUNTALK‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E***********************************************************************ˆFUNCTION:�REQUEST�STATUS*3*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSTATƒ(ANY�MODE)*7*ˆPURPOSE:‚STANDARD�IOS�REQUEST�STATUS�FUNCTION�COMMAND*E**********************************************************************)REQ_STAT�FUNCTION�FREQSTATƒREQUEST�STATUS‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E********************************************************************** *ˆFUNCTION:�CHANGE�CONFIGURATION*3*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOCNFGƒ(ANY�MODE)*=*ˆPURPOSE:‚STANDARD�IOS�CHANGE�CONFIGURATION�FUNCTION�COMMAND*E**********************************************************************6CNFG_DEV�FUNCTION�FCNFGDEVƒCHANGE�DEVICE�CONFIGURATION‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E**********************************************************************(*ˆFUNCTION:�CHANGE�DEFAULT�CONFIGURATION*3*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOCHDC‚(ANY�MODE)*7*ˆPURPOSE:‚STANDARD�IOS�CHANGE�DEFAULT�FUNCTION�COMMAND*E**********************************************************************7CH_DEFLT�FUNCTION�FCHDEFLTƒCHANGE�DEFAULT�CONFIGURATION‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*D*********************************************************************"*ˆFUNCTION:�COMMAND�OUT�/�DATA�OUT*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOCODO‚(CONTROLLER�MODE�ONLY)*9*ˆPURPOSE:�TO�ALLOW�THE�USER�TO�SEND�NON-STANDARD�COMMAND1*‘SEQUENCES�(ATN�TRUE)�FOLLOWED�BY�A�DATA�STRING.*D*********************************************************************7CDAT_OUT�BUSCMD�AUXˆSEND�COMMAND�STRING�FROM�AUX�BUFFER‰BUSCMD�UNTˆUNTALK'‰DATAXFR�OUT‡INITIATE�DMA�READ�(OUTPUT)#‰DATAXFR�TERM†SEND�TERMINATING�CHAR'‰DATAXFR�SEOI†SEND �'EOI'�WITH�LAST�BYTE‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E**********************************************************************!*ˆFUNCTION:�COMMAND�OUT�/�DATA�IN*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOCODI‚(CONTROLLER�MODE�ONLY)*;*ˆPURPOSE:�TO�ALLOW�THE�USER�TO�SEND�A�NON-STANDARD�COMMAND-*‘SEQUENCE�(ATN�TRUE)�FOLLOWED�BY�AN�INPUT�OF*‘DATA�COMMAND.*E**********************************************************************6CDAT_IN‚BUSCMD�AUXˆSEND�COMMAND�STRING�FROM�AUX�BUFFER%‰DATAXFR�INˆINTIATE�DMA�WRITE�(INPUT)‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E***********************************************************************ˆFUNCTION:�COMMAND�OUT*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOCMDO‚(CONTROLLER�MODE�ONLY)*;*ˆPURPOSE:�TO�ALLOW�THE�USER�TO�SEND�A�NON-STANDARD�COMMAND*‘SEQUENCE�(ATN�TRUE).*E**********************************************************************6CMD_OUT‚BUSCMD�AUXˆSEND�COMMAND�STRING�FROM�AUX�BUFFER‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E**********************************************************************"*ˆFUNCTION:�READ�SECONDARY�ADDRESS*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IORSEC‚(CONTROLLER�MODE�ONLY)*8*ˆPURPOSE:�SIMILAR�TO�INPUT�DATA�EXCEPT�THAT�A�SECONDARY*‘ADDRESS�MUST�BE�SPECIFIED.*E**********************************************************************READ_SEC�BUSCMD�UNTˆUNTALK‰BUSCMD�UNLˆUNLISTEN ‰BUSCMD�OTAˆPRIMARY�TALK�ADDRESS‰BUSCMD�OSAˆSECONDARY�ADDRESS&‰DATAXFR�INˆINITIATE�DMA�WRITE�(INPUT)‰BUSCMD�UNTˆUNTALK‰FUNCTION�END…END�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENTE**********************************************************************#*ˆFUNCTION:�WRITE�SECONDARY�ADDRESS*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOWSEC‚(CONTROLLER�MODE�ONLY)*9*ˆPURPOSE:�SIMILAR�TO�OUTPUT�DATA�EXCEPT�THAT�A�SECONDARY*‘ADDRESS�MUST�BE�SPECIFIED*D*********************************************************************WRITE_SEC�BUSCMD�UNT‡UNTALK‰BUSCMD�UNLˆUNLISTEN"‰BUSCMD�LAGˆPRIMARY�LISTEN�ADDRESS‰BUSCMD�OSAˆSECONDARY�ADDRESS'‰DATAXFR�OUT‡INITIATE�DMA�READ�(OUTPUT)2‰DATAXFR�TERM†SEND�TERMINATION�CHAR�(IF�NECESSARY)'‰DATAXFR�SEOI†SEND�'EOI'�WITH�LAST�BYTE‰BUSCMD�UNLˆUNLISTEN‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*C********************************************************************%*ˆFUNCTION:�UNCONFIGURE�PARALLEL�POLL*>*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOPPU‚(CONTROLLER�MODE�ONLY)*1*ˆPURPOSE:�TO�RESET�ALL�DEVICES�OF�THEIR�PARALLEL*‘POLL�CONFIGURATION�STATE.*C********************************************************************5PP_UNCFG�BUSCMD�PPUˆPARALLEL�POLL�UNCONFIGURE�COMMAND‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*B*******************************************************************#*ˆFUNCTION:�CONFIGURE�PARALLEL�POLL*>*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOPPC‚(CONTROLLER�MODE�ONLY)*6*ˆPURPOSE:�TO�CONFIGURE�WHICH�OF�8�PARALLEL�POLL�LINES+*‘THE�SPECIFIED�DEVICE�IS�TO�RESPONDON�WHEN*‘PARALLEL�POLLED.*A******************************************************************PP_CNFIG�BUSCMD�UNTˆUNTALK‰BUSCMD�UNLˆUNLISTEN"‰BUSCMD�LAGˆPRIMARY�LISTEN�ADDRESS+‰BUSCMD�PPCˆPARALLEL�POLL�CONFIGURE�COMMAND(‰BUSCMD�PPEˆSEND�POLL�AND�SENSE�BIT�INFO‰BUSCMD�UNLˆUNLISTEN‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*@*****************************************************************!*ˆFUNCTION:�CONDUCT�PARALLEL�POLL*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOPPOL�(CONTROLLER�MODE�ONLY)*=*ˆPURPOSE:�ALLOW�ACTIVE�CONTROLLER�TO�PARALLEL�ALL�CONFIGURED-*‘DEVICES�(I.E.�DEVICES�WHO�ARE�PARALLEL�POLL'*‘CONFIGURED)�AND�RECEIVE�THEIR�STATUS.*B*******************************************************************-COND_PP‚AUXCMD�TCSŠTAKE�CONTROL�SYNCHRONOUSLY,‰FUNCTION�FRPP‡REQUEST�PARALLEL�POLL�ROUTINE‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE �WORD�ALIGNMENT*E**********************************************************************$*ˆFUNCTION:�SET�PARALLEL�POLL�STATUS*8*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSPPS‚(T/L�MODE�ONLY)*:*ˆPURPOSE:‚SET�UP�THE�PARALLEL�POLL�RESPONSE�BIT�(PPR)�AND*’THE�SENSE�BIT�(S).*E**********************************************************************/SET_PPƒFUNCTION�FSETPP…SET�PARALLEL�POLL�STATUS‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*E**********************************************************************"*ˆFUNCTION:�SET�SERIAL�POLL�STATUS*8*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSSPS�(T/L�MODE�ONLY)*5*ˆPURPOSE:‚SET�THE�VALUE�TO�BE�RETURNED�TO�THE�ACTIVE'*’CONTROLLER�WHEN�WE�ARE�SERIAL�POLLED.*E**********************************************************************-SET_SPƒFUNCTION�FSETSP…SET�SERIAL�POLL�STATUS‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*C********************************************************************'*ˆFUNCTION:�DEVICE�STATUS�(SERIAL�POLL)*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSPOL�(CONTROLLER�MODE�ONLY)*2*ˆPURPOSE:�CONDUCT�SERIAL�POLL�OF�SPECIFIED�DEVICE*B*******************************************************************COND_SP‚BUSCMD�UNTˆUNTALK‰BUSCMD�UNLˆUNLISTEN#‰BUSCMD�SPEˆSEND�SERIAL�POLL�ENABLE%‰BUSCMD�OTAˆSEND�PRIMARY�TALK�ADDRESS%‰DATAXFR�SPB‡RECEIVE�SERIAL�POLL�BYTE"‰BUSCMD�SPDˆLEAVE�SERIAL�POLL�MODE‰BUSCMD�UNTˆUNTALK‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*C********************************************************************!*ˆFUNCTION:�PARALLEL�POLL�DISABLE*>*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOPPD‚(CONTROLLER�MODE�ONLY)*@*ˆPURPOSE:�TO�DISABLE�A�DEVICE�FROM�SENDING�A�STATUS�BIT�MESSAGE!*‘IN�RESPONSE�TO�A�PARALLEL�POLL.*C********************************************************************PP_DISAB�BUSCMD�UNTˆUNTALK‰BUSCMD�UNLˆUNLISTEN ‰BUSCMD�LAGˆLISTEN�ADDRESS�GROUP#‰BUSCMD�PPCˆPARALLEL�POLL�CONFIGURE)‰BUSCMD�PPDˆPARALLEL�POLL�DISABLE�COMMAND‰BUSCMD�UNLˆUNLISTEN‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*C*********************************************************************ˆFUNCTION:�INTERFACE�CLEAR*C*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSIFC�(SYS�CONTROLLER�MODE�ONLY)*1*ˆPURPOSE:�TO�ALLOW�THE�SYSTEM�CONTROLLER�TO�SEND**‘THE�INTERFACE�CLEAR�COMMAND�TO�THE�GPIBC*C********************************************************************'INTF_CLR�FUNCTION�FSIC…SEND�IFC�COMMAND‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*C*********************************************************************ˆFUNCTION:�REMOTE�ENABLE*C*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSREN�(SYS�CONTROLLER�MODE�ONLY)*1*ˆPURPOSE:�TO�ALLOW�THE�SYSTEM�TO�SEND�THE�REMOTE*‘ENABLE�MESSAGE�TO�THE�GPIBC.*C********************************************************************.REM_ENAB�AUXCMD�SRE1ˆSEND�REMOTE�ENABLE�(CS=1)‰FUNCTION�END‰END�OF�MENU‰DS.W�0�ASSURE�WORD�ALIGNMENT*C*********************************************************************ˆFUNCTION:�REMOTE�DISABLE*C*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOCREN�(SYS�CONTROLLER�MODE�ONLY)*1*ˆPURPOSE:�TO�ALLOW�THE�SYSTEM�TO�SEND�THE�REMOTE*‘DISABLE�MESSAGE�TO�THE�GPIBC.*C********************************************************************/REM_DNAB�AUXCMD�SRE0ˆSEND�REMOTE�DISABLE�(CS=0)‰FUNCTION�END‰END�OF�MENU‰DS.W�0�ASSURE�WORD�ALIGNMENT*C********************************************************************2*ˆFUNCTION:�ENTRY�I:�ABORT�BUS�AND�DEVICE�MESSAGES*’ENTRY�II:‚CLEAR�ALL�DEVICES*F*ˆFUNCTION�CODE�TO�INITIATE�MENU:�I.�IOABT1�(SYS�CONTROLLER�MODE�ONLY)#*¨II.�IOSDCL�(CONTROLLER�MODE�ONLY)*7*ˆPURPOSE:�TO�HALT�ALL�ACTIVITY�ON�THE�GPIBC�BY�SENDING/*‘THE�INTERFACE�CLEAR�AND�DEVICE�CLEAR�MESSAGES*C********************************************************************2S_IFCDCL�FUNCTION�FSIC‡SEND�INTEFACE�CLEAR�COMMAND*S_ DCL„BUSCMD�DCLŠSEND�DEVICE�CLEAR�COMMAND‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*C********************************************************************%*ˆFUNCTION:�LOCAL�LOCKOUT�ALL�DEVICES*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSLLO‚(CONTROLLER�MODE�ONLY)*-*ˆPURPOSE:�ALLOW�USER�TO�SEND�OUT�LLO�COMMAND*C********************************************************************$S_LOCLOK�BUSCMD�LLOŠSEND�LLO�COMMAND‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*C********************************************************************!*ˆFUNCTION:�ABORT�DEVICE�MESSAGES*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOABT2�(CONTROLLER�MODE�ONLY)*0*ˆPURPOSE:�TO�HALT�ANY�I/O�TO�DEVICES‚BY�SENDING"*‘THE�UNTALK�AND�UNLISTEN�COMMANDS*B*******************************************************************S_UNTUNL�BUSCMD�UNTŠSEND�UNTALK‰BUSCMD�UNLŠSEND�UNLISTEN‰FUNCTION�ENDŠEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*A*******************************************************************ˆFUNCTION:�TAKE�CONTROL*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOTCTL�(CONTROLLER�MODE�ONLY)*1*ˆPURPOSE:�TO�ALLOW�USER�TO�REGAIN�CONTROL�OF�THE)*‘BUS�AT�ANY�TIME�PROVIDED�HE�HAS�CONTROL-*‘OF�THE�BUS�AND�HAS�CONTROLLER�CAPABILITIES.*A******************************************************************/TAKE_CTL�FUNCTION�FTAKCTL‚TAKE�CONTROL�FUNCTION‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*A*******************************************************************ˆFUNCTION:�GO�TO�STANDBY*>*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOGTS�(CONTROLLER�MODE�ONLY)*2*ˆPURPOSE:�TO�ALLOW�USER�TO�RELEASE�CONTROL�OF�THE)*‘BUS�AT�ANY�TIME�PROVIDED�HE�HAS�CONTROL-*‘OF�THE�BUS�AND�HAS�CONTROLLER�CAPABILITIES.*A******************************************************************,GO_STBY‚FUNCTION�FGTS…GO�TO�STANDBY�FUNCTION‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT    A*******************************************************************ˆFUNCTION:�REQUEST�CONTROL*(*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IORQCL*5*ˆPURPOSE:�TO�ALLOW�USER�TO�INITIALLY�TAKE�CONTROL�OF-*‘THE�BUS�AFTER�THE�SYSTEM�IS�INITIALIZED�AND'*‘THE�MVME-300�HAS�COME�UP�IN�T/L�MODE./*‘THIS�COMMAND�WILL�PUT�THE�TMS9914�INTO�'CACS'.*‘AND�ALLOW�NORMAL�CONTROLLER�FUCTIONS�WITHOUT!*‘HAVE�TO�BE�A�SYSTEM�CONTROLLER.*A******************************************************************1REQ_CTL‚FUNCTION�FREQCTL‚REQUEST�CONTROL�FUNCTION‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*A*******************************************************************ˆFUNCTION:�RELEASE�CONTROL*(*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IORLCL*2*ˆPURPOSE:�TO�ALLOW�USER�TO�GIVE�UP�CONTROL�OF�THE)*‘BUS�AT�ANY�TIME�PROVIDED�HE�HAS�CONTROL+*‘OF�THE�BUS.‚THIS�COMMAND�SIMPLY�DROPS�THE+*‘ATN�LINE�ON�THE�BUS�AND�SWITCHES�THE�GPIB%*‘DRIVER�FROM�CONTROLLER�TO�T/L�MODE.#*‘(THE�9914�GOES�INTO�'CIDS'�STATE)*A******************************************************************1REL_CTL‚FUNCTION�FRELCTL‚RELEASE�CONTROL�FUNCTION‰FUNCTION�END†END�OF�MENU‰DS.W�0ŒASSURE�WORD�ALIGNMENT*A*******************************************************************ˆFUNCTION:�PASS�CONTROL*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOPCTL�(CONTROLLER�MODE�ONLY)*3*ˆPURPOSE:�TO�ALLOW�USER�TO�PASS�CONTROL�TO�ANOTHER)*‘DEVICE�ON�THE�BUS�CAPABLE�OF�CONTROLLER*‘RESPONSIBILITIES.*B*******************************************************************PASS_CTL�BUSCMD�UNTŠSEND�UNTALK‰BUSCMD�UNLŠSEND�UNLISTEN%‰BUSCMD�OTAŠSEND�PRIMARY�TALK�ADDRESS‰BUSCMD�TCTŠSEND�TAKE�CONTROL/‰FUNCTION�FRELCTL„ISSUE�RELEASE�CONTROL�COMMAND‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*A******************************************************************"*ˆFUNCTION:�CLEAR�SPECIFIED�DEVICE*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSSDC‚(CONTROLLER�MODE�ONLY)*$*ˆPURPOSE: �TO�CLEAR�SPECIFIED�DEVICE*B*******************************************************************SPEC_CLR�BUSCMD�UNTŠUNTALK‰BUSCMD�UNLŠUNLISTEN"‰BUSCMD�LAGŠPRIMARY�LISTEN�ADDRESS"‰BUSCMD�SDCŠSELECTIVE�DEVICE�CLEAR‰BUSCMD�UNLŠUNTALK‰FUNCTION�ENDŠEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMNET*A******************************************************************%*ˆFUNCTION:�CLEAR�ADDRESSED�LISTENERS*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IODSDC‚(CONTROLLER�MODE�ONLY)*!*ˆPURPOSE:�TO�CLEAR�ALL�LISTENERS*B********************************************************************ADDR_CLR�BUSCMD�SDCŠSELECTIVE�DEVICE�CLEAR‰FUNCTION�ENDŠEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMNET*A******************************************************************!*ˆFUNCTION:�SPECIFIED�GO�TO�LOCAL*A*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSGTL‚(CONTROLLER�&�T/L�MODES)*2*ˆPURPOSE:�TO�PUT�SPECIFIED�LISTENER�IN�LOCAL�MODE*B*******************************************************************SPEC_GTL�BUSCMD�UNTŠUNTALK‰BUSCMD�UNLŠUNLISTEN"‰BUSCMD�LAGŠPRIMARY�LISTEN�ADDRESS‰BUSCMD�GTLŠGO�TO�LOCAL�COMMAND‰BUSCMD�UNLŠUNLISTEN‰FUNCTION�ENDŠEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*A******************************************************************+*ˆFUNCTION:�ADDRESSED�LISTENERS�GO�TO�LOCAL*A*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IODGTL‚(CONTROLLER�&�T/L�MODES)*3*ˆPURPOSE:�TO�PUT�ADDRESSED�LISTENERS�IN�LOCAL�MODE*B*******************************************************************'ADDR_GTL�BUSCMD�GTLŠGO�TO�LOCAL�COMMAND‰FUNCTION�ENDŠEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*B*********************************************************************ˆFUNCTION:�REMOTE�ENABLE�SPECIFIED�DEVICE*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IODREM‚(CONTROLLER�MODE�ONLY)*5*ˆPURPOSE:�TO�PLACE�A�SPECIFIED�DEVICE�IN�REMOTE�MODE*B*******************************************************************'SPEC_REM�AUXCMD�SRE1‰SEND�REMOTE�ENABLE‰BUSCMD�UNTŠUNTALK‰BUSCMD�UNLŠUNLISTEN"‰BUSCMD�LAGŠPRIMARY�LISTEN�ADDRESS‰BUSCMD�UNLŠUNLISTEN‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*A******************************************************************$*ˆFUNCTION:�TRIGGER�SPECIFIED�DEVICE*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOSGET‚(CONTROLLER�MODE�ONLY)*(*ˆPURPOSE:�TO�TRIGGER�A�SPECIFIED�DEVICE*>***************************************************************SPEC_GET�BUSCMD�UNTŠUNTALK‰BUSCMD�UNLŠUNLISTEN"‰BUSCMD�LAGŠPRIMARY�LISTEN�ADDRESS&‰BUSCMD�GETŠSEND�GROUP�EXECUTE�TRIGGER‰BUSCMD�UNLŠUNLISTEN‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*A******************************************************************'*ˆFUNCTION:�TRIGGER�ADDRESSED�LISTENERS*?*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IODGET‚(CONTROLLER�MODE�ONLY)*-*ˆPURPOSE:�TO�TRIGGER�ALL�ADDRESSED�LISTENERS*>***************************************************************.ADDR_GET�BUSCMD�GETŠSEND�GROUP�EXECUTE�TRIGGER‰FUNCTION�ENDˆEND�OF�MENU‰DS.W�0ŽASSURE�WORD�ALIGNMENT*B*******************************************************************-*ˆFUNCTION:�PRIMARY�AND�SECONDARY�READ�TO�BUS*’ENTRY�POINT�I:‚SECONDARY�READ*’ENTRY�POINT�II:�PRIMARY�READ*;*ˆFUNCTION�CODE�TO�INITIATE�MENU:�I:�IORSEC‚(T/L�MODE�ONLY)*§II:�IOREAD‚(T/L�MODE�ONLY)*1*ˆPURPOSE:‚ALLOW�OWNER�OF�BUS�TO�MAKE�PRIMARY�AND-*’SECONDARY�READ�REQUESTS�FROM�THE�CONTROLLER *’IN�CHARGE.B*******************************************************************$RSEC_TL�EQU�*�READ�SECONDARY�ADDRESS8INTL_DAT�DATAXFR�INŠREAD�DATA‚(WHEN�CONTROLLER�REQUESTS)�FUNCTION�END�END�OF�MENU�DS.W�0–ASSURE�WORD�ALLIGNMENT*E**********************************************************************0*ˆFUNCTION:�PRIMARY�AND�SECONDARY�WRITE�FROM�BUS *’ENTRY�POINT�I:‚SECONDARY�WRITE*’ENTRY�POINT�II:�PRIMARY�WRITE*;*ˆFUNCTION�CODE�TO�INITIATE�MENU:�I:�IOWSEC‚(T/L�MODE�ONLY)*§II:�IOWRIT‚(T/L�MODE�ONLY)*1*ˆPURPOSE:‚ALLOW�OWNER�OF� THE�BUS�TO�MAKE�PRIMARY0*’AND�SECONDARY�WRITE�REQUESTS�TO�THE�CONTROLLER *’IN�CHARGE.*D*********************************************************************%WSEC_TL�EQU�*�WRITE�SECONDARY�ADDRESS:OUTL_DAT�DATAXFR�OUT‰WRITE�DATA‚(WHEN�CONTROLLER�REQUESTS)8�DATAXFR�TERM�SEND�TERMINATION�CHARACTERS�(IF�NECESSARY)'�DATAXFR�SEOI�SEND�'EOI'�WITH�LAST�BYTE�FUNCTION�END�END�OF�MENU�DS.W�0–ASSURE�WORD�ALLIGNMENT*B*******************************************************************1*ˆFUNCTION:�OUTPUT�WITH�INPUT�COMMAND�IN�T/L�MODE*8*ˆFUNCTION�CODE�TO�INITIATE�MENU:�IOOWIN‚(T/L�MODE�ONLY)*7*ˆPURPOSE:‚COMBINATION�OF�THE�PRIMARY�WRITE�FOLLOWED�BY%*’PRIMARY�READ�OPERATION�IN�T/L�MODE.*B*******************************************************************:OITL_DAT�DATAXFR�OUTƒWRITE�DATA�(WHEN�CONTROLLER�REQUESTS)&�DATAXFR�TERMŠSEND�MESSAGE�TERMINATORS'�DATAXFR�SEOIŠSEND�'EOI'�WITH�LAST�BYTE0�DATAXFR�INŒREAD�DATA�(WHEN�CONTROLLER�REQUESTS)�FUNCTION�ENDŠEND�OF�MENU�DS.W�0�ASSURE�WORD�ALLIGNMENT TTL GPIB DRIVER - DRIVER TABLES PAGEB*************************************************************************´********’MENU�ITEM�CODE�JUMP�TABLE•**À*/*†THIS�TABLE�IS�INDEXED�BY�THE�MENU�ELEMENTS.�*7*†THE�ORDER�OF�THIS�TABLE�MUST�REMAIN�CONSISTENT�WITH‡*%*†THE�VALUES�ASSIGNED�TO�EACH�ITEM.™********´*******B****************************************************************** MENUCTBL:�DC.W�0‘END�OF�MENU�INDICATOR*�DC.W�SENDUNT-MENUCTBL‚UNTALK�ROUTINE�ADDR,�DC.W�SENDUNL-MENUCTBL‚UNLISTEN�ROUTINE�ADDR:�DC.W�SENDLAG-MENUCTBL‚PRIMARY�LISTEN�ADDR�ROUTINE�ADDRESS8�DC.W�SENDOTA-MENUCTBL‚PRIMARY�TALK�ADDR�ROUTINE�ADDRESS6�DC.W�SENDOSA-MENUCTBL‚SECONDARY�R/W�ADDR�ROUTINE�ADDR=�DC.W�SENDPPU-MENUCTBL‚PARALLEL�POLL�UNCONFIGURE�ROUTINE�ADDR;�DC.W�SENDPPC-MENUCTBL‚PARALLEL�POLL�CONFIGURE�ROUTINE�ADDR8�DC.W�SENDPPE-MENUCTBL‚PARALLEL�POLL�ENABLE�ROUTINE�ADDR9�DC.W�SENDPPD-MENUCTBL‚PARALLEL�POLL�DISABLE�ROUTINE�ADDR6�DC.W�SENDSPE-MENUCTBL‚SERIAL�POLL�ENABLE�ROUTINE�ADDR7�DC.W�SENDSPD-MENUCTBL‚SERIAL�POLL�DISABLE�ROUTINE�ADDR0�DC.W�SENDDCL-MENUCTBL‚DEVICE�CLEAR�ROUTINE�ADDR1�DC.W�SENDLLO-MENUCTBL‚LOCAL�LOCKOUT�ROUTINE�ADDR0�DC.W�SENDTCT-MENUCTBL‚PASS�CONTROL�ROUTINE�ADDR:�DC.W�SENDSDC-MENUCTBL‚SELECTIVE�DEVICE�CLEAR�ROUTINE�ADDR/�DC.W�SENDGTL-MENUCTBL‚GO�TO�LOCAL�ROUTINE�ADDR9�DC.W�SENDGET-MENUCTBL‚GROUP�EXECUTE�TRIGGER�ROUTINE�ADDR5 DC.W SENDAUXS-MENUCTBL SEND AUXILIARY COMMAND STRINGC DC.W READDATA-MENUCTBL INITIATE DMA WRITE ROUTINE ADDR (READ DATA)C DC.W WRITDATA-MENUCTBL INITIATE DMA READ ROUTINE ADDR (WRITE DATA)B DC.W SENDTERM-MENUCTBL SEND TERMINATION CHARACTER(S) ROUTINE ADDR+�DC.W�READSP-MENUCTBLƒREAD�SERIAL�POLL�BYTE5�DC.W�SENDEOI-MENUCTBL‚SEND�'EOI'�WITH�LAST�DATA�BYTE=�DC.W�AUXPROC-MENUCTBL‚GENERAL�AUXILIARY�COMMAND�ROUTINE�ADDR=�DC.W�SENDIFC-MENUCTBL‚SEND�IFC�COMMAND�ROUTINE�FUNCTION�ADDRG�DC.W�SENDRPP-MENUCTBL‚SEND�REQUEST�PARALLEL�POLL�ROUTINE�FUNCTION�ADDRD�DC.W�SENDRLC-MENUCTBLƒPERFORM�RELEASE�CONTROL�ROUTINE�FUNCTION�ADDRA�DC.W�SENDTCA-MENUCTBLƒPERFORM�TAKE�CONTROL�ROUTINE�FUNCTION�ADDRD�DC.W�SENDRQC-MENUCTBLƒPERFORM�REQUEST�CONTROL�ROUTINE�FUNCTION�ADDR2�DC.W�REQSTAT-MENUCTBL‚REQUEST�STATUS�ROUTINE�ADDR4�DC.W�CNFGDEV-MENUCTBL‚CONFIGURE�DEVICE�ROUTINE�ADDR@�DC.W�CHDEFLT-MENUCTBL‚CHANGE�DEFAULT�CONFIGURATION�ROUTINE�ADDR:�DC.W�SETPP-MENUCTBL„SET�PARALLEL�POLL�STATUS�ROUTINE�ADDR8�DC.W�SETSP-MENUCTBL„SET�SERIAL�POLL�STATUS�ROUTINE�ADDR5�DC.W�SENDGTS-MENUCTBL‚GO�TO�STANDBY�FUNCTION�ROUTINE*6MENUCLEN EQU (*-MENUCTBL)/2 NUMBER OF ENTRIES IN TABLE  PAGEC**************************************************************************µ********˜CONTROLLERŸ*'*ŒCODE/FUNCTION�MENU�TABLE�JUMP�TABLE’**Á*1*†THIS�TABLE�CONTAINS�THE�ADDRESSES�OF�THE�MENUŽ*7*†TABLES�FOR�EACH�OF�THE�GPIBC�IOS�FUNCTIONS�THAT�AREˆ*8*†VALID�IN�CONTROLLER�ONLY�MODE.�THIS�TABLE�IS�INDEXED‡*8*†BY�A�MATCH�IN�'IOSCMDTB'.�IF�THE�ENTRY�IS�ZERO,�THIS‡*'*†MENU�IS�INVALID� IN�CONTROLLER�MODE.˜**Á********µ*******C*******************************************************************%CTLCFTBL�DC.W�INP_DATA-CTLCFTBL‚INPUT�DC.W�OUT_DATA-CTLCFTBLƒOUTPUT)�DC.W�OWI_DATA-CTLCFTBLƒOUTPUT�WITH�INPUT&�DC.W�REQ_STAT-CTLCFTBLƒREQUEST�STATUS,�DC.W�CNFG_DEV-CTLCFTBLƒCHANGE�CONFIGURATION4�DC.W�CH_DEFLT-CTLCFTBLƒCHANGE�DEFAULT�CONFIGURATION,�DC.W�CDAT_OUT-CTLCFTBLƒCOMMAND�OUT/DATA�OUT*�DC.W�CDAT_IN-CTLCFTBL„COMMAND�OUT/DATA�IN"�DC.W�CMD_OUT-CTLCFTBL„COMMAND�OUT&�DC.W�READ_SEC-CTLCFTBLƒREAD�SECONDARY(�DC.W�WRITE_SEC-CTLCFTBLƒWRITE�SECONDARY1�DC.W�PP_UNCFG-CTLCFTBLƒPARALLEL�POLL�UNCONFIGURE/�DC.W�PP_CNFIG-CTLCFTBLƒPARALLEL�POLL�CONFIGURE,�DC.W�COND_PP-CTLCFTBL„CONDUCT�PARALLEL�POLL.�DC.W�SET_PP-CTLCFTBL…SET�PARALLEL�POLL�STATUS,�DC.W�SET_SP-CTLCFTBL…SET�SERIAL�POLL�STATUS*�DC.W�COND_SP-CTLCFTBL„CONDUCT�SERIAL�POLL-�DC.W�PP_DISAB-CTLCFTBLƒPARALLEL�POLL�DISABLE'�DC.W�INTF_CLR-CTLCFTBLƒINTERFACE�CLEAR%�DC.W�REM_ENAB-CTLCFTBLƒREMOTE�ENABLE&�DC.W�REM_DNAB-CTLCFTBLƒREMOTE�DISABLE&�DC.W�S_DCL-CTLCFTBL†CLEAR�ALL�DEVICES3�DC.W�ADDR_CLR-CTLCFTBLƒCLEAR�ALL�LISTENING�DEVICES%�DC.W�S_LOCLOK-CTLCFTBLƒLOCAL�LOCKOUT$�DC.W�PASS_CTL-CTLCFTBLƒPASS�CONTROL-�DC.W�ADDR_GTL-CTLCFTBLƒLISTENERS�GO�TO�LOCAL)�DC.W�ADDR_GET-CTLCFTBLƒLISTENERS�TRIGGER2�DC.W�S_IFCDCL-CTLCFTBLƒINTERFACE�AND�DEVICE�CLEAR+�DC.W�S_UNTUNL-CTLCFTBLƒUNTALK�AND�UNLISTEN$�DC.W�TAKE_CTL-CTLCFTBLƒTAKE�CONTROL�DC.W�0“REQUEST�CONTROL&�DC.W�REL_CTL-CTLCFTBL„RELEASE�CONTROL$�DC.W�GO_STBY-CTLCFTBL„GO�TO�STANDBY.�DC.W�SPEC_CLR-CTLCFTBLƒSPECIFIED�CLEAR�DEVICE/�DC.W�SPEC_REM-CTLCFTBLƒSPECIFIED�REMOTE�DEVICE0�DC.W�SPEC_GET-CTLCFTBLƒSPECIFIED�TRIGGER�DEVICE-�DC.W�SPEC_GTL-CTLCFTBLƒSPECIFIED�GO�TO�LOCAL  PAGEC**************************************************************************�TALKER/LISTENER–*******'*ŒCODE/FUNCTION�MENU�TABLE�JUMP�TABLE’**Á*6*†THIS�TABLE�CONTAINS�THE�ADDRESSES�OF�THE�MENU�ITEM‰*6*†TABLE�FOR�EACH�OF�THE�GPIBC�IOS�FUNCTIONS�THAT�ARE‰*8*†VALID�IN�TALKER/LISTENER�MODE.�THIS�TABLE�IS�INDEXED‡*7*†BY�A�MATCH�IN�'IOSCMDTB'.�IF�AN�ENTRY�IS�ZERO,�THENˆ*/*†THAT�MENU�IS�INVALID�IN�TALK/LISTENER�MODE.�**Á********µ*******C*******************************************************************#TLCFTBL�DC.W�INTL_DAT-TLCFTBL‚INPUT�DC.W�OUTL_DAT-TLCFTBLƒOUTPUT(�DC.W�OITL_DAT-TLCFTBLƒOUTPUT�WITH�INPUT%�DC.W�REQ_STAT-TLCFTBLƒREQUEST�STATUS+�DC.W�CNFG_DEV-TLCFTBLƒCHANGE�CONFIGURATION3�DC.W�CH_DEFLT-TLCFTBLƒCHANGE�DEFAULT�CONFIGURATION�DC.W�0’COMMAND�OUT/DATA�OUT�DC.W�0’COMMAND�OUT/DATA�IN�DC.W�0’COMMAND�OUT$�DC.W�RSEC_TL-TLCFTBL„READ�SECONDARY%�DC.W�WSEC_TL-TLCFTBL„WRITE�SECONDARY!�DC.W�0’PARALLEL�POLL�UNCONFIGURE�DC.W�0’PARALLEL�POLL�CONFIGURE�DC.W�0’CONDUCT�PARALLEL�POLL-�DC.W�SET_PP-TLCFTBL…SET�PARALLEL�POLL�STATUS+�DC.W�SET_SP-TLCFTBL…SET�SERIAL�POLL�STATUS�DC.W�0’CONDUCT�SERIAL�POLL�DC.W�0’PARALLEL�POLL�DISABLE&�DC.W�INTF_CLR-TLCFTBLƒINTERFACE�CLEAR�DC.W�0’REMOTE�ENABLE�DC.W�0’REMOTE�DISABLE�DC.W�0’CLEAR�ALL�DEVICES#�DC.W�0’CLEAR�ALL�LISTENING�DEVICES�DC.W�0’LOCAL�LOCKOUT�DC.W�0’PASS�CONTROL�DC.W�0’LISTENERS�GO�TO�LOCAL�DC.W�0’LISTENERS�TRIGGER"�DC.W�0’INTERFACE�AND�DEVICE�CLEAR�DC.W�0’UNTALK�AND�UNLISTEN�DC.W�0’TAKE�CONTROL%�DC.W�REQ_CTL-TLCFTBL„REQUEST�CONTROL�DC.W�0’RELEASE�CONTROL�DC.W�0’GO�TO�STANDBY�DC.W�0’SPECIFIED�CLEAR�DEVICE�DC.W�0’SPECIFIED�REMOTE�DEVICE �DC.W�0’SPECIFIED�TRIGGER�DEVICE�DC.W�0’SPECIFIED�GO�TO�LOCAL  PAGEC**************************************************************************µ*******!*’CODE/FUNCTION�IOS�MATCH�TABLE’**Á*6*†THIS�TABLE�CONTAINS�THE�COMBINED�CODE�AND�FUNCTION‰*;*†FOR�EACH�COMMAND�AVAILABLE�IN�IOS�TO�A�BUSSABLE�DEVICE.„*7*†WHEN�AN�IOS�PARAMETER�BLOCK�IS�RECEIVED,�THIS�TABLEˆ*8*†WILL�BE�SCANNED�FOR�A�MATCH.�WHEN�FOUND�THE�RELATIVE‡*5*†OFFSET�IN�THE�TABLE�WILL�INDEX�INTO�'CFMENUTB'�TOŠ*:*†POINT�TO�THE�APPRIORIATE�MENU�DRIVER�FOR�THAT�FUNCTION…*1*†THESE�COMMANDS�ARE�PASSED�IN�THE�IOSPB�IN�THEŽ**† PARAMETER�'IOSFCT'.¨**Á********µ*******C*******************************************************************IOSCMDTB�DC.W�IOREAD„INPUT�DC.W�IOWRIT‡OUTPUT�DC.W�IOOWIN‡OUTPUT�WITH�INPUT�DC.W�IOSTAT‡REQUEST�STATUS!�DC.W�IOCNFG‡CHANGE�CONFIGURATION)�DC.W�IOCHDC‡CHANGE�DEFAULT�CONFIGURATION!�DC.W�IOCODO‡COMMAND�OUT/DATA�OUT �DC.W�IOCODI‡COMMAND�OUT/DATA�IN�DC.W�IOCMDO‡COMMAND�OUT�DC.W�IORSEC‡READ�SECONDARY�DC.W�IOWSEC‡WRITE�SECONDARY%�DC.W�IOPPUˆPARALLEL�POLL�UNCONFIGURE#�DC.W�IOPPCˆPARALLEL�POLL�CONFIGURE"�DC.W�IOPPOL‡CONDUCT�PARALLEL�POLL%�DC.W�IOSPPS‡SET�PARALLEL�POLL�STATUS#�DC.W�IOSSPS‡SET�SERIAL�POLL�STATUS �DC.W�IOSPOL‡CONDUCT�SERIAL�POLL!�DC.W�IOPPDˆPARALLEL�POLL�DISABLE�DC.W�IOSIFC‡INTERFACE�CLEAR�DC.W�IOSREN‡REMOTE�ENABLE�DC.W�IOCREN‡REMOTE�DISABLE�DC.W�IOSDCL‡CLEAR�ALL�DEVICES(�DC.W�IOSSDC‡CLEAR�ALL�LISTENING�DEVICES�DC.W�IOSLLO‡LOCAL�LOCKOUT�DC.W�IOPCTL‡PASS�CONTROL"�DC.W�IOSGTL‡LISTENERS�GO�TO�LOCAL�DC.W�IOSGET‡LISTENERS�TRIGGER'�DC.W�IOABT1‡INTERFACE�AND�DEVICE�CLEAR �DC.W�IOABT2‡UNTALK�AND�UNLISTEN�DC.W�IOTCTL‡TAKE�CONTROL�DC.W�IORQCL‡REQUEST�CONTROL�DC.W�IORLCL‡RELEASE�CONTROL�DC.W�IOGTSˆGO�TO�STANDBY#�DC.W�IODSDC‡SPECIFIED�CLEAR�DEVICE$�DC.W�IODREM‡SPECIFIED�REMOTE�DEVICE%�DC.W�IODGET‡SPECIFIED�TRIGGER�DEVICE"�DC.W�IODGTL‡SPECIFIED�GO�TO�LOCAL*6NUMCMDS�EQU�(*-IOSCMDTB)/2‚NUMBER�OF�COMMANDS�IN�TABLE  PAGEF***********************************************************************.*ŽCOMMAND�BUFFER/MODE/ABILITY�VALIDATION�TABLE*:*ˆThis�table�is�used�by�VALIDATES�and�VALOPER�to�determine4*ˆwhether�certain�parameters/modes�need�be�validated:*ˆfor�the�desired�command.�This�table�is�indexed�according9*ˆto�the�index�for�IOSCMDTB.�The�structure�is�as�follows:**ˆ|--|--|--|--|--|--|--|--|*ˆ|�7|�6|�5|�4|�3|�2|�1|�0|*ˆ|--|--|--|--|--|--|--|--|:*‰|‚|‚|‚|‚|‚|‚|‚|___�must�have�talker�ability�(VALTALK)�**=*‰|‚|‚|‚|‚|‚|‚|______�must�have�listener�ability�(VALLIST)�**<*‰|‚|‚|‚|‚|‚|_________�must�have�controller�ability�(VALCTL)C*‰|‚|‚|‚|‚|____________�must�have�sys.�controller�ability�(VALSCTL)7*‰|‚|‚|‚|_______________�must�have�SRQ�ability�(VALSRQ)@*‰|‚|‚|__________________�validate�primary�buffer�addr.(VALPBUF)C*‰|‚|_____________________�validate�secondary�buffer�addr.(VALSBUF)G*‰|________________________�validate�configuration�buf.�addr.�(VALCBUF)**ˆ|--|--|--|--|--|--|--|--|*ˆ|15|14|13|12|11|10|�9|�8|*ˆ|--|--|--|--|--|--|--|--|2*‰|‚|‚|‚|‚|‚|‚|‚|___�valid�in�talker�mode(VALTMOD)5*‰|‚|‚|‚|‚|‚|‚|______�valid�in�listener�mode(VALLMOD):*‰|‚|‚|‚|‚|‚|_________�must�be�in�controller�mode(VALCMOD)?*‰|‚|‚|‚|‚|____________�valid�only�for�BUS�in�T/L�mode(VALBTLM) *‰|‚|‚|‚|Ÿor�device�on�CTL�mode.@*‰|‚|‚|‚|_______________�valid�only�for�bussable�device(VALBDEV)C*‰|‚|‚|__________________�command�valid�only�for�BUS�itself(VALBUS)?*‰|‚|_____________________�validate�secondary�address�(VALSADR)>*‰|________________________�must�be�in�charge�(control)�of�BUS*A*ˆNOTE:‚DO�NOT�CHANGE�THE�ORDER�OF�BITS�0-4�BECAUSE�THEY�DIRECTLY8*�CORRESPOND�TO�THE�ATTRIBUTES�WORD�IN�THE�CONFIGURATION*�BLOCK�FOR�EACH�DEVICE.*@*…**�NOTE:‚THESE�CAPABILITIES�WHEN�DESIGNATED�IN�THE�TABLE�BELOW9*�ARE�WITH�RESPECT�TO�THE�BUS.‚IF�THAT�PARTICULAR�COMMAND9*�IS�USED�AND�IT�IS�DIRECTED�TOWARDS�A�DEVICE�RATHER�THAN6*�THE�BUS,�THE�BIT�BEING�SET�WILL�TAKE�ON�ITS�OPPOSITE3*�MEANING.‚THAT�IS,�IF�'VALTALK'�IS�SPECIFIED�FOR�A:*�COMMAND,�IF�THE�COMMAND�IS�DIRECTED�TOWARDS�THE�BUS�THAT8*�IMPLIES�THAT�THE�BUS�HAS�TALKER�ABILITIES.�HOWEVER,�IF?*�THAT�SAME�COMMAND�WAS�DIRECTED�TOWARS�A�DEVICE,�THE�'VALTALK'=*�BIT�IMPLIES�THAT�THE�DEVICE�MUST�HAVE�LISTENER�CAPABILITIES<*�BECAUSE�THE�BUS�WILL�BE�TRYING�TO�TALK�TO�IT.�THE�OPPOSITE**�IS�ALSO�TRUE�FOR�THE�'VALLIST'�BIT�ALSO.* 3VALPARTB�DC.W�VALLIST+VALPBUF+VALBTLM+VALLMOD‡INPUT,�DC.W�VALTMOD+VALTALK+VALPBUF+VALBTLM�OUTPUTG�DC.W�VALTALK+VALLIST+VALPBUF+VALSBUF+VALBTLM+VALTMOD‚OUTPUT�WITH�INPUT�DC.W�VA LCBUF§REQUEST�STATUS"�DC.W�VALCBUF§CHANGE�CONFIGURATION'�DC.W�VALCBUF§CHANGE�DEF.�CONFIGURATION@�DC.W�VALCTL+VALBUS+VALPBUF+VALSBUF+VALCMOD‰COMMAND�OUT/DATA�OUT?�DC.W�VALCTL+VALBUS+VALPBUF+VALSBUF+VALCMOD‰COMMAND�OUT/DATA�IN/�DC.W�VALCTL+VALBUS+VALSBUF+VALCMOD‘COMMAND�OUT<�DC.W�VALLMOD+VALLIST+VALPBUF+VALBTLM+VALSADR‡READ�SECONDARY=�DC.W�VALTMOD+VALTALK+VALPBUF+VALBTLM+VALSADR‡WRITE�SECONDARY5�DC.W�VALCTL+VALBUS+VALCMOD™PARALLEL�POLL�UNCONFIGURE-�DC.W�VALBDEV+VALCMODŸPARALLEL�POLL�CONFIGURE1�DC.W�VALCTL+VALBUS+VALCMOD™CONDUCT�PARALLEL�POLL-�DC.W�VALBTLM+VALBUS SET�PARALLEL�POLL�STATUS+�DC.W�VALBTLM+VALBUS SET�SERIAL�POLL�STATUS0�DC.W�VALBDEV+VALSRQ+VALCMOD˜CONDUCT�SERIAL�POLL+�DC.W�VALBDEV+VALCMODŸPARALLEL�POLL�DISABLE$�DC.W�VALSCTL+VALBUS INTERFACE�CLEAR*�DC.W�VALSCTL+VALBUS+VALCMOD˜REMOTE�ENABLE+�DC.W�VALSCTL+VALBUS+VALCMOD˜REMOTE�DISABLE-�DC.W�VALCTL+VALBUS+VALCMOD™CLEAR�ALL�DEVICES7�DC.W�VALCTL+VALBUS+VALCMOD™CLEAR�ALL�LISTENING�DEVICES)�DC.W�VALCTL+VALBUS+VALCMOD™LOCAL�LOCKOUT1�DC.W�VALCTL+VALBDEV+VALCMOD+VALBCHG‘PASS�CONTROL1�DC.W�VALCTL+VALBUS+VALCMOD™LISTENERS�GO�TO�LOCAL-�DC.W�VALCTL+VALBUS+VALCMOD™LISTENERS�TRIGGER/�DC.W�VALSCTL+VALBUS INTERFACE�AND�DEVICE�CLEAR/�DC.W�VALCTL+VALBUS+VALCMOD™UNTALK�AND�UNLISTEN!�DC.W�VALBUS+VALCMOD TAKE�CONTROL$�DC.W�VALBUS+VALBTLM REQUEST�CONTROL+�DC.W�VALCTL+VALBUS+VALCMOD™RELEASE�CONTROL)�DC.W�VALCTL+VALBUS+VALCMOD™GO�TO�STANDBY,�DC.W�VALBDEV+VALCMODŸSPECIFIED�CLEAR�DEVICE-�DC.W�VALBDEV+VALCMODŸSPECIFIED�REMOTE�DEVICE.�DC.W�VALBDEV+VALCMODŸSPECIFIED�TRIGGER�DEVICE+�DC.W�VALBDEV+VALCMODŸSPECIFIED�GO�TO�LOCAL  PAGE@*****************************************************************>*‚PARAMETER�BLOCK�ELEMENT�SIZE�TABLE�FOR�CONFIGURATION�REQUEST*@****************************************************************PAR_SIZ�DC.B�2…RECORD�LENGTH�DC.B�4ŒDEVICE�SIZE�DC.B�4ŒWRITE�TIMEOUT�VALUE�DC.B�4ŒREAD�TIMEOUT�VALUE�DC.B�4ŒEOR�REQUIREMENTS�DC.B�2ŒEOS�WRITE/READ�CHAR#�DC.B�1ŒPARALLEL�POLL�CONFIGURATION�DC.B�1ŒPRIMARY�ADDRESS3�DC.B�4Œ#�OF�BYTES�IN�FIXED�WRITE�-�FORMATTED/IMAGE2�DC.B�4Œ#�OF�BYTES�IN�FIXED�READ�-�FORMATTED/IMAGE#�DC.B�4ŒREAD�SECONDARY�ADDRESS�MASK$�DC.B�4ŒWRITE�SECONDARY�ADDRESS�MASK(�DC.B�8ŒRESERVED�FOR�LATER�USE/EXPANSION�DC.B�0ŒEND�OF�CONFIGURATION* DS 0 ‰IFEQ†DTYPE‰TTL‡INTERRUPT�HANDLER O*******************************************************************************O*******************************************************************************O*********************************************************************************ˆSASI�INTERRUPT�HANDLER*E*ˆControl�can�come�to�the�SASI�interrupt‚handler�when�CMR�receives�anG*ˆinterrupt�on�the�interrupt�level�that�is�used�by�the�SASI�controller.B*ˆIf�the‚interrupt�is�a‚SASI�interrupt,�the‚SASI‚interrupt�handlerF*ˆsets�the�C�bit�of�the�SR,�and�lowers�the�interrupt�mask�level�by�one*ˆlevel�upon�return.*D*ˆEntry:„A1�=�physical�address�of�the�SASI�interrupt�handler�routine"*’A5�=�physical�address�of�the�CCB1*’SR�=�Masked�at�the�level�of�the�SASI�interrupt.*O*******************************************************************************O*******************************************************************************O******************************************************************************* -‰PAGEš#######################################O******************************************************************************** *ˆSASI�INTERRUPT�POLLING�ROUTINE*%*ˆEntry:„A5�=�physical�address�of�CCB*<*ˆExit:…Return�to�CMR�via�RTS�if�it�IS�NOT�a�SASI�interrupt.4*’Fall�through�to�SASIINT�if�it�IS�a�SASI�interrupt.*O******************************************************************************* *¨Time >INTERUPT�MOVE.LƒCCBCHB(A5),A0ˆ16�(4/0)‡Point�A0‚to�the �MVME4201‰MOVEQ„#REQINT,D0Œ4�(1/0)…memory-mappedƒI/O‚area,4‰AND.B„FLAGS(A0),D0Š8�(2/0)…and‚check�the�SASI‚FLAGS0‰BNE.S„SASIINT�8�(1/0)…register‚to�see�if�a�SASI&‰RTS›16�(3/0)…interrupt�is�pending.ƒIf$*¦--------…there‚isn't�a�SASI�inter-$*¦52(11/0)…rupt�pending,‚return�with*³SR.C�=�0‚to�indicate�that*³the�interrupt‚isn't�ours.*³The�AND‚instruction�auto-*³matically�clears�the‚SR.C *³bit�for�us. $*¨If�we're�using�an�EXORmacs�system,%*¦the�time�for�the�polling�routine�is[b4k7s9{8ƒ6‹1“8›3£A«C³0»2Ã/Ë4Ó5Û5ã2ë5ó4û3< 027#<+>3:;9C3K<*¦computed�as�follows. &*¦Time�=�52�+�11*3�+�0*1�=�85�cycles„{*«=�85*(0.125)�microsecondsˆ{*«=�10.625�microseconds. #*¨The�EXORmacs�typically�requires�3)*¦wait�cycles�for�a�read�cycle�and�1�wait)*¦cycle�for�a�write�cycle,�and�the�micro-'*¦processor�in�a�standard�EXORmacs�runs&*¦at�8.0�megahertz�for�a�cycle�time�of*¦0.125�microseconds. %*¨Notice�that�the�label�INTERUPT�that)*¦we�use�here�is�intentionally�misspelled"*¦so�it�won't�exceed�8�characters. -‰PAGEš#######################################O********************************************************************************#*ˆSASI�INTERRUPT�CO-ROUTINE�LINKAGE*C*ˆControl�reaches�this�point�when�we've�successfully�identified�theA*ˆinterrupt�as�a‚SASI�interrupt.‚This�routine�is�also�called�as�aB*ˆsubroutine�when�the‚command-processing�routine�wants�to�activateB*ˆinterrupt�processing.‚Whenever�the�interrupt�handler�empties�theB*ˆI/O�queue,�we�deactivate�interrupt�processing.‚When�the�command-B*ˆprocessing�routine‚puts�a�new�queue�entry�into�a�empty�queue,�it5*ˆmust�call�SASIINT�to�activate�interrupt�processing.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�P�P *™A‚P�*ƒP�P�P*"*ˆExit:…Jump�to�co-routine�segment*O******************************************************************************* 2SASIINT‚EQU†*–We�know�we�have�a�SASI�interrupt,�so>L0420„EQU†DSABLINT+LEDOFF†disable�the�interrupt�at�the�MVME420?‰MOVE.Bƒ#L0420,CONTROL(A0)ƒSASI�Peripheral�Adapter.‚Then�enable<‰MOVE.WƒCCBSR(A5),SR‰68000�interrupts�at�our�interrupt�level'*¦so�that�other�interrupts�at�our�level'*¦won't�be�delayed�while�we�process�our$*¦interrupt.‚Every�interrupt�handler)*¦should�mask�its�interrupt�at�the�source)*¦of�the�interrupt�and�then�quickly�lower(*¦the�system�interrupt�mask�by�one�level)*¦to�allow�the�system�to�respond�to�other#*¦interrupts�that�occur�at�the�same*¦priority�level. @L0430„REG†A4/A3/A2/D3/D2/D1†A5,�A1,�A0,�and�D0�have�already�been;‰MOVEM.L‚L0430,-(SP)Šsaved�by�CMR.‚Here�we�save�the�rest�of'*¦the�registers�that�we�need�to�use.‚We(*¦save�only�the�registers�that�we�really%*¦need�because�we�don't�want�to�waste(*¦time�or�stack�space.‚Time,�especially,'*¦is�important�in�an�interrupt�handler. <‰MOVE.LƒIOQUEUE(A5),A1‰Set�A1�=�LOC(Drive's�variable�block).)*¦The�first�entry�of�the�IOQUEUE�contains)*¦a�pointer�to�the�variable�block�for�the)*¦disc�drive�that�we�should�be�accessing. =‰MOVE.LƒINTSWTCH(A5),A3ˆBranch�to�the�co-routine�segment�that"‰JMP†(A3)‘should�be�executed�next. %*¨Control�will�eventually�return�from(*¦the�selected�co-routine�segment�to�the&*¦INTRTN�routine,�which�implements�the*¦return�linkage�to�the�system. -‰PAGEš#######################################O*********************************************************************************ˆSASI�OPCODE�TABLE*@*ˆThis�table‚contains�the‚SASI-defined�opcode‚values�for�the�I/OD*ˆoperations�that�we�currently�use�with�the�SA1403D�SASI�controller.*O******************************************************************************* 2*’---------------------------�SASI�Opcode�value.Œ{*’|¹{!*’|”------�IOFUNCT�index�value .Š{*’|”|¤{*’|”|¤{*’V”V¤{‰DC.B…$0A’-1�=�Write�disc.–{!OPTBL„DC.B…$04“0�=�Format�disc.•{/‰DC.B…$C0’+1�=�Define�format�for�floppy�disc.ƒ{‰DC.B…$08’+2�=�Read�disc.—{ 5FTRACKƒDC.B…$06”The�opcode�for�a�format-track�command)*¦is�not�indexed�by�the�IOFUNCT�value�for%*¦a�format-track�command.‚The�format-$*¦track�command�has�the�same�IOFUNCT&*¦value�that�is�used�for�a�format-disc'*¦command,�and�we�uniquely�identify�the'*¦format-track�command�by�the�fact�that(*¦its�IOOPTS�value�is�different�from�the)*¦IOOPTS�value�that�is�used�for�a�format-(*¦disc�command.‚Then�we�compute�a�pseudo'*¦IOFUNCT�value�that�indexes�from�OPTBL *¦to�FTRACK. '‰DS.W…0–This�statement�ensures�that�the'*¦location�counter�is�aligned�to�a�word *¦boundary.-‰PAGEš#######################################3SENSECMD�EQU†$03”This�label�defines�the�SASI�opcode(*¦value�for�a�request-sense�command.‚The$*¦SASI�driver�issues�a�request-sense&*¦command�whenever�the�SASI�controller'*¦returns�a�status�value�that�indicates$*¦an�error.‚The�controller�returns�a&*¦status�value�at�the�end�of�every�I/O(*¦transaction,�and�the�driver�checks�the%*¦status�value�to�see�if�an�error�has(*¦occurred.‚If�an�error�has�occurred,�we)*¦issue�a�request-sense�command�to�obtain'*¦detailed�information�about�the�error. "*¨A�user's�program�cannot�directly&*¦generate�a�request-sense�command,�so(*¦the�opcode�value�for�the�request-sense)*¦command�isn't�in�the�SASI�opcode�table.&*¦The�SASI�driver�automatically�issues)*¦request-sense�commands�as�necessary�for*¦error�analysis. -‰PAGEš#######################################O*********************************************************************************ˆPROCESS�NEXT�QUEUE�ENTRY*E*ˆControl�comes�to�this�co-routine�segment�to�process�the�front�entryD*ˆof�the�IOQUEUE.‚We�are�guaranteed�that�the�queue�in�non-empty�when *ˆcontrol�comes�to�this�routine.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*�*�P*9*ˆExits�to:‚Send�a�command�packet�to�the�SASI�controller.*O******************************************************************************* =PROCQUE‚LEA†CMDEND(A5),A3ŠWe�want�to�examine�the�variables�in(*¦the�drive's�I/O�packet,�and�we�want�to'*¦construct�a�command�packet�for�a�SASI)*¦command�that�will�implement�part�or�all&*¦of�the�function�that�is�specified�in$*¦the�drive's�I/O�packet.‚Then�we'll)*¦transmit�the�command�packet�to�the�SASI *¦controller. %*¨We�start�by�pointing�A3�to�the�byte(*¦that�immediately�follows�the�last�byte(*¦of�the�command�packet�in�memory.‚We'll(*¦use�autodecrement�addressing�to�access*¦the�command�packet.-‰PAGEš####################################### /***********************************************-*�MOD�FOR�DTC�520A�SASI�CONTROLLER�11/16/83ƒ**(* Modified for both controllers 12/12/83*/***********************************************(‰CMP.B…#1,IOFUNCT(A1)†TEST�FOR�CONFIGURE!‰BNE.S…PROQ1�BRA�IF�NOT�CONFIGURE-‰BTSTW…#IOASIZE,CONFGBLK+IOSATW(A1)‚8"�DRIVE?‰BNE.S…PROQ1�BRA�IF�8"�DRIVE6‰LEA‡DTCCMD(A5),A3‡POINT�TO�CONFIGURE�DRIVE�CMD.�PCKT.‰BRA.S…L0490AŽGO�SEND�DATA/************************************************�END�OF�MOD—11/17/83ƒ*/*********************************************** ‰PAGEDPROQ1„MOVE.BƒCTRLCODE(A1),-(A3)…Copy�the�control-code�value�from�the2L1‡SET†CMDCTRLŽdrive's�I/O�packet�into�the�CMDCTRL%*¦field�of�the�command�packet.‚Notice'*¦the�use�of�the�SET�pseudo�instruction)*¦to�generate�a�concordance�entry�for�the&*¦CMDCTRL�field�that�is�modified�here. ;‰MOVE.LƒIOSCTCNT(A1),D0ˆNow�use�the�IOSCTCNT�value�from�the<‰MOVE.Lƒ#MAXSECTS,D1‰drive's�I/O�packet�to�fill�the�CMDSECTS0‰CMP.L„D1,D0�field�of�the�command�packet.‚If�the3‰BLS.S„L0470�count�of�remaining�sectors�exceeds�the3‰MOVE.LƒD1,D0�maximum�number�of�sectors�that�can�be>16,(A3)+ƒdisc�drive's�I/O�packet�to�set�up�the;‰MOVE.BƒDRIVENUM(A1),D1†logical�sector�number�in�the�CMDLSN8‰LSL.B„#LUNFIELD,D1‰field�of�the�command�packet.‚We�also6‰OR.B…D1,-(A3)�use�the�DRIVENUM�value�from�the�drive's1L1‡SET†CMDLSN�I/O�packet�to�set�the�LUN�(Logical-#*¦Unit-Number)�field�in�the�command&*¦packet.‚Notice�that�the�LUN�field�in)*¦the�command�packet�occupies�the�top�few&*¦bits�of�the�first�byte�of�the�CMDLSN%*¦(Logical-Sector-Number)�field.‚Also'*¦notice�the�use�of�the�SET�instruction)*¦to�generate�a�concordance�entry�for�the*¦CMDLSN�field.-‰PAGEš#######################################9‰ADD.L„D0,IOSECTOR(A1)ˆIncrease�the�IOSECTOR�value�in�the%*¦drive's�I/O�packet�by�the�number�of%*¦sectors�that�will�be�processed�as�a%*¦result�of�this�command�packet.‚This(*¦adjustment�causes�IOSECTOR�to�point�to)*¦the�sector�that�should�be�specified�for(*¦the�next�(if�any)�command�packet�after *¦this�one. ;‰MOVE.BƒIOFUNCT(A1),D0‰Get�the�IOFUNCT�code�into�D0.W�so�we+‰EXT.W„D0“can�use�it�to�index�into�the�SASI1‰BNE.S„L0490�opcode�table.‚If�the�IOFUNCT�code�is(*¦nonzero,�we�aren't�processing�a�format'*¦command.‚In�this�case,�we�can�use�the&*¦IOFUNCT�value�directly.‚For�a�format#*¦command,�however,�we�must�do�some*¦special�processing. >L0480„EQU†CONFGBLK+IOSILVˆFor�a�format�command�we�must�install@‰MOVE.BƒL0480(A1),CMDILV(A5)�an�interleave�value�into�the�CMDILV$*¦field,�which�overlays�the�CMDSECTS'*¦field�of�the�command�packet.‚There�is'*¦no�sector�count�for�a�format�command,'*¦but�the�controller�requires�an�inter-%*¦leave�code�in�place�of�the�CMDSECTS*¦field�for�a�format�command. :‰BTSTW„#IOPTRKB,IOOPTS(A1)„If�the�IOOPTS�value�in�the�disc4‰BEQ.S„L0490�drive's�I/O�packet�indicates�that�we're:‰MOVEQWƒFTRACK-OPTBL,D0†processing�a�format-track�command,'*¦adjust�D0.W�to�index�the�format-track!*¦entry�of�the�SASI�opcode�table.%*¦Otherwise,�D0.W�already�indexes�the&*¦format-disc�entry�of�the�SASI�opcode*¦table. #*¨We�use�a�single�IOFUNCT�value�for&*¦both�the�format-disc�command�and�the&*¦format-track�command.‚We�distinguish)*¦one�command�from�the�other�by�examining*¦their�IOOPTS�values. FL0490„MOVE.BƒOPTBL(PC,D0.W),-(A3)ƒFinally,�fill�the�CMDOP�field�of�the4L1‡SET†CMDOP�command�packet�from�the�proper�entry�of'*¦the�SASI�opcode�table.‚Notice�that�A3&*¦now�points�to�the�CMDOP�field�of�the'*¦command�packet,�so�we�can�use�A3�with)*¦autoincrement�addressing�as�we�send�the(*¦command�packet�to�the�SASI�controller.'*¦Also�notice�the�use�of�the�SET�pseudo'*¦instruction�to�generate�a�concordance*¦entry�for�the�CMDOP�field.-‰PAGEš#######################################6L0490AƒBSR†SENDCMD�Send�the�command�packet�to�the�SASI&*¦controller�to�tell�the�controller�to&*¦start�processing.‚Subroutine�SENDCMD'*¦uses�A3�with�autoincrement�addressing(*¦to�send�the�command�packet�to�the�SASI)*¦controller,�and�subroutine�SENDCMD�also'*¦assumes�that�A0�points�to�the�memory-)*¦mapped�I/O�area�for�the�SASI�peripheral *¦adapter. O*********************************************************************************ˆREAD�O R�WRITE�NEXT�SECTOR*B*ˆControl‚comes�to�the�top�of�this‚co-routine�when�the�SASI�driverD*ˆis�ready�to�read�or�write�the�data�for�the�next�sector�that�should@*ˆbe�transferred.‚Control�also‚comes�to�this‚routine‚immediately=*ˆafter‚any�command‚sequence‚has�been‚transmitted‚to‚the‚SASI *ˆcontroller.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*�*�P*1*ˆExits�to:‚Branches�to�interrupt�return�routine.*O******************************************************************************* 8NEXTSECT�BSR†INTRTN‘The�SASI�controller�needs�time�to�do$*¦its�job�before�we�can�transfer�any(*¦data,�so�return�control�to�the�system.'*¦When�the�SASI�controller�has�finished$*¦its�current�task,�we'll�receive�an&*¦interrupt�that�will�cause�control�to(*¦come�back�here.‚The�co-routine�linkage)*¦conveniently�allows�us�to�call�the�rest&*¦of�the�system�as�if�it�were�simply�a)*¦subroutine�to�be�executed�while�we�have*¦nothing�better�to�do. *Â(Continued)-‰PAGEš########################################*¨If�we've�just�transmitted�a�write%*¦command�to�the�SASI�controller,�the'*¦interrupt�should�occur�quickly�(since(*¦the�controller�should�soon�be�ready�to'*¦copy�a�sector�of�output�data�into�its$*¦data�buffer).‚However,�experiments&*¦have�shown�that�the�controller�needs'*¦enough�time�even�in�this�case�to�make(*¦it�worthwhile�for�us�to�return�control*¦to�the�system. %*¨If�we've�just�transmitted�a�read�or'*¦format�command�to�the�controller,�the%*¦controller�will�obviously�require�a&*¦substantial�amount�of�time�before�it*¦interrupts�the�system�again. 9L0530„EQU†CONFGBLK+IOSPSMˆControl�reaches�this�co-routine;‰MOVE.WƒL0530(A1),D1‰segment�when�the�controller�interrupts(*¦to�indicate�that�it's�ready�to�proceed'*¦with�the�I/O�operation.‚We�get�IOSPSM&*¦into�D1.W,�so�D1.W�now�indicates�the!*¦logical�sector�size�(in�bytes). 9‰TST.B„HALFSCTS(A1)‹If�the�next�sector�to�be�processed�is2‰BEQ.S„L0535�a�half�sector,�divide�the�sector�size2‰LSR.W„#1,D1�by�two�to�account�for�the�fact�that�a>‰SUB.B„#1,HALFSCTS(A1)†half�sector�has�only�half�as�many�bytes(*¦as�a�normal�sector.‚Then�decrement�the(*¦count�of�the�half�sectors�remaining�to%*¦be�processed.‚Half�sectors�arise�in'*¦track�zero�of�a�double-density�floppy(*¦disc�because�the�sectors�in�track�zero%*¦of�a�double-density�floppy�disc�are*¦recorded�with�single�density.-‰PAGEš#######################################‰MOVEP.L‚DATA0(A0),D0†|‚the�memory�map.‚Therefore,�the�MOVEP.L5‰MOVE.LƒD0,(A3)+Š|‚instruction�accesses�the�same�data(*§|‚register�four�consecutive�times�with/‰DBRA…D3,L0550Š----‚the�maximum�possible�speed. #*¨If�the�SASI�controller�happens�to$*¦suffer�from�a�catastrophic�failure)*¦during�this�loop,�we'll�get�a�bus�error*¦to�indicate�the�problem. 4‰DBRA…D1,READDATAŒIf�we�haven't�finished�reading�the&*¦current�sector�of�data,�loop�back�to(*¦read�the�next�chunk�of�LCDSCTSZ�bytes.$*¦By�reading�LCDSCTSZ�bytes�and�then)*¦checking�the�controller,�we�can�prevent&*¦the�careless�user�from�causing�a�bus*¦error. 0‰BRA.S„RWCOMMON�We've�finished�reading�an�entire(*¦sector�of�input�data,�so�now�go�to�the#*¦common�routine�that�completes�the&*¦processing�of�a�sector�for�both�read"*¦operations�and�write�operations. -‰PAGEš#######################################O*********************************************************************************ˆWRITE�A�SECTOR�OF�DATA*O******************************************************************************* GWRTDATA‚MOVEQBƒSELECTED+REQWRITE,D3ƒWe're�performing�a�write�operation,4‰BSR†CHKFLAGS�so�check�the�SASI�controller�to�verify)*¦that�the�controller�is�ready�to�receive'*¦output�data.‚Subroutine�CHKFLAGS�sets)*¦the�CC.Z�bit�if�the�controller�is�ready&*¦for�the�operation�indicated�in�D3.B.-‰PAGEš#######################################>L0560„SNE.B„NOFINISH(A1)‹If�the�controller�isn't�ready�for�the7‰BNE.S„READSTAT�proper�operation,�set�the�NOFINISH�flag%*¦and�go�try�to�read�the�controller's$*¦status�report.‚We�use�the�NOFINISH'*¦flag�to�indicate�that�a�read�or�write$*¦I/O�operation�has�failed�to�finish$*¦correctly�for�some�unknown�reason. &*¨Control�comes�through�this�same�code$*¦segment�if�the�controller�fails�to'*¦become�ready�for�the�proper�operation*¦during�a�read�transaction. .L0561„EQU†4*8”Each�iteration�of�the�inner�loop=L0562„EQU†LCDSCTSZ/L0561‡below�transfers�4*8�=�32�data�bytes,=L0563„EQU†L0562*L0561Šand�each�iteration�of�the�outer�loop�is9‰IFNE…LCDSCTSZ-L0563‡supposed�to�transfer�LCDSCTSZ�bytes./‰FAIL…0”[****�ERROR�****�ERROR�****�ERROR�****]+‰ENDCšTherefore,�we�must�verify�that�4*8�is#*¦an�exact�divisor�of�LCDSCTSZ.‚The#*¦instruction�that�is�conditionally&*¦assembled�here�generates�an�assembly)*¦error�if�4*8�is�not�an�exact�divisor�of%*¦LCDSCTSZ.‚If�this�error�occurs,�the(*¦maintenance�programmer�will�be�alerted(*¦to�change�the�inner�loop�below�to�make(*¦it�transfe r�some�other�number�of�bytes)*¦so�that�a�single�iteration�of�the�outer#*¦loop�can�transfer�LCDSCTSZ�bytes. @‰MOVEQWƒLCDSCTSZ/L0561-1,D3„Initialize�D3.W�to�control�the�inner'*¦loop.‚We'll�perform�enough�iterations(*¦of�the�inner�loop�to�transfer�LCDSCTSZ*¦bytes�of�data.-‰PAGEš#######################################?L0570„MOVE.Lƒ(A3)+,D0Š----‚Each�complete�iteration�of�this�loop>‰MOVEP.L‚D0,DATA0(A0)†|‚transfers�4*8�=�32�data�bytes�from�the(*§|‚output�buffer�to�the�SASI�controller8‰MOVE.Lƒ(A3)+,D0Š|‚and�we�perform�just�enough�iterations>‰MOVEP.L‚D0,DATA0(A0)†|‚of�this�inner�loop�to�transfer�a�total *§|‚of�LCDSCTSZ�bytes�during�one1‰MOVE.Lƒ(A3)+,D0Š|‚iteration�of�the�outer�loop.‹{‰MOVEP.L‚D0,DATA0(A0)†|©{#*§|„We�use�a�MOVEP.L�instruction�to7‰MOVE.Lƒ(A3)+,D0Š|‚transfer�four�consecutive�data�bytes?‰MOVEP.L‚D0,DATA0(A0)†|‚with�the�maximum�possible�speed,�and�we&*§|‚replicate�the�code�in�this�loop�to7‰MOVE.Lƒ(A3)+,D0Š|‚reduce�the�effects�of�loop�overhead.;‰MOVEP.L‚D0,DATA0(A0)†|‚We�could�replicate�the�code�in�this'*§|‚loop�more�times�for�even�more�speed8‰MOVE.Lƒ(A3)+,D0Š|‚but�diminishing�returns�begin�to�make?‰MOVEP.L‚D0,DATA0(A0)†|‚further�replications�less�attractive.�{*§|¤{8‰MOVE.Lƒ(A3)+,D0Š|„The�SASI�controller�actually�has�just<‰MOVEP.L‚D0,DATA0(A0)†|‚one�data�register,�but�that�register'*§|‚appears�at�4�different�locations�in9‰MOVE.Lƒ(A3)+,D0Š|‚the�memory�map.‚Therefore,�the�MOVEP.L:‰MOVEP.L‚D0,DATA0(A0)†|‚instruction�accesses�the�same�data%*§|‚register�4�consecutive�times�with/‰DBRA…D3,L0570Š----�the�maximum�possible�speed. #*¨If�the�SASI�controller�happens�to$*¦suffer�from�a�catastrophic�failure)*¦during�this�loop,�we'll�get�a�bus�error*¦to�indicate�the�problem. 3‰DBRA…D1,WRTDATA�If�we�haven't�finished�writing�the&*¦current�sector�of�data,�loop�back�to)*¦write�the�next�chunk�of�LCDSCTSZ�bytes.$*¦By�writing�LCDSCTSZ�bytes�and�then)*¦checking�the�controller,�we�can�prevent&*¦the�careless�user�from�causing�a�bus*¦error. &*¨We've�finished�transferring�a�sector&*¦of�output�data,�so�now�control�falls(*¦into�the�common�routine�that�completes%*¦the�processing�of�a�sector�for�both'*¦read�operations�and�write�operations. -‰PAGEš#######################################O********************************************************************************#*ˆCOMPLETE�PROCESSING�OF�READ/WRITE*#*ˆEntered�from:�READDATA�or�WRTDATA* *ˆExits�to:*O******************************************************************************* @RWCOMMON�MOVE.LƒA3,IOBUFPTR(A1)ˆUpdate�the�I/O�buffer�pointer�to#*¦point�to�the�next�byte�of�the�I/O&*¦buffer.‚If�there's�another�sector�of'*¦data�to�be�transferred,�IOBUFPTR�will'*¦be�used�to�address�the�I/O�buffer.‚If'*¦there�isn't�another�sector�of�data�to'*¦be�transferred,�we'll�use�IOBUFPTR�to)*¦calculate�the�number�of�bytes�that�were*¦actually�transferred. :‰SUB.B„#1,CMDSECTS(A5)ˆDecrement�the�count�of�sectors�that4‰BHI†NEXTSECT�remain�to�be�processed�for�the�current&*¦SASI�command�sequence.‚If�we�haven't(*¦finished�processing�all�of�the�sectors(*¦for�the�current�SASI�command�sequence,'*¦loop�back�to�process�the�next�sector. .‰TST.B„D2•We've�finished�processing�all�of�the5‰BGT.S„RDSTAT1Žsector(s)�for�the�current�SASI�command&*¦sequence.‚If�we're�performing�a�read%*¦operation,�go�read�the�controller's&*¦status�report.‚The�controller�should#*¦have�the�status�report�for�a�read$*¦operation�ready�almost�immediately(*¦after�the�last�sector�of�data�has�been%*¦read,�so�there's�no�advantage�to�be$*¦gained�by�returning�control�to�the(*¦system�to�wait�for�a�status-ready�SASI(*¦interrupt.‚Recall�that�D2.B�=�+1�for�a)*¦read�transaction�and�that�D2.B�=�-1�for*¦a�write�transaction. $*¨If�we're�performing�a�write�opera-)*¦tion,�fall�into�the�top�of�the�READSTAT%*¦routine.‚Control�will�return�to�the)*¦system,�and�we'll�get�control�back�when&*¦a�status-ready�interrupt�occurs.‚The'*¦controller �will�require�a�significant)*¦amount�of�time�before�it�has�its�status%*¦report�ready�because�it�must�do�the(*¦physical�writing�of�the�last�sector�of'*¦data�before�it�can�prepare�its�status *¦report. -‰PAGEš#######################################O********************************************************************************!*ˆREAD�THE�SASI�CONTROLLER�STATUS*O******************************************************************************* 7READSTAT�BSR.S„INTRTN‘Return�control�to�the�system,�and)*¦wait�for�a�status-ready�SASI�interrupt.&*¦We'll�get�control�back�when�the�SASI)*¦controller�has�its�status�report�ready. 5RDSTAT1‚BSR†GETSTAT�Get�the�status�bits�from�the�SASI6‰BNE.S„STATERRŽcontroller's�status�byte�into�D0.B,�and(*¦report�an�error�if�the�status�bits�are&*¦nonzero.‚A�status�bit�that�is�set�in(*¦the�controller's�status�byte�indicates&*¦an�error.‚Subroutine�GETSTAT�returns$*¦the�condition�codes�reflecting�the(*¦status�bits�from�the�SASI�controller's*¦status�byte.-‰PAGEš#######################################6‰MOVEQBƒISTACFG,D1�If�the�NOFINISH�flag�is�nonzero,�we8‰TST.B„NOFINISH(A1)‰return�a�status�code�indicating�that4‰BNE.S„SASIDONE�the�actual�configuration�of�the�disc(*¦doesn't�match�the�configuration�in�the%*¦current�configuration�block.‚An�I/O)*¦operation�failed�to�finish�properly,�so&*¦the�sector�size�on�the�disc�probably&*¦doesn't�match�the�sector�size�in�the*¦configuration�block. 8‰TST.L„IOSCTCNT(A1)‹The�SASI�controller�has�successfully1‰BNE†PROCQUEŽcompleted�the�entire�I/O�transaction(*¦that�was�specified�by�the�last�command(*¦sequence�that�we�gave�it.‚If�there�are'*¦any�sectors�remaining�to�be�processed)*¦for�the�current�entry�of�the�I/O�queue,'*¦loop�back�to�process�another�chunk�of*¦the�entire�I/O�transfer. %*¨Recall�that�IOSCTCNT�is�always�zero&*¦for�any�I/O�transaction�that�doesn't(*¦involve�the�transfer�of�any�read/write*¦data. 9‰MOVE.BƒEOVFLAG(A1),D1‰We've�now�completed�the�entire�I/O'*¦transaction�that�was�specified�by�the$*¦command�that�generated�the�current%*¦entry�of�the�I/O�queue.‚The�EOVFLAG'*¦value�that�we�get�into�D1.B�here�will#*¦be�returned�to�the�user�as�an�I/O&*¦status�code.‚If�the�I/O�transfer�was'*¦truncated�to�avoid�running�beyond�the(*¦end�of�the�disc,�we�return�the�ISTAEOV'*¦status�code.‚Otherwise,�we�return�the)*¦ISTAOK�status�code�to�indicate�that�the!*¦entire�operation�went�smoothly. %*¨Control�now�falls�into�the�SASIDONE"*¦routine�to�finish�processing�the!*¦current�entry�of�the�I/O�queue. -‰PAGEš#######################################O*********************************************************************************ˆFINISH�PROCESSING�QUEUE�ENTRY*B*ˆControl�comes‚to�the�top‚of�this‚co-routine�when�the�SASI�driverC*ˆis�ready�to�finish‚processing‚the�current�entry�of�the‚I/O�queue.E*ˆEither�we've�completed�the�I/O�transaction�that�is�specified�by�theC*ˆcurrent�wntry�of�the‚queue,�or�else�we've‚run�into�some�unreason-G*ˆable�problem�that�we�can't�solve.�We'll�queue�an�I/O�completion�eventC*ˆto�the�attached�task,�and�we'll‚remove�the‚current�entry�from�theD*ˆI/O�queue.‚If�the�I/O�queue�has�another�entry,�we'll�loop�back�and*ˆstart�processing�it.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB*’A5�=�physical�address�of�CCB*�D1.B�=�status�value*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*�*�P*3*ˆExits�to:‚IDLELOOP�routine�if�I/O�queue�is�empty.4*“PROCQUE�if�the�I/O�queue�contains�an�active�entry.*O******************************************************************************* 3SASIDONE�EQU†*–We�use�a�MOVEM.L�instruction�to�pull=L0630„REG†D0/D2/A1/A3/A4‡several�variables�out�of�the�currentA‰MOVEM.L‚IOBUFLOC(A1),L0630ƒI/O�packet�in�one�step.‚This�instruc-(*¦tion�sets�up�the�registers�as�follows. L1‡SET†IOBUFLOC�D0�=�IOBUFLOC.L1‡SET†IOBUFPT R�D2�=�IOBUFPTR.L1‡SET†IOBUFTCB�A1�=�IOBUFTCB.5L1‡SET†DCBPNTRŽA3�=�DCBPNTR.‚(For�subroutine�QEVENTI)5L1‡SET†IOCBPTRŽA4�=�IOCBPTR.‚(For�subroutine�QEVENTI) $*¨The�SET�instructions�that�are�used'*¦here�are�just�dummy�instructions�that&*¦generate�artificial�label�references%*¦for�the�concordance�listing.‚Future)*¦maintenance�programmers�will�be�able�to)*¦use�the�concordance�listing�to�discover$*¦that�this�segment�of�code�accesses*¦these�variables.-‰PAGEš#######################################1‰SUB.L„D0,D2’Now�compute�the�number�of�data�bytes=‰MOVE.LƒD2,IOSLEN(A4)ˆthat�we�actually�transferred,�and�store&*¦that�number�into�the�IOSLEN�field�of%*¦the�IOCB.‚For�an�I/O�operation�that%*¦doesn't�involve�the�transfer�of�any%*¦read/write�data,�we�have�IOBUFLOC�=)*¦IOBUFPTR,�so�we�properly�set�IOSLEN�=�0*¦in�this�case. 8‰LEA†ERRDISK(PC),A2‰Use�the�Versados�error�code�to�check:WHEEL„MOVE.Bƒ(A2)+,D2�whether�the�IOSRRN�field�of�the�IOCB2‰BEQ.S„NOCOPY�needs�updating.�If�the�error�code�is4‰CMP.B„D2,D1�found�in�the�table�ERRDISK,�then�update3‰BNE.S„WHEEL�the�IOSRRN�field�in�the�IOCB.�The�last1‰MOVE.LƒD3,IOSRRN(A4)ˆentry�in�the�table�is�zero. 3NOCOPYƒBSR†QEVENTI�Subroutine�QEVENTI�queues�an�I/O(*¦completion�event�to�the�attached�task.)*¦Registers�A5,�A4,�A3,�and�D1.B�must�all)*¦be�set�properly�when�we�call�subroutine *¦QEVENTI. 9‰SUB.B„#1,TCBIOCNT(A1)ˆDecrement�the�count�of�outstanding'*¦I/O�operations�for�the�task�that�owns)*¦the�I/O�buffer�(or�the�IOCB�in�the�case%*¦of�a�format�command�or�a�configure-*¦floppy�command). 6L0640„REG†A1/A3/A4�Here�we�remove�the�front�entry�fromA‰MOVEM.L‚IOQUEUE+4(A5),L0640‚the�I/O�queue,�and�we�simultaneouslyA‰MOVEM.L‚L0640,IOQUEUE(A5)„set�A1�to�point�to�the�drive�block�for(*¦the�disc�drive�that�is�associated�with$*¦the�next�(if�any)�entry�of�the�I/O%*¦queue.‚Since�there�are�a�maximum�of(*¦four�entries�in�the�I/O�queue,�we�need'*¦to�move�no�more�than�three�entries�to(*¦remove�the�first�entry�from�the�queue. 6‰SUB.W„#4,IOQCNT(A5)ŠReduce�the�queue-count�pointer�to1‰BHI†PROCQUEŽaccount�for�the�fact�that�we've�just(*¦removed�a�four-byte�entry�from�the�I/O$*¦queue.‚If�there�is�still�an�active&*¦entry�in�the�I/O�queue,�loop�back�to"*¦start�processing�the�next�entry. $*¨If�the�I/O�queue�is�empty,�control(*¦falls�into�the�co-routine�segment�that%*¦is�potentially�active�when�the�SASI'*¦controller�is�caught�up�and�should�be*¦idle. -‰PAGEš#######################################O*********************************************************************************ˆIDLE�LOOP�ROUTINE*C*ˆControl�falls�into�this�co-routine‚segment�when�the‚I/O�queue�hasD*ˆbeen�emptied.‚The�SASI�controller�is�completely�caught�up�with�all?*ˆof�its�requests,‚and�the‚controller‚should‚now�be‚idle.‚We'llB*ˆsimply�return�control�to�the‚system�to‚idle�the‚SASI‚controller.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*�*�P*D*ˆExits�to:‚Stays�in�loop�until�the�driver�receives�another�command.*O******************************************************************************* :IDLELOOP�BSR.S„INTRTN‘The�I/O�queue�is�empty,�so�we�simply%*¦return�control�to�the�system.‚We've)*¦caught�up�with�all�of�the�requests�that'*¦have�been�set�up�for�processing�under*¦interrupt�control. *ˆExits�to:‚SASIDONE�to�terminate�processing�for�the�activity.*O******************************************************************************* 7CTRLERR1�ADDQ.Lƒ#4,SP’Control�comes�to�this�entry�point%*¦when�a�controller�error�is�detected%*¦from�within�a�subroutine.‚We�remove&*¦the�subroutine's�return�address�from(*¦the�stack,�s o�the�stack�is�restored�to&*¦the�condition�that�it�had�before�the*¦subroutine�was�called.-‰PAGEš####################################### >CTRLERR‚ST.B…SASIDOWN(A5)‹Down�the�SASI�channel�by�setting�the"*¦variable�that�indicates�that�the#*¦controller�is�down.‚If�the�system(*¦tries�to�access�the�SASI�channel�again#*¦without�resetting�it�first,�we'll%*¦report�an�error�indicating�that�the$*¦channel�is�down.‚The�system�really"*¦shouldn't�try�to�access�the�SASI'*¦channel�again�without�first�resetting$*¦the�controller.‚Even�resetting�the)*¦controller�may�not�correct�the�problem,'*¦but�we'll�let�the�system�try�as�often*¦as�it�wishes. 5‰MOVEQBƒISTACNT,D1�Set�up�D1.B�for�reporting�a�status5‰BRA†SASIDONE�code�that�indicates�a�controller�error,%*¦and�go�terminate�processing�for�the!*¦current�entry�of�the�I/O�queue. -‰PAGEš#######################################O******************************************************************************** *ˆCHKFLAGS.AL*O******************************************************************************* GREADRDY‚MOVEQBƒSELECTED+REQREAD,D3„This�special�entry�point�is�used�for(*¦checking�the�SASI�controller�to�see�if(*¦it�has�input�data�ready�to�transfer�to(*¦us.‚We�get�the�proper�FLAGS�value�into'*¦D3.B,�and�then�control�falls�directly'*¦into�the�main�entry�point�for�subrou-*¦tine�CHKFLAGS. -‰PAGEš#######################################:*ˆControl�sometimes�falls�into�this�subroutine�from�above.  ½GÅ8Í*Õ;Ý6å8í2õý*8 484%P-L5T=@E.M(U%]eE'*¦processor�in�a�standard�EXORmacs�runs&*¦at�8.0�megahertz�for�a�cycle�time�of*¦0.125�microseconds.‰PAGEO*********************************************************************************ˆINTERRUPT�CO-ROUTINE�LINKAGE*D*ˆThis�routine�is�entered�either�due�to�a�WDC�interrupt�or�jumped�toD*ˆfrom�the�command�processor�if�WDC�is�executing�a�previous�command.@*ˆWe'll�turn�off�the�interrupts,�save�registers,�and�jump�to‚the*ˆexpected�co-routine.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7%*™D„#�#�#�#�=�Saved�to�use�as�working#*™A‚P�*ƒ#�#�P�registers�throughout.*=*ˆExit:…Jump�to�co-routine�segment�addressed�by�INTSWTCH(A5).*O************ ******************************************************************* .SASIINT‚EQU‡*•We�know�we�have�a�WDC�interrupt.5‰MOVE.Bƒ#DSBLDINT,INTCTRL(A0)‚Disable�data�interrupt.)‰BTST.Bƒ#BITCB,FLAGS(A0)‡Is�the�WDC�busy?+‰BNE.S„L0431’Yes.�Must�be�a�data�interrupt.@‰MOVE.BƒSENSE(A0),SENSBYT0(A5)�The�WDC�is�not�busy,�so�clear�the"*¨command�completion�interrupt�and"*¨the�DRQ�by�reading�SENSE�byte�0. @L0430„REG†A4/A3/A2/D3/D2/D1†A5,�A1,�A0,�and�D0�have�already�been@L0431„MOVEM.L‚L0430,-(SP)Šsaved�by�CMR.‚Here�we�save�the�rest�of'*¦the�registers�that�we�need�to�use.‚We(*¦save�only�the�registers�that�we�really%*¦need�because�we�don't�want�to�waste(*¦time�or�stack�space.‚Time,�especially,'*¦is�important�in�an�interrupt�handler. <‰MOVE.LƒIOQUEUE(A5),A1‰Set�A1�=�LOC(Drive's�variable�block).)*¦The�first�entry�of�the�IOQUEUE�contains)*¦a�pointer�to�the�variable�block�for�the)*¦disc�drive�that�we�should�be�accessing. =‰MOVE.LƒINTSWTCH(A5),A3ˆBranch�to�the�co-routine�segment�that0‰JMP†(A3)‘should�be�executed�next.‚The�registers*¦are�set�up�as�follows. *¦A5�=�LOC(CCB).˜{*¦A4�=�Scratch.™{*¦A3�=�Scratch.™{%*¦A1�=�LOC(Drive's�variable�block).…{"*¦A0�=�LOC(SELECT)�=�LOC(FLAGS).ˆ{ %*¨Control�will�eventually�return�from(*¦the�selected�co-routine�segment�to�the&*¦INTRTN�routine,�which�implements�the*¦return�linkage�to�the�system. PAGEO*********************************************************************************ˆWINCHESTER�OPCODE�TABLE*E*ˆThe�Winchester�opcode�table�contains�the�WDC-defined�values�for�the9*ˆI/O�operations�that�are�currently�supported�by�the�WDC.*O******************************************************************************* 1*’---------------------------�WDC�Opcode�value.�{*’|¹{!*’|”------�IOFUNCT�index�value.Š{*’|”|¤{*’|”|¤{*’V”V¤{‰DC.B…$0A’-1�=�Write�disc.–{!OPTBL„DC.B…$04“0�=�Format�disc.•{ ‰DC.B…$C0’+1�=�Configure�drive’{‰DC.B…$08’+2�=�Read�disc.—{5FTRACKƒDC.B…$06”The�opcode�for�a�format-track�command)*¦is�not�indexed�by�the�IOFUNCT�value�for%*¦a�format-track�command.‚The�format-$*¦track�command�has�the�same�IOFUNCT&*¦value�that�is�used�for�a�format-disc'*¦command,�and�we�uniquely�identify�the'*¦format-track�command�by�the�fact�that(*¦its�IOOPTS�value�is�different�from�the)*¦IOOPTS�value�that�is�used�for�a�format-(*¦disc�command.‚Then�we�compute�a�pseudo'*¦IOFUNCT�value�that�indexes�from�OPTBL *¦to�FTRACK.K*****************************************************************************ˆBWN‡2/13/84ƒPJD‡9/19/84*0ALTSECƒDC.B†$07‘Here's�the�opcode�for�the�format*¦alternate�sectors�command.#*¦We'll�do�the�same�trick�as�above.*J**************************************************************************  '‰DS.W…0–This�statement�ensures�that�the'*¦location�counter�is�aligned�to�a�word ‰PAGEO*********************************************************************************ˆPROCESS�NEXT�QUEUE�ENTRY*E*ˆControl�comes�to�this�co-routine�segment�to�process�the�front�entryA*ˆof�the�IOQUEUE.‚We�are�guaranteed�that�the�IOQUEUE�is�non-empty%*ˆwhen�control�comes�to�this�routine.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�* *™A„Pƒ*ƒP**ˆExit:*O******************************************************************************* =PROCQUE‚LEA†CMDEND(A5),A3ŠWe�start�by�pointing�A3�to�the�byte(*¦that�immediately�follows�the�last�byte(*¦of�the�command�packet�in�memory.‚We'll(*¦use�autodecrement�addressing�to�access*¦the�command�packet. ?‰MOVE.BƒCTRLCODE(A1),-(A3)…Copy�the�control-code�value�from�the%*¦drive's�I/O�packet�into�the�CMDCTRL*¦field�of�the�command�packet. ;* WE'LL ASSUME A READ OR WRITE COMMAND, SINCE MOST WILL BE. ‰CLR.L„D07‰MOVE.BƒHALFSCTS(A1),D0†Are�any�half�sectors�specified?)‰BNE.S„L0470�YES.�READ�HALF�SECTORS�FIRST >‰MOVE.LƒIOSCTCNT(A1),D0† Get�the�total�#�of�sectors�to�transfer‰MOVE.Lƒ#MAXSECTS,D12‰CMP.L„D1,D0�Is�#�required�<=�MAX�per�WDC�command?*‰BLS.S„L0470�Yes.�This�requires�1�command.0‰MOVE.LƒD1,D0�NO.�Transfer�Max.�in�this�command.9L0470„MOVE.BƒD0,-(A3)�Move�#�of�sectors�to�command�packet PAGE%*¨If�we're�processing�a�command�(such#*¦as�a�format�command)�that�doesn't)*¦involve�an�actual�I/O�transfer,�we�have*¦IOSCTCNT�=�0. <‰SUB.L„D0,IOSCTCNT(A1)ˆReduce�the�count�of�remaining�sectors'*¦by�the�number�of�sectors�that�will�be'*¦processed�as�a�result�of�this�command'*¦packet.‚If�this�command�packet�is�the(*¦last�(or�only)�command�packet�for�this'*¦I/O�transaction,�we�have�IOSCTCNT�=�0*¦now. =‰MOVE.LƒIOSECTOR(A1),-(A3)…We�use�the�IOSECTOR�value�from�the?‰AND.W„#LSNMASK>>16,(A3)+ƒdisc�drive's�I/O�packet�to�set�up�the<‰MOVE.BƒDRIVENUM(A1),D1†logical�sector�number�in�the�command:‰LSL.B„#LUNFIELD,D1‰packet.‚We�also�use�the�DRIVENUM�value5‰OR.B…D1,-(A3)�from�the�drive's�I/O�packet�to�set�the(*¦LUN�(Logical-Unit-Number)�field�in�the%*¦command�packet.‚Notice�that�the�LUN&*¦field�in�the�command�packet�occupies'*¦the�top�few�bits�of�the�first�byte�of(*¦the�LSN�(Logical-Sector-Number)�field. 9‰ADD.L„D0,IOSECTOR(A1)ˆIncrease�the�IOSECTOR�value�in�the%*¦drive's�I/O�packet�by�the�number�of%*¦sectors�that�will�be�processed�as�a%*¦result�of�this�command�packet.‚This(*¦adjustment�causes�IOSECTOR�to�point�to)*¦the�sector�that�should�be�specified�for(*¦the�next�(if�any)�command�packet�after *¦this�one. ;‰MOVE.BƒIOFUNCT(A1),D0‰Get�the�IOFUNCT�code�into�D0.W�so�we*‰EXT.W„D0“can�use�it�to�index�into�the�WDC1‰BNE.S„L0481�opcode�table.‚If�the�IOFUNCT�code�is(*¦nonzero,�we�aren't�processing�a�format'*¦command.‚In�this�case,�we�can�use�the&*¦IOFUNCT�value�directly.‚For�a�format#*¦command,�however,�we�must�do�some*¦special�processing. PAGE>L0480„EQU†CONFGBLK+IOSILVˆFor�a�format�command�we�must�install@‰MOVE.BƒL0480(A1),CMDILV(A5)�an�interleave�value�into�the�CMDILV$*¦field,�which�overlays�the�CMDSECTS'*¦field�of�the�command�packet.‚There�is'*¦no�sector�count�for�a�format�command,'*¦but�the�controller�requires�an�inter-%*¦leave�code�in�place�of�the�CMDSECTS*¦field�for�a�format�command.* I***************************************************************************ˆBWN‡2/13/84ƒPJD‡9/19/84*>****…BTSTW„#IOPTRKB,IOOPTS(A1)„If�the�IOOPTS�value�in�the�disc8****…BEQ.S„L0490�drive's�I/O�packet�indicates�that�we're*'‰CMP.W…#IOPDSK,IOOPTS(A1)‚Format�disk�?‰BEQ.S…L0490�Branch�if�yes.*>*ˆUse�a�compare�instead�to�see�if�we�have�a�plain�format�track *ˆcommand.*-‰CMP.W…#IOPTRK,IOOPTS(A1)‚Plain�format�track?,‰IF‚‚THEN.SŽIf�not,�see�if�it's�a�format *¦alternate�sector�type�command.*"ŽIFƒIOOPTS(A1)‚<EQ>‚#IOPBAD…THEN.S +“MOVEQB„ALTSEC-OPTBL,D0‡If�alternate�sector*²type�command,�then*²set�up�to�get�ALTSEC *²command. “BRA.S…L0490 ŽENDI ‰ENDI*H************************************************************************:‰MOVEQWƒFTRACK-OPTBL,D0†processing�a�format-track�command,'*¦adjust�D0.W�to�index�the�format-track *¦entry�of�the�WDC�opcode�table.%*¦Otherwise,�D0.W�already�indexes�the%*¦format-disc�entry�of�the�WDC�opcode*¦table. #*¨We�use�a�single�IOFUNCT�value�for&*¦both�the�format-disc�command�and�the&*¦format-track�command.‚We�distinguish)*¦one�command�from�the�other�by�examining*¦their�IOOPTS�values.L0481;L0483„EQU†CONFGBLK+IOSSPTˆFor�all�commands,�change�6th�byte(*¦to�single-density,�128�bytes/sector�if(*¦we�are�on�track�0�(floppy�discs�only).*/‰CLR.L„D1•Compare�the�#�of�sectors�per�track�to=‰MOVE.BƒL0483(A1),D1‰the�starting�sector�#�in�the�cmd�packet.8‰CMP.W„1(A3),D1�When�it's�within�Track�0,�change�CMDCTRL1‰BLE.S„L0490�to�single�density,�128�bytes/sector.4CHGSSCƒEQU†$C7”Notice�A3�is�pointing�to�the�2nd�byte+‰AND.B„#CHGSSC,4(A3)ˆof�the�command�packet.&*¨This�is�valid�for�a�floppy�only.‚The)*¦starting�sector�#�will�never�be�greater!*¦than�a�word�value�for�a�floppy. L0490„EQU‡* I************************************************************************** *ˆBWN‡2/13/84*?*ˆBecause�of�the�added�code,�we�get�a�displacement�error�on�the*ˆcommented�out�statement.*‰LEA‡OPTBL(PC),A4‰MOVE.B„0(A4,D0.W),-(A3)D***†MOVE.BƒOPTBL(PC,D0.W),-(A3)ƒFinally,�fill�the�CMDOP�field�of�the**O********************************************************************************)*¦command�packet�from�the�proper�entry�of&*¦the�WDC�opcode�table.‚Notice�that�A3&*¦now�points�to�the�CMDOP�field�of�the'*¦command�packet,�so�we�can�use�A3�with)*¦autoincrement�addressing�as�we�send�the(*¦command�packet�to�the�SASI�controller.#***********************************ééGSENDNEW‚BTSTW„#IOPRTYB,IOOPTS(A1)ƒcheck�for�no�retry�option�on�this�cmd‰BNE.S„SENDNEW12‰MOVE.Bƒ#RETRYCNT,RETRY(A5)„Initialize�retry�count‰BRA.S„SENDAGN@SENDNEW1�MOVE.Bƒ#$01,RETRY(A5)ˆtell�firmware�'no�retries�please'%*************************************7SENDAGN‚BSR†SENDCMD�Send�the�command�packet�to�the�WDC.$*¦controller,�and�subroutine�SENDCMD'*¦assumes�that�A0�points�to�the�memory-*¦mapped�I/O�area�for�the�WDC.* *¨Control�falls�thru�to�the�data*¦handling�part�of�the�driver.‰PAGEO*********************************************************************************ˆDATA�HANDLER*B*ˆWe�assume�that�the�command�is�a�data�transfer�type�(i.e.�read�or?*ˆwrite)�and�set�up�to�transfer�a�sector.‚This�is�wasted�if�theéééééB*ˆcommand�is�a�configure�or�format�but�since�most�comands�are�R/W,*ˆwe�won't�worry�about�it.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*ƒP**ˆExit:*O******************************************************************************* NEXTSECT�EQU†*L0491„EQU†CONFGBLK+IOSPSM3‰MOVE.WƒL0491(A1),D1‹Get�the�number�of�bytes/sector2‰TST.B„HALFSCTS(A1)‹Does�this�command�involve�half *¦sectors?‰BEQ.S„L0530’No.)‰LSR.W„#1,D1’Yes.�Divide�sector�size�by�2 7‰IFNE…LCDSCTSZ-128‹The�driver�depends�on�LCDSCTSZ�to�be‰FAIL…0”equal�to�128.‰ENDCœIf�this�error�occurs,�the(*¦mainte nance�programmer�will�be�alerted*¦of�the�error. PAGE;L0530„LSR.W„#LCDSCTBT,D1‰D1.B�=�number�of�blocks/sector�for*¨the�current�command.%‰MOVE.BƒD1,BLKCNT(A5)ˆSave�the�count. 7NEXTSEC1�BSR†INTRTN‘The�WDC�controller�needs�time�to�do$*¦its�job�before�we�can�transfer�any(*¦data,�so�return�control�to�the�system.&*¦When�the�WDC�controller�has�finished$*¦its�current�task,�we'll�receive�an&*¦interrupt�that�will�cause�control�to(*¦come�back�here.‚The�co-routine�linkage)*¦conveniently�allows�us�to�call�the�rest&*¦of�the�system�as�if�it�were�simply�a)*¦subroutine�to�be�executed�while�we�have*¦nothing�better�to�do.  *¦THE�INTERRUPT�ENTERS�HERE<‰MOVE.LƒIOBUFPTR(A1),A3ˆPoint�A3�to�the�next�byte�of�the�I/O&*¦buffer.‚We�now�have�both�A3�and�D1.W%*¦set�up�properly�for�a�read�or�write'*¦transaction.‚If�we're�performing�some&*¦other�kind�of�transaction�(such�as�a(*¦format�command),�we've�simply�wasted�a(*¦little�time�by�setting�up�A3�and�D1.W. ;‰MOVE.BƒIOFUNCT(A1),D2‰Set�D2.B�=�+1�for�a�read�transaction2‰ASR.B„#1,D2�or�-1�for�a�write�transaction.‚We�setO*********************************************************************************ˆBWN‡2/15/84ƒPJD‡9/19/84**ˆCommented�out�this�line:3****…BEQ†RDSTAT1ŽD2.B�=�0�for�any�other�kind�of�I/O#*¦transaction.‚If�the�command�we're&*¦processing�is�neither�a�read�command(*¦nor�a�write�command,�we�have�a�COMMAND"*¦COMPLETION�and�can�check�status.**ˆInstead,�do�this�branch:*‰BNE.S…RD_WR�If�this�is�a�read�or�a�write, *¦go�do�it*%*ˆNow�take�care�of�the�format�command**/‰IF.B†IOFUNCT(A1)‚‚#FMTFUNCƒTHEN.S„Format�?*9*ˆThe�effect�of�formatting�sectors�as�good�is�the�same�as<*ˆthe�usual�formatting�track,�so�we�decided�to�leave�it�out.* *ˆFormat�track�sectors�as�"good"**/**ŒCMP.WŠ#IOPGOOD,IOOPTS(A1)„"Format�as�good�?"**ŒIFƒƒTHEN.S‘Yes�.....'**‘MOVE.B„#GOODCODE,D5�D5.B�<---�Opcode-**‘MOVE.B„#32,D2ŽD2.B�<---�First�"bad"�sector*°If�greater�than�or�equal�to*°32,�then�no�bad�sectors.*'**‘BSR‡SEND_BYTESŠSend�the�256�bytes�of*°format�descriptor�to�the *°controller.*?*ˆWe�want�to�disable�the�data�interrupt�because�we�are�all�doneC*ˆsending�data.�The�CMDSECTS�field,�which�is�the�same�as�the�CMDILVA*ˆ(interleave�factor)�field,�must�be�set�to�0,�as�it�is�tested�in *ˆINTRTN.***‘SF.B†CMDSECTS(A5)**‘BRA‡READSTATŒGo�read�status*°(just�like�a�data�transfer)***ŒENDI***ˆFormat�track�sectors�as�"bad"** )ŽCMP.WŠ#IOPBAD,IOOPTS(A1)‚Format�as�bad�?ŽIFƒƒTHEN.S–Yes�...,“MOVE.W„ALTCYL(A1),D0…D0.W�<---�cylinder�no.*°of�alternate�sector6“MOVE.B„ALTHEAD(A1),D1„D1.B�<---�head�no.�of�alternate3“MOVE.B„BADSEC(A1),D2…D2.B�<---�first�bad�sector�in*°track.*,“MOVE.B„#GOODCODE,D5ˆD5.B�<---�Opcode�(good)+“BSR‡SEND_BYTESŠSend�256�bytes�to�controlle*°to�mark�sectors�0�through*°sector�no.�-�1‚as‚"good",*°and�the�sectors�from *°sector�no.*°through�31�as�"bad",*°designating�corresponding*°sectors�on�the�alternate*°track�as�"alternates".**?*ˆWe�want�to�disable�the�data�interrupt�because�we�are�all�doneC*ˆsending�data.�The�CMDSECTS�field,�which�is�the�same�as�the�CMDILVA*ˆ(interleave�factor)�field,�must�be�set�to�0,�as�it�is�tested�in *ˆINTRTN.*“SF.B†CMDSECTS(A5)(“BSR‡INTRTNŽWait�for�controller�to�do�it**3“BTST.B„#BITCB,FLAGS(A0)„Is�WDC�busy?�Shouldn't�be. “BNE‡CTRLERR/“TST.B…SENSBYT0(A5)ˆAny�errors�on�this�command?“BNE.L…CHECKERR***ˆMark�sectors�as�"alternates"*>*ˆWe�must�restore�the�interleave�factor�in�the�command�packet.**&“MOVE.B„CONFGBLK+IOSILV(A1),CMDILV(A5) )“BSR‡SET_UP_ALTŠSet�up�"format�alternate"*°command�packet.*;*ˆSENDCMD�expects�to�find�the�address�of�the�command�packet*ˆin�A3.*“LEA‡CMDOP(A5),A3 “BSR‡SENDCMD “BSR‡INTRTN 2“MOVE.B„#ALTCODE,D5‡D5.B�<---�Opcode�for�alternate*)“MOVE.B„#32,D2ŽD2.B�<---�first�sector�no.*°to�be�marked�"bad".,“BSR‡SEND_BYTES‡Send�256�bytes�to�controller*°to�mark�all�sect ors�of�the *°alternate�track�as�"alternate"*?*ˆWe�want�to�disable�the�data�interrupt�because�we�are�all�doneC*ˆsending�data.�The�CMDSECTS�field,�which�is�the�same�as�the�CMDILVA*ˆ(interleave�factor)�field,�must�be�set�to�0,�as�it�is�tested�in *ˆINTRTN.*“SF.B†CMDSECTS(A5) “BRA‡READSTATŽENDI ‰ENDI*‰BRA‡RDSTAT1—If�control�reaches�this�point*°we�have�a�command�completion*°and�can�check�status. RD_WR„EQU‡*K*************************************************************************** 8‰MOVE.BƒFLAGS(A0),D0‹If�we're�performing�a�data�transfer *¦the�controller�should�be�BUSY.éé*%%%%%%%%%%%%ƒBWN‚12/21/84**‚Here's�the�problem:*?*‚How�do�we�get�the�correct�sector�number�to�be�returned�to�IOS>*‚when�there�is�an�error�here�(like�track/sector�ID�not�found)G*‚and�also�when�there�is�another�error�later�on�after�we�have�upped�theB*‚LSN�and�decremented�the�CMDSECTS�in�the�command�packet,�and�alsoD*‚keep�the�correct�sector�number�for�retries�and�correctible�errors?*B*‚If�an�error�occurs�here,�we�will�not�read�or�write�any�data�into?*‚the�user�buffer,�so�retries�and�correctibility�do�not�matter.-*‚We�will�definitely�have�an�error�to�report.*D*‚Since�at�this�point�we�have�the�current�LSN�in�the�command�packet,?*‚we�are�going�to�go�right�to�STATERR.‚If�we�have�to�update�the6*‚RRN�for�the�IOS�parameter�block,�it�will�be�correct.*,**‡BPL†CHECKERR�NOT�BUSY.�Go�to�check�error. ‰BPL‡STATERR*D*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ‰BTST…#BITDRQ,D0�Is�DRQ�on.3‰BEQ†CTRLERRŽWe�don't�know�why�there's�an�interrupt*@*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>* *ˆbwn‡3/5/84*=*ˆDouble�check�that‚we�will�not�read�or�write�past�the�end�of$*ˆthe�buffer�on�our�next�read/write.1*ˆStarting�address�is�in�A3,�ending�address�is�in8*ˆIOBUFEND,�and�we�are�about�to�transfer�LCDSCTSZ�bytes.**(‰MOVE.L„A3,D0™D0�<---�Starting�address�+‰ADD.L…#LCDSCTSZ-1,D0˜128�-�1‰CMP.L…IOBUFEND(A1),D0'‰IFˆƒTHEN.S‘About�to�go�past�user's*°buffer�?�NOT�NICE�!!!“TST.B…D2’If�this�is�a�read,�thenéé*“IFƒƒTHEN.SŒRead�bytes�into�bit�bucket˜BSR.S…READJUNK˜BRA‡RWCOMMON‡Then�continue�on.“ENDI*C*ˆIf�this�was�a�write,�and�you�miscalculated,�you�are�going�to�mess*ˆup�the�disk.* ‰ENDI*D*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *‰TST.B„D2•Check�for�read�or�write�command.'‰BLT.S„WRTDATAŽBRANCH�IF�WRITE�COMMAND.*¨FALL�THRU�ON�READ ‰PAGEO********************************************************************************C*ˆREAD�DATA�ROUTINE�entered�after�a�WDC�interrupt�(DRQ)�for�a�read.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB)*’A3�=�pointer�to�next�byte�of�I/O�buffer*’A5�=�physical�address�of�CCB*!*ˆRegi ster�usage:…0�1�2�3�4�5�6�7*™D‚*…**™A‚P…**9*ˆExit:…Branches�to�read/write�common�routine�(RWCOMMON).*O******************************************************************************* READDATA�EQU†*.L0546„EQU†4*8”Each�iteration�of�the�inner�loop%*¦below�transfers�4*8�=�32�data�bytes @‰MOVEQWƒLCDSCTSZ/L0546-1,D3„Initialize�D3.W�to�control�the�inner'*¦loop.‚We'll�perform�enough�iterations(*¦of�the�inner�loop�to�transfer�LCDSCTSZ(*¦bytes�of�data,�which�must�and�has�been*¦checked�to�be�=�128 PAGEDL0550„MOVEP.L‚DATA0(A0),D0†----ƒEach�complete�iteration�of�this�loop9‰MOVE.LƒD0,(A3)+Š|ƒtransfers�4*8�=�32�data�bytes�from�the'*§|ƒWDC�controller�to�the�input�buffer,=‰MOVEP.L‚DATA0(A0),D0†|ƒand�we�perform�just�enough�iterations9‰MOVE.LƒD0,(A3)+Š|ƒof�this�inner�loop�to�transfer�a�total *§|ƒof�LCDSCTSZ�bytes�during�one4‰MOVEP.L‚DATA0(A0),D0†|ƒiteration�of�the�outer�loop.‰MOVE.LƒD0,(A3)+Š|#*§|ƒWe�use�a�MOVEP.L�instruction�to<‰MOVEP.L‚DATA0(A0),D0†|ƒtransfer�four�consecutive�data�bytes:‰MOVE.LƒD0,(A3)+Š|ƒwith�the�maximum�possible�speed,�and�we&*§|ƒreplicate�the�code�in�this�loop�to<‰MOVEP.L‚DATA0(A0),D0†|ƒreduce�the�effects�of�loop�overhead.6‰MOVE.LƒD0,(A3)+Š|ƒWe�could�replicate�the�code�in�this'*§|ƒloop�more�times�for�even�more�speed=‰MOVEP.L‚DATA0(A0),D0†|ƒbut�diminishing�returns�begin�to�make8‰MOVE.LƒD0,(A3)+Š|ƒfurther�replications�less�attractive.*§|<‰MOVEP.L‚DATA0(A0),D0†|…The�WDC�controller�actually�has�just7‰MOVE.LƒD0,(A3)+Š|ƒone�data�register,�but�that�register'*§|ƒappears�at�4�different�locations�in>‰MOVEP.L‚DATA0(A0),D0†|ƒthe�memory�map.�Therefore,�the�MOVEP.L9‰MOVE.LƒD0,(A3)+Š|ƒinstruction�actually�accesses�the�same%*§|ƒdata�register�four�times�with�the+‰DBRA…D3,L0550Š----‚maximum�possible�speed.  1‰BRA.S„RWCOMMON�We've�finished�reading�a�complete'*¦block�of�input�data,�so�now�go�to�the#*¦common�routine�that�completes�the*¦processing�for�both�read"*¦operations�and�write�operations.‰PAGEO********************************************************************************B*ˆREADJUNK‚ROUTINE�entered�after�a�WDC�interrupt�(DRQ)�for�a�read.D*ˆwhen�we�realize�that�we�are�about�to�write�past�the�user's�buffer.2*ˆWe�will�just�read�the�bytes�into�the�bit�bucket.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB)*’A3�=�pointer�to�next�byte�of�I/O�buffer*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*…**™A‚P…**9*ˆExit:…Branches�to�read/write�common�routine�(RWCOMMON).*O******************************************************************************* READJUNK�EQU†* @‰MOVEQWƒLCDSCTSZ/L0546-1,D3„Initialize�D3.W�to�control�the�inner'*¦loop.‚We'll�perform�enough�iterations(*¦of�the�inner�loop�to�transfer�LCDSCTSZ(*¦bytes�of�data,�which�must�and�has�been*¦checked�to�be�=�128 PAGEFRD_LOOP‚MOVEP.L‚DATA0(A0),D0†----ƒEach�complete�iteration�of�this�loop**£|ƒtransfers�4*8�=�32�data�bytes�from�the$*§|ƒWDC�controller�to�the�BIT�BUCKET=‰MOVEP.L‚DATA0(A0),D0†|ƒand�we�perform�just�enough�iterations**£|ƒof�this�inner�loop�to�transfer�a�total *§|ƒof�LCDSCTSZ�bytes�during�one4‰MOVEP.L‚DATA0(A0),D0†|ƒiteration�of�the�outer�loop.*£|#*§|ƒWe�use�a�MOVEP.L�instruction�to<‰MOVEP.L‚DATA0(A0),D0†|ƒtransfer�four�consecutive�data�bytes+*£|ƒwith�the�maximum�possible�speed,�and�we&*§|ƒreplicate�the�code�in�this�loop�to<‰MOVEP.L‚DATA0(A0),D0†|ƒreduce�the�effects�of�loop�overhead.'*£|ƒWe�could�replicate�the�code�in�this'*§|ƒloop�more�times�for�even�more�speed=‰MOVEP.L‚DATA0(A0),D0†|ƒbut�diminishing�returns�begin�to�make)*£|ƒfurther�replications�less�attractive.*§|<‰MOVEP.L‚DATA0(A0),D0†|…The�WDC�controller�actually�has�just(*£|ƒone�data�register,�but�that�register'*§|ƒappears�at�4�different�locations�in>‰MOVEP.L‚DATA0(A0),D0†|ƒthe�memory�map.�Therefore,�the�MOVEP.L**£|ƒinstruction�actually�accesses�the�same%*§|ƒdata�register�four�times�with�the-‰DBRA…D3,RD_LOOPˆ----‚maxi mum�possible�speed.  ‰RTSO*******************************************************************************   ‰PAGEO********************************************************************************K*…WRITE�DATA�ROUTINE�entered�when�we�have�a�WDC�interupt�(DRQ)�for�a�write.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB)*’A3�=�pointer�to�next�byte�in�I/O�buffer*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*…**™A‚P…**=*ˆExit:…Fall�through�to�read/write�common�routine�(RWCOMMON).*O******************************************************************************* WRTDATA‚EQU†* .L0561„EQU†4*8”Each�iteration�of�the�inner�loop&*¦below�transfers�4*8�=�32�data�bytes. @‰MOVEQWƒLCDSCTSZ/L0561-1,D3„Initialize�D3.W�to�control�the�inner'*¦loop.‚We'll�perform�enough�iterations(*¦of�the�inner�loop�to�transfer�LCDSCTSZ*¦bytes�of�data.�ei.�128�bytes PAGE?L0570„MOVE.Lƒ(A3)+,D0Š----‚Each�complete�iteration�of�this�loop>‰MOVEP.L‚D0,DATA0(A0)†|ƒtransfers�4*8�=�32�data�bytes�from�the'*§|ƒoutput�buffer�to�the�WDC�controller8‰MOVE.Lƒ(A3)+,D0Š|ƒand�we�perform�just�enough�iterations>‰MOVEP.L‚D0,DATA0(A0)†|ƒof�this�inner�loop�to�transfer�a�total *§|ƒof�LCDSCTSZ�bytes�during�one/‰MOVE.Lƒ(A3)+,D0Š|ƒiteration�of�the�outer�loop.‰MOVEP.L‚D0,DATA0(A0)†|#*§|…We�use�a�MOVEP.L�instruction�to7‰MOVE.Lƒ(A3)+,D0Š|ƒtransfer�four�consecutive�data�bytes?‰MOVEP.L‚D0,DATA0(A0)†|ƒwith�the�maximum�possible�speed,�and�we&*§|ƒreplicate�the�code�in�this�loop�to7‰MOVE.Lƒ(A3)+,D0Š|ƒreduce�the�effects�of�loop�overhead.;‰MOVEP.L‚D0,DATA0(A0)†|ƒWe�could�replicate�the�code�in�this'*§|ƒloop�more�times�for�even�more�speed8‰MOVE.Lƒ(A3)+,D0Š|ƒbut�diminishing�returns�begin�to�make=‰MOVEP.L‚D0,DATA0(A0)†|ƒfurther�replications�less�attractive.*§|7‰MOVE.Lƒ(A3)+,D0Š|…The�WDC�controller�actually�has�just<‰MOVEP.L‚D0,DATA0(A0)†|ƒone�data�register,�but�that�register'*§|ƒappears�at�4�different�locations�in9‰MOVE.Lƒ(A3)+,D0Š|ƒthe�memory�map.‚Therefore,�the�MOVEP.L:‰MOVEP.L‚D0,DATA0(A0)†|ƒinstruction�accesses�the�same�data%*§|ƒregister�4�consecutive�times�with/‰DBRA…D3,L0570Š----‚the�maximum�possible�speed. %*¨We've�finished�transferring�a�block&*¦of�output�data,�so�now�control�falls(*¦into�the�common�routine�that�completes*¦the�processing�for�both'*¦read�operations�and�write�operations.‰PAGEO********************************************************************************<*ˆREAD/WRITE�COMMON�ROUTINE‚entered�after�reading�or�writing*£a�block�of�data�(128�bytes)*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB-*’A3�=�pointer�to�next�byte�in�the�I/O�buffer*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D *™A‚P�PƒPƒP*=*ˆExit:…Fall�through�to�SASIDONE�routine�to�finish�processing%*’the�current�entry�of�the�I/O�queue.*O******************************************************************************* @RWCOMMON�MOVE.LƒA3,IOBUFPTR(A1)ˆUpdate�the�I/O�buffer�pointer�to#*¦point�to�the�next�byte�of�the�I/O%*¦buffer.‚If�there's�another�block�of'*¦data�to�be�transferred,�IOBUFPTR�will'*¦be�used�to�address�the�I/O�buffer.‚If&*¦there�isn't�another�block�of�data�to'*¦be�transferred,�we'll�use�IOBUFPTR�to)*¦calculate�the�number�of�bytes�that�were&*¦actually�transferred�or�to�perform�a*¦retry�on�read�data�errors. PAGE9‰SUB.B…#1,BLKCNT(A5)‰Subtract�1�from�block�count�for�this *¦sector.0‰BNE†NEXTSEC1�We�haven't�finished�a�sector�so�go(*¦to�continue�the�transfer�if�the�WDC�is*¦requesting�data�transfer. *¨We'll�finished�the�sector,�So*%%%%%%%%‚BWN�12/21/84=*‚HERE�WE�INCREMENT�THE�LSN�AND�DECREMENT�THE�CMDSECTS�FIELDS*‚OF�THE�COMMAND�PACKET**  ééééé7‰ADD.L„#1,CMDOP(A5)‹Increment�the�LSN.�This�may�be�used%*¦to�retry�if�sector�is�found�to�have*¦an�ECC/CRC�error.:‰SUB.B„#1,CMDSECTS(A5)ˆDecrement�the�count�of�sectors�that4‰BHI†NEXTSECT�remain�to�be�processed�for�the�current**%%%%%%%%%%%%%%%%%%%%%%%%%% %*¦WDC�command�sequence.‚If�we�haven't(*¦finished�processing�all�of�the�sectors'*¦for�the�current�WDC�command�sequence,$*¦loop�back�to�process�the�next�one. =‰BTST.Bƒ#BITCB,FLAGS(A0)‡We've�finished�processing�all�of�the'*¦sector(s)�for�the�current�WDC�command *¦sequence. 1‰BNE.S„READSTAT�The�WDC�may�still�be�BUSY�because(*¦of�a�data�ECC�error�in�the�last�sector%*¦read.�In�this�case�let's�return�and$*¦wait�for�the�completion�interrupt. #*¨If�the�WDC�is�done.�(normal�case)A‰MOVE.BƒSENSE(A0),SENSBYT0(A5)�Read�SENSE�BYTE�0�to�clear�CC�int."‰BRA.S„RDSTAT1�Go�to�check�status. 7READSTAT�BSR.S„INTRTN‘Return�control�to�the�system,�and(*¦wait�for�a�status-ready�WDC�interrupt.%*¦We'll�get�control�back�when�the�WDC)*¦controller�has�its�status�report�ready. PAGEO********************************************************************************$*ˆWe�get�here�after�a�WDC�interrupt.2*ˆWe�are�expecting�a�command�completion�interrupt.*O******************************************************************************* 6‰BTST.Bƒ#BITCB,FLAGS(A0)…Is�WDC�BUSY?�It�shouldn't�be.4‰BNE†CTRLERRŽYES.�Must�be�a�DRQ�interrupt�that�we're*¦not�expecting.ARDSTAT1‚TST.B„SENSBYT0(A5)‰Were�there�any�errors�in�this�command?é'‰BNE.L„CHECKERR�YES.�Go�to�check�error. =XFERDONE�CLR.B„HALFSCTS(A1)‹This�clears�the�half�sector�count"*¦since�all�half�sectors�have�been%*¦transfered�any�additional�transfers&*¦for�this�I/O�packet�will�be�sectors.7‰TST.L„IOSCTCNT(A1)‹The�WDC�controller�has�successfully1‰BNE†PROCQUEŽcompleted�the�entire�I/O�transaction(*¦that�was�specified�by�the�last�command(*¦sequence�that�we�gave�it.‚If�there�are'*¦any�sectors�remaining�to�be�processed)*¦for�the�current�entry�of�the�I/O�queue,'*¦loop�back�to�process�another�chunk�of*¦the�entire�I/O�transfer. %*¨Recall�that�IOSCTCNT�is�always�zero&*¦for�any�I/O�transaction�that�doesn't(*¦involve�the�transfer�of�any�read/write*¦data. 9‰MOVE.BƒEOVFLAG(A1),D1‰We've�now�completed�the�ent  ire�I/O'*¦transaction�that�was�specified�by�the$*¦command�that�generated�the�current%*¦entry�of�the�I/O�queue.‚The�EOVFLAG'*¦value�that�we�get�into�D1.B�here�will#*¦be�returned�to�the�user�as�an�I/O&*¦status�code.‚If�the�I/O�transfer�was'*¦truncated�to�avoid�running�beyond�the(*¦end�of�the�disc,�we�return�the�ISTAEOV'*¦status�code.‚Otherwise,�we�return�the)*¦ISTAOK�status�code�to�indicate�that�the!*¦entire�operation�went�smoothly. $*¨Control�now�falls�into�the�WDCDONE"*¦routine�to�finish�processing�the!*¦current�entry�of�the�I/O�queue.‰PAGEO*********************************************************************************ˆFINISH�PROCESSING�QUEUE�ENTRY*F*ˆControl�comes�here�when‚the�driver�is�ready�to�finish�processing�theE*ˆcurrent�entry�of�the‚I/O�queue.‚We'll�queue�an�I/O�completion�eventC*ˆto�the�attached‚task,�and�we'll‚remove�the‚current�entry‚from�theF*ˆqueue.‚If�the�I/O�queue�has�another�entry,�we'll�loop�back�and�start*ˆprocessing�that�entry.*%*ˆEntry:„A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*ƒ* *™A„*ƒ*�*�P*=*ˆExit:…Branches�to�process�next�queue�entry�if�there�is�one.0*’Falls�through�to�idle�loop�if�there�isn't�one.*O******************************************************************************* 3SASIDONE�EQU†*–We�use�a�MOVEM.L�instruction�to�pull=L0630„REG†D0/D2/A1/A3/A4‡several�variables�out�of�the�currentA‰MOVEM.L‚IOBUFLOC(A1),L0630ƒI/O�packet�in�one�step.‚This�instruc-(*¦tion�sets�up�the�registers�as�follows. L1‡SET†IOBUFLOC�D0�=�IOBUFLOC.L1‡SET†IOBUFPTR�D2�=�IOBUFPTR.L1‡SET†IOBUFTCB�A1�=�IOBUFTCB.5L1‡SET†DCBPNTRŽA3�=�DCBPNTR.‚(For�subroutine�QEVENTI)5L1‡SET†IOCBPTRŽA4�=�IOCBPTR.‚(For�subroutine�QEVENTI) $*¨The�SET�instructions�that�are�used'*¦here�are�just�dummy�instructions�that&*¦generate�artificial�label�references%*¦for�the�concordance�listing.‚Future)*¦maintenance�programmers�will�be�able�to)*¦use�the�concordance�listing�to�discover$*¦that�this�segment�of�code�accesses*¦these�variables. PAGE1‰SUB.L„D0,D2’Now�compute�the�number�of�data�bytes=‰MOVE.LƒD2,IOSLEN(A4)ˆthat�we�actually�transferred,�and�store&*¦that�number�into�the�IOSLEN�field�of%*¦the�IOCB.‚For�an�I/O�operation�that%*¦doesn't�involve�the�transfer�of�any%*¦read/write�data,�we�have�IOBUFLOC�=)*¦IOBUFPTR,�so�we�properly�set�IOSLEN�=�0*¦in�this�case. 3‰LEA‡ERRDISK(PC),A2ˆTest�the�Versados�error�code�to=BERNARD‚MOVE.B„(A2)+,D2Œdetermine�whether�the�IOSRRN�field�of6‰BEQ.S…NOCOPYŽthe�IOCB�needs�to�be�updated.�If�a�match0‰CMP.B…D2,D1�is�found�in�the�table�ERRDISK,�then4‰BNE.S…BERNARD�update�the�IOSRRN�field�with�Versados*‰MOVE.L„D3,IOSRRN(A4)‡sector�number�in�D3. 3NOCOPYƒBSR†QEVENTI�Subroutine�QEVENTI�queues�an�I/O(*¦completion�event�to�the�attached�task.)*¦Registers�A5,�A4,�A3,�and�D1.B�must�all)*¦be�set�properly�when�we�call�subroutine *¦QEVENTI. 9‰SUB.B„#1,TCBIOCNT(A1)ˆDecrement�the�count�of�outstanding'*¦I/O�operations�for�the�task�that�owns)*¦the�I/O�buffer�(or�the�IOCB�in�the�case%*¦of�a�format�command�or�a�configure-*¦floppy�command). 6L0640„REG†A1/A3/A4�Here�we�remove�the�front�entry�fromA‰MOVEM.L‚IOQUEUE+4(A5),L0640‚the�I/O�queue,�and�we�simultaneouslyA‰MOVEM.L‚L0640,IOQUEUE(A5)„set�A1�to�point�to�the�drive�block�for(*¦the�disc�drive�that�is�associated�with$*¦the�next�(if�any)�entry�of�the�I/O%*¦queue.‚Since�there�are�a�maximum�of(*¦four�entries�in�the�I/O�queue,�we�need'*¦to�move�no�more�than�three�entries�to(*¦remove�the�first�entry�from�the�queue. 6‰SUB.W„#4,IOQCNT(A5)ŠReduce�the�queue-count�pointer�to1‰BHI†PROCQUEŽaccount�for�the�fact�that�we've�just(*¦removed�a�four-byte�entry�from�the�I/O$*¦queue.‚If�there�is�still�an�active&*¦entry�in�the�I/O�queue,�loop�back�to"*¦start�processing�the�next�entry. $*¨If�the�I/O�queue�is�empty,�control(*¦falls�into�the�co-routine�segment�that%*¦is�potentially�active�when�the�SASI'*¦controller�is�caught�up�and�should�be*¦idle.‰PAGEO! ********************************************************************************@*ˆIDLE�LOOP�ROUTINE�entered�when�the�I/O�queue�has�been�emptied.B*ˆThe�controller�is�completely�caught�up�with�all�of�its�requests,D*ˆand�the�controller�should�now�be�idle.‚We'll�simple�return�control'*ˆto�the�system�to�idle�the�controller.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D„*�*�* *™A‚P…*�*�P**ˆExit:…Return�to�CMR�via�RTS*O******************************************************************************* :IDLELOOP�BSR.S„INTRTN‘The�I/O�queue�is�empty,�so�we�simply%*¦return�control�to�the�system.‚We've)*¦caught�up�with�all�of�the�requests�that'*¦have�been�set�up�for�processing�under*¦interrupt�control. ƒD2ƒDO.S‰Mark�good�up�to�sect�no.-1*°or�mark�alternate +�MOVE.B„D5,DATA0(A0)ˆMove�opcode�(00�or�40)'�MOVE.B„D3,DATA0(A0)ˆMove�sector�number&�MOVE.B„#0,DATA0(A0)ˆMove�3�more�bytes�MOVE.B„#0,DATA0(A0)�MOVE.B„#0,DATA0(A0) ,�ADDQ.B„#1,D3ŽGet�next�sector�number�into�D3 �SUBQ.W„#5,D6 ‰ENDW ‰MOVE.W„D0,D4-‰LSR.W…#8,D4�D4.W‚<---�MSB�of�cylinder�number ,‰LSL.B…#5,D1�Get�head�number�into�bits�7,6,52‰ADD.B…D2,D1�Get�sector�number�into�bits�0-4�of�D1 5‰WHILE.BƒD3‚‚#32‚DO.S„Mark�sectors�to�31�as�"bad" &�MOVE.B„#BADCODE,DATA0(A0)ˆSend�opcode'�MOVE.B„D3,DATA0(A0)ŽSend�sector�number-�MOVE.B„D4,DATA0(A0)ŽSend�MSB�of�cylinder�no.-�MOVE.B„D0,DATA0(A0)ŽSend�LSB�of�cylinder�no.,�MOVE.B„D1,DATA0(A0)ŽSend�Head+sector�number �ADD.B…#1,D3 �ADD.B…#1,D1 �SUBQ.W„#5,D6 ‰ENDW*=*ˆWe�have�now�sent�5*32�=�160‚bytes.�The�controller�wants�256"*ˆso�we�send�96�more,�4�at�a�time.*‰REPEAT �MOVEP.LƒD3,DATA0(A0) �SUBQ.W„#4,D6 ‰UNTIL… *‰MOVEM.Lƒ(SP)+,SEND_REGS…Restore�registers ‰RTS   ‰PAGEF*********************************************************************** *ˆSET_UP_ALT*;*ˆSet�up�a�command�packet�for�the�format�alternate�command.;*ˆJust�take�the�command�packet�you�have�now,�and�substitute<*ˆthe�alternate�sector�number�for�the�sector�number�in�there*ˆnow.**/*ˆEntry:„A1�=�address�of�drive's�variable�block*’A5�=�a" ddress�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D„**™A„P‡P*ˆP�=�parameter�register!*ˆ*�=�saved�and�restored�register**ˆExit:…same�as�entry*O*******************************************************************************SET_UP_ALT‰EQU‡**!‰MOVE.L„D1,-(SP)ŒSave�register�D15‰MOVE.L„CMDOP(A5),D1ˆSave�bytes�0-3�of�command�packet*¦in�D1.*2‰AND.L…#LSNMSKNOT,D1‡Mask�out�lower�21�bits�of�D1.#*¦These�bits�contain�the�old�sector *¦number.%*¦The�stuff�we�want�to�save�is�in�D1.*3‰MOVE.L„IOALTSEC(A1),CMDOP(A5)ˆPut�alternate�sector*¦number�into�command�packet.B‰AND.L…#LSNMASK,CMDOP(A5)‚Mask�out�upper�11�bits�of�command�packet$*¦These�bits�contain�Opcode�and�LUN.*1‰OR.L†D1,CMDOP(A5)ˆCombine�the�old�Opcode�and�lun!*¦with�the�new�(alternate)�sector *¦number.$‰MOVE.L„(SP)+,D1‚Restore�register�D1**‰RTS  ‰PAGEO*********************************************************************************ˆCHECK�ERROR�ROUTINE***ˆSome�error�has�been�detected�by�the�WDC.**ˆFor�a�READ�command:>*�If�the�error�is�an�ECC�error�(correctable�or�uncorrectable),+*’1.‚Compare�current�error�with�last�error.<*’2.‚If�retry�count�is�not�exhausted,�retry�from�bad�sector.;*’3.‚If�retry�count�is�exhausted,�error�is�correctable,�and7*–the�last�two�errors�were�identical,�we'll�correct�the4*–error�in�memory�and�issue�the�rest�of�the�command.*’4.‚Else�report�the�error.*+*ˆFor�all�other�commands,�report�the�error.*<*ˆEntry:„A0�=�physical�address�of�WDC�Memory-Mapped�I/O�area/*’A1�=�pointer�to�drive's�variable�block�in�CCB<*’A3�=�pointer�to�I/O�buffer�(except�on�last�sector�of�xfer)*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*�*�P**ˆExit:…Report�the�error.*O******************************************************************************* CHECKERR�EQU†*%‰SUB.B„#1,RETRY(A5)‰DECR.�RETRY�COUNT)UNCORRER�EQU†$12’UNCORRECTABLE�DATA�ERROR%CORRERƒEQU†$13’CORRECTABLE�DATA�ERROR0‰MOVE.Wƒ#8,D0�LOOP�COUNTER�TO�READ�&�COMPARE�THE*§REMAINING�9�SENSE�BYTES. %*£NOTE:�THAT�THERE�IS�NO�NEED�TO�INIT#*§THE�SAVE�AREA�FOR�THE�SENSE�BYTES&*§SINCE�THE�COMPARE�IS�ONLY�USED�AFTER*§ALL�RETRIES�HAVE�BEEN�DONE 9‰LEA†SENSBYT0(A5),A4†POINTER�TO�SENSE�BYTE�0.�NOTICE�THAT$*§THE�10�SENSE�BYTES�ARE�ACCESSED�IN *§ORDER�(ei.�0..9)�BY�SEQUENTIAL!*§READS�OF�THE�SAME�MEMORY�MAPPED!*§BYTE�IN�THE�WDC.�WE�HAVE�DONE�A#*§READ�OF�SENSE�BYTE�0�TO�CLEAR�THE&*§INTERRUPT.�WE'LL�GET�BYTE�0�FROM�THE *§SAVE�AREA,THEN�ACCESS�1�THRU�9 !‰MOVE.Bƒ(A4)+,D1�GET�SENSE�BYTE�07‰EOR.B„#CORRER,D1‹D1.B�WILL�=�0�IF�ERROR�IS�CORRECTABLE8‰OR.B…RETRY(A5),D1‰D1.B�=�0�IF�CORRECTABLE�&�RETRY�COUNT*«=�0(L0552„MOVE.BƒSENSE(A0),D2‰GET�SENSE�BYTE‰CMP.B„(A4),D2 PAGE0‰BEQ.S„L0553�BRANCH�IF�BYTE�FOR�CURRENT�ERROR�IS*§THE�SAME�AS�LAST�ERROR‰OR.B…#1,D1�SET�D1�TO�NON-ZERO2L0553„MOVE.BƒD2,(A4)+�SAVE�THE�CURRENT�ERROR�BYTES‰DBRA…D0,L0552 )*¦D1.B�=�0�IF(LAST�ERROR�=�CURRENT�ERROR)*±&�(ERROR�IS�CORRECTABLE)*±&�(RETRY�COUNT�=�0) ‰TST.B„D1&‰BNE.S„L0555�BRANCH�IF�NOT�CORRECTABLE  $* HERE TO CORRECT DATA IN THE BUFFERL0554„EQU†CONFGBLK+IOSPSM:‰MOVE.LƒIOBUFPTR(A1),A3†POINTER�TO�NEXT�LOCATION�IN�BUFFER7‰SUB.W„L0554(A1),A3‰A3�POINTS�TO�1ST�BYTE�IN�BAD�SECTOR ‰CLR.L„D1=‰MOVE.BƒSENSBYT7(A5),D1†GET�BYTE�OFFSET�FROM�THE�START�OF�THE"*§THE�SECTOR�TO�THE�1ST�ERROR�BYTE-‰ADD.W„D1,A3�BUFFER�ADDRESS�OF�1ST�ERROR�BYTE>‰MOVE.BƒSENSBYT8(A5),D1†CORRECTION�MASK�FOR�THE�1ST�ERROR�BYTE‰EOR.B„D1,(A3)+�CORRECT�BYTE)‰MOVE.BƒSENSBYT9(A5),D1†SAME�FOR�2ND�BYTE‰EOR.B„D1,(A3)0‰LEA†CMDOP(A5),A3‰POINT�A3�TO�THE�COMMAND�PACKET9‰TST.B„CMDSECTS(A5)‰ARE�ANY�MORE�SECTORS�TO�BE�TRANSFERED*§FOR�THIS�COMMAND?'‰BNE†SENDNEWŽYES.�SEND�COMMAND�FOR�REST‰BRA†XFERDONE�NO.�ALL�DONE * HERE FOR OTHER ERRORS*%%%%%%%%%%%%%%%ƒBWN‚12/21/84*H*‚We�only�get�to�CHECKERR�if�we�read�or�wrote�the�data�and�upped�the�LSN3*‚and�CMDSECTS�in�the�command�packet�in�preparation" *‚for�going�to�SENDNEW.*(*‚However,�at�this�point�we�will�either:**ˆ(1)�branch�to�STATERR�if�no�more�retries7*ˆ(2)�branch�to�STATERR�if�error�is�not�code�$12�or�$!#*ˆ(3)�do�a�retry*E*‚In�each�of�these�cases�we�want�to�have�the�current�LSN�and�CMDSECTSE*‚in�the�command�packet,�so�we�have�to�add�1�to�CMDSECTS�and�subtract*‚1�from�the�LSN.*L0555:‰ADDQ.B…#1,CMDSECTS(A5)‰SUBQ.L…#1,CMDOP(A5)*D*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%‰TST.B„RETRY(A5)ŒIS�RETRY�COUNT�=�0�?%‰BEQ.S„STATERR�&�REPORT�ERROR�IF�ZERO‰MOVE.Bƒ#$FE,D1:‰AND.B„SENSBYT0(A5),D1†MASK�LSB�SO�CODES�$12�AND�$13�=�$12‰CMP.B„#UNCORRER,D12‰BNE.S„STATERRŽREPORT�ERROR�IF�NOT�CODE�$12�OR�$13 -* HERE TO DO A RETRY OF THE LAST SECTOR READ.E* THE BAD SECTOR HAS BEEN READ INTO THE BUFFER AND THE COMMAND PACKET0* IS POINTING TO THE NEXT SECTOR. (BWN 12/21/84)é ‰CLR.L„D1%‰MOVE.WƒL0554(A1),D1‰GET�BYTES/SECTOR*‰TST.B„HALFSCTS(A1)‰IS�THIS�A�HALF�SECTOR?‰BEQ.S„L0556�NO.*‰LSR.W„#1,D1�YES.�BYTE/SECTOR�DIVIDED�BY�2�last�entry�in�table�are *¦undefined. ‰BLS.S„L0955‰MOVE.Bƒ#ISTAICE,D1 ‰BRA†SASIDONE EL0955„MOVE.BƒERRCODE(PC,D2.W),D1‚Use�that�error�code�as�an�index�into(*¦the�WDC�error-code�table,�and�we�get�a)*¦Versados�error�code�from�the�table�into%*¦D1.B.‚Once�we've�tra# nslated�the�WDC(*¦error�code�into�a�Versados�error�code,%*¦we�transfer�control�to�the�SASIDONE&*¦routine,�which�will�report�the�error*¦code�in�D1.B�to�the�user. PAGE 3‰LEA‡ERRDISK(PC),A4ˆTest�the�Versados�error�code�to$43 AND /=$80 ARE REPORTED AS "ISTAICE". CODE $80 IS A SELF-G* TEST ERROR AND IS REPORTED AS "ISTAUNR". THESE CHECKS ARE MADE IN THE* STATERR ROUTINE. ‰PAGEO*********************************************************************************ˆCONTROLLER�ERROR�ROUTINE*@*ˆThe�purpose�of�this�routine�is�to�report�"state'�errors�of�the*ˆcontroller,�for�example:>*Š1.‚The�WDC�wants�to�be�read�or�written�but�the�driver�is�not%*Žexpecting�to�transfer�more�data,�orD*Š2.‚The�WDC�generated�an�interupt�but�the�condition�has�changed,�orC*Š3.‚The�WDC�went�'busy'�before�the�entire�command�packed�was�sent.**ˆThere�are�2�entry�points:6*ŠCTRLERR1:�If�the�error�was�detected�in�a�subroutine.2*ŠCTRLERR�:�If�the�error�was�detected�in�the�main.*O******************************************************************************* 7CTRLERR1�ADDQ.Lƒ#4,SP’Control�comes�to�this�entry�point%*¦when�a�controller�error�is�detected%*¦from�within�a�subroutine.‚We�remove&*¦the�subroutine's�return�address�from(*¦the�stack,�so�the�stack�is�restored�to&*¦the�condition�that�it�had�before�the*¦subroutine�was�called.  =CTRLERR‚ST.B…SASIDOWN(A5)‹Down�the�WDC�channel�by�setting�the"*¦variable�that�indicates�that�the#*¦controller�is�down.‚If�the�system'*¦tries�to�access�the�WDC�channel�again#*¦without�resetting�it�first,�we'll%*¦report�an�error�indicating�that�the$*¦channel�is�down.‚The�system�really!*¦shouldn't�try�to�access�the�WDC'*¦channel�again�without�first�resetting$*¦the�controller.‚Even�resetting�the)*¦controller�may�not�correct�the�problem,'*¦but�we'll�let�the�system�try�as�often*¦as�it�wishes. 5‰MOVEQBƒISTACNT,D1�Set�up�D1.B�for�reporting�a�status5‰BRA†SASIDONE�code�that�indicates�a�controller�error,%*¦and�go�terminate�processing�for�the!*¦current�entry�of�the�I/O�queue.‰PAGEO*********************************************************************************ˆSEND�COMMAND�ROUTINE*G*ˆThe�purpose�of�this�routine�is�to�send�the�command�packet�to�the�WDC.*8*ˆEntry:„A0�=�address�of�1st�byte�of�the�command�packet.5*’A3�=�physical�address�of�WDC�Memory-Mapped�I/O�area*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�**™A‚P…**"*ˆExit:…Return�to�calling�routine.*O******************************************************************************* SENDCMD‚EQU‡*&‰MOVEQW„CMDLEN-1,D1‰Number�of�bytes�-1"L0521„EQU‡(1<‰BTST.B„#BITCB,FLAGS(A0)„The�WDC�should�be�BUSY.‚However,�if�a6*ˆBEQ‡CTRLERR1Œhigher�level�interrupt�occurs�here,�the&*¦the�controller�will�not�be�BUSY�upon**¦return�and�the�check�is�no�longer�valid.'*¦That's�why�it�has�been�commented�out.‰RTS ‰ENDC-‰TTL‡Extended�DCB's�for�each�network�terminal‰PAGE ‰OFFSET�0 TNMSGTƒDS.B†1TNMIORƒEQU‰1ˆI/O�requestTNMIOCƒEQU‰2‡I/O�completeTNMUB„EQU‰3‡unsolicited�breakTNMHIOƒEQU‰4‡halt�IO�request/‰DS.Bˆ1‡unused�-�needed�to�word-align�IOS�block-TNIOS„DS.B†IOSBLN„message�type�1--I/O�requestTNWDATA‚DS.B†0‰write�data�start )‰OFFSET„TNIOS…message�type-2�I/O�completeTNSTATƒDS.B†1‰status#‰DS.B†1‰alignment�for�even�boundary(TNDLENƒDS.L†1‰length�of�data�(for�reads)TNRDATA‚DS.B†0‰data�(for�rea$ ds)                  ééééé†#=/*=/*†ACIADRV.AF=/*-=/* Chain file to assemble ACIA serial driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to ACIADRV.LS=/*=/IFC \1ƒ=ARG�ACIADRV.LS=/ENDIF=/*$=ASM ACIADRV.SA,ACIADRV.RO,\1;RZ=150=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMCCB.EQ=/*}=/*=ENDééééé�% =/*=/*†DARTDRV.AF=/*I=/* Chain file to assemble SCN2681 SUBORDINATE serial port driver for the$=/* local port on the MVME115 board.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to DARTDRV.LS=/*=/IFC \1ƒ=ARG�DARTDRV.LS=/ENDIF=/*$=ASM DARTDRV.SA,DARTDRV.RO,\1;RZ=140=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.SCN2681.EQ=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9995.&.TERMCCB.EQ=/*}=/*=ENDééééé˜=/*=/*†DARTSPR.AF=/*H=/* Chain file to assemble SCN2681 SUPERVISOR serial port driver for the$=/* local port on the MVME115 board.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to DARTSPR.LS=/*=/IFC \1ƒ=ARG�DARTSPR.LS=/ENDIF=/*$=ASM DARTSPR.SA,DARTSPR.RO,\1;RZ=100=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.SCN2681.EQ=/*ƒ9999.M68230.M68230.EQ=/*}=/*=ENDééééé% é¡=/*=/*†EPCIDRV.AF=/**=/* Chain file to assemble SIG 2661 driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to EPCIDRV.LS=/*=/IFC \1ƒ=ARG�EPCIDRV.LS=/ENDIF=/*$=ASM EPCIDRV.SA,EPCIDRV.RO,\1;RZ=150=/*{ Included files are:=/*ƒ9995.&.SIG2661.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMCCB.EQ=/*}=/*=ENDéééééª=/* =/*†IPCDRV.AF=/*)=/* Chain file to assemble the IPC driver=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to IPCDRV.LS=/*=/IFC \1ƒ=ARG�IPCDRV.LS=/ENDIF=/*#=ASM IPCDRV.SA,IPCDRV.RO,\1;MRZ=160=/*{ Included files are:=/*ƒ9995.&.TRACE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.DUALPORT.MC=/*ƒ9995.&.UTILITY.MC=/*}=/*=ENDééé& ééé³=/*=/*†M300DRV.AF=/*.=/* Chain file to assemble the IEEE-488 driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M300DRV.LS=/*=/IFC \1ƒ=ARG�M300DRV.LS=/ENDIF=/*&=ASM M300DRV.SA,M300DRV.RO,\1;-WRZ=160=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.DUALPORT.MC=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.M300DRV.EQ=/*ƒM300TABL.AI=/*ƒM300INIT.AI=/*ƒM300INTR.AI=/*ƒM300CMND.AI=/*}=/*=ENDééééé¼=/*=/*†M315DRV.AF=/*==/* Chain file to assemble the MVME315 disk controller driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M315DRV.LS=/*=/IFC \1ƒ=ARG�M315DRV.LS=/ENDIF=/*$=ASM M315DRV.SA,M315DRV.RO,\1;RZ=180=/*{ Included files are:=/*ƒ9995.&.DUALPORT.MC=/*ƒ9995.&.TRACE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*}=/*=ENDé& éééééÅ=/*=/*†M320DRV.AF=/*==/* Chain file to assemble the MVME320 disk controller driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M320DRV.LS=/*=/IFC \1ƒ=ARG�M320DRV.LS=/ENDIF=/*&=ASM M320DRV.SA,M320DRV.RO,\1;-WRZ=186=/*{ Included files are:=/*ƒ9995.&.DUALPORT.MC=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*}=/*=ENDééééééÎ=/*=/*†M420DRV.AF=/*/=/* Chain file to assemble VME420 (SASI) driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M420DRV.LS=/*=/IFC \1ƒ=ARG�M420DRV.LS=/ENDIF=/*$=ASM M420DRV.SA,' M420DRV.RO,\1;RZ=186=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ =/*ƒCOMCMD.AI=/*ƒM420INT.AI=/*}=/*=ENDéééééé×=/*=/*†M435DRV.AF=/*.=/* Chain file to assemble the MAG tape driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to M435DRV.LS=/*=/IFC \1ƒ=ARG�M435DRV.LS=/ENDIF=/*&=ASM M435DRV.SA,M435DRV.RO,\1;-WRZ=150=/*{ Included files are:=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*}=/*=END éééééé' à=/* =/*†MFPDRV.AF=/*H=/* Chain file to assemble MK68910 serial port driver for local ports on=/* VME120 and VME128 boards.=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to MFPDRV.LS=/*=/IFC \1ƒ=ARG�MFPDRV.LS=/ENDIF=/*"=ASM MFPDRV.SA,MFPDRV.RO,\1;RZ=140=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMCCB.EQ=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9999.MK68901.MK68901.EQ=/*}=/*=ENDéééééé=/*=/*†MPCCDRV.AF=/*G=/* Chain file to assemble R68560 serial port driver for the local port*=/* on the VME050 system controller board.=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to MPCCDRV.LS=/*=/IFC \1ƒ=ARG�MPCCDRV.LS=/ENDIF=/*$=ASM MPCCDRV.SA,MPCCDRV.RO,\1;RZ=140=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMCCB.EQ=/*ƒ9995.&.TERMINAL.EQ=/*}=/*=ENDééé( ééò=/*=/*†MPSCDRV.AF=/*6=/* Chain file to assemble NEC 7201 subordinate driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to MPSCDRV.LS=/*=/IFC \1ƒ=ARG�MPSCDRV.LS=/ENDIF=/*$=ASM MPSCDRV.SA,MPSCDRV.RO,\1;RZ=150=/*{ Included files are:=/*ƒ9995.&.MVME400.EQ=/*ƒ9995.&.NEC7201.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMCCB.EQ=/*}=/*=ENDéééééû=/*=/*†MPSCSPR.AF=/*K=/* Chain file to assemble NEC 7201 supervisor driver for the MVME400 board=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to MPSCSPR.LS=/*=/IFC \1ƒ=ARG�MPSCSPR.LS=/ENDIF=/*$=ASM MPSCSPR.SA,MPSCSPR.RO,\1;RZ=106=/*{ Included files are:=/*ƒ9995.&.NEC7201.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.CCB.EQ=/*}=/*=ENDéé( éééé=/*=/*†MPSCSUP.AF=/*B=/* Chain file to assemble NEC 7201 supervisor driver for the VM02=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to MPSCSUP.LS=/*=/IFC \1ƒ=ARG�MPSCSUP.LS=/ENDIF=/*$=ASM MPSCSUP.SA,MPSCSUP.RO,\1;RZ=106=/*{ Included files are:=/*ƒ9995.&.NEC7201.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.CCB.EQ=/*}=/*=ENDéééééé ' P050DRV AF""bbP115DRV AF++bbPIADRV AF44bbPV01DRV AF==bbRWINDRV AFFFbbSIODRV AFOObbTERMLIB AFXXbbTNTDRV AFaabbVM22DRV AFjjbb) =/*=/*†P050DRV.AF=/*>=/* Chain file to assemble printer driver for the VME050 board=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to P050DRV.LS=/*=/IFC \1ƒ=ARG�P050DRV.LS=/ENDIF=/*%=ASM P050DRV.SA,P050DRV.RO,\1;MRZ=146=/*{ Included files are:=/*ƒ9995.&.TRACE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*}=/*=ENDéééééé=/*=/*†P115DRV.AF=/*B=/* Chain file to assemble the printer driver for the VME115 board=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to P115DRV.LS=/*=/IFC \1ƒ=ARG�P115DRV.LS=/ENDIF=/*%=ASM P115DRV.SA,P115DRV.RO,\1;MRZ=146=/*{ Included files are:=/*ƒ9995.&.TRACE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9999.M68230.M68230.EQ=/*}=/*=ENDééé) ééé#=/* =/*†PIADRV.AF=/*8=/* Chain file to assemble the printer driver for a PIA.=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to PIADRV.LS=/*=/IFC \1ƒ=ARG�PIADRV.LS=/ENDIF=/*#=ASM PIADRV.SA,PIADRV.RO,\1;MRZ=146=/*{ Included files are:=/*ƒ9995.&.TRACE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*}=/*=ENDéééééé,=/*=/*†PV01DRV.AF=/*@=/* Chain file to assemble the printer driver for the VM01 board=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to PV01DRV.LS=/*=/IFC \1ƒ=ARG�PV01DRV.LS=/ENDIF=/*%=ASM PV01DRV.SA,PV01DRV.RO,\1;MRZ=146=/*{ Included files are:=/*ƒ9995.&.TRACE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*}=/*=ENDé* ééééé5=/*=/*†RWINDRV.AF=/*:=/* Chain file to assemble the RWIN disk controller driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to RWINDRV.LS=/*=/IFC \1ƒ=ARG�RWINDRV.LS=/ENDIF=/*&=ASM RWINDRV.SA,RWINDRV.RO,\1;-WRZ=186=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ =/*ƒCOMCMD.AI=/*ƒRWININT.AI=/*}=/*=ENDéééééé>=/* =/*†SIODRV.AF=/*H=/* Chain file to assemble MK68564 serial port driver for the local port=/* on the VM04 board.=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to SIODRV.LS=/*=/IFC \1ƒ=AR* G�SIODRV.LS=/ENDIF=/*"=ASM SIODRV.SA,SIODRV.RO,\1;RZ=140=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.BAB.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9995.&.TERMCCB.EQ=/*}=/*=ENDéééééG=/*=/*†TERMLIB.AF=/*0=/* Chain file to assemble library for terminals=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to TERMLIB.LS=/*=/IFC \1ƒ=ARG�TERMLIB.LS=/ENDIF=/*$=ASM TERMLIB.SA,TERMLIB.RO,\1;RZ=150=/*{ Included files are:=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.TERMINAL.EQ=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TERMCCB.EQ=/*ƒ9995.&.BAB.EQ=/*}=/*=ENDééééé+ P=/* =/*†TNTDRV.AF=/*B=/* Chain file to assemble the Transparent Network Terminal driver=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to TNTDRV.LS=/*=/IFC \1ƒ=ARG�TNTDRV.LS=/ENDIF=/*"=ASM TNTDRV.SA,TNTDRV.RO,\1;RZ=110=/*{ Included files are:=/*ƒ9995.&.TR1.EQ=/*ƒ9995.&.TR1RTCD.EQ=/*ƒ9995.&.EXE.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*ƒ9995.NTS.TR1X.EQ=/*ƒ9995.NTS.NTS.EQ =/*ƒTNTMF.AI=/*}=/*=ENDééééééY=/*=/*†VM22DRV.AF=/**=/* Chain file to assemble the VM22 driver=/*:=/* If no output argument is specified for the listing the)=/* chain file will default to VM22DRV.LS=/*=/IFC \1ƒ=ARG�VM22DRV.LS=/ENDIF=/*$=ASM VM22DRV.SA,VM22DRV.RO,\1;RZ=130=/*{ Included files are:=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.IOE.EQ=/*ƒ9995.&.NIO.EQ=/*}=/*=ENDéééé+ ééb' DRVLIB LOGPHY SAwwGbbQEVENT SA€€K¾bbSETTIME SAÑÑ kbbLOGPHY AFââbbQEVENT AFëëbbSETTIME AFôôbb:LOGPHYƒIDNT†4,4‡DRIVER�LIBRARY�LOGICAL-PHYSICAL�SUBROUTINE* *ˆINCLUDES**ˆ9995.&.TCB.EQ*ˆ9995.&.STR.EQ*ˆ9995.&.UTILITY.MC*‰NOLIST‰INCLUDEƒ9995.&.UTILITY.MC‰NOLIST‰INCLUDEƒ9995.&.TCB.EQ‰NOLIST‰INCLUDEƒ9995.&.STR.EQ‰LIST‰PAGEK****************************************************************************/*‰LOGPHY�--�DO�LOGICAL�TO�PHYSICAL�CALL�TO�EXEC*6*‰Does�an�exec�LOGPHY�call�to�check�out�the�address�of*‰a�buffer�or�parameter�block.*$*‰Entry:�D5�=�buffer�length�in�bytes-*�D6�=�buffer�logical�start�addr�(to�convert)/*�A0�=�address�of�TCB�of�task�containing�buffer*�A5�=�address�of�CCB*0*‰Exit:‚CCR:��=�physical�address�is�in�D6.L.**•�=�address�is�invalid�for�this�task.*�D6�=�Logical�address**K*************************************************************************** ‰SECTIONƒ15‰OPT‡BRS ‰XDEF†LOGPHY LOGPHY: 6ŠMOVEM.L�D0-D5/D7/A0-A5,-(A7)‚Save�registers�on�stack. 2ŠPUSHƒ#1‘Initialize�flag�(on�the�stack)�to�nonzero*§to�indicate�BAD�ADDRESS. **‚Validate�and�convert�address.*&ŠBTSTƒ#0,D6ŽIf�the�address�is�not�odd,ŠIF…�THENŠ* !ŠTST.L‚D5‘If�the�length�is�not�0,ŠIF…�THENŠ* ?ŠMOVE.L�TCBTST(A0),A0†A0�<--�address�of�his�task�segment�table.9ŠTR0$.LOGPHY�,�Call�exec�to�validate�and�convert�address.5ŠCLR„(SP)�If�good,�set�flag�to�0�to�indicate�success.ŠNOP—If�bad�length,+ŠNOP—or�bad�address,�fall�through�to�error. ŠENDI ŠENDI  **‚Set�condition�codes�and�exit.*2ŠPOP„D0‘Set�condition�codes�according�to�the�flag.;ŠMOVEM.L�(A7)+,D0-D5/D7/A0-A5ƒRestore�registers�and�return.ŠRTS—*‰ENDéoH, ‰PAGE3QEVENTƒIDNT†4,4ƒQUEUE�EVENTS�FROM�DRIVERS�(TRAP�#0)‰OPT‡BRS,PCS,CREH************************************************************************H**************************************************************************ˆQEVENT*@*ˆSubroutine�QEVENT�queues�an�event�message�from�a�driver�to�the'*ˆtask�that�is�attached�to�the�channel.*B*ˆThere�are�several�entry�points�to�this�routine,�depending�on�the"*ˆtype�of�event�you�need�to�queue.**ˆEXIT::*ŒCondition�codes��=�the�event�was�successfully�queued5*ŒCondition�codes��=�bad�return�from�TRAP�#0�call*‰PAGEH**************************************************************************ˆENTRY�POINTS�AND�DESCRIPTIONS*J***************************************************************************-*ˆEntry�point“Description�of�event�to�be�sent-*ˆ-----------“--------------------------------*ˆ1.�N_NRM_QEVENT�Normal�I/O�completion�event*¦Queued�from�command�level�(0)*-*ˆ2.�I_NRM_QEVENT�Normal�I/O�completion�event*¦Queued�from�interrupt�handler* *ˆ3.�N_HLT_QEVENT�HALT�I/O�event*¦Queued�from�command�level�(0)* *ˆ4.�I_HLT_QEVENT�HALT�I/O�EVENT*¦Queued�from�interrupt�handler*!*ˆFor�entry�points�1.�through�4.:*‹Registers�upon�entry:6*’A0�=�addr�of�place�to�copy�event�(must�have�at�least*œ20�bytes�reserved)*—or'*—0�if�you�do�not�want�the�event�copied*’A5�=�addr�of�CCB*’D1.B�=�error�message*’D3.L�=�addr�of�DCB***ˆ5.�N_UNS_QEVENT�Unsolicited‚device�event*¦Queued�from�command�level�(0)*¦Status�value�0�(DCB�known)***ˆ6.�I_UNS_QEVENT�Unsolicited�device�event*¦Queued�from�interrupt�handler*¦Status�value�0�(DCB�known)**ˆFor�entry�points�5.�and�6.:**‹Registers�upon�entry:6*’A0�=�addr�of�place�to�copy�event�(must�have�at�least*œ20�bytes�reserved)*—or'*—0�if�you�do�not�want�the�event�copied*’A5�=�addr�of�CCB*’D3.L�=�addr�of�DCB*’D4.W�=�device�status�and�type*7*ˆNOTE:�The�unsolicited�channel�event�(type�$FF)�is�notxE�B‰B‘W™B¡E©R±T¹MÁ%6*ˆhandled�by�this�routine.‚It�was�only�used�in�the�IPC5*ˆinterpreted�driver�as�far�as�I�could�determine,�and0*ˆI�decided�it�was�not�worth�coding�up�here.ƒbwn*4*ˆNOTE:�The�unsolicited�device�event�(type�$80)�with2*ˆstatus�value�1�is�not�handled�by�this�routine.‚I*ˆdon't�know�who�needs�it.**‰PAGED*********************************************************************)*ˆE�V�E�N�T…W�I�T�H†N�O…A�L�T�E�R�N�A�T�E**‘S�E�R�V�I�C�E…A�D�D�R�E�S�S*N********************************************************************************ˆEvent�as�seen�by�exec:*ˆ---------------------)*’Event�with�no�alternate�service�address*+*’+---------+---------+---------+---------+$*ˆD2‚=…|�length‚|‚$01„|‚typeƒ|‚key„|+*’+---------+---------+---------+---------+**ˆD3‚=…|‚DCB�address‚or�channel�mnemonic…|+*’+---------------------------------------+&*ˆD4‚=…|‚continuation�of�message�...Š|+*’+---------------------------------------+ *ˆD5‚=…|§|+*’+---------------------------------------+ *ˆD6‚=…|§|+*’+---------------------------------------+*H************************************************************************‰PAGEJ****************************************************************************’Normal�I/O�completion�event#*’with�no�alternate�service�address*+*’+---------+---------+---------+---------+*ˆD2‚=…|‚$A…|‚$01„|‚$70„|‚key„|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD4‚=…|ƒ0…|�errorƒ|*’+-------------------+***’I/O�HALT�event#*’with�no�alternate�service�address*+*’+---------+---------+---------+---------+*ˆD2‚=…|‚$A…|‚$01„|‚$71„|‚key„|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+-----, ----------------------------------+*ˆD4‚=…|ƒ0…|�errorƒ|*’+-------------------+**’Unsolicited�device�event#*’with�no�alternate�service�address**’and�status�value�=�0�(DCB�address�known)*+*’+---------+---------+---------+---------+*ˆD2‚=…|‚$C…|‚$01„|‚$80„|‚key„|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+---------------------------------------+$*ˆD4‚=…|ƒ0…|ƒ0…|�dev.stat|�dev.type|+*’+-------------------+---------+---------+***‰PAGEI**************************************************************************)*ˆE�V�E�N�T…W�I�T�H„A�N„A�L�T�E�R�N�A�T�E**‘S�E�R�V�I�C�E…A�D�D�R�E�S�S*J***************************************************************************)*’Event�with�an�alternate�service�address*+*’+---------+---------+---------+---------++*ˆD2‚=…|�length‚|‚$81„|�upper�word�of�addr|+*’+---------+---------+---------+---------+)*ˆD3‚=…|�lower�word�of�addr|‚typeƒ|‚key„|+*’+---------------------------------------+**ˆD4‚=…|�DCB�address�or�channel�mnemonic‡|+*’+---------------------------------------+"*ˆD5‚=…|�continuation�of�message�|+*’+---------------------------------------+ *ˆD6‚=…|§|+*’+---------------------------------------+*‰PAGED**********************************************************************’Normal�I/O�completion�event#*’with�an�alternate�service�address*+*’+---------+---------+---------+---------+'*ˆD2‚=…|‚$E…|‚$81„|�comp�addr�upper�wd|+*’+---------+---------+---------+---------+(*ˆD3‚=…|comp�addr�lower�wd�|‚$70„|‚key„|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD5‚=…|ƒ0…|�errorƒ|*’+-------------------+***’I/O�HALT�event#*’with�an�alternate�service�address*+*’+---------+---------+---------+---------+'*ˆD2‚=…|‚$E…|‚$81„|comp�addr�upper�wd�|+*’+---------+---------+---------+---------+(*ˆD3‚=…|�comp.�addr�lower�w|ƒ$71ƒ|‚key„|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD5‚=…|ƒ0…|�errorƒ|*’+-------------------+**’Unsolicited�device�event#*’with�an�alternate�service�address**’and�status�value�=�0�(DCB�address�known)*+*’+---------+---------+---------+---------+(*ˆD2‚=…|‚$10„|‚$81„|comp�addr�upper�wd�|+*’+---------+---------+---------+---------+(*ˆD3‚=…|comp�addr�lower�wd�|‚$80„|‚key„|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+$*ˆD5‚=…|ƒ0…|ƒ0…|�dev.stat|�dev.type|+*’+-------------------+---------+---------+***J**************************************************************************‰PAGEK*****************************************************************************ˆCalling�the�exec:*ˆ-----------------**ˆfrom�interrupt�handler:**ŠMOVE.L‚#24,D0*ŠLEA‚,A0 *ŠTRAPƒ#0*ŠBRA.Sƒƒreturn�1*Їreturn�2**ˆfrom�non-interrupt�handler:**ŠMOVE.L‚#23,D0*ŠLEA‚,A0 *ŠTRAPƒ#0*ŠBRA.Sƒƒreturn�1*Їreturn�2**H************************************************************************* *‚EQUATES* EXEC…EQU‡07EVNTSVSZ�EQU‡4‰Number�of�bytes�added�to�event�length�if**œthe�alternate�service�address�is�needed.6EVNTCMSZ�EQU‡10ˆSize�of�a�normal�completion�event�with*œno�extra�fields.(EVNTMXSZ�EQU‡18ˆMaximum�size�of�an�event6EVNTIOƒEQU‡1‰Event�code�for�an�event�with�no�alternate*œservice�address.:EVNTIOSA�EQU‡$81‡Event�code�for�an�event�with�an�alternate*œservice�address***ˆXDEF'S*‰XDEF†N_NRM_QEVENT‰XDEF†I_NRM_QEVENT‰XDEF†N_HLT_QEVENT‰XDEF†I_HLT_QEVENT‰XDEF†N_UNS_QEVENT‰XDEF†I_UNS_QEVENT* *ˆINCLUDES**ˆ9995..CCB.EQ*ˆ9995..STR.EQ*ˆ9995..LV5.EQ*ˆ9995..UTILITY.MC*‰NOLIST‰INCLUDEƒ9995.&.CCB.EQ‰NOLIST‰INCLUDEƒ9995.&.STR.EQ‰NOLIST‰INCLUDEƒ9995.&.LV5.EQ‰NOLIST‰INCLUDEƒ9995.&.UTILITY.MC‰LIST ‰SECTIONƒ15QEVENT_REGSˆRE- G‡D0-D7/A0-A5‰PAGEE**********************************************************************+*ˆN�O�R�M�A�L„C�O�M�P�L�E�T�I�O�N†E�V�E�N�T*D******************************************************************** N_NRM_QEVENT:)‰MOVEM.LƒQEVENT_REGS,-(SP)�Save�registers‰MOVE.L„#T0QEVNTT,D0‰BRA‡NRM_QEVENT I_NRM_QEVENT:)‰MOVEM.LƒQEVENT_REGS,-(SP)�Save�registers‰MOVE.L„#T0QEVNTI,D0 L1‡SET‡XPSNRM<<80NRM_QEVENT‰MOVE.W„#L1,D5‹D5.W�<---�event�type�in*°upper�byte,�0's�in�lower*=*‚The�following�code�is�used�both�by�the�normal�event�routine$*‚and�by�the�halt�I/O�event�routine.A*‚On�entry,�D5.W‚contains�the�appropriate�event�type�in�its�upper!*‚byte,�and�00�in�its�lower�byte:*+*’+---------------------------------------+*ˆD5‚=…|ƒ?…|ƒ?…|‚typeƒ|„0„|+*’+-------------------+---------+---------+*NRM_HLT*?*‚First�we�find�out�of�there�is�an�alternate�completion�service *‚address.*‰MOVE.L„CCBSVVC(A5),D2 ‰IF„„THEN‰PAGEJ***************************************************************************+*ˆN�O�R�M�A�L„C�O�M�P�L�E�T�I�O�N‡E�V�E�N�T**ˆO�R„H�A�L�TƒI�/�O„E�V�E�N�T*-*ˆW�I�T�H…A�N…A�L�T�E�R�N�A�T�E…A�D�D�R�E�S�S*E**********************************************************************@*‚At�this�point�we�know�there�is�a�completion�service�address�in<*‚D2.‚We�have�to�get�its�upper�word�in�the�lower�word�of�D2,@*‚and�its�lower�word�in�the�upper�word�of�D3.‚But�first,�we�move;*‚the�DCB�address�which�is�currently�in�D3�into�D4�where�it"*‚belongs,�and�we�copy�D2�into�D3.* �MOVE.LƒD3,D4 �MOVE.LƒD2,D3*#*‚Now�the�registers�look�like�this:*+*’+---------------------------------------+*ˆD1‚=…|…?ƒ|„?„|ƒ?…|error„|+*’+-------------------+---------+---------+*+*’+---------+---------+---------+---------+0*ˆD2‚=…|comp�addr�upper�wd�|�comp�addr�lower�wd|+*’+---------+---------+---------+---------+0*ˆD3‚=…|comp�addr�upper�wd�|�comp�addr�lower�wd|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD5‚=…|ˆ?Š|�type„|ƒ0…|+*’+---------------------------------------+*+*‚Remember,�we�want�them�to�look�like�this:*+*’+---------+---------+---------+---------+'*ˆD2‚=…|‚$E…|‚$81„|�comp�addr�upper�wd|+*’+---------+---------+---------+---------+)*ˆD3‚=…|comp�addr�lower�wd�|‚typeƒ|‚key„|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD5‚=…|ƒ0…|�errorƒ|*’+-------------------+*@*‚Now�to�fix�up�D3.‚We�will�SWAP�it�and�then�move�the�event�type,*‚from�D5.W�upper�byte‚into�D3.W�upper�byte.+*‚Then�we�will�put�the�CCBKEY�byte�into�D3.*�SWAPŠD3 �MOVE.WˆD5,D3�MOVE.BˆCCBKEY(A5),D3*#*‚The�registers�now�look�like�this:**+*’+---------------------------------------+*ˆD1‚=…|…?ƒ|„?„|ƒ?…|error„|+*’+-------------------+---------+---------+*+*’+---------+---------+---------+---------+0*ˆD2‚=…|comp�addr�upper�wd�|�comp�addr�lower�wd|+*’+---------+---------+---------+---------+)*ˆD3‚=…|comp�addr�lower�wd�|�type„|‚key„|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD5‚=…|ˆ?Š|‚typeƒ|ƒ0…|+*’+---------------------------------------+**=*‚Now�to�fix�up�D2.‚We�need�to�move�the�length�and�event�code$*‚($0E81)�into�D2.W,�then�do�a�SWAP.*L1‡SET‡EVNTCMSZ+EVNTSVSZ%L1‡SET‡L1<<8+EVNTIOSA�D2.W�<---�$0E81�MOVE.W„#L1,D2�SWAP†D2*#*‚THE�REGISTERS�NOW�LOOK�LIKE�THIS:**+*’+---------------------------------------+*ˆD1‚=…|…?ƒ|„?„|ƒ?…|error„|+*’+-------------------+---------+---------+*+*’+---------+---------+---------+---------+&*ˆD2‚=…|‚$0Eˆ$81ƒ|�comp�addr�upper�wd|+*’+---------+---------+---------+---------+)*ˆD3‚=…|comp�addr�lower�wd�|‚typeƒ|‚key„|+*’+-------------------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+---------------------------------------+*ˆD5‚=…|ˆ?Š|‚typeƒ|ƒ0…|+*’+-------------------------- --------------+*@*‚Now�to�fix�up�D5.‚We�need�to�get�the�error�code�into�the�lowerB*‚byte�of�the�upper�word,�and�a�0�into�the�upper�byte�of�the�upper*‚word.* �CLR.WƒD5 �MOVE.B‚D1,D5�SWAP„D5* *‚The�event�is�now�ready�to�send)*‚See�if�we�need�to�copy�into�user's�area*‰IF.L„A0‚‚#0ƒTHENŽBSRƒCOPY4_EVENT‰ENDI* ‰PAGE‰ELSEJ***************************************************************************+*ˆN�O�R�M�A�L„C�O�M�P�L�E�T�I�O�N‡E�V�E�N�T**ˆO�R„H�A�L�TƒI�/�O„E�V�E�N�T*-*ˆW�I�T�H…N�O…A�L�T�E�R�N�A�T�E…A�D�D�R�E�S�S*E**********************************************************************?* We arrive here because we have a normal completion event or a>* halt I/O event with no alternate completion service address.N*‚Thus�register�D3�is�all�set,�and�we�only�have�to�fix�up�registers�D2�and�D4.**#*‚THE�REGISTERS�NOW�LOOK�LIKE�THIS:**+*’+---------------------------------------+*ˆD1‚=…|…?ƒ|„?„|ƒ?…|�errorƒ|+*’+-------------------+---------+---------+*+*’+---------+---------+---------+---------+ *ˆD2‚=…|�?—|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+ *ˆD4‚=…|�?–|+*’+---------------------------------------+*ˆD5‚=…|‰?‰|�type„|ƒ0…|+*’+---------------------------------------+**L1‡SET‡EVNTCMSZ<<24+EVNTIO<<16* �MOVE.Lˆ#L1,D2‡D2�<---�$0A010000 �MOVE.WˆD5,D2�MOVE.BˆCCBKEY(A5),D2 �CLR.W‰D4 �MOVE.BˆD1,D4�SWAPŠD4 *#*‚THE�REGISTERS�NOW�LOOK�LIKE�THIS:**+*’+---------------------------------------+*ˆD1‚=…|…?ƒ|„?„|ƒ?…|�errorƒ|+*’+-------------------+---------+---------+*+*’+---------+---------+---------+---------+*ˆD2‚=…|‚$0Aˆ$01ƒ|‚typeƒ|‚key„|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+*ˆD4‚=…|„0„|�errorƒ|‰?‰|+*’+---------------------------------------+*+*’+---------------------------------------+*ˆD5‚=…|ˆ?Š|‚typeƒ|ƒ0…|+*’+---------------------------------------+**!*‚The�event�is�now�ready�to�send.0*‚See�if�the�user�wants�us�to�copy�it�somewhere.*ŒIF.LƒA0‚‚#0ƒTHEN‘BSRƒCOPY3_EVENTŒENDI‰ENDI ‰PAGEK****************************************************************************0*ˆS�E�N�D„T�H�EƒE�V�E�N�T…I�N…D2�-�D4‚OR„D2�-�D5*M******************************************************************************!*‚The�event�is�now�ready�to�send.* SEND_EVENT**‚Set�up�for�the�TRAP�#0�call.*‰MOVE.L„CCBRQSTA(A5),A0‰TRAP‚#0 ‰BRAƒEVENT_OK ‰MOVEQ�#1,D0‰BRAƒRESTORE_REGSEVENT_OK„CLRƒD0 RESTORE_REGS‰MOVEM.L„(SP)+,QEVENT_REGS‰RTS‰PAGEJ***************************************************************************1*ˆC�O�P�Y…T�H�E…E�V�E�N�T„T�O„U�S�E�R�'�S„A�R�E�A*H************************************************************************ COPY3_EVENT:‰MOVEM.L„D2-D4,(A0)‰RTS COPY4_EVENT:‰MOVEM.L„D2-D5,(A0)‰RTS  ‰PAGEI***************************************************************************ˆH�A�L�T„I�/�O†E�V�E�N�T*K*************************************************************************** N_HLT_QEVENT)‰MOVEM.LƒQEVENT_REGS,-(SP)�Save�registers‰MOVE.L„#T0QEVNTT,D0‰BRAƒHLT_QEVENT I_HLT_QEVENT)‰MOVEM.LƒQEVENT_REGS,-(SP)�Save�registers‰MOVE.L„#T0QEVNTI,D0L1‡SET‡XPSHLT<<8 HLT_QEVENT*‰MOVE.W„#L1,D5ŽD5.W�<---�event�type�*�$100 ‰BRA‡NRM_HLT L**************************************************************************** ‰PAGEG************************************************************************-*ˆU�N�S�O�L�I�C�I�T�E�D…D�E�V�I�C�E…E�V�E�N�T*H************************************************************************ N_UNS_QEVENT:‰MOVEM.L„QEVENT_REGS,-(SP)‰MOVE.L„#T0QEVNTT,D0‰BRA‡UNS_QEVENT I_UNS_QEVENT:‰MOVEM.L„QEVENT_REGS,-(SP)‰MOVE.L…#T0QEVNTI,D0 )*‚On�entry,�the�registers�look�like�this:**+*’+---------------------------------. ------+ *ˆD2‚=…|“?“|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+ *ˆD4‚=…|‰?‰|dev�stat�|dev�type�|+*’+---------------------------------------+* UNS_QEVENT‰MOVE.L„CCBSVVC(A5),D2 ‰IFƒ„THEN‰PAGEM******************************************************************************-*ˆU�N�S�O�L�I�C�I�T�E�D†D�E�V�I�C�E„E�V�E�N�T*)*ˆW�I�T�H…A�L�T�E�R�N�A�T�E„A�D�D�R�E�S�S*C********************************************************************G*‚We�have�to�move�things�up�to�squeeze�the�alternate�completion�address0*‚into�the�registers�D2�and�D3�as�we�did�before.* ŽCLR.LŠD5 ŽMOVE.W‰D4,D5 ŽMOVE.L‰D3,D4 ŽMOVE.L‰D2,D3ŽSWAP�D3 $*ƒNow,�the�registers�look�like�this:**+*’+---------------------------------------+0*ˆD2‚=…|comp�addr�upper�wd�|comp�addr�lower�wd�|+*’+---------------------------------------+0*ˆD3‚=…|comp�addr�lower�wd�|comp�addr�upper�wd�|+*’+---------+---------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+$*ˆD5‚=…|„0„|„0„|dev�stat�|dev�type�|+*’+---------------------------------------+*L1‡SET‡XPSUNS<<8ŽMOVE.W‰#L1,D3ŽD3.W‚<---‚$8000ŽMOVE.B‰CCBKEY(A5),D3L1‡SET‡EVNTCMSZ+EVNTSVSZ+2%L1‡SET‡L1<<8+EVNTIOSA�D2.W‚<---�$1081ŽMOVE.W‰#L1,D2 ŽSWAP�D2$*ƒNow,�the�registers�look�like�this:**+*’+---------------------------------------+(*ˆD2‚=…|‚$10„|ƒ$81ƒ|comp�addr�upper�wd�|+*’+---------------------------------------+(*ˆD3‚=…|comp�addr�lower�wd�|‚$80„|‚key„|+*’+---------+---------+---------+---------+*ˆD4‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+$*ˆD5‚=…|„0„|ƒ0…|dev�stat�|dev�type�|+*’+---------------------------------------+***!*‚The�event�is�now�ready�to�send.%*‚Let's�see�if�the�user�wants�a�copy.*�IF.L‚A0‚‚#0‚THEN.L‘BSR‚COPY4_EVENT�ENDI‰ELSE ‰PAGED*********************************************************************-*ˆU�N�S�O�L�I�C�I�T�E�D…D�E�V�I�C�E…E�V�E�N�T*&*ˆWITH„NO„ALTERNATE„COMPLETION„ADDRESS*C******************************************************************* L1‡SET‡EVNTCMSZ+2"L1‡SET‡L1<<24+EVNTIO<<16+XPSUNS<<8 ‰MOVE.L„#L1,D2“D2�<---�$0C018000‰MOVE.B„CCBKEY(A5),D2*$*‚Now,�the�registers�look�like�this:**+*’+---------------------------------------+*ˆD2‚=…|‚$0C„|‚01…|‚$80„|‚key„|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+ *ˆD4‚=…|‰?‰|dev�stat�|dev�type�|+*’+---------------------------------------+*‰AND.L�#$0000FFFF,D4*$*‚Now,�the�registers�look�like�this:**+*’+---------------------------------------+*ˆD2‚=…|‚$0C„|‚01…|‚$80„|‚key„|+*’+---------+---------+---------+---------+*ˆD3‚=…|‹DCB�address‘|+*’+-------------------+---------+---------+#*ˆD4‚=…|ƒ0…|„0„|dev�stat�|dev�typ‚|+*’+---------------------------------------+*!*‚Now�the�event�is�ready�to�send.%*‚Let's�see�if�the�user�wants�a�copy.*ŽIF.LƒA0‚‚#0„THEN.L’BSRƒCOPY3_EVENTŽENDI‰ENDI ‰BRA‡SEND_EVENT ‰ENDééé. é‰PAGE5SETTIME‚IDNT†4,4‡SET�UP�PERIODIC�ACTIVATION�(TRAP�#0)‰OPT‡PCS,BRS,CREN******************************************************************************N******************************************************************************* *ˆSET_TIME*;*ˆThis�routine�sets�up�and�does�a�trap�0�call�to�generate�a;*ˆwakeup�call.‚The�driver�writer�may�want�to�do�this�before>*ˆgiving�a�command�to�the�controller�as�a�timeout,�so�that�the>*ˆsystem�will�not�hang�waiting�for�an�interrupt�that�may�never*ˆcome.*<*ˆThis�routine�will�not�do�the�TRAP�#0�call�if�the�number�of!*ˆmilliseconds�asked�for�is�zero.**ˆSubroutines�called:**ˆEntry:„A5�=�address�of�CCB *’A3�=�address�of�wakeup�routine.*’D3�=�number�of�milliseconds�for�wakeup�call.*"*ˆRegisters�usage:†0‚1‚2‚3‚4‚5‚6‚7 *™D„*‚*‚*‚P *™A„*‚*…P…P**™P�=�parameter�register*™R�=�return�register!*™*�=�saved�and�restored�register*6*ˆExit:…CCR:��=�periodic�activation�call�succeeded)*—�=�periodic�activation�call�did�not *žsucceed*žor�number�of�milliseconds�=�0*"*ˆExits�to:�RTS�to�calling�routine*L******************************************************************************…NOTES�on�using�this�routine:*?*…The�address�you�send�in�A3�is�the�address�where�the�exec�will.*…start�you�executing�when�the�timer�goes�off.*@*…When�you�start�executing,�the�registers�saved�by�the�exec�are:*ˆD0,D1,A0,�and�A1.>*…This�is�different�from�the�registers�that�are�saved�when�you2*…ordinarily�get�an�interrupt,�namely‚D0,A0,A1,A5.*D*…In�D1�you�find�an�ID�that�you�told�the�exec�about�when�you�did�the;*…trap�call.‚In�our�case,�the�ID�is�the�address�of�the�CCB.*B*…So�the�first�thing�to�do�upon�wakeup�is�to�push�A5�and�any�other<*…registers�you�might�use�on�the�stack,�and�move�D1�into�A5.**3*…Also,�you�must�return�with�an�RTE�from�this�call.*M*****************************************************************************É<Ò0M****************************************************************************** *ˆINCLUDES**ˆ9995.&.UTILITY.MC*ˆ9995.&.STR.EQ*ˆ9995.&.CCB.EQ*‰NOLIST‰INCLUDEƒ9995.&.UTILITY.MC‰NOLIST‰INCLUDEƒ9995.&.STR.EQ‰NOLIST‰INCLUDEƒ9995.&.CCB.EQ‰LIST ‰SECTIONƒ15 SET_TIME:*SET_REGS�REG„D0-D2/A0-A1&�SAVE‡SET_REGSŽSave�registers�used�for *°trap�call* �PUSH‡#1”Set�flag�for�bad�return�TST.L†D3”Are�we�asking�for�0*°milliseconds?#�BEQ.S†SET_RET�If�so,�there�will�be*°no�exec�call.$�MOVE.L…#T0RQPA,D0ŒD0�<---�directive�CLRˆD1/�MOVE.B…CCBPPRIO(A5),D1‡D1�<---�interrupt�level!�MOVE.L…A5,D2‘D2�<---�CCB�address'�MOVE.L…A3,A0‘A0�<---�address�of�wakeup,�MOVE.L…D3,A1‘A1�<---�no.�of�milliseconds�to*¸wait�for�wakeup�TRAP‡#0 �BRA.S†SET_WAT1Žrequest�accepted#�BRA.S†SET_RET�request�not�accepted'SET_WAT1ˆCLRˆ(SP)’Clear�flag�to�show�OK**'SET_RET‰POPˆD0”Fix�CCR�by�popping�stack�RESTORE„SET_REGS ‰RTS‰END L**************************************************************************** é/ éé=/*=/*†DRVLIB.LOGPHY.AF=/*B=/* Chain file to assemble DRVLIB.LOGPHY.SA, a driver library file=/*:=/* If no output argument is specified for the listing the/=/* chain file will default to DRVLIB.LOGPHY.LS=/*=/IFC \1ƒ=ARG�DRVLIB.LOGPHY.LS=/ENDIF=/*.=ASM DRVLIB.LOGPHY.SA,DRVLIB.LOGPHY.RO,\1;Z=75=/*{ Included files are:=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.TCB.EQ=/*ƒ9995.&.STR.EQ=/*}=/*=ENDééééééÚ=/*=/*†DRVLIB.QEVENT.AF=/*B=/* Chain file to assemble DRVLIB.QEVENT.SA, a driver library file=/*:=/* If no output argument is specified for the listing the/=/* chain file will default to DRVLIB.QEVENT.LS=/*=/IFC \1ƒ=ARG�DRVLIB.QEVENT.LS=/ENDIF=/*.=ASM DRVLIB.QEVENT.SA,DRVLIB.QEVENT.RO,\1;Z=75=/*{ Included files are:=/*ƒ9995.&.CCB.EQ=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.LV5.EQ=/*ƒ9995.&.UTILITY.MC=/*}=/*=ENDééé/ éééã=/*=/*†DRVLIB.SETTIME.AF=/*C=/* Chain file to assemble DRVLIB.SETTIME.SA, a driver library file=/*:=/* If no output argument is specified for the listing the0=/* chain file will default to DRVLIB.SETTIME.LS=/*=/IFC \1ƒ=ARG�DRVLIB.SETTIME.LS=/ENDIF=/*0=ASM DRVLIB.SETTIME.SA,DRVLIB.SETTIME.RO,\1;Z=75=/*{ Included files are:=/*ƒ9995.&.UTILITY.MC=/*ƒ9995.&.STR.EQ=/*ƒ9995.&.CCB.EQ=/*}=/*=ENDééééééì' VMES10 CRTINIT SAóbbEDITMODESA""~ubbFEEDER SA££%bbINCHAR SAÌ̤bbOUTCHS SAååÏÙbbPAGEMODESA¶¶ rbbPOUTCHS SAǸò bbERMDRV SAÁ ²0 ybb0 4CRTINIT‚IDNT†1,00†Configure�the�virtual�display�area <*************************************************************º**�Routine�name:ŽCRTINIT—*<*----------------------------------------------------------*-*�Current�revision.....................1.00�*1*�Date�written.........................12-21-82Œ*2*�Written�by...........................S.Pri-Tal‹*)*�Date�changed.........................”*)*�Changed�by...........................”**º**�Description�of�change:£**º**º**º**º**º**º*<************************************************************.*�Function:�Initialize�all�the�CRT�constants�*<*----------------------------------------------------------**�Input�parameters:�none£*<*----------------------------------------------------------**�Registers�affected:�none¡*<*----------------------------------------------------------* *�External�routines�used:�none�*<************************************************************‰PAGE ‰XDEF†CRTINIT‰XDEF†SCRNINIT *‰XDEF†FACS�Field�Attribute�Codes�in�effect 5‰XDEF†CPERLINEŒNumber�of�characters�per�absolute�line+‰XDEF†BPERLINEŒNumber�of�bytes�per�RAM�line2‰XDEF†LPERSCRNŒNumber�of�lines�per�absolute�screen "‰XDEF†S.SCRNŽVirtual�home�position*‰XDEF†E.SCRNŽEnd�address�of�virtual�screen 3‰XDEF†C.LINEŽNumber�of�characters�in�a�virtual�line.‰XDEF†B.LINEŽNumber�of�bytes�in�a�virtual�line/‰XDEF†PB.LINE�Number�of�blanked�bytes�in�a�line2‰XDEF†S.LINEŽStart�address�of�virtual�current�line0‰XDEF†E.LINEŽEnd�address�of�virtual�current�line0‰XDEF†L.SCRNŽNumber�of�lines�in�a�virtual�screen (‰XDEF†SCREENŽBase�address�of�display�RAM<‰XDEF†CRTCADD,CRTCREG…Addresses�of�CRT�controller�registers. +‰XDEF†LEFTCOL�Left�column�of�virtual�screen-‰XDEF†RIGHTCOLŒRight�column�of�virtual�screen*$*Š0<=�LEFTCOL/RIGHTCOL�<=�CPERLINE-1*(‰XDEF†TOPLINE�Top�line�of�virtual�screen+‰XDEF†BOTLINE�Bottom�line�of�virtual�screen*#*Š0<=�TOPLINE/BOTLINE�<=�LPERSCRN-1*#‰XDEF†PAGEFLAGŒ0=scroll;�$FFFF=page ù?F E*.SCREENƒEQU‡$F17000�Base�address�of�display�RAM(CRTCADD‚EQU‡$F1A021�Base�address�of�CRTC1CRTCREG‚EQU‡$F1A023�Address�of�CRTC�register�file‰PAGE ‰SECTIONƒ16CPERLINE�DC.W†80’Number�of�characters�in�absolute�line3LPERSCRN�DC.W†25’Number�of�lines�in�absolute�screen6BPERLINE�DC.L†160‘Number�of�bytes�in�absolute�RAM�line*G* The following 4 constants can be changed by using escape sequences or* their eqivalents.*,LEFTCOL‚DC.W†0“Default�value�for�left�column/RIGHTCOL�DC.W†79’Default�value�for�right�column)TOPLINE‚DC.W†0“Default�value�for�top�line-BOTLINE‚DC.W†23’Default�value�for�bottom�line 7S.SCRNƒDC.L†$F17000�Init�to�be�the�same�as�start�of�RAM7E.SCRNƒDC.L†$F17F00�End�address�of�virtual�display�area&C.LINEƒDC.W†79’Adjusted�for�DBRA�loopsB.LINEƒDC.L†160)S.LINEƒDC.L†$F17000�Start�of�current�line'E.LINEƒDC.L†$F170A0�End�of�current�linePB.LINE‚DC.W†00&L.SCRNƒDC.W†23’Adjusted�for�DBRA�loops)*C.SCRNƒDC.L†1919�Adjusted�for�DBRA�loopsFACS…DC.W†$4400#PAGEFLAG�DC.W†0“Init�to�scroll�mode‰PAGE‰SECTIONƒ11’Program�areaSCRNINIT�DS.W†0-‰MOVE.W„#80,CPERLINEˆ80�characters�per�screen1‰MOVE.W„#25,LPERSCRNˆ24�lines�in�the�display�area‰CLR.W…TOPLINE‰MOVE.W„#23,BOTLINE‰CLR.W…LEFTCOL‰MOVE.W„#79,RIGHTCOL‰CLR.W…PAGEFLAG SPC 1 CRTINIT‚EQU‡*'‰MOVEM.LƒD0/A0,-(A7)‰Save�user's�values‰CLR.L…D0’HSKP ** Init the FACs register*‰MOVE.W„#$4400,FACS**ˆD15†cleared�for�unprotect*ˆD14†set�for�display*ˆD13†cleared�for�non-blink*ˆD12†cleared�fo0 r�no�underline$*ˆD11†cleared�for�non�inverted�video<*ˆD10-D08‚set�for�half�brightness�(111�=�maximum�brightness)*ˆD07†cleared�for�no�TAB*ˆD06-D00‚null�character* *9* Init number of RAM bytes required for one absolute line**’BPERLINE�=�CPERLINE*2*:‰MOVE.W„CPERLINE,D0‰Maximum�number�of�characters�in�a�line‰LSL.L…#1,D0Ž*2,‰MOVE.L„D0,BPERLINEˆ=Bytes�per�absolute�line *M* Init the number of character per line in the virtual display area - C.LINE.*!*’C.LINE�=�RIGHTCOL�-�LEFTCOL�+�1*>* (adjusted for DBRA loops, expressed in characters on screen)* ‰CLR.L…D0;‰MOVE.W„RIGHTCOL,D0‰Requested�last�column�in�virtual�screen;‰SUB.W…LEFTCOL,D0‰-Requested�first�column�in�virtual�screen9‰MOVE.W„D0,C.LINEŠ=Number�of�characters�in�a�virtual�line*¦-1�to�adjust�for�DBRA�loops ‰ADD.W…#1,D0 ‰LSL.W…#1,D0-‰MOVE.L„D0,B.LINE‹Init�bytes�per�virtual�line *1* Init the number of blanked bytes in a RAM line.* *’PB.LINE�=[CPERLINE�-�C.LINE]*2* ‰CLR.L…D0<‰MOVE.W„CPERLINE,D0‰Number�of�characters�in�an�absolute�line8‰SUB.W…C.LINE,D0Š-Number�of�characters�in�a�virtual�line)‰SUB.W…#1,D0�To�adjust�for�the�DBRA�value‰LSL.W…#1,D0�Times�29‰MOVE.W„D0,PB.LINE‰=Number�of�blanked�bytes�in�a�RAM�line *@* Init the number of lines in the virtual display area - L.SCRN.**’L.SCRN�=�BOTLINE�-�TOPLINE�+1** Adjusted for DBRA loops* ‰CLR.L…D0(‰MOVE.W„BOTLINE,D0ŠRequested�bottom�line%‰SUB.W…TOPLINE,D0‰-Requested�top�line6‰MOVE.W„D0,L.SCRNŠ=Number�of�lines�in�a�virtual�screen *D* Init the number of character in the virtual display area - C.SCRN.*#*’C.SCRN�=�[C.LINE�+1]�*�[L.SCRN+1]*H* (adjusted for DBRA loops, expressed in number of characters in screen)* *ˆCLR.L…D09*ˆMOVE.W„C.LINE,D0‹Number�of�characters�in�a�virtual�line$*ˆADD.W…#1,D0�To�adjust�for�the�DBRA*ˆMOVE.W„D0,C.SCRN6*ˆMOVE.W„L.SCRN,D0‹Number�of�lines�in�a�virtual�screen$*ˆADD.W…#1,D0�To�adjust�for�the�DBRA<*ˆMULU.W„C.SCRN,D0Š=Number�of�characters�in�a�virtual�screen*ˆMOVE.W„D0,C.SCRN-*ˆSUB.W…#1,C.SCRNŠ-1�to�adjust�for�DBRA�loops *H* Init the absolute address of home position in the virtual display area*0*ˆS.SCRN�=�SCREEN�+�TOPLINE*BPERLINE�+�LEFTCOL*2* ,‰MOVE.L„BPERLINE,D0ˆ=Bytes�per�absolute�line0‰MULU.W„TOPLINE,D0‰=Unused�area�on�top�of�screen‰ADD.W…LEFTCOL,D00‰ADD.W…LEFTCOL,D0‰+Unused�bytes�at�start�of�line.‰ADD.L…#SCREEN,D0‰+Base�address�of�display�RAM+‰MOVE.L„D0,S.SCRNŠ=Virtual�home�RAM�address *B* Init the absolute address of the end of the virtual display area*1*ˆE.SCRN�=�SCREEN�+�BOTLINE*BPERLINE�+�RIGHTCOL*2*,‰MOVE.L„BPERLINE,D0ˆ=Bytes�per�absolute�line9‰MULU.W„BOTLINE,D0‰=Number�of�bytes�to�start�of�last�line‰ADD.W…RIGHTCOL,D07‰ADD.W…RIGHTCOL,D0ˆ=Number�of�bytes�to�end�of�last�line&‰ADD.L…#SCREEN,D0‰=Base�address�of�RAM ‰ADD.L…#2,D01‰MOVE.L„D0,E.SCRNŠ=End�of�virtual�screen�in�RAM+1 *?* Init S.LINE to point to start address of cursor virtual line.=* Init E.LINE to point to end address of cursor virtual line.*‰CLR.L…D0’HSKP ‰MOVE.B„#$E,CRTCADD‰Point�to�R14‰MOVE.B„CRTCREG,D0 ‰LSL.W…#8,D0‰MOVE.B„#$F,CRTCADD2‰MOVE.B„CRTCREG,D0ŠD0.W=absolute�address�of�cursor ‰LSL.W…#1,D0 ‰MOVE.L„D0,A02‰ADD.L…#SCREEN,A0ŠA0.L=address�of�cursor�on�screen ‰LSR.W…#1,D0‰DIVU†CPERLINE,D0‰D0.L=00cc00ll‰SWAP†D0’D0.W=00cc7‰SUB.W…LEFTCOL,D0ŠD0.W=number�of�spots�to�start�of�line‰LSL.W…#1,D0�To�make�it�bytes ‰SUB.W…D0,A0‰MOVE.L„A0,S.LINE ‰ADD.W…C.LINE,A0‰ADD.W…C.LINE,A0 ‰ADD.W…#2,A0‰MOVE.L„A0,E.LINE‰MOVEM.Lƒ(A7)+,D0/A0‰RTS‰END é1 éé9EDITMODE‚IDNTƒ1,0„VME/10�edit�mode�emulation�for�TERMDRV.O*v*****************************************************************************O*******************************************************************************O**********************************************************************************É***=***†FILENAME:‚EDITMODE�--�EDIT�MODE�EMULATION�FOR�TERMDRV�******É***8***†ENVIRONMENT:‚Linked�into�TERMDRV�for�the�VME/10.’******É***E***†FUNCTION:‚When�the�keyboard/screen�is�put�into�edit�mode,�any…***?***‰characters�received�from�the�keyboard�are�sent�here�for‰******‰special�interpretation.©******É***B***†NOTES:‚Only�RETURN�COMMAND�mode�is�implemented;�NON-RETURNˆ***D***‰COMMAND�mode�is�not�since�the�VERSAdos�editor�(E.LO)�doesn't„******‰use�it.¹******É***,***†EXTERNAL�DATA�STRUCTURES�REFERENCED:Ÿ*** ***‰CCB�for�terminal�driver.¨***(***‰Various�parameters�from�CRTINIT. ******É***)***†EXTERNAL�ENTRY�POINTS�REFERENCED:¢******‰OUTCHSº******É***"***†SERVICES�CALLED�VIA�TRAPS:©******É***O*******************************************************************************O*******************************************************************************O*^***************************************************************************** *,*‚Revision�history�(add�new�changes�to�top).*…Date†Author‰ChangesG*…--------‚-------------‚----------------------------------------------;*†1/30/85‚Mike�Duh‡Set�RING_BELL�flag�when�$07�is�detected.2*†7/19/83‚Steve�FranckƒSeparated�out�FEEDER�stuff.'*†4/31/83‚Steve�FranckƒInitial�writing.*ŠPAGE* *‚XDEF's.*:ŠXDEFƒEDITMODE‹Entry�pt.�for�char's�received�in�edit�mode.5ŠXDEFƒKB_LOCKŒFlag�indicating�whether�the�keyboard�is(*§locked�(from�having�sent�a�termination*§packet�in�edit�mode).7ŠXDEFƒDUP_CHAR‹This�is�a�word�field,�$FFFF�if�there�was%*§no�DUPLICATE�CHAR�specified�when�we'*§got�put�into�command�mode,�else�$00dd%*§($dd=the�DUPLICATE�CHAR)�if�one�was *§specified.    * 8#?+F3:;3C*K)S,[)c'k1s>{GƒO‹@“80*‚XREF's�(indicate�where�the�XDEF�is,�if�known).*8ŠXREFƒOUTCHS�Routine�in�OUTCHS�to�output�char�on�screen./*ž(All�of�the�following�are�XDEF'ed�in�CRTINIT)9ŠXREFƒBPERLINE‹#�of�bytes�per�absolute�display�line�(.L).$*§Note�that�since�this�is�a�longword#*§the�address�BPERLINE+2�is�used�in%*§DIVU�instructions�(which�use�only�a"*§word�for�the�divisor).‚The�upper*§word�is�always�0.3ŠXREFƒC.LINE�#�of�char's�per�virtual�line�-�1�(.W).DŠXREFƒS.LINE,E.LINE�Start/end�addr�+�1�of�current�virtual�line�(.L).>ŠXREFƒS.SCRN,E.SCRN†Start/end�addr�+�1�of�virtual�screen�(.L).4ŠXREFƒSCREEN�Base�address�of�screen�RAM�(an�equate).?ŠXREFƒCRTCADD,CRTCREG„Addr's�of�CRT�controller�reg's�(equates)..*ž(All�of�the�following�are�XDEF'ed�in�FEEDER)3ŠXREFƒFEEDER�Entry�point�and�some�variables�for�the>ŠXREFƒFEEDER_ADDRESS…FEEDER�module�which�takes�our�packets�and)ŠXREFƒFEEDER_COUNT‡gives�them�to�TERMDRV. 0ŠXREFƒRING_BELL‹Flag�set�when�$07�is�detected�in&*žorder�to�ring�the�bell�in�KEYBRD.AG.ŠPAGEO*********************************************************************************‰INCLUDE�FILES�AND�EQUATES*O******************************************************************************* *=*‚Define�the�environment�as�EXORMACS/S�in�a�switch�t1 o�control*‚conditional�assemblies.*2ENVIRONMENT�EQU‚'EX/S'�This�is�for�the�EXORMACS/S.  **‚Include�files:5*‰UTILITY.MC‹General�purpose�macros�(e.g.�PUSH,�POP).,*‰IOE.SA�Equates�for�IOS-related�structures.7*‰EQUCCB.EQŒEquates�for�device-independent�part�of�CCB.9*‰TERMDRV.EQ‹Equates�for�the�generalized�terminal�driver.*ŠNOLISTŠINCLUDE‚9995.&.UTILITY.MCŠINCLUDE‚9995.&.IOE.EQŠINCLUDE‚9995.&.CCB.EQŠINCLUDE‚9995.VMES10.TERMDRV.EQŠLIST  .FALSE…EQU„$00�Value�FALSE�for�a�flag�variable.,TRUE†EQU„$FF�Value�TRUE‚for�a�flag�variable.  4BSˆEQU„$08�Definitions�for�certain�ASCII�characters. LFˆEQU„$0A�* CRˆEQU„$0D�*SPACE…EQU„$20�*DELETE„EQU„$7F�*  5HOME†EQU„$C0�Definitions�for�certain�characters�which7UPARROWƒEQU„$C1�are�recognized�by�the�EXORTERM�155�(and4DOWNARROW�EQU„$C2�hence�OUTCHS)�as�special�commands.ERASE_EOL�EQU„$D5�*DEL_LINE‚EQU„$D7�*  :START_OF_DATA�EQU�$DD�Definitions�for�certain�parts�of�the1FILLER_BYTE�EQU‚$FF�packet�returned�in�edit�mode.END_OF_DATA�EQU‚$DE�*ŠPAGEO*********************************************************************************‰MISCELLANEOUS�MACROS*O*******************************************************************************  *G*‚The�OUTPUT�and�OUTPUT_D0�macros�invoke�the�external�subroutine�OUTCHSF*‚to�output�a�character�to�the�EXORMACS/S�screen.‚OUTPUT_D0�just�callsC*‚the�routine�to�output�whatever�is�in�D0.B,�while�OUTCHS�has�as�anH*‚argument�the�value�of�a�character.‚This�character�must�be�in�the�rangeH*‚$00�-�$FF,�of�course,�and�must�be�an�immediate�value�specified�WITHOUT*‚THE�'#'.‚For�example,7*‰OUTPUT�'A'ƒcauses�an�'A'�to�be�written�to�the�screen.*OUTPUT_D0 MACRO ŠBSR.L‚OUTCHSŠENDM OUTPUT„MACRO ŠIFGEƒ\1-$80ŠMOVEQ‚#$FFFFFF00+\1,D0ŠENDC ŠIFLTƒ\1-$80 ŠMOVEQ‚#\1,D0ŠENDC ŠBSR.L‚OUTCHSŠENDMŠPAGEO*********************************************************************************‰DATA�VARIABLES*O******************************************************************************* ŠSECTION�0 **‚Flags.*�THENŠIf�there�is�one,1ŠCMP.B‚D0,D1Ž.‚If�this�character�is�one�of�those,&ŠBEQ.L‚ERASE_LINE‰.‚go�erase�the�line.ŠENDI–. ,ŠCLR„D1‘D1.W�<--�offset�from�table,�which�is4ŠMOVE.B�EDIT_TBL(PC,D0),D1�(routine�addr�-�JMPBASE).;ŠLEA„JMPBASE(PC),A0…Jump�to�the�specified�routine:‚that�is,4ŠJMP„0(A0,D1)‹to�JMPBASE�+�(routine�addr�-�JMPBASE).ŠPAGEO********************************************************************************:*‰TABLE�OF�ACTION�TO�TAKE�FOR�EACH�CHAR�WHILE�IN�EDIT�MODE*O******************************************************************************* EDIT_TBL: ***************7*‚$00�-�$1F‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------&ŠDC.BƒIGNORE-JMPBASE…$00�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$01�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$02�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$03�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$04�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$05�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$06�--�Ignore�it.ŠDC.BƒBELL-JMPBASE‡$07�--�Bell.,ŠDC.BƒPRINT-JMPBASE†$08�--�Print�as�is.�(BS)-ŠDC.BƒPRINT-JMPBASE†$09�--�Print�as�is.�(TAB)7ŠDC.BƒDO_LF-JMPBASE†$0A�--�Special�processing�for�(LF).@ŠDC.BƒPRINT_TERM-JMPBASE�$0B�--�Print�and�send�packet.�(UP�LINE)6ŠDC.BƒPRINT-JMPBASE†$0C�--�Print�as�is.�(CURSOR�RIGHT)7ŠDC.BƒDO_CR-JMPBASE†$0D�--�Special�processing�for�(CR).&ŠDC.BƒIGNORE-JMPBASE…$0E�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$0F�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$10�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$11�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$12�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$13�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$14�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$15�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$16�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$17�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$18�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$19�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$1A�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$1B�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$1C�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$1D�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$1E�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$1F�--�Ignore�it.ŠPAGE***************7*‚$20�-�$3F‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------0ŠDC.B‚PRINT_LOOK-JMPBASE�$20�--�Print�as�is.‚(�)0ŠDC.B‚PRINT_LOOK-JMPBASE�$21�--�Print�as�is.‚(!)0ŠDC.B‚PRINT_LOOK-JMPBASE�$22�--�Print�as�is.‚(")0ŠDC.B‚PRINT_LOOK-JMPBASE�$23�--�Print�as�is.‚(#)0ŠDC.B‚PRINT_LOOK-JMPBASE�$24�--�Print�as�is.‚($)0ŠDC.B‚PRINT_LOOK-JMPBASE�$25�--�Print�as�is.‚(%)0ŠDC.B‚PRINT_LOOK-JMPBASE�$26�--�Print�as�is.‚(&)0ŠDC.B‚PRINT_LOOK-JMPBASE�$27�--�Print�as�is.‚(')0ŠDC.B‚PRINT_LOOK-JMPBASE�$28�--�Print�as�is.‚(()0ŠDC.B‚PRINT_LOOK-JMPBASE�$29�--�Print�as�is.‚())0ŠDC.B‚PRINT_LOOK-JMPBASE�$2A�--�Print�as�is.‚(*)0ŠDC.B‚PRINT_LOOK-JMPBASE�$2B�--�Print�as�is.‚(+)0ŠDC.B‚PRINT_LOOK-JMPBASE�$2C�--�Print�as�is.‚(,)0ŠDC.B‚PRINT_LOOK-JMPBASE�$2D�--�Print�as�is.‚(-)0ŠDC.B‚PRINT_LOOK-JMPBASE�$2E�--�Print�as�is.‚(.)0ŠDC.B‚PRINT_LOOK-JMPBASE�$2F�--�Print�as�is.‚(/)0ŠDC.B‚PRINT_LOOK-JMPBASE�$30�--�Print�as�is.‚(0)0ŠDC.B‚PRINT_LOOK-JMPBASE�$31�--�Print�as�is.‚(1)0ŠDC.B‚PRINT_LOOK-JMPBASE�$32�--�Print�as�is.‚(2)0ŠDC.B‚PRINT_LOOK-JMPBASE�$33�--�Print�as�is.‚(3)0ŠDC.B‚PRINT_LOOK-JMPBASE�$34�--�Print�as�is.‚(4)0ŠDC.B‚PRINT_LOOK-JMPBASE�$35�--�Print�as�is.‚(5)0ŠDC.B‚PRINT_LOOK-JMPBA2 SE�$36�--�Print�as�is.‚(6)0ŠDC.B‚PRINT_LOOK-JMPBASE�$37�--�Print�as�is.‚(7)0ŠDC.B‚PRINT_LOOK-JMPBASE�$38�--�Print�as�is.‚(8)0ŠDC.B‚PRINT_LOOK-JMPBASE�$39�--�Print�as�is.‚(9)0ŠDC.B‚PRINT_LOOK-JMPBASE�$3A�--�Print�as�is.‚(:)0ŠDC.B‚PRINT_LOOK-JMPBASE�$3B�--�Print�as�is.‚(;)0ŠDC.B‚PRINT_LOOK-JMPBASE�$3C�--�Print�as�is.‚(<)0ŠDC.B‚PRINT_LOOK-JMPBASE�$3D�--�Print�as�is.‚(=)0ŠDC.B‚PRINT_LOOK-JMPBASE�$3E�--�Print�as�is.‚(>)0ŠDC.B‚PRINT_LOOK-JMPBASE�$3F�--�Print�as�is.‚(?)ŠPAGE***************7*‚$40�-�$5F‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------0ŠDC.B‚PRINT_LOOK-JMPBASE�$40�--�Print�as�is.‚(@)0ŠDC.B‚PRINT_LOOK-JMPBASE�$41�--�Print�as�is.‚(A)0ŠDC.B‚PRINT_LOOK-JMPBASE�$42�--�Print�as�is.‚(B)0ŠDC.B‚PRINT_LOOK-JMPBASE�$43�--�Print�as�is.‚(C)0ŠDC.B‚PRINT_LOOK-JMPBASE�$44�--�Print�as�is.‚(D)0ŠDC.B‚PRINT_LOOK-JMPBASE�$45�--�Print�as�is.‚(E)0ŠDC.B‚PRINT_LOOK-JMPBASE�$46�--�Print�as�is.‚(F)0ŠDC.B‚PRINT_LOOK-JMPBASE�$47�--�Print�as�is.‚(G)0ŠDC.B‚PRINT_LOOK-JMPBASE�$48�--�Print�as�is.‚(H)0ŠDC.B‚PRINT_LOOK-JMPBASE�$49�--�Print�as�is.‚(I)0ŠDC.B‚PRINT_LOOK-JMPBASE�$4A�--�Print�as�is.‚(J)0ŠDC.B‚PRINT_LOOK-JMPBASE�$4B�--�Print�as�is.‚(K)0ŠDC.B‚PRINT_LOOK-JMPBASE�$4C�--�Print�as�is.‚(L)0ŠDC.B‚PRINT_LOOK-JMPBASE�$4D�--�Print�as�is.‚(M)0ŠDC.B‚PRINT_LOOK-JMPBASE�$4E�--�Print�as�is.‚(N)0ŠDC.B‚PRINT_LOOK-JMPBASE�$4F�--�Print�as�is.‚(O)0ŠDC.B‚PRINT_LOOK-JMPBASE�$50�--�Print�as�is.‚(P)0ŠDC.B‚PRINT_LOOK-JMPBASE�$51�--�Print�as�is.‚(Q)0ŠDC.B‚PRINT_LOOK-JMPBASE�$52�--�Print�as�is.‚(R)0ŠDC.B‚PRINT_LOOK-JMPBASE�$53�--�Print�as�is.‚(S)0ŠDC.B‚PRINT_LOOK-JMPBASE�$54�--�Print�as�is.‚(T)0ŠDC.B‚PRINT_LOOK-JMPBASE�$55�--�Print�as�is.‚(U)0ŠDC.B‚PRINT_LOOK-JMPBASE�$56�--�Print�as�is.‚(V)0ŠDC.B‚PRINT_LOOK-JMPBASE�$57�--�Print�as�is.‚(W)0ŠDC.B‚PRINT_LOOK-JMPBASE�$58�--�Print�as�is.‚(X)0ŠDC.B‚PRINT_LOOK-JMPBASE�$59�--�Print�as�is.‚(Y)0ŠDC.B‚PRINT_LOOK-JMPBASE�$5A�--�Print�as�is.‚(Z)0ŠDC.B‚PRINT_LOOK-JMPBASE�$5B�--�Print�as�is.‚([)0ŠDC.B‚PRINT_LOOK-JMPBASE�$5C�--�Print�as�is.‚(\)0ŠDC.B‚PRINT_LOOK-JMPBASE�$5D�--�Print�as�is.‚(])0ŠDC.B‚PRINT_LOOK-JMPBASE�$5E�--�Print�as�is.‚(^)0ŠDC.B‚PRINT_LOOK-JMPBASE�$5F�--�Print�as�is.‚(_)ŠPAGE***************7*‚$60�-�$7F‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------0ŠDC.B‚PRINT_LOOK-JMPBASE�$60�--�Print�as�is.‚(`)0ŠDC.B‚PRINT_LOOK-JMPBASE�$61�--�Print�as�is.‚(a)0ŠDC.B‚PRINT_LOOK-JMPBASE�$62�--�Print�as�is.‚(b)0ŠDC.B‚PRINT_LOOK-JMPBASE�$63�--�Print�as�is.‚(c)0ŠDC.B‚PRINT_LOOK-JMPBASE�$64�--�Print�as�is.‚(d)0ŠDC.B‚PRINT_LOOK-JMPBASE�$65�--�Print�as�is.‚(e)0ŠDC.B‚PRINT_LOOK-JMPBASE�$66�--�Print�as�is.‚(f)0ŠDC.B‚PRINT_LOOK-JMPBASE�$67�--�Print�as�is.‚(g)0ŠDC.B‚PRINT_LOOK-JMPBASE�$68�--�Print�as�is.‚(h)0ŠDC.B‚PRINT_LOOK-JMPBASE�$69�--�Print�as�is.‚(i)0ŠDC.B‚PRINT_LOOK-JMPBASE�$6A�--�Print�as�is.‚(j)0ŠDC.B‚PRINT_LOOK-JMPBASE�$6B�--�Print�as�is.‚(k)0ŠDC.B‚PRINT_LOOK-JMPBASE�$6C�--�Print�as�is.‚(l)0ŠDC.B‚PRINT_LOOK-JMPBASE�$6D�--�Print�as�is.‚(m)0ŠDC.B‚PRINT_LOOK-JMPBASE�$6E�--�Print�as�is.‚(n)0ŠDC.B‚PRINT_LOOK-JMPBASE�$6F�--�Print�as�is.‚(o)0ŠDC.B‚PRINT_LOOK-JMPBASE�$70�--�Print�as�is.‚(p)0ŠDC.B‚PRINT_LOOK-JMPBASE�$71�--�Print�as�is.‚(q)0ŠDC.B‚PRINT_LOOK-JMPBASE�$72�--�Print�as�is.‚(r)0ŠDC.B‚PRINT_LOOK-JMPBASE�$73�--�Print�as�is.‚(s)0ŠDC.B‚PRINT_LOOK-JMPBASE�$74�--�Print�as�is.‚(t)0ŠDC.B‚PRINT_LOOK-JMPBASE�$75�--�Print�as�is.‚(u)0ŠDC.B‚PRINT_LOOK-JMPBASE�$76�--�Print�as�is.‚(v)0ŠDC.B‚PRINT_LOOK-JMPBASE�$77�--�Print�as�is.‚(w)0ŠDC.B‚PRINT_LOOK-JMPBASE�$78�--�Print�as�is.‚(x)0ŠDC.B‚PRINT_LOOK-JMPBASE�$79�--�Print�as�is.‚(y)0ŠDC.B‚PRINT_LOOK-JMPBASE�$7A�--�Print�as�is.‚(z)0ŠDC.B‚PRINT_LOOK-JMPBASE�$7B�--�Print�as�is.‚({)0ŠDC.B‚PRINT_LOOK-JMPBASE�$7C�--�Print�as�is.‚(|)0ŠDC.B‚PRINT_LOOK-JMPBASE�$7D�--�Print�as�is.‚(})0ŠDC.B‚PRINT_LOOK-JMPBASE�$7E�--�Print�as�is.‚(~)7ŠDC.BƒDO_DEL-JMPBASE…$7F�--�Special�handling�for�(DEL).ŠPAGE************3 ***7*‚$80�-�$9F‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------&ŠDC.BƒIGNORE-JMPBASE…$80�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$81�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$82�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$83�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$84�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$85�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$86�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$87�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$88�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$89�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$8A�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$8B�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$8C�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$8D�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$8E�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$8F�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$90�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$91�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$92�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$93�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$94�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$95�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$96�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$97�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$98�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$99�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$9A�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$9B�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$9C�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$9D�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$9E�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$9F�--�Ignore�it.ŠPAGE***************7*‚$A0�-�$BF‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------9ŠDC.BƒTERMINATE-JMPBASE‚$A0�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A1�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A2�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A3�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A4�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A5�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A6�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A7�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A8�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$A9�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$AA�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$AB�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$AC�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$AD�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$AE�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$AF�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B0�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B1�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B2�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B3�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B4�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B5�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B6�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B7�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B8�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$B9�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$BA�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$BB�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$BC�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$BD�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$BE�--�Function�key:�send�packet.9ŠDC.BƒTERMINATE-JMPBASE‚$BF�--�Function�key:�send�packet.ŠPAGE***************7*‚$C0�-�$DF‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------=ŠDC.BƒPRINT_TERM-JMPBASE�$C0�--�Print�and�send�packet.‚(HOME)BŠDC.BƒPRINT_TERM-JMPBASE�$C1�--�Print�and�send�packet.‚(CURSOR�UP)DŠDC.BƒPRINT_TERM-JMPBASE�$C2�--�Print�and�send�packet.�(CURSOR�DOWN)5ŠDC.BƒPRINT-JMPBASE†$C3�--�Print�as�is.‚(CURSOR�LEFT)6ŠDC.BƒPRINT-JMPBASE†$C4�--�Print�as�is.‚(CURSOR�RIGHT)&ŠDC.BƒIGNORE-JMPBASE…$C5�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$C6�--�Ignore�it.&ŠDC.BƒIG3 NORE-JMPBASE…$C7�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$C8�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$C9�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$CA�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$CB�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$CC�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$CD�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$CE�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$CF�--�Ignore�it.DŠDC.BƒPRINT_CHANGE-JMPBASE�$D0�--�Print�&�change.�(CHARACTER�INSERT)DŠDC.BƒPRINT_CHANGE-JMPBASE�$D1�--�Print�&�change.�(CHARACTER�DELETE)&ŠDC.BƒIGNORE-JMPBASE…$D2�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$D3�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$D4�--�Ignore�it.BŠDC.BƒERASE_LINE-JMPBASE�$D5�--�Special�handling�for�(ERASE�LINE).DŠDC.BƒPRINT_TERM-JMPBASE�$D6�--�Print�and�send�packet.�(LINE�INSERT)DŠDC.BƒPRINT_TERM-JMPBASE�$D7�--�Print�and�send�packet.�(LINE�DELETE)&ŠDC.BƒIGNORE-JMPBASE…$D8�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$D9�--�Ignore�it.5ŠDC.BƒPRINT-JMPBASE†$DA�--�Print�as�is.‚(FORWARD�TAB)6ŠDC.BƒPRINT-JMPBASE†$DB�--�Print�as�is.‚(BACKWARD�TAB)&ŠDC.BƒIGNORE-JMPBASE…$DC�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$DD�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$DE�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$DF�--�Ignore�it.ŠPAGE***************7*‚$E0�-�$FF‚*ƒRoutine�offsetˆCharƒDescription�of�actionF***************ƒ----------------†----ƒ--------------------------------&ŠDC.BƒIGNORE-JMPBASE…$E0�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E1�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E2�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E3�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E4�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E5�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E6�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E7�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E8�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$E9�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$EA�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$EB�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$EC�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$ED�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$EE�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$EF�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F0�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F1�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F2�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F3�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F4�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F5�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F6�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F7�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F8�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$F9�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$FA�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$FB�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$FC�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$FD�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$FE�--�Ignore�it.&ŠDC.BƒIGNORE-JMPBASE…$FF�--�Ignore�it.ŠPAGEO*v*****************************************************************************O**********************************************************************************É***7***�GET_CURSOR_ADDRESS�--�RETURNS�ADDRESS�OF�CURSOR�******É***=***†FUNCTION:‚This�routine�returns�the�address�of�the�CRT�***?***‰controller�cursor,�relative�to�the�base�of�the�RAM�used‰***C***‰to�hold�the�characters�to�be�displayed�(called�screen�RAM).…******É******†NOTES:½******É******É***E***†REGISTER�USAGE:‚(A)rgument‚(D)estroyed‚(P)reserved‚(R)eturned‚***)***Œ0ƒ1ƒ2ƒ3ƒ4ƒ5ƒ6ƒ7‡SR�hi„SR�lo�(CCR)…******‡D:ƒRƒ.ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.‡.ˆD�******‡A:ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.ƒ. ******É******†ENTRY�CONDITIONS:²******É***-***†EXIT�CONDITIONS�DIFFERENT�FROM�ENTRY:ž***@***‰D0.L�=�the�address�of�the�cursor�relative�to�screen�RAM.ˆ******É***O*^*****************************************************************************O******************************************************************************* GET_CURSOR_ADDRESS: !ŠMOVEQ‚#0,D0ŽD0�<--�$00�00�00�00. 9ŠMOVE.B�#$0E,CRTCADD‡D0�<--�$00�00�hh�00,�where�hh�is�the7ŠMOVE.B�CRTCREG,D0‰high�address�byte�taken�from�the�CRTŠLSL„#8,D0Žcontroller. 9ŠMOVE.B�#$0F,CRTCADD‡D0�<--�$00�00�hh�ll,�where�ll�is�the<ŠMOVE.B�CRTCREG,D0‰low�address�byte�from�the�CRT�controller. 4ŠADD.L‚D0,D0ŽConvert�from�char�address�to�byte�addr. ŠRTS—Return.ŠPAGEO*v****************************4 ****************************************************;***…CODE�TO�PERFORM�ACTIONS�FOR�CHAR'S�ENTERED�IN�EDIT�MODE*** ***…FUNCTION:F***‡Except�for�DUPLICATE,�these�are�all�routines�specified�in�EDIT_TBLC***‡for�the�handling�of�incoming�characters�in�edit�mode.‚DUPLICATEE***‡is�different�in�that�it�is�checked�for�separately�since�it�is�notE***‡known�at�assembly�time�which�character�will�be�the�DUPLICATE�char)***‡(and�the�EDIT_TBL�should�be�ROMable).****** ***…NOTES:*********…ENTRY�CONDITIONS:***‡D0.B�=�the�char�entered."***‡A5ƒ=�address�of�TERMDRV's�CCB.***O*^*****************************************************************************  **********6*‚Duplicate�on�this�line�the�char�from�the�line�above.* DUPLICATE:=ŠMOVE.L�S.LINE(PC),D0†If�we're�on�the�top�line�(start�of�this=ŠCMP.L‚S.SCRN(PC),D0†line�=�start�of�screen),�just�ignore�theŠBEQ.L‚IGNORE�DUPLICATE�char. =ŠBSR„GET_CURSOR_ADDRESS�We're�not�on�the�top�line,�so�get�the6ŠADD.L‚#SCREEN,D0‰address�of�the�cursor�in�screen�RAM.?ŠSUB.L‚BPERLINE(PC),D0„A0�<--�addr�of�the�character�above�this.ŠMOVE.L�D0,A0Ž*4ŠMOVEQ‚#$7F,D0ŒD0.B�<--�the�char�there�(bits�0�-�6).ŠAND„(A0),D0Œ*-ŠBRA„PRINT_LOOKˆGo�act�like�he�typed�that�in.  *J*‚JMPBASE�is�used�in�constructing�the�table�EDIT_TBL.‚The�table�designatesM*‚the�routine�to�be�executed�for�a�given�char�by�storing�the�routine's�offsetH*‚from�JMPBASE.‚Since�the�offset�is�treated�as�an�unsigned�8-bit�number,?*‚the�routine�entry�points�must�all�be�fairly�close�to�JMPBASE.* JMPBASEƒEQU„*  **********&*‚Move�the�cursor�down�with�page�wrap.*DO_LF:>ŠMOVEQI�DOWNARROW,D0‡Translate�the�LF�to�a�DOWNARROW�so�we�get)*£page�wrap�and�fall�through�to�print�it.  ********** *‚Output�the�char�and�terminate.* PRINT_TERM:2ŠBSR.L‚MAKE_PACKETˆConstruct�a�termination�packet. ŠOUTPUT_D0‘Output�the�character.&ŠBRA.L‚SEND_PACKETˆGo�send�the�packet.  ***********‚Just�terminate.* TERMINATE:5ŠBSR.L‚MAKE_PACKETˆConstruct�a�termination�packet�andŠBRA.L‚SEND_PACKETˆgo�send�it.  **********"*‚Erase�the�line�the�cursor�is�on.* ERASE_LINE:0ŠOUTPUT�CR‘Go�back�to�the�beginning�of�the�line.'ŠOUTPUT�ERASE_EOLŠErase�to�end�of�line.3ŠBRA„CHANGE_EXITˆMark�change�to�this�line�and�exit.  **********,*‚Delete�the�char�to�the�left�of�the�cursor.*DO_DEL:BŠBSR„GET_CURSOR_ADDRESS�If�we're�not�on�the�1st�column�of�the�line9ŠADD.L‚#SCREEN,D0‰(cursor�addr�<>�start�of�current�line),ŠIF.L�D0��S.LINE(PC)�THEN#ŠOUTPUT�BS‘output�a�backspace�char.ŠENDI–* 6ŠOUTPUT�SPACEŽOutput�a�space�char�and�a�backspace�char/ŠOUTPUT�BS‘to�delete�the�char�under�the�cursor. >CHANGE_EXIT:�ST‚CHANGEDŒMark�that�we�changed�something�on�thisŠBRA„EXIT�line�and�exit.  **********@*‚Output�the�char�and�fake�a�CR�if�we�wrapped�around�the�screen.* PRINT_LOOK:(ŠST…CHANGEDŒMark�change�to�this�line�andŠOUTPUT_D0‘output�the�char.DŠBSR.L‚GET_CURSOR_ADDRESS�If�we're�not�on�the�1st�column�of�the�line<ŠADD.L‚#SCREEN,D0‰(cursor�address�<>�start�of�current�line),ŠCMP.L‚S.LINE(PC),D0†*ŠBNE„EXIT�just�exit. :ŠOUTPUT�UPARROWŒWe�wrapped,�so�move�us�back�to�the�line�we,ŠBRA„DO_CRŽwere�on�and�act�like�he�hit�a�CR.  **********D*‚Mark�that�the�line�was�changed�and�fall�through�to�PRINT�and�EXIT.* PRINT_CHANGE: ŠST…CHANGED  **********0*‚Just�output�the�char�and�fall�through�to�EXIT.*PRINT: ŠOUTPUT_D0  **********1*‚Just�ignore�this�char�and�return�from�EDITMODE.*IGNORE:5EXIT:…RESTORE�D0/D1/A0/A1‡Restore�registers�and�exit.ŠRTS—*  ***********‚Do�a�CR�LF�sequence.*DO_CR:.ŠBSR„MAKE_PACKETˆPrepare�a�termination�packet. >ŠMOVE.L�E.LINE(PC),D0†If�we're�on�the�last�line�of�the�virtualHˆIF.L�D0��E.SCRN(PC)�THEN�screen�(end�of�this�line�=�end�of�screen),9ŠMOVE.B�#$D9,PKT_TERM†put�a�$D9�terminator�in�the�packet,(ŠELSE–Else�(we're�not�on�the�last�line),9ŠMOVE.B�#$DF,PKT_TERM†put�a�$DF�terminator�in�the�packet,ŠENDI–* 4 ŠOUTPUT�CR‘Output�a�CR,�LF. ŠOUTPUT�LF‘* &ŠBRA.L‚SEND_PACKETˆGo�send�the�packet.  ************ 07 = CTRL G = BELL*�ADDED‚01/30/85*8* RING_BELL flag is set so that the interrupt routine in9* KEYBRD.AG will output an ALARM command to the keyboard.*BELL: ŠSTˆRING_BELL ŠBRA‡EXITŠPAGEO*v*****************************************************************************O**********************************************************************************É***3***ŽMAKE_PACKET�--�PREPARE�A�TERMINATION�PACKET�******É***@***†FUNCTION:‚When�a�key�is�struck�which�necessitates�that�aŠ***@***‰packet�be�sent�to�the�driver,�this�routine�is�called.‚It‡***C***‰will�prepare�a�packet,�including�data�if�there�was�a�change…***D***‰on�the�line,�and�set�up�the�variables�for�the�FEEDER�routine„******‰to�send�it�later.¯******É******†NOTES:½******É******É******É***E***†REGISTER�USAGE:‚(A)rgument‚(D)estroyed‚(P)reserved‚(R)eturned‚***)***Œ0ƒ1ƒ2ƒ3ƒ4ƒ5ƒ6ƒ7‡SR�hi„SR�lo�(CCR)…******‡D:ƒAP‚.ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.‡.ˆD�******‡A:ƒPƒPƒ.ƒ.ƒ.ƒ.ƒ.ƒP ******É******†ENTRY�CONDITIONS:²***)***‰D0.B�=�the�terminating�character.Ÿ******É***-***†EXIT�CONDITIONS�DIFFERENT�FROM�ENTRY:ž******É******É***O*^*****************************************************************************O******************************************************************************* MAKE_PACKET: .ŠSAVEƒD0/A0/A1‹Save�registers�we'll�blow�away.ŠST…KB_LOCKŒLock�the�keyboard. **‚Construct�the�packet�header.*4ŠLEA„PKT_CFLAG,A1‡A1�<--�address�of�start�of�packet.0ŠST…(A1)+ŽSet�the�change�flag�to�$FF�(no�change)%*§for�now.‚We�may�overwrite�it�later.4ŠMOVE.B�D0,(A1)+‹Put�the�terminating�char�out�there. DŠBSR.L‚GET_CURSOR_ADDRESS�D0�<--�cursor�addr�relative�to�screen�RAM.BŠDIVUƒBPERLINE+2(PC),D0‚D0�<--�$00�xx�00�rr;�rr=line,�xx=2*column.9ŠADD.B‚#$20,D0ŒConvert�to�ASCII�and�put�it�in�the�buffer.ŠMOVE.B�D0,(A1)+‹*ŠSWAPƒD0‘D0.B�<--�column�#. ŠLSR„#1,D0Ž*9ŠADD.B‚#$20,D0ŒConvert�to�ASCII�and�put�it�in�the�buffer.ŠMOVE.B�D0,(A1)+‹* *B*‚If�we�changed�anything�on�this�line,�add�the�data�to�the�packet.*,ŠTST.B‚CHANGEDŒIf�the�line�has�been�changed,ŠIF…�THENŠ* 1ŠSF…CHANGEDŒReset�the�CHANGED�flag�for�next�time. >ŠMOVE.B�PKT_LINE,PKT_CFLAG�Move�the�line�#�to�the�change�flag. *1*‚Move�the�line�from�screen�RAM�to�packet�buffer.*@ŠMOVE.L�S.LINE(PC),A0†A0�<--�addr�of�current�line�in�screen�RAM.DŠMOVEƒC.LINE(PC),D0�D0�<--�#�of�char's�per�line�(adjusted�for�DBRA). AFILL_LOOP�MOVEQ‚#$7F,D1ŒGet�the�next�char�from�screen�RAM�and�and)ŠAND„(A0)+,D1‹off�all�but�the�low�7�bits.0ŠMOVE.B�D1,(A1)+‹Put�that�value�into�the�packet.;ŠDBRAƒD0,FILL_LOOP‡Keep�going�until�the�full�line�is�moved. *!*‚Get�rid�of�the�trailing�blanks.*DŠMOVEƒC.LINE(PC),D0�D0�<--�#�of�char's�per�line�(adjusted�for�DBRA)..ŠMOVEQ‚#SPACE,D1ŠD1�<--�space�char�for�search. >TRAIL_LOOP�CMP.B�-(A1),D1‹Search�backward�through�the�packet's2ŠDBNEƒD0,TRAIL_LOOP†data�area�for�a�nonblank�char.2ŠADD.L‚#1,A1ŽA1�<--�address�of�the�following�char. ŠENDI *5*‚Finish�up�the�packet,�prepare�the�feeder,�and�exit.*BŠMOVE.B�#END_OF_DATA,(A1)‚Add�the�end-of-data�indicator�to�packet. 5ŠLEA„PACKET,A0ŠSet�feeder�address�to�start�of�packet.ŠMOVE.L�A0,FEEDER_ADDRESS‚*5ŠSUB.L‚A0,A1ŽSet�feeder�count�to�#�of�bytes�in�packet)ŠADD„#1,A1Ž*†=‚end�addr�-�start�addr�+�1.ŠMOVEƒA1,FEEDER_COUNT„* -ŠRESTORE�D0/A0/A1ŠRestore�registers�and�exit.ŠRTSŠPAGEO*v********************************************************************************5***†SEND_PACKET�--�SEND�TERMINATION�PACKET�TO�TERMDRV***F***†FUNCTION:‚This�code�sends�the�termination�packet,�already�preparedC***‰in�the�buffer�PACKET,�to�the�driver�TERMDRV.‚Before�doing�so�itB***‰stores�the�current�cursor�line�#�in�the�packet.‚FEEDER_ADDRESS)***‰and�FEEDER_COUNT�must�already�be�set.*** ***†NOTES:*********†ENTRY�CONDITIONS:"***‰A5�=�address�of�TERMDRV's�CCB.***O*^************5 ***************************************************************** SEND_PACKET: BŠBSR„GET_CURSOR_ADDRESS�D0�<--�cursor�addr�relative�to�screen�RAM.AŠDIVUƒBPERLINE+2(PC),D0‚D0�<--�$xx�xx�00�rr.‚rr=line�#,�xx=trash.9ŠADD.B‚#$20,D0ŒConvert�to�ASCII�and�put�it�in�the�packet.ŠMOVE.B�D0,PKT_LINEˆ* 8ŠBSR.L‚FEEDER�Call�the�feeder�to�give�this�to�the�driverŠBRA„EXIT�and�exit.   ŠENDé>FEEDER„IDNTƒ1,0„VME/10�subroutine�to�feed�a�buffer�to�TERMDRV.O*v*****************************************************************************O*******************************************************************************O**********************************************************************************É***4***†FILENAME:‚FEEDER�--�FEED�A�BUFFER�TO�TERMDRV–******É***8***†ENVIRONMENT:‚Linked�into�TERMDRV�for�the�VME/10.’******É***G***†FUNCTION:‚TERMDRV�basically�only�accepts�a�character�at�a�time.ƒ***D***‰If�you�have�a�buffer�full�of�characters�to�send,�you�can�use„***=***‰this�routine�to�give�them,�one�at�a�time,�to�TERMDRV.‹******É***E***†NOTES:‚When�control�is�returned�to�the�caller,�the�buffer�has…***@***‰not�necessarily�been�completely�sent.‚No�notification�is‡***;***‰provided�to�indicate�that�the�buffer�has�been�sent.�******É***,***†EXTERNAL�DATA�STRUCTURES�REFERENCED:Ÿ*** ***‰CCB�for�terminal�driver.¨******É***)***†EXTERNAL�ENTRY�POINTS�REFERENCED:¢******‰GOT_CHAR¸******É***"***†SERVICES�CALLED�VIA�TRAPS:©******É***O*******************************************************************************O*******************************************************************************O*^***************************************************************************** *,*‚Revision�history�(add�new�changes�to�top).*…Date†Author‰ChangesG*…--------‚-------------‚----------------------------------------------'*†7/19/83‚Steve�FranckƒInitial�writing.*ŠPAGE* *‚XDEF's.*6ŠXDEFƒSTOP_ITŒEntry�pt.�for�background�routine�to�stop'*§us�from�trying�to�feed�more�char's�to *§the�driver.6ŠXDEFƒUNSTOP�Entry�pt.�for�us�to�resume�feeding�char's"*§to�the�driver�if�we�had�stopped.6ŠXDEFƒFEEDER�Entry�pt.�for�routine�that�feeds�a�buffer!*§a�byte�at�a�time�to�the�driver.?ŠXDEFƒFEEDER_ADDRESS,FEEDER_COUNT,FEEDER_WAITING‚Variables�used%*§in�dealing�with�the�feeder�routine.>ŠXDEFƒREL_FLAG,REL_ADDR,REL_PAGES‚Variables�to�use�if�you�want›1¤C¬:´<¼/&*§FEEDER�to�release�memory�to�the�exec*§when�it�is�done�feeding.   *0*‚XREF's�(indicate�where�the�XDEF�is,�if�known).*6ŠXREFƒGOT_CHAR‹Entry�pt.�in�TERMDRV�to�process�a�char.ŠPAGEO*********************************************************************************‰INCLUDE�FILES�AND�EQUATES*O******************************************************************************* *=*‚Define�the�environment�as�EXORMACS/S�in�a�switch�to�control*‚conditional�assemblies.*2ENVIRONMENT�EQU‚'EX/S'�This�is�for�the�EXORMACS/S.  **‚Include�files:5*‰UTILITY.MC‹General�purpose�macros�(e.g.�PUSH,�POP).,*‰IOE.SA�Equates�for�IOS-related�structures.7*‰EQUCCB.EQŒEquates�for�device-independent�part�of�CCB.9*‰TERMDRV.EQ‹Equates�for�the�generalized�terminal�driver.(*‰STR.EQ�Equates�for�trap�#0�calls,�etc.*ŠNOLISTŠINCLUDE‚9995.&.UTILITY.MCŠINCLUDE‚9995.&.IOE.EQŠINCLUDE‚9995.&.CCB.EQŠINCLUDE‚9995.VMES10.TERMDRV.EQŠINCLUDE‚9995.&.STR.EQŠLIST  .FALSE…5 EQU„$00�Value�FALSE�for�a�flag�variable.,TRUE†EQU„$FF�Value�TRUE‚for�a�flag�variable.ŠPAGEO*********************************************************************************‰DATA�VARIABLES*O******************************************************************************* ŠSECTION�0 *I*‚These�variables�are�used�as�arguments�to�the�FEEDER�routine�which�gives-*‚bytes�in�a�buffer�one�at�a�time�to�TERMDRV.*@FEEDER_ADDRESS�DC.L�0�Address�of�next�byte�for�feeder�subroutine*§to�feed�to�the�driver.;FEEDER_COUNT�DC.W�0‘#�of�bytes�remaining�to�feed�to�driver.CFEEDER_WAITING�DC.B�FALSE‹Flag�indicating�whether�or�not�the�feeder$*§is�waiting�for�room�in�the�receive"*§queue.‚Used�by�UNSTOP�routine�to'*§restart�the�feeder�if�it�had�to�stop. =REL_FLAG‚DC.BƒFALSEŽFlag�indicating�whether�or�not�the�feeder(*§should�release�memory�to�the�exec�when)*§it�is�done�feeding�a�buffer�to�TERMDRV.4REL_ADDR‚DC.Lƒ0’Start�addr�of�buffer�to�be�released.5REL_PAGES�DC.Lƒ0’#�of�pages�in�buffer�to�be�released.ŠPAGEO*v*****************************************************************************O**********************************************************************************É***4***�FEEDER�--�FEEDS�A�BUFFER�BYTEWISE�TO�TERMDRV�******É***G***†FUNCTION:‚This�routine,�whose�entry�point�is�XDEF'ed,�will�takeƒ***@***ˆthe�buffer�described�by�the�variables�FEEDER_ADDRESS�and‰***E***ˆFEEDER_COUNT�and�transfer�it�a�byte�at�a�time�to�the�terminal„***C***ˆdriver,�TERMDRV.‚It�senses�when�the�STOPPED�flag�in�the�CCB…***G***ˆgets�set,�which�means�that�the�driver's�receive�queue�is�almost‚***A***ˆfull,�and�stops�sending.‚Provisions�must�be�made�for�this‡***C***ˆroutine�to�be�invoked�again�later�when�there�is�room�in�the†******ˆreceive�queue.³******É******†NOTES:½******É******É***E***†REGISTER�USAGE:‚(A)rgument‚(D)estroyed‚(P)reserved‚(R)eturned‚***)***Œ0ƒ1ƒ2ƒ3ƒ4ƒ5ƒ6ƒ7‡SR�hi„SR�lo�(CCR)…******‡D:ƒPƒPƒ.ƒ.ƒ.ƒ.ƒ.ƒ.‡.ˆD�******‡A:ƒPƒPƒ.ƒ.ƒPƒAƒ.ƒP ******É******†ENTRY�CONDITIONS:²***&***ˆA5ƒ=�address�of�TERMDRV's�CCB.¡******É***-***†EXIT�CONDITIONS�DIFFERENT�FROM�ENTRY:ž******É******É***O*^*****************************************************************************O******************************************************************************* ŠDS…0ŠOPT„BRS ŠSECTION�0 FEEDER: ;ŠSAVEƒD0/D1/A0/A1/A4…Save�registers�we,�or�the�driver,�use.AŠMOVE.L�FEEDER_ADDRESS,A4‚A4�<--�addr�of�1st�byte�to�feed�driver.  ŠREPEAT ;ŠSUB„#1,FEEDER_COUNT„Decrement�the�count�of�bytes�remaining$ŠBMI„DONE�and�get�out�if�we're�done. -ŠMOVE.B�(A4)+,D0‹D0�<--�next�byte�for�driver.5ŠPEA„RETURN(PC)‰Call�the�driver�at�the�point�where�he6ŠPUSH.L�D1‘has�the�character�and�starts�to�process�it.ŠBRA.L‚GOT_CHAR‹* @RETURN„TST.B‚STOPPED(A5)ˆHaving�returned�from�the�driver,�see�if-ŠUNTIL‚�he's�full�and�repeat�if�he's�not.  *D*‚The�driver�can't�take�any�more�characters�now,�so�we�have�to�exit.*@ŠMOVE.L�A4,FEEDER_ADDRESS‚Save�address�of�next�byte�to�feed�him.6ŠST…FEEDER_WAITING…Remind�someone�that�we're�not�done. 4ŠBRA„EXIT�Just�exit�for�now;�we'll�get�called�later.  *H*‚The�buffer�has�been�fed�to�the�driver.‚Release�the�buffer�if�necessary *‚and�exit.*:DONE†TST.B‚REL_FLAG‹If�we're�supposed�to�release�a�buffer,ŠIF…�THENŠ* 7ŠSAVEƒD2-D7/A2-A3/A5…Save�rest�of�registers,�except�A6.;ŠMOVE.L�REL_ADDR,A0ˆA0�<--�start�addr�of�buffer�to�release.1ŠMOVE.L�REL_PAGES,D1‡D1�<--�#�of�pages�in�buffer.(ŠTR0$.PGFR�,�Ask�exec�to�free�the�pages.ŠBRA„RELEASED‹Good�return.*ŠTR0$.KILLER�Bad�return--crash�the�system. �THENŠof�his�work�(this�should�be�the�case),)ŠBSR„FEEDER�call�him�to�let�him�continue.ŠENDI–* ŠRTS—Return.     ŠENDééHINCHAR„IDNTƒ1,0‚Routine�to�get�incoming�char's�and�handle�special�modes.O*v*****************************************************************************O*******************************************************************************O**********************************************************************************É***I***…FILENAME:�INCHAR�--�GET�INCOMING�CHAR'S�AND�HANDLE�SPECIAL�MODES.ƒ******É***K***…ENVIRONMENT:�Part�of�VERSAdos�keyboard/screen�driver�for�the�VME/10.******É***G***…FUNCTION:�The�subroutine�in�this�module�is�called�by�TERMDRV�to…***#***‡handle�incoming�characters.§******É******…NOTES:¾******É***,***…EXTERNAL�DATA�STRUCTURES�REFERENCED: *******‡EDIT_FLAG„KB_LOCK„PAGEFLAG„PROMODE—******É***)***…EXTERNAL�ENTRY�POINTS�REFERENCED:£***"***‡GET_CHAR…EDITMODE…PAGEMODE ******É***"***…SERVICES�CALLED�VIA�TRAPS:ª******É******É***O*******************************************************************************O******************************************6 *************************************O*^***************************************************************************** *,*‚Revision�history�(add�new�changes�to�top).*…Date†Author‰ChangesG*…--------‚-------------‚----------------------------------------------'*†5/23/83‚Steve�FranckƒInitial�writing.* * *‚XDEF's.*+ŠXDEFƒIN_CHARŒEntry�point�for�this�routine. *0*‚XREF's�(indicate�where�the�XDEF�is,�if�known).*2ŠXREFƒGET_CHAR‹Routine�to�get�a�scan�code�from�the&*§keyboard�and�generate�a�char,�update"*§modes,�etc.;�in�module�KEYBOARD. 7ŠXREFƒEDITMODE‹Routine�to�handle�incoming�characters�if*§we're�in�edit�mode. 8ŠXREFƒEDIT_FLAGŠFlag�indicating�whether�or�not�we�are�in *§edit�mode;�in�module�EDITMODE. 7ŠXREFƒPAGEMODE‹Routine�to�handle�incoming�characters�if%*§we're�in�page�mode�or�protect�mode. 7ŠXREFƒPAGEFLAG‹Flag�indicating�whether�or�not�we�are�in*§page�mode;�in�module�CRTINIT. 6ŠXREFƒPROMODEŒFlag�indicating�whether�or�not�we�are�inÄ;Í@Õ*!*§protect�mode;�in�module�OUTCHS. 9ŠXREFƒKB_LOCKŒFlag�indicating�whether�or�not�the�keyboard'*§is�'software�locked,'�meaning�that�no!*§characters�should�be�generated. **‚Equate�files�included:0*…UTILITY.MC„Utility�macros�(like�PUSH�and�POP).*ŠNOLISTŠINCLUDE�9995.&.UTILITY.MCŠLISTŠPAGEO*v*****************************************************************************O**********************************************************************************É***7***�IN_CHAR�--�HANDLE�CHAR�FROM�THE�VME/10�KEYBOARD�******É***H***…FUNCTION:�This�routine�is�called�by�TERMDRV,�the�keyboard�screen„***E***‡driver,�when�scan�codes�are�received�from�the�keyboard.‚After„***D***‡calling�GET_CHAR�to�figure�out�what�the�char�is,�EDITMODE�is†***D***‡called�if�necessary.‚'Software�lock'�of�the�keyboard�is�also…*** ***‡handled�by�this�routine.ª******É******…NOTES:¾******É***E***…REGISTER�USAGE:‚(A)rgument‚(D)estroyed‚(P)reserved‚(R)eturnedƒ***)***Œ0ƒ1ƒ2ƒ3ƒ4ƒ5ƒ6ƒ7‡SR�hi„SR�lo�(CCR)…******‡D:ƒRƒPƒ.ƒ.ƒ.ƒ.ƒ.ƒ.‡.ˆR�******‡A:ƒ.ƒ.ƒ.ƒ.ƒ.ƒAƒ.ƒP ******É******…ENTRY�CONDITIONS:³***&***‡A5ƒ=�address�of�TERMDRV's�CCB.¢******É***-***…EXIT�CONDITIONS�DIFFERENT�FROM�ENTRY:Ÿ***I***‡CCR:��=�keystroke�didn't�generate�a�char�or�break�for�TERMDRV.***A***Œ:��=�generated�char�is�in�D0.W�(bits�8-15�are�0).„***%***’�=�a�break�was�generated.š***(***‡D0�is�not�preserved�in�any�case.¢******É***O*^*****************************************************************************O******************************************************************************* ŠDS…0 ŠSECTION�0ŠOPT„BRS IN_CHAR: (ŠSAVEƒD1‘Save�registers�we'll�blow�away. 0ŠBSR.L‚GET_CHAR‹Get�the�character�(or�whatever).'ŠIF…�THENŠIf�it�is�a�char�or�break, ŠIF…�THENŠ.�If�it's�a�break, "ŠSF…KB_LOCKŒ.ƒUnlock�the�keyboard; ŠELSE–.�Else�(it's�a�character), 4ŠTST.B‚KB_LOCKŒ.ƒIf�the�keyboard�is�software�locked,ŠIF…�THENŠ.ƒ* -ŠCLR„D0‘.…Set�CCR:��to�say�'false�alarm.' *ŠELSE–.ƒElse�(the�keyboard�is�not�locked), *ŠTST.B‚EDIT_FLAGŠ.…If�we�are�in�edit�mode,ŠIF…�THENŠ.…* 0ŠBSR.L‚EDITMODE‹.‡Call�the�edit�mode�handler�and-ŠCLR„D0‘.‡set�CCR:��to�say�'false�alarm.' 'ŠELSE–.…Else�(we�are�not�in�edit�mode), 8ŠMOVE.B�PAGEFLAG,D1ˆ.‡If�we�are�in�page�or�protect�mode,ŠOR.BƒPROMODE,D1‰.‡*ŠIF…�THENŠ.‡* 0ŠBSR.L‚PAGEMODE‹.‰Call�the�page�mode�handler;�he*±will�set�the�condition�codes. 'ŠELSE–.‡Else�(we�are�not�in�page�mode), /ŠMOVEQ‚#1,D1Ž.‰Set�CCR:�,�to�say�'there*±is�a�char�in�D0.' ŠENDI–. ŠENDI–. ŠENDI–. ŠENDI–. ŠENDI–.   7ŠRESTORE�D1�Restore�registers�and�return�with�condition7 ŠRTS—codes�set.   ŠENDéééé7OUTCHSƒIDNT†1,00†Output�a�character�to�the�display�RAM. <*************************************************************º**�Routine�name:ŽOUTCHS˜*<*----------------------------------------------------------*-*�Current�revision.....................1.00�*1*�Date�written.........................12-18-82Œ*2*�Written�by...........................S.Pri-Tal‹*/*�Date�changed.........................3-1-83Ž*2*�Changed�by...........................R.�RUSTAD‹**º**�Description�of�change:£**º**º*0*�Date�changed.........................8-17-84�*1*�Changed�by...........................B.�NASONŒ**º**�Description�of�change:£**ƒChanged�all�XREF.S�to�XREF�**º*0*�Date�changed........................10-24-84�*1*�Changed�by...........................B.�NASONŒ**º**�Description�of�change:£*5*‚System�was�hanging�when�SHIFT/CLEAR�was�hit�while‡*7*‚there�was�an�output‚to�the�screen.‚The�registers�A2ƒ*:*‚and�D6�were�not�being�set�up�in�CLEAR_SCREEN,�which�is‚*;*‚called�by�BREAK_CLEAR�in�GET_CHAR�in�the�KEYBOARD�module*,*‚So�now�we�set�up�the�registers�properly.�**º*0*�Date�changed.........................1-30-85�*/*�Changed�by...........................M.�DUHŽ**º**�Description�of�change:£*7*ƒSet�RING_BELL�flag�when�$07�is�to�be�output�(BELL).„**º**º*<************************************************************9*�Function:�Output�the�character�in�D0.B�to�the�display„*/*‹RAM�if�character�is�printable,�else�perform„**‹the�required�function.™*<*----------------------------------------------------------*/*�Input�parameters:‚D0.B�character�to�output.�*<*----------------------------------------------------------**�Registers�affected:�none¡*<*----------------------------------------------------------* *�External�routines�used:�none�*<************************************************************‰PAGE ‰XDEF†OUTCHS‰XDEF†EDIT_FLAG 4‰XDEF†RESET_SCREEN‚Alternate�entry�for�reset�command4‰XDEF†CLEAR_SCREEN‚Alternate�entry�for�clear�commandÝ7æ9î?öBþ-,-0+&T.a6O>QFSNDVA^BfSn:vU~J†SŽK–>žF¦K‰XDEF†PROMODE‡Protect�mode�flag )‰XDEF†RABSOLUT†Read�absolute�entry�point. (‰XREF†CRTINITƒInit�the�screen�parameters‰XREF†SCRNINIT /‰XREF†FACS†Field�attribute,�word�sized�register3‰XREF†PAGEFLAG‚Word�sized�flag.�If=$FFFF,�page�mode 5‰XREF†CPERLINE‚Number�of�characters�per�absolute�line0‰XREF†BPERLINE‚Number�of�bytes�per�absolute�line2‰XREF†LPERSCRN‚Number�of�lines�per�absolute�screen 2‰XREF†C.LINE„Number�of�characters�per�virtual�line-‰XREF†B.LINE„Number�of�bytes�per�virtual7 �line *‰XREF†S.LINE„Start�address�of�current�line(‰XREF†E.LINE„End�address�of�current�line *‰XREF†PB.LINEƒUnused�part�of�absolute�line 2‰XREF†L.SCRN„Number�of�lines�in�the�virtual�screen <‰XREF†S.SCRN„Address�of�home�character�in�the�virtual�screen<‰XREF†E.SCRN„Address�of�last�character�in�the�virtual�screen (‰XREF†TOPLINEƒTop�line�of�virtual�screen+‰XREF†BOTLINEƒBottom�line�of�virtual�screen,‰XREF†LEFTCOLƒLeft�collumn�of�virtual�screen.‰XREF†RIGHTCOL‚Right�collumn�of�virtual�screen 9‰XREF†FEEDER„Address�of�subroutine�to�give�data�to�driver=‰XREF†FEEDER_ADDRESS†Address�of�data�buffer�to�give�to�FEEDER,‰XREF†FEEDER_COUNTˆ#�of�bytes�in�data�bufferA‰XREF†REL_FLAG‚Flag�which�tells�feeder�subroutine�to�release�mem.7‰XREF†REL_ADDR‚Memory�address�of�buffer�to�be�released.*‰XREF†REL_PAGES�Number�of�pages�in�buffer.‰XREF†DUP_CHAR (‰XREF†KB_LOCK�Key�board�lock/unlock�flag.‰XREF†POUTCHS�Output�character�in�protect�mode 0‰XREF†RING_BELL‹Flag�set�when�$07�is�detected�in%*§order�to�ring�the�bell�in�KEYBRD.AG‰PAGE .SCREENƒEQU‡$F17000�Base�address�of�display�RAM0CRTCADD‚EQU‡$F1A021�Address�register�of�the�CRTC-CRTCREG‚EQU‡$F1A023�Register�file�of�the�CRTC)EPCIBASE�EQU‡$F1A031�Base�address�of�EPCIKBDADDR‚EQU‡$0C$LFCHARƒEQU‡$0A‘ASCII�line�feed�char.0START_OF_DATA�EQU‚$DDŽ'Start�of�data'�indicator./END_OF_DATA�EQU„$DE‘End�of�write/read�indicator,END_OF_FIELD�EQUƒ$F9‘End�of�field�indicator.$FALSE„EQU‡0“Indicate�condition�false#TRUE…EQU‡-1’Indicate�true�condition"CLEARTAB�EQU‡$18‘Clear�tab�command#SPACE„EQU‡$20ŽASCII�space�character#ESC_CHAR‚EQU„$1B�ASCII�escape�char.;NUMBER_PAGES�EQU‚8‘Number�of�pages�to�give�to�feeder�during*£a�read�absolute.6INIT_TAB‚EQU„10‘Initial�tab�spacing.‚The�reset�command#*§($F1)�will�put�tabs�on�the�screen*§with�this�spacing. ** Register use:*’D0.L�=�general�use+*’D1.W�=�absolute�address�of�initial�cursor/*’D2.W�=�chracter�to�decode�and�word�to�display)*’D3.W�=�lines�per�virtual�screen�counter+*’D4.W�=�characers�per�virtual�line�counter *’D5.L�=�bytes�per�absolute�line*’D6.L�=�bytes�per�virtual�line*’D7.L�=�general�use-*’A0.L�=�address�of�cursor�in�the�display�RAM*’A1.L�=�Address�of�FACS*’A2.L�=�Address�of�S.LINE*’A3.L�-�General�use*  ‰PAGE ‰SECTIONƒ11  **ˆDEFINE�STORAGE*=ESC_FLAG‚DC.BƒFALSEŽThis�flag�is�true�if�someone�has�reserved(*§a�char�and�the�first�char�received�was&*§an�ESC.‚In�that�case�we�wait�for�the*§next�char�and�set�its�bit�7.:CHAR_RESERVED�DC.B�FALSE…Next�character�reserved�indicator(SAVE_CHAR…DS.B�1‰Save�area�for�character:SAVE_CR1†DS.B�1‰Save�area�for�character‚These�are�used�for;SAVE_CR2†DS.B�1‰Save�area�for�character‚read�absolute�only.)SAVE_CR3†DS.B�1‰Save�area�for�character‚*-SAVE_CURSORƒDS.L�1‰Current�cursor�ram�addressBCHAR_OWNER„DS.L�1‰Address�of�routine�that�owns�next�incoming�char.4XTCHBUF‚DS.W†10ˆScratch�buffer�for�feeder�subroutineEDIT_FLAG�DC.B…FALSE‰DS.W†0,PROMODE‚DC.W†FALSE…Set�protect�mode�to�false=COL_CNT‚DS.L†1‰Current�column�number,�used�in�set�tab�routine‰DS.W†0;SAVEFACS�DC.W†0‰Save�FACS�in�use�when�write�absolute�occurs>LASTFAC‚DC.B†FALSE…Last�character�processed�--�indicates�if�it*œwas�a�FAC�or�not.�THEN.S 8ŠTST.B‚ESC_FLAG‹If�the�last�char�we�received�was�an�ESC,ŠIF…�THEN.Sˆ* 2ŠSF…ESC_FLAG‹Clear�the�'last�char�was�an�ESC'�flag5ŠBSETƒ#7,D0Žand�set�bit�7�in�D0�and�D2�(both�of�which-ŠBSETƒ#7,D2Žhold�the�char�following�the�ESC). (ŠELSE.S”Else�(last�char�was�not�an�ESC), 6ŠIF.B�D0��#ESC_CHAR�THEN.S�If�this�char�is�an�ESC,0ŠST…ESC_FLAG‹set�the�'last�char�was�an�ESC'�flagŠBRA„RETURN�and�exit.ŠENDI–* ŠENDI /‰SF�CHAR_RESERVEDŽReset�character�reserved�flag:‰MOVE.L�CHAR_OWNER,A3ŠGet�the�address�of�the�routine�which*¨process�this�character'‰JMP�(A3)–Go�process�incoming�character ‰ENDI *(*ˆFind�entry�in�table�for�this�character*OUTCH1(‰MOVE†D2,D0…Reset�upper�part�of�register5‰ADD‡D0,D0…Multiply�by�two�because�table�is�word�wide+‰MOVE†JUMPTABL(PC,D0),D0�Get�offset�address2‰JMP‡JUMPTABL(PC,D0)„Go�process�incoming�character‰PAGEJUMPTABL,ŠDC.WƒRETURN-JUMPTABL„$00�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$01�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$02�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$03�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$04�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$05�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$06�--�Illegal�--�exit ŠDC.WƒBELL-JUMPTABL†$07�--�Bell.#ŠDC.WƒBS-JUMPTABLˆ$08�--�Backspace.(ŠDC.WƒHT-JUMPTABLˆ$09�--�Horizontal�tab.#ŠDC.WƒLF-JUMPTABLˆ$0A�--�Line�feed.&ŠDC.WƒUP-JUMPTABLˆ$0B�--�Vertical�tab.&ŠDC.WƒRIGHT-JUMPTABL…$0C�--�Form�feed.)ŠDC.WƒCR-JUMPTABLˆ$0D�--�Carriage�return.,ŠDC.WƒRETURN-JUMPTABL„$0E�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$0F�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$10�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$11�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$12�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$13�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$14�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$15�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$16�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$17�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$18�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$19�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1A�--�Illegal�--�exit!ŠDC.WƒESC-JUMPTABL‡$1B�--�Escape.,ŠDC.WƒRETURN-JUMPTABL„$1C�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1D�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1E�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1F�--�Illegal�--�exit,ŠDC.WƒDISPLAY-JUMPTABLƒ$20�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$21�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$22�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$23�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$24�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$25�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$26�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$27�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$28�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$29�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$30�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$31�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$32�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$33�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$34�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$35�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$36�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$37�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$38�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$39�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3F�--�Display�as�is.,ŠDC.8 WƒDISPLAY-JUMPTABLƒ$40�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$41�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$42�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$43�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$44�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$45�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$46�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$47�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$48�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$49�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$50�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$51�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$52�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$53�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$54�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$55�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$56�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$57�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$58�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$59�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$60�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$61�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$62�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$63�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$64�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$65�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$66�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$67�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$68�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$69�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$70�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$71�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$72�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$73�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$74�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$75�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$76�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$77�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$78�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$79�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7E�--�Display�as�is.+ŠDC.WƒRETURN-JUMPTABL„$7F�--�Display�as�is.'ŠDC.WƒRETURN-JUMPTABL„$80�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$81�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$82�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$83�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$84�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$85�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$86�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$87�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$88�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$89�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8A�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8B�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8C�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8D�--�Ignore�it.4ŠDC.WƒSTART_EDITMODE-JUMPTABLƒ$8E�--�Start�edit�mode1ŠDC.WƒSTOP_EDITMODE-JUMPTABL„$8F�--�End�edit�mode'ŠDC.WƒRETURN-JUMPTABL„$90�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$91�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$92�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$93�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$94�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$95�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$96�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$97�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$98�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$99�9 --�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9A�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9B�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9C�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9D�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9E�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9F�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A0�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A1�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A2�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A3�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A4�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A5�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A6�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A7�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A8�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A9�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AA�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AB�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AC�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AD�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AE�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AF�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B0�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B1�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B2�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B3�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B4�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B5�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B6�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B7�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B8�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B9�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BA�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BB�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BC�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BD�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BE�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BF�--�Ignore�it.%ŠDC.WƒHOME-JUMPTABL†$C0�=�Cursor�home!ŠDC.WƒUP-JUMPTABLˆ$C1�=�Cursor�up%ŠDC.WƒDOWN-JUMPTABL†$C2�=�Cursor�down&ŠDC.WƒSEEKL-JUMPTABL…$C3�=�Cursor�left'ŠDC.WƒRIGHT-JUMPTABL…$C4�=�Cursor�right$ŠDC.WƒC5-JUMPTABLˆ$C5�=�Write�cursor#ŠDC.WƒC6-JUMPTABLˆ$C6�=�Read�cursor(ŠDC.WƒSPAGE-JUMPTABL…$C7�=�Set�page�mode*ŠDC.WƒRPAGE-JUMPTABL…$C8�=�Reset�page�mode0ŠDC.WƒSETTOP-JUMPTABL„$C9�=�Set�top�display�line5ŠDC.WƒSETBOTOM-JUMPTABL‚$CA�=�Set�bottom�display�line5ŠDC.WƒSETLEFT-JUMPTABLƒ$CB�=�Set�left�display�collumn7ŠDC.WƒSETRIGHT-JUMPTABL‚$CC�=�Set�right�display�collumn,ŠDC.WƒSETPRO-JUMPTABL„$CD�=�Set�protect�mode,ŠDC.WƒWABSOLUT-JUMPTABL‚$CE�=�Write�absolute+ŠDC.WƒRABSOLUT-JUMPTABL‚$CF�=�Read�absolute5ŠDC.WƒICHAR-JUMPTABL…$D0�=�Insert�character�at�cursor5ŠDC.WƒDCHAR-JUMPTABL…$D1�=�Delete�character�at�cursor,ŠDC.WƒKEYENAB-JUMPTABLƒ$D2�=�Enable�keyboard.ŠDC.WƒKEYDSABL-JUMPTABL‚$D3�=�Disable�keyboard?ŠDC.WƒEEPAGE-JUMPTABL„$D4�=�Erase�all�unprotected�to�end�of�pag?ŠDC.WƒEELINE-JUMPTABL„$D5�=�Erase�all�unprotected�to�end�of�lin5ŠDC.WƒINS_LINE-JUMPTABL‚$D6�=�Insert�a�line�at�cursor5ŠDC.WƒDEL_LINE-JUMPTABL‚$D7�=�Delete�a�line�at�cursor:ŠDC.WƒCLEAR-JUMPTABL…$D8�=�Erase�all�unprotected�in�screen5ŠDC.WƒRETURN-JUMPTABL„$D9�=�Send�page�to�line�printer'ŠDC.WƒSEEKFT-JUMPTABL„$DA�=�Forward�tab$ŠDC.WƒSEEKBT-JUMPTABL„$DB�=�Back�tab#ŠDC.WƒSETTAB-JUMPTABL„$DC�=�Set�tabŠDC.WƒRETURN-JUMPTABL„$DD�=ŠDC.WƒRETURN-JUMPTABL„$DE�=0ŠDC.WƒRETURN-JUMPTABL„$DF�=�Send�line�to�printer%ŠDC.WƒSBLINK-JUMPTABL„$E0�=�Set�blink'ŠDC.WƒRBLINK-JUMPTABL„$E1�=�Reset�blink-ŠDC.WƒSINVERT-JUMPTABLƒ$E2�=�Set�video�invert/ŠDC.WƒRINVERT-JUMPTABLƒ$E3�=�Reset�video�invert-ŠDC.WƒUPBRIGHT-JUMPTABL‚$E4�=�Set�half�bright/ŠDC.WƒDNBRIGHT-JUMPTABL‚$E5�=�Reset�half�bright)ŠDC.WƒSULINE-JUMPTABL„$E6�=�Set�underline+ŠDC.WƒRULINE-JUMPTABL„$E7�=�Reset�underline,ŠDC.WƒNONDISP-JUMPTABLƒ$E8�=�Set�non-display(ŠDC.WƒSETDISP-JUMPTABLƒ$E9�=�Set�display-ŠDC.WƒPROTECT-JUMPTABLƒ$EA�=�Set�protect�mode-ŠDC.WƒALLOW-JUMPTABL…$EB�=�Reset�protect�modeŠDC.WƒRETURN-JUMPTABL„$EC�=ŠDC.WƒRETURN-JUMPTABL„$ED�=ŠDC.WƒRETURN-JUMPTABL„$EE�=ŠDC.WƒRETURN-JUMPTABL„$EF�=ŠDC.WƒRETURN-JUMPTABL„$F0�=2ŠDC.WƒRESET24-JUMPTABLƒ$F1�=�Reset�24�line�screen.ŠDC.WƒRETURN-JUMPTABL„$F2�=ŠDC.WƒRETURN-JUMPTABL„$F3�=ŠDC.WƒRETURN-JUMPTABL„$F4�=ŠDC.WƒRETURN-JUMPTABL„$F5�=ŠDC.WƒRETURN-JUMPTABL„$F6�=2ŠDC.WƒRESET25-JUMPTA9 BLƒ$F7�=�Reset�25�line�screen.ŠDC.WƒRETURN-JUMPTABL„$F8�=ŠDC.WƒRETURN-JUMPTABL„$F9�=ŠDC.WƒRETURN-JUMPTABL„$FA�=ŠDC.WƒRETURN-JUMPTABL„$FB�=ŠDC.WƒRETURN-JUMPTABL„$FC�=ŠDC.WƒRETURN-JUMPTABL„$FD�=ŠDC.WƒRETURN-JUMPTABL„$FE�=ŠDC.WƒRETURN-JUMPTABL„$FF�=  ‰PAGE*'* $7F = DLE, delete character at cursor*DLE'‰AND.W…#$FF80,(A0)‰Null�character�space)‰OR.B†#$20,(A0)‹Space�character�at�cursor ‰BRA‡RETURN *** Send the command in D0 to this key board*'WKBD…OR.B†#KBDADDR,D0‰To�this�key�board‰MOVE.B„D0,EPCIBASE‰RTS ** 07 = CTRL G = BELL*�ADDED‚01/30/85*8* RING_BELL flag is set so that the interrupt routine in9* KEYBRD.AG will output an ALARM command to the keyboard.*BELL ‰STˆRING_BELL ‰BRA‡RETURN ** 08 = CTRL H = BS, back space*:* Cursor moves left to first unprotected column, with line* and page rollover.**BS SEEKL„EQU‡*‰IF.L†A0��S.LINE�OR.L‰A0��S.SCRN�THEN.S9‰MOVE.L„E.LINE,A0‹If�start�of�line�encountered�set�to�end‰ENDI)‰SUBQ.L„#2,A0�Back�cursor�up�one�position ‰BRA‡WRITCRSR‰PAGE*"* 09 = CTRL I = HT, horizontal tab*2* Seek a TAB at an un-protected spot to the right,* with line and page rollover.** If none found, move right*HT$SEEKFTƒEQU‡*“Seek�a�tab�to�the�right!‰MOVE.L„A0,A3�Set�loop�terminator*‰ADDQ.L„#2,A0�Get�off�of�current�character‰BRA.S…SEEKFT1‰REPEAT-‰MOVE.W„(A0)+,D0ŒScan�forward�on�current�line‰TST.B…D0’Is�the�tab�bit�set0‰BMI.S…SEEKFT2�Found�tab�position�if�bit�was�setSEEKFT1‰IF.L†A0��E.LINE�THEN.S+‰MOVE.L„S.LINE,A0‹Only�wrap�on�current�line‰ENDI (‰UNTIL.LƒA0��A3ŠLoop�for�entire�line%‰BRA‡RETURNŽJust�exit�if�no�tab�foundSEEKFT2)‰SUBQ.L„#2,A0�Adjust�because�of�increment,‰BRA‡WRITCRSRŒUpdate�current�cursor�position‰PAGE**�0A…LINE�FEED**LF8‰MOVE.L„A0,D0…Absolute�cursor�address�into�a�usable�reg.‰SUB.L…#SCREEN,D04‰DIVU†BPERLINE+2,D0‡D0.W�is�the�absolute�line�number7‰IFˆBOTLINE��D0�THEN.S‚IF�we�are�on�the�bottom�line‰BRA‡SCROLL1�Scroll�the�screen‰ENDI/‰BRA‡DOWN�If�not�at�bottom�move�the�cursor�down***�0D…Carriage�return*2* Position cursor at left most unprotected column.** FAC's are reset.*CR‰AND.W…#$4400,(A1)‰Reset�FACs‰MOVE.L„S.LINE,A0‹Start�of�line ‰BRA‡WRITCRSR * *�1B…Escape*(* Set high bit of next character output.* ESC†EQU‡*#‰BSR‡GET_CHARŒNeed�anoter�character ‰BSET†#7,D0‰BRA‡HAVE_CHAR‰PAGE**�$8E„START�EDIT�MODE*START_EDITMODE ‰BSR‡GET_CHAR‰IF.B�D0��#$FF�THEN.S‰MOVE†#$FFFF,DUP_CHAR‰ELSE.S‰MOVE†D2,DUP_CHAR‰ENDI ‰STˆEDIT_FLAG ‰BRA‡RETURN**�$8F‚STOP�EDIT�MODE* STOP_EDITMODE%‰SFˆEDIT_FLAG‹Turn�off�edit�mode�flag ‰BRA‡RETURN‰PAGE**�$C0„cursor�home*A* Cursor moves to top left corner of screen, seeks an unprotected* space to the right.** HOME…EQU‡* ‰MOVE.L„S.SCRN,A0‹Top�left�space6‰MOVE.L„A0,S.LINE‹Modify�start�and�end�of�current�line‰MOVE.L„A0,E.LINE‰ADD.L…D6,4(A2) ‰BRA‡WRITCRSR * * C1 = Up*C* Cursor moves up one line in same column, seeks unprotected column+* to the left, with line and page rollover.**(UP‡SUB.L…D5,A0�Same�column�in�line�above3‰SUB.L…D5,(A2)�Modify�start�and�end�of�current�line‰SUB.L…D5,4(A2)‰CMP.L…S.SCRN,A0‹Out�of�screen?‰BGE.S…UP.1�No,�do�it‰MOVE.L„E.SCRN,A0‹Yes,�rollover*‰MOVE.L„A0,S.LINE‹Update�start/end�of�line‰SUB.L…D6,(A2)‰MOVE.L„A0,E.LINE ‰ADD.W…#1,D4!‰LSL.W…#1,D4�Bytes�to�end�of�line(‰SUB.W…D4,A0�To�stay�in�the�same�collumn +UP.1…EQU‡*“Modify�start/end�of�current�line ‰BRA‡WRITCRSR‰PAGE* * C2 = Down*A* Cursor seeks an unprotected spot to the right, starting at same+* collumn on next line, with page rollover.* DOWN…EQU‡*%‰ADD.L…D5,A0�Same�column�on�next�line/‰ADD.L…D5,(A2)�Modify�start/end�of�current�line‰ADD.L…D5,4(A2)#‰CMP.L…E.SCRN,A0‹Out�of�the�screen?‰BLT.S…DOWN1�No,�do�it$‰MOVE.L„S.SCRN,A0‹Yes,�page�roll: over‰MOVE.L„A0,S.LINE‰MOVE.L„A0,E.LINE&‰ADD.L…D6,4(A2)ŒD6=B.LINE,�A2==>S.LINE ‰ADD.W…#1,D4$‰LSL.W…#1,D4�D4=#�of�bytes�to�e.line ‰SUB.L…D4,D5 ‰ADD.W…D5,A0DOWN13‰BRA‡WRITCRSRŒSeek�an�unprotected�spot�to�the�right *** C3 = cursor left, same as back space 08.* * * C4 = Right*)* Seek an unprotected space to the right.*RIGHT'‰ADDQ.L„#2,A0�Get�off�of�current�column‰IF.L�A0��E.LINE�THEN.S‰MOVE.L„S.LINE,A0‹Do�line�wrap‰ENDI‰BRA‡WRITCRSRŒUpdate�the�cursor‰PAGE*+*�$C5„Move�the�cursor�to�the�requested�spot*C5: 'ŠBSR„GET_CHAR‹D0.B�<--�the�line�#�char.'ŠMOVE.B�D0,SAVE_CHAR‡Save�it�for�later. )ŠBSR„GET_CHAR‹D0.B�<--�the�column�#�char.&ŠMOVEQ‚#0,D1ŽD1�<--�the�column�#�char.ŠMOVE.B�D0,D1Ž*1ŠSUB.B‚#$20,D1ŒAdjust�it�so�0�is�first�line,�etc. 4ŠCMP„LEFTCOL,D1‰Ensure�that�the�column�#�is�in�range2ŠBLO„RETURN�(�LEFTCOL�<�column�#�<�RIGHTCOL).‚Just0ŠCMP„RIGHTCOL,D1ˆignore�the�command�if�it�isn't. ŠBHI„RETURN�* 4ŠMOVEQ‚#0,D0ŽD0�<--�line�#�char�(saved�from�before).ŠMOVE.B�SAVE_CHAR,D0‡*1ŠSUB.B‚#$20,D0ŒAdjust�it�so�0�is�first�line,�etc. 2ŠCMP„TOPLINE,D0‰Ensure�that�the�line�#�is�in�range0ŠBLO„RETURN�(�TOPLINE�<�line�#�<�BOTLINE�).‚Just/ŠCMP„BOTLINE,D0‰ignore�the�command�if�it�isn't. ŠBHI„RETURN�* /ŠMULUƒD5,D0ŽD0�<--�start�addr�of�absolute�line.ŠADD.L‚#SCREEN,D0‰*"ŠADD„D1,D1ŽA0�<--�addr�of�cursor�=ŠADD.L‚D0,D1Ž*„2�*�column�#�+'ŠMOVE.L�D1,A0Ž*„start�of�absolute�line. -ŠMOVEQ‚#0,D1ŽS.LINE�(start�of�virtual�line)�=7ŠMOVEƒLEFTCOL,D1‰*„2�*�left�column�of�virtual�display�+$ŠADD„D1,D1Ž*„start�of�absolute�line.ŠADD.L‚D0,D1Ž*ŠMOVE.L�D1,S.LINEŠ* +ŠADD.L‚D6,D1ŽE.LINE�(end�of�virtual�line)�=4ŠMOVE.L�D1,E.LINEŠ*„S.LINE�+�bytes�per�virtual�line. 5ŠBRA„WRITCRSR‹Seek�an�unprotected�space�to�the�right.‰PAGEC6‡EQU‡***�$C6„Read�the�cursor�position.**‚Input�parametersƒ:�none.*G*‚Registers�affected�:�D0.W�=�LLCC�(see�C5�for�an�explanation�of�LLCC).**+‰BSR‡READCRSRŒGet�cursor's�absolute�address‰DIVU†D5,D1�D1=00CC00LL‰SWAP†D1’D1=00LL00CC3‰LSL.W…#8-1,D1�D1=00LLCC00�(-1�to�convert�to�bytes)0‰ADD.L…#$DD2020DE,D1‡Add�the�offset�for�the�user*¦Set�start�data�and�end�data*‰LEA‡XTCHBUF(PC),A0†Set�up�for�FEEDER�call‰MOVE.L„D1,(A0)�Move�to�buffer,‰MOVE.W„#4,FEEDER_COUNT…Set�length�of�buffer:‰MOVE.L„A0,FEEDER_ADDRESSƒSet�address�of�buffer�for�FEEDER‰BSR‡FEEDERŽGive�data�to�driver‰BRA‡RETURNŽReturn�to�caller **�$C7„Set�page�mode.* SPAGE„EQU‡*6‰MOVE.W„#-1,PAGEFLAGˆSet�page�mode�flag�true�and�reset‰SFˆPROMODE�protect�mode.2‰MOVE.W„#$C0,D0�Entry�into�page�mode�causes�a�home *¦cursor.‰BRA‡POUTCHSƒ* **�$C8„Set�scroll�mode.* RPAGE„EQU‡*5‰CLR.W…PAGEFLAGŒReset�page�mode�flag�and�protect�mode‰SFˆPROMODE�flag. ‰BRA‡HOME**�$CD„Set�protect�mode*SETPRO‰STˆPROMODEƒSet�protect�mode‰CLR‡PAGEFLAG‚Reset�page�mode!‰MOVE†#$C0,D0ƒForce�a�cursor�home‰BRA‡POUTCHSƒ* ‰PAGE***�$C9„Set�top�line�of�virtual�display�area*G* The top line is set by: 1. Bringing the cursor to the requested line,*œand�then�entering�an�ESC�I."*™2.�Entering�outch�with�D0.W=LLC5 SETTOPƒEQU‡* ‰BSR‡GET_CHARŒGet�next�character‰SUB.B…#$20,D2$‰CMP.W…BOTLINE,D2Š0=botline ‰BHI‡RETURN$‰MOVE.W„D2,TOPLINEŠStore�in�constantINITIT‰BSR‡CRTINIT�Re-configure�CRT&‰BRA‡HOME†Put�cursor�in�home�position. *-*�$CA„Set�bottom�line�of�virtual�display�area*"*�Same�as�C9�for�bottom�line‚ESC�J*SETBOTOM�EQU‡*‰BSR‡GET_CHARŒGet�line�number!‰SUB.B…#$20,D2�Adjust�line�number+‰CMP.W…LPERSCRN,D2‰lperscrn>botline>topline ‰BHS‡RETURN‰CMP.W…TOPLINE,D2 ‰BLO‡RETURN‰MOVE.W„D2,BOTLINE ‰BRA‡INITIT *5*�$CB„Set�left�display�column�of�virtual�screen‚ESC�K* SETLEFT‚EQU‡*‰BSR‡GET_CHARŒGet�left�column‰SUB.B…#$20,D2‰CMP.W…RIGHTCOL,D2 ‰BHI‡RETURN‰MOVE.W„D2,LEFTCOL ‰BRA‡INITIT‰PAGE*4*�$CC„Set�right�display�column�of�dispaly�area‚ESC�L*SETRIGHT�EQU‡*‰BSR‡GET_CHA: RŒGet�right�column‰SUB.B…#$20,D2,‰CMP.W…CPERLINE,D2‰cperlineleftcol ‰BHS‡RETURN‰CMP.W…LEFTCOL,D2 ‰BLO‡RETURN‰MOVE.W„D2,RIGHTCOL ‰BRA‡INITIT SEEIFIN‚EQU‡*-‰LSR.W…#8,D0�Check�to�see�if�the�user�defined%‰TST.W…D0’the�spot�in�the�second�byte ‰BNE.S…RTSIT*:* The routine will calculate the current line and collumn.+* Left collumn is #00, and top line is #00.*2*�InputŒA0.L�=�Address�of�cursor�in�display�screen**�Output‹A0.L�=�unchanged*’D0.L�=�00CC00LL&*™whereˆLL�=�Line�number,�top�line�=�0'*¦CC�=�Collumn�number,�left�collumn�=�0 GETSPOT‚EQU‡*‰CLR.L…D0’HSKP ‰MOVE.L„A0,D04‰SUB.L…#SCREEN,D0‰=Absolute�cursor�address�on�screen ‰LSR.W…#1,D0*‰DIVU†CPERLINE,D0‰The�quotiant=line�number RTSIT„RTS‰PAGE**�$CD„erase�to�end�of�field*7* All contiguous unprotected characters are spaced out.** FACs are unaffected.* Cursor stays where is.* EEFIELD‚EQU‡*$‰MOVE.W„D6,D7�Words�per�virtual�line#‰LSR.W…#1,D7�Bytes�per�virtual�line-‰SUB.W…D4,D7�Number�of�bytes�to�start�of�line‰BRA.S…EEFIELD0 ‰CLR.W…D3 ‰CLR.W…D7&EEFIELD0�TST.W…(A0)�Is�spot�protected?‰BMI‡RETURNŽYes,�that's�it#‰AND.W…#$FF80,(A0)‰No,�space�it�out‰OR.W†#$20,(A0)+'‰DBRA†D4,EEFIELD0‰Repeat�to�end�of�line$‰ADD.W…PB.LINE,A0ŠStart�of�next�line‰MOVE.W„C.LINE,D4‰CMP.L…E.SCRN,A0(‰BLE.S…EEFIELD1ŒAre�we�ar�end�of�screen?#‰MOVE.L„S.SCRN,A0‹Yes,�roll�it�over.EEFIELD1�DBRA†D3,EEFIELD0‰Repeat�for�all�lines2‰MOVE.W„D7,D4�Add�the�characters�before�the�cursor‰DBRA†D7,EEFIELD0‰BRA‡RETURNŽAnd�then�return‰PAGE**�$CE„write�absolute* WABSOLUT: -ŠREPEAT”Wait�for�a�'start�of�data'�indicator.ŠBSR„GET_CHAR‹*ŠUNTIL.B�D0��#START_OF_DATA .ŠMOVEƒ(A1),SAVEFACS†Save�FACS�currently�in�use 'ŠBSR„GET_CHAR‹D0.B�<--�the�line�#�char.'ŠMOVE.B�D0,SAVE_CHAR‡Save�it�for�later. )ŠBSR„GET_CHAR‹D0.B�<--�the�column�#�char.&ŠMOVEQ‚#0,D1ŽD1�<--�the�column�#�char.ŠMOVE.B�D0,D1Ž*1ŠSUB.B‚#$20,D1ŒAdjust�it�so�0�is�first�line,�etc. 5ŠCMP„CPERLINE,D1ˆEnsure�that�the�column�#�is�in�range-ŠBHS„RETURN�(�LEFTCOL�<�column�#�<�RIGHTCOL). 4ŠMOVEQ‚#0,D0ŽD0�<--�line�#�char�(saved�from�before).ŠMOVE.B�SAVE_CHAR,D0‡*1ŠSUB.B‚#$20,D0ŒAdjust�it�so�0�is�first�line,�etc. /ŠCMP„LPERSCRN,D0ˆEnsure�the�line�#�is�in�range. ŠBHI„RETURN�*BŠMOVE.L�A0,SAVE_CURSOR…Save�the�cursor�address�in�the�vertual�scrn /ŠMULUƒD5,D0ŽD0�<--�start�addr�of�absolute�line.ŠADD.L‚#SCREEN,D0‰*"ŠADD„D1,D1ŽA0�<--�addr�of�cursor�=ŠADD.L‚D0,D1Ž*„2�*�column�#�+'ŠMOVE.L�D1,A0Ž*„start�of�absolute�line. -ŠMOVEQ‚#0,D1ŽS.LINE�(start�of�virtual�line)�=7ŠMOVEƒLEFTCOL,D1‰*„2�*�left�column�of�virtual�display�+$ŠADD„D1,D1Ž*„start�of�absolute�line.ŠADD.L‚D0,D1Ž*ŠMOVE.L�D1,S.LINEŠ* +ŠADD.L‚D6,D1ŽE.LINE�(end�of�virtual�line)�=4ŠMOVE.L�D1,E.LINEŠ*„S.LINE�+�bytes�per�virtual�line. 7ŠST…CHAR_RESERVED†Set�up�to�receive�incoming�charactersŠLEA„WABS1(PC),A3‡*ŠMOVE.L�A3,CHAR_OWNER†*%ŠBRA„WRITCRSR‹Update�cursor�position.WABS1!ŠIF.B�D0��#END_OF_DATA�THEN.S6‰MOVE.L„SAVE_CURSOR,D0†Restore�virtual�screen's�S.LINE *°and�E.LINE!‰MOVE.L„D0,D1�Copy�cursor�address‰SUB.L…#SCREEN,D0*‰DIVU†BPERLINE+2,D0‡Find�line�cursor�is�on*¦remainder�=�position�in�line‰CLR‡D0’Forget�line�we�are�on‰SWAP†D0,‰SUB.L…D0,D1�we�now�know�the�absolute�s.line-‰MOVE†LEFTCOL,D0Šso�adjust�it�by�the�value�in‰ADD‡D0,D0�leftcol.‰ADD.L…D0,D1�*1‰MOVE.L„D1,S.LINE‹bingo�we�now�have�start�of�line-‰ADD.L…B.LINE,D1‹add�the�number�of�bytes/line%‰MOVE.L„D1,E.LINE‹and�set�end�of�line8‰MOVE.L„SAVE_CURSOR,A0†Set�cursor�back�to�virtual�screen‰MOVE†SAVEFACS,FACS‰BRA‡WRITCRSRŒ*ŠENDIŠST…CHAR_RESERVED‰IF.B„D2��#$E0�AND.B‘D2��#$EB�THEN.S6‰TST.B…LASTFAC�See�if�the�last�character�processed�was*¦a�FAC.5‰IF„�THEN.S�If�it�was�not�a�FAC�then�destroy�what)*¦could�be�another�FAC�currently�on�scrn.9‰MOVE.B„#$FF,1(A0)ŠFac�processing�checks�the�current�char%*¦to�determine�if�a�new�FAC�should�be'*¦declared.�If�we�are�currentl; y�sitting**¦on�a�FAC�definition�it�must�be�destroyed‰ENDI3‰STˆLASTFAC�Tell�the�loop�we�have�been�here�before. ‰BRA�OUTCH1‰ENDI3‰TST.B…LASTFAC�If�the�last�character�was�a�FAC�then"*¦the�cursor�must�be�moved�off�it.‰IFˆ�THEN.S)‰ADD.L…#2,A0�Move�the�cursor�off�the�FAC.4‰SFˆLASTFAC�Indicate�the�last�character�was't�a�FAC.‰ENDI8‰MOVE.W„LPERSCRN,D0‰FIND�THE�END�OF�THE�ABSOLUTE�DISPLAY ‰MULU†D5,D0�*‰ADD.L…#SCREEN,D0Š*5‰OR.W†FACS,D2�Write�the�current�character�to�the�scrn‰MOVE.W„D2,(A0)+Œ*‰IF.L†A0��D0�THEN.S&‰BRA‡RETURNŽExit�if�past�end�of�screen‰ENDI,‰BRA‡WRITCRSRŒUpdate�current�cursor�position **�$CF„read�absolute**RABSOLUT�EQU‡*8‰BSR‡GET_CHAR‚Get�row�address�for�beginning�adr.�of�read*‰MOVE.B„D0,SAVE_CHAR‚Save�the�row�address.8‰BSR‡GET_CHAR‚Get�col.�address�of�begining�read�address. ‰MOVE.B„D0,SAVE_CR1‰Save�it�also0‰BSR‡GET_CHAR‚Get�row�address�of�ending�address.‰MOVE.B„D0,SAVE_CR2‰Save�it.0‰BSR‡GET_CHAR‚Get�col.�address�of�ending�address‰MOVE.B„D0,SAVE_CR3‰Save�it.***ˆALLOCATE�MEMORY--SAVE�THE�BUFFER�ADDRESS*0‰MOVE.L„#4,D0…Service�request�code�for�PAGEALOC.7‰MOVE.L„#8,A0…Set�up�memory�descriptor�and�get�8�pages. ‰SUB.L…A1,A1‰TRAP†#0&‰BRA.S…RABSO1„Branch�if�we�got�memory.#‰BRA‡RETURN„Just�exit�if�we�didn't.**ˆSAVE�BUFFER�ADDRESS*RABSO13‰STˆREL_FLAGŒTell�feeder�to�release�mem.�when�done.*‰MOVE.L„A0,REL_ADDR‰Feeder�buffer�address.4‰MOVE.L„A0,FEEDER_ADDRESSƒBuffer�address�for�feeder..‰MOVE.L„A0,A2�Put�address�in�useable�register.@‰MOVE.L„#NUMBER_PAGES,REL_PAGES‚Tell�feeder�the�number�of�pages.‰MOVE.B„#START_OF_DATA,(A2)+;‰MOVE†#1,FEEDER_COUNT…Update�the�charater�count�for�feeder.*=*ˆFIND�THE�BEGINNING�AND�ENDING�ADDRESSES�BASED�ON�THE�CURSOR *ˆADDRESSES*/ˆMOVE‡SAVE_CR2,D0‰Convert�ending�address�first.)‰SUB‡#$2020,D0‹Adjust�the�cursor�address.‰BSR.S…CONVERT�*'‰MOVE.L„A0,A1�Put�it�in�the�proper�reg.,‰MOVE†SAVE_CHAR,D0ˆNow�do�beginning�address.)‰SUB‡#$2020,D0‹Adjust�the�cursor�address.‰BSR.S…CONVERT�*6‰MOVE.L„A0,D1�This�will�be�the�end�of�current�line�adr‰ADD.L…D5,D1�*?*†A0�=�STARTING�ADDRESS†A1�=�ENDING�ADDRESS„A2�=�BUFFER�ADDRESS ‰REPEAT8‰IF.L†A0��D1�THEN.SƒIf�we�are�at�the�end�of�the�line8‰MOVE.B„#END_OF_FIELD,(A2)+�move�in�the�line�terminator.*‰ADDQ†#1,FEEDER_COUNT…Update�feeder�count. ‰ADD.L…D5,D1‰ENDI ‰TST.B…1(A0)5‰IF‚�THEN.S�End�of�lines�are�flagged�by�an�end�of,‰MOVE.B‚#END_OF_FIELD,(A2)+ƒfield�character.*‰ADDQ†#1,FEEDER_COUNT…Adjust�feeder�count.‰ENDI‰IF.B…1(A0)��#01�THEN.S!‰ADDQ.L„#2,A0�Adjust�the�pointer. ‰BRA.S…RABSO2‰ENDI+‰MOVE.B„1(A0),D0ŒWe�could�be�on�a�tab�stop.)‰AND.B…#$7F,D0�Strip�of�the�tab�stop�bit.*‰MOVE.B„D0,(A2)+ŒMove�data�byte�to�buffer.%‰ADDQ.L„#2,A0�Bump�to�next�character.3‰ADDQ†#1,FEEDER_COUNT…Bump�feeders�character�count.RABSO2‰UNTIL.LƒA0��A1D‰MOVE.B„#END_OF_DATA,(A2)�We�are�all�done�moving�data�to�the�buffer.;‰ADDQ†#1,FEEDER_COUNT…Bump�number�of�characters�for�feeder.(‰BSR‡FEEDERŽSend�the�data�to�the�driver./‰BRA‡RETURNŽWe�are�all�done�--�thankyou�kindly.*2* Convert the llcc value to a display RAM address.**ˆInputƒD0.W�=�llcc*ˆOutput‚A0.L�=�screen�address* CONVERT‚EQU‡*%‰MOVE.L„D6,-(A7)ŒGet�some�ellbow�room ‰CLR.L…D6 ‰MOVE.W„D0,D6‰AND.W…#$00FF,D0‰CMP.W…CPERLINE,D0 ‰BGT.S…CONRET‰LSR.L…#8,D6�D6.L=000000ll‰CMP.W…LPERSCRN,D6 ‰BGT.S…CONRET ‰MULU.W„D5,D6 ‰LSL.W…#1,D0 ‰ADD.B…D0,D6‰ADD.L…#SCREEN,D6 ‰MOVE.L„D6,A0CONRETƒMOVE.L„(A7)+,D6‰RTS‰PAGE*8*‚$D0„Insert�a�character�at�the�current�cursor�position.B*‰Starting�at�the�current�cursor�position,�characters�are�moved�to@*‰the�right�until�the�end�of�line�or�a�protected�field�is�hit.‚A>*‰space�is�put�in�the�current�cursor�position.‚The�cursor�does *‰not�move.*7ICHAR:„MOVEQ‚#SPACE,D0ŠInitialize�LAST�CHAR�to�a�space. ICHAR12ŠMOVEQ‚#$7F,D1ŒD1�<--�the�char�from�this�position.ŠAND„(A0),D1Œ*9ŠAND„#$FF80,(A0)ˆPut�the�LAST�CHAR�out�there�in�its�plac; e.ŠOR…D0,(A0)+‹and�advance�to�the�next�position.1ŠMOVEƒD1,D0ŽSet�LAST�CHAR�to�the�char�we�just�got;ŠDBRAƒD4,ICHAR1Š(for�next�pass)�and�loop�until�end�of�line. ICHAR3„BRA„RETURN�Exit. *8*‚$D1„Delete�a�character�at�the�current�cursor�position.F*‰Starting�just�past�the�current�cursor�position,�characters�are�movedB*‰to�the�left�until�the�end�of�line�or�a�protected�field�is�hit.‚A@*‰space�is�put�in�the�final�modifiable�position.‚The�cursor�does%*‰not�move.‚The�entry�point�is�DCHAR.*<DCHAR1„MOVEƒ2(A0),D0‹D0�<--�the�char�from�the�next�position. *ŠAND„#$7F,D0ŒPut�the�char�in�this�position%ŠOR…D0,(A0)+‹and�advance�to�the�next. :DCHAR:„AND„#$FF80,(A0)ˆRemove�the�char�from�this�position.2ŠDBRAƒD4,DCHAR1ŠLoop�if�there�are�more�characters. 6DCHAR2„OR…#$20,(A0)ŠPut�a�space�in�this�final�positionŠBRA„RETURN�and�return.‰PAGE**‚$D2ƒENABLE�KEYBOARD*KEYENAB ‰SFˆKB_LOCK ‰BRA‡RETURN   **‚$D3ƒDISABLE�KEYBOARD*KEYDSABL ‰STˆKB_LOCK ‰BRA‡RETURN   ***�$D4„erase�all�unprotected�to�end�of�page**ˆFACs�are�not�affected!*ˆCursor�position�is�not�affected* EEPAGEƒEQU‡*‰BSR‡GETSPOT�D0=00CC00LL‰SUB.W…TOPLINE,D0-‰SUB.W…D0,D3�Number�of�lines�to�end�of�screenEEPAGE1‚BSR‡ERASE�Erase�them ‰BRA‡RETURN  **�$D5„Erase�to�end�of�line* EELINEƒEQU‡*‰CLR.W…D3’Only�one�line ‰BRA‡EEPAGE1  *3*‚$D6„Insert�a�line�at�the�current�cursor�position.@*‰Starting�at�the�bottom�of�the�screen�and�working�up,�copy�each=*‰line�to�the�line�below.‚The�line�the�cursor�is�on�is�filled=*‰with�blanks�and�the�cursor�is�positioned�at�the�left�of�the3*‰line.‚(In�all�this,�'line'�means�'virtual�line.')*INS_LINE6ŠMOVE.L�E.SCRN,A0ŠA0�<--�addr�just�past�end�of�screen. AŠWHILE.L�A0��E.LINE�DO.S‚While�A0�is�not�on�the�current�line, 6ŠMOVE.L�A0,A1ŽA1�<--�addr�just�past�end�of�line�above./ŠSUB.L‚D5,A1Ž*‡(D5�is�bytes�per�absolute�line.)0ŠMOVE.L�A0,-(SP)‹Save�the�address�for�this�line. 6ŠMOVEƒC.LINE,D0ŠD0�<--�#�of�chars�in�virtual�line�-�1.@INS_LIN1‚MOVEƒ-(A1),-(A0)ˆMove�all�words�(attribute�and�char)�in.ŠDBRAƒD0,INS_LIN1ˆthis�line�to�the�line�below. 3ŠMOVE.L�(SP)+,A0‹Restore�the�address�for�this�line.-ŠSUB.L‚D5,A0ŽA0�<--�address�for�next�line�up. ŠENDW (*§At�this�point�A0�is�the�addr�just�past&*§the�end�of�the�current�virtual�line.6ŠMOVEƒC.LINE,D0ŠD0�<--�#�of�chars�in�virtual�line�-�1.?INS_LIN2‚AND.B‚#$80,-(A0)‰Fill�the�current�line�with�spaces�and%ŠOR.Bƒ#$20,(A0)Šinnocuous�attributes.ŠMOVE.B�#$44,-(A0)‰*ŠDBRAƒD0,INS_LIN2ˆ*%*§At�this�point�A0�is�the�addr�of�the(*§beginning�of�the�current�virtual�line.,ŠBRA„WRITCRSR‹Go�set�the�new�cursor�address.   **�$D7‚DELETE�LINE*DEL_LINE;‰MOVE.L„S.LINE,A0�Beginning�address�of�current�virtual�lineDELINE;‰MOVE.L„A0,A1…Calculate�the�address�of�the�beginning�of�the‰ADD.L…D5,A1…next�line.4‰MOVE†C.LINE,D0�Number�of�bytes�per�line�to�be�moved?‰CMP.L…E.SCRN,A1�See�if�move�from�address�is�passed�end�of�scrn-‰BHS.S…DELINE2ƒBranch�if�passed�end�of�screen2‰MOVE.L„A0,-(A7)‚Save�destination�address�on�stackDELINE1*‰MOVE.W„(A1)+,(A0)+�Move�line�up�on�screen‰DBRA†D0,DELINE1‚*,‰MOVE.L„(A7)+,A0‚Restore�destination�address'‰ADD.L…D5,A0‡Point�to�next�virtual�line,‰BRA.S…DELINE„Go�move�next�line�up�on�screenDELINE22‰MOVE.B„#$44,(A0)+ƒBlank�the�bottom�line�of�screen.‰AND.B…#$80,(A0)„Save�tab�stop�if�there�is�one+‰OR.B†#$20,(A0)+ƒSet�space�in�this�location‰DBRA†D0,DELINE2ƒ*9‰MOVE.L„S.LINE,A0„Set�cursor�to�beginning�of�current�line‰BRA‡WRITCRSR…*   **�$D8„clear�screen,�cursor�home*B* All unprotected positions in display area are filled with nulls.* FAC's are not affected.* * Cursor moves to home position.** CLEAR_SCREENA‰MOVEM.LƒD0-D7/A0-A3,-(A7)ƒSet�up�the�alternate�entry�for�command6‰MOVE†L.SCRN,D3‹Set�up�the�reg�because�it�isn't�set�ip*%%%%%%%%%‚BWN‚10/24/84*6*ƒSet�up�the�other�registers�we�need�for�this�routine.*‰LEA‡S.L< INE,A2‰MOVE.L„B.LINE,D6!*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% CLEAR„EQU‡*‰MOVE.L„S.SCRN,A0‹Start�at�home‰MOVE.W„C.LINE,D4‹A�full�line"‰BSR.S…ERASE�Erase�all�unprotected‰BRA‡HOME�Put�cursor�at�home *%* Erase D4.W characters in D3.w lines* ERASE„EQU‡*‰IF‚PAGEFLAG��#TRUE�THEN.S0‰TST‡(A0)+�Used�only�when�alternate�entry�called ‰BMI.S…ERASE1‰ENDI$‰AND.W…#$0080,(A0)‰Clear�current�FAC ‰OR.W†#$4400,(A0)+ˆWrite�a�space/ERASE1ƒDBRA†D4,ERASEŒRepeat�for�D4.w�characters)‰MOVE.W„C.LINE,D4‹Reset�character�counter$‰ADD.W…PB.LINE,A0ŠStart�of�next�line$‰DBRA†D3,ERASEŒRepeat�for�D3.w�lines‰RTS‰PAGE**�$DA„Forward�tab* * Same as HT* ** DB = BT, back tab*@* Position cursor at first tab in first unprotected to the left.**  SEEKBTƒEQU‡*‰MOVE.L„A0,A3�Loop�terminator‰REPEAT‰IF.L†A0��S.LINE�THEN.S+‰MOVE.L„E.LINE,A0‹Wrap�on�current�line�only‰ENDI1‰MOVE.W„-(A0),D0ŒCharacter�preceeding�current�one‰TST.B…D0’Is�this�a�tab�stop*‰BMI.S…SEEKBT2�Branch�if�we�hit�a�tab�stopSEEKBT1;‰UNTIL.LƒA0��A3ŠScan�line�until�we�get�where�we�startedSEEKBT2#‰BRA‡WRITCRSRŒUpdate�cursor�address‰PAGE** DC = set tab* SETTABƒEQU‡*/‰CLR.L…COL_CNTƒInitialize�current�column�number‰BRA.S…SETTAB2SETTAB1:‰ADD.L…#2,COL_CNTŠUpdate�the�column�count�for�the�next�guy‰MOVE.L„COL_CNT,D0@‰IF.L‚D0��BPERLINE�THEN.S�Make�sure�we�don't�go�out�of�range<‰WHILE�D2��#LFCHAR�DO.S„If�out�of�range�discard�incoming/‰BSR�GET_CHAR’until�terminated�with�a�line�feed‰ENDW‰BRA‡RETURNŽExit‰ENDISETTAB2.‰BSR‡GET_CHAR‚Get�next�character�of�tab�string6‰MOVE†LPERSCRN,D3‰Set�loop�control�for�absolute�screen‰SUBQ†#1,D3�DBRA�adjustment9‰CMP.B…#LFCHAR,D2ŠEnd�of�string�is�indicated�by�line�feed‰BNE.S…SETTAB2A‹**C*‡LINE�FEED�CHARACTER�DETECTED,‚IF�IT�FOLLOWED�SET�TABS--�RESET�ALL*‡CURRENT�TABS*SETTAB42‰TST.L…COL_CNT�If�column�count�zero�then�line�feed*°followed�set�command‰IF��THEN.S+‰LEA‡SCREEN,A0‹Point�to�beginning�of�screen+‰MOVE†LPERSCRN,D5‰Get�#�of�lines�per�screen8‰MULU†CPERLINE,D5‰*�characters�per�line�=�#�of�character*©positions�on�screenCLRTAB‰AND.W…#$FF7F,(A0)+ˆReset�tab(‰DBRA†D5,CLRTAB‹Loop�until�end�of�screen‰ENDI ‰BRA‡RETURNSETTAB2A4‰MOVE.L„COL_CNT,A0ŠPoint�to�current�position�in�line‰ADD.L…#SCREEN,A0Š*-‰CMP.B…#SPACE,D2‹Is�this�a�filler�character�?5‰BEQ.S…SETTAB1�Get�next�character�if�current�is�space'‰CMP.B…#CLEARTAB,D2ˆClear�tab�request�?+‰BEQ.S…RESETTABŒBranch�if�clear�tab�request**„SET�TAB�REQUEST*SETTAB37‰BSET.B„#7,1(A0)ŒSet�tab�bit�in�high�nibble�of�the�dis-4‰ADD.L…D5,A0�played�char.�for�every�column�on�screen‰DBRA†D3,SETTAB3Š*‰BRA.S…SETTAB1RESETTAB1‰BCLR.B„#7,1(A0)ŒTurn�tab�bit�off�in�every�column‰ADD.L…D5,A0�*‰DBRA†D3,RESETTAB‰* ‰BRA‡SETTAB1‰PAGE*F* The characters $E0-$EF will set or reset the field attribute bits in'* the XREFed, word sized register FACS.* FACS is defined as follows:**ˆD15�=�Set�for�protect*ˆD14�=�Set�for�display*ˆD13�=�Set�for�blink*ˆD12�=�Set�for�underline*ˆD11�=�Set�for�inverse�video*ˆD10�=�color/intensity�bit�1*ˆD09�=�color/intensity�bit�2*ˆD08�=�color/intensity�bit�3 *„D07-D00�=�0* ** E0 = set blink* SBLINKƒEQU‡*B‰IF.B�1(A0)��#01�THEN.S…Allow�another�FAC�to�be�defined�only‚f&*¦if�we�are�currently�sitting�on�a�FAC *¦definition.!‰BSET.B„#5,(A1)�Set�the�blink�bit‰ELSE.S4‰MOVE.B„#$64,(A1)‹Not�on�a�current�FAC�definition�so*¦reset�the�FACS.‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen9‰MOVE.B„#01,1(A0)‹Simulate�character�position�used�by�FAC ‰BRA‡RETURN ** E1 = reset blink* RBLINKƒEQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FACC‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.#‰BCLR.B„#5,(A1)�Reset�the�blink�bit‰ELSE.S4‰MOVE.B„#44,(A1)ŒReset�any�other�FACS�for�this�line.< ‰ENDI ‰BRA‡RETURN ** E2 = set video invert* SINVERT‚EQU‡*C‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.#‰BSET.B„#3,(A1)�Set�the�inverse�bit‰ELSE.S7‰MOVE.B„#$4C,(A1)‹Set�invert�only�bit.�(plus�dislay�and *¦intensity.‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FAC ‰BRA‡RETURN ** E3 = reset video invert* RINVERT‚EQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FACC‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.%‰BCLR.B„#3,(A1)�Reset�the�inverse�bit‰ELSE.S#‰MOVE.B„#$44,(A1)‹Reset�everything.‰ENDI ‰BRA‡RETURN ** E4 = Set half bright*UPBRIGHT�EQU‡*,‰MOVE.B„(A1),D2�Get�the�MSB�part�of�the�FACs'‰AND.B…#$F8,D2�Only�the�brightness�bits ‰OR.B†#$05,D2�Set�to�half�bright‰MOVE.B„D2,(A1)�* ‰BRA‡RETURN ** E5 = Reset half bright*DNBRIGHT�EQU‡*,‰MOVE.B„(A1),D2�Get�the�MSB�part�of�the�FACs'‰AND.B…#$F8,D2�Turn�off�brightness�bits‰OR.B†#$02,D2�Reset�half�bright‰MOVE.B„D2,(A1)�* ‰BRA‡RETURN ** E6 = set underline* SULINEƒEQU‡*C‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.%‰BSET.B„#4,(A1)�Set�the�underline�bit‰ELSE.S)‰MOVE.B„#$54,(A1)‹Set�underline�FAC�only.‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FAC ‰BRA‡RET.1 ** E7 = reset underline* RULINEƒEQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FACC‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.'‰BCLR.B„#4,(A1)�Reset�the�underline�bit‰ELSE.S.‰MOVE.B„#44,(A1)ŒReset�all�FACS�for�this�line.‰ENDI ‰BRA‡RET.1 ** E8 = set non display* NONDISP‚EQU‡*C‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.'‰BCLR.B„#6,(A1)�Set�the�non-display�bit‰ELSE.S(‰MOVE.B„#4,(A1)�Turn�off�the�dispay�bit.‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FAC ‰BRA‡RETURN ** E9 = reset non-display* SETDISP‚EQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FACC‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.2‰BSET.B„#6,(A1)�Set�display�along�with�other�FACS.‰ELSE.S:‰MOVE.B„#$44,(A1)‹Set�display�bit�only,�turn�off�all�other*¦FACS.‰ENDI ‰BRA.S…RET.1 ** EA = set protect* PROTECT‚EQU‡*C‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.6‰BSET.B„#7,(A1)�Set�protect�bit�and�don't�change�other*¦FACs�allready�there.‰ELSE.S'‰MOVE.B„#$C4,(A1)‹Set�protect�FAC�only.‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FAC ‰BRA.S…RET.1 ** EB = reset protect* ALLOW„EQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�FACC‰IF.B‚1(A0)��#01�THEN.SƒAllow�another�FAC�to�be�defined�only�if#*¦we�are�currently�sitting�on�a�FAC *¦definition.+‰BCLR.B„#7,(A1)�Reset�only�the�protect�FAC.‰ELSE.S!‰MOVE.B„#$44,(A1)‹Reset�all�FACs.‰ENDIRET.1„BRA‡RETURNŠPAGE* * F1 = reset*K* The display area is filled with spaces, all FAC's are reset, tabs are setL* every INIT_TAB spaces, the virtual screen is restored to its default size,* and the cursor is HOMEd.* RESET_SCREEN>‰MOVEM.L�D0-D7/A0-A3,-(A7)�Set�up�stack�so�we�can�exit�clean„T5‰LEA‡S.LINE,A2‡Fix�up�the�registers�because�we�didn't*¢come�through�the�normal�path‰MOVE.L„= B.LINE,D6‡*$‰BRA.S…RESET25‰Clear�25�line�screen.RESET240‰MOVE†#24,NUMBER_LINES�Set�up�to�clear�24�lines.RESET253ŠBSR„SCRNINIT‹Reset�all�the�parameters�to�defaults. *‚Fill�the�screen�with�blanks.4ŠLEA„SCREEN,A0ŠA0�<--�start�addr�of�absolute�screen.6ŠMOVEƒ#$4400,D2ŠD2�<--�default�attributes�and�a�end�of#*¦line�char�for�filling�the�screen.:ŠMOVEƒNUMBER_LINES,D5„D5�<--�#�of�characters�on�screen�-�1<ŠMULUƒCPERLINE,D5ˆ*‚=�lines�per�screen�*�chars�per�line�-�1. ŠSUBQƒ#1,D5Ž* �DO.SŠWhile�there�are�more�tabs�to�place, 5ŠBSETW‚#7,(A0)ŒSet�a�tab�in�this�position�and�advance%ŠADD.L‚#2*INIT_TAB,A0…INIT_TAB�chars. 0ŠSUBQƒ#1,D5ŽKeep�going�until�all�tabs�are�placedŠENDW–on�this�line. /ŠMOVEƒBPERLINE,A0ˆA0.L�<--�address�of�next�line7ŠADD.L‚(SP)+,A0‹*„=�addr�of�last�line�+�bytes�per�line. 0ŠSUBQƒ#1,D2ŽKeep�going�until�all�lines�are�done. ŠUNTIL‚�*ŠSF…EDIT_FLAGŠClear�edit�modeŠSF…PAGEFLAG‹page�modeŠSF…PROMODEŒand�protect�mode.3ŠMOVE.LƒB.LINE,D6ˆHome�needs�bytes�per�virtual�line?ŠMOVE…#25,NUMBER_LINES�Set�up�the�screen�to�25�lines�in�case�we*£did�a�24�line�screen�clear.ŠBRA‡HOMEŒHome�the�cursor.‰PAGE* * DISPLAYL*---------------------------------------------------------------------------L* 1. Write the requested character in the display RAM at the current cursor.I* 2. Seek a non-protected spot to the right, with line and page rollover.6*„if�none�found,�sound�bell,�and�stay�at�current�spot.,* 3. Update the cursor register of the CRTC.** Input parameters:*------------------4* A0.L = current cursor posiotion in the display RAM8* D2.L = $000000XX, where XX is the requested character.0* D3.W = Maximum number of characters on screen.F* FACS = An XREFed, word sized register containing the FACs in effect.* DISPLAY‚EQU‡*‰MOVE.L�A0,A3’Init�reg.‰WHILE.L�A3��S.LINE�DO.S2‰MOVE.B�-1(A3),D0ŽMove�end�of�line�to�current�char‰AND.B�#$7F,D0‘could�be�a�tab7‰BNE.S�DISPLAY1�Branch�if�a�character�occupies�position0‰OR.B‚#$20,-1(A3)�Space�fill�to�move�end�of�line)‰SUBQ.L�#2,A3’Backup�to�beginning�of�line‰ENDWDISPLAY1‰IF.B‚1(A0)��#01�THEN.S5‰MOVE.B„#$44,FACS‹Reset�the�FAC�defined�for�this�line#*¦because�it�is�being�written�over.‰ENDI :‰MOVE.B„FACS,(A0)+ŠMove�current�FACS�to�current�Screen�loc%‰AND.B…#$80,(A0)‹Keep�tab�information,‰OR.B†D2,(A0)+ŒWrite�character�to�the�screen  SCROLLƒEQU‡*‰IF.L†A0��E.SCRN‚THEN.S!‰IF.B†EDIT_FLAG��#TRUE�THEN.S(‰BRA�HOMEŒEND�OF�SCREEN�AND�IN�EDIT�MODE‰ENDI*‰BRA.SƒSCROLL1‚End�of�screen�not�edit�mode‰ENDI SEEKR2‰IF.L†A0��E.LINE�THEN.S#‰ADD.L…D5,(A2)�Update�start�of�line‰ADD.L…D5,4(A2)Œand�end�ofline‰MOVE.L„S.LINE,A0‰ENDI‰BRA.S…WRITCRSR ** Scroll*)* Input parameters : A0.L > end of screen* SCROLL1‚EQU‡*2‰MOVE.L„E.SCRN,E.LINE‡Modify�start�and�end�of�line‰MOVE.L„E.SCRN,S.LINE‰SUB.L…D6,(A2) %‰MOVE.L„S.SCRN,A0‹Start�of�first�line‰MOVE.L„S.SCRN,A3!‰ADD.L…D5,A3�Start�of�second�line&‰BRA.S…SCROLLR�Do�not�scroll�last�line ,SCROLL2‚MOVE.W„C.LINE,D4‹Characters�per�line6SCROLLIT�MOVE.W„(A3)+,(A0)+‰Move�line�#n+1�to�line�#n.!‰DBRA†D4,SCROLLIT‰Scroll�one�line$‰ADD.W…PB.LINE,A0ŠStart�of�next�line‰ADD.W…PB.LINE,A3SCROLLR%‰DBRA†D3,SCROLL2ŠRepeat�for�all�lines $‰MOVE.L„S.LINE,A0‹Start�of�last�line7‰MOVE.W„C.LINE,D4‹Reset�last�line�to�no�facs�and�spaces‰MOVE.W„(A1),D2 ‰OR.B†#$20,D2 2SCROLL3‚AND.W…#$0080,(A0)‰Save�only�a�possible�tab,‰OR.W†D2,(A0)+ŒInit�FACs�and�space�character‰DBRA†D4,SCROLL3ŠThe�whole�l= ine $‰MOVE.L„S.LINE,A0‹Start�of�last�line WRITCRSR�EQU‡**9* Convert display RAM address to absolute cursor address,* and write into CRTC.** A0.L = Diaplay cursor address*/‰MOVE.L„A0,D1�Calculate�cursor�absolute�address‰SUB.L…#SCREEN,D1+‰LSR.L…#1,D1�To�take�care�of�attribute�area WRITEABS�EQU‡**/* Write the absolute cursor address in the CRTC* * D1.W = absolute cursor address*!‰MOVE.B„#$0F,CRTCADDˆPoint�to�R152‰MOVE.B„D1,CRTCREGŠStore�LSB�of�new�cursor�address ‰LSR.W…#8,D1�Position�upper�byte!‰MOVE.B„#$0E,CRTCADDˆPoint�to�R143‰MOVE.B„D1,CRTCREGŠSrore�MSB�of�new�cursor�register 6RETURNƒMOVEM.Lƒ(A7)+,D0-D7/A0-A3ƒRestore�user's�values‰RTS‰PAGEREADCRSR�EQU‡***‚Read�the�cursor�position*6*‚This�routine�is�for�internal�use,�and�is�not�XDEFed.)*‚For�an�external�control�routine�see�C6.**‚Input�parametersƒ:�none*>*‚Registers�affected�:�D1.W�=�Absolute�address�of�cursor�spot.&*—A0.L�=�Screen�RAM�address�of�cursor.*‰CLR.L…D1’HSKP!‰MOVE.B„#$0E,CRTCADDˆPoint�to�R14.‰MOVE.B„CRTCREG,D1ŠGet�current�cursor�position‰ROL.W…#8,D1�Put�it�in�MSB!‰MOVE.B„#$0F,CRTCADDˆPoint�to�R154‰MOVE.B„CRTCREG,D1ŠGet�lower�byte�of�cursor�position-‰LSL.W…#1,D1�Adjust�for�screen�RAM�operations ‰MOVE.L„D1,A0‰ADD.L…#SCREEN,A0‰RTS***GET_CHAR3‰STˆCHAR_RESERVED‡Reserve�next�character�for�caller>‰MOVE.L„(A7)+,CHAR_OWNER„Save�callers�return�address�for�later'‰BRA‡RETURNŽWait�for�the�next�character‰END9PAGEMODE‚IDNTƒ1,0„VME/10�page�mode�emulation�for�TERMDRV.O*v*****************************************************************************O*******************************************************************************O**********************************************************************************É***=***†FILENAME:‚PAGEMODE�--�PAGE�MODE�EMULATION�FOR�TERMDRV�******É***7***†ENVIRONMENT:‚Linked�into�TERMDRV�for�the�VME/10“******É***E***†FUNCTION:‚When�the�keyboard/screen�is�put�into�page�mode,�any…***?***‰characters�received�from�the�keyboard�are�sent�here�for‰******‰special�interpretation.©******É******†NOTES:½******É***,***†EXTERNAL�DATA�STRUCTURES�REFERENCED:Ÿ******É***)***†EXTERNAL�ENTRY�POINTS�REFERENCED:¢******‰OUTCHSº******É***"***†SERVICES�CALLED�VIA�TRAPS:©******É******É***O*******************************************************************************O*******************************************************************************O*^***************************************************************************** *,*‚Revision�history�(add�new�changes�to�top).*…Date†Author‰ChangesG*…--------‚-------------‚----------------------------------------------&*†5/23/83‚Russ�Rustad„Initial�writing.*ŠPAGE* *‚XDEF's.*:ŠXDEFƒPAGEMODE‹Entry�pt.�for�char's�received�in�page�mode.  *0*‚XREF's�(indicate�where�the�XDEF�is,�if�known).*8ŠXREFƒOUTCHS�Routine�in�OUTCHS�to�output�char�on�screen./*ž(All�of�the�following�are�XDEF'ed�in�CRTINIT)ŠPAGEO*********************************************************************************‰INCLUDE�FILES�AND�EQUATES*O******************************************************************************* **‚Include�files:*  *.*‚Equates�for�the�values�of�the�function�keys.*9FN_LOW„EQU„$A0�These�define�the�range�of�values�generated%FN_HIGHƒEQU„$BF�by�the�function�keys.ŠPAGEO*v*****************************************************************************®@·3O**********************************************************************************É***+***�PAGEMODE�--�PAGE�MODE�INPUT�HANDLER–******É***E***†FUNCTION:‚When�an�external�routine�receives�a�character�while…***:***‰the�screen�is�in�page�mode,�he> �calls�this�routine.Ž******É******†NOTES:½******É***E***†REGISTER�USAGE:‚(A)rgument‚(D)estroyed‚(P)reserved‚(R)eturned‚***)***Œ0ƒ1ƒ2ƒ3ƒ4ƒ5ƒ6ƒ7‡SR�hi„SR�lo�(CCR)…******‡D:ƒAR‚.ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.‡.ˆR�******‡A:ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.ƒ.ƒP ******É******†ENTRY�CONDITIONS:²***8***‰D0.W�=�$00cc�where�cc�is�the�received�character.�******É***-***†EXIT�CONDITIONS�DIFFERENT�FROM�ENTRY:ž***6***‰CCR:��=�keystroke�did�not�generate�a�char.’***@***Ž,�=�generated�char�is�in�D0.W�(bits�8-15�are�0).ƒ***(***‰D0�is�not�preserved�in�any�case. ******É***O*^*****************************************************************************O******************************************************************************* ŠDS…0ŠOPT„BRS ŠSECTION�0  PAGEMODE: 1ŠMOVEM.L�D1,-(SP)ŠSave�registers�we'll�blow�away. DŠIF.B�D0��#FN_LOW�AND.B�D0��#FN_HIGH�THENƒIf�the�key�pressed*§was�a�function�key, 9ŠMOVEQ‚#1,D1ŒSet�CCR�to�,�to�say�'we�got�a�char.' %ŠELSE–Else�(it's�not�a�function�key), 8ŠBSR.L‚OUTCHS�Call�OUTCHS�to�output�the�char�and�set�CCR3ŠMOVEQ‚#0,D1Žto��to�say�'ignore�the�keystroke.' ŠENDI -ŠMOVEM.L�(SP)+,D1ŠRestore�registers�and�exit.ŠRTS—*   ŠENDéé8POUTCHSƒIDNT†1,00†Output�a�character�to�the�display�RAM. <*************************************************************º**�Routine�name:�POUTCHS˜*<*----------------------------------------------------------*-*�Current�revision.....................1.10�*1*�Date�written.........................12-18-82Œ*2*�Written�by...........................S.Pri-Tal‹*/*�Date�changed.........................3-1-83Ž*2*�Changed�by...........................R.�RUSTAD‹**º**�Description�of�change:£**º*0*�Date�changed.........................8-17-84�*1*�Changed�by...........................B.�NASONŒ**º**�Description�of�change:£**ƒChanged�all�XREF.S�to�XREF�**º*0*�Date�changed.........................8-30-84�*3*ƒchanged�to�mask�'tab�stop'�bit.....D.�Vanderlinˆ**º*0*�Date�changed.........................1-30-85�*/*�Changed�by...........................M.�DUHŽ**º**�Description�of�change:£*7*ƒSet�RING_BELL�flag�when�$07�is�to�be�output�(BELL).„**º*<************************************************************9*�Function:�Output�the�character�in�D0.B�to�the�display„*/*‹RAM�if�character�is�printable,�else�perform„**‹the�required�function.™*<*----------------------------------------------------------*/*�Input�parameters:‚D0.B�character�to�output.�*<*----------------------------------------------------------**�Registers�affected:�none¡*<*----------------------------------------------------------* *�External�routines�used:�none�*<************************************************************‰PAGE ‰XDEF†POUTCHS (‰XREF†CRTINITƒInit�the�screen�parameters‰XREF†SCRNINIT /‰XREF„FACS†Field�attribute,�word�sized�register3‰XREF„PAGEFLAG‚Word�sized�flag.�If=$FFFF,�page�mode5‰XREF„PROMODEƒWord�sized�flag.�If=$FFFF,�protect�mode 5‰XREF„CPERLINE‚Number�of�characters�per�absolute�line0‰XREF„BPERLINE‚Number�of�bytes�per�absolute�line2‰XREF„LPERSCRN‚Number�of�lines�per�absolute�screen 2‰XREF„C.LINE„Number�of�characters�per�virtual�line¸¿7È<ÐEØ4à,è,ð/ø-FHNS N(S0T8<@JHLPIX;`BhTpCxZ€EˆE�B˜; K¨L> -‰XREF„B.LINE„Number�of�bytes�per�virtual�line *‰XREF„S.LINE„Start�address�of�current�line(‰XREF„E.LINE„End�address�of�current�line *‰XREF„PB.LINEƒUnused�part�of�absolute�line 2‰XREF„L.SCRN„Number�of�lines�in�the�virtual�screen <‰XREF„S.SCRN„Address�of�home�character�in�the�virtual�screen<‰XREF„E.SCRN„Address�of�last�character�in�the�virtual�screen (‰XREF„TOPLINEƒTop�line�of�virtual�screen+‰XREF„BOTLINEƒBottom�line�of�virtual�screen,‰XREF„LEFTCOLƒLeft�collumn�of�virtual�screen.‰XREF„RIGHTCOL‚Right�collumn�of�virtual�screen 9‰XREF†FEEDER„Address�of�subroutine�to�give�data�to�driver=‰XREF†FEEDER_ADDRESS†Address�of�data�buffer�to�give�to�FEEDER,‰XREF†FEEDER_COUNTˆ#�of�bytes�in�data�buffer ‰XREF†DUP_CHAR (‰XREF†KB_LOCK�Key�board�lock/unlock�flag 2‰XREF†RABSOLUTŒOutchs�read�absolute�entry�address. 0‰XREF†RING_BELL‹Flag�set�when�$07�is�detected�in%*§order�to�ring�the�bell�in�KEYBRD.AG‰PAGE .SCREENƒEQU‡$F17000�Base�address�of�display�RAM0CRTCADD‚EQU‡$F1A021�Address�register�of�the�CRTC-CRTCREG‚EQU‡$F1A023�Register�file�of�the�CRTC)EPCIBASE�EQU‡$F1A031�Base�address�of�EPCIKBDADDR‚EQU‡$0C$LFCHARƒEQU‡$0A‘ASCII�line�feed�char.0START_OF_DATA�EQU‚$DDŽ'Start�of�data'�indicator./END_OF_DATA�EQU„$DE‘End�of�write/read�indicator$FALSE„EQU‡0“Indicate�condition�false#TRUE…EQU‡-1’Indicate�true�condition"CLEARTAB�EQU‡$18‘Clear�tab�command#SPACE„EQU‡$20ŽASCII�space�character#ESC_CHAR‚EQU„$1B�ASCII�escape�char.+END_OF_FIELD�EQU�$F9�End�of�field�indicator6INIT_TAB‚EQU„10‘Initial�tab�spacing.‚The�reset�command#*§($F1)�will�put�tabs�on�the�screen*§with�this�spacing.* *ˆFAC�EQUATES*3PROTECT_FAC�EQU„$C5‡Protect�fac�with�intensity�code3DISPLAY_FAC�EQU„$44‡Display�fac�with�intensity�code/BLINK_FACƒEQU„$A5‡Blink�fac�with�intensity�code7UNDERLINE_FAC�EQU‚$55‡Underline�fac�with�intensity�code9INVERSE_FAC�EQU„$4D‡Inverse�video�fac�with�intensity�code!NODIS_FACƒEQU„$05‡Set�non-display** Register use:*’D0.L�=�general�use+*’D1.W�=�absolute�address�of�initial�cursor/*’D2.W�=�chracter�to�decode�and�word�to�display)*’D3.W�=�lines�per�virtual�screen�counter+*’D4.W�=�characers�per�virtual�line�counter *’D5.L�=�bytes�per�absolute�line*’D6.L�=�bytes�per�virtual�line*’D7.L�=�general�use-*’A0.L�=�address�of�cursor�in�the�display�RAM*’A1.L�=�Address�of�FACS*’A2.L�=�Address�of�S.LINE*’A3.L�-�General�use*  ‰PAGE ‰SECTIONƒ11  **ˆDEFINE�STORAGE*=ESC_FLAG‚DC.BƒFALSEŽThis�flag�is�true�if�someone�has�reserved(*§a�char�and�the�first�char�received�was&*§an�ESC.‚In�that�case�we�wait�for�the*§next�char�and�set�its�bit�7.:CHAR_RESERVED�DC.B�FALSE…Next�character�reserved�indicator(SAVE_CHAR…DS.B�1‰Save�area�for�character-SAVE_CURSORƒDS.L�1‰Current�cursor�ram�addressBCHAR_OWNER„DS.L�1‰Address�of�routine�that�owns�next�incoming�char.5XTCHBUF‚DS.W†162‡Scratch�buffer�for�feeder�subroutineEDIT_FLAG�DC.B…FALSE=COL_CNT‚DS.L†1‰Current�column�number,�used�in�set�tab�routine?PRO_FIELD�DC.B…FALSE…This�field�used�to�determine�where�to�stop(* when�a�protected�field�is�encountered.‰DS.W†00SAVEFACS‚DC.W…0‰FACS�saved�during�write�absolute=LASTFACƒDC.B…FALSE…Set�last�character�processed�to�not�a�FAC.8NUMBER_LINES�DC.Wƒ25‡Number�of�lines�to�clear�on�screen.‰PAGE POUTCHS‚DS.W†0 HAVE_CHAR‰MOVE.B„D0,D2�D2.B�=�Character ** Now find out what to do*:‰TST.B…CHAR_RESERVED‡Byte�is�set�if�a�routine�expects�more*ªthan�a�single�character‰IF��THEN.S 8ŠTST.B‚ESC_FLAG‹If�the�last�char�we�received�was�an�ESC,ŠIF…�THEN.Sˆ* 2ŠSF…ESC_FLAG‹Clear�the�'last�char�was�an�ESC'�flag5ŠBSETƒ#7,D0Žand�set�bit�7�in�D0�and�D2�(both�of�which-ŠBSETƒ#7,D2Žhold�the�char�following�the�ESC). (ŠELSE.S”Else�(last�char�was�not�an�ESC), 6ŠIF.B�D0��#ESC_CHAR�THEN.S�If�this�char�is�an�ESC,0ŠST…ESC_FLAG‹set�the�'last�char�was�an�ESC'�flagŠBRA„RETURN�and�exit.ŠENDI–* ŠENDI /‰SF�CHAR_RESERVEDŽReset�character�reserved�flag? :‰MOVE.L�CHAR_OWNER,A3ŠGet�the�address�of�the�routine�which*¨process�this�character'‰JMP�(A3)–Go�process�incoming�character ‰ENDI *(*ˆFind�entry�in�table�for�this�character*OUTCH1(‰MOVE†D2,D0…Reset�upper�part�of�register5‰ADD‡D0,D0…Multiply�by�two�because�table�is�word�wide+‰MOVE†JUMPTABL(PC,D0),D0�Get�offset�address2‰JMP‡JUMPTABL(PC,D0)„Go�process�incoming�character‰PAGEJUMPTABL,ŠDC.WƒRETURN-JUMPTABL„$00�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$01�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$02�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$03�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$04�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$05�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$06�--�Illegal�--�exit ŠDC.WƒBELL-JUMPTABL†$07�--�Bell.#ŠDC.WƒBS-JUMPTABLˆ$08�--�Backspace.(ŠDC.WƒHT-JUMPTABLˆ$09�--�Horizontal�tab.%ŠDC.WƒDOWN-JUMPTABL†$0A�--�Line�feed.&ŠDC.WƒUP-JUMPTABLˆ$0B�--�Vertical�tab.&ŠDC.WƒRIGHT-JUMPTABL…$0C�--�Form�feed.)ŠDC.WƒCR-JUMPTABLˆ$0D�--�Carriage�return.,ŠDC.WƒRETURN-JUMPTABL„$0E�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$0F�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$10�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$11�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$12�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$13�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$14�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$15�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$16�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$17�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$18�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$19�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1A�--�Illegal�--�exit!ŠDC.WƒESC-JUMPTABL‡$1B�--�Escape.,ŠDC.WƒRETURN-JUMPTABL„$1C�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1D�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1E�--�Illegal�--�exit,ŠDC.WƒRETURN-JUMPTABL„$1F�--�Illegal�--�exit,ŠDC.WƒDISPLAY-JUMPTABLƒ$20�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$21�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$22�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$23�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$24�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$25�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$26�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$27�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$28�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$29�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$2F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$30�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$31�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$32�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$33�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$34�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$35�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$36�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$37�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$38�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$39�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$3F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$40�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$41�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$42�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$43�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$44�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$45�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$46�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$47�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$48�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$49�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$4F�--�Display�as�is.? ,ŠDC.WƒDISPLAY-JUMPTABLƒ$50�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$51�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$52�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$53�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$54�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$55�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$56�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$57�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$58�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$59�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$5F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$60�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$61�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$62�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$63�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$64�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$65�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$66�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$67�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$68�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$69�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$6F�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$70�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$71�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$72�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$73�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$74�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$75�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$76�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$77�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$78�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$79�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7A�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7B�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7C�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7D�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7E�--�Display�as�is.,ŠDC.WƒDISPLAY-JUMPTABLƒ$7F�--�Display�as�is.'ŠDC.WƒRETURN-JUMPTABL„$80�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$81�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$82�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$83�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$84�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$85�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$86�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$87�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$88�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$89�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8A�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8B�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8C�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$8D�--�Ignore�it.4ŠDC.WƒSTART_EDITMODE-JUMPTABLƒ$8E�--�Start�edit�mode1ŠDC.WƒSTOP_EDITMODE-JUMPTABL„$8F�--�End�edit�mode'ŠDC.WƒRETURN-JUMPTABL„$90�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$91�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$92�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$93�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$94�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$95�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$96�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$97�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$98�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$99�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9A�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9B�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9C�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9D�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9E�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$9F�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A0�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A1�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A2�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A3�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A4�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A5�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A6�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A7�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A8�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$A9�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AA�--�Ignore�it.@ 'ŠDC.WƒRETURN-JUMPTABL„$AB�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AC�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AD�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AE�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$AF�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B0�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B1�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B2�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B3�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B4�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B5�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B6�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B7�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B8�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$B9�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BA�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BB�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BC�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BD�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BE�--�Ignore�it.'ŠDC.WƒRETURN-JUMPTABL„$BF�--�Ignore�it.%ŠDC.WƒHOME-JUMPTABL†$C0�=�Cursor�home!ŠDC.WƒUP-JUMPTABLˆ$C1�=�Cursor�up%ŠDC.WƒDOWN-JUMPTABL†$C2�=�Cursor�down&ŠDC.WƒSEEKL-JUMPTABL…$C3�=�Cursor�left'ŠDC.WƒRIGHT-JUMPTABL…$C4�=�Cursor�right$ŠDC.WƒC5-JUMPTABLˆ$C5�=�Write�cursor#ŠDC.WƒC6-JUMPTABLˆ$C6�=�Read�cursor(ŠDC.WƒSPAGE-JUMPTABL…$C7�=�Set�page�mode*ŠDC.WƒRPAGE-JUMPTABL…$C8�=�Set�scroll�mode0ŠDC.WƒSETTOP-JUMPTABL„$C9�=�Set�top�display�line5ŠDC.WƒSETBOTOM-JUMPTABL‚$CA�=�Set�bottom�display�line5ŠDC.WƒSETLEFT-JUMPTABLƒ$CB�=�Set�left�display�collumn7ŠDC.WƒSETRIGHT-JUMPTABL‚$CC�=�Set�right�display�collumn-ŠDC.WƒSETPROT-JUMPTABLƒ$CD�=�Set�protect�mode,ŠDC.WƒWABSOLUT-JUMPTABL‚$CE�=�Write�absolute+ŠDC.WƒREADABSO-JUMPTABL‚$CF�=�Read�absolute5ŠDC.WƒICHAR-JUMPTABL…$D0�=�Insert�character�at�cursor5ŠDC.WƒDCHAR-JUMPTABL…$D1�=�Delete�character�at�cursor,ŠDC.WƒKEYENAB-JUMPTABLƒ$D2�=�Enable�keyboard.ŠDC.WƒKEYDSABL-JUMPTABL‚$D3�=�Disable�keyboard?ŠDC.WƒEEPAGE-JUMPTABL„$D4�=�Erase�all�unprotected�to�end�of�pag?ŠDC.WƒEELINE-JUMPTABL„$D5�=�Erase�all�unprotected�to�end�of�lin3ŠDC.WƒINS_LINE-JUMPTABL‚$D6�=�Page�mode�insert�line3ŠDC.WƒDEL_LINE-JUMPTABL‚$D7�=�Page�mode�delete�line:ŠDC.WƒCLEAR-JUMPTABL…$D8�=�Erase�all�unprotected�in�screen&ŠDC.WƒSNDPAGE-JUMPTABLƒ$D9�=�Send�page'ŠDC.WƒSEEKFT-JUMPTABL„$DA�=�Forward�tab$ŠDC.WƒSEEKBT-JUMPTABL„$DB�=�Back�tab#ŠDC.WƒSETTAB-JUMPTABL„$DC�=�Set�tabŠDC.WƒRETURN-JUMPTABL„$DD�=ŠDC.WƒRETURN-JUMPTABL„$DE�=(ŠDC.WƒSEND_LINE-JUMPTABL�$DF�=�Send�line%ŠDC.WƒSBLINK-JUMPTABL„$E0�=�Set�blink'ŠDC.WƒRBLINK-JUMPTABL„$E1�=�Reset�blink-ŠDC.WƒSINVERT-JUMPTABLƒ$E2�=�Set�video�invert/ŠDC.WƒRINVERT-JUMPTABLƒ$E3�=�Reset�video�invert-ŠDC.WƒUPBRIGHT-JUMPTABL‚$E4�=�Set�half�bright/ŠDC.WƒDNBRIGHT-JUMPTABL‚$E5�=�Reset�half�bright)ŠDC.WƒSULINE-JUMPTABL„$E6�=�Set�underline+ŠDC.WƒRULINE-JUMPTABL„$E7�=�Reset�underline,ŠDC.WƒNONDISP-JUMPTABLƒ$E8�=�Set�non-display(ŠDC.WƒSETDISP-JUMPTABLƒ$E9�=�Set�display-ŠDC.WƒPROTECT-JUMPTABLƒ$EA�=�Set�protect�mode-ŠDC.WƒALLOW-JUMPTABL…$EB�=�Reset�protect�modeŠDC.WƒRETURN-JUMPTABL„$EC�=ŠDC.WƒRETURN-JUMPTABL„$ED�=ŠDC.WƒRETURN-JUMPTABL„$EE�=ŠDC.WƒRETURN-JUMPTABL„$EF�=ŠDC.WƒRETURN-JUMPTABL„$F0�=2ŠDC.WƒRESET24-JUMPTABLƒ$F1�=�Reset�24�line�screen.ŠDC.WƒRETURN-JUMPTABL„$F2�=ŠDC.WƒRETURN-JUMPTABL„$F3�=ŠDC.WƒRETURN-JUMPTABL„$F4�=ŠDC.WƒRETURN-JUMPTABL„$F5�=ŠDC.WƒRETURN-JUMPTABL„$F6�=2ŠDC.WƒRESET25-JUMPTABLƒ$F7�=�Reset�25�line�screen.ŠDC.WƒRETURN-JUMPTABL„$F8�=ŠDC.WƒRETURN-JUMPTABL„$F9�=ŠDC.WƒRETURN-JUMPTABL„$FA�=ŠDC.WƒRETURN-JUMPTABL„$FB�=ŠDC.WƒRETURN-JUMPTABL„$FC�=ŠDC.WƒRETURN-JUMPTABL„$FD�=ŠDC.WƒRETURN-JUMPTABL„$FE�=ŠDC.WƒRETURN-JUMPTABL„$FF�=  ‰PAGE*'* $7F = DLE, delete character at cursor*DLE'‰AND.W…#$FF80,(A0)‰Null�character�space)‰OR.B†#$20,(A0)‹Space�character�at�cursor ‰BRA‡RETURN *** Send the command in D0 to this key board*'WKBD…OR.B†#KBDADDR,D0‰To�this�key�board‰MOVE.B„D0,EPCIBASE‰RTS ** 07 = CTRL G = BELL*�ADDED‚01/30/85*8* RING_BELL flag is set so that the interrupt routine in9* KEYBRD.AG will output an ALARM command to the keyboard.*BELL ‰STˆRING_BELL ‰BRA‡RETURN‰PAGE*@ * 08 = CTRL H = BS, back space*:* Cursor moves left to first unprotected column, with line* and page rollover.**BS SEEKL„EQU‡* ‰IF.B†PAGEFLAG��#TRUE�THEN.S‰IF.L†A0��S.SCRN�THEN.S9‰MOVE.L„E.SCRN,A0‹We�need�to�put�the�cursor�on�the�bottom7‰MOVE.L„A0,E.LINE‹line�and�update�the�beginning�and�end+‰MOVE.L„A0,S.LINE‹of�current�line�pointers.‰SUB.L…D6,S.LINE ‰BRA‡WRITCRSR‰ENDI‰IF.L†A0��S.LINE�THEN.S3‰SUB.L…D5,A0�Find�the�beginning�address�of�the�line:‰MOVE.L„A0,S.LINE‹above�the�cursor�and�update�the�pointer.0‰ADD.L…D6,A0�Find�the�ending�address�of�the�line:‰MOVE.L„A0,E.LINE‹above�the�cursor�and�update�the�pointer. ‰BRA‡WRITCRSRŒUpdate�the�cursor.‰ENDI0‰SUBQ.L„#2,A0�Move�the�cursor�left�one�position.‰BRA‡WRITCRSRŒ*‰ENDI!‰MOVE.L„A0,A3�Set�loop�terminator‰REPEAT‰IF.L†A0��S.SCRN�THEN.S6‰MOVE.L„E.SCRN,A0‹If�back�to�start�go�to�end�of�screen1‰MOVE.L„A0,E.LINE‹Set�end�of�current�virtual�line3‰MOVE.L„A0,S.LINE‹Set�start�of�current�virtual�line‰SUB.L…D6,(A2)�*‰ELSE.S‰IF.L†A0��S.LINE�THEN.S'‰SUB.L…D5,A0�Set�start�of�previous�line‰MOVE.L„A0,S.LINE‹*$‰ADD.L…D6,A0�Set�end�of�virtual�line.‰MOVE.L„A0,E.LINE‹and�A0�points�to�end�of�line‰ENDI‰ENDI&‰TST‡-(A0)�Is�current�spot�unprotected#‰BMI.S…SEEKL1ŽBranch�if�unprotected1‰TST.B…1(A0)�If�we�are�at�end�of�line�move�cursor*¦back�another�position.‰IFˆ�THEN.S‰*‰BRA.S…SEEKL1Ž*‰ELSE.S2‰BRA.S…SEEKL2ŽGo�update�cursor�because�we�found�an*¦unprotected�spot.‰ENDISEEKL1‰UNTIL.LƒA0��A35‰MOVE.L„S.SCRN,A0‹Put�cursor�in�home�position--no�un-$*¦protected�areas�in�current�screen.SEEKL2 ‰BRA‡WRITCRSR‰PAGE*"* 09 = CTRL I = HT, horizontal tab*2* Seek a TAB at an un-protected spot to the right,* with line and page rollover.**HT$SEEKFTƒEQU‡*“Seek�a�tab�to�the�right2‰SFˆPRO_FIELD‹Have�not�encountered�protected�field!‰MOVE.L„A0,A3�Set�loop�terminator*‰ADDQ.L„#2,A0�Get�off�of�current�character‰BRA.S…SEEKFT2‰REPEAT(‰TST‡(A0)+�Is�current�location�protected!‰BPL.S…SEEKFT1�Branch�if�it�isn't*3*ˆCursor�is�in�a�protected�field�--�check�to�see�if2*ˆencountered�earlier�and�we�are�still�in�it�or�if*ˆthis�is�the�first�time*0‰TST.B…PRO_FIELD‹First�time�in�protected�field�?‰IF��THEN.S0‰STˆPRO_FIELD‹Tell�world�we�have�encountered�the$*©protected�field�for�the�first�time.‰BRA.S…SEEKFT2�Now�move�out�of�protected�field‰ENDI7‰BRA.S…SEEKFT2�Still�in�protected�field�continue�search*©for�first�unprotected�field. SEEKFT16‰TST.B…PRO_FIELD‹If�this�is�an�unprotected�field�check$*¨to�see�if�we�passed�through�a�pro-"*¨tected�field�first.‚The�tab�must"*¨move�out�of�current�field�to�the*¨next�unprotected�field.‰IF��THEN.S/‰TST.B�-1(A0)’We�cannot�stop�on�an�end�of�line.‰IF��THEN.S�*/‰BRA.S‚SEEKFT2�Branch�if�we�are�at�end�of�line.‰ENDI'ŠSUBQ.L�#2,A0‘Adjust�the�cursor�address0ŠBRA�WRITCRSR‘Found�our�tab�stop�which�really�is"*ªjust�an�unprotected�field�to�the*ªright�of�the�current�field.‰ENDISEEKFT2ŒIF.L‚A0��E.LINE�THEN.S“ADD.L‚D5,A0ˆDo�line�rollover8“MOVE.L�A0,E.LINE„Add�absolute�#�of�character�for�e.line2“SUB.L‚D6,A0ˆS.line�=�e.line�-�#�char�in�virt�line“MOVE.L�A0,S.LINE„*7ŒST�PRO_FIELD‰Because�we�went�off-line�fake�a�protected*¦field�hit�so�cursor�will�stop‰ENDI‰IF.L�A0��E.SCRN�THEN.S"ŒMOVE.L�S.SCRN,A0…Do�page�rollover'ŒMOVE.L�A0,S.LINE…Set�new�start�of�line%ŒMOVE.L�A0,E.LINE…Set�new�end�of�lineŒADD.L‚D6,E.LINE…*7ŒST�PRO_FIELD‰Because�we�went�off-line�fake�a�protected*¦field�hit�so�cursor�will�stop‰ENDISEEKFT3‰UNTIL.LƒA0��A3 ‰BRA�RETURN‰PAGE***�0D…Carriage�return*2* Position cursor at left most unprotected column.** FAC's are reset.*CR‰AND.W…#$4400,(A1)‰Reset�FACs‰MOVE.L„S.LINE,A0‹Start�of�line ‰BSR‡SEEKR ‰BRA‡WRITCRSR * *�1B…Escape*(* Set high bit of next character output.* ESC†EQU‡*#‰BSR‡GET_CHARŒNeed�anoter�character ‰BSET†#7,D0‰BRA‡HAVE_CHAR‰PAGE*A *�$8E„START�EDIT�MODE*START_EDITMODE ‰BSR‡GET_CHAR‰IF.B�D0��#$FF�THEN.S‰MOVE†#$FFFF,DUP_CHAR‰ELSE.S‰MOVE†D2,DUP_CHAR‰ENDI ‰STˆEDIT_FLAG ‰SFˆPAGEFLAG ‰SFˆPROMODE ‰BRA‡RETURN**�$8F‚STOP�EDIT�MODE* STOP_EDITMODE%‰SFˆEDIT_FLAG‹Turn�off�edit�mode�flag ‰BRA‡RETURN‰PAGE**�$C0„cursor�home*A* Cursor moves to top left corner of screen, seeks an unprotected* space to the right.* HOME…EQU‡* ‰MOVE.L„S.SCRN,A0‹Top�left�space6‰MOVE.L„A0,S.LINE‹Modify�start�and�end�of�current�line‰MOVE.L„A0,E.LINE‰ADD.L…D6,4(A2) ‰BSR‡SEEKR ‰BRA‡WRITCRSR * * C1 = Up*C* Cursor moves up one line in same column, seeks unprotected column+* to the left, with line and page rollover.**(UP‡SUB.L…D5,A0�Same�column�in�line�above3‰SUB.L…D5,(A2)�Modify�start�and�end�of�current�line‰SUB.L…D5,4(A2)‰CMP.L…S.SCRN,A0‹Out�of�screen?‰BGE.S…UP.1�No,�do�it4‰MOVE.L„A0,D0�Roll�screen�over--find�cursor�position(*¦relative�to�the�beginning�of�the�line.4‰SUB.L…S.LINE,D0‹D0�<--�cursor�offset�into�this�line,‰MOVE.L„E.SCRN,A0‹Point�to�bottom�of�screen.*‰MOVE.L„A0,S.LINE‹Update�start/end�of�line‰SUB.L…D6,(A2)‰MOVE.L„A0,E.LINE%‰MOVE.L„S.LINE,A0‹Position�the�cursor‰ADD.L…D0,A0�* +UP.1…EQU‡*“Modify�start/end�of�current�line ‰LEA‡2(A0),A0 ‰BRA‡SEEKL‰PAGE* * C2 = Down*A* Cursor seeks an unprotected spot to the right, starting at same+* collumn on next line, with page rollover.* DOWN…EQU‡*%‰ADD.L…D5,A0�Same�column�on�next�line/‰ADD.L…D5,(A2)�Modify�start/end�of�current�line‰ADD.L…D5,4(A2)#‰CMP.L…E.SCRN,A0‹Out�of�the�screen?‰BLT.S…DOWN1�No,�do�it4‰MOVE.L„A0,D0�Roll�screen�over--find�cursor�position(*¦relative�to�the�beginning�of�the�line.4‰SUB.L…S.LINE,D0‹D0�<--�cursor�offset�into�this�line/‰MOVE.L„S.SCRN,A0‹Point�to�beginning�of�screen.'‰MOVE.L„A0,S.LINE‹Update�line�pointers.‰MOVE.L„A0,E.LINE‹*‰ADD.L…D6,4(A2)Œ* ‰ADD.L…D0,A0�Position�the�cursorDOWN10‰BSR‡SEEKR�Seek�an�unprotected�spot�to�the�right ‰BRA‡WRITCRSR *** C3 = cursor left, same as back space 08.* * * C4 = Right*D* Seek an unprotected space to the right with line and page rollover*RIGHT!‰MOVE.L„A0,A3�Set�loop�terminator'‰ADDQ.L„#2,A0�Get�off�of�current�column ‰BRA.S…RIGHT1‰REPEAT-‰TST.W…(A0)+�Pointing�to�unprotected�column�?‰IF��THEN.S/‰TST.B…-1(A0)ŽWe�cannot�stop�on�an�end�of�line.$‰IFƒ�THEN.SŽEnd�of�line�is�a�00. ‰BRA.S‚RIGHT2‰ENDI'‰SUBQ.L„#2,A0�Adjust�for�auto�increment%‰BRA‡WRITCRSRŒUpdate�cursor�on�screen‰ENDIRIGHT1 ‰IF.B‚PAGEFLAG��#TRUE�THEN.S “BRA�WRITCRSR‰ENDI‰IF.L�A0��E.SCRN�THEN.S ‰MOVE.L�S.SCRN,A0„Do�screen�wrap;‰MOVE.L�A0,S.LINE„Update�beginning�and�ending�line�pointers‰MOVE.L�A0,E.LINE„*‰ADD.L‚D6,E.LINE„*‰ENDI‰IF.L�A0��E.LINE�THEN.S‰ADD.L…D5,A0�Do�line�wrap!‰MOVE.L„A0,E.LINE‹New�end�of�line‰SUB.L…D6,A0�New�start�of�line‰MOVE.L„A0,S.LINE‹*‰ENDIRIGHT2‰UNTIL.LƒA0��A3)‰BRA‡RETURNŽNo�unprotected�so�leave�as�is‰PAGE*+*�$C5„Move�the�cursor�to�the�requested�spot*C5: 'ŠBSR„GET_CHAR‹D0.B�<--�the�line�#�char.'ŠMOVE.B�D0,SAVE_CHAR‡Save�it�for�later. )ŠBSR„GET_CHAR‹D0.B�<--�the�column�#�char.&ŠMOVEQ‚#0,D1ŽD1�<--�the�column�#�char.ŠMOVE.B�D0,D1Ž*1ŠSUB.B‚#$20,D1ŒAdjust�it�so�0�is�first�line,�etc. 4ŠCMP„LEFTCOL,D1‰Ensure�that�the�column�#�is�in�range2ŠBLO„RETURN�(�LEFTCOL�<�column�#�<�RIGHTCOL).‚Just0ŠCMP„RIGHTCOL,D1ˆignore�the�command�if�it�isn't. ŠBHI„RETURN�* 4ŠMOVEQ‚#0,D0ŽD0�<--�line�#�char�(saved�from�before).ŠMOVE.B�SAVE_CHAR,D0‡*1ŠSUB.B‚#$20,D0ŒAdjust�it�so�0�is�first�line,�etc. 2ŠCMP„TOPLINE,D0‰Ensure�that�the�line�#�is�in�range0ŠBLO„RETURN�(�TOPLINE�<�line�#�<�BOTLINE�).‚Just/ŠCMP„BOTLINE,D0‰ignore�the�command�if�it�isn't. ŠBHI„RETURN�* /ŠMULUƒD5,D0ŽD0�<--�start�addr�of�absolute�line.ŠADD.L‚#SCREEN,D0‰*"ŠADD„D1,D1ŽA0�<--�addr�of�cursor�=ŠADD.L‚D0,D1Ž*„2�*�column�#�+'ŠMOVE.L�D1,A0Ž*„start�of�absolute�line. A -ŠMOVEQ‚#0,D1ŽS.LINE�(start�of�virtual�line)�=7ŠMOVEƒLEFTCOL,D1‰*„2�*�left�column�of�virtual�display�+$ŠADD„D1,D1Ž*„start�of�absolute�line.ŠADD.L‚D0,D1Ž*ŠMOVE.L�D1,S.LINEŠ* +ŠADD.L‚D6,D1ŽE.LINE�(end�of�virtual�line)�=4ŠMOVE.L�D1,E.LINEŠ*„S.LINE�+�bytes�per�virtual�line.<‰IF.B‚PROMODE��#TRUE�THEN.SƒDo�a�seek�right�if�screen�is“BSR�SEEKR�in�protect�mode.‰ENDI ŠBRA„WRITCRSR‰PAGEC6‡EQU‡***�$C6„Read�the�cursor�position.**‚Input�parametersƒ:�none.*G*‚Registers�affected�:�D0.W�=�LLCC�(see�C5�for�an�explanation�of�LLCC).**+‰BSR‡READCRSRŒGet�cursor's�absolute�address‰DIVU†D5,D1�D1=00CC00LL‰SWAP†D1’D1=00LL00CC3‰LSL.W…#8-1,D1�D1=00LLCC00�(-1�to�convert�to�bytes)0‰ADD.L…#$DD2020DE,D1‡Add�the�offset�for�the�user*¦Set�start�data�and�end�data*‰LEA‡XTCHBUF(PC),A0†Set�up�for�FEEDER�call‰MOVE.L„D1,(A0)�Move�to�buffer,‰MOVE.W„#4,FEEDER_COUNT…Set�length�of�buffer:‰MOVE.L„A0,FEEDER_ADDRESSƒSet�address�of�buffer�for�FEEDER‰BSR‡FEEDERŽGive�data�to�driver‰BRA‡RETURNŽReturn�to�caller***�$C7„Set�page�mode.* SPAGE„EQU‡*‰MOVE.W„#-1,PAGEFLAG ‰SFˆPROMODE ‰BRA‡HOME **�$C8„Set�scroll�mode.* RPAGE„EQU‡*‰CLR.W…PAGEFLAG ‰SFˆPROMODE'‰MOVE.L„S.SCRN,A0�Do�a�scroll�mode�home‰MOVE.LƒA0,S.LINE‚*‰MOVE.LƒA0,E.LINE‚*‰ADD.L„D6,4(A2)ƒ*‰BRA‡WRITCRSR‚***�$CD„Set�protect�mode*SETPROT‰STˆPROMODEƒSet�protect�mode‰CLR‡PAGEFLAG‚Reset�page�mode-‰BRA‡HOME†Set�the�cursor�to�the�home�position‰PAGE***�$C9„Set�top�line�of�virtual�display�area*G* The top line is set by: 1. Bringing the cursor to the requested line,*œand�then�entering�an�ESC�I."*™2.�Entering�outch�with�D0.W=LLC5 SETTOPƒEQU‡* ‰BSR‡GET_CHARŒGet�next�character‰SUB.B…#$20,D2$‰CMP.W…BOTLINE,D2Š0=botline ‰BHI‡RETURN$‰MOVE.W„D2,TOPLINEŠStore�in�constantINITIT‰BSR‡CRTINIT�Re-configure�CRT&‰BRA‡HOME†Put�cursor�in�home�position. *-*�$CA„Set�bottom�line�of�virtual�display�area*"*�Same�as�C9�for�bottom�line‚ESC�J*SETBOTOM�EQU‡*‰BSR‡GET_CHARŒGet�line�number!‰SUB.B…#$20,D2�Adjust�line�number+‰CMP.W…LPERSCRN,D2‰lperscrn>botline>topline ‰BHS‡RETURN‰CMP.W…TOPLINE,D2 ‰BLO‡RETURN‰MOVE.W„D2,BOTLINE ‰BRA‡INITIT *5*�$CB„Set�left�display�column�of�virtual�screen‚ESC�K* SETLEFT‚EQU‡*‰BSR‡GET_CHARŒGet�left�column‰SUB.B…#$20,D2‰CMP.W…RIGHTCOL,D2 ‰BHI‡RETURN‰MOVE.W„D2,LEFTCOL ‰BRA‡INITIT‰PAGE*4*�$CC„Set�right�display�column�of�dispaly�area‚ESC�L*SETRIGHT�EQU‡*‰BSR‡GET_CHARŒGet�right�column‰SUB.B…#$20,D2,‰CMP.W…CPERLINE,D2‰cperlineleftcol ‰BHS‡RETURN‰CMP.W…LEFTCOL,D2 ‰BLO‡RETURN‰MOVE.W„D2,RIGHTCOL ‰BRA‡INITIT SEEIFIN‚EQU‡*-‰LSR.W…#8,D0�Check�to�see�if�the�user�defined%‰TST.W…D0’the�spot�in�the�second�byte ‰BNE.S…RTSIT*:* The routine will calculate the current line and collumn.+* Left collumn is #00, and top line is #00.*2*�InputŒA0.L�=�Address�of�cursor�in�display�screen**�Output‹A0.L�=�unchanged*’D0.L�=�00CC00LL&*™whereˆLL�=�Line�number,�top�line�=�0'*¦CC�=�Collumn�number,�left�collumn�=�0 GETSPOT‚EQU‡*‰CLR.L…D0’HSKP ‰MOVE.L„A0,D04‰SUB.L…#SCREEN,D0‰=Absolute�cursor�address�on�screen ‰LSR.W…#1,D0*‰DIVU†CPERLINE,D0‰The�quotiant=line�number RTSIT„RTS‰PAGE**�$CE„write�absolute* WABSOLUT: -ŠREPEAT”Wait�for�a�'start�of�data'�indicator.ŠBSR„GET_CHAR‹*ŠUNTIL.B�D0��#START_OF_DATA ,ŠMOVEƒ(A1),SAVEFACS†Save�current�FACS�in�use 'ŠBSR„GET_CHAR‹D0.B�<--�the�line�#�char.'ŠMOVE.B�D0,SAVE_CHAR‡Save�it�for�later. )ŠBSR„GET_CHAR‹D0.B�<--�the�column�#�char.&ŠMOVEQ‚#0,D1ŽD1�<--�the�column�#�char.ŠMOVE.B�D0,D1Ž*1ŠSUB.B‚#$20,D1ŒAdjust�it�so�0�is�first�line,�etc. 5ŠCMP„CPERLINE,D1ˆEnsure�that�the�column�#�is�in�range-ŠBHS„RETURN�(�LEFTCOL�<�column�#�<�RIGHTCOL). 4ŠMOVEQ‚#0,D0ŽD0�<--�line�#�char�(saved�from�before).ŠMOVE.B�SAVE_CHAR,D0‡*1ŠSUB.B‚#$20,D0ŒAdjust�it�so�0�is�first�line,�etc. /ŠCMP„LPERSCRN,D0ˆEnsure�the�line�#�is�in�range. ŠBHI„RETURN�*B BŠMOVE.L�A0,SAVE_CURSOR…Save�the�cursor�address�in�the�vertual�scrn /ŠMULUƒD5,D0ŽD0�<--�start�addr�of�absolute�line.ŠADD.L‚#SCREEN,D0‰*"ŠADD„D1,D1ŽA0�<--�addr�of�cursor�=ŠADD.L‚D0,D1Ž*„2�*�column�#�+'ŠMOVE.L�D1,A0Ž*„start�of�absolute�line. -ŠMOVEQ‚#0,D1ŽS.LINE�(start�of�virtual�line)�=7ŠMOVEƒLEFTCOL,D1‰*„2�*�left�column�of�virtual�display�+$ŠADD„D1,D1Ž*„start�of�absolute�line.ŠADD.L‚D0,D1Ž*ŠMOVE.L�D1,S.LINEŠ* +ŠADD.L‚D6,D1ŽE.LINE�(end�of�virtual�line)�=4ŠMOVE.L�D1,E.LINEŠ*„S.LINE�+�bytes�per�virtual�line. 7ŠST…CHAR_RESERVED†Set�up�to�receive�incoming�charactersŠLEA„WABS1(PC),A3‡*ŠMOVE.L�A3,CHAR_OWNER†*%ŠBRA„WRITCRSR‹Update�cursor�position.WABS1!ŠIF.B�D0��#END_OF_DATA�THEN.S6‰MOVE.L„SAVE_CURSOR,D0†Restore�virtual�screen's�S.LINE *°and�E.LINE!‰MOVE.L„D0,D1�Copy�cursor�address‰SUB.L…#SCREEN,D0*‰DIVU†BPERLINE+2,D0‡Find�line�cursor�is�on*¦remainder�=�position�in�line‰CLR‡D0’Forget�line�we�are�on‰SWAP†D0,‰SUB.L…D0,D1�we�now�know�the�absolute�s.line-‰MOVE†LEFTCOL,D0Šso�adjust�it�by�the�value�in‰ADD‡D0,D0�leftcol.‰ADD.L…D0,D1�*1‰MOVE.L„D1,S.LINE‹bingo�we�now�have�start�of�line-‰ADD.L…B.LINE,D1‹add�the�number�of�bytes/line%‰MOVE.L„D1,E.LINE‹and�set�end�of�line8‰MOVE.L„SAVE_CURSOR,A0†Set�cursor�back�to�virtual�screen/‰MOVE†SAVEFACS,(A1)‡Reset�FACS�for�current�line‰BRA‡WRITCRSRŒ*ŠENDIŠST…CHAR_RESERVED‰IF.B�D2��#$E0�AND.BŽD2��#$EB�THEN.S6‰TST.B…LASTFAC�See�if�the�last�character�processed�was*¦a�FAC.5‰IF‚�THEN.S�If�it�was�not�a�FAC�then�destroy�what'*¦is�currently�on�the�screen�because�it*¦could�be�another�FAC.:‰MOVE.B„#$FF,1(A0)ŠDestroy�current�character.�(if�a�FAC�is&*¦written�here�the�code�will�be�a�01.)‰ENDI3‰STˆLASTFAC�Tell�the�loop�we�have�been�here�before.‰BRA‚OUTCH1“Process�the�FAC.‰ENDI3‰TST.B…LASTFAC�If�the�last�character�was�a�FAC�then3‰IFƒ�THEN.SŽthe�cursor�has�not�been�updated,�so-‰ADD.L…#2,A0�let's�add�2�and�get�off�our�FAC.)‰SFˆLASTFAC�Last�character�was�not�a�FAC.‰ENDI8‰MOVE.W„LPERSCRN,D0‰FIND�THE�END�OF�THE�ABSOLUTE�DISPLAY ‰MULU†D5,D0�*‰ADD.L…#SCREEN,D0Š*5‰OR.W†FACS,D2�Write�the�current�character�to�the�scrn‰MOVE.W„D2,(A0)+Œ*‰IF.L†A0��D0�THEN.S&‰BRA‡RETURNŽExit�if�past�end�of�screen‰ENDI,‰BRA‡WRITCRSRŒUpdate�current�cursor�position **�$CF„read�absolute*+*ˆUses�the�read�absolute�routine�in�outchs.*READABSO�EQU‡* ‰JMP‡RABSOLUT *2* Convert the llcc value to a display RAM address.**ˆInputƒD0.W�=�llcc*ˆOutput‚A0.L�=�screen�address* CONVERT‚EQU‡*%‰MOVE.L„D6,-(A7)ŒGet�some�ellbow�room ‰CLR.L…D6 ‰MOVE.W„D0,D6‰AND.W…#$00FF,D0‰CMP.W…CPERLINE,D0 ‰BGT.S…CONRET‰LSR.L…#8,D6�D6.L=000000ll‰CMP.W…LPERSCRN,D6 ‰BGT.S…CONRET ‰MULU.W„D5,D6 ‰LSL.W…#1,D0 ‰ADD.B…D0,D6‰ADD.L…#SCREEN,D6 ‰MOVE.L„D6,A0CONRETƒMOVE.L„(A7)+,D6‰RTS‰PAGE*8*‚$D0„Insert�a�character�at�the�current�cursor�position.B*‰Starting�at�the�current�cursor�position,�characters�are�moved�to@*‰the�right�until�the�end�of�line�or�a�protected�field�is�hit.‚A>*‰space�is�put�in�the�current�cursor�position.‚The�cursor�does *‰not�move.*7ICHAR:„MOVEQ‚#SPACE,D0ŠInitialize�LAST�CHAR�to�a�space. .ICHAR1„TST„(A0)�If�this�position�is�protected,ŠBMI.S‚ICHAR3�get�out. 2ŠMOVEQ‚#$7F,D1ŒD1�<--�the�char�from�this�position.ŠAND„(A0),D1Œ*9ŠAND„#$FF80,(A0)ˆPut�the�LAST�CHAR�out�there�in�its�place.ŠOR…D0,(A0)+‹and�advance�to�the�next�position.1ŠMOVEƒD1,D0ŽSet�LAST�CHAR�to�the�char�we�just�got;ŠDBRAƒD4,ICHAR1Š(for�next�pass)�and�loop�until�end�of�line. ICHAR3„BRA„RETURN�Exit. *8*‚$D1„Delete�a�character�at�the�current�cursor�position.F*‰Starting�just�past�the�current�cursor�position,�characters�are�movedB*‰to�the�left�until�the�end�of�line�or�a�protected�field�is�hit.‚A@*‰space�is�put�in�the�final�modifiable�position.‚The�cursor�does%*‰not�move.‚The�entry�point�is�DCHAR.*�#TRUE�THEN.S ŠBRA�RETURNŠENDI6ŠMOVE.L�E.SCRN,A0ŠA0�<--�addr�just�past�end�of�screen. AŠWHILE.L�A0��E.LINE�DO.S‚While�A0�is�not�on�the�current�line, 6ŠMOVE.L�A0,A1ŽA1�<--�addr�just�past�end�of�line�above./ŠSUB.L‚D5,A1Ž*‡(D5�is�bytes�per�absolute�line.)0ŠMOVE.L�A0,-(SP)‹Save�the�address�for�this�line. 6ŠMOVEƒC.LINE,D0ŠD0�<--�#�of�chars�in�virtual�line�-�1.@INS_LIN1‚MOVEƒ-(A1),-(A0)ˆMove�all�words�(attribute�and�char)�in.ŠDBRAƒD0,INS_LIN1ˆthis�line�to�the�line�below. 3ŠMOVE.L�(SP)+,A0‹Restore�the�address�for�this�line.-ŠSUB.L‚D5,A0ŽA0�<--�address�for�next�line�up. ŠENDW (*§At�this�point�A0�is�the�addr�just�past&*§the�end�of�the�current�virtual�line.6ŠMOVEƒC.LINE,D0ŠD0�<--�#�of�chars�in�virtual�line�-�1.?INS_LIN2‚AND.B‚#$80,-(A0)‰Fill�the�current�line�with�spaces�and%ŠOR.Bƒ#$20,(A0)Šinnocuous�attributes.ŠMOVE.B�#$44,-(A0)‰*ŠDBRAƒD0,INS_LIN2ˆ*%*§At�this�point�A0�is�the�addr�of�the(*§beginning�of�the�current�virtual�line.,ŠBRA„WRITCRSR‹Go�set�the�new�cursor�address.   **�$D7‚DELETE�LINE*DEL_LINE‰IF.B�PROMODE��#TRUE�THEN.S ‰BRA�RETURN‰ENDI;‰MOVE.L„S.LINE,A0�Beginning�address�of�current�virtual�lineDELINE;‰MOVE.L„A0,A1…Calculate�the�address�of�the�beginning�of�the‰ADD.L…D5,A1…next�line.4‰MOVE†C.LINE,D0�Number�of�bytes�per�line�to�be�moved?‰CMP.L…E.SCRN,A1�See�if�move�from�address�is�passed�end�of�scrn-‰BHS.S…DELINE2ƒBranch�if�passed�end�of�screen2‰MOVE.L„A0,-(A7)‚Save�destination�address�on�stackDELINE1*‰MOVE.W„(A1)+,(A0)+�Move�line�up�on�screen‰DBRA†D0,DELINE1‚*,‰MOVE.L„(A7)+,A0‚Restore�destination�address'‰ADD.L…D5,A0‡Point�to�next�virtual�line,‰BRA.S…DELINE„Go�move�next�line�up�on�screenDELINE22‰MOVE.B„#$44,(A0)+ƒBlank�the�bottom�line�of�screen.‰AND.B…#$80,(A0)„Save�tab�stop�if�there�is�one+‰OR.B†#$20,(A0)+ƒSet�space�in�this�location‰DBRA†D0,DELINE2ƒ*9‰MOVE.L„S.LINE,A0„Set�cursor�to�beginning�of�current�line‰BRA‡WRITCRSR…* PAGE*+*�$D5„Erase�to�end�of�line‚(Page�mode�only)* EELINEƒEQU‡*!‰MOVE†FACS,-(A7)ŠSave�current�FAC‰IF.B�1(A0)��#01�THEN.S ‰MOVE.Bƒ#$44,FACSŒReset�to�FACS.‰ELSE.S)‰MOVE.LƒA0,A3�Save�current�line�position.‰WHILE.L‚A3��S.LINE�DO.S=‰IF.B…-1(A3)��#01�THEN.SƒFind�the�FAC�code�for�this�field.‰MOVE.Bƒ-2(A3),FACSŒPropogate�the�current�FAC.‰BRA.S„EELINE1‰ELSE.S5‰SUBQ.Lƒ#2,A3�Find�a�FAC�definition�or�the�start�of�a *¦*‚line.‰ENDI‰ENDW‰ENDIEELINE1‰WHILE.L‚A0��E.LINE�DO.S/‰MOVE.BƒFACS,(A0)+‹Propogate�FAC�to�end�of�line%‰AND.B„#$80,(A0)ŒSave�tab�information3‰OR.B…#$20,(A0)+‹Move�end�of�line�marker�by�writing*°spaces�to�the�end.‰ENDW%‰MOVE†(A7)+,FACSŠRestore�current�FAC. ‰BRA‡RETURN**�$D8„clear�screen,�cursor�home*C* All unprotected positions in display area are filled with spaces.* FAC's are not affected.* * Cursor moves to home position.** CLEAR„EQU‡*‰MOVE.L„S.SCRN,A0‹Start�at�homeC ‰MOVE.W„C.LINE,D4‹A�full�line"‰BSR.S…ERASE�Erase�all�unprotected‰BRA‡HOME�Put�cursor�at�home *%* Erase D4.W characters in D3.w lines* ERASE„EQU‡*‰IF.B�PROMODE��#TRUE�THEN.S‰TST.W…(A0)+�Is�it�protected?‰BMI.S…ERASE1ŽYes,�keep�looking'‰AND.W…#$FF80,-2(A0)‡Preserve�the�FAC's!‰OR.W†#$0000,-2(A0)‡Write�a�space‰ELSE.S,‰AND‡#$0080,(A0)‰Reset�FAC�but�save�tab�info,‰ORˆ#$4400,(A0)+ˆWrite�end�of�line�character‰ENDI/ERASE1ƒDBRA†D4,ERASEŒRepeat�for�D4.w�characters)‰MOVE.W„C.LINE,D4‹Reset�character�counter$‰ADD.W…PB.LINE,A0ŠStart�of�next�line$‰DBRA†D3,ERASEŒRepeat�for�D3.w�lines‰RTS‰PAGE**�$D9„SEND�PAGE**ˆSend�all�unprotected�fields*SNDPAGE9‰MOVE.L„S.SCRN,A0ŠStart�at�beginning�of�the�virtual�scrn.2‰MOVE.L„A0,-(A7)ŒSave�beginning�line�adr�on�stack.%‰LEA‡XTCHBUF,A1ŠFeeder�needs�a�buffer9‰MOVE.L„A1,FEEDER_ADDRESSƒTell�feeder�where�his�buffer�isA‰MOVE.B„#START_OF_DATA,(A1)+�Bracket�data�with�start�and�end�data:‰MOVE†#1,FEEDER_COUNT…Bump�number�of�characters�for�feeder*?*‡Find�all�unprotected�fields�on�the�screen�and�put�them�in�the**‡feeder�buffer�and�ship�them�to�the�host.*3‰MOVE…L.SCRN,D2ŽWe�only�want�to�do�1�screens�worth.0‰MOVE…C.LINE,D1ŒWe�do�1�screen�a�line�at�a�time.SNDPAGE1+‰TST.B…(A0)�Is�current�position�protected�?2‰BPL.S…SNDPAGE3ŒBranch�if�position�is�unprotected.#‰ADDQ.L„#2,A0�Go�to�next�character.%‰DBRA†D1,SNDPAGE1‰Do�the�entire�line.7‰ADD.L…D5,(A7)�Find�the�start�of�the�next�virtual�line.‰MOVE.L„(A7),A0�*4‰MOVE†C.LINE,D1‹Update�number�of�character�per�line.:‰DBRA†D2,SNDPAGE1‰Find�out�if�we�are�at�the�end�of�screen.6‰BRA.S…SNDPAGE4ŒEnd�of�screen�so�fix�feeder�buffer�and*¦ship�the�data�and�exit.SNDPAGE2,‰TST.B…(A0)�Is�current�character�protected�?3‰BPL.S…SNDPAGE3ŒBranch�if�character�is�unprotected.:‰MOVE.B„#END_OF_FIELD,(A1)+�Mark�end�of�unprotected�field.>‰ADDQ†#1,FEEDER_COUNT…Bump�the�number�of�chars.�for�the�driver4‰BRA.S…SNDPAGE6ŒGo�spin�through�the�protected�field.SNDPAGE33‰MOVEQ…#$7F,D0�The�char�is�in�bits�0-6�of�the�byte.‰AND.B…1(A0),D0$*¦Bit�7�is�the�'tab�stop'�bit�and�is*¦not�to�be�considered�"data"**‰BNE.S…SNDPAG35ŒBranch�if�not�end�of�line.7‰ADD.L…D5,(A7)�Find�the�next�virtual�line�beginning�adr‰MOVE.L„(A7),A0�*5‰MOVE†C.LINE,D1‹Update�number�of�characters�per�line.*B*…Check�to�see�if�we�were�in�a�protected�or�unprotected�field�when*…we�got�to�the�end�of�line.*!‰IF.B†PRO_FIELD��#TRUE�THEN.S6‰BRA.S…SNDPAGE7ŒContinue�processing�a�protected�field.‰ELSE.S*‰BRA.S…SNDPAG36ŒUnprotected�field�wrapped.‰ENDISNDPAG355‰MOVE.B„D0,(A1)+ŒMove�unprotected�character�to�feeder *ªbuffer.8‰ADDQ†#1,FEEDER_COUNT…Update�the�number�of�characters�to*ªgive�to�the�driver.&‰ADDQ.L„#2,A0�Point�to�next�character.)‰SFˆPRO_FIELD‹Last�field�was�unprotected.(‰DBRA†D1,SNDPAGE2‰Spin�through�the�line.5‰ADD.L…D5,(A7)�Find�the�beginning�of�the�next�virtual*©line.‰MOVE.L„(A7),A0�*0‰MOVE†C.LINE,D1‹Update�number�of�character/line.SNDPAG36:‰DBRA†D2,SNDPAGE2‰Check�to�see�if�we�are�at�the�end�of�the *ªscreen.C‰MOVE.B„#END_OF_FIELD,(A1)+‚Move�end�of�field�mark�to�feeder�buffer.‰ADDQ†#1,FEEDER_COUNT…Update�the�feeder�count.SNDPAGE4A‰MOVE.B„#END_OF_DATA,(A1)„Move�end�of�data�mark�to�feeder�buffer..‰ADDQ†#1,FEEDER_COUNT…Update�the�feeder�count. ‰BSR‡FEEDERŽShip�data�to�driver.$‰MOVE.L„(A7)+,A0ŒClean�up�the�stack.‰BRA‡RETURNŽExit.SNDPAGE5$‰TST.B…(A0)�Is�character�protected�?#‰BPL.S…SNDPAGE3ŒBranch�if�it�isn't.SNDPAGE6(‰ADDQ†#2,A0�Point�to�the�next�character.'‰STˆPRO_FIELD‹Last�field�was�protected.'‰DBRA†D1,SNDPAGE5‰Go�throught�the�line.7‰ADD.L…D5,(A7)�Find�the�next�virtual�line�beginning�adr‰MOVE.L„(A7),A0�*+‰MOVE†C.LINE,D1‹Update�characters�per�line.SNDPAGE7/‰DBRA†D2,SNDPAGE5‰Go�through�the�entire�screen.0‰BRA‡SNDPAGE4ŒWe�are�at�the�end�of�the�screen�so&*¦fix�up�feeders�buffer�and�ship�it�to*¦the�driver�then�exit.‰PAGE**�$DA„Forward�tab* * Same as HT* ** DB = BT, back tab*C =* Position cursor at first unprotected character to the left.** SEEKBTƒEQU‡*‰IF.L�A0��S.SCRN�THEN.S**ˆDO�SCREEN�WRAP*7‰MOVE.L„E.SCRN,A0�End�of�screen�becomes�new�end�of�line‰MOVE.L„A0,E.LINE�*2‰MOVE.L„A0,S.LINE�Update�the�start�of�line�pointer‰SUB.L…D6,S.LINE�*‰ENDI‰IF.L�A0��S.LINE�THEN.S**ˆDO�LINE�WRAP*‰SUB.L…D5,A0…New�start�of�line‰MOVE.L„A0,S.LINE�*‰ADD.L…D6,A0…New�end�of�line‰MOVE.L„A0,E.LINE�*‰ENDI**ˆFIND�AN�UNPROTECTED�FIELD*‰WHILE.L�A0��S.LINE�DO.S,‰TST‡-(A0)…Check�previous�character�position<‰BPL.S…SEEKBT1ƒBranch�if�unprotected�(hi�bit�of�word�is�off)‰ENDW**ˆSTART�OF�LINE�BUT�PROTECTED* ‰BRA‡SEEKBT*'*ˆFIND�PROTECTED�FIELD�OR�START�OF�LINE*SEEKBT1‰IF.L�A0��S.LINE�THEN.S‰TST‡(A0)†Is�location�protected‰BMI.S…SEEKBT2ƒBranch�if�it�is/‰BRA‡WRITCRSR‚Beginning�of�line�and�unprotectedSEEKBT2‰IF.L�A0��S.SCRN�THEN.S**ˆDO�SCREEN�WRAP*7‰MOVE.L„E.SCRN,A0�End�of�screen�becomes�new�end�of�line‰MOVE.L„A0,E.LINE�*2‰MOVE.L„A0,S.LINE�Update�the�start�of�line�pointer‰SUB.L…D6,S.LINE�*‰ENDI**ˆDO�LINE�WRAP*‰SUB.L…D5,A0…New�start�of�line‰MOVE.L„A0,S.LINE�*‰ADD.L…D6,A0…New�end�of�line‰MOVE.L„A0,E.LINE�*‰ENDI'‰TST‡-(A0)…Search�for�a�protected�field$‰BPL.S…SEEKBT1ƒBranch�if�unprotected&‰ADDQ.L„#2,A0…Adjust�for�the�decrement‰BRA‡WRITCRSR‚Update�cursor‰PAGE** DC = set tab* SETTABƒEQU‡*/‰CLR.L…COL_CNTƒInitialize�current�column�number‰BRA.S…SETTAB2SETTAB1:‰ADD.L…#2,COL_CNTŠUpdate�the�column�count�for�the�next�guy‰MOVE.L„COL_CNT,D0@‰IF.L‚D0��BPERLINE�THEN.S�Make�sure�we�don't�go�out�of�range<‰WHILE�D2��#LFCHAR�DO.S„If�out�of�range�discard�incoming/‰BSR�GET_CHAR’until�terminated�with�a�line�feed‰ENDW‰BRA‡RETURNŽExit‰ENDISETTAB2.‰BSR‡GET_CHAR‚Get�next�character�of�tab�string6‰MOVE†LPERSCRN,D3‰Set�loop�control�for�absolute�screen‰SUBQ†#1,D3�DBRA�adjustment9‰CMP.B…#LFCHAR,D2ŠEnd�of�string�is�indicated�by�line�feed‰BNE.S…SETTAB2A‹**C*‡LINE�FEED�CHARACTER�DETECTED,‚IF�IT�FOLLOWED�SET�TABS--�RESET�ALL*‡CURRENT�TABS*SETTAB42‰TST.L…COL_CNT�If�column�count�zero�then�line�feed*°followed�set�command‰IF��THEN.S+‰LEA‡SCREEN,A0‹Point�to�beginning�of�screen+‰MOVE†LPERSCRN,D5‰Get�#�of�lines�per�screen8‰MULU†CPERLINE,D5‰*�characters�per�line�=�#�of�character*©positions�on�screenCLRTAB‰AND.W…#$FF7F,(A0)+ˆReset�tab(‰DBRA†D5,CLRTAB‹Loop�until�end�of�screen‰ENDI ‰BRA‡RETURNSETTAB2A4‰MOVE.L„COL_CNT,A0ŠPoint�to�current�position�in�line‰ADD.L…#SCREEN,A0Š*-‰CMP.B…#SPACE,D2‹Is�this�a�filler�character�?5‰BEQ.S…SETTAB1�Get�next�character�if�current�is�space'‰CMP.B…#CLEARTAB,D2ˆClear�tab�request�?+‰BEQ.S…RESETTABŒBranch�if�clear�tab�request**„SET�TAB�REQUEST*SETTAB37‰BSET.B„#7,1(A0)ŒSet�tab�bit�in�high�nibble�of�the�dis-4‰ADD.L…D5,A0�played�char.�for�every�column�on�screen‰DBRA†D3,SETTAB3Š*‰BRA.S…SETTAB1RESETTAB1‰BCLR.B„#7,1(A0)ŒTurn�tab�bit�off�in�every�column‰ADD.L…D5,A0�*‰DBRA†D3,RESETTAB‰* ‰BRA‡SETTAB1‰PAGE**ˆ$DFƒSEND‚LINE* SEND_LINE"‰CLR‡D1ˆSet�protected�field�switch'‰LEA‡XTCHBUF,A1ŠPoint�to�feeder�buffer.:‰MOVE.L„A1,FEEDER_ADDRESSƒTell�feeder�where�his�buffer�is.:‰MOVE.B„#START_OF_DATA,(A1)+�Start�of�data�($DD)�required.5‰MOVE†#1,FEEDER_COUNT…Tell�feeder�he�has�1�character.5‰MOVE.L„S.LINE,A0ŠStart�at�the�beginning�of�the�line. ‰WHILE.LƒA0��E.LINE�DO ‰ADDQ.L„#1,A0…Bump�past�the�FAC.;‰MOVE.B„(A0)+,D0ƒFind�out�if�we�are�at�the�end�of�the�line.#‰AND.B…#$7F,D0„Could�be�a�tab�stop.‰IF��THEN.SSENDL1C‰MOVE.B„#END_OF_DATA,(A1)�End�of�line,�move�($DE)�to�feeder�buffer.1‰ADDQ†#1,FEEDER_COUNTƒUpdate�his�#�of�characters.&‰BSR‡FEEDER„Ship�buffer�to�the�driver.(‰BRA‡RETURN„Get�out�because�we�are�done.‰ENDI,‰CMP.B…#01,D0„Check�for�FAC�definition�code.‰IF��THEN.S‰MOVE.B�-1(A0),D0„Get�the�FAC"‰ROR.W…#2,D0…Get�to�the�right�bits*D *ˆCHECK�HALF�BRIGHT*&‰ROR.W…#1,D0…Half�bright�bit�on�or�off‰IF��THEN.S*‰MOVE.B�#$E5,(A1)+ƒSend�reset�half�bright.‰ELSE.S'‰MOVE.B�#$E4,(A1)+ƒSend�set�half�bright‰ENDI **ˆCHECK�VIDEO�INVERT*'‰ROR.W…#1,D0…Video�invert�bit�on�or�off‰IF��THEN.S)‰MOVE.B�#$E2,(A1)+ƒSend�set�video�invert.‰ELSE.S+‰MOVE.B�#$E3,(A1)+ƒSend�reset�video�invert.‰ENDI**ˆCHECK�UNDERLINE*$‰ROR.W…#1,D0…Underline�bit�on�or�off‰IF��THEN.S&‰MOVE.B�#$E6,(A1)+ƒSend�set�underline.‰ELSE.S(‰MOVE.B�#$E7,(A1)+ƒSend�reset�underline.‰ENDI* *ˆCHECK�BLINK* ‰ROR.W…#1,D0…Blink�bit�on�or�off‰IF��THEN.S"‰MOVE.B�#$E0,(A1)+ƒSend�set�blink.‰ELSE.S$‰MOVE.B�#$E1,(A1)+ƒSend�reset�blink.‰ENDI**ˆCHECK�DISPLAY*"‰ROR.W…#1,D0…Display�bit�on�or�off‰IF��THEN.S$‰MOVE.B�#$E9,(A1)+ƒSend�set�display.‰ELSE.S&‰MOVE.B�#$E8,(A1)+ƒSend�reset�display.‰ENDI**ˆCHECK�PROTECT*"‰ROR.W…#1,D0…Protest�bit�on�or�off‰IF��THEN.S$‰MOVE.B�#$EA,(A1)+ƒSend�set�protect.‰ELSE.S&‰MOVE.B�#$EB,(A1)+ƒSend�reset�protect.‰ENDI+‰ADDQ†#6,FEEDER_COUNT�Update�Feeders�count. ‰BRA.S…SENDL2‰ENDI1‰MOVE.B„D0,(A1)+‚Move�character�to�feeder�buffer.-‰ADDQ†#1,FEEDER_COUNT�Update�character�count.SENDL2‰ENDW4‰BRA‡SENDL1„End�of�line�encountered�--�time�to�quit.‰PAGE*F* The characters $E0-$EF will set or reset the field attribute bits in'* the XREFed, word sized register FACS.* FACS is defined as follows:**ˆD15�=�Set�for�protect*ˆD14�=�Set�for�display*ˆD13�=�Set�for�blink*ˆD12�=�Set�for�underline*ˆD11�=�Set�for�inverse�video*ˆD10�=�color/intensity�bit�1*ˆD09�=�color/intensity�bit�2*ˆD08�=�color/intensity�bit�3 *„D07-D00�=�0* ** E0 = set blink* SBLINKƒEQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BSET.B„#5,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$64,(A1)‹reset�all�other�FACS‰ENDI'‰MOVE.B„FACS,(A0)‹Update�FAC�on�screen. :‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac4‰ORˆ#$8000,(A0)‰Tell�world�the�FAC�code�is�protected*¦so�it�cannot�be�written�over.2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** E1 = reset blink* RBLINKƒEQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen9‰MOVE.B„#$01,(A0)‹Simulate�character�position�used�by�fac9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BCLR.B„#5,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$44,(A1)‹reset�all�other�FACS‰ENDI‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN** E2 = set video invert* SINVERT‚EQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BSET.B„#3,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$4C,(A1)‹reset�all�other�FACS‰ENDI'‰MOVE.B„FACS,(A0)‹Update�FAC�on�screen.:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** E3 = reset video invert* RINVERT‚EQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BCLR.B„#3,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$44,(A1)‹reset�all�other�FACS‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** E4 = Set half bright*UPBRIGHT�EQU‡*,‰MOVE.B„(A1),D2�Get�the�MSB�part�of�the�FACs'‰AND.B…#$F8,D2�Only�the�brightness�bits ‰OR.B†#$04,D2�Set�to�half�bright‰MOVE.B„D2,(A1)�*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen9‰MOVE.B„#$01,(A0)‹Simulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** E5 = Reset half bright*DNBRIGHT�EQU‡*,‰MOVE.B„(A1),D2�Get�the�MSB�part�of�the�FACsD '‰AND.B…#$F8,D2�Turn�off�brightness�bits‰OR.B†#$04,D2�Reset�half�bright‰MOVE.B„D2,(A1)�*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** E6 = set underline* SULINEƒEQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BSET.B„#4,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$54,(A1)‹reset�all�other�FACS‰ENDI'‰MOVE.B„FACS,(A0)‹Update�FAC�on�screen.:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN  ** E7 = reset underline* RULINEƒEQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BCLR.B„#4,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$44,(A1)‹reset�all�other�FACS‰ENDI#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac(‰ORˆ#$8000,(A0)‰Set�protect�bit�for�FAC.2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** E8 = set non display* NONDISP‚EQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BCLR.B„#6,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise%‰MOVE.B„#$4,(A1)Œreset�all�other�FACS‰ENDI'‰MOVE.B„FACS,(A0)‹Update�FAC�on�screen.:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN  ** E9 = reset non-display* SETDISP‚EQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BSET.B„#6,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$44,(A1)‹reset�all�other�FACS‰ENDI‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** EA = set protect* PROTECT‚EQU‡*9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BSET.B„#7,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$C4,(A1)‹reset�all�other�FACS‰ENDI'‰MOVE.B„FACS,(A0)‹Update�FAC�on�screen.:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac‰ORˆ#$8000,(A0)‰Set�protect�bit2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogated ‰BRA‡RETURN ** EB = reset protect* ALLOW„EQU‡*#‰MOVE.B„FACS,(A0)‹Put�FAC�on�screen:‰MOVE.B„#$01,1(A0)ŠSimulate�character�position�used�by�fac9‰IF.B�1(A0)��#01�THEN.S„If�we�are�on�a�FAC�definition8‰BCLR.B„#7,(A1)�just�OR�the�new�FAC�bit�into�current�FAC‰ELSE.S˜otherwise&‰MOVE.B„#$64,(A1)‹reset�all�other�FACS‰ENDI0‰ORˆ#$8000,(A0)‰Set�protect�bit�for�FAC�position2‰BSR‡PROFACŽCheck�to�see�if�FAC�must�be�propogatedRET.1„BRA‡RETURNŠPAGE* * F1 = reset*K* The display area is filled with spaces, all FAC's are reset, tabs are setL* every INIT_TAB spaces, the virtual screen is restored to its default size,* and the cursor is HOMEd.*RESET24?‰MOVE†#24,NUMBER_LINES�Set�up�the�small�screen�reset.�(24�line) RESET253ŠBSR„SCRNINIT‹Reset�all�the�parameters�to�defaults. *‚Fill�the�screen�with�blanks.4ŠLEA„SCREEN,A0ŠA0�<--�start�addr�of�absolute�screen.5ŠMOVEƒ#$4400,D2ŠD2�<--�default�attributes�and�a�space*§char�for�filling�the�screen.:ŠMOVEƒNUMBER_LINES,D5„D5�<--�#�of�characters�on�screen�-�1<ŠMULUƒCPERLINE,D5ˆ*‚=�lines�per�screen�*�chars�per�line�-�1. ŠSUBQƒ#1,D5Ž* �DO.SŠWhile�there�are�more�tabs�to�place, 5ŠBSETW‚#7,(A0)ŒSet�a�tab�in�this�position�and�advance%ŠADD.L‚#2*INIT_TAB,A0…INIT_TAB�chars. 0ŠSUBQƒ#1,D5ŽKeep�going�until�all�tabs�are�placedŠENDW–on�this�line. /ŠMOVEƒBPERLINE,A0ˆA0.L�<--�address�of�next�line7ŠADD.L‚(SP)+,A0‹*„=�addr�of�last�line�+�bytes�per�line. 0ŠSUBQƒ#1,D2ŽKeep�going�until�all�lines�are�done. ŠUNTIL‚�*ŠSF…EDIT_FLAGŠClear�edit�modeŠSF…PAGEFLAG‹page�modeŠSF…PROMODEŒand�protect�mode.;ŠMOVE.LƒB.LINE,D6ˆHome�routine�needs�bytes�per�virtual�lineBŠMOVE…#25,NUMBER_LINES�Reset�lines/screen�because�we�may�have�done*£a�24�line�reset.ŠBRA‡HOMEŒHome�the�cursor.‰PAGE* * DISPLAYL*---------------------------------------------------------------------------L* 1. Write the requested character in the display RAM at the current cursor.I* 2. Seek a non-protected spot to the right, with line and page rollover.6*„if�none�found,�sound�bell,�and�stay�at�current�spot.,* 3. Update the cursor register of the CRTC.** Input parameters:*------------------4* A0.L = current cursor posiotion in the display RAM8* D2.L = $000000XX, where XX is the requested character.0* D3.W = Maximum number of characters on screen.F* FACS = An XREFed, word sized register containing the FACs in effect.* DISPLAY‚EQU‡* ‰IF.B†PAGEFLAG��#TRUE�THEN.S“BRA.S�DISPLAY1‰ENDI/‰TST‡(A0)�Check�for�cursor�in�a�protected�field‰BPL.S…DISPLAY1ŒBranch�if�not*<*„Cursor�is�in�a�protected�field�--�we�can�only�accept�a�FAC*%‰TST.B…D2’Check�if�character�is�a�FAC‰IF��THEN.S �BRA�OUTCH1‰ENDI*�BSR.S�SEEKR�Not�a�FAC�so�seek�unprotectedDISPLAY1‰BSR‡PROFACŽPropogate�FAC:‰MOVE.B„FACS,(A0)+ŠMove�current�FACS�to�current�Screen�loc%‰AND.B…#$80,(A0)‹Keep�tab�information,‰OR.B†D2,(A0)+ŒWrite�character�to�the�screen‰IF.LƒA0��E.LINE�THEN.S1‰ADD.L‚D5,S.LINEŽUpdate�beginning�and�ending�line5‰ADD.L‚D5,E.LINEŽaddresses�because�we�are�about�to�go‰ENDIšto�the�next�line.3‰BSR.S…SEEKR�If�protected�find�an�unprotected�char.#‰BRA‡WRITCRSRŒUpdate�current�cursor*?* Starting at the current display address, find an un-protected* spot to the right.* SEEKR„EQU‡* ‰IF.B�PAGEFLAG��#TRUE�THEN.S“RTS‰ENDI ‰MOVE.L„A0,A3�Set�up�termination‰IF.L†A0��S.LINE�THEN.S‰REPEAT D*„If�the�End�of�Line�character�is�in�the�first�character�position�ofB*„a�line,�while�we�are�in�protect�mode,‚the�cursor�is�moved�down�a*„line. ‰IF.B‚1(A0)��#00�THEN.S!‰ADD.L…D5,A0�Update�start�of�line‰MOVE.L„A0,S.LINE‹*+‰ADD.L…D5,E.LINE‹Update�end�of�virtual�line‰ELSE.S4‰BRA.S…SEEKR1ŽIf�End�of�Line�is�not�at�the�beginning'*¦of�the�line--go�ahead�and�seek�right.‰ENDI‰UNTIL.L�A0��A3‰RTS‰ENDI*7*„Find�an�unprotected�character�position�on�the�screen.*SEEKR1‰REPEAT‰IF.L†A0��E.SCRN�THEN.S9‰MOVE.L„S.SCRN,A0‹Wrap�the�search�for�an�unprotected�char2‰MOVE.L„A0,S.LINE‹Update�beginning�and�ending�adr.‰MOVE.L„A0,E.LINE‹*‰ADD.L…D6,E.LINE‹*,‰BRA.S…SEEKR2Ž*�Check�to�see�if�we�are�done.‰ENDI‰IF.L†A0��E.LINE�THEN.S#‰ADD.L…D5,(A2)�Update�start�of�line‰ADD.L…D5,4(A2)Œand�end�ofline‰MOVE.L„S.LINE,A0,‰BRA.S…SEEKR2Ž*�Check�to�see�if�we�are�done.‰ENDI2‰TST.W…(A0)+�Unprotected�fields�are�the�ones�where*¦bit�8�is�turned�off.‰IF��THEN.S5‰TST.B‚-1(A0)‘Make�sure�we�aren't�at�the�end�of�line.‰IF‚�THEN.S5‰ADD.LƒD5,S.LINE�In�protect�mode�the�cursor�cannot�be%*¦on�an�end�of�line--update�pointers.‰ADD.LƒD5,E.LINEƒ*‰MOVE.L‚S.LINE,A0�*3‰BRA.SƒSEEKR2�Go�make�sure�we�didn't�go�off-screen.‰ENDI3‰SUBQ.L„#2,A0�Character�not�protected�update�cursor*¦because�of�auto-increment.‰RTS‰ENDISEEKR2‰UNTIL.L�A0��A3*C*‚There�are�no�unprotected�fields�on�the�screen�so�home�the�cursor.**:‰MOVE.L„S.SCRN,A0‹Set�cursor�address�to�beginning�of�scrn.8‰MOVE.L„A0,S.LINE‹Update�beginning�and�ending�line�ptrs.‰ADD.L…D5,4(A2)Œ**‰RTS‡RETURNŽExit�no�unprotected�area�found‰PAGEWRITCRSR�EQU‡**E 9* Convert display RAM address to absolute cursor address,* and write into CRTC.** A0.L = Diaplay cursor address*/‰MOVE.L„A0,D1�Calculate�cursor�absolute�address‰SUB.L…#SCREEN,D1+‰LSR.L…#1,D1�To�take�care�of�attribute�area WRITEABS�EQU‡**/* Write the absolute cursor address in the CRTC* * D1.W = absolute cursor address*!‰MOVE.B„#$0F,CRTCADDˆPoint�to�R152‰MOVE.B„D1,CRTCREGŠStore�LSB�of�new�cursor�address ‰LSR.W…#8,D1�Position�upper�byte!‰MOVE.B„#$0E,CRTCADDˆPoint�to�R143‰MOVE.B„D1,CRTCREGŠSrore�MSB�of�new�cursor�register 6RETURNƒMOVEM.Lƒ(A7)+,D0-D7/A0-A3ƒRestore�user's�values‰RTS‰PAGEREADCRSR�EQU‡***‚Read�the�cursor�position*6*‚This�routine�is�for�internal�use,�and�is�not�XDEFed.)*‚For�an�external�control�routine�see�C6.**‚Input�parametersƒ:�none*>*‚Registers�affected�:�D1.W�=�Absolute�address�of�cursor�spot.&*—A0.L�=�Screen�RAM�address�of�cursor.*‰CLR.L…D1’HSKP!‰MOVE.B„#$0E,CRTCADDˆPoint�to�R14.‰MOVE.B„CRTCREG,D1ŠGet�current�cursor�position‰ROL.W…#8,D1�Put�it�in�MSB!‰MOVE.B„#$0F,CRTCADDˆPoint�to�R154‰MOVE.B„CRTCREG,D1ŠGet�lower�byte�of�cursor�position-‰LSL.W…#1,D1�Adjust�for�screen�RAM�operations ‰MOVE.L„D1,A0‰ADD.L…#SCREEN,A0‰RTS***GET_CHAR3‰STˆCHAR_RESERVED‡Reserve�next�character�for�caller>‰MOVE.L„(A7)+,CHAR_OWNER„Save�callers�return�address�for�later'‰BRA‡RETURNŽWait�for�the�next�character**ˆPROPOGATE�FAC�CODE*PROFAC‰IF.L‚A0��E.LINE�THEN.S ‰MOVE.L�A0,A10‰MOVE.B�(A1),D0�Get�the�FAC�which�will�be�moved.'‰ADDQ.L�#2,A1’Get�off�current�location.‰WHILE.L‚A1��E.LINE�DO.S2‰IF.Bƒ1(A1)��#00�THEN.S‚Check�for�end�of�line.7‰BRA.S‚PROFAC1�Branch�if�we�are�at�the�end�of�the�line.‰ENDI3‰CMP.B‚#1,1(A1)�Stop�if�we�are�on�a�FAC�definition.‰BEQ.S�PROFAC1A�*1‰MOVE.B�D0,(A1)�Move�the�FAC�code�to�end�of�line.‰ADDQ.L�#2,A1’*‰ENDW‰BRA.S�PROFAC1‰ENDIPROFAC1A)‰MOVE.L„A0,A1�Save�current�cursor�address‰IF.L†A1��S.LINE�THEN.S‰RTS›Exit�--�nothing�to�do‰ENDI1‰MOVE.B�-1(A1),D3ŽThere�could�be�a�tab�stop�here.%*¦Let's�turn�the�bit�off�before�we�go*¦on.‰AND.B�#$7F,D3‘*%‰IF‚‚THEN.SŽExit�--�nothing�to�do‰RTS‰ENDI‰WHILE.L�A1��S.LINE�DO.S@‰IF.B�-1(A1)��#01�THEN.SƒTry�to�find�where�a�FAC�was�defined‰MOVE.B�-2(A1),D0‰BRA.SƒPROFAC1‰ELSE.S ‰SUBQ.L‚#2,A1‰ENDI‰ENDW1‰MOVE.Bƒ#DISPLAY_FAC,D0‡Use�a�display�FAC�because*©a�01�was�not�found.8‰MOVE.BƒD0,FACSŽUpdate�the�FAC�for�the�rest�of�the�line.PROFAC1 ‰MOVE.L‚A0,A1‰WHILE.L�A1��S.LINE�DO.S'‰MOVE.B‚-(A1),D3�Get�previous�character,‰AND.Bƒ#$7F,D3�Check�if�line�end�or�tab�only‰BNE.S„PROFAC2,‰OR.B„#$20,(A1)�Remove�end�of�line�character!‰MOVE.B‚D0,-(A1)ŽUpdate�FAC�code.‰ENDWPROFAC2‰RTS‰ENDéééééF ǰ9TERMDRVƒIDNTƒ4,1‡VERSADOS�TERMINAL�DRIVER�WITH�TYPE-AHEAD6ŠTTL„TERMDRV:‚VERSADOS�TERMINAL�DRIVER�WITH�TYPE-AHEAD ŠLLENƒ120J**************************************************************************J**************************************************************************J**************************************************************************J***************************************************************************4*‰TERMDRV:‚VERSAdos�terminal�driver�with�type-ahead.*?*‰Purpose:‚VERSAdos�device�driver�to�handle�the�VME/10�keyboard *�&�screen.**‰Revision�history:4*‘1/15/85‚Added�code�to�return�error�code�to�user�in,*šhalt�I/O�parameter�block.�Return�of�$E6�in*šoriginal�I/O�parameter�block.ééééé ²¹Â%ÊGÒ6Ú6âTê=òOú6 B 1 : B "8 *< 2> :4 B9 J@ RC ZK b; jA rG zF ‚9 ŠD ’; šA ¢79*�01/30/85‚Modified‚KEYBRD.AG,�OUTCHS.SA,�POUTCHS.SA,�and.*šEDITMODE.SA‚to�use�the�BELL�in�the�keyboard.?*�10/10/84‚There�was�a�problem�if�any�other�board�in�the�system0*šis�configured�to�use�the�same�interrupt�level,-*šbecause�GET_CHAR�assumes�that�the�interrupt*šis�always�for�him.,*šFixed�GET_CHAR�to�send�back�both�Z�bit�and)*šV�bit�set�if�the�interrupt�is�not�ours,+*šso�that�IN_CHAR�will�pass�it�along�to�the1*šmain�interrupt�handler,�and�we�will�then�return4*što�CMR�with�the�carry�bit�cleared�to�indicate�that *šthe�interrupt�is�not�ours.†bwn;*‘2/�9/84‚Fixed�problem�with�READ�TERMINATOR�initialization*šin�subroutine�SETUP.6*‘7/19/83‚Changed�RESET�command�sent�to�OUTCHS�to�$F7.**‘6/�3/83‚Initial�writing�by�Steve�Franck.**‰RMS68K�routines�used: *�TR0$.RQPA *�TR0$.QEVENT*�TR0$.QEVENTI *�TR0$.LOGPHY *�TR0$.KILLER *�TR0$.GETTCB**‰Other�notes:6*�Currently�this�code�is�neither�ROMable�nor�position-*’independent.'*�Assemble�using�chain�file�TERMDRV.AF.*J**************************************************************************J**************************************************************************J**************************************************************************J**************************************************************************‰PAGE*F*‚To�assemble�this�code�for�its�proper�target�environment,�change�thisF ééA*‚equate,�which�will�serve�as�a�switch�in�conditional�assemblies.2*‚Valid�values�for�the�switch�are:‚'7201',�'EX/S'.(*‚FOR�NOW,�THIS�SWITCH�MUST�BE�'EX/S'!!!*ENVIRONMENT EQU 'EX/S' * *‚XDEF's.*8ŠXDEFƒGOT_CHAR‹Entry�point�for�driver�to�receive�a�char.7ŠXDEFƒCHECK_WORK‰Background�exec's�entry�point�to�check*§for�more�work. * *‚XREF's.*=ŠXREFƒSTOP_IT,UNSTOP…Device-specific�routines�to�stop�further&*§traffic�from�the�device�and�to�allow *§it�again. ‰IFEQ†ENVIRONMENT-'EX/S'"*§Subroutines�for�initializing�and'*§controlling�VME/10�keyboard�&�screen."ŠXREFƒINIT_KEYBOARD,IN_CHAR,OUTCHS‰ENDC  **‚Equate�files�included:**‰EQUSTR*‰EQUTCB*‰EQUCCB*‰VMES10.IOE.SA*‰NIO*‰LV5&*‰NEC7201‚only�if�ENVIRONMENT�=�'7201'*‰VMES10.TERMDRV.EQ*ŠNOLISTŠINCLUDE�9995.&.STR.EQŠNOLISTŠINCLUDE�9995.&.TCB.EQŠINCLUDE�9995.&.CCB.EQŠINCLUDE�9995.&.IOE.EQŠINCLUDE�9995.&.NIO.EQŠINCLUDE�9995.&.LV5.EQŠLISTŠPAGEO*********************************************************************************‰NOTES�ON�CODING�STANDARDS*O******************************************************************************* G*‚Because�this�is�an�I/O�driver,�speed�is�of�the�utmost�importance,�andG*‚as�a�result�tradeoffs�were�made�decreasing�the�straightforwardness�ofL*‚the�code�in�favor�of�less�time�spent�processing�interrupts.‚In�particular,F*‚the�interrupt�service�portion�of�this�driver�is�not�at�all�modular--H*‚some�'routines'�have�multiple�entry�and�exit�points,�and�return�is�not*‚always�to�the�caller.*G*‚One�visual�aid�used�which�may�save�you�some�work�is�the�use�of�labelsD*‚in�executable�code.‚Consider�the�following�sample�program�segment:*.*‰LABEL1:˜label�alone�on�line,�followed�by�':'*‘MOVE.B�......7*‰LABEL2:�ADD.B‚......Šlabel�not�alone,�followed�by�':'-*‰LABEL3‚CMP.B‚......Šlabel�not�alone,�no�':'*F*‚Each�way�of�writing�the�label�has�its�own�significance.‚LABEL1�marksC*‚the�beginning�of�a�logical�module,�and�nothing�falls�into�LABEL1.G*‚LABEL2�is�a�label�branched�to�from�outside�the�logical�module.‚LABEL3F*‚is�a�'local'�label,�branched�to�only�from�within�the�logical�module.  >*‚For�each�subroutine,�register�usage�is�specified�as�follows:**‰Entry:�A5�=�address�of�CCB**‰Exit:‚A0�=�garbage"*�A1�=�address�of�our�side�of�7201*G*‚The�entry�conditions�specify�only�the�REQUIREMENTS�of�the�routine.‚InI*‚other�words,�a�register�may�be�known�to�contain�a�particular�value,�butI*‚if�it�is�not�used�by�a�routine,�it�is�not�listed�as�an�entry�condition.J*‚The�exit�conditions�list�only�those�registers�which�CHANGE.‚In�the�aboveH*‚example,�the�fact�that�A5�is�not�listed�as�an�exit�condition�indicates"*‚that�it�still�points�to�the�CCB.*J*‚If�a�module�does�not�represent�a�subroutine�(that�is,�will�not�return�toK*‚the�code�it�was�entered�from),�the�exit�conditions�for�the�registers�will*‚not�be�specified.ŠPAGEO******************************************************************************** *‰EQUATES*O******************************************************************************* *,* EQUATES FOR SOME SPECIAL ASCII CHARACTERS.*'NUL†EQU‡$00‡Null�char.‚Usually�ignored..BEL†EQU‡$07‡Bell�char.‚Rings�bell�on�terminal.BS‡EQU‡$08‡Backspace�char.6LF‡EQU‡$0A‡Line�feed�char.‚Causes�cursor�to�move�down.=CR‡EQU‡$0D†Carriage�return�char.‚Moves�cursor�to�left�margin.SPACE„EQU‡$20‡Space�char.$L_ARROW‚EQU‡$3C‡Left‚arrow�char�'<'.%G R_ARROW‚EQU‡$3E‡Right�arrow�char�'>'.#BKSLASH‚EQU‡$5C‡Backslash�char�'\'.'CARET„EQU‡$5E‡Uparrow�(caret)�char�'^'.8DEL†EQU‡$7F‡Delete�char�(also�called�'rubout').‚Like�BS. $HI_CTLƒEQU‡$1F‡Highest�control�char. IBS_SP_BS�EQU�BS<<24+SPACE<<16+BS<<8‚Backspace,�space,�backspace�all�left-*§justified�in�32�bits. *?*‚Masks�delineating�all�recognized�(REC)�and�unrecognized�(UNR)(*‚attributes�(ATT)�and�parameters�(PAR).*‰IFEQ†ENVIRONMENT-'EX/S'BREC_ATTƒEQU„%1000001111000001‚1�bits�represent�defined�attributes.CUNR_ATTƒEQU„$FFFF-REC_ATT†The�1's�complement�of�that�are�undefined. BREC_PARƒEQU„%0111011111111111‚1�bits�represent�defined�parameters.CUNR_PARƒEQU„$FFFF-REC_PAR†The�1's�complement�of�that�are�undefined.‰ENDC ŠPAGE**‚Miscellaneous�equates.* *IOEVCD„EQU„1’Event�code�we�will�use�(I/O). ;BRK_LENƒEQU„300�#�of�milliseconds�to�maintain�break�signal. *I*‚This�is�a�semi-arbitrary�value�that�can�be�written�out�to�a�register�onH*‚some�device�and�then�read�back,�in�order�to�test�(in�a�very�small�way)C*‚the�device's�health.‚On�the�7201,�for�example,�this�is�written�to*‚the�vector�register�(2B).*TEST_VAL‚EQU„$17ŠPAGEK*****************************************************************************‰EQUATES�FOR�TRANSPARENT�MODE*K*************************************************************************** *F*‚Equates�describing�the�part�of�the�CSB�used�when�setting�TRANSPARENTH*‚MODE.‚We�pass�the�driver�the�address�of�our�branch�table�and�he�passesI*‚us�back�the�address�of�his�branch�table,�the�value�we�should�have�in�A5G*‚when�we�call�him,�and�the�SR�that�we�should�use.‚Actually,�we�may�useG*‚a�different�SR�as�long�as�the�supervisor�bit�is�set�and�the�interrupt9*‚level�is�not�lower�than�the�one�in�the�SR�he�passes�us.*7ŠOFFSET�IOSTTM�This�stuff�will�be�in�the�CSB�at�IOSTTM.9IOSTMU„DS.Bƒ4’Here�the�user�will�store,�before�making�the&*§CHANGE�DEFAULTS�call,�the�address�of*§his�table�of�branches. 7ŠOFFSET�IOSTTM�This�stuff�will�be�in�the�CSB�at�IOSTTM.9IOSTMD„DS.Bƒ4’the�addr�of�the�driver's�table�of�branches;/IOSTMA„DS.Bƒ4’the�value�the�driver�wants�in�A5;5IOSTMS„DS.Bƒ2’the�SR�with�the�MINIMUM�interrupt�level*§set. 5ŠOFFSET�0ŽThis�defines�the�user's�TM�interface�table.*£We�JSR�to�this�entry�when:#TM_RCA„DS.Bƒ4’...we�receive�a�char.7TM_TBE„DS.Bƒ4’...we�become�capable�of�another�transmit.2TM_BRK_RECV�DS.B�4’...we�detect�an�incoming�break.�