IMD 1.17: 25/11/2014 13:05:18 82VKXBVERDOS D* BT20:0 68K VERSADOS/RMS68K OBJECT 4.5 (DS,DD 96 tpi 5.1/4" DISK) REVISED: 04/22/86 DISK 20 OF 24  BT20 82VKXBVERDOS 0420²c-�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*$ KILL.DRIVER M300INT_ID,T0RQPA,A5,A4 !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$‰KILL.DRIVER�M300INT_ID,T0RQPA,A5,A4*.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¹EÁ6É!*ˆ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,SETPR025‚MOVE.L�(A7)+,A1ƒrestore�environment 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:+*>>>>>>>>>>>>>>>>>>>>>>>>>�10/28/85ƒREV�4.5+�MOVEM.L�D2-D7/A1-A6,-(A7)ƒsave�environment1�MOVE.L�QTAIL(A5),A6ƒget�pointer�to�current�entry(�CMPA.L�QHEAD(A5),A6‰is�the�queue�empty?(�BEQ.S�HLTERR�br�=�yes�(nothing�to�halt)4*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*9*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< *ˆ4/24/84ƒbwn**ˆFix�an�OOPS�!#*LEA.L�GPIBQEND,A0‹set�end-of-queue LEA.L GPIBQEND(A5),A0*>*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<**ˆLocate�t  he�command*1HLTC60 CMPA.L DCBQOFST(A6),A4 is this the device?�BEQ.S�HLTC80�br�=�yes*'�ADDA.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�environment,�MOVEQ�#ISTAOK,D1†set�good�error�return�code RTS*)*>>>>>>>>>>>>>>>>>>>>>>>�10/28/85‚REV�4.5.HLTERR�MOVE.B�#ISTAIF,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�update�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.7ŠTST.B‚BINTCNT(A5)ˆIf�we're�not�queueing�the�event�from*ŠIF…�THEN.Sˆwithin�the�interrupt�tour,0ŒMOVEQ‚#T0QEVNTT,D0…D0�<--�the�QEVNTT�directive.ŒTRAPƒ#0"ŒBRA.S‚OKEVENTŠIf�good,�go�return.1ŒMOVEM.L�(A7)+,D2-D7/A0-A6�Restore�the�registers.&ŒKILL.DRIVER�M300INT_ID,T0QEVNTT,A5,A4ŠELSE.S0ŒMOVEQ‚#T0QEVNTI,D0…D0�<--�the�QEVNTI�directive.ŒTRAPƒ#0"ŒBRA.S‚OKEVENTŠIf�good,�go�return.1ŒMOVEM.L�(A7)+,D2-D7/A0-A6�Restore�the�registers.&ŒKILL.DRIVER�M300INT_ID,T0QEVNTI,A5,A4ŠENDI 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�=�task�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 NNNNN' 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=/* =/*†DRVLIB.LF=/*'=/* Link chain file to create DRVLIB.RO.=/* Input modules should all be in SECTION 15.=/*:=/* If no output argument is specified for the listing the(=/* chain file will default to DRVLIB.LL=/*=/IFC \1ƒ=ARG�DRVLIB.LL=/ENDIF=/*=LINK„,DRVLIB.RO,\1;HMIXRINPUT DRVLIB.QEVENT.ROIN„DRVLIB.LOGPHY.ROINPUT DRVLIB.SETTIME.ROEND=/*=ENDNNNN NNbHACIADRV‚IDNT�45,0…VERSAdos�ACIA�terminal�driver�with�type-ahead�12/03/85D‰TTL‚ACIADRV:�VERSAdos�ACIA�terminal�driver�with�type-ahead�12/03/85 ‰LLENƒ120J**************************************************************************J***************************************************************************9*‰ACIADRV:‚VERSAdos�ACIA�terminal�driver�with�type-ahead.*8*‰Purpose:‚VERSAdos�device�driver�to�handle�asynchronous/*�terminals�(of�any�type)�over�the�ACIA�chip�on*�the�following�boards:*’DEBUG�(EXORmacs),…MVME110**‰Revision�history:*7*�12/18/85‚Install�NEW�Killer�modification�which�leaves,*šThe�Driver�ID�(Number)�and�Reason�(Number)2*šin�CRASHSAV�along�with�the�CCB�and�DCB�pointers.8*�12/17/84‚Interrupt�routine�and�RCA�routine�modified�to1*šprevent�the�EDITOR�from�hanging.‚We�must�detect5*šend-of-break�before�checking�the�received�character4*šfor�bit�7�set�(garbage�character�at�end-of-break).6*�11/21/84‚Modified�the�interrupt�routine.‚The�Special0*šReceive�Condition�routine�is�executed�now�only1*šwhen�there�has�been�a�receive�interrupt�and�SRC2*šbits�are�pending.‚This�will�prevent�the�terminal/*šfrom�hanging�when�BREAK�is�pressed�to�log�on.1*�10/23/84‚All�BSR's�to�TERMLIB�now�JSR's�in�case.*šTERMLIB�is�located�more�than�32K�bytes�away.3*‘9/27/84‚Adding�documentation,�INCLUDE�9995�files,"*šusing�TERM_BREAK�in�SRC�routine.,*‘9/25/84‚Removed�XREF�to�BREAK�and�GET_LEN.5*‘9/21/84‚Changed�PASS19.MPSCDRV.SA�to�drive�an�ACIA.3*‘8/30/84‚Fixed�SPR�concerning�SETUP.‚Commented�out(*šthe�code�that�tests�the�modem�bit.‚Now**šif�the�off�hook�bit�is�set,�the�DTR�line&*šis�set�low,‚whether�or�not�the�modem *šbit�is�set.9*�05/23/84‚Changed�code�that�referenced�the�baud�rate�PIA1*šon�the�EXORmacs�to�be�executed�conditionally�if/*šthe�channel�type�is�a�$66�or�a�$67.‚This�will(*šallow�the�ACIADRV�to�work�on�a�VME110.1*šChanged�the�code�that�reset�the�ACIA�to�get�the!*švalue�for�reset�out�of�the�CDB.0*šChanged�UNSTOP�routine�to�fix�bug�where�a�chark-t=|B„CŒ5”:œA¤F¬L´I¼QÄFÌL(*šis�destroyed�in�the�USE�XOFF/XON�mode.2*šChanged�GET_STAT�routine�to�test�CTS�bit�instead *šof�DCD�bit.7*�08/05/83‚Changed�To�Drive�An�ACIA�instead�of�NEC�72017*�10/19/82‚Major�repairs�so�that�interrupts�will�not�be3*šdisabled�so�long�as�to�screw�up�SDLC.‚Revision�1.**‘9/16/82‚Initial�release�by�Steve�Franck.*J**************************************************************************J**************************************************************************‰PAGE****‚XREF's�from�TERMLIB* ‰XREF†LOG_ERR ‰XREF†RESET‰XREF†TERM_INIT‰XREF†TERM_COMMAND‰XREF†TERM_TBE‰XREF†TERM_BREAK‰XREF†TERM_GOT_CHAR **‚Include�files�used....**‰INCLUDE�9995.&.STR.EQ*‰INCLUDE�9995.&.TCB.EQ*‰INCLUDE�9995.&.CCB.EQ*‰INCLUDE�9995.&.IOE.EQ*‰INCLUDE�9995.&.KILL.MC*‰INCLUDE�9995.&.KILLDRV.EQ*‰INCLUDE�9995.&.NIO.EQ*‰INCLUDE�9995.&.LV5.EQ*‰INCLUDE�9995.&.BAB.EQ*‰INCLUDE�9995.&.TERMINAL.EQ*‰INCLUDE�9995.&.UTILITY.MC*‰INCLUDE�9995.&.TERMCCB.EQ* ŠPAGE**‚ACIA�equates:* CREG†EQU„0 SREG†EQU„CREG DREG†EQU„2,RDRFBITƒEQU„0’Receive�data�register�full�bit.TDREBITƒEQU„1’Transmit�data�register�empty�bit$DCDBIT„EQU„2’Data�Carrier�Detect�bitCTSBIT„EQU„3’Clear�To�Send�bit'OVRNBITƒEQU„5’Received�data�overrun�bit**%*‰SPECIAL�EQUATE�FOR�THE�EXORMACS�PIA*0BAUDPIAƒEQU„$FEE001ŒBaud�rate�PIA�device�address(*£Address�of�PIA�on�EXORmacs�Debug�board#*£to�set�the�baud�rate�for�the�ACIA*ŠNOLISTNNŠINCLUDE�9995.&.STR.EQŠINCLUDE�9995.&.TCB.EQŠINCLUDE�9995.&.CCB.EQŠINCLUDE�9995.&.IOE.EQŠINCLUDE�9995.&.KILL.MCŠINCLUDE�9995.&.KILLDRV.EQŠINCLUDE�9995.&.NIO.EQŠINCLUDE�9995.&.LV5.EQŠINCLUDE�9995.&.BAB.EQŠINCLUDE�9995.&.UTILITY.MCŠLISTŠINCLUDE�9995.&.TERMINAL.EQŠINCLUDE�9995.&.TERMCCB.EQŠOFFSET‚TERMDDP */*‚Device�dependent�Background�activation�blocks$*‚None�required�for�the�ACIA�driver.**7�RESERVE.1�XINTENAB‘Value�to�put�in�control�register�to*§enable�transmit�interrupts. 7�RESERVE.1�XINTDISA‘Value�to�put�in�control�register�to*§disable�transmit�interrupts. 0�RESERVE.1�XRTSHI“Value�to�make�RTS�line�go�HIGH <�RESERVE.1�GOTBREAK‘Indicates�that�a�break�has�been�recieved*§and�that�all�errors�shall�be%*§ignored�untill�after�the�next�valid *§character *@*ƒCompute�the�number�of�pages�of�memory�that�we�need�for�one�CCB>*ƒfor�the�MPSC�driver.‚CMR�automatically�allocates�one�page�ofA*ƒmemory�($100�bytes)�for�the�CCB,�and�our�variable�EXTCCBSZ�willB*ƒreside�in�the�CMR�parameter�table�at�the�beginning�of�the�driver8*ƒto�tell�CMR�how�many�extra�pages�of�memory�are�needed.**CCBSIZEB�EQU‡*PAGESIZE�EQU‡$100L1‡SET‡CCBSIZEB+PAGESIZE-1CCBSIZE‚EQU‡L1/PAGESIZEEXTCCBSZ�EQU‡CCBSIZE-1;ŠTTL„ACIADRV:‚VERSADOS�ACIA�TERMINAL�DRIVER�WITH�TYPE-AHEADŠPAGEJ***************************************************************************+*‰SERVICE�VECTOR�TABLE,�REVISION�INFO,�ETC.*@*‰This�table�is�examined�by�CMR�when�the�channel�is�allocated�toC*‰determine�where�to�go�for�interrupts,�commands,�&�initialization.<*‰It�must�always�be�at�the�very�top�of�the�driver�code.‚Also>*‰included�is�a�parameter�telling�the�number�of�extra�pages�of>*‰memory�to�include�in�the�CCB,�and�information�describing�the*‰revision�of�the�driver.*L**************************************************************************** ŠSECTION‚0ŠOPT„BRS ACIADRV: *D*‚Service�vector�table.‚Notice�that�these�values�are�relative�to�theC*‚beginning�of�the�driver�so�the�mechanism�is�position-independent!*=ŠDC.LƒINTERRUPT-ACIADRV‚Address�of�interrupt�service�routine.9ŠDC.LƒCOMMAND-ACIADRV„Address�of�command�service�routine.5ŠDC.LƒINIT-ACIADRV‡Address�of�initialization�routine.ŠDC.Lƒ0’Reserved. **‚Other�CMR�parameters.*7ŠDC.BƒEXTCCBSZ‹#�of�extra�pages�in�the�CCB.‚The�CCB�may)*§be�any�size�from�1�to�256�pages�(a�page'*§is�256�bytes):‚if�this�field�is�0,�it*§will�be�1�page,�etc.ŠDC.Bƒ0,0,0ŽReserved.ŠDC.Lƒ0,0,0ŽReserved. **‚Revision�info:*/ŠDC.Bƒ'121854'‹Date�of�last�assembly�as�MMDDYY.1ŠDC.Bƒ'�'�Space�indicates�no�patches�to�.LO�file.)ŠDC.Bƒ'4'�Major�VERSAdos�revision�number.*‰PAGE*+*‚Jump�table�for�use�by�the�generic�TERMLIB*‰BRA.L…PUT_CHAR ‰BRA.L…CK_TBE‰BRA.L…DDP_RESET ‰BRA.L…SETUP‰BRA.L…CLOCK_RESET‰BRA.L…GET_STAT‰BRA.L…DDP_STOP‰BRA.L…DDP_UNSTOP‰BRA.L…DDP_BEG_BREAK‰BRA.L…DDP_END _BREAK **‰PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INITIALIZATION�ROUTINE*>*‰This�routine�is�called�by�CMR�when�the�channel�is�allocated.9*‰Its�purpose�is�to�set�up�things�for�command�service�and7*‰interrupt�service.‚The�major�functions�performed�are:"*�Validate�the�channel�type�field.+*�Get�memory�for�transmit�&�receive�queues..*�Initialize�flags,�pointers,�etc.�in�the�CCB.*�Initialize�the�ACIA.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.**‰Entry:�A5�=�address�of�CCB.*'*‰Exits�to:‚CMR�(via�RTS)�if�all�is�OK.'*”KILLER�if�exec�won't�allocate�memory.*J**************************************************************************J**************************************************************************J************************************************************************** ŠDS…0 INIT:.‰JSR‡TERM_INIT‹Do�the�device-independent�stuff2‰IFƒƒTHEN…Something�went�wrong�with�TERM_INIT.4‰IFƒƒTHEN„The�exec�call�failed�and�we�cannot�get!*œthe�scheduler's�entry�point�!!!-ŽKILL.DRIVER�ACIADRV_ID,BAD_T_INIT,A5,#NO_DCB‰ELSE�RTS�The�channel�is�down�!!‰ENDI‰ENDI*?*‚Call�guarded�for�the�device�dependent�initialization�routine.*‰LEA‡DO_INIT(PC),A0‰MOVE.L„#T0GUARD,D0‰TRAP†#0‰RTSŠPAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰COMMAND�SERVICE�ROUTINE*>*‰We�get�entered�here�when�the�attached�task�(IOS)�invokes�CMR?*‰via�a�TRAP�1�with�an�INITIATE�I/O�parameter�block�to�process.>*‰CMR�has�already�checked�the�CMR�parameter�block�to�ensure�it<*‰resides�within�the�address�space�of�the�attached�task.‚IOSA*‰has�already�validated�the�IOCB,�except�for�the�buffer�addresses *‰therein.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.*5*‰Entry:�A2�=�physical�address�of�CMR�parameter�block*�A5�=�physical�address�of�CCB*3*‰Exit:‚D0�=�results�of�parameter�block�validation:3*•always�0�in�our�case,�indicating�it�was�OK,�since2*•IOS�will�not�send�us�any�request�except�HALT�I/O/*•if�we�are�already�busy,�and�CMR�makes�all�the*•other�checks.*A*‰Note:‚TERMLIB�does�not�recognize�CMR�commands�for�HALT�&�RESET.B*‰HALT�can�still�be�accomplished�through�use�of�the�HALT�I/O�IOCB.*J**************************************************************************J**************************************************************************J************************************************************************** COMMAND:‹JSR…TERM_COMMAND‹RTS—return�to�CMR.‹PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INTERRUPT�HANDLING�ROUTINE*<*‰This�routine�completes�I/O�requests�started�by�the�command:*‰service�routine.‚It�is�entered�at�the�interrupt�priority;*‰level�of�interrupts�on�this�channel,�and�is�essentially�a9*‰subroutine�to�the�first�level�interrupt�handler�in�CMR.*:*‰Entry:�D0,A0,A1�have�been�saved�by�CMR�and�are�available*�A5�=�address�of�CCB*9*‰Exit�is�always�via�RTS,�which�takes�us�back�to�CMR.‚The3*�carry�bit�is�examined�by�CMR�to�determine�whether7*�the�driver�h andled�the�interrupt�or�whether�it�should4*�pass�the�interrupt�on�to�the�next�guy�in�the�chain*�on�that�vector:*��=�'I�handled�it'**‰Stack:*�(A7)+4�.�.�.*�(A7)ƒlongword�return�address*J**************************************************************************J**************************************************************************J************************************************************************** INTERRUPT:0‰MOVE.L„CCBCHB(A5),A1‡STATUS/CONTROL�REG�ADDRESS$‰MOVE.B„SREG(A1),D0‰GET�COPY�OF�SREG‰IF��THEN.S�IF�NO�INTERRUPT‹AND…#$FFFE,SR‹CLEAR�CARRY‹RTS‰ENDI ‰PUSH.L„D1’SAVE�D1 (‰BTST†#RDRFBIT,D0‰Test�Receive�reg�full.*‰BNE.S…RCA‘Branch�if�received�a�character. +‰BTST†#OVRNBIT,D0‰Test�for�receive�overrun.‰BNE.S…SRC‘Branch�if�overrun. )‰BTST†#DCDBIT,D0ŠTest�for�DCD�transition.&‰BNE.S…SRC‘Branch�if�DCD�(don't�care). -‰BTST†#TDREBIT,D0‰Test�transmit�buffer�empty.%‰BNE.S…TBE‘Branch�if�buffer�is�empty. +‰BRA.S…INT_EXITŒShould�not�get�here�anyway.ŠPAGEJ***************************************************************************)*‰TRANSMIT�BUFFER�EMPTY�INTERRUPT�HANDLER*=*‰The�ACIA's�transmit�buffer�just�became�empty,�so�if�we�have+*‰more�characters�to�send�we�can�do�it�now.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�ACIA*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** TBE:5ŠMOVE.B�XINTDISA(A5),CREG(A1)ƒDISABLE�XMIT�INTERRUPTS *%%%%%%%%%%ƒBWN‚9/17/84*F*‚Call�the�device-independent�routine�that�deals�with�transparent�mode)*‚or�invokes�the�XMIT�background�routine.* ‰JSR‡TERM_TBE ‰BRA‡INT_EXITŠPAGEJ***************************************************************************(*‰RECEIVED�CHARACTER�AVAILABLE�INTERRUPT*=*‰The�ACIA�has�just�received�a�character,�and�it�is�available=*‰for�reading.‚We�will�do�that�now,�and�the�result�will�go�in$*‰the�receive�queue�if�there's�room.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�ACIA*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** RCA:.‰MOVEQ…#$74,D1‰Test�PARITY,FRAMING,OVERRUN�and‰AND.B…D0,D1‹DCD�errors.&‰BNE.S…SRC�Branch�if�one�of�the�above. 8‰MOVE.B�DREG(A1),D0ˆGet�the�char�from�the�ACIA�and�reset ‰TST.B…GOTBREAK(A5) ‰IF��THEN/‹SFˆGOTBREAK(A5)„Clear�error�on�last�char�flag./‹TST.B…D0ŽIs�this�garbage�char�at�end-of-break? ‹BLT‡INT_EXIT‰ENDI *%%%%%%%%%%%%‚BWN�9/17/84*C*‚Call�the�device�independent�routine�to�check�for�transparent�modeG*‚and�do�the�stuff�for�transparent�mode�or�if�not�in�tranparent�mode�toG*‚check�for�any�special�characters�such�as�XON,�XOFF,�BREAK�EQUIVALENT,G*‚or�DISCARD�OUTPUT.�Otherwise,�put�the�character�in�the�receive�queue.*‰JSR‡TERM_GOT_CHAR ‰BRA‡INT_EXITŠPAGEJ***************************************************************************%*‰SPECIAL�RECEIVE�CONDITION�INTERRUPT*:*‰The�ACIA�detected�an�error�in�the�process�of�receiving�a<*‰character.‚We�need�to�record�this�information�so�that�when<*‰the�corresponding�data�is�requested�from�the�receive�queue*‰we�can�report�an�error.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�ACIA*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** #SRC:†EQU„*’A1�<--�addr�of�our�ACIA."*£D0�<--�our�ACIA�status�register.'‰MOVE.B‚DREG(A1),D1ˆD1�CONTENTS�OF�DREG0‰TST.BƒGOTBREAK(A5)‡TEST�ERROR�ON�LAST�CHAR�FLAG ‰BNE…INT_EXIT ‰BTST†#4,D0"‰IF��THEN.S�TEST�FRAMING�ERROR‹ST…GOTBREAK(A5)†SET�ERROR�FLAG3‹JSR„TERM_BREAKˆCall �the�device�independent�routine*£to�take�care�of�a�break. ‹BRA„INT_EXIT‰ENDI—* ‰BTSTƒ#6,D0ŽTEST�PARITY�ERROR‰IF��THEN.S1‹PUT_BYTE�PAR_FRAM,D0„Log�a�parity/framing�error;‹JSR„LOG_ERRŠ* ‹BRA„INT_EXIT*¢else�(not�parity�or�framing)‰ELSE.S‰BTST†#5,D0‹TEST�OVERRUN�ERROR‰IF��THEN.S*‹PUT_BYTE�OVERRUN,D0…Log�an�overrun�error.‹JSR„LOG_ERRŠ* ‹BRA„INT_EXIT‰ENDI–*‰ENDI2‰BRA„INT_EXIT‹Exit.�MUST�HAVE�BEEN�DCD.�DONT�CARE.‰NOP‰PAGE*E*‚Now�exit�as�from�an�interrupt.‚We�may�in�fact�have�been�called�fromF*‚command�service�or�initialization,�but�they�had�to�set�it�up�to�look*‚like�an�interrupt,�too.*INT_EXIT:�POP.L‚D1‘Restore�D1,7ŠMOVEQ‚#1,D0Žset�carry�bit�to�tell�CMR�'we�handled�it,' ŠSUBQƒ#2,D0Ž*ŠRTS—and�return.ŠPAGEO********************************************************************************2*‰ROUTINES�TO�SET�THE�CLOCK�DIVISOR�TO�x16�AND�x64*7*‰No�work�here�since�ACIA�cannot�set�the�clock�divisor.*=*‰We�must�have�a�CLOCKRESET�entry�point�for�TERMLIB,�however.**‰Entry:*‹A1ƒ=*‹A5ƒ=�addr�of�our�CCB.**‰Exit:*O******************************************************************************* CLOCK_RESET:ŠRTSŠPAGEK*****************************************************************************!*�R�O�U�T�I�N�E�S„C�A�L�L�E�D„B�Y**–T�E�R�M�L�I�B**F**********************************************************************‰PAGEL******************************************************************************ˆTRANSMIT�THE�CHARACTER*?*ˆThis�is�the�device�dependent�routine�that�actually�writes�the*ˆcharacter�to�the�device.*F*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning�of�the *ˆdriver.**ˆEntry:„A1�=�address�of�ACIA*’A5�=�address�of�CCB*’D0.B�=�character�to�transmit*ˆInterrupt�level�on�entry:�0*C*ˆExit:…All�registers�are�preserved,�including�the�status�register.<*’It�is�important�to�keep�the�interrupt�level�the�same�as�it*’was�upon�entry.*J************************************************************************** PUT_CHAR:‰PUSHƒSR‰INHIBIT1‰MOVE.B�D0,DREG(A1)ˆOtherwise,�transmit�the�char./‰MOVE.B�XINTENAB(A5),CREG(A1)‚ENABLE�XMIT�INTS.‰POP„SR‰RTS‰PAGEM******************************************************************************$*ˆCHECK�THE�DEVICE'S�TRANSMIT�BUFFER*F*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installed�at*ˆthe�beginning�of�the�driver.**ˆEntry:�A1�=�address�of�ACIA*�A5�=�address�of�CCB*ˆInterrupt�level�on�entry:�0**ˆExit:‚Condition�codes:"*��=�transmit�buffer�not�empty*��=�transmit�buffer�empty<*ˆIt�is�important�to�keep�the�interrupt�level�the�same�as�it*ˆwas�upon�entry.*M*****************************************************************************CK_TBE:A‰BTST.B�#TDREBIT,SREG(A1)‚If�ACIA's�transmit�buffer�is�not�empty,‰RTS‰PAGEH************************************************************************* *ˆDEVICE�DEPENDENT�RESET�ROUTINE*9*ˆThis�is�the�device-dependent�part�of�the�reset�routine.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:�A5�=�addr�of�CCB*ˆInterrupt�level�on�entry:�0*$*ˆExit:‚All�registers�are�preserved.<*ˆIt�is�important�to�keep�the�interrupt�level�the�same�as�it*ˆwas�upon�entry.*E********************************************************************* DDP_RESET:*A*‚ACIA�did�not�have�any�device�dependent�reset�stuff�in�the�RESET:*‚routine,�which�is�where�this�stuff�would�have�come�from.* ŠRTS—exit.ŠPAGEJ***************************************************************************@*‰SUBROUTINE�TO�SET�UP�THE�DEVICE�ACCORDING�TO�THE�CONFIGURATION*;*‰Uses�the�working�configuration�(in�the�CCB)�to�set�up�the;*‰device,�and�some�configuration-related�fields�in�the�CCB.*?*‰The�offset�to�this�routine�must�be�installed�at�the�beginning*‰of�the�driver.**‰Entry:�A5�=�address�of�CCB*‰In terrupt�level�on�entry:�0*$*‰Exit:‚All�registers�are�preserved.<*‰It�is�important�to�keep�the�interrupt�level�the�same�as�it*‰was�upon�entry.*J************************************************************************** SETUP:<ŠMOVEM.L�D0-D1/A0-A3,-(A7)�Save�some�registers�on�the�stack. ŠPUSHƒSR **‚First�set�up�addresses.*4ŠLEA„CONFIG(A5),A0†A0�<--�addr�of�CCB�configuration.3ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�ACIA�port.**‚[4]„x16�clock�rate,(*‰stop�bits�&�parity�from�configuration.*)ŠMOVE.Bƒ#1,D0ŒStart�with�x16�clock�in�D0. )‰BTSTWƒ#IOABITS,IOSATW(A0)ƒTEST�BITS/CHAR‰IF��THEN.S�IF�8�THEN‹OR.Bƒ#$10,D0Œ(8�bits/char)>‹BTSTW‚#IOAUSEP,IOSATW(A0)�If�we're�using�parity,�enable�it... ‹IF…�THEN �OR.Bƒ#$08,D09�BTSTW‚#IOAPRTY,IOSATW(A0)�and�if�we're�using�odd�parity,�IF…�THENŠset�it�up. �OR.Bƒ#$04,D0�ENDI‹ELSE.S•8�BITS�NO�PARITY)�BTSTW‚#IOASTPB,IOSATW(A0)ƒTEST�STOP�BITS�IF��THEN.S�IF�1�THEN �OR.Wƒ#$04,D0�ENDI‹ENDIƒPAGE‰ELSE.S˜ELSE�7�THEN)‹BTSTW„#IOASTPB,IOSATW(A0)„TEST�STOP�BITS‹IF��THEN.S�OR.Wƒ#$08,D0�IF�1‹ENDI&‹BTSTW„#IOAPRTY,IOSATW(A0)ƒTEST�PARITY‹IF��THEN.S‘IF�ODD�THEN �OR.W„#$04,D0‹ENDI‰ENDI "*§Transmitter�int�disabled�DTR�low /ŠOR.B…#$80,D0ŽRecieve,Overrun,DCD‚Int's�Enabled‰INHIBITŠMOVE.BƒD0,(A1)‰POP‡SR9ŠMOVE.BƒD0,XINTDISA(A5)†SAVE�CONT�REG�(XMIT�INT�DISABLED) ŠOR.B…#$20,D08ŠMOVE.BƒD0,XINTENAB(A5)…SAVE�CONT�REG�(XMIT�INT�ENABLED):ŠAND.B„#%10011111,D0„Clear�bits�5�and�6�for�setting�up�RTS*ŠOR.B…#%01000000,D0„Set�RTS�bit�for�a�HIGHŠMOVE.BƒD0,XRTSHI(A5)**‚Set�up�baud�rate*G‰IF.B�CCBTYPE(A5)��#$66�OR.B�CCBTYPE(A5)��#$67�THEN.S�KG�052384.‹MOVE.B„IOSBRT(A0),D0‡The�configured�baud�rate‹PUT_BYTE‚$F0,D1ŽMask!‹BTST†#0,CCBTYPE(A5)†A�side�port?‹IF��THEN.S �LSL.B…#4,D0�PUT_BYTE‚$0F,D1‹ENDI2‹AND.B…D1,BAUDPIA…Clear�old�baud�rate…KEG�05/23/842‹OR.B†D0,BAUDPIA…Insert�new�baud�rate„KEG�05/23/84‰ENDI **‚Restore�registers�and�return.*8ŠMOVEM.L�(A7)+,D0-D1/A0-A3�Restore�registers�from�stack.ŠRTSŠPAGEJ****************************************************************************‰GET�DEVICE�STATUS�BYTE*"*‰Prepares�the�DEVICE�STATUS�byte.*8*‰Note:‚this�routine�does�not�set�the�break�indicator�in*�the�device�status�byte.*?*‰The�offset�to�this�routine�must�be�installed�at�the�beginning*‰of�the�driver.**‰Entry:�A5�=�address�of�CCB*‰Interrupt�level�on�entry:�0*&*‰Exit:‚D0.B�=�the�device�status�byte.<*‰It�is�important�to�keep�the�interrupt�level�the�same�as�it*‰was�upon�entry.*J************************************************************************** GET_STAT: ŠCLR.B‚D0 ŠPUSH.L�A0ŠMOVE.LƒCCBCHB(A5),A00ŠBTST…#CTSBIT,SREG(A0)„TEST�CTS�BITŒKEG�05/23/84ŠIF��THEN.S'ŒBSETƒ#XDSNRB,D0ŠDATA�SET�NOT�READY�BITŠENDI ŠPOP.L‚A0 ŠRTS—Return.ŠPAGEM******************************************************************************5*ˆDEVICE�DEPENDENT�STUFF�FOR�LOWERING�A�HARDWARE�LINE*ˆTO�STOP�THE�TRANSMITTER.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�address�of�ACIA*�A5�=�address�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*K*************************************************************************** DDP_STOP:DŠMOVE.B�XRTSHI(A5),CREG(A1)�Make�RTS�go�HIGH�to�stop�the�transmitter*¤KEG�05/23/84ŠRTS‰PAGEK****************************************************************************$*ˆDEVICE�DEPENDENT�UNSTOP�THE�DEVICE*=*ˆWhen�we�are�not�using�XOFF/XON,�we�unstop�the�device�in�our*ˆown�device�dependent�way.*;*ˆWe�are�running�in�background�when�this�routine�is�called.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�address�of�ACIA*�A5�=�address�of�the�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit :ƒAll�registers�are�preserved.*J************************************************************************** DDP_UNSTOP:CŠMOVE.B�XINTENAB(A5),CREG(A1)�Make�RTS�go�LOW�to�enable�transmitter*¦KEG�05/23/84ŠRTSŠPAGEK****************************************************************************&*ˆDEVICE�DEPENDENT�BEGIN�BREAK�ROUTINE*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�addr�of�ACIA*�A5�=�addr�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*E********************************************************************* DDP_BEG_BREAK:‰SAVEƒD08‰MOVE.B�XINTDISA(A5),D0„D0�<--�image�of�ACIA�CONTROL�REG,‰OR.Bƒ#$60,D0ŒAdd�bits�to�send�break�signal.‰MOVE.B�D0,CREG(A1)ˆ* ‰RESTORE�D0‰RTS‰PAGEK****************************************************************************$*ˆDEVICE�DEPENDENT�END�BREAK�ROUTINE*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�addr�of�ACIA*�A5�=�addr�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*L**************************************************************************** DDP_END_BREAK:.‰MOVE.B‚XINTENAB(A5),CREG(A1)ƒENABLE�XMIT�INT.‰RTS‰PAGEI***************************************************************************“B�A�C�K�G�R�O�U�N�D**šAND**‘C�A�L�L�__�G�U�A�R�D�E�D**–R�O�U�T�I�N�E�S**•(DEVICE-DEPENDENT)*E*********************************************************************ŠPAGEO*********************************************************************************‰FINISH�OFF�THE�INITIALIZATION*A*‰The�initialization�routine�has�gone�around�resetting�everything@*‰it�can,�but�the�routines�RESET�and�SETUP�should�only�be�called>*‰from�within�the�background.‚So�he�invoked�this�routine�to�do *‰it�for�him.**‰Entry:*�A5�=�address�of�CCB.*O******************************************************************************* DO_INIT:**‚Inhibit�interrupts*‰PUSH†SR‰INHIBIT*)*‚Get�address�of�start�of�driver�into�CCB*‰LEA‡ACIADRV(PC),A4‰MOVE.L„A4,DRV_ADDR(A5)*0*‚Now�actually�do�the�minimum�setup�on�the�ACIA.*.ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�ACIA.4ŠMOVE.B�CCBRESV(A5),CREG(A1)�Reset�our�ACIA�channel. ŠJSR„RESETŽReset�everything.ŠBSR.L‚DDP_RESET5ŠBSR.L‚SETUPŽSet�up�the�ACIA�according�to�the�config.**‚Enable�interrupts�now.*‰POP‡SR‰RTS‰PAGE*********************** *‚PATCH�SPACE***********************ŠDS.Wƒ30ŠEND  N‰PAGE7DISKLIB‚IDNT†45,0†VERSAdos�disk�driver�generic�routines3‰TTL‡DISKLIB:‚VERSAdos�disk�driver�generic�routines ‰LLEN†120 ‰OPT‡CRE,PCS,BRSO*******************************************************************************O*******************************************************************************O********************************************************************************(*‰DISKLIB:‚VERSAdos�Disk‚Driver‚Routines*7*‰Purpose:‚A�collection�of�disk�driver�routines�used�to *“support�the�following�drivers: *œM320DRV *œRWINDRV *œM420DRV *œVM22DRV *œSCSIDRV *œM360DRV**‰Revision�history:<*�10/08/85‚Extracted�from�VERSAdos�4.4�release�of�RWINDRV.SA=*�11/26/85‚Added�code�for�extended�configuration�block�R.E.M.7*�12/05/85‚Install�NEW�Killer�modification�which�leaves,*šThe�Driver�ID�(Number)�and�Reason�(Number)2*šin�CRASHSAV�along�with�the�CCB�and�DCB�pointers.:*�12/11/85‚Added�CHK_PARAM�call�to�all�disk�drivers�R.E.M.**‰Other�notes:0*�This�code�is�ROMab le�and�position-independent.*O*******************************************************************************O*******************************************************************************O*******************************************************************************  * *‚INCLUDES***ˆ9995.&.IOE.EQ*ˆ9995.&.STR.EQ*ˆ9995.&.TCB.EQ*ˆ9995.&.NIO.EQ*ˆ9995.&.LV5.EQ*ˆ9995.&.CCB.EQ*ˆ9995.&.DISK.EQ*ˆ9995.&.UTILITY.MC*ˆ9995.&.DISKCCB.EQ*ˆ9995.&.DISKMEM.EQ*ˆ9995.&.KILL.MC*ˆ9995.&.KILLDRV.EQ*‰NOLIST‰INCLUDEƒ9995.&.IOE.EQ‰INCLUDEƒ9995.&.STR.EQ‰INCLUDEƒ9995.&.TCB.EQ‰INCLUDEƒ9995.&.NIO.EQ‰INCLUDEƒ9995.&.LV5.EQ‰INCLUDEƒ9995.&.CCB.EQ‰INCLUDEƒ9995.&.DISK.EQ‰INCLUDEƒ9995.&.UTILITY.MC‰INCLUDEƒ9995.&.DISKCCB.EQ‰INCLUDEƒ9995.&.DISKMEM.EQ‰INCLUDEƒ9995.&.KILL.MC‰INCLUDEƒ9995.&.KILLDRV.EQ‰LIST‰PAGEÍÔEÝNå=í@õ>ýI- :@7%2-;5:=8E1M;U5]1e+m1u5}+…2�0•4�2¥.­4µ9½<O********************************************************************************1*ƒEQUATES�AND�MACROS�FOR�THE�GENERIC�DISK�LIBRARY*O*********************************************************************************@*ƒOFFSET�TO�MARK�THE�END�OF�THE�SERVICE�VECTOR�TABLE�IN�A�DRIVER*SERVECT‚EQU‡$28*=*‚A�DRIVER�THAT�WISHES�TO�USE�DISKLIB�MUST�HAVE�THE�FOLLOWING>*‚BRANCH�TABLE�IMMEDIATELY�FOLLOWING�THE�SERVICE�VECTOR�TABLE:**†BRA.L‡SET_CNFG*†BRA.L‡SET_CODE*†BRA.L‡CHK_FLOPPY*†BRA.L‡CHK_LSN*†BRA.L‡BLD_PACKET*†BRA.L‡DISK_START*†BRA.L‡CHK_PARAM*‰OFFSET„SERVECTT_SET_CNFG‰DS.L†1T_SET_CODE‰DS.L†1T_CHK_FLOPPY‡DS.L†1T_CHK_LSNŠDS.L†1T_BLD_PACKET‡DS.L†1T_DISK_START‡DS.L†1T_CHK_PARAMˆDS.L†1** O********************************************************************************>*ƒMACRO�TO�PERFORM�THE�JUMP�TO�the�device�DEPENDENT�SUBROUTINE**ƒAssumption:‚None.**ƒCalled�by:ƒT_JSR‚ROUTINE*2*‰where‚T_ROUTINE�is�an�offset�in�the�above�table.*O******************************************************************************** T_JSR„MACRO ‰IFC�'\1','' ŒFAIL‚400ŒMEXIT‰ENDC‰MOVE.L�A4,-(SP)‰MOVE.L�DRV_ADDR(A5),A4 ‰JSR„T_\1(A4)‰MOVE.L�(SP)+,A4‰ENDM‰PAGEO********************************************************************************2*ƒDescriptions�of�the�routines�required�by�DISKLIB*O*******************************************************************************  N*******************************************************************************)*ˆSET_CNFG…SET�UP�FOR�A�CONFIGURE�COMMAND*C*ˆThis‚is�a�device�dependent�routine�whose�offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toD*ˆset�the�fields's�in�the�drive's�variable�block,�device-independent#*ˆportion,�for�a�configure�command.**A*ˆEntry:�A1�=�pointer�to�Drive's�Variable�Block�in�global�memory.#*�A5�=�physical�address�of�the�CCB.* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A„P‡P* *ˆCalls:�none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:7*�‚Drive/controller�supports�the�configure�request.?*�‚Drive/controller�does�not�support�the�configure�request.4*•D1.B�=�VERSAdos�error�code�for�the�error�detected.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N******************************************************************************‰PAGEN******************************************************************************* *ˆSET_CODE*F*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installed�atE*ˆthe�beginning�of�the�driver.‚The�function�of�this�routine�is�to�setD*ˆany�media‚and/or‚drive�related�codes�in�the�driv e's�variable�blockC*ˆ(device-dependent�portion)‚required�by‚the�particular‚controller.>*ˆIt�is�called�by�configure,�read,�write,�and�format�commands.**A*ˆEntry:„A1�=�pointer�to�Drive's�Variable�Block�in�global�memory.#*’A5�=�physical�address�of�the�CCB.* *’Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A„P‡P* *ˆCalls:�none**ˆExit:‚RTS�to�caller.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N******************************************************************************‰PAGEN********************************************************************************ˆCHK_FLOPPY�ROUTINE*C*ˆThis�is�a‚device�dependent‚routine�whose‚offset�must‚be�installedD*ˆat�the�beginning�of�the�driver.�The‚function�of‚this�routine‚is�toF*ˆcheck�that�the�bytes�per�sector,‚sectors�per�track,�and�data-densityG*ˆdensity�values�are�consistent�with�each�other.�This�routine�is�called?*ˆafter�the‚user's‚configuration‚block‚has‚been‚filled‚with‚theG*ˆproposed�configuration.�Therefore,�A0�points�to�the�end�of�the�user's*ˆconfiguration�block.*0*ˆEntry:�A0�=�end�of�user's�configuration�block.* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A‚P* *ˆCalls:�none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:-*��no�errors�in�this�configuration�check.*��an�error�was�found.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N******************************************************************************‰PAGEN******************************************************************************* *ˆCHK_LSN*C*ˆThis�is�a�device�dependent�routine�whose�offset�must‚be‚installedD*ˆat�the�beginning�of�the‚driver.�The�function�of�this�routine�is�toC*ˆcheck�that‚the�requested�starting�logical‚sector�number�(in�D2.L)E*ˆis�less�than�or�same�as�the�largest�logical�sector�number�supported$*ˆby�the�particular�disk�controller.**-*ˆEntry:�D2�=�starting�logical�sector�number.* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D†P*™A* *ˆCalls:�none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:3*��=�starting�logical�sector�number�is�invalid.1*��=�starting�logical�sector�number�is�valid.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N******************************************************************************‰PAGEN******************************************************************************* *ˆBLD_PACKET*C*ˆThis�is�a�device-dependent�routine�whose‚offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toC*ˆbuild�any�or�all‚parts�of�the�command�packet�that�can�be�built�at=*ˆinterrupt‚level�0‚which‚will�be‚used‚by�the‚particular‚disk,*ˆcontroller�to�process�the�current�command.*A*ˆEntry:„A1�=�pointer�to�Drive's�Variable�Block�in�global�memory.#*’A5�=�physical�address�of�the�CCB.* *’Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A„P‡P* *ˆCalls:„none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:3*�‚No�errors�were�found�in�building�the�packet.4*�‚An�error�was�detected�in�building�the�packet.4*•D1.B�=�VERSAdos�error�code�for�the�error�detected.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N******************************************************************************‰PAGEN******************************************************************************* *ˆDISK_START*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedE*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�to:*8*Š1.‚Perform�device-dependent�code�to�start�the�command.**D*ˆEntry:�A1�=�address�of�the�drives�variable�block�in�global�memory.#*�A5�=�physical�address�of�the�CCB.*=*�Interrupt�level�on�entry�is�at�our�hardware�level�(masked). *!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A„P‡P* *ˆCalls:�none**ˆExit:‚RTS�to�caller.*N******************************************************************************‰PAGEN********************************************************************************ˆCHK_PARAM�ROUTINE*C*ˆThis�is�a‚device�dependent‚routine�whose‚offset�must‚be�installedD*ˆat�the�beginning�of�the�driver.�The‚function�of‚this�routine‚is�toB*ˆvalidate‚any‚device‚dependent‚parameters.‚This�routine�is�called?*ˆafter�the‚user's‚configuration‚block‚has‚been‚filled‚with‚theG*ˆproposed�configuration.�Therefore,�A0�points�to�the�end�of�the�user's*ˆconfiguration�block.*/*ˆEntry:�A0�=�end�of�user's�configuration�block* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™DˆR*™A‚P* *ˆCalls:�none*$*ˆExit:‚RTS�back�to�calling�routine.>*�CONDITION�CODES:��no�errors�in�this�configuration�check.* �an�error�was�found./*�D3.B�=�Returned�error�code�if�error�is�found.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N******************************************************************************‰PAGEO********************************************************************************;*ƒDEVICE-DEPENDENT�ROUTINES‚THAT�ARE�NOT�CALLED�BY�DISKLIB,9*ƒBUT�NEVERTHELESS�NEED�TO�DO�CERTAIN�THINGS�FOR�DISKLIB.*O*********************************************************************************INIT:>*…This�is�the�entry�point�for�an�INITIALIZATION�call�from�CMR.*‰INIT�must�do�the�following:*6*ŽPut�the�starting�address�of�the�driver�into�the�CCB:*�LEA…MY_DRVR(PC),A0*�MOVE.L‚A0,DRV_ADDR(A5)*4*ŽPut�the�number�of�devices�controlled�into�the�CCB:*�MOVE.L‚#DRIVES,MAX_DRVS(A5)*(*ŽPut�the�drive�block�size�into�the�CCB:*�MOVE.L‚#DRVBLKSZ,DRV_SIZE(A5)**‘....**“RTSO*******************************************************************************‰PAGE** *‚XREF's.**C*‚This�XREF�is�from�the�driver�library�DRVLIB.RO�which�is�linked�in*‚at�SYSgen�time.*0‰XREF†LOGPHYŽConvert�logical�address�to�physical6‰XREF†I_NRM_QEVENTˆQueue�a�normal�I/O�completion�event*¦from�interrupt�handler6‰XREF†N_NRM_QEVENTˆQueue�a�normal�I/O�completion�event*¦from�command�level.**I*‚These�XREF's�are�from�the�DSKTYPE�module,�table�of�valid�disk�channels.*5‰XREF†CH_TYPESŒChannel�types�for�disk�drivers�(table)0‰XREF†NUMTYPESŒNumber�of�supported�channel�types5‰XREF†NUMBYTESŒNumber�of�bytes�ber�entry�in�the�table *(*‚XDEF'S�for�the�device-dependent�module*2‰XDEF†DISK_INIT‹Device-independent�initialization.6‰XDEF†DISK_COMMANDˆDevice-independent�command�handler.-‰XDEF†CHAN_DONE‹Interrupt�completion�routine..‰XDEF†LSN2CHS�Convert�logical�sector�number�to$*§Cylinder-Head-Sector�within�track.5‰XDEF†LOGPHY1�Logical-to-physical�address�conversion.  ‰SECTION�14DISKLIB: **‚Identification�mnemonic*‰DC.B†'!DISKLIB'**‚Revision�info:*/ŠDC.Bƒ'121185'‹Date�of�last�assembly�as�MMDDYY.1ŠDC.Bƒ'�'�Space�indicates�no�patches�to�.LO�file.)ŠDC.Bƒ'4'�Major�VERSAdos�revision�number.*Š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�the�device*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.ŠPAGEJ****************************************************************************‰COMMAND�SWITCHING�TABLE*:*‰These�are�used�by�the�command�service�routine�to�jump�to.*‰the�appropriate�routine�to�handle�a�command.*J************************************************************************** ŠDS…0 CMDSWIT: 3‰DC.W…READCMD-*-4ŒThe�read�command�tells�the�driver2‰DC.W…IOREAD�to�read�data�from�a�disk�into�memory. 5‰DC.W…WRITECMD-*-4‹The�write�command�tells�the�driver1‰DC.W…IOWRIT�to�write�data�from�memory�to�a�disk. 5‰DC.W…STATCMD-*-4ŒThe�status�command�tells�the�driver-‰DC.W…IOSTAT�to�return�the�current�status�and *¦configuration�of�a�disk�drive. 7‰DC.W…CONFIG-*-4�The�configure�command�tells�the�driver3‰DC.W…IOCNFG�to�change�the�current�configuration�of*¦a�disk�drive. 3‰DC.W…DFCONFIG-*-4‹The�change�default�configuration3‰DC.W…IOCHDC�command�tells�the�driver�to�change�the(*¦default�configuration�of�a�disk�drive. 4‰DC.W…FORMAT-*-4�The�format�command�tells�the�driver*‰DC.W…IOFRMT�to�format�an�entire�disk�or�a*¦particular�track�of�a�disk. ‰DC.W…0”End�of�switching�table.‰PAGEO*******************************************************************************O*******************************************************************************O*********************************************************************************ˆINITIALIZATION�ROUTINE*B*ˆThis‚subroutine�is�called�from�the�device-dependent�driver�afterA*ˆit�receives�an�initialization�call�from�CMR.‚It's�purpose�is�to?*ˆset�things�up�for�command�service�and�interrupt�service.‚It's*ˆspecific�functions�are:**Š1.�Validate�the�channel�type.>*Š2.�Allocate�global�memory�for�the�drive's�variable�block�and**�store�the�starting�address�into�the�CCB.*:*ˆEntry�is�through�a�JSR�from�the�device-dependent�module.?*ˆEntry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.*%*ˆEntry:„A6�=�physical�address�of�TCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:ˆ0�1�2�3�4�5�6�7*œD‚**œA‚*‰P*D*ˆExit:…RTS�to�the�device-dependent�module�with�condition�codes�set: *”�and�‚channel�is�down.$*”‹memory�allocation�has�failed./*”‹all�went�well,�OK�to�proceed�with�device*£dependent�I/O.*O*******************************************************************************O*******************************************************************************O******************************************************************************* ‰SECTIONƒ14‰DSˆ0 DISK_INIT:*F*‚Check�the�channel�type�field�we�are�supposed�to�be�to�make�sure�it's*‚a�type�this�driver�handles.*/ŠMOVE.B�CCBTYPE(A5),D0…D0�<--�our�channel�type.7ŠLEA„CH_TYPES,A0ˆA0�<--�addr�of�table�of�cha nnel�types. ŠFOR.W…D1=#1‚TO‚#NUMTYPESƒDOŒCMP.Bƒ(A0)+,D0 ŒBEQ‡CH_FOUNDŒADD.L…#NUMBYTES-1,A0ŠENDF*%*„BAD�CHANNEL�TYPE�!!!„SEND�BACK�*A‰MOVE.B�#ISTAICE,CHANDOWN(A5)‚Return�Indeterminate�Channel�Error.)‰MOVE.B„#-1,D0‹Set�condition�code�to�#‰RTS˜and�return�to�calling�routine.‰PAGE**…GOOD�CHANNEL�TYPE�!!!*CH_FOUND*=*‚We�got�here�because�we�found�the�channel�type�in�the�table.B*‚We�cannot�validate�the�Device�Code�because�we�do�not�have�enoughH*‚information�yet.‚The�Device�Code�is�checked�at�CONFIGURE�command�time.* *M*‚We�now�allocate�global�memory�for�all�of�the�drive�variable�blocks�based�onK*„1)�the�number�of�devices�SYSGEN'ed�in�for�the�device-dependent�driver�and5*„2)�the�size�of�one�drive�variable�block�(DRV_SIZE).*A‰MOVE.W„MAX_DRVS(A5),D0‚D0�<--�number�of�drives�for�this�channel.9‰MULU†DRV_SIZE(A5),D0‚Total�space�required�for�all�DVB's.<‰ADD.W…#PAGESIZE-1,D0ƒConvert�to�an�integral�number�of�pages)‰LSR.W…#8,D0Œto�allocate�physical�memory.‰MOVEA.WƒD0,A0 ‰MOVE.L„#4,D0‰TRAP†#0�Allocate�memory.‰BRA.S…INIT100ŠGood�return.,‰BRA.S…INIT150ŠMemory�allocation�has�failed. 7INIT100‚MOVE.L„A0,DVBPTR(A5)„Save�the�start�of�the�DVB.*,*‚Clear�the�drive�variable�block�area�(DVB):*8‰MULU†#PAGESIZE,D2…D2�is�returned�as�the�number�of�pages4‰ADD.L…D2,A0Œthat�were�allocated.‚A0�is�setup�to�the3‰LSR.W…#2,D2Œend�of�global�memory.‚D2�is�setup�as�a,‰SUB.W…#1,D2Œcounter�of�long�words�to�clear. -CLRDVBƒCLR.L…-(A0)ŒClear�the�DVB�memory�area.‰DBRA†D2,CLRDVB ‰MOVE.B„#0,D0ŒReturn�.‰RTS .INIT150‚STˆCHANDOWN(A5)…Mark�the�channel�down.‰MOVE.B„#1,D0ŒReturn�.‰RTS‰PAGEO*******************************************************************************O*******************************************************************************O*********************************************************************************ˆCOMMAND�SERVICE�ROUTINE*B*ˆThis�subroutine�is�called‚from�the�device-dependent‚driver�afterD*ˆit�receives�a�command�to�initiate�an�I/O�transaction�with�a�deviceB*ˆthat�is�controlled�by�that�driver.‚The�purpose‚of�this�module�is@*ˆto�perform�the‚common�tasks‚that�are‚necessary�for‚all�command@*ˆroutines,�and�to‚direct�control‚to�the‚individual�routine‚thatB*ˆprocesses�the�given�command‚through�the�command�switching‚table.*5*ˆEntry:„A2�=�physical�address�of�CMR�parameter�block*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*"*ˆRegisters�usage:„0�1�2�3�4�5�6�7 *™D‚*�*�*…R�R*™A‚*�R�P�R�R�P�P*@*ˆEXIT:…A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’D6�=�Channel�device�#*9*ˆExits�to:�The�routine�that�processes�the�given�command.*O*******************************************************************************O*******************************************************************************O******************************************************************************* DISK_COMMAND: 6‰MOVE.LƒSP,SAVESP(A5)ŠSave�the�stack�pointer�so�we�can$*¦later�abort�at�any�level�of�nested$*¦subroutines�and�easily�restore�the%*¦stack�environment�that�existed�when*¦this�routine�began�execution. :‰MOVE.LƒXIOCPK(A2),D6ŠGet�the�physical�address�of�the�IOCB2‰MOVEQ.L‚#0,D5�for�the�command�into�A4.‚Subroutine7‰MOVE.WƒXIOPLN(A2),D5ˆLOGPHY1�converts�the�logical�IOCB?‰MOVE.LƒCCBTASKA(A5),A0†address�(in�D6)�into�a�physical�address)‰BSR.L„LOGPHY1Žfor�us.‚Subroutine�LOGPHY11‰MOVE.LƒD6,A4�returns�the�physical�address�of�the *¦IOCB�in�D6. 9‰MOVE.LƒXIOUID(A2),A3ŠGet�the�physical�address�of�the�DCB2‰MOVEQ.L‚#0,D6�into�A3,�and�get�the�channel�device;‰MOVE.BƒDCBCDV(A3),D6ˆnumber�into�D6.‚These�values�indicate&*¦the�particular�device�that�should�be*¦accessed�by�the�command.‰PAGE8‰MOVEQIƒISTACDN,D1�If�the�disk�channel�is�down,�go�queue:‰TST.B„CHANDOWN(A5)‰an�event�to�the�attached�task�to�indi-8‰BNE.S„C MDEXIT2�cate�that�the�channel�is�out�of�service. 8‰MOVE.LƒDVBPTR(A5),A1ˆSet�up�A1�to�point�to�the�variable>‰MOVE.WƒDRV_SIZE(A5),D0†block�for�the�disk�drive�that�is�to�be-‰MULU…D6,D0�accessed�by�the�command.‚The�disk1‰ADD.L„D0,A1�drive�variable�block's�are�in�global%*¦memory,�and�the�particular�variable#*¦block�is�indicated�by�the�drive's!*¦channel�device�number.‚The�code&*¦here�depends�on�the�fact�that�global#*¦memory�is�organized�into�parallel)*¦variable�blocks�with�one�variable�block *¦for�each�drive�on�the�channel.  7‰MOVE.WƒIOSFCT(A4),D0ŠNow�prepare�to�search�the�command;‰LEA†CMDSWIT(PC),A0‡switching�table�for�the�command�that�is6‰MOVEQIƒISTAIF,D1Œspecified�by�the�IOSFCT�field�of�the$*¦IOCB.‚We�put�the�IOSFCT�value�into%*¦D0.W,�and�we�put�the�address�of�the(*¦switching�table�into�A0.‚We�also�put�a$*¦status�code�into�D1.B.‚This�status'*¦code�will�be�used�if�the�given�IOSFCT%*¦value�doesn't�correspond�to�a�valid*¦command�code.  4L0030„MOVE.Wƒ(A0)+,D2�This�loop�searches�the�command7‰BEQ.S„CMDEXIT2�switching�table�to�see�if�we�can�find�a6‰CMP.W„(A0)+,D0�match�for�the�IOSFCT�value�in�D0.W.‚If4‰BNE.S„L0030�we�reach�the�end-of-table�sentinel�word)*¦without�finding�a�match,�we�go�queue�an&*¦event�to�tell�the�attached�task�that)*¦we've�received�an�invalid�command�code.&*¦Otherwise,�we�set�up�D2.W�to�contain&*¦the�switching�offset�for�the�routine!*¦that�handles�the�given�command.  8‰JMP†0(A0,D2.W)‹Transfer�control�to�the�command�routine.‰PAGEO*******************************************************************************O*********************************************************************************ˆSTATUS�COMMAND�ROUTINE*G*ˆThe�command�service�processor�invokes�the�STATCMD�routine�in�responseE*ˆto�a�status�command.‚Its�purpose‚is�to�set�up�the�user�task's�para-E*ˆmeter�block�to�reflect�the‚drive's�current�status�and�configuration=*ˆbased�on�the�configure�block�in�the�drive's�variable�block.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task**’D5�=�03*’D6�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*‰*�* *™A‚*�P�*ƒP�P**ˆCalls:„STATCONF*7*ˆExit:…Falls�through�to�common�exit�routine�(CMDEXIT).*O*******************************************************************************O******************************************************************************* STATCMD: :EQ170„EQU†CONFGBLK+IOSATWˆSet�up�A2�to�point�to�the�IOSATW+‰LEA†EQ170(A1),A2‰field�in�the�drive�block. 2‰BSR.S„STATCONF�Set�IOSDST,�IOSCTP,�IOSDTP,�IOSDRC%*¦in�the�user�task's‚parameter�block. :‰MOVE.WƒREC_ATT(A1),(A0)+†Set�the�IOSATM�and�IOSPRM�fields=‰MOVE.WƒREC_PAR(A1),(A0)+„in�the�user�task's�status�parameter%*¦block.‚The�masks�contain�all�of�the!*¦bits�significant�to�the�driver. 8EQ120„EQU†IOSDLN-IOSATWŠCheck�to�make�sure�the�configure6EQ121„EQU†EQ120/2Žblock�contains�an�integral�number�of6EQ122„EQU†EQ121*2Žwords.�Generate�an�assembly�error�if.‰IFNE…EQ120-EQ122Šthis�assumption�is�not�true.‰FAIL…0‰ENDC ?EQ1120ƒEQU†IOSEATM-IOSATW‡Set�equates�to�copy�parameters�fieldsEQ1121ƒEQU†EQ1120/2 :‰MOVEQWƒEQ1121-1,D0‹Copy�the�drive's�current�configuration?L0130„MOVE.Wƒ(A2)+,(A0)+Švalues�from�the�configure�block�in�the6‰DBRA…D0,L0130�CCB�to�the�user�task's�status�para�blk.)*¦This�portion�copies�only�the�parameters*¦up�to�IOSEATM.‰PAGE<‰MOVE.WƒREC_XAT(A1),(A0)+†Set�the�IOSEATM�and�IOSEPRM�fields=‰MOVE.WƒREC_XPR(A1),(A0)+„in�the�user�task's�status�parameter%*¦block.‚The�masks�contain�all�of�the!*¦bits�significant�to�the�driver. AEQ1122ƒEQU†IOSEATW-IOSEATM†Set�the�pointer�in�the�configure�block8‰ADDQ.Lƒ#EQ1122,A2‹of�the�CCB�to�the�extended�parameters EQ1123ƒEQU†IOSDLN-IOSEATWEQ1124ƒEQU†EQ1123/2 :‰MOVEQWƒEQ1124-1,D0‹Copy�the�dri ve's�current�configuration?L1130„MOVE.Wƒ(A2)+,(A0)+Švalues�from�the�configure�block�in�the6‰DBRA…D0,L1130�CCB�to�the�user�task's�status�para�blk."*¦This�portion�copies�the�extended *¦parameters. ‰PAGEO*********************************************************************************ˆCOMMON�EXIT�ROUTINE*B*ˆThe�CMDEXIT‚routine�is�a‚common�exit�routine�that�is�used�by�theC*ˆmany�different�paths�through�the�command�service�routine.‚ControlC*ˆcomes�to�one�of�three�entry�points�below�to�terminate�processing.*%*ˆEntry:„A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB3*’A6�=�physical�address�of�TCB�of�the�attached�task**�D1.B�=�IOSSTA�status�value*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚R�**™A‚*‰P*1*ˆExit:…Return�to�device-dependent�module�via�RTS*O*******************************************************************************  BCMDEXIT1�MOVEQIƒISTAOK,D1ŒWe've�finished�processing�a�command�with'*¦no�errors�and�we�want�to�queue�an�I/O(*¦completion�event�to�the�attached�task. ECMDEXIT2�LEA‡DO_EVENT(PC),A0…We've�finished�processing�a�command�with8‰MOVE.L„#T0GUARD,D0‰an�error�and�we�want�to�queue�an�I/O/‰TRAP†#0’completion�event�to�the�attached�task.$*¦The�status�value�for�the�completed&*¦command�is�in�D1.B�when�we�get�here. "*¨We�use�CALL-GUARDED�to�queue�the&*¦event�for�command�completion�so�that&*¦it�will�be�protected�from�any�events$*¦queued�from�the�interrupt�handler. BCMDEXIT3�MOVE.LƒSAVESP(A5),SPŠRestore�the�stack�pointer,�and�clear4‰MOVEQ„#0,D0�D0�to�indicate�that�the�command�service(‰RTS›routine�has�operated�properly.‚Then$*¦return�control�to�the�routine�that"*¦called�subroutine�DISK_COMMANDS. #*¨This�exit�is�valid�from�any�level&*¦within�the�driver�because�we�restore(*¦the�SP�as�saved�upon�entry.�The�driver*¦remains�re-entrant.‰PAGEO******************************************************************************** *ˆSTATUS/CONFIGURE�COMMON�CHORES*F*ˆThe�subroutine�STATCONF�performs�functions�that�are�common�to�status?*ˆcommands,�configure�commands,�and�default�configure�commands.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.<*’A2�=�IOSATW�field�in�drive's�configure�block�of�CCB�or�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™DŒ*�* *™A‚*�P�PƒP�P*&*ˆExit:…Return�to�the�calling�routine.*O******************************************************************************* STATCONF: ;‰MOVE.LƒIOSDBP(A4),D6ŠGet�the�physical�address�of�the�first9‰MOVE.Lƒ#IOSDLN,D5‹location�of�the�user�task's�configure/?‰MOVE.LƒCCBTASKA(A5),A0†status�parameter�block�into�D6.‚LOGPHY17‰BSR.L„LOGPHY1Žconverts�the�logical�addres�of�the�users>STATCON1�MOVE.LƒD6,A0�parameter�block�into�a�physical�address. 8‰TST.B„MOUNTED(A1)ŒIf�the�disk�is�not�currently�mounted,/‰SEQ.B„(A0)‘we�set�the�XDSNRB�bit�of�the�IOSDST@‰AND.B„#1<‰MOVEQIƒXDSRDK-XDSFDK,D5…the�IOSATW�field�of�the�configuration8L0180„ADD.B„#XDSFDK,D5‹block�that�is�indicated�by�A2.‚We8‰MOVE.BƒD5,(A0)+�always�use�the�configuration�block�that2L1‡SET†IOSDTP�is�indicated�by�A2�instead�of�simply)*¦using�the�current�configuration�because(*¦we�want�to�maintain�consistency�in�the&*¦case�of�a�default�configure�command. =‰MOVE.B„DRV_CODE(A1),(A0)+„Set�the�I OSDRC�(driver-code)�field1L1‡SET‡IOSDRCŽin�the�user�task's�configure/status**¦parameter�block.�Note�that�A0�now�points(*¦to�the�IOSATM�field�of�the�user�task's&‰RTS›configure/status�parameter�block.‰PAGEO*******************************************************************************O*********************************************************************************ˆDEFAULT�CONFIGURE�COMMAND*H*ˆThe�command�service�processor�invokes�the�DFCONFIG�routine�in�responseG*ˆto�a�default�configure�command.‚Its�purpose�is�to�establish�or�changeE*ˆthe�drive's�default�configuration,�which�is�kept�in�the�drive's�DCB*ˆarea.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory..*’A2�=�physical�address�of�CMR�parameter�block*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*3*’D6�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�*�*ƒP�P*™A‚*�P�*�P�P�P*;*ˆExit:…Branches�to�common�configuration�chores�(CONFGCOM).*O*******************************************************************************O******************************************************************************* DFCONFIG: :EQ160„EQU†DCBDKC+IOSATWŠSet�up�register�A2�to�point�to�the7‰LEA†EQ160(A3),A2‰IOSATW�field�of�the�default�configure"*¦block�in�the�drive's�DCB�(Device*¦Control�Block)�area. 0‰MOVEQ.L‚#0,D5’Clear�D5�to�differentiate�between%*¦a�configure�command�a�def-configure%*¦command�in�the�common�configuration *¦routine. 2‰BRA.S„CONFGCOM�Branch�to�the�common�configuration(*¦routine,�which�does�everything�we�need*¦to�do.‰PAGEO*******************************************************************************O*********************************************************************************ˆCONFIGURE�COMMAND*F*ˆThe�command�service�processor�invokes�the�CONFIG�routine�in�responseC*ˆto�a‚configure�command.‚Its�purpose�is�to�establish�or‚change�theF*ˆdrive's�current�configuration,�which�is�kept�in�the�drive's�variable6*ˆblock�in�the�drive-associated�area�of�global�memory.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*3*’D6�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�*�*ƒP�P*™A‚*�P�*�P�P�P*;*ˆExit:…Branches�to�CMDEXIT2�for�non-existent�devices,�else$*’falls�through�to�CONFGCOM�routine.*O*******************************************************************************O******************************************************************************* CONFIG:2‰BSR.L„CHK_DEVICE�Fill�DRV_CODE,�REC_ATT,�REC_PAR,)*¦REC_XAT,�and�REC_XPR�if�our�device�code(*¦is�found�in�DSKTYPE.‚If�not,�exit�with*¦an�error�to�CMDEXIT2. :EQ210„EQU†CONFGBLK+IOSATWˆSet�up�A2�to�point�to�the�IOSATW9‰LEA†EQ210(A1),A2‰field�of�the�drive's�configure�block�in%*¦the�drive-associated�area�of�global'*¦memory.‚This�configure�block�contains(*¦the�drive's�current�configuration,�and%*¦that's�the�configuration�we�want�to*¦establish�or�change. =EQ220„EQU†DCBDKC+IOSWTOŠCopy�the�IOSWTO�(write-timeout)�field=EQ230„EQU†CONFGBLK+IOSWTO†and�the�IOSRTO�(read-timeout)�fieldB‰MOVE.LƒEQ220(A3),EQ230(A1)‚from�the�drive's�default�configurationEQ250„EQU†CONFGBLK+IOSRTO†block.‚The�user�isn't�allowed�to�setC‰MOVE.LƒEQ240(A3),EQ250(A1)‚or�change�these�values�with�a�configure'*¦command,�so�we�always�use�the�default%*¦values.‚We�need�to�put�these�values&*¦into�the�current�configuration�block$*¦now�so�we'll�have�the�right�values)*¦there�when�we�copy�them�into�the�user's*¦configure�parameter�block. ;‰MOVEQ.L‚#CNFGFUNC,D5‹Put�the�function�code�for�a�configure)*¦command�into�register�D5,�and�fall�into#*¦the�common�configuration�rou tine.‰PAGEO*********************************************************************************ˆCOMMON�CONFIGURATION�CHORES*D*ˆThe‚CONFGCOM‚routine�is�used�by�the‚configure�(CONFIG)�and�defaultF*ˆconfigure�(DFCONFIG)�routines.‚Its�purpose�is�to�do�most�of�the�work*ˆfor�both�of�them.*9*ˆEntry:„A0�=�pointer�to�IOSATM�field�of�user�task's�CSB.:*’A1�=�pointer�to�drive's�variable�block�in�global�memory.5*’A2�=�physical�address�of�IOSATW�field�in�CCB�or�DCB*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task**�D5.L�=�I/O�function�flag5*�D6.L�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�*�*ƒP�P*™A‚*�P�*�P�P�P*C*ˆCalls:„STATCONF,�STATCON1,�CHK_FLOPPY,�CHK_LSN,�CMD_COM,�SET_CNFG*3*ˆExit:…Branches�to�CMDEXIT1�for�default�configure..*’Branches�to�CMDEXIT1�for�configure-dismount.+*’Branches�to�START_IO�for�configure-mount.0*’Branches�to�CONERROR�for�configuration�errors.*O******************************************************************************* CONFGCOM: <‰MOVEM.L‚D6/D5,-(SP)ŠSave�D6�and�D5�(D5�is�on�top�of�stack). 3‰MOVE.Wƒ#$FFFF,D1ŒSet�up�D1.W�with�a�bit�pattern�to>‰SUB.W„REC_PAR(A1),D1‡indicate�the�IOSPRM�bits�we�don't�allow. 2‰BSR.S„STATCONF�Set�IOSDST,�IOSCTP,�IOSDTP,�IOSDRC%*¦in�the�user�task's‚parameter�block. 6‰MOVE.Wƒ(A0)+,D0�Copy�the�user�task's�IOSATM�into�D0.W4‰MOVE.Wƒ(A0)+,D2�and�the�user�task's�IOSPRM�in�D2.W.3L1‡SET†IOSATM�These�masks�indicate�which�fields�the,L1‡SET†IOSPRM�user�task�is�specifying�in�the*¦configure�parameter�block. 3CONERR40�EQU†CECDAP‘If�the�user�task's�IOSPRM�field:‰MOVEQIƒCONERR40,D3Šcontains�any�bits�that�are�not�allowed1‰AND.W„D2,D1�for�the�IOSPRM�field,�abort�with�the4‰BNE.L„CONERROR�error�code�in�D3.B�to�be�returned�to&*¦the�user�task�in�the�IOSDST�field�of *¦the�configure�parameter�block.‰PAGE3CONERR41�EQU†CECDIA‘If�the�user�task's�IOSATM�field:‰MOVEQIƒCONERR41,D3Šcontains�any�bits�that�are�not�allowed6‰MOVE.Wƒ#$FFFF,D1Œfor�the�IOSATM�field,�abort�with�the:‰SUB.W„REC_ATT(A1),D1‡error�code�in�D3.B�to�be�returned�to1‰AND.W„D0,D1�the�user�task�in�the�IOSDST�field�of.‰BNE.L„CONERROR�the�configure�parameter�block. #*¨If�we�don't�abort�here,�we�end�up*¦with�D1.W�=�0�to�use�later�as*¦as�an�index�register. 6‰TAS.B„ACTIVE(A1)�If�the�command�that�we're�processing.‰BNE.S„L0810�is�the�first�configure�or�default:‰MOVEQ.L‚#$FFFFFFFF,D0ˆconfigure�command�received�for�this<‰MOVEQ.L‚#$FFFFFFFF,D2ˆdisk�since�system�initialization,�set'*¦all�bits�of�D0�and�D2.‚These�settings)*¦for�D0�and�D2�will�cause�us�to�copy�all)*¦attribute�and�parameter�fields�from�the'*¦user�task's�configure�parameter�block(*¦into�the�disk's�current�configuration.(*¦This�special�case�allows�IOS�to�set�up%*¦the�disk's�initial�configuration�to%*¦include�even�the�disk-configuration'*¦fields�that�are�not�recognized�by�the *¦driver. 4L0810„AND.W„D0,(A0)�Set�the�IOSATW�field�in�the�user/‰NOT.W„D0“task's�configure�block�to�reflect�the7‰AND.W„(A2)+,D0�final�attributes�that�will�be�in�effect1‰OR.W…D0,(A0)Žwith�the�proposed�configuration.‚We3L1‡SET†IOSATW�compute�this�final�attribute�value�by'*¦combining�the�attribute�bits�that�the)*¦user�task�is�specifying�with�the�values&*¦of�the�remaining�attribute�bits�from(*¦the�existing�configuration.‚The�IOSATM&*¦value�from�the�user�task's�configure'*¦parameter�block�tells�which�attribute'*¦bits�the�user�task�is�specifying,�and(*¦the�other�attribute�bits�come�from�the*¦existing�configuration. 8CONERR42�EQU†CECDIW�If�(1)�the�final�attributes�indicate9‰MOVEQIƒCONERR42,D3Šthat�the�disk�is�a�rigid�disk�and�(2)8‰MOVE.Wƒ(A0)+,D0�they�also�specify�any�attribute(s)�that5‰AND.W„#$1F,D0Žapply�only�to�floppy�disks,�abort�with=‰CMP.W„#1<*‚will�reflect�the�total�configuration�that�is�being�proposed. F*ˆRecall�that�D1.W�=�0�from�above.‚We�also�have�D2.W�=�IOSPRM�from�theH*‚user�task's�configure�parameter‚block,‚or�else�we‚have‚D2.W�=�$FFFF‚ifK*‚we're�processing‚the�first‚configure�command�or�default�configure�commandI*‚that�has‚been‚processed�for�this‚disk�since�system-initialization‚time.L*‚Additionally,�we�have‚A0�=�LOC(IOSREC)�in�the�user�task's�configure�param-I*‚eter�block,‚and�we‚have‚A2�=�LOC(IOSREC)‚in�the�configure�block�that�is*‚being�updated. 1‰BRA.S„L0310’Branch�into�the�loop�that�merges�the#*¦parameter�values.‚We'll�use�D1.W,%*¦which�equals�zero�from�above,�as�an *¦index�into�the�CONFGLEN�table. O*********************************************************************************ˆCONFIGURATION-LENGTH�TABLE*F*ˆThis‚table�defines�the�length�of�each�parameter�field�in�a�configureF*ˆblock�for�a�disk�drive.‚There�is�one�entry�in�the�CONFGLEN�table�forE*ˆeach‚parameter�field�in�a‚configure�block,�and�the�value�of�a�tableD*ˆentry�is‚N-1�where�N�is‚the�length�(in�bytes)‚of�the�corresponding*ˆparameter�field.*O******************************************************************************* CONFGLEN:)‰DC.B…IOSRSZ-IOSREC-1†Length(IOSREC)�-�1.)‰DC.B…IOSWTO-IOSRSZ-1†Length(IOSRSZ)�-�1.)‰DC.B…IOSRTO-IOSWTO-1†Length(IOSWTO)�-�1.)‰DC.B…IOSSPT-IOSRTO-1†Length(IOSRTO)�-�1.)‰DC.B…IOSHDS-IOSSPT-1†Length(IOSSPT)�-�1.)‰DC.B…IOSTRK-IOSHDS-1†Length(IOSHDS)�-�1.)‰DC.B…IOSILV-IOSTRK-1†Length(IOSTRK)�-�1.)‰DC.B…IOSSOF-IOSILV-1†Length(IOSILV)�-�1.)‰DC.B…IOSPSM-IOSSOF-1†Length(IOSSOF)�-�1.)‰DC.B…IOSSHD-IOSPSM-1†Length(IOSPSM)�-�1.*‰DC.B…IOSTRKD-IOSSHD-1…Length(IOSPSD)�-�1.,‰DC.B…IOSPCOM-IOSTRKD-1„Length(IOSTRKD)�-�1.,‰DC.B…IOSSPTD-IOSPCOM-1„Length(IOSPCOM)�-�1.,‰DC.B…IOSSRTD-IOSSPTD-1„Length(IOSSPTD)�-�1.,‰DC.B…IOSEWCC-IOSSRTD-1„Length(IOSSRTD)�-�1.+‰DC.B…IOSECC-IOSEWCC-1…Length(IOSEWCC)�-�1.*‰DC.B…IOSEATM-IOSECC-1…Length(IOSECC)�-�1.$‰DC.B…-1“End-of-Parameters�Sentinel. ECONFGLN:,‰DC.B…IOSGPB2-IOSGPB1-1„Length(IOSGPB1)�-�1.,‰DC.B…IOSGPB3-IOSGPB2-1„Length(IOSGPB2)�-�1.,‰DC.B…IOSGPB4-IOSGPB3-1„Length(IOSGPB3)�-�1.+‰DC.B…IOSSSC-IOSGPB4-1…Length(IOSGPB4)�-�1.*‰DC.B…IOSDRSV-IOSSSC-1…Length(IOSSSC)�-�1.-‰DC.B…-1“End-of-Extended-Parameters�Sentinel.,‰DS.W†0“Ensure�its�aligned�to�word�boundary.‰PAGE*G*ˆThis�loop,�which�is�entered�at�L0310,�processes�the�parameter�fields.* 2L0280„ROR.W„#1,D2’Bring�the�next�bit�of�the�IOSPRM&*¦field�into�bit�15�of�D2�where�we�can*¦easily�test�it. 0L0290„TST.W„D2•If�the�parameter-mask�bit�is�set,2‰BMI.S„L0300�the�user�is�specifying�this�parameter3‰MOVE.Bƒ(A2),(A0)Œvalue.‚Otherwise,�the�user�is�not>L0300„CMP.B„(A2)+,(A0)+Šspecifying�this�parameter�value,�so�we3‰DBRA…D0,L0290�copy�the�parameter�from�the�existing$*¦configuration�into�the�user�task's&*¦configure�parameter�block.‚This�loop$*¦processes�one�byte�at�a�time�until$*¦we've�processed�all�byte(s)�of�the%*¦current�parameter�field.‚Notice�the)*¦use�of�the�CMP.B�instruction�to�advance*¦both�address�registers. /‰ADDQ.Wƒ#1,D1’Advance�D1.W�to�index�to�the�next$*¦byte�of�the�CONFGLEN�table.‚Recall)*¦that�we�had�D1.W�=�0�when�control�first*¦entered�this�loop. DL0310„MOVE.BƒCONFGLEN(PC,D1.W),D0ƒGet�the�next�entry�of�the�CONFGLEN,‰EXT.W„D0“table�into�D0.W.‚This�value�is�N-14‰BGE.S„L0280�where�N�is�the�number�of�byte(s)�in�the%*¦next�parameter�field.‚If�we�haven't#*¦reached�the�negative�end-of-table&*¦sentinel�entry,�loop�back�to�process*¦the�next�parameter�field. ?*ˆNow�we�want�to �process�the�Extended�Parameters�and�Attributes 3‰MOVE.Wƒ#$FFFF,D1ŒSet�up�D1.W�with�a�bit�pattern�to>‰SUB.W„REC_XPR(A1),D1‡indicate�the�IOSEPRM�bits�we�don't�allow 7‰MOVE.Wƒ(A0)+,D0�Copy�the�user�task's�IOSEATM�into�D0.W5‰MOVE.Wƒ(A0)+,D2�and�the�user�task's�IOSEPRM�in�D2.W.4L1‡SET†IOSEATMŽThese�masks�indicate�which�fields�the-L1‡SET†IOSEPRMŽuser�task�is�specifying�in�the*¦configure�parameter�block. "*¦If�the�user�task's�IOSEPRM�field:‰MOVEQIƒCONERR40,D3Šcontains�any�bits�that�are�not�allowed2‰AND.W„D2,D1�for�the�IOSEPRM�field,�abort�with�the4‰BNE.L„CONERROR�error�code�in�D3.B�to�be�returned�to&*¦the�user�task�in�the�IOSDST�field�of *¦the�configure�parameter�block.EQU1000‚EQU†IOSEATW-IOSEATM5‰ADDQ.Lƒ#EQU1000,A2ŒIncrement�to�the�IOSEATW�field�of*¦configure�parameter�block‰PAGE"*¦If�the�user�task's�IOSEATM�field:‰MOVEQIƒCONERR41,D3Šcontains�any�bits�that�are�not�allowed7‰MOVE.Wƒ#$FFFF,D1Œfor�the�IOSEATM�field,�abort�with�the:‰SUB.W„REC_XAT(A1),D1‡error�code�in�D3.B�to�be�returned�to1‰AND.W„D0,D1�the�user�task�in�the�IOSDST�field�of.‰BNE.L„CONERROR�the�configure�parameter�block. #*¨If�we�don't�abort�here,�we�end�up*¦with�D1.W�=�0�to�use�later�as*¦as�an�index�register. 8‰BTST…#6,ACTIVE(A1)ˆIf�the�command�that�we're�processing.‰BNE.S„L1810�is�the�first�configure�or�default:‰MOVEQ.L‚#$FFFFFFFF,D0ˆconfigure�command�received�for�this<‰MOVEQ.L‚#$FFFFFFFF,D2ˆdisk�since�system�initialization,�set9‰BSET…#6,ACTIVE(A1)ˆall�bits�of�D0�and�D2.‚These�settings)*¦for�D0�and�D2�will�cause�us�to�copy�all)*¦attribute�and�parameter�fields�from�the'*¦user�task's�configure�parameter�block(*¦into�the�disk's�current�configuration.(*¦This�special�case�allows�IOS�to�set�up%*¦the�disk's�initial�configuration�to%*¦include�even�the�disk-configuration'*¦fields�that�are�not�recognized�by�the *¦driver. 5L1810„AND.W„D0,(A0)�Set�the�IOSEATW�field�in�the�user/‰NOT.W„D0“task's�configure�block�to�reflect�the7‰AND.W„(A2)+,D0�final�attributes�that�will�be�in�effect2‰OR.W…D0,(A0)+�with�the�proposed�configuration.‚We4L1‡SET†IOSEATW�compute�this�final�attribute�value�by'*¦combining�the�attribute�bits�that�the)*¦user�task�is�specifying�with�the�values&*¦of�the�remaining�attribute�bits�from)*¦the�existing�configuration.�The�IOSEATM&*¦value�from�the�user�task's�configure'*¦parameter�block�tells�which�attribute'*¦bits�the�user�task�is�specifying,�and(*¦the�other�attribute�bits�come�from�the*¦existing�configuration. ‰BRA.S…L1310 ‰PAGE*F*ˆNow�we�want�to�process�the�parameter�fields.‚For�any�parameter�fieldM*‚that�the�user�task�is�not�specifying,�we'll�copy�the�existing�configurationL*‚value�into�the�user�task's�configure�parameter�block.‚The�resulting�mergedK*‚parameter�values�that�end�up‚in‚the�user�task's�configure�parameter�block>*‚will�reflect�the�total�configuration�that�is�being�proposed. G*ˆRecall�that�D1.W�=�0�from�above.‚We�also�have�D2.W�=�IOSEPRM�from�theH*‚user�task's�configure�parameter‚block,‚or�else�we‚have‚D2.W�=�$FFFF‚ifK*‚we're�processing‚the�first‚configure�command�or�default�configure�commandI*‚that�has‚been‚processed�for�this‚disk�since�system-initialization‚time.M*‚Additionally,�we�have‚A0�=�LOC(IOSGPB1)�in�the�user�task's�configure�param-J*‚eter�block,‚and�we‚have‚A2�=�LOC(IOSGPB1)‚in�the�configure�block�that�is*‚being�updated. 3L1280„ROR.W„#1,D2’Bring�the�next�bit�of�the�IOSEPRM&*¦field�into�bit�15�of�D2�where�we�can*¦easily�test�it. 0L1290„TST.W„D2•If�the�parameter-mask�bit�is�set,2‰BMI.S„L1300�the�user�is�specifying�this�parameter3‰MOVE.Bƒ(A2),(A0)Œvalue.‚Otherwise,�the�user�is�not>L1300„CMP.B„(A2)+,(A0)+Šspecifying�this�parameter�value,�so�we3‰DBRA…D0,L1290�copy�the�parameter�from�the�existing$*¦configuration�into�the�user�task's&*¦configure�parameter�block.‚This�loop$*¦processes�one�byte�at�a�time�until$*¦we've�processed�all�byte(s)�of�the%*¦current�parameter�field.‚Notice�the)*¦ use�of�the�CMP.B�instruction�to�advance*¦both�address�registers. /‰ADDQ.Wƒ#1,D1’Advance�D1.W�to�index�to�the�next$*¦byte�of�the�ECONFGLN�table.‚Recall)*¦that�we�had�D1.W�=�0�when�control�first*¦entered�this�loop. DL1310„MOVE.BƒECONFGLN(PC,D1.W),D0ƒGet�the�next�entry�of�the�ECONFGLN,‰EXT.W„D0“table�into�D0.W.‚This�value�is�N-14‰BGE.S„L1280�where�N�is�the�number�of�byte(s)�in�the%*¦next�parameter�field.‚If�we�haven't#*¦reached�the�negative�end-of-table&*¦sentinel�entry,�loop�back�to�process*¦the�next�parameter�field. &*¨Notice�that�A0�points�to�the�IOSDRSV$*¦field�of�the�user�task's�configure(*¦parameter�block�when�control�falls�out'*¦of�this�loop.‚Similarly,�A2�points�to$*¦the�IOSDRSV�field�of�the�configure%*¦block�for�the�configuration�that�is*¦being�updated.‰PAGEG*ˆNow�we�want�to�check�the�proposed�configuration�to�see�if�it�containsK*‚any�invalid‚or�inconsistent�configuration�values.‚If�it�does,�we'll�abort#*‚with�an�appropriate�error�report. 4CONERR43�EQU†CECDII‘The�interleave�factor�for�a�disk6‰MOVEQIƒCONERR43,D3Šmust�be�in�the�range�1�through�the8EQ320„EQU†IOSILV-IOSDRSV‡number�of�sectors�per�track.‚If7‰MOVE.BƒEQ320(A0),D0‰the�IOSILV�parameter�isn't�in�this6‰BEQ.L„CONERROR�range,�abort�with�an�error�report.�The>EQ321„EQU†IOSSPT-IOSDRSV‡error�is�returned�to�the�user�task�in5‰CMP.B„EQ321(A0),D0‰the�IOSDST�field�of�the�configure ‰BHS.L„CONERROR�parameter�block.* 5EQ322„EQU†IOSSOF-IOSDRSV‰The�spiral�offset�for�a�disk7‰MOVE.BƒEQ322(A0),D0‰must�be�in�the�range�0�through�the3‰CMP.B„EQ321(A0),D0‰number�of�sectors�per�track.‚If2‰BHS.L„CONERROR�the�IOSSOF�parameter�isn't�in�this$*¦range,�abort�with�an�error�report.* 1CONERR44�EQU†CECDSS‘The�driver�contains�code�that;‰MOVEQIƒCONERR44,D3Šassumes�that�the�logical�sector�size�is&*¦a�nonzero�multiple�of�LCDSCTSZ�where>EQ325„EQU†IOSPSM-IOSDRSV‡LCDSCTSZ�is�defined�to�be�the�largest9‰MOVE.WƒEQ325(A0),D0‰common�divisor�of�all�possible�valid5‰BEQ.L„CONERROR�sector�sizes.‚Here�we�check�to�verify'*¦that�the�logical�sector�size�(IOSPSM)#*¦is�nonzero.‚If�we�abort�here,�the(*¦error�code�in�D3.B�will�be�returned�to&*¦the�user�task�in�the�IOSDST�field�of *¦the�configure�parameter�block. ;‰MOVEQ.L‚#VDOSRSZ>>2,D1‰Now�we�get�the�VERSAdos�record�size3‰ASL.L„#2,D1�into�D1.L,�and�we�set�the�IOSREC�field?EQ326„EQU†IOSREC-IOSDRSV‡of�the�configure�parameter�block�equal;‰MOVE.WƒD1,EQ326(A0)‰to�the�VERSAdos�record�size.‚We�save�a)*¦word�of�memory�here�by�taking�advantage&*¦of�the�fact�that�the�VERSAdos�record *¦size�is�evenly�divisible�by�4. 8EQ327„EQU†VDOSRSZ>>2�If�the�VERSAdos�record�size�is�ever9EQ328„EQU†EQ327<<2�changed�so�that�it�isn't�a�multiple�of6‰IFNE…VDOSRSZ-EQ328ˆ4,�we�want�to�generate�an�assembly/‰FAIL…0”[****�ERROR�****�ERROR�****�ERROR�****]-‰ENDCšerror�to�alert�the�confused�maintenance'*¦programmer�to�the�problem�that�arises(*¦here.‚The�instruction�that�is�normally$*¦skipped�here�generates�an�assembly)*¦error�if�the�VERSAdos�record�size�isn't*¦a�multiple�of�4.‰PAGE.‰DIVU…D0,D1’We�require�that�the�logical�sector*‰SWAP…D1“size�(in�D0.W)�evenly�divides�the(*¦VERSAdos�record�size�(in�D1)�so�we�can)*¦translate�an�integral�number�of�logical(*¦sector(s)�into�a�VERSAdos�record.‚Here(*¦we�get�the�remainder�from�the�division(*¦into�D1.W,�and�we�save�the�quotient�in*¦the�top�half�of�D1. >‰AND.W„#(1<‚THEN�track�must�be�nonzero�and�EVEN.‹LSR.B‚#1,D0�D0�<--�IOSSPT�/�2.2‹BCS.L‚CONERROR�Error�if�sectors�per�track�is�odd."*¦We�save�the�IOSSPT�value�in�D2.W)*¦for�future�use,�and�we�save�IOSSPT/2�in$*¦D0.L�for�future�use�(floppy�only). %*¨We�must�have�an�even�number�for�the(*¦number�of�sectors�per�track�because�we(*¦pair�up�the�sectors�in�track�zero�of�a&*¦256�BYTES/SECTOR�floppy�disk.‚Recall'*¦that�track�zero�of�a�256�BYTES/SECTOR'*¦floppy�disk�is�recorded�in�128�BYTES/&*¦SECTOR,�so�two�sectors�in�track�zero)*¦are�equal�in�size�to�a�single�sector�in'*¦any�other�track�of�a�256�BYTES/SECTOR*¦floppy�disk.‰ENDI‰PAGE8CONERR46�EQU†CECDDS‘Get�the�error�code�that�we'll�use�to9‰MOVEQIƒCONERR46,D3Šindicate�that�something�is�wrong�with*¦the�disk's�capacity. 5‰MOVEQ.L‚#0,D5�Initialize�number�of�surfaces�to�zero. :EQ330„EQU†IOSATW-IOSDRSV‰Determine�rigid�or�floppy�disk�to>‰BTSTW„#IOARDISC,EQ330(A0)‚use�in�calculation�of�#�of�heads�or‰BNE.S„L0320�#�of�sides.*B*„Check�to�make�sure�that�the�bytes�per�sector,�sectors�per�track,A*„and�data�density�values�are�consistent�for�5�1/4"�and�8"�floppyF*„diskettes.‚If�not,�go�to�CONERROR�with�a�error�code�$47.ƒ11/7/84�BWN*8CONERR47�EQU†CECDFC‘Get�the�error�code�that�we'll�use�to8‰MOVEQI„CONERR47,D3‰indicate�that�there�is�a�conflict�in9‰T_JSR…CHK_FLOPPYŠthe�floppy�disk�configuration.‚If�there5‰BNE.L…CONERRORŒis�an�error,�branch�to�CONERROR.�Else8‰MOVEQIƒCONERR46,D3Šrestore�error�code�for�next�routine. 2‰ADDQ.Lƒ#1,D5’Set�D5�=�1�for�a�single-sided�floppy?‰BTSTW„#IOADSIDE,EQ330(A0)‚disk.‚Determine�the�actual�number�of/‰BEQ.S„L0845�sides�from�the�IOADSIDE�bit�of�the-‰ADDQ…#1,D5�attributes�word.�If�double-sided,‰BRA.S„L0845�Set�D5�=�2. ;EQ840„EQU†IOSHDS-IOSDRSV‰We�have�a�rigid�disk,�so�calculate.L0320„MOVE.BƒEQ840(A0),D5‰the�number�of�heads. 4L0845„MULU…D5,D2’Compute�the�total�number�of�logical‚THEN‘of�logical�sectors�to�account�for�theC‰CMP.W�#VDOSRSZ,IOSPSM-IOSDRSV(A0)�fact�that�the�sectors�in�track�03‰IF�‚THEN‘of�a�256�BYTES/SECTOR�floppy�disk�are0‰SUB.L„D0,D2�half�as�large�as�normal�sectors.‚We7‰BLS.L„CONERROR�now�have�the�total�capacity�of�the�disk-‰ENDIšin�terms�of�full-sized�logical�sectors.*‰ENDIšIf�the�total�capacity�of�the�disk�in(*¦terms�of�full-sized�logical�sectors�is#*¦zero�or�less,�we�r eport�an�error. 0‰MOVE.LƒD2,D0’We�want�to�divide�the�disk's�total0‰CLR.W„D2“sector�count�(in�D2)�by�VDOSRSZ/IOSPSM)‰SWAP…D2“(in�D1)�to�obtain�the�total�disk/‰DIVU…D1,D2�capacity�terms�of�VERSAdos�records.>EQ880„EQU†IOSRSZ-IOSDRSV‡Unfortunately,�the�resulting�quotient:‰MOVE.WƒD2,EQ880(A0)‰can�be�a�32-bit�number,�and�the�680002‰MOVE.WƒD0,D2�is�limited�to�16-bit�quotients.‚This1‰DIVU…D1,D2�code�performs�the�division�to�yield�a8‰MOVE.WƒD2,EQ880+2(A0)‡32-bit�quotient,�and�we�store�the%*¦result�into�the�IOSRSZ�field�of�the(*¦user�task's�configure�parameter�block.%*¦We�simply�discard�the�remainder�(if$*¦any),�so�the�user�can't�access�any$*¦partial�VERSAdos�record�that�might*¦exist�at�the�end�of�the�disk. %*¨We�perform�the�division�analogously)*¦to�the�way�a�person�does�long�division.)*¦The�difference�is�that�we�use�a�base�of#*¦65,536�instead�of�base�10.‚Divide)*¦fault�can't�occur�on�the�first�division)*¦because�we�reduce�the�dividend�to�a�16-&*¦bit�number.‚Divide�fault�can't�occur$*¦on�the�second�division�because�the)*¦remainder�in�the�top�half�of�D2�must�be*¦less�than�the�divisor. 1‰IFEQ…VDOSRSZ�To�guarantee�that�divide�fault�does/‰FAIL…0”[****�ERROR�****�ERROR�****�ERROR�****],‰ENDCšnot�occur,�we�must�assure�that�VDOSRSZ *¦is�nonzero. 7‰T_JSR…CHK_PARAM‹Now�we�must�check�any�device�dependent(‰BNE‡CONERRORŒparameters�for�any�errors. ‰PAGEG*ˆFinally,�we're�ready�to�copy�the�proposed�configuration�from�the�userI*‚task's‚configure‚parameter�block�into�the�configure�block�that�is�being *‚updated. A‰MOVEQWƒIOSDRSV-IOSEATW-1,D0„All�parameters�and�attributes�in�the=L0330„MOVE.Bƒ-(A0),-(A2)Šproposed�configuration�are�valid,�so3‰DBRA…D0,L0330�copy�the�proposed�configuration�into=EQU1001‚EQU†IOSEATW-IOSEATM†the�configure�block�that�is�being5‰SUBQ.Lƒ#EQU1001,A0Šupdated.‚For�a�configure�command,8‰SUBQ.Lƒ#EQU1001,A2Šwe're�updating�the�current�configure?‰MOVEQWƒIOSEATM-IOSATW-1,D0‚block�in�the�drive's�variable�block3L1330„MOVE.Bƒ-(A0),-(A2)Šwhich�is�in�global�memory,2‰DBRA†D0,L1330Œand�for�a�default�configure�command&*¦we're�updating�the�default�configure'*¦block�in�the�drive's�DCB.‚Notice�that)*¦we�copy�the�IOSATW�field�and�all�of�the)*¦parameter�fields,�but�we�don't�copy�the%*¦mask�fields�because�the�mask�fields(*¦aren't�really�part�of�the�total�device*¦configuration. $*¨At�the�conclusion�of�this�step,�A2#*¦points�to�the�IOSATW�field�of�the'*¦configure�block�that's�being�updated,&*¦so�A2�is�set�properly�for�us�to�call*¦subroutine�STATCON1. /‰TST.L„(SP)“Recall�that�the�value�on�top�of�the0‰BEQ.S„L0830�stack�is�zero�if�we're�performing�a(*¦default�configure�command.‚We�skip�the$*¦next�section�of�code�for�a�default&*¦configure�command,�and�we�execute�it)*¦only�for�an�ordinary�configure�command. D*ˆThis‚section‚of�code‚is�executed�only�for�a�configure�command,�not"*‚for�a�default�configure�command.  :‰MOVE.WƒD1,SCTPVREC(A1)ˆSet�SCTPVREC�<--�VDOSRSZ/IOSPSM�to(*¦indicate�the�number�of�logical�sectors'*¦in�a�VERSAdos�record.‚Recall�that�the(*¦desired�value�was�computed�earlier�and%*¦was�kept�in�D1.‚We�need�to�know�how'*¦many�logical�sector(s)�there�are�in�a)*¦VERSAdos�record�so�we�can�make�the�disk(*¦appear�to�contain�VERSAdos�records.‚We"*¦don't�want�to�set�SCTPVREC�for�a#*¦default�configure�command�because%*¦SCTPVREC�is�effectively�part�of�the)*¦drive's�current�configuration,�not�part'*¦of�the�drive's�default�configuration.‰PAGE7‰MOVE.WƒIOSOPT(A4),D0ŠIf�the�entire�IOSOPT�field�of�the2‰BNE.S„L0820�IOCB�is�zero,�set�the�MOUNTED�flag�to8‰ST.B…MOUNTED(A1)Šindicate�that�the�disk�is�now�mounted.(*¦A�configure�command�with�a�zero�IOSOPT(*¦field�is�defined�to�be�a�configure�and*¦mount�command. 6L0820„CMP.W„#IOPDMNT,D0ŒIf�the�IOSOPT�field�is�set�for2‰IF��THEN’Dismount,�clear�the�MOUNTED�flag�and;‰CLR.B„MOUNTED(A1)Šset�the�DCBCCF�flag�to�indicate�the�disk7‰ST.B…DCBCCF(A3)‹is�now�dismounted.‚A�configure�command4‰BRA†CMDEXIT1� with�this�option�bit�set�is�defined�to*‰ENDIšbe�a�configure�and�dismount�command.$*¦Setting�the�DCBCCF�flag�in�the�DCB%*¦indicates�that�the�operating�system(*¦should�return�the�drive�to�its�default*¦configuration. @*ˆControl‚converges‚here‚for‚both‚configure‚commands‚and�default*‚configure�commands. 5L0830„BSR†STATCON1�Set�IOSDST,�IOSCTP,�IOSDTP,�IOSDRC%*¦in�the�user�task's‚parameter�block. "‰MOVEM.L‚(SP)+,D5/D6ŠRestore�Regs.1‰TST.L„D5“Does�D5�contain�a�0�for�a�def-conf�cmd?/‰BEQ†CMDEXIT1�Done�if�it�does...branch�to�exit. ,‰BSR†CMD_COMŽDo�stuff�common�to�all�commands8‰T_JSR„SET_CNFG�Get�configure�parameters�in�drive�block.-‰IF�‚THEN‘Condition�codes�set��if�the/ŠBRA…CMDEXIT2Ždrive/controller�does�not�support!‰ENDI›configure�command,�so�exit!&‰BRA.L„START_IO�Start�the�I/O�rolling!*8* Registers are set as follows before executing CMD_COM:**ˆA6�=�TCB�of�attached�task. *ˆA5�=�CCB *ˆA4�=�IOCB *ˆA3�=�DCB#*ˆA1�=�Disk�drive's�variable�block.*ˆD6�=�Drive's�device�number.*ˆD5�=�1�=�I/O�function�flag.‰PAGEO*********************************************************************************ˆCONFIGURATION�ERROR�ROUTINE*E*ˆControl�comes�to�this�routine�when‚it�is�necessary�to�abort�with�anE*ˆerror�code�from�any�configuration�command.‚Error�codes�in�the�rangeC*ˆ$01�to�$3F‚are�universal.‚Error�codes�in�the�range‚$40�to�$7F�are*ˆunique�to�this�driver.*!*ˆEntry:„D3�=‚detailed�error�code<*’D6�=‚physical�address�of�user's�task�configure�para.�block*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D„RƒP…P*™A‚**2*ˆExit:…Branches�to�common�exit�routine�(CMDEXIT).*O*******************************************************************************  CONERROR: 2‰MOVE.LƒD6,A0’Put�the�detailed�error�code�into�the5‰MOVE.BƒD3,IOSDST(A0)ˆIOSDST�field�of�the�user�task's9‰MOVEQIƒISTACNF,D1‹configure�parameter�block,�and�then�go4‰BRA†CMDEXIT2�to�the�command�processor's�common�exit(*¦routine�with�D1.B�set�up�to�report�the#*¦major�error�code�that�indicates�a*¦configuration�error.‰PAGEO*******************************************************************************O*********************************************************************************ˆREAD�COMMAND�ROUTINE*G*ˆThe�command�service�processor�invokes�the�READCMD�routine�in�responseB*ˆto�a�read�command.‚Its�purpose�is�to�prepare�for�a�data�transferE*ˆfrom�the�disk�to�memory�based�on�the�drive's�current�configuration.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task**’D5�=�03*’D6�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�*�*�*�*�* *™A‚*�PƒP�P�P***ˆCalls:„CHK_MT,�CMD_COM,�BUF_COM,�CONVERT*-*ˆExit:…Branches�to�START_IO�routine�if�okay.,*’Branches�to�CMDEXIT2�if�error�is�detected.*O*******************************************************************************O******************************************************************************* READCMD:.‰BSR†CHK_MT�Determine�if�the�drive�is�mounted. ;‰MOVEQ.L‚#READFUNC,D5‰Set�up�flag�for�read�command�into�D5.)‰BSR†CMD_COMŽDo�the�stuff�common�for�I/O.1‰BSR.L„BUF_COMŽDo�the�stuff�common�to�read/write.6‰BSR.L„CONVERTŽConvert�the�VERSAdos�sector�to�logical.‰BRA.L„START_IO‰PAGEO*******************************************************************************O*********************************************************************************ˆWRITE�COMMAND�ROUTINE*H*ˆThe�command�service�processor�invokes�the�WRITECMD�routine�in�responseC*ˆto�a�write�command.‚Its�purpose�is�to�prepare�for�a�data�transferE*ˆfrom�memory�to�the�disk�based�on�the�drive's�current�configuration.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6 �=�physical�address�of�TCB�of�attached�task**’D5�=�03*’D6�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�*�*�*�*�* *™A‚*�PƒP�P�P***ˆCalls:„CHK_MT,�CMD_COM,�BUF_COM,�CONVERT*-*ˆExit:…Branches�to�START_IO�routine�if�okay.,*’Branches�to�CMDEXIT2�if�error�is�detected.*O*******************************************************************************O******************************************************************************* WRITECMD:.‰BSR†CHK_MT�Determine�if�the�drive�is�mounted. 9‰MOVEQ.L‚#WRTFUNC,D5ŠSet�up�flag�for�write�command�in�D5.)‰BSR†CMD_COMŽDo�the�stuff�common�for�I/O.1‰BSR.L„BUF_COMŽDo�the�stuff�common�to�read/write.6‰BSR.L„CONVERTŽConvert�the�VERSAdos�sector�to�logical.‰BRA.L„START_IO‰PAGEO*******************************************************************************O*********************************************************************************ˆFORMAT�COMMAND�ROUTINE*F*ˆThe�command�service�processor�invokes�the�FORMAT�routine�in�responseE*ˆto�a�format�command.‚Its�purpose�is�to�prepare�to�format-alternate,E*ˆformat-disk�or�format-track�based�on�drive's�current�configuration.*Ü Å5Î;Ö?Þ>æ5î5ö7þ68=??&C.?6F>>F;N8VA*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task**’D5�=�03*’D6�=�Channel�device�#�for�the�disk�drive�(DCBCDV)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�*�*�*�*�* *™A‚*�PƒP�P�P***ˆCalls:„CHK_MT,�CMD_COM,�CONVERT,�FRMTALT*-*ˆExit:…Branches�to�START_IO�routine�if�okay.,*’Branches�to�CMDEXIT2�if�error�is�detected.*O*******************************************************************************O******************************************************************************* FORMAT:.‰BSR†CHK_MT�Determine�if�the�drive�is�mounted. :‰MOVEQ.L‚#FMTFUNC,D5ŠSet�up�flag�for�format�command�in�D5.2‰BSR†CMD_COMŽDo�the�stuff�common�for�all�commands. .‰MOVEQ.L‚#0,D2�Set�the�VERSAdos�record�length.6‰BSR.L„CONVERTŽConvert�the�VERSAdos�sector�to�logical.*A*ˆFor�alternate�sector�commands,�Offset�IOSALT�=�IOSSAD�holds�the@*ˆsector�number�for�the�alternate�sector,�and�we�want�to�save�it*ˆin�IOBUFLOC�=�IOALTSEC.*-‰CMP.W„#IOPBAD,IOOPTS(A1)ƒFormat�bad�command? ‰IF‡�THEN=ŠMOVE.LƒIOSSAD(A4),D6‡Get�sector�number�of�alternate�into�D6.3ŠBSR.LƒFRMTALTŽExecute�subroutine�to�set�things�up.‰ENDI ‰BRA.L„START_IO‰PAGEO********************************************************************************0*ˆSUBROUTINE�TO�CHECK�FOR�THE�DISK�BEING�MOUNTED*C*ˆThis�subroutine�is�called�by�the�READ,�WRITE�and�FORMAT�commands.A*ˆIts�function�is�to�check�the�MOUNTED�byte�of�the�drive�block�toC*ˆensure�the�drive�is�mounted�before�processing�the�command.‚If�the8*ˆdrive�is�not�mounted,�we�exit�with�an�error�condition.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*%*ˆExit:…RTS�to�caller�if�all�is�okay."*’CMDEXIT2�if�disk�is�not�mounted.*O******************************************************************************* CHK_MT:8‰MOVEQIƒISTADNM,D1�If�the�disk�that�is�being�accessed�is6‰TST.B„MOUNTED(A1)Šnot�mounted,�reject�the�command�and#‰BEQ†CMDEXIT2�return�an�error�code. ‰RTS‰PAGEO********************************************************************************.*ˆSUBROUTINE�TO�DO�WORK�COMMON�TO�ALL�COMMANDS*C*ˆThis�routine�is�called�by�the�handlers�of�READ,�WRITE,�FORMAT�andB*ˆCONFIGURE�commands.‚Its�function�is�to�do�the�work�common�to�all@*ˆcommands�going�to�the�disk�controller.‚It�stores�the�following 7*ˆfields�in�the�drive�block:‚IOOPTS,�DRIVENUM,�IOFUNCT,'*¤CTRLCODE,�IOCBPTR,�DCBPNTR,�IOBUFTCB.G*ˆIt�initializes�EOVFLAG�to�contain�good�status.�It�clears�these�fields3*ˆin�the�drive�block:‰NOFINISH,�HALFSCTS,�IOSCTCNT,)*¤IOSECTOR,�IOBUFEND,�IOBUFLOC,�IOBUFPTR.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task**’D5�=�I/O�Function�flag*’D6�=�Device�number*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D„* *™A‚*�P…P*0*ˆCalls:„SET_CODE�in�the�device-dependent�module**ˆExit:…RTS�back�to�the�caller.*O******************************************************************************* CMD_COM: =‰MOVE.LƒCCBTASKA(A5),A0†Point�A0�to�the�TCB�that�controls�the*¦task�that�owns�the�IOCB. *7*ˆSave�the�variables�we�have�so�far�in�the�drive�block.*C‰MOVE.WƒIOSOPT(A4),IOOPTS(A1)�Copy�the�I/O�options�field,�the�drive=‰MOVE.BƒD6,DRIVENUM(A1)†number�and�the�I/O�function�flag�into'‰MOVE.BƒD5,IOFUNCT(A1)‡the�drive�block. 1‰T_JSR„SET_CODE�Calculate�the�controller�code�and*¦copy�it�into�the�drive�block.‰PAGEC‰MOVEM.L‚A0/A3/A4,IOBUFTCB(A1)‚Save�the�TCB,DCB�and�IOCB�addresses. *%*ˆInitialize�EOVFLAG�for�good�status.*5‰MOVEQIƒISTAOK,D1ŒInitialize�EOVFLAG�to�indicate�good‰MOVE.BƒD1,EOVFLAG(A1)‡status.*8*ˆClear�the�variables�that�we�don't�have�values�for�yet.*‰MOVE.Lƒ#0,IOBUFPTR(A1)‰MOVE.Lƒ#0,IOBUFLOC(A1)‰MOVE.Lƒ#0,IOBUFEND(A1)‰MOVE.Lƒ#0,HALFSCTS(A1)‰MOVE.Lƒ#0,IOSECTOR(A1)‰MOVE.Lƒ#0,IOSCTCNT(A1)  ‰MOVE.Bƒ#0,NOFINISH(A1) ‰RTS‰PAGEO********************************************************************************9*ˆSUBROUTINE�TO�DO�WORK�COMMON�TO�READ�AND�WRITE�COMMANDS*:*ˆThis�routine�is�called�by�the�handlers�of�READ�and�WRITE?*ˆcommands.‚Its�function�is�to�check�that�the�drive�is�mounted,<*ˆget�the�VERSAdos�random�record�number,�validate�the�buffer:*ˆaddress�and�length,�and�fill�the�following�fields�in�the6*ˆdrive�block:‚IOBUFEND,�IOBUFTCB,�IOBUFPTR,�IOBUFLOC.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�*�Rƒ*�*�* *™A‚*�P…P*7*ˆExit:…D2�=�Count�of�VERSAdos�records�to�be�processed.**ˆCalls:„LOGPHY1*.*ˆExits�to:�RTS�back�to�caller�if�all�is�okay. *’CMDEXIT2�if�error�is�detected.*O******************************************************************************* BUF_COM: =‰MOVE.LƒCCBTASKA(A5),A0†Point�A0�to�the�TCB�that�controls�the*¦task�that�owns�the�IOCB. *B*ˆThe�IOOPTS�field�already�stored�in�the�drive�block�tells�us�when@*ˆthe�IOCB�includes�the�optional�IOSTSK�and�IOSSES�fields.‚TheseB*ˆfields�designate�the�task�that�owns�the�I/O�buffer�when�the�task>*ˆthat�owns�the�IOCB�is�a�system�task�that�doesn't�own�the�I/O *ˆbuffer. 5ˆTST.W„IOOPTS(A1)‹Test�the�options�field�for�Task�ID.0ˆIF��THEN’If��the�task�is�a�system�task. 6‰LEA†IOSTSK(A4),A0ŠWe�need�to�get�a�pointer�to�the�TCB5‰MOVE.LƒA1,-(SP)�that�controls�the�task�that�owns�the7‰MOVE.Lƒ#T0GETTCB,D0‰I/O�buffer.‚The�T0GETTCB�executive/‰TRAP…#EXEC�request�uses�A0�as�a�pointer�to�the4‰BRA.S„L0350�IOSTSK/IOSSES�packet,�and�it�returns�A0)*¦with�a�pointer�to�the�TCB�that�controls"*¦the�specified�task.‚The�T0GETTCB(*¦executive�request�destroys�A1,�D0,�D1,)*¦and�D2,�but�we�preserve�the�value�of�A1$*¦by�saving�it�on�the�stack.‚Control%*¦returns�from�the�T0GETTCB�executive(*¦request�to�the�instruction�immediately&*¦following�the�TRAP�instruction�if�no*¦errors�are�detected. 9L0340„MOVEQIƒISTAADD,D1�Control�returns�from�the�T0GETTCB4‰BRA†CMDEXIT2�executive�request�to�this�point�if�the'*¦specified�task�doesn't�exist.‚In�this%*¦case,�we�report�an�error�indicating$*¦th at�the�specification�for�the�I/O%*¦buffer�is�bad.‚Notice�that�we�don't(*¦need�to�clean�up�the�stack�because�the*¦error�routine�cleans�it�up. 8L0350„MOVE.Lƒ(SP)+,A1�Restore�A1�to�point�to�the�drive's)*¦area�of�the�drive-associated�portion�of*¦global�memory.‰ENDI 1‰MOVE.LƒA0,IOBUFTCB(A1)ˆSave�the�new�TCB�address. 9‰MOVE.LƒIOSSAD(A4),D6ŠGet�the�physical�address�of�the�I/O<‰MOVE.LƒIOSEAD(A4),D5ˆbuffer�into�D6,�and�get�the�length�(in.‰SUB.L„D6,D5�bytes)�of�the�I/O�buffer�into�D5.5‰ADD.L„#1,D5�Subroutine�LOGPHY1�requires�the�buffer's3‰BSR.L„LOGPHY1Žlogical�address�and�its�length�in�D6&*¦and�D5�as�inputs,�and�the�subroutine(*¦also�assumes�that�A0�points�to�the�TCB&*¦that�controls�the�task�that�owns�the(*¦I/O�buffer.�Subroutine�LOGPHY1�returns)*¦buffer's�physical�address�in�D6,�and�it *¦preserves�the�other�registers. ?‰MOVE.LƒD6,IOBUFPTR(A1)†Save�the�buffer�pointer�in�drive�block.@‰MOVE.LƒD6,IOBUFLOC(A1)†Save�the�buffer�location�in�drive�block.*C*ˆWe�want�to�find�the�address�of�the�last�byte�in�the�user's‚bufferC*ˆand�save�it�in�IOBUFEND.‚This�will�enable�us�to�double�check�thatB*ˆwe�will�not�read�past�the�end�of�the�buffer,�which�would�be�bad.**‰MOVE.L„D5,D4�D4�<---�Length�of�I/O�buffer.‰ADD.L…D6,D4�D4�<---�Starting�address�+�length!‰SUBQ.L„#1,D4—-1�=�ending�address‰MOVE.L„D4,IOBUFEND(A1)‰PAGE*A*ˆCalculate�the�total�number�of�VERSAdos�records�to�be�processed.*'*¨Divide�the�buffer�size�(in�D5)�by�the?EQ380„EQU†CONFGBLK+IOSREC†VERSAdos�record�size.‚The�quotient�in<‰DIVU.WƒEQ380(A1),D5‰D5.W�tells�us�how�many�VERSAdos�records'*¦we�need�to�process,�and�the�remainder&*¦in�the�top�half�of�D5�should�be�zero)*¦because�we�don't�allow�any�I/O�transfer"*¦that�involves�a�partial�VERSAdos *¦record. '*¨We�don't�need�to�worry�about�dividing#*¦by�zero�here�because�the�VERSAdos$*¦record�size�is�a�nonzero�constant. 1‰MOVEQ.L‚#0,D2’Move�the�count�of�VERSAdos�records2‰MOVE.WƒD5,D2�into�D2,�and�report�a�buffer-address4‰CMP.L„D5,D2�error�if�the�top�half�of�D5�is�nonzero.1‰BNE.S„L0340�The�top�half�of�D5�can�be�nonzero�in$*¦one�of�two�ways.‚Either�the�buffer(*¦size�isn't�an�integral�multiple�of�the#*¦VERSAdos�record�size,�or�else�the)*¦buffer�size�is�so�large�that�it�exceeds)*¦the�capacity�of�65,535�VERSAdos�records$*¦(i.e.,�16,776,960�bytes).‚With�the)*¦present�level�of�technology�there�is�no'*¦need�to�allow�a�single�I/O�command�to(*¦specify�a�transfer�of�more�than�65,535*¦VERSAdos�records.‰RTS‰PAGEO********************************************************************************;*ˆSUBROUTINE�TO�CONVERT�VERSADOS�RECORDS�TO�LOGICAL�SECTORS*C*ˆThis�routine�is‚called�by�the�handlers�of‚READ,�WRITE,�and�FORMATD*ˆcommands.‚Its�function�is�to�validate�the�VERSAdos�starting�recordE*ˆnumber�and�truncate�the�length�if�found�to�go�beyond�the�end�of�theA*ˆdisk.‚It�then‚converts�the‚VERSAdos�record‚numbers�defining�theC*ˆstart�and�length‚of�the�I/O�transfer‚to�logical�sector�numbers�on>*ˆthe�disk.‚It�stores�the�following�fields�in�the�drive�block:(*ˆIOSECTOR,�IOSCTCNT,�HALFSCTS,�NOFINISH*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*1*’D2�=�Count�of�VERSAdos�records�to�be�processed.*•=�0�for�format�commands.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�R�*�R*™A‚*�P*,*ˆExit:…RTS�back�to�the�caller�if�no�errors.!*’CMDEXIT2�if�errors�encountered.**’D2�=�Count�of�logical�sectors%*’D4�=�Starting�logical�sector�number*O******************************************************************************* CONVERT:*A*ˆDetermine�whether�the�starting�VERSAdos�record�number�is�beyond)*ˆthe�end�of�the�disk.‚Exit�now�if�it�is.*;‰MOVE.LƒIOSRRN(A4),D3ˆGet�the�specified�VERSAdos�record�no. ;EQ890„EQU†CONFGBLK+IOSRSZˆNow�check�to�see�if�the�specified6‰M  OVE.LƒEQ890(A1),D0‰VERSAdos�record�number�(in�D3)�is2‰SUB.L„D3,D0�beyond�the�end�of�the�disk,�and�abort0‰IF��THEN’with�an�error�report�if�it�is.‚The3ŠMOVEQI�ISTARR,D1�user�has�a�serious�problem�if�the5ŠBRA„CMDEXIT2Žspecified�starting�record�is�beyond�the)‰ENDIšend�of�the�disk.‚Recall�that�IOSRSZ(*¦specifies�the�total�number�of�VERSAdos'*¦records�available�on�the�entire�disk.&*¦Since�the�record�number�of�the�first&*¦record�is�zero,�the�record�number�of)*¦the�last�VERSAdos�record�on�the�disk�is *¦IOSRSZ-1. #*¦D0�<--�#�of�VERSAdos�records�from%*¦starting�record�to�the�end�of�disk.‰PAGE*B*ˆDetermine�whether�the�number�of�VERSAdos�records�to�be�processedA*ˆwill�go�beyond�the�end�of�the�disk.�Truncate�length�if�it�does.*-‰CMP.L„D0,D2’Check�to�see�if�the�record�count4‰IF‚�THEN‘exceeds�the�number�of�VERSAdos�records:ŠMOVEQI�ISTAEOV,D1Œthat�are�available�between�the�starting=ŠMOVE.B�D1,EOVFLAG(A1)ˆrecord�and�the�end�of�the�disk.�Change-ŠSUB.L‚D0,D2‘EOVFLAG�to�reflect�the�error�and8ŠMULUƒ#VDOSRSZ,D2‹truncate�the�length�of�transfer�in�D2.8ŠSUB.L‚D2,IOBUFEND(A1)‡Use�D2�to�truncate�the�buffer�end1ŠCLR.L‚D2”address�to�match�the�length�of�transfer*ŠMOVE.W�D0,D2‘that�we're�going�to�process.‰ENDI%*¨There�are�routines�in�VERSAdos�that(*¦depend�on�us�to�return�this�particular(*¦error�code�when�an�I/O�transfer�starts'*¦at�a�legal�VERSAdos�record�number�but%*¦extends�beyond�the�end�of�the�disk. *3*ˆConvert�the�VERSAdos�records�into�logical�sectors*7‰MOVE.WƒSCTPVREC(A1),D0ˆGet�the�number�of�sector(s)�per2‰MULU.WƒD0,D2�VERSAdos�record�into�D0,�and�convert'*¦the�count�of�VERSAdos�records�(in�D2)%*¦into�a�count�of�logical�sectors.‚D2'*¦now�tells�us�how�many�logical�sectors(*¦to�process.�The�result�is�a�32-bit�no. 0‰MOVEQ.L‚#0,D4’Here�we�set�D4�<--�D3*SCTPVREC�to7L0680„ADD.L„D3,D4�start�the�conversion�of�the�specified2‰BCS.S„L0730�VERSAdos�record�number�into�a�logical-‰SUB.W„#1,D0�sector�number.‚We're�effectively3‰BHI.S„L0680�multiplying�the�VERSAdos�record�number)*¦by�the�number�of�logical�sector(s)�in�a&*¦single�VERSAdos�record,�but�we�can't(*¦use�a�multiply�instruction�because�the$*¦VERSAdos�record�number�is�32-bits. *,*ˆDetermine�disk�type�to�complete�conversion*?EQ690„EQU†CONFGBLK+IOSATWˆIf�the�disk�that�is�being�accessed�isB‰BTSTW„#IOARDISC,EQ690(A1)‚a�hard�disk,�or�128�BYTES/SECTOR�floppy-‰BNE.S„L0750�disk,�the�rest�of�the�conversionB***†BTSTW„#IOADDEN,EQ690(A1)ƒroutine�can�be�skipped�because�D4�now>‰CMP.W„#VDOSRSZ>>1,CONFGBLK+IOSPSM(A1)�has�the�correct�logical‰BEQ.S„L0750�sector�number.‰PAGE*.*„Conversion�for�256�BYTES/SECTOR�floppy�disks!*ˆD2�<--�Count�of�logical�sectors(*ˆD3�<--�Starting�VERSAdos�record�number'*ˆD4�<--�Starting�logical�sector�number 4‰MOVEQ.L‚#0,D0’We're�dealing�with�a�256�BYTES/SECTORAEQ710„EQU†CONFGBLK+IOSSPT†floppy�disk.�Get�the�number�of�VERSAdos;‰MOVE.BƒEQ710(A1),D0‰records�in�track�zero�(recorded�in�128#‰LSR.B„#1,D0�BYTES/SECTOR)�into�D0. *@*ˆCheck�for�the�starting�logical�sector�number�beyond�track�zero*2‰CMP.L„D0,D4’If�the�starting�logical�sector�number4‰BHS.S„L0740�is�beyond�the�end�of�track�zero,�go�add(*¦IOSSPT/2�to�it�to�correct�for�the�fact)*¦that�the�sectors�in�track�zero�are�only%*¦half�sectors.‚All�of�the�sectors�in)*¦track�zero�were�counted�as�full�sectors$*¦in�the�original�computation�of�the*¦logical�sector�number. *1*ˆThe�starting�sector�number�is�within�track�zero*.‰SUB.L„D4,D0�D0�<--�full�sectors�in�track�zero1‰ASL.W„#1,D4�D4�<--�Starting�sector�in�track�zero*B*ˆDouble�sector�count�if�entire�I/O�transfer�is�within�track�zero.?*ˆIncrease�sector�count�by�number�of�full�sectors�in�track�zero,*ˆif�the�transfer�extends�beyond�track�zero.*/‰CMP.L„D0,D2�D2�<--�total�count�of�full�sectors1‰BHI.S„L0720�Branch�if�extends�beyond�track�zero.3‰MOVE.LƒD2,D0�D0/D2�<--�total�count�of�full�sectors1L0720„ADD.L„D0,D2�D2�<--�count�of�logical�sectors‰BCC.S„L0755�Error�if�overflow. &*¦D0�<--�count�of�full�s  ectors�track�0‰PAGE*ˆa�logical�sector�number�and�to�store�the�following�fields�in?*ˆthe�drive�block:‚IOALTSEC,�IOBUFPTR,�ALTCYL,�ALTHEAD,�BADSEC.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*.*’D4�=�Logical�sector�number�to�be�marked�bad.'*’D6�=�Alternate�VERSAdos�record�number*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*ƒ* *™A‚*�P…P**ˆCalls:„LSN2CHS*'*ˆExit:…RTS�back�to�the�caller�if�okay.&*’CMDEXIT2�if�an�error�is�encountered.*O******************************************************************************* FRMTALT:*?*ˆThe�alternate�sectors�command�only�works�for�the�rigid�disks,>*ˆso�we�will�check�here�if�we�have�a�rigid�disk�and�abort�with*ˆan�error�message�if�not.*"‰MOVEQI„ISTAIF,D1•If�this�is�not�a/‰MOVE.W„CONFGBLK+IOSATW(A1),D0ˆrigid�disk,�then'‰BTSTW…#IOARDISC,D0’abort�with�an�error‰BEQ.L…CMDEXIT2–message. *3*ˆRecall�that�the�alternate�sector�number�is�in�D6.*4‰MOVE.L„CONFGBLK+IOSRSZ(A1),D0ˆIf�this�sector�number(‰MOVEQI„ISTARR,D1•goes�beyond�the�end�of!‰SUB.L…D6,D0™the�disk,�then�abort&‰BLS.L…CMDEXIT2–with�an�error�message.‰PAGE*@*ˆConvert�the�VERSAdos�record�number‚in�D6�into�a�logical�sector5*ˆnumber�in�D3,�then�move�into�IOALTSEC�and�IOBUFPTR.*/‰MOVE.W„SCTPVREC(A1),D0…Set�D3�<---�D6*SCTPVREC/‰MOVEQ.Lƒ#0,D3�by�successive�adds,�since�IOSALT‰MOVEQI„ISTARR,D1#‰REPEAT˜is�maybe�more�than�16�bits.-�ADD.LƒD6,D3�Abort�if�result�exceeds�32�bits.�BCS.LƒCMDEXIT2 �SUBQ.W‚#1,D0 ‰UNTIL.S‚<‰MOVE.L„D3,IOALTSEC(A1)…Logical�sector�address�of�alternate.7‰MOVE.L„D3,IOBUFPTR(A1)…Must�also�be�saved�in�IOBUFPTR.*A*ˆWe�are�going�to�check�that�the�track�of�the�alternate�sector�is<*ˆnot�the�same�as�the�track�of�the�bad�sector.‚If�it�is,�theE*ˆcontroller�would�make�that�track�inaccessible,�and�that's�an�error.*A*ˆThe�subroutine�LSN2CHS�takes�a�logical�sector�number�in�D0,�and?*ˆreturns�the�cylinder�number�in�D0.W,�the�head�number�in�D1.B,1*ˆand�the�sector�number�within�the�track�in�D2.B.* ‰MOVE.L„D6,D0‰BSR.L…LSN2CHS‰MOVE.W„D0,ALTCYL(A1! )‰MOVE.B„D1,ALTHEAD(A1)*@*ˆConvert�sector�to�be�marked�bad�in�D4�to�cylinder,head,sector.* ‰MOVE.L„D4,D0‰BSR.L…LSN2CHS<‰MOVE.B„D2,BADSEC(A1)‡It�is�the�sector�number�within�the�bad*¦track�that�we�need�to�save.*1‰CLR.L…D2’We�don't�need�to�compare�sector�numbers**¦within�the�track,�and�we�need�to�restore"*¦D2�to�0�because�it�is�going�into *¦IOSCTCNT$‰CMP.W…ALTCYL(A1),D0‡Same�cylinder�?!‰BNE.S…NOT_ALT�If�not,�no�problem7‰CMP.B…ALTHEAD(A1),D1†Same�cylinder�and�same�head�means#*¦same�track,�and�this�is�an�error.‰IFƒƒTHEN.S“MOVE.B„#ISTAIF,D1 “BRA‡CMDEXIT2‰ENDINOT_ALT‰RTS‰PAGEO********************************************************************************%*ˆSUBROUTINE�TO�CHECK�THE�DEVICE�CODE*;*ˆThis�routine�is�called�by�the�handler�of�CONFIG�commands.;*ˆIts�function�is�to�check�the�device�code�for�this�channelD*ˆto�see�that�it�exists�in�the�DSKTYPE�module�and�is�associated�with@*ˆthe�current�channel.‚If�it�exists,�the�following�fields�in�the=*ˆdrive's�variable�block�are�set:‚DRV_CODE,�REC_ATT,�REC_PAR,*ˆREC_XAT,�REC_XPR*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB.*’A5�=�physical�address�of�CCB.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A„PƒPƒP*/*ˆExit�to:‚RTS�to�calling�routine�if�all�is�ok. *’CMDEXIT2�if�error�is�detected.*O******************************************************************************* CHK_DEVICE: /‰MOVE.B„CCBTYPE(A5),D0ƒD0�<--�our�channel�type.7‰LEA‡CH_TYPES,A0†A0�<--�addr�of�table�of�channel�types. -‰MOVE.B„DCBFLG(A3),D2„D2�<--�our�device�code.<‰MOVE.B„D2,DRV_CODE(A1)‚Store�in�the�drive's�variable�block. ‰FOR.W…D1=#1‚TO‚#NUMTYPESƒDO‹CMP.Bƒ(A0)+,D0‹BEQ‡CHAN_FOUNDCHK_AGAIN‚ADD.L…#NUMBYTES-1,A0‰ENDF*8*„DEVICE�CODE�WAS�NOT�FOUND�ASSOCIATED�WITH�OUR�CHANNEL:*5‰MOVE.B„#ISTANDV,D1†Return�Non-existant�device�error. ‰BRA‡CMDEXIT2*@*…A�channel�matching�ours�has�been�found,�see�if�our�device�code>*…matches�the�DRV_CODE�entry�in�DSKTYPE.‚A0�is�pointing�to�theB*…device�code�entry�in�the�table.‚Note�that�the�CHANNEL�must�existA*…because�we�checked�it�at�INITIALIZATION�time,�we�couldn't�check9*…our�device�code�because�we�didn't�know�it�at�that�time.* CHAN_FOUND‰CMP.B…(A0),D2ŠIs�this�for�me?(‰BNE‡CHK_AGAINˆNo�-�try�another�channel.‰PAGE*D*…Our�device�code�and�channel�type�matches�that�stored�in�the�table.2*…Load�REC_ATT�and�REC_PAR�from�the�table�entries.**—Channel�type“(byte)*ŒA0‚---->‚Drive�code•(byte)*—Recognized�attributesŠ(word)*—Recognized�parametersŠ(word)'*—Recognized�Extended�attributes�(word)'*—Recognized�Extended�parameters�(word) 5‰MOVE.B„(A0)+,D2‹Already�have�the�device�code�stored.7‰MOVE.W„(A0)+,REC_ATT(A1)‚Set�up�the�attributes�and�the9‰MOVE.W„(A0)+,REC_PAR(A1)‚parameters�masks�in�the�drive's)‰MOVE.W„(A0)+,REC_XAT(A1)‚variable�block.‰MOVE.W„(A0)+,REC_XPR(A1)‰RTS‰PAGEM*******************************************************************************ˆSTART_IO�SUBROUTINE*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A3�=�physical�address�of�DCB*’A4�=�physical�address�of�IOCB*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D„* *™A‚*�P…P*?*ˆCalls:„BLD_PACKET,�DISK_START�in�the�device-dependent�module.**ˆExit:…RTS�back�to�the�caller.*M***************************************************************************** START_IO:5‰T_JSR„BLD_PACKET�Call�the�device-dependent�driver�to3‰IF‚‚THEN�build�the�command�packet�for�the�disk/‹BRA„CMDEXIT2�controller�board.‚Condition�codes'‰ENDIšset��if�the�driver�detects�an"*¦error�while�building�the�packet. ;‰MOVE.LƒIOBUFTCB(A1),A0ˆIncrement�the�TCBIOCNT�field�of�the;‰ADD.B„#1,TCBIOCNT(A0)†TCB�that�controls�the�task�that�owns)*¦the�I/O�buffer�(or�the�IOCB�in�the�case#*¦of! �a�format�a�configure�command).$*¦The�TCBIOCNT�field�of�a�task's�TCB'*¦indicates�how�many�I/O�request(s)�the#*¦task�has�pending�completion�under*¦interrupt�control. 3‰MOVE.WƒSR,-(SP)�Save�the�value�of�the�SR,�and�then9‰MOVE.WƒCCBISR(A5),SRˆinhibit�interrupts�at�the�channel's*¦interrupt�level. 5‰T_JSR…DISK_STARTŒCall�the�device-dependent�driver�to$*¦do�command�queueing�and�setting�up*¦of�INTSWTCH,�etc. 5‰MOVE.Wƒ(SP)+,SR�Restore�the�SR,�and�transfer�control4‰BRA†CMDEXIT3�to�the�command�processor's�common�exit *¦routine.‰PAGEM******************************************************************************B*ˆLSN2CHS�--�Convert�logical�sector�number�to�cylinder,head,sector*“within�track.*&*ˆAlgorithm:„(SPT�=�sectors�per�track)*–(LSN�=�logical�sector�number)**’LSN.*‹----------------ˆ=…Cylinder�no.�+�Remainder1*ŠSPT*Number�of�heads* *�Remainder1,*‹------------------†=…Head�no.�+�Remainder2*’SPT*)*ˆRemainder2‚=‚sector�number�within�track*/*ˆEntry:„A1�=�address�of�drive's�variable�block*’D0�=�logical�sector�number*!*ˆRegister�usage:…0ƒ1�2�3�4�5�6�7"*™D‚P/R�R�R‘P�=�Parameter�register*™A†P“R�=�Return�register**ˆExit:…D0.B�=�Cylinder�number*’D1.B�=�Head�number**’D2.B�=�Sector�number�within�track�(0-31)**ˆExits�to:�RTS�to�caller*O******************************************************************************* LSN2CHS: ‰CLR.L…D1 ‰CLR.L…D26‰MOVE.B„CONFGBLK+IOSHDS(A1),D1‡D1�<---�Number�of�heads8‰MOVE.B„CONFGBLK+IOSSPT(A1),D2‡D2�<---�Sectors�per�track2‰MULU†D2,D1�D1�<---�Number�of�heads*�Sectors/track"‰DIVU†D1,D0�D0.W�=�Cylinder�number"‰MOVE.L„D0,D1�D1.W�<---�Remainder1 ‰LSR.L…#8,D1 ‰LSR.L…#8,D1‰DIVU†D2,D1�D1.W�=�Head�Number.‰MOVE.L„D1,D2�D2.W�<---�Sector�number�in�track ‰LSR.L…#8,D2 ‰LSR.L…#8,D2‰RTS‰PAGEO********************************************************************************(*ˆLOGICAL-TO-PHYSICAL�ADDRESS�CONVERSION*F*ˆGiven�a�physical�TCB�address�and�the�logical�address�and�length�of�aE*ˆmemory�area,�subroutine‚LOGPHY�computes�the�physical�address�of�theE*ˆmemory�area.‚It�also�checks�to�make�sure�that�the�given�memory�areaE*ˆreally�belongs�to�the�task‚that�is�controlled�by�the�specified�TCB.*D*ˆThe�subroutine�will�not�return�unless�the�specified�memory�residesH*ˆentirely�within�the�memory�segment�that�belongs�to�the�specified�task.*?*ˆEntry:„A0�=�physical�address�of�TCB�of�task�containing�buffer;*’D6�=�logical�address�of�the�first�word�of�the�memory�area)*’D5�=�length�in�bytes�of�the�memory�area*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚P�P‡P�R *™A‚P�P‡P*B*ˆExit:…D6�=�physical�address�of�the�first�word�of�the�memory�area *’Return�to�the�calling�routine.*O******************************************************************************* -LOGPHY1‚BSR†LOGPHY‘Use�the�routine�in�DRVLIB. ‰IF‚�THEN.S5‹MOVEQIƒISTAADD,D1‹LOGPHY�returns�this�condition�code)‹BRA†CMDEXIT2‹if�(1)�the�specified�memory'*¦area�is�completely�outside�any�memory'*¦segment�that�belongs�to�the�specified'*¦task�or�(2)�the�specified�memory�area!*¦is�in�a�memory-mapped�I/O�area.‰ENDI *‰RTS�Control�reaches�this�point�when�we've'*¦made�a�successful�address�conversion.‰PAGEJ****************************************************************************•B�A�C�K�G�R�O�U�N�D*œAND*”C�A�L�L�__�G�U�A�R�D�E�D**˜R�O�U�T�I�N�E�S**•(DEVICE�INDEPENDENT)*J************************************************************************** O*********************************************************************************‰SEND�THE�EVENT�(CALL�GUARDED)*6*‰Somebody�in�command�service�wants�to�queue�an�event,=*‰but�of�course�he�couldn't�send�it�since�the�Q_EVENT�routine;*‰can�only�be�called�from�the�background.‚So�he�asked�me�to)*‰do�it�for�him.‚I'm�such�a�nice�routine.*!*ˆEntry:„A3ƒ=‚Address�of�the�DCB.*’A4ƒ=‚Address�of�the�IOCB.*’A5ƒ=‚Add" ress�of�the�CCB.*’D1.B�=‚Error/status�code.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D„P *™AˆP�P�P**ˆCalls:„Q_EVENT***ˆExit:…RTS�back�to�caller�if�all�is�okay.*’KILLER�if�error�is�detected.*O******************************************************************************* DO_EVENT: /‰ST†NONINTERRUPT(A5)ƒSet�up�for�a�normal�event.0‰BSR…Q_EVENTŒCall�the�routine�to�send�the�event.‰SF†NONINTERRUPT(A5) ‰IF‚‚THEN&ŠKILL.DRIVER�DISKLIB_ID,T0QEVNTT,A5,A3‰ENDI ‰RTS‰PAGEJ***************************************************************************5*‰QUEUE�A�COMPLETION�EVENT�TO�THE�ATTACHED�TASK�(IOS)*;*‰This�routine�calls�the�exec�to�send�a�small�event�to�IOS.;*‰It�uses�I_NRM_QEVENT�if�we're�processing�an�interrupt�and:*‰N_NRM_QEVENT�if�we're�not.‚These�routines�are�in�DRVLIB.*7*‰NOTE:�this�routine�may�only�be�called�from�within�the*�background!!!!!*!*ˆEntry:„A3ƒ=‚Address�of�the�DCB.*’A4ƒ=‚Address�of�the�IOCB.*’A5ƒ=‚Address�of�the�CCB.*’D1.B�=‚Error/status�code.4*’NONINTERRUPT�=�00�=�Processing�an�interrupt�event.0*’NONINTERRUPT�=�FF�=�Processing�a�normal�event.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D„P *™AˆP�P�P*#*ˆCalls:‚I_NRM_QEVENT,�N_NRM_QEVENT*7*ˆExit:ƒRTS�back�to�caller�with�the�condition�code�set:**��=�The�event�was�sucessfully�queued."*��=�Unsucessful�TRAP�#0�call.*O******************************************************************************* Q_EVENT: :‰MOVEM.LƒD3/A0,-(A7)‰Save�the�registers�we�will�blow�away. 9‰MOVE.BƒD1,IOSSTA(A4)ŠStore�the�status�code�into�the�IOCB&*¦where�it�can�be�examined�by�the�task$*¦that�originally�requested�the�I/O. **‚Set�up�A0�and�D3�for�DRVLIB:*/‰MOVE.L„#0,A0�A0�<--�0�=�DO�NOT�COPY�THE�EVENT! ‰MOVE.L„A3,D3�D3�<--�DCB�address #‰IF.BƒNONINTERRUPT(A5)‚‚#0ƒTHEN$‹BSR.LƒI_NRM_QEVENTˆInterrupt�event.‰ELSE!‹BSR.LƒN_NRM_QEVENTˆNormal�event.‰ENDI +‰MOVEM.L‚(A7)+,D3/A0ŠRestore�the�registers.‰RTS‰PAGEL*****************************************************************************/*ˆR�O�U�T�I�N�E�S„F�O�R„T�H�E…I�N�T�E�R�R�U�P�T*'*‹H�A�N�D�L�E�R…F�O�R„T�H�E…D�E�V�I�C�E**’D�E�P�E�N�D�E�N�T…M�O�D�U�L�E*L**************************************************************************** O*******************************************************************************O*******************************************************************************O*********************************************************************************ˆINTERRUPT�HANDLER*B*ˆThis‚subroutine�is�called�from�the�device-dependent�driver�afterC*ˆit�completes�the�device-dependent�interrupt�handling.‚Its�purposeA*ˆis�do�the�common�things�for�command�completion�interrupts.‚It's*ˆspecific�functions�are:*=*Š1.�Get�the�TCB,�IOCB�and�DCB�addresses�and�the�IOBUFLOC�and;*�IOBUFPTR�variables�out�of�the�drive�block�into�designated *�registers.1*Š2.�Calculate�the�data�transfer�length�in�bytes.=*Š3.�Complete�the�IOSRRN�field�if�the�specific�VERSAdos�error*�code�requires�it.'*Š4.�Queue�the�completion�event�to�IOS.D*Š5.�Decrement�the�count�of�outstanding�I/O�operations�for�our�task.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’A5�=�physical�address�of�CCB*’D1�=�VERSAdos�error�code,*’D2�=�Logical�sector�number�of�error�sector*!*ˆRegister�usage:ˆ0�1�2�3�4�5�6�7 *œD‚S�*�* *œA„SƒS�S�P**ˆCalls:„MATCH_ERR,�Q_EVENT*+*ˆExit:…RTS�to�the�device-dependent�module.*O*******************************************************************************O*******************************************************************************O******************************************************************************* CHAN_DONE: 0EQ630„REG†D0/D2/A1/A3/A4‡Save�working�registers.‰MOVEM.L‚EQ630,-(A7)Š* #‰TST.B„D1“Test�the�error�condition.4‰IF��THEN’If�there�was�an�error�for�the�command,4ŠBSR†MATCH_ERR‹execute�t" he�subroutine�that�completes,‰ENDIšthe�IOSRRN�field�of�the�IOCB�if�req'd.‰PAGE@‰MOVEM.L‚IOBUFLOC(A1),EQ630…We�use�a�MOVEM.L�instruction�to�pull&*¦several�variables�out�of�drive�block'*¦in�one�step.‚This�instruction�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�Q_EVENT)5L1‡SET†IOCBPTRŽA4�=�IOCBPTR.‚(For�subroutine�Q_EVENT) $*¨The�SET�instructions�that�are�used'*¦here�are�just�dummy�instructions�that&*¦generate�artificial�label�references*¦for�the�concordance�listing. 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. 3‰SF†NONINTERRUPT(A5)†Set�up�for�an�interrupt�event.*‰BSR…Q_EVENT�Go�send�the�completion�event. ‰IF‚‚THEN&ŠKILL.DRIVER�DISKLIB_ID,T0QEVNTI,A5,A3‰ENDI 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).‰MOVEM.L�(A7)+,EQ630‰RTS‰PAGEO*********************************************************************************ˆMATCH_ERR�ROUTINE*C*ˆThis�routine�determines�whether�the�VERSAdos�error�code�passed�inF*ˆregister�D1�must�update�the�IOSRRN�field�in�the�IOS�parameter�block.*A*ˆEntry:„A1�=�pointer�to�drive's�variable�block�in�global�memory.*’D1�=�VERSAdos�error�code,*’D2�=�Logical�sector�number�of�error�sector*!*ˆRegister�usage:ˆ0�1�2�3�4�5�6�7*œD‚#�PŽ#�=�saved�by�CHAN_DONE *œA„#ƒ#�#**ˆExit:…RTS�to�caller*O******************************************************************************* MATCH_ERR:3‰LEA‡ERRDISK(PC),A4†Test�the�VERSAdos�error�code�to=LOOKING‚MOVE.B„(A4)+,D0Œdetermine�whether�the�IOSRRN�field�of8‰BEQ.S…NOTFOUNDŒthe�IOCB�needs�to�be�updated.�If�a�match0‰CMP.B…D0,D1�is�found�in�the�table�ERRDISK,�then'‰BNE.S…LOOKING�update�the�IOSRRN�field. ***ˆWe�have�a�match�of�VERSAdos�error�codes.>*ˆCalculate�the�VERSAdos�record�number�from�the�logical�sector*ˆnumber�returned�in�D2.*@EQ635„EQU‡CONFGBLK+IOSATW‡Determine�the�disk�type�from�the�drive@‰BTSTW…#IOARDISC,EQ635(A1)�variable�block.‚If�it�is�a�hard�disk,2‰BNE.S…E150�the�LSN�equals�the�VERSAdos�sector�no. A***†BTSTW…#IOADDEN,EQ635(A1)„If�this�is�a�128�BYTES/SECTOR�floppyB‰CMP.W�#VDOSRSZ>>1,CONFGBLK+IOSPSM(A1)�disk,�divide�the�LSN�by�two.‰BEQ.S…E100�to�get�the�VERSAdos�sector�number. AEQ640„EQU‡CONFGBLK+IOSSPT†We�must�have�a�256�BYTES/SECTOR�floppy.7‰MOVEQ.Lƒ#0,D0�Use�the�sectors�per�track�value�from�the8‰MOVE.B„EQ640(A1),D0ˆdrive's�variable�block�to�determine3‰CMP.L…D0,D2�if�the�error�sector�is�within�track�0.4‰BLT.S…E100�If�its�within�track�0,�divide�the�LSN�by4‰LSR.L…#1,D0�2�to�get�the�VERSAdos�sector�number.�If4‰SUB.L…D0,D2�its�beyond�track�0,�convert�the�sectors3‰BRA.S…E150�per�track�to�VERSAdos�sectors�per�track'*¦and�subtract�that�from�the�LSN�to�get*¦the�VERSAdos�sector�number.‰PAGE 3E100…LSR.L…#1,D2�Convert�from�LSN�by�dividing�by�2.E150…MOVE.L„IOCBPTR(A1),A4‰MOVE.L„D2,IOSRRN(A4) NOTFOUND‰RTS O********************************************************************************1*ˆVERSADOS�DISK�ERROR�CODES�CROSS-REFERENCE�TABLE*A*ˆThis�list�of�VERSAdos�error�codes�are�the�ones�that�must�update.*ˆthe�IOSRRN�field�in�the�IOS�parameter�block.*O******************************************************************************* ,ERRDISK‚DC.B†ISTACMP�D2�=�DATA�COMPARE�ERROR'‰DC.B†ISTASPE�D3�=�SECTOR�PROTECT�ERROR!‰DC.B†ISTACRC�E3�=�DATA�CRC�ERROR*‰DC.B†ISTADDM�E5�=�DELETED�DATA�MARK�ERROR2‰DC.B†ISTADME�EC�=�TRACK/SECTOR�ID�NOT�FOUND�ERROR)‰DC.B†ISTAMRK�ED�=�ADDRESS�M# ARK�CRC�ERROR#‰DC.B†ISTABDS�EF�=�BAD�SECTOR�ERROR‰DC.B†0 *********************** *‚PATCH�SPACE***********************‰DS.Wƒ30‰ENDNNNNN?EPCIDRVƒIDNTƒ45,0†VERSAdos�2661�terminal�driver�with�type-ahead;ŠTTL„EPCIDRV:‚VERSAdos�2661�terminal�driver�with�type-ahead ŠLLENƒ120J**************************************************************************J**************************************************************************J**************************************************************************J***************************************************************************9*‰EPCIDRV:‚VERSAdos�2661�terminal�driver�with�type-ahead.*8*‰Purpose:‚VERSAdos�device�driver�to�handle�asynchronous3*�terminals�(of�any�type)�over�the�SIG�2661�chip�on*�the�following�boards: *’MVME101**‰Revision�history:*7*�12/18/85‚Install�NEW�Killer�modification�which�leaves,*šThe�Driver�ID�(Number)�and�Reason�(Number)2*šin�CRASHSAV�along�with�the�CCB�and�DCB�pointers.7*�02/14/85‚Modified�INITERR�routine�to�clear�the�status5*šregister�flags;�old�instrucion�did�not�clear�flags./*šModified�PUT_CHAR�to�disable�interrupts�until,*šcharacter�is�transmitted;�old�instructions *šallowed�characters�to�be�lost.1*�10/23/84‚All�BSR's�to�TERMLIB�now�JSR's�in�case.*šTERMLIB�is�located�more�than�32K�bytes�away.:*�10/01/84‚Changed�PASS19.MPSCDRV.SA�to�drive�the�SIG2661,+*šalso�deleted�XREF's�to�BREAK�and�GET_LEN.3*‘8/30/84‚Fixed�SPR�concerning�SETUP.‚Commented�out(*šthe�code�that�tests�the�modem�bit.‚Now**šif�the�off�hook�bit�is�set,�the�DTR�line&*šis�set�low,‚whether�or�not�the�modem *šbit�is�set.*6*‘10/3/83‚Changes�to�let�interrupts�work�correctly�for**š2661�chip.�Also�allowes�DATA�I/O�to�work0*švia�RTS�line�(not�DTR).�DTR�is�always�enabled.*š(2661�chip�only).,*šChanged�by:�Marco�Schmidt�Motorola�Munich.2*‘8/19/83‚Added�conditional�assembly�stuff�to�make-*šthis�driver�assemble�for�the�7201�chip�(the4*šoriginal�driver)�and�for�the�Signetics�2661�(EPCI),*šchip.‚The�2661�is�on�both�the�VM01�and�the*šMVME101�board.8*‘4/�7/83‚Changed�UNSTOP�routine�to�fix�bug�where�a�char(*šis�destroyed�in�the�USE�XOFF/XON�mode.* ^0g;oEw=/‡�—AŸ?§G¯L·H¿LÇNÏV×7*�10/19/82‚Major�repairs�so�that�interrupts�will�not�be3*šdisabled�so�long�as�to�screw�up�SDLC.‚Revision�1.**‘9/16/82‚Initial�release�by�Steve�Franck.*J**************************************************************************J******************# ********************************************************J**************************************************************************J**************************************************************************‰PAGE***‚XREF's�from�TERMLIB* ‰XREF†LOG_ERR ‰XREF†RESET‰XREF†TERM_INIT‰XREF†TERM_COMMAND‰XREF†TERM_TBE‰XREF†TERM_BREAK‰XREF†TERM_GOT_CHAR**‚Equate�files�included:**ˆ9995.&.SIG2661.EQ*ˆ9995.&.STR.EQ*ˆ9995.&.TCB.EQ*ˆ9995.&.CCB.EQ*ˆ9995.&.BAB.EQ*ˆ9995.&.IOE.EQ*ˆ9995.&.NIO.EQ*ˆ9995.&.LV5.EQ**ˆ9995.&.TERMINAL.EQ„Equates�for�terminals*ˆ9995.&.UTILITY.MCA*ˆ9995.&.TERMCCB.EQ…Offsets�and�equates�for�CCBDDP�for�terminals.*ˆ9995.&.KILL.MC*ˆ9995.&.KILLDRV.EQ*ŠNOLISTŠINCLUDE�9995.&.STR.EQŠINCLUDE�9995.&.TCB.EQŠINCLUDE�9995.&.CCB.EQŠINCLUDE�9995.&.IOE.EQŠINCLUDE�9995.&.NIO.EQŠINCLUDE�9995.&.LV5.EQŠINCLUDE�9995.&.BAB.EQŠINCLUDE�9995.&.UTILITY.MCŠINCLUDE�9995.&.KILL.MCŠINCLUDE�9995.&.KILLDRV.EQŠLISTŠINCLUDE�9995.&.SIG2661.EQŠINCLUDE�9995.&.TERMINAL.EQŠINCLUDE�9995.&.TERMCCB.EQŠOFFSET‚TERMDDP*0*‚Device�dependent�Background�activation�blocks:$*„None�required�for�the�EPCI�driver.**@*ƒCompute�the�number�of�pages�of�memory�that�we�need�for�one�CCBNN>*ƒfor�the�MPSC�driver.‚CMR�automatically�allocates�one�page�ofA*ƒmemory�($100�bytes)�for�the�CCB,�and�our�variable�EXTCCBSZ�willB*ƒreside�in�the�CMR�parameter�table�at�the�beginning�of�the�driver8*ƒto�tell�CMR�how�many�extra�pages�of�memory�are�needed.**CCBSIZEB�EQU‡*PAGESIZE�EQU‡$100L1‡SET‡CCBSIZEB+PAGESIZE-1CCBSIZE‚EQU‡L1/PAGESIZEEXTCCBSZ�EQU‡CCBSIZE-1;ŠTTL„EPCIDRV:‚VERSADOS�2661�TERMINAL�DRIVER�WITH�TYPE-AHEADŠPAGEJ***************************************************************************+*‰SERVICE�VECTOR�TABLE,�REVISION�INFO,�ETC.*@*‰This�table�is�examined�by�CMR�when�the�channel�is�allocated�toC*‰determine�where�to�go�for�interrupts,�commands,�&�initialization.<*‰It�must�always�be�at�the�very�top�of�the�driver�code.‚Also>*‰included�is�a�parameter�telling�the�number�of�extra�pages�of>*‰memory�to�include�in�the�CCB,�and�information�describing�the*‰revision�of�the�driver.*L**************************************************************************** ŠSECTION‚0ŠOPT„BRS EPCIDRV: *D*‚Service�vector�table.‚Notice�that�these�values�are�relative�to�theC*‚beginning�of�the�driver�so�the�mechanism�is�position-independent!*=ŠDC.LƒINTERRUPT-EPCIDRV‚Address�of�interrupt�service�routine.9ŠDC.LƒCOMMAND-EPCIDRV„Address�of�command�service�routine.5ŠDC.LƒINIT-EPCIDRV‡Address�of�initialization�routine.ŠDC.Lƒ0’Reserved. **‚Other�CMR�parameters.*7ŠDC.BƒEXTCCBSZ‹#�of�extra�pages�in�the�CCB.‚The�CCB�may)*§be�any�size�from�1�to�256�pages�(a�page'*§is�256�bytes):‚if�this�field�is�0,�it*§will�be�1�page,�etc.ŠDC.Bƒ0,0,0ŽReserved.ŠDC.Lƒ0,0,0ŽReserved. **‚Revision�info:*/ŠDC.Bƒ'121885'‹Date�of�last�assembly�as�MMDDYY.1ŠDC.Bƒ'�'�Space�indicates�no�patches�to�.LO�file.)ŠDC.Bƒ'4'�Major�VERSAdos�revision�number.*‰PAGE*+*‚Jump�table�for�use�by�the�generic�TERMLIB*‰BRA.L…PUT_CHAR ‰BRA.L…CK_TBE‰BRA.L…DDP_RESET ‰BRA.L…SETUP‰BRA.L…CLOCK_RESET‰BRA.L…GET_STAT‰BRA.L…DDP_STOP‰BRA.L…DDP_UNSTOP‰BRA.L…DDP_BEG_BREAK‰BRA.L…DDP_END_BREAK **‰PAGEJ**************************************************************************J**************************************************************************J**************************************$ **************************************‰INITIALIZATION�ROUTINE*>*‰This�routine�is�called�by�CMR�when�the�channel�is�allocated.9*‰Its�purpose�is�to�set�up�things�for�command�service�and7*‰interrupt�service.‚The�major�functions�performed�are:"*�Validate�the�channel�type�field.+*�Get�memory�for�transmit�&�receive�queues..*�Initialize�flags,�pointers,�etc.�in�the�CCB.*�Initialize�the�2661.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.**‰Entry:�A5�=�address�of�CCB.*'*‰Exits�to:‚CMR�(via�RTS)�if�all�is�OK.'*”KILLER�if�exec�won't�allocate�memory.*J**************************************************************************J**************************************************************************J************************************************************************** ŠDS…0 INIT:.‰JSR‡TERM_INIT‹Do�the�device-independent�stuff2‰IFƒƒTHEN…Something�went�wrong�with�TERM_INIT.4‰IFƒƒTHEN„The�exec�call�failed�and�we�cannot�get!*œthe�scheduler's�entry�point�!!!-‹KILL.DRIVER�EPCIDRV_ID,BAD_T_INIT,A5,#NO_DCB‰ELSE�RTS�The�channel�is�down�!!‰ENDI‰ENDI*?*‚Call�guarded�for�the�device�dependent�initialization�routine.**‰LEA‡DO_INIT(PC),A0‰MOVE.L„#T0GUARD,D0‰TRAP†#0‰RTSŠPAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰COMMAND�SERVICE�ROUTINE*>*‰We�get�entered�here�when�the�attached�task�(IOS)�invokes�CMR?*‰via�a�TRAP�1�with�an�INITIATE�I/O�parameter�block�to�process.>*‰CMR�has�already�checked�the�CMR�parameter�block�to�ensure�it<*‰resides�within�the�address�space�of�the�attached�task.‚IOSA*‰has�already�validated�the�IOCB,�except�for�the�buffer�addresses *‰therein.*@*‰We�got�here�through�a�JSR�from�CMR,�and�will�exit�with�an�RTS.>*‰All�registers�have�been�saved�by�CMR�and�may�be�used�freely.?*‰Entry�is�at�interrupt�level�0,�and�we�are�in�supervisor�mode.*5*‰Entry:�A2�=�physical�address�of�CMR�parameter�block*�A5�=�physical�address�of�CCB*3*‰Exit:‚D0�=�results�of�parameter�block�validation:3*•always�0�in�our�case,�indicating�it�was�OK,�since2*•IOS�will�not�send�us�any�request�except�HALT�I/O/*•if�we�are�already�busy,�and�CMR�makes�all�the*•other�checks.*A*‰Note:‚TERMLIB�does�not�recognize�CMR�commands�for�HALT�&�RESET.B*‰HALT�can�still�be�accomplished�through�use�of�the�HALT�I/O�IOCB.*J**************************************************************************J**************************************************************************J************************************************************************** COMMAND:‹JSR…TERM_COMMAND‹RTS—return�to�CMR.‹PAGEJ**************************************************************************J**************************************************************************J****************************************************************************‰INTERRUPT�HANDLING�ROUTINE*<*‰This�routine�completes�I/O�requests�started�by�the�command:*‰service�routine.‚It�is�entered�at�the�interrupt�priority;*‰level�of�interrupts�on�this�channel,�and�is�essentially�a9*‰subroutine�to�the�first�level�interrupt�handler�in�CMR.*:*‰Entry:�D0,A0,A1�have�been�saved�by�CMR�and�are�available*�A5�=�address�of�CCB*9*‰Exit�is�always�via�RTS,�which�takes�us�back�to�CMR.‚The3*�carry�bit�is�examined�by�CMR�to�determine�whether7*�the�driver�handled�the�interrupt�or�whether�it�should4*�pass�the�interrupt�on�to�the�next�guy�in�the�chain*�on�that�vector:*��=�'I�handled�it'**‰Stack:*�(A7)+4�.�.�.*�(A7)ƒlongword�return�address*J**************************************************************************J************$ **************************************************************J************************************************************************** INTERRUPT:ŠPUSH.L�D1‘save�D1*ŠMOVE.L�CCBCHB(A5),A1†get�address�of�2661.8ŠMOVE.B�CREG(A1),D1ˆget�contents�of�the�control�register7ŠMOVE.B�SREG(A1),D0ˆget�contents�of�the�status�register*-*‰do�we�have�anything�enabled�on�this�device?**ŠBTSTƒ#TXEN,D1‹is�the�transmitter�enabled?3ŠBNE.S‚INT010�branch�if�it�is�-�we'e�getting�closer'ŠBTSTƒ#RXEN,D1‹is�the�receiver�enabled?1ŠBNE.S‚INT010�branch�if�it�is�-�we're�even�closer*3*‰this�interrupt�must�not�be�for�us�-�return�to�CMR*5INTNOP„POP.L‚D1‘restore�D1�so�CMR�will�work�correctly$ŠAND.W‚#$FFFE,SRŠclear�the�carry�bitŠRTS—and�go�awayŠPAGENNNN*8*ˆis�probably�some�interrupt�for�us�-�find�out�what�kind*$INT010ƒPUSH.L„D2ˆnow�we�need�D2�also6‰MOVE.B„D0,D2…need�another�copy�of�the�status�register!‰AND.B…#$38,D2ƒget�any�error�bits*‰BNE.S…SRC‡branch�if�any�error�bits�are�on‰POP.L…D2ˆrestore�it.‰BTST†#RXRDY,D0�is�there�a�receiver�interrupt?'‰BNE.S…RCA‡branch�if�yes�-�go�handle�it1‰BTST†#TXRDY,D0�is�there�a�transmitter�interrupt?'‰BNE.S…TBE‡branch�if�yes�-�go�handle�it8‰BTST†#DNR,D0ƒis�there�a�change�in�the�DSR�or�DCD�lines?‰BNE.S…DSRTN…branch�if�there�is,‰BTST†#FB,D1„are�we�in�the�force�break�mode?+‰BNE.S…FBMODE„branch�if�forcing�a�break�now*B*ˆif�we�got�here�there�really�wasn't�on�interrupt�for�us�after�all*‰BRA.S…INTNOP„and�return‰PAGEJ***************************************************************************)*‰TRANSMIT�BUFFER�EMPTY�INTERRUPT�HANDLER*=*‰The�2661's�transmit�buffer�just�became�empty,�so�if�we�have+*‰more�characters�to�send�we�can�do�it�now.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�2661NNN*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** TBE:(ŠMOVE.B„CREG(A1),D1‰get�co% ntrol�register%ŠBCLR†#TXEN,D1Œswitch�off�the�Xmitter!ŠMOVE.B„D1,CREG(A1)‰load�the�chip *%%%%%%%%%%ƒBWN‚9/17/84*F*‚Call�the�device-independent�routine�that�deals�with�transparent�mode)*‚or�invokes�the�XMIT�background�routine.* ‰JSR‡TERM_TBE‰BRA.S…INT_EXIT‰PAGEJ***************************************************************************(*‰RECEIVED�CHARACTER�AVAILABLE�INTERRUPT*=*‰The�2661�has�just�received�a�character,�and�it�is�available=*‰for�reading.‚We�will�do�that�now,�and�the�result�will�go�in$*‰the�receive�queue�if�there's�room.**‰Entry:�A0�=�NOT�USED*�A1�=�address�of�2661*�A5�=�address�of�CCB*<*‰Since�this�is�not�a�subroutine,�registers�at�exit�are�just-*‰the�entry�requirements�of�the�next�routine.*J************************************************************************** RCA:/‰MOVE.B„DREG(A1),D0‰Get�the�char�from�the�chip.*C*‚Call�the�device�independent�routine�to�check�for�transparent�modeG*‚and�do�the�stuff�for�transparent�mode�or�if�not�in�tranparent�mode�toG*‚check�for�any�special�characters�such�as�XON,�XOFF,�BREAK�EQUIVALENT,G*‚or�DISCARD�OUTPUT.�Otherwise,�put�the�character�in�the�receive�queue.*‰JSR‡TERM_GOT_CHAR‰BRA.S…INT_EXIT‰PAGEN*******************************************************************************%*ˆSPECIAL�RECEIVE�CONDITION�INTERRUPT,*‘An�error�bit�is�on�in�the�status�register.*‘Determine�actual�cause.*‘bit�3�=�parity�error*‘bit�4�=�dada�overrun8*‘bit�5�=�framing�error�or�break�(break�if�data�reg�=�0)**ˆEntry:ƒA0�=�NOT�USED*‘A1�=�address�of�2661*‘A5�=�CCB�adddress*‘D0�=�status�register�value*‘D1�=�control�register�value$*‘D2�=�error�bits�of�status�register)*–D2�MUST�be�pulled�off�the�stack�in�here*O******************************************************************************* SRC:+‰POP.L„D2“restore�D2�to�make�the�rest�happy6‰BSET…#ERRSET,D1‹clear�status�reg�error�flags„02/14/85%‰MOVE.BƒD1,CREG(A1)Šdo�it�to�the�chip‰BTST…#PE,D0�a�parity�error?,‰BEQ.S„INTERR10�branch�if�not�a�parity�error;INTERR05�PUT_BYTE�PAR_FRAM,D0Šset�parity/framing�error�code ‰JSR†LOG_ERRŽand�go�tell�someone‰BRA.S„INT_EXIT$INTERR10�BTST…#DOVR,D0�data�overrun?*‰BEQ.S„INTERR20�branch�if�not�data�overrun0‰PUT_BYTE�OVERRUN,D0‹set�data�overrun�error�code ‰JSR†LOG_ERRŽand�go�tell�someone‰BRA.S„INT_EXIT%INTERR20�BTST…#FE,D0�a�framing�error?3‰BEQ.S„INT_EXIT�branch�if�no�-�we�shouldn't�be�here;‰MOVE.BƒDREG(A1),D0Šsee�if�a�break�instead�of�framing�error0‰BNE.S„INTERR05�branch�if�really�a�framing�error**ˆa�break�was�received*(‰MOVE.B„CREG(A1),D1‰get�control�register"‰BCLR†#RXEN,D1Œswitch�off�reciever)‰MOVE.B„D1,CREG(A1)‰tell�control�register*3‰JSR†TERM_BREAK‹Call�the�device�independent�routine*¦to�take�care�of�a�break.‰BRA.S„INT_EXIT‰PAGEO*********************************************************************************ˆFBMODE„FORCE�BREAK�INTERRUPT/*‘We�are�in�a�force�break�mode.‚We�want�to�stay3*‘in�this�mode�until�the�timer�we�previously�set-up *‘expires.**ˆEntry:‚A0�=�NOT�USED*�A1�=�address�of�2661*�A5�=�CCB�address*O******************************************************************************* FBMODE:+‰BRA.S„INT_EXIT�just�exit�interrupt�service‰PAGEO******************************************************************************** *ˆDSRTN…DATA�SET�READY�INTERRUPT4*’There�was�a�change�in�the�DSR�line�or�the‚DCD�line3*’or�the�transmitter�went�empty.‚We�only�care�about*’the�transmitter�going�empty.**ˆEntry:‚A0�=�NOT�USED*�A1�=�address�of�2661*�A5�=�CCB�address*�D0�=�status�register�value*�D1�=�control�register�value*O******************************************************************************* DSRTN:/‰MOVE.BƒSREG(A1),D1Šre-read�the�status�register,‰BTST…#DNR,D1Žis�the�interrupt�bit�still�on?3‰BEQ.S„INT_EXIT�branch�if�no,�ignore�this�interrupt,‰CMP.B„D0,D1�see�if�DSR�and�DCD�have�changed/‰BNE†TBE’this�is�really�a�transmitter�interrupt2‰BRA.S„I% NT_EXIT�we�don't�care�about�this�interrupt‰NOP‰PAGE*E*‚Now�exit�as�from�an�interrupt.‚We�may�in�fact�have�been�called�fromF*‚command�service�or�initialization,�but�they�had�to�set�it�up�to�look*‚like�an�interrupt,�too.*INT_EXIT:�POP.L‚D1‘Restore�D1,7ŠMOVEQ‚#1,D0Žset�carry�bit�to�tell�CMR�'we�handled�it,' ŠSUBQƒ#2,D0Ž*ŠRTS—and�return.ŠPAGEO********************************************************************************2*‰ROUTINES�TO�SET�THE�CLOCK�DIVISOR�TO�x16�AND�x64*7*‰No�work�here�since�2661�cannot�set�the�clock�divisor.*=*‰We�must�have�a�CLOCKRESET�entry�point�for�TERMLIB,�however.**‰Entry:*‹A5ƒ=�addr�of�our�CCB.**‰Exit:*O******************************************************************************* CLOCK_RESET:ŠRTSŠPAGEK*****************************************************************************!*�R�O�U�T�I�N�E�S„C�A�L�L�E�D„B�Y**–T�E�R�M�L�I�B**F**********************************************************************‰PAGEL******************************************************************************ˆTRANSMIT�THE�CHARACTER*?*ˆThis�is�the�device�dependent�routine�that�actually�writes�the*ˆcharacter�to�the�device.*F*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning�of�the *ˆdriver.**ˆEntry:„A1�=�address�of�2661*’A5�=�address�of�CCB*’D0.B�=�character�to�transmit*ˆInterrupt�level�on�entry:�0*C*ˆExit:…All�registers�are�preserved,�including�the�status�register.<*’It�is�important�to�keep�the�interrupt�level�the�same�as�it*’was�upon�entry.*J************************************************************************** PUT_CHAR:ŠSAVE„D1ŠPUSH„SR D***�The�following�code�was�commented�out�and�re-arranged�toŠ02/14/85#*** prevent the loss of characters:)***‡MOVE.B‚D0,DREG(A1)ˆtransmit�the�char.0***‡MOVE.B‚CREG(A1),D1ˆswitch�on�the�transmitter***‡BSET„#TXEN,D1‹set�the�bit$***‡MOVE.B‚D1,CREG(A1)ˆtell�the�chip ŠINHIBIT/ŠMOVE.B‚CREG(A1),D1ˆread�current�register�value-ŠBSET„#TXEN,D1‹set�the�transmitter�enable�bit7ŠMOVE.B‚D1,CREG(A1)ˆtell�the�chip�to�enable�transmitter*ŠMOVE.B‚D0,DREG(A1)ˆtransmit�the�character ŠPOP…SR ŠRESTORE�D1ŠRTS‰PAGEM******************************************************************************$*ˆCHECK�THE�DEVICE'S�TRANSMIT�BUFFER*F*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installed�at*ˆthe�beginning�of�the�driver.**ˆEntry:�A1�=�address�of�2661*�A5�=�address�of�CCB*ˆInterrupt�level�on�entry:�0**ˆExit:‚Condition�codes:"*��=�transmit�buffer�not�empty*��=�transmit�buffer�empty<*ˆIt�is�important�to�keep�the�interrupt�level�the�same�as�it*ˆwas�upon�entry.*M*****************************************************************************CK_TBE:ŠMOVEM.L�D0-D1,-(A7)ŠPUSHƒSRŠINHIBIT ŠMOVE.B�CREG(A1),D1 ŠMOVE.B�D1,D0ŠBSETƒ#TXEN,D1ŠMOVE.B�D1,CREG(A1)5ŠBTST.B�#0,SREG(A1)ˆTest�if�transmit�buffer�is�empty. ŠIF��THEN$ŒMOVE.B�D0,CREG(A1)†BUFFER�IS�EMPTY.ŒPOP„SR4ŒAND.W‚#$FFFB,SRˆset�condition�code�for�return�.ŒMOVEM.L�(A7)+,D0-D1ŒRTS ŠENDI **‚Transmitter�is�not�empty:*(ŠMOVE.B�D0,CREG(A1)ˆBUFFER�IS�NOT�EMPTY.ŠPOP„SR3ŠOR.Wƒ#$0004,SRŠset�condition�code�for�return�.ŠMOVEM.L�(A7)+,D0-D1ŠRTS‰PAGEH************************************************************************* *ˆDEVICE�DEPENDENT�RESET�ROUTINE*9*ˆThis�is�the�device-dependent�part�of�the�reset�routine.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:�A5�=�addr�of�CCB*ˆInterrupt�level�on�entry:�0*$*ˆExit:‚All�registers�are�preserved.<*ˆIt�is�important�to�keep�the�interrupt�level�the�same�as�it*ˆwas�upon�entry.*E********************************************************************* DDP_RESET:6ŠMOVEM.L‚A1/D0,-(A7)†save�used�registers�on�the�stack.ŠPUSH…SRŠINHIBIT )& ŠMOVE.LƒCCBCHB(A5),A1„get�address�of�26615ŠMOVE.Bƒ#$37,CREG(A1)„turn�the�tranmitter�on,�rec.�on'ŠMOVE.BƒDREG(A1),D0†clear�any�interrupt ŠPOP†SR0ŠMOVEM.L‚(A7)+,A1/D0†Restore�saved�registers�and ŠRTS—exit.ŠPAGEJ***************************************************************************@*‰SUBROUTINE�TO�SET�UP�THE�DEVICE�ACCORDING�TO�THE�CONFIGURATION*;*‰Uses�the�working�configuration�(in�the�CCB)�to�set�up�the;*‰device,�and�some�configuration-related�fields�in�the�CCB.*?*‰The�offset�to�this�routine�must�be�installed�at�the�beginning*‰of�the�driver.**‰Entry:�A5�=�address�of�CCB*‰Interrupt�level�on�entry:�0*$*‰Exit:‚All�registers�are�preserved.<*‰It�is�important�to�keep�the�interrupt�level�the�same�as�it*‰was�upon�entry.*J************************************************************************** SETUP:<ŠMOVEM.L�D0-D1/A0-A3,-(A7)�Save�some�registers�on�the�stack.ŠPUSHƒSR**‚First�set�up�addresses:4ŠLEA„CONFIG(A5),A0†A0�<--�addr�of�CCB�configuration.3ŠMOVE.L�CCBCHB(A5),A1†A1�<--�addr�of�our�2661�port. -ŠPUT_BYTE‚ASY16X,D0…Start�with�x16�clock�rate:ŠBTSTW‚#IOASTPB,IOSATW(A0)�Add�in�the�number�of�stop�bits. ŠIF…�THENŠOR.B…#SB1,D0�1�stop�bitŠELSEŠOR.B…#SB2,D0�2�stop�bitsŠENDI >ŠBTSTW‚#IOAUSEP,IOSATW(A0)�If�we're�using�parity,�enable�it... ŠIF…�THENŠOR.B…#PENBL,D0:ŠBTSTW‚#IOAPRTY,IOSATW(A0)�and�if�we're�using�even�parity,ŠIF…�THENŠset�it�up.ŠOR.B…#PTYPE,D0ŠENDIŠENDI 1ŠBTSTW‚#IOABITS,IOSATW(A0)�Add�in�bits/char�info. ŠIF…�THENŠOR.Bƒ#BIT7,D0ˆ(7�bits/char)ŠELSEŠOR.Bƒ#BIT8,D0ˆ(8�bits/char)ŠENDI ŠINHIBIT2ŠMOVE.BƒD0,MREG1(A1)…set�mode�reg�1�for�above�info2ŠMOVE.BƒIOSBRT(A0),D0„get�user�specified�baud�rate#ŠOR.B…#ITCX16,D0‡set�16x�clock�rate=ŠMOVE.BƒD0,MREG2(A1)…set�mode�reg�2�for�16x�clock�rate�&�baud ŠMOVE…(A7),SRŠPAGE*/*‚[5]„RTS�&�DTR�lines�low,�transmitter�enabled,*‰bits/char�from�configuration.*2ŠMOVE.Bƒ#$37,D0Žset�for�norm,�RTS�low,�reset�error"*ªflags,no�break,disable�transmit,*ªenable�receiver,�DTR�low***5***‚Remove�the�modem�test,�as�per�the�MPSCDRV�driver:***C****†BTSTW‚#IOAMODM,IOSATW(A0)„If�this�is�a�modem�we're�talking�to,****†IF…�THENŽ*8ŠBTSTW‚#IOAOFFH,IOSATW(A0)„and�the�guy�wants�it�offhook,ŠIF…�THENŽ*ŠAND.B‚#$FF-DTR,D0 ***‡ENDIš*ŠENDIš* ŠINHIBIT,ŠMOVE.B‚D0,CREG(A0)ˆset�the�control�register0ŠMOVE.B‚SREG(A0),D0ˆclear�any�pending�interruptsŠPOP„SR **‚Restore�registers�and�return.*8ŠMOVEM.L�(A7)+,D0-D1/A0-A3�Restore�registers�from�stack.ŠRTSŠPAGEJ****************************************************************************‰GET�DEVICE�STATUS�BYTE*"*‰Prepares�the�DEVICE�STATUS�byte.*8*‰Note:‚this�routine�does�not�set�the�break�indicator�in*�the�device�status�byte.*?*‰The�offset�to�this�routine�must�be�installed�at�the�beginning*‰of�the�driver.**‰Entry:�A5�=�address�of�CCB*‰Interrupt�level�on�entry:�0*&*‰Exit:‚D0.B�=�the�device�status�byte.<*‰It�is�important�to�keep�the�interrupt�level�the�same�as�it*‰was�upon�entry.*J************************************************************************** GET_STAT:*4* Let's see if the device status bit 'DSR' is ready.* ‰CLR.B…D0‰MOVEM.LƒD1/A0,-(A7) 2‰MOVE.L„CCBCHB(A5),A0‡get�the�address�of�the�2661.5‰MOVE.B„SREG(A0),D1‰get�the�DSR�bit�of�the�status�reg ‰TST.B…D1/‰IFˆ�THEN‹bit�7�is�the�DSR�bit�in�2661�chip5‰BSET†#XDSNRB,D0Šset�the�unready�bit�in�the�dev.state‰ENDI ‰MOVEM.Lƒ(A7)+,D1/A0‰RTS‰PAGEM******************************************************************************5*ˆDEVICE�DEPENDENT�STUFF�FOR�LOWERING�A�HARDWARE�LINE*ˆTO�STOP�THE�TRANSMITTER.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�address�of�2661*�A5�=�address�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*K**********& ***************************************************************** DDP_STOP:*0*ˆThe�VME101�board�needs�RTS�for�the�hand�shake!*ŠSAVE…D0 ,ŠMOVE.BƒCREG(A1),D0‰get�the�control�register%ŠBCLR…#RTS,D0�disable�request�to�send%ŠMOVE.BƒD0,CREG(A1)‰do�it�to�the�chip ŠRESTORE‚D0ŠRTSŠPAGEK****************************************************************************$*ˆDEVICE�DEPENDENT�UNSTOP�THE�DEVICE*=*ˆWhen�we�are�not�using�XOFF/XON,�we�unstop�the�device�in�our*ˆown�device�dependent�way.*;*ˆWe�are�running�in�background�when�this�routine�is�called.*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�address�of�2661*�A5�=�address�of�the�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*J************************************************************************** DDP_UNSTOP:*2*‰for�the�VME101�we�need�RTS�to�do�the�hand�shake.*ŠSAVE…D0 ,ŠMOVE.BƒCREG(A1),D0‰get�the�control�register$ŠBSET…#RTS,D0�enable�request�to�send)ŠMOVE.BƒD0,CREG(A1)‰and�do�it�to�the�chip ŠRESTORE‚D0ŠRTSŠPAGEK****************************************************************************&*ˆDEVICE�DEPENDENT�BEGIN�BREAK�ROUTINE*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�addr�of�2661*�A5�=�addr�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*E********************************************************************* DDP_BEG_BREAK:*)*‚start�the�2661�sending�the�break�signal*‰SAVE„D0 9‰MOVE.B‚CREG(A1),D0†get�current�state�of�control�register)‰OR.B„#FB,D0‹turn�on�the�force�brack�line+‰OR.B„#TXEN,D0‰turn�on�the�transmitter�also-‰MOVE.B‚D0,CREG(A1)†and�write�it�all�back�out ‰RESTORE�D0‰RTS‰PAGEK****************************************************************************$*ˆDEVICE�DEPENDENT�END�BREAK�ROUTINE*?*ˆThe�offset�to�this�routine�must�be�installed�at�the�beginning*ˆof�the�driver.**ˆEntry:‚A1�=�addr�of�2661*�A5�=�addr�of�CCB3*ˆInterrupt�level�on�entry:�INHIBITED�at�our�level.*$*ˆExit:ƒAll�registers�are�preserved.*L**************************************************************************** DDP_END_BREAK:ŠSAVE„D0 9ŠMOVE.B‚CREG(A1),D0Šget�current�state�of�control�registerŠBCLR„#3,D0�turn�off�the�break,ŠBCLR„#TXEN,D0�turn�off�the�transmitter�also)ŠMOVE.B‚D0,CREG(A1)Šand�write�it�back�out0ŠMOVE.B‚SREG(A1),D0Šclear�any�pending�interrupts ŠRESTORE�D0ŠRTSŠPAGEI***************************************************************************“B�A�C�K�G�R�O�U�N�D**šAND**‘C�A�L�L�__�G�U�A�R�D�E�D**–R�O�U�T�I�N�E�S**•(DEVICE-DEPENDENT)*E*********************************************************************ŠPAGEO*********************************************************************************‰FINISH�OFF�THE�INITIALIZATION*A*‰The�initialization�routine�has�gone�around�resetting�everything@*‰it�can,�but�the�routines�RESET�and�SETUP�should�only�be�called>*‰from�within�the�background.‚So�he�invoked�this�routine�to�do *‰it�for�him.**‰Entry:*�A1�=�address�of�2661.*�A5�=�address�of�CCB.*O******************************************************************************* DO_INIT:**‚Inhibit�interrupts*‰PUSH†SR‰INHIBIT*)*‚Get�address�of�start�of�driver�into�CCB*‰LEA‡EPCIDRV(PC),A4‰MOVE.L„A4,DRV_ADDR(A5) ‰JSR„RESETŽReset�everything.‰BSR.L‚DDP_RESET5‰BSR.L‚SETUPŽSet�up�the�2661�according�to�the�config.**‚Enable�interrupts�now.*‰POP‡SR‰RTS‰PAGE*********************** *‚PATCH�SPACE***********************ŠDS.Wƒ30ŠEND  ' NNNNNNNDIPCDRV„IDNTƒ48,0…VERSAdos�IPC�channel�I/O�Handler�Process�-�01/16/86@ŠTTL„IPCDRV:‚VERSAdos�IPC�channel�I/O�Handler�Process�-�01/16/86 ŠNOFORMATŠPAGE ŠLLENƒ120J***************************************************************************,* IPC -- REV. 1.05 02JUN80 (TB59) STEVE BALL4*�2.00�02NOV81�(TL09)�JIM�SMITH…-�SPLIT�IPC�FROM�CMR.*�2.01�01FEB82�(TL09)�JIM�SMITH…-�VECTOR�CHAIN**�2.02�23FEB82�(TL09)�JIM�SMITH…-�IOCB�USE4*�4.00�01SEP82ˆMARC�BRIEL„-�CONFIGURE�CLASS�REQUESTS4*�4.30�14SEP83�(TB59)�STEVE�BALL„-�FIX�HALT�I/O�BUGS6*�4.xx�23APR84ˆFRED�MATHESON�-�UPDATE�PER�NEW�FIRMWARE3*�4.40�28NOV84ˆPHIL�DUCLOSƒ-�ADD�CONFIG�AREA�IN�CCB:*�4.41�27DEC84ˆDICK�VANDERLIN�-�BUG�FIX�FOR�DCT�TABLE�SIZE.*�4.43�19MAR85ˆPHIL�DUCLOSƒ-�FIX‚HALT�I/O�BUGS8*�4.44�26MAR85ˆPHIL�DUCLOSƒ-�ADD�UPDATE�IOSATW�IN�CONFIG8*�4.45�12JUN85ˆPHIL�DUCLOSƒ-�QUICK�FIX�FOR�CMD�CHAN�BUGS*>*ˆ4.45�IS�A�QUICK�AND�DIRTY�FIX�FOR�SOME�COMMAND�CHANNEL�BUGS.F*ˆPLEASE!!!�FIX�THESE�BUGS�CORRECTLY�SOMETIME�IN�THE�FUTURE.�PJD�61285*8*�4.46�10SEPT85‡Bob�Matthewsƒ-�In�the�LUDTBL�the�current*²configuration�area�for*²entries�4,5,6,7�read�IOSPLN*²and�should�have�been�IOSTLN*2*�4.47�12DEC85ˆMike�D.ˆ-�Install�NEW�Killer�stuff.7*�4.48�16JAN86ˆSTEVE�LUDWIGƒ-�return�cyls,hds,spt�disks*B*******************************************************************+*�Changes�to�IPCDRV�for�version�4.3ƒ8/28/84*?*‚1.�The�IPC�driver�has�been�modified�to�take�advantages�of�the;*…increased�functionality�provided�by�recent�changes�to�the*…MCCM�firmware.*+*�Changes�to�IPCDRV�for�version�4.3ƒ9/25/84*<*‚1.�The�IPC�driver�was�modified�to�delete�refenences�to�the*…Seconday�Map�bit.*?*‚2.�The�IPC�driver�was�modified�to�include�changes�required�by*…4.4�enhancements.* *�Changes�to�IPCDRVƒ11/26/84ƒPJD*G* 1. The device area was moved from an allocated segment to the CCB andF*„current�configuration�information�was�added�to�the�CCB.‚2�additional@*„segments�are�now�required�for�the�CCB.‚The�getseg�call�for�theØß4è\ð?øI0>G8 G(I0D8B@IH5P7XV`ThNp=x<€7ˆ=�=˜= B¨=°6¸EÀKÈ?' *„device�area�was�deleted.*C********************************************************************.* USER REQUEST SIDE FOR IPC COMMAND PROCESSING*9*ƒPURPOSE:‚VALIDATE�AND�PASS�IPC�COMMAND�INFORMATION�FROM#*�USER�TO�IPC,�68000�SHARED�MEMORY.**ƒENTRY:‚JSR�FROM�CMR�HANDLER*‹JSR�FROM�INTERRUPT�HANDLER*5*ƒEXIT:‚RTS�-�PARAMETER�BLOCK�VALIDATION�STATUS�IN�D0***ƒSYSGEN�OPTIONS:�DCB�CONFIGURE�PARAMETERS**ƒEXEC�ROUTINES�CALLED:‚QEVENTT**ƒCODE�IS�RE-ENTRANT*H*-----------------------------------------------------------------------**ŠPAGE **‚Included�equate�files:*ˆ9995.&.TRACE.EQ*ˆ9995.&.STR.EQ*ˆ9995.&.TCB.EQ*ˆ9995.&.CCB.EQ*ˆ9995.&.IOE.EQ*ˆ9995.&.NIO.EQ*ˆ9995.&.LV5.EQ*ˆ9995.&.KILL.MC*ˆ9995.&.KILLDRV.EQ*ŠNOLISTŠINCLUDE�9995.&.TRACE.EQŠINCLUDE�9995.&.STR.EQŠINCLUDE�9995.&.TCB.EQŠINCLUDE�9995.&.CCB.EQŠINCLUDE�9995.&.IOE.EQŠINCLUDE�9995.&.NIO.EQŠINCLUDE�9995.&.LV5.EQŠINCLUDE�9995.&.KILL.MCŠINCLUDE�9995.&.KILLDRV.EQN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<ŠINCLUDE�9995.&.DUALPORT.MCŠINCLUDE�9995.&.UTILITY.MCN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>ŠLISTŠPAGE* ŠSECTION�0‰PAGEO*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83**ˆBIT�TEST�MACRO* BTSTM„MACRO „IFGE†\1-16‰OPT‡MEX‰BTSTW…#\1-16,\2(\3) ‰OPT‡NOMEX„ENDC* „IFLT†\1-16‰OPT‡MEX‰BTSTW…#\1,\2+2(\3) ‰OPT‡NOMEX„ENDC‰ENDM *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<‰PAGE**$*…EQUATES�FOR�TESTING�VECTOR�NUMBERS*#AVECTLOƒEQU„25‘LOWEST�AUTO�VECTOR�#$AVECTHIƒEQU„31‘HIGHEST�AUTO�VECTOR�##UVECTLOƒEQU„64‘LOWEST�USER�VECTOR�# IPCORG„EQU„*ŠPAGE*6* IPC COMMAND PACKET FORMAT (AS SEEN IN SHARED MEMORY)* ŠOFFSET�0IPCSTX„DS.Bƒ1*2�START�OF�TEXTIPCPID„DS.Bƒ1*2�PACKET�IDN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<*£$40�=�2nd�Configure�Packet*£0ƒ=�all�othersN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>IPCPKSZƒDS.Bƒ1*2�PACKET�SIZE IPCPHDVƒDS.Bƒ1*2�PHYSICAL�DEVICE%IPCCHCMƒDS.Bƒ1*2�CHANNEL�COMMAND�TYPEIPCDVCMƒDS.Bƒ1*2�DEVICE�COMMAND$IPCNBKSƒDS.Bƒ2*2�#BLOCKS�TO�TRANSFERIPCBKSZƒDS.Bƒ2*2�BLOCKSIZE*IPCBUFAD‚DS.Bƒ4*2�68000�ADDRESS�(PHYSICAL)IPCCKSMƒDS.Bƒ2*2�CHECKSUM$IPCCMPRM‚DS.Bƒ4*2�COMMAND�PARAMETERSIPCETX„DS.Bƒ1*2�ETX�LOCATION** OUTPUT WITH INPUT EXTENSIONŠOFFSET�IPCCMPRM!IPCSWCFƒDS.Bƒ4*2�SOFTWARE�OPTIONS-IPCNBKS2‚DS.Bƒ2*2�#BLOCKS�(OUTPUT�WITH�INPUT)/IPCBKSZ2‚DS.Bƒ2*2�BLOCKSIZE�(OUTPUT�WITH�INPUT)3IPCBUFA2‚DS.Bƒ4*2�68000�ADDRESS�(OUTPUT�WITH�INPUT)IPCETX2ƒDS.Bƒ1*2�ETX�LOCATION** CONFIGURE PACKET (1st)*ŠOFFSET�IPCNBKS)IPCHWC1ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�1)IPCHWC2ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�2)IPCHWC3ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�3)IPCHWC4ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�4)IPCSWC1ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�1)IPCSWC2ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�2)IPCSWC3ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�3)IPCSWC4ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�4IPCCETXƒDS.Bƒ1*2�ETX�LOCATIONN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<** CONFIGURE PACKET (2nd)*ŠOFFSET�IPCNBKS$IPCPMSKƒDS.Bƒ2*2�IOCB�PARAMETER�MASKIPCXOF„DS.Bƒ1*2�XOFF�CHARACTERIPCXON„DS.Bƒ1*2�XON�CHARACTER%IPCBRK„DS.Bƒ1*2�BREAK�EQUIVALENT�CHARŠDS.Bƒ1*2�UNUSED"IPCRPRTƒDS.Bƒ1*2�REPRINT�LINE�CHAR!IPCCNCLƒDS.Bƒ1*2�CANCEL�LINE�CHAR,IPCRTRMƒDS.Bƒ4*2�READ�TERMINATING�CHAR'S�(4)&IPCEOL„DS.Bƒ2*2�END�OF�LINE�STRING�(2)IPC2ETXƒDS.Bƒ1*2�ETX*N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>** FORMAT TRACK PACKETŠOFFSET�IPCBUFAD'IPCFPSNƒDS.Bƒ4*2�PHYSICAL�SECTOR�NUMBERIPCFETXƒDS.Bƒ1*2�ETX�LOCATION** FORMAT DISK PACKETŠOFFSET�IPCNBKSIPCDETXƒDS.Bƒ1*2�ETX�LOCATION** REQUEST STATUS PACKET( ŠOFFSET�IPCNBKSIPCRETXƒDS.Bƒ1*2�ETX�LOCATION* * IPC RETURN (COMPLETION) PACKET* ŠOFFSET�0RTNSTX„DS.Bƒ1*2�START�OF�TEXTRTNPID„DS.Bƒ1*2�PACKET�I.D.RTNPKSZƒDS.Bƒ1*2�PACKET�SIZE RTNPHDVƒDS.Bƒ1*2�PHYSICAL�DEVICE RTNCHCMƒDS.Bƒ1*2�CHANNEL�COMMANDRTNSTCMƒDS.Bƒ1*2�STATUS�COMMANDRTNSTVLƒDS.Bƒ2*2�STATUS�VALUERTNSTPRƒEQU„*’STATUS�PARAMETERS** IPC NORMAL COMPLETION EVENT*ŠOFFSET�RTNSTPRRTNBLKSƒDS.Bƒ2*2�NO.�OF�BLOCKSRTNBKSZƒDS.Bƒ2*2�BLOCK�SIZE#RTNDADRƒDS.Bƒ4*2�68K�MEMORY�ADDRESS** DISK ERROR COMPLETION EVENT*ŠOFFSET�RTNSTPR%RTNSECNƒDS.Bƒ4*2�ENDING�SECTOR�NUMBER** DISK STATUS RETURN*ŠOFFSET�RTNSTPRRTNDSTAƒDS.Bƒ2*2�DEVICE�STATUS RTNLSECƒDS.Bƒ4*2�LOGICAL�SECTORS* * PRINTER/TERMINAL STATUS RETURN*ŠOFFSET�RTNSTPRRTNSTADƒDS.Bƒ4*2�DEVICE�STATUS)RTNHWS1ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�1)RTNHWS2ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�2)RTNHWS3ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�3)RTNHWS4ƒDS.Bƒ1*2�H/W�CONFIGURATION�BYTE�4)RTNSWS1ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�1)RTNSWS2ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�2)RTNSWS3ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�3)RTNSWS4ƒDS.Bƒ1*2�S/W�CONFIGURATION�BYTE�4** IPC MEM MAPPED EQUATES*,IPCINT„EQU„$0D�68000�TO�IPC�INTERRUPT�OFFSET*IPCRESET‚EQU„$0F�68000�TO�IPC�RESET�OFFSET'IPCIMB1ƒEQU„$101�68000�TO�IPC�WRITE�BOX%IPCIAB1ƒEQU„$103�68000�TO�IPC�ACK�BOX#IPCIM1„EQU„$105�68000�COMMAND�WRITE'IPCIMB2ƒEQU„$181�IPC�TO�68000�WRITE�BOX%IPCIAB2ƒEQU„$183�IPC�TO�68000�ACK�BOX!IPCIM2„EQU„$185�IPC�COMMAND�WRITE*IPCLST„EQU„$1FF�LAST�BYTE�OF�SHARED�MEMORY** MISCELLANEOUS EQUATES* STX‡EQU„$02 ETX‡EQU„$03 RSˆEQU„$1E ACK‡EQU„$06 NAK‡EQU„$151LUMAX…EQU„8’MAXIMUM�DEVICE�NO.�VALUE�FOR�DISK�IPC(*£MCCM�MAX�IS�5�BUT�THEIR�IS�TABLE�SPACE*£ENOUGH�FOR�8.(IPCRDCDƒEQU„$10�CHANNEL�COMMAND�FOR�READ)IPCWRCDƒEQU„$20�CHANNEL�COMMAND�FOR�WRITE(RTNGDC„EQU„$70�NORMAL�STATUS�PACKET�CODE,RTNHLT„EQU„$71�HALT/ABORT�STATUS�PACKET�CODE+RTNSTA„EQU„$72�SOLICITED�STATUS�PACKET�CODE&RTNUNS„EQU„$80�UNSOLICITED�PACKET�CODE"RTNGDS„EQU„$0000ŽGOOD�STATUS�VALUE,SPKT†EQU„$0200ŽFIRST�2�BYTES�OF�EVERY�PACKET+SECSIZƒEQU„$100“SYSTEM�REQUIRED�SECTOR�SIZE'IOPKSZ„EQU„21”READ�OR�WRITE�PACKET�SIZE,OWIPKSZƒEQU„29”OUTPUT�WITH�INPUT�PACKET�SIZE'STPKSZ„EQU„7•STATUS�REQUEST�PACKET�SIZE#CNPKSZ„EQU„15”CONFIGURE�PACKET�SIZEN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<'C2PKSZ„EQU„21”CONFIGURE�2nd�PACKET�SIZE(TBKPKSZƒEQU„7•TRANSMIT�BREAK�PACKET�SIZEN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>$FDPKSZ„EQU„7•FORMAT�DISK�PACKET�SIZE&FTPKSZ„EQU„15”FORMAT�TRACK�PACKET�SIZEHLTPKSZƒEQU„7•HALT�PACKET�SIZEIOEVCD„EQU„1•I/O�EVENT�CODE$SMMBIT„EQU„24”SECONDARY�MEM.�MAP�BIT3PRTPRM„EQU„$0023‘PRINTER�CONFIG�PARAMETER�EDIT�MASK4PRTATM„EQU„$0003‘PRINTER�CONFIG�ATTRIBUTES�EDIT�MASK4TERPRM„EQU„$5FB3‘TERMINAL�CONFIG�PARAMETER�EDIT�MASK5TERATM„EQU„$06FE‘TERMINAL�CONFIG�ATTRIBUTES�EDIT�MASK** OPTION EQUATES*$XPKCECH‚EQU„$C0000000ŽNO�ECHO�OPTIONN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<)XPKCNUL‚EQU„$A0000000ŽACCEPT�NULLS�OPTIONN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PJD 3/14/85 >>>>>>>)XPKNTPA‚EQU„$90000000ŽNO�TYPEAHEAD�OPTIONN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PJD 3/14/85 >>>>>>>)XPKCXFN‚EQU„$84000000ŽUSE�XOFF/XON�OPTIONN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PJD 3/14/85 >>>>>>>-XPKCTAB‚EQU„$88000000ŽFLUSH�TYPE�AHEAD�BUFFERN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<+XSWFF„EQU„$82000000ŽTOP�OF�PAGE�(FORM�FEED)** CONFIGURATION EQUATES*XHWBITƒEQU„2–8�BIT�PARITYXHWPRTY‚EQU„4–PARITYXHWEVNƒEQU„5–EVEN�PARITYXHWSTPƒEQU„6–2�STOP�BITSXHWMDMƒEQU„4–MODEM*N*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<XSWXONƒEQU„2–XON/XOFF�OR�CTS)XSWFLSH‚EQU„3–FLUSH�THE�TYPE�AHEAD�BUFFER'XSWTAHD‚EQU„4–ACCEPT/INHIBIT�TYPE�AHEAD( !XSWNULƒEQU„5–DISCARD/ACCEPT�NULLSN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>XSWHDXƒEQU„6–HALF�DUPLEXXSWALFƒEQU„0–AUTO�LINE�FEED%XSWTOFƒEQU„1–TOP�OF�FORM�BEFORE�PRINT‰PAGE*%*ˆEQUATES�FOR�CHANNEL/DEVICE�COMMANDS*XREAD„EQU…$1001�READ!XWRITCƒEQU…$2001�WRITE�WITH�CHECK$XWRITNƒEQU…$2002�WRITE�WITHOUT�CHECKXRCRC„EQU…$3001�READ�CRCXREADYƒEQU…$3002�READY"XRDHP„EQU…$3003�READ�HEAD�POSITIONXFTRAKƒEQU…$4001�FORMAT�TRACKXFDISKƒEQU…$4002�FORMAT�DISK'XWDDM„EQU…$4003�WRITE�DELETED�DATA�MARKXRESTOR‚EQU…$4004�RESTOREXSEEK„EQU…$4005�SEEKXHALT„EQU…$5001�HALTXBOOT„EQU…$6000�BOOTSTRAP�LOAD*6*ˆADDITIONAL�EQUATES�FOR�COMM.�CHANNEL/DEVICE�COMMANDS*XINF…EQU…$1001�READ�FORMATTEDXINI…EQU…$1002�READ�IMAGE XOUTF„EQU…$2001�OUTPUT�FORMATTEDXOUTI„EQU…$2002�OUTPUT�IMAGE0XOFIF„EQU…$2801�OUTPUT�FORMATTED�INPUT�FORMATTED,XOFIM„EQU…$2802�OUTPUT�FORMATTED�INPUT�IMAGE(XOIIM„EQU…$2803�OUTPUT�IMAGE�INPUT�IMAGE,XOIIF„EQU…$2804�OUTPUT�IMAGE�INPUT�FORMATTED"XBCASTƒEQU…$2007�BROADCAST�MESSAGE XCONH„EQU…$4001�CONFIGURE�DEVICEN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<.XCON2PƒEQU…$4002�CONFIGURE�DEVICE�(2ND�PACKET)&XCNF2PK‚EQU…$40‘PACKET�ID�(2ND�PACKET)(XTRNSBK‚EQU…$4003�TRANSMIT�BREAK�REQUESTN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>**ˆSTATUS�VALUE*XPSOK„EQU…0“SUCCESSFULXPSCRCƒEQU…1“DATA�CRC�ERROR!XPSDWPƒEQU…2“DISK�WRITE�PROTECTEDXPSDNRƒEQU…3“DISK�NOT�READY#XPSRDMƒEQU…4“READ�DELETED�DATA�MARK"XPSDEVƒEQU…5“INVALID�DEVICE�ADDRES!XPSIDAƒEQU…6“INVALID�DISK�ADDRESSXPSSEKƒEQU…7“RESTORE�ERRORXPSDMEƒEQU…8“RECORD�NOT�FOUND#XPSMRKƒEQU…9“ADDRESS�MARK�CRC�ERRORXPSCDMA‚EQU…$A’DMA�ERRORXPSCSMƒEQU…$B’CHECKSUM�ERRORXPSBSYƒEQU…$C’DEVICE�BUSY(XPSCBSY‚EQU…$D’CHANNEL�BUSY�(FORMATTING)XPSINDƒEQU…$E’INDETERMINATEXPSCNTL‚EQU…$F’CONTROLLER�ERRORXPSDVCƒEQU…$10‘DEVICE�ERRORXPSSEEK‚EQU…$11‘SEEK�ERROR#XPSNODR‚EQU…$12‘NO�DEVICE�CONNECTED&XPXCFGƒEQU…$13‘DEVICE�CONNECT�CONFLICTXPSCMPƒEQU…$14‘COMPARE�ERROR%XPSSWPƒEQU…$15‘SECTOR�WRITE�PROTECTEDXPSBADƒEQU…$16‘BAD�SECTORXPSTOTƒEQU…$17‘TIMEOUTXPSCMDƒEQU…$18‘INVALID�COMMAND!XPSICMƒEQU…1“INVALID�HALT�COMMANDXPSDMAƒEQU…1“DMA�CHANNEL�ERROR'XPSCSTA‚EQU…1“PERSONALITY�STATUS�RETURNO*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<<&*ˆIPC�Completion�Packet�Flag�Positions*'PIDPKTF‚EQU…6“PACKET�ID�2nd�PACKET�FLAGO*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>>* *ˆADDITIONAL�COMM.�STATUS�VALUES*XPSPARƒEQU…1“PARITY�ERRORXPSBRKƒEQU…2“BREAK�CONDITIONXPSFRMƒEQU…4“FRAMMING�ERRORXPSOVRƒEQU…6“DATA�OVERUN!XPSOUTƒEQU…7“PRINTER�OUT�OF�PAPER**ƒMiscellaneous�equates*5CCBEXTRA‚EQU„3”This�parameter�specifies�the�number�of+*£extra�pages�to�be�allocated�by�CMR�to�the**£CCB�when�the�channel�is�allocated.�Up�to"*£255�extra�pages�may�be�specifiedŠPAGE*** MACRO FOR PUTTING THE H/W PRIORITY LEVEL'* TO THE PRIORITY INDICATED BY THE CCB.* INHIB„MACRO,‰MOVE.W„CCBISR(A5),SR‡SET�PROCESSOR�PRIORITY‰ENDM*+* MACRO FOR DROPPING THE H/W PRIORITY LEVEL* TO AN INTERRUPTABLE STATE.* ENABL„MACRO3‰MOVE.W„CCBSR(A5),SRˆDROP�PROCESSOR�PRIORITY�BY�ONE‰ENDM‰PAGE* * STRUCTURE FOR DEVICE NO. TABLE* ‰OFFSET�0LUFLG„DS.Bƒ2–ENTRY�FLAGLUDCB„DS.Bƒ4–DCB�ADDRESSLUIOCBƒDS.Bƒ4–IOCB�ADDRESSLUTCB„DS.Bƒ4–TCB�ADDRESSLUBADRƒDS.Bƒ4–BUFFER�ADDRESS-LUMISCƒDS.Bƒ4–MISC�LWORD�(USED�WITH�HALT�I/O)>CNFG…DS.BƒIOSDDC-IOSATWŠspace�for�device�#�independent�portion*¦of�configuration.5LUENTRY‚EQU„*–length�of�common�part�of�device�#�entry**ˆAPPROXIMATELY�225�INSTRUCTIONS�EXECUTED�TO�GET�TO�THIS�POINT *ˆ(600�us).*J***************************************************************************IOHUSER:** CHECK FOR RESET*ƒIF�RESET,�DO�IT�AND�GET�OUT*)ŠCMP.B‚#XDREST,XIOSCD(A2)�TEST�RESET�BYTE#ŠBNE.S‚IOH01000‹BRANCH�IF�NOT�RESETŠBSR„CMRRESTŒCALL�RESET�ROUTINEŠBRA„IPCUSRTN‹RETURN*$* RETURN IF CHANNEL IS IN ERROR MODE*!IOH01000‚BTSTW‚#CCBFGER,CCBFG(A5)2ŠBEQ.S‚IOH01010‹BRANCH�IF�NOT�MARKED�IN�ERROR�MODE)ŠMOVE.B�#ISTACDN,D1ˆSET�UP�IOS�ERROR�CODE ŠBRA„ABORT*D* IF WE ARE WAITING FOR ACK/NAK THEN WE CANNOT HONOR THE REQUEST AND2*ƒMUST�SIGNAL�THE�CALLER�THAT�THE�CHANNEL�IS�BUSY.*IOH01010‚EQU„* ŠCLR.L‚D7'ŠBTSTW‚#CCBFGWAK,CCBFG(A5)�WAITING�ACK?)ŠBNE.S‚IOH01015‹BRANCH�IF�NOT�WAITING�ACK* 2ŠBTSTW‚#CCBBUSY,CCBFG(A5)„COMMAND�BUILD�AREA�BUSY?#ŠBEQ.S‚IOH01020ŽNO,�PROCESS�COMMAND*F* REQUEST CAME THRU WHILE WAITING FOR ACK - GIVE USER BACK BUSY STATUS*,IOH01015‚MOVE.B�#XSTBSY,D0‡ERROR�RETURN�CODE ŠBRA„IPCUSRTN*(* CONVERT LOGICAL PB ADDRESS TO PHYSICAL*IOH01020‚CLR.L‚D5,ŠMOVE.L�XIOCPK(A2),D6†ADDR�OF�COMMAND�PACKET+ŠMOVE.W�XIOPLN(A2),D5†LENGTH�OF�COMMAND�PKT"ŠMOVE.L�CCBTASKA(A5),A1„SET�UP�TCB ŠBSR„IOHADRCKŠBRA.S‚IOH01060‹GOOD�RETURNŠNOP—BAD�LENGTH�RETURN(ŠMOVE.B�#ISTAIP,D1‰SET�UP�IOS�ERROR�CODE ŠBRA„ABORT5IOH01060‚MOVE.L�D6,A3ŽCOMMAND�PACKET�PHYSICAL�ADDRESS*3* DETERMINE IF SHARED MEMORY IS FREE (IT SHOULD BE)*.ŠMOVE.L�CCBCHB(A5),A4†MEMORY�MAPPED�BASE�TO�A4ŠMOVE.B�IPCIMB1(A4),D00ŠBEQ.S‚IOH02060‹BRANCH�IF�NO�ERROR�(MEMORY�FREE)*:* SHARED MEMORY IS NOT FREE AND WE ARE NOT WAITING ON ACK.*ƒERROR�CONDITION.*)ŠBSETW‚#CCBFGER,CCBFG(A5)�MARK�CCB�AS�BAD)ŠMOVE.B�#ISTACDN,D1ˆSET�UP�IOS�ERROR�CODE ŠBRA„ABORT *K****************************************************************************(*‚FIND�THE�COMMAND�IN�THE�COMMAND�TABLE.* IOH02060‚EQU„*)ŠMOVE.L�XIOUID(A2),A4†PICK�UP�DCB�POINTER8ŠMOVE.L�CCBTASKA(A5),CCBTASKB(A5)�SET�UP�BUFFER�TASK�TCB-ŠMOVEQ‚#NUMCMDS-1,D0†Set�up�the�loop�counter./ŠLEA„CMDTBL,A0ŠA0�<--�address�of�command�table./ŠMOVE.W�IOSFCT(A3),D6†Set�up�user�command�code. 8CMDSRCHƒCMP.W‚(A0)+,D6‹Search�the�table�for�the�command.ŠDBEQƒD0,CMDSRCH‰* 3ŠBNE.S‚CMDERR�If�we�found�the�command�in�the�table,8ŠADD.L‚#JMPOFF-2,A0‡get�the�corresponding�entry�from�the5ŠMOVE.W�(A0),D0Œjump�table�and�jump�to�the�routine�to"ŠJMP„(A0,D0.W)Šhandle�the�command.ŠSPC„2>CMDERR„MOVE.B�#ISTAIF,D1ŠThe�command�wasn't�found�in�the�table2ŠBRA„ABORTŽso�exit�with�an�invalid�function�error.ŠPAGEM*******************************************************************************‰REQUEST�STATUS*(*‰Entry:�A2�=�address�of�CMR�param�block*�A3�=�address�of�user's�IOCB*�A4�=�address�of�DCB*�A5�=�address�of�my�CCB*�A6�=�address�of�user's�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory*M******************************************************************************REQSTAT:&ŠBSR†CNFGLEN�SET�UP�DATA�BUFFER�LENGTH0ŠMOVE.LƒIOSDBP(A3),D6‡SET�UP�DATA�BUFFER�ADDRESS ŠBSR†BUFADDR*¦Physical�Addr�returned�in�D62ŠMOVE.LƒD6,CCBPTR(A5)‡SAVE�BUFFER�PHYSICAL�ADDRESSŠSPC†2*?*‰Retrieve�the�masks�of�supported�attributes�and�parameters�for@*‰the�requested�device�and�store�them�in�the�users�configuration*‰status�block.* ŠMOVE.L�D6,A0 ŠBSR„VALATPRM$ŠMOVE.W�D0,IOSATM(A0)‰Attribute�mask$ŠMOVE.W�D1,IOSPRM(A0)‰Parameter�mask-ŠCMP.B‚#XTDIPC,CCBTYPE(A5)ƒDISK�IPC?‚<<011686ŠIF…�THEN.S8ŠMOVE.B�DCBDKC+IOSSPT(A4),IOSSPT(A0)‚RETURN�SPT�FROM�DCB9ŠMOVE.W�DCBDKC+IOSTRK(A4),IOSTRK(A0)‚RETURN�CYLS�FROM�DCB8ŠMOVE.B�DCBDKC+IOSHDS(A4),IOSHDS(A0)‚RETURN�HDS�FROM�DCBŠENDI™011686>>ŠSPC„2 ŠCLR.L„D6-ŠBSET…#LUFACT,D6ŠSET�ACTIVE�DEVICE�TABLE�FLAG%ŠBSR†DEVTBLŽSET�UP�DEVICE�TABLE�ENTRY /ŠBSR†SETPKTŽSET�UP�PACKET�HEADER�IN�SHARED�MEM. ŠMOVE.Wƒ#XREADY,D16ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDS#ŠMOVE.Bƒ#ETX,IPCRETX(A1)„SET�UP�ETX.ŠMOVE.Bƒ#STPKSZ,IPCPKSZ(A1)�SET�UP�PACKET�SIZE ŠBRA†NRMEXIT      ŠPAGEM****************************************************************************** *‰CONFIGURE*@*‰This�command�changes�the�CCB�configuration,�the�one�from�which<*‰the�driver�sets�up�the�device�and�under�which�it�performs.*(*‰Entry:�A2�=�address�of�CMR�param�block*�A3�=�address�of�user's�IOCB*�A4�=�address�of�DCB*�A5�=�address�of�my�CCB*�A6�=�address�of�user's�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory*M****************************************************************************** CONFIGUR:%ŠCMP.B„#XTDIPC,CCBTYPE(A5)�DISK�IPC‚?/ŠBEQ†REQSTAT�YES,�MUST�LOOK�LIKE�STATUS�REQUEST &ŠBSR†CNFGLEN�SET�UP�DATA�BUFFER�LENGTH0ŠMOVE.LƒIOSDBP(A3),D6‡SET�UP�DATA�BUFFER�ADDRESS ŠBSR†BUFADDR* 2ŠMOVE.LƒD6,CCBPTR(A5)‡SAVE�BUFFER�PHYSICAL�ADDRESS#ŠMOVE.LƒD6,A0�SET�UP�BUFFER�POINTERŠSPC„2-ŠBSR†VALATPRMŒRetrieve�the�masks�of�supported6ŠMOVEM.W‚D0-D1,-(A7)‰attributes�and�parameters�for�the(*¦requested�device�and�save�the�masks�on *¦the�stack.ŠSPC„29ŠMOVE.Bƒ#CECUAP,D2ŠIf�unsupported�attributes�or�parameter2ŠNOT.W„D0’are�specified�in�the�users�attributes�or<ŠAND.W„IOSATM(A0),D0‡parameters�mask,�return�a�configuration*ŠNOT.W„D1’error.�Restore�the�stacked�masks1ŠAND.W„IOSPRM(A0),D1‡before�processing�the�error. ŠOR.W…D0,D1ŠMOVEM.W‚(A7)+,D0-D1ŠBNE.S„IPCR220AŠSPC„26ŠMOVE.Bƒ#CECCDO,D2ŠIf�the�user�is�trying�to�change�the1ŠMOVE.Wƒ#%1100,D3‹read�or�write�timeout,�return�a)ŠAND.W„IOSPRM(A0),D3‡configuration�error.ŠBNE.S„IPCR220AŠBRA.S„IPCR220BŠPAGEŠSPC†2BIPCR220A‚MOVE.BƒD2,IOSCEC(A0)‡Save�the�configuration�error�code�in:ŠMOVE.Bƒ#ISTACNF,D1‰the�users�configuration�data�block�and/ŠBRA†ABORT�return�a�configuration�error�to�IOS.ŠSPC†2IPCR220B‚CLR.L„D6-ŠBSET…#LUFACT,D6ŠSET�ACTIVE�DEVICE�TABLE�FLAG%ŠBSR†DEVTBLŽSET�UP�DEVICE�TABLE�ENTRY*/ŠBSR†SETPKTŽSET�UP�PACKET�HEADER�IN�SHARED�MEM.ŠMOVE.Wƒ#XCONH,D16ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDSŠSPC†23ŠMOVE.LƒCCBPTR(A5),A0‡Load�the�address�of�the�users*¦configure�parameter�block.N*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PJD 11/26/843‰MOVEM.LƒA5,-(A7)ŒSave�the�CCB�address�on�the�stack:‰MOVE.L„CCBDTBL(A5),A5†Get�the�start�address�of�the�device*¦tables‰CLR.L…D0’Need�the�whole�reg!4‰MOVE.B„DCBCDV(A4),D0‡Get�the�device�number�from�DCB6‰MULU†#LUDSZE,D0ŠMUL�size�of�an�entry�by�device�number&*¦to�get�distance�from�start�of�table./‰ADD.L…D0,A5�Add�to�base�to�get�start�of�device*¦table�for�this�device.4‰LEA‡CONFIG(A5),A5‡Use�offset�from�base�of�CONFIG�so!*¦we�can�use�the�IOE�equates�into*¦the�configuration�data.N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< PJD 11/26/84ŠSPC†2O*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83A*‰BTSTW‚#DATPRT,DCBATT(A4)ƒIf�the�requested�device�is�a�terminal,>ŠBTSTM‚DATPRT,DCBATT,A4…If�the�requested�device�is�a�terminal, *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<:ŠBEQ.S‚IPCR222Œbranch�to�generate�a�terminal�configuration *£packet.‰PAGE*)*ˆSet�up�the�printer�configuration�packet**'*ˆStart�of�Hardware�Confoguration�bytes0ŠMOVE.Lƒ#$80000000,D0‡SET�UP�H/W�CONFIGURE�BYTES*&*ˆCheck�for�line�length�change�request*B‰BTSTW…#IOSRECB,IOSPRM(A0)�Does�he�want�to�change�the�line�length?#‰BEQ.S…IPCR221AŒNo,�use�the�current=ŠMOVE.BƒIOSREC+1(A0),D0…Yes,�pick�up�the�line�length�he�wants‰BRA.S…IPCR221B**ˆUse�the�current�line�length*;IPCR221A�MOVE.B„IOSREC+1(A5),D0…Use�the�current�line�lengthCIPCR221B‚MOVEP.L‚D0,IPCHWC1(A1)†PUT�H/W�CONFIGURATION�IN�SHARED�MEM%*ˆEnd�of�Hardware�Configuration�bytes'*ˆStart�of�Software�Configuration�bytes‰MOVE.L„#$00000080,D0*+*ˆCheck�for�Top�of�Form�before�print�option*A‰BTSTW…#IOASNFF,IOSATM(A0)�Does�he�want�to�change�the�Top�of�Form *¦option?#‰BEQ.S…IPCR221DŒNo,�use�the�current8‰BTSTW…#IOASNFF,IOSATW(A0)�Yes,�does�he�want�the�option? ‰BEQ.S…IPCR221EŒNo,�don't�set�it-IPCR221C�BSET†#XSWTOF,D0ŠYes,�set�the�option!‰BRA.S…IPCR221EDIPCR221D�BTSTW…#IOASNFF,IOSATW(A5)�Is�the�option�set�in�the�current? ‰BNE.S…IPCR221CŒYes,�keep�it�set:IPCR221E�ROL.L…#8,D0�Rotate�the�first�byte�out�of�the�way.*!*ˆCheck�for�Auto�Line�feed�option*C‰BTSTW…#IOALNFD,IOSATM(A0)�Does�he�want�to�change�the�AUTO�LINEFEED *¦option?#‰BEQ.S…IPCR221GŒNo,�use�the�current<ŠBTSTW„#IOALNFD,IOSATW(A0)�Yes,�does�he�want�AUTO�LINE�FEED?.ŠBEQ.S„IPCR221HŒNo,�NO�AUTO�LINE�FEED�desired.;IPCR221F‚BSET…#XSWALF,D0ŠYes,�set�the�AUTO�LINE�FEED�option‰BRA.S…IPCR221H6IPCR221G�BTSTW…#IOALNFD,IOSATW(A5)�Use�AUTO�LINE�FEED?3‰BNE.S…IPCR221FŒYes,�set�the�AUTO�LINE�FEED�option.+ ;IPCR221H�ROL.L…#8,D0�Rotate�the�second�byte�out�of�the�way.*'*ˆCheck�the�end�of�line/print�character*C‰BTSTW…#IOSELCB,IOSPRM(A0)�Does�he�want�to�change�the�end-print�ch?#‰BEQ.S…IPCR221IŒNo,�use�the�current7‰MOVE.B„IOSELC(A0),D0‡Yes,�get�the�char�he�wants�to�use‰BRA.S…IPCR221J3IPCR221I�MOVE.B„IOSELC(A5),D0‡Use�the�current�value6IPCR221J�ROL.L…#8,D0�Move�the�3rd�byte�out�of�the�way.*4*ˆAll�choices�made,�send�the�lword�to�the�shared�ram*?‰MOVEP.LƒD0,IPCSWC1(A1)†Send�the�Software�Config�to�shared�mem.*)*ˆEnd�of�the�Software�Configuration�bytes"*ˆEnd�of�the�Printer�Configuration* ŠBRA†IPCR249ŠPAGE*!*ˆStart�of�Terminal�Configuration* IPCR222ƒEQU†*ŠMOVE.Lƒ#$80,D0*"*‰CHECK�ATTRIBUTE�MASK�-�STOP�BITS*ŠBTSTW„#IOASTPB,IOSATM(A0)ŠBEQ.S„IPCR223ŽUSE�DEFAULT*%*‰SETUP�STOP�BITS�FROM�ATTRIBUTE�WORD*(ŠBTSTW„#IOASTPB,IOSATW(A0)‚2�STOP�BITS�?ŠBEQ.S„IPCR225ŽBRANCH�IF�NO&ŠBRA.S„IPCR224ŽYES�-�GO�SET�OPTION�BIT*1*‰SETUP�STOP�BITS�FROM�CURRENT�CONFIGURATION�AREA* IPCR223ƒEQU†*(ŠBTSTW„#IOASTPB,IOSATW(A5)‚2�STOP�BITS�?ŠBEQ.S„IPCR225ŽBRANCH�IF�NO**‰SET�THE�OPTION�BIT* IPCR224ƒEQU†*ŠBSET…#XHWSTP,D0*%*‰CHECK�ATTRIBUTE�MASK�-�7/8�BIT�MASK* IPCR225ƒEQU†*ŠBTSTW„#IOABITS,IOSATM(A0)ŠBEQ.S„IPCR226�USE�DEFAULT***‰SETUP�NUMBER�OF�BITS�FROM�ATTRIBUTE�WORD*"ŠBTSTW„#IOABITS,IOSATW(A0)‚8�BIT�?ŠBNE.S„IPCR228ŽBRANCH�IF�NOŠBRA.S„IPCR227ŽYES*6*‰SETUP�NUMBER�OF�BITS�FROM�CURRENT�CONFIGURATION�AREA* IPCR226ƒEQU†*"ŠBTSTW„#IOABITS,IOSATW(A5)‚8�BIT�?ŠBNE.S„IPCR228ŽBRANCH�IF�NO**‰SET�THE�8�BIT�OPTION�BIT* IPCR227ƒEQU†*$ŠBSET…#XHWBIT,D0‹YES,�SET�OPTION�BIT**‰CHECK�ATTRIBUTE�MASK�-�PARITY* IPCR228ƒEQU†*ŠBTSTW„#IOAUSEP,IOSATM(A0)ŠBEQ.S„IPCR229�USE�DEFAULT*&*‰SETUP�PARITY�USE�FROM�ATTRIBUTE�WORD*%ŠBTSTW„#IOAUSEP,IOSATW(A0)‚USE�PARITYŠBEQ.S„IPCR231ŽBRANCH�IF�NOŠBRA.S„IPCR230ŽYES*2*‰SETUP�PARITY�USE�FROM�CURRENT�CONFIGURATION�AREA* IPCR229ƒEQU†*$ŠBTSTW„#IOAUSEP,IOSATW(A5)‚USE�PARIYŠBEQ.S„IPCR231ŽBRANCH�IF�NO**‰SET�THE�PARITY�USE�OPTION�BIT* IPCR230ƒEQU†*%ŠBSET…#XHWPRTY,D0ŠYES,�SET�OPTION�BIT*(*‰CHECK�ATTRIBUTE�MASK�-�ODD/EVEN�PARITY* IPCR231ƒEQU†*ŠBTSTW„#IOAPRTY,IOSATM(A0)ŠBEQ.S„IPCR232�USE�DEFAULT*+*‰SETUP�EVEN/ODD�PARITY�FROM�ATTRIBUTE�WORD*&ŠBTSTW„#IOAPRTY,IOSATW(A0)‚EVEN�PARITYŠBEQ.S„IPCR234ŽBRANCH�IF�NOŠBRA.S„IPCR233ŽYES*7*‰SETUP�EVEN/ODD�PARITY�FROM�CURRENT�CONFIGURATION�AREA* IPCR232ƒEQU†*(ŠBTSTW„#IOAPRTY,IOSATW(A5)‚EVEN�PARITY�?ŠBEQ.S„IPCR234ŽBRANCH�IF�NO* *‰SET�THE�PARITY�EVEN�OPTION�BIT* IPCR233ƒEQU†*$ŠBSET…#XHWEVN,D0‹YES,�SET�OPTION�BIT*%*‰PUT�BYTE�1�H/W�CONFIG�IN�SHARED�MEM* IPCR234ƒEQU†*ŠMOVE.BƒD0,IPCHWC1(A1)*(*ˆCheck�the�parameters�mask�for�baudrate*<‰BTSTW…#IOSBRTB,IOSPRM(A0)�Should�we�configure�the�baudrate?'‰BEQ.S…IPCR234AŒNo,�use�the�current�one.ŠMOVE.BƒIOSBRT(A0),D0‡Yes,�pick�up�the�new�one‰BRA.S…IPCR234B*(*ˆUse�the�current�configuration‚baudrate*=IPCR234A�MOVE.B„IOSBRT(A5),D0‡Use�the�current�config�baudrate>‰MOVE.B„D0,IOSBRT(A0)‡Update�the�user's�IOCB�to�show�new�bdrte**‰CHECK�ATTRIBUTE�MASK�-�MODEM*"IPCR234B‚BTSTW„#IOAMODM,IOSATM(A0)ŠBEQ.S„IPCR235�USE�DEFAULT*!*‰SETUP�MODEM�FROM�ATTRIBUTE�WORD*!ŠBTSTW„#IOAMODM,IOSATW(A0)‚MODEM?ŠBEQ.S„IPCR237ŽBRANCH�IF�NOŠBRA.S„IPCR236ŽYES*-*‰SETUP�MODEM�FROM�CURRENT�CONFIGURATION�AREA* IPCR235ƒEQU†*"ŠBTSTW„#IOAMODM,IOSATW(A5)‚MODEM�?ŠBEQ.S„IPCR237ŽBRANCH�IF�NO**‰SET�THE�MODEM�OPTION�BIT* IPCR236ƒEQU†**ŠBSET…#XHWMDM,D0‹YES,�SET�MODEM�OPTION�BIT*(*‰PUT�BYTE�2�H/W�CONFIG�IN�SHARED�MEMORY* IPCR237ƒEQU†*ŠMOVE.BƒD0,IPCHWC2(A1)*'*ˆCheck�the�parameters�mask�-�Null�Pads*3‰BTSTW…#IOSNLSB,IOSPRM(A0)‹Configure�the�null�pads?*‰BEQ.S…IPCR237A–No,�use�the�current�config:ŠMOVE.BƒIOSNLS(A0),IPCHWC3(A1)ˆYes,�move�user's�value�into *°shared�ram.‰BRA.S…IPCR237B*CIPCR237A‚MOVE.BƒIOSNLS(A5),IPCHWC3(A1)ˆUse�the�current�config�value+ .ŠMOVE.BƒIOSNLS(A5),IOSNLS(A0)‰Update�user�IOCB*#*ˆCheck�the�record�length�parameter*?IPCR237B�BTSTW…#IOSRECB,IOSPRM(A0)‹Configure�the�record�length?‰BEQ.S…IPCR237C>ŠMOVE.BƒIOSREC+1(A0),IPCHWC4(A1)‚PUT�LINE�LENGTH�IN�SHARED�MEM‰BRA.S…IPCR237D(IPCR237C�MOVE.B„IOSREC+1(A5),IPCHWC4(A1)!‰MOVE.B„IOSREC+1(A5),IOSREC+1(A0)IPCR237D‚CLR.L„D02ŠMOVEP.L‚D0,IPCSWC1(A1)‡SET�UP�S/W�CONFIGURE�BYTES*ŠOR.B…#$80,D0ŽSET�THE�CONFIGURE�OPTION�BIT*$*‰CHECK�ATTRIBUTE�MASK�-�HALF�DUPLEX*ŠBTSTW„#IOAECHO,IOSATM(A0)ŠBEQ.S„IPCR238�USE�DEFAULT*'*‰SETUP�HALF�DUPLEX�FROM�ATTRIBUTE�WORD*'ŠBTSTW„#IOAECHO,IOSATW(A0)‚HALF�DUPLEX?ŠBEQ.S„IPCR240ŽBRANCH�IF�NOŠBRA.S„IPCR239ŽYES*3*‰SETUP�HALF�DUPLEX�FROM�CURRENT�CONFIGURATION�AREA* IPCR238ƒEQU†*(ŠBTSTW„#IOAECHO,IOSATW(A5)‚HALF�DUPLEX�?ŠBEQ.S„IPCR240ŽBRANCH�IF�NO* *‰SET�THE�HALF�DUPLEX�OPTION�BIT* IPCR239ƒEQU†*1ŠBSET…#XSWHDX,D0‹YES�-�SET�HALF�DUPLEX�OPTION�BITN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<*%*‰CHECK�ATTRIBUTE�MASK�-�ACCEPT�NULLS* IPCR240ƒEQU†*ŠBTSTW„#IOAPNUL,IOSATM(A0)ŠBEQ.S„IPCR241�USE�DEFAULT*(*‰SETUP�ACCEPT�NULLS�FROM�ATTRIBUTE�WORD*)ŠBTSTW„#IOAPNUL,IOSATW(A0)‚ACCEPT�NULLS�?ŠBEQ.S„IPCR243ŽBRANCH�IF�NOŠBRA.S„IPCR242ŽYES*4*‰SETUP�ACCEPT�NULLS�FROM�CURRENT�CONFIGURATION�AREA* IPCR241ƒEQU†*)ŠBTSTW„#IOAPNUL,IOSATW(A5)‚ACCEPT�NULLS�?ŠBEQ.S„IPCR243ŽBRANCH�IF�NO*!*‰SET�THE�ACCEPT�NULLS�OPTION�BIT* IPCR242ƒEQU†*%ŠBSET…#XSWNUL,D0ŠYES�-�SET�OPTION�BIT***‰CHECK�ATTRIBUTE�MASK�-�ACCEPT�TYPE�AHEAD* IPCR243ƒEQU†*ŠBTSTW„#IOATAHD,IOSATM(A0)ŠBEQ.S„IPCR244�USE�DEFAULT*-*‰SETUP�ACCEPT�TYPE�AHEAD�FROM�ATTRIBUTE�WORD*,ŠBTSTW„#IOATAHD,IOSATW(A0)‚ACCEPT�TYPE�AHEAD+ŠBEQ.S„IPCR246ŽBRANCH�IF�TYPE�AHEAD�ALLOWED#ŠBRA.S„IPCR245ŽTYPE�AHEAD�INHIBITED*9*‰SETUP�ACCEPT�TYPE�AHEAD�FROM�CURRENT�CONFIGURATION�AREA* IPCR244ƒEQU†*.ŠBTSTW„#IOATAHD,IOSATW(A5)‚ACCEPT�TYPE�AHEAD�?+ŠBEQ.S„IPCR246ŽBRANCH�IF�TYPE�AHEAD�ALLOWED*0*‰SET�THE�ACCEPT�TYPE�AHEAD�INHIBITED�OPTION�BIT* IPCR245ƒEQU†*/ŠBSET…#XSWTAHD,D0‰NO�-�SET�TYPE�AHEAD�INHIBITED*(*‰CHECK�ATTRIBUTE�MASK�-�XON/XOFF�OR�CTS* IPCR246ƒEQU†*ŠBTSTW„#IOAXCTL,IOSATM(A0)ŠBEQ.S„IPCR247�USE�DEFAULT*+*‰SETUP�XON/XOFF�OR�CTS�FROM�ATTRIBUTE�WORD*'ŠBTSTW„#IOAXCTL,IOSATW(A0)�USE�XON/XOFFŠBEQ.S„IPCR249ŽNO�-�USE�CTSŠBRA.S„IPCR248ŽYES*7*‰SETUP�XON/XOFF�OR�CTS�FROM�CURRENT�CONFIGURATION�AREA* IPCR247ƒEQU†*'ŠBTSTW„#IOAXCTL,IOSATW(A0)�USE�XON/XOFFŠBEQ.S„IPCR249�NO�-�USE�CTS**‰SET�THE�USE�XON/XOFF�OPTION* IPCR248ƒEQU†*ŠBSET…#XSWXON,D0 IPCR249ƒEQU†*ŠMOVE.Lƒ(A7)+,A5ŒRESTORE�A5 IPCR250ƒEQU†*2ŠMOVE.BƒD0,IPCSWC1(A1)†SET�UP�S/W�CONFIGURE�BYTE�1N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>*G*ˆ3/26/85‚PJD�-�THIS�CODE�WAS�ADDED�TO�UPDATE�THE�CURRENT�CONFIGURATIONA*ˆATTRIBUTE�WORD�WHEN�A�CONFIGURATION�OCCURS.‚ONLY�THE�ATTRIBUTESG*ˆSUPPORTED�BY�THE�OLD�MCCM�ARE�UPDATED�HERE,�SO�THEY'LL�STILL�BE�VALIDD*ˆEVEN�IF�THE�SECOND�CONFIGURATION�PACKET�(SUPPORTED�ONLY�BY�THE�NEWE*ˆVM30-1�FIRMWARE)�FAILS.‚THE�ATTRIBUTE�WORD�WILL�BE�UPDATED�WITH�ALLH*ˆOF�THE�USER'S�ATTRIBUTE�BITS�WHEN�THE�SECOND�PACKET�COMPLETES�SUCCESS-*ˆFULLY�LATER�ON.*9‰MOVE.W„#$007C,D0‹GET�MASK�OF�MAX�ATTRIBUTES�FOR�OLD�MCCM(‰AND.W…IOSATM(A0),D0‡GET�USER'S�NEW�MASK)‰MOVE.W„IOSATW(A0),D1‡GET�USER'S�NEW�WORD+‰AND.W…D0,D1�STRIP�OFF�ANY�UNUSED�WORD�BITS-‰NOT.L…D0’MAKE�INVERSE�OF�MASK�-�BITS�TO�SAVE<‰AND.W…IOSATW(A5),D0‡ZERO�OUT�BITS�TO�BE�UPDATED�WITH�USER'S%‰OR.W†D1,D0�OR�IN�THE�USER'S�NEW�BITS;‰MOVE.W„D0,IOSATW(A5)‡UPDATE�THE�CURRENT�CONFIGURATION�AREA*K****************************************************************************#ŠMOVE.Bƒ#ETX,IPCCETX(A1)„SET�UP�ETX.ŠMOVE.Bƒ#CNPKSZ,IPCPKSZ(A1)�SET�UP�PACKET�SIZE9ŠMOVE.Bƒ#1,DCBCCF(A4)‡SET�CONFIGURATION�COORDINATION�FLAG ŠBRA†NRMEXITŠPAGEM*******************************************************************************‰CHANGE�DEFAULT�CONFIGURATION*, 6*‰This�command�changes�the�DCB�configuration,�to�which4*‰IOS�will�restore�us�(via�a�CONFIGURE�command)�when/*‰FHS�closes�the�last�allocation�of�the�device.*(*‰Entry:�A2�=�address�of�CMR�param�block*�A3�=�address�of�user's�IOCB*�A4�=�address�of�DCB*�A5�=�address�of�my�CCB*�A6�=�address�of�user's�TCB*M******************************************************************************CHNGDEF:%ŠCMP.B‚#XTDIPC,CCBTYPE(A5)ƒDISK�IPC‚?2ŠBEQ„REQSTAT�If�so,�perform�a�configuration/status *§request.&ŠBSR„CNFGLEN�SET�UP�DATA�BUFFER�LENGTH0ŠMOVE.LƒIOSDBP(A3),D6‡SET�UP�DATA�BUFFER�ADDRESS ŠBSR†BUFADDR2ŠMOVE.LƒD6,CCBPTR(A5)‡SAVE�BUFFER�PHYSICAL�ADDRESS 7ŠLEA†DCBDEV(A4),A0„A0�<--�address�of�DCB�configuration. *G************************************************************************)* Printer/Terminal change default command** CCHGD020ƒMOVE.L�CCBPTR(A5),A1†A1�<--�physical�address�of�data�block.ŠSPC„23ŠMOVE.B�#CECUAP,D2‹If�any�unsupported�attributes�or3ŠBSR„VALATPRM‹parameters�are�specified�in�the�users1ŠNOT.W‚D0‘attributes�or�parameters�mask,�return�a)ŠAND.W‚IOSATM(A1),D0†configuration�error. ŠNOT.W‚D1ŠAND.W‚IOSPRM(A1),D1 ŠOR.WƒD0,D1 ŠBNE„BADCNFGŠSPC„2*F*‚First�we�need�to�see�what�his�proposed�configuration�will�look�like.D*‚Plug�into�his�data�block�the�current�values�for�those�attributes�&?*‚parameters�he�doesn't�want�to�change.‚The�appropriate�current(*‚configuration�is�at�A0�and�he's�at�A1.*4ŠMOVE.W�IOSATM(A1),D0†Pick�up�users�attributes�mask.;ŠAND.W‚D0,IOSATW(A1)†Zero�out�the�attributes�of�his�that�he.ŠNOT.W‚D0‘doesn't�want�to�change,�zero�out�the<ŠAND.W‚IOSATW(A0),D0†attributes�of�mine�that�he�does�want�to:ŠOR.WƒD0,IOSATW(A1)†change,�and�combine�them�in�his�space. @ŠMOVE.W�IOSPRM(A1),D0†Get�mask�of�parameters�he�wants�to�change. 1ŠLSR.W‚#1,D0ŽIf�he's�not�changing�the�LINE�WIDTH,ŠBCS.S‚CHGD022Œgive�him�ours.ŠMOVE.W�IOSREC(A0),IOSREC(A1) 8CHGD022ƒLSR.W‚#1,D0ŽIf�he's�not�changing�the�LINES/PAGE,ŠBCS.S‚CHGD024Œgive�him�ours.ŠMOVE.L�IOSRSZ(A0),IOSRSZ(A1) :CHGD024ƒLSR.W‚#1,D0ŽIf�he's�not�changing�the�WRITE�TIMEOUT$ŠBCS.S‚CHGD026Œvalue,�give�him�ours.ŠMOVE.L�IOSWTO(A0),IOSWTO(A1) 9CHGD026ƒLSR.W‚#1,D0ŽIf�he's�not�changing�the�READ�TIMEOUT$ŠBCS.S‚CHGD028Œvalue,�give�him�ours.ŠMOVE.L�IOSRTO(A0),IOSRTO(A1) O*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83F*CHGD028ƒBTSTW‚#DATPRT,DCBATT(A4)ƒIf�the�device�is�a�terminal,�processCCHGD028„BTSTM‚DATPRT,DCBATT,A4‚If�the�device�is�a�terminal,�process *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<2ŠBEQ.S‚CHGD031Œthe�terminal�specific�configuration *£parameters.ŠSPC„24ŠLSR.W‚#1,D0�If�the�user�is�not�changing�the�Logical7ŠBCS.S‚CHGD029ŽRecord�length,�copy�the�current�default.ŠMOVE.W�IOSLRL(A0),IOSLRL(A1) 7CHGD029ƒLSR.W‚#1,D0�If�the�user�is�not�changing�the�EOL3ŠBCS.S‚CHGD030ŒCHARACTER,�copy�the�current�default.ŠMOVE.B�IOSELC(A0),IOSELC(A1)CHGD030ƒBRA.S‚OKCNFGŠSPC„2I*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>FAM 11/07/846CHGD031ƒLSR.W‚#1,D0Žif�he's�changing�the�XOFF/XON�charŠBCS.S‚CHGD031A‹give�him�oursŠMOVE.B�IOSXOF(A0),IOSXOF(A1)ŠMOVE.B�IOSXON(A0),IOSXON(A1)?CHGD031A‚LSR.W‚#1,D0Žif�he's�changing�the�BREAK�EQUIVALENT�charŠBCS.S‚CHGD031B‹give�him�oursŠMOVE.B�IOSBRC(A0),IOSBRC(A1)=CHGD031B‚LSR.W‚#1,D0Žif�he's�changing�the�DISCARD�OUTPUT�charŠBCS.S‚CHGD031C‹give�him�oursŠMOVE.B�IOSDOP(A0),IOSDOP(A1)*;CHGD031C‚LSR.W‚#1,D0Žif�he's�changing�the�REPRINT�LINE�charŠBCS.S‚CHGD031D‹give�him�oursŠMOVE.B�IOSRLN(A0),IOSRLN(A1)*:CHGD031D‚LSR.W‚#1,D0Žif�he's�changing�the�CANCEL�LINE�charŠBCS.S‚CHGD031E‹give�him�oursŠMOVE.B�IOSCLC(A0),IOSCLC(A1)*:CHGD031E‚LSR.W‚#1,D0Žif�he's�changing�the�READ�TERMINATORSŠBCS.S‚CHGD031F‹give�him�oursŠMOVE.L�IOSRTV(A0),IOSRTV(A1)*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>FAM 11/07/84*7CHGD032ƒLSR.W‚#1,D0ŽIf�he's�not�changing�the�BAUD�RATE,ŠBCS.S‚CHGD034Œgive�him�ours.ŠMOVE.B�IOSBRT(A0),IOSBRT(A1) 9CHGD034ƒLSR.W‚#1,D0ŽIf�he's�not�changing�the�NUL�PADDING,ŠBCS.S‚CHGD036Œgive�him�ours.ŠMOVE.B�IOSNLS(A0),IOSNLS(A1) 7CHGD036ƒLSR.W‚#2,D0Žthe�TERMINATOR-CLASS�doesn't�apply.6ŠBCS.S‚OKCNFG�If�the�user�is�not�changing�the�TERMINAL<ŠMOVE.B�IOSTCD(A0),IOSTCD(A1)�CODE,�copy�the�current�default )*£Currently�there�are�no�error�checks�for)*§MCCM�serial�parallel�ports,�so�go�ahead"*§with�the�proposed�configuration. *OKCNFG:*J*‚It�passed�all�the�tests,�so�move�it�to�the�real�thing�(either�the�DCB�orH*‚or�the�CCB).‚Don't�move�the�masks,�though;�start�with�ATTRIBUTES�WORD.*ŠSPC„2BŠMOVE.L�IOSDST(A0),IOSDST(A1)‚Copy�the�device,�driver,�and�channel3ŠCLR.B‚IOSDST(A1)‹codes�from�the�DCB�into�the�users'*¥configuration�block.�Clear�the�status(*¥field�for�lack�of�current�information.ŠSPC„22ŠBSR.S‚CNFGLEN�Load�D5�with�the�number�of�bytes�to<ŠSUB.W‚#IOSATW+1,D5ˆtransfer-1�and�load�the�addresses�of�the8ŠADD.L‚#IOSATW,A0ŠATTRIBUTES�WORD�in�A0�for�the�CCB/DCB,:ŠADD.L‚#IOSATW,A1Šand�in�A1�for�the�users�configure�block.ŠSPC„2FCNFGLOOP‚MOVE.B�(A1)+,(A0)+‰Copy�the�users�coniguration�block�into�theŠDBRAƒD5,CNFGLOOPˆCCB/DCB. :ŠMOVE.B�#1,DCBCCF(A4)†Set�configuration�coordination�flag. ŠCLR.L‚D1‘*1ŠBRA„ABORT�good�status�but�use�the�ABORT�routine. *0*‚Configuration�error!‚Set�D1�to�indicate�error.*BADCNFG: :ŠMOVE.B‚#ISTACNF,D1‰Return�the�configuration�error�code�in?ŠMOVE.B�D2,IOSCEC(A1)†the�users�configure�data�block�and�return(ŠBRA…ABORTŒa�configuration�error�to�IOS.ŠPAGEL*****************************************************************************%*‰GET�CONFIGURATION�DATA�BLOCK�LENGTH**‚Entry�:�A4�=�Address�of�DCB*ŠA5�=�Address�of�CCB*B*‚Exit�:‚D5�=�Configuration�data�block�length�for�requested�device*L**************************************************************************** CNFGLEN:8ŠMOVE.L�#IOSDLN,D5ŒLoad�D5.L�with�the�configuration�dataAŠCMP.B‚#XTDIPC,CCBTYPE(A5)�block�length�for�the�disk,�printer,�or2ŠBEQ.S‚CNFGLENRŒterminal�based�on�the�device�type.ŠSPC„2ŠMOVE.L�#IOSPLN,D5O*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83*‰BTSTW‚#DATPRT,DCBATT(A4)ŠBTSTM‚DATPRT,DCBATT,A4 *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ŠBNE.S‚CNFGLENRŠSPC„2ŠMOVE.L�#IOSTLN,D5ŠSPC„2 CNFGLENR‚RTSŠPAGEL*****************************************************************************2*‰GET�MASKS�OF�SUPPORTED�ATTRIBUTES�AND�PARAMETERS**†Entry�:�A4�=�Address�of�DCB*ŽA5�=�Address�of�CCB*>*†Exit‚:�D0.W�=�Supported�attributes�mask�for�requested�device7*ŽD1.W�=�Supported�parameters�mask�for�requested�device*L**************************************************************************** VALATPRM:.ŠMOVE.W�#0,D0‘If�the�device�is�a�disk�IPC,�the7ŠMOVE.W�#0,D1�supported�attributes�and�parameters�masksAŠCMP.B‚#XTDIPC,CCBTYPE(A5)�are�both�zero�because�configuration�is,ŠBEQ.S‚VALATRTNŒnot�supported�on�the�device.ŠSPC„2<ŠMOVE.W�#PRTATM,D0‹If�the�device�is�a�printer�or�a�terminal,<ŠMOVE.W�#PRTPRM,D1‰load�the�appropriate�supported�attributesO*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83?*‰BTSTW‚#DATPRT,DCBATT(A4)�and�parameters�masks�for�the�device.<ŠBTSTM‚DATPRT,DCBATT,A4�and�parameters�masks�for�the�device. *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ŠBNE.S‚VALATRTNŠSPC„2ŠMOVE.W�#TERATM,D0ŠMOVE.W�#TERPRM,D1ŠSPC„2 VALATRTN‚RTSŠPAGEL******************************************************************************‰READ�COMMAND*,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB- *‰A6�=�address�of�users�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory*L*****************************************************************************READ:5ŠBSR„IOSCOMNŒDo�the�stuff�common�to�all�I/O�commands,7ŠMOVE.L�D6,CCBPTR(A5)†save�the�buffer�physical�address. ŠCLR.L‚D6&ŠBSETƒ#LUFXFR,D6ŒSET�DATA�TRANSFER�BITŠBSETƒ#LUFACT,D6ŒSET�ACTIVE�BIT%ŠCMP.B‚#XTDIPC,CCBTYPE(A5)ƒDISK�IPC�?ŠBNE.S‚READ10�BRANCH�IF�NO$ŠBSR„DSKPRM�YES,�VALIDATE�PARAMETERS+READ10„BSR„DEVTBL�SET�UP�DEVICE�TABLE�ENTRY /ŠBSR„SETPKT�SET�UP�PACKET�HEADER�IN�SHARED�MEM. %ŠCMP.B„#XTDIPC,CCBTYPE(A5)�DISK�IPC�?ŠBNE.S„READ20ŽBRANCH�IF�NO ŠMOVE.Wƒ#XREAD,D1&ŠBSR†DSKCMDŽYES,�SET�UP�COMMAND�PACKETŠBRA†NRMEXIT�GO�FINISH�UP 1READ20„BTSTW„#IOPFORB,IOSOPT(A3)�FORMATTED�MODE�?ŠBNE.S„READ30ŽNO4ŠMOVE.Wƒ#XINF,D1ŒYES,�SET�UP�READ�FORMATTED�COMMANDS ŠBRA.S„READ401READ30„MOVE.Wƒ#XINI,D1ŒSET�UP�READ�IMAGE�COMMANDSREAD40„CLR.L„D0+ŠBTSTW„#IOPECHB,IOSOPT(A3)�ECHO�SPECIFIED�?ŠBEQ.S„READ50ŽYES+ŠOR.L…#XPKCECH,D0‰NO,�SET�UP�NO�ECHO�OPTIONN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<< READ50„EQU†*2ŠBTSTW„#IOPCTAB,IOSOPT(A3)�FLUSH�TYPE�AHEAD�BUFFERŠBEQ.S„READ60ŽNO0ŠOR.L…#XPKCTAB,D0‰NO,�SET�UP�FLUSH�BUFFER�OPTION READ60„EQU†* *ºFAM�7/04/84N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>*6‰MOVEM.LƒD0/A5,-(A7)‰Save�the�CCB�address�on�the�stack:‰MOVE.L„CCBDTBL(A5),A5†Get�the�start�address�of�the�device*¦tables‰CLR.L…D0’Need�the�whole�reg!4‰MOVE.B„DCBCDV(A4),D0‡Get�the�device�number�from�DCB6‰MULU†#LUDSZE,D0ŠMUL�size�of�an�entry�by�device�number&*¦to�get�distance�from�start�of�table./‰ADD.L…D0,A5�Add�to�base�to�get�start�of�device*¦table�for�this�device.‰MOVEM.Lƒ(A7)+,D0ŒRestore�D04‰LEA‡CONFIG(A5),A5‡Use�offset�from�base�of�CONFIG�so!*¦we�can�use�the�IOE�equates�into*¦the�configuration�data.2‰BTSTW…#IOAPNUL,IOSATW(A5)�SHOULD�WE�ACCEPT�NULLS?‰BEQ.S…READ61ŽNO2‰OR.L†#XPKCNUL,D0‰YES,�ADD�THE�BIT�TO�ACCEPT�NULLS*8READ61ƒBTSTW…#IOAXCTL,IOSATW(A5)�SHOULD�WE�USE�XON/XOFF?‰BEQ.S…READ62ŽNO2‰OR.L†#XPKCXFN,D0‰YES,�ADD�THE�BIT�TO�USE�XON/XOFF*9READ62ƒBTSTW…#IOATAHD,IOSATW(A5)�SHOULD�WE�USE�TYPEAHEAD?‰BEQ.S…READ70ŽNO3‰OR.L†#XPKNTPA,D0‰YES,�ADD�THE�BIT�TO�USE�TYPEAHEAD*/READ70ƒMOVEM.Lƒ(A7)+,A5ŒRESTORE�THE�CCB�ADDRESS"ŠBSR†MCCMCMD�SET�UP�COMMAND�PACKETŠBRA†NRMEXIT�GO�FINISH�UPŠPAGEL******************************************************************************‰WRITE**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory**L*****************************************************************************WRITE:5ŠBSR„IOSCOMNŒDo�the�stuff�common�to�all�I/O�commands,7ŠMOVE.L�D6,CCBPTR(A5)†save�the�buffer�physical�address. ŠCLR.L‚D6&ŠBSETƒ#LUFXFR,D6ŒSET�DATA�TRANSFER�BITŠBSETƒ#LUFACT,D6ŒSET�ACTIVE�BIT%ŠCMP.B‚#XTDIPC,CCBTYPE(A5)ƒDISK�IPC�?ŠBNE.S‚WRIT10�BRANCH�IF�NO$ŠBSR„DSKPRM�YES,�VALIDATE�PARAMETERS+WRIT10„BSR„DEVTBL�SET�UP�DEVICE�TABLE�ENTRY /ŠBSR„SETPKT�SET�UP�PACKET�HEADER�IN�SHARED�MEM. %ŠCMP.B„#XTDIPC,CCBTYPE(A5)�DISK�IPC�?ŠBNE.S„WRIT50ŽBRANCH�IF�NO O*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83A*WRIT20„BTSTW„#DATWRC,DCBATT(A0)‚WRITE�WITH�VERIFY�FOR�THIS�DCB�?>WRIT20…BTSTM„DATWRC,DCBATT,A0‚WRITE�WITH�VERIFY�FOR�THIS�DCB�? *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ŠBEQ.S„WRIT30ŽNO4ŠMOVE.Wƒ#XWRITC,D1ŠYES,�SET�UP�WRITE/VERIFY�COMMANDS ŠBRA.S„WRIT408WRIT30„MOVE.Wƒ#XWRITN,D1ŠSET�UP�WRITE/NO�VERIFY�COMMANDS 'WRIT40„BSR†DSKCMDŽSET�UP�COMMAND�PACKETŠBRA†NRMEXIT�GO�FINISH�UP 1WRIT50„BTSTW„#IOPFORB,IOSOPT(A3)�FORMATTED�MODE�?ŠBNE.S„WRIT60ŽNO6ŠMOVE.Wƒ#XOUTF,D1‹YES,�SET�UP�WRITE�FORMATTED�COMMANDS ŠBRA.S„WRIT70- 3WRIT60„MOVE.Wƒ#XOUTI,D1‹SET�UP�WRITE�IMAGE�COMMANDSWRIT70„CLR.L„D0O*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/832*‰BTSTW„#DATPRT,DCBATT(A0)‚THIS�A�PRINTER�DEVICE�?/ŠBTSTM„DATPRT,DCBATT,A0‚THIS�A�PRINTER�DEVICE�? *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ŠBEQ.S„WRIT80ŽNO3ŠTST.B„DCBBCT(A0)ŠFIRST�WRITE�FOR�THIS�ASSIGNMENT�?$ŠBNE.S„WRIT80ŽNO,�NO�NEED�TO�DO�A�FF.ŠOR.L…#XSWFF,D0‹YES,�SET�UP�TOP�OF�PAGE�OPTION-ŠADD.B„#1,DCBBCT(A0)‡NOW�SET�TOP�OF�PAGE�FLAG)WRIT80„BSR†MCCMCMD�SET�UP�COMMMAND�PACKETŠBRA†NRMEXIT�GO�FINISH�UPŠPAGEL*****************************************************************************%*‰OUTPUT�W/�INPUT‚(MCCM�COMMAND�ONLY)**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory**L*****************************************************************************OUTWINP:*'*‚First�take�care�of�the�WRITE�portion.*5ŠBSR„IOSCOMNŒDo�the�stuff�common�to�all�I/O�commands,8ŠMOVE.L�D6,CCBPTR(A5)†store�the�buffer�physical�address.*$*‚Now�take�care�of�the�READ�portion.*?ŠMOVE.L�IOSRRN(A3),D6†D6�<--�logical�start�addr�of�read�buffer.<ŠMOVE.L�IOSLEN(A3),D5†D5�<--�length�of�read�buffer�in�bytes./ŠMOVE.L�D5,CCBLEN1(A5)…Save�the�buffer�length�&&ŠBSR„BUFADDRŒget�the�physical�address,8ŠMOVE.L�D6,CCBPTR1(A5)…save�the�buffer�physical�address. ŠCLR.L‚D6&ŠBSETƒ#LUFXFR,D6ŒSET�DATA�TRANSFER�BITŠBSETƒ#LUFACT,D6ŒSET�ACTIVE�BIT%ŠBSR„DEVTBL�SET�UP�DEVICE�TABLE�ENTRY /ŠBSR„SETPKT�SET�UP�PACKET�HEADER�IN�SHARED�MEM. 3OUTW10„BTSTW„#IOPFORB,IOSOPT(A3)‚OUTPUT�FORMATTED�?ŠBNE.S„OUTW30ŽNO,ŠBTSTW„#IOPINFB,IOSOPT(A3)�INPUT�FORMATTED�?ŠBNE.S„OUTW20ŽNO8ŠMOVE.Wƒ#XOFIF,D1‹SET�UP�OUTPUT�FRMT/INPUT�FRMT�COMMANDS ŠBRA.S„OUTW50?OUTW20„MOVE.Wƒ#XOFIM,D1‹SET�UP�OUTPUT�FRMT/INPUT�IMAGE�COMMANDS ŠBRA.S„OUTW502OUTW30„BTSTW„#IOPINFB,IOSOPT(A3)‚INPUT�FORMATTED�?ŠBNE.S„OUTW40ŽNO5ŠMOVE.Wƒ#XOIIF,D1‹SET�UP�OUTPUT�IMAGE/INPUT�FRMT�CMDS ŠBRA.S„OUTW50>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<< OUTW60„EQU†*4ŠBTSTW„#IOPCTAB,IOSOPT(A3)�FLUSH�TYPE�AHEAD�BUFFER�?ŠBEQ.S„OUTW61ŽNO,ŠOR.L…#XPKCTAB,D0‰SET�UP�FLUSH�BUFFER�OPTIONN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>*‚THEN.S'ŒKILL.DRIVER�IPCDRV_ID,BAD_DEVICE,A5,A4ŠENDI,ŠMULU…#LUDSZE,D0ŠCALCULATE�POSITION�IN�TABLE2ŠMOVE.LƒCCBDTBL(A5),A1†SET�UP�DEVICE�TABLE�POINTERŠINHIBŠTST.W„LUFLG(A1,D0.L)ˆACTIVE�?ŠBEQ†HALTERŽNO,�ERROR3ŠBSETW„#LUFHLT,LUFLG(A1,D0.L)�SET�HALT�PENDING�FLAG3ŠMOVE.LƒA3,LUMISC(A1,D0.L)‚SAVE�HALT�PACKET�POINTERŠENABL /ŠBSR†SETPKTŽSET�UP�PACKET�HEADER�IN�SHARED�MEM. ŠMOVE.Wƒ#XHALT,D16ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDS#ŠMOVE.Bƒ#ETX,IPCRETX(A1)„SET�UP�ETX/ŠMOVE.Bƒ#HLTPKSZ,IPCPKSZ(A1)†SET�UP�PACKET�SIZE ŠBRA†NRMEXITŠPAGEH**************************************************************************‰TRANSMIT�BREAK�REQUEST*<*‰This�command�sends�the�break�request�to�the�LUN�specified.**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**J***************************************************************************TBREAK: ŠCLR.L„D6-ŠBSET…#LUFACT,D6ŒSET�ACTIVE�DEVICE�TABLE�FLAG%ŠBSR†DEVTBL�SET�UP�DEVICE�TABLE�ENTRY*,ŠBSR†SETPKT�SET�UP�PACKET�HDR�IN�SHARED�MEM.ŠMOVE.Wƒ#XTRNSBK,D16ŠMOVEP.W‚D1,IPCCHCM(A1)ˆSET�UP�CHANNEL/DEVICE�COMMANDS#ŠMOVE.Bƒ#ETX,IPCRETX(A1)†SET�UP�ETX/ŠMOVE.Bƒ#TBKPKSZ,IPCPKSZ(A1)‚SET�UP�PACKET�SIZE ŠBRA†NRMEXITŠPAGEL*****************************************************************************C*‰ROUTINE�COMMON�TO�ALL�I/O�COMMANDS�(READ,�WRITE,�OUTPUT�W/�INPUT)**‚Entry:�A3�=�address�of�IOCB*‰A5�=�address�of�CCB**‚Exit:‚(normal)*‰D6�=�physical�addr�of�buffer**‚Exit:‚(abort). *‰D1�=�error�status**L*****************************************************************************IOSCOMN:?ŠBTSTW‚#IOPTSKB,IOSOPT(A3)�If�the�buffers�reside�in�a�different"ŠBEQ.S‚IOSC005Œtask�from�the�IOCB, 9ŠLEA„IOSTSK(A3),A0†Point�to�the�taskname�&�session�of�the7ŠTR0$.GETTCB‚,Œbuffer�owner�&�call�exec�to�get�address."ŠBRA.S‚OKTCBŽIf�it's�good,�branch.ŠNOP—If�it's�bad,7ŠMOVE.B�#ISTAADD,D1ˆset�status�in�IOCB�to�address�errorŠTST.L‚(A7)+Žadjust�stackŠBRA„ABORT�and�exit�to�CMR. :OKTCB…MOVE.L�A0,CCBTASKB(A5)„Save�physical�address�of�TCB. *<*‚Validate�the�info�in�the�IOCB�about�the�primary�buffer�and *‚convert�to�physical�addresses.*BIOSC005ƒMOVE.L�IOSSAD(A3),D6†D6�<--�buffer�physical�start�address.+ŠMOVE.L�IOSEAD(A3),D5†D5�<--�buffer�length.ŠSUB.L‚D6,D5Ž*ŠADDQ.L�#1,D5Ž*)ŠMOVE.L�D5,CCBLEN(A5)†Save�length�in�CCB. >ŠMOVE.L�CCBTASKB(A5),A1„A1�<--�address�of�TCB�of�buffer�owner. ŠBSR„IOHADRCK‹Check�the�address.$ŠBRA.S‚IOSC010ŒIf�it's�good,�branch.ŠNOP—If�it's�a�bad�base�addrŠTST.L‚(A7)+Žadjust�stack4ŠMOVE.B�#ISTAADD,D1ˆSet�IOCB�status�to�ADDRESS�ERROR2ŠBRA„ABORT�and�exit�with�appropriate�error�status. IOSC010ƒEQU„*N*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<< ŠGO_OFF_BD�D6N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>ŠRTSŠPAGEK****************************************************************************/*‰VALIDATE�BUFFER�ADDRESS�&�CONVERT�TO�PHYSICAL*$*‰Entry:�D5�=�buffer�length�in�bytes-*�D6�=�buffer�logical�start�addr�(to�convert)*�A3�=�address�of�IOCB*�A5�=�address�of�CCB***‰Exit:‚D6ƒ=�buffer�physical�start�address*�D5ƒ=�buffer�length*K****************************************************************************BUFADDR:>ŠMOVE.L�CCBTASKB(A5),A1„A1�<--�address�of�TCB�of�buffer�owner. ŠBSR„IOHADRCK‹Check�the�address.$ŠBRA.S‚OKADDR2ŒIf�it's�good,�branch.ŠNOP—If�it's�a�bad�base�addrŠTST.L‚(A7)+Žadjust�stack4ŠMOVE.B�#ISTAADD,D1ˆSet�IOCB�status�to�ADDRESS�ERROR2ŠBRA„ABORT�and�exit�with�appropriate�error�status.OKADDR2ƒEQU„*’Return.*N*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<< ŠGO_OFF_BD‚D6N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>ŠRTSŠPAGEO*********************************************************************************ˆCHECK�DISK�PARAMETERS**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**O********************************************************************************DSKPRM:%‰MOVE.W‚IOSOPT(A3),D1‰PICK�UP�OPTIONS+‰AND.Wƒ#IOPRAN,D1ŒRANDOM�OPTION�SPECIFIED�?‰BNE.SƒDSKPR10�YES(‰MOVE.B‚#ISTATM,D1ŒSET�UP�IOS�ERROR�CODE‰BRA.SƒDSKPR25�ERROR�EXIT(DSKPR10‚MOVE.L‚IOSRRN(A3),D1‰PICK�UP�RRN‰BPL.SƒDSKPR30�GOOD�RRN/DSKPR20‚MOVE.B‚#ISTARR,D1ŒSET�UP�IOS�ERROR�CODE DSKPR25‚TST.Lƒ(A7)+‘ADJUST�STACK‰BRA…ABORT�ERROR�EXITŠSPC„2ADSKPR30ƒCMP.LƒDCBSEC(A4),D1‡If�the�random�record�number�specified7ŠBLT.SƒDSKPR35‹in�the�IOCB�is�past�the�end�of�the�disk,1ŠMOVE.B�#ISTARR,D1‰return�an�end-of-volume�error.ŠBRA.S‚DSKPR25ŠSPC„22DSKPR35‚MOVE.L‚CCBLEN(A5),D1‰PICK�UP�BUFFER�LENGTH"‰DIVS„#256,D1�CALC.�NO.�OF�SECTORS ‰MOVE.L‚D1,D2*‰AND.Lƒ#$FFFF0000,D2‰MUST�BE�WHOLE�SECTORS‰BEQ.SƒDSKPR40�ITS�OK5‰MOVE.B‚#ISTAADD,D1‹ERROR,�PARTIAL�SECTOR�NOT�ALLOWED‰BRA…DSKPR25�ERROR�EXIT1DSKPR40‚MOVE.W‚D1,CCBBLKS(A5)ˆSAVE�NO.�OF�SECTORS2‰ADD.LƒIOSRRN(A3),D1‰CALC.�LAST�SECTOR�TO�TRANSFER‰CMP.LƒDCBSEC(A4),D1‰RANGE�OK�?‰BLE.SƒDSKPR50�YES4‰MOVE.L‚DCBSEC(A4),D1‰NO,�CALC.�MAX�SECTORS�CAN�READ‰SUB.LƒIOSRRN(A3),D1/‰MOVE.W‚D1,CCBBLKS(A5)ˆSAVE�SECTORS�TO�TRANSFER ‰BSET„#LUFEOF,D6ŒSET�EOF�PENDINGDSKPR50‚RTS›RETURN‰PAGEO********************************************************************************** SET UP DEVICE TABLE ENTRY**,*‚Entry:�A2�=�address�of�CMR�parameter�block/ çÐ@ÙFáIéBñNù;8 P5@!H)61=9:A;I=Q6YEaXi?q;yD�>‰G‘F*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‰D6�=�device�table�flag*N*******************************************************************************DEVTBL: ŠCLR.L‚D0(ŠMOVE.B�DCBCDV(A4),D0‰PICK�UP�DEVICE�NO. ŠCMP.B‚#LUMAX,D0�DEVICE�NO.�OK�?ŠIF‚‚THEN.S'ŒKILL.DRIVER�IPCDRV_ID,BAD_DEVICE,A5,A4ŠENDIŠMULUƒ#LUDSZE,D0ŒCALC.�POSITION3ŠMOVE.L�CCBDTBL(A5),A0ˆPICK�UP�DEVICE�TABLE�POINTER(ŠTST.W‚LUFLG(A0,D0.L)ŠTHIS�DEVICE�FREE�?ŠBEQ.S‚DEVT010�YESŠTST.L‚(A7)+‘ADJUST�STACK+ŠMOVE.B�#ISTADB,D1ŒRETURN�DEVICE�BUSY�ERRORŠBRA„ABORT�ERROR�EXIT2DEVT010ƒMOVE.W�D6,LUFLG(A0,D0.L)‡UPDATE�TABLE�FLAG,ŠMOVE.L�A4,LUDCB(A0,D0.L)‡SET�UP�DCB�ADDRESS.ŠMOVE.L�A3,LUIOCB(A0,D0.L)†SET�UP�IOCB�ADDRESS6ŠMOVE.L�CCBTASKB(A5),LUTCB(A0,D0.L)�SET�UP�TCB�ADDRESS8ŠMOVE.L�CCBPTR(A5),LUBADR(A0,D0.L)�SET�UP�BUFFER�ADDRESS ŠRTSšRETURNŠPAGEJ***************************************************************************%*ˆSET�UP�PACKET�HEADER�IN�SHARED�MEM.**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*,*‰Return�:�A1�=�address�of�IPC�shared�memory**I**************************************************************************SETPKT:)ŠLEA†CCBSHR(A5),A1‡GET�COMMAND�BUILD�AREA)ŠLEA†IPCIM1(A1),A1‡SET�UP�MESSAGE�ADDRESSŠMOVE.Wƒ#SPKT,D1/ŠMOVEP.W‚D1,IPCSTX(A1)‡SET�UP�STX�AND�PACKET�ID%ŠMOVE.LƒXIOUID(A2),A0‡GET�DCB�ADDRESS0ŠMOVE.BƒDCBCDV(A0),IPCPHDV(A1)‚SET�UP�DEVICE�NO. ŠRTSšRETURNŠPAGEJ***************************************************************************)*‰SET�UP�DISK�PARAMETERS�IN�SHARED�MEMORY*&*‚Entry:�A1�=�address�of�SHARED�MEMORY%*‰A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‰D1�=�CHANNEL/DEVICE�commands*K****************************************************************************DSKCMD:6ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDSŠMOVE.WƒCCBBLKS(A5),D18ŠMOVEP.W‚D1,IPCNBKS(A1)†SET�UP�NO.�OF�BLOCKS�TO�TRANSFERŠMOVE.Wƒ#SECSIZ,D1)ŠMOVEP.W‚D1,IPCBKSZ(A1)†SET�UP�BLOCK�SIZEŠMOVE.LƒCCBPTR(A5),D1.ŠMOVEP.L‚D1,IPCBUFAD(A1)…SET�UP�BUFFER�ADDRESS ŠCLR.L„D1'ŠMOVEP.W‚D1,IPCCKSM(A1)†SET�UP�CHECKSUMŠMOVE.LƒIOSRRN(A3),D1#ŠMOVEP.L‚D1,IPCCMPRM(A1)…SET�UP�PSN"ŠMOVE.Bƒ#ETX,IPCETX(A1)…SET�UP�ETX.ŠMOVE.Bƒ#IOPKSZ,IPCPKSZ(A1)�SET�UP�PACKET�SIZE ŠRTSšRETURNŠPAGEJ***************************************************************************)*ˆSET�UP�MCCM�PARAMETERS�IN�SHARED�MEMORY**&*‚Entry:�A1�=�address�of�SHARED�MEMORY%*‰A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‰D0�=�options*‰D1�=�channel/device�commands**L*****************************************************************************MCCMCMD:6ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDS&ŠMOVEP.L‚D0,IPCSWCF(A1)†SET�UP�OPTIONS ŠMOVE.Lƒ#1,D18ŠMOVEP.W‚D1,IPCNBKS(A1)†SET�UP�NO.�OF�BLOCKS�TO�TRANSFERŠMOVE.LƒCCBLEN(A5),D1)ŠMOVEP.W‚D1,IPCBKSZ(A1)†SET�UP�BLOCK�SIZEŠMOVE.LƒCCBPTR(A5),D1.ŠMOVEP.L‚D1,IPCBUFAD(A1)…SET�UP�BUFFER�ADDRESS ŠCLR.L„D1'ŠMOVEP.W‚D1,IPCCKSM(A1)†SET�UP�CHECKSUM"ŠMOVE.Bƒ#ETX,IPCETX(A1)…SET�UP�ETX.ŠMOVE.Bƒ#IOPKSZ,IPCPKSZ(A1)�SET�UP�PACKET�SIZE ŠRTSšRETURNŠPAGEO******************************************************************************** *ˆNORMAL�EXIT*,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*I**************************************************************************NRMEXIT:/ ‰MOVE.L„CCBCHB(A5),A0‰TST.B…IPCIMB1(A0)‰BNE.S…NRMEXIT*/* INDICATE AWAITING ACK, BUMP I/O PENDING COUNT*ŠINHIB'ŠBSETW‚#CCBFGWAK,CCBFG(A5)ƒSET�CCB�FLAGŠMOVE.L�CCBTASKB(A5),A0-ŠADD.B‚#1,TCBIOCNT(A0)„BUMP�I/O�PENDING�COUNT** INTERRUPT THE IPC*4ŠLEA„CCBSHR(A5),A0‰GET�POINTER�TO�COMMAND�BUILD�AREA4ŠLEA„IPCIM1(A0),A0ˆADD�OFFSET�TO�NOT�USE�IPC�OFFSETS2ŠMOVE.L�#$D,D0�MOVE�$10*4�LONG�WORDS�(DBRA�ADDS�1)0ŠMOVE.L�CCBCHB(A5),A1†SET�UP�SHARED�MEM.�POINTER‰LEA‡IPCIM1(A1),A19MOVESHR‚MOVEP.L�0(A0),D1�GET�DATA�FROM�COMMAND�BUILD�AREA'‰MOVEP.L�D1,0(A1)�MOVE�IT�TO�SHARED�RAM‰LEA‡8(A0),A0ŒADD�TO�GET�NEXT‰LEA‡8(A1),A1ŒADD�TO�GET�NEXT#‰DBRA†D0,MOVESHRŠLOOP�TIL�ALL�MOVED;‰MOVE.L„CCBCHB(A5),A1‡GET�THE�SHARED�RAM�ADDRESS�BACK�AGAIN8‰BCLRW…#CCBBUSY,CCBFG(A5)‚FREE�UP�THE�COMMAND�BUILD�AREA(ŠMOVE.B�#$80,IPCIMB1(A1)ƒMESSAGE�WAITING0ŠADD.B‚#2,CCBICNT(A5)…BUMP�OUTSTANDING�INT�COUNT%ŠMOVE.B�#$80,IPCINT(A1)„INTERRUPT�IPC‰ENABL#ŠCLR.L‚D0‘SET�UP�GOOD�RETURN�TO�CMR*7* USER REQUEST SIDE OF IPC ALWAYS EXITS FROM THIS POINT*IPCUSRTN‚EQU„*ŠRTS—RETURN�TO�MAINLINEŠPAGEJ*****************************************************************************‚NOTHING�TO�HALT�ERROR�ROUTINE*%*’ENTRY:�A2�=�PARAMETER�BLOCK�ADDRESS*™A3�=�IOCB�PACKET�ADDRESS*™A4�=�ADDRESS�OF�DCB*™A5�=�ADDRESS�OF�CCB*™A6�=�ADDRESS�OF�CALLERS�TCB*H************************************************************************* HALTER:‚ENABL)‰LEA‡CCBPKT(A5),A4‡SET�UP�QUEUE�WORK�AREA ‰MOVE.L„#6,D0�SET�UP�PACKET�SIZE$‰MOVE.B„#XPSHLT,D1ŠSET�UP�EVENT�TYPE"‰MOVE.L„XIOUID(A2),D2‡SET�UP�PB�ID&‰MOVE.W„#ISTAIF,D3ŠSET�UP�STATUS�VALUE7‰MOVE.B„#ISTAIF,IOSSTA(A3)‚RETURN�STATUS�TO�USER'S�IOCB‰BSR‡QEVNT�GO�QUEUE�EVENT ‰CLR.L…D0‰BRA‡IPCUSRTNŒRETURN‰PAGEJ*****************************************************************************ˆABORT�COMMAND�ROUTINE*%*’ENTRY:�A2�=�PARAMETER�BLOCK�ADDRESS*™A3�=�IOCB�PACKET�ADDRESS*™A4�=�ADDRESS�OF�DCB*™A5�=�ADDRESS�OF�CCB*™A6�=�ADDRESS�OF�CALLERS�TCB*™D1�=�IOS�ERROR�CODE*H*************************************************************************ABORT:)‰LEA‡CCBPKT(A5),A4‡SET�UP�QUEUE�WORK�AREA ‰MOVE.L„#6,D0�SET�UP�PACKET�SIZE"‰MOVE.L„XIOUID(A2),D2‡SET�UP�PB�ID‰AND.W…#$FF,D1!‰MOVE.W„D1,D3�SET�UP�STATUS�VALUE!‰MOVE.B„D1,IOSSTA(A3)‡UPDATE�IOCB$‰MOVE.B„#XPSNRM,D1ŠSET�UP�EVENT�TYPE‰BSR‡QEVNT�GO�QUEUE�EVENT ‰CLR.L…D0‰BRA‡IPCUSRTNŒRETURNŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLING�TASKS�ADDRESS�SPACE.*#*�ENTRY:ƒD5‚-�NO.�OF�BYTES�TO�CHECK*ŠD6‚-�68000�ADDRESS�(LOGICAL)*ŠA1‚-�TCB�ADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1**7*�EXIT:„D6�-�PHYSICAL�ADDRESS�OF�BUFFER�BASE�(IF�LEGAL)*ŠRETURN�TO�PC„FOR�GOOD�ADDRESS*”PC+2‚FOR�BAD�LENGTH*”PC+4‚FOR�BAD�ADDRESS*F*********************************************************************** IOHADRCK:$ŠBTSTƒ#0,D6ŽMUST�BE�ON�WORD�BOUNDARY(ŠBNE.S‚IOHADR6ŒBRANCH�IF�BAD�BUFFER�BASE ŠTST.L‚D5.ŠBEQ.S‚IOHADR8ŒDON'T�GO�TO�LOGPHY�WITH�0�COUNT IOHADR2ƒEQU„*/ŠMOVE.L�TCBTST(A1),A0†ADDRESS�OF�TASK�SEG�TABLE ŠTR0$.LOGPHY&ŠBRA.S‚IOHADR8ŒBRANCH�FOR�GOOD�ADDRESSŠNOP—FOR�PART�IN/PART�OUT�ERROR-IOHADR6ƒADD.L‚#2,(A7)ŒADJUST�FOR�ERROR�RETURN IOHADR8ƒRTSŠPAGEI***************************************************************************ˆGET�TCB�ROUTINE*)*’ENTRY:�A0�=�POINTER�TO�TASK�AND�SESSION***’EXEC�ROUTINE*’REGISTERS�USED:�D0-D1/A0-A1***’EXIT:�A0�=�TCB�ADRESS**˜RETURN�TO�PC„FOR�GOOD�TASK�SPECIFICATION!*¢PC+2‚FOR�BAD�TASK�SPECIFICATION**J***************************************************************************GETTCB: ŠTR0$.GETTCB%ŠBRA.S„GETT10ŽGOOD�TASK�SPECIFICATION%ŠADD.L„#2,(A7)�BAD�TASK�SPECIFICATION GETT10„RTSŠPAGEJ**************************************************************************** * SUBROUTINE0  TO COMPUTE CHECKSUM*&*‡ENTRY:�A1�=�PHYS�ADDR�OF�BLOCK�BEGIN,*ŽD5�=�ONE�RELATIVE�COUNT�OF�NUMBER�OF�BYTES*C*‡EXIT:‚D1�=�CHECKSUM�(SUM�OF�BYTES�WITH�WORD(16�BIT)�SIGNIFICANCE)** REGISTERS D0,D5 DESTROYED*M****************************************************************************** *IPCCKSUM:"*ˆTR0$.KILLER‰GO�CRASH�THE�SYSTEM?*‰CLR.LƒD1‹ACCUMULATOR)*‰MOVE.L‚A1,D0ˆADDRESS�OF�BLOCK�BEGINNING'*‰BTSTW‚#24,D0ˆIS�IT�FOR�2NDARY�MEMORY?*‰BNE.SƒCKSUM2‡BRANCH�IF�YES+* CHECKSUM CALCULATION IF IN PRIMARY MEMORY*‰CLR.LƒD0‹BYTE�HOLDER*IPCCK30ƒEQU…*'*‰SUB.Lƒ#1,D5ˆBEGIN�WITH�ZERO�REL�INDEX*‰BLT.SƒIPCCK50†BRANCH�IF�DONE*‰MOVE.B‚0(A1,D5.L),D0 *‰NOT.BƒD0/*‰ADD.WƒD0,D1ˆCONTRIBUTE�THIS�BYTE�TO�CHECKSUUM*‰BRA…IPCCK30†GO�FOR�ANOTHER*IPCCK50ƒEQU„**‰RTS…0ŒBACK�TO�MAINLINE** CHECKSUM CALCULATION IF IN 2NDARY MEMORY *CKSUM2„EQU„*!*‰TR0$.KILLERˆGO�CRASH�THE�SYSTEM"*‰AND.Lƒ#$00FFFFFF,D0‡CLEAR�BIT�24*‰MOVE.L‚D0,A1ˆFOR�INDEXING*‰CLR.LƒD0‹BYTE�HOLDER+*‰MOVE.W‚SR,-(A7)…SAVE�FOR�INTERRUPT�UNMASK*IPCCK80ƒEQU…*ŒLOOP�TOP,*‰SUB.Lƒ#1,D5ˆBEGIN�WITH�ZERO�RELATIVE�INDEX/*‰BLT.SƒIPCCK90†BRANCH�IF�DONE�WITH�CALCULATION"*‰MOVE.W‚#$2700,SR„MASK�INTERRUPTS!*‰MOVE.W‚#0,$FE0006ƒTOGGLE�2NDARY+*‰MOVE.B‚0(A1,D5.L),D0‡PICK�UP�NEXT�FOR�SUM*‰MOVE.W‚(A7),SR†UNMASK *‰NOT.BƒD0.*‰ADD.WƒD0,D1ˆCONTRIBUTE�THIS�BYTE�TO�CHECKSUM *‰BRA…IPCCK80(*IPCCK90‚ADD.Lƒ#2,A7‰BYPASS�SAVED�STATUS*‰BRA.SƒIPCCK50‡BACK�TO�CALLERŠPAGEI****************************************************************************‚CMR�RESET�ROUTINE*%*ˆENTRY:�A2�=�PARAMETER�BLOCK�ADDRESS*�A3�=�PACKET�ADDRESS*�A5�=�CCB�ADDRESS*�A6�=�CALLERS�TCB�ADDRESS*I**************************************************************************5* Just a note for future maintainers of this code ---*G*�The�following�reset�routine�has�never�been�invoked.‚In�practice�thereH*ƒis�no�way�for�us�to�reach�this�code�even�though�BSR�CMRREST�is�presentF*ƒin�the�code.‚If�this�code�were�ever�executed,�the�most�likely�resultC*ƒwould�be�to�lose�the�IPC�until�a�reboot�takes�place.‚When�a�resetH*ƒis�issued,�the�IPC�goes�into�a�self�test�mode�and�there�is�no�good�way@*ƒto�tell�when�it�is�done.‚The�amount�of�time�spent�in�self�testG*ƒmode�may�be�considerable.‚To�handle�the�reset�logic�in�an�intelligentD*ƒway�would�involve�significant�changes�to�the�driver�and�to�IOS.‚As6*ƒof�01/18/84,�no�such�changes�have�been�contemplated.*CMRREST:*/ŠMOVE.L�CCBCHB(A5),A4†SET�UP�SHARED�MEM�POINTER*5*‰SET�LAST�BYTE�OF�SHARED�MEMORY�AS�AN�INDICATOR�THAT*‰RESET�IS�NOT�COMPLETE*ŠMOVE.B�#$FF,IPCLST(A4)=* CLEAR ERROR MODE,WAITING FOR ACK, DEALT WITH ACK, EXIT FLAG%ŠCLR.L‚CCBNAKAD(A5)‡CLEAR�NAK�ADDRESS'ŠCLR.L‚CCBERAD1(A5)‡CLEAR�ERROR�ADDRESSŠINHIB•INHIBIT�INTERRUPTSEŠAND.W�#-1-(1<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>PJD>31485>*G*‰THIS�CODE�WAS�ADDED�ON�3/14/85�TO�LOOK�FOR�THE�INVALID�COMMAND�STATUSC*‰AT�THE�WRONG�PLACE�BECAUSE�THE�VM30-1�FIRMWARE�1.0�PUTS�IT�THERE.*D*‰THIS�CODE�MAY�BE�REMOVED�IN�THE�FUTURE�WHEN�THE�VM30-1�FIRMWARE�IS *‰UPDATED*9ŠCMP.B‚#RTNHLT,RTNCHCM+IPCIM2(A4)�HALT/ABORT�PACKET�CODE?4ŠBEQ.S‚PKTC001�BRANCH�IF�YES,�CHECK�THE�STATUS�VALUEŠBRA.S‚PKTC010*N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<*&*‰Check�for�Configuration�(2nd�Packet)*"ŠBTST.B�#PIDPKTF,RTNPID+IPCIM2(A4)ŠBEQ.S‚PKTC010�NO,�IPC�ERRORŠBRA„INEXIT�YES�2nd�Packet*N*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<*.PKTC030ƒMOVE.L‚LUDCB(A2),A0‰SET�UP�DCB�POINTER ŠCLR.LƒD1%ŠCMP.Bƒ#XTDIPC,CCBTYPE(A5)‚DISK�IPC�? ŠBNE…MCCMPKTŽNO,�MUST�BE�AN�MCCM*‰BRA…DSKPKT�YESŠPAGEL*****************************************************************************,* HANDLE DISK NORMAL COMPLETION PACKETS HERE*+*ˆENTRY:�A2�=�address�of�device�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*�D0�=�packet�status�value*O********************************************************************************DSKPKT:/ŠLEA…DERXREF(PC),A1‡SET�STATUS�CROSS�REF.�TABLE*ŠCMP.Wƒ#DERXL,D0ŒERROR�CODE�IN�THE�TABLE�?ŠBLE.SƒDSKPK10ŽBRANCH�IF�YES'ŠBSR…IPCUNSER�NO,�IPC�ERROR�-�RESET�IPCŠBRA…IPCINRTN�RETURN'DSKPK10ƒCMP.Wƒ#XPSCSM,D0‹CHECKSUM�ERRORŠBNE.SƒDSKPK20ŽBRANCH�IF�NOŠCLR.LƒD0“YES,�IGNORE�IT1DSKPK20ƒLSL.Wƒ#1,D0�TIMES�2�FOR�POSITION�IN�TABLE+ŠMOVE.B‚(A1,D0.W),D1‰PICK�UP�IOS�ERROR�CODE!ŠBNE.SƒDSKPK30ŽBRANCH�IF�AN�ERROR&ŠBTSTWƒ#LUFEOF,LUFLG(A2)„EOF�PENDING�?ŠBEQ.SƒDSKPK30ŽBRANCH�IF�NO)ŠMOVE.B‚#ISTAEOV,D1ŠSET�UP�IOS�ERROR�CODEŠBRA.SƒDSKPK505DSKPK30ƒBTST„#1,1(A1,D0.W)ˆNEED�TO�UPDATE�PSN�FIELD�?ŠBEQ.SƒDSKPK40ŽBRANCH�IF�NO:ŠMOVEP.L�RTNSTPR+IPCIM2(A4),D2‚PICK�UP�PSN�FROM�SHARED�MEM+ŠMOVE.L‚D2,IOSRRN(A3)ˆUPDATE�IOCB�RRN�FIELDDSKPK40ƒCLR.LƒD41ŠBTST„#0,1(A1,D0.W)ˆNEED�TO�UPDATE�LENGTH�FIELD�?ŠBEQ.SƒDSKPK60ŽBRANCH�IF�NODSKPK50ƒCLR.LƒD35ŠMOVEP.W�RTNBLKS+IPCIM2(A4),D3‚PICK�UP�NO.�OF�SECTORS2ŠMOVEP.W�RTNBKSZ+IPCIM2(A4),D4‚PICK�UP�SECTOR�SIZEŠMULU„D3,D4�CALC.�NO.�OF�BYTES5DSKPK60ƒMOVE.L‚D4,IOSLEN(A3)ˆUPDATE�IOCB�LENGTH�FIELD.ŠMOVE.B‚D1,IOSSTA(A3)ˆUPDATE�IOCB�STATUS�FIELD ŠBRA…INEXITŠPAGEK****************************************************************************!* HANDLE UNSOLICITED PACKE2 TS HERE*+*ˆENTRY:�A2�=�address�of�device�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*L*****************************************************************************UNSPKT:.ŠCMP.B‚#RTNUNS,RTNSTCM+IPCIM2(A4)�RIGHT�CODE�?ŠBEQ.S‚UNSP010�BRANCH�IF�YES'ŠBSR„IPCUNSERŽNO,�IPC�ERROR�-�RESET�IPCŠBRA„IPCINRTNŽRETURN0UNSP010ƒMOVE.L�LUDCB(A2),D2ŠPICK�UP�LAST�CMD�DCB$ŠBEQ.S‚UNSP030�FIRST�ONE,�USE�CCB�ID ŠMOVE.L�D2,A0‘SET�UP�DCB�POINTER'ŠMOVE.W�#XSTVDST,D3‹SET�UP�STATUS�VALUE%ŠCMP.B‚#XTDIPC,CCBTYPE(A5)ƒDISK�IPC�?ŠBNE.S‚UNSP020�NO;ŠMOVE.B�RTNSTAD+IPCIM2(A4),D0‚GET�STATUS�FROM�SHARED�MEMORYŠMOVE.L�D0,D4‘MAKE�ANOTHER�COPY"ŠAND.W‚#$0F,D4�ISOLATE�DEVICE�BITS"ŠAND.W‚#$F0,D0�ISOLATE�STATUS�BITS$ŠLSL.W‚#8,D0‘SET�UP�BYTE�1�OF�STATUSŠOR.WƒD0,D4‘MERGE�BYTE�1�AND�2:ŠMOVEP.L�RTNLSEC+IPCIM2(A4),D0‚GET�SECTORS�FROM�SHARED�MEM-ŠMOVE.L�D0,DCBSEC(A0)‰UPDATE�DCB�WITH�SECTORS&ŠMOVE.L�#8,D0‘SET�UP�EVENT�INFO�LENGTHŠBRA.S‚UNSP040BUNSP020ƒMOVE.B�RTNSTAD+IPCIM2(A4),D0‚GET�STATUS�FROM�SHARED�MEMORYŠMOVE.L�D0,D4‘MAKE�ANOTHER�COPY"ŠAND.W‚#$0F,D4�ISOLATE�DEVICE�BITS"ŠAND.W‚#$F0,D0�ISOLATE�STATUS�BITSŠBSETƒ#XDSBRK,D0ŒSET�BREAK�BIT$ŠLSL.W‚#8,D0‘SET�UP�BYTE�1�OF�STATUSŠOR.WƒD0,D4‘MERGE�BYTE�1�AND�2&ŠMOVE.L�#8,D0‘SET�UP�EVENT�INFO�LENGTHŠBRA.S‚UNSP040  5UNSP030ƒMOVE.L�CCBMNEM(A5),D2ˆSET�UP�CHANNEL�MNEMONIC'ŠMOVE.W�#XSTVNID,D3‹SET�UP�STATUS�VALUE0ŠMOVE.B�RTNSTPR+IPCIM2(A4),D0‚PICK�UP�IPC�STATUSŠMOVE.L�D0,D4‘MAKE�ANOTHER�COPY"ŠAND.W‚#$0F,D4�ISOLATE�DEVICE�BITS"ŠAND.W‚#$F0,D0�ISOLATE�STATUS�BITS$ŠLSL.W‚#8,D0‘SET�UP�BYTE�1�OF�STATUSŠOR.WƒD0,D4‘MERGE�BYTE�1�AND�2/ŠMOVE.B�RTNPHDV+IPCIM2(A4),D5�SET�UP�DEVICE�NO.'ŠMOVE.L�#10,D0�SET�UP�EVENT�INFO�LENGTH+UNSP040ƒMOVE.B�#XPSUNS,D1ŒSET�UP�EVENT�TYPE+ŠLEA„CCBCPKT(A5),A4ˆSET�UP�EVENT�BUILD�AREA#ŠBSR„QEVNT‘QUEUE�NOTIFICATION�EVENT ŠBRA„INEX010ŠPAGEJ*************************************************************************** * HANDLE HALT/ABORT PACKET ($71)*+*ˆENTRY:�A2�=�address�of�device�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*�D0�=�packet�status�value*K****************************************************************************HLTPKT:#ŠCMP.W‚#XPSICM,D0ŒINVALID�COMMAND�?ŠBNE.S‚HLTP010�BRANCH�IF�NON*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<*#*‰Configure�Command�-�second�packet*"ŠBTST.B�#PIDPKTF,RTNPID+IPCIM2(A4)ŠBNE.S‚HLTP030�YES�-�2nd�packet*N*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>0ŠBCLRW‚#LUFHLT,LUFLG(A2)…Clear�halt�pending�flag&ŠBRA„INEX020�Go�acknowledge�and�returnGHLTP010ƒMOVE.B�#ISTATO,IOSSTA(A3)„UPDATE�ORIG�REQUEST�IOCB�STATUS�FIELDŠMOVE.LƒA6,-(A7)ŒSAVE�A62ŠMOVE.LƒLUMISC(A2),A6‡GET�HALT�PACKET�IOCB�ADDRESS.ŠMOVE.Bƒ#ISTAOK,IOSSTA(A6)‚UPDATE�STATUS�TO�OKŠMOVE.Lƒ(A7)+,A6ŒRESTORE�A67ŠCLR.L‚IOSLEN(A3)ŒUPDATE�ORIG�REQUEST�IOCB�LENGTH�FIELD&ŠMOVE.W�#ISTATO,D3ŒSET�UP�STATUS�VALUE$ŠMOVE.B�#XPSHLT,D1ŒSET�UP�EVENT�TYPE-HLTP020ƒMOVE.L�#6,D0‘SET�UP�EVENT�INFO�LENGTH)ŠMOVE.L�LUDCB(A2),D2ŠSET�UP�DCB�FOR�EVENT+ŠLEA„CCBCPKT(A5),A4ˆSET�UP�EVENT�BUILD�AREAŠBSR„QEVNT‘QUEUE�HALT�EVENT)ŠCLR.W‚LUFLG(A2)�CLEAR�DEVICE�TABLE�ENTRY ŠBRA„INEX010* *‰2nd�Packet* HLTP030ƒEQU„*+ŠMOVE.L�LUBADR(A2),A1‰SET�UP�BUFFER�POINTER=ŠAND.L‚#$F84F,IOSPRM(A1)…SET�UNCONFIGURABLE�BITS�(2nd)�PACKET ŠBRA„STAP030ŠPAGEL*****************************************************************************0* HANDLE SOLICITED DEVICE/CONFIGURE PACKET ($72)*+*ˆENTRY:�A2�=�address�of�device�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*�D0�=�packet�status�value*L*****************************************************************************STAPKT:+ŠMOVE.L�LUBADR(A2),A1‰SET�UP�BUFFER�POINTER(ŠMOVE.L�LUDCB(A2),A0ŠPICK�UP�DCB�ADDRESS<ŠMOVE.B�RTNDSTA+IPCIM2(A4),D1‚PICK�UP�STATUS�FROM�SHARED�MEM ŠMOVE.L�D1,D2"ŠAND.B‚#$0F,D2�ISO2 LATE�DEVICE�TYPE-ŠMOVE.B�D2,IOSDTP(A1)‰UPDATE�CONFIGURE�BUFFER"ŠAND.B‚#$F0,D1�ISOLATE�STATUS�BITS-ŠMOVE.B�D1,IOSDST(A1)‰UPDATE�DEV�STATUS�FIELD%ŠCMP.B‚#XTDIPC,CCBTYPE(A5)ƒDISK�IPC�?ŠBNE.S‚STAP020�NO&ŠCMP.W‚#3,D0‘DEVICE�NOT�READY�STATUS�?%ŠBEQ.S‚STAP010�BRANCH�IF�YES,�IT'S�OKŠCMP.W‚#$05,D0ŠBEQ.S‚STAP010$*¦JMP�IF�INVALID�LOGICAL�UNIT�NUMBERŠCMP.W‚#$12,D0ŠBEQ.S‚STAP010*¦JMP�IF�DEVICE�NOT�THEREŠCMP.W‚#$10,D0ŠBEQ.S‚STAP010*¦JMP�IF�DEVICE�ERROR�RETURNEDŠCMP.W‚#$13,D0ŠBEQ.S‚STAP010*¦JMP�IF�DEVICE�CONFLICT�ERRORŠTST.W‚D0”RIGHT�STATUS�VALUE�?ŠBEQ.S‚STAP010�BRANCH�IF�YES‰CMP.W…#$0E,D0‰BNE.S…STAP010!*¦JMP�IF�OTHER�THAN�INDETERMINATE*¦CHANNEL�ERROR'ŠBSR†IPCUNSERŒNO,�IPC�ERROR�-�RESET�IPCŠBRA†IPCINRTNŒRETURN1STAP010ƒCLR.B„IOSSTA(A3)ŠUPDATE�IOCB�STATUS�FIELD>ŠMOVEP.L‚RTNLSEC+IPCIM2(A4),D1�PICK�UP�SECTORS�FROM�SHARED�MEM*ŠMOVE.LƒD1,IOSRSZ(A1)‡UPDATE�SECTORS�FIELD'ŠCLR.W„IOSATW(A1)ŠCLEAR�ATTRIBUTES�WORDŠBRA.S„STAP030* STAP020ƒEQU„*N*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 6/04/84 <<<<<<<ŠTST†D0’REQUEST�STATUS�COMMANDŠBEQ†STAP300�YES*&*‰Check�for�Configuration�(1st�Packet)*"ŠBTST.B�#PIDPKTF,RTNPID+IPCIM2(A4)ŠBNE.S‚STAP035�Not�1st�PacketN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>*ŠCLR.B‚IOSSTA(A3)ŒUPDATE�IOCB�STATUS�FIELD*O*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> *ºBKM�7/14/83$*‰BTSTWƒ#DATPRT,DCBATT(A0)ƒPRINTER�?!ŠBTSTMƒDATPRT,DCBATT,A0ƒPRINTER�? *ºBKM�7/14/83O*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<ŠBEQ…STAP040ŽBRANCH�IF�NO*>*ˆPrinter�configuration�complete.‚Update�current�configuration*ˆand�return�the�results.*&‰MOVEM.LƒA5,-(A7)ŒSave�the�CCB�address6‰LEA‡CONFIG(A2),A5‡Use�the�CONFIG�offset�so�we�can�use*¦the�IOE�equates.BŠMOVE.B‚RTNHWS4+IPCIM2(A4),IOSREC+1(A1)�UPDATE�RECORD�LENGTH�FIELD?ŠMOVE.B‚RTNHWS4+IPCIM2(A4),IOSREC+1(A5)�Update�the�current�line*±length�config�value..:ŠMOVE.B‚RTNSWS2+IPCIM2(A4),D3‚PICK�UP�S/W�CONFIGURE�BYTE�2-‰CLR.W…IOSATW(A5)ŠWipe�the�old�attributes�out!ŠBTST„#XSWALF,D3‹AUTO�LINE�FEED�?ŠBEQ.SƒSTAP025ŽBRANCH�IF�NOC‰BSETW…#IOALNFD,IOSATW(A5)�Yes,�set�the�attribute�in�current�config0ŠBSETWƒ#IOALNFD,IOSATW(A1)‚YES,�SET�UP�ATTRIBUTE‰MOVE.B„RTNSWS3+IPCIM2(A4),IOSELC(A5)�Set�up�end/print�char�in*°current�configuration�area.*‰MOVEM.Lƒ(A7)+,A5ŒRestore�the�CCB�address.* STAP030ƒEQU…* ŠCLR.LƒD1FŠMOVE.B�CCBTYPE(A5),IOSCTP(A1)�Return�the�channel�type�and�driver�code<ŠMOVE.B�#IODIPC,IOSDRC(A1)ƒin�the�users�configuration�block.ŠBRA…INEXIT�GO�QUEUE�EVENT*B*ˆEnd�of�second�packet�from�MCCM.‚Update�the�current�config�values* STAP035‚EQU‡*&‰MOVEM.LƒA5,-(A7)ŒSave�the�CCB�address:‰LEA‡CONFIG(A2),A5‡Use�the�CONFIG�offset�so�we�can�use�the*¦IOE�equates.‰MOVE.W„IOSREC(A1),IOSREC(A5)‰MOVE.L„IOSRSZ(A1),IOSRSZ(A5)<‰MOVE.B„IOSXOF(A1),IOSXOF(A5)�Update�the�current�config�area<‰MOVE.B„IOSXON(A1),IOSXON(A5)�Update�the�current�config�area<‰MOVE.B„IOSBRC(A1),IOSBRC(A5)�Update�the�current�config�area0‰CLR.B…IOSDOP(A5)ŒUpdate�the�current�config�area<‰MOVE.B„IOSRLN(A1),IOSRLN(A5)�Update�the�current�config�area<‰MOVE.B„IOSCLC(A1),IOSCLC(A5)�Update�the�current�config�area<‰MOVE.L„IOSRTV(A1),IOSRTV(A5)�Update�the�current�config�area<‰MOVE.L„IOSEOL(A1),IOSEOL(A5)�Update�the�current�config�area<‰MOVE.B„IOSBRT(A1),IOSBRT(A5)�Update�the�current�config�area<‰MOVE.B„IOSNLS(A1),IOSNLS(A5)�Update�the�current�config�area*G*ˆ3/26/85�PJD�-�THIS�CODE�WAS�ADDED�TO�UPDATE�THE�CURRENT�CONFIGURATION0*ˆATTRIBUTE�WORD�DURING�A�CONFIGURATION�REQUEST.**3‰MOVE.W„IOSATM(A1),D0‡GET�THE�USER'S�ATTRIBUTE�MASK3‰MOVE.W„IOSATW(A1),D1‡GET�THE�USER'S�ATTRIBUTE�WORD5‰AND.W…D0,D1�STRIP�OFF�ANY�UNEEDED�BITS�FROM�THE�WORD)‰NOT.W…D0’INVERT�THE�MASK�->�BITS�TO�SAVE-‰AND.W…IOSATW(A5),D0‡CLEAR�BITS�TO�BE�CHANGED%‰OR.W†D1,D0�OR�IN�THE�USER'S�NEW�WORD<‰MOVE.W„D0,IOSATW(A5)‡SAVE�THE�N3 EW�ATTRIBUTE�WORD�IN�CURRENT *§CONFIG�AREA*‰MOVEM.Lƒ(A7)+,A5‰BRA.S…STAP030ŠPAGE* STAP040ƒEQU…*0ŠBSR…BLDATRMŽCALL�THE�BUILD�ATTRIBUTE�SUBROUTINE1ŠMOVE.W‚D1,IOSATW(A1)ˆUPDATE�USER�ATTRIBUTE�FIELD* *‰CONFIGURE�COMMAND�(2nd�Packet)* STAP150ƒEQU…***‰NOW�LETS�INTERRUPT�IPC�FOR*‰EVENT�COMPLETION.*1ŠMOVE.LƒCCBCHB(A5),A4‡SETUP�SHARED�MEMORY�POINTER.ŠCLR.B„IPCIMB2(A4)‰CLEAR�THE�MESSAGE�SENT�FLAG5ŠMOVE.Bƒ#ACK,IPCIAB1(A4)„PLACE�ACK�INTO�SHARED�MEMORY)ŠMOVE.Bƒ#$80,IPCINT(A4)…INTERRUPT�THE�IPC.ŠCLR.W„CCBRCNT(A5)‰JUST�IN�CASE�A�RESET�WORKED**ˆCHECK�FOR�SHARED�MEMORY�FREE*-STAP152‚TST.B…IPCIMB1(A4)‰IS�THE�MEMORY�FREE?$‰BNE.S…STAP152�NO,�WAIT�FOR�IT�TO�BE***‰BUILD�SECOND�PACKET*/STAP151ƒLEA†IPCIM1(A4),A4‡SETUP�MESSAGE�ADDRESSŠMOVE.Wƒ#SPKT,D1/ŠMOVEP.W‚D1,IPCSTX(A4)‡SET�UP�STX�AND�PACKET�ID+ŠBSET…#PIDPKTF,IPCPID(A4)�SET�2nd�PACKET�ID0ŠMOVE.BƒDCBCDV(A0),IPCPHDV(A4)‚SET�UP�DEVICE�NO.* *ˆSet�up�pointer�to�device�table* ‰CLR.L…D1+‰MOVE.B„DCBCDV(A0),D1‡Get�the�device�number)‰MULU†#LUDSZE,D1ŠMul�by�size�of�one�table2‰MOVE.L„CCBDTBL(A5),A0†Get�start�address�of�tables4‰ADD.L…D1,A0�Add�to�get�start�of�this�device's�table:‰LEA‡CONFIG(A0),A0‡Use�the�CONFIG�offset�so�we�can�use�IOE *¦equates.ŠMOVE.Wƒ#XCON2P,D16ŠMOVEP.W‚D1,IPCCHCM(A4)†SET�UP�CHANNEL/DEVICE�COMMANDS*?*‰Using�the�Parameter�Mask�determine�which�parameters�come�from4*‰the�Parameter�Block�and�which�ones�use�the�default*,ŠMOVE.W‚IOSPRM(A1),D0ˆGET�MASK�OF�PARAMETERSŠMOVE.W‚#$5FB3,D10ŠMOVEP.W�D1,IPCPMSK(A4)‡PARAMETER�MASK�TO�PACKETŠLSR.Wƒ#2,D0�LINES�PER�PAGEŠBCS.SƒSTAP155�YESŠMOVE.LƒIOSRSZ(A0),IOSRSZ(A1) STAP155ƒLSR.Wƒ#3,D0�XON/XOF�CharŠBCS.SƒSTAP170�YES*2*‰Move�current�config�XON/XOF�char's�to�2nd�packet*ŠMOVE.B‚IOSXOF(A0),IPCXOF(A4)3ŠMOVE.B‚IOSXOF(A0),IOSXOF(A1)ŠUpdate�the�users�IOCBŠMOVE.B‚IOSXON(A0),IPCXON(A4)3ŠMOVE.B‚IOSXON(A0),IOSXON(A1)ŠUpdate�the�users�IOCBŠBRA.SƒSTAP175*'*‰Move�new�XON/XOF�char's�to�2nd�packet* STAP170ƒEQU…*ŠMOVE.B‚IOSXOF(A1),IPCXOF(A4)ŠMOVE.B‚IOSXON(A1),IPCXON(A4) STAP175ƒEQU…*!ŠLSR.Wƒ#1,D0�BRK�equivalent�char.ŠBCS.SƒSTAP180�YES*,*‰Move�current�config�BRK�char�to�2nd�packet*ŠMOVE.B‚IOSBRC(A0),IPCBRK(A4)3ŠMOVE.B‚IOSBRC(A0),IOSBRC(A1)ŠUpdate�the�users�IOCBŠBRA.SƒSTAP185*!*‰Move�new�BRK�char�to�2nd�packet* STAP180ƒEQU…*ŠMOVE.B‚IOSBRC(A1),IPCBRK(A4) STAP185ƒEQU…*ŠLSR.Wƒ#2,D0�REPRINT�LINE�charŠBCS.SƒSTAP190�YES*5*‰Move�current�config�REPRINT�LINE�char�to�2nd�packet*ŠMOVE.B‚IOSRLN(A0),IPCRPRT(A4)/ŠMOVE.B‚IOSRLN(A0),IOSRLN(A1)ŠUpdate�users�IOCBŠBRA.SƒSTAP195***‰Move�new�REPRINT�LINE�char�to�2nd�packet* STAP190ƒEQU…*ŠMOVE.B‚IOSRLN(A1),IPCRPRT(A4) STAP195ƒEQU…*ŠLSR.Wƒ#1,D0�CANCEL�LINE�charŠBCS.SƒSTAP200�YES*4*‰Move�current�config�CANCEL�LINE�char�to�2nd�packet*ŠMOVE.B‚IOSCLC(A0),IPCCNCL(A4)/ŠMOVE.B‚IOSCLC(A0),IOSCLC(A1)‰Update�users�IOCBŠBRA.SƒSTAP205*)*‰Move�new�CANCEL�LINE‚char�to�2nd�packet* STAP200ƒEQU…*ŠMOVE.B‚IOSCLC(A1),IPCCNCL(A4) STAP205ƒEQU…*$ŠLSR.Wƒ#1,D0�READ�TERMINATING�char'sŠBCS.SƒSTAP210�YES*;*‰Move�current�config�READ�TERMINATING�char's�to�2nd�packet*ŠMOVE.L‚IOSRTV(A0),D1ŠMOVEP.L�D1,IPCRTRM(A4)'‰MOVE.L„D1,IOSRTV(A1)‡Update�users�IOCBŠBRA.SƒSTAP215*0*‰Move�new�READ�TERMINATING�char's�to�2nd�packet* STAP210ƒEQU…*ŠMOVE.L‚IOSRTV(A1),D1ŠMOVEP.L�D1,IPCRTRM(A4) STAP215ƒEQU…*ŠLSR.Wƒ#1,D0�EOD-OF-LINE�stringŠBCS.SƒSTAP220�YES*6*‰Move�current�config�END-OF-LINE�string�to�2nd�packet*ŠMOVE.W‚IOSEOL(A0),D1ŠMOVEP.W�D1,IPCEOL(A4)'‰MOVE.W„D1,IOSEOL(A1)‡Update�users�IOCBŠBRA.SƒSTAP225*+*‰Move�new�END-OF-LINE�string�to�2nd�packet* STAP220ƒEQU…*ŠMOVE.W‚IOSEOL(A1),D1ŠMOVEP.W�D1,IPCEOL(A4)*** STAP225ƒEQU…*#ŠMOVE.B‚#ETX,IPC2ETX(A4)†SET�UP�ETX.ŠMOVE.B‚#C2PKSZ,IPCPKSZ(A4)ƒSET�UP�PACKET�SIZE**‰INDICATE�AWAITING�ACK*'ŠBSETWƒ#CCBFGWAK,CCBFG(A5)ƒSET�CCB�FLAG**‰INTERRUPT�THE�IPC* NRXINP„EQU„*0ŠM3 OVE.L�CCBCHB(A5),A1†SET�UP�SHARED�MEM.�POINTER(ŠMOVE.B�#$80,IPCIMB1(A1)ƒMESSAGE�WAITING0ŠADD.B‚#2,CCBICNT(A5)…BUMP�OUTSTANDING�INT�COUNT%ŠMOVE.B�#$80,IPCINT(A1)„INTERRUPT�IPC#ŠCLR.L‚D0‘SET�UP�GOOD�RETURN�TO�CMR ŠBRA„IPCINRTNŠPAGEK*****************************************************************************†REQUEST�STATUS�HANDLING**ˆENTRY:�A0�=�address�of�DCB!*�A1�=�address�of�user�data�block$*�A2�=�address�of�device�table�entry(*�A4�=�address�of�IPC�shared�memory�base*K*************************************************************************** STAP300ƒEQU…*,ŠLEA…DCBDEV(A0),A3ˆADDR�OF�DCB�CONFIGURATION0ŠBSR…BLDATRMŽcall�the�build�attribute�subroutine1ŠMOVE.W‚D1,IOSATW(A1)ˆupdate�user�attribute�field,‰MOVE.L„DCBATT(A0),D1‡Get�the�DCB�attributes**@*‰Move�configuration�info�from�CURRENT�CONFIG�to�user�data�block*8‰LEA‡CONFIG(A2),A3‡Use�the�CONFIG�offset�into�the�device%*¦table�so�we�an�use�the�IOE�equates.;‰LEA‡DCBDEV(A0),A0‡Get�the�DCB�device�dependent�area�offset*>ŠMOVE.W‚IOSREC(A3),IOSREC(A1)�Move�Current�values�to�user�IOCB@ŠMOVE.L‚IOSRSZ(A3),IOSRSZ(A1)�Except�that�some�values�(those�notAŠMOVE.L‚IOSWTO(A0),IOSWTO(A1)�configurable�anyway)�will�come�from *§the�DCB.4ŠBTST…#DATPRT,D1ŠCheck�the�DCB�attributes-�is�this�a *¦printer?5ŠBNE.SƒSTAP330ŽYes,�skip�the�update�of�the�term�stuff**ˆTerminal�status�request*ŠMOVE.L‚IOSRTO(A0),IOSRTO(A1)ŠMOVE.B‚IOSXOF(A3),IOSXOF(A1)ŠMOVE.B‚IOSXON(A3),IOSXON(A1)ŠMOVE.B‚IOSBRC(A3),IOSBRC(A1)ŠMOVE.B‚IOSDOP(A3),IOSDOP(A1)ŠMOVE.B‚IOSRLN(A3),IOSRLN(A1)ŠMOVE.B‚IOSCLC(A3),IOSCLC(A1)ŠMOVE.L‚IOSRTV(A3),IOSRTV(A1)ŠMOVE.L‚IOSEOL(A3),IOSEOL(A1)ŠMOVE.B‚IOSBRT(A3),IOSBRT(A1)ŠMOVE.B‚IOSNLS(A3),IOSNLS(A1)ŠMOVE.B‚IOSTCD(A0),IOSTCD(A1) STAP320ƒEQU…* ŠCLR.LƒD1 ŠBRA.SƒINEXITN*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FAM 6/04/84 >>>>>>>*%*ˆRemainder�of�printer�status�request*$STAP330‚MOVE.W„IOSREC(A0),IOSLRL(A1)‰MOVE.B„IOSELC(A0),IOSELC(A1)‰BRA.S…STAP320*ŠPAGEK****************************************************************************,*‰HANDLE�MCCM�NORMAL�COMPLETION�PACKETS�HERE*+*‹ENTRY:�A2�=�address�of�device�table�entry*’A3�=�address�of�IOCB(*’A4�=�address�of�IPC�shared�memory�base*’A5�=�address�of�CCB*’D0�=�packet�status�value*K****************************************************************************MCCMPKT:2ŠLEA…MERXREF(PC),A1‡SET�UP�STATUS�CROSS�REF.�TABLE*ŠCMP.Wƒ#MERXL,D0ŒERROR�CODE�IN�THE�TABLE�?ŠBLE.SƒMCCMP10ŽBRANCH�IF�YES)ŠBSR.SƒIPCUNSER�NO,�IPC�ERROR�-�RESET�IPCŠBRA.SƒIPCINRTN�RETURN)MCCMP10ƒCMP.Wƒ#XPSCSM,D0‹CHECKSUM�ERROR�?ŠBNE.SƒMCCMP20ŽBRANCH�IF�NOŠCLR.LƒD0“YES,�IGNORE�ERROR1MCCMP20ƒLSL.Wƒ#1,D0�TIMES�2�FOR�POSITION�IN�TABLE,ŠMOVE.B‚(A1,D0.W),D1‰PICK�UP�IOCB�ERROR�CODE ŠCLR.L…D41ŠBTST„#0,1(A1,D0.W)ˆNEED�TO�UPDATE�LENGTH�FIELD�?ŠBEQ.SƒMCCMP30ŽBRANCH�IF�NO5ŠMOVEP.W�RTNBKSZ+IPCIM2(A4),D4‚PICK�UP�TRANSFER�BYTES5MCCMP30ƒMOVE.L‚D4,IOSLEN(A3)ˆUPDATE�IOCB�LENGTH�FIELD.ŠMOVE.B‚D1,IOSSTA(A3)ˆUPDATE�IOCB�STATUS�FIELD*¦FALL�THRU�TO�"INEXIT"ŠPAGEK****************************************************************************!*‚NORMAL�EXIT�FROM�INTERRUPT�TOUR*+*ˆENTRY:�A2�=�address�of�device�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*K****************************************************************************INEXIT:&ŠMOVE.L‚#6,D0�SET�UP�EVENT�INFO�LENGTH)ŠMOVE.L‚LUDCB(A2),D2‰SET�UP�DCB�FOR�EVENT+ŠMOVE.W‚D1,D3�SET�UP�STATUS�VALUE�FOR�EVENT$ŠMOVE.B‚#XPSNRM,D1‹SET�UP�EVENT�TYPE+ŠLEA…CCBCPKT(A5),A4‡SET�UP�EVENT�BUILD�AREA!ŠBSR…QEVNT�QUEUE�COMPLETION�EVENT)ŠCLR.WƒLUFLG(A2)ŒCLEAR�DEVICE�TABLE�ENTRY*5* DECREMENT I/O PENDING COUNT IF SOLICITED TYPE EVENT*7INEX010ƒMOVE.L�CCBCHB(A5),A4†RESTORE�SHARED�MEM�POINTER.ŠBTSTƒ#7,RTNSTCM+IPCIM2(A4)‚IS�THIS�SOLICITED?ŠBNE.S‚INEX020ŒBRANCH�IF�NO ŠMOVE.L�LUTCB(A2),A0‡TCB�ADDRESS2ŠSUB.B‚#1,TCBIOCNT(A0)„DECREMENT�I4 /O�PENDING�COUNT**‰NOW�LETS�INTERRUPT�IPC�FOR*‰EVENT�COMPLETION.*5INEX020ƒCLR.B‚IPCIMB2(A4)ˆCLEAR�THE�MESSAGE�SENT�FLAG5ŠMOVE.B�#ACK,IPCIAB1(A4)ƒPLACE�ACK�INTO�SHARED�MEMORY)ŠMOVE.B�#$80,IPCINT(A4)„INTERRUPT�THE�IPC.ŠCLR.W‚CCBRCNT(A5)ˆJUST�IN�CASE�A�RESET�WORKED*4*‰IPC�INTERRUPT�HANDLER�ALWAYS�EXITS�FROM�THIS�POINT*IPCINRTN‚EQU„**‰ENABL˜ENABLE�INTERRUPTS6ŠSUB.L‚#1,CCBINL(A5)‰DECREMENT�INTERRUPT�NESTING�LEVEL/ŠMOVEM.L�(A7)+,D1-D7/A2-A4/A6ƒRESTORE�REGISTERS"ŠOR.W„#$01,SRŽSET�RETURN�CONDITION ŠRTS…0”BACK�TO�INTERRUPT�HANDLERŠPAGEK*****************************************************************************6* ROUTINE TO HANDLE 68000 DETECTED FATAL CHANNEL ERROR'*ƒSAVE�CALLING�ADDRESS�IN�CCB�FOR�DEBUG*ƒMARK�THE�CHANNEL�IN�ERROR*ƒQUEUE�EVENT�TO�CALLING�TASK*ƒRETURN*+*ˆENTRY:�A2�=�address�of�device�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*K**************************************************************************** IPCUNSER:ŠINHIB,ŠMOVE.L�(A7),CCBERAD1(A5)‚SAVE�ERROR�ADDRESS3ŠOR.Wƒ#(1<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 11/07/84 <<<<<<C*********************************************************************‰BUILD�ATTRIBUTES�MASK*!*‹ENTRY:�A1�=�user�buffer�pointer(*’A4�=�address�of�IPC�shared�memory�base**‹EXIT:‚D1�=�attribute�mask*C******************************************************************* BLDATRMƒEQU…* ŠCLR.LƒD1:ŠMOVE.B‚RTNHWS1+IPCIM2(A4),D2�PICK�UP�H/W�CONFIGURE�BYTE�1ŠBTST„#XHWBIT,D2‹8�BIT�?ŠBNE.SƒBLDA010ŽBRANCH�IF�YES&ŠBSET„#IOABITS,D1ŠNO,�SET�UP�ATTRIBUTE%BLDA010ƒBTST„#XHWSTP,D2‹2�STOP�BITS�?ŠBEQ.SƒBLDA020ŽBRANCH�IF�NO'ŠBSET„#IOASTPB,D1ŠYES,�SET�UP�ATTRIBUTE!BLDA020ƒBTST„#XHWPRTY,D2ŠPARITY�?ŠBEQ.SƒBLDA030ŽBRANCH�IF�NO'ŠBSET„#IOAUSEP,D1ŠYES,�SET�UP�ATTRIBUTEŠBTST„#XHWEVN,D2‹EVEN�PARITY�?ŠBEQ.SƒBLDA030ŽBRANCH�IF�NO'ŠBSET„#IOAPRTY,D1ŠYES,�SET�UP�ATTRIBUTEABLDA030ƒMOVE.B‚RTNHWS2+IPCIM2(A4),D2‚PICK�UP�H/W�CONFIGURE�BYTE�2ŠBTST„#XHWMDM,D2‹MODEM�?ŠBEQ.SƒBLDA040ŽBRANCH�IF�NO'ŠBSET„#IOAMODM,D1ŠYES,�SET�UP�ATTRIBUTE,BLDA040ƒAND.Bƒ#$0F,D2ŽISOLATE�BAUD�RATE�BITS,ŠMOVE.B‚D2,IOSBRT(A1)ˆUPDATE�BAUD�RATE�FIELD6ŠMOVE.B‚RTNHWS3+IPCIM2(A4),IOSNLS(A1)�UPDATE�NULL�PADS<ŠMOVE.B‚RTNHWS4+IPCIM2(A4),IOSREC+1(A1)�UPDATE�RECORD�LENGTHŠCLR.BƒIOSREC(A1):ŠMOVE.B‚RTNSWS1+IPCIM2(A4),D3‚PICK�UP�S/W�CONFIGURE�BYTE�1ŠBTST„#XSWHDX,D3‹HALF�DUPLEXŠBEQ.SƒBLDA050ŽBRANCH�IF�NO'ŠBSET„#IOAECHO,D1ŠYES,�SET�UP�ATTRIBUTE BLDA050ƒEQU…*ŠBTST„#XSWNUL,D3‹ACCEPT�NULLSŠBEQ.SƒBLDA060ŽBRANCH�IF�NO'ŠBSET„#IOAPNUL,D1ŠYES,�SET�UP�ATTRIBUTE BLDA060ƒEQU…*#ŠBTST„#XSWTAHD,D3ŠACCEPT�TYPE�AHEADŠBEQ.SƒBLDA070ŽBRANCH�IF�NO'ŠBSET„#IOATAHD,D1ŠYES,�SET�UP�ATTRIBUTE BLDA070ƒEQU…* ŠBTST„#XSWXON,D3‹ACCEPT�XON/XOFFŠBEQ.SƒBLDA080ŽBRANCH�IF�NO'ŠBSET„#IOAXCTL,D1ŠYES,�SET�UP�ATTRIBUTE BLDA080ƒEQU…*ŠRTSN*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FAM 11/07/84 <<<<<<ŠPAGEJ**************************************************************************** QEVNT**„PLACE�MSG�ON�USER'S�ASQ* *ˆA4�=�COMPLETION�PACKET�POINTER*ˆA5�=�CCB�ADDRESS'*ˆD0�=�PACKET�LENGTH(MINUS�HEADER�INFO)*ˆD1�=�EVENT�TYPE*ˆD2�=�ID�(4�BYTES)*ˆD3�=�STATUS�VALUE�(2�BYTES) *‡[D4�=�DEVICE�STATUS�(2�BYTES)]*‡[D5�=�DEVICE�NUMBER�(1�BYTE)4 ]*J***************************************************************************QEVNT:ŠMOVE.L�D0,D6ŽSAVE�LENGTH-ŠMOVE.L�#2,D7ŽOFFSET�FOR�STAGING�(NO�SVC�VCT)'ŠMOVE.B�#IOEVCD,1(A4)†CODE�(NO�SVC�VCT)(ŠMOVE.L�CCBSVVC(A5),2(A4)‚SERVICE�VECTOR*ŠBEQ.S‚QEVNT10ŒBRANCH�IF�NO�SERVICE�VECTOR'ŠADD.L‚#4,D0ŽCORRECT�LENGTH�FOR�SVC�VCT/ŠADD.L‚#4,D7ŽCORRECT�OFFSET�STAGING�FOR�SVC�VCT*ŠADD.L‚#$00800000,(A4)„CORRECT�FOR�SVC�VCT QEVNT10ƒEQU„*$ŠMOVE.B�D1,0(A4,D7)ˆCMPL.�EVENT�TYPE)ŠMOVE.B�CCBKEY(A5),1(A4,D7)�USER'S�ID�KEY*ŠADD.L‚#4,D0ŽCOMPLETE�LENGTH�OF�RETURN�MSG1ŠCMP.B‚CCBASQL(A5),D0…USER'S�MAX�ASQ�ENTRY�LENGTH"ŠBLS.S‚QEVNT20ŒBRANCH�IF�LENGTH�OK/ŠMOVE.B�CCBASQL(A5),D0…USER'S�LENGTH�IS�SMALLER QEVNT20ƒEQU„*ŠMOVE.B�D0,(A4)ŒCORRRECT�LENGTH QEVNT40ƒEQU„*ŠMOVE.L�D2,2(A4,D7)ˆSET�UP�ID'ŠMOVE.W�D3,6(A4,D7)ˆSET�UP�STATUS�VALUEŠCMP.B‚#6,D6Ž6�BYTE�INFO�?ŠBEQ.S‚QEVNT50ŒBRANCH�IF�YES(ŠMOVE.W�D4,8(A4,D7)ˆSET�UP�DEVICE�STATUSŠCMP.B‚#8,D6Ž8�BYTE�INFO�?ŠBEQ.S‚QEVNT50ŒBRANCH�IF�YES)ŠMOVE.B�D5,10(A4,D7)‡SET�UP�DEVICE�NUMBER%ŠCLR.B‚11(A4,D7)ŠCLEAR�RESERVED�FIELD*@* NOW LET'S PUT THE COMPLETION INTO REGISTERS, INTERRUPT IOH FOR&*ƒEVENT�COMPLETION,�SEND�EVENT�TO�TASK** QEVNT50ƒEQU„*ŠMOVEM.L�(A4),D2-D7ŠBSR.S‚IPCQEVNTŠRTSŠPAGEK*****************************************************************************9* ROUTINE TO QUEUE EVENT (ALREADY STAGED IN REGISTERS) TO*ƒ-�DRIVING�TASK. *ƒ-�EVENT�BEGINS�IN�REGISTER�D2.***ˆEXEC�ROUTINE/*ˆREGISTERS�USED:�D0-D1/A0,A3-A6‚WORK�REGISTERS*˜D2-D7‹STAGING�REGISTERS**K**************************************************************************** IPCQEVNT:#ŠMOVEM.L�A3-A5,-(A7)‡SAVE�REGISTERS)ŠMOVE.L�CCBRQSTA(A5),A0„CALLER'S�TCB�ADDRŠSPC„2<ŠMOVE.L�#T0QEVNTI,D0‡WHEN�ONE�OR�MORE�INTERRUPTS�ARE�PENDING:ŠTST.B‚CCBINL(A5)‰USE�THE�QEVNTI�ENTRY�POINT.�ELSE�USE�THE ŠBNE.S‚IOHQ4ŽQUEVNTT�ENTRY�POINTŠMOVE.L�#T0QEVNTT,D0 IOHQ4…TRAPƒ#0ŠSPC„2"ŠBRA.S‚IOHQ5ŽBRANCH�IF�QUEUEING�OK&ŠMOVEM.L�(A7)+,A3-A5‡RESTORE�REGISTERS7ŠMOVE.L�(A7),CCBQVER1(A5)‚SAVE�CALLERS�ADDRESS�FOR�DBUGŠBRA.S‚IOHQRTN IOHQ5…EQU„*&ŠMOVEM.L�(A7)+,A3-A5‡RESTORE�REGISTERS)ŠCLR.L‚CCBQVER1(A5)‡CLEAR�Q�ERROR�ADDRESS IOHQRTNƒEQU„*ŠRTS‰PAGE***"* DISK ERROR CROSS-REFERENCE TABLE**ˆSTRUCTURE:�-�POSITION*“-�IOCB�ERROR�CODE*“-�UPDATE�FLAG*%*ˆUPDATE�FLAG:‚BIT�0�-�LENGTH�OF�XFER*–BIT�1�-�PSN�PROVIDED**DERXREF‚DC.B„0,1‘(0)�NO�ERROR"‰DC.B„ISTACRC,2‹(1)�DATA�CRC�ERROR)‰DC.B„ISTAWP,0Œ(2)�DEVICE�WRITE�PROTECTED#‰DC.B„ISTANR,0Œ(3)�DEVICE�NOT�READY*‰DC.B„ISTADDM,2‹(4)�READ�DELETED�DATA�MARK'‰DC.B„ISTAIE,0Œ(5)�LOGICAL�UNTT�#�ERROR'‰DC.B„ISTAIE,0Œ(6)�INVALID�DISK�ADDRESS!‰DC.B„ISTARES,0‹(7)�RESTORE�ERROR$‰DC.B„ISTADME,2‹(8)�RECORD�NOT�FOUND&‰DC.B„ISTAMRK,2‹(9)�ADDRESS�MARK�ERROR&‰DC.B„ISTADMA,0‹($A)�DMA�CHANNEL�ERROR#‰DC.B„ISTACSM,0‹($B)�CHECKSUM�ERROR‰DC.B„ISTADB,0Œ($C)�DEVICE�BUSY!‰DC.B„ISTACHN,0‹($D)�CHANNEL�BUSY!‰DC.B„ISTAIE,0Œ($E)�INDETERMINATE%‰DC.B„ISTACNT,0‹($F)�CONTROLLER�ERROR"‰DC.B„ISTAUNR,0‹($10)�DEVICE�ERROR ‰DC.B„ISTASEK,0‹($11)�SEEK�ERROR‰DC.B„ISTANR,0Œ($12)�NO�DEVICE-‰DC.B„ISTACFG,0‹($13)�DEVICE�CONNECT�CONFLICT$‰DC.B„ISTACMP,2‹($14)�DCOMPARE�ERROR,‰DC.B„ISTASPE,2‹($15)�SECTOR�WRITE�PROTECTED!‰DC.B„ISTABDS,2‹($16)�BBAD�SECTOR‰DC.B„ISTATO,0Œ($17)�TIMEOUT$‰DC.B„ISTAIE,0Œ($18)�INVALID�COMMAND#‰DC.B„ISTABUS,0‹($19)�DMA�BUS�ERROR'‰DC.B„ISTAMAP,0‹($1A)�DMA�MAPPING�ERROR*‰DC.B„ISTADMC,0‹($1B)�DMA�CONTROLLER�ERROR)DERXL„EQU…(*-DERXREF)/2-1…MAX�ERROR�VALUE‰PAGE***"* MCCM ERROR CROSS-REFERENCE TABLE**ˆSTRUCTURE:�-�POSITION*“-�IOCB�ERROR�CODE*“-�UPDATE�FLAG*%*ˆUPDATE�FLAG:‚BIT�0�-�LENGTH�OF�XFER**MERXREF‚DC.B„0,1‘(0)�NO�ERROR ‰DC.B„ISTACSM,1‹(1)�PARITY�ERROR‰DC.B„ISTABRK,1‹(2)�BREAK#‰DC.B„ISTANR,0Œ(3)�DEVICE�NOT�READY"‰DC.B„ISTACSM,1‹(4)�FRAMMING�ERROR'‰DC.B„ISTAIE,0Œ(5)�LOGICAL�UNTT�#�ERROR"‰DC.B„ISTADO,1Œ(6)�RECIEVE�OVERRUN'‰DC.B„ISTANR,1Œ(7)�PRINTER�OUT�OF�PAPER‰DC.B„ISTAIE,0Œ(8)�U5 NUSED‰DC.B„ISTAIE,0Œ(9)�UNUSED&‰DC.B„ISTADMA,1‹($A)�DMA�CHANNEL�ERROR‰DC.B„ISTACSM,0‹($B)�UNUSED‰DC.B„ISTAIE,0Œ($C)�DEVICE�BUSY‰DC.B„ISTAIE,0Œ($D)�UNUSED!‰DC.B„ISTAIE,0Œ($E)�INDETERMINATE)MERXL„EQU…(*-MERXREF)/2-1…MAX�ERROR�VALUE ‰END(M300DRV‚IDNT�45,0…MVME-300�(GPIB)�driver$‰TTL‚M300DRV:�MVME-300�(GPIB)�driverD*********************************************************************&*’GENERAL�PURPOSE�INTERFACE�BUS�DRIVER*D********************************************************************'*…5/31/84†BWNŽFive�bugs�found�and�fixed(*£1)�Typo�error�in�code�at�SP_TO.�Caused'*¦system�to�crash�while�serial�polling.&*¦Change�instruction�MOVEM�A3-A3,-(A7)*¦to�MOVEM.L�A3-A5,-(A7).(*£2)�IOSPB�and�DCB�pointers�not�setup�at *¦PROCM100�after�Serial�Polling.(*¦Moved�instructions�containing�pointers*¦up�two�instructions.(*£3)�The�fifth�instruction�of�HLTCMD�was'*¦changed�to�read�LEA.L�GPIBQEND(A5),A0(*£4)�Problem:�crashing�GPIB�driver�while!*¦waiting�for�a�DMA�read�to�start(*¦Diagnosis:�An�SRQ�interrupt�was�occur-(*¦ing�while�the�MVME300�was�in�DMA�mode.'*¦The�TMS9914A�interrupt�regs�were�tri-&*¦stated�at�this�point�and�thus�cannot *¦be�read.'*¦Solution:�To�disable�TMS9914a�intrpts%*¦prior�to�any�DMA�and�re-enable�when%*¦DMA�was�complete.‚Also�to�re-enable"*¦if�HaltIO�or�Bus�Error�occurred.*)*£5)�Fixed�length�buffer�transfers�of�DMA&*¦read�were�not�being�properly�set�up.&*¦The�IOS�buffer�length�was�being�used&*¦instead�of�the�sysgened�fixed�buffer!*¦length.�A�label�and�branch�were*¦modified�in�READDATA.*#*ˆ5/31/84ƒBWNŽVME/10�problem�fixed:'*¦The�driver�did�not�work�on�thw�VME/10&*¦because�the�off-board�RAM�is�seen�at"*¦different�addresses�by�the�68010*¦and�the�GPIB�device.&*¦Two�macros�were�created�to�correctly*¦translate�addresses.)*¦Near�label�INTR115�plus�7�instructions:**¦MOVE.B‚MARLSB(A1),D0*¦MOVE.L‚MENUCPOS(A5),A0* *¦changed�to:**¦MOVE.B‚MARLSB(A1),D0*¦GET_ON_BD‚D0*¦MOVE.L‚MENUCPOS(A5),A0*)*¦Near�label‚SETUPDMA�plus�5�instructions**¦MOVE.L„A0,D0*¦MOVE.B„D0,MARLSB(A1)* *¦changed�to:**¦MOVE.L„A0,D0*¦GO_OFF_BD‚D0*¦MOVE.B„D0,MARLSB(A1)*(*œThe�GET_ON_BD�and�GO_OFF_BDƒmacros�are*œdefined�in�9995..DUALPORT.MC.™D¢Aª'-*œThese�macros�require�substitutions�based�on*œthe�target�system.2*œThis�is�done�at�SYSgen�time,�with�equates�in�the**œSYSCMD.CD�file�and�DEF�statements�in�the*œM300DRV.LG�file.*9*ˆ10/16/84ŒSerial�Poll�processing�altered.‚Due�to�devices1*œthat�have�the�capability�to�toggle�the�SRQ�line**œSRQ's�were�being�missed�if�the�following1*œcircumstance�occurred.�A�device�toggled�the�SRQ/*œline,�we�started�to�poll,�another�device�(one0*œalready�polled)�generated�TRUE�SRQ,�we�reached0*œend�of�SRQ�polling�list�(once�around�the�BUS)..*œTo�remedy�this�problem,�code�was�inserted�at/*œPROCMSRQ�to�'loop'�the�BUS�twice�to�catch�any *œTRUE�SRQ's.*8*ˆ10/16/84ŒRemove�pending�SRQ's�at�power-on/bootup�time.*<*ˆ09/17/85ŒCorrect�problem�in�parallel�poll�mode,�PPIS�state*œin�module�M300INTR.AI.2*ˆ10/28/85ŒCorrect�problem�with�HALT�I/O�in�module*œM300CMND.AI�and�M300INTR.AI*7*ˆ12/12/85ŒInstall�NEW�Killer�modification�which�leaves,*œThe�Driver�ID�(Number)�and�Reason�(Number)2*œin�CRASHSAV�along�with�the�CCB�and�DCB�pointers.* SECTION 0 OPT BRL M300DRV:>�DC.L�INTRGPIB-M300DRV‡self�relative�interrupt�service�address<�DC.L�CMNDGPIB-M300DRV‡self�relative�command�service�addressC�DC.L�INITGPIB-M300DRV‡self�relative�initialization�service�address�DC.L�0–reserved*)*ƒreserve�space�for�CMR�allocation�of�CCB* XREF GPIBXP*�DC.W�GPIBXP‚#�of�extra�pages�for�this�CCB*@*…NOTE:�In�the�above�location�CMR�uses�the�first�byte�for�numberA*ƒof�extra�pages�needed,�but�since�only�5 a�word�may�XREF'ed�a�word>*ƒwas�reserved.�So�only�the�upper�byte�is�significant,�and�the*ƒnext�byte�will�be�0.*5�DC.B�0,0…next�14�bytes�reserved�for�later�use�by�CMR DC.L 0,0,0*5�DC.B�'121285'‚date�of�last�assembly�in�MMDDYY�format*�DC.B�'�'ƒreserved�for�patches*4�DC.B�'4'‚minimum�major�VERSAdos�revision�level�that*¦driver�is�compatible�with.**‚INCLUDE�FILES�(FOR�NOW)�ARE:**ˆNOLIST*ˆ9995.&.STR.SA*ˆ9995.&.CCB.EQ*ˆ9995.&.TCB.EQ*ˆ9995.&.LV5.EQ*ˆ9995.&.IOE.EQ*ˆ9995.&.NIO.EQ*ˆ9995.&.KILL.MC*ˆ9995.&.KILLDRV.EQ*ˆ9995.&.DUALPORT.MC*ˆLIST*ˆ9995.&.M300DRV.EQ *ˆM300TABL.AI *ˆM300INIT.AI *ˆM300INTR.AI *ˆM300CMND.AI* NOLIST�INCLUDEˆ9995.&.STR.EQ�INCLUDEˆ9995.&.CCB.EQ�INCLUDEˆ9995.&.TCB.EQ�INCLUDEˆ9995.&.DUALPORT.MC�INCLUDEˆ9995.&.KILL.MC�INCLUDEˆ9995.&.KILLDRV.EQ LIST TTL GPIB DRIVER - (LV5)�INCLUDEˆ9995.&.LV5.EQ LIST TTL GPIB DRIVER - (IOE)�INCLUDEˆ9995.&.IOE.EQ LIST TTL GPIB DRIVER - (NIO)�INCLUDEˆ9995.&.NIO.EQ LIST�INCLUDEˆ9995.&.M300DRV.EQ�INCLUDEˆM300TABL.AI�INCLUDEˆM300INIT.AI�INCLUDEˆM300INTR.AI�INCLUDEˆM300CMND.AI**‚GPIB�PATCH�AREA* DS.B 256 END NNNNN6M319DRVƒIDNTƒ45,0†VERSAdos�M319�Disk�Driver�-�12/13/852ŠTTL„M319DRV:‚VERSAdos�M319�Disk�Driver�-�12/13/85J***************************************************************************,* IPC -- REV. 1.05 02JUN80 (TB59) STEVE BALL8*�IPC‰2.00�02NOV81�(TL09)�JIM�SMITH�-�SPLIT�IPC�FROM�CMR2*�IPC‰2.01�01FEB82�(TL09)�JIM�SMITH�-�VECTOR�CHAIN.*�IPC‰2.02�23FEB82�(TL09)�JIM�SMITH�-�IOCB�USE7*�IPC‰4.00�01SEP82ˆMARC�BRIEL-�CONFIGURE�CLASS�REQUESTS7*�M315DRV…5.00�19MAY83ˆRONI�WOOD�-�CHANGED�FOR�M315�IPC>*�M315DRV…5.01�7JULY83ˆMARCO�SCHMIDT�-�PATCHES�TO�5.00�CHANGES*¡DISK�CONTROLLER�BOARD. *¡USED�IPCDRV�AS�A�BASE.‚DELETED*¡ALL�REFERENCE�TO�MCCM�STUFF.*¡ALL�OTHER�CHANGES�ARE�MARKED.?*�M315DRV…5.01�06DEC83ˆJULIE�HOBAN�-�CHANGES�MARKED�BY�11/17/83=*�M315DRV…5.01�24JAN84ˆJULIE�HOBAN�-�BUG�FIXES�EFFECTING�INIT*¯CHANGES�MARKED�BY�01/24/848*�M315DRV…5.01�27JAN84ˆJUTTA�KINDERMANN�-�CHANGES�TO�THE*´PARAMETER�DEF.�PART�AND*´THE�CONFIGURE�DISK�PART*´ALL�CHANGES�ARE�MARKED�BY*¸'�01/27/84�'.>*�M315DRV…5.10�23MAR84ˆFRANZ�MARSCHNER‚-�CHANGE�TO�THE�COMMAND*´SERVICE�PART�TO�ENABLE*´USE�IN�THE�VME/10�SYSTEM*´ADDED�TWO�XREF'S�TO*´SATISFY�VME/10�HARDWARE*´DEPENDENCIES*´ALL�CHANGES�ARE�MARKED�BY*¸'�03/28/84�'.<*�M315DRV…5.20�09MAY84ˆJULIE�HOBAN†-�FIX�TO�CONFIGURE�LENGTH*´TABLE:�CHANGES�MARKED�BY*¸'�05/09/84�'.:*�M315DRV…5.30�27AUG84ˆJULIE�HOBAN†-�MODIFIED�TO�USE�MACRO*´DUALPORT.MC�TO�ACCESS*´OFF�BOARD�RAM�ADDRESSES.8*�M315DRV…5.31�17OCT84ˆDICK�VANDERLINƒ-�CONFIGBLK�OFFSET6 *´DEFINATION(SYMBUG�PROBLEM)<*�M315DRV…5.32�26NOV84ˆJULIE�HOBAN†-�CONFIGURATION�CHECK�$47*´ADDED�-�SAME�AS�VME320.O*********************************************************************************!*�M319DRV…2.00ƒMAY�85ˆALOIS�FERTL*B*�M319DRV…2.10ƒDEC�85‚Install�NEW�Killer�modification�which�leaves,*œThe�Driver�ID�(Number)�and�Reason�(Number)2*œin�CRASHSAV�along�with�the�CCB�and�DCB�pointers.**™Changed�for�IDTC�VME319**‰List�of�Changes*«²6»$Ã\Ë0Ó1Û:ãLë5ó1û:C CBA#5+J38;5C0K5S [,cBk4s-{3ƒ4‹6“5›H?*‰-�The�driver�uses�the�simple�command�channel�protocol�without*‹ACK/NAK�handling.@*‰-�Byte�#�3�in�configuration�status�block�indicating�the�driver@*‹code�is�redefined�to�indicate�the�type�of�hard�disk�controller=*‹(XEBEC�or�ADAPTEC)�connected�to�the�IDTC.�This�byte�is�also<*‹used�to�indicate�a�Floppy�Tape�device.�The�controller�code8*‹is�used�in�configuration�requests�to�the�VME319�board.A*‰-�Stepping�rates�were�implemented�for�hard�disks�to�support�the?*‹'buffered�step'�feature�of�XEBEC�S1410A�and�ADAPTEC�ACB�4000.A*‰-�The�driver�is�interrupt�driven�(wait�loop�of�M315DRV�removed)=*‰-�There�is�no�command�queuing�used.�If�the�channel�is�busy,9*‹control�is�passed�back�to�calling�program�with�a�status*‹indicating�'Channel�busy'.?*‰-�The�updating�of�configuration�parameters�is�now�done�on�the<*‹Interrupt�Side�of�the�Driver.�This�saves�the�configuration9*‹tables�in�case�the�VME319�firmware�is�not�accepting�the>*‹proposed�configuration.�(Problen�of�mounting�a�foreign�disk)<*‰-�The�driver�acxeps�four�hard�disks�connected�to�one�IDTC.;*‹The�disks�were�decodet�from�the�device�number�within�DCB.3*‹Device�#�0�and�1:„Drive�0�and�1�on�controller�#�03*‹Device�#�2�and�3:„Drive�0�and�1�on�controller�#�17*‰-�The�driver�supports�a�Cipher�525�Floppy�Tape�drive.D*‰-�Sector�#3�of�the�first�segment�on�this�Tape�contains�information@*‹stored�by�MVME319�firmware.�This�sector�must�never�be�written.A*‹To�ensure�this,�an�offset�is�added�to�each�Random�Record�NumberA*‹provided�by�VERSAdos.�The‚number�of�sectors�per�segment�is�used *‹offset.B*‰-�If�a�CONFIGURATION/STATUS�Request�for�the�Floppy�Tape�occures,A*‹a�read�of�sector�#3�is�issued�to�the�MVME319.�Reading�sector�#3=*‹initializes�the�Media�Defect�Table�of�the�firmware.�It�also7*‹provides�the�number�of�sectors�available�on�the�tape.*!*�M319DRV‚2.1‚14NOV85‚ALOIS�FERTL'*�-�Maximum�device�number�reduced�to�8.,*�-�Test�for�write�with�CRC�check�corrected.6*�-�Update�flag�for�'record�not�found'�error�corrected!*’to�return�PSN�of�defect�sector.'*£all�changes�marked�by�'�11/14/85�AF�'***=*†******‚Many�parts�of�the�M315DRV�were�used�without�changes.<*ŽAlso�the�comments�related�to�this�sections�is�not�changed.*;*‰NOTE�-----�Many�comments�in�this�driver�refer�to�the�time0*”'currently'.‚This�refers�to�the�time�frame�May.*”and�June�1983.‚It�also�refers�to�this�driver3*”only�in�association�with�the�M315�disk�controller6*”board�and�all�changes/additions�for�that�board�only.*.* USER REQUEST SIDE FOR IPC COMMAND PROCESSING*9*ƒPURPOSE:‚VALIDATE�AND�PASS�IPC�COMMAND�INFORMATION�FROM#*�USER�TO�IPC,�68000�SHARED�MEMORY.**ƒENTRY:‚JSR�FROM�CMR�HANDLER*‹JSR�FROM�INTERRUPT�HANDLER*5*ƒEXIT:‚RTS�-�PARAMETER�BLOCK�VALIDATION�STATUS�IN�D0**ƒEXEC�ROUTINES�CALLED:‚QEVENTT**ƒCODE�IS�RE-ENTRANT*H*-----------------------------------------------------------------------**ŠPAGE *‚Included�Macro�file**ˆ9995.&.DUALPORT.MC**‚Included�equate�files:*ˆ9995.&.TRACE.EQ*ˆ9995.&.STR.EQ*ˆ9995.&.TCB.EQ*ˆ9995.&.CCB.EQ*ˆ9995.&.IOE.EQ*ˆ9995.&.NIO.EQ*ˆ9995.&.LV5.EQ*ˆ9995.&.KILL.MC*ˆ9995.&.KILLDRV.EQ*ŠINCLUDE�9995.&.DUALPORT.MCŠNOLIST ŠTTL�TRACE.SAŠINCLUDE�9995.&.TRACE.EQŠNOLISTŠTTL…96 995.&.STR.EQŠINCLUDE�9995.&.STR.EQŠNOLISTŠTTL…9995.&.TCB.EQŠINCLUDE�9995.&.TCB.EQŠNOLISTŠTTL…9995.&.CCB.EQŠINCLUDE�9995.&.CCB.EQŠNOLISTŠTTL…9995.&.IOE.EQŠINCLUDE�9995.&.IOE.EQŠNOLISTŠTTL…9995.&.NIO.EQŠINCLUDE�9995.&.NIO.EQŠNOLISTŠTTL…9995.&.LV5.EQŠINCLUDE�9995.&.LV5.EQŠNOLISTŠTTL…9995.&.KILL.MCŠINCLUDE�9995.&.KILL.MCŠNOLISTŠTTL…9995.&.KILLDRV.EQŠINCLUDE�9995.&.KILLDRV.EQŠLISTŠPAGE5ŠTTL„VERSADOS�M319�DISK�DRIVER�VERSION�2.1�-�12/13/85* ŠSECTION�0**$*…EQUATES�FOR�TESTING�VECTOR�NUMBERS*#AVECTLOƒEQU„25‘LOWEST�AUTO�VECTOR�#$AVECTHIƒEQU„31‘HIGHEST�AUTO�VECTOR�##UVECTLOƒEQU„64‘LOWEST�USER�VECTOR�# IPCORG„EQU„*ŠPAGE*6* IPC COMMAND PACKET FORMAT (AS SEEN IN SHARED MEMORY)*4*ˆNOTE:‚The�IPC�driver�never�used�the�packet�ID�byte0*�for�anything�-�the�value�was�always�zero.‚This0*�driver�currently�does�the�same�thing�-�however3*�the�packet�ID�now�is�the�address�modifier�for�the.*�read/write�buffer�addresses.‚If�the�value�is2*�zero�the�MVME319�firmware�uses�a�default�address2*�modifier�-�regular�global�memory.‚Otherwise,�the2*�value�in�packet�ID�is�used�by�the�MVME319�as�the1*�address�modifier�to�use.‚This�is�set-up�for�the4*�future�when�several�processor�boards�are�using�one0*�MVME319�disk�controller�board.‚This�supplies�a0*�way�for�the�disk�controller�to�use�the�correct*�memory�locations. ŠOFFSET�0IPCSTX„DS.Bƒ1*2�START�OF�TEXTIPCPID„DS.Bƒ1*2�PACKET�IDIPCPKSZƒDS.Bƒ1*2�PACKET�SIZE IPCPHDVƒDS.Bƒ1*2�PHYSICAL�DEVICE%IPCCHCMƒDS.Bƒ1*2�CHANNEL�COMMAND�TYPEIPCDVCMƒDS.Bƒ1*2�DEVICE�COMMAND$IPCNBKSƒDS.Bƒ2*2�#BLOCKS�TO�TRANSFERIPCBKSZƒDS.Bƒ2*2�BLOCKSIZE*IPCBUFAD‚DS.Bƒ4*2�68000�ADDRESS�(PHYSICAL)IPCCKSMƒDS.Bƒ2*2�CHECKSUM$IPCCMPRM‚DS.Bƒ4*2�COMMAND�PARAMETERSIPCETX„DS.Bƒ1*2�ETX�LOCATION*9*ˆUIPC�CONFIGURATION�PACKET�-�BOARD�LEVEL�-�COMMAND�$5000*2*ˆThis�is�a�new�packet�set�up�for�the�MVME310�UIPC4*ˆconcept.‚It�passes�basic�information�to�the�board.4*ˆThe�current�impemetation�in�this�driver�is�to�pass4*ˆthe�interrupt�vector�number�to�the�disk�controller3*ˆboard.‚If�this�packet�is�not�sent,�the�board�uses4*ˆa�default�value�of�vector�number�64.�Only�one�byte5*ˆcurrently�contains�a�value,�the�rest�are�zeroed�out6*ˆand�reserved�for�future�use.‚The�command�code�is�$505*ˆand�currently�implemented�function�code�is�00�-�for1*ˆUIPC�configuration�and�control.‚This�command�is3*ˆcompletely�unrelated�to�the�configure�command�the0*ˆdriver�receives�from�VERSAdos.‚This�command�is7*ˆsent�by�the�driver�to�the�board�in�the�initialization7*ˆportion.‚Interrupts�are�inhibited�during�execution�of5*ˆthis�command.‚The�initializer�polls�til�the�command8*ˆis�complete.�If�the�command�fails,�the�board�is�marked*ˆdown�in�the�CCB.*‰OFFSET�IPCNBKSIPCVECT‚DS.Bƒ1*2�vector�number;IPCATTR‚DS.Bƒ1*2�attribute�byte�simple�or�extended�protocol)IPCRESV1�DS.Bƒ4*2�reserved�for�future�use)IPCRESV2�DS.Bƒ4*2�reserved�for�future�use)IPCRESV3�DS.Bƒ4*2�reserved�for�future�use)IPCRESV4�DS.Bƒ4*2�reserved�for�future�use)IPCRESV5�DS.Bƒ4*2�reserved�for�future�useIPCVETX‚DS.Bƒ1*2�ETX�location*<*‰UIPC�Drive/Media�configuration�packet�-�command�code�$4008*9*‰This�command�is�used�to�tell�the�board�how�the�floppies<*‰and�hard�disks�are�configured.‚It�is�sent�on�behalf�of�the6*‰driver�receiving�either�a�configuration�command�or�a?*‰default�configuration�command�from�VERSAdos.‚This�is�normally:*‰done�during�boot�time�by�IOI,�once�for�each�drive.‚Mount;*‰and�Init�also�issue�these�commands.‚If�these�commands�are:*‰not�sent�to�the�board�the�board�assumes�several�defaults<*‰depending�on�the�disk�size.‚The�M319�disk�controller�knows?*‰if�the�floppy�is�single�or�double�track�density�by�the�number*‰of�sectors�per�track.*+*‰The�defaults�assumed�for�8"�floppies�are:B*‰MOTOROLA�format,�double�sided,�single�density,�128�byte�sectors,=*‰77�cylinders,�no�interleaving,�no�spiral�offset,�26�sectors *‰per�track./*‰The�defaults�assumed�for�5�1/4"�floppies�are:D*‰IBM�format,�double�sided,�double�d7 ensity,�96TPI,�256�byte�sectors,=*‰80�cylinders,�no�interleaving,�no�spiral�offset,�16�sectors *‰per�track.*B*‰The�physical�device�numbers�for�floppies�are�04,�05,�06,�and�07.**‰FLOPPY�DISK�CONFIGURE�PACKET*ŠOFFSET�IPCNBKS$IPCFATR0‚DS.Bƒ1*2�attributes�byte�#0*(*‰bit�definitions�of�attributes�byte�#0:*G*‚bit�0�=�0�=�if�a�compensation�value�is�specified�it�is�write�pre-comp?*Š1�=�if�a�compensation�value�is�specified�it�is�read�post-comp=*‚bit�1�=�0�=�compensation�value�is�specified‚(byte�$F�value))*Š1�=�compensation�value�is�not�specified*‚bit�2�=�0�=�5�1/4"�diskette=*Š1�=�8"�diskette‚(�if�26�or�52�sectors/track�diskette�is�8")*‚bit�3�=�not�defined#*‚bit�4�=�0�=�single�sided�diskette*Š1�=�double�sided�diskette**‚bit�5�=�0�=�single�density�(FM�encoding)#*Š1�=�double�density�(MFM�encoding)*‚bit�6�=�0�=�no�spiral�offset*Š1�=�spiral�offset*‚bit�7�=�0�=�IBM�formatting*Š1�=�MOTOROLA�formatting$IPCFATR1‚DS.Bƒ1*2�attributes�byte�#1(*‰bit�definitions�of�attributes�byte�#1:B*‚bits�0,1,2�=�stepping�rate.�If�zero�the�M319�uses�6�milliseconds-*�for�8"�and�6�milliseconds�for�5�1/4"�disks.* *ž8"‘5�1/4"*!*�=�001‡3�millisecs.‰6�millisecs."*�=�010‡6�millisecs.ˆ12�millisecs.#*�=�011†10�millisecs.ˆ20�millisecs.#*�=�100†15�millisecs.ˆ30�millisecs.*"IPCFSPTƒDS.Bƒ1*2�sectors�per�track6IPCFSIDƒDS.Bƒ1*2�#�of�sides�-�either�01�or�02�is�valid5IPCFSLGƒDS.Bƒ2*2�sector�length�in�bytes�-�either�128,"*§256,�512�or�1024.‚Currently�only'*§128�and�256�are�being�used.‚The�board)*§does�double�reads�for�sector�length�128IPCFNC„DS.Bƒ2*2�#�of�cylinders8IPCFPCNƒDS.Bƒ2*2�1st�cylinder�with�compensationƒ01/27/84#IPCFNU„DS.Bƒ4*2�not�used�-�reserved!IPCFIF„DS.Bƒ1*2�interleave�factor$IPCFNU1ƒDS.Bƒ1*2�not�used�-�reserved$IPCFNU2ƒDS.Bƒ2*2�not�used�-�reserved$IPCFNU3ƒDS.Bƒ4*2�not�used�-�reservedIPCHFETX‚DS.Bƒ1*2�ETX�location***‚Floppy�Tape�configure�Packet*ŠOFFSET�IPCNBKSIPCTNU1ƒDS.Bƒ1*2�not�used'IPCTTYPƒDS.Bƒ1*2�Device�type�$80�=�Tape7IPCTNSEC‚DS.Bƒ1*2�Number�of�sectors�per�segment�on�TapeIPCTNU2ƒDS.Bƒ1*2�not�used-IPCTSSZƒDS.Bƒ2*2�physical�sector�size�on�tapeIPCTNU3ƒDS.Bƒ4*2�not�usedIPCTNU4ƒDS.Bƒ4*2�not�used%IPCTSKIP‚DS.Bƒ1*2�skip�factor�on�tapeIPCTNU5ƒDS.Bƒ4*2�not�usedIPCTNU6ƒDS.Bƒ2*2�not�usedIPCTNU7ƒDS.Bƒ1*2�not�usedIPCTETXƒDS.Bƒ1*2�ETX�location**9*‰The�layout�and�associated�values�are�different�for�hard:*‰disks�from�the�floppy�disks.‚If�this�command�is�not�sent;*‰to�the�controller�or�if�the�values�in�the�packet�are�zero"*‰the�following�defaults�are�used:@*‰4�heads,�256�byte�sectors,�256�cylinders,�128�pre-compensationA*‰value,�128�reduced�write�current,�and�7�bits�of�ECC�data�burst.7*‰This�actually�defines�an�8"�10�megabyte�(unformatted)*‰Winchester�disk.*D*‰The�physical�device�numbers�for�hard�disks�are�00,�01,�02,�and�03.**‰HARD�DISK�CONFIGURE�PACKET*ŠOFFSET�IPCFSPT,IPCHSPTƒDS.Bƒ1*2�#�of�sectors/track…01/27/84IPCHNOHƒDS.Bƒ1*2�#�of�heads'IPCHSLGƒDS.Bƒ2*2�sector�length�in�bytesIPCHNC„DS.Bƒ2*2�#�of�cylinders1IPCHPC„DS.Bƒ2*2�write�pre-compensation�cylinder�#2IPCHRWCƒDS.Bƒ2*2�reduced�write�current�cylinder�#.&IPCHECCƒDS.Bƒ1*2�ECC�data�burst�lengthIPCHNU„DS.Bƒ1*2�not�used!IPCHIF„DS.Bƒ1*2�interleave�factorIPCHNU1ƒDS.Bƒ1*2�not�usedIPCHNU2ƒDS.Bƒ2*2�not�used2IPCHATRƒDS.Bƒ1*2�attributes�byte�for�stepping�rateIPCHNU3ƒDS.Bƒ1*2�not�used!IPCHCTYP‚DS.Bƒ1*2�controller�typeIPCHNU4ƒDS.Bƒ1*2�not�used#*§The�remaining�fields�are�the�same!*§as�the�floppy�configure�packet.** FORMAT TRACK PACKETŠOFFSET�IPCBUFAD'IPCFPSNƒDS.Bƒ4*2�PHYSICAL�SECTOR�NUMBERIPCFETXƒDS.Bƒ1*2�ETX�LOCATION** FORMAT DISK PACKETŠOFFSET�IPCNBKSIPCDETXƒDS.Bƒ1*2�ETX�LOCATION** REQUEST STATUS PACKETŠOFFSET�IPCNBKSIPCRETXƒDS.Bƒ1*2�ETX�LOCATION* * IPC RETURN (COMPLETION) PACKET* ŠOFFSET�0RTNSTX„DS.Bƒ1*2�START�OF�TEXTRTNPID„DS.Bƒ1*2�PACKET�I.D.RTNPKSZƒDS.Bƒ1*2�PACKET�SIZE RTNPHDVƒDS.Bƒ1*2�PHYSICAL�DEVICE RTNCHCMƒDS.Bƒ1*2�CHANNEL�COMMANDRTNSTCMƒ7 DS.Bƒ1*2�STATUS�COMMANDRTNSTVLƒDS.Bƒ2*2�STATUS�VALUERTNSTPRƒEQU„*’STATUS�PARAMETERS** IPC NORMAL COMPLETION EVENT*ŠOFFSET�RTNSTPRRTNBLKSƒDS.Bƒ2*2�NO.�OF�BLOCKSRTNBKSZƒDS.Bƒ2*2�BLOCK�SIZE#RTNDADRƒDS.Bƒ4*2�68K�MEMORY�ADDRESS** DISK ERROR COMPLETION EVENT*ŠOFFSET�RTNSTPR%RTNSECNƒDS.Bƒ4*2�ENDING�SECTOR�NUMBER** DISK STATUS RETURN*ŠOFFSET�RTNSTPRRTNDSTAƒDS.Bƒ2*2�DEVICE�STATUS RTNLSECƒDS.Bƒ4*2�LOGICAL�SECTORS*‰OFFSET�RTNSTPRRTNSTAD‚DS.B…4*2’DEVICE�STATUS** IPC MEM MAPPED EQUATES*;*‚The�MVME319�does�not�have�an�IPC�interrupt�byte,�nor�does;*‚it�have�a�reset�interrupt�byte.�Every�byte�written�to�the=*‚command�channel�interrupts�the�board.‚All�references�to�the=*‚software�interrupt�are�deleted�in�the�driver.‚If�the�driver>*‚determines�a�need�for�a�reset,�the�board�is�marked�in�error.=*‚The�driver�used�to�try�to�issue�a�reset�if�it�found�a�fatal@*‚error�-�such�as�the�command�packet�from�the�IPC�was�clobbered.*'IPCIMB1ƒEQU„$101�68000�TO�IPC�WRITE�BOX%IPCIAB1ƒEQU„$103�68000�TO�IPC�ACK�BOX#IPCIM1„EQU„$105�68000�COMMAND�WRITE'IPCIMB2ƒEQU„$181�IPC�TO�68000�WRITE�BOX%IPCIAB2ƒEQU„$183�IPC�TO�68000�ACK�BOX!IPCIM2„EQU„$185�IPC�COMMAND�WRITE* * STRUCTURE FOR DEVICE NO. TABLE*9*�The�address�of�this�table�is�in�the�CCB.‚The�memory�for<* this table gets allocated in the initialization section of>*�the�driver.‚The�length�is�dependent�on�#�of�devices�and�each<*�entry�length.‚The�number�of�devices�is�now�set�to�12.‚Each>* entry pertains to a disk - the disk device number is used to?* determine where in the table the entry is; ie, drive 0 is theF*�1st�entry,�drive�1�the�2nd,�etc.‚The�complete�IOCB�for�configurationF* is saved in this table - it is defined as the current configuration.>* The default configuration is save in the DCB for each drive.* ‰OFFSET�0LUFLG„DS.Bƒ2–ENTRY�FLAGLUDCB„DS.Bƒ4–DCB�ADDRESSLUIOCBƒDS.Bƒ4–IOCB�ADDRESSLUTCB„DS.Bƒ4–TCB�ADDRESSLUBADRƒDS.Bƒ4–BUFFER�ADDRESS.ACTIVEƒDS.Bƒ1–ACTIVE�FLAG�-�USED�FOR�CONFIGURE$MOUNTED‚DS.Bƒ1–MOUNTED/DISMOUNT�FLAG,CONFGBLK�EQU„*-IOSATW�OFFSET�TO�CONFIG�BLOCK6LUCONFƒDS…(IOSDRSV-IOSATW)/2…configure�parameter�block(LUENTRY‚EQU„*–LENGTH�OF�DEVICE�NO.�ENTRY** EQUATES FOR 'LUFLG'*LUFEOFƒEQU„0“EOF�PENDINGLUFHLTƒEQU„1“HALT�PENDING"LUFXFRƒEQU„2“DATA�TRANSFER�REQUEST(LUFCFGƒEQU„3“This�is�a�configure�request3LUFCFGD‚EQU„4“The�configure�request�is�for�defaults5LUFTSRƒEQU„5“This�is�a�status�Request�for�Floppy�TapeLUFACTƒEQU„15’ACTIVE�DEVICE** MISCELLANEOUS EQUATES*STX‡EQU„$02�start�packet�codeETX‡EQU„$03�end�packet�codeACK‡EQU„$06�ack�codeNAK‡EQU„$15�nak�code9EXCCP…EQU„$00�attribute�extended�command�channel�protocol7SICCP…EQU„$80�attribute�simple�command�channel�protocol-ADAPCNTƒEQU„$02�identifies�ADAPTEC�controller*TAPECNTƒEQU„$80�identifies�TAPE�controller1TPIFSL„EQU„1’length�of�information�sector�on�tape7TPIFSN„EQU„3’sector�number�of�information�block�on�tape0LUMAX…EQU„8’MAXIMUM�DEVICE�NO.�VALUEƒ11/14/85�AF3SECOFF„EQU„4’OFFSET�TO�NO.�OF�SECTORS�IN�CONFIG�TBL(RTNGDC„EQU„$70�NORMAL�STATUS�PACKET�CODE,RTNHLT„EQU„$71�HALT/ABORT�STATUS�PACKET�CODE+RTNSTA„EQU„$72�SOLICITED�STATUS�PACKET�CODE"RTNGDS„EQU„$0000ŽGOOD�STATUS�VALUE,SPKT†EQU„$0200ŽFIRST�2�BYTES�OF�EVERY�PACKETDLUPAGE„EQU„(LUMAX*LUENTRY+256)/256�NO.�OF�PAGES�FOR�DEVICE�NO.�TABLE+SECSIZƒEQU„$100“SYSTEM�REQUIRED�SECTOR�SIZE'IOPKSZ„EQU„21”READ�OR�WRITE�PACKET�SIZE'STPKSZ„EQU„7•STATUS�REQUEST�PACKET�SIZE#CNPKSZ„EQU„29”CONFIGURE�PACKET�SIZE$FDPKSZ„EQU„7•FORMAT�DISK�PACKET�SIZE&FTPKSZ„EQU„15”FORMAT�TRACK�PACKET�SIZEHLTPKSZƒEQU„7•HALT�PACKET�SIZEIOEVCD„EQU„1•I/O�EVENT�CODE*DSKATM„EQUƒ$031F�supported�attributes�mask)IOATM…EQUƒ$031F�supported�attributes�mask/NVALATMƒEQUƒ$FFFF-DSKATMˆunsupported�attributes+DSKPRMM„EQUƒ$DBF3�supported�parameters�mask)IOPRM†EQUƒ$DBF3�supported�parameters�mask0NVALPRMƒEQU„$FFFF-DSKPRMM‡unsupported�parameters$VDOSRSZ‚EQU‡256‘VERSAdos�sector�sizeLCDS8 CTBT�EQU‡7@LCDSCTSZ�EQU‡1<‰MOVE.B‚#SICCP,IPCATTR(A1)�set�simple�command�channel�protocol ‰CLR.LƒD1*‰MOVEP.L�D1,IPCRESV1(A1)„clear�unused�area*‰MOVEP.L�D1,IPCRESV2(A1)„clear�unused�area*‰MOVEP.L�D1,IPCRESV3(A1)„clear�unused�area*‰MOVEP.L�D1,IPCRESV4(A1)„clear�unused�area*‰MOVEP.L�D1,IPCRESV5(A1)„clear�unused�area ‰MOVE.B�#ETX,IPCVETX(A1)„set�ETX7‰MOVE.L‚CCBCHB(A5),A1†restore�memory�mapped�I/O�address'‰INHIB–inhibit�interrupts�on�this�board:‰MOVE.B‚#$80,IPCIMB1(A1)ƒsend�message�waiting�to�the�board* *‰poll�for�the�completition�byte*5IPCI30ƒMOVE.B‚IPCIMB2(A1),D1…get�message�waiting�flag9 (‰BEQ.SƒIPCI30�branch�til�something�there*2*ˆreceived�message�waiting�-�see�if�packet�is�good*0‰CLR.BƒIPCIMB2(A1)ˆclear�the�mesage�waiting�flag(‰CMP.Bƒ#STX,RTNSTX+IPCIM2(A1)ƒis�it�STX?-‰BNE.SƒIPCIERRŒbranch�if�no�-this�is�an�error ‰CLR.LƒD0-‰MOVE.B‚RTNPKSZ+IPCIM2(A1),D0‚get�packet�size"‰SUB.Lƒ#1,D0Žmake�it�zero�relative)‰LSL.Lƒ#1,D0Žaccount�for�every�other�byte,‰ADD.Lƒ#IPCIM2,D0‰add�in�the�offset�to�start5‰CMP.Bƒ#ETX,0(A1,D0.L)„does�the�message�end�with�ETX?(‰BNE.SƒIPCIERRŒbranch�if�no�-�hard�error8‰MOVEP.W�RTNSTVL+IPCIM2(A1),D0ƒget�returned�status�value-‰BNE.SƒIPCIERRŒbranch�if�an�error�is�returned* *‰init�done*IPCI50ƒUNMASK•enable�interrupts ‰RTS‘RETURN**ˆSomething�was�wrong�with5*ˆthe�message�format�or�an�error�status�was�returned.!*ˆMark�the�board�down�and�return.*6IPCIERR‚BSETWƒ#CCBFGER,CCBFG(A5)�set�error�flag�in�CCB6‰OR.W„#(1<*ˆAPPROXIMATELY�225�INSTRUCTIONS�EXECUTED�TO�GET�TO�THIS�POINT *ˆ(600�us).*J***************************************************************************IOHUSER:** CHECK FOR RESET*ƒIF�RESET,�DO�IT�AND�GET�OUT*)ŠCMP.B‚#XDREST,XIOSCD(A2)�TEST�RESET�BYTE#ŠBNE.S‚IOH01000‹BRANCH�IF�NOT�RESETŠBSR„CMRRESTŒCALL�RESET�ROUTINEŠBRA„IPCUSRTN‹RETURN*(* CONVERT LOGICAL PB ADDRESS TO PHYSICAL*IOH01000‚CLR.L‚D5,ŠMOVE.L�XIOCPK(A2),D6†ADDR�OF�COMMAND�PACKET+ŠMOVE.W�XIOPLN(A2),D5†LENGTH�OF�COMMAND�PKT"ŠMOVE.L�CCBTASKA(A5),A1„SET�UP�TCB ŠBSR„IOHADRCKŠBRA.S‚IOH01010‹GOOD�RETURNŠNOP—BAD�LENGTH�RETURN(ŠMOVE.B�#ISTAIP,D1‰SET�UP�IOS�ERROR�CODE ŠBRA„ABORT5IOH01010‚MOVE.L�D6,A3ŽCOMMAND�PACKET�PHYSICAL�ADDRESS*$* RETURN IF CHANNEL IS IN ERROR MODE*ŠBTSTW‚#CCBFGER,CCBFG(A5)2ŠBEQ.S‚IOH01020‹BRANCH�IF�NOT�MARKED�IN�ERROR�MODE)ŠMOVE.B�#ISTACDN,D1ˆSET�UP�IOS�ERROR�CODE ŠBRA„ABORT*E* If there is a command on the VME319 which is not finished yet, give,* back status "CHANNEL BUSY" to calling task*IOH01020‚EQU„*.ŠMOVE.L�CCBCHB(A5),A4†MEMORY�MAPPED�BASE�TO�A4ŠMOVE.B�CCBICNT(A5),D0&ŠBEQ.S‚IOH01030‹branch�if�channel�free*4* Channel is not free -- give user back busy status.*(ŠMOVE.B�#XSTBSY,D0‰SET�UP�IOS�ERROR�CODE ŠBRA„IPCUSRTNŠPAGEK****************************************************************************(*‚FIND�THE�COMMAND�IN�THE�COMMAND�TABLE.* IOH01030‚EQU„*)ŠMOVE.L�XIOUID(A2),A4†PICK�UP�DCB�POINTER8ŠMOVE.L�CCBTASKA(A5),CCBTASKB(A5)�SET�UP�BUFFER�TASK�TCB-ŠMOVEQ‚#NUMCMDS-1,D0†Set�up�the�loop�counter./ŠLEA„CMDTBL,A0ŠA0�<--�address�of�command�table./ŠMOVE.W�IOSFCT(A3),D6†Set�up�user�command�code. 8CMDSRCHƒCMP.W‚(A0)+,D6‹Search�the�table�for�the�command.ŠDBEQƒD0,CMDSRCH‰* 3ŠBNE.S‚CMDERR�If�we�found�the�command�in�the�table,8ŠADD.L‚#JMPOFF-2,A0‡get�the�corresponding�entry�from�the5ŠMOVE.W�(A0),D0Œjump�table�and�jump�to�the�routine�to"ŠJMP„(A0,D0.W)Šhandle�the�command.ŠSPC„2>CMDERR„MOVE.B�#ISTAIF,D1ŠThe�command�wasn't�found�in�the�table2ŠBRA„ABORTŽso�exit�with�an�invalid�function�error.ŠPAGEM*******************************************************************************‰REQUEST�STATUS2*‰This�command�is�a�request�status�to�the�MVME319.:*‰It�is�to�return�the�current�configuration�to�the�caller.*(*‰Entry:�A2�=�address�of�CMR�param�block*�A3�=�address�of�user's�IOCB*�A4�=�address�of�DCB*�A5�=�address�of�my�CCB*�A6�=�address�of�user's�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory*™and�address�of�dev: ice�tableM******************************************************************************REQSTAT:6ŠMOVE.Lƒ#IOSDLN,D5Šlength�of�configure�parameter�block<ŠMOVE.LƒIOSDBP(A3),D6‡logical�address�of�configure�para.�blk+ŠBSR†BUFADDR�get�the�physical�address�of�it<ŠMOVE.LƒD6,CCBPTR(A5)‡save�phys.�addr�of�configure�para.�blk ŠCLR.L„D6,ŠBSR„DEVTBL�get�get�device�table�entry�stuff%ŠMOVE.L‚A0,A1�address�of�top�of�table"ŠADD.LƒD0,A1�address�of�this�entry-ŠMOVE.L�A2,D7Žsave�address�of�CMR�param�block/ŠLEA…LUCONF(A1),A2ˆaddress�of�this�config�blockŠCLR.L‚D5‘clear�for�later�use/ŠBSR.S‚STATCONF‹STATCONF�sets�up�A0�to�point�to&*£the�IOSATM�field�of�the�users�status%*£parameter�block.‚It�also�determines&*£the�drives�device�status�and�sets�up(*£the�first�group�of�fields�in�the�users*£status�parameter�block.9L0110…EQU„IOATM<<16ŠSet�IOSATM�field�and�the�IOSPRM�field?ŠMOVE.L�#L0110+IOPRM,(A0)+�in�the�users�status�para.�block.‚The%*£values�we�return�are�significant�to*£this�driver.L0120…EQU„IOSDLN-IOSATWL0121…EQU„L0120/2L0122…EQU„L0121*2*ŠMOVEQ‚#L0121-1,D0ˆnumber�of�words�to�move;L0130…MOVE.W�(A2)+,(A0)+ˆcopy�current�configuration�to�userŠDBRAƒD0,L01307ŠCMP.B‚#TAPECNT,DCBDKC+IOSDRC(A4)�is�this�a�tape�device*ŠBEQ.S‚RDTINF•yes�-‚read�information�block*²to�get�the�number�of�sectors*²available�on�TapeŠCLR.L„D1’set�for�good�return"ŠMOVE.L�D7,A2Žget�back�the�address.ŠBRA†ABORT�use�abort�to�queue�event�and�returnŠPAGEL*****************************************************************************-*‰Read‚the�Information�Block�of�a�Floppy�Tape*>*‰This�subroutine�is�called�if�a�Config/Status�Request�occuresE*‰for�a�Floppy�Tape�device.�After�the�Format�command�the�VME319�Firm-C*‰ware�writes�information�about�bad�Segments�and�the�number�of�goodA*‰sectors�to�the�fourth�sector�of�the�tape.�A�read�of�this�sectorB*‰causes�the�VME319�Firmware�to�update�its�own�Tables�and�provides@*‰the�number�of�good�sectors�on�Tape�to�update�the�Device�Tables*‰in�this�driver.*+*‰entry:�A1�=�pointer�to�device�table�entry*�A4�=�address�of�DCB*�A5�=�address�of�CCB*L*****************************************************************************RDTINF:9ŠMOVE.W�#TPIFSL,CCBBLKS(A5)‚Set�number�of�sectors�to�read9ŠLEA„CCBTIBL(A5),A2…Get�address�of�buffer�for�this�sector0ŠMOVE.L�A2,CCBPTR(A5)†Set�up�destination�address?ŠMOVE.L�#TPIFSN,CCBRRN(A5)�Set�up�number�of�irst�sector�to�read ŠCLR.L‚D63ŠBSETƒ#LUFTSR,D6‰Set�status�request�for�Floppy�Tape"ŠBSETƒ#LUFACT,D6‰Set�device�activeŠMOVE.W�D6,LUFLG(A1) ŠBSR„SETPKT�Set�up�packet�header%ŠMOVE.W�#XREAD,D1ŠSet�up�Read�command%ŠBSR„DSKCMD�Set�up�in�Command�Channel ŠMOVE.L�D7,A2 ŠBRA„NRMEXITŠPAGEL***************************************************************************** *‰STATUS/CONFIGURE�COMMON�CHORES*6*‰This�subroutine�performs�functions�common�to�status,,*‰configure,�and�default�configure�commands.*+*‰entry:‚A1�=�pointer�to�device�table�entry!*‘A2�=�IOSATW�field�in�CCB�or�DCB*‘A3�=�physical�address�of�IOCB*‘A5�=�physical�address�of�CCB*M***************************************************************************** STATCONF:7ŠMOVE.L�IOSDBP(A3),D6†get�physical�address�of�the�first!*§location�of�the�users�configure*§parameter�block)ŠMOVE.L�#IOSDLN,D5‰parameter�block�length0ŠMOVE.L�A1,-(A7)‹save�device�table�entry�pointer0ŠBSR„BUFADDRŒconvert�logical�to�physical�address3ŠMOVE.L�(A7)+,A1‹restore�device�table�entry�pointerSTATCON1‚MOVE.L�D6,A0Žsave�it&ŠMOVE.L�D6,CCBPTR(A5)†save�in�CCB�also1ŠTST.B‚MOUNTED(A1)ˆif�the�disk�is�not�mounted�set'ŠSEQ.B‚(A0)�XDSNRB�BIT�of�device�status-ŠAND.B‚#1<*‰call�to�the�board�is�complete.‚The�mounted/dismounted�optionB*‰is�checked�to�see�if�the�DCB�must�be�changed�for�mount/dismount.*(*‰Entry:�A2�=�address�of�CMR�param�block*�A3�=�address�of�user's�IOCB*�A4�=�address�of�DCB*�A5�=�address�of�my�CCB*�A6�=�address�of�user's�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory*™and�device�tableM****************************************************************************** CONFIGUR: 3ŠMOVE.L�#IOSDLN,D5‰configure�parameter�block�length<ŠMOVE.LƒIOSDBP(A3),D6„logical�address�of�configure�para.�blk(ŠBSR†BUFADDRŠconvert�to�physical�address?ŠMOVE.LƒD6,CCBPTR(A5)„save�the�phy.�addr�of�configure�para.�blk ŠCLR.L„D6&ŠBSET„#LUFACT,D6ˆset�for�active�device0ŠBSET„#LUFCFG,D6ˆset�this�is�a�configure�request%ŠBSR†DEVTBL‹set�up�device�table�entry!ŠMOVE.LƒA0,A1Œtop�of�device�tableŠADD.L„D0,A1Œtop�of�this�entry9ŠMOVE.LƒA2,D7Œmust�save�the�parameter�block�addr�11/17/83/ŠLEA…LUCONF(A1),A2…sart�of�this�configure�block2L0220…EQU„DCBDKC+IOSWTO†write-timeout�field�in�DBC>2,D1†get�VERSAdos�sector�size‰ASL.L…#2,D1�make�it�real3L0326„EQU‡IOSREC-IOSDRSV†point�to�record�size�field ‰MOVE.W„D1,L0326(A0)ˆand�save�it*‰DIVU†D0,D1�see�if�record�size�makes�sense‰SWAP†D1*‰AND.W…#(1<�error�01/27/84%CONERR46�EQU‡$46‘disk�size�error�code'‰MOVEQ…#CONERR46,D3ˆset�up�just�in�case‰MOVEQ.Lƒ#0,D5�clear�for�use*8*ˆCompute�the�number�of�sides�on�a�floppy�disk�to�use�in6*ˆcalculation�of�logical�sectors.‚Determine�rigid�disk9*ˆor�floppy�from�the�#IOARDISC�bit�o�the�attributes�word.6*ˆIf�a�floppy,�set�D5�=�1�for�a�single-sided�diskette.9*ˆDetermine�the�actual�number�of�sides�from�#IOADSIDE�bit6*ˆof�the�attributes�word.‚If�double-sided,�set�D5�=�2.*2LC000„EQU‡IOSATW-IOSDRSV†offset�to�attributes�word0‰BTSTW…#IOARDISC,LC000(A0)�see�if�floppy�or�hard"‰BNE.S…LC010�branch�if�a�hard�diskM********* Configuration check for floppies only ***************** JH 11/26/845CONERR47�EQU†$47”Get�the�error�code�that�we'll�use�to6‰MOVEQ„#CONERR47,D3‰indicate�that�we�don't�support�the)*¦proposed�configuration.�We'll�keep�this(*¦error�code�in�D3.B�as�we�make�computa-$*¦tions�regarding�the�configuration. 9‰BTSTWƒ#IOADDEN,LC000(A0)„Single-�or�double-data�density? ‰BEQ.SƒCNF172?EQ375„EQU…IOSPSM-IOSDRSVŠAt�this�time,�Versados�and�this�driver5‰CMP.Wƒ#256,EQ375(A0)ˆsupport�the�double�data-density5‰BNE…CONERRORŽconfiguration�with�256�bytes�per�sector.‰BRA.SƒCNF175�ONLY�and�the�single�data-densityCCNF172ƒCMP.Wƒ#128,EQ375(A0)ˆconfiguration�with�128�bytes�per�sector‰BNE…CONERRORŽONLY.6CNF175ƒMOVEQƒ#CONERR46,D3ŠRestore�disk�size�error�codeN********************************************************************* 11/26/84‰ADDQ.L„#1,D5�set�for�floppy8‰BTSTW…#IOADSIDE,LC000(A0)�see�if�single�or�double�sided#‰BEQ.S…L0845�branch�if�single�sided"‰ADDQ.L„#1,D5�set�for�double�sided‰BRA.S…L0845�and�go�continueLC010>L0840„EQU‡IOSHDS-IOSDRSV†offset�to�number�of�heads�-�hard�disk(‰MOVE.B„L0840(A0),D5ˆget�number�of�heads‰PAGE*<*ˆCompute�the�total�numberr�of�logical�sectors�for�an�entireC*ˆhard�disk�as�IOSSPT*IOSHDS*IOSTRK,�and�IOSSPT*< �#�of�heads�*IOSTRK?*ˆfor�a�floppy.‚The�order�of�multiplication�is�important�as�theB*ˆfirst�2�factors�are�both�one-byte�values,�thus�assuring�that�the.*ˆintermediate�product�doesn't�exceed�16�bits.*0L0845„MULU†D5,D2�#�of�heads�by�sectors�per�track7L0850„EQU‡IOSTRK-IOSDRSV†offset�the�number�of�cylinders.‰MULU.W„L0850(A0),D2ˆtimes�number�of�cylinders?CNERROR2�BEQ‡CONERROR‹cannot�be�zero�-�some�value�must�be�wrong6‰CMP.L…#LSNMASK,D2‰see�if�bigger�than�largest�possible1‰BHI‡CONERRORŒbranch�if�too�big�-�error�somewhere*@*ˆIf�the�disk�is�a�double�density�floppy�disk,�subtract�IOSSPT/2=*ˆfrom�the�total�number�of�logical�sectors�to�account�for�the<*ˆfact�that�the�sectors�in�track�zero�are�single�density�and*ˆhalf�the�size�of�the�rest.*2L0860„EQU‡IOSATW-IOSDRSV†offset�to�attributes�word/‰BTSTW…#IOADDEN,L0860(A0)‚see�if�double�density$‰BEQ.S…L0870�branch�if�single�desity)‰LSR‡#1,D0�get�(sectors/track)/2‰01/27/846‰BHI.S…SUBSETR�if�even,�use�(sectors/track)/2‚01/27/843‰ADDQ†#1,D0�if�odd,�incr.(sectors/track)/2‚01/27/843SUBSETR‚SUB.L…D0,D2�get�rid�of�1/2�track�of�sectors3CNERROR3�BLS‡CONERRORŒbranch�if�less�than�0�-�error*>*ˆNow�lets�see�have�many�VERSAdos�sized�sectors�we�really�have*L0870„MOVE.L„D2,D0�sector�count‰CLR.W…D2’clear�for�use‰SWAP†D2$‰DIVU†D1,D2�divide�by�VDOSRSZ/IOSPSM5L0880„EQU‡IOSRSZ-IOSDRSV†offset�to�total�sector�count"‰MOVE.W„D2,L0880(A0)ˆand�save�half‰MOVE.W„D0,D2�do�for�the�rest ‰DIVU†D1,D2$‰MOVE.W„D2,L0880+2(A0)†save�the�rest‰PAGE*6*ƒNow�take�a�copy�of�users�updated�configuration�blockA*ƒWe�need�this�copy�to�update�the�configuration�in�the�DCB�or�our:*ƒown�device�table�in�the�interrupt�service�routine�if�the3*ƒVME319�board�has�agreed�to�our�new�configuration.*,L0328…LEA„CCBCNBE(A5),A2…bottom�of�save�area6EQ330…EQU„(IOSDRSV-IOSATW)/2-1�number�of�words�to�move$ŠMOVEQ‚#EQ330,D0Šset�up�loop�counterL0330…MOVEƒ-(A0),-(A2)ˆcopy-ŠDBRAƒD0,L0330‹A2�points�to�IOSATW�at�the�end*8*ˆThis�section�of�code�is�only�for�the�configure�command*6*ˆSee�if�this�is�a�mount,�dismount,�or�configure�only.:*ˆIf�IOSOPT�field�is�zero�this�is�a�mount�command.�Set�the:*ˆmounted�flag�to�indicate�this.‚If�the�IOPDMNT�bit�is�set;*ˆthis�is�a�dismount�and�we�have�to�tell�ourselves�that�and2*ˆVERSAdos�also.‚VERSAdos�will�then�know�to�change;*ˆback�to�default�configuration�and�the�volume�is�no�longer*ˆthere.*;‰BTSTW…#CCBFCF,CCBFG(A5)ƒsee�if�this�is�a�default�configure2‰BNE.S…L0830�branch�if�a�default�configure�command7‰MOVE.W„IOSOPT(A3),D0‡get�the�options�field�of�the�IOCB'‰BNE.S…L0820�branch�if�dismount�command#‰ST.B†MOUNTED(A1)‰set�mounted�field,L0820„ROL.W…#15-IOPDMNTB,D0…get�dismount�bit‰BPL.S…L0830�branch�if�mount$‰CLR.B…MOUNTED(A1)‰set�to�dismounted)‰ST.B†DCBCCF(A4)Šset�dismount�in�DCB�also3L0830„BSR‡STATCON1Œgo�update�device�status�and�type‰PAGE*@*ˆNow�build�the�packet�information�for�the�disk�controller�board*%‰BSR‡SETPKTŽset�initial�packet�header%‰MOVE.W„#XCONFIG,D1‰configure�command!‰MOVEP.WƒD1,IPCCHCM(A1)†to�packet8‰MOVE.L„CCBPTR(A5),A0‡get�user's�parameter�block�address1‰MOVE.B„#CNPKSZ,IPCPKSZ(A1)�29�byte�packet�length<‰CMP.B…#TAPECNT,DCBDKC+IOSDRC(A4)„see�fi�this�is�Floppy�Tape‰BEQ‡CONFT010–branch�if�Tape6‰BTSTW…#IOARDISC,IOSATW(A0)Šsee�if�floppy�or�hard�disk#‰BNE‡CONFH010Œbranch�if�a�hard�disk*(*ˆbuild�floppy�disk�configuration�packet*ˆdo�attributes�byte�0�first%*ˆA0�=�user's�parameter�block�address!*ˆA1�=�M319�shared�memory�address*!‰CLR.L…D1ˆbuild�attributes�byte�0'‰BTSTW…#IOASIZE,IOSATW(A0)�8"�or�5.25"?4‰BEQ.S…CONFF010‚branch�if�5.25�-�is�also�the�default‰BSET†#2,D1…set�for�8"�disketteA‰BRA.S…CONFF020‚leave�compensation�attrib.�bit�unchanged�01/27/84;CONFF010�BSET†#1,D1…set�no�compensation�for�5�1/4"‹01/27/84CONFF020�CLR.L…D2-‰MOVE.W„IOSPCOM(A0),D2…get�the�pre-comp�value.‰MOVEP.WƒD2,IPCFPCN(A1)�set�the�pre-comp�value2‰BTSTW…#IOADPCOM,IOSATW(A0)‚pre-comp�or�post-comp?8‰BEQ.S…CONFF030Œbranch�if�pre-�also�the�default�01/27/84%‰BSET†#0< ,D1�set�for�post-compensation1CONFF030�BTSTW…#IOADSIDE,IOSATW(A0)†single�sided?(‰BEQ.S…CONFF040Œbranch�if�single�sided�- ‰BSET†#4,D1�set�for�double�sided/CONFF040�BTSTW…#IOADDEN,IOSATW(A0)�FM�encoding?‰BEQ.S…CONFF050Œbranch�if�FM ‰BSET†#5,D1…set�for�MFM�encoding0CONFF050�TST.B…IOSSOF(A0)Šspiral�offset?�11/7/83*‰BEQ.S…CONFF060Œbranch�if�no�spiral�offset!‰BSET†#6,D1�set�for�spiral�offset.CONFF060�BTSTW…#IOAFRMT,IOSATW(A0)�IBM�format?‰BNE.S…CONFF070‚branch�if�IBM#‰BSET†#7,D1…set�for�Motorola�format5CONFF070�MOVE.B„D1,IPCFATR0(A1)…set�attributes�byte�0**ˆattributes�byte�1**‰MOVE.B„IOSSR(A0),D1ˆget�the�stepping�rate0‰BNE.S…CONFF080Œno�-�save�stepping�rate‡01/27/847‰BTSTW…#IOASIZE,IOSATW(A0)�yes�-�5�1/4"�or�8"?‹01/27/844‰BEQ.S…CONFF075Œ5�1/4",�use�stepping�code�1ƒ01/27/84-‰ADD.B…#1,D1�8",�use�stepping�code�2‡01/27/842CONFF075�ADD.B…#1,D1�stepping�code�1�or�2Š01/27/845CONFF080�MOVE.B„D1,IPCFATR1(A1)…set�the�stepping�rate**ˆrest�of�the�packet*0‰MOVE.B„IOSSPT(A0),IPCFSPT(A1)ˆsectors�per�track"‰MOVE.B„#1,D1™set�for�single�sided/‰BTSTW…#IOADSIDE,IOSATW(A0)�is�it�single�sided?&‰BEQ.S…CONFF090‚branch�if�single�sided"‰MOVE.B„#2,D1…set�for�double�sided-CONFF090�MOVE.B„D1,IPCFSID(A1)†set�#�of�sides%‰MOVE.W„IOSPSM(A0),D1‡get�sector�size'‰MOVEP.WƒD1,IPCFSLG(A1)†set�sector�size(‰MOVE.W„IOSTRK(A0),D1‡get�#�of�cylinders‰MOVEP.WƒD1,IPCFNC(A1)‡set�it ‰CLR.L…D1)‰MOVEP.LƒD1,IPCFNU(A1)‡clear�unused�bytes3‰MOVE.B„IOSILV(A0),IPCFIF(A1)…set�interleave�factor‰BRA.S…CONFH050“and�continue*&*ˆbuild�packet�for�hard�disk�configure*CONFH010�CLR.L…D1&‰MOVEP.WƒD1,IPCFATR0(A1)…no�attributes9‰MOVE.B„IOSSPT(A0),IPCHSPT(A1)ˆset�sectors/trackƒ01/27/84-‰MOVE.B„IOSHDS(A0),IPCHNOH(A1)ˆset�#�of�heads%‰MOVE.W„IOSPSM(A0),D0‡get�sector�size'‰MOVEP.WƒD0,IPCHSLG(A1)†set�sector�size)‰MOVE.W„IOSPCOM(A0),D0†get�pre-comp�value%CONFH020�MOVEP.WƒD0,IPCHPC(A1)‡set�it(‰MOVE.W„IOSTRK(A0),D0‡get�#�of�cylinders‰MOVEP.WƒD0,IPCHNC(A1)‡SET�IT:‰MOVE.W„IOSRWCC(A0),D0†get�specified�reduced�write�current(‰MOVE.W„IOSECC(A0),D1‡get�ECC�value�also?CONFH030�MOVEP.WƒD0,IPCHRWC(A1)†set�reduced�write�current�value‰MOVE.B„D1,IPCHECC(A1)†set�ECC"‰MOVE.B„#0,IPCHNU(A1)‡clear�unused+‰MOVE.B„IOSILV(A0),D0‡get�interleave�factor3CONFH040�MOVE.B„D0,IPCHIF(A1)‡set�interleave�factor,CONFH050�CLR.L…D0’use�to�clear�unused�fields‰MOVE.B„D0,IPCFNU1(A1)†not�used ‰MOVEP.WƒD0,IPCFNU2(A1)†not�used*3*ƒset�up�controller�type�and�step�rate�if�hard�disk*/ŠBTSTW‚#IOARDISC,IOSATW(A0)�is�this�a�hard�diskŠBNE.S‚CONFH060‹branch�if�yes6ŠMOVEP.L�D0,IPCFNU3(A1)„clear�unused�fields�for�floppyŠBRA.S‚CONFH070*ECONFH060‚MOVE.B�IOSSR(A0),IPCHATR(A1)ƒset�stepping�rate�for�hard�disc#ŠMOVE.B�D0,IPCHNU3(A1)Šclear�unused3ŠMOVE.B�IOSDRC(A0),IPCHCTYP(A1)�set�controller�type#ŠMOVE.B�D0,IPCHNU4(A1)Šclear�unused*)CONFH070�MOVE.B„#ETX,IPCHFETX(A1)ƒset�ETX!‰CLR.L…D1’set�for�no�errors�found3‰MOVE.L„D7,A2�restore�CMR�para�blk�addrƒJH�01/24/84*‰BRA‡NRMEXIT�go�send�the�packet�and�returnŠPAGE*)*ƒset�up�configure�packet�for�Floppy�Tape*:CONFT010�CLR.L…D1’clear�for�stting�unused�space�in�channel#‰MOVE.B„D1,IPCTNU1(A1)†clear�unused4‰MOVE.B„#TAPECNT,IPCTTYP(A1)�set�device�type�is�Tape<‰MOVE.B„IOSSPT(A0),IPCTNSEC(A1)‚set�#�of�sectors�per�segment#‰MOVE.B„D1,IPCTNU2(A1)†clear�unused%‰MOVE.W„IOSPSM(A0),D0‡get�sector�size0‰MOVEP.WƒD0,IPCTSSZ(A1)†set�physical�sector�size$‰MOVEP.LƒD1,IPCTNU3(A1)†clear�unused$‰MOVEP.LƒD1,IPCTNU4(A1)†clear�unused7‰MOVE.B„IOSILV(A0),IPCTSKIP(A1)‚set�segment�ship�faktor$‰MOVEP.LƒD1,IPCTNU5(A1)†clear�unused$‰MOVEP.WƒD1,IPCTNU6(A1)†clear�unused#‰MOVE.B„D1,IPCTNU7(A1)†clear�unused%‰BRA.S…CONFH070Œset�up�etx�and�return‰PAGEL******************************************************************************ˆCONFIGURATION�ERROR�ROUTINE*8*ˆControl�comes�here�is�there�is�a�detected�error�in�the*ˆconfiguration�command.*ˆentry:ƒD3�=�error�code0*‘D6�=�physical�address�of�users�parameter�block7*‘D7�=�physical�address�of�C= MR�parameter�block‡11/17/83.*ˆNote:„Must�restore‚D6�and�D5�before�exiting.*L**************************************************************************** CONERROR:4‰MOVE.L„CCBDTBL(A5),A0†device�table�address‚01/27/84‰MOVEQ.Lƒ#0,D0¥01/27/84,‰MOVE.B„DCBCDV(A4),D0‡device�number‰01/27/84-‰MULU†#LUENTRY,D0‰calculate�position„01/27/84/‰CLR.W…LUFLG(A0,D0.L)†unset�active�bit†01/27/84)‰MOVE.L„D6,A0…get�users�parameter�address%‰MOVE.B„D3,IOSDST(A0)‡save�error�code1‰MOVEQ…#ISTACNF+$FFFFFF00,D1‰set�major�error�code>*ˆMOVEM.Lƒ(A7)+,D5/D6‰restore�regs�-�not�used�for�319�01/27/842‰MOVE.L„D7,A2�including�CMR�para�blk�addrƒ11/17/83‰BRA‡ABORT�and�return‰PAGEL******************************************************************************‰READ�COMMAND*,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory*L*****************************************************************************READ:5ŠBSR„IOSCOMNŒDo�the�stuff�common�to�all�I/O�commands,7ŠMOVE.L�D6,CCBPTR(A5)†save�the�buffer�physical�address. ŠCLR.L‚D6&ŠBSETƒ#LUFXFR,D6ŒSET�DATA�TRANSFER�BITŠBSETƒ#LUFACT,D6ŒSET�ACTIVE�BIT%ŠBSR„DEVTBL�SET�UP�DEVICE�TABLE�ENTRYŠBSR„DSKPRM�VALIDATE�PARAMETERS/ŠBSR„SETPKT�SET�UP�PACKET�HEADER�IN�SHARED�MEM.ŠMOVE.Wƒ#XREAD,D1&ŠBSR†DSKCMDŽYES,�SET�UP�COMMAND�PACKETŠBRA†NRMEXIT�GO�FINISH�UPŠPAGEL******************************************************************************‰WRITE**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory**L*****************************************************************************WRITE:5ŠBSR„IOSCOMNŒDo�the�stuff�common�to�all�I/O�commands,7ŠMOVE.L�D6,CCBPTR(A5)†save�the�buffer�physical�address. ŠCLR.L‚D6&ŠBSETƒ#LUFXFR,D6ŒSET�DATA�TRANSFER�BITŠBSETƒ#LUFACT,D6ŒSET�ACTIVE�BIT%ŠBSR„DEVTBL�SET�UP�DEVICE�TABLE�ENTRYŠBSR„DSKPRM�VALIDATE�PARAMETERS/ŠBSR„SETPKT�SET�UP�PACKET�HEADER�IN�SHARED�MEM.<ŠBTSTW‚#DATWRC,DCBATT+2(A4)‚WRITE�WITH�VERIFY�FOR�THIS�DCB�? *¹11/14/85�AFŠBEQ.S„WRIT30ŽNO4ŠMOVE.Wƒ#XWRITC,D1ŠYES,�SET�UP�WRITE/VERIFY�COMMANDS ŠBRA.S„WRIT408WRIT30„MOVE.Wƒ#XWRITN,D1ŠSET�UP�WRITE/NO�VERIFY�COMMANDS 'WRIT40„BSR†DSKCMDŽSET�UP�COMMAND�PACKETŠBRA†NRMEXIT�GO�FINISH�UPŠPAGEH**************************************************************************ˆFORMAT�DISK�COMMAND*,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB* *‰Additional-*‰Registers‚A1�=�address�of�IPC�shared�memory**I**************************************************************************FORMAT: )‰BTSTWƒ#IOPFTRK,IOSOPT(A3)‚FORMAT�TRACK�?‰BEQ.SƒFORMT20ŽBRANCH�IF�NO*A*‚format�track�is�not�allowed�for�devices�connected�to�an�ADAPTEC'*‚or�for�the�FLOPPY�TAPE�---�check�this*)ŠMOVE.B�#ISTAIF,D1‰error�invalid�function1ŠCMP.B‚#ADAPCNT,DCBDKC+IOSDRC(A4)�is�this�ADAPTECŠBEQ„ABORTŽyes�error2ŠCMP.B‚#TAPECNT,DCBDKC+IOSDRC(A4)�or�FLOPPY�TAPE�?ŠBEQ„ABORTŽyes�error*!‰MOVE.L‚IOSRRN(A3),D1‰PICK�UP�RRN%‰BPL.SƒFORMT20�GOOD�ID�POSITIVE�VALUE/FORMT10‚MOVE.B‚#ISTARR,D1ŒSET�UP�IOS�ERROR�CODE ‰BRA…ABORT FORMT20‚CLR.LƒD6‰BSET„#LUFACT,D6ŒSET�ACTIVE�BIT%‰BSR…DEVTBL�SET�UP�DEVICE�TABLE�ENTRY5‰LEA‡LUCONF(A0,D0.L),A1‚GET�ADDRESS�OF�CONFIURE�BLOCK(‰BTSTW…#IOPFTRK,IOSOPT(A3)‚FORMAT�TRACK?‰BEQ.S…FORMT25ŽBRANCH�IF�NO3‰CMP.LƒSECOFF(A1),D1ŠSEE�IF�THIS�IS�BEYOND�THE�DISK*‰BLT.SƒFORMT25�BRANCH�IF�STILL�ON�THE�DISK*‰CLR.WƒLUFLG(A0,D0.L)ˆUNSET�THE�ACTIVE�BIT‰BRA‡FORMT10�AND�RETURN6FORMT25‚BSR…SETPKT�SET�UP�PACKET�HEADER�IN�SHARED�MEM. 0FORMT30ƒBTSTW„#IOPFTRK,IOSOPT(A3)‚FORMAT�TRACK�?ŠBNE.S„FORMT40�YESŠMOVE.Wƒ#XFDISK,D16ŠMOVEP.W‚D1,= IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDS#ŠMOVE.Bƒ#ETX,IPCDETX(A1)„SET�UP�ETX.ŠMOVE.Bƒ#FDPKSZ,IPCPKSZ(A1)�SET�UP�PACKET�SIZEŠBRA†NRMEXIT�GO�FINISH�UP FORMT40ƒMOVE.Wƒ#XFTRAK,D16ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDSŠMOVE.Wƒ#SECSIZ,D1)ŠMOVEP.W‚D1,IPCBKSZ(A1)†SET�UP�BLOCK�SIZE ŠCLR.L„D1*ŠMOVEP.W‚D1,IPCNBKS(A1)†ZERO�NO.�OF�BLOCKSŠMOVE.LƒIOSRRN(A3),D1"ŠMOVEP.L‚D1,IPCFPSN(A1)†SET�UP�PSN#ŠMOVE.Bƒ#ETX,IPCFETX(A1)„SET�UP�ETX.ŠMOVE.Bƒ#FTPKSZ,IPCPKSZ(A1)…SET�UP�PACKET�SIZEŠBRA†NRMEXIT�GO�FINISH�UPŠPAGEL*****************************************************************************C*‰ROUTINE�COMMON�TO�ALL�I/O�COMMANDS�(READ,�WRITE,�OUTPUT�W/�INPUT)**‚Entry:�A3�=�address�of�IOCB*‰A5�=�address�of�CCB**º £C¬>´<¼CÄKÌCÔ:ÜIä<ì<ô8ü:5 <E,$L*****************************************************************************IOSCOMN:?ŠBTSTW‚#IOPTSKB,IOSOPT(A3)�If�the�buffers�reside�in�a�different"ŠBEQ.S‚IOSC005Œtask�from�the�IOCB, 9ŠLEA„IOSTSK(A3),A0†Point�to�the�taskname�&�session�of�the7ŠTR0$.GETTCB‚,Œbuffer�owner�&�call�exec�to�get�address."ŠBRA.S‚OKTCBŽIf�it's�good,�branch.ŠNOP—If�it's�bad,7ŠMOVE.B�#ISTAADD,D1ˆset�status�in�IOCB�to�address�errorŠTST.L‚(A7)+Žadjust�stackŠBRA„ABORT�and�exit�to�CMR. :OKTCB…MOVE.L�A0,CCBTASKB(A5)„Save�physical�address�of�TCB. *<*‚Validate�the�info�in�the�IOCB�about�the�primary�buffer�and *‚convert�to�physical�addresses.*BIOSC005ƒMOVE.L�IOSSAD(A3),D6†D6�<--�buffer�physical�start�address.+ŠMOVE.L�IOSEAD(A3),D5†D5�<--�buffer�length.ŠSUB.L‚D6,D5Ž*ŠADDQ.L�#1,D5Ž*)ŠMOVE.L�D5,CCBLEN(A5)†Save�length�in�CCB. >ŠMOVE.L�CCBTASKB(A5),A1„A1�<--�address�of�TCB�of�buffer�owner. ŠBSR„IOHADRCK‹Check�the�address.$ŠBRA.S‚IOSC010ŒIf�it's�good,�branch.ŠNOP—If�it's�a�bad�base�addrŠTST.L‚(A7)+Žadjust�stack4ŠMOVE.B�#ISTAADD,D1ˆSet�IOCB�status�to�ADDRESS�ERROR2ŠBRA„ABORT�and�exit�with�appropriate�error�status. IOSC010ƒRTSŠPAGEK****************************************************************************/*‰VALIDATE�BUFFER�ADDRESS�&�CONVERT�TO�PHYSICAL*$*‰Entry:�D5�=�buffer�length�in�bytes-*�D6�=�buffer�logical�start�addr�(to�convert)*�A3�=�address�of�IOCB*�A5�=�address�of�CCB***‰Exit:‚D6ƒ=�buffer�physical�start�address*�D5ƒ=�buffer�length*K****************************************************************************BUFADDR:>ŠMOVE.L�CCBTASKB(A5),A1„A1�<--�address�of�TCB�of�buffer�owner. ŠBSR„IOHADRCK‹Check�the�address.$ŠBRA.S‚OKADDR2ŒIf�it's�good,�branch.ŠNOP—If�it's�a�bad�base�addrŠTST.L‚(A7)+Žadjust�stack4ŠMOVE.B�#ISTAADD,D1ˆSet�IOCB�status�to�ADDRESS�ERROR2ŠBRA„ABORT�and�exit�with�appropriate�error�status.OKADDR2ƒRTS—Return.ŠPAGEO*********************************************************************************ˆCHECK�DISK�PARAMETERS**%*‚Entry:�A0�=�address�of�device�table%*‰A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB,*‰D0=‚offset�in�device�table�for�this�device**O********************************************************************************DSKPRM:3‰LEA…LUCONF(A0,D0.L),A1„GET�ADDRESS�OF�CONFIGURE�PB%‰MOVE.W‚IOSOPT(A3),D1‰PICK�UP�OPTIONS+‰AND.Wƒ#IOPRAN,D1ŒRANDOM�OPTION�SPECIFIED�?‰BNE.SƒDSKPR10�YES(‰MOVE.B‚#ISTATM,D1ŒSET�UP�IOS�ERROR�CODE‰TST.Lƒ(A7)+‘ADJUST�STACK‰BRA…ABORT�ERROR�EXIT(DSKPR10‚MOVE.L‚IOSRRN(A3),D1‰PICK�UP�RRN#‰MOVE.L‚D1,CCBRRN(A5)†make�own�copy‰BPL.SƒDSKPR30�GOOD�RRN/DSKPR20‚MOVE.B‚#ISTARR,D1ŒSET�UP�IOS�ERROR�CODE DSKPR25‚TST.Lƒ(A7)+‘ADJUST�STACK*‰CLR.WƒLUFLG(A0,D0.L)‡SET�TO�DOING�NOTHING‰BRA…ABORT�ERROR�EXITŠSPC„2ADSKPR30ƒCMP.LƒSECOFF(A1),D1‡If�the�random�record�number�specified7ŠBLT.SƒDSKPR35‹in�the�IOCB�is�past�the�end�of�the�disk,2ŠMOVE.B�#I> STAEOV,D1ˆreturn�an�end-of-volume�error.ŠBRA.S‚DSKPR25ŠSPC„22DSKPR35‚MOVE.L‚CCBLEN(A5),D1‰PICK�UP�BUFFER�LENGTH"‰DIVS„#256,D1�CALC.�NO.�OF�SECTORS ‰MOVE.L‚D1,D2*‰AND.Lƒ#$FFFF0000,D2‰MUST�BE�WHOLE�SECTORS‰BEQ.SƒDSKPR40�ITS�OK5‰MOVE.B‚#ISTAADD,D1‹ERROR,�PARTIAL�SECTOR�NOT�ALLOWED‰BRA…DSKPR25�RETURN1DSKPR40‚MOVE.W‚D1,CCBBLKS(A5)ˆSAVE�NO.�OF�SECTORS2‰ADD.LƒCCBRRN(A5),D1‰CALC.�LAST�SECTOR�TO�TRANSFER‰CMP.LƒSECOFF(A1),D1‰RANGE�OK�?‰BLE.SƒDSKPR50�YES4‰MOVE.L‚SECOFF(A1),D1‰NO,�CALC.�MAX�SECTORS�CAN�READ‰SUB.LƒCCBRRN(A5),D1/‰MOVE.W‚D1,CCBBLKS(A5)ˆSAVE�SECTORS�TO�TRANSFER ‰BSET„#LUFEOF,D6ŒSET�EOF�PENDING-‰MOVE.WƒD6,LUFLG(A0,D0.L)„SET�IN�DEVICE�TABLE>DSKPR50‚CMP.Bƒ#TAPECNT,DCBDKC+IOSDRC(A4)‚is�this�a�Floppy�Tape!‰BNE.SƒDSKPR60Œno�-�nothing�to�do ‰CLR.LƒD1<‰MOVE.B‚IOSSPT-IOSATW(A1),D1‚get�number�os�sectors�per�track9‰ADD.LƒD1,CCBRRN(A5)‰add�the�offset�to�the�rand.�rec.�nr. DSKPR60‚RTS‰PAGEO********************************************************************************** SET UP DEVICE TABLE ENTRY**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‰D6�=�device�table�flag*N*******************************************************************************DEVTBL: ŠCLR.L‚D0(ŠMOVE.B�DCBCDV(A4),D0‰PICK�UP�DEVICE�NO. ŠCMP.B‚#LUMAX,D0�DEVICE�NO.�OK�?ŠIF‚‚THEN.S(ŒKILL.DRIVER�M319DRV_ID,BAD_DEVICE,A5,A4ŠENDI ŠMULUƒ#LUENTRY,D0‹CALC.�POSITION3ŠMOVE.L�CCBDTBL(A5),A0ˆPICK�UP�DEVICE�TABLE�POINTER(ŠTST.W‚LUFLG(A0,D0.L)ŠTHIS�DEVICE�FREE�?ŠBEQ.S‚DEVT010�YESŠTST.L‚(A7)+‘ADJUST�STACK+ŠMOVE.B�#ISTADB,D1ŒRETURN�DEVICE�BUSY�ERRORŠBRA„ABORT�ERROR�EXIT2DEVT010ƒMOVE.W�D6,LUFLG(A0,D0.L)‡UPDATE�TABLE�FLAG,ŠMOVE.L�A4,LUDCB(A0,D0.L)‡SET�UP�DCB�ADDRESS.ŠMOVE.L�A3,LUIOCB(A0,D0.L)†SET�UP�IOCB�ADDRESS6ŠMOVE.L�CCBTASKB(A5),LUTCB(A0,D0.L)�SET�UP�TCB�ADDRESS8ŠMOVE.L�CCBPTR(A5),LUBADR(A0,D0.L)�SET�UP�BUFFER�ADDRESS ŠRTSšRETURNŠPAGEJ***************************************************************************%*ˆSET�UP�PACKET�HEADER�IN�SHARED�MEM.**,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*,*‰Return�:�A1�=�address�of�IPC�shared�memory**I**************************************************************************SETPKT:%ŠMOVE.LƒCCBCHB(A5),A1‡MEM�MAPPED�ADDR)ŠLEA†IPCIM1(A1),A1‡SET�UP�MESSAGE�ADDRESSŠMOVE.Wƒ#SPKT,D1/ŠMOVEP.W‚D1,IPCSTX(A1)‡SET�UP�STX�AND�PACKET�ID0ŠMOVE.BƒDCBCDV(A4),D0‡get�device�numberŽ03/26/84*ŠCMP.B„#4,D0�number�4-7�is�floppy‹03/26/846ŠBGE.S„SETPKT10Œit's�a�floppy�-�nothing�to�do‚03/26/843ŠBCLRW„#1,D0�if�>=�2�then�on�controller�#1‚03/26/84ŠBEQ.S„SETPKT10Œno�03/26/84'ŠBSETW„#4,D0�set�controller�#1Ž03/26/84ASETPKT10‚MOVE.BƒD0,IPCPHDV(A1)†set�device�in�IPC-channel†03/26/84 ŠRTSšRETURNŠPAGEJ***************************************************************************)*‰SET�UP�DISK�PARAMETERS�IN�SHARED�MEMORY*&*‚Entry:�A1�=�address�of�SHARED�MEMORY%*‰A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB**‰D1�=�CHANNEL/DEVICE�commands*K****************************************************************************DSKCMD:6ŠMOVEP.W‚D1,IPCCHCM(A1)†SET�UP�CHANNEL/DEVICE�COMMANDSŠMOVE.WƒCCBBLKS(A5),D18ŠMOVEP.W‚D1,IPCNBKS(A1)†SET�UP�NO.�OF�BLOCKS�TO�TRANSFERŠMOVE.Wƒ#SECSIZ,D1)ŠMOVEP.W‚D1,IPCBKSZ(A1)†SET�UP�BLOCK�SIZEŠMOVE.LƒCCBPTR(A5),D1*A*ˆAdjust�the�address�if�an�offboard�offset�applies.…(JH*08/27/84)* ŠGO_OFF_BD�D16*‰CMPI.Lƒ#MEMTOP,D1ŠONBOARD�MEMORY�(VME/10)�?ƒ03/28/84*‰BGT.S„GOGON1ŽNOš03/28/845*‰ADDI.Lƒ#OFFST,D1‹YES�ADJUST�BUFFER�ADDRESSƒ03/28/84*¦FOR�VME/10’03/28/84=GOGON1„MOVEP.L‚D1,IPCBUFAD(A1)…SET�UP�BUFFER�ADDRESS‡03/28/84 ŠCLR.L„D1'ŠMOVEP.W‚D1,IPCCKSM(A1)†SET�UP�CHECKSUMŠMOVE.LƒCCBRRN(A5),D1#ŠMOVEP.L‚D1,IPCCMPRM(A1)…SET�UP�PSN> "ŠMOVE.Bƒ#ETX,IPCETX(A1)…SET�UP�ETX.ŠMOVE.Bƒ#IOPKSZ,IPCPKSZ(A1)�SET�UP�PACKET�SIZE ŠRTSšRETURNŠPAGEO******************************************************************************** *ˆNORMAL�EXIT*,*‚Entry:�A2�=�address�of�CMR�parameter�block*‰A3�=�address�of�IOCB*‰A4�=�address�of�DCB*‰A5�=�address�of�CCB*‰A6�=�address�of�users�TCB*I**************************************************************************NRMEXIT:** BUMP I/O PENDING COUNT*ŠMOVE.L�CCBTASKB(A5),A0-ŠADD.B‚#1,TCBIOCNT(A0)„BUMP�I/O�PENDING�COUNT** INTERRUPT THE IPC*0ŠMOVE.L�CCBCHB(A5),A1†SET�UP�SHARED�MEM.�POINTER (ŠMOVE.B�#$80,IPCIMB1(A1)ƒMESSAGE�WAITING0ŠADD.B‚#1,CCBICNT(A5)…BUMP�OUTSTANDING�INT�COUNT*#ŠCLR.L‚D0‘SET�UP�GOOD�RETURN�TO�CMR*7* USER REQUEST SIDE OF IPC ALWAYS EXITS FROM THIS POINT*IPCUSRTN‚EQU„*ŠRTS—RETURN�TO�MAINLINEŠPAGEJ*****************************************************************************ˆABORT�COMMAND�ROUTINE*%*’ENTRY:�A2�=�PARAMETER�BLOCK�ADDRESS*™A3�=�IOCB�PACKET�ADDRESS*™A4�=�ADDRESS�OF�DCB*™A5�=�ADDRESS�OF�CCB*™A6�=�ADDRESS�OF�CALLERS�TCB*™D1�=�IOS�ERROR�CODE*H*************************************************************************ABORT:)‰LEA‡CCBPKT(A5),A4‡SET�UP�QUEUE�WORK�AREA ‰MOVE.L„#6,D0�SET�UP�PACKET�SIZE"‰MOVE.L„XIOUID(A2),D2‡SET�UP�PB�ID‰AND.W…#$FF,D1!‰MOVE.W„D1,D3�SET�UP�STATUS�VALUE!‰MOVE.B„D1,IOSSTA(A3)‡UPDATE�IOCB$‰MOVE.B„#XPSNRM,D1ŠSET�UP�EVENT�TYPE‰BSR‡QEVNT�GO�QUEUE�EVENT5‰MOVE.L„XIOUID(A2),A4‡RESTORE�DCB�ADDRESSˆJH�01/24/84 ‰CLR.L…D0‰BRA‡IPCUSRTNŒRETURNŠPAGEF***********************************************************************B* SUBROUTINE TO CHECK ADDRESS BOUNDARIES TO SEE IF ENTIRELY WITHIN*ƒCALLING�TASKS�ADDRESS�SPACE.*#*�ENTRY:ƒD5‚-�NO.�OF�BYTES�TO�CHECK*ŠD6‚-�68000�ADDRESS�(LOGICAL)*ŠA1‚-�TCB�ADDRESS** EXEC ROUTINE#* REGISTERS USED: D0-D1,D3,D6/A0-A1**7*�EXIT:„D6�-�PHYSICAL�ADDRESS�OF�BUFFER�BASE�(IF�LEGAL)*ŠRETURN�TO�PC„FOR�GOOD�ADDRESS*”PC+2‚FOR�BAD�LENGTH*”PC+4‚FOR�BAD�ADDRESS*F*********************************************************************** IOHADRCK:$ŠBTSTƒ#0,D6ŽMUST�BE�ON�WORD�BOUNDARY(ŠBNE.S‚IOHADR6ŒBRANCH�IF�BAD�BUFFER�BASE ŠTST.L‚D5.ŠBEQ.S‚IOHADR8ŒDON'T�GO�TO�LOGPHY�WITH�0�COUNT/ŠMOVE.L�TCBTST(A1),A0†ADDRESS�OF�TASK�SEG�TABLE ŠTR0$.LOGPHY&ŠBRA.S‚IOHADR8ŒBRANCH�FOR�GOOD�ADDRESSŠNOP—error�bad�length-IOHADR6ƒADD.L‚#2,(A7)ŒADJUST�FOR�ERROR�RETURN IOHADR8ƒRTSŠPAGEI****************************************************************************‚CMR�RESET�ROUTINE8*ˆThe�MVME319�does�not�support�the�reset.�If�the�command8*ˆchannel�memory�is�incorrect�the�channel�is�marked�down9*ˆand�the�user�is�notified.‚All�the�code�to�actually�send;*ˆa�reset�to�the�board�is�commented�out.‚The�reset�was�used@*ˆby�the�UDC�and�FDC�to�try�to�recover�from�a�bad�shared�memory.*%*ˆENTRY:�A2�=�PARAMETER�BLOCK�ADDRESS*�A3�=�PACKET�ADDRESS*�A5�=�CCB�ADDRESS*�A6�=�CALLERS�TCB�ADDRESS*I**************************************************************************CMRREST:*/ŠMOVE.L�CCBCHB(A5),A4†SET�UP�SHARED�MEM�POINTER=* CLEAR ERROR MODE,WAITING FOR ACK, DEALT WITH ACK, EXIT FLAG&*‰CLR.L‚CCBNAKAD(A5)‡CLEAR�NAK�ADDRESS(*‰CLR.L‚CCBERAD1(A5)‡CLEAR�ERROR�ADDRESS*‰INHIB•INHIBIT�INTERRUPTSEŠAND.W�#-1-(1<ŠMOVE.B�IOSSPT-IOSATW(A4),D0�get�number�of�sectors�per�segment?ŠSUB.L‚D0,D1…reduce�by�number�of�sectors�in�se@ gment�because�the-*œfirst�segment�is�not�accessable�by�VERSAdos9ŠMOVE.L�D1,IOSRSZ-IOSATW(A4)�store�number�in�device�table'ŠMOVE.L�LUDCB(A2),A4‡address�of�the�DCB3ŠMOVE.L�D1,DCBSEC(A4)†also�set�up�number�of�sectors1ŠMOVE.L�LUBADR(A2),A4†address�of�users�CSB�buffer0ŠMOVE.L�D1,IOSRSZ(A4)†also�return�it�to�the�user&RQST10„CLR.L‚D1‘set�up�for�good�return*£next�is�normal�exitŠPAGEK****************************************************************************!*‚NORMAL�EXIT�FROM�INTERRUPT�TOUR*+*ˆENTRY:�A2�=�address�of�devide�table�entry*�A3�=�address�of�IOCB*�A5�=�address�of�CCB*K****************************************************************************INEXIT:&ŠMOVE.L‚#6,D0�SET�UP�EVENT�INFO�LENGTH)ŠMOVE.L‚LUDCB(A2),D2‰SET�UP�DCB�FOR�EVENT+ŠMOVE.W‚D1,D3�SET�UP�STATUS�VALUE�FOR�EVENT$ŠMOVE.B‚#XPSNRM,D1‹SET�UP�EVENT�TYPE+ŠLEA…CCBCPKT(A5),A4‡SET�UP�EVENT�BUILD�AREA#ŠBSR.SƒQEVNT�QUEUE�COMPLETION�EVENT)ŠCLR.WƒLUFLG(A2)ŒCLEAR�DEVICE�TABLE�ENTRY*5* DECREMENT I/O PENDING COUNT IF SOLICITED TYPE EVENT*7INEX010ƒMOVE.L�CCBCHB(A5),A4†RESTORE�SHARED�MEM�POINTER.ŠBTSTƒ#7,RTNSTCM+IPCIM2(A4)‚IS�THIS�SOLICITED?ŠBNE.S‚INEX020ŒBRANCH�IF�NO ŠMOVE.L�LUTCB(A2),A0‡TCB�ADDRESS2ŠSUB.B‚#1,TCBIOCNT(A0)„DECREMENT�I/O�PENDING�COUNT**ƒEVENT�COMPLETION*/INEX020ƒCLR.B‚IPCIMB2(A4)ˆclear�message�waiting.ŠCLR.W‚CCBRCNT(A5)ˆJUST�IN�CASE�A�RESET�WORKED*4* IPC INTERRUPT HANDLER ALWAYS EXITS FROM THIS POINT*IPCINRTN‚EQU„*6ŠSUB.L‚#1,CCBINL(A5)‰DECREMENT�INTERRUPT�NESTING�LEVEL/ŠMOVEM.L�(A7)+,D1-D7/A2-A4/A6ƒRESTORE�REGISTERS"ŠOR.W„#$01,SRŽSET�RETURN�CONDITION&IPCNIRTN‚RTSšBACK�TO�INTERRUPT�HANDLER‰PAGEK*****************************************************************************6* ROUTINE TO HANDLE 68000 DETECTED FATAL CHANNEL ERROR'*ƒSAVE�CALLING�ADDRESS�IN�CCB�FOR�DEBUG*ƒMARK�THE�CHANNEL�IN�ERROR*ƒQUEUE�EVENT�TO�CALLING�TASK*ƒRETURN@*ƒThis�routine�has�been�changed�for�the�MVME319.�This�board�doesC*ƒnot�contain�a�reset�interrupt,�therefore�the�board�is�immediately@*ƒmarked�down�instead�of�trying�to�recover�once�as�the�other�IPCC*ƒboards�do.‚The�unused�code�has�been�commented�out�-�but�left�here*ƒfor�informational�purposes.*+*ˆENTRY:�A2�=�address�of�devide�table�entry*�A3�=�address�of�IOCB(*�A4�=�address�of�IPC�shared�memory�base*�A5�=�address�of�CCB*K**************************************************************************** IPCUNSER:ŠINHIB,ŠMOVE.L�(A7),CCBERAD1(A5)‚SAVE�ERROR�ADDRESS3ŠOR.Wƒ#(1<�>¥@­?µ?½=Å9Í7Õ7Ý6å8í2õ:ý@  9 *K***************************************************************************K***************************************************************************K***************************************************************************K***************************************************************************‰PAGE‰OPT�CRE,PCS,BRS*>*ƒThese�variables�are�XREFed�in�the�link�chain�file�M320DRV.LG=*ƒand�allow�the�user�to�modify�certain�media/drive�parameters>*ƒwithout�having�to�re-assemble�the�driver.‚See�the�link�chain+*ƒfile�for�a�description�of�the�parameters.* ‰XREF�FRMT_SD ‰XREF�FRMT_DD ‰XREF�FRMT_HD ‰XREF�SETTM_5 ‰XREF�SETTM_8‰XREF�SETTM_HD ‰XREF�LDTM_5 ‰XREF�LDTM_8 ‰XREF�LDTM_HD‰XREF�TYP_SEEK **‰MISC�EQUATESB *3DRIVESƒEQU‡4“Total�number�of�drives�on�our�channel. **ƒXREF'S�from�DISKLIB*ŠXREF…DISK_INITŠXREF…DISK_COMMANDŠXREF…CHAN_DONE **‚Equate�files�included:* *‰INCLUDE‚9995.&.TCB.EQ*‰INCLUDE‚9995.&.STR.EQ*‰INCLUDE‚9995.&.CCB.EQ*‰INCLUDE‚9995.&.LV5.EQ*‰INCLUDE‚9995.&.IOE.EQ*‰INCLUDE‚9995.&.NIO.EQ*‰INCLUDE‚9995.&.DISKCCB.EQ*‰INCLUDE‚9995.&.DISKMEM.EQ*‰INCLUDE‚9995.&.DISK.EQ*‰INCLUDE‚9995.&.KILL.MC*‰INCLUDE‚9995.&.KILLDRV.EQ*‰INCLUDE‚9995.&.UTILITY.MCNNB*‰INCLUDE‚9995.&.DUALPORT.MCƒMacro�file�to�use�with�VMEbus�drivers**$*‰Include�the�standard�equate�files:*‰NOLIST‰INCLUDE‚9995.&.TCB.EQ‰INCLUDE‚9995.&.STR.EQ‰INCLUDE‚9995.&.CCB.EQ‰INCLUDE‚9995.&.LV5.EQ‰INCLUDE‚9995.&.IOE.EQ‰INCLUDE‚9995.&.NIO.EQ‰INCLUDE‚9995.&.KILL.MC‰INCLUDE‚9995.&.KILLDRV.EQ‰INCLUDE‚9995.&.UTILITY.MC‰INCLUDE‚9995.&.DUALPORT.MC ‰TTL†DISK.EQ‰LIST‰INCLUDE‚9995.&.DISK.EQ‰TTL†DISKCCB.EQ‰INCLUDE‚9995.&.DISKCCB.EQ‰TTL†M320DRV.SA‰PAGE/‰OFFSETƒDCCBDDP�Continue�with�channel-dependent*¦CCB�variable�space.  M*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%* *%%%Å%%%*B*%%%„Device-dependent,�channel�related,�variables�start�here.‰%%%* *%%%Å%%%**%%%™(CCB�SPACE)¡%%%* *%%%Å%%%*M*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*  /SPURINT‚DS.B…1–We�use�this�variable�for�keeping'*¦count�of�any�spurious�interrupts�that'*¦should�occur�during�execution�of�this%*¦driver.‚When�the�number�of�spurious$*¦interrupts�reaches�$80,�we�set�the*¦channel�down. 2ECATABLE�DS.L…1–The�variable�ECATABLE�contains�the$*¦address�of�the�ECA�Table�contained!*¦in�global�memory.‚The�ECA�Table$*¦contains�pointers�to�the�four�ECAs *¦for�the�four�available�drives.‰PAGE7IOQUEUE‚DS.L…DRIVES‘The�IOQUEUE�is�used�to�indicate�the(*¦I/O�activities�(if�any)�that�are�lined'*¦up�waiting�to�be�done�under�interrupt**¦control�by�the�VME320�interrupt�handler.'*¦Since�we�can�never�have�more�than�one'*¦command�pending�for�any�single�drive,(*¦the�IOQUEUE�has�exactly�enough�entries%*¦to�accommodate�one�I/O�activity�for)*¦each�drive�that�a�VME320�controller�can*¦possibly�control. $*¨An�entry�in�the�IOQUEUE�is�a�long-)*¦word�pointer�that�contains�the�physical(*¦address�of�a�drive's�variable�block�in%*¦the�drive-associated�area�of�global&*¦memory�and�the�values�in�the�drive's**¦variable�block�describe�the�I/O�activity$*¦that�must�be�done�with�that�drive. )*§The�VME320�driver�puts�entries�into�the'*¦IOQUEUE�in�the�order�in�which�the�I/O)*¦requests�are�received,�so�no�drive�on�a&*¦VME320�channel�has�priority�over�any'*¦other�drive�on�the�same�channel.‚When&*¦the�VME320�driver�receives�a�new�I/O%*¦request,�the�driver�simply�puts�the&*¦entry�for�that�request�into�the�next *¦available�slot�of�the�IOQUEUE. )*§When�the�VME320�driver�completes�an�I/O&*¦activity�under�interrupt�control,�it(*¦moves�all�remaining�IOQUEUE�entries�up%*¦by�one�position�in�the�IOQUEUE.‚The(*¦physical�movement�of�queue�entries�may%*¦sound�like�a�poor�approach�at�first&*¦glance,�but�it�turns�out�to�be�quite%*¦good.‚The�use�of�wrapping�front�and$*¦rear�queue�pointers�with�position-(*¦independent�code�is�rather�cB umbersome,$*¦and�the�physical�movement�of�queue%*¦entries�is�a�better�technique�for�a"*¦short�queue�such�as�the�IOQUEUE.‰PAGE1IOQCNTƒDS.W…1–This�variable�contains�the�count�of#*¦the�number�of�bytes�in�the�active)*¦entries�in�the�IOQUEUE,�so�IOQCNT�=�4*N)*¦where�N�is�the�number�of�active�entries(*¦in�the�IOQUEUE.‚The�value�of�IOQCNT�is$*¦always�in�the�range�from�0�through&*¦through�4*DRIVES,�so�we�could�easily&*¦use�a�single�byte�for�this�variable.(*¦However,�we�use�a�full�word�for�coding%*¦convenience.‚Notice�that�IOQCNT�can%*¦be�used�as�an�offset�pointer�to�the&*¦next�available�entry�in�the�IOQUEUE. H*‚The�following�fields�are�used�by�the�CHECKERR�routine.‚The�fields�thatH*‚hold�variables�due�to�a�command�that�had�an�error�are�NOT�cleared�when'*‚a�command�completes�without�an�error. 1RETRY_FLAG�DS.B„1•This�variable�is�the�retry_flag'*¦and�is�set�when�we�issue�driver�retry%*¦commands�to�the�controller�after�an*¦error�has�occured. 6STATFLAG�DS.B‡1”This�variable�is�the�'STATUS'�flag�and)*¦is�set�up�exactly�as�the�STATUS�byte�in**¦the�VME320's�memory�mapped�I/O�space.�It**¦is�used�to�find�out�which�drive�aborted. 7‰DS.W…0�MUST�BE�ON�WORD�BOUNDARY�for�MOVE.L�instruction 3SAVECMD‚DS.B…1–This�variable�saves�the�command�code(*¦of�the�command�which�got�the�error.�It(*¦is�restored�to�the�command�packet�from(*¦this�location�after�a�successful�seek.'*¦Also�used�to�save�command�code�of�the*¦command�in�error. 3STAT1„DS.B†1•This�variable�contains�the�main�status'*¦returned�from�a�command�when�an�error*¦is�reported. 0STAT2„DS.W†1•This�variable�contains�the�extended%*¦status�word�returned�from�a�command*¦when�an�error�is�reported.‰PAGE1RECNT„DS.B†1•This�variable�contains�the�number�of&*¦retries�performed�by�the�VME320�disk*¦controller�during�a�command. 7RETRY_COUNT�DS.Bƒ1•This�variable�contains�the�number�of'*¦retries�performed�by�the�DRIVER�after"*¦the�controller�had�a�soft�error. 6MAX_COUNT�EQU†5•This�equate�defines�the�maximum�number(*¦of�DRIVER�retries�to�be�done�after�the*¦controller�had�a�soft�error. MAXSPTƒEQU†32 5SECTBUFF�DS.W…MAXSPT‘This�variable�points�to�a�buffer#*¦that�will�hold�a�string�of�sector(*¦numbers�used�to�implement�interleaving*¦and�spiral�offset.  M*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%* *%%%Å%%%*>*%%%„End�of�device�dependent,�channel�related,�variables.�%%%* *%%%Å%%%**%%%•END�OF�CCB�SPACE %%%* *%%%Å%%%*M*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*  3CCBSIZEB�EQU†*–CCBSIZEB�defines�the�size�(in�bytes)**¦of�a�complete�CCB�for�the�VME320�driver. %*¨CCBSIZE�defines�the�size�(in�pages)AL0080„EQU†CCBSIZEB+PAGESIZE-1‚of�a�CCB�for�the�VME320�driver,�andBCCBSIZE‚EQU†L0080/PAGESIZE‡EXTCCBSZ�defines�the�size�(in�pages)�of*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�IOSSHD�is�not�used�by�the�VME320. *„|ƒ|ƒ|ƒ|„|A*„|ƒ|ƒ|ƒ|„----------------�1�=�IOSTRKD�is�not�used�by�the�VME320. *„|ƒ|ƒ|ƒ|9*„|ƒ|ƒ|ƒ---------------------�1�=�IOSPCOM�is�significant.*„|ƒ|ƒ|F*„|ƒ|ƒ-------------------------�1�=�IOSSPTD�is�not�used�by�the�VME320.*„|ƒ|<*„|ƒ-----------------------------�1�=�IOSSRB�is�significant.*„|K*„---------------------------------�1�=�IOSRWCCB�is�not�used�by�the�VME320. *„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0$*‚+---+---+---+---++---+---+---+---+*‚|ƒ|ƒ|ƒ|ƒ||ƒ|ƒ|ƒ|ƒ|$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|/*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�IOSREC�is�significant.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|1*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�IOSRSZ�is�significant. *„|ƒ|ƒ|ƒ|„|ƒ|>*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�IOSWTO�is�not�used�by�the�VME320. *„|ƒ|ƒ|ƒ|„|@*„|ƒ|ƒ|ƒ|„----------------�1�=�IOSRTO�is�not�used�by�the�VME320. *„|ƒ|ƒ|ƒ|8*„|ƒ|ƒ|ƒ---------------------�1�=�IOSSPT�is�significant.*„|ƒ|ƒ|:*„|ƒ|ƒ-------------------------�1�=�IOSHDS�is�significant.*„|ƒ|<*„|ƒ-----------------------------�1�=�IOSTRK�is�significant.*„|>*„---------------------------------�1�=�IOSILV�is�significant. PAGE*'*ˆATTRIBUTES�MASK�FOR�THE�VME320�DRIVER* **ƒ15‚14‚13‚12ƒ11‚10ƒ9ƒ8$*‚+---+---+---+---++---+---+---+---+*‚| |$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|;*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Post-read/pre-write�precomp�req'dC .*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|Œ(not�used)=*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�8�"�floppy�disk;�0�=�5-1/4�"�disk. *„|ƒ|ƒ|ƒ|„|ƒ|A*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�Alternate�sector�handling�capability *„|ƒ|ƒ|ƒ|„|-*„---------------------------------…Not�used.  *„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0$*‚+---+---+---+---++---+---+---+---+*‚|‹|ƒ||ƒ|ƒ|ƒ|ƒ|$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|<*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Double�data-density�(MFM)�on�media.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|9*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�Double�track-density�on�media.*„|ƒ|ƒ|ƒ|„|ƒ|�(not�used)6*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�Double-sided�floppy�disk. *„|ƒ|ƒ|ƒ|„|?*„|ƒ|ƒ|ƒ|„----------------�1�=�IBM�format;�0�=�Motorola�format.*„|ƒ|ƒ|ƒ|™(must�always�be�IBM)>*„|ƒ|ƒ|ƒ---------------------�1�=�Rigid�disk;�0�=�floppy�disk.*„|ƒ|ƒ|G*„|ƒ|ƒ-------------------------�1�=�Double�data-density�(MFM)�on�drive.*„|ƒ|¡(not�used)D*„|ƒ-----------------------------�1�=�Double�track-density�on�drive.*„|¥(not�used)C*„---------------------------------�1�=�Seek�required�on�SMD�drive.�PAGE¦(not�used)A*ˆThis�driver�communicates�commands�to�the�VME320�disk�controllerC*‚board�through�an‚Event�Control�Area‚(ECA).ƒThere�is�one�ECA�blockE*‚allocated‚per�possible�drive�on�the�controller�board.‚The�format�ofA*‚ECA�is�shown�in�the�following�diagram.ƒA‚description‚of‚all‚the**‚parameters�within�the�ECA�block�follows. * *¡ECA�FORMAT* *‰Bit�15°Bit�0?*ˆ+-----------------------------+-----------------------------+$*‚$�0ƒ|ˆCommand�Code‰|‰Main�Status‰|?*ˆ+-----------------------------+-----------------------------+*‚$�2ƒ|•Extended�Status—|?*ˆ+-----------------------------+-----------------------------+>*‚$�4ƒ|‚Maximum�Number�of�Retries‚|‚Actual�Number�of�Retriesƒ|?*ˆ+-----------------------------+-----------------------------+$*‚$�6ƒ|‰DMA�TypeŒ|‡Command�Options‡|?*ˆ+-----------------------------+-----------------------------+%*‚$�8ƒ|“Buffer�Address�(upper�word)�|?*ˆ+-----------------------------+-----------------------------+%*‚$�Aƒ|“Buffer�Address�(lower�word)�|?*ˆ+-----------------------------+-----------------------------+!*‚$�Cƒ|“Buffer�Length�Requested‘|?*ˆ+-----------------------------+-----------------------------+,*‚$�Eƒ|ŽActual�Number�of�Bytes�Transferred‹|?*ˆ+-----------------------------+-----------------------------+*‚$10ƒ|–Cylinder�Number–|?*ˆ+-----------------------------+-----------------------------+0*‚$12ƒ|„Head�or�Surface�Numberƒ|‡Sector�Number‰|?*ˆ+-----------------------------+-----------------------------+#*‚$14ƒ|‘Current�Cylinder�Position‘|?*ˆ+-----------------------------+-----------------------------+*‚$16ƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+*‚$18ƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+*‚$1Aƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+*‚$1Cƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+*‚$1Eƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+'*‚$20ƒ|‡N0�-�Reserved‰|ˆN1�-�Reservedˆ|?*ˆ+-----------------------------+-----------------------------+'*‚$22ƒ|‡N2�-�Reserved‰|ˆN3�-�Reservedˆ|?*ˆ+-----------------------------+-----------------------------+,*‚$24ƒ|†N4�-�Post-Data�Gap…|ˆN5�-�Reservedˆ|?*ˆ+-----------------------------+-----------------------------+(*‚$26ƒ|†Sector�Length�Code…|‹Fill�Byte‰|?*ˆ+-----------------------------+-----------------------------+ PAGE **œECA�FORMAT�(continued)**‰Bit�15°Bit�0?*ˆ+-----------------------------+-----------------------------+*‚$28ƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+*‚$2Aƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+*‚$2Cƒ|™Reservedš|?*ˆ+-----------------------------+-----------------------------+)*‚$2Eƒ|ŠDrive�Type‰|…Number�of�Surfaces†|?*ˆ+-----------------------------+-----------------D ------------+1*‚$30ƒ|„Number�of�Sectors/Track‚|ˆStepping�Rateˆ|?*ˆ+-----------------------------+-----------------------------+-*‚$32ƒ|†Head�Settling�Time…|‡Head�Load�Timeˆ|?*ˆ+-----------------------------+-----------------------------+-*‚$34ƒ|‰Seek�Type‹|ƒReserved�for�Controllerƒ|?*ˆ+-----------------------------+-----------------------------+**‚$36ƒ|�Low�Write�Current�Boundary�TrackŽ|?*ˆ+-----------------------------------------------------------+(*‚$38ƒ|ŽPrecompensation�Boundary�Track�|?*ˆ+-----------------------------------------------------------+*‚$3Aƒ|—ECC�Remainder—|?*ˆ+-----------------------------------------------------------+*‚$3Cƒ|—ECC�Remainder—|?*ˆ+-----------------------------------------------------------+*‚$3Eƒ|—ECC�Remainder—|?*ˆ+-----------------------------------------------------------+(*‚$40ƒ|ŽAppend�ECC�Remainder�from�Disk�|?*ˆ+-----------------------------------------------------------+(*‚$42ƒ|ŽAppend�ECC�Remainder�from�Disk�|?*ˆ+-----------------------------------------------------------+(*‚$44ƒ|ŽAppend�ECC�Remainder�from�Disk�|?*ˆ+-----------------------------------------------------------+*‚$46ƒ|™Reservedš|?*ˆ+-----------------------------------------------------------+*‚$48ƒ|™Reservedš|?*ˆ+-----------------------------------------------------------+*‚$4Aƒ|”VME320�Working�Area”|?*ˆ+-----------------------------------------------------------+*‚$4Cƒ|”VME320�Working�Area”|?*ˆ+-----------------------------------------------------------+*‚$4Eƒ|”VME320�Working�Area”|?*ˆ+-----------------------------------------------------------+*‚$50ƒ|”VME320�Working�Area”|?*ˆ+-----------------------------------------------------------+*‚$52ƒ|”VME320�Working�Area”|?*ˆ+-----------------------------------------------------------+*‚$54ƒ|”VME320�Working�Area”|?*ˆ+-----------------------------------------------------------+%*‚$56ƒ|�Reserved�for�the�Controller�|?*ˆ+-----------------------------------------------------------+ PAGE*6*‚The�following�section�defines�the�variables�that�are-*‚contained�in�the�VME320�Event�Control�Area:* ‰OFFSET„04CMDCODE‚DS.B†1•The�CMDCODE�field�of�the�ECA�contains(*¦the�command�code�that�tells�the�VME320*¦what�operation�to�perform. #READ…EQU‡5“VME320�readƒcommand�code%WRITE„EQU‡6“VME320�write‚command�code%FRMT…EQU‡7“VME320�format�command�code#SEEK…EQU‡0“VME320�seekƒcommand�code 4MAINSTAT�DS.B†1•The�MAINSTAT�field�of�the�ECA�is�set%*¦by�the�VME320�and�contains�the�main'*¦status�value�about�command�execution.)*¦The�values�for�MAINSTAT�can�be�found�in'*¦the�error�code�table�in�this�driver's*¦interrupt�handler. 2EXTSTAT‚DS.W†1•The�EXTSTAT�field�of�the�ECA�is�set%*¦by�the�VME320�and�contains�the�bit-)*¦oriented�status�about�command�exection. 6MAXRETRY�DS.B†1•The�MAXRETRY�field�of�the�ECA�contains#*¦the�maximum�number�of�retries�PER(*¦COMMAND�that�the�VME320�should�attempt'*¦after�a�disk�operation�error.‚Zero�in"*¦this�field�indicates�no�retries. 0RETRY„EQU‡10’The�recommended�value�for�MAXRETRY.5MINTRYƒEQU‡1“Minimum�retry�count�to�validate�sectors. 4ACTRETRY�DS.B†1•The�ACTRETRY�field�of�the�ECA�is�set'*¦by�the�VME320�and�contains�the�actual)*¦number�of�retries�executed�PER�COMMAND. 4DMATYPE‚DS.B†1•The�DMATYPE�field�of�the�ECA�contains'*¦a�value�representing�the�DMA�transfer(*¦mode�of�operation�-�holding�the�bus�or*¦releasing�the�bus. +DMA†EQU‡0•This�value�entered�in�the�DMATYPE'*¦field�allows�the�user�to�free�the�bus(*¦between�two-word�transfers.‚A�non-zero(*¦value�would�allow�the�user�to�keep�the*¦bus�for�up�to�200�usec. 2CMDOPTƒDS.B†1•The�CMDOPT�field�of�the�ECA�contains**¦options�applicable�to�read�commands�when&*¦handling�deleted�data�address�marks.‰PAGE/OPT0…EQU‡0•This�bit�in�the�CMDOPT�field�defines&*¦the�handling�of�deleted�data�address&*¦marks.�A�'0'�in�this�field�skips�the)*¦sector�with�a�deleted�data�address�mark'*¦as�if�it�did�not�exist.�A�'1'�D in�this%*¦field�transfers�the�sector�with�the)*¦deleted�data�address�mark�regardless�of&*¦the�CRC/ECC�check�and�terminates�the *¦operation. /OPT2…EQU‡2•This�bit�in�the�CMDOPT�field�enables&*¦automatic�error�correction.�A�'1'�in)*¦this�field�uses�the�ECA�remainder�field)*¦in�the�ECA�and�corrects�the�data�in�the#*¦VME320�internal�memory.�The�error)*¦correction�vector�and�relative�position$*¦are�saved�in�the�ECA�working�area. >OPT†EQU‡0<FORMSIZE�EQU‡EQ070/PAGESIZE†memory�for�a�write�buffer�required$*¦for�format�tracks�on�the�VME320.�4 *¦bytes�per�sector�per�track�are'*¦required�for�floppies�and�5�bytes�for *¦hard�disks. PAGE* *ˆVME320�Memory-mapped�I/O�Space* 1‰OFFSETƒ-13”This�OFFSET�block�defines�the�memory-(*¦mapped�I/O�space�for�a�VME320�channel.(*¦The�VME320�driver�communicates�through%*¦this�memory-mapped�I/O�space�to�the'*¦VME320�disk�controller.�A�negative�13&*¦offset�is�used�due�to�the�controller)*¦status�register�being�13�bytes�from�the'*¦start�of�the�memory-mapped�I/O�space. +‰DS.B†1•The�one-byte�registers�ECA0�through1ECA0…DS.B†1“ECA3�are�read/write�registers�used�to*‰DS.B†1“communicate�the�address�of�the�ECA(ECA1…DS.B†6“Pointer�Table�to�the�VME320. /VECTORƒDS.B†1•The�one-byte�register�VECTOR�is�a-‰DS.B†1“read/write�register�set�by�the�driver)*¦to�contain�the�interrupt�vector�number. /SOURCEƒDS.B†1•The�one-byte�register�SOURCE�is�a-‰DS.B†1“read/write�register�set�by�the�VME320"*¦at�interrupt�acknowledge�time�to'*¦identify�which�drive�is�the�source�of*¦the�interrupt. **ˆInterrupt�'SOURCE'�Register* *„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0$*‚+---+---+---+---++---+---+---+---+*‚|ƒ|‡|ƒ||ƒ|ƒ|ƒ|ƒ|$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|%*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Not�defined.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|'*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�Not�defined. *„|ƒ|ƒ|ƒ|„|ƒ|)*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�Not�defined. *„|ƒ|ƒ|ƒ|„|+*„|ƒ|ƒ|ƒ|„----------------�1�=�Not�defined. *„|ƒ|ƒ|ƒ|;*„|ƒ|ƒ|ƒ---------------------�1�=�Drive�0�Source�Interrupt.*„|ƒ|ƒ|=*„|ƒ|ƒ-------------------------�1�=�Drive�1�Source�Interrupt.*„|ƒ|?*„|ƒ-----------------------------�1�=�Drive�2�Source�Interrupt.*„|A*„---------------------------------�1�=�Drive�3�Source�Interrupt.* PAGE /STATUSƒDS.B†1•The�one-byte�register�STATUS�is�a(*¦read/write�register�used�by�the�driver%*¦to�issue�a�command�to�the�VME320�by!*¦setting�the�bit�in�the�register"*¦corresponding�to�the�drive�we're*¦processing�the�command�for. %*¨This�driver�uses�command�queueing�-"*¦it�allows�only�one�command�to�be)*¦processed�by�the�controller�at�oE ne�time'*¦and�maintains�a�queue�for�any�pending&*¦commands�received�from�the�operating *¦system. **ˆDrive�Busy�'STATUS'�Register* *„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0$*‚+---+---+---+---++---+---+---+---+*‚|ƒ|‡|ƒ||ƒ|ƒ|ƒ|ƒ|$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|%*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Not�defined.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|'*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�Not�defined. *„|ƒ|ƒ|ƒ|„|ƒ|)*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�Not�defined. *„|ƒ|ƒ|ƒ|„|+*„|ƒ|ƒ|ƒ|„----------------�1�=�Not�defined. *„|ƒ|ƒ|ƒ|/*„|ƒ|ƒ|ƒ---------------------�1�=�Drive�0�Busy.*„|ƒ|ƒ|1*„|ƒ|ƒ-------------------------�1�=�Drive�1�Busy.*„|ƒ|3*„|ƒ-----------------------------�1�=�Drive�2�Busy.*„|5*„---------------------------------�1�=�Drive�3�Busy.*‰PAGEO********************************************************************************1*ˆSERVICE�VECTOR�TABLE,�PARAMETERS,�REVISION�INFO*@*ˆThe�first‚several‚locations�of�every‚I/O�driver�must�contain�aB*ˆservice�vector�table�to�contain�the‚long-word�relative�addressesB*ˆof�the�three�driver�subroutines�that�CMR�uses.‚The�CMR�parameterC*ˆtable�immediately�follows�the�service�vector�table�and�includes�aA*ˆfield�telling‚CMR‚how�many�extra�pages‚to�allocate�for�the�CCB.E*ˆThe�revision�table�immediately�follows�the�the�CMR�parameter�table.*O*******************************************************************************O******************************************************************************* ‰SECTION‚0 M320DRV: *D*‚Service�vector�table.‚Notice�that�these�values�are�relative�to�theC*‚beginning�of�the�driver�so�the�mechanism�is�position-independent!* <‰DC.L…INTERUPT-M320DRV…Address�of�interrupt�service�routine.:‰DC.L…COMMANDS-M320DRV…Address�of�command�service�routine.5‰DC.L…INIT-M320DRV‰Address�of�initialization�routine.‰DC.L…0”Reserved. **‚Other�CMR�parameters.*3‰DC.B…EXTCCBSZ�#�of�extra�pages�in�the�CCB.‚The�CCB(*§may�be�any�size�from�1�to�256�pages�(a&*§page�is�256�bytes):‚if�this�field�is*§0,�it�will�be�1�page,�etc.‰DC.B…0,0,0�Reserved.‰DC.L…0,0,0�Reserved. **‚Revision�info:*/‰DC.B…'012386'�Date�of�last�assembly�as�MMDDYY.1‰DC.B…'�'’Space�indicates�no�patches�to�.LO�file.)‰DC.B…'4'’Major�VERSAdos�revision�number.‰PAGEO********************************************************************************7*ˆJump�table�for�use�by�the�generic�disk�driver�DISKLIB*O******************************************************************************* ‰BRA.L„SET_CNFG‰BRA.L„SET_CODE‰BRA.L„CHK_FLOPPY‰BRA.L„CHK_LSN‰BRA.L„BLD_PACKET‰BRA.L„DISK_START‰BRA.L„CHK_PARAM‰PAGEO*******************************************************************************O*********************************************************************************ˆINITIALIZATION�ROUTINE*B*ˆThis‚subroutine�is�called�from�CMR‚when�CMR�is�invoked�by�a�taskB*ˆ(normally�IOI)�to‚allocate�a�channel.‚Its�purpose�is�to�give�theD*ˆdriver�a�chance�to�set�up�things�for�command�service�and�interrupt-*ˆservice.‚The�basic�functions�performed�are:*5*ˆ1.‚Put�the�start�address�of�the�driver�into�the�CCB*Œvariable�DRV_ADDR.2*ˆ2.‚Put�the�total�number�of�drives�on�our�channel!*Œinto�the�CCB�variable�MAX_DRVS.8*ˆ3.‚Put�the�size�in�bytes�of�the�drive's�variable�block!*Œinto�the�CCB�variable�DRV_SIZE.?*ˆ4.‚Device-Independent�initialization�in�the�call�to�DISK_INIT"*Žto�initialize�the�CCB�variables.?*ˆ5.‚Device-Dependent�initialization�in�the�call�to�DO_INIT�for"*Ždevice�dependent�initialization.*B*ˆThis�subroutine�is�entered�through�a�JSR�from�CMR,�and�will�exit7*ˆwith�an�RTS.‚The�processor�is�in�the�supervisor�mode.*%*ˆEntry:„A6�=�physical�address�of�TCB*’A5�=�physical�address�of�CCB*5*ˆInterrupt�level�is�0.‚Registers�may�be�used�freely.*.*ˆRegisters�used�in�DISK_INIT:…0�1�2�3�4�5�6�7*¦D‚**¦A‚*‰P**ˆExits�to:�CMR�via�RTS*O**************************************************************F *****************O*******************************************************************************ŠPAGEINIT: *)*‚Get�address�of�start�of�driver�into�CCB*ŠLEA‡M320DRV(PC),A0ŠMOVE.L„A0,DRV_ADDR(A5)*9*‚Get�the�number�of�drives�supported�by�the�M320�channel.*ŠMOVE.W„#DRIVES,MAX_DRVS(A5)*5*‚Get�the�size�in�bytes�of�the�drive's�variable�block*ŠMOVE.W„#DRVBLKSZ,DRV_SIZE(A5)*>*‚Perform�the�device-independent�initialization�by�calling�the'*‚generic�routine�DISK_INIT�in�DISKLIB.*/‰JSR†DISK_INITŒDo�the�device-independent�stuff.4‰IF‚‚THEN.SŽSomething�went�wrong�with�DISK_INIT.‹RTS™The�channel�is�down�!!‰ENDI*8*‚Perform�any�device-dependent�initialization�in�DO_INIT*/‰BSR.L„DO_INITŽDevice�dependent�initialization.‰RTS‰PAGEO*******************************************************************************O*********************************************************************************ˆCOMMAND�SERVICE�ROUTINE*C*ˆThis�subroutine�is�called�from�CMR�when�CMR�receives�a�command�toA*ˆinitiate�an‚I/O�transaction‚with�a�device�that�is�controlled�by?*ˆthis�driver.‚Its�function�is�to‚process�the‚given�command‚andB*ˆqueue�the�command�to�the�controller.‚These�functions�are�handled%*ˆby�the�generic�disk�driver�DISKLIB.*5*ˆEntry:„A2�=�physical�address�of�CMR�parameter�block*’A5�=�physical�address�of�CCB/*’A6�=�physical�address�of�TCB�of�attached�task*5*ˆInterrupt�level�is�0.‚Registers�may�be�used�freely.*1*ˆRegisters�used�by�DISK_COMMAND:†0�1�2�3�4�5�6�7*ªD‚*�*�*�*�*�*�**ªA‚*�*�*�*�*�P**ˆExits�to:�CMR�via�RTS*O*******************************************************************************O******************************************************************************* COMMANDS: *,*‚Perform�any�device-dependent�stuff�here...* =*‚We�have�received�a�command,�so�we�know�there�is�someone�out**‚there�to�talk�to.‚Let�DISKLIB�handle�it.*&‰JSR†DISK_COMMAND‹Perform�the�command.‰RTS�Return�to�CMR.‰PAGEO*******************************************************************************O*********************************************************************************ˆVME320�INTERRUPT�HANDLER*G*ˆControl�can�come�to�the�VME320�interrupt‚handler�when�CMR�receives�anH*ˆinterrupt�on�the�interrupt�level�that�is�used�by�the�VME320�controllerF*ˆIf�the‚interrupt�is�a�VME320�interrupt,�the�VME320‚interrupt�handlerF*ˆsets�the�C�bit�of�the�SR,�and�lowers�the‚interrupt�mask‚level�by�one*ˆlevel�upon�return.*?*ˆEntry:„A1�=�Physical�address�of�the�VME320�interrupt�handler.#*’A5�=�Physical�address�of�the�CCB.3*’SR�=�Masked�at�the�level�of�the�VME320�interrupt.*O*******************************************************************************O*******************************************************************************  O********************************************************************************"*ˆVME320�INTERRUPT�POLLING�ROUTINE*%*ˆEntry:„A5�=�physical�address�of�CCB*/*ˆRegister�Usage:�D0,A0�both�saved�by�the�exec.*1*ˆFunction:�Determine�if�the�interrupt�if�for�me.*>*ˆExit:…Return�to�CMR�via�RTS�if�it�IS�NOT�a�VME320�interrupt.0*’Branch�to�M320INT�if�it�IS�a�VME320�interrupt.*O******************************************************************************* INTERUPT:7‰MOVE.L„CCBCHB(A5),A0‰Get�the�memory-mapped�I/O�address0‰MOVEQ.Lƒ#7,D0�of�the�VME320�and�test�the�SOURCE@INT100ƒBTST†D0,SOURCE(A0)‡register�to�determine�which�drive�sent2‰BNE‡M320INT�the�interrupt.�If�none�of�the�bits�in7‰DBRA†D0,INT100‹SOURCE�are�set,�disclaim�the�interrupt.  *¦THE�INTERRUPT�IS�NOT�FOR�MECLEAR„EQU‡0<<0‰AND.B…#CLEAR,CCR‰RTS PAGEO********************************************************************************%*ˆVME320�INTERRUPT�CO-ROUTINE�LINKAGE*C*ˆControl�reaches�this�point�when�we've�successfully�identified�the@*ˆinterrupt�as�a�VME320�interrupt‚ORƒthis�routine�is�called�as�a(*ˆsubroutine�from�the�commanF d�processor.*7*ˆThe�interrupt�level�is�masked�at�our�channel's�level.*?*ˆEntry:„A0�=�Physical�address�of�VME320�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�R�R�#�#�P�registers�throughout.*"*ˆExit:…Jump�to�co-routine�segment*O******************************************************************************* *¦THE�INTERRUPT�IS�FOR�MECM320INT‚BCLR…D0,STATUS(A0)ˆClear�the�interrupt�by�clearing�busy�bit1‰SUBQ.Lƒ#4,D0�D0�is�now�equal�to�the�drive�number /INTLOOP‚EQU‡*“I'M�HERE�FROM�THE�COMMAND�HANDLER9‰MOVE.WƒCCBSR(A5),SR‹Enable�68000�interrupts�at�our�level'*¦so�that�other�interrupts�at�our�level'*¦won't�be�delayed�while�we�process�our *¦interrupt. ‰MOVE.BƒDRIVENUM(A1),D2†variable�block.�Copy�it�to�the�working2‰MOVE.LƒD2,D1�register�and�mulitply�by�four�to�use0‰MULU…#4,D1�as�an�offset�to�have�A2�point�to�the>‰MOVE.LƒECATABLE(A5),A2†ECA�packet�for�the�drive�number�we�are9‰MOVE.Lƒ(A2,D1),A2‹handling:�command�setup�or�completion. 5‰GET_ON_BD�A2’Call�the�macro�to�adjust�the�ECA�packet,‰RTS›address�for�dual�ported�ram�and�return. PAGEO*********************************************************************************ˆPROCESS�NEXT�COMMAND*G*ˆControl�comes�to�this�co-routine�segment�to�process�the�next�command.C*ˆSometimes�we're�required�to�do�a�little�housekeeping�based�on�the$*ˆtype�of�command�and�data�transfer.*?*ˆEntry:„A0�=�Physical�address�of�VME320�Memory-Mapped�I/O�area9*’A1�=�Pointer�to�drive's�variable�block�in�global�memory#*’A2�=�Pointer�to�drive's�ECA�block*’A5�=�Physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�P�P…P**ˆExit:…BSR�to�INTRTN*O******************************************************************************* /PROCNEXT�TST.L„HALFSCTS(A1)‰Test�the�data�type.5‰IF��THEN’If�we�have�done�track�0�on�a�DD�floppy,‰MOVE.Lƒ#FRMT_DD,D2Š*-‰MOVE.BƒD2,N4(A2)ŒRestore�N4�in�th�ECA�block.‰MOVE.LƒFORMATD(PC),D2‡*4‰MOVE.WƒD2,SLC(A2)‹Restore�the�SLC�in�the�ECA�block.8‰MOVE.BƒDRIVTYPE(A1),DRVTYPE(A2)�Restore�the�drive�type.,‰CLR.L„HALFSCTS(A1)‰Clear�the�HALFSCTS�flag.‰ENDI 6‰MOVE.LƒIOSECTOR(A1),D0†Get�the�logical�sector�number.7‰BSR.L„FILLCHSŽFill�cylinder-head-sector�fields�in�ECA. :‰CMP.B„#FMTFUNC,IOFUNCT(A1)�If�this�is�the�format�command, ‰IF��THEN6‰BSR.L„BLDBUFFŽBuild/Set�the�buffer�fields�for�format.‰ELSE6‰BSR.L„CHS2BUFŽSet�the�buffer�fields�for�read�&�write.‰ENDI CPROCQUE‚CLR.B„RETRY_FLAG(A5)‡Clear�the�retry_flag�for�each�command.3‰CLR.B„RETRY_COUNT(A5)†Set�the�retry_count�to�zero. 9RESENDƒBSR†GET_ADDR�Get�the�drive�number�and�ECA�address.>‰MOVE.Bƒ#$07,MAINSTAT(A2)„Set�the�main�status�byte�busy,�clear=‰MOVE.Wƒ#0,NUMBYTE(A2)‡number�of�bytes�transferred�from�last.2‰ADDQ.Lƒ#4,D2�Fix�drive�number�to�equal�bit�number *¦to�set�in�the�STATUS�register. ;‰BSET…D2,STATUS(A0)ˆTell�the�controller�to�process�command! ;INTNEXT‚BSR.L„INTRTN‘The�VME320�controller�needs�time�to�do**¦its�job�so�return�control�to�the�system.)*¦When�the�VME320�controller�has�finished$*¦its�current�task,�we'll�receive�an&*¦interrupt�that�will�cause�control�to*¦come�back�here. PAGEO*********************************************************************************ˆTHE�INTERRUPT�ENTERSG �HERE*@*ˆControl�comes�to�this�co-routine�segment�when�we've�received�a>*ˆcommand�completion�interrupt.‚We�need�to�check�the�status�of>*ˆcommand.�If�an�error�occured�we�exit�to�process�it.‚If�thereC*ˆis�more�to�do�before�this�command�is�totally�finished�,�we�branch*ˆto�finish�it.*O******************************************************************************* 7‰TST.B„RETRY_FLAG(A5)‰Test�the�retry�flag,�If��then6‰BNE.L„CHECKRETRY‹this�command�completion�was�due�to�a'*¦driver�retry�and�the�original�command*¦must�be�re-issued. ;‰MOVE.BƒMAINSTAT(A2),D0ˆGet�the�status�bits�from�the�VME3207‰BNE.L„CHECKERR�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. *A*ˆIf�the�main�status�is�zero�but�the�extended�status�is�not�zero,* ˆIF.W�EXTSTAT(A2)��#0�THEN.S5ŠMOVE.Lƒ#1,D0�Make�it�look�like�we�got�error�code�01.%ŠBRA.L„CHECKERRŒBranch�to�do�retries.ˆENDI*=*ˆFor�read�and�write�commands,�check�that�the�number�of�bytes3*ˆtransferred�equals�the�number�of�bytes�requested.*@ˆIF.B�CMDCODE(A2)��#READ�OR.B�CMDCODE(A2)��#WRITE�THEN.S ‰MOVE.W�NUMBYTE(A2),D1‰IF.W�BUFLEN(A2)��D1�THEN.S5ŠMOVE.Lƒ#1,D0�Make�it�look�like�we�got�error�code�01.%ŠBRA.L„CHECKERRŒBranch�to�do�retries.‰ENDIˆENDI*=*ˆFor�read�commands,�check�the�6-byte�ECC�remainder�for�zero.*#ˆIF.B�CMDCODE(A2)��#READ�THEN.S 3‰IF.L�ECC(A2)��#0�OR.W�ECC+4(A2)��#0�THEN.S5ŠMOVE.Lƒ#1,D0�Make�it�look�like�we�got�error�code�01.%ŠBRA.S„CHECKERRŒBranch�to�do�retries.‰ENDIˆENDI PAGE6‰MOVEQIƒISTACFG,D1�If�the�NOFINISH�flag�is�nonzero,�we8‰TST.B„NOFINISH(A1)‰return�a�status�code�indicating�that2‰BNE†V320DONE�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. :‰TST.L„IOSCTCNT(A1)‹The�VME320�controller�has�successfully2‰BNE†PROCNEXT�completed�the�entire�I/O�transaction(*¦that�was�specified�by�the�last�command(*¦sequence�that�we�gave�it.‚If�there�are&*¦any�bytes�remaining�to�be�processed,'*¦loop�back�to�process�another�chunk�of*¦the�entire�I/O�transfer. 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�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�disk,�the'*¦code�is�ISTAEOV.�Otherwise,�we�return*¦the�ISTAOK�status�code. PAGE O*********************************************************************************ˆFINISH�PROCESSING�QUEUE�ENTRY*D*ˆControl�comes‚to�the�top‚of�this‚co-routine�when�the�VME320�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�entry�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�VME320�Memory-Mapped�I/O�area9*’A1�=�Pointer�to�drive's�variable�block�in�global�memory#*’A2�=�Pointer�to�drive's�ECA�block*’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******************************************************************************* V320DONE�EQU†*>‰CMP.B„#FMTFUNC,IOG FUNCT(A1)‚If�this�was�a�format�command,�take2‰IF��THEN’this�turnoff�to�subroutine�MEMRTN�to3ŠBSR.L‚MEMRTN�return�the�segment�of�memory�allocate‰ENDIšfor�the�format�buffer. ‰JSR†CHAN_DONE 6EQ170„REG†A1/A3/A4�Here�we�remove�the�front�entry�fromE‰MOVEM.L‚IOQUEUE+4(A5),EQ170‚the�I/O�queue,�and�we�set�A1�to�point�toB‰MOVEM.L‚EQ170,IOQUEUE(A5)„the�drive�block�for�the�disk�drive�that&*¦is�associated�with�the�next�(if�any)*¦entry�of�the�I/O�queue. 7‰SUB.W„#4,IOQCNT(A5)ŠReduce�the�queue-count�pointer�and5‰BHI†PROCQUEŽloop�back�if�next�entry�is�still�active. PAGEO*********************************************************************************ˆIDLE�LOOP�ROUTINE*G*ˆThis�routine�is�entered�when�the�controller�is�caught�up�with�all�theF*ˆwork�and�the�controller�is�idle.‚We'll�return�control�to�the�system.*?*ˆEntry:„A0�=�physical�address�of�VME320�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB*3*ˆExit:…BSR�to�INTRTN.‚It�should�never�return�here.*O******************************************************************************* 5IDLELOOP�BSR‡INTRTN�The�I/O�is�all�done,�so�we�return*¦control�to�the�system. O********************************************************************************2*ˆModified�to�run�with�spurious�interruptsƒ2/16/84*O******************************************************************************* BV320IDLE�ADD.B…#1,SPURINT(A5)ˆIf�control�ever�gets�here,�we�have�a@‰CMP.B…#$80,SPURINT(A5)„SPURIOUS�INTERRUPT�AND�WE�SIMPLY�RETURN.2‰BNE‡IDLELOOPŒIf�the�number�of�spurious�interrupts9‰ST.B†CHANDOWN(A5)ˆreaches�$80,�then�set�the�channel�down/‰BRA‡IDLELOOPŒand�return�to�the�idle�loop�until*¦another�command�gets�us�out.*"*¦NOTE:�$80�is�an�arbitrary�value.#*¬Chances�are�that�if�the�number�of"*¬spurious�interrupts�reaches�this *¬number,�the�disk�controller�is *¬failing. PAGEO*********************************************************************************ˆINTERRUPT-RETURN�ROUTINE*G*ˆControl�reaches�this�point�in�the�VME320�interrupt�handler�when�we'veC*ˆfinished�exectuting�a�co-routine�segment‚and�we�wish�to‚return�toC*ˆthe�system.‚We�return‚control�to�the�system�whenever�we�must�waitB*ˆon�a�controller‚activity,‚and�we�depend�on�an‚interrupt�to�bringC*ˆcontrol�back�to�us�when�the�controller�has�finished�its�activity.*B*ˆWe�restore‚the�registers�that�were�saved�at�the�beginning�of�theC*ˆinterrupt�handler,�set�the�SR,�and�set�the�C-bit�to�indicate�that(*ˆwe've�processed�the�interrupt�for�CMR.*?*ˆEntry:„A0�=�physical�address�of�VME320�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB**ˆExit:…Return�to�CMR�via�RTS*O******************************************************************************* FINTRTNƒMOVE.Lƒ(SP)+,INTSWTCH(A5)…This�routine�is�called�as�an�ordinary'*¦subroutine,�so�the�stack�contains�the(*¦address�of�the�co-routine�segment�that'*¦should�be�executed�in�response�to�the%*¦next�interrupt.‚We�get�that�address&*¦out�of�the�stack,�and�we�put�it�into*¦the�interrupt�switch. <‰MOVEM.L‚(SP)+,RTSREGSŠRestore�the�registers�that�were�saved1CARRY„EQU†1<<0‘in�INTERUPT,�set�the�SR.C�bit,�and4‰OR.B…#CARRY,CCR‹retrun�to�CMR.‚Setting�the�SR.C�bit)‰RTS›indicates�that�we�have�processed�the *¦interrupt. *¨Notice�that�we�don't�raise�the(*¦interrupt�mask�level,�so�the�interrupt'*¦mask�level�is�one�level�lower�than�it'*¦was�when�the�VME320�interrupt�handler*¦was�invoked. PAGEO*********************************************************************************ˆVME320�ERROR�HANDLING�ROUTINE*B*ˆThis�routine�is�executed�when�the�main�status�byte�of�the�ECA�isB*ˆNOT�zero�after�a�command�completion�interrupt,�and�also�when�the?*ˆcommand�completion�was�due�to�our�own�retry.‚Here�we�save�theB*ˆcommand�code,�status�bytes�and�number�of�controller�retries�fromA*ˆthe�command�that�had�the�error�in�the�CCB.‚Here�we�also�performD*ˆdriver�retries�for�certain�error�codes.�Another�important�functionC*ˆof�this�routine�is�to�get�the�H VERSAdos�error�code�from�the�VME320C*ˆerror�code,�and�compute�the�VERSAdos�sector�number�from�the�error *ˆsector�number�(when�required).***ˆEntry:„A2ƒ=�Pointer�to�drive's�ECA�block*’A5ƒ=�Physical�address�of�CCB$*’D0.B�=�Main�status�from�ECA�packet*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�R�*�R*™A†P…P*"*ˆExit:„D1.B�=�VERSAdos�error�code*‘D3.L�=�VERSAdos�sector�number*O******************************************************************************* CHECKRETRY:*@*ˆWhen�a�recalibrate�command�completes�successfully�as�part�of�a>*ˆdriver�retry,�clear�the�retry_flag�and�re-issue�the�original *ˆcommand.*(‰SFˆRETRY_FLAG(A5)�Set�retry_flag�false.*‰MOVE.L„#0,CMDCODE(A2)�Clear�status�bytes.=‰MOVE.B„SAVECMD(A5),CMDCODE(A2)‡Set�command�code�to�original.!‰BRA‡RESEND˜Re-issue�the�command.‰PAGE CHECKERR:B‰IF.B�D0��#ERRCEND�THEN.S‚If�the�error�code�returned�is�one�of2ŠMOVE.Bƒ#ISTAICE,D1‰the�undefined�error�codes�then-ŠBRA.L„CHK_END�return�the�general�error�code.‰ENDI F‰IF.B�#CNFGFUNC��IOFUNCT(A1)�THEN.S‚If�this�is�a�configure�command0ŠMOVEQ„#0,D1�then�don't�return�any�error�code�---ŠBRA.L„CHK_END�return�as�if�no�error�occured.‰ENDI 2‰BTSTW…#IOPRTYB,IOOPTS(A1)�Test�retry�options�bit.0‰IF�ƒTHEN.SŽIf�set,�don't�do�driver�retries. :‹IF.B‚D0��#1‚THEN.S„If�it's�a�non-recoverable�error...:�BSR.L�EXTEND_STATUS‡Use�the�extended�status�to�report�the1�BRA.L�REPORT10Œmost�correct�VERSAdos�error�code. (‹ELSE.S–Not�the�non-recoverable�error...+�BRA†REPORT_ERROR…Go�report�the�error�code. ‹ENDI ‰ENDI‰PAGE‰IF.B�D0��#1�THEN.S*9*ˆFor�nonrecoverable�errors,�a�recalibrate�and�a�re-issue;*ˆof�the�command�may�get�rid�of�the�error.‚When�an�error�is9*ˆdetected,�we�set�the�retry_flag�and�issue�a�recalibrate9*ˆcommand�to�the�controller.‚When�we�return,�we�clear�the>*ˆretry_flag�and�re-issue�the�original�command.‚This�procedure=*ˆis�repeated�until�the�command�is�successfully�completed,�or=*ˆthe�maximum�retry�count�is�reached,�at�which�time�the�error*ˆis�reported.*#‰IF.B�RETRY_FLAG(A5)��#0�THEN.S -ŒWHILE.B�RETRY_COUNT(A5)��#MAX_COUNT�DO.S 0�ADD.B�#1,RETRY_COUNT(A5)ŒIncrement�retry_count.6�MOVE.B�CMDCODE(A2),SAVECMD(A5)†Save�the�command�code.1�MOVE.L�#0,CMDCODE(A2)�Set�command�code�to�recal.'�ST…RETRY_FLAG(A5)�Set�retry_flag�true. �BRA„RESEND—Issue�a�recalibrate. ŒENDW ‰ELSE.S -ŒWHILE.B�RETRY_COUNT(A5)��#MAX_COUNT�DO.S 5�ADD.B‚#1,RETRY_COUNT(A5)‹Add�one�to�the�retry_count..�MOVE.L�#0,CMDCODE(A2)�Try�seek�command�again. �BRAƒRESEND ŒENDW‰ENDI*C*ˆUse�the�extended�status�to�report�the�most�correct�VERSAdos�error"*ˆcode�for�main�status�=�$01�only.*2ŒBSR†EXTEND_STATUS…Convert�to�VERSAdos�error�code./ŒBRA†REPORT10ŠBranch�to�finish�error�reporting. ‰ENDI‰PAGE)‰IF.B�D0��#07�OR.B�D0��#09�THEN.S*:*ˆFor�error�codes�07�(busy)�and�09�(DMA�error),�a�re-issue;*ˆof�the�command�may�get�rid�of�the�error.‚When�an�error�is;*ˆdetected,�we�set�the�retry_flag�and�re-issue�the�original:*ˆcommand.‚This�procedure�is�repeated�until�the�command�is:*ˆis�successfully�completed,�or�the�maximum�retry�count�is<*ˆreached,�at�which�time�the�error�is�reported.�We�increment.*ˆby�two�so�we�don't�end�up�doing�ten�retries.* NNH NNNNN-ŠWHILE.B�RETRY_COUNT(A5)��#MAX_COUNT�DO.S 5ŒADD.B‚#2,RETRY_COUNT(A5)‚Increment�retry_count�by�2.+ŒST…RETRY_FLAG(A5)†Set�the�retry_flag�true.!ŒBRA„RESENDŽRe-issue�the�command. ‹ENDW‰ENDI ‰BRA.S…ENDTABLE O*********************************************************************************ˆVME320�ERROR-CODE�TABLE*E*ˆThis�table�translates�VME320�error�codes�into�VERSAdos�error�codes.C*ˆThere�are�some�error�codes�defined�by�the�VME320�controller�whichC*ˆare�not�implemented�in�the�firmware�(10/11/85).‚These�are�defined*ˆbelow�as�#ISTAICE.*O*******************************************************************************  *§----‚VME320�Error�Code.*§|*§|%*§V…VME320�Definition�and�Explanation "ERRCODE‚DC.B…ISTACNT‡$00„No�error.7‰DC.B…ISTABDS‡$01„Nonrecoverable�error�(driver�retries)!‰DC.B…ISTANRˆ$02„Drive�not�ready.‰DC.B…ISTAICE‡$03„Reserved.:‰DC.B…ISTAICE‡$04„Invalid�sector�address�(not�implemented)7‰DC.B…ISTAICE‡$05„Floppy�data�overrun„(not�implemented)9‰DC.B…ISTAWPˆ$06„Illegal�command�(used�for�write�protect)!‰DC.B…ISTANRˆ$07„Controller�busy.%‰DC.B…ISTANRˆ$08„Drive�not�available.,‰DC.B…ISTABUS‡$09„DMA�error�(driver�retries)‰DC.B…ISTANRˆ$0A„Command�abort. AERRCEND‚EQU†*-ERRCODE…Error�codes�$0B�through�$FF�are�reported�as0*Ÿ"ISTAICE".�These�codes�are�currently�undefined * by�the�VME320�disk�controller.ENDTABLE�DS.W…0 PAGE REPORT_ERROR:=‰MOVE.BƒERRCODE(PC,D0),D1†Translate�the�main�status�byte�into(*¦a�VERSAdos�error�code�using�the�VME320*¦ERROR�CODE�TABLE. REPORT10:D‰MOVE.L‚CMDCODE(A2),SAVECMD(A5)�Save�the�command�code,�status�bytes,D‰MOVE.B‚ACTRETRY(A2),RECNT(A5)‚and�number�of�f/w�retries�in�the�CCB.  /‰MOVEQ.L‚#0,D3’Using�the�actual�number�of�bytes<‰MOVE.WƒBUFLEN(A2),D3ˆtransferred,�and�knowing�the�bytes�per;‰SUB.W„NUMBYTE(A2),D3‡sector,�calculate�which�sector�of�the>‰SUB.L„D3,IOBUFPTR(A1)†transaction�had�the�error�and�add�it�to6‰DIVU…BPS(A1),D3‹the�starting�sector�number�to�get�the3‰MOVEQ.L‚#0,D2�physical�sector�number.‚Subtract�theNNI NNNNN2‰MOVE.WƒD3,D2�number�of�bytes�NOT�transferred�from?‰MOVE.LƒIOSECTOR(A1),D3†IOBUFPTR�to�correct�#�bytes�transfered.NNNNNNN4  &6 .5 6= >> F@ N? V9 ^9 f8 n2 v3 ~ †> ŽA –> žA ¦9 ®9 ¶> ¾6 Æ; Î2 Ö  Þ æB î(+‰SUB.L„D2,D3�D3�<--�logical�'error'�sector.,‰MOVE.LƒD3,D2�D2�<--�logical�'error'�sector. B*ˆThe�NUMBYTE�field�shows�how�many�bytes�in�sector�increments�wereB*ˆsuccessfully�transferred.�The�BUFLEN�fields�shows�how�many�bytes?*ˆwere�requested.‚IOSECTOR�points�to�the�next�sector�that�wouldA*ˆbe�transferred�it�everything�was�successful.‚D2.L�is�set�to�the<*ˆlogical�error�sector�for�the�CHAN_DONE�routine�in�DISKLIB.  CHK_END‚CLR.B„RETRY_FLAG(A5) ‰BRA†V320DONE PAGEO********************I ************************************************************"*ˆVME320�EXTENDED-ERROR-CODE�TABLE*A*ˆThis�table�translates�VME320�extended�error�codes�into�VERSAdos *ˆerror�codes*O*******************************************************************************  * ----‚VME320�Error�Code.* |* |&* V…VME320�Definition�and�Explanation. 9EXTCODE‚DC.B…ISTAUNR‡Bit�0:‚Write�fault�(not�implemented),‰DC.B…ISTACRC‡Bit�1:‚Correctable�data�error.2‰DC.B…ISTADOˆBit�2:‚Data�overrun�(not�implemented))‰DC.B…ISTADME‡Bit�3:‚No�identifier�found.‰DC.B…ISTANRˆBit�4:‚Not�ready.9‰DC.B…ISTADDM‡Bit�5:‚Deleted�data�address�mark�(not�impl)"‰DC.B…ISTAWPˆBit�6:‚Write�protect.'‰DC.B…ISTABDS‡Bit�7:‚Positioning�error.9‰DC.B…ISTACRC‡Bit�8:‚Data�part�timeout�-�SAME�AS�BIT�1!!!8‰DC.B…ISTACNF‡Bit�9:‚Disk�format�error�(not�implemented)=‰DC.B…ISTACRC‡Bit�10:�Uncorrectable�ECC�data�error�(not�impl)9‰DC.B…ISTANRˆBit�11:�Command�stop�or�drive�not�available.*‰DC.B…ISTACFG‡Bit�12:�Drive�type�rejected.*‰DC.B…ISTABDS‡Bit�13:�Positioning�timeout.:‰DC.B…ISTADME‡Bit�14:�Wrong�ID-DATA-ID�sequence�(not�impl)&‰DC.B…ISTABUS‡Bit�15:�Bus�error�fault.‰DS.W…0 *C*ˆExtended�status�provides�useful�status�for�nonrecoverable�errors.*EXTEND_STATUS:0‰MOVE.WƒEXTSTAT(A2),D0‡Read�the�extended�status. ‰IF��THEN5ŠMOVE.Lƒ#16,D2ŽWhen�a�more�specific�code�is�specified8CHK01…SUBQ.Lƒ#1,D2�report�it�instead�of�the�general�code4ŠROR.W„#1,D0�in�the�main�status�byte.�Since�only�one4ŠBCC.S„CHK01�error�code�is�allowed,�report�the�first.ŠNEG.L„D2’one�set�in�the�extended�status�code.ŠADD.L„#15,D2Ž*ŠMOVE.BƒEXTCODE(PC,D2),D1ƒ*‰ENDI‰RTS PAGEO*********************************************************************************ˆCONTROLLER-ERROR�ROUTINE*G*ˆControl�comes�to�this‚routine�when�we've�detected�a�controller�error.G*ˆWe�declare�a�controller�error�when�a�VME320�controller�does�somethingF*ˆthat�simply�cannot�be�explained‚by�any‚defined�set�of�circumstances.G*ˆWhen�a�controller�error�occurs,�we‚down�the�VME320�channel�and�reportF*ˆa�controller�error.‚A�controller�error�is�a�serious�problem,�and�the?*ˆsystem�shouldn't�try�to�use�the�VME320�channel�following�one.*A*ˆThere�are‚two�entry�points.‚The�entry�point‚at�CTRLERR1‚is�usedD*ˆthe�error�is�detected�within�a�subroutine.‚The�entry�point�CTRLERR*ˆis�used�otherwise.*?*ˆEntry:„A0�=�Physical�address�of�VME320�Memory-Mapped�I/O�area9*’A1�=�Pointer�to�drive's�variable�block�in�global�memory*’A5�=�Physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�* *™A‚P�Pƒ*�*�P*>*ˆExits�to:‚V320DONE�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,�so�the�stack�is�restored�to&*¦the�condition�that�it�had�before�the*¦subroutine�was�called. 9CTRLERR‚ST.B…CHANDOWN(A5)‹Down�the�channel�by�setting�the"*¦variable�that�indicates�that�the#*¦controller�is�down.‚If�the�system**¦tries�to�access�the�VME320�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�VME320'*¦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‰MOVEQIƒISTACNT,D1�Set�up�D1.B�for�reporting�a�status4‰BRA†V320DONE�code�that�indicates�a�controller�error%*¦and�go�terminate�processing�for�the!*¦current�entry�of�the�I/O�queue. PAGEO********************************************************************************?*ˆThese�constants�are�used�by�the�VME320�driver.‚Constants�were>*ˆchosen�over�equates�so�the�driver�could�be�easily�patcJ hed�to*ˆoptimize�drive�operation.*O******************************************************************************* =FORMATS‚DC.L†$1B0000E5�Format�fields�N4,�N5,�SLC�and�FILLBYTE#*¦for�a�single-density�floppy�disk.*=FORMATD‚DC.L†$360001E5�Format�fields�N4,�N5,�SLC�and�FILLBYTE**¦for�double-density�floppy�and�hard�disk.* A*ˆFloppy�disk�stepping�rate�table�for�floppy�disks�as�defined�forL*‚VERSAdos�4.3.‚The�values�below�are�in�milliseconds.‚This�driver�translatesK*‚the�stepping�rate�code�into�a�millisecond�value�using�the�table�below�forK*‚8"�floppy�disk�drives�and�doubles�the�values�below�for�5-1/4"�floppy�disk *‚drives.* $*“8"…5-1/4"„UnitsƒStepping�Rate�Code%*’---…------„-----ƒ------------------ SRFCODE‚DC.B‡6ˆ12‡Msec„Default‰DC.B‡3ˆ06‡Msec„00‰DC.B‡6ˆ12‡Msec„01‰DC.B†10ˆ20‡Msec„10‰DC.B†15ˆ30‡Msec„11 *=*ˆHard�disk�stepping�rate�table�for�hard�disks�as�defined�forL*‚VERSAdos�4.4.�The�values�below�are�in�milliseconds.‚This�driver�translatesH*‚the�stepping�rate�code�into�a�millisecond�value�using�the�table�below.* *‘Hard†Units†Stepping�Rate�Code*‘----†-----†------------------ SRHCODE‚DC.B‡5ˆMsec†Default‰DC.B‡6ˆMsec†00‰DC.B†10ˆMsec†01‰DC.B†15ˆMsec†10‰DC.B†20ˆMsec†11‰SPC�5N*******************************************************************************"*ˆEND�OF�INTERRUPT�SERVICE�ROUTINE*N******************************************************************************ŠPAGEN********************************************************************************!*�R�O�U�T�I�N�E�S„C�A�L�L�E�D„B�Y**–D�I�S�K�L�I�B**N******************************************************************************‰PAGEN*******************************************************************************)*ˆSET_CNFG…SET�UP�FOR�A�CONFIGURE�COMMAND*C*ˆThis‚is�a�device�dependent�routine�whose�offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toD*ˆset�the�fields's�in�the�drive's�variable�block,�device-independent#*ˆportion,�for�a�configure�command.**A*ˆEntry:�A1�=�pointer�to�Drive's�Variable�Block�in�global�memory.#*�A5�=�physical�address�of�the�CCB.* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D„R*™A„P‡P* *ˆCalls:�none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:7*�‚Drive/controller�supports�the�configure�request.?*�‚Drive/controller�does�not�support�the�configure�request.4*•D1.B�=�VERSAdos�error�code�for�the�error�detected.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N****************************************************************************** SET_CNFG:*>*ˆThe�VME320�disk�controller�doesn't�have�a�configure�command,6*ˆtherefore�it�does�not�require�any�special�variables.*?‰CMP.B�D0,D0‰Compare�D0�with�itself�to�satisfy�condition�codes.‰RTS‰PAGEN******************************************************************************* *ˆSET_CODE*F*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installed�atE*ˆthe�beginning�of�the�driver.‚The�function�of�this�routine�is�to�setD*ˆany�media‚and/or‚drive�related�codes�in�the�drive's�variable�blockC*ˆ(device-dependent�portion)‚required�by‚the�particular‚controller.>*ˆIt�is�called�by�configure,�read,�write,�and�format�commands.**A*ˆEntry:„A1�=�pointer�to�Drive's�Variable�Block�in�global�memory.#*’A5�=�physical�address�of�the�CCB.* *’Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A„P‡P* *ˆCalls:�none**ˆExit:‚RTS�to�caller.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N****************************************************************************** SET_CODE:*@*ˆThe�VME320�doesn't�have�a�media/drive�controller�code.‚It�uses@*ˆthree�fields�to�accomplish�a�similar�function:�the�drive�type,?*ˆsector�length�code,�and�post-data�gap.‚These�three�fields�J are'*ˆcalculated�in�the�BLD_PACKET�routine.*‰RTS‰PAGEN********************************************************************************ˆCHK_FLOPPY�ROUTINE*C*ˆThis�is�a‚device�dependent‚routine�whose‚offset�must‚be�installedD*ˆat�the�beginning�of�the�driver.�The‚function�of‚this�routine‚is�toF*ˆcheck�that�the�bytes�per�sector,‚sectors�per�track,�and�data-densityG*ˆdensity�values�are�consistent�with�each�other.�This�routine�is�called?*ˆafter�the‚user's‚configuration‚block‚has‚been‚filled‚with‚theG*ˆproposed�configuration.�Therefore,�A0�points�to�the�end�of�the�user's*ˆconfiguration�block.*0*ˆEntry:�A0�=�end�of�user's�configuration�block.* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A‚P* *ˆCalls:�none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:-*��no�errors�in�this�configuration�check.*��an�error�was�found.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N****************************************************************************** CHK_FLOPPY:*?*ˆThe�VME320�is�used�by�VERSAdos�to�support�only�128�bytes�as�a>*ˆsingle-density�floppy�disk�and�256�bytes�as�a�double-density<*ˆfloppy�disk.‚The�VME320�states�that�other�combinations�are=*ˆpossible,�but�we�don't�use�them�and�we�haven't�tested�them,E*ˆso�we�don't�limit�the�user�by�returning�an�error�from�this�routine.*?‰CMP.B�D0,D0‰Compare�D0�with�itself�to�satisfy�condition�codes.‰RTS‰PAGEN******************************************************************************* *ˆCHK_LSN*C*ˆThis�is�a�device�dependent�routine�whose�offset�must‚be‚installedD*ˆat�the�beginning�of�the‚driver.�The�function�of�this�routine�is�toC*ˆcheck�that‚the�requested�starting�logical‚sector�number�(in�D2.L)E*ˆis�less�than�or�same�as�the�largest�logical�sector�number�supported$*ˆby�the�particular�disk�controller.**-*ˆEntry:�D2�=�starting�logical�sector�number.* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D†P*™A* *ˆCalls:�none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:3*��=�starting�logical�sector�number�is�invalid.1*��=�starting�logical�sector�number�is�valid.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N****************************************************************************** CHK_LSN:*=*ˆThe�VME320�does�not�perform�data�transfers�based�on�logical<*ˆsector�numbers.‚It�uses�cylinder,�head,�and�sector�numbers6*ˆto�locate�logical�sectors,�and�is�not�limited�to�any*ˆmaximum�sector�number.*?‰CMP.B�D0,D0‰Compare�D0�with�itself�to�satisfy�condition�codes.‰RTS‰PAGEN******************************************************************************* *ˆBLD_PACKET*C*ˆThis�is�a�device-dependent�routine�whose‚offset�must�be�installedD*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�toC*ˆbuild�any�or�all‚parts�of�the�command�packet�that�can�be�built�at=*ˆinterrupt‚level�0‚which‚will�be‚used‚by�the‚particular‚disk,*ˆcontroller�to�process�the�current�command.*A*ˆEntry:„A1�=�pointer�to�Drive's�Variable�Block�in�global�memory.#*’A5�=�physical�address�of�the�CCB.* *’Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�R�* *™A‚*�P�*…P* *ˆCalls:„none*/*ˆExit:‚RTS�to�caller�with�condition�codes�set:3*�‚No�errors�were�found�in�building�the�packet.4*�‚An�error�was�detected�in�building�the�packet.4*•D1.B�=�VERSAdos�error�code�for�the�error�detected.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N****************************************************************************** BLD_PACKET::‰MOVEM.LƒD0/D2/A0/A2,-(SP)ƒSave�the�registers�we�will�use. +‰MOVE.L„IOBUFEND(A1),D0…Last�byte�in�buffer+‰SUB.L…IOBUFLOC(A1),D0…First�byte�in�buffer ‰IF�ƒTHEN5‰ADDQ.L„#1,D0�Add�one�to�get�total�bytes�to�transfer.‰ENDI4‰MOVE.L„D0,IOBUFLEN(A1)…Store�it�in�the�drK ive�block. ‰MOVEQ.Lƒ#0,D0�*6‰MOVE.B„DRIVENUM(A1),D0…Drive�number�to�use�as�offset.)‰MULU†#4,D0�Make�into�a�long-word�offset.3‰MOVE.L„ECATABLE(A5),A2…A2�<--�pointer�to�ECA�table,‰MOVE.L„(A2,D0),A2ŠA2�<--�ECA�block�address. !*¦Adjust�the�ECA�block�address�to'*¦account�for�Dual�Ported�Ram�if�req'd. ‰GET_ON_BD�A2 (* The registers will be used as follows: *‚A0�=�Scratch(*‚A1�=�Drive's�variable�block�in�the�CCB*‚A2�=�Drive's�ECA�block*‚D0�=�Scratch*‚D1�=�Scratch*‚D2�=�Scratch PAGE*.*�SET�THE�DISK�CONTROL�FIELDS�IN�THE�ECA�BLOCK*?*ˆ+-----------------------------+-----------------------------+)*‚$2Eƒ|ŠDrive�Type‰|…Number�of�Surfaces†|?*ˆ+-----------------------------+-----------------------------+1*‚$30ƒ|„Number�of�Sectors/Track‚|ˆStepping�Rateˆ|?*ˆ+-----------------------------+-----------------------------+-*‚$32ƒ|†Head�Settling�Time…|‡Head�Load�Timeˆ|?*ˆ+-----------------------------+-----------------------------+-*‚$34ƒ|‰Seek�Type‹|ƒReserved�for�Controllerƒ|?*ˆ+-----------------------------+-----------------------------+**‚$36ƒ|�Low�Write�Current�Boundary�TrackŽ|?*ˆ+-----------------------------------------------------------+(*‚$38ƒ|ŽPrecompensation�Boundary�Track�|?*ˆ+-----------------------------------------------------------+* SPC 2***¤DRIVE�TYPE: ‰CLR.L„D2“*?EQ450„EQU†CONFGBLK+IOSATW†If�the�disk�that�is�being�accessed�isC‰BTSTW„#IOARDISC,EQ450(A1)‚a�hard�disk,�put�the�drive�type�code�for6‰IF‡�THENŒECC�hard�disk�format�into�D2�and�branch.‹MOVE.Bƒ#TYPE2,D2 ‹BRA†DRV_TYPE‰ENDI 9‰BTSTW„#IOADDEN,EQ450(A1)ƒTest�for�single-�or�double-data‰IF‡�THENŒdensity. 5‹MOVE.Bƒ#TYPE0,D2ŠWe're�a�single�density�floppy�disk.=‹BTSTW„#IOASIZE,EQ450(A1)�Put�the�drive�type�code�for�8"�into3‹IF‡�THENŠD2.‚If�the�attributes�word�says�we're9�MOVE.Bƒ#TYPE4,D2ˆactually�5.25",�change�drive�type�code.‹ENDI ‰ELSE 5‹MOVE.Bƒ#TYPE5,D2ŠWe're�a�double�density�floppy�disk.@‹BTSTW„#IOASIZE,EQ450(A1)�Put�the�drive�type�code�for�5.25"�into3‹IF‡�THENŠD2.‚If�the�attributes�word�says�we're6�MOVE.Bƒ#TYPE1,D2ˆactually�8",�change�drive�type�code.‹ENDI ‰ENDIDRV_TYPE=‰MOVE.BƒD2,DRVTYPE(A2)‡D2�<--�Drive�type�(keep�for�reference)3‰MOVE.BƒD2,DRIVTYPE(A1)†Save�it�in�the�drive�block. PAGE***¤NUMBER�OF�SURFACES: ‰CLR.L„D0“*=EQ460„EQU†CONFGBLK+IOSATW†Determine�if�this�is�a�hard�disk�or@‰BTSTW„#IOARDISC,EQ460(A1)‚floppy�disk�from�the�attributes�word. &‰IF‡�THENŒIf�we're�a�hard�disk....EQ470„EQU†CONFGBLK+IOSHDS†*5‰MOVE.BƒEQ470(A1),D0‰Put�the�number�of�heads�into�D0. ‰ELSEšIf�we're�a�floppy�disk....6‰MOVEQ.L‚#1,D0�Put�default�value�of�one�surface�in�D0.?‰BTSTW„#IOADSIDE,EQ460(A1)‚Determine�actual�number�of�surfaces.6‰IF‡�THENŒIf�attributes�word�indicates�2�surfaces.0‰MOVEQ.L‚#2,D0�Change�number�of�surfaces�to�two.‰ENDI‰ENDI;‰MOVE.BƒD0,NUMSURF(A2)‡Put�the�number�of�surfaces�into�ECA.7‰MOVE.WƒD0,SURF(A1)ŠStore�number�of�surfaces�in�drive's!*¦variable�block�for�easy�access. SPC 2***¤SECTORS�PER�TRACK:EQ480„EQU†CONFGBLK+IOSSPT†*;‰MOVE.BƒEQ480(A1),D0‰Put�number�of�sectors�per�track�in�D0.5‰MOVE.BƒD0,NUMSPT(A2)ˆPut�number�of�sectors�into�ECA.5‰MOVE.WƒD0,SPT(A1)‹Store�number�of�sectors�in�drive's!*¦variable�block�for�easy�access. SPC 2"***¤HEAD�SET/LOAD�TIMES�FOR�5-1/4" ‰BTST…#2,D2.‰IF��THEN’Execute�for�drive�types�4�and�5:5ŠMOVE.Lƒ#SETTM_5,D0‰D0�<--�head�settling�time�in�msec3ŠASL.B„#1,D0�D0�<--�settling�time�in�500�usec�units.ŠMOVE.BƒD0,HEADSET(A2)†Write�to�the�ECA�block.0ŠMOVE.Lƒ#LDTM_5,D0ŠD0�<--�head�load�time�in�msec3ŠASL.B„#1,D0�D0�<--�settling�time�in�500�usec�units/ŠMOVE.BƒD0,HEADLOAD(A2)…Write�to�the�ECA�block.ŠBRA.S„STEP_RATE‰ENDI SPC 2%***¤HEAD�SET/LOAD�TIMES�FOR�HARD�DISK ‰BTST…#1,D2 ‰IF‡�THEN6ŠMOVE.Lƒ#SETTM_HD,D0ˆD0�<--�head�settling�time�in�msec3ŠASL.B„#1,D0�D0�<--�settling�time�in�500�usec�units1ŠMOVE.BƒD0,HEADSET(A2)†Put�it�into�the�EK CA�block.1ŠMOVE.Lƒ#LDTM_HD,D0‰D0�<--�head�load�time�in�msec4ŠASL.B„#1,D0�D0�<--�head�load�time�in�500�usec�units2ŠMOVE.BƒD0,HEADLOAD(A2)…Put�it�into�the�ECA�block. PAGE***¥SEEK�TYPE�FOR�HARD�DISKS%ŠMOVE.Lƒ#TYP_SEEK,D0‰D0�<--�seek�type3ŠIF‡�THENŒSeek�type�zero�defines�buffered�seek:9ŠMOVE.B�#BUFFSEEK,SEEKTYPE(A2)�Put�it�into�the�ECA�block.-ŠELSEšSeek�type�not�zero�defines�single�step:9ŠMOVE.B�#STEPSEEK,SEEKTYPE(A2)�Put�it�into�the�ECA�block.ŠENDIŠBRA.S„STEP_RATE‰ENDI ***¤HEAD�SET/LOAD�TIMES�FOR�8"5‰MOVE.Lƒ#SETTM_8,D0ŠD0�<--�head�settling�time�in�msec3‰ASL.B„#1,D0�D0�<--�settling�time�in�500�usec�units1‰MOVE.BƒD0,HEADSET(A2)‡Put�it�into�the�ECA�block.0‰MOVE.Lƒ#LDTM_8,D0‹D0�<--�head�load�time�in�msec4‰ASL.B„#1,D0�D0�<--�head�load�time�in�500�usec�units2‰MOVE.BƒD0,HEADLOAD(A2)†Put�it�into�the�ECA�block. STEP_RATE SPC 2***¤HEAD�STEPPING�RATE9‰MOVE.BƒCONFGBLK+IOSSRTD(A1),D0ƒD0�<--�Stepping�rate�code ‰BTST…#1,D2 ‰IF‡�THEN9‰LEA†SRHCODE(PC),A0‡A0�<--�pointer�to�step�rates�for�hard‰ELSE;‰LEA†SRFCODE(PC),A0‡A0�<--�pointer�to�step�rates�for�floppy‰ENDI /‰MOVE.Bƒ(A0,D0),D1‹D1�<--�Stepping�rate�in�msec9‰BTSTW„#IOARDISC,CONFGBLK+IOSATW(A1)‚Test�for�floppy�disk‰IF��THEN’If�floppy�disk,8ŠBTSTW„#IOASIZE,CONFGBLK+IOSATW(A1)‚Test�the�floppy�size%ŠIF��THEN‘Execute�for�5.25"�only:-‹ASL.B„#1,D1ŽDouble�the�stepping�rate�in�msecŠENDIBŠMOVE.Bƒ#STEPSEEK,SEEKTYPE(A2)�Copy�single�step�seek�to�ECA�block.‰ENDI &‰ASL.B„#1,D1�Convert�to�500�usec�units2‰MOVE.BƒD1,STEPRATE(A2)†Put�it�into�the�ECA�block. SPC 2$***¤PRECOMPENSATION�CYLINDER�NUMBER:>EQ490„EQU†CONFGBLK+IOSPCOM…Copy�the�precompensation�value�fromD‰MOVE.WƒEQ490(A1),PRECOMP(A2)�the�drive's�variable�block�to�the�ECA. PAGE&***¤LOW-WRITE�CURRENT�CYLINDER�NUMBER:EQ500„EQU†CONFGBLK+IOSTRK4‰MOVEQ.L‚#0,D0�Use�zero�'cause�we�need�4�head�lines.‰MOVE.WƒD0,LOWCURR(A2) SPC 2>EQ505„EQU†CONFGBLK+IOSPSM†Store�the�number�of�bytes�per�sector@‰MOVE.WƒEQ505(A1),BPS(A1)„in�drive's�var.�block�for�easy�access. SPC 2*.*�SET�THE�TRACK�FORMAT�FIELDS�IN�THE�ECA�BLOCK*?*ˆ+-----------------------------+-----------------------------+'*‚$20ƒ|‡N0�-�Reserved‰|ˆN1�-�Reservedˆ|?*ˆ+-----------------------------+-----------------------------+'*‚$22ƒ|‡N2�-�Reserved‰|ˆN3�-�Reservedˆ|?*ˆ+-----------------------------+-----------------------------+,*‚$24ƒ|†N4�-�Post-Data�Gap…|ˆN5�-�Reservedˆ|?*ˆ+-----------------------------+-----------------------------+(*‚$26ƒ|†Sector�Length�Code…|‹Fill�Byte‰|?*ˆ+-----------------------------+-----------------------------+* ‰CMP.B„#0,D2 '‰IF��THEN’Execute�for�drive�type�0:2‰LEA†FORMATS(PC),A0‡Single-density�8"�floppy�disk.9‰MOVE.Lƒ(A0),N4(A2)ŠGet�the�fields�from�the�link�AND�from8‰MOVE.Lƒ#FRMT_SD,D0Šconstants�at�the�end�of�driver�code.,‰MOVE.BƒD0,N4(A2)ŒPut�it�into�the�ECA�block.‰ENDI ‰CMP.B„#1,D2 '‰IF��THEN’Execute�for�drive�type�1:2‰LEA†FORMATD(PC),A0‡Double-density�8"�floppy�disk.9‰MOVE.Lƒ(A0),N4(A2)ŠGet�the�fields�from�the�link�AND�from8‰MOVE.Lƒ#FRMT_DD,D0Šconstants�at�the�end�of�driver�code.,‰MOVE.BƒD0,N4(A2)ŒPut�it�into�the�ECA�block.‰ENDI PAGE ‰CMP.B„#2,D2 '‰IF��THEN’Execute�for�drive�type�2:N)‰LEA†FORMATD(PC),A0‡Hard�disk�using�ECC�-9‰MOVE.Lƒ(A0),N4(A2)ŠGet�the�fields�from�the�link�AND�from8‰MOVE.Lƒ#FRMT_HD,D0Šconstants�at�the�end�of�driver�code.,‰MOVE.BƒD0,N4(A2)ŒPut�it�into�the�ECA�block.‰ENDI ‰CMP.B„#3,D2 '‰IF��THEN’Execute�for�drive�type�3:)‰LEA†FORMATD(PC),A0‡Hard�disk�using�CRC�-9‰MOVE.Lƒ(A0),N4(A2)ŠGet�the�fields�from�the�link�AND�from8‰MOVE.Lƒ#FRMT_HD,D0Šconstants�at�the�end�of�driver�code.,‰MOVE.BƒD0,N4(A2)ŒPut�it�into�the�ECA�block.‰ENDI ‰CMP.B„#4,L D2 '‰IF��THEN’Execute�for�drive�type�4:4‰LEA†FORMATS(PC),A0‡Single-density�5.25‚floppy�disk.9‰MOVE.Lƒ(A0),N4(A2)ŠGet�the�fields�from�the�link�AND�from8‰MOVE.Lƒ#FRMT_SD,D0Šconstants�at�the�end�of�driver�code.,‰MOVE.BƒD0,N4(A2)ŒPut�it�into�the�ECA�block.‰ENDI ‰CMP.B„#5,D2 '‰IF��THEN’Execute�for�drive�type�5:4‰LEA†FORMATD(PC),A0‡Double-density�5.25‚floppy�disk.9‰MOVE.Lƒ(A0),N4(A2)ŠGet�the�fields�from�the�link�AND�from8‰MOVE.Lƒ#FRMT_DD,D0Šconstants�at�the�end�of�driver�code.,‰MOVE.BƒD0,N4(A2)ŒPut�it�into�the�ECA�block.‰ENDI PAGE*F*‚Now�we�get�to�select�the�work�we're�going�to�do�based�on�the�type�ofF*‚command.‚Most�of�the�work�is�going�to�be�for�format�commands�because(*‚of�the�buffer�we're�required�to�build.*7‰CMP.Bƒ#FMTFUNC,IOFUNCT(A1)‚Test�the�I/O�function�code.&‰IF†�THEN�If�NOT�a�format�command,6ŠMOVE.L�IOSECTOR(A1),D0‡Get�the�logical�sector�number.)ŠBSR.L‚FILLCHS�Convert�to�CYL.HEAD.SECTOR1ŠBSR.L‚CHS2BUF�Fill�the�buffer�fields�in�the�ECA. ‰ELSE.L 3ŠCMP.W‚#IOPTRK,IOOPTS(A1)†If�format�track-by-track,ŠIF…�THEN�*(‹TST.L‚IOSECTOR(A1)‹Test�for�track�zero.1‹IF…‚THEN�If�we're�track�0,�do�the�following: N>ŒBTSTW‚#IOARDISC,CONFGBLK+IOSATW(A1)‚If�this�is�a�floppy�disk,.ŒIF…‚THENŒand�the�bytes�per�sector�is�256,:�CMP.W‚#VDOSRSZ,CONFGBLK+IOSPSM(A1)�then�we�need�to�set�up,�IF�‚THEN�HALFSCTS.‚Take�the�sectors�per(ŽCLR.L‚D0’track,�divide�by�2,�and�we�now>ŽMOVE.B�CONFGBLK+IOSSPT(A1),D0‚have�HALFSCTS�for�this�command. ŽASR.L‚#1,D0ŽMOVE.L�D0,HALFSCTS(A1)�ENDIŒENDI‹ENDI@‹MOVE.L�#0,IOSCTCNT(A1)†Clear�the�IOSCTCNT�field�in�drive�block.ŠENDI *‰CMP.Wƒ#IOPDSK,IOOPTS(A1)„If�format�drive,6‰IF†�THEN�Put�the�total�number�sectors�in�IOSCTCNT(ŠMOVE.L�CONFGBLK+IOSRSZ(A1),IOSCTCNT(A1)‰ENDI PAGE2‰CMP.Wƒ#IOPBAD,IOOPTS(A1)„If�format�sector�as�bad, ‰IF†�THEN*@*ˆThe�alternate�sectors�command�is�not�supported�under�VERSAdos.NNNNNB*ˆIf�the�user�has�set�the�option�bit,�then�we�abort�with�an�error.*.‰MOVE.B„#ISTAIF,D1”Set�D1�with�the�error�code,‰BRA.S…BLD_OUT—and�exit. (‰ELSEšWe're�formatting�but�none�are�BAD. :‰MOVE.Bƒ#0,BADSEC(A1)ˆSet�this�field�to�indicate�none�BAD.6‰MOVE.LƒIOSECTOR(A1),D0†Get�the�logical�sector�number.3‰BSR.L„FILLCHSŽConvert�LSN�to�cylinder,head,sector. ‰ENDI 6‰TST.L„FORMBUFF(A1)‰See�if�we�already�have�a�buffer... ‰IF‚�THEN )‰MOVE.Lƒ#FORMSIZE,A0‰Ask�for�format�size./‰MOVE.LƒL #4,D0�Service�request�code�for�PAGEALOC8‰MOVEM.L‚A1/A2,-(SP)ŠSave�A1�for�this�type�of�exec�call.‰BSR.L„EXECREQ ‰MOVEM.L‚(SP)+,A1/A2ŠRestore�A1.=‰MOVE.LƒA0,FORMBUFF(A1)†Save�address�of�format�buffer�in�CCB. ‰ENDI ,‰BSR.L„BLDBUFFŽDo�this�for�all�format�types. ‰ENDI PAGE*!*–COMPLETE�THE�ECA�COMMAND�FIELDS*?*ˆ+-----------------------------+-----------------------------+$*‚$�0ƒ|ˆCommand�Code‰|‰Main�Status‰|?*ˆ+-----------------------------+-----------------------------+*‚$�2ƒ|•Extended�Status—|?*ˆ+-----------------------------+-----------------------------+>*‚$�4ƒ|‚Maximum�Number�of�Retries‚|‚Actual�Number�of�Retriesƒ|?*ˆ+-----------------------------+-----------------------------+$*‚$�6ƒ|‰DMA�TypeŒ|‡Command�Options‡|?*ˆ+-----------------------------+-----------------------------+* ***¤COMMAND�CODE�etc..‰MOVE.Lƒ#0,CMDCODE(A2)‡Clear�the�status�bytes./‰MOVE.BƒIOFUNCT(A1),D0‡D0�<--�I/O�function�code ‰EXT.W„D0“*B‰MOVE.BƒOPTBL(PC,D0),CMDCODE(A2)�Use�table�to�set�code�in�the�ECA. ***¤RETRIES�AND�COMMAND�OPTIONS6‰MOVE.Lƒ#0,MAXRETRY(A2)†Clear�retry�and�options�bytes.2‰BTSTW„#IOPRTYB,IOOPTS(A1)‚Test�retry�options�bit.‰IF��THEN’If�cleared,C‰MOVE.Bƒ#RETRY,MAXRETRY(A2)‚Set�the�maximum�retry�count�in�the�ECA.@‰MOVE.Bƒ#OPT,CMDOPT(A2)†Set�command�option�for�error�correction. ‰ELSEšIf�set,B‰MOVE.Bƒ#MINTRY,MAXRETRY(A2)�keep�options�=�0�but�set�retries�=�1.‰ENDI ***¤DMA�TYPE5‰MOVE.Bƒ#DMA,DMATYPE(A2)…Set�the�DMA�type�in�the�ECA.‰CLR.B„D1“Set�good�status. BLD_OUT:9‰MOVEM.L‚(SP)+,D0/D2/A0/A2„Restore�the�registers�we�used.#‰TST.B„D1“Set�the�status�on�return.‰RTS  O*********************************************************************************ˆVME320�COMMAND�CODE�TABLE*B*ˆThis�table�contains�the�VME320�defined�command�codes�for�the�I/O!*ˆoperations�currently�supported.*O******************************************************************************* 0‰DC.B…WRITE�Write�command‚(6):�IOFUNCT�equals�-14OPTBL„DC.B…FRMT‘Format�command�(7):�IOFUNCT�equals‚0/‰DC.B…SEEK‘Configure-seek�(0):�IOFUNCT�equals‚1-‰DC.B…READ‘Read�commandƒ(5):�IOFUNCT�equals‚2‰DS.W†0“End�of�table‰PAGEN******************************************************************************* *ˆDISK_START*C*ˆThis�is�a�device�dependent�routine�whose�offset�must�be�installedE*ˆat�the�beginning�of�the�driver.�The�function�of�this�routine�is�to:*.*Š1.‚Set�up�the�device-dependent�fields�in�the*Ždrive's�variable�block.-*Š2.‚Set�up�for�command�queueing�if�required./*Š3.‚If�the�drive�is�not�busy,�tell�the�command*Žto�the�controller.**D*ˆEntry:�A1�=�address�of�the�drives�variable�block�in�global�memory.#*�A5�=�physical�address�of�the�CCB.*=*�Interrupt�level�on�entry�is�at�our�hardware�level�(masked).*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚* *™A‚*�P‡P**ˆCalls:�INTLOOP**ˆExit:‚RTS�to�caller.*N****************************************************************************** DISK_START: ‰PUSH…SR/‰MOVEM.L‚D0/A0,-(A7)ŠSave�any�registers�we�use. 6‰LEA†IOQCNT(A5),A0ŠPut�the�pointer�to�the�drive's�area8‰MOVE.Wƒ(A0),D0Žof�global�memory�into�the�next�available;EQ180„EQU†IOQUEUE-IOQCNT‡queue�entry,�and�advance�the�queue=‰MOVE.LƒA1,EQ180(A0,D0.W)„pointer.‚We�don't�need�to�check�for2‰ADD.W„#4,(A0)Žqueue�overflow�because�we�can�never&*¦accumulate�more�than�one�queue�entry'*¦for�each�drive.‚We�also�don't�need�to(*¦check�for�queue�wrap-around�because�we'*¦physically�move�queue�entries�instead&*¦of�using�wrap-around�queue�pointers. -‰TST.W„D0•If�the�queue�wasn't�empty�before�we/‰BNE†L0410�made�the�latest�entry,�the�interrupt$*¦handler�is�already�active�and�will)*¦eventually�complete�the�I/O�transaction'*¦that�we've�just�specified.‚Otherwise,#*¦we�need�to�activate�the�interrupt *¦handler.‰PAGE8‰LEA†PROCQUE(PC),A0‰Set�up�the�co-routine�switch�pointer@‰MOVE.LƒA0,INTSWTCH(A5)†to�start�processing�new�I/O�queue�entry.<‰MOVE.LƒCCBCHB(A5),AM 0ˆA0�<--�VME320�memory-mapped�I/O�space. ,‰BSR†INTLOOPŽTell�command�to�the�controller.*C*ƒNow�we�have�started�off�the�I/O�and�are�ready�to�return�to�CMR�to(*ƒbe�awakened�when�an�interrupt�arrives.* 9L0410„MOVEM.L‚(A7)+,D0/A0ŠRestore�registers�that�we�used.‰POP‡SR‰RTS‰SPC‡15‰PAGEN********************************************************************************ˆCHK_PARAM�ROUTINE*C*ˆThis�is�a‚device�dependent‚routine�whose‚offset�must‚be�installedD*ˆat�the�beginning�of�the�driver.�The‚function�of‚this�routine‚is�toB*ˆvalidate‚any‚device‚dependent‚parameters.‚This�routine�is�called?*ˆafter�the‚user's‚configuration‚block‚has‚been‚filled‚with‚theG*ˆproposed�configuration.�Therefore,�A0�points�to�the�end�of�the�user's*ˆconfiguration�block.*/*ˆEntry:�A0�=�end�of�user's�configuration�block* *�Interrupt�level�on�entry�is�0.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™DˆR*™A‚P* *ˆCalls:�none*$*ˆExit:‚RTS�back�to�calling�routine.>*�CONDITION�CODES:��no�errors�in�this�configuration�check.* �an�error�was�found./*�D3.B�=�Returned�error�code�if�error�is�found.*F*ˆThe�interrupt�level�upon�exit�must�be�the�same�as�it�was�upon�entry.*N****************************************************************************** CHK_PARAM: ‰CMP.B…D0,D0�Set�condition�codes ‰RTS›Return.‰PAGEN******************************************************************************* *‰END�ROUTINES�CALLED�BY�DISKLIB*N******************************************************************************‰PAGEO********************************************************************************7*ˆSUBROUTINES�USED�BY�THE�COMMAND�AND�INTERRUPT�HANDLER*O*******************************************************************************  O********************************************************************************9*ˆCONVERT�THE�PHYSICAL�STARTING�SECTOR�NUMBER�ON�THE�DISK*B*ˆThis�routine�converts�the�Physical�sector�number�contained�in�D0>*ˆto�the�cylinder�number,�head�number�and�sector�number�fields/*ˆrequired�for�the�ECA�packet,�and�stores�them.*:*ˆEntry:„A1�=�Pointer�to�drive's�variable�block�in�the�CCB#*’A2�=�Pointer�to�drive's�ECA�block.*’D0�=�Physical�sector�number�to�be�converted.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚R�R�R*™A„P�P**ˆExit:…D0.W�=�Cylinder�number*’D1.B�=�Head�number5*’D2.B�=�Sector�number�within�track�(starting�with�1)*8*ˆExits�to:‚Command�Handler�or�Interrupt�Handler�via�RTS***‘PSN=*ˆ---------------------------ƒ=�Cylinder�number�+�Remainder�1*ˆSectors�per�Track�*�#�Heads* *‹Remainder�10*ˆ------------------Œ=�Head�number�+�Remainder�2*ˆSectors�per�Track*/*ˆRemainder�2“=�Sector�number�(counting�from�0)*B*ˆNOTE:„This�driver�sometimes�refers�to�the�physical�sector�number9*‘as�the�logical�sector�number�-�they�are�the�same�thing.*O******************************************************************************* SPC 2*+*’COMPLETE�SECTOR�ADDRESS�FIELDS�IN�THE�ECA*?*ˆ+-----------------------------------------------------------+*‚$10ƒ|–Cylinder�Number–|?*ˆ+-----------------------------+-----------------------------+0*‚$12ƒ|„Head�or�Surface�Numberƒ|‡Sector�Number‰|?*ˆ+-----------------------------+-----------------------------+* PAGE FILLCHS: ‰CLR.L„D1 ‰CLR.L„D2 -‰MOVE.WƒSURF(A1),D1�D1�<--�Number�of�surfacesA‰MOVE.BƒCONFGBLK+IOSSPT(A1),D2„D2�<--�Number�of�sectors�per�track3‰MULU…D2,D1�D1�<---�Number�of�surfaces�*�sect/track$‰DIVU…D1,D0�D0.W�<--�Cylinder�number ‰MOVE.LƒD0,D1/‰LSR.L„#8,D1�Shift�remainder�1�for�next�divide.!‰LSR.L„#8,D1�D1.W�<--�Remainder�1 ‰DIVU…D2,D1�D1.W�<--�Head�number ‰MOVE.LƒD1,D2-‰SWAP…D2“D2.W‚<---�Sector�number�in�the�track4‰ADDQ.Lƒ#1,D2�VME320�counts�sectors�starting�at�one. ;‰MOVE.WƒD0,CYLNUM(A2)ˆPut�cylinder�number�in�the�ECA�block.8‰MOVE.BƒD1,HEADNUMM (A2)‡Put�head�number�in�the�ECA�block.:‰MOVE.BƒD2,SECTNUM(A2)‡Put�sector�number�in�the�ECA�block. ‰RTS PAGEO*********************************************************************************ˆCHS�TO�BUFFER�ADDRESS*8*ˆThis�routine�fills�the�buffer�fields�in�the�ECA�block.-*ˆIt�uses�the�fields�of�the�I/O�packet�storedA*ˆearlier�to�make�calculations�about�transfer�lengths.‚It�updates;*ˆfields�in�the�I/O�packet�that�are�used�later�to�determine@*ˆif�the�command�has�been�completed.‚This�routine�is�called�from1*ˆboth�the�command�handler�and�interrupt�handler.*@*ˆEntry:„A1�=�Pointer�to�drive's�variable�block�in�global�memory#*’A2�=�Pointer�to�drive's�ECA�block*’D0.W�=�Cylinder�number�}3*’D1.B�=�Head�number…}�-�defining�starting�sector�#*’D2.B�=�Sector�numberƒ}*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�**™A„P�P*D*ˆExit:�(1)�Sets�the�buffer�fields�in�ECA�block�for�read/write�only.;*Ž(2)�Modifies�N4,�SLC�and�DRVTYPE�fields�in�the�ECA�packet7*’for�track�0�accesses�on�a�double-density�floppy�disk.<*Ž(3)�Updates�the�I/O�packet�to�determine�command�completion#*’for�read�and�write�commands�only.**ˆExits�to:�Caller�via�RTS*O******************************************************************************* SPC 2* *•COMPLETE�THE�ECA�BUFFER�FIELDS*?*ˆ+-----------------------------+-----------------------------+%*‚$�8ƒ|“Buffer�Address�(upper�word)�|?*ˆ+-----------------------------+-----------------------------+%*‚$�Aƒ|“Buffer�Address�(lower�word)�|?*ˆ+-----------------------------+-----------------------------+!*‚$�Cƒ|“Buffer�Length�Requested‘|?*ˆ+-----------------------------+-----------------------------+,*‚$�Eƒ|ŽActual�Number�of�Bytes�Transferred‹|?*ˆ+-----------------------------+-----------------------------+* PAGE CHS2BUF;‰MOVE.LƒIOBUFLEN(A1),D0†D0�<--�number�of�bytes�to�transfer.8‰IF��THEN.L�Buffer�length�is�zero�for�format�&�seek. =‰MOVE.LƒHALFSCTS(A1),D1†D1�<--�sector�transfer�across�track�0 ‰IF��THEN0ŠMULU…#128,D1�D1�<--�#�bytes�to�transfer�track�08ŠMOVE.Bƒ#0,SLC(A2)ŠChange�sector�length�code�in�the�ECA.ŠMOVE.Lƒ#FRMT_SD,D2‰*1ŠMOVE.BƒD2,N4(A2)‹Change�format�field�in�the�ECA.?ŠBTST.Bƒ#0,DRVTYPE(A2)†Making�sure�drive�type�indicates�double-ŠIF��THEN‘*>ŠSUB.B„#1,DRVTYPE(A2)†Change�drive�type�code�to�single�densityŠENDI-ŠSUB.L„D1,D0�D0�<--�#�bytes�to�transfer�next. ‰ELSE4ŠMOVE.Lƒ#MAXB,D1ŒD1�<--�max�number�of�bytes�to�xfer./ŠCMP.L„D1,D0�Compare�to�number�bytes�requested.3ŠIF��THEN‘Branch�if�the�transfer�is�within�max.-ŠSUB.L„D1,D0�Subtract�maximum�from�requested.&ŠELSE™D0�<--�#�bytes�to�transfer�next.-ŠMOVE.LƒD0,D1�D1�<--�#�bytes�to�transfer�now./ŠMOVEQ.L‚#0,D0�D0�<--�#�bytes�to�transfer�next.ŠENDI‰ENDI PAGE*.*‚Copy�the�buffer�length�(in�bytes)�to�the�ECA'*ˆD1�=�Number�of�bytes�to�transfer�NOW.(*ˆD0�=�Number�of�bytes�to�transfer�NEXT.*8‰MOVE.WƒD1,BUFLEN(A2)ˆCopy�the�bytes�to�transfer�to�ECA. &‰MOVE.LƒA0,-(SP)�Save�A0�on�the�stack./‰MOVE.LƒIOBUFPTR(A1),A0†Get�the�buffer�address.+‰GO_OFF_BD�A0’Adjust�if�there�is�an�offset.:‰MOVE.LƒA0,BUFADDR(A2)‡Copy�the�buffer�address�to�the�ECA.‰MOVE.Lƒ(SP)+,A0�Restore�A0.*$*ƒHousekeeping�in�the�drive�block...*5‰ADD.L„D1,IOBUFPTR(A1)†<--�1st�byte�to�transfer�next.5‰MOVE.LƒD0,IOBUFLEN(A1)†<--�#�bytes�to�transfer�next. ‰DIVU…BPS(A1),D17‰ADD.L„D1,IOSECTOR(A1)†<--�1st�sector�to�transfer�next.‰DIVU…BPS(A1),D07‰MOVE.LƒD0,IOSCTCNT(A1)†<--�#�sectors�to�transfer�next. ‰TST.L„HALFSCTS(A1) ‰IF��THEN ŠCLR.L‚D0ŠMOVE.B�CONFGBLK+IOSSPT(A1),D08ŠMOVE.L�D0,IOSECTOR(A1)‡<--�1st�sector�to�transfer�next.,‰ENDIš(double-density�floppies/track�0�only) ‰ENDI ‰RTS *A*„NOTES�ON�MULTIPLE�TRANSFERS:‚Mulitple�block�transfers�can�occurN*‚when:�(1)�the�data�transfer�crosses�the�track�0�boundary�of�a�double-densityL*‚floppy�disk�and�(2)�the�data�transfer�is�larger�than�the�maximum�number�of*‚byteN s�allowed�by�the�VME320.* PAGEO*********************************************************************************ˆBUILD�FORMAT�BUFFER�ROUTINE*A*ˆThis�routine�builds�the�format�buffer�for�the�VME320�controllerA*ˆboard.‚It�uses�fields�from�the�ECA�packet�for�its�computations.?*ˆIt�implements�interleaving�and�spiral�offset.�This�routine�is=*ˆcalled�from�both�the�interrupt�handler�and�command�handler.*@*ˆEntry:„A1�=�Pointer�to�drive's�variable�block�in�global�memory#*’A2�=�Pointer�to�drive's�ECA�block*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�*�**™A„P�P*C*ˆExit:�(1)�Sets�the�buffer�fields�in�the�ECA�block�for�format�cmd.:*Ž(2)�Builds�the�format�buffer�for�one�track,�implementing.*’'format�sector�as�bad'�option�from�VERSAdos.**ˆExits�to:�Caller�via�RTS*O******************************************************************************* ?BLDBUFF‚MOVEM.L‚D4/A0/A3,-(SP)‡Save�working�registers�on�stack. ‰CLR.L„D2%‰MOVE.WƒSPT(A1),D2‹Sectors�per�track. 0‰CMP.W„#IOPDSK,IOOPTS(A1)ƒTest�the�command�type. ‰IF��THEN’Housekeeping...;‰SUB.LƒD2,IOSCTCNT(A1)‡Decrement�sector�count�format-drive.;‰ADD.LƒD2,IOSECTOR(A1)‡Increment�start�sector�format-drive.‰ENDI :‰TST.L„HALFSCTS(A1)‰Execute�for�track�0�on�DD�floppy�only: ,‰IF‡�THENŒReset�these�fields�in�the�ECA::‰MOVE.Bƒ#0,SLC(A2)‹Change�sector�length�code�to�128�bytes.‰MOVE.Lƒ#FRMT_SD,D0Š*6‰MOVE.BƒD0,N4(A2)ŒChange�N4�to�reflect�single�density.0‰BTST.Bƒ#0,DRVTYPE(A2)‡Change�drive�type�code...1‰IF‡�THENŒMake�sure�it�indicates�DD�before�we‰SUB.B„#1,DRVTYPE(A2)‡subtract.‰ENDI‰ENDI :‰LEA†SECTBUFF(A5),A0†Get�pointer�to�sector�numbers�buffer.,‰MOVE.LƒA0,A3�A0�<--�Sector�number�buffer�#1 PAGEL****************************************************************************>*ˆBUILD�STRING�OF�SECTOR�NUMBERS�USING�THE�INTERLEAVE�FACTORˆ*L*****************************************************************************E*‚A0�=�Pointer�to�sector�number�buffer�#1�used�for�interleave�factors9*‚A1�=�Pointer�to�drive's�variable�block�in�global�memory#*‚A2�=�Pointer�to�drive's�ECA�block*‚D0�=�Scratch*‚D1�=�Scratch*‚D2�=�Sectors�per�track,*‚D4�=�Scratch�(will�hold�interleave�factor) ‰CLR.L„D4E‰MOVE.BƒCONFGBLK+IOSILV(A1),D4�Interleave�factor�from�configure�block$‰IF‡�THENŒIf�NOT�zero,�its�okay.4‰MOVEQ.L‚#1,D4�Make�the�factor�of�zero�equal�to�one.‰ENDI 4*ˆCMP.W„#IOPBAD,IOOPTS(A1)ƒFormat�command�options...'*ˆIF‡�THENŒIf�format�sector�as�bad,,*ˆCMP.B„#1,D4�And�interleaving�is�specified,*ˆIF‡�THEN<*ˆMOVE.Bƒ#1,BADSEC(A1)ˆForce�entire�track�to�be�formated�BAD*ˆENDI*ˆENDI &‰MOVEQ.L‚#1,D0�Starting�sector�number.)‰BRA†RW_INTBŽBranch�to�entry�inside�loop. +RW_INTA‚MOVE.BƒD1,(A0)+�Copy�sector�number.#‰ADD.L„D4,D1�Add�interleave�factor.8‰CMP.W„SPT(A1),D1‹Have�we�got�to�the�last�sector�number?$‰BLE†RW_INTCŽBranch�if�last�or�less./‰ADDQ.Lƒ#1,D0�Increment�starting�sector�number. * Enter here.RW_INTB‚MOVE.LƒD0,D1�Copy�to�working�register.RW_INTC‚DBRA…D2,RW_INTA PAGEL****************************************************************************:*ˆBUILD�STRING�OF�SECTOR�NUMBERS�USING�THE�SPRIAL�OFFSETŒ*L*****************************************************************************I*‚A0�=�Pointer�to�sector�number�buffer�#2�used�to�implement�spiral�offset9*‚A1�=�Pointer�to�drive's�variable�block�in�global�memory#*‚A2�=�Pointer�to�drive's�ECA�blockB*‚A3�=�Pointer�to�start�of�sector�number�buffer�#1�(saved�earlier)*‚D0�=�Scratch*‚D1�=�Scratch*‚D2�=�Scratch(*‚D4�=�Scratch�(will�hold�spiral�offset) ‰CLR.L„D4:‰MOVE.BƒCONFGBLK+IOSSOF(A1),D4„D4�<--‚Spiral�offset�value.'‰IF‡�THENŒBranch�if�around�if�none. 4*ˆCMP.W„#IOPBAD,IOOPTS(A1)ƒFormat�command�options...'*ˆIF‡�THENŒIf�format�sector�as�bad,<*ˆMOVE.Bƒ#1,BADSEC(A1)ˆForce�entire�track�to�be�formated�BAD*ˆENDI :‰MOVE.WƒSPT(A1),D2‹Get�the�number�of�sectors�in�the�track.&N ‰SUBQ.Lƒ#1,D2�D2�<--�DBxx�loop�counter ARW_SOFƒMOVE.Bƒ(A3)+,(A0)+ŠCopy�the�sector�numbers�w/�interleaving(‰DBRA…D2,RW_SOFŒto�the�buffer�following. <‰MOVE.BƒHEADNUM(A2),D0‡D0�<--�surface�number�from�ECA�block.+‰MULU…D0,D4�Spiral�Offset�*�Surface�number.%‰MOVE.WƒSPT(A1),D2‹Sectors�per�track.)‰SUB.L„D4,D2�Offset�due�to�spiral�offset.2‰LEA†SECTBUFF(A5),A3†Pointer�to�interleave�buffer.-‰ADDA.LƒD2,A3�A3�<--�string�of�sector�numbers ‰ENDI  PAGE2***************************************************ˆCOMPLETE�THE�FORMAT�BUFFERŽ*2***************************************************3*‚A0�=�Scratch‚(will�hold�pointer�to�format�buffer)9*‚A1�=�Pointer�to�drive's�variable�block�in�global�memory#*‚A2�=�Pointer�to�drive's�ECA�blockM*‚A3�=�Pointer�to�string�of�sector�numbers�w/�interleaving�and�spiral�offsets*‚D0�=�Scratch*‚D1�=�Scratch*‚D2�=�Scratch*<‰MOVE.LƒFORMBUFF(A1),A0†A0�<--�Pointer�to�the�format�buffer.;‰MOVE.BƒBADSEC(A1),D0ˆD0�<--�Bad�sector�in�alternate�track.  *¦NOTE:�BADSEC�has�been�set�to�0$*¦if�this�was�not�a�format�sector�as*¦bad�command. ‰CLR.L„D2:‰MOVE.WƒSPT(A1),D2‹Get�the�number�of�sectors�in�the�track.&‰SUBQ.Lƒ#1,D2�D2�<--�DBxx�loop�counter �THENŒBuild�the�buffer�for�GOOD�sectors... 9‰BTST.Bƒ#1,DRVTYPE(A2)‡Drive�type�defines�#�bytes/sector:3‰BEQ†FMT_FLOP�5-bytes�for�hard�disks/4-bytes�floppy=‰MOVE.BƒCYLNUM(A2),(A0)+…Copy�the�MSB�of�the�cylinder�number.GFMT_FLOP�MOVE.BƒCYLNUM+1(A2),(A0)+ƒCopy�the�LSB�of�the�cylinder�number.+‰MOVE.BƒHEADNUM(A2),(A0)+„Head�number�-�all'‰MOVE.Bƒ(A3)+,(A0)+ŠSector�number�-�all.‰MOVE.BƒSLC(A2),(A0)+ˆSector�length�code�-�all )‰ELSEšBuild�the�buffer�for�BAD�sectors... '‰MOVEQ.L‚#2,D1�D1�<--�DBxx�loop�counterHBAD_SEC‚MOVE.BƒCYLNUM(A2),(A0)+…Copy�the�MSB�of�the�Bad�cylinder�number.C‰MOVE.BƒCYLNUM+1(A2),(A0)+ƒCopy�the�LSB�of�the�Bad�cylinder�number.)‰MOVE.BƒHEADNUM(A2),(A0)+„Bad�head�number$‰MOVE.Bƒ(A3),(A0)+‹Bad�sector�number;‰MOVE.Bƒ#$FF,(A0)+‹Force�SLC�to�$FF�to�indicate�BAD�sector.7‰MOVE.BƒALTCYL(A1),(A0)+…Alternate�cylinder�number�MSB.9‰MOVE.BƒALTCYL+1(A1),(A0)+ƒAlternate�cylinder�number�LSB./‰MOVE.BƒALTHEAD(A1),(A0)+„Alternate�head�number*‰MOVE.Bƒ(A3),(A0)+‹Alternate�sector�number5‰MOVE.BƒALTSLC(A1),(A0)+…Alternate�sector�length�code+‰MOVE.Bƒ#72,(A0)+ŒPost�ID�gap�(fixed�value)8‰DBRA…D1,BAD_SEC‹Repeat�to�get�2�ID�headers�written�out. 2‰ADD.L„#1,A3�Increment�A3�to�point�to�next�sector.‰ENDI 5‰DBRA…D2,FMT_LOOPŠComplete�the�buffer�-�date�required *¦for�every�sector�in�the�track. PAGE*<*‚The�buffer�is�built�-�Fill�buffer�fields�in�the�ECA�block.*8‰MOVE.LƒFORMBUFF(A1),D2†D2�<--�1st�byte�in�format�buffer0‰MOVE.LƒA0,D1�D1�<--�1st�byte�past�format�buffer-‰SUB.L„D2,D1�D1�=�length�of�the�format�buffer-‰MOVE.LƒD2,A0�D2�=�start�of�the�format�buffer/‰GO_OFF_BD�A0’Adjust�for�dual-port�ram�address. <‰MOVE.LƒA0,BUFADDR(A2)‡Put�the�format�buffer�address�in�ECA.=‰MOVE.WƒD1,BUFLEN(A2)ˆPut�the�length�of�format�buffer�in�ECA.*>*‚Replace�the�sectors�per�track�field�for�bad�sector�handling.* ‰CLR.L„D2“*4‰MOVE.WƒSPT(A1),D2‹D2�<--�current�sectors�per�track.=‰MOVE.BƒBADSEC(A1),D0ˆTest�flag�indicating�bad�sector�number.3‰IF‡�THENŒIf�flag�is��then�we�a�bad�sector.<‰ADD.B„#2,NUMSPT(A2)ˆAdd�to�the�number�of�sectors�per�track.‰ELSE<‰MOVE.BƒD2,NUMSPT(A2)ˆRestore�sectors�per�track�if�all�good.‰ENDI*I*‚Now�this�is�interesting.‚In�order�to�format�a�sector�as�bad�and�specifyM*‚an�alternate,�the�number�of�sectors�per�track�must�be�adjusted�to�equal�theG*‚number�of�'CYL-HEAD-SECTOR�#...'�data�sequences�in�the�format�buffer.J*‚When�all�the�sectors�are�good,�then�this�field�exactly�equals�the�numberI*‚of�sectors�in�the�track.‚When�any�bad�sectors�are�specified,�this�fieldF*‚is�increased�by�3�times�the�number�of�bad�sectors�to�account�for�theF*‚three�ID�headers�specifying�the�alternate�written�to�tO he�bad�sector.*+‰MOVEM.L‚(SP)+,D4/A0/A3‡Restore�from�stack.‰RTS PAGEO*********************************************************************************ˆMEMORY�RETURN*<*ˆThis�routine�is�called�by�the�interrupt�handler�for�format:*ˆcommands.‚It's�purpose�is�to�return�the�global�memory�it<*ˆrequested�for�the�format�buffer�which�is�no�longer�needed.*@*ˆEntry:„A1�=�Pointer�to�drive's�variable�block�in�global�memory*’A5�=�Address�of�our�CCB.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚*�**™A‚P**ˆExit:…To�caller�if�no�errors*’To�killer�if�error*O******************************************************************************* MEMRTNNNN9‰MOVEM.L‚D1/A0,-(A7)ŠSave�important�regs�we'll�blow�away.)‰MOVE.Lƒ#FORMSIZE,D1‰Ask�for�format�size./‰MOVE.Lƒ#5,D0�Service�request�code�for�PAGEFREE%‰MOVE.LƒFORMBUFF(A1),A0†Start�address8‰MOVE.Lƒ#0,FORMBUFF(A1)†Clear�the�format�buffer�pointer. ‰BSR†EXECREQ'‰MOVEM.L‚(A7)+,D1/A0ŠRestore�A0�and�D1.‰RTS‰PAGEO******************************************************************************** *ˆEXECREQ*9*ˆThis�subroutine�is�called�by�the�format�command�to�both<*ˆget�system�memory�to�use�as�a�format�buffer,�and�to�return:*ˆsystem�memory.�The�calls�it�is�used�for�are�PAGEALOC�and<*ˆPAGEFREE.�The�registers�(D0,�A0,�A1)�have�been�set�for�the*ˆparticular�call�before�entry.*9*ˆEntry:„A0�=�Format�buffer�size�in�pages�(PAGEALOC�only)+*•=�Start�address�of�memory�(PAGEFREE�only)9*’A1�=�Pointer�to�drive's�variable�block�in�global�memory*’A2�=�Pointer�to�somethingNNNN*’A5�=�Address�of�our�CCB.*’D0�=�Service�request�code.:*’D1�=�Buffer�size�in�pages�to�be�returned�(PAGEFREE�only)*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D*™A„P�P**ˆExit:…To�caller�if�no�errors*’To�killer�if�error*O******************************************************************************* EXECREQ::‰MOVEM.L‚A1/A2,-(SP)ŠSave�A1/A2�on�this�type�of�exec�call.‰TRAP…#0“Execustive�request‰BRA†GOOD_CALLŒGood�return."‰MOVEM.L‚(SP)+,A1/A2ŠRestore�A1/A2/‰KILL.DRIVER�M320DRV_IO D,BOTH_A_F,A5,DCBPNTR(A1) GOOD_CALL"‰MOVEM.L‚(SP)+,A1/A2ŠRestore�A1/A2‰RTS‰PAGEN********************************************************************************‰FINISH�OFF�THE�INITIALIZATION*2*‰These�other�device-dependent�things�MUST�be�done>*‰before�we�can�handle�commands.‚They�probably�could�have�been?*‰done�in�INIT�at�the�start�of�the�driver�but�are�handled�here.*=*‰1.‚Allocate�global�memory�for�the�Event�Control�Areas�(ECA)$*‰2.‚Initialize�ECA�Address�Pointer.-*‰3.‚Initialize�ECA�drive�interrupt�register.6*‰4.‚Initialize�ECA�drive�source�and�status�registers.**‰Entry:�A5�=�address�of�CCB.* *‰Calls:�none*N****************************************************************************** DO_INIT: 8‰MOVE.Lƒ#PAGES,A0ŽAllocate�global�memory�for�one�ECA�for5‰MOVE.Lƒ#4,D0�each�possible�device�and�the�associated*‰TRAP…#0“ECA�pointer�table.‚The�address�of'*¦the�memory�segment�is�returned�in�A0.*‰BRA†INIT30�Good�return!‰BRA.L„INITERRŽBad�return.INIT30:‰MOVE.LƒA0,ECATABLE(A5)ˆStore�the�ECA�table�address�in�the3‰MOVEQ.L‚#DRIVES,D1‹CCB.‚Clear�all�memory�locations6‰MULU…#PKTLONG,D1Šin�all�four�ECA�packets�plus�the�ECA/‰ADDQ.Lƒ#4,D1�table�itself,�and�restore�the�ECA'INIT45ƒCLR.L„(A0)+�table�address�to�A0.‰DBRA…D1,INIT45‰MOVE.LƒECATABLE(A5),A0‰PAGE*@*ˆAdjust�the�global�ram�address�of�the�ECA�pointer�table�and�the7*ˆECA�packets�if�an�onboard�ram/offset�address�applies.* ‰GO_OFF_BD�A0!*¨Get�the�base�address�of�the�ECA(‰MOVE.LƒA0,D0�Pointer�Table.‚Immediately6‰ADD.L„#16,D0�following�the�table�are�the�ECA�packets.;‰MOVEQ.L‚#DRIVES-1,D1‰Fill�the�ECA�table�in�global�ram�with7‰MOVE.LƒECATABLE(A5),A0†the�ECA�packet�addresses�of�the>INIT40ƒMOVE.LƒD0,(A0)+�four�possible�drives�on�the�controller.‰ADD.L„#PKTLEN,D0‹*‰DBRA…D1,INIT40Œ* ‰MOVE.LƒECATABLE(A5),A0*@*ˆAdjust�the�global�ram�address�of�the�ECA�pointer�table�and�the7*ˆECA�packets�if�an�onboard�ram/offset�address�applies.* ‰GO_OFF_BD�A0#*©Get�the�ECA�Pointer�Table�address1‰MOVE.LƒA0,D1�into�a�working�register.‚We�have�to4‰ROR.L„#1,D1�translate�the�address�before�we�tell�it5‰MOVEQ.L‚#2,D2�to�the�controller.�The�address�must�be1‰MOVE.BƒD1,D0�divided�by�2�and�the�order�of�bytes4INIT50ƒASL.L„#8,D0�reversed�i.e.�the�MSB�becomes�the.‰ASR.L„#8,D1�LSB�and�the�LSB�becomes�the�MSB�-5‰MOVE.BƒD1,D0�(the�address�AABBCCDD�becomes�DDCCBBAA)‰DBRA…D2,INIT50 9‰MOVE.LƒCCBCHB(A5),A0ŠGet�the�controller�address�and�tell9‰MOVEP.L‚D0,ECA0(A0)Šthe�ECA�Pointer�Table�address�to�theD‰MOVE.BƒCCBVECT(A5),VECTOR(A0)�controller�through�the�ECA�registers.;‰MOVE.Bƒ#0,SOURCE(A0)ˆTell�the�controller�the�vector�number:‰MOVE.Bƒ#0,STATUS(A0)ˆand�initialize�the�source�and�status‰BRA†INITDONE�registers. 4INITERR‚SNE.B„CHANDOWN(A5)‹If�an�error�was�detected,1INITDONE�RTS›shut�the�channel�down�by�setting�the *¦variable�CHANDOWN�to�non-zero. *********************** *‚PATCH�SPACE***********************ŠDS.Wƒ30ŠENDNNNN