.TITLE MOSLNI - MOS LNI DEVICE DRIVER ROUTINES ; THERE ARE TWO ENTRIES FOR EACH DEVICE IN THE DCTS - THE RECEIVE ; SIDE MUST COME FIRST, AND THE TWO MUST HAVE THEIR LINK DEVICES ; SET CORRECTLY. ALSO, THE TRANSMIT SIDE MUST HAVE AS ITS INTERRUPT ; VECTOR A LOCATION WHICH WILL NEVER RECEIVE AN INTERRUPT. ; ALL INTERRUPTS ARE CALLED THROUGH THE PREPROCESSOR WHICH ; LOOKS LIKE THE READ SIDE HANDLER TO MOS. .INSRT ../moscnf-1.sml .INSRT ../mosmac.sml .INSRT ../mostbl.sml .ENABL ISD .LIST ME $CNFIG .PAGE $DFDCT .PAGE $DFIOR .PAGE $DFIST .NLIST ME .LIST MEB .CSECT MOS .GLOBL .LNII ;NET INITIALIZE ROUTINE .GLOBL .LNIIT ;NET INPUT TRANSFER ROUTINE .GLOBL .LNIOT ;NET OUTPUT TRANSFER ROUTINE .GLOBL LNIIN ;NET INTERRUPT ROUTINE .GLOBL LNINN,LNINM,LNISN ;NAME TABLE ENTRY DATA .GLOBL $IOCMR ;I/O COMPLETION EXIT .GLOBL TYPE ;A FEW THINGS TO HACK THE SYSTEM .GLOBL $NETID,$HSTID ;MY NAME .GLOBL $MLNTP,$MLNBT ;CODE SPACE TOP/BOTTOM .SBTTL LNI INTERFACE REGISTER ASSIGNMENTS ; ; LNICSR = 00 ; LNI COMMAND REGISTER LNIRSR = 02 ; LNI STATUS REGISTER LNIOAL = 10 ; LNI OUTPUT ADDR REG LNIOAH = 12 ; LNI OUTPUT ADDR REG LNIIAL = 14 ; LNI INPUT ADDR REG LNIIAH = 16 ; LNI OUTPUT ADDR REG LNIOBC = 20 ; LNI OUTPUT BYTE COUNT REG LNIIBC = 22 ; LNI INPUT BYTE COUNT REG ; COMMAND REG BITS LN.ROK = 100000 ; RING OK LN.OFIR = 40000 ; OUTPUT FIFO INPUT READY LN.OFOR = 20000 ; OUTPUT READY LN.IFIR = 10000 ; INPUT FIFO INPUT READY LN.IFOR = 4000 ; OUTPUT READY LN.COF = 2000 ; CLEAR O/P FIFO LN.DENB = 1000 ; ENABLE DMA LN.DINT = 400 ; DMA DONE INTERRUPT LN.CLRNT = 200 ; CLEAR NT LN.RRSET = 140 ; READ AND RESET LN.RMNT = 100 ; REMOVE FROM NT LN.ADDNT = 40 ; ADD TO NT LN.FRCT = 20 ; FORCE TOKEN OUTPUT LN.OPDINT = 10 ; OUTPUT DONE INTERRUPT LN.OPENB = 4 ; OUTPUT ENABLE LN.IPDINT = 2 ; INPUT DONE INTERRUPT LN.IPENB = 1 ; ENABLE INPUT ; STATUS REG LN.OFE = 100000 ; OUTPUT FRMT ERR LN.BMA = 40000 ; BAD MATCH/ACCEPT LN.CNM = 20000 ; CRC NO MATCH LN.ROCB = 10000 ; RCVD O/P CRC BAD LN.OUR = 4000 ; OUTPUT UNDERRUN LN.MSGE = 2000 ; MESSAGE ERR LN.IFE = 1000 ; INPUT FORMAT ERR LN.ICB = 400 ; INPUT CRC BAD LN.IOR = 200 ; INPUT OVERRUN LN.NTB = 100 ; NAME TABLE BUSY LN.NTE = 40 ; NT ERR LN.RRF = 20 ; RR FIND LN.ACC = 10 ; ACCPT LN.MTCH = 4 ; MATCH LN.OPC = 2 ; OUTPUT COMPLETE LN.IPC = 1 ; INPUT COMPLETE .PAGE .SBTTL SOME LNI CONSTANTS LNINMA = 04 ; OFFSET INTO NAME FOR NAME LNINL = 10 ; LNI NAME LENGTH LNINDT = 20 ; LNI NAME DMA TIME LNINTT = 100 ; TIME TO ADD TO NT LNIDPT = 200 ; DMA PREFILL TIME LNITML = 20 ; LENGTH OF TOKEN MESSAGE LNITDT = 40 ; TIME FOR DMA LNITTT = 1000 ; TIME TO SEND IT LNIML = 14 ; PLACE WHERE MSG LENGTH IS LNIHL = 16 ; LENGTH OF HEADER LNIIFT = 200 ; TIME FOR I/P FIFO TO EMPTY LNIIER = LN.IFE!LN.ICB!LN.IOR ; INPUT AND OUTPUT ERRORS LNIOER = LN.OFE!LN.BMA!LN.CNM!LN.ROCB!LN.OUR .PAGE .SBTTL LNI INTERFACE INITIALIZATION ROUTINE ; ; CALLED WITH: R2 - ADDRESS OF DCT ; ; NOTE THAT NOT ONLY IS THE FIRST ENTRY RESERVED FOR THE DRIEVR TO FILL ; IN WITH THE REAL ADDRESS OF THIS HOST IN STRUCTURED PROTOCOLS, BUT SINCE ; THE HARDWARE FOR DPNM'S DOESN'T WORK IN MESSAGES A SECOND IS RESERVED FOR ; A BROADCAST ADDRESS WHICH IS SIMPLY HOST 0 ON THE APPROPRIATE SUBNET. $MLNTP: .LNII: $PUSH R0,R1,R3,R4 MOV DCTCSR(R2),R0 MOV #LN.CLRNT,LNICSR(R0) ; CLEAR OUT NT CLR LNIIAH(R0) CLR LNIOAH(R0) MOV #LNINM,R4 ; FILL IN MY NAME AS A DEFAULT ADD #LNINMA,R4 TSTB (R4)+ ; NOTHING FOR PROT TSTB LNISN ; WAS DEFAULT SUBNET SUPPLIED? BNE 1$ MOVB $NETID+1,(R4)+ ; NO, USE SUBNET FROM SYSTEM BR 2$ 1$: TSTB (R4)+ ; YUP, USE IT 2$: MOV $HSTID,(R4)+ ; NOW FILL IN HOST NUMBER FROM SYSTEM ADD #LNINMA,R4 ; NOW DO BROADCAST ADDRESS CLR (R4)+ ; ZERO IS BROADCAST ADDRESS CLR (R4)+ MOV LNINN,R3 ; LOAD IN NUMBER OF NAMES MOV #LNINM,R4 ; AND TABLE ADDR LNLDNM: MOV R4,LNIOAL(R0) ; LOAD IN NAME NOW MOV #LNINL,LNIOBC(R0) ; PUT NAME IN FIFO MOV #LN.DENB,LNICSR(R0) MOV #LNINDT,R1 2$: TST LNIOBC(R0) BEQ 3$ $LOOP R1,2$ BUGHLT 3$: MOV #LN.ADDNT,LNICSR(R0) ; STICK IT INTO NT MOV #LNINTT,R1 4$: BIT #LN.NTB,LNIRSR(R0) BEQ 5$ $LOOP R1,4$ BUGHLT 5$: BIT #LN.NTE,LNIRSR(R0) ; MAKE IT OK? BEQ 6$ BUGHLT 6$: ADD #LNINL,R4 ; POINT AT NEXT NAME $LOOP R3,LNLDNM ; IF THERE IS ANOTHER DO IT BIT #LN.ROK,LNICSR(R0) ; RING UP? BNE 10$ ; YES CALL LNIRI ; NO, TRY AND INIT RING 10$: MOV #LN.DENB,LNICSR(R0) MOV DCTLNK(R2),R0 ; GET COMPANION DEVICE MOV R0,R1 ; SET UP OTHER VECTOR ADD #DCTIHX,R1 MOV R1,@DCTIVA(R0) MOV DCTIVA(R0),R1 MOV #340,2(R1) BIC #DF.OFL,DCTFLG(R2) ; INDICATE DEVICE ON-LINE BIC #DF.OFL,DCTFLG(R0) ; DO BOTH SIDES $POP R4,R3,R1,R0 RTS PC ; RETURN .PAGE .SBTTL LNI INPUT TRANSFER INITIALIZATION ROUTNE ; ; CALLED WITH: R2 - POINTER TO DEVICE CONTROL TABLE (DCT) ; ; RETURNS WITH: R0 THRU R5 - UNCHANGED ; .LNIIT: $PUSH R0,R1 CMP DCTBR(R2),#LNIHL+2 ; LONG ENOUGH FOR MINIMAL MSG? BGE 1$ BUGHLT 1$: MOV DCTCSR(R2),R0 ; RING UP? BIT #LN.ROK,LNICSR(R0) BNE 3$ ; YES CALL LNIRI ; TRY INIT RING 3$: CLR LNIIBC(R0) ; SET UP XFER MOV DCTUVA(R2),LNIIAL(R0) BIS #LN.IPENB!LN.IPDINT,LNICSR(R0) ; ENABLE (CLRS I/P FIFO) MOV DCTBR(R2),LNIIBC(R0) BIS #DF.ACT,DCTFLG(R2) ; INDICATE ACTIVE $POP R1,R0 RTS PC .PAGE .SBTTL LNI OUTPUT TRANSFER INITIALIZATION ROUTINE ; ; CALLED WITH: R2 - POINTER TO DEVICE CONTROL TABLE (DCT) ; ; RETURNS WITH: R0 THRU R5 - UNCHANGED ; .LNIOT: $PUSH R0, R1 MOV DCTUVA(R2),R0 ; POINTER TO PKT MOV LNIML(R0),R0 ; PACKET LENGTH FIELD ADD #LNIHL,R0 CMP R0,DCTBR(R2) ; DOES THE PACKET LEN EQ RQSTD I/O? BEQ 1$ BUGHLT 1$: MOV DCTCSR(R2),R0 ; SET UP XFER CLR LNIOBC(R0) BIS #LN.COF,LNICSR(R0) ; CLEAR O/P FIFO MOV DCTUVA(R2),LNIOAL(R0) MOV DCTBR(R2),LNIOBC(R0) ; SET UP FOR DMA MOV #LNIDPT,R1 ; DMA PREFILL 2$: TST LNIOBC(R0) ; ALL LOADED? BEQ 3$ BIT #LN.OFIR,LNICSR(R0) ; FIFO FULL? BEQ 3$ $LOOP R1,2$ BUGHLT 3$: BIS #LN.OPENB!LN.OPDINT,LNICSR(R0) BIT #LN.ROK,LNICSR(R0) ; RING UP? BNE 4$ ; YES BIS #LN.FRCT,LNICSR(R0) ; NO, TRY TO BRING UP WITH THIS XFER 4$: BIS #DF.ACT,DCTFLG(R2) ; INDICATE ACTIVE $POP R1, R0 RTS PC .PAGE .SBTTL LNI INTERRUPT HANDLER ; ; CALLED WITH: R0 - ADDRESS OF DEVICE CONTROL TABLE ; (SP) - OLD R0 ; LNIIN: $PUSH R1,R2 MOV DCTCSR(R0),R1 BIT #DF.ACT,DCTFLG(R0) ; INPUT SIDE BUSY? BEQ 10$ ; NO, TRY OUTPUT BIT #LN.IPC,LNIRSR(R1) ; DID HE COMPLETE? BEQ 10$ ; NO, TRY OUTPUT MOV #LNIIFT,R2 1$: BIT #LN.IFOR,LNICSR(R1) ; FIFO DRAINED? BEQ 2$ TST LNIIBC(R1) ; OR DMA DONE? BEQ 2$ $LOOP R2,1$ BUGHLT 2$: MOV DCTQH(R0),R2 ; GET IORB BIT #LN.IFOR,LNICSR(R1) ; DATA LEFT IN FIFO IS AN ERROR BNE 3$ BIT #LNIIER,LNIRSR(R1) ; ANY ERRORS? BEQ 4$ 3$: BIS #I.ERR,IRSTA(R2) ; LOG 4$: MOV DCTBR(R0),IRBX(R2) ; INDICATE NUMBER OF BYTES DONE SUB LNIIBC(R1),IRBX(R2) BIC #DF.ACT,DCTFLG(R0) ; CLEAR, AS IOCMR WILL SET IF NEEDED CALL $IOCMR 10$: MOV DCTLNK(R0),R0 ; NOW DO OUTPUT SIDE BIT #DF.ACT,DCTFLG(R0) ; BUSY? BEQ LNIDN BIT #LN.OPC,LNIRSR(R1) ; DID HE COMPLETE? BEQ LNIDN ; NO, FINISH BIC #LN.FRCT,LNICSR(R1) ; TURN OFF IF ON BIT #LN.OUR,LNIRSR(R1) ; O/P DMA ERR BEQ 11$ $PUSH R0 MOV #ODEM,R0 CALL TYPE $POP R0 11$: MOV DCTQH(R0),R2 ; GET IORB BIT #LNIOER,LNIRSR(R1) ; ANY ERRORS? BEQ 12$ BIS #I.ERR,IRSTA(R2) ; LOG 12$: MOV DCTBR(R0),IRBX(R2) ; INDICATE NUMBER OF BYTES DONE SUB LNIOBC(R1),IRBX(R2) BIC #DF.ACT,DCTFLG(R0) ; CLEAR, AS IOCMR WILL SET IF NEEDED CALL $IOCMR LNIDN: $POP R2,R1,R0 ; AND WE'RE DONE $RTT .PAGE .SBTTL BRING UP RING BY FORCING A SHORT MESSAGE ; ; ATTEMPT TO INIT RING BY FORCING OUT A MESSAGE ; ASSUMES R0 POINTS TO LNI REGISTERS ; LNIRI: $PUSH R1 BIT #LN.ROK,LNICSR(R0) ; REALLY NOT THERE? BNE 12$ ; SOMEBODY ELSE FIXED? ; THIS CODE IS HERE TO PREVENT A CALL FROM INSIDE READ ; DAMAGING AN OUTPUT TRANSACTION. THERE IS POSSIBLY ; A SCREW WITH A OP COMPLETING AFTER INTERRUPTS GO OFF ; AND BEFORE WE TEST ENABLE. THE LATCH ON INTERRUPTS ; SHOULD DO THIS OK, AND THE COMP BIT WILL BE ON (WE HOPE) BIT #LN.OPENB,LNICSR(R0) ; OP TRANSFER IN PROGRESS? BEQ 2$ BIS #LN.FRCT,LNICSR(R0) ; INTERRUPT ROUTINE CLEARS BR 12$ 2$: MOV #LNITM,LNIOAL(R0) ; LOAD CRUFT INTO FIFO MOV #LNITML,LNIOBC(R0) MOV #LN.DENB,LNICSR(R0) ; OK TO STOMP ON CSR MOV #LNITDT,R1 ; AS ONLY GETS HERE FROM 7$: TST LNIOBC(R0) ; INIT OR READ WITH NO BEQ 8$ ; WRITE ACTIVE $LOOP R1,7$ BUGHLT 8$: MOV #LN.FRCT!LN.OPENB,LNICSR(R0) MOV #LNITTT,R1 ; PUSH IT OUT ONTO RING 9$: BIT #LN.OPC,LNIRSR(R0) BNE 10$ $LOOP R1,9$ BUGHLT 10$: BIT #LN.ROK,LNICSR(R0) ; MAKE IT? BNE 11$ ; YES $PUSH R0 MOV #CBRUM,R0 ; NO, BARF CALL TYPE $POP R0 11$: MOV #LN.DENB,LNICSR(R0) ; TURN DMA ON AND FT OFF 12$: $POP R1 RTS PC .PAGE .SBTTL DATA AREA .CSECT MOSDAT, STATIC ; RING INITIALIZATION MESSAGE LNITM: .WORD 0,0,0,0,0,0,2,72727 ; SHORT MESSAGE ; SOME ERROR MESSAGES ODEM: .ASCIZ <15><12>/LNI output DMA error/<15><12> CBRUM: .ASCIZ <15><12>/Can't bring ring up/<15><12> .EVEN $MLNBT: .END