.TITLE XQDRV .IDENT /01/ ; ; VERSION 01 ; ; PAUL ELKINS ; ; 9-FEB-84 15:00 ; ; LOS ALAMOS NATIONAL LAB. ; PO BOX 1663 MS-J957 ; LOS ALAMOS NM 87545 ; 505 667 3502 ; ; ; ;COPYRIGHT, 1984,THE REGENTS OF THE UNIVERSITY OF CALIFORNIA. ;THIS SOFTWARE WAS PRODUCED UNDER A U.S. GOVERNMENT CONTRACT ;(W-7405-ENG-36) BY THE LOS ALAMOS NATIONAL LABORATORY,WHICH ;IS OPERATED BY THE UNIVERSITY OF CALIFORNIA FOR THE U.S. ;DEPARTMENT OF ENERGY. THE U.S. GOVERNMENT IS LICENSED TO USE, ;REPRODUCE, AND DISTRIBUTE THIS SOFTWARE. PERMISSION IS GRANTED ;TO THE PUBLIC TO COPY AND USE THIS SOFTWARE WITHOUT CHARGE, ;PROVIDED THAT THIS NOTICE AND ANY STATEMENT OF AUTHORSHIP ARE ;REPRODUCED ON ALL COPIES. NEITHER THE GOVERNMENT NOR THE ;UNIVERSITY MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ;ANY LIABILITY OR RESPONSIBILITY FOR THE USE OF THIS SOFTWARE. ; ; XQ: DRIVER FOR DEQNA ; ; LEGAL FUNCTIONS ARE ; ; IO.KIL(12) CANCEL I/O ; IO.RLB(1000) READ LOGICAL BLOCK ; IO.WLB(400) WRITE LOGICAL BLOCK ; IO.GLI(16420) GET LINK ERROR COUNTERS ; IO.GLC(16430) GET AND CLEAR LINK ERROR COUNTERS ; ; ; ; .MCALL HWDDF$,PKTDF$,DEVDF$,XQPRCL,XQSTAT ; HWDDF$ ;DEFINE HARDWARE REGISTERS PKTDF$ ;DEFINE I/O PACKET DEFINITIONS DEVDF$ ;DEFINE DEVICE TABLE OFFSETS XQPRCL ;DEFINE XQ: PROTOCOL OFFSETS XQSTAT ;DEFINE XQ: STATISTICS PARAMETERS ; ; LOCAL DATA STRUCTURES ; STN=174440 ;QNA BASE ADDRESS RBDL=STN+4 ;RECEIVE BDL BUFFER TBDL=STN+10 ;XMIT BDL BUFFER XQVEC=STN+14 ;QNA VECTOR BUFFER XQCSR==STN+16 ;QNA CSR REGISTER VECTOR==310 ;QNA VECTOR ADDRESS BDLSIZ=6 ;SIZE OF BDL IN WORDS BUFSIZ=40 ;RECEIVE DATA BUFFER SIZE IN WORDS NBUF=116 ;NUMBER OF RECEIVE DATA BUFFERS SWC=100 ;SETUP WORD COUNT IBDL=100000 ;INITIAL VALUE FOR BDL FLAG,STATUS-1/2 CHAIN=40000 ;CHAIN BLOCK DESCRIPTOR BIT X$$Q11=1 ;NUMBER OF UNITS MAXPKT=576. ;MAXIMUM NUMBER OF BYTES/PACKET MINPKT=64. ;MINIMUM PACKET SIZE IN BYTES BUSY=1 ;INITIATE ENTRY BUSY STATUS BIT IREQ=2 ;INTERRUPT REQUEST OUTSTANDING RDONLY=4 ;READ ONLY I/O PACKET SEARCH SAFTY=RBUFDL/2 ;SAFETY ZONE IN BYTES XFLG=0 ;BDL FLAG OFFSET IN BYTES XDSC=2 ;BDL DESCRIPTOR OFFSET IN BYTES XADR=4 ;BDL ADDRESS-LO OFFSET IN BYTES XCNT=6 ;BDL WORD COUNT OFFSET IN BYTES XST1=10 ;BDL STATUS-1 OFFSET IN BYTES XST2=12 ;BDL STATUS-2 OFFSET IN BYTES PQBDL=2 ;PACKET QUEUE BDL POINTER OFFSET PQTSK=4 ;PACKET QUEUE DESTINATION TASK OFFSET DEBUG=0 ;INCLUDE DE-BUG CODE IF DEFINED ;LOCAL MACRO'S ; .MACRO CQUE NBUF .REPT NBUF .WORD .+10 ;LINK TO NEXT BLOCK .BLKW 1 ;BDL VIRTUAL ADDRESS .BLKW 1 ;TASK NAME HIGH WORD .BLKW 1 ;TASK NAME LOW WORD .ENDR .BLKW 4 ;LAST BLOCK(NO LINK) .ENDM .PAGE .SBTTL PACKET FORMAT ; ; PACKET FORMAT FIELD SIZE FIELD OFFSET ; ; _______________ ; ! ! ; ! DESTINATION ! 6 XQDST ; !_______________! ; ! ! ; ! SOURCE ! 6 XQSRC ; !_______________! ; ! ! ; ! TYPE ! 2 XQTYP ; !_______________! ; ! ! ; ! WORD COUNT ! 2 XQWC ; !_______________! ; ! ! ; ! DESTINATION ! 4 XQDTSK ; ! TASK NAME ! ; !_______________! ; ! ! ; ! SOURCE ! 4 XQSTSK ; ! TASK NAME ! ; !_______________! ; ! ! ; ! SUB-TYPE ! 2 XQSTYP ; !_______________! ; ! ! ; ! USER SEQUENCE ! 2 XQSEQ ; !_______________! ; ! ! ; ! DATA ! 32- XQDAT ; !_______________! ; .PAGE .SBTTL DRIVER DISPATCH TABLE ; LD$XQ=0 ;DEFINE NECESSARY SYMBOL FOR LOADABLE DRIVER ; ; DRIVER DISPATCH TABLE ; BASE: ;DRIVER STARTING ADDRESS ; $XQTBL::.WORD XQINI ;DEVICE INITIALIZATION .WORD XQCAN ;DEVICE I/O CANCELLATION .WORD XQTMO ;DEVICE TIMEOUT XQTRY .WORD XQPWR ;POWER FAIL RECOVERY ROUTINE .PAGE .SBTTL DRIVER INITIATION CODE ; THIS SECTION IS CALLED WHEN A PACKET IS QUEUED TO THIS ; DEVICE, AND THE DRIVER RETURN'S HERE WHEN A REQUEST ; IS FINISHED, IN ORDER TO SERVICE ANY PENDING REQUESTS ; XQINI: 1$: MOV #CKPKT,R2 ;I/O PACKET CHECK ROUTINE CALL $GSPKT ;GET AN I/O PACKET BCS 3$ ;NONE AVAILABLE JSR PC,10$ ;GOT ONE PROCESS IT BR 1$ ;LOOK FOR MORE WORK 3$: JSR PC,FLUSH ;FLUSH STALE PACKETS JSR PC,CKRLI ;CHECK FOR RECEIVE LIST INVALID RETURN ;NO WORK EXIT ; ; CONTROL PASSES HERE WHEN A PACKET HAS BEEN SUCCESSFULLY ; REMOVED FROM THE I/O QUEUE WITH THE FOLLOWING ARGUMENTS ; GIVEN: ; R1 = ADDRESS OF THE I/O PACKET ; R2 = PHYSICAL UNIT NUMBER OF THE REQUEST UCB. ; R3 = CONTROLLER INDEX (CONTROLLER NUMBER TIMES 2) ; R4 = ADDRESS OF THE SCB ; R5 = ADDRESS OF THE UCB ; 10$: CMPB #IO.RLB/400,I.FCN+1(R1) ; READ LOGICAL ? BNE 20$ ;IF EQ NO MOV RDQUE,R2 ;GET BLOCK ADR FROM CKPKT JSR PC,RXFR ;TRANSFER USER BUFFER RTS PC ; 20$: CMPB #IO.WLB/400,I.FCN+1(R1) ;WRITE LOGICAL ? BNE 30$ ;NOT WLB JSR PC,XMIT ;SEND PACKET RTS PC ; 30$: JSR PC,GSTAT ;GET THE STATUS RTS PC ; .PAGE .SBTTL SEND PACKET ; ; ETHERNET SEND PACKET ; ; XMIT: MOV R1,WIOPK ;SAVE I/O PKT ADDRESS MOV I.PRM(R1),R3 ;GET RELOCATION BASE MOV I.PRM+2(R1),R4 ;GET DISPLACEMENT(BITS 0-5) MOV I.PRM+4(R1),R1 ;GET BYTE COUNT CMP R1,#MAXPKT ;TEST FOR PACKET TO LARGE BGT 5$ ;YES CMP R1,#MINPKT ;CHECK FOR MINIMUM PACKET SIZE BGE 10$ ;IN RANGE CONTINUE MOV #MINPKT,R1 ;TO SMALL INSERT MINIMUM SIZE BR 10$ ;CONTINUE 5$: CLR WIOPK ;CLEAR WRITE FLAG(I/O PKT ADR) TST (SP)+ ;POP JSR ADDRESS OFF STACK JMP ER1 ;PACKET TO LARGE 10$: ASR R1 ;MAKE WORD COUNT CLR R2 ;HIGH ORDER 6 BITS ASHC #6,R2 ;GET 22-BIT BASE ADDRESS BIC #177700,R4 ;CLEAR APF BITS BIS R4,R3 ;INSERT BITS 0-5 MOV #120000,-(SP) ;DESC BITS PLUS ADR-HI MOV #TBUFD,R4 ;XMIT BDL ADDRESS JSR PC,MBDL ;MAKE XMIT BDL TST (SP)+ ;CLEAN UP STACK MOV TBUFDX,TBDL ;SETUP XMIT BDL REGISTER MOV TBUFDX+2,TBDL+2 ;START XMIT RETURN .PAGE .SBTTL GET QNA LINK INFORMATION ; ;GET LINK NODE PHYSICAL ADDRESS ; AND ERROR COUNTERS ; ; ERROR COUNTERS CAN ALSO BE CLEARED ; GSTAT: MOV I.PRM+4(R1),R2 ;GET COUNT CMP R2,#STACNT ;TEST COUNT RANGE BLE 10$ ;IN RANGE MOV #STACNT,R2 ;FIX AT MAXIMUM RANGE 10$: ASR R2 ;CONVERT TO WORD COUNT MOV I.PRM+2(R1),R0 ;USER BUFFER OFFSET(DIB) MOV KISAR6,-(SP) ;SAVE KERNEL APR6 MOV I.PRM(R1),KISAR6 ;MAP TO USER BUFFER SEC ;ASSUME STATUS NOT TO BE CLEARED BIT #IO.GLC&10,I.FCN(R1) ;TEST FOR CLEAR STATUS BIT BEQ 15$ ;NO CLC ;CLEAR STATUS 15$: MOV #NODE,R3 ;STATUS BUFFER MOV R2,R1 ;SAVE WORD COUNT FOR IOSB 20$: MOV (R3)+,(R0)+ ;TRANSFER STATUS TO USER BUFFER SOB R2,20$ ;LOOP ON STATUS WORD COUNT MOV (SP)+,KISAR6 ;RESTORE KERNEL APR6 BCS 30$ ;SKIP CLEAR STATUS MOV #NODE+2,R0 ;STATUS STARTING ADDRESS MOV R1,R2 ;GET WORD COUNT DEC R2 ;DON'T CLEAR NODE ADDRESS BEQ 30$ ;COUNT EQUAL ZERO 25$: CLR (R0)+ ;CLEAR STATUS SOB R2,25$ ;LOOP ON STATUS WORD COUNT 30$: MOV #IS.SUC,R0 ;SET SUCCESS CODE ASL R1 ;CONVERT BACK TO BYTE COUNT CALL $IODON ;FINISH I/O RETURN .PAGE .SBTTL INTERRUPT SERVICE ROUTINE ; ; INPUT INTERRUPT SERVICE ROUTINE ; R5 = UCB ADDRESS ; $XQINT::INTSV$ XQ,PR5,X$$Q11 ;;; MOV #401,XQCSR ;;;DISABLE INTERRUPTS CALL $FORK ;;;CREATE A SYSTEM PROCESS ; ;PROCESS PACKETS AT FORK LEVEL ; 1$: MOV XQCSR,R4 ;GET CSR VALUE BIT #100200,R4 ;ANY REQUESTS OUTSTANDING BEQ 20$ ;NO EXIT BIT #100000,R4 ;ANY RECEIVE REQUESTS ? BEQ 10$ ;NO MUST BE XMIT BIC #200,R4 ;NO DON'T DISTURB XMIT MOV R4,XQCSR ;CLEAR RECEIVE REQUSET JSR PC,RINT ;PROCESS RECEIVE REQUESTS BR 1$ ;ANY REQUESTS PENDING 10$: MOV R4,XQCSR ;CLEAR XMIT REQUEST JSR PC,XINT ;PROCESS XMIT REQUEST BR 1$ ;ANY REQUESTS PENDING 20$: MOV #501,XQCSR ;RESTORE INTERRUPTS JMP XQINI ;ANY WORK LEFT ? .PAGE .SBTTL RECEIVE INTERRUPT PROCESSING ; ; ;FIND ALL PACKETS GET BYTE COUNT AND STATUS FOR EACH ;MAKE AN ENTRY IN THE PACKET USED QUEUE FOR DISTRIBUTION ;TO USER TASKS WHEN QIO'S ARE POSTED(MAYBE THEY ALREADY ARE) ; R4=BDL POINTER ; R2=WORD COUNT ; RINT: MOV CRBDL,R4 ;GET LAST BDL(CURRENT) ADDRESS 10$: BIT #40000,(R4) ;IS BDL USED BNE 12$ ;YES 11$: RTS PC ;ALL DONE<<<<< EXIT >>>>> 12$: BIT #CHAIN,2(R4) ;TEST FOR CHAIN BLOCK BEQ 15$ ;NO CMP R4,CRBDL ;DOES PACKET SPAN CHAIN BLOCK ? BNE 13$ ;YES LEAVE CRBDL AS IS MOV #RBUFD,CRBDL ;NO RESET CRBDL 13$: MOV #RBUFD,R4 ;YES RESET BDL POINTER BR 10$ ;FIND END OF PACKET 15$: CMP #IBDL,XST1(R4) ;HAS STATUS BEEN UPDATED YET ? BEQ 11$ ;NO EXIT BIT #100000,XST1(R4) ;TEST FOR END OF PACKET BEQ 20$ ;YES MOV #IBDL,(R4) ;RE-INITIALIZE BDL FLAG MOV #IBDL,XST1(R4) ;RE-INITIALIZE STATUS-1 MOV #IBDL,XST2(R4) ;RE-INITIALIZE STATUS-2 ADD #BDLSIZ*2,R4 ;NOT END OF PACKET BR 10$ ;FIND END OF PACKET 20$: CMP #IBDL,XST2(R4) ;HAS BYTE COUNT BEEN UPDATED YET ? BEQ 11$ ;NO EXIT BIT #40000,XST1(R4) ;TEST FOR ERRORS BNE 21$ ;YES FIND THEM INC RCTR ;INCREMENT RECEIVE PACKET COUNT BR 30$ ;NO ERRORS 21$: MOV XST1(R4),R2 ;GET READ STATUS-1 INC RERR ;BUMP TOTAL RECEIVE ERROR COUNT BIT #4000,R2 ;TEST FOR RUNT BEQ 22$ ;NO INC RUNT ;COUNT RUNT ERRORS 22$: BIT #10000,R2 ;TEST FOR DISCARD BEQ 25$ ;NO RE-POST BUFFER INC DISCAR ;COUNT DISCARD ERRORS BIT #2,R2 ;TEST FOR CRC BEQ 23$ ;NO INC CRC ;COUNT CRC ERRORS 23$: BIT #1,R2 ;TEST FOR OVR BEQ 24$ ;NO TRY FRAME INC OVR ;COUNT OVERFLOW ERRORS 24$: BIT #4,R2 ;TEST FOR FRAME ERROR BEQ 25$ ;NO RE-POST BUFFER INC FRAME ;COUNT FRAME ERRORS 25$: MOV #IBDL,(R4) ;INIT FLAG(RE-POST BUFFER) MOV #IBDL,XST1(R4) ;INIT STATUS-1 MOV #IBDL,XST2(R4) ;INIT STATUS-2 ADD #BDLSIZ*2,R4 ;NEXT BDL POINTER MOV R4,CRBDL ;NEW CRBDL POINTER BR 10$ ;ANY MORE PACKETS TO PROCESS 30$: MOV XST2(R4),R2 ;GET BYTE COUNT BIC #177400,R2 ;CLEAR HIGH BYTE MOV XST1(R4),-(SP) ;GET STATUS-1(HIGH BYTE COUNT) BIC #174377,(SP) ;EXTRACT HIGH BYTE COUNT BITS BIS (SP)+,R2 ;MERGE WITH LO BYTE COUNT BITS ADD #74,R2 ;ADD IN ADR FILTER LOSS MOV R4,-(SP) ;SAVE NEW BDL ADDRESS MOV #IBDL,(R4) ;RE-INITIALIZE BDL FLAG MOV #IBDL,XST1(R4) ;RE-INITIALIZE BDL STATUS-1 MOV #IBDL,XST2(R4) ;RE-INITIALIZE BDL STATUS-2 MOV CRBDL,R4 ;GET START OF PACKET ADR BIC #IBDL,XDSC(R4) ;INVALIDATE BUFFER MOV R2,XST1(R4) ;SAVE BYTE COUNT IN FIRST BUFFER (STATUS-1) MOV XADR(R4),R2 ;GET BUFFER ADR-LO SUB BASLO,R2 ;GET OFFSET FROM START OF DRIVER BIS #120000,R2 ;SET APF=APR5 MOV R2,XST2(R4) ;SAVE BUFFER VIRTUAL ADDRESS(STATUS-2) ; ;QUEUE PACKET(R4=BDL ADR,R2=BUFFER ADR) ;FIND FREE BLOCK MOV PKLHE,R3 ;GET EMPTY LIST PTR MOV (R3),PKLHE ;REMOVE BLOCK FROM QUEUE ;INSERT IN USED QUEUE MOV PKLHU+2,R0 ;END OF USED LIST MOV R3,(R0) ;INSERT LINK IN LAST BLOCK MOV R3,PKLHU+2 ;UPDATE END OF LIST CLR (R3)+ ;INDICATE NEW END OF LIST MOV R4,(R3)+ ;INSERT BDL ADDRESS MOV XQDTSK(R2),(R3)+ ;INSERT TASK NAME(1) MOV XQDTSK+2(R2),(R3)+ ;INSERT TASK NAME(2) ADD #BDLSIZ*2,(SP) ;ADVANCE BDL POINTER MOV (SP)+,CRBDL ;START OF PACKET BDL ADDRESS JMP RINT ;ANY MORE PACKETS .PAGE .SBTTL TRANSMIT INTERRUPT PROCESSING ; XINT: MOV TBUFD+10,R4 ;GET STATUS-1 BIT #360,R4 ;TEST FOR COLISION COUNT BEQ 5$ ;NO MOV R4,R1 ;GET READY TO COUNT COLISION'S BIC #177400,R1 ;MASKOUT HIGH ORDER BITS ASH #-4,R1 ;POSITION COUNT BITS ADD R1,COLCNT ;ADD INTO COUNT 5$: MOV #IS.SUC,R0 ;ASSUME SUCCESS CLR R1 ;CLEAR ERROR STATUS WORD BIT #40000,R4 ;ANY ERRORS BNE 10$ ;YES GO FIND THEM INC XCTR ;INCREMENT XMIT PACKET COUNTER BR 20$ ;NO 10$: INC XERR ;TOTAL XMIT ERROR COUNT BIT #10000,R4 ;TEST FOR LOSS BEQ 11$ ;NO INC LOSS ;COUNT LOSS ERRORS 11$: BIT #4000,R4 ;TEST FOR NO-CARRIER BEQ 12$ ;NO INC NOCAR ;COUNT NO-CARRIER ERRORS 12$: BIT #1000,R4 ;TEST FOR ABORT BEQ 14$ ;NO INC ABORT ;COUNT ABORT ERRORS 14$: MOV R4,R1 ;GIVE PROGRAM STATUS BITS BIC #20017,R1 ;CLEAR RESERVED BITS MOV #IE.FHE,R0 ;FATAL HARDWARE ERROR 20$: MOV U.SCB(R5),R4 ;GET SCB MOV WIOPK,S.PKT(R4) ;PUT I/O PACKET ADDRESS IN SCB CALL $IODON ;FINISH UP I/O CLR WIOPK ;CLEAR XMIT SWITCH RTS PC ;LOOK FOR MORE WORK<<<< EXIT >>>> .PAGE .SBTTL TRANSFER USER RECEIVE BUFFER ; ;TRANSFER USER(RECEIVE) BUFFER AND DO IODON PROCESSING ; ;INPUT ; R2=QUEUE BLOCK ADDRESS ; ;REGISTERS USED BY THIS SUBROUTINE ; ; R0=USER BUFFER ADDESS ; R1=QNA RECEIVE BUFFER ; R2=REMAINING WORD COUNT ; R3=CURRENT BLOCK WORD COUNT ; R4=BDL ADDRESS ; RXFR: MOV R2,-(SP) ;SAVE BLOCK ADDRESS MOV PQBDL(R2),R4 ;GET BDL ADDRESS MOV R4,-(SP) ;SAVE START OF PACKET BDL MOV XST1(R4),R2 ;GET BYTE COUNT CMP R2,I.PRM+4(R1) ;IS PACKET TO LARGE BLE 5$ ;NO MOV I.PRM+4(R1),R2 ;YES GET USER BUFFER LENGTH 5$: MOV R2,-(SP) ;SAVE BYTE COUNT FOR IOSB ASR R2 ;CONVERT TO WORD COUNT MOV I.PRM+2(R1),R0 ;GET USER BUFFER OFFSET(DIB) MOV KISAR6,-(SP) ;SAVE KERNEL APR6 MOV I.PRM(R1),KISAR6 ;MAP TO USER BUFFER MOV XST2(R4),R1 ;GET QNA DATA BUFFER 10$: BIT #CHAIN,XDSC(R4) ;TEST FOR CHAIN BLOCK BEQ 15$ ;NO MOV #RBUFD,R4 ;YES RESET BDL ADDRESS MOV #RBUF,R1 ;RESET DATA BUFFER 15$: MOV R2,R3 ;ASSUME LE BUFSIZ CMP R2,#BUFSIZ ;TEST FOR MORE THAN ONE BLOCK BLE 20$ ;LE ONE BLOCK MOV #BUFSIZ,R3 ;MORE THAN ONE BUFFER 20$: MOV (R1)+,(R0)+ ;TRANSFER BLOCK TO USER BUFFER SOB R3,20$ ;LOOP ON BUFFER SIZE ADD #BDLSIZ*2,R4 ;UPDATE BDL ADDRESS SUB #BUFSIZ,R2 ;UPDATE REMAINING WORD COUNT BGT 10$ ;MORE TO XFR MOV (SP)+,KISAR6 ;RESTORE KERNEL APR6 MOV (SP)+,R1 ;GET BYTE COUNT FOR $IODON MOV (SP)+,R3 ;RESTORE START OF PACKET BDL MOV #IBDL,XST1(R3) ;INITIALIZE STATUS-1(IN FIRST BUFFER ONLY) MOV #IBDL,XST2(R3) ;INITIALIZE STATUS-2(IN FIRST BUFFER ONLY) BIS #IBDL,XDSC(R3) ;RE-VALIDATE BUFFER 25$: MOV (SP)+,R0 ;INSERT BLOCK IN EMPTY QUEUE MOV PKLHE,(R0) ;LINK NEW BLOCK INTO MOV R0,PKLHE ;BEGINING OF LIST MOV #IS.SUC,R0 ;SET IOSB TO SUCCESS CALL $IODON ;FINISH UP TASK I/O RETURN .PAGE .SBTTL I/O PACKET CHECK ROUTINE ; ;GENERAL PACKET CHECK ROUTINE(ENTRY FROM $GSPKT) ; R1=I/O PACKET ADDRESS ; CKPKT: MOV R1,-(SP) ;SAVE I/O PACKET ADDRESS CMPB #IO.RLB/400,I.FCN+1(R1) ;IS IT RLB ? BNE 20$ ;NO SKIP IT MOV I.TCB(R1),R2 ;GET TCB ADR MOV #PKLHU,R3 ;GET USED LISTHEAD POINTER BR 10$ ;NOT EMPTY 5$: CMP T.NAM(R2),PQTSK(R3) ;TASK NAME(1) MATCH ? BNE 10$ ;NO MATCH CMP T.NAM+2(R2),PQTSK+2(R3) ;TASK NAME(2) MATCH ? BEQ 15$ ;FOUND MATCH 10$: MOV R3,R1 ;SAVE CURRENT BLOCK ADDRESS MOV (R1),R3 ;GET NEW BLOCK ADDRESS BNE 5$ ;NOT END TRY AGAIN BR 25$ ;REJECT PACKET 15$: MOV R3,RDQUE ;SAVE BLOCK ADDRESS MOV (R3),(R1) ;REMOVE PKT(CLOSE UP LIST) BNE 30$ ;REQUEST WAITING FOR THIS PACKET MOV R1,PKLHU+2 ;UPDATE END OF LIST POINTER BR 30$ ;REQUEST WAITING FOR THIS PACKET 20$: CMPB #IO.WLB/400,I.FCN+1(R1) ;TEST FOR WLB BNE 30$ ;EITHER GET STATUS OR ILLEGAL FUNCTION TST WIOPK ;XMIT OUTSTANDING ? BEQ 30$ ;NO ACCEPT PACKET 25$: SEC ;REJECT PACKET BR 35$ ;REJECT PACKET EXIT 30$: CLC ;ACCEPT PACKET 35$: MOV (SP)+,R1 ;RESTORE I/O PACKET ADDRESS RETURN .PAGE .SBTTL I/O DONE,CANCEL,TIMEOUT ; ; NOTE THAT $IODON PLACES R0 AND R1 IN IOSB AND IOSB+2 ; COMMON FINISH ROUTINE FOR ALL DONE,CANCEL,TIMEOUT ; R0=FIRST I/O STATUS WORD ; R1=SECOND I/O STATUS WORD ; R5=UCB ADDRESS ; DONE: CALL $IODON ;FINISH I/O JMP XQINI ;LOOK FOR MORE WORK XQ1: CLR R1 ;WORD COUNT=0 BR DONE ;DO I/O DONE PROCESSING ER1: MOV #IE.RBG,R0 ;ILLEGAL RECORD SIZE BR XQ1 ; ; CANCEL I/O ; ; R5=UCB ADDRESS ; R4=SCB ADDRESS ; R3=CONTROLLER INDEX ; R1=TCB ADDRESS ; R0=ACTIVE I/O PACKET ADDRESS ; XQCAN: MOV WIOPK,R2 ;;;GET WRITE I/O PACKET ADDRESS BEQ 5$ ;;;NONE OUTSTANDING CMP R1,I.TCB(R2) ;;;WAS THIS TASK DOING A WRITE BNE 5$ ;;;NO CLR WIOPK ;;;CLEAR WRITE I/O PKT FLAG 5$: RETURN ;;;EXIT ; ; DEVICE TIMEOUT ; XQTMO: MOV #IE.TMO,R0 ;SET TIME OUT BR XQ1 ;FINISH IN COMMON CODE .PAGE .SBTTL FLUSH STALE PACKETS ;FLUSH STALE PACKETS(IE. PACKETS IN THE SAFETY ZONE) ; ;USES REGISTERS RO-R4 ; FLUSH: MOV CRBDL,R0 ;GET CURRENT BDL POINTER MOV #SAFTY,R1 ;GET SAFETY ZONE SIZE IN BYTES ADD R0,R1 ;GET SAFETY ZONE HI-LIMIT MOV #PKLHU,R3 ;GET QUEUE LISTHEAD MOV #5$,R2 ;NO-WRAP TEST ROUTINE ENTRY CMP R1,#RBUFDE ;WRAP ARROUND ? BLOS 20$ ;NO CHECK SAFETY BAND SUB #RBUFDE,R1 ;WRAP ARROUND ADJUST LIMIT ADD #RBUFD,R1 ;HI-LIMIT NOW LO-LIMIT MOV #10$,R2 ;WRAP TEST ROUTINE ENTRY BR 20$ ;CHECK SAFETY BAND 5$: BLO 20$ ;PACKET OK SKIP CMP R4,R1 ;CHECK HI-LIMIT BHI 20$ ;PACKET OK SKIP BR 15$ ;ERROR FLUSH PACKET 10$: BHIS 15$ ;PACKET IN SAFETY ZONE FLUSH IT CMP R4,R1 ;CHECK HI-LIMIT BHIS 20$ ;PACKET OK SKIP 15$: MOV CTSK,PQTSK(R3) ;INSERT CLEANUP TASK NAME MOV CTSK+2,PQTSK+2(R3) ;AND FLUSH IT 20$: MOV (R3),R3 ;GET NEXT ENTRY BEQ 25$ ;DONE EXIT MOV PQBDL(R3),R4 ;GET BDL POINTER CMP R4,R0 ;CHECK LO-LIMIT JMP (R2) ;GO TO TEST ROUTINE 25$: RTS PC .PAGE .SBTTL RECEIVE LIST INVALID CHECK ;CHECK FOR RECEIVE LIST INVALID ;IF INVALID INITIALIZE BDL AND RE-START LIST ; ;USES R0-R2 ; CKRLI: BIT #40,XQCSR ;RECEIVE LIST INVALID ? BEQ 10$ ;NO EXIT NOP ;********************* MOV #RBUFD,R0 ;YES FLUSH ALL PACKETS MOV #NBUF,R1 ;NUMBER OF BUFFERS MOV #IBDL,R2 ;GET INITIALIZE FLAG WORD 5$: MOV R2,XFLG(R0) ;INITIALIZE BD FLAG BIS R2,XDSC(R0) ;SET BUFFER VALID MOV R2,XST1(R0) ;INITIALIZE STATUS-1 MOV R2,XST2(R0) ;INITIALIZE STATUS-2 ADD #BDLSIZ*2,R0 ;POINT TO NEXT DESCRIPTOR SOB R1,5$ ;END OF LIST YET ? MOV PKLHE,@PKLHU+2 ;CONNECT USED/EMPTY QUEUES MOV PKLHU,PKLHE ;PUT ALL ENTRIES IN EMPTY QUEUE CLR PKLHU ;INDICATE QUEUE EMPTY MOV #PKLHU,PKLHU+2 ;SET USED QUEUE TO EMPTY STATE MOV #RBUFD,CRBDL ;RESET CRBDL POINTER MOV RBUFDX,RBDL ;SETUP QNA LO-BDL REGISTER MOV RBUFDX+2,RBDL+2 ;START RECEIVE LIST 10$: RTS PC ;EXIT .PAGE .SBTTL MAKE BDL SUBROUTINES ;MAKE BDL SUBROUTINE ; R4=BDL ADDRESS ; R3=BUF ADR-LO ; R2=BUF ADR-HI ; R1=WC ; (SP)=DESCRIPTOR BITS MBDL: MOV #IBDL,(R4)+ ;INIT FLAG BIS 2(SP),R2 ;INSERT DESC. BITS MOV R2,(R4)+ ;DESC PLUS ADR-HI MOV R3,(R4)+ ;ADR-LO MOV R1,(R4) ;INSERT WORD COUNT NEG (R4)+ ;MAKE IT NEGATIVE MOV #IBDL,(R4)+ ;STATUS-1 MOV #IBDL,(R4)+ ;STATUS-2 RTS PC ;MAKE RECEIVE BDL ENTRY MBDL1: MOV 2(SP),-(SP) ;FIX UP STACK FOR MBDL JSR PC,MBDL ;MAKE BUFFER DESCRIPTOR TST (SP)+ ;CLEAN UP STACK BIC #177700,R2 ;CLEAR DESC BITS ADD R1,R3 ;GET NEXT BUFFER ADDRESS(R1=WC) ADC R2 ;ADD OVERFLOW IF ANY ADD R1,R3 ;REMEMBER R1=WORD COUNT ADC R2 ;ADD OVERFLOW IF ANY RTS PC .PAGE .SBTTL POWER FAIL INITIALIZE ; ;POWERFAIL ENTRY ; ; R3=CONTROLLER INDEX ; R4=SCB ADDRESS ; R5=UCB ADDRESS ; ;REGISTERS USED BY POWERFAIL ; ; R4=BDL ADR ; R3=BUF ADR-LO ; R2=BUF ADR-HI ; R1=WC ; R0=#REC. BUFFERS ; (SP)=DESC BITE XQPWR: MOV R5,CNTBL ;SAVE UCB ADDRESS MOV #2,XQCSR ;RESET QNA CLR XQCSR ;CLEAR RESET MOV #2,R2 ;OUTER LOOP COUNT MOV #RBUF+41,R0 ;INIT NODE ADR 1-7 MOV #NODES,R3 ;GET MULTICAST/BROADCAST NODES ADR MOVB (R3),NODE ;GET MY NODE ADDRESS 9$: MOV #7,R1 ;INTER LOOP COUNT 10$: MOVB (R3)+,(R0)+ ;INIT NODE ADDRESS BPL 15$ ;PHYSICAL ADDRESS IF PLUS CMPB #-1,-1(R0) ;BROADCAST ? BNE 13$ ;NO MUST BE MULTICAST MOV R0,-(SP) ;SAVE SETUP BUFFER POINTER MOV #6,R4 ;BROADCAST FIELD SIZE 11$: MOVB #-1,-41(R0) ;FILL IN BROADCAST BYTE ADD #10,R0 ;NEXT BYTE POINTER SOB R4,11$ ;LOOP ON BROADCAST FIELD SIZE MOV (SP)+,R0 ;RESTORE SETUP BUFFER POINTER 13$: BISB #1,-41(R0) ;SET MULTICAST BIT(OK FOR BROADCAST) 15$: SOB R1,10$ ;LOOP ON NUMBER OF FIELDS MOV #RBUF+141,R0 ;INIT NODE ADR 8-14 SOB R2,9$ ;LOOP ON NUMBER OF FIELD GROUPS MOV KISAR5,R3 ;DRIVER BASE APR CLR R2 ;CLEAR HI-ADDRESS BITS ASHC #6,R2 ;BUILD DRIVER BASE ADDRESS MOV #ADR22I,R0 ;INPUT ADDRESS OFFSET TABLE MOV #ADR22O,R1 ;22-BIT OUTPUT ADDRESS TABLE MOV #ADR22L/2,R4 ;NUMBER OF 22-BIT ADDRESS ENTRIES 20$: MOV R3,(R1) ;COMPUTE 22-BIT ADR ADD (R0)+,(R1)+ ;ADD LOW ORDER OFFSET MOV R2,(R1) ;STORE HIGH ORDER OFFSET ADC (R1)+ ;ADD OVERFLOW IF ANY SOB R4,20$ ;LOOP ON NUMBER OF 22-BIT ADDRESS'S MOV #SWC,R1 ;SETUP WORD COUNT MOV RBUFX,R3 ;GET 22-BIT RBUF ADDRESS MOV RBUFX+2,R2 ;GET 22-BIT RBUF ADDRESS(HI) MOV #TBUFD,R4 ;XMIT BDL ADDRESS MOV #130000,-(SP) ;XMIT BDL DESC. BITS JSR PC,MBDL1 ;MAKE XMIT BDL CMP (R4)+,(R4)+ ;SKIP XMIT BDL TERMINATOR MOV #100000,(SP) ;RECEIVE BDL DESC. BITS JSR PC,MBDL1 ;MAKE RECEIVE BDL MOV RBUFDX,RBDL ;RECEIVE SETUP LO MOV RBUFDX+2,RBDL+2 ;START RECEIVE SETUP MOV TBUFDX,TBDL ;XMIT SETUP LO MOV TBUFDX+2,TBDL+2 ;START XMIT SETUP BDL 30$: BIT #100000,RBUFD+10 ;WAIT ON SETUP BNE 30$ ;TRY AGAIN MOV #RBUFD,R4 ;RECEIVE BDL START ADDRESS MOV RBUFX,R3 ;RBUF-LO MOV RBUFX+2,R2 ;RBUF-HI MOV #BUFSIZ,R1 ;RECEIVE BUFFER SIZE(WORDS) MOV #NBUF,R0 ;NUMBER OF RECEIVE BUFFERS 40$: JSR PC,MBDL1 ;MAKE REC. BDL SOB R0,40$ ;LOOP ON NUMBER OF BUFFERS TST (SP)+ ;CLEAN UP STACK FROM MBDL1 MOV RBUFDX,R3 ;GET RBUFD 22-BIT ADDRESS(LO) MOV RBUFDX+2,R2 ;GET HIGH ADDRESS BITS BIS #IBDL!CHAIN,R2 ;CHAIN BIT MOV #IBDL,(R4)+ ;BUILD CHAIN BLOCK MOV R2,(R4)+ ;DESC. BITS/ADR-HI MOV R3,(R4)+ ;ADR-LO MOV #VECTOR,XQVEC ;INSERT VECTOR ADDRESS MOV #100600,XQCSR ;CLEAR INTERRUP REQUEST MOV #501,XQCSR ;ENABLE INTERRUP MOV #RBUFD,CRBDL ;INITIALIZE BDL STARTING ADR MOV RBUFDX,RBDL ;RECEIVE BDL LO MOV RBUFDX+2,RBDL+2 ;START RECEIVE BDL RETURN .PAGE .SBTTL VARIABLE STORAGE AND DATA BUFFERS ; ; CNTBL: .BLKW X$$Q11 ;UCB ADDRESS OF CURRENT REQUEST WIOPK: .WORD 0 ;WRITE I/O PACKET ADDRESS CRBDL: .WORD 0 ;CURRENT RECEIVE BUFFER POINTER RDQUE: .WORD 0 ;POINTER FOR PACKET CURRENTLY BEING XFR'D STATUS: .WORD 0 ;DRIVER STATUS WORD CTSK: .RAD50 /LWT.../ ;CLEANUP TASK NAME NODE:: .BLKB STACNT ;NODE ADDRESS AND ERROR COUNTERS RCTR=NODE+XQRCTR ;TOTAL NUMBER OF PACKETS RECEIVED XCTR=NODE+XQXCTR ;TOTAL NUMBER OF PACKETS TRANSMITTED RERR=NODE+XQRERR ;TOTAL NUMBER OF RECEIVE ERRORS XERR=NODE+XQXERR ;TOTAL NUMBER OF TRANSMIT ERRORS LOSS=NODE+XQLOSS ;XMIT LOSS ERROR COUNT NOCAR=NODE+XQNCAR ;XMIT NO-CARRIER ERROR COUNT ABORT=NODE+XQABO ;XMIT ABORT ERROR COUNT COLCNT=NODE+XQCOLL ;XMIT COLLISION COUNT RUNT=NODE+XQRUNT ;RECEIVE RUNT ERROR COUNT DISCAR=NODE+XQDISC ;RECEIVE DISCARD ERROR COUNT OVR=NODE+XQOVF ;RECEIVE OVERFLOW ERROR COUNT CRC=NODE+XQCRC ;RECEIVE CRC ERROR COUNT FRAME=NODE+XQFRAM ;RECEIVE FRAME ERROR COUNT ADR22I: .WORD RBUFD-BASE ;RECEIVE BDL OFFSET .WORD TBUFD-BASE ;XMIT BDL OFFSET .WORD RBUF-BASE ;RECEIVE BUFFER OFFSET .WORD BASE-BASE ;DRIVER BASE ADDRESS OFFSET ADR22L=.-ADR22I ;LENGTH OF INPUT OFFSET ADDRESS'S ADR22O: .BLKW ADR22L ;22-BIT ADDRESS SAVE BUFFER RBUFDX=ADR22O ;RECEIVE BDL 22-BIT ADDRESS TBUFDX=ADR22O+4 ;XMIT BDL 22-BIT ADDRESS RBUFX=ADR22O+10 ;RECEIVE BUFFER 22-BIT ADDRESS BASLO=ADR22O+14 ;DRIVER BASE 22-BIT ADDRESS PKLHU: .WORD 0,.-2 ;USED BLOCK LIST HEAD PKLHE: .WORD PKTQUE ;FREE BLOCK LIST HEAD PKTQUE: CQUE NBUF-1 ;CREATE PACKET USED QUEUE TBUFD: .BLKW BDLSIZ+2 ;XMIT BDL PLUS TERMINATOR RBUFD: .BLKW NBUF*BDLSIZ+3 ;REC BDL PLUS CHAIN BLOCK RBUFDE=.-10 ;END OF RECEIVE BDL RBUFDL=RBUFDE-RBUFD ;BUFFER DESCRIPTOR LIST LENGTH RBUF: .BLKW NBUF*BUFSIZ ;QNA RECEIVE DATA BUFFERS ENDQNA: .END