IMD 1.17: 25/11/2014 13:08:10 82VKXBVERDOS D* BT21:0 68K VERSADOS/RMS68K OBJECT 4.5 (DS,DD 96 tpi 5.1/4" DISK) REVISED: 04/22/86 DISK 21 OF 24  BT21 82VKXBVERDOS 0420²b-@2H1P.X\`]h;p@xF€9ˆ8�<˜: 7¨;°;¸7À:È?ÐDØLàLèBðCøA;? ‰NOLISTŠTTL…9995.&.STR.EQŠINCLUDE�9995.&.STR.EQ‰NOLISTŠTTL…9995.&.TCB.EQŠINCLUDE�9995.&.TCB.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.&.TRACE.EQŠINCLUDE�9995.&.TRACE.EQ‰NOLISTŠTTL…9995.&.DUALPORT.MCŠINCLUDE�9995.&.DUALPORT.MC‰NOLISTŠTTL…9995.&.KILL.MCŠINCLUDE�9995.&.KILL.MC‰NOLISTŠTTL…9995.&.KILLDRV.EQŠINCLUDE�9995.&.KILLDRV.EQ‰LIST*1ŠTTL…VERSAdos�4.5�MVME331/332�ICC�Driver�VER.�3.0‰PAGE*$*�Envelope�buffer�format‚for�the�ICC* ŠOFFSET‚0.MSG‡DS.L„1‘offset�to�message�part�of�envelope..FLK‡DS.L„1‘offset�to�forward�link�in�envelope.7FLNKB…EQU…*-1�byte�that�makes�forward�link�odd�or�even.ENVLLENƒEQU…*‘envelope�length.*4FLKFLG„EQU…0‘If�bit�0�of�the�foreward�field�is�zero,,*£it�is�a�pointer�to�the�next�envelope,�else%*£this�is�the�end�of�the�linked�list.*#* Message buffer format for the ICC* ŠOFFSET‚-12DCB‡DS.L„1‘DCB�part�of�messageTCBP†DS.L„1‘TCB�part�of�message IOCB†DS.L„1‘IOCB�part�of�messageFLNK†DS.L„1‘FLINK�in�message"CMD‡DS.B„1‘command�part�of�message"PORT†DS.B„1‘port�number�of�message#SAD‡DS.L„1‘start�address�of�message"LEN‡DS.L„1‘length�of�data�transfer"STAT†DS.B„1‘status�byte�of�message'TERM†DS.B„1‘terminating�part�of�message)RLEN†DS.L„1‘return�length�part�of�messageTCMDLENƒEQU…*-DCB* * Buffered Pipe Protocol Equates*)OSLEN…EQU…12�operating�system�part�length8NOPORTSƒEQU…06�number�of�ports�to�use�for�calculation�of *£pool�size.,NOPGPP„EQU…02�number�of�pool�pages�per�port.1TOTPAGES‚EQU…NOPORTS*NOPGPP„total�number�of�pages/TOTBYTES‚EQU…TOTPAGES*256†lotal�number�of�bytes:NOPACKSƒEQU…(TOTBYTES/(TCMDLEN+ENVLLEN))‚number�of�packets** General equates*/ILEN†EQU…6‰length�of�configuration�ITEM�+�DATA.8MAXP†EQU…8‰This�driver�assumes�to�handle�a�MVME332�board3*›and�therefore�device�tables�will�be�allocated�for *›8�ports.;NOSSE…EQU…4‰number�of�solicited�event�packets�on�each�port.1*›These�packets�are�sent�to�the�port�on�the�first*›CONFIGURE�request.=MINPKT„EQU…8‰number�of�packages�which�must�be�present�in�pool0*›to�start�an�I/O�command.�This�value�is�choosen2*›as�some�commamds�e.g.�READ�or�CONFIGURE�needs�up5*›to�5�pakeges.�The�remaining�3�are�for�the�interrupt0*›handler,�to�send�'abort'�commands�on�receiving *›BREAK's.ŠPAGE*'*‚Equates�for�the�configure�ICC�command*!CICCI1„EQU…1‰configure�ICC�ITEM�1!CICCI2„EQU…2‰configure�ICC�ITEM�2!CICCI3„EQU…3‰configure�ICC�ITEM�3!CICCI4„EQU…4‰configure�ICC�ITEM�4!CICCI5„EQU…5‰configure�ICC�ITEM�5!CICCI6„EQU…6‰configure�ICC�ITEM�6*C*‚This�are�the�bit�definitions�for�Solicited�Event�Record�and�State*$BRKB†EQU…0‰solicited�event�BREAK�bit"CTSB†EQU…1‰solicited�event�CTS�bit"DCDB†EQU…2‰solicited�event�DCD�bit&IR1B†EQU…8‰solicited�event�IRAT�#1�bit&IR2B†EQU…9‰solicited�event�IRAT�#2�bit*#*‚This�are�the�cinfigure�port�items*CPI01…EQU…1‰configure�baudrate)CPI02…EQU…2‰configure�number�of�data�bits)CPI03…EQU…3‰configure�number�of�stop�bits$CPI04…EQU…4‰configure�type�of�parity&CPI05…EQU…5‰configure�DTR�output�state&CPI06…EQU…6‰configure�RTS�output�state%CPI07…EQU…7‰configure�receiver�enable(CPI08…EQU…8‰configure�transmitter�enable"CPI09…EQU…9‰configure�break�enable)CPI10…EQU…10ˆconfigure�DCD�input�function)CPI11…EQU…11ˆconfigure�CTS�input�function#CPI12…EQU…12ˆconfigure�read�timeout$CPI13…EQU…13ˆconfigure�write�timeout%CPI14…EQU…14ˆconfigure�break�duration.CPI15…EQU…15ˆconfigure�delete�character�string-CPI16…EQU…16ˆconfigure�control�character�echo2CPI17…EQU…17ˆconfigure�control�character�indicator7CPI18…EQU…18ˆconfigure�terminate�on�at�least�no�of�chrs$CPI19…EQU…19ˆconfigure�hardcopy�mode!CPI20…EQU…20ˆconfigure�line�width2CPI21…EQU…21ˆconfigure�echo�bell�or�terminate�read#CPI22…EQU…22ˆconfigure�nulls�string CPI23…EQU…23ˆconfigure�trash�TXQ CPI24…EQU…24ˆconfigure�flush�TXQ CPI25…EQU…25ˆconfigure�flush�RXQ ,CPI26…EQU…26ˆconfigure�write�line�terminator%CPI27…EQU…27ˆconfigure�XOFF�character$CPI28…EQU…28ˆconfigure�XON‚character#CPI29…EQU…29ˆconfigure�RX�handshake2CPI30…EQU…30ˆconfigure�read�line�terminator�string%CPI31…EQU…31ˆconfigure�bell�character0CPI32…EQU…32ˆconfigure�cancel�hardcopy�character,CPI33…EQU…33ˆconfigure�any�character�for�XON*CPI34…EQU…34ˆconfigure�RXQ�high�water�mark)CPI35…EQU…35ˆconfigure�RXQ�low‚water�mark‰PAGE**‚This�are�the�ICC�commands*CMDRD…EQU…1‰ICC�read�commandCMDWR…EQU…2‰ICC�write�commandCMDAB…EQU…3‰ICC�abort�command-CMDSSE„EQU…4‰ICC�send�solicited�event�command'CMDCNFIƒEQU…5‰ICC�configure�ICC�command(CMDCNFPƒEQU…6‰ICC�configure�PORT�command)CMDCNFTƒEQU…7‰ICC�configure�TABLE�command,CMDRQI„EQU…11ˆICC�reuqest�ICC�status�command-CMDRQP„EQU…12ˆICC�reuqest�PORT�status�command.CMDRQT„EQU…13ˆICC�reuqest�TABLE�status�command%CMDRSTPƒEQU…14ˆICC�reset�PORT�command%CMDSNBPƒEQU…15ˆICC�send�BREAK�to�PORT$CMDFRXQƒEQU…16ˆICC�flush�RXQ�command$CMDFTXQƒEQU…17ˆICC�flush�TXQ�command&CMDBT…EQU…18ˆICC�boot�firmware�command'CMDGO…EQU…19ˆICC�start�booted�firmware!**‚This�are�the�ICC�port�numbers*PORT1„EQU‡1‰port�number�onePORT2„EQU‡2‰port�number�twoPORT3„EQU‡3‰port�number�threePORT4„EQU‡4‰port�number�fourPORT5„EQU‡5‰port�number�fivePORT6„EQU‡6‰port�number�sixPORT7„EQU‡7‰port�number�sevenPORT8„EQU‡8‰port�number�eight*)* Initial SET command equates for the ICC*!SETSTRLN‚EQU…10‰SET�string�length.SETHD…EQU…$533E†'S'�and�AM�code�for�SET�string STRPST„EQU…$07ˆstrip�status�mask?BERRB…EQU…3ŠThis�bit�reflects�the�status�of�the�boards�watchdog *œtimer.�It�is�zero�on�time�out.*+*�ICC�board�equates‚for�register�locations.*,INTRG…EQU…0ŠOffset�to�ICC�interrupt�register-STMSG…EQU…1ŠOffset�to�ICC�status/message�byte/INTRICCB‚EQU…1ŠInterrupt�the�ICC�with�bit�0�set***.CRˆEQU…$0D�CR�-�general�termination�character.BSˆEQU…$08�Back�space�key.DEL‡EQU…$7F�Delete�key.*4* This are the bit equates for the IOS options field*+OPT3†EQU…3‘Output/input�formatted/image�bitOPT5†EQU…5‘Suppress�echo�bit7OPT10…EQU…10�Formatted/image�input�on�output�with�input.OPT12…EQU…12�Flush�type�ahead�on�read�orƒ-�"�-)*£Clear�discard�output�on�output�command.*N* This are the equates for attributes and parameters recognized in ths driver.*5RECATT„EQU…%0000111111111111�1�=�recognized�attribute!*£Transparent�mode�not�supported.8UNRATT„EQU…$FFFF-RECATT†mask�of�not�supported�attributes?RECPAR„EQU…%0111111111111111�1�=�allowed�parameter�on�configure6UNRPAR„EQU…$FFFF-RECPAR†mask�of�parameters�not�allowed**‚Configure�equates*-TABLEN„EQU…$100Žlength�of�an�ICC�action�table-OKSTAT„EQU…0‘good�status�of�returned�messages!TIRAT…EQU…1‘table�ITEM�no�1�(RAT)!TITAT…EQU…2‘table�ITEM�no�2�(TAT)#TIIRAT„EQU…3‘table�ITEM�no�3�(IRAT)!TIRTT…EQU…4‘table�ITEM�no�4�(RTT)!TITTT…EQU…5‘table�ITEM�no�5�(TTT)!TIWAT…EQU…6‘table�ITEM�no�6�(WAT):DCDFLG„EQU…$8C+3�offset�to�DCD�flag�in�request�port�status:CTSFLG„EQU…$90+3�offset�to�CTS�flag�in�request�port�status**‚Structure�for�device�table.*L* A table gets allocated in the initialization section of the driver to holdN* an entry for each port on the ICC. The address of this table is saved in theO* CCB. Each entry pertains to a port and the device number is used to determine"* where in the table the entry is.* ŠOFFSET�0LUBUSY„DS.B„1ŠPort�busy�flags."LUCONTRƒDS.B„1ŠPort�control�flags.6LUSTAT„DS.B„1ŠCurrent�status�of�port�(CSB�format�used)CLUSEDONE‚DS.B„1ŠFlag�to�dertermine�whether�solicited�event�packeges*œhave�been�sent.@LUWIPA„DS.L„1ŠBuffer�address�for�input�part�of�output�with�input-*œcommand.�Is�also�to�hold�the�CSB�address�of*œa�configure�request.LURLTL„DS.L„1ŠLength�of�termination�string�for�read�and�write.BCONFIG„EQU…*-IOSATWƒSet�zero�offset�for�configuration�information.?LUCONF„DS.W„(IOSTLN-IOSATW)/2�Define�space�for�device�dependent&*£configuration.�This�holds�the�actual*£configuration�of�the�port.?* The sequence of the following definition must not be changed.*2LUIRATID‚DS.W„1‘Immediate�Receive�Action�Table�ID.)LUIRAT„DS.W„TABLEN/2ŠSpace�for�the�table.'LURATIDƒDS.W„1‘Receive�Action�Table�ID.(LURAT…DS.W„TABLEN/2ŠSpace�for�the�table.(LUTATIDƒDS.W„1‘Transmit�Action�Table�ID.(LUTAT…DS.W„TABLEN/2ŠSpace�for�the�table.%LUWATIDƒDS.W„1‘Write�Action�Table�ID.(LUWAT…DS.W„TABLEN/2ŠSpace�for�the�table.�#0�THEN.S�if�we�still�have�packets*@*ˆGet�empty�envelope�from�free�envelope�pool�for�BPP�status�pipe*‰INHIBIT—Inhibit�interrupts5‰MOVE.L„FEP_O(A5),A2ˆLoad�first�free�envelope�pointer2‰MOVE.L„(A2),FEP_O(A5)†Point�to�next�free�envelope,‰SUBQ.L„#1,NOPK_O(A5)‡Decrement�packet�count*G*ˆGet�empty�message�packet�from�free�envelope�pool�for�BPP�command�pipe*4‰MOVE.L„FMP_O(A5),A1ˆLoad�first�free�message�pointer8‰MOVE.L„(A1),FMP_O(A5)†Point�to�next�free�message�packet**ˆload�task�control�info�here:*8‰MOVEM.LƒD3-D5,(A1)ŠLoad�DCB,�IOCB�and�TCB�into�message.*-‰LEA‡OSLEN(A1),A1ˆPoint�to�ICC�part�of�packet*;‰MOVE.B„#1<***ƒSubroutine�to�link�a�packet�back�to�the�BPP�command�queue.?***‡This�routine�is�called�by�the�interrupt�service�part�of�theC***‡driver�to�relink�a�solicted�event�packet�or�a�previous�returned?***‡data�transfer�packet�with�a�changed�message�part�to�the�BBP***‡command�queue.***2***ƒEntry�conditions:‚A0.L‚points�to�the�envelope.***–A1.L‚points�to�the�message.******ƒExit�conditions:ƒNone***K****************************************************************************RE_LINK:(ŠMOVEM.L�A0-A2,-(A7)‡Save�some�registers*:ŠMOVE.B�#1<�THEN.SˆIf�there�is�an�error%‰MOVE.B„#ISTAADD,D1‰return�error�code‰LEA‡4(A7),A7Œadjust�stack!ŠBRA.S‚NCMDCMPL‹go�do�normal�exit‰ENDI*>ŠBTST.B�#XDSNRB,LUSTAT(A6)�See�whether�the�CTS�line�is�active.2ŠIF��THEN.SŒIf�not,�set�device�not�ready�error(ŠMOVE.B�#ISTANR,D1‰and�complete�command. ŠLEA„4(A7),A7ŠBRA.S‚NCMDCMPLŠENDI*)‰MOVE.L„D6,A0ŒReturn�buffer�start�address)‰MOVE.L„D5,D2ŒReturn�the�length�of�buffer!‰MOVE.L„A3,D5ŒReturn�IOCB�pointer$‰MOVE.L„A4,D3ŒReturn�the�DCB�pointer*‰MOVE.L„CCBTASKB(A5),D4‚Return�TCB�of�task*‰RTS*L*ƒSet�logical�buffer�start�address�and�length�for�output�with�input�request.*DOIP:0‰MOVE.L„IOSRRN(A3),D6‡load�logical�start�address.‰MOVE.L„IOSLEN(A3),D5‡load�logical�end�address ‰BRA‡CHECK_B�go�calculate�length‰PAGEK******************************************************************************H***†ICMDCMPL�=�routine�that�updates�IOCB�and�queues�an�event�to�indicate-***�that�IO�is�complete�from�interrupt�level!***-***†Entry�conditions�:�A3.L�=�pointer�to�IOCB4***™A6.L�=�pointer�to�the�entry�in�our�device�table.!***™D1.B�=�status�of�completed�IO***™D3.L�=�pointer�to�DCB***9***†Exit�conditions‚:�We�check�if�there�are�more�packets.***K**************************************************************************** ICMDCMPL:5ŠMOVE.B‚D1,IOSSTA(A3)…Put�completition�status�in�IOCB(ŠCLR.BƒLUBUSY(A6)ˆClear�port�busy�flags.#ŠMOVE.L‚#0,A0�Do�not�copy�the�event$ŠJSR…I_NRM_QEVENT†Go�queue�the�event8ŠIF��THEN.SŒif�something�went�wrong�kill�the�system.)‹KILL.DRIVER�M331DRV_ID,I_NRM_QVENT,A5,D3ŠENDI!ŠMOVE.L‚D7,A0�Get�the�TCB�pointer?ŠSUB.Bƒ#1,TCBIOCNT(A0)ƒand�decrement�the�I/O�count�of�the�task."ŠBRA…NEXT_PACK‰See�if�more�packets K******************************************************************************L***‚EXTINTR‚is�used�to�exit�and�indicate�that�we�have�serviced�the�interrupt***?***†Exit�condition:�set�carry�bit�to�indicate�interrupt�served.***K****************************************************************************EXTINTR: ‰OR.W†#1,SR™set�return�condition/‰MOVEM.Lƒ(A7)+,D1-D7/A2-A4/A6Šrestore�registers‰RTS K******************************************************************************D***‚EXTINTR0:�set�return�condition�if�we�did�not�take�the�interrupt!***E***†Exit�condition:�reset�carry�bit�to�indicate�interrupt�not�served.***K**************************************************************************** EXTINTR0:%‰AND.W†#$FFFE,SR”set�return�condition/‰MOVEM.Lƒ(A7)+,D1-D7/A2-A4/A6Šrestore�registers‰RTSŠPAGEK****************************************************************************** H***†NCMDCMPL�=�routine�that�updates�IOCB�and�queues�an�event�to�indicate+***�that�IO�is�complete�from�command�level!***-***†Entry�conditions�:�A3.L�=�pointer�to�IOCB3***™A6.L�=�pointer�to�our�entry�in�the�device�table!***™D1.B�=�status�of�completed�IO***™A4.L�=�pointer�to�DCB***&***†Exit�conditions‚:�We�exit�to�exec!***K**************************************************************************** NCMDCMPL:'ŠCLR.BƒLUBUSY(A6)ˆClear�port�busy�flagsNCMDERR:+ŠMOVE.B‚D1,IOSSTA(A3)…Update�status�in�IOCBŠMOVE.L‚A4,D3�Get�DCB�pointer'ŠMOVE.L‚#0,A0�Indicate�no�copy�of�event0ŠJSR…N_NRM_QEVENT†Call�DRVLIB�to�queue�the�event8ŠIF��THEN.SŒIf�something�went�wrong�kill�the�system.)‹KILL.DRIVER�M331DRV_ID,N_NRM_QVENT,A5,D3ŠENDI$ŠBRA.SƒOK_RETŒBranch�to�good�return.ŠPAGEK******************************************************************************H***‚CMD_SENT�is�called�from�the�command�service�part�of�the�driver�after@***‹all�necessary�commands�for�the�specific�I/O�request�are�sent***‹to�the�ICC.***+***„Entry�conditions:�D3.L�=�pointer�to�DCB***–D4.L�=�pointer�to�TCB***–D5.L�=�pointer�to�IOCB-***–A6.L�=�pointer�to�our�decice�table�entry.***:***„Exit�conditions:‚clear�D0�to�indicate�successfull�call***–return�to�EXEC.***K**************************************************************************** CMD_SENT:5ŠMOVE.L‚D3,LUDCB(A6)†Store�DCB,�TCB�and�IOCB�pointers*ŠMOVE.L‚D5,LUIOCB(A6)…in�our�device�table.ŠMOVE.L‚D4,LUTCB(A6)(ŠMOVE.L‚D4,A0�Get�the�task's�TCB�pointer;ŠADD.Bƒ#1,TCBIOCNT(A0)ƒand�increment�outstanding�I/O�count.,ŠBSET„#ACTIVE,LUBUSY(A6)�Set�port�busy�flag.*G*‚This�is�the�entry�point�for�HALT�I/O�requests,�as�this�calls�will�not *‚increment�the�tasks�I/O�count.* CMD_EXIT:@ŠMOVE.L‚CCBCHB(A5),A0…See�whether�the�bus�error�condition�on�the>ŠBTST„#BERRB,STMSG(A0)‚ICC�board�is�true.�If�the�bit�is�clear,"ŠIF��THEN.SŒthe�board�is�down.5ŠCLR.BƒD0�Clear�to�indicate�we�call�the�error�routine#ŠBRA.SƒSET_DOWNŠfrom�command�level.ŠELSE.S7ŠTST.BƒCCBFLAG(A5)‡If�the�error�flag�in�the�CCB�is�set,,ŠIF��THEN.SŒcall�also�the�error�routine. ŠCLR.BƒD0ŠBRA.SƒSET_DOWNŠENDIŠENDI*C*‚The�command�service�routine�always�exits�via�one�of�these�labels.*4OK_RET:ƒCLR.LƒD0�Set�exit�condition�for�good�return.BAD_RET:‚EQU…*ŠRTS—Return�to�EXECŠPAGEK******************************************************************************E***ƒSET_DOWN�is�called�if�the�driver�detects�that�the�BUS-TIMEOUT�bit=***Œof�the�ICC�board�is�clared.�This�indicates�that�the�board;***Œis�down.�SET_DOWN�checks�all�device�table�entries�about<***Œpending�I/O�requests�and�sends�back�a�completition�event!***Œindicating�the�channel�error.***G***ƒEntry�conditions:�D0.B�=�0‚if�request�is�from�command�service�level8***•D0.B�=�FF�if�request�is�from�interrupt�service�level***K**************************************************************************** SET_DOWN:ŠINHIBIT“Mask�interrupts. ?ŠMOVE.B‚#1<�THEN.SŒIf�this�is�an�outstanding�I/O,'ŠCLR.BƒLUBUSY(A6)ˆclear�the�busy�flags,<ŠMOVE.L‚LUIOCB(A6),A3…and�write�completition�status�to�IOCB.ŠMOVE.B‚D1,IOSSTA(A3)8ŠMOVE.L‚LUDCB(A6),D3†Get�the�DCB�pointer�from�the�table.* ŠTST.BƒD0,ŠIF��THEN.SŒIf�called�from�command�level.ŠJSR…N_NRM_QEVENT†use�this�routine�from�DRVLIBŠIF��THEN.S)‹KILL.DRIVER�M331DRV_ID,N_NRM_QVENT,A5,D3ŠENDIŠELSE.S2ŠJSR…I_NRM_QEVENT†else�queue�from�interrupt�level.ŠIF��THEN.S)‹KILL.DRIVER�M331DRV_ID,I_NRM_QVENT,A5,D3ŠENDIŠENDI*8ŠMOVE.L‚LUTCB(A6),A3†Now�decrement�the�requesting�task's !ŠSUB.Bƒ#1,TCBIOCNT(A3)ƒI/O�count.ŠENDI*/ŠLEA…LULEN(A6),A6†Adjust�pointer�to�next�entry.&ŠSUB.Lƒ#1,D2�Decrement�device�counter.,ŠUNTIL�D2��#0Šuntil�all�devices�checked.*&ŠENABLE”Set�to�previous�interrupt�mask* ŠTST.BƒD05ŠIF��THEN.SŒWe�are�aktivated�from�command�service+ŠBRA…OK_RETŒlevel,�so�go�to�its�exit�point.ŠENDI*8ŠBRA…EXTINTR0ŠElse�use�interrupt�level�exit�and�indicate-*£the�interrupt�as�not�served.�This�gives�the(*£common�interrupt�handler�the�chance�to.*£process�further�boards�of�this�vector�chain.‰PAGEK******************************************************************************A***‚This�are�the�routines�which�are�called�to�change�the�ICC�readC***‚configuration�for�the�requested�port�dynamically.�The�change�is7***‚always�from�an�existing�configuration�to�a�new�one.,***‚The�following�naming�convention�is�used:I***†The�letters�in�front�of�the�underscore�are�the�current�configuration.D***†The�letters�behind�are�an�abbrivation�for�the�new�configuration.:***‡e.g.ƒFE_INE‚indicates�to�change�from�formatted�echo�to***–image�no�echo.***@***…Entry�conditions:�A0.L�=�pointer�to�Read�Action�Table�(RAT).)***—A6.l�=�pointer�to�device�table�entry.***K************************************************************************‰*FE_FE:IE_IE:FNE_FNE:INE_INE:-ŠRTS…No�change�of�configuration;�just�return.*+*‚Change�from�formatted�echo�to�image�echo.E*‚Set�all�characters�which�are�not�read�terminator�to�read�with�echo.*FE_IE:$ŠBSR…P_NULLŒCheck�pass�null�setting.)ŠMOVE.L‚A0,A1�Load�base�address�of�table.+ŠMOVE.W‚#255,D3‹Set�count�for�entire�table. ŠCLR.LƒD0�Set�to�READ�CHARACTER..ŠBSR…SETTABLEŠCall�the�utility�for�the�change.ŠBRA…TEACH�Configure�the�ICC.*F*‚Change�from�image�echo�to�formatted�no�echo�with�check�of�pass�null.*IE_FNE:)ŠBSR.SƒD_NULLŒCheck�discard�null�setting.!*£and�fall�into�the�next�routine.2*‚Change�from�formatted�echo�to�formatted�no�echo.H*‚Set�all�characters�which�are�not�read�terminator�to�read�without�echo.*FE_FNE:(ŠMOVE.L‚A0,A1�Load�base�address�of�table*ŠMOVE.W‚#255,D3‹Set�count�for�entire�table2ŠMOVEQƒ#7,D0�Set�value�READ�CHARACTER�WITHOUT�ECHOŠBSR…SETTABLEŠLet�utility�work.'ŠBSR…SETFKEY‹Set�defined�function�keys.!ŠBRA…TEACH�Go�to�configure�table.*B*‚Change�from�image�echo�to�image�no�echo�with�check�of�pass�null.*FE_INE:)ŠBSR.SƒP_NULLŒCheck�setting�of�pass�null,!*£and�fall�into�the�next�routine.**‚Change�from�image�echo�to�image�no�echo.H*‚Set�all�characters�which�are�not�read�terminator�to�read�without�echo.*IE_INE:(ŠMOVE.L‚A0,A1�Load�base�address�of�table*ŠMOVE.W‚#255,D3‹Set�count�for�entire�table2ŠMOVEQƒ#7,D0�Set�value�READ�CHARACTER�WITHOUT�ECHOŠBSR…SETTABLEŠUpdate�the�table.!ŠBRA…TEACH�Go�to�configure�table.*+*‚Change�from�image�echo�to�formatted�echo.J*‚Set�all�control�characters�which�are�not�read�terminator�to�read�control*‚character�with�echo.*IE_FE:,ŠBSR.SƒD_NULLŒCheck�setting�of�discard�null.)ŠMOVE.L‚A0,A1�Load�base�address�of�table.0ŠMOVE.W‚#31,D3ŒSet�count�for�control�characters.-ŠMOVEQƒ#2,D0�Set�value�READ�CONTROL�CHARACTER*ŠBSR…SETTABLEŠDo�the�changes�in�the�table.)ŠBSR.SƒSETFKEY‹Set�defined�function�keys.ŠBRA…TEACH�Configure�the�table.*F*‚Change�from�image�no�echo�to�formatted�echo�with�check�of�pass�null.*INE_FE:,ŠBSR.SƒD_NULLŒCheck�setting�of�discard�null,!*£and�fall�into�the�next�routine.2*‚Change�from�formatted�no�echo�to�formatted�echo.E*‚Set�all�characters�which�are�not�read�terminator�to�read�with�echo.*FNE_FE:)ŠMOVE.L‚A0,A1�Load�base�address�of�table./ŠMOVE.W‚#31,D3ŒSet�count�for�all�control�chars.1ŠMOVEQƒ#2,D0�Set�value�for�READ�CONTROL�CHARACTER(ŠBSR…SETTABLEŠChange�this�part�of�table.;ŠLEA…32(A0),A1‰Load�table�offset�for�non�control�characters2ŠMOVE.W‚#255-32,D3ˆSet�count�for�those�characters.&ŠCLR.LƒD0�Set�value�for�READ�CHARACTER+ŠBSR.SƒSETTABLEŠand�change�it�in�the�table. )ŠBSR.SƒSETFKEY‹Set�defined�function�keys.ŠBRA…TEACH�Configure�the�table.*F*‚Change�from�formatted�no�echo�to�image�echo�with�check�of�pass�null.*FNE_IE:%ŠBSR.SƒP_NULLŒCheck�pass�null�setting!*£and�fall�into�the�next�routine.**‚Change�from�image�no�echo�to�image�echo.E*‚Set�all�characters�which�are�not�read�terminator�to�read�with�echo.*INE_IE:)ŠMOVE.L‚A0,A1�Load�base�address�of�table.-ŠMOVE.W‚#255,D3‹Set�count�for�all�characters.#ŠCLR.LƒD0�Set�value�READ�CHARACTER.!ŠBSR.SƒSETTABLEŠChange�the�table.!ŠBRA.SƒTEACH�Configure�the�table.*1*‚Change�from�formatted�no�echo�to�image�no�echo.B*‚Set�all�control�characters�which�are�not�read�terminator�to�read*‚without�echo.*FNE_INE:&ŠBSR.SƒP_NULLŒCheck�pass�null�setting.)ŠMOVE.L‚A0,A1�Load�base�address�of�table./ŠMOVE.W‚#31,D3ŒSet�count�for�control�caracters.3ŠMOVEQƒ#7,D0�Set�value�READ�CHARACTER�WITHOUT�ECHO.!ŠBSR.SƒSETTABLEŠChange�the�table.&ŠBRA.SƒTEACH�Send�it�to�the�ICC�board.*1*‚Change�from�image�no�echo�to�formatted�no�echo.*‚Set�all�function�keys*INE_FNE:)ŠBSR.SƒD_NULLŒCheck�discard�null�setting.!ŠBSR.SƒSETFKEY‹Set�function�keys.ŠBRA.SƒTEACH�Configure�table.ŠPAGEK******************************************************************************G***‚Routine�to�configure�the�discard�NULL�function�for�formatted�reads.@***‚It�is�called�if�read�option�changes�from�image�to�formatted.******„Entry�conditions�:�none***C***„Exit�conditions‚:�D7�is�set�to�FF�if�the�IRAT�table�is�changed.***K****************************************************************************'D_NULL:ƒBTST„#IOAPNUL,CONFIG+IOSATW(A6)7ŠIF��THEN.SŒIf�our�configuration�is�to�pass�NULL's,<ŠMOVE.B‚#6,LUIRAT(A6)…discard�them�if�we�change�to�formatted'ŠST†D7�read.�D7�is�set�to�configure�the%ŠENDI–Immediate�Receive�Action�Table.ŠRTS K******************************************************************************C***‚Routine�to�configure�the�discard�NULL�function�for�image�reads.@***‚It�is�called�if�read�option�changes�from�formatted�to�image.******„Entry�conditions�:�none***C***„Exit�conditions‚:�D7�is�set�to�FF�if�the�IRAT�table�is�changed.***K****************************************************************************'P_NULL:ƒBTST„#IOAPNUL,CONFIG+IOSATW(A6)7ŠIF��THEN.SŒIf�our�configuration�is�to�pass�NULL's,;ŠMOVE.B‚#3,LUIRAT(A6)…read�them�if�we�change�to�image�read.+ŠST†D7�Set�D7�to�indicate�Immediate�ReceiveŠENDI–Action�Table�is�changed.ŠRTS K******************************************************************************B***ƒThis�subroutine�is�to�set�the�defined�function�keys�within�the***ƒRead�Action�Table�(RAT).***-***…Entry�conditions�:�A0.L�=�pointer�to�RAT.)***˜A6.L�=�pointer�to�device�table�entry.***K****************************************************************************SETFKEY:6ŠMOVE.B�#1,BS(A0)ŠBS�and�DEL�are�always�used�to�delete7ŠMOVE.B�#1,DEL(A0)‰the�last�character.�Set�it�in�table. ŠCLR.L‚D0ŠMOVE.B�CONFIG+IOSRLN(A6),D08ŠIF��THEN.SŒIf�a�reprint�line�char�is�defined�in�the6ŠMOVE.B�#5,(A0,D0.W)‡current�configuration,�set�it�up.ŠENDIŠMOVE.B�CONFIG+IOSCLC(A6),D0:ŠIF��THEN.SŒDo�the�same�for�the�cancel�line�character.ŠMOVE.B�#4,(A0,D0.W)ŠENDIŠRTS K******************************************************************************@***„This�routine�is�called�to�change�read�action�definitions�forC***„characters�which�are�not�read�terminators�($08)�within�the�RAT.***7***…Entry�conditions�:�A1.L�=�start�address�for�search.5***˜D3.W�=�number�of�bytes�to�search�(zero�relative).!***˜D0.B�=�new�read�action�value.******…Exit�conditions�:‚none***K************************************************************************‰* SETTABLE:ŠMOVE.L�A1,-(A7)8SETLOOPƒCMP.B‚#8,(A1)+‹Is�this�location�read�terminator?ŠBEQ.S‚SETNEXTŒNo,�try�next.+ŠMOVE.B�D0,-1(A1)ŠWrite�in�new�read�action.=SETNEXTƒDBRAƒD3,SETLOOP‰Repeat�for�given�number�of�locations.ŠMOVE.L�(A7)+,A1 ŠRTS K******************************************************************************E***ƒThis�routine�is�to�issue�a�configure�table�call�to�the�ICC�to�setH***ƒup�the�changed�read�options.�As�this�routine�gets�activ�by�a�branch,>***ƒthe�final�RTS�returns�to�the�location�which�called�RDOPT!!***?***†Entry�conditions�:�D7.B�=��if�the�IRAT�is�to�configure,)*** �if�only�the�RAT�is�to�configure.******†Exit�conditions‚:�none***K****************************************************************************TEACH: ŠTST.BƒD79ŠIF��THEN.SŒIf�D7�indicates�that�the�IRAT�is�changed,<ŠLEA…LUIRATID(A6),A0ƒset�the�table�start�address�to�the�IRAT?ŠMOVE.L‚#(TABLEN+2)*2,D2‚table�#�and�the�length�for�two�tables.ŠELSE.S9ŠLEA„LURATID(A6),A0…Else�set�values�to�configure�the�Read'ŠMOVE.L�#TABLEN+2,D2‡Action�Table�only.ŠENDI6ŠMOVE.B�#CMDCNFT,D0ˆSet�the�command�code�and�issue�the ŠBSR„LINKBPPŒrequest�to�the�ICC.ŠRTS ŠPAGEK******************************************************************************J***ƒRDOPT�is�the�subroutine�to�handle�the�IOCB�options�for�a�read�request.C***ƒThe�following�options�are�processed:‚-�Flush�Type�Ahead�Buffer.***©-�Supress�Echo***©-�Read�Image/FormattedC***ƒFor�echo�and�mode,�the�byte�LUCONTR�from�the�device�table�entryJ***ƒcontains�the�actual�read�configuration.�A�value�in�the�range�of�0�-�15M***ƒis�built�as�an�entry�for�the�case�macro.�The�value�is�defined�as�follows: ***‡Bit�0‚0�request�is�formatted***Ž1„-�"�-ƒimage***‡Bit�1‚0„-�"�-ƒecho***Ž1„-�"�-ƒno�echo-***‡Bit�2‚0�actual�configuration�is�formatted***Ž1‹-�"�-‰image***‡Bit�3‚0‹-�"�-‰echo***Ž1‹-�"�-‰no�echoG***‡e.g.�a�value�of�6�means�to�change�the�configuration�from�image�echo***Œto�formatted�no�echo.***?***†Entry�conditions:�A6.L�=�pointer�to�our�device�table�entry.1***˜D5.W�=�read�options�from�IOCB.�If�the�request****Ÿis�output�with�input,�the�format�bit�3$***Ÿmust�be�set�according�to�bit�10.******†Exit�conditions:‚none/***˜it�exits�via�one�of�the�routines�jumped�to.***K****************************************************************************RDOPT:!ŠBTSTWƒ#IOATAHD,CONFIG+IOSATW(A6):ŠIF��THEN.SŒIf�we�are�configured�to�use�the�type�ahead9ŠBTST„#OPT12,D5‰feature�an�the�current�read�option�or�our:ŠIF��THEN.SŒflag�in�the�control�byte�tells�us�to�flush=ŠMOVE.L‚#CMDFRXQ,D0‡the�receive�buffer�before�the�write,�send1ŠBSR…LINKBPP‹a�flush�RX�queue�command�to�the�ICC.9ŠBCLR„#FRXQFLG,LUCONTR(A6)�In�either�case�reset�the�flag.ŠELSE.SŠBCLR„#FRXQFLG,LUCONTR(A6)ŠIF��THEN.SŠMOVE.L‚#CMDFRXQ,D0 ŠBSR…LINKBPPŠENDIŠENDIŠENDI*/*‚now�build�the�value�for�the�case�macro�in�D0.*!ŠBTSTW‚#IOAECHO,CONFIG+IOSATW(A6)8ŠIF��THEN.SŒIf�the�no�echo�bit�is�set�in�the�current5ŠBSETƒ#OPT5,D5‹attribute�word,�simply�set�no�echo�forŠENDI–the�request.;ŠMOVE.B�LUCONTR(A6),D7…Load�the�current�read�configuration.$ŠCLR.L‚D0‘Clear�to�build�case�value.ŠBTSTƒ#OPT3,D59ŠIF��THEN.SŒIf�the�request�is�for�image�read,�set�bit6ŠADDQ.L�#1,D0Žzero�of�case�value�and�the�control�flag.ŠBSETƒ#RDIMAGE,LUCONTR(A6)/ŠELSE.S”Else�reset�the�control�flag�to�indicate*ŠBCLRƒ#RDIMAGE,LUCONTR(A6)’formatted�read.ŠENDIŠBTSTƒ#OPT5,D5:ŠIF��THEN.SŒIf�the�request�is�for�a�read�without�echo,7ŠADDQ.L�#2,D0Žadd�bit�one�of�case�value�and�the�control ŠBSETƒ#NOECHOB,LUCONTR(A6)�flag.0ŠELSE.S”Else�reset�control�flag�to�indicate�read%ŠBCLRƒ#NOECHOB,LUCONTR(A6)™with�echo.ŠENDIŠBTSTƒ#RDIMAGE,D77ŠIF��THEN.SŒIf�the�last�read�was�image,�add�bit�two ŠADDQ.L�#4,D0Žto�the�case�value.ŠENDIŠBTSTƒ#NOECHOB,D76ŠIF��THEN.SŒIf�the�last�read�was�without�echo,�add*ŠADDQ.L�#8,D0Žbit�three�to�the�case�value.ŠENDI1ŠLEA„LURAT(A6),A0‡Point�to�the�Read�Action�Table.,ŠCLR.BƒD7�Clear�for�usage�as�flag�whether�to*£configure�the�IRAT�or�not.*.*„Do�the�case�using�A1�and�D0,�the�case�value.*>ŠCASEƒ1,0,FE_FE,FE_IE,FE_FNE,FE_INE,IE_FE,IE_IE,IE_FNE,IE_INE, =&�FNE_FE,FNE_IE,FNE_FNE,FNE_INE,INE_FE,INE_IE,INE_FNE,INE_INE*ŠPAGEK******************************************************************************G***‚This�is�the�routine�to�configure�the�attribute�bits.�All�attributesH***‚are�configured�regardless�the�content�of�the�attribute�mask�to�avoid.***‚problems�on�changing�speciffic�attributes.***G***„Entry�conditions:�A0.L�=�pointer�to�next�Item�entry�in�Item�Buffer.6***–A3.L�=�pointer�to�users�Configuation�Status�Block.)***–D2.L�=�Current�length�of�Item�buffer.#***–D5.W�=�Attributes�to�configure.***:***„Exit�conditions:‚D2.L�=�Updated�length�of�Item�buffer.***K**************************************************************************** CONF_ATTR:*!*ˆattribute�bit�0�-�hardcopy�mode*0ŠMOVE.W‚#CPI19,(A0)+†load�hard�copy�mode�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOAHCPY,D5‡see�how�attribute�is�set&ŠIF��THEN.SŒelse�do�hard�copy�mode%ŠCLR.Lƒ(A0)+�confg.�for�terminal�modeŠELSE.S3ŠMOVE.L‚#'<>',(A0)+‡put�required�brackets�in�bufferŠENDI !*ˆattribute�bit�1�-�XON/XOFF�mode ATTR1:2ŠMOVE.W‚#CPI29,(A0)+†load�handshake�contr.�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOAXCTL,D5‡see�how�attribute�is�setŠIF��THEN.S(ŠMOVE.L‚#2,(A0)+ŠUse�hardware�handshake. 2ŠMOVE.W‚#CPI10,(A0)+†load�handshake�contr.�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN4ŠCLR.Lƒ(A0)+�Setting�DCD�as�handshake�line�sets�also**£CTS�as�handshake.�But�as�the�default�for+*£CTS�is�status�input,�changes�of�this�line*£will�cause�solicited�events.+ŠMOVE.W‚#CPI05,(A0)+†load�initial�DTR�state ŠADD.Lƒ#6,D2�increment�table�LEN ŠMOVE.L‚#$FF,(A0)+ˆset�to�enable +ŠMOVE.W‚#CPI06,(A0)+†load�initial�RTS�state ŠADD.Lƒ#6,D2�increment�table�LEN ŠMOVE.L‚#$FF,(A0)+ˆset�to�enableŠELSE.SŠMOVE.L‚#1,(A0)+Šuse�XON/XOFF2ŠMOVE.W‚#CPI10,(A0)+†load�handshake�contr.�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN)ŠMOVE.L‚#$FF,(A0)+ˆuse�CTS�for�interruptsŠENDI *ˆattribute�bit�2�-�bits/char ATTR2:+ŠMOVE.W‚#CPI02,(A0)+†load�bits/char�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOABITS,D5‡see�how�attribute�is�setŠIF��THEN.S+ŠMOVE.L‚#8,(A0)+ŠRequest�if�for�8�bit/char.!ŠMOVE.W‚#1<ŠMOVEM.L�D2/A0,-(A7)‡else�configure�the�8�bit�Read�TranslationŠLEA…CRTT8B(A5),A0…TableŠMOVE.L‚#TABLEN+2,D2ŠMOVE.B‚#CMDCNFT,D0 ŠBSR…LINKBPPŠMOVEM.L�(A7)+,D2/A0ŠELSE.S&ŠMOVE.L‚#7,(A0)+Šconfigure�7�bits/charATTR2H:ƒMOVEM.L�D2/A0,-(A7)8ŠLEA…CRTT7B(A5),A0…and�the�7�bit�Read�Translation�Table.:ŠMOVE.L‚#TABLEN+2,D2†This�is�necessary�as�the�board�always;ŠMOVE.B‚#CMDCNFT,D0‡reads�the�characters�with�bit�seven�set)ŠBSR…LINKBPP‹if�configured�to�7�bit/char.ŠMOVEM.L�(A7)+,D2/A0ŠENDI *ˆattribute�bit�3�-�stop�bits ATTR3:+ŠMOVE.W‚#CPI03,(A0)+†load�stop�bits�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOASTPB,D5‡see�how�attribute�is�setŠIF��THEN.S ŠMOVE.L‚#1,(A0)+Šload�1�stop�bitŠELSE.S!ŠMOVE.L‚#2,(A0)+Šload�2�stop�bitsŠENDI -*ˆattribute�bit�4�-�use�parity/type�of�parity ATTR4:/ŠMOVE.W‚#CPI04,(A0)+†load�parity�contr.�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOAUSEP,D5‡see�how�attribute�is�setŠIF��THEN.S ŠCLR.Lƒ(A0)+ŠELSE.S&ŠBTST„#IOAPRTY,D5‡test�for�odd�or�evenŠIF��THEN.S ŠMOVE.L‚#1,(A0)+Šload�odd�parityŠELSE.S!ŠMOVE.L‚#2,(A0)+Šload�even�parityŠENDIŠENDI #*ˆattribute�bit�6�-�local�echo�mode ATTR6:&ŠLEA…LURATID(A6),A1„point�to�RAT�table)ŠMOVE.W‚#TIRAT,(A1)+†Set�up�the�table�ID.*ŠBTST„#IOAECHO,D5‡see�how�attribute�is�setŠIF��THEN.S/ŒBCLR.B‚#NOECHOB,LUCONTR(A6)�clear�no�echo�flag:ŒBCLR.B‚#RDIMAGE,LUCONTR(A6)�set�configured�for�image�readŒMOVE.W‚#$0202,D05ŒFOR.W�D7�=�#1�TO�#16�DO.Sƒfor�all�control�characters%ŽMOVE.W�D0,(A1)+‡set�contol�char�echoŒENDF4ŒFOR.W�D7�=�#1�TO�#(TABLEN-32)/2�DO.Sƒfor�all�others &ŽCLR.W‚(A1)+Šset�rest�of�table�to�echoŒENDF4ŒLEA…LURAT(A6),A1„Load�the�base�address�of�the�table4ŒMOVE.B‚#1,BS(A1)‡and�set�the�default�characters�for)ŒMOVE.B‚#1,DEL(A1)†delete�last�character. '*ˆlets�switch�on�control�character�echo +ŒMOVE.W‚#CPI16,(A0)+†load�echo�CNTL�ITEM�no ŒADD.Lƒ#6,D2�increment�table�LEN!ŒMOVE.L‚#$FF,(A0)+ˆswitch�on�echoŠELSE.S-ŒBSET.B‚#NOECHOB,LUCONTR(A6)…set�no�echo�flagŒBCLR.B‚#RDIMAGE,LUCONTR(A6)ŒMOVE.W‚#$0707,D0 ŒFOR.W�D7�=�#1�TO�#TABLEN/2�DO.S;ŽMOVE.W‚D0,(A1)+†Set�the�entire�table�to�read�without�echo.ŒENDF (*ˆlets�switch�off�control�character�echo +ŒMOVE.W‚#CPI16,(A0)+†load�echo�CNTL�ITEM�no ŒADD.Lƒ#6,D2�increment�table�LEN ŒMOVE.L‚#0,(A0)+Šswitch�off�echoŠENDI #*ˆattribute�bit�7�-�type�ahead�mode ATTR7:+ŠMOVE.W‚#CPI25,(A0)+†load�flush�RXQ�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOATAHD,D5‡see�how�attribute�is�setŠIF��THEN.S!ŠCLR.Lƒ(A0)+�load�no�flush�of�RXQŠELSE.S$ŠMOVE.L‚#$FF,(A0)+ˆload�flush�of�RXQŠENDI 1*ˆattribute�bit�8�-�terminate�on�buffer�full�mode ATTR8:-ŠMOVE.W‚#CPI21,(A0)+†load�buffer�full�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOATFUL,D5�see�how�attribute�is�setŠIF��THEN.S*ŠCLR.Lƒ(A0)+�terminate�read�on�buffer�fullŠELSE.S'ŠMOVE.L‚#$FF,(A0)+ˆload�echo�bell�valueŠENDI *ˆattribute�bit�9�-�pass�nulls ATTR9:-ŠLEA…LUIRATID(A6),A1ƒGet�base�address�of�IRATŠMOVE.W‚#TIIRAT,(A1)+ŠMOVE.W‚#$0303,D7ŠMOVE.W‚#TABLEN/2-1,D0@ATTR9H1ƒMOVE.W‚D7,(A1)+ŠFill�entire�table�with�RECEIVE�CHARACTERŠDBRA„D0,ATTR9H1 ŠBTST„#IOAPNUL,D5ŠIF��THEN.SŠLEA…LUIRAT(A6),A1)ŠMOVE.B‚#6,(A1)‹set�IRAT�to�discard�nullsŠENDI '*ˆattribute�bit�11�-�modem�off�the�hook ATTR11:;ŠBTST„#IOAMODM,D5‡If�we�are�connected�to�a�modem,�take�care'ŠIF��THEN.SŒabout�off�hook�setting.&ŠMOVE.W‚#CPI05,(A0)+†DTR�state�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN*ŠBTST„#IOAOFFH,D5‡see�how�attribute�is�setŠIF��THEN.SŠMOVE.L‚#$FF,(A0)+ˆset�DTRŠELSE.SŠCLR.Lƒ(A0)+�clr�DTRŠENDIŠENDI*ŠRTS ŠPAGEK******************************************************************************E***ƒThis�is�the�table�which�defines�the�Baud�Rates�used�with�VERSAdos#***ƒand�supported�by�the�ICC�board.***K****************************************************************************BAUDTBL:ŠDC.L„50ŠDC.L„75 ŠDC.L„110 ŠDC.L„134 ŠDC.L„150 ŠDC.L„300 ŠDC.L„600 ŠDC.L„1200 ŠDC.L„1800 ŠDC.L„2000 ŠDC.L„2400 ŠDC.L„3600 ŠDC.L„4800 ŠDC.L„7200 ŠDC.L„9600 ŠDC.L„19200 ŠDC.L„38400 ŠPAGEK******************************************************************************B***‚This�is�the�routine�to�configure�the�requested�Parameters.�AllD***‚parameters�are�processed�regardless�the�content�of�the�parameter<***‚mask�to�avoid�problems�on�changing�a�specific�parameter.***G***„Entry�conditions:�A0.L�=�pointer�to�next�Item�entry�in�Item�Buffer.6***–A3.L�=�pointer�to�users�Configuation�Status�Block.)***–D2.L�=�Current�length�of�Item�buffer.***:***„Exit�conditions:‚D2.L�=�Updated�length�of�Item�buffer.***K**************************************************************************** CONF_PAR:*‰paramater�bit�0�-�Line�width*,ŠMOVE.W‚#CPI20,(A0)+†load�line�width�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN!ŠCLR.LƒD0�use�as�working�register$ŠMOVE.W‚IOSREC(A3),D0…get�line�width)ŠMOVE.L‚D0,(A0)+Šload�line�width�in�table*&*ˆparameter�bit�4�-�XOFF/XON‚character*PAR4:+ŠLEA…LUIRAT(A6),A1…Get�base�address�of�IRAT ŠCLR.WƒD0�clear�working�register+ŠMOVE.W‚#CPI33,(A0)+†load�XON/ANY�parameter0ŠMOVE.L‚#$FF,(A0)+ˆpreload�with�any�char�for�XON!ŠADD.Lƒ#6,D2�increment�ITEM�count,ŠMOVE.B‚IOSXOF(A3),D0…get�the�XOFF�characterŠIF��THEN.S1ŠMOVE.B‚#0,(A1,D0.W)†put�action�character�in�IRAT+ŠMOVE.B‚IOSXON(A3),D0…get�the�XON�character*ŠIF��THEN.SŒelse�use�any�chr�to�enable1ŠMOVE.B‚#1,(A1,D0.W)†put�action�character�in�IRAT'ŠCLR.Lƒ-4(A0)Œuse�XON�char�to�enable�TXŠENDIŠENDI* .*ˆparameter�bit�5�-�break�equivalent�character* ŠCLR.WƒD0�clear�working�register-ŠMOVE.B‚IOSBRC(A3),D0…get�the�BREAK�characterŠIF��THEN.S1ŠMOVE.B‚#2,(A1,D0.W)†put�action�character�in�IRATŠENDI*,*ˆparameter�bit�6�-�discard�output�character* ŠCLR.WƒD0�clear�working�register/ŠMOVE.B‚IOSDOP(A3),D0…get�the�DISCARD�characterŠIF��THEN.S8ŠMOVE.B‚#4,(A1,D0.W)†Put�IRAT�EVENT�#1�character�in�IRATŠENDI***ˆparameter�bit�7�-�reprint�line�character*0ŠLEA…LURAT(A6),A1†Get�base�address�of�RAT�table. ŠCLR.WƒD0�clear�working�register1ŠMOVE.B‚IOSRLN(A3),D0…get�the�REDISPLAY�characterŠIF��THEN.S0ŠMOVE.B‚#5,(A1,D0.W)†put�action�character�in�RATŠENDI*)*ˆparameter�bit�8�-�cancel�line�character* ŠCLR.WƒD0�clear�working�register.ŠMOVE.B‚IOSCLC(A3),D0…get�the�CANCEL�characterŠIF��THEN.S0ŠMOVE.B‚#4,(A1,D0.W)†put�action�character�in�RATŠENDI*$*ˆparameter�bit�9�-�read�terminators*,ŠMOVE.W‚#CPI30,(A0)+†read�terminator�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN-ŠMOVE.L‚IOSEOL(A3),(A0)+‚load�read�terminatorŠLEA…LURAT(A6),A2†point�to�RAT ŠCLR.WƒD0�clear�working�register'ŠLEA…IOSRTV(A3),A1…point�to�read�stringŠFOR.BƒD7�=�#1�TO�#4�DO.SŠMOVE.B‚(A1)+,D0ŠIF��THEN.S=ŠMOVE.B‚#8,(A2,D0.W)†Set�all�termination�char's�for�terminateŠENDI–read�without�echo.ŠENDF*'*ˆparameter�bit�10�-�end�of�line�string*;ŠLEA…LUWATID(A6),A2„Get�base�address�of�Write�Action�Table."ŠMOVE.W‚#TIWAT,(A2)+†Set�table�ID. ŠMOVE.L‚A2,A17ŠMOVE.W‚#TABLEN/2-1,D0„Fill�the�entire�table�with�value)PAR10H1ƒCLR.Wƒ(A1)+�WRITE�CHARACTER�FAST.ŠDBRA„D0,PAR10H18ŠMOVE.B‚#2,CR(A2)‰$0D�needed�for�terminator�to�pass�them*£to�the�Transmit�Action�Table.>ŠLEA…LUTATID(A6),A2„Get�base�address�of�Transmit�Action�Table.!ŠMOVE.W‚#TITAT,(A2)+†Set�table�ID ŠMOVE.L‚A2,A17ŠMOVE.W‚#TABLEN/2-1,D0„Fill�entire�table�with�the�value'PAR10H2ƒCLR.Wƒ(A1)+�TRANSMIT�CHARACTER.ŠDBRA„D0,PAR10H2/ŠMOVE.B‚#2,CR(A2)‰Set�to�insert�NULLS�after�CR.*,ŠMOVE.W‚#CPI26,(A0)+†read�terminator�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN-ŠMOVE.L‚IOSEOL(A3),(A0)+‚load�read�terminator*=ŠLEA…IOSEOL+4(A3),A2ƒPoint�to�the�byte�behind�the�EOL�string. ŠCLR.LƒD0 ŠMOVE.W‚#3,D03COUNTL„TST.Bƒ-(A2)�Decrement�until�first�byte�.ŠDBNE„D0,COUNTLŠADDQ.W‚#1,D0�Correct�length.-ŠMOVE.L‚D0,LURLTL(A6)…Store�it�for�later�use.*#*ˆparameter�bit�11�-�baud�rate�code*+ŠMOVE.W‚#CPI01,(A0)+†load�baud�rate�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LEN ŠCLR.LƒD0+ŠMOVE.B‚IOSBRT(A3),D0…Get�the�baudrate�code)ŠLSL.Lƒ#2,D0�Adjust�for�long�word�access.6ŠLEA…BAUDTBL(PC),A1„Get�the�base�address�of�the�table.)ŠMOVE.L‚(A1,D0.L),(A0)+ƒSet�the�baudrate.*!*ˆparameter�bit�12�-�null�padding*1ŠMOVE.W‚#CPI22,(A0)+†load�number�of�nulls�ITEM�no ŠADD.Lƒ#6,D2�increment�table�LENŠCLR.LƒD0�use�as�work�register-ŠMOVE.B‚IOSNLS(A3),D0…get�the�number�of�nulls ŠMOVE.L‚D0,(A0)+Šload�into�table*%*ˆparameter�bit�13�-�terminator�class*/ŠTST.BƒIOSTRC(A3)ˆDo�we�have�a�terminator�classŠIF��THEN.S/ŠLEA…LURAT(A6),A1†Get�base�address�of�RAT�table/ŠFOR.WƒD7�=�#0�TO�#$FF�DO.S‚for�entire�table�doŠMOVE.B‚D7,D3�make�a�copyŠMOVE.B‚D7,D0�make�a�copyŠAND.Bƒ#$0F,D3‹drop�MSBs.ŠAND.BƒIOSTRC(A3),D0…and�with�terminator�class'ŠLSL.Bƒ#4,D0�shift�result�to�right�half!ŠCMP.BƒD0,D3�is�this�a�terminatorŠIF��THEN.S9ŠMOVE.B‚#8,(A1,D7)ˆWrite�TERMINATE�WITH�NO�ECHO�to�table.ŠENDIŠENDFŠENDI ‰RTS ‰PAGEK******************************************************************************A***†GETLUBUF�is�a�subroutine�to�get�the�base�address�of�the�entry***†in�the�device�table.***8***†Entry�conditions:�D1.W�=�port�number‚(zero�relative)***+***†Exit�conditions�:�A6.L�=�buffer�pointer***˜D2.W�is�preserved***K**************************************************************************** GETLUBUF:ŠMOVE.L�D2,-(A7)Œsave�register8ŠMOVE.L�LUTBFP(A5),A6‡Get�the�base�address�of�the�table.#ŠMOVE.W�#LULEN,D2‹get�the�page�size  ŠMULUƒD1,D2�get�the�table�offset$ŠLEA„(A6,D2.L),A6ˆpoint�to�our�table!ŠMOVE.L�(A7)+,D2Œrestore�registerŠRTS‰PAGEF*** -------------------------------------------------------------- ***D***�CNFGCMN‚Common�configure�routine�which�checks�attributes�and‚******�parameters.´******À***;***�Input�conditions:�D0.W�=�recognized�attributes�maskŒ***)***“D2.W�=�recognized�parameters�maskŒ******À***.***“A0ƒ=�address�of�current�configuiration…***"***“A3ƒ=�address�of�users�IOCB‘*** ***“A4ƒ=�base�address�of�DCB“*** ***“A5ƒ=�base�address�of�CCB“******À***=***�Exit�conditions:‚if�error:�D1.B�=�error�code�for�IOCB‰***$***�D0,D5-D7/A0-A2�are�destroyed‡***)***�if�inv�address�branch�to�NCMDCMPL‚***(***�else�return�error�code�in�D1�andƒ******�clear�zero�bit•******“if�no�error:¡***$***�D0,D5-D7/A0,A2�are�destroyed‡***$***�A1�=�physical�address�of�CSB‡***"***�Set�zero�bit�for�no�error.‰******�normal�RTS™******À******À***F*** -------------------------------------------------------------- ****CNFGCMN:0‰MOVE.L„IOSDBP(A3),D6‡get�logical�address�of�CSB'‰MOVE.L„#IOSTLN,D5Šget�CSB�table�length‰MOVE.L„A0,A1�save�regisrer.‰MOVE.L„CCBTASKB(A5),A0…get�address�of�his�TCB**‰JSR‡LOGPHYŽgo�convert�logical�to�physical*‰IFˆ†THEN.S%ŠMOVE.B‚#ISTAADD,D1‡return�error�codeŠLEA…4(A7),A7Šadjust�stackŠBRA…NCMDCMPLŠgo�return�command‰ENDI‰MOVE.L„A1,A0�restore�register$‰MOVE.L„D6,A1�load�CSB�table�pointer*8* check illegal parameters and attributes and parameters*)‰MOVEQ…#CECCDO,D7Špreload�with�error�code*.‰AND.W…IOSATM(A1),D0‡find�unallowed�attributes ‰BNE‡BADCNFG�report�error�if�any*.‰AND.W…IOSPRM(A1),D2‡find�unallowed�parameters ‰BNE‡BADCNFG�report�error�if�any*.* check unrecognized attributes and parameters*)‰MOVEQ…#CECUAP,D7Špreload�with�error�code*6‰MOVE.W„#UNRATT,D0Šget�mask�of�unrecognized�attributes1‰AND.W…IOSATM(A1),D0‡find�unrecognized�attributes ‰BNE‡BADCNFG�report�error�if�any*6ŠMOVE.W‚#UNRPAR,D0ˆget�mask�of�unrecognized�attributes1‰AND.W…IOSPRM(A1),D0‡find�unrecognized�attributes ‰BNE‡BADCNFG�report�error�if�any*9* now copy the table pointed by A4.L to our device table!*-‰MOVE.W„IOSATM(A1),D0‡D0�=�his�attribute�mask9‰AND.W…D0,IOSATW(A1)‡zero�out�attributes�he�does�not�want‰NOT.W…D0’to�change9‰AND.W…IOSATW(A0),D0‡zero�out�the�attributes�of�mine�that'‰OR.W†D0,IOSATW(A1)‡does�want�to�change*>‰MOVE.W„IOSPRM(A1),D0‡get�mask�of�parameters�he�wants�to�chang#‰MOVEM.LƒA0-A1,-(A7)‰save�registers1‰LEA‡IOSREC(A0),A0‡address�of�first�param.�in�CCB;‰LEA‡IOSREC(A1),A1‡address�of�first�param.�in�user�dat�bloc)‰LEA‡PARSIZE,A2Šload�parameter�size�table*E* if this is the first configure, then copy CSB to local device table*/ŠTST.BƒLUSEDONE(A6)†is�this�the�first�configure(‰IFˆ�THEN.S‰copy�CSB�to�device�table*<‰MOVE.W„#(IOSTLN-IOSATW)/2-1,D0�calc�number�of�bytes�to�copy*NXTPR:#‰MOVE.W„(A1)+,(A0)+‰copy�parameters‰DBRA†D0,NXTPR!‰BRA.S…CHKPRMŽgo�check�parameters‰ENDINXTPRM:"‰CLR.L…D2’clear�to�hold�word�value-‰MOVE.B„(A2)+,D2Œnumber�of�bytes�in�parameter,‰BEQ.S…CHKPRMŽend�of�table�flagged�with�zero+‰LSR.W…#1,D0�check�if�bit�in�parameter�mask(‰IFˆ�THEN.S‰if�not�then�skip�it�else,‰SUBQ.W„#1,D2�move�parameter�into�data�blockMOVPARM::‰MOVE.B„(A0)+,(A1)+‰copy�as�many�as�the�size�of�size�table‰DBRA†D2,MOVPARMŠdo�next�byte‰ELSE.S#‰ADD.L…D2,A0�skip�to�next�parameter#‰ADD.L…D2,A1�skip�to�next�parameter‰ENDI‰BRA‡NXTPRMŽdo�next�parameter*CHKPRM:%‰MOVEM.Lƒ(A7)+,A0-A1‰resore�registers+‰MOVEQ…#CECTBR,D7Šload�baud�rate�error�code)‰CMP.B…#$10,IOSBRT(A1)…test�max�baud�rate$‰BHI.S…BADCNFG�log�error�if�too�high*'‰MOVEQ…#CECTIM,D7Šload�modem�error�code>‰MOVE.W„#1<�#$0F�THEN.S�if�no�terminator�classB‰BTSTW…#IOATFUL,IOSATW(A1)�and�we�we�are�not�terminating�on�buffer6‰IFˆ�THEN.S‰full,�and�no�read�terminators,�this�is%‰TST.L…IOSRTV(A1)Ša�bad�configuration‰BEQ.S…BADCNFG�exit‰ENDI"‰ELSE.S˜we�have�a�terminator�class‰MOVE.B„#$0F,D2�check�class‰AND.B…D0,D2�mask�value‰LSL.B…#4,D0�match�value‰AND.B…D0,D2�mask�.�match�value‰CMP.B…D0,D2�test�the�class'‰BNE.S…BADCNFG�this�is�a�bad�term�class‰ENDI*;‰BTSTW…#IOABITS,IOSATW(A1)�if�we�only�have�7�bits/char,�but3‰IFˆ�THEN.S‰the�only�possible�termination�is�onB‰IF.B†IOSTRC(A1)��#$0F�THEN.S�a�char�with�high�bit�set�-�error7‰BTST.B„#3,IOSTRC(A1)‡test�if�high�bit�of�mach�value�=0%‰BEQ.S…OKCNFGŽthe�configuration�is�OK‰ENDI*<‰MOVE.L„IOSRTV(A1),D0‡check�read�terminators�for�some�valuesCHKNXT:‰ROL.L…#8,D0�with�high�bit�set"‰BEQ.S…BADCNFG�we�did�not�find�any‰BPL.S…OKCNFGŽwe�did�find�one ‰CLR.B…D0‰BRA‡CHKNXTŽdo�next‰ENDI*OKCNFG:/‰MOVE.B„CCBTYPE(A5),IOSCTP(A1)�set�channel�type*‰MOVE.B„XDSACIA,IOSDTP(A1)‚set�device�type<‰MOVE.B„#IODTERM,IOSDRC(A1)�set�driver�code�to�terminal�type/‰STˆDCBCCF(A4)Šset�flag�for�default�config�done#ŠCLR.BƒD2�set�zero�bit�for�no�error‰RTS*BADCNFG:2‰MOVE.B„D7,IOSCEC(A1)‡set�the�specified�error�code*ŠMOVE.B‚#ISTACNF,D1‡load�config�error�codeŠRTS‰PAGEF*************************************************************************À*** ***‚INITº***<***‡get�a�segment�of�memory�from�exec�and�format�it�into…***1***‡free�envelope�pool�and�free�message�pool.�******‡do�SET�command�for�ICC.¢***>***‡send�configure�ICC�command�to�ICC�(configure�interruptƒ******‡vector�and�level.)§***-***‡poll�until�the�configuration�is�done.”******‡normal�exit�from�INIT.£******À***F***********************************************************************INIT:*)*ˆget�some�pages�of�memory�for�free�pools*!‰MOVE.L„A5,-(A7)Œsave�CCB�pointer4‰TR0$.PAGAL�#TOTPAGESŠget�some�memory�for�free�pools‰BRA.S…DOENV�start�if�OK‰MOVE.L‚(A7)+,A5?ŠKILL.DRIVER�M331DRV_ID,T0PAGAL,A5,#NO_DCBƒno�memory�available. ‰PAGE**ˆformat�free�envelope�pool*DOENV:$‰MOVE.L„(A7)+,A5Œrestore�CCB�pointer1‰MOVE.L„#NOPACKS,D0‰get�number�of�packets�we�have8‰MOVE.L„D0,NOPK_O(A5)‡store�the�number�of�packets�in�CCB9‰MOVE.L„A0,FEP_O(A5)ˆstore�the�free�envelope�pool�pointer ‰REPEAT*‰LEA‡ENVLLEN(A0),A0†point�to�next�envelope)‰MOVE.L„A0,-ENVLLEN(A0)…store�the�pointer$‰SUBQ.L„#1,D0�decrement�packet�count%‰UNTIL.LƒD0��#0Šcount�has�expired**ˆformat�free�message�pool*8‰MOVE.L„A0,FMP_O(A5)ˆstore�the�free�message�pool�pointer3‰MOVE.L„NOPK_O(A5),D0‡get�number�of�packets�we�have ‰REPEAT)‰LEA‡TCMDLEN(A0),A0†point�to�next�message)‰MOVE.L„A0,-TCMDLEN(A0)…store�the�pointer$‰SUBQ.L„#1,D0�decrement�packet�count%‰UNTIL.LƒD0��#0Šcount�has�expired*A*ˆget�empty�envelope�from�free�envelope�pool�for�BPP�command�pipe*5‰MOVE.L„FEP_O(A5),A0ˆload�first�free�envelope�pointer2‰MOVE.L„(A0),FEP_O(A5)†point�to�next�free�envelope,‰SUBQ.L„#1,NOPK_O(A5)‡decrement�packet�count,‰MOVE.B„#1<™8¡7©:±;¹BÁAÉBÑCÙ,ŠMOVE.L�D0,(A0)+‹store�the�converted�address*B*„Now�read�the�ICC�status�register�and�check�whether�the�self�testB*„is�finished.�If�an�error�condition�exists,�mark�the�channel�down *„and�exit.*1ŠMOVE.L�CCBCHB(A5),A1†get�the�boards�base�address STEST_WAIT:'ŠMOVE.B�STMSG(A1),D1‡get�the�ICC�status(ŠBCHGƒ#BERRB,D1Šinvert�the�bus�error�bitŠAND.B‚#$F,D1�strip�BIT�4�-�7.ŠBEQ.S‚STEST_OK‹on�zero�ICC�self�test�finished.ŠCMP.B‚#7,D1Žif�7�then�ICC�performs�self�test.ŠBEQ.S‚STEST_WAIT4ŠBSR…INITERR‹else�something�went�wrong;�call�to�save*£address�and�set�board�down.*ˆdo�SET�command!!* STEST_OK:/‰LEA‡SETSTR_O(A5),A0…point�to�SET�string�in�CCB.‰MOVE.W„#SETSTRLN,D2ˆload�the�SET�sting�length*‰REPEATWO0:'‰MOVE.B„STMSG(A1),D1ˆget�the�ICC�status‰AND.B…#STRPST,D1Šstrip�MSB's"‰CMP.B…#1,D1�are�we�still�waiting?‰BEQ‡WO0‘wait�until�changed!‰CMP.B…#0,D1�is�ready�?‰IF��THEN.S1ŠBSR…INITERRŽError;�call�to�save�address�and�mark‰ENDIšthe�channel�down.2‰MOVE.B„(A0)+,STMSG(A1)…write�the�data�byte�to�ICC-‰MOVE.B„#INTRICCB,INTRG(A1)�interrupt�the�ICCWO1:'‰MOVE.B„STMSG(A1),D1ˆget�the�ICC�status‰AND.B…#STRPST,D1Šstrip�MSB's"‰CMP.B…#0,D1�are�we�still�waiting?‰BEQ‡WO1‘wait�until�changed!‰CMP.B…#1,D1�is�ready�?‰IF��THEN.S0ŠBSR…INITERRŽError;�call�to�save�address�and�set‰ENDIšthe�channel�down.3‰CLR.B…STMSG(A1)‹Clear�out�the�message/status�byte.-‰MOVE.B„#INTRICCB,INTRG(A1)�interrupt�the�ICC"‰SUBQ.B„#1,D2�decrement�loop�count .‰UNTIL.BƒD2��#0Šuntil�string�has�been�sent*,*ƒAllocate�the�memory�for�our�device�tables.*!‰MOVE.L„A5,-(A7)Œsave�CCB�pointer9‰TR0$.PAGAL�#LUPAGES‹get�the�pages�for�the�device�tables.‰BRA.S…DOCNFSŽstart�if�OK‰MOVE.L‚(A7)+,A5?ŠKILL.DRIVER�M331DRV_ID,T0PAGAL,A5,#NO_DCB‚no�memory�available.‰PAGEDOCNFS:$‰MOVE.L„(A7)+,A5Œrestore�CCB�pointer2‰MOVE.L„A0,LUTBFP(A5)‡Save�the�base�address�of�our*¦device�tables.*2*ˆNow�send�the�configure�ICC�command�to�the�board.=*ˆFirst�format�the�configure�ICC�ITEM's�in�the�Item�buffer�of0*ˆport.�A0.L�points�to�first�device�table�entry.* ‰MOVE.L„A0,A24‰LEA‡LUCITAB(A0),A0†Get�base�address�of�Item�buffer.*C*…Use�ITEM�6,�the�HALT�SAVE�ADDRESS�feature�for�degugging�purposes.*,‰MOVE.W„#CICCI6,(A0)+‡load�ICC�config.ITEM�6-‰LEA‡HALTSA(A5),A1‡point�to�halt�save�address/‰MOVE.L„#'!HTS',(A1)+‡put�in�eye�catcher�in�CCB'‰MOVE.L„A1,(A0)+Œload�halt�save�address*>‰MOVE.W„#CICCI4,(A0)+‡load�ICC�config.ITEM�4,�interrupt�level.!‰CLR.L…D1’use�as�working�register>‰MOVE.B„CCBPPRIO(A5),D1…load�interrupt�hardware�level�from�CCB)‰MOVE.L„D1,(A0)+Œput�into�the�Item�table.*?‰MOVE.W„#CICCI3,(A0)+‡load�ICC�config.ITEM�3,�interrupt�vector.4‰MOVE.B„CCBVECT(A5),D1†get�interrupt�vector�from�CCB%‰MOVE.L„D1,(A0)+Œput�into�Item�table.*.ŠMOVE.B�#CMDCNFI,D0ˆload�configure�ICC�command2ŠMOVE.B�#PORT1-1,D1ˆload�port�1�(we�use�its�queue)5ŠLEA„LUCITAB(A2),A0…load�the�start�of�configure�table1ŠMOVE.L�#3*ILEN,D2‰load�length�of�configure�table*/‰BSR‡LINKBPP�link�packet�into�BPP�command�queue*K*ƒAfter�the�initialization�call�to�the�ICC�we�have�to�wait�for�completitionG*ƒof�the�command.�This�is�necessary�to�avoid�bus�timeouts�on�the�board.D*ƒThese�timeouts�may�occure�if�control�is�given�back�to�the�VERSAdosG*ƒInitializer�immediately�after�setting�the�command.�If�the�InitializerF*ƒtries�to�access�a�non�existing�board,�the�ICC�is�not�able�to�get�the0*ƒbus�to�return�the�status�for�the�init�command.C*ƒBefore�entering�the�wait�loop,�we�use�the�time�to�set�up�the�Read**ƒTranslation�Tables�for�7�and�8�bit/char.*:ŠLEA…CRTT7B(A5),A0…Get�the�base�address�of�the�7�bit�table-ŠMOVE.W‚#TIRTT,(A0)+†and�set�up�the�Table�ID.$ŠLEA…TABLEN(A0),A0…Fill�it�top�down.ŠMOVE.W‚#1  27,D0?FILLTT7H:�MOVE.B‚D0,-(A0)ŠFirst�fill�the�upper�half�with�ASCII.ŠDBRA„D0,FILLTT7H*ŠMOVE.W‚#127,D0:FILLTT7L:�MOVE.B‚D0,-(A0)ŠFill�lower�half�also�eith�ASCII.ŠDBRA„D0,FILLTT7L*:ŠLEA…CRTT8B(A5),A0…Get�the�base�address�of�the�8�bit�table*ŠMOVE.W‚#TIRTT,(A0)+†and�set�the�Table�ID.<ŠLEA…TABLEN(A0),A0…Fill�also�top�down�with�value�of�255�-�0.ŠMOVE.W‚#255,D0FILLTT8:‚MOVE.B‚D0,-(A0)ŠDBRA„D0,FILLTT8*:ŠMOVE.L‚CCBCHB(A5),A1…Get�the�base�address�of�the�channel.7ŠMOVE.L‚BPPS_O(A5),A0…Get�the�status�pipe�tail�pointer.AINITPOLL:�BTST„#0,FLNKB(A0)†If�this�bit�is�zero,�the�completition/ŠBEQ.SƒINITOKŒstatus�is�sent�back�from�the�ICC.1ŠBTST„#BERRB,STMSG(A1)‚Check�the�bus�timeout�bit.'ŠBNE.SƒINITPOLLŠProceed�waiting�if�set.7ŠBSR.SƒINITERR‹Else�call�to�save�address�and�mark�down.**0INITOK:ƒRTS—Initialization�of�the�channel�is�ok,*£return�to�Initializer.*D*‚This�routine�is�called�if�a�error�condition�is�detected�during�the*‚initialization�of�the�board.*INITERR:DŠMOVE.B‚#1<***‚We�get�here�when�the�atteched�task�IOS�invokes�CMR�via�***A***‚a�TRAP�1�with�an�initiate�I/O�parameter�block�to�process.Š***@***‚CMR�has�already�checked�the�parameter�block�to�ensure�it‹***>***‚resides�within�the�address�space�of�the�attached�task.�***A***‚IOS�has�already�validated�the�IOCB,�except�for�the�bufferŠ******‚address�therein.³******Å***D***‚We�got�here�through�a�JSR�from�CMR,�and�will�exit�witn�a�RTS‡***@***‚all�registers�have�been�saved�by�CMR�and�we�may�use�them‹***C***‚freely.�Entry�is�at�interrupt�level�0,�and�we�are�in�super-ˆ******‚visor�mode.¸******Å***F***‚Entry�conditions:�A2.L�=�phisical�address�of�CMR�parameter�blk…***&***”A5.L�=�phisical�address�of�CCB“***2***”A6.L�=�phisical�address�of�TCB�of�attached‡*** ***¶task‹***A***‚Exit�conditions:‚D0.B�=�Status�of�processing�the�repuest.‰*******›It�is�nonzer  o�only�in�the�case�theˆ***/***›the�driver�has�not�enough�free�packegesƒ***.***›to�porocess�the�given�request.�In�this„***)***›case�status�$84�"channel�busy"�is‰***$***›returned�to�the�CMR�handler.Ž******Å***%***‚Do�the�common�part�of�COMMAND¦******Å*******Šdecode�the�following�IOS�commands:™******Å***'***ŠIOOWINƒoutput�with�input…(0004)–******ŠIOREADƒread’(0001)–******ŠIOWRITƒwrite‘(0002)–******ŠIOHALTƒhalt�I/OŽ(0110)–***$***ŠIOTBRKƒtransmit�breakˆ(0040)–***$***ŠIOSTATƒrequest�statusˆ(0140)–******ŠIOCNFGƒconfigure�(0180)–***%***ŠIOCHDCƒchange�defaults‡(8002)–******Å***K***************************************************************************** Command jump table*CMDSRT:&‰DC.W†IOOWINŽoutput�with�input�command‰DC.W†IOREADŽread�command‰DC.W†IOWRITŽwrite�command‰DC.W†IOHALTŽhalt�I/O�command#‰DC.W†IOTBRKŽtransmit�break�command#‰DC.W†IOSTATŽrequest�status�command‰DC.W†IOCNFGŽconfigure�command$‰DC.W†IOCHDCŽchange�defaults�command**ˆCommand�routine�offsets*CMDRTS:*‰DC.W†IOOWINR-*Œoffset�to�command�routines‰DC.W†IOREADR-*‰DC.W†IOWRITR-*‰DC.W†IOHALTR-*‰DC.W†IOTBRKR-*‰DC.W†IOSTATR-*‰DC.W†IOCNFGR-*‰DC.W†IOCHDCR-*‰PAGEK******************************************************************************9***‚This�the�actual�entry�in�the�command�service�routine.***K****************************************************************************CMND:)‰MOVE.L„XIOUID(A2),A4‡get�the�DCB�pointer* ‰CLR.L…D5’clear�working�register0‰MOVE.L„XIOCPK(A2),D6‡load�logical�start�address.‰MOVE.W„XIOPLN(A2),D5‡load�logical�end�address,‰MOVE.L„CCBTASKA(A5),A0…load�the�TCB�address**‰JSR‡LOGPHYŽgo�convert�logical�to�physical*‰IF��THEN.S$‰MOVE.B„#ISTAIP,D1‰return�error�code‰BRA‡NCMDCMPL‹go�exit�driver‰ENDI*‰MOVE.L„D6,A3�get�IOCB�pointer*ŠTST.BƒCCBFLAG(A5)2ŠIF��THEN.SŒIf�the�channel�is�down,�det�up�the*ŠMOVE.B‚#ISTACDN,D1‡error�code�and�return. ŠBRA…NCMDERRŠENDI*<ŠMOVE.L‚#MINPKT,D0ˆNow�check�if�we�have�enough�free�packeges@ŠCMP.LƒNOPK_O(A5),D0…to�send�all�commands�which�may�be�necessary7ŠIF��THEN.SŒto�process�the�request.�Return�"channel3ŠMOVE.B‚#XSTBSY,D0ˆbusy"�to�the�CMR�handler�if�not. ŠBRA…BAD_RETŠENDI*1‰MOVE.L„CCBTASKA(A5),CCBTASKB(A5)�make�task�A�=�B*'‰MOVE.W„(A3),D2�get�the�type�of�command‰CLR.W…D1’use�as�work�register5‰MOVE.B„DCBCDV(A4),D1‡get�the�device�number�from�DCB.*$‰LEA‡CMDSRT(PC),A0‡point�to�commandsB‰MOVE.W„#(CMDRTS-CMDSRT)/2,D3�number�of�cmnds�we�have�in�the�tableNXTCMD:#‰CMP.W…(A0)+,D2Œis�this�the�command ‰DBEQ†D3,NXTCMD‹loop�until�found‰BNE.S…NOCMD�if�no�command�exit*%*ƒAt�this�point�we�found�the�command.*6‰BSR‡GETLUBUF‰Get�the�device�table�entry�for�this�port *£into�A6.LB‰LEA‡CMDRTS-CMDSRT-2(A0),A0�get�the�command�routine�offset�pointer*‰MOVE.W„(A0),D0�get�command�routine�offset&‰JMP‡(A0,D0.W)‹jump�to�command�routine*-* We get here when we do not find the command*NOCMD:"‰MOVE.B„#ISTAIF,D1Šload�error�code‰BRA‡NCMDCMPLŒgo�exit�driver‰PAGE F*** -------------------------------------------------------------- ******‚IOHALTR·******À***#***ˆif�we�have�running�I/O�then�*******Šabort�command�running�on�this�port”*** ***ˆelse´***&***ŠReturn�invalid�function�error.˜***$***Šand�queue�normal�halt�event.š******À***F*** -------------------------------------------------------------- ****IOHALTR:F*‚Inhibit�interrupts�so�that�no�abort�can�be�sent�by�BREAK�which�could *‚confuse�us!*‰INHIBIT•mask�all�interrupts5ŠBTST„#ACTIVE,LUBUSY(A6)�see�if�the�device�is�active."ŠBEQ.SƒUNSHLT�No,�so�its�unsolicid**‰HALT�OUTSTANDING�I/O*SOLHLT:?ŠMOVE.L�A3,LUHIOCB(A6)…save�the�halt�IOCB�address�in�the�deviceŠCLR.L‚D2‘table.$ŠMOVE.B�#CMDAB,D0Šload�abort�command)ŠBSR„LINKBPPŒgo�link�in�BPP�command�queue%ŠBSET.B�#HLTFLG,LUCONTR(A6)�flag�haltŠBTST„#LSTREAD,LUCONTR(A6)1ŠIF��THEN.SŒIf�the�active�command�is�a�write,BŠBSET.B�#FTXQFLG,LUCONTR(A6)�set�the�flag�to�flush�TX�  queue�beforeŠENDI–the�next�command.ŠENABLE”enable�interuptsŠBRA„CMD_EXIT‹exit UNSHLT:!*‚If�there�is�no�I/O�in�progress:H*‚If�the�condition�exists,�someone�sent�us�a�Halt�I/O�request�for�an�I/OG*‚they�thought�was�in�progress�BUT�by�the�time�the�Halt�command�reached'*‚us�we�have�already�completed�the�I/O.*ŠENABLE”enable�interupts*4ŠMOVE.L‚A4,D3�Copy�the�DCB�pointer�to�used�register.ŠMOVE.B‚#ISTAIF,D1>ŠMOVE.B‚D1,IOSSTA(A3)…update�the�users�haltI/O�parameter�block+*£with�the�code�that�says�Invalid�Function.*#ŠMOVE.L‚#0,A0�Set�no�copy�of�event.*ŠJSR…N_HLT_QEVENT†Queue�normal�halt�event.ŠIF��THEN.S9‹KILL.DRIVER�M331DRV_ID,N_HLT_QVENT,A5,D3‚Kill�if�failed.ŠENDI*ŠBRA„CMD_EXIT‹do�normal�exit*‰PAGEF*** -------------------------------------------------------------- ******À******ƒIOWRITR…write�request:£***'***Œcall�IO_COMM�do�common�part�I/O•******‡If�image�write�request:¢***3***Œsend�the�write�request�to�the�ICC�and�exit.‰***#***‡If�formatted�write�request:ž***#***Œsearch�write�buffer�for�CR.™***+***Œsend�remaining�buffer�if�not�empty.‘***-***Œsend�termination�string�if�not�empty.�***(***ŒIf�any�command�sent�BRA‚CMD_SENT“***"***Œelse�quit�command�as�done.š******À***F*** -------------------------------------------------------------- ***IOWRITR:0ŠCLR.BƒD0�Set�register�to�indicate�use�of�IOSSAD2ŠBSR…IO_COMN‹and�IOSEAD�to�describe�output�buffer.*ŠBTSTW‚#OPT12,IOSOPT(A3)4ŠIF��THEN.SŒIf�option�is�to�clear�discard�output8ŠBCLR.B�#DISCARDF,LUCONTR(A6)�condition,�reset�the�flag.ŠENDI*-ŠMOVE.L‚D2,IOSLEN(A3)…Preset�transfer�length.*ŠBTST.B�#DISCARDF,LUCONTR(A6)2ŠIF��THEN.SŒIf�we�actually�discard�the�output,7ŠMOVE.B�#ISTAOK,D1‰quit�the�request�sa�done�and�return. ŠBRA„NCMDCMPLŠENDI*ŠBCLR.B‚#FTXQFLG,LUCONTR(A6)4ŠIF��THEN.SŒIf�this�flag�is�set,�send�a�flush�TX3ŠMOVE.B‚#CMDFTXQ,D0‡queue�command�to�the�ICC�board. ŠBSR…LINKBPPŠENDI*AŠBCLR„#LSTREAD,LUCONTR(A6)�Clear�the�flag�indicating�last�command *¦was�read.3ŠBTSTW‚#OPT3,IOSOPT(A3)ƒFormatted�or�image�request?ŠBNE.S‚IOWRI10ŒBranch�if�image.4ŠBSR„CRLOCK�This�is�a�formatted�write,�see�whether�a6ŠSUB.L‚D0,D2ŽCR�is�in�the�buffer.�If�so,�transmit�only@ŠMOVE.L�D2,IOSLEN(A3)†the�part�in�front�of�the�CR�and�preset�theA*4/24/86‚BEQ.S‚IOWRI20Œtransfer�length.�If�the�first�character�in)*£the�buffer�is�CR,�skip�transmitting�the+*£buffer�and�go�to�send�termination�string.*/IOWRI10ƒMOVE.B‚#CMDWR,D0‰Set�up�'write'�command1ŠBSET.B‚#WRFLG,LUBUSY(A6)�Set�flag�write�running.BŠBSET.B‚#TLENGTH,LUBUSY(A6)�Set�flag�to�obtain�length�from�returnd *¥packet.0ŠBSR…LINKBPP‹Go�link�packet�in�BBP�command�queue*3ŠBTSTWƒ#OPT3,IOSOPT(A3)‚If�this�is�an�image�output,ŠBNE„CMD_SENT‹do�normal�exit**‚else�handle�line�termination.*$ŠCLR.L‚D0‘get�configured�line�lengthŠMOVE.W�CONFIG+IOSREC(A6),D0'ŠBEQ.S‚IOWRI20Œif�zero,�send�EOL�string**ŠREPEAT”See�if�#�of�chars�sent�is�an�exact4ŠSUB.L‚D0,D2Žmultiple�of�the�configured�line�length. ŠUNTIL�)ŠBEQ„CMD_SENT‹Yes,�do�not�send�EOL�string*�THEN.SŒtermination�string�is�not�zero,�load4ŠLEA„CONFIG+IOSEOL(A6),A0�the�address�of�the�string.**4/24/86ƒBTSTƒ#WRFLG,LUBUSY(A6)<*4/24/86‚IF��THEN.SŒIf�the�write�running�flag�is'nt�set,.*4/24/86‚BSET.B�#WRFLG,LUBUSY(A6)‚then�set�it.*4/24/86‚ELSE.S=ŠBSET.B�#WRFRM,LUBUSY(A6)‚Else�set�flag�formatted�write.�This2*4/24/86‚ENDI–indicates�two�write�packages�must�be'*£returned�before�we�quit�this�request.$ŠMOVE.B�#CMDWR,D0Šdo�'write'�command0ŠBSR„LINKBPPŒgo�link�packet�in�BBP�command�queue*4/24/86‚ELSE.SG*4/24/86‚BTSTƒ#WRFLG,LUBUSY(A6)‚If�the�length�of�the�termination�string@*4/24/86‚IF��THEN.SŒis�zero�and�the�first�char�in�buffer�was5*4/24/86‚CLR.B‚D1‘a�CR,�just�quit�the�request�with�OK&*4/24/86‚BRA„NCMDCMPL‹status�and�exit. *4/24/86‚ENDIŠENDI*-ŠBRA…C  MD_SENTŠRequest�is�processed,�now�exit.‰PAGEF*** -------------------------------------------------------------- ******À*******‚IOOWINR†output�with�input�request:—***9***‡call�RDOPT�to�configure�the�options�for�the�read.ˆ***>***‡call�IO_COMN�to�validate�the�input�buffer�and�save�theƒ***3***Œreturned�physical�buffer�address�and�length‰******‡handle�the�write�part:£***3***‡call�IO_COMN�to�validate�the�output�buffer.Ž******‡If�image�write�request£***!***Œsend�to�the�ICC�and�exit.›******‡Else�formatted�write:¤***"***Œsearch�write�buffer�for�CRš***+***Œsend�remaining�buffer�if�not�empty.‘***-***Œsend�termination�string�if�not�empty.�***2***Œif�any�command�sent�up�to�this�point,�exitŠ***0***Œelse�initiate�the�read�command�and�exit.Œ******À***F*** -------------------------------------------------------------- ****IOOWINR:=ŠBCLR.B‚#DISCARDF,LUCONTR(A6)�Each�read�clears�the�condition.6ŠBCLR„#LSTREAD,LUCONTR(A6)‚Set�last�request�was�write.*ŠBCLR.B‚#FTXQFLG,LUCONTR(A6)9ŠIF��THEN.SŒIf�the�flag�is�set,�send�a�flush�TX�queue'ŠMOVE.B‚#CMDFTXQ,D0‡command�to�the�ICC. ŠBSR…LINKBPPŠENDI*>*„do�some�work�for�the�read�to�set�up�after�the�write�is�done.*7ŠMOVE.W�IOSOPT(A3),D5†Get�IOS�options�for�this�request.$ŠBCLRƒ#3,D5ŽClear�out�the�image�bit.!ŠBCLRƒ#10,D5�Image�input�request?ŠBEQ.S‚CMDIP1�No,�just�skip.+ŠBSETƒ#3,D5ŽIndicate�image�read�with�bit�3.2CMDIP1:ƒBSR„RDOPTŽConfigure�requested�read�options*9ŠMOVE.B‚#$FF,D0‹Set�register�to�indicate�IOSRRN�is�buffer0ŠBSR…IO_COMN‹start�address�and�IOSLEN�is�length.?ŠMOVE.L�A0,LUWIPA(A6)†Store�the�start�address�and�the�lenth�for!ŠMOVE.L�D2,LUWILEN(A6)…later�use.*/ŠCLR.BƒD0�Now�do�the�write�part�of�the�request.9ŠBSR…IO_COMN‹Chech�the�buffer�and�get�address�and�length.*<ŠBSET.B�#OIFLG,LUBUSY(A6)‚flag�channel�for�output�with�input)ŠBTSTW‚#OPT3,IOSOPT(A3)ƒFormatted�output?ŠBNE.S‚IOOWI10ŒNo,�it's�image.4ŠBSR„CRLOCK�This�is�a�formatted�write:�See�whether�a6ŠSUB.L‚D0,D2ŽCR�is�in�the�buffer.�If�so,�transmit�only@*4/24/86‚BEQ.S‚IOOWI20Œtha�part�in�front�of�the�CR.�If�the�first(*£char�is�CR,�skip�sending�th�buffer�and#*£go�to�process�termination�string.*0IOOWI10:‚MOVE.B�#CMDWR,D0ŠSet�up�'write'�command4ŠBSET.B�#WRFLG,LUBUSY(A6)‚Set�flag�write�is�running.0ŠBSR„LINKBPPŒgo�link�packet�in�BBP�command�queue*1ŠBTSTW‚#OPT3,IOSOPT(A3)ƒIs�this�output�formatted?ŠBNE„CMD_SENT‹No,�then�exit.*$ŠCLR.L‚D0‘get�configured�line�lengthŠMOVE.W�CONFIG+IOSREC(A6),D0'ŠBEQ.S‚IOOWI20Œif�zero,�send�EOL�string**ŠREPEAT”See�if�#�of�chars�sent�is�an�exact4ŠSUB.L‚D0,D2Žmultiple�of�the�configured�line�length. ŠUNTIL�$ŠBEQ„CMD_SENT‹Do�not�send�EOL�string*IOOWI20ƒMOVE.L�LURLTL(A6),D2;ŠIF��THEN.SŒIf�the�length�of�the�configured�termination@ŠLEA„CONFIG+IOSEOL(A6),A0‚string�is�not�zero,�load�it's�address.**4/24/86‚BTSTƒ#WRFLG,LUBUSY(A6)=*4/24/86‚IF��THEN.SŒIf�the�write�running�flag�is�not�set,-*4/24/86‚BSET.B�#WRFLG,LUBUSY(A6)‚set�it�now.*4/24/86‚ELSE.SCŠBSET.B�#WRFRM,LUBUSY(A6)‚Else�set�flag�formatted�write�to�indicate8*4/24/86‚ENDI–that�we�expect�two�returned�write�packets.*%ŠMOVE.B‚#CMDWR,D0‰Set�'write'�command-ŠBSR…LINKBPP‹and�send�the�termination�string.*5*4//24/86�ELSE.S”else�the�termination�string�is�zero.?*4//24/86�BTSTƒ#WRFLG,LUBUSY(A6)‚See�whether�we�issued�a�write.9*4//24/86�IF��THEN.SŒNoting�is�running�yet,�so�set�upA*4//24/86�MOVE.L�LUWIPA(A6),A0†a�read�request�to�the�ICC.�Use�theC*4//24/86�MOVE.L�LUWILEN(A6),D2…prepared�buffer�address�and�length./*4//24/86�MOVE.B�#CMDRD,D0ŠSet�the�read�command&*4//24/86�BSR„LINKBPPŒand�send�it�out.*4//24/86 ENDIŠENDI*ŠBRA„CMD_SENT‹Exit�normal.‰PAGEF*** -------------------------------------------------------------- ******À******�IOREADR¸***5***‡call�RDOPT�to�configure�option�for�this�read.Œ***2***‡call�IO_COMN�to�validate�the�input�buffer.�***3***‡call�LINKBPP�to�send�the�request�to�the�ICCŽ******‡do�normal�command�exit.¢******À***  F*** -------------------------------------------------------------- ****IOREADR: BŠBCLR.B�#DISCARDF,LUCONTR(A6)�Every�read�clears�discard�condition.:ŠBSET„#LSTREAD,LUCONTR(A6)�Indicate�last�request�was�read.)ŠMOVE.W�IOSOPT(A3),D5†Get�the�IOS�options&ŠBSR„RDOPTŽand�configure�READ�options.*2ŠCLR.B‚D0‘Set�up�register�to�force�usage�of�IOSSAD4ŠBSR„IO_COMNŒand�IOSEAD�for�buffer�checks�and�common*£stuff.*%ŠMOVE.B�#CMDRD,D0ŠSet�'read'�command.3ŠBSET.B�#RDFLG,LUBUSY(A6)‚Set�flag�read�is�running.*0ŠBSR„LINKBPPŒGo�link�packet�in�BBP�command�queue*ŠBRA„CMD_SENT‹exit�from�command‰PAGEF*** -------------------------------------------------------------- ******À******‚IOTBRKR·***(***‰send�a�SEND�BREAK�command�to�ICC—***;***‰the�ICC�automatically�stops�sending�the�break�after„******‰300�ms.°******À***F*** -------------------------------------------------------------- ****IOTBRKR:+‰MOVE.B„#CMDSNBP,D0‰load�send�break�command-‰BSR‡LINKBPP�go�link�command�in�command�queue!‰MOVE.W„#ISTAOK,D1Šload�OK�statusŠBRA„NCMDCMPL‹terminate‰PAGEF*** -------------------------------------------------------------- ******À******‚IOSTATR·***<***†copy�our�current�configuration�and�the�status�of�the†*** ***†port�into�the�user�area.¢******À***F*** -------------------------------------------------------------- ****IOSTATR:0‰MOVE.L„IOSDBP(A3),D6‡get�logical�address�of�CSB'‰MOVE.L„#IOSTLN,D5Šget�CSB�table�length.‰MOVE.L„CCBTASKB(A5),A0…get�address�of�his�TCB**‰JSR‡LOGPHYŽgo�convert�logical�to�physical*‰IFˆ†THEN.S%‰MOVE.B„#ISTAADD,D1‰return�error�code‰BRA‡NCMDCMPLŒgo�return�command‰ENDI*$‰MOVE.L„D6,A1�load�CSB�table�pointer8‰MOVE.B„LUSTAT(A6),IOSDST(A1)�set�up�the�current�status./‰MOVE.B„CCBTYPE(A5),IOSCTP(A1)�set�channel�type+‰MOVE.B„#XDSACIA,IOSDTP(A1)�set�device�type*‰MOVE.B„#IOD331,IOSDRC(A1)‚set�driver�code<‰MOVE.W„#RECATT,IOSATM(A1)‚set�mask�of�recognized�attributes<‰MOVE.W„#RECPAR,IOSPRM(A1)‚set�mask�of�recognized�parameters*9‰LEA‡LUCONF(A6),A0‡point�to�configuration�in�device�table2‰LEA‡IOSATW(A1),A1‡point�to�mask�in�his�data�block*;‰MOVE.W„#(IOSTLN-IOSATW)/2-1,D0�get�number�of�words�to�move*REQLOOP:‰MOVE.W„(A0)+,(A1)+‰move�a�word‰DBRA†D0,REQLOOPŠdo�next�word*#‰MOVE.B„#ISTAOK,D1Šload�good�status‰BRA‡NCMDCMPLŒexit�from�command‰PAGEJ*** -------------------------------------------------------------------******Ä******‚IOCNFGR»***>***‡All�current�and�new�attributes�and�parameters�are�used‡***:***‡to�build�a�configuration�item�table�and�new�action‹***<***‡tables.�This�is�done�to�avoid�configuration�problems‰***<***‡if�only�some�attributes�or�parameters�are�to�change.‰***>***‰call�CNFGCMN‚to�validate�the�attributes�and�parameters„*** ***‰configure�all�attributes£*** ***‰configure�all�parameters£***;***‰send�configure�table�and�configure�port�cmds�to�ICCˆ***+***‰send�reset�port�command�to�the�ICC.˜***>***‰send�request�port�status�command�to�the�ICC.�When�this…***5***‰command�is�returned,�the�request�is�finished.Ž***,***‰do�normal�exit�from�command�handler.—******Ä***J*** -------------------------------------------------------------------****IOCNFGR:*ŠBCLR.B‚#FTXQFLG,LUCONTR(A6)*ŠIF��THEN.S�if�the�flag�is�set,�......2ŠMOVE.B‚#CMDFTXQ,D0Šqueue�command�to�the�ICC�..... ŠBSR…LINKBPPŠENDI*8ŠLEA„CONFIG(A6),A0†Point�to�current�configuration�in�the*£device�table.*@‰MOVE.L„DCBDEV+IOSWTO(A4),IOSWTO(A0)�copy�write�and�read�timeout<‰MOVE.L„DCBDEV+IOSRTO(A4),IOSRTO(A0)�values�to�device�table.*=ŠMOVE.W‚#1<ŠMOVE.W‚IOSATW(A3),D5…Preset�the�arrtibutes�word�for�the�call.*2ŠBSR…CONF_ATTR‰Set�up�configuration�of�attributes.*1ŠBSR…CONF_PARŠSet�up�configuration�of�parameters.*,*…Now�send�the�defined�Item�table�to�the�ICC*4ŠLEA…LUCITAB(A6),A0„Load�base�address�of�Item�table.6ŠMOVE.B‚#CMDCNFP,D0‡Set�up�configure�port�Item�command2ŠBSR…LINKBPP‹and�link�packet�in�BPP�command�queue.*'*…Now�configure�the�four�Action�Tables.*7ŠMOVE.B‚#CMDCNFT,D0‡Set�up�the�configure�table�command.>ŠLEA…LUIRATID(A6),A0ƒLoad�the�base�address�of�the�first�table,AŠMOVE.L‚#(TABLEN+2)*4,D2‚set�the�length�to�configure�four�tables,2ŠBSR…LINKBPP‹and�link�packet�in�BPP�command�queue.‰PAGE*<*ˆhere�is�the�part�were�we�send�some�solicited�event�packets>*ˆto�the�ICC.�This�is�only�done�if�this�is�the�first�configure<*ˆrequest�for�this�port�after�initialization�of�the�channel.*4ŠMOVE.L‚A4,D3�Get�the�DCB�address�to�include�it�into*£the�message.<ŠTST.BƒLUSEDONE(A6)†If�this�is�not�the�first�configure,�skip-ŠBNE.SƒNOSEŽsending�solicited�event�packages.*+‰CLR.L…D2�Clear�registers�not�used�for�this‰CLR.L…D4�command. ‰CLR.L…D5'‰MOVE.L„D5,A0ŒNo�buffer�address�needed.*1‰MOVE.B„#CMDSSE,D0Šset�up�solicited�event�command :‰FOR.B‚D6�=�#1�TO�#NOSSE�BY�#1�DO.S�send�some�to�each�port/‰BSR‡LINKBPP�link�packet�into�BPP�command�queue‰ENDF*&ŠST†LUSEDONE(A6)†Set�to�indicate�done.NOSE:*9*ˆdo�a�reset�port�to�initialize�the�hardware�of�the�port.*/ŠMOVE.L‚CCBTASKB(A5),D4ƒSet�up�the�TCB�address.*ŠMOVE.L‚(A7)+,D5ŠRestore�the�IOCB�address./ŠMOVE.B‚#CMDRSTP,D0‡load�configure�port�command-ŠBSR…LINKBPP‹link�packet�in�BPP�command�queue*2ŠMOVE.B‚#CMDRQP,D0ˆNow�issue�a�request�port�status;ŠLEA…LUCITAB(A6),A0„command.�This�returnes�the�actual�level$ŠBSR…LINKBPP‹of�the�handshake�lines.*5ŠBRA…CMD_SENTŠExit�the�request.�the�interrupt�handler*£finishes�it�up.‰PAGEF*** -------------------------------------------------------------- ******À******‚IOCHDCR·***4***‰call�CNFGCMN�to�fill�and�validate�users�CSB.‹***6***‰copy�user�CSB�to�default�configuration�in�DCB.‰***=***‰copy�current�status�of�requested�device�to�users�CSB.‚*******‰goto�NCMDCMPL�to�complete�command.•******À***F**********************************************************************IOCHDCR:'*ˆfirst�get�our�configure�table�pointer*:ŠLEA…DCBDEV(A4),A0…Get�address�of�DCB�configuration�block.*2ŠCLR.WƒD0�Indicate,�that�all�recognized�attributes(ŠCLR.WƒD2�and�parameters�may�be�changed.*3ŠBSR…CNFGCMN‹Validate�the�attributes�and�parameters,ŠBNE…NCMDCMPLŠand�exit�if�an�error�detected.*8ŠMOVE.B‚LUSTAT(A6),IOSDST(A1)‚Update�the�current�status.6ŠLEA…IOSATW(A1),A1ŠPoint�to�the�attribute�word�in�both2ŠLEA…DCBDEV+IOSATW(A4),A0ƒblocks�in�order�to�copy.3ŠMOVE.W‚#(IOSTLN-IOSATW)/2-1,D0�#�of�words�to�copy. CDEFLOOP:#ŠMOVE.W‚(A1)+,(A0)+‡Do�word�by�word8ŠDBRA„D0,CDEFLOOP‡until�configuration�in�DCB�is�updated.*)ŠMOVE.B‚#ISTAOK,D1ˆLoad�no�error�code�and(ŠBRA…NCMDCMPLŠquit�this�command�as�done.‰PAGEF********************************************************************** ***�INTR»***C***�This�is�the�routine�that�completes�the�I/O�requests�started„***@***�by�the�the�command�service�routine.�It�is�entered�at�the‡***F*** interrupt priority level of interrupts on this channel, and is ***E***�essentially�a�subroutine�to�the�first�level�interrupt�handler‚******À***A***�Entry�conditions:�D0,A0,A1�have�been�saved�by�CMR�and�are†******“availa  ble.£******À***B***�Exit�conditions:�Exit�is�always�via�an�RTS,�which�takes�us…***1***’back�to�CMR.�The�carry�bit�is�examined�by…***3***’CMR�to�determine�whether�the�driver�handledƒ***4***’the�interrupt�or�not,�so�it�can�be�passed�on‚******’the�interrupt�chain.š******À***-***‹for�each�packet�in�BPP�staus�queue�do�******À***4***ŽRemove�returned�information�from�the�message†***!***Žand�save�it�in�registers.™******À***%***Žcase�return�packet�command�of•******À******‰1„READ”:™******‰2„WRITE“:™*** ***‰3„SEND�SOLICITED�EVENT„:™******‰4„ABORT“:™******‰5„CONFIGURE�ICC‹:™******‰6„CONFIGURE�PORTŠ:™******‰7„CONFIGURE�TABLE‰:™******‰8„RESERVED�:™******‰9„RESERVED�:™******‰10ƒRESERVED�:™******‰11ƒREQUEST�ICC�STATUS†:™*** ***‰12ƒREQUEST�PORT�STATUS…:™***!***‰13ƒREQUEST�TABLE�STATUS„:™******‰14ƒRESET�PORTŽ:™******‰15ƒSEND�BREAKŽ:™******‰16ƒFLUSH�RXQ�:™******‰17ƒFLUSH�TXQ�:™******À***F***----------------------------------------------------------------****INTR:@ŠMOVEM.L�D1-D7/A2-A4/A6,-(A7)‚Save�the�registers�used�inside�the*§interrupt�handler.9ŠTST.BƒCCBFLAG(A5)‡If�the�channel�is�in�error,�return�and4ŠBNE…EXTINTR0Šindicate�interrupt�not�served,�to�give'*£CMR's�interrupt�handler�the�change�to%*£pass�control�to�next�channel�in�CCB*£interrupt�chain.;ŠMOVE.L‚CCBCHB(A5),A0…Now�lets�have�a�loock�into�the�boards>ŠBTST„#BERRB,STMSG(A0)‚status�register�to�decide�whether�a�bus+ŠIF��THEN.SŒerror�or�timeout�is�flaged.7ŠMOVE.B‚#$FF,D0‹If�the�bit�is�clear,�indicate�we�are�in1ŠBRA…SET_DOWNŠinterrupt�level�and�call�routine�to/ŠENDI–complete�all�pending�requests�with�error.*L*‚If�we�reach�this�point,�the�board�seems�still�alive,�see�whether�it�passes*‚back�a�status�packet.*>ŠMOVE.L‚BPPS_O(A5),A0…Get�the�status�pipe�pointer�and�see�if�aDŠBTST.B‚#FLKFLG,FLNKB(A0)�buffer�is�returned.�If�the�address�is�odd,9ŠBNE…EXTINTR0Šthe�interrupt�is�not�from�this�board.�Exit,"*£indicating�interrupt�not�served.(ŠBRA.SƒDO_INTR‹Go�and�handle�this�pcket.*L*‚This�is�an�enry�point�where�we�get�after�handling�the�first�packet.�BeforeI*‚we�exit�the�interrupt�handler,�we�check�whether�an�additional�packet�isE*‚returned,�while�we�are�processing�the�last�one.�If�not,�we�quit�the*‚Interrupt�as�served.* NEXT_PACK:=ŠTST.BƒCCBFLAG(A5)‡At�this�point�repeat�the�check�whether�theŠBNE…EXTINTR‹board�is�down. 9ŠMOVE.L‚CCBCHB(A5),A0…Check�also�the�ICC�status�register.ŠBTST„#BERRB,STMSG(A0)ŠIF��THEN.S4ŠMOVE.B‚#$FF,D0‹The�board�is�down�now.�Terminate�allŠBRA…SET_DOWNŠpending�requests.ŠENDI*8‰MOVE.L„BPPS_O(A5),A0…See�whether�there�is�an�additional+‰BTST.B„#FLKFLG,FLNKB(A0)�message�returned.1‰BNE‡EXTINTR‹No,�exit�and�report�the�interrupt�as *¤served.DO_INTR:;ŠMOVE.L‚MSG(A0),A1ˆGet�the�pointer�to�the�returned�message.*0ŠGET_ON_BD�A1ŽLet�change�it�to�onbord�address�if *£necessary.8ŠMOVE.L‚FLK(A0),D0ˆGet�the�pointer�to�the�next�envelope.*$ŠGET_ON_BD�D0ŽSet�them�also�onboard.*2ŠMOVE.L�D0,BPPS_O(A5)†Store�it�status�pipe�pointer ŠCLR.W‚D5 ŠCLR.W‚D1*ŠMOVE.B�CMD(A1),D5‰Get�the�type�of�command'ŠMOVE.B�PORT(A1),D1ˆGet�the�port�number8ŠSUBQ.B�#1,D1Žand�set�it�zero�relative�for�internal�use.+ŠMOVE.B�STAT(A1),D0ˆGet�status�from�message-ŠMOVE.B�TERM(A1),D4ˆGet�the�terminating�char.(ŠMOVE.L�SAD(A1),A2‰Get�the�start�address*/ŠGET_ON_BD�A2ŽChange�it�to�onbord�if�necessary.*)ŠMOVE.L�RLEN(A1),D2ˆGet�the�return�length$ŠMOVE.L�IOCB(A1),A3ˆGet�IOCB�pointer'ŠMOVE.L�TCBP(A1),D7ˆGet�the�TCB�pointer"ŠMOVE.L�DCB(A1),D3‰Get�DCB�pointer*6ŠBSR„GETLUBUF‹Get�the�base�address�of�the�device�table*£entry�for�this�port�into�A6.*A*‚Now�call�the�routine�depending�on�the�type�of�command�returned.*= CASE 4,5,RESV,READ,WRITE,ABORT,SSEVENT,CNFICC,CNFPRT,CNFTBL,F& RQICCST,RESV,RESV,RESV,RQPRTST,RQTBLST,RESETPT,SNDBRK,FLSRXQ,FLSTXQ, & RESV,RESV ŠPAGEF***----------------------------------------------------------------******À*** ***‚READº***=***†Check�whether�a�HALT�I/O�or�BREAK�  was�received,�while…***9***†the�read�was�running.�In�this�case�finish�up�this‰******†request.²***<***†If�the�read�terminates�normal,�further�action�may�be†******†necessary:°***,***†-�Formatted�read�regardless�of�echo:–***<***ˆIf�the�length�of�the�termination�string�is�not�zero,„******Œsend�it�to�the�port; ***6***ˆelse�complete�the�request�by�sending�an�event.Š******†-�Image�read�with�echo:£***>***ˆIf�terminated�by�read�terminator,�send�it�to�the�port;‚***6***ˆelse�complete�the�request�by�sending�an�event.Š******†-�Image�without�echo:¥***1***ˆComplete�the�request�by�sending�an�event.�******À***F***----------------------------------------------------------------***READ:=ŠBCLR.B‚#RDFLG,LUBUSY(A6)�Clear�the�flags�indicating�read�and5ŠBCLR.B‚#OIFLG,LUBUSY(A6)�output�w.�input�is�running.*=ŠMOVE.L‚D2,IOSLEN(A3)…Update�the�transfer�length�in�the�IOCB.* ŠTST.BƒD00ŠIF��THEN.SŒIf�the�returned�status�is�>�$80:7ŠBSR…INTRCMN‹Link�the�packages�back�to�pools,�we�do�not$ŠCMP.Bƒ#$82,D0‹need�them�any�longer.%ŠIF��THEN.SŒIf�the�status�is�$81,/ŠMOVE.B‚#ISTADO,D1ˆreport�a�data�overrun�error.ŠELSE.S>ŠMOVE.B‚#ISTACSM,D1‡Else�quit�the�command�with�checksum�error.ŠENDI%ŠBRA…ICMDCMPLŠFinish�up�this�command.ŠENDI*6*‚Now�handle�the�packet�according�the�returned�status.*;‰CASE†4,0,RSTAT0,RSTAT1,RSTAT2,RSTATR,RSTAT4,RSTATR,RSTATR,B&ˆRSTATR,RSTATR,RSTATR,RSTATR,RSTATR,RSTAT12,RSTATR,RSTATR,RSTATR,%&ˆRSTATR,RSTATR,RSTATR,RSTATR,RSTAT20*RSTAT0::ŠMOVE.B�D4,(A2,D2.L)‡This�read�is�terminated�by�one�of�the**£defined�read�terminators.�Move�this�byte*£into�the�buffer.ŠBTST.B�#RDIMAGE,LUCONTR(A6)8ŠIF��THEN.SŒIf�the�request�was�image�read,�increment8ŠADDQ.L�#1,IOSLEN(A3)†the�transfer�length�to�include�theŠENDI–termination�character.*E*‚RSTAT0�falls�always�into�the�next�status�routine�to�finish�command.7*‚RSTAT1�is�called�if�the�read�fills�the�entire�buffer.*RSTAT1:@ŠBCLR.B�#HLTFLG,LUCONTR(A6)�If�a�HALT�I/O�is�received�before�the"ŠBNE„IQEVTHLT‹command�is�complete,*£go�and�process�the�halt.*DŠBCLR.B�#BRKFLG,LUCONTR(A6)�If�a�break�was�received�before�complete,&ŠBNE.S‚RQEVTBRKŒgo�queue�a�break�event*'ŠBRA.S‚RDONEŽGo�and�finish�up�the�read.*3*ƒWe�received�a�bad�status,�bring�the�channel�down.*RSTAT2:RSTATR:-ŠMOVE.B‚#$FF,D0‹Quit�all�pending�requests�and(ŠBRA…SET_DOWNŠmark�the�channel�in�error.*M*‚This�part�is�entered�if�the�status�indicates,�that�the�command�was�aborted.*RSTAT4:?ŠBCLR.B�#HLTFLG,LUCONTR(A6)�If�it�was�aborted�due�to�a�HALT�I/O+ŠBNE„IQEVTHLT‹request,�report�a�halt�event.'*£Else�it�was�a�break,�simply�fall�into*£its�handling. RQEVTBRK:0ŠBSR�INTRCMN�Link�the�packets�back�to�the�pools.(ŠMOVE.B�#ISTABRK,D1ˆSet�up�break�status,3ŠBRA„ICMDCMPL‹and�do�common�exit�part�of�interrupt.*F* This is the handling if the returned status indicates a data overrun* in the receive queue.*RSTAT12:*I* This is the status for the at least # of character function of the ICC.E* It should never become true, but if it happens, we handle it like a* data overrun.*RSTAT20:0ŠBSR�INTRCMN�Link�the�packets�back�to�the�pools.,ŠMOVE.B�#ISTADO,D1‰Set�up�data�overrun�error3ŠBRA„ICMDCMPL‹and�do�common�exit�part�of�interrupt.*7*‚This�is�the�common�code�for�a�normal�terminated�read.F*‚If�there�is�any�command�to�send�to�the�ICC,�the�returned�packets�are*‚used�to�do�this.*RDONE:ŠBTSTƒ#RDIMAGE,LUCONTR(A6):ŠIF��THEN.SŒIf�the�request�was�formatted�read,�we�sendEŠMOVE.L�LURLTL(A6),LEN(A1)�the�EOL�string�if�it's�length�is�not�zero.7ŠIF��THEN.SŒThis�is�done�regardless�of�echo�or�not.6‹BSET‚#WRFLG,LUBUSY(A6)‚Set�the�flag�write�is�running.B‹LEA„CONFIG+IOSEOL(A6),A4�Get�the�address�of�the�EOL�string�in�the:‹GO_OFF_BD�A4�device�table,�convert�it�to�offboard�address/‹MOVE.L�A4,SAD(A1)ˆand�write�it�to�the�message.0‹MOVE.B�#CMDWR,CMD(A1)„Set�up�the�write�command,4‹BSR„RE_LINK‹and�link�the�packets�back�to�the�queue.#‹BRA„NEXT_PACK‰See�for  �nect�packet.ŠENDI.ŠELSE.S”If�the�request�was�formatted�read�with‹BTSTƒ#NOECHOB,LUCONTR(A6)�echo‹IF��THEN.S4ŒTST.B�STAT(A1)Šand�the�read�was�terminated�due�to�a;ŒIF��THEN.SŠtermination�character,�send�this�character.2ŒBSET‚#WRFLG,LUBUSY(A6)‚Set�flag�write�is�running.:�LEA„TERM(A1),A4†Point�to�the�termination�character�in�the.�GO_OFF_BD�A4Œmessage�and�convert�the�address.6�MOVE.L�A4,SAD(A1)‡This�is�the�buffer�to�write�and�its!�MOVE.L�#1,LEN(A1)‡length�is�one.+�MOVE.B�#CMDWR,CMD(A1)ƒSet�up�write�command4�BSR„RE_LINKŠand�link�the�packets�back�to�the�queue.$�BRA„NEXT_PACKˆSee�for�more�packets.)ŒENDI•We�need�not�to�echo�the�terminator.‹ENDIŠENDI0ŠBSR„INTRCMNŠLink�the�packets�back�to�the�pools.0ŠMOVE.B�#ISTAOK,D1‡Complete�the�command�as�done. ŠBRA„ICMDCMPL ‰PAGEF***----------------------------------------------------------------*** ***‚WRITE¹***A***„-�If�a�HALT�I/O�or�a�BREAK�was�flaged,�while�the�read�wasƒ***'***ˆrunning,�finish�up�the�request.™***=***„-�If�this�is�the�first�packet�from�a�formatted�write,‡******ˆjust�exit.®***?***„-�If�this�is�the�last�packet�of�a�write�and�the�request…***;***ˆwas�not�output�with�input,�finish�up�the�command�by…***%***ˆqueuing�a�completition�event;›***:***†Else�set�up�the�read�command�for�the�ICC�and�exit.ˆ******À***F***----------------------------------------------------------------****WRITE:*ŠBCLR.B�#TLENGTH,LUBUSY(A6):ŠIF��THEN.SŒThe�first�returned�write�packet�is�the�one=ŠMOVE.L�D2,IOSLEN(A3)†from�which�to�take�the�transfer�length.ŠENDI*,ŠCASEƒ4,0,WSTAT0,WSTAT1,WSTAT2,WSTATR,WSTAT4***WSTAT0:WSTAT1:DŠBCLR.B�#WRFRM,LUBUSY(A6)‚Clear�the�control�flag.�If�the�request�was6ŠBNE.S‚LNTRMŽformatted,�we�expect�an�additional�packet*£before�we�complete.1ŠBCLR.B�#WRFLG,LUBUSY(A6)‚Cleat�the�control�flag.7ŠBCLR.B�#HLTFLG,LUCONTR(A6)�If�a�HALT�I/O�was�requestd.ŠBNE„IQEVTHLTŒgo�to�handle�it.*?ŠBCLR.B�#BRKFLG,LUCONTR(A6)�If�a�break�was�received,�handle�it. ŠBNE.S‚WBREAK*CŠBTST.B�#OIFLG,LUBUSY(A6)‚If�this�was�an�output�with�input�request,.ŠBNE.S‚OWICMD�go�to�initialize�the�input�part.*2ŠBSR„INTRCMNŒUnlink�packets�and‚them�to�free�pools,ŠMOVE.B�#ISTAOK,D1‰and�complete�the�request. ŠBRA„ICMDCMPL**‚We�received�a�bad�status:*WSTAT2:WSTATR:-ŠMOVE.B‚#$FF,D0‹Quit�all�pending�requests�and$ŠBRA…SET_DOWNŠmark�the�channel�down.*3*‚This�code�gets�active�if�the�command�is�abortded.*WSTAT4:AŠBCLR.B�#WRFRM,LUBUSY(A6)‚If�the�request�was�formatted,�we�expect"ŠBNE.S‚LNTRMŽan�additional�packet.*:ŠBCLR.B�#WRFLG,LUBUSY(A6)‚Clear�the�write�is�running�flag.?ŠBCLR.B�#HLTFLG,LUCONTR(A6)�If�we�are�aborted�due�to�a�HALT�I/O/ŠBNE.S‚IQEVTHLTŒrequest,�go�to�queue�the�event.*9ŠBCLR.B�#BRKFLG,LUCONTR(A6)�Else�it�was�a�received�break.;WBREAK:ƒBSR„INTRCMN�Unlink�packet�and‚return�in�free�pools.'ŠMOVE.B�#ISTABRK,D1‰Set�up�break�status(ŠBRA„ICMDCMPLŒand�finish�up�the�request.*1*‚This�was�the�first�packet�of�a�formatted�write:*LNTRM:5ŠBSR„INTRCMNŒLink�back�the�packeges�to�the�free�pools8ŠBRA„NEXT_PACKŠand�see�if�there�is�an�additional�packet.*?*‚We�completed�the�output�part�of�an�output�with�input�command.%*‚Now�we�have�to�initialize�the�read.*OWICMD:1ŠBSETƒ#RDFLG,LUBUSY(A6)‚Set�flag�read�is�running.+ŠMOVE.B�#CMDRD,CMD(A1)…Set�up�read�command.1ŠMOVE.L�LUWIPA(A6),D2†Get�address�of�input�buffer2ŠGO_OFF_BD�D2ŽTranslate�address�to�offboard�value.-ŠMOVE.L�D2,SAD(A1)‰Set�up�the�buffer�address.AŠMOVE.L�LUWILEN(A6),LEN(A1)�Set�up�the�length�of�the�read�buffer.9ŠBSR„RE_LINKŒLink�the�packages�back�to�the�command�queue.+ŠBRA„NEXT_PACKŠSee�for�additional�packages.* IQEVTHLT:2ŠBSR„INTRCMNŒLink�the�packages�back�to�free�pools.5ŠCLR.B‚LUBUSY(A6)‰Clear�the�active�flag�for�the�port.@ŠMOVE.L�LUHIOCB(A6),A0…Get�the�IOCB�address�of�the�HALT�request.DŠMOVE.B�#ISTAOK,IOSSTA(A0)�Update�the�users�Halt�I/O�status�with�OK.4ŠMOVE.B‚#ISTATO,D1ˆSet�up�timeout�status�for�request.ŠMOVE.B‚D1,IOSSTA(A3)…and�for�the�qu eue�event.*#ŠMOVE.L‚#0,A0�Set�no�copy�of�event.:ŠJSR…I_HLT_QEVENT†Queue�a�HALT�event�from�interrupt�level.ŠIF��THEN.S)‹KILL.DRIVER�M331DRV_ID,I_HLT_QVENT,A5,D3ŠENDI*)ŠBRA…NEXT_PACK‰See�for�additional�packet.*ŠPAGEF***----------------------------------------------------------------******À***.***�SSEVENT‚(SEND�SOLICITED�EVENT�COMMAND)˜*******†Make�a�copy�of�ICC�STATE�and�MASK.˜***1***†Relink�the�solicited�event�packet�to�ICC.‘***@***†Update�the�device�status�with�reported�status�of�CTS�and‚******†DCD�line.±***+***†Decode�the�type�of�solicited�event.—***"***†Do�the�appropriate�action. ******À***F***----------------------------------------------------------------****SSEVENT::ŠMOVEM.W�RLEN(A1),D6-D7„Get�record�and�state�of�sol.�event4ŠMOVE.L‚DCB(A1),D3ˆGet�the�DCB�address�of�this�port.&ŠCLR.LƒRLEN(A1)ŠClear�state�and�record#ŠCLR.WƒSTAT(A1)ŠClear�STAT�and�TERM*1ŠBSR…RE_LINK‹Link�the�solicited�event�packet�back*£to�the�command�queue.=*‰update�the�device�status�byte�with�the�received�status�from*‰the�port�returning�this�event*ŠBTST„#CTSB,D73ŠIF��THEN.SŒSet�the�not�ready�bit�according�the:ŠBCLR.B‚#XDSNRB,LUSTAT(A6)�returned�state�of�the�CTS�line.ŠELSE.SŠBSET.B‚#XDSNRB,LUSTAT(A6)ŠENDI 1ŠBTST„#DCDB,D7ŠSet�the�DCD�bit�also�according�the/ŠIF��THEN.SŒreturned�state�of�the�DCD�line.ŠBCLR.B‚#XDSDCD,LUSTAT(A6)ŠELSE.SŠBSET.B‚#XDSDCD,LUSTAT(A6)ŠENDI*%*‰lets�see�what�kind�of�event�we�have*(ŠBTST„#IR1B,D6Šdo�we�have�IRAT�#1�event?ŠIF��THEN.S=ŠBCHG.B‚#DISCARDF,LUCONTR(A6)�toggle�the�discsrd�output�flag.ŠENDI*"ŠBTST„#BRKB,D6ŠIf�we�have�a�break,ŠBNE.SƒBREAK�go�and�process�it.*-ŠBTST„#DCDB,D6ŠDo�we�have�DCD�change�of�stateŠIF��THEN.SEŠBTSTWƒ#IOADCD,CONFIG+IOSATW(A6)�If�we�are�configured�to�report�this,$ŠBNE.SƒBREAK�handle�it�like�a�break.ŠENDI**‰BRA‡NEXT_PACKˆSee�for�additional�packets.**‚We�received�a�Break�event.*BREAK:?ŠBTST.B‚#WRFLG,LUBUSY(A6)�If�a�write�or�read�is�running�on�this-ŠBNE.SƒSOLICID‹port,�this�is�a�solicid�event.ŠBTST.B‚#RDFLG,LUBUSY(A6) ŠBEQ.SƒUNSOL*SOLICID:<ŠBSET.B‚#BRKFLG,LUCONTR(A6)�Set�flag�for�the�reason�of�abort1ŠMOVE.B‚#CMDAB,D0‰and�abort�the�running�commands. ŠBSR…LINKBPPAŠBSET.B‚#FTXQFLG,LUCONTR(A6)�Set�flags�to�flush�TX�and�RX�queues.ŠBSET.B‚#FRXQFLG,LUCONTR(A6)%ŠBRA…NEXT_PACK‰See�fore�more�packets.*UNSOL:DŠBSET.B‚#FRXQFLG,LUCONTR(A6)�Set�flag�to�flush�RX�queue�before�read.2ŠMOVE.B‚LUSTAT(A6),D4…Get�the�status�of�our�device6ŠBSET„#XDSBRK,D4ˆSet�the�break�bit�in�the�status�byte.!ŠLSL.Wƒ#8,D4�Shift�to�second�byte(ŠMOVE.B‚#XDSACIA,D4‡Load�the�device�type'ŠMOVE.L‚#0,A0�Set�no�copy�of�the�event.3ŠJSR.LƒI_UNS_QEVENT†Queue�unsolicited�device�event.ŠIF��THEN.S)‹KILL.DRIVER�M331DRV_ID,I_UNS_QVENT,A5,D3ŠENDI%ŠBRA…NEXT_PACK‰See�for�more�packeges.‰PAGEF***----------------------------------------------------------------******À*** ***�ABORTº***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****ABORT:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.  F***----------------------------------------------------------------******À******�CNFICC:¸***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****CNFICC:)‰CMP.B„#OKSTAT,STAT(A1)‚See�if�packet�OK.‰IF��THEN.S-ŠMOVE.B‚#$FF,D0‹Quit�all�pending�requests�and$ŠBRA…SET_DOWNŠmark�the�channel�down.‰ENDI3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.  F***----------------------------------------------------------------******À******�CNFPRT:¸***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***------------------------------------- ---------------------------****CNFPRT:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.  F***----------------------------------------------------------------******À******�CNFTBL:¸***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****CNFTBL:3‰BSR‡INTRCMNŠUnlink�packet�and�return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.  F***----------------------------------------------------------------******�RQICCST:·***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****RQICCST:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.  F***----------------------------------------------------------------******À******�RQPRTST¸***%***†if�bad�status�kill�the�system�***3***†call‚INTRCMN‚(return�packets�to�free�pools)�***2***†exit‚to�CMDCMPL‚to�quit�configure�request.Ž******À***F***----------------------------------------------------------------****RQPRTST:(ŠCMP.Bƒ#OKSTAT,STAT(A1)‚see�if�packet�OKŠIF��THEN.SŠCMP.Bƒ#4,STAT(A1)$ŠBEQ…IQEVTHLTŠreturn�successful�halt-ŠMOVE.B‚#$FF,D0‹Quit�all�pending�requests�and$ŠBRA…SET_DOWNŠmark�the�channel�down.ŠENDI*3ŠBSR…INTRCMN‹Unlink�packet�and‚return�in�free�pools*$ŠTST.BƒCTSFLG(A2)ˆTest�the�CTS�state6ŠIF��THEN.SŒand�set�bit�in�status�byte�accordingly8ŠBCLR.B‚#XDSNRB,LUSTAT(A6)�clear�status�byte�accordinglyŠELSE.S6ŠBSET.B‚#XDSNRB,LUSTAT(A6)�set�status�byte�accordinglyŠENDI*$ŠTST.BƒDCDFLG(A2)ˆTest�the�DCD�state6ŠIF��THEN.SŒand�set�bit�in�status�byte�accordingly8ŠBCLR.B‚#XDSDCD,LUSTAT(A6)�clear�status�byte�accordinglyŠELSE.S6ŠBSET.B‚#XDSDCD,LUSTAT(A6)�set�status�byte�accordinglyŠENDI*:ŠMOVE.L‚LUWIPA(A6),A2…Update�the�device�status�in�the�CSB.ŠMOVE.B‚LUSTAT(A6),IOSDST(A2)*3ŠMOVE.B‚#ISTAOK,D1ˆQuit�the�request�with�OK�status. ŠBRA…ICMDCMPL  F***----------------------------------------------------------------******À******�RQTBLST:·***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****RQTBLST:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.‰PAGEF***----------------------------------------------------------------******À******�RESETPT¸***%***†if�bad�status�kill�the�system�***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****RESETPT:(‰CMP.B…#OKSTAT,STAT(A1)�See�if�packet�OKŠIF��THEN.SŠCMP.Bƒ#4,STAT(A1)ŠIF��THEN.S-ŠMOVE.B‚#$FF,D0‹Quit�all�pending�requests�and$ŠBRA…SET_DOWNŠmark�the�channel�down.ŠENDIŠENDI3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packages. F***----------------------------------------------------------------******À******�SNDBRK:¸***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****SNDBRK:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packeges.  F***----------------------------------------------------------------******À******�FLSRXQ:¸***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****FLSRXQ:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packages.  F***----------------------------------------------------------------******À******�FLSTXQ:¸***3***†call‚I NTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À******À***F***----------------------------------------------------------------****FLSTXQ:3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packages.  F***----------------------------------------------------------------*** ***�RESV»***3***†call‚INTRCMN‚(return�packets�to�free�pools)�******†exit‚to�NEXT_PACK¨******À***F***----------------------------------------------------------------****RESV:/*ˆthese�commands�are�not�jet�implemented�by�ICC 3‰BSR‡INTRCMNŠUnlink�packet�and‚return�in�free�pools+‰BRA‡NEXT_PACKˆSee�for�additional�packages. E**************************************************************************–END�OF�ICCDRV˜*****E*********************************************************************‰END NNNNNJ* WARNING - The MVME360 driver is NOT supported without the purchase of an(*‹MVME360�board,�part�number�MVME360-VX.ŠENDNNNNNN Ná5M420DRV‚IDNT�45,0…VERSAdos�MVME420�(SASI)�disk�driverNNNNNNNãêóMû*- 787#>+:3;;7C9K9S:[5c6k;sB{?ƒ2‹;“;›3£5«9³3»IÃ7Ë0Ó31‰TTL‚M420DRV:�VERSAdos�MVME420�(SASI)�disk�driverK***************************************************************************K***************************************************************************K***************************************************************************K****************************************************************************%*ˆM420DRV:‚VERSAdos�SASI�disk�driver.**ˆRevision�history:**ˆ10/31/85‚Initial�release.4*ˆ12/11/85‚Added�CHK_PARAM�routine�called�by�DISKlib*K***************************************************************************K***************************************************************************K***************************************************************************K***************************************************************************‰PAGE**ƒXREF'S�from�DISKLIB*ŠXREF…DISK_INITŠXREF…DISK_COMMANDŠXREF…CHAN_DONE **‚Equate�files�included:* *‰INCLUDE‚9995.&.TCB.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.&.UTILITY.MC  ŠOPT�CRE,PCS **‰MISC�EQUATES*3DRIVES ƒEQU‡4“Total�number�of�drives�on�our�channel. **ˆBWN‡2/13/84ƒPJD‚9/18/84*1GOODCODE�EQU‡0“Opcode�for�format�sector�as�"good"1BADCODE‚EQU‡$80‘Opcode�for�format�sector�as�"bad"7ALTCODE‚EQU‡$40‘Opcode�for�format�sector�as�"alternate"*‰NOLIST*$*‰Include�the�standard�equate�files:*‰INCLUDE‚9995.&.TCB.EQ‰INCLUDE‚9995.&.CCB.EQ‰INCLUDE‚9995.&.LV5.EQ‰INCLUDE‚9995.&.IOE.EQ‰INCLUDE‚9995.&.NIO.EQ‰INCLUDE‚9995.&.UTILITY.MC ‰TTL†DISK.EQ‰LIST‰INCLUDE‚9995.&.DISK.EQ‰TTL†DISKCCB.EQ‰INCLUDE‚9995.&.DISKCCB.EQ‰TTL†M420DRV.SA‰PAGE/‰OFFSETƒDCCBDDP�Continue�with�channel-dependent*¦CCB�variable�space.  M*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%* *%%%Å%%%*B*%%%„Device-dependent,�channel�related,�variables�start�here.‰%%%* *%%%Å%%%**%%%™(CCB�SPACE)¡%%%* *%%%Å%%%*M*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*  E*ˆThe�following�subsection�of‚the�channel-related�part�of�the�device-H*‚dependent�portion‚of‚the‚CCB�is�used�by�the�SASI�interrupt�handler�forH*‚building�a‚command�packet�that�can�be�sent�to�the�SASI�controller.ƒTheM*‚variables�in�the�command�packet�must�occur�in�the�exact�order�that�is�shownK*‚because�the�entire�command�packet�is�treated�as�an�indivisible�block.ƒTheK*‚SASI�controller‚interprets�the�individual�fields�of�the�command�packet�as#*‚shown�in�the�illustrations�below.  4*‡7‚6‚5‚4‚3‚2‚1‚0‹Byte�zero�of�a�SASI�command�packetD*…--------------------------‡contains�the�opcode�that�tells�the�SASI4*‚0‚|‰Opcode‰|‡controller�what�operation�to�perform.?*…|------------------------|‡Bits�7�-�5�of�byte�one�contain�the5*‚1‚|‚LUNƒ|�|‡controller-defined�logical�unit�number,3*…|---------�--|‡which�is�equivalent�to�the�channel3*‚2‚|‰Logicalˆ|‡device�number.‚Bits�4-0�of�byte�one7*…|--‡Sector‡--|‡and�all�of�bytes�two�and�three�usually/*‚3‚|‰Number‰|‡contain�a�logical�sector�number.*…|------------------------|7*‚4‚|†Sector�Count†|‰Byte�four�of�a�SASI�command�packetB*…|------------------------|‡normally�contains�a�sector�count,�but<*‚5‚|†Control�Code†|‡byte�four�is�used�to�contain�the�inter-B*…--------------------------‡leave�factor�when�a�format�command�is*‡^‚^›being�specified.*‡|‚|:*‡|‚----�Disable�data�Finally,�byte�five�of�a�SASI�command;*‡|‡error�correction.†packet�contains�a�control�code.‚Bit�7**‡|žof�the�control�code�can�be�set�to�dis-A*‡-------�Disable�retries.‡able�automatic�controller�retries,�and)*¦bit�6�of�the�control�code�can�be�set�to%*¦disable�data�error�correction.‚Bits&*¦5-0�of�the�control�code�are�ignored.‰PAGE4*‡7‚6‚5‚4‚3‚2‚1‚0‹When�the�opcode�field�of�a�commandC*…--------------------------‡packet�specifies�the�SASI�command�thatB*‚0‚|‚Define-Format�Opcode‚|‡defines�the�format�for�a�floppy�disc,@*…|------------------------|‡some�of�the�remaining�fields�of�the5*‚1‚|‚LUNƒ|�|‡command�packet�are�interpreted�a�little2*…|---------�--|‡differently�(as�described�below).*‚2‚|ˆIgnored‰|.*…|--”--|‰The�field�that�normally�contains�the-*‚3‚|˜|‡logical�sector�number�is�ignored,�andA*…|------------------------|‡the�field�that�normally�contains�the1*‚4‚|ˆIgnored‰|‡sector�count�is�also�ignored.‚TheB*…|------------------------|‡control-code�field�is�used�to�specify9*‚5‚|†Control�Code†|‡the�format�that�is�being�defined�forB*…--------------------------‡the�floppy�disc.‚Bit�0�of�the�control**™^‚^‰code�can�be�set�to�specify�a�double-)*™|‚|‰sided�floppy�disc,�and�bit�1�of�theA*‚1�=�Double�Density�-----‚|‰control�code�can�be�set�to�specify�a(*œ|‰double-density�floppy�disc.‚Bits�7-2>*‚1�=�Double�Sided�----------‰of�the�control�code�are�ignored. E*ˆThese�variables�define�the�command�packet�that�was�described�above. !‰DS.W…0”Align�to�a�word�boundary. 2CMDOP„DS.B…1–The�CMDOP�field�of�the�command�packet)*¦contains�the�opcode�that�tells�the�SASI'*¦controller�what�operation�to�perform.$*¦For�example,�the�CMDOP�field�might)*¦contain�an�opcode�that�specifies�a�read)*¦op eration,�a�write�operation,�a�format-**¦disc�operation,�a�format-track�operation%*¦or�a�define-format�operation.‚Refer'*¦to�the�interrupt�handler�for�details. 2CMDLSNƒDS.B…3–The�CMDLSN�field�of�a�command�packet:LSNMASK‚EQU†$001FFFFFŒoften�contains�a�logical�unit�number5LUNFIELD�EQU†5”and�a�logical�sector�number�to�specify)*¦a�particular�area�of�a�particular�disc.&*¦The�LSNMASK�value�is�a�bit�mask�that$*¦indicates�which�bits�of�the�CMDLSN(*¦field�can�be�used�for�a�logical�sector)*¦number,�and�the�LUNFIELD�value�is�a�bit)*¦number�to�indicate�that�bits�5-7�of�the)*¦first�byte�of�the�CMDLSN�field�are�used"*¦for�the�LUN�field.‚The�LUN�field)*¦contains�the�controller-defined�logical)*¦unit�number,�which�is�equivalent�to�the*¦channel�device�number. 4CMDSECTS�DS.B…1–The�CMDSECTS�field�contains�a�sector8CMDILVƒEQU†CMDSECTS�count�for�a�read�or�write�operation,&*¦and�it�contains�an�interleave�factor&*¦for�a�format�operation.‚The�CMDSECTS&*¦field�always�contains�the�value�zero *¦for�a�define-format�operation.‰PAGE/MAXSECTS�EQU†255”This�label�defines�the�maximum(*¦possible�value�that�can�be�used�in�the'*¦CMDSECTS�field.‚If�an�I/O�transaction)*¦involves�more�than�MAXSECTS�sectors,�we(*¦must�break�up�the�transaction�into�two*¦or�more�smaller�transactions. 2CMDCTRL‚DS.B…1–The�CMDCTRL�field�of�a�SASI�command3NORETRY‚EQU†7”packet�contains�a�control�code.‚Bit�74NOCORRƒEQU†6”of�the�control�code�in�a�normal�command)*¦packet�can�be�set�to�disable�controller(*¦retries,�and�bit�6�of�the�control�code'*¦in�a�normal�command�packet�can�be�set'*¦to�disable�data�error�correction.‚The(*¦SASI�controller�ordinarily�ignores�the%*¦remaining�bits�of�the�control�code. >CTRLDFLT�EQU†0<*%%%„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�SASI�driver. %*¨CCBSIZE�defines�the�size�(in�pages)?L0080„EQU†CCBSIZEB+PAGESIZE-1‚of�a�CCB�for�the�SASI�driver,�andBCCBSIZE‚EQU†L0080/PAGESIZE‡EXTCCBSZ�defines�the�size�(in�pages)�of*ƒ15‚14‚13‚12ƒ11‚10ƒ9ƒ8„in�the�parameters�mask�are�not�used�byI*‚+---+---+---+---++---+---+---+---+‚the�SASI�driver,�but�all�of�the�bits8*‚|‹|ƒ||ƒ|ƒ|ƒ|ƒ|‚that�are�defined�for�any�disc�drive�are;*‚+---+---+---+---++---+---+---+---+‚shown�in�the�diagrams.*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|:*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�IOSSOF�is�significant�(not�used).*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|1*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�IOSPSM�is�significant. *„|ƒ|ƒ|ƒ|„|ƒ|>*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�IOSSHD�is�significant�(not�used). *„|ƒ|ƒ|ƒ|„|A*„|ƒ|ƒ|ƒ|„----------------�1�=�IOSTRKD�is�significant�(not�used). *„|ƒ|ƒ|ƒ|D*„|ƒ|ƒ|ƒ---------------------�1�=�IOSPCOM�is�significant�(not�used).*„|ƒ|ƒ|F*„|ƒ|ƒ-------------------------�1�=�IOSSPTD�is�significant�(not�used).*„|ƒ|G*„|ƒ-----------------------------�1�=�IOSSRB�is�significant�(not�used).*„|K*„---------------------------------�1�=�IOSRWCCB�is�significant�(not�used).  *„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0$*‚+---+---+---+---++---+---+---+---+*‚|ƒ|ƒ|ƒ|ƒ||ƒ|ƒ|ƒ|ƒ|$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|/*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�IOSREC�is�significant.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|1*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�IOSRSZ�is�significant. *„|ƒ|ƒ|ƒ|„|ƒ|>*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�IOSWTO�is�significant�(not�used). *„|ƒ|ƒ|ƒ|„|@*„|ƒ|ƒ|ƒ|„----------------�1�=�IOSRTO�is�significant�(not�used). *„|ƒ|ƒ|ƒ|8*„|ƒ|ƒ|ƒ---------------------�1�=�IOSSPT�is�significant.*„|ƒ|ƒ|:*„|ƒ|ƒ-------------------------�1�=�IOSHDS�is�significant.*„|ƒ|<*„|ƒ-----------------------------�1�=�IOSTRK�is�significant.*„|>*„---------------------------------�1�=�IOSILV�is�significant. PAGE*%*ˆAttributes�Mask�for�the�SASI�Driver* '*¨The�individual�bits�of�the�attributes&*¦word�are�interpreted�as�shown�in�the*¦accompanying�diagrams. !*¨Notice�that�the�top�half�of�the<*ƒ15‚14‚13‚12ƒ11‚10ƒ9ƒ8„attributes�word�is�completely�unusedI*‚+---+---+---+---++---+---+---+---+‚for�a�SASI�disc,�but�the�top�half�of+*‚| |‚the�attributes�word�is�still�present.$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|:*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Post-read/pre-write�precomp�req'd#*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ˆ(Not�used�by�SASI).4*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�8�"�disk;�0�=�5-1/4"�disk *„|ƒ|ƒ|ƒ|„|ƒ|-*„---------------------------------�Not�used.  *„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0$*‚+---+---+---+---++---+---+---+---+*‚|‹|ƒ||ƒ|ƒ|ƒ|ƒ|$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|<*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Double�data-density�(MFM)�on�media.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|9*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�Double�track-density�on�media.*„|ƒ|ƒ|ƒ|„|ƒ|�(Always�1)6*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�Double-sided�floppy�disc. *„|ƒ|ƒ|ƒ|„|?*„|ƒ|ƒ|ƒ|„----------------�1�=�IBM�format;�0�=�Motorola�format.*„|ƒ|ƒ|ƒ|™(Always�1)>*„|ƒ|ƒ|ƒ---------------------�1�=�Rigid�disc;�0�=�floppy�disc.*„|ƒ|ƒ|G*„|ƒ|ƒ-------------------------�1�=�Double�data-density�(MFM)�on�drive.*„|ƒ|¡(Not�used�by�SASI).D*„|ƒ-----------------------------�1�=�Double�track-density�on�drive.*„|¥(Not�used�by�SASI).K*„---------------------------------�1�=�Seek�req'd�w/�head�switch�on�drive.*ª(Not�used�by�SASI). PAGE*!*ˆMVME420�memory-mapped�I/O�space* 0‰OFFSETƒ-1•This�OFFSET�block�defines�the�memory-&*¦mapped�I/O�space�for�a�SASI�channel.&*¦The�SASI�driver�communicates�throu gh&*¦this�memory-mapped�I/O�space�with�an&*¦MVME420�SASI�Peripheral�Adapter,�and'*¦the�MVME420�in�turn�communicates�with*¦an�SA1403D�SASI�controller. %*¨The�CCBCHB�pointer�that�is�supposed"*¦to�point�to�the�beginning�of�the(*¦memory-mapped�I/O�area�actually�points$*¦to�byte�1�of�the�memory-mapped�I/O(*¦area,�so�we�use�an�offset�of�-1�in�the$*¦OFFSET�statement�to�compensate.‚We%*¦want�the�CCBCHB�pointer�to�point�to)*¦byte�1�instead�of�byte�0�of�the�memory-&*¦mapped�I/O�area�because�that�circum-)*¦stance�allows�us�to�use�(An)�addressing)*¦to�address�the�first�meaningful�byte�of*¦the�interface�area. $*¨The�MVME420�does�not�decode�all�of$*¦the�bytes�in�its�memory-mapped�I/O(*¦space,�so�a�number�of�the�bytes�in�the(*¦memory-mapped�I/O�space�are�unused.‚In(*¦particular,�the�MVME420�doesn't�decode$*¦any�bytes�at�even�addresses,�so�we(*¦include�unnamed�DS.B�statements�in�the(*¦code�below�to�skip�the�unused�bytes�at*¦even�addresses. ,‰DS.B…1–Writing�the�value�$01�(i.e.,�SEL)�to5SELECTƒDS.B…1”the�SELECT�register�selects�the�SA1403D.SEL†EQU†$01’controller.‚The�controller�must�be%*¦selected�as�the�first�step�in�every&*¦I/O�transaction�that�we�perform�with%*¦the�controller.‚The�driver�must�not*¦issue�a�select�command�if�the!*¦controller�is�already�selected. %*¨The�SELECT�register�is�a�write-only *¦register.‰PAGE2FLAGS„EQU†SELECT‘The�FLAGS�register�is�a�read-only)*¦register�that�shares�its�memory�address&*¦with�the�write-only�SELECT�register.8*„7ƒ6ƒ5ƒ4„3ƒ2ƒ1ƒ0„The�bits�in�the�FLAGS�register�provideI*‚+---+---+---+---++---+---+---+---+‚status�information�about�the�SA1403D6*‚|ƒ|‡|ƒ||ƒ|ƒ|ƒ|ƒ|‚controller�as�shown�in�the�diagram.$*‚+---+---+---+---++---+---+---+---+*„^ƒ^ƒ^ƒ^„^ƒ^ƒ^ƒ^*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ|<*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|ƒ----�1�=�Controller�requesting�command�byte.*„|ƒ|ƒ|ƒ|„|ƒ|ƒ|=*„|ƒ|ƒ|ƒ|„|ƒ|ƒ--------�1�=�Controller�requesting�output�data. *„|ƒ|ƒ|ƒ|„|ƒ|=*„|ƒ|ƒ|ƒ|„|ƒ------------�1�=�Controller�has�input�data�ready. *„|ƒ|ƒ|ƒ|„|@*„|ƒ|ƒ|ƒ|„----------------�1�=�Controller�has�status�byte�ready. *„|ƒ|ƒ|ƒ|B*„|ƒ|ƒ|ƒ---------------------�1�=�Controller�requesting�interrupt.*„|ƒ|ƒ|)*„|ƒ|ƒ-------------------------…Not�used.*„|ƒ|+*„|ƒ-----------------------------…Not�used.*„|<*„---------------------------------�1�=�Controller�selected.  2BITCMDƒEQU†0–Bit�0�of�the�FLAGS�register�is�set�if;REQCMDƒEQU†1<*‚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*********************************************************************************ˆINTERRUPT�POLLING�ROUTINE*B*ˆControl�can�come�to�the‚SASI�interrupt�handler�when�CMR�receivesC*ˆan�interrupt�on�the�interrupt�level�that�is�used�by�the�SASI�diskC*ˆcontroller.�If�the�interrupt�is�a�SASI�interrupt,�the�SASI�driverA*ˆhandles�it,‚and�returns�to�CMR�with�the�C�bit�set�of�the�SR.‚IfA*ˆthe�interrupt�is�not�a�SASI�interrupt,‚return�to�CMR�with�the�C*ˆbit�cleared.*#*ˆEntry:„JSR�from�interrupt�handler*’A5�=�physical�address�of�CCB*<*ˆThe�interrupt�level�is�at�the�level�of�the�SASI�interrupt.8*ˆD0,�A0,�A1,�A5�have�been�saved�by�CMR.‚The�driver�must *ˆsave�any�other�registers�used.*!*ˆRegister�usage:…0�1�2�3�4�5�6�7*™D‚**™A‚*‰P**ˆExit:…RTS�back�to�CMR*O*******************************************************************************O******************************************************************************* **ˆIs�the�interrupt�for�me?**¨Time >INTERUPT�MOVE.LƒCCBCHB(A5),A0ˆ16�(4/0)‡Point�A0‚to�the�MVME4201‰MOVEQ„#REQINT,D0Œ4�(1/0)…memory-mappedƒI/O‚area,4‰AND.B„FLAGS(A0),D0Š8�(2/0)…and‚check�the�SASI‚FLAGS0‰BNE.S„SASIINT�8�(1/0)…register‚to�see�if�a�SASI&‰RTS›16�(3/0)…interrupt�is�pending.ƒIf$*¦--------…there‚isn't�a�SASI�inter-$*¦52(11/0)…rupt�pending,‚return�with*³SR.C�=�0‚to�indicate�that*³the�interrupt‚isn't�ours.*³The�AND‚instruction�auto-*³matically�clears�the‚SR.C *³bit�for�us.‰PAGEO********************************************************************************#*ˆSASI�INTERRUPT�CO-ROUTINE�LINKAGE*C*ˆControl�reaches�this�point�when�we've�successfully�identified�theA*ˆinterrupt�as�a‚SASI�interrupt.‚This�routine�is�also�called�as�aB*ˆsubroutine�when�the‚command-processing�routine�wants�to�activateB*ˆinterrupt�processing.‚Whenever�the�interrupt�handler�empties�theB*ˆI/O�queue,�we�deactivate�interrupt�processing.‚When�the�command-B*ˆprocessing�routine‚puts�a�new�queue�entry�into�a�empty�queue,�it5*ˆmust�call�SASIINT�to�activate�interrupt�processing.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB*!*ˆRegister�usage:…0�1�2�3�4�5�6�7 *™D‚*�P�P *™A‚P�*ƒP�P�P*=*ˆExit:…Jump�to�co-routine�segment�addressed�by�INTSWTCH(A5).*O******************************************************************************* 2SASIINT‚EQU†*–We�know�we�have�a�SASI�interrupt,�so>EQ420„EQU†DSABLINT+LEDOFF†disable�the�interrupt�at�the�MVME420?‰MOVE.Bƒ#EQ420,CONTROL(A0)ƒSASI�Peripheral�Adapter.‚Then�enable<‰MOVE.WƒCCBSR(A5),SR‰68000�interrupts�at�our�interrupt�level'*¦so�that�other�interrupts�at�our�level'*¦won't�be�delayed �while�we�process�our$*¦interrupt.‚Every�interrupt�handler)*¦should�mask�its�interrupt�at�the�source)*¦of�the�interrupt�and�then�quickly�lower(*¦the�system�interrupt�mask�by�one�level)*¦to�allow�the�system�to�respond�to�other#*¦interrupts�that�occur�at�the�same*¦priority�level. @EQ430„REG†A4/A3/A2/D3/D2/D1†A5,�A1,�A0,�and�D0�have�already�been;‰MOVEM.L‚EQ430,-(SP)Šsaved�by�CMR.‚Here�we�save�the�rest�of'*¦the�registers�that�we�need�to�use.‚We(*¦save�only�the�registers�that�we�really%*¦need�because�we�don't�want�to�waste(*¦time�or�stack�space.‚Time,�especially,'*¦is�important�in�an�interrupt�handler. <‰MOVE.LƒIOQUEUE(A5),A1‰Set�A1�=�LOC(Drive's�variable�block).)*¦The�first�entry�of�the�IOQUEUE�contains)*¦a�pointer�to�the�variable�block�for�the)*¦disc�drive�that�we�should�be�accessing. =‰MOVE.LƒINTSWTCH(A5),A3ˆBranch�to�the�co-routine�segment�that"‰JMP†(A3)‘should�be�executed�next. %*¨Control�will�eventually�return�from(*¦the�selected�co-routine�segment�to�the&*¦INTRTN�routine,�which�implements�the*¦return�linkage�to�the�system.‰PAGEO*********************************************************************************ˆSASI�OPCODE�TABLE*@*ˆThis�table‚contains�the‚SASI-defined�opcode‚values�for�the�I/OD*ˆoperations�that�we�currently�use�with�the�SA1403D�SASI�controller.*O******************************************************************************* 0*’---------------------------�SASI�Opcode�value.*’|*’|”------�IOFUNCT�index�value.*’|”|*’V”V‰DC.B…$0A’-1�=�Write�disc.OPTBL„DC.B…$04“0�=�Format�disc.-‰DC.B…$C0’+1�=�Define�format�for�floppy�disc.‰DC.B…$08’+2�=�Read�disc. 5FTRACKƒDC.B…$06”The�opcode�for�a�format-track�command)*¦is�not�indexed�by�the�IOFUNCT�value�for%*¦a�format-track�command.‚The�format-$*¦track�command�has�the�same�IOFUNCT&*¦value�that�is�used�for�a�format-disc'*¦command,�and�we�uniquely�identify�the'*¦format-track�command�by�the�fact�that(*¦its�IOOPTS�value�is�different�from�the)*¦IOOPTS�value�that�is�used�for�a�format-(*¦disc�command.‚Then�we�compute�a�pseudo'*¦IOFUNCT�value�that�indexes�from�OPTBL *¦to�FTRACK. !‰DS.W…0–Align�to�a�word�boundary. 3SENSECMD�EQU†$03”This�label�defines�the�SASI�opcode(*¦value�for�a�request-sense�command.‚The$*¦SASI�driver�issues�a�request-sense&*¦command�whenever�the�SASI�controller'*¦returns�a�status�value�that�indicates$*¦an�error.‚The�controller�returns�a&*¦status�value�at�the�end�of�every�I/O(*¦transaction,�and�the�driver�checks�the%*¦status�value�to�see�if�an�error�has(*¦occurred.‚If�an�error�has�occurred,�we)*¦issue�a�request-sense�command�to�obtain'*¦detailed�information�about�the�error. "*¨A�user's�program�cannot�directly&*¦generate�a�request-sense�command,�so(*¦the�opcode�value�for�the�request-sense)*¦command�isn't�in�the�SASI�opcode�table.&*¦The�SASI�driver�automatically�issues)*¦request-sense�commands�as�necessary�for*¦error�analysis.‰PAGEO*********************************************************************************ˆPROCESS�NEXT�QUEUE�ENTRY*E*ˆControl�comes�to�this�co-routine�segment�to�process�the�front�entryD*ˆof�the�IOQUEUE.‚We�are�guaranteed�that�the�queue�in�non-empty�when *ˆcontrol�comes�to�this�routine.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�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*9*ˆExits�to:‚Send�a�command�packet�to�the�SASI�controller.*O******************************************************************************* =PROCQUE‚LEA†CMDEND(A5),A3ŠWe�want�to�examine�the�variables�in(*¦the�drive's�I/O�packet,�and�we�want�to'*¦construct�a�command�packet�for�a�SASI)*¦command�that�will�implement�part�or�all&*¦of�the�function�that�is�specified�in$*¦the�drive's�I/O�packet.‚Then�we'll)*¦transmit�the�command�packet�to�the�SASI *¦controller. %*¨We�start�by�pointing�A3�to�t he�byte(*¦that�immediately�follows�the�last�byte(*¦of�the�command�packet�in�memory.‚We'll(*¦use�autodecrement�addressing�to�access*¦the�command�packet.*+* MOD FOR DTC 520A SASI CONTROLLER 11/16/83*(*�Modified�for�both�controllers„12/12/83*(‰CMP.B…#1,IOFUNCT(A1)†TEST�FOR�CONFIGURE!‰BNE.S…PROQ1�BRA�IF�NOT�CONFIGURE-‰BTSTW…#IOASIZE,CONFGBLK+IOSATW(A1)‚8"�DRIVE?‰BNE.S…PROQ1�BRA�IF�8"�DRIVE6‰LEA‡DTCCMD(A5),A3‡POINT�TO�CONFIGURE�DRIVE�CMD.�PCKT.‰BRA.S…L0490AŽGO�SEND�DATA**�END�OF�MOD—11/17/83ƒ**DPROQ1„MOVE.BƒCTRLCODE(A1),-(A3)…Copy�the�control-code�value�from�the2L1‡SET†CMDCTRLŽdrive's�I/O�packet�into�the�CMDCTRL%*¦field�of�the�command�packet.‚Notice'*¦the�use�of�the�SET�pseudo�instruction)*¦to�generate�a�concordance�entry�for�the&*¦CMDCTRL�field�that�is�modified�here.‰PAGE;‰MOVE.LƒIOSCTCNT(A1),D0ˆNow�use�the�IOSCTCNT�value�from�the<‰MOVE.Lƒ#MAXSECTS,D1‰drive's�I/O�packet�to�fill�the�CMDSECTS0‰CMP.L„D1,D0�field�of�the�command�packet.‚If�the3‰BLS.S„L0470�count�of�remaining�sectors�exceeds�the3‰MOVE.LƒD1,D0�maximum�number�of�sectors�that�can�be>16,(A3)+ƒdisc�drive's�I/O�packet�to�set�up�the;‰MOVE.BƒDRIVENUM(A1),D1†logical�sector�number�in�the�CMDLSN8‰LSL.B„#LUNFIELD,D1‰field�of�the�command�packet.‚We�also6‰OR.B…D1,-(A3)�use�the�DRIVENUM�value�from�the�drive's1L1‡SET†CMDLSN�I/O�packet�to�set�the�LUN�(Logical-#*¦Unit-Number)�field�in�the�command&*¦packet.‚Notice�that�the�LUN�field�in)*¦the�command�packet�occupies�the�top�few&*¦bits�of�the�first�byte�of�the�CMDLSN%*¦(Logical-Sector-Number)�field.‚Also'*¦notice�the�use�of�the�SET�instruction)*¦to�generate�a�concordance�entry�for�the*¦CMDLSN�field. 9‰ADD.L„D0,IOSECTOR(A1)ˆIncrease�the�IOSECTOR�value�in�the%*¦drive's�I/O�packet�by�the�number�of%*¦sectors�that�will�be�processed�as�a%*¦result�of�this�command�packet.‚This(*¦adjustment�causes�IOSECTOR�to�point�to)*¦the�sector�that�should�be�specified�for(*¦the�next�(if�any)�command�packet�after *¦this�one.‰PAGE;‰MOVE.BƒIOFUNCT(A1),D0‰Get�the�IOFUNCT�code�into�D0.W�so�we+‰EXT.W„D0“can�use�it�to�index�into�the�SASI1‰BNE.S„L0490�opcode�table.‚If�the�IOFUNCT�code�is(*¦nonzero,�we�aren't�processing�a�format'*¦command.‚In�this�case,�we�can�use�the&*¦IOFUNCT�value�directly.‚For�a�format#*¦command,�however,�we�must�do�some*¦special�processing. >EQ480„EQU†CONFGBLK+IOSILVˆFor�a�format�command�we�must�install@‰MOVE.BƒEQ480(A1),CMDILV(A5)�an�interleave�value�into�the�CMDILV$*¦field,�which�overlays�the�CMDSECTS'*¦field�of�the�command�packet.‚There�is'*¦no�sector�count�for�a�format�command,'*¦but�the�controller�requires�an�inter-%*¦leave�code�in�place�of�the�CMDSECTS*¦field�for�a�format�command. 9‰CMP.W„#IOPTRK,IOOPTS(A1)…If�the�IOOPTS�value�in�the�disc4‰BNE.S„L0490�drive's�I/O�packet�indicates�that�we're:‰MOVEQWƒFTRACK-OPTBL,D0†processing�a�format-track�command,'*¦adjust�D0.W�to�index�the�format-track!*¦entry�of�the�SASI�opcode�table.%*¦Otherwise,�D0.W�already�indexes�the&*¦format-disc�entry�of�the�SASI�opcode*¦table. #*¨We�use�a�single�IOFUNCT�value�for&*¦both�the�format-disc�c ommand�and�the&*¦format-track�command.‚We�distinguish)*¦one�command�from�the�other�by�examining*¦their�IOOPTS�values. FL0490„MOVE.BƒOPTBL(PC,D0.W),-(A3)ƒFinally,�fill�the�CMDOP�field�of�the4L1‡SET†CMDOP�command�packet�from�the�proper�entry�of'*¦the�SASI�opcode�table.‚Notice�that�A3&*¦now�points�to�the�CMDOP�field�of�the'*¦command�packet,�so�we�can�use�A3�with)*¦autoincrement�addressing�as�we�send�the(*¦command�packet�to�the�SASI�controller.'*¦Also�notice�the�use�of�the�SET�pseudo'*¦instruction�to�generate�a�concordance*¦entry�for�the�CMDOP�field. 6L0490AƒBSR†SENDCMD�Send�the�command�packet�to�the�SASI&*¦controller�to�tell�the�controller�to&*¦start�processing.‚Subroutine�SENDCMD'*¦uses�A3�with�autoincrement�addressing(*¦to�send�the�command�packet�to�the�SASI)*¦controller,�and�subroutine�SENDCMD�also'*¦assumes�that�A0�points�to�the�memory-)*¦mapped�I/O�area�for�the�SASI�peripheral *¦adapter.‰PAGEO*********************************************************************************ˆREAD�OR�WRITE�NEXT�SECTOR*B*ˆControl‚comes�to�the�top�of�this‚co-routine�when�the�SASI�driverD*ˆis�ready�to�read�or�write�the�data�for�the�next�sector�that�should@*ˆbe�transferred.‚Control�also‚comes�to�this‚routine‚immediately=*ˆafter‚any�command‚sequence‚has�been‚transmitted‚to‚the‚SASI *ˆcontroller.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�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*1*ˆExits�to:‚Branches�to�interrupt�return�routine.*O******************************************************************************* 8NEXTSECT�BSR†INTRTN‘The�SASI�controller�needs�time�to�do$*¦its�job�before�we�can�transfer�any(*¦data,�so�return�control�to�the�system.'*¦When�the�SASI�controller�has�finished$*¦its�current�task,�we'll�receive�an&*¦interrupt�that�will�cause�control�to(*¦come�back�here.‚The�co-routine�linkage)*¦conveniently�allows�us�to�call�the�rest&*¦of�the�system�as�if�it�were�simply�a)*¦subroutine�to�be�executed�while�we�have*¦nothing�better�to�do. #*¨If�we've�just�transmitted�a�write%*¦command�to�the�SASI�controller,�the'*¦interrupt�should�occur�quickly�(since(*¦the�controller�should�soon�be�ready�to'*¦copy�a�sector�of�output�data�into�its$*¦data�buffer).‚However,�experiments&*¦have�shown�that�the�controller�needs'*¦enough�time�even�in�this�case�to�make(*¦it�worthwhile�for�us�to�return�control*¦to�the�system. %*¨If�we've�just�transmitted�a�read�or'*¦format�command�to�the�controller,�the%*¦controller�will�obviously�require�a&*¦substantial�amount�of�time�before�it*¦interrupts�the�system�again.‰PAGE9EQ530„EQU†CONFGBLK+IOSPSMˆControl�reaches�this�co-routine;‰MOVE.WƒEQ530(A1),D1‰segment�when�the�controller�interrupts(*¦to�indicate�that�it's�ready�to�proceed'*¦with�the�I/O�operation.‚We�get�IOSPSM&*¦into�D1.W,�so�D1.W�now�indicates�the!*¦logical�sector�size�(in�bytes). 9‰TST.L„HALFSCTS(A1)‹If�the�next�sector�to�be�processed�is2‰BEQ.S„L0535�a�half�sector,�divide�the�sector�size2‰LSR.W„#1,D1�by�two�to�account�for�the�fact�that�a>‰SUB.L„#1,HALFSCTS(A1)†half�sector�has�only�half�as�many�bytes(*¦as�a�normal�sector.‚Then�decrement�the(*¦count�of�the�half�sectors�remaining�to%*¦be�processed.‚Half�sectors�arise�in'*¦track�zero�of�a�double-density�floppy(*¦disc�because�the�sectors�in�track�zero%*¦of�a�double-density�floppy�disc�are*¦recorded�with�single�density. ‰MOVEP.L‚DATA0(A0),D0†|‚the�memory�map.‚Therefore,�the�MOVEP.L5‰MOVE.LƒD0,(A3)+Š|‚instruction�accesses�the�same�data(*§|‚register�four�consecutive�times�with/‰DBRA…D3,L0550Š----‚the�maximum�possible�speed. #*¨If�the�SASI�controller�happens�to$*¦suffer�from�a�catastrophic�failure)*¦during�this�loop,�we'll�get�a�bus�error*¦to�indicate�the�problem. 4‰DBRA…D1,READDATAŒIf�we�haven't�finished�reading�the&*¦current�sector�of�data,�loop�back�to(*¦read�the�next�chunk�of�LCDSCTSZ�bytes.$*¦By�reading�LCDSCTSZ�bytes�and�then)*¦checking�the�controller,�we�can�prevent&*¦the�careless�user�from�causing�a�bus*¦error. 0‰BRA.S„RWCOMMON�We've�finished�reading�an�entire(*¦sector�of�input�data,�so�now�go�to�the#*¦common�routine�that�completes�the&*¦processing�of�a�sector�for�both�read"*¦operations�and�write�operations.‰PAGEO*********************************************************************************ˆWRITE�A�SECTOR�OF�DATA*O******************************************************************************* GWRTDATA‚MOVEQIƒSELECTED+REQWRITE,D3ƒWe're�performing�a�write�operation,4‰BSR†CHKFLAGS�so�check�the�SASI�controller�to�verify)*¦that�the�controller�is�ready�to�receive'*¦output�data.‚Subroutine�CHKFLAGS�sets)*¦the�CC.Z�bit�if�the�controller�is�ready&*¦for�the�operation�indicated�in�D3.B. >L0560„SNE.B„NOFINISH(A1)‹If�the�controller�isn't�ready�for�the7‰BNE.S„READSTAT�proper�operation,�set�the�NOFINISH�flag%*¦and�go�try�to�read�the�controller's$*¦status�report.‚We�use�the�NOFINISH'*¦flag�to�indicate�that�a�read�or�write$*¦I/O�operation�has�failed�to�finish$*¦correctly�for�some�unknown�reason. &*¨Control�comes�through�this�same�code$*¦segment�if�the�controller�fails�to'*¦become�ready�for�the�proper�operation*¦during�a�read�transaction. .EQ561„EQU†4*8”Each�iteration�of�the�inner�loop=EQ562„EQU†LCDSCTSZ/EQ561‡below�trans fers�4*8�=�32�data�bytes,=EQ563„EQU†EQ562*EQ561Šand�each�iteration�of�the�outer�loop�is9‰IFNE…LCDSCTSZ-EQ563‡supposed�to�transfer�LCDSCTSZ�bytes./‰FAIL…0”[****�ERROR�****�ERROR�****�ERROR�****]+‰ENDCšTherefore,�we�must�verify�that�4*8�is#*¦an�exact�divisor�of�LCDSCTSZ.‚The#*¦instruction�that�is�conditionally&*¦assembled�here�generates�an�assembly)*¦error�if�4*8�is�not�an�exact�divisor�of%*¦LCDSCTSZ.‚If�this�error�occurs,�the(*¦maintenance�programmer�will�be�alerted(*¦to�change�the�inner�loop�below�to�make(*¦it�transfer�some�other�number�of�bytes)*¦so�that�a�single�iteration�of�the�outer#*¦loop�can�transfer�LCDSCTSZ�bytes. @‰MOVEQWƒLCDSCTSZ/EQ561-1,D3„Initialize�D3.W�to�control�the�inner'*¦loop.‚We'll�perform�enough�iterations(*¦of�the�inner�loop�to�transfer�LCDSCTSZ*¦bytes�of�data.‰PAGE?L0570„MOVE.Lƒ(A3)+,D0Š----‚Each�complete�iteration�of�this�loop>‰MOVEP.L‚D0,DATA0(A0)†|‚transfers�4*8�=�32�data�bytes�from�the(*§|‚output�buffer�to�the�SASI�controller8‰MOVE.Lƒ(A3)+,D0Š|‚and�we�perform�just�enough�iterations>‰MOVEP.L‚D0,DATA0(A0)†|‚of�this�inner�loop�to�transfer�a�total *§|‚of�LCDSCTSZ�bytes�during�one/‰MOVE.Lƒ(A3)+,D0Š|‚iteration�of�the�outer�loop.‰MOVEP.L‚D0,DATA0(A0)†|#*§|„We�use�a�MOVEP.L�instruction�to7‰MOVE.Lƒ(A3)+,D0Š|‚transfer�four�consecutive�data�bytes?‰MOVEP.L‚D0,DATA0(A0)†|‚with�the�maximum�possible�speed,�and�we&*§|‚replicate�the�code�in�this�loop�to7‰MOVE.Lƒ(A3)+,D0Š|‚reduce�the�effects�of�loop�overhead.;‰MOVEP.L‚D0,DATA0(A0)†|‚We�could�replicate�the�code�in�this'*§|‚loop�more�times�for�even�more�speed8‰MOVE.Lƒ(A3)+,D0Š|‚but�diminishing�returns�begin�to�make=‰MOVEP.L‚D0,DATA0(A0)†|‚further�replications�less�attractive.*§|8‰MOVE.Lƒ(A3)+,D0Š|„The�SASI�controller�actually�has�just<‰MOVEP.L‚D0,DATA0(A0)†|‚one�data�register,�but�that�register'*§|‚appears�at�4�different�locations�in9‰MOVE.Lƒ(A3)+,D0Š|‚the�memory�map.‚Therefore,�the�MOVEP.L:‰MOVEP.L‚D0,DATA0(A0)†|‚instruction�accesses�the�same�data%*§|‚register�4�consecutive�times�with/‰DBRA…D3,L0570Š----�the�maximum�possible�speed. #*¨If�the�SASI�controller�happens�to$*¦suffer�from�a�catastrophic�failure)*¦during�this�loop,�we'll�get�a�bus�error*¦to�indicate�the�problem. 3‰DBRA…D1,WRTDATA�If�we�haven't�finished�writing�the&*¦current�sector�of�data,�loop�back�to)*¦write�the�next�chunk�of�LCDSCTSZ�bytes.$*¦By�writing�LCDSCTSZ�bytes�and�then)*¦checking�the�controller,�we�can�prevent&*¦the�careless�user�from�causing�a�bus*¦error. &*¨We've�finished�transferring�a�sector&*¦of�output�data,�so�now�control�falls(*¦into�the�common�routine�that�completes%*¦the�processing�of�a�sector�for�both'*¦read�operations�and�write�operations.‰PAGEòÛ0ä8ì5ô6ü93 38@$>,@4:<3D<L5T7\2d8l<tK|F„IŒD”Eœ=¤B¬@´>¼;Ä'O********************************************************************************#*ˆCOMPLETE�PROCESSING�OF�READ/WRITE*#*ˆEntered�from:�READDATA�or�WRTDATA* *ˆExits�to:*O******************************************************************************* @RWCOMMON�MOVE.LƒA3,IOBUFPTR(A1)ˆUpdate�the�I/O�buffer�pointer�to#*¦point�to�the�next�byte�of�the�I/O&*¦buffer.‚If�there's�another�sector�of'*¦data�to�be�transferred,�IOBUFPTR�will'*¦be�used�to�address�the�I/O�buffer.‚If'*¦there�isn't�another�sector�of�data�to'*¦be�transferred,�we'll�use�IOBUFPTR�to)*¦calculate�the�number�of�bytes�that�were*¦actually�transferred. :‰SUB.B„#1,CMDSECTS(A5)ˆDecrement�the�count�of�sectors�that4‰BHI†NEXTSECT�remain�to�be�processed�for�the�current&*¦SASI�command�sequence.‚If�we�haven't(*¦finished�processing�all�of�the�sectors(*¦for�the�current�SASI�command�sequence,'*¦loop�back�to�process�the�next�sector. .‰TST.B„D2•We've�finished�processing�all�of�the5‰BGT.S„RDSTAT1Žsector(s)�for�t he�current�SASI�command&*¦sequence.‚If�we're�performing�a�read%*¦operation,�go�read�the�controller's&*¦status�report.‚The�controller�should#*¦have�the�status�report�for�a�read$*¦operation�ready�almost�immediately(*¦after�the�last�sector�of�data�has�been%*¦read,�so�there's�no�advantage�to�be$*¦gained�by�returning�control�to�the(*¦system�to�wait�for�a�status-ready�SASI(*¦interrupt.‚Recall�that�D2.B�=�+1�for�a)*¦read�transaction�and�that�D2.B�=�-1�for*¦a�write�transaction. $*¨If�we're�performing�a�write�opera-)*¦tion,�fall�into�the�top�of�the�READSTAT%*¦routine.‚Control�will�return�to�the)*¦system,�and�we'll�get�control�back�when&*¦a�status-ready�interrupt�occurs.‚The'*¦controller�will�require�a�significant)*¦amount�of�time�before�it�has�its�status%*¦report�ready�because�it�must�do�the(*¦physical�writing�of�the�last�sector�of'*¦data�before�it�can�prepare�its�status *¦report.‰PAGEO********************************************************************************!*ˆREAD�THE�SASI�CONTROLLER�STATUS*O******************************************************************************* 7READSTAT�BSR.S„INTRTN‘Return�control�to�the�system,�and)*¦wait�for�a�status-ready�SASI�interrupt.&*¦We'll�get�control�back�when�the�SASI)*¦controller�has�its�status�report�ready. 5RDSTAT1‚BSR†GETSTAT�Get�the�status�bits�from�the�SASI6‰BNE.S„STATERRŽcontroller's�status�byte�into�D0.B,�and(*¦report�an�error�if�the�status�bits�are&*¦nonzero.‚A�status�bit�that�is�set�in(*¦the�controller's�status�byte�indicates&*¦an�error.‚Subroutine�GETSTAT�returns$*¦the�condition�codes�reflecting�the(*¦status�bits�from�the�SASI�controller's*¦status�byte. 6‰MOVEQIƒISTACFG,D1�If�the�NOFINISH�flag�is�nonzero,�we8‰TST.B„NOFINISH(A1)‰return�a�status�code�indicating�that4‰BNE.S„SASIDONE�the�actual�configuration�of�the�disc(*¦doesn't�match�the�configuration�in�the%*¦current�configuration�block.‚An�I/O)*¦operation�failed�to�finish�properly,�so&*¦the�sector�size�on�the�disc�probably&*¦doesn't�match�the�sector�size�in�the*¦configuration�block. 8‰TST.L„IOSCTCNT(A1)‹The�SASI�controller�has�successfully1‰BNE†PROCQUEŽcompleted�the�entire�I/O�transaction(*¦that�was�specified�by�the�last�command(*¦sequence�that�we�gave�it.‚If�there�are'*¦any�sectors�remaining�to�be�processed)*¦for�the�current�entry�of�the�I/O�queue,'*¦loop�back�to�process�another�chunk�of*¦the�entire�I/O�transfer. %*¨Recall�that�IOSCTCNT�is�always�zero&*¦for�any�I/O�transaction�that�doesn't(*¦involve�the�transfer�of�any�read/write*¦data. 9‰MOVE.BƒEOVFLAG(A1),D1‰We've�now�completed�the�entire�I/O'*¦transaction�that�was�specified�by�the$*¦command�that�generated�the�current%*¦entry�of�the�I/O�queue.‚The�EOVFLAG'*¦value�that�we�get�into�D1.B�here�will#*¦be�returned�to�the�user�as�an�I/O&*¦status�code.‚If�the�I/O�transfer�was'*¦truncated�to�avoid�running�beyond�the(*¦end�of�the�disc,�we�return�the�ISTAEOV'*¦status�code.‚Otherwise,�we�return�the)*¦ISTAOK�status�code�to�indicate�that�the!*¦entire�operation�went�smoothly.‰PAGEO*********************************************************************************ˆFINISH�PROCESSING�QUEUE�ENTRY*F*ˆControl�comes�here�when�the�driver�is�done�with�the�current�command.D*ˆWe�call�CHAN_DONE�in‚DISKLIB�to�queue�the�I/O�completion�event�for@*ˆus,�and‚we‚remove�the�current‚entry�from‚the�queue.‚If�the�I/OD*ˆqueue�has�another�entry,‚we'll�loop�back�and�start�processing�that*ˆentry.*=*ˆEntry:„D1.B�=�VERSAdos�error�code�if�error,�otherwise�zero.9*’D2�=�Logical�sector�number�if�error,�otherwise�garbage.)*’A1�=�Pointer�to�drive's�variable�block.*’A5�=�Physical�address�of�CCB*?*ˆThese�entry�conditions�are�required�by�the�CHAN_DONE�routine.*6*ˆCalls:„CHAN_DONE�in�the�generic�disk�driver�DISKLIB.*=*ˆExit:…Branches�to�process�next�queue�entry�if�there�is�one.0*’Falls�through�to�idle�loop�if�there�isn't�one.*O****************************************************************** ************* SASIDONE�EQU†* 2‰JSR†CHAN_DONEŒCall�the�generic�disk�driver�to�set"*¦fields�in�the�IOCB�and�queue�the*¦event�for�us. 6EQ650„REG†A1/A3/A4�Here�we�remove�the�front�entry�fromA‰MOVEM.L‚IOQUEUE+4(A5),EQ650‚the�I/O�queue,�and�we�simultaneouslyA‰MOVEM.L‚EQ650,IOQUEUE(A5)„set�A1�to�point�to�the�drive�block�for(*¦the�disc�drive�that�is�associated�with$*¦the�next�(if�any)�entry�of�the�I/O%*¦queue.‚Since�there�are�a�maximum�of(*¦four�entries�in�the�I/O�queue,�we�need'*¦to�move�no�more�than�three�entries�to(*¦remove�the�first�entry�from�the�queue. 6‰SUB.W„#4,IOQCNT(A5)ŠReduce�the�queue-count�pointer�to1‰BHI†PROCQUEŽaccount�for�the�fact�that�we've�just(*¦removed�a�four-byte�entry�from�the�I/O$*¦queue.‚If�there�is�still�an�active&*¦entry�in�the�I/O�queue,�loop�back�to"*¦start�processing�the�next�entry. $*¨If�the�I/O�queue�is�empty,�control(*¦falls�into�the�co-routine�segment�that%*¦is�potentially�active�when�the�SASI'*¦controller�is�caught�up�and�should�be*¦idle.‰PAGEO*********************************************************************************ˆIDLE�LOOP�ROUTINE*C*ˆControl�falls�into�this�co-routine‚segment�when�the‚I/O�queue�hasD*ˆbeen�emptied.‚The�SASI�controller�is�completely�caught�up�with�all?*ˆof�its�requests,‚and�the‚controller‚should‚now�be‚idle.‚We'llB*ˆsimply�return�control�to�the‚system�to‚idle�the‚SASI‚controller.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�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*D*ˆExits�to:‚Stays�in�loop�until�the�driver�receives�another�command.*O******************************************************************************* :IDLELOOP�BSR.S„INTRTN‘The�I/O�queue�is�empty,�so�we�simply%*¦return�control�to�the�system.‚We've)*¦caught�up�with�all�of�the�requests�that'*¦have�been�set�up�for�processing�under*¦interrupt�control. 4‰ST.B…CHANDOWN(A5)‹If�control�ever�comes�to�this�co-%*¦routine�segment,�we�have�a�problem.#*¦Apparently,�we've�received�a�SASI%*¦interrupt�when�we�haven't�given�the%*¦controller�anything�to�do.‚In�fact,%*¦not�only�have�we�not�given�the�SASI'*¦controller�anything�to�do,�we�haven't*¦even�enabled�its�interrupt. #*¨It's�hard�to�tell�what�might�have$*¦caused�this�problem,�but�something$*¦serious�is�wrong.‚We�mark�the�SASI&*¦channel�down,�and�we'll�report�it�as%*¦being�down�the�next�time�the�system*¦tries�to�access�it. 2‰BRA.S„IDLELOOP�Return�to�the�idle�loop.‚We'll�get$*¦out�of�this�loop�whenever�the�SASI&*¦driver�receives�another�command�that(*¦requires�some�action�that�must�be�done*¦under�interrupt�control.‰PAGEO*********************************************************************************ˆRETURN�FROM�INTERRUPT*C*ˆThis�routine�is�called�whenever�we�want�to�return�control�to�CMR;B*ˆto�wait�for�the�next�interrupt�or�when�we've�finished�processingA*ˆall�commands.‚This�routine�is�always�called�as�a�subroutine,�so?*ˆthe�stack�contains�the�address�of�the�co-routine�segment�thatD*ˆshould�be�executed�in�response�to�the�next�interrupt.�This�routineA*ˆstores�that�address�in�INTSWTCH,�and�enables�data�interrupts�if!*ˆthere�is�data�left�to�transfer.*=*ˆEntry:„A0�=�physical�address�of�SASI�Memory-Mapped�I/O�area*’A5�=�physical�address�of�CCB*O******************************************************************************* DINTRTNƒMOVE.Lƒ(SP)+,INTSWTCH(A5)ƒSave�the�co-routine�switch�address. AEQ440„REG†D1/D2/D3/A2/A3/A4„Restore�the�registers�that�were�saved;‰MOVEM.L‚(SP)+,EQ440Šat�the�start�of�the�interrupt�handler. 5‰TST.W„IOQCNT(A5)�If�the�IOQUEUE�is�non-empty,�enable/‰BEQ.S„L0455�SASI�interrupts.‚If�the�IOQUEUE�is&*§empty,�however,�we�don't�enable�SASI?EQ450„EQU†ENABLINT+LEDOFF†interrupts,�giving�us�an�extra�margin%‰MOVE.Bƒ#EQ450,CONTROL(A0)ƒof�safety. !*¨If�our�processing�has�been�slow)*¦because�of�higher-leve l�interrupts,�the(*¦SASI�controller�might�already�have�the'*¦next�interrupt�pending.‚In�this�case,(*¦the�interrupt�will�occur�as�soon�as�we(*¦enable�SASI�interrupts�here,�and�we'll*¦have�nested�SASI�interrupts. 4CARRY„EQU†1<<0“Finally,�set�the�SR.C�bit,�and�return:L0455„OR.B…#CARRY,CCR‹control�to�CMR.‚Setting�the�SR.C�bit)‰RTS›indicates�that�we�have�processed�the *¦interrupt.‰PAGEO*********************************************************************************ˆSTATUS-ERROR�ROUTINE*E*ˆControl�comes�to�this�routine�when�the�SASI�controller�has�reportedB*ˆa�status�error.‚We'll‚interrogate�the‚controller�to�get�detailedA*ˆinformation‚regarding‚the�exact‚nature�of�the‚error,�then�we'llD*ˆreport�the‚detailed�error�classification�to�the�user�via�the�error*ˆstatus�code.*=*ˆEntry:„A0�=�physical�address�of�SASI�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*8*ˆExits�to:‚SASIDONE�routine�to�report�error�to�the�user*O******************************************************************************* ;STATERR‚LEA†CMDEND(A5),A3ŠWe'll�use�the�same�command�packet3‰CLR.W„-(A3)�that�we�used�for�the�command�that�just5L1‡SET†CMDCTRLŽgenerated�the�status�error�because�the7L1‡SET†CMDSECTS�LUN�(Logical-Unit-Number)�field�and�the&*¦LSN�(Logical-Sector-Number)�field�of%*¦that�command�packet�are�already�set)*¦properly�for�the�particular�part�of�the)*¦particular�disc�that�was�being�accessed&*¦when�the�error�occurred.‚Here�we�set$*¦up�A3�for�autodecrement�addressing(*¦through�the�command�packet�in�the�CCB,#*¦and�then�we�clear�the�CMDCTRL�and(*¦CMDSECTS�fields�of�the�command�packet. ?‰SUBQ.Lƒ#CMDSECTS-CMDLSN,A3„Since�the�LSN�and�LUN�fields�of�the)*¦command�packet�are�already�set�properly&*¦for�the�disc�that�was�being�accessed'*¦when�the�error�occurred,�we�skip�over*¦those�fields. :‰MOVE.Bƒ#SENSECMD,-(A3)ˆPut�the�opcode�for�a�request-sense1‰BSR†SENDCMDŽcommand�into�the�opcode�field�of�the/L1‡SET†CMDOP�command�packet,�and�use�subroutine'*¦SENDCMD�to�send�the�command�packet�to!*¦the�SASI�controller.‚Subroutine$*¦SENDCMD�assumes�that�A3�is�set�for&*¦autoincrementing�through�the�command%*¦packet,�and�subroutine�SENDCMD�also'*¦assumes�that�A0�points�to�the�memory-*¦mapped�I/O�area�for�the�SASI.‰PAGE?‰MOVEQIƒSELECTED+REQREAD,D3„The�SASI�controller�should�be�ready3‰BSR.S„CHKFLAGS�to�respond�with�its�four�data�bytes5‰BNE.S„CTRLERRŽwithin�a�few�microseconds,�so�we�don't**¦return�control�to�the�system�while�we're'*¦waiting�on�the�controller's�response.)*¦Instead,�we�call�CHKFLAGS�to�wait�until**¦the�controller�is�ready.�If�the�control-**¦ler�becomes�ready�for�the�wrong�activity%*¦or�if�the�controller�doesn't�become)*¦ready�at�all�within�a�few�microseconds,(*¦CHKFLAGS�returns�control�with�the�CC.Z(*¦bit�reset�to�indicate�the�FATAL�error. &*¨The�timeout�loop�that�is�provided�by**¦CHKFLAGS�is�considerably�longer�than�the(*¦controller�actually�needs,�so�we�won't(*¦time�out�here�unless�the�controller�is)*¦really�failing.‚On�the�other�hand,�only)*¦a�small�portion�of�the�complete�timeout)*¦loop�will�ever�be�executed�under�normal**¦circumstances,�so�the�timeout�loop�won't&*¦adversely�affect�system�performance. 9‰MOVEP.L‚DATA0(A0),D2‹Read�all�four�data�bytes�into�D2�by1‰ROL.L„#8,D2�accessing�the�SASI�controller's�data5‰AND.W„#ERRBITS,D2Šregister�at�all�four�of�its�memory&*¦addresses,�and�isolate�the�bits�that"*¦define�the�actual�error�code.‚We&*¦isolate�the�error-definition�bits�in&*¦D2.W,�and�we'll�later�use�D2.W�as�an'*¦index�into�the�SASI�error-code�table. 2‰BSR†GETSTAT�Get�the�controller's�status�code,�and0‰BNE.S„CTRLERRŽdeclare�a�controller�error�if�the(*¦controller�gives�us�an�error�status�on(*¦the�request-sense�command.‚If�the�SASI$*¦controller�can't�even�respond�to�a)*¦request-sense�command�without�reporting**¦a�new�error,�something�serious�is� wrong. @‰MOVE.BƒERRCODE(PC,D2.W),D1„The�controller�has�properly�given�us'*¦a�SASI�error�code�to�define�the�exact%*¦nature�of�the�problem�that�occurred%*¦during�the�last�I/O�transaction.‚We&*¦use�that�error�code�as�an�index�into)*¦the�SASI�error-code�table,�and�we�get�a)*¦Versados�error�code�from�the�table�into&*¦D1.B.‚Once�we've�translated�the�SASI(*¦error�code�into�a�Versados�error�code,%*¦we�transfer�control�to�the�SASIDONE&*¦routine,�which�will�report�the�error*¦code�in�D1.B�to�the�user. 9‰MOVE.L„CMDOP(A5),D2ŠGet�the�sector�number�with�the�error2‰AND.L…#LSNMASK,D2‰from�the�status�packet�into�D2. ‰BRA‡SASIDONE‰PAGEO*********************************************************************************ˆSASI�ERROR-CODE�TABLE*C*ˆThis�table�translates�SASI�error�codes�into�Versados�error�codes.*O*******************************************************************************  /*ˆThe�type-0�error�codes�describe�drive�errors.  *¨----‚SASI�Error�Code.*¨|*¨|$*¨V…SASI�Definition�and�Explanation. ?ERRCODE‚DC.B…ISTACNT‡$00„No�error.‚There�are�two�possible�cases&*¦in�which�we�can�get�this�error�code. &*¦The�most�likely�case�arises�when�the(*¦SASI�controller�detects�a�parity�error!*¦in�the�command�sequence�that�we%*¦transmit�to�it.‚A�parity�error�is�a&*¦special�kind�of�error,�and�we�really'*¦shouldn't�use�a�request-sense�command(*¦following�a�parity�error.‚However,�the(*¦code�is�simpler�if�we�do,�and�the�SASI)*¦controller�reports�that�it�has�no�error(*¦in�this�case�because�a�parity�error�is&*¦not�classified�as�an�ordinary�error. $*¦The�other�case�that�generates�this'*¦error�code�can�occur�as�a�result�of�a%*¦controller�malfunction�in�which�the'*¦controller�first�reports�an�error�and*¦then�refuses�to�classify�it. '*¦We�report�a�controller�error�whenever$*¦we�get�this�error�code�because�the'*¦situation�is�serious�in�either�of�the*¦possible�cases. 2‰DC.B…ISTANRˆ$01„No�index�signal.‚Versados�doesn't'*¦really�have�an�error�code�to�describe%*¦this�situation,�so�we�simply�report*¦that�the�disc�is�not�ready. 8‰DC.B…ISTASEK‡$02„No�seek�complete.‚Since�the�seek�never$*¦completed,�we�report�a�seek�error. 4‰DC.B…ISTACRC‡$03„Write�fault�(rigid�disc�only).‚The)*¦controller�was�unable�to�write�the�data'*¦to�the�rigid�disc�correctly.‚Versados&*¦doesn't�really�have�an�error�code�to)*¦describe�this�situation,�so�we�report�a*¦CRC�data�error.‰PAGE*¨----‚SASI�Error�Code.*¨|*¨|$*¨V…SASI�Definition�and�Explanation. 7‰DC.B…ISTANRˆ$04„Drive�not�ready.‚We�report�an�error�to'*¦indicate�that�the�drive�is�not�ready. 6‰DC.B…ISTANRˆ$05„Drive�not�selected�(rigid�disc�only).'*¦Versados�doesn't�really�have�an�error(*¦code�to�describe�this�situation,�so�we&*¦report�an�error�to�indicate�that�the*¦drive�is�not�ready. 7‰DC.B…ISTAUNR‡$06„No�track�00.‚Versados�doesn't�have�an(*¦error�code�to�describe�this�situation,&*¦so�we�simply�report�an�unrecoverable*¦device�error. '*¦The�following�SASI�error�codes�aren't)*¦defined,�and�we�report�an�indeterminate&*¦channel�error�if�we�receive�an�error*¦code�that�isn't�defined. '‰DC.B…ISTAICE‡$07„Undefined�error�code.'‰DC.B…ISTAICE‡$08„Undefined�error�code.'‰DC.B…ISTAICE‡$09„Undefined�error�code.'‰DC.B…ISTAICE‡$0A„Undefined�error�code.'‰DC.B…ISTAICE‡$0B„Undefined�error�code.'‰DC.B…ISTAICE‡$0C„Undefined�error�code.'‰DC.B…ISTAICE‡$0D„Undefined�error�code.'‰DC.B…ISTAICE‡$0E„Undefined�error�code.'‰DC.B…ISTAICE‡$0F„Undefined�error�code.‰PAGE4*ˆThe�type-1�error�codes�describe�controller�errors.  *¨----‚SASI�Error�Code.*¨|*¨|$*¨V…SASI�Definition�and�Explanation. 8‰DC.B…ISTAMRK‡$10„ID�read�error.‚A�rigid�disc�had�an�ECC(*¦error�in�an�ID�field,�or�a�floppy�disc%*¦had�a�CRC�error�in�an�ID�field.‚The&*¦error�cannot�be�corrected.‚Since�the(*¦error�is�in�the�ID�field,�we�report�an%*¦address-mark�error.‚Note:‚ECC�means'*¦Error-Correcting�Code,�and�CRC�stands*¦for�Cyclical�Record�Check.  7‰DC.B…ISTACRC‡$11„An�uncorrectable�data�error�was�found&*¦during�a�read�operation.‚We�report�a*¦CRC�data�error. 6‰DC.B…ISTADME‡$12„An�ID�address�mark�was�not�found,�so(*¦the�disc�may�be�unformatted.‚We�report'*¦an�error�indicating�that�the�track�or*¦sector�ID�was�not�found. 8‰DC.B…ISTADDM‡$13„Data�address�mark�not�found.‚We�report&*¦an�error�indicating�that�a�data�mark*¦has�been�deleted. 7‰DC.B…ISTASAˆ$14„Record�not�found.‚The�correct�cylinder)*¦and�head�were�found,�but�the�sector�was'*¦not�found.‚We�report�an�error�code�to&*¦indicate�that�the�sector�address�was *¦invalid. 5‰DC.B…ISTASEK‡$15„Seek�error.‚The�read/write�head�was(*¦positioned�to�a�wrong�cylinder,�and/or(*¦a�wrong�head�was�selected.‚We�report�a *¦seek�error. 7‰DC.B…ISTATOˆ$16„DMA�data�timeout�error.‚The�controller%*¦has�reported�a�timeout�error,�so�we'*¦report�a�timeout�error�to�the�system. 4‰DC.B…ISTAWPˆ$17„Write�protected�device.‚The�user�is)*¦trying�to�write�to�a�disc�that�is�write)*¦protected,�so�we�report�a�error�to�that *¦effect.‰PAGE*¨----‚SASI�Error�Code.*¨|*¨|$*¨V…SASI�Definition�and�Explanation. 6‰DC.B…ISTACRC‡$18„Correctable�data-field�error.‚An�ECC(*¦error�occurred,�but�the�data�error�was&*¦automatically�corrected�if�automatic"*¦data�correction�wasn't�disabled. 8‰DC.B…ISTABDS‡$19„Bad�track�found.‚Versados�doesn't�have&*¦an�error�code�for�a�bad�track,�so�we&*¦report�the�code�that�indicates�a�bad *¦sector. 8‰DC.B…ISTACFG‡$1A„Format�error.‚While�the�controller�was&*¦performing�a�check-track�command,�it(*¦discovered�that�the�format�on�the�disc'*¦was�not�as�expected.‚Since�the�format&*¦of�the�disc�doesn't�match�the�format%*¦that�the�controller�thinks�the�disc&*¦should�have,�we�report�an�error�code'*¦indicating�that�the�device�configura-*¦tion�is�incorrect. '*¦The�following�SASI�error�codes�aren't)*¦defined,�and�we�report�an�indeterminate&*¦channel�error�if�we�receive�an�error*¦code�that�isn't�defined. '‰DC.B…ISTAICE‡$1B„Undefined�error�code.'‰DC.B…ISTAICE‡$1C„Undefined�error�code.'‰DC.B…ISTAICE‡$1D„Undefined�error�code.'‰DC.B…ISTAICE‡$1E„Undefined�error�code.'‰DC.B…ISTAICE‡$1F„Undefined�error�code.‰PAGE1*ˆThe�type-2�error�codes�describe�command�errors.  *¨----‚SASI�Error�Code.*¨|*¨|$*¨V…SASI�Definition�and�Explanation. 8‰DC.B…ISTAIEˆ$20„Invalid�command�received�from�the�host.'*¦Since�we�have�no�business�sending�the(*¦SASI�controller�an�invalid�command,�we'*¦report�an�error�code�to�indicate�that'*¦some�internal�I/O�error�has�occurred. 5‰DC.B…ISTAEOV‡$21„Illegal�logical�sector�address.‚The&*¦sector�address�is�beyond�the�maximum'*¦address�for�the�type�of�drive�that�is(*¦being�used.‚Someone�has�probably�given)*¦us�some�bad�configuration�parameters�to&*¦cause�this�error�to�occur.‚We�report*¦an�end-of-volume�error. 4‰DC.B…ISTAUNR‡$22„Illegal�function�for�the�specified#*¦drive.‚For�example,�a�check-track)*¦command�does�not�apply�for�floppy�discs(*¦with�IBM�track�format.‚Versados�has�no(*¦error�code�to�describe�this�situation,&*¦so�we�simply�report�an�error�code�to)*¦indicate�that�there�is�an�unrecoverable*¦error. '*¦The�following�SASI�error�codes�aren't)*¦defined,�and�we�report�an�indeterminate&*¦channel�error�if�we�receive�an�error*¦code�that�isn't�defined. '‰DC.B…ISTAICE‡$23„Undefined�error�code.'‰DC.B…ISTAICE‡$24„Undefined�error�code.'‰DC.B…ISTAICE‡$25„Undefined�error�code.'‰DC.B…ISTAICE‡$26„Undefined�error�code.'‰DC.B…ISTAICE‡$27„Undefined�error�code.'‰DC.B…ISTAICE‡$28„Undefined�error�code.'‰DC.B…ISTAICE‡$29„Undefined�error�code.'‰DC.B…ISTAICE‡$2A„Undefined�error�code.'‰DC.B…ISTAICE‡$2B„Undefined�error�code.'‰DC.B…ISTAICE‡$2C„Undefined�error�code.'‰DC.B…ISTAICE‡$2D„Undefined�error�code.'‰DC.B…ISTAICE‡$2E„Undefined�error�code.'‰DC.B…ISTAICE‡$2F„Undefined�error�code.‰PAGE7*ˆThe�type-3�error�codes�describe�miscellaneous�errors.  *¨----‚SASI�Error�Code.*¨|*¨|$*¨V…SASI�Definition�and� Explanation. 8‰DC.B…ISTAUNR‡$30„RAM�error�in�SASI�controller.‚A�memory)*¦failure�has�occurred�in�the�controller,&*¦so�we�report�an�unrecoverable�error. '*¦The�following�SASI�error�codes�aren't)*¦defined,�and�we�report�an�indeterminate&*¦channel�error�if�we�receive�an�error*¦code�that�isn't�defined. '‰DC.B…ISTAICE‡$31„Undefined�error�code.'‰DC.B…ISTAICE‡$32„Undefined�error�code.'‰DC.B…ISTAICE‡$33„Undefined�error�code.'‰DC.B…ISTAICE‡$34„Undefined�error�code.'‰DC.B…ISTAICE‡$35„Undefined�error�code.'‰DC.B…ISTAICE‡$36„Undefined�error�code.'‰DC.B…ISTAICE‡$37„Undefined�error�code.'‰DC.B…ISTAICE‡$38„Undefined�error�code.'‰DC.B…ISTAICE‡$39„Undefined�error�code.'‰DC.B…ISTAICE‡$3A„Undefined�error�code.'‰DC.B…ISTAICE‡$3B„Undefined�error�code.'‰DC.B…ISTAICE‡$3C„Undefined�error�code.'‰DC.B…ISTAICE‡$3D„Undefined�error�code.'‰DC.B…ISTAICE‡$3E„Undefined�error�code.'‰DC.B…ISTAICE‡$3F„Undefined�error�code.‰PAGEO*********************************************************************************ˆCONTROLLER-ERROR�ROUTINE*G*ˆControl�comes�to�this‚routine�when�we've�detected�a�controller�error.G*ˆWe�declare�a�controller�error�when�the�SASI�controller�does�somethingF*ˆthat�simply�cannot�be�explained‚by�any‚defined�set�of�circumstances.E*ˆWhen�a�controller�error�occurs,�we‚down�the‚SASI�channel�and�reportF*ˆa�controller�error.‚A�controller�error�is�a�serious�problem,�and�the=*ˆsystem�shouldn't�try�to�use�the�SASI�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�SASI�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:‚SASIDONE�to�terminate�processing�for�the�activity.*O******************************************************************************* 7CTRLERR1�ADDQ.Lƒ#4,SP’Control�comes�to�this�entry�point%*¦when�a�controller�error�is�detected%*¦from�within�a�subroutine.‚We�remove&*¦the�subroutine's�return�address�from(*¦the�stack,�so�the�stack�is�restored�to&*¦the�condition�that�it�had�before�the*¦subroutine�was�called. >CTRLERR‚ST.B…CHANDOWN(A5)‹Down�the�SASI�channel�by�setting�the"*¦variable�that�indicates�that�the#*¦controller�is�down.‚If�the�system(*¦tries�to�access�the�SASI�channel�again#*¦without�resetting�it�first,�we'll%*¦report�an�error�indicating�that�the$*¦channel�is�down.‚The�system�really"*¦shouldn't�try�to�access�the�SASI'*¦channel�again�without�first�resetting$*¦the�controller.‚Even�resetting�the)*¦controller�may�not�correct�the�problem,'*¦but�we'll�let�the�system�try�as�often*¦as�it�wishes. 5‰MOVEQIƒISTACNT,D1�Set�up�D1.B�for�reporting�a�status5‰BRA†SASIDONE�code�that�indicates�a�controller�error,%*¦and�go�terminate�processing�for�the!*¦current�entry�of�the�I/O�queue.‰PAGEO******************************************************************************** *ˆCHKFLAGS.AL*O******************************************************************************* GREADRDY‚MOVEQIƒSELECTED+REQREAD,D3„This�special�entry�point�is�used�for(*¦checking�the�SASI�controller�to�see�if(*¦it�has�input�data�ready�to�transfer�to(*¦us.‚We�get�the�proper�FLAGS�value�into'*¦D3.B,�and�then�control�falls�directly'*¦into�the�main�entry�point�for�subrou-*¦tine�CHKFLAGS. :*ˆControl�sometimes�falls�into�this�subroutine�from�above.  ‚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: F***********************************************************************Ä*3*ˆModified�for�both�types�of�controllers�12/12/83�**Ä*F********************************************************************** *H*‚We�need�to�set�up�a�variable�block�to�describe�a�define-format�commandD*‚sequence�that�can�be�sent�to�the�SASI�controller.‚This�needs�to�beB*‚done�ONLY�for�5�1/4"�drives.‚For�an�8"�drive�we�do�one�of�these:F*„a)�8"�FLOPPY:‚This�is�supported,�but�we�don't�need�to�set�up�for�it.7*�or�b)�8"�HARD:„This�is�NOT�supported,�so�return�.*EQ710„EQU‡CONFGBLK+IOSATW/‰BTSTW…#IOASIZE,EQ710(A1)‚Check�the�size�first. ‰IF‚‚THEN.SŽThis�is�an�8"... AEQ720†EQU…CONFGBLK+IOSATW…Since�it�is�an�8",�test�floppy�or�hard.8‹MOVE.B‚#ISTACNF,D1‰Return�error�in�D1�for�8"�hard�disk.@‹BTSTWƒ#IOARDISC,EQ720(A1)�Set��for�floppy�and��for�hard"‹RTS™disk�(and�D1�has�error�code).‰ENDI‰PAGE**‚This�is�a�5�1/4"�drive:*=‰MOVEM.LƒD0/D2/D3/A0/A3,-(A7)ƒSave�the�registers�we�will�use. *‰LEA‡DTCCMD(A5),A0‡POINT�TO�COMMAND�PACKET#‰CLR.B…DTCFLAG(A5)‰ARM�LOOP�COUNTEREQ730„EQU‡CONFGBLK+IOSATW‰BTSTW…#IOARDISC,EQ730(A1)‰BEQ.S…L0650AŽBRA�FOR�FLOPPY  **‚Must�be�a�5�1/4"�HARD�disk:*;‰MOVE.L„#$C2000000,(A0)+„INIT�TO�A�CLASS�6,OPCODE�2�COMMAND(‰MOVE.W„#0,(A0)+ŒFOR�DTC�520A�CONTROLLER STVALUE‚EQU‡$0B3C0000 3‰MOVE.L„#STVALUE,D3‰GET�STEP�VALUE�DEFAULTS�INTO�D3 EQHEADS‚EQU‡IOSHDS+CONFGBLK -‰ADD.B…EQHEADS(A1),D3†SET�#�OF�HEADS�(BYTE�4)‰SUBQ†#$1,D3Ž#�OF�HEADS�-�1**ˆB15•B0*ˆ---------------- ---------*‚D3„!…!…!…!…!*ˆ------------------------- *‹^…^…^…^*‹!…!…!…!---------(#�HEADS)�-�1"*‹!…!…!---------------$0„STEP�MODE)*‹!…!---------------------$3CƒSTEP�PERIOD2*‹!---------------------------$0BƒSTEP�PULSE�WIDTH*0*ˆTHIS�TAKES�CARE�OF�#�HEADS�AND�THE�STEP�VALUES*1‰MOVE.L„D3,(A0)+ŒMOVE�DATA�TO�RAM�(1ST�LONG�WORD)*EQTRK„EQU‡IOSTRK+CONFGBLK *‰MOVE.W„EQTRK(A1),D3ˆGET�TOTAL�#�CYLINDERS#‰MOVE.W„D3,D2�SAVE�LOWER�WORD�IN�D2$‰AND.L…#$0000FFFF,D3‡MASK�UPPER�WORD(‰SWAP†D3’TOTAL�#�CYLINDERS�IN�UPPER�WORD,‰LSL.W…#7,D2�DIVIDE�BY�2�AND�PLACE�IN�BYTE�2‰ADD.W…D2,D3�MOVE�IT�INTO�D3%‰AND.B…#0,D3�MAKE�SURE�LAST�BYTE�IS�0‰PAGE**ˆB15•B0*ˆ-------------------------*‚D3„!…!…!…!…!*ˆ------------------------- *‹^…^…^…^&*‹!…!…!…!---------SET�TO�0ˆ(TYPE/SEEK)0*‹!…!…!---------------(#�CYLINDERS)/2�(PRE-COMP)/*‹!…!---------------------#�CYLINDERS…(LO�BYTE)3*‹!---------------------------#�CYLINDERS…(HI�BYTE)*0*ˆTHIS�TAKES�CARE�OF�#�CYLINDERS�&�PRECOMP�VALUE*‰MOVE.L„D3,(A0)+ŒSAVE�IN�MEMORY ‰MOVE.W„#0,D3�GET�0,‰MOVE.W„D3,(A0)+ŒCLEAR�LAST�2�BYTES�OF�BLOCK 1‰LEA‡DTCCMD(A5),A0‡GET�POINTER�TO�PARAMETER�BLOCK*‰MOVE.L„DCBPNTR(A1),A3†A3�<--�DCB�address.#‰MOVE.B„DCBCDV(A3),D3‡GET�LUN�FIELD‰LSL.B…#5,D3�SHIFT�LUN�FIELD-‰MOVE.B„D3,1(A0)ŒPLACE�LUN�IN�PARAMETER�BLOCK‰BRA.S…SETCNFG_EXIT  **‚Must�be�a�5�1/4"�FLOPPY�disk:*7L0650AƒMOVE.L„#$C0000000,(A0)+„CLASS�6,OPCODE�0�COMMAND‰MOVE.W„#0,(A0)+ŒINTO�DTCCMD 0STVAL1ƒEQU‡$17060015‹FOR�MICROPOLIS�1115-6�DRIVE !‰MOVE.L„#STVAL1,D0ŠSET�UP�DTCDATA **ˆB15•B0*ˆ-------------------------*‚D0„!…!…!…!…!*ˆ------------------------- *‹^…^…^…^'*‹!…!…!…!---------HEAD�SETTLE�TIME�15mS8*‹!…!…!---------------MAX�CYLINDER�ADDRESS�SET�TO�0�HERE,*‹!…!---------------------STEP�INTERVAL„6�mS4*‹!---------------------------STEP�PULSE�WIDTH�17�uS*4*ˆTHIS�TAKES�CARE�OF�#�CYLINDERS�&�TIMING�PARAMETERS*‰PAGE'‰MOVE.W„EQTRK(A1),D3ˆGET�#�OF�CYLINDERS-‰AND.L…#$FFFF00FF,D0‡MAKE�SURE�FIELD�IS�CLEAR-‰AND.L…#$0000FFFF,D3‡MAKE�SURE�FIELD�IS�CLEAR‰LSL.W…#8,D3�PUT�#�IN�BYTE�1(‰ADD.L…D3,D0�PUT�IN�MAX�CYLINDER�ADDRESS‰MOVE.L„D0,(A0)+ŒPUT�IN�DTCDATA 0STVAL2ƒEQU‡$CD000B80‹FOR�MICROPOLIS�1115-6�DRIVE-‰MOVE.L„#STVAL2,(A0)+‡NO�MODIFICATIONS�PASSED **ˆB15•B0*ˆ-------------------------*‚D0„!…!…!…!…!*ˆ------------------------- *‹^…^…^…^(*‹!…!…!…!---------DRIVE�IDENTIFIER�-�$803*‹!…!…!---------------DELAY�AFTER�WRITE�DE-ASSERTED7*‹!…!---------------------VALID�DATA�AFTER�DRIVE�SELECT:*‹!---------------------------VALID�DATA�AFTER�HEAD�SELECT*0*ˆTHIS�TAKES�CARE�OF�ADDTIONAL�TIMING�PARAMETERS* -‰MOVE.W„#0,(A0)+ŒLAST�2�BYTES�0�BY�DEFINITION6‰LEA‡DTCCMD(A5),A0‡NOW�GO�BACK�AND�FIX�DENSITY�&�SIDES BYTE5„EQU‡5“LAST�BYTE�IN�DTCCMD!EQCNFGƒEQU‡IOSATW+CONFGBLK…IOSATW*‰MOVE.B„BYTE5(A0),D0ˆGET�FIELD�IN�QUESTION ‰MOVE.W„EQCNFG(A1),D3‡GET�IOSATW+‰BTST†#IOATDEN,D3‰SINGLE�OR�DOUBLE�DENSITY?‰BEQ.S…MOD1�BRA�IF�SINGLE%‰OR.B†#6,D0�THESE�BITS�ARE�SET�FOR�2D-MOD1…BTST†#IOADSIDE,D3ˆSINGLE�OR�DOUBLE�SIDED‰BEQ.S…MOD2�BRA�IF�SINGLE‰OR.B†#1,D0�THIS�BIT�SET�FOR�2S&MOD2…MOVE.B„D0,BYTE5(A0)ˆREPLACE�FIELD #‰MOVE.B„DCBCDV(A3),D3‡GET�LUN�FIELD‰LSL.B…#5,D3�SHIFT�LUN�FIELD(‰MOVE.B„D3,1(A0)ŒPLACE�LUN�IN�DATA�FIELD *%*‚Common�exit�point�for�5�1/4"�drive:7*‚Return��since�the�controller�supports�the�command* SETCNFG_EXIT: (‰MOVE.B„#0,D0’Set�good�status�on�return.<‰MOVEM.Lƒ(A7)+,D0/D2/D3/A0/A3ƒRestore�the�registers�we�used.‰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: 4‰MOVEM.LƒD0/D4,-(A7)‰Save�any�registers�we�will�use. K****************************************************************************0*ƒModified�for�the�1403ES�controller�1/10/84ƒBWN**ƒTrack�format�byte:*!*ˆ00ˆSingle�density,�single�sided *ˆ01ˆSingle�density,double�sided *ˆ06ˆDouble�density,single�sided *ˆ07ˆDouble�density,double�sided**‰PAGE.‰MOVEQ…#0,D4�This�register�will�hold�CTRLCODE. *5*‚The�CTRLCODE�needs�to�be�set�up�only�for�8"�floppy,1*‚and�we�are�doing�a�CONFIG�command.‚In�all�other*‚cases�it�is�set�to�zero.*‰CMP.B…#CNFGFUNC,IOFUNCT(A1)+‰IF‚‚THEN.SŽThis�is�a�CONFIG�command... EQ652†EQU‡CONFGBLK+IOSATW5‹MOVE.W„EQ652(A1),D0†Get�the�attributes�word�into�D0. ‹BTSTW…#IOASIZE,D0&‹IF‚‚THEN.SŒThis�is�an�8"�drive... �BTSTW…#IOARDISC,D0#�IF‚‚THEN.SŠand�it�is�a�floppy. "�BTST†#IOADDEN,D0ƒDouble�density�?�IF‚‚THEN.SˆIf�so,#‘BSET„#CMDDDEN,D4ƒset�bits�1�and�2.‘BSET„#CMDDDEN2,D4�ENDI �BTST†#IOADSIDE,D0‚Double�sided?�IF‚‚THEN.S$‘BSET„#CMDDSIDE,D4‚If�so,�set�bit�0.�ENDI �ENDI ‹ENDI ‰ENDI 0‰MOVE.B„D4,CTRLCODE(A1)…Set�up�the�control�code. 3‰MOVEM.Lƒ(A7)+,D0/D4‰Restore�the�registers�we�used.‰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*******************************************************************************/*‚Tables�used�to�check�the�floppy�configurationJ*‚The�RWIN�and�SASI�controllers�agree�on�their�values�for�128�byte�sectorsN*‚and�256�byte�sector.�However�there�is�a�difference�on�the�1024�byte�sectors,E*‚and�a�difference�in�what�is�supported�by�the�different�controllers.J*‚For�now,�with�only�128�or�256�bytes�sectors,�there�is�no�difference,�and*‚we�can�use�the�same�tables.**$*ƒBYTES�PER�SECTOR�--�SINGLE�DENSITY*-BPS_S„DC.W†128Š128�bytes,�single�data�density,‰DC.W†0Œwe�do�not�support�256�single�density,‰DC.W†0Œwe�do�not�support�512�single�density-‰DC.W†0Œwe�do�not�support�1024�single�density*$*ƒBYTES�PER�SECTOR�--�DOUBLE�DENSITY*5BPS_D„DC.W†0ŒSASI�does�not�support�128�double�density(‰DC.W†256Š256�bytes,�double�data�density,‰DC.W†0Œwe�do�not�support�512�double�density-‰DC.W†0Œwe�do�not�support�1024�double�density‰PAGEƒTHEN.SŒIf�double�density,�move�pntr�to*ŽADDQ.Lƒ#BPS_DENS,A2„double�density�table.‰ENDI***6‰MOVE.W„IOSPSM-IOSDRSV(A0),D6‰D6�<---�bytes�per�sector 0‰MOVE.W�#C_TBL_SZ-1,D7�Search�for�match�in�bytes)BPS_LOOP�CMP.Wƒ(A2)+,D6’per�sector�table.‰DBEQ„D7,BPS_LOOP.‰BNE.SƒRET“If�no�match,�return�with�CCR�=�*'*‚We�are�here�because�we�found�a�match.* BPS_FOUND4‰LEA‡SPT5_S(PC),A2‡A2�<---‚pntr�to�sector�per�track,#*¦5",�single�density�table.(SPT5_S)1‰BTSTW…#IOADDEN,D4‰If�double�density,�point�A2�to-‰IFƒƒTHEN.SŒsectors�per�track,�5",�double,ŽADDQ.Lƒ#SPT_DDEN,A2„density�table.�(SPT5_D)‰ENDI.‰BTSTW…#IOASIZE,D4‰If�8"�diskette,�point�A2�to0‰IFƒƒTHEN.SŒthe�sectors�per�track,�8"�table,4ŽADDQ.Lƒ#SPT_SIZE,A2„either�single�or�double�density*‰ENDIšas�fixed�up�above.(SPT8_D�or�SPT8_S)*D*ƒNow�that�A2�is�pointing�to�the�proper�table�for�sectors�per�track,G*ƒset�up�D4�to�point�to�the�byte�offset�of�our�entry�from�the�beginning=*ƒof�the�proper�table,�and�let's�check�the�sectors�per�track.*‰MOVE.W„#C_TBL_SZ-1,D3 ‰SUB.W…D7,D37‰MOVE.B„IOSSPT-IOSDRSV(A0),D2‰D2�<---�sectors�per�track‰CMP.B…0(A2,D3.W),D2ARET†MOVEM.Lƒ(A7)+,D2/D3/D4/D6/D7/A2ƒReturn�with�CCR=�if�match‰RTS›found�and��otherwise.‰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: :‰CMP.L„#LSNMASK+1,D2ŠSince�the�first�logical�sector�on�the)*¦disk�is�logical�sector�zero,�the�number(*¦of�the�last�logical�sector�on�the�disk&*¦is�D2-1.‚If�this�number�is�too�large)*¦to�fit�under�the�LSN�mask,�something�is'*¦wrong.‚We�can't�have�a�logical�sector(*¦number�that�is�larger�than�the�largest(*¦sector�number�that�the�SASI�controller *¦supports.‰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*™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****************************************************************************** *F*‚This�function�is�not�required�by�the�SASI�driver.‚The�command�packet8*‚is�built�with�the�interrupts�masked�in�the�co-routine.* BLD_PACKET: ‰CMP.B…D0,D0‰RTS‰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:�SASIINT**ˆ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;EQ670„EQU†IOQUEUE-IOQCNT‡queue�entry,�and�advance�the�queue=‰MOVE.LƒA1,EQ670(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�we1‰BNE.S„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�tell�the�interrupt�handler�to�start<‰MOVE.LƒCCBCHB(A5),A0ˆprocessing�a�new�I/O�queue�entry.‚Then4‰BSR†SASIINTŽpoint�A0�to�the�MVME420's�memory-mapped"*¦I/O�area,�and�activate�interrupt%*¦processing�by�calling�the�interrupt#*¦handler�once�as�a�subroutine.‚The%*¦machine's�interrupt�level�is�at�the)*¦same�level�that�would�be�present�during#*¦an�actual�interrupt�from�the�SASI(*¦channel,�so�the�interrupt�handler�will(*¦perform�correctly.‚We�need�to�call�the(*¦interrupt�handler�once�as�a�subroutine%*¦to�activate�interrupt�processing�if&*¦interrupt�processing�isn't�currently *¦active. *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‡6‰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‚th is�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.N******************************************************************************* *‰END�ROUTINES�CALLED�BY�DISKLIB*N******************************************************************************Š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.*A*‰1.‚Resets�both�the�SA1403D�SASI�controller�and�the�MVME420�SASI*�Peripheral�Adapter.2*‰2.‚Tests�the�MVME420�to�see�if�it�is�functional.**‰Entry:�A5�=�address�of�CCB.**‰Registers�may�be�used�freely.* *‰Calls:�none*N****************************************************************************** DO_INIT: **‚Reset�the�controller*5‰MOVE.LƒCCBCHB(A5),A4ŠGet�the�physical�address�of�the:‰LEA†DIAGNOST(A4),A3†channel's�memory-mapped�I/O�area�into"*¦A4,�and�set�up�A3�to�address�the$*¦MVME420's�DIAGNOST�register.‚We'll&*¦access�the�DIAGNOST�register�several'*¦times,�so�it's�worthwhile�to�dedicate%*¦an�address�register�to�point�to�it. ?‰MOVE.Bƒ#RESET,CONTROL(A4)…Reset�the�MVME420�and�the�SA1403D�by(*¦setting�the�RESET�bit�in�the�MVME420's#*¦CONTROL�register.‚In�one�case�the'*¦MVME420�and�the�SA1403D�may�have�just&*¦been�reset�by�the�automatic�power-up)*¦reset,�but�resetting�them�again�in�that&*¦one�case�does�no�harm.‚Resetting�the&*¦MVME420�illuminates�its�fail�LED�and$*¦also�disables�its�interrupt.‚We'll&*¦extinguish�the�fail�LED�later�if�the)*¦MVME420�passes�the�tests�we're�about�to(*¦perform,�but�we'll�leave�the�interrupt&*¦disabled�until�we�want�an�interrupt. **‚Test�the�controller*3‰MOVEQIƒ$55,D0‘Write�a�distinctive�bit�pattern�into4‰MOVE.BƒD0,(A3)Žthe�MVME420's�DIAGNOST�register,�and5‰CMP.B„(A3),D0Žset�the�CHANDOWN�flag�if�we�can't�read5‰SNE.B„CHANDOWN(A5)‰back�the�same�bit�pattern�that�we%*¦wrote.‚If�we�read�back�the�same�bit$*¦pattern�that�we�wrote,�however,�we%*¦clear�the�CHANDOWN�flag�to�indicate"*¦that�(so�far,�at�least)�the�SASI*¦channel�is�not�down. .‰NOT.B„D0•Invert�the�bit�pattern�that�we�wrote1‰NOT.B„(A3)‘to�the�DIAGNOST�register�earlier,�and.‰SUB.B„(A3),D0Žcheck�to�see�if�the�pattern�was:‰OR.B…D0,CHANDOWN(A5)†inverted�properly.‚If�it�wasn't,�set(*¦the�CHANDOWN�flag�to�indicate�that�the"*¦SASI�channel�is�definitely�down. 0‰BNE.S„L0020’If�the�MVME420�failed�either�of�the$*¦tests�above,�return�to�the�calling&*¦routine�and�leave�the�MVME420's�fail$*¦LED�illuminated.‚The�tests�that�we(*¦perform�on�the�MVME420�certainly�don't&*¦comprise�a�comprehensive�checkout�by)*¦any�means,�but�they'll�probably�catch�a'*¦surprising�number�of�problems.‚In�any(*¦case,�the�checks�that�we�make�are�con-)*¦siderably�better�than�no�checks�at�all. ?EQ460„EQU†LEDOFF+DSABLINTˆThe�MVME420�passed�our�cursory�tests,?‰MOVE.Bƒ#EQ460,CONTROL(A4)ƒso�extinguish�its�fail�LED,�but�keep&*¦its�interrupt�disabled.‚The�fail�LED'*¦was�automatically�illuminated�when�we%*¦reset�the�MVME420,�and�the�f ail�LED'*¦remained�lit�until�now.‚The�MVME420's&*¦interrupt�was�automatically�disabled&*¦by�our�earlier�reset�command,�and�we%*¦want�to�keep�the�interrupt�disabled$*¦until�we�have�a�specific�reason�to *¦enable�it. L0020„RTS *********************** *‚PATCH�SPACE***********************ŠDS.Wƒ30ŠENDNN‰PAGE/************************************************ *ˆM435DRV.SA*/***********************************************‰OPT‡CRE‰OPT‡PCS‰OPT‡BRS-M435DRV‚IDNT†45,0†MAG�TAPE�driver�for�MVME435)‰TTL‡M435DRV:‚MAG�TAPE�driver�for�MVME435‰PAGE$TRACE„SET�'OFF'‰Tracer�for�debuggingG*************************************************************************ˆMAGTAPE.COMMENTS.SA*G************************************************************************1*ˆDRIVER�FOR�MAG�TAPE�USING�MVME435�ADAPTER�BOARD*G**************************************************************************ˆREVISION�HISTORY***ˆ9/9/83„Written�by�B.W.N.,*ˆ9/28/83ƒImplementing�direct�mode�for�reads-*ˆ11/30/83‚Fixes‚to�prevent�tape�from�running*’off�the�end�of�the�reel.;*ˆ12/1/83ƒDelay�added�for�slow�transport�in�checking�ready.'*ˆ3/9/84„Cleaned�up‚comments�in�WAKEUP.:*ˆ3/13/84ƒFixed�TIMEFLAG(A1)�--->‚TIMEFLAG(A5)‚in�FINDDENS#*’(should�have�been�offset�from�A5)%*ˆ4/4/84„New�board�with�enhancements:4*’(1)�Can�disable�and�enable�interrupts�at�the�board+*–level�by�writing�into�the�DSCMD�register.***–Use�new�macros,�ENABLMTA�and�INHIBMTA�to'*–turn�the�board�interrupt�on�in�INTRTN0*–and�to�turn�the�board�interrupt�off�when�about*–to�give�a�command.*1*–Replace�INHIB�which�masks�all�interrupts�at�the1*–whole�interrupt�level�with�INHIBMTA,�which�only"*–affects�interrupts�at�the�board.*4*–The�only�exception�is�when�we�are�messing�with�the-*–IOQUEUE�in�the�command�handler�and�MTADONE.*–Why�is�that,�you�ask?3*–I�hope�to�find�out�why�the�SASI�does�it�this�way.*6*’(2)�After�reading�a�hard�error,�a�read�of�the�status2*–register�will�clear�the�interrupt�so�there�is�no*–need�to�stop�the�tape.1*–For�testing�purposes,�for�now,�if�the�interrupt1*–does�not�go�away,�in�one�read,�we�will�stop�the*–tape�as�before.*4*’(3)�An�interrupt�is�generated�when�DNBSY�gets�set.1*–Bit�1�in�the�STAT2�register�can�now�mean�one�of'*–3�things:�DNBSY,FNBSY,�and�file�mark.ÅÌ?Õ4Ý.å6í:õ\ýa: 9H7%=-95H=EE;M;UC]6e:m9uZ}J…O�6•=�>¥I­KµK1*–For�a�DNBSY�we�just�continue�as�if�no�interrupt*–of�that�type�were�received.**ˆ4/12/84ƒBug�fix:4*’A1�was�not�getting�set�up�properly�for�a�branch�to*’PROCQUE�from�MTADONE.6*’Now�we�put�the�address�of�the�drive's�variable�block*’into�A1�before�we�branch.*.*’End�of�tape�handling�was�not�right�in�MTINT.*’Eliminated�a�BRA‚MTINT3.*.*’Check�for�end�of�tape�on�forward�command�and6*’beginning�of�tape�on�reversa�command�was�not�correct*’in�PROCQUE�(STAT1�vs.�STAT2)*A*ˆ5/4/84„Sometimes�when�a�blank�tape�is�mounted�on�the�transport,2*’we�decide�erroneously�that�the�transport�density *’cannot�be�changed�in�software.3*’Don't�know�at�this�point�why�this�seems�to�occur,/*’possibly�something�to�do�with�the�transport�?.*’Anyway,� don't�want�to�lock�out�the�user�from0*’selecting�a�transport�density�for�a�write�from.*’loadpoint,�so�change�the�logic�in�SELECT2�to*’ignore�the�CNGDENS�flag.*4*’Use�BRanch�short�wherever�possible�and�add�a�patch*’area�at�the�end.*8*ˆ4/7/84„Replace�SELECT2�calls�with�SELECT�calls.‚Modify *’SELECT.*5*ˆ5/22/84ƒRewrite�the�DOWRITE�routine�using�WHILE-DO.2*’Add�a�periodic�activation�call�to�timeout�in�the5*’driver�if�DOREAD�takes�too�long.‚We�do�this�because6*’IOS�sends�us�a�timeout�for�the�IOSRTO�value�and�this9*’must�make�do�for�not�only�read,�but�rewind,�search,�and:*’everything�but�write.�We�want�a�short�read�timeout�but�a1*’long�rewind�timeout�so�we�must�do�it�ourselves.4*’This�requires�changes�to�the�9995..IOE.EQ�file�and*’a�new�sysgen�to�test.*<*ˆ6/15/84ƒIf�user�asks�for�a�timeout�with�a�0�interval,�just*’treat�as�no�timeout.:*’After�a�command�has�completed,�inhibit�interrupts�at�the8*’board�and�enable�interrupts�at�the�system�level�(lower0*’mask�by�1)�so�that�we�don't�tie�up�the�system.*<*ˆ9/18/84ƒFound�a�problem�while�testing�on�VM03.‚Continually3*’getting�timed�out�during�reads.‚Timing�dependent.3*’The�problem�was�I�was�reading�STAT1�a�second�time4*’in�the�interrupt�service�routine,�and�there�was�an<*’interrupt�pending�that�got�cleared�but�was�never�serviced.*5*’It�is�possible�for�the�following�sequence�to�occur:8*’HALFFULL�interrupt�occurs,�Read�STAT2,‚FNBSY�interrupt4*’occurs,�read�STAT1.‚In�this�case�we�will�not�get�a*’FNBSY�interrupt.8*’Therefore�when�it�is�time�to�check�for�FNBSY,�read�the6*’bit�4�in�STAT1�to�decide�if�it�is�a�FNBSY�instead�of*’the�bit�1�in�STAT2.*’Changes�made�in�MTINT.*;*ˆ12/04/84‚On�tape�drives�running�at�100�ips�on�the�VME/10,5*’the�READ2K�routine�was�not�getting�bytes�out�of�the0*’FIFO�fast�enough.‚Speeded�up�the�primary�loop.1*’This�reduced�the�time�between�4�byte�reads�from4*’25.6�micro�seconds�to�about�11�microseconds,�which*’did�the�trick.*7*’On�tape�drives�that�do�not�conform�to�the�PERTEC�spec6*’for�which�the�MVME435�board�was�designed,�reading�in,*’direct�mode�corrupted�bytes�on�the�VME/10.4*’As�a�work�around,�the�driver�now�reads�in�buffered4*’mode�when�the�user�specifies�a�buffer�size�of�40962*’bytes�or�less.‚I'm�not�sure�why,�but�on�the�tape4*’drives�I�used�for�testing,�there�will�be�more�than6*’4096�bytes�read�from�the�MVME435�when�the�tape�block7*’size�is�larger�than�4096,�even�when�we�are�reading�in-*’buffered�mode.‚This�is�a�good�feature,�as�a2*’buffer�overflow�message�will�alert�the�user�that6*’the�block�size�on�the�tape�is�indeed�larger�than�his;*’4096�byte�buffer.�But�mostly�we�expect�the�user�knows�the%*’size�of�the�tape�blocks�being�read.*=*ˆ12/7/84ƒWhen�a�user�asks�for�0�read�tries�or�0�write�tries,&*’the�driver�should�change�the�0�to�1.9*’That�was�not�being�done�in�the�right�place�in�CONFGCOM.=*ˆ11/12/85‚In�line�3903�and�8176�removed�the�comment�(*)�from*’SF.B�TIMEFLAG�in�both�places.5*’In�routine�CKRDY�added�BRA�MTINT3�after�return�from*’BSR.L�INTRTN6*’Modifications�to�HALT�I/O�logic�to�return�the�corret*’error�status.2*’In�routine�STOPTAPE�added�an�ENABLMTA�macro�call*7*ˆ12/11/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*ˆ01/27/86‚-Fixed�bug�in�READ2K�MOVE.L�#HAFBUF,D2....was*§MOVE.W�#HAFBUF,D23*’-�Changed�the�check�for�less�than�2048�bytes�from2*”�to��allowing�the�write2k�to�execute�for*”any�buffer�length�of�2048.9*’-�Fixed�a�problem�of�the�driver�not�detecting�a�pending6*”interrupt�that�occurrs�while�the�driver�is�masked�at6*”interrupt�level.�This�causes�buss�errors�if�the�tape6*”drive�was�not�fast�enough�to�read�data�from�the�FIFO2*”as�the�driver�was�in�writing�data�into�the�FIFO.I**************************************************************************(*ˆMODULES�CALLED�IN�THE�MAG�TAPE�DRIVER:*H*--------------------ƒINITIALIZATIONƒ-----------------------------------*<*�INITIAL‚ EQU‡*‡Initializes�the�device�dependent�part�of�CCB$*œInitializes�MVME435�and�tape�drive*K*--------------------------------------------------------------------------*H*--------------------ƒCOMMAND�SERVICE‚----------------------------------**6*�COMMANDS�EQU‡*‡Dispatches�commands�received�from�CMR**�STATCMD‚EQU‡*‡Status�command.*�STATCONF�EQU‡*‡Updates�first�4�bytes�of�IOCB!*�DFCONFG‚EQU‡*‡Default�configure*�CONFG„EQU‡*‡Configure�command5*�CONFGCOM�EQU‡*‡Executes�common�configuration�chores**?*�CONERROR�EQU‡*‡Error�exit�for�configure�and�default�configure*1*�RDWRTCMD�EQU‡*‡Entry�for�read�and�write�command@*�COMMCMD‚EQU‡*‡Entry�for�I/O�commands�other�than�read,write,�or*œconfigure�&�mount2*�CONFG2ƒEQU‡*‡Entry�point�for�configure�and�mount *�HALTCMD‚EQU‡*‡Halt�I/O�command2*�LOGPHYƒEQU‡*‡Convert�logical�to�physical�address***�HALTEXIT�EQU‡*‡Exit�for�halt�I/O�command$*�CMDEXIT‚EQU‡*‡Commands�common�exit;*�CMDEXIT1“Entry�point�for�commands�completed�without�error>*�CMDEXIT2�EQU‡*‡Entry�point�for�commands�completed�with�error9*�CMDEXIT3�EQU‡*‡Entry�point�for�commands�to�be�completed*œunder�interrupt�control*%*�QEVENTT”Queues�I/O�completion�event* *�EXECREQ‚EQU‡*‡Does�trap�0�call *�KILL_IT‚EQU‡*‡Kills�the�system*&*�CMDSWIT‚EQU‡*‡Table�used�in�COMMANDS'*�CONFGLEN�EQU‡*‡Table�used�in�CONFGCOM*K*--------------------------------------------------------------------------*F*-------------------„INTERRUPT�SERVICEƒ-------------------------------*%*�INTERUPT�EQU‡*‡Interprets�interrupt+*�MTINT„EQU‡*‡Dispatches�mag�tape�interrupt***�PROCQUE‚EQU‡*‡Processes�next�queue�entry'*�SELECTƒEQU‡*‡Selects�proper�transport-*œRe-selects�transport�with�requested�density*œfor�write�from�loadpoint**�DOWRITE‚EQU‡*‡Write�to�tape<*�WRITE2K”Transfer�2K�bytes�from�FIFO�to�memory(direct�mode)3*�WRITDATA�EQU‡*‡Transfer�bytes�from�FIFO�to�memory*>*�DOCONFG‚EQU‡*‡Do�the�configure�and�mount�(interrupt�control)&*�FINDDENS�EQU‡*‡Find�the�tape�density1*�SET_TIME“Do�trap�0�call�for�periodic�activation*œduring�FINDDENS�command.2*�WAKEUP•Routine�that�is�activated�during�periodic'*œactivation�wakeup�call�from�FINDDENS.;*�WAKEUP2”Routine�for�wakeup�calls�from�DOREAD,SPACE,�ERASE*œSEARCH,�and�DOREWIND*+*�DORDFWD‚EQU‡*‡Do�the�read�forward�command.*�READ2K•Transfer�2K�bytes�from�FIFO�to�memory*ž(direct�mode)3*�READDATA�EQU‡*‡Transfer�bytes�from‚FIFO�to�memory+*žbuffered�mode/end�of�block�in�direct�mode*;*�STOPTAPE“After�reset�formatter�command,�wait�for�the�tape2*žto�stop,�clear�the�formatter�not�busy�interrupt.**&*�DOREWIND�EQU‡*‡Do�the�rewind�command*;*�DOSFMFWD�EQU‡*‡Do�the�search�forward�for�filemark�command;*�DOSFMREV�EQU‡*‡Do�the�search�reverse�for�filemark�command+*�SEARCH•Common�routine�for�search�filemark*,*�DOSPFWD�EQU‡*ˆDo�the�space�forward�command,*�DOSPREV�EQU‡*ˆDo�the�space�reverse�command2*�SPACE–Common�routine�for�space�forward�&�reverse*-*�DOWRTFM‚EQU‡*‡Do�the�write�filemark�command$*�DOERASE‚EQU‡*‡Do�the�erase�command:*�FM_ERAS_COMM�Common�routine�for�erase�and�write�filemark*;*�MTADONE‚EQU‡*‡Complete�command�processing�under�interrupt *œcontrol%*�QEVENTI”Queues�I/O�completion�event*3*�CKRDY–See�if�the�transport�is�ready.�If�not�ready,*œimmediately,�delay�for�a�while�until�it�is*œor�we�have�run�out�of�time.*#*�IDLELOOP�EQU‡*‡Wait�for�a�command*%*�OPTABLE‚EQU‡*‡Table�used�in�PROCQUE*�TRTABLE”Table�used�in�SELECT*I*------------------------------------------------------------------------F**********************************************************************‰PAGEI***************************************************************************ˆMAGTAPE.MACROS.SA*J*************************************************************************** *ˆMacros�for�the�mag�tape�driver*J******************************************************************************A*<<<<<<<<<<<<<<<<<< COMMENTED OUT 12/2/8  3 >>>>>>>>>>>>>>>>>>>>>>>*<*ˆIt�was�discovered�that�getting�ready�takes�some�transports:*ˆlonger�than�others,�so�we�needed�a�timeout�to�test�ready(*ˆafter�a�delay�of�several�milliseconds. *ˆA�subroutine�does�the�job�now.****ƒCKRDY„MACRO**?*ˆPut�the�not�ready�error�code�into�D1,�and�check�the�ready�bit=*ˆof�the�STAT1�register.‚If�the�transport�is�not�ready,�go�to *ˆMTADONE.*****†MOVE.B„#ISTANR,D1***†BTST†#READYB,STAT1(A0)***†BEQ.S‡MTADONE***†ENDM*** CKEOT„MACRO**<*ˆPut�the�end�of�volume�(end�of�tape)�error�code�into�D1�and2*ˆcheck�the�end�of�tape�bit�of�the�STAT1�register.**ˆIf�we�are�at�end�of�tape,�go�to�MTADONE.**‰MOVE.B„#ISTAEOV,D1‰BTST†#EOTB,STAT1(A0)‰BNE.L…MTADONE‰ENDM*** INHIB„MACRO**"*ˆInhibit�interrupts�at�our�level.**‰MOVE.W„CCBISR(A5),SR‰ENDM7*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *ˆbwn‡4/4/84*INHIBMTA MACRO*"*ˆInhibit�interrupts�at�the�board.**‰MOVE.B„#DISABLCD,DSCMD(A0)‰ENDM*/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%* ENABL„MACRO**2*ˆEnable�interrupts�by�lowering�mask�by�one�level.**‰MOVE.W„CCBSR(A5),SR‰ENDM*D*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *ˆbwn‡4/4/84*'*ˆEnable�interrupts�at�the�board�level.**ENABLMTA MACRO**‰MOVE.B„#ENABLECD,DSCMD(A0)‰ENDM**F*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%**8*ˆCheck�filemark�and�if�a�filemark�was�detected,�put�the)*ˆISTAEOF�message�in�D1�and�go�to�MTADONE** CKFM…MACRO‰MOVE.B„#ISTAEOF,D1‰TST.B…SAVEFM(A1)‰BNE.L‡MTADONE‰ENDM***8*ˆCheck�for�beginning�of�tape�and�if�so,�put�the�ISTABOV!*ˆmessage�in�D1�and�go�to�MTADONE** CKBOT„MACRO‰MOVE.B„#ISTABOV,D1‰BTST†#LDPNTB,STAT1(A0)‰BNE.L‡MTADONE‰ENDM**6*ˆCKTRDEN�macro�updates�the�current�transport�density.8*ˆIt�requires�that�A0�=�address�of�memory-mapped�IO�area-*ˆand�A1�=�address�of�drive's�variable�block.** CKTRDEN‚MACRO‰TST.B…STAT1(A0)‰IFˆ†THEN.S“MOVE.B„#XDSD800,TRANDENS(A1)‰ELSE.S“MOVE.B„#XDSD1600,TRANDENS(A1)‰ENDI‰ENDM * *ˆTRACE�macro�used�for�debuggingH*ˆIf�the�TRACE�is�'ON',�then�whenever�the�macro�TRACE�XX�is�encountered,7*ˆthe�characters�'XX'�will�be�put�into�the�trace�table.*ˆCall:ƒTRACE�R1,RTR8*�This�will�put�the�characters�'R1'�into�the�trace�table6*�that�starts�at�RTR_TABLE�and�is�indexed�by�RTR_INDEX*�and�has�length�RTR_LEN.* TRACE„MACRO‰IFEQ†TRACE-'ON'�MOVE.W…D0,-(SP)�MOVE.W…#\2_TABLE,D0�ADDƒ\2_INDEX(A5),D0�MOVE‚#'\1',(A5,D0)�ADD.W�#2,\2_INDEX(A5)"�IF„\2_INDEX(A5)‚‚#\2_LENƒTHEN“CLR„\2_INDEX(A5)�ENDI�MOVE.W…(SP)+,D0‰ENDC‰ENDM *@*ˆThe�CLR_TR�macro�is�used�to�clear�the�trace�table�of�interest.*ˆCall:�CLR_TRƒRTR3*ŽThis�clears�the�RTR„table�from�offset�0�to�offset *ŽRTR_LEN-1.* CLR_TRƒMACRO‰IFEQ†TRACE-'ON'�MOVEM.L‰D4/A3,-(SP)�LEAƒ\1_TABLE(A5),A3�FORƒD4=#1‚TO‚#\1_LENƒDO “CLR.B…(A3)+�ENDF�CLRƒ\1_INDEX(A5)�MOVEM.L‰(SP)+,D4/A3‰ENDC‰ENDM G************************************************************************Í*'*ˆFrom�the�SASI�driver�by�David�Pheanis*C*******************************************************************  2LONGWORD�MACRO›This�macro�skips�zero�or�more�bytes'*¦in�memory�(if�necessary)�to�align�the)*¦assembler's�location�counter�to�a�long-&*¦word�boundary.‚We�define�a�long-word)*¦boundary�to�be�a�location�whose�address*¦is�evenly�divisible�by�4. ,‰DS.W…0–First,�align�the�location�counter�to"*¦a�word�boundary.‚If�the�location(*¦counter�is�already�on�a�word�boundary,*¦we�don't�change�it. 0‰IFNE…*/4*4-*�If�the�location�counter�isn't�on�a-‰DS.W…1”long-word�boundary,�advance�it�by�one-‰ENDCšword�to�put�it�on�a�long-word�boundary. ‰ENDM-‰PAGEš#######################################1MOVEIAƒMACRO›This�macro�is�u  seful�when�we�want�to%*¦put�an�immediate�value�into�an�"*¦register.‚If�the�immediate�value"*¦happens�to�be�small�enough�to�be#*¦represented�correctly�in�a�16-bit&*¦two's-complement�number�system,�this#*¦macro�generates�a�two-word�MOVE.W)*¦instruction�knowing�that�sign�extension)*¦will�occur�at�execution�time�to�set�the'*¦entire��register�properly.‚Other-(*¦wise,�the�macro�generates�a�three-word#*¦MOVE.L�instruction.‚By�using�this'*¦macro�we�can�be�assured�of�generating'*¦the�shortest�correct�instruction,�and)*¦the�macro�will�still�function�correctly#*¦if�the�immediate�value�happens�to&*¦change�as�a�result�of�future�program$*¦modifications.‚The�MOVEIA�macro�is*¦invoked�as�follows. "*¦[