Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_SRC_1_19910112
-
7/ft3/monitor/stanford/phymei.mac
There are 2 other files named phymei.mac in the archive. Click here to see a list.
;<6-1-MONITOR>PHYMEI.MAC.168, 18-Mar-85 01:36:02, Edit by LOUGHEED
;<6-1-MONITOR>PHYMEI.MAC.167, 15-Mar-85 14:12:56, Edit by LOUGHEED
; Move some code into extended code section
; Flush EVENCF conditional, previous edit history
SEARCH PROLOG,SERCOD,PHYPAR
TTITLE (PHYMEI,,< - DEVICE DEPENDENT CODE FOR MEIS INTERFACE>)
SUBTTL L. BOSACK 4-MAR-82 /LB/KSL/DE
;COPYRIGHT (C) 1982, 1983, 1984, 1985
;THE BOARD OF TRUSTEES, LELAND STANFORD JUNIOR UNIVERSITY, STANFORD, CA 94305
;ALL RIGHTS RESERVED.
IFNDEF REL6,<REL6==1> ;DEFAULT ASSEMBLY FOR RELEASE 6.X
IFE REL6,<DEFINE XRESCD <RESCD>>
IFE REL6,<DEFINE XSWAPCD <SWAPCD>>
SUBTTL PARAMETER DEFINITIONS
MXMEUN==2 ;MAXIMUM MEIS INTERFACES PER CONTROLLER
;REGISTERS
;**NOTE**: (*) FLAGS REGISTERS WHOSE CONTENTS CHANGE AS A FUNCTION OF NET SEL.
DR.CR==0 ;CONTROL REGISTER
DR.SR==1 ;(*)STATUS REGISTER
DR.ER==2 ;ERROR REGISTER
DR.MR==3 ;MAINTENANCE REGISTER
DR.AS==4 ;ATTENTION SUMMARY
DR.BC==5 ;BYTE COUNT REGISTER
DR.DT==6 ;DRIVE TYPE REGISTER
DR.DPC==7 ;(*)DATA CONTROLLER PC REGISTER
DR.RA==10 ;(*)RECEIVER BUFFER ADDRESS REGISTER
DR.RBD==11 ;(*)RECEIVER BUFFER DATA REGISTER
DR.RS==12 ;(*)RECEIVED PACKET STATUS REGISTER
DR.MD==13 ;DATA CONVERSION MODE REGISTER (AND NET SELECT)
DR.CSN==14 ;CONTROLLER SERIAL NUMBER REGISTER
DR.DMD==15 ;DIAGNOSTIC MEMORY DATA REGISTER
DR.DMA==16 ;DIAGNOSTIC MEMORY ADDRESS REGISTER
DR.ABA==17 ;(*)ABSOLUTE RECEIVER BUFFER ADDRESS REGISTER
DR.EA==20 ;(*)ETHERNET ADDRESS REGISTER
DR.HC==21 ;TRANSMIT PACKET HEADER COUNT
DR.DSN==23 ;(*)ETHERNET INTERFACE SERIAL NUMBER
N.MEIR==24 ;NUMBER OF REGISTERS
DO.CR==0B5 ;CONTROL REGISTER
DO.SR==1B5 ;(*)STATUS REGISTER
DO.ER==2B5 ;ERROR REGISTER
DO.MR==3B5 ;MAINTENANCE REGISTER
DO.AS==4B5 ;ATTENTION SUMMARY
DO.BC==5B5 ;BYTE COUNT REGISTER
DO.DT==6B5 ;DRIVE TYPE REGISTER
DO.DPC==7B5 ;(*)DATA CONTROLLER PC REGISTER
DO.RA==10B5 ;(*)RECEIVER BUFFER ADDRESS REGISTER
DO.RBD==11B5 ;(*)RECEIVER BUFFER DATA REGISTER
DO.RS==12B5 ;(*)RECEIVED PACKET STATUS REGISTER
DO.MD==13B5 ;DATA CONVERSION MODE REGISTER (AND NET SELECT)
DO.CSN==14B5 ;CONTROLLER SERIAL NUMBER REGISTER
DO.TRD==15B5 ;TRAILING DATA REGISTER (USED TO APPEND PUP CHECKSUMS)
DO.DMA==16B5 ;DIAGNOSTIC MEMORY ADDRESS REGISTER
DO.ABA==17B5 ;(*)ABSOLUTE RECEIVER BUFFER ADDRESS REGISTER
DO.EA==20B5 ;(*)ETHERNET ADDRESS REGISTER
DO.HC==21B5 ;TRANSMIT PACKET HEADER COUNT
DO.MCV==22B5 ;MICROCODE VERSION NUMBER
DO.DSN==23B5 ;(*)ETHERNET INTERFACE SERIAL NUMBER
;FUNCTIONS
DF.NOP==1 ;NO OPERATION
DF.REN==3 ;RECEIVER ENABLE
DF.RDI==5 ;RECEIVER DISABLE
DF.FRP==7 ;FLUSH RECEIVED PACKET
DF.CLR==11 ;CLEAR
DF.FXP==13 ;FLUSH TRANSMIT BUFFER (3MB), UCODE DUMP (10MB)
DF.WRT==61 ;WRITE DATA
DF.RED==71 ;READ DATA
;**NOTE** (*) FLAGS BITS THAT REFLECT THE SELECTED NET INTERFACE ONLY
;BITS IN STATUS REGISTER
DS.ATA==1B20 ;ATTENTION
DS.ERR==1B21 ;COMPOSITE ERROR (LOGICAL OR OF BITS IN ERROR REGISTER)
DS.CD==1B23 ;(*)ETHER CARRIER DETECT
DS.IEX==1B24 ;(*)INTERFACE EXISTS
DS.XAQ==1B25 ;(*)TRANSMIT ACQUIRED ETHER
DS.XA1==1B26 ;TRANSMIT BUFFER AVAILABLE ON INTERFACE 1 (DS.XAV)
DS.XA0==1B27 ;TRANSMIT BUFFER AVAILABLE ON INTERFACE 0
DS.DRY==1B28 ;DRIVE READY (ALWAYS 1)
DS.REN==1B32 ;(*)RECEIVER ENABLED
DS.ROV==1B33 ;(*)RECEIVER OVERRUN (PACKET BUFFER EXHAUSTED)
DS.RP1==1B34 ;RECEIVED PACKET ON INTERFACE 1
DS.RP0==1B35 ;RECEIVED PACKET ON INTERFACE 0 (DS.RPK)
;ERROR REGISTER
ER.IVR==1B20 ;INVALID READ
ER.IVW==1B21 ;INVALID WRITE
ER.AQ1==1B22 ;AQUISITION FAILED ON ETHER 1
ER.AQ0==1B23 ;AQUISITION FAILED ON ETHER 0
ER.ABT==1B24 ;MASSBUS TRANSFER ABORTED
ER.DPE==1B31 ;DATA BUS PARITY ERROR
ER.CPE==1B32 ;CONTROL BUS PARITY ERROR
ER.RMR==1B33 ;REGISTER MODIFICATION REFUSED
ER.ILR==1B34 ;ILLEGAL REGISTER
ER.ILF==1B35 ;ILLEGAL FUNCTION
;MAINTENANCE REG
MR.SEL==1B20 ;BOARD SELECT
MR.INI==1B21 ;INIT
MR.LLP==1B28 ;LOCAL LOOPBACK
MR.PRM==1B30 ;PASS ALL PACKETS
MR.RCV==1B31 ;ENABLE RECEPTION
MR.ATA==1B32 ;MAINT ATA
MR.DPI==1B33 ;DATA PARITY (1 INVERTS TO CAUSE ERRORS)
MR.CPI==1B34 ;CTL PARITY (1 INVERTS TO CAUSE ERRORS)
MR.EN==1B35 ;ENABLE MAINT MODE
;RECEIVED PACKET STATUS
RS.CRC==1B20 ;CRC ERROR (3MB ONLY)
RS.OFL==1B23 ;OVERFLOW (PACKET EXCEEDED BUFFER) (3MB ONLY)
RS.PLM==7777 ;PACKET LENGTH MASK
;DATA CONVERSION MODE AND ETHER SELECT REGISTER
MD.HDR==1B30 ;HEADER MODE SELECT (0= 16-BIT MODE, 1= 32-BIT MODE)
MD.SEL==1B32 ;ETHER SELECT (0= ETHER 0, 1= ETHER 1)
MD.TRL==1B28 ;ENABLE SENDING TRAILER DATA
;0 - LOW 16 BITS IN EACH 18 BIT HALFWORD
;1 - 32 HIGH BITS OF EACH 36 BIT WORD (BYTE HDW FORMAT)
;2 - 36 BITS PACKED
;3 - 7 BIT ASCII
;4 - BYTE SWAP (LIKE 0 BUT WITH THE 8 BIT BYTES SWAPPED)
;5 - 9 BIT ASCII
;ETHERNET ADDRESS REGISTER DEFINITIONS
EA.WEN==1B20 ;WRITE ENABLE
EA.AE3==1B27 ;ADDRESS ENABLE FOR 3MB
EA.AM3==377 ;ADDRESS MASK FOR 3MB
EA.10A==3777 ;ADDRESS MASK FOR 10MB
EA.10D==377 ;DATA MASK FOR 10MB
;KDB EXTENSION DEFINITIONS
;KDBUDB==KDBDDP ;UDB TABLE IS OF VARIABLE LENGTH
MEKADR==KDBDDP+MXMEUN ;MAX 2 INTERFACES ON A MEIS
MEKSER==MEKADR+1 ;MEIS CONTROLLER SERIAL NUMBER
MEKUDB==MEKSER+1 ;ACTIVE UDB (0 IF NONE)
MEKATS==MEKUDB+1 ;ATTN STATUS IF ATTN DURING XFR (FLAG TO MEIINT)ELSE -1
LK.MEI==MEKATS+1 ;LENGTH OF KDB FOR MEIS
;UDB EXTENSION DEFINITIONS
IFE REL6,<MEUBAS==UDBDDD> ;START OF MEIS UDB CELLS
IFN REL6,<MEUBAS==UDBDDM> ;START OF MEIS UDB CELLS
MEUFLG==MEUBAS ;BOOKKEEPING FLAGS
MEUERR==MEUBAS+1 ;SMASHED PACKET COUNT - CRC AND OVERFLOW
MEUMCV==MEUBAS+2 ;MICROCODE VERSION NUMBER
MEUNCT==:MEUBAS+3 ;MULTINET NCT CORRESPONDING TO THIS INTERFACE
MEUHNG==MEUBAS+4 ;NUMBER OF TIMES MEIHNG WAS INVOKED
MEUROV==MEUBAS+5 ;RECEIVER OVERFLOW COUNT
MEUSIZ==MEUBAS+6 ;DRIBBLE PACKET COUNT
MEUFLS==MEUBAS+7 ;FLUSHED PACKET COUNT
MEUXAV==MEUBAS+10 ;TRANSMIT BUFFER AVAILABLE STATUS BIT MASK
MEURPK==MEUBAS+11 ;RECEIVED PACKET AVAILABLE STATUS BIT MASK
MEURIQ==MEUBAS+12 ;-1 IF READ IN QUEUE, 0 OTHERWISE
L.MEI==MEUBAS+13 ;LENGTH OF MEIS UDB
;FLAGS IN LEFT HALF OF MEUFLG. RIGHT HALF CONTAINS MINIMUM PACKET SIZE.
MU%10M==1B0 ;NI IS THE 10MB VARIETY (OFF IMPLIES 3MB FLAVOR)
MU%ENA==1B1 ;NI HAS BEEN ENABLED FOR RECEPTION
MU%LLP==1B2 ;NI IS IN HARDWARE LOOPBACK
MU%PRM==1B3 ;NI IS A PROMISCUOUS RECEIVER
MU%MNT==1B4 ;NI MAINTENANCE MODE STATUS HAS CHANGED
SUBTTL DISPATCH AND INITIALIZATION
MEIDSP::JRST MEIINI ;0 - INITIALIZE
JRST MEISIO ;1 - START IO
JRST MEIINT ;2 - DONE INTERRUPT
JRST RSKP ;3 - ERROR RECOVERY
JRST MEIHNG ;4 - HUNG DEVICE RESET
RET ;5 - CONVERT LINEAR ADDRESS TO POSITION
RET ;6 - BEST LATENCY COMPUTATION, MUST RETURN IORB
RET ;7 - START POSITIONING, USED TO GET LINK SETUP
JRST MEIATN ;10 - ATTENTION INTERRUPT
RET ;11 - SKIP IF POSITION REQUIRED
RET ;12 - STACK SECOND CHANNEL COMMAND, FAIL
JRST RETZ ;13 - CHECK UNIT EXISTS
RET ;14 - CHECK FOR HALTED MICROCODE IN CONTROLLER
RET ;15 - RELEASE PORT
SUBTTL INITIALIZATION
;WE ARE CALLED ONCE PER MEIS FOUND. WE MUST BUILD THE KDB AND AS MANY
;UDBS AS ARE REQUIRED (ONE PER NET INTERFACE)
;P1/ CDB, Q2/ MASSBUS UNIT NUMBER OF MEIS
MEIINI: SAVEQ
MOVE P2,CDBIUN(P1) ;GET KDB ADDRESS
ADD P2,Q2 ;POINT TO CORRECT UNIT
MOVE P2,0(P2) ;GET ENTRY
SKIPE P3,P2 ;KDB ALREADY EXIST?
JRST MEIIOU ;YES - DON'T CREATE A NEW ONE
MOVX T1,LK.MEI ;LENGTH OF KDB
CALL PHYALC ;RESERVE SPACE
RET ;RETURN IF NO SPACE FOUND
MOVEM T1,P2 ;SAVE ADDRESS IN PROPER AC
MOVE P3,T1 ;COPY KDB
MOVEI T1,.BTKDB ;MARK AS KDB
DPB T1,USYBKT ; ...
MOVX T2,DO.CSN ;GET MEIS SERIAL NUMBER
CALL RDREG3 ; ...
MOVEM T1,MEKSER(P2) ;STORE IN KDB
MOVX T1,.UTMEI ;SET UP UNIT TYPE IN KDB
STOR T1,USTYP,(P2) ;...
MOVSI T1,-MXMEUN ;SET UP AOBJN INDEX LH
HRRI T1,KDBUDB(P2) ;MAKE RH POINT TO UDB ENTRIES IN KDB
MOVEM T1,KDBIUN(P2) ;INITIAL POINTER
MOVEM T1,KDBCUN(P2) ;CURRENT POINTER
HRRZM Q2,MEKADR(P2) ;SAVE KDB ADDRESS
XMOVEI T1,MEIDSP ;INSERT DISPATCH VECTOR
MOVEM T1,KDBDSP(P2) ; ...
SETOM MEKATS(P2) ;NO INTERRUPT ACTION NEEDED
MEIIOU: MOVSI Q1,-MXMEUN ;SLAVE INDEX
MEIILP: CALL MEIUIN ;INITIALIZE A SINGLE INTERFACE
NOP ;IGNORE ERROR RETURN, NOTHING TO DO ABOUT IT
AOBJN Q1,MEIILP ;TRY NEXT SLAVE
RET
;HERE TO INITIALIZE A SINGLE INTERFACE
;FIRST DETERMINE IF THIS NET INTERFACE EXISTS. IF SO, BUILD A UDB FOR IT.
MEIUIN: HRRZ T2,Q1 ;GET SLAVE NUMBER
LSH T2,3 ;POSITION
TXO T2,DO.MD ;BUILD DATAO
CALL WTREG3 ;SELECT UNIT
MOVX T2,DO.SR ;READ STATUS REG
CALL RDREG3 ; ...
TXNN T1,DS.IEX ;INTERFACE EXIST?
JRST MEIINX ;NO, DO NOTHING
MOVE T3,[XWD MEIDSP, L.MEI] ;DISPATCH,,LENGTH FOR PHYUDB
CALL PHYUDB ;CREATE UDB AS SPECIFIED
BUG.(HLT,PMENUB,PHYMEI,HARD,<No free stg for MEIS UDB>)
MOVEI T1,.UTMEI ;SETUP UNIT TYPE
TLO T1,(US.PRQ!US.TAP) ;IMAGINE POSITIONING IS REQUIRED AND WE
IORM T1,UDBSTS(P3) ;ARE LIKE A MAGTAPE
HRRZM Q1,UDBSLV(P3) ;SET SLAVE ADDRESS
MOVX T2,DO.DSN ;GET INTERFACE SERIAL NUMBER
CALL RDREG ; ...
MOVEM T1,UDBDSN(P3) ;STORE IN UDB
MOVE T2,[MU%10M+^D60] ;ASSUME 10MB INTERFACE, 60. BYTE MINIMUM
CAIGE T1,10000 ;IS THIS A 10MB NI?
MOVEI T2,4 ;3MB INTERFACE, 4. BYTE MINIMUM PACKET
MOVEM T2,MEUFLG(P3) ;SET UP FLAG WORD
MOVX T2,DO.MCV ;GET MICROCODE VERSION NUMBER
CALL RDREG ; ...
MOVEM T1,MEUMCV(P3) ;STOR IN UDB
HRRZ T1,Q1 ;GET UNIT NUMBER
ADDI T1,KDBUDB(P2) ;ADDRESS TABLE
MOVEM P3,(T1) ;SAVE UDB IN KDB
MOVEM P2,UDBKDB(P3) ;SAVE KDB IN UDB
CALL RAMCLR ;CLEAR ALL ADDRESSES IN ADDRESS RAM
SKIPN T1,ENCUTP ;GET POINTER TO PHYSICAL DEVICE TABLE
MOVE T1,ENIUTP ;FIRST TIME, GET INITIAL POINTER
JUMPGE T1,MEIINX ;HAVE ALL WE ARE ALLOWED?
MOVE T2,P3 ;GET UDB
HRL T2,UDBCDB(P3) ;GET CDB,,UDB IN T2
MOVEM T2,ENCUTB(T1) ;STORE IN TABLE
ADJSP T1,1 ;INCREMENT POINTER AND COUNT
MOVEM T1,ENCUTP ;STORE UPDATED POINTER
DMOVE T1,[ DS.XA0 ;GET TX AND RX AVAILABLE FLAGS FOR NI 0
DS.RP0 ]
SKIPE UDBSLV(P3) ;SKIP IF THIS IS INTERFACE 0
DMOVE T1,[ DS.XA1 ;GET TX AND RX AVAILABLE FLAGS FOR NI 1
DS.RP1 ]
MOVE T3,MEUMCV(P3) ;GET CONTROLLER MICROCODE VERSION
CAIGE T3,1003 ;SKIP IF IT IS THE MOST RECENT REVISION
DMOVE T1,[ DS.XA1
DS.RP0 ] ;ELSE GET THE OLD TX AND RX FLAG BITS
DMOVEM T1,MEUXAV(P3) ;SET THE STATUS FLAG MASK WORDS
MEIINX: RETSKP ;DONE
;RAMCLR - CLEAR ADDRESS RAM FOR 3 OR 10MB INTERFACE
;MUST BE CALLED WITH INTERRUPTS OFF
;TAKES P1,P2,P3 SET UP
;RETURNS +1 ALWAYS
RAMCLR: CALL MEIRDI ;SELECT INTERFACE, DISABLE RECEPTION
MOVE T1,MEUFLG(P3) ;GET OUR FLAGS
TXNN T1,MU%10M ;10MB INTERFACE?
JRST RAM3CL ;NO, GO CLEAR A 3MB INTERFACE
MOVSI T4,-EA.10A ;SET UP AOBJN POINTER
RAM10L: MOVEI T2,(T4) ;SELECT AN ADDRESS
TXO T2,DO.EA ; ...
CALL WTREG ; ...
MOVX T2,DO.EA+EA.WEN ;WRITE A ZERO TO THAT ADDRESS
CALL WTREG ; ...
AOBJN T4,RAM10L ;LOOP OVER ENTIRE ADDRESS RAM
RET ;RETURN TO CALLER
RAM3CL: MOVSI T4,-EA.AM3 ;SET UP LOOP COUNTER
RAM3LP: MOVEI T2,(T4) ;GET ADDRESS WE WANT TO CLEAR
TXO T2,DO.EA+EA.WEN ;WRITE RAM, BUT DO NOT ENABLE RECEPTION
CALL WTREG ;DISABLE RECEPTION AT THAT ADDRESS
AOBJN T4,RAM3LP ;LOOP OVER ENTIRE ADDRESS RAM
RET ;RETURN TO CALLER
;UTILITY ROUTINE TO ENABLE RECEPTION
;*NOTE*:THIS ROUTINE CHANGES THE SELECTED NET - BEWARE IF INTERRUPTABLE
;P1,P2,P3/ CDB,KDB,UDB
MEIENR: CALL MEICON ;SELECT THE INTERFACE
MOVE T2,[EXP DO.CR!DF.REN] ;ENABLE RECEPTION
CALLRET WTREG ; ...
;UTILITY ROUTINE TO DISABLE RECEPTION
;*NOTE*:THIS ROUTINE CHANGES THE SELECTED NET - BEWARE IF INTERRUPTABLE
;P1,P2,P3/ CDB,KDB,UDB
MEIRDI: CALL MEICON ;SELECT THE INTERFACE
MOVE T2,[EXP DO.CR!DF.RDI] ;DISABLE RECEPTION
CALLRET WTREG ; ...
;MEISDN - CALLED FROM HIGHER LEVELS TO CHECK IF MEIS IS ENABLED
;CALLED FROM PROCESS CONTEXT
;T1/ CDB,,UDB
;RETURNS +1 ALWAYS
XSWAPCD
MEISDN::HRRZS T1 ;DON'T NEED CDB
MOVE T1,MEUFLG(T1) ;GET FLAGS FOR THIS NI
TXNN T1,MU%ENA ;ENABLED
RETSKP ;NO, SKIP RETURN
RET ;YES, MEIS IS NOT DOWN
;MEITYP - CALLED FROM HIGHER LEVELS TO CHECK INTERFACE TYPE
;CALLED FROM PROCESS CONTEXT
;T1/ CDB,,UDB
;RETURNS +1 3MB INTERFACE
; +2 10MB INTERFACE
MEITYP::HRRZS T1 ;DON'T NEED CDB
MOVE T1,MEUFLG(T1) ;GET FLAGS FOR THIS NI
TXNE T1,MU%10M ;10MB INTERFACE?
RETSKP ;YES, SKIP RETURN
RET ;NO, MUST BE 3MB INTERFACE
;MEIPRM - FORCE AN INTERFACE INTO PROMISCUOUS MODE
;TAKES T1/ CDB,,UDB
; T2/ 0 FOR NORMAL RECEPTION, -1 FOR PROMISCUOUS
;RETURNS +1 ALWAYS
MEIPRM::HRRZS T1 ;DON'T NEED CDB
MOVE T3,MEUFLG(T1) ;GET FLAGS FOR THIS NI
TXO T3,MU%PRM!MU%MNT ;SET PROMISCUOUS AND MAINT ACTION NEEDED
SKIPN T2 ;ASSUMPTION CORRECT?
TXZ T3,MU%PRM ;NO, CLEAR PROMISCUOUS
MEIPM0: MOVEM T3,MEUFLG(T1) ;RESET FLAG WORD
SETZM MEITIM ;MAKE SCHEDULER SET NEW MAINT MODE STATUS
RET ;RETURN TO CALLER
;MEILLP - FORCE AN INTERFACE INTO HARDWARE LOOPBACK
;TAKES T1/ CDB,,UDB
; T2/ 0 FOR NORMAL RECEPTION, -1 FOR LOOPBACK
;RETURNS +1 ALWAYS
MEILLP::HRRZS T1 ;DON'T NEED CDB
MOVE T3,MEUFLG(T1) ;GET FLAGS FOR THIS NI
TXO T3,MU%LLP!MU%MNT ;SET LOOPBACK AND MAINT ACTION NEEDED
SKIPN T2 ;ASSUMPTION CORRECT?
TXZ T3,MU%LLP ;NO, CLEAR LOOPBACK
JRST MEIPM0 ;GO JOIN COMMON CODE
;SET10M - SET/CLEAR A (NON-WILD) 48-BIT HARDWARE ADDRESS IN A 10MB MEIS
;NI MUST BE SELECTED AND DISABLED. INTERRUPTS MUST ALSO BE OFF.
;TAKES T1/ FSM NUMBER - 1B0 SET IF SETTING THAT ADDRESS, CLEAR IF CLEARING
; T2/ POINTER TO 6 BYTE STRING OF 8-BIT BYTES
; P1,P2,P3/ SET UP AS USUAL
;RETURNS +1 ALWAYS
XRESCD
SET10M: SAVEQ ;PRESERVE QX REGISTERS
DMOVE Q1,T1 ;COPY OUR ARGUMENTS
MOVSI Q3,-6 ;SET UP LOOP COUNT
SET10L: MOVEI T2,(Q3) ;COPY BYTE NUMBER
LSH T2,^D8 ;SHIFT IT TO FORM HIGH BITS OF ADDRESS
ILDB T3,Q2 ;GET BYTE OF ADDRESS DATA
IORI T2,(T3) ;OR INTO ADDRESS MASK (FORM 11 BIT ADDRESS)
TXO T2,DO.EA ;ETHERNET ADDRESS REGISTER
CALL WTREG ;SELECT AN OFFSET INTO THE ADDRESS RAM
MOVX T2,DO.EA ;READ CURRENT CONTENTS OF THAT OFFSET
CALL RDREG ; ...
ANDI T1,EA.10D ;MASK OUT ANY EXTRANEOUS BITS
MOVE T2,BITS(Q1) ;CREATE A BIT PATTERN TO SELECT THE RIGHT FSM
ROT T2,^D8 ;FSM #0 IS MSB OF ADDRESS RAM DATA, ETC.
SKIPGE Q1 ;SKIP IF CLEARING THIS ADDRESS
TDOA T2,T1 ;SET FSM ASSIGNMENT AND SKIP
ANDCA T2,T1 ;CLEAR FSM ASSIGNMENT
TXO T2,DO.EA+EA.WEN ;ETHERNET ADDRESS REGISTER, WRITE ENABLE
CALL WTREG ;SET DATA
AOBJN Q3,SET10L ;LOOP OVER ALL ADDRESS BYTES
RET ;RETURN TO CALLER
;SET3MB - SET/CLEAR AN 8-BIT HARDWARE ADDRESS IN A 3MB MEIS
;NI MUST BE SELECTED AND DISABLED. INTERRUPTS MUST ALSO BE OFF.
;TAKES T1/ 8-BIT ADDRESS - 1B0 SET IF SETTING THAT ADDRESS, CLEAR IF CLEARING
; P1,P2,P3/ SET UP AS USUAL
;RETURNS +1 ALWAYS
SET3MB: MOVE T2,[EXP DO.EA!EA.WEN] ;WRITE ETHER ADDRESS MASK
TXZE T1,1B0 ;ENABLING RECEPTION?
TXO T1,EA.AE3 ;YES, INDICATE SO
IORI T2,(T1) ;AT THIS ADDRESS
CALL WTREG ; ...
RET ;RETURN TO CALLER
;MEIADR - SET MEIS ADDRESS
;CALLED FROM PROCESS CONTEXT
;ALSO DISABLES RECEPTION FOR THE SPECIFIED INTERFACE
;TAKES T1/ CDB,,UDB
; FOR 3MB: T2/ 8-BIT ADDRESS
;
; FOR 10MB: T2/ FSM NUMBER (FSM ZERO RESERVED FOR BROADCAST)
; T3/ FIRST 32 BITS OF ADDRESS, RIGHT JUSTIFIED
; T4/ LAST 16 BITS OF ADDRESS, RIGHT JUSTIFIED
;RETURNS +1 ALWAYS
MEIADR::SAVEP ;PRESERVE ACS
ASUBR <MEIAD1,MEIAD2,MEIAD3,MEIAD4> ;LOCAL STORAGE
HLRZ P1,T1 ;GET CDB
HRRZ P3,T1 ;GET UDB
MOVE P2,UDBKDB(P3) ;GET KDB
NOSKED
IOPIOF ;INTERLOCK AGAINST INTERRUPTS
CALL MEIRDI ;SELECT MEIS, DISABLE RECEPTION
MOVE T1,MEUFLG(P3) ;GET OUR FLAG WORD
TXNE T1,MU%10M ;10MB INTERFACE?
JRST MEIAD0 ;YES, JUMP TO 10MB MASK CODE
MOVE T1,MEIAD2 ;COPY ADDRESS WE WISH TO LISTEN ON
TXO T1,1B0 ;SAY ENABLE RECEPTION
CALL SET3MB ;FIRST SET SPECIFIED ADDRESS
MOVX T1,1B0 ;SETUP FOR BROADCASTS
CALL SET3MB ; ...
MEIADZ: IOPION
OKSKED
MOVX T1,MU%ENA ;INTERFACE ENABLED FLAG
IORM T1,MEUFLG(P3) ;RECORD IN UDB
RET
;SET MASK FOR 10MB INTERFACE
MEIAD0: MOVX T1,1B0+0 ;SET ADDRESS IN FSM 0
MOVE T2,[POINT 8,[EXP -1,-1]] ;THE BROADCAST ADDRESS (ALL ONES)
CALL SET10M ;SET BROADCAST ADDRESS
MOVE T1,MEIAD4 ;GET LAST 16 BITS OF HDW ADDRESS
LSH T1,^D20 ;LEFT JUSTIFY IT
MOVEM T1,MEIAD4 ;AND PUT IT BACK
MOVEI T2,MEIAD3 ;BEGIN SETTING UP THE BYTE POINTER
HRLI T2,(POINT 8,,3) ;SET UP POINTER TO START OF HDW ADDRESS
MOVE T1,MEIAD2 ;GET FSM SPECIFIED BY USER
TXO T1,1B0 ;INDICATE WE ARE SETTING THE ADDRESS
CALL SET10M ;SET OUR PRIMARY ADDRESS
JRST MEIADZ ;JOIN EXIT CODE
;ROUTINE CALLED FROM HIGHER LEVELS TO ENABLE RECEPTION
;CALLED FROM PROCESS CONTEXT
;T1/ CDB,,UDB
MEION:: SAVEP ;PRESERVE ACS
HLRZ P1,T1 ;GET CDB
HRRZ P3,T1 ;GET UDB
MOVE P2,UDBKDB(P3) ;GET KDB
NOSKED ;NO SCHEDULING
IOPIOF ;INTERLOCK AGAINST INTERRUPTS
CALL MEIENR ;ENABLE RECEPTION
MOVX T1,MU%ENA ;GET FLAG TO SAY WE'RE ENABLED
IORM T1,MEUFLG(P3) ;SET IT
CALL MEIMNT ;SET UP ANY MAINTENANCE MODE CHARACTERISTICS
IOPION ;REALLOW PI LEVEL 5 ACTIVITY
OKSKED ;REALLOW SCHEDULING
RET ;RETURN TO CALLER
;ROUTINE CALLED FROM HIGHER LEVELS TO DISABLE RECEPTION
;CALLED FROM PROCESS CONTEXT
;T1/ CDB,,UDB
MEIOFF::SAVEP ;PRESERVE ACS
HLRZ P1,T1 ;GET CDB
HRRZ P3,T1 ;GET UDB
MOVE P2,UDBKDB(P3) ;GET KDB
NOSKED
IOPIOF ;INTERLOCK AGAINST INTERRUPTS
CALL MEIRDI ;DISABLE RECEPTION
IOPION
OKSKED
MOVX T1,MU%ENA ;RECEPTION ENABLED FLAG
ANDCAM T1,MEUFLG(P3) ;CLEAR IT
RET
;MEICON - SELECT THE NET INTERFACE
;ASSUMES P1,P2,P3 SET UP
RESCD
MEICON: MOVX T2,DO.MD ;WANT MODE REGISTER
SKIPE UDBSLV(P3) ;SKIP IF INTERFACE IS IN SLOT 0
TXO T2,MD.SEL ;ELSE SELECT INTERFACE IN SLOT 1
CALL WTREG ;AND WRITE SELECT
RET ;RETURN TO CALLER
SUBTTL START IO
;MEISIO - START I/O ON THE MEIS
;TAKES P1/ CDB POINTER
; P3/ UDB POINTER
; P4/ IORB POINTER
;RETURNS +1 FAILURE
; +2 SUCCESS, CHANNEL STARTED
MEISIO: SAVEQ ;SAVE REGISTERS
MOVE P2,UDBKDB(P3) ;SET UP THE KDB
SKIPLE T1,UDBERR(P3) ;SPECIAL ERROR RECOVERY FUNCTION?
JRST MEISI1 ;YES - USE IT
LDB T1,IRYFCN ;GET FUNCTION FROM IORB
CAIG T1,MXEFCN ;LESS THAN MAX EXTERNAL FUNCTION?
MEISI1: SKIPN Q1,MEIFCN(T1) ;NO, GET HARDWARE FUNCTION WORD
BUG.(HLT,MEIILF,PHYMEI,HARD,<Illegal function at MEISIO>,<<T1,FNC>>)
CALL CHKCON ;CHECK DEVICE OK AND SELECT INTERFACE
RET ;INTERFACE SICK
SETOM MEKATS(P2) ;FLAG NO SPECIAL DONE INTERRUPT ACTION
HRRZM P3,MEKUDB(P2) ;SAVE ACTIVE UDB
LDB T2,IRYFCN ;GET ORIGINAL FUNCTION
CAIE T2,IRFWRT ;IS IT A WRITE?
JRST MEISI2 ;NO, PROCEED WITH READ CODE
TDNE T1,MEUXAV(P3) ;YES - IS THE TRANSMIT BUFFER AVAILABLE?
JRST MEISI3 ;YES, PROCEED WITH WRITE CODE
BUG.(CHK,PMEXNA,PHYMEI,SOFT,<Transmit buffer unavailable at MEISIO>)
MOVX T1,IS.ERR ;GET ERROR BIT
IORM T1,IRBSTS(P4) ;SET IT IN IORB SO IT GETS DEQUEUED
CALL MEIHNG ;RESET INTERFACE
RET ;QUIT NOW
MEISI3: JE IRTRF,(P4),MEISI2 ;SKIP THIS STUFF IF NOT USING TRAILER MODE
LOAD T2,IRCHK,(P4) ;WANT TRAILER. GET CHECKSUM.
TXO T2,DO.TRD ;SEND TO TRAILING DATA REG
CALL WTREG ; ...
MEISI2: LOAD T2,IRPMD,(P4) ;GET DATA MODE
HRRZ T1,UDBSLV(P3) ;GET SLAVE NO
LSH T1,3 ;BUILD MODE WORD
OPSTR <SKIPE>,IRTRF,(P4) ;TRAILER MODE WANTED?
TXO T2,MD.TRL ;YES - TELL HARDWARE.
OPSTR <SKIPE>,IRHDR,(P4) ;32-BIT MODE HEADERS WANTED?
TXO T2,MD.HDR ;YES - TELL HARDWARE
IOR T2,T1 ;...
TXO T2,DO.MD ; ..
CALL WTREG ;SEND TO HW
LOAD T2,IRHLN,(P4) ;GET HEADER LENGTH
TXO T2,DO.HC ;...
CALL WTREG ;SEND TO MEIS
MOVE T1,IRBCNT(P4) ;GET DATA BYTE COUNT
LOAD T2,IRPMD,(P4) ;GET DATA MODE
LDB T3,IRYFCN ;GET FUNCTION (READ OR WRITE)
CAIE T3,IRFRED ;READING?
IFSKP.
LOAD T3,IRHLN,(P4) ;YES, GET HEADER LENGTH
CALL WRDCNV ;MAKE INTO NUMBER OF WORDS
LSH T1,2 ;MAKE INTO NUMBER OF 9-BIT BYTES
MOVE T2,T1 ;COPY INTO T2 FOR LATER
ELSE.
CAIE T2,.PM36 ;36-BIT MODE?
IFSKP.
MOVE T2,T1 ;YES, COPY BYTE SIZE
;THIS CODE MUST BE HERE SO THAT WE GIVE THE UNHACKED BYTE COUNT TO WRDCNV
;WHEN READING IN A PACKET. WE ONLY HACK THE COUNT WHEN WRITING.
IDIVI T2,^D18 ;FIND MODULO 18
CAIN T3,^D14 ;IF IT WAS 14
SUBI T1,2 ;MAKE IT 12 INSTEAD
ENDIF. ;END OF .PM36 CONVERSION
;NOTE THAT WE ARE ASSUMING AN EVEN NUMBER OF 16-BIT HEADER WORDS!
;AT THIS POINT THE DATA COUNT IS IN T1 SO WE TAKE ADVANTAGE OF
;THE ADD TO COPY IT INTO T2 WHERE WE WANT IT...
LOAD T2,IRHLN,(P4) ;GET HEADER LENGTH (IN 16-BIT WORDS)
LSH T2,1 ;CONVERT TO BYTES
ADDI T2,(T1) ;CALCULATE TOTAL NUMBER OF BYTES
ENDIF. ;END OF WRITE BYTE COUNT CALCULATION
HRLI T2,(DO.BC) ;BUILD DATAO
CALLRET CHSTRT ;START CHANNEL, FUNCTION WORD IN Q1
;NON-SKIP IF ERROR, SKIP IF OKAY
;CHKCON - CHECK IF THIS INTERFACE IS USABLE AND SELECT IT
;TAKES P1,P2,P3 SET UP
;RETURNS +1 INTERFACE UNUSABLE, T1/ STATUS
; +2 INTERFACE OKAY, T1/ STATUS
CHKCON: CALL MEICON ;SELECT THE INTERFACE
MOVX T2,DO.SR ;READ STATUS REGISTER
CALL RDREG ; ...
PUSH P,T1 ;SAVE STATUS FLAGS
TXNE T1,DS.ROV ;OVERFLOW?
AOS MEUROV(P3) ;YES, COUNT IT
TXNN T1,DS.ERR!DS.ROV ;ANY ERRORS?
JRST CHKCN1 ;NO, NO PROBLEMS
CALL MEIHNG ;YES, RESET THE MEIS
MOVEM T1,(P) ;SAVE NEW STATUS RETURNED BY MEIHNG
TXNE T1,DS.ERR!DS.ROV ;STILL ERRORS?
JRST CHKNOK ;YES - NOT OK
CHKCN1: MOVX T1,US.OFS ;NO - CLEAR UNSAFE BITS
ANDCAM T1,UDBSTS(P3) ; ...
POP P,T1 ;RESTORE STATUS
RETSKP ;AND RETURN GO
CHKNOK: MOVX T2,US.OFS ;ACT UNSAFE.
IORM T2,UDBSTS(P3) ;STORE IN STATUS WORD
POP P,T1 ;RESTORE STATUS
RET ;RETURN UNAVAILABLE
;WRDCNV - CONVERT BYTE COUNT TO 36-BIT WORD COUNT
;TAKES T1/ DATA BYTE COUNT
; T2/ DATA MODE (BETTER BE LEGAL BECAUSE WE DON'T CHECK)
; T3/ HEADER WORD COUNT
;RETURNS +1 ALWAYS WITH T1/ COUNT OF 36-BIT WORDS
WRDCNV::CALL @[ IFIW!WRDC16 ;.PM16
IFIW!WRDC16 ;.PM32
IFIW!TO36 ;.PM36
IFIW!WRDC7 ;.PMASC
IFIW!WRDC16 ;.PM16S
IFIW!WRDC16 ](T2) ;.PM9
LSH T3,-1 ;CONVERT HEADER WORDS TO 36-BIT WORDS
ADDI T1,(T3) ;COUNT THE HEADER BYTES
RET ;RETURN TO CALLER
WRDC7: IDIVI T1,5 ;FIND NUMBER OF WHOLE WORDS TO USE
SKIPE T2 ;IF THERE ARE ANY BYTES LEFT OVER
ADDI T1,1 ;THEN USE ANOTHER WORD FOR THEM
RET ;THAT'S ALL FOR ASCII MODE
WRDC16: TRZE T1,3 ;REMAINDER MOD 4?
ADDI T1,4 ;YES, ROUND UP
LSH T1,-2 ;DIVIDE DOWN
RET
;FRM36 - GIVEN COUNT OF 36-BIT WORDS, CALCULATE COUNT OF ETHERNET BYTES
;USED ONLY FOR THE 36-BIT DATA MODE
;TAKES T1/ NO. OF 36-BIT WORDS
;RETURNS +1 ALWAYS, T1/ NO. OF 8-BIT ETHERNET BYTES
;CLOBBERS T1-T2
FRM36:: LSHC T1,-1 ;GET NUMBER OF PAIRS OF WORDS, EXTRA BIT IN T2
IMULI T1,^D9 ;9 BYTES PER PAIR OF WORDS
TXNE T2,1B0 ;IF WE ORIGINALLY HAD AN EXTRA WORD
ADDI T1,^D5 ;COUNT IT IN
RET ;RETURN TO CALLER
;TO36 - CONVERT ETHERNET BYTES INTO 36-BIT WORDS FOR READ FROM NET
;TAKES T1/ NO. OF 8-BIT ETHERNET BYTES
;RETURNS +1 ALWAYS, T1/ NO. OF 36-BIT WORDS
;CLOBBERS T1-T2
TO36:: IDIVI T1,^D9 ;9 BYTES FOR EVERY TWO WORDS
LSH T1,1 ;COMPUTE NUMBER OF WHOLE WORD PAIRS
CAIL T2,5 ;ENOUGH LEFT OVER TO MAKE ANOTHER WORD?
ADDI T1,1 ;YES, ADD IT IN
RET
SUBTTL HUNG DEVICE
;MEILUP - LOOP OVER ALL MEIS DEVICES, XCT'ING INSTRUCTION AT CALLER +1
;SETS UP P1,P2,P3
;RETURNS +2 ALWAYS
MEILUP: PIOFF ;DON'T LET NOBODY TOUCH US NOW
MOVE P5,ENIUTP ;SET UP POINTER INTO CHANNEL,,UNIT TABLE
MEILU0: SKIPN ENCUTB(P5) ;SKIP IF WE HAVE A MEIS HERE
JRST MEILU1 ;GO ON TO THE NEXT IF NOT
HLRZ P1,ENCUTB(P5) ;GET CDB
HRRZ P3,ENCUTB(P5) ;GET UDB
MOVE P2,UDBKDB(P3) ;GET KDB
XCT @0(P) ;EXECUTE INSTRUCTION AT CALLER PC +1
MEILU1: AOBJN P5,MEILU0 ;LOOP OVER ALL MEIS DEVICES
PION ;PI'S BACK ON
RETSKP ;RETURN TO CALLER
;MEIFIX - MDDT CALLABLE ROUTINE TO RESET ALL THE MEIS DEVICES
MEIFIX: CALL MEILUP ;LOOP OVER ALL MEIS DEVICES
CALL MEIFX0 ;RESET EACH ONE (INST IS XCT'ED BY MEILUP)
SETZM MEITIM ;SCHEDULER WILL RESTART THE INTERFACES
RET ;RETURN TO CALLER
MEIFX0: CALL MEIHNG ;RESET THE INTERFACE, FIX UP DATA STRUCTURES
MOVE T2,[DO.MR!MR.EN!MR.INI] ;FINISH WITH MASTER RESET OF CONTROLLER
CALL WTREG ;WIPE STATE OF BOTH INTERFACES
RET ;RETURN TO CALLER
;MEIREG - MDDT CALLABLE ROUTINE TO EXAMINE THE FIRST MEIS'S STATUS REGISTER
MEIREG: SKIPN T1,ENCUTB ;IF NO MEIS THERE
RET ;DON'T DO ANYTHING
HRRZ P3,T1 ;GET UDB
HLRZ P1,T1 ;GET CDB
MOVE P2,UDBKDB(P3) ;GET KDB
NOSKED ;NO SCHEDULING
PIOFF ;NO INTERRUPTS OF ANY TYPE
CALL MEICON ;SELECT THE INTERFACE
MOVX T2,DO.SR ;CODE FOR STATUS REGISTER
CALL RDREG ;READ THE REGISTER INTO T1
PION ;TURN ON PI SYSTEM
OKSKED ;REALLOW SCHEDULING
RET ;RETURN TO CALLER
;MEIMNT - PUT MEIS INTO SOME TYPE OF MAINTENANCE MODE
;USES FLAG BITS IN MEUFLG(P3) BELOW TO DETERMINE APPROPRIATE ACTION
MEIMNT: MOVE T1,MEUFLG(P3) ;GET FLAG WORD FOR THIS INTERFACE
SETZ T2, ;NO CONTROL BITS SET YET
TXNE T1,MU%LLP ;SETTING LOCAL LOOPBACK?
TXO T2,MR.EN!MR.RCV!MR.LLP ;YES, SET THE BITS
TXNE T1,MU%PRM ;WANT PROMISCUOUS RECEPTION?
TXO T2,MR.EN!MR.RCV!MR.PRM ;YES, SET THE BITS
TXZN T1,MU%MNT ;SKIP MAINTENANCE MODE STATUS HAS CHANGED
JUMPE T2,R ;QUIT NOW IF NOTHING TO DO
MOVEM T1,MEUFLG(P3) ;UPDATE FLAG WORD
TXO T2,DO.MR ;WANT TO WRITE MAINTENANCE REGISTER
SKIPE UDBSLV(P3) ;SKIP IF NETWORK INTERFACE 0 IS SELECTED
TXO T2,MR.SEL ;SET BOARD SELECT BIT IF WE WANT N.I. 1
CALL WTREG ;WRITE THE MAINTENANCE REGISTER
RET ;RETURN TO CALLER
;MEIHNG - HERE WHEN SOMETHING GOES WRONG.
;WE RETURN NEW STATUS REGISTER CONTENTS IN T1
MEIHNG: AOS MEUHNG(P3) ;COUNT ANOTHER INVOKATION OF MEIHNG
MOVX T2,US.REW ;CLEAR REWIND (THIS IS SOMEWHAT RISKY)
ANDCAM T2,UDBSTS(P3)
SETZM MEURIQ(P3) ;CLEAR READ IN QUEUE FLAG
MOVE T2,MEKUDB(P2) ;GET UDB OF ACTIVE INTERFACE
CAMN T2,P3 ;IS IT US?
SETZM MEKUDB(P2) ;YES, CLEAR ACTIVE UDB
MOVX T2,DO.ER ;READ ERROR REGISTER
CALL RDREG ; ...
JUMPE T1,MEIHN0 ;GO RESET IF NO COMPOSITE ERROR
BUG.(CHK,MEIERR,PHYMEI,HARD,<MEIS hardware error>,<<T1,A>,<P3,B>>)
MOVE T2,[DO.MR!MR.EN!MR.INI] ;MASTER RESET OF CONTROLLER
CALL WTREG ;WIPE STATE OF BOTH INTERFACES
SETZM MEITIM ;SCHEDULER WILL RESTART THE INTERFACES
JRST MEIHN1 ;GO READ STATUS AND RETURN
MEIHN0: MOVX T2,<DO.CR!DF.CLR> ;FUNCTION IS MEIS CLEAR
CALL WTREG ; ...
MOVE T2,[EXP DO.CR!DF.REN] ;RE-ENABLE RECEIVER
CALL WTREG ; ...
CALL MEIMNT ;ENABLE ANY MAINTENANCE MODE FUNCTIONS
MEIHN1: MOVX T2,DO.SR ;READ STATUS REGISTER
CALL RDREG ; ...
RET ;RETURN TO CALLER
SUBTTL MEIS EXISTENCE CHECKS
;MEICHK - CHECK THE MEIS UNITS EVERY MINUTE
;CALLED BY 100 MS CLOCK IN SCHEDULER
MEICHK::SAVEP ;SAVE SOME REGISTERS
MOVE P4,ENIUTP ;INITIAL POINTER TO MEIS CDB,,UDB TABLE
MEICH0: HRRZ P3,ENCUTB(P4) ;GET UDB ADDRESS
JUMPE P3,MEICH3 ;ALL DONE IF WE'VE RUN OUT OF UDB'S
MOVE T1,MEUFLG(P3) ;GET FLAG WORD OF THE UDB
TXNN T1,MU%ENA ;DO WE THINK THIS MEIS IS ENABLED?
JRST MEICH2 ;NO, SKIP OVER IT
HLRZ P1,ENCUTB(P4) ;GET CDB ADDRESS
MOVE P2,UDBKDB(P3) ;GET KDB ADDRESS
IOPIOFF ;LOCK OUT INTERRUPTS
SKIPE MEKUDB(P2) ;ANY ACTIVE INTERFACES ON THIS CONTROLLER?
JRST MEICH1 ;YES, SKIP THE CHECKS
CALL MEICON ;SELECT THE APPROPRIATE INTERFACE
MOVX T2,DO.SR ;READ STATUS REGISTER
CALL RDREG ; ...
MOVE T2,CDBADR(P1) ;GET CHANNEL ADDRESS
MOVE T3,UDBADR(P3) ;GET UNIT ADDRESS
MOVE T4,UDBSLV(P3) ;GET SLOT NUMBER
TXNE T1,DS.IEX ;DOES THE INTERFACE STILL EXIST?
IFSKP.
BUG.(INF,MEIGON,PHYMEI,HARD,<MEIS interface vanished>,<<T2,C>,<T3,U>,<T4,N>>)
MOVX T1,MU%ENA ;GET RECEIVER ENABLED FLAG
ANDCAM T1,MEUFLG(P3) ;AND CLEAR IT
JRST MEICH1 ;GO CHECK NEXT MEIS, IF ANY
ENDIF.
TXNE T1,DS.REN ;IS THE RECEIVER STILL ENABLED?
IFSKP.
BUG.(INF,MEIOFX,PHYMEI,HARD,<MEIS interface restarted>,<<T2,C>,<T3,U>,<T4,N>>)
CALL MEIHNG ;RESET AND REENABLE THE MEIS
ENDIF.
MEICH1: CALL MEIMNT ;CHECK MAINTENANCE MODE STATUS
IOPION ;REALLOW INTERRUPTS
MEICH2: AOBJN P4,MEICH0 ;LOOP OVER ALL MEIS'S
MEICH3: MOVEI T1,^D60000 ;CHECK IN 60 SECONDS
MOVEM T1,MEITIM ;RESET MEIS TIMER
RET ;RETURN TO CALLER
SUBTTL INTERRUPT PROCESSING
;HERE TO HANDLE DEVICE ATTENTIONS
MEIATN: MOVE P3,MEKUDB(P2) ;GET ACTIVE UDB
JUMPE P3,MEIATR ;NONE - SEE WHAT HAPPENED
MOVE T2,UDBSTS(P3) ;GET STATUS OF DRIVE
TXNN T2,US.ACT ;EXPECTING AN INTERRUPT FROM THIS DEVICE?
JRST MEIATR ;NO - SEE WHAT HAPPENED
CALL SETIRB ;YES - GET ACTIVE IORB
CALL MEICON ;SELECT THIS NET INTERFACE
MOVX T2,DO.SR ;READ STATUS REGISTER
CALL RDREG ; ...
SKIPE T2,UDBERR(P3) ;IN ERROR RECOVERY?
JRST ERRATN ;YES, HAVE TO USE A DISPATCH ADDRESS
TXNE T1,DS.ROV ;OVERFLOW?
AOS MEUROV(P3) ;YES, COUNT IT
TXNE T1,DS.ERR!DS.ROV ;NO, ERROR?
JRST MEIATE ;YES
;HERE ON ATTENTION INTERRUPT WITH NO ERRORS
;WE CAN GET HERE IF AN ATTENTION CONDITION COMES UP DURING OR JUST AFTER
;THE END OF A TRANSFER. SET MEKATS NON-NEGATIVE AS A FLAG TO MEIINT. WHEN
;THIS FLAG IS SET MEIINT WILL DO THE SECOND PART OF ATTENTION PROCESSING
;AFTER THE TRANSFER TERMINATION LOGIC
MOVEM T1,MEKATS(P2) ;FLAG SPECIAL ACTION NEEDED
ATNX0: MOVEI P4,0 ;NO SPECIFIC IORB TO RETURN
MEICLA: ;CLEAR ATTENTION, CALLED AS A SUBR
ATNXIT: MOVEI T2,1 ;POSITION OUR BIT
HRRZ T1,MEKADR(P2) ;WITH OUR UNIT ADDRESS
ROT T2,(T1) ; ...
HRLI T2,(DO.AS) ;BUILD DATAO
CALLRET WTREGX ;AND CLEAR OUR ATTENTION BIT
MEIATE: HRRZ T3,UDBAKA(P3) ;ERROR - GET UNIT #
CAMN T3,CDBXFR(P1) ;SAME UNIT AS TRANSFER?
JRST ATNX0 ;YES - ERROR ON XFERING UNIT (IGNORE)
; WILL HANDLE LATER IN XFER INTERRUPT CODE
;HERE IF AN ERROR ON A NON-TRANSFERRING DRIVE
MOVX T1,IS.ERR!IS.NRT ;FLAG ERROR IN IORB
IORM T1,IRBSTS(P4) ; ...
TLO P4,-1 ;SET SEEK ERROR FLAG
CALLRET MEIHNG ;RESET DEVICE AND RETURN TO CHANNEL
;HERE ON ATTENTION INTERRUPT IF DRIVE IS IN ERROR RECOVERY
ERRATN: MOVE T1,UDBERR(P3) ;GET FUNCTION BEING PERFORMED
SKIPL T1,MEIFCN(T1) ;GET DISPATCH ADDRESS
JRST (T1) ;GO PROCESS THE INTERRUPT
JRST ATNX0 ;DATA TRANSFER FUNCTION - DEFER
;HERE ON AN ATTENTION INTERRUPT WHEN THE DEVICE IS NOT ACTIVE
;ALSO CALLED AS A SUBROUTINE FROM MEIINT WHEN AN ATTENTION WAS NOTICED
;AT THE END OF A TRANSFER.
;THIS ROUTINE CHECKS EACH NET INTERFACE FOR RECEIVED PACKETS AND PROCESSES
;ALL THAT CAN BE PROCESSED AT INTERRUPT LEVEL. THE REMAINING (AT MOST ONE PER
;NET INTERFACE)PACKETS HAVE TO BE SENT DOWN THE CHANNEL
;CALLED UNDER CONTROLLED CIRCUMSTANCES
; CALL MEIATR
;RETURNS+1(ALWAYS):
;ALL NI ATTENTION CONDITIONS PROCESSED AND ATTENTION CLEARED
;MODIFIES P3,P4,Q1 (SO SAVE THEM IF YOU CARE!!)
MEIATR: CALL MEICLA ;CLEAR ATTENTION
SKIPE P3,KDBUDB+0(P2) ;GET UDB FOR INTERFACE 0
CALL MEIATU ;EXAMINE IT
SKIPE P3,KDBUDB+1(P2) ;GET UDB FOR INTERFACE 1
CALL MEIATU ;EXAMINE IT
SKIPN P3 ;SKIP IF WE HAVE A UDB POINTER
MOVE P3,KDBUDB+0(P2) ;WAS NO UDB FOR 1, PRESUMABLY WE HAVE ONE FOR 0
MOVX T2,DO.SR ;READ STATUS REGISTER NOW
CALL RDREG ; ...
TXNE T1,DS.ATA ;ATTENTION STILL UP?
JRST MEIATR ;YES, GO SCAN INTERFACES AGAIN
RET ;RETURN TO CALLER
;MEIATU - EXAMINE A SINGLE NETWORK INTERFACE FOR ATTENTION CONDITIONS
;P1,P2,P3 SET UP
;RETURNS +1 ALWAYS
MEIATU: PUSH P,[0] ;SIMULATE STKVAR FOR SPEED
CALL MEICON ;SELECT THE INTERFACE
MEIAT0: MOVX T2,DO.SR ;READ STATUS REGISTER
CALL RDREG ; ...
MOVEM T1,0(P) ;SAVE STATUS BITS
TXNE T1,DS.ROV ;OVERFLOW?
AOS MEUROV(P3) ;YES, COUNT IT
TXNE T1,DS.ERR!DS.ROV ;COMPOSITE ERROR OR RECEIVER OVERFLOW UP?
JRST MEIAT2 ;YES, GO CLEAR IT AND RETURN
TDNN T1,MEURPK(P3) ;ATTN DUE TO PACKET AVAILABLE?
JRST MEIAT4 ;NO, SOMETHING ELSE.
CALL MEIPRP ;PROCESS RECEIVED PACKET
AOSA MEUFLS(P3) ;DONE - FLUSH IT AFTER COUNTING IT
JRST MEIAT1 ;PACKET QUEUED, LOOK AT OTHER CONDITIONS
MOVE T2,[EXP DO.CR!DF.FRP] ;FLUSH PACKET
CALL WTREG ; ...
JRST MEIAT0 ;LOOP FOR MORE PACKETS
MEIAT1: SKIPA T1,0(P) ;LOAD SAVED STATUS AND SKIP
MEIAT2: CALL MEIHNG ;CLEAR ERROR, RETURN NEW STATUS IN T1
MEIAT4: TDNN T1,MEUXAV(P3) ;TRANSMIT BUFFER AVAILABLE?
JRST MEIATX ;NO - GO CLEAN UP AND EXIT
MOVX T2,US.REW ;YES - CLEAR REWIND
TDNN T2,UDBSTS(P3) ;NOW UP?
JRST MEIATX ;NO - DO NOTHING
TLO Q1,-1 ;YES - FLAG CHAN SCHED CYCLE NEEDED
ANDCAM T2,UDBSTS(P3) ;AND CLEAR IN UDB
MEIATX: ADJSP P,-1 ;ADJUST STACK
RET ;RETURN TO CALLER
;MEIPRP - PROCESS A RECEIVED PACKET
;RETURNS NONSKIP IF PACKET IS DONE, ELSE QUEUES IORB AND SKIPS.
;NOTE: ONLY ONE READ CAN BE IN PROGRESS AT ANY TIME - THE PACKET LOOKAHEAD
; ONLY PEEKS AT THE TOP PACKET.
MEIPRP: AOS T1,MEICNT ;COUNT AN INTERRUPT
CAIL T1,^D5000 ;TOO MUCH TIME AT INTERRUPT LEVEL?
JRST MEIPR2 ;YES, NET IS BUSTED. GO RESET WORLD.
SKIPE MEURIQ(P3) ;IS THERE A READ QUEUED UP ON THIS INTERFACE
RETSKP ;YES, HAVE TO PUNT
MOVX T2,DO.RS ;GET LENGTH HW SAW
CALL RDREG ; ...
TXNE T1,RS.CRC!RS.OFL ;ERRORS? (3MB INTERFACE ONLY)
JRST MEIPR0 ;YES, HANDLE SPECIALLY
ANDI T1,RS.PLM ;NO ERRORS - MASK LENGTH
HRRZ T2,MEUFLG(P3) ;GET MINIMUM LEGAL PACKET LENGTH
CAIGE T1,(T2) ;SKIP IF INTERFACE GAVE US A REASONABLE PACKET
JRST MEIPR1 ;HANDLE SMALL PACKETS SPECIALLY
PUSH P,T1 ;SAVE LENGTH ON STACK
MOVE T2,[EXP DO.RA!7] ;ASSUME 10MB INTERFACE
MOVE T3,MEUFLG(P3) ;GET FLAG WORD
TXNN T3,MU%10M ;WAS ASSUMPTION CORRECT?
MOVE T2,[EXP DO.RA!1] ;NO, IT'S A 3MB INTERFACE
CALL WTREG ;SET ADDRESS COUNTER
MOVX T2,DO.RBD ;AND READ THE PACKET TYPE WORD
CALL RDREG ; ...
MOVE T2,T1 ;PASS UP PACKET TYPE IN T2
POP P,T1 ;PACKET LENGTH IS PASSED IN T1
IFE REL6,<CALL ETHRCI> ;HIGHER LEVELS FIGURE OUT WHAT TO DO WITH IT
IFN REL6,<XCALL (XCDSEC,ETHRCI)> ;HIGHER LEVELS FIGURE OUT WHAT TO DO WITH IT
RET ;FLUSH PACKET FROM RAM
CALL ONTWQ ;IORB IN T1, APPEND TO TWQ
TLO Q1,-1 ;INDICATE CHAN SCHED NEEDED
SETOM MEURIQ(P3) ;INDICATE READ IN QUEUE
RETSKP ;SKIP RETURN TO CALLER
;HERE WHEN THE PACKET IS SMASHED OR HAS A BAD CRC (3MB ONLY) OR IF THE
; PACKET IS ABNORMALLY SMALL.
MEIPR0: AOSA MEUERR(P3) ;COUNT A SMASHED OR BAD CRC PACKET
MEIPR1: AOS MEUSIZ(P3) ;COUNT A BAD PACKET SIZE
RET ;FLUSH THE PACKET
;HERE WHEN WE COUNTED TOO MANY INTERRUPTS WITHIN ONE 100 MS. TIME PERIOD.
; THIS USUALLY HAPPENS IF THE NET HARDWARE IS BROKEN. RATHER THAN SPEND ANY
; MORE TIME AT INTERRUPT LEVEL, WE BLAST BOTH INTERFACES WITH A MAINTENANCE
; MODE RESET. WE CLEAR MEITIM WHICH WILL INVOKE MEICHK TO RESTART THE ACTIVE
; INTERFACES.
MEIPR2: CALL MEIHNG ;RESET THE INTERFACE (FIX UP SOFTWARE FLAGS)
MOVE T2,[DO.MR!MR.EN!MR.INI] ;MASTER RESET OF CONTROLLER
CALL WTREG ;WIPE STATE OF BOTH INTERFACES
SETZM MEITIM ;SCHEDULER WILL RESTART THE INTERFACES
BUG.(INF,MEIRST,PHYMEI,SOFT,<MEIS controller reset>,<<P2,P2>>)
RETSKP ;PRETEND WE READ A PACKET
;MEIRTL - READ TRAILING 16-BIT WORD OF THE CURRENT ETHERNET PACKET
;TAKES T1/ LENGTH OF PACKET IN BYTES
; T2/ CDB,,UDB
;RETURNS +1 ALWAYS, T1/ 16-BITS OF DATA
XRESCD
MEIRTL::SAVEP ;PRESERVE THE P REGISTERS
HLRZ P1,T2 ;CDB ADDRESS
HRRZ P3,T2 ;UDB ADDRESS
MOVE P2,UDBKDB(P3) ;KDB ADDRESS
ADDI T1,1 ;ROUND UP USER'S COUNT
LSH T1,-1 ;CONVERT TO 16-BIT WORDS
MOVX T2,DO.RA ;WRITE ADDRESS REGISTER
IORI T2,-1(T1) ;CALCULATE RELATIVE OFFSET OF LAST WORD
CALL WTREG ;SET RAM POINTER AT DESIRED WORD
MOVX T2,DO.RBD ;READ A WORD FROM THE RECEIVER BUFFER
CALL RDREG ; ...
RET ;RETURN, T1/ DESIRED WORD
RESCD
;MEIRHD - READ LEADING BYTES FROM PACKET INTO A USER BUFFER
;ASSUMES HIGHER LEVELS ARE USING 32-BIT HEADER MODE
;TAKES T1/ GLOBAL (EXTENDED) ADDRESS OF BUFFER
; T2/ CDB,,UDB
; T4/ BYTES TO READ INTO BUFFER
;USES P4 AND P5 AS A DOUBLE-WORD GLOBAL BYTE POINTER
;RETURNS +1 ALWAYS
XRESCD
MEIRHD::SAVEP ;WE WIPE MOST OF THE P REGISTERS
HLRZ P1,T2 ;CDB ADDRESS
HRRZ P3,T2 ;UDB ADDRESS
MOVE P2,UDBKDB(P3) ;KDB ADDRESS
SKIPG T4 ;RANGE CHECK
BUG.(HLT,MEIHDR,PHYMEI,SOFT,<Bad arg to MEIRHD>,<<T4,DATA>>)
ADDI T4,1 ;ROUND USER BYTE COUNT UP
LSH T4,-1 ;CONVERT TO 16-BIT WORDS
MOVSI P4,442040 ;"POINT 16," WITH GLOBAL BIT SET
MOVE P5,T1 ;SET UP ADDRESS PORTION OF BYTE POINTER
MOVX T2,DO.RA ;SET ADDRESS COUNTER TO WORD ZERO
CALL WTREG ; ...
MEIRH0: MOVX T2,DO.RBD ;AND READ
CALL RDREG ; ...
IDPB T1,P4 ;STORE
SOJG T4,MEIRH0 ;DONE?
RET ;RETURN TO CALLER
RESCD
;HERE ON DATA TRANSFER DONE INTERRUPTS
MEIINT: SKIPN P3,MEKUDB(P2) ;HAVE A CURENT UDB?
JRST MEIBDD ;BAD DONE INT
SETZM MEKUDB(P2) ;CLEAR ACTIVE UDB
CALL SETIRB ;SET POINTER TO CURRENT IORB IN P4
CALL CHKRH ;CHECK CHANNEL FOR ERRORS
JRST MEIIER ;ERRORS, GO RESET THE WORLD
CALL CHKMEI ;SELECT MEIS AND CHECK FOR ERRORS(STATUS IN T1)
JRST MEIIER ;ERRORS, GO RESET WORLD
LDB T2,IRYFCN ;GET FUNCTION
CAIE T2,IRFRED ;READ?
IFSKP.
SETZM MEURIQ(P3) ;CLEAR READ IN QUEUE FLAG
AOS UDBRED(P3) ;UPDATE READ COUNT
AOS UDBRCT(P3) ; ...
ELSE.
AOS UDBWRT(P3) ;UPDATE WRITE COUNT
AOS UDBWCT(P3) ; ...
ENDIF.
TXNE T1,DS.RP0!DS.RP1 ;PACKETS TO PROCESS IN EITHER NI (STATUS IN T1)
JRST MEIIN2 ;YES - ACT AS IF ATTN HAPPENED
SKIPGE MEKATS(P2) ;WAS THERE AN ATTENTION EARLIER IN THE DONE?
JRST MEIIN3 ;NO - CHECK TRANSMIT BUFFER AVAILABLE
MEIIN2: PUSH P,P3 ;YES - SAVE UDB
PUSH P,P4 ;SAVE IORB
PUSH P,Q1 ;SAVE Q1
CALL MEIATR ;CALL 2ND PART OF ATTENTION INTERRUPT
POP P,Q1 ;RESTORE Q1
POP P,P4 ;RESTORE P4
POP P,P3 ;RESTORE P3
SETOM MEKATS(P2) ;NOTHING MORE TO DO
CALL MEICON ;MUST RE-SELECT THIS NI
MOVX T2,DO.SR ;READ STATUS AGAIN
CALL RDREG ; ...
MEIIN3: TDNE T1,MEUXAV(P3) ;TRANSMIT BUFFER AVAILABLE?(STATUS STILL IN T1)
JRST MEIIN5 ;YES - NOTHING MORE TO DO
;THE TRANSMIT BUFFER IS NOT AVAILABLE. TO PREVENT PHYSIO FROM TRYING TO
;TO SCHEDULE A WRITE AT THE END OF THIS DONE INTERRUPT, WE MUST SET US.REW
;IF THE NEXT IORB IN THE TWQ IS INDEED A WRITE OR IF THERE IS NO IORB.
MOVX T1,US.REW ;NO - GET FLAG
HRRZ T3,IRBLNK(P4) ;LOOK AT SUCCESSOR IORB
JUMPE T3,MEIIN4 ;NONE
EXCH T3,P4 ;NEED TO LOOK AT FUNCTION
LDB T2,IRYFCN ;GET FUNCTION
EXCH T3,P4 ;RESTORE
CAIE T2,IRFRED ;A READ?
MEIIN4: IORM T1,UDBSTS(P3) ;NO, A WRITE - MUST ACT BUSY
MEIIN5: RETSKP ;ALL DONE
;CHKRH - CHECK RHXX CHANNEL FOR ERRORS
;TAKES P1/ ADDRESS OF CDB
;RETURNS +1 ERROR
; +2 NO ERRORS
;CLOBBERS T1,T2
CHKRH: CALL CKERR ;CALL CHANNEL INDEPENDENT CHECKING ROUTINE
TRNA ;SOME ERRORS, GO REPORT THEM
RETSKP ;ALL GOOD, SKIP RETURN
MOVE T1,CDBCNI(P1) ;GET CONI AT INTERRUPT
HRRZ T2,CDBICP(P1) ;GET POINTER TO CHANNEL LOGOUT AREA
MOVE T2,1(T2) ;GET STATUS BITS FROM LOGOUT AREA
BUG.(CHK,MEIRHX,PHYMEI,HARD,<RH20/MEIS error>,<<T1,CNI>,<T2,LGT>>)
RET ;TAKE FAILURE RETURN
;CHKMEI - SELECT AND CHECK MEIS DEVICE FOR ERRORS
;RETURNS(+1):
; ERROR CONDITION, CLOBBERS T1-T3
;RETURNS(+2):
; MEIS NI IS GOOD, STATUS IN T1, T2-T3 CLOBBERED
CHKMEI: MOVE T1,UDBSLV(P3) ;GET INTERFACE NUMBER
LSH T1,3 ;SET APPROPRIATE INTERFACE BIT
MOVX T2,DO.MD ;WE WRITE THE MODE REGISTER
IOR T2,T1 ;SET NI NUMBER
CALL WTREG ;SELECT THE NI
MOVX T2,DO.SR ;READ STATUS REGISTER
CALL RDREG ; ...
TXNE T1,DS.ROV ;OVERFLOW?
AOS MEUROV(P3) ;YES, COUNT IT
TXNN T1,DS.ERR!DS.ROV ;ERROR OR RECEIVER OVERFLOW?
RETSKP ;NO, TAKE GOOD RETURN
PUSH P,T1 ;SAVE STATUS BITS
MOVX T2,DO.ER ;ERROR REGISTER
CALL RDREG ;READ IT
POP P,T2 ;RESTORE STATUS REGISTER BITS
BUG.(CHK,MEIDVX,PHYMEI,HARD,<MEIS termination error>,<<T2,S>,<T1,E>>)
RET ;TAKE FAILURE RETURN
;RECOVER FROM AN ERROR DETECTED AT TRANSFER TERMINATION
;COMMON HANDLING FOR CHKRH AND CHKMEI ERROR RETURNS
MEIIER: CALL CLRCHL ;RESET CHANNEL
CALL MEIHNG ;RESET INTERFACE
MOVX T1,IS.ERR!IS.DTE!IS.NRT ;CALL IT A DATA ERROR, DON'T RETRY
IORM T1,IRBSTS(P4) ;SET ERROR FLAGS IN IORB STATUS WORD
RET ;AND HOPE FOR ERROR RECOVERY
;HERE WHEN A DONE INTERRUPT WITH NO UDB ACTIVE
MEIBDD: BUG.(CHK,PMEBDD,PHYMEI,HARD,<MEIS done interrupt with no active UDB>)
RET
;FUNCTION TABLE
MEIFCN: 0 ;0 - ILLEGAL
DF.RED ;1 - READ
0 ;2 - ILLEGAL (READ FORMAT)
DF.WRT ;3 - WRITE
MXEFCN==.-MEIFCN-1 ;MAXIMUM EXTERNAL FUNCTION
MXFCN==.-MEIFCN-1 ;MAXIMUM FUNCTION
TNXEND
END