.MCALL .MODULE .MODULE NC,VERSION=22,COMMENT=,AUDIT=NO ; Copyright (c) 1998 by Mentec, Inc., Nashua, NH. ; All rights reserved ; ; This software is furnished under a license for use only on a ; single computer system and may be copied only with the ; inclusion of the above copyright notice. This software, or ; any other copies thereof, may not be provided or otherwise ; made available to any other person except for use on such ; system and to one who agrees to these license terms. Title ; to and ownership of the software shall at all times remain ; in Mentec, Inc. ; ; The information in this document is subject to change without ; notice and should not be construed as a commitment by Digital ; Equipment Corporation, or Mentec, Inc. ; ; Digital and Mentec assume no responsibility for the use or ; reliability of its software on equipment which is not supplied ; by Digital or Mentec, and listed in the Software Product ; Description. ;++ ; ; Edit Who Date Description of modification ; ---- --- ---- --------------------------- ; 001 WLD 19-NOV-90 Remove definition of FBMON$ ; 022 ARB 03-JAN-97 Add SPFUNs 206, 207, and 210 ;-- .SBTTL CONDITIONAL ASSEMBLY SUMMARY ;+ ;COND ; LOOP (0) controls loopback code ; 0 no loopback code ; 1 yes loopback code ; ; MMG$T std conditional = 1 ; TIM$T std conditional (no code effects) ; ERL$G std conditional (no code effects) ;- NI$CNA = 1 ;We're building NC .INCLUDE "SRC:NI.MAC" ;Include the class handler code .SBTTL .SBTTL ******************************************************** .SBTTL * DECNA Ethernet Controller Device Handler * .SBTTL ******************************************************** .SBTTL General Information ;+ ; Title : Ethernet DECNA driver ; ; Author : Carlos Alonso ; ; Date : 14-Nov-84 ; ; Info : The DECNA, Professional 300 Series to Ethernet Adapter, is a ; communications option which resides in a Professional 300 ; System option slot. This communications option allows higher ; level software protocols, an Rt-11 spfun interface to allow ; users to write applications, to communicate with their peers ; over a 10 Megabyte/second Ethernet. The Ethernet protocol ; utilizes encapsulated packets containing 64 and 1500 data ; bytes. The DECNA interfaces to the Ethernet through a Digital ; H4000 transreceiver or as part of a cluster around a DELNI ; (Local Network Interconnect). The DECNA conforms to the ; Ethernet Local Area Network Specification, Version 2.0. ; The DECNA may be subdivided into four sections: ; o The Ethernet Serial Interface ; o The Ethernet Communications Controller ; (Based on the Intels' 82586 chip) ; o The Dual-ported Memory ; o Professional 300 Bus Interface ; ; However will maintain this program should become familiar and ; reference the following two documents: ; ; 1-. Intels' - LAN Components User's Manual ; ; 2-. DECNA-K Professional 300 Series to Ethernet ; Adapter. Engineering Specification ; ;- .SBTTL General RT-11 Definitions ; Now set the audit trail .AUDIT .NI ;Class handler .AUDIT .NC ;Port handler ; Conditionals - Always PRO and XM. .IIF NDF MMG$T MMG$T = 1 ; XM only ; Testing conditional .IIF NDF LOOP LOOP = 0 ; Loopback code ; SYSCOM locations ; SYSPTR = 54 ; Pointer to base of RMON ; RMON fixed offsets QCOMP = 270 ; Address of I/O completion routine ; SPUSR = 272 ; Special device error word SYSVER = 276 ; Monitor version number (byte) CONFIG = 300 ; Configuration word CONFG2 = 370 ; Configuration word extension PRO$ = 020000 ; Processor is a PRO-3xx SYSGEN = 372 ; Sysgen feature word ; MEMPTR = 430 ; Offset to memory control block ptr ; CORPTX = 4 ; Offset to extended mem block ; P1EXT = 432 ; Address of PAR1 externalization rtn ; ; BIT definitions ; BIT00 = 1 ;2 ** 0 BIT01 = 2 ;2 ** 1 BIT02 = 4 ;2 ** 2 BIT03 = 10 ;2 ** 3 BIT04 = 20 ;2 ** 4 BIT05 = 40 ;2 ** 5 BIT06 = 100 ;2 ** 6 BIT07 = 200 ;2 ** 7 BIT08 = 400 ;2 ** 8 BIT09 = 1000 ;2 ** 9 BIT10 = 2000 ;2 ** 10 BIT11 = 4000 ;2 ** 11 BIT12 = 10000 ;2 ** 12 BIT13 = 20000 ;2 ** 13 BIT14 = 40000 ;2 ** 14 BIT15 = 100000 ;2 ** 15 .SBTTL Macros ; 1. Start the CNA controller. .MACRO SRTCNA CNACMD,ERRADR MOV CNACMD,SCBCMD(R1) ; Get command mask in place JSR PC,CMD ; Go do command BCS ERRADR ; Branch if error .ENDM SRTCNA ; 2. Get control block ( from a pool allocated for data structures needed for ; communicating with the CNA). .MACRO GETBLK ERRADR,?A CALL GTBLK BCC A JMP ERRADR A: .ENDM GETBLK ; 3. Restore control block .MACRO PUTBLK CALL PTBLK .ENDM PUTBLK ; 4. Save and Restore registers. .MACRO SAVRG A .IRP REG, ; Repeat for parameters MOV REG,-(SP) ; Save in stack .ENDR .ENDM SAVRG .MACRO RESRG A .IRP REG, ; Repeat for parameter MOV (SP)+,REG ; Restore from stack .ENDR .ENDM RESRG ; 5. Map to extended and unmap. .MACRO MAP PAR1VL MOV PAR1VL,@#KISAR1 .ENDM MAP ;6. Generate page definitions .MACRO PAGDEF NUM,ADDR PG'NUM' = ADDR PHYL'NUM' = *100 PHYH'NUM' = &77 .ENDM PAGDEF .SBTTL Description of DECNA/Host Interaction ;+ ; DECNA/Host interaction: ; Communications between the CNA and the Host are carried out via shared ; memory. The CNA consist of two independent units: the Command Unit CU ; and the Receive Unit RU. The CU executes commands from shared memory. ; THe RU handles all activites related to frame recption. THe CU and RU ; enable the CNA to engage in the two activities simultaneously: the CU ; may be fetching and executing commands out of memory, and the RU may ; be storing received frames in memory. ; ; --------- ---------- ; | | Shared Memory | | ; | Host | _________________________ | DECNA | ; | | --------------| |-------| | ; |_______| | | |________| ; | Initialization Root | ; | | ; | System Control Block | ; | | ; | RU CU | ; |_______________________| ; ; The Shared Memory structure (inside the CNA) is composed of four parts ; Initialization Root, System Control Block SCB, Command List, and ; Receive FRame Area RFA. ; The Initalization Root is at a predetermined location in memory, ; (0fffff6h) known to both the Host and DECNA and contains a pointer to ; the SCB at initialization time. ; The SCB serves as a bidirectional mailbox between the host and the CU ; and RU. It is the central element through which the host and the DECNA ; exchange control and status information. ; The CU is a list of command for the CU which are placed in memory unit ; called a Command Block. ; The RU is a list of free frame descriptors and a list of buffers pre- ; pared by the user - so packets arrive without being solicited. ; Following is a more detailed description of these and more data stru- ; ctures. .SBTTL CNA Device Register and Data Structures ; CNA Device Registers ( I/O page ). ; ; ------------------------------- ; | Option ROM Data | 00 CNARMD ; ------------------------------- ; | Option ROM Address | 02 CNARMA ; ------------------------------- ; | Control Register | 04 CNACTL ; ------------------------------- ; | Memory High Order Bits | 06 CNAMEM ; ------------------------------- ; ;- ;+ ; Control Register Definitions(write only register0 ; ; ------------------------------------- ; | RE | | OA | LP | CA | IE | ME | EM | ; ------------------------------------- ; ; Where: ; RE = Reset (cycling bit causes reset of controller) ; The function resets the CNA to the ETHERNET parameter ; ; OA = Option/Address Rom selection ; 0 selects Option ROM ; 1 selects Physical Address ROM ; ; LP = Loopback(1 selects internal controller loopback) ; ; CA = Control Awake(cycling bit instructs CU to look at SCB) ; ; IE = Interrupt Enable(1 selects enable) ; ; ME = Memory Enable (1 enables dual ported memory) ; ; EM = Enable memory ;- CR.EM = BIT00 ;enable memory CR.ME = BIT01 ;Memory Chip Enable CR.IE = BIT02 ;Interrupt Enable CR.CA = BIT03 ;Control Awake CR.LP = BIT04 ;Loopback CR.OA = BIT05 ;Option/Address Selection CR.ED = BIT07 ;enable Intel 82586 ;+ ; System Configuration Pointer (SCP) ; ; This structure points to Intermediate System Control Block(ISCB). ; It is located at the top of the Dual-ported memory. ; ; Format is: ; -------------------------------- ; | | SYSBUS | 0FFFFF6H ; -------------------------------- ; |\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\| 0FFFFF8H ; -------------------------------- ; |\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\| 0FFFFFAH ; -------------------------------- ; |A15 ISCP ADDRESS A0 | 0FFFFFCH ; -------------- | ; |\\\\\\\\\\\\\\|A23 A16 | 0FFFFFEH ; -------------------------------- ; ; where: ; SYSBUS 0 = Word Mode(16 bits) ; 1 = Byte Mode(8 bits) ; ; ISCP 22 bit pointer to System Control Block ; ;- ; Top of 128k Dual ported memory - Use top page (PAR1) value. ; ; 1. load PAR1 = TOPAR1 Change mapping using MPHTR$ ; 2. load R0 = 20000 ; 3. Access SYSBUS(R0) ; 4. Access ISCP(R0) TOPAR1 = 137600 ; PAR1 value to load. SYSBUS = 017766 ; Selects mode ISCP = 017774 ; Location of ISCP ;+ ; Intermediate System Control Pointer ; ; ------------------------------- ; | | BUSY | ISCBSY ; ------------------------------- ; |A15 SCB OFFSET A00| ISCOFF ; ------------------------------- ; |A15 SCB BASE A00| ISCBSE ; --------------- | ; |\\\\\\\\\\\\\\\|A23 A16| ISCBSE + 2 ; ------------------------------- ; ;***Note*** All the CNA data structures must be residing on a 64K ; boundary, laid out by the base of the SCB and the 16-bit ; offset. ;- ;+ ; System Control Block ; ; ------------------------------------- ; | CX | PR | CN | RN | CUSTAT | RUSTAT | SCBSTS ; ------------------------------------- ; | XC | RP | NC | NR | CUCMD | RUCMD | SCBCMD ; ------------------------------------- ; |Command Block List Offset | SCBCBL ; ------------------------------------- ; |Receive Packet Area Offset | SCBPRA ; ------------------------------------- ; |Number of CRC Errors | SCBCRC ; ------------------------------------- ; |Number of Framing Errors* | SCBALN ; ------------------------------------- ; |Number of Resource Errors | SCBRSC ; ------------------------------------- ; |Number of Overrun Errors | SCBOVR ; ------------------------------------- ;- ;SCBSTS - status word for CNA ; ST.CX = BIT15 ;Command Done Interrupt ST.PR = BIT14 ;Packet Receive Interrupt ST.CN = BIT13 ;CU Not Ready Interrupt ST.RN = BIT12 ;RU Not Ready Interrupt ST.CU = BIT11-BIT08 ;CU Status Field CU.IDL = 0 ;CU Idle CU.SPN = 1*BIT08 ;CU Suspended CU.RDY = 2*BIT08 ;CU Ready ST.RU = BIT07-BIT04 ;RU Status Field RU.IDL = 0 ;RU Idle RU.SPN = 1*BIT04 ;RU Syspended RU.NRS = 2*BIT04 ;RU No Resources RU.RDY = 4*BIT04 ;RU Ready ; ;SCBCMD - SCB command word bit definitions ; CM.XC = BIT15 ;CLear Command Done Int CM.RP = BIT14 ;Clear Packet Received Int CM.NC = BIT13 ;Clear CU Not Rdy Int CM.NR = BIT12 ;Clear RU No Resources Int CLFLGS=CM.XC+CM.RP+CM.NC+CM.NR ;clear all interrupt flags CM.CU = ST.CU ;CU Command Field CU.NOP = 0 ;CU No Operations Command CU.SRT = 1*BIT08 ;CU Start Command CU.RES = 2*BIT08 ;CU Resume Command CU.STP = 3*BIT08 ;CU Suspend(Stop) Command CU.ABT = 4*BIT08 ;CU Abort Command CM.RE = BIT07 ;CNA hardware reset command CM.RU = ST.RU ;RU command field RU.NOP = 0 ;RU No Operations Command RU.SRT = 1*BIT04 ;RU Start Command RU.RES = 2*BIT04 ;RU Resume Command RU.STP = 3*BIT04 ;RU Suspend(Stop) Command RU.ABT = 4*BIT04 ;RU Abort Command ;+ ; Command Block Format ; ; --------------------------------------- ; | C | B | Command Specific Status | CBLSTS ; --------------------------------------- ; | EL | S | I |\\\\\\\\\\\\\\\\\\\| CMD | CBLCMD ; --------------------------------------- ; |A15 Link Field | CBLLNK ; --------------------------------------- ; | Command Specific Parameters | ; --------------------------------------- ; ;- CBLSTS = 0 ;Command Block Status Word CBL.C = BIT15 ;Command Complete Bit CBL.B = BIT14 ;Command Begun Bit CBL.OK = BIT13 ;Command Executed Successfully CBL.AB = BIT12 ;Command Was Aborted CBLCMD = 2 ;Command Block Command Word CBL.EL = BIT15 ;End of List Bit CBL.S = BIT14 ;Suspend Bit CBL.I = BIT13 ;Interrupt Bit CBL.CM = BIT03-1 ;Command Field CM.NOP = 0 ;No Operation CM.SPA = 1 ;Set Physical Address CM.CFG = 2 ;Configure CM.SMA = 3 ;Set Multicast Address CM.XMT = 4 ;Transmit CM.TDR = 5 ;Perform TDR Test CM.DMP = 6 ;Dump Status of Intel 82586 CM.DIA = 7 ;Diagnose CBLLNK = 4 ;Command Block Link Word RLSADD = 14 ; Address of last Deallocator ; Individual commands ;+ ; Configure Command Bit Defintions (CM.CFG = 2) ; ; ------------------------------------ ; | Common command block parameters | ; ------------------------------------ ; |\\\\\\\\|FIFO LMT|\\\\\\\| BYTE CNT | CFGWA ; ------------------------------------ ; |XL|IL|PL|AL| ALEN |SB|SA|\\\\\\\\\\\| CFGWB ; ------------------------------------ ; |INTER PCKT GAP|EB| EPRI |\\| LPRI | CFGWC ; ------------------------------------ ; | RETRY NUM |\\\| SLOT TIME | CFGWD ; ------------------------------------ ; |DS|CDT|RS|CRS|PD|BS|CC|NI|TN|MD|BD|P| CFGWE ; ------------------------------------ ; |\\\\\\\\\\\\\\\\\| MIN PACKET SIZE | CFGWF ; ------------------------------------ ;- ; ;Offset Definitions ; CFGWA = 6 CFGWB = 10 CFGWC = 12 CFGWD = 14 CFGWE = 16 CFGWF = 20 ; ;Default Configuration parameters ; CFGDFA = CFA.LM+4 ;set byte count to 4 CFGDFB = CFB.PL+CFB.AL+CFB.AN ;Set AL =1 reset is default values CFGDFC = CFC.GP ;interpacket gap of 96 bytes CFGDFD = CFD.RT+1000 ; retry of 16 plus slot time of 512. CFGDFE = CFE.TN ; set TONO_CRS = 1 ; ;Bit definitions for CONFIGURE command block ; CFA.LM = 10*BIT08 ;FIFO Limit of 8 bytes CFA.BY = BIT04-1 ;Byte Count Mask CFB.XL = BIT15 ;External Loopback CFB.IL = BIT14 ;Internal Loopback CFB.PL = 2*BIT12 ;Preamble Length of 8 bytes CFB.AL = BIT11 ;Locate Address in buffer CFB.AN = 6*BIT08 ;Address length of 6 bytes CFB.SB = BIT07 ;Save bad packets in a buffer CFB.SA = BIT06 ;External Ready Sychronization CFC.GP = ^d96*BIT08 ;inter packet gap of 96 bytes CFC.EB = BIT07 ;If zero than start backoff after ;jamming has finished CFC.EP = BIT07-BIT04 ;Priority Mask CFC.LP = BIT03-1 ;Linear Prority Mask CFD.RT = ^D15*BIT12 ;Retry count of 15 times CFD.TM = BIT11-1 ;Slot Time Mask CFE.DS = BIT15 ;Clear means trcvr has collision det CFE.CD = BIT15-BIT12 ;CDT Fill Mask CFE.RS = BIT11 ;Clear means external carrier det sig CFE.CR = BIT11-BIT08 ;Carrier Detect Fill CFE.PD = BIT07 ;Bit Stuffing parameter(0 = ETHERNET) CFE.BS = BIT06 ;Bitstuffing Framing Mode(0=ETHERNET) CFE.CC = BIT05 ;CCITT CRC if reset CFE.NI = BIT04 ;if 0 then append CRC to message CFE.TN = BIT03 ;if one then xmit with no carrier sense CFE.MD = BIT02 ;if 0 then use Manchester recording CFE.BD = BIT01 ;if set then disable broadcast addrs CFE.P = BIT00 ;if set then enable promiscuous mode CFF.MN = BIT08-1 ;Min Packet size mask ;+ ; Multicast Setup Defintions (CM.SMA = 3) ; ; ------------------------------------ ; | Common command block parameters | ; ------------------------------------ ; | Length (bytes) of Multicast List | MLTCNT ; ------------------------------------ ; | Byte 1 | Byte 0 | MLTADR ; ------------------------------------ ; | ... | Byte 3 | ; ------------------------------------ ; | ... | Byte n | ; ------------------------------------ ; ;- MLTCNT = 6 ;count field for multicast list MLTADR = 10 ;start of multicast field ;+ ; Transmit Command Defintions (CM.XMT = 4) ; ; -------------------------------------- ; | C | B | Command Specific Status | XMTSTS ; -------------------------------------- ; | EL | S | I |\\\\\\\\\\\\\\\\\\\| CMD | XMTCMD ; --------------------------------------- ; |A15 Link Field | XMTLNK ; --------------------------------------- ; | Buffer Descriptor Pointer | XMTBDP ; --------------------------------------- ; | CCB Pointer | XMTCCB ; --------------------------------------- ;- XMTSTS = CBLSTS XMTCMD = CBLCMD XMTLNK = CBLLNK XMTBDP = 06 ;Buffer Descriptor Pointer XMTCCB = 10 ;Destination Address ; ; additional status returned in transmit case ; XM.CSL = BIT10 ;Carrier sense lost XM.CTS = BIT09 ;Clear to Send XM.OVR = BIT08 ;Overrun Transferring data XM.DFR = BIT07 ;Transmit was deferred XM.HBT = BIT06 ;Heartbeat XM.ABT = BIT05 ;Xmit Abort due to excessive collision XM.AMT = BIT04-1 ;Deferral count mask ;+ ; Transmit Buffer Descriptor ; ; -------------------------------- ; | EP |\\| Current Buffer Length | TBDCNT ; -------------------------------- ; | Buffer Descriptor Link Address | TBDLNK ; -------------------------------- ; | Buffer Address | TBDBUF ; -------------------------------- ; |\\\\\\\\\\\\\\\\\\| Addr Ext | TBDEXT ; -------------------------------- ;- TBDBGN = 0 TBDCNT = TBDBGN ;Current Buffer Length TBD.EP = BIT15 ;End of Packet Bit TBD.LN = BIT14-1 ;Current Length Field TBDLNK = TBDBGN+2 ;Descriptor Link Address TBDBUF = TBDBGN+4 ;Buffer Address TBDEXT = TBDBGN+6 ;Buffer Address Extension TBDCCB = TBDBGN+10 ;+ ; Receive Packet Descriptor Format (An area in itself...) ; -------------------------------------- ; | C | B | Receive Packet Status | PKTSTS ; -------------------------------------- ; | EL | S | I |\\\\\\\\\\\\\\\\\\\\\\\\\\| PKTCMD ; --------------------------------------- ; | Link Field | PKTLNK ; --------------------------------------- ; | Buffer Descriptor Offset | PKTBUF ; --------------------------------------- ; | RCV CCB Pointer | PKTCCB ; --------------------------------------- PKTSTS = 0 ;Packet Block Status Word PK.C = BIT15 ;Packet Complete Bit PK.B = BIT14 ;Packet Begun Bit PK.OK = BIT13 ;Packet received w/o errors PK.CRC = BIT11 ;CRC errors PK.FRM = BIT10 ;Framing errors PK.RER = BIT09 ;Resource error PK.OVR = BIT08 ;DMA Overrun PK.SHT = BIT07 ;Packet too short PKTCMD = 2 ;Packet Block Command Word PKT.EL = BIT15 ;End of List Bit PKT.S = BIT14 ;Suspend Bit PKT.I = BIT13 ;Interrupt Bit PKTLNK = 4 ;Packet Link Adddress PKTBUF = 6 ;Packet Buffer Descriptor Offset PKTCCB = 10 ;Packet CCB pointer ;+ ;Receive Buffer Descriptor ; -------------------------------- ; | EP | F | Current Buffer Length | RBDCNT ; -------------------------------- ; | Buffer Descriptor Link Address | RBDLNK ; -------------------------------- ; | Buffer Address | RBDBUF ; -------------------------------- ; |\\\\\\\\\\\\\\\\\\| Addr Ext | RBDEXT ; -------------------------------- ; | EL | Max Buffer Length | RBDLEN ; -------------------------------- ; | Address of CCB owning Buffer | ; -------------------------------- RBDBGN = 0 RBDCNT = RBDBGN ;Current Buffer Length RBD.EP = BIT15 ;End of Packet Bit RBD.F = BIT14 ;Buffer Full or being used Bit RBD.LN = BIT14-1 ;Current Length Field RBDLNK = RBDBGN+2 ;Descriptor Link Address RBDBUF = RBDBGN+4 ;Buffer Address RBDEXT = RBDBGN+6 ;Buffer Address Extension RBDLEN = RBDBGN+10 ;Max Buffer Length RBD.EL = BIT15 ;End of Buffer Descriptor List RBD.MX = BIT14-1 ;Max Length Field RBDCCB = RBDBGN+12 ; ; Driver Switches - CNASWT ; SW.BRD = BIT00 ; Broadband connection flag SW.LOO = BIT01 ; controller loopback flag SW.XLO = BIT02 ; external loopback req SW.ON = BIT03 ; circuit on flag SW.HBT = BIT04 ; Heartbeat valid to test if set. SW.PRO = BIT05 ; Promiscuous mode ; PRO.MD = BIT15 ; Promiscuous mode bit in char word. .SBTTL Extended memory definitions. ;+ ; The CNA controller interacts with its own (on board) dual-ported memory ; which is also accessed by the host to send commands to the controller. ; This memory is the mailbox between the two subsystems. The memory is ; enabled on the extended RT-11 region, and can be accessed by the host ; in chunks (or pages ) of 8k words. There are 16 pages available which total ; the 128k bytes of memory in the Dual Ported Memory (DPM). ; Addressing Modes: ; 1- When the host is creating the data structures it needs it will ; modify the PAR1 value as necessary, ; 2- when filling in pointers within this data sturctures it will use ; an offset value relative to the System Control Block SCB, ; 3- when filling in buffers addresses within this data structures it ; will use the physical 24-bit address as required by the controller. ; ; Example: (for the corresponding numbers above) ; 1- Creating the SCB - creating a command block or a receive block, ; or creating the TBD transmit buffer descriptor - or receive ; buffer descriptor RBD. ; 2- The Command blocks and Frame Descriptor are pointed by the SCB ; thru a 16-bit offset relative to the SCB start. The RBD and ; TBDs above are linked thru 16-bit offsets! ; 3- The TBDs and RBDs point to physical buffers with a 24-Bit absolute ; address. ;- ; PAR1 constants BEGREL = 20000 ; Begining virtual address ENDREL = 37776 ; Ending virtual address PGSIZ = 20000 ; Page size = 8k bytes ; Page 1 (control structures => SCP - ISCB - SCB) ; (It also contains the Command Block List and the Receive FRame Area ; data structures which include; Frame Descriptor, Receive Buffer Descriptors ; Transmit Command, Transmit Buffer Descriptors.) ; The SCP which is at the top of memory will point to the ISCB which will ; contain the address of the SCB (the system mailbox). The SCB will reside ; in the lowest part of memory (relative to the base selected) at page 1 ; of the 128k bytes of memory. (This memory has been mapped somewhere in ; the PRO extended memory - carefully chosen so as not to conflict with the ; bitmap memory etc). PAGDEF 1,134000 ; Page 2 (receive buff) (control structures => receive buffers ) ; A total of 2 pages and 10 buffers have been selected! The buffer size has ; been preset to the maxium size ethernet packet 1518. bytes. PAGDEF 2,134200 ;***ACTion*** need to create macros for this guys RCV1L = 020000 + 0 RCV1H = 056 RCV2L = 020000 + MAXMSG ; ADD PACKET SIZE RCV2H = 056 RCV3L = 020000 + ; ADD PACKET SIZE RCV3H = 056 RCV4L = 020000 + ; ADD PACKET SIZE RCV4H = 056 RC9L = 020000 + RC9H = 056 ; values for MOVBLK pag2 RCVPR1 = 134200 RCVBF1 = 20000 RCVPR2 = 134227 RCVBF2 = 20052 RCVPR3 = 134257 RCVBF3 = 20024 RCVPR4 = 134306 RCVBF4 = 20076 RCPR9 = 134336 RCBF9 = 20050 ; Page 3 (receive buff) PAGDEF 3,134400 RCV5L = 040000 + 0 RCV5H = 056 RCV6L = 040000 + MAXMSG ; ADD PACKET SIZE RCV6H = 056 RCV7L = 040000 + ; ADD PACKET SIZE RCV7H = 056 RCV8L = 040000 + ; ADD PACKET SIZE RCV8H = 056 RC10L = 040000 + RC10H = 056 ; values for MOVBLK pag3 RCVPR5 = 134400 RCVBF5 = 20000 RCVPR6 = 134427 RCVBF6 = 20052 RCVPR7 = 134457 RCVBF7 = 20024 RCVPR8 = 134506 RCVBF8 = 20076 RCPR10 = 134536 RCBF10 = 20050 ; Page 4 (transmit buff) PAGDEF 4,134600 ; physical values for control structures XMT1L = 060000 + 0 ; LOW 16-BITS XMT1H = 056 ; HIGH ORDER 6 BITS ; values to use with BLKMV routine XMTPAR = 134600 XMTBUF = 20000 ; Page 5 (not used) PAGDEF 5,135000 ; Page 16 (SCP) : Like described above the "top" of the selected memory ; (128k) contains the pointer to the SCB data structures. PAGDEF 16,137600 ; ; Define Extended memory offset (based on the relocation bias - which ; will be loaded in R1). ; ;+ ; *Note**Note**Note**Note**Note**Note**Note**Note**Note**Note**Note* ; The following equates define offsets of the data structures which will ; reside in PAGE1 of the DECNA region, the base 13 400 000. ;- ; Intermediate System Control Block ; ISCBSY = 0 ; Busy word ISCOFF = ISCBSY + 2 ; Offset to SCB - 16 bit ISCBSE = ISCBSY + 4 ; Base of SCB - physical ; Two words ; ; System Control Block ; SCBSTS = ISCBSY + 10 ; Status word SCBCMD = SCBSTS + 2 ; Command word SCBCBL = SCBSTS + 4 ; Ptr to command block SCBPRA = SCBSTS + 6 ; Ptr to receive area SCBCRC = SCBSTS + 10 ; Crc errors SCBALN = SCBSTS + 12 ; Align errors SCBRSC = SCBSTS + 14 ; Redundancy errors SCBOVR = SCBSTS + 16 ; Overrun errors ; ; Command blocks and descriptors ; FRELST = SCBOVR + 2 ; Free list (512 words) CMDBLK = FRELST + 1024. ; Command area ( 128 words) MULCMD = CMDBLK + 256. ; Multi-cast addresses command MULLEN = MULCMD + 6 ; Multi-cast byte count MULLST = MULLEN + 2 ; Start of addresses .SBTTL General Definitions (Size and identities) ;+ ; Hardwired CNA Driver values ;- BLKNUM = 30. ; Number of dymanic control/descriptor blocks BLKSIZ = 10. ; Size of dynamic block on free list DISINT = 70 ; Disable interrupts for CNA ENBINT = 50 ; Enable interrupts for CNA CLRINT = 110 ; Clear any outstanding interrupt request CNAID = 000042 ; ID to use for DECNA to get vector and csr INTCTL = 173206 ; Interrupt controller 1's CSR DELAY = 250. ; Delay used to timeout Intel 82586 (dead timer) ; ...results in a delay of about 3mS max. MINMSG = 64.-4 ; Minimum Message size is 64 bytes (4 bytes of ; ...CRC are added by the device. MAXMSG = 1518.-4 ; Maximum Message size is 1518 bytes (4 bytes of ; ...CRC are added by the device. PROOVR = 14. ; Ethernet Overhead to/from DECNA (6 by dest + ; ...6 by source + 2 by protocol) MULMAX = 16. ; Maximum number of multicast addresses to enable NIL = -1 ; NIL address for CNA PKNUM = 10. ; Number of receive frame descriptors RBDNUM = 10. ; Number of receive buffer descriptor AMOUNT = 512.*2 ; Size of free list (words) LSTSIZ = AMOUNT/BLKSIZ ; Number of entries in free list CMDSIZ = 128. ; Size of command area (words) .SBTTL Installation code ;+ ; The Installation code which gets entered at bootstrap or with the ; KMON INSTALL command performs the following checks. It uses the device ; slot Id (like every other cti bus controllers) and it will check for ; the existance of the CSR. It will also create a global regions at base ; equal 13,400,000 of 128k bytes. ;- .DRINS NI .ENABL LSB ; Equates DPMSIZ = 4000 ; 128K Memory DPMBAS = 134000 ; Base of dual-ported memory BR 10$ ; Non-system device entry BR 40$ ; Error at install system dev 10$: ; Check if anything there with that id MOV @#SYSPTR,R1 ; R1 -> RMON MOV GETVEC(R1),R0 ; R0 -> $GTVEC TST (R0)+ ; R0 -> $GTCSR MOV #CNAID,-(SP) ; STORE ID CALL @R0 ; GO GET VECTOR MOV (SP)+,R0 ; *C* POP STACK BCS 40$ ; BRANCH IF CANNOT INSTALL ; Create an extended memory handler region, if possible. First ; remove all existing regions by the name we expect to use. MOV P1EXT(R1),R0 ;R0 -> PAR1 Externalization routine 20$: .ADDR #NCNAME,R5 ;R5 -> Region name we need CALL FINDGR(R0) ;Check for existing region BCS 30$ ;None exists, try to create one MOV R1,-(SP) ;Save pointer to RCB BIT #GR.NRF,GR.STA(R1) ;Return the memory to free list? BNE 25$ ;Nope... MOV GR.SIZ(R1),R2 ;R2 = Size of region to deallocate MOV GR.ADR(R1),R1 ;R1 -> Region CALL XDEALC(R0) ;Deallocate the region 25$: CLR @(SP)+ ;Free the RCB (size = 0) BR 20$ ;And loop until region not found 30$: TST R1 ;Is there a free slot? BEQ 40$ ;Nope, so reject installation MOV #DPMSIZ,(R1)+ ;Build RCB (size) MOV #DPMBAS,(R1)+ ; (address) MOV #,(R1)+ ; (status=private, ; non-return to free) .ADDR #NCNAME,R5 ;R5 -> Handler region name MOV (R5)+,(R1)+ ; (name, first word) MOV @R5,@R1 ; (name, second word) TST (PC)+ ;Accept installation (carry = 0) 40$: SEC ;Reject installation (carry = 1) RTS PC .DSABL LSB NCNAME: .WORD NI$HND .RAD50 /$ / .Assume . LE 400,<;INSTALL area overflow> .SBTTL SET option parameter table ;+ ; The .drset macro is used to generate the desired set options. ;- ;1. Find out the source address of the ethernet controller. .DRSET SHOW,CNAID,O.SHOW .SBTTL SET option routines ; SHOW Physical address of ethernet controller ; The physical address is obtained by first selecting the address prom ; (set a bit in CTL) and then performing succesive reads to the i/o page ; option ROM register. The option ROM address register must be written ; first to start the ROM data at the first location. .MCALL .TTYOU,.PRINT,.ADDR .ASSUME CTLMSK = 000040 ; Select Address Prom .ENABL LSB O.SHOW: CALL GETINF ; Get info - CSR - BCS 30$ ; Branch if none .ADDR #MSG,R0 ; R0 -> message .PRINT ; Print message CLRB @RMA ; Start to read from begining MOVB #CTLMSK,@CTL ; Load mask into CTL MOV RMD,R1 ; R1 -> Base of CSR MOV #6.,R2 ; R2 = number of bytes BR 20$ ; Skip next 10$: .TTYOU #'- 20$: MOV (R1),-(SP) ; Get contents of Prom MOVB (SP),R0 ; Get first byte .REPT 4. ASR R0 ; Get high nibble in R0 ... .ENDR ; ... into low nibble BIC #^C<017>,R0 ; Clear any high bits .ADDR #HEX,R0,ADD ; R0 -> into Hex table value MOVB (R0),R0 ; R0 = hex value in ascii .TTYOU ; print it MOVB (SP)+,R0 ; Get same copy for low nibble BIC #^C<017>,R0 ; Clear high nibble .ADDR #HEX,R0,ADD ; R0 -> into Hex table value MOVB @R0,R0 ; R0 = hex value in ascii .TTYOU ; print it DEC R2 ; Are we finish ? BNE 10$ ; No, branch; get another byte .ADDR #CRLF,R0 ; Get address of text .PRINT ; print it! 30$: RTS PC ; Return .DSABL LSB ;+ ; Get information from device id. ; GETVEC = 436 GETINF: MOV R5,-(SP) MOV @#SYSPTR,R5 ; R5 -> RMON BASE MOV R3,-(SP) ; (SP) DEVICE ID MOV GETVEC(R5),R5 ; R5 -> $GTVEC TST (R5)+ ; R5 -> $GTCSR CALL @R5 ; GO GET CSR BCS 40$ ; Branch if error MOV (SP),RMD ; STORE IT ADD #2,(SP) MOV (SP),RMA ; NEXT ADD #2,(SP) MOV (SP),CTL ; NEXT ADD #2,(SP) 40$: MOV (SP)+,MEM ; NEXT, POP STACK TOO MOV (SP)+,R5 ; RESTORE RTS PC .NLIST BEX ; Data RMD: .WORD 0 RMA: .WORD 0 CTL: .WORD 0 MEM: .WORD 0 MSG: .ASCII /Ethernet address = /<200> HEX: .ASCII /0123456789ABCDEF/ CRLF: .BYTE 0 .EVEN .LIST BEX .Assume . LE 1000,<;SET area overflow> .SBTTL I/O Initiation Section .SBTTL Some startup routines .PSECT NIDVR .MCALL .TTYOU,.PRINT .SBTTL INIT - Initialize during first entry to handler. ;+ ; INIT - This routine will perform the following functions: ; o Get CSR and VEC from device ID ; o Get slot number for enabling interrupts later on ; o Reset the DECNA ; o Read the physical ethernet address ; o Select the base address of the 128k bytes of on board ; dual-ported memory ; o Enable the memory and ethernet board ;- .ENABL LSB DPMMSK = 027 ; Mask to select base ... ; ... of DPM (13 400 000) INIT: MOV @#SYSPTR,R5 ; R5 -> RMON BASE MOV #CNAID,-(SP) ; (SP) DEVICE ID MOV GETVEC(R5),R5 ; R5 -> $GTVEC CALL @R5 ; GO GET VECTOR MOV (SP)+,CNAVEC ; *C* STORE IT BCS 2$ ; BRANCH IF ERROR MOV #CNAID,-(SP) ; (SP) DEVICE ID TST (R5)+ ; R5 -> $GTCSR CALL @R5 ; GO GET CSR MOV (SP)+,R0 ; *C* R0 = CSR BCS 2$ ; BRANCH IF ERROR MOV R0,CN$RMD ; STORE IT ADD R0,CN$RMA ; NEXT ADD R0,CN$CTL ; NEXT ADD R0,CN$MEM ; NEXT ; Get slot number from CSR MOV #CNAID,-(SP) ; (SP) DEVICE ID TST (R5)+ ; R5 -> $GTSLT CALL @R5 ; GO GET SLOT # MOV (SP)+,CNASLT ; *C* SAVE SLOT NUMBER BCS 2$ ; BRANCH IF ERROR ; Start initializing 1$: CLR TMPCTL ; Clear flag CLR @CN$CTL ; Software reset ; Read physical station address CLR @CN$RMA ; Start reading from begining BISB #CTLMSK,TMPCTL ; Store mask to set MOVB TMPCTL,@CN$CTL ; Select address PROM MOV CN$RMD,R1 ; R1 -> Address PROM reg .ADDR #NIPHAD,R2 ; R2 -> Store address here .REPT 6 MOVB (R1),(R2)+ ; Store the six bytes .ENDR ; Set base of memory using the mask into I/O page register MOVB #DPMMSK,@CN$MEM ; Load it ; Enable dual ported memory BISB #,TMPCTL ; Select mask to generate MOVB TMPCTL,@CN$CTL ; Set bits TST (PC)+ ; Clear carry and skip 2$: SEC ; Error return RTS PC .DSABL LSB .SBTTL ENABLE - Initialize during first open portal. ;+ ; ENABLE - This routine will be call during the first open portal ; request. Its functions include, creating the SCP - ISCP - ; SCB initialization, configuring the controller, setting ; the ethernet address in the controller and starting the ; receiver free list. It will also enable interrupts for the ; given slot! and It will set the transmitter/receiver to ; not busy status. ;- .ENABL LSB ENABLE: JSR PC,SAVPAR ; Save mapping JSR PC,CNAINI ; Go initialize data structs JSR PC,CNCONF ; Go configure decna ; On return from CNCONF we are mapped thru par1 to base of DPM BCS 32$ ; Branch if error ; Load Ethernet address MOV #CMDBLK,R2 ; R2 = CMD OFFSET ADD R1,R2 ; ADD RELOCATION BIAS CLR (R2)+ ; CLEAR STATUS WORD MOV #CBL.EL+CM.SPA,(R2)+ ; SET PHYSICAL COMMAND AND ; NO MORE ON LIST. CLR (R2)+ ; CLEAR LINK WORD .ADDR #NIPHAD,R0 ; R0 -> ETHER ADDRESS MOV (R0)+,(R2)+ ; MOVE FIRST TWO BYTES MOV (R0)+,(R2)+ ; NEXT TWO MOV (R0)+,(R2)+ ; LAST TWO CALL SETIT ; GO CONFIGURE 32$: BCS E.BAD ; BRANCH IF ERRORS 35$: JSR PC,LSTINI ; INITIALIZE THE FREE LIST GETBLK E.BAD ; GET A BLOCK FROM FREE LIST ; The return value in R0 contains the actual virtual address MOV R0,R5 ; R5 -> ACQUIRED BLOCK MOV R0,BEGFD ; SAVE BEGINNING OF LIST SUB #BEGREL,R0 ; R0 = OFFSET TO BLOCK MOV #PKNUM,R3 ; GET PACKET LOOP COUNT MOV R0,R4 ; SAVE INITIAL OFFSET MOV R0,SCBPRA(R1) ; SETUP LINK TO FIRST FD ; + ; Initialize the frame descriptors FD. ; ; SCB ; _______________ ; | Status | ; | ------------- | ; | Command | ; | ------------- | ; | Cmd List | ________ _______ ; | ------------- | | | | | ; | RCV List |------+ FD 1 |---- o ----- o ---- o ----+ FD n | ; | ------------- | | | | | ; | | -------- ------- ; | | | | ; | | -------- ------- ; | | | | | | ; |_______________| + RBD 1 | --- o ----- o ---- o ----+ RBD n | ; | | | | ; -------- ------- ; | | ; buffer 1 buffer n ; - 40$: CLR (R5)+ ; CLEAR STATUS WORD CLR (R5)+ ; CLEAR COMMAND WORD DEC R3 ; ARE WE FINISH SETTING PKNUM? BLE 50$ ; YES, BRANCH GETBLK E.BAD ; GET ANOTHER BLOCK SUB #BEGREL,R0 ; R0 = OFFSET TO BLOCK MOV R0,(R5)+ ; PUT IT IN LINK FIELD MOV #NIL,(R5)+ ; CLEAR RDB LINK FIELD CLR (R5) ; CLEAR NEXT LOCATION ADD #BEGREL,R0 ; R0 -> VIRTUAL ADDRESS MOV R0,R5 ; SWITCH TO NEW BLOCK BR 40$ ; REPEAT FOR PKNUM TIMES 50$: MOV R4,(R5)+ ; MAKE A CIRCULAR LIST MOV #NIL,(R5)+ ; CLEAR RDB LINK FIELD MOV #PKT.EL,PKTCMD(R0) ; SET EL = 1; END OF LIST MOV R0,ENDFD ; SAVE LAST FD ; Initialize the receive buffer descriptor RBD (see picture above) MOV #RBDNUM,R3 ; NUMBER OF RDB TO ALLOCATE GETBLK E.BAD ; GET A BLOCK MOV R0,R4 ; R4 -> FREE BLOCK BR 70$ ; SKIP NEXT 60$: GETBLK E.BAD ; GET ANOTHER BLOCK 70$: CLR RBDCNT(R0) ; CLEAR EOF & F FLAGS CLR RBDLNK(R0) ; CLEAR NEXT RBD LINK JSR PC,GETPHY ; LOAD PHYSICAL ADDRESSES MOV #MAXMSG,RBDLEN(R0) ; GET MAXIUM PACKET SIZE MOV SCBPRA(R1),R5 ; R5 -> FIRST FD ADD #BEGREL,R5 ; POINT TO ACTUAL LOCATION MOV PKTBUF(R5),RBDLNK(R0) ; GET RBD LINK AND MOVE IT TO MOV R0,PKTBUF(R5) ; THIS RBD, NOW MAKE THIS ONE ; FIRST ON FREE RBD LIST SUB #BEGREL,PKTBUF(R5) ; MAKE THE RIGHT OFFSET SOB R3,60$ ; REPEAT FOR RBDNUM OF STRUCTS MOV R0,BEGRBD ; SAVE CURRENT BEGINNING RBD MOV R4,ENDRBD ; SAVE LAST RBD BIS #RBD.EL,RBDLEN(R4) ; SET EL = 1 ON LAST RBD MOV BEGRBD,RBDLNK(R4) ; LINK IN CIRCULAR LIST SUB #BEGREL,RBDLNK(R4) ; MAKE CORRECT BUFFER SRTCNA #,E.BAD ; START CNA ; Make sure transmit is available MOV #-1,XBUSY ; SET INDICATOR NOT BUSY MOV #-1,RBUSY ; SET INDICATOR NOT BUSY ; Enable interrupts controller for this slot MOV CNASLT,R0 ; GET SLOT NUMBER IN R1 BIS #CLRINT,R0 ; GET PEND INTERRUP FUNC MOV R0,@#INTCTL ; GO DO IT MOV CNASLT,R0 ; GET SLOT NUMBER BIS #ENBINT,R0 ; ENABLE INTERRUPTS MOV R0,@#INTCTL ; GO DO IT CLR SCBCBL(R1) ; CLEAR COMMAND LIST ; Exit code TST (PC)+ ; SKIP NEXT, CLEAR FLAG E.BAD: SEC ; INDICATE ERROR RTS PC .DSABL LSB .SBTTL LSTINI - Initialize list ;+ ; The following routine will initialize an area of PAR1 map to page 1, ; which contains a link list of 5 word data structures which are selected ; for command list or receive frame area commands. The macros putblk and ; getblk are used to put and take data structures from this pool! ;- .ENABL LSB LSTINI: MOV R1,-(SP) ; SAVE REGISTER RELOC MOV #FRELST,R2 ; R2 = OFFSET INTO FRELST ADD R1,R2 ; R2 -> VIRTUALLY AT FRELST MOV R2,LSTHD ; STORE LIST HEAD MOV R2,R3 ; SAVE LIST HEAD MOV #LSTSIZ,R1 ; GET LIST SIZE 10$: ADD #BLKSIZ,R2 ; POINT TO NEXT BLOCK MOV R2,(R3) ; SETUP LINK WORD MOV R2,R3 ; SAVE FOR NEXT LINK SOB R1,10$ ; REPEAT FOR LIST SIZE CLR R3 ; INDICATE END MOV (SP)+,R1 ; RESTORE MAPPING BIAS RTS PC .DSABL LSB .SBTTL GETBLK - Get block from free list ;+ ; A block is obtained from the pool of data structures - like a stack! ; Output: R0 -> virtual address of block obtained ;- .ENABL LSB GTBLK: SAVRG ; SAVE REGISTER MOV LSTHD,R2 ; R2 -> CURRENT LIST HEAD TST @R2 ; ANYTHING THERE ? BEQ 10$ ; NO, BRANCH; EMPTY LIST MOV R2,R0 ; ALLOCATE THIS BLOCK MOV (R2),LSTHD ; STEP TO NEXT BLOCK TST (PC)+ ; SUCCESS; SKIP NEXT 10$: SEC ; FAILURE INDICATION RESRG ; RESTORE REGISTER RTS PC .DSABL LSB .SBTTL PUTBLK - Put block back on frelist ;+ ; A data structure is given back to the pool. ; Input: R0 -> block to put back ;- PUTBLK: MOV LSTHD,(R0) ; MAKE FIRST SECOND MOV R0,LSTHD ; MAKE NEW FIRST RTS PC ; RETURN .SBTTL GETPHY - Get physical address of buffer for RBD ;+ ; The routine ENABLE created a circular ring of receive buffer descriptors ; which have associated with them frame descriptors! Each receive buffer ; descriptor RBD has associatted with it a buffer! This buffer ( a total ; of 10 buffer) reside in extended memory ! Their 24-bit physical address ; must be stored in the RBD for the controller to know where to store the ; incoming packets! This routine is used to get the physical address of the ; buffer depending on the buffer in question. (This buffers have been designed ; in a static way therfore we know their value to start with). ; ; Input: R0 -> start of RBD ; R3 = RBD to fill in ;- .ENABL LSB GETPHY: MOV R3,-(SP) ; SAVE R3 FOR AWHILE NEG R3 ; COMPUTE TABLE ENTRY ADD #10.,R3 ; AS 10 - (R3) ASL R3 ; SHIFT FOR OFFSET TO ENTRY ASL R3 ; (TWO WORD ENTRIES) .ADDR #BUFADR,R3,ADD ; R3 -> TABLE ENTRY MOV (R3)+,RBDBUF(R0) ; LOAD PHYSICAL LOW MOV (R3),RBDEXT(R0) ; AND PHYSICAL HIGH MOV (SP)+,R3 ; RESTORE SAVED R3 RETURN .DSABL LSB .SBTTL DISABL - Cleanup after last close portal. ;+ ; DISABL - This routine will disable the interrupts for the slot in question ; in the CTI bus! It will also disable the CNA board and its dual ; ported memory! DISABL: ; Disable PRO-3xx interrupts MOV CNASLT,R1 ; GET SLOT NUMBER IN R1 BIS #DISINT,R1 ; GET DISABLE FUNCTION MOV R1,@#INTCTL ; DISABLE INTERRUPTS MOV CNASLT,R1 ; GET SLOT NUMBER IN R1 BIS #CLRINT,R1 ; GET PEND INTERRUP FUNC MOV R1,@#INTCTL ; Reset CNA but leave memory active BICB #CR.ED+CR.IE,TMPCTL ; Disable Intel chip BISB #CR.EM+CR.ME+CR.LP,TMPCTL ; Leave memory enable and loop ; disable MOVB TMPCTL,@CN$CTL ; Disable Intel chip RTS PC .SBTTL SETUP - Set hearing characteristics of controller ;+ ; SETUP - This routine is called at init time to set the characteristics of ; the ethernet controller. It is also called whenever there is a change in the ; NI translation table (of rt11 units to ethernet portals). It is used to ; enable the promiscous mode and to enable multicast addresses. The completion ; of the routine (or execution of the command is actually done by the SETIT ; and SETMLT routines. ;- .ENABL LSB SETUP: JSR PC,SAVPAR ; SAVE CURRENT MAPPING MAP #PG1 ; MAP TO CONTROL STRUTURES MOV #BEGREL,R1 ; R1 = RELOCATION BIAS ; Promiscous mode setting MOV #CMDBLK,R2 ; R2 = offset to command block ADD R1,R2 ; Add reloc of page CLR (R2)+ ; Clear status word MOV #CBL.EL+CM.CFG,(R2)+ ; Setup command word CLR (R2)+ ; Clear link word MOV #CFGDFA+6,(R2)+ ; Setup first config word MOV #CFGDFB,(R2)+ ; Setup second config word MOV #CFGDFC,(R2)+ ; Setup third config MOV #CFGDFD,(R2)+ ; Fourth MOV #CFGDFE,(R2) ; Fifth BIC #CFE.TN,(R2) ; Configure baseband TST NIPMFG ; Is promiscous desired? BNE 10$ ; Yes, branch; setit up BIC #CFE.P,(R2) ; Clear promiscous bit BR 20$ ; Go merge with common code 10$: BIS #CFE.P,(R2) ; Set prosmiscous bit 20$: CALL SETIT ; Go configure ; Start of multicast address processing .ADDR #NIUAT,R0 ; R0 -> UNIT ADDRESS TABLE MOV #MULLST,R2 ; R2 = OFFSET TO MULTI-LIST MOV #MULLEN,R3 ; R3 = OFFSET TO MULTI-LENGHT ADD R1,R2 ; ADD RELOC BIAS ADD R1,R3 ; ADD RELOC BIAS CLR (R3) ; INIT THE BYTE LENGHT MOV #8.,R4 ; NUMBER OF ENTRIES IN R4 30$: MOV (R0)+,-(SP) ; IS THIS ENTRY FILLED? BIS (R0)+,(SP) ; CHECK THE 2ND WORD BIS (R0)+,(SP)+ ; AND THE 3RD WORD BEQ 40$ ; NO, BRANCH SUB #UA.ESZ,R0 ; BACKUP THE POINTER .REPT 3 MOV (R0)+,(R2)+ ; STORE THE SIX BYTE ADDRESS .ENDR ADD #6.,(R3) ; UPDATE BYTE COUNT 40$: DEC R4 ; MORE TO DO ? BGT 30$ ; YES, BRANCH CALL SETMLT ; GO SET MULTICAST VALUES RTS PC ; Return .DSABL LSB .SBTTL SETMLT - Set/Reset multicast address ;+ ; SETMLT - The following routine sets/reset the multicast address for the ; ethernet controller. Look at the data structure for the command above. ; Due to a bug - the command must be executed with the DECNA in loopback ; mode. ; Input: R1 = reloc bias ; Mapping to page 1 ; ;- .ENABL LSB SETMLT: MOV #MULCMD,R2 ; R2 = OFFSET TO COMMAND ADD R1,R2 ; ADD RELOC CLR (R2)+ ; CLEAR STATUS WORD MOV #,(R2)+ ; SET COMMAND WORD CLR (R2)+ ; CLEAR LINK BISB #CR.EM+CR.ED+CR.ME+CR.IE,TMPCTL ; Set bits in CTL BICB #CR.LP,TMPCTL ; Enable loopback MOVB TMPCTL,@CN$CTL ; Do it 5$: TST SCBCMD(R1) ; Check for ready ? BNE 5$ 7$: MOV #MULCMD,SCBCBL(R1) ; Setup cmd ptr offset MOV #CLFLGS+CU.SRT,SCBCMD(R1) ; Start the cna command BISB #CR.EM+CR.ED+CR.CA+CR.ME+CR.IE,TMPCTL MOVB TMPCTL,@CN$CTL BICB #CR.CA,TMPCTL MOVB TMPCTL,@CN$CTL MOV #DELAY*4,R0 ; R0 = delay extra long 10$: BIT #,SCBSTS(R1) ; Is command done (int) ? BNE 20$ ; No, branch SOB R0,10$ ; Wait for command completion 15$: 20$: BISB #CR.LP,TMPCTL ; Disable loopback MOVB TMPCTL,@CN$CTL ; Go do it RTS PC ; Return .DSABL LSB .SBTTL CNAINI - Initialize the DECNA controller ;+ ; The initialization of the DECNA starts by setting up some pointer in ; the highest memory addresses of the dual-ported memory. When the CNA ; is first toggle, the controller will read the 5 word located at the ; top of memory, this will be the setup pointer (SCP) to the ISCP, which ; will point to the SCB. ;- .ENABL LSB CNAINI: MAP #PG16 ; Map to top page ; Setup System Configuration Pointer (SCP) MOV #BEGREL,R1 ; R1 = relocation bias CLR SYSBUS(R1) ; Select word mode MOV #PHYL1,ISCP(R1) ; Load lower 16-bit MOVB #PHYH1,ISCP+2(R1) ; Load high byte (22-bit) ; Setup Internal System Configuration Pointer (ISCP) MAP #PG1 ; Map to page one MOV #1,ISCBSY(R1) ; Indicate not busy MOV #PHYL1,ISCBSE(R1) ; Establish scb base ... MOV #PHYH1,ISCBSE+2(R1) ; ... as base of dpm MOV #SCBSTS,ISCOFF(R1) ; Store scb offset ; Clear the System Control Block SCB MOV R1,R2 ; Get copy of relocation ADD #SCBSTS,R2 ; R2 -> scb MOV #8.,R3 ; R3 = wordcount 10$: CLR (R2)+ ; Clear word SOB R3,10$ ; Repeat for wordcount ; Perform System pointer initialization. BISB #CR.LP+CR.EM+CR.ED+CR.CA+CR.ME,TMPCTL ; Toggle 0-1-0 ... MOVB TMPCTL,@CN$CTL ; BICB #CR.CA,TMPCTL ; ... the ca MOVB TMPCTL,@CN$CTL RTS PC .DSABL LSB .SBTTL CNCONF - Configure the DECNA ;+ ; CNCONF - Configure baseband, broadcast enable, buffer must provide ; source-destination address and protocol etc etc ; ; SETIT - Entry for setting physical address. ;- .ENABL LSB CNCONF: MOV #CMDBLK,R2 ; R2 = offset to command block ADD R1,R2 ; Add reloc of page CLR (R2)+ ; Clear status word MOV #CBL.EL+CM.CFG,(R2)+ ; Setup command word CLR (R2)+ ; Clear link word MOV #CFGDFA+6,(R2)+ ; Setup first config word .if ne loop MOV #CFGDFB+CFB.XL,(R2)+ .iff MOV #CFGDFB,(R2)+ ; Setup second config word .endc MOV #CFGDFC,(R2)+ ; Setup third config MOV #CFGDFD,(R2)+ ; Fourth MOV #CFGDFE,(R2) ; Fifth BIC #CFE.TN,(R2) ; Configure baseband SETIT: BISB #CR.EM+CR.ED+CR.ME+CR.IE,TMPCTL ; Set bits in CTL BICB #CR.LP,TMPCTL ; Enable loopback MOVB TMPCTL,@CN$CTL ; Do it 5$: TST SCBCMD(R1) ; Check for ready ? BNE 5$ 7$: MOV #CMDBLK,SCBCBL(R1) ; Setup cmd ptr offset MOV #CLFLGS+CU.SRT,SCBCMD(R1) ; Start the cna command BISB #CR.EM+CR.ED+CR.CA+CR.ME+CR.IE,TMPCTL MOVB TMPCTL,@CN$CTL BICB #CR.CA,TMPCTL MOVB TMPCTL,@CN$CTL MOV #DELAY*4,R0 ; R0 = delay extra long 10$: BIT #,SCBSTS(R1) ; Is command done (int) ? BNE 20$ ; No, branch SOB R0,10$ ; Wait for command completion 20$: BISB #CR.LP,TMPCTL ; Disable loopback MOVB TMPCTL,@CN$CTL ; Go do it RTS PC ; Return .DSABL LSB .SBTTL Xmit/Recv - Transmit and Receive initiation. ;+ ; Transmit/Receive ;- .ENABL LSB XMIT: TST XBUSY ; TRANSMITTER BUSY ? BPL 10$ ; YES, BRANCH; EXIT MOV NIOCQE,R4 ; R4 -> Q-ELEMENT BEQ 10$ ; BRANCH IF NONE INC XBUSY ; MAKE IT BUSY UNTIL INTERRUPT JSR PC,SAVPAR ; SAVE CURRENT MAPPING MAP #PG1 ; MAP TO PAGE 1 MOV #BEGREL,R1 ; R1 = RELOCATION BIAS BEQ 10$ ; BRANCH IF NONE JSR PC,SRCCHK ; CHECK IF SOURCE ADDRESS IN JSR PC,BLKMV ; GO MOVE DATA FROM USER TO XM GETBLK 20$ ; ALLOCATE BLOCK FROM FREE LIS MOV R0,R3 ; R3 -> BLOCK MOV R0,R2 ; SAVE ADDRESS IN R2 CLR (R3)+ ; ZERO COMMAND STATUS MOV #CBL.EL+CBL.I+CM.XMT,(R3)+ ; LOAD COMMAND CLR (R3)+ ; CLEAR LINK TO NEXT CB GETBLK 20$ ; ALLOCATE ANOTHER BLOCK TBD MOV R0,(R3) ; SET OFFSET TO TBD IN CB SUB #BEGREL,(R3) ; GET ACTUAL OFFSET MOV R0,R3 ; R3 -> TBD MOV Q$WCNT(R4),R0 ; R0 = WORDCOUNT DEC R0 ; R0 = ADJUST FOR STATUS WORD DEC R0 ; R0 = ADJUST FOR RESERVED WOR ASL R0 ; R0 = BYTE COUNT MOV R0,(R3) ; STORE ACTUAL COUNT BIS #TBD.EP,(R3)+ ; MAKE THIS THE LAST TBD CLR (R3)+ ; CLEAR LINK TO NEXT TBD MOV #XMT1L,(R3)+ ; GET PHYSICAL LOW MOV #XMT1H,(R3)+ ; GET PHYSICAL HIGH MOV R2,SCBCBL(R1) ; LOAD CB OFFSET IN SCB SUB #BEGREL,SCBCBL(R1) ; SUBTRACT THE RELOC BIAS SRTCNA #CU.SRT,20$ ; START THE SHOW... 10$: TST (PC)+ ; GOOD EXIT 20$: SEC ; SET CARRY RTS PC .DSABL LSB ;+ ; ;- .ENABL LSB RECV: JSR PC,SAVPAR ; SAVE CURRENT MAPPING MAP #PG1 ; MAP TO PAGE 1 MOV #BEGREL,R1 ; GET RELOC BIAS INTO R1 CALL RCVINT ; GO MERGE WITH ISR RTS PC .DSABL LSB .SBTTL BLKMV - Move data between extended and user ;+ ; Input: 40$: MOVB Q$UNIT(R4),R0 ;Update stats ;022 BIC #^C,R0 ;022 ASL R0 ;022 ASL R0 ;022 .ADDR #NIXUN0,R0,ADD ;022 ADD #1,2(R0) ;022 ADC (R0) ;022 CALL NIFIN ;Complete the request ;022 ; R4 -> q-element ; ;- .ENABL LSB BLKMV: SAVRG MOV R4,R3 ; R3 -> Q-ELEMENT ; Set call location MOV @#SYSPTR,R4 ; R4 -> RMON MOV P1EXT(R4),(PC)+ ; STORE OFFSET $MVBLK: .WORD 0 ; STORE ADDRESS HERE SUB #2,$MVBLK ; CALCULATE RIGHT ADDRESS ; Get byte count in wordcount MOV Q$WCNT(R3),R5 ; R5 = WORDCOUNT DEC R5 ; ADJUST FOR STATUS WORD DEC R5 ; ADJUST FOR RESERVED WORD ;;;*CHECKPOINT* ; Get input buffer values MOV Q$PAR(R3),R1 ; R1 = PAR VALUE MOV Q$BUFF(R3),R2 ; R2 -> BUFFER ADDRESS ; TST (R2)+ ; SKIP STATUS WORD add #4,r2 ; Get output buffer values ; Page 4 value MOV #XMTPAR,R3 ; R3 = PAR VALUE MOV #XMTBUF,R4 ; R4 -> TRANSMIT BUF CALL @$MVBLK ; Transfer data RESRG ; Restore registers RTS PC .DSABL LSB .SBTTL SRCCHK - Source address check ;+ ; If the user hasn't loaded the source address in the transmit ethernet packet ; the handler will load the physical address in the user buffer. ;- .ENABL LSB SRCCHK: JSR PC,SAVPAR ; SAVE CURRENT MAPPING SAVRG ; SAVE REGISTER TO USE ; R4 -> Q-ELEMENT MAP Q$PAR(R4) ; MAP TO USER SPACE MOV Q$BUFF(R4),R2 ; R2 -> USER BUFFER add #4,r2 ; Skip status and reserved ; words ADD #EF.SRC,R2 ; R2 -> SOURCE ADDRESS MOV @R2,-(SP) ; IS THERE AN ADDRESS ? BIS 2(R2),(SP) ; ... BIS 4(R2),(SP)+ ; AND LAST WORD BNE 10$ ; YES, BRANCH ; Load physical address if none have been provided .ADDR #NIPHAD,R1 ; R1 -> PHYSICAL ADDRESS MOV (R1)+,(R2)+ ; STORE 1ST WORD MOV (R1)+,(R2)+ ; STORE 2ND WORD MOV (R1)+,(R2)+ ; STORE 3RD WORD 10$: RESRG ; RESTORE REGISTER RTS PC ; RETURN ; RESTORE MAPPING .DSABL LSB .SBTTL Interrupt entry ;+ ; This routine handles the general interrupt from the CNA. The cause ; of this interrupt could be for one of four reasons: ; o A command has been completely processed by the CU ; o A packet has been received by the RU ; o The control unit CU went not ready ; o The receive unit RU went not ready ; Dispatch to the appropiate service routines. On multiple interrupt bits ; set all interrupts are handled before exiting the service routine. ;- .DRAST NI,5,NCABOR .ENABL LSB JSR PC,SAVPAR ; SAVE PAR1 SAVRG ; SAVE REGISTERS MAP #PG1 ; MAP PAR1 TO PAGE 1 MOV #BEGREL,R1 ; R1 = RELOCATION BIAS PAR1 MOV SCBSTS(R1),-(SP) ; SAVE THE CNA STATUS BIC #^C,(SP) ; ISOLATE INTERRUPT BITS SRTCNA (SP),10$ ; CLEAR THE INTERRUPT FLAGS ; ; DISPATCH TO THE INDIVIDUAL SERVICE ROUTINES ; 10$: ASL (SP) ; CHECK COMMAND DONE ? BCC 20$ ; NO, BRANCH ADD #1,NIOPKT+2 ; COUNT INTERRUPT ;022 ADC NIOPKT ;022 JSR PC,CNACXS ; GO PROCESS COMPLETED COMMAND 20$: ASL (SP) ; PACKED RECEIVE INTERRUP ? BCC 30$ ; NO, BRANCH ADD #1,NIIPKT+2 ; COUNT INTERRUPT ;022 ADC NIIPKT ;022 JSR PC,CNAPRS ; GO PROCESS RECEIVED PACKETS 30$: ASL (SP) ; CU NOT READY ? BCC 40$ ; NO, BRANCH JSR PC,CNACNS ; GO PROCESS CU STATE 40$: ASL (SP)+ ; RU NOT READY ? BCC 50$ ; NO, BRANCH JSR PC,CNARNS ; GO PROCESS RU STATE 50$: RESRG ; RESTORE REGISTERS RTS PC .DSABL LSB .SBTTL Abort entry point ;+ ; ;- NCABOR: CALLR NIABRT .SBTTL CNACXS - Command done interrupt service routine ;+ ; ... on entry we are map to page 1 ;- .ENABL LSB CNACXS: TST NOQCHG ; Q- BEING MODIFIED BNE 40$ ; YES, EXIT MOV SCBCBL(R1),R2 ; GET BEG OF LIST ADD #BEGREL,R2 ; ADD BIAS TST (R2) ; ANYTHING THERE! BNE 20$ ; BRANCH IF NOT EMPTY 10$: RTS PC ; RETURN 20$: MOV R2,R0 ; SAVE CB ADDRESS TST (R2)+ ; IS DONE BIT SET ? BPL 10$ ; NO, BRANCH; EXIT MOV (R2)+,R3 ; EXTRACT COMMAND FIELD BIC #^C,R3 ; WITH THIS MASK TST (R2)+ ; ADVANCE COMMAND LINK ; Only one command at a time for now... CMP R3,#CM.XMT ; IS THIS TRANSMIT COMPLETE? BNE 10$ ; NO, BRANCH ; (R2) -> TBD CNAXMT: MOV #-1,XBUSY ; FREE TRANSMITTER MOV NIOCQE,R4 ; R4 -> Q-ELEMENT MOV (R2),R2 ; R2 -> TBD ADD #BEGREL,R2 ; ADD RELOC BIAS MOV (R0),-(SP) ; SAVE COMPLETION STATUS CALL PUTBLK ; DEALLOCATE CB MOV R2,R0 ; GET R0 TOPOINT AT TBD CALL PUTBLK ; DEALLOCATE TBD MOV (SP)+,R2 ; GET STATUS BIT #CBL.OK,R2 ; NO ERROR ? BNE 30$ ; YES, BRANCH BIS #HDERR$,@-2(R4) ; STORE ERROR IN CSW MOV #RC.XMT+SC.WEC,-(SP) ; SET USER BUFFER STATUS JSR PC,@$PTWRD ; GO PUT STATUS 30$: MOV Q$LINK(R4),NIOCQE ; UPDATE INTERNAL QUEUE MOVB Q$UNIT(R4),R0 ; UPDATE STATS ;022 BIC #^C,R0 ;022 ASL R0 ;022 ASL R0 ;022 .ADDR #NIXUN0,R0,ADD ;022 ADD #1,2(R0) ;022 ADC (R0) ;022 CALL NIFIN ; RETURN Q-ELEMENT TO RT ; Check if more work to do JMP XMIT ; GO SEE IF MORE WORK 40$: RTS PC .DSABL LSB .SBTTL CNAPRS - Packet received interrupt service routine ;+ ; ...on entry we are map to page 1. ;- .ENABL LSB CNAPRS: TST NIQCHG ; INPUT Q BEING MODIFIED ? BNE F.END ; YES, BRANCH RCVINT: INC RBUSY ; iS THE ROUTINE BEING USED? BNE F.END ; YES, EXIT NEXT: MOV SCBPRA(R1),R3 ; GET RECEIVE PACKET AREA PTR BEQ F1.END ; BRANCH IF INVALID ADD #BEGREL,R3 ; GET RELOC BIAS MOV R3,BEGFD ; SAVE IT HERE TOO TST (R3)+ ; IS THIS PACKET COMPLETE ? BMI 3$ ; YES, PROCESS ;022 1$: DEC RBUSY ; IF THERE IS ANOTHER FRAME ;022 BPL NEXT ; TO PROCESS THEN LOOP ;022 BR F1.END ; NOPE... ;022 2$: TST NIQUEF ; DONOT THROW AWAY FRAMES ;022 BNE 1$ ; IF FRAME QUEUEING IS ENABLED ;022 BR C.END ; ELSE: DROP PACKET ;022 3$: TST (R3)+ ; SKIP COMMAND FIELD ;022 MOV (R3)+,SCBPRA(R1) ; SAVE ADDRESS OF NEXT FD MOV (R3)+,R2 ; R2 -> RBD ADD #BEGREL,R2 ; ADD RELOCATION BIAS MOV BEGFD,R3 ; R3 -> CURRENT FD MOV R2,R5 ; SAVE RBD ADDRESS CLR R0 ; R4 WILL HOLD BYTE COUNT 10$: MOV (R2),R0 ; ACCUMULATE BYTE COUNT ; *NOTE* For now because the buffer size can accomodate the largest packet ; there will only be one RBD necessary for packet. Therfore the ; following branch should always occur. BMI 20$ ; BRANCH IF END OF PACKET SET ;( This branch only works as long as packets are less that 1514. bytes ) br .-2 20$: MOV NIICQE,R4 ; ANYTHING TO READ ? BEQ 2$ ; NO, BRANCH ;022 TST NIPMFG ; PROMISCOUS ENABLED ? BNE 22$ ; YES, SKIP NEXT CHECKS ; REGISTERS ; ; R0 = BYTE COUNT ; R1 = RELOC ; R2 = PTR TO RBD ; R3 = PTR TO FD ; R4 = Q-ELEMENT (FIRST) ; R5 = PTR RBD JSR PC,GETPRO ; GO GET PROTOCOL VALUE ; Return protocol in R5 JSR PC,GETQEL ; GO GET Q-ELEMENT BR C.END ; BAD ADDRESS/PROTOCOL ;022 BR 2$ ; NO MATCHING QEL ;022 .BR 22$ ; ADDR/PROT/QEL OK ;022 ; R4 -> Q-ELEMENT ; Check for any receive errors and set flag for now 22$: BIC #^C,R0 ; FLUSH OFF END OF LIST MARK ; Move data to user buffer 30$: BIT #PK.OK,(R3) ; PACKET RECEIVED OK? BEQ C.END ; NO, BRANCH JSR PC,MOVBLK ; GO MOVE DATA BCC 40$ ; BRANCH IF NO ERROR ; R4 -> Q-ELEMENT BIS #HDERR$,@-2(R4) ; INDICATE ERROR IN CSW MOV #RC.TRU,-(SP) ; SET ERROR CODE JSR PC,@$PTWRD ; PUT IT 40$: MOVB Q$UNIT(R4),R0 ; UPDATE STATS ;022 BIC #^C,R0 ;022 ASL R0 ;022 ASL R0 ;022 .ADDR #NIRUN0,R0,ADD ;022 ADD #1,2(R0) ;022 ADC (R0) ;022 JSR PC,NIIDEQ ; GO RETURN Q-ELMENT ;022 C.END: JSR PC,MANAGE ; GO UPDATE CIRCULAR LIST JMP NEXT F1.END: MOV #-1,RBUSY ; MAKE ROUTINE AVAILABLE F.END: RTS PC .DSABL LSB .SBTTL CNACNS - Control Unit not ready service routine ;+ ; For now I don't need to start the control unit since most commands ; are handle one at a time and each starts the command unit themselves. ; ; * ACTION * What about multiple units issuing commands ?????? ;- CNACNS: RTS PC .SBTTL CNARNS - Receive Unit not ready service routine ;+ ; The receiver can become idle if - a multicast address command is issued ; and when there are no more resourses. For now I will assume that the ; first situation is the one happening. Later on, if the later happens, I ; will have to do something with the ring of receive buffers! ;- .ENABL LSB CNARNS: SRTCNA #,10$ ; Re-start the ... ; receiver unit. TST (PC)+ 10$: SEC RTS PC .DSABL LSB .SBTTL MANAGE - Update circular rings ;+ ; Input: R1 -> Relocation ; R2 = RBD ; ;- .ENABL LSB MANAGE: SAVRG ; SAVE REGISTER TO USE MOV BEGFD,R0 ; R0 -> CURRENT FD BIS #PKT.EL,PKTCMD(R0) ; MAKE THIS FD THE LAST MOV R0,R3 ; SAVE THE VALUE MOV ENDFD,R0 ; R0 = LAST FD BIC #PKT.EL,PKTCMD(R0) ; MAKE THIS FD AVAILABLE MOV R3,ENDFD ; MAKE CURRENT LAST MOV SCBPRA(R1),BEGFD ; SAVE NEXT VALUE OF FD ADD #BEGREL,BEGFD ; GET ACTUAL VALUE ; ; Now update the RBD ; MOV BEGRBD,R0 ; R0 = CURRENT RBD BIS #RBD.EL,RBDLEN(R0) ; SET CURRENT TO UNAVAILABLE MOV R0,R3 ; SAVE VALUE MOV ENDRBD,R0 ; GET LAST RBD BIC #RBD.EL,RBDLEN(R0) ; MAKE LAST AVAILABLE MOV R3,ENDRBD ; MAKE CURRENT LAST MOV RBDLNK(R2),BEGRBD ; GET NEXT RBD ADD #BEGREL,BEGRBD ; ADD RELOC BIAS RESRG RTS PC .DSABL LSB .SBTTL GETPRO - Get protocol from user buffer ; ; ; GETPRO: SAVRG ; SAVE REGISTERS USED .ADDR #FAKEQ,R4 ; R4 -> FAKE Q-ELEMENT MOV R2,R0 ; R0 -> RBD JSR PC,INVALS ; GET INPUT PAR AND BUF VALUE ; ; On return R2 = buffer address ; R1 = Par1 value ; MOV R1,Q$PAR(R4) ; STORE PAR1 VALUE MOV R2,Q$BUFF(R4) ; STORE BUFFER VALUE ; It also points at the packet destination address .ADDR #NCDST,R3 ; R3 -> STORE DESTINATION HERE MOV #UA.ESZ,R1 ; R1 = LENGHT OF ADDRESS 10$: JSR PC,@$GTBYT ; GO GET ANOTHER BYTE MOVB (SP)+,(R3)+ ; STORE NEXT BYTE SOB R1,10$ ; REPEAT FOR SIX BYTES ; Prepare fake q-element to get protocol ADD #EF.TYP,R2 ; OFFSET INTO PROTOCOL MOV R2,Q$BUFF(R4) ; STORE BUFFER VALUE ; R3 is pointing at the protocol location MOV R3,R0 ; SAVE VALUE JSR PC,@$GTBYT ; GO GET BYTE MOVB (SP)+,(R3)+ ; STORE LOW BYTE JSR PC,@$GTBYT ; GO GET ANOTHER BYTE MOVB (SP)+,(R3)+ ; STORE NEXT BYTE MOV (R0),R5 ; STORE PROTOCOL IN R5 RESRG ; RESTORE REGISTER RTS PC .DSABL LSB .SBTTL INVALS - Input values for Par1 and buf ;+ ; ;- .ENABL LSB INVALS: SAVRG ; SAVE REGISTER TO USE MOV RBDBUF(R0),R3 ; GET PHYSICAL LOW! CMP #RC9L,R3 ; AT PAGE 2 ? BLO CHKG3 ; NO, BRANCH; CHECK PAGE 3 ; Buff 4 BNE 9$ ; NOT EXACTLY BUFF 5 MOV #RCPR9,R1 ; R1 -> PAGE 2 MOV #RCBF9,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 9$: CMP #RCV4L,R3 ; AT PAGE 2 ? BNE 10$ ; NOT EXACTLY BUFF 4 MOV #RCVPR4,R1 ; R1 -> PAGE 2 MOV #RCVBF4,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 10$: ; Buff 3 CMP #RCV3L,R3 ; AT PAGE 2 ? BNE 20$ ; NOT EXACTLY BUFF 3 MOV #RCVPR3,R1 ; R1 -> PAGE 2 MOV #RCVBF3,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 20$: ; Buff 2 CMP #RCV2L,R3 ; AT PAGE 2 ? BNE 30$ ; NOT EXACTLY BUFF 2 MOV #RCVPR2,R1 ; R1 -> PAGE 2 MOV #RCVBF2,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 30$: ; Buff 1 CMP #RCV1L,R3 ; AT PAGE 2 ? BNE CHKG3 ; NOT EXACTLY BUFF 1 MOV #RCVPR1,R1 ; R1 -> PAGE 2 MOV #RCVBF1,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END CHKG3: ; Page 3 ; Buff 10 CMP #RC10L,R3 ; AT PAGE 2 ? BNE 39$ ; NOT EXACTLY BUFF 4 MOV #RCPR10,R1 ; R1 -> PAGE 2 MOV #RCBF10,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END ; BUFF 8 39$: CMP #RCV8L,R3 ; AT PAGE 2 ? BNE 40$ ; NOT EXACTLY BUFF 4 MOV #RCVPR8,R1 ; R1 -> PAGE 2 MOV #RCVBF8,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 40$: ; Buff 7 CMP #RCV7L,R3 ; AT PAGE 2 ? BNE 50$ ; NOT EXACTLY BUFF 3 MOV #RCVPR7,R1 ; R1 -> PAGE 2 MOV #RCVBF7,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 50$: ; Buff 6 CMP #RCV6L,R3 ; AT PAGE 2 ? BNE 60$ ; NOT EXACTLY BUFF 2 MOV #RCVPR6,R1 ; R1 -> PAGE 2 MOV #RCVBF6,R2 ; R2 -> BUFFER LOCATION BR 70$ ; SKIP TO END 60$: ; Buff 5 CMP #RCV5L,R3 ; AT PAGE 2 ? BNE 70$ ; NOT EXACTLY BUFF 1 MOV #RCVPR5,R1 ; R1 -> PAGE 2 MOV #RCVBF5,R2 ; R2 -> BUFFER LOCATION 70$: RESRG RTS PC .DSABL LSB .SBTTL GETQEL - Get q-element matching protocol if any ;+ ; ; input: R5 = protocol ; ; JSR PC,GETQEL ;+036 ... ; Returns here on address/protocol invalid ; ... ; Returns here if no matching QEL found ;-036 ... ; Returns here if address/protocol/QEL OK ; ;- .ENABL LSB GETQEL: SAVRG CLR R3 ; HOLD UNIT VALUE HERE .ADDR #NIUPT,R1 ; R1 -> PROTOCOL TABLE 10$: CMP (R1)+,R5 ; IS PROTOCOL FOUND HERE ? BEQ 20$ ; YES, BRANCH INC R3 ; UPDATE UNIT VALUE CMP #8.,R3 ; DID WE COVER ALL UNITS ? BGT 10$ ; NO, BRANCH; REPEAT BR 50$ ; ERROR - PROTOCOL NOT FOUND ; R3 = Unit offset 20$: CALL MATADR ; Go see if address is valid BCS 50$ ; Branch if any errors ; Find Q-element in the internal queue .ADDR #NIUOT,R1 ; R1 -> UNIT OWNERSHIP TABLE ASL R3 ; MAKE WORD OFFSET ADD R3,R1 ; R1 -> JOB/UNIT COMBO MOVB @R1,R0 ; R0 = CURRENT JOB/UNIT ; Search for q-elements with job/unit in R0 MOV NIICQE,R1 ; R1 -> Q-ELEMENT 30$: CMPB Q$UNIT(R1),R0 ; IS IT THE RIGHT JOB ? BEQ 40$ ; YES, BRANCH MOV Q$LINK(R1),R1 ; GET NEXT ELEMENT BEQ 45$ ; BRANCH IF NO MORE ;022 BR 30$ ; REPEAT IF ELEMENT FOUND 40$: MOV R1,R4 ; RETURN ELEMENT IN R4 ADD #2,12(SP) ; OK ;022 45$: ADD #2,12(SP) ; NO MATCHING QEL ;022 50$: RESRG ; ADDR/PROT ERROR ;022 RTS PC .DSABL LSB .SBTTL MATADR - Match Address ;+ ; ;- .ENABL LSB MATADR: SAVRG ; SAVE REGISTER .ADDR #NIPHAD,R0 ; R0 -> PHYSICAL ADDRESS .ADDR #NCDST,R1 ; R1 -> PACKET DESTINATION MOV R1,R2 ; MAKE A COPY CMP (R0)+,(R1)+ ; FIRST WORD EQUAL ? BNE 10$ ; NO, BRANCH CMP (R0)+,(R1)+ ; NEXT WORD EQUAL ? BNE 10$ ; NO, BRANCH CMP (R0)+,(R1)+ ; ADDRESS MATCH ? BEQ 30$ ; YES, BRANCH 10$: MOV R2,R1 ; R1 -> PACKET DESTINATION .ADDR #NIUAT,R0 ; R0 -> BEGIN OF MULTI ADDRESS MUL #UA.ESZ,R3 ; CALCUALTE OFFSET ADD R3,R0 ; POINT TO MULTI-CAST ADDRESS CMP (R0)+,(R1)+ ; FIRST WORD EQUAL ? BNE 20$ ; NO, BRANCH CMP (R0)+,(R1)+ ; NEXT WORD EQUAL ? BNE 20$ ; NO, BRANCH CMP (R0)+,(R1)+ ; ADDRESS MATCH ? BNE 20$ ; NO, BRANCH 30$: TST (PC)+ 20$: SEC RESRG ; RESTORE REGISTER RTS PC .DSABL LSB .SBTTL MOVBLK - Move data between user and extended memory ;+ ; Input: R0 -> BYTE COUNT ; R1 -> bias ; R2 -> RBD in question ; R3 -> ; R4 -> Q-ELEMENT ; R5 -> ; ;- .ENABL LSB MOVBLK: SAVRG ; Set call location MOV @#SYSPTR,R3 ; R4 -> RMON MOV P1EXT(R3),(PC)+ ; STORE OFFSET $BLKMV: .WORD 0 ; STORE ADDRESS HERE SUB #2,$BLKMV ; CALCULATE RIGHT ADDRESS ; Get byte count in wordcount MOV R0,R5 ; GET BYTE COUNT IN R5 MOV Q$WCNT(R4),R0 ; R0 = ASK WORDCOUNT DEC R0 ; NOT COUNT STATUS DEC R0 ; NOT COUNT LENGHT ASL R0 ; MAKE IT BYTE COUNT CMP R5,R0 ; RECEIVED > ASK FOR ? BLE 10$ ; NO, BRANCH MOV #-1,RCVFLG ; INDICATE TRUNCATION MOV R0,R5 ; MAKE ASK - ACTUAL RECEIVED 10$: MOV Q$BUFF(R4),R0 ; GET BUFFER ADDRESS TST (R0)+ ; SKIP STATUS MOV R0,Q$BUFF(R4) ; SAVE IT IN Q-ELEMENT MOV R5,-(SP) ; LENGHT IN BYTES TO STORE JSR PC,@$PTWRD ; STORE IT ; Q$BUFF(R4) IS INCREMENTED BY 2 MOV R2,R0 ; R0 = RBD IN QUESTION ; Get output buffer values MOV Q$PAR(R4),R3 ; R3 = PAR VALUE MOV Q$BUFF(R4),R4 ; R4 -> BUFFER ADDRESS ASR R5 ; MAKE IT WORDCOUNT ; Get input buffer values JSR PC,INVALS ; Get the values CALL @$BLKMV ; Transfer data RESRG ; Restore registers TST RCVFLG ; ANY ERRORS ? BPL 20$ ; NO, BRANCH CLR RCVFLG ; CLEAR FLAG SEC ; SET CARRY 20$: RTS PC .DSABL LSB .SBTTL Support routines .SBTTL CMD - Start the controller to process commands ;+ ; CMD - Issue command by toggling the CA bit 0-1-0. ; ; 1. CR.LP - Loopback disable ; 2. CR.EM - Non-Reset memory ; 3. CR.ED - Enable the intel chip ; 4. CR.ME - Enable dual ported memory for host ; 5. CR.IE - Interrupt enable ; ; The Ethernet controller informs the host of acceptance by clearing the ; command word. After setting the status bits the controller issues an ; interrupt to the cpu. ; ; input: R1 -> base of control structures ;- .ENABL LSB CMD: BISB #CR.LP+CR.EM+CR.ED+CR.CA+CR.ME+CR.IE,TMPCTL MOVB TMPCTL,@CN$CTL ; .if ne loop BICB #CR.LP,TMPCTL .endc BICB #CR.CA,TMPCTL ; ... the ca MOVB TMPCTL,@CN$CTL 10$: TST SCBCMD(R1) ; Check command word cleared BNE 10$ TST (PC)+ ; Skip next; indicate success 20$: SEC ; Indicate timeout RTS PC ; Return to caller .DSABL LSB .SBTTL Impure data area ;+ ; ;- .PSECT NIDAT ; Table definition .DRVTB NI,0,NIINT,SLOTID=CNAID ; Definitions: CN$RMD: .WORD 0 CN$RMA: .WORD 2 CN$CTL: .WORD 4 CN$MEM: .WORD 6 NINAME: .WORD NI$HND ; Extended memory handler region name .WORD 0 ; ; Operational paramters ; ; User received packet values (**critical ordering**) NCDST: .BLKW 3 ; STORE DESTINATION HERE NCPROT: .BLKW 1 ; STORE PROTOCOL VALUE HERE FREEND: .BLKW 1 ; End of Free Buffer List pointer BEGRBD: .BLKW 1 ; POINTER TO FIRST RDB ENDRBD: .BLKW 1 ; POINTER TO LAST RDB ENDFD: .BLKW 1 ; PONTER TO LAST FD BEGFD: .BLKW 1 ; POINTER TO CURRENT FD CNAVEC: .BLKW 1 ; Hardware vector number CNASLT: .BLKW 1 ; Hardware Slot Number LSTHD: .BLKW 1 ; pointer to top of work space ; ; Fake Q-element to use with the getbyte routine in the monitor ; FAKEQ: .WORD 0 ; SIMULATE Q.BLKN .WORD 0 ; F.BUF: .WORD 0 ; BUFFER ADDRESS .WORD 0 ; .WORD 0 ; F.PAR: .WORD 0 ; PAR1 VALUE ; Receive flag - for errors etc RCVFLG: .WORD 0 ; FLAG FOR NOW... ; Store current value of CTL TMPCTL: .WORD 0 ; Transmit busy flag XBUSY: .WORD -1 ; Receive busy flag RBUSY: .WORD -1 ; Receive buffer physical address (22-bit, low and high order) table BUFADR: .WORD RCV1L, RCV1H .WORD RCV2L, RCV2H .WORD RCV3L, RCV3H .WORD RCV4L, RCV4H .WORD RC9L, RC9H .WORD RCV5L, RCV5H .WORD RCV6L, RCV6H .WORD RCV7L, RCV7H .WORD RCV8L, RCV8H .WORD RC10L, RC10H NISLEN =: <.-NISBLK>/2 ;022 .SBTTL LOAD - DEQNA Port Handler LOAD Code .SBTTL UNLOAD - DEQNA Port Handler UNLOAD code ;+ ; ; LOAD/UNLOAD ; The DEQNA/DELQA has nothing port-specific that is done at ; this time, this is simply a stub. ; ;- .PSECT SETOVR LOAD:: UNLOAD:: CLC ;Ensure success RETURN .Assume <. - LODOVR> LE 1000 MESSAGE= .END