IMD 1.17: 11/11/2014 14:55:55 82VKXBVERDOS C* VERSADOS/RMS68K OBJECT 4.4 SN=48634 16 OF 22  BT16\82VKXBVERDOS 0420¿:-,3SRequest Disconnect ÿUnknown SDLC Response ÿ24éééé G1SSCT ASREL' NTS SSCT SAF%(…System Service Control Task+2pOUTTERM NSSCT pNTSSERV .JF3"$ & (Aú0<NAg.H瀀 |`6 DATAB˜³ÈnúF3Nu,HOî€ OCîaêHîŠB®¢~Aî¦1|ÿÿCè"!IB¨Aè^QÏÿèaà~F3Aî1|ÿÿCè"!IB¨AèJQÏÿè~AîF1|ÿÿB¨Aè"QÏÿðpýNAIî„*LF3 -g (@,gì+lB¬&lkJ,fž f|ÿÿ`Ä F3gH瀀 |`H&l ÿÿgp Aú(Cú4°�gAè³ÈnôH瀀 |`F3 (Nû.NTS2.SSCr)m+L`ÿZaô |d0<NA`ÿ>€F3 oH瀀 |`ÂAú åˆÑðüNФ¤¤šš¤€F3 oH瀀 |`‚Aú åˆÑðüNÐŠŠŠØØŠ&L€F3 oH瀀 |`@Aú åˆÑðüNÐ"""öÿÿþÐÿÿþÐ+F3°+gtadfÿ "úÿ0< I0ÛQÈÿü|ÿÿal`þVaºfþæ0< J4ÛQÈÿüI3|ÿÿ(HB,aBýrajgeô`”g |ÿÿ`þ ƒgðÔ&L`ŒalfI3þ˜0< J"K4ÙQÈÿü!k !k!k !k|ÿÿ(HB,aBý ageôF3`,g |ÿÿ`ý°a€`ý¨ÔfýÔJ,gýÌ`ÿ LCîÎ$I$üSSCT$ü PF3.B$ü. ER4üR $:ÖÂraÜÂraÔÂraÌÂraÄÂra¼Âra´I3Âra¬`DCúbEú "<CaBüf$:†EîÎ$Â$Â$ Kra‚Âr azAèÂrI3@apÂrajÂr adü ¼ CîÎ" ’‰R�aBü|ÿÿ`üÔSSCT Error- Code F3STS BCT R E C # R TH RH Data èaaF3SAfîNu o^0ÀNu0<NA~Aî¦ (ÿÿf ¼B(1|Bh!|I3<aaBûxAè^QÏÿÒNuCî„ )g"@`öB¨#HNu~Eî *ÿÿf Bj"jI3B€NuEêJQÏÿæpÿNupJ.™f)@¼ Bª%|( JažaBûNu/JF3g ÿgDü`/ |è0<NA _DüLßNu~EîF *ÿÿfBjB€NuEê3"QÏÿêpÿNu4é8M1TRANSSCN ASREL' NTS TRANSSCNSAG2(…TRANSPORT LAYER - SCAN USER QUEUE³2pNWLNKBQ pNWSETDC pTRADTXQ pTRABTOU pSBGTUSQ pNWDQHD pLCTBEG pNATBEG pNNTBEG pNWLSTC pNWLODSC JTRAMOVB ÚJTRASCAN pNWSIGNAL pSBPTFRBF *¾J3„ &nT + g=|HNs 9(gX&@IúN +g*@|#aA Îgì`<|#aA Äf4$kJ3�H B«B«"F«ë B«aA ž#ë(`¦†aA Šf*$y(B‡J*F3€ f( $H( ga `ÿda:`ÿ^&x Gëÿô +g&*@'mB­-fÞI3 ­ aB ÿ2- gÌNsHçôJjgfJjf^CêJk°B€)S€Àü&*xI3€@ GõJ«g+f+ g0 JaB þØ`p)áH+ )áIKë$-I3 g*B°mfð²mfê- fÄg )fžaB þŽ-6f +"g+@8I3  @'h"B¨í6aB þfLß/NuHçôCêpÀü&*x Gõ*k *— gJjF3 f¦* * Aí< g @²( fô´( fî`ÿ:B� Ší6* fgRmO3 H`ÿj JaB ýð­ g,/ (m$ìì+l$gí  UaB ýÂaB ý¾(_F3 `ÿT"<ÿ`"<ÿ`"<ÿ*x Cêp1² QÈÿø3A B‘¼ ÑÑ>3 ||Bi|#B)BiBjBª5|4-G `þ24éé éAG1TRANSSUB ASREL' NTS TRANSSUBSAHW(…TRANSPORT LAYER - MOVE DATAÊ2JTRACTOLC XJTRACTOLL JTRADTXQ pSBSDLCKL JTRABTOU lpSBPTXMQ JSNDBIU $pLCTBEG pNATBEG pNNTBEG pDBUFSZ pTRAMOVB pNWLNKPB pNWSIGNAL pSBPTFRBF pSBGTFRML *ôF3 / 0-gÆ f¾(m 2-*-f°- fZ fœ U,F3 gAì pN@`| ì`8*,,, h6pN@`Nq`Ú+F,B€08 ]@"I3€ XAÒ¬S�ƒÀ;A*aB ÿpgkí aj(_Nuí “m*$HCê IB€08 ¼ F3 B)mmBi><- f>ÑRmgú+l0í |B)F3 Bi, g éí XˆY€XG3m\ˆ]€°­0mÑ -0­ Þ@"mF3 ,"ä‰$B` ÙQÉÿü`ÙQÊÿüÑ­,‘­0J’g/a¸$_-gÿ8`4-I3 ga€`Bì­  UaB þd­+l gí- ga4`F3 ìa\`þ6aT(_Nu- f4 fî+l,+l0X­,Y­0B€08 U@I3 "Ò¬�ƒÀfr;A*aB ýèg nþxí $H“m*- f|"li B-F3 J-fi Bm( ) f 2)Aóÿ;A( -0Aê.‡ nB‡-(ÁF3  ¾x b ÁA`þ¬í B‡>8  € A`þ�m AêB€08 F3 B‡BjB* 2-(g0ÁT‡U€°­0mþ` -0èÿþB* `þNGíB¬ +g&@F3 `ö'LNu&x B­Gëÿô +g&@`ö'MNu5G-f| BjB* mL3@ -gG ¾- f / aB ü¨*_Nu JaB üžfNup N@/ -6gÆ-6gF3 ¼(m8- 6g<$m8 ¾jg€`ÿÿaÐJ€oâ0< m@&-D(¶€F3 l(�„™­DÙ¬,äŽD` ÙQÎÿü`ÙQÌÿüJ€g|fí 6+H@L3€ g,­ 6­ 6a¨ì UaB úà­ 6ga `þ> JaB úÊ`þ4(_NuF3 /$m< JaýNu/ « g +fJS ë `ë AëaB ùÈB¬!LF3 (_$@"L'jg*ë `"/ « gÊ +gÄ$L"@'igë  kzI3! ,) h6pN@`Nqé|  k(IaB ù\(J`° F*x  ª!j!j @3 !j éê k(IaB ù&pÀü&Aõ h(JaB ù(_Nu4éééé ééé' SDLC ROOT AGgg–bbSYSCMD CDxx \bbMACROS SI‰‰bbOVERVIEWSIŽŽU¦bbBEGSDLC ROëëbbBUFMGT ROôôbbBUFMGTX ROýýbbDLTRACE RObbEXORDLC RObbIBFMGT RObbPORTAIO RO!!bbPORTAV4 RO**bb**ˆSDLC.ROOT.AG*!‰TTL‡SDLC�DRIVER,�GENERIC�SECTION'* Arguments substituted via SYSGEN are;**„VERSION�-�Version�number*„REVISIO�-�Revision�number#*„REVDATE�-�Date�of�latest�revision%*„CHIPTYP�-�MPU�type�-�68000�or�680107*„STATION�-�Station�type�-�1�(Primary)�or�2�(Secondary)<*„IFRMBCT�-�I_frame�byte�counts�included�-�1�(Yes)�or�0�(No)E*„RES7201�-�Board�containing�the�NEC7201�-�02�(VM02)�or�400�(MVME400)* ‰OPT‡MEX,CRE VER†EQU‡\VERSIONŒVERSION�NUMBER/REV†EQU‡\REVISIOŒREVISION�NUMBER�WITHIN�VERSION /CHIPTYPE�EQU‡\CHIPTYPŒMPU�TYPE�(68000�OR�68010) 8STATION‚EQU‡\STATIONŒSTATION�TYPE�(PRIMARY�OR�SECONDARY)#PRIMARY‚EQU‡1“PRIMARY�STATION�VALUE&SECONDAR�EQU‡2“SECONDARY�STATION�VALUE 4IFRMBCT‚EQU‡\IFRMBCTŒSEND/RCV�BYTE�COUNT�ON�I_FRAMES YES†EQU‡1NO‡EQU‡0 0RES7201‚EQU‡\RES7201ŒNEC7201�RESIDENT�BOARD�TYPE* 02 = VM02, or 400 = MVME400 ‰IFEQ†CHIPTYPE-68000 ‹OPT‡P=68000‹IFEQ†STATION-PRIMARY/SDLCPRI†IDNT†VER,REVƒ68000�SDLC�PRIMARY�STATION:�TTL‡68000�PRIMARY�STATION�(Copyright�1982/3�Motorola�Inc)‹ENDC‹IFEQ†STATION-SECONDAR1SDLCSEC†IDNT†VER,REVƒ68000�SDLC�SECONDARY�STATION<�TTL‡68000�SECONDARY�STATION�(Copyright�1982/3�Motorola�Inc)‹ENDC‰ENDC‰IFEQ†CHIPTYPE-68010 ‹OPT‡P=68010‹IFEQ†STATION-PRIMARY/SDLCPRI†IDNT†VER,REVƒ68010�SDLC�PRIMARY�STATION:�TTL‡68010�PRIMARY�STATION�(Copyright�1982/3�Motorola�Inc)‹ENDC‹IFEQ†STATION-SECONDAR1SDLCSEC†IDNT†VER,REVƒ68010�SDLC�SECONDARY�STATION<�TTL‡68010�SECONDARY�STATION�(Copyright�1982/3�Motorola�Inc)‹ENDC‰ENDC‰IFNE†CHIPTYPE-68000‹IFNE†CHIPTYPE-680100�FAIL†1�INVALID�CHIPTYPE,�MUST�BE�68000�OR�68010‹ENDC‰ENDC‰IFNE†STATION-PRIMARY‹IFNE†STATION-SECONDAR5�FAIL†1�INVALID�STATION,�MUST�BE�PRIMARY�OR�SECONDARY‹ENDC‰ENDC‰IFNE†IFRMBCT-YES‹IFNE†IFRMBCT-NO8�FAIL†1�INVALID�IFRMBCT�VALUE,�MUST�BE�1�(YES)�OR�0�(NO)‹ENDC‰ENDC‰IFNE†RES7201-02‹IFNE†RES7201-400;�FAIL†1�INVALID�RES7201,�MUST�BE�02�(VM02)�OR�400�(MVME400)‹ENDC‰ENDC‰IFEQ†RES7201-400_KhL $‹XREF†MVME400ƒMVME400's�Base�Address‰ENDC‰PAGE‰INCLUDEƒSDLC.OVERVIEW.SI‰PAGE‰INCLUDEƒSDLC.MACROS.SI‰PAGE‰INCLUDEƒ9995.&.CRASH.MC‰INCLUDEƒ9995.&.NEC7201.EQ ‰INCLUDEƒ9995.SDLCPRI.TEMPLTS.EQ‰PAGE‰IFEQ†RES7201-400‹INCLUDEƒ9995.&.MVME400.EQ‹PAGE‰ENDC‰INCLUDEƒ9995.&.STR.EQ‰PAGE** NEC7201 Device Addresses*;‰XREF†NECCTL_A,NECCTL_B,NECDAT_A,NECDAT_B�NEC7201�Addresses ‰SECTIONƒ9 L*****************************************************************************‰DC.B†'**SDLC**'‰IFEQ†STATION-PRIMARY)‹DC.B†'PRIMARY�'ŠEYE-CATCHER�STATION�TYPE‰ENDC‰IFEQ†STATION-SECONDARY)‹DC.B†'SECONDAR'ŠEYE-CATCHER�STATION�TYPE‰ENDC‰IFEQ†CHIPTYPE-68000‹DC.B†'68000ƒ'ŠMPU�TYPE‰ENDC‰IFEQ†CHIPTYPE-68010‹DC.B†'68010ƒ'ŠMPU�TYPE‰ENDC‰IFEQ†RES7201-02‹DC.B†'VM02„'ŠBOARD�TYPE‰ENDC‰IFEQ†RES7201-400‹DC.B†'MVME400�'ŠBOARD�TYPE‰ENDC(‰DC.B†'\REVDATE'ŠDATE�OF�LATEST�REVISION*L*****************************************************************************;‰XDEF†PWRUP,SBSDLCRCST,SBUSRACK,SDLCQUSB,SDLCTMOUT,SDLCPRSB>‰XDEF†SDLCRCST,USRACK,SDLCQU,SDLCTTMOUT,SDLCPR,SBSDLCFL,SDLCFL*‰XDEF†INT7201,INT7201A,PWR,SDLCKL,SBSDLCKL*0‰XREF†SBGTFRIR,SBPTFRBF,SBPTFRML,SBPTUSQ,SDLCPCB‰IFEQ†CHIPTYPE-68000 ‹XREF†SBRQPA‰ENDC‰XREF†TRACFLAG,DLTRACE*‰IFEQ†STATION-PRIMARY‹INCLUDEƒSDLCPRI.POLLQ.SI‰ENDC‰IFEQ†STATION-SECONDARY‹INCLUDEƒSDLCSEC.PWRUP.SI‰ENDC‰INCLUDEƒSDLCPRI.INT7201.SI‰INCLUDEƒSDLCPRI.TRANSMIT.SI‰INCLUDEƒSDLCPRI.RECEIVE.SI‰IFEQ†STATION-PRIMARY‹INCLUDEƒSDLCPRI.FRMCNT.SI‰ENDC‰IFEQ†STATION-SECONDARY‹INCLUDEƒSDLCSEC.FRMCNT.SI‰ENDC‰INCLUDEƒSDLCPRI.SUBRTN.SI‰ENDéC‚******************************************************************‚*�SDLC.SYSCMD.CD1‚*„SYSGEN�Command�File�for�SDLC�driver�generation‚*4‚*„Create�an�SDLC�driver�for�a�specific�environment.‚*‚*„Arguments�are:*‚*‡Arg�1�=�Mnemonic�-�legal�mnemonics�are:‚* ‚*‘"GMADPRI"�-�GM�primary�system"‚*‘"GMADSEC"�-�GM�secondary�system$‚*‘"HDS4PRI"�-�HDS400�primary�system&‚*‘"HDS4SEC"�-�HDS400�secondary�system$‚*‘"VME10PRI"-�VME/10�primary�system‚*:‚*‡Arg�2�=�Overall�listing�file/device.‚Listing�is�handled‚*‘by�driver�chain�file.‚*K‚*�Each�time�maintenance�is�performed,�the�following�three�arguments�should1‚*�be�updated:�REVDATE�-�Date�of�latest�revision, ‚*�VERSION�-�Version�number,�and‚*�REVISIO�-�Revision�number.‚*/‚REVDATEƒ=�"09/07/83"ƒ*�Date�of�latest�revision‚VERSIONƒ=�3Œ*�Version�number‚REVISIOƒ=�7Œ*�Revision�number ‚*‚&LF‡=�0ŒLegal�mnemonic�flag ‚IFEQˆ"\1"‰,"GMADPRI"…&LF‡=�1…STATIONƒ=�1‰Primary�station…CHIPTYPƒ=�"68000"…RES7201ƒ=�02ˆVM02…SUBSˆSDLC.ROOT.AG3…ASM‰SDLC.ROOT.AG,SDLC.GMADPRI.RO,&.SYSGEN.TF;Z=100 …=COPY‡&.SYSGEN.TF,&.SYSASM.LS;A$…=COPY‡&.SYSGEN.TF,SDLC.GMADPRI.LS;Y‚ENDC‚IFEQˆ"\1"‰,"GMADSEC"…&LF‡=�1…STATIONƒ=�2‰Secondary�station…CHIPTYPƒ=�"68000"…RES7201ƒ=�02ˆVM02…SUBSˆSDLC.ROOT.AG3…ASM‰SDLC.ROOT.AG,SDLC.GMADSEC.RO,&.SYSGEN.TF;Z=100 …=COPY‡&.SYSGEN.TF,&.SYSASM.LS;A$…=COPY‡&.SYSGEN.TF,SDLC.GMADSEC.LS;Y‚ENDC‚IFEQˆ"\1"‰,"HDS4PRI"…&LF‡=�1…STATIONƒ=�1‰Primary�station…CHIPTYPƒ=�"68000"…RES7201ƒ=�02ˆVM02…SUBSˆSDLC.ROOT.AG3…ASM‰SDLC.ROOT.AG,SDLC.HDS4PRI.RO,&.SYSGEN.TF;Z=100 …=COPY‡&.SYSGEN.TF,&.SYSASM.LS;A$…=COPY‡&.SYSGEN.TF,SDLC.HDS4PRI.LS;Y‚ENDC‚IFEQˆ"\1"‰,"HDS4SEC"…&LF‡=�1…STATIONƒ=�2‰Secondary�station…CHIPTYPƒ=�"68000"…RES7201ƒ=�02ˆVM02…SUBSˆSDLC.ROOT.AG3…ASM‰SDLC.ROOT.AG,SDLC.HDS4SEC.RO,&.SYSGEN.TF;Z=100 …=COPY‡&.SYSGEN.TF,&.SYSASM.LS;A$…=COPY‡&.SYSGEN.TF,SDLC.HDS4SEC.LS;Y‚ENDC‚IFEQˆ"\1"‰,"VME10PRI"…&LF‡=�1…STATIONƒ=�1‰Primary�station…CHIPTYPƒ=�"68010" pJy…RES7201ƒ=�400‡MVME400…SUBSˆSDLC.ROOT.AG1…ASM‰SDLC.ROOT.AG,SDLC.VME10.RO,&.SYSGEN.TF;Z=100 …=COPY‡&.SYSGEN.TF,&.SYSASM.LS;A"…=COPY‡&.SYSGEN.TF,SDLC.VME10.LS;Y‚ENDC ‚IFEQˆ\&LF6…MSG‰"\1"�is�an�invalid�mnemonic.�Legal�mnemonics�are:;…MSG‰"GMADPRI","GMADSEC","HDS4PRI","HDS4SEC",�or�"VME10PRI".…MSG‰Please�rerun�sysgen�with�proper�mnemonic.…ABORT‡‚ENDC 3‚IFRMBCTƒ=�1Œ*�Send�and�Receive�I_Frame�Byte�Counts ‚*�END�OF�SDLC.SYSCMD.CDC‚******************************************************************‚END‰ééééé******************************** BEGINNING OF SDLC.MACROS.AI ******************************** RTS2RTE‚MACRO‰IFEQ†CHIPTYPE-680101‹MOVE.W„(A7),-(A7)ˆCREATE:�0(A7)�=�PC�(High�Word)1‹MOVE.W„4(A7),2(A7)‡.......�2(A7)�=�PC�(Low�Word).‹CLR.W…4(A7)�.......�4(A7)�=�VOR�(Short�Stack)‰ENDC6‰MOVE.W„SR,-(A7)ŒPush�SR�so�we�can�RTE�rather�than�RTS‰ENDM ************************** END OF SDLC.MACROS.AI **************************ééééé é�6* ****************************************************6* * BEGINNING OF FILE 'FIX:48.SDLC.OVERVIEW.AI' *1*�*�Date�Revised:�September�7,�1983,�Ed�Skinner†**�*²*2*�*�Note:�This�is�a�"generated"�file.‚Updates�to„*3*�*�these�introductory�notes�should�be�applied�to„*2*�*�SDLC.OVERVIEW.PR�-�See�a�description�of�this…**�*�contained�herein. **�*²*6* ******************************************************** 1 Introduction*C*†The�Motorola�Synchronous�Data�Link�Control�(referred�to‚simply‚asG*�SDLC)‚is‚a‚component�of�the�Network�Services�facility�available�under * VERSAdos.B*†The�SDLC�implementation�provides�a‚communications‚circuit‚driverI*�using�the�NEC7201�device�in�the�bit-oriented�protocol�mode.‚Frame�levelI*�commands�are�highly�similar�to�those�in�IBM's�SDLC.‚Support�is�providedG*�for‚the‚remote‚loading�and�dumping�of�stations,�multi-drop�as�well�asJ* point to point configurations, with circuit speeds of up to 57,600 baud. Š�“—›Ÿ£§&«¯³·»¿ÃÇËÏÓ×Ûß E*†Because�of�the�many�configurations�within�which�this�implementationI*�must�function,�operation�is�limited�to�half-duplex�only�(at�the‚present* time).***"* 2 Overview of System Preparation*D*†The‚SDLC�implementation�exists�as�a�permanently�resident�extensionF*�of�the�system's�executive�(RMS68K).‚As�such,�it�is‚"link"ed‚with‚theE*�executive‚such‚that‚a‚single‚load�module�exists�containing�both�theE*�executive�and�the�SDLC�driver.‚Additionally,‚in‚those‚systems‚whereD*�Network‚Services‚(NTS)‚executes‚on‚the‚same�processor,�it�(NetworkE* Services) will be similarly "link"ed and loaded with the executive.D*†Generally�speaking,�a�version�of�the�SDLC�driver�is�first‚producedH*�which‚is�"customized"�for�the�target�system.‚The�parameters�which�makeG*�a�given�implementation�unique�include�the�type�of‚processor‚(68000‚orH*�68010),‚the‚residence�of�Network�Services�(on-board�or�off-board),�theD*�type�of�board�upon�which‚the‚communications‚device‚(an‚NEC7201)‚isG*�located,‚and‚the‚address�of�the�various�registers�of�that�device,�andC* whether the implementation is for a primary or secondary station.C*†Generation�of�the�SDLC�driver�is�facilitated�by�chain‚files‚which?*�"customize"ƒtheƒgeneric‚driver‚for‚one‚of‚the‚specific‚targetB*�environments.‚This‚"customized"‚version‚(an‚object‚file)‚is‚thenA*�combined‚with‚other‚modules‚(such‚as‚the‚RMS68K‚kernel,‚NetworkA*�Services,�and�so�on)‚to‚create‚a‚single‚load‚module.ƒThis‚final4* preparation is outside the scope of this document.B*†For‚the‚GMAD‚system,�the�primary�station�software�runs�on�a�VM02J* board, with Network Services executing on a tightly coupled Exormacs MPUH*�board.ƒA�shared�memory�facility�is�used�for�the�communications�between* Network Services and SDLC.D*†Similarly,�the�secondary�GMAD�station�software�also�runs�on�a‚VM02I*�board,‚except�that�its�Network�Services�is�on-board,�and�a�considerably=* simpler shared memory area is used for inter-communication.>*†Preparation�of‚the‚HDS-400‚Primary‚and‚Secondary‚stations‚is* similar to the GMAD stations.C*†The‚VME/10‚Primary�station�for�an�HDS-400�runs�on�a�VME/10�systemD*�using�an�MC68010�MPU�and‚MVME400‚board‚(which‚contains‚the‚NEC7201 * device).* *** 3 SDLC Driver Preparation*@*†The‚first‚step,‚is‚to‚prepare�a�copy�of�the�informational�fileJ* (what you are currently reading) for inclusion into the assembly stream.F*�Note‚that‚this‚preparation‚need�be�done�only�if�the�SDLC.OVERVIEW.PRH*�input�file�has�been�updated.‚When�several�versions�of�SDLC�drivers‚areB*�to‚be‚generated,‚the‚OVERVIEW.CF‚(SDLC.OVERVIEW.CF)‚need‚only‚beH*�executed�before�generating�the�first�version.‚Once�this�has�been‚done,J* several different versions of the SDLC driver may be generated, re-using* the overview file./*†An�example�of�creating�this�overview�file�is;*†=USE�48.SDLC*†=OVERVIEW.CF)*‹=/*�CREATE�OVERVIEW.AI�FROM�OVERVIEW.PR1*‹=101.USERLIB.PROSE�OVERVIEW.PR,OVERVIEW.LS;Z=64*‹Version:�dd-mmmm-yy*‹No�errors�detected.*‹=DEL�OVERVIEW.AI#*‹DELETED�FIX:0048.SDLC.OVERVIEW.AI*‹=E�OVERVIEW.LS,OVERVIEW.AI;L*‹VERSAdos�EDITOR‚RELEASE‚x.y*‹COPYRIGHT�BY�MOTOROLA�19zz&*Ž(Example�output�deleted�for�brevity) *‹EDIT�DONE*‹=ENDE*†The�next�one�or�more�steps�consist�of�generating�version(s)�of�SDLCG*�as‚required‚for�the�target�system.‚SDLC�may�be�generated�as�a�primaryE*�or�secondary�station,�and�for�the�MC68000‚or‚MC68010‚processor.ƒTheE*�chain‚file‚which‚performs‚this�is�&.CONFIG.CF.‚It�is�always�invokedI*�with�two�arguments.‚The�first�argument�specifies�the�configuration,�theI*�second�argument�specifies�the�overall�listing�file�or�device.‚The�firstE*�argument�names�for�various‚SDLC‚configurations‚are:‚HDS-400‚PrimaryF*�Station‚("HDS4PRI"),‚HDS-400‚Secondary‚Station�("HDS4SEC"),�GMAD�DMSJ* (Primary) Station ("GMADPRI"), GMAD PMS (Secondary) Station ("GMADSEC"),/* and VME/10 HDS-400 Primary Station ("VME10").B*†The‚chain‚file‚produces�object�and�listing�files�appropriate�for"* the specified system as follows;*0* +--------------+--------------+--------------+!*�!‚Argument„!„Object„!ƒListing„!0* +--------------+--------------+--------------+)*�!‚"HDS4PRI"ƒ!‚HDS4PRI.RO‚!‚HDS4PRI.LS‚!)*�!‚"HDS4SEC"ƒ!‚HDS4SEC.RO‚!‚HDS4SEC.LS‚!)*�!‚"GMADPRI"ƒ!‚GMADPRI.RO‚!‚GMADPRI.LS‚!)*�!‚"GMADSEC"ƒ!‚GMADSEC.RO‚!‚GMADSEC.LS‚!&*�!‚"VME10PRI"‚!‚VME10.RO„!‚VME10.LS„!0* +--------------+--------------+--------------+** 4 Required Files*B*†The�following�files�are�the�minimum�set�required‚to‚generate‚all* versions of the SDLC driver;F*�&.SYSGEN.CF‚-‚The‚user‚invoked�chain�file�producing�SDLC�for�the�all*†SDLC�implementations.G*�SDLC.SYSCMD.CD�-�The�SYSGEN�command�file�used�in�the‚preparation‚of‚a*†version�of�the�SDLC�driver,F*�SDLC.ROOT.AG‚-‚The‚file‚"assembled"�to�produce�a�version�of�the�SDLCE*†driver,�as�directed�by�parameters�specified�by�the�user,�and�by�the*†SYSCMD.CD�command�file,G*�SDLC.OVERVIEW.CF‚-‚The‚chain�file�which�causes�SDLC.OVERVIEW.AI�to�be7*†created�from�SDLC.OVERVIEW.PR�via�the�PROSE�facility,9*�SDLC.OVERVIEW.PRƒ-ƒTheƒ"prose"ƒinput„file,„processed„by3*†SDLC.OVERVIEW.CF,�which�creates�SDLC.OVERVIEW.AI,G*�SDLC.OVERVIEW.AI‚-‚Created‚from�SDLC.OVERVIEW.PR�by�SDLC.OVERVIEW.CF,B*†this�file�presents�a�gross�overview�of�the‚implementation,‚and‚a'*†list�of�known�problems�and/or�errors,0* 9995.&.NEC7201.EQ - Defines NEC7201 Symbolics,2* 9995.&.STR.EQ - Defines RMS68K Kernel Symbolics,3* SDLCPRI.TEMPLTS.EQ - Defines SDLC Control Blocks,;* MVME400.EQUATES.AI - Defines the MVME400 board Symbolics,A* SDLC.MACROS.AI - Defines miscellaneous macros required by SDLC,F*�SDLCPRI.POLLQ.AI‚-‚Primary‚Station,‚External�(User)�Interfaces,�SDLC(*†Start�Up�Logic,�and�Polling�Algorithm,D*�SDLCPRI.INT7201.AI�-‚Primary‚Station,‚Transmitter‚Flush‚Logic,‚and*†NEC7201�Interrupt�Dispatcher,;* SDLCPRI.TRANSMIT.AI - Primary Station Transmitter Driver,7* SDLCPRI.RECEIVE.AI - Primary Station Receiver Driver,4* SDLCPRI.FRMCNT.AI - Primary Station Frame Handler,)* SDLCPRI.SUBRTN.AI - Common Subroutines,H*�SDLCSEC.PWRUP.AI‚-‚Secondary�Station,�External�(User)�Interfaces,�SDLC5*†Start�Up�Logic,�and�Po lling�Response�Algorithm,�andD*�SDLCSEC.FRMCNT.AI�-�Secondary‚Station‚Frame‚Handler,‚and‚Link‚Mode*†Finite�State�Machine.**** 5 Primary Station Files*@*†The�following�files�comprise�the�primary�station's�generation;* SLDC.ROOT.AG,* SDLC.OVERVIEW.AI,* 9995.&.NEC7201.EQ,* 9995.&.STR.EQ,* SDLCPRI.TEMPLTS.EQ,* SDLC.MACROS.AI,* MVME400.EQUATES.AI,* SDLCPRI.POLLQ.AI,* SDLCPRI.INT7201.AI,* SDLCPRI.TRANSMIT.AI,* SDLCPRI.RECEIVE.AI,* SDLCPRI.FRMCNT.AI, and* SDLCPRI.SUBRTN.AI.**** 6 Secondary Station Files*B*†The�following�files�comprise�the�secondary�station's�generation;* SLDC.ROOT.AG* SDLC.OVERVIEW.AI,* 9995.&.NEC7201.EQ,* 9995.&.STR.EQ,* SDLCPRI.TEMPLTS.EQ,* SDLC.MACROS.AI,* MVME400.EQUATES.AI,* SDLCSEC.PWRUP.AI,* SDLCPRI.INT7201.AI,* SDLCPRI.RECEIVE.AI,* SDLCSEC.FRMCNT.AI,* SDLCPRI.TRANSMIT.AI, and* SDLCPRI.SUBRTN.AI.**** 7 ROM-based Version Files*9*†The�files�which�comprise�SDLCROM�are�currently�unknown.**** 8 Primary Data Flows*>*†The‚primary‚data‚flow‚into‚SDLC‚is‚via�the�SBPTXMQ�and�PTXMQI*�functions�which�are�located�in�the�buffer�management�module�(BUFMGT‚andH*�BUFMGTX).ƒThese�functions�enqueue�a�transmit�buffer�to�the�appropriateI*�Secondary�Control�Block�(SCB)�where�the�SDLC�driver�will�find�it�at‚theF*�proper‚time.ƒIn‚the�primary�station,�the�SBPTXMQ�and�PTXMQ�functionsH*�"awaken"�SDLC�each�time�a�buffer�is�enqueued�by�calling�the‚SDLC‚entryF*�point‚SDLCQUSB‚or‚SDLCQU�function.‚In�the�secondary�station,�SDLC�is?*�not‚"awakened"‚when‚a‚buffer‚is‚enqueued.ƒIn‚anƒEXORMACS/VM02J* configuration, buffers are passed from the EXORMACS to the VM02 thru the* VM02 request queue.>*†The�primary�data�flow�from‚SDLC‚is‚via‚the‚SBPTUSQ‚and‚PTUSQI*�functions‚which�are�located�in�the�buffer�management�module�(BUFMGT�andG*�BUFMGTX).‚When�SDLC�has�received�an�error�free�transmission‚(which‚isB*�not‚an‚internally‚used‚SDLC‚control‚frame),‚the‚SBPTUSQ�or�PTUSQD*�function�is�called�and�the�received‚buffer‚is‚enqueued‚to‚the‚userI*�queue.‚In�an�EXORMACS/VM02�configuration,�the�user�queue�passes�buffers * from the VM02 to the EXORMACS.C*†In�general,�all�information�frames�(I_frames)‚contain‚applicationH*�program‚data,‚supervisory�frames�(S_frames)�are�used�internally�by�theI*�various�SDLC�stations�on�a�link,�and�un-numbered�(U_frames)�are�used‚to* control the mode of the link.C*†It‚is‚very�important�to�note�that�U_frames�are�never�"created"�orI*�"consumed"�by�the�SDLC�module:‚They�are�always�initiated�and�terminatedE*�outside‚of‚SDLC.ƒ"Hand-shake"‚procedures�exist�between�SDLC�and�theH*�U_frame�creator�and�consumer�to�assist�in�the�synchronization‚of‚these* two processes.**** 9 Entry Points*C*†External‚entry‚points�are�provided�within�the�SDLC�implementation* for the following conditions;*@* +----------+------+------------------------+-----+-----+-----+8*�!�Entry„!�Type�!�Input�Description†!�Pri�!�Sec�!�ROM�!@* +----------+------+------------------------+-----+-----+-----+;*�!�PWRUP„!�Subr�!�Start�SDLC�Operationƒ!�Yes�!�Yes�!�Yes�!2*�!�PWR†!�Intr�!�NEC7201�A-Side�Intr„!‚?‚!‚?‚!‚?‚!<*�!�INT7201‚!�Intr�!�NEC7201�B-Side�Intr„!�Yes�!�Yes�!�Yes�!=*�!�INT7201A�!�Intr�!�NEC7201�A-Side�Intr„!�Yes�!�Yes�!�Yes�!+*�!�SDLCQXMT�!�Subr�!�Unknown�!‚?‚!‚?‚!‚?‚!>*�!�SDLCQUSB�!�Subr�!�Send�Traffic�Enqueued‚!�Yes�!�No‚!�Yes�!<*�!�SDLCQUƒ!�Trap�!�Send�Traffic�Enqueued‚!�Yes�!�No‚!�Yes�!?*�!�SBUSRACK�!�Subr�!�Ack�SIM,�DISC,�or�SNRM�!�No‚!�Yes�!�Yes�!=*�!�USRACKƒ!�Trap�!�Ack�SIM,�DISC,�or�SNRM�!�No‚!�Yes�!�Yes�!>*�!�SDLCTMOU�!�Subr�!�Receive�Timer�Expired‚!�Yes�!�Yes�!�No‚!>*�!�SDLCTTMO�!�Trap�!�Receive�Timer�Expired‚!�Yes�!�Yes�!�No‚!:*�!�SDLCKLƒ!�Trap�!�Terminate�Operation„!�Yes�!�Yes�!�No‚!<*�!�SBSDLCKL�!�Subr�!�Terminate�Operation„!�Yes�!�Yes�!�No‚!9*�!�SDLCPRSB�!�Subr�!�50�mSecond�Tickˆ!�Yes�!�Yes�!�***�!7*�!�SDLCPRƒ!�Trap�!�50�mSecond�Tickˆ!�Yes�!�Yes�!�***�!=*�!�SDLCFLƒ!�T rap�!�Flush�All�Send�Traffic�!�Yes�!�Yes�!�No‚!?*�!�SBSDLCFL�!�Subr�!�Flush�All�Send�Traffic�!�Yes�!�Yes�!�No‚!<*�!�SDLCRCST�!�Trap�!�Buffer(s)�Now�Exist„!�No‚!�Yes�!�Yes�!<*�!�SBSDLCRC�!�Subr�!�Buffer(s)�Now�Exist„!�No‚!�Yes�!�Yes�!@* +----------+------+------------------------+-----+-----+-----+*F*�***�SDLCROM�executes�without�the�aid�of�"timers",‚and‚so‚these‚entry,* points are never used in actual operation.***'* 10 Support Functions and/or Variables*C*†Externally‚defined‚routines�which�are�used�by�this�implementation* are;I*�SBGTFRIR�-�FOREGROUND�(interrupt�handler)�USE�ONLY,�get�one�buffer‚fromE*†the�free�pool�regardless�of�the�low�water�mark�and�how�many�buffers *†remain,1* DLTRACE - add an entry to the SDLC trace table,.* SBPTFRBF - return a buffer to the free pool,2* SBPTFRML - return many buffers to the free pool,1* SBPTUSQ - put a buffer into the user queue, andF*�SBRQPA�-�(RMS68K�kernel�entry�point)�request‚a‚periodic‚activation‚-B*†Note‚that‚the�use�of�this�function�is�being�phased�out.‚ExistingD*†versions�(based�on�the�MC68000�MPU)�continue�to�use�this‚function,;*†andƒthereforeƒrequireƒLINK'ing‚with‚the‚associated‚RMS68KC*†functions.‚Newer�versions�(based�on�the�MC68010�MPU)�will�use‚theE*†TRAP�#0�instruction�to�access�the�same�function,�and�so�do�not�need'*†to�be�LINK'ed�with�the�RMS68K�Kernel.:* Additionally, various RMS68K functions are used by SDLC.*C*†Externally�defined�symbolic�variables�used�by‚this‚implementation* are;D* NECCTL_A - address of the NEC7201 device control register, Port A,D* NTCCTL_B - address of the NEC7201 device control register, Port B,A* NECDAT_A - address of the NEC7201 device data register, Port A,A* NECDAT_B - address of the NEC7201 device data register, Port B,5* SDLCPCB - pointer to the Primary Control Block, and2* TRACFLAG - trace wanted (least significant bit).**** 11 Known Problems*@*†The‚following‚paragraphs‚detail‚the‚"known"�problems�which�areD*�either�thought�to�be�within‚this‚SDLC‚implementation,‚or‚that‚haveI*�significant�bearing�on�SDLC's�performance.‚The�order�of�presentation�of'* these problems is of no significance.*G*�Thruput�Improvement�-�The�overall�system�thruput�could‚be‚improved‚byE*†adding�a�transmission�to�a�secondary�system�after�receiving�traffic@*†from�it.‚Presently,�when�a‚secondary‚station‚transmits‚inboundC*†traffic,‚it‚must�wait�for�the�next�poll�before�it�"finds�out"�howA*†many�frames�the�primary�station�received.‚During‚this‚period‚of6*†time,ƒseveralƒbuffersƒmayƒbeƒtiedƒup‚waiting‚for‚theC*†acknowledgement.‚If�the�primary�station�were�to�transmit�an�RR‚orA*†RNR‚(without‚the‚poll‚bit)�after�receiving�the�final�bit�from�a<*†secondary‚(assuming‚that‚informationƒframesƒwereƒreceived,E*†otherwise�the�extra�transmission�is�extraneous),�then�the�secondary<*†station‚would‚immediately‚know‚how‚many‚of‚its‚frames‚wereA*†successfully‚received‚by‚the�primary�station.‚This�change�would?*†have�a�significant�impact‚during‚the‚upload‚process‚where‚the7*†secondaryƒstationƒonlyƒhasƒfourƒbuffersƒto‚play‚with.A*†Unfortunately,�Network�Services�appears�to�be‚unable‚to‚keep‚up>*†with‚the‚current‚upload‚rate,‚and‚this‚proposed�change�would?*†significantly�accelerate‚the‚upload‚thruput‚thereby‚causing‚a+*†resource�shortage�in�the�primary�station.J* Architectural Problem - Use of the Low Water Mark facility of the buffer?*†pool�is�incorrect.ƒGenerally‚speaking,‚routines‚which‚consumeE*†system�buffers�should�be�subject�to�the�Low�Water�Mark,�while�those@*†which�return�buffers�to�the�pool,‚or‚that‚initiate‚some‚actionC*†which‚will‚cause�buffers�to�be�returned�to�the�pool�should�not�beA*†subject�to�the�Low�Water�Mark.‚Presently,�there�are‚a‚couple‚of@*†exceptions‚to‚these‚guidelines.ƒSpecifically,�the�SDLC�traffic>*†receive�routines�are�not�subject‚to‚the‚Low‚Water‚Mark:ƒThey;*†shouldƒbe.ƒThe‚NTS‚functions‚which‚perform‚the‚connect ionE*†tear-down�(disconnect,�etc)�are�subject�to�the�Low�Water�Mark:�They>*†should‚not‚be.ƒBecause‚of‚these‚"mis-architected"�functions,C*†dead-lock�situations�occur�when�a�node�receives�to�a‚traffic‚loadB*†which‚exceeds‚its�thruput.‚All�buffers�are�consumed�with�receive@*†traffic,�and�no�buffers�are‚left‚to‚send‚application-level,‚orE*†definite�response�traffic�which�would�uncommit�some�of�the�received *†buffers.C*�Performance�Problem�-‚The‚primary‚station‚is‚not‚re-enabling‚it'sE*†receiver�soon�enough�between�successive�receptions�when�the�sendingC*†secondary�station�is�running�in�its�ROM�version�and�is‚sending‚an>*†upload.ƒThe‚primary‚receives‚the‚first‚and�third�information>*†frames,�but�misses�the‚second‚one.ƒThis‚results‚in‚excessive*†upload�durations.G*�Unknown‚Cause‚-‚A�"Receive�buffer�overrun"�error�occurs�approximatelyE*†every�four�frames�when�receiving�an�upload�from�a�secondary�stationB*†running‚in‚it's�ROM�version.‚This�problem�is�most�likely�relatedA*†to�the�preceeding�problem.‚However,�the�sequence‚of‚events‚that=*†lead‚to‚the‚receive‚buffer‚overrun‚error‚are�a�mystery:‚TheC*†secondary�station�should�not�be�sending�over-length‚messages,‚and@*†error‚recovery‚in‚the‚primary‚should�prevent�other�errors�from*†"turning�into"�this�error.F*�Unknown�Cause�-�A�secondary�station�is�apparently‚getting‚stuck‚in‚a@*†Frame‚Reject‚state‚thereby‚preventing‚that�station�(only)�from*†completing�a�restart.I*�Unknown�Cause�-�Cessation�of�down-load�during�stress�periods�requires‚a?*†reboot‚of‚the‚entire‚system.ƒThis�situation�is�rare,�and�onlyE*†occurs�when�one�or�more�uploads�are�in�progress�at�the�same�time�as@*†downloads.ƒA‚"dead-lock"‚situation‚occurs�where�all�the�systemA*†buffers�are�in�use,�and�another�buffer�is�needed‚to‚free‚up‚anyB*†buffers.ƒThere‚may�be�other�problems�which�appear�to�be�the�sameA*†as�the�dead-lock�situation.‚This�may�be�an‚overall‚buffer‚usageB*†problem,‚or‚an‚NTS�problem�rather�than�a�specific�problem�in�the*†SDLC�implementation.E*�Architectural�Problem�-�If�a�secondary‚fails‚(or‚is‚manually‚reset)A*†while‚a‚download‚is‚in�progress�to�that�secondary,�the�state�ofC*†that�station�as�recorded�in�the�primary�occasionally‚prevents‚theC*†flushing‚of�traffic.‚This�causes�a�large�number�of�system�buffers>*†to�be�tied�up�for�an�extended�period�(conceivably,�forever).H*�Architectural�Problem�-�The�download�(and�upload)�processes‚contain‚noE*†data�rate�regulating�mechanisms�and�tend,�therefore,�to�drive�otherA*†parts�of�the�system�into�error�recovery‚situations‚by‚placing‚aB*†severe‚load‚on�the�system�unnecessarily.‚Due�to�the�difficultiesD*†in�correcting�this�problem,�no�practical�solution�appears�to‚existA*†at‚this‚time.ƒ(These�"difficulties"�include�the�need�to�totallyD*†revamp�how�uploads�and�downloads�are�performed�across�all‚products-*†currently�using�Network�Services�and�SDLC.)D*�Unknown‚Cause‚-‚An‚excessive‚retransmission‚error�is�occuring�on�a8*†download‚information‚block.„Theƒblockƒshouldƒhaveƒbeen>*†acknowledged‚by‚the‚loaded‚secondary,‚or‚it‚should�have�been@*†flushed�upon�download�completion.‚Either‚of‚these‚events‚would?*†prevent‚the‚excessive‚retransmission‚error‚which‚is�occuring.?*†There�is,�ostensibly,�no�problem�with‚this.ƒBut‚the‚system‚is'*†indicating�some�error,�none�the�less.F*�Unknown‚Cause‚-‚Apparently‚a�message�is�occasionally�being�discarded>*†erroneously�during‚the‚download‚and/or‚restart‚process.ƒThisD*†causes‚the�affected�secondary�station�to�be�unable�to�complete�itsA*†restart�and�requires�the�manual�resetting�of‚that‚station.ƒThis<*†problemƒmayƒbe‚related‚to‚the‚aforementioned‚architectural%*†difficulties�concerning�link�reset.@*�Architectural‚Problem‚-‚The‚"cooperation"‚between‚SDLCƒandƒNTSC*†concerning‚link‚reset�and/or�restart�is�faulty�due�to�a�number�ofC*†problems�in�the�architecture�of�this�area.‚The�"problems"�lead‚to1*†dead-lock�and/or�poor�performance�fairly�often .D*�Architectual‚Difficulty‚-‚RMS68K‚handling‚of‚set�date�and�time�may>*†result�in‚several‚seconds‚of‚computation‚with‚all‚interruptsC*†masked.ƒNTS/SDLC�"feels"�this�by�missing�transmission(s)�from�theC*†primary�station,�and�loosing�contact�for�several�seconds.‚As‚thisE*†only�occurs�when�a�secondary�station�is�re-starting,�the�problem�isD*†minor�the�problem�is�considered�to�be�an�"annoyance"�rather�than‚a=*†"problem".ƒCorrection‚of‚this‚problem‚may‚be‚implemented�byE*†changing�the�algorithm�within�RMS68K�and/or�by�revamping�the�"powerD*†on"�/�"power�off"�decision�criteria�within�SDLC.‚Regardless�of�theC*†RMS68K�changes,�the�SDLC's�up/down�criteria�should�be‚revamped‚as@*†the‚present‚implementation‚is‚crude‚and�"over-reacts"�to�minor*†transgressions.G*�Hardware�Problem�-�If�a�secondary�(or�the�primary)‚station‚fails‚suchC*†that‚it‚is�unable�to�perform�a�reset�of�the�communications�deviceD*†(NEC�7201),�and�the�failure�occurs�at�a�time�when�that�station‚hasA*†its‚transmitter‚enabled,‚the‚communications�circuit�will�be�"in?*†use"�for�an�indefinate�period�and‚no‚stations‚will‚be‚able‚to=*†communicate.ƒThis‚situation‚will‚continue‚until‚the‚failingC*†station�is�identified�and�disconnected�from�the�circuit.‚The‚mostD*†expeditious‚method�for�resolving�this�problem�is�to�1)�verify�thatE*†it�is�occuring�-�a�line�monitor�will�display�a�continuous�stream�ofC*†data‚on‚the�circuit�-�normally�the�same�byte�over�and�over�again,E*†and�then�to�2)�begin�disconnecting�secondary�stations�one�at�a�timeC*†until‚the�line�monitor�indicates�a�cessation�of�this�pattern.‚TheB*†continuous�transmission�will�cease�when�the‚offending‚station‚isD*†disconnected.‚Alternatively,�secondary�stations�may�be�powered�off@*†rather�than�being�disconnected.‚This‚condition‚(of‚a‚secondaryE*†"hogging"�the�circuit)�is�very�difficult�to�identify�in�the�primaryD*†station's�software,�and�it�is�uncertain�if�any�automatic‚procedureC*†can‚be‚initiated�by�the�primary�to�resolve�this�situation�even�if%*†it�could�determine�that�it�existed.*0* **********************************************0* * END OF FILE 'FIX:48.SDLC.OVERVIEW.AI' *0* **********************************************ééE1BEGSDLC ASREL' SDLC BEGSDLC SAQ(…Beginning of SDLC segment2IBEGSDLC )3 `þ4éééé éééãI1BUFMGT ASREL' SDLC BUFMGT SAQ(…BUFFER MANAGEMENT SUBROUTINESó2pUSERQHD pUSERQND pSDLCPCB ISBPTFRML ISBGTUSQ pSDLCQUSB ISBPTUSQ ¼ISBPTXMQ 6IGTFRBF LpFQBCNT IGTFRIR IPTFRBF âIGTFRML žpFQLWM IPTFRML pNATBEG IGTUSQ IPTUSQ ¶\2IPTXMQ 0pFREEQHD ISBGTFRBF RISBGTFRIR ISBPTFRBF èISBGTFRML ¤)JF3 P@ a@×Ns@ç||Sy(nk|&y(#Ó(F×B“FßNuRy(F×B/&|ÿÿÿÿF3 J FßNua@×Ns@ç||09(°y(o"Sy(k y(#Ð(F×B�FßNuRy(F×B/F3 |ÿÿÿÿFßNua@×Ns@çB/BgB§JAoÿý`ašf| —.ˆRoQÉÿì| _F3 2n |ÿÿÿÿFßNua@×Ns@ç±ügÿý| ¹(#È(Ry(Fß |ÿÿÿÿNua@×NsF3€  @J€g aÂ`ô |ÿÿÿÿNua@×Ns@çB€±ügÿý( "y("iD ÿg°gF3 ÓüXJfò|FßNuBhB( B( B�i|$iJ©fEé#H$ˆI3Š BiF×aB þ\| |ÿÿÿÿFßNua@×Ns@ç gÿýB�|$y( fEù(#È($ˆF3  Fß 9(g @pÀü&Að hpN@ |ÿÿÿÿNua@×Ns@ç|| 9(g @#Ð&3� (fB¹(F×B�FßNuF×B/ |ÿÿÿÿFßNu4éééìI1BUFMGTX ASREL' SDLC BUFMGTX SAR (…BUFFER MANAGEMENT SUBROUTINESö2pUSERQHD pUSERQND pSDLCPCB ISBPTFRML  pSYSPOFF pSDLCQXMT ISBGTUSQ LpSDLCQUSB ISBPTUSQ ÂISBPTXMQ *IGTFRBF ¢pFQBCNT IGTFRIR IPTFRBF †IGTFRML @pFQLWM pMEMOFF IPTFRML pNATBEG …2IGTUSQ FIPTUSQ ¼IPTXMQ $pFREEQHD pFREEQND ISBGTFRBF ¨ISBGTFRIR ISBPTFRBF ŒISBGTFRML F)ºF3P� a@×Ns@ç/ |"x J¸ fÿýFï|Jé kòfÿýSi n kF|B© F3B  &i —ü€×ø Ófÿý#S © gÿýFïB“B«B«B« "_FßNuRi F3 fÿý© gÿýFïB/&|ÿÿÿÿ"_FßNua@×Ns@ç|/ "x Fï|JéF3…"„ kòfÿý0) °i oPSi nk@B©  i ‘ü€Ñø Ðfÿý#P © gF3 ÿýFïB�B¨B¨B¨ "_ FßNuRi fÿý© gÿýFïB/ |ÿÿÿÿ"_FßNuF3 a@×Ns@çB/BgB§JAoÿý`aÿNf| —.ˆRoQÉÿê| _2n |ÿÿF3 ÿÿFßNua@×Ns@ç/ ±ügÿý"x B�Fï|Jé kòfÿý © �gÿý‘øF3… P€ Ñü€#H J© fJi fÿý‘ü€#H Ri oÿý© gÿýFï"_ |ÿÿI3 ÿÿFßNua@×Ns  @J€g aÿt`ò |ÿÿÿÿNua@×Ns@ç±ügÿýJ¸ gaB ýÂF3@ |FßNuB€( "x "iD ÿg°gÓüXJfò|FßNuBhB( B(I3 B�i|$iJ©fEé#H$ˆBiF×aB ýV| |ÿÿÿÿFßNua@×F3E$ Ns@ç gÿý"x B�F×|Jé kôfÿý ) g@$@Õø ‘ø $ˆ#H © gÿýF3  F× 8 g @pÀü&Að hpN@ |ÿÿÿÿFßNu‘ø #H Ñü€#H © gF3„ ÿýF×`¼a@×Ns@ç|"x F×|Jé kôfÿý ) €J€g, @Ñø J�fB©@3‚@ Ðfÿý#P © gÿýF×B�FßNu© gÿýF× |ÿÿÿÿB/FßNu4ééõI1DLTRACE ASREL' SDLC DLTRACE SAS#(…TRACE INTERRUPTS ON DATA LINKA2pSDLCPCB pNECCTL_A pNECCTL_B IDLTRACE pTRACEBEG )@<3@@@ $y($R4ï$ï4À$ñù(ù(Eê"y(µémEé"Š"y(Nu4éééééééþ,1EXORDLC ASREL' SDLC EXORDLC SAS5(…}2JSBSDLCFL $pSYSPOFF JSBSDLCKL 8JSBUSRACK JSDLCQXMT .JSDLCQUSB ’pMEMOFF pV2RQHD pSBGTFRBF *”H3 .,<¡aA ög <ÿT—` 1GFa Nu.,<¢`Ú|a NuB‡,<£F3�� `Æ/ " y(B�‘ù(Jé kúCé  €J€g"@Óù( fô"ˆ"y(© ` /×3 "Ÿ‘"_NuNu4ééééééM1IBUFMGT ASREL' SDLC IBFMGT SAT(…BUFFER MANAGEMENT INIT SUBROUTINE 2pSZDBUF HSBINFRBF ( (3 B�B€0:A ú@$HÑÀ³Èm$ˆRA`ò•ÀB’Nu4ééééééé  D1PORTAIO ASREL' SDLC PORTAIO SAT4(…PASS INERRUPT ON TO HDIO 2IPORTAIO pNECCTL_A ):>3 9(f )Ofp$qNÒ$o/iT"iX)ÿÿgäH€LßNu4éééééééN1PORTAV4 ASREL' SDLC PORTAV4 SATW(…MVME400, PASS INTERRUPT ON TO HDIO 2IPORTAIO pNECCTL_A )$(3 $iX€$iTBgHz@çNÒ9(fìLßNs4ééééé  éé"' TEST OUTTERM RO77bbG1OUTTERM ASREL' TEST OUTTERM SAU!(…Put Message out to terminal2NOUTTERM .*03AÖ!I !J0¼1|1|B¨Bh B¨NBNu4ééééééé/  ' VM02 VEC7201 AGDDbbSTRSDLC ROMMbb**ˆVM02.VEC7201.AG* ŠSECTION�8 ŠXDEFƒVEC7201=VEC7201ƒEQU„\V2G1IR6‹*�NEC7201�uses�the�Group�1,�IRQ�6�vector%ŠNOP—Must�have�code�to�satisfy�linkerŠENDééééééé<91STRSDLC ASREL' STRSDLC SAU%(…Start up SDLCx2pPORTAIO pSYSTYPE pVEC7201 pINT7201 pINT7201A pBEGSDLC pPWRUP pTRACFLAG pTRACEBEG HSTRSDLC (8H3@ :A þgNu&lAú pN@` `ÔHDIO*H0<"m6Eé "FIX:48.SDLCSEC.FRMCNT.AI' *5***************************************************** I* NOTE: I THINK THIS PROCEDURE (TRANSEQ) IS ALWAYS THE WRONG THING TO DO!@*‡WE�WILL�RE-USE�THE�FIRST�BUFFER�IN�THE�RECEIVE�QUEUE.‚IS�THEREE*‡ALWAYS�ONE�THERE?‚IS�IT�OK�TO�RE-INITIALIZE�ITS�BYTE�COUNT,�STATUS,3*‡ERROR,�RETRY�COUNT,�AND�SECONDARY�STATION�NUMBER?L* This situation (reaching the end of the transmit queue without sending the;*‡final�bit�should�occur�only�as�a�result�of�a�FLUSH�order.* ED SKINNER, MARCH 3, 1983 &‰FAIL†501‡TRANSEQ�IS�VERY,�VERY�WRONG! *TRANSEQ‚EQU‡*‰TRANSMIT�(END�OF�QUEUE)�EXIT/‰MOVE.L„SDPRCV(A5),A2�TRANSMIT�AN�"RR"�RESPONSE ‰CMPA.L„#0,A2‰CRASH.EQ‚*+1‡DIE�IF�NO�BUFFER! ‰MOVE.B„#SDDRRR+$10,SDDCMD(A2)�*‰BRA.L…VCTINIT6‚* &TRANSPB‚EQU‡*‰TRANSMIT�(POLL�BIT)�EXIT@‰MOVE.L„SDPRCV(A5),A3�TxMITTED�A�POLL�BIT,�GET�INTO�RECEIVE�MODE‰BRA.L…SDLCRC02‚* ‰PAGE%TRANSUF‚EQU‡*‰TRANSMIT�UNDERFLOW�EXIT‰MOVE.B„#NCW0RG1,NECCTL_B„*#‰MOVE.B„#NCW1IRD+NCW1STV,NECCTL_B�*9‰MOVE.B„#SDPBFC,SDPBSY(A5)�SET�SDLC�BUSY�IN�FRAME�CONTROL‰ADD.W…#1,SDSHCTOF(A4)…3/2/83'‰BTST.B„#0,SDDCMD(A3)�I�FIELD�TxMITTED?‰IFˆ�THEN.S)‹SUB.B…#2,SDSVSC(A4)�YES,�FIX�UP�Vs�COUNT‹AND.B…#$0E,SDSVSC(A4)6‹SUB.B…#1,SDSUKT(A4)�And�number�of�un-ack'd�frames�out‰ENDI/‰TST.L…SDSTHD(A4)�DID�AN�SDLC�FLUSH�JUST�OCCUR?‰IFˆ�THEN.S/‹MOVE.L„SDPRCV(A5),A2�Yes,�send�an�"RR"�command‹MOVE.B„#SDDRRR+$10,SDDCMD(A2)3‹MOVE.B„#SDPTRQ,SDPTXF(A5)�(sending�from�rcv�queue)‹BRA.L…VCTINIT6‰ENDI1‰TST.B…SDDRTC(A3)�No,�shall�we�try�sending�again?<‰BEQ.S…TRANSPBƒCount�is�zero,�so�we'll�try�again�when�polled@‰SUB.B…#1,SDDRTC(A3)�Count�isn't�zero�yet,�decrement�one�attempt=‰BNE.S…TRANSPBƒand�resend�(when�polled)�if�count�not�zero�yet?* Fall-thru to next page when the retransmission count expires.‰PAGE4* Note: We fall-thru to here from the previous page. h5q3y<�=‰<‘K™B¡Q©M±?¹4* The retry count has expired for a transmit buffer.=* Return it to the originator after marking it as unsendable.F* Then, fix up the transmit queue by linking the buffer just after the.*‡unsendable�one�to�the�buffer�just�before�it.?* For example, if the transmit queue currently looks like this;'*†A�-->�B�-->�C,�where�B�is�unsendable.:* Then we fix up the transmit queue so it looks like this;*†A�-------->�C.K* The fix-up is accomplished by looking for a buffer that points to the oneO* we just got rid of, and then storing the "next" buffer's address (as returned3* to us by SOMESEND) into its forward link pointer.3‰MOVE.B„#SDDSSTE,SDDSTS+1(A3)�Mark�it�as�unsendable6‰MOVE.L„A3,A1…A1�=�A(Unsendable�buffer�-�for�SOMESEND)>‰MOVE.L„A3,A2…A2�=�A(Unsendable�buffer�-�for�WHILE�clause�use)6‰BSR.L…SOMESEND‚Pass�the�Unsendable�buffer�to�the�user7‰MOVE.L„A1,A3…A3�=�A(Next�buffer�in�the�transmit�queue)?‰LEA‡SDSTHD-SDDLNK(A4),A1�Find�buffer�before�the�unsendable�one?‰WHILE.LƒSDDLNK(A1)��A2�DO.S�Pointing�to�unsendable�buffer?/‹MOVE.L„SDDLNK(A1),A1‡No,�on�to�the�next�buffer‰ENDW@‰MOVE.L„A3,SDDLNK(A1)�yes,�store�"next"�into�"before�unsendable"<‰BRA.S…TRANSPBƒAll�done�with�clean-up,�go�see�what�to�do�now ‰PAGE'RECEITO‚EQU‡*‰RECEIVE�TIME�OUT�OCCURRED‰MOVE.B„#SDDSSRT,SDDSTS+1(A3)‰ADD.W…#1,SDSHCRTP(A4)…3/2/83 ‰BRA.S…HSKP0 /RECEIEE‚EQU‡*‰RECEIVE�EXCESSIVE�ERRORS�OCCURRED‰MOVE.B„#SDDSSRE,SDDSTS+1(A3)‰ADD.W…#1,SDSHCREX(A4)…3/2/83 *ˆBRA.S…HSKP0 &RECEILB‚EQU‡*‰RECEIVE,�NO�BUFFERS�LEFT +RECEIFB‚EQU‡*‰RECEIVED�A�FINAL�BIT�RESPONSE ***ˆEND�OF�A�RCV�SEQUENCE,�SHUT�RECEIVER�OFF* HSKP0„MOVE.B„#NCW0RG1,NECCTL_B„*#‰MOVE.B„#NCW1IRD+NCW1STV,NECCTL_B�*‰MOVE.B„#NCW0RG3,NECCTL_B„*#‰MOVE.B„#NCW3BT8+NCW3AUE,NEC  CTL_B„*‰ADD.W…#1,SDSHCROF(A4)…3/2/83&‰BSR.L…SOMETOCLR�CLEAR�RECEIVE�TIMEOUT&* A5 = PRIMARY CONTROL BLOCK'S ADDRESS(* A4 = SECONDARY CONTROL BLOCK'S ADDRESS‰MOVE.L„SDPRCV(A5),A2#* A2 = CURRENT RCV BUFFER'S ADDRESS9‰MOVE.B„#SDPBFC,SDPBSY(A5)�SET�SDLC�BUSY�IN�FRAME�CONTROL,‰MOVE.W„#$2500,SR�LOWER�68000�INTERRUPT�MASK,‰BSR.L…SBXIDQ„CHECK�FOR�"XID"�ON�TxMIT�QUEUE* Fall-thru to the next page‰PAGE7* NOTE: WE MAY FALL-THRU TO HERE FROM THE PREVIOUS PAGE **ˆSDLC�FRAME�CONTROL�PROCEDURES*9HSKP1„MOVE.L„A2,SDPRCV(A5)�SAVE�NEW�HEAD�OF�RECEIVE�QUEUE!‰IF.B†SDDSTS+1(A2)��#0�THEN.S‹CLR.L…D0ˆNo�RCV�errors,‹MOVE.B„SDSCST(A4),D0 ‹SUB.B…#1,D0 ‹ASL.L…#2,D08‹JMP.S…RCVVCT(PC,D0.W)�To�current�state�if�no�RCV�errors,RCVVCT…BRA.L…VCTINITƒTo�INITIALIZATION�STATE+‹BRA.L…VCTINIBƒTo�INITIALIZATION�BUSY�STATE$‹BRA.L…VCTDISCƒTo�DISCONNECTED�STATE&‹BRA.L…VCTNRM„To�NORMAL�RESPONSE�STATE‹BRA.L…VCTBSY„To�BUSY�STATE$‹BRA.L…VCTFRMRƒTo�FRAME�REJECT�STATE‰ENDI‰MOVE.L„A2,A1…Rcv�Errors,5‰BSR.L…SOMESEND‚Tell�the�Application�Program�about�it ‰MOVE.L„A1,A20‰BSR.L…SOMEFREE‚*�FREE�ANY�OTHER�RECEIVE�BUFFERS+‰BRA.L…SDLCRC01‚*�GO�BACK�INTO�RECEIVE�MODE‰PAGE *$*ˆINITIALIZATION�STATE�FRAME�CONTROL*2VCTINIT‚MOVE.B„#SDSCIBSY,SDSCST(A4)�"SIM"�COMMAND?‰CMP.B…#SDDCSIM,SDDRSP(A2)‰BEQ.S…VCTINIT3,‰MOVE.B„#SDSCIM,SDSCST(A4)�NO,�POLL�BIT�SET?‰BTST.B„#$4,SDDRSP(A2)‰IFˆ�THEN.S5‹MOVE.B„#SDSCIM,SDSCST(A4)�Yes,�Send�a�"RIM"�Response‹MOVE.B„#SDDRRIM,SDDCMD(A2))VCTINIT6ƒCLR.W…SDDBCT(A2)�INIT�BYTE�COUNT%VCTINIT7ƒCLR.W…SDDSTS(A2)�INIT�STATUS"‹CLR.B…SDDRTC(A2)�INIT�RETRY�COUNT!‹CLR.B…SDDERR(A2)�INIT�SDLC�ERROR,‹MOVE.B„SDSSEC(A4),SDDSEC(A2)�INIT�STATION�#4‹MOVE.L„A2,SDPRCV(A5)�SAVE�NEW�HEAD�OF�RECEIVE�QUEUE ‹MOVE.L„A2,A3$‹BRA.L…TRANSMTƒTRANSMIT�THE�RESPONSE‰ENDI�FREE�QUEUE‰BSR.L…SOMEDISPOSE ‰MOVE.L„A1,A26‰MOVE.L„A1,D0…Any�more�receive�buffers�after�that�one?;‰BNE.L…HSKP1…Yes,�loop�back�up�and�see�what�the�next�one�is;‰BRA.L…SDLCRC01‚No,�just�go�turn�the�receiver�back�on�again :VCTINIT2�MOVE.B„#SDSCRDM,SDSCST(A4)�SET�DISCONNECTED�STATEGVCTINIT3�TST.W…SDDBCT(A2)�DATA�FIELD�ON�"SIM"�"SNRM"�OR�"DISC"�COMMAND?=‰BNE.L…FRMRPI„Yes,�he�shouldn't�have�done�that!�(Go�FRMR�him)<‰BSR.L…SBGTFRIR‚NO,�Get�a�buffer�for�sending�a�"UA"�response‰IFˆ�THEN.S2‹BSR.L…SOMEFREE‚NO�BUFFERS,�So�don't�send�anything@‹BRA.L…SDLCRC01‚(Make�like�we�didn't�receive�his�command�at�all)‰ENDI6‰CLR.B…SDSVRC(A4)�No�data�field,�it's�a�valid�command,-‰CLR.B…SDSVSC(A4)�reset�our�Vr�and�Vs�counts,1‰MOVE.L„A2,A1…and�tell�the�user�what�has�happened‰BSR.L…SOMESEND'‰MOVE.L„A3,A2…then�send�a�"UA"�response‰MOVE.B„#SDDRUA,SDDCMD(A2)�*@‰MOVE.B„#SDPTRN,SDPTXF(A5)�*�SET�TxMIT�FLAG�AS�IF�"RNR"�TxMITTEDJ* NOTE: THIS WILL CAUSE RECEIVED I-FRAMES TO BE IGNORED UNTIL AN "RNR" CAN?* BE TRANSMITTED BECAUSE WE ARE IN THE BUSY OR INIT BUSY STATE.M* WE HAVE PASSED A RECEIVED SNRM ON TO THE "USER" IN OUR MACHINE, AND HE MUST(* ACKNOWLEDGE IT BEFORE WE CAN CONTINUE.‰BRA.S…VCTINIT6‚* ‰PAGE *)*ˆINITIALIZATION�BUSY�STATE�FRAME�CONTROL*+VCTINIB‚BTST.B„#$4,SDDRSP(A2)�POLL�BIT�SET?2‰BEQ.S…VCTINIT1‚*�NO,�FREE�BUFFER,�GO�INTO�RECEIVEF‰MOVE.B‚#SDDRRNR+$10,SDDCMD(A2)�YES,�BUILD�&�TRANSMIT�A�"RNR"�RESPONSE‰BRA.S…VCTINIT6‚* ‰PAGE **ˆBUSY�STATE�FRAME�CONTROL**VCTBSYƒBTST.B„#$4,SDDRSP(A2)�POLL�BIT�SET?2‰BEQ.L…VCTINIT1‚*�NO,�FREE�BUFFER,�GO�INTO�RECEIVEF‰MOVE.B‚#SDDRRNR+$10,SDDCMD(A2)�YES,�BUILD�&�TRANSMIT�A�"RNR"�RESPONSE‰BRA.L…VCTINIT6ƒ* ‰PAGE *"*ˆFRAME�REJECT�STATE�FRAME�CONTROL*+VCTFRMR‚BTST.B„#$4,SDDRSP(A2)�POLL�BIT�SET?2‰BEQ.L…VCTINIT1‚*�NO,�FREE�BUFFER,�GO�INTO�RECEIVEC‰MOVE.B„#SDSCIBSY,SDSCST(A4)�YES,�"SIM",�"DISC",�OR�"SNRM"�COMMAND?‰CMP.B…#SDDCSIM,SDDRSP(A2)�*‰BEQ.L…VCTINIT3‚*‰CMP.B…#SDDCDISC,SDDRSP(A2)�*‰BEQ.L…VCTINIT2‚*‰MOVE.B„#SDSCBSY,SDSCST(A4)�*‰CMP.B…#SDDCSNRM,SDDRSP(A2)�*‰BEQ.L…VCTINIT3‚*4‰BRA.S…FRMRS  P„NO,�BUILD�&�TRANSMIT�A�"FRMR"�RESPONSE ‰PAGE E* FRAME REJECTS WILL BE TRANSMITTED BY A SECONDARY STATION FOR ANY OF* THE FOLLOWING REASONS;K* 1) INVALID COMMAND - IN DISC OR NRM STATE, RECEIVE AN XID, AND HAVE NEVER*–TRANSMITTED�AN�XID,�OR2*–IN�NRM�AND�RECEIVE�AN�"UNKNOWN"�SDLC�COMMAND,�OR2*–IN�FRAME�REJECT�STATE�AND�RECEIVE�ANY�OTHER�THAN*–A�SIM,�DISC,�OR�SNRM�COMMAND.J* 2) PROHIBITED I-FIELD - RECEIVED AN I-FIELD ON A COMMAND WHICH IS A SIM,*–SNRM,�DISC,�RR,�RNR,�OR�REJ.G* 3) BUFFER OVERRUN - RECEIVE AN OTHERWISE "GOOD" FRAME WHICH IS LONGER*–THAN�A�BUFFER.H* 4) INVALID Nr COUNT - RECEIVED AN Nr VALUE (IN EITHER A SUPERVISORY OR2*–AN�INFORMATION�FRAME)�WHICH�ACKNOWLEDGES�A�FRAME*–WE�HAVE�NOT�TRANSMITTED. **ˆCREATE�"FRaMe�Reject"�DATA*4FRMRICƒMOVE.B„#$01,SDPFRB+2(A5)‚INVALID�COMMAND�FRMR)‰CMP.B…#SDSCRDM,SDSCST(A4)�IN�DISC�STATE?,‰BEQ.L…VCTDISC1‚*�IF�YES,�SEND�"DM"�RESPONSE‰BRA.S…FRMRGN„NO,�SEND�"FRMR" 7FRMRPIƒMOVE.B„#$03,SDPFRB+2(A5)ƒPROHIBITED�I�FIELD�FRMR‰BRA.S…FRMRGN„* 3FRMRBOƒMOVE.B„#$04,SDPFRB+2(A5)ƒBUFFER�OVERRUN�FRMR‰BRA.S…FRMRGN„* 5FRMRNRƒMOVE.B„#$08,SDPFRB+2(A5)ƒINVALID�NR�COUNT�FRMR*BFRMRGNƒMOVE.B„SDDRSP(A2),SDPFRB(A5)�OFFENDING�COMMAND�->�FRMR�DATA=‰MOVE.B„SDSVSC(A4),D0�CURRENT�"NR"�&�"NS"�COUNTS�->�FRMR�DATA‰OR.B†SDSVRC(A4),D0‡*‰AND.B…#$EE,D0ƒ*‰MOVE.B„D0,SDPFRB+1(A5)(‰BSR.L…SOMEFREE‚FREE�ALL�RECEIVE�BUFFERS"‰BSR.L…SBGTFRIR‚FETCH�A�NEW�BUFFER6‰BGT.L…SDLCRC01‚OUT�IF�THERE�ARE�ABSOLUTELY�NO�BUFFERS2* GOT ONE, DON'T CARE IF IT'S THE LAST ONE OR NOT.‰MOVE.L„A3,A2…*DFRMRSPƒMOVE.B„#SDSCRFR,SDSCST(A4)�BUILD�&�TRANSMIT�A�"FRMR"�RESPONSE‰MOVE.B„#SDDRFRMR,SDDCMD(A2)�*'‰MOVE.W„#3,SDDBCT(A2)�*�INIT�BYTE�COUNT)‰MOVE.L„SDPFRB(A5),SDDDAT(A2)�*�INIT�DATA‰BRA.L…VCTINIT7‚* ‰PAGE * *ˆDISCONNECT�STATE�FRAME�CONTROL*+VCTDISC‚BTST.B„#$4,SDDRSP(A2)�POLL�BIT�SET?2‰BEQ.L…VCTINIT1‚*�NO,�FREE�BUFFER,�GO�INTO�RECEIVEC‰MOVE.B„#SDSCIBSY,SDSCST(A4)�YES,�"SIM",�"DISC",�OR�"SNRM"�COMMAND?‰CMP.B…#SDDCSIM,SDDRSP(A2)�*‰BEQ.L…VCTINIT3‚*‰CMP.B…#SDDCDISC,SDDRSP(A2)�*‰BEQ.L…VCTINIT2‚*‰MOVE.B„#SDSCBSY,SDSCST(A4)�*‰CMP.B…#SDDCSNRM,SDDRSP(A2)�*‰BEQ.L…VCTINIT3‚*.‰MOVE.B„#SDSCRDM,SDSCST(A4)�NO,�"XID"�COMMAND?‰CMP.B…#SDDCXID,SDDRSP(A2)�*‰BEQ.S…XIDRSP„*/‰CMP.B…#SDDCTEST,SDDRSP(A2)�NO,�"TEST"�COMMAND?‰BEQ.S…TESTRSP‚*GVCTDISC1�MOVE.B„#SDDRDM,SDDCMD(A2)‚NO,�BUILD�&�TRANSMIT�A�"DM"�RESPONSE‰BRA.L…VCTINIT6‚* ‰PAGE **ˆTRANSMIT�A�"TEST"�RESPONSE*%TESTRSP‚MOVE.B„#SDDCTEST,SDDCMD(A2)�*‰BRA.L…VCTINIT7‚* ‰PAGE J***************************************************************************<*‚SUBROUTINE:‚"SBXIDQ"�CHECK�FOR�AN�"XID"�ON�THE�TxMIT�QUEUE*2*‚ENTER:ŠA4.L�=�ADDRESS�OF�SECONDARY�CONTROL�BLOCK)*’A5.L�=�ADDRESS�OF�PRIMARY�CONTROL�BLOCK*!*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7*’D�U*’A�U�UƒU�P�PƒS *¢|_�stack*K*************************************************************************** 9SBXIDQƒMOVE.L„SDSTHD(A4),A3�"XID"�REPONSE�ON�TxMIT�QUEUE?6‰IF.L†A3��#0�AND.B�SDDCMD(A3)��#SDDCXID�THEN.S8‹MOVE.L„SDDLNK(A3),SDSTHD(A4)�TAKE�"XID"�OFF�TxMIT�QUEUE‹IF.L†SDPXID(A5)��#0�THEN.S5�MOVE.L„SDPXID(A5),A1…DISPOSE�OF�THE�OLD�"XID"�BUFFER�BSR.L…SOMEDISPOSE‹ENDI/‹MOVE.L„A3,SDPXID(A5)�NEW�"XID"�RESPONSE�BUFFER‰ENDI‰RTS ‰PAGE *&*ˆTRANSMIT�AN�"XID"�OR�"FRMR"�RESPONSE*2XIDRSPƒBSR.S…SBXIDQ„CHECK�FOR�"XID"�ON�TxMIT�QUEUE,‰MOVE.L„SDPXID(A5),D0�"XID"�RESPONSE�BUFFER?&‰BEQ.L…FRMRIC„*�IF�NO,�INVALID�COMMAND,‰BSR.L…SBGTFRIR‚FETCH�A�RCV�BUFFER�FOR�LATER‰IFˆ�THEN.S1‹BSR.L…SOMEFREE‚NO�BUFFERS,�JUST�STAY�IN�RCV�MODE‹BRA.L…SDLCRC01‰ENDI‰MOVE.L„A3,SDPRCV(A5)�*0‰MOVE.L„A2,A1…SEND�THE�"XID"�COMMAND�TO�THE�USER‰BSR.L…SOMESEND‚*,‰MOVE.L„SDPXID(A5),A3�PREPARE�"XID"�RESPONSE‰CLR.W…SDDSTS(A3)�*�STATUS!‰CLR.B…SDDRTC(A3)�*�RETRY�COUNTER‰CLR.B…SDDERR(A3)�*�ERROR)‰MOVE.B„SDSSEC(A4),SDDSEC(A3)�*�STATION�#%‰MOVE.B„#SDDCXID,SDDCMD(A3)�*�COMMAND1‰BRA.L…TRANSMTƒTRANSMIT�TH  E�"XID"�&�GO�TO�RECEIVE ‰PAGE *%*ˆNORMAL�RESPONSE‚STATE�FRAME�CONTROL*/VCTNRMƒMOVE.L„SDSTHD(A4),A3‡HEAD�OF�TxMIT�QUEUE*VCTNRM02�CLR.L…D0ˆIS�COMMAND�AN�"I"�FIELD?‰MOVE.B„SDDRSP(A2),D0 ‰BTST.L„#0,D0#‰BEQ.L…DSPNR1„YES,�OUT�IF�"I"�FRAME0‰BTST.L„#1,D0…NO,�"RR",�"RNR",�OR�"REJ"�COMMAND?0‰BEQ.S…DSPNR…YES,�OUT�IF�RR,�RNR,�OR�REJ�COMMAND‰BTST.L„#4,D0…NO,�POLL�BIT�SET?‰BEQ.S…VCTNRM06C‰MOVE.B„#SDSCIBSY,SDSCST(A4)�YES,�"SIM",�"DISC",�OR�"SNRM"�COMMAND?‰CMP.B…#SDDCSIM,D0‰BEQ.L…VCTINIT3‰CMP.B…#SDDCDISC,D0‰IF.B†D0��#SDDCDISC�THEN.S<‹CMP.B…#SDPTXQ,SDPTXF(A5)�"DISC",�TxMITTED�FROM�TxMIT�QUEUE?‹BNE.L…VCTINIT26‹CMP.B…#SDDRRD,SDDCMD(A3)�YES,�WAS�"RD"�LAST�RESPONSE?‹BNE.L…VCTINIT2K* NOTE: THE "RD" RESPONSE WILL BE LEFT ON THE TRANSMIT QUEUE UNTIL A "DISC"F*�COMMAND�IS�RECEIVED.‚THE�"RD"�CAME�FROM�A�"USER"�WITHIN�OUR�MACHINE.&‹MOVE.L„A3,A1…YES,�DISPOSE�OF�THE�"RD"‹BSR.L…SOMEDISPOSE-‹MOVE.L„A1,SDSTHD(A4)�NEW�HEAD�OF�TxMIT�QUEUE‹BRA.L…VCTINIT2‰ENDI‰MOVE.B„#SDSCBSY,SDSCST(A4)�*‰CMP.B…#SDDCSNRM,D0�*‰BEQ.L…VCTINIT3‚*.‰MOVE.B„#SDSCNRM,SDSCST(A4)�NO,�"XID"�COMMAND?‰CMP.B…#SDDCXID,D0�*‰BEQ.L…XIDRSP„*'‰CMP.B…#SDDCTEST,D0�NO,�"TEST"�COMMAND?‰BEQ.L…TESTRSP‚*!‰AND.B…#$EF,D0‚NO,�CLEAR�POLL�BIT)VCTNRM06�CMP.B…#SDDCUI,D0�IS�COMMAND�"UI"‰BEQ.L…RSPUI…*%‰BRA.L…FRMRIC„*�I�GIVE�UP�IF�IT�ISN'T ‰PAGE ADSPNR„TST.W…SDDBCT(A2)�DATA�FIELD�ON�"RR"�"RNR"�OR�"REJ"�COMMAND?$‰BNE.L…FRMRPI„*�IF�YES,�FRAME�REJECT**ˆTEST�FOR�A�VALID�Nr�COUNT*DSPNR1ƒCLR.L…D0 ‰CLR.L…D1 ‰CLR.L…D2$‰MOVE.B„SDDRSP(A2),D0�FETCH�Nr�COUNT‰LSR.B…#5,D0…*$‰MOVE.B„SDSVSC(A4),D1�FETCH�Vs�COUNT‰LSR.B…#1,D1…*-‰MOVE.B„SDSUKT(A4),D2�FETCH�#�TxMITTED�FRAMES ‰BEQ.S…DSPNR2„*�FRAMES�TxMITTED?>‰CMP.L…#0,A3…ALL�XMIT�FRAMES�GONE�(RESULT�OF�A�FLUSH)?�3/21/831‰BEQ.S…DSPNR2„YES,�SAME�AS�IF�NO�I_FRAMES�3/21/833‰BTST.B„#0,SDDCMD(A3)�NO,�"I"�FRAME�ON�TxMIT�QUEUE?‰BNE.S…DSPNR2„*�*1‰MOVE.B„SDDCMD(A3),D1�*�YES,�GET�Ns�COUNT�FROM�IT‰LSR.B…#1,D1…*�*‰ADD.B…D2,D1…*�*‰AND.B…#7,D1…*�*DSPNR2ƒWHILE.BƒD0��D1�DO.S‹SUB.B…#1,D1…NEXT�Vs�COUNT ‹AND.B…#7,D1#‹SUB.B…#1,D2…ALL�Vs�COUNTS�CHECKED?#‹BMI.L…FRMRNR„YES,�INVALID�Nr�COUNT‰ENDW* Fall-thru to the next page‰PAGE3* NOTE: WE FALL-THRU TO HERE FROM THE PREVIOUS PAGE *"*ˆDISPOSE�OF�TXMIT�BUFFERS�TO�NR-1*%‰CLR.L…D1ˆFETCH�Nr�COUNT�FROM�COMMAND‰MOVE.B„SDDRSP(A2),D1�*‰LSR.B„#4,D1…*‰AND.B…#$0E,D1ƒ*‰MOVE.B„D1,SDSVSC(A4)�*�Vs�=�Nr ‰MOVE.L„A3,D0…TxMIT�QUEUE�EMPTY?‰BEQ.L…DSPRC1„YES,�OUT>DSPNR4ƒCMP.B…#SDPTXQ,SDPTXF(A5)�NO,�TxMITTED�FROM�TxMIT�QUEUE?‰BNE.L…DSPRC1„*&‰CLR.L…D0ˆYES,�TXMITTED�A�UI�RESPONSE?‰MOVE.B„SDDCMD(A3),D0�*‰AND.B…#$EF,D0ƒ*‰IF.B†D0��#SDDCUI�THEN.S‹BTST.L„#0,D0…I�FIELD? ‹BNE.L…DCRTX8‹TST.B…SDSUKT(A4)�YES,�UNACKNOWLEDGED�I�FRAMES�TxMITTED? ‹BEQ.L…DSPRC1‹AND.B…#$0E,D0ƒYES,�Nr�=�Ns?‹IF.B†D1��D0�THEN.S4�MOVE.B„SDDRSP(A2),D0�YES,�is�response�RR,�RNR,�REJ?�AND.B…#$03,D0ƒ*�CMP.B…#1,D0…*�BNE.S…DSPUI…*-�BTST.B„#4,SDDRSP(A2)�and�poll/final�bit�set?�BNE.S…DSPUI…*+�MOVE.L„A2,A1…NO,�DISPOSE�OF�RECEIVE�BUFFER�BSR.L…SOMEDISPOSE�*%�MOVE.L„A1,A2…END�OF�RECEIVE�BUFFERS?�MOVE.L„A1,D0…*�BEQ.S…DSPUI…**�BRA.L…VCTNRM02‚NO,�TEST�BUFFER'S�RESPONSE‹ENDI‰ENDI)‰MOVE.L„A3,A1…NO,�DISPOSE�OF�TxMIT�BUFFER!‰BTST.B„#4,SDDCMD(A3)�POLL/FINAL?‰IFˆ�THEN.S‹BSR.L…SOMEDISPOSE�NO ‹MOVE.L„A1,A3‹SUB.B…#1,SDSUKT(A4) ‹BRA.S…DSPNR4‰ELSE.S7‹BSR.L…SOMEDISPOSE�YES,�ALSO�DISPOSE�OF�RECEIVE�BUFFERS ‹MOVE.L„A1,A34‹CLR.B…SDSUKT(A4)�CLEAR�UNACKNOWLEDGED�I�FRAME�COUNT ‹BRA.L…DSPRC1‰ENDI ‰PAGE *,*ˆA�UI�(UNNUMBERED�I�FIELD)�COMMAND�OCCURRED*=RSPUI„MOVE.L„A2,A1…SEND�RECEIVE�BUFFER�TO�APPLICATION�PROGRAM‰BSR.L…SOMESEND%‰MOVE.L„A1,A2…END�OF�RECEIVE�BUFFERS? ‰MOVE.L„A1,D0 ‰BEQ.S…DSPUI*‰BRA.L…VCTNRM02‚NO,�TEST�BUFFER'S�RESPONSE ‰PAGE **ˆDISPOSE�OF�UI�TXMIT�BUFFERS*9DSPUI„CMP.B…#SDPTXQ,SDPTXF(A5)�TxMITTED�FROM�TxMIT�QUEUE?‰BNE.L…DSPRC1„*&‰MOVE.L„A3,D0…YES,�END�O  F�TxMIT�QUEUE?‰BEQ.L…DSPRC1„*%‰CLR.L…D1ˆNO,�TXMITTED�A�UI�RESPONSE?‰MOVE.B„SDDCMD(A3),D1�*‰AND.B…#$EF,D1ƒ*‰CMP.B…#SDDCUI,D1�*‰BNE.S…DCRTX…**‰MOVE.L„A3,A1…YES,�DISPOSE�OF�TXMIT�BUFFER‰BTST.B„#4,SDDCMD(A3)�*‰IFˆ�THEN.S>‹BSR.L…SOMEDISPOSE�POLL/FINAL�SET,�ALSO�DISPOSE�OF�RCV�BUFFERS ‹MOVE.L„A1,A3 ‹BRA.S…DSPRC1‰ENDI#‰BSR.L…SOMEDISPOSE�POLL/FINAL�CLEAR ‰MOVE.L„A1,A3 ‰BRA.S…DSPUI ‰PAGE **ˆDECREMENT�TxMIT�RETRY�COUNTS*DCRTX„MOVE.L„A3,A1…*‰MOVE.B„SDSUKT(A4),D1+DCRTX2ƒMOVE.L„A3,D0…ALL�TxMIT�BUFFERS�GONE?‰BEQ.S…DCRTX5„*"‰BTST.B„#0,SDDCMD(A3)�NO,�I�FIELD?‰IFˆ�THEN.S*‹TST.B…D1ˆYES,�UNACKNOWLEDGED�COUNT�CLEAR?‹BEQ.S…DCRTX5„YES,�OUT ‹SUB.B…#1,D1‰ENDI7‰TST.B…SDDRTC(A3)�NO,�DECREMENT�RETRY�COUNT�IF�NON-ZERO ‰BEQ.S…DCRTX4*‰SUB.B…#1,SDDRTC(A3)�DECREMENT�RETRY�COUNT‰BNE.S…DCRTX4„EXPIRED??‰MOVE.L„A3,A1…YES,�SEND�THIS�TxMIT�BUFFER�TO�APPL�PGM�AS�UNSENT>‰MOVE.B„#SDDSSTE,SDDSTS+1(A3)�SET�RETRY�COUNTER�EXPIRED�STATUS$‰BTST.B„#$4,SDDCMD(A3)�POLL�BIT�SET?‰IFˆ�THEN.S&‹BSR.L…SOMESEND‚YES,�LAST�TXMIT�BUFFER4‹CLR.B…SDSUKT(A4)�CLEAR�UNACKNOWLEDGED�I�FRAME�COUNT ‹BRA.S…DCRTX5‰ENDI"‰BTST.B„#0,SDDCMD(A3)�NO,�I�FIELD?‰IFˆ�THEN.S#‹SUB.B…#1,SDSUKT(A4)�YES,�FIX�COUNT‰ENDI‰BSR.L…SOMESEND%‰MOVE.L„A1,A3…FETCH�NEXT�TxMIT�BUFFER ‰BRA.S…DCRTX2 .DCRTX4ƒCLR.B…SDDERR(A3)�CLEAR�SDLC�ERROR�FIELD$‰BTST.B„#$4,SDDCMD(A3)�POLL�BIT�SET?‰IFˆ�THEN.S1‹MOVE.L„SDDLNK(A3),A3�No,�FETCH�NEXT�TxMIT�BUFFER ‹BRA.S…DCRTX2‰ENDI!* Fall-Thru if poll/final bit set ‰PAGE +DCRTX5ƒMOVE.L„A1,A3ƒNEW�HEAD�OF�TxMIT�QUEUE**ˆDISPOSE�OF�RCV�BUFFERS*3DSPRC1ƒMOVE.L„A3,SDSTHD(A4)�NEW�HEAD�OF�TxMIT�QUEUE.‰MOVE.L„A2,D0…ALL�RECEIVE�BUFFERS�DISPOSED�OF? ‰BEQ.S…SELTX4‰CMP.B…#SDDERBO,SDDERR(A2)�NO,�BUFFER�OVERRUN�ERROR? ‰BEQ.L…FRMRBO0‰TST.B…SDDERR(A2)�NO,�SOME�OTHER�SDLC�RCV�ERROR? ‰BNE.S…SELTX2/‰MOVE.B„SDDRSP(A2),D0�IS�COMMAND‚UI�OR�I�FIELD?‰AND.B…#$EF,D0‰IF.B†D0��#SDDCUI�THEN.S ‹BTST.L„#0,D0 ‹BNE.S…SELTX2„OUT�IF�NOT�I-FRAME‰ENDI;‰MOVE.L„A2,A1…UI�OR�I-FRAME,�SEND�IT�TO�APPLICATION�PROGRAM‰BTST.B„#4,SDDRSP(A2)‰IFˆ�THEN.S!‹BSR.L…SOMESEND‚FINAL�BIT�NOT�SET ‹MOVE.L„A1,A2 ‹BRA.S…DSPRC1‰ELSE.S5‹BSR.L…SOMESEND‚*�YES,�ALSO�FREE�ALL�RCV�BUFFERS�LEFT$‹MOVE.L„A1,A2…FALL-THRU�TO�NEXT�PAGE‰ENDI ‰PAGE :* WARNING: WE MAY FALL-THRU TO HERE FROM THE PREVIOUS PAGE*%*ˆFETCH�A�BUFFER�&�TRANSMIT�SOMETHING*)SELTX„BSR.L…SOMEFREE‚FREE�ANY�OLD�BUFFERS"‰BSR.L…SBGTFRIR‚FETCH�A�NEW�BUFFER3‰BGT.L…SDLCRC01‚OUT�IF�ABSOLUTELY�NO�BUFFERS�AT�ALL‰IFˆ�THEN.S* GOT THE VERY LAST BUFFER/‹MOVE.L„A3,SDPRCV(A5)�NEW�HEAD�OF�RECEIVE�QUEUE ‹MOVE.L„A3,A21‹MOVE.B„#SDDRRNR+$10,SDDCMD(A2)�TRANSMIT�AN�"RNR"3‹MOVE.B„#SDPTRQ,SDPTXF(A5)�TxMITTING�FROM�RCV�QUEUE‹BRA.L…VCTINIT6‰ENDI3‰MOVE.L„A3,SDPRCV(A5)�NO,�NEW�HEAD�OF�RECEIVE�QUEUE-‰MOVE.L„A3,A2…USE�NEW�BUFFER�TO�TRANSMIT�FROM‰MOVE.B„#$10,SDDRSP(A2)**ˆSELECT�A�RESPONSE�TO�TRANSMIT*+SELTX2ƒBTST.B„#$4,SDDRSP(A2)�FINAL�BIT�SET?‰IFˆ�THEN.S(‹MOVE.L„A2,A1…NO,�DISPOSE�OF�THIS�BUFFER‹BSR.L…SOMEDISPOSE ‹MOVE.L„A1,A2 ‹BRA.L…DSPRC1‰ENDI5‰MOVE.L„A2,SDPRCV(A5)�ONLY�1�BUFFER�LEFT�IN�RCV�QUEUE‰MOVE.B„SDDRSP(A2),D0?‰AND.B…#$1F,D0ƒWere�we�sent�an�RNR�command?�or�have�no�traffic?9‰IF.B†D0��#SDDRRNR+$10�OR.L�SDSTHD(A4)��#0�THEN.S9‹MOVE.B„#SDDRRR+$10,SDDCMD(A2)�Yes,�send�an�"RR"�response3‹MOVE.B„#SDPTRQ,SDPTXF(A5)�(sending�from�rcv�queue)‹BRA.L…VCTINIT6‰ENDI‰MOVE.L„SDSTHD(A4),A3‰MOVE.B„#SDPTXQ,SDPTXF(A5)#‰BTST.B„#0,SDDCMD(A0)�YES,�I�FIELD?‰IFˆ�THEN.S:‹CLR.B…SDSUKT(A4)�YES,�CLEAR�UNACKNOWLEDGED�TRANSMIT�COUNT‰ENDI‰BRA.L…TRANSMT ‰PAGEG* When a "flush" occurs, after all transmit frames have been discarded,H* and when, at the moment of the flush, we are transmitting one of theseH* frames, an abort is transmitted and the transmitter turned off (by theE*�flush�procedure).‚Immediately�after�doing�that,�we�branch�to�SDLCRQ* to d ecide what to do next.I* In a secondary station, we simply exit because we will wait to see whatK* the primary wants us to do next (presumably he will poll us fairly soon). SDLCRQƒSDLRSRG‰RTE /***********************************************/* END OF FILE 'FIX:48.SDLCSEC.FRMCNT.AI' */***********************************************ééééééé4****************************************************4* BEGINNING OF FILE 'FIX:48.SDLCSEC.PWRUP.AI' *4**************************************************** M*�NOTE:�AT�STARTUP,�OUR�CURRENT�STATE�IS�"DISCONNECT�MODE".‚THE�STARTER-UPPERE*‡(WHO?)�STORES�#SDSCRDM�INTO�SDSCST�THEREBY�ASSERTING�THIS�STATE.‚WEE*‡ARE�IN�THIS�STATE�WHEN�THE�PWRUP�SUBROUTINE�IS�CALLED,�WHICH�IS�THE&*‡FIRST�CALL�TO�THE�SDLC�DRIVER�LOGIC. SDLRSRG‚MACRO2‰MOVEM.Lƒ(A7)+,A0-A6/D0-D2�RESTORE�SAVED�REGISTERS‰ENDM SDLSVRG‚MACRO‰MOVEM.LƒA0-A6/D0-D2,-(A7)‰ENDM‰PAGE H*************************************************************************Æ*D*�SUBROUTINE:‚"PWRUP"�INITIALIZE�THE�NEC7201�CHIP�AT�POWER�UP�TIME„*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤* *‘D�U�U�U®**‘A�U�U�UƒP…S¤**Æ*H************************************************************************ ‰NEXTWB,PWRUP„MOVE.B„#NCW0RCN,NECCTL_B„CHANNEL�RESET‰MOVE.B„#NCW0RG2,NECCTL_A)‰MOVE.B„#NCW2RTS+NCW2PRI+NCW2BIN,NECCTL_A*‰MOVE.B„#NCW0RG2,NECCTL_B„INTERRUPT�VECTOR‰MOVE.B„#0,NECCTL_B‰MOVE.B„#NCW0RG4,NECCTL_B„MODE)‰MOVE.B„#NCW4C01+NCW4SDL+NCW4SME,NECCTL_B#‰MOVE.B„#NCW0RG7,NECCTL_B„SDLC�FLAG‰MOVE.B„#SDLCFLAG,NECCTL_B3‰MOVE.B„#NCW0RG3,NECCTL_B„ENABLE�AUTO�ENABLE�OF�CTS!‰MOVE.B„#NCW3BT8+NCW3AUE,NECCTL_B‰IFEQ†RES7201-400‹MOVE.W„SR,-(A7)!‹ORI.W…#$0700,SRŠMask�Interrupts!5‹MOVE.L„#MVME400,A0ˆA0�=�Address�of�the�MVME400�board'‹BCLR.B„#REGSELEC,CTLPIA_A(A0)�Set�DDRAA‹MOVE.B„#WRT_LED+WRT_SEL,DATPIA_A(A0)�to�output�mid-two�bits�only:‹BSET.B„#REGSELEC,CTLPIA_A(A0)�Switch�now�to�Data�Reg�on�A=‹BSET.B„#WRT_SEL,DATPIA_A(A0)�Select�baud�rate�jumpers�Port�2(‹MOVE.B„DATPIA_A(A0),D0�and�read�them�in6‹ANDI.W„#$07,D0‹AND'ing�off�all�but�the�baud�rate�bitsB‹MOVE.B„V400BAUD(PC,D0.W ),D0�and�get�the�4-bit�corresponding�value3‹MOVE.B„D0,-(A7)Šsaving�it�on�the�stack�temporarily,‹BCLR.B„#REGSELEC,CTLPIA_B(A0)�Now,�set�DDRB2‹MOVE.B„#%11111111,DATPIA_B(A0)�to�all�bits�output:‹BSET.B„#REGSELEC,CTLPIA_B(A0)�Switch�now�to�Data�Reg�on�BÁ5ÊLÒKÚIâ;‹MOVE.B„DATPIA_B(A0),D0�and�read�the�current�4-bit�settings.‹ANDI.B„#RATE1MSK,D0�drop�out�Port�2's�setting;‹OR.B†(A7)+,D0�and�OR�in�the�new�value�we�figured�out�aboveB‹MOVE.B„D0,DATPIA_B(A0)�and�output�the�new�rate�(Port�1�unchanged)#‹MOVE.W„(A7)+,SRŠUnmask�Interrupts!‰ENDC,‰LEA‡SDLCPR(PC),A0‡Address�of�"SDLCPR"�->�A0‰MOVE.L„#TIMCNST,A1‰MOVE.W„#$4005,D19‰MOVE.L„#DLC1,D2ŒRequest�a�Periodic,�Recurring�Activation‰IFEQ†CHIPTYPE-68000 ‹TR0.RQPA‰ENDC‰IFNE†CHIPTYPE-68000 ‹TR0$.RQPA‰ENDC3‰BRA.S…HOPOVER�(MUST�BE�2�BYTE�INSTRUCTION)‚2/24/831‰ILLEGAL�DIE�IF�SBRQPA�RETURNS�ANY�ERROR!ˆ2/24/83 5HOPOVER‚BRA.L…SBSDLCRCSTŠGo�turn�on�the�receiver�now! ‰IFEQ†RES7201-400"V400BAUDƒDC.B†15,14,13,12,10,7,5,2‰ENDC *3*„This�is�a�dummy�routine�to�satisfy�XREF�in�BUFMGT*‰XDEF†SDLCQXMT )SDLCQXMT�ILLEGAL�Die,�should�not�be�used! ‰PAGE ‰SECTIONƒ9H*************************************************************************Æ*0*ˆTRAP:‚"SDLCQU"‚TRAP�SERVICE�ROUTINE�FOR�SDLC�*0*™A�BUFFER�HAS�BEEN�ENQUEUED�FOR�TRANSMISSION.�*,*™IN�THE�SECONDARY�STATION,�WE�DON'T�CARE.…**ˆSUBROUTINE:‚"SDLCQUSB"§**Æ**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ 'SDLCQUƒBSR.S…SDLCQUSB‚DO�THE�SUBROUTINE=‰MOVE.W„SR,0(A7)‚REPLACE�SR�ON�STACK�TO�GIVE�PROPER�CC�RETURN‰RTE‘AND�RETURN 2SDLCQUSB�RTS‘Just�Return,�We�don't�care�about�this ‰PAGE H*************************************************************************Æ*4*ˆTRAP:‚"SDLCTTMOUT"‚TRAP�SERVICE�ROUTINE�FOR�SDLCŒ*,*�THIS�ROUTINE�IS�ENTERED�WHEN�THE�RECEIVE�**�TIMEOUT�EXPIRESš**ˆSUBROUTINE:‚"SDLCTMOUT"¦**Æ**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ SDLCTMOUT‚RTS2RTE%SDLCTTMOUT�SDLSVRG�SAVE�ALL�USER�REGS‰MOVE.L„SDLCPCB,A6�RESTORE�REGS‰MOVEM.LƒSDPRRTA0(A6),A0-A6‰ADD.W…#1,SDSHCRTO(A4)…3/2/83‰BRA.L…RECEITOƒRECEIVE�TIMEOUT ‰PAGE H*************************************************************************Æ*8*ˆTRAP:‚"SDLCPR"‚TRAP�SERVICE�ROUTINE�WHICH�IS�ENTEREDˆ*%*™WHEN�THE�PERIODIC�TIMER�RUNS�DOWNŒ**ˆSUBROUTINE:‚"SDLCPRSB"§**Æ**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤*H************************************************************************ SDLCPRSB RTS2RTE!SDLCPRƒSDLSVRGŽSAVE�ALL�REGISTERS2‰MOVE.L„SDLCPCB,A5�ARE�WE�BUSY�WAITING�FOR�BUFERS?$‰IF.B†SDPBSY(A5)��#SDPBWB�THEN.S‹SDLRSRGŽNO,�RETURN‹RTE‰ENDI8‰BRA.S…SDLCRC01‚YES,�GO�GET�ONE�AND�TURN�ON�THE�RECEIVER‰PAGE H*************************************************************************Æ*0*ˆTRAP:‚"SDLCKL"ƒTRAP�SERVICE�ROUTINE�FOR�SDLC�*&*šTHIS�ROUTINE�EFFECTIVELY�KILLS�THEŠ*.*šSDLC�LINK�AND�CANCELS�PERIODIC�ACTIVATIONS‚**ˆSUBROUTINE:‚"SBSDLCKL"§**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤* *‘DƒU�U®**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ 9SDLCKLƒBSR.S…SBSDLCKL‚TRAP�ENTRY�POINT,�DO�THE�SUBROUTINE9‰MOVE.W„SR,0(A7)‚REPLACE�SR�ON�STACK�SO�WE�GIVE�PROPER�CC‰RTE‘AND�RETURN /SBSDLCKL�MOVE.W„SR,-(A7)‚SUBROUTINE�ENTRY�POINT!‰ORI.W…#$0700,SR�MASK�TO�LEVEL�7!1‰MOVE.B„#NCW0RCN,NECCTL_B�CHANNEL�RESET�7201�CHIP'‰BSR.L…SOMETOCLR�TURN�OFF�RECEIVE�TIMER‰MOVE.W„#$8005,D1;‰MOVE.L„#DLC1,D2‚Discontinue�Recurring�Periodic�Activations‰IFEQ†CHIPTYPE-68000 ‹TR0.RQPA‰E NDC‰IFNE†CHIPTYPE-68000 ‹TR0$.RQPA‰ENDC‰BRA.S…SDLCKLEX)‰ILLEGAL�DIE�IF�SBRQPA�RETURNS�ANY�ERROR! 6SDLCKLEX�MOVE.W„(A7)+,SR‚RESTORE�PRIOR�INTERRUPT�LEVEL‰RTS‘AND�RETURN ‰PAGE H*************************************************************************Æ*<*ˆSUBROUTINE:‚"SBUSRACK"‚USER�ACKNOWLEDGES�RECEIPT�OF�SDLC„*!*¡"SIM"�"DISC"�OR�"SNRM"�FRAMESˆ**ˆTRAP:ˆ"USRACK"©**Æ*&*ˆENTER:‚D0.B�=�"SDDCSIM"�=>�ACK�SIM›**•=�"SDDCDISC"�=>�ACK�DISC™**•=�"SDDCSNRM"�=>�ACK�SNRM™**Æ**Æ*#*ˆREGISTERS�USED:ƒ0�1�2�3�4�5�6�7�**˜D�P«* *˜A�U�S�**š|‚|Š|_�stack–**š|‚|____________�preserved’**š|_______________�used—**Æ**Æ*H************************************************************************ 9USRACKƒBSR.S…SBUSRACK‚TRAP�ENTRY�POINT,�DO�THE�SUBROUTINE5‰MOVE.W„SR,0(A7)‚REPLACE�SR�ON�STACK�GIVING�PROPER�CC‰RTE‘AND�RETURN @SBUSRACK�MOVE.L„SDLCPCB,A0�FETCH�SECONDARY�CONTROL�BLOCK�ADDRESS‰MOVE.L„SDPFSEC(A0),A0‰IF.B†D0��#SDDCSIM�THEN.S2‹MOVE.B„#SDSCRDM,SDSCST(A0)�IF�SIM,�SET�DISC�STATE‰ELSE.S‹IF.B†D0��#SDDCDISC�THEN.S3�MOVE.B„#SDSCRDM,SDSCST(A0)�IF�DISC,�SET�DISC�STATE‹ELSE.S�IF.B†D0��#SDDCSNRM�THEN.S2�MOVE.B„#SDSCNRM,SDSCST(A0)�IF�SNRM,�SET�NRM�STATE�ELSE.S%‘ILLEGAL�OTHERWISE,�ILLEGAL�ACK,�DIE!�ENDI‹ENDI‰ENDI‰RTS ‰PAGE H*************************************************************************Æ*2*ˆTRAP:‚"SDLCRCST"‚TRAP�SERVICE�ROUTINE�FOR�SDLCŽ*)*™THIS�ROUTINE�FETCHES�A�RECEIVE�BUFFERˆ**™AND�STARTS�UP�THE�RECEIVER“**ˆSUBROUTINE:‚"SBSDLCRCST"¥**Æ**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ SBSDLCRCST RTS2RTE#SDLCRCST�SDLSVRG�SAVE�ALL�USER�REGS>SDLCRC01�MOVE.L„SDLCPCB,A5�PRIMARY�CONTROL�BLOCK�ADDRESS�->�A5<‰MOVE.L„SDPFSEC(A5),A4�SECONDARY�CONTROL�BLOCK�ADDRESS�->�A4)‰CLR.L…SDPRCV(A5)�CLEAR�HEAD�OF�RCV�QUEUE ‰MOVE.W„SR,D0‰AND.W…#$0700,D0%‰CMP.W…#$0500,D0�AT�LEAST�LEVEL�FIVE?‰IF.W†#$0500��D0�THEN.S‹MOVE.W„SR,D0…NO,‹AND.W…#$F8FF,D0.‹OR.W†#$0500,D0�RAISE�TO�INTERRUPT�LEVEL�FIVE!-‹MOVE.W„D0,SR…(OLD�SR�AND�LEVEL�ARE�ON�STACK)‰ENDI-‰MOVE.B„#SDPBNB,SDPBSY(A5)�SET�SSDLC�NOT�BUSY$‰BSR.L…SBGTFRIR‚GET�A�RECEIVE�BUFFER‰IFˆ�THEN.S8‹MOVE.B„#SDPBWB,SDPBSY(A5)�NONE�AVAILABLE,�SLEEP�A�WHILE‹SDLRSRG‹RTE‰ENDIBSDLCRC02�MOVE.L„A3,SDPRCV(A5)�LINK�RCV�BUFFER�TO�HEAD�OF�RCV�QUEUE-‰MOVE.W„SDPRLG(A5),SDDBCT(A3)�INIT�BYTE�COUNT‰CLR.W…SDDSTS(A3)�INIT�STATUS!‰CLR.B…SDDERR(A3)�INIT�SDLC�ERROR,‰MOVE.B„SDSSEC(A4),SDDSEC(A3)�STATION�NUMBER#‰BRA.L…RECEIVEƒGO�INTO�RECEIVE�MODE .**********************************************.* END OF FILE 'FIX:48.SDLCSEC.PWRUP.AI' *.**********************************************éééé éé' GEN IBUFQ AGööbbIDLCP AGÿÿLbbILOADP AGbbINETP AGbbINET LG+bbINETNOL LG##4bbINETV2 LG,,1bbLOADV2 LG55bb**ˆGEN.IBUFQ.AG*0IBUFQ„IDNT†1,0ƒINIT�PARAMS�FOR�BUFFER�MANAGEMENT ‰SECTIONƒ8*$*ˆCOPYRIGHTED�1982�BY�MOTOROLA,�INC.*F***********************************************************************Ä*3*„Initialization�Parameters�for�Buffer�Management‘**Ä*F*********************************************************************** ‰XDEF†NUMBUF5NUMBUFƒDC.W†\NUMBUFƒNunber�of�buffers�in�Buffer�Queue ‰XDEF†SZDBUF4SZDBUFƒDC.W†\SZDBUFƒSize�of�data�area�in�each�buffer ‰XDEF†FQULWM4FQULWMƒDC.W†\FQULWMƒFree�Queue�User's�Low�Water�Mark‰ENDéééééî**ˆGEN.IDLCP.AG*1IDLCP…IDNTƒ1,0�Initialization�parameters�for�SDLC*‰NOLIST*‰INCLUDE�9995.INET.INET.EQ*‰LISTŠNOLISTŠINCLUDE�9995.INET.INET.EQŠLIST ŠSECTION�8*$*ˆCOPYRIGHTED�1982�BY�MOTOROLA,�INC.*F************************** *********************************************Ä*?*„Initialization�Parameters�for�Synchronous�Data�Link�Control…**Ä*F*********************************************************************** STAFLG„SET„0 ŠXDEFƒSTATION STATIONƒEQU„*ŠIFC„'\STATION','PRIMARY'&�DC.B‚0�Station�ID�flag,�0�for�primary STAFLG‡SETƒ1ŠENDCŠIFC„'\STATION','SECONDARY'*�DC.B‚1�Station�ID�flag,�<>0�for�secondary STAFLG‡SETƒ2ŠENDC ŠIFEQƒSTAFLG5�FAIL‚100ƒSTATION�must�equal�'PRIMARY'�or�'SECONDARY'ŠENDC ŠIFNEƒSTAFLG*STAFLG‡SET‚STAFLG-1…0=PRIMARY,�1=SECONDARYŠENDC* ŠXDEFƒSYSTYPE7SYSTYPEƒDC.Bƒ\SYSTYPE‹System�type�(NOLINK,LINKMAIN,...)* ŠXDEFƒMAXSEC ŠIFEQƒSTAFLGBMAXSEC‡DC.Wƒ\MAXSEC…Max�#�secondary�stations�(if�local�is�primary) �XDEFƒFSSTN0FSSTNˆDC.Bƒ\FSSTN�First�Secondary�Station�Number �XDEFƒSSINC-SSINCˆDC.Bƒ\SSINC�Secondary�Station�INCrementŠENDC ŠIFNEƒSTAFLG5MAXSEC‡DC.Wƒ1’If�local�station�is�secondary,�MAXSEC=1 �XDEFƒFSSTN FSSTNˆDC.Bƒ0 �XDEFƒSSINC SSINCˆDC.Bƒ0ŠENDC ŠXDEFƒDLBR%DLBR†DC.Wƒ\DLBRŽData�Link's�Baud�Rate ŠXDEFƒTXRTRY(TXRTRY„DC.Bƒ\TXRTRYŒTransmit�Retry�Count ŠXDEFƒRCRTRY'RCRTRY„DC.Bƒ\RCRTRYŒReceive�Retry�Count ŠXDEFƒMXOBF3MXOBF…DC.Bƒ\MXOBF�Maximum�Number�of�Outbound�Frames ŠXDEFƒRCTOV3RCTOV…DC.Wƒ\RCTOV�Receive�Timeout�Value�(1=50�Msec) ŠXDEFƒRTRDLY+RTRDLY„DC.Wƒ\RTRDLYŒRetry�Delay�(1=50�Msec) ŠXDEFƒTXDLY,TXDLY…DC.Wƒ\TXDLY�Transmit�Delay�(1=50�Msec) ŠXDEFƒPFDLY4PFDLY…DC.Wƒ\PFDLY�Poll�Powered�Off�Delay�(1=50�Msec) ŠXDEFƒPNDLY3PNDLY…DC.Wƒ\PNDLY�Poll�Powered�On�Delay�(1=50�Msec) ŠXDEFƒTXPDS$TXPDS…DC.Bƒ\TXPDS�#�of�Transmit�PadsŠEND÷M**ˆGEN.ILOADP.AG*(ILOADP„IDNTƒ1,0�Init.�equates�for�LOADV2 ŠSECTION�8*$* COPYRIGHTED 1982 BY MOTOROLA, INC.*#* Initialization equates for LOADV2* ŠXDEFƒV2OFF'V2OFF…EQU„\V2OFF�Offset�for�VM02�memory ŠXDEFƒV2SYSP0V2SYSP„EQU„\V2SYSPŒAddress�for�VM02�SYSPAR�area.ŠENDéééééé **ˆGEN.INETP.AG*/INETP„IDNT†1,0ƒINIT�PARAMS�FOR�NETWORK�SERVICES ‰SECTIONƒ8*$*ˆCOPYRIGHTED�1982�BY�MOTOROLA,�INC.*F***********************************************************************Ä*0*„Initialization�Parameters�for�Network�Services*Ä*F*********************************************************************** ‰XDEF†MAXLNAUFMAXLNAU‚DC.W†\MAXLNAU‚Max�#�Network�Addressable�Units�at�local�station ‰XDEF†MAXNAMEGMAXNAME‚DC.W†\MAXNAME‚Max�#�Network�Names�(if�primary�-�max�in�network) ‰XDEF†MAXCONN/MAXCONN‚DC.W†\MAXCONN‚Max�#�Logical�Connections ‰XDEF†OPERDEVOPERDEV‚DC.L†0‰ENDééééé =/*=/*†GEN.INET.LG=/*.=/* Link chain file run at sysgen time to link=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*"=LINK ,&.INET.LO,&.SYSGEN.TF;HMIXS TASK INET,$AATTR SDPSEG SDLC(R):9,10,2 $0000 SEG SSCT:14,0 SEG INET(R):8DEF DLCBLDCB,$0000DEF SBINFRBF,$0000DEF STRSDLC,$0000INPUT…SDLC.BEGSDLC.ROINˆSDLC.BUFMGTX.ROINˆSDLC.EXORDLC.ROINˆNTS.NTSREQ.ROINˆNTS.NTCREQP.ROINˆNTS.NWCREQ.ROINˆNTS.TRANSSUB.ROINˆNTS.TRANSSCN.ROINˆNTS.SSCT.ROINˆNTS.NWCTPRI.ROIN‡TEST.OUTTERM.ROINˆNTS.NTSSERV.ROINŠ&.SYSPAR.ROIN…M68000.INET.ROINˆGEN.INETP.ROINˆGEN.IDLCP.ROINˆGEN.IBUFQ.ROINˆGEN.ILOADP.ROIN‡INET.NTBLDTB.ROIN…M68000.SRSN.ROIN‡INET.NWTEST.ROIN‡INET.GETSTA.ROINPUT„INET.OUTTERMS.ROLIB 0.&.UTILIB.ROEND=/*=ENDéé éé,=/*=/*†GEN.INETNOL.LG=/*.=/* Link chain file run at sysgen time to link=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*$=LINK ,&.INETNOL.LO,&.SYSGEN.TF;HMIX TASK INET,$AATTR SDPSEG SDLC:9,10,2 SEG SSCT:14,0 SEG &INT:8DEF PORTAIO,$0000DEF NECDAT_A,$F70011DEF NECDAT_B,$F70013DEF NECCTL_A,$F70015DEF NECCTL_B,$F70017INPUT…SDLC.BEGSDLC.ROINˆSDLC.BUFMGTX.ROINˆSDLC.SDLCPRI.ROINˆSDLC.DLTRACE.ROIN 9999.M68XXX.EXRQPA.ROIN‚9999.M6840.RDTIMER.ROIN‰NTS.NTSREQ.ROIN‰NTS.NTCREQP.ROIN‰NTS.NWCREQ.ROIN‰NTS.TRANSSUB.ROIN‰NTS.TRANSSCN.ROIN‰NTS.SSCT.ROIN‰NTS.NWCTPRI.ROINˆTEST.OUTTERM.ROIN‰NTS.NTSSERV.ROIN‹&.SYSPAR.ROIN†M68000.INET.ROIN‰GEN.IDLCP.ROIN‰GEN.INETP.ROIN‰GEN.IBUFQ.ROIN‰GEN.ILOADP.ROINˆINET.IPSDLC.ROINˆINET.GETSTA.ROINˆSDLC.IBFMGT.ROINˆINET.NTBLDTB.ROIN†M68000.SRSN.ROINˆINET.NWTEST.ROINˆVM02.STRSDLC.ROINˆVM02.VEC7201.ROINPUT…INET.OUTTERMS.ROLIB 0.&.UTILIB.ROEND=/*=ENDééé5=/*=/*†GEN.INETV2.LG=/*.=/* Link chain file run at sysgen time to link=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*%=LINK ,VM02.INET.LO,&.SYSGEN.TF;SHMIX TASK INET,$AATTR SDPSEG SDLC:9,10,2 \V2BSTR SEG SSCT:14,0 SEG &INT:8DEFƒNECDAT_A,$F70011DEFƒNECDAT_B,$F70013DEFƒNECCTL_A,$F70015DEFƒNECCTL_B,$F70017DEFƒMAXCONN,$8000DEFƒMAXLNAU,$8000DEFƒMAXNAME,$8000DEFƒNTBLDTB,$8000DEFƒNTSREQ,$0000DEFƒNWCT,$0000DEFƒOUTTERMS,$0000DEFƒSSCT,$0000DEFƒTRASCAN,$0000INPUT‡9999.M68XXX.EXRQPA.ROINPUT‡9999.M6840.RDTIMER.ROINPUT‡SDLC.BEGSDLC.ROINPUT‡SDLC.BUFMGTX.ROINPUT‡SDLC.PORTAIO.ROINPUT‡SDLC.SDLCPRI.ROINPUT‡SDLC.DLTRACE.ROINPUT„&.SYSPAR.ROINPUT„M68000.INET.ROINPUT„GEN.IDLCP.ROINPUT„GEN.IBUFQ.ROINPUT„GEN.ILOADP.ROINPUT„INET.IPSDLC.ROINPUT„SDLC.IBFMGT.ROINPUT„M68000.SRSN.ROINPUT„INET.NWTEST.ROINPUT„VM02.STRSDLC.ROINPUT„VM02.VEC7201.ROINPUT„INET.GETSTA.ROLIB 0.&.UTILIB.RO END=/*=ENDééé$2=/*=/*†GEN.LOADV2.LG=/*.=/* Link chain file run at sysgen time to link=/*D=/* Sysgen parameter LINKLS = \LINKLS = file/device to which to send=/* the linker listing=/*%=LINK ,&.LOADV2.LO,&.SYSGEN.TF;HAMIXSSEG SEG0:0,8,14INPUT &.SYSPAR.ROINPUT INET.LOADV2.ROINPUT GEN.ILOADP.ROLIB 0.&.UTILIB.ROEND=/*=ENDéééééé-' NETVM02 INT LGBB bb =/*=/*†&..SYSINIT.LG=/*=/*=LINK ,INIT.LO,SYSGEN.TF;HAMIXSSEG .INT:8 \PCINPUT ROGEN.ROINPUT &.INITDAT.ROINPUT 9999.C13O15.SYSPAR.ROEND=/*=ENDééééééé: ' SDLCPRI FRMCNT SIOO5ÊbbINT7201 SIˆˆ+bbPOLLQ SI¹¹.cbbRECEIVE SIêê5žbbSUBRTN SI## bbTRANSMITSIDDLbb‰PAGE4****************************************************5* BEGINNING OF FILE 'FIX:48.SDLCPRI.FRMCNT.AI' *4**************************************************** 9TRANSEQ‚EQU‡*‰End�of�Xmt�Queue�reached,�P/F�bit�NOT�sent!‰MOVE.B„#NCW0EOI,N ECCTL_A8‰MOVE.B„#NCW0RG1,NECCTL_B„Disable�Transmitter�Interrupts!‰MOVE.B„#NCW1IRD+NCW1STV,NECCTL_B9‰MOVE.B„#SDPBFC,SDPBSY(A5)�SET�SDLC�BUSY�IN�FRAME�CONTROL‰ADD.W…#1,SDSHCTOF(A4)…3/2/83‰MOVE.L„SDSTHD(A4),A3‰MOVE.L„SDPRCV(A5),A2 ‰BSR.L…SOMEFREE�FREE�RCV�BUFFERS ‰LEA‡0,A2�*-‰CLR.B…SDSPWR(A4)�ASSUME�DEVICE�IS�POWERED�UP0‰BRA.L…DSPUI…DISPOSE�OF�ANY�TxMITTED�"UI"�FRAMES .TRANSPB‚BRA.L…RECEIVEƒTRANSMIT�(POLL�BIT)�EXIT ‰PAGE %TRANSUF‚EQU‡*‰TRANSMIT�UNDERFLOW�EXIT8‰MOVE.B„#NCW0RG1,NECCTL_B„Disable�Transmitter�Interrupts!‰MOVE.B„#NCW1IRD+NCW1STV,NECCTL_B9‰MOVE.B„#SDPBFC,SDPBSY(A5)�SET�SDLC�BUSY�IN�FRAME�CONTROL'‰BTST.B„#0,SDDCMD(A3)�I�FIELD�TxMITTED?‰IFˆ�THEN.S*‹SUB.B…#2,SDSVSC(A4)�YES,�FIX�UP�Vs�COUNTS‹AND.B…#$0E,SDSVSC(A4)‹SUB.B…#1,SDSUKT(A4)‰ENDI)‰TST.L…SDSTHD(A4)�Did�a�flush�just�occur?(‰BEQ.S…TRANSUF3‚Yes,�go�send�an�"RR"�now&‰TST.B…SDDRTC(A3)�No,�any�retry�count?2‰BEQ.L…TRANSMTƒNo,�retry�sending�forever�and�ever!>‰SUB.B…#1,SDDRTC(A3)�Yes,�count�one�attempt�to�send�the�buffer7‰BNE.L…TRANSMTƒand�go�re-send�it�if�count�not�exhausted4* The retry count has expired for a transmit buffer.=* Return it to the originator after marking it as unsendable.F* Then, fix up the transmit queue by linking the buffer just after the.*‡unsendable�one�to�the�buffer�just�before�it.?* For example, if the transmit queue currently looks like this;'*†A�-->�B�-->�C,�where�B�is�unsendable.:* Then we fix up the transmit queue so it looks like this;*†A�-------->�C.K* The fix-up is accomplished by looking for a buffer that points to the oneO* we just got rid of, and then storing the "next" buffer's address (as returned3* to us by SOMESEND) into its forward link pointer.G1P@X@`NhOpJx33‰MOVE.B„#SDDSSTE,SDDSTS+1(A3)�Mark�it�as�unsendable6‰MOVE.L„A3,A1…A1�=�A(Unsendable�buffer�-�for�SOMESEND)>‰MOVE.L„A3,A2…A2�=�A(Unsendable�buffer�-�for�WHILE�clause�use)6‰BSR.L…SOMESEND‚Pass�the�Unsendable�buffer�to�the�user7‰MOVE.L„A1,A3…A3�=�A(Next�buffer�in�the�transmit�queue)?‰LEA‡SDSTHD-SDDLNK(A4),A1�Find�buffer�before�the�unsendable�one?‰WHILE.LƒSDDLNK(A1)��A2�DO.S�Pointing�to�unsendable�buffer?/‹MOVE.L„SDDLNK(A1),A1‡No,�on�to�the�next�buffer‰ENDW@‰MOVE.L„A3,SDDLNK(A1)�yes,�store�"next"�into�"before�unsendable"8‰BNE.L…TRANSMTƒGo�send�the�next�one�if�something's�thereETRANSUF3�MOVE.L„SDPRCV(A5),A3�Otherwise,�send�an�"RR"�command�instead‰BRA.L…SDLCPR5B ‰PAGE /RECEIEE‚EQU‡*‰RECEIVE�EXCESSIVE�ERRORS�OCCURRED‰MOVE.B„#SDDSSRE,SDDSTS+1(A3)‰ADD.W…#1,SDSHCREX(A4) ‰BRA.S…HSKP2 ‰PAGE 'RECEITO‚EQU‡*‰RECEIVE�TIME�OUT�OCCURRED‰MOVE.B„#SDDERTO,SDDERR(A3)‰ADD.W…#1,SDSHCRTP(A4) +RECEIFB‚EQU‡*‰RECEIVED�A�FINAL�BIT�RESPONSE *RECEILB‚EQU‡*‰RECEIVE�DEPLETED�BUFFER�POOL ***ˆEND�OF�A�RCV�SEQUENCE,�SHUT�RECEIVER�OFF*HSKP2„MOVE.B„#NCW0RG1,NECCTL_B!‰MOVE.B„#NCW1IRD+NCW1STV,NECCTL_B‰MOVE.B„#NCW0RG3,NECCTL_B!‰MOVE.B„#NCW3BT8+NCW3AUE,NECCTL_B‰ADD.W…#1,SDSHCROF(A4)…3/2/83&‰BSR.L…SOMETOCLR�CLEAR�RECEIVE�TIMEOUT‰MOVE.L„SDSTHD(A4),A3‰MOVE.L„SDPRCV(A5),A2&* A5 = PRIMARY CONTROL BLOCK'S ADDRESS(* A4 = SECONDARY CONTROL BLOCK'S ADDRESS%* A3 = CURRENT TXMIT BUFFER'S ADDRESS#* A2 = CURRENT RCV BUFFER'S ADDRESS * Fall-thru to the next page‰PAGE3* NOTE: WE FALL-THRU TO HERE FROM THE PREVIOUS PAGE **ˆSDLC�FRAME�CONTROL�PROCEDURES*9‰MOVE.B„#SDPBFC,SDPBSY(A5)�SET�SDLC�BUSY�IN�FRAME�CONTROL,‰MOVE.W„#$2500,SR�LOWER�68000�INTERRUPT�MASK@‰CLR.B…SDSTXF(A4)�ASSUME�NOT�(RNR�SENT�&�GOOD�RSP�RCV'D)�2/24/83 %‰IF.B†SDDRSP(A2)��#SDDRRIM�THEN.S5‹OR.B†#SDDSRIM,SDDSTS(A2)�IF�RIM,�THEN�SET�RIM�STATUS‰ELSE.S$‹IF.B…SDDRSP(A2)��#SDDRDM�THEN.S5�OR.B†#SDDSRDM,SDDSTS(A2)�IF�RDM,�THEN�SET�RDM�STATUS‹ELSE.S $�IF.B†SDDRSP(A2)��#SDDRRD�THEN.S3�OR.B†#SDDSRRD,SDDSTS(A2)�IF�RD,�THEN�SET�RD�STATUS�ENDI‹ENDI‰ENDI.‰MOVE.B„SDDERR(A2),D0�Very�bad�error�received?‰IFˆ�THEN.S4‹IF.B†D0��#SDDENNR�AND.B�D0��#SDDEIFU�THEN.S-�BRA.L…INVRSP„Yes,�can't�tell�what�it�is,�out‹ENDI‰ENDI7‰CLR.B…SDSPWR(A4)�No,�It's�either�OK,�or�just�sorta�bad‰MOVE.B„#SDSCNRM,SDSCST(A4)$‰IF.B†SDPTXF(A5)��#SDPTRN�THEN.S<‹MOVE.B„#SDSTRN,SDSTXF(A4)�Sent�RNR�or�RR,�assert�good�reply‰ENDI ‰PAGE+HSKP9„IF.B†SDDRSP(A2)��#SDDRFRMR�THEN.SA*ŠSecondaries�send�Frame�Reject�for�any�of�the�following�reasons;*Œ1�-�Invalid�command,?*�In�DISC�or�NRM�state,�and�Rcv�XID�but�don't�have�one�to�send,/*�In�NRM�state�and�Rcv�an�"unknown"�command,�or6*�In�FRMR�state�and�Rcv�other�than�SIM,�DISC,�or�SNRM,*Œ2�-�Prohibited�I_field,7*�Rcv�an�I_field�on�a�SIM,�SNRM,�DISC,�RR,�RNR,�or�REJ,*Œ3�-�Buffer�Overrun,<*�Rcv�an�otherwise�good�frame�which�is�longer�than�a�buffer,*Œ4�-�Invalid�Nr�Count,>*�Rcv�an�Nr�count�which�acknowledges�an�frame�he's�never�sent.2‹OR.B†#SDDSFRM,SDDSTS(A2)�SET�FRMR�OCCURRED�STATUS.‹MOVE.L„A2,A1�SEND�FRMR�TO�APPLICATION�PROGRAM‹BSR.L…SOMESEND ‹MOVE.L„A1,A2$‹BSR.L…SOMEFREE�FREE�ALL�RCV�BUFFERS)‹BRA.L…DCRTX�DECREMENT�TxMIT�RETRY�COUNTS‰ENDI‰CLR.L…D0ˆNO,�IS�RESPONSE�UI?‰MOVE.B„SDDRSP(A2),D0‰AND.B…#$EF,D0‰IF.B†D0��#SDDCUI�THEN.S8‹MOVE.L„A2,A1…SEND�RECEIVE�BUFFER�TO�APPLICATION�PROGRAM‹BSR.L…SOMESEND%‹MOVE.L„A1,A2…END�OF�RECEIVE�BUFFERS? ‹MOVE.L„A1,D0 ‹BEQ.L…DSPUI'‹BRA.L…HSKP9…NO,�TEST�BUFFER'S�RESPONSE‰ENDI!‰AND‡#$0F,D0ƒNO,�IS�RESPONSE�RNR?‰IF.B†D0��#SDDRRNR�THEN.S6‹MOVE.B„#SDSCBSY,SDSCST(A4)�YES,�SET�REMOTE�BUSY�STATE ‹BRA.L…DSPNR‰ENDI!‰CMP.B…#SDDRRR,D0�IS�RESPONSE�RR?‰BEQ.L…DSPNR…* '‰CMP.B…#SDDRREJ,D0�NO,�IS�RESPONSE�REJ?‰BEQ.L…DSPNR…* $‰BTST.L„#$0,D0„NO,�IS�IT�AN�I�FIELD?!‰BEQ.L…DSPNR1„YES,�CHECK�Nr�COUNT *‰MOVE.L„A3,D0…NO,�ANYTHING�IN�TxMIT�QUEUE?‰BEQ.L…DSPRC1„*<‰CMP.B…#SDPTXQ,SDPTXF(A5)�DID�WE�TxMIT�FROM�THE�TxMIT�QUEUE?‰BNE.L…DSPRC1„* ‰PAGE%‰IF.B†SDDCMD(A3)��#SDDCSIM�THEN.S$‹IF.B†SDDRSP(A2)��#SDDRUA�THEN.S)�MOVE.B„#SDSCRDM,SDSCST(A4)�RDM�-->�STATE�CLR.B…SDSVRC(A4)�0�-->�Vr�CLR.B…SDSVSC(A4)�0�-->�Vs �BRA.L…OKRSP‹ELSE.S �BRA.L…INVRSP‹ENDI‰ENDI&‰IF.B†SDDCMD(A3)��#SDDCSNRM�THEN.S$‹IF.B†SDDRSP(A2)��#SDDRUA�THEN.S)�MOVE.B„#SDSCNRM,SDSCST(A4)�NRM�-->�STATE�CLR.B…SDSVRC(A4)�0�-->�Vr�CLR.B…SDSVSC(A4)�0�-->�Vs �BRA.L…OKRSP‹ELSE.S �BRA.L…INVRSP‹ENDI‰ENDI&‰IF.B†SDDCMD(A3)��#SDDCDISC�THEN.S$‹IF.B†SDDRSP(A2)��#SDDRUA�THEN.S)�MOVE.B„#SDSCRDM,SDSCST(A4)�RDM�-->�STATE �BRA.L…OKRSP‹ELSE.S �BRA.L…INVRSP‹ENDI‰ENDI#‰IF.B†SDDCMD(A3)��#SDDCXID�OR.B!“SDDCMD(A3)��#SDDCTEST�THEN.S‹MOVE.B„SDDCMD(A3),D0‹IF.B†D0��SDDRSP(A2)�THEN.S9�MOVE.L„A3,A1…If�response�=�command,�discard�xmit�buffer,�BSR.L…SOMEDISPOSE�MOVE.L„A1,SDSTHD(A4).�MOVE.L„A2,A1…Pass�the�response�to�application�BSR.L…SOMESEND �MOVE.L„A1,A2�BSR.L…SOMEFREE2�BRA.L…SDLCRQ„and�select�next�station�to�talk�with‹ELSE.S �BRA.L…INVRSP‹ENDI‰ENDI0‰BRA.L…DSPUI…All�others�go�to�DSPUI�for�handling‰PAGE /* May fall-thru to here from the previous page! ADSPNR„TST.W…SDDBCT(A2)�DATA�FIELD�ON�"RR"�"RNR"�OR�"REJ"�COMMAND?(‰BNE.L…INVRSP„*�IF�YES,�INVALID�RESPONSE**ˆTEST�FOR�A�VALID�Nr�COUNT*DSPNR1ƒCLR.L…D0 ‰CLR.L…D1 ‰CLR.L…D2$‰MOVE.B„SDDRSP(A2),D0�FETCH�Nr�COUNT‰LSR.B…#5,D0…*$‰MOVE.B„SDSVSC(A4),D1�FETCH�Vs�COUNT‰LSR.B…#1,D1…*-‰MOVE.B„SDSUKT(A4),D2�FETCH�#�TxMITTED�FRAMES ‰BEQ.S…DSPNR2„*�FRAMES�TxMITTED?9‰CMP.L…#0,A3…XMIT�I_FRMS�GONE�JUST�AFTER�A�PURGE?�3/21/836‰BEQ.S…DSPNR2„YES,�SAME�AS�IF�NO�I_FRAMES�SENT�3/21/833‰BTST.B„#0,SDDCMD(A3)�NO,�"I"�FRAME�ON�TxMIT�QUEUE? ‰BNE.S…DSPNR2/‰MOVE.B„SDDCMD(A3),D1�YES,�GET�Ns�COUNT�FROM�IT ‰LSR.B…#1,D1 ‰ADD.B…D2,D1 ‰AND.B…#7,D1DSPNR2ƒWHILE.BƒD0��D1�DO.S‹SUB.B…#1,D1…NEXT�Vs�COUNT ‹AND.B…#7,D1 #‹SUB.B…#1,D2…ALL�Vs�COUNTS�CHECKED?#‹BMI.L…INVRSP„YES,�INVALID�Nr�COUNT‰ENDW* Fall-thru to the next page‰PAGE3* NOTE: WE FALL-THRU TO HERE FROM THE PREVIOUS PAGE *"*ˆDISPOSE�OF�TXMIT�BUFFERS�TO�NR-1*&‰CLR.L…D1‰FETCH�Nr�COUNT�FROM�RESPONSE‰MOVE.B„SDDRSP(A2),D1 ‰LSR.B…#4,D1‰AND.B…#$0E,D1‰MOVE.B„D1,SDSVSC(A4)�Vs�=�Nr&‰MOVE.L„A3,D0…ANYTHING�IN�TxMIT�QUEUE? ‰BEQ.L…DSPRC1'DSPNR3A‚CLR.L…D0ˆTXMITTED�A�UI�COMMAND?‰MOVE.B„SDDCMD(A3),D0‰AND.B…#$EF,D0‰IF.B†D0��#SDDCUI�THEN.S‹BTST.L„#0,D0…I�FIELD? ‹BNE.L…DCRTX8‹TST.B…SDSUKT(A4)�YES,�UNACKNOWLEDGED�I�FRAMES�TxMITTED? ‹BEQ.L…DSPRC1‹AND.B…#$0E,D0ƒYES,�Nr�=�Ns? ‹CMP.B…D1,D0‹IF.B†D1��D0�THEN.S8�MOVE.B„SDDRSP(A2),D0�Nr�=�Ns,�IS�RESPONSE�RR,�RNR,�REJ?�AND.B…#$03,D0 �CMP.B…#1,D0 �BNE.S…DSPUI,�MOVE.L„A2,A1…YES,�DISPOSE�OF�RECEIVE�BUFFER�BSR.L…SOMEDISPOSE%�MOVE.L„A1,A2…END�OF�RECEIVE�BUFFERS? �MOVE.L„A1,D0,�BNE.L…HSKP9…No,�go�see�what�the�next�one�is>�CMP.B…#SDPTXQ,SDPTXF(A5)�Yes,�did�we�send�from�the�xmt�queue?'�BNE.L…DSPRC1„No,�go�finish�cleaning�up6�BRA.S…DSPUI…Yes,�discard�any�transmitted�"UI"�buffers‹ENDI‰ENDI/‰MOVE.L„A3,A1…Nr�<>�Ns,�DISPOSE�OF�TxMIT�BUFFER‰BTST.B„#4,SDDCMD(A3)‰IFˆ�THEN.S.‹BSR.L…SOMEDISPOSE�YES,�DISPOSE�OF�RCV�BUFFERS ‹MOVE.L„A1,A34‹CLR.B…SDSUKT(A4)�CLEAR�UNACKNOWLEDGED�I�FRAME�COUNT ‹BRA.L…DSPRC1‰ELSE.S‹BSR.L…SOMEDISPOSE ‹MOVE.L„A1,A3‹SUB.B…#1,SDSUKT(A4)‹BRA.S…DSPNR3A‰ENDI ‰PAGE*"*ˆAN�INVALID�RESPONSE�WAS�RECEIVED*DINVRSPƒMOVE.B„#$FF,SDSPWR(A4)„LET'S�ASSUME�THE�DEVICE�IS�POWERED�OFF**ˆDISPOSE�OF�UI�TXMIT�BUFFERS*&DSPUI„MOVE.L„A3,D0…END�OF�TxMIT�QUEUE?‰BEQ.L…DSPRC1„Yes,�out ‰CLR.L…D1ˆNo,‰MOVE.B„SDDCMD(A3),D1‰AND.B…#$EF,D1+‰CMP.B…#SDDCUI,D1�Did�we�send�a�UI�command? ‰BNE.S…DCRTX*‰MOVE.L„A3,A1…YES,�DISPOSE�OF�TXMIT�BUFFER)‰BTST.B„#4,SDDCMD(A3)�Poll/final�bit�set?‰IFˆ�THEN.S‹BSR.L…SOMEDISPOSE�No ‹MOVE.L„A1,A3 ‹BRA.S…DSPUI‰ENDI7‰BSR.L…SOMEDISPOSE�Yes,�also�dispose�of�receive�buffers ‰MOVE.L„A1,A3 ‰BRA.S…DSPRC1 ‰PAGE**ˆDECREMENT�TxMIT�RETRY�COUNTS*DCRTX„MOVE.L„A3,A1…*‰MOVE.B„SDSUKT(A4),D1�**DCRTX2ƒCMP.L…#0,A3…ALL�TxMIT�BUFFERS�GONE? ‰BEQ.S…DCRTX5"‰BTST.B„#0,SDDCMD(A3)�NO,�I�FIELD?‰IFˆ�THEN.S*‹TST.B…D1ˆYES,�UNACKNOWLEDGED�COUNT�CLEAR? ‹BEQ.S…DCRTX5‹SUB.B…#1,D1…YES,�DECREMENT�IT‰ENDI7‰TST.B…SDDRTC(A3)�NO,�DECREMENT�RETRY�COUNT�IF�NON-ZERO ‰BEQ.S…DCRTX4*‰SUB.B…#1,SDDRTC(A3)�DECREMENT�RETRY�COUNT‰BNE.S…DCRTX4„EXPIRED??‰MOVE.L„A3,A1…YES,�SEND�THIS�TxMIT�BUFFER�TO�APPL�PGM�AS�UNSENT>‰MOVE.B„#SDDSSTE,SDDSTS+1(A3)‚SET�RETRY�COUNTER�EXPIRED�STATUS$‰BTST.B„#$4,SDDCMD(A3)‚POLL�BIT�SET?‰IFˆ�THEN.S&‹BSR.L…SOMESEND�YES,�LAST�TXMIT�BUFFER4‹CLR.B…SDSUKT(A4)�CLEAR�UNACKNOWLEDGED�I�FRAME�COUNT ‹BRA.S…DCRTX5‰ENDI"‰BTST.B„#0,SDDCMD(A3)�NO,�I�FIELD?‰IFˆ�THEN.S2‹SUB.B…#1,SDSUKT(A4)�YES,�FIX�UNACKNOWLEDGED�COUNT‰ENDI‰BSR.L…SOMESEND%‰MOVE.L„A1,A3�FETCH�NEXT�TxMIT�BUFFER ‰BRA.S…DCRTX2 )DCRTX4ƒCLR.B…SDDERR(A3)�CLEAR�ERROR�FIELD$‰BTST.B„#$4,SDDCMD(A3)�POLL�BIT�SET? ‰BNE.S…DCRTX5-‰MOVE.L„SDDLNK(A3),A3�FETCH�NEXT�TxMIT�BUFFER ‰BRA.S…DCRTX2 +DCRTX5ƒMOVE.L„A1,A3ƒNEW�HEAD�OF�TxMIT�QUEUE*ˆBRA.S…DSPRC1„FALL-THRU ‰PAGE:* WARNING: WE MAY FALL-THRU TO HERE FROM THE PREVIOUS PAGE**ˆDISPOSE�OF�RCV�BUFFERS*3DSPRC1ƒMOVE.L„A3,SDSTHD(A4)�NEW�HEAD�OF�TxMIT�QUEUE.‰MOVE.L„A2,D0…ALL�RECEIVE�BUFFERS�DISPOSED�OF?‰BEQ.L…SDLCRQ„*‰MOVE.B„SDDERR(A2),D0‰IFˆ�THEN.S4‹IF.B†D0��#SDDENNR�AND.B�D0��#SDDEIFU�THEN.S?�MOVE.B„#$FF,SDSPWR(A4)�Bad�error,�assume�station�is�turned�off‹ENDI)‹TST.B…SDDSTS+1(A2)�REPORT�ERROR�TO�USER?‹BNE.S…DSPRC3„Yes,�go�tell�him+‹BRA.S…DSPRC5„NO,�JUST�FREE�THE�RCV�BUFFERS‰ENDIC‰MOVE.B„SDDRSP(A2),D0�IS�RESPONSE�FRMR,�RD,�DM,�RIM,�UI�OR�I�FIELD?‰AND.B…#$EF,D0ƒ*‰CMP.B…#SDDCUI,D0�*‰BEQ.S…DSPRC3„*‰CMP.B…#SDDRRD,SDDRSP(A2)�*‰BEQ.S…DSPRC3„*‰CMP.B…#SDDRDM,SDDRSP(A2)�*‰BEQ.S…DSPRC3„*‰CMP.B…#SDDRRIM,SDDRSP(A2) ‰BEQ.S…DSPRC3‰CMP.B…#SDDRFRMR,SDDRSP(A2)  ‰BEQ.S…DSPRC3 ‰BTST.L„#0,D0 ‰BNE.S…DSPRC5CDSPRC3ƒMOVE.L„A2,A1…YES,�SEND�RECEIVE�BUFFER�TO�APPLICATION�PROGRAM$‰BTST.B„#4,SDDRSP(A2)‚Final�bit�set?‰IFˆ�THEN.S‹BSR.L…SOMESEND‚NO ‹MOVE.L„A1,A2 ‹BRA.S…DSPRC1‰ENDI3‰BSR.L…SOMESEND‚YES,�ALSO�FREE�ALL�RCV�BUFFERS�LEFT ‰MOVE.L„A1,A2*DSPRC5ƒBSR.L…SOMEFREE‚FREE�ALL�RCV�BUFFERS0‰BRA.S…SDLCRQ„SELECT�NEXT�SDLC�SECONDARY�STATION ‰PAGE*(*ˆTHE�RESPONSE�WAS�VALID�FOR�THE�COMMAND**OKRSP„MOVE.L„A3,A1…DISPOSE�OF�TXMIT�BUFFER‰BSR.L…SOMEDISPOSE�*‰MOVE.L„A1,SDSTHD(A4)�*‰BSR.L…SOMEFREE�*=*ˆBRA.S…SDLCRQ„Fall�thru�and�select�next�station�to�talk�with ‰PAGE8* Warning: May fall-thru to here from the previous page!*#*ˆSET�THE�STATION'S�POLL�DELAY�TIME*%SDLCRQƒIF.B†SDSPWR(A4)��#0�THEN.S‹IF.L‡SDSTHD(A4)��#0�THEN.S<�MOVE.W…SDSTPN(A4),SDSCTD(A4)�Up,�no�tfc,�use�Power�On�Delay‹ELSE.S8�MOVE.W…SDSTTX(A4),SDSCTD(A4)�Up,�tfr,�use�Traffic�Delay‹ENDI‰ELSE.S3‹FAIL†501�Is�this�next�MOVE.B�correct�at�this�time?9‹MOVE.B„#SDSCBSY,SDSCST(A4)�Set�busy�state�to�poll�device‹IF.L†SDSTHD(A4)��#0�THEN.S?�MOVE.W„SDSTPF(A4),SDSCTD(A4)�Down,�no�tfc,�use�Power�Off�Delay‹ELSE.S:�MOVE.W„SDSTRT(A4),SDSCTD(A4)�Down,�tfc,�use�Re-Xmit�Delay‹ENDI‰ENDI+‰MOVE.L„A4,A0…SELECT�NEXT�SECONDARY�STATION‰BRA.L…SDLCSN1 .**********************************************/* END OF FILE 'FIX:48.SDLCPRI.FRMCNT.AI' *.**********************************************éé‰PAGE6******************************************************6* BEGINNING OF FILE 'FIX:48.SDLCPRI.INT7201.AI' *6****************************************************** INTRSRG‚MACROD‰MOVEM.Lƒ(A7)+,A1-A2/D0�Restore�Registers�Used�by�Interrupt�Handlers‰ENDM INTSVRG‚MACROA‰MOVEM.LƒA1-A2/D0,-(A7)�Save�Registers�Used�by�Interrupt�Handlers‰ENDM H*************************************************************************Æ*9*ˆSUBROUTINE:‚"SBSDLCFL"‚FLUSH�(PURGE)�A�TRANSMIT�QUEUE‡**ˆTRAP:ˆ"SDLCFL"©*.*ˆENTER:‚D1.B�=�SDLC�STATION�NUMBER�TO�FLUSH“**ˆRETURN:�CCR³**‘Z�set�BUFFERS�WERE�FLUSHED›*%*‘N�set�ILLEGAL�SDLC�STATION�NUMBER”*#*ˆREGISTERS�USED:ƒ0�1�2�3�4�5�6�7�**˜DƒP©* *˜A�U�U‹S�**œ|‹|_�stack–**œ|_____________�used—**Æ*H************************************************************************ SBSDLCFL RTS2RTE5SDLCFLƒBSR.L…FINDSCBƒFind�the�Secondary�Control�Block‰IFˆ�THEN.L?‹ANDI.B„#$F7,1(A7)�Return�Negative�Clear�(Legal�station�number)0‹ORI.B…#$04,1(A7)�And�Zero�Set�(Buffers�Flushed)+‹ORI.W…#$700,SR�SCB�Found,�MASK�INTERRUPTS!(‹ADD.W…#1,SDSHCFLS(A1)�Count�the�flushes/‹MOVE.L„SDSTHD(A1),A0�Find�his�transmit�buffers)‹MOVE.L„A2,-(A7)�Protect�A2�while�tracing‹BSR.L…GETRACE�Get�a�trace�row‹IFˆ�THEN.SE**********************************************************************�Trace�Entry�Format°*E**********************************************************************Ã*#*‚+0Ž+4Ž+8‚+9‚+10…+12�+13�+14�+15‚*E* +---------------+---------------+---+---+-------+---+---+---+---+ *6*�!†PC‡!�A(1st�Buffer)�!�#�!�S�!ƒ0ƒ!�C�!�R�!�D0!�D1!�*E* +---------------+---------------+---+---+-------+---+---+---+---+ **Ã**�PC�=�Program�Counter,­*A*�A(1st�Buffer)�=�Address�of�the�first�buffer�being�flushed,�or…*1*‘Zero�when�no�buffer(s)�is(are)�being�flushed,…**�#�=�Station's�Number,­* *�S�=�Station's�Current�State,¦**�0�=�Unused,·*7*�C�=�When�A(1st�Buffer)�<>�0,�Buffer's�Command�Byte,�* €7‰8‘ ™0¡1©8*�R�=�When�A(1st�Buffer)�<>�0,�Buffer's�Response�Byte,Ž*9*�D0�=�When�A(1st�Buffer)�<>�0,�Buffer's�1st�Data�Byte,�*9*�D1�=�When�A(1st�Buffer)�<>�0,�Buffer's�2nd�Data�Byte.�**Ã*E*********************************************************************�PEA‡*(PC)�If�we�get�one,�then)�MOVE.L„(A7)+,0(A2)�trace�our�PC�address,�MOVE.L„A0,4(A2)�A(1st�Buffer),)�MOVE.B„SDSSEC(A1),8(A2)�Station�address,9�MOVE.B„SDSCST(A1),9(A2)�His�current�state�(as�in�IOWA?),&�CLR.W…10(A2)�(Zero�fill�unused�bytes)�IF.L†#0��A0�THEN.S/�MOVE.B„SDDCMD(A0),12(A2)�1st�Buffer's�Command,#�MOVE.B„SDDRSP(A0),13(A2)�Response,#�MOVE.B„SDDDAT+0(A0),14(A2)�and�two.�MOVE.B„SDDDAT+1(A0),15(A2)�...�...�data�bytes�ELSE.S-�CLR.L…12(A2)�But�if�no�buffers,�store�zeroes�ENDI‹ENDI)‹MOVE.L„(A7)+,A2�Recover�A2�after�tracing‹IF.L†#0��A0�THEN.S-�CLR.L…SDSTHD(A1)�Make�all�buffers�disappear,.�BSR.L…SBPTFRML‚(return�them�to�the�free�pool)‹ENDI'‹MOVE.L„A1,A0…A0�=�A(SCB�being�flushed)‹MOVE.L„SDLCPCB,A1�A1�=�A(PCB)?‹IF.B†#SDPBTX��SDPBSY(A1)�AND.L�A0��SDPRRTA4(A1)�THEN.S$�IF.B†#SDPTXQ��SDPTXF(A1)�THEN.S;�MOVE.B„#NCW0SAB,NECCTL_B�Xmt'g�one�of�the�flushed�buffers,'�MOVE.B„#NCW0RG1,NECCTL_B�Abort�it,�and6�MOVE.B„#NCW1IRD+NCW1STV,NECCTL_B�turn�off�everything!�MOVEM.LƒA0-A6/D0-D2,-(A7)�MOVE.L„SDLCPCB,A64�MOVEM.LƒSDPRRTA0(A6),A0-A6�Restore�driver's�context�ADD.W…#1,SDSHCTOF(A4)�MOVE.L„SDPRCV(A5),A2,�BSR.L…SOMEFREE†Release�Rcv�Bfr�to�free�pool�LEA‡0,A2ŠNo�Rcv"�MOVE.L„A2,A3‰......�or�Xmt�Buffer0�MOVE.B„#$FF,SDSPWR(A4)�and�mark�station�as�DOWN$�BRA.L…SDLCRQˆNow�go�reset�its�timer�ENDI‹ENDI‰ELSE.S?‹ANDI.B„#$FB,1(A7)�Return�Zero�Clear�(Buffers�were�not�flushed);‹ORI.B…#$08,1(A7)�And�Negative�Set�(Illegal�station�number)‰ENDI‰RTE‘(UN-MASKS�INTERRUPTS) ‰PAGE!* OVERVIEW OF INTERRUPT VECTORING -* SIGNIFICANT CONTROL BLOCK AND AREA SETTINGS M* 1) The low-memory (0..3FF) interrupt vector which the NEC7201 uses contains)*„the�address�of�the�INT7201�routine,�andO* 2) The SDLC Primary Control Block (PCB) contains eight vectors, four for eachI*„side�of�the�NEC7201.‚B-side�vectors�(0..3)�in�the�PCB�are�maintained�byI*„the�SDLC�driver.‚A-side�vectors�(4..7)�are�all�the�same�however,�eitherE*„pointing�to�INT7201A�or�to�PORTAIO.‚INT7201A�is�used�when�no�A-sideB*„driver�exists,�PORTAIO�is�used�when�an�A-side�driver�is�present. * NEC7201 INTERRUPT VECTOR NOTES J* When no interrupt is pending in the NEC7201, the interrupt vector numberM*�register�(2B)�"rests"�at�vector�7.‚Note�that�vector�7�is�for�A-side�SpecialM*�Receive�Condition�Interrupts.‚The�difference�between�a�"resting"�and�"real"L* interrupt vector in register 2B is indicated in the A-side register 0, bitJ*�number�1:‚Where�this�bit�is�set�(1),�an�interrupt�is�pending.‚Where�thisO* bit is clear (0), no interrupt was pending, and the interrupt vector "rests".H* (Note that register 2B must be read before the pending bit is tested.) * INTERRUPT PROCESSING SEQUENCE L* When something interrupts using the low-memory interrupt vector designatedL*�as�the�NEC7201s�vector,�the�MPU�vectors�to�the�INT7201�routine.‚There,�theO* 7201's internal interrupt vector number is read from register 2B, and controlM* is passed via the corresponding vector in the SDLC PCB (note that vector #7@* will be used when the 7201 does not have a pending interrupt).O* Where a B-side interrupt was present (vector 0..3), we go to an SDLC routine.K* Where an A-side vector (4..7) was presented, we go to INT7201 or PORTAIO.J* For A-side interrupts, if no A-side driver has overwritten vectors 4..7,G* we go to INT7201A and acknowledge the interrupt, making it "go away".L* If an A-side driver exists, we go to PORTAIO w hich checks the pending flagL* in the 7201's A-side register 0, and thereby determines whether or not the* 7201 has a pending interrupt.N* Where a pending interrupt exists (must be an A-side interrupt), PORTAIO usesM* two SDLC PCB pointers to store the interrupt vector number as read from theN* 7201 (PORTAIO will right justify the vector in some cases), and then to jumpL*�to�some�other�address.‚(The�A-side�driver�has�stored�these�two�addresses.)O* Where no pending interrupt exists (i.e., the interrupt vector number read wasO* 4..7 [should have been #7, by the way], and the interrupt pending flag in theN* 7201's register 0 on the A-side was clear), the PORTAIO routine "assumes" anO* External Status change interrupt for the B-side (SDLC), and forces processing?* to the current SDLC External Status interrupt handling state.L*�This�"assumed"�External�Status�interrupt�is�questionable.‚As�we�don't�knowM* who interrupted (it is not the NEC7201), it is unclear what to do about it.‰PAGEH*************************************************************************Æ*9*ˆI.�S.�R.:‚"INT7201"‚NEC7201�Interrupt�Service�Routine‡**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*<*ˆVectors�through�Primary�Control�Block's�Indirect�Vectors†*6*ˆOffset�by�NEC7201's�Status�Affects�Vector�RegisterŒ**Æ*3*ˆSaves�Registers�D0.L,�A1.L,�&�A2.L�on�the�Stack�*+*˜A1.L�=�Address�of�Primary�Control�Block‡**Æ*H************************************************************************ "INT7201‚INTSVRG—SAVE�REGS�ON�STACK,‰CLR.W…D0’Read�the�NEC7201's�Vector�Register‰MOVE.B„#NCW0RG2,NECCTL_B‰MOVE.B„NECCTL_B,D01‰MOVE.L„SDLCPCB,A1Š(A1�=�A(Primary�Control�Block)0*ˆBTST†#0,TRACFLAG+1‡Should�interrupt�be�traced?*ˆIFˆ�THEN.S!*ŠBSR‡DLTRACE�Trace�the�interrupt*ˆENDIB‰MOVE.L„SDPVCT(A1,D0.W),A2‚Find�out�Where�To�Go�for�this�Interrupt‰JMP‡(A2)�And�Go�There! ‰PAGE I**************************************************************************Ç*'*ˆINT7201A�-�A-Side�Interrupt�Handlerœ**Ç*H*�An�A-Side�Interrupt�has�occurred,�or�something�other�than�an�NEC7201‚*I* interrupt has brought us here (in which case the NEC7201 has given us *F*�vector�#7).‚Either�way,�we�don't�want�the�nasty�little�sucker.‚So,‚*H*�if�the�NEC7201�really�did�cause�the�interrupt,�we�acknowledge�it�and‚*H*�thereby�make�the�interrupt�go�away.‚Otherwise,�we�simply�exit�in�the�*G*�hope�that�whatever�brought�us�here�won't�do�it�again�(as�we�have�noƒ*F*�idea�what�we�should�do�about�it�since�we�don't�know�what�"it"�is)!„**Ç*I************************************************************************* @INT7201A�BTST.B„#1,NECCTL_A‰Is�an�interrupt�pending�in�the�7201?1‰IFˆ�THEN.S‰Yes,�see�what�flavor�of�interrupt9‹IF.W†D0��#16�THEN.S�On�Transmitter�Empty�Interrupts,;�MOVE.B„#NCW0RTI,NECCTL_AƒReset�Transmitter�Empty�Interrupt‹ELSE.S7�IF.W†D0��#20�THEN.S�On�External�Status�Interrupts,9�MOVE.B„#NCW0REX,NECCTL_AƒReset�External�Status�Interrupt�ELSE.S8�IF.W†D0��#24�THEN.S�On�Receive�Character�Interrupts/‘TST.B…NECDAT_AŒRead�the�Char�(Clears�the�Intr)�ELSE.S5*�Otherwise,�on�Special�Receive�Condition�Interrupts,7‘MOVE.B„#NCW0ERR,NECCTL_AƒReset�Error�(Clears�the�Intr)�ENDI�ENDI‹ENDI?‹MOVE.B„#NCW0EOI,NECCTL_AƒWhatever,�make�the�interrupt�go�away!‰ENDI4*ˆBRA.S…INTEXIT�And�go�exit�from�handling�interrupts)* Fall-thru to the Interrupt Exit Routine APWR†EQU‡INT7201A‚On�Power�Up,�Reset�Any�Pending�A-Side�Interrupts ‰PAGE H*************************************************************************Æ*.*ˆ"INTEXIT"�-�NEC7201�Interrupt�Exit�Routine”**Æ*:*ˆNOTE:�All�interrupt�handling�procedures�must�come�hereˆ**ˆupon�completion.®**Æ*:*ˆChecks�for�"another"�pending�interrupt�in�the�NEC7201.ˆ*:*ˆIf�present,�we�vector�thru�the�Primary�Control�Block'sˆ*?*ˆIndirect�Vector�as�indicated�by�the�7201's�Vector�Register.ƒ*>*ˆIf�no�"other"�interrupt�is�pending ,�registers�are�restored„*?*ˆfrom�the�stack,�and�an�RTE�is�executed�thereby�returning�toƒ**ˆthe�interrupted�process.¦**Æ*;*ˆAssumes�Registers�D0.L,�A1.L,�&�A2.L�still�on�the�Stack‡**Æ*H************************************************************************ ?* Warning: We may "fall-thru" to here from the preceeding page. INTEXIT‚CLR.W…D0‰MOVE.B„#NCW0RG2,NECCTL_B9‰MOVE.B„NECCTL_B,D0‰Read�the�7201's�Vector�Register,�then9‰BTST.B„#1,NECCTL_A‰If�Interrupt�Pending�Flag�Is�Now�Set,4‰IFˆ�THEN.S‰Then�"another"�Interrupt�is�Present.8‹MOVE.L„SDLCPCB,A1ŠSo,�Set�A1�=�A(Primary�Control�Block)0*ŠBTST†#0,TRACFLAG+1‡Should�interrupt�be�traced?*ŠIFˆ�THEN.S!*ŒBSR‡DLTRACE�Trace�the�interrupt*ŠENDI:‹MOVE.L„SDPVCT(A1,D0.W),A2‚Regardless,�Fetch�"Where�To�Go")‹JMP‡(A2)�And�Go�Handle�the�new�Interrupt-‰ENDIšBut�if�no�"other"�Interrupt�is�present,#‰INTRSRG—Then�Restore�the�Registers'‰RTE›And�Resume�the�Interrupted�Process 0************************************************0* END OF FILE 'FIX:48.SDLCPRI.INT7201.AI' *0************************************************éééé4****************************************************4* BEGINNING OF FILE 'FIX:48.SDLCPRI.POLLQ.AI' *4**************************************************** SDLRSRG‚MACRO2‰MOVEM.Lƒ(A7)+,A0-A6/D0-D2�RESTORE�SAVED�REGISTERS‰ENDM SDLSVRG‚MACRO‰MOVEM.LƒA0-A6/D0-D2,-(A7)�*‰ENDM ‰SECTIONƒ9‰PAGEH*************************************************************************Æ*D*�SUBROUTINE:‚"PWRUP"�INITIALIZE�THE�NEC7201�CHIP�AT�POWER�UP�TIME„**Æ*+*�ENTER:‚A4.L�=�ADDRESS�OF�SDLC'S�SEGMENT�**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤* *‘D�U�U°**‘A�U�U�UƒP…S¤* *¡|__�stackœ**Æ*H************************************************************************ ‰NEXTWB,PWRUP„MOVE.B„#NCW0RCN,NECCTL_BƒCHANNEL�RESET‰MOVE.B„#NCW0RG2,NECCTL_A)‰MOVE.B„#NCW2RTS+NCW2PRI+NCW2BIN,NECCTL_A*‰MOVE.B„#NCW0RG2,NECCTL_BƒINTERRUPT�VECTOR‰MOVE.B„#0,NECCTL_B‰MOVE.B„#NCW0RG4,NECCTL_BƒMODE)‰MOVE.B„#NCW4C01+NCW4SDL+NCW4SME,NECCTL_B#‰MOVE.B„#NCW0RG7,NECCTL_BƒSDLC�FLAG‰MOVE.B„#SDLCFLAG,NECCTL_B3‰MOVE.B„#NCW0RG3,NECCTL_BƒENABLE�AUTO�ENABLE�OF�CTS!‰MOVE.B„#NCW3BT8+NCW3AUE,NECCTL_B‰IFEQ†RES7201-400‹MOVE.W„SR,-(A7)!‹ORI.W…#$0700,SRŠMask�Interrupts!5‹MOVE.L„#MVME400,A0ˆA0�=�Address�of�the�MVME400�board'‹BCLR.B„#REGSELEC,CTLPIA_A(A0)�Set�DDRAA‹MOVE.B„#WRT_LED+WRT_SEL,DATPIA_A(A0)�to�output�mid-two�bits�only:‹BSET.B„#REGSELEC,CTLPIA_A(A0)�Switch�now�to�Data�Reg�on�A=‹BSET.B„#WRT_SEL,DATPIA_A(A0)�Select�baud�rate�jumpers�Port�2(‹MOVE.B„DATPIA_A(A0),D0�and�read�them�in6‹ANDI.W„#$07,D0‹AND'ing�off�all�but�the�baud�rate�bitsB‹MOVE.B„V400BAUD(PC,D0.W),D0�and�get�the�4-bit�corresponding�value3‹MOVE.B„D0,-(A7)Šsaving�it�on�the�stack�temporarily,‹BCLR.B„#REGSELEC,CTLPIA_B(A0)�Now,�set�DDRB2‹MOVE.B„#%11111111,DATPIA_B(A0)�to�all �bits�output:‹BSET.B„#REGSELEC,CTLPIA_B(A0)�Switch�now�to�Data�Reg�on�B;‹MOVE.B„DATPIA_B(A0),D0�and�read�the�current�4-bit�settings.‹ANDI.B„#RATE1MSK,D0�drop�out�Port�2's�setting;‹OR.B†(A7)+,D0�and�OR�in�the�new�value�we�figured�out�above±8ºKÂIÊ0Ò;Ú-B‹MOVE.B„D0,DATPIA_B(A0)�and�output�the�new�rate�(Port�1�unchanged)#‹MOVE.W„(A7)+,SRŠUnmask�Interrupts!‰ENDC,‰LEA‡SDLCPR(PC),A0†FETCH�ADDRESS�OF�"SDLCPR"‰MOVE.L„#TIMCNST,A1'‰MOVE.W„#$4005,D1�INTERRUPT�LEVEL�->�D1‰MOVE.L„#DLC1,D2ŒI.D.�#�->�D2‰IFEQ†CHIPTYPE-68000 ‹TR0.RQPA‰ENDC‰IFNE†CHIPTYPE-68000 ‹TR0$.RQPA‰ENDC3‰RTS‘RETURN�(MUST�BE�A�2�BYTE�INSTRUCTION!)‚2/24/831‰ILLEGAL�DIE�IF�SBRQPA�RETURNS�ANY�ERROR!ˆ2/24/83 ‰IFEQ†RES7201-400"V400BAUDƒDC.B†15,14,13,12,10,7,5,2‰ENDC *3*„This�is�a�dummy�routine�to�satisfy�XREF�in�BUFMGT*‰XDEF†SDLCQXMT SDLCQXMT RTS‰PAGEH*************************************************************************Æ*9*ˆTRAP:‚"SDLCRCST"�THIS�ROUTINE�IS�A�"DUMMY"�TO�PROVIDEˆ*'*šCOMPATABILITY�FOR�BUFFER�MANAGEMENT‰**ˆSUBROUTINE:‚"SBSDLCRCST"¥**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ =SDLCRCST�BSR.S…SBSDLCRCST�TRAP�ENTRY�POINT,�DO�THE�SUBROUTINE+‰MOVE.W„SR,0(A7)‚REPLACE�THE�CONDITION�CODE"‰RTE‘SO�WE�GIVE�PROPER�RETURN�CODE +SBSDLCRCST�ILLEGAL‹Die,�should�not�be�used!‰PAGEH*************************************************************************Æ*0*ˆTRAP:‚"USRACK"ƒTRAP�SERVICE�ROUTINE�FOR�SDLC�**ˆSUBROUTINE:‚"SBUSRACK"§**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ 9USRACKƒBSR.S…SBUSRACK‚TRAP�ENTRY�POINT,�DO�THE�SUBROUTINE+‰MOVE.W„SR,0(A7)‚REPLACE�THE�CONDITION�CODE"‰RTE‘SO�WE�GIVE�PROPER�RETURN�CODE )SBUSRACK�ILLEGAL�Die,�should�not�be�used!‰PAGEH*************************************************************************Æ*0*ˆTRAP:‚"SDLCKL"ƒTRAP�SERVICE�ROUTINE�FOR�SDLC�*&*šTHIS�ROUTINE�EFFECTIVELY�KILLS�THEŠ*.*šSDLC�LINK�AND�CANCELS�PERIODIC�ACTIVATIONS‚**ˆSUBROUTINE:‚"SBSDLCKL"§**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤* *‘DƒU�U®**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ 9SDLCKLƒBSR.S…SBSDLCKL‚TRAP�ENTRY�POINT,�DO�THE�SUBROUTINE+‰MOVE.W„SR,0(A7)‚REPLACE�THE�CONDITION�CODE&‰RTE‘SO�WE�GIVE�THE�PROPER�RETURN�CODE @SBSDLCKL�MOVE.B„#NCW0RCN,NECCTL_B�CHANNEL�RESET�THE�NEC7201�CHIP2‰MOVE.W„#$8005,D1�DISCONTINUE�PERIODIC�ACTIVATIONS‰MOVE.L„#DLC1,D2‚*‰IFEQ†CHIPTYPE-68000 ‹TR0.RQPA‰ENDC‰IFNE†CHIPTYPE-68000 ‹TR0$.RQPA‰ENDC.‰RTS‘OK,�RETURN�(MUST�BE�A�2�BYTE�INSTRUCTION)1‰ILLEGAL�DIE�IF�SBRQPA�RETURNS�ANY�ERROR!ˆ2/24/83‰PAGEH*************************************************************************Æ*0*ˆTRAP:‚"SDLCQU"‚TRAP�SERVICE�ROUTINE�FOR�SDLC�*+*™THIS�ROUTINE�CHECKS�TRANSMIT�QUEUES�FOR†*0*™DATA�TO�TRANSMIT�BETWEEN�PERIODIC�ACTIVATIONS**ˆSUBROUTINE:‚"SDLCQUSB"§**Æ**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ SDLCQUSB RTS2RTESDLCQUƒSDLSVRG‰MOVE.L„SDLCPCB,A5‰ADD.W…#1,SDPHCQUS(A5) ‰MOVE.W„SR,D0%‰AND.W…#$0700,D0‹AT�LEAST�AT�LEVEL�5?‰IF.W†D0��#$0500�THEN.S ‹MOVE.W„SR,D0‹AND.W…#$F8FF,D0‹No,-‹OR.W†#$0500,D0‹assert�we�are�now�at�level�5!.‹MOVE.W„D0,SR�(old�SR�and�intr�level�on�stack)‰ENDI‰BRA.S…SDLCPR3‰PAGEH*************************************************************************Æ*4*ˆTRAP:‚"SDLCTTMOUT"‚TRAP�SERVICE�ROUTINE�FOR�SDLCŒ*,*�THIS�ROUTINE�IS�ENTERED�WHEN�THE�RECEIVE�**�TIMEOUT�EXPIRESš**ˆSUBROUTINE:‚"SDLCTMO UT"¦**Æ**Æ*#*�REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¤**‘D´**‘A�S¤* *¡|__�stackœ**Æ*H************************************************************************ SDLCTMOUT‚RTS2RTE%SDLCTTMOUT�SDLSVRG�SAVE�ALL�USER�REGS+‰MOVE.L„SDLCPCB,A6�RESTORE�REGS�FROM�P.C.B.‰MOVEM.LƒSDPRRTA0(A6),A0-A6‰ADD.W…#1,SDSHCRTO(A4)…3/2/83‰BRA.L…RECEITOƒRECEIVE�TIMEOUT ‰PAGE H*************************************************************************Æ*>*ˆTRAP:‚"SDLCPR"‚TRAP�ROUTINE�WHICH�IS�ENTERED�WHEN�PERIODIC‚**™TIMER�RUNS�DOWNž**ˆSUBROUTINE:‚"SDLCPRSB"§**Æ*0*ˆENTER:‚D0.L�=�#�INTERVALS�WHICH�HAVE�ELAPSED‘**�D1.L�=�ACTIVATION�I.D. **Æ*C*�WARNING:‚THIS�SECTION�OF�CODE�RUNS�AT�INTERRUPT�LEVEL�FIVE�(5).…*C*�HOWEVER,�WHEN�WE�ENTER�HERE�AFTER�COMPLETING�A�TRANSACTION�WITH†*F*�A�SECONDARY�STATION,�WE�ARE�AT�"FUNNY�LEVEL�5"�-�I.E.,�WE�SUFFEREDƒ*E*�A�LEVEL�SIX�(6)�INTERRUPT,�HANDLED�IT,�AND�THEN�LOWERED�THE�LEVEL„*E*�TO�FIVE.‚AS�A�RESULT,�WE�MAY�HAVE�INTERRUPTED�OURSELVES.‚FOR�THIS‚*G*�REASON,�THE�VARIABLE�"SDPBSY"�IS�USED�TO�ALLOW�ACCESS�TO�THE�"START‚*D*�NEW�WORK"�PORTIONS�OF�THIS�IMPLEMENTATION.‚WHEN�THIS�VARIABLE�IS„*E*�SET�TO�"NOT�BUSY",�THEN�AND�ONLY�THEN�CAN�WE�LOOK�FOR�NEW�WORK�TO„*G*�BE�INITIATED.‚WHEN�WE�ARE�NOT�"NOT�BUSY"�(I.E.,�WE�ARE�BUSY�SENDING�*E*�OR�RECEIVING,�OR�WHATEVER)�WE�CAN�ONLY�DECREMENT�THE�TIMER�VALUES„*F*�IN�THE�SECONDARY�CONTROL�BLOCKS,�AND�NO�MORE.‚LASTLY,�BECAUSE�EVEN‚*D*�THIS�COULD�BE�"INTERRUPTED"�BY�OURSELVES,�WE�MUST�HANDLE�A�TIMER…*G*�VALUE�WHICH�GOES�TO�LESS�THAN�ZERO�(I.E.,�WE�COMMITTED�TO�DECREMENT‚*H* A TIMER, WERE INTERRUPTED AND ZEROED THAT COUNTER, AND THEN RETURNED *2*�TO�SUBTRACT�ONE,�LEAVING�THAT�COUNT�NEGATIVE).—**Æ**�ED�SKINNER,�MARCH�2,�1983¬**Æ*H************************************************************************ SDLCPRSB RTS2RTESDLCPRƒSDLSVRG‰MOVE.L„#0,A1…SET�UP�REGISTERS‰MOVE.L„SDLCPCB,A5�*‰MOVE.L„SDPFSEC(A5),A0†**<*ˆDECREMENT�THE�CURRENT�TIME�DELAY�OF�ALL�SECONDARY�STATIONS$*‰AND�SELECT�THE�1ST�ONE�THAT'S�ZERO* ‰WHILE.BƒSDSSEC(A0)��#0�DO.S‹IF.W†SDSCTD(A0)��#0�THEN.S2�SUB.W…D0,SDSCTD(A0)�Timer�:=�Timer�-�Elapsed_Time‹ENDI<‹ADD.L…#SDSLNG,A0�Thusly�update�ALL�Secondary�Control�Blocks‰ENDW* Fall-thru to the next page‰PAGE:* NOTE: MAY BE FALLING-THRU TO HERE FROM THE PREVIOUS PAGE F* NOTE: ENTER HERE FROM SDLCQUSB - SOMEONE HAS ENQUEUED AN XMIT BUFFER FSDLCPR3‚MOVE.L„SDPFSEC(A5),A0�Are�we�NOT�"NOT�BUSY"�(ie,�are�we�busy?)$‰IF.B†SDPBSY(A5)��#SDPBNB�THEN.S‹SDLRSRG�Yes,�exit‹RTE‰ENDI‰PAGE*1*ˆSELECT�THE�1ST�SCB�WHOSE�TIME�DELAY�IS�NOW�ZERO*?SDLCSLƒWHILE.BƒSDSSEC(A0)��#0�AND.W�SDSCTD(A0)��#0�DO.S,SDLCSN1„ADD.L…#SDSLNG,A0�Advance�to�next�SCB‰ENDW‰IF.B†SDSSEC(A0)��#0�THEN.S<‹MOVE.B„#SDPBNB,SDPBSY(A5)�End�of�list,�set�SDLC�to�NOT�BUSY‹SDLRSRG�And�exit‹RTE‰ENDI‰MOVE.L„A0,A4…A4�=�A(SCB)(‰MOVE.B„#SDPBFC,SDPBSY(A5)�set�SDLC�BUSY* Fall-Thru to next page‰PAGE7* WARNING: MAY FALL-THRU TO HERE FROM THE PREVIOUS PAGE*0* A4 = CURRENT SECONDARY'S CONTROL BLOCK ADDRESS.* A5 = CURRENT PRIMARY'S CONTROL BLOCK ADDRESS*.*ˆA�SECONDARY�CONTROL�BLOCK�HAS�BEEN�SELECTED,*ˆDetermine�what�to�send.*3‰CMP.B…#SDSCBSY,SDSCST(A4)�SECONDARY�IN�BUSY�STATE?‰BEQ.S…SDLCPR5ƒ*)‰TST.L…SDSTHD(A4)�NO,�SOMETHING�TO�TXMIT?‰BNE.S…SDLCPR6ƒ*=SDLCPR5‚BSR.L…SBGTFRIR‚NO,�FETCH�A�RCV�BUFFER�&�TXMIT�AN�"RR"-‰BEQ.S…SDLCPR5B‚GOT�ONE�AND�IT'S�NOT�THE�LAST‰IFˆ�THEN.S6‹MOVE.B„#SDPBNB,SDPBSY(A5)�Didn't�get�one,�go�NOT�BUSY‹SDLRSRG�And�exit‹RTE‰ENDI!* GOT ONE, BUT IT'S THE VERY LASTASDLCPR5A�MOVE.B„#SDDRRNR+$10,SDDCMD(A3)�YES,�SET�AN�"RNR"�COMMAND‰BRA.S…SDLCPR5C #*ˆA3�=�BUFFER�CONTROL�BLOCK�ADDRESS;SDLCPR5B�MOVE.B„#SDDRRR+$10,SDDCMD(A3)�SEND�AN�"RR"�COMMAND?SDLCPR5C�MOVE.L„A3,SDPRCV(A5)‚*�(TxMIT�FROM�THE�RECEIVE�BUFFER)‰MOVE.B„#SDPTRQ,SDPTXF(A5)�*�**‰MOVE.W„SDPRLG(A5),SDDBCT(A3)�*�BYTE�COUNT‰C LR.W…SDDSTS(A3)�*�STATUS‰CLR.B…SDDERR(A3)�*�SDLC�ERROR$‰CLR.B…SDDRTC(A3)�*�SDLC�RETRY�COUNT.‰MOVE.B„SDSSEC(A4),SDDSEC(A3)�*�STATION�NUMBER‰BRA.L…TRANSMTƒ*�*‰PAGEH* NOTE: ED SKINNER, 2/24/83 - WHEN WE HAVE A "SNRM" TO SEND, WE ACTUALLYI*�PERFORM�THE�FOLLOWING:‚1)�TRANSMIT�A�"RNR"�COMMAND�AND�RECEIVE�A�"GOOD"H*�RESPONSE.‚THIS�IS�DONE�SO�THE�REMOTE�STATION�WILL�KNOW�HOW�MANY�OF�HISH* INFORMATION FRAMES THAT WE HAVE RECEIVED, THEREBY AVOIDING DUPLICATIONH*�OF�FRAMES.‚WE�MUST�GET�A�"GOOD"�RESPONSE�TO�THE�RNR�BEFORE�SENDING�THEH* SNRM SO THAT WE KNOW HE GOT THE RNR OK, AND THEREFORE NOW KNOWS OUR NrI*�VALUE.‚(BY�A�"GOOD"�RESPONSE,�I�MEAN�A�RECEIVED�REPLY�OF�ANY�KIND�WHICHJ* WAS RECEIVED WITHOUT ANY ERRORS - DOES AN Ns ERROR COUNT? I DON'T KNOW!)D* ONCE WE'VE RECEIVED A "GOOD" REPLY, WE CAN THEN TRANSMIT THE SNRM. 6SDLCPR6‚MOVE.L„SDSTHD(A4),A3�WE�HAVE�SOMETHING�TO�TXMT3‰CMP.B…#SDDCSNRM,SDDCMD(A3)�"SNRM"�COMMAND?Ž9/14/82&‰BNE.S…SDLCPR6C‚*�BRANCH�IF�NOš9/14/829‰CMP.B…#SDSTRN,SDSTXF(A4)�YES,�TXMITTED�AN�"RNR"?ˆ2/23/83'‰BEQ.S…SDLCPR6C‚*�BRANCH�IF�YES™9/14/82?‰BSR.L…SBGTFRIR‚NO,�FETCH�A�RCV�BUFFER�&�TXMIT�AN�"RNR"�9/14/825‰BEQ.S…SDLCPR5A‚GOT�ONE�AND�IT'S�NOT�THE�LAST‹9/14/82‰IFˆ�THEN.S6‹MOVE.B„#SDPBNB,SDPBSY(A5)�Didn't�get�one,�go�NOT�BUSY‹SDLRSRG�And�exit‹RTE‰ENDI"* WE JUST GOT THE VERY LAST BUFFER)‰BRA.S…SDLCPR5A‚TRANSMIT�AN�"RNR"—9/14/82 "SDLCPR6C�MOVE.B„#SDPTXQ,SDPTXF(A5)‰MOVE.L„A3,-(A7),‰BSR.L…SBGTFRIR‚Get�a�buffer�to�receive�into‰IFˆ�THEN.S:‹MOVE.W„SDPRLG(A5),SDDBCT(A3)�Ok,�Prepare�it�for�later�use‹CLR.W…SDDSTS(A3)�STATUS‹CLR.B…SDDERR(A3)�SDLC�ERROR‹MOVE.L„A3,SDPRCV(A5)‹MOVE.L„(A7)+,A3)‹BTST.B„#0,SDDCMD(A3)�I�Frame�to�be�sent?‹IFˆ�THEN.S4�CLR.B…SDSUKT(A4)�Yes,�zero�the�number�of�frames�out‹ENDI‰ELSE.S.‹MOVE.L„(A7)+,A0�Absolutely�no�buffers�at�all,-‹MOVE.B„#SDPBNB,SDPBSY(A5)�Set�SDLC�not�busy,‹SDLRSRG�And�exit‹RTE‰ENDI$‰BRA.L…TRANSMTƒGo�start�transmitting .**********************************************.* END OF FILE 'FIX:48.SDLCPRI.POLLQ.AI' *.**********************************************é‰PAGE6******************************************************6* BEGINNING OF FILE 'FIX:48.SDLCPRI.RECEIVE.AI' *6****************************************************** H*************************************************************************'*ˆMODULE:‚"RECEIVE"�RECEIVE�SDLC�FRAMES*-*ˆENTER:‚A5.L�=�PRIMARY�CONTROL�BLOCK�ADDRESS(*�A4.L�=�SECONDARY�CONTROL�BLOCK�ADDRESS*9*ˆENTRY�ASSUMES�A0-A6/D0-D7�HAVE�BEEN�PUSHED�ON�THE�STACK5*–AND�ENTRY�WAS�THROUGH�EXCEPTION�(TRAP�OR�INTERRUPT)*>*ˆEXIT:‚"RECEIFB"‚SDLC�RESPONSE�WITH�FINAL�BIT�SET�CAUSED�EXIT'*�"RECEITO"‚RECEIVE�TIMEOUT�CAUSED�EXIT3*�"RECEILB"‚THE�FREE�QUEUE�HAS�ONLY�ONE�BUFFER�LEFT9*�"RECEIEE"‚AN�EXCESSIVE�NUMBER�OF�RCV�ERRORS�CAUSED�EXIT*!*ˆREGISTERS�USED:ƒ0�1�2�3�4�5�6�7*˜D�U*˜A�U�U�U�U�P�PƒS* |ƒ|ƒ|__�stack* |ƒ|______�preserved* |__________�used*#*ˆEXITS�TO�EXTERNALLY�DEFINED�LABEL&*ŽWITH�A0-A6/D0-D7�PUSHED�ON�THE�STACK&*ŽAND�ASSUMES�FINAL�EXIT�WILL�BE�"RTE"*H************************************************************************ ?RECEIVE‚MOVE.B„#SDPBRC,SDPBSY(A5)‚Mark�us�as�busy�receiving�now ‰ADD.W…#1,SDSHCRCV(A4)…3/2/83 <‰LEA‡RCVSTSEI(PC),A0…and�set�interrupt�vectors�for�receiving‰MOVE.L„A0,SDPVCT2(A5)‰LEA‡RCVST1(PC),A0‰MOVE.L„A0,SDPVCT3(A5)‰LEA‡RCVSTS(PC),A0‰MOVE.L„A0,SDPVCT4(A5) 5‰MOVE.L„SDPRCV(A5),A3‡Find�the�buffer�to�receive�into6‰LEA‡SDDDAT(A3),A2‡A2�=�A(data�area�within�the�buffer)(‰MOVE.L„#0,A1�(Zero�the�high�word�of�A1)‰MOVE.W„SDPRLG(A5),A1‡an d6‰MOVE.W„A1,SDDBCT(A3)‹store�maximum�byte�count‚2/24/83:‰MOVE.B„SDSRRT(A4),SDSCSE(A4)�Initialize�the�error�counter.‰CLR.B…SDDERR(A3)ŠClear�the�error�flagŠ2/24/83B‰MOVEM.LƒA0-A6,SDPRRTA0(A5)‚Save�regs�for�interrupt�handlers�usage9‰MOVE.W„#-1,SDPRBCT(A5)…make�the�count�field�"bad"„3/8/83 ‰OR.W†#$700,SRŒMask�interrupts2‰MOVE.B„#NCW0RG6,NECCTL_B„Load�the�station�address0‰MOVE.B„SDSSEC(A4),NECCTL_B‚We�are�interested�in;‰MOVE.B„#NCW0REX+NCW0RG1,NECCTL_B�EXT�&�RCV�CHAR�INT�ENABLEâ:ëBóKûG4 :#)‰MOVE.B„#NCW1IRX+NCW1EXI+NCW1STV,NECCTL_B$‰MOVE.B„#NCW0RG3,NECCTL_B„RCV�ENABLE;W3TOTAL‚EQU‡NCW3BT8+NCW3AUE+NCW3EHU+NCW3CRC+NCW3ADS+NCW3RXE‰MOVE.B„#W3TOTAL,NECCTL_B!‰MOVE.B„#NCW0RG5,NECCTL_B„SET�DTR‰MOVE.B„#NCW5DTR,NECCTL_B5‰MOVE.B„#NCW0RTX,NECCTL_B„ENABLE�INT�ON�NEXT�RCV�CHAR!‰MOVE.B„#NCW0RTC+NCW0REX,NECCTL_B '‰BSR.L…SOMETOUT‚TRIGGER�RECEIVE�TIMEOUT ‰SDLRSRG—Restore�all�registers,‰INTSVRG—Then�save�only�the�"interrupt"�ones‰BRA.L…INTEXIT ‰PAGE*#* External Status Interrupt Handler*I*�NOTE:‚THIS�STATE�IS�USED�WHEN�AN�EXTERNAL�STATUS�INTERRUPT�OCCURS�PRIORB*ˆTO�RECEIVING�THE�FIRST�CHARACTER�OF�A�RECEIVE�FRAME.‚DURING�THISF*ˆPERIOD�(BEFORE�WE�BEGIN�RECEIVING�A�FRAME)�WE�IGNORE�EXTERNAL�STATUSE*ˆINTERRUPTS.‚WE�DON'T�CARE�ABOUT�RECEIVE�ABORTS�AND/OR�CLEAR�TO�SENDC*ˆAND/OR�DATA�CARRIER�DETECT�STATE�CHANGES�WHEN�WE�ARE�NOT�ACTUALLY*ˆRECEIVING�A�FRAME. 1RCVSTSEI�MOVE.B„NECCTL_B,D0ŠGET�THE�CHIP'S�STATUS*œIGNORE�RECEIVE�ABORT,*œHUNT�MODE�CHANGES,*œCLEAR�TO�SEND�CHANGES,�AND*œDATA�CARRIER�DETECT�CHANGES./‰MOVE.B„#NCW0REX,NECCTL_B�RESET�EXTERNAL�STATUS.‰MOVE.B„#NCW0EOI,NECCTL_A�AND�END�OF�INTERRUPT‰BRA.L…INTEXIT‰PAGE*#* External Status Interrupt Handler**1*ˆVECTORED�STATE�TO�PROCESS�EXT/STATUS�INTERRUPTS*%RCVSTEƒMOVE.B„NECCTL_B,D0�SDLC�ABORT?‰BTST.L„#7,D0…*‰BNE.S…RCVSTE1ƒ*,‰BTST.L„#3,D0…NO,�DataCarrierDetect�DROPPED?‰BEQ.S…RCVSTE2ƒ*4‰MOVE.B„#NCW0REX,NECCTL_B�NO,�RESET�INTERRUPT�&�EXIT‰MOVE.B„#NCW0EOI,NECCTL_A�*‰BRA.L…INTEXIT‡* 7RCVSTE1‚MOVE.B„#NCW0REX,NECCTL_B„RESET�INTERRUPT�&�EXIT‰MOVE.B„#NCW0EOI,NECCTL_A�*3RCVSTE1A�INTRSRG“LET'S�SAVE�ALL�THE�USERS'�REGS�NOW ‰SDLSVRG“*‰MOVE.L„SDLCPCB,A6�RESTORE�REGS‰MOVEM.LƒSDPRRTA0(A6),A0-A6�*3‰MOVE.B„#SDDEABT,SDDERR(A3)„SET�SDLC�ABORT�OCCURRED‰ADD.W…#1,SDSHCRAB(A4)…3/2/83‰BRA.L…RCVSTSF�*   7RCVSTE2‚MOVE.B„#NCW0REX,NECCTL_B„RESET�INTERRUPT�&�EXIT‰MOVE.B„#NCW0EOI,NECCTL_A�*+‰INTRSRG“LET'S�SAVE�ALL�THE�USERS'�REGS�NOW ‰SDLSVRG“*‰MOVE.L„SDLCPCB,A6�RESTORE�REGS‰MOVEM.LƒSDPRRTA0(A6),A0-A6�*<‰MOVE.B„#SDDEABT,SDDERR(A3)„ASSUME�AN�ABORT�OCCURREDƒ2/24/83‰ADD.W…#1,SDSHCRDD(A4)…3/2/83‰BRA.L…RCVSTSE�* ‰PAGE *%* Receive Character Interrupt Handler**2*ˆVECTORED�STATE�TO�PROCESS�1ST�RCV�CHAR�AVAILABLE*�THEN.S0‹MOVE.L„SDPRRTA2(A1),A2…More�may�be�received�OK,5‹MOVE.B„NECDAT_B,(A2)+‡Store�received�byte�into�buffe2‹MOVE.L„A2,SDPRRTA2(A1)…Save�updated�data�address.‰ELSE.S9‹LEA‡RCVST4(PC),A2‡Buffer�is�full,�better�by�1st�FCS�byte<‹MOVE.L„A2,SDPVCT3(A1)†Use�BUFFER�OVERRUN�vector�if�rcv�more2‹MOVE.B„NECDAT_B,D0Šand�discard�1st�FCS�byte�(hope‰ENDI‰MOVE.B„#NCW0EOI,NECCTL_A‰BRA.L…INTEXIT ‰PAGE *%* Receive Character Interrupt Handler**+*ˆVECTORED�STATE�TO�PROCESS�OVERRUN�BUFFERS*2RCVST4ƒMOVE.L„SDPRRTA3(A1),A2�BUFFER�OVERRUN�ERROR‰MOVE.B„#SDDERBO,SDDERR(A2)1‰MOVE.B„NECDAT_B,D0�REMOVE�CHARACTER�FROM�NEC7201‰MOVE.L„SDPRRTA4(A1),A2…3/2/83‰ADD.W…#1,SDSHCROB(A2)…3/2/83‰MOVE.B„#NCW0EOI,NECCTL_A‰BRA.L…INTEXIT ‰PAGE *-* Special Receive Condition Interrupt Handler**2*ˆVECTORED�STATE�TO�PROCESS�SPECIAL�RCV�CONDITIONS*?RCVSTSƒMOVE.B„NECDAT_B,D0‚REMOVE�2ND�CRC�CHARACTER�FROM�NEC7201+‰INTRSRG“LET'S�SAVE�ALL�THE�USERS'�REGS�NOW‰SDLSVRG‰MOVE.L„SDLCPCB,A6�RESTORE�REGS‰MOVEM.LƒSDPRRTA0(A6),A0-A64‰MOVE.B„#NCW0RG1,NECCTL_B�Get�Register�1�Information‰MOVE.B„NECCTL_B,D03‰MOVE.B„#NCW0ERR,NECCTL_B�(reset�special�interrupt)!‰MOVE.B„#NCW0RTC+NCW0RTX,NECCTL_B‰MOVE.B„#NCW0EOI,NECCTL_A )‰MOVE.L„A2,-(A7)ŒProtect�A2�while�tracing‰BSR.L…GETRACE�Get�a�trace�row‰IFˆ�THEN.SE**********************************************************************�Trace�Entry�Format°*E**********************************************************************Ã*'*‚+0Ž+4Ž+8‚+9‚+10�+11�+12�+13�+14�+15‚*E* +---------------+---------------+---+---+---+---+---+---+---+---+ *:*�!†PC‡!�A(Rcv�Buffer)�!�#�!�S�!�C�!�R�!�D0!�D1!�E�!�R1!�*E* +---------------+---------------+---+---+---+---+---+---+---+---+ **Ã**�PC�=�Program�Counter,­*8*�A(Rcv�Buffer)�=�Address�of�the�buffer�just�received,Ž**�#�=�Station's�Number,­* *�S�=�Station's�Current�State,¦**�C�=�Buffer's�Command�Byte,¨**�R�=�Buffer's�Response�Byte,§* *�D0�=�Buffer's�1st�Data�Byte,¦* *�D1�=�Buffer's�2nd�Data�Byte,¦*!*�E�=�Buffer's�Error�Code�Byte,¥*(*�R1�=�NEC7201�Read�Register�One�Byte.ž**Ã*E*********************************************************************,‹PEA‡*(PC)�If�we�get�a�trace�row,�then�trace#‹MOVE.L„(A7)+,0(A2)‰our�PC�address,‹MOVE.L„A3,4(A2)ŒA(Rcv�Buffer),)‹MOVE.B„SDSSEC(A4),8(A2)„Station�address,+‹MOVE.B„SDSCST(A4),9(A2)„His�current�state,0‹MOVE.B„SDDCMD(A3),10(A2)ƒCommand�Byte�(if�any),(‹MOVE.B„SDDRSP(A3),11(A2)ƒResponse�Byte,%‹MOVE.B„SDDDAT+0(A3),12(A2)�First�and.‹MOVE.B„SDDDAT+1(A3),13(A2)�Second�data�bytes,.‹MOVE.B„SDDERR(A3),14(A2)ƒError�code�byte,�and-‹MOVE.B„D0,15(A2)‹Register�1�from�the�NEC7201‰ENDI)‰MOVE.L„(A7)+,A2ŒRecover�A2�after�tracing $‰BTST.L„#7,D0…End�of�Frame�detected?‰BEQ.S…RCVSTSA‰BTST.L„#6,D0…Yes,�FCS�error?‰IFˆ�THEN.S=‹MOVE.B„#SDDECRC,SDDERR(A3)�Yes,�post�the�error�in�the�buffer‹ADD.W…#1,SDSHCRCR(A4)…3/2/83‰ENDI&RCVSTSA‚BTST.L „#5,D0…receiver�overrun?‰IFˆ�THEN.S6‹MOVE.B„#SDDERCU,SDDERR(A3)�Yes,�post�it�in�the�buffer‹ADD.W…#1,SDSHCROR(A4)…3/2/83‰ENDI,‰CMP.B…#SDDERTO,SDDERR(A3)�Receive�time-out?0‰BEQ.L…RECEITO�Yes,�depart�from�here�completely!,‰TST.B…SDDERR(A3)ŠAny�error�detected�so�far?‰IFˆ�THEN.S/‹CMP.B…#SDDERBO,SDDERR(A3)�Yes,�frame�too�long?1‹BNE.L…RCVSTSE�No,�just�ignore�the�received�frame(‹TST.B…SDSCSE(A4)ŠYes,�any�retries�left?-‹BNE.L…RCVSTSE’Yes,�ignore�the�received�frame7* When a Buffer Overrun occurs and no retries are left,J* the overlength frame is passed to the application with the error posted.L* This allows someone to complain about these "big" frames we are receiving.‰ENDI9‰MOVE.W„A1,D0…Calculate�how�many�bytes�are�in�the�buffer,5‰ADD.W…#1,D0…Adding�one�for�1st�FCS�character�overrun‰SUB.W…D0,SDDBCT(A3)C‰CMP.W…#-1,SDDBCT(A3)�Is�the�frame�too�short?�(LT�32�bits?)�8/27/82‰IFˆ�THEN.S8‹MOVE.B„#SDDEIFU,SDDERR(A3)�Yes,�post�the�error‰10/13/82‹ADD.W…#1,SDSHCR32(A4)…3/2/83‹BRA.L…RCVSTSF©10/13/82‰ENDI,‰BTST.B„#0,SDDRSP(A3)‚No,�was�it�an�I�frame?$‰BNE.S…RCVSTSDƒOut�if�not�an�I�frame‰IFEQ†IFRMBCT-YES3‹MOVE.W„SDPRBCT(A5),D0‚I�Frame's�Length�as�Claimed?‹CMP.W…SDDBCT(A3),D0‹BNE.S…RCVSTSB6ˆNo,�branch‰ENDC=‰CMP.B…#SDPTRN,SDPTXF(A5)‚Yes,�did�we�just�send�an�RNR�frame?0‰BNE.S…RCVSTSB3ŒNo,�it's�OK�to�rcv�I�frames�thenHRCVSTSB6�MOVE.B„#SDDEIFU,SDDERR(A3)�Yes,�station�shouldn't�have�sent�it!‰ADD.W…#1,SDSHCRLN(A4)…3/2/83‰BRA.S…RCVSTSB4 ARCVSTSB3�MOVE.B„SDDRSP(A3),D0‡NO,�DOES�Vr�=�Ns�in�received�frame? ‰ASL.B…#4,D0‰AND.B…#$E0,D0‰CMP.B…SDSVRC(A4),D0‰BEQ.S…RCVSTSC:RCVSTSB5�MOVE.B„#SDDENNR,SDDERR(A3)�NO,�SET�Vr�<>�Ns�ERROR‰ADD.W…#1,SDSHCRNR(A4)…3/2/83ARCVSTSB4�BTST.B„#4,SDDRSP(A3)‡Is�the�received�poll/final�bit�set?‰BEQ.S…RCVSTSE-‰BRA.L…RECEIFB�YES,�EXIT�(RECEIVED�FINAL�BIT) 5RCVSTSC‚ADD.B…#$20,SDSVRC(A4)…Vr�=�Ns,�so�Vr�=�Vr�+�1‰AND.B…#$E0,SDSVRC(A4)@RCVSTSD‚BTST.B„#4,SDDRSP(A3)‡Is�the�received�poll/final�bit�set?‰BEQ.S…RCVSTSD1-‰BRA.L…RECEIFB�YES,�EXIT�(RECEIVED�FINAL�BIT) �A2 ‰ADD.L…A3,A2#‰MOVE.L„#0,A1…BUFFER'S�LENGTH�->�A1‰MOVE.W„SDPRLG(A5),A1 ‰MOVE.W„A1,SDDBCT(A3)�BYTE�COUNT"‰CLR.B…SDDERR(A3)„CLEAR�SDLC�ERROR%‰MOVEM.LƒA0-A6,SDPRRTA0(A5)�SAVE�REGS2‰LEA‡RCVST1(PC),A0‡VECTORED�STATE�FOR�1ST�RCV�CHAR‰MOVE.L„A0,SDPVCT3(A5)*‰LEA‡RCVSTSEI(PC),A0…AND�IGNORE�EXT�STATUS‰MOVE.L„A0,SDPVCT2(A5)7‰MOVE.W„#-1,SDPRBCT(A5)…MAKE�COUNT�FIELD�INVALID†3/8/83‰ADD.W…#1,SDSHCRRS(A4)…3/2/835‰MOVE.B„#NCW0RG3,NECCTL_BƒRe-enable�hunt�mode�2/10/83H MOVE.B #NCW3BT8+NCW3AUE+NCW3EHU+NCW3CRC+NCW3ADS+NCW3RXE,NECCTL_B 2/10/8'‰BSR.L…SOMETOUT‚TRIGGER�RECEIVE�TIMEOUT$‰SDLRSRG—Restore�all�registers,�then'‰INTSVRG—Save�only�the�"interrupt"�ones ‰BRA.L…INTEXIT 0************************************************0* END OF FILE 'FIX:48.SDLCPRI.RECEIVE.AI' *0************************************************éé‰PAGE5*****************************************************5* BEGINNING OF FILE 'FIX:48.SDLCPRI.SUBRTN.AI' *5*****************************************************   J***************************************************************************È*6*‚SUBROUTINE:‚"SOMETOUT"‚TRIGGER�THE�RECEIVE�TIMEOUT’**È*1*‚ENTER:�A4.L�=�SECONDARY�CONTROL�BLOCK�ADDRESS™**È**È*#*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¥* *’D�U�U�U¯* *’A�U�U…P…S¥**”|‡|…|_�stackž**”|‡|_______�preservedš**”|_______________�usedŸ**È*J************************************************************************** 7SOMETOUT�LEA‡SDLCTTMOUT(PC),A0ƒACTIVATION�ADDRESS�->�A0'‰CLR.L…D0’TIME�INTERVAL�(IN�MSEC)�->�A1‰MOVE.W„SDSTOC(A4),D0‡*‰BEQ.S…SOMETOU1Œ*‰MULU.W„#TIMCNST,D0‰*‰MOVE.W„D0,A1�*'‰MOVE.W„#$0006,D1‹INTERRUPT�LEVEL�->�D1‰MOVE.L„#DLC2,D2ŒI.D.�#�->�D2‰IFEQ†CHIPTYPE-68000 ‹TR0.RQPA‰ENDC‰IFNE†CHIPTYPE-68000 ‹TR0$.RQPA‰ENDC3SOMETOU1�RTS›(MUST�BE�A�2�BYTE�INSTRUCTION)�2/24/831‰ILLEGAL�DIE�IF�SBRQPA�RETURNS�ANY�ERROR!ˆ2/24/83 ‰PAGE J***************************************************************************È*5*‚SUBROUTINE:‚"SOMETOCLR"‚CLEAR�THE�RECEIVE�TIMEOUT“**È**È**È*#*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¥* *’D�U�U�U¯* *’A�U�U‹S¥**”|�|_�stackž**”|_______________�usedŸ**È*J************************************************************************** 8SOMETOCLR�LEA†SDLCTTMOUT(PC),A0ƒACTIVATION�ADDRESS�->�A0'‰CLR.L…D0’TIME�INTERVAL�(IN�MSEC)�->�D1‰MOVE.W„SDSTOC(A4),D0‡*‰BEQ.S…SOMECLR1Œ*‰MULU.W„#TIMCNST,D0‰*‰MOVE.W„D0,A1�*'‰MOVE.W„#$8006,D1‹INTERRUPT�LEVEL�->�D1‰MOVE.L„#DLC2,D2‹I.D.�#�->�D2‰IFEQ†CHIPTYPE-68000 ‹TR0.RQPA‰ENDC‰IFNE†CHIPTYPE-68000 ‹TR0$.RQPA‰ENDC3SOMECLR1�RTS›(MUST�BE�A�2�BYTE�INSTRUCTION)�2/24/831‰ILLEGAL�DIE�IF�SBRQPA�RETURNS�ANY�ERROR!ˆ2/24/83 ‰PAGE J***************************************************************************È*1*‚SUBROUTINE:‚"SOMEDISPOSE"�DISPOSE�OF�A�BUFFER˜*N$Q,A4+*È*.*‚ENTER:�A1.L�=�ADDRESS�OF�BUFFER�TO�DISPOSEœ*(*‰A5.L�=�PRIMARY�CONTROL�BLOCK�ADDRESS›**È*;*‚RETURN:�A1.L�=�ADDRESS�OF�LINK�FIELD�OF�DISPOSED�BUFFER�**È*#*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¥**’Dµ* *’A�U�R‡PƒS¥**”|�|‡|ƒ|_�stackž**”|�|‡|_____�preservedš**”|�|_____________�returned›**”|_______________�usedŸ**È*J************************************************************************** #SOMEDISPOSE MOVE.L SDDLNK(A1),-(A7) ‰MOVE.L„A1,A0‰BSR.L…SBPTFRBF‰MOVE.L„(A7)+,A1‰RTS ‰PAGE J***************************************************************************È*?*‚SUBROUTINE:‚"SOMESEND"‚SEND�A�BUFFER�TO�APPLICATION�PROGRAM‰**È*+*‚ENTER:�A1.L�=�ADDRESS�OF�BUFFER�TO�SENDŸ*(*‰A5.L�=�PRIMARY�CONTROL�BLOCK�ADDRESS›**È*7*‚RETURN:�A1.L�=�ADDRESS�OF�LINK�FIELD�OF�SENT�BUFFER“**È*#*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¥**’D�U³* *’A�U�R‡PƒS¥* *–|‡|ƒ|¥**–|‡|ƒ|_�stackž**–|‡|_____�preservedš**–|_____________�returned›**È*J******************** ****************************************************** SOMESEND�MOVE.L„SDDLNK(A1),-(A7) ‰MOVE.L„A1,A0‰MOVE.L„A2,-(A7)‰BSR.L…SBPTUSQ‰MOVE.L„(A7)+,A2‰MOVE.L„(A7)+,A1‰RTS ‰PAGE J***************************************************************************È*F*‚SUBROUTINE:‚"SOMEFREE"�FREE�THE�LINK�OF�RCV�BUFFERS�TO�BUFFER�POOLƒ**È*5*‚ENTER:�A2.L�=�ADDRESS�OF�FIRST�RCV�BUFFER�TO�FREE•*(*‰A5.L�=�PRIMARY�CONTROL�BLOCK�ADDRESS›**È*#*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¥**’D�U³* *’A�UƒP…PƒS¥**”|‰|ƒ|_�stackž**”|‰|_____�preservedš**”|_______________�usedŸ**È*J************************************************************************** SOMEFREE�MOVE.L„A2,A0‰BSR.L…SBPTFRML‰RTS ‰PAGE J***************************************************************************È*8*‚SUBROUTINE:‚"FINDSCB"�Find�a�Secondary�Control�Block‘**È*D*‚ENTER:�D1.B�=�Secondary�Station�Address,�or�$FF�(Global�Address)†*7*�Note:�Where�the�Global�Address�is�used,�the�address…*3*–of�the�1st�Secondary�Control�Block�is�returned.ƒ**È*4*‚RETURN:�Negative�=�0�(Plus)�-�SCB�Found,�see�A1,–*** A1�=�A(SCB�-�Secondary�Control�Block),‚*>*ŠNegative�=�1�(Minus)�-�SCB�Not�Found,�A1�is�indeterminite.„**È*#*‚REGISTERS�USED:ƒ0�1�2�3�4�5�6�7¥**’D�P³* *’A�|�R‹S¥**”|�|‹|_�stackž**”|�|_____________�returned›**”|_______________�preservedš**È*J************************************************************************** ‰XDEF†FINDSCB >FLYPAPER�EQU‡$FFFFFFFF‹Fly-Paper,�causes�Address�Error�if�used 8FINDSCB‚MOVE.L„SDLCPCB,A1ŠVia�the�Primary�Control�Block,8‰MOVE.L„SDPFSEC(A1),A1†Find�the�address�of�the�first�SCB‰IF.B†D1��#$FF�THEN.S9‹WHILE.BƒSDSSEC(A1)��#0�AND.B�SDSSEC(A1)��D1�DO.S&�ADDA.L„#SDSLNG,A1ŠAdvance�to�next�SCB‹ENDW‰ENDI‰IF.B†SDSSEC(A1)��#0�THEN.S0‹MOVE.L„#FLYPAPER,A1ˆNot�Found,�A1�=�Bug�Catcher ‹ORI.B…#$08,CCRŒAnd�Negative�=�1‰ELSE.S1‹ANDI.B„#$F7,CCRŒFound,�Negative�=�0,�A1�=�A(SCB)‰ENDI‰RTS ‰PAGE J***************************************************************************È*1*‚SUBROUTINE:‚"GETRACE"�Get�a�Trace�Row�Address˜**È**‚ENTER:�No�Arguments³**È*A*‚RETURN:�Carry�=�0�(Carry�Clear)�-�Trace�Row�Address�Returned,‰**¤A2�=�A(Trace�Row),’*%*¤(The�trace�flag�is�on�and�a�traceƒ**¥area�exists),–*3*ŠCarry�=�1�(Carry�Set)�-ƒNo�Trace�Row�Available,�**¤A2�=�#$FFFFFFFF,”*%*¤(Either�the�trace�flag�is�off,�orƒ**¥no�trace�area�exists).�**È*H*‚Note:�The�sixteen�bytes�from�0(A2)�thru�15(A2)�are�available�for�any‚*B*ˆtrace�information�(when�the�"Not�Equal"�return�occurs).‚Common�*B*ˆusage�is�to�store�the�current�PC�value�at�0(A2).L,�identifying‚*B*ˆthe�procedure�which�is�tracing,�followed�by�procedure�specific‚**ˆtrace�information.®**È**‚Example�Usage:¸*+*ŠMOVE.L„A2,-(A7)ŒProtect�A2�if�necessary‰*!*ŠBSR.L…GETRACE�Get�a�trace�row‘*)*ŠIFˆ�THEN.S‰If�a�row�is�available,Š* *ŒPEA‡*(PC)­***ŒMOVE.L„(A7)+,0(A2)‰Store�my�PC�address‹**ŒMOVE.B„x,4(A2)«**ŒMOVE.B„y,5(A2)«*)*ŒMOVE.L„z,6(A2)�Store�some�informationˆ**ŒMOVE.L„a,10(A2)ª*.*ŒMOVE.W„b,14(A2)Œ-�Do�Not�Exceed�15(A2).B�-„**ŠENDIº*0*ŠMOVE.L„(A7)+,A2Œand�recover�A2�(if�"pushed")„**È*J************************************************************************** ‰XREF†TRACEBEG GETRACE‚MOVE.L„TRACEBEG,A2‰BTST.B„#0,TRACFLAG+1 ‰IFˆ�AND.L�A2��#0�THEN.S‹MOVEM.LƒA3-A4,-(A7)0‹MOVE.L„A2,A3�A3�=�A(Trace�control�&�trace�area)‹MOVE.W„SR,-(A7) ‹ORI.W…#$0700,SR‹MASK�INTERRUPTS ‹MOVE.L„0(A3),A2ŒGet�A(Next�Row)%‹LEA‡16(A2),A4‹Figure�A(New�Next�Row)‹IF.L†A4��4(A3)�THEN.S.�LEA‡8(A3),A4ŠReset�to�beginning�when�past�end �MOVE.L„A4,A2�LEA‡16(A2),A4‹ENDI4‹MOVE.L„A4,0(A3)ŒStore�new�A(Next�Row)�for�next�time"‹MOVE.W„(A7)+,SRŒUNMASK�INTERRUPTS)‹LEA‡15(A2),A4‹See�if�a�"Full�Row"�exists‹IF.L†A4��4(A3)�THEN.S,�ANDI.Bƒ#$FE,CCR�and�assert�Row�Exists�if�OK‹ELSE.S3�MOVE.Lƒ#FLYPAPER,A2‰otherwise,�A2�=�#$FFFFFFFF�and�ORI.B„#$01,CCR˜No�Row�Exists‹ENDI‹MOVEM.Lƒ(A7)+,A3-A4‰ELSE.S .‹MOVE.L„#FLYPAPER,A2ˆelse,�A2�=�#$FFFFFFFF�and‹ORI.B…#$01,CCR’No�Row�Exists‰ENDI‰RTS /***********************************************/* END OF FILE 'FIX:48.SDLCPRI.SUBRTN.AI' */***********************************************ééé‰PAGE7*******************************************************7* BEGINNING OF FILE 'FIX:48.SDLCPRI.TRANSMIT.AI' *7******************************************************* H*************************************************************************(*ˆMODULE:‚"TRANSMT"�TRANSMIT�SDLC�FRAMES*-*ˆENTER:‚A5.L�=�PRIMARY�CONTROL�BLOCK�ADDRESS(*�A4.L�=�SECONDARY�CONTROL�BLOCK�ADDRESS%*�A3.L�=�BUFFER�CONTROL�BLOCK�ADDRESS9*ˆENTRY�ASSUMES�A0-A6/D0-D7�HAVE�BEEN�PUSHED�ON�THE�STACK5*–AND�ENTRY�WAS�THROUGH�EXCEPTION�(TRAP�OR�INTERRUPT)2*ˆEXIT:‚"TRANSUF"‚A�TRANSMIT�UNDERFLOW�CAUSED�EXIT-*�"TRANSEQ"‚END�OF�TRANSMIT�QUEUE�CAUSED�EXIT6*�"TRANSPB"‚SDLC�COMMAND�WITH�POLL�BIT�SET�CAUSED�EXIT!*ˆREGISTERS�USED:ƒ0�1�2�3�4�5�6�7*˜D�U*˜A�U�U�U�U�P�PƒS* |ƒ|ƒ|_�stack* |ƒ|_____�preserved* |_________�used#*ˆEXITS�TO�EXTERNALLY�DEFINED�LABEL&*ŽWITH�A0-A6/D0-D7�PUSHED�ON�THE�STACK&*ŽAND�ASSUMES�FINAL�EXIT�WILL�BE�"RTE"*H************************************************************************E* NOTE: ALL INFORMATION FRAMES HAVE THEIR LENGTHS TRANSMITTED AS WELLA*�AS�THEIR�DATA.‚THE�LENGTH�IS�SENT�AS�THE�FIRST�TWO�BYTES�OF�THE* INFORMATION FIELD AS FOLLOWS;N*
H*�THE�RECEIVING�STATION�MUST,�OF�COURSE,�EXPECT�THIS.‚THE�LENGTH�IS�SENTM* AS THE NEC7201 HAS THE NASTY TENDENCY TO SEND THE FRAME CHECK SEQUENCE WHENN*�A�TRANSMITTER�UNDERRUN�OCCURS.‚IF�WE�DO�THIS�BY�ACCIDENT,�THEN�WE�MUST�BEGINL* SENDING AN ABORT WITHIN THREE CHARACTER TIMES (TWO FCS CHARACTERS PLUS THEL*�ENDING�FLAG)�FOR�THE�RECEIVING�STATION�TO�KNOW�THAT�WE�GOOFED.‚IF�FOR�SOMEH* REASON WE DON'T INITIATE THE ABORT IN TIME, WITHOUT THE DATA COUNT THEK* RECEIVING STATION WOULD HAVE NO WAY OF KNOWING THAT THE FRAME HE HAS JUSTM*�RECEIVED�IS�NO�GOOD.‚THE�RECEIVER�HANDLES�THIS�"BAD�LENGTH"�FRAME�JUST�LIKE>* ANY OTHER ERRONEOUS FRAME - HE IGNORES THE FRAME COMPLETELY. :TRANSMT‚MOVE.B„#SDPBTX,SDPBSY(A5)‚Set�us�busy�transmitting<+E9MU8]>e6mJuE}>…‰ADD.W…#1,SDSHCTXM(A4)…3/2/83‰OR.W†#$700,SRŒMask�Interrupts!<‰MOVE.B„#NCW0REX+NCW0RG1,NECCTL_B�Reset�any�pending�ExternalB‰MOVE.B„#NCW1EXI+NCW1STV,NECCTL_B�Enable�only�ExtStatus�(not�Xmtr)‰MOVE.B„#NCW0RG5,NECCTL_B9‰MOVE.B„#NCW5DTR+NCW5TX8+NCW5TXE+NCW5RTS+NCW5TCE,NECCTL_B ‰PAGE C* DTR and RTS are now active, wait for CTS to become active as well ‰MOVE.B„NECCTL_B,D0.‰BTST.L„#5,D0�Is�Clear�to�Send�already�active?‰IFˆ�THEN.S)‹LEA‡TXMSTCTS(PC),A0…No,�Must�wait�for�it7‹MOVE.L„A0,SDPVCT2(A5)†ExtStatus�to�TXMSTCTS�(CTS�Wait)‹LEA‡TXMSTOFF(PC),A0;‹MOVE.L„A0,SDPVCT1(A5)†and�XmtrEmpty�to�TXMSTOFF�(Xmtr�Off)‹MOVEM.LƒA0-A6,SDPRRTA0(A5)‹SDLRSRG‹INTSVRG'‹BRA.L…INTEXIT�Exit�till�CTS�comes�true *#* External Status  Interrupt Handler*0TXMSTCTSƒMOVE.B„NECCTL_B,D0‰ExtStatus�Interrupt,‹MOVE.B„#NCW0REX,NECCTL_B+‹MOVE.B„#NCW0EOI,NECCTL_AƒAck�the�interrupt*‹BTST.L„#5,D0�Is�Clear�to�Send�now�active?‹IFˆ�THEN.S!�BRA.L…INTEXIT‹No,�wait�some�more‹ENDI‹INTRSRG‹SDLSVRG)‹MOVE.L„SDLCPCB,A6ŠYes,�Now�we�can�begin!0‹MOVEM.LƒSDPRRTA0(A6),A0-A6‚Restore�BG�Registers‰ENDI * Fall-thru to the next page‰PAGE7* NOTE: WE MAY FALL-THRU TO HERE FROM THE PREVIOUS PAGE ‰MOVE.B„#NCW0RG1,NECCTL_B@‰MOVE.B„#NCW1TXI+NCW1EXI+NCW1STV,NECCTL_B�Enable�Xmtr�Interrupts )* Pre-frame transmission delay algorithm.+* Replaced on August 23, 1983 by Ed Skinner*D*†Where�a�pre-frame�transmission�delay�is�required,�we�send�a�"null"L*�frame�consisting�of�the�specified�number�of�bytes.‚This�frame�is�addressedH* to station $00 (there ain't no such station), and is not sent with anyJ*�FCS.‚These�two�conditions�(station�$00�and�no�FCS)�should�guarantee�that3* no station receives this as a valid transmission.E*†A�pre-frame�transmission�delay�is�needed�for�either�of�two�reasons.J* First, where Mancester encoding is used (such as in the Exormacs/HDS-400G* and GMAD Weld Monitor configurations), the Mancester chip will supplyM* Transmit Clock to the NEC7201 sometime after RTS is output (from the 7201).K* The single leading flag sent by the NEC7201 is not always received intactL*�by�the�target�station.‚This�may�be�due�to�some�difficulty�in�the�MancesterJ*�receiver�and/or�NEC7201.‚Regardless,�it�remains�that�the�first�characterM* transmitted by the NEC7201 (an SDLC Flag) is not always received correctly.C*†Secondly,�a�pre-frame�transmission�delay�may�be�used�to�allow�theM* receiving software (in the target node) additional time in which to prepare* for receiving a frame.D*†To�effect�the�pre-frame�transmission�delay,�a�frame�containing�$00I*�bytes�in�all�fields�is�transmitted.‚As�the�station�address�$00�is�not�aI* valid station address according to the SDLC protocol, no station should.* begin active reception of this "null" frame.F*†Once�the�specified�number�of�"null"�bytes�have�been�transmitted,�theI* transmitter is allowed to revert to the "flagging" condition (no FCS isG*�sent).‚Since�any�receiver�of�this�frame�will�think�the�last�two�bytesH* are the FCS, and as these bytes do not contain the computed FCS, it isI* unlikely (1 chance in 65535) that it will appear to be the correct FCS.I* Additionally, since the odds of a transmission error which would changeG* the address field to some "real" station address are much more remoteF* (although no information is available in this regard, the error rateF* should be similar to that of a satellite link (1 in 10**9) or betterJ* considering the "protected" environment and circuit length), the overallF* probability of some station receiving this leading transmission as aE*�valid�frame�are�comfortably�remote.‚(Besides�that,�the�reason�we'reE* sending this little sucker is because the first frame usually isn'tJ*�received�as�the�leading�flag�is�missed.‚This�makes�it�even�more�unlikelyB* that this leading pad frame might be received as a valid frame.)D*†Note�that�when�a�frame�transmission�completes,�we�do�not�send�thisK* "leading pad" frame when more than one frame is sent in quick succession. 2TXMSTPAD�TST.W…SDSTPD(A4)ŠAny�leading�frame�delay?‰IFˆ�THEN.S1‹MOVE.W„SDSTPD(A4),A1‡Yes,�A1.W�=�Character�Count‹LEA‡TXMSTPNX(PC),A08‹MOVE.L„A0,SDPVCT1(A5)†Xmtr�Intr�-->�TXMSTPNX�(Next�Pad)‹LEA‡TXMSTEI(PC),A07‹MOVE.L„A0,SDPVCT2(A5)†ExtSta�Intr�-->�TXMSTEI�(Ignore)‹MOVEM.LƒA0-A6,SDPRRTA0(A5)‹SDLRSRG‹INTSVRG9‹MOVE.B„#$00,NECDAT_B‡Send�Station�Address�=�$00�(Nobody)#‹BRA.L…INTEXIT�Exit�till�Xmtr�Empty ‰PAGE*%* Transmitter Empty Interrupt Handler*B* Enter here upon Transmitter Empty interrupts where the last byteE*�output�is�now�being�transmitted�by�the�NEC7201.‚Because�the�NEC7201J* gives us the Transmitter Empty interrupt up to one c haracter time beforeF* the character is actually needed, there is a one character "latency"E*�between�what�we�output,�and�what�the�NEC7201�is�sending.‚Therefore,H* we actually output one more than the specified number of leading pads,H* and terminate this operation when we get the interrupt indicating thatG* the last byte output (the "extra" byte) is now being transmitted, andI* therefore, that the specified number of leading pads have, in fact, now* all been transmitted. 5TXMSTPNXƒSUB.W…#1,SDPRRTA1+2(A1)ƒSent�one�delay�byte,‹IFˆ�THEN.S7�MOVE.B„#$00,NECDAT_B‡Send�another�till�count�exhausted*�MOVE.B„#NCW0EOI,NECCTL_AƒEnd�of�Interrupt.�BRA.L…INTEXIT�And�exit�till�another�Xmtr�Intr‹ENDI1‹MOVE.B„#NCW0EOI,NECCTL_AƒEnd�of�Interrupt�(Xmtr)‹INTRSRG‹SDLSVRG‹MOVE.L„SDLCPCB,A60‹MOVEM.LƒSDPRRTA0(A6),A0-A6‚Restore�BG�Registers‰ENDI%* And begin sending the "real" frame. %TXMSTNXT�ADD.W…#1,SDSHCTXS(A4)‡3/2/83* Fall-thru to the next page‰PAGE8* NOTE: WE WILL FALL-THRU TO HERE FROM THE PREVIOUS PAGE 7* "EMBELLISH" SDLC COMMAND WITH Nr/Ns COUNTS & POLL BIT ‰MOVE.B„SDDCMD(A3),D0‰AND.B…#$03,D0‰IF.B†D0��#3�THEN.S#‹MOVE.B„SDDCMD(A3),D0ƒS�or�I�frame,‹AND.B…#$1F,D0/‹OR.B†SDSVRC(A4),D0ƒOR�in�the�current�Vr�count. ‹BTST.L„#0,D0‹IFˆ�THEN.S�AND.B…#$F1,D0‰I�frame,4�OR.B†SDSVSC(A4),D0ƒOR�in�the�current�Vs�count�also,(�OR.B†#$10,D0‰assert�the�poll/final�bit,/�ADD.B…#2,SDSVSC(A4)ƒ(Advance�Vs�for�next�time):�AND.B…#$0E,SDSVSC(A4)ƒ(making�sure�it's�only�3�bits�wide)3�ADD.B…#1,SDSUKT(A4)ƒbump�the�number�of�frames�out,�MOVE.B„SDSUKT(A4),D11�TST.L…SDDLNK(A3)†any�more�frames�after�this�one?(�IFˆ�AND.B�D1��SDSMXF(A4)�THEN.S9�MOVE.L„SDDLNK(A3),A0ƒyes,�and�haven't�reached�max�limit,�BTST.B„#0,SDDCMD(A0)�IFˆ�THEN.S2‘AND.B…#$EF,D0‰don't�poll/final�if�next�is�I�frame�ENDI�ENDI‹ELSE.S�MOVE.B„D0,D1ŽIf�we�are�sending*�AND.B…#$1F,D1Œa�Receiver�Not�Ready�frame,!�IF.B†D1��#SDDRRNR+$10�THEN.S/�MOVE.B„#SDPTRN,SDPTXF(A5)�Then�assert�RNR�Sent�ENDI‹ENDI7‹MOVE.B„D0,SDDCMD(A3)‡Store�the�command�byte�to�be�sent‰ENDI* Fall-thru to the next page‰PAGE8* NOTE: WE WILL FALL-THRU TO HERE FROM THE PREVIOUS PAGE 8‰LEA‡TXMST0(PC),A0‡Prepare�interrupt�vectors�for�sending‰MOVE.L„A0,SDPVCT1(A5)<‰LEA‡TXMSTEI(PC),A0†For�1st�Char�Out,�we�ignore�ExtSta�Intrs‰MOVE.L„A0,SDPVCT2(A5) .‰LEA‡SDDDAT(A3),A2‡A2�=�A(data�area�of�buffer) +‰MOVE.B„SDDCMD(A3),D0‡Figure�I�field�length)‰AND.B…#$03,D0�according�to�type�of�frame‰IF.B†D0��#$01�THEN.S<‹MOVE.W„SDDBCT(A3),A1‡I�and�U�frames�specify�I�field�lengths‰ELSE.S2‹MOVE.W„#0,A1�While�S�frames�never�have�an�I�field‰ENDI C‰MOVEM.LƒA0-A6,SDPRRTA0(A5)‚Save�regs�for�interrupt�handlers�to�use* A5 = SDPRRTA5 = A(PCB)* A4 = SDPRRTA4 = A(SCB)* A3 = SDPRRTA3 = A(Buffer)(* A2 = SDPRRTA2 = A(Data within I field)#* A1 = SDPRRTA1 = Length of I fieldG* A0 = SDPRRTA0 = Not used for anything special - just leftover garbage ‰ADD.W…#1,SDSHCTXA(A4)…3/2/83 ‰MOVE.B„SDSSEC(A4),D0‡3/3/832‰IF.B†D0��SDDSEC(A3)�AND.B�D0��#$FF�THEN.S$‹ILLEGAL—Die�if�bad�station�address!‰ENDI* Fall-thru to the next page‰PAGE8* NOTE: WE WILL FALL-THRU TO HERE FROM THE PREVIOUS PAGE )‰MOVE.L„A2,-(A7)ŒProtect�A2�while�tracing‰BSR.L…GETRACE�Get�a�trace�row‰IFˆ�THEN.SE**********************************************************************�Trace�Entry�Format°*E**********************************************************************Ã*'*‚+0Ž+4Ž+8‚+9‚+10�+11�+12�+13�+14�+15‚*E* +---------------+---------------+---+---+---+---+---+---+---+---+ *:*�!†PC‡!�A(Xmt�Buffer)�!�#�!�S�!�U�!�C�!�RC!�D0!�D1!�0�!�*E* +---------------+---------------+---+---+---+---+---+---+---+---+ **Ã**�PC�=�Program�Counter,­*<*�A(Xmt�Buffer)�=�Address�of�the�buffer�to�be�transmitted,Š**�#�=�Station's�Number,­* *�S�=�Station's�Current�State,¦*/*�U�=�Station's�Current�Unacknow ledged�Count,—**�C�=�Buffer's�Command�Byte,¨**�RC�=�Buffer's�Retry�Count,¨* *�D0�=�Buffer's�1st�Data�Byte,¦* *�D0�=�Buffer's�2nd�Data�Byte,¦**�0�=�Unused.·**Ã*E*********************************************************************,‹PEA‡*(PC)�If�we�get�a�trace�row,�then�trace#‹MOVE.L„(A7)+,0(A2)‰our�PC�address, ‹MOVE.L„A3,4(A2)ŒA(Xmit�buffer),)‹MOVE.B„SDSSEC(A4),8(A2)„Station�Address,+‹MOVE.B„SDSCST(A4),9(A2)„His�current�state,7‹MOVE.B„SDSUKT(A4),10(A2)ƒCurrent�unacknowledged�count,'‹MOVE.B„SDDCMD(A3),11(A2)ƒCommand�byte,&‹MOVE.B„SDDRTC(A3),12(A2)ƒRetry�Count,%‹MOVE.B„SDDDAT+0(A3),13(A2)�and�first4‹MOVE.B„SDDDAT+1(A3),14(A2)�...�.....�two�data�bytes$‹CLR.B…15(A2)Ž(Zero�the�unused�byte)‰ENDI)‰MOVE.L„(A7)+,A2ŒRecover�A2�after�tracing ?‰MOVE.B„#NCW0RTG,NECCTL_B„Reset�the�transmitter's�FCS�generatorB‰MOVE.B„SDDSEC(A3),NECDAT_B‚Output�the�secondary�station's�address=‰MOVE.B„#NCW0RTU,NECCTL_B„Enable�FCS�transmission�on�Underrun ‰SDLRSRG—Recover�all�registers,,‰INTSVRG—Make�stack�look�like�interrupt�regs4‰BRA.L…INTEXIT�And�go�see�if�an�interrupt�is�pending‰PAGE *%* Transmitter Empty Interrupt Handler*,*ˆVECTORED�STATE�TO�TxMIT�SDLC�COMMAND�FIELD*ATXMST0ƒMOVE.B„NECCTL_B,D0‰Since�we've�been�ignoring�ExtSta�Intrs,2‰BTST.L„#6,D0�We�now�check�for�an�earlier�underrun,‰BNE.L…TXMSTE1�If�true,�go�send�an�Abort�now"‰MOVE.L„SDPRRTA3(A1),A2…Otherwise,2‰MOVE.B„SDDCMD(A2),NECDAT_B�Send�the�command�field‰IFEQ†IFRMBCT-YES6‹BTST.B„#0,SDDCMD(A2)‡Where�we�are�sending�an�I�frame,‹BNE.S…TXMST012‹LEA‡TXMSTL1(PC),A2†We�Send�a�"Length"�Field�first‹BRA.S…TXMST02‰ENDCATXMST01‚LEA‡TXMST1(PC),A2‡Set�Up�the�Next�Xmtr�Empty�Intr�HandlerTXMST02‚MOVE.L„A2,SDPVCT1(A1)1‰LEA‡TXMSTE(PC),A2‡And�from�now�on,�we�care�about1‰MOVE.L„A2,SDPVCT2(A1)†External�Status�Interrupts‰MOVE.B„#NCW0EOI,NECCTL_A‰BRA.L…INTEXIT ‰PAGE ‰IFEQ†IFRMBCT-YES*%* Transmitter Empty Interrupt Handler**/*ˆVECTORED�STATE�TO�TxMIT�SDLC�LENGTH�FIELD�#�1*7TXMSTL1‚MOVE.L„SDPRRTA3(A1),A2�OUTPUT�SDLC�LENGTH�FIELD‰MOVE.B„SDDBCT(A2),NECDAT_B‚*+‰LEA‡TXMSTL2(PC),A2†SET�NEXT�VECTORED�STATE‰MOVE.L„A2,SDPVCT1(A1)†*‰MOVE.B„#NCW0EOI,NECCTL_A‰BRA.L…INTEXIT ‰PAGE *%* Transmitter Empty Interrupt Handler**/*ˆVECTORED�STATE�TO�TxMIT�SDLC�LENGTH�FIELD�#�2*7TXMSTL2‚MOVE.L„SDPRRTA3(A1),A2�OUTPUT�SDLC�LENGTH�FIELD"‰MOVE.B„SDDBCT+1(A2),NECDAT_B�*œ10*‰LEA‡TXMST1(PC),A2‡SET�NEXT�VECTORED�STATE‰MOVE.L„A2,SDPVCT1(A1)†*‰MOVE.B„#NCW0EOI,NECCTL_A„*�10‰BRA.L…INTEXIT‡*‚ENDC ‰PAGE *#* External Status Interrupt Handler**4*ˆVECTORED�STATE�TO�PROCESS�STATUS�CHANGE�INTERRUPTS*!TXMSTEƒMOVE.B„NECCTL_B,D0‰GET�RR0‰BTST.L„#6,D0�UNDERRUN?(‰BNE.S…TXMSTE1�YES,�HURRY�AND�SEND�ABORTTXMSTE0‚BTST.L„#5,D0�CTS�DROP?%‰BEQ.S…TXMSTE1�YES,�XMTR�DYING,�ABORT'‰BRA.S…TXMSTE2�NO,�IGNORE�THE�INTERRUPT 3TXMSTE1‚MOVE.B„#NCW0SAB,NECCTL_BƒSEND�AN�SDLC�ABORT‰MOVE.L„SDPRRTA4(A1),A2‰ADD.W…#1,SDSHCTUN(A2)4‰MOVE.L„SDPRRTA3(A1),A2…RESTORE�BUFFER�CONTROL�BLOCK0‰MOVE.B„#SDDETXU,SDDERR(A2)�TxMIT�UNDERRUN�ERROR*‰MOVE.B„#NCW0REX,NECCTL_BƒRESET�INTERRUPTS‰MOVE.B„#NCW0EOI,NECCTL_A‰INTRSRG—SAVE�ALL�USER'S�REGS‰SDLSVRG‰MOVE.L„SDLCPCB,A5ŠRESTORE�REGS‰MOVEM.LƒSDPRRTA3(A5),A3-A5(‰BRA.L…TRANSUF�EXIT�(TRANSMIT�UNDERFLOW) ETXMSTE2‚MOVE.B„#NCW0REX,NECCTL_BƒIgnore�the�External�Status�Interrupt‰MOVE.B„#NCW0EOI,NECCTL_A‰BRA.L…INTEXIT ‰PAGE *%* Transmitter Empty Interrupt Handler**0*ˆVECTORED�STATE�TO�TxMIT�SDLC�INFORMATION�FIELD*>TXMST1ƒSUB.W…#1,SDPRRTA1+2(A1)ƒDecrement�number�of�bytes�to�go‰IFˆ�THEN.S/‹MOVE.L„SDPRRTA2(A1),A2…If�"more"�bytes�remain,5‹MOVE.B„(A2)+,NECDAT_B‡Output�the�next�data�byte,�and7‹MOVE.L„A2,SDPRRTA2(A1)…Save�data�pointer�for�next�time‰ELSE.S9‹LEA‡TXMSTOFF(PC),A2…When�done,�prepare�to�send�FCS�bytes/‹MOVE.L„A2,SDPVCT1(A1)†(Xmtr�Intr�not�expected)0‹LEA‡TXMST2(PC),A2‡and�Expect�an�External�Status&‹M OVE.L„A2,SDPVCT2(A1)†interrupt�next,9‹MOVE.B„#NCW0RTI,NECCTL_BƒAnd�make�the�Xmtr�Empty�go�away‰ENDI6‰MOVE.B„#NCW0EOI,NECCTL_AƒEither�way,�End�of�Interrupt‰BRA.L…INTEXIT ‰PAGE *#* External Status Interrupt Handler* *ˆVECTORED�STATE�TO�TRANSMIT�CRC*0TXMST2ƒMOVE.B„NECCTL_B,D0‰Get�the�Chip's�Status,(‰BTST.L„#6,D0�Is�it�sending�the�FCS�now?$‰BEQ.L…TXMSTE0�No,�go�check�CTS�fall5‰LEA‡TXMSTEI(PC),A2†Yes,�Chip�is�now�sending�the�FCS.3‰MOVE.L„A2,SDPVCT2(A1)†Ignore�Underruns�from�now�on‰MOVE.B„#NCW0REX,NECCTL_B‰MOVE.B„#NCW0EOI,NECCTL_AƒAnd2‰LEA‡TXMST3(PC),A2‡Set�up�for�Xmtr�Empty�Interrupt,‰MOVE.L„A2,SDPVCT1(A1)†To�take�us�to�TXMST3.4‰BRA.L…INTEXIT�(Occurs�when�FCS�sending�is�complete) ‰PAGE *%* Transmitter Empty Interrupt Handler*(*ˆVECTORED�STATE�AFTER�CRC�HAS�BEEN�SENT* TXMST3ƒINTRSRG—SAVE�ALL�REGS�NOW‰SDLSVRG‰MOVE.L„SDLCPCB,A6�RESTORE�REGS‰MOVEM.LƒSDPRRTA0(A6),A0-A6.‰BTST.B„#4,SDDCMD(A3)‡POLL�BIT�SET�IN�COMMAND?‰BNE.S…TXMST3A�Yes,�See�below‰MOVE.B„#NCW0EOI,NECCTL_AƒNo,6‰MOVE.L„SDDLNK(A3),A3‡Is�there�something�else�to�send? ‰MOVE.L„A3,D04‰BNE.L…TXMSTPADŽYup,�go�send�it�(with�leading�delay)'‰ADD.W…#1,SDSHCTNP(A4)…No,�done�sending+‰BRA.L…TRANSEQ�Go�figure�out�what�to�do�now ‰PAGE J* WHEN WE ARE READY TO SHUT DOWN THE TRANSMITTER, WE MUST DELAY FOR 11 BITJ* TIMES TO ALLOW THE ENDING FLAG TO LEAVE THE SHIFT REGISTER (8 BIT TIMES)L* AND TO PASS THRU OTHER HARDWARE (SUCH AS THE MANCESTER ENCODER WHICH NEEDSJ*�3�MORE�BIT�TIMES).‚SINCE�WE�CANNOT�MEASURE�INDIVIDUAL�BIT�TIMES,�WE�WAITL* A TOTAL OF 16 BIT TIMES BY SENDING TWO "PAD" CHARACTERS CONSISTING OF $00.M* THIS VALUE IS USED AS NO SECONDARIES HAVE THIS ADDRESS AND, THEREFORE, NONEK*�OF�THEM�WILL�START�TO�RECEIVE�THIS�INFORMATION.‚ADDITIONALLY,�WE�TURN�THEM* TRANSMITTER OFF AFTER THE LAST ONE IS OUT WITHOUT SENDING ANY FCS SEQUENCE.K* TURNING THE TRANSMITTER OFF, IF SOMEONE IS RECEIVING AT THAT TIME, CAUSESI* THE LINE TO GO TO A MARKING STATE WHICH WILL CAUSE THEM TO DETECT FIRSTI*�A�RECEIVE�ABORT,�AND�THEN�A�MARKING�(IDLE)�LINE.‚FROM�THESE�INDICATIONSF* WE ARE ASSURED THAT NO STATION WILL RECEIVE THESE TRAILING PADS AS A+*�VALID�FRAME.ƒED�SKINNER,�MARCH�2,�1983... /TXMST3A‚MOVE.B„#$00,NECDAT_B�OUTPUT�A�NULL�CHAR*‰LEA‡TXMST4(PC),A0‡SET�NEXT�VECTORED�STATE‰MOVE.L„A0,SDPVCT1(A5)‰MOVE.B„#NCW0EOI,NECCTL_A&‰SDLRSRG—Restore�full�set�of�registers$‰INTSVRG—And�stack�the�interrupt�set4‰BRA.L…INTEXIT�And�go�see�if�another�interrupt�pends ‰PAGE *%* Transmitter Empty Interrupt Handler***ˆOUTPUT�2ND�NULL�CHAR*-TXMST4ƒMOVE.B„#$00,NECDAT_B�OUTPUT�A�PAD�NULL*‰LEA‡TXMST5(PC),A2‡SET�NEXT�VECTORED�STATE‰MOVE.L„A2,SDPVCT1(A1)‰MOVE.B„#NCW0EOI,NECCTL_A‰BRA.L…INTEXIT ‰PAGE *%* Transmitter Empty Interrupt Handler**E*ˆTxMIT�SHUTDOWN�WITH�POLL�BIT�SET�IN�COMMAND�(NOT�NECESSARILY!�E.S.)*=TXMST5ƒMOVE.B„#NCW0EOI,NECCTL_A�LETS�SAVE�ALL�THE�USER'S�REGSTXMENDƒINTRSRG‰SDLSVRG‰MOVE.L„SDLCPCB,A6�RESTORE�REGS‰MOVEM.LƒSDPRRTA0(A6),A0-A6‰ADD.W…#1,SDSHCTEN(A4)…3/2/83"‰BRA.L…TRANSPBƒEXIT�(POLL�BIT�SET) ‰PAGE *#* External Status Interrupt Handler**8*ˆEXTERNAL�STATUS�INTERRUPT�HANDLER�WHICH�IS�USED�DURING*’1)�LEADING�PAD�TRANSMISSION,+*’2)�TRANSMISSION�OF�THE�ADDRESS�FIELD,�AND*’3)�TRAILING�PAD�TRANSMISSION.@*ˆIN�ALL�THREE�CASES,�"UNDERRUN"�INDICATIONS�ARE�IGNORED�AS�WELL=*ˆAS�ALL�OTHER�CONDITIONS�EXCEPT�FOR�A�FALL�OF�CLEAR�TO�SEND.*0TXMSTEI‚MOVE.B„NECCTL_B,D0‰GET�THE�CHIP'S�STATUS/‰MOVE.B„#NCW0REX,NECCTL_BƒRESET�EXTERNAL�STATUS.‰MOVE.B„#NCW0EOI,NECCTL_AƒAND�END�OF�INTERRUPT‰MOVE.L„SDPRRTA4(A1),A2…3/2/83‰ADD.W…#1,SDSHCEXA(A2)…3/2/83?‰BTST.L„#5,D0…CTS�fall?‚If�yes,�then�must�assume�frame�sent�OK,=‰BEQ.S…TXMEND„We�"assume"�poll�bit�sent,�and�go�into�rcv�now.I* CTS did not drop, so we ignore the External Status Interrupt completely‰BRA.L…INTEXIT ‰PAGE *%* Transmitter Empty Interrupt Handler*F* This state is to be used when transmitter interrupts  are supposed toE*�be�off,�or�are�otherwise�not�expected.‚If�one�happens�while�in�this-* state, the system is intentionally crashed.* 2TXMSTOFF�CRASH.Tƒ*+1‘Fail�with�an�Addressing�Error 1*************************************************1* END OF FILE 'FIX:48.SDLCPRI.TRANSMIT.AI' *1*************************************************ééé' IOCFAIL SA™™‘bbM600CMDSSA® ðÒbbM600CMTSSA©‹Z›bbM600DRV SA  bbM600INTLSA-ÿbbM600LIB SAFFUòbbM600SERVSA››§bbM605DRV SAÀÀ]ãbbM605LIB SA!!~bbM610DRV SA2 #¹ Ebb610LIB SA ô ô<bb0IOCFAILƒIDNTƒ1,0�Board�Fail�Montior�Task�4-28-82 ŠOPT�PCS,FRSM*----------------------------------------------------------------------------*-*ˆIOCFAIL‚I/O�CHANNEL�BOARD�FAIL�HANDLER�TASK**ˆVersion�1.0‚4/27/82�(C313)*<*ˆThis�task�is�a�shell�to�handle�board�fails,�if�so�desired.:*ˆIt�gets�an�ASQ�to�be�able�to�receive�events�from�drivers;*ˆwhich�can�receive�board�fail�interrupts.�It�then�attaches>*ˆto�each�driver�it�wants�to�monitor.�The�attach�call�uses�the9*ˆsame�device�name�as�the�level�4�CCB�allocate�call�used.:*ˆThese�device�names�are�entered�in�this�task�by�the�user.*;*ˆThis�task�accepts�events�from�I/O�Channel�device�drivers.:*ˆAn�event�is�queued�to�this�task�whenever�a�device�driver<*ˆexperiences�a�board�fail�interrupt.‚As�supplied,�this�task=*ˆonly�reads�the�event.‚The�user�may�add�to�or�eliminate�this*ˆtask�according�to�his�needs.*N*-----------------------------------------------------------------------------* *ˆEQUATES*8NOFDEV„EQU„16‘maximum�number�of�I/O�channel�devices�this%*§may�be�changed�to�the�actual�number&*§of�I/O�channel�devices�on�the�system*"MSGLNG„EQU„10‘event�message�length*%QUELNG„EQU„MSGLNG*NOFDEV†queue�length*1ASQOPT„EQU„$D‘ASQ�options:�don't�stack�registers,*§enable�ASQ�and�ASR*%GTASQ…EQU„31‘Get�ASQ�directive�number-WTEVNT„EQU„36‘Wait�for�event�directive�number)RDEVNT„EQU„34‘Read�event�directive�number0RTEVNT„EQU„37‘Return�from�event�directive�number+TERM†EQU„15‘Terminate�task�directive�number.CMR‡EQU„60‘Channel�management�directive�number**‰Event�layout* ŠOFFSET�0 EVTLNG„DS.Bƒ1’event�length�($0A)EVTCOD„DS.Bƒ1’event�codeƒ($09) EVTDEV„DS.Lƒ1’failed�device�name5EVTADR„DS.Lƒ1’failed�device�memory�mapped�I/O�addressŠPAGE ŠSECTION�0*+*‰Ta sk�Creation�Date�and�Version�Identifier*D‰EQU„*’start�of�dataŠDC.Bƒ'042882�1'‰identifier**‰Device�Name�Table*6*‰THIS�TABLE�TO�BE�MODIFIED�FOR�EACH�DEVICE�TO�MONITOR**‰table�structure:‘?šI¢ 0*‰multiple�4�byte�fields�containing�device�names8*‰last�4�byte�field�set�to�zero�to�indicate�end�of�table*-DEVTBL„DC.Lƒ'RA41'�attach�to�level�4�RAD1�CCB ŠDC.Lƒ'RA42'ŠDC.Lƒ0’end�of�table**‰misc.�data�area*7TRP1PB„DS.Bƒ22‘Trap�1�parameter�block�used�by�all�callsŠDS.Bƒ8’Stack�area STACK…EQU„* PAGE* *‰ENTRY�POINT* *‰get�an�ASQ*'IOCFAILƒLEA„STACK(PC),A7‡load�the�stack.ŠLEA„TRP1PB(PC),A1†get�parameter�block�address"ŠMOVE.L�A1,A0Žsave�it�for�the�callŠCLR.L‚(A1)+Žtask�nameŠCLR.L‚(A1)+Žsession%ŠMOVE.B�#ASQOPT,(A1)+†set�the�options$ŠMOVE.B�#MSGLNG,(A1)+†message�length"ŠMOVE.L�#QUELNG,(A1)+†queue�length"ŠLEA„IOCASR(PC),A2†Get�ASR�addressŠMOVE.L�A2,(A1)+‹ASR�addressŠCLR.W‚(A1)�not�used*ŠMOVE.L�#GTASQ,D0Šget�ASQ�directive�numberŠTRAPƒ#1‘get�an�ASQ(ŠBNE.S‚ERRORŽbranch�if�an�error�returned*.*‰attach�to�all�devices�listed�in�device�table"*‰these�are�the�devices�to�monitor*+ŠLEA„DEVTBL(PC),A2†get�device�table�address-IOCATT„TST.L‚(A2)�a�device�left�to�attach�to?(ŠBEQ.S‚IOCWAITŒbranch�if�no�devices�left-ŠMOVE.L�A0,A1Žrestore�parameter�block�addressŠMOVE.B�#3,(A1)+‹attach�codeŠCLR.B‚(A1)+Žnot�used'ŠMOVE.W�#1,(A1)+‹set�queue�event�option9ŠMOVE.L�(A2)+,(A1)+ˆset�device�name�from�the�device�table(ŠMOVE.W�#MSGLNG,(A1)+†set�message�lengthŠCLR.L‚(A1)+Žuse�default�ASRŠCLR.L‚(A1)+Žnot�used3ŠMOVE.L�#CMR,D0Œchannel�management�directive�numberŠTRAPƒ#1‘do�the�attach*ŠBRA„IOCATT�go�see�if�another�attach�to�do**‰wait�for�an�event*9IOCWAITƒMOVE.L�#WTEVNT,D0‰wait�for�event�directive�numberŠTRAPƒ#1‘do�the�wait**‰USER�CODE�MAY�BE�ADDED�HERE*#ŠBRA„IOCWAITŒgo�wait�for�next�eventŠPAGE*"*‰IOCASR„read�the�event�and�return*“registers�are�not�stacked* IOCASR„EQU„*5ŠLEA„TRP1PB(PC),A0†Get�trap�1�parameter�block�address.ŠMOVE.L�#RDEVNT,D0‰read�event�directive�numberŠTRAPƒ#1‘read�the�event(ŠBNE.S‚ERRORŽbranch�if�an�error�returned**‰the�event�is�now�at�TRP1PB*‰USER�CODE�MAY�BE�ADDED�HERE*%ŠMOVE.L�#1,A0Žreturn�with�ASR�enabled5ŠMOVE.L�#RTEVNT,D0‰return�from�event�directive�numberŠTRAPƒ#1‘return�from�this�event*2*‰terminate�this�task�if�receive�any�trap�1�errors*5ERROR…MOVE.L�#TERM,D0‹terminate�task�directive�numberŠTRAPƒ#1‘do�the�termination ŠEND„IOCFAIL éééé éé‰TTL‡5.‚Command�Service�Section‰PAGE*š5.‚Command�Service�Section*G*‡Recall‚again�that�CMR�views�an�I/O�driver�(such�as�the�A/D�driver)�asL*‚a�collection�of�three�major�subroutines.‚One�subroutine,�which�has�alreadyJ*‚been‚presented‚for‚the�A/D�driver,�is�used�at�channel-allocation�time�toG*‚initialize�the�I/O�device(s)�on�the�channel‚that‚is‚served‚by‚the‚I/OF*‚driver‚and‚to‚perform‚any‚other‚initialization‚steps�that�the�driverL*‚requires.‚Another�subroutine�is�used�for�responding�to�an�I/O�command�thatK*‚was‚ultimately‚generated�by�a�user�task,�and�the�third�subroutine�is�usedK*‚to�respond�to�an�interrupt�from�a�device�on�the�channel�that�is‚served‚by*‚the�I/O�driver.*D*‡This‚section‚of‚the‚listing�for�the�RMS68K�A/D�driver�contains�theI*‚command-processing�subroutine�that�is�called�by�CMR‚when‚CMR‚receives‚aI*‚command‚to‚perform‚an�I/O�transaction�with�the�A/D�driver.‚This�sectionM*‚also�includes�several�subsidiary�routines�that�are�used�by�the�A/D�driver's'ª¯³·»¿Ã"ÇËÏÓ×Ûßãçëïó÷ûÿ'    *‚command-processing�subroutine.!‰TTL‡5.1.‚Command�Switching�Table*‰PAGE*™5.1.‚Command�Switching�Table*F*‡This�switching�table�is�used�by�the�command-processing‚subroutine‚toK*‚route‚control‚to�the�particular�routine�that�responds�to�the�command�thatH*‚has�been�received.‚The�CMD_CODE�(i.e.,�command-code)‚field‚in‚the‚IOCBH*‚specifies‚the‚particular‚command‚that‚is�requested,�and�we�search�thisL*‚switching�table�to�find�a�match�for�the�given�CMD_CODE�value.‚If�we�find�aJ*‚match‚for‚the‚CMD_CODE�value,�we�transfer�control�to�the�routine�that�isL*‚specified�in�the�switching�table�for�the�given�CMD_CODE�value.‚If�we�don'tJ*‚find‚the‚given‚CMD_CODE�value�in�the�switching�table,�we�return�a�statusH*‚code�to�tell�the�user�task�that�the�CMD_CODE�value‚is‚invalid.ƒIn‚this(*‚case,�of�course,�we�abort�the�command.*D*‡Each‚entry‚in‚the�command�switching�table�contains�two�fields.‚TheH*‚first�field�contains�a�16-bit�unsigned‚relative‚offset‚that‚yields‚theK*‚address‚of‚the�routine�that�responds�to�the�given�command,�and�the�secondJ*‚field�contains�the�16-bit�CMD_CODE�value�for�the�command.‚The�end‚of‚theI*‚switching‚table‚is‚marked‚by�a�zero�sentinel�word�in�the�position�of�an*‚offset�value.*A*‡Notice�that�we�use�a‚relative‚offset‚instead‚of‚using‚an‚actualK*‚address.‚This�approach�has�two�advantages.‚The�first�advantage�is�that�byK*‚using�an�offset�we�can�easily�write�position-independent�code.‚The‚secondJ*‚advantage‚is‚that‚we�can�save�memory�by�using�a�16-bit�offset�instead�of%*‚using�a�long-word�absolute�address.*B*‡The�A/D�driver�searches�this‚switching‚table‚by‚using‚a‚straightG*‚linear‚search.ƒA‚straight‚linear‚search�turns�out�to�be�faster�than�aL*‚binary�search�because�the�table�is�too�short�to�justify�the�added‚overheadF*‚of‚binary‚searching.ƒIf‚the‚table‚ever�expands�to�contain�25�or�moreL*‚entries,�a�binary�search�should�be�considered.‚For�a�table�with�fewer�thanH*‚25‚entries,‚however,‚a‚linear‚search�is�generally�faster�than�a�binaryI*‚search.‚Maximum�speed�with�a�linear�search�can�be�achieved‚if‚the‚tableI*‚entries‚are‚ordered‚with‚the�entries�that�are�used�most�often�appearingL*‚nearest�the�beginning�of�t he�table.‚Since�the�switching�table�is�so�short,M*‚though,�the�table�entries�are�ordered�logically�instead�of�being�ordered�by!*‚usage�to�achieve�maximum�speed.*B*‡The�valid�CMD_CODE�values�for‚the‚A/D‚driver‚are‚the‚consecutiveH*‚integers‚from‚zero‚through‚four,‚so�we�could�easily�use�a�direct�tableL*‚lookup�approach�instead�of�searching�the�switching�table.‚However,�a�tableL*‚search‚is�more�general�than�a�direct�table�lookup,�so�we�use�the�search�to(*‚ensure�flexibility�for�future�changes.  ?CMDSWIT‚DC.W…OPEN_CMD-*-4‹The�open�command�tells�the�A/D�driver0‰DC.W…OPEN‘to‚open‚the�specified�A/D�measurement%*¦channel(s)�for�the�requesting�task. *Â(Continued)-‰PAGEš#######################################1‰DC.W…MEAS_S-*-4�The‚single-endedƒmeasureƒcommand9‰DC.W…MEASURE+SINGLE‡tells‚the‚A/D‚driver�to�make�zero�or)*¦more�single-ended�measurements�from�the#*¦specified�measurement�channel(s). 1‰DC.W…MEAS_D-*-4�Theƒdifferentialƒmeasure‚command7‰DC.W…MEASURE+DIFF‰tells�the�A/D�driver�to‚make‚zero‚or)*¦more�differential�measurements�from�the)*¦specified�differential�channel�pair(s). 8‰DC.W…STOP_CMD-*-4‹The�stop�command�tells�the�A/D�driver2‰DC.W…STOP‘to�terminate�the�measure�command(s),�if#*¦any,ƒthat‚are‚presently‚using‚the%*¦specified‚measurement‚channel(s)ƒor*¦differential�channel�pair(s). 2‰DC.W…CLOSECMD-*-4‹Theƒclose‚command‚tells‚the‚A/D0‰DC.W…CLOSE�driver�to�close�all‚of‚the‚specified)*¦measurement�channel(s)�and�to�make�them#*¦available�for�use�by�other�tasks. -‰DC.W…0–This�zero�sentinel�word�in�the�normal'*¦position‚of‚an�offset�value�marks�the%*¦end�of�the�command�switching�table.1‰TTL‡5.2.‚Subroutine�COMMANDS�(Command�Processor)‰PAGE.*‘5.2.‚Subroutine�COMMANDS�(Command�Processor)*H*‡Subroutine�COMMANDS�is�called�from�CMR�whenever�CMR�receives�a�commandJ*‚from�a�user�task�to�initiate�an�I/O�transaction�with�the�A/D‚driver.ƒAnyM*‚command�that�invokes�subroutine�COMMANDS�in�the�A/D�driver�is�considered�toI*‚be�a�command�that�initiates�an�I/O�transaction�with‚the‚driver,‚so,‚forL*‚example,‚a�command�to�open�or�close�a�measurement�channel�is�considered�toM*‚be�a�command�to�initiate�an�I/O�transaction�with�the�A/D�driver�even�thoughH*‚such‚a‚command‚doesn't‚result‚directly�in�an�I/O�operation�with�an�A/D*‚board.*E*‡Upon�entry�to�subroutine�COMMANDS�register�A2‚contains‚the‚physicalH*‚memory‚address‚of‚the‚CMR‚parameter�block�for�the�command,�register�A5L*‚contains�the�physical�memory�address�of�the�A/D�channel's�CCB,�register‚A6L*‚contains‚the�physical�memory�address�of�the�TCB�that�governs�the�task�thatI*‚invoked�CMR,�and�the�processor�is�in�supervisor‚mode‚at‚interrupt‚levelI*‚zero.ƒThe‚following‚diagram�graphically�summarizes�the�entry�conditions;*‚for�subroutine�COMMANDS�in�the�case�of�a�typical�command.**2*�Typical�Entry�Conditions�for�Subroutine�COMMANDS*1*‰+-----------+‰+----------+‰+------------------+<*‚A2�--->|�CMR‡|-------->|�User…|-------->|‚Input�Buffer�1‚|/*‰|�Parameter�|‰|�Task'sƒ|‰+------------------+*‰|�Block…|‰|�I/O†|„.Ž.*‰+-----------+‰|�Command‚|„.Ž.*Ÿ|�Block„|„.Ž.*Ÿ|Š|*Ÿ|Š|‰+------------------+ *Ÿ|Š|-------->|‚Input�Buffer�n‚|#*Ÿ+----------+‰+------------------+**´Note:‚Input�buffers.*‰+-----------+‰+----------+‰are‚used‚only‚for:*‚A5�--->|�CCB‡|-------->|�MVME-600�|‰the�MEASURE�command./*‰|�(Channel‚|‰|�Memory-‚|‰They�are�not�present,*‰|�Controlƒ|‰|�Mappedƒ|‰for�other�commands.*‰|�Block)„|‰|�I/O�Area�|*‰+-----------+‰+----------+***‰+-----------+*‚A6�--->|�TCB‡| *‰|�(Task…| *‰|�Controlƒ| *‰|�Block)„|*‰+-----------+**E*‡Upon�return�from�subroutine�COMMANDS�register�A6‚must‚be‚preserved.K*‚In‚fact,‚as�a�standard�practice�throughout�the�entire�operating�system�we*‰PAGEJ*‚always�maintain�A6�as�a�pointer�to�the�TCB�for�the�task‚that‚called‚uponI*‚the‚operating‚ system‚to�perform�an�operation.‚If�a�system�crash�somehowJ*‚occurs,�register�A6�can�provide�a�clue�to�the�environment�at‚the‚time‚of *‚the�crash.*G*‡Besides‚preserving�register�A6,�subroutine�COMMANDS�must�put�a�statusG*‚code�into�D0.B�(i.e.,�the‚least-significant‚byte‚of‚register‚D0)‚uponI*‚return‚to‚the‚calling�routine.‚If�subroutine�COMMANDS�processes�the�I/OK*‚request�without�finding�any�errors,�the�subroutine�returns�control‚to‚theK*‚calling‚routine�with�D0.B�=�0�to�indicate�that�all�is�well.‚If�subroutineM*‚COMMANDS�discovers�an�error,�however,�the�subroutine�returns�control�to�theF*‚calling‚routine‚with‚a‚nonzero‚error‚code‚in�D0.B�to�indicate�that�aI*‚problem�has�been�encountered.‚Subroutine�COMMANDS�uses‚a‚unique‚nonzeroM*‚error�code�for�each�particular�error�that�the�subroutine�can�detect,�so�theI*‚user�can�determine�the�exact�nature�of�a�problem‚by‚examining‚the‚errorJ*‚code‚that‚subroutine�COMMANDS�returns�in�D0.B.‚A�complete�list�of�all�ofM*‚the�error�codes�and�their�meanings�is�available�elsewhere�in�the�listing�of*‚the�A/D�driver.*H*‡A�zero�status�code�in�D0.B�indicates�only�that�subroutine�COMMANDS�hasK*‚processed�the�user�task's�I/O�request�without�detecting�any�errors,‚and‚aL*‚zero‚status�code�does�not�necessarily�indicate�that�the�I/O�activities�forK*‚the�I/O�request�have�been�completed�without�any�errors.‚Some�I/O‚requestsM*‚cause�subroutine�COMMANDS�to�set�up�sequences�of�I/O�operations�that�are�toK*‚be�performed�over�an�extended�period�of�time.‚In�cases�like�these,�a‚zeroL*‚status‚code�that�is�returned�in�D0.B�by�subroutine�COMMANDS�indicates�onlyF*‚that�the�subroutine�has�processed�the‚I/O‚request‚and‚has‚set‚up‚theI*‚sequences‚of‚I/O‚operations�without�detecting�any�errors.‚A�zero�statusK*‚code�in�such�a�case�does�not�indicate�that�any�of�the�I/O‚operations‚haveH*‚been‚completed‚successfully,‚and‚the‚I/O�operations�could�cause�errors *‚later�when�they�are�performed.*C*‡Besides�returning�a�status�code‚in‚D0.B,‚subroutine‚COMMANDS‚alsoI*‚returns‚the‚same‚status‚code�in�the�status�field�of�the�user�task's�I/OH*‚command�block.‚The�I/O�command�block�is�the‚parameter‚block‚that‚tellsL*‚subroutine‚COMMANDS�exactly�what�the�user�task�wants�the�driver�to�do,�andL*‚the�layout�of�the�I/O�command�block�is�defined�elsewhere�in�the�listing‚of*‚the�A/D�driver.*C*‡In‚addition‚to‚preserving‚A6‚and�returning�a�status�code�in�D0.B,M*‚subroutine�COMMANDS�must,�of�course,�preserve�the�SP�and�the�system�byte�ofH*‚the‚SR.ƒAll‚other‚registers�may�be�modified�upon�return�to�the�calling *‚routine.*F*‡Subroutine�COMMANDS�performs�the�common�tasks�that�are‚necessary‚forH*‚all‚command‚routines,‚and‚then‚the�subroutine�uses�a�command�switchingL*‚table�to�direct�control�to�the�individual�routine�that�processes�the‚givenE*‚command.ƒIf‚the‚command-code‚value‚in‚the‚I/O�command�block�doesn'tI*‚designate�a�valid�command,�subroutine�COMMANDS�returns‚an‚error‚code‚inM*‚D0.B�(and�in�the�status�field�of�the�user�task's�I/O�command�block)�to�tell,*‚the�user�task�that�the�command�is�invalid.*‰PAGEG*‡The�table�below�summarizes�the�general�usage�of�registers�in�the‚partC*‚of‚subroutine‚COMMANDS‚that‚is‚common‚to‚all‚command‚routines.‚InM*‚particular,�the�final�values�that�are�shown�below�are�in�the�registers�whenE*‚control‚branches‚from‚the‚common‚part‚of‚subroutine‚COMMANDS�to�the4*‚individual�routine�that�handles�the�given�command.*F*‚#�&�A6�=�LOC(TCB�of�the�task�that�invoked�CMR).„#�=�Entry�condition.-*‚#�&�A5�=�LOC(CCB).¡&�=�Preserved�on�return.#*†A4�=�LOC(CMD_CODE�field�in�IOCB).*†A3�=�LOC(DUPETBL).?*‚#ƒA2�=�LOC(CMR�Parameter�Block)�initially.‚Then�LOC(MSBDATA).6*†A1�=�LOC(CNFIELD�in�IOCB)�if�the�IOCB�has�a�CNFIELD.*†A0�=�Scratch.* *†D6.L�=�0.D*†D5.L�=�Number�of�words�in�IOCB�after�CMD_CODE�field.‚Also�in�D4.L.D*†D4.L�=�Number�of�words�i n�IOCB�after�CMD_CODE�field.‚Copy�of�D5.L. *†D3.L�=�0.*†D2.L�=�Scratch.C*†D1.L�=�Scratch.‚Control�offset�for�the�channel�being�initialized.+*†D0.B�=�STATNSNG�(for�the�MEAS_S�command).**B*‡The�individual�command-processing‚routines‚all‚use‚a‚common‚exitG*‚routine‚to‚ensure‚a‚uniform‚return‚condition�for�subroutine�COMMANDS.J*‚Subroutine�COMMANDS�preserves�A6,�A5,�the�SP,�and�the�system‚byte‚of‚theJ*‚SR,‚and‚the‚subroutine�returns�its�status�code�in�D0.B�and�in�the�statusE*‚field�of�the�user�task's‚I/O‚command‚block.ƒAll‚other‚registers‚areK*‚subject‚to‚modification�and�may�contain�meaningless�values�upon�return�to*‚the�calling�routine.*C*‡Note�with�care�that�the�processor�is‚at‚interrupt‚level‚zero‚whenM*‚subroutine�COMMANDS�receives�control,�so�subroutine�COMMANDS�and�all�of�itsG*‚subordinate�routines�are‚subject‚to‚interrupts‚from‚the‚periodically-L*‚activated‚measurement�routine�and/or�from�the�completion�of�an�externally-K*‚triggered�measurement.‚The�periodically-activated�measurement�routine‚andK*‚the‚A/D‚interrupt�handler�may�access�and/or�change�values�in�the�CCB,�andE*‚subroutine�COMMANDS�must�be�carefully�coded�with�this�fact�in�mind.  ?COMMANDS�MOVE.LƒSP,SAVE_SP(A5)‰Save�the‚stack‚pointer‚so‚we‚can$*¦later‚abort‚at‚any‚level‚of�nested$*¦subroutines‚and‚easily‚restoreƒthe%*¦stack‚environment‚that‚existed‚when*¦this�routine�began�execution.-‰PAGEš#######################################2‰MOVE.LƒA5,A4’Set‚A4�<--�LOC(CCB)�to�indicate�that%*¦A4�doesn't‚yet‚contain‚the‚physical)*¦memory�address�of�the�CMD_CODE�field�of'*¦the�user's�IOCB.‚Since�the�IOCB‚can't)*¦possibly�be�at�the�same�physical�memory(*¦location�where�the�CCB�resides,�we‚can'*¦later‚compare‚A4�to�A5�to�find�out�if)*¦A4�has�been�set�to�contain�the�physical)*¦memory�address�of�the�CMD_CODE�field�of&*¦the�user's�IOCB.‚As�long�as�A4‚=‚A5,)*¦we�know�that�A4�doesn't�yet�contain�the&*¦address�of�the�CMD_CODE‚field‚of‚the'*¦IOCB.ƒAfter�A4�=�LOC(CMD_CODE[IOCB]),(*¦we'll�be�able�to�use�A4�to�address‚the&*¦user's‚IOCB.ƒIn�particular,�we'll�be$*¦able�to�access‚the‚IOCB‚to‚store‚a&*¦status‚code‚into‚the�STATUS�field�of *¦the�IOCB. "*¨This�step‚and‚the‚next‚two‚steps%*¦should‚be‚done‚in‚order�with�no�new%*¦intervening�steps.ƒThe‚code‚remains(*¦sensitive‚until�A4�has�been�set�to�its#*¦final�value,�LOC(CMD_CODE[IOCB]). 8‰MOVE.LƒXIOCPK(A2),D6ŠGet�the�physical‚memory‚address‚of0‰MOVEQ.L‚#0,D5�the‚IOCB‚for‚the‚command‚into‚A4.<‰MOVE.WƒXIOPLN(A2),D5ˆSubroutine�LOGPHY�converts�the‚logical2‰BSR†LOGPHY�IOCB‚address�(in�D6.L)�into�a�physical2‰MOVE.LƒD6,A4�address�for�us.‚We�must‚call‚subrou-$*¦tine‚LOGPHY‚with‚A6‚containing‚the)*¦physical�address�of�the�TCB�of�the�task(*¦that‚owns�the�IOCB,�and�we�must�set�up'*¦D5.L�to�specify�the�length‚(in‚bytes)(*¦of�the�IOCB.‚If�all�goes�well,�subrou-)*¦tine�LOGPHY�returns�the�physical�memory*¦address�of�the�IOCB�in�D6.L. %*¨Subroutine‚LOGPHY‚aborts�processing$*¦if�the�IOCB‚that‚we‚specify‚is‚not'*¦entirely‚within‚a�memory�segment�that)*¦belongs�to�the�task�that�owns�the�IOCB.(*¦If‚this�error�occurs,�the�fact�that�we(*¦set�A4�=�A5�above�will�prevent�us‚from'*¦trying‚to‚store�a�status�code�into�an#*¦IOCB�that�doesn't�properly�exist. #*¨We�must‚execute‚one‚more‚critical(*¦step‚to�set�A4�to�its�final�value,�and&*¦then�this�sequence‚of‚critical‚steps*¦will�be�complete.-‰PAGEš#######################################3‰MOVEQ.L‚#0,D6’Clear�D6.L�for�general�use,�and‚then8‰MOVE.WƒD6,(A4)+�initialize�the�STATUS�field�of�the�IOCB3LˆSET†STATUS�to�zero.‚We'll�later�update�the�least-)*¦significant�byte�of�the�STATUS�field�to(*¦reflect�the�actual�status�code�that‚we*¦want�to�return�to�the�user. %*¨As‚we‚clear�the�STATUS�field�of�the(*¦IOCB�here,�we�simultaneously�set�A4‚to(*¦contain‚the�physical�memory�address�of(*¦the�CMD_CODE�field�of�the�IOCB.‚Now�we&*¦can‚safely‚use‚A4�with�autodecrement%*¦addressing �to�update‚the‚LSB‚of‚the*¦STATUS�field�in�the�IOCB. "*¨Thisƒstep‚completes‚the‚critical&*¦sequence�of�three�steps‚that‚must‚be'*¦done‚in‚order�with�no�intervening�new"*¦steps.ƒNow‚we‚can‚safely‚use‚the)*¦common�exit�routine�whenever�we�want�to *¦exit�from�subroutine�COMMANDS. 7‰MOVEQBƒSTATCBLN,D0ŒIf�the�specified�length�of‚the‚IOCB:‰SUBQ.Lƒ#IOCB_MIN,D5‰is‚shorter‚than�the�minimum�allowable4‰BLO.S„CMDEXIT2�length�for�an‚IOCB,‚abort‚processing-‰LSR.L„#1,D5�andƒreturnƒan‚error‚status‚code.5‰MOVE.LƒD5,D4�Otherwise,�set�both�D5.L�and�D4.L�equal$*¦to‚the‚number‚of‚words‚(not�bytes)(*¦remaining�in�the�IOCB�after�the�end‚of(*¦the�CMD_CODE�field.‚We'll�later�use�D5(*¦and�D4�as�counters�when�we�process‚the(*¦remaining�fields�(if�any)�of�the�IOCB. 8‰MOVEQBƒISTACDN,D0�If�the�A/D�channel�is�down,�go�return7‰TST.B„AD_DOWN(A5)Šan�error�status�to‚indicate‚that‚the5‰BNE.S„CMDEX2AŽA/D‚channel�is�out�of�service�for�now.$*¦Although‚we‚could‚process‚OPEN‚and(*¦CLOSE‚commands�for�a�dead�A/D�channel,&*¦we�choose�to�reject‚all‚A/D‚commands*¦for�the�sake�of�consistency.-‰PAGEš#######################################1‰TST.B„BAD_INT(A5)ŒIf‚we‚have‚receivedƒaƒspurious0‰BEQ.S„L9“interrupt‚from�the�A/D�converter�board(*¦and�haven't�yet�reported�it,�clear‚the8‰CLR.B„BAD_INT(A5)Šbad-interrupt‚flag,‚abort�the�current4‰MOVEQBƒSTATBINT,D0Šcommand,‚andƒreportƒtheƒspurious‚32,767‚(i.e.,‚$7FFF)&*¦because‚the‚processor‚interprets�the(*¦value�in�D2.W�as�a�signed�number‚here.&*¦We‚could‚easily‚avoid�this�potential'*¦error�by�adding�just‚one‚instruction,(*¦but‚the�offset�value�in�D2.W�is�not�at'*¦all�likely�to�exceed�32,767.‚The‚size&*¦of‚the‚entire‚driver�(in�its�initial)*¦release)�is�smaller�than�$500�bytes,�so&*¦an‚offset‚in‚excess�of�32,767�is�not'*¦possible�unless�the�driver‚changes‚by"*¦more�than�an�order�of�magnitude.+‰TTL†5.2.1.‚OPEN_CMD�Routine�(OPEN�Command)-‰PAGEš#######################################N*******************************************************************************Ì*@*ˆThe�remaining�part�of�this�program�is�not�commented�yet.‚Any‡*A*ˆcomments�that�exist�beyond�this�point�are�scratch�comments�or‡**ˆpreliminary�comments.¯**Ì*N****************************************************************************** 4*ˆOPEN�Command.‚Control�enters�at�location�OPEN_CMD. %*†#�A6�=�LOC(TCB�of�requesting�task).*†#�A5�=�LOC(CCB).%*†#�A4�=�LOC(CMD_CODE�field�in�IOCB).*†#�A3�=�LOC(DUPETBL).*†#�A2�=�LOC(MSBDATA).*†#�A1�=�LOC(CNFIELD�in�IOCB)./*ˆA0�=�LOC(Channel�block�for�selected�channel). *ˆD7.L�= *†#�D6.L�=�0.2*†#�D5.L�=�Number�of�words�after�CMD_CODE�in�IOCB.2*†#�D4.L�=�Number�of�words�after�CMD_CODE�in�IOCB. *†#�D3.L�=�0.*ˆD2.L�=�Scratch.*ˆD1.L�=�Scratch.*ˆD0.L�=�Scratch.  8L12†BSR†VALID_CN�Validate�next�channel�number,�and�point'*¦A0�to�its�channel�block.‚Also�advance'*¦A1�to�point�to�following�channel�num. ‰MOVEQBƒSTATOPEN,D0'‰TST.L„TCB_ADDR(A0)‰Is�it�already�open?,‰BNE.S„CMDEXIT2�Error:‚Channel�already�open. 7OPEN_CMD�DBRA…D5,L12�Loop�until�all�channels�processed. ,‰BRA.S„L14’No�errors�in�any�channel�numbers.    ,L13†MOVE.Wƒ-(A1),D1�Get�next�channel�number. LˆSET†CNFIELD(‰BSR†CNLBLKAD�Point�A0�to�channel�block.9‰MOVE.LƒA6,TCB_ADDR(A0)†Open�channel�for�requesting�task./L14†DBRA…D4,L13�Loop�until�all�channels�opened.‰TTL†5.2.2.‚Common�Exit�Routine-‰PAGEš#######################################?*ˆCommon�exit�routine.‚Control�falls�in�from�above�in�one�case. %*†#�A6�=�LOC(TCB�of�requesting�task).*†#�A5�=�LOC(CCB).1*†#�A4�=�LOC(CMD_CODE�field�in�IOCB)�or�LOC(CCB). &*ˆSTATUS�word�in�IOCB�is�zero�already. /CMDEXIT1�MOVEQBƒISTAOK,D0ŒD0.B�<--�Status�code.    ,*ˆSecond�entry�point�to�common�exit�routine. *†#�D0.B�=�Status�code. 8CMDEXIT2�CMP.L„A4,A5’If�A4�=�A5,�then�A4�hasn't�yet�been2‰BEQ.S„CMDEXIT3�set�to�contain�the�physical�memory&*¦address�of�the�CMD_CODE�field�of�the&*¦IOCB.‚In�this�case,�we�have�probably)*¦aborted�processing�because�the�IOCB�was(*¦improperly�specified,�and�we�obviously$*¦can't�store�a�status�code�into�the"*¦STATUS�field�of�the�erroneously-#*¦specified�IOCB.‚The�check�that�we(*¦perform�here�prevents�us�from�making�a&*¦wild�store�into�a�random�location�of *¦memory. 3‰MOVE.BƒD0,-(A4)�Put�the�8-bit�status�code�into�the1LˆSET†STATUS�least-significant�byte�of�the�STATUS(*¦word�in�th  e�IOCB.‚The�most-significant)*¦byte�of�the�STATUS�word�is�zero�because'*¦we�cleared�it�at�the�beginning�of�the *¦command-processing�subroutine. DCMDEXIT3�MOVE.LƒSAVE_SP(A5),SP‰Restore�the�stack�pointer,�and�return'‰RTS›control�to�the�routine�that�called&*¦subroutine�COMMANDS.‚The�status�code(*¦is�in�D0.B�as�required.‚Notice�that�we&*¦can�use�this�return�routine�to�abort&*¦processing�from�any�level�within�the$*¦command�service�routine�because�we(*¦restore�the�stack�pointer�to�the�value&*¦that�it�had�when�subroutine�COMMANDS$*¦began�execution�at�its�main�level. #*¨Our�handling�of�the�stack�pointer'*¦appears�to�eliminate�re-entrancy,�but'*¦the�A/D�driver�is�still�re-entrant�in'*¦the�necessary�context�because�subrou-%*¦tine�COMMANDS�can�never�be�called�a(*¦second�time�from�a�user�task�executing)*¦at�interrupt�level�zero�until�we�return*¦control�from�the�first�call. $*¨Subroutine�COMMANDS�can�accept�re-'*¦entrant�calls�for�another�A/D�channel'*¦because�each�channel�has�its�own�CCB.+‰TTL†5.2.3.‚STOP_CMD�Routine�(STOP�Command)-‰PAGEš#######################################?*ˆCLOSE�Command�and�STOP�Command.‚First�part�is�common�to�both. %*†#�A6�=�LOC(TCB�of�requesting�task).*†#�A5�=�LOC(CCB).*†#�A4�=�LOC(CMD_CODE�in�IOCB).*†#�A3�=�LOC(DUPETBL).*†#�A2�=�LOC(MSBDATA).*†#�A1�=�LOC(CNFIELD�in�IOCB)./*ˆA0�=�LOC(Channel�block�for�selected�channel). *ˆD7.L�=4*†#�D6.L�=�0.‚We�set�D6.L�<--�-1�for�a�STOP�command.2*†#�D5.L�=�Number�of�words�after�CMD_CODE�in�IOCB.2*†#�D4.L�=�Number�of�words�after�CMD_CODE�in�IOCB. *†#�D3.L�=�0.*ˆD2.L�=�Scratch.*ˆD1.L�=�Scratch.*ˆD0.L�=�Scratch. :STOP_CMD�MOVEQ.L‚#-1,D6�Set�flag�to�indicate�STOP�command. ,‰TTL†5.2.4.‚CLOSECMD�Routine�(CLOSE�Command)5CLOSECMD�TST.L„D5“D5�=�0�if�no�channels�specified.‚In/‰BNE.S„L19’this�case�we�close�all�open�channels'*¦for�this�task.‚Fall�through�to�make�a)*¦list�of�all�channels�open�to�this�task.  L15†EQU†(MAXCNLS-1)*CNLBLKSZ6‰LEA†CNLBLK+L15(A5),A0„Point�A0�to�last�channel�block.7‰MOVEQWƒMAXCNLS-1,D0‰Channel�number�of�last�channel�and *¦channel�count�to�control�loop.  *ˆFirst�pass�through�the�channel�block(s)�of�the�IOCB�for�both1*ˆsingle-ended�and�differential�MEASURE�commands. %*†#�A6�=�LOC(TCB�of�requesting�task).*†#�A5�=�LOC(CCB).*†#�A4�=�LOC(CMD_CODE�in�IOCB).*†#�A3�=�LOC(DUPETBL).@*ˆA2�=�LOC(Current�field�in�channel�block�for�selected�channel).**†#�A1�=�LOC(First�channel�block�in�IOCB)./*ˆA0�=�LOC(Channel�block�for�selected�channel). *ˆD7.L�=%*ˆD6.L�=�Scratch.‚Address�for�LOGPHY.'*ˆD5.L�=�ScratchƒByte�count�for�LOGPHY.I*†#�D4.L�=�Number�of�words�after�beginning�of�first�channel�block�in�IOCB*�>�0.+*†#�D3.L�=�+0�for�single-ended�measurement."*�-1�for�differential�measurement.I*†#�D2.L�=�Number�of�words�after�beginning�of�first�channel�block�in�IOCB*�>�0.B*ˆD1.L�=�Scratch.‚We�use�it�for�channel�number�of�current�channel.*ˆD0.L�=�Scratch.  @MEAS_LP1�SUBQ.Wƒ#CHNBLKSZ/2,D2‰If�the�remaining�part�of�the�IOCB1‰BHS.S„L23’contains�enough�words�to�accommodate�a)*¦full�channel�block,�go�process�the�next*¦channel�block. :‰ADDQ.Wƒ#CHNBLKSZ/2,D2‰If�we've�finished�processing�all�of3‰BEQ.S„MEAS_PS2�the�words�of�the�IOCB,�go�start�the!*¦second�pass�through�the�channel*¦block(s)�of�the�IOCB. " '*¨Otherwise,�we�have�an�IOCB�that�isn't)*¦formatted�correctly�since�it�contains�a&*¦partial�channel�block�at�its�end.‚In(*¦this�case,�control�falls�into�the�next'*¦routine,�which�reports�an�IOCB�error. AIOCB_ERR�MOVEQBƒSTATIOCB,D0ŒGet�the�status�code�that�indicates�an&*¦IOCB�that�isn't�correctly�formatted.)*¦We've�found�that�the�length�of�the�IOCB&*¦doesn't�match�up�with�the�predefined&*¦IOCB�template�for�a�MEASURE�command. 6MEAS_ERR�BRA†CMDEXIT2�Abort�processing�for�the�MEASURE'*¦command,�and�report�the�error�that�is'*¦indicated�by�the�status�code�in�D0.B.%*¦Control�branches�to�this�error�exit)*¦from�several�different�places�to�report*¦various�types�of�errors. 6L23†MOVEQ.L‚#0,D6’Clear�D6.L�to�indicate�that�we�don't5‰BSR†VALIDATE�allow�the�specified�measurement�channel(*¦to�be�previously�active,�and�then�call%*¦subroutine�VALIDATE�to�validate�the)*¦channel�number�that�is�addressed�in�the'*¦IOCB�by�A1.‚Subroutine�VALIDATE�makes(*¦several�validity�checks�on�the�channel'*¦number,�and�it�aborts�processing�with'*¦an�error�report�if�it�finds�an�error.(*¦If�subroutine�VALIDATE�doesn't�find�an)*¦error,�it�returns�the�specified�channel&*¦number�in�D1.W.‚Also,�the�subroutine(*¦advances�A1�to�point�to�the�next�field'*¦of�the�channel�block�in�the�IOCB,�and'*¦it�points�A0�to�the�CCB�channel�block(*¦for�the�specified�measurement�channel. 7‰LEA†CNL_CMPL(A0),A2ˆPoint�A2�to�the�channel-completion(*¦field�of�the�CCB�channel�block�for�the&*¦specified�measurement�channel.‚We'll)*¦use�A2�with�autoincrement�addressing�to)*¦access�several�of�the�fields�in�the�CCB*¦channel�block. %*¨We'll�save�the�pointer�to�the�first&*¦byte�of�the�CCB�channel�block�in�A0.&*¦At�the�end�of�the�first�pass�through&*¦the�channel�block(s)�of�the�IOCB,�A0)*¦will�point�to�the�CCB�channel�block�for(*¦the�last�measurement�channel�selected,)*¦and�we'll�use�that�pointer�value�during)*¦the�first�iteration�of�the�second�pass. ‰MOVE.Wƒ(A1)+,D0 LˆSET†CHN_CMP‰MOVE.WƒD0,(A2)+LˆSET†CNL_CMPL ‰ROL.B„#7-SUBR_B,D0 ‰BPL.S„L24 1‰SUBQ.Wƒ#2,D2�2�words�for�the�subroutine�address.‰BLO.S„IOCB_ERR ‰MOVE.Lƒ(A1)+,D6 LˆSET†SUBRTNE6‰MOVEQ.L‚#2,D5�Minimum�possible�length�for�subroutine. ‰BSR†LOGPHY 0L24†MOVE.LƒD6,(A2)+�Physical�subroutine�address. LˆSET†SUBRTN ‰MOVE.Lƒ(A1)+,D6 LˆSET†BUFFER‰MOVE.Wƒ(A1)+,D5 LˆSET†BUFSZ ‰BSR†LOGPHY‰MOVE.LƒD6,(A2)+LˆSET†BUF_ADDR ‰CLR.W„(A2)+LˆSET†BUF_PNTR ‰MOVEQBƒEXTTRG+PGA,D0.‰AND.W„(A1)+,D0�Ignore�all�but�those�two�bits.LˆSET†TRIGGAIN ‰AND.B„#MUX+CNLSEL,D1‰ADDQ.Bƒ#MUX07,D1 ‰OR.B…D1,D0 ‰MOVEQBƒMUX815+MUX07,D14‰AND.B„D3,D1�D3�=�$FF�IF�DIFFERENTIAL,�$00�if�single ‰OR.B…D1,D0 ‰MOVE.BƒD0,(A2)+LˆSET†CTRL_VAL ‰ROL.B„#7-EXTTRG_B,D0‰BPL.S„MEAS_LP1 ‰ST.B…ET_FLG_S(SP) ‰TST.B„MEAS_CNT(A5)‰BEQ.S„MEAS_LP1 ‰MOVEQBƒSTATBUSY,D0‰BRA.S„MEAS_ERR4‰TTL†5.2.5.3.‚Second�Pass�through�the�Channel�Blocks-‰PAGEš#######################################?*ˆSecond�pass�through�the�channel�block(s)�of�the�IOCB�for�both1*ˆsingle-ended�and�differential�MEASURE�commands. %*†#�A6�=�LOC(TCB�of�requesting�task).*†#�A5�=�LOC(CCB).*†#�A4�=�LOC(CMD_CODE�in�IOCB).5*†#�A3�=�LOC(DUPETBL).‚Available�for�scratch�use�now.*ˆA2�=;*ˆA1�=�LOC(Current�field�of�current�channel�block�in�IOCB).E*†#�A0�=�LOC(Channel�block�for�selected�channel).‚Initially�points�to>*�CCB�channel�block�for�last�selected�measurement�channel�from *�first�pass. *ˆD7.L�=*ˆD6.L�=�Scratch.*ˆD5.L�=�ScratchI*†#�D4.L�=�Number�of�words�after�beginning�of�first�channel�block�in�IOCB*�>�0.+*†#�D3.L�=�+0�for�single-ended�measurement."*�-1�for�differential�measurement.*ˆD2.L�=�Scratch.B*ˆD1.L�=�Scratch.‚We�use�it�for�channel�number�of�current�channel.*ˆD0.L�=�Scratch.  "MEAS_PS2�MOVE.Bƒ(SP)+,EXT_TRIG(A5)LˆSET†ET_FLG_S‰ADDQ.Bƒ#1,MEAS_CNT(A5)8‰MOVE.Lƒ(SP)+,A1�Point�A1�to�first�channel�block�in�IOCB# LˆSET†CBADDR_S MEAS_LP2�MOVE.Wƒ(A1)+,D1 LˆSET†CHN_NUM>‰MOVE.BƒD1,CNL_PTR(A0)‡Point�previous�channel�block�to�current‰BSR†CNLBLKAD�one. ‰MOVE.Wƒ(A1)+,D0 LˆSET†CHN_CMP‰ROL.B„#7-SUBR_B,D0 ‰BPL.S„L25 +‰SUBQ.Wƒ#2,D4�2�WORDS�FOR�SUBROUTINE�FIELD.+‰ADDQ.Lƒ#4,A1�4�BYTES�FOR�SUBROUTINE�FIELD. L25†EQU†*L26†EQU†BUFSZ-BUFFERC‰MOVE.WƒL26(A1),BUF_SIZE(A0)�The�measurement�channel�is�now�active. ‰ADDQ.Lƒ#CHNBLKSZ-BUFFER,A1 ‰SUBQ.Wƒ#CHNBLKSZ/2,D4‰BHI.S„MEAS_LP2"‰TTL†5.2.5.4.‚Final�Command�Set-Up-‰PAGEš#######################################F*ˆNow�set�up�the�command�variables�in�the�channel�block�for�the�master*‚measurement�channel.  4‰MOVE.BƒCNL_PTR(A0),D1‡Top�half�of�D1.W�=�0�already.'‰BSR†CNLBLKAD�Point�A0�to�top�of�chain.‰LEA†CNL_PTR(A0),A2 3‰TAS.B„(A2)+�Mark�top�of�chain�by�setting�sign�bit. LˆSET†CNL_PTR ‰MOVE.Wƒ(SP)+,(A2)+ LˆSET†COMPL_SLˆSET†CMD_CMPL ,‰MOVE.Lƒ(SP)+,A1�Delta-T�-->�A1.‚(For�RQPA).LˆSET†DELTAT_S ‰MOVE.Wƒ(SP)+,D1 LˆSET†R_CNT_S‰MOVE.WƒD1,(A2)+ LˆSET†RPT_CNT ‰MOVE.LƒA4,(A2)+LˆSET†IOCB_ADR 1‰ST.B…(A2)+’Set�the�flag�that�says�we�haven't�yet3LˆSET†NORQPA�requested�a�periodic�activation�of�the$*¦periodically-activated�measurement'*¦routine�for�this�command.‚We'll�later&*¦clear�the�NORQPA�flag�if�we�success-(*¦fully�request�a�periodic�activation�of(*¦the�periodically-activated�measurement*¦routine�for�this�command. 2‰MOVE.WƒSR,D0’Get�the�SR�value�into�D0.W,�and�save6‰MOVE.WƒD0,-(SP)�a�copy�of�it�on�the�stack�so�we'll�be&*¦able�to�restore�the�present�SR�value*¦later. =‰AND.W„#$FFFF-INT_MASK,D0…Clear�the�interrupt-level�bits�from8‰OR.W…CCBISR(A5),D0ˆthe�SR�value,�and�set�the�interrupt-2‰MOVE.WƒD0,SR�level�bits�to�the�interrupt�level�of'*¦the�A/D�converter�board.‚Then�put�the&*¦updated�SR�value�into�the�SR�to�mask&*¦interrupts�at�the�level�of�the�board&*¦without�changing�any�of�the�other�SR$*¦bits.‚We�take�extra�steps�to�avoid&*¦changing�any�of�the�SR�bits�that�are&*¦presently�undefined�because�those�SR$*¦bits�might�have�meanings�in�future!*¦processors�in�the�68000�family. #*¨We�must�mask�interrupts�before�we'*¦issue�the�RQPA�executive�request�(see%*¦below)�so�we�can�guarantee�that�the$*¦periodically-activated�measurement&*¦routine�won't�be�activated�before�we$*¦perform�the�first�exectuion�of�the&*¦measurement�routine�ourselves.‚Also,#*¦interrupts�must�be�masked�when�we)*¦execute�the�measurement�routine�because'*¦the�measurement�routine�has�no�way�to*¦mask�interrupts�at�the�board. ‰SUBQ.Wƒ#1,D1+‰BEQ.S„L28’Repeat�count�=�1.ƒThe�IMMED�flag *¦doesn't�matter�if�RPT_CNT�=�1. #‰MOVE.LƒA1,D0�Test�Delta-T�(in�A1).%‰SEQ.B„(A2)‘A2�remains�at�LOC(IMMED). LˆSET†IMMED‰BEQ.S„L28’Delta�T�=�0. 1‰MOVE.LƒA0,D2�D2�<--�LOC(CNLBLK�in�CCB)�for�RQPA.!‰LEA†MEAS_PA(PC),A0‡LOC(ROUTINE). ACTIVATE�EQU†0<<15REPEATƒEQU†1<<14‰MOVEQWƒACTIVATE+REPEAT,D1‰MOVE.BƒCCBPPRIO(A5),D1‰MOVE.Lƒ#T0RQPA,D0‰TRAP…#EXEC�Destroys�D0,�D1.‰BRA.S„L27’OK. )‰MOVE.LƒD2,A0�Not�OK.‚LOC(CNLBLK)�-->�A0.*‰BSR†STOP1�Stop�measurements�just�started. ‰MOVEQBƒSTATRQPA,D0‰BRA.S„L29’Go�to�CMDEXIT2. 5L27†CLR.B„-(A2)’We've�successfully�requested�periodic,LˆSET†NORQPA�activation�of�the�periodically-(*¦activated�measurement�routine�for�this'*¦command,�so�clear�the�NORQPA�flag.‚By&*¦clearing�the�NORQPA�flag�we�indicate%*¦that�there�is�a�periodic�activation)*¦active�for�this�command,�and�we'll�know'*¦to�stop�that�periodic�activation�when(*¦we�complete�(or�stop)�the�measurements*¦for�the�command. !‰MOVE.LƒD2,A0�LOC(CNLBLK�in�CCB). =L28†MOVEQ.L‚#T0QEVNTT,D6‹Get�the�code�that�we�use�for�queuing$*¦an�event�from�a�routine�that�isn't)*¦being�executed�as�an�interrupt�handler. 1‰BSR.S„MEAS_RTN�Call�the�measurement�routine.‚The&*¦measurement�routine�returns�a�status*¦value�in�D0.W. #L29†MOVE.Wƒ(SP)+,SR�Restore�the�SR. ‰BRA†CMDEXIT2,‰TTL†5.2.5.5.‚MEAS_RTN�(Measurement�Routine)# -‰PAGEš#######################################D*ˆInterrupts�must�be�masked�throughout�this�routine.‚This�routine�is*ˆnot�re-entrant. *†#�A5�=�LOC(CCB).*ˆA3�=�LOC(BUFFER).*ˆA2�=�LOC(MSBDATA).*ˆA1�=�Scratch.#*†#�A0�=�LOC(Channel�block�in�CCB). *†#�D6.L�=�T0QEVNTI�or�T0QEVNTT.*ˆD5.W�=�Status�code.*ˆD4.L�=�Scratch�in�STOP1.*ˆD3.B�=�Scratch�in�STOP1. *ˆD2.B�=�CTRL_VAL(A0)�initially.1*ˆD2.L�=�Buffer�offset�later.‚(Top�half�is�zero.)3*ˆD1.W�=�Measurement�result;�later,�channel�number.**ˆD0.L�=�Scratch.‚D0.W�=�Status�on�return.  MEAS_RTN�MOVE.LƒCCBCHB(A5),A2 >MEAS_NXT�MOVEQ.L‚#0,D1�We'll�depend�on�byte�1�of�D1�being�zero5‰MOVE.BƒCTLOFFST(A0),D1†both�here�and�later�(at�L52).9‰MOVE.BƒCTRL_VAL(A0),D2†Get�CTRL_VAL�and�keep�it�in�D2.B.2‰MOVE.BƒD2,CONTROL(A2,D1.W)‚Start�the�measurement. L43†EQU†8+10‘Cycles�per�loop.�D1.W.‰MOVE.LƒBUF_ADDR(A0),A3‰MOVEQ.L‚#0,D2‰MOVE.WƒBUF_PNTR(A0),D27‰MOVE.WƒD1,0(A3,D2.L)ˆResult�-->�buffer.‚We�use�D2.L�to*¦avoid�sign�extension�of�D2.W. ‰MOVE.WƒCNL_CMPL(A0),D0‰BTST.Lƒ#SUBR_B,D0‰BEQ.S„L48’No�subroutine. ‰MOVE.LƒSUBRTN(A0),A1‰JSR†(A1)‘Call�the�subroutine. L48†ADDQ.Wƒ#2,D2‰CMP.W„BUF_SIZE(A0),D2 ‰BLO.S„L49‰MOVEQ.L‚#0,D21L49†MOVE.WƒD2,BUF_PNTR(A0)†Update�buffer�pointer. *‰BSR.S„WAKEUP�Issue�wakeup�if�appropriate. ‰MOVEQ.L‚#MEAS_TYP,D2 ‰BSR.S„QEVENT ‰MOVEQ.L‚#CP_MASK,D1‰AND.B„CNL_PTR(A0),D1-‰BSR†CNLBLKAD�Point�A0�to�next�channel�block. ‰TST.B„CNL_PTR(A0)!‰BPL†MEAS_NXT�Not�master�channel.  ‰MOVEQ.L‚#0,D5�Good�status. ‰TST.W„RPT_CNT(A0)‰BEQ.S„L50’0�=�infinity. ‰SUBQ.Wƒ#1,RPT_CNT(A0) ‰BEQ.S„L53 L50†TST.B„IMMED(A0)!‰BNE†MEAS_NXT�Repeat�immediately.-‰BRA.S„L55’Return�with�good�status.‚We'll�get&*¦activated�again�by�the�next�periodic *¦activation.  L51†BSR†CNLBLKAD@L52†MOVE.BƒCNL_PTR(A0),D1‡Byte�1�of�D1�=�0�already�from�earlier. ‰BPL.S„L51 L53†MOVE.WƒCMD_CMPL(A0),D0,‰BSR.S„WAKEUP�Issue�a�wakeup�if�appropriate. ‰MOVEQ.L‚#CMPL_TYP,D2 ‰MOVE.WƒD5,D1 ‰BSR.S„QEVENT ‰LSR.W„#EVENT_B+1,D0 ‰BCS.S„L54 ‰MOVE.LƒIOCB_ADR(A0),A1‰MOVE.WƒD5,-(A1) LˆSET†STATUS L54†BSR.S„STOP1 L55†MOVE.WƒD5,D0‰RTS‰TTL†5.2.5.6.‚Subroutine�WAKEUP-‰PAGEš#######################################*ˆSubroutine�WAKEUP ;*†#�A0�=�LOC(Channel�block�for�current�measurement�channel) *†#�D0.W�=�completion�code. +*ˆWe�preserve�all�registers�except�the�CCR.  WAKEUPƒEQU†*WU_REGS‚REG†A0/D0‰MOVEM.L‚WU_REGS,-(SP) ‰LSR.W„#WAKEUP_B+1,D0 ‰BCC.S„L56 ‰MOVEQ.L‚#T0WAKEUP,D0‰MOVE.LƒTCB_ADDR(A0),A0 ‰TRAP…#EXEC L56†MOVEM.L‚(SP)+,WU_REGS‰RTS‰TTL†5.2.5.7.‚Subroutine�QEVENT-‰PAGEš#######################################*ˆSubroutine�QEVENT *†#�A5�=�LOC(CCB).*†#�A0�=�LOC(Channel�Block). "*†#�D6.L�=�Executive�Request�Code.*†#�D2.L�=�Event�type.-*†#�D1.W�=�Status�code�or�measurement�result.*†#�D0.W�=�Completion�option.  QEVENTƒEQU†* !QREGS„REG†D0-D3/D5-D7/A0-A1/A3-A5‰MOVEM.L‚QREGS,-(SP) ‰MOVE.WƒD0,D3�Completion�option.‰LSR.W„#EVENT_B+1,D0‰BCC.S„L59’No�event�requested. ‰SWAP…D30‰MOVE.WƒD1,D3�Status�code�or�measurement�result. ‰ROL.W„#8,D2 L57†EQU†ELENGTH<<24L58†EQU†ECODE<<16 ‰OR.L…#L57+L58+EDRVCD,D2 ‰MOVE.LƒD6,D0$ ‰MOVE.LƒTCB_ADDR(A0),A0 ‰TRAP…#EXEC#‰NOP›Good.‚BRA.S�L59�in�the�future.)*ˆ—Bad.‚For�now,�just�ignore�that. L59†MOVEM.L‚(SP)+,QREGS‰RTS‰TTL†5.2.6.‚Common�Subroutines‰TTL†5.2.6.1.‚Subroutine�STOP-‰PAGEš#######################################6*ˆStop�the�measurements�specified�by�the�STOP�command.-*ˆControl�enters�at�STOP2�for�a�STOP�command.0*ˆControl�enters�at�STOP1�for�a�MEASURE�command.@*ˆInterrupts�are�masked�at�the�level�of�the�A/D�converter�board. *†#�A5�=�LOC(CCB).*ˆA3�=-*†#�A2�=�LOC(MSBDATA).‚We�set�this�for�STOP1.*†#�A1�=�LOC(last�CNFIELD)�+�2./*ˆA0�=�LOC(Channel�block�for�selected�channel). *ˆD7.L�=*ˆD6.L�=*ˆD5.L�=C*†#�D4.L�=�Number�of�words�after�CMD_CODE�in�IOCB.‚Set�0�for�STOP1.H*†#�D3.B�=�+0�initially�to�indicate�that�no�active�MEASURE�commands�have*’been�stopped.:*�Nonzero�later�if�we�actually�stop�an�active�measurement.;*�Initially�random�for�STOP1.‚We�know�we'll�stop�something.*ˆD2.L�=�Scratch.*ˆD1.L�=�Scratch.*ˆD0.L�=�Scratch.  6STOP1„MOVE.LƒSP,A1�To�prevent�bus�error�on�access�with*¦-(A1). ‰MOVE.LƒCCBCHB(A5),A2*‰MOVEQ.L‚#0,D4�Clear�count�for�no�repeats. 0L30†CLR.W„ACTIVE(A0)‹Mark�this�channel�inactive. )‰MOVEQ.L‚#0,D1�To�clear�top�half�of�D1.W.<‰MOVE.BƒCNL_PTR(A0),D1‡Get�channel�number�of�next�channel�in0‰BPL.S„L32’this�group.‚Branch�unless�the�current&*¦channel�is�the�master�channel�of�the*¦group. 1‰MOVE.BƒD1,D3�Save�pointer�to�next�channel�in�D3.%*¦Notice�that�D3.B�<>�0�now�since�the*¦sign�bit�is�set. 6‰TST.B„NORQPA(A0)�Skip�if�the�measurement�sequence�for+‰BNE.S„L31’this�command�wasn't�periodically *¦activated. 3‰MOVEQ.L‚#-1,D1�Bit�15�says�deactivate�routine;�all*¦other�bits�ignored./‰MOVE.LƒA0,D2�Pointer�to�current�channel�block.9‰MOVEQ.L‚#T0RQPA,D0‹Code�for�Request�Periodic�Activation.,‰TRAP…#EXEC�Request�deactivation�of�routine.(‰NOP›Good�return.‚No�such�thing�as�a�bad#*¦return,�so�we�merge�good�and�bad.*¦Destroys�D0�and�D1.-‰PAGEš#######################################*†#�D6.L�=�+0�if�selected�channel�is�not�allowed�to�be�active.*�-1�otherwise.*ˆD5.L�=*ˆD4.L�=*ˆD3.L�=*ˆD2.L�="*ˆD1.W�=�Channel�Number�on�return.*ˆD0.L�=�Scratch.  >VALIDATE�BSR.S„VALID_CN�Validate�next�channel�number�and�point'*¦A0�to�its�channel�block.‚Also�advance*¦A1�to�point�to�next�word. ‰MOVEQBƒSTATNOPN,D08‰CMP.L„TCB_ADDR(A0),A6†Is�the�channel�open�to�this�task?#‰BNE.S„CMDEX2BŽNo.‚Report�an�error. )‰TST.L„D6“Skip�the�active�test�for�a�STOP‰BNE.S„L38’command. ‰MOVEQBƒSTATACTV,D04‰TST.W„ACTIVE(A0)‹Is�the�channel�active�(measuring)?4‰BNE.S„CMDEX2BŽYes.‚Report�an�error.‚Can't�close�it. L38†RTS!‰TTL†5.2.6.3.‚Subroutine�VALID_CN-‰PAGEš#######################################*ˆSubroutine�VALID_CN *†#�A5�=�LOC(CCB).%*†#�A4�=�LOC(CMD_CODE�field�in�IOCB).*†#�A3�=�LOC(DUPETBL).9*†#�A1�=�LOC(Channel-number�word).‚Incremented�on�return.-*ˆA0�=�LOC(Selected�Channel�Block)�on�return. 9*ˆD1.W�=�Channel�Number�on�return.‚On�entry�for�CNLBLKAD.*ˆD0.L�=�Scratch.  >VALID_CN�MOVE.Wƒ(A1)+,D1�Get�next�channel�number�into�D1.W�andLˆSET†CNFIELDŽadvance�A1. LˆSET†CHN_NUM ‰MOVEQBƒSTAT0_95,D0‰CMP.W„#MAXCNLS-1,D1*‰BHI.S„CMDEX2BŽError:‚Channel�Number�>�95. ‰MOVEQBƒSTATDUPE,D0‰TAS.B„0(A3,D1.W) LˆSET†DUPETBL6CMDEX2B‚BNE.S„CMDEX2CŽError:‚Duplicate�channel�number. ‰TST.B„DIFF_F(A5)"‰BEQ.S„CNLBLKAD�Single-ended�mode. ‰MOVEQBƒSTATDIFF,D0‰BTST.Lƒ#MUX_BIT,D13‰BNE.S„CMDEX2CŽInvalid�differential�channel�number. CNLBLKAD�LEA†CNLBLK(A5),A0‰MOVEQWƒCNLBLKSZ,D0 ‰MULU…D1,D00‰ADD.L„D0,A0�Point�A0�to�selected�channel�block. ‰RTSH‚TTL„5.2.6.4.‚Subroutine�LOGPHY�(Logical-to-Physical�Address�Conversion)-‰PAGEš#######################################*ˆSubroutine�LOGPHY %*†#�A6�=�LOC(TCB�of�requesting�task). B*†#�D6.L�=�LOC(Buffer)�to�be�converted.‚Logical�address�coming�in;*­physical�address�going�out.%*†#�D5.L�=�Number�of�bytes�in�buffer. LOGPHYƒEQU†*LOG_REGS�REG†D0-D5/D7/A0‰MOVEM.L‚LOG_REGS,-(SP) ‰MOVE.WƒD6,CCR"‰BCS.S„L39’Starts�at�odd�location. ‰MOVE.WƒD5,CCR(‰BCS.S„L39’Contains�odd�number�of�bytes. ‰TST.L„D5‰BEQ.S„L39’Length�=�0. ‰MOVE.LƒTCBTST(A6),A0‰MOVE.Lƒ#T0LOGPHY,D0 ‰TRAP…#EXEC.‰BRA.S„L40’Valid�physical�address�now�in�D6.L.‰NOP7L39†MOVEQBƒISTAADD,D0‹Bad�buffer�address�and/or�length. 8CMDEX2C‚BRA†CMDEXIT2�Notice�that�A4�and�A5�have�not�been"*¦changed.‚The�values�of�these�two)*¦registers�are�important�in�the�command-(*¦exit�routine,�and�we�must�never�branch)*¦to�the�command-exit�routine�while�A4�or*¦A5�is�modified. '*¨Some�code�uses�the�branch�instruction(*¦here�as�a�stepping�stone�to�get�to�the*¦command-exit�routine. L40†MOVEM.L‚(SP)+,LOG_REGS‰RTS2‰TTL†6.‚Periodically-Activated�Measurement�Routine-‰PAGEš#######################################-*ˆPeriodically-activated�measurement�routine. $*†#�D0.L�=�Number�of�time�intervals.*†#�D1.L�=�LOC(Channel�block).*ˆD2.L�=�Used�by�MEAS_RTN.*ˆD3.L�=�Used�by�MEAS_RTN.*ˆD4.L�=�Used�by�MEAS_RTN.*ˆD5.L�=�Used�by�MEAS_RTN.*ˆD6.L�=�T0QEVNTI. "*ˆA0�=�saved�and�restored�by�exec."*ˆA1�=�saved�and�restored�by�exec.*ˆA2�=�Used�by�MEAS_RTN.*ˆA3�=�Used�by�MEAS_RTN.*ˆA5�=�LOC(CCB). 8*†#�SR�=�Masked�at�the�level�of�the�A/D�converter�board.  MEAS_PA‚EQU†*PA_REGS‚REG†D2-D6/A2-A3/A5‰MOVEM.L‚PA_REGS,-(SP)/‰MOVE.LƒD1,A0�A0�<--�LOC(Master�channel�block). /‰MOVEQ.L‚#0,D0�A0�-�CNLBLK-CNL_NUM(A0)*CNLBLKSZ‰MOVE.BƒCNL_NUM(A0),D0‰MULU.Wƒ#CNLBLKSZ,D0‰LEA†-CNLBLK(A0),A5‰SUB.L„D0,A5�A5�<--�LOC(CCB). ‰TST.B„ET_WAIT(A5)% )‰BNE.S„L60’Waiting�on�ET.‚Skip�this�time. ‰MOVEQ.L‚#T0QEVNTI,D6 ‰BSR†MEAS_RTN L60†MOVEM.L‚(SP)+,PA_REGS‰RTE‰TTL†7.‚Interrupt�Handler-‰PAGEš#######################################*ˆInterrupt�handler !*ˆD0�=�Saved�and�restored�by�CMR.*ˆD1�=�Used�by�MEAS_RD.*ˆD2�=�Used�by�MEAS_RD.*ˆD3�=�Used�by�MEAS_RD.*ˆD4�=�Used�by�MEAS_RD.*ˆD5�=�Used�by�MEAS_RD. !*ˆA0�=�Saved�and�restored�by�CMR.!*ˆA1�=�Saved�and�restored�by�CMR.*ˆA2�=�Used�by�MEAS_RD.*ˆA3�=�Used�by�MEAS_RD.*†#�A5�=�LOC(CCB). B*†#�SR�=�Masked�at�the�interrupt�level�of�the�A/D�converter�board.  INTERUPT�MOVE.LƒCCBCHB(A5),A1‰TST.B„MSBDATA(A1)ŠClears�SR.C. LˆSET†INTFF_B%‰BPL.S„L63’Not�our�interrupt.‚Return. ‰TST.B„ET_WAIT(A5))‰BNE.S„L61’Waiting�on�ET.‚Good�interrupt. ‰ST.B…BAD_INT(A5)'‰TST.B„LSBDATA(A1)ŠClear�bad�interrupt. ‰BRA.S„L62 L61†EQU†*INT_REGS�REG†D1-D6/A2-A3‰MOVEM.L‚INT_REGS,-(SP)‰CLR.B„ET_WAIT(A5) 5‰MOVE.LƒCBPTR(A5),A0‰Pointer�to�active�channel�block.&‰MOVE.LƒA1,A2�Pointer�to�LOC(MSBDATA).‰MOVEQ.L‚#T0QEVNTI,D6 ‰BSR†MEAS_RD ‰MOVEM.L‚(SP)+,INT_REGS L62†EQU†*CARRY„EQU†1<<0‰OR.B…#CARRY,CCRL63†RTS ééé'œ ?‰TTL†MVME-600�and�MVME-601�Analog-to-Digital�I/O�Driver�Program   /*ƒVV‡VVƒMM‡MMƒEEEEEEEEE„6666666…0000000…00000007*ƒVV‡VVƒMMM…MMMƒEEEEEEEEEƒ666666666ƒ000000000ƒ000000000(*„VV…VV„MMMMƒMMMMƒEEŠ66…66ƒ00„/00ƒ00„/00)*„VV…VV„MM�MM�MM�MMƒEEŠ66Š00ƒ//00ƒ00ƒ//005*…VVƒVV…MM‚MMM‚MMƒEEEEEEEE„66666666„00‚//�00ƒ00‚//�004*…VVƒVV…MMƒMƒMMƒEEEEEEEE„666666666ƒ00�//‚00ƒ00�//‚00&*†VV�VV†MM‡MMƒEEŠ66…66ƒ00//ƒ00ƒ00//ƒ00$*†VV�VV†MM‡MMƒEEŠ66…66ƒ00/„00ƒ00/„003*‡VVV‡MM‡MMƒEEEEEEEEEƒ666666666ƒ000000000ƒ000000000+*ˆVˆMM‡MMƒEEEEEEEEE„6666666…0000000…0000000   *—AAAAAŽ//ƒDDDDDDDDD*–AAAAAAAŒ//„DDDDDDDDDD*•AA…AAŠ//†DD…DD*•AA…AA‰//‡DD…DD*•AAAAAAAAAˆ//ˆDD…DD*•AAAAAAAAA‡//‰DD…DD*•AA…AA†//ŠDD…DD*•AA…AA…//‹DD…DD*•AA…AA„//‹DDDDDDDDDD*•AA…AAƒ//ŒDDDDDDDDD   4*…DDDDDDDDD„RRRRRRRR„IIIIIIƒVV‡VVƒEEEEEEEEEƒRRRRRRRR7*…DDDDDDDDDDƒRRRRRRRRRƒIIIIIIƒVV‡VVƒEEEEEEEEEƒRRRRRRRRR*†DD…DDƒRR…RR…II†VV…VV„EEŠRR…RR*†DD…DDƒRR…RR…II†VV…VV„EEŠRR…RR-*†DD…DDƒRRRRRRRRR…II‡VVƒVV…EEEEEEEE„RRRRRRRRR+*†DD…DDƒRRRRRRRR†II‡VVƒVV…EEEEEEEE„RRRRRRRR*†DD…DDƒRR‚RRˆIIˆVV�VV†EEŠRR‚RR*†DD…DDƒRRƒRR‡IIˆVV�VV†EEŠRRƒRR-*…DDDDDDDDDDƒRR„RR„IIIIII‡VVV‡EEEEEEEEEƒRR„RR**…DDDDDDDDD„RR…RRƒIIIIIIˆVˆEEEEEEEEEƒRR…RR        E*ˆThis�program�is�re-entrant�and�position�independent,‚and�it�can�runF*ƒin�a�ROM�that‚appears‚at‚any�convenient‚location‚in�the�68000�memoryB*ƒspace.„A�single‚copy�of�the‚A/D‚driver�can‚control�any‚number‚of@*ƒMVME-600�and�MVME-601�A/D�measurement�channels�simultaneously.‰TTL‡Table�of�Contents‰PAGE*ŸTable�of�Contents*I*‚1.‚Introduction�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.„4*I*‚2.‚Options,�Macros,�Equates,�and�Data�Structures‚.�.�.�.�.�.�.�.�.�.ƒ10*E*†2.1.‚Miscellaneous�Options�and�E% quates‚.�.�.�.�.�.�.�.�.�.�.�.�.ƒ11E*†2.2.‚Macro�Definitions‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ15E*†2.3.‚CMR�Parameter�Block‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ22F*†2.4.‚IOCB�(I/O�Command�Block)�Structure�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ27*š¡Aª-²(º*Â(Ê#Ò.Ú3â3ê6ò:ú:: 9 $"$*726:)B3J8R6Z;b5j<r:z9‚6Š7?*Œ2.4.1.‚IOCB�OFFSET�Block‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ28?*Œ2.4.2.‚CMD_CODE�(Command-Code)�Equates‚.�.�.�.�.�.�.�.�.�.ƒ38@*Œ2.4.3.‚STATUS�Equates�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ39*E*†2.5.‚CCB�(Channel�Control�Block)�Structure‚.�.�.�.�.�.�.�.�.�.�.ƒ46*@*Œ2.5.1.‚Universally-Defined�CCB�Fields�.�.�.�.�.�.�.�.�.�.�.ƒ47?*Œ2.5.2.‚CCB�Fields�for�the�A/D�Driver‚.�.�.�.�.�.�.�.�.�.�.ƒ53*0*”2.5.2.1.‚A/D�CCB�Fields�Relating�to�a�Complete/*žMVME-600�A/D�Converter�Board�.�.�.�.�.�.�.ƒ543*”2.5.2.2.‚CCB�Channel�Block�for�an�A/D�Measurement.*žChannel‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ60*F*†2.6.‚TCB�(Task�Control�Block)�Structure�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ74E*†2.7.‚I/O�Event�Structure‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ75E*†2.8.‚MVME-600�and�MVME-601�Memory�Layout‚.�.�.�.�.�.�.�.�.�.�.�.ƒ79*?*Œ2.8.1.‚Memory-Mapped�I/O�Space‚.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ79@*Œ2.8.2.‚Control�Register�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ82?*Œ2.8.3.‚Output�Data�Registers‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ85@*Œ2.8.4.‚Channel-Number�Equates�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ87*J*‚3.‚Required�Driver�Tables�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ90*F*†3.1.‚A/D�Service�Vector�Table�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ91F*†3.2.‚Parameter�Table�for�CMR�Parameters�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ93F*†3.3.‚Revision�Table�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.ƒ94*I*‚4.‚Initialization�Section�(Subroutine�INITIAL)‚.�.�.�.�.�.�.�.�.�.�.ƒ95* *Â(Continued)*‰PAGE*™Table�of�Contents,�Continued*J*‚5.‚Command�Service�Section‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.‚101*F*†5.1.‚Command�Switching�Table‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.‚102F*†5.2.‚Subroutine�COMMANDS�(Command�Processor)‚.�.�.�.�.�.�.�.�.�.‚104*@*Œ5.2.1.‚OPEN_CMD�Routine�(OPEN�Command)‚.�.�.�.�.�.�.�.�.�.‚111@*Œ5.2.2.‚Common�Exit�Routine‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.‚xxx@*Œ5.2.3.‚STOP_CMD�Routine�(STOP�Command)‚.�.�.�.�.�.�.�.�.�.‚xxxA*Œ5.2.4.‚CLOSECMD�Routine�(CLOSE�Command)�.�.�.�.�.�.�.�.�.�.‚xxx@*Œ5.2.5.‚MEAS_D�and�MEAS_S�Routines�(MEASURE�Commands)‚.�.�.‚xxx*9*”5.2.5.1.‚Initial�Decoding�of�Header�Section�.�.�.�.‚xxx8*”5.2.5.2.‚First�Pass�through�the�Channel�Blocks‚.�.‚xxx9*”5.2.5.3.‚Second�Pass�through�the�Channel�Blocks�.�.‚xxx9*”5.2.5.4.‚Final�Command�Set-Up�.�.�.�.�.�.�.�.�.�.�.‚xxx9*”5.2.5.5.‚MEAS_RTN�(Measurement�Routine)�.�.�.�.�.�.‚xxx8*”5.2.5.6.‚Subroutine�WAKEUP‚.�.�.�.�.�.�.�.�.�.�.�.‚xxx8*”5.2.5.7.‚Subroutine�QEVENT‚.�.�.�.�.�.�.�.�.�.�.�.‚xxx*A*Œ5.2.6.‚Common�Subroutines�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.‚xxx*8*”5.2.6.1.‚Subroutine�STOP‚.�.�.�.�.�.�.�.�.�.�.�.�.‚xxx8*”5.2.6.2.‚Subroutine�VALIDATE‚.�.�.�.�.�.�.�.�.�.�.‚xxx8*”5.2.6.3.‚Subroutine�VALID_CN‚.�.�.�.�.�.�.�.�.�.�.‚xxx1*”5.2.6.4.‚Subroutine�LOGPHY�(Logical-to-Physical/*žAddress�Conversion)‚.�.�.�.�.�.�.�.�.�.�.‚xxx*K*‚6.‚Periodically-Activated�Measurement�Routine�.�.�.�.�.�.�.�.�.�.�.�.‚xxx*J*‚7.‚Interrupt�Handler‚.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.‚xxx*K*‚8.‚Symbol-Table�Concordance�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.�.‚xxx‰TTL‡1.‚Introduction‰PAGE*Ÿ1.‚Introduction*H*‡This�program,�which�is�commonly�known�as�the�A/D�driver,�is�the�RMS68KG*‚I/O‚driver‚for‚the‚MVME-600‚analog-to-digital‚converter�board�and�theK*‚MVME-601�analog-to-digital�expander�board.‚RMS68K�is�the�popular�name‚forI*‚the‚Real-Time‚Multitasking‚Software‚that�forms�the�kernel�of�Motorola'sL*‚real-time�operating�system�for�processors�in�the�68000�family,�and�the‚A/DI*‚driver‚runs‚in‚sup& ervisor‚mode�as�an�extension�of�the�RMS68K�executive.F*‚The�A/D�driver‚provides‚the‚device-dependent‚portion‚of‚the‚softwareG*‚interface‚for‚any‚desired‚number‚of‚MVME-600�A/D�converter�boards�and*‚MVME-601�A/D�expander�boards.*G*‡The�A/D�driver�is�written�as�a�re-entrant�program,�and�the�program‚isL*‚also�written�to�be�position�independent.‚Therefore,�the�object�program�forJ*‚the�A/D�driver�can�be�executed�from�a�ROM�that�appears‚at‚any‚convenientF*‚location‚in‚the‚68000‚address‚space,‚and‚the�program�can�be�executedM*‚re-entrantly�so�that�a�single�copy�of�the�A/D�driver�can�control�any�numberC*‚of�MVME-600�and�MVME-601�A/D�measurement�channels�simultaneously.*E*‡Besides‚reading�any‚further,‚the�reader�should�carefully�review�the)*‚hardware�user's�manual�for‚the‚MVME-600F*‚A/D‚converter‚board‚and‚the‚MVME-601‚A/D�expander�board.‚That�manualG*‚describes�both�boards�in‚detail,‚and‚it‚provides‚complete‚informationJ*‚regarding‚the‚jumpers‚and�other�hardware�options�that�are�available�withF*‚the�boards.‚The�hardware�manual�for‚the‚MVME-600‚and‚the‚MVME-601‚is*‚available�as�follows:*‰PAGEG*‚MVME600�Analog�Input�Module�MVME601�A/D�Expander�Module�User's�Manual(*‚Manual�Number:‚MICROSYSTEMS�MVME600/D1*'*‚Motorola�Semiconductor�Products,�Inc.*‚Literature�Distribution*‚P.�O.�Box�20912*‚Phoenix,�Arizona‚85036*‚(602)�994-6561**‰PAGEG*‡The�driver�is�largely�table�driven,�and�many�future�modifications‚canF*‚be‚made‚by‚simply‚changing‚table‚entries‚or�by�adding�new�entries�to*‚existing�tables.*B*‡The�subroutines�in�the‚A/D‚driver‚are‚general-purpose‚in‚nature.J*‚Instead‚of‚being‚used�to�the�limits�of�their�capabilities�in�the�presentG*‚version�of�the�driver,�they‚are‚flexible‚enough‚to‚perform‚additionalL*‚functions�that�may�be�needed�in�the�future.‚Some�subroutines�may�be�calledI*‚from�only�one�place,�but�they�are�still�coded‚as‚subroutines‚to‚provideL*‚modularity‚of�organization�and�to�make�their�functions�easily�available�to!*‚future�maintenance�programmers.*A*‡Instead�of�using‚a‚complicated‚and‚error-prone‚method‚of‚makingJ*‚measurements‚under‚interrupt‚control,�the�A/D�driver�uses�a�simple�senseD*‚loop�to�make‚normal‚measurements.ƒA‚measurement‚that‚is‚made‚underJ*‚sense-loop‚control‚requires‚only�38�microseconds�of�sense-loop�overhead,H*‚and�the�overhead�that�is�required�to‚service‚a‚single‚interrupt‚easilyH*‚exceeds‚38‚microseconds.ƒTherefore,‚the�driver�actually�saves�time�andF*‚improves�throughput�by�using�a‚simple‚sense‚loop‚instead‚of‚using‚anJ*‚interrupt-driven‚scheme‚for�making�measurements.‚The�A/D�driver�does,�ofI*‚course,�use�an�interrupt-driven�scheme�when�the�driver‚wants‚to‚make‚an#*‚externally-triggered�measurement.*E*‡To‚promote‚readability‚and�maintainability,�the�following�standards3*‚are�carefully�observed�throughout�the�A/D�driver.*=*ŒAll�instructions�in�the�A/D�driver�are�typed�in�upper‚case,>*‡and‚comments‚are‚always‚typed‚in�a�mixture�of�upper�case�and%*‡lower�case�to�maximize�readability.*<*ŒTab�stops�in�the�A/D�driver�are�in�columns�10,�19,‚40,‚and=*‡42,‚and‚the‚right-hand‚margin‚is�in�column�78.‚The�same�tab;*‡stops‚and‚the‚same‚right-hand‚margin‚are‚used‚religiously<*‡throughout‚the‚driver‚to‚ensure‚consistent‚formatting.‚The?*‡opcode�field�starts�at�the�tab�stop�in‚column‚10,‚the‚operand*‰PAGEB*‡field‚starts�at�the�tab�stop�in�column�19,�and�the�comment�field=*‡starts�at�the�tab�stop�in�column�40.‚We‚use‚the‚tab‚stop‚in:*‡column‚42‚to‚provide‚indentation‚for‚the‚first‚line‚of�aA*‡paragraph�of�code�comments.‚Please�refer�to�any�section�of‚codeA*‡anywhere‚in‚the�entire�program�listing�to�see�how�code�comments*‡are�formatted.*<*ŒInstructions�throughout�the�A/D�driver�are‚carefully‚coded:*‡to‚prevent‚the‚operand‚field‚of‚an‚instruction‚from‚ever>*‡extending�into�the�comment�field,‚which‚begins‚in‚column‚40.A*‡Where‚necessary,‚we�define�labels�of�a�local�nature�to�allow�usA*‡to�shorten�a�long�operand�field�& and�thereby�prevent‚the‚operandA*‡field‚from�extending�into�the�comment�field.‚By�maintaining�the?*‡strict�columnization�of‚non-overlapping‚fields‚throughout‚theA*‡entire‚program,‚we�significantly�improve�the�readability�of�the *‡listing.*;*ŒThe�current�version�of�Motorola's‚68000‚assembler‚doesn'tC*‡support�local�labels,�so�we�use�labels�of�the�form�Lj,�Ljj,�Ljjj,;*‡or�Ljjjj�where‚local‚labels‚would‚ordinarily‚be‚used.ƒFor=*‡example,‚a‚label‚such‚as‚L1,‚L12,�L123,�or�L1234�in�the�A/D=*‡driver�is�always�a�local�label�with�no�global�significance.*6*ŒWe�use�the�label�"L"‚in‚a‚rather‚special‚way.ƒWhen‚aC*‡segment�of�code�uses�an�addressing�mode�such�as�register-indirect>*‡addressing�to�access�a‚variable‚without‚explicitly‚using‚theB*‡variable's‚label,�we�place�a�SET�assembler�directive�immediately:*‡after�the‚code‚segment‚to‚set‚L‚temporarily‚equal‚to‚the?*‡variable's‚label.ƒWe‚don't�really�care�about�the�value�of�the?*‡label�L,�but�we�do�care�about�the�fact‚that‚the‚SET‚assemblerC*‡directive�generates�a�concordance�entry�for�the�variable's�label.A*‡Future�maintenance�programmers�will�conveniently�be�able‚to‚useC*‡the�concordance�listing�to�find�references�to�variables�even�when6*‡the�variable�names�aren't�used�directly�in�the�code.*E*‡Some�of�the�labels�that�are�used�in�the�various‚I/O‚data‚structuresK*‚are‚non-mnemonic,‚and�a�few�of�the�labels�in�the�data�structures�are�evenL*‚anti-mnemonic.‚These�labels�have�been�created�by�a�number�of�people�as�theH*‚operating‚system‚has‚grown‚over‚the�years,�and�these�labels�are�now�soG*‚firmly�entrenched�that�they�can't‚reasonably‚be‚changed.ƒAlthough‚theK*‚labels‚in‚the�I/O�data�structures�can't�easily�be�changed,�the�A/D�driverL*‚does�at�least�provide�comments�to�explain�the�true�meanings�of�the‚variousG*‚fields�of�the�I/O�data�structures�as�they�are�used�by�the�A/D�driver.*5‰TTL‡2.‚Options,�Macros,�Equates,�and�Data�Structures‰PAGE2*�2.‚Options,�Macros,�Equates,�and�Data�Structures*B*‡Before‚we‚get‚into‚the‚actual‚code�of�the�A/D�driver,�we�need�toI*‚define�a�few�miscellaneous�macros�and�some�equates�that‚are‚used‚by‚the *‚driver.*F*‡We‚also‚need�to�define�the�data�structures�with�which�the�A/D�driverL*‚works.‚These�data�structures�include�the�IOCB�(I/O�Control�Block),�the�CMRI*‚parameter‚block,‚the‚CCB‚(Channel�Control�Block),�the�TCB�(Task�ControlI*‚Block),�the�I/O�measurement�event�message,�and‚the‚I/O‚completion‚eventJ*‚message.ƒThe‚A/D�driver�shares�these�data�structures�with�other�parts�ofI*‚the�system�software,�and�the�A/D�driver�doesn't�use‚every‚part‚of‚everyJ*‚data‚structure.ƒThe�documentation�in�this�section�explains�primarily�theF*‚parts�of�the�data�structures�that�are�significant�to�the�A/D�driver.*E*‡Besides�using�the�data�structures�that�are�mentioned‚above,‚the‚A/DH*‚driver‚also‚deals‚with‚the‚memory-mapped�I/O�area�for�the�MVME-600�A/DH*‚converter�board�and�its�subordinate�MVME-601‚A/D‚expander‚boards.ƒThisH*‚section‚of‚the‚listing‚includes‚a�definition�of�that�memory-mapped�I/O*‚area.+‰TTL‡2.1.‚Miscellaneous�Options�and�Equates*‰PAGE(*”2.1.‚Miscellaneous�Options�and�Equates*D*‡This‚section‚contains‚some‚options�that�tell�the�assembler�what�weM*‚want�it�to�do,�and�this�section�also�contains�some�miscellaneous�equates�toK*‚define‚labels�that�are�useful�for�the�code�in�the�A/D�driver.‚The�equatesL*‚in�this�section�are�presented�in�alphabetical�order�for�ease�of‚reference.E*‚The‚options‚must‚occur‚before‚any‚code-affecting‚or‚code-generatingL*‚statements�because�the�options�tell�the�assembler�how�to�assemble�the‚rest*‚of�the�program.  1‰NOFORMAT–####################################### ‰OPT†CRE,PCS /CODE…EQU†8–This�label�defines�the�number�of‚the(*¦program‚section�that�contains�code�and&*¦constants.‚Section�8�is‚a‚relatively"*¦arbitraryƒsection,ƒbut‚it‚is‚the&*¦section�where�the‚system‚expects‚(by%*¦default)�to�see�code�for�a�program. ?DELAY„EQU†38�mic' rosecondsˆThis�label�defines�the�amount�of�time$*¦(in‚terms‚of‚microseconds)‚that‚is(*¦required‚for�an�MVME-600�A/D�converter)*¦board�to�complete�a�single�A/D�measure-&*¦ment.ƒThe‚A/D�driver�uses�this�label(*¦when�the�driver�delays�to�wait�for‚the"*¦boardƒto‚make‚a‚measurement.ƒThe'*¦driver�times�each�A/D‚measurement‚and'*¦aborts‚with‚an�error�if�the�A/D�board)*¦doesn't�complete�a�measurement�within�a*¦reasonable�amount�of�time.-‰PAGEš#######################################)EXEC…EQU†0–This‚label‚is‚used‚with‚aƒTRAP%*¦instruction‚to‚generate‚a‚trap�that *¦requests�an�executive�service. 8INT_MASK�EQU†$0700’This�label�defines�a�bit�mask�for�the#*¦interrupt-levelƒbitsƒin‚the‚68000&*¦status�register.‚The�A/D‚driver‚uses'*¦this‚label‚when�the�driver�deals�with*¦the�interrupt-level�bits. :MAXCNLS‚EQU†(1+5)*16�This�label�defines�the�maximum�number(*¦of‚measurement�channels�that�can�exist%*¦in�a�single�CMR�A/D‚channel.ƒAn‚A/D'*¦channel‚must‚contain�one�MVME-600�A/D(*¦converter�board,�and�it�can‚optionally%*¦contain‚as‚many‚as‚five�subordinate(*¦MVME-601�A/D�expander�boards.‚The�main)*¦A/D�converter�board�contains�16�single-&*¦ended�measurement‚channels,‚and‚each$*¦expanderƒboard‚contributes‚16‚more$*¦single-ended�measurement�channels. ;‰IFNE…MAXCNLS/4*4-MAXCNLS„The�A/D‚driver‚contains‚code‚that-‰FAILš[****�ERROR�****�ERROR�****�ERROR�****]-‰ENDCšworks�under�the�assumption�that�MAXCNLS&*¦is‚evenly‚divisible�by�4.‚If�someone$*¦ever‚changes‚something‚thatƒcauses'*¦MAXCNLS‚not‚to�be�evenly�divisible�by(*¦4,�the�statement�that�is‚conditionally(*¦skipped‚here�will�generate�an�assembly&*¦error�to�alert�the‚programmer‚to‚the$*¦failure.ƒBy‚using‚the‚assembler�to'*¦perform�this�check,�we�can�be‚sure‚of$*¦finding‚the‚error‚at‚assembly‚time)*¦instead�of�finding�it�later�as�a�result#*¦of�a�difficult�debugging�session.-‰PAGEš#######################################0MHZ†EQU†100”This�label�defines�the�maximum‚clock&*¦rate‚(in‚terms‚of�megahertz)�that�is(*¦expected�for�a�68000�microprocessor‚in&*¦the‚near‚future.‚The�A/D�driver�uses)*¦this�label�when�it�times�a�measurement,&*¦and‚we‚want‚MHZ�to�be�high�enough�to(*¦insure�an�adequate�time�delay�with‚the'*¦fastest‚foreseeable�68000.‚If�we�ever&*¦start�getting�68000‚systems‚that‚can(*¦run‚with�clock�speeds�in�excess�of�100(*¦megahertz,�we�must�adjust�the�value‚of'*¦this‚label�upward.‚On�the�other�hand,)*¦a�value�for�MHZ�that�is�larger�than�the"*¦actualƒspeedƒof‚the‚system‚clock(*¦doesn't�present�any�problems.‚A�larger%*¦MHZ‚value‚simply‚means‚that�the�A/D(*¦driver�delays�longer�in�a�STOP‚command'*¦and‚before‚it�aborts�a�measurement�in)*¦the�case�of�an�A/D�converter�board�that%*¦has‚gone‚bad.ƒSince�the�extra�delay&*¦occurs�only�in‚conjunction‚with‚STOP)*¦commands�and�with�board�failures,�it�is)*¦not�likely�to�be�a�noticeable�factor�in*¦actual�practice. /SAFETYƒEQU†2–This‚label‚defines‚a�safety�factor(*¦that�the�A/D�driver�uses�when�it‚times&*¦out‚a‚measurement.‚By�delaying�twice%*¦as�long�as‚should‚be‚necessary,‚the(*¦A/D‚driver�provides�an�extra�margin�of'*¦safety�that�will�forestall‚the‚advent'*¦of‚timing‚errors�until�timing�changes(*¦exceed�the�limit�of�the�safety�factor.-‰PAGEš#######################################4T0LOGPHY�EQU†8–These�labels�define�executive-request7T0QEVNTI�EQU†24“codes�that�are�used�when�the�A/D�driver7T0QEVNTT�EQU†23“makes�executive�requests�via�TRAP�#EXEC3T0RQPAƒEQU†34“calls�to�the�executive.‚The‚executive6T0WAKEUP�EQU†22“requests‚and�their�functions�are�fully#*¦documented‚in‚theƒstandardƒRMS68K%*¦documentation‚package.ƒBriefly,‚the)*¦functions�of�these�particular�executive*¦requests�are�as�follows: $*¨T0LOGPHY‚converts‚a‚logical�memory)*¦address�into�a�physical�memory�address.)*¦Address�conversion�is�necessary�because(*¦tasks�use�logical�memory-mapped‚memory(*¦addresses‚whereas�the�A/D�driver,�like(*¦the�rest�of�the�operating�system,‚uses#*¦actual�physical�memory�addresses. '*¨T0QEVNTI�queue' s�an�event�message�from(*¦an�interrupt�handler�to�a�task.‚Please$*¦noteƒthatƒa‚periodically-activated#*¦routine‚such‚asƒtheƒperiodically-&*¦activated‚A/D‚measurement‚routine�is(*¦considered�to�be�an�interrupt�handler. '*¨T0QEVNTT�queues�an�event�message�from'*¦a‚task-level‚process�(such�as�the�A/D)*¦driver's�command-processing�subroutine)"*¦toƒa‚task.ƒThe‚driver's‚command-(*¦processing�subroutine�is�considered‚to'*¦be‚a‚task-level�process�because�it�is$*¦invoked�directly‚as‚a‚result‚of‚an'*¦executive‚request‚from�a�task�instead#*¦of�being�invoked�by�an�interrupt. '*¨T0RQPA�requests�a�periodic�activation'*¦of‚a‚specified�routine�at�a�specified'*¦interrupt�level.‚The�T0RQPA‚executive(*¦request‚can�also�be�used�to�deactivate$*¦a‚routine‚that‚has‚previously‚been$*¦activated.ƒThe‚A/D‚driver‚uses�the&*¦T0RQPA�executive‚request‚to‚activate"*¦and„deactivateƒtheƒperiodically-$*¦activated�A/D�measurement�routine. %*¨T0WAKEUP�wakes�up�a‚specified‚task."*¦TheƒA/Dƒdriver‚uses‚the‚T0WAKEUP%*¦executive�request�to‚wake‚up‚a‚user'*¦task‚when‚the�user�task�has�asked�the(*¦driver�to�wake�it�up�at�the‚completion)*¦of�some�measurement�or�some�sequence�of*¦measurements.‰TTL‡2.2.‚Macro�Definitions‰PAGE*œ2.2.‚Macro�Definitions*G*‡This‚section�contains�the�definitions�of�several�macros�that�might�beL*‚useful�in�the�A/D�driver.‚For�ease�of�reference�the�macros�in�this�section&*‚are�presented�in�alphabetical�order.*C*‡Macros‚are‚occasionally‚useful‚for‚modifying�some�of�the�built-in#*‚characteristics�of�the�assembler.-‰PAGEš#######################################0ADDIA„MACRO›This‚macro�is�useful�when�we�want�to#*¦add‚an‚immediate‚value‚to‚an‚"*¦register.„Ifƒthe‚immediate‚value#*¦happens�to‚be‚in‚the‚range‚from‚1(*¦through‚8,�this�macro�generates�a�one-!*¦word‚ADDQ.Lƒinstruction.„Ifƒthe(*¦immediate‚value�is�out�of�range�for�an(*¦ADDQ.L�instruction�but�is�small‚enough)*¦to�be�represented�correctly�in�a�16-bit&*¦two's-complement‚number‚system,‚this"*¦macroƒgeneratesƒaƒtwo-word‚ADD.W)*¦instruction�knowing�that�sign�extension)*¦will�occur�at�execution�time�to�add�the)*¦correct�32-bit�value�to�the�entire�(*¦register.‚Otherwise,�this�macro�gener-&*¦ates�a�three-word�ADD.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$*¦ADDIA�macro�is�invoked�as�follows. !*¦[