.TITLE GATDEQ Network DEC DEQNA (QBUS) Ethernet driver .NLIST BEX .ENABL LC ; ; Pdp11/dcn network DEC DEQNA Ethernet driver ; ; This module is an extension of the network processes. it transmits and ; Receives packets using the DEC DEQNA Ethernet DMA interface ; ; External symbols ; .GLOBL .WAIT,.SKED,.ASYN,.STIM ;supervisor services .GLOBL NETINP,NETOUT ;process initialization ; ; Entry symbols ; .GLOBL DQIPAT ;input process control vector .GLOBL DQOPAT ;output process control vector ; ; System definitions ; .ASECT .MCALL .COM,.PSA,.GAT,.PAT ;dcnlib definitions .MCALL .SETV,.SKED,.ETH ;dcnlib macros .MCALL .CTIM,.ASYN,$DFEH ;moslib definitions .COM ;define common data .PSA ;define process stoage areas .GAT ;define gateway/bridge storage areas .ETH ;define ethernet storage areas $DFEH ;define header for farbling ; ; Module definitions ; ; Process save area extension (dqr) ; . = GATENR DQRSUP: .BLKB 128. ;rcvd setup DQXSUP: .BLKB 128. ;xmt setup .BLKW REGEND/2+NTISTK ;process stack DQREND = . ;end of dqr extension ; ; Process save area extension (dqx) ; . = GATENX .BLKW REGEND/2+NTOSTK ;process stack DQXEND = . ;end of dqx extension ; ; DEQNA device register block (dev) ; . = 0 DEQSAD: .BLKW 1 ;board station address (6 words) RO .BLKW 1 ; DEQRBL: .BLKW 1 ;receive BDL start address low WO DEQRBH: .BLKW 1 ;receive BDL start address high WO DEQTBL: .BLKW 1 ;transmit BDL start address low WO DEQTBH: .BLKW 1 ;transmit BDL start address high WO DEQVEC: .BLKW 1 ;ISR vector address RW DEQCSR: .BLKW 1 ;DEQNA CSR RW ; ; DEQNA CSR bit assignment ; CSRRE = 1 ;Receiver enable RW CSRSR = 2 ;Software reset RW CSRNI = 4 ;Nonexistant memory interrupt RO CSRBD = 10 ;Boot/Diagnostic ROM RW CSRXL = 20 ;Transmit list invalid RO CSRRL = 40 ;Receive list invalid RO CSRIE = 100 ;Interrupt enable RW CSRXI = 200 ;Transmit Interrupt request RW CSRIL = 400 ;Internal loopback RW CSREL = 1000 ;External loopback RW CSRSE = 2000 ;Sanity timer enable RW ; 4000 ;Reserved CSROK = 10000 ;Fuse OK RO CSRCA = 20000 ;Carrier RO ; 40000 ;Reserved CSRRI = 100000 ;Receive Interrupt request RW ; ; Buffer Descriptors ; . = 0 BDFLAG: .BLKW 1 ;Flags ; FLINIT = 100000 ;Initialized value; DEQNA isn't using yet FLUSE = 140000 ;The DEQNA is using this buffer ; BDADHA: .BLKW 1 ;Addr. descriptor bits/High order addr. bits ; BDV = 100000 ;Valid BDVBA = 100000 ;Valid buffer address BDVBD = 140000 ;Valid buffer descriptor address BDINV = 000000 ;This address is now invalid (end of the BDL) BDVRR = 40000 ;Reserved BDC = 40000 ;Chain address BDE = 20000 ;End of Message BDS = 10000 ;Set-Up BDL = 200 ;Low byte only termination BDH = 100 ;High byte only start ; BDADDR: .BLKW 1 ;Low order address bits BDSIZ: .BLKW 1 ;Buffer size BDSW1: .BLKW 1 ;BDL status word #1 ; Transmit status word #1 BDT1LN = 100000 ;Lastnot BDT1EU = 40000 ;Error/used BDT1LO = 10000 ;Loss BDT1NC = 4000 ;No carier BDT1S4 = 2000 ;STE16 BDT1AB = 1000 ;Abort BDT1FA = 400 ;Fail BDT1CM = 360 ;Collision count mask ; Receive status word #1 BDR1LN = 100000 ;Lastnot BDR1EU = 40000 ;Error/used BDR1ES = 20000 ;ESetup BDR1DC = 10000 ;Discard BDR1RU = 4000 ;Runt BDR1SH = 3400 ;Mask; RCV Byte length 10:08 (high) BDR1FE = 4 ;Frame alignment error BDR1CE = 2 ;CRC error BDR1OV = 1 ;Overflow ; LAST-out(15)/Error/Used(14) BDS1IN = 100000 ;Ini value, bufer hasn't been used yet BDS1US = 140000 ;Buffer used, not last segment of message BDS1LS = 0 ;Buffer contains last message segment BDS1LE = 40000 ;Buffer cont. last message segment with errors ; BDSW2: .BLKW 1 ;BDL status word #2 ; Transmit status word #2 BDT2TD = 37777 ;TDR 100 nsec resolution count. ; Receive status word #2 BDR2SL = 377 ;Receive byte length bits 07:00 (low) ; ; BDSIZE = . ;Size of the BD ; ; Parameter area extension (par) ; . = ETHLEN CIINI: .BLKW ;Ini RCVer COINI: .BLKW ;Ini XMTer CISIO: .BLKW ;RCV startio COSIO: .BLKW ;XMT startio CIINT: .BLKW ;RCV interrupts CIIRC: .BLKW ;RCV interrupt events COINT: .BLKW ;XMT Interrupts CORST: .BLKW ;XMT resets COASY: .BLKW ;XMT async events COTMO: .BLKW ;XMT timeouts COUEX: .BLKW ;Unexpected interrupts COMAD: .BLKW ;missed addresses ; DQRBLK: .BLKW BDSIZE/2 ;receive request block .BLKW 2 ; DQXBLK: .BLKW BDSIZE/2 ;transmit request block .BLKW 2 .PAGE ; ; Procedure segment ; ; Supervisor-state procedure ; Dsects: r2 = dev, r3 = par, r4 = reg, r5 = psa ; ; Note: calling process sets r0 = byte count, r1 = starting address. ; At completion of transfer r0 = byte count ; .PSECT $KERI,RO,I DEQCOD:: ;Label to find the code ; ; Initialize ; DQIINI: INC CIINI(R3) ;Count IINI attempts MOV #CSRSR,DEQCSR(R2) ;Reset device MOV PARVEC(R3),DEQVEC(R2) ;Set interrupt vector ; MOV #FLINIT,DQRBLK+BDFLAG(R3) ; MOV #BDVBA,DQRBLK+BDADHA(R3) ;Valid Setup packet MOV R5,R1 ;Get XMT PSA ADD #DQRSUP,R1 ;Add SUP offset MOV R1,DQRBLK+BDADDR(R3) ;Set start address MOV #-64.,DQRBLK+BDSIZ(R3) ;128 Bytes MOV #BDS1IN,DQRBLK+BDSW1(R3) ; MOV #177400,DQRBLK+BDSW2(R3) ;Trash RCVed size CLR DQRBLK+BDSW2+2(R3) ;Set following BDL CLR DQRBLK+BDSW2+4(R3) ;And mark it as End-of-List ; MOV #FLINIT,DQXBLK+BDFLAG(R3) ; MOV #BDVBA!BDE!BDS,DQXBLK+BDADHA(R3) ;Valid Setup packet MOV R5,R1 ;Get XMT PSA ADD #DQXSUP,R1 ;Add SUP offset MOV R1,DQXBLK+BDADDR(R3) ;Set start address MOV #-64.,DQXBLK+BDSIZ(R3) ;128 Bytes MOV #BDS1IN,DQXBLK+BDSW1(R3) ; CLR DQXBLK+BDSW2(R3) ; CLR DQXBLK+BDSW2+2(R3) ;Set following BDL CLR DQXBLK+BDSW2+4(R3) ;And mark it as End-of-List ; MOV R0,-(SP) ;Save R0 MOV R2,-(SP) ;Save R2 MOV R4,-(SP) ;Save R4 MOV R5,R0 ;Get XMT PSA ADD #DQXSUP,R0 ;Add setup offset MOV R3,R1 ;Get PAR ADD #ETHADR,R1 ;Add address offset MOV #6,R4 ;6 bytes/addresses ; 1$: CLRB 100(R0) ;Zero second half CLRB (R0)+ ;And first half MOVB (R2),(R1)+ ;Set one byte of our address MOVB (R2),100(R0) ;Set one byte in second half MOVB #377,(R0)+ ;Set BC address in first half ; MOV R4,-(SP) ;Save byte count MOV #6,R4 ;Count of things left to do 2$: MOVB (R2),100(R0) ;Second half first MOVB (R2),(R0)+ ;Now first half SOB R4,2$ ;Do six times MOV (SP)+,R4 ;Restore remaining count ; TST (R2)+ ;Done with this register SOB R4,1$ ;Do the whole address ; MOV #8.,R4 ;Now add 16 zeroes to each 3$: CLR 100(R0) ;Second half CLR (R0)+ ;First half SOB R4,3$ ;Do both eight times ; MOV (SP)+,R4 ;Restore R4 MOV (SP)+,R2 ;Restore R2 MOV (SP)+,R0 ;Restore R0 ; MOV #CSRRE,DEQCSR(R2) ;Enable receiver ; MOV R3,R1 ;Get PAR ADD #DQRBLK+BDFLAG,R1 ;Add R-BDL offset MOV R1,DEQRBL(R2) ;Set R-BDL address CLR DEQRBH(R2) ;Let RCV take off ADD #DQXBLK-DQRBLK,R1 ;Get X-BDL MOV R1,DEQTBL(R2) ;Set X-BDL pointer CLR DEQTBH(R2) ;Let XMT take off ; 6$: BIT #CSRRI,DEQCSR(R2) ;Receiver done? BEQ 6$ ;Yes MOV #CSRSR,DEQCSR(R2) ;Reset device CLR DEQCSR(R2) ;Get rid of the bit MOV #CSRRE!CSRIL!CSRIE,DEQCSR(R2) ;Enable rcver and interrupts ; BR DQIEX ;Take common exit ; ; Do XMT initialization ; DQOINI: INC COINI(R3) ADD #4,R0 ;Allocate output vector ; DQIEX: MOV #INT+EXTBAS,R1 ;allocate input vector .SETV RTS PC .PAGE ; ; Start block transfer input ; DQISIO: INC CISIO(R3) MOV #FLINIT,DQRBLK+BDFLAG(R3) ;Initialize BDL MOV #BDVBA,DQRBLK+BDADHA(R3) ;Set Valid Buffer Address ADD #4,R1 ; SUB #4,R0 ; MOV R1,DQRBLK+BDADDR(R3) ;Set low order address bits ASR R0 ;shift size to word count NEG R0 ;2's complement MOV R0,DQRBLK+BDSIZ(R3) ;Set buffer size MOV #BDS1IN,DQRBLK+BDSW1(R3) ;Reset SW1 MOV #177400,DQRBLK+BDSW2(R3) ;Trash received byte count CLR DQRBLK+BDSW2+2(R3) ;Prevent chaining CLR DQRBLK+BDSW2+4(R3) ; MOV R3,R0 ;Get PAR address ADD #DQRBLK+BDFLAG,R0 ;Add R-BDL offset MOV R0,DEQRBL(R2) ;Set low portion CLR DEQRBH(R2) ;Take off. JMP .WAIT .page ; ; Start block transfer output ; DQOSIO: SUB #4,R0 ;@@ Dave's change MOV #60.,-(SP) ;Account for stupid Ethernet hardware SUB R0,(SP) ; BHI 1$ ; CLR (SP) ; 1$: ADD (SP)+,R0 ; ADD #4,R1 ; INC COSIO(R3) ;Count OSIO attempts MOV #FLINIT,DQXBLK+BDFLAG(R3) ;Initialize BDL MOV #BDVBA!BDE,DQXBLK+BDADHA(R3) ;Set Valid and Last buffer MOV R1,DQXBLK+BDADDR(R3) ;Set low order address bits ASR R0 ;shift size to word count BCC 2$ ;No low bit set INC R0 ;adjust count BIS #BDL,DQXBLK+BDADHA(R3) ;Mention it in the BDL 2$: NEG R0 ;2's complement MOV R0,DQXBLK+BDSIZ(R3) ;Set buffer size MOV #BDS1IN,DQXBLK+BDSW1(R3) ;Reset SW1 CLR DQXBLK+BDSW2(R3) ; CLR DQXBLK+BDSW2+2(R3) ;Prevent chaining CLR DQXBLK+BDSW2+4(R3) ; MOV R3,R0 ;Get PAR address ADD #DQXBLK+BDFLAG,R0 ;Add R-BDL offset MOV R0,DEQTBL(R2) ;Set low portion CLR DEQTBH(R2) ;Take off. JSR PC,.WAIT ;Enter wait state MOV PARTRY(R3),R0 ;Start output timer SUB R0,RESTIM(R5) ;Set residual time to next poll JMP .STIM ; .PAGE ; ; Receiver async entry ; DQIASY: BIS #1,REGPS(R4) ;error situation. TSTB PSASTS(R5) BMI 1$ ;br if process is running JMP .SKED ;schedule process 1$: RTS PC ; ; Device interrupt input ; DQIINT: INC CIINT(R3) MOV DEQCSR(R2),R0 ;Get CSR contents MOV R0,DEQCSR(R2) ;Clear interrupt request bits BIT #CSRNI,R0 ;Nonexistant memory trap? BEQ 5$ ;No BIS #1,REGPS(R4) 5$: BIT #CSRRI,R0 ;RCV interrupt BEQ 1$ INC CIIRC(R3) BIT #BDR1EU,DEQRBL+BDSW1(R3) ;Error? BEQ 2$ ;No BIS #1,REGPS(R4) ;Oh well. 2$: TSTB PSASTS(R5) ;Process in wait state? BMI 1$ ;No. Forget this RCV interrupt MOV DQRBLK+BDADDR(R3),R1 ;retrieve buffer address ; BIT #1,(R1) ;Multi/Broadcast? BNE 10$ ;yup CMP (R1),ETHADR(R3) ;confirm first two bytes BNE 11$ ;no match CMP 2(R1),ETHADR+2(R3) ;second two bytes BNE 11$ ;no match CMP 4(R1),ETHADR+4(R3) ;final run BEQ 10$ ;local match 11$: INC COMAD(R3) ;count missed addresses BIS #1,REGPS(R4) ;force error ; 10$: SUB #4,R1 ;Adjust for header CLR (R1) CMPB DQRBLK+BDSW2(R3),DQRBLK+BDSW2+1(R3) ;Check validity BEQ 3$ ;Valid BIS #1,REGPS(R4) ;RCV error 3$: MOV DQRBLK+BDSW2(R3),REGR0(R4) ;Get byte count MOVB DQRBLK+BDSW1+1(R3),REGR0+1(R4) ;Set high byte ADD #60.+4+4,REGR0(R4) ;Add filtersize + IL_header + CRC BIC #174000,REGR0(R4) ;Toss trash MOV REGR0(R4),2(R1) MOV R0,-(SP) .SKED ;Schedule RCV PSA MOV (SP)+,R0 1$: BIT #CSRXI,R0 ;XMT interrupt? BEQ 4$ ;No MOVB PARPID(R3),R1 ;Signal output side MOV #ASY,R0 JMP .ASYN 4$: RTS PC ; ; Dummy output interrupt entry ; DQOINT: INC COINT(R3) RTS PC .page ; ; Reset link ; DQORST: INC CORST(R3) RTS PC ;not used ; ; Device output done ; DQOASY: INC COASY(R3) ; TSTB PSASTS(R5) ;is process running? BMI 4$ ;br if yes TSTB R0 ;Is this a timer interrupt BNE 1$ ;Br if no INC COTMO(R3) ;Count time out MOV #CSRSR,DEQCSR(R2);Reset device CLR DEQCSR(R2) ;Clear Reset condition MOV #CSRRE!CSRIL!CSRIE,DEQCSR(R2);Enable rcvr and interrupts MOVB PARPID(R3),R1 ;Signal input side SUB #2,R1 ; MOV #ASY,R0 ; .ASYN ; BR 2$ ;Exit with error ; 1$: .CTIM ;Clear output timeout ADD R0,RESTIM(R5) ; BIT #BDT1EU,DQXBLK+BDSW1(R3) ;XMT error? BEQ 3$ ;branch if no 2$: BIS #1,REGPS(R4) ;no. declare error 3$: JMP .SKED ; 4$: INC COUEX(R3) ;Count unexpected interrupt RTS PC ; ; Data segment ; .PSECT $KERD,RO,D ; ; Process headers ; DQIPAT: .PAT DQREND,NETINP,PRI3,<0,DQIASY,DQIINI,DQISIO,DQIINT> DQOPAT: .PAT DQXEND,NETOUT,PRI3,<0,DQOASY,DQOINI,DQOSIO,DQOINT,DQORST> ; .END